mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-06-11 17:30:18 +00:00
Compare commits
12 Commits
tray-iconi
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb08b19c0d | ||
|
|
7497919e8f | ||
|
|
41cbe7b31c | ||
| 425e951341 | |||
| 2e4a0b92fc | |||
| 9f839579e2 | |||
| 900066b9d4 | |||
| 97534b0670 | |||
|
|
62672ade04 | ||
| b22e1c1ccc | |||
|
|
1b8e60c26d | ||
| 035dfdd332 |
@@ -518,6 +518,7 @@ const struct prefs vars[] =
|
|||||||
{"irc_conf_mode", P_OFFINT (hex_irc_conf_mode), TYPE_BOOL},
|
{"irc_conf_mode", P_OFFINT (hex_irc_conf_mode), TYPE_BOOL},
|
||||||
{"irc_extra_hilight", P_OFFSET (hex_irc_extra_hilight), TYPE_STR},
|
{"irc_extra_hilight", P_OFFSET (hex_irc_extra_hilight), TYPE_STR},
|
||||||
{"irc_hide_nickchange", P_OFFINT (hex_irc_hide_nickchange), TYPE_BOOL},
|
{"irc_hide_nickchange", P_OFFINT (hex_irc_hide_nickchange), TYPE_BOOL},
|
||||||
|
{"irc_hide_join_part_hostmask", P_OFFINT (hex_irc_hide_join_part_hostmask), TYPE_BOOL},
|
||||||
{"irc_hide_version", P_OFFINT (hex_irc_hide_version), TYPE_BOOL},
|
{"irc_hide_version", P_OFFINT (hex_irc_hide_version), TYPE_BOOL},
|
||||||
{"irc_hidehost", P_OFFINT (hex_irc_hidehost), TYPE_BOOL},
|
{"irc_hidehost", P_OFFINT (hex_irc_hidehost), TYPE_BOOL},
|
||||||
{"irc_id_ntext", P_OFFSET (hex_irc_id_ntext), TYPE_STR},
|
{"irc_id_ntext", P_OFFSET (hex_irc_id_ntext), TYPE_STR},
|
||||||
|
|||||||
@@ -3462,28 +3462,45 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|||||||
int use_ssl = FALSE;
|
int use_ssl = FALSE;
|
||||||
#endif
|
#endif
|
||||||
int is_url = TRUE;
|
int is_url = TRUE;
|
||||||
|
int no_proxy = FALSE;
|
||||||
server *serv = sess->server;
|
server *serv = sess->server;
|
||||||
ircnet *net = NULL;
|
ircnet *net = NULL;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
/* BitchX uses -ssl, mIRC uses -e, let's support both */
|
if (g_strcmp0 (word[2 + offset], "-ssl") == 0 || g_strcmp0 (word[2 + offset], "-e") == 0)
|
||||||
if (g_strcmp0 (word[2], "-ssl") == 0 || g_strcmp0 (word[2], "-e") == 0)
|
{
|
||||||
{
|
use_ssl = TRUE;
|
||||||
use_ssl = TRUE;
|
use_ssl_noverify = FALSE;
|
||||||
offset++; /* args move up by 1 word */
|
offset++;
|
||||||
}
|
}
|
||||||
else if (g_strcmp0 (word[2], "-ssl-noverify") == 0)
|
else if (g_strcmp0 (word[2 + offset], "-ssl-noverify") == 0)
|
||||||
{
|
{
|
||||||
use_ssl = TRUE;
|
use_ssl = TRUE;
|
||||||
use_ssl_noverify = TRUE;
|
use_ssl_noverify = TRUE;
|
||||||
offset++; /* args move up by 1 word */
|
offset++;
|
||||||
}
|
}
|
||||||
else if (g_strcmp0 (word[2], "-insecure") == 0)
|
else if (g_strcmp0 (word[2 + offset], "-insecure") == 0)
|
||||||
{
|
{
|
||||||
use_ssl = FALSE;
|
use_ssl = FALSE;
|
||||||
offset++; /* args move up by 1 word */
|
use_ssl_noverify = FALSE;
|
||||||
}
|
offset++;
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
if (g_strcmp0 (word[2 + offset], "-noproxy") == 0)
|
||||||
|
{
|
||||||
|
no_proxy = TRUE;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serv->dont_use_proxy = no_proxy;
|
||||||
|
|
||||||
if (!parse_irc_url (word[2 + offset], &server_name, &port, &channel, &key, &use_ssl))
|
if (!parse_irc_url (word[2 + offset], &server_name, &port, &channel, &key, &use_ssl))
|
||||||
{
|
{
|
||||||
@@ -3584,10 +3601,18 @@ cmd_servchan (struct session *sess, char *tbuf, char *word[],
|
|||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
if (g_strcmp0 (word[2], "-ssl") == 0 || g_strcmp0 (word[2], "-ssl-noverify") == 0 || g_strcmp0 (word[2], "-insecure") == 0)
|
if (g_strcmp0 (word[2 + offset], "-ssl") == 0 || g_strcmp0 (word[2 + offset], "-ssl-noverify") == 0 || g_strcmp0 (word[2 + offset], "-insecure") == 0)
|
||||||
offset++;
|
offset++;
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
if (g_strcmp0 (word[2 + offset], "-noproxy") == 0)
|
||||||
|
offset++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (*word[4 + offset])
|
if (*word[4 + offset])
|
||||||
{
|
{
|
||||||
@@ -4119,17 +4144,17 @@ const struct commands xc_cmds[] = {
|
|||||||
{"SEND", cmd_send, 0, 0, 1, N_("SEND <nick> [<file>]")},
|
{"SEND", cmd_send, 0, 0, 1, N_("SEND <nick> [<file>]")},
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
{"SERVCHAN", cmd_servchan, 0, 0, 1,
|
{"SERVCHAN", cmd_servchan, 0, 0, 1,
|
||||||
N_("SERVCHAN [-insecure|-ssl|-ssl-noverify] <host> <port> <channel>, connects and joins a channel using ssl unless otherwise specified")},
|
N_("SERVCHAN [-noproxy] [-insecure|-ssl|-ssl-noverify] <host> <port> <channel>, connects and joins a channel using ssl unless otherwise specified")},
|
||||||
#else
|
#else
|
||||||
{"SERVCHAN", cmd_servchan, 0, 0, 1,
|
{"SERVCHAN", cmd_servchan, 0, 0, 1,
|
||||||
N_("SERVCHAN <host> <port> <channel>, connects and joins a channel")},
|
N_("SERVCHAN [-noproxy] <host> <port> <channel>, connects and joins a channel")},
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
{"SERVER", cmd_server, 0, 0, 1,
|
{"SERVER", cmd_server, 0, 0, 1,
|
||||||
N_("SERVER [-insecure|-ssl|-ssl-noverify] <host> [<port>] [<password>], connects to a server using ssl unless otherwise specified, the default port is 6697 for ssl connections and 6667 for insecure connections")},
|
N_("SERVER [-noproxy] [-insecure|-ssl|-ssl-noverify] <host> [<port>] [<password>], connects to a server using ssl unless otherwise specified, the default port is 6697 for ssl connections and 6667 for insecure connections")},
|
||||||
#else
|
#else
|
||||||
{"SERVER", cmd_server, 0, 0, 1,
|
{"SERVER", cmd_server, 0, 0, 1,
|
||||||
N_("SERVER <host> [<port>] [<password>], connects to a server, the default port is 6667")},
|
N_("SERVER [-noproxy] <host> [<port>] [<password>], connects to a server, the default port is 6667")},
|
||||||
#endif
|
#endif
|
||||||
{"SET", cmd_set, 0, 0, 1, N_("SET [-e] [-off|-on] [-quiet] <variable> [<value>]")},
|
{"SET", cmd_set, 0, 0, 1, N_("SET [-e] [-off|-on] [-quiet] <variable> [<value>]")},
|
||||||
{"SETCURSOR", cmd_setcursor, 0, 0, 1, N_("SETCURSOR [-|+]<position>, reposition the cursor in the inputbox")},
|
{"SETCURSOR", cmd_setcursor, 0, 0, 1, N_("SETCURSOR [-|+]<position>, reposition the cursor in the inputbox")},
|
||||||
|
|||||||
@@ -522,7 +522,7 @@ ssl_cb_verify (int ok, X509_STORE_CTX * ctx)
|
|||||||
X509 *current_cert = X509_STORE_CTX_get_current_cert (ctx);
|
X509 *current_cert = X509_STORE_CTX_get_current_cert (ctx);
|
||||||
|
|
||||||
if (!current_cert)
|
if (!current_cert)
|
||||||
return TRUE;
|
return ok;
|
||||||
|
|
||||||
X509_NAME_oneline (X509_get_subject_name (current_cert),
|
X509_NAME_oneline (X509_get_subject_name (current_cert),
|
||||||
subject, sizeof (subject));
|
subject, sizeof (subject));
|
||||||
@@ -534,13 +534,21 @@ ssl_cb_verify (int ok, X509_STORE_CTX * ctx)
|
|||||||
g_snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
|
g_snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
|
||||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
|
EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
|
||||||
|
|
||||||
return TRUE;
|
if (!ok)
|
||||||
|
{
|
||||||
|
int err = X509_STORE_CTX_get_error (ctx);
|
||||||
|
g_snprintf (buf, sizeof (buf), "* Verify E: %s (%d)",
|
||||||
|
X509_verify_cert_error_string (err), err);
|
||||||
|
EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ssl_do_connect (server * serv)
|
ssl_do_connect (server * serv)
|
||||||
{
|
{
|
||||||
char buf[256]; // ERR_error_string() MUST have this size
|
char buf[256];
|
||||||
|
|
||||||
g_sess = serv->server_session;
|
g_sess = serv->server_session;
|
||||||
|
|
||||||
@@ -559,9 +567,10 @@ ssl_do_connect (server * serv)
|
|||||||
if (SSL_connect (serv->ssl) <= 0)
|
if (SSL_connect (serv->ssl) <= 0)
|
||||||
{
|
{
|
||||||
char err_buf[128];
|
char err_buf[128];
|
||||||
int err;
|
int err, ssl_err;
|
||||||
|
|
||||||
g_sess = NULL;
|
g_sess = NULL;
|
||||||
|
ssl_err = SSL_get_error (serv->ssl, -1);
|
||||||
if ((err = ERR_get_error ()) > 0)
|
if ((err = ERR_get_error ()) > 0)
|
||||||
{
|
{
|
||||||
ERR_error_string (err, err_buf);
|
ERR_error_string (err, err_buf);
|
||||||
@@ -571,6 +580,8 @@ ssl_do_connect (server * serv)
|
|||||||
|
|
||||||
if (ERR_GET_REASON (err) == SSL_R_WRONG_VERSION_NUMBER)
|
if (ERR_GET_REASON (err) == SSL_R_WRONG_VERSION_NUMBER)
|
||||||
PrintText (serv->server_session, _("Are you sure this is a SSL capable server and port?\n"));
|
PrintText (serv->server_session, _("Are you sure this is a SSL capable server and port?\n"));
|
||||||
|
else if (ssl_err == SSL_ERROR_SSL)
|
||||||
|
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, "* TLS handshake rejected by protocol/certificate/cipher policy", NULL, NULL, NULL, 0);
|
||||||
|
|
||||||
server_cleanup (serv);
|
server_cleanup (serv);
|
||||||
|
|
||||||
@@ -649,29 +660,13 @@ ssl_do_connect (server * serv)
|
|||||||
int hostname_err;
|
int hostname_err;
|
||||||
if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0)
|
if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0)
|
||||||
{
|
{
|
||||||
g_snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname? (%d)%s",
|
g_snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname (%d)",
|
||||||
hostname_err, serv->accept_invalid_cert ? " -- Ignored" : "");
|
hostname_err);
|
||||||
if (serv->accept_invalid_cert)
|
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0);
|
||||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0);
|
goto conn_fail;
|
||||||
else
|
|
||||||
goto conn_fail;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
|
|
||||||
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
|
|
||||||
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
|
||||||
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
|
|
||||||
case X509_V_ERR_CERT_HAS_EXPIRED:
|
|
||||||
if (serv->accept_invalid_cert)
|
|
||||||
{
|
|
||||||
g_snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",
|
|
||||||
X509_verify_cert_error_string (verify_error),
|
|
||||||
verify_error);
|
|
||||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
|
||||||
NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
g_snprintf (buf, sizeof (buf), "%s.? (%d)",
|
g_snprintf (buf, sizeof (buf), "%s.? (%d)",
|
||||||
X509_verify_cert_error_string (verify_error),
|
X509_verify_cert_error_string (verify_error),
|
||||||
|
|||||||
@@ -86,15 +86,17 @@ _SSL_context_init (void (*info_cb_func))
|
|||||||
|
|
||||||
SSLeay_add_ssl_algorithms ();
|
SSLeay_add_ssl_algorithms ();
|
||||||
SSL_load_error_strings ();
|
SSL_load_error_strings ();
|
||||||
ctx = SSL_CTX_new (SSLv23_client_method ());
|
ctx = SSL_CTX_new (TLS_client_method ());
|
||||||
|
|
||||||
SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_BOTH);
|
SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_BOTH);
|
||||||
SSL_CTX_set_timeout (ctx, 300);
|
SSL_CTX_set_timeout (ctx, 300);
|
||||||
SSL_CTX_set_options (ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3
|
SSL_CTX_set_options (ctx, SSL_OP_NO_COMPRESSION
|
||||||
|SSL_OP_NO_COMPRESSION
|
|
||||||
|SSL_OP_SINGLE_DH_USE|SSL_OP_SINGLE_ECDH_USE
|
|SSL_OP_SINGLE_DH_USE|SSL_OP_SINGLE_ECDH_USE
|
||||||
|SSL_OP_NO_TICKET
|
|SSL_OP_NO_TICKET
|
||||||
|SSL_OP_CIPHER_SERVER_PREFERENCE);
|
|SSL_OP_NO_RENEGOTIATION);
|
||||||
|
SSL_CTX_set_min_proto_version (ctx, TLS1_2_VERSION);
|
||||||
|
SSL_CTX_set_cipher_list (ctx, "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!DSS");
|
||||||
|
SSL_CTX_set_ciphersuites (ctx, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256");
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined (OPENSSL_NO_COMP) /* workaround for OpenSSL 0.9.8 */
|
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined (OPENSSL_NO_COMP) /* workaround for OpenSSL 0.9.8 */
|
||||||
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
|
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
|
||||||
@@ -311,7 +313,7 @@ _SSL_socket (SSL_CTX *ctx, int sd)
|
|||||||
#else
|
#else
|
||||||
method = SSL_CTX_get_ssl_method (ctx);
|
method = SSL_CTX_get_ssl_method (ctx);
|
||||||
#endif
|
#endif
|
||||||
if (method == SSLv23_client_method())
|
if (method == TLS_client_method())
|
||||||
SSL_set_connect_state (ssl);
|
SSL_set_connect_state (ssl);
|
||||||
else
|
else
|
||||||
SSL_set_accept_state(ssl);
|
SSL_set_accept_state(ssl);
|
||||||
|
|||||||
@@ -1809,12 +1809,97 @@ format_event (session *sess, int index, char **args, char *o, gsize sizeofo, uns
|
|||||||
o[0] = 0;
|
o[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
text_event_without_hostmask_format (const char *format, int host_arg)
|
||||||
|
{
|
||||||
|
char token[3];
|
||||||
|
const char *arg;
|
||||||
|
const char *open;
|
||||||
|
const char *close;
|
||||||
|
const char *start;
|
||||||
|
char *out;
|
||||||
|
gsize prefix_len;
|
||||||
|
|
||||||
|
g_snprintf (token, sizeof (token), "$%d", host_arg);
|
||||||
|
arg = strstr (format, token);
|
||||||
|
if (!arg)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
open = arg;
|
||||||
|
while (open > format && *open != '(' && *open != '\n')
|
||||||
|
open--;
|
||||||
|
|
||||||
|
close = arg + strlen (token);
|
||||||
|
while (*close && *close != ')' && *close != '\n')
|
||||||
|
close++;
|
||||||
|
|
||||||
|
if (*open != '(' || *close != ')')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
start = open;
|
||||||
|
if (start > format && start[-1] == ' ')
|
||||||
|
start--;
|
||||||
|
|
||||||
|
prefix_len = start - format;
|
||||||
|
out = g_malloc (prefix_len + strlen (close + 1) + 1);
|
||||||
|
memcpy (out, format, prefix_len);
|
||||||
|
strcpy (out + prefix_len, close + 1);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
display_event_string (session *sess, int event, char **args, char *format,
|
||||||
|
unsigned int stripcolor_args, time_t timestamp)
|
||||||
|
{
|
||||||
|
char *compiled;
|
||||||
|
char *saved;
|
||||||
|
char o[4096];
|
||||||
|
int max_arg;
|
||||||
|
|
||||||
|
if (pevt_build_string (format, &compiled, &max_arg) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
saved = pntevts[event];
|
||||||
|
pntevts[event] = compiled;
|
||||||
|
format_event (sess, event, args, o, sizeof (o), stripcolor_args);
|
||||||
|
pntevts[event] = saved;
|
||||||
|
g_free (compiled);
|
||||||
|
|
||||||
|
if (o[0])
|
||||||
|
PrintTextTimeStamp (sess, o, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
display_event (session *sess, int event, char **args,
|
display_event (session *sess, int event, char **args,
|
||||||
unsigned int stripcolor_args, time_t timestamp)
|
unsigned int stripcolor_args, time_t timestamp)
|
||||||
{
|
{
|
||||||
char o[4096];
|
char o[4096];
|
||||||
format_event (sess, event, args, o, sizeof (o), stripcolor_args);
|
char *format;
|
||||||
|
char *host;
|
||||||
|
int host_arg;
|
||||||
|
|
||||||
|
if (prefs.hex_irc_hide_join_part_hostmask &&
|
||||||
|
(event == XP_TE_JOIN || event == XP_TE_PART || event == XP_TE_PARTREASON))
|
||||||
|
{
|
||||||
|
host_arg = event == XP_TE_JOIN ? 3 : 2;
|
||||||
|
format = text_event_without_hostmask_format (pntevts_text[event], host_arg);
|
||||||
|
if (format)
|
||||||
|
{
|
||||||
|
display_event_string (sess, event, args, format, stripcolor_args, timestamp);
|
||||||
|
g_free (format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
host = args[host_arg];
|
||||||
|
args[host_arg] = "";
|
||||||
|
format_event (sess, event, args, o, sizeof (o), stripcolor_args);
|
||||||
|
args[host_arg] = host;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format_event (sess, event, args, o, sizeof (o), stripcolor_args);
|
||||||
|
}
|
||||||
|
|
||||||
if (o[0])
|
if (o[0])
|
||||||
PrintTextTimeStamp (sess, o, timestamp);
|
PrintTextTimeStamp (sess, o, timestamp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ struct zoitechatprefs
|
|||||||
unsigned int hex_irc_conf_mode;
|
unsigned int hex_irc_conf_mode;
|
||||||
unsigned int hex_irc_hidehost;
|
unsigned int hex_irc_hidehost;
|
||||||
unsigned int hex_irc_hide_nickchange;
|
unsigned int hex_irc_hide_nickchange;
|
||||||
|
unsigned int hex_irc_hide_join_part_hostmask;
|
||||||
unsigned int hex_irc_hide_version;
|
unsigned int hex_irc_hide_version;
|
||||||
unsigned int hex_irc_invisible;
|
unsigned int hex_irc_invisible;
|
||||||
unsigned int hex_irc_logging;
|
unsigned int hex_irc_logging;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ void key_action_tab_clean (void);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Remember that the *number* of actions is this *plus* 1 --AGL */
|
/* Remember that the *number* of actions is this *plus* 1 --AGL */
|
||||||
#define KEY_MAX_ACTIONS 14
|
#define KEY_MAX_ACTIONS 16
|
||||||
|
|
||||||
struct key_binding
|
struct key_binding
|
||||||
{
|
{
|
||||||
@@ -142,6 +142,13 @@ static int key_action_move_tab_family_right (GtkWidget * wid, GdkEventKey * evt,
|
|||||||
static int key_action_put_history (GtkWidget * wid, GdkEventKey * evt,
|
static int key_action_put_history (GtkWidget * wid, GdkEventKey * evt,
|
||||||
char *d1, char *d2,
|
char *d1, char *d2,
|
||||||
struct session *sess);
|
struct session *sess);
|
||||||
|
static int key_action_menu_shortcut (GtkWidget * wid, GdkEventKey * evt,
|
||||||
|
char *d1, char *d2,
|
||||||
|
struct session *sess);
|
||||||
|
static int key_action_reopen_closed_tab (GtkWidget * wid, GdkEventKey * evt,
|
||||||
|
char *d1, char *d2,
|
||||||
|
struct session *sess);
|
||||||
|
|
||||||
|
|
||||||
static GSList *keybind_list = NULL;
|
static GSList *keybind_list = NULL;
|
||||||
|
|
||||||
@@ -260,7 +267,7 @@ static const struct key_action key_actions[KEY_MAX_ACTIONS + 1] = {
|
|||||||
{key_action_handle_command, "Run Command",
|
{key_action_handle_command, "Run Command",
|
||||||
N_("The \002Run Command\002 action runs the data in Data 1 as if it had 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. Escapes in Data 1 are interpreted (for example \002\\n\002, \002\\r\002, \002\\t\002, \002\\xNN\002 and \002\\\\\002), so it is possible to run more than one command by using newlines.")},
|
N_("The \002Run Command\002 action runs the data in Data 1 as if it had 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. Escapes in Data 1 are interpreted (for example \002\\n\002, \002\\r\002, \002\\t\002, \002\\xNN\002 and \002\\\\\002), so it is possible to run more than one command by using newlines.")},
|
||||||
{key_action_page_switch, "Change Page",
|
{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. Set Data 1 to auto to switch to the page with the most recent and important activity (queries first, then channels with hilight, channels with dialogue, channels with other data)")},
|
N_("The \002Change Page\002 command switches between pages in the notebook. Set Data 1 to the page number, channel name, network/channel, or auto. If Data 2 is set to anything then numeric switches are relative to the current position. Auto switches to the page with the most recent and important activity (queries first, then channels with hilight, channels with dialogue, channels with other data)")},
|
||||||
{key_action_insert, "Insert in Buffer",
|
{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. Escapes in Data 1 are interpreted (for example \002\\n\002, \002\\r\002, \002\\t\002, \002\\xNN\002 and \002\\\\\002).")},
|
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. Escapes in Data 1 are interpreted (for example \002\\n\002, \002\\r\002, \002\\t\002, \002\\xNN\002 and \002\\\\\002).")},
|
||||||
{key_action_scroll_page, "Scroll Page",
|
{key_action_scroll_page, "Scroll Page",
|
||||||
@@ -287,6 +294,10 @@ static const struct key_action key_actions[KEY_MAX_ACTIONS + 1] = {
|
|||||||
N_("This command moves the current tab family to the right")},
|
N_("This command moves the current tab family to the right")},
|
||||||
{key_action_put_history, "Push input line into history",
|
{key_action_put_history, "Push input line into history",
|
||||||
N_("Push input line into history but doesn't send to server")},
|
N_("Push input line into history but doesn't send to server")},
|
||||||
|
{key_action_menu_shortcut, "Menu Shortcut",
|
||||||
|
N_("Runs one of the built-in menu shortcuts. Set Data 1 to: network-list, new-server-tab, new-server-window, close, quit, menu-toggle, user-list-toggle, fullscreen-toggle, away-toggle, reset-marker, move-marker, copy-selection, search-text, search-next, search-previous or contents.")},
|
||||||
|
{key_action_reopen_closed_tab, "Reopen Closed Tab",
|
||||||
|
N_("Reopens the most recently closed channel tab")},
|
||||||
};
|
};
|
||||||
|
|
||||||
#define default_kb_cfg \
|
#define default_kb_cfg \
|
||||||
@@ -329,7 +340,86 @@ static const struct key_action key_actions[KEY_MAX_ACTIONS + 1] = {
|
|||||||
"ACCEL=<Alt>Right\nMove front tab right\nD1!\nD2!\n\n"\
|
"ACCEL=<Alt>Right\nMove front tab right\nD1!\nD2!\n\n"\
|
||||||
"ACCEL=<Primary><Shift>Page_Up\nMove tab family left\nD1!\nD2!\n\n"\
|
"ACCEL=<Primary><Shift>Page_Up\nMove tab family left\nD1!\nD2!\n\n"\
|
||||||
"ACCEL=<Primary><Shift>Page_Down\nMove tab family right\nD1!\nD2!\n\n"\
|
"ACCEL=<Primary><Shift>Page_Down\nMove tab family right\nD1!\nD2!\n\n"\
|
||||||
"ACCEL=F9\nRun Command\nD1:/GUI MENU TOGGLE\nD2!\n\n"
|
"ACCEL=<Primary>s\nMenu Shortcut\nD1:network-list\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary>t\nMenu Shortcut\nD1:new-server-tab\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary>n\nMenu Shortcut\nD1:new-server-window\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary>w\nMenu Shortcut\nD1:close\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary>q\nMenu Shortcut\nD1:quit\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary>F9\nMenu Shortcut\nD1:menu-toggle\nD2!\n\n"\
|
||||||
|
"ACCEL=F7\nMenu Shortcut\nD1:user-list-toggle\nD2!\n\n"\
|
||||||
|
"ACCEL=F11\nMenu Shortcut\nD1:fullscreen-toggle\nD2!\n\n"\
|
||||||
|
"ACCEL=<Alt>a\nMenu Shortcut\nD1:away-toggle\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary>m\nMenu Shortcut\nD1:reset-marker\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary><Shift>M\nMenu Shortcut\nD1:move-marker\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary><Shift>C\nMenu Shortcut\nD1:copy-selection\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary>f\nMenu Shortcut\nD1:search-text\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary>g\nMenu Shortcut\nD1:search-next\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary><Shift>G\nMenu Shortcut\nD1:search-previous\nD2!\n\n"\
|
||||||
|
"ACCEL=F1\nMenu Shortcut\nD1:contents\nD2!\n\n"\
|
||||||
|
"ACCEL=<Primary><Shift>T\nReopen Closed Tab\nD1!\nD2!\n\n"
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
key_builtin_data_match (char *line, char *data)
|
||||||
|
{
|
||||||
|
if (line[2] == '!')
|
||||||
|
return data == NULL || data[0] == 0;
|
||||||
|
|
||||||
|
if (line[2] == ':')
|
||||||
|
return !strcmp (&line[3], data ? data : "");
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
key_binding_is_builtin (struct key_binding *kb)
|
||||||
|
{
|
||||||
|
char *buf, *ibuf;
|
||||||
|
char *action;
|
||||||
|
int pnt = 0;
|
||||||
|
int state = 0;
|
||||||
|
gboolean match = FALSE;
|
||||||
|
gboolean d1_match = FALSE;
|
||||||
|
off_t size;
|
||||||
|
|
||||||
|
if (kb->action < 0 || kb->action > KEY_MAX_ACTIONS)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
action = key_actions[kb->action].name;
|
||||||
|
ibuf = g_strdup (default_kb_cfg);
|
||||||
|
size = strlen (default_kb_cfg);
|
||||||
|
|
||||||
|
while (buf_get_line (ibuf, &buf, &pnt, size))
|
||||||
|
{
|
||||||
|
if (strlen (buf) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
match = !strcmp (buf, action);
|
||||||
|
state = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
d1_match = match && key_builtin_data_match (buf, kb->data1);
|
||||||
|
state = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (d1_match && key_builtin_data_match (buf, kb->data2))
|
||||||
|
{
|
||||||
|
g_free (ibuf);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
state = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (ibuf);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
key_init ()
|
key_init ()
|
||||||
@@ -443,28 +533,6 @@ key_handle_key_press (GtkWidget *wid, GdkEventKey *evt, session *sess)
|
|||||||
if (!list)
|
if (!list)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
current_sess = sess;
|
current_sess = sess;
|
||||||
if ((evt->state & GDK_CONTROL_MASK) &&
|
|
||||||
!(evt->state & (GDK_MOD1_MASK | GDK_META_MASK)))
|
|
||||||
{
|
|
||||||
if (!(evt->state & GDK_SHIFT_MASK) &&
|
|
||||||
(evt->keyval == GDK_KEY_w || evt->keyval == GDK_KEY_W))
|
|
||||||
{
|
|
||||||
if (sess->type == SESS_CHANNEL)
|
|
||||||
{
|
|
||||||
fe_close_window (sess);
|
|
||||||
g_signal_stop_emission_by_name (G_OBJECT (wid), "key-press-event");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((evt->state & GDK_SHIFT_MASK) &&
|
|
||||||
(evt->keyval == GDK_KEY_t || evt->keyval == GDK_KEY_T))
|
|
||||||
{
|
|
||||||
mg_reopen_closed_channel_tab ();
|
|
||||||
g_signal_stop_emission_by_name (G_OBJECT (wid), "key-press-event");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin_emit_keypress (sess, evt->state, evt->keyval, gdk_keyval_to_unicode (evt->keyval)))
|
if (plugin_emit_keypress (sess, evt->state, evt->keyval, gdk_keyval_to_unicode (evt->keyval)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -508,6 +576,31 @@ key_handle_key_press (GtkWidget *wid, GdkEventKey *evt, session *sess)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
key_get_menu_accel (const char *name, guint *keyval, GdkModifierType *mod)
|
||||||
|
{
|
||||||
|
struct key_binding *kb;
|
||||||
|
GSList *list;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
list = keybind_list;
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
kb = (struct key_binding*)list->data;
|
||||||
|
if (kb->action >= 0 && kb->action <= KEY_MAX_ACTIONS && kb->keyval != 0 && !strcmp (key_actions[kb->action].name, "Menu Shortcut") && kb->data1 && !strcmp (kb->data1, name))
|
||||||
|
{
|
||||||
|
*keyval = kb->keyval;
|
||||||
|
*mod = kb->mod;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
list = g_slist_next (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ***** GUI code here ******************* */
|
/* ***** GUI code here ******************* */
|
||||||
|
|
||||||
@@ -518,6 +611,7 @@ enum
|
|||||||
ACTION_COLUMN,
|
ACTION_COLUMN,
|
||||||
D1_COLUMN,
|
D1_COLUMN,
|
||||||
D2_COLUMN,
|
D2_COLUMN,
|
||||||
|
CUSTOM_COLUMN,
|
||||||
N_COLUMNS
|
N_COLUMNS
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -642,16 +736,32 @@ key_dialog_keypress (GtkWidget *wid, GdkEventKey *evt, gpointer userdata)
|
|||||||
|
|
||||||
if (handled)
|
if (handled)
|
||||||
{
|
{
|
||||||
|
gboolean custom1, custom2;
|
||||||
|
|
||||||
sel = gtk_tree_view_get_selection (view);
|
sel = gtk_tree_view_get_selection (view);
|
||||||
gtk_tree_selection_get_selected (sel, &store, &iter1);
|
if (!gtk_tree_selection_get_selected (sel, &store, &iter1))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
path = gtk_tree_model_get_path (store, &iter1);
|
path = gtk_tree_model_get_path (store, &iter1);
|
||||||
if (delta == 1)
|
if (delta == 1)
|
||||||
gtk_tree_path_next (path);
|
gtk_tree_path_next (path);
|
||||||
else
|
else if (!gtk_tree_path_prev (path))
|
||||||
gtk_tree_path_prev (path);
|
{
|
||||||
gtk_tree_model_get_iter (store, &iter2, path);
|
gtk_tree_path_free (path);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gtk_tree_model_get_iter (store, &iter2, path))
|
||||||
|
{
|
||||||
|
gtk_tree_path_free (path);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
gtk_tree_path_free (path);
|
gtk_tree_path_free (path);
|
||||||
gtk_list_store_swap (GTK_LIST_STORE (store), &iter1, &iter2);
|
gtk_tree_model_get (store, &iter1, CUSTOM_COLUMN, &custom1, -1);
|
||||||
|
gtk_tree_model_get (store, &iter2, CUSTOM_COLUMN, &custom2, -1);
|
||||||
|
if (custom1 && custom2)
|
||||||
|
gtk_list_store_swap (GTK_LIST_STORE (store), &iter1, &iter2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
@@ -663,14 +773,23 @@ key_dialog_selection_changed (GtkTreeSelection *sel, gpointer userdata)
|
|||||||
GtkTreeModel *model;
|
GtkTreeModel *model;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
GtkXText *xtext;
|
GtkXText *xtext;
|
||||||
|
GtkWidget *delete_button;
|
||||||
char *actiontext;
|
char *actiontext;
|
||||||
|
gboolean custom;
|
||||||
int action;
|
int action;
|
||||||
|
|
||||||
|
delete_button = g_object_get_data (G_OBJECT (key_dialog), "delete_button");
|
||||||
if (!gtk_tree_selection_get_selected (sel, &model, &iter) || model == NULL)
|
if (!gtk_tree_selection_get_selected (sel, &model, &iter) || model == NULL)
|
||||||
|
{
|
||||||
|
if (delete_button)
|
||||||
|
gtk_widget_set_sensitive (delete_button, FALSE);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
xtext = GTK_XTEXT (g_object_get_data (G_OBJECT (key_dialog), "xtext"));
|
xtext = GTK_XTEXT (g_object_get_data (G_OBJECT (key_dialog), "xtext"));
|
||||||
gtk_tree_model_get (model, &iter, ACTION_COLUMN, &actiontext, -1);
|
gtk_tree_model_get (model, &iter, ACTION_COLUMN, &actiontext, CUSTOM_COLUMN, &custom, -1);
|
||||||
|
if (delete_button)
|
||||||
|
gtk_widget_set_sensitive (delete_button, custom);
|
||||||
|
|
||||||
if (actiontext)
|
if (actiontext)
|
||||||
{
|
{
|
||||||
@@ -745,7 +864,10 @@ key_dialog_save (GtkWidget *wid, gpointer userdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key_save_kbs () == 0)
|
if (key_save_kbs () == 0)
|
||||||
|
{
|
||||||
|
menu_update_quit_accel ();
|
||||||
key_dialog_close (wid, NULL);
|
key_dialog_close (wid, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -758,6 +880,7 @@ key_dialog_add (GtkWidget *wid, gpointer userdata)
|
|||||||
GtkTreePath *path;
|
GtkTreePath *path;
|
||||||
|
|
||||||
gtk_list_store_append (store, &iter);
|
gtk_list_store_append (store, &iter);
|
||||||
|
gtk_list_store_set (store, &iter, CUSTOM_COLUMN, TRUE, -1);
|
||||||
|
|
||||||
/* make sure the new row is visible and selected */
|
/* make sure the new row is visible and selected */
|
||||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
|
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
|
||||||
@@ -774,9 +897,14 @@ key_dialog_delete (GtkWidget *wid, gpointer userdata)
|
|||||||
GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
|
GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
GtkTreePath *path;
|
GtkTreePath *path;
|
||||||
|
gboolean custom;
|
||||||
|
|
||||||
if (gtkutil_treeview_get_selected (view, &iter, -1))
|
if (gtkutil_treeview_get_selected (view, &iter, -1))
|
||||||
{
|
{
|
||||||
|
gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, CUSTOM_COLUMN, &custom, -1);
|
||||||
|
if (!custom)
|
||||||
|
return;
|
||||||
|
|
||||||
/* delete this row, select next one */
|
/* delete this row, select next one */
|
||||||
if (gtk_list_store_remove (store, &iter))
|
if (gtk_list_store_remove (store, &iter))
|
||||||
{
|
{
|
||||||
@@ -803,13 +931,13 @@ key_dialog_treeview_new (GtkWidget *box)
|
|||||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
|
||||||
|
|
||||||
store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
|
store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
|
||||||
G_TYPE_STRING, G_TYPE_STRING);
|
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
|
||||||
g_return_val_if_fail (store != NULL, NULL);
|
g_return_val_if_fail (store != NULL, NULL);
|
||||||
|
|
||||||
view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
|
view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
|
||||||
gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (view), TRUE);
|
gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (view), TRUE);
|
||||||
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
|
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
|
||||||
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), TRUE);
|
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), FALSE);
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT (view), "key-press-event",
|
g_signal_connect (G_OBJECT (view), "key-press-event",
|
||||||
G_CALLBACK (key_dialog_keypress), NULL);
|
G_CALLBACK (key_dialog_keypress), NULL);
|
||||||
@@ -880,6 +1008,7 @@ key_dialog_treeview_new (GtkWidget *box)
|
|||||||
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), ACTION_COLUMN,
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), ACTION_COLUMN,
|
||||||
"Action", render,
|
"Action", render,
|
||||||
"text", ACTION_COLUMN,
|
"text", ACTION_COLUMN,
|
||||||
|
"editable", CUSTOM_COLUMN,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
render = gtk_cell_renderer_text_new ();
|
render = gtk_cell_renderer_text_new ();
|
||||||
@@ -890,6 +1019,7 @@ key_dialog_treeview_new (GtkWidget *box)
|
|||||||
GTK_TREE_VIEW (view), D1_COLUMN,
|
GTK_TREE_VIEW (view), D1_COLUMN,
|
||||||
"Data1", render,
|
"Data1", render,
|
||||||
"text", D1_COLUMN,
|
"text", D1_COLUMN,
|
||||||
|
"editable", CUSTOM_COLUMN,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
render = gtk_cell_renderer_text_new ();
|
render = gtk_cell_renderer_text_new ();
|
||||||
@@ -900,6 +1030,7 @@ key_dialog_treeview_new (GtkWidget *box)
|
|||||||
GTK_TREE_VIEW (view), D2_COLUMN,
|
GTK_TREE_VIEW (view), D2_COLUMN,
|
||||||
"Data2", render,
|
"Data2", render,
|
||||||
"text", D2_COLUMN,
|
"text", D2_COLUMN,
|
||||||
|
"editable", CUSTOM_COLUMN,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), KEY_COLUMN);
|
col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), KEY_COLUMN);
|
||||||
@@ -945,7 +1076,8 @@ key_dialog_load (GtkListStore *store)
|
|||||||
ACCEL_COLUMN, accel_text,
|
ACCEL_COLUMN, accel_text,
|
||||||
ACTION_COLUMN, key_actions[kb->action].name,
|
ACTION_COLUMN, key_actions[kb->action].name,
|
||||||
D1_COLUMN, kb->data1,
|
D1_COLUMN, kb->data1,
|
||||||
D2_COLUMN, kb->data2, -1);
|
D2_COLUMN, kb->data2,
|
||||||
|
CUSTOM_COLUMN, !key_binding_is_builtin (kb), -1);
|
||||||
|
|
||||||
g_free (accel_text);
|
g_free (accel_text);
|
||||||
g_free (label_text);
|
g_free (label_text);
|
||||||
@@ -958,7 +1090,7 @@ void
|
|||||||
key_dialog_show ()
|
key_dialog_show ()
|
||||||
{
|
{
|
||||||
GtkWidget *vbox, *box;
|
GtkWidget *vbox, *box;
|
||||||
GtkWidget *view, *xtext;
|
GtkWidget *view, *xtext, *delete_button;
|
||||||
GtkListStore *store;
|
GtkListStore *store;
|
||||||
XTextColor xtext_palette[XTEXT_COLS];
|
XTextColor xtext_palette[XTEXT_COLS];
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@@ -992,8 +1124,10 @@ key_dialog_show ()
|
|||||||
|
|
||||||
gtkutil_button (box, ICON_FKEYS_NEW, NULL, key_dialog_add,
|
gtkutil_button (box, ICON_FKEYS_NEW, NULL, key_dialog_add,
|
||||||
NULL, _("Add"));
|
NULL, _("Add"));
|
||||||
gtkutil_button (box, ICON_FKEYS_DELETE, NULL, key_dialog_delete,
|
delete_button = gtkutil_button (box, ICON_FKEYS_DELETE, NULL, key_dialog_delete,
|
||||||
NULL, _("Delete"));
|
NULL, _("Delete"));
|
||||||
|
g_object_set_data (G_OBJECT (key_dialog), "delete_button", delete_button);
|
||||||
|
gtk_widget_set_sensitive (delete_button, FALSE);
|
||||||
gtkutil_button (box, ICON_FKEYS_CANCEL, NULL, key_dialog_close,
|
gtkutil_button (box, ICON_FKEYS_CANCEL, NULL, key_dialog_close,
|
||||||
NULL, _("Cancel"));
|
NULL, _("Cancel"));
|
||||||
gtkutil_button (box, ICON_FKEYS_SAVE, NULL, key_dialog_save,
|
gtkutil_button (box, ICON_FKEYS_SAVE, NULL, key_dialog_save,
|
||||||
@@ -1289,6 +1423,24 @@ key_action_handle_command (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
key_action_menu_shortcut (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
||||||
|
char *d2, struct session *sess)
|
||||||
|
{
|
||||||
|
if (menu_key_action (d1, evt->keyval, evt->state))
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
key_action_reopen_closed_tab (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
||||||
|
char *d2, struct session *sess)
|
||||||
|
{
|
||||||
|
mg_reopen_closed_channel_tab ();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the given session is inside the main window. This predicate
|
* Check if the given session is inside the main window. This predicate
|
||||||
* is passed to lastact_getfirst() as a way to filter out detached sessions.
|
* is passed to lastact_getfirst() as a way to filter out detached sessions.
|
||||||
@@ -1307,6 +1459,9 @@ key_action_page_switch (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
|||||||
char *d2, struct session *sess)
|
char *d2, struct session *sess)
|
||||||
{
|
{
|
||||||
session *newsess;
|
session *newsess;
|
||||||
|
char *network;
|
||||||
|
char *channel;
|
||||||
|
char *slash;
|
||||||
int len, i, num;
|
int len, i, num;
|
||||||
|
|
||||||
if (!d1)
|
if (!d1)
|
||||||
@@ -1318,21 +1473,13 @@ key_action_page_switch (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
|||||||
|
|
||||||
if (g_ascii_strcasecmp(d1, "auto") == 0)
|
if (g_ascii_strcasecmp(d1, "auto") == 0)
|
||||||
{
|
{
|
||||||
/* Auto switch makes no sense in detached sessions */
|
|
||||||
if (!sess->gui->is_tab)
|
if (!sess->gui->is_tab)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Obtain a session with recent activity */
|
|
||||||
newsess = lastact_getfirst(session_check_is_tab);
|
newsess = lastact_getfirst(session_check_is_tab);
|
||||||
|
|
||||||
if (newsess)
|
if (newsess)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Only sessions in the current window should be considered (i.e.
|
|
||||||
* we don't want to move the focus on a different window). This
|
|
||||||
* call could, in theory, do this, but we checked before that
|
|
||||||
* newsess->gui->is_tab and sess->gui->is_tab.
|
|
||||||
*/
|
|
||||||
mg_bring_tofront_sess(newsess);
|
mg_bring_tofront_sess(newsess);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1346,8 +1493,27 @@ key_action_page_switch (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
|||||||
{
|
{
|
||||||
if (i == 0 && (d1[i] == '+' || d1[i] == '-'))
|
if (i == 0 && (d1[i] == '+' || d1[i] == '-'))
|
||||||
continue;
|
continue;
|
||||||
else
|
|
||||||
return 1;
|
network = NULL;
|
||||||
|
channel = d1;
|
||||||
|
slash = strchr (d1, '/');
|
||||||
|
|
||||||
|
if (slash && slash[1])
|
||||||
|
{
|
||||||
|
network = g_strndup (d1, slash - d1);
|
||||||
|
channel = slash + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
newsess = plugin_find_context (network, channel, sess->server);
|
||||||
|
g_free (network);
|
||||||
|
|
||||||
|
if (newsess && newsess->gui)
|
||||||
|
{
|
||||||
|
mg_bring_tofront_sess(newsess);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,5 +35,6 @@ int key_handle_key_press (GtkWidget * wid, GdkEventKey * evt, session *sess);
|
|||||||
int key_action_insert (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2,
|
int key_action_insert (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2,
|
||||||
session *sess);
|
session *sess);
|
||||||
void key_check_replace_on_change (GtkEditable *editable, gpointer data);
|
void key_check_replace_on_change (GtkEditable *editable, gpointer data);
|
||||||
|
gboolean key_get_menu_accel (const char *name, guint *keyval, GdkModifierType *mod);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1003,7 +1003,9 @@ mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata
|
|||||||
menu_set_fullscreen (current_sess->gui, prefs.hex_gui_win_fullscreen);
|
menu_set_fullscreen (current_sess->gui, prefs.hex_gui_win_fullscreen);
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
mg_win32_allow_autohide_taskbar (wid, event);
|
if (event->changed_mask &
|
||||||
|
(GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN))
|
||||||
|
mg_win32_allow_autohide_taskbar (wid, event);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -1755,44 +1755,6 @@ menu_change_layout (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
menu_update_quit_accel (void)
|
|
||||||
{
|
|
||||||
GSList *list;
|
|
||||||
|
|
||||||
list = sess_list;
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
session *sess = list->data;
|
|
||||||
session_gui *gui = sess->gui;
|
|
||||||
GtkWidget *item;
|
|
||||||
GtkAccelGroup *accel_group;
|
|
||||||
int enabled;
|
|
||||||
|
|
||||||
list = list->next;
|
|
||||||
if (!gui)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
item = gui->menu_item[MENU_ID_QUIT];
|
|
||||||
if (!item)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
enabled = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "zc-ctrlq-enabled"));
|
|
||||||
if (enabled == (int)prefs.hex_gui_ctrlq_quit)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
accel_group = g_object_get_data (G_OBJECT (item), "zc-quit-accel-group");
|
|
||||||
if (!accel_group)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (prefs.hex_gui_ctrlq_quit)
|
|
||||||
gtk_widget_add_accelerator (item, "activate", accel_group, GDK_KEY_q, STATE_CTRL, GTK_ACCEL_VISIBLE);
|
|
||||||
else
|
|
||||||
gtk_widget_remove_accelerator (item, accel_group, GDK_KEY_q, STATE_CTRL);
|
|
||||||
g_object_set_data (G_OBJECT (item), "zc-ctrlq-enabled", GINT_TO_POINTER (prefs.hex_gui_ctrlq_quit));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
menu_layout_cb (GtkWidget *item, gpointer none)
|
menu_layout_cb (GtkWidget *item, gpointer none)
|
||||||
{
|
{
|
||||||
@@ -1939,13 +1901,13 @@ menu_about (GtkWidget *wid, gpointer sess)
|
|||||||
|
|
||||||
static struct mymenu mymenu[] = {
|
static struct mymenu mymenu[] = {
|
||||||
{N_("_ZoiteChat"), 0, 0, M_NEWMENU, MENU_ID_ZOITECHAT, 0, 1},
|
{N_("_ZoiteChat"), 0, 0, M_NEWMENU, MENU_ID_ZOITECHAT, 0, 1},
|
||||||
{N_("Network Li_st"), menu_open_server_list, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_s},
|
{N_("Network Li_st"), menu_open_server_list, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
|
|
||||||
{N_("_New"), 0, 0, M_MENUSUB, 0, 0, 1},
|
{N_("_New"), 0, 0, M_MENUSUB, 0, 0, 1},
|
||||||
{N_("Server Tab"), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_t},
|
{N_("Server Tab"), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Channel Tab"), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
|
{N_("Channel Tab"), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Server Window"), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_n},
|
{N_("Server Window"), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Channel Window"), menu_newchannel_window, 0, M_MENUITEM, 0, 0, 1},
|
{N_("Channel Window"), menu_newchannel_window, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_END, 0, 0, 0},
|
{0, 0, 0, M_END, 0, 0, 0},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
@@ -1957,13 +1919,13 @@ static struct mymenu mymenu[] = {
|
|||||||
#define CLOSE_OFFSET (13)
|
#define CLOSE_OFFSET (13)
|
||||||
{0, menu_close, 0, M_MENUITEM, 0, 0, 1},
|
{0, menu_close, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
{N_("_Quit"), menu_quit, 0, M_MENUITEM, MENU_ID_QUIT, 0, 1, GDK_KEY_q}, /* 15 */
|
{N_("_Quit"), menu_quit, 0, M_MENUITEM, MENU_ID_QUIT, 0, 1}, /* 15 */
|
||||||
|
|
||||||
{N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
|
{N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
|
||||||
#define MENUBAR_OFFSET (17)
|
#define MENUBAR_OFFSET (17)
|
||||||
{N_("_Menu Bar"), menu_bar_toggle_cb, 0, M_MENUTOG, MENU_ID_MENUBAR, 0, 1, GDK_KEY_F9},
|
{N_("_Menu Bar"), menu_bar_toggle_cb, 0, M_MENUTOG, MENU_ID_MENUBAR, 0, 1},
|
||||||
{N_("_Topic Bar"), menu_topicbar_toggle, 0, M_MENUTOG, MENU_ID_TOPICBAR, 0, 1},
|
{N_("_Topic Bar"), menu_topicbar_toggle, 0, M_MENUTOG, MENU_ID_TOPICBAR, 0, 1},
|
||||||
{N_("_User List"), menu_userlist_toggle, 0, M_MENUTOG, MENU_ID_USERLIST, 0, 1, GDK_KEY_F7},
|
{N_("_User List"), menu_userlist_toggle, 0, M_MENUTOG, MENU_ID_USERLIST, 0, 1},
|
||||||
{N_("U_ser List Buttons"), menu_ulbuttons_toggle, 0, M_MENUTOG, MENU_ID_ULBUTTONS, 0, 1},
|
{N_("U_ser List Buttons"), menu_ulbuttons_toggle, 0, M_MENUTOG, MENU_ID_ULBUTTONS, 0, 1},
|
||||||
{N_("M_ode Buttons"), menu_cmbuttons_toggle, 0, M_MENUTOG, MENU_ID_MODEBUTTONS, 0, 1},
|
{N_("M_ode Buttons"), menu_cmbuttons_toggle, 0, M_MENUTOG, MENU_ID_MODEBUTTONS, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
@@ -1980,7 +1942,7 @@ static struct mymenu mymenu[] = {
|
|||||||
{N_("Both"), menu_metres_both, 0, M_MENURADIO, 0, 0, 1},
|
{N_("Both"), menu_metres_both, 0, M_MENURADIO, 0, 0, 1},
|
||||||
{0, 0, 0, M_END, 0, 0, 0}, /* 32 */
|
{0, 0, 0, M_END, 0, 0, 0}, /* 32 */
|
||||||
{ 0, 0, 0, M_SEP, 0, 0, 0 },
|
{ 0, 0, 0, M_SEP, 0, 0, 0 },
|
||||||
{N_ ("_Fullscreen"), menu_fullscreen_toggle, 0, M_MENUTOG, MENU_ID_FULLSCREEN, 0, 1, GDK_KEY_F11},
|
{N_ ("_Fullscreen"), menu_fullscreen_toggle, 0, M_MENUTOG, MENU_ID_FULLSCREEN, 0, 1},
|
||||||
|
|
||||||
{N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
|
{N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
|
||||||
{N_("_Disconnect"), menu_disconnect, 0, M_MENUITEM, MENU_ID_DISCONNECT, 0, 1},
|
{N_("_Disconnect"), menu_disconnect, 0, M_MENUITEM, MENU_ID_DISCONNECT, 0, 1},
|
||||||
@@ -1989,7 +1951,7 @@ static struct mymenu mymenu[] = {
|
|||||||
{N_("Channel _List"), menu_chanlist, 0, M_MENUITEM, 0, 0, 1},
|
{N_("Channel _List"), menu_chanlist, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
#define AWAY_OFFSET (41)
|
#define AWAY_OFFSET (41)
|
||||||
{N_("Marked _Away"), menu_away_toggle, 0, M_MENUITEM, MENU_ID_AWAY, 0, 1, GDK_KEY_a},
|
{N_("Marked _Away"), menu_away_toggle, 0, M_MENUITEM, MENU_ID_AWAY, 0, 1},
|
||||||
|
|
||||||
{N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
|
{N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
|
||||||
|
|
||||||
@@ -2017,25 +1979,191 @@ static struct mymenu mymenu[] = {
|
|||||||
{N_("_Raw Log"), menu_rawlog, 0, M_MENUITEM, 0, 0, 1}, /* 61 */
|
{N_("_Raw Log"), menu_rawlog, 0, M_MENUITEM, 0, 0, 1}, /* 61 */
|
||||||
{N_("_URL Grabber"), url_opengui, 0, M_MENUITEM, 0, 0, 1},
|
{N_("_URL Grabber"), url_opengui, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_m},
|
{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Move to Marker Line"), menu_movetomarker, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_M},
|
{N_("Move to Marker Line"), menu_movetomarker, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_C},
|
{N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("C_lear Text"), menu_flushbuffer, 0, M_MENUITEM, 0, 0, 1},
|
{N_("C_lear Text"), menu_flushbuffer, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Save Text" ELLIPSIS), menu_savebuffer, 0, M_MENUITEM, 0, 0, 1},
|
{N_("Save Text" ELLIPSIS), menu_savebuffer, 0, M_MENUITEM, 0, 0, 1},
|
||||||
#define SEARCH_OFFSET (70)
|
#define SEARCH_OFFSET (70)
|
||||||
{N_("Search"), 0, 0, M_MENUSUB, 0, 0, 1},
|
{N_("Search"), 0, 0, M_MENUSUB, 0, 0, 1},
|
||||||
{N_("Search Text" ELLIPSIS), menu_search, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_f},
|
{N_("Search Text" ELLIPSIS), menu_search, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Search Next" ), menu_search_next, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_g},
|
{N_("Search Next" ), menu_search_next, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Search Previous" ), menu_search_prev, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_G},
|
{N_("Search Previous" ), menu_search_prev, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_END, 0, 0, 0},
|
{0, 0, 0, M_END, 0, 0, 0},
|
||||||
|
|
||||||
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
|
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
|
||||||
{N_("_Contents"), menu_docs, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_F1},
|
{N_("_Contents"), menu_docs, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("_About"), menu_about, 0, M_MENUITEM, 0, 0, 1},
|
{N_("_About"), menu_about, 0, M_MENUITEM, 0, 0, 1},
|
||||||
|
|
||||||
{0, 0, 0, M_END, 0, 0, 0},
|
{0, 0, 0, M_END, 0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
menu_get_key_action_name (int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return "network-list";
|
||||||
|
case 4:
|
||||||
|
return "new-server-tab";
|
||||||
|
case 6:
|
||||||
|
return "new-server-window";
|
||||||
|
case CLOSE_OFFSET:
|
||||||
|
return "close";
|
||||||
|
case 15:
|
||||||
|
return "quit";
|
||||||
|
case MENUBAR_OFFSET:
|
||||||
|
return "menu-toggle";
|
||||||
|
case MENUBAR_OFFSET + 2:
|
||||||
|
return "user-list-toggle";
|
||||||
|
case 34:
|
||||||
|
return "fullscreen-toggle";
|
||||||
|
case AWAY_OFFSET:
|
||||||
|
return "away-toggle";
|
||||||
|
case 65:
|
||||||
|
return "reset-marker";
|
||||||
|
case 66:
|
||||||
|
return "move-marker";
|
||||||
|
case 67:
|
||||||
|
return "copy-selection";
|
||||||
|
case SEARCH_OFFSET + 1:
|
||||||
|
return "search-text";
|
||||||
|
case SEARCH_OFFSET + 2:
|
||||||
|
return "search-next";
|
||||||
|
case SEARCH_OFFSET + 3:
|
||||||
|
return "search-previous";
|
||||||
|
case 75:
|
||||||
|
return "contents";
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
menu_add_keybinding_accel (GtkWidget *item, GtkAccelGroup *accel_group, const char *name)
|
||||||
|
{
|
||||||
|
guint keyval;
|
||||||
|
GdkModifierType mod;
|
||||||
|
|
||||||
|
if (!accel_group || !key_get_menu_accel (name, &keyval, &mod))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!strcmp (name, "quit") && !prefs.hex_gui_ctrlq_quit && keyval == GDK_KEY_q && mod == STATE_CTRL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_widget_add_accelerator (item, "activate", accel_group, keyval, mod, GTK_ACCEL_VISIBLE);
|
||||||
|
g_object_set_data (G_OBJECT (item), "zc-key-accel-key", GUINT_TO_POINTER (keyval));
|
||||||
|
g_object_set_data (G_OBJECT (item), "zc-key-accel-mod", GUINT_TO_POINTER (mod));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
menu_refresh_keybinding_accels (GtkWidget *widget, gpointer data)
|
||||||
|
{
|
||||||
|
GtkAccelGroup *accel_group = data;
|
||||||
|
const char *name;
|
||||||
|
guint keyval;
|
||||||
|
GdkModifierType mod;
|
||||||
|
GtkWidget *submenu;
|
||||||
|
GList *children, *list;
|
||||||
|
|
||||||
|
if (GTK_IS_MENU_ITEM (widget))
|
||||||
|
{
|
||||||
|
keyval = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), "zc-key-accel-key"));
|
||||||
|
mod = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), "zc-key-accel-mod"));
|
||||||
|
if (keyval != 0)
|
||||||
|
{
|
||||||
|
gtk_widget_remove_accelerator (widget, accel_group, keyval, mod);
|
||||||
|
g_object_set_data (G_OBJECT (widget), "zc-key-accel-key", NULL);
|
||||||
|
g_object_set_data (G_OBJECT (widget), "zc-key-accel-mod", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
name = g_object_get_data (G_OBJECT (widget), "zc-key-action");
|
||||||
|
menu_add_keybinding_accel (widget, accel_group, name);
|
||||||
|
|
||||||
|
submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
|
||||||
|
if (submenu)
|
||||||
|
menu_refresh_keybinding_accels (submenu, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GTK_IS_CONTAINER (widget))
|
||||||
|
{
|
||||||
|
children = gtk_container_get_children (GTK_CONTAINER (widget));
|
||||||
|
for (list = children; list; list = g_list_next (list))
|
||||||
|
menu_refresh_keybinding_accels (list->data, data);
|
||||||
|
g_list_free (children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
menu_update_quit_accel (void)
|
||||||
|
{
|
||||||
|
session *sess;
|
||||||
|
GSList *list;
|
||||||
|
GtkAccelGroup *accel_group;
|
||||||
|
|
||||||
|
list = sess_list;
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
sess = list->data;
|
||||||
|
if (sess && sess->gui && sess->gui->menu)
|
||||||
|
{
|
||||||
|
accel_group = g_object_get_data (G_OBJECT (sess->gui->menu), "accel");
|
||||||
|
if (accel_group)
|
||||||
|
menu_refresh_keybinding_accels (sess->gui->menu, accel_group);
|
||||||
|
}
|
||||||
|
list = g_slist_next (list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
menu_key_action (const char *name, guint keyval, GdkModifierType state)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!strcmp (name, "network-list"))
|
||||||
|
menu_open_server_list (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "new-server-tab"))
|
||||||
|
menu_newserver_tab (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "new-server-window"))
|
||||||
|
menu_newserver_window (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "close"))
|
||||||
|
menu_close (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "quit"))
|
||||||
|
{
|
||||||
|
if (!prefs.hex_gui_ctrlq_quit && keyval == GDK_KEY_q && (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == STATE_CTRL)
|
||||||
|
return FALSE;
|
||||||
|
menu_quit (NULL, NULL);
|
||||||
|
}
|
||||||
|
else if (!strcmp (name, "menu-toggle"))
|
||||||
|
menu_bar_toggle_cb ();
|
||||||
|
else if (!strcmp (name, "user-list-toggle"))
|
||||||
|
menu_userlist_toggle (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "fullscreen-toggle"))
|
||||||
|
menu_fullscreen_toggle (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "away-toggle"))
|
||||||
|
menu_away_toggle (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "reset-marker"))
|
||||||
|
menu_resetmarker (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "move-marker"))
|
||||||
|
menu_movetomarker (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "copy-selection"))
|
||||||
|
menu_copy_selection (NULL, NULL);
|
||||||
|
else if (!strcmp (name, "search-text"))
|
||||||
|
menu_search ();
|
||||||
|
else if (!strcmp (name, "search-next"))
|
||||||
|
menu_search_next (NULL);
|
||||||
|
else if (!strcmp (name, "search-previous"))
|
||||||
|
menu_search_prev (NULL);
|
||||||
|
else if (!strcmp (name, "contents"))
|
||||||
|
menu_docs (NULL, NULL);
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
menu_set_away (session_gui *gui, int away)
|
menu_set_away (session_gui *gui, int away)
|
||||||
{
|
{
|
||||||
@@ -2641,6 +2769,8 @@ menu_create_main (void *accel_group, int bar, int away, int toplevel,
|
|||||||
case M_MENUITEM:
|
case M_MENUITEM:
|
||||||
item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
|
item = gtk_menu_item_new_with_mnemonic (_(mymenu[i].text));
|
||||||
normalitem:
|
normalitem:
|
||||||
|
g_object_set_data (G_OBJECT (item), "zc-key-action", (gpointer) menu_get_key_action_name (i));
|
||||||
|
menu_add_keybinding_accel (item, accel_group, menu_get_key_action_name (i));
|
||||||
if (mymenu[i].key != 0 && !(mymenu[i].id == MENU_ID_QUIT && !prefs.hex_gui_ctrlq_quit))
|
if (mymenu[i].key != 0 && !(mymenu[i].id == MENU_ID_QUIT && !prefs.hex_gui_ctrlq_quit))
|
||||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||||
mymenu[i].key,
|
mymenu[i].key,
|
||||||
@@ -2669,6 +2799,8 @@ normalitem:
|
|||||||
case M_MENUTOG:
|
case M_MENUTOG:
|
||||||
item = gtk_check_menu_item_new_with_mnemonic (_(mymenu[i].text));
|
item = gtk_check_menu_item_new_with_mnemonic (_(mymenu[i].text));
|
||||||
togitem:
|
togitem:
|
||||||
|
g_object_set_data (G_OBJECT (item), "zc-key-action", (gpointer) menu_get_key_action_name (i));
|
||||||
|
menu_add_keybinding_accel (item, accel_group, menu_get_key_action_name (i));
|
||||||
/* must avoid callback for Radio buttons */
|
/* must avoid callback for Radio buttons */
|
||||||
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), mymenu[i].state);
|
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), mymenu[i].state);
|
||||||
/*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
|
/*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ void menu_bar_toggle (void);
|
|||||||
void menu_add_plugin_items (GtkWidget *menu, char *root, char *target);
|
void menu_add_plugin_items (GtkWidget *menu, char *root, char *target);
|
||||||
void menu_change_layout (void);
|
void menu_change_layout (void);
|
||||||
void menu_update_quit_accel (void);
|
void menu_update_quit_accel (void);
|
||||||
|
gboolean menu_key_action (const char *name, guint keyval, GdkModifierType state);
|
||||||
|
|
||||||
void menu_set_away (session_gui *gui, int away);
|
void menu_set_away (session_gui *gui, int away);
|
||||||
void menu_set_fullscreen (session_gui *gui, int fullscreen);
|
void menu_set_fullscreen (session_gui *gui, int fullscreen);
|
||||||
|
|||||||
@@ -855,7 +855,6 @@ tray_toggle_visibility (gboolean force_hide)
|
|||||||
static int maximized;
|
static int maximized;
|
||||||
static int fullscreen;
|
static int fullscreen;
|
||||||
GtkWindow *win;
|
GtkWindow *win;
|
||||||
WinStatus status;
|
|
||||||
|
|
||||||
if (!tray_backend_active)
|
if (!tray_backend_active)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -871,9 +870,7 @@ tray_toggle_visibility (gboolean force_hide)
|
|||||||
if (!win)
|
if (!win)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
status = tray_get_window_status ();
|
if (force_hide || gtk_widget_get_visible (GTK_WIDGET (win)))
|
||||||
|
|
||||||
if (force_hide || status != WS_HIDDEN)
|
|
||||||
{
|
{
|
||||||
if (prefs.hex_gui_tray_away)
|
if (prefs.hex_gui_tray_away)
|
||||||
zoitechat_command (ph, "ALLSERV AWAY");
|
zoitechat_command (ph, "ALLSERV AWAY");
|
||||||
@@ -893,8 +890,8 @@ tray_toggle_visibility (gboolean force_hide)
|
|||||||
gtk_window_maximize (win);
|
gtk_window_maximize (win);
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
gtk_window_fullscreen (win);
|
gtk_window_fullscreen (win);
|
||||||
gtk_window_deiconify (win);
|
|
||||||
gtk_widget_show (GTK_WIDGET (win));
|
gtk_widget_show (GTK_WIDGET (win));
|
||||||
|
gtk_window_deiconify (win);
|
||||||
gtk_window_present (win);
|
gtk_window_present (win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -546,6 +546,7 @@ static const setting general_settings[] =
|
|||||||
{ST_TOGGLE, N_("WHOIS on notify"), P_OFFINTNL(hex_notify_whois_online), N_("Sends a /WHOIS when a user comes online in your notify list."), 0, 0},
|
{ST_TOGGLE, N_("WHOIS on notify"), P_OFFINTNL(hex_notify_whois_online), N_("Sends a /WHOIS when a user comes online in your notify list."), 0, 0},
|
||||||
{ST_TOGGLE, N_("Hide join and part messages"), P_OFFINTNL(hex_irc_conf_mode), N_("Hide channel join/part messages by default."), 0, 0},
|
{ST_TOGGLE, N_("Hide join and part messages"), P_OFFINTNL(hex_irc_conf_mode), N_("Hide channel join/part messages by default."), 0, 0},
|
||||||
{ST_TOGGLE, N_("Hide nick change messages"), P_OFFINTNL(hex_irc_hide_nickchange), 0, 0, 0},
|
{ST_TOGGLE, N_("Hide nick change messages"), P_OFFINTNL(hex_irc_hide_nickchange), 0, 0, 0},
|
||||||
|
{ST_TOGGLE, N_("Hide hostmasks in join and part messages"), P_OFFINTNL(hex_irc_hide_join_part_hostmask), 0, 0, 0},
|
||||||
{ST_TOGGLE, N_("Enable Ctrl+Q to quit"), P_OFFINTNL(hex_gui_ctrlq_quit), 0, 0, 0},
|
{ST_TOGGLE, N_("Enable Ctrl+Q to quit"), P_OFFINTNL(hex_gui_ctrlq_quit), 0, 0, 0},
|
||||||
|
|
||||||
{ST_END, 0, 0, 0, 0, 0}
|
{ST_END, 0, 0, 0, 0, 0}
|
||||||
|
|||||||
Reference in New Issue
Block a user