/* Copyright (C) 2000-2004 Markus Lausser (sgop@users.sf.net) This is free software distributed under the terms of the GNU Public License. See the file COPYING for details. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "lopster.h" #include "connection.h" #include "global.h" #include "search.h" #include "transfer.h" #include "support.h" #include "callbacks.h" #include "chat.h" #include "server.h" #include "scheme.h" #include "commands.h" #include "log.h" #include "handler.h" #include "hotlist.h" #include "string_list.h" #include "utils.h" #include "userinfo.h" #define MAX_LINE_LENGTH 150 static GList* stamps = NULL; static void detect_channel_pixs(channel_user_t* cu, GdkPixmap** pix, GdkBitmap** bit) { if (cu->flags & CU_OP) { *pix = global.pix.sgreen; *bit = global.pix.sgreenb; } else if (cu->flags & CU_VOICE) { *pix = global.pix.syellow; *bit = global.pix.syellowb; } else { *pix = global.pix.dummy; *bit = global.pix.dummyb; } } static char* mode_tip(int mode) { switch (mode) { case 0: return "Topic is restricted"; case 1: return "Channel is registered"; case 2: return "No outside messages"; case 3: return "Secret"; case 4: return "Channel is private"; case 5: return "Channel is invite only"; case 6: return "Channel is moderated"; default: return "unknown channel mode"; } } GdkColor* get_nick_color(const char *nick, int mode) { static GdkColor fore; char *hex1 = "89abcdef"; char *hex2 = "456789ab"; char *hex3 = "01234567"; char* hex; char ncolor[8] = "#000000"; int i1; unsigned long sum = 1; int prim[6] = { 71, 79, 83, 89, 101, 113 }; if (!nick) return &fore; if (mode == 1) hex = hex1; else if (mode == 2) hex = hex2; else if (mode == 3) hex = hex3; else hex = hex2; while (*nick) sum *= *nick++; // sum = l_rand(sum); for (i1 = 0; i1 < 6; i1++) { ncolor[i1+1] = hex[(sum%prim[i1]) % 8]; } gdk_color_parse(ncolor, &fore); gdk_color_alloc(gtk_widget_get_colormap(global.win), &fore); return &fore; } void chat_print_network(chat_page_t* page, int type, net_t* net, int max_length, int num) { GtkWidget* temp; char sname[1024]; if (!page) return; if (num) { temp = chat_print_text(page, type, "chat_background", "("); sprintf(sname, "%d", g_list_index(global.net_active, net)+1); temp = chat_print_text(page, type, "message", sname); temp = chat_print_text(page, type, "chat_background", ") "); } temp = chat_print_text_w(page, type, "nick", net->name, max_length); if (temp) { int length = strlen(net->name); if (max_length > length) length = max_length; text_insert_token(temp, net->name, net, TEXT_SERVER, GTK_TEXT(temp)->text_end-GTK_TEXT(temp)->gap_size- length); } } void chat_print_channel(chat_page_t* page, int message_type, char* channel, net_t* net) { GtkWidget* temp; channel_entry_t* chan; if (!page) return; chan = g_malloc(sizeof(*chan)); chan->name = g_strdup(channel); chan->net = net; chan->topic = NULL; chan->level = -1; chan->online = -1; chan->limit = -1; temp = chat_print_text(page, message_type, "nick", channel); if (temp) { text_insert_token(temp, channel, chan, TEXT_CHANNEL, GTK_TEXT(temp)->text_end-GTK_TEXT(temp)->gap_size- strlen(channel)); } } void chat_print_url(chat_page_t* page, int message_type, char* url) { GtkWidget* temp; if (!page) return; temp = chat_print_text(page, message_type, "url", url); if (temp) { text_insert_token(temp, url, g_strdup(url), TEXT_URL, GTK_TEXT(temp)->text_end-GTK_TEXT(temp)->gap_size- strlen(url)); } } char* chat_print_nick(chat_page_t* page, int message_type, char* user, net_t* net) { int colored = 0; static char style[64]; GtkWidget* temp; net_user_t* nu; static char* unknown_nick = NULL; if (!unknown_nick) unknown_nick = "_unknown_"; if (!page) return NULL; if (!user) user = unknown_nick; if (net && !g_strcasecmp(net->user.username, user)) strcpy(style, "yourself"); else if (global.options.colored_nicks) { strcpy(style, "nick"); colored = 1; } else if (string_list_search(LIST_FRIEND, user)) strcpy(style, "friend"); else strcpy(style, "user"); nu = g_malloc(sizeof(*nu)); nu->net = net; nu->user = g_strdup(user); temp = chat_print_text(page, message_type, style, user); if (temp) { text_insert_token(temp, user, nu, TEXT_USER, GTK_TEXT(temp)->text_end-GTK_TEXT(temp)->gap_size- strlen(user)); } if (colored) return NULL; else return style; } void chat_print_file(chat_page_t* page, char* filename, char* text) { if (!page) return; chat_print_text(page, M_PUBLIC, "text", text); if (page->main) { text_insert_token(page->main, text, g_strdup(filename), TEXT_FILE, GTK_TEXT(page->main)->text_end - GTK_TEXT(page->main)->gap_size - strlen(text)); } } static style_t* chat_get_style(char* color, const char* text, GdkColor** mcolor) { style_t* style; if (!color) { style = style_get(global.scheme, "user"); *mcolor = get_nick_color(NULL, global.options.colored_nicks); } else if (!strcmp(color, "nick")) { style = style_get(global.scheme, "user"); *mcolor = get_nick_color(text, global.options.colored_nicks); } else { style = style_get(global.scheme, color); *mcolor = style->fore; } return style; } static void text_delete_token(word_info_t* winfo) { switch (winfo->type) { case TEXT_FILE: g_free(winfo->data); break; case TEXT_SERVER: break; case TEXT_USER: { net_user_t* nu; nu = winfo->data; g_free(nu->user); g_free(nu); break; } case TEXT_URL: g_free(winfo->data); break; case TEXT_CHANNEL: { channel_entry_t* chan; chan = winfo->data; g_free(chan->name); if (chan->topic) g_free(chan->topic); g_free(chan); break; } default: break; } g_free(winfo->word); g_free(winfo); } static void text_update_tokens(GtkWidget* widget, int offset) { text_info_t* tinfo; word_info_t* winfo; int i1; int pos; tinfo = gtk_object_get_data(GTK_OBJECT(widget), "text_info"); if (!tinfo) return; pos = 0; for (i1 = 0; i1 < tinfo->pos; i1++) { winfo = tinfo->info[i1]; winfo->start_pos -= offset; if (winfo->start_pos < 0) { text_delete_token(winfo); } else { if (i1 != pos) tinfo->info[pos] = winfo; pos++; } } tinfo->pos = pos; } static void check_buffer(GtkText* text) { int limit = global.options.max_chat_buffer*1000; int del_cnt; if (limit == 0) return; if (gtk_text_get_length(text) > (unsigned int)limit) { del_cnt = gtk_text_get_length (text) - limit; gtk_text_set_point(text, 0); gtk_text_forward_delete(text, del_cnt); text_update_tokens(GTK_WIDGET(text), del_cnt); } gtk_text_set_point(text, gtk_text_get_length (text)); } void snap_to_bottom(GtkWidget * text) { GtkAdjustment *vertical_adjustment; vertical_adjustment = GTK_ADJUSTMENT(GTK_TEXT(text)->vadj); gtk_adjustment_set_value(vertical_adjustment, vertical_adjustment->upper - vertical_adjustment->lower - vertical_adjustment->page_size); } static int chat_page_thaw(gpointer data) { chat_page_t *page = (chat_page_t *) data; if (page->header && (page->type == P_PUBLIC)) { check_buffer(GTK_TEXT(page->header)); gtk_text_thaw(GTK_TEXT(page->header)); } if (page->wallop) { check_buffer(GTK_TEXT(page->wallop)); gtk_text_thaw(GTK_TEXT(page->wallop)); } if (page->main) { check_buffer(GTK_TEXT(page->main)); gtk_text_thaw(GTK_TEXT(page->main)); } if (page->timeout >= 0) { gtk_timeout_remove(page->timeout); page->timeout = -1; } if (page->snap & 1) snap_to_bottom(page->header); if (page->snap & 2) snap_to_bottom(page->wallop); if (page->snap & 4) snap_to_bottom(page->main); page->snap = 0; page->modified = 0; return 1; } static int scroll_mode(GtkWidget * text) { int value = GTK_ADJUSTMENT(GTK_TEXT(text)->vadj)->value; int page_size = GTK_ADJUSTMENT(GTK_TEXT(text)->vadj)->page_size; int upper = GTK_ADJUSTMENT(GTK_TEXT(text)->vadj)->upper; if (value + page_size < upper) return 0; else return 1; } static void chat_page_freeze(chat_page_t * page, int message_type) { if ((message_type == M_TOPIC) && ((page->modified & 1) == 0) && scroll_mode(page->header)) page->snap |= 1; if ((message_type == M_OP) && ((page->modified & 2) == 0) && scroll_mode(page->wallop)) page->snap |= 2; if ((message_type == M_PUBLIC) && ((page->modified & 4) == 0) && scroll_mode(page->main)) page->snap |= 4; if (page->timeout >= 0) { // update g_freeze gtk_timeout_remove(page->timeout); } else { // first g_freeze if (page->header && (page->type == P_PUBLIC)) gtk_text_freeze(GTK_TEXT(page->header)); if (page->wallop) gtk_text_freeze(GTK_TEXT(page->wallop)); if (page->main) gtk_text_freeze(GTK_TEXT(page->main)); } page->timeout = gtk_timeout_add(100, chat_page_thaw, page); } GtkWidget* chat_print_text(chat_page_t * page, int message_type, char *color, const char *text) { style_t *style; GtkWidget *temp; GdkColor *mcolor; GtkPaned* paned; if (!page || page->type == P_CHANNEL) return NULL; if (message_type == M_TOPIC) temp = page->header; else if (message_type == M_OP) { if (page->type == P_PUBLIC) { paned = GTK_PANED(page->paned); if (paned->child1_size < 60) gtk_paned_set_position(paned, 60); } temp = page->wallop; } else temp = page->main; if (!temp) return NULL; style = chat_get_style(color, text, &mcolor); chat_page_freeze(page, message_type); gtk_text_insert(GTK_TEXT(temp), style->font, mcolor, style->back, text, strlen(text)); highlight(page, 1); return temp; } GtkWidget* chat_print_text_w(chat_page_t * page, int message_type, char *color, char *text, int width) { style_t *style; GtkWidget *temp; GdkColor *mcolor; char tempstr[1024]; if (!page || page->type == P_CHANNEL) return NULL; if (message_type == M_TOPIC) temp = page->header; else if (message_type == M_OP) temp = page->wallop; else temp = page->main; if (!temp) return NULL; if (width<0) width = 0; style = chat_get_style(color, text, &mcolor); chat_page_freeze(page, message_type); gtk_text_insert(GTK_TEXT(temp), style->font, mcolor, style->back, text, strlen(text)); if (width > (signed)strlen(text)) { int nw = width-strlen(text); sprintf(tempstr, "%*s", nw, " "); gtk_text_insert(GTK_TEXT(temp), style->font, mcolor, style->back, tempstr, strlen(tempstr)); } highlight(page, 1); return temp; } static void chat_print_text_color(chat_page_t * page, int message_type, char *color, GdkColor* fore, GdkColor* back, const char *text) { style_t *style; GtkWidget *temp; GdkColor *f; GdkColor *b; if (!page || page->type == P_CHANNEL) return; if (message_type == M_TOPIC) temp = page->header; else if (message_type == M_OP) temp = page->wallop; else temp = page->main; if (!temp) return; style = chat_get_style(color, text, &f); if (fore) f = fore; if (back) b = back; else b = style->back; chat_page_freeze(page, message_type); gtk_text_insert(GTK_TEXT(temp), style->font, f, b, text, strlen(text)); highlight(page, 1); return; } void chat_print_colored(chat_page_t * page, int message_type, char *base_color, const char *text) { GdkColor *fgcolor = NULL; GdkColor *bgcolor = NULL; char *pos2; int len; char temp_str[2048]; int index; while (1) { pos2 = search_highlight_string(text, &len); if (!pos2) break; strncpy(temp_str, text, pos2 - text); temp_str[pos2 - text] = 0; if (global.options.strip_colors) chat_print_text(page, message_type, base_color, temp_str); else chat_print_text_color(page, message_type, base_color, fgcolor, bgcolor, temp_str); if (pos2[0] == 0x03) { if (pos2[1] == 0 || pos2[2] == 0 || pos2[3] == 0) return; if (pos2[1] == 0x0f) { fgcolor = NULL; bgcolor = NULL; len = 2; } else if (pos2[1] == ',') { index = ColorTable2(pos2[3] - '0'); if (index < 0) index = -index; bgcolor = &global.color_table[index]; len = 4; } else if (pos2[1] != '-') { index = ColorTable(pos2[1] - '0', pos2[2] - '0'); if (index < 0) index = -index; fgcolor = &global.color_table[index]; len = 3; } } else { strncpy(temp_str, pos2, len); temp_str[len] = 0; chat_print_text(page, message_type, "highlight", temp_str); } text = pos2 + len; } if (global.options.strip_colors) chat_print_text(page, message_type, base_color, text); else chat_print_text_color(page, message_type, base_color, fgcolor, bgcolor, text); return; } chat_page_t* chat_print_current(char* style, char* text) { chat_page_t* page; page = chat_page_get_printable(); if (!page) return NULL; chat_print_colored(page, M_PUBLIC, style, text); return page; } void chat_print_current_ln(char* style, char* text) { chat_page_t* page; page = chat_print_current(style, text); if (page) chat_print_text(page, M_PUBLIC, style, "\n"); } void chat_print_time_stamp(chat_page_t * page, int message_type) { char stime[200] = ""; if (global.options.timestamps == TIME_NONE) return; chat_print_text(page, message_type, "text", "["); chat_print_text(page, message_type, "message", current_time(stime, global.options.timestamps)); chat_print_text(page, message_type, "text", "] "); } //////////////////////////// //////////////////////////// //////////////////////////// //////////////////////////// //////////////////////////// //////////////////////////// GtkWidget *create_online_popup(channel_user_t* cu) { GtkWidget *popup; GtkWidget *item; GtkWidget *separator; GtkAccelGroup *popup_accels; if (cu) { popup = create_user_popup(M_ONLINE, cu); separator = gtk_menu_item_new(); gtk_widget_show(separator); gtk_container_add(GTK_CONTAINER(popup), separator); gtk_widget_set_sensitive(separator, FALSE); separator = gtk_menu_item_new(); gtk_widget_show(separator); gtk_container_add(GTK_CONTAINER(popup), separator); gtk_widget_set_sensitive(separator, FALSE); item = gtk_menu_item_new_with_label("Refresh List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_refresh_list_activate), cu->page); if (!cu->page->active) gtk_widget_set_sensitive(item, FALSE); separator = gtk_menu_item_new(); gtk_widget_show(separator); gtk_container_add(GTK_CONTAINER(popup), separator); gtk_widget_set_sensitive(separator, FALSE); } else { popup = gtk_menu_new(); gtk_object_set_data(GTK_OBJECT(popup), "popup", popup); popup_accels = gtk_menu_ensure_uline_accel_group(GTK_MENU(popup)); } item = gtk_menu_item_new_with_label("Customize List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_customize_list_activate), GINT_TO_POINTER(4)); return popup; } void line_insert_lf(char *line) { char *last_ws = line; char *temp = line; int length; if (!line) return; length = strlen(line); if (length == 0) return; if (line[length - 1] == '\n') { line[length - 1] = 0; length--; } if (length <= MAX_LINE_LENGTH) return; while (line) { while (temp - line <= MAX_LINE_LENGTH) { last_ws = temp; temp = strpbrk(temp + 1, " \n\t"); if (!temp) break; if (*temp == '\n') { last_ws = temp; break; } } if ((last_ws - line > 0) && (temp)) { *last_ws = '\n'; line = temp = last_ws + 1; } else { break; } } } chat_page_t* chat_page_get_printable() { chat_page_t* page; page = global.current_page; if (!page || (page->type == P_CHANNEL)) { page = chat_page_search(NULL, "temp_page", P_OTHER, 3); if (!page) page = create_other_page(NULL, "temp_page", "Temporary"); } return page; } void on_hide_show_clicked(GtkButton * button, gpointer user_data ATTR_UNUSED) { GtkWidget *temp; GtkPaned *paned; int pos; temp = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(button), "con_widget")); paned = GTK_PANED(global.current_page->toplevel); if (GTK_WIDGET_VISIBLE(temp)) { pos = (int) gtk_object_get_data(GTK_OBJECT(button), "pan_pos"); gtk_paned_set_position(paned, pos); } else { gtk_object_set_data(GTK_OBJECT(button), "pan_pos", (gpointer) (paned->child1_size)); gtk_paned_set_position(paned, paned->child1_size + temp->allocation.width); } } void chat_page_update_network(chat_page_t* page, net_t* net) { char* text; if (page->net != net && page->type != P_CHANNEL) { if (!net) { chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 1); chat_print_text(page, M_PUBLIC, "message", "Left Network "); chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, page->net, 0, 1); chat_print_text(page, M_PUBLIC, "user", "]\n"); } else { chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 1); chat_print_text(page, M_PUBLIC, "message", "Joined Network "); chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "user", "]\n"); } } chat_page_set_active(page, 1); page->net = net; text = g_strdup_printf("%s\n%s", net?net->name:"", page->vname); gtk_label_set_text(GTK_LABEL(page->tlabel), text); g_free(text); } chat_page_t* create_private_page(net_t* net, char *name) { GtkWidget *scrolledwindow27; GtkWidget *text4; GtkWidget *tab_label; GtkWidget *label; GtkWidget *pix1; GtkWidget *button; GtkWidget *vbox; GtkNotebook *notebook; chat_page_t *page; hot_t *hot; char* text; notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook3")); if (global.options.switch_im) switch_to_page(1); page = chat_page_search2(name, P_PRIVATE); if (page) { if (net) chat_page_update_network(page, net); gtk_notebook_set_page(GTK_NOTEBOOK(notebook), gtk_notebook_page_num(GTK_NOTEBOOK(notebook), page->toplevel)); return page; } vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); scrolledwindow27 = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow27); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow27), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow27, TRUE, TRUE, 0); text4 = gtk_text_new(NULL, NULL); gtk_signal_connect_after(GTK_OBJECT(text4), "button_press_event", GTK_SIGNAL_FUNC(on_text_button_press_event), NULL); gtk_widget_set_style(text4, global.scheme->style); gtk_widget_show(text4); gtk_text_set_word_wrap(GTK_TEXT(text4), 1); gtk_container_add(GTK_CONTAINER(scrolledwindow27), text4); tab_label = gtk_hbox_new (FALSE, 2); gtk_widget_ref (tab_label); gtk_widget_show (tab_label); text = g_strdup_printf("%s\n%s", net?net->name:"", name); label = gtk_label_new(text); g_free(text); gtk_widget_show(label); gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0); button = gtk_button_new(); gtk_widget_show(button); gtk_box_pack_start (GTK_BOX (tab_label), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); gtk_widget_set_sensitive(button, FALSE); pix1 = create_pixmap (global.win, "close.xpm"); gtk_widget_show (pix1); gtk_container_add (GTK_CONTAINER (button), pix1); page = chat_page_new(name, name, P_PRIVATE, net); page->header = NULL; page->main = text4; page->wallop = NULL; page->tmain = tab_label; page->tlabel = label; page->tclose = button; page->toplevel = vbox; gtk_widget_hide(button); gtk_object_set_data(GTK_OBJECT(tab_label), "page", page); gtk_notebook_append_page(notebook, page->toplevel, page->tmain); if (global.options.switch_im) { gtk_notebook_set_page(GTK_NOTEBOOK(notebook), gtk_notebook_page_num(GTK_NOTEBOOK(notebook), page->toplevel)); } gtk_signal_connect(GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_chat_close_clicked), page); hot = hotlist_search_user(name); if (hot) { if (hot->nets && !net) chat_page_update_network(page, hot->nets->data); } else { hot = hotlist_add(name, NULL, 0); } return page; } void send_afk(net_t* net, char *user, afk_t * afk) { char *message; int d, h, m; char s1[1024]; char s2[1024]; char s3[1024]; time_t tim; user_timestamp_t* stamp; if (!net) return; // do not send AFK message to enemies if (string_list_search(LIST_ENEMY, user)) return; if (!afk->message || !(afk->message[0])) return; stamp = timestamp_search(stamps, user); if (!stamp || (timestamp_difference(stamp) > 1000*200)) { tim = global.current_time - afk->since; // seconds tim /= 60; // minutes m = tim % 60; // %minutes tim /= 60; // hours h = tim % 24; // %hours d = tim / 24; // days if (d) sprintf(s1, "%d days ", d); else *s1 = 0; if (h || d) sprintf(s2, "%d hours ", h); else *s2 = 0; if (m || h || d) sprintf(s3, "%d minutes", m); else sprintf(s3, "%d minutes", 0); message = g_strdup_printf("AFK: %s [%s%s%s]", afk->message, s1, s2, s3); send_notice(net, user, message, 0); g_free(message); } stamps = timestamp_touch_user(stamps, user); } int check_server_join_quit(net_t* net, char *data) { char *temp; char *serv; char *str1; char *str2; int mode = 0; temp = g_strdup(data); str1 = arg(temp, 0); serv = arg(NULL, 0); str2 = arg(NULL, 1); if (!str1) goto done_false; if (!serv) goto done_false; if (!str2) goto done_false; if (g_strcasecmp(str1, "Server")) goto done_false; if (!strncmp(str2, "has quit", 8)) mode = 1; if (!strncmp(str2, "has joined", 10)) mode = 2; if (mode == 0) goto done_false; if (mode == 2) { network_links_get(net); goto done_true; } // remove the server (mode 1) { chat_page_t *page; char* prefix; page = chat_page_get_printable(); chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 0); chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "user", "] "); prefix = g_strdup_printf("Server [%s] has quit.\n", serv); chat_print_text(page, M_PUBLIC, "message", prefix); g_free(prefix); } link_remove(net->links, serv); done_true: g_free(temp); return 1; done_false: g_free(temp); return 0; } void send_global(net_t* net, char *text) { char *text2; char *pos; if (!NET_CONNECTED(net)) return; line_insert_lf(text); do { pos = strchr(text, '\n'); if (pos) *pos = 0; if (global.options.parse_colors) text2 = cparse(text); else text2 = text; command_send(net, CMD_ANNOUNCE, text2); if (!pos) break; text = pos + 1; } while (*text); } void send_wallop(net_t* net, char *text) { char *text2; char *pos; if (!NET_CONNECTED(net)) return; line_insert_lf(text); do { pos = strchr(text, '\n'); if (pos) *pos = 0; if (global.options.parse_colors) text2 = cparse(text); else text2 = text; command_send(net, CMD_WALLOP, text2); if (!pos) break; text = pos + 1; } while (*text); } void send_private_emote(net_t* net, char* nick, char *text) { char *text2; char *pos; chat_page_t* page; int in_private; char *style; if (!NET_CONNECTED(net)) return; page = chat_page_get_printable(); if ((global.current_page->type == P_PRIVATE) && !strcasecmp(global.current_page->name, nick)) in_private = 1; else in_private = 0; line_insert_lf(text); do { pos = strchr(text, '\n'); if (pos) *pos = 0; if (global.options.parse_colors) text2 = cparse(text); else text2 = text; command_send(net, CMD_PRIVATE_EMOTE, nick, text2); l_log(NULL, nick, LOG_PRIVATE, "<%s %s>\n", net->user.username, text2); if (!in_private) { chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "<"); chat_print_text(page, M_PUBLIC, "text", "to: "); chat_print_nick(page, M_PUBLIC, nick, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_nick(page, M_PUBLIC, net->user.username, net); chat_print_text(page, M_PUBLIC, "text", " "); chat_print_text(page, M_PUBLIC, "whisper", text2); chat_print_text(page, M_PUBLIC, "text", "\n"); } else { chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "<"); style = chat_print_nick(page, M_PUBLIC, net->user.username, net); chat_print_text(page, M_PUBLIC, style, " "); chat_print_colored(page, M_PUBLIC, style, text2); chat_print_text(page, M_PUBLIC, "user", ">\n"); } if (!pos) break; text = pos + 1; } while (*text); } void send_public_emote(chat_page_t* page, char *text) { char *text2; char *pos; if (page->type != P_PUBLIC || !page->net || !page->active) return; convert_quotes(text); line_insert_lf(text); do { pos = strchr(text, '\n'); if (pos) *pos = 0; if (global.options.parse_colors) text2 = cparse(text); else text2 = text; command_send(page->net, CMD_PUBLIC_EMOTE, page->name, text2); if (!pos) break; text = pos + 1; } while (*text); } static int is_url(char *word) { int len = strlen (word); char* at; char* dot; if (!isalnum(*word)) return 0; dot = word; while ((dot = strchr(dot, '.'))) { dot++; if (*dot == '.') return 0; } if (len < 5) return 0; if (!strncasecmp (word, "irc://", 6)) return 1; if (!strncasecmp (word, "irc.", 4)) return 1; if (!strncasecmp (word, "ftp.", 4)) return 1; if (!strncasecmp (word, "ftp:", 4)) return 1; if (!strncasecmp (word, "www.", 4)) return 1; if (!strncasecmp (word, "http:", 5)) return 1; if (!strncasecmp (word, "https:", 6)) return 1; at = strchr (word, '@'); /* check for email addy */ dot = strrchr (word, '.'); if (at && dot) { if ((unsigned long) at < (unsigned long) dot) { return 0; } } if (!strncasecmp (word + len - 5, ".html", 5)) return 1; if (!strncasecmp (word + len - 4, ".htm", 4)) return 1; if (!strncasecmp (word + len - 4, ".org", 4)) return 1; if (!strncasecmp (word + len - 4, ".net", 4)) return 1; if (!strncasecmp (word + len - 4, ".com", 4)) return 1; if (!strncasecmp (word + len - 4, ".edu", 4)) return 1; if (len > 5) { if (word[len - 3] == '.' && isalpha (word[len - 2]) && isalpha (word[len - 1])) return 1; } return 0; } static void chat_print_line(chat_page_t* page, int type, char* style, char* message) { char* pos2; char save1 = 0; char save2 = 0; if (!message) return; do { while (*message == ' ') { chat_print_text(page, type, style, " "); message++; } pos2 = strchr(message, ' '); if (pos2) *pos2 = 0; if (is_url(message)) { if (message[strlen(message)-1] == '.') { message[strlen(message)-1] = 0; save1 = 1; } else save1 = 0; if (message[strlen(message)-1] == ')') { message[strlen(message)-1] = 0; save2 = 1; } else save2 = 0; if (!is_string_in_list(global.urls, message)) global.urls = g_list_append(global.urls, g_strdup(message)); chat_print_url(page, type, message); if (save2) chat_print_text(page, type, style, ")"); if (save1) chat_print_text(page, type, style, "."); } else { chat_print_colored(page, type, style, message); } if (!pos2) break; chat_print_text(page, type, style, " "); message = pos2+1; } while (*message != 0); } void send_private(net_t* net, char* nick, char *text, int show) { char *text2; char *pos; chat_page_t* page; int in_private; if (!NET_CONNECTED(net)) return; page = chat_page_get_printable(); if ((global.current_page->type == P_PRIVATE) && !strcasecmp(global.current_page->name, nick)) in_private = 1; else in_private = 0; line_insert_lf(text); do { pos = strchr(text, '\n'); if (pos) *pos = 0; if (global.options.parse_colors) text2 = cparse(text); else text2 = text; command_send(net, CMD_PRIVMSG, nick, text2); if (show) { l_log(NULL, nick, LOG_PRIVATE, "<%s> %s\n", net->user.username, text2); chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "<"); if (!in_private) { chat_print_text(page, M_PUBLIC, "text", "to: "); chat_print_nick(page, M_PUBLIC, nick, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_line(page, M_PUBLIC, "whisper", text2); } else { chat_print_nick(page, M_PUBLIC, net->user.username, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_line(page, M_PUBLIC, "text", text2); } chat_print_text(page, M_PUBLIC, "text", "\n"); } if (!pos) break; text = pos + 1; } while (*text); /* now touch timestamp for this user, so it does not receive * AFK messages for a while */ stamps = timestamp_touch_user(stamps, nick); } void send_notice(net_t* net, char* nick, char *text, int show) { char *text2; char *pos; chat_page_t* page; int in_private; if (!NET_CONNECTED(net)) return; page = chat_page_get_printable(); if ((global.current_page->type == P_PRIVATE) && !strcasecmp(global.current_page->name, nick)) in_private = 1; else in_private = 0; line_insert_lf(text); do { pos = strchr(text, '\n'); if (pos) *pos = 0; if (global.options.parse_colors) text2 = cparse(text); else text2 = text; command_send(net, CMD_NOTICE, nick, text2); if (show) { l_log(NULL, nick, LOG_PRIVATE, "<%s> %s\n", net->user.username, text2); if (!in_private) { chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "-"); chat_print_text(page, M_PUBLIC, "text", "to: "); chat_print_nick(page, M_PUBLIC, nick, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_text(page, M_PUBLIC, "whisper", text2); chat_print_text(page, M_PUBLIC, "text", "\n"); } else { chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "-"); chat_print_nick(page, M_PUBLIC, net->user.username, net); chat_print_text(page, M_PUBLIC, "user", "- "); chat_print_colored(page, M_PUBLIC, "text", text2); chat_print_text(page, M_PUBLIC, "text", "\n"); } } if (!pos) break; text = pos + 1; } while (*text); /* now touch timestamp for this user, so it does not receive * AFK messages for a while */ stamps = timestamp_touch_user(stamps, nick); } void send_public(chat_page_t* page, char *text) { char *text2; char *pos; if (!page) return; if (page->type != P_PUBLIC) return; if (!page->net) return; if (!page->active) return; line_insert_lf(text); do { pos = strchr(text, '\n'); if (pos) *pos = 0; if (global.options.parse_colors) text2 = cparse(text); else text2 = text; command_send(page->net, CMD_PUBLIC, page->name, text2); if (!pos) break; text = pos + 1; } while (*text); } void send_chwallop(chat_page_t* page, char *text) { char *text2; char *pos; if (!page) return; if (page->type != P_PUBLIC) return; if (!page->net) return; if (!page->active) return; line_insert_lf(text); do { pos = strchr(text, '\n'); if (pos) *pos = 0; if (global.options.parse_colors) text2 = cparse(text); else text2 = text; command_send(page->net, CMD_CHAN_WALLOP, page->name, text2); if (!pos) break; text = pos + 1; } while (*text); } channel_user_t* search_user_in_list(GtkCList * clist, char *user, int* row) { int i1; channel_user_t* cu; if (!user) return NULL; if (!list) return NULL; for (i1 = 0; i1 < clist->rows; i1++) { cu = gtk_clist_get_row_data(clist, i1); if (!cu) continue; if (!g_strcasecmp(user, cu->user)) { *row = i1; return cu; } } return NULL; } GList *user_search(char *user) { GtkCList *temp; char *text; char t[500]; int i1; GdkPixmap *pixmap = NULL; GdkBitmap *bitmap = NULL; guint8 space; int len = strlen(user); GList *result = NULL; if (!global.current_page || (global.current_page->type != P_PUBLIC)) return NULL; temp = GTK_CLIST(global.current_page->online); if (!temp) return NULL; for (i1 = 0; i1 < temp->rows; i1++) { gtk_clist_get_pixtext(temp, i1, 0, &text, &space, &pixmap, &bitmap); strcpy(t, text); if (strncasecmp(user, t, len) == 0) { result = g_list_append(result, g_strdup(t)); } } return result; } int user_search_full(chat_page_t* page, char *user) { GtkCList *temp; char *text; char t[500]; int i1; GdkPixmap *pixmap = NULL; GdkBitmap *bitmap = NULL; guint8 space; if (!page || (page->type != P_PUBLIC)) return 0; temp = GTK_CLIST(page->online); if (!temp) return 0; for (i1 = 0; i1 < temp->rows; i1++) { gtk_clist_get_pixtext(temp, i1, 0, &text, &space, &pixmap, &bitmap); strcpy(t, text); if (g_strcasecmp(user, t) == 0) return 1; } return 0; } char *search_highlight_string(const char *string, int *len) { char *pos; char *str; char *result = NULL; const char *temp_str; GList *dlist; *len = 0; temp_str = string; for (dlist = global.string_list[LIST_HIGHLIGHT]; dlist; dlist = dlist->next) { str = dlist->data; if ((pos = strcasestr((char*)temp_str, str)) != NULL) { if (!result || pos < result) { result = pos; *len = strlen(str); } } } pos = strchr(string, 0x03); if (pos) { if (!result || pos < result) { result = pos; *len = 3; } } return result; } // /alias c {/eval say $cparse("$*")} gint user_compare(GtkCList * clist, gconstpointer ptr1, gconstpointer ptr2) { channel_user_t* cu1; channel_user_t* cu2; GtkCListRow *row1 = (GtkCListRow *) ptr1; GtkCListRow *row2 = (GtkCListRow *) ptr2; cu1 = row1->data; if (!cu1) return 0; cu2 = row2->data; if (!cu2) return 0; if (clist->sort_column == 0) { return g_strcasecmp(cu1->user, cu2->user); } else if (clist->sort_column == 1) { if (cu1->files < cu2->files) return -1; if (cu1->files > cu2->files) return 1; else return 0; } else if (clist->sort_column == 2) { if (cu1->speed < cu2->speed) return -1; if (cu1->speed > cu2->speed) return 1; else return 0; } else { return 0; } } void highlight(chat_page_t * page, int high) { chat_page_t *page2; if (page->window) return; if (!page) return; // only highlight pages with a net, but highlight downloads if (!page->net && strcmp(page->name, "Downloads")) return; page2 = chat_page_get_current_main(); if ((page2 == page) && high) return; gtk_widget_set_style(page->tlabel, global.styles[STYLE_TAB1+high]); } void set_afk(char *message) { if (global.afk.message) { g_free(global.afk.message); global.afk.message = NULL; } if (message) { global.afk.message = g_strdup(message); global.afk.since = global.current_time; } if (global.afk.message) client_message("AFK", "%s", global.afk.message); else client_message("AFK", "deactivated"); } void chat_page_down(chat_page_t * page) { GtkAdjustment *vertical_adjustment; int value; if (!page || page->type == P_CHANNEL || !page->main) return; vertical_adjustment = GTK_ADJUSTMENT(GTK_TEXT(page->main)->vadj); value = vertical_adjustment->value + vertical_adjustment->page_size; if (value > vertical_adjustment->upper - vertical_adjustment->lower - vertical_adjustment->page_size) value = vertical_adjustment->upper - vertical_adjustment->lower - vertical_adjustment->page_size; gtk_adjustment_set_value(vertical_adjustment, value); } void chat_page_up(chat_page_t * page) { GtkAdjustment *vertical_adjustment; int value; if (!page || page->type == P_CHANNEL || !page->main) return; vertical_adjustment = GTK_ADJUSTMENT(GTK_TEXT(page->main)->vadj); value = vertical_adjustment->value - vertical_adjustment->page_size; if (value < 0) value = 0; gtk_adjustment_set_value(vertical_adjustment, value); } chat_page_t *chat_page_get_current_main() { GtkNotebook *notebook; GtkNotebookPage* page; chat_page_t *page1; // return global.current_page; notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook3")); page = notebook->cur_page; if (!page) return NULL; page1 = gtk_object_get_data(GTK_OBJECT(page->tab_label), "page"); return page1; } chat_page_t *chat_page_new(char* name, char *vname, int type, net_t* net) { chat_page_t *page; page = g_malloc(sizeof(*page)); page->name = g_strdup(name); page->vname = g_strdup(vname); page->window = NULL; page->type = type; page->header = NULL; page->wallop = NULL; page->main = NULL; page->tmain = NULL; page->tlabel = NULL; page->tclose = NULL; page->online = NULL; page->no = NULL; page->toplevel = NULL; page->timeout = -1; page->snap = 0; page->modified = 7; page->active = 1; page->lines = 0; page->close_on_part = 0; page->chmode = 0; page->limit = 0; page->level = 1; page->net = net; page->opped = 0; page->part_request = 0; page->join_request = 0; global.chat_pages = g_list_append(global.chat_pages, page); return page; } static void channel_entry_destroy(channel_entry_t* channel); static void channel_list_clear(chat_page_t* page); void chat_page_destroy(chat_page_t * page) { GtkWidget *channel_widget; GtkNotebook *notebook; int num; text_info_t* tinfo; global.chat_pages = g_list_remove(global.chat_pages, page); if (page->timeout >= 0) { gtk_timeout_remove(page->timeout); page->timeout = -1; } chat_page_clear(page, 0); chat_page_clear(page, 1); if (page->wallop) { tinfo = gtk_object_get_data(GTK_OBJECT(page->wallop), "text_info"); if (tinfo) g_free(tinfo); } if (page->main) { tinfo = gtk_object_get_data(GTK_OBJECT(page->main), "text_info"); if (tinfo) g_free(tinfo); if (page->type == P_CHANNEL) channel_list_clear(page); } channel_widget = page->toplevel; if (!channel_widget) return; notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook3")); num = gtk_notebook_page_num(notebook, channel_widget); gtk_notebook_remove_page(notebook, num); if (page->window) { gtk_object_set_data(GTK_OBJECT(page->window), "channel", NULL); gtk_widget_destroy(page->window); } if (global.current_page == page) { global.current_page = chat_page_get_current_main(); } if (page->type == P_PRIVATE) hotlist_remove(page->vname, 0); /* if (page->type == P_PUBLIC) opchannel_remove(page->name); */ if (page->name) g_free(page->name); if (page->vname) g_free(page->vname); g_free(page); } void chat_page_attach_to_main(chat_page_t * page) { GtkNotebook *notebook; GtkWidget *channel_widget; if (page->window == NULL) return; channel_widget = page->toplevel; if (!channel_widget) return; gtk_widget_ref(channel_widget); gtk_container_remove(GTK_CONTAINER(channel_widget->parent), channel_widget); notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook3")); gtk_notebook_append_page(notebook, channel_widget, page->tmain); gtk_widget_unref(channel_widget); gtk_notebook_set_page(GTK_NOTEBOOK(notebook), gtk_notebook_page_num(GTK_NOTEBOOK(notebook), channel_widget)); page->window = NULL; } void chat_page_attach_to_new(chat_page_t * page) { char str[2048]; GtkWidget *channel; GtkWidget *window; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *button1; GtkWidget *entry; if (page->window) return; channel = page->toplevel; if (!channel) return; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), channel->allocation.width, channel->allocation.height + 60); if (page->type == P_PRIVATE) sprintf(str, "Private: "); else if (page->type == P_PUBLIC) sprintf(str, "Channel: "); else *str = 0; strcat(str, page->vname); if (page->net) { strcat(str, " ["); strcat(str, page->net->name); strcat(str, " ]"); } if (!page->active) strcat(str, " [inactive]"); gtk_window_set_title(GTK_WINDOW(window), str); gtk_widget_show(window); gtk_object_set_data(GTK_OBJECT(window), "channel", page); gtk_widget_ref(channel); gtk_container_remove(GTK_CONTAINER(channel->parent), channel); vbox = gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_widget_show(vbox); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_box_pack_start(GTK_BOX(vbox), channel, TRUE, TRUE, 0); gtk_widget_unref(channel); hbox = gtk_hbox_new(FALSE, 2); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); entry = gtk_entry_new(); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); gtk_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(on_chat_entry_activate), NULL); gtk_signal_connect(GTK_OBJECT(entry), "key_press_event", GTK_SIGNAL_FUNC(on_chat_entry_key_press_event), NULL); button1 = gtk_button_new_with_label("Leave Room"); gtk_widget_show(button1); gtk_box_pack_start(GTK_BOX(hbox), button1, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(button1), "clicked", GTK_SIGNAL_FUNC(on_chat_leave_clicked), page); gtk_widget_set_sensitive(button1, TRUE); button1 = gtk_button_new_with_label("X"); gtk_widget_show(button1); gtk_box_pack_start(GTK_BOX(hbox), button1, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(button1), "clicked", GTK_SIGNAL_FUNC(on_chat_attach_clicked), page); gtk_signal_connect(GTK_OBJECT(window), "focus_in_event", GTK_SIGNAL_FUNC(on_window_focus_in_event), page); gtk_signal_connect(GTK_OBJECT(window), "focus_out_event", GTK_SIGNAL_FUNC(on_window_focus_out_event), page); page->window = window; gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(on_chat_destroy), window); } void chat_page_leave(chat_page_t * page, char* reason) { if (page->type == P_PUBLIC) { if (page->active && NET_CONNECTED(page->net)) { page->close_on_part = 1; command_send(page->net, CMD_PART, page->name, reason); } else chat_page_destroy(page); } else { chat_page_destroy(page); } } chat_page_t *chat_page_search2(char *name, int type) { GList *dlist; chat_page_t *page = NULL; for (dlist = global.chat_pages; dlist; dlist = dlist->next) { page = dlist->data; if (page->type != type) continue; if (type == P_PRIVATE) { if (!g_strcasecmp(page->vname, name)) break; } else { if (!g_strcasecmp(page->name, name)) break; } } if (dlist) return page; else return NULL; } // flags: 1 = active, 2 = inactive, 3 = any chat_page_t *chat_page_search(net_t* net, char *name, int type, int flags) { GList *dlist; chat_page_t *page = NULL; for (dlist = global.chat_pages; dlist; dlist = dlist->next) { page = dlist->data; // printf("%s %d %p\n", page->name, page->type, page->server); // check name and type if (type == P_PRIVATE) { if (g_strcasecmp(page->vname, name)) continue; } else { if (g_strcasecmp(page->name, name)) continue; } if ((type != -1) && (page->type != type)) continue; // check flags if (page->active && ((flags&1) == 0)) continue; if (!page->active && ((flags&2) == 0)) continue; if (page->net == net) break; } if (dlist) return page; else return NULL; } void chat_page_clear(chat_page_t * page, int where) { text_info_t* tinfo; GtkWidget* widget; int i1; word_info_t* winfo; if (page->type == P_CHANNEL) return; switch (where) { case 0: widget = page->wallop; break; case 1: widget = page->main; break; default: widget = NULL; break; } if (!widget) return; gtk_text_set_point(GTK_TEXT(widget), 0); gtk_text_forward_delete(GTK_TEXT(widget), gtk_text_get_length(GTK_TEXT(widget))); tinfo = gtk_object_get_data(GTK_OBJECT(widget), "text_info"); if (!tinfo) return; for (i1 = 0; i1 < tinfo->pos; i1++) { winfo = tinfo->info[i1]; text_delete_token(winfo); } if (tinfo->info) g_free(tinfo->info); tinfo->pos = tinfo->alloc = 0; tinfo->info = NULL; } void chat_page_set_active(chat_page_t * page, int active) { char str[1024]; if (!page) return; if (page->active == active) return; page->active = active; // redraw label if (!page->tlabel) return; if (active) gtk_widget_set_sensitive(page->tlabel, TRUE); else gtk_widget_set_sensitive(page->tlabel, FALSE); highlight(page, 0); if (page->active) { if (page->type == P_PRIVATE) sprintf(str, "Private: %s", page->vname); else if (page->type == P_PUBLIC) { sprintf(str, "Channel: %s", page->name); } else strcpy(str, page->name); } else { if (page->type == P_PRIVATE) sprintf(str, "Private: %s [inactive]", page->vname); else if (page->type == P_PUBLIC) sprintf(str, "Channel: %s [inactive]", page->name); else strcpy(str, page->name); } if (page->window) gtk_window_set_title(GTK_WINDOW(page->window), str); } user_timestamp_t *timestamp_new(char *user) { user_timestamp_t *result; result = g_malloc(sizeof(*result)); result->user = g_strdup(user); timestamp_touch(result); return result; } user_timestamp_t *timestamp_search(GList * stamps, char *user) { GList *dlist; user_timestamp_t *result; for (dlist = stamps; dlist; dlist = dlist->next) { result = (user_timestamp_t *) (dlist->data); if (!g_strcasecmp(result->user, user)) return result; } return NULL; } void timestamp_touch(user_timestamp_t * stamp) { gettimeofday(&(stamp->tv), 0); } int timestamp_difference(user_timestamp_t * stamp) { struct timeval tv; int result; gettimeofday(&(tv), 0); result = (tv.tv_sec - stamp->tv.tv_sec) * 1000 + (tv.tv_usec - stamp->tv.tv_usec) / 1000; return (result); } GList* timestamp_touch_user(GList* user_list, char* user) { user_timestamp_t* stamp; stamp = timestamp_search(user_list, user); if (!stamp) { stamp = timestamp_new(user); user_list = g_list_append(user_list, stamp); } else timestamp_touch(stamp); return user_list; } chat_page_t *create_other_page(net_t* net, char *name, char *title) { GtkWidget *scrolledwindow27; GtkWidget *text4; GtkWidget *tab_label; GtkWidget *label; GtkWidget *button; GtkWidget *pix1; GtkWidget *vbox; GtkNotebook *notebook; chat_page_t *page; char* text; vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook3")); scrolledwindow27 = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow27); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow27), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow27, TRUE, TRUE, 0); text4 = gtk_text_new(NULL, NULL); gtk_signal_connect_after(GTK_OBJECT(text4), "button_press_event", GTK_SIGNAL_FUNC(on_text_button_press_event), NULL); gtk_widget_set_style(text4, global.scheme->style); gtk_widget_show(text4); gtk_text_set_word_wrap(GTK_TEXT(text4), 1); gtk_container_add(GTK_CONTAINER(scrolledwindow27), text4); tab_label = gtk_hbox_new (FALSE, 2); gtk_widget_ref (tab_label); gtk_widget_show (tab_label); text = g_strdup_printf("%s\n%s", net?net->name:"", title); label = gtk_label_new(text); g_free(text); gtk_widget_show(label); gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0); button = gtk_button_new(); gtk_widget_show(button); gtk_box_pack_start (GTK_BOX (tab_label), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); gtk_widget_set_sensitive(button, FALSE); pix1 = create_pixmap (global.win, "close.xpm"); gtk_widget_show (pix1); gtk_container_add (GTK_CONTAINER (button), pix1); page = chat_page_new(name, title, P_OTHER, net); page->header = NULL; page->main = text4; page->wallop = NULL; page->tmain = tab_label; page->tlabel = label; page->tclose = button; page->toplevel = vbox; gtk_widget_hide(button); gtk_object_set_data(GTK_OBJECT(tab_label), "page", page); gtk_notebook_append_page(notebook, page->toplevel, page->tmain); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_chat_close_clicked), page); return page; } chat_page_t *create_network_page(net_t* net) { GtkWidget* paned; GtkWidget *scrolledwindow1; GtkWidget *scrolledwindow2; GtkWidget *text1; GtkWidget *text2; GtkWidget *tab_label; GtkWidget *label; GtkWidget *button; GtkWidget *pix1; GtkNotebook *notebook; chat_page_t *page; char* text; notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook3")); if (global.options.server_motd) paned = gtk_hpaned_new(); else paned = gtk_vpaned_new(); gtk_widget_show(paned); gtk_paned_set_gutter_size(GTK_PANED(paned), 10); gtk_paned_set_position(GTK_PANED(paned), global.server_paned); // the MOTD page scrolledwindow1 = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow1); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); if (global.options.server_motd) gtk_paned_pack2(GTK_PANED(paned), scrolledwindow1, TRUE, TRUE); else gtk_paned_pack1(GTK_PANED(paned), scrolledwindow1, TRUE, TRUE); text1 = gtk_text_new(NULL, NULL); gtk_signal_connect_after(GTK_OBJECT(text1), "button_press_event", GTK_SIGNAL_FUNC(on_text_button_press_event), NULL); gtk_widget_set_style(text1, global.scheme->style); gtk_widget_show(text1); gtk_text_set_word_wrap(GTK_TEXT(text1), TRUE); gtk_container_add(GTK_CONTAINER(scrolledwindow1), text1); // the SERVER page scrolledwindow2 = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow2); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow2), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); if (global.options.server_motd) gtk_paned_pack1(GTK_PANED(paned), scrolledwindow2, TRUE, TRUE); else gtk_paned_pack2(GTK_PANED(paned), scrolledwindow2, TRUE, TRUE); text2 = gtk_text_new(NULL, NULL); gtk_signal_connect_after(GTK_OBJECT(text2), "button_press_event", GTK_SIGNAL_FUNC(on_text_button_press_event), NULL); gtk_widget_set_style(text2, global.scheme->style); gtk_widget_show(text2); gtk_text_set_word_wrap(GTK_TEXT(text2), TRUE); gtk_container_add(GTK_CONTAINER(scrolledwindow2), text2); // the tab_label tab_label = gtk_hbox_new (FALSE, 2); gtk_widget_ref (tab_label); gtk_widget_show (tab_label); text = g_strdup_printf("%s\nServer/MOTD", net?net->name:""); label = gtk_label_new(text); g_free(text); gtk_widget_show(label); gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0); button = gtk_button_new(); gtk_widget_show(button); gtk_box_pack_start (GTK_BOX (tab_label), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); gtk_widget_set_sensitive(button, FALSE); pix1 = create_pixmap (global.win, "close.xpm"); gtk_widget_show (pix1); gtk_container_add (GTK_CONTAINER (button), pix1); page = chat_page_new("Server", "Server/MOTD", P_SERVER, net); page->header = NULL; page->main = text2; page->wallop = text1; page->tmain = tab_label; page->tlabel = label; page->tclose = button; page->toplevel = paned; page->paned = paned; gtk_widget_hide(button); gtk_object_set_data(GTK_OBJECT(tab_label), "page", page); gtk_notebook_append_page(notebook, page->toplevel, page->tmain); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_chat_close_clicked), page); return page; } void channel_set_mode(chat_page_t* page, char* who, int set, int clear, int send) { GtkToggleButton* button; int i1; if ((page->chmode & set) == set && (page->chmode & clear) == 0) return; set = (~page->chmode) & set; clear = page->chmode & clear; if (send && page->net) { command_send(page->net, CMD_SET_CHAN_MODE, page->name, set, clear); } else { page->chmode |= set; page->chmode &= ~clear; for (i1 = 0; i1 < CMODE_NUMBER; i1++) { button = GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(page->main), CModeNames[i1])); if (set & (1<name, page->net); chat_print_text(page, M_PUBLIC, "text", ") "); if (who) { if (strchr(who, '.')) chat_print_network(page, M_PUBLIC, page->net, 0, 1); else chat_print_nick(page, M_PUBLIC, who, page->net); chat_print_text(page, M_PUBLIC, "error", " changed channel mode: "); } else { chat_print_text(page, M_PUBLIC, "error", "Channel mode: "); } chat_print_text(page, M_PUBLIC, "text", int2chmode_lop(set, clear)); chat_print_text(page, M_PUBLIC, "text", "\n"); } } void channel_set_limit(chat_page_t* page, char* who, int limit, int send) { GtkEntry* entry; char str[128]; if (page->limit == limit) return; if (send && page->net) command_send(page->net, CMD_SET_CHAN_LIMIT, page->name, limit); else { page->limit = limit; sprintf(str, "%d", limit); entry = GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(page->main), "limit")); gtk_entry_set_text(entry, str); chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 0); chat_print_text(page, M_PUBLIC, "text", "("); chat_print_channel(page, M_PUBLIC, page->name, page->net); chat_print_text(page, M_PUBLIC, "text", ") "); if (who) { if (strchr(who, '.')) chat_print_network(page, M_PUBLIC, page->net, 0, 1); else chat_print_nick(page, M_PUBLIC, who, page->net); chat_print_text(page, M_PUBLIC, "error", " changed channel limit: "); } else { chat_print_text(page, M_PUBLIC, "error", "Channel limit: "); } chat_print_text(page, M_PUBLIC, "text", str); chat_print_text(page, M_PUBLIC, "text", "\n"); } } void channel_set_level(chat_page_t* page, char* who, int level, int send) { GtkEntry* entry; GtkWidget* combo; if (page->level == (unsigned)level) return; if (send && page->net) { command_send(page->net, CMD_SET_CHAN_LEVEL, page->name, LevelShort(level)); } else { page->level = level; combo = gtk_object_get_data(GTK_OBJECT(page->main), "level"); entry = GTK_ENTRY(GTK_COMBO(combo)->entry); gtk_entry_set_text(entry, LevelShort(level)); chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 0); chat_print_text(page, M_PUBLIC, "text", "("); chat_print_channel(page, M_PUBLIC, page->name, page->net); chat_print_text(page, M_PUBLIC, "text", ") "); if (who) { if (strchr(who, '.')) chat_print_network(page, M_PUBLIC, page->net, 0, 1); else chat_print_nick(page, M_PUBLIC, who, page->net); chat_print_text(page, M_PUBLIC, "error", " changed channel level: "); } else { chat_print_text(page, M_PUBLIC, "error", "Channel level: "); } chat_print_text(page, M_PUBLIC, "text", LevelShort(level)); chat_print_text(page, M_PUBLIC, "text", "\n"); } } static void channel_mode_activate(chat_page_t* page, int activate) { GtkWidget* button; int i1; GList* dlist; net_t* net; if (page) { net = page->net; if (!page->net) return; for (i1 = 0; i1 < CMODE_NUMBER; i1++) { button = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(page->main), CModeNames[i1])); if (activate && ((1<net->user.level < L_MOD)) continue; gtk_widget_set_sensitive(button, activate); } button = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(page->main), "limit")); gtk_widget_set_sensitive(button, activate); button = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(page->main), "level")); gtk_widget_set_sensitive(button, activate); } else { for (dlist = global.chat_pages; dlist; dlist = dlist->next) { page = dlist->data; if (page->type != P_PUBLIC) continue; if (!page->net) continue; for (i1 = 0; i1 < CMODE_NUMBER; i1++) { button = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(page->main), CModeNames[i1])); if (activate && ((1<net->user.level < L_MOD)) continue; gtk_widget_set_sensitive(button, activate); } button = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(page->main), "limit")); gtk_widget_set_sensitive(button, activate); button = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(page->main), "level")); gtk_widget_set_sensitive(button, activate); } } } int channel_refresh(gpointer data ATTR_UNUSED) { chat_page_t* page; GList* dlist; for (dlist = global.chat_pages; dlist; dlist = dlist->next) { page = dlist->data; if (page->type != P_PUBLIC) continue; if (!page->active) continue; command_send(page->net, CMD_NAMES_LIST, page->name); } return 1; } static void channel_list_show(chat_page_t* page); static void on_channel_show_clicked(GtkButton* button ATTR_UNUSED, gpointer user_data) { chat_page_t *page = user_data; if (!page) return; channel_list_show(page); } static void on_channel_refresh_clicked(GtkButton* button ATTR_UNUSED, gpointer user_data) { chat_page_t *page = user_data; if (!page) return; channel_list_get_real(page); } chat_page_t* create_channel_page(net_t* net) { GtkWidget *scrolledwindow; GtkWidget *button; GtkWidget *pix1; GtkWidget *label; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *tab_label; GtkNotebook *notebook; GtkWidget* channel_list; chat_page_t* page; // GtkWidget *entry; GtkObject *spinbutton_adj; GtkWidget *spinbutton; char* text; notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook3")); switch_to_page(1); page = chat_page_search(net, "Channels", P_CHANNEL, 3); if (page) { gtk_notebook_set_page(GTK_NOTEBOOK(notebook), gtk_notebook_page_num(GTK_NOTEBOOK(notebook), page->toplevel)); return page; } else { page = chat_page_new("Channels", "Channels", P_CHANNEL, net); } vbox = gtk_vbox_new(FALSE, 2); gtk_widget_show(vbox); hbox = gtk_hbox_new(FALSE, 5); gtk_widget_show(hbox); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); label = gtk_label_new ("Min Users"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); channel_list = gtk_clist_new (5); spinbutton_adj = gtk_adjustment_new (5, 0, 10000, 1, 100, 100); spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0); gtk_widget_show (spinbutton); gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); gtk_object_set_data(GTK_OBJECT(channel_list), "min", spinbutton); label = gtk_label_new ("Max Users"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); spinbutton_adj = gtk_adjustment_new (0, 0, 10000, 1, 100, 100); spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0); gtk_widget_show (spinbutton); gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); gtk_object_set_data(GTK_OBJECT(channel_list), "max", spinbutton); /* label = gtk_label_new ("Filter"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); entry = gtk_entry_new (); gtk_widget_show (entry); gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); gtk_entry_set_text(GTK_ENTRY(entry), ""); gtk_widget_set_sensitive(entry, FALSE); // */ button = gtk_button_new_with_label (" Apply "); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); gtk_object_set_data(GTK_OBJECT(channel_list), "apply", button); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_channel_show_clicked), page); label = gtk_label_new ("inactive"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); gtk_object_set_data(GTK_OBJECT(channel_list), "label", label); button = gtk_button_new_with_label (" Refresh List "); gtk_widget_show (button); gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); gtk_object_set_data(GTK_OBJECT(channel_list), "refresh", button); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_channel_refresh_clicked), page); scrolledwindow = gtk_scrolled_window_new (NULL, NULL); gtk_widget_ref (scrolledwindow); gtk_widget_show (scrolledwindow); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0); gtk_widget_show (channel_list); gtk_container_add (GTK_CONTAINER (scrolledwindow), channel_list); gtk_clist_set_column_width(GTK_CLIST(channel_list), 0, global.channel_width[0]); gtk_clist_set_column_visibility(GTK_CLIST(channel_list), 0, global.channel_show[0]); gtk_clist_set_column_width(GTK_CLIST(channel_list), 1, global.channel_width[1]); gtk_clist_set_column_visibility(GTK_CLIST(channel_list), 1, global.channel_show[1]); gtk_clist_set_column_width(GTK_CLIST(channel_list), 2, global.channel_width[2]); gtk_clist_set_column_visibility(GTK_CLIST(channel_list), 2, global.channel_show[2]); gtk_clist_set_column_width(GTK_CLIST(channel_list), 3, global.channel_width[3]); gtk_clist_set_column_visibility(GTK_CLIST(channel_list), 3, global.channel_show[3]); gtk_clist_set_column_width(GTK_CLIST(channel_list), 4, global.channel_width[4]); gtk_clist_set_column_visibility(GTK_CLIST(channel_list), 4, global.channel_show[4]); gtk_clist_set_selection_mode(GTK_CLIST(channel_list), GTK_SELECTION_EXTENDED); gtk_clist_column_titles_show(GTK_CLIST(channel_list)); label = gtk_label_new ("Channel"); gtk_widget_show (label); gtk_clist_set_column_widget (GTK_CLIST (channel_list), 0, label); label = gtk_label_new ("Online"); gtk_widget_show (label); gtk_clist_set_column_widget (GTK_CLIST (channel_list), 1, label); label = gtk_label_new ("Limit"); gtk_widget_show (label); gtk_clist_set_column_widget (GTK_CLIST (channel_list), 2, label); label = gtk_label_new ("Level"); gtk_widget_show (label); gtk_clist_set_column_widget (GTK_CLIST (channel_list), 3, label); label = gtk_label_new ("Topic"); gtk_widget_show (label); gtk_clist_set_column_widget (GTK_CLIST (channel_list), 4, label); gtk_signal_connect(GTK_OBJECT(channel_list), "click_column", GTK_SIGNAL_FUNC(on_list_click_column), NULL); gtk_signal_connect(GTK_OBJECT(channel_list), "button_press_event", GTK_SIGNAL_FUNC(on_channel_button_press_event), NULL); gtk_clist_set_sort_column(GTK_CLIST(channel_list), 1); gtk_clist_set_auto_sort(GTK_CLIST(channel_list), TRUE); gtk_clist_set_compare_func(GTK_CLIST(channel_list), channel_compare); tab_label = gtk_hbox_new (FALSE, 2); gtk_widget_ref (tab_label); gtk_widget_show (tab_label); text = g_strdup_printf("%s\n%s", net?net->name:"", "Channels"); label = gtk_label_new(text); g_free(text); gtk_widget_show(label); gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0); button = gtk_button_new(); gtk_widget_show(button); gtk_box_pack_start (GTK_BOX (tab_label), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); // gtk_widget_set_sensitive(button, FALSE); pix1 = create_pixmap (global.win, "close.xpm"); gtk_widget_show (pix1); gtk_container_add (GTK_CONTAINER (button), pix1); page->toplevel = vbox; page->header = NULL; page->main = channel_list; page->wallop = NULL; page->tmain = tab_label; page->tlabel = label; page->tclose = button; gtk_widget_hide(button); gtk_object_set_data(GTK_OBJECT(tab_label), "page", page); gtk_notebook_append_page(notebook, page->toplevel, page->tmain); gtk_notebook_set_page(GTK_NOTEBOOK(notebook), gtk_notebook_page_num(GTK_NOTEBOOK(notebook), page->toplevel)); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_chat_close_clicked), page); return page; } void on_join_channel_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { channel_entry_t* channel = user_data; join_channel(channel->net, channel->name); } static void on_part_channel_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { channel_entry_t* channel = user_data; chat_page_t* page; page = chat_page_search(channel->net, channel->name, P_PUBLIC, 1); if (page) chat_page_leave(page, NULL); } void on_auto_join_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { channel_entry_t* channel = user_data; char* text; if (channel && channel->net && channel->name) { text = is_string_in_list(channel->net->auto_join, channel->name); if (text) { channel->net->auto_join = g_list_remove(channel->net->auto_join, text); g_free(text); } else { channel->net->auto_join = g_list_append(channel->net->auto_join, g_strdup(channel->name)); } server_save(); } } void on_refresh_channels_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { chat_page_t* page = user_data; if (page) channel_list_get_real(page); } static int channel_online(channel_entry_t* channel) { if (!channel->net || !channel->name) return 0; if (chat_page_search(channel->net, channel->name, P_PUBLIC, 1)) return 1; else return 0; } static void on_open_url_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { char* url = user_data; browse_url(url); } GtkWidget* create_url_popup(char* url) { GtkWidget *popup; GtkWidget *item; GtkAccelGroup *popup_accels; if (!url) return NULL; popup = gtk_menu_new(); popup_accels = gtk_menu_ensure_uline_accel_group(GTK_MENU(popup)); item = gtk_menu_item_new_with_label(url); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Open URL"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_open_url_activate), url); return popup; } GtkWidget* create_channel_popup(channel_entry_t* channel, int ctab) { GtkWidget *popup; GtkWidget *item; GtkAccelGroup *popup_accels; popup = gtk_menu_new(); popup_accels = gtk_menu_ensure_uline_accel_group(GTK_MENU(popup)); if (channel) { if (channel_online(channel)) { item = gtk_menu_item_new_with_label("Part Channel"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_part_channel_activate), channel); } else { item = gtk_menu_item_new_with_label("Join Channel"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_join_channel_activate), channel); if (!NET_CONNECTED(channel->net)) gtk_widget_set_sensitive(item, FALSE); } if (is_string_in_list(channel->net->auto_join, channel->name)) item = gtk_menu_item_new_with_label("Remove from Autojoin"); else item = gtk_menu_item_new_with_label("Add to Autojoin"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_auto_join_activate), channel); if (!ctab) return popup; item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); } if (global.current_page && (global.current_page->type == P_CHANNEL)) { item = gtk_menu_item_new_with_label("Refresh List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_refresh_channels_activate), global.current_page); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); } item = gtk_menu_item_new_with_label("Customize List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_customize_list_activate), GINT_TO_POINTER(3)); return popup; } static channel_user_t* channel_user_new(char* name, int files, int speed, int flags, chat_page_t* page) { channel_user_t* cu; cu = g_malloc(sizeof(*cu)); cu->user = g_strdup(name); cu->files = files; cu->speed = speed; if (flags < 0) cu->flags = 0; else cu->flags = flags; cu->page = page; return cu; } static void channel_user_destroy(gpointer data) { channel_user_t* cu = data; if (!cu) return; g_free(cu->user); g_free(cu); } void chat_page_set_op(chat_page_t* page, int status) { if (!page || (page->type != P_PUBLIC)) return; if (!page->net) return; if (page->opped == status) return; page->opped = status; if (status) { channel_mode_activate(page, TRUE); } else { channel_mode_activate(page, FALSE); } } void text_insert_token(GtkWidget* widget, char* name, void* data, int type, guint pos) { text_info_t* tinfo; word_info_t* winfo; tinfo = gtk_object_get_data(GTK_OBJECT(widget), "text_info"); if (!tinfo) { tinfo = g_malloc(sizeof(*tinfo)); tinfo->alloc = 0; tinfo->pos = 0; tinfo->info = NULL; gtk_object_set_data(GTK_OBJECT(widget), "text_info", tinfo); } if (tinfo->pos >= tinfo->alloc) { tinfo->info = g_realloc(tinfo->info, sizeof(word_info_t*)*(tinfo->alloc+100)); tinfo->alloc += 100; } winfo = g_malloc(sizeof(*winfo)); winfo->word = g_strdup(name); winfo->data = data; winfo->type = type; winfo->start_pos = pos; winfo->length = strlen(name); tinfo->info[tinfo->pos] = winfo; tinfo->pos++; } word_info_t* text_get_info(GtkWidget* widget, gint pos) { text_info_t* tinfo; int i1, i2, i3; word_info_t* winfo; tinfo = gtk_object_get_data(GTK_OBJECT(widget), "text_info"); if (!tinfo) return NULL; if (tinfo->pos == 0) return NULL; i1 = 0; i2 = tinfo->pos-1; while (i1 < i2) { if (tinfo->info[i1]->start_pos > pos) i2 = i1; else if (tinfo->info[i2]->start_pos <= pos) i1 = i2; else { i3 = (i1+i2)/2; if (tinfo->info[i3]->start_pos > pos) i2 = i3; else if (i1 == i3) i2 = i3; else i1 = i3; } } winfo = tinfo->info[i1]; if ((pos >= winfo->start_pos) && (pos < winfo->start_pos+winfo->length)) return winfo; else return NULL; } GtkWidget* create_file_popup(word_info_t* winfo) { GtkWidget *popup; GtkWidget *item; int mime; if (!winfo) return NULL; popup = gtk_menu_new(); mime = mtype_get((char*)(winfo->data)); item = create_open_menu(mime, (char*)(winfo->data), 1); gtk_container_add(GTK_CONTAINER(popup), item); return popup; } void activate_auto_afk() { if (!global.afk.auto_afk) return; if (global.afk.message) return; if (global.current_time - global.afk.since > 10*60) { set_afk("Automatically activated away message"); } } void deactivate_auto_afk() { if (global.afk.message) { if (!global.afk.auto_afk) return; global.afk.since = global.current_time; set_afk(NULL); } else { global.afk.since = global.current_time; } } void update_channel_user(chat_page_t* page, channel_user_t* cu) { GtkWidget* temp = page->online; GdkPixmap *pixmap = NULL; GdkBitmap *bitmap = NULL; int row; sprintf(tstr[0], "%s", cu->user); sprintf(tstr[1], "%d", cu->files); strcpy(tstr[2], LineSpeed(cu->speed)); row = gtk_clist_find_row_from_data(GTK_CLIST(temp), cu); if (row < 0) return; detect_channel_pixs(cu, &pixmap, &bitmap); gtk_clist_set_pixtext(GTK_CLIST(temp), row, 0, tstr[0], 5, pixmap, bitmap); gtk_clist_set_text(GTK_CLIST(temp), row, 1, tstr[1]); detect_line_pixs(cu->speed, &pixmap, &bitmap); gtk_clist_set_pixtext(GTK_CLIST(temp), row, 2, tstr[2], 5, pixmap, bitmap); } GList* find_channels(net_t* net, char* user) { GList* result = NULL; GList *dlist; chat_page_t *page; GtkWidget *temp; int row; // mark users in online lists for (dlist = global.chat_pages; dlist; dlist = dlist->next) { page = dlist->data; if (page->type != P_PUBLIC) continue; temp = page->online; if (!temp) continue; if (net && page->net != net) continue; if (search_user_in_list(GTK_CLIST(temp), user, &row)) { result = g_list_append(result, page); break; } } return result; } void chat_print_prefix(chat_page_t* page, int which) { char* prefix = NULL; int old_val; if (!global.scheme) return; if (which == 0) prefix = cparse(global.scheme->server_prefix); else if (which == 1) prefix = cparse(global.scheme->client_prefix); else if (which == 2) prefix = cparse(global.scheme->join_prefix); else if (which == 3) prefix = cparse(global.scheme->part_prefix); old_val = global.options.strip_colors; global.options.strip_colors = 0; if (which == 0) chat_print_colored(page, M_PUBLIC, "error", prefix); else if (which == 1) chat_print_colored(page, M_PUBLIC, "message", prefix); else if (which == 2) chat_print_colored(page, M_PUBLIC, "join", prefix); else if (which == 3) chat_print_colored(page, M_PUBLIC, "part", prefix); global.options.strip_colors = old_val; } static void check_reply(net_t* net, chat_page_t* page, char* user, char* message) { static GtkWidget* temp = NULL; char* pos; int len; if (!temp) temp = lookup_widget(global.win, "notebook1"); if (!g_strcasecmp(user, net->user.username)) return; if (message) { pos = strcasestr(message, net->user.username); if (!pos) return; len = strlen(net->user.username); if (pos[len] != 0 && pos[len] != '.' && pos[len] != ',' && pos[len] != ':' && pos[len] != ' ' && pos[len] != ')') return; if (pos != message) { pos--; if (*pos != '(' && *pos != ' ') return; } } if (gtk_notebook_get_current_page(GTK_NOTEBOOK(temp)) != 1 || page != global.current_page) update_reply(user, net, 1); else update_reply(user, net, 0); if (message) ext_handle(EVENT_MESSAGE_REPLY, user, message); } void public_message(net_t* net, char* channel, char* user, char* message) { chat_page_t* page; int ignored = 0; char *dummy = ""; char* pos1; if (!message) message = dummy; global.appearance = timestamp_touch_user(global.appearance, user); l_log(net, channel, LOG_CHANNEL, "<%s> %s\n", user, message); if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); ignored = 1; } else { page = chat_page_search(net, channel, P_PUBLIC, 1); if (!page) return; check_reply(net, page, user, message); } do { pos1 = strchr(message, '\n'); if (pos1) *pos1 = 0; chat_print_time_stamp(page, M_PUBLIC); if (ignored) { chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "user", ":"); chat_print_channel(page, M_PUBLIC, channel, net); chat_print_text(page, M_PUBLIC, "user", "] "); } chat_print_text(page, M_PUBLIC, "user", "<"); chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_line(page, M_PUBLIC, "text", message); chat_print_text(page, M_PUBLIC, "text", "\n"); if (!pos1) break; message = pos1 + 1; } while (*message != 0); } void public_wallop(net_t* net, char* channel, char* user, char* message) { chat_page_t* page; int ignored = 0; char *dummy = ""; char* pos1; int type; if (!message) message = dummy; global.appearance = timestamp_touch_user(global.appearance, user); l_log(net, channel, LOG_CHANNEL, "<%s> [Wallop] %s\n", user, message); if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); ignored = 1; } else { page = chat_page_search(net, channel, P_PUBLIC, 1); if (!page) return; check_reply(net, page, user, message); } do { pos1 = strchr(message, '\n'); if (pos1) *pos1 = 0; if (ignored) { chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "user", ":"); chat_print_text(page, M_PUBLIC, "text", "chop"); chat_print_text(page, M_PUBLIC, "user", "] "); type = M_PUBLIC; } else if (global.options.piping & PIPE_CHWALLOP) { chat_print_time_stamp(page, M_OP); type = M_OP; } else { chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "message", "(Channel op) "); type = M_PUBLIC; } chat_print_text(page, type, "user", "<"); chat_print_nick(page, type, user, net); chat_print_text(page, type, "user", "> "); chat_print_line(page, type, "text", message); chat_print_text(page, type, "text", "\n"); if (!pos1) break; message = pos1 + 1; } while (*message != 0); } void operator_message(net_t* net, char* user, char* message) { chat_page_t* page; int info = 1; char *dummy = ""; char* pos1; if (!message) message = dummy; l_log(net, "Operator", LOG_OPERATOR, "<%s> %s\n", user, message); global.appearance = timestamp_touch_user(global.appearance, user); if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); } else if (global.options.piping & PIPE_WALLOP) { page = chat_page_search(net, "Wallop", P_OTHER, 3); if (!page) page = create_other_page(net, "Wallop", "Operator"); check_reply(net, page, user, message); info = 0; } else { page = chat_page_get_printable();; check_reply(net, page, user, message); } do { pos1 = strchr(message, '\n'); if (pos1) *pos1 = 0; chat_print_time_stamp(page, M_PUBLIC); if (info) { chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "user", ":"); chat_print_text(page, M_PUBLIC, "text", "wallop"); chat_print_text(page, M_PUBLIC, "user", "] "); } chat_print_text(page, M_PUBLIC, "user", "<"); chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_line(page, M_PUBLIC, "text", message); chat_print_text(page, M_PUBLIC, "text", "\n"); if (!pos1) break; message = pos1 + 1; } while (*message != 0); } void global_message(net_t* net, char* user, char* message) { chat_page_t* page; int info = 1; char *dummy = ""; char* pos1; if (!message) message = dummy; l_log(net, "Global", LOG_GLOBAL, "<%s> %s\n", user, message); global.appearance = timestamp_touch_user(global.appearance, user); if (net->flags & NETWORK_IGN_GLOBAL) return; if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); } else if (global.options.piping & PIPE_GLOBAL) { page = chat_page_search2("Global", P_OTHER); if (!page) page = create_other_page(NULL, "Global", "Global"); check_reply(net, page, user, message); info = 0; } else { page = chat_page_get_printable();; check_reply(net, page, user, message); } do { pos1 = strchr(message, '\n'); if (pos1) *pos1 = 0; chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); if (info) { chat_print_text(page, M_PUBLIC, "user", ":"); chat_print_text(page, M_PUBLIC, "text", "global"); } chat_print_text(page, M_PUBLIC, "user", "] "); chat_print_text(page, M_PUBLIC, "user", "<"); chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_line(page, M_PUBLIC, "text", message); chat_print_text(page, M_PUBLIC, "text", "\n"); if (!pos1) break; message = pos1 + 1; } while (*message != 0); } void public_notice(net_t* net, char* channel, char* user, char* message) { chat_page_t* page; int ignored = 0; char *dummy = ""; char* pos1; if (!message) message = dummy; global.appearance = timestamp_touch_user(global.appearance, user); l_log(net, channel, LOG_CHANNEL, "-%s- %s\n", user, message); if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); ignored = 1; } else { page = chat_page_search(net, channel, P_PUBLIC, 1); if (!page) return; } do { pos1 = strchr(message, '\n'); if (pos1) *pos1 = 0; chat_print_time_stamp(page, M_PUBLIC); if (ignored) { chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "user", ":"); chat_print_channel(page, M_PUBLIC, channel, net); chat_print_text(page, M_PUBLIC, "user", "] "); } chat_print_text(page, M_PUBLIC, "user", "-"); chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "- "); chat_print_line(page, M_PUBLIC, "text", message); chat_print_text(page, M_PUBLIC, "text", "\n"); if (!pos1) break; message = pos1 + 1; } while (*message != 0); } void subscription_send_info(net_t* net, char* user); void private_message(net_t* net, char* user, char* message) { char *dummy = ""; chat_page_t *page; int ignored = 0; char* pos1; int mode; if (!message) message = dummy; global.appearance = timestamp_touch_user(global.appearance, user); if (!strcmp(message, "//WantQueue")) return; l_log(NULL, user, LOG_PRIVATE, "<%s> %s\n", user, message); if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; ignored = 1; } else { if (!strncasecmp(message, "!Subscription", 13)) { subscription_send_info(net, user); return; } if (!strncasecmp(message, "!Status", 7)) { send_user_status(net, user); return; } /* we dont send any servers if (!strcmp(message, "!GetOnline")) { send_online_servers(net, user); return; } */ // but we allow to receive servers. if (!strcmp(message, "!OnlineServer")) { get_online_server(message); return; } } page = NULL; if (ignored) { page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); } else if ((page = chat_page_search2(user, P_PRIVATE))) { chat_page_update_network(page, net); } else if (global.afk.message && (global.options.piping & PIPE_AWAY_LOG)) { page = chat_page_search(NULL, "AwayLog", P_OTHER, 3); if (!page) page = create_other_page(NULL, "AwayLog", "Away Log"); } else if (global.options.piping & PIPE_PRIVATE) { page = create_private_page(net, user); } if (!page) { page = chat_page_get_printable(); mode = 0; } else { mode = 1; } if (!ignored) ext_handle(EVENT_IM, user, message); do { pos1 = strchr(message, '\n'); if (pos1) *pos1 = 0; chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "<"); if (mode == 1) { chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_line(page, M_PUBLIC, "text", message); } else { chat_print_text(page, M_PUBLIC, "text", "from: "); chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "> "); chat_print_line(page, M_PUBLIC, "whisper", message); } chat_print_text(page, M_PUBLIC, "text", "\n"); if (!pos1) break; message = pos1 + 1; } while (*message != 0); if (ignored) return; check_reply(net, page, user, NULL); if (global.afk.message) send_afk(net, user, &global.afk); } void private_notice(net_t* net, char* user, char* message) { char *dummy = ""; chat_page_t *page; int ignored = 0; char* pos1; int mode; if (!message) message = dummy; global.appearance = timestamp_touch_user(global.appearance, user); l_log(NULL, user, LOG_PRIVATE, "-%s- %s\n", user, message); if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; ignored = 1; } page = NULL; if (ignored) { page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); } else if ((page = chat_page_search2(user, P_PRIVATE))) { chat_page_update_network(page, net); } else if (global.afk.message && (global.options.piping & PIPE_AWAY_LOG)) { page = chat_page_search(NULL, "AwayLog", P_OTHER, 3); if (!page) page = create_other_page(NULL, "AwayLog", "Away Log"); } else if (global.options.piping & PIPE_PRIVATE) { page = chat_page_search(NULL, "Notice", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Notice", "Notices"); } if (!page) { page = chat_page_get_printable(); mode = 0; } else { mode = 1; } do { pos1 = strchr(message, '\n'); if (pos1) *pos1 = 0; chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "user", "-"); if (mode == 1) { chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "- "); chat_print_line(page, M_PUBLIC, "text", message); } else { chat_print_text(page, M_PUBLIC, "user", "-"); chat_print_text(page, M_PUBLIC, "text", "from: "); chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "- "); chat_print_line(page, M_PUBLIC, "whisper", message); } chat_print_text(page, M_PUBLIC, "text", "\n"); if (!pos1) break; message = pos1 + 1; } while (*message != 0); } void motd_message(net_t* net, char* message) { chat_page_t* page; int pserver; char* pos1; if (net->flags & NETWORK_MESSAGES) { page = chat_page_search(net, "Server", P_SERVER, 3); if (!page) page = create_network_page(net); pserver = 0; } else { page = chat_page_search(NULL, "Server", P_SERVER, 3); if (!page) page = create_network_page(NULL); pserver = 1; } if (!page) { printf("have no current page\n"); return; } do { pos1 = strchr(message, '\n'); if (pos1) *pos1 = 0; chat_print_time_stamp(page, M_OP); if (pserver) { chat_print_text(page, M_OP, "user", "["); chat_print_network(page, M_OP, net, 0, 1); chat_print_text(page, M_OP, "user", "] "); } chat_print_line(page, M_OP, "text", message); chat_print_text(page, M_OP, "text", "\n"); if (!pos1) break; message = pos1 + 1; } while (*message != 0); } void user_parted(net_t* net, chat_page_t* page, char* user, char* reason, int share, int link, int quit, char* who) { GtkWidget *temp; GtkWidget *temp2; char temp_str[1024]; char *pos; user_timestamp_t *stamp; int row; channel_user_t* cu; if (!page) return; pos = string_list_search(LIST_FRIEND, user); stamp = timestamp_search(global.appearance, user); if ((stamp && (timestamp_difference(stamp) < 1000 * global.options.recent_timeout) &&(global.options.show_parts == 1)) || // recent (global.options.show_parts == 2) || // show all pos || quit == 2) { // friend/kick chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 3); chat_print_text(page, M_PUBLIC, "user", "["); chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "user", "] "); if (quit == 1) chat_print_text(page, M_PUBLIC, "part", "has quit"); else if (quit == 0) chat_print_text(page, M_PUBLIC, "part", "has left"); else chat_print_text(page, M_PUBLIC, "part", "was kicked"); if (link >= 0) { sprintf(temp_str, " (%s)(%d)", LineSpeedShort[verify_speed(link)], share); chat_print_text(page, M_PUBLIC, "chat_background", temp_str); } if (reason || who) { chat_print_text(page, M_PUBLIC, "text", " ("); if (who) { chat_print_nick(page, M_PUBLIC, who, net); if (reason) chat_print_text(page, M_PUBLIC, "text", ": "); } if (reason) chat_print_text(page, M_PUBLIC, "text", reason); chat_print_text(page, M_PUBLIC, "text", ")"); } chat_print_text(page, M_PUBLIC, "chat_background", "\n"); } temp = page->online; cu = search_user_in_list(GTK_CLIST(temp), user, &row); if (cu) gtk_clist_remove(GTK_CLIST(temp), row); temp2 = page->no; sprintf(temp_str, "%d users online !", GTK_CLIST(temp)->rows); gtk_entry_set_text(GTK_ENTRY(temp2), temp_str); } void user_online(chat_page_t* page, char* user, int share, int link, int flags) { char *t2; GtkWidget *temp; GtkWidget *temp2; int row; channel_user_t* cu; temp = page->online; cu = search_user_in_list(GTK_CLIST(temp), user, &row); strcpy(tstr[0], user); sprintf(tstr[1], "%d", share); strcpy(tstr[2], LineSpeed(link)); if (!cu) { cu = channel_user_new(user, share, link, flags, page); row = gtk_clist_append(GTK_CLIST(temp), list); gtk_clist_set_row_data_full(GTK_CLIST(temp), row, cu, channel_user_destroy); if (global.options.colored_nicks2) { GdkColor* color = get_nick_color(user, global.options.colored_nicks2); gtk_clist_set_foreground(GTK_CLIST(temp), row, color); } gtk_clist_sort(GTK_CLIST(temp)); } else { cu->files = share; cu->speed = link; if (flags >= 0) cu->flags = flags; } update_channel_user(page, cu); temp2 = page->no; t2 = g_strdup_printf("%d users online !", GTK_CLIST(temp)->rows); gtk_entry_set_text(GTK_ENTRY(temp2), t2); g_free(t2); } void user_joined(chat_page_t* page, char* user, int share, int link) { char *friend; char* temp; friend = string_list_search(LIST_FRIEND, user); if ((global.options.show_joins == 1) || friend) { chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 2); chat_print_text(page, M_PUBLIC, "user", "["); chat_print_nick(page, M_PUBLIC, user, page->net); chat_print_text(page, M_PUBLIC, "user", "] "); chat_print_text(page, M_PUBLIC, "join", "has joined"); if (link >= 0) { temp = g_strdup_printf(" (%s)(%d)", LineSpeedShort[verify_speed(link)], share); chat_print_text(page, M_PUBLIC, "chat_background", temp); g_free(temp); } chat_print_text(page, M_PUBLIC, "chat_background", "\n"); } user_online(page, user, share, link, 0); } static void on_chmode_clicked(GtkToggleButton * togglebutton, gpointer user_data) { int set; chat_page_t* page; int mode = (int)user_data; if (gtk_toggle_button_get_active(togglebutton)) set = 1; else set = 0; page = gtk_object_get_data(GTK_OBJECT(togglebutton), "page"); if (!page) { printf("page not found\n"); return; } channel_set_mode(page, NULL, set?mode:0, set?0:mode, 1); } static void on_limit_activate(GtkEditable * editable, gpointer user_data) { char* str; chat_page_t* page = user_data; str = gtk_entry_get_text(GTK_ENTRY(editable)); channel_set_limit(page, NULL, atoi(str), 1); } static void on_level_changed(GtkEditable * editable, gpointer user_data) { char* str; chat_page_t* page = user_data; str = gtk_entry_get_text(GTK_ENTRY(editable)); channel_set_level(page, NULL, level2int(str), 1); } void channel_join_ack(chat_page_t* page) { if (!page->net) return; command_send(page->net, CMD_GET_CHAN_MODE, page->name); command_send(page->net, CMD_GET_CHAN_LIMIT, page->name); command_send(page->net, CMD_GET_CHAN_LEVEL, page->name); gtk_clist_clear(GTK_CLIST(page->online)); if (!page->active) chat_page_set_active(page, 1); if (page->net->user.level >= L_MOD) chat_page_set_op(page, TRUE); else chat_page_set_op(page, FALSE); l_log(page->net, page->name, LOG_CHANNEL, "[................] %s", ctime(&global.current_time)); } static chat_page_t* create_channel(net_t* net, char* channel) { GtkWidget *channel_widget; GtkWidget *channel_widget2; GtkWidget *scrolledwindow27; GtkWidget *text4; GtkWidget *topic; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *scrolledwindow26; GtkWidget *clist1; GtkWidget *label96; GtkWidget *label97; GtkWidget *label98; GtkWidget *tab_label; GtkWidget *entry18; GtkWidget *button; GtkNotebook *notebook; GtkTooltips *tips; GtkWidget *button2; GtkWidget *pix1; GtkWidget *vbox2; GtkWidget *hbox2; GtkWidget *hbox3; GtkWidget *hbox4; GtkWidget *label; GtkWidget *main_; GtkWidget *wallop; GtkWidget *hbox_temp; GtkWidget *combo; GtkWidget *combo_entry; GList *combo_items; GtkWidget *wid; char* text; chat_page_t *page; style_t *style; int i1; char mode[2] = "a"; tips = (GtkTooltips *) gtk_object_get_data(GTK_OBJECT(global.win), "tooltips"); page = chat_page_search(net, channel, P_PUBLIC, 3); if (page) return page; page = chat_page_new(channel, channel, P_PUBLIC, net); channel_widget = gtk_hpaned_new(); gtk_paned_set_gutter_size(GTK_PANED(channel_widget), 10); gtk_paned_set_position(GTK_PANED(channel_widget), global.channel_paned); gtk_widget_show(channel_widget); vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_paned_pack1(GTK_PANED(channel_widget), vbox, TRUE, TRUE); hbox = gtk_hbox_new(FALSE, 0); gtk_object_set_data(GTK_OBJECT(global.win), "hbox", hbox); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); topic = gtk_text_new(NULL, NULL); gtk_widget_set_style(topic, global.scheme->style); gtk_widget_show(topic); gtk_signal_connect_after(GTK_OBJECT(topic), "button_press_event", GTK_SIGNAL_FUNC(on_text_button_press_event), NULL); style = style_get(global.scheme, "text"); if (style && style->font) gtk_widget_set_usize(topic, -1, style->font->ascent + style->font->descent+1); else gtk_widget_set_usize(topic, -1, 22); gtk_text_set_word_wrap(GTK_TEXT(topic), 1); gtk_box_pack_start(GTK_BOX(hbox), topic, TRUE, TRUE, 0); // button2 = gtk_button_new(); gtk_widget_show(button2); gtk_box_pack_start(GTK_BOX(hbox), button2, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS(button2, GTK_CAN_FOCUS); gtk_button_set_relief(GTK_BUTTON(button2), GTK_RELIEF_NONE); vbox2 = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox2); gtk_container_add(GTK_CONTAINER(button2), vbox2); hbox2 = gtk_hbox_new(FALSE, 5); hbox_temp = hbox2; gtk_widget_show(hbox2); gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); label = gtk_label_new("hide users"); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); pix1 = create_pixmap(global.win, "arrowr.xpm"); gtk_widget_show(pix1); gtk_box_pack_start(GTK_BOX(hbox2), pix1, FALSE, FALSE, 0); hbox2 = gtk_hbox_new(FALSE, 5); gtk_widget_show (hbox2); gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); gtk_widget_hide(hbox2); pix1 = create_pixmap(global.win, "arrowl.xpm"); gtk_widget_show(pix1); gtk_box_pack_start(GTK_BOX(hbox2), pix1, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(button2), "clicked", GTK_SIGNAL_FUNC(on_button_users_clicked), NULL); label = gtk_label_new("show users"); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); channel_widget2 = gtk_vpaned_new(); gtk_widget_show(channel_widget2); gtk_paned_set_position(GTK_PANED(channel_widget2), 0); gtk_box_pack_start(GTK_BOX(vbox), channel_widget2, TRUE, TRUE, 0); scrolledwindow27 = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow27); gtk_paned_pack1(GTK_PANED(channel_widget2), scrolledwindow27, TRUE, TRUE); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow27), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_range_set_update_policy(GTK_RANGE (GTK_SCROLLED_WINDOW(scrolledwindow27)-> hscrollbar), GTK_UPDATE_CONTINUOUS); gtk_range_set_update_policy(GTK_RANGE (GTK_SCROLLED_WINDOW(scrolledwindow27)-> vscrollbar), GTK_UPDATE_CONTINUOUS); text4 = gtk_text_new(NULL, NULL); wallop = text4; gtk_widget_set_style(text4, global.scheme->style); gtk_signal_connect_after(GTK_OBJECT(text4), "button_press_event", GTK_SIGNAL_FUNC(on_text_button_press_event), NULL); gtk_widget_show(text4); gtk_text_set_word_wrap(GTK_TEXT(text4), 1); gtk_container_add(GTK_CONTAINER(scrolledwindow27), text4); scrolledwindow27 = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow27); gtk_paned_pack2(GTK_PANED(channel_widget2), scrolledwindow27, TRUE, TRUE); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow27), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_range_set_update_policy(GTK_RANGE (GTK_SCROLLED_WINDOW(scrolledwindow27)-> hscrollbar), GTK_UPDATE_CONTINUOUS); gtk_range_set_update_policy(GTK_RANGE (GTK_SCROLLED_WINDOW(scrolledwindow27)-> vscrollbar), GTK_UPDATE_CONTINUOUS); text4 = gtk_text_new(NULL, NULL); main_ = text4; gtk_widget_set_style(text4, global.scheme->style); gtk_signal_connect_after(GTK_OBJECT(text4), "button_press_event", GTK_SIGNAL_FUNC(on_text_button_press_event), NULL); gtk_widget_show(text4); gtk_text_set_word_wrap(GTK_TEXT(text4), 1); gtk_container_add(GTK_CONTAINER(scrolledwindow27), text4); /// vbox = gtk_vbox_new(FALSE, 0); wid = vbox; gtk_widget_show(vbox); gtk_paned_pack2(GTK_PANED(channel_widget), vbox, TRUE, TRUE); hbox3 = gtk_hbox_new(FALSE, 0); gtk_widget_show (hbox3); gtk_box_pack_start(GTK_BOX(vbox), hbox3, FALSE, FALSE, 0); hbox4 = gtk_hbox_new(TRUE, 0); gtk_widget_show (hbox4); gtk_box_pack_start(GTK_BOX(hbox3), hbox4, FALSE, FALSE, 0); for (i1 = 0; i1 < CMODE_NUMBER; i1++) { mode[0] = toupper(CModeNames[i1][1]); button = gtk_toggle_button_new_with_label(mode); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox4), button, TRUE, TRUE, 0); gtk_object_set_data(GTK_OBJECT(main_), CModeNames[i1], button); gtk_signal_connect_after(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(on_chmode_clicked), (gpointer)(1<user.level < L_MOD) gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); gtk_tooltips_set_tip (tips, button, mode_tip(i1), NULL); } hbox4 = gtk_hbox_new(FALSE, 0); gtk_widget_show (hbox4); gtk_box_pack_start(GTK_BOX(hbox3), hbox4, TRUE, TRUE, 0); entry18 = gtk_entry_new(); gtk_tooltips_set_tip (tips, entry18, "Channel user limit", NULL); gtk_widget_show (entry18); gtk_box_pack_start(GTK_BOX(hbox4), entry18, TRUE, TRUE, 0); gtk_widget_set_usize (entry18, 1, -2); if (net->user.level < L_MOD) gtk_widget_set_sensitive(GTK_WIDGET(entry18), FALSE); gtk_object_set_data(GTK_OBJECT(main_), "limit", entry18); gtk_signal_connect (GTK_OBJECT (entry18), "activate", GTK_SIGNAL_FUNC (on_limit_activate), (gpointer)page); ////////// combo = gtk_combo_new (); gtk_box_pack_start(GTK_BOX(hbox4), combo, TRUE, TRUE, 0); gtk_widget_set_usize (combo, 1, -2); gtk_widget_show (combo); combo_items = NULL; combo_items = g_list_append (combo_items, LevelShort(0)); combo_items = g_list_append (combo_items, LevelShort(1)); combo_items = g_list_append (combo_items, LevelShort(2)); combo_items = g_list_append (combo_items, LevelShort(3)); combo_items = g_list_append (combo_items, LevelShort(4)); gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_items); g_list_free (combo_items); if (net->user.level < L_MOD) gtk_widget_set_sensitive(GTK_WIDGET(combo), FALSE); gtk_object_set_data(GTK_OBJECT(main_), "level", combo); combo_entry = GTK_COMBO (combo)->entry; gtk_widget_show (combo_entry); gtk_tooltips_set_tip (tips, combo_entry, "Channel level", NULL); gtk_entry_set_editable (GTK_ENTRY (combo_entry), FALSE); gtk_entry_set_text(GTK_ENTRY(combo_entry), LevelShort(page->level)); gtk_signal_connect (GTK_OBJECT (combo_entry), "changed", GTK_SIGNAL_FUNC (on_level_changed), (gpointer)page); scrolledwindow26 = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow26); gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow26, TRUE, TRUE, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow26), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); clist1 = gtk_clist_new(3); gtk_widget_show(clist1); gtk_container_add(GTK_CONTAINER(scrolledwindow26), clist1); gtk_clist_set_column_width(GTK_CLIST(clist1), 0, global.online_width[0]); gtk_clist_set_column_width(GTK_CLIST(clist1), 1, global.online_width[1]); gtk_clist_set_column_width(GTK_CLIST(clist1), 2, global.online_width[2]); gtk_clist_set_column_visibility(GTK_CLIST(clist1), 0, global.online_show[0]); gtk_clist_set_column_visibility(GTK_CLIST(clist1), 1, global.online_show[1]); gtk_clist_set_column_visibility(GTK_CLIST(clist1), 2, global.online_show[2]); gtk_clist_column_titles_show(GTK_CLIST(clist1)); label96 = gtk_label_new("User"); gtk_widget_show(label96); gtk_clist_set_column_widget(GTK_CLIST(clist1), 0, label96); label97 = gtk_label_new("Share"); gtk_widget_show(label97); gtk_clist_set_column_widget(GTK_CLIST(clist1), 1, label97); label98 = gtk_label_new("Speed"); gtk_widget_show(label98); gtk_clist_set_column_widget(GTK_CLIST(clist1), 2, label98); hbox = gtk_hbox_new(FALSE, 0); gtk_object_set_data(GTK_OBJECT(global.win), "hbox", hbox); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); entry18 = gtk_entry_new(); gtk_widget_show(entry18); gtk_box_pack_start(GTK_BOX(hbox), entry18, TRUE, TRUE, 0); gtk_widget_set_usize (combo, 1, -2); button = gtk_button_new_with_label("Save"); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(on_online_save_clicked), NULL); gtk_tooltips_set_tip(tips, button, "Save Chat Page Layout", NULL); tab_label = gtk_hbox_new (FALSE, 2); gtk_widget_ref (tab_label); gtk_widget_show (tab_label); text = g_strdup_printf("%s\n%s", net?net->name:"", channel); label = gtk_label_new(text); g_free(text); gtk_widget_show(label); gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0); button = gtk_button_new(); gtk_widget_show(button); gtk_box_pack_start (GTK_BOX (tab_label), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); gtk_widget_set_sensitive(button, FALSE); pix1 = create_pixmap (global.win, "close.xpm"); gtk_widget_show (pix1); gtk_container_add (GTK_CONTAINER (button), pix1); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_chat_close_clicked), page); gtk_signal_connect(GTK_OBJECT(clist1), "button_press_event", GTK_SIGNAL_FUNC(on_online_button_press_event), NULL); gtk_signal_connect(GTK_OBJECT(clist1), "click_column", GTK_SIGNAL_FUNC(on_list_click_column), NULL); gtk_clist_set_sort_column(GTK_CLIST(clist1), 0); gtk_clist_set_auto_sort(GTK_CLIST(clist1), TRUE); gtk_clist_set_compare_func(GTK_CLIST(clist1), user_compare); notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook3")); page->header = topic; page->main = main_; page->wallop = wallop; page->tlabel = label; page->tmain = tab_label; page->tclose = button; gtk_widget_hide(button); page->online = clist1; page->no = entry18; page->toplevel = channel_widget; page->paned = channel_widget2; gtk_object_set_data(GTK_OBJECT(tab_label), "page", page); gtk_notebook_append_page(notebook, page->toplevel, page->tmain); gtk_notebook_set_page(GTK_NOTEBOOK(notebook), gtk_notebook_page_num(GTK_NOTEBOOK(notebook), channel_widget)); set_up_button2(button2, hbox2, hbox_temp, wid); gtk_signal_connect(GTK_OBJECT(button2), "clicked", GTK_SIGNAL_FUNC(on_hide_show_clicked), NULL); chat_page_set_active(page, 0); net->channel_setup(page); return page; } void join_channel(net_t* net, char *name) { GList* dlist; chat_page_t* page; if (net) { if (net->active_server) { page = create_channel(net, name); // we assume here that the command_send(net, CMD_JOIN, name); chat_page_set_active(page, 0); } } else { for (dlist = global.net_active; dlist; dlist = dlist->next) { net = dlist->data; join_channel(net, name); } } } void destroy_channel(chat_page_t* page) { if (page->close_on_part) chat_page_destroy(page); else { chat_page_set_active(page, 0); // we didnt request the part! if (global.options.rejoin_when_kicked) join_channel(page->net, page->name); } } void channel_set_topic(chat_page_t* page, char* who, char* topic, int action) { GtkWidget *temp; GtkText* text; char* topic2; if (!page || !page->header) return; if (action == 1) { if (page->net) command_send(page->net, CMD_SET_TOPIC, page->name, topic); } else { if (action == 2) { temp = page->header; text = GTK_TEXT(page->header); if (text->text_end - text->gap_size > 0) chat_print_text(page, M_TOPIC, "text", "\n"); chat_print_text(page, M_TOPIC, "text", ":"); if (topic) { topic2 = g_strdup(topic); chat_print_line(page, M_TOPIC, "text", topic2); g_free(topic2); } snap_to_bottom(page->header); } if (!who) return; chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 0); chat_print_text(page, M_PUBLIC, "text", "("); chat_print_channel(page, M_PUBLIC, page->name, page->net); chat_print_text(page, M_PUBLIC, "text", ") "); chat_print_nick(page, M_PUBLIC, who, page->net); if (topic) { chat_print_text(page, M_PUBLIC, "error", " changed channel topic: "); chat_print_line(page, M_PUBLIC, "text", topic); chat_print_text(page, M_PUBLIC, "text", "\n"); } else { chat_print_text(page, M_PUBLIC, "error", " cleared channel topic\n"); } } } void user_flagged(chat_page_t* page, char* who, char* user, int set, int flag, char* reason) { channel_user_t* cu; int row; char* nick; char* pos; if (!flag || !who || !page || !user) return; if (!page->net) return; if (!strcmp(user, "you")) nick = page->net->user.username; else nick = user; pos = strchr(nick, '!'); if (pos) *pos = 0; cu = search_user_in_list(GTK_CLIST(page->online), nick, &row); if (cu) { if (set && (cu->flags & flag)) return; if (!set && !(cu->flags & flag)) return; if (set) cu->flags |= flag; else cu->flags &= ~flag; update_channel_user(page, cu); } chat_print_time_stamp(page, M_PUBLIC); chat_print_prefix(page, 0); chat_print_text(page, M_PUBLIC, "text", "("); chat_print_channel(page, M_PUBLIC, page->name, page->net); chat_print_text(page, M_PUBLIC, "text", ") "); chat_print_nick(page, M_PUBLIC, nick, page->net); if (flag == CU_OP && set) chat_print_text(page, M_PUBLIC, "error", " was opped "); else if (flag == CU_OP && !set) chat_print_text(page, M_PUBLIC, "error", " was deopped "); else if (flag == CU_VOICE && set) chat_print_text(page, M_PUBLIC, "error", " was voiced "); else if (flag == CU_VOICE && !set) chat_print_text(page, M_PUBLIC, "error", " was devoiced "); else if (flag == CU_MUZZLED && set) chat_print_text(page, M_PUBLIC, "error", " was muzzled "); else if (flag == CU_MUZZLED && !set) chat_print_text(page, M_PUBLIC, "error", " was unmuzzled "); else if (flag == CU_BANNED && set) chat_print_text(page, M_PUBLIC, "error", " was banned "); else if (flag == CU_BANNED && !set) chat_print_text(page, M_PUBLIC, "error", " was unbanned "); else if (flag == CU_CREATOR && set) chat_print_text(page, M_PUBLIC, "error", " creator status added "); else if (flag == CU_CREATOR && !set) chat_print_text(page, M_PUBLIC, "error", " creator status removed "); chat_print_text(page, M_PUBLIC, "text", "("); if (strchr(who, '.')) chat_print_network(page, M_PUBLIC, page->net, 0, 0); else chat_print_nick(page, M_PUBLIC, who, page->net); if (reason) { chat_print_text(page, M_PUBLIC, "text", ": "); chat_print_text(page, M_PUBLIC, "text", reason); } chat_print_text(page, M_PUBLIC, "text", ")\n"); if (!strcasecmp(page->net->user.username, nick) && flag == CU_OP) { if (set) chat_page_set_op(page, TRUE); else if (page->net->user.level < L_MOD) chat_page_set_op(page, FALSE); } } void public_emote(net_t* net, char* channel, char* user, char* message) { char *dummy = ""; chat_page_t *page; char* style; int ignored = 0; if (!message) message = dummy; global.appearance = timestamp_touch_user(global.appearance, user); l_log(net, channel, LOG_CHANNEL, "<%s %s>\n", user, message); if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); ignored = 1; } else { page = chat_page_search(net, channel, P_PUBLIC, 1); if (!page) return; check_reply(net, page, user, message); } chat_print_time_stamp(page, M_PUBLIC); if (ignored) { chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "user", ":"); chat_print_channel(page, M_PUBLIC, channel, net); chat_print_text(page, M_PUBLIC, "user", "] "); } chat_print_text(page, M_PUBLIC, "user", "<"); style = chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, style, " "); chat_print_colored(page, M_PUBLIC, style, message); chat_print_text(page, M_PUBLIC, "user", ">\n"); } void private_emote(net_t* net, char* user, char* message) { char *dummy = ""; chat_page_t *page; int ignored = 0; int mode; char* style; if (!message) message = dummy; global.appearance = timestamp_touch_user(global.appearance, user); l_log(NULL, user, LOG_PRIVATE, "<%s %s>\n", user, message); if (string_list_search(LIST_IGNORE, user)) { if (global.options.no_piping & NOPIPE_IGNORE) return; ignored = 1; } page = NULL; if (ignored) { page = chat_page_search(NULL, "Ignored", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Ignored", "Ignored users"); } else if ((page = chat_page_search2(user, P_PRIVATE))) { chat_page_update_network(page, net); } else if (global.afk.message && (global.options.piping & PIPE_AWAY_LOG)) { page = chat_page_search(NULL, "AwayLog", P_OTHER, 3); if (!page) page = create_other_page(NULL, "AwayLog", "Away Log"); } else if (global.options.piping & PIPE_PRIVATE) { page = create_private_page(net, user); } if (!page) { page = chat_page_get_printable(); mode = 0; } else { mode = 1; } ext_handle(EVENT_IM, user, message); chat_print_time_stamp(page, M_PUBLIC); if (mode == 1) { chat_print_text(page, M_PUBLIC, "user", "<"); style = chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, style, " "); chat_print_colored(page, M_PUBLIC, style, message); chat_print_text(page, M_PUBLIC, "user", ">\n"); } else { chat_print_text(page, M_PUBLIC, "user", "<"); chat_print_text(page, M_PUBLIC, "text", "from: "); chat_print_nick(page, M_PUBLIC, user, net); chat_print_text(page, M_PUBLIC, "text", " "); chat_print_colored(page, M_PUBLIC, "whisper", message); chat_print_text(page, M_PUBLIC, "user", ">\n"); } if (ignored) return; check_reply(net, page, user, NULL); if (global.afk.message) send_afk(net, user, &global.afk); } void channel_entry_new(net_t* net, char* name, char* online, char* topic, char* limit, char* level) { chat_page_t* page; channel_entry_t* channel; GList* dlist; page = chat_page_search(net, "Channels", P_CHANNEL, 3); if (!page) return; channel = g_malloc(sizeof(*channel)); channel->name = g_strdup(name); if (limit) channel->limit = atoi(limit); else channel->limit = -1; if (level) channel->level = atoi(level); else channel->level = -1; channel->online = atoi(online); if (topic) channel->topic = g_strdup(topic); else channel->topic = NULL; channel->net = net; dlist = gtk_object_get_data(GTK_OBJECT(page->main), "channel_list"); dlist = g_list_prepend(dlist, channel); gtk_object_set_data(GTK_OBJECT(page->main), "channel_list", dlist); } static void channel_entry_destroy(channel_entry_t* channel) { g_free(channel->name); if (channel->topic) g_free(channel->topic); g_free(channel); } static void channel_list_save(chat_page_t* page) { char filename[2048]; int min, max; FILE* file; GtkWidget* temp; GList* dlist; channel_entry_t* channel; if (!page || !page->net || !page->main) return; sprintf(filename, "%s%cchannels%c%s", global.options.config_dir, DIR_SEP, DIR_SEP, page->net->name); if ((file = fopen(filename, "w")) == NULL) { client_message("Error", "Could not save channel list [%s]", page->net->name); return; } temp = gtk_object_get_data(GTK_OBJECT(page->main), "min"); min = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(temp)); temp = gtk_object_get_data(GTK_OBJECT(page->main), "max"); max = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(temp)); qfprintf(file, "CHANNEL_LIST 1 %S %d %d %S\n", page->net->name, min, max, ""); dlist = gtk_object_get_data(GTK_OBJECT(page->main), "channel_list"); for ( ;dlist; dlist = dlist->next) { channel = dlist->data; qfprintf(file, "%S %d %d %d %S\n", channel->name, channel->limit, channel->level, channel->online, channel->topic?channel->topic:""); } fclose(file); } static void channel_list_show(chat_page_t* page) { GList* channel_list; GList* dlist; GtkWidget* temp; int row; channel_entry_t* channel; int min, max; int shown, hidden; char str[1024]; if (!page) return; gtk_clist_clear(GTK_CLIST(page->main)); channel_list = gtk_object_get_data(GTK_OBJECT(page->main), "channel_list"); if (!channel_list) { strcpy(tstr[0], "No entries found!"); tstr[1][0] = 0; tstr[2][0] = 0; tstr[3][0] = 0; tstr[4][0] = 0; row = gtk_clist_append(GTK_CLIST(page->main), list); return; } temp = gtk_object_get_data(GTK_OBJECT(page->main), "min"); min = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(temp)); temp = gtk_object_get_data(GTK_OBJECT(page->main), "max"); max = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(temp)); shown = hidden = 0; gtk_clist_freeze(GTK_CLIST(page->main)); for (dlist = channel_list; dlist; dlist = dlist->next) { channel = dlist->data; if (channel->online < min || (max && channel->online > max)) { hidden++; continue; } shown++; strcpy(tstr[0], channel->name); if (channel->online >= 0) sprintf(tstr[1], "%d", channel->online); else tstr[1][0] = 0; if (channel->limit >= 0) sprintf(tstr[2], "%d", channel->limit); else tstr[2][0] = 0; if (channel->level >= 0) sprintf(tstr[3], "%d", channel->level); else tstr[3][0] = 0; if (channel->topic) strcpy(tstr[4], channel->topic); else tstr[4][0] = 0; row = gtk_clist_prepend(GTK_CLIST(page->main), list); gtk_clist_set_row_data(GTK_CLIST(page->main), row, channel); } temp = gtk_object_get_data(GTK_OBJECT(page->main), "apply"); if (temp) gtk_widget_set_sensitive(temp, TRUE); temp = gtk_object_get_data(GTK_OBJECT(page->main), "refresh"); if (temp) gtk_widget_set_sensitive(temp, TRUE); gtk_clist_thaw(GTK_CLIST(page->main)); temp = gtk_object_get_data(GTK_OBJECT(page->main), "label"); sprintf(str, "%d shown - %d hidden", shown, hidden); gtk_label_set_text(GTK_LABEL(temp), str); } void channel_list_end(chat_page_t* page) { channel_list_show(page); channel_list_save(page); } static GList* channel_entry_load_1(chat_page_t* page, FILE* fd) { char* name; char* limit; char* level; char* online; char* topic; char temp[2048]; GList* dlist = NULL; channel_entry_t* channel; if (!page || !page->net) return NULL; while (mfgets(temp, sizeof(temp), fd)) { name = arg(temp, 2); limit = arg(NULL, 0); level = arg(NULL, 0); online = arg(NULL, 0); topic = arg(NULL, 2); if (!topic) return dlist; channel = g_malloc(sizeof(*channel)); channel->name = g_strdup(name); channel->limit = atoi(limit); channel->level = atoi(level); channel->online = atoi(online); channel->topic = g_strdup(topic); channel->net = page->net; dlist = g_list_prepend(dlist, channel); } return dlist; } static int channel_list_load(chat_page_t* page) { struct stat st; FILE *file; char temp[2048]; char* string; int list_version; GtkWidget* widget; GList* dlist; if (!page || !page->net || !page->main) return 0; channel_list_clear(page); sprintf(temp, "%s%cchannels%c%s", global.options.config_dir, DIR_SEP, DIR_SEP, page->net->name); if (stat(temp, &st) < 0) return 0; if ((file = fopen(temp, "r")) == NULL) return 0; // skip the first line. mfgets(temp, sizeof(temp), file); string = arg(temp, 0); string = arg(NULL, 0); if (!string) { fclose(file); return 0; } list_version = atoi(string); string = arg(NULL, 2); // net name string = arg(NULL, 0); // min users if (!string) { fclose(file); return 0; } widget = gtk_object_get_data(GTK_OBJECT(page->main), "min"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), atoi(string)); string = arg(NULL, 0); // max users if (!string) { fclose(file); return 0; } widget = gtk_object_get_data(GTK_OBJECT(page->main), "max"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), atoi(string)); // FILTER missing if (list_version == 1) { dlist = channel_entry_load_1(page, file); } else { dlist = NULL; } fclose(file); if (dlist) { gtk_object_set_data(GTK_OBJECT(page->main), "channel_list", dlist); channel_list_show(page); } return (dlist != 0); } static void channel_list_clear(chat_page_t* page) { GList* channel_list; GList* dlist; channel_entry_t* channel; if (page->type != P_CHANNEL) return; gtk_clist_clear(GTK_CLIST(page->main)); channel_list = gtk_object_get_data(GTK_OBJECT(page->main), "channel_list"); for (dlist = channel_list; dlist; dlist = dlist->next) { channel = dlist->data; channel_entry_destroy(channel); } if (channel_list) g_list_free(channel_list); gtk_object_set_data(GTK_OBJECT(page->main), "channel_list", NULL); } void channel_list_get_real(chat_page_t* page) { GtkWidget* temp; if (!page || !page->net) return; channel_list_clear(page); temp = gtk_object_get_data(GTK_OBJECT(page->main), "label"); gtk_label_set_text(GTK_LABEL(temp), "Refreshing List..."); temp = gtk_object_get_data(GTK_OBJECT(page->main), "apply"); if (temp) gtk_widget_set_sensitive(temp, FALSE); temp = gtk_object_get_data(GTK_OBJECT(page->main), "refresh"); if (temp) gtk_widget_set_sensitive(temp, FALSE); command_send(page->net, CMD_FULL_CHANNEL_LIST); } void channel_list_get(net_t* net) { chat_page_t* page; page = create_channel_page(net); if (!page) return; if (!channel_list_load(page)) channel_list_get_real(page); }