⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtk.c

📁 一个曾经热门的网络游戏RO查看GRF工具的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <gtk/gtk.h>#include <glib/gthread.h>#include <glade/glade.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include <errno.h>#include "grf.h"GladeXML *xml;Grf *grf = NULL;GString *filename;GtkWidget *opensel = NULL, *savesel = NULL, *dirsel = NULL;GtkTreeModel *filelist;GtkTreePath *current_selection = NULL;gboolean filling = FALSE;GdkCursor *busy_cursor = NULL;typedef struct {	GThread *thread;	enum {		STATUS_INIT,		STATUS_MKDIR,		STATUS_EXTRACT,		STATUS_DONE	} status;	unsigned long max;	unsigned long current;	unsigned long failed;	char file[PATH_MAX];	gboolean stop;} ExtractProgress;ExtractProgress extractProgress, lastKnownProgress;GStaticMutex extractProgressM;enum {	INDEX_COL,	DISPLAY_COL,	TYPE_COL,	SIZE_COL,	SIZE_DISPLAY_COL,	N_COLS};#define W(x) glade_xml_get_widget (xml, #x)#define _(x) x/*********************** * Utility functions ***********************/static voidshow_error (gchar *format, ...){	GtkWidget *dialog;	va_list ap;	gchar *msg;	va_start (ap, format);	msg = g_strdup_vprintf (format, ap);	va_end (ap);	dialog = gtk_message_dialog_new (GTK_WINDOW (W(main)),		GTK_DIALOG_MODAL,		GTK_MESSAGE_ERROR,		GTK_BUTTONS_OK,		msg);	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);	gtk_dialog_run (GTK_DIALOG (dialog));	gtk_widget_destroy (dialog);	g_free (msg);}static GladeXML *load_glade (gchar *basename){	GladeXML *xml;	char self[PATH_MAX + 1];	GList *search_dirs = NULL, *dir;	gchar *filename = NULL;	/* Locate itself if we're on Linux */	if (realpath ("/proc/self/exe", self)) {		char *dir;		dir = g_path_get_dirname (self);		search_dirs = g_list_append (search_dirs, dir);		search_dirs = g_list_append (search_dirs,			g_strdup_printf ("%s/../share/grftool", dir));	}	search_dirs = g_list_append (search_dirs, g_strdup ("."));	for (dir = search_dirs; dir; dir = dir->next) {		gchar *fn;		fn = g_strdup_printf ("%s/%s", (gchar *) dir->data, basename);		if (g_file_test (fn, G_FILE_TEST_IS_REGULAR)) {			filename = fn;			break;		}		g_free (fn);	}	g_list_foreach (search_dirs, (GFunc) g_free, NULL);	g_list_free (search_dirs);	if (!filename) {		show_error (_("Unable to initialize the user interface. You may have to re-install this software."));		exit (5);	}	xml = glade_xml_new (filename, NULL, NULL);	if (!xml) {		show_error (_("Unable to initialize the user interface. You may have to re-install this software."));		exit (5);	}	glade_xml_signal_autoconnect (xml);	return xml;}static voidset_status (const char *msg){	static guint ctx = 0;	GtkStatusbar *bar;	bar = GTK_STATUSBAR (W(status));	gtk_statusbar_pop (bar, ctx);	ctx = gtk_statusbar_get_context_id (bar, msg);	gtk_statusbar_push (bar, ctx, msg);}static voidmkdirs (const char *dir){	gchar **paths;	GString *str;	gint i = 0;	paths = g_strsplit (dir, G_DIR_SEPARATOR_S, -1);	str = g_string_new ("");	while (paths[i]) {		if (!*paths[i]) {			i++;			continue;		}		if (i > 0)			g_string_append_c (str, G_DIR_SEPARATOR);		g_string_append (str, paths[i]);		if (!g_file_test (str->str, G_FILE_TEST_IS_DIR))			mkdir (str->str, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);		i++;	}	g_string_free (str, TRUE);	g_strfreev (paths);}static char *get_type_name (char *filename){	char *ext;	ext = strrchr (filename, '.');	if (!ext)		return g_strdup (_("Unknown"));	ext = g_utf8_strup (ext + 1, -1);	if (strcmp (ext, "BMP") == 0) {		g_free (ext);		return g_strdup (_("Bitmap Image"));	} else if (strcmp (ext, "JPG") == 0) {		g_free (ext);		return g_strdup (_("JPEG Image"));	} else if (strcmp (ext, "GIF") == 0) {		g_free (ext);		return g_strdup (_("GIF Image"));	} else if (strcmp (ext, "PNG") == 0) {		g_free (ext);		return g_strdup (_("PNG Image"));	} else if (strcmp (ext, "TXT") == 0) {		g_free (ext);		return g_strdup (_("Text File"));	} else if (strcmp (ext, "WAV") == 0) {		g_free (ext);		return g_strdup (_("Wave Sound"));	} else if (strcmp (ext, "MP3") == 0) {		g_free (ext);		return g_strdup (_("MP3 Music"));	} else if (strcmp (ext, "SPR") == 0) {		g_free (ext);		return g_strdup (_("Sprite Data"));	} else if (strcmp (ext, "XML") == 0) {		g_free (ext);		return g_strdup (_("XML Document"));	} else		return ext;}/* Attempt to convert a string (possibly with Korean encoding) to UTF-8 */static inline char *str_to_utf8 (char *str, gsize *bytes_written){	char *encodings[] = {		"CSEUCKR", "CSISO2022KR", "EUC-KR", "EUCKR",		"ISO-2022-KR", "ISO646-KR", "ISO2022KR",		"ISO8859-1", "UTF-8"	};	int j;	char *ret = NULL;	if (!(ret = g_locale_to_utf8 (str, -1, NULL, bytes_written, NULL)))	for (j = 0; j < sizeof (encodings) / sizeof (char *); j++) {		ret = g_convert (str, -1,			"UTF-8", encodings[j],			NULL, bytes_written, NULL);		if (ret)			break;	}	return ret;}static char *friendly_size_name (unsigned long size){	if (size < 1024)		return g_strdup_printf ("%ld bytes", size);	else if (size >= 1024 && size < 1024 * 1024)		return g_strdup_printf ("%.1f KB", size / 1024.0);	else		return g_strdup_printf ("%.1f MB", size / 1024.0 / 1024.0);}static unsigned longfill_filelist (){	long i;	unsigned long num = 0;	GtkTreeIter iter = {};	gchar *search;	GPatternSpec *pattern = NULL;	filling = TRUE;	gtk_list_store_clear (GTK_LIST_STORE (filelist));	search = (gchar *) gtk_entry_get_text (GTK_ENTRY (W(searchentry)));	if (search && *search) {		if (!strchr (search, '*')) {			search = g_strdup_printf ("*%s*", search);			pattern = g_pattern_spec_new (search);			g_free (search);		} else			pattern = g_pattern_spec_new (search);	}	/* Detach list model from view to make insertion faster */	g_object_ref (filelist);	gtk_tree_view_set_model (GTK_TREE_VIEW (W(filelist)), NULL);	/* We add items to the list in reversed order because for some reason	   the list reverses the order again. i is not an unsigned long because	   it will conflict with 'i >= 0' and 'i--' */	for (i = (long) grf->nfiles - 1; i >= 0; i--) {		char *filename = NULL;		char *size = NULL;		char *type;		if (!grf->files[i].real_len)			continue;		/* Do not display folders */		if (grf->files[i].type == 2)			continue;		/* Attempt to convert the filename to UTF-8 */		if (!grf->files[i].name) {			printf("%ld: %s\n", i, grf->files[i].name);			continue;		}		filename = str_to_utf8 (grf->files[i].name, NULL);		if (!filename)			continue;		if (pattern && !g_pattern_match_string (pattern, filename)) {			g_free (filename);			continue;		}		size = friendly_size_name (grf->files[i].real_len);		type = get_type_name (filename);		/* Add to list */		gtk_list_store_prepend (GTK_LIST_STORE (filelist), &iter);		gtk_list_store_set (GTK_LIST_STORE (filelist), &iter,			INDEX_COL, i,			DISPLAY_COL, filename,			TYPE_COL, type,			SIZE_COL, grf->files[i].real_len,			SIZE_DISPLAY_COL, size,			-1);		num++;		g_free (size);		g_free (filename);		g_free (type);	}	/* Re-attach model */	gtk_tree_view_set_model (GTK_TREE_VIEW (W(filelist)), filelist);	g_object_unref (filelist);	filling = FALSE;	if (pattern)		g_pattern_spec_free (pattern);	return num;}static voidopen_grf_file (const char *fname){	char *title, *tmp;	GrfError err;	Grf *newgrf;	GList *list, *cols;	if (!g_file_test (fname, G_FILE_TEST_EXISTS)) {		show_error (_("File %s does not exist."), fname);		return;	}	gdk_window_set_cursor (W(main)->window, busy_cursor);	set_status (_("Loading..."));	while (gtk_events_pending ()) gtk_main_iteration ();	newgrf = grf_open (fname, &err);	if (!newgrf) {		char *base;		base = g_path_get_basename (fname);		set_status ("");		show_error (_("Error while opening %s:\n%s"),			base, grf_strerror (err));		g_free (base);		return;	}	if (grf)		grf_free (grf);	grf = newgrf;	g_string_printf (filename, "%s", fname);	title = g_strdup_printf (_("%s - GRF Tool"), fname);	gtk_window_set_title (GTK_WINDOW (W(main)), title);	g_free (title);	gtk_list_store_clear (GTK_LIST_STORE (filelist));	cols = gtk_tree_view_get_columns (GTK_TREE_VIEW (W(filelist)));	for (list = cols; list; list = list->next) {		GtkTreeViewColumn *col = (GtkTreeViewColumn *) list->data;		gtk_tree_view_column_set_sort_indicator (col, FALSE);	}	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (filelist),		GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);	g_list_free (cols);	fill_filelist ();	tmp = g_path_get_basename (fname);	title = g_strdup_printf (_("%s: %ld files"), tmp, grf->nfiles);	set_status (title);	g_free (tmp);	g_free (title);	gtk_widget_set_sensitive (W(extract), TRUE);	gdk_window_set_cursor (W(main)->window, NULL);}static gbooleanidle_open (gpointer fname){	open_grf_file ((const char *) fname);	return FALSE;}static voidpreview_file (char *display, char *fname){	GtkTextBuffer *buf;	char *ext;	if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (W(preview_toggle))))		return;	ext = strrchr (display, '.');	if (!ext) return;	ext = g_utf8_strup (ext, -1);	buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (W(text_preview)));	gtk_text_buffer_set_text (buf, "", 0);	gtk_image_set_from_file (GTK_IMAGE (W(image_preview)), NULL);	if (strcmp (ext, ".TXT") == 0 || strcmp (ext, ".XML") == 0) {		char *data, *text;		unsigned long size;		gsize strsize;		GrfError err;		(void *) data = grf_get (grf, fname, &size, &err);		if (!data) {			set_status (grf_strerror (err));			goto end;		}		text = str_to_utf8 (data, &strsize);		size = strsize;		g_free (data);		gtk_text_buffer_set_text (buf, text, size);		gtk_notebook_set_current_page (GTK_NOTEBOOK (W(notebook1)), 0);		g_free (text);	} else if (strcmp (ext, ".BMP") == 0 || strcmp (ext, ".JPG") == 0	  || strcmp (ext, ".PNG") == 0 || strcmp (ext, ".GIF") == 0) {		char *data, *tmpfile = NULL;		unsigned long size;		GrfError err;		GError *gerr = NULL;		int fd;		(void *) data = grf_get (grf, fname, &size, &err);		if (!data) {			set_status (grf_strerror (err));			goto end;		}		if ((fd = g_file_open_tmp ("grftoolXXXXXX", &tmpfile, &gerr)) == -1) {			show_error (_("Unable to create a temporary file: %s"),				gerr->message);			g_error_free (gerr);			goto end;		}		write (fd, data, size);		close (fd);		gtk_image_set_from_file (GTK_IMAGE (W(image_preview)), tmpfile);		remove (tmpfile);		g_free (tmpfile);		gtk_notebook_set_current_page (GTK_NOTEBOOK (W(notebook1)), 1);	} else		gtk_notebook_set_current_page (GTK_NOTEBOOK (W(notebook1)), 0);	end:	g_free (ext);}static gpointerextract_thread (gpointer user_data){	GList *args = user_data;	const char *savedir = g_list_nth_data (args, 0);	GList *files = g_list_nth_data (args, 1);	GList *indices = g_list_nth_data (args, 2);	GList *l, *f, *dirs = NULL;	char *dir;	unsigned long failed = 0, max = 0;	gboolean stop = FALSE;	GTimer *timer = NULL;	g_list_free (args);	/* Generate a list of unique subdirectories */	for (l = files; l; l = l->next) {		char *p;		/* Convert paths to Unix paths */		for (p = (char *) l->data; *p; p++) if (*p == '\\') *p = G_DIR_SEPARATOR;		dir = g_path_get_dirname ((gchar *) l->data);		if (!g_list_find_custom (dirs, dir, (GCompareFunc) g_ascii_strcasecmp)) {			dirs = g_list_prepend (dirs, dir);			max++;		} else			g_free (dir);	}	g_static_mutex_lock (&extractProgressM);	extractProgress.max = max;	extractProgress.status = STATUS_MKDIR;	g_static_mutex_unlock (&extractProgressM);	/* Create the subdirectories */	dirs = g_list_sort (dirs, (GCompareFunc) g_ascii_strcasecmp);	dirs = g_list_reverse (dirs);	for (l = dirs; l; l = l->next) {		dir = g_build_filename (G_DIR_SEPARATOR_S, savedir, (char *) l->data, NULL);		mkdirs (dir);		g_free (dir);		g_static_mutex_lock (&extractProgressM);		extractProgress.current++;		stop = extractProgress.stop;		g_static_mutex_unlock (&extractProgressM);	}	g_list_foreach (dirs, (GFunc) g_free, NULL);	g_list_free (dirs);	if (stop) goto end;	g_static_mutex_lock (&extractProgressM);	extractProgress.current = 0;	extractProgress.max = g_list_length (files);	extractProgress.status = STATUS_EXTRACT;	stop = extractProgress.stop;	g_static_mutex_unlock (&extractProgressM);	if (stop) goto end;	timer = g_timer_new ();	g_timer_start (timer);	/* Start the actual extraction */	for (l = indices, f = files; l; l = l->next, f = f->next) {		unsigned long i;		char *fname;		i = GPOINTER_TO_INT (l->data);		fname = g_build_filename (savedir, (char *) f->data, NULL);		if (!grf_index_extract (grf, i, fname, NULL))			failed++;		g_free (fname);		g_static_mutex_lock (&extractProgressM);		extractProgress.current++;		strncpy (extractProgress.file, grf->files[i].name, PATH_MAX - 1);		stop = extractProgress.stop;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -