2 parted - a frontend to libparted
3 Copyright (C) 1999-2001, 2007, 2009-2011 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <parted/debug.h>
40 #endif /* !ENABLE_NLS */
44 #define MIN(a,b) ( (a<b)? a : b )
47 wchar_strlen (const wchar_t* str)
57 wchar_strchr (const wchar_t* str, char ch)
60 return wcschr (str, ch);
62 return strchr (str, ch);
67 wchar_strcasecmp (const wchar_t* a, const wchar_t* b)
70 return wcscasecmp (a, b);
72 return strcasecmp (a, b);
77 wchar_strncasecmp (const wchar_t* a, const wchar_t* b, size_t n)
80 return wcsncasecmp (a, b, n);
82 return strncasecmp (a, b, n);
87 wchar_strdup (const wchar_t* str)
96 /* converts a string from the encoding in the gettext catalogues to wide
97 * character strings (of type wchar_t*).
101 gettext_to_wchar (const char* str)
108 count = strlen (str) + 1;
109 result = malloc (count * sizeof (wchar_t));
113 memset(&ps, 0, sizeof (ps));
114 status = mbsrtowcs(result, &str, count, &ps);
115 if (status == (size_t) -1)
118 result = xrealloc (result, (wcslen (result) + 1) * sizeof (wchar_t));
122 fprintf (stderr, "Error during translation: %s\n", strerror (errno));
126 #else /* ENABLE_NLS */
129 gettext_to_wchar (const char* str)
131 return xstrdup (str);
134 #endif /* !ENABLE_NLS */
139 wchar_to_str (const wchar_t* str, size_t count)
147 if (count == 0 || wcslen(str) < count)
148 count = wcslen (str);
150 out_buf = result = malloc ((count + 1) * MB_LEN_MAX);
154 memset(&ps, 0, sizeof(ps));
156 for (i = 0; i < count; i++) {
157 status = wcrtomb (out_buf, str[i], &ps);
158 if (status == (size_t) -1)
163 status = wcrtomb (out_buf, 0, &ps);
164 if (status == (size_t) -1)
167 result = realloc (result, strlen (result) + 1);
171 fprintf (stderr, "Error during translation: %s\n", strerror (errno));
175 #else /* ENABLE_NLS */
178 wchar_to_str (const wchar_t* str, size_t count)
182 result = xstrdup (str);
183 if (count && count < strlen (result))
188 #endif /* !ENABLE_NLS */
191 print_wchar (const wchar_t* str, size_t count, FILE *fp)
193 char* tmp = wchar_to_str (str, count);
194 fprintf (fp, "%s", tmp);
203 list = xmalloc (sizeof (StrList));
210 str_list_destroy (StrList* list)
213 str_list_destroy (list->next);
214 str_list_destroy_node (list);
219 str_list_destroy_node (StrList* list)
221 void *p = (char *) (list->str); /* discard const */
227 str_list_duplicate_node (const StrList* node)
229 StrList* result = str_list_alloc ();
230 result->str = wchar_strdup (node->str);
235 str_list_duplicate (const StrList* list)
238 return str_list_join (str_list_duplicate_node (list),
239 str_list_duplicate (list->next));
245 str_list_join (StrList* a, StrList* b)
249 for (walk = a; walk && walk->next; walk = walk->next);
260 _str_list_append (StrList* list, const wchar_t* str)
265 for (walk = list; walk->next; walk = walk->next);
266 walk->next = str_list_alloc ();
269 walk = list = str_list_alloc ();
277 str_list_append (StrList* list, const char* str)
279 return _str_list_append (list, gettext_to_wchar (str));
283 str_list_append_unique (StrList* list, const char* str)
286 wchar_t* new_str = gettext_to_wchar (str);
288 for (walk=list; walk; walk=walk->next) {
290 if (wchar_strcasecmp (new_str, walk->str) == 0) {
297 return _str_list_append (list, new_str);
301 str_list_insert (StrList* list, const char* str)
303 return str_list_join (str_list_create (str, NULL), list);
307 str_list_create (const char* first, ...)
313 list = str_list_append (NULL, first);
316 va_start (args, first);
317 while ( (str = va_arg (args, char*)) )
318 str_list_append (list, str);
326 str_list_create_unique (const char* first, ...)
332 list = str_list_append (NULL, first);
335 va_start (args, first);
336 while ( (str = va_arg (args, char*)) )
337 str_list_append_unique (list, str);
345 str_list_convert_node (const StrList* list)
347 return wchar_to_str (list->str, 0);
351 str_list_convert (const StrList* list)
356 char* str = xstrdup ("");
358 for (walk = list; walk; walk = walk->next) {
360 char* tmp = wchar_to_str (walk->str, 0);
362 length += strlen (tmp);
364 str = realloc (str, length);
365 strcpy (str + pos, tmp);
376 str_list_print (const StrList* list, FILE *fp)
380 for (walk=list; walk; walk=walk->next) {
382 print_wchar (walk->str, 0, fp);
387 str_search (const wchar_t* str, int n, wchar_t c)
398 /* Japanese don't leave spaces between words, so ALL Japanese characters
399 * are treated as delimiters. Note: since the translations should already
400 * be properly formatted (eg: spaces after commas), there should be no
401 * need to include them. Best not to avoid side effects, like 3.
403 * FIXME: how do we exclude "." and "(" ?
404 * FIXME: glibc doesn't like umlaute. i.e. \"o (TeX notation), which should
409 is_break_point (wchar_t c)
412 return !iswalnum (c) && !iswpunct (c);
414 return !isalnum (c) && !ispunct (c);
418 /* NOTE: this should not return '\n' as a space, because explicit '\n' may
419 * be placed inside strings.
425 return c == (wchar_t) btowc(' ');
432 str_list_print_wrap (const StrList* list, int line_length, int offset,
433 int indent, FILE *fp)
444 PED_ASSERT (line_length - indent > 10);
446 line_left = line_length - offset;
448 for (walk=list; walk; walk=walk->next) {
452 str_len = wchar_strlen (str);
454 while (line_left < str_len || wchar_strchr (str, '\n')) {
457 cut_left = MIN (line_left - 1, str_len - 1);
459 /* we can have a space "over", but not a comma */
460 if (cut_left < str_len
461 && is_space (str [cut_left + 1]))
464 while (cut_left && !is_break_point (str [cut_left]))
466 while (cut_left && is_space (str [cut_left]))
469 /* str [cut_left] is either the end of a word, or a
470 * Japanese character, or the start of a blank line.
473 search_result = str_search (str, cut_left + 1, '\n');
474 if (search_result != -1) {
475 cut_left = search_result - 1;
479 for (cut_right = cut_left + (line_break ? 2 : 1);
480 cut_right < str_len && is_space (str [cut_right]);
484 print_wchar (str, cut_left + 1, fp);
487 str_len -= cut_right;
488 line_left = line_length - indent;
490 if (walk->next || *str)
491 fprintf (fp, "\n%*s", indent, "");
496 print_wchar (str, 0, fp);
497 line_left -= wchar_strlen (str);
502 _str_list_match_node (const StrList* list, const wchar_t* str)
504 if (wchar_strcasecmp (list->str, str) == 0)
506 if (wchar_strncasecmp (list->str, str, wchar_strlen (str)) == 0)
512 str_list_match_node (const StrList* list, const char* str)
514 wchar_t* wc_str = gettext_to_wchar (str); /* FIXME */
517 status = _str_list_match_node (list, wc_str);
523 /* returns: 2 for full match
528 str_list_match_any (const StrList* list, const char* str)
532 wchar_t* wc_str = gettext_to_wchar (str);
534 for (walk = list; walk; walk = walk->next) {
535 int this_status = _str_list_match_node (walk, wc_str);
536 if (this_status > best_status)
537 best_status = this_status;
545 str_list_match (const StrList* list, const char* str)
548 const StrList* partial_match = NULL;
550 wchar_t* wc_str = gettext_to_wchar (str);
552 for (walk = list; walk; walk = walk->next) {
553 switch (_str_list_match_node (walk, wc_str)) {
556 return (StrList*) walk;
561 partial_match = walk;
566 return ambiguous ? NULL : (StrList*) partial_match;
570 str_list_length (const StrList* list)
575 for (walk = list; walk; walk = walk->next)