2011-02-24 04:14:30 +01:00
/* X-Chat
* Copyright (C) 2004-2008 Peter Zelezny.
2013-03-31 21:44:48 +02:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
2011-02-24 04:14:30 +01:00
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
2026-03-24 23:00:09 -06:00
#include <sys/stat.h>
2011-02-24 04:14:30 +01:00
#include <gdk/gdkkeysyms.h>
2026-01-05 23:12:38 -07:00
#include "../common/zoitechat.h"
#include "../common/zoitechatc.h"
2011-02-24 04:14:30 +01:00
#include "../common/servlist.h"
#include "../common/cfgfiles.h"
#include "../common/fe.h"
2026-06-02 15:57:28 -06:00
#include "../common/secretstore.h"
2012-07-21 14:26:19 +02:00
#include "../common/util.h"
2011-02-24 04:14:30 +01:00
#include "fe-gtk.h"
#include "gtkutil.h"
#include "menu.h"
#include "pixmaps.h"
2012-10-21 03:03:38 +02:00
#include "fkeys.h"
2026-03-04 23:28:01 -07:00
#include "theme/theme-manager.h"
2011-02-24 04:14:30 +01:00
2013-05-11 15:22:28 +02:00
#define SERVLIST_X_PADDING 4 /* horizontal paddig in the network editor */
#define SERVLIST_Y_PADDING 0 /* vertical padding in the network editor */
2011-02-24 04:14:30 +01:00
2026-02-18 01:30:45 -07:00
#define ICON_SERVLIST_CONNECT "zc-menu-connect"
2026-01-30 15:27:01 -07:00
#define ICON_SERVLIST_ADD "list-add"
#define ICON_SERVLIST_REMOVE "list-remove"
2026-03-13 13:32:08 -06:00
#define ICON_SERVLIST_CLOSE "gtk-close"
2026-01-30 15:27:01 -07:00
#define ICON_SERVLIST_ERROR "dialog-error"
2021-05-23 06:58:18 +01:00
#ifdef USE_OPENSSL
2021-05-30 18:45:22 +01:00
# define DEFAULT_SERVER "newserver/6697"
2021-05-23 06:58:18 +01:00
#else
2021-05-30 18:45:22 +01:00
# define DEFAULT_SERVER "newserver/6667"
2021-05-23 06:58:18 +01:00
#endif
2011-02-24 04:14:30 +01:00
/* servlistgui.c globals */
static GtkWidget * serverlist_win = NULL ;
2013-05-11 15:58:52 +02:00
static GtkWidget * networks_tree ; /* network TreeView */
static int netlist_win_width = 0 ; /* don't hardcode pixels, just use as much as needed by default, save if resized */
static int netlist_win_height = 0 ;
static int netedit_win_width = 0 ;
static int netedit_win_height = 0 ;
2011-02-24 04:14:30 +01:00
2013-05-12 16:59:21 +02:00
static int netedit_active_tab = 0 ;
2011-02-24 04:14:30 +01:00
/* global user info */
static GtkWidget * entry_nick1 ;
static GtkWidget * entry_nick2 ;
static GtkWidget * entry_nick3 ;
static GtkWidget * entry_guser ;
2012-05-16 19:47:12 +02:00
/* static GtkWidget *entry_greal; */
2011-02-24 04:14:30 +01:00
2013-05-11 09:20:03 -04:00
enum {
SERVER_TREE ,
CHANNEL_TREE ,
CMD_TREE ,
N_TREES ,
};
2011-02-24 04:14:30 +01:00
/* edit area */
static GtkWidget * edit_win ;
static GtkWidget * edit_entry_nick ;
static GtkWidget * edit_entry_nick2 ;
static GtkWidget * edit_entry_user ;
static GtkWidget * edit_entry_real ;
static GtkWidget * edit_entry_pass ;
2026-06-02 15:57:28 -06:00
static GtkWidget * edit_check_show_pass ;
static GtkWidget * edit_check_use_keyring ;
2026-07-09 12:50:13 -06:00
static GtkWidget * edit_check_ask_pass ;
2026-06-05 10:38:16 -06:00
static GtkWidget * edit_button_encrypt_pass ;
static GtkWidget * edit_button_import_pass ;
2026-06-02 15:57:28 -06:00
static int edit_pass_changed ;
static char * edit_loaded_password ;
2011-02-24 04:14:30 +01:00
static GtkWidget * edit_label_nick ;
static GtkWidget * edit_label_nick2 ;
static GtkWidget * edit_label_real ;
static GtkWidget * edit_label_user ;
2013-05-11 09:20:03 -04:00
static GtkWidget * edit_trees [ N_TREES ];
2026-03-24 23:00:09 -06:00
static GtkWidget * edit_button_cert_generate ;
2026-03-30 11:46:08 -06:00
static GtkWidget * edit_button_cert_import ;
2026-03-24 23:00:09 -06:00
static GtkWidget * edit_button_cert_info ;
static GtkWidget * edit_button_cert_delete ;
2011-02-24 04:14:30 +01:00
static ircnet * selected_net = NULL ;
static ircserver * selected_serv = NULL ;
2013-05-20 13:19:20 -03:00
static commandentry * selected_cmd = NULL ;
static favchannel * selected_chan = NULL ;
2011-02-24 04:14:30 +01:00
static session * servlist_sess ;
static void servlist_network_row_cb ( GtkTreeSelection * sel , gpointer user_data );
static GtkWidget * servlist_open_edit ( GtkWidget * parent , ircnet * net );
2026-06-05 10:38:16 -06:00
static void servlist_password_changed_cb ( GtkEditable * editable , gpointer userdata );
static void
servlist_update_password_tools ( ircnet * net )
{
gboolean has_local ;
gboolean use_keyring ;
if ( ! edit_button_encrypt_pass || ! edit_button_import_pass )
return ;
use_keyring = net && ( net -> flags & FLAG_USE_KEYRING );
2026-07-09 12:50:13 -06:00
if (( net && ( net -> flags & FLAG_PROMPT_PASSWORD )) ||
( edit_check_ask_pass && gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( edit_check_ask_pass ))))
use_keyring = FALSE ;
has_local = net && net -> pass && * net -> pass && ! use_keyring && ! edit_pass_changed &&
( ! edit_check_ask_pass || ! gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( edit_check_ask_pass )));
2026-06-05 10:38:16 -06:00
gtk_widget_set_sensitive ( edit_button_encrypt_pass , has_local && ! servlist_password_is_encrypted ( net -> pass ));
gtk_widget_set_sensitive ( edit_button_import_pass , has_local );
}
static void
servlist_entry_set_text_silent ( GtkWidget * entry , const char * text )
{
g_signal_handlers_block_by_func ( G_OBJECT ( entry ), G_CALLBACK ( servlist_password_changed_cb ), NULL );
gtk_entry_set_text ( GTK_ENTRY ( entry ), text );
g_signal_handlers_unblock_by_func ( G_OBJECT ( entry ), G_CALLBACK ( servlist_password_changed_cb ), NULL );
}
2026-07-09 12:50:13 -06:00
static void
servlist_toggle_ask_pass_cb ( GtkToggleButton * toggle , gpointer userdata )
{
gboolean active = gtk_toggle_button_get_active ( toggle );
gtk_widget_set_sensitive ( edit_check_use_keyring , ! active );
gtk_widget_set_sensitive ( edit_entry_pass , ! active && ( ! selected_net || selected_net -> logintype != LOGIN_SASLEXTERNAL ));
gtk_widget_set_sensitive ( edit_check_show_pass , ! active );
servlist_update_password_tools ( selected_net );
}
2026-06-05 10:38:16 -06:00
static char *
servlist_display_password ( ircnet * net )
{
if ( ! net )
return NULL ;
if ( edit_pass_changed )
return g_strdup ( gtk_entry_get_text ( GTK_ENTRY ( edit_entry_pass )));
if ( edit_loaded_password )
return g_strdup ( edit_loaded_password );
if ( net -> flags & FLAG_USE_KEYRING )
return secretstore_get_network_password ( net -> name );
return servlist_password_decrypt_for_storage ( net -> pass );
}
2011-02-24 04:14:30 +01:00
2026-06-02 15:57:28 -06:00
static void
servlist_toggle_show_password_cb ( GtkToggleButton * toggle , gpointer userdata )
{
if ( gtk_toggle_button_get_active ( toggle ))
{
2026-06-05 10:38:16 -06:00
char * password = servlist_display_password ( selected_net );
if ( password )
{
if ( edit_loaded_password )
{
memset ( edit_loaded_password , 0 , strlen ( edit_loaded_password ));
g_free ( edit_loaded_password );
}
edit_loaded_password = g_strdup ( password );
servlist_entry_set_text_silent ( userdata , password );
memset ( password , 0 , strlen ( password ));
g_free ( password );
}
2026-06-02 15:57:28 -06:00
gtk_entry_set_visibility ( GTK_ENTRY ( userdata ), TRUE );
}
else
{
gtk_entry_set_visibility ( GTK_ENTRY ( userdata ), FALSE );
if ( edit_loaded_password && ! edit_pass_changed )
2026-06-05 10:38:16 -06:00
servlist_entry_set_text_silent ( userdata , "***" );
2026-06-02 15:57:28 -06:00
}
}
static void
servlist_toggle_keyring_cb ( GtkToggleButton * toggle , gpointer userdata )
{
2026-06-05 10:38:16 -06:00
servlist_update_password_tools ( selected_net );
2026-06-02 15:57:28 -06:00
}
static void
servlist_password_changed_cb ( GtkEditable * editable , gpointer userdata )
{
edit_pass_changed = 1 ;
if ( edit_loaded_password && strcmp ( gtk_entry_get_text ( GTK_ENTRY ( editable )), "***" ))
{
memset ( edit_loaded_password , 0 , strlen ( edit_loaded_password ));
g_free ( edit_loaded_password );
edit_loaded_password = NULL ;
}
2026-06-05 10:38:16 -06:00
servlist_update_password_tools ( selected_net );
2026-06-02 15:57:28 -06:00
}
static void
2026-06-05 10:38:16 -06:00
servlist_encrypt_password_cb ( GtkWidget * button , gpointer userdata )
2026-06-02 15:57:28 -06:00
{
ircnet * net = userdata ;
2026-06-05 10:38:16 -06:00
char * plain ;
char * enc ;
if ( ! net || ( net -> flags & FLAG_USE_KEYRING ) || ! net -> pass || servlist_password_is_encrypted ( net -> pass ))
2026-06-02 15:57:28 -06:00
return ;
2026-06-05 10:38:16 -06:00
plain = servlist_password_decrypt_for_storage ( net -> pass );
if ( ! plain || !* plain )
{
if ( plain )
{
memset ( plain , 0 , strlen ( plain ));
g_free ( plain );
}
2026-06-02 15:57:28 -06:00
return ;
2026-06-05 10:38:16 -06:00
}
enc = servlist_password_encrypt_for_storage ( plain );
memset ( plain , 0 , strlen ( plain ));
g_free ( plain );
if ( ! enc )
2026-06-02 15:57:28 -06:00
{
2026-06-05 10:38:16 -06:00
fe_message ( _ ( "Could not encrypt this password." ), FE_MSG_WARN );
return ;
2026-06-02 15:57:28 -06:00
}
2026-06-05 10:38:16 -06:00
g_free ( net -> pass );
net -> pass = enc ;
servlist_save ();
servlist_update_password_tools ( net );
}
static void
servlist_import_password_cb ( GtkWidget * button , gpointer userdata )
{
ircnet * net = userdata ;
char * plain ;
if ( ! net || ! net -> name || ( net -> flags & FLAG_USE_KEYRING ) || ! net -> pass || !* net -> pass )
return ;
plain = servlist_password_decrypt_for_storage ( net -> pass );
if ( ! plain || !* plain )
{
if ( plain )
{
memset ( plain , 0 , strlen ( plain ));
g_free ( plain );
}
return ;
}
if ( ! secretstore_set_network_password ( net -> name , plain ))
{
memset ( plain , 0 , strlen ( plain ));
g_free ( plain );
fe_message ( _ ( "Could not move this password into the system keyring." ), FE_MSG_WARN );
return ;
}
memset ( plain , 0 , strlen ( plain ));
g_free ( plain );
g_free ( net -> pass );
net -> pass = NULL ;
net -> flags |= FLAG_USE_KEYRING ;
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( edit_check_use_keyring ), TRUE );
servlist_entry_set_text_silent ( edit_entry_pass , "***" );
2026-06-02 15:57:28 -06:00
edit_pass_changed = 0 ;
2026-06-05 10:38:16 -06:00
servlist_save ();
servlist_update_password_tools ( net );
2026-06-02 15:57:28 -06:00
}
2026-03-24 23:00:09 -06:00
static char *
servlist_get_cert_file ( ircnet * net )
{
if ( ! net || ! net -> name || ! net -> name [ 0 ])
return NULL ;
return g_strdup_printf ( "%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem" ,
get_xdir (), net -> name );
}
static gboolean
servlist_network_cert_exists ( ircnet * net )
{
char * cert_file ;
gboolean exists ;
cert_file = servlist_get_cert_file ( net );
if ( ! cert_file )
return FALSE ;
exists = g_file_test ( cert_file , G_FILE_TEST_IS_REGULAR );
g_free ( cert_file );
return exists ;
}
static void
servlist_update_cert_buttons ( ircnet * net )
{
gboolean has_cert = servlist_network_cert_exists ( net );
if ( edit_button_cert_generate )
gtk_widget_set_visible ( edit_button_cert_generate , ! has_cert );
2026-03-30 11:46:08 -06:00
if ( edit_button_cert_import )
gtk_widget_set_visible ( edit_button_cert_import , ! has_cert );
2026-03-24 23:00:09 -06:00
if ( edit_button_cert_info )
gtk_widget_set_visible ( edit_button_cert_info , has_cert );
if ( edit_button_cert_delete )
gtk_widget_set_visible ( edit_button_cert_delete , has_cert );
}
2026-03-30 11:46:08 -06:00
static void
servlist_import_client_cert_cb ( GtkWidget * button , gpointer userdata )
{
ircnet * net = ( ircnet * ) userdata ;
GtkWidget * dialog ;
GtkWidget * message ;
GtkFileFilter * filter ;
char * cert_dir ;
char * cert_file ;
char * source_file ;
char * contents ;
gsize length ;
if ( ! net || ! net -> name || ! net -> name [ 0 ])
return ;
dialog = gtk_file_chooser_dialog_new ( _ ( "Import Client Certificate" ),
GTK_WINDOW ( edit_win ),
GTK_FILE_CHOOSER_ACTION_OPEN ,
_ ( "_Cancel" ), GTK_RESPONSE_CANCEL ,
_ ( "_Open" ), GTK_RESPONSE_ACCEPT ,
NULL );
filter = gtk_file_filter_new ();
gtk_file_filter_set_name ( filter , _ ( "Certificate files" ));
gtk_file_filter_add_pattern ( filter , "*.pem" );
gtk_file_filter_add_pattern ( filter , "*.crt" );
gtk_file_filter_add_pattern ( filter , "*.cer" );
gtk_file_chooser_add_filter ( GTK_FILE_CHOOSER ( dialog ), filter );
filter = gtk_file_filter_new ();
gtk_file_filter_set_name ( filter , _ ( "All files" ));
gtk_file_filter_add_pattern ( filter , "*" );
gtk_file_chooser_add_filter ( GTK_FILE_CHOOSER ( dialog ), filter );
theme_manager_attach_window ( dialog );
if ( gtk_dialog_run ( GTK_DIALOG ( dialog )) != GTK_RESPONSE_ACCEPT )
{
gtk_widget_destroy ( dialog );
return ;
}
source_file = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER ( dialog ));
gtk_widget_destroy ( dialog );
if ( ! source_file )
return ;
cert_dir = g_build_filename ( get_xdir (), "certs" , NULL );
cert_file = servlist_get_cert_file ( net );
contents = NULL ;
length = 0 ;
if ( cert_file &&
g_mkdir_with_parents ( cert_dir , 0700 ) == 0 &&
g_file_get_contents ( source_file , & contents , & length , NULL ) &&
g_file_set_contents ( cert_file , contents , length , NULL ))
{
chmod ( cert_file , 0600 );
servlist_update_cert_buttons ( net );
message = gtk_message_dialog_new ( GTK_WINDOW ( edit_win ),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
GTK_MESSAGE_INFO ,
GTK_BUTTONS_CLOSE ,
_ ( "Client certificate imported for \" %s \" ." ),
net -> name );
}
else
{
message = gtk_message_dialog_new ( GTK_WINDOW ( edit_win ),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
GTK_MESSAGE_ERROR ,
GTK_BUTTONS_CLOSE ,
_ ( "Failed to import client certificate for \" %s \" ." ),
net -> name );
}
theme_manager_attach_window ( message );
g_signal_connect_swapped ( message , "response" , G_CALLBACK ( gtk_widget_destroy ), message );
gtk_widget_show ( message );
g_free ( contents );
g_free ( cert_file );
g_free ( cert_dir );
g_free ( source_file );
}
2026-03-24 23:00:09 -06:00
static void
servlist_generate_client_cert_cb ( GtkWidget * button , gpointer userdata )
{
#ifdef USE_OPENSSL
ircnet * net = ( ircnet * ) userdata ;
GtkWidget * dialog ;
char * cert_dir ;
char * cert_file ;
char * key_file ;
char * crt_file ;
char * subject ;
2026-03-25 00:26:23 -06:00
char * openssl_conf ;
const char * conf_data ;
2026-03-24 23:00:09 -06:00
char * key_data ;
char * crt_data ;
char * pem_data ;
char * stderr_data ;
char * stdout_data ;
gsize key_len ;
gsize crt_len ;
gboolean spawned ;
gboolean success ;
gint status ;
2026-03-25 00:26:23 -06:00
char * argv [ 20 ];
2026-03-30 11:57:58 -06:00
char ** envp ;
2026-03-24 23:00:09 -06:00
if ( ! net || ! net -> name || ! net -> name [ 0 ])
return ;
cert_dir = g_build_filename ( get_xdir (), "certs" , NULL );
cert_file = servlist_get_cert_file ( net );
key_file = g_strdup_printf ( "%s" G_DIR_SEPARATOR_S "%s.key" , cert_dir , net -> name );
crt_file = g_strdup_printf ( "%s" G_DIR_SEPARATOR_S "%s.crt" , cert_dir , net -> name );
subject = g_strdup_printf ( "/CN=%s" , net -> name );
2026-03-25 00:26:23 -06:00
openssl_conf = g_build_filename ( cert_dir , "openssl.cnf" , NULL );
conf_data = "[req] \n "
"distinguished_name=req_distinguished_name \n "
"[req_distinguished_name] \n " ;
2026-03-24 23:00:09 -06:00
key_data = NULL ;
crt_data = NULL ;
pem_data = NULL ;
stderr_data = NULL ;
stdout_data = NULL ;
key_len = 0 ;
crt_len = 0 ;
success = FALSE ;
status = 0 ;
2026-03-30 11:57:58 -06:00
envp = g_environ_unsetenv ( g_get_environ (), "LD_LIBRARY_PATH" );
2026-03-24 23:00:09 -06:00
2026-03-25 00:26:23 -06:00
if ( g_mkdir_with_parents ( cert_dir , 0700 ) == 0 &&
g_file_set_contents ( openssl_conf , conf_data , - 1 , NULL ))
2026-03-24 23:00:09 -06:00
{
argv [ 0 ] = "openssl" ;
argv [ 1 ] = "req" ;
argv [ 2 ] = "-x509" ;
argv [ 3 ] = "-newkey" ;
argv [ 4 ] = "ec" ;
argv [ 5 ] = "-pkeyopt" ;
argv [ 6 ] = "ec_paramgen_curve:P-256" ;
argv [ 7 ] = "-sha256" ;
argv [ 8 ] = "-days" ;
argv [ 9 ] = "3650" ;
argv [ 10 ] = "-nodes" ;
argv [ 11 ] = "-keyout" ;
argv [ 12 ] = key_file ;
argv [ 13 ] = "-out" ;
argv [ 14 ] = crt_file ;
2026-03-25 00:26:23 -06:00
argv [ 15 ] = "-config" ;
argv [ 16 ] = openssl_conf ;
argv [ 17 ] = "-subj" ;
argv [ 18 ] = subject ;
argv [ 19 ] = NULL ;
2026-03-24 23:00:09 -06:00
2026-03-30 11:57:58 -06:00
spawned = g_spawn_sync ( NULL , argv , envp , G_SPAWN_SEARCH_PATH , NULL , NULL ,
2026-03-24 23:00:09 -06:00
& stdout_data , & stderr_data , & status , NULL );
if ( spawned && g_spawn_check_exit_status ( status , NULL ) &&
g_file_get_contents ( key_file , & key_data , & key_len , NULL ) &&
g_file_get_contents ( crt_file , & crt_data , & crt_len , NULL ))
{
pem_data = g_strconcat ( key_data , crt_data , NULL );
if ( pem_data && g_file_set_contents ( cert_file , pem_data , - 1 , NULL ))
{
chmod ( cert_file , 0600 );
success = TRUE ;
}
}
}
g_remove ( key_file );
g_remove ( crt_file );
2026-03-25 00:26:23 -06:00
g_remove ( openssl_conf );
2026-03-24 23:00:09 -06:00
if ( success )
{
servlist_update_cert_buttons ( net );
dialog = gtk_message_dialog_new ( GTK_WINDOW ( edit_win ),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
GTK_MESSAGE_INFO ,
GTK_BUTTONS_CLOSE ,
_ ( "Client certificate generated for \" %s \" ." ),
net -> name );
}
else
{
dialog = gtk_message_dialog_new ( GTK_WINDOW ( edit_win ),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
GTK_MESSAGE_ERROR ,
GTK_BUTTONS_CLOSE ,
_ ( "Failed to generate the client certificate for \" %s \" ." ),
net -> name );
if ( stderr_data && stderr_data [ 0 ])
gtk_message_dialog_format_secondary_text ( GTK_MESSAGE_DIALOG ( dialog ), "%s" , stderr_data );
}
theme_manager_attach_window ( dialog );
g_signal_connect_swapped ( dialog , "response" , G_CALLBACK ( gtk_widget_destroy ), dialog );
gtk_widget_show ( dialog );
g_free ( stdout_data );
g_free ( stderr_data );
g_free ( pem_data );
g_free ( key_data );
g_free ( crt_data );
g_free ( subject );
g_free ( crt_file );
g_free ( key_file );
2026-03-25 00:26:23 -06:00
g_free ( openssl_conf );
2026-03-24 23:00:09 -06:00
g_free ( cert_file );
g_free ( cert_dir );
2026-03-30 11:57:58 -06:00
g_strfreev ( envp );
2026-03-24 23:00:09 -06:00
#else
return ;
#endif
}
static void
servlist_cert_info_cb ( GtkWidget * button , gpointer userdata )
{
#ifdef USE_OPENSSL
ircnet * net = ( ircnet * ) userdata ;
GtkWidget * dialog ;
char * cert_file ;
char * stdout_data ;
char * stderr_data ;
gboolean spawned ;
gint status ;
char * argv [ 12 ];
2026-03-30 11:57:58 -06:00
char ** envp ;
2026-03-24 23:00:09 -06:00
cert_file = servlist_get_cert_file ( net );
if ( ! cert_file )
return ;
stdout_data = NULL ;
stderr_data = NULL ;
status = 0 ;
2026-03-30 11:57:58 -06:00
envp = g_environ_unsetenv ( g_get_environ (), "LD_LIBRARY_PATH" );
2026-03-24 23:00:09 -06:00
argv [ 0 ] = "openssl" ;
argv [ 1 ] = "x509" ;
argv [ 2 ] = "-in" ;
argv [ 3 ] = cert_file ;
argv [ 4 ] = "-noout" ;
argv [ 5 ] = "-subject" ;
argv [ 6 ] = "-issuer" ;
argv [ 7 ] = "-startdate" ;
argv [ 8 ] = "-enddate" ;
argv [ 9 ] = "-fingerprint" ;
argv [ 10 ] = "-sha256" ;
argv [ 11 ] = NULL ;
2026-03-30 11:57:58 -06:00
spawned = g_spawn_sync ( NULL , argv , envp , G_SPAWN_SEARCH_PATH , NULL , NULL ,
2026-03-24 23:00:09 -06:00
& stdout_data , & stderr_data , & status , NULL );
if ( spawned && g_spawn_check_exit_status ( status , NULL ) && stdout_data && stdout_data [ 0 ])
{
dialog = gtk_message_dialog_new ( GTK_WINDOW ( edit_win ),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
GTK_MESSAGE_INFO ,
GTK_BUTTONS_CLOSE ,
_ ( "Client certificate information for \" %s \" ." ),
net -> name );
gtk_message_dialog_format_secondary_text ( GTK_MESSAGE_DIALOG ( dialog ), "%s" , stdout_data );
}
else
{
dialog = gtk_message_dialog_new ( GTK_WINDOW ( edit_win ),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
GTK_MESSAGE_ERROR ,
GTK_BUTTONS_CLOSE ,
_ ( "Failed to read client certificate information for \" %s \" ." ),
net -> name );
if ( stderr_data && stderr_data [ 0 ])
gtk_message_dialog_format_secondary_text ( GTK_MESSAGE_DIALOG ( dialog ), "%s" , stderr_data );
}
theme_manager_attach_window ( dialog );
g_signal_connect_swapped ( dialog , "response" , G_CALLBACK ( gtk_widget_destroy ), dialog );
gtk_widget_show ( dialog );
g_free ( stdout_data );
g_free ( stderr_data );
g_free ( cert_file );
2026-03-30 11:57:58 -06:00
g_strfreev ( envp );
2026-03-24 23:00:09 -06:00
#else
return ;
#endif
}
static void
servlist_delete_client_cert_cb ( GtkWidget * button , gpointer userdata )
{
ircnet * net = ( ircnet * ) userdata ;
GtkWidget * dialog ;
char * cert_file ;
cert_file = servlist_get_cert_file ( net );
if ( ! cert_file )
return ;
if ( g_remove ( cert_file ) == 0 )
{
servlist_update_cert_buttons ( net );
dialog = gtk_message_dialog_new ( GTK_WINDOW ( edit_win ),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
GTK_MESSAGE_INFO ,
GTK_BUTTONS_CLOSE ,
_ ( "Client certificate removed for \" %s \" ." ),
net -> name );
}
else
{
dialog = gtk_message_dialog_new ( GTK_WINDOW ( edit_win ),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
GTK_MESSAGE_ERROR ,
GTK_BUTTONS_CLOSE ,
_ ( "Failed to remove client certificate for \" %s \" ." ),
net -> name );
}
theme_manager_attach_window ( dialog );
g_signal_connect_swapped ( dialog , "response" , G_CALLBACK ( gtk_widget_destroy ), dialog );
gtk_widget_show ( dialog );
g_free ( cert_file );
}
2026-01-30 15:27:01 -07:00
static GtkWidget *
servlist_icon_button_new ( const char * label , const char * icon_name )
{
GtkWidget * button ;
2026-03-27 10:38:26 -06:00
( void ) icon_name ;
2026-01-30 15:27:01 -07:00
button = gtk_button_new_with_mnemonic ( label );
return button ;
}
2011-02-24 04:14:30 +01:00
static const char * pages [] =
{
2012-10-13 06:17:27 +02:00
IRC_DEFAULT_CHARSET ,
2015-01-18 02:10:04 -08:00
"CP1252 (Windows-1252)" ,
2011-02-24 04:14:30 +01:00
"ISO-8859-15 (Western Europe)" ,
"ISO-8859-2 (Central Europe)" ,
"ISO-8859-7 (Greek)" ,
"ISO-8859-8 (Hebrew)" ,
"ISO-8859-9 (Turkish)" ,
"ISO-2022-JP (Japanese)" ,
"SJIS (Japanese)" ,
"CP949 (Korean)" ,
"KOI8-R (Cyrillic)" ,
"CP1251 (Cyrillic)" ,
"CP1256 (Arabic)" ,
"CP1257 (Baltic)" ,
"GB18030 (Chinese)" ,
"TIS-620 (Thai)" ,
NULL
};
2013-05-10 23:52:47 +02:00
/* This is our dictionary for authentication types. Keep these in sync with
* login_types[]! This allows us to re-order the login type dropdown in the
* network list without breaking config compatibility.
2013-05-11 02:40:08 +02:00
*
* Also make sure inbound_nickserv_login() won't break, i.e. if you add a new
2026-01-05 23:12:38 -07:00
* type that is NickServ-based, add it there as well so that ZoiteChat knows to
2013-05-11 02:40:08 +02:00
* treat it as such.
2013-05-10 23:52:47 +02:00
*/
static int login_types_conf [] =
{
2013-05-13 13:22:25 +02:00
LOGIN_DEFAULT , /* default entry - we don't use this but it makes indexing consistent with login_types[] so it's nice */
LOGIN_SASL ,
2013-09-04 17:34:57 -04:00
#ifdef USE_OPENSSL
2013-09-02 14:24:37 -04:00
LOGIN_SASLEXTERNAL ,
2023-11-01 19:12:32 +01:00
LOGIN_SASL_SCRAM_SHA_1 ,
LOGIN_SASL_SCRAM_SHA_256 ,
LOGIN_SASL_SCRAM_SHA_512 ,
2013-09-04 17:34:57 -04:00
#endif
2013-05-13 13:22:25 +02:00
LOGIN_PASS ,
LOGIN_MSG_NICKSERV ,
LOGIN_NICKSERV ,
2013-09-04 17:34:57 -04:00
#ifdef USE_OPENSSL
2013-05-19 04:34:20 +02:00
LOGIN_CHALLENGEAUTH ,
2013-09-04 17:34:57 -04:00
#endif
2013-05-19 04:34:20 +02:00
LOGIN_CUSTOM
2013-05-11 20:42:29 +02:00
#if 0
2013-05-13 13:22:25 +02:00
LOGIN_NS,
2013-05-19 05:17:13 +02:00
LOGIN_MSG_NS,
2013-05-13 13:22:25 +02:00
LOGIN_AUTH,
2013-05-17 01:39:28 +02:00
#endif
2013-05-10 23:52:47 +02:00
};
static const char * login_types [] =
2013-04-28 21:24:53 +02:00
{
2013-05-10 23:52:47 +02:00
"Default" ,
2023-11-01 19:12:32 +01:00
"SASL PLAIN (username + password)" ,
2013-09-04 17:34:57 -04:00
#ifdef USE_OPENSSL
2013-09-02 14:24:37 -04:00
"SASL EXTERNAL (cert)" ,
2023-11-01 19:12:32 +01:00
"SASL SCRAM-SHA-1" ,
"SASL SCRAM-SHA-256" ,
"SASL SCRAM-SHA-512" ,
2013-09-04 17:34:57 -04:00
#endif
2017-08-19 20:48:50 +02:00
"Server password (/PASS password)" ,
2013-05-11 20:42:29 +02:00
"NickServ (/MSG NickServ + password)" ,
2013-05-12 16:37:32 +02:00
"NickServ (/NICKSERV + password)" ,
2013-09-04 17:34:57 -04:00
#ifdef USE_OPENSSL
2013-05-17 01:39:28 +02:00
"Challenge Auth (username + password)" ,
2013-09-04 17:34:57 -04:00
#endif
2013-05-19 04:34:20 +02:00
"Custom... (connect commands)" ,
2013-05-11 20:42:29 +02:00
#if 0
"NickServ (/NS + password)",
2013-05-19 05:17:13 +02:00
"NickServ (/MSG NS + password)",
2013-05-11 20:42:29 +02:00
"AUTH (/AUTH nickname password)",
2013-05-17 01:39:28 +02:00
#endif
2013-04-28 21:24:53 +02:00
NULL
};
2013-05-10 23:52:47 +02:00
/* poor man's IndexOf() - find the dropdown string index that belongs to the given config value */
static int
servlist_get_login_desc_index ( int conf_value )
{
int i ;
int length = sizeof ( login_types_conf ) / sizeof ( login_types_conf [ 0 ]); /* the number of elements in the conf array */
for ( i = 0 ; i < length ; i ++ )
{
if ( login_types_conf [ i ] == conf_value )
{
return i ;
}
}
return 0 ; /* make the compiler happy */
}
2011-02-24 04:14:30 +01:00
static void
servlist_select_and_show ( GtkTreeView * treeview , GtkTreeIter * iter ,
GtkListStore * store )
{
GtkTreePath * path ;
GtkTreeSelection * sel ;
sel = gtk_tree_view_get_selection ( treeview );
/* select this network */
gtk_tree_selection_select_iter ( sel , iter );
/* and make sure it's visible */
path = gtk_tree_model_get_path ( GTK_TREE_MODEL ( store ), iter );
if ( path )
{
gtk_tree_view_scroll_to_cell ( treeview , path , NULL , TRUE , 0.5 , 0.5 );
gtk_tree_view_set_cursor ( treeview , path , NULL , FALSE );
gtk_tree_path_free ( path );
}
}
2013-05-11 09:20:03 -04:00
static void
servlist_channels_populate ( ircnet * net , GtkWidget * treeview )
{
GtkListStore * store ;
GtkTreeIter iter ;
2013-05-12 05:44:32 +02:00
int i ;
favchannel * favchan ;
GSList * list = net -> favchanlist ;
2013-05-11 09:20:03 -04:00
2013-05-12 05:44:32 +02:00
store = ( GtkListStore * ) gtk_tree_view_get_model ( GTK_TREE_VIEW ( treeview ));
gtk_list_store_clear ( store );
2013-05-11 09:20:03 -04:00
2013-05-12 05:44:32 +02:00
i = 0 ;
while ( list )
{
favchan = list -> data ;
gtk_list_store_append ( store , & iter );
gtk_list_store_set ( store , & iter , 0 , favchan -> name , 1 , favchan -> key , 2 , TRUE , - 1 );
2013-05-11 09:20:03 -04:00
2013-05-12 05:44:32 +02:00
if ( net -> selected == i )
2013-05-11 09:20:03 -04:00
{
2013-05-12 05:44:32 +02:00
/* select this server */
servlist_select_and_show ( GTK_TREE_VIEW ( treeview ), & iter , store );
2013-05-11 09:20:03 -04:00
}
2013-05-12 05:44:32 +02:00
i ++ ;
list = list -> next ;
2013-05-11 09:20:03 -04:00
}
}
2011-02-24 04:14:30 +01:00
static void
servlist_servers_populate ( ircnet * net , GtkWidget * treeview )
{
GtkListStore * store ;
GtkTreeIter iter ;
int i ;
ircserver * serv ;
GSList * list = net -> servlist ;
store = ( GtkListStore * ) gtk_tree_view_get_model ( GTK_TREE_VIEW ( treeview ));
gtk_list_store_clear ( store );
i = 0 ;
while ( list )
{
serv = list -> data ;
gtk_list_store_append ( store , & iter );
gtk_list_store_set ( store , & iter , 0 , serv -> hostname , 1 , 1 , - 1 );
if ( net -> selected == i )
2013-05-12 05:44:32 +02:00
{
2011-02-24 04:14:30 +01:00
/* select this server */
servlist_select_and_show ( GTK_TREE_VIEW ( treeview ), & iter , store );
2013-05-12 05:44:32 +02:00
}
2011-02-24 04:14:30 +01:00
i ++ ;
list = list -> next ;
}
}
2013-05-11 20:06:22 +02:00
static void
servlist_commands_populate ( ircnet * net , GtkWidget * treeview )
{
GtkListStore * store ;
GtkTreeIter iter ;
int i ;
commandentry * entry ;
GSList * list = net -> commandlist ;
store = ( GtkListStore * ) gtk_tree_view_get_model ( GTK_TREE_VIEW ( treeview ));
gtk_list_store_clear ( store );
i = 0 ;
while ( list )
{
entry = list -> data ;
gtk_list_store_append ( store , & iter );
gtk_list_store_set ( store , & iter , 0 , entry -> command , 1 , 1 , - 1 );
if ( net -> selected == i )
{
/* select this server */
servlist_select_and_show ( GTK_TREE_VIEW ( treeview ), & iter , store );
}
i ++ ;
list = list -> next ;
}
}
2011-02-24 04:14:30 +01:00
static void
servlist_networks_populate_ ( GtkWidget * treeview , GSList * netlist , gboolean favorites )
{
GtkListStore * store ;
GtkTreeIter iter ;
int i ;
ircnet * net ;
if ( ! netlist )
{
net = servlist_net_add ( _ ( "New Network" ), "" , FALSE );
2021-05-23 06:58:18 +01:00
servlist_server_add ( net , DEFAULT_SERVER );
2011-02-24 04:14:30 +01:00
netlist = network_list ;
}
store = ( GtkListStore * ) gtk_tree_view_get_model ( GTK_TREE_VIEW ( treeview ));
gtk_list_store_clear ( store );
i = 0 ;
while ( netlist )
{
net = netlist -> data ;
if ( ! favorites || ( net -> flags & FLAG_FAVORITE ))
{
if ( favorites )
gtk_list_store_insert_with_values ( store , & iter , 0x7fffffff , 0 , net -> name , 1 , 1 , 2 , 400 , - 1 );
else
gtk_list_store_insert_with_values ( store , & iter , 0x7fffffff , 0 , net -> name , 1 , 1 , 2 , ( net -> flags & FLAG_FAVORITE ) ? 800 : 400 , - 1 );
2012-10-22 13:49:28 +02:00
if ( i == prefs . hex_gui_slist_select )
2011-02-24 04:14:30 +01:00
{
/* select this network */
servlist_select_and_show ( GTK_TREE_VIEW ( treeview ), & iter , store );
selected_net = net ;
}
}
i ++ ;
netlist = netlist -> next ;
}
}
static void
servlist_networks_populate ( GtkWidget * treeview , GSList * netlist )
{
2012-10-22 13:49:28 +02:00
servlist_networks_populate_ ( treeview , netlist , prefs . hex_gui_slist_fav );
2011-02-24 04:14:30 +01:00
}
static void
servlist_server_row_cb ( GtkTreeSelection * sel , gpointer user_data )
{
GtkTreeModel * model ;
GtkTreeIter iter ;
ircserver * serv ;
char * servname ;
int pos ;
if ( ! selected_net )
return ;
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_tree_model_get ( model , & iter , 0 , & servname , - 1 );
serv = servlist_server_find ( selected_net , servname , & pos );
g_free ( servname );
if ( serv )
selected_net -> selected = pos ;
selected_serv = serv ;
}
}
2013-05-20 13:19:20 -03:00
static void
servlist_command_row_cb ( GtkTreeSelection * sel , gpointer user_data )
{
GtkTreeModel * model ;
GtkTreeIter iter ;
commandentry * cmd ;
char * cmdname ;
int pos ;
if ( ! selected_net )
return ;
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_tree_model_get ( model , & iter , 0 , & cmdname , - 1 );
cmd = servlist_command_find ( selected_net , cmdname , & pos );
g_free ( cmdname );
if ( cmd )
selected_net -> selected = pos ;
selected_cmd = cmd ;
}
}
static void
servlist_channel_row_cb ( GtkTreeSelection * sel , gpointer user_data )
{
GtkTreeModel * model ;
GtkTreeIter iter ;
favchannel * channel ;
char * channame ;
int pos ;
if ( ! selected_net )
return ;
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_tree_model_get ( model , & iter , 0 , & channame , - 1 );
channel = servlist_favchan_find ( selected_net , channame , & pos );
g_free ( channame );
if ( channel )
selected_net -> selected = pos ;
selected_chan = channel ;
}
}
2011-02-24 04:14:30 +01:00
static void
servlist_start_editing ( GtkTreeView * tree )
{
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
GtkTreePath * path ;
sel = gtk_tree_view_get_selection ( tree );
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
path = gtk_tree_model_get_path ( GTK_TREE_MODEL ( model ), & iter );
if ( path )
{
gtk_tree_view_set_cursor ( tree , path ,
gtk_tree_view_get_column ( tree , 0 ), TRUE );
gtk_tree_path_free ( path );
}
}
}
static void
2013-05-11 09:20:03 -04:00
servlist_addserver ( void )
2011-02-24 04:14:30 +01:00
{
GtkTreeIter iter ;
GtkListStore * store ;
if ( ! selected_net )
return ;
2013-05-11 09:20:03 -04:00
store = GTK_LIST_STORE ( gtk_tree_view_get_model ( GTK_TREE_VIEW ( edit_trees [ SERVER_TREE ])));
2021-05-23 06:58:18 +01:00
servlist_server_add ( selected_net , DEFAULT_SERVER );
2011-02-24 04:14:30 +01:00
gtk_list_store_append ( store , & iter );
2021-05-23 06:58:18 +01:00
gtk_list_store_set ( store , & iter , 0 , DEFAULT_SERVER , 1 , TRUE , - 1 );
2011-02-24 04:14:30 +01:00
/* select this server */
2013-05-11 09:20:03 -04:00
servlist_select_and_show ( GTK_TREE_VIEW ( edit_trees [ SERVER_TREE ]), & iter , store );
2013-05-11 20:06:22 +02:00
servlist_start_editing ( GTK_TREE_VIEW ( edit_trees [ SERVER_TREE ]));
2011-02-24 04:14:30 +01:00
servlist_server_row_cb ( gtk_tree_view_get_selection ( GTK_TREE_VIEW ( networks_tree )), NULL );
}
2013-05-11 09:20:03 -04:00
static void
servlist_addcommand ( void )
{
GtkTreeIter iter ;
GtkListStore * store ;
if ( ! selected_net )
return ;
store = GTK_LIST_STORE ( gtk_tree_view_get_model ( GTK_TREE_VIEW ( edit_trees [ CMD_TREE ])));
2013-05-11 20:06:22 +02:00
servlist_command_add ( selected_net , "ECHO hello" );
2013-05-11 09:20:03 -04:00
gtk_list_store_append ( store , & iter );
2013-05-12 05:44:32 +02:00
gtk_list_store_set ( store , & iter , 0 , "ECHO hello" , 1 , TRUE , - 1 );
2013-05-11 09:20:03 -04:00
servlist_select_and_show ( GTK_TREE_VIEW ( edit_trees [ CMD_TREE ]), & iter , store );
2013-05-11 20:06:22 +02:00
servlist_start_editing ( GTK_TREE_VIEW ( edit_trees [ CMD_TREE ]));
2013-05-11 09:20:03 -04:00
2013-05-20 13:19:20 -03:00
servlist_command_row_cb ( gtk_tree_view_get_selection ( GTK_TREE_VIEW ( networks_tree )), NULL );
2013-05-11 09:20:03 -04:00
}
2013-05-12 05:44:32 +02:00
static void
servlist_addchannel ( void )
{
GtkTreeIter iter ;
GtkListStore * store ;
if ( ! selected_net )
return ;
store = GTK_LIST_STORE ( gtk_tree_view_get_model ( GTK_TREE_VIEW ( edit_trees [ CHANNEL_TREE ])));
servlist_favchan_add ( selected_net , "#channel" );
gtk_list_store_append ( store , & iter );
gtk_list_store_set ( store , & iter , 0 , "#channel" , 1 , "" , 2 , TRUE , - 1 );
/* select this server */
servlist_select_and_show ( GTK_TREE_VIEW ( edit_trees [ CHANNEL_TREE ]), & iter , store );
servlist_start_editing ( GTK_TREE_VIEW ( edit_trees [ CHANNEL_TREE ]));
2013-05-20 13:19:20 -03:00
servlist_channel_row_cb ( gtk_tree_view_get_selection ( GTK_TREE_VIEW ( networks_tree )), NULL );
2013-05-12 05:44:32 +02:00
}
2011-02-24 04:14:30 +01:00
static void
servlist_addnet_cb ( GtkWidget * item , GtkTreeView * treeview )
{
GtkTreeIter iter ;
GtkListStore * store ;
ircnet * net ;
net = servlist_net_add ( _ ( "New Network" ), "" , TRUE );
2014-12-28 06:37:25 -05:00
net -> encoding = g_strdup ( IRC_DEFAULT_CHARSET );
2021-05-23 06:58:18 +01:00
servlist_server_add ( net , DEFAULT_SERVER );
2011-02-24 04:14:30 +01:00
store = ( GtkListStore * ) gtk_tree_view_get_model ( treeview );
gtk_list_store_prepend ( store , & iter );
gtk_list_store_set ( store , & iter , 0 , net -> name , 1 , 1 , - 1 );
/* select this network */
servlist_select_and_show ( GTK_TREE_VIEW ( networks_tree ), & iter , store );
servlist_start_editing ( GTK_TREE_VIEW ( networks_tree ));
servlist_network_row_cb ( gtk_tree_view_get_selection ( GTK_TREE_VIEW ( networks_tree )), NULL );
}
static void
servlist_deletenetwork ( ircnet * net )
{
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
/* remove from GUI */
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( networks_tree ));
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
gtk_list_store_remove ( GTK_LIST_STORE ( model ), & iter );
/* remove from list */
servlist_net_remove ( net );
/* force something to be selected */
gtk_tree_model_get_iter_first ( model , & iter );
servlist_select_and_show ( GTK_TREE_VIEW ( networks_tree ), & iter ,
GTK_LIST_STORE ( model ));
servlist_network_row_cb ( sel , NULL );
}
static void
servlist_deletenetdialog_cb ( GtkDialog * dialog , gint arg1 , ircnet * net )
{
gtk_widget_destroy ( GTK_WIDGET ( dialog ));
if ( arg1 == GTK_RESPONSE_OK )
servlist_deletenetwork ( net );
}
2013-05-20 13:19:20 -03:00
static GSList *
servlist_move_item ( GtkTreeView * view , GSList * list , gpointer item , int delta )
2011-02-24 04:14:30 +01:00
{
2013-05-20 13:19:20 -03:00
GtkTreeModel * store ;
GtkTreeIter iter1 , iter2 ;
GtkTreeSelection * sel ;
GtkTreePath * path ;
2011-02-24 04:14:30 +01:00
int pos ;
2013-05-20 13:19:20 -03:00
/* Keep tree in sync w/ list, there has to be an easier way to get iters */
sel = gtk_tree_view_get_selection ( view );
gtk_tree_selection_get_selected ( sel , & store , & iter1 );
path = gtk_tree_model_get_path ( store , & iter1 );
if ( delta == 1 )
gtk_tree_path_next ( path );
else
gtk_tree_path_prev ( path );
gtk_tree_model_get_iter ( store , & iter2 , path );
2013-06-04 12:32:51 -03:00
gtk_tree_path_free ( path );
2013-05-20 13:19:20 -03:00
pos = g_slist_index ( list , item );
2011-02-24 04:14:30 +01:00
if ( pos >= 0 )
{
pos += delta ;
if ( pos >= 0 )
{
2013-05-20 13:19:20 -03:00
list = g_slist_remove ( list , item );
list = g_slist_insert ( list , item , pos );
2011-02-24 04:14:30 +01:00
2013-05-20 13:19:20 -03:00
gtk_list_store_swap ( GTK_LIST_STORE ( store ), & iter1 , & iter2 );
2011-02-24 04:14:30 +01:00
}
}
2013-05-20 13:19:20 -03:00
return list ;
2011-02-24 04:14:30 +01:00
}
static gboolean
servlist_net_keypress_cb ( GtkWidget * wid , GdkEventKey * evt , gpointer tree )
{
2013-05-20 13:19:20 -03:00
gboolean handled = FALSE ;
if ( ! selected_net || prefs . hex_gui_slist_fav )
2011-02-24 04:14:30 +01:00
return FALSE ;
2012-10-21 03:03:38 +02:00
if ( evt -> state & STATE_SHIFT )
2011-02-24 04:14:30 +01:00
{
2013-09-15 03:21:56 -04:00
if ( evt -> keyval == GDK_KEY_Up )
2011-02-24 04:14:30 +01:00
{
2013-05-20 13:19:20 -03:00
handled = TRUE ;
network_list = servlist_move_item ( GTK_TREE_VIEW ( tree ), network_list , selected_net , - 1 );
2011-02-24 04:14:30 +01:00
}
2013-09-15 03:21:56 -04:00
else if ( evt -> keyval == GDK_KEY_Down )
2011-02-24 04:14:30 +01:00
{
2013-05-20 13:19:20 -03:00
handled = TRUE ;
network_list = servlist_move_item ( GTK_TREE_VIEW ( tree ), network_list , selected_net , + 1 );
2011-02-24 04:14:30 +01:00
}
}
2013-05-20 13:19:20 -03:00
return handled ;
2011-02-24 04:14:30 +01:00
}
static gint
servlist_compare ( ircnet * net1 , ircnet * net2 )
{
gchar * net1_casefolded , * net2_casefolded ;
int result = 0 ;
net1_casefolded = g_utf8_casefold ( net1 -> name , - 1 ),
net2_casefolded = g_utf8_casefold ( net2 -> name , - 1 ),
result = g_utf8_collate ( net1_casefolded , net2_casefolded );
g_free ( net1_casefolded );
g_free ( net2_casefolded );
return result ;
}
static void
servlist_sort ( GtkWidget * button , gpointer none )
{
network_list = g_slist_sort ( network_list ,( GCompareFunc ) servlist_compare );
servlist_networks_populate ( networks_tree , network_list );
}
static gboolean
servlist_has_selection ( GtkTreeView * tree )
{
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
/* make sure something is selected */
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( tree ));
return gtk_tree_selection_get_selected ( sel , & model , & iter );
}
static void
servlist_favor ( GtkWidget * button , gpointer none )
{
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
if ( ! selected_net )
return ;
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( networks_tree ));
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
if ( selected_net -> flags & FLAG_FAVORITE )
{
gtk_list_store_set ( GTK_LIST_STORE ( model ), & iter , 2 , 400 , - 1 );
selected_net -> flags &= ~ FLAG_FAVORITE ;
}
else
{
gtk_list_store_set ( GTK_LIST_STORE ( model ), & iter , 2 , 800 , - 1 );
selected_net -> flags |= FLAG_FAVORITE ;
}
}
}
static void
servlist_update_from_entry ( char ** str , GtkWidget * entry )
{
2014-12-28 06:37:25 -05:00
g_free ( * str );
2011-02-24 04:14:30 +01:00
2013-05-12 01:43:27 -04:00
if ( gtk_entry_get_text ( GTK_ENTRY ( entry ))[ 0 ] == 0 )
2011-02-24 04:14:30 +01:00
* str = NULL ;
else
2014-12-28 06:37:25 -05:00
* str = g_strdup ( gtk_entry_get_text ( GTK_ENTRY ( entry )));
2011-02-24 04:14:30 +01:00
}
2026-06-05 10:38:16 -06:00
static char *
servlist_edit_current_password ( ircnet * net )
{
if ( ! net )
return NULL ;
if ( net -> flags & FLAG_USE_KEYRING )
return secretstore_get_network_password ( net -> name );
return servlist_password_decrypt_for_storage ( net -> pass );
}
2011-02-24 04:14:30 +01:00
static void
servlist_edit_update ( ircnet * net )
{
2026-06-05 10:38:16 -06:00
gboolean use_keyring ;
2026-07-09 12:50:13 -06:00
gboolean ask_pass ;
2026-06-05 10:38:16 -06:00
gboolean keyring_changed ;
char * password = NULL ;
2011-02-24 04:14:30 +01:00
servlist_update_from_entry ( & net -> nick , edit_entry_nick );
servlist_update_from_entry ( & net -> nick2 , edit_entry_nick2 );
servlist_update_from_entry ( & net -> user , edit_entry_user );
servlist_update_from_entry ( & net -> real , edit_entry_real );
2026-06-02 15:57:28 -06:00
if ( net && net -> name )
{
2026-07-09 12:50:13 -06:00
ask_pass = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( edit_check_ask_pass ));
use_keyring = ! ask_pass && gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( edit_check_use_keyring ));
2026-06-05 10:38:16 -06:00
keyring_changed = !! ( net -> flags & FLAG_USE_KEYRING ) != !! use_keyring ;
2026-07-09 12:50:13 -06:00
if ( ask_pass )
{
secretstore_delete_network_password ( net -> name );
if ( net -> pass )
{
memset ( net -> pass , 0 , strlen ( net -> pass ));
g_free ( net -> pass );
net -> pass = NULL ;
}
net -> flags &= ~ FLAG_USE_KEYRING ;
net -> flags |= FLAG_PROMPT_PASSWORD ;
return ;
}
net -> flags &= ~ FLAG_PROMPT_PASSWORD ;
2026-06-05 10:38:16 -06:00
if ( ! edit_pass_changed && ! keyring_changed )
2026-06-02 15:57:28 -06:00
return ;
2026-06-05 10:38:16 -06:00
if ( edit_pass_changed )
password = g_strdup ( gtk_entry_get_text ( GTK_ENTRY ( edit_entry_pass )));
else
password = servlist_edit_current_password ( net );
if ( use_keyring )
2026-06-02 15:57:28 -06:00
{
if ( password && * password )
{
if ( ! secretstore_set_network_password ( net -> name , password ))
2026-06-05 10:38:16 -06:00
{
2026-06-02 15:57:28 -06:00
fe_message ( _ ( "No system keyring is available. ZoiteChat can save this password using local encrypted fallback storage, but it is less protected than your desktop keyring." ), FE_MSG_WARN );
2026-06-05 10:38:16 -06:00
memset ( password , 0 , strlen ( password ));
g_free ( password );
return ;
}
2026-06-02 15:57:28 -06:00
}
else
secretstore_delete_network_password ( net -> name );
2026-06-05 10:38:16 -06:00
net -> flags |= FLAG_USE_KEYRING ;
g_free ( net -> pass );
net -> pass = NULL ;
2026-06-02 15:57:28 -06:00
}
else
{
char * enc = NULL ;
if ( password && * password )
2026-06-05 10:38:16 -06:00
{
2026-06-02 15:57:28 -06:00
enc = servlist_password_encrypt_for_storage ( password );
2026-06-05 10:38:16 -06:00
if ( ! enc )
{
fe_message ( _ ( "Could not encrypt this password." ), FE_MSG_WARN );
memset ( password , 0 , strlen ( password ));
g_free ( password );
return ;
}
}
secretstore_delete_network_password ( net -> name );
net -> flags &= ~ FLAG_USE_KEYRING ;
2026-06-02 15:57:28 -06:00
g_free ( net -> pass );
net -> pass = enc ;
}
2026-06-05 10:38:16 -06:00
if ( password )
{
memset ( password , 0 , strlen ( password ));
g_free ( password );
}
2026-06-02 15:57:28 -06:00
}
2011-02-24 04:14:30 +01:00
}
static void
servlist_edit_close_cb ( GtkWidget * button , gpointer userdata )
{
if ( selected_net )
servlist_edit_update ( selected_net );
2026-06-02 15:57:28 -06:00
if ( edit_loaded_password )
{
memset ( edit_loaded_password , 0 , strlen ( edit_loaded_password ));
g_free ( edit_loaded_password );
edit_loaded_password = NULL ;
}
2011-02-24 04:14:30 +01:00
gtk_widget_destroy ( edit_win );
edit_win = NULL ;
2026-06-05 10:38:16 -06:00
edit_entry_pass = NULL ;
edit_check_show_pass = NULL ;
2026-07-09 12:50:13 -06:00
edit_check_ask_pass = NULL ;
2026-06-05 10:38:16 -06:00
edit_button_encrypt_pass = NULL ;
edit_button_import_pass = NULL ;
2011-02-24 04:14:30 +01:00
}
static gint
servlist_editwin_delete_cb ( GtkWidget * win , GdkEventAny * event , gpointer none )
{
servlist_edit_close_cb ( NULL , NULL );
return FALSE ;
}
static gboolean
servlist_configure_cb ( GtkWindow * win , GdkEventConfigure * event , gpointer none )
{
/* remember the window size */
2013-05-11 15:58:52 +02:00
gtk_window_get_size ( win , & netlist_win_width , & netlist_win_height );
return FALSE ;
}
static gboolean
servlist_edit_configure_cb ( GtkWindow * win , GdkEventConfigure * event , gpointer none )
{
/* remember the window size */
gtk_window_get_size ( win , & netedit_win_width , & netedit_win_height );
2011-02-24 04:14:30 +01:00
return FALSE ;
}
static void
servlist_edit_cb ( GtkWidget * but , gpointer none )
{
if ( ! servlist_has_selection ( GTK_TREE_VIEW ( networks_tree )))
return ;
2026-06-02 15:57:28 -06:00
if ( ! selected_net || ! selected_net -> name )
return ;
if (( selected_net -> flags & FLAG_USE_KEYRING ) && ! secretstore_require_unlock ( selected_net -> name ))
return ;
2011-02-24 04:14:30 +01:00
edit_win = servlist_open_edit ( serverlist_win , selected_net );
gtkutil_set_icon ( edit_win );
2013-05-11 09:20:03 -04:00
servlist_servers_populate ( selected_net , edit_trees [ SERVER_TREE ]);
2013-05-12 05:44:32 +02:00
servlist_channels_populate ( selected_net , edit_trees [ CHANNEL_TREE ]);
2013-05-11 20:06:22 +02:00
servlist_commands_populate ( selected_net , edit_trees [ CMD_TREE ]);
2026-03-17 10:30:54 -06:00
g_signal_connect ( G_OBJECT ( edit_win ), "delete-event" ,
2011-02-24 04:14:30 +01:00
G_CALLBACK ( servlist_editwin_delete_cb ), 0 );
2026-03-17 10:30:54 -06:00
g_signal_connect ( G_OBJECT ( edit_win ), "configure-event" ,
2013-05-11 15:58:52 +02:00
G_CALLBACK ( servlist_edit_configure_cb ), 0 );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( edit_win );
}
static void
servlist_deletenet_cb ( GtkWidget * item , ircnet * net )
{
GtkWidget * dialog ;
if ( ! servlist_has_selection ( GTK_TREE_VIEW ( networks_tree )))
return ;
net = selected_net ;
if ( ! net )
return ;
dialog = gtk_message_dialog_new ( GTK_WINDOW ( serverlist_win ),
GTK_DIALOG_DESTROY_WITH_PARENT |
GTK_DIALOG_MODAL ,
GTK_MESSAGE_QUESTION ,
GTK_BUTTONS_OK_CANCEL ,
_ ( "Really remove network \" %s \" and all its servers?" ),
net -> name );
2026-03-04 23:28:01 -07:00
theme_manager_attach_window ( dialog );
2011-02-24 04:14:30 +01:00
g_signal_connect ( dialog , "response" ,
G_CALLBACK ( servlist_deletenetdialog_cb ), net );
gtk_window_set_position ( GTK_WINDOW ( dialog ), GTK_WIN_POS_MOUSE );
gtk_widget_show ( dialog );
}
static void
servlist_deleteserver ( ircserver * serv , GtkTreeModel * model )
{
GtkTreeSelection * sel ;
GtkTreeIter iter ;
/* don't remove the last server */
if ( selected_net && g_slist_length ( selected_net -> servlist ) < 2 )
return ;
/* remove from GUI */
2013-05-11 09:20:03 -04:00
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( edit_trees [ SERVER_TREE ]));
2011-02-24 04:14:30 +01:00
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
gtk_list_store_remove ( GTK_LIST_STORE ( model ), & iter );
/* remove from list */
if ( selected_net )
servlist_server_remove ( selected_net , serv );
}
static void
2013-05-11 09:20:03 -04:00
servlist_editbutton_cb ( GtkWidget * item , GtkNotebook * notebook )
2011-02-24 04:14:30 +01:00
{
2013-05-11 09:20:03 -04:00
servlist_start_editing ( GTK_TREE_VIEW ( edit_trees [ gtk_notebook_get_current_page ( notebook )]));
2011-02-24 04:14:30 +01:00
}
static void
2013-05-11 09:20:03 -04:00
servlist_deleteserver_cb ( void )
2011-02-24 04:14:30 +01:00
{
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
char * servname ;
ircserver * serv ;
int pos ;
/* find the selected item in the GUI */
2013-05-11 09:20:03 -04:00
model = gtk_tree_view_get_model ( GTK_TREE_VIEW ( edit_trees [ SERVER_TREE ]));
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( edit_trees [ SERVER_TREE ]));
2011-02-24 04:14:30 +01:00
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_tree_model_get ( model , & iter , 0 , & servname , - 1 );
serv = servlist_server_find ( selected_net , servname , & pos );
g_free ( servname );
if ( serv )
2013-05-11 20:06:22 +02:00
{
2011-02-24 04:14:30 +01:00
servlist_deleteserver ( serv , model );
2013-05-11 20:06:22 +02:00
}
}
}
static void
servlist_deletecommand ( commandentry * entry , GtkTreeModel * model )
{
GtkTreeSelection * sel ;
GtkTreeIter iter ;
/* remove from GUI */
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( edit_trees [ CMD_TREE ]));
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_list_store_remove ( GTK_LIST_STORE ( model ), & iter );
}
/* remove from list */
if ( selected_net )
{
servlist_command_remove ( selected_net , entry );
}
}
static void
servlist_deletecommand_cb ( void )
{
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
char * command ;
commandentry * entry ;
int pos ;
/* find the selected item in the GUI */
model = gtk_tree_view_get_model ( GTK_TREE_VIEW ( edit_trees [ CMD_TREE ]));
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( edit_trees [ CMD_TREE ]));
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_tree_model_get ( model , & iter , 0 , & command , - 1 ); /* query the content of the selection */
entry = servlist_command_find ( selected_net , command , & pos );
g_free ( command );
if ( entry )
{
servlist_deletecommand ( entry , model );
}
2011-02-24 04:14:30 +01:00
}
}
2013-05-12 05:44:32 +02:00
static void
servlist_deletechannel ( favchannel * favchan , GtkTreeModel * model )
{
GtkTreeSelection * sel ;
GtkTreeIter iter ;
/* remove from GUI */
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( edit_trees [ CHANNEL_TREE ]));
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_list_store_remove ( GTK_LIST_STORE ( model ), & iter );
}
/* remove from list */
if ( selected_net )
{
servlist_favchan_remove ( selected_net , favchan );
}
}
static void
servlist_deletechannel_cb ( void )
{
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
char * name ;
char * key ;
favchannel * favchan ;
int pos ;
/* find the selected item in the GUI */
model = gtk_tree_view_get_model ( GTK_TREE_VIEW ( edit_trees [ CHANNEL_TREE ]));
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( edit_trees [ CHANNEL_TREE ]));
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_tree_model_get ( model , & iter , 0 , & name , 1 , & key , - 1 ); /* query the content of the selection */
favchan = servlist_favchan_find ( selected_net , name , & pos );
g_free ( name );
if ( favchan )
{
servlist_deletechannel ( favchan , model );
}
}
}
2011-02-24 04:14:30 +01:00
static ircnet *
servlist_find_selected_net ( GtkTreeSelection * sel )
{
GtkTreeModel * model ;
GtkTreeIter iter ;
char * netname ;
int pos ;
ircnet * net = NULL ;
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ))
{
gtk_tree_model_get ( model , & iter , 0 , & netname , - 1 );
net = servlist_net_find ( netname , & pos , strcmp );
g_free ( netname );
if ( net )
2012-10-22 13:49:28 +02:00
prefs . hex_gui_slist_select = pos ;
2011-02-24 04:14:30 +01:00
}
return net ;
}
static void
servlist_network_row_cb ( GtkTreeSelection * sel , gpointer user_data )
{
ircnet * net ;
selected_net = NULL ;
net = servlist_find_selected_net ( sel );
if ( net )
selected_net = net ;
}
static int
servlist_savegui ( void )
{
char * sp ;
2014-02-02 19:07:52 -05:00
const char * nick1 , * nick2 ;
2011-02-24 04:14:30 +01:00
/* check for blank username, ircd will not allow this */
2013-05-12 01:43:27 -04:00
if ( gtk_entry_get_text ( GTK_ENTRY ( entry_guser ))[ 0 ] == 0 )
2011-02-24 04:14:30 +01:00
return 1 ;
2013-05-12 01:43:27 -04:00
/* if (gtk_entry_get_text (GTK_ENTRY (entry_greal))[0] == 0)
2012-05-16 19:47:12 +02:00
return 1; */
2011-02-24 04:14:30 +01:00
2014-02-01 13:31:42 -05:00
nick1 = gtk_entry_get_text ( GTK_ENTRY ( entry_nick1 ));
nick2 = gtk_entry_get_text ( GTK_ENTRY ( entry_nick2 ));
/* ensure unique nicknames */
if ( ! rfc_casecmp ( nick1 , nick2 ))
return 2 ;
2014-12-10 09:32:16 -05:00
safe_strcpy ( prefs . hex_irc_nick1 , nick1 , sizeof ( prefs . hex_irc_nick1 ));
safe_strcpy ( prefs . hex_irc_nick2 , nick2 , sizeof ( prefs . hex_irc_nick2 ));
safe_strcpy ( prefs . hex_irc_nick3 , gtk_entry_get_text ( GTK_ENTRY ( entry_nick3 )), sizeof ( prefs . hex_irc_nick3 ));
safe_strcpy ( prefs . hex_irc_user_name , gtk_entry_get_text ( GTK_ENTRY ( entry_guser )), sizeof ( prefs . hex_irc_user_name ));
2012-10-22 14:50:36 +02:00
sp = strchr ( prefs . hex_irc_user_name , ' ' );
2011-02-24 04:14:30 +01:00
if ( sp )
sp [ 0 ] = 0 ; /* spaces will break the login */
2013-05-12 01:43:27 -04:00
/* strcpy (prefs.hex_irc_real_name, gtk_entry_get_text (GTK_ENTRY (entry_greal))); */
2011-02-24 04:14:30 +01:00
servlist_save ();
2026-03-16 21:55:36 -06:00
if ( ! save_config ())
fe_message ( _ ( "Could not save zoitechat.conf." ), FE_MSG_WARN );
2011-02-24 04:14:30 +01:00
return 0 ;
}
static gboolean
servlist_get_iter_from_name ( GtkTreeModel * model , gchar * name , GtkTreeIter * iter )
{
GtkTreePath * path = gtk_tree_path_new_from_string ( name );
if ( ! gtk_tree_model_get_iter ( model , iter , path ))
{
gtk_tree_path_free ( path );
return FALSE ;
}
gtk_tree_path_free ( path );
return TRUE ;
}
static void
2013-05-11 09:20:03 -04:00
servlist_addbutton_cb ( GtkWidget * item , GtkNotebook * notebook )
2011-02-24 04:14:30 +01:00
{
2013-05-11 09:20:03 -04:00
switch ( gtk_notebook_get_current_page ( notebook ))
{
case SERVER_TREE :
servlist_addserver ();
break ;
case CHANNEL_TREE :
2013-05-12 05:44:32 +02:00
servlist_addchannel ();
2013-05-11 09:20:03 -04:00
break ;
case CMD_TREE :
servlist_addcommand ();
break ;
default :
break ;
}
2011-02-24 04:14:30 +01:00
}
static void
2013-05-11 09:20:03 -04:00
servlist_deletebutton_cb ( GtkWidget * item , GtkNotebook * notebook )
2011-02-24 04:14:30 +01:00
{
2013-05-11 09:20:03 -04:00
switch ( gtk_notebook_get_current_page ( notebook ))
2011-02-24 04:14:30 +01:00
{
2013-05-11 09:20:03 -04:00
case SERVER_TREE :
servlist_deleteserver_cb ();
break ;
case CHANNEL_TREE :
2013-05-11 20:06:22 +02:00
servlist_deletechannel_cb ();
2013-05-11 09:20:03 -04:00
break ;
case CMD_TREE :
2013-05-11 20:06:22 +02:00
servlist_deletecommand_cb ();
2013-05-11 09:20:03 -04:00
break ;
default :
break ;
2011-02-24 04:14:30 +01:00
}
}
2013-05-20 13:19:20 -03:00
static gboolean
servlist_keypress_cb ( GtkWidget * wid , GdkEventKey * evt , GtkNotebook * notebook )
{
gboolean handled = FALSE ;
int delta = 0 ;
if ( ! selected_net )
return FALSE ;
if ( evt -> state & STATE_SHIFT )
{
2013-09-15 03:21:56 -04:00
if ( evt -> keyval == GDK_KEY_Up )
2013-05-20 13:19:20 -03:00
{
handled = TRUE ;
delta = - 1 ;
}
2013-09-15 03:21:56 -04:00
else if ( evt -> keyval == GDK_KEY_Down )
2013-05-20 13:19:20 -03:00
{
handled = TRUE ;
delta = + 1 ;
}
}
if ( handled )
{
switch ( gtk_notebook_get_current_page ( notebook ))
{
case SERVER_TREE :
if ( selected_serv )
selected_net -> servlist = servlist_move_item ( GTK_TREE_VIEW ( edit_trees [ SERVER_TREE ]),
selected_net -> servlist , selected_serv , delta );
break ;
case CHANNEL_TREE :
if ( selected_chan )
selected_net -> favchanlist = servlist_move_item ( GTK_TREE_VIEW ( edit_trees [ CHANNEL_TREE ]),
selected_net -> favchanlist , selected_chan , delta );
break ;
case CMD_TREE :
if ( selected_cmd )
selected_net -> commandlist = servlist_move_item ( GTK_TREE_VIEW ( edit_trees [ CMD_TREE ]),
selected_net -> commandlist , selected_cmd , delta );
break ;
}
}
return handled ;
}
2011-02-24 04:14:30 +01:00
void
servlist_autojoinedit ( ircnet * net , char * channel , gboolean add )
{
2013-05-12 05:44:32 +02:00
favchannel * fav ;
2011-02-24 04:14:30 +01:00
2013-05-12 05:44:32 +02:00
if ( add )
2011-02-24 04:14:30 +01:00
{
2013-05-12 05:44:32 +02:00
servlist_favchan_add ( net , channel );
servlist_save ();
2011-02-24 04:14:30 +01:00
}
2013-05-12 05:44:32 +02:00
else
2011-02-24 04:14:30 +01:00
{
2013-05-12 05:44:32 +02:00
fav = servlist_favchan_find ( net , channel , NULL );
2014-04-18 20:40:16 -04:00
if ( fav )
{
servlist_favchan_remove ( net , fav );
servlist_save ();
}
2011-02-24 04:14:30 +01:00
}
}
2013-05-11 03:13:50 +02:00
static void
servlist_toggle_global_user ( gboolean sensitive )
{
gtk_widget_set_sensitive ( edit_entry_nick , sensitive );
gtk_widget_set_sensitive ( edit_label_nick , sensitive );
gtk_widget_set_sensitive ( edit_entry_nick2 , sensitive );
gtk_widget_set_sensitive ( edit_label_nick2 , sensitive );
gtk_widget_set_sensitive ( edit_entry_user , sensitive );
gtk_widget_set_sensitive ( edit_label_user , sensitive );
gtk_widget_set_sensitive ( edit_entry_real , sensitive );
gtk_widget_set_sensitive ( edit_label_real , sensitive );
}
2011-02-24 04:14:30 +01:00
static void
servlist_connect_cb ( GtkWidget * button , gpointer userdata )
{
2014-02-01 13:31:42 -05:00
int servlist_err ;
2011-02-24 04:14:30 +01:00
if ( ! selected_net )
return ;
2014-02-01 13:31:42 -05:00
servlist_err = servlist_savegui ();
if ( servlist_err == 1 )
{
fe_message ( _ ( "User name cannot be left blank." ), FE_MSG_ERROR );
return ;
}
2011-02-24 04:14:30 +01:00
if ( ! is_session ( servlist_sess ))
servlist_sess = NULL ; /* open a new one */
{
GSList * list ;
session * sess ;
session * chosen = servlist_sess ;
servlist_sess = NULL ; /* open a new one */
for ( list = sess_list ; list ; list = list -> next )
{
sess = list -> data ;
if ( sess -> server -> network == selected_net )
{
servlist_sess = sess ;
if ( sess -> server -> connected )
servlist_sess = NULL ; /* open a new one */
break ;
}
}
/* use the chosen one, if it's empty */
if ( ! servlist_sess &&
chosen &&
! chosen -> server -> connected &&
chosen -> server -> server_session -> channel [ 0 ] == 0 )
{
servlist_sess = chosen ;
}
}
servlist_connect ( servlist_sess , selected_net , TRUE );
gtk_widget_destroy ( serverlist_win );
serverlist_win = NULL ;
selected_net = NULL ;
}
static void
servlist_celledit_cb ( GtkCellRendererText * cell , gchar * arg1 , gchar * arg2 ,
gpointer user_data )
{
GtkTreeModel * model = ( GtkTreeModel * ) user_data ;
GtkTreeIter iter ;
GtkTreePath * path ;
char * netname ;
ircnet * net ;
if ( ! arg1 || ! arg2 )
return ;
path = gtk_tree_path_new_from_string ( arg1 );
if ( ! path )
return ;
if ( ! gtk_tree_model_get_iter ( model , & iter , path ))
{
gtk_tree_path_free ( path );
return ;
}
gtk_tree_model_get ( model , & iter , 0 , & netname , - 1 );
net = servlist_net_find ( netname , NULL , strcmp );
g_free ( netname );
if ( net )
{
/* delete empty item */
if ( arg2 [ 0 ] == 0 )
{
servlist_deletenetwork ( net );
gtk_tree_path_free ( path );
return ;
}
netname = net -> name ;
2014-12-28 06:37:25 -05:00
net -> name = g_strdup ( arg2 );
2011-02-24 04:14:30 +01:00
gtk_list_store_set ( GTK_LIST_STORE ( model ), & iter , 0 , net -> name , - 1 );
2014-12-28 06:37:25 -05:00
g_free ( netname );
2011-02-24 04:14:30 +01:00
}
gtk_tree_path_free ( path );
}
static void
servlist_check_cb ( GtkWidget * but , gpointer num_p )
{
int num = GPOINTER_TO_INT ( num_p );
if ( ! selected_net )
return ;
if (( 1 << num ) == FLAG_CYCLE || ( 1 << num ) == FLAG_USE_PROXY )
{
/* these ones are reversed, so it's compat with 2.0.x */
2013-05-12 01:43:27 -04:00
if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( but )))
2011-02-24 04:14:30 +01:00
selected_net -> flags &= ~ ( 1 << num );
else
selected_net -> flags |= ( 1 << num );
} else
{
2013-05-12 01:43:27 -04:00
if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( but )))
2011-02-24 04:14:30 +01:00
selected_net -> flags |= ( 1 << num );
else
selected_net -> flags &= ~ ( 1 << num );
}
if (( 1 << num ) == FLAG_USE_GLOBAL )
{
2013-05-12 01:43:27 -04:00
servlist_toggle_global_user ( ! gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( but )));
2011-02-24 04:14:30 +01:00
}
}
2026-01-30 16:04:50 -07:00
typedef enum
{
SERVLIST_ALIGN_START ,
SERVLIST_ALIGN_CENTER ,
SERVLIST_ALIGN_FILL
} servlist_align ;
static GtkAlign
servlist_align_to_gtk ( servlist_align align )
{
switch ( align )
{
case SERVLIST_ALIGN_FILL :
return GTK_ALIGN_FILL ;
case SERVLIST_ALIGN_CENTER :
return GTK_ALIGN_CENTER ;
case SERVLIST_ALIGN_START :
default :
return GTK_ALIGN_START ;
}
}
static void
servlist_table_attach ( GtkWidget * table , GtkWidget * child ,
guint left_attach , guint right_attach ,
guint top_attach , guint bottom_attach ,
gboolean hexpand , gboolean vexpand ,
servlist_align halign , servlist_align valign ,
guint xpad , guint ypad )
{
gtk_widget_set_hexpand ( child , hexpand );
gtk_widget_set_vexpand ( child , vexpand );
gtk_widget_set_halign ( child , servlist_align_to_gtk ( halign ));
gtk_widget_set_valign ( child , servlist_align_to_gtk ( valign ));
gtk_widget_set_margin_start ( child , xpad );
gtk_widget_set_margin_end ( child , xpad );
gtk_widget_set_margin_top ( child , ypad );
gtk_widget_set_margin_bottom ( child , ypad );
2026-01-30 17:13:44 -07:00
gtk_grid_attach ( GTK_GRID ( table ), child , left_attach , top_attach ,
right_attach - left_attach , bottom_attach - top_attach );
2026-01-30 16:04:50 -07:00
}
2011-02-24 04:14:30 +01:00
static GtkWidget *
servlist_create_check ( int num , int state , GtkWidget * table , int row , int col , char * labeltext )
{
GtkWidget * but ;
but = gtk_check_button_new_with_label ( labeltext );
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( but ), state );
g_signal_connect ( G_OBJECT ( but ), "toggled" ,
G_CALLBACK ( servlist_check_cb ), GINT_TO_POINTER ( num ));
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table , but , col , col + 2 , row , row + 1 ,
TRUE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( but );
return but ;
}
static GtkWidget *
servlist_create_entry ( GtkWidget * table , char * labeltext , int row ,
char * def , GtkWidget ** label_ret , char * tip )
{
GtkWidget * label , * entry ;
label = gtk_label_new_with_mnemonic ( labeltext );
if ( label_ret )
* label_ret = label ;
gtk_widget_show ( label );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table , label , 0 , 1 , row , row + 1 ,
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
2026-01-23 20:18:49 -07:00
gtk_widget_set_halign ( label , GTK_ALIGN_START );
gtk_widget_set_valign ( label , GTK_ALIGN_CENTER );
2011-02-24 04:14:30 +01:00
entry = gtk_entry_new ();
2014-01-18 04:08:32 -05:00
gtk_widget_set_tooltip_text ( entry , tip );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( entry );
gtk_entry_set_text ( GTK_ENTRY ( entry ), def ? def : "" );
gtk_label_set_mnemonic_widget ( GTK_LABEL ( label ), entry );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table , entry , 1 , 2 , row , row + 1 ,
TRUE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
2011-02-24 04:14:30 +01:00
return entry ;
}
static gint
servlist_delete_cb ( GtkWidget * win , GdkEventAny * event , gpointer userdata )
{
servlist_savegui ();
serverlist_win = NULL ;
selected_net = NULL ;
if ( sess_list == NULL )
2026-01-05 23:12:38 -07:00
zoitechat_exit ();
2011-02-24 04:14:30 +01:00
return FALSE ;
}
static void
servlist_close_cb ( GtkWidget * button , gpointer userdata )
{
servlist_savegui ();
gtk_widget_destroy ( serverlist_win );
serverlist_win = NULL ;
selected_net = NULL ;
if ( sess_list == NULL )
2026-01-05 23:12:38 -07:00
zoitechat_exit ();
2011-02-24 04:14:30 +01:00
}
/* convert "host:port" format to "host/port" */
static char *
servlist_sanitize_hostname ( char * host )
{
char * ret , * c , * e ;
2014-12-28 06:37:25 -05:00
ret = g_strdup ( host );
2011-02-24 04:14:30 +01:00
c = strchr ( ret , ':' );
e = strrchr ( ret , ':' );
/* if only one colon exists it's probably not IPv6 */
if ( c && c == e )
* c = '/' ;
2016-03-21 04:36:24 +08:00
return g_strstrip ( ret );
2011-02-24 04:14:30 +01:00
}
2013-05-11 20:06:22 +02:00
/* remove leading slash */
static char *
servlist_sanitize_command ( char * cmd )
{
if ( cmd [ 0 ] == '/' )
{
return ( g_strdup ( cmd + 1 ));
}
else
{
return ( g_strdup ( cmd ));
}
}
2011-02-24 04:14:30 +01:00
static void
2013-05-12 05:44:32 +02:00
servlist_editserver_cb ( GtkCellRendererText * cell , gchar * name , gchar * newval , gpointer user_data )
2011-02-24 04:14:30 +01:00
{
GtkTreeModel * model = ( GtkTreeModel * ) user_data ;
GtkTreeIter iter ;
char * servname ;
ircserver * serv ;
if ( ! selected_net )
2013-05-12 05:44:32 +02:00
{
2011-02-24 04:14:30 +01:00
return ;
2013-05-12 05:44:32 +02:00
}
2011-02-24 04:14:30 +01:00
2013-05-12 05:44:32 +02:00
if ( ! servlist_get_iter_from_name ( model , name , & iter ))
2011-02-24 04:14:30 +01:00
{
return ;
}
gtk_tree_model_get ( model , & iter , 0 , & servname , - 1 );
serv = servlist_server_find ( selected_net , servname , NULL );
g_free ( servname );
if ( serv )
{
/* delete empty item */
2013-05-12 05:44:32 +02:00
if ( newval [ 0 ] == 0 )
2011-02-24 04:14:30 +01:00
{
servlist_deleteserver ( serv , model );
return ;
}
servname = serv -> hostname ;
2013-05-12 05:44:32 +02:00
serv -> hostname = servlist_sanitize_hostname ( newval );
2011-02-24 04:14:30 +01:00
gtk_list_store_set ( GTK_LIST_STORE ( model ), & iter , 0 , serv -> hostname , - 1 );
2014-12-28 06:37:25 -05:00
g_free ( servname );
2011-02-24 04:14:30 +01:00
}
}
2013-05-11 20:06:22 +02:00
static void
2013-05-12 05:44:32 +02:00
servlist_editcommand_cb ( GtkCellRendererText * cell , gchar * name , gchar * newval , gpointer user_data )
2013-05-11 20:06:22 +02:00
{
GtkTreeModel * model = ( GtkTreeModel * ) user_data ;
GtkTreeIter iter ;
char * cmd ;
commandentry * entry ;
if ( ! selected_net )
2013-05-12 05:44:32 +02:00
{
2013-05-11 20:06:22 +02:00
return ;
2013-05-12 05:44:32 +02:00
}
2013-05-11 20:06:22 +02:00
2013-05-12 05:44:32 +02:00
if ( ! servlist_get_iter_from_name ( model , name , & iter ))
2013-05-11 20:06:22 +02:00
{
return ;
}
gtk_tree_model_get ( model , & iter , 0 , & cmd , - 1 );
entry = servlist_command_find ( selected_net , cmd , NULL );
g_free ( cmd );
if ( entry )
{
/* delete empty item */
2013-05-12 05:44:32 +02:00
if ( newval [ 0 ] == 0 )
2013-05-11 20:06:22 +02:00
{
servlist_deletecommand ( entry , model );
return ;
}
cmd = entry -> command ;
2013-05-12 05:44:32 +02:00
entry -> command = servlist_sanitize_command ( newval );
2013-05-11 20:06:22 +02:00
gtk_list_store_set ( GTK_LIST_STORE ( model ), & iter , 0 , entry -> command , - 1 );
2014-12-28 06:37:25 -05:00
g_free ( cmd );
2013-05-11 20:06:22 +02:00
}
2013-05-12 05:44:32 +02:00
}
2013-05-11 20:06:22 +02:00
2013-05-12 05:44:32 +02:00
static void
servlist_editchannel_cb ( GtkCellRendererText * cell , gchar * name , gchar * newval , gpointer user_data )
{
GtkTreeModel * model = ( GtkTreeModel * ) user_data ;
GtkTreeIter iter ;
char * chan ;
char * key ;
favchannel * favchan ;
if ( ! selected_net )
{
return ;
}
if ( ! servlist_get_iter_from_name ( model , name , & iter ))
{
return ;
}
gtk_tree_model_get ( model , & iter , 0 , & chan , 1 , & key , - 1 );
favchan = servlist_favchan_find ( selected_net , chan , NULL );
g_free ( chan );
if ( favchan )
{
/* delete empty item */
if ( newval [ 0 ] == 0 )
{
servlist_deletechannel ( favchan , model );
return ;
}
chan = favchan -> name ;
favchan -> name = g_strdup ( newval );
gtk_list_store_set ( GTK_LIST_STORE ( model ), & iter , 0 , favchan -> name , - 1 );
g_free ( chan );
}
}
static void
servlist_editkey_cb ( GtkCellRendererText * cell , gchar * name , gchar * newval , gpointer user_data )
{
GtkTreeModel * model = ( GtkTreeModel * ) user_data ;
GtkTreeIter iter ;
char * chan ;
char * key ;
favchannel * favchan ;
if ( ! selected_net )
{
return ;
}
if ( ! servlist_get_iter_from_name ( model , name , & iter ))
{
return ;
}
gtk_tree_model_get ( model , & iter , 0 , & chan , 1 , & key , - 1 );
favchan = servlist_favchan_find ( selected_net , chan , NULL );
g_free ( chan );
if ( favchan )
{
key = favchan -> key ;
2013-05-17 02:24:47 +02:00
if ( strlen ( newval )) /* check key length, the field can be empty in order to delete the key! */
{
favchan -> key = g_strdup ( newval );
}
else /* if key's empty, make sure we actually remove the key */
{
favchan -> key = NULL ;
}
2013-05-12 05:44:32 +02:00
gtk_list_store_set ( GTK_LIST_STORE ( model ), & iter , 1 , favchan -> key , - 1 );
g_free ( key );
}
2013-05-11 20:06:22 +02:00
}
2013-05-12 16:59:21 +02:00
static gboolean
servlist_edit_tabswitch_cb ( GtkNotebook * nb , gpointer * newtab , guint newindex , gpointer user_data )
{
/* remember the active tab */
netedit_active_tab = newindex ;
return FALSE ;
}
2011-02-24 04:14:30 +01:00
static void
servlist_combo_cb ( GtkEntry * entry , gpointer userdata )
{
if ( ! selected_net )
return ;
2014-12-28 06:37:25 -05:00
g_free ( selected_net -> encoding );
selected_net -> encoding = g_strdup ( gtk_entry_get_text ( entry ));
2011-02-24 04:14:30 +01:00
}
2013-05-10 23:52:47 +02:00
/* Fills up the network's authentication type so that it's guaranteed to be either NULL or a valid value. */
2013-04-28 21:24:53 +02:00
static void
2013-05-19 04:34:20 +02:00
servlist_logintypecombo_cb ( GtkComboBox * cb , gpointer * userdata )
2013-04-28 21:24:53 +02:00
{
2013-05-10 23:52:47 +02:00
int index ;
2013-04-28 21:24:53 +02:00
if ( ! selected_net )
{
return ;
}
2013-05-11 09:20:03 -04:00
index = gtk_combo_box_get_active ( cb ); /* starts at 0, returns -1 for invalid selections */
2013-05-10 23:52:47 +02:00
2014-08-23 14:13:34 -04:00
if ( index == - 1 )
return ; /* Invalid */
/* The selection is valid. It can be 0, which is the default type, but we need to allow
* that so that you can revert from other types. servlist_save() will dump 0 anyway.
*/
selected_net -> logintype = login_types_conf [ index ];
2013-05-19 04:34:20 +02:00
if ( login_types_conf [ index ] == LOGIN_CUSTOM )
{
gtk_notebook_set_current_page ( GTK_NOTEBOOK ( userdata ), 2 ); /* FIXME avoid hardcoding? */
}
2013-09-02 14:24:37 -04:00
/* EXTERNAL uses a cert, not a pass */
if ( login_types_conf [ index ] == LOGIN_SASLEXTERNAL )
gtk_widget_set_sensitive ( edit_entry_pass , FALSE );
else
gtk_widget_set_sensitive ( edit_entry_pass , TRUE );
2013-04-28 21:24:53 +02:00
}
2014-04-18 23:45:27 -04:00
static void
servlist_username_changed_cb ( GtkEntry * entry , gpointer userdata )
{
GtkWidget * connect_btn = GTK_WIDGET ( userdata );
if ( gtk_entry_get_text ( entry )[ 0 ] == 0 )
{
2026-01-30 15:27:01 -07:00
gtk_entry_set_icon_from_icon_name ( entry , GTK_ENTRY_ICON_SECONDARY , ICON_SERVLIST_ERROR );
2014-04-18 23:45:27 -04:00
gtk_entry_set_icon_tooltip_text ( entry , GTK_ENTRY_ICON_SECONDARY ,
_ ( "User name cannot be left blank." ));
gtk_widget_set_sensitive ( connect_btn , FALSE );
}
else
{
2026-01-23 12:57:52 -07:00
gtk_entry_set_icon_from_icon_name ( entry , GTK_ENTRY_ICON_SECONDARY , NULL );
2014-04-18 23:45:27 -04:00
gtk_widget_set_sensitive ( connect_btn , TRUE );
}
}
static void
servlist_nick_changed_cb ( GtkEntry * entry , gpointer userdata )
{
GtkWidget * connect_btn = GTK_WIDGET ( userdata );
const gchar * nick1 = gtk_entry_get_text ( GTK_ENTRY ( entry_nick1 ));
const gchar * nick2 = gtk_entry_get_text ( GTK_ENTRY ( entry_nick2 ));
2016-06-12 15:01:39 -04:00
if ( ! nick1 [ 0 ] || ! nick2 [ 0 ])
{
entry = GTK_ENTRY ( ! nick1 [ 0 ] ? entry_nick1 : entry_nick2 );
2026-01-30 15:27:01 -07:00
gtk_entry_set_icon_from_icon_name ( entry , GTK_ENTRY_ICON_SECONDARY , ICON_SERVLIST_ERROR );
2016-06-12 15:01:39 -04:00
gtk_entry_set_icon_tooltip_text ( entry , GTK_ENTRY_ICON_SECONDARY ,
_ ( "You cannot have an empty nick name." ));
gtk_widget_set_sensitive ( connect_btn , FALSE );
}
else if ( ! rfc_casecmp ( nick1 , nick2 ))
2014-04-18 23:45:27 -04:00
{
2026-01-30 15:27:01 -07:00
gtk_entry_set_icon_from_icon_name ( entry , GTK_ENTRY_ICON_SECONDARY , ICON_SERVLIST_ERROR );
2014-04-18 23:45:27 -04:00
gtk_entry_set_icon_tooltip_text ( entry , GTK_ENTRY_ICON_SECONDARY ,
_ ( "You must have two unique nick names." ));
gtk_widget_set_sensitive ( connect_btn , FALSE );
}
else
{
2026-01-23 12:57:52 -07:00
gtk_entry_set_icon_from_icon_name ( GTK_ENTRY ( entry_nick1 ), GTK_ENTRY_ICON_SECONDARY , NULL );
gtk_entry_set_icon_from_icon_name ( GTK_ENTRY ( entry_nick2 ), GTK_ENTRY_ICON_SECONDARY , NULL );
2014-04-18 23:45:27 -04:00
gtk_widget_set_sensitive ( connect_btn , TRUE );
}
}
2013-04-28 21:24:53 +02:00
2011-02-24 04:14:30 +01:00
static GtkWidget *
servlist_create_charsetcombo ( void )
{
GtkWidget * cb ;
int i ;
2013-05-11 09:20:03 -04:00
cb = gtk_combo_box_text_new_with_entry ();
2011-02-24 04:14:30 +01:00
i = 0 ;
while ( pages [ i ])
{
2013-05-11 09:20:03 -04:00
gtk_combo_box_text_append_text ( GTK_COMBO_BOX_TEXT ( cb ), ( char * ) pages [ i ]);
2011-02-24 04:14:30 +01:00
i ++ ;
}
2013-05-11 09:20:03 -04:00
2015-01-18 02:10:05 -08:00
gtk_entry_set_text ( GTK_ENTRY ( gtk_bin_get_child ( GTK_BIN ( cb ))), selected_net -> encoding ? selected_net -> encoding : pages [ 0 ]);
2013-05-11 09:20:03 -04:00
2013-05-12 01:43:27 -04:00
g_signal_connect ( G_OBJECT ( gtk_bin_get_child ( GTK_BIN ( cb ))), "changed" ,
2011-02-24 04:14:30 +01:00
G_CALLBACK ( servlist_combo_cb ), NULL );
return cb ;
}
2013-04-28 21:24:53 +02:00
static GtkWidget *
2013-05-19 04:34:20 +02:00
servlist_create_logintypecombo ( GtkWidget * data )
2013-04-28 21:24:53 +02:00
{
GtkWidget * cb ;
int i ;
2013-05-11 09:20:03 -04:00
cb = gtk_combo_box_text_new ();
2013-04-28 21:24:53 +02:00
2013-05-10 23:52:47 +02:00
i = 0 ;
2013-04-28 21:24:53 +02:00
2013-05-10 23:52:47 +02:00
while ( login_types [ i ])
2013-04-28 21:24:53 +02:00
{
2013-05-11 09:20:03 -04:00
gtk_combo_box_text_append_text ( GTK_COMBO_BOX_TEXT ( cb ), ( char * ) login_types [ i ]);
2013-04-28 21:24:53 +02:00
i ++ ;
}
2013-05-11 11:54:42 +02:00
gtk_combo_box_set_active ( GTK_COMBO_BOX ( cb ), servlist_get_login_desc_index ( selected_net -> logintype ));
2013-05-11 09:20:03 -04:00
2014-01-18 04:08:32 -05:00
gtk_widget_set_tooltip_text ( cb , _ ( "The way you identify yourself to the server. For custom login methods use connect commands." ));
2013-05-19 04:34:20 +02:00
g_signal_connect ( G_OBJECT ( GTK_BIN ( cb )), "changed" , G_CALLBACK ( servlist_logintypecombo_cb ), data );
2013-04-28 21:24:53 +02:00
return cb ;
}
2011-02-24 04:14:30 +01:00
static void
no_servlist ( GtkWidget * igad , gpointer serv )
{
2013-05-12 01:43:27 -04:00
if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( igad )))
2012-10-22 13:49:28 +02:00
prefs . hex_gui_slist_skip = TRUE ;
2011-02-24 04:14:30 +01:00
else
2012-10-22 13:49:28 +02:00
prefs . hex_gui_slist_skip = FALSE ;
2011-02-24 04:14:30 +01:00
}
static void
fav_servlist ( GtkWidget * igad , gpointer serv )
{
2013-05-12 01:43:27 -04:00
if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( igad )))
2012-10-22 13:49:28 +02:00
prefs . hex_gui_slist_fav = TRUE ;
2011-02-24 04:14:30 +01:00
else
2012-10-22 13:49:28 +02:00
prefs . hex_gui_slist_fav = FALSE ;
2011-02-24 04:14:30 +01:00
servlist_networks_populate ( networks_tree , network_list );
}
static GtkWidget *
bold_label ( char * text )
{
char buf [ 128 ];
GtkWidget * label ;
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "<b>%s</b>" , text );
2011-02-24 04:14:30 +01:00
label = gtk_label_new ( buf );
gtk_label_set_use_markup ( GTK_LABEL ( label ), TRUE );
2026-01-23 20:18:49 -07:00
gtk_widget_set_halign ( label , GTK_ALIGN_START );
gtk_widget_set_valign ( label , GTK_ALIGN_CENTER );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( label );
return label ;
}
static GtkWidget *
servlist_open_edit ( GtkWidget * parent , ircnet * net )
{
GtkWidget * editwindow ;
GtkWidget * vbox5 ;
GtkWidget * table3 ;
GtkWidget * label34 ;
2013-05-10 23:52:47 +02:00
GtkWidget * label_logintype ;
2011-02-24 04:14:30 +01:00
GtkWidget * comboboxentry_charset ;
2013-05-11 09:20:03 -04:00
GtkWidget * combobox_logintypes ;
2011-02-24 04:14:30 +01:00
GtkWidget * hbox1 ;
GtkWidget * scrolledwindow2 ;
2013-05-11 01:20:53 +02:00
GtkWidget * scrolledwindow4 ;
GtkWidget * scrolledwindow5 ;
2011-02-24 04:14:30 +01:00
GtkWidget * treeview_servers ;
2013-05-11 09:20:03 -04:00
GtkWidget * treeview_channels ;
GtkWidget * treeview_commands ;
2011-02-24 04:14:30 +01:00
GtkWidget * vbuttonbox1 ;
GtkWidget * buttonadd ;
GtkWidget * buttonremove ;
GtkWidget * buttonedit ;
2026-03-24 23:00:09 -06:00
GtkWidget * hbox_cert_buttons ;
2011-02-24 04:14:30 +01:00
GtkWidget * hseparator2 ;
GtkWidget * hbuttonbox4 ;
GtkWidget * button10 ;
GtkWidget * check ;
2013-05-11 01:20:53 +02:00
GtkWidget * notebook ;
2011-02-24 04:14:30 +01:00
GtkTreeModel * model ;
GtkListStore * store ;
GtkCellRenderer * renderer ;
char buf [ 128 ];
editwindow = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
2026-03-04 23:28:01 -07:00
theme_manager_attach_window ( editwindow );
2011-02-24 04:14:30 +01:00
gtk_container_set_border_width ( GTK_CONTAINER ( editwindow ), 4 );
2017-09-15 17:36:02 -04:00
g_snprintf ( buf , sizeof ( buf ), _ ( "Edit %s - %s" ), net -> name , _ ( DISPLAY_NAME ));
2011-02-24 04:14:30 +01:00
gtk_window_set_title ( GTK_WINDOW ( editwindow ), buf );
2013-05-11 15:58:52 +02:00
gtk_window_set_default_size ( GTK_WINDOW ( editwindow ), netedit_win_width , netedit_win_height );
2011-02-24 04:14:30 +01:00
gtk_window_set_transient_for ( GTK_WINDOW ( editwindow ), GTK_WINDOW ( parent ));
gtk_window_set_modal ( GTK_WINDOW ( editwindow ), TRUE );
gtk_window_set_type_hint ( GTK_WINDOW ( editwindow ), GDK_WINDOW_TYPE_HINT_DIALOG );
gtk_window_set_role ( GTK_WINDOW ( editwindow ), "editserv" );
2026-02-05 01:59:15 -07:00
vbox5 = gtkutil_box_new ( GTK_ORIENTATION_VERTICAL , FALSE , 0 );
2011-02-24 04:14:30 +01:00
gtk_container_add ( GTK_CONTAINER ( editwindow ), vbox5 );
2013-05-11 20:06:22 +02:00
/* Tabs and buttons */
2026-02-05 01:59:15 -07:00
hbox1 = gtkutil_box_new ( GTK_ORIENTATION_HORIZONTAL , FALSE , 0 );
2013-05-11 15:22:28 +02:00
gtk_box_pack_start ( GTK_BOX ( vbox5 ), hbox1 , TRUE , TRUE , 4 );
2011-02-24 04:14:30 +01:00
scrolledwindow2 = gtk_scrolled_window_new ( NULL , NULL );
2013-05-11 01:20:53 +02:00
scrolledwindow4 = gtk_scrolled_window_new ( NULL , NULL );
scrolledwindow5 = gtk_scrolled_window_new ( NULL , NULL );
notebook = gtk_notebook_new ();
2013-06-02 20:50:43 -04:00
gtk_notebook_append_page ( GTK_NOTEBOOK ( notebook ), scrolledwindow2 , gtk_label_new ( _ ( "Servers" )));
gtk_notebook_append_page ( GTK_NOTEBOOK ( notebook ), scrolledwindow4 , gtk_label_new ( _ ( "Autojoin channels" )));
gtk_notebook_append_page ( GTK_NOTEBOOK ( notebook ), scrolledwindow5 , gtk_label_new ( _ ( "Connect commands" )));
2013-05-11 16:30:45 +02:00
gtk_notebook_set_tab_pos ( GTK_NOTEBOOK ( notebook ), GTK_POS_BOTTOM );
2013-05-11 15:22:28 +02:00
gtk_box_pack_start ( GTK_BOX ( hbox1 ), notebook , TRUE , TRUE , SERVLIST_X_PADDING );
2013-05-11 01:20:53 +02:00
2013-05-11 20:06:22 +02:00
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolledwindow2 ), GTK_POLICY_NEVER , GTK_POLICY_AUTOMATIC );
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( scrolledwindow2 ), GTK_SHADOW_IN );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolledwindow4 ), GTK_POLICY_NEVER , GTK_POLICY_AUTOMATIC );
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( scrolledwindow4 ), GTK_SHADOW_IN );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolledwindow5 ), GTK_POLICY_NEVER , GTK_POLICY_AUTOMATIC );
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( scrolledwindow5 ), GTK_SHADOW_IN );
2014-01-18 04:08:32 -05:00
gtk_widget_set_tooltip_text ( scrolledwindow5 , _ ( "%n=Nick name \n %p=Password \n %r=Real name \n %u=User name" ));
2011-02-24 04:14:30 +01:00
2013-05-11 09:20:03 -04:00
/* Server Tree */
2011-02-24 04:14:30 +01:00
store = gtk_list_store_new ( 2 , G_TYPE_STRING , G_TYPE_BOOLEAN );
model = GTK_TREE_MODEL ( store );
2013-05-11 09:20:03 -04:00
edit_trees [ SERVER_TREE ] = treeview_servers = gtk_tree_view_new_with_model ( model );
2026-03-17 10:30:54 -06:00
g_signal_connect ( G_OBJECT ( treeview_servers ), "key-press-event" ,
2013-05-20 13:19:20 -03:00
G_CALLBACK ( servlist_keypress_cb ), notebook );
g_signal_connect ( G_OBJECT ( gtk_tree_view_get_selection ( GTK_TREE_VIEW ( treeview_servers ))),
"changed" , G_CALLBACK ( servlist_server_row_cb ), NULL );
2011-02-24 04:14:30 +01:00
g_object_unref ( model );
gtk_container_add ( GTK_CONTAINER ( scrolledwindow2 ), treeview_servers );
2013-05-11 09:20:03 -04:00
gtk_widget_set_size_request ( treeview_servers , - 1 , 80 );
2011-02-24 04:14:30 +01:00
gtk_tree_view_set_headers_visible ( GTK_TREE_VIEW ( treeview_servers ),
FALSE );
renderer = gtk_cell_renderer_text_new ();
g_signal_connect ( G_OBJECT ( renderer ), "edited" ,
G_CALLBACK ( servlist_editserver_cb ), model );
gtk_tree_view_insert_column_with_attributes (
GTK_TREE_VIEW ( treeview_servers ), - 1 ,
0 , renderer ,
"text" , 0 ,
"editable" , 1 ,
NULL );
2013-05-11 09:20:03 -04:00
/* Channel Tree */
store = gtk_list_store_new ( 3 , G_TYPE_STRING , G_TYPE_STRING , G_TYPE_BOOLEAN );
model = GTK_TREE_MODEL ( store );
edit_trees [ CHANNEL_TREE ] = treeview_channels = gtk_tree_view_new_with_model ( model );
2026-03-17 10:30:54 -06:00
g_signal_connect ( G_OBJECT ( treeview_channels ), "key-press-event" ,
2013-05-20 13:19:20 -03:00
G_CALLBACK ( servlist_keypress_cb ), notebook );
g_signal_connect ( G_OBJECT ( gtk_tree_view_get_selection ( GTK_TREE_VIEW ( treeview_channels ))),
"changed" , G_CALLBACK ( servlist_channel_row_cb ), NULL );
2013-05-11 09:20:03 -04:00
g_object_unref ( model );
gtk_container_add ( GTK_CONTAINER ( scrolledwindow4 ), treeview_channels );
gtk_tree_view_set_headers_visible ( GTK_TREE_VIEW ( treeview_channels ), TRUE );
renderer = gtk_cell_renderer_text_new ();
g_signal_connect ( G_OBJECT ( renderer ), "edited" ,
G_CALLBACK ( servlist_editchannel_cb ), model );
gtk_tree_view_insert_column_with_attributes (
GTK_TREE_VIEW ( treeview_channels ), - 1 ,
_ ( "Channel" ), renderer ,
"text" , 0 ,
"editable" , 2 ,
NULL );
renderer = gtk_cell_renderer_text_new ();
g_signal_connect ( G_OBJECT ( renderer ), "edited" ,
G_CALLBACK ( servlist_editkey_cb ), model );
gtk_tree_view_insert_column_with_attributes (
GTK_TREE_VIEW ( treeview_channels ), - 1 ,
_ ( "Key (Password)" ), renderer ,
"text" , 1 ,
"editable" , 2 ,
NULL );
gtk_tree_view_column_set_expand ( gtk_tree_view_get_column ( GTK_TREE_VIEW ( treeview_channels ), 0 ), TRUE );
gtk_tree_view_column_set_expand ( gtk_tree_view_get_column ( GTK_TREE_VIEW ( treeview_channels ), 1 ), TRUE );
2013-05-11 20:06:22 +02:00
2013-05-11 09:20:03 -04:00
/* Command Tree */
store = gtk_list_store_new ( 2 , G_TYPE_STRING , G_TYPE_BOOLEAN );
model = GTK_TREE_MODEL ( store );
edit_trees [ CMD_TREE ] = treeview_commands = gtk_tree_view_new_with_model ( model );
2026-03-17 10:30:54 -06:00
g_signal_connect ( G_OBJECT ( treeview_commands ), "key-press-event" ,
2013-05-20 13:19:20 -03:00
G_CALLBACK ( servlist_keypress_cb ), notebook );
g_signal_connect ( G_OBJECT ( gtk_tree_view_get_selection ( GTK_TREE_VIEW ( treeview_commands ))),
"changed" , G_CALLBACK ( servlist_command_row_cb ), NULL );
2013-05-11 09:20:03 -04:00
g_object_unref ( model );
gtk_container_add ( GTK_CONTAINER ( scrolledwindow5 ), treeview_commands );
gtk_tree_view_set_headers_visible ( GTK_TREE_VIEW ( treeview_commands ),
FALSE );
renderer = gtk_cell_renderer_text_new ();
g_signal_connect ( G_OBJECT ( renderer ), "edited" ,
G_CALLBACK ( servlist_editcommand_cb ), model );
gtk_tree_view_insert_column_with_attributes (
GTK_TREE_VIEW ( treeview_commands ), - 1 ,
0 , renderer ,
"text" , 0 ,
"editable" , 1 ,
NULL );
2013-05-11 20:06:22 +02:00
2013-05-11 09:20:03 -04:00
/* Button Box */
2026-01-30 17:48:25 -07:00
vbuttonbox1 = gtk_button_box_new ( GTK_ORIENTATION_VERTICAL );
2011-02-24 04:14:30 +01:00
gtk_box_set_spacing ( GTK_BOX ( vbuttonbox1 ), 3 );
gtk_button_box_set_layout ( GTK_BUTTON_BOX ( vbuttonbox1 ), GTK_BUTTONBOX_START );
gtk_box_pack_start ( GTK_BOX ( hbox1 ), vbuttonbox1 , FALSE , FALSE , 3 );
2026-01-30 15:27:01 -07:00
buttonadd = servlist_icon_button_new ( _ ( "_Add" ), ICON_SERVLIST_ADD );
2011-02-24 04:14:30 +01:00
g_signal_connect ( G_OBJECT ( buttonadd ), "clicked" ,
2013-05-11 09:20:03 -04:00
G_CALLBACK ( servlist_addbutton_cb ), notebook );
2011-02-24 04:14:30 +01:00
gtk_container_add ( GTK_CONTAINER ( vbuttonbox1 ), buttonadd );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( buttonadd , TRUE );
2011-02-24 04:14:30 +01:00
2026-01-30 15:27:01 -07:00
buttonremove = servlist_icon_button_new ( _ ( "_Remove" ), ICON_SERVLIST_REMOVE );
2011-02-24 04:14:30 +01:00
g_signal_connect ( G_OBJECT ( buttonremove ), "clicked" ,
2013-05-11 09:20:03 -04:00
G_CALLBACK ( servlist_deletebutton_cb ), notebook );
2011-02-24 04:14:30 +01:00
gtk_container_add ( GTK_CONTAINER ( vbuttonbox1 ), buttonremove );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( buttonremove , TRUE );
2011-02-24 04:14:30 +01:00
buttonedit = gtk_button_new_with_mnemonic ( _ ( "_Edit" ));
g_signal_connect ( G_OBJECT ( buttonedit ), "clicked" ,
2013-05-11 09:20:03 -04:00
G_CALLBACK ( servlist_editbutton_cb ), notebook );
2011-02-24 04:14:30 +01:00
gtk_container_add ( GTK_CONTAINER ( vbuttonbox1 ), buttonedit );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( buttonedit , TRUE );
2011-02-24 04:14:30 +01:00
2013-05-11 20:06:22 +02:00
/* Checkboxes and entries */
2026-07-09 12:50:13 -06:00
table3 = gtkutil_grid_new ( 19 , 2 , FALSE );
2026-01-30 17:13:44 -07:00
gtk_box_pack_start ( GTK_BOX ( vbox5 ), table3 , FALSE , FALSE , 0 );
gtk_grid_set_row_spacing ( GTK_GRID ( table3 ), 2 );
gtk_grid_set_column_spacing ( GTK_GRID ( table3 ), 8 );
2013-05-11 15:22:28 +02:00
check = servlist_create_check ( 0 , ! ( net -> flags & FLAG_CYCLE ), table3 , 0 , 0 , _ ( "Connect to selected server only" ));
2014-01-18 04:08:32 -05:00
gtk_widget_set_tooltip_text ( check , _ ( "Don't cycle through all the servers when the connection fails." ));
2013-05-11 15:22:28 +02:00
servlist_create_check ( 3 , net -> flags & FLAG_AUTO_CONNECT , table3 , 1 , 0 , _ ( "Connect to this network automatically" ));
servlist_create_check ( 4 , ! ( net -> flags & FLAG_USE_PROXY ), table3 , 2 , 0 , _ ( "Bypass proxy server" ));
check = servlist_create_check ( 2 , net -> flags & FLAG_USE_SSL , table3 , 3 , 0 , _ ( "Use SSL for all the servers on this network" ));
#ifndef USE_OPENSSL
gtk_widget_set_sensitive ( check , FALSE );
#endif
check = servlist_create_check ( 5 , net -> flags & FLAG_ALLOW_INVALID , table3 , 4 , 0 , _ ( "Accept invalid SSL certificates" ));
#ifndef USE_OPENSSL
gtk_widget_set_sensitive ( check , FALSE );
#endif
servlist_create_check ( 1 , net -> flags & FLAG_USE_GLOBAL , table3 , 5 , 0 , _ ( "Use global user information" ));
2026-07-09 12:50:13 -06:00
edit_check_ask_pass = gtk_check_button_new_with_mnemonic ( _ ( "Ask for password on connect" ));
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( edit_check_ask_pass ), net -> flags & FLAG_PROMPT_PASSWORD );
servlist_table_attach ( table3 , edit_check_ask_pass , 0 , 2 , 6 , 7 ,
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
g_signal_connect ( G_OBJECT ( edit_check_ask_pass ), "toggled" ,
G_CALLBACK ( servlist_toggle_ask_pass_cb ), NULL );
2026-06-02 15:57:28 -06:00
edit_check_use_keyring = gtk_check_button_new_with_mnemonic ( _ ( "Use system keyring" ));
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( edit_check_use_keyring ), net -> flags & FLAG_USE_KEYRING );
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , edit_check_use_keyring , 0 , 2 , 7 , 8 ,
2026-06-02 15:57:28 -06:00
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
g_signal_connect ( G_OBJECT ( edit_check_use_keyring ), "toggled" ,
G_CALLBACK ( servlist_toggle_keyring_cb ), NULL );
2026-07-09 12:50:13 -06:00
edit_entry_nick = servlist_create_entry ( table3 , _ ( "_Nick name:" ), 8 , net -> nick , & edit_label_nick , 0 );
edit_entry_nick2 = servlist_create_entry ( table3 , _ ( "Second choice:" ), 9 , net -> nick2 , & edit_label_nick2 , 0 );
edit_entry_real = servlist_create_entry ( table3 , _ ( "Rea_l name:" ), 10 , net -> real , & edit_label_real , 0 );
edit_entry_user = servlist_create_entry ( table3 , _ ( "_User name:" ), 11 , net -> user , & edit_label_user , 0 );
2013-05-11 15:22:28 +02:00
label_logintype = gtk_label_new ( _ ( "Login method:" ));
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , label_logintype , 0 , 1 , 12 , 13 ,
2026-01-30 16:04:50 -07:00
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
2026-01-23 20:18:49 -07:00
gtk_widget_set_halign ( label_logintype , GTK_ALIGN_START );
gtk_widget_set_valign ( label_logintype , GTK_ALIGN_CENTER );
2013-05-19 04:34:20 +02:00
combobox_logintypes = servlist_create_logintypecombo ( notebook );
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , combobox_logintypes , 1 , 2 , 12 , 13 ,
2026-01-30 16:04:50 -07:00
FALSE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_FILL ,
4 , 2 );
2013-05-11 15:22:28 +02:00
2026-07-09 12:50:13 -06:00
edit_entry_pass = servlist_create_entry ( table3 , _ ( "Password:" ), 13 , NULL , 0 , _ ( "Password used for login. If in doubt, leave blank." ));
2026-06-02 15:57:28 -06:00
if ( edit_loaded_password )
{
memset ( edit_loaded_password , 0 , strlen ( edit_loaded_password ));
g_free ( edit_loaded_password );
edit_loaded_password = NULL ;
}
edit_pass_changed = 0 ;
g_signal_connect ( G_OBJECT ( edit_entry_pass ), "changed" ,
G_CALLBACK ( servlist_password_changed_cb ), NULL );
if ( net -> flags & FLAG_USE_KEYRING )
{
char * stored = secretstore_get_network_password ( net -> name );
if ( stored && * stored )
2026-06-05 10:38:16 -06:00
{
edit_loaded_password = g_strdup ( stored );
servlist_entry_set_text_silent ( edit_entry_pass , "***" );
}
2026-06-02 15:57:28 -06:00
if ( stored )
{
memset ( stored , 0 , strlen ( stored ));
g_free ( stored );
}
}
else if ( net -> pass && * net -> pass )
{
2026-06-05 10:38:16 -06:00
servlist_entry_set_text_silent ( edit_entry_pass , "***" );
2026-06-02 15:57:28 -06:00
}
edit_pass_changed = 0 ;
2013-05-11 15:22:28 +02:00
gtk_entry_set_visibility ( GTK_ENTRY ( edit_entry_pass ), FALSE );
2013-09-02 14:24:37 -04:00
if ( selected_net && selected_net -> logintype == LOGIN_SASLEXTERNAL )
gtk_widget_set_sensitive ( edit_entry_pass , FALSE );
2026-06-02 15:57:28 -06:00
edit_check_show_pass = gtk_check_button_new_with_mnemonic ( _ ( "Show password" ));
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , edit_check_show_pass , 0 , 2 , 14 , 15 ,
2026-06-02 15:57:28 -06:00
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
4 , 2 );
g_signal_connect ( G_OBJECT ( edit_check_show_pass ), "toggled" ,
G_CALLBACK ( servlist_toggle_show_password_cb ), edit_entry_pass );
2013-05-11 15:22:28 +02:00
2026-06-05 10:38:16 -06:00
edit_button_encrypt_pass = gtk_button_new_with_mnemonic ( _ ( "Encrypt saved password" ));
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , edit_button_encrypt_pass , 0 , 1 , 15 , 16 ,
2026-06-05 10:38:16 -06:00
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
g_signal_connect ( G_OBJECT ( edit_button_encrypt_pass ), "clicked" ,
G_CALLBACK ( servlist_encrypt_password_cb ), net );
edit_button_import_pass = gtk_button_new_with_mnemonic ( _ ( "Move password to keyring" ));
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , edit_button_import_pass , 1 , 2 , 15 , 16 ,
2026-06-05 10:38:16 -06:00
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
4 , 2 );
g_signal_connect ( G_OBJECT ( edit_button_import_pass ), "clicked" ,
G_CALLBACK ( servlist_import_password_cb ), net );
2013-05-11 15:22:28 +02:00
label34 = gtk_label_new ( _ ( "Character set:" ));
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , label34 , 0 , 1 , 16 , 17 ,
2026-01-30 16:04:50 -07:00
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
2026-01-23 20:18:49 -07:00
gtk_widget_set_halign ( label34 , GTK_ALIGN_START );
gtk_widget_set_valign ( label34 , GTK_ALIGN_CENTER );
2013-05-11 15:22:28 +02:00
comboboxentry_charset = servlist_create_charsetcombo ();
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , comboboxentry_charset , 1 , 2 , 16 , 17 ,
2026-01-30 16:04:50 -07:00
FALSE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_FILL ,
4 , 2 );
2013-05-11 15:22:28 +02:00
2026-03-24 23:00:09 -06:00
hbox_cert_buttons = gtkutil_box_new ( GTK_ORIENTATION_HORIZONTAL , FALSE , 6 );
edit_button_cert_generate = gtk_button_new_with_mnemonic ( _ ( "Generate client SSL cert" ));
g_signal_connect ( G_OBJECT ( edit_button_cert_generate ), "clicked" ,
G_CALLBACK ( servlist_generate_client_cert_cb ), net );
gtk_box_pack_start ( GTK_BOX ( hbox_cert_buttons ), edit_button_cert_generate , FALSE , FALSE , 0 );
2026-03-30 11:46:08 -06:00
edit_button_cert_import = gtk_button_new_with_mnemonic ( _ ( "Import client SSL cert" ));
g_signal_connect ( G_OBJECT ( edit_button_cert_import ), "clicked" ,
G_CALLBACK ( servlist_import_client_cert_cb ), net );
gtk_box_pack_start ( GTK_BOX ( hbox_cert_buttons ), edit_button_cert_import , FALSE , FALSE , 0 );
2026-03-24 23:00:09 -06:00
edit_button_cert_info = gtk_button_new_with_mnemonic ( _ ( "Client SSL cert info" ));
g_signal_connect ( G_OBJECT ( edit_button_cert_info ), "clicked" ,
G_CALLBACK ( servlist_cert_info_cb ), net );
gtk_box_pack_start ( GTK_BOX ( hbox_cert_buttons ), edit_button_cert_info , FALSE , FALSE , 0 );
edit_button_cert_delete = gtk_button_new_with_mnemonic ( _ ( "Delete cert" ));
g_signal_connect ( G_OBJECT ( edit_button_cert_delete ), "clicked" ,
G_CALLBACK ( servlist_delete_client_cert_cb ), net );
gtk_box_pack_start ( GTK_BOX ( hbox_cert_buttons ), edit_button_cert_delete , FALSE , FALSE , 0 );
2026-07-09 12:50:13 -06:00
servlist_table_attach ( table3 , hbox_cert_buttons , 0 , 2 , 17 , 18 ,
2026-03-24 23:00:09 -06:00
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
SERVLIST_X_PADDING , SERVLIST_Y_PADDING );
2013-05-11 20:06:22 +02:00
/* Rule and Close button */
2026-01-30 17:48:25 -07:00
hseparator2 = gtk_separator_new ( GTK_ORIENTATION_HORIZONTAL );
2011-02-24 04:14:30 +01:00
gtk_box_pack_start ( GTK_BOX ( vbox5 ), hseparator2 , FALSE , FALSE , 8 );
2026-01-30 17:03:27 -07:00
hbuttonbox4 = gtk_button_box_new ( GTK_ORIENTATION_HORIZONTAL );
gtk_button_box_set_layout ( GTK_BUTTON_BOX ( hbuttonbox4 ), GTK_BUTTONBOX_END );
gtk_box_pack_start ( GTK_BOX ( vbox5 ), hbuttonbox4 , FALSE , FALSE , 0 );
2011-02-24 04:14:30 +01:00
2026-01-30 15:27:01 -07:00
button10 = servlist_icon_button_new ( _ ( "_Close" ), ICON_SERVLIST_CLOSE );
2011-02-24 04:14:30 +01:00
g_signal_connect ( G_OBJECT ( button10 ), "clicked" ,
G_CALLBACK ( servlist_edit_close_cb ), 0 );
gtk_container_add ( GTK_CONTAINER ( hbuttonbox4 ), button10 );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( button10 , TRUE );
2011-02-24 04:14:30 +01:00
if ( net -> flags & FLAG_USE_GLOBAL )
{
2013-05-11 03:13:50 +02:00
servlist_toggle_global_user ( FALSE );
2011-02-24 04:14:30 +01:00
}
2026-06-02 15:57:28 -06:00
servlist_toggle_keyring_cb ( GTK_TOGGLE_BUTTON ( edit_check_use_keyring ), NULL );
2026-06-05 10:38:16 -06:00
servlist_update_password_tools ( net );
2011-02-24 04:14:30 +01:00
gtk_widget_grab_focus ( button10 );
gtk_widget_grab_default ( button10 );
2013-05-11 09:20:03 -04:00
gtk_widget_show_all ( editwindow );
2026-03-24 23:00:09 -06:00
servlist_update_cert_buttons ( net );
2013-05-11 09:20:03 -04:00
2013-05-12 16:59:21 +02:00
/* We can't set the active tab without child elements being shown, so this must be *after* gtk_widget_show()s! */
gtk_notebook_set_current_page ( GTK_NOTEBOOK ( notebook ), netedit_active_tab );
/* We need to connect this *after* setting the active tab so that the value doesn't get overriden. */
g_signal_connect ( G_OBJECT ( notebook ), "switch-page" , G_CALLBACK ( servlist_edit_tabswitch_cb ), notebook );
2011-02-24 04:14:30 +01:00
return editwindow ;
}
static GtkWidget *
servlist_open_networks ( void )
{
GtkWidget * servlist ;
GtkWidget * vbox1 ;
GtkWidget * label2 ;
GtkWidget * table1 ;
GtkWidget * label3 ;
GtkWidget * label4 ;
GtkWidget * label5 ;
GtkWidget * label6 ;
2012-05-16 19:47:12 +02:00
/* GtkWidget *label7; */
2011-02-24 04:14:30 +01:00
GtkWidget * entry1 ;
GtkWidget * entry2 ;
GtkWidget * entry3 ;
GtkWidget * entry4 ;
2012-05-16 19:47:12 +02:00
/* GtkWidget *entry5; */
2011-02-24 04:14:30 +01:00
GtkWidget * vbox2 ;
GtkWidget * label1 ;
GtkWidget * table4 ;
GtkWidget * scrolledwindow3 ;
GtkWidget * treeview_networks ;
GtkWidget * checkbutton_skip ;
GtkWidget * checkbutton_fav ;
GtkWidget * hbox ;
GtkWidget * vbuttonbox2 ;
GtkWidget * button_add ;
GtkWidget * button_remove ;
GtkWidget * button_edit ;
GtkWidget * button_sort ;
GtkWidget * hseparator1 ;
GtkWidget * hbuttonbox1 ;
GtkWidget * button_connect ;
GtkWidget * button_close ;
GtkTreeModel * model ;
GtkListStore * store ;
GtkCellRenderer * renderer ;
2017-09-15 17:36:02 -04:00
char buf [ 128 ];
2011-02-24 04:14:30 +01:00
servlist = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
2026-03-04 23:28:01 -07:00
theme_manager_attach_window ( servlist );
2011-02-24 04:14:30 +01:00
gtk_container_set_border_width ( GTK_CONTAINER ( servlist ), 4 );
2017-09-15 17:36:02 -04:00
g_snprintf ( buf , sizeof ( buf ), _ ( "Network List - %s" ), _ ( DISPLAY_NAME ));
gtk_window_set_title ( GTK_WINDOW ( servlist ), buf );
2013-05-11 15:58:52 +02:00
gtk_window_set_default_size ( GTK_WINDOW ( servlist ), netlist_win_width , netlist_win_height );
2011-02-24 04:14:30 +01:00
gtk_window_set_role ( GTK_WINDOW ( servlist ), "servlist" );
gtk_window_set_type_hint ( GTK_WINDOW ( servlist ), GDK_WINDOW_TYPE_HINT_DIALOG );
if ( current_sess )
gtk_window_set_transient_for ( GTK_WINDOW ( servlist ), GTK_WINDOW ( current_sess -> gui -> window ));
2026-02-05 01:59:15 -07:00
vbox1 = gtkutil_box_new ( GTK_ORIENTATION_VERTICAL , FALSE , 0 );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( vbox1 );
gtk_container_add ( GTK_CONTAINER ( servlist ), vbox1 );
label2 = bold_label ( _ ( "User Information" ));
gtk_box_pack_start ( GTK_BOX ( vbox1 ), label2 , FALSE , FALSE , 0 );
2026-02-05 01:59:15 -07:00
table1 = gtkutil_grid_new ( 5 , 2 , FALSE );
2026-01-30 17:13:44 -07:00
gtk_widget_show ( table1 );
gtk_box_pack_start ( GTK_BOX ( vbox1 ), table1 , FALSE , FALSE , 0 );
gtk_container_set_border_width ( GTK_CONTAINER ( table1 ), 8 );
gtk_grid_set_row_spacing ( GTK_GRID ( table1 ), 2 );
gtk_grid_set_column_spacing ( GTK_GRID ( table1 ), 4 );
2011-02-24 04:14:30 +01:00
label3 = gtk_label_new_with_mnemonic ( _ ( "_Nick name:" ));
gtk_widget_show ( label3 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table1 , label3 , 0 , 1 , 0 , 1 ,
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2026-01-23 20:18:49 -07:00
gtk_widget_set_halign ( label3 , GTK_ALIGN_START );
gtk_widget_set_valign ( label3 , GTK_ALIGN_CENTER );
2011-02-24 04:14:30 +01:00
label4 = gtk_label_new ( _ ( "Second choice:" ));
gtk_widget_show ( label4 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table1 , label4 , 0 , 1 , 1 , 2 ,
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2026-01-23 20:18:49 -07:00
gtk_widget_set_halign ( label4 , GTK_ALIGN_START );
gtk_widget_set_valign ( label4 , GTK_ALIGN_CENTER );
2011-02-24 04:14:30 +01:00
label5 = gtk_label_new ( _ ( "Third choice:" ));
gtk_widget_show ( label5 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table1 , label5 , 0 , 1 , 2 , 3 ,
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2026-01-23 20:18:49 -07:00
gtk_widget_set_halign ( label5 , GTK_ALIGN_START );
gtk_widget_set_valign ( label5 , GTK_ALIGN_CENTER );
2011-02-24 04:14:30 +01:00
label6 = gtk_label_new_with_mnemonic ( _ ( "_User name:" ));
gtk_widget_show ( label6 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table1 , label6 , 0 , 1 , 3 , 4 ,
FALSE , FALSE ,
SERVLIST_ALIGN_START , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2026-01-23 20:18:49 -07:00
gtk_widget_set_halign ( label6 , GTK_ALIGN_START );
gtk_widget_set_valign ( label6 , GTK_ALIGN_CENTER );
2011-02-24 04:14:30 +01:00
2012-05-16 19:47:12 +02:00
/* label7 = gtk_label_new_with_mnemonic (_("Rea_l name:"));
2011-02-24 04:14:30 +01:00
gtk_widget_show (label7);
gtk_table_attach (GTK_TABLE (table1), label7, 0, 1, 4, 5,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
2026-01-23 21:16:43 -07:00
*/
2011-02-24 04:14:30 +01:00
entry_nick1 = entry1 = gtk_entry_new ();
2012-10-22 14:50:36 +02:00
gtk_entry_set_text ( GTK_ENTRY ( entry1 ), prefs . hex_irc_nick1 );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( entry1 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table1 , entry1 , 1 , 2 , 0 , 1 ,
TRUE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2011-02-24 04:14:30 +01:00
entry_nick2 = entry2 = gtk_entry_new ();
2012-10-22 14:50:36 +02:00
gtk_entry_set_text ( GTK_ENTRY ( entry2 ), prefs . hex_irc_nick2 );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( entry2 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table1 , entry2 , 1 , 2 , 1 , 2 ,
TRUE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2011-02-24 04:14:30 +01:00
entry_nick3 = entry3 = gtk_entry_new ();
2012-10-22 14:50:36 +02:00
gtk_entry_set_text ( GTK_ENTRY ( entry3 ), prefs . hex_irc_nick3 );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( entry3 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table1 , entry3 , 1 , 2 , 2 , 3 ,
TRUE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2011-02-24 04:14:30 +01:00
entry_guser = entry4 = gtk_entry_new ();
2012-10-22 14:50:36 +02:00
gtk_entry_set_text ( GTK_ENTRY ( entry4 ), prefs . hex_irc_user_name );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( entry4 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table1 , entry4 , 1 , 2 , 3 , 4 ,
TRUE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2011-02-24 04:14:30 +01:00
2012-05-16 19:47:12 +02:00
/* entry_greal = entry5 = gtk_entry_new ();
2012-10-22 14:50:36 +02:00
gtk_entry_set_text (GTK_ENTRY (entry5), prefs.hex_irc_real_name);
2011-02-24 04:14:30 +01:00
gtk_widget_show (entry5);
gtk_table_attach (GTK_TABLE (table1), entry5, 1, 2, 4, 5,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2012-05-16 19:47:12 +02:00
(GtkAttachOptions) (0), 0, 0); */
2011-02-24 04:14:30 +01:00
2026-02-05 01:59:15 -07:00
vbox2 = gtkutil_box_new ( GTK_ORIENTATION_VERTICAL , FALSE , 0 );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( vbox2 );
gtk_box_pack_start ( GTK_BOX ( vbox1 ), vbox2 , TRUE , TRUE , 0 );
label1 = bold_label ( _ ( "Networks" ));
gtk_box_pack_start ( GTK_BOX ( vbox2 ), label1 , FALSE , FALSE , 0 );
2026-02-05 01:59:15 -07:00
table4 = gtkutil_grid_new ( 2 , 2 , FALSE );
2026-01-30 17:13:44 -07:00
gtk_widget_show ( table4 );
gtk_box_pack_start ( GTK_BOX ( vbox2 ), table4 , TRUE , TRUE , 0 );
gtk_container_set_border_width ( GTK_CONTAINER ( table4 ), 8 );
gtk_grid_set_row_spacing ( GTK_GRID ( table4 ), 2 );
gtk_grid_set_column_spacing ( GTK_GRID ( table4 ), 3 );
2011-02-24 04:14:30 +01:00
scrolledwindow3 = gtk_scrolled_window_new ( NULL , NULL );
gtk_widget_show ( scrolledwindow3 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table4 , scrolledwindow3 , 0 , 1 , 0 , 1 ,
TRUE , TRUE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_FILL ,
0 , 0 );
2011-02-24 04:14:30 +01:00
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolledwindow3 ),
GTK_POLICY_NEVER , GTK_POLICY_ALWAYS );
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( scrolledwindow3 ),
GTK_SHADOW_IN );
store = gtk_list_store_new ( 3 , G_TYPE_STRING , G_TYPE_BOOLEAN , G_TYPE_INT );
model = GTK_TREE_MODEL ( store );
networks_tree = treeview_networks = gtk_tree_view_new_with_model ( model );
g_object_unref ( model );
gtk_widget_show ( treeview_networks );
gtk_container_add ( GTK_CONTAINER ( scrolledwindow3 ), treeview_networks );
gtk_tree_view_set_headers_visible ( GTK_TREE_VIEW ( treeview_networks ),
FALSE );
renderer = gtk_cell_renderer_text_new ();
g_signal_connect ( G_OBJECT ( renderer ), "edited" ,
G_CALLBACK ( servlist_celledit_cb ), model );
gtk_tree_view_insert_column_with_attributes (
GTK_TREE_VIEW ( treeview_networks ), - 1 ,
0 , renderer ,
"text" , 0 ,
"editable" , 1 ,
"weight" , 2 ,
NULL );
2026-02-05 01:59:15 -07:00
hbox = gtkutil_box_new ( GTK_ORIENTATION_HORIZONTAL , FALSE , 0 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table4 , hbox , 0 , 2 , 1 , 2 ,
FALSE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_CENTER ,
0 , 0 );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( hbox );
checkbutton_skip =
gtk_check_button_new_with_mnemonic ( _ ( "Skip network list on startup" ));
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( checkbutton_skip ),
2012-10-22 13:49:28 +02:00
prefs . hex_gui_slist_skip );
2011-02-24 04:14:30 +01:00
gtk_container_add ( GTK_CONTAINER ( hbox ), checkbutton_skip );
g_signal_connect ( G_OBJECT ( checkbutton_skip ), "toggled" ,
G_CALLBACK ( no_servlist ), 0 );
gtk_widget_show ( checkbutton_skip );
checkbutton_fav =
gtk_check_button_new_with_mnemonic ( _ ( "Show favorites only" ));
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( checkbutton_fav ),
2012-10-22 13:49:28 +02:00
prefs . hex_gui_slist_fav );
2011-02-24 04:14:30 +01:00
gtk_container_add ( GTK_CONTAINER ( hbox ), checkbutton_fav );
g_signal_connect ( G_OBJECT ( checkbutton_fav ), "toggled" ,
G_CALLBACK ( fav_servlist ), 0 );
gtk_widget_show ( checkbutton_fav );
2026-01-30 17:48:25 -07:00
vbuttonbox2 = gtk_button_box_new ( GTK_ORIENTATION_VERTICAL );
2011-02-24 04:14:30 +01:00
gtk_box_set_spacing ( GTK_BOX ( vbuttonbox2 ), 3 );
gtk_button_box_set_layout ( GTK_BUTTON_BOX ( vbuttonbox2 ), GTK_BUTTONBOX_START );
gtk_widget_show ( vbuttonbox2 );
2026-01-30 16:04:50 -07:00
servlist_table_attach ( table4 , vbuttonbox2 , 1 , 2 , 0 , 1 ,
FALSE , FALSE ,
SERVLIST_ALIGN_FILL , SERVLIST_ALIGN_FILL ,
0 , 0 );
2011-02-24 04:14:30 +01:00
2026-01-30 15:27:01 -07:00
button_add = servlist_icon_button_new ( _ ( "_Add" ), ICON_SERVLIST_ADD );
2011-02-24 04:14:30 +01:00
g_signal_connect ( G_OBJECT ( button_add ), "clicked" ,
G_CALLBACK ( servlist_addnet_cb ), networks_tree );
gtk_widget_show ( button_add );
gtk_container_add ( GTK_CONTAINER ( vbuttonbox2 ), button_add );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( button_add , TRUE );
2011-02-24 04:14:30 +01:00
2026-01-30 15:27:01 -07:00
button_remove = servlist_icon_button_new ( _ ( "_Remove" ), ICON_SERVLIST_REMOVE );
2011-02-24 04:14:30 +01:00
g_signal_connect ( G_OBJECT ( button_remove ), "clicked" ,
G_CALLBACK ( servlist_deletenet_cb ), 0 );
gtk_widget_show ( button_remove );
gtk_container_add ( GTK_CONTAINER ( vbuttonbox2 ), button_remove );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( button_remove , TRUE );
2011-02-24 04:14:30 +01:00
button_edit = gtk_button_new_with_mnemonic ( _ ( "_Edit..." ));
g_signal_connect ( G_OBJECT ( button_edit ), "clicked" ,
G_CALLBACK ( servlist_edit_cb ), 0 );
gtk_widget_show ( button_edit );
gtk_container_add ( GTK_CONTAINER ( vbuttonbox2 ), button_edit );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( button_edit , TRUE );
2011-02-24 04:14:30 +01:00
button_sort = gtk_button_new_with_mnemonic ( _ ( "_Sort" ));
2014-01-18 04:08:32 -05:00
gtk_widget_set_tooltip_text ( button_sort , _ ( "Sorts the network list in alphabetical order. "
2017-08-19 20:48:50 +02:00
"Use Shift+Up and Shift+Down keys to move a row." ));
2011-02-24 04:14:30 +01:00
g_signal_connect ( G_OBJECT ( button_sort ), "clicked" ,
G_CALLBACK ( servlist_sort ), 0 );
gtk_widget_show ( button_sort );
gtk_container_add ( GTK_CONTAINER ( vbuttonbox2 ), button_sort );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( button_sort , TRUE );
2011-02-24 04:14:30 +01:00
button_sort = gtk_button_new_with_mnemonic ( _ ( "_Favor" ));
2014-01-18 04:08:32 -05:00
gtk_widget_set_tooltip_text ( button_sort , _ ( "Mark or unmark this network as a favorite." ));
2011-02-24 04:14:30 +01:00
g_signal_connect ( G_OBJECT ( button_sort ), "clicked" ,
G_CALLBACK ( servlist_favor ), 0 );
gtk_widget_show ( button_sort );
gtk_container_add ( GTK_CONTAINER ( vbuttonbox2 ), button_sort );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( button_sort , TRUE );
2011-02-24 04:14:30 +01:00
2026-01-30 17:48:25 -07:00
hseparator1 = gtk_separator_new ( GTK_ORIENTATION_HORIZONTAL );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( hseparator1 );
gtk_box_pack_start ( GTK_BOX ( vbox1 ), hseparator1 , FALSE , TRUE , 4 );
2026-01-30 17:03:27 -07:00
hbuttonbox1 = gtk_button_box_new ( GTK_ORIENTATION_HORIZONTAL );
gtk_button_box_set_layout ( GTK_BUTTON_BOX ( hbuttonbox1 ), GTK_BUTTONBOX_SPREAD );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( hbuttonbox1 );
gtk_box_pack_start ( GTK_BOX ( vbox1 ), hbuttonbox1 , FALSE , TRUE , 0 );
gtk_container_set_border_width ( GTK_CONTAINER ( hbuttonbox1 ), 8 );
2026-01-30 15:27:01 -07:00
button_close = servlist_icon_button_new ( _ ( "_Close" ), ICON_SERVLIST_CLOSE );
2011-02-24 04:14:30 +01:00
gtk_widget_show ( button_close );
g_signal_connect ( G_OBJECT ( button_close ), "clicked" ,
G_CALLBACK ( servlist_close_cb ), 0 );
gtk_container_add ( GTK_CONTAINER ( hbuttonbox1 ), button_close );
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( button_close , TRUE );
2011-02-24 04:14:30 +01:00
2026-01-30 15:27:01 -07:00
button_connect = gtkutil_button ( hbuttonbox1 , ICON_SERVLIST_CONNECT , NULL ,
2011-02-24 04:14:30 +01:00
servlist_connect_cb , NULL , _ ( "C_onnect" ));
2013-05-12 01:43:27 -04:00
gtk_widget_set_can_default ( button_connect , TRUE );
2011-02-24 04:14:30 +01:00
2014-04-18 23:45:27 -04:00
g_signal_connect ( G_OBJECT ( entry_guser ), "changed" ,
2014-04-18 23:50:27 -04:00
G_CALLBACK ( servlist_username_changed_cb ), button_connect );
2014-04-18 23:45:27 -04:00
g_signal_connect ( G_OBJECT ( entry_nick1 ), "changed" ,
2014-04-18 23:50:27 -04:00
G_CALLBACK ( servlist_nick_changed_cb ), button_connect );
2014-04-18 23:45:27 -04:00
g_signal_connect ( G_OBJECT ( entry_nick2 ), "changed" ,
2014-04-18 23:50:27 -04:00
G_CALLBACK ( servlist_nick_changed_cb ), button_connect );
2014-04-18 23:45:27 -04:00
2016-05-16 08:50:13 -04:00
/* Run validity checks now */
servlist_nick_changed_cb ( GTK_ENTRY ( entry_nick2 ), button_connect );
servlist_username_changed_cb ( GTK_ENTRY ( entry_guser ), button_connect );
2011-02-24 04:14:30 +01:00
gtk_label_set_mnemonic_widget ( GTK_LABEL ( label3 ), entry1 );
gtk_label_set_mnemonic_widget ( GTK_LABEL ( label6 ), entry4 );
2012-05-16 19:47:12 +02:00
/* gtk_label_set_mnemonic_widget (GTK_LABEL (label7), entry5); */
2011-02-24 04:14:30 +01:00
gtk_widget_grab_focus ( networks_tree );
gtk_widget_grab_default ( button_close );
return servlist ;
}
void
fe_serverlist_open ( session * sess )
{
if ( serverlist_win )
{
gtk_window_present ( GTK_WINDOW ( serverlist_win ));
return ;
}
servlist_sess = sess ;
serverlist_win = servlist_open_networks ();
gtkutil_set_icon ( serverlist_win );
servlist_networks_populate ( networks_tree , network_list );
2026-03-17 10:30:54 -06:00
g_signal_connect ( G_OBJECT ( serverlist_win ), "delete-event" ,
2011-02-24 04:14:30 +01:00
G_CALLBACK ( servlist_delete_cb ), 0 );
2026-03-17 10:30:54 -06:00
g_signal_connect ( G_OBJECT ( serverlist_win ), "configure-event" ,
2011-02-24 04:14:30 +01:00
G_CALLBACK ( servlist_configure_cb ), 0 );
g_signal_connect ( G_OBJECT ( gtk_tree_view_get_selection ( GTK_TREE_VIEW ( networks_tree ))),
"changed" , G_CALLBACK ( servlist_network_row_cb ), NULL );
2026-03-17 10:30:54 -06:00
g_signal_connect ( G_OBJECT ( networks_tree ), "key-press-event" ,
2011-02-24 04:14:30 +01:00
G_CALLBACK ( servlist_net_keypress_cb ), networks_tree );
gtk_widget_show ( serverlist_win );
}