4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <sys/types.h>
35 #include "gtkimhtml.h"
36 #include <gdk/gdkkeysyms.h>
41 #include "pixmaps/bold.xpm"
42 #include "pixmaps/italic.xpm"
43 #include "pixmaps/underline.xpm"
44 #include "pixmaps/strike.xpm"
45 #include "pixmaps/small.xpm"
46 #include "pixmaps/normal.xpm"
47 #include "pixmaps/big.xpm"
48 #include "pixmaps/fontface.xpm"
49 #include "pixmaps/fgcolor.xpm"
50 #include "pixmaps/bgcolor.xpm"
51 #include "pixmaps/link.xpm"
52 #include "pixmaps/smile_icon.xpm"
53 #include "pixmaps/wood.xpm"
54 #include "pixmaps/save_small.xpm"
55 #include "pixmaps/speaker.xpm"
57 #include "pixmaps/luke03.xpm"
58 #include "pixmaps/oneeye.xpm"
59 #include "pixmaps/crazy4.xpm"
60 #include "pixmaps/mrt.xpm"
61 #include "pixmaps/download.xpm"
62 #include "pixmaps/farted.xpm"
64 static gchar
*ispell_cmd
[] = { "ispell", "-a", NULL
};
68 GdkPixmap
*dark_icon_pm
= NULL
;
69 GdkBitmap
*dark_icon_bm
= NULL
;
71 GtkWidget
*all_convos
= NULL
;
72 GtkWidget
*convo_notebook
= NULL
;
74 char fontface
[128] = { 0 };
75 char fontxfld
[256] = { 0 };
77 extern GdkColor bgcolor
;
78 extern GdkColor fgcolor
;
80 void check_everything(GtkWidget
*entry
);
81 gboolean
keypress_callback(GtkWidget
*entry
, GdkEventKey
* event
, struct conversation
*c
);
83 static void update_icon(struct conversation
*);
84 static void remove_icon(struct conversation
*);
86 static void update_checkbox(struct conversation
*);
87 static void remove_checkbox(struct conversation
*);
89 /*------------------------------------------------------------------------*/
91 /*------------------------------------------------------------------------*/
94 void gaim_setup_imhtml(GtkWidget
*imhtml
)
96 g_return_if_fail(imhtml
!= NULL
);
97 g_return_if_fail(GTK_IS_IMHTML(imhtml
));
98 if (!(convo_options
& OPT_CONVO_SHOW_SMILEY
))
99 gtk_imhtml_show_smileys(GTK_IMHTML(imhtml
), FALSE
);
100 gtk_signal_connect(GTK_OBJECT(imhtml
), "url_clicked", GTK_SIGNAL_FUNC(open_url
), NULL
);
101 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), "C:)", luke03_xpm
);
102 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), "C:-)", luke03_xpm
);
103 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), "O-)", oneeye_xpm
);
104 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), ">:)", crazy4_xpm
);
105 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), ">:-)", crazy4_xpm
);
106 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), ":-o)))", mrt_xpm
);
107 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), ":-O)))", mrt_xpm
);
108 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), "8-|)", download_xpm
);
109 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml
), ":-]", farted_xpm
);
112 void quiet_set(GtkWidget
*tb
, int state
)
115 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(tb
), state
);
120 void set_state_lock(int i
)
125 void toggle_sensitive(GtkWidget
*widget
, GtkWidget
*to_toggle
)
127 gboolean sensitivity
= GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(to_toggle
));
129 if (sensitivity
== TRUE
)
130 gtk_widget_set_sensitive(GTK_WIDGET(to_toggle
), FALSE
);
132 gtk_widget_set_sensitive(GTK_WIDGET(to_toggle
), TRUE
);
137 void set_convo_name(struct conversation
*c
, const char *nname
)
140 g_snprintf(c
->name
, sizeof(c
->name
), "%s", nname
);
145 struct conversation
*new_conversation(char *name
)
147 struct conversation
*c
;
149 c
= find_conversation(name
);
154 c
= (struct conversation
*)g_new0(struct conversation
, 1);
155 g_snprintf(c
->name
, sizeof(c
->name
), "%s", name
);
157 if ((logging_options
& OPT_LOG_ALL
) || find_log_info(c
->name
)) {
160 fd
= open_log_file(c
->name
);
162 if (!(logging_options
& OPT_LOG_STRIP_HTML
))
164 "<HR><BR><H3 Align=Center> ---- New Conversation @ %s ----</H3><BR>\n",
167 fprintf(fd
, " ---- New Conversation @ %s ----\n", full_date());
170 /* do we want to do something here? */ ;
174 c
->gc
= (struct gaim_connection
*)connections
->data
;
175 c
->history
= g_string_new("");
176 conversations
= g_list_append(conversations
, c
);
180 plugin_event(event_new_conversation
, name
, 0, 0, 0);
185 struct conversation
*find_conversation(char *name
)
187 char *cuser
= g_malloc(1024);
188 struct conversation
*c
;
189 GList
*cnv
= conversations
;
191 strcpy(cuser
, normalize(name
));
194 c
= (struct conversation
*)cnv
->data
;
195 if (!g_strcasecmp(cuser
, normalize(c
->name
))) {
205 /* ---------------------------------------------------
206 * Function to remove a log file entry
207 * ---------------------------------------------------
210 void rm_log(struct log_conversation
*a
)
212 struct conversation
*cnv
= find_conversation(a
->name
);
214 log_conversations
= g_list_remove(log_conversations
, a
);
218 if (cnv
&& !(im_options
& OPT_IM_ONE_WINDOW
))
219 set_convo_title(cnv
);
222 struct log_conversation
*find_log_info(char *name
)
224 char *pname
= g_malloc(1024);
225 GList
*lc
= log_conversations
;
226 struct log_conversation
*l
;
229 strcpy(pname
, normalize(name
));
232 l
= (struct log_conversation
*)lc
->data
;
233 if (!g_strcasecmp(pname
, normalize(l
->name
))) {
243 void delete_conversation(struct conversation
*c
)
245 conversations
= g_list_remove(conversations
, c
);
246 if (c
->fg_color_dialog
)
247 gtk_widget_destroy(c
->fg_color_dialog
);
248 if (c
->bg_color_dialog
)
249 gtk_widget_destroy(c
->bg_color_dialog
);
251 gtk_widget_destroy(c
->font_dialog
);
252 if (c
->smiley_dialog
)
253 gtk_widget_destroy(c
->smiley_dialog
);
255 gtk_widget_destroy(c
->link_dialog
);
257 gtk_widget_destroy(c
->log_dialog
);
260 gtk_widget_destroy(c
->save_icon
);
262 if (c
->typing_timeout
)
263 gtk_timeout_remove(c
->typing_timeout
);
264 g_string_free(c
->history
, TRUE
);
268 void update_log_convs()
270 GSList
*C
= connections
;
271 struct gaim_connection
*g
;
273 GList
*cnv
= conversations
;
274 struct conversation
*c
;
277 c
= (struct conversation
*)cnv
->data
;
280 gtk_widget_set_sensitive(c
->log_button
,
281 ((logging_options
& OPT_LOG_ALL
)) ? FALSE
: TRUE
);
287 g
= (struct gaim_connection
*)C
->data
;
288 bcs
= g
->buddy_chats
;
290 c
= (struct conversation
*)bcs
->data
;
293 gtk_widget_set_sensitive(c
->log_button
,
294 ((logging_options
& OPT_LOG_ALL
)) ? FALSE
:
303 void update_font_buttons()
305 GList
*cnv
= conversations
;
306 struct conversation
*c
;
309 c
= (struct conversation
*)cnv
->data
;
312 gtk_widget_set_sensitive(c
->bold
,
313 ((font_options
& OPT_FONT_BOLD
)) ? FALSE
: TRUE
);
316 gtk_widget_set_sensitive(c
->italic
,
317 ((font_options
& OPT_FONT_ITALIC
)) ? FALSE
: TRUE
);
320 gtk_widget_set_sensitive(c
->underline
,
321 ((font_options
& OPT_FONT_UNDERLINE
)) ? FALSE
: TRUE
);
324 gtk_widget_set_sensitive(c
->strike
,
325 ((font_options
& OPT_FONT_STRIKE
)) ? FALSE
: TRUE
);
332 void update_transparency()
334 GList *cnv = conversations;
335 struct conversation *c;
337 This func should be uncalled!
340 c = (struct conversation *)cnv->data;
343 gtk_html_set_transparent(GTK_HTML(c->text),
344 (transparent) ? TRUE : FALSE);
352 /*------------------------------------------------------------------------*/
354 /*------------------------------------------------------------------------*/
356 void toggle_loggle(GtkWidget
*loggle
, struct conversation
*c
)
360 if (find_log_info(c
->name
))
361 rm_log(find_log_info(c
->name
));
362 else if (GTK_TOGGLE_BUTTON(loggle
)->active
)
368 static void do_save_convo(GtkObject
*obj
, GtkWidget
*wid
)
370 struct conversation
*c
= gtk_object_get_user_data(obj
);
371 char *filename
= gtk_file_selection_get_filename(GTK_FILE_SELECTION(wid
));
373 if (file_is_dir(filename
, wid
))
375 if ((!c
->is_chat
&& g_list_find(conversations
, c
)) ||
376 (c
->is_chat
&& g_slist_find(connections
, c
->gc
) && g_slist_find(c
->gc
->buddy_chats
, c
)))
377 filename
= g_strdup(filename
);
380 gtk_widget_destroy(wid
);
383 f
= fopen(filename
, "w+");
387 fprintf(f
, "%s", c
->history
->str
);
391 void save_convo(GtkWidget
*save
, struct conversation
*c
)
394 GtkWidget
*window
= gtk_file_selection_new(_("Gaim - Save Conversation"));
395 g_snprintf(buf
, sizeof(buf
), "%s/%s.log", g_get_home_dir(), normalize(c
->name
));
396 gtk_file_selection_set_filename(GTK_FILE_SELECTION(window
), buf
);
397 gtk_object_set_user_data(GTK_OBJECT(GTK_FILE_SELECTION(window
)->ok_button
), c
);
398 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window
)->ok_button
),
399 "clicked", GTK_SIGNAL_FUNC(do_save_convo
), window
);
400 gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(window
)->cancel_button
),
401 "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy
), (gpointer
)window
);
402 gtk_widget_show(window
);
405 void insert_smiley(GtkWidget
*smiley
, struct conversation
*c
)
409 if (GTK_TOGGLE_BUTTON(smiley
)->active
)
410 show_smiley_dialog(c
, smiley
);
411 else if (c
->smiley_dialog
)
412 close_smiley_dialog(smiley
, c
);
417 int close_callback(GtkWidget
*widget
, struct conversation
*c
)
419 if (c
->is_chat
&& (widget
== c
->close
) && !(chat_options
& OPT_CHAT_ONE_WINDOW
)) {
420 GtkWidget
*tmp
= c
->window
;
421 debug_printf("chat clicked close button\n");
423 gtk_widget_destroy(tmp
);
427 debug_printf("conversation close callback\n");
429 if (convo_options
& OPT_CONVO_CHECK_SPELLING
)
430 gtkspell_detach(GTK_TEXT(c
->entry
));
433 GSList
*cn
= connections
;
435 struct gaim_connection
*gc
= cn
->data
;
437 if (gc
->prpl
->convo_closed
)
438 gc
->prpl
->convo_closed(gc
, c
->name
);
442 if (im_options
& OPT_IM_ONE_WINDOW
) {
443 if ((g_list_length(conversations
) > 1) ||
444 ((convo_options
& OPT_CONVO_COMBINE
) &&
445 (chat_options
& OPT_CHAT_ONE_WINDOW
) && chats
)) {
446 gtk_notebook_remove_page(GTK_NOTEBOOK(convo_notebook
),
447 g_list_index(conversations
, c
));
450 gtk_widget_destroy(c
->window
);
453 convo_notebook
= NULL
;
454 if (convo_options
& OPT_CONVO_COMBINE
) {
456 chat_notebook
= NULL
;
461 gtk_widget_destroy(c
->window
);
465 if (chat_options
& OPT_CHAT_ONE_WINDOW
) {
466 if ((convo_options
& OPT_CONVO_COMBINE
) && (im_options
& OPT_IM_ONE_WINDOW
)
467 && (conversations
|| chats
->next
)) {
468 gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook
),
469 g_list_index(chats
, c
) +
470 g_list_length(conversations
));
471 } else if (g_list_length(chats
) > 1) {
472 gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook
),
473 g_list_index(chats
, c
));
476 gtk_widget_destroy(c
->window
);
479 chat_notebook
= NULL
;
480 if (convo_options
& OPT_CONVO_COMBINE
) {
482 convo_notebook
= NULL
;
487 gtk_widget_destroy(c
->window
);
492 if (c
->fg_color_dialog
)
493 gtk_widget_destroy(c
->fg_color_dialog
);
494 c
->fg_color_dialog
= NULL
;
495 if (c
->bg_color_dialog
)
496 gtk_widget_destroy(c
->bg_color_dialog
);
497 c
->bg_color_dialog
= NULL
;
499 gtk_widget_destroy(c
->font_dialog
);
500 c
->font_dialog
= NULL
;
501 if (c
->smiley_dialog
)
502 gtk_widget_destroy(c
->smiley_dialog
);
503 c
->smiley_dialog
= NULL
;
505 gtk_widget_destroy(c
->link_dialog
);
506 c
->link_dialog
= NULL
;
508 gtk_widget_destroy(c
->log_dialog
);
509 c
->log_dialog
= NULL
;
512 chats
= g_list_remove(chats
, c
);
514 serv_chat_leave(c
->gc
, c
->id
);
518 delete_conversation(c
);
524 void set_font_face(char *newfont
, struct conversation
*c
)
530 sprintf(c
->fontxfld
, "%s", newfont
&& *newfont
? newfont
: DEFAULT_FONT_XFLD
);
531 for (i
= 0; i
< strlen(c
->fontxfld
); i
++) {
532 if (c
->fontxfld
[i
] == '-') {
536 c
->fontface
[k
++] = c
->fontxfld
[i
];
538 c
->fontface
[k
] = '\0';
541 pre_fontface
= g_strconcat("<FONT FACE=\"", c
->fontface
, "\">", NULL
);
542 surround(c
->entry
, pre_fontface
, "</FONT>");
543 gtk_widget_grab_focus(c
->entry
);
544 g_free(pre_fontface
);
547 gint
delete_all_convo(GtkWidget
*w
, GdkEventAny
*e
, gpointer d
)
549 if (w
== all_convos
) {
550 while (conversations
) {
551 struct conversation
*c
= conversations
->data
;
552 close_callback(c
->close
, c
);
555 if (w
== all_chats
) {
557 struct conversation
*c
= chats
->data
;
558 close_callback(c
->close
, c
);
564 static gint
delete_event_convo(GtkWidget
*w
, GdkEventAny
*e
, struct conversation
*c
)
566 delete_conversation(c
);
570 void add_callback(GtkWidget
*widget
, struct conversation
*c
)
572 struct buddy
*b
= find_buddy(c
->gc
, c
->name
);
574 show_confirm_del(c
->gc
, c
->name
);
576 show_add_buddy(c
->gc
, c
->name
, NULL
, NULL
);
578 gtk_widget_grab_focus(c
->entry
);
582 void block_callback(GtkWidget
*widget
, struct conversation
*c
)
585 show_add_perm(c
->gc
, c
->name
, FALSE
);
586 gtk_widget_grab_focus(c
->entry
);
589 void warn_callback(GtkWidget
*widget
, struct conversation
*c
)
591 show_warn_dialog(c
->gc
, c
->name
);
592 gtk_widget_grab_focus(c
->entry
);
595 void info_callback(GtkWidget
*w
, struct conversation
*c
)
601 i
= GTK_LIST(c
->list
)->selection
;
603 name
= (char *)gtk_object_get_user_data(GTK_OBJECT(i
->data
));
608 serv_get_info(c
->gc
, name
);
610 serv_get_info(c
->gc
, c
->name
);
611 gtk_widget_grab_focus(c
->entry
);
615 static void move_next_tab(GtkNotebook
*notebook
, gboolean chat
)
617 int currpage
= gtk_notebook_get_current_page(notebook
);
620 struct conversation
*d
= NULL
;
622 if ((convo_options
& OPT_CONVO_COMBINE
) &&
623 (im_options
& OPT_IM_ONE_WINDOW
) &&
624 (chat_options
& OPT_CHAT_ONE_WINDOW
))
625 convlen
= g_list_length(conversations
);
630 /* if chat, find next unread chat */
631 cnv
= g_list_nth(chats
, currpage
- convlen
);
640 gtk_notebook_set_page(notebook
, convlen
+ g_list_index(chats
, d
));
644 /* else find next unread convo */
645 cnv
= g_list_nth(conversations
, currpage
);
654 gtk_notebook_set_page(notebook
, g_list_index(conversations
, d
));
659 if (convo_options
& OPT_CONVO_COMBINE
) {
660 if (chat
&& (im_options
& OPT_IM_ONE_WINDOW
)) {
661 /* if chat find next unread convo */
671 gtk_notebook_set_page(notebook
, g_list_index(conversations
, d
));
674 } else if (!chat
&& (chat_options
& OPT_CHAT_ONE_WINDOW
)) {
675 /* else find next unread chat */
685 gtk_notebook_set_page(notebook
, convlen
+ g_list_index(chats
, d
));
692 /* if chat find first unread chat */
702 gtk_notebook_set_page(notebook
, convlen
+ g_list_index(chats
, d
));
706 /* else find first unread convo */
716 gtk_notebook_set_page(notebook
, g_list_index(conversations
, d
));
721 /* go to next page */
722 if (currpage
+ 1 == g_list_length(notebook
->children
))
723 gtk_notebook_set_page(notebook
, 0);
725 gtk_notebook_next_page(notebook
);
728 gboolean
keypress_callback(GtkWidget
*entry
, GdkEventKey
* event
, struct conversation
*c
)
731 if (event
->keyval
== GDK_Escape
) {
732 if (convo_options
& OPT_CONVO_ESC_CAN_CLOSE
) {
733 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
734 close_callback(c
->close
, c
);
737 } else if (event
->keyval
== GDK_Page_Up
) {
738 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
739 gtk_imhtml_page_up(GTK_IMHTML(c
->text
));
740 } else if (event
->keyval
== GDK_Page_Down
) {
741 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
742 gtk_imhtml_page_down(GTK_IMHTML(c
->text
));
743 } else if ((event
->keyval
== GDK_F2
) && (convo_options
& OPT_CONVO_F2_TOGGLES
)) {
744 gtk_imhtml_show_comments(GTK_IMHTML(c
->text
), !GTK_IMHTML(c
->text
)->comments
);
745 } else if ((event
->keyval
== GDK_Return
) || (event
->keyval
== GDK_KP_Enter
)) {
746 if ((event
->state
& GDK_CONTROL_MASK
) && (convo_options
& OPT_CONVO_CTL_ENTER
)) {
747 gtk_signal_emit_by_name(GTK_OBJECT(entry
), "activate", c
);
748 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
750 } else if (!(event
->state
& (GDK_SHIFT_MASK
| GDK_CONTROL_MASK
)) && (convo_options
& OPT_CONVO_ENTER_SENDS
)) {
751 gtk_signal_emit_by_name(GTK_OBJECT(entry
), "activate", c
);
752 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
756 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
757 oldpos
= pos
= gtk_editable_get_position(GTK_EDITABLE(entry
));
758 gtk_editable_insert_text(GTK_EDITABLE(entry
), "\n", 1, &pos
);
760 gtk_editable_set_position(GTK_EDITABLE(entry
), pos
+ 1);
763 } else if ((event
->state
& GDK_CONTROL_MASK
) && (event
->keyval
== 'm')) {
765 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
766 oldpos
= pos
= gtk_editable_get_position(GTK_EDITABLE(entry
));
767 gtk_editable_insert_text(GTK_EDITABLE(entry
), "\n", 1, &pos
);
769 gtk_editable_set_position(GTK_EDITABLE(entry
), pos
+ 1);
770 } else if (event
->state
& GDK_CONTROL_MASK
) {
771 if (convo_options
& OPT_CONVO_CTL_CHARS
) {
772 switch (event
->keyval
) {
776 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c
->italic
)));
777 do_italic(c
->italic
, c
->entry
);
778 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
780 case 'u': /* ctl-u is GDK_Clear, which clears the line */
782 quiet_set(c
->underline
,
783 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
785 do_underline(c
->underline
, c
->entry
);
786 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
788 case 'b': /* ctl-b is GDK_Left, which moves backwards */
791 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c
->bold
)));
792 do_bold(c
->bold
, c
->entry
);
793 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
798 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c
->strike
)));
799 do_strike(c
->strike
, c
->entry
);
800 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
804 if (convo_options
& OPT_CONVO_CTL_SMILEYS
) {
807 switch (event
->keyval
) {
842 sprintf(buf
, "O:-)");
858 if (GTK_OLD_EDITABLE(c
->entry
)->has_selection
) {
859 int finish
= GTK_OLD_EDITABLE(c
->entry
)->selection_end_pos
;
860 gtk_editable_insert_text(GTK_EDITABLE(c
->entry
),
861 buf
, strlen(buf
), &finish
);
863 pos
= GTK_OLD_EDITABLE(c
->entry
)->current_pos
;
864 gtk_editable_insert_text(GTK_EDITABLE(c
->entry
),
865 buf
, strlen(buf
), &pos
);
867 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
870 if (event
->keyval
== 'l') {
871 gtk_imhtml_clear(GTK_IMHTML(c
->text
));
872 g_string_free(c
->history
, TRUE
);
873 c
->history
= g_string_new("");
875 if ((!c
->is_chat
&& (im_options
& OPT_IM_ONE_WINDOW
)) ||
876 (c
->is_chat
&& (chat_options
& OPT_CHAT_ONE_WINDOW
))) {
877 GtkWidget
*notebook
= (c
->is_chat
? chat_notebook
: convo_notebook
);
878 if (event
->keyval
== '[') {
879 gtk_notebook_prev_page(GTK_NOTEBOOK(notebook
));
880 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
881 } else if (event
->keyval
== ']') {
882 gtk_notebook_next_page(GTK_NOTEBOOK(notebook
));
883 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
884 } else if (event
->keyval
== GDK_Tab
) {
885 move_next_tab(GTK_NOTEBOOK(notebook
), c
->is_chat
);
886 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
890 } else if ((event
->keyval
== GDK_Tab
) && c
->is_chat
&& (chat_options
& OPT_CHAT_TAB_COMPLETE
)) {
892 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
894 } else if (((!c
->is_chat
&& (im_options
& OPT_IM_ONE_WINDOW
)) ||
895 (c
->is_chat
&& (chat_options
& OPT_CHAT_ONE_WINDOW
))) &&
896 (event
->state
& GDK_MOD1_MASK
) && (event
->keyval
> '0') && (event
->keyval
<= '9')) {
897 GtkWidget
*notebook
= (c
->is_chat
? chat_notebook
: convo_notebook
);
898 gtk_notebook_set_page(GTK_NOTEBOOK(notebook
), event
->keyval
- '1');
899 gtk_signal_emit_stop_by_name(GTK_OBJECT(entry
), "key_press_event");
902 if (c
&& (!(misc_options
& OPT_MISC_STEALTH_TYPING
)) && !c
->is_chat
) {
903 char *txt
= gtk_editable_get_chars(GTK_EDITABLE(c
->entry
), 0, -1);
904 if ((strlen(txt
) == 0 && event
->keyval
< 256 && isprint(event
->keyval
)) ||
905 (c
->type_again
!= 0 && time(NULL
) > c
->type_again
)) {
906 int timeout
= serv_send_typing(c
->gc
, c
->name
);
908 c
->type_again
= time(NULL
) + timeout
;
912 else if (strlen(txt
) == 1) {
913 if ((GTK_OLD_EDITABLE(c
->entry
)->current_pos
== 1 && event
->keyval
== GDK_BackSpace
) ||
914 (GTK_OLD_EDITABLE(c
->entry
)->current_pos
== 0 && event
->keyval
== GDK_Delete
))
915 serv_send_typing_stopped(c
->gc
, c
->name
);
916 } else if (GTK_OLD_EDITABLE(c
->entry
)->selection_start_pos
== 0) {
917 if (GTK_OLD_EDITABLE(c
->entry
)->selection_end_pos
== strlen(txt
) &&
918 (event
->keyval
== GDK_BackSpace
|| event
->keyval
== GDK_Delete
))
919 serv_send_typing_stopped(c
->gc
, c
->name
);
927 void send_callback(GtkWidget
*widget
, struct conversation
*c
)
936 buf2
= gtk_editable_get_chars(GTK_EDITABLE(c
->entry
), 0, -1);
937 limit
= 32 * 1024; /* you shouldn't be sending more than 32k in your messages. that's a book. */
938 buf
= g_malloc(limit
);
939 g_snprintf(buf
, limit
, "%s", buf2
);
946 buf2
= g_malloc(limit
);
948 if (c
->gc
->flags
& OPT_CONN_HTML
) {
949 if (convo_options
& OPT_CONVO_SEND_LINKS
)
952 if (font_options
& OPT_FONT_BOLD
) {
953 g_snprintf(buf2
, limit
, "<B>%s</B>", buf
);
957 if (font_options
& OPT_FONT_ITALIC
) {
958 g_snprintf(buf2
, limit
, "<I>%s</I>", buf
);
962 if (font_options
& OPT_FONT_UNDERLINE
) {
963 g_snprintf(buf2
, limit
, "<U>%s</U>", buf
);
967 if (font_options
& OPT_FONT_STRIKE
) {
968 g_snprintf(buf2
, limit
, "<STRIKE>%s</STRIKE>", buf
);
972 if ((font_options
& OPT_FONT_FACE
) || c
->hasfont
) {
973 g_snprintf(buf2
, limit
, "<FONT FACE=\"%s\">%s</FONT>", c
->fontface
, buf
);
977 if (font_options
& OPT_FONT_SIZE
) {
978 g_snprintf(buf2
, limit
, "<FONT SIZE=\"%d\">%s</FONT>", fontsize
, buf
);
982 if ((font_options
& OPT_FONT_FGCOL
) || c
->hasfg
) {
983 g_snprintf(buf2
, limit
, "<FONT COLOR=\"#%02X%02X%02X\">%s</FONT>", c
->fgcol
.red
,
984 c
->fgcol
.green
, c
->fgcol
.blue
, buf
);
988 if ((font_options
& OPT_FONT_BGCOL
) || c
->hasbg
) {
989 g_snprintf(buf2
, limit
, "<BODY BGCOLOR=\"#%02X%02X%02X\">%s</BODY>",
990 c
->bgcol
.red
, c
->bgcol
.green
, c
->bgcol
.blue
, buf
);
995 quiet_set(c
->bold
, FALSE
);
996 quiet_set(c
->strike
, FALSE
);
997 quiet_set(c
->italic
, FALSE
);
998 quiet_set(c
->underline
, FALSE
);
999 quiet_set(c
->font
, FALSE
);
1000 quiet_set(c
->fgcolorbtn
, FALSE
);
1001 quiet_set(c
->bgcolorbtn
, FALSE
);
1002 quiet_set(c
->link
, FALSE
);
1003 gtk_widget_grab_focus(c
->entry
);
1006 char *buffy
= g_strdup(buf
);
1007 enum gaim_event evnt
= c
->is_chat
? event_chat_send
: event_im_send
;
1008 int plugin_return
= plugin_event(evnt
, c
->gc
,
1009 c
->is_chat
? (void *)c
->id
: c
->name
,
1016 if (plugin_return
) {
1017 gtk_editable_delete_text(GTK_EDITABLE(c
->entry
), 0, -1);
1023 g_snprintf(buf
, limit
, "%s", buffy
);
1030 buffy
= g_strdup(buf
);
1031 plugin_event(event_im_displayed_sent
, c
->gc
, c
->name
, &buffy
, 0);
1034 if (c
->check
&& gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c
->check
)))
1035 imflags
= IM_FLAG_CHECKBOX
;
1036 err
= serv_send_im(c
->gc
, c
->name
, buffy
, imflags
);
1042 write_to_conv(c
, buf
, WFLAG_SEND
, NULL
, time(NULL
), -1);
1044 if (c
->makesound
&& (sound_options
& OPT_SOUND_SEND
))
1047 if (im_options
& OPT_IM_POPDOWN
)
1048 gtk_widget_hide(c
->window
);
1051 err
= serv_chat_send(c
->gc
, c
->id
, buf
);
1053 /* no sound because we do that when we receive our message */
1061 do_error_dialog(_("Unable to send message: too large"), _("Message Error"));
1063 do_error_dialog(_("Unable to send message: Unknown reason"), _("Message Error"));
1065 gtk_editable_delete_text(GTK_EDITABLE(c
->entry
), 0, -1);
1067 if ((err
> 0) && (away_options
& OPT_AWAY_BACK_ON_IM
)) {
1068 if (awaymessage
!= NULL
) {
1070 } else if (c
->gc
->away
) {
1071 serv_set_away(c
->gc
, GAIM_AWAY_CUSTOM
, NULL
);
1077 int entry_key_pressed(GtkWidget
*w
, GtkWidget
*entry
)
1079 check_everything(w
);
1083 /*------------------------------------------------------------------------*/
1084 /* HTML-type stuff */
1085 /*------------------------------------------------------------------------*/
1087 int count_tag(GtkWidget
*entry
, char *s1
, char *s2
)
1091 char *tmp
, *tmpo
, h
;
1092 tmpo
= gtk_editable_get_chars(GTK_EDITABLE(entry
), 0, -1);
1093 h
= tmpo
[GTK_OLD_EDITABLE(entry
)->current_pos
];
1094 tmpo
[GTK_OLD_EDITABLE(entry
)->current_pos
] = '\0';
1097 p1
= strstr(tmp
, s1
);
1098 p2
= strstr(tmp
, s2
);
1102 tmp
= p1
+ strlen(s1
);
1103 } else if (p2
< p1
) {
1105 tmp
= p2
+ strlen(s2
);
1110 tmp
= p1
+ strlen(s1
);
1113 tmp
= p2
+ strlen(s2
);
1117 tmpo
[GTK_OLD_EDITABLE(entry
)->current_pos
] = h
;
1123 int invert_tags(GtkWidget
*entry
, char *s1
, char *s2
, int really
)
1125 int start
= GTK_OLD_EDITABLE(entry
)->selection_start_pos
;
1126 int finish
= GTK_OLD_EDITABLE(entry
)->selection_end_pos
;
1129 s
= gtk_editable_get_chars(GTK_EDITABLE(entry
), 0, -1);
1130 if (!g_strncasecmp(&s
[start
], s1
, strlen(s1
)) &&
1131 !g_strncasecmp(&s
[finish
- strlen(s2
)], s2
, strlen(s2
))) {
1133 gtk_editable_delete_text(GTK_EDITABLE(entry
), start
, start
+ strlen(s1
));
1134 gtk_editable_delete_text(GTK_EDITABLE(entry
), finish
- strlen(s2
) - strlen(s1
),
1135 finish
- strlen(s1
));
1145 void remove_tags(GtkWidget
*entry
, char *tag
)
1148 int start
= GTK_OLD_EDITABLE(entry
)->selection_start_pos
;
1149 int finish
= GTK_OLD_EDITABLE(entry
)->selection_end_pos
;
1151 s
= gtk_editable_get_chars(GTK_EDITABLE(entry
), 0, -1);
1154 if (start
> finish
) {
1160 if (strstr(tag
, "<FONT SIZE=")) {
1161 while ((t
= strstr(t
, "<FONT SIZE="))) {
1162 if (((t
- s
) < finish
) && ((t
- s
) >= start
)) {
1163 gtk_editable_delete_text(GTK_EDITABLE(entry
), (t
- s
),
1164 (t
- s
) + strlen(tag
));
1166 s
= gtk_editable_get_chars(GTK_EDITABLE(entry
), 0, -1);
1172 while ((t
= strstr(t
, tag
))) {
1173 if (((t
- s
) < finish
) && ((t
- s
) >= start
)) {
1174 gtk_editable_delete_text(GTK_EDITABLE(entry
), (t
- s
),
1175 (t
- s
) + strlen(tag
));
1177 s
= gtk_editable_get_chars(GTK_EDITABLE(entry
), 0, -1);
1186 static char *html_logize(char *p
)
1195 while (*temp_p
!= '\0') {
1197 if ((*temp_p
== '\n') || ((*temp_p
== '<') && (*(temp_p
+ 1) == '!')))
1203 buffer_p
= g_malloc(char_len
+ (4 * num_cr
) + 1);
1204 buffer_start
= buffer_p
;
1206 while (*temp_p
!= '\0') {
1207 if (*temp_p
== '\n') {
1213 } else if ((*temp_p
== '<') && (*(temp_p
+ 1) == '!')) {
1219 *buffer_p
++ = *temp_p
;
1224 return buffer_start
;
1227 void surround(GtkWidget
*entry
, char *pre
, char *post
)
1229 int temp
, pos
= GTK_OLD_EDITABLE(entry
)->current_pos
;
1233 if (convo_options
& OPT_CONVO_CHECK_SPELLING
) {
1234 gtkspell_detach(GTK_TEXT(entry
));
1237 if (GTK_OLD_EDITABLE(entry
)->has_selection
) {
1238 remove_tags(entry
, pre
);
1239 remove_tags(entry
, post
);
1240 start
= GTK_OLD_EDITABLE(entry
)->selection_start_pos
;
1241 finish
= GTK_OLD_EDITABLE(entry
)->selection_end_pos
;
1242 if (start
> finish
) {
1248 gtk_editable_insert_text(GTK_EDITABLE(entry
), pre
, strlen(pre
), &dummy
);
1249 dummy
= finish
+ strlen(pre
);
1250 gtk_editable_insert_text(GTK_EDITABLE(entry
), post
, strlen(post
), &dummy
);
1251 gtk_editable_select_region(GTK_EDITABLE(entry
), start
,
1252 finish
+ strlen(pre
) + strlen(post
));
1255 gtk_editable_insert_text(GTK_EDITABLE(entry
), pre
, strlen(pre
), &pos
);
1257 dummy
= pos
+ strlen(pre
);
1258 gtk_editable_insert_text(GTK_EDITABLE(entry
), post
, strlen(post
), &dummy
);
1259 gtk_editable_set_position(GTK_EDITABLE(entry
), dummy
);
1262 gtk_editable_insert_text(GTK_EDITABLE(entry
), post
, strlen(post
), &dummy
);
1263 gtk_editable_set_position(GTK_EDITABLE(entry
), pos
);
1267 if (convo_options
& OPT_CONVO_CHECK_SPELLING
) {
1268 gtkspell_attach(GTK_TEXT(entry
));
1271 gtk_widget_grab_focus(entry
);
1274 void advance_past(GtkWidget
*entry
, char *pre
, char *post
)
1278 if (invert_tags(entry
, pre
, post
, 1))
1280 s
= gtk_editable_get_chars(GTK_EDITABLE(entry
), 0, -1);
1281 pos
= GTK_OLD_EDITABLE(entry
)->current_pos
;
1282 debug_printf(_("Currently at %d, "), pos
);
1283 s2
= strstr(&s
[pos
], post
);
1285 pos
= s2
- s
+ strlen(post
);
1287 gtk_editable_insert_text(GTK_EDITABLE(entry
), post
, strlen(post
), &pos
);
1290 debug_printf(_("Setting position to %d\n"), pos
);
1291 gtk_editable_set_position(GTK_EDITABLE(entry
), pos
);
1292 gtk_widget_grab_focus(entry
);
1295 void toggle_fg_color(GtkWidget
*color
, struct conversation
*c
)
1299 if (GTK_TOGGLE_BUTTON(color
)->active
)
1300 show_fgcolor_dialog(c
, color
);
1301 else if (c
->fg_color_dialog
)
1302 cancel_fgcolor(color
, c
);
1304 advance_past(c
->entry
, "<FONT COLOR>", "</FONT>");
1307 void toggle_bg_color(GtkWidget
*color
, struct conversation
*c
)
1311 if (GTK_TOGGLE_BUTTON(color
)->active
)
1312 show_bgcolor_dialog(c
, color
);
1313 else if (c
->bg_color_dialog
)
1314 cancel_bgcolor(color
, c
);
1316 advance_past(c
->entry
, "<BODY BGCOLOR>", "</BODY>");
1319 void toggle_font(GtkWidget
*font
, struct conversation
*c
)
1323 if (GTK_TOGGLE_BUTTON(font
)->active
)
1324 show_font_dialog(c
, font
);
1325 else if (c
->font_dialog
)
1326 cancel_font(font
, c
);
1328 advance_past(c
->entry
, "<FONT FACE>", "</FONT>");
1331 void toggle_link(GtkWidget
*linky
, struct conversation
*c
)
1335 if (GTK_TOGGLE_BUTTON(linky
)->active
)
1336 show_add_link(linky
, c
);
1337 else if (c
->link_dialog
)
1338 cancel_link(linky
, c
);
1340 advance_past(c
->entry
, "<A HREF>", "</A>");
1343 void do_strike(GtkWidget
*strike
, GtkWidget
*entry
)
1348 if (GTK_TOGGLE_BUTTON(strike
)->active
)
1349 surround(entry
, "<STRIKE>", "</STRIKE>");
1351 advance_past(entry
, "<STRIKE>", "</STRIKE>");
1355 void do_bold(GtkWidget
*bold
, GtkWidget
*entry
)
1359 if (GTK_TOGGLE_BUTTON(bold
)->active
)
1360 surround(entry
, "<B>", "</B>");
1362 advance_past(entry
, "<B>", "</B>");
1365 void do_underline(GtkWidget
*underline
, GtkWidget
*entry
)
1369 if (GTK_TOGGLE_BUTTON(underline
)->active
)
1370 surround(entry
, "<U>", "</U>");
1372 advance_past(entry
, "<U>", "</U>");
1375 void do_italic(GtkWidget
*italic
, GtkWidget
*entry
)
1379 if (GTK_TOGGLE_BUTTON(italic
)->active
)
1380 surround(entry
, "<I>", "</I>");
1382 advance_past(entry
, "<I>", "</I>");
1385 /* html code to modify font sizes must all be the same length, */
1386 /* currently set to 15 chars */
1388 void do_small(GtkWidget
*small
, GtkWidget
*entry
)
1392 surround(entry
, "<FONT SIZE=\"1\">", "</FONT>");
1395 void do_normal(GtkWidget
*normal
, GtkWidget
*entry
)
1399 surround(entry
, "<FONT SIZE=\"3\">", "</FONT>");
1402 void do_big(GtkWidget
*big
, GtkWidget
*entry
)
1406 surround(entry
, "<FONT SIZE=\"5\">", "</FONT>");
1409 void check_everything(GtkWidget
*entry
)
1411 struct conversation
*c
;
1413 c
= (struct conversation
*)gtk_object_get_user_data(GTK_OBJECT(entry
));
1416 if (invert_tags(entry
, "<B>", "</B>", 0))
1417 quiet_set(c
->bold
, TRUE
);
1418 else if (count_tag(entry
, "<B>", "</B>"))
1419 quiet_set(c
->bold
, TRUE
);
1421 quiet_set(c
->bold
, FALSE
);
1422 if (invert_tags(entry
, "<I>", "</I>", 0))
1423 quiet_set(c
->italic
, TRUE
);
1424 else if (count_tag(entry
, "<I>", "</I>"))
1425 quiet_set(c
->italic
, TRUE
);
1427 quiet_set(c
->italic
, FALSE
);
1429 if (invert_tags(entry
, "<FONT COLOR", "</FONT>", 0))
1430 quiet_set(c
->fgcolorbtn
, TRUE
);
1431 else if (count_tag(entry
, "<FONT COLOR", "</FONT>"))
1432 quiet_set(c
->fgcolorbtn
, TRUE
);
1434 quiet_set(c
->fgcolorbtn
, FALSE
);
1436 if (invert_tags(entry
, "<BODY BGCOLOR", "</BODY>", 0))
1437 quiet_set(c
->bgcolorbtn
, TRUE
);
1438 else if (count_tag(entry
, "<BODY BGCOLOR", "</BODY>"))
1439 quiet_set(c
->bgcolorbtn
, TRUE
);
1441 quiet_set(c
->bgcolorbtn
, FALSE
);
1443 if (invert_tags(entry
, "<FONT FACE", "</FONT>", 0))
1444 quiet_set(c
->font
, TRUE
);
1445 else if (count_tag(entry
, "<FONT FACE", "</FONT>"))
1446 quiet_set(c
->font
, TRUE
);
1448 quiet_set(c
->font
, FALSE
);
1450 if (invert_tags(entry
, "<A HREF", "</A>", 0))
1451 quiet_set(c
->link
, TRUE
);
1452 else if (count_tag(entry
, "<A HREF", "</A>"))
1453 quiet_set(c
->link
, TRUE
);
1455 quiet_set(c
->link
, FALSE
);
1457 if (invert_tags(entry
, "<U>", "</U>", 0))
1458 quiet_set(c
->underline
, TRUE
);
1459 else if (count_tag(entry
, "<U>", "</U>"))
1460 quiet_set(c
->underline
, TRUE
);
1462 quiet_set(c
->underline
, FALSE
);
1464 if (invert_tags(entry
, "<STRIKE>", "</STRIKE>", 0))
1465 quiet_set(c
->strike
, TRUE
);
1466 else if (count_tag(entry
, "<STRIKE>", "</STRIKE>"))
1467 quiet_set(c
->strike
, TRUE
);
1469 quiet_set(c
->strike
, FALSE
);
1473 /*------------------------------------------------------------------------*/
1474 /* Takin care of the window.. */
1475 /*------------------------------------------------------------------------*/
1478 /* this is going to be interesting since the conversation could either be a
1479 * normal IM conversation or a chat window. but hopefully it won't matter */
1480 void write_to_conv(struct conversation
*c
, char *what
, int flags
, char *who
, time_t mtime
, gint length
)
1487 int gtk_font_options
= 0;
1489 char buf2
[BUF_LONG
];
1491 int unhighlight
= 0;
1493 if (c
->is_chat
&& (!c
->gc
|| !g_slist_find(c
->gc
->buddy_chats
, c
)))
1496 if (!c
->is_chat
&& !g_list_find(conversations
, c
))
1499 gtk_widget_show(c
->window
);
1501 if (!c
->is_chat
|| !(c
->gc
->prpl
->options
& OPT_PROTO_UNIQUE_CHATNAME
)) {
1503 if (flags
& WFLAG_SEND
) {
1504 b
= find_buddy(c
->gc
, c
->gc
->username
);
1505 if (b
&& strcmp(b
->name
, b
->show
))
1507 else if (c
->gc
->displayname
[0])
1508 who
= c
->gc
->displayname
;
1510 who
= c
->gc
->username
;
1512 b
= find_buddy(c
->gc
, c
->name
);
1519 b
= find_buddy(c
->gc
, who
);
1525 strftime(mdate
, sizeof(mdate
), "%H:%M:%S", localtime(&mtime
));
1527 gtk_font_options
= gtk_font_options
^ GTK_IMHTML_NO_COMMENTS
;
1529 if (convo_options
& OPT_CONVO_IGNORE_COLOUR
)
1530 gtk_font_options
= gtk_font_options
^ GTK_IMHTML_NO_COLOURS
;
1532 if (convo_options
& OPT_CONVO_IGNORE_FONTS
)
1533 gtk_font_options
= gtk_font_options
^ GTK_IMHTML_NO_FONTS
;
1535 if (convo_options
& OPT_CONVO_IGNORE_SIZES
)
1536 gtk_font_options
= gtk_font_options
^ GTK_IMHTML_NO_SIZES
;
1538 if (!(logging_options
& OPT_LOG_STRIP_HTML
))
1539 gtk_font_options
= gtk_font_options
^ GTK_IMHTML_RETURN_LOG
;
1541 if (flags
& WFLAG_SYSTEM
) {
1542 if (convo_options
& OPT_CONVO_SHOW_TIME
)
1543 g_snprintf(buf
, BUF_LONG
, "<FONT SIZE=\"2\">(%s) </FONT><B>%s</B>", mdate
, what
);
1545 g_snprintf(buf
, BUF_LONG
, "<B>%s</B>", what
);
1546 g_snprintf(buf2
, sizeof(buf2
), "<FONT SIZE=\"2\"><!--(%s) --></FONT><B>%s</B><BR>",
1549 gtk_imhtml_append_text(GTK_IMHTML(c
->text
), buf2
, -1, 0);
1551 if (logging_options
& OPT_LOG_STRIP_HTML
) {
1552 char *t1
= strip_html(buf
);
1553 c
->history
= g_string_append(c
->history
, t1
);
1554 c
->history
= g_string_append(c
->history
, "\n");
1557 c
->history
= g_string_append(c
->history
, buf
);
1558 c
->history
= g_string_append(c
->history
, "<BR>\n");
1561 if (!(flags
& WFLAG_NOLOG
) && ((logging_options
& OPT_LOG_ALL
) || find_log_info(c
->name
))) {
1565 if (logging_options
& OPT_LOG_STRIP_HTML
) {
1566 t1
= strip_html(buf
);
1571 g_snprintf(nm
, 256, "%s.chat", c
->name
);
1573 g_snprintf(nm
, 256, "%s", c
->name
);
1574 fd
= open_log_file(nm
);
1576 if (logging_options
& OPT_LOG_STRIP_HTML
) {
1577 fprintf(fd
, "%s\n", t1
);
1579 fprintf(fd
, "%s<BR>\n", t1
);
1583 if (logging_options
& OPT_LOG_STRIP_HTML
) {
1587 } else if (flags
& WFLAG_NOLOG
) {
1588 g_snprintf(buf
, BUF_LONG
, "<B><FONT COLOR=\"#777777\">%s</FONT></B><BR>", what
);
1589 gtk_imhtml_append_text(GTK_IMHTML(c
->text
), buf
, -1, 0);
1591 if (flags
& WFLAG_WHISPER
) {
1592 /* if we're whispering, it's not an autoresponse */
1593 if (meify(what
, length
)) {
1594 str
= g_malloc(1024);
1595 g_snprintf(str
, 1024, "***%s", who
);
1596 strcpy(colour
, "#6C2585");
1598 str
= g_malloc(1024);
1599 g_snprintf(str
, 1024, "*%s*:", who
);
1600 strcpy(colour
, "#00ff00");
1603 if (meify(what
, length
)) {
1604 str
= g_malloc(1024);
1605 if (flags
& WFLAG_AUTO
)
1606 g_snprintf(str
, 1024, "%s ***%s", AUTO_RESPONSE
, who
);
1608 g_snprintf(str
, 1024, "***%s", who
);
1609 if (flags
& WFLAG_NICK
)
1610 strcpy(colour
, "#af7f00");
1612 strcpy(colour
, "#062585");
1614 str
= g_malloc(1024);
1615 if (flags
& WFLAG_AUTO
)
1616 g_snprintf(str
, 1024, "%s %s", who
, AUTO_RESPONSE
);
1618 g_snprintf(str
, 1024, "%s:", who
);
1619 if (flags
& WFLAG_NICK
)
1620 strcpy(colour
, "#af7f00");
1621 else if (flags
& WFLAG_RECV
)
1622 strcpy(colour
, "#ff0000");
1623 else if (flags
& WFLAG_SEND
)
1624 strcpy(colour
, "#0000ff");
1628 if (convo_options
& OPT_CONVO_SHOW_TIME
)
1629 g_snprintf(buf
, BUF_LONG
, "<FONT COLOR=\"%s\"><FONT SIZE=\"2\">(%s) </FONT>"
1630 "<B>%s</B></FONT> ", colour
, mdate
, str
);
1632 g_snprintf(buf
, BUF_LONG
, "<FONT COLOR=\"%s\"><B>%s</B></FONT> ", colour
, str
);
1633 g_snprintf(buf2
, BUF_LONG
, "<FONT COLOR=\"%s\"><FONT SIZE=\"2\"><!--(%s) --></FONT>"
1634 "<B>%s</B></FONT> ", colour
, mdate
, str
);
1638 gtk_imhtml_append_text(GTK_IMHTML(c
->text
), buf2
, -1, 0);
1640 logstr
= gtk_imhtml_append_text(GTK_IMHTML(c
->text
), what
, length
, gtk_font_options
);
1642 gtk_imhtml_append_text(GTK_IMHTML(c
->text
), "<BR>", -1, 0);
1644 /* XXX this needs to be updated for the new length argument */
1645 if (logging_options
& OPT_LOG_STRIP_HTML
) {
1647 t1
= strip_html(buf
);
1648 t2
= strip_html(what
);
1649 c
->history
= g_string_append(c
->history
, t1
);
1650 c
->history
= g_string_append(c
->history
, t2
);
1651 c
->history
= g_string_append(c
->history
, "\n");
1656 t1
= html_logize(buf
);
1657 t2
= html_logize(what
);
1658 c
->history
= g_string_append(c
->history
, t1
);
1659 c
->history
= g_string_append(c
->history
, t2
);
1660 c
->history
= g_string_append(c
->history
, "\n");
1661 c
->history
= g_string_append(c
->history
, logstr
->str
);
1662 c
->history
= g_string_append(c
->history
, "<BR>\n");
1667 /* XXX this needs to be updated for the new length argument */
1668 if ((logging_options
& OPT_LOG_ALL
) || find_log_info(c
->name
)) {
1670 char *nm
= g_malloc(256);
1672 g_snprintf(nm
, 256, "%s.chat", c
->name
);
1674 g_snprintf(nm
, 256, "%s", c
->name
);
1676 if (logging_options
& OPT_LOG_STRIP_HTML
) {
1677 t1
= strip_html(buf
);
1678 t2
= strip_html(what
);
1680 t1
= html_logize(buf
);
1681 t2
= html_logize(what
);
1683 fd
= open_log_file(nm
);
1685 if (logging_options
& OPT_LOG_STRIP_HTML
) {
1686 fprintf(fd
, "%s%s\n", t1
, t2
);
1688 fprintf(fd
, "%s%s%s<BR>\n", t1
, t2
, logstr
->str
);
1689 g_string_free(logstr
, TRUE
);
1699 if ((c
->is_chat
&& (chat_options
& OPT_CHAT_POPUP
)) ||
1700 (!c
->is_chat
&& (im_options
& OPT_IM_POPUP
)))
1701 gdk_window_show(c
->window
->window
);
1703 /* tab highlighting */
1704 if (c
->is_chat
&& !(chat_options
& OPT_CHAT_ONE_WINDOW
)) /* if chat but not tabbed chat */
1706 if (!c
->is_chat
&& !(im_options
& OPT_IM_ONE_WINDOW
)) /* if convo but not tabbed convo */
1708 if (!(flags
& WFLAG_RECV
) && !(flags
& WFLAG_SYSTEM
))
1710 if ((c
->unseen
== 2) || ((c
->unseen
== 1) && !(flags
& WFLAG_NICK
)))
1715 if ((convo_options
& OPT_CONVO_COMBINE
) && (im_options
& OPT_IM_ONE_WINDOW
))
1716 offs
= g_list_length(conversations
);
1719 if (gtk_notebook_get_current_page(GTK_NOTEBOOK(chat_notebook
)) ==
1720 g_list_index(chats
, c
) + offs
)
1723 if (gtk_notebook_get_current_page(GTK_NOTEBOOK(convo_notebook
)) ==
1724 g_list_index(conversations
, c
))
1727 if ((c
->unseen
!= -1) && unhighlight
) /* If there's no typing message
1728 and we're on the same tab, don't bother
1729 changing the color. */
1733 GtkNotebook
*notebook
= GTK_NOTEBOOK(c
->is_chat
? chat_notebook
: convo_notebook
);
1734 int offs
= ((convo_options
& OPT_CONVO_COMBINE
) &&
1735 (im_options
& OPT_IM_ONE_WINDOW
) && c
->is_chat
) ?
1736 g_list_length(conversations
) : 0;
1737 GList
*ws
= (c
->is_chat
? chats
: conversations
);
1738 GtkWidget
*label
= gtk_notebook_get_tab_label(notebook
,
1739 gtk_notebook_get_nth_page(notebook
,
1740 offs
+ g_list_index(ws
, c
)));
1742 style
= gtk_style_new();
1743 if (!GTK_WIDGET_REALIZED(label
))
1744 gtk_widget_realize(label
);
1745 gdk_font_unref(gtk_style_get_font(style
));
1746 gtk_style_set_font(style
, gdk_font_ref(gtk_style_get_font(label
->style
)));
1747 if (!unhighlight
&& flags
& WFLAG_NICK
) {
1748 style
->fg
[0].red
= 0x0000;
1749 style
->fg
[0].green
= 0x0000;
1750 style
->fg
[0].blue
= 0xcccc;
1752 } else if (!unhighlight
) {
1753 style
->fg
[0].red
= 0xcccc;
1754 style
->fg
[0].green
= 0x0000;
1755 style
->fg
[0].blue
= 0x0000;
1760 gtk_widget_set_style(label
, style
);
1761 gtk_style_unref(style
);
1763 if (flags
& WFLAG_RECV
)
1764 reset_typing(g_strdup(c
->name
));
1767 void update_progress(struct conversation
*c
, float percent
) {
1768 while (gtk_events_pending())
1769 gtk_main_iteration();
1771 if (percent
>= 1 && !(c
->progress
))
1775 gtk_widget_destroy(c
->progress
);
1781 GtkBox
*box
= GTK_BOX(c
->text
->parent
->parent
);
1782 c
->progress
= gtk_progress_bar_new();
1783 gtk_box_pack_end(box
, c
->progress
, FALSE
, FALSE
, 0);
1784 gtk_widget_set_usize (c
->progress
, 1, 8);
1785 gtk_widget_show (c
->progress
);
1789 gtk_progress_set_percentage(GTK_PROGRESS(c
->progress
), percent
);
1792 GtkWidget
*build_conv_toolbar(struct conversation
*c
)
1794 GdkPixmap
*strike_i
, *small_i
, *normal_i
, *big_i
, *bold_i
, *italic_i
, *underline_i
, *speaker_i
,
1795 *wood_i
, *fgcolor_i
, *bgcolor_i
, *link_i
, *font_i
, *smiley_i
, *save_i
;
1796 GtkWidget
*strike_p
, *small_p
, *normal_p
, *big_p
, *bold_p
, *italic_p
, *underline_p
, *speaker_p
,
1797 *wood_p
, *fgcolor_p
, *bgcolor_p
, *link_p
, *font_p
, *smiley_p
, *save_p
;
1798 GtkWidget
*strike
, *small
, *normal
, *big
, *bold
, *italic
, *underline
, *speaker
, *wood
,
1799 *fgcolorbtn
, *bgcolorbtn
, *link
, *font
, *smiley
, *save
;
1805 toolbar
= gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL
, GTK_TOOLBAR_ICONS
);
1809 bold_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, bold_xpm
);
1810 bold_p
= gtk_pixmap_new(bold_i
, mask
);
1811 gtk_widget_show(bold_p
);
1812 gdk_bitmap_unref(mask
);
1814 italic_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, italic_xpm
);
1815 italic_p
= gtk_pixmap_new(italic_i
, mask
);
1816 gtk_widget_show(italic_p
);
1817 gdk_bitmap_unref(mask
);
1819 underline_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
,
1820 &win
->style
->white
, underline_xpm
);
1821 underline_p
= gtk_pixmap_new(underline_i
, mask
);
1822 gtk_widget_show(underline_p
);
1823 gdk_bitmap_unref(mask
);
1825 strike_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, strike_xpm
);
1826 strike_p
= gtk_pixmap_new(strike_i
, mask
);
1827 gtk_widget_show(strike_p
);
1828 gdk_bitmap_unref(mask
);
1830 small_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, small_xpm
);
1831 small_p
= gtk_pixmap_new(small_i
, mask
);
1832 gtk_widget_show(small_p
);
1833 gdk_bitmap_unref(mask
);
1835 normal_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, normal_xpm
);
1836 normal_p
= gtk_pixmap_new(normal_i
, mask
);
1837 gtk_widget_show(normal_p
);
1838 gdk_bitmap_unref(mask
);
1840 big_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, big_xpm
);
1841 big_p
= gtk_pixmap_new(big_i
, mask
);
1842 gtk_widget_show(big_p
);
1843 gdk_bitmap_unref(mask
);
1845 font_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, fontface_xpm
);
1846 font_p
= gtk_pixmap_new(font_i
, mask
);
1847 gtk_widget_show(font_p
);
1848 gdk_bitmap_unref(mask
);
1850 fgcolor_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, fgcolor_xpm
);
1851 fgcolor_p
= gtk_pixmap_new(fgcolor_i
, mask
);
1852 gtk_widget_show(fgcolor_p
);
1853 gdk_bitmap_unref(mask
);
1855 bgcolor_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, bgcolor_xpm
);
1856 bgcolor_p
= gtk_pixmap_new(bgcolor_i
, mask
);
1857 gtk_widget_show(bgcolor_p
);
1858 gdk_bitmap_unref(mask
);
1860 link_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, link_xpm
);
1861 link_p
= gtk_pixmap_new(link_i
, mask
);
1862 gtk_widget_show(link_p
);
1863 gdk_bitmap_unref(mask
);
1865 smiley_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, smile_icon_xpm
);
1866 smiley_p
= gtk_pixmap_new(smiley_i
, mask
);
1867 gtk_widget_show(smiley_p
);
1868 gdk_bitmap_unref(mask
);
1870 wood_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, wood_xpm
);
1871 wood_p
= gtk_pixmap_new(wood_i
, mask
);
1872 gtk_widget_show(wood_p
);
1873 gdk_bitmap_unref(mask
);
1875 save_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, save_small_xpm
);
1876 save_p
= gtk_pixmap_new(save_i
, mask
);
1877 gtk_widget_show(save_p
);
1878 gdk_bitmap_unref(mask
);
1880 speaker_i
= gdk_pixmap_create_from_xpm_d(win
->window
, &mask
, &win
->style
->white
, speaker_xpm
);
1881 speaker_p
= gtk_pixmap_new(speaker_i
, mask
);
1882 gtk_widget_show(speaker_p
);
1883 gdk_bitmap_unref(mask
);
1886 bold
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1887 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
, NULL
,
1888 NULL
, _("Bold Text"), _("Bold"), bold_p
,
1889 GTK_SIGNAL_FUNC(do_bold
), entry
);
1890 italic
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1891 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
,
1892 NULL
, NULL
, _("Italics Text"),
1893 _("Italics"), italic_p
, GTK_SIGNAL_FUNC(do_italic
), entry
);
1894 underline
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1895 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
,
1896 NULL
, NULL
, _("Underline Text"),
1897 _("Underline"), underline_p
,
1898 GTK_SIGNAL_FUNC(do_underline
), entry
);
1900 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
), GTK_TOOLBAR_CHILD_TOGGLEBUTTON
, NULL
,
1901 NULL
, _("Strike through Text"), _("Strike"), strike_p
,
1902 GTK_SIGNAL_FUNC(do_strike
), entry
);
1904 gtk_toolbar_append_space(GTK_TOOLBAR(toolbar
));
1906 small
= gtk_toolbar_append_item(GTK_TOOLBAR(toolbar
),
1907 NULL
, _("Decrease font size"), _("Small"),
1908 small_p
, GTK_SIGNAL_FUNC(do_small
), entry
);
1909 normal
= gtk_toolbar_append_item(GTK_TOOLBAR(toolbar
),
1910 NULL
, _("Normal font size"), _("Normal"),
1911 normal_p
, GTK_SIGNAL_FUNC(do_normal
), entry
);
1912 big
= gtk_toolbar_append_item(GTK_TOOLBAR(toolbar
),
1913 NULL
, _("Increase font size"), _("Big"),
1914 big_p
, GTK_SIGNAL_FUNC(do_big
), entry
);
1916 gtk_toolbar_append_space(GTK_TOOLBAR(toolbar
));
1918 font
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1919 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
,
1920 NULL
, NULL
, _("Select Font"),
1921 _("Font"), font_p
, GTK_SIGNAL_FUNC(toggle_font
), c
);
1922 fgcolorbtn
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1923 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
,
1924 NULL
, NULL
, _("Text Color"),
1925 _("Color"), fgcolor_p
, GTK_SIGNAL_FUNC(toggle_fg_color
),
1928 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
), GTK_TOOLBAR_CHILD_TOGGLEBUTTON
, NULL
,
1929 NULL
, _("Background Color"), _("Color"), bgcolor_p
,
1930 GTK_SIGNAL_FUNC(toggle_bg_color
), c
);
1932 gtk_toolbar_append_space(GTK_TOOLBAR(toolbar
));
1934 link
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1935 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
,
1936 NULL
, NULL
, _("Insert Link"),
1937 _("Link"), link_p
, GTK_SIGNAL_FUNC(toggle_link
), c
);
1938 smiley
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1939 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
,
1940 NULL
, NULL
, _("Insert smiley face"), _("Smiley"),
1941 smiley_p
, GTK_SIGNAL_FUNC(insert_smiley
), c
);
1943 gtk_toolbar_append_space(GTK_TOOLBAR(toolbar
));
1945 wood
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1946 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
,
1947 NULL
, NULL
, _("Enable logging"),
1948 _("Logging"), wood_p
, GTK_SIGNAL_FUNC(toggle_loggle
), c
);
1950 if (find_log_info(c
->name
))
1951 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(wood
), TRUE
);
1953 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(wood
), FALSE
);
1956 save
= gtk_toolbar_append_item(GTK_TOOLBAR(toolbar
),
1957 NULL
, _("Save Conversation"),
1958 _("Save"), save_p
, GTK_SIGNAL_FUNC(save_convo
), c
);
1960 speaker
= gtk_toolbar_append_element(GTK_TOOLBAR(toolbar
),
1961 GTK_TOOLBAR_CHILD_TOGGLEBUTTON
,
1962 NULL
, NULL
, _("Enable sounds"),
1963 _("Sound"), speaker_p
, GTK_SIGNAL_FUNC(set_option
),
1966 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(speaker
), TRUE
);
1968 /* use a slicker look if the user wants to */
1969 if (misc_options
& OPT_MISC_COOL_LOOK
) {
1970 gtk_button_set_relief(GTK_BUTTON(bold
), GTK_RELIEF_NONE
);
1971 gtk_button_set_relief(GTK_BUTTON(italic
), GTK_RELIEF_NONE
);
1972 gtk_button_set_relief(GTK_BUTTON(underline
), GTK_RELIEF_NONE
);
1973 gtk_button_set_relief(GTK_BUTTON(strike
), GTK_RELIEF_NONE
);
1974 gtk_button_set_relief(GTK_BUTTON(small
), GTK_RELIEF_NONE
);
1975 gtk_button_set_relief(GTK_BUTTON(normal
), GTK_RELIEF_NONE
);
1976 gtk_button_set_relief(GTK_BUTTON(big
), GTK_RELIEF_NONE
);
1977 gtk_button_set_relief(GTK_BUTTON(font
), GTK_RELIEF_NONE
);
1978 gtk_button_set_relief(GTK_BUTTON(fgcolorbtn
), GTK_RELIEF_NONE
);
1979 gtk_button_set_relief(GTK_BUTTON(bgcolorbtn
), GTK_RELIEF_NONE
);
1980 gtk_button_set_relief(GTK_BUTTON(link
), GTK_RELIEF_NONE
);
1981 gtk_button_set_relief(GTK_BUTTON(smiley
), GTK_RELIEF_NONE
);
1982 gtk_button_set_relief(GTK_BUTTON(wood
), GTK_RELIEF_NONE
);
1983 gtk_button_set_relief(GTK_BUTTON(save
), GTK_RELIEF_NONE
);
1984 gtk_button_set_relief(GTK_BUTTON(speaker
), GTK_RELIEF_NONE
);
1987 gtk_widget_show(toolbar
);
1989 gdk_pixmap_unref(bold_i
);
1990 gdk_pixmap_unref(italic_i
);
1991 gdk_pixmap_unref(underline_i
);
1992 gdk_pixmap_unref(strike_i
);
1993 gdk_pixmap_unref(small_i
);
1994 gdk_pixmap_unref(normal_i
);
1995 gdk_pixmap_unref(big_i
);
1996 gdk_pixmap_unref(font_i
);
1997 gdk_pixmap_unref(fgcolor_i
);
1998 gdk_pixmap_unref(bgcolor_i
);
1999 gdk_pixmap_unref(link_i
);
2000 gdk_pixmap_unref(smiley_i
);
2001 gdk_pixmap_unref(wood_i
);
2002 gdk_pixmap_unref(save_i
);
2003 gdk_pixmap_unref(speaker_i
);
2008 c
->underline
= underline
;
2009 c
->log_button
= wood
;
2010 c
->fgcolorbtn
= fgcolorbtn
;
2011 c
->bgcolorbtn
= bgcolorbtn
;
2017 gtk_widget_set_sensitive(c
->log_button
, ((logging_options
& OPT_LOG_ALL
)) ? FALSE
: TRUE
);
2019 gtk_widget_set_sensitive(c
->bold
, ((font_options
& OPT_FONT_BOLD
)) ? FALSE
: TRUE
);
2020 gtk_widget_set_sensitive(c
->italic
, ((font_options
& OPT_FONT_ITALIC
)) ? FALSE
: TRUE
);
2021 gtk_widget_set_sensitive(c
->underline
, ((font_options
& OPT_FONT_UNDERLINE
)) ? FALSE
: TRUE
);
2022 gtk_widget_set_sensitive(c
->strike
, ((font_options
& OPT_FONT_STRIKE
)) ? FALSE
: TRUE
);
2027 static void convo_sel_send(GtkObject
*m
, struct gaim_connection
*c
)
2029 struct conversation
*cnv
= gtk_object_get_user_data(m
);
2036 set_convo_title(cnv
);
2038 update_buttons_by_protocol(cnv
);
2041 update_checkbox(cnv
);
2044 int set_dispstyle(int chat
)
2049 switch (chat_options
& (OPT_CHAT_BUTTON_TEXT
| OPT_CHAT_BUTTON_XPM
)) {
2050 case OPT_CHAT_BUTTON_TEXT
:
2053 case OPT_CHAT_BUTTON_XPM
:
2056 default: /* both or neither */
2061 switch (im_options
& (OPT_IM_BUTTON_TEXT
| OPT_IM_BUTTON_XPM
)) {
2062 case OPT_IM_BUTTON_TEXT
:
2065 case OPT_IM_BUTTON_XPM
:
2068 default: /* both or neither */
2076 void update_convo_add_button(struct conversation
*c
)
2078 int dispstyle
= set_dispstyle(0);
2079 GtkWidget
*parent
= c
->add
->parent
;
2080 gboolean rebuild
= FALSE
;
2082 if (find_buddy(c
->gc
, c
->name
)) {
2083 if (!gtk_object_get_user_data(GTK_OBJECT(c
->add
))) {
2084 gtk_widget_destroy(c
->add
);
2085 c
->add
= picture_button2(c
->window
, _("Remove"), gnome_remove_xpm
, dispstyle
);
2089 if (c
->gc
->prpl
->remove_buddy
== NULL
)
2090 gtk_widget_set_sensitive(c
->add
, FALSE
);
2092 gtk_widget_set_sensitive(c
->add
, TRUE
);
2094 gtk_widget_set_sensitive(c
->add
, FALSE
);
2095 gtk_object_set_user_data(GTK_OBJECT(c
->add
), c
);
2097 if (gtk_object_get_user_data(GTK_OBJECT(c
->add
))) {
2098 gtk_widget_destroy(c
->add
);
2099 c
->add
= picture_button2(c
->window
, _("Add"), gnome_add_xpm
, dispstyle
);
2103 if (c
->gc
->prpl
->add_buddy
== NULL
)
2104 gtk_widget_set_sensitive(c
->add
, FALSE
);
2106 gtk_widget_set_sensitive(c
->add
, TRUE
);
2108 gtk_widget_set_sensitive(c
->add
, FALSE
);
2112 gtk_signal_connect(GTK_OBJECT(c
->add
), "clicked", GTK_SIGNAL_FUNC(add_callback
), c
);
2113 gtk_box_pack_end(GTK_BOX(parent
), c
->add
, dispstyle
, dispstyle
, 0);
2114 gtk_box_reorder_child(GTK_BOX(parent
), c
->add
, 2);
2115 gtk_widget_show(c
->add
);
2119 static void create_convo_menu(struct conversation
*cnv
)
2121 GtkWidget
*menu
, *opt
;
2122 GSList
*g
= connections
;
2123 struct gaim_connection
*c
;
2126 if (g_slist_length(g
) < 2)
2127 gtk_widget_hide(cnv
->menu
->parent
);
2129 menu
= gtk_menu_new();
2132 c
= (struct gaim_connection
*)g
->data
;
2133 g_snprintf(buf
, sizeof buf
, "%s (%s)", c
->username
, c
->prpl
->name());
2134 opt
= gtk_menu_item_new_with_label(buf
);
2135 gtk_object_set_user_data(GTK_OBJECT(opt
), cnv
);
2136 gtk_signal_connect(GTK_OBJECT(opt
), "activate",
2137 GTK_SIGNAL_FUNC(convo_sel_send
), c
);
2138 gtk_widget_show(opt
);
2139 gtk_menu_append(GTK_MENU(menu
), opt
);
2143 gtk_option_menu_remove_menu(GTK_OPTION_MENU(cnv
->menu
));
2144 gtk_option_menu_set_menu(GTK_OPTION_MENU(cnv
->menu
), menu
);
2145 gtk_option_menu_set_history(GTK_OPTION_MENU(cnv
->menu
), 0);
2147 gtk_widget_show(cnv
->menu
);
2148 gtk_widget_show(cnv
->menu
->parent
);
2152 void redo_convo_menus()
2154 GList
*c
= conversations
;
2155 struct conversation
*C
;
2158 C
= (struct conversation
*)c
->data
;
2161 create_convo_menu(C
);
2163 if (g_slist_find(connections
, C
->gc
))
2164 set_convo_gc(C
, C
->gc
);
2166 set_convo_gc(C
, connections
? connections
->data
: NULL
);
2170 void convo_menu_remove(struct gaim_connection
*gc
)
2172 GList
*c
= conversations
;
2173 struct conversation
*C
;
2176 C
= (struct conversation
*)c
->data
;
2184 void set_convo_gc(struct conversation
*c
, struct gaim_connection
*gc
)
2187 gtk_option_menu_set_history(GTK_OPTION_MENU(c
->menu
), g_slist_index(connections
, gc
));
2196 update_buttons_by_protocol(c
);
2202 void update_buttons_by_protocol(struct conversation
*c
)
2206 gtk_widget_set_sensitive(c
->info
, FALSE
);
2208 gtk_widget_set_sensitive(c
->send
, FALSE
);
2210 gtk_widget_set_sensitive(c
->warn
, FALSE
);
2212 gtk_widget_set_sensitive(c
->block
, FALSE
);
2214 gtk_widget_set_sensitive(c
->add
, FALSE
);
2216 gtk_widget_set_sensitive(c
->whisper
, FALSE
);
2218 gtk_widget_set_sensitive(c
->invite
, FALSE
);
2223 if (c
->gc
->prpl
->get_info
== NULL
&& c
->info
)
2224 gtk_widget_set_sensitive(c
->info
, FALSE
);
2226 gtk_widget_set_sensitive(c
->info
, TRUE
);
2229 if (c
->gc
->prpl
->chat_send
== NULL
&& c
->send
)
2230 gtk_widget_set_sensitive(c
->send
, FALSE
);
2232 gtk_widget_set_sensitive(c
->send
, TRUE
);
2234 if (c
->gc
->prpl
->send_im
== NULL
&& c
->send
)
2235 gtk_widget_set_sensitive(c
->send
, FALSE
);
2237 gtk_widget_set_sensitive(c
->send
, TRUE
);
2240 if (c
->gc
->prpl
->warn
== NULL
&& c
->warn
)
2241 gtk_widget_set_sensitive(c
->warn
, FALSE
);
2243 gtk_widget_set_sensitive(c
->warn
, TRUE
);
2245 if (c
->gc
->prpl
->add_permit
== NULL
&& c
->block
)
2246 gtk_widget_set_sensitive(c
->block
, FALSE
);
2248 gtk_widget_set_sensitive(c
->block
, TRUE
);
2251 update_convo_add_button(c
);
2254 if (c
->gc
->prpl
->chat_whisper
== NULL
)
2255 gtk_widget_set_sensitive(c
->whisper
, FALSE
);
2257 gtk_widget_set_sensitive(c
->whisper
, TRUE
);
2261 if (c
->gc
->prpl
->chat_invite
== NULL
)
2262 gtk_widget_set_sensitive(c
->invite
, FALSE
);
2264 gtk_widget_set_sensitive(c
->invite
, TRUE
);
2268 void convo_switch(GtkNotebook
*notebook
, GtkWidget
*page
, gint page_num
, gpointer data
)
2270 GtkWidget
*label
= gtk_notebook_get_tab_label(notebook
,
2271 gtk_notebook_get_nth_page(notebook
, page_num
));
2273 struct conversation
*c
;
2274 if ((convo_options
& OPT_CONVO_COMBINE
) &&
2275 (im_options
& OPT_IM_ONE_WINDOW
) &&
2276 (chat_options
& OPT_CHAT_ONE_WINDOW
)) {
2277 int len
= g_list_length(conversations
);
2279 c
= g_list_nth_data(conversations
, page_num
);
2281 c
= g_list_nth_data(chats
, page_num
- len
);
2282 } else if (GTK_WIDGET(notebook
) == convo_notebook
)
2283 c
= g_list_nth_data(conversations
, page_num
);
2285 c
= g_list_nth_data(chats
, page_num
);
2286 if (c
&& c
->window
&& c
->entry
)
2287 gtk_window_set_focus(GTK_WINDOW(c
->window
), c
->entry
);
2288 if (!GTK_WIDGET_REALIZED(label
))
2290 if (c
->unseen
== -1) return;
2291 style
= gtk_style_new();
2292 gdk_font_unref(gtk_style_get_font(style
));
2293 gtk_style_set_font(style
, gdk_font_ref(gtk_style_get_font(label
->style
)));
2294 gtk_widget_set_style(label
, style
);
2295 gtk_style_unref(style
);
2300 void show_typing(struct conversation
*c
) {
2303 GtkNotebook
*notebook
= GTK_NOTEBOOK(c
->is_chat
? chat_notebook
: convo_notebook
);
2304 int offs
= ((convo_options
& OPT_CONVO_COMBINE
) &&
2305 (im_options
& OPT_IM_ONE_WINDOW
) && c
->is_chat
) ?
2306 g_list_length(conversations
) : 0;
2307 GList
*ws
= (c
->is_chat
? chats
: conversations
);
2308 GtkWidget
*label
= gtk_notebook_get_tab_label(notebook
,
2309 gtk_notebook_get_nth_page(notebook
,
2310 offs
+ g_list_index(ws
, c
)));
2311 if (c
->is_chat
) /* We shouldn't be getting typing notifications from chats. */
2313 if (im_options
& OPT_IM_ONE_WINDOW
) { /* We'll make the tab green */
2315 style
= gtk_style_new();
2316 if (!GTK_WIDGET_REALIZED(label
))
2317 gtk_widget_realize(label
);
2318 gdk_font_unref(gtk_style_get_font(style
));
2319 gtk_style_set_font(style
, gdk_font_ref(gtk_style_get_font(label
->style
)));
2320 style
->fg
[0].red
= 0x0000;
2321 style
->fg
[0].green
= 0x9999;
2322 style
->fg
[0].blue
= 0x0000;
2323 gtk_widget_set_style(label
, style
);
2324 debug_printf("setting style\n");
2325 gtk_style_unref(style
);
2328 GtkWindow
*win
= (GtkWindow
*)c
->window
;
2330 if (strstr(win
->title
, " [TYPING]"))
2332 buf
= g_malloc(strlen(win
->title
) + strlen(" [TYPING]") + 1);
2334 strlen(win
->title
) + strlen(" [TYPING]") + 1, "%s [TYPING]",
2336 gtk_window_set_title(win
, buf
);
2342 /* This returns a boolean, so that it can timeout */
2343 gboolean
reset_typing(char *name
) {
2344 struct conversation
*c
= find_conversation(name
);
2349 /* Reset the title (if necessary) */
2350 debug_printf("resetting style\n");
2353 c
->typing_timeout
= 0;
2356 if (!(im_options
& OPT_IM_ONE_WINDOW
)) {
2357 GtkWindow
*win
= (GtkWindow
*)c
->window
;
2359 if (strstr(win
->title
, " [TYPING]")) {
2360 new_title
= g_malloc(strlen(win
->title
) - strlen("[TYPING]"));
2361 g_snprintf(new_title
, strlen(win
->title
) - strlen("[TYPING]"), win
->title
);
2362 gtk_window_set_title(win
, new_title
);
2366 } else if (c
->unseen
== -1) {
2367 GtkNotebook
*notebook
= GTK_NOTEBOOK(convo_notebook
);
2368 int offs
= ((convo_options
& OPT_CONVO_COMBINE
) &&
2369 (im_options
& OPT_IM_ONE_WINDOW
) && c
->is_chat
) ?
2370 g_list_length(conversations
) : 0;
2371 GList
*ws
= (conversations
);
2372 GtkWidget
*label
= gtk_notebook_get_tab_label(notebook
,
2373 gtk_notebook_get_nth_page(notebook
,
2374 offs
+ g_list_index(ws
, c
)));
2376 style
= gtk_style_new();
2377 if (!GTK_WIDGET_REALIZED(label
))
2378 gtk_widget_realize(label
);
2379 gdk_font_unref(gtk_style_get_font(style
));
2380 gtk_style_set_font(style
, gdk_font_ref(gtk_style_get_font(label
->style
)));
2382 gtk_widget_set_style(label
, style
);
2383 gtk_style_unref(style
);
2386 c
->typing_timeout
= 0;
2390 void show_conv(struct conversation
*c
)
2410 int dispstyle
= set_dispstyle(0);
2412 c
->font_dialog
= NULL
;
2413 c
->fg_color_dialog
= NULL
;
2414 c
->bg_color_dialog
= NULL
;
2415 c
->smiley_dialog
= NULL
;
2416 c
->link_dialog
= NULL
;
2417 c
->log_dialog
= NULL
;
2418 sprintf(c
->fontxfld
, "%s", fontxfld
);
2419 sprintf(c
->fontface
, "%s", fontface
);
2426 if (im_options
& OPT_IM_ONE_WINDOW
) {
2428 win
= all_convos
= c
->window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
2429 if ((convo_options
& OPT_CONVO_COMBINE
) && (chat_options
& OPT_CHAT_ONE_WINDOW
))
2430 all_chats
= all_convos
;
2431 gtk_window_set_wmclass(GTK_WINDOW(win
), "conversation", "Gaim");
2432 gtk_window_set_policy(GTK_WINDOW(win
), TRUE
, TRUE
, FALSE
);
2433 gtk_container_border_width(GTK_CONTAINER(win
), 0);
2434 gtk_widget_realize(win
);
2435 aol_icon(win
->window
);
2436 gtk_window_set_title(GTK_WINDOW(win
), _("Gaim - Conversations"));
2437 gtk_signal_connect(GTK_OBJECT(win
), "delete_event",
2438 GTK_SIGNAL_FUNC(delete_all_convo
), NULL
);
2440 convo_notebook
= gtk_notebook_new();
2441 if ((convo_options
& OPT_CONVO_COMBINE
) && (chat_options
& OPT_CHAT_ONE_WINDOW
))
2442 chat_notebook
= convo_notebook
;
2443 if (im_options
& OPT_IM_SIDE_TAB
) {
2444 if (im_options
& OPT_IM_BR_TAB
) {
2445 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook
),
2448 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook
),
2452 if (im_options
& OPT_IM_BR_TAB
) {
2453 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook
),
2456 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook
),
2460 gtk_notebook_set_scrollable(GTK_NOTEBOOK(convo_notebook
), TRUE
);
2461 gtk_notebook_popup_enable(GTK_NOTEBOOK(convo_notebook
));
2462 gtk_container_add(GTK_CONTAINER(win
), convo_notebook
);
2463 gtk_signal_connect(GTK_OBJECT(convo_notebook
), "switch-page",
2464 GTK_SIGNAL_FUNC(convo_switch
), NULL
);
2465 gtk_widget_show(convo_notebook
);
2467 win
= c
->window
= all_convos
;
2469 cont
= gtk_vbox_new(FALSE
, 5);
2470 gtk_container_set_border_width(GTK_CONTAINER(cont
), 5);
2471 /* this doesn't matter since we're resetting the name once we're out of the if */
2472 gtk_notebook_insert_page(GTK_NOTEBOOK(convo_notebook
), cont
, gtk_label_new(c
->name
),
2473 g_list_index(conversations
, c
));
2474 gtk_widget_show(cont
);
2476 cont
= win
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
2478 gtk_object_set_user_data(GTK_OBJECT(win
), c
);
2479 gtk_window_set_wmclass(GTK_WINDOW(win
), "conversation", "Gaim");
2480 gtk_window_set_policy(GTK_WINDOW(win
), TRUE
, TRUE
, TRUE
);
2481 gtk_container_border_width(GTK_CONTAINER(win
), 10);
2482 gtk_widget_realize(win
);
2483 aol_icon(win
->window
);
2484 gtk_signal_connect(GTK_OBJECT(win
), "delete_event",
2485 GTK_SIGNAL_FUNC(delete_event_convo
), c
);
2489 paned
= gtk_vpaned_new();
2490 gtk_paned_set_gutter_size(GTK_PANED(paned
), 15);
2491 gtk_container_add(GTK_CONTAINER(cont
), paned
);
2492 gtk_widget_show(paned
);
2494 vbox
= gtk_vbox_new(FALSE
, 5);
2495 gtk_paned_pack1(GTK_PANED(paned
), vbox
, FALSE
, TRUE
);
2496 gtk_widget_show(vbox
);
2498 sw
= gtk_scrolled_window_new(NULL
, NULL
);
2500 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw
), GTK_POLICY_NEVER
, GTK_POLICY_ALWAYS
);
2501 gtk_box_pack_start(GTK_BOX(vbox
), sw
, TRUE
, TRUE
, 0);
2502 gtk_widget_set_usize(sw
, conv_size
.width
, conv_size
.height
);
2503 gtk_widget_show(sw
);
2505 text
= gtk_imhtml_new(NULL
, NULL
);
2507 gtk_container_add(GTK_CONTAINER(sw
), text
);
2508 GTK_LAYOUT(text
)->hadjustment
->step_increment
= 10.0;
2509 GTK_LAYOUT(text
)->vadjustment
->step_increment
= 10.0;
2510 if (convo_options
& OPT_CONVO_SHOW_TIME
)
2511 gtk_imhtml_show_comments(GTK_IMHTML(text
), TRUE
);
2512 gaim_setup_imhtml(text
);
2513 gtk_widget_show(text
);
2515 vbox2
= gtk_vbox_new(FALSE
, 5);
2516 gtk_paned_pack2(GTK_PANED(paned
), vbox2
, FALSE
, FALSE
);
2517 gtk_widget_show(vbox2
);
2519 hbox
= gtk_hbox_new(FALSE
, 0);
2520 gtk_box_pack_start(GTK_BOX(vbox2
), hbox
, FALSE
, FALSE
, 0);
2521 gtk_widget_show(hbox
);
2523 label
= gtk_label_new(_("Send message as: "));
2524 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 5);
2525 gtk_widget_show(label
);
2527 c
->menu
= gtk_option_menu_new();
2528 gtk_box_pack_start(GTK_BOX(hbox
), c
->menu
, FALSE
, FALSE
, 5);
2529 gtk_widget_show(c
->menu
);
2531 create_convo_menu(c
);
2533 c
->lbox
= gtk_hbox_new(FALSE
, 0);
2534 gtk_box_pack_start(GTK_BOX(vbox2
), c
->lbox
, FALSE
, FALSE
, 0);
2535 gtk_widget_show(c
->lbox
);
2537 entry
= gtk_text_new(NULL
, NULL
);
2539 if (!(im_options
& OPT_IM_ONE_WINDOW
))
2540 gtk_window_set_focus(GTK_WINDOW(c
->window
), c
->entry
);
2542 toolbar
= build_conv_toolbar(c
);
2543 gtk_box_pack_start(GTK_BOX(vbox2
), toolbar
, FALSE
, FALSE
, 0);
2545 gtk_object_set_user_data(GTK_OBJECT(entry
), c
);
2546 gtk_text_set_editable(GTK_TEXT(entry
), TRUE
);
2547 gtk_text_set_word_wrap(GTK_TEXT(entry
), TRUE
);
2548 gtk_widget_set_usize(entry
, conv_size
.width
- 20, MAX(conv_size
.entry_height
, 25));
2550 gtk_signal_connect(GTK_OBJECT(entry
), "activate", GTK_SIGNAL_FUNC(send_callback
), c
);
2551 gtk_signal_connect(GTK_OBJECT(entry
), "key_press_event", GTK_SIGNAL_FUNC(keypress_callback
), c
);
2552 gtk_signal_connect(GTK_OBJECT(entry
), "key_press_event", GTK_SIGNAL_FUNC(entry_key_pressed
),
2554 if (convo_options
& OPT_CONVO_CHECK_SPELLING
)
2555 gtkspell_attach(GTK_TEXT(c
->entry
));
2556 gtk_box_pack_start(GTK_BOX(vbox2
), entry
, TRUE
, TRUE
, 0);
2557 gtk_widget_show(entry
);
2559 c
->bbox
= bbox
= gtk_hbox_new(FALSE
, 5);
2560 gtk_box_pack_start(GTK_BOX(vbox2
), bbox
, FALSE
, FALSE
, 0);
2561 gtk_widget_show(bbox
);
2563 close
= picture_button2(win
, _("Close"), cancel_xpm
, dispstyle
);
2565 gtk_object_set_user_data(GTK_OBJECT(close
), c
);
2566 gtk_signal_connect(GTK_OBJECT(close
), "clicked", GTK_SIGNAL_FUNC(close_callback
), c
);
2567 gtk_box_pack_end(GTK_BOX(bbox
), close
, dispstyle
, dispstyle
, 0);
2568 gtk_widget_show(close
);
2570 c
->sep1
= gtk_vseparator_new();
2571 gtk_box_pack_end(GTK_BOX(bbox
), c
->sep1
, dispstyle
, dispstyle
, 0);
2572 gtk_widget_show(c
->sep1
);
2574 if (c
->gc
&& find_buddy(c
->gc
, c
->name
) != NULL
) {
2575 add
= picture_button2(win
, _("Remove"), gnome_remove_xpm
, dispstyle
);
2576 gtk_object_set_user_data(GTK_OBJECT(add
), c
);
2578 add
= picture_button2(win
, _("Add"), gnome_add_xpm
, dispstyle
);
2580 gtk_signal_connect(GTK_OBJECT(add
), "clicked", GTK_SIGNAL_FUNC(add_callback
), c
);
2581 gtk_box_pack_end(GTK_BOX(bbox
), add
, dispstyle
, dispstyle
, 0);
2582 gtk_widget_show(add
);
2584 block
= picture_button2(win
, _("Block"), block_xpm
, dispstyle
);
2586 gtk_signal_connect(GTK_OBJECT(block
), "clicked", GTK_SIGNAL_FUNC(block_callback
), c
);
2587 gtk_box_pack_end(GTK_BOX(bbox
), block
, dispstyle
, dispstyle
, 0);
2588 gtk_widget_show(block
);
2590 warn
= picture_button2(win
, _("Warn"), warn_xpm
, dispstyle
);
2592 gtk_signal_connect(GTK_OBJECT(warn
), "clicked", GTK_SIGNAL_FUNC(warn_callback
), c
);
2593 gtk_box_pack_end(GTK_BOX(bbox
), warn
, dispstyle
, dispstyle
, 0);
2594 gtk_widget_show(warn
);
2596 info
= picture_button2(win
, _("Info"), tb_search_xpm
, dispstyle
);
2599 gtk_signal_connect(GTK_OBJECT(info
), "clicked", GTK_SIGNAL_FUNC(info_callback
), c
);
2600 gtk_box_pack_end(GTK_BOX(bbox
), info
, dispstyle
, dispstyle
, 0);
2601 gtk_widget_show(info
);
2603 c
->sep2
= gtk_vseparator_new();
2604 gtk_box_pack_end(GTK_BOX(bbox
), c
->sep2
, dispstyle
, dispstyle
, 0);
2605 gtk_widget_show(c
->sep2
);
2607 send
= picture_button2(win
, _("Send"), tmp_send_xpm
, dispstyle
);
2609 gtk_signal_connect(GTK_OBJECT(send
), "clicked", GTK_SIGNAL_FUNC(send_callback
), c
);
2610 gtk_box_pack_end(GTK_BOX(bbox
), send
, dispstyle
, dispstyle
, 0);
2611 gtk_widget_show(send
);
2613 update_buttons_by_protocol(c
);
2615 gtk_widget_show(win
);
2619 void toggle_spellchk()
2621 GList
*cnv
= conversations
;
2623 struct conversation
*c
;
2624 GSList
*con
= connections
;
2625 struct gaim_connection
*gc
;
2627 if (convo_options
& OPT_CONVO_CHECK_SPELLING
)
2628 gtkspell_start(NULL
, ispell_cmd
);
2631 c
= (struct conversation
*)cnv
->data
;
2632 if (convo_options
& OPT_CONVO_CHECK_SPELLING
)
2633 gtkspell_attach(GTK_TEXT(c
->entry
));
2635 gtkspell_detach(GTK_TEXT(c
->entry
));
2640 gc
= (struct gaim_connection
*)con
->data
;
2641 cht
= gc
->buddy_chats
;
2643 c
= (struct conversation
*)cht
->data
;
2644 if (convo_options
& OPT_CONVO_CHECK_SPELLING
)
2645 gtkspell_attach(GTK_TEXT(c
->entry
));
2647 gtkspell_detach(GTK_TEXT(c
->entry
));
2653 if (!(convo_options
& OPT_CONVO_CHECK_SPELLING
))
2657 void toggle_timestamps()
2659 GList
*cnv
= conversations
;
2661 struct conversation
*c
;
2662 GSList
*con
= connections
;
2663 struct gaim_connection
*gc
;
2666 c
= (struct conversation
*)cnv
->data
;
2667 if (convo_options
& OPT_CONVO_SHOW_TIME
)
2668 gtk_imhtml_show_comments(GTK_IMHTML(c
->text
), TRUE
);
2670 gtk_imhtml_show_comments(GTK_IMHTML(c
->text
), FALSE
);
2675 gc
= (struct gaim_connection
*)con
->data
;
2676 cht
= gc
->buddy_chats
;
2678 c
= (struct conversation
*)cht
->data
;
2679 if (convo_options
& OPT_CONVO_SHOW_TIME
)
2680 gtk_imhtml_show_comments(GTK_IMHTML(c
->text
), TRUE
);
2682 gtk_imhtml_show_comments(GTK_IMHTML(c
->text
), FALSE
);
2689 void toggle_smileys()
2691 GList
*cnv
= conversations
;
2693 struct conversation
*c
;
2694 GSList
*con
= connections
;
2695 struct gaim_connection
*gc
;
2698 c
= (struct conversation
*)cnv
->data
;
2699 if (convo_options
& OPT_CONVO_SHOW_SMILEY
)
2700 gtk_imhtml_show_smileys(GTK_IMHTML(c
->text
), TRUE
);
2702 gtk_imhtml_show_smileys(GTK_IMHTML(c
->text
), FALSE
);
2707 gc
= (struct gaim_connection
*)con
->data
;
2708 cht
= gc
->buddy_chats
;
2710 c
= (struct conversation
*)cht
->data
;
2711 if (convo_options
& OPT_CONVO_SHOW_SMILEY
)
2712 gtk_imhtml_show_smileys(GTK_IMHTML(c
->text
), TRUE
);
2714 gtk_imhtml_show_smileys(GTK_IMHTML(c
->text
), FALSE
);
2723 /* evil, evil i tell you! evil! */
2724 if (im_options
& OPT_IM_ONE_WINDOW
) {
2725 GList
*x
= conversations
;
2726 if ((convo_options
& OPT_CONVO_COMBINE
) && (chat_options
& OPT_CHAT_ONE_WINDOW
)) {
2727 all_convos
= all_chats
;
2728 convo_notebook
= chat_notebook
;
2731 struct conversation
*c
= x
->data
;
2732 GtkWidget
*imhtml
, *win
;
2739 gtk_widget_destroy(c
->text
);
2740 gtk_widget_reparent(imhtml
, c
->sw
);
2742 gtk_widget_destroy(win
);
2751 x
= m
= conversations
;
2752 conversations
= NULL
;
2754 struct conversation
*c
= x
->data
;
2761 gtk_container_remove(GTK_CONTAINER(c
->sw
), c
->text
);
2762 gtk_widget_reparent(imhtml
, c
->sw
);
2771 if ((convo_options
& OPT_CONVO_COMBINE
) && (chat_options
& OPT_CHAT_ONE_WINDOW
)) {
2773 struct conversation
*c
;
2775 gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook
), 0);
2779 gtk_window_set_focus(GTK_WINDOW(c
->window
), c
->entry
);
2782 gtk_widget_destroy(all_convos
);
2784 chat_notebook
= NULL
;
2786 } else if (all_convos
)
2787 gtk_widget_destroy(all_convos
);
2789 convo_notebook
= NULL
;
2798 if (!chats
&& !conversations
)
2801 if (convo_options
& OPT_CONVO_COMBINE
) {
2803 all_chats
= all_convos
;
2804 chat_notebook
= convo_notebook
;
2806 } else if (!conversations
) {
2807 all_convos
= all_chats
;
2808 convo_notebook
= chat_notebook
;
2814 chat_notebook
= NULL
;
2816 } else if (!conversations
) {
2818 convo_notebook
= NULL
;
2824 if (convo_options
& OPT_CONVO_COMBINE
) {
2825 all_convos
= all_chats
;
2826 convo_notebook
= chat_notebook
;
2829 convo_notebook
= NULL
;
2831 x
= m
= conversations
;
2833 struct conversation
*c
= x
->data
;
2840 gtk_container_remove(GTK_CONTAINER(c
->sw
), c
->text
);
2841 gtk_widget_reparent(imhtml
, c
->sw
);
2850 if (convo_options
& OPT_CONVO_COMBINE
) {
2852 gtk_widget_destroy(tmp
);
2855 gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook
), 0);
2861 set_convo_title(m
->data
);
2866 void set_convo_title(struct conversation
*c
)
2873 if ((im_options
& OPT_IM_ALIAS_TAB
) && c
->gc
&& ((b
= find_buddy(c
->gc
, c
->name
)) != NULL
))
2878 if (im_options
& OPT_IM_ONE_WINDOW
) {
2879 nb
= GTK_NOTEBOOK(convo_notebook
);
2880 index
= g_list_index(conversations
, c
);
2881 gtk_notebook_set_tab_label_text(nb
, gtk_notebook_get_nth_page(nb
, index
), text
);
2884 if ((find_log_info(c
->name
)) || (logging_options
& OPT_LOG_ALL
))
2885 g_snprintf(buf
, sizeof(buf
), LOG_CONVERSATION_TITLE
, text
);
2887 g_snprintf(buf
, sizeof(buf
), CONVERSATION_TITLE
, text
);
2888 gtk_window_set_title(GTK_WINDOW(c
->window
), buf
);
2892 void set_convo_titles()
2894 GList
*c
= conversations
;
2896 set_convo_title(c
->data
);
2901 void raise_convo_tab(struct conversation
*c
)
2903 gtk_notebook_set_page(GTK_NOTEBOOK(convo_notebook
), g_list_index(conversations
, c
));
2904 gdk_window_show(c
->window
->window
);
2907 void update_im_tabs()
2909 if (!convo_notebook
|| !all_convos
)
2911 if (im_options
& OPT_IM_SIDE_TAB
) {
2912 if (im_options
& OPT_IM_BR_TAB
) {
2913 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook
), GTK_POS_RIGHT
);
2915 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook
), GTK_POS_LEFT
);
2918 if (im_options
& OPT_IM_BR_TAB
) {
2919 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook
), GTK_POS_BOTTOM
);
2921 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook
), GTK_POS_TOP
);
2926 void update_chat_tabs()
2928 if (!chat_notebook
|| !all_chats
)
2930 if (chat_options
& OPT_CHAT_SIDE_TAB
) {
2931 if (chat_options
& OPT_CHAT_BR_TAB
) {
2932 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook
), GTK_POS_RIGHT
);
2934 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook
), GTK_POS_LEFT
);
2937 if (chat_options
& OPT_CHAT_BR_TAB
) {
2938 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook
), GTK_POS_BOTTOM
);
2940 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook
), GTK_POS_TOP
);
2945 void update_convo_color(gboolean fg
)
2947 GList
*c
= conversations
;
2948 struct conversation
*b
;
2965 void update_convo_font()
2967 GList
*c
= conversations
;
2968 struct conversation
*b
;
2975 sprintf(b
->fontface
, "%s", fontface
);
2976 sprintf(b
->fontxfld
, "%s", fontxfld
);
2981 #include <gdk-pixbuf/gdk-pixbuf.h>
2983 #define SCALE(x) ((gdk_pixbuf_animation_get_width(x) <= 48 && gdk_pixbuf_animation_get_height(x) <= 48) \
2986 static gboolean
redraw_icon(gpointer data
)
2988 struct conversation
*c
= data
;
2991 GdkPixbufFrame
*frame
;
3000 if (!g_list_find(conversations
, c
)) {
3001 debug_printf("I think this is a bug.\n");
3005 frames
= gdk_pixbuf_animation_get_frames(c
->anim
);
3006 frame
= g_list_nth_data(frames
, c
->frame
);
3007 switch (gdk_pixbuf_frame_get_action(frame
)) {
3008 case GDK_PIXBUF_FRAME_RETAIN
:
3009 buf
= gdk_pixbuf_frame_get_pixbuf(frame
);
3010 scale
= gdk_pixbuf_scale_simple(buf
,
3011 MAX(gdk_pixbuf_get_width(buf
) * SCALE(c
->anim
) /
3012 gdk_pixbuf_animation_get_width(c
->anim
), 1),
3013 MAX(gdk_pixbuf_get_height(buf
) * SCALE(c
->anim
) /
3014 gdk_pixbuf_animation_get_height(c
->anim
), 1),
3015 GDK_INTERP_NEAREST
);
3016 gdk_pixbuf_render_pixmap_and_mask(scale
, &src
, &bm
, 100);
3017 gdk_pixbuf_unref(scale
);
3018 gtk_pixmap_get(GTK_PIXMAP(c
->icon
), &pm
, NULL
);
3019 gc
= gdk_gc_new(pm
);
3020 gdk_gc_set_clip_mask(gc
, bm
);
3022 gdk_gc_set_clip_origin(gc
, gdk_pixbuf_frame_get_x_offset(frame
) *
3023 SCALE(c
->anim
)/gdk_pixbuf_get_width(scale
),
3024 gdk_pixbuf_frame_get_y_offset(frame
));
3025 gdk_draw_pixmap(pm
, gc
, src
, 0, 0, gdk_pixbuf_frame_get_x_offset(frame
)*
3026 SCALE(c
->anim
)/gdk_pixbuf_get_width(scale
),
3027 gdk_pixbuf_frame_get_y_offset(frame
),-1,-1);
3029 gdk_pixmap_unref(src
);
3030 gtk_widget_queue_draw(c
->icon
);
3033 case GDK_PIXBUF_FRAME_DISPOSE
:
3034 buf
= gdk_pixbuf_frame_get_pixbuf(frame
);
3035 scale
= gdk_pixbuf_scale_simple(buf
,
3036 MAX(gdk_pixbuf_get_width(buf
) * SCALE(c
->anim
) /
3037 gdk_pixbuf_animation_get_width(c
->anim
), 1),
3038 MAX(gdk_pixbuf_get_height(buf
) * SCALE(c
->anim
) /
3039 gdk_pixbuf_animation_get_height(c
->anim
), 1),
3040 GDK_INTERP_NEAREST
);
3041 gdk_pixbuf_render_pixmap_and_mask(scale
, &pm
, &bm
, 100);
3042 gdk_pixbuf_unref(scale
);
3043 gtk_pixmap_set(GTK_PIXMAP(c
->icon
), pm
, bm
);
3044 gdk_pixmap_unref(pm
);
3046 gdk_bitmap_unref(bm
);
3048 case GDK_PIXBUF_FRAME_REVERT
:
3049 frame
= frames
->data
;
3050 buf
= gdk_pixbuf_frame_get_pixbuf(frame
);
3051 scale
= gdk_pixbuf_scale_simple(buf
,
3052 MAX(gdk_pixbuf_get_width(buf
) * SCALE(c
->anim
) /
3053 gdk_pixbuf_animation_get_width(c
->anim
), 1),
3054 MAX(gdk_pixbuf_get_height(buf
) * SCALE(c
->anim
) /
3055 gdk_pixbuf_animation_get_height(c
->anim
), 1),
3056 GDK_INTERP_NEAREST
);
3057 gdk_pixbuf_render_pixmap_and_mask(scale
, &pm
, &bm
, 100);
3058 gdk_pixbuf_unref(scale
);
3059 gtk_pixmap_set(GTK_PIXMAP(c
->icon
), pm
, bm
);
3060 gdk_pixmap_unref(pm
);
3062 gdk_bitmap_unref(bm
);
3066 c
->frame
= (c
->frame
+ 1) % g_list_length(frames
);
3067 delay
= MAX(gdk_pixbuf_frame_get_delay_time(frame
), 13);
3068 c
->icon_timer
= gtk_timeout_add(delay
* 10, redraw_icon
, c
);
3073 static void stop_anim(GtkObject
*obj
, struct conversation
*c
)
3076 gtk_timeout_remove(c
->icon_timer
);
3080 static void start_anim(GtkObject
*obj
, struct conversation
*c
)
3083 GdkPixbufFrame
*frame
;
3086 frames
= gdk_pixbuf_animation_get_frames(c
->anim
);
3087 frame
= g_list_nth_data(frames
, c
->frame
);
3088 delay
= MAX(gdk_pixbuf_frame_get_delay_time(frame
), 13);
3089 c
->icon_timer
= gtk_timeout_add(delay
* 10, redraw_icon
, c
);
3092 static int des_save_icon(GtkObject
*obj
, GdkEvent
*e
, struct conversation
*c
)
3094 gtk_widget_destroy(c
->save_icon
);
3095 c
->save_icon
= NULL
;
3099 static void do_save_icon(GtkObject
*obj
, struct conversation
*c
)
3102 char *f
= gtk_file_selection_get_filename(GTK_FILE_SELECTION(c
->save_icon
));
3103 if (file_is_dir(f
, c
->save_icon
))
3106 file
= fopen(f
, "w");
3109 void *data
= get_icon_data(c
->gc
, normalize(c
->name
), &len
);
3111 fwrite(data
, 1, len
, file
);
3114 do_error_dialog("Can't open file for writing", "Error");
3117 gtk_widget_destroy(c
->save_icon
);
3118 c
->save_icon
= NULL
;
3121 static void cancel_save_icon(GtkObject
*obj
, struct conversation
*c
)
3123 gtk_widget_destroy(c
->save_icon
);
3124 c
->save_icon
= NULL
;
3127 static void save_icon(GtkObject
*obj
, struct conversation
*c
)
3132 gdk_window_raise(c
->save_icon
->window
);
3136 c
->save_icon
= gtk_file_selection_new(_("Gaim - Save Icon"));
3137 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(c
->save_icon
));
3138 g_snprintf(buf
, BUF_LEN
- 1, "%s/%s.icon", g_get_home_dir(), c
->name
);
3139 gtk_file_selection_set_filename(GTK_FILE_SELECTION(c
->save_icon
), buf
);
3140 gtk_signal_connect(GTK_OBJECT(c
->save_icon
), "delete_event",
3141 GTK_SIGNAL_FUNC(des_save_icon
), c
);
3142 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(c
->save_icon
)->ok_button
), "clicked",
3143 GTK_SIGNAL_FUNC(do_save_icon
), c
);
3144 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(c
->save_icon
)->cancel_button
), "clicked",
3145 GTK_SIGNAL_FUNC(cancel_save_icon
), c
);
3147 gtk_widget_show(c
->save_icon
);
3150 static gboolean
icon_menu(GtkObject
*obj
, GdkEventButton
*e
, struct conversation
*c
)
3157 if (e
->type
!= GDK_BUTTON_PRESS
)
3160 menu
= gtk_menu_new();
3162 if (c
->icon_timer
) {
3163 button
= gtk_menu_item_new_with_label(_("Disable Animation"));
3164 gtk_signal_connect(GTK_OBJECT(button
), "activate", GTK_SIGNAL_FUNC(stop_anim
), c
);
3165 gtk_menu_append(GTK_MENU(menu
), button
);
3166 gtk_widget_show(button
);
3167 } else if (c
->anim
&& (gdk_pixbuf_animation_get_num_frames(c
->anim
) > 1)) {
3168 button
= gtk_menu_item_new_with_label(_("Enable Animation"));
3169 gtk_signal_connect(GTK_OBJECT(button
), "activate", GTK_SIGNAL_FUNC(start_anim
), c
);
3170 gtk_menu_append(GTK_MENU(menu
), button
);
3171 gtk_widget_show(button
);
3174 button
= gtk_menu_item_new_with_label(_("Hide Icon"));
3175 gtk_signal_connect_object(GTK_OBJECT(button
), "activate",
3176 GTK_SIGNAL_FUNC(remove_icon
), (void *)c
);
3177 gtk_menu_append(GTK_MENU(menu
), button
);
3178 gtk_widget_show(button
);
3180 button
= gtk_menu_item_new_with_label(_("Save Icon As..."));
3181 gtk_signal_connect(GTK_OBJECT(button
), "activate", GTK_SIGNAL_FUNC(save_icon
), c
);
3182 gtk_menu_append(GTK_MENU(menu
), button
);
3183 gtk_widget_show(button
);
3185 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, e
->button
, e
->time
);
3191 void remove_icon(struct conversation
*c
)
3195 gtk_container_remove(GTK_CONTAINER(c
->bbox
), c
->icon
->parent
->parent
);
3198 gdk_pixbuf_animation_unref(c
->anim
);
3201 gtk_timeout_remove(c
->icon_timer
);
3207 void update_icon(struct conversation
*c
)
3231 if (im_options
& OPT_IM_HIDE_ICONS
)
3237 data
= get_icon_data(c
->gc
, normalize(c
->name
), &len
);
3241 /* this is such an evil hack, i don't know why i'm even considering it.
3242 * we'll do it differently when gdk-pixbuf-loader isn't leaky anymore. */
3243 g_snprintf(filename
, sizeof(filename
), "%s/gaimicon-%s.%d", g_get_tmp_dir(), c
->name
, getpid());
3244 file
= fopen(filename
, "w");
3247 fwrite(data
, 1, len
, file
);
3250 c
->anim
= gdk_pixbuf_animation_new_from_file(filename
);
3251 /* make sure we remove the file as soon as possible */
3257 frames
= gdk_pixbuf_animation_get_frames(c
->anim
);
3258 buf
= gdk_pixbuf_frame_get_pixbuf(frames
->data
);
3259 sf
= SCALE(c
->anim
);
3260 scale
= gdk_pixbuf_scale_simple(buf
,
3261 MAX(gdk_pixbuf_get_width(buf
) * sf
/
3262 gdk_pixbuf_animation_get_width(c
->anim
), 1),
3263 MAX(gdk_pixbuf_get_height(buf
) * sf
/
3264 gdk_pixbuf_animation_get_height(c
->anim
), 1),
3265 GDK_INTERP_NEAREST
);
3267 if (gdk_pixbuf_animation_get_num_frames(c
->anim
) > 1) {
3268 int delay
= MAX(gdk_pixbuf_frame_get_delay_time(frames
->data
), 13);
3270 c
->icon_timer
= gtk_timeout_add(delay
* 10, redraw_icon
, c
);
3273 gdk_pixbuf_render_pixmap_and_mask(scale
, &pm
, &bm
, 100);
3274 gdk_pixbuf_unref(scale
);
3276 frame
= gtk_frame_new(NULL
);
3277 gtk_frame_set_shadow_type(GTK_FRAME(frame
), bm
? GTK_SHADOW_NONE
: GTK_SHADOW_IN
);
3278 gtk_box_pack_start(GTK_BOX(c
->bbox
), frame
, FALSE
, FALSE
, 5);
3279 gtk_widget_show(frame
);
3281 event
= gtk_event_box_new();
3282 gtk_container_add(GTK_CONTAINER(frame
), event
);
3283 gtk_signal_connect(GTK_OBJECT(event
), "button-press-event", GTK_SIGNAL_FUNC(icon_menu
), c
);
3284 gtk_widget_show(event
);
3286 c
->icon
= gtk_pixmap_new(pm
, bm
);
3287 gtk_widget_set_usize(c
->icon
, sf
, sf
);
3288 gtk_container_add(GTK_CONTAINER(event
), c
->icon
);
3289 gtk_widget_show(c
->icon
);
3290 gdk_pixmap_unref(pm
);
3292 gdk_bitmap_unref(bm
);
3296 void got_new_icon(struct gaim_connection
*gc
, char *who
)
3298 struct conversation
*c
= find_conversation(who
);
3299 if (c
&& (c
->gc
== gc
))
3303 void set_hide_icons()
3305 GList
*c
= conversations
;
3307 update_icon(c
->data
);
3312 static void remove_checkbox(struct conversation
*c
)
3315 gtk_container_remove(GTK_CONTAINER(c
->lbox
), c
->check
);
3319 static void update_checkbox(struct conversation
*c
)
3329 if (!c
->gc
->checkbox
)
3332 c
->check
= gtk_check_button_new_with_label(c
->gc
->checkbox
);
3333 gtk_box_pack_start(GTK_BOX(c
->lbox
), c
->check
, FALSE
, FALSE
, 5);
3334 gtk_widget_show(c
->check
);