1 /* 8bit strings utilities
2 Copyright (C) 2007 Free Software Foundation, Inc.
7 The file_date routine is mostly from GNU's fileutils package,
8 written by Richard Stallman and David MacKenzie.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
34 /* functions for singlebyte encodings, all characters have width 1
35 * using standard system functions
36 * there are only small differences between functions in strutil8bit.c
40 static const char replch
= '?';
43 * Inlines to equalize 'char' signedness for single 'char' encodings.
45 * isspace((unsigned char)c);
50 #define DECLARE_CTYPE_WRAPPER(func_name) \
51 static inline int char_##func_name(char c) \
53 return func_name((int)(unsigned char)c); \
56 DECLARE_CTYPE_WRAPPER(isalnum
)
57 DECLARE_CTYPE_WRAPPER(isalpha
)
58 DECLARE_CTYPE_WRAPPER(isascii
)
59 DECLARE_CTYPE_WRAPPER(isblank
)
60 DECLARE_CTYPE_WRAPPER(iscntrl
)
61 DECLARE_CTYPE_WRAPPER(isdigit
)
62 DECLARE_CTYPE_WRAPPER(isgraph
)
63 DECLARE_CTYPE_WRAPPER(islower
)
64 DECLARE_CTYPE_WRAPPER(isprint
)
65 DECLARE_CTYPE_WRAPPER(ispunct
)
66 DECLARE_CTYPE_WRAPPER(isspace
)
67 DECLARE_CTYPE_WRAPPER(isupper
)
68 DECLARE_CTYPE_WRAPPER(isxdigit
)
69 DECLARE_CTYPE_WRAPPER(toupper
)
70 DECLARE_CTYPE_WRAPPER(tolower
)
73 str_8bit_insert_replace_char (GString
* buffer
)
75 g_string_append_c (buffer
, replch
);
79 str_8bit_is_valid_string (const char *text
)
86 str_8bit_is_valid_char (const char *ch
, size_t size
)
94 str_8bit_cnext_char (const char **text
)
100 str_8bit_cprev_char (const char **text
)
106 str_8bit_cnext_noncomb_char (const char **text
)
108 if (*text
[0] != '\0')
118 str_8bit_cprev_noncomb_char (const char **text
, const char *begin
)
120 if ((*text
) != begin
)
130 str_8bit_isspace (const char *text
)
132 return char_isspace (text
[0]);
136 str_8bit_ispunct (const char *text
)
138 return char_ispunct (text
[0]);
142 str_8bit_isalnum (const char *text
)
144 return char_isalnum (text
[0]);
148 str_8bit_isdigit (const char *text
)
150 return char_isdigit (text
[0]);
154 str_8bit_isprint (const char *text
)
156 return char_isprint (text
[0]);
160 str_8bit_iscombiningmark (const char *text
)
167 str_8bit_toupper (const char *text
, char **out
, size_t * remain
)
171 (*out
)[0] = char_toupper (text
[0]);
178 str_8bit_tolower (const char *text
, char **out
, size_t * remain
)
182 (*out
)[0] = char_tolower (text
[0]);
189 str_8bit_length (const char *text
)
191 return strlen (text
);
195 str_8bit_length2 (const char *text
, int size
)
197 return (size
>= 0) ? min (strlen (text
), (gsize
)size
) : strlen (text
);
201 str_8bit_conv_gerror_message (GError
*error
, const char *def_msg
)
206 /* glib messages are in UTF-8 charset */
207 conv
= str_crt_conv_from ("UTF-8");
209 if (conv
== INVALID_CONV
)
210 ret
= g_strdup (def_msg
!= NULL
? def_msg
: "");
214 buf
= g_string_new ("");
216 if (str_convert (conv
, error
->message
, buf
) != ESTR_FAILURE
) {
218 g_string_free (buf
, FALSE
);
220 ret
= g_strdup (def_msg
!= NULL
? def_msg
: "");
221 g_string_free (buf
, TRUE
);
224 str_close_conv (conv
);
231 str_8bit_vfs_convert_to (GIConv coder
, const char *string
,
232 int size
, GString
* buffer
)
236 if (coder
== str_cnv_not_convert
)
238 g_string_append_len (buffer
, string
, size
);
239 result
= ESTR_SUCCESS
;
242 result
= str_nconvert (coder
, (char *) string
, size
, buffer
);
249 str_8bit_term_form (const char *text
)
251 static char result
[BUF_MEDIUM
];
258 remain
= sizeof (result
);
259 length
= strlen (text
);
261 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
263 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
271 str_8bit_fit_to_term (const char *text
, int width
, align_crt_t just_mode
)
273 static char result
[BUF_MEDIUM
];
280 length
= strlen (text
);
282 remain
= sizeof (result
);
284 if ((int)length
<= width
)
287 switch (HIDE_FIT (just_mode
))
291 ident
= (width
- length
) / 2;
294 ident
= width
- length
;
298 if ((int)remain
<= ident
)
300 memset (actual
, ' ', ident
);
304 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
306 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
308 if (width
- length
- ident
> 0)
310 if (remain
<= width
- length
- ident
)
312 memset (actual
, ' ', width
- length
- ident
);
313 actual
+= width
- length
- ident
;
314 remain
-= width
- length
- ident
;
319 if (IS_FIT (just_mode
))
321 for (; pos
+ 1 <= (gsize
)width
/ 2 && remain
> 1;
322 actual
++, pos
++, remain
--)
325 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
334 pos
+= length
- width
+ 1;
336 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
338 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
344 switch (HIDE_FIT (just_mode
))
347 ident
= (length
- width
) / 2;
350 ident
= length
- width
;
355 for (; pos
< (gsize
)(ident
+ width
) && remain
> 1;
356 pos
++, actual
++, remain
--)
359 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
370 str_8bit_term_trim (const char *text
, int width
)
372 static char result
[BUF_MEDIUM
];
378 length
= strlen (text
);
380 remain
= sizeof (result
);
382 if (width
< (int)length
)
386 memset (actual
, '.', width
);
392 memset (actual
, '.', 3);
396 pos
+= length
- width
+ 3;
398 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
400 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
406 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
408 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
417 str_8bit_term_width2 (const char *text
, size_t length
)
419 return (length
!= (size_t) (-1))
420 ? min (strlen (text
), length
) : strlen (text
);
424 str_8bit_term_width1 (const char *text
)
426 return str_8bit_term_width2 (text
, (size_t) (-1));
430 str_8bit_term_char_width (const char *text
)
437 str_8bit_msg_term_size (const char *text
, int *lines
, int *columns
)
447 tmp
= g_strdup ((char *)text
);
451 q
= strchr (p
, '\n');
458 width
= str_8bit_term_width1 (p
);
459 if (width
> (*columns
))
472 str_8bit_term_substring (const char *text
, int start
, int width
)
474 static char result
[BUF_MEDIUM
];
481 remain
= sizeof (result
);
482 length
= strlen (text
);
484 if (start
< (int)length
)
487 for (; pos
< length
&& width
> 0 && remain
> 1;
488 pos
++, width
--, actual
++, remain
--)
491 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
495 for (; width
> 0 && remain
> 1; actual
++, remain
--, width
--)
505 str_8bit_trunc (const char *text
, int width
)
507 static char result
[MC_MAXPATHLEN
];
514 remain
= sizeof (result
);
515 length
= strlen (text
);
517 if ((int)length
> width
)
519 for (; pos
+ 1 <= (gsize
)width
/ 2 && remain
> 1; actual
++, pos
++, remain
--)
521 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
530 pos
+= length
- width
+ 1;
532 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
534 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
539 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
541 actual
[0] = char_isprint (text
[pos
]) ? text
[pos
] : '.';
551 str_8bit_offset_to_pos (const char *text
, size_t length
)
558 str_8bit_column_to_pos (const char *text
, size_t pos
)
565 str_8bit_create_search_needle (const char *needle
, int case_sen
)
568 return (char *) needle
;
572 str_8bit_release_search_needle (char *needle
, int case_sen
)
579 str_8bit_search_first (const char *text
, const char *search
, int case_sen
)
586 fold_text
= (case_sen
) ? (char *) text
: g_strdown (g_strdup (text
));
587 fold_search
= (case_sen
) ? (char *) search
: g_strdown (g_strdup (search
));
589 match
= g_strstr_len (fold_text
, -1, fold_search
);
592 offsset
= match
- fold_text
;
593 match
= text
+ offsset
;
599 g_free (fold_search
);
606 str_8bit_search_last (const char *text
, const char *search
, int case_sen
)
613 fold_text
= (case_sen
) ? (char *) text
: g_strdown (g_strdup (text
));
614 fold_search
= (case_sen
) ? (char *) search
: g_strdown (g_strdup (search
));
616 match
= g_strrstr_len (fold_text
, -1, fold_search
);
619 offsset
= match
- fold_text
;
620 match
= text
+ offsset
;
626 g_free (fold_search
);
633 str_8bit_compare (const char *t1
, const char *t2
)
635 return strcmp (t1
, t2
);
639 str_8bit_ncompare (const char *t1
, const char *t2
)
641 return strncmp (t1
, t2
, min (strlen (t1
), strlen (t2
)));
645 str_8bit_casecmp (const char *t1
, const char *t2
)
647 return g_strcasecmp (t1
, t2
);
651 str_8bit_ncasecmp (const char *t1
, const char *t2
)
653 return g_strncasecmp (t1
, t2
, min (strlen (t1
), strlen (t2
)));
657 str_8bit_prefix (const char *text
, const char *prefix
)
660 for (result
= 0; text
[result
] != '\0' && prefix
[result
] != '\0'
661 && text
[result
] == prefix
[result
]; result
++);
666 str_8bit_caseprefix (const char *text
, const char *prefix
)
669 for (result
= 0; text
[result
] != '\0' && prefix
[result
] != '\0'
670 && char_toupper (text
[result
]) == char_toupper (prefix
[result
]); result
++);
677 str_8bit_fix_string (char *text
)
683 str_8bit_create_key (const char *text
, int case_sen
)
685 return (case_sen
) ? (char *) text
: g_strdown (g_strdup (text
));
689 str_8bit_key_collate (const char *t1
, const char *t2
, int case_sen
)
692 return strcmp (t1
, t2
);
694 return strcoll (t1
, t2
);
698 str_8bit_release_key (char *key
, int case_sen
)
707 struct str_class result
;
709 result
.conv_gerror_message
= str_8bit_conv_gerror_message
;
710 result
.vfs_convert_to
= str_8bit_vfs_convert_to
;
711 result
.insert_replace_char
= str_8bit_insert_replace_char
;
712 result
.is_valid_string
= str_8bit_is_valid_string
;
713 result
.is_valid_char
= str_8bit_is_valid_char
;
714 result
.cnext_char
= str_8bit_cnext_char
;
715 result
.cprev_char
= str_8bit_cprev_char
;
716 result
.cnext_char_safe
= str_8bit_cnext_char
;
717 result
.cprev_char_safe
= str_8bit_cprev_char
;
718 result
.cnext_noncomb_char
= str_8bit_cnext_noncomb_char
;
719 result
.cprev_noncomb_char
= str_8bit_cprev_noncomb_char
;
720 result
.isspace
= str_8bit_isspace
;
721 result
.ispunct
= str_8bit_ispunct
;
722 result
.isalnum
= str_8bit_isalnum
;
723 result
.isdigit
= str_8bit_isdigit
;
724 result
.isprint
= str_8bit_isprint
;
725 result
.iscombiningmark
= str_8bit_iscombiningmark
;
726 result
.toupper
= str_8bit_toupper
;
727 result
.tolower
= str_8bit_tolower
;
728 result
.length
= str_8bit_length
;
729 result
.length2
= str_8bit_length2
;
730 result
.length_noncomb
= str_8bit_length
;
731 result
.fix_string
= str_8bit_fix_string
;
732 result
.term_form
= str_8bit_term_form
;
733 result
.fit_to_term
= str_8bit_fit_to_term
;
734 result
.term_trim
= str_8bit_term_trim
;
735 result
.term_width2
= str_8bit_term_width2
;
736 result
.term_width1
= str_8bit_term_width1
;
737 result
.term_char_width
= str_8bit_term_char_width
;
738 result
.msg_term_size
= str_8bit_msg_term_size
;
739 result
.term_substring
= str_8bit_term_substring
;
740 result
.trunc
= str_8bit_trunc
;
741 result
.offset_to_pos
= str_8bit_offset_to_pos
;
742 result
.column_to_pos
= str_8bit_column_to_pos
;
743 result
.create_search_needle
= str_8bit_create_search_needle
;
744 result
.release_search_needle
= str_8bit_release_search_needle
;
745 result
.search_first
= str_8bit_search_first
;
746 result
.search_last
= str_8bit_search_last
;
747 result
.compare
= str_8bit_compare
;
748 result
.ncompare
= str_8bit_ncompare
;
749 result
.casecmp
= str_8bit_casecmp
;
750 result
.ncasecmp
= str_8bit_ncasecmp
;
751 result
.prefix
= str_8bit_prefix
;
752 result
.caseprefix
= str_8bit_caseprefix
;
753 result
.create_key
= str_8bit_create_key
;
754 result
.create_key_for_filename
= str_8bit_create_key
;
755 result
.key_collate
= str_8bit_key_collate
;
756 result
.release_key
= str_8bit_release_key
;