Anonymous avatar Anonymous committed cadc334

Why didn't anybody tell me that I missed the strlist.c? (fdisk@sv.gnu.org/fdisk--main--0--patch-22)
fdisk@sv.gnu.org/fdisk--main--0--patch-22
Keywords:

Comments (0)

Files changed (1)

+/*
+    GNU fdisk - a clone of Linux fdisk.
+    This file originally from GNU Parted.
+
+    Copyright (C) 1999, 2000, 2001, 2002, 2006 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 2 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, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#include "config.h"
+
+#include <parted/debug.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#ifdef ENABLE_NLS
+
+#undef __USE_GNU
+#define __USE_GNU
+
+#include <wchar.h>
+#include <wctype.h>
+
+#else /* ENABLE_NLS */
+
+#ifdef wchar_t
+#undef wchar_t
+#endif
+
+#define wchar_t char
+
+#endif /* !ENABLE_NLS */
+
+#include "strlist.h"
+
+#define MIN(a,b)	( (a<b)?  a : b )
+
+int
+wchar_strlen (const wchar_t* str)
+{
+#ifdef ENABLE_NLS
+	return wcslen (str);
+#else
+	return strlen (str);
+#endif
+}
+
+wchar_t*
+wchar_strchr (const wchar_t* str, char ch)
+{
+#ifdef ENABLE_NLS
+	return wcschr (str, ch);
+#else
+	return strchr (str, ch);
+#endif
+}
+
+int
+wchar_strcasecmp (const wchar_t* a, const wchar_t* b)
+{
+#ifdef ENABLE_NLS
+	return wcscasecmp (a, b);
+#else
+	return strcasecmp (a, b);
+#endif
+}
+
+int
+wchar_strncasecmp (const wchar_t* a, const wchar_t* b, size_t n)
+{
+#ifdef ENABLE_NLS
+	return wcsncasecmp (a, b, n);
+#else
+	return strncasecmp (a, b, n);
+#endif
+}
+
+wchar_t*
+wchar_strdup (const wchar_t* str)
+{
+#ifdef ENABLE_NLS
+	return wcsdup (str);
+#else
+	return strdup (str);
+#endif
+}
+
+/* converts a string from the encoding in the gettext catalogues to wide
+ * character strings (of type wchar_t*).
+ */
+#ifdef ENABLE_NLS
+static wchar_t*
+gettext_to_wchar (const char* str)
+{
+	int		count;
+	wchar_t*	result;
+	size_t		status;
+	mbstate_t	ps;
+
+	count = strlen (str) + 1;
+	result = malloc (count * sizeof (wchar_t));
+	if (!result)
+		goto error;
+
+	memset(&ps, 0, sizeof (ps));
+	status = mbsrtowcs(result, &str, count, &ps);
+	if (status == (size_t) -1)
+		goto error;
+
+	result = realloc (result, (wcslen (result) + 1) * sizeof (wchar_t));
+	return result;
+
+error:
+	printf ("Error during translation: %s\n", strerror (errno));
+	exit (1);
+}
+
+#else /* ENABLE_NLS */
+
+static wchar_t*
+gettext_to_wchar (const char* str)
+{
+	return strdup (str);
+}
+
+#endif /* !ENABLE_NLS */
+
+
+#ifdef ENABLE_NLS
+static char*
+wchar_to_str (const wchar_t* str, size_t count)
+{
+	char*		result;
+	char*		out_buf;
+	size_t		status;
+	mbstate_t	ps;
+	size_t		i;
+
+	if (count == 0 || wcslen(str) < count)
+		count = wcslen (str);
+
+	out_buf = result = malloc ((count + 1) *  MB_LEN_MAX);
+	if (!result)
+		goto error;
+
+	memset(&ps, 0, sizeof(ps));
+
+	for (i = 0; i < count; i++) {
+		status = wcrtomb (out_buf, str[i], &ps);
+		if (status == (size_t) -1)
+			goto error;
+		out_buf += status;
+	}
+
+	status = wcrtomb (out_buf, 0, &ps);
+	if (status == (size_t) -1)
+		goto error;
+
+	result = realloc (result, strlen (result) + 1);
+	return result;
+
+error:
+	printf ("Error during translation: %s\n", strerror (errno));
+	exit (1);
+}
+
+#else /* ENABLE_NLS */
+
+static char*
+wchar_to_str (const wchar_t* str, size_t count)
+{
+	char*		result;
+
+	result = strdup (str);
+	if (count && count < strlen (result))
+		result [count] = 0;
+	return result;
+}
+
+#endif /* !ENABLE_NLS */
+
+static void
+print_wchar (const wchar_t* str, size_t count)
+{
+	char*	tmp = wchar_to_str (str, count);
+	printf ("%s", tmp);
+	free (tmp);
+}
+
+static StrList* 
+str_list_alloc ()
+{
+	StrList*	list;
+
+	list = (StrList*) malloc (sizeof (StrList));
+	list->next = 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)
+{
+	free ((wchar_t*) list->str);
+	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 = strdup ("");
+
+	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)
+{
+	const StrList*	walk;
+
+	for (walk=list; walk; walk=walk->next) {
+		if (walk->str)
+			print_wchar (walk->str, 0);
+	}
+}
+
+static char*
+get_spaces (int space_count)
+{
+	char*	str;
+	int	i;
+
+	str = malloc (space_count + 1);
+	for (i = 0; i < space_count; i++)
+		str [i] = ' ';
+	str [i] = 0;
+
+	return str;
+}
+
+static int
+str_search (const wchar_t* str, int n, wchar_t c)
+{
+	int	i;
+
+	for (i=0; i<n; i++)
+		if (str [i] == c)
+			return i;
+	return -1;
+}
+
+
+/* Japanese don't leave spaces between words, so ALL Japanese characters
+ * are treated as delimiters.  Note: since the translations should already
+ * be properly formatted (eg: spaces after commas), there should be no
+ * need to include them.  Best not to avoid side effects, like 3.
+14159 :-)
+ * FIXME: how do we exclude "." and "(" ?
+ * FIXME: glibc doesn't like umlaute.  i.e. \"o (TeX notation), which should
+ * look like: �
+ */
+
+static int
+is_break_point (wchar_t c)
+{
+#ifdef ENABLE_NLS
+	return !iswalnum (c) && !iswpunct (c);
+#else
+	return !isalnum (c) && !ispunct (c);
+#endif
+}
+
+/* NOTE: this should not return '\n' as a space, because explicit '\n' may
+ * be placed inside strings.
+ */
+static int
+is_space (wchar_t c)
+{
+#ifdef ENABLE_NLS
+	return c == (wchar_t) btowc(' ');
+#else
+	return c == ' ';
+#endif
+}
+
+void
+str_list_print_wrap (const StrList* list, int line_length, int offset,
+		     int indent)
+{
+	const StrList*	walk;
+	const wchar_t*	str;
+	int		str_len;
+	int		cut_right;
+	int		cut_left;
+	int		line_left;
+	char*		spaces;
+	int		search_result;
+	int		line_break;
+
+	PED_ASSERT (line_length - indent > 10, return);
+
+	spaces = get_spaces (indent);
+	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);
+
+			str += cut_right;
+			str_len -= cut_right;
+			line_left = line_length - indent;
+
+			if (walk->next || *str)
+				printf ("\n%s", spaces);
+			else if (line_break)
+				printf ("\n");
+		}
+
+		print_wchar (str, 0);
+		line_left -= wchar_strlen (str);
+	}
+
+	free (spaces);
+}
+
+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;
+}
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.