/* parted - a frontend to libparted Copyright (C) 1999-2001, 2007, 2009-2014, 2019-2022 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include "xalloc.h" #ifdef ENABLE_NLS #undef __USE_GNU #define __USE_GNU #include #include #endif /* !ENABLE_NLS */ #include "strlist.h" #define MIN(a,b) ( (anext = NULL; return list; } void str_list_destroy (StrList* list) { if (list) { str_list_destroy (list->next); str_list_destroy_node (list); } } void str_list_destroy_node (StrList* list) { void *p = (char *) (list->str); /* discard const */ free (p); free (list); } StrList* str_list_duplicate_node (const StrList* node) { StrList* result = str_list_alloc (); result->str = wchar_strdup (node->str); return result; } StrList* str_list_duplicate (const StrList* list) { if (list) return str_list_join (str_list_duplicate_node (list), str_list_duplicate (list->next)); else return NULL; } StrList* str_list_join (StrList* a, StrList* b) { StrList* walk; for (walk = a; walk && walk->next; walk = walk->next); if (walk) { walk->next = b; return a; } else { return b; } } static StrList* _str_list_append (StrList* list, const wchar_t* str) { StrList* walk; if (list) { for (walk = list; walk->next; walk = walk->next); walk->next = str_list_alloc (); walk = walk->next; } else { walk = list = str_list_alloc (); } walk->str = str; return list; } StrList* str_list_append (StrList* list, const char* str) { return _str_list_append (list, gettext_to_wchar (str)); } StrList* str_list_append_unique (StrList* list, const char* str) { StrList* walk; wchar_t* new_str = gettext_to_wchar (str); for (walk=list; walk; walk=walk->next) { if (walk->str) { if (wchar_strcasecmp (new_str, walk->str) == 0) { free (new_str); return list; } } } return _str_list_append (list, new_str); } StrList* str_list_insert (StrList* list, const char* str) { return str_list_join (str_list_create (str, NULL), list); } StrList* str_list_create (const char* first, ...) { va_list args; char* str; StrList* list; list = str_list_append (NULL, first); if (first) { va_start (args, first); while ( (str = va_arg (args, char*)) ) str_list_append (list, str); va_end (args); } return list; } StrList* str_list_create_unique (const char* first, ...) { va_list args; char* str; StrList* list; list = str_list_append (NULL, first); if (first) { va_start (args, first); while ( (str = va_arg (args, char*)) ) str_list_append_unique (list, str); va_end (args); } return list; } char* str_list_convert_node (const StrList* list) { return wchar_to_str (list->str, 0); } char* str_list_convert (const StrList* list) { const StrList* walk; int pos = 0; int length = 1; char* str = xstrdup (""); for (walk = list; walk; walk = walk->next) { if (walk->str) { char* tmp = wchar_to_str (walk->str, 0); length += strlen (tmp); str = realloc (str, length); strcpy (str + pos, tmp); pos = length - 1; free (tmp); } } return str; } void str_list_print (const StrList* list, FILE *fp) { const StrList* walk; for (walk=list; walk; walk=walk->next) { if (walk->str) print_wchar (walk->str, 0, fp); } } static int str_search (const wchar_t* str, int n, wchar_t c) { int i; for (i=0; i 10); line_left = line_length - offset; for (walk=list; walk; walk=walk->next) { if (!walk->str) continue; str = walk->str; str_len = wchar_strlen (str); while (line_left < str_len || wchar_strchr (str, '\n')) { line_break = 0; cut_left = MIN (line_left - 1, str_len - 1); /* we can have a space "over", but not a comma */ if (cut_left < str_len && is_space (str [cut_left + 1])) cut_left++; while (cut_left && !is_break_point (str [cut_left])) cut_left--; while (cut_left && is_space (str [cut_left])) cut_left--; /* str [cut_left] is either the end of a word, or a * Japanese character, or the start of a blank line. */ search_result = str_search (str, cut_left + 1, '\n'); if (search_result != -1) { cut_left = search_result - 1; line_break = 1; } for (cut_right = cut_left + (line_break ? 2 : 1); cut_right < str_len && is_space (str [cut_right]); cut_right++); if (cut_left > 0) print_wchar (str, cut_left + 1, fp); str += cut_right; str_len -= cut_right; line_left = line_length - indent; if (walk->next || *str) fprintf (fp, "\n%*s", indent, ""); else if (line_break) fputc ('\n', fp); } print_wchar (str, 0, fp); line_left -= wchar_strlen (str); } } static int _str_list_match_node (const StrList* list, const wchar_t* str) { if (wchar_strcasecmp (list->str, str) == 0) return 2; if (wchar_strncasecmp (list->str, str, wchar_strlen (str)) == 0) return 1; return 0; } int str_list_match_node (const StrList* list, const char* str) { wchar_t* wc_str = gettext_to_wchar (str); /* FIXME */ int status; status = _str_list_match_node (list, wc_str); free (wc_str); return status; } /* returns: 2 for full match 1 for partial match 0 for no match */ int str_list_match_any (const StrList* list, const char* str) { const StrList* walk; int best_status = 0; wchar_t* wc_str = gettext_to_wchar (str); for (walk = list; walk; walk = walk->next) { int this_status = _str_list_match_node (walk, wc_str); if (this_status > best_status) best_status = this_status; } free (wc_str); return best_status; } StrList* str_list_match (const StrList* list, const char* str) { const StrList* walk; const StrList* partial_match = NULL; int ambiguous = 0; wchar_t* wc_str = gettext_to_wchar (str); for (walk = list; walk; walk = walk->next) { switch (_str_list_match_node (walk, wc_str)) { case 2: free (wc_str); return (StrList*) walk; case 1: if (partial_match) ambiguous = 1; partial_match = walk; } } free (wc_str); return ambiguous ? NULL : (StrList*) partial_match; } int str_list_length (const StrList* list) { int length = 0; const StrList* walk; for (walk = list; walk; walk = walk->next) length++; return length; }