2 parted - a frontend to libparted
3 Copyright (C) 1999, 2000, 2001, 2007 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 #else /* ENABLE_NLS */
48 #endif /* !ENABLE_NLS */
52 #define MIN(a,b) ( (a<b)? a : b )
55 wchar_strlen (const wchar_t* str)
65 wchar_strchr (const wchar_t* str, char ch)
68 return wcschr (str, ch);
70 return strchr (str, ch);
75 wchar_strcasecmp (const wchar_t* a, const wchar_t* b)
78 return wcscasecmp (a, b);
80 return strcasecmp (a, b);
85 wchar_strncasecmp (const wchar_t* a, const wchar_t* b, size_t n)
88 return wcsncasecmp (a, b, n);
90 return strncasecmp (a, b, n);
95 wchar_strdup (const wchar_t* str)
100 return xstrdup (str);
104 /* converts a string from the encoding in the gettext catalogues to wide
105 * character strings (of type wchar_t*).
109 gettext_to_wchar (const char* str)
116 count = strlen (str) + 1;
117 result = malloc (count * sizeof (wchar_t));
121 memset(&ps, 0, sizeof (ps));
122 status = mbsrtowcs(result, &str, count, &ps);
123 if (status == (size_t) -1)
126 result = realloc (result, (wcslen (result) + 1) * sizeof (wchar_t));
130 printf ("Error during translation: %s\n", strerror (errno));
134 #else /* ENABLE_NLS */
137 gettext_to_wchar (const char* str)
139 return xstrdup (str);
142 #endif /* !ENABLE_NLS */
147 wchar_to_str (const wchar_t* str, size_t count)
155 if (count == 0 || wcslen(str) < count)
156 count = wcslen (str);
158 out_buf = result = malloc ((count + 1) * MB_LEN_MAX);
162 memset(&ps, 0, sizeof(ps));
164 for (i = 0; i < count; i++) {
165 status = wcrtomb (out_buf, str[i], &ps);
166 if (status == (size_t) -1)
171 status = wcrtomb (out_buf, 0, &ps);
172 if (status == (size_t) -1)
175 result = realloc (result, strlen (result) + 1);
179 printf ("Error during translation: %s\n", strerror (errno));
183 #else /* ENABLE_NLS */
186 wchar_to_str (const wchar_t* str, size_t count)
190 result = xstrdup (str);
191 if (count && count < strlen (result))
196 #endif /* !ENABLE_NLS */
199 print_wchar (const wchar_t* str, size_t count)
201 char* tmp = wchar_to_str (str, count);
211 list = xmalloc (sizeof (StrList));
218 str_list_destroy (StrList* list)
221 str_list_destroy (list->next);
222 str_list_destroy_node (list);
227 str_list_destroy_node (StrList* list)
229 free ((wchar_t*) list->str);
234 str_list_duplicate_node (const StrList* node)
236 StrList* result = str_list_alloc ();
237 result->str = wchar_strdup (node->str);
242 str_list_duplicate (const StrList* list)
245 return str_list_join (str_list_duplicate_node (list),
246 str_list_duplicate (list->next));
252 str_list_join (StrList* a, StrList* b)
256 for (walk = a; walk && walk->next; walk = walk->next);
267 _str_list_append (StrList* list, const wchar_t* str)
272 for (walk = list; walk->next; walk = walk->next);
273 walk->next = str_list_alloc ();
276 walk = list = str_list_alloc ();
284 str_list_append (StrList* list, const char* str)
286 return _str_list_append (list, gettext_to_wchar (str));
290 str_list_append_unique (StrList* list, const char* str)
293 wchar_t* new_str = gettext_to_wchar (str);
295 for (walk=list; walk; walk=walk->next) {
297 if (wchar_strcasecmp (new_str, walk->str) == 0) {
304 return _str_list_append (list, new_str);
308 str_list_insert (StrList* list, const char* str)
310 return str_list_join (str_list_create (str, NULL), list);
314 str_list_create (const char* first, ...)
320 list = str_list_append (NULL, first);
323 va_start (args, first);
324 while ( (str = va_arg (args, char*)) )
325 str_list_append (list, str);
333 str_list_create_unique (const char* first, ...)
339 list = str_list_append (NULL, first);
342 va_start (args, first);
343 while ( (str = va_arg (args, char*)) )
344 str_list_append_unique (list, str);
352 str_list_convert_node (const StrList* list)
354 return wchar_to_str (list->str, 0);
358 str_list_convert (const StrList* list)
363 char* str = xstrdup ("");
365 for (walk = list; walk; walk = walk->next) {
367 char* tmp = wchar_to_str (walk->str, 0);
369 length += strlen (tmp);
371 str = realloc (str, length);
372 strcpy (str + pos, tmp);
383 str_list_print (const StrList* list)
387 for (walk=list; walk; walk=walk->next) {
389 print_wchar (walk->str, 0);
394 str_search (const wchar_t* str, int n, wchar_t c)
405 /* Japanese don't leave spaces between words, so ALL Japanese characters
406 * are treated as delimiters. Note: since the translations should already
407 * be properly formatted (eg: spaces after commas), there should be no
408 * need to include them. Best not to avoid side effects, like 3.
410 * FIXME: how do we exclude "." and "(" ?
411 * FIXME: glibc doesn't like umlaute. i.e. \"o (TeX notation), which should
416 is_break_point (wchar_t c)
419 return !iswalnum (c) && !iswpunct (c);
421 return !isalnum (c) && !ispunct (c);
425 /* NOTE: this should not return '\n' as a space, because explicit '\n' may
426 * be placed inside strings.
432 return c == (wchar_t) btowc(' ');
439 str_list_print_wrap (const StrList* list, int line_length, int offset,
451 PED_ASSERT (line_length - indent > 10, return);
453 line_left = line_length - offset;
455 for (walk=list; walk; walk=walk->next) {
459 str_len = wchar_strlen (str);
461 while (line_left < str_len || wchar_strchr (str, '\n')) {
464 cut_left = MIN (line_left - 1, str_len - 1);
466 /* we can have a space "over", but not a comma */
467 if (cut_left < str_len
468 && is_space (str [cut_left + 1]))
471 while (cut_left && !is_break_point (str [cut_left]))
473 while (cut_left && is_space (str [cut_left]))
476 /* str [cut_left] is either the end of a word, or a
477 * Japanese character, or the start of a blank line.
480 search_result = str_search (str, cut_left + 1, '\n');
481 if (search_result != -1) {
482 cut_left = search_result - 1;
486 for (cut_right = cut_left + (line_break ? 2 : 1);
487 cut_right < str_len && is_space (str [cut_right]);
491 print_wchar (str, cut_left + 1);
494 str_len -= cut_right;
495 line_left = line_length - indent;
497 if (walk->next || *str)
498 printf ("\n%*s", indent, "");
503 print_wchar (str, 0);
504 line_left -= wchar_strlen (str);
509 _str_list_match_node (const StrList* list, const wchar_t* str)
511 if (wchar_strcasecmp (list->str, str) == 0)
513 if (wchar_strncasecmp (list->str, str, wchar_strlen (str)) == 0)
519 str_list_match_node (const StrList* list, const char* str)
521 wchar_t* wc_str = gettext_to_wchar (str); /* FIXME */
524 status = _str_list_match_node (list, wc_str);
530 /* returns: 2 for full match
535 str_list_match_any (const StrList* list, const char* str)
539 wchar_t* wc_str = gettext_to_wchar (str);
541 for (walk = list; walk; walk = walk->next) {
542 int this_status = _str_list_match_node (walk, wc_str);
543 if (this_status > best_status)
544 best_status = this_status;
552 str_list_match (const StrList* list, const char* str)
555 const StrList* partial_match = NULL;
557 wchar_t* wc_str = gettext_to_wchar (str);
559 for (walk = list; walk; walk = walk->next) {
560 switch (_str_list_match_node (walk, wc_str)) {
563 return (StrList*) walk;
568 partial_match = walk;
573 return ambiguous ? NULL : (StrList*) partial_match;
577 str_list_length (const StrList* list)
582 for (walk = list; walk; walk = walk->next)