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, int 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 (width >= (int) 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, '.', width);
423 actual += width;
424 }
425 else
426 {
427 memset (actual, '.', 3);
428 actual += 3;
429 remain -= 3;
430
431 for (pos = length - width + 3; pos < length && remain > 1; pos++, actual++, remain--)
432 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
433 }
434 }
435
436 actual[0] = '\0';
437 return result;
438 }
439
440
441
442 static int
443 str_8bit_term_width2 (const char *text, size_t length)
444 {
445 size_t text_len;
446
447 text_len = strlen (text);
448
449 return (length != (size_t) (-1)) ? MIN (text_len, length) : text_len;
450 }
451
452
453
454 static int
455 str_8bit_term_width1 (const char *text)
456 {
457 return str_8bit_term_width2 (text, (size_t) (-1));
458 }
459
460
461
462 static int
463 str_8bit_term_char_width (const char *text)
464 {
465 (void) text;
466 return 1;
467 }
468
469
470
471 static const char *
472 str_8bit_term_substring (const char *text, int start, int width)
473 {
474 static char result[BUF_MEDIUM];
475 size_t remain;
476 char *actual;
477 size_t length;
478
479 actual = result;
480 remain = sizeof (result);
481 length = strlen (text);
482
483 if (start < (int) length)
484 {
485 size_t pos;
486
487 for (pos = start; pos < length && width > 0 && remain > 1;
488 pos++, width--, actual++, remain--)
489 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
490 }
491
492 for (; width > 0 && remain > 1; actual++, remain--, width--)
493 actual[0] = ' ';
494
495 actual[0] = '\0';
496 return result;
497 }
498
499
500
501 static const char *
502 str_8bit_trunc (const char *text, int width)
503 {
504 static char result[MC_MAXPATHLEN];
505 int remain;
506 char *actual;
507 size_t pos = 0;
508 size_t length;
509
510 actual = result;
511 remain = sizeof (result);
512 length = strlen (text);
513
514 if ((int) length > width)
515 {
516 for (; pos + 1 <= (gsize) width / 2 && remain > 1; actual++, pos++, remain--)
517 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
518
519 if (remain <= 1)
520 goto finally;
521 actual[0] = '~';
522 actual++;
523 remain--;
524
525 pos += length - width + 1;
526 for (; pos < length && remain > 1; pos++, actual++, remain--)
527 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
528 }
529 else
530 {
531 for (; pos < length && remain > 1; pos++, actual++, remain--)
532 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
533 }
534
535 finally:
536 actual[0] = '\0';
537 return result;
538 }
539
540
541
542 static int
543 str_8bit_offset_to_pos (const char *text, size_t length)
544 {
545 (void) text;
546 return (int) length;
547 }
548
549
550
551 static int
552 str_8bit_column_to_pos (const char *text, size_t pos)
553 {
554 (void) text;
555 return (int) pos;
556 }
557
558
559
560 static char *
561 str_8bit_create_search_needle (const char *needle, gboolean case_sen)
562 {
563 (void) case_sen;
564 return (char *) needle;
565 }
566
567
568
569 static void
570 str_8bit_release_search_needle (char *needle, gboolean case_sen)
571 {
572 (void) case_sen;
573 (void) needle;
574 }
575
576
577
578 static char *
579 str_8bit_strdown (const char *str)
580 {
581 char *rets, *p;
582
583 if (str == NULL)
584 return NULL;
585
586 rets = g_strdup (str);
587
588 for (p = rets; *p != '\0'; p++)
589 *p = char_tolower (*p);
590
591 return rets;
592 }
593
594
595
596 static const char *
597 str_8bit_search_first (const char *text, const char *search, gboolean case_sen)
598 {
599 char *fold_text;
600 char *fold_search;
601 const char *match;
602
603 fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
604 fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
605
606 match = g_strstr_len (fold_text, -1, fold_search);
607 if (match != NULL)
608 {
609 size_t offset;
610
611 offset = match - fold_text;
612 match = text + offset;
613 }
614
615 if (!case_sen)
616 {
617 g_free (fold_text);
618 g_free (fold_search);
619 }
620
621 return match;
622 }
623
624
625
626 static const char *
627 str_8bit_search_last (const char *text, const char *search, gboolean case_sen)
628 {
629 char *fold_text;
630 char *fold_search;
631 const char *match;
632
633 fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
634 fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
635
636 match = g_strrstr_len (fold_text, -1, fold_search);
637 if (match != NULL)
638 {
639 size_t offset;
640
641 offset = match - fold_text;
642 match = text + offset;
643 }
644
645 if (!case_sen)
646 {
647 g_free (fold_text);
648 g_free (fold_search);
649 }
650
651 return match;
652 }
653
654
655
656 static int
657 str_8bit_compare (const char *t1, const char *t2)
658 {
659 return strcmp (t1, t2);
660 }
661
662
663
664 static int
665 str_8bit_ncompare (const char *t1, const char *t2)
666 {
667 size_t l1, l2;
668
669 l1 = strlen (t1);
670 l2 = strlen (t2);
671
672 return strncmp (t1, t2, MIN (l1, l2));
673 }
674
675
676
677 static int
678 str_8bit_casecmp (const char *s1, const char *s2)
679 {
680
681
682 #ifdef HAVE_STRCASECMP
683 g_return_val_if_fail (s1 != NULL, 0);
684 g_return_val_if_fail (s2 != NULL, 0);
685
686 return strcasecmp (s1, s2);
687 #else
688
689 g_return_val_if_fail (s1 != NULL, 0);
690 g_return_val_if_fail (s2 != NULL, 0);
691
692 for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++)
693 {
694 gint c1, c2;
695
696
697
698
699 c1 = isupper ((guchar) *s1) ? tolower ((guchar) *s1) : *s1;
700 c2 = isupper ((guchar) *s2) ? tolower ((guchar) *s2) : *s2;
701 if (c1 != c2)
702 return (c1 - c2);
703 }
704
705 return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
706 #endif
707 }
708
709
710
711 static int
712 str_8bit_ncasecmp (const char *s1, const char *s2)
713 {
714 size_t l1, l2;
715 size_t n;
716
717 g_return_val_if_fail (s1 != NULL, 0);
718 g_return_val_if_fail (s2 != NULL, 0);
719
720 l1 = strlen (s1);
721 l2 = strlen (s2);
722 n = MIN (l1, l2);
723
724
725
726 #ifdef HAVE_STRNCASECMP
727 return strncasecmp (s1, s2, n);
728 #else
729
730 for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++)
731 {
732 gint c1, c2;
733
734 n--;
735
736
737
738 c1 = isupper ((guchar) *s1) ? tolower ((guchar) *s1) : *s1;
739 c2 = isupper ((guchar) *s2) ? tolower ((guchar) *s2) : *s2;
740 if (c1 != c2)
741 return (c1 - c2);
742 }
743
744 if (n == 0)
745 return 0;
746
747 return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
748
749 #endif
750 }
751
752
753
754 static int
755 str_8bit_prefix (const char *text, const char *prefix)
756 {
757 int result;
758
759 for (result = 0;
760 text[result] != '\0' && prefix[result] != '\0' && text[result] == prefix[result]; result++)
761 ;
762
763 return result;
764 }
765
766
767
768 static int
769 str_8bit_caseprefix (const char *text, const char *prefix)
770 {
771 int result;
772
773 for (result = 0; text[result] != '\0' && prefix[result] != '\0'
774 && char_toupper (text[result]) == char_toupper (prefix[result]);
775 result++)
776 ;
777
778 return result;
779 }
780
781
782
783 static void
784 str_8bit_fix_string (char *text)
785 {
786 (void) text;
787 }
788
789
790
791 static char *
792 str_8bit_create_key (const char *text, gboolean case_sen)
793 {
794 return case_sen ? (char *) text : str_8bit_strdown (text);
795 }
796
797
798
799 static int
800 str_8bit_key_collate (const char *t1, const char *t2, gboolean case_sen)
801 {
802 return case_sen ? strcmp (t1, t2) : strcoll (t1, t2);
803 }
804
805
806
807 static void
808 str_8bit_release_key (char *key, gboolean case_sen)
809 {
810 if (!case_sen)
811 g_free (key);
812 }
813
814
815
816
817
818 struct str_class
819 str_8bit_init (void)
820 {
821 struct str_class result;
822
823 result.conv_gerror_message = str_8bit_conv_gerror_message;
824 result.vfs_convert_to = str_8bit_vfs_convert_to;
825 result.insert_replace_char = str_8bit_insert_replace_char;
826 result.is_valid_string = str_8bit_is_valid_string;
827 result.is_valid_char = str_8bit_is_valid_char;
828 result.cnext_char = str_8bit_cnext_char;
829 result.cprev_char = str_8bit_cprev_char;
830 result.cnext_char_safe = str_8bit_cnext_char;
831 result.cprev_char_safe = str_8bit_cprev_char;
832 result.cnext_noncomb_char = str_8bit_cnext_noncomb_char;
833 result.cprev_noncomb_char = str_8bit_cprev_noncomb_char;
834 result.char_isspace = str_8bit_isspace;
835 result.char_ispunct = str_8bit_ispunct;
836 result.char_isalnum = str_8bit_isalnum;
837 result.char_isdigit = str_8bit_isdigit;
838 result.char_isprint = str_8bit_isprint;
839 result.char_iscombiningmark = str_8bit_iscombiningmark;
840 result.char_toupper = str_8bit_toupper;
841 result.char_tolower = str_8bit_tolower;
842 result.length = str_8bit_length;
843 result.length2 = str_8bit_length2;
844 result.length_noncomb = str_8bit_length;
845 result.fix_string = str_8bit_fix_string;
846 result.term_form = str_8bit_term_form;
847 result.fit_to_term = str_8bit_fit_to_term;
848 result.term_trim = str_8bit_term_trim;
849 result.term_width2 = str_8bit_term_width2;
850 result.term_width1 = str_8bit_term_width1;
851 result.term_char_width = str_8bit_term_char_width;
852 result.term_substring = str_8bit_term_substring;
853 result.trunc = str_8bit_trunc;
854 result.offset_to_pos = str_8bit_offset_to_pos;
855 result.column_to_pos = str_8bit_column_to_pos;
856 result.create_search_needle = str_8bit_create_search_needle;
857 result.release_search_needle = str_8bit_release_search_needle;
858 result.search_first = str_8bit_search_first;
859 result.search_last = str_8bit_search_last;
860 result.compare = str_8bit_compare;
861 result.ncompare = str_8bit_ncompare;
862 result.casecmp = str_8bit_casecmp;
863 result.ncasecmp = str_8bit_ncasecmp;
864 result.prefix = str_8bit_prefix;
865 result.caseprefix = str_8bit_caseprefix;
866 result.create_key = str_8bit_create_key;
867 result.create_key_for_filename = str_8bit_create_key;
868 result.key_collate = str_8bit_key_collate;
869 result.release_key = str_8bit_release_key;
870
871 return result;
872 }
873
874