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

📄 fkeys.c

📁 The major functionality added in this release includes: - Rootless mode in X11 - Widget Templt
💻 C
📖 第 1 页 / 共 3 页
字号:
/* X-Chat * Copyright (C) 1998 Peter Zelezny. * * 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 */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <string.h>#include "../../config.h"#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include <fcntl.h>#include <ctype.h>#include "fe-gtk.h"#include "../common/xchat.h"#include "../common/xchatc.h"#include "../common/cfgfiles.h"#include "../common/userlist.h"#include "../common/outbound.h"#include "../common/util.h"#include "../common/text.h"#include <gdk/gdkkeysyms.h>#include "gtkutil.h"#include "menu.h"#include "xtext.h"#include "wins.h"#include "palette.h"#include "maingui.h"#include "textgui.h"#include "fkeys.h"static int tab_nick_comp (GtkWidget * t, int shift);static void nick_comp_chng (GtkWidget * t, int updown);static void replace_handle (GtkWidget * wid);/***************** Key Binding Code ******************//* NOTES:   To add a new action:   1) inc KEY_MAX_ACTIONS   2) write the function at the bottom of this file (with all the others)   FIXME: Write about calling and returning   3) Add it to key_actions   --AGL *//* Remember that the *number* of actions is this *plus* 1 --AGL */#define KEY_MAX_ACTIONS 12/* These are cp'ed from history.c --AGL */#define STATE_SHIFT     GDK_SHIFT_MASK#define	STATE_ALT	GDK_MOD1_MASK#define STATE_CTRL	GDK_CONTROL_MASKstruct key_binding{	int keyval;						  /* GDK keynumber */	char *keyname;					  /* String with the name of the function */	int action;						  /* Index into key_actions */	int mod;							  /* Flags of STATE_* above */	char *data1, *data2;			  /* Pointers to strings, these must be freed */	struct key_binding *next;};struct key_action{	int (*handler) (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2,						 struct session * sess);	char *name;	char *help;};static int key_load_kbs (char *);static void key_load_defaults ();static void key_save_kbs (char *);static int key_action_handle_command (GtkWidget * wid, GdkEventKey * evt,												  char *d1, char *d2,												  struct session *sess);static int key_action_page_switch (GtkWidget * wid, GdkEventKey * evt,											  char *d1, char *d2, struct session *sess);int key_action_insert (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2,							  struct session *sess);static int key_action_scroll_page (GtkWidget * wid, GdkEventKey * evt,											  char *d1, char *d2, struct session *sess);static int key_action_set_buffer (GtkWidget * wid, GdkEventKey * evt,											 char *d1, char *d2, struct session *sess);static int key_action_history_up (GtkWidget * wid, GdkEventKey * evt,											 char *d1, char *d2, struct session *sess);static int key_action_history_down (GtkWidget * wid, GdkEventKey * evt,												char *d1, char *d2, struct session *sess);static int key_action_tab_comp (GtkWidget * wid, GdkEventKey * evt, char *d1,										  char *d2, struct session *sess);static int key_action_comp_chng (GtkWidget * wid, GdkEventKey * evt, char *d1,											char *d2, struct session *sess);static int key_action_replace (GtkWidget * wid, GdkEventKey * evt, char *d1,										 char *d2, struct session *sess);static int key_action_move_tab_left (GtkWidget * wid, GdkEventKey * evt,												 char *d1, char *d2,												 struct session *sess);static int key_action_move_tab_right (GtkWidget * wid, GdkEventKey * evt,												  char *d1, char *d2,												  struct session *sess);static int key_action_put_history (GtkWidget * wid, GdkEventKey * evt,												  char *d1, char *d2,												  struct session *sess);static GtkWidget *key_dialog;static struct key_binding *keys_root = NULL;static struct key_action key_actions[KEY_MAX_ACTIONS + 1] = {	{key_action_handle_command, "Run Command",	 N_("The \002Run Command\002 action runs the data in Data 1 as if it has been typed into the entry box where you pressed the key sequence. Thus it can contain text (which will be sent to the channel/person), commands or user commands. When run all \002\\n\002 characters in Data 1 are used to deliminate seperate commands so it is possible to run more than one command. If you want a \002\\\002 in the actual text run then enter \002\\\\\002")},	{key_action_page_switch, "Change Page",	 N_("The \002Change Page\002 command switches between pages in the notebook. Set Data 1 to the page you want to switch to. If Data 2 is set to anything then the switch will be relative to the current position")},	{key_action_insert, "Insert in Buffer",	 N_("The \002Insert in Buffer\002 command will insert the contents of Data 1 into the entry where the key sequence was pressed at the current cursor position")},	{key_action_scroll_page, "Scroll Page",	 N_("The \002Scroll Page\002 command scrolls the text widget up or down one page. If Data 1 is set to anything the page scrolls up, else it scrolls down")},	{key_action_set_buffer, "Set Buffer",	 N_("The \002Set Buffer\002 command sets the entry where the key sequence was entered to the contents of Data 1")},	{key_action_history_up, "Last Command",	 N_("The \002Last Command\002 command sets the entry to contain the last command entered - the same as pressing up in a shell")},	{key_action_history_down, "Next Command",	 N_("The \002Next Command\002 command sets the entry to contain the next command entered - the same as pressing down in a shell")},	{key_action_tab_comp, "Complete nick/command",	 N_("This command changes the text in the entry to finish an incomplete nickname or command. If Data 1 is set then double-tabbing in a string will select the last nick, not the next")},	{key_action_comp_chng, "Change Selected Nick",	 N_("This command scrolls up and down through the list of nicks. If Data 1 is set to anything it will scroll up, else it scrolls down")},	{key_action_replace, "Check For Replace",	 N_("This command checks the last work entered in the entry against the replace list and replaces it if it finds a match")},	{key_action_move_tab_left, "Move front tab left",	 N_("This command move the front tab left by one")},	{key_action_move_tab_right, "Move front tab right",	 N_("This command move the front tab right by one")},	{key_action_put_history, "Push input line into history",	 N_("Push input line into history but doesn't send to server")},};voidkey_init (){	keys_root = NULL;	if (key_load_kbs (NULL) == 1)	{		key_load_defaults ();		if (key_load_kbs (NULL) == 1)			gtkutil_simpledialog				(_("There was an error loading key bindings configuration"));	}}static char *key_get_key_name (int keyval){	return gdk_keyval_name (gdk_keyval_to_lower (keyval));}/* Ok, here are the NOTES   key_handle_key_press now handles all the key presses and history_keypress is now defunct. It goes thru the linked list keys_root and finds a matching key. It runs the action func and switches on these values:   0) Return   1) Find next   2) stop signal and return   * history_keypress is now dead (and gone)   * key_handle_key_press now takes its role   * All the possible actions are in a struct called key_actions (in fkeys.c)   * it is made of {function, name, desc}   * key bindings can pass 2 *text* strings to the handler. If more options are nee   ded a format can be put on one of these options   * key actions are passed {   the entry widget   the Gdk event   data 1   data 2   session struct   }   * key bindings are stored in a linked list of key_binding structs   * which looks like {   int keyval;  GDK keynumber   char *keyname;  String with the name of the function    int action;  Index into key_actions    int mod; Flags of STATE_* above    char *data1, *data2;  Pointers to strings, these must be freed    struct key_binding *next;   }   * remember that is (data1 || data2) != NULL then they need to be free()'ed   --AGL */intkey_handle_key_press (GtkWidget * wid, GdkEventKey * evt,							 struct session *sess){	struct key_binding *kb, *last = NULL;	int keyval = evt->keyval;	int mod, n;	mod = evt->state & (STATE_CTRL | STATE_ALT | STATE_SHIFT);	kb = keys_root;	while (kb)	{		if (kb->keyval == keyval && kb->mod == mod)		{			if (kb->action < 0 || kb->action > KEY_MAX_ACTIONS)				return 0;			/* Bump this binding to the top of the list */			if (last != NULL)			{				last->next = kb->next;				kb->next = keys_root;				keys_root = kb;			}			/* Run the function */			n = key_actions[kb->action].handler (wid, evt, kb->data1,															 kb->data2, sess);			switch (n)			{			case 0:				return 1;			case 2:				gtk_signal_emit_stop_by_name (GTK_OBJECT (wid),														"key_press_event");				return 1;			}		}		last = kb;		kb = kb->next;	}	/* check if it's a return or enter */	if ((evt->keyval == GDK_Return)		 || (evt->keyval == GDK_KP_Enter /*&& mod == 0*/))		handle_inputgad (wid, sess);	if (evt->keyval == GDK_KP_Enter)		gtk_signal_emit_stop_by_name (GTK_OBJECT (wid), "key_press_event");	return 1;}/* Walks keys_root and free()'s everything *//*static voidkey_free_all (){	struct key_binding *cur, *next;	cur = keys_root;	while (cur)	{		next = cur->next;		if (cur->data1)			free (cur->data1);		if (cur->data2)			free (cur->data2);		free (cur);		cur = next;	}	keys_root = NULL;}*//* Turns mod flags into a C-A-S string */static char *key_make_mod_str (int mod, char *buf){	int i = 0;	if (mod & STATE_CTRL)	{		if (i)			buf[i++] = '-';		buf[i++] = 'C';	}	if (mod & STATE_ALT)	{		if (i)			buf[i++] = '-';		buf[i++] = 'A';	}	if (mod & STATE_SHIFT)	{		if (i)			buf[i++] = '-';		buf[i++] = 'S';	}	buf[i] = 0;	return buf;}/* ***** GUI code here ******************* *//* NOTE: The key_dialog defin is above --AGL */static GtkWidget *key_dialog_act_menu, *key_dialog_kb_clist;static GtkWidget *key_dialog_tog_c, *key_dialog_tog_s, *key_dialog_tog_a;static GtkWidget *key_dialog_ent_key, *key_dialog_ent_d1, *key_dialog_ent_d2;static GtkWidget *key_dialog_text;static voidkey_load_defaults (){	char def[] =		/* This is the default config */		"A\nminus\nChange Page\nD1:-1\nD2:Relative\n\n"		"A\n9\nChange Page\nD1:9\nD2!\n\n"		"A\n8\nChange Page\nD1:8\nD2!\n\n"		"A\n7\nChange Page\nD1:7\nD2!\n\n"		"A\n6\nChange Page\nD1:6\nD2!\n\n"		"A\n5\nChange Page\nD1:5\nD2!\n\n"		"A\n4\nChange Page\nD1:4\nD2!\n\n"		"A\n3\nChange Page\nD1:3\nD2!\n\n"		"A\n2\nChange Page\nD1:2\nD2!\n\n"		"A\n1\nChange Page\nD1:1\nD2!\n\n"		"C\no\nInsert in Buffer\nD1:%O\nD2!\n\n"		"C\nb\nInsert in Buffer\nD1:%B\nD2!\n\n"		"C\nk\nInsert in Buffer\nD1:%C\nD2!\n\n"		"S\nNext\nChange Selected Nick\nD1!\nD2!\n\n"		"S\nPrior\nChange Selected Nick\nD1:Up\nD2!\n\n"		"None\nNext\nScroll Page\nD1!\nD2!\n\n"		"None\nPrior\nScroll Page\nD1:Up\nD2!\n\n"		"None\nDown\nNext Command\nD1!\nD2!\n\n"		"None\nUp\nLast Command\nD1!\nD2!\n\n"		"None\nTab\nComplete nick/command\nD1!\nD2!\n\n"		"None\nspace\nCheck For Replace\nD1!\nD2!\n\n"		"None\nReturn\nCheck For Replace\nD1!\nD2!\n\n"		"A\nequal\nChange Page\nD1:1\nD2:Relative\n\n"		"C\nTab\nComplete nick/command\nD1:Up\nD2!\n\n"		"A\nLeft\nMove front tab left\nD1!\nD2!\n\n"		"A\nRight\nMove front tab right\nD1!\nD2!\n\n";	char buf[512];	int fd;	snprintf (buf, 512, "%s/keybindings.conf", get_xdir ());	fd = open (buf, O_CREAT | O_TRUNC | O_WRONLY | OFLAGS, 0x180);	if (fd < 0)		/* ???!!! */		return;	write (fd, def, strlen (def));	close (fd);}static voidkey_dialog_close (){	key_dialog = NULL;	key_save_kbs (NULL);}static voidkey_dialog_add_new (GtkWidget * button, GtkCList * list){	gchar *strs[] = { "", _("<none>"), _("<none>"), _("<none>"), _("<none>") };	struct key_binding *kb;	kb = malloc (sizeof (struct key_binding));	kb->keyval = 0;	kb->keyname = NULL;	kb->action = -1;	kb->mod = 0;	kb->data1 = kb->data2 = NULL;	kb->next = keys_root;	keys_root = kb;	gtk_clist_set_row_data (GTK_CLIST (list),									gtk_clist_append (GTK_CLIST (list), strs), kb);}static voidkey_dialog_delete (GtkWidget * button, GtkCList * list){	struct key_binding *kb, *cur, *last;	int row = gtkutil_clist_selection ((GtkWidget *) list);	if (row != -1)	{		kb = gtk_clist_get_row_data (list, row);		cur = keys_root;		last = NULL;		while (cur)		{			if (cur == kb)			{				if (last)					last->next = kb->next;				else					keys_root = kb->next;				if (kb->data1)					free (kb->data1);				if (kb->data2)					free (kb->data2);				free (kb);				gtk_clist_remove (list, row);				return;			}			last = cur;			cur = cur->next;		}		printf (_("*** key_dialog_delete: couldn't find kb in list!\n"));		/*if (getenv ("XCHAT_DEBUG"))			abort ();*/	}}static voidkey_dialog_sel_act (GtkWidget * un, int num){	int row = gtkutil_clist_selection (key_dialog_kb_clist);	struct key_binding *kb;	if (row != -1)	{		kb = gtk_clist_get_row_data (GTK_CLIST (key_dialog_kb_clist), row);		kb->action = num;		gtk_clist_set_text (GTK_CLIST (key_dialog_kb_clist), row, 2,								  _(key_actions[num].name));		if (key_actions[num].help)		{			gtk_xtext_clear (GTK_XTEXT (key_dialog_text));			PrintTextRaw (key_dialog_text, _(key_actions[num].help), 0);		}	}}static voidkey_dialog_sel_row (GtkWidget * clist, gint row, gint column,						  GdkEventButton * evt, gpointer data){	struct key_binding *kb = gtk_clist_get_row_data (GTK_CLIST (clist), row);	if (kb == NULL)	{		printf ("*** key_dialog_sel_row: kb == NULL\n");		abort ();	}	if (kb->action > -1 && kb->action <= KEY_MAX_ACTIONS)	{		gtk_option_menu_set_history (GTK_OPTION_MENU (key_dialog_act_menu),											  kb->action);		if (key_actions[kb->action].help)		{			gtk_xtext_clear (GTK_XTEXT (key_dialog_text));			PrintTextRaw (key_dialog_text, _(key_actions[kb->action].help), 0);		}	}	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (key_dialog_tog_c),										  (kb->mod & STATE_CTRL) == STATE_CTRL);	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (key_dialog_tog_s),										  (kb->mod & STATE_SHIFT) == STATE_SHIFT);	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (key_dialog_tog_a),										  (kb->mod & STATE_ALT) == STATE_ALT);	if (kb->data1)		gtk_entry_set_text (GTK_ENTRY (key_dialog_ent_d1), kb->data1);	else		gtk_entry_set_text (GTK_ENTRY (key_dialog_ent_d1), "");	if (kb->data2)		gtk_entry_set_text (GTK_ENTRY (key_dialog_ent_d2), kb->data2);	else		gtk_entry_set_text (GTK_ENTRY (key_dialog_ent_d2), "");	if (kb->keyname)		gtk_entry_set_text (GTK_ENTRY (key_dialog_ent_key), kb->keyname);	else		gtk_entry_set_text (GTK_ENTRY (key_dialog_ent_key), "");}static voidkey_dialog_tog_key (GtkWidget * tog, int kstate){	int state = GTK_TOGGLE_BUTTON (tog)->active;	int row = gtkutil_clist_selection (key_dialog_kb_clist);	struct key_binding *kb;	char buf[32];	if (row == -1)		return;	kb = gtk_clist_get_row_data (GTK_CLIST (key_dialog_kb_clist), row);	if (state)		kb->mod |= kstate;	else		kb->mod &= ~kstate;	gtk_clist_set_text (GTK_CLIST (key_dialog_kb_clist), row, 0,							  key_make_mod_str (kb->mod, buf));}static GtkWidget *key_dialog_make_toggle (char *label, void *callback, void *option,								GtkWidget * box){	GtkWidget *wid;	wid = gtk_check_button_new_with_label (label);	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid), 0);	gtk_signal_connect (GTK_OBJECT (wid), "toggled",							  GTK_SIGNAL_FUNC (callback), option);	gtk_widget_show (wid);	gtk_box_pack_end (GTK_BOX (box), wid, 0, 0, 0);	return wid;}static GtkWidget *key_dialog_make_entry (char *label, char *act, void *callback, void *option,							  GtkWidget * box){	GtkWidget *wid, *hbox;;	hbox = gtk_hbox_new (0, 2);	if (label)	{		wid = gtk_label_new (label);		gtk_widget_show (wid);		gtk_box_pack_start (GTK_BOX (hbox), wid, 0, 0, 0);	}	wid = gtk_entry_new ();	if (act)	{		gtk_signal_connect (GTK_OBJECT (wid), act, GTK_SIGNAL_FUNC (callback),								  option);	}	gtk_box_pack_start (GTK_BOX (hbox), wid, 0, 0, 0);	gtk_widget_show (wid);	gtk_widget_show (hbox);	gtk_box_pack_start (GTK_BOX (box), hbox, 0, 0, 0);	return wid;}static voidkey_dialog_set_key (GtkWidget * entry, GdkEventKey * evt, void *none){	int row = gtkutil_clist_selection (key_dialog_kb_clist);	struct key_binding *kb;	gtk_entry_set_text (GTK_ENTRY (entry), "");	if (row == -1)		return;	kb = gtk_clist_get_row_data (GTK_CLIST (key_dialog_kb_clist), row);	kb->keyval = evt->keyval;	kb->keyname = key_get_key_name (kb->keyval);	gtk_clist_set_text (GTK_CLIST (key_dialog_kb_clist), row, 1, kb->keyname);	gtk_entry_set_text (GTK_ENTRY (entry), kb->keyname);	gtk_signal_emit_stop_by_name (GTK_OBJECT (entry), "key_press_event");}static voidkey_dialog_set_data (GtkWidget * entry, int d){	char *text = gtk_entry_get_text (GTK_ENTRY (entry));	int row = gtkutil_clist_selection (key_dialog_kb_clist);	struct key_binding *kb;	char *buf;	int len = strlen (text);	len++;	if (row == -1)		return;	kb = gtk_clist_get_row_data (GTK_CLIST (key_dialog_kb_clist), row);	if (d == 0)	{									  /* using data1 */		if (kb->data1)			free (kb->data1);		buf = (char *) malloc (len);		memcpy (buf, text, len);		kb->data1 = buf;		gtk_clist_set_text (GTK_CLIST (key_dialog_kb_clist), row, 3, text);	} else	{		if (kb->data2)			free (kb->data2);		buf = (char *) malloc (len);		memcpy (buf, text, len);		kb->data2 = buf;		gtk_clist_set_text (GTK_CLIST (key_dialog_kb_clist), row, 4, text);	}}voidkey_dialog_show (){	GtkWidget *vbox, *hbox, *list, *vbox2, *wid, *wid2, *wid3, *hbox2;	struct key_binding *kb;	gchar *titles[] = { _("Mod"), _("Key"), _("Action"), "1", "2" };	char temp[32];

⌨️ 快捷键说明

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