2 ASCII strings utilities
4 Copyright (C) 2007, 2011
5 The Free Software Foundation, Inc.
10 The file_date routine is mostly from GNU's fileutils package,
11 written by Richard Stallman and David MacKenzie.
13 This file is part of the Midnight Commander.
15 The Midnight Commander is free software: you can redistribute it
16 and/or modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation, either version 3 of the License,
18 or (at your option) any later version.
20 The Midnight Commander is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
34 #include "lib/global.h"
35 #include "lib/strutil.h"
37 /* using g_ascii function from glib
38 * on terminal are showed only ascii characters (lower then 0x80)
41 static const char replch
= '?';
44 str_ascii_insert_replace_char (GString
* buffer
)
46 g_string_append_c (buffer
, replch
);
50 str_ascii_is_valid_string (const char *text
)
57 str_ascii_is_valid_char (const char *ch
, size_t size
)
65 str_ascii_cnext_char (const char **text
)
71 str_ascii_cprev_char (const char **text
)
77 str_ascii_cnext_noncomb_char (const char **text
)
89 str_ascii_cprev_noncomb_char (const char **text
, const char *begin
)
101 str_ascii_isspace (const char *text
)
103 return g_ascii_isspace ((gchar
) text
[0]);
107 str_ascii_ispunct (const char *text
)
109 return g_ascii_ispunct ((gchar
) text
[0]);
113 str_ascii_isalnum (const char *text
)
115 return g_ascii_isalnum ((gchar
) text
[0]);
119 str_ascii_isdigit (const char *text
)
121 return g_ascii_isdigit ((gchar
) text
[0]);
125 str_ascii_isprint (const char *text
)
127 return g_ascii_isprint ((gchar
) text
[0]);
131 str_ascii_iscombiningmark (const char *text
)
138 str_ascii_toupper (const char *text
, char **out
, size_t * remain
)
142 (*out
)[0] = (char) g_ascii_toupper ((gchar
) text
[0]);
149 str_ascii_tolower (const char *text
, char **out
, size_t * remain
)
153 (*out
)[0] = (char) g_ascii_tolower ((gchar
) text
[0]);
160 str_ascii_length (const char *text
)
162 return strlen (text
);
166 str_ascii_length2 (const char *text
, int size
)
168 return (size
>= 0) ? min (strlen (text
), (gsize
) size
) : strlen (text
);
172 str_ascii_conv_gerror_message (GError
* error
, const char *def_msg
)
174 /* the same as str_utf8_conv_gerror_message() */
175 if ((error
!= NULL
) && (error
->message
!= NULL
))
176 return g_strdup (error
->message
);
178 return g_strdup (def_msg
!= NULL
? def_msg
: "");
182 str_ascii_vfs_convert_to (GIConv coder
, const char *string
, int size
, GString
* buffer
)
185 g_string_append_len (buffer
, string
, size
);
191 str_ascii_term_form (const char *text
)
193 static char result
[BUF_MEDIUM
];
200 remain
= sizeof (result
);
201 length
= strlen (text
);
203 /* go throw all characters and check, if they are ascii and printable */
204 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
206 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
207 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
215 str_ascii_fit_to_term (const char *text
, int width
, align_crt_t just_mode
)
217 static char result
[BUF_MEDIUM
];
224 length
= strlen (text
);
226 remain
= sizeof (result
);
228 if ((int) length
<= width
)
231 switch (HIDE_FIT (just_mode
))
235 ident
= (width
- length
) / 2;
238 ident
= width
- length
;
242 /* add space before text */
243 if ((int) remain
<= ident
)
245 memset (actual
, ' ', ident
);
249 /* copy all characters */
250 for (; pos
< (gsize
) length
&& remain
> 1; pos
++, actual
++, remain
--)
252 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
253 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
256 /* add space after text */
257 if (width
- length
- ident
> 0)
259 if (remain
<= width
- length
- ident
)
261 memset (actual
, ' ', width
- length
- ident
);
262 actual
+= width
- length
- ident
;
263 remain
-= width
- length
- ident
;
268 if (IS_FIT (just_mode
))
270 /* copy prefix of text, that is not wider than width / 2 */
271 for (; pos
+ 1 <= (gsize
) width
/ 2 && remain
> 1; actual
++, pos
++, remain
--)
273 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
274 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
283 pos
+= length
- width
+ 1;
285 /* copy suffix of text */
286 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
288 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
289 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
295 switch (HIDE_FIT (just_mode
))
298 ident
= (length
- width
) / 2;
301 ident
= length
- width
;
305 /* copy substring text, substring start from ident and take width
306 * characters from text */
308 for (; pos
< (gsize
) (ident
+ width
) && remain
> 1; pos
++, actual
++, remain
--)
310 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
311 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
322 str_ascii_term_trim (const char *text
, int width
)
324 static char result
[BUF_MEDIUM
];
330 length
= strlen (text
);
332 remain
= sizeof (result
);
337 if (width
< (int) length
)
341 memset (actual
, '.', width
);
347 memset (actual
, '.', 3);
351 pos
+= length
- width
+ 3;
353 /* copy suffix of text */
354 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
356 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
357 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
363 /* copy all characters */
364 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
366 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
367 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
377 str_ascii_term_width2 (const char *text
, size_t length
)
379 return (length
!= (size_t) (-1)) ? min (strlen (text
), length
) : strlen (text
);
383 str_ascii_term_width1 (const char *text
)
385 return str_ascii_term_width2 (text
, (size_t) (-1));
389 str_ascii_term_char_width (const char *text
)
396 str_ascii_term_substring (const char *text
, int start
, int width
)
398 static char result
[BUF_MEDIUM
];
405 remain
= sizeof (result
);
406 length
= strlen (text
);
408 if (start
< (int) length
)
411 /* copy at most width characters from text from start */
412 for (; pos
< length
&& width
> 0 && remain
> 1; pos
++, width
--, actual
++, remain
--)
415 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
416 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
420 /* if text is shorter then width, add space to the end */
421 for (; width
> 0 && remain
> 1; actual
++, remain
--, width
--)
431 str_ascii_trunc (const char *text
, int width
)
433 static char result
[MC_MAXPATHLEN
];
440 remain
= sizeof (result
);
441 length
= strlen (text
);
443 if ((int) length
> width
)
445 /* copy prefix of text */
446 for (; pos
+ 1 <= (gsize
) width
/ 2 && remain
> 1; actual
++, pos
++, remain
--)
448 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
449 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
458 pos
+= length
- width
+ 1;
460 /* copy suffix of text */
461 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
463 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
464 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
469 /* copy all characters */
470 for (; pos
< length
&& remain
> 1; pos
++, actual
++, remain
--)
472 actual
[0] = isascii ((unsigned char) text
[pos
]) ? text
[pos
] : '?';
473 actual
[0] = g_ascii_isprint ((gchar
) actual
[0]) ? actual
[0] : '.';
483 str_ascii_offset_to_pos (const char *text
, size_t length
)
490 str_ascii_column_to_pos (const char *text
, size_t pos
)
497 str_ascii_create_search_needle (const char *needle
, int case_sen
)
500 return (char *) needle
;
504 str_ascii_release_search_needle (char *needle
, int case_sen
)
512 str_ascii_search_first (const char *text
, const char *search
, int case_sen
)
519 fold_text
= (case_sen
) ? (char *) text
: g_ascii_strdown (text
, -1);
520 fold_search
= (case_sen
) ? (char *) search
: g_ascii_strdown (search
, -1);
522 match
= g_strstr_len (fold_text
, -1, fold_search
);
525 offset
= match
- fold_text
;
526 match
= text
+ offset
;
532 g_free (fold_search
);
539 str_ascii_search_last (const char *text
, const char *search
, int case_sen
)
546 fold_text
= (case_sen
) ? (char *) text
: g_ascii_strdown (text
, -1);
547 fold_search
= (case_sen
) ? (char *) search
: g_ascii_strdown (search
, -1);
549 match
= g_strrstr_len (fold_text
, -1, fold_search
);
552 offset
= match
- fold_text
;
553 match
= text
+ offset
;
559 g_free (fold_search
);
566 str_ascii_compare (const char *t1
, const char *t2
)
568 return strcmp (t1
, t2
);
572 str_ascii_ncompare (const char *t1
, const char *t2
)
574 return strncmp (t1
, t2
, min (strlen (t1
), strlen (t2
)));
578 str_ascii_casecmp (const char *t1
, const char *t2
)
580 return g_ascii_strcasecmp (t1
, t2
);
584 str_ascii_ncasecmp (const char *t1
, const char *t2
)
586 return g_ascii_strncasecmp (t1
, t2
, min (strlen (t1
), strlen (t2
)));
590 str_ascii_fix_string (char *text
)
592 for (; text
[0] != '\0'; text
++)
594 text
[0] = ((unsigned char) text
[0] < 128) ? text
[0] : '?';
599 str_ascii_create_key (const char *text
, int case_sen
)
602 return (char *) text
;
606 str_ascii_key_collate (const char *t1
, const char *t2
, int case_sen
)
608 return (case_sen
) ? strcmp (t1
, t2
) : g_ascii_strcasecmp (t1
, t2
);
612 str_ascii_release_key (char *key
, int case_sen
)
619 str_ascii_prefix (const char *text
, const char *prefix
)
622 for (result
= 0; text
[result
] != '\0' && prefix
[result
] != '\0'
623 && text
[result
] == prefix
[result
]; result
++);
628 str_ascii_caseprefix (const char *text
, const char *prefix
)
631 for (result
= 0; text
[result
] != '\0' && prefix
[result
] != '\0'
632 && g_ascii_toupper (text
[result
]) == g_ascii_toupper (prefix
[result
]); result
++);
638 str_ascii_init (void)
640 struct str_class result
;
642 result
.conv_gerror_message
= str_ascii_conv_gerror_message
;
643 result
.vfs_convert_to
= str_ascii_vfs_convert_to
;
644 result
.insert_replace_char
= str_ascii_insert_replace_char
;
645 result
.is_valid_string
= str_ascii_is_valid_string
;
646 result
.is_valid_char
= str_ascii_is_valid_char
;
647 result
.cnext_char
= str_ascii_cnext_char
;
648 result
.cprev_char
= str_ascii_cprev_char
;
649 result
.cnext_char_safe
= str_ascii_cnext_char
;
650 result
.cprev_char_safe
= str_ascii_cprev_char
;
651 result
.cnext_noncomb_char
= str_ascii_cnext_noncomb_char
;
652 result
.cprev_noncomb_char
= str_ascii_cprev_noncomb_char
;
653 result
.isspace
= str_ascii_isspace
;
654 result
.ispunct
= str_ascii_ispunct
;
655 result
.isalnum
= str_ascii_isalnum
;
656 result
.isdigit
= str_ascii_isdigit
;
657 result
.isprint
= str_ascii_isprint
;
658 result
.iscombiningmark
= str_ascii_iscombiningmark
;
659 result
.toupper
= str_ascii_toupper
;
660 result
.tolower
= str_ascii_tolower
;
661 result
.length
= str_ascii_length
;
662 result
.length2
= str_ascii_length2
;
663 result
.length_noncomb
= str_ascii_length
;
664 result
.fix_string
= str_ascii_fix_string
;
665 result
.term_form
= str_ascii_term_form
;
666 result
.fit_to_term
= str_ascii_fit_to_term
;
667 result
.term_trim
= str_ascii_term_trim
;
668 result
.term_width2
= str_ascii_term_width2
;
669 result
.term_width1
= str_ascii_term_width1
;
670 result
.term_char_width
= str_ascii_term_char_width
;
671 result
.term_substring
= str_ascii_term_substring
;
672 result
.trunc
= str_ascii_trunc
;
673 result
.offset_to_pos
= str_ascii_offset_to_pos
;
674 result
.column_to_pos
= str_ascii_column_to_pos
;
675 result
.create_search_needle
= str_ascii_create_search_needle
;
676 result
.release_search_needle
= str_ascii_release_search_needle
;
677 result
.search_first
= str_ascii_search_first
;
678 result
.search_last
= str_ascii_search_last
;
679 result
.compare
= str_ascii_compare
;
680 result
.ncompare
= str_ascii_ncompare
;
681 result
.casecmp
= str_ascii_casecmp
;
682 result
.ncasecmp
= str_ascii_ncasecmp
;
683 result
.prefix
= str_ascii_prefix
;
684 result
.caseprefix
= str_ascii_caseprefix
;
685 result
.create_key
= str_ascii_create_key
;
686 result
.create_key_for_filename
= str_ascii_create_key
;
687 result
.key_collate
= str_ascii_key_collate
;
688 result
.release_key
= str_ascii_release_key
;