/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Engrampa
 *
 *  Copyright (C) 2001 The 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <config.h>
#include <errno.h>
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <limits.h>
#include <langinfo.h>
#include "gtk-utils.h"
#include "fr-process.h"
#include "glib-utils.h"

#define LOAD_BUFFER_SIZE 65536

static void
count_selected (GtkTreeModel *model,
		GtkTreePath  *path,
		GtkTreeIter  *iter,
		gpointer      data)
{
	int *n = data;
	*n = *n + 1;
}


int
_gtk_count_selected (GtkTreeSelection *selection)
{
	int n = 0;

	if (selection == NULL)
		return 0;
	gtk_tree_selection_selected_foreach (selection, count_selected, &n);
	return n;
}


GtkWidget*
_gtk_message_dialog_new (GtkWindow        *parent,
			 GtkDialogFlags    flags,
			 const char       *icon_name,
			 const char       *message,
			 const char       *secondary_message,
			 const gchar      *first_button_text,
			 ...)
{
	GtkWidget    *dialog;
	GtkWidget    *label;
	GtkWidget    *image;
	GtkWidget    *hbox;
	GtkWidget    *content_area;
	va_list       args;
	const gchar  *text;
	int           response_id;
	char         *markup_text;

	g_return_val_if_fail ((message != NULL) || (secondary_message != NULL), NULL);

	if (icon_name == NULL)
		icon_name = "dialog-information";

	dialog = gtk_dialog_new_with_buttons ("", parent, flags, NULL, NULL);
	content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

	/* Add label and image */

	image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_DIALOG);
	gtk_widget_set_valign (image, GTK_ALIGN_START);

	label = gtk_label_new ("");

	if (message != NULL) {
		char *escaped_message;

		escaped_message = g_markup_escape_text (message, -1);
		if (secondary_message != NULL) {
			char *escaped_secondary_message = g_markup_escape_text (secondary_message, -1);
			markup_text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
						       escaped_message,
						       escaped_secondary_message);
			g_free (escaped_secondary_message);
		}
		else
			markup_text = g_strdup (escaped_message);
		g_free (escaped_message);
	}
	else
		markup_text = g_markup_escape_text (secondary_message, -1);

	gtk_label_set_markup (GTK_LABEL (label), markup_text);
	g_free (markup_text);

	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
	gtk_label_set_selectable (GTK_LABEL (label), TRUE);

	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 24);
	gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);

	gtk_box_pack_start (GTK_BOX (hbox), image,
			    FALSE, FALSE, 0);

	gtk_box_pack_start (GTK_BOX (hbox), label,
			    TRUE, TRUE, 0);

	gtk_box_pack_start (GTK_BOX (content_area),
			    hbox,
			    FALSE, FALSE, 0);

	gtk_widget_show_all (hbox);

	/* Add buttons */

	if (first_button_text == NULL)
		return dialog;

	va_start (args, first_button_text);

	text = first_button_text;
	response_id = va_arg (args, gint);

	while (text != NULL) {
		gtk_dialog_add_button (GTK_DIALOG (dialog), text, response_id);

		text = va_arg (args, char*);
		if (text == NULL)
			break;
		response_id = va_arg (args, int);
	}

	va_end (args);

	return dialog;
}


static GtkWidget *
create_button (const char *icon_name,
	       const char *text)
{
	GtkIconTheme *icon_theme;
	GtkWidget    *button;

	button = gtk_button_new_with_mnemonic (text);
	icon_theme = gtk_icon_theme_get_default ();
	if (gtk_icon_theme_has_icon (icon_theme, icon_name)) {
		GtkWidget *image;
		image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
		gtk_button_set_image (GTK_BUTTON (button), image);
	}
	gtk_widget_set_can_default (button, TRUE);

	gtk_widget_show (button);

	return button;
}


char *
_gtk_request_dialog_run (GtkWindow        *parent,
			 GtkDialogFlags    flags,
			 const char       *title,
			 const char       *message,
			 const char       *default_value,
			 int               max_length,
			 const gchar      *no_button_text,
			 const gchar      *yes_button_text)
{
	GtkWidget    *dialog;
	GtkWidget    *label;
	GtkWidget    *image;
	GtkWidget    *hbox;
	GtkWidget    *vbox;
	GtkWidget    *entry;
	GtkWidget    *button;
	GtkWidget    *content_area;
	char         *result;

	dialog = gtk_dialog_new_with_buttons (title, parent, flags, NULL, NULL);
	content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

	/* Add label and image */

	image = gtk_image_new_from_icon_name ("dialog-question", GTK_ICON_SIZE_DIALOG);
	gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
	gtk_widget_set_valign (image, GTK_ALIGN_START);

	label = gtk_label_new_with_mnemonic (message);
	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
	gtk_label_set_selectable (GTK_LABEL (label), FALSE);
	gtk_label_set_xalign (GTK_LABEL (label), 0.0);
	gtk_label_set_yalign (GTK_LABEL (label), 0.0);

	entry = gtk_entry_new ();
	gtk_entry_set_width_chars (GTK_ENTRY (entry), 50);
	gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
	gtk_entry_set_max_length (GTK_ENTRY (entry), max_length);
	gtk_entry_set_text (GTK_ENTRY (entry), default_value);
	gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);

	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);

	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
	gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);

	gtk_box_set_spacing (GTK_BOX (content_area), 14); /* 14 + 2 * 5 = 24 */
	gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
	gtk_box_set_spacing (GTK_BOX (vbox), 6);

	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (content_area), hbox, FALSE, FALSE, 0);

	gtk_widget_show_all (hbox);

	/* Add buttons */

	button = create_button ("process-stop", no_button_text);
	gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
				      button,
				      GTK_RESPONSE_CANCEL);

	button = create_button ("gtk-ok", yes_button_text);
	gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
				      button,
				      GTK_RESPONSE_YES);

	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);

	/* Run dialog */

	gtk_widget_grab_focus (entry);

	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES)
		result = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
	else
		result = NULL;

	gtk_widget_destroy (dialog);

	return result;
}


GtkWidget*
_gtk_error_dialog_new (GtkWindow        *parent,
		       GtkDialogFlags    flags,
		       GList            *row_output,
		       const char       *primary_text,
		       const char       *secondary_text,
		       ...)
{
	GtkWidget     *dialog;
	GtkWidget     *label;
	GtkWidget     *image;
	GtkWidget     *hbox;
	GtkWidget     *vbox;
	GtkWidget     *text_view;
	GtkWidget     *scrolled = NULL;
	GtkWidget     *expander;
	GtkWidget     *content_area;
	GtkWidget     *action_area;
	GtkTextBuffer *text_buf;
	GtkTextIter    iter;
	GList         *scan;
	char          *escaped_message, *markup_text;
	va_list        args;
	gboolean       view_output = (row_output != NULL);

	dialog = gtk_dialog_new_with_buttons ("",
					      parent,
					      flags,
					      "gtk-ok", GTK_RESPONSE_OK,
					      NULL);
	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);

	content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

	action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));

	/* Add label and image */

	image = gtk_image_new_from_icon_name ("dialog-error", GTK_ICON_SIZE_DIALOG);
	gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
	gtk_widget_set_valign (image, GTK_ALIGN_START);

	label = gtk_label_new ("");
	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
	gtk_label_set_selectable (GTK_LABEL (label), TRUE);
	gtk_label_set_xalign (GTK_LABEL (label), 0.0);
	gtk_label_set_yalign (GTK_LABEL (label), 0.0);

	escaped_message = g_markup_escape_text (primary_text, -1);
	if (secondary_text != NULL) {
		char *secondary_message;
		char *escaped_secondary_message;

		va_start (args, secondary_text);
		secondary_message = g_strdup_vprintf (secondary_text, args);
		va_end (args);
		escaped_secondary_message = g_markup_escape_text (secondary_message, -1);

		markup_text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
					       escaped_message,
					       escaped_secondary_message);

		g_free (escaped_secondary_message);
		g_free (secondary_message);
	}
	else
		markup_text = g_strdup (escaped_message);
	gtk_label_set_markup (GTK_LABEL (label), markup_text);
	g_free (markup_text);
	g_free (escaped_message);

	if (view_output) {
		gtk_widget_set_size_request (dialog, 500, -1);

		/* Expander */

		expander = gtk_expander_new_with_mnemonic (_("Command _Line Output"));
		gtk_expander_set_expanded (GTK_EXPANDER (expander), secondary_text == NULL);

		/* Add text */

		scrolled = gtk_scrolled_window_new (NULL, NULL);
		gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
						GTK_POLICY_AUTOMATIC,
						GTK_POLICY_AUTOMATIC);
		gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
						     GTK_SHADOW_ETCHED_IN);
		gtk_widget_set_size_request (scrolled, -1, 200);

		text_buf = gtk_text_buffer_new (NULL);
		gtk_text_buffer_create_tag (text_buf, "monospace",
					    "family", "monospace", NULL);
		gtk_text_buffer_get_iter_at_offset (text_buf, &iter, 0);
		for (scan = row_output; scan; scan = scan->next) {
			char *line = scan->data;
			char *utf8_line;
			gsize bytes_written;

			utf8_line = g_locale_to_utf8 (line, -1, NULL, &bytes_written, NULL);
			gtk_text_buffer_insert_with_tags_by_name (text_buf,
								  &iter,
								  utf8_line,
								  bytes_written,
								  "monospace", NULL);
			g_free (utf8_line);

			gtk_text_buffer_insert (text_buf, &iter, "\n", 1);
		}
		text_view = gtk_text_view_new_with_buffer (text_buf);
		g_object_unref (text_buf);
		gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), FALSE);
		gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (text_view), FALSE);
	}

	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);

	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);

	if (view_output) {
		gtk_container_add (GTK_CONTAINER (scrolled), text_view);
		gtk_container_add (GTK_CONTAINER (expander), scrolled);
		gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
	}

	gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, FALSE, 0);

	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
	gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
	gtk_box_set_spacing (GTK_BOX (content_area), 14); /* 14 + 2 * 5 = 24 */
	gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
	gtk_box_set_spacing (GTK_BOX (action_area), 6);

	gtk_widget_show_all (vbox);

	return dialog;
}


void
_gtk_error_dialog_run (GtkWindow        *parent,
		       const gchar      *main_message,
		       const gchar      *format,
		       ...)
{
	GtkWidget *d;
	char      *message;
	va_list    args;

	va_start (args, format);
	message = g_strdup_vprintf (format, args);
	va_end (args);

	d =  _gtk_message_dialog_new (parent,
				      GTK_DIALOG_MODAL,
				      "dialog-error",
				      main_message,
				      message,
				      "gtk-close", GTK_RESPONSE_CANCEL,
				      NULL);
	g_free (message);

	g_signal_connect (G_OBJECT (d), "response",
			  G_CALLBACK (gtk_widget_destroy),
			  NULL);

	gtk_widget_show (d);
}


void
_gtk_entry_set_locale_text (GtkEntry   *entry,
			    const char *text)
{
	char *utf8_text;

	if (text == NULL)
		return;

	utf8_text = g_locale_to_utf8 (text, -1, NULL, NULL, NULL);
	if (utf8_text != NULL)
		gtk_entry_set_text (entry, utf8_text);
	else
		gtk_entry_set_text (entry, "");
	g_free (utf8_text);
}


char *
_gtk_entry_get_locale_text (GtkEntry *entry)
{
	const char *utf8_text;
	char       *text;

	utf8_text = gtk_entry_get_text (entry);
	if (utf8_text == NULL)
		return NULL;

	text = g_locale_from_utf8 (utf8_text, -1, NULL, NULL, NULL);

	return text;
}


void
_gtk_entry_set_filename_text (GtkEntry   *entry,
			      const char *text)
{
	char *utf8_text;

	utf8_text = g_filename_to_utf8 (text, -1, NULL, NULL, NULL);
	if (utf8_text != NULL) {
		gtk_entry_set_text (entry, utf8_text);
		g_free (utf8_text);
	} else
		gtk_entry_set_text (entry, "");
}


static GdkPixbuf *
get_themed_icon_pixbuf (GThemedIcon  *icon,
		        int           size,
		        GtkIconTheme *icon_theme)
{
	char        **icon_names;
	GtkIconInfo  *icon_info;
	GdkPixbuf    *pixbuf;
	GError       *error = NULL;

	g_object_get (icon, "names", &icon_names, NULL);

	icon_info = gtk_icon_theme_choose_icon (icon_theme, (const char **)icon_names, size, 0);
	if (icon_info == NULL)
		icon_info = gtk_icon_theme_lookup_icon (icon_theme, "text-x-generic", size, GTK_ICON_LOOKUP_USE_BUILTIN);

	pixbuf = gtk_icon_info_load_icon (icon_info, &error);
	if (pixbuf == NULL) {
		g_warning ("could not load icon pixbuf: %s\n", error->message);
		g_clear_error (&error);
	}

	g_object_unref (icon_info);
	g_strfreev (icon_names);

	return pixbuf;
}


static GdkPixbuf *
get_file_icon_pixbuf (GFileIcon *icon,
		      int        size)
{
	GFile     *file;
	char      *filename;
	GdkPixbuf *pixbuf;

	file = g_file_icon_get_file (icon);
	filename = g_file_get_path (file);
	pixbuf = gdk_pixbuf_new_from_file_at_size (filename, size, -1, NULL);
	g_free (filename);
	g_object_unref (file);

	return pixbuf;
}


GdkPixbuf *
get_icon_pixbuf (GIcon        *icon,
		 int           size,
		 GtkIconTheme *theme)
{
	if (icon == NULL)
		return NULL;
	if (G_IS_THEMED_ICON (icon))
		return get_themed_icon_pixbuf (G_THEMED_ICON (icon), size, theme);
	if (G_IS_FILE_ICON (icon))
		return get_file_icon_pixbuf (G_FILE_ICON (icon), size);
	return NULL;
}


GdkPixbuf *
get_mime_type_pixbuf (const char   *mime_type,
		      int           icon_size,
		      GtkIconTheme *icon_theme)
{
	GdkPixbuf *pixbuf = NULL;
	GIcon     *icon;

	if (icon_theme == NULL)
		icon_theme = gtk_icon_theme_get_default ();

	icon = g_content_type_get_icon (mime_type);
	pixbuf = get_icon_pixbuf (icon, icon_size, icon_theme);
	g_object_unref (icon);

	return pixbuf;
}

static gboolean
xdg_open_guide_show()
{
	if (!g_spawn_command_line_async("/usr/bin/xdg-open help:engrampa", NULL)) {
#ifdef MATE_ENABLE_DEBUG
	debug(DEBUG_INFO, "xdg-open help:engrampa\n");
#endif
		return FALSE;
	}
	return TRUE;
}

gboolean
xdg_open_uri(const char* path)
{
	GString *cmd;
	cmd = g_string_new ("/usr/bin/xdg-open");
	g_string_append_printf(cmd," %s", path);
	if (!g_spawn_command_line_async(cmd, NULL)) {
#ifdef MATE_ENABLE_DEBUG
	debug(DEBUG_INFO, "xdg-open help:engrampa\n");
#endif
		return FALSE;
	}
	return TRUE;
}

static gboolean
notify_user_guide_show()
{
	GError *error = NULL;
	GDBusConnection *connection = NULL;
	GDBusProxy *proxy = NULL;

	// 获取 D-Bus 连接
	connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
	if (error != NULL) {
		g_printerr("Failed to get bus connection: %s\n", error->message);
		g_error_free(error);
		return FALSE;
	}

	// 创建 D-Bus 代理
	proxy = g_dbus_proxy_new_sync(connection,
					G_DBUS_PROXY_FLAGS_NONE,
					NULL,
					"com.kylinUserGuide.hotel_1000",
					"/",
					"com.guide.hotel",
					NULL,
					&error);
	if (error != NULL) {
		g_printerr("Failed to create proxy: %s\n", error->message);
		g_error_free(error);
		g_object_unref(connection);
		return FALSE;
	}

	// 调用代理方法
	g_dbus_proxy_call_sync(proxy,
				"showGuide",
				g_variant_new("(s)", "engrampa"),
				G_DBUS_CALL_FLAGS_NONE,
				-1,
				NULL,
				&error);
	if (error != NULL) {
		g_printerr("Failed to call showGuide: %s\n", error->message);
		g_error_free(error);
		error = NULL;
		g_object_unref(connection);
		return FALSE;
	}

	g_object_unref(connection);
	return TRUE;
}

static gboolean
call_user_guide_show()
{
	if (!g_spawn_command_line_async("kylin-user-guide -A engrampa", NULL)) {
#ifdef MATE_ENABLE_DEBUG
	debug(DEBUG_INFO, "help failed command : kylin-user-guide -A engrampa\n");
#endif
		return FALSE;
	}
	return TRUE;
}

void
show_help_dialog (GtkWindow  *parent,
		  const char *section)
{
	gboolean ret = TRUE;
	// notify_user_guide_show();

	ret = xdg_open_guide_show();
	if (!ret) {
		ret = call_user_guide_show();
	}
	if (!ret) {
		ret = notify_user_guide_show();
	}
	if (!ret) {
		if (! gtk_show_uri_on_window (NULL, "help:engrampa", GDK_CURRENT_TIME, NULL)) {
			GtkWidget *dialog;

			dialog = _gtk_message_dialog_new (parent,
							GTK_DIALOG_DESTROY_WITH_PARENT,
							"dialog-error",
							_("Could not display help"),
							"",
							"gtk-ok", GTK_RESPONSE_OK,
							NULL);
			gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);

			g_signal_connect (G_OBJECT (dialog), "response",
					G_CALLBACK (gtk_widget_destroy),
					NULL);

			gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);

			gtk_widget_show (dialog);
		}
	}
}


GtkBuilder *
_gtk_builder_new_from_resource (const char *resource_path)
{
	GtkBuilder *builder;
	char       *full_path;
	GError     *error = NULL;

	builder = gtk_builder_new ();
	full_path = g_strconcat (ENGRAMPA_RESOURCE_UI_PATH G_DIR_SEPARATOR_S, resource_path, NULL);
        if (! gtk_builder_add_from_resource (builder, full_path, &error)) {
                g_warning ("%s\n", error->message);
                g_clear_error (&error);
        }
	g_free (full_path);

        return builder;
}


GtkWidget *
_gtk_builder_get_widget (GtkBuilder *builder,
			 const char *name)
{
	return (GtkWidget *) gtk_builder_get_object (builder, name);
}

int
_gtk_widget_lookup_for_size (GtkWidget *widget,
                             GtkIconSize icon_size)
{
	int w, h;
	gtk_icon_size_lookup (icon_size,
			      &w, &h);
	return MAX (w, h);
}

int is_valid_utf8(const char *s)
{
    const unsigned char *p = (const unsigned char *)s;
    while (*p) {
        if (*p < 0x80) {
            p++;
        } else if ((p[0] & 0xE0) == 0xC0 && (p[1] & 0xC0) == 0x80) {
            p += 2;
        } else if ((p[0] & 0xF0) == 0xE0 && (p[1] & 0xC0) == 0x80 && (p[2] & 0xC0) == 0x80) {
            p += 3;
        } else if ((p[0] & 0xF8) == 0xF0 && (p[1] & 0xC0) == 0x80 && (p[2] & 0xC0) == 0x80 && (p[3] & 0xC0) == 0x80) {
            p += 4;
        } else {
            return 0; // 非法UTF-8
        }
    }
    return 1; // 合法UTF-8
}

const gchar *
detection_encoding(const gchar *src)
{
    if(is_valid_utf8(src))
        return  g_strdup("UTF-8");
    else
        return  g_strdup("GB18030");
}

/*
 * Get the character code type. (UTF-8 or GB18030)
 * @param s the string to be operator.
 * @return return the code type. (1 means UTF-8, 0 for GB18030, -1 for error)
 */
int get_character_code_type(const char* s)
{
	if (NULL == s)
	{
		return -1;
	}

	int i = 0;
	for(; s[i] != '\0'; i++)
	{
		// ASCII character.
		if (!(s[i] & 0x80))
		{
			continue;
		}
		// Hanzi utf-8 code possiable.
		else if(!( (s[i] & 0xF0) ^ 0xE0)
				&& s[i+1]
				&& !( (s[i+1] & 0xC0) ^ 0x80)
				&& s[i+2]
				&& !( (s[i+2] & 0xC0) ^ 0x80))
		{
			return 1;
		}
		// Not a UTF-8 code.
		else
		{
			return 0;
		}
	}

	return -1;
}

static gchar *
converted_string(const gchar *src, const gchar *from_charset, const gchar *to_charset)
{
	if (from_charset != NULL && g_strcasecmp(from_charset, to_charset) == 0) {
		return NULL;
	}

	if (from_charset == NULL || strcmp(from_charset, "") == 0
	    || g_strcasecmp(from_charset, "TIS-620") == 0
	    || g_strcasecmp(from_charset, "GB18030") == 0
	    || g_strcasecmp(from_charset, "GBK") == 0
	    || g_strcasecmp(from_charset, "GB2312") == 0
	    || g_strcasecmp(from_charset, "Big5") == 0
	    || g_strcasecmp(from_charset, "x-euc-tw") == 0
	    || g_strncasecmp(from_charset, "WINDOWS-", strlen("WINDOWS-")) == 0
	    || g_strncasecmp(from_charset, "ISO-8859-", strlen("ISO-8859-")) == 0
	    || g_strncasecmp(from_charset, "x-mac", strlen("x-mac")) == 0
	    || g_strcasecmp(from_charset, "KOI8-R") == 0) {
		from_charset = g_strdup("GB18030");
	}

	GIConv cd = g_iconv_open(to_charset, from_charset);
	if (cd == NULL) {
		return NULL;
	}

	gchar *dest_str = g_strnfill(PATH_MAX, 0);;
	gchar *src_str = g_strdup(src);
	gchar *src_str_ptr = src_str;
	size_t src_str_len = strlen(src_str);
	size_t dest_str_len = PATH_MAX - 1;
	gchar *dest_str_ptr = dest_str;

	gsize result = g_iconv(cd, &src_str_ptr, &src_str_len, &dest_str_ptr, &dest_str_len);
	if (result == (gsize)-1) {
		g_free(src_str);
		g_free(dest_str);
		g_iconv_close(cd);
		return NULL;
	}

	gchar *ret = g_strdup(dest_str);

	g_free(src_str);
	g_free(dest_str);
	g_iconv_close(cd);

	return ret;
}

const gchar *
get_converted_string(const gchar *src)
{
	const gchar *file_name_coding = detection_encoding (src);
	const char *local_charset = nl_langinfo(CODESET);
	if (local_charset == NULL) {
		local_charset = "UTF-8";
	}

	if (file_name_coding != NULL && g_strcasecmp(file_name_coding, local_charset) == 0) {
		g_free(file_name_coding);
		return NULL;
	}

	gchar *ret = converted_string(src, file_name_coding, local_charset);

	g_free(file_name_coding);

	return ret;
}

gchar *
get_converted_utf8_string(const gchar *src)
{
	const gchar *file_name_coding = detection_encoding (src);
	const char *local_charset = "UTF-8";
	if (file_name_coding != NULL && g_strcasecmp(file_name_coding, local_charset) == 0) {
		g_free(file_name_coding);
		return g_strdup(src);
	}

	gchar *ret = converted_string(src, file_name_coding, local_charset);

	g_free(file_name_coding);

	return ret;
}
