📄 serverlist.c
字号:
/* X-Chat * Copyright (C) 1998 Peter Zelezny. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <unistd.h>#include "fe-gtk.h"#include "../common/xchat.h"#include "../common/cfgfiles.h"#include "../common/fe.h"#include "../common/server.h"#include "../common/xchatc.h"#include "serverlist.h"#include "gtkutil.h"#include "pixmaps.h"#include "wins.h"static GtkWidget *slwin = 0;static GtkWidget *sleditwin = 0;static GtkWidget *entry_server;static GtkWidget *entry_channel;static GtkWidget *quickview;static GtkWidget *entry_port;static GtkWidget *entry_comment;static GtkWidget *entry_password;static GtkWidget *entry_nick;static GtkWidget *entry_eomcmd;static GtkWidget *entry_autoconnect;static GtkWidget *entry_use_proxy;static GtkWidget *entry_use_ssl;static GtkWidget *entry_accept_invalid_cert;static GtkWidget *nick1gad;static GtkWidget *nick2gad;static GtkWidget *nick3gad;static GtkWidget *realnamegad;static GtkWidget *usernamegad;static GtkWidget *sltree;static GtkWidget *button_connnew;static GtkWidget *button_conn;static GtkWidget *button_chan_new;static GSList *server_malloc_list = 0;static GSList *server_parents = 0;static GtkCTreeNode *editnode = 0;static struct slentry *editentry = 0;static int previous_depth = 0;static int closing_list = 0;/*static gboolean channelbox = 0;*/static gboolean first_autoconnect = 0;static gboolean new_entry = 0;static gboolean some_are_auto = 0;/************************** * Public functions: * * ----------------- * * open_server_list * * serverlist_autoconnect * **************************//* * is_group: * Returns TRUE or FALSE if a TreeNode is a group or not */static intis_group (GtkCTreeNode * selected){ struct slentry *conn; if (!selected) return 0; conn = gtk_ctree_node_get_row_data (GTK_CTREE (sltree), selected); if (!strcmp (conn->server, "SUB")) return 1; else return 0;}/* * add_server_entry: * takes a struct slentry as argument and parses + inserts it into the tree (and mem) */static voidadd_server_entry (struct slentry *serv){ gchar *text[] = { "" }; struct slentry *new = 0; GtkCTreeNode *node = 0; GtkCTreeNode *parent = 0; GdkColor autoconnect_color = { 0, 0x0000, 0x8000, 0x0000 }; if (g_slist_last (server_parents)) parent = ((g_slist_last (server_parents))->data); if (!strcmp ("SUB", serv->server)) { new = malloc (sizeof (struct slentry)); memset (new, 0, sizeof (struct slentry)); text[0] = new->comment; strcpy (new->comment, serv->comment); strcpy (new->server, serv->server); if (serv->port) new->port = 1; node = gtk_ctree_insert_node (GTK_CTREE (sltree), parent, NULL, text, 4, pix_globe, mask_globe, pix_globe, mask_globe, FALSE, FALSE); if (new->port) gtk_ctree_expand (GTK_CTREE (sltree), node); else gtk_ctree_collapse (GTK_CTREE (sltree), node); gtk_ctree_node_set_row_data (GTK_CTREE (sltree), node, new); server_parents = g_slist_append (server_parents, node); server_malloc_list = g_slist_prepend (server_malloc_list, new); } else if (!strcmp ("ENDSUB", serv->server) && g_slist_last (server_parents)) server_parents = g_slist_remove (server_parents, ((g_slist_last (server_parents))->data)); else { new = malloc (sizeof (struct slentry)); new->port = serv->port; new->flags = serv->flags; strcpy (new->comment, serv->comment); strcpy (new->channel, serv->channel); strcpy (new->server, serv->server); strcpy (new->password, serv->password); strcpy (new->nick, serv->nick); strcpy (new->eom_cmd, serv->eom_cmd); text[0] = new->comment; node = gtk_ctree_insert_node (GTK_CTREE (sltree), parent, NULL, text, 4, pix_server, mask_server, pix_server, mask_server, TRUE, FALSE); gtk_ctree_node_set_row_data (GTK_CTREE (sltree), node, new); server_malloc_list = g_slist_prepend (server_malloc_list, new); if (new->flags & AUTOCONNECT) { gtk_ctree_node_set_foreground (GTK_CTREE (sltree), node, &autoconnect_color); some_are_auto = TRUE; } }}/* * add_defaults: * called if ~/.xchat/serverlist.conf isn't found */static voidadd_defaults (void){ struct slentry serv; int i = 0; serv.password[0] = 0; serv.nick[0] = 0; serv.eom_cmd[0] = 0; while (dserv[i].server != 0) { strcpy (serv.channel, dserv[i].channel); strcpy (serv.server, dserv[i].server); strcpy (serv.comment, dserv[i].comment); serv.port = dserv[i].port; serv.flags = 0; add_server_entry (&serv); i++; }}/* * read_next_server_entry: * reads lines from ~/.xchat/serverlist.conf until it has filled a server entry */static char *read_next_server_entry (char *my_cfg, struct slentry *serv){ char *my_cfg_tmp; if ((my_cfg_tmp = cfg_get_str (my_cfg, "servername ", serv->server))) my_cfg = my_cfg_tmp; else return 0; /* EOF */ if ((my_cfg_tmp = cfg_get_str (my_cfg, "port", serv->channel))) { my_cfg = my_cfg_tmp; serv->port = atoi (serv->channel); } if ((my_cfg_tmp = cfg_get_str (my_cfg, "flags", serv->channel))) { my_cfg = my_cfg_tmp; serv->flags = atoi (serv->channel); } if ((my_cfg_tmp = cfg_get_str (my_cfg, "channel", serv->channel))) my_cfg = my_cfg_tmp; if ((my_cfg_tmp = cfg_get_str (my_cfg, "password", serv->password))) my_cfg = my_cfg_tmp; if ((my_cfg_tmp = cfg_get_str (my_cfg, "nick", serv->nick))) my_cfg = my_cfg_tmp; if ((my_cfg_tmp = cfg_get_str (my_cfg, "comment", serv->comment))) my_cfg = my_cfg_tmp; if ((my_cfg_tmp = cfg_get_str (my_cfg, "eom_cmd", serv->eom_cmd))) my_cfg = my_cfg_tmp; return my_cfg;}/* * load_serverentrys: * opens the serverlist.conf file and parses it */static voidload_serverentrys (int select_row){ struct slentry serv; struct stat st; int fh, i; char *cfg, *my_cfg; char file[256]; snprintf (file, sizeof file, "%s/serverlist.conf", get_xdir ()); fh = open (file, O_RDONLY | OFLAGS); if (fh != -1) { fstat (fh, &st); if (st.st_size == 0) { add_defaults (); } else { my_cfg = cfg = malloc (st.st_size + 1); cfg[0] = '\0'; i = read (fh, cfg, st.st_size); if (i >= 0) cfg[i] = '\0'; do { serv.nick[0] = 0; serv.flags = 0; serv.eom_cmd[0] = 0; my_cfg = read_next_server_entry (my_cfg, &serv); if (my_cfg) add_server_entry (&serv); } while (my_cfg); free (cfg); while (server_parents) { server_parents = g_slist_remove (server_parents, server_parents->data); } } close (fh); } else { add_defaults (); } gtk_clist_select_row (GTK_CLIST (sltree), select_row, 0); GTK_CLIST (sltree)->focus_row = select_row;}/* * write_serverentry: * takes a serverentry and a filehandle and writes the entry to the file */static voidwrite_serverentry (struct slentry *entry, int fh){ char buf[1024]; snprintf (buf, sizeof buf, "servername = %s\n" "port = %d\n" "flags = %d\n" "channel = %s\n" "password = %s\n" "nick = %s\n" "comment = %s\n" "eom_cmd = %s\n\n", entry->server, entry->port, entry->flags, entry->channel, entry->password, entry->nick, entry->comment, entry->eom_cmd); write (fh, buf, strlen (buf));}/* * parse_serverentrys: * used by save_serverentrys to parse the servers currently in mem before writing */static voidparse_serverentrys (GtkCTree * ctree, GtkCTreeNode * node, int *fh){ struct slentry *temporary = gtk_ctree_node_get_row_data (GTK_CTREE (sltree), node); struct slentry buf; GtkCTreeNode *tempus = node; int diff = 0, depth = 0; while ((GTK_CTREE_ROW (tempus))->parent) { depth++; tempus = GTK_CTREE_NODE ((GTK_CTREE_ROW (tempus))->parent); } diff = depth - previous_depth; previous_depth = depth; temporary = gtk_ctree_node_get_row_data (GTK_CTREE (sltree), node); while (diff < 0) { memset (&buf, 0, sizeof (struct slentry)); strcpy (buf.server, "ENDSUB"); write_serverentry (&buf, *fh); diff++; } memcpy (&buf, temporary, sizeof (struct slentry)); write_serverentry (&buf, *fh); if (!strcmp (buf.server, "SUB") && (((GTK_CTREE_ROW (node))->children)) == 0) { /* If we got a group without any children we need an ENDSUB at least */ memset (&buf, 0, sizeof (struct slentry)); strcpy (buf.server, "ENDSUB"); write_serverentry (&buf, *fh); }}/* * save_serverentrys: * function called elsewhere whenever we want to dump contents in mem to disk */static voidsave_serverentrys (void){ int fh; char file[512]; char buf[256]; check_prefs_dir (); snprintf (file, sizeof file, "%s/serverlist.conf", get_xdir ()); fh = open (file, O_TRUNC | O_WRONLY | O_CREAT | OFLAGS, 0600); if (fh != -1) { previous_depth = 0; strcpy (buf, "version = "VERSION"\n\n"); write (fh, buf, strlen (buf)); gtk_ctree_pre_recursive (GTK_CTREE (sltree), NULL, GTK_CTREE_FUNC (parse_serverentrys), &fh); close (fh); }}/* * reload_servers: * little cute function to dump mem to disk, free mem and reload from disk */static voidreload_servers (void){ int focus_row; if (sleditwin) { gtk_widget_destroy (sleditwin); sleditwin = 0; } if (sltree) { focus_row = GTK_CLIST (sltree)->focus_row; closing_list = 1; gtk_clist_freeze (GTK_CLIST (sltree)); save_serverentrys (); while (gtk_ctree_node_nth (GTK_CTREE (sltree), 0)) gtk_ctree_remove_node (GTK_CTREE (sltree), gtk_ctree_node_nth (GTK_CTREE (sltree), 0)); while (server_malloc_list) { free (server_malloc_list->data); server_malloc_list = g_slist_remove (server_malloc_list, server_malloc_list->data); } load_serverentrys (focus_row); gtk_clist_thaw (GTK_CLIST (sltree)); closing_list = 0; }}/* * delete_server_clicked: * called when the "delete" button is clicked in server list GUI */static voiddelete_server_clicked (GtkWidget * wid, struct session *sess){ GtkCTreeNode *selected = 0; selected = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (sltree)->row_list, GTK_CLIST (sltree)->focus_row)); if (selected) { gtk_ctree_unselect (GTK_CTREE (sltree), selected); gtk_ctree_remove_node (GTK_CTREE (sltree), selected); reload_servers (); }}/* * close_edit_entry: * called when we want to destroy the edit entry win */static voidclose_edit_entry (void){ if (sleditwin) { gtk_widget_destroy (GTK_WIDGET (sleditwin)); sleditwin = 0; } if (new_entry) gtk_ctree_remove_node (GTK_CTREE (sltree), editnode); if (sltree) reload_servers (); sleditwin = 0; editentry = 0; editnode = 0; new_entry = 0;}/* * done_edit_entry: * called when were done editing an entry */static voiddone_edit_entry (void){ if (!sleditwin) return; if (!editentry) return; if (!editnode) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -