This source file includes following definitions.
- DECLARE_CTYPE_WRAPPER
- str_8bit_is_valid_string
- str_8bit_is_valid_char
- str_8bit_cnext_char
- str_8bit_cprev_char
- str_8bit_cnext_noncomb_char
- str_8bit_cprev_noncomb_char
- str_8bit_isspace
- str_8bit_ispunct
- str_8bit_isalnum
- str_8bit_isdigit
- str_8bit_isprint
- str_8bit_iscombiningmark
- str_8bit_toupper
- str_8bit_tolower
- str_8bit_length
- str_8bit_length2
- str_8bit_conv_gerror_message
- str_8bit_vfs_convert_to
- str_8bit_term_form
- str_8bit_fit_to_term
- str_8bit_term_trim
- str_8bit_term_width2
- str_8bit_term_width1
- str_8bit_term_char_width
- str_8bit_term_substring
- str_8bit_trunc
- str_8bit_offset_to_pos
- str_8bit_column_to_pos
- str_8bit_create_search_needle
- str_8bit_release_search_needle
- str_8bit_strdown
- str_8bit_search_first
- str_8bit_search_last
- str_8bit_compare
- str_8bit_ncompare
- str_8bit_casecmp
- str_8bit_ncasecmp
- str_8bit_prefix
- str_8bit_caseprefix
- str_8bit_fix_string
- str_8bit_create_key
- str_8bit_key_collate
- str_8bit_release_key
- str_8bit_init
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 <ctype.h>
29 #include <stdlib.h>
30
31 #include "lib/global.h"
32 #include "lib/strutil.h"
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 #define DECLARE_CTYPE_WRAPPER(func_name) \
52 static inline int char_##func_name (char c) { return func_name ((int) (unsigned char) c); }
53
54
55
56
57
58
59
60 static const char replch = '?';
61
62
63
64
65
66 DECLARE_CTYPE_WRAPPER (isalnum)
67 DECLARE_CTYPE_WRAPPER (isdigit)
68 DECLARE_CTYPE_WRAPPER (isprint)
69 DECLARE_CTYPE_WRAPPER (ispunct)
70 DECLARE_CTYPE_WRAPPER (isspace)
71 DECLARE_CTYPE_WRAPPER (toupper)
72 DECLARE_CTYPE_WRAPPER (tolower)
73
74
75
76 static void
77 str_8bit_insert_replace_char (GString *buffer)
78 {
79 g_string_append_c (buffer, replch);
80 }
81
82
83
84 static gboolean
85 str_8bit_is_valid_string (const char *text)
86 {
87 (void) text;
88 return TRUE;
89 }
90
91
92
93 static int
94 str_8bit_is_valid_char (const char *ch, size_t size)
95 {
96 (void) ch;
97 (void) size;
98 return 1;
99 }
100
101
102
103 static void
104 str_8bit_cnext_char (const char **text)
105 {
106 (*text)++;
107 }
108
109
110
111 static void
112 str_8bit_cprev_char (const char **text)
113 {
114 (*text)--;
115 }
116
117
118
119 static int
120 str_8bit_cnext_noncomb_char (const char **text)
121 {
122 if (*text[0] == '\0')
123 return 0;
124
125 (*text)++;
126 return 1;
127 }
128
129
130
131 static int
132 str_8bit_cprev_noncomb_char (const char **text, const char *begin)
133 {
134 if ((*text) == begin)
135 return 0;
136
137 (*text)--;
138 return 1;
139 }
140
141
142
143 static gboolean
144 str_8bit_isspace (const char *text)
145 {
146 return char_isspace (text[0]) != 0;
147 }
148
149
150
151 static gboolean
152 str_8bit_ispunct (const char *text)
153 {
154 return char_ispunct (text[0]) != 0;
155 }
156
157
158
159 static gboolean
160 str_8bit_isalnum (const char *text)
161 {
162 return char_isalnum (text[0]) != 0;
163 }
164
165
166
167 static gboolean
168 str_8bit_isdigit (const char *text)
169 {
170 return char_isdigit (text[0]) != 0;
171 }
172
173
174
175 static gboolean
176 str_8bit_isprint (const char *text)
177 {
178 return char_isprint (text[0]) != 0;
179 }
180
181
182
183 static gboolean
184 str_8bit_iscombiningmark (const char *text)
185 {
186 (void) text;
187 return FALSE;
188 }
189
190
191
192 static int
193 str_8bit_toupper (const char *text, char **out, size_t *remain)
194 {
195 if (*remain <= 1)
196 return FALSE;
197
198 (*out)[0] = char_toupper (text[0]);
199 (*out)++;
200 (*remain)--;
201 return TRUE;
202 }
203
204
205
206 static gboolean
207 str_8bit_tolower (const char *text, char **out, size_t *remain)
208 {
209 if (*remain <= 1)
210 return FALSE;
211
212 (*out)[0] = char_tolower (text[0]);
213 (*out)++;
214 (*remain)--;
215 return TRUE;
216 }
217
218
219
220 static int
221 str_8bit_length (const char *text)
222 {
223 return strlen (text);
224 }
225
226
227
228 static int
229 str_8bit_length2 (const char *text, int size)
230 {
231 size_t length;
232
233 length = strlen (text);
234
235 return (size >= 0) ? MIN (length, (size_t) size) : length;
236 }
237
238
239
240 static gchar *
241 str_8bit_conv_gerror_message (GError *mcerror, const char *def_msg)
242 {
243 GIConv conv;
244 gchar *ret;
245
246
247 conv = str_crt_conv_from ("UTF-8");
248
249 if (conv == INVALID_CONV)
250 ret = g_strdup (def_msg != NULL ? def_msg : "");
251 else
252 {
253 GString *buf;
254
255 buf = g_string_new ("");
256
257 if (str_convert (conv, mcerror->message, buf) != ESTR_FAILURE)
258 ret = g_string_free (buf, FALSE);
259 else
260 {
261 ret = g_strdup (def_msg != NULL ? def_msg : "");
262 g_string_free (buf, TRUE);
263 }
264
265 str_close_conv (conv);
266 }
267
268 return ret;
269 }
270
271
272
273 static estr_t
274 str_8bit_vfs_convert_to (GIConv coder, const char *string, int size, GString *buffer)
275 {
276 estr_t result = ESTR_SUCCESS;
277
278 if (coder == str_cnv_not_convert)
279 g_string_append_len (buffer, string, size);
280 else
281 result = str_nconvert (coder, string, size, buffer);
282
283 return result;
284 }
285
286
287
288 static const char *
289 str_8bit_term_form (const char *text)
290 {
291 static char result[BUF_MEDIUM];
292 char *actual;
293 size_t remain;
294 size_t length;
295 size_t pos = 0;
296
297 actual = result;
298 remain = sizeof (result);
299 length = strlen (text);
300
301 for (; pos < length && remain > 1; pos++, actual++, remain--)
302 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
303
304 actual[0] = '\0';
305 return result;
306 }
307
308
309
310 static const char *
311 str_8bit_fit_to_term (const char *text, int width, align_crt_t just_mode)
312 {
313 static char result[BUF_MEDIUM];
314 char *actual;
315 size_t remain;
316 int ident = 0;
317 size_t length;
318 size_t pos = 0;
319
320 length = strlen (text);
321 actual = result;
322 remain = sizeof (result);
323
324 if ((int) length <= width)
325 {
326 switch (HIDE_FIT (just_mode))
327 {
328 case J_CENTER_LEFT:
329 case J_CENTER:
330 ident = (width - length) / 2;
331 break;
332 case J_RIGHT:
333 ident = width - length;
334 break;
335 default:
336 break;
337 }
338
339 if ((int) remain <= ident)
340 goto finally;
341 memset (actual, ' ', ident);
342 actual += ident;
343 remain -= ident;
344
345 for (; pos < length && remain > 1; pos++, actual++, remain--)
346 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
347
348 if (width - length - ident > 0)
349 {
350 if (remain <= width - length - ident)
351 goto finally;
352 memset (actual, ' ', width - length - ident);
353 actual += width - length - ident;
354 }
355 }
356 else if (IS_FIT (just_mode))
357 {
358 for (; pos + 1 <= (gsize) width / 2 && remain > 1; actual++, pos++, remain--)
359 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
360
361 if (remain <= 1)
362 goto finally;
363 actual[0] = '~';
364 actual++;
365 remain--;
366
367 pos += length - width + 1;
368 for (; pos < length && remain > 1; pos++, actual++, remain--)
369 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
370 }
371 else
372 {
373 switch (HIDE_FIT (just_mode))
374 {
375 case J_CENTER:
376 ident = (length - width) / 2;
377 break;
378 case J_RIGHT:
379 ident = length - width;
380 break;
381 default:
382 break;
383 }
384
385 pos += ident;
386 for (; pos < (gsize) (ident + width) && remain > 1; pos++, actual++, remain--)
387 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
388 }
389
390 finally:
391 if (actual >= result + sizeof (result))
392 actual = result + sizeof (result) - 1;
393 actual[0] = '\0';
394 return result;
395 }
396
397
398
399 static const char *
400 str_8bit_term_trim (const char *text, const ssize_t width)
401 {
402 static char result[BUF_MEDIUM];
403 size_t remain;
404 char *actual;
405 size_t length;
406
407 length = strlen (text);
408 actual = result;
409 remain = sizeof (result);
410
411 if (width > 0)
412 {
413 size_t pos;
414
415 if ((size_t) width >= length)
416 {
417 for (pos = 0; pos < length && remain > 1; pos++, actual++, remain--)
418 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
419 }
420 else if (width <= 3)
421 {
422 memset (actual, '.', (size_t) width);
423 actual += width;
424 }
425 else
426 {
427 memset (actual, '.', 3);
428 actual += 3;
429 remain -= 3;
430
431 for (pos = length - (size_t) width + 3; pos < length && remain > 1;
432 pos++, actual++, remain--)
433 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
434 }
435 }
436
437 actual[0] = '\0';
438 return result;
439 }
440
441
442
443 static size_t
444 str_8bit_term_width2 (const char *text, const ssize_t width)
445 {
446 const size_t text_len = strlen (text);
447
448 return (width < 0 ? text_len : MIN (text_len, (size_t) width));
449 }
450
451
452
453 static size_t
454 str_8bit_term_width1 (const char *text)
455 {
456 return str_8bit_term_width2 (text, -1);
457 }
458
459
460
461 static int
462 str_8bit_term_char_width (const char *text)
463 {
464 (void) text;
465 return 1;
466 }
467
468
469
470 static const char *
471 str_8bit_term_substring (const char *text, int start, int width)
472 {
473 static char result[BUF_MEDIUM];
474 size_t remain;
475 char *actual;
476 size_t length;
477
478 actual = result;
479 remain = sizeof (result);
480 length = strlen (text);
481
482 if (start < (int) length)
483 {
484 size_t pos;
485
486 for (pos = start; pos < length && width > 0 && remain > 1;
487 pos++, width--, actual++, remain--)
488 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
489 }
490
491 for (; width > 0 && remain > 1; actual++, remain--, width--)
492 actual[0] = ' ';
493
494 actual[0] = '\0';
495 return result;
496 }
497
498
499
500 static const char *
501 str_8bit_trunc (const char *text, const ssize_t width)
502 {
503 static char result[MC_MAXPATHLEN];
504 int remain;
505 char *actual;
506 size_t pos = 0;
507 size_t length;
508
509 actual = result;
510 remain = sizeof (result);
511 length = strlen (text);
512
513 if (width >= 0 && length > (size_t) width)
514 {
515 for (; pos + 1 <= (size_t) width / 2 && remain > 1; actual++, pos++, remain--)
516 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
517
518 if (remain <= 1)
519 goto finally;
520 actual[0] = '~';
521 actual++;
522 remain--;
523
524 pos += length - (size_t) width + 1;
525 for (; pos < length && remain > 1; pos++, actual++, remain--)
526 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
527 }
528 else
529 {
530 for (; pos < length && remain > 1; pos++, actual++, remain--)
531 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
532 }
533
534 finally:
535 actual[0] = '\0';
536 return result;
537 }
538
539
540
541 static int
542 str_8bit_offset_to_pos (const char *text, size_t length)
543 {
544 (void) text;
545 return (int) length;
546 }
547
548
549
550 static int
551 str_8bit_column_to_pos (const char *text, size_t pos)
552 {
553 (void) text;
554 return (int) pos;
555 }
556
557
558
559 static char *
560 str_8bit_create_search_needle (const char *needle, gboolean case_sen)
561 {
562 (void) case_sen;
563 return (char *) needle;
564 }
565
566
567
568 static void
569 str_8bit_release_search_needle (char *needle, gboolean case_sen)
570 {
571 (void) case_sen;
572 (void) needle;
573 }
574
575
576
577 static char *
578 str_8bit_strdown (const char *str)
579 {
580 char *rets, *p;
581
582 if (str == NULL)
583 return NULL;
584
585 rets = g_strdup (str);
586
587 for (p = rets; *p != '\0'; p++)
588 *p = char_tolower (*p);
589
590 return rets;
591 }
592
593
594
595 static const char *
596 str_8bit_search_first (const char *text, const char *search, gboolean case_sen)
597 {
598 char *fold_text;
599 char *fold_search;
600 const char *match;
601
602 fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
603 fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
604
605 match = g_strstr_len (fold_text, -1, fold_search);
606 if (match != NULL)
607 {
608 size_t offset;
609
610 offset = match - fold_text;
611 match = text + offset;
612 }
613
614 if (!case_sen)
615 {
616 g_free (fold_text);
617 g_free (fold_search);
618 }
619
620 return match;
621 }
622
623
624
625 static const char *
626 str_8bit_search_last (const char *text, const char *search, gboolean case_sen)
627 {
628 char *fold_text;
629 char *fold_search;
630 const char *match;
631
632 fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
633 fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
634
635 match = g_strrstr_len (fold_text, -1, fold_search);
636 if (match != NULL)
637 {
638 size_t offset;
639
640 offset = match - fold_text;
641 match = text + offset;
642 }
643
644 if (!case_sen)
645 {
646 g_free (fold_text);
647 g_free (fold_search);
648 }
649
650 return match;
651 }
652
653
654
655 static int
656 str_8bit_compare (const char *t1, const char *t2)
657 {
658 return strcmp (t1, t2);
659 }
660
661
662
663 static int
664 str_8bit_ncompare (const char *t1, const char *t2)
665 {
666 size_t l1, l2;
667
668 l1 = strlen (t1);
669 l2 = strlen (t2);
670
671 return strncmp (t1, t2, MIN (l1, l2));
672 }
673
674
675
676 static int
677 str_8bit_casecmp (const char *s1, const char *s2)
678 {
679
680
681 #ifdef HAVE_STRCASECMP
682 g_return_val_if_fail (s1 != NULL, 0);
683 g_return_val_if_fail (s2 != NULL, 0);
684
685 return strcasecmp (s1, s2);
686 #else
687
688 g_return_val_if_fail (s1 != NULL, 0);
689 g_return_val_if_fail (s2 != NULL, 0);
690
691 for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++)
692 {
693 gint c1, c2;
694
695
696
697
698 c1 = isupper ((guchar) *s1) ? tolower ((guchar) *s1) : *s1;
699 c2 = isupper ((guchar) *s2) ? tolower ((guchar) *s2) : *s2;
700 if (c1 != c2)
701 return (c1 - c2);
702 }
703
704 return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
705 #endif
706 }
707
708
709
710 static int
711 str_8bit_ncasecmp (const char *s1, const char *s2)
712 {
713 size_t l1, l2;
714 size_t n;
715
716 g_return_val_if_fail (s1 != NULL, 0);
717 g_return_val_if_fail (s2 != NULL, 0);
718
719 l1 = strlen (s1);
720 l2 = strlen (s2);
721 n = MIN (l1, l2);
722
723
724
725 #ifdef HAVE_STRNCASECMP
726 return strncasecmp (s1, s2, n);
727 #else
728
729 for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++)
730 {
731 gint c1, c2;
732
733 n--;
734
735
736
737 c1 = isupper ((guchar) *s1) ? tolower ((guchar) *s1) : *s1;
738 c2 = isupper ((guchar) *s2) ? tolower ((guchar) *s2) : *s2;
739 if (c1 != c2)
740 return (c1 - c2);
741 }
742
743 if (n == 0)
744 return 0;
745
746 return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
747
748 #endif
749 }
750
751
752
753 static int
754 str_8bit_prefix (const char *text, const char *prefix)
755 {
756 int result;
757
758 for (result = 0;
759 text[result] != '\0' && prefix[result] != '\0' && text[result] == prefix[result]; result++)
760 ;
761
762 return result;
763 }
764
765
766
767 static int
768 str_8bit_caseprefix (const char *text, const char *prefix)
769 {
770 int result;
771
772 for (result = 0; text[result] != '\0' && prefix[result] != '\0'
773 && char_toupper (text[result]) == char_toupper (prefix[result]);
774 result++)
775 ;
776
777 return result;
778 }
779
780
781
782 static void
783 str_8bit_fix_string (char *text)
784 {
785 (void) text;
786 }
787
788
789
790 static char *
791 str_8bit_create_key (const char *text, gboolean case_sen)
792 {
793 return case_sen ? (char *) text : str_8bit_strdown (text);
794 }
795
796
797
798 static int
799 str_8bit_key_collate (const char *t1, const char *t2, gboolean case_sen)
800 {
801 return case_sen ? strcmp (t1, t2) : strcoll (t1, t2);
802 }
803
804
805
806 static void
807 str_8bit_release_key (char *key, gboolean case_sen)
808 {
809 if (!case_sen)
810 g_free (key);
811 }
812
813
814
815
816
817 struct str_class
818 str_8bit_init (void)
819 {
820 struct str_class result;
821
822 result.conv_gerror_message = str_8bit_conv_gerror_message;
823 result.vfs_convert_to = str_8bit_vfs_convert_to;
824 result.insert_replace_char = str_8bit_insert_replace_char;
825 result.is_valid_string = str_8bit_is_valid_string;
826 result.is_valid_char = str_8bit_is_valid_char;
827 result.cnext_char = str_8bit_cnext_char;
828 result.cprev_char = str_8bit_cprev_char;
829 result.cnext_char_safe = str_8bit_cnext_char;
830 result.cprev_char_safe = str_8bit_cprev_char;
831 result.cnext_noncomb_char = str_8bit_cnext_noncomb_char;
832 result.cprev_noncomb_char = str_8bit_cprev_noncomb_char;
833 result.char_isspace = str_8bit_isspace;
834 result.char_ispunct = str_8bit_ispunct;
835 result.char_isalnum = str_8bit_isalnum;
836 result.char_isdigit = str_8bit_isdigit;
837 result.char_isprint = str_8bit_isprint;
838 result.char_iscombiningmark = str_8bit_iscombiningmark;
839 result.char_toupper = str_8bit_toupper;
840 result.char_tolower = str_8bit_tolower;
841 result.length = str_8bit_length;
842 result.length2 = str_8bit_length2;
843 result.length_noncomb = str_8bit_length;
844 result.fix_string = str_8bit_fix_string;
845 result.term_form = str_8bit_term_form;
846 result.fit_to_term = str_8bit_fit_to_term;
847 result.term_trim = str_8bit_term_trim;
848 result.term_width2 = str_8bit_term_width2;
849 result.term_width1 = str_8bit_term_width1;
850 result.term_char_width = str_8bit_term_char_width;
851 result.term_substring = str_8bit_term_substring;
852 result.trunc = str_8bit_trunc;
853 result.offset_to_pos = str_8bit_offset_to_pos;
854 result.column_to_pos = str_8bit_column_to_pos;
855 result.create_search_needle = str_8bit_create_search_needle;
856 result.release_search_needle = str_8bit_release_search_needle;
857 result.search_first = str_8bit_search_first;
858 result.search_last = str_8bit_search_last;
859 result.compare = str_8bit_compare;
860 result.ncompare = str_8bit_ncompare;
861 result.casecmp = str_8bit_casecmp;
862 result.ncasecmp = str_8bit_ncasecmp;
863 result.prefix = str_8bit_prefix;
864 result.caseprefix = str_8bit_caseprefix;
865 result.create_key = str_8bit_create_key;
866 result.create_key_for_filename = str_8bit_create_key;
867 result.key_collate = str_8bit_key_collate;
868 result.release_key = str_8bit_release_key;
869
870 return result;
871 }
872
873