1 /* common strings utilities
2 Copyright (C) 2007 Free Software Foundation, Inc.
7 The file_date routine is mostly from GNU's fileutils package,
8 written by Richard Stallman and David MacKenzie.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
36 /*names, that are used for utf-8 */
37 static const char *str_utf8_encodings
[] = {
43 /* standard 8bit encodings, no wide or multibytes characters*/
44 static const char *str_8bit_encodings
[] = {
61 /* terminal encoding*/
63 /* function for encoding specific operations*/
64 static struct str_class used_class
;
66 GIConv str_cnv_to_term
;
67 GIConv str_cnv_from_term
;
68 GIConv str_cnv_not_convert
;
70 /* if enc is same encoding like on terminal*/
72 str_test_not_convert (const char *enc
)
74 return g_ascii_strcasecmp (enc
, codeset
) == 0;
78 str_crt_conv_to (const char *to_enc
)
80 return (!str_test_not_convert (to_enc
))
81 ? g_iconv_open (to_enc
, codeset
) : str_cnv_not_convert
;
85 str_crt_conv_from (const char *from_enc
)
87 return (!str_test_not_convert (from_enc
))
88 ? g_iconv_open (codeset
, from_enc
) : str_cnv_not_convert
;
92 str_close_conv (GIConv conv
)
94 if (conv
!= str_cnv_not_convert
)
99 _str_convert (GIConv coder
, const char *string
, int size
, GString
* buffer
)
101 estr_t state
= ESTR_SUCCESS
;
102 gchar
*tmp_buff
= NULL
;
104 gsize bytes_read
= 0;
105 gsize bytes_written
= 0;
106 GError
*error
= NULL
;
109 if (coder
== INVALID_CONV
)
112 if (string
== NULL
|| buffer
== NULL
)
116 if (! used_class.is_valid_string (string))
123 size
= strlen (string
);
127 left
= strlen (string
);
133 g_iconv (coder
, NULL
, NULL
, NULL
, NULL
);
137 tmp_buff
= g_convert_with_iconv ((const gchar
*) string
,
141 &bytes_written
, &error
);
144 int code
= error
->code
;
146 g_error_free (error
);
151 case G_CONVERT_ERROR_NO_CONVERSION
:
152 /* Conversion between the requested character sets is not supported. */
153 tmp_buff
= g_strnfill (strlen (string
), '?');
154 g_string_append (buffer
, tmp_buff
);
158 case G_CONVERT_ERROR_ILLEGAL_SEQUENCE
:
159 /* Invalid byte sequence in conversion input. */
160 if ((tmp_buff
== NULL
) && (bytes_read
!= 0))
161 /* recode valid byte sequence */
162 tmp_buff
= g_convert_with_iconv ((const gchar
*) string
,
164 coder
, NULL
, NULL
, NULL
);
166 if (tmp_buff
!= NULL
)
168 g_string_append (buffer
, tmp_buff
);
172 if ((int)bytes_read
< left
)
174 string
+= bytes_read
+ 1;
175 size
-= (bytes_read
+ 1);
176 left
-= (bytes_read
+ 1);
177 g_string_append_c (buffer
, *(string
-1));
183 state
= ESTR_PROBLEM
;
186 case G_CONVERT_ERROR_PARTIAL_INPUT
:
187 /* Partial character sequence at end of input. */
188 g_string_append (buffer
, tmp_buff
);
190 if ((int)bytes_read
< left
)
192 left
= left
- bytes_read
;
193 tmp_buff
= g_strnfill (left
, '?');
194 g_string_append (buffer
, tmp_buff
);
199 case G_CONVERT_ERROR_BAD_URI
: /* Don't know how handle this error :( */
200 case G_CONVERT_ERROR_NOT_ABSOLUTE_PATH
: /* Don't know how handle this error :( */
201 case G_CONVERT_ERROR_FAILED
: /* Conversion failed for some reason. */
209 if (tmp_buff
!= NULL
)
213 g_string_append (buffer
, tmp_buff
);
215 string
+= bytes_read
;
221 g_string_append (buffer
, string
);
227 g_string_append (buffer
, string
);
236 str_convert (GIConv coder
, const char *string
, GString
* buffer
)
238 return _str_convert (coder
, string
, -1, buffer
);
242 str_nconvert (GIConv coder
, const char *string
, int size
, GString
* buffer
)
244 return _str_convert (coder
, string
, size
, buffer
);
248 str_conv_gerror_message (GError
*error
, const char *def_msg
)
250 return used_class
.conv_gerror_message (error
, def_msg
);
254 str_vfs_convert_from (GIConv coder
, const char *string
, GString
* buffer
)
258 if (coder
== str_cnv_not_convert
)
260 g_string_append (buffer
, string
!= NULL
? string
: "");
261 result
= ESTR_SUCCESS
;
264 result
= _str_convert (coder
, string
, -1, buffer
);
270 str_vfs_convert_to (GIConv coder
, const char *string
, int size
,
273 return used_class
.vfs_convert_to (coder
, string
, size
, buffer
);
277 str_printf (GString
* buffer
, const char *format
, ...)
280 va_start (ap
, format
);
281 #if GLIB_CHECK_VERSION (2, 14, 0)
282 g_string_append_vprintf (buffer
, format
, ap
);
286 tmp
= g_strdup_vprintf (format
, ap
);
287 g_string_append (buffer
, tmp
);
295 str_insert_replace_char (GString
* buffer
)
297 used_class
.insert_replace_char (buffer
);
301 str_translate_char (GIConv conv
, const char *keys
, size_t ch_size
,
302 char *output
, size_t out_size
)
307 g_iconv (conv
, NULL
, NULL
, NULL
, NULL
);
309 left
= (ch_size
== (size_t) (-1)) ? strlen (keys
) : ch_size
;
311 cnv
= g_iconv (conv
, (gchar
**) &keys
, &left
, &output
, &out_size
);
312 if (cnv
== (size_t)(-1)) {
313 return (errno
== EINVAL
) ? ESTR_PROBLEM
: ESTR_FAILURE
;
322 str_detect_termencoding (void)
324 return (nl_langinfo (CODESET
));
328 str_test_encoding_class (const char *encoding
, const char **table
)
332 if ( encoding
== NULL
)
335 for (t
= 0; table
[t
] != NULL
; t
++)
337 result
+= (g_ascii_strncasecmp (encoding
, table
[t
],
338 strlen (table
[t
])) == 0);
344 str_choose_str_functions ()
346 if (str_test_encoding_class (codeset
, str_utf8_encodings
))
348 used_class
= str_utf8_init ();
350 else if (str_test_encoding_class (codeset
, str_8bit_encodings
))
352 used_class
= str_8bit_init ();
356 used_class
= str_ascii_init ();
361 str_isutf8 (const char *codeset_name
)
364 if (str_test_encoding_class (codeset_name
, str_utf8_encodings
))
372 str_init_strings (const char *termenc
)
374 codeset
= g_strdup ((termenc
!= NULL
)
376 : str_detect_termencoding ());
378 str_cnv_not_convert
= g_iconv_open (codeset
, codeset
);
379 if (str_cnv_not_convert
== INVALID_CONV
)
384 codeset
= g_strdup (str_detect_termencoding ());
385 str_cnv_not_convert
= g_iconv_open (codeset
, codeset
);
388 if (str_cnv_not_convert
== INVALID_CONV
)
391 codeset
= g_strdup ("ascii");
392 str_cnv_not_convert
= g_iconv_open (codeset
, codeset
);
396 str_cnv_to_term
= str_cnv_not_convert
;
397 str_cnv_from_term
= str_cnv_not_convert
;
399 str_choose_str_functions ();
403 str_uninit_strings ()
405 g_iconv_close (str_cnv_not_convert
);
409 str_term_form (const char *text
)
411 return used_class
.term_form (text
);
415 str_fit_to_term (const char *text
, int width
, align_crt_t just_mode
)
417 return used_class
.fit_to_term (text
, width
, just_mode
);
421 str_term_trim (const char *text
, int width
)
423 return used_class
.term_trim (text
, width
);
427 str_msg_term_size (const char *text
, int *lines
, int *columns
)
429 used_class
.msg_term_size (text
, lines
, columns
);
433 str_term_substring (const char *text
, int start
, int width
)
435 return used_class
.term_substring (text
, start
, width
);
439 str_get_next_char (char *text
)
442 used_class
.cnext_char ((const char **) &text
);
447 str_cget_next_char (const char *text
)
449 used_class
.cnext_char(&text
);
454 str_next_char (char **text
)
456 used_class
.cnext_char ((const char **) text
);
460 str_cnext_char (const char **text
)
462 used_class
.cnext_char (text
);
466 str_get_prev_char (char *text
)
468 used_class
.cprev_char ((const char **) &text
);
473 str_cget_prev_char (const char *text
)
475 used_class
.cprev_char (&text
);
480 str_prev_char (char **text
)
482 used_class
.cprev_char ((const char **) text
);
486 str_cprev_char (const char **text
)
488 used_class
.cprev_char (text
);
492 str_get_next_char_safe (char *text
)
494 used_class
.cnext_char_safe ((const char **) &text
);
499 str_cget_next_char_safe (const char *text
)
501 used_class
.cnext_char_safe (&text
);
506 str_next_char_safe (char **text
)
508 used_class
.cnext_char_safe ((const char **) text
);
512 str_cnext_char_safe (const char **text
)
514 used_class
.cnext_char_safe (text
);
518 str_get_prev_char_safe (char *text
)
520 used_class
.cprev_char_safe ((const char **) &text
);
525 str_cget_prev_char_safe (const char *text
)
527 used_class
.cprev_char_safe (&text
);
532 str_prev_char_safe (char **text
)
534 used_class
.cprev_char_safe ((const char **) text
);
538 str_cprev_char_safe (const char **text
)
540 used_class
.cprev_char_safe (text
);
544 str_next_noncomb_char (char **text
)
546 return used_class
.cnext_noncomb_char ((const char **) text
);
550 str_cnext_noncomb_char (const char **text
)
552 return used_class
.cnext_noncomb_char (text
);
556 str_prev_noncomb_char (char **text
, const char *begin
)
558 return used_class
.cprev_noncomb_char ((const char **) text
, begin
);
562 str_cprev_noncomb_char (const char **text
, const char *begin
)
564 return used_class
.cprev_noncomb_char (text
, begin
);
568 str_is_valid_char (const char *ch
, size_t size
)
570 return used_class
.is_valid_char (ch
, size
);
574 str_term_width1 (const char *text
)
576 return used_class
.term_width1 (text
);
580 str_term_width2 (const char *text
, size_t length
)
582 return used_class
.term_width2 (text
, length
);
586 str_term_char_width (const char *text
)
588 return used_class
.term_char_width (text
);
592 str_offset_to_pos (const char *text
, size_t length
)
594 return used_class
.offset_to_pos (text
, length
);
598 str_length (const char *text
)
600 return used_class
.length (text
);
604 str_length_char (const char *text
)
606 return str_cget_next_char_safe (text
)-text
;
610 str_length2 (const char *text
, int size
)
612 return used_class
.length2 (text
, size
);
616 str_length_noncomb (const char *text
)
618 return used_class
.length_noncomb (text
);
622 str_column_to_pos (const char *text
, size_t pos
)
624 return used_class
.column_to_pos (text
, pos
);
628 str_isspace (const char *ch
)
630 return used_class
.isspace (ch
);
634 str_ispunct (const char *ch
)
636 return used_class
.ispunct (ch
);
640 str_isalnum (const char *ch
)
642 return used_class
.isalnum (ch
);
646 str_isdigit (const char *ch
)
648 return used_class
.isdigit (ch
);
652 str_toupper (const char *ch
, char **out
, size_t * remain
)
654 return used_class
.toupper (ch
, out
, remain
);
658 str_tolower (const char *ch
, char **out
, size_t * remain
)
660 return used_class
.tolower (ch
, out
, remain
);
664 str_isprint (const char *ch
)
666 return used_class
.isprint (ch
);
670 str_iscombiningmark (const char *ch
)
672 return used_class
.iscombiningmark (ch
);
676 str_trunc (const char *text
, int width
)
678 return used_class
.trunc (text
, width
);
682 str_create_search_needle (const char *needle
, int case_sen
)
684 return used_class
.create_search_needle (needle
, case_sen
);
689 str_release_search_needle (char *needle
, int case_sen
)
691 used_class
.release_search_needle (needle
, case_sen
);
695 str_search_first (const char *text
, const char *search
, int case_sen
)
697 return used_class
.search_first (text
, search
, case_sen
);
701 str_search_last (const char *text
, const char *search
, int case_sen
)
703 return used_class
.search_last (text
, search
, case_sen
);
707 str_is_valid_string (const char *text
)
709 return used_class
.is_valid_string (text
);
713 str_compare (const char *t1
, const char *t2
)
715 return used_class
.compare (t1
, t2
);
719 str_ncompare (const char *t1
, const char *t2
)
721 return used_class
.ncompare (t1
, t2
);
725 str_casecmp (const char *t1
, const char *t2
)
727 return used_class
.casecmp (t1
, t2
);
731 str_ncasecmp (const char *t1
, const char *t2
)
733 return used_class
.ncasecmp (t1
, t2
);
737 str_prefix (const char *text
, const char *prefix
)
739 return used_class
.prefix (text
, prefix
);
743 str_caseprefix (const char *text
, const char *prefix
)
745 return used_class
.caseprefix (text
, prefix
);
749 str_fix_string (char *text
)
751 used_class
.fix_string (text
);
755 str_create_key (const char *text
, int case_sen
)
757 return used_class
.create_key (text
, case_sen
);
761 str_create_key_for_filename (const char *text
, int case_sen
)
763 return used_class
.create_key_for_filename (text
, case_sen
);
767 str_key_collate (const char *t1
, const char *t2
, int case_sen
)
769 return used_class
.key_collate (t1
, t2
, case_sen
);
773 str_release_key (char *key
, int case_sen
)
775 used_class
.release_key (key
, case_sen
);