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