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
29 #include <sys/types.h>
34 #include "gtkimhtml.h"
42 #include "pixmaps/ok.xpm"
43 #include "pixmaps/cancel.xpm"
44 #include "pixmaps/tb_search.xpm"
46 void serv_login(struct aim_user
*user
)
48 struct prpl
*p
= find_prpl(user
->protocol
);
54 if (!strlen(user
->password
) && !(p
->options
& OPT_PROTO_NO_PASSWORD
)) {
55 do_error_dialog(_("Please enter your password"), _("Signon Error"));
59 debug_printf(PACKAGE
" " VERSION
" logging in %s using %s\n", user
->username
, p
->name());
62 do_error_dialog(_("You cannot log this account in; you do not have "
63 "the protocol it uses loaded, or the protocol does "
64 "not have a login function."), _("Login Error"));
68 static gboolean
send_keepalive(gpointer d
)
70 struct gaim_connection
*gc
= d
;
71 if (gc
->prpl
&& gc
->prpl
->keepalive
)
72 gc
->prpl
->keepalive(gc
);
76 static void update_keepalive(struct gaim_connection
*gc
, gboolean on
)
78 if (on
&& !gc
->keepalive
) {
79 debug_printf("allowing NOP\n");
80 gc
->keepalive
= g_timeout_add(60000, send_keepalive
, gc
);
81 } else if (!on
&& gc
->keepalive
> 0) {
82 debug_printf("removing NOP\n");
83 g_source_remove(gc
->keepalive
);
88 void serv_close(struct gaim_connection
*gc
)
90 while (gc
->buddy_chats
) {
91 struct conversation
*b
= gc
->buddy_chats
->data
;
92 gc
->buddy_chats
= g_slist_remove(gc
->buddy_chats
, b
);
94 update_buttons_by_protocol(b
);
97 if (gc
->idle_timer
> 0)
98 g_source_remove(gc
->idle_timer
);
101 update_keepalive(gc
, FALSE
);
103 if (gc
->prpl
&& gc
->prpl
->close
)
107 destroy_gaim_conn(gc
);
110 void serv_touch_idle(struct gaim_connection
*gc
)
112 /* Are we idle? If so, not anymore */
113 if (gc
->is_idle
> 0) {
115 serv_set_idle(gc
, 0);
118 if (gc
->is_auto_away
)
122 void serv_finish_login(struct gaim_connection
*gc
)
124 if (strlen(gc
->user
->user_info
)) {
125 /* g_malloc(strlen(gc->user->user_info) * 4);
126 strncpy_withhtml(buf, gc->user->user_info, strlen(gc->user->user_info) * 4); */
127 serv_set_info(gc
, gc
->user
->user_info
);
131 if (gc
->idle_timer
> 0)
132 g_source_remove(gc
->idle_timer
);
134 gc
->idle_timer
= g_timeout_add(20000, check_idle
, gc
);
137 time(&gc
->login_time
);
139 if (gc
->prpl
->options
& OPT_PROTO_CORRECT_TIME
)
140 serv_add_buddy(gc
, gc
->username
);
142 update_keepalive(gc
, TRUE
);
145 /* This should return the elapsed time in seconds in which Gaim will not send
146 * typing notifications.
147 * if it returns zero, it will not send any more typing notifications */
148 int serv_send_typing(struct gaim_connection
*g
, char *name
) {
149 if (g
&& g
->prpl
&& g
->prpl
->send_typing
)
150 return g
->prpl
->send_typing(g
, name
);
154 void serv_send_typing_stopped(struct gaim_connection
*g
, char *name
) {
155 if (g
&& g
->prpl
&& g
->prpl
->send_typing_stopped
)
156 g
->prpl
->send_typing_stopped(g
, name
);
159 int serv_send_im(struct gaim_connection
*gc
, char *name
, char *message
, int flags
)
162 if (gc
->prpl
&& gc
->prpl
->send_im
)
163 val
= gc
->prpl
->send_im(gc
, name
, message
, flags
);
165 if (!(flags
& IM_FLAG_AWAY
))
168 serv_send_typing_stopped(gc
, name
);
172 void serv_get_info(struct gaim_connection
*g
, char *name
)
174 if (g
&& g
->prpl
&& g
->prpl
->get_info
)
175 g
->prpl
->get_info(g
, name
);
178 void serv_get_away(struct gaim_connection
*g
, char *name
)
180 if (g
&& g
->prpl
&& g
->prpl
->get_away
)
181 g
->prpl
->get_away(g
, name
);
184 void serv_get_dir(struct gaim_connection
*g
, char *name
)
186 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->get_dir
)
187 g
->prpl
->get_dir(g
, name
);
190 void serv_set_dir(struct gaim_connection
*g
, char *first
, char *middle
, char *last
, char *maiden
,
191 char *city
, char *state
, char *country
, int web
)
193 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->set_dir
)
194 g
->prpl
->set_dir(g
, first
, middle
, last
, maiden
, city
, state
, country
, web
);
197 void serv_dir_search(struct gaim_connection
*g
, char *first
, char *middle
, char *last
, char *maiden
,
198 char *city
, char *state
, char *country
, char *email
)
200 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->dir_search
)
201 g
->prpl
->dir_search(g
, first
, middle
, last
, maiden
, city
, state
, country
, email
);
205 void serv_set_away(struct gaim_connection
*gc
, char *state
, char *message
)
207 if (gc
&& gc
->prpl
&& gc
->prpl
->set_away
) {
210 buf
= g_malloc(strlen(message
) + 1);
211 if (gc
->flags
& OPT_CONN_HTML
)
212 strncpy(buf
, message
, strlen(message
) + 1);
214 strncpy_nohtml(buf
, message
, strlen(message
) + 1);
217 gc
->prpl
->set_away(gc
, state
, buf
);
219 plugin_event(event_away
, gc
, state
, buf
, 0);
225 system_log(log_away
, gc
, NULL
, OPT_LOG_BUDDY_AWAY
| OPT_LOG_MY_SIGNON
);
228 void serv_set_away_all(char *message
)
230 GSList
*c
= connections
;
231 struct gaim_connection
*g
;
234 g
= (struct gaim_connection
*)c
->data
;
235 serv_set_away(g
, GAIM_AWAY_CUSTOM
, message
);
240 void serv_set_info(struct gaim_connection
*g
, char *info
)
242 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->set_info
) {
243 plugin_event(event_set_info
, g
, info
, 0, 0);
244 g
->prpl
->set_info(g
, info
);
248 void serv_change_passwd(struct gaim_connection
*g
, char *orig
, char *new)
250 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->change_passwd
)
251 g
->prpl
->change_passwd(g
, orig
, new);
254 void serv_add_buddy(struct gaim_connection
*g
, char *name
)
256 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->add_buddy
)
257 g
->prpl
->add_buddy(g
, name
);
260 void serv_add_buddies(struct gaim_connection
*g
, GList
*buddies
)
262 if (g
&& g_slist_find(connections
, g
) && g
->prpl
) {
263 if (g
->prpl
->add_buddies
)
264 g
->prpl
->add_buddies(g
, buddies
);
265 else if (g
->prpl
->add_buddy
)
267 g
->prpl
->add_buddy(g
, buddies
->data
);
268 buddies
= buddies
->next
;
274 void serv_remove_buddy(struct gaim_connection
*g
, char *name
, char *group
)
276 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->remove_buddy
)
277 g
->prpl
->remove_buddy(g
, name
, group
);
280 void serv_remove_buddies(struct gaim_connection
*gc
, GList
*g
, char *group
)
282 if (!g_slist_find(connections
, gc
))
285 return; /* how the hell did that happen? */
286 if (gc
->prpl
->remove_buddies
)
287 gc
->prpl
->remove_buddies(gc
, g
, group
);
290 serv_remove_buddy(gc
, g
->data
, group
);
296 void serv_add_permit(struct gaim_connection
*g
, char *name
)
298 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->add_permit
)
299 g
->prpl
->add_permit(g
, name
);
302 void serv_add_deny(struct gaim_connection
*g
, char *name
)
304 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->add_deny
)
305 g
->prpl
->add_deny(g
, name
);
308 void serv_rem_permit(struct gaim_connection
*g
, char *name
)
310 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->rem_permit
)
311 g
->prpl
->rem_permit(g
, name
);
314 void serv_rem_deny(struct gaim_connection
*g
, char *name
)
316 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->rem_deny
)
317 g
->prpl
->rem_deny(g
, name
);
320 void serv_set_permit_deny(struct gaim_connection
*g
)
322 /* this is called when either you import a buddy list, and make lots of changes that way,
323 * or when the user toggles the permit/deny mode in the prefs. In either case you should
324 * probably be resetting and resending the permit/deny info when you get this. */
325 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->set_permit_deny
)
326 g
->prpl
->set_permit_deny(g
);
330 void serv_set_idle(struct gaim_connection
*g
, int time
)
332 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->set_idle
)
333 g
->prpl
->set_idle(g
, time
);
336 void serv_warn(struct gaim_connection
*g
, char *name
, int anon
)
338 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->warn
)
339 g
->prpl
->warn(g
, name
, anon
);
342 void serv_join_chat(struct gaim_connection
*g
, GList
*data
)
344 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->join_chat
)
345 g
->prpl
->join_chat(g
, data
);
348 void serv_chat_invite(struct gaim_connection
*g
, int id
, char *message
, char *name
)
350 char *buffy
= message
&& *message
? g_strdup(message
) : NULL
;
351 plugin_event(event_chat_send_invite
, g
, (void *)id
, name
, &buffy
);
352 if (g
&& g_slist_find(connections
, g
) && g
->prpl
&& g
->prpl
->chat_invite
)
353 g
->prpl
->chat_invite(g
, id
, buffy
, name
);
358 void serv_chat_leave(struct gaim_connection
*g
, int id
)
360 if (!g_slist_find(connections
, g
))
363 if (g
->prpl
&& g
->prpl
->chat_leave
)
364 g
->prpl
->chat_leave(g
, id
);
367 void serv_chat_whisper(struct gaim_connection
*g
, int id
, char *who
, char *message
)
369 if (g
->prpl
&& g
->prpl
->chat_whisper
)
370 g
->prpl
->chat_whisper(g
, id
, who
, message
);
373 int serv_chat_send(struct gaim_connection
*g
, int id
, char *message
)
376 if (g
->prpl
&& g
->prpl
->chat_send
)
377 val
= g
->prpl
->chat_send(g
, id
, message
);
382 int find_queue_row_by_name(char *name
)
388 templist
= message_queue
;
390 for (i
= 0; i
< GTK_CLIST(clistqueue
)->rows
; i
++) {
391 gtk_clist_get_text(GTK_CLIST(clistqueue
), i
, 0, &temp
);
393 if (!strcmp(name
, temp
))
400 int find_queue_total_by_name(char *name
)
405 templist
= message_queue
;
408 struct queued_message
*qm
= (struct queued_message
*)templist
->data
;
409 if ((qm
->flags
& WFLAG_RECV
) && !strcmp(name
, qm
->name
))
412 templist
= templist
->next
;
418 struct queued_away_response
{
423 struct queued_away_response
*find_queued_away_response_by_name(char *name
)
426 struct queued_away_response
*qar
;
428 templist
= away_time_queue
;
431 qar
= (struct queued_away_response
*)templist
->data
;
433 if (!strcmp(name
, qar
->name
))
436 templist
= templist
->next
;
442 /* woo. i'm actually going to comment this function. isn't that fun. make sure to follow along, kids */
443 void serv_got_im(struct gaim_connection
*gc
, char *name
, char *message
, guint32 flags
, time_t mtime
, gint len
)
450 struct conversation
*cnv
;
453 /* pay no attention to the man behind the curtain.
455 * the reason i feel okay with this is because it's useful to some plugins.
456 * Gaim doesn't ever use it itself. Besides, it's not entirely accurate; it's
457 * possible to have false negatives with most protocols. Also with some it's
458 * easy to have false positives as well. So if you're a plugin author, don't
459 * rely on this, still do your own checks. but uh. it's a start. */
460 if (flags
& IM_FLAG_GAIMUSER
)
461 debug_printf("%s is a gaim user.\n", name
);
463 /* we should update the conversation window buttons and menu, if it exists. */
464 cnv
= find_conversation(name
);
466 set_convo_gc(cnv
, gc
);
467 /* we do the new_conv check here in case any plugins decide to create it */
471 /* plugin stuff. we pass a char ** but we don't want to pass what's been given us
472 * by the prpls. so we create temp holders and pass those instead. it's basically
473 * just to avoid segfaults. of course, if the data is binary, plugins don't see it.
474 * bitch all you want; i really don't want you to be dealing with it. */
476 buffy
= g_malloc(MAX(strlen(message
) + 1, BUF_LONG
));
477 strcpy(buffy
, message
);
478 angel
= g_strdup(name
);
479 plugin_return
= plugin_event(event_im_recv
, gc
, &angel
, &buffy
, (void *)flags
);
481 if (!buffy
|| !angel
|| plugin_return
) {
491 name
= g_strdup(name
);
492 message
= g_memdup(message
, len
);
495 /* TiK, using TOC, sends an automated message in order to get your away message. Now,
496 * this is one of the biggest hacks I think I've seen. But, in order to be nice to
497 * TiK, we're going to give users the option to ignore it. */
498 if ((away_options
& OPT_AWAY_TIK_HACK
) && gc
->away
&& strlen(gc
->away
) && (len
< 0) &&
499 !strcmp(message
, ">>>Automated Message: Getting Away Message<<<")) {
500 char *tmpmsg
= stylize(awaymessage
->message
, MSG_LEN
);
501 serv_send_im(gc
, name
, tmpmsg
, IM_FLAG_AWAY
);
508 /* if you can't figure this out, stop reading right now.
509 * "we're not worthy! we're not worthy!" */
510 if ((len
< 0) && (convo_options
& OPT_CONVO_SEND_LINKS
))
511 linkify_text(message
);
513 /* um. when we call write_to_conv with the message we received, it's nice to pass whether
514 * or not it was an auto-response. so if it was an auto-response, we set the appropriate
515 * flag. this is just so prpls don't have to know about WFLAG_* (though some do anyway) */
516 if (flags
& IM_FLAG_AWAY
)
519 /* alright. two cases for how to handle this. either we're away or we're not. if we're not,
520 * then it's easy. if we are, then there are three or four different ways of handling it
521 * and different things we have to do for each. */
525 struct buddy
*b
= find_buddy(gc
, name
);
526 char *alias
= b
? b
->show
: name
;
528 struct queued_away_response
*qar
;
532 /* either we're going to queue it or not. Because of the way awayness currently
533 * works, this is fucked up. it's possible for an account to be away without the
534 * imaway dialog being shown. in fact, it's possible for *all* the accounts to be
535 * away without the imaway dialog being shown. so in order for this to be queued
536 * properly, we have to make sure that the imaway dialog actually exists, first. */
537 if (!cnv
&& clistqueue
&& (away_options
& OPT_AWAY_QUEUE
)) {
538 /* alright, so we're going to queue it. neat, eh? :) so first we create
539 * something to store the message, and add it to our queue. Then we update
540 * the away dialog to indicate that we've queued something. */
541 struct queued_message
*qm
;
543 qm
= g_new0(struct queued_message
, 1);
544 g_snprintf(qm
->name
, sizeof(qm
->name
), "%s", name
);
545 qm
->message
= g_memdup(message
, len
== -1 ? strlen(message
) + 1 : len
);
548 qm
->flags
= WFLAG_RECV
| away
;
550 message_queue
= g_slist_append(message_queue
, qm
);
553 set_user_state(away
);
556 row
= find_queue_row_by_name(qm
->name
);
562 qtotal
= find_queue_total_by_name(qm
->name
);
563 g_snprintf(number
, 32, _("(%d messages)"), qtotal
);
564 gtk_clist_set_text(GTK_CLIST(clistqueue
), row
, 1, number
);
569 heh
[1] = _("(1 message)");
570 gtk_clist_append(GTK_CLIST(clistqueue
), heh
);
573 /* ok, so we're not queuing it. well then, we'll try to handle it normally.
574 * Some people think that ignoring it is a perfectly acceptible way to handle
575 * it. i think they're on crack, but hey, that's why it's optional. */
576 if (away_options
& OPT_AWAY_DISCARD
) {
582 /* ok, so we're not ignoring it. make sure the conversation exists and is
583 * updated (partly handled above already), play the receive sound (sound.c
584 * will take care of not playing while away), and then write it to the
587 cnv
= new_conversation(name
);
588 set_convo_gc(cnv
, gc
);
590 if (new_conv
&& (sound_options
& OPT_SOUND_FIRST_RCV
))
591 play_sound(FIRST_RECEIVE
);
592 else if (cnv
->makesound
&& (sound_options
& OPT_SOUND_RECV
))
595 write_to_conv(cnv
, message
, away
| WFLAG_RECV
, NULL
, mtime
, len
);
598 /* regardless of whether we queue it or not, we should send an auto-response. That is,
599 * of course, unless the horse.... no wait. */
600 if ((away_options
& OPT_AWAY_NO_AUTO_RESP
) || !strlen(gc
->away
) ||
601 ((away_options
& OPT_AWAY_IDLE_RESP
) && !gc
->is_idle
)) {
607 /* this used to be based on the conversation window. but um, if you went away, and
608 * someone sent you a message and got your auto-response, and then you closed the
609 * window, and then the sent you another one, they'd get the auto-response back
610 * too soon. besides that, we need to keep track of this even if we've got a queue.
611 * so the rest of this block is just the auto-response, if necessary */
612 qar
= find_queued_away_response_by_name(name
);
614 qar
= (struct queued_away_response
*)g_new0(struct queued_away_response
, 1);
615 g_snprintf(qar
->name
, sizeof(qar
->name
), "%s", name
);
617 away_time_queue
= g_slist_append(away_time_queue
, qar
);
619 if ((t
- qar
->sent_away
) < away_resend
) {
626 /* apply default fonts and colors */
627 tmpmsg
= stylize(gc
->away
, MSG_LEN
);
628 serv_send_im(gc
, name
, away_subs(tmpmsg
, alias
), IM_FLAG_AWAY
);
629 if (!cnv
&& clistqueue
&& (away_options
& OPT_AWAY_QUEUE
)) {
630 struct queued_message
*qm
;
631 qm
= g_new0(struct queued_message
, 1);
632 g_snprintf(qm
->name
, sizeof(qm
->name
), "%s", name
);
633 qm
->message
= g_strdup(away_subs(tmpmsg
, alias
));
636 qm
->flags
= WFLAG_SEND
| WFLAG_AUTO
;
638 message_queue
= g_slist_append(message_queue
, qm
);
639 } else if (cnv
!= NULL
)
640 write_to_conv(cnv
, away_subs(tmpmsg
, alias
), WFLAG_SEND
| WFLAG_AUTO
, NULL
,
644 /* we're not away. this is easy. if the convo window doesn't exist, create and update
645 * it (if it does exist it was updated earlier), then play a sound indicating we've
646 * received it and then display it. easy. */
648 cnv
= new_conversation(name
);
649 set_convo_gc(cnv
, gc
);
651 if (new_conv
&& (sound_options
& OPT_SOUND_FIRST_RCV
))
652 play_sound(FIRST_RECEIVE
);
653 else if (cnv
->makesound
&& (sound_options
& OPT_SOUND_RECV
))
656 set_convo_name(cnv
, name
);
658 write_to_conv(cnv
, message
, away
| WFLAG_RECV
, NULL
, mtime
, len
);
661 plugin_event(event_im_displayed_rcvd
, gc
, name
, message
, (void *)flags
);
668 void serv_got_update(struct gaim_connection
*gc
, char *name
, int loggedin
, int evil
, time_t signon
,
669 time_t idle
, int type
, guint caps
)
671 struct buddy
*b
= find_buddy(gc
, name
);
673 if (signon
&& (gc
->prpl
->options
& OPT_PROTO_CORRECT_TIME
)) {
674 char *tmp
= g_strdup(normalize(name
));
675 if (!g_strcasecmp(tmp
, normalize(gc
->username
))) {
677 gc
->correction_time
= (signon
- gc
->login_time
);
684 debug_printf("Error, no such buddy %s\n", name
);
688 /* This code will 'align' the name from the TOC */
689 /* server with what's in our record. We want to */
690 /* store things how THEY want it... */
691 if (strcmp(name
, b
->name
)) {
692 char *who
= g_strdup(b
->name
);
693 g_snprintf(b
->name
, sizeof(b
->name
), "%s", name
);
694 handle_buddy_rename(b
, who
);
698 if (!b
->idle
&& idle
) {
699 plugin_event(event_buddy_idle
, gc
, b
->name
, 0, 0);
700 system_log(log_idle
, gc
, b
, OPT_LOG_BUDDY_IDLE
);
702 if (b
->idle
&& !idle
) {
703 do_pounce(gc
, b
->name
, OPT_POUNCE_UNIDLE
);
704 plugin_event(event_buddy_unidle
, gc
, b
->name
, 0, 0);
705 system_log(log_unidle
, gc
, b
, OPT_LOG_BUDDY_IDLE
);
711 if ((b
->uc
& UC_UNAVAILABLE
) && !(type
& UC_UNAVAILABLE
)) {
712 do_pounce(gc
, b
->name
, OPT_POUNCE_UNAWAY
);
713 plugin_event(event_buddy_back
, gc
, b
->name
, 0, 0);
714 system_log(log_back
, gc
, b
, OPT_LOG_BUDDY_AWAY
);
715 } else if (!(b
->uc
& UC_UNAVAILABLE
) && (type
& UC_UNAVAILABLE
)) {
716 plugin_event(event_buddy_away
, gc
, b
->name
, 0, 0);
717 system_log(log_away
, gc
, b
, OPT_LOG_BUDDY_AWAY
);
729 do_pounce(gc
, b
->name
, OPT_POUNCE_SIGNON
);
730 plugin_event(event_buddy_signon
, gc
, b
->name
, 0, 0);
731 system_log(log_signon
, gc
, b
, OPT_LOG_BUDDY_SIGNON
);
735 plugin_event(event_buddy_signoff
, gc
, b
->name
, 0, 0);
736 system_log(log_signoff
, gc
, b
, OPT_LOG_BUDDY_SIGNON
);
745 void serv_got_eviled(struct gaim_connection
*gc
, char *name
, int lev
)
749 plugin_event(event_warned
, gc
, name
, (void *)lev
, 0);
751 if (gc
->evil
>= lev
) {
758 g_snprintf(buf2
, sizeof(buf2
), "%s has just been warned by %s.\nYour new warning level is %d%%",
759 gc
->username
, ((name
== NULL
)? "an anonymous person" : name
), lev
);
761 do_error_dialog(buf2
, _("Warned"));
764 void serv_got_typing(struct gaim_connection
*gc
, char *name
, int timeout
) {
765 struct conversation
*cnv
= find_conversation(name
);
767 set_convo_gc(cnv
, gc
);
770 plugin_event(event_got_typing
, gc
, name
, 0, 0);
771 do_pounce(gc
, name
, OPT_POUNCE_TYPING
);
773 if (cnv
->typing_timeout
)
774 gtk_timeout_remove (cnv
->typing_timeout
);
775 cnv
->typing_timeout
= gtk_timeout_add(timeout
* 1000,(GtkFunction
)reset_typing
,
780 void serv_got_typing_stopped(struct gaim_connection
*gc
, char *name
) {
781 struct conversation
*c
= find_conversation(name
);
782 if (c
->typing_timeout
) {
783 gtk_timeout_remove (c
->typing_timeout
);
785 reset_typing(g_strdup(name
));
788 static void close_invite(GtkWidget
*w
, GtkWidget
*w2
)
790 GList
*str
= gtk_object_get_user_data(GTK_OBJECT(w2
));
800 gtk_widget_destroy(w2
);
803 static void chat_invite_callback(GtkWidget
*w
, GtkWidget
*w2
)
805 struct gaim_connection
*g
= (struct gaim_connection
*)
806 gtk_object_get_user_data(GTK_OBJECT(GTK_DIALOG(w2
)->vbox
));
809 str
= gtk_object_get_user_data(GTK_OBJECT(w2
));
811 serv_join_chat(g
, str
);
816 /* this is either a g_malloc'd char* or g_malloc'd int* */
823 gtk_widget_destroy(w2
);
828 void serv_got_chat_invite(struct gaim_connection
*g
, char *name
, char *who
, char *message
, GList
*data
)
838 plugin_event(event_chat_invited
, g
, who
, name
, message
);
841 g_snprintf(buf2
, sizeof(buf2
), "User '%s' invites %s to buddy chat room: '%s'\n%s", who
,
842 g
->username
, name
, message
);
844 g_snprintf(buf2
, sizeof(buf2
), "User '%s' invites %s to buddy chat room: '%s'\n", who
,
847 d
= gtk_dialog_new();
848 gtk_widget_realize(d
);
852 label
= gtk_label_new(buf2
);
853 gtk_widget_show(label
);
854 yesbtn
= picture_button(d
, _("Yes"), ok_xpm
);
855 nobtn
= picture_button(d
, _("No"), cancel_xpm
);
856 gtk_widget_show(nobtn
);
857 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d
)->vbox
), label
, FALSE
, FALSE
, 5);
858 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d
)->action_area
), yesbtn
, FALSE
, FALSE
, 5);
859 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d
)->action_area
), nobtn
, FALSE
, FALSE
, 5);
861 gtk_object_set_user_data(GTK_OBJECT(GTK_DIALOG(d
)->vbox
), g
);
862 gtk_object_set_user_data(GTK_OBJECT(d
), data
);
865 gtk_window_set_title(GTK_WINDOW(d
), "Buddy chat invite");
866 gtk_signal_connect(GTK_OBJECT(nobtn
), "clicked", GTK_SIGNAL_FUNC(close_invite
), d
);
867 gtk_signal_connect(GTK_OBJECT(yesbtn
), "clicked", GTK_SIGNAL_FUNC(chat_invite_callback
), d
);
873 struct conversation
*serv_got_joined_chat(struct gaim_connection
*gc
, int id
, char *name
)
875 struct conversation
*b
;
877 plugin_event(event_chat_join
, gc
, (void *)id
, name
, 0);
879 b
= (struct conversation
*)g_new0(struct conversation
, 1);
880 gc
->buddy_chats
= g_slist_append(gc
->buddy_chats
, b
);
881 chats
= g_list_append(chats
, b
);
888 b
->history
= g_string_new("");
889 g_snprintf(b
->name
, 80, "%s", name
);
891 if ((logging_options
& OPT_LOG_ALL
) || find_log_info(b
->name
)) {
895 filename
= (char *)malloc(100);
896 g_snprintf(filename
, 100, "%s.chat", b
->name
);
898 fd
= open_log_file(filename
);
900 if (!(logging_options
& OPT_LOG_STRIP_HTML
))
902 "<HR><BR><H3 Align=Center> ---- New Conversation @ %s ----</H3><BR>\n",
905 fprintf(fd
, "---- New Conversation @ %s ----\n", full_date());
912 show_new_buddy_chat(b
);
917 void serv_got_chat_left(struct gaim_connection
*g
, int id
)
919 GSList
*bcs
= g
->buddy_chats
;
920 struct conversation
*b
= NULL
;
924 b
= (struct conversation
*)bcs
->data
;
935 plugin_event(event_chat_leave
, g
, (void *)b
->id
, 0, 0);
937 debug_printf("Leaving room %s.\n", b
->name
);
939 g
->buddy_chats
= g_slist_remove(g
->buddy_chats
, b
);
944 void serv_got_chat_in(struct gaim_connection
*g
, int id
, char *who
, int whisper
, char *message
,
948 GSList
*bcs
= g
->buddy_chats
;
949 struct conversation
*b
= NULL
;
953 b
= (struct conversation
*)bcs
->data
;
963 if (plugin_event(event_chat_recv
, g
, (void *)b
->id
, who
, message
))
966 buf
= g_malloc(MAX(strlen(message
) * 2, 8192));
967 strcpy(buf
, message
);
969 if (convo_options
& OPT_CONVO_SEND_LINKS
)
977 chat_write(b
, who
, w
, buf
, mtime
);
981 static void des_popup(GtkWidget
*w
, GtkWidget
*window
)
984 char *u
= gtk_object_get_user_data(GTK_OBJECT(window
));
987 gtk_widget_destroy(window
);
990 void serv_got_popup(char *msg
, char *u
, int wid
, int hei
)
998 char *url
= g_strdup(u
);
1000 GAIM_DIALOG(window
);
1001 gtk_window_set_wmclass(GTK_WINDOW(window
), "popup", "Gaim");
1002 gtk_window_set_policy(GTK_WINDOW(window
), FALSE
, FALSE
, TRUE
);
1003 gtk_window_set_title(GTK_WINDOW(window
), "Gaim - Popup");
1004 gtk_container_set_border_width(GTK_CONTAINER(window
), 5);
1005 gtk_signal_connect(GTK_OBJECT(window
), "destroy", GTK_SIGNAL_FUNC(des_popup
), window
);
1006 gtk_object_set_user_data(GTK_OBJECT(window
), url
);
1007 gtk_widget_realize(window
);
1008 aol_icon(window
->window
);
1010 vbox
= gtk_vbox_new(FALSE
, 5);
1011 gtk_container_add(GTK_CONTAINER(window
), vbox
);
1013 sw
= gtk_scrolled_window_new(NULL
, NULL
);
1014 gtk_widget_set_usize(sw
, wid
, hei
);
1015 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw
), GTK_POLICY_NEVER
, GTK_POLICY_ALWAYS
);
1016 gtk_box_pack_start(GTK_BOX(vbox
), sw
, TRUE
, TRUE
, 5);
1018 text
= gtk_imhtml_new(NULL
, NULL
);
1019 gtk_container_add(GTK_CONTAINER(sw
), text
);
1020 GTK_LAYOUT(text
)->hadjustment
->step_increment
= 10.0;
1021 GTK_LAYOUT(text
)->vadjustment
->step_increment
= 10.0;
1022 gaim_setup_imhtml(text
);
1024 hbox
= gtk_hbox_new(FALSE
, 5);
1025 gtk_box_pack_end(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 5);
1027 button
= picture_button(window
, _("Close"), cancel_xpm
);
1028 gtk_box_pack_end(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 5);
1029 gtk_signal_connect(GTK_OBJECT(button
), "clicked", GTK_SIGNAL_FUNC(des_popup
), window
);
1031 button
= picture_button(window
, _("More Info"), tb_search_xpm
);
1032 gtk_box_pack_end(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 5);
1033 gtk_signal_connect(GTK_OBJECT(button
), "clicked", GTK_SIGNAL_FUNC(open_url
), url
);
1035 gtk_widget_show_all(window
);
1037 gtk_imhtml_append_text(GTK_IMHTML(text
), msg
, -1, GTK_IMHTML_NO_NEWLINE
);