📄 util.c
字号:
/*================================================================== * util.c - Utility functions * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * 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., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green <jgreen@users.sourceforge.net> * Smurf homepage: http://smurf.sourceforge.net *==================================================================*/#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include <gtk/gtk.h>#include "util.h"#include "pixmap.h"#include "i18n.h"#include "widgets/popdog.h"static GString *log_buf = NULL;static gint log_maxsize = GBUF_MAXSIZE;gboolean log_viewactive = FALSE; /* log window active? */gint log_poplevel = LogBad;gint log_groups = 0; /* # of nested log groups */gint log_grp_popup_lvl; /* lowest log level to cause popup */gint log_grp_highest_lvl; /* highest occured log level in open group */static GtkWidget *log_view_widg = NULL; /* currently active error view widg *//* unique dialog system data */typedef struct { GtkWidget *dialog; gchar *strkey; int key2;} UniqueDialogKey;gboolean unique_dialog_inited = FALSE;GArray *unique_dialog_array;static void util_cb_quick_popup_btn_clicked (GtkWidget *btn, gpointer userdata);static void util_unique_dialog_init (void);static void util_cb_waitfor_widget_destroyed (GtkWidget *widg, gpointer data);static void log_view_cb_destroy (void);/* pops up a dialog for user input, for simple questionsThe arguments should be:msg, btn1label, btn1func (UtilQuickFunc *), btn1data, btn2label, btn2func...if btn1label = NULL then a single "OK" button is created,otherwise a button is created for each label that is provided with acallback to btnNfunc, if btnNfunc is NULL then gtk_widget_destroy is used */GtkWidget *util_quick_popup (gchar * msg, gchar * btn1, ...){ va_list args; GtkWidget *popdog; GtkWidget *lbl; GtkWidget *btn; gchar *s; UtilQuickFunc func; gpointer userdata; gint index = 1; popdog = gtk_popdog_new (NULL); gtk_window_set_modal (GTK_WINDOW (popdog), TRUE); lbl = gtk_label_new (msg); gtk_widget_show (lbl); gtk_box_pack_start (GTK_BOX (GTK_POPDOG (popdog)->vbox), lbl, FALSE, FALSE, 0); va_start (args, btn1); if (!btn1) { btn = gtk_button_new_with_label (_("OK")); gtk_signal_connect_object (GTK_OBJECT (btn), "clicked", (GtkSignalFunc) gtk_widget_destroy, GTK_OBJECT (popdog)); gtk_widget_show (btn); gtk_box_pack_start (GTK_BOX (GTK_POPDOG (popdog)->action_area), btn, FALSE, FALSE, 0); } else { s = btn1; do { btn = gtk_button_new_with_label (s); func = va_arg (args, UtilQuickFunc); userdata = va_arg (args, gpointer); if (!func) /* use destroy (popdog) as callback if !func */ { func = (UtilQuickFunc)gtk_widget_destroy; userdata = popdog; } gtk_object_set_data (GTK_OBJECT (btn), "parent", popdog); gtk_object_set_data (GTK_OBJECT (btn), "func", func); gtk_object_set_data (GTK_OBJECT (btn), "index", GINT_TO_POINTER (index++)); gtk_signal_connect (GTK_OBJECT (btn), "clicked", util_cb_quick_popup_btn_clicked, userdata); gtk_widget_show (btn); gtk_box_pack_start (GTK_BOX (GTK_POPDOG (popdog)->action_area), btn, FALSE, FALSE, 0); } while ((s = va_arg (args, gchar *))); } va_end (args); gtk_widget_show (popdog); return (popdog);}static voidutil_cb_quick_popup_btn_clicked (GtkWidget *btn, gpointer userdata){ GtkWidget *parent; UtilQuickFunc func; gint index; index = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (btn), "index")); util_widget_action (btn, GINT_TO_POINTER (index)); func = gtk_object_get_data (GTK_OBJECT (btn), "func"); parent = gtk_object_get_data (GTK_OBJECT (btn), "parent"); (*func) (userdata, parent);}/* Unique dialog system is for allowing unique non-modal dialogs for resources identified by a string key and an optional additional integer key, attempting to open up a second dialog for the same resource will cause the first dialog to be brought to the front of view and no additional dialog will be created */static voidutil_unique_dialog_init (void){ unique_dialog_array = g_array_new (FALSE, FALSE, sizeof (UniqueDialogKey)); unique_dialog_inited = TRUE;}/* looks up a unique dialog widget by its keys, returns the widget or NULL */GtkWidget *util_lookup_unique_dialog (gchar *strkey, gint key2){ UniqueDialogKey *udkeyp; gint i; if (!unique_dialog_inited) util_unique_dialog_init (); for (i = unique_dialog_array->len - 1; i >= 0; i--) { udkeyp = &g_array_index (unique_dialog_array, UniqueDialogKey, i); if ((udkeyp->strkey == strkey || strcmp (udkeyp->strkey, strkey) == 0) && udkeyp->key2 == key2) return (udkeyp->dialog); } return (NULL);}/* register a unique dialog, if a dialog already exists with the same keys, then activate the existing dialog and return FALSE, otherwise register the new dialog and return TRUE */gbooleanutil_register_unique_dialog (GtkWidget *dialog, gchar *strkey, gint key2){ UniqueDialogKey udkey; GtkWidget *widg; if (!unique_dialog_inited) util_unique_dialog_init (); if ((widg = util_lookup_unique_dialog (strkey, key2))) { gtk_widget_activate (widg); return (FALSE); } /* tell window manager to remember dialog state (position etc) */ gtk_window_set_wmclass (GTK_WINDOW (dialog), strkey, "Smurf"); udkey.dialog = dialog; udkey.strkey = strkey; udkey.key2 = key2; g_array_append_val (unique_dialog_array, udkey); gtk_signal_connect (GTK_OBJECT (dialog), "destroy", (GtkSignalFunc)util_unregister_unique_dialog, NULL); return (TRUE);}voidutil_unregister_unique_dialog (GtkWidget *dialog){ UniqueDialogKey *udkeyp; gint i; if (!unique_dialog_inited) util_unique_dialog_init (); for (i = unique_dialog_array->len - 1; i >= 0; i--) { udkeyp = &g_array_index (unique_dialog_array, UniqueDialogKey, i); if (udkeyp->dialog == dialog) break; } if (i >= 0) g_array_remove_index (unique_dialog_array, i);}/* activate (or raise) a unique dialog into view */gbooleanutil_activate_unique_dialog (gchar *strkey, gint key2){ GtkWidget *dialog; if ((dialog = util_lookup_unique_dialog (strkey, key2))) { gdk_window_raise (GTK_WIDGET (dialog)->window); return (TRUE); } return (FALSE);}/* run gtk_main loop until the GtkObject data property "action" is != NULL, mates nicely with util_quick_popup, returns value of "action". Useful for complex routines that require a lot of user dialog interaction. Rather than having to save state info and exit and return to a routine, a call to this routine can be made which will wait for the user's choice and return the index of the button (or other user specified value), -1 if the widget was destroyed or -2 if gtk_main_quit was called */gpointerutil_waitfor_widget_action (GtkWidget *widg){ GQuark quark; gpointer val = NULL; gboolean destroyed = FALSE; guint sigid; /* initialize the action variable to NULL */ quark = gtk_object_data_force_id ("action"); gtk_object_set_data_by_id (GTK_OBJECT (widg), quark, NULL); /* already passing one variable to destroy signal handler, so bind this one as a GtkObject data item, will notify us if widget was destroyed */ gtk_object_set_data (GTK_OBJECT (widg), "_destroyed", &destroyed); /* val is set to "action" by util_cb_waitfor_widget_destroyed if the widget we are waiting for gets killed */ sigid = gtk_signal_connect (GTK_OBJECT (widg), "destroy", GTK_SIGNAL_FUNC (util_cb_waitfor_widget_destroyed), &val); do { if (gtk_main_iteration ()) /* run the gtk main loop, wait if no events */ val = GINT_TO_POINTER (-2); /* gtk_main_quit was called, return -2 */ else if (val == NULL) /* check the "action" data property */ val = gtk_object_get_data_by_id (GTK_OBJECT (widg), quark); } while (val == NULL); /* loop until "action" is set */ if (!destroyed) gtk_signal_disconnect (GTK_OBJECT (widg), sigid); return (val);}static voidutil_cb_waitfor_widget_destroyed (GtkWidget *widg, gpointer data){ gpointer *val = data; gpointer action; gboolean *destroyed; action = gtk_object_get_data (GTK_OBJECT (widg), "action"); destroyed = gtk_object_get_data (GTK_OBJECT (widg), "_destroyed"); *destroyed = TRUE; if (action) *val = action; else *val = GINT_TO_POINTER (-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -