2 UTF-8 strings utilities
4 Copyright (C) 2007, 2011
5 The Free Software Foundation, Inc.
10 The file_date routine is mostly from GNU's fileutils package,
11 written by Richard Stallman and David MacKenzie.
13 This file is part of the Midnight Commander.
15 The Midnight Commander is free software: you can redistribute it
16 and/or modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation, either version 3 of the License,
18 or (at your option) any later version.
20 The Midnight Commander is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
37 #include "lib/global.h"
38 #include "lib/strutil.h"
40 /* using function for utf-8 from glib */
42 static const char replch
[] = "\xEF\xBF\xBD";
45 str_unichar_iscombiningmark (gunichar uni
)
47 int type
= g_unichar_type (uni
);
48 return (type
== G_UNICODE_COMBINING_MARK
)
49 || (type
== G_UNICODE_ENCLOSING_MARK
) || (type
== G_UNICODE_NON_SPACING_MARK
);
53 str_utf8_insert_replace_char (GString
* buffer
)
55 g_string_append (buffer
, replch
);
59 str_utf8_is_valid_string (const char *text
)
61 return g_utf8_validate (text
, -1, NULL
);
65 str_utf8_is_valid_char (const char *ch
, size_t size
)
67 switch (g_utf8_get_char_validated (ch
, size
))
79 str_utf8_cnext_char (const char **text
)
81 (*text
) = g_utf8_next_char (*text
);
85 str_utf8_cprev_char (const char **text
)
87 (*text
) = g_utf8_prev_char (*text
);
91 str_utf8_cnext_char_safe (const char **text
)
93 if (str_utf8_is_valid_char (*text
, -1) == 1)
94 (*text
) = g_utf8_next_char (*text
);
100 str_utf8_cprev_char_safe (const char **text
)
102 const char *result
= g_utf8_prev_char (*text
);
103 const char *t
= result
;
104 str_utf8_cnext_char_safe (&t
);
112 str_utf8_fix_string (char *text
)
116 while (text
[0] != '\0')
118 uni
= g_utf8_get_char_validated (text
, -1);
119 if ((uni
!= (gunichar
) (-1)) && (uni
!= (gunichar
) (-2)))
121 text
= g_utf8_next_char (text
);
132 str_utf8_isspace (const char *text
)
134 gunichar uni
= g_utf8_get_char_validated (text
, -1);
135 return g_unichar_isspace (uni
);
139 str_utf8_ispunct (const char *text
)
141 gunichar uni
= g_utf8_get_char_validated (text
, -1);
142 return g_unichar_ispunct (uni
);
146 str_utf8_isalnum (const char *text
)
148 gunichar uni
= g_utf8_get_char_validated (text
, -1);
149 return g_unichar_isalnum (uni
);
153 str_utf8_isdigit (const char *text
)
155 gunichar uni
= g_utf8_get_char_validated (text
, -1);
156 return g_unichar_isdigit (uni
);
160 str_utf8_isprint (const char *ch
)
162 gunichar uni
= g_utf8_get_char_validated (ch
, -1);
163 return g_unichar_isprint (uni
);
167 str_utf8_iscombiningmark (const char *ch
)
169 gunichar uni
= g_utf8_get_char_validated (ch
, -1);
170 return str_unichar_iscombiningmark (uni
);
174 str_utf8_cnext_noncomb_char (const char **text
)
177 while ((*text
)[0] != '\0')
179 str_utf8_cnext_char_safe (text
);
181 if (!str_utf8_iscombiningmark (*text
))
188 str_utf8_cprev_noncomb_char (const char **text
, const char *begin
)
191 while ((*text
) != begin
)
193 str_utf8_cprev_char_safe (text
);
195 if (!str_utf8_iscombiningmark (*text
))
202 str_utf8_toupper (const char *text
, char **out
, size_t * remain
)
207 uni
= g_utf8_get_char_validated (text
, -1);
208 if (uni
== (gunichar
) (-1) || uni
== (gunichar
) (-2))
211 uni
= g_unichar_toupper (uni
);
212 left
= g_unichar_to_utf8 (uni
, NULL
);
216 left
= g_unichar_to_utf8 (uni
, *out
);
223 str_utf8_tolower (const char *text
, char **out
, size_t * remain
)
228 uni
= g_utf8_get_char_validated (text
, -1);
229 if (uni
== (gunichar
) (-1) || uni
== (gunichar
) (-2))
232 uni
= g_unichar_tolower (uni
);
233 left
= g_unichar_to_utf8 (uni
, NULL
);
237 left
= g_unichar_to_utf8 (uni
, *out
);
244 str_utf8_length (const char *text
)
251 while (!g_utf8_validate (start
, -1, &end
) && start
[0] != '\0')
255 result
+= g_utf8_strlen (start
, end
- start
);
263 result
= g_utf8_strlen (text
, -1);
267 if (start
[0] != '\0' && start
!= end
)
269 result
+= g_utf8_strlen (start
, end
- start
);
277 str_utf8_length2 (const char *text
, int size
)
284 while (!g_utf8_validate (start
, -1, &end
) && start
[0] != '\0' && size
> 0)
288 result
+= g_utf8_strlen (start
, min (end
- start
, size
));
291 result
+= (size
> 0);
298 result
= g_utf8_strlen (text
, size
);
302 if (start
[0] != '\0' && start
!= end
&& size
> 0)
304 result
+= g_utf8_strlen (start
, min (end
- start
, size
));
312 str_utf8_length_noncomb (const char *text
)
315 const char *t
= text
;
319 str_utf8_cnext_noncomb_char (&t
);
328 str_utf8_questmark_sustb (char **string, size_t * left, GString * buffer)
330 char *next = g_utf8_next_char (*string);
331 (*left) -= next - (*string);
333 g_string_append_c (buffer, '?');
338 str_utf8_conv_gerror_message (GError
* error
, const char *def_msg
)
340 if ((error
!= NULL
) && (error
->message
!= NULL
))
341 return g_strdup (error
->message
);
343 return g_strdup (def_msg
!= NULL
? def_msg
: "");
347 str_utf8_vfs_convert_to (GIConv coder
, const char *string
, int size
, GString
* buffer
)
351 if (coder
== str_cnv_not_convert
)
353 g_string_append_len (buffer
, string
, size
);
354 result
= ESTR_SUCCESS
;
357 result
= str_nconvert (coder
, (char *) string
, size
, buffer
);
364 char text
[BUF_MEDIUM
* 6];
369 /* utiliti function, that make string valid in utf8 and all characters printable
370 * return width of string too*/
371 static const struct term_form
*
372 str_utf8_make_make_term_form (const char *text
, size_t length
)
374 static struct term_form result
;
379 result
.text
[0] = '\0';
382 actual
= result
.text
;
384 /* check if text start with combining character,
385 * add space at begin in this case */
386 if (length
!= 0 && text
[0] != '\0')
388 uni
= g_utf8_get_char_validated (text
, -1);
389 if ((uni
!= (gunichar
) (-1)) && (uni
!= (gunichar
) (-2)))
391 if (str_unichar_iscombiningmark (uni
))
401 while (length
!= 0 && text
[0] != '\0')
403 uni
= g_utf8_get_char_validated (text
, -1);
404 if ((uni
!= (gunichar
) (-1)) && (uni
!= (gunichar
) (-2)))
406 if (g_unichar_isprint (uni
))
408 left
= g_unichar_to_utf8 (uni
, actual
);
410 if (!str_unichar_iscombiningmark (uni
))
413 if (g_unichar_iswide (uni
))
425 text
= g_utf8_next_char (text
);
430 /*actual[0] = '?'; */
431 memcpy (actual
, replch
, strlen (replch
));
432 actual
+= strlen (replch
);
435 if (length
!= (size_t) (-1))
444 str_utf8_term_form (const char *text
)
446 static char result
[BUF_MEDIUM
* 6];
447 const struct term_form
*pre_form
;
450 pre_form
= str_utf8_make_make_term_form (text
, (size_t) (-1));
451 if (pre_form
->compose
)
453 composed
= g_utf8_normalize (pre_form
->text
, -1, G_NORMALIZE_DEFAULT_COMPOSE
);
454 g_strlcpy (result
, composed
, sizeof (result
));
459 g_strlcpy (result
, pre_form
->text
, sizeof (result
));
473 /* utiliti function, that copy all characters from cheked to actual */
475 utf8_tool_copy_chars_to_end (struct utf8_tool
*tool
)
482 while (tool
->cheked
[0] != '\0')
484 uni
= g_utf8_get_char (tool
->cheked
);
485 tool
->compose
|= str_unichar_iscombiningmark (uni
);
486 left
= g_unichar_to_utf8 (uni
, NULL
);
487 if (tool
->remain
<= left
)
489 left
= g_unichar_to_utf8 (uni
, tool
->actual
);
490 tool
->actual
+= left
;
491 tool
->remain
-= left
;
492 tool
->cheked
= g_utf8_next_char (tool
->cheked
);
497 /* utiliti function, that copy characters from cheked to actual until ident is
498 * smaller than to_ident */
500 utf8_tool_copy_chars_to (struct utf8_tool
*tool
, int to_ident
)
508 while (tool
->cheked
[0] != '\0')
510 uni
= g_utf8_get_char (tool
->cheked
);
511 if (!str_unichar_iscombiningmark (uni
))
514 if (g_unichar_iswide (uni
))
516 if (tool
->ident
+ w
> to_ident
)
525 left
= g_unichar_to_utf8 (uni
, NULL
);
526 if (tool
->remain
<= left
)
528 left
= g_unichar_to_utf8 (uni
, tool
->actual
);
529 tool
->actual
+= left
;
530 tool
->remain
-= left
;
531 tool
->cheked
= g_utf8_next_char (tool
->cheked
);
537 /* utiliti function, add count spaces to actual */
539 utf8_tool_insert_space (struct utf8_tool
*tool
, int count
)
543 if (tool
->remain
<= (gsize
) count
)
545 memset (tool
->actual
, ' ', count
);
546 tool
->actual
+= count
;
547 tool
->remain
-= count
;
551 /* utiliti function, add one characters to actual */
553 utf8_tool_insert_char (struct utf8_tool
*tool
, char ch
)
555 if (tool
->remain
<= 1)
557 tool
->actual
[0] = ch
;
563 /* utiliti function, thah skip characters from cheked until ident is greater or
564 * equal to to_ident */
566 utf8_tool_skip_chars_to (struct utf8_tool
*tool
, int to_ident
)
570 while (to_ident
> tool
->ident
&& tool
->cheked
[0] != '\0')
572 uni
= g_utf8_get_char (tool
->cheked
);
573 if (!str_unichar_iscombiningmark (uni
))
576 if (g_unichar_iswide (uni
))
579 tool
->cheked
= g_utf8_next_char (tool
->cheked
);
581 uni
= g_utf8_get_char (tool
->cheked
);
582 while (str_unichar_iscombiningmark (uni
))
584 tool
->cheked
= g_utf8_next_char (tool
->cheked
);
585 uni
= g_utf8_get_char (tool
->cheked
);
591 utf8_tool_compose (char *buffer
, size_t size
)
593 char *composed
= g_utf8_normalize (buffer
, -1, G_NORMALIZE_DEFAULT_COMPOSE
);
594 g_strlcpy (buffer
, composed
, size
);
600 str_utf8_fit_to_term (const char *text
, int width
, align_crt_t just_mode
)
602 static char result
[BUF_MEDIUM
* 6];
603 const struct term_form
*pre_form
;
604 struct utf8_tool tool
;
606 pre_form
= str_utf8_make_make_term_form (text
, (size_t) (-1));
607 tool
.cheked
= pre_form
->text
;
608 tool
.actual
= result
;
609 tool
.remain
= sizeof (result
);
612 if (pre_form
->width
<= (gsize
) width
)
615 switch (HIDE_FIT (just_mode
))
619 tool
.ident
= (width
- pre_form
->width
) / 2;
622 tool
.ident
= width
- pre_form
->width
;
626 utf8_tool_insert_space (&tool
, tool
.ident
);
627 utf8_tool_copy_chars_to_end (&tool
);
628 utf8_tool_insert_space (&tool
, width
- pre_form
->width
- tool
.ident
);
632 if (IS_FIT (just_mode
))
635 utf8_tool_copy_chars_to (&tool
, width
/ 2);
636 utf8_tool_insert_char (&tool
, '~');
639 utf8_tool_skip_chars_to (&tool
, pre_form
->width
- width
+ 1);
640 utf8_tool_copy_chars_to_end (&tool
);
641 utf8_tool_insert_space (&tool
, width
- (pre_form
->width
- tool
.ident
+ 1));
646 switch (HIDE_FIT (just_mode
))
649 tool
.ident
= (width
- pre_form
->width
) / 2;
652 tool
.ident
= width
- pre_form
->width
;
656 utf8_tool_skip_chars_to (&tool
, 0);
657 utf8_tool_insert_space (&tool
, tool
.ident
);
658 utf8_tool_copy_chars_to (&tool
, width
);
659 utf8_tool_insert_space (&tool
, width
- tool
.ident
);
663 tool
.actual
[0] = '\0';
665 utf8_tool_compose (result
, sizeof (result
));
670 str_utf8_term_trim (const char *text
, int width
)
672 static char result
[BUF_MEDIUM
* 6];
673 const struct term_form
*pre_form
;
674 struct utf8_tool tool
;
682 pre_form
= str_utf8_make_make_term_form (text
, (size_t) (-1));
684 tool
.cheked
= pre_form
->text
;
685 tool
.actual
= result
;
686 tool
.remain
= sizeof (result
);
689 if ((gsize
) width
< pre_form
->width
)
693 memset (tool
.actual
, '.', width
);
694 tool
.actual
+= width
;
695 tool
.remain
-= width
;
699 memset (tool
.actual
, '.', 3);
704 utf8_tool_skip_chars_to (&tool
, pre_form
->width
- width
+ 3);
705 utf8_tool_copy_chars_to_end (&tool
);
710 utf8_tool_copy_chars_to_end (&tool
);
713 tool
.actual
[0] = '\0';
715 utf8_tool_compose (result
, sizeof (result
));
720 str_utf8_term_width2 (const char *text
, size_t length
)
722 const struct term_form
*result
;
724 result
= str_utf8_make_make_term_form (text
, length
);
725 return result
->width
;
729 str_utf8_term_width1 (const char *text
)
731 return str_utf8_term_width2 (text
, (size_t) (-1));
735 str_utf8_term_char_width (const char *text
)
737 gunichar uni
= g_utf8_get_char_validated (text
, -1);
738 return (str_unichar_iscombiningmark (uni
)) ? 0 : ((g_unichar_iswide (uni
)) ? 2 : 1);
742 str_utf8_term_substring (const char *text
, int start
, int width
)
744 static char result
[BUF_MEDIUM
* 6];
745 const struct term_form
*pre_form
;
746 struct utf8_tool tool
;
748 pre_form
= str_utf8_make_make_term_form (text
, (size_t) (-1));
750 tool
.cheked
= pre_form
->text
;
751 tool
.actual
= result
;
752 tool
.remain
= sizeof (result
);
756 utf8_tool_skip_chars_to (&tool
, 0);
759 utf8_tool_insert_space (&tool
, tool
.ident
);
761 utf8_tool_copy_chars_to (&tool
, width
);
762 utf8_tool_insert_space (&tool
, width
- tool
.ident
);
764 tool
.actual
[0] = '\0';
766 utf8_tool_compose (result
, sizeof (result
));
771 str_utf8_trunc (const char *text
, int width
)
773 static char result
[MC_MAXPATHLEN
* 6 * 2];
774 const struct term_form
*pre_form
;
775 struct utf8_tool tool
;
777 pre_form
= str_utf8_make_make_term_form (text
, (size_t) (-1));
779 tool
.cheked
= pre_form
->text
;
780 tool
.actual
= result
;
781 tool
.remain
= sizeof (result
);
784 if (pre_form
->width
> (gsize
) width
)
787 utf8_tool_copy_chars_to (&tool
, width
/ 2);
788 utf8_tool_insert_char (&tool
, '~');
791 utf8_tool_skip_chars_to (&tool
, pre_form
->width
- width
+ 1);
792 utf8_tool_copy_chars_to_end (&tool
);
796 utf8_tool_copy_chars_to_end (&tool
);
799 tool
.actual
[0] = '\0';
801 utf8_tool_compose (result
, sizeof (result
));
806 str_utf8_offset_to_pos (const char *text
, size_t length
)
808 if (str_utf8_is_valid_string (text
))
809 return g_utf8_offset_to_pointer (text
, length
) - text
;
813 GString
*buffer
= g_string_new (text
);
815 str_utf8_fix_string (buffer
->str
);
816 result
= g_utf8_offset_to_pointer (buffer
->str
, length
) - buffer
->str
;
817 g_string_free (buffer
, TRUE
);
823 str_utf8_column_to_pos (const char *text
, size_t pos
)
832 while (text
[0] != '\0')
834 uni
= g_utf8_get_char_validated (text
, 6);
835 if ((uni
!= (gunichar
) (-1)) && (uni
!= (gunichar
) (-2)))
837 if (g_unichar_isprint (uni
))
839 if (!str_unichar_iscombiningmark (uni
))
842 if (g_unichar_iswide (uni
))
850 text
= g_utf8_next_char (text
);
857 if ((gsize
) width
> pos
)
867 str_utf8_create_search_needle (const char *needle
, int case_sen
)
873 return g_utf8_normalize (needle
, -1, G_NORMALIZE_ALL
);
877 char *fold
= g_utf8_casefold (needle
, -1);
878 char *result
= g_utf8_normalize (fold
, -1, G_NORMALIZE_ALL
);
888 str_utf8_release_search_needle (char *needle
, int case_sen
)
896 str_utf8_search_first (const char *text
, const char *search
, int case_sen
)
901 const char *result
= NULL
;
904 fold_text
= (case_sen
) ? (char *) text
: g_utf8_casefold (text
, -1);
905 deco_text
= g_utf8_normalize (fold_text
, -1, G_NORMALIZE_ALL
);
910 match
= g_strstr_len (match
, -1, search
);
913 if ((!str_utf8_iscombiningmark (match
) || (match
== deco_text
)) &&
914 !str_utf8_iscombiningmark (match
+ strlen (search
)))
921 str_utf8_cnext_noncomb_char (&m
);
922 str_utf8_cnext_noncomb_char (&result
);
927 str_utf8_cnext_char (&match
);
931 while (match
!= NULL
&& result
== NULL
);
941 str_utf8_search_last (const char *text
, const char *search
, int case_sen
)
946 const char *result
= NULL
;
949 fold_text
= (case_sen
) ? (char *) text
: g_utf8_casefold (text
, -1);
950 deco_text
= g_utf8_normalize (fold_text
, -1, G_NORMALIZE_ALL
);
954 match
= g_strrstr_len (deco_text
, -1, search
);
957 if ((!str_utf8_iscombiningmark (match
) || (match
== deco_text
)) &&
958 !str_utf8_iscombiningmark (match
+ strlen (search
)))
965 str_utf8_cnext_noncomb_char (&m
);
966 str_utf8_cnext_noncomb_char (&result
);
975 while (match
!= NULL
&& result
== NULL
);
985 str_utf8_normalize (const char *text
)
993 fixed
= g_string_sized_new (4);
996 while (!g_utf8_validate (start
, -1, &end
) && start
[0] != '\0')
1000 tmp
= g_utf8_normalize (start
, end
- start
, G_NORMALIZE_ALL
);
1001 g_string_append (fixed
, tmp
);
1004 g_string_append_c (fixed
, end
[0]);
1010 result
= g_utf8_normalize (text
, -1, G_NORMALIZE_ALL
);
1011 g_string_free (fixed
, TRUE
);
1015 if (start
[0] != '\0' && start
!= end
)
1017 tmp
= g_utf8_normalize (start
, end
- start
, G_NORMALIZE_ALL
);
1018 g_string_append (fixed
, tmp
);
1021 result
= g_string_free (fixed
, FALSE
);
1028 str_utf8_casefold_normalize (const char *text
)
1036 fixed
= g_string_sized_new (4);
1039 while (!g_utf8_validate (start
, -1, &end
) && start
[0] != '\0')
1043 fold
= g_utf8_casefold (start
, end
- start
);
1044 tmp
= g_utf8_normalize (fold
, -1, G_NORMALIZE_ALL
);
1045 g_string_append (fixed
, tmp
);
1049 g_string_append_c (fixed
, end
[0]);
1055 fold
= g_utf8_casefold (text
, -1);
1056 result
= g_utf8_normalize (fold
, -1, G_NORMALIZE_ALL
);
1058 g_string_free (fixed
, TRUE
);
1062 if (start
[0] != '\0' && start
!= end
)
1064 fold
= g_utf8_casefold (start
, end
- start
);
1065 tmp
= g_utf8_normalize (fold
, -1, G_NORMALIZE_ALL
);
1066 g_string_append (fixed
, tmp
);
1070 result
= g_string_free (fixed
, FALSE
);
1077 str_utf8_compare (const char *t1
, const char *t2
)
1082 n1
= str_utf8_normalize (t1
);
1083 n2
= str_utf8_normalize (t2
);
1085 result
= strcmp (n1
, n2
);
1094 str_utf8_ncompare (const char *t1
, const char *t2
)
1099 n1
= str_utf8_normalize (t1
);
1100 n2
= str_utf8_normalize (t2
);
1102 result
= strncmp (n1
, n2
, min (strlen (n1
), strlen (n2
)));
1111 str_utf8_casecmp (const char *t1
, const char *t2
)
1116 n1
= str_utf8_casefold_normalize (t1
);
1117 n2
= str_utf8_casefold_normalize (t2
);
1119 result
= strcmp (n1
, n2
);
1128 str_utf8_ncasecmp (const char *t1
, const char *t2
)
1133 n1
= str_utf8_casefold_normalize (t1
);
1134 n2
= str_utf8_casefold_normalize (t2
);
1136 result
= strncmp (n1
, n2
, min (strlen (n1
), strlen (n2
)));
1145 str_utf8_prefix (const char *text
, const char *prefix
)
1147 char *t
= str_utf8_normalize (text
);
1148 char *p
= str_utf8_normalize (prefix
);
1151 const char *nnt
= t
;
1152 const char *nnp
= p
;
1155 while (nt
[0] != '\0' && np
[0] != '\0')
1157 str_utf8_cnext_char_safe (&nnt
);
1158 str_utf8_cnext_char_safe (&nnp
);
1159 if (nnt
- nt
!= nnp
- np
)
1161 if (strncmp (nt
, np
, nnt
- nt
) != 0)
1176 str_utf8_caseprefix (const char *text
, const char *prefix
)
1178 char *t
= str_utf8_casefold_normalize (text
);
1179 char *p
= str_utf8_casefold_normalize (prefix
);
1182 const char *nnt
= t
;
1183 const char *nnp
= p
;
1186 while (nt
[0] != '\0' && np
[0] != '\0')
1188 str_utf8_cnext_char_safe (&nnt
);
1189 str_utf8_cnext_char_safe (&nnp
);
1190 if (nnt
- nt
!= nnp
- np
)
1192 if (strncmp (nt
, np
, nnt
- nt
) != 0)
1207 str_utf8_create_key_gen (const char *text
, int case_sen
,
1208 gchar
* (*keygen
) (const gchar
* text
, gssize size
))
1214 result
= str_utf8_normalize (text
);
1220 const char *start
, *end
;
1223 dot
= text
[0] == '.';
1224 fixed
= g_string_sized_new (16);
1231 g_string_append_c (fixed
, '.');
1234 while (!g_utf8_validate (start
, -1, &end
) && start
[0] != '\0')
1238 fold
= g_utf8_casefold (start
, end
- start
);
1239 key
= keygen (fold
, -1);
1240 g_string_append (fixed
, key
);
1244 g_string_append_c (fixed
, end
[0]);
1250 fold
= g_utf8_casefold (start
, -1);
1251 result
= keygen (fold
, -1);
1253 g_string_free (fixed
, TRUE
);
1255 else if (dot
&& (start
== text
+ 1))
1257 fold
= g_utf8_casefold (start
, -1);
1258 key
= keygen (fold
, -1);
1259 g_string_append (fixed
, key
);
1262 result
= g_string_free (fixed
, FALSE
);
1266 if (start
[0] != '\0' && start
!= end
)
1268 fold
= g_utf8_casefold (start
, end
- start
);
1269 key
= keygen (fold
, -1);
1270 g_string_append (fixed
, key
);
1274 result
= g_string_free (fixed
, FALSE
);
1281 str_utf8_create_key (const char *text
, int case_sen
)
1283 return str_utf8_create_key_gen (text
, case_sen
, g_utf8_collate_key
);
1286 #ifdef MC__USE_STR_UTF8_CREATE_KEY_FOR_FILENAME
1288 str_utf8_create_key_for_filename (const char *text
, int case_sen
)
1290 return str_utf8_create_key_gen (text
, case_sen
, g_utf8_collate_key_for_filename
);
1295 str_utf8_key_collate (const char *t1
, const char *t2
, int case_sen
)
1298 return strcmp (t1
, t2
);
1302 str_utf8_release_key (char *key
, int case_sen
)
1309 str_utf8_init (void)
1311 struct str_class result
;
1313 result
.conv_gerror_message
= str_utf8_conv_gerror_message
;
1314 result
.vfs_convert_to
= str_utf8_vfs_convert_to
;
1315 result
.insert_replace_char
= str_utf8_insert_replace_char
;
1316 result
.is_valid_string
= str_utf8_is_valid_string
;
1317 result
.is_valid_char
= str_utf8_is_valid_char
;
1318 result
.cnext_char
= str_utf8_cnext_char
;
1319 result
.cprev_char
= str_utf8_cprev_char
;
1320 result
.cnext_char_safe
= str_utf8_cnext_char_safe
;
1321 result
.cprev_char_safe
= str_utf8_cprev_char_safe
;
1322 result
.cnext_noncomb_char
= str_utf8_cnext_noncomb_char
;
1323 result
.cprev_noncomb_char
= str_utf8_cprev_noncomb_char
;
1324 result
.isspace
= str_utf8_isspace
;
1325 result
.ispunct
= str_utf8_ispunct
;
1326 result
.isalnum
= str_utf8_isalnum
;
1327 result
.isdigit
= str_utf8_isdigit
;
1328 result
.isprint
= str_utf8_isprint
;
1329 result
.iscombiningmark
= str_utf8_iscombiningmark
;
1330 result
.toupper
= str_utf8_toupper
;
1331 result
.tolower
= str_utf8_tolower
;
1332 result
.length
= str_utf8_length
;
1333 result
.length2
= str_utf8_length2
;
1334 result
.length_noncomb
= str_utf8_length_noncomb
;
1335 result
.fix_string
= str_utf8_fix_string
;
1336 result
.term_form
= str_utf8_term_form
;
1337 result
.fit_to_term
= str_utf8_fit_to_term
;
1338 result
.term_trim
= str_utf8_term_trim
;
1339 result
.term_width2
= str_utf8_term_width2
;
1340 result
.term_width1
= str_utf8_term_width1
;
1341 result
.term_char_width
= str_utf8_term_char_width
;
1342 result
.term_substring
= str_utf8_term_substring
;
1343 result
.trunc
= str_utf8_trunc
;
1344 result
.offset_to_pos
= str_utf8_offset_to_pos
;
1345 result
.column_to_pos
= str_utf8_column_to_pos
;
1346 result
.create_search_needle
= str_utf8_create_search_needle
;
1347 result
.release_search_needle
= str_utf8_release_search_needle
;
1348 result
.search_first
= str_utf8_search_first
;
1349 result
.search_last
= str_utf8_search_last
;
1350 result
.compare
= str_utf8_compare
;
1351 result
.ncompare
= str_utf8_ncompare
;
1352 result
.casecmp
= str_utf8_casecmp
;
1353 result
.ncasecmp
= str_utf8_ncasecmp
;
1354 result
.prefix
= str_utf8_prefix
;
1355 result
.caseprefix
= str_utf8_caseprefix
;
1356 result
.create_key
= str_utf8_create_key
;
1357 #ifdef MC__USE_STR_UTF8_CREATE_KEY_FOR_FILENAME
1358 /* case insensitive sort files in "a1 a2 a10" order */
1359 result
.create_key_for_filename
= str_utf8_create_key_for_filename
;
1361 /* case insensitive sort files in "a1 a10 a2" order */
1362 result
.create_key_for_filename
= str_utf8_create_key
;
1364 result
.key_collate
= str_utf8_key_collate
;
1365 result
.release_key
= str_utf8_release_key
;