This source file includes following definitions.
- str_test_not_convert
- _str_convert
- str_test_encoding_class
- str_choose_str_functions
- str_crt_conv_to
- str_crt_conv_from
- str_close_conv
- str_convert
- str_nconvert
- str_conv_gerror_message
- str_vfs_convert_from
- str_vfs_convert_to
- str_printf
- str_insert_replace_char
- str_translate_char
- str_detect_termencoding
- str_isutf8
- str_init_strings
- str_uninit_strings
- str_term_form
- str_fit_to_term
- str_term_trim
- str_term_substring
- str_get_next_char
- str_cget_next_char
- str_next_char
- str_cnext_char
- str_get_prev_char
- str_cget_prev_char
- str_prev_char
- str_cprev_char
- str_get_next_char_safe
- str_cget_next_char_safe
- str_next_char_safe
- str_cnext_char_safe
- str_get_prev_char_safe
- str_cget_prev_char_safe
- str_prev_char_safe
- str_cprev_char_safe
- str_next_noncomb_char
- str_cnext_noncomb_char
- str_prev_noncomb_char
- str_cprev_noncomb_char
- str_is_valid_char
- str_term_width1
- str_term_width2
- str_term_char_width
- str_offset_to_pos
- str_length
- str_length_char
- str_length2
- str_length_noncomb
- str_column_to_pos
- str_isspace
- str_ispunct
- str_isalnum
- str_isdigit
- str_toupper
- str_tolower
- str_isprint
- str_iscombiningmark
- str_trunc
- str_create_search_needle
- str_release_search_needle
- str_search_first
- str_search_last
- str_is_valid_string
- str_compare
- str_ncompare
- str_casecmp
- str_ncasecmp
- str_prefix
- str_caseprefix
- str_fix_string
- str_create_key
- str_create_key_for_filename
- str_key_collate
- str_release_key
- str_msg_term_size
- strrstr_skip_count
- parse_integer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <config.h>
27
28 #include <stdlib.h>
29 #include <langinfo.h>
30 #include <string.h>
31 #include <errno.h>
32
33 #include "lib/global.h"
34 #include "lib/util.h"
35 #include "lib/strutil.h"
36
37
38
39 GIConv str_cnv_to_term;
40 GIConv str_cnv_from_term;
41 GIConv str_cnv_not_convert = INVALID_CONV;
42
43
44
45
46
47
48
49
50
51
52 static const char *const str_utf8_encodings[] = {
53 "utf-8",
54 "utf8",
55 NULL
56 };
57
58
59 static const char *const str_8bit_encodings[] = {
60 "cp-1251",
61 "cp1251",
62
63 "ansi-1251",
64 "ansi1251",
65 "cp-1250",
66 "cp1250",
67 "cp-866",
68 "cp866",
69
70 "ibm-866",
71 "ibm866",
72 "cp-850",
73 "cp850",
74 "cp-852",
75 "cp852",
76 "iso-8859",
77 "iso8859",
78 "koi8",
79 NULL
80 };
81
82
83 static char *codeset = NULL;
84 static char *term_encoding = NULL;
85
86 static struct str_class used_class;
87
88
89
90
91
92
93 static int
94 str_test_not_convert (const char *enc)
95 {
96 return g_ascii_strcasecmp (enc, codeset) == 0;
97 }
98
99
100
101 static estr_t
102 _str_convert (GIConv coder, const char *string, int size, GString *buffer)
103 {
104 estr_t state = ESTR_SUCCESS;
105 gssize left;
106 gsize bytes_read = 0;
107 gsize bytes_written = 0;
108
109 errno = 0;
110
111 if (coder == INVALID_CONV)
112 return ESTR_FAILURE;
113
114 if (string == NULL || buffer == NULL)
115 return ESTR_FAILURE;
116
117
118
119
120
121
122
123 if (size < 0)
124 size = strlen (string);
125 else
126 {
127 left = strlen (string);
128 if (left < size)
129 size = left;
130 }
131
132 left = size;
133 g_iconv (coder, NULL, NULL, NULL, NULL);
134
135 while (left != 0)
136 {
137 gchar *tmp_buff;
138 GError *mcerror = NULL;
139
140 tmp_buff = g_convert_with_iconv ((const gchar *) string,
141 left, coder, &bytes_read, &bytes_written, &mcerror);
142 if (mcerror != NULL)
143 {
144 int code = mcerror->code;
145
146 g_error_free (mcerror);
147 mcerror = NULL;
148
149 switch (code)
150 {
151 case G_CONVERT_ERROR_NO_CONVERSION:
152
153 g_free (tmp_buff);
154 mc_g_string_append_c_len (buffer, '?', strlen (string));
155 return ESTR_FAILURE;
156
157 case G_CONVERT_ERROR_ILLEGAL_SEQUENCE:
158
159 if ((tmp_buff == NULL) && (bytes_read != 0))
160
161 tmp_buff = g_convert_with_iconv ((const gchar *) string,
162 bytes_read, coder, NULL, NULL, NULL);
163
164 if (tmp_buff != NULL)
165 {
166 g_string_append (buffer, tmp_buff);
167 g_free (tmp_buff);
168 }
169
170 if ((int) bytes_read >= left)
171 return ESTR_PROBLEM;
172
173 string += bytes_read + 1;
174 size -= (bytes_read + 1);
175 left -= (bytes_read + 1);
176 g_string_append_c (buffer, *(string - 1));
177 state = ESTR_PROBLEM;
178 break;
179
180 case G_CONVERT_ERROR_PARTIAL_INPUT:
181
182 g_string_append (buffer, tmp_buff);
183 g_free (tmp_buff);
184 if ((int) bytes_read < left)
185 mc_g_string_append_c_len (buffer, '?', left - bytes_read);
186 return ESTR_PROBLEM;
187
188 case G_CONVERT_ERROR_BAD_URI:
189 case G_CONVERT_ERROR_NOT_ABSOLUTE_PATH:
190 case G_CONVERT_ERROR_FAILED:
191 default:
192 g_free (tmp_buff);
193 return ESTR_FAILURE;
194 }
195 }
196 else if (tmp_buff == NULL)
197 {
198 g_string_append (buffer, string);
199 return ESTR_PROBLEM;
200 }
201 else if (*tmp_buff == '\0')
202 {
203 g_free (tmp_buff);
204 g_string_append (buffer, string);
205 return state;
206 }
207 else
208 {
209 g_string_append (buffer, tmp_buff);
210 g_free (tmp_buff);
211 string += bytes_read;
212 left -= bytes_read;
213 }
214 }
215
216 return state;
217 }
218
219
220
221 static int
222 str_test_encoding_class (const char *encoding, const char *const *table)
223 {
224 int result = 0;
225
226 if (encoding != NULL)
227 {
228 int t;
229
230 for (t = 0; table[t] != NULL; t++)
231 if (g_ascii_strncasecmp (encoding, table[t], strlen (table[t])) == 0)
232 result++;
233 }
234
235 return result;
236 }
237
238
239
240 static void
241 str_choose_str_functions (void)
242 {
243 if (str_test_encoding_class (codeset, str_utf8_encodings))
244 used_class = str_utf8_init ();
245 else if (str_test_encoding_class (codeset, str_8bit_encodings))
246 used_class = str_8bit_init ();
247 else
248 used_class = str_ascii_init ();
249 }
250
251
252
253
254
255 GIConv
256 str_crt_conv_to (const char *to_enc)
257 {
258 return (!str_test_not_convert (to_enc)) ? g_iconv_open (to_enc, codeset) : str_cnv_not_convert;
259 }
260
261
262
263 GIConv
264 str_crt_conv_from (const char *from_enc)
265 {
266 return (!str_test_not_convert (from_enc))
267 ? g_iconv_open (codeset, from_enc) : str_cnv_not_convert;
268 }
269
270
271
272 void
273 str_close_conv (GIConv conv)
274 {
275 if (conv != INVALID_CONV && conv != str_cnv_not_convert)
276 g_iconv_close (conv);
277 }
278
279
280
281 estr_t
282 str_convert (GIConv coder, const char *string, GString *buffer)
283 {
284 return _str_convert (coder, string, -1, buffer);
285 }
286
287
288
289 estr_t
290 str_nconvert (GIConv coder, const char *string, int size, GString *buffer)
291 {
292 return _str_convert (coder, string, size, buffer);
293 }
294
295
296
297 gchar *
298 str_conv_gerror_message (GError *mcerror, const char *def_msg)
299 {
300 return used_class.conv_gerror_message (mcerror, def_msg);
301 }
302
303
304
305 estr_t
306 str_vfs_convert_from (GIConv coder, const char *string, GString *buffer)
307 {
308 estr_t result = ESTR_SUCCESS;
309
310 if (coder == str_cnv_not_convert)
311 g_string_append (buffer, string != NULL ? string : "");
312 else
313 result = _str_convert (coder, string, -1, buffer);
314
315 return result;
316 }
317
318
319
320 estr_t
321 str_vfs_convert_to (GIConv coder, const char *string, int size, GString *buffer)
322 {
323 return used_class.vfs_convert_to (coder, string, size, buffer);
324 }
325
326
327
328 void
329 str_printf (GString *buffer, const char *format, ...)
330 {
331 va_list ap;
332 va_start (ap, format);
333
334 g_string_append_vprintf (buffer, format, ap);
335 va_end (ap);
336 }
337
338
339
340 void
341 str_insert_replace_char (GString *buffer)
342 {
343 used_class.insert_replace_char (buffer);
344 }
345
346
347
348 estr_t
349 str_translate_char (GIConv conv, const char *keys, size_t ch_size, char *output, size_t out_size)
350 {
351 size_t left;
352 size_t cnv;
353
354 g_iconv (conv, NULL, NULL, NULL, NULL);
355
356 left = (ch_size == (size_t) (-1)) ? strlen (keys) : ch_size;
357
358 cnv = g_iconv (conv, (gchar **) & keys, &left, &output, &out_size);
359 if (cnv == (size_t) (-1))
360 return (errno == EINVAL) ? ESTR_PROBLEM : ESTR_FAILURE;
361
362 output[0] = '\0';
363 return ESTR_SUCCESS;
364 }
365
366
367
368 const char *
369 str_detect_termencoding (void)
370 {
371 if (term_encoding == NULL)
372 {
373
374
375
376
377 term_encoding = g_ascii_strup (nl_langinfo (CODESET), -1);
378 }
379
380 return term_encoding;
381 }
382
383
384
385 gboolean
386 str_isutf8 (const char *codeset_name)
387 {
388 return (str_test_encoding_class (codeset_name, str_utf8_encodings) != 0);
389 }
390
391
392
393 void
394 str_init_strings (const char *termenc)
395 {
396 codeset = termenc != NULL ? g_ascii_strup (termenc, -1) : g_strdup (str_detect_termencoding ());
397
398 str_cnv_not_convert = g_iconv_open (codeset, codeset);
399 if (str_cnv_not_convert == INVALID_CONV)
400 {
401 if (termenc != NULL)
402 {
403 g_free (codeset);
404 codeset = g_strdup (str_detect_termencoding ());
405 str_cnv_not_convert = g_iconv_open (codeset, codeset);
406 }
407
408 if (str_cnv_not_convert == INVALID_CONV)
409 {
410 g_free (codeset);
411 codeset = g_strdup (DEFAULT_CHARSET);
412 str_cnv_not_convert = g_iconv_open (codeset, codeset);
413 }
414 }
415
416 str_cnv_to_term = str_cnv_not_convert;
417 str_cnv_from_term = str_cnv_not_convert;
418
419 str_choose_str_functions ();
420 }
421
422
423
424 void
425 str_uninit_strings (void)
426 {
427 if (str_cnv_not_convert != INVALID_CONV)
428 g_iconv_close (str_cnv_not_convert);
429
430 MC_PTR_FREE (term_encoding);
431 MC_PTR_FREE (codeset);
432 }
433
434
435
436 const char *
437 str_term_form (const char *text)
438 {
439 return used_class.term_form (text);
440 }
441
442
443
444 const char *
445 str_fit_to_term (const char *text, int width, align_crt_t just_mode)
446 {
447 return used_class.fit_to_term (text, width, just_mode);
448 }
449
450
451
452 const char *
453 str_term_trim (const char *text, int width)
454 {
455 return used_class.term_trim (text, width);
456 }
457
458
459
460 const char *
461 str_term_substring (const char *text, int start, int width)
462 {
463 return used_class.term_substring (text, start, width);
464 }
465
466
467
468 char *
469 str_get_next_char (char *text)
470 {
471
472 used_class.cnext_char ((const char **) &text);
473 return text;
474 }
475
476
477
478 const char *
479 str_cget_next_char (const char *text)
480 {
481 used_class.cnext_char (&text);
482 return text;
483 }
484
485
486
487 void
488 str_next_char (char **text)
489 {
490 used_class.cnext_char ((const char **) text);
491 }
492
493
494
495 void
496 str_cnext_char (const char **text)
497 {
498 used_class.cnext_char (text);
499 }
500
501
502
503 char *
504 str_get_prev_char (char *text)
505 {
506 used_class.cprev_char ((const char **) &text);
507 return text;
508 }
509
510
511
512 const char *
513 str_cget_prev_char (const char *text)
514 {
515 used_class.cprev_char (&text);
516 return text;
517 }
518
519
520
521 void
522 str_prev_char (char **text)
523 {
524 used_class.cprev_char ((const char **) text);
525 }
526
527
528
529 void
530 str_cprev_char (const char **text)
531 {
532 used_class.cprev_char (text);
533 }
534
535
536
537 char *
538 str_get_next_char_safe (char *text)
539 {
540 used_class.cnext_char_safe ((const char **) &text);
541 return text;
542 }
543
544
545
546 const char *
547 str_cget_next_char_safe (const char *text)
548 {
549 used_class.cnext_char_safe (&text);
550 return text;
551 }
552
553
554
555 void
556 str_next_char_safe (char **text)
557 {
558 used_class.cnext_char_safe ((const char **) text);
559 }
560
561
562
563 void
564 str_cnext_char_safe (const char **text)
565 {
566 used_class.cnext_char_safe (text);
567 }
568
569
570
571 char *
572 str_get_prev_char_safe (char *text)
573 {
574 used_class.cprev_char_safe ((const char **) &text);
575 return text;
576 }
577
578
579
580 const char *
581 str_cget_prev_char_safe (const char *text)
582 {
583 used_class.cprev_char_safe (&text);
584 return text;
585 }
586
587
588
589 void
590 str_prev_char_safe (char **text)
591 {
592 used_class.cprev_char_safe ((const char **) text);
593 }
594
595
596
597 void
598 str_cprev_char_safe (const char **text)
599 {
600 used_class.cprev_char_safe (text);
601 }
602
603
604
605 int
606 str_next_noncomb_char (char **text)
607 {
608 return used_class.cnext_noncomb_char ((const char **) text);
609 }
610
611
612
613 int
614 str_cnext_noncomb_char (const char **text)
615 {
616 return used_class.cnext_noncomb_char (text);
617 }
618
619
620
621 int
622 str_prev_noncomb_char (char **text, const char *begin)
623 {
624 return used_class.cprev_noncomb_char ((const char **) text, begin);
625 }
626
627
628
629 int
630 str_cprev_noncomb_char (const char **text, const char *begin)
631 {
632 return used_class.cprev_noncomb_char (text, begin);
633 }
634
635
636
637 int
638 str_is_valid_char (const char *ch, size_t size)
639 {
640 return used_class.is_valid_char (ch, size);
641 }
642
643
644
645 int
646 str_term_width1 (const char *text)
647 {
648 return used_class.term_width1 (text);
649 }
650
651
652
653 int
654 str_term_width2 (const char *text, size_t length)
655 {
656 return used_class.term_width2 (text, length);
657 }
658
659
660
661 int
662 str_term_char_width (const char *text)
663 {
664 return used_class.term_char_width (text);
665 }
666
667
668
669 int
670 str_offset_to_pos (const char *text, size_t length)
671 {
672 return used_class.offset_to_pos (text, length);
673 }
674
675
676
677 int
678 str_length (const char *text)
679 {
680 return used_class.length (text);
681 }
682
683
684
685 int
686 str_length_char (const char *text)
687 {
688 return str_cget_next_char_safe (text) - text;
689 }
690
691
692
693 int
694 str_length2 (const char *text, int size)
695 {
696 return used_class.length2 (text, size);
697 }
698
699
700
701 int
702 str_length_noncomb (const char *text)
703 {
704 return used_class.length_noncomb (text);
705 }
706
707
708
709 int
710 str_column_to_pos (const char *text, size_t pos)
711 {
712 return used_class.column_to_pos (text, pos);
713 }
714
715
716
717 gboolean
718 str_isspace (const char *ch)
719 {
720 return used_class.char_isspace (ch);
721 }
722
723
724
725 gboolean
726 str_ispunct (const char *ch)
727 {
728 return used_class.char_ispunct (ch);
729 }
730
731
732
733 gboolean
734 str_isalnum (const char *ch)
735 {
736 return used_class.char_isalnum (ch);
737 }
738
739
740
741 gboolean
742 str_isdigit (const char *ch)
743 {
744 return used_class.char_isdigit (ch);
745 }
746
747
748
749 gboolean
750 str_toupper (const char *ch, char **out, size_t *remain)
751 {
752 return used_class.char_toupper (ch, out, remain);
753 }
754
755
756
757 gboolean
758 str_tolower (const char *ch, char **out, size_t *remain)
759 {
760 return used_class.char_tolower (ch, out, remain);
761 }
762
763
764
765 gboolean
766 str_isprint (const char *ch)
767 {
768 return used_class.char_isprint (ch);
769 }
770
771
772
773 gboolean
774 str_iscombiningmark (const char *ch)
775 {
776 return used_class.char_iscombiningmark (ch);
777 }
778
779
780
781 const char *
782 str_trunc (const char *text, int width)
783 {
784 return used_class.trunc (text, width);
785 }
786
787
788
789 char *
790 str_create_search_needle (const char *needle, gboolean case_sen)
791 {
792 return used_class.create_search_needle (needle, case_sen);
793 }
794
795
796
797 void
798 str_release_search_needle (char *needle, gboolean case_sen)
799 {
800 used_class.release_search_needle (needle, case_sen);
801 }
802
803
804
805 const char *
806 str_search_first (const char *text, const char *search, gboolean case_sen)
807 {
808 return used_class.search_first (text, search, case_sen);
809 }
810
811
812
813 const char *
814 str_search_last (const char *text, const char *search, gboolean case_sen)
815 {
816 return used_class.search_last (text, search, case_sen);
817 }
818
819
820
821 gboolean
822 str_is_valid_string (const char *text)
823 {
824 return used_class.is_valid_string (text);
825 }
826
827
828
829 int
830 str_compare (const char *t1, const char *t2)
831 {
832 return used_class.compare (t1, t2);
833 }
834
835
836
837 int
838 str_ncompare (const char *t1, const char *t2)
839 {
840 return used_class.ncompare (t1, t2);
841 }
842
843
844
845 int
846 str_casecmp (const char *t1, const char *t2)
847 {
848 return used_class.casecmp (t1, t2);
849 }
850
851
852
853 int
854 str_ncasecmp (const char *t1, const char *t2)
855 {
856 return used_class.ncasecmp (t1, t2);
857 }
858
859
860
861 int
862 str_prefix (const char *text, const char *prefix)
863 {
864 return used_class.prefix (text, prefix);
865 }
866
867
868
869 int
870 str_caseprefix (const char *text, const char *prefix)
871 {
872 return used_class.caseprefix (text, prefix);
873 }
874
875
876
877 void
878 str_fix_string (char *text)
879 {
880 used_class.fix_string (text);
881 }
882
883
884
885 char *
886 str_create_key (const char *text, gboolean case_sen)
887 {
888 return used_class.create_key (text, case_sen);
889 }
890
891
892
893 char *
894 str_create_key_for_filename (const char *text, gboolean case_sen)
895 {
896 return used_class.create_key_for_filename (text, case_sen);
897 }
898
899
900
901 int
902 str_key_collate (const char *t1, const char *t2, gboolean case_sen)
903 {
904 return used_class.key_collate (t1, t2, case_sen);
905 }
906
907
908
909 void
910 str_release_key (char *key, gboolean case_sen)
911 {
912 used_class.release_key (key, case_sen);
913 }
914
915
916
917 void
918 str_msg_term_size (const char *text, int *lines, int *columns)
919 {
920 char *p, *tmp;
921 char *q;
922 char c = '\0';
923
924 *lines = 1;
925 *columns = 0;
926
927 tmp = g_strdup (text);
928 p = tmp;
929
930 while (TRUE)
931 {
932 int width;
933
934 q = strchr (p, '\n');
935 if (q != NULL)
936 {
937 c = q[0];
938 q[0] = '\0';
939 }
940
941 width = str_term_width1 (p);
942 if (width > *columns)
943 *columns = width;
944
945 if (q == NULL)
946 break;
947
948 q[0] = c;
949 p = q + 1;
950 (*lines)++;
951 }
952
953 g_free (tmp);
954 }
955
956
957
958 char *
959 strrstr_skip_count (const char *haystack, const char *needle, size_t skip_count)
960 {
961 char *semi;
962 ssize_t len;
963
964 len = strlen (haystack);
965
966 do
967 {
968 semi = g_strrstr_len (haystack, len, needle);
969 if (semi == NULL)
970 return NULL;
971 len = semi - haystack - 1;
972 }
973 while (skip_count-- != 0);
974
975 return semi;
976 }
977
978
979
980
981
982
983
984
985
986
987 uintmax_t
988 parse_integer (const char *str, gboolean *invalid)
989 {
990 uintmax_t n;
991 char *suffix;
992 strtol_error_t e;
993
994 e = xstrtoumax (str, &suffix, 10, &n, "bcEGkKMPTwYZ0");
995 if (e == LONGINT_INVALID_SUFFIX_CHAR && *suffix == 'x')
996 {
997 uintmax_t multiplier;
998
999 multiplier = parse_integer (suffix + 1, invalid);
1000 if (multiplier != 0 && n * multiplier / multiplier != n)
1001 {
1002 *invalid = TRUE;
1003 return 0;
1004 }
1005
1006 n *= multiplier;
1007 }
1008 else if (e != LONGINT_OK)
1009 {
1010 *invalid = TRUE;
1011 n = 0;
1012 }
1013
1014 return n;
1015 }
1016
1017