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 return (size >= 0) ? MIN (strlen (text), (gsize) size) : strlen (text);
237 }
238
239
240
241 static gchar *
242 str_8bit_conv_gerror_message (GError * mcerror, const char *def_msg)
243 {
244 GIConv conv;
245 gchar *ret;
246
247
248 conv = str_crt_conv_from ("UTF-8");
249
250 if (conv == INVALID_CONV)
251 ret = g_strdup (def_msg != NULL ? def_msg : "");
252 else
253 {
254 GString *buf;
255
256 buf = g_string_new ("");
257
258 if (str_convert (conv, mcerror->message, buf) != ESTR_FAILURE)
259 ret = g_string_free (buf, FALSE);
260 else
261 {
262 ret = g_strdup (def_msg != NULL ? def_msg : "");
263 g_string_free (buf, TRUE);
264 }
265
266 str_close_conv (conv);
267 }
268
269 return ret;
270 }
271
272
273
274 static estr_t
275 str_8bit_vfs_convert_to (GIConv coder, const char *string, int size, GString * buffer)
276 {
277 estr_t result = ESTR_SUCCESS;
278
279 if (coder == str_cnv_not_convert)
280 g_string_append_len (buffer, string, size);
281 else
282 result = str_nconvert (coder, string, size, buffer);
283
284 return result;
285 }
286
287
288
289 static const char *
290 str_8bit_term_form (const char *text)
291 {
292 static char result[BUF_MEDIUM];
293 char *actual;
294 size_t remain;
295 size_t length;
296 size_t pos = 0;
297
298 actual = result;
299 remain = sizeof (result);
300 length = strlen (text);
301
302 for (; pos < length && remain > 1; pos++, actual++, remain--)
303 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
304
305 actual[0] = '\0';
306 return result;
307 }
308
309
310
311 static const char *
312 str_8bit_fit_to_term (const char *text, int width, align_crt_t just_mode)
313 {
314 static char result[BUF_MEDIUM];
315 char *actual;
316 size_t remain;
317 int ident = 0;
318 size_t length;
319 size_t pos = 0;
320
321 length = strlen (text);
322 actual = result;
323 remain = sizeof (result);
324
325 if ((int) length <= width)
326 {
327 switch (HIDE_FIT (just_mode))
328 {
329 case J_CENTER_LEFT:
330 case J_CENTER:
331 ident = (width - length) / 2;
332 break;
333 case J_RIGHT:
334 ident = width - length;
335 break;
336 default:
337 break;
338 }
339
340 if ((int) remain <= ident)
341 goto finally;
342 memset (actual, ' ', ident);
343 actual += ident;
344 remain -= ident;
345
346 for (; pos < length && remain > 1; pos++, actual++, remain--)
347 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
348
349 if (width - length - ident > 0)
350 {
351 if (remain <= width - length - ident)
352 goto finally;
353 memset (actual, ' ', width - length - ident);
354 actual += width - length - ident;
355 }
356 }
357 else if (IS_FIT (just_mode))
358 {
359 for (; pos + 1 <= (gsize) width / 2 && remain > 1; actual++, pos++, remain--)
360 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
361
362 if (remain <= 1)
363 goto finally;
364 actual[0] = '~';
365 actual++;
366 remain--;
367
368 pos += length - width + 1;
369 for (; pos < length && remain > 1; pos++, actual++, remain--)
370 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
371 }
372 else
373 {
374 switch (HIDE_FIT (just_mode))
375 {
376 case J_CENTER:
377 ident = (length - width) / 2;
378 break;
379 case J_RIGHT:
380 ident = length - width;
381 break;
382 default:
383 break;
384 }
385
386 pos += ident;
387 for (; pos < (gsize) (ident + width) && remain > 1; pos++, actual++, remain--)
388 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
389 }
390
391 finally:
392 if (actual >= result + sizeof (result))
393 actual = result + sizeof (result) - 1;
394 actual[0] = '\0';
395 return result;
396 }
397
398
399
400 static const char *
401 str_8bit_term_trim (const char *text, int width)
402 {
403 static char result[BUF_MEDIUM];
404 size_t remain;
405 char *actual;
406 size_t length;
407
408 length = strlen (text);
409 actual = result;
410 remain = sizeof (result);
411
412 if (width > 0)
413 {
414 size_t pos;
415
416 if (width >= (int) length)
417 {
418 for (pos = 0; pos < length && remain > 1; pos++, actual++, remain--)
419 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
420 }
421 else if (width <= 3)
422 {
423 memset (actual, '.', width);
424 actual += width;
425 }
426 else
427 {
428 memset (actual, '.', 3);
429 actual += 3;
430 remain -= 3;
431
432 for (pos = length - width + 3; pos < length && remain > 1; 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 int
444 str_8bit_term_width2 (const char *text, size_t length)
445 {
446 return (length != (size_t) (-1)) ? MIN (strlen (text), length) : strlen (text);
447 }
448
449
450
451 static int
452 str_8bit_term_width1 (const char *text)
453 {
454 return str_8bit_term_width2 (text, (size_t) (-1));
455 }
456
457
458
459 static int
460 str_8bit_term_char_width (const char *text)
461 {
462 (void) text;
463 return 1;
464 }
465
466
467
468 static const char *
469 str_8bit_term_substring (const char *text, int start, int width)
470 {
471 static char result[BUF_MEDIUM];
472 size_t remain;
473 char *actual;
474 size_t length;
475
476 actual = result;
477 remain = sizeof (result);
478 length = strlen (text);
479
480 if (start < (int) length)
481 {
482 size_t pos;
483
484 for (pos = start; pos < length && width > 0 && remain > 1;
485 pos++, width--, actual++, remain--)
486 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
487 }
488
489 for (; width > 0 && remain > 1; actual++, remain--, width--)
490 actual[0] = ' ';
491
492 actual[0] = '\0';
493 return result;
494 }
495
496
497
498 static const char *
499 str_8bit_trunc (const char *text, int width)
500 {
501 static char result[MC_MAXPATHLEN];
502 int remain;
503 char *actual;
504 size_t pos = 0;
505 size_t length;
506
507 actual = result;
508 remain = sizeof (result);
509 length = strlen (text);
510
511 if ((int) length > width)
512 {
513 for (; pos + 1 <= (gsize) width / 2 && remain > 1; actual++, pos++, remain--)
514 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
515
516 if (remain <= 1)
517 goto finally;
518 actual[0] = '~';
519 actual++;
520 remain--;
521
522 pos += length - width + 1;
523 for (; pos < length && remain > 1; pos++, actual++, remain--)
524 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
525 }
526 else
527 {
528 for (; pos < length && remain > 1; pos++, actual++, remain--)
529 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
530 }
531
532 finally:
533 actual[0] = '\0';
534 return result;
535 }
536
537
538
539 static int
540 str_8bit_offset_to_pos (const char *text, size_t length)
541 {
542 (void) text;
543 return (int) length;
544 }
545
546
547
548 static int
549 str_8bit_column_to_pos (const char *text, size_t pos)
550 {
551 (void) text;
552 return (int) pos;
553 }
554
555
556
557 static char *
558 str_8bit_create_search_needle (const char *needle, gboolean case_sen)
559 {
560 (void) case_sen;
561 return (char *) needle;
562 }
563
564
565
566 static void
567 str_8bit_release_search_needle (char *needle, gboolean case_sen)
568 {
569 (void) case_sen;
570 (void) needle;
571 }
572
573
574
575 static char *
576 str_8bit_strdown (const char *str)
577 {
578 char *rets, *p;
579
580 if (str == NULL)
581 return NULL;
582
583 rets = g_strdup (str);
584
585 for (p = rets; *p != '\0'; p++)
586 *p = char_tolower (*p);
587
588 return rets;
589 }
590
591
592
593 static const char *
594 str_8bit_search_first (const char *text, const char *search, gboolean case_sen)
595 {
596 char *fold_text;
597 char *fold_search;
598 const char *match;
599
600 fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
601 fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
602
603 match = g_strstr_len (fold_text, -1, fold_search);
604 if (match != NULL)
605 {
606 size_t offset;
607
608 offset = match - fold_text;
609 match = text + offset;
610 }
611
612 if (!case_sen)
613 {
614 g_free (fold_text);
615 g_free (fold_search);
616 }
617
618 return match;
619 }
620
621
622
623 static const char *
624 str_8bit_search_last (const char *text, const char *search, gboolean case_sen)
625 {
626 char *fold_text;
627 char *fold_search;
628 const char *match;
629
630 fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
631 fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
632
633 match = g_strrstr_len (fold_text, -1, fold_search);
634 if (match != NULL)
635 {
636 size_t offset;
637
638 offset = match - fold_text;
639 match = text + offset;
640 }
641
642 if (!case_sen)
643 {
644 g_free (fold_text);
645 g_free (fold_search);
646 }
647
648 return match;
649 }
650
651
652
653 static int
654 str_8bit_compare (const char *t1, const char *t2)
655 {
656 return strcmp (t1, t2);
657 }
658
659
660
661 static int
662 str_8bit_ncompare (const char *t1, const char *t2)
663 {
664 return strncmp (t1, t2, MIN (strlen (t1), strlen (t2)));
665 }
666
667
668
669 static int
670 str_8bit_casecmp (const char *s1, const char *s2)
671 {
672
673
674 #ifdef HAVE_STRCASECMP
675 g_return_val_if_fail (s1 != NULL, 0);
676 g_return_val_if_fail (s2 != NULL, 0);
677
678 return strcasecmp (s1, s2);
679 #else
680
681 g_return_val_if_fail (s1 != NULL, 0);
682 g_return_val_if_fail (s2 != NULL, 0);
683
684 for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++)
685 {
686 gint c1, c2;
687
688
689
690
691 c1 = isupper ((guchar) * s1) ? tolower ((guchar) * s1) : *s1;
692 c2 = isupper ((guchar) * s2) ? tolower ((guchar) * s2) : *s2;
693 if (c1 != c2)
694 return (c1 - c2);
695 }
696
697 return (((gint) (guchar) * s1) - ((gint) (guchar) * s2));
698 #endif
699 }
700
701
702
703 static int
704 str_8bit_ncasecmp (const char *s1, const char *s2)
705 {
706 size_t n;
707
708 g_return_val_if_fail (s1 != NULL, 0);
709 g_return_val_if_fail (s2 != NULL, 0);
710
711 n = MIN (strlen (s1), strlen (s2));
712
713
714
715 #ifdef HAVE_STRNCASECMP
716 return strncasecmp (s1, s2, n);
717 #else
718
719 for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++)
720 {
721 gint c1, c2;
722
723 n--;
724
725
726
727 c1 = isupper ((guchar) * s1) ? tolower ((guchar) * s1) : *s1;
728 c2 = isupper ((guchar) * s2) ? tolower ((guchar) * s2) : *s2;
729 if (c1 != c2)
730 return (c1 - c2);
731 }
732
733 if (n == 0)
734 return 0;
735
736 return (((gint) (guchar) * s1) - ((gint) (guchar) * s2));
737
738 #endif
739 }
740
741
742
743 static int
744 str_8bit_prefix (const char *text, const char *prefix)
745 {
746 int result;
747
748 for (result = 0; text[result] != '\0' && prefix[result] != '\0'
749 && text[result] == prefix[result]; result++);
750
751 return result;
752 }
753
754
755
756 static int
757 str_8bit_caseprefix (const char *text, const char *prefix)
758 {
759 int result;
760
761 for (result = 0; text[result] != '\0' && prefix[result] != '\0'
762 && char_toupper (text[result]) == char_toupper (prefix[result]); result++);
763
764 return result;
765 }
766
767
768
769 static void
770 str_8bit_fix_string (char *text)
771 {
772 (void) text;
773 }
774
775
776
777 static char *
778 str_8bit_create_key (const char *text, gboolean case_sen)
779 {
780 return case_sen ? (char *) text : str_8bit_strdown (text);
781 }
782
783
784
785 static int
786 str_8bit_key_collate (const char *t1, const char *t2, gboolean case_sen)
787 {
788 return case_sen ? strcmp (t1, t2) : strcoll (t1, t2);
789 }
790
791
792
793 static void
794 str_8bit_release_key (char *key, gboolean case_sen)
795 {
796 if (!case_sen)
797 g_free (key);
798 }
799
800
801
802
803
804 struct str_class
805 str_8bit_init (void)
806 {
807 struct str_class result;
808
809 result.conv_gerror_message = str_8bit_conv_gerror_message;
810 result.vfs_convert_to = str_8bit_vfs_convert_to;
811 result.insert_replace_char = str_8bit_insert_replace_char;
812 result.is_valid_string = str_8bit_is_valid_string;
813 result.is_valid_char = str_8bit_is_valid_char;
814 result.cnext_char = str_8bit_cnext_char;
815 result.cprev_char = str_8bit_cprev_char;
816 result.cnext_char_safe = str_8bit_cnext_char;
817 result.cprev_char_safe = str_8bit_cprev_char;
818 result.cnext_noncomb_char = str_8bit_cnext_noncomb_char;
819 result.cprev_noncomb_char = str_8bit_cprev_noncomb_char;
820 result.char_isspace = str_8bit_isspace;
821 result.char_ispunct = str_8bit_ispunct;
822 result.char_isalnum = str_8bit_isalnum;
823 result.char_isdigit = str_8bit_isdigit;
824 result.char_isprint = str_8bit_isprint;
825 result.char_iscombiningmark = str_8bit_iscombiningmark;
826 result.char_toupper = str_8bit_toupper;
827 result.char_tolower = str_8bit_tolower;
828 result.length = str_8bit_length;
829 result.length2 = str_8bit_length2;
830 result.length_noncomb = str_8bit_length;
831 result.fix_string = str_8bit_fix_string;
832 result.term_form = str_8bit_term_form;
833 result.fit_to_term = str_8bit_fit_to_term;
834 result.term_trim = str_8bit_term_trim;
835 result.term_width2 = str_8bit_term_width2;
836 result.term_width1 = str_8bit_term_width1;
837 result.term_char_width = str_8bit_term_char_width;
838 result.term_substring = str_8bit_term_substring;
839 result.trunc = str_8bit_trunc;
840 result.offset_to_pos = str_8bit_offset_to_pos;
841 result.column_to_pos = str_8bit_column_to_pos;
842 result.create_search_needle = str_8bit_create_search_needle;
843 result.release_search_needle = str_8bit_release_search_needle;
844 result.search_first = str_8bit_search_first;
845 result.search_last = str_8bit_search_last;
846 result.compare = str_8bit_compare;
847 result.ncompare = str_8bit_ncompare;
848 result.casecmp = str_8bit_casecmp;
849 result.ncasecmp = str_8bit_ncasecmp;
850 result.prefix = str_8bit_prefix;
851 result.caseprefix = str_8bit_caseprefix;
852 result.create_key = str_8bit_create_key;
853 result.create_key_for_filename = str_8bit_create_key;
854 result.key_collate = str_8bit_key_collate;
855 result.release_key = str_8bit_release_key;
856
857 return result;
858 }
859
860