2 ASCII strings utilities
4 Copyright (C) 2007-2017
5 Free Software Foundation, Inc.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 #include "lib/global.h"
32 #include "lib/strutil.h"
34 /* using g_ascii function from glib
35 * on terminal are showed only ascii characters (lower than 0x80)
38 /*** global variables ****************************************************************************/
40 /*** file scope macro definitions ****************************************************************/
42 /*** file scope type declarations ****************************************************************/
44 /*** file scope variables ************************************************************************/
46 static const char replch
= '?';
48 /* --------------------------------------------------------------------------------------------- */
49 /*** file scope functions ************************************************************************/
50 /* --------------------------------------------------------------------------------------------- */
53 str_ascii_insert_replace_char (GString
* buffer
)
55 g_string_append_c (buffer
, replch
);
58 /* --------------------------------------------------------------------------------------------- */
61 str_ascii_is_valid_string (const char *text
)
67 /* --------------------------------------------------------------------------------------------- */
70 str_ascii_is_valid_char (const char *ch
, size_t size
)
77 /* --------------------------------------------------------------------------------------------- */
80 str_ascii_cnext_char (const char **text
)
85 /* --------------------------------------------------------------------------------------------- */
88 str_ascii_cprev_char (const char **text
)
93 /* --------------------------------------------------------------------------------------------- */
96 str_ascii_cnext_noncomb_char (const char **text
)
105 /* --------------------------------------------------------------------------------------------- */
108 str_ascii_cprev_noncomb_char (const char **text
, const char *begin
)
110 if ((*text
) == begin
)
117 /* --------------------------------------------------------------------------------------------- */
120 str_ascii_isspace (const char *text
)
122 return g_ascii_isspace ((gchar
) text
[0]);
125 /* --------------------------------------------------------------------------------------------- */
128 str_ascii_ispunct (const char *text
)
130 return g_ascii_ispunct ((gchar
) text
[0]);
133 /* --------------------------------------------------------------------------------------------- */
136 str_ascii_isalnum (const char *text
)
138 return g_ascii_isalnum ((gchar
) text
[0]);
141 /* --------------------------------------------------------------------------------------------- */
144 str_ascii_isdigit (const char *text
)
146 return g_ascii_isdigit ((gchar
) text
[0]);
149 /* --------------------------------------------------------------------------------------------- */
152 str_ascii_isprint (const char *text
)
154 return g_ascii_isprint ((gchar
) text
[0]);
157 /* --------------------------------------------------------------------------------------------- */
160 str_ascii_iscombiningmark (const char *text
)
166 /* --------------------------------------------------------------------------------------------- */
169 str_ascii_toupper (const char *text
, char **out
, size_t * remain
)
174 (*out
)[0] = (char) g_ascii_toupper ((gchar
) text
[0]);
180 /* --------------------------------------------------------------------------------------------- */
183 str_ascii_tolower (const char *text
, char **out
, size_t * remain
)
188 (*out
)[0] = (char) g_ascii_tolower ((gchar
) text
[0]);
194 /* --------------------------------------------------------------------------------------------- */
197 str_ascii_length (const char *text
)
199 return strlen (text
);
202 /* --------------------------------------------------------------------------------------------- */
205 str_ascii_length2 (const char *text
, int size
)
207 return (size
>= 0) ? MIN (strlen (text
), (gsize
) size
) : strlen (text
);
210 /* --------------------------------------------------------------------------------------------- */
213 str_ascii_conv_gerror_message (GError
* mcerror
, const char *def_msg
)
215 /* the same as str_utf8_conv_gerror_message() */
217 return g_strdup (mcerror
->message
);
219 return g_strdup (def_msg
!= NULL
? def_msg
: "");
222 /* --------------------------------------------------------------------------------------------- */
225 str_ascii_vfs_convert_to (GIConv coder
, const char *string
, int size
, GString
* buffer
)
228 g_string_append_len (buffer
, string
, size
);
232 /* --------------------------------------------------------------------------------------------- */
235 str_ascii_term_form (const char *text
)
237 static char result
[BUF_MEDIUM
];
244 remain
= sizeof (result
);
245 length
= strlen (text
);
247 /* go throw all characters and check, if they are ascii and printable */
248 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
250 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
251 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
258 /* --------------------------------------------------------------------------------------------- */
261 str_ascii_fit_to_term (const char *text
, int width
, align_crt_t just_mode
)
263 static char result
[BUF_MEDIUM
];
270 length
= strlen (text
);
272 remain
= sizeof (result
);
274 if ((int) length
<= width
)
276 switch (HIDE_FIT (just_mode
))
280 ident
= (width
- length
) / 2;
283 ident
= width
- length
;
289 /* add space before text */
290 if ((int) remain
<= ident
)
292 memset (actual
, ' ', ident
);
296 /* copy all characters */
297 for (; pos
< (gsize
) length
&& remain
> 1; pos
++, actual
++, remain
--)
299 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
300 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
303 /* add space after text */
304 if (width
- length
- ident
> 0)
306 if (remain
<= width
- length
- ident
)
308 memset (actual
, ' ', width
- length
- ident
);
309 actual
+= width
- length
- ident
;
312 else if (IS_FIT (just_mode
))
314 /* copy prefix of text, that is not wider than width / 2 */
315 for (; pos
+ 1 <= (gsize
) width
/ 2 && remain
> 1; actual
++, pos
++, remain
--)
317 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
318 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
327 pos
+= length
- width
+ 1;
329 /* copy suffix of text */
330 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
332 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
333 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
338 switch (HIDE_FIT (just_mode
))
341 ident
= (length
- width
) / 2;
344 ident
= length
- width
;
350 /* copy substring text, substring start from ident and take width
351 * characters from text */
353 for (; pos
< (gsize
) (ident
+ width
) && remain
> 1; pos
++, actual
++, remain
--)
355 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
356 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
362 if (actual
>= result
+ sizeof (result
))
363 actual
= result
+ sizeof (result
) - 1;
368 /* --------------------------------------------------------------------------------------------- */
371 str_ascii_term_trim (const char *text
, int width
)
373 static char result
[BUF_MEDIUM
];
378 length
= strlen (text
);
380 remain
= sizeof (result
);
386 if (width
>= (int) length
)
388 /* copy all characters */
389 for (pos
= 0; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
391 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
392 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
397 memset (actual
, '.', width
);
402 memset (actual
, '.', 3);
406 /* copy suffix of text */
407 for (pos
= length
- width
+ 3; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
409 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
410 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
419 /* --------------------------------------------------------------------------------------------- */
422 str_ascii_term_width2 (const char *text
, size_t length
)
424 return (length
!= (size_t) (-1)) ? MIN (strlen (text
), length
) : strlen (text
);
427 /* --------------------------------------------------------------------------------------------- */
430 str_ascii_term_width1 (const char *text
)
432 return str_ascii_term_width2 (text
, (size_t) (-1));
435 /* --------------------------------------------------------------------------------------------- */
438 str_ascii_term_char_width (const char *text
)
444 /* --------------------------------------------------------------------------------------------- */
447 str_ascii_term_substring (const char *text
, int start
, int width
)
449 static char result
[BUF_MEDIUM
];
455 remain
= sizeof (result
);
456 length
= strlen (text
);
458 if (start
< (int) length
)
462 /* copy at most width characters from text from start */
463 for (pos
= start
; pos
< length
&& width
> 0 && remain
> 1;
464 pos
++, width
--, actual
++, remain
--)
466 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
467 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
471 /* if text is shorter then width, add space to the end */
472 for (; width
> 0 && remain
> 1; actual
++, remain
--, width
--)
479 /* --------------------------------------------------------------------------------------------- */
482 str_ascii_trunc (const char *text
, int width
)
484 static char result
[MC_MAXPATHLEN
];
491 remain
= sizeof (result
);
492 length
= strlen (text
);
494 if ((int) length
> width
)
496 /* copy prefix of text */
497 for (; pos
+ 1 <= (gsize
) width
/ 2 && remain
> 1; actual
++, pos
++, remain
--)
499 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
500 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
509 pos
+= length
- width
+ 1;
511 /* copy suffix of text */
512 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
514 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
515 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
520 /* copy all characters */
521 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
523 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
524 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
533 /* --------------------------------------------------------------------------------------------- */
536 str_ascii_offset_to_pos (const char *text
, size_t length
)
542 /* --------------------------------------------------------------------------------------------- */
545 str_ascii_column_to_pos (const char *text
, size_t pos
)
551 /* --------------------------------------------------------------------------------------------- */
554 str_ascii_create_search_needle (const char *needle
, int case_sen
)
557 return (char *) needle
;
560 /* --------------------------------------------------------------------------------------------- */
563 str_ascii_release_search_needle (char *needle
, int case_sen
)
570 /* --------------------------------------------------------------------------------------------- */
573 str_ascii_search_first (const char *text
, const char *search
, int case_sen
)
579 fold_text
= (case_sen
) ? (char *) text
: g_ascii_strdown (text
, -1);
580 fold_search
= (case_sen
) ? (char *) search
: g_ascii_strdown (search
, -1);
582 match
= g_strstr_len (fold_text
, -1, fold_search
);
587 offset
= match
- fold_text
;
588 match
= text
+ offset
;
594 g_free (fold_search
);
600 /* --------------------------------------------------------------------------------------------- */
603 str_ascii_search_last (const char *text
, const char *search
, int case_sen
)
609 fold_text
= (case_sen
) ? (char *) text
: g_ascii_strdown (text
, -1);
610 fold_search
= (case_sen
) ? (char *) search
: g_ascii_strdown (search
, -1);
612 match
= g_strrstr_len (fold_text
, -1, fold_search
);
617 offset
= match
- fold_text
;
618 match
= text
+ offset
;
624 g_free (fold_search
);
630 /* --------------------------------------------------------------------------------------------- */
633 str_ascii_compare (const char *t1
, const char *t2
)
635 return strcmp (t1
, t2
);
638 /* --------------------------------------------------------------------------------------------- */
641 str_ascii_ncompare (const char *t1
, const char *t2
)
643 return strncmp (t1
, t2
, MIN (strlen (t1
), strlen (t2
)));
646 /* --------------------------------------------------------------------------------------------- */
649 str_ascii_casecmp (const char *t1
, const char *t2
)
651 return g_ascii_strcasecmp (t1
, t2
);
654 /* --------------------------------------------------------------------------------------------- */
657 str_ascii_ncasecmp (const char *t1
, const char *t2
)
659 return g_ascii_strncasecmp (t1
, t2
, MIN (strlen (t1
), strlen (t2
)));
662 /* --------------------------------------------------------------------------------------------- */
665 str_ascii_fix_string (char *text
)
667 for (; text
[0] != '\0'; text
++)
668 text
[0] = ((unsigned char) text
[0] < 128) ? text
[0] : '?';
671 /* --------------------------------------------------------------------------------------------- */
674 str_ascii_create_key (const char *text
, int case_sen
)
677 return (char *) text
;
680 /* --------------------------------------------------------------------------------------------- */
683 str_ascii_key_collate (const char *t1
, const char *t2
, int case_sen
)
685 return (case_sen
) ? strcmp (t1
, t2
) : g_ascii_strcasecmp (t1
, t2
);
688 /* --------------------------------------------------------------------------------------------- */
691 str_ascii_release_key (char *key
, int case_sen
)
697 /* --------------------------------------------------------------------------------------------- */
700 str_ascii_prefix (const char *text
, const char *prefix
)
704 for (result
= 0; text
[result
] != '\0' && prefix
[result
] != '\0'
705 && text
[result
] == prefix
[result
]; result
++);
710 /* --------------------------------------------------------------------------------------------- */
713 str_ascii_caseprefix (const char *text
, const char *prefix
)
717 for (result
= 0; text
[result
] != '\0' && prefix
[result
] != '\0'
718 && g_ascii_toupper (text
[result
]) == g_ascii_toupper (prefix
[result
]); result
++);
723 /* --------------------------------------------------------------------------------------------- */
724 /*** public functions ****************************************************************************/
725 /* --------------------------------------------------------------------------------------------- */
728 str_ascii_init (void)
730 struct str_class result
;
732 result
.conv_gerror_message
= str_ascii_conv_gerror_message
;
733 result
.vfs_convert_to
= str_ascii_vfs_convert_to
;
734 result
.insert_replace_char
= str_ascii_insert_replace_char
;
735 result
.is_valid_string
= str_ascii_is_valid_string
;
736 result
.is_valid_char
= str_ascii_is_valid_char
;
737 result
.cnext_char
= str_ascii_cnext_char
;
738 result
.cprev_char
= str_ascii_cprev_char
;
739 result
.cnext_char_safe
= str_ascii_cnext_char
;
740 result
.cprev_char_safe
= str_ascii_cprev_char
;
741 result
.cnext_noncomb_char
= str_ascii_cnext_noncomb_char
;
742 result
.cprev_noncomb_char
= str_ascii_cprev_noncomb_char
;
743 result
.char_isspace
= str_ascii_isspace
;
744 result
.char_ispunct
= str_ascii_ispunct
;
745 result
.char_isalnum
= str_ascii_isalnum
;
746 result
.char_isdigit
= str_ascii_isdigit
;
747 result
.char_isprint
= str_ascii_isprint
;
748 result
.char_iscombiningmark
= str_ascii_iscombiningmark
;
749 result
.char_toupper
= str_ascii_toupper
;
750 result
.char_tolower
= str_ascii_tolower
;
751 result
.length
= str_ascii_length
;
752 result
.length2
= str_ascii_length2
;
753 result
.length_noncomb
= str_ascii_length
;
754 result
.fix_string
= str_ascii_fix_string
;
755 result
.term_form
= str_ascii_term_form
;
756 result
.fit_to_term
= str_ascii_fit_to_term
;
757 result
.term_trim
= str_ascii_term_trim
;
758 result
.term_width2
= str_ascii_term_width2
;
759 result
.term_width1
= str_ascii_term_width1
;
760 result
.term_char_width
= str_ascii_term_char_width
;
761 result
.term_substring
= str_ascii_term_substring
;
762 result
.trunc
= str_ascii_trunc
;
763 result
.offset_to_pos
= str_ascii_offset_to_pos
;
764 result
.column_to_pos
= str_ascii_column_to_pos
;
765 result
.create_search_needle
= str_ascii_create_search_needle
;
766 result
.release_search_needle
= str_ascii_release_search_needle
;
767 result
.search_first
= str_ascii_search_first
;
768 result
.search_last
= str_ascii_search_last
;
769 result
.compare
= str_ascii_compare
;
770 result
.ncompare
= str_ascii_ncompare
;
771 result
.casecmp
= str_ascii_casecmp
;
772 result
.ncasecmp
= str_ascii_ncasecmp
;
773 result
.prefix
= str_ascii_prefix
;
774 result
.caseprefix
= str_ascii_caseprefix
;
775 result
.create_key
= str_ascii_create_key
;
776 result
.create_key_for_filename
= str_ascii_create_key
;
777 result
.key_collate
= str_ascii_key_collate
;
778 result
.release_key
= str_ascii_release_key
;
783 /* --------------------------------------------------------------------------------------------- */