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.
38 //names, that are used for utf-8
39 static const char *str_utf8_encodings
[] = {
45 // standard 8bit encodings, no wide or multibytes characters
46 static const char *str_8bit_encodings
[] = {
65 // function for encoding specific operations
66 static struct str_class used_class
;
68 iconv_t str_cnv_to_term
;
69 iconv_t str_cnv_from_term
;
70 iconv_t str_cnv_not_convert
;
72 // if enc is same encoding like on terminal
74 str_test_not_convert (const char *enc
)
76 return g_ascii_strcasecmp (enc
, codeset
) == 0;
80 str_crt_conv_to (const char *to_enc
)
82 return (!str_test_not_convert (to_enc
))
83 ? g_iconv_open (to_enc
, codeset
) : str_cnv_not_convert
;
87 str_crt_conv_from (const char *from_enc
)
89 return (!str_test_not_convert (from_enc
))
90 ? g_iconv_open (codeset
, from_enc
) : str_cnv_not_convert
;
94 str_close_conv (GIConv conv
)
96 if (conv
!= str_cnv_not_convert
)
101 _str_convert (GIConv coder
, char *string
, int size
, GString
* buffer
)
106 gsize bytes_read
, bytes_written
;
107 GError
*error
= NULL
;
111 if (used_class
.is_valid_string (string
))
116 size
= strlen (string
);
120 left
= strlen (string
);
126 if (coder
== (GIConv
) (-1))
129 g_iconv (coder
, NULL
, NULL
, NULL
, NULL
);
133 tmp_buff
= g_convert_with_iconv ((const gchar
*) string
,
137 &bytes_written
, &error
);
143 case G_CONVERT_ERROR_NO_CONVERSION
:
144 /* Conversion between the requested character sets is not supported. */
145 tmp_buff
= g_strnfill (strlen (string
), '?');
146 g_string_append (buffer
, tmp_buff
);
148 g_error_free (error
);
151 case G_CONVERT_ERROR_ILLEGAL_SEQUENCE
:
152 /* Invalid byte sequence in conversion input. */
153 g_string_append (buffer
, tmp_buff
);
154 g_string_append (buffer
, "?");
156 if (bytes_read
< left
)
158 string
+= bytes_read
+ 1;
159 size
-= (bytes_read
+ 1);
160 left
-= (bytes_read
+ 1);
164 g_error_free (error
);
167 state
= ESTR_PROBLEM
;
169 case G_CONVERT_ERROR_PARTIAL_INPUT
:
170 /* Partial character sequence at end of input. */
171 g_error_free (error
);
172 g_string_append (buffer
, tmp_buff
);
174 if (bytes_read
< left
)
176 left
= left
- bytes_read
;
177 tmp_buff
= g_strnfill (left
, '?');
178 g_string_append (buffer
, tmp_buff
);
183 case G_CONVERT_ERROR_BAD_URI
: /* Don't know how handle this error :( */
184 case G_CONVERT_ERROR_NOT_ABSOLUTE_PATH
: /* Don't know how handle this error :( */
185 case G_CONVERT_ERROR_FAILED
: /* Conversion failed for some reason. */
187 g_error_free (error
);
193 g_error_free (error
);
197 g_string_append (buffer
, tmp_buff
);
199 string
+= bytes_read
;
210 str_convert (GIConv coder
, char *string
, GString
* buffer
)
214 result
= _str_convert (coder
, string
, -1, buffer
);
220 str_nconvert (GIConv coder
, char *string
, int size
, GString
* buffer
)
224 result
= _str_convert (coder
, string
, size
, buffer
);
230 str_vfs_convert_from (GIConv coder
, char *string
, GString
* buffer
)
234 if (coder
== str_cnv_not_convert
)
236 g_string_append (buffer
, string
);
240 result
= _str_convert (coder
, string
, -1, buffer
);
246 str_vfs_convert_to (GIConv coder
, const char *string
, int size
,
249 return used_class
.vfs_convert_to (coder
, string
, size
, buffer
);
253 str_printf (GString
* buffer
, const char *format
, ...)
256 va_start (ap
, format
);
257 g_string_append_vprintf (buffer
, format
, ap
);
262 str_insert_replace_char (GString
* buffer
)
264 used_class
.insert_replace_char (buffer
);
268 str_translate_char (str_conv_t conv
, char *keys
, size_t ch_size
,
269 char *output
, size_t out_size
)
274 iconv (conv
, NULL
, NULL
, NULL
, NULL
);
276 left
= (ch_size
== (size_t) (-1)) ? strlen (keys
) : ch_size
;
278 cnv
= iconv (conv
, &keys
, &left
, &output
, &out_size
);
279 if (cnv
== (size_t) (-1))
295 str_detect_termencoding ()
297 return (nl_langinfo (CODESET
));
301 str_test_encoding_class (const char *encoding
, const char **table
)
306 for (t
= 0; table
[t
] != NULL
; t
++)
308 result
+= (g_ascii_strncasecmp (encoding
, table
[t
],
309 strlen (table
[t
])) == 0);
316 str_choose_str_functions ()
318 if (str_test_encoding_class (codeset
, str_utf8_encodings
))
320 used_class
= str_utf8_init ();
322 else if (str_test_encoding_class (codeset
, str_8bit_encodings
))
324 used_class
= str_8bit_init ();
328 used_class
= str_ascii_init ();
333 str_isutf8 (char *codeset_name
)
336 if (str_test_encoding_class (codeset_name
, str_utf8_encodings
))
344 str_init_strings (const char *termenc
)
346 codeset
= g_strdup ((termenc
!= NULL
)
347 ? termenc
: str_detect_termencoding ());
349 str_cnv_not_convert
= iconv_open (codeset
, codeset
);
350 if (str_cnv_not_convert
== INVALID_CONV
)
355 codeset
= g_strdup (str_detect_termencoding ());
356 str_cnv_not_convert
= iconv_open (codeset
, codeset
);
359 if (str_cnv_not_convert
== INVALID_CONV
)
362 codeset
= g_strdup ("ascii");
363 str_cnv_not_convert
= iconv_open (codeset
, codeset
);
367 str_cnv_to_term
= str_cnv_not_convert
;
368 str_cnv_from_term
= str_cnv_not_convert
;
370 str_choose_str_functions ();
374 str_uninit_strings ()
376 iconv_close (str_cnv_not_convert
);
380 str_term_form (const char *text
)
382 return used_class
.term_form (text
);
386 str_fit_to_term (const char *text
, int width
, int just_mode
)
388 return used_class
.fit_to_term (text
, width
, just_mode
);
392 str_term_trim (const char *text
, int width
)
394 return used_class
.term_trim (text
, width
);
398 str_msg_term_size (const char *text
, int *lines
, int *columns
)
400 return used_class
.msg_term_size (text
, lines
, columns
);
404 str_term_substring (const char *text
, int start
, int width
)
406 return used_class
.term_substring (text
, start
, width
);
410 str_get_next_char (char *text
)
413 used_class
.cnext_char ((const char **) &text
);
418 str_cget_next_char (const char *text
)
420 used_class
.cnext_char (&text
);
425 str_next_char (char **text
)
427 used_class
.cnext_char ((const char **) text
);
431 str_cnext_char (const char **text
)
433 used_class
.cnext_char (text
);
437 str_get_prev_char (char *text
)
439 used_class
.cprev_char ((const char **) &text
);
444 str_cget_prev_char (const char *text
)
446 used_class
.cprev_char (&text
);
451 str_prev_char (char **text
)
453 used_class
.cprev_char ((const char **) text
);
457 str_cprev_char (const char **text
)
459 used_class
.cprev_char (text
);
463 str_get_next_char_safe (char *text
)
465 used_class
.cnext_char_safe ((const char **) &text
);
470 str_cget_next_char_safe (const char *text
)
472 used_class
.cnext_char_safe (&text
);
477 str_next_char_safe (char **text
)
479 used_class
.cnext_char_safe ((const char **) text
);
483 str_cnext_char_safe (const char **text
)
485 used_class
.cnext_char_safe (text
);
489 str_get_prev_char_safe (char *text
)
491 used_class
.cprev_char_safe ((const char **) &text
);
496 str_cget_prev_char_safe (const char *text
)
498 used_class
.cprev_char_safe (&text
);
503 str_prev_char_safe (char **text
)
505 used_class
.cprev_char_safe ((const char **) text
);
509 str_cprev_char_safe (const char **text
)
511 used_class
.cprev_char_safe (text
);
515 str_next_noncomb_char (char **text
)
517 return used_class
.cnext_noncomb_char ((const char **) text
);
521 str_cnext_noncomb_char (const char **text
)
523 return used_class
.cnext_noncomb_char (text
);
527 str_prev_noncomb_char (char **text
, const char *begin
)
529 return used_class
.cprev_noncomb_char ((const char **) text
, begin
);
533 str_cprev_noncomb_char (const char **text
, const char *begin
)
535 return used_class
.cprev_noncomb_char (text
, begin
);
539 str_is_valid_char (const char *ch
, size_t size
)
541 return used_class
.is_valid_char (ch
, size
);
545 str_term_width1 (const char *text
)
547 return used_class
.term_width1 (text
);
551 str_term_width2 (const char *text
, size_t length
)
553 return used_class
.term_width2 (text
, length
);
557 str_term_char_width (const char *text
)
559 return used_class
.term_char_width (text
);
563 str_offset_to_pos (const char *text
, size_t length
)
565 return used_class
.offset_to_pos (text
, length
);
569 str_length (const char *text
)
571 return used_class
.length (text
);
575 str_length2 (const char *text
, int size
)
577 return used_class
.length2 (text
, size
);
581 str_length_noncomb (const char *text
)
583 return used_class
.length_noncomb (text
);
587 str_column_to_pos (const char *text
, size_t pos
)
589 return used_class
.column_to_pos (text
, pos
);
593 str_isspace (const char *ch
)
595 return used_class
.isspace (ch
);
599 str_ispunct (const char *ch
)
601 return used_class
.ispunct (ch
);
605 str_isalnum (const char *ch
)
607 return used_class
.isalnum (ch
);
611 str_isdigit (const char *ch
)
613 return used_class
.isdigit (ch
);
617 str_toupper (const char *ch
, char **out
, size_t * remain
)
619 return used_class
.toupper (ch
, out
, remain
);
623 str_tolower (const char *ch
, char **out
, size_t * remain
)
625 return used_class
.tolower (ch
, out
, remain
);
629 str_isprint (const char *ch
)
631 return used_class
.isprint (ch
);
635 str_iscombiningmark (const char *ch
)
637 return used_class
.iscombiningmark (ch
);
641 str_trunc (const char *text
, int width
)
643 return used_class
.trunc (text
, width
);
647 str_create_search_needle (const char *needle
, int case_sen
)
649 return used_class
.create_search_needle (needle
, case_sen
);
654 str_release_search_needle (char *needle
, int case_sen
)
656 used_class
.release_search_needle (needle
, case_sen
);
660 str_search_first (const char *text
, const char *search
, int case_sen
)
662 return used_class
.search_first (text
, search
, case_sen
);
666 str_search_last (const char *text
, const char *search
, int case_sen
)
668 return used_class
.search_last (text
, search
, case_sen
);
672 str_is_valid_string (const char *text
)
674 return used_class
.is_valid_string (text
);
678 str_compare (const char *t1
, const char *t2
)
680 return used_class
.compare (t1
, t2
);
684 str_ncompare (const char *t1
, const char *t2
)
686 return used_class
.ncompare (t1
, t2
);
690 str_casecmp (const char *t1
, const char *t2
)
692 return used_class
.casecmp (t1
, t2
);
696 str_ncasecmp (const char *t1
, const char *t2
)
698 return used_class
.ncasecmp (t1
, t2
);
702 str_prefix (const char *text
, const char *prefix
)
704 return used_class
.prefix (text
, prefix
);
708 str_caseprefix (const char *text
, const char *prefix
)
710 return used_class
.caseprefix (text
, prefix
);
714 str_fix_string (char *text
)
716 used_class
.fix_string (text
);
720 str_create_key (const char *text
, int case_sen
)
722 return used_class
.create_key (text
, case_sen
);
726 str_create_key_for_filename (const char *text
, int case_sen
)
728 return used_class
.create_key_for_filename (text
, case_sen
);
732 str_key_collate (const char *t1
, const char *t2
, int case_sen
)
734 return used_class
.key_collate (t1
, t2
, case_sen
);
738 str_release_key (char *key
, int case_sen
)
740 used_class
.release_key (key
, case_sen
);