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
)
987 GString
*fixed
= g_string_new ("");
994 while (!g_utf8_validate (start
, -1, &end
) && start
[0] != '\0')
998 tmp
= g_utf8_normalize (start
, end
- start
, G_NORMALIZE_ALL
);
999 g_string_append (fixed
, tmp
);
1002 g_string_append_c (fixed
, end
[0]);
1008 result
= g_utf8_normalize (text
, -1, G_NORMALIZE_ALL
);
1012 if (start
[0] != '\0' && start
!= end
)
1014 tmp
= g_utf8_normalize (start
, end
- start
, G_NORMALIZE_ALL
);
1015 g_string_append (fixed
, tmp
);
1018 result
= g_strdup (fixed
->str
);
1020 g_string_free (fixed
, TRUE
);
1026 str_utf8_casefold_normalize (const char *text
)
1028 GString
*fixed
= g_string_new ("");
1035 while (!g_utf8_validate (start
, -1, &end
) && start
[0] != '\0')
1039 fold
= g_utf8_casefold (start
, end
- start
);
1040 tmp
= g_utf8_normalize (fold
, -1, G_NORMALIZE_ALL
);
1041 g_string_append (fixed
, tmp
);
1045 g_string_append_c (fixed
, end
[0]);
1051 fold
= g_utf8_casefold (text
, -1);
1052 result
= g_utf8_normalize (fold
, -1, G_NORMALIZE_ALL
);
1057 if (start
[0] != '\0' && start
!= end
)
1059 fold
= g_utf8_casefold (start
, end
- start
);
1060 tmp
= g_utf8_normalize (fold
, -1, G_NORMALIZE_ALL
);
1061 g_string_append (fixed
, tmp
);
1065 result
= g_strdup (fixed
->str
);
1067 g_string_free (fixed
, TRUE
);
1073 str_utf8_compare (const char *t1
, const char *t2
)
1078 n1
= str_utf8_normalize (t1
);
1079 n2
= str_utf8_normalize (t2
);
1081 result
= strcmp (n1
, n2
);
1090 str_utf8_ncompare (const char *t1
, const char *t2
)
1095 n1
= str_utf8_normalize (t1
);
1096 n2
= str_utf8_normalize (t2
);
1098 result
= strncmp (n1
, n2
, min (strlen (n1
), strlen (n2
)));
1107 str_utf8_casecmp (const char *t1
, const char *t2
)
1112 n1
= str_utf8_casefold_normalize (t1
);
1113 n2
= str_utf8_casefold_normalize (t2
);
1115 result
= strcmp (n1
, n2
);
1124 str_utf8_ncasecmp (const char *t1
, const char *t2
)
1129 n1
= str_utf8_casefold_normalize (t1
);
1130 n2
= str_utf8_casefold_normalize (t2
);
1132 result
= strncmp (n1
, n2
, min (strlen (n1
), strlen (n2
)));
1141 str_utf8_prefix (const char *text
, const char *prefix
)
1143 char *t
= str_utf8_normalize (text
);
1144 char *p
= str_utf8_normalize (prefix
);
1147 const char *nnt
= t
;
1148 const char *nnp
= p
;
1151 while (nt
[0] != '\0' && np
[0] != '\0')
1153 str_utf8_cnext_char_safe (&nnt
);
1154 str_utf8_cnext_char_safe (&nnp
);
1155 if (nnt
- nt
!= nnp
- np
)
1157 if (strncmp (nt
, np
, nnt
- nt
) != 0)
1172 str_utf8_caseprefix (const char *text
, const char *prefix
)
1174 char *t
= str_utf8_casefold_normalize (text
);
1175 char *p
= str_utf8_casefold_normalize (prefix
);
1178 const char *nnt
= t
;
1179 const char *nnp
= p
;
1182 while (nt
[0] != '\0' && np
[0] != '\0')
1184 str_utf8_cnext_char_safe (&nnt
);
1185 str_utf8_cnext_char_safe (&nnp
);
1186 if (nnt
- nt
!= nnp
- np
)
1188 if (strncmp (nt
, np
, nnt
- nt
) != 0)
1203 str_utf8_create_key_gen (const char *text
, int case_sen
,
1204 gchar
* (*keygen
) (const gchar
* text
, gssize size
))
1210 result
= str_utf8_normalize (text
);
1216 const char *start
, *end
;
1219 dot
= text
[0] == '.';
1220 fixed
= g_string_sized_new (16);
1227 g_string_append_c (fixed
, '.');
1230 while (!g_utf8_validate (start
, -1, &end
) && start
[0] != '\0')
1234 fold
= g_utf8_casefold (start
, end
- start
);
1235 key
= keygen (fold
, -1);
1236 g_string_append (fixed
, key
);
1240 g_string_append_c (fixed
, end
[0]);
1246 fold
= g_utf8_casefold (start
, -1);
1247 result
= keygen (fold
, -1);
1249 g_string_free (fixed
, TRUE
);
1251 else if (dot
&& (start
== text
+ 1))
1253 fold
= g_utf8_casefold (start
, -1);
1254 key
= keygen (fold
, -1);
1255 g_string_append (fixed
, key
);
1258 result
= g_string_free (fixed
, FALSE
);
1262 if (start
[0] != '\0' && start
!= end
)
1264 fold
= g_utf8_casefold (start
, end
- start
);
1265 key
= keygen (fold
, -1);
1266 g_string_append (fixed
, key
);
1270 result
= g_string_free (fixed
, FALSE
);
1277 str_utf8_create_key (const char *text
, int case_sen
)
1279 return str_utf8_create_key_gen (text
, case_sen
, g_utf8_collate_key
);
1282 #ifdef MC__USE_STR_UTF8_CREATE_KEY_FOR_FILENAME
1284 str_utf8_create_key_for_filename (const char *text
, int case_sen
)
1286 return str_utf8_create_key_gen (text
, case_sen
, g_utf8_collate_key_for_filename
);
1291 str_utf8_key_collate (const char *t1
, const char *t2
, int case_sen
)
1294 return strcmp (t1
, t2
);
1298 str_utf8_release_key (char *key
, int case_sen
)
1305 str_utf8_init (void)
1307 struct str_class result
;
1309 result
.conv_gerror_message
= str_utf8_conv_gerror_message
;
1310 result
.vfs_convert_to
= str_utf8_vfs_convert_to
;
1311 result
.insert_replace_char
= str_utf8_insert_replace_char
;
1312 result
.is_valid_string
= str_utf8_is_valid_string
;
1313 result
.is_valid_char
= str_utf8_is_valid_char
;
1314 result
.cnext_char
= str_utf8_cnext_char
;
1315 result
.cprev_char
= str_utf8_cprev_char
;
1316 result
.cnext_char_safe
= str_utf8_cnext_char_safe
;
1317 result
.cprev_char_safe
= str_utf8_cprev_char_safe
;
1318 result
.cnext_noncomb_char
= str_utf8_cnext_noncomb_char
;
1319 result
.cprev_noncomb_char
= str_utf8_cprev_noncomb_char
;
1320 result
.isspace
= str_utf8_isspace
;
1321 result
.ispunct
= str_utf8_ispunct
;
1322 result
.isalnum
= str_utf8_isalnum
;
1323 result
.isdigit
= str_utf8_isdigit
;
1324 result
.isprint
= str_utf8_isprint
;
1325 result
.iscombiningmark
= str_utf8_iscombiningmark
;
1326 result
.toupper
= str_utf8_toupper
;
1327 result
.tolower
= str_utf8_tolower
;
1328 result
.length
= str_utf8_length
;
1329 result
.length2
= str_utf8_length2
;
1330 result
.length_noncomb
= str_utf8_length_noncomb
;
1331 result
.fix_string
= str_utf8_fix_string
;
1332 result
.term_form
= str_utf8_term_form
;
1333 result
.fit_to_term
= str_utf8_fit_to_term
;
1334 result
.term_trim
= str_utf8_term_trim
;
1335 result
.term_width2
= str_utf8_term_width2
;
1336 result
.term_width1
= str_utf8_term_width1
;
1337 result
.term_char_width
= str_utf8_term_char_width
;
1338 result
.term_substring
= str_utf8_term_substring
;
1339 result
.trunc
= str_utf8_trunc
;
1340 result
.offset_to_pos
= str_utf8_offset_to_pos
;
1341 result
.column_to_pos
= str_utf8_column_to_pos
;
1342 result
.create_search_needle
= str_utf8_create_search_needle
;
1343 result
.release_search_needle
= str_utf8_release_search_needle
;
1344 result
.search_first
= str_utf8_search_first
;
1345 result
.search_last
= str_utf8_search_last
;
1346 result
.compare
= str_utf8_compare
;
1347 result
.ncompare
= str_utf8_ncompare
;
1348 result
.casecmp
= str_utf8_casecmp
;
1349 result
.ncasecmp
= str_utf8_ncasecmp
;
1350 result
.prefix
= str_utf8_prefix
;
1351 result
.caseprefix
= str_utf8_caseprefix
;
1352 result
.create_key
= str_utf8_create_key
;
1353 #ifdef MC__USE_STR_UTF8_CREATE_KEY_FOR_FILENAME
1354 /* case insensitive sort files in "a1 a2 a10" order */
1355 result
.create_key_for_filename
= str_utf8_create_key_for_filename
;
1357 /* case insensitive sort files in "a1 a10 a2" order */
1358 result
.create_key_for_filename
= str_utf8_create_key
;
1360 result
.key_collate
= str_utf8_key_collate
;
1361 result
.release_key
= str_utf8_release_key
;