comparison src/buddy.c @ 1030:38452403563b

[gaim-migrate @ 1040] updating the buddy list to work better with multiple connections. there are still a bunch of things fucked up with this but i wanted more people to start working on it than just me, especially since i won't be here this weekend. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 27 Oct 2000 07:53:32 +0000
parents 1d8f05ea6bdf
children 643a4d81c18a
comparison
equal deleted inserted replaced
1029:740c6f933fe0 1030:38452403563b
36 #include <math.h> 36 #include <math.h>
37 #include <time.h> 37 #include <time.h>
38 38
39 #include <gtk/gtk.h> 39 #include <gtk/gtk.h>
40 #include <gdk/gdkx.h> 40 #include <gdk/gdkx.h>
41 #include "prpl.h"
41 #include "gaim.h" 42 #include "gaim.h"
42 #include <aim.h> 43 #include <aim.h>
43 #include "pixmaps/admin_icon.xpm"
44 #include "pixmaps/aol_icon.xpm"
45 #include "pixmaps/free_icon.xpm"
46 #include "pixmaps/dt_icon.xpm"
47 #include "pixmaps/no_icon.xpm"
48 #include "pixmaps/login_icon.xpm" 44 #include "pixmaps/login_icon.xpm"
49 #include "pixmaps/logout_icon.xpm" 45 #include "pixmaps/logout_icon.xpm"
50 46 #include "pixmaps/no_icon.xpm"
51 #include "pixmaps/away_icon.xpm" 47
52 #include "pixmaps/away_small.xpm" 48 #include "pixmaps/away_small.xpm"
53 49
54 #include "pixmaps/add_small.xpm" 50 #include "pixmaps/add_small.xpm"
55 #include "pixmaps/import_small.xpm" 51 #include "pixmaps/import_small.xpm"
56 #include "pixmaps/export_small.xpm" 52 #include "pixmaps/export_small.xpm"
84 extern int ticker_prefs; 80 extern int ticker_prefs;
85 81
86 GtkWidget *blist = NULL; 82 GtkWidget *blist = NULL;
87 GtkWidget *bpmenu; 83 GtkWidget *bpmenu;
88 GtkWidget *buddies; 84 GtkWidget *buddies;
89 int permdeny;
90 85
91 void BuddyTickerLogonTimeout( gpointer data ); 86 void BuddyTickerLogonTimeout( gpointer data );
92 void BuddyTickerLogoutTimeout( gpointer data ); 87 void BuddyTickerLogoutTimeout( gpointer data );
93 88
94 /* Predefine some functions */ 89 /* Predefine some functions */
95 static void new_bp_callback(GtkWidget *w, char *name); 90 static void new_bp_callback(GtkWidget *w, char *name);
96 static void log_callback(GtkWidget *w, char *name); 91 static void log_callback(GtkWidget *w, char *name);
92
93 /* stuff for actual display of buddy list */
94 struct buddy_show {
95 GtkWidget *item;
96 GtkWidget *pix;
97 GtkWidget *label;
98 char *name;
99 GSList *connlist;
100 guint log_timer;
101 };
102 struct group_show {
103 GtkWidget *item;
104 GtkWidget *label;
105 GtkWidget *tree;
106 GSList *members;
107 char *name;
108 };
109 static GSList *shows = NULL;
97 110
98 111
99 void destroy_buddy() 112 void destroy_buddy()
100 { 113 {
101 if (blist) 114 if (blist)
102 gtk_widget_destroy(blist); 115 gtk_widget_destroy(blist);
103 blist=NULL; 116 blist=NULL;
104 imchatbox = NULL; 117 imchatbox = NULL;
105 }
106
107 void update_num_groups()
108 {
109 GSList *grp = groups;
110 GList *mem;
111 struct buddy *b;
112 struct group *g;
113 int pres, total;
114 char buf[BUF_LONG];
115
116 #ifndef USE_APPLET
117 if (!(display_options & OPT_DISP_SHOW_GRPNUM))
118 return;
119 #else
120 int onl = 0;
121 int all = 0;
122 #endif
123
124 while(grp) {
125 g = (struct group *)grp->data;
126 mem = g->members;
127 pres = 0;
128 total = 0;
129 while(mem) {
130 b = (struct buddy *)mem->data;
131 if (b->present)
132 pres++;
133 total++;
134
135
136 mem = mem->next;
137 }
138
139 g_snprintf(buf, sizeof(buf), "%s (%d/%d)", g->name, pres, total);
140
141 #ifdef USE_APPLET
142 onl += pres;
143 all += total;
144 if (display_options & OPT_DISP_SHOW_GRPNUM)
145 #endif
146 gtk_label_set(GTK_LABEL(g->label), buf);
147 grp = g_slist_next(grp);
148 }
149 #ifdef USE_APPLET
150 g_snprintf(buf, sizeof(buf), _("%d/%d Buddies Online"), onl, all);
151 applet_set_tooltips(buf);
152 #endif
153 }
154
155 void update_show_idlepix()
156 {
157 GSList *grp = groups;
158 GList *mem;
159 struct group *g;
160 struct buddy *b;
161
162 while (grp) {
163 g = (struct group *)grp->data;
164 mem = g->members;
165
166 while(mem) {
167 b = (struct buddy *)mem->data;
168
169 if (display_options & OPT_DISP_SHOW_IDLETIME)
170 gtk_widget_show(b->idletime);
171 else
172 gtk_widget_hide(b->idletime);
173
174 if (display_options & OPT_DISP_SHOW_PIXMAPS)
175 gtk_widget_show(b->pix);
176 else
177 gtk_widget_hide(b->pix);
178 mem = mem->next;
179 }
180 grp = g_slist_next(grp);
181 }
182 }
183
184 void update_all_buddies()
185 {
186 GSList *grp = groups;
187 GList *mem;
188 struct buddy *b;
189 struct group *g;
190 int count;
191
192 while(grp) {
193 g = (struct group *)grp->data;
194 count = 0;
195 mem = g->members;
196 while(mem) {
197 b = (struct buddy *)mem->data;
198
199 if (b->present || !GTK_WIDGET_VISIBLE(b->item))
200 set_buddy(b);
201
202 if (b->present || GTK_WIDGET_VISIBLE(b->item))
203 count++;
204
205 mem = mem->next;
206 }
207 /* this is a fall-back in case we missed any */
208 if (!count && (display_options & OPT_DISP_NO_MT_GRP))
209 gtk_widget_hide(g->item);
210 else gtk_widget_show(g->item);
211
212 grp = g_slist_next(grp);
213 }
214
215
216 } 118 }
217 119
218 static void adjust_pic(GtkWidget *button, const char *c, gchar **xpm) 120 static void adjust_pic(GtkWidget *button, const char *c, gchar **xpm)
219 { 121 {
220 GdkPixmap *pm; 122 GdkPixmap *pm;
287 } 189 }
288 } 190 }
289 191
290 void signoff(struct gaim_connection *gc) 192 void signoff(struct gaim_connection *gc)
291 { 193 {
292 GList *mem;
293
294 plugin_event(event_signoff, gc, 0, 0, 0); 194 plugin_event(event_signoff, gc, 0, 0, 0);
295 serv_close(gc); 195 serv_close(gc);
296 196
297 if (connections) return; 197 if (connections) return;
298 while(groups) {
299 mem = ((struct group *)groups->data)->members;
300 while(mem) {
301 g_free(mem->data);
302 mem = g_list_remove(mem, mem->data);
303 }
304 g_free(groups->data);
305 groups = g_slist_remove(groups, groups->data);
306 }
307 198
308 sprintf(debug_buff, "date: %s\n", full_date()); 199 sprintf(debug_buff, "date: %s\n", full_date());
309 debug_print(debug_buff); 200 debug_print(debug_buff);
310 update_keepalive(gc, FALSE); 201 update_keepalive(gc, FALSE);
311 destroy_all_dialogs(); 202 destroy_all_dialogs();
331 gtk_tree_item_expand(GTK_TREE_ITEM(widget)); 222 gtk_tree_item_expand(GTK_TREE_ITEM(widget));
332 } else { 223 } else {
333 } 224 }
334 } 225 }
335 226
336 void pressed_im(GtkWidget *widget, struct buddy *b) 227 void pressed_im(GtkWidget *widget, struct buddy_show *b)
337 { 228 {
338 struct conversation *c; 229 struct conversation *c;
339 230
340 c = find_conversation(b->name); 231 c = find_conversation(b->name);
341 232
357 } else { 248 } else {
358 c = new_conversation(buddy); 249 c = new_conversation(buddy);
359 } 250 }
360 } 251 }
361 252
362 void pressed_info(GtkWidget *widget, struct buddy *b) 253 void pressed_info(GtkWidget *widget, struct buddy_show *b)
363 { 254 {
364 serv_get_info(b->name); 255 serv_get_info(b->name);
365 } 256 }
366 257
367 void pressed_alias(GtkWidget *widget, struct buddy *b) 258 void pressed_alias(GtkWidget *widget, struct buddy_show *b)
368 { 259 {
369 alias_dialog(b); 260 struct buddy *m = find_buddy(connections->data, b->name);
370 } 261 alias_dialog(m);
371 262 }
372 void pressed_dir_info(GtkWidget *widget, struct buddy *b) 263
264 void pressed_dir_info(GtkWidget *widget, struct buddy_show *b)
373 { 265 {
374 serv_get_dir(b->name); 266 serv_get_dir(b->name);
375 267
376 } 268 }
377 269
378 void pressed_away_msg(GtkWidget *widget, struct buddy *b) 270 void pressed_away_msg(GtkWidget *widget, struct buddy_show *b)
379 { 271 {
380 serv_get_away_msg(b->name); 272 serv_get_away_msg(b->name);
381 273
382 } 274 }
383 275
384 void handle_click_buddy(GtkWidget *widget, GdkEventButton *event, struct buddy *b) 276 void handle_click_buddy(GtkWidget *widget, GdkEventButton *event, struct buddy_show *b)
385 { 277 {
386 if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { 278 if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
387 struct conversation *c; 279 struct conversation *c;
388 280
389 c = find_conversation(b->name); 281 c = find_conversation(b->name);
465 } 357 }
466 } 358 }
467 359
468 360
469 361
470 void remove_buddy(struct group *rem_g, struct buddy *rem_b) 362 void remove_buddy(struct gaim_connection *gc, struct group *rem_g, struct buddy *rem_b)
471 { 363 {
472 GSList *grp; 364 GSList *grp;
473 GList *mem; 365 GSList *mem;
474 struct buddy *b; 366 struct conversation *c;
475 int count = 0;
476 367
477 struct group *delg; 368 struct group *delg;
478 struct buddy *delb; 369 struct buddy *delb;
479 370
480 grp = g_slist_find(groups, rem_g); 371 /* we assume that gc is not NULL and that the buddy exists somewhere within the
372 * gc's buddy list, therefore we can safely remove it. we need to ensure this
373 * via the UI
374 */
375
376 grp = g_slist_find(gc->groups, rem_g);
481 delg = (struct group *)grp->data; 377 delg = (struct group *)grp->data;
482 mem = delg->members; 378 mem = delg->members;
483 379
484 mem = g_list_find(mem, rem_b); 380 mem = g_slist_find(mem, rem_b);
485 delb = (struct buddy *)mem->data; 381 delb = (struct buddy *)mem->data;
486 382
487 gtk_tree_remove_items(GTK_TREE(delg->tree), g_list_append(NULL, delb->item)); 383 delg->members = g_slist_remove(delg->members, delb);
488 delg->members = g_list_remove(delg->members, delb); 384 serv_remove_buddy(gc, delb->name);
489 serv_remove_buddy(delb->name); 385 c = find_conversation(delb->name);
490 g_free(delb); 386 g_free(delb);
491 mem = delg->members; 387 mem = delg->members;
492 while (mem && !count) { 388
493 b = (struct buddy *)mem->data; 389 if (c)
494 if (b->present || GTK_WIDGET_VISIBLE(b->item)) count++; 390 update_convo_add_button(c);
495 mem = mem->next;
496 }
497 if (!count && (display_options & OPT_DISP_NO_MT_GRP))
498 gtk_widget_hide(delg->item);
499
500
501 serv_save_config();
502 391
503 // flush buddy list to cache 392 // flush buddy list to cache
504 393
505 do_export( (GtkWidget *) NULL, 0 ); 394 do_export( (GtkWidget *) NULL, 0 );
506 395 }
507 update_num_groups(); 396
508 } 397 void remove_group(struct gaim_connection *gc, struct group *rem_g)
509
510 void remove_group(struct group *rem_g)
511 { 398 {
512 GSList *grp; 399 GSList *grp;
513 GList *mem; 400 GSList *mem;
514 401
515 struct group *delg; 402 struct group *delg;
516 struct buddy *delb; 403 struct buddy *delb;
517 404
518 grp = g_slist_find(groups, rem_g); 405 struct conversation *c;
406
407 /* we assume that the group actually does exist within the gc, and that the gc is not NULL.
408 * the UI is responsible for this */
409
410 grp = g_slist_find(gc->groups, rem_g);
519 delg = (struct group *)grp->data; 411 delg = (struct group *)grp->data;
520 mem = delg->members; 412 mem = delg->members;
521 413
522 while(delg->members) { 414 while(delg->members) {
523 delb = (struct buddy *)delg->members->data; 415 delb = (struct buddy *)delg->members->data;
524 gtk_tree_remove_items(GTK_TREE(delg->tree), g_list_append(NULL, delb->item)); 416 delg->members = g_slist_remove(delg->members, delb);
525 delg->members = g_list_remove(delg->members, delb); 417 c = find_conversation(delb->name);
526 serv_remove_buddy(delb->name); 418 if (c)
419 update_convo_add_button(c);
420 serv_remove_buddy(gc, delb->name);
527 g_free(delb); 421 g_free(delb);
528 } 422 }
529 423
530 424 gc->groups = g_slist_remove(gc->groups, delg);
531 gtk_tree_remove_items(GTK_TREE(buddies), g_list_append(NULL, delg->item));
532 groups = g_slist_remove(groups, delg);
533 g_free(delg); 425 g_free(delg);
534
535 serv_save_config();
536 426
537 // flush buddy list to cache 427 // flush buddy list to cache
538 428
539 do_export( (GtkWidget *) NULL, 0 ); 429 do_export( (GtkWidget *) NULL, 0 );
540 } 430 }
545 435
546 gboolean edit_drag_compare_func (GtkCTree *ctree, GtkCTreeNode *source_node, 436 gboolean edit_drag_compare_func (GtkCTree *ctree, GtkCTreeNode *source_node,
547 GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling) 437 GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling)
548 { 438 {
549 gboolean leaf; 439 gboolean leaf;
550 440 struct gaim_connection *gc, *pc;
551 gtk_ctree_get_node_info (ctree, source_node, NULL, 441 char *source;
442 char *parent;
443
444 gtk_ctree_get_node_info (ctree, source_node, &source,
552 NULL, NULL, NULL, NULL, NULL, &leaf, NULL); 445 NULL, NULL, NULL, NULL, NULL, &leaf, NULL);
553 446
554 447 gc = (struct gaim_connection *)gtk_ctree_node_get_row_data(GTK_CTREE(ctree), source_node);
555 if (leaf) { 448
449 if (!strcmp(gc->username, source)) {
556 if (!new_parent) 450 if (!new_parent)
557 return FALSE; 451 return TRUE;
558 } else { 452 } else if (leaf) {
559 453 if (new_parent) {
560 if (new_parent) 454 gtk_ctree_get_node_info (ctree, new_parent, &parent,
561 return FALSE; 455 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
562 456 pc = (struct gaim_connection *)gtk_ctree_node_get_row_data(GTK_CTREE(ctree),
563 } 457 new_parent);
564 458 if (strcmp(parent, pc->username))
565 return TRUE; 459 return TRUE;
460 }
461 } else /* group */ {
462 if (g_slist_length(connections) > 1 && new_parent) {
463 gtk_ctree_get_node_info (ctree, new_parent, &parent,
464 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
465 pc = (struct gaim_connection *)gtk_ctree_node_get_row_data(GTK_CTREE(ctree),
466 new_parent);
467 if (!strcmp(parent, pc->username))
468 return TRUE;
469 } else if (g_slist_length(connections) == 1 && !new_parent)
470 return TRUE;
471 }
472
473 return FALSE;
566 } 474 }
567 475
568 476
569 477
570 static void edit_tree_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent, 478 static void edit_tree_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent,
571 GtkCTreeNode *sibling, gpointer data) 479 GtkCTreeNode *sibling, gpointer data)
572 { 480 {
573 char *source; 481 gboolean leaf;
574 char *target1; 482 char *source = "";
575 char *target2; 483 char *target1 = "";
484 char *target2 = "";
485 struct gaim_connection *gc, *pc = NULL, *sc = NULL;
486
487 gc = (struct gaim_connection *)gtk_ctree_node_get_row_data(GTK_CTREE(ctree), child);
576 488
577 gtk_ctree_get_node_info (ctree, child, &source, 489 gtk_ctree_get_node_info (ctree, child, &source,
578 NULL, NULL, NULL, NULL, NULL, NULL, NULL); 490 NULL, NULL, NULL, NULL, NULL, &leaf, NULL);
579 if (parent) 491 if (parent) {
580 gtk_ctree_get_node_info (ctree, parent, &target1, 492 gtk_ctree_get_node_info (ctree, parent, &target1,
581 NULL, NULL, NULL, NULL, NULL, NULL, NULL); 493 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
582 if (sibling) 494 pc = (struct gaim_connection *)gtk_ctree_node_get_row_data(GTK_CTREE(ctree), parent);
495 }
496
497 if (sibling) {
583 gtk_ctree_get_node_info (ctree, sibling, &target2, 498 gtk_ctree_get_node_info (ctree, sibling, &target2,
584 NULL, NULL, NULL, NULL, NULL, NULL, NULL); 499 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
585 500 sc = (struct gaim_connection *)gtk_ctree_node_get_row_data(GTK_CTREE(ctree), sibling);
586 501 }
587 if (!parent) { 502
588 GSList *grps; 503 if (!strcmp(source, gc->username)) {
589 GList *buds; 504 /* not that it particularly matters which order the connections
505 * are in, but just for debugging sake, i guess.... */
506 connections = g_slist_remove(connections, gc);
507 if (sibling) {
508 int pos = g_slist_index(connections, sc);
509 if (pos)
510 connections = g_slist_insert(connections, gc, pos);
511 else
512 connections = g_slist_prepend(connections, gc);
513 } else
514 connections = g_slist_append(connections, gc);
515 } else if (leaf) {
516 /* we moved a buddy. hopefully we just changed groups or positions or something.
517 * if we changed connections, we copy the buddy to the new connection. if the new
518 * connection already had the buddy in its buddy list but in a different group,
519 * we change the group that the buddy is in */
520 struct group *new_g, *old_g;
521 struct buddy *b, *s = NULL;
522 int pos;
523
524 if (gc != pc) {
525 /* we changed connections */
526 struct buddy *a;
527
528 a = find_buddy(pc, source);
529
530 if (a) {
531 /* the buddy is in the new connection, so we'll remove it from
532 * its current group and add it to the proper group below */
533 struct group *og;
534 og = find_group_by_buddy(pc, source);
535 og->members = g_slist_remove(og->members, a);
536 } else {
537 /* we don't have this buddy yet; let's add him */
538 serv_add_buddy(pc, source);
539 }
540 }
541
542 b = find_buddy(gc, source);
543 new_g = find_group(pc, target1);
544 old_g = find_group_by_buddy(gc, source);
545
546 if (gc == pc) /* this is the same connection, so we'll remove it from its old group */
547 old_g->members = g_slist_remove(old_g->members, b);
548
549 if (sibling) {
550 s = find_buddy(sc, target2);
551 pos = g_slist_index(new_g->members, s);
552 if (pos)
553 new_g->members = g_slist_insert(new_g->members, b, pos);
554 else
555 new_g->members = g_slist_prepend(new_g->members, b);
556 } else
557 new_g->members = g_slist_append(new_g->members, b);
558
559 if (pc != gc)
560 build_edit_tree();
561 } else /* group */ {
562 /* move the group. if moving connections, copy the group, and each buddy in the
563 * group. if the buddy exists in the new connection, leave it where it is. */
564
590 struct group *g, *g2; 565 struct group *g, *g2;
591 GList *tmp, *mem; 566 int pos;
592 int pos, count; 567
593 struct buddy *b; 568 if (g_slist_length(connections) > 1) {
594 /* Okay we've moved group order... */ 569 g = find_group(pc, source);
595 570 if (!g)
596 g = find_group(source); 571 g = add_group(pc, source);
597 572
598 gtk_widget_ref(g->tree); 573 pc->groups = g_slist_remove(pc->groups, g);
599 574
600 buds = g->members; 575 if (sibling) {
601 while(buds) { 576 g2 = find_group(pc, target2);
602 b = (struct buddy *)buds->data; 577 pos = g_slist_index(pc->groups, g2);
603 gtk_widget_ref(b->item); 578 if (pos)
604 gtk_widget_ref(b->label); 579 pc->groups = g_slist_insert(pc->groups, g, pos);
605 gtk_widget_ref(b->idletime); 580 else
606 gtk_widget_ref(b->pix); 581 pc->groups = g_slist_prepend(pc->groups, g);
607 buds = buds->next; 582 } else
583 pc->groups = g_slist_append(pc->groups, g);
584
585 if (pc != gc) {
586 GSList *mem;
587 struct buddy *b;
588 g2 = find_group(gc, source);
589
590 mem = g2->members;
591 while (mem) {
592 b = (struct buddy *)mem->data;
593 if (!find_buddy(pc, b->name))
594 add_buddy(pc, g->name, b->name, b->show);
595 mem = mem->next;
596 }
597
598 build_edit_tree();
599 }
600 } else {
601 g = find_group(gc, source);
602
603 gc->groups = g_slist_remove(gc->groups, g);
604
605 if (sibling) {
606 g2 = find_group(gc, target2);
607 pos = g_slist_index(gc->groups, g2);
608 if (pos)
609 gc->groups = g_slist_insert(gc->groups, g, pos);
610 else
611 gc->groups = g_slist_prepend(gc->groups, g);
612 } else
613 gc->groups = g_slist_append(gc->groups, g);
608 } 614 }
609 615 }
610 616
611 617 do_export( (GtkWidget *) NULL, 0 );
612
613 pos = g_list_index(GTK_TREE(buddies)->children, g->item);
614
615 tmp = g_list_append(NULL, g->item);
616 gtk_tree_remove_items(GTK_TREE(buddies), tmp);
617 g_list_free(tmp);
618
619 groups = g_slist_remove(groups, g);
620
621 g->item = gtk_tree_item_new_with_label(g->name);
622 mem = g->members; count = 0;
623 while (mem && !count) {
624 b = (struct buddy *)mem->data;
625 if (b->present) count++;
626 mem = mem->next;
627 }
628 if (!count) gtk_widget_show(g->item);
629
630 if (sibling) {
631 g2 = find_group(target2);
632 pos = g_slist_index(groups, g2);
633 if (pos == 0) {
634 groups = g_slist_prepend(groups, g);
635 gtk_tree_prepend(GTK_TREE(buddies), g->item);
636 } else {
637 groups = g_slist_insert(groups, g, pos);
638 gtk_tree_insert(GTK_TREE(buddies), g->item, pos);
639 }
640
641 } else {
642 groups = g_slist_append(groups, g);
643 gtk_tree_append(GTK_TREE(buddies), g->item);
644
645 }
646
647 gtk_tree_item_set_subtree (GTK_TREE_ITEM(g->item), g->tree);
648 gtk_tree_item_expand (GTK_TREE_ITEM(g->item));
649 gtk_signal_connect(GTK_OBJECT(g->item), "button_press_event",
650 GTK_SIGNAL_FUNC(handle_click_group),
651 NULL);
652 gtk_object_set_user_data(GTK_OBJECT(g->item), NULL);
653
654 gtk_widget_unref(g->tree);
655
656 update_num_groups();
657
658 buds = g->members;
659
660 while(buds) {
661 b = (struct buddy *)buds->data;
662 set_buddy(b);
663 buds = buds->next;
664 }
665
666 grps = groups;
667 while(grps) {
668 g = (struct group *)grps->data;
669 grps = g_slist_next(grps);
670 }
671
672 } else {
673 struct group *new_g, *old_g;
674 struct buddy *b, *s;
675 GtkWidget *gtree;
676 GtkWidget *owner;
677 GList *temp;
678 int pos;
679
680 b = find_buddy(source);
681 new_g = find_group(target1);
682 old_g = find_group_by_buddy(source);
683 gtree = old_g->tree;
684 if (sibling)
685 s = find_buddy(target2);
686 else
687 s = NULL;
688
689 old_g->members = g_list_remove(old_g->members, b);
690
691 gtk_widget_ref(b->item);
692 gtk_widget_ref(b->label);
693 gtk_widget_ref(b->pix);
694 gtk_widget_ref(b->idletime);
695 gtk_widget_ref(gtree);
696
697 owner = GTK_TREE(gtree)->tree_owner;
698
699 temp = g_list_append(NULL, b->item);
700 gtk_tree_remove_items(GTK_TREE(old_g->tree), temp);
701 g_list_free(temp);
702
703 if (gtree->parent == NULL){
704 gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), gtree);
705 gtk_tree_item_expand (GTK_TREE_ITEM(owner));
706 }
707
708 if (!sibling) {
709 gtk_tree_append(GTK_TREE(new_g->tree), b->item);
710 new_g->members = g_list_append(new_g->members, b);
711 } else {
712 pos = g_list_index(new_g->members, s);
713 if (pos != 0) {
714 new_g->members = g_list_insert(new_g->members, b, pos);
715 gtk_tree_insert(GTK_TREE(new_g->tree), b->item, pos);
716 } else {
717 new_g->members = g_list_prepend(new_g->members, b);
718 gtk_tree_prepend(GTK_TREE(new_g->tree), b->item);
719
720 }
721 }
722
723 gtk_widget_unref(b->item);
724 gtk_widget_unref(b->label);
725 gtk_widget_unref(b->pix);
726 gtk_widget_unref(b->idletime);
727 gtk_widget_unref(gtree);
728
729 gtk_ctree_expand(ctree, parent);
730
731 update_num_groups();
732 update_show_idlepix();
733 if (b->present) {
734 GList *mem = old_g->members;
735 struct buddy *bt;
736 int count = 0;
737 while (mem && !count) {
738 bt = (struct buddy *)mem->data;
739 if (bt->present || GTK_WIDGET_VISIBLE(b->item)) count++;
740 mem = mem->next;
741 }
742 if (!count && (display_options & OPT_DISP_NO_MT_GRP))
743 gtk_widget_hide(old_g->item);
744 gtk_widget_show(new_g->item);
745 }
746 set_buddy(b);
747
748
749
750
751
752 }
753
754 serv_save_config();
755
756 // flush buddy list to cache
757
758 do_export( (GtkWidget *) NULL, 0 );
759 } 618 }
760 619
761 620
762 621
763 void build_edit_tree() 622 void build_edit_tree()
764 { 623 {
765 GtkCTreeNode *p = NULL, *n; 624 GtkCTreeNode *c = NULL, *p = NULL, *n;
766 GSList *grp = groups; 625 GSList *con = connections;
767 GList *mem; 626 GSList *grp;
627 GSList *mem;
628 struct gaim_connection *z;
768 struct group *g; 629 struct group *g;
769 struct buddy *b; 630 struct buddy *b;
770 char *text[1]; 631 char *text[1];
771 632
772 gtk_clist_freeze(GTK_CLIST(edittree)); 633 gtk_clist_freeze(GTK_CLIST(edittree));
773 gtk_clist_clear(GTK_CLIST(edittree)); 634 gtk_clist_clear(GTK_CLIST(edittree));
774 635
775 636
776 while(grp) { 637 while (con) {
777 g = (struct group *)grp->data; 638 z = (struct gaim_connection *)con->data;
778 639
779 text[0] = g->name; 640 if (g_slist_length(connections) > 1) {
780 641 text[0] = z->username;
781 p = gtk_ctree_insert_node(GTK_CTREE(edittree), NULL, 642
782 NULL, text, 5, NULL, NULL, 643 c = gtk_ctree_insert_node(GTK_CTREE(edittree), NULL,
783 NULL, NULL, 0, 1); 644 NULL, text, 5, NULL, NULL,
784 645 NULL, NULL, 0, 1);
785 n = NULL; 646
786 647 gtk_ctree_node_set_row_data(GTK_CTREE(edittree), c, z);
787 mem = g->members; 648 } else
788 649 c = NULL;
789 while(mem) { 650
790 b = (struct buddy *)mem->data; 651 grp = z->groups;
791 652
792 text[0] = b->name; 653 while(grp) {
793 654 g = (struct group *)grp->data;
794 n = gtk_ctree_insert_node(GTK_CTREE(edittree), 655
795 p, NULL, text, 5, 656 text[0] = g->name;
796 NULL, NULL, 657
797 NULL, NULL, 1, 1); 658 p = gtk_ctree_insert_node(GTK_CTREE(edittree), c,
798 659 NULL, text, 5, NULL, NULL,
799 mem = mem->next; 660 NULL, NULL, 0, 1);
800 661
801 } 662 gtk_ctree_node_set_row_data(GTK_CTREE(edittree), p, z);
802 grp = g_slist_next(grp); 663
664 n = NULL;
665
666 mem = g->members;
667
668 while(mem) {
669 b = (struct buddy *)mem->data;
670
671 text[0] = b->name;
672
673 n = gtk_ctree_insert_node(GTK_CTREE(edittree),
674 p, NULL, text, 5,
675 NULL, NULL,
676 NULL, NULL, 1, 1);
677
678 gtk_ctree_node_set_row_data(GTK_CTREE(edittree), n, z);
679
680 mem = mem->next;
681
682 }
683 grp = g_slist_next(grp);
684 }
685 con = g_slist_next(con);
803 } 686 }
804 687
805 gtk_clist_thaw(GTK_CLIST(edittree)); 688 gtk_clist_thaw(GTK_CLIST(edittree));
806 689
807 } 690 }
808 691
809 struct buddy *add_buddy(char *group, char *buddy, char *show) 692 struct buddy *add_buddy(struct gaim_connection *gc, char *group, char *buddy, char *show)
810 { 693 {
811 struct buddy *b; 694 struct buddy *b;
812 struct group *g; 695 struct group *g;
813 GdkPixmap *pm; 696
814 GdkBitmap *bm; 697 if ((b = find_buddy(gc, buddy)) != NULL)
815 GtkWidget *box;
816
817
818 if ((b = find_buddy(buddy)) != NULL)
819 return b; 698 return b;
820 699
821 g = find_group(group); 700 g = find_group(gc, group);
822 701
823 if (g == NULL) 702 if (g == NULL)
824 g = add_group(group); 703 g = add_group(gc, group);
825 704
826 b = (struct buddy *)g_new0(struct buddy, 1); 705 b = (struct buddy *)g_new0(struct buddy, 1);
827 706
828 if (!b) 707 if (!b)
829 return NULL; 708 return NULL;
830 709
831 b->present = 0; 710 b->present = 0;
832 b->item = gtk_tree_item_new();
833 711
834 g_snprintf(b->name, sizeof(b->name), "%s", buddy); 712 g_snprintf(b->name, sizeof(b->name), "%s", buddy);
835 g_snprintf(b->show, sizeof(b->show), "%s", show ? (show[0] ? show : buddy) : buddy); 713 g_snprintf(b->show, sizeof(b->show), "%s", show ? (show[0] ? show : buddy) : buddy);
836 714
837 g->members = g_list_append(g->members, b); 715 g->members = g_slist_append(g->members, b);
838
839
840 if (blist == NULL)
841 return b;
842
843 box = gtk_hbox_new(FALSE, 1);
844 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
845 NULL, (gchar **)login_icon_xpm);
846 b->pix = gtk_pixmap_new(pm, bm);
847 716
848 b->idle = 0; 717 b->idle = 0;
849 b->caps = 0; 718 b->caps = 0;
850 719
851 gtk_widget_show(b->pix);
852 gdk_pixmap_unref(pm);
853 gdk_bitmap_unref(bm);
854
855 b->label = gtk_label_new(buddy);
856 gtk_misc_set_alignment(GTK_MISC(b->label), 0.0, 0.5);
857
858 b->idletime = gtk_label_new("");
859
860 gtk_tree_append(GTK_TREE(g->tree),b->item);
861 gtk_container_add(GTK_CONTAINER(b->item), box);
862
863 gtk_box_pack_start(GTK_BOX(box), b->pix, FALSE, FALSE, 1);
864 gtk_box_pack_start(GTK_BOX(box), b->label, TRUE, TRUE, 1);
865 gtk_box_pack_start(GTK_BOX(box), b->idletime, FALSE, FALSE, 1);
866
867 gtk_widget_show(b->label);
868 gtk_widget_show(box);
869
870 gtk_object_set_user_data(GTK_OBJECT(b->item), b);
871
872 gtk_signal_connect(GTK_OBJECT(b->item), "button_press_event",
873 GTK_SIGNAL_FUNC(handle_click_buddy), b);
874
875 return b; 720 return b;
876 } 721 }
877 722
878 723
879 struct group *add_group(char *group) 724 struct group *add_group(struct gaim_connection *gc, char *group)
880 { 725 {
881 struct group *g = find_group(group); 726 struct group *g = find_group(gc, group);
882 if (g) 727 if (g)
883 return g; 728 return g;
884 g = (struct group *)g_new0(struct group, 1); 729 g = (struct group *)g_new0(struct group, 1);
885 if (!g) 730 if (!g)
886 return NULL; 731 return NULL;
887 732
888 strncpy(g->name, group, sizeof(g->name)); 733 strncpy(g->name, group, sizeof(g->name));
889 groups = g_slist_append(groups, g); 734 gc->groups = g_slist_append(gc->groups, g);
890 735
891 if (blist == NULL)
892 return g;
893
894 g->item = gtk_tree_item_new();
895 g->label = gtk_label_new(g->name);
896 gtk_misc_set_alignment(GTK_MISC(g->label), 0.0, 0.5);
897 gtk_widget_show(g->label);
898 gtk_container_add(GTK_CONTAINER(g->item), g->label);
899 g->tree = gtk_tree_new();
900 gtk_widget_show(g->item);
901 gtk_widget_show(g->tree);
902 gtk_tree_append(GTK_TREE(buddies), g->item);
903 gtk_tree_item_set_subtree(GTK_TREE_ITEM(g->item), g->tree);
904 gtk_tree_item_expand(GTK_TREE_ITEM(g->item));
905 gtk_signal_connect(GTK_OBJECT(g->item), "button_press_event",
906 GTK_SIGNAL_FUNC(handle_click_group),
907 NULL);
908 gtk_object_set_user_data(GTK_OBJECT(g->item), NULL);
909 g->members = NULL; 736 g->members = NULL;
910 if (display_options & OPT_DISP_NO_MT_GRP) 737
911 gtk_widget_hide(g->item);
912
913
914 build_edit_tree(); 738 build_edit_tree();
915 739
916 return g; 740 return g;
917
918 } 741 }
919 742
920 743
921 static void do_del_buddy(GtkWidget *w, GtkCTree *ctree) 744 static void do_del_buddy(GtkWidget *w, GtkCTree *ctree)
922 { 745 {
923 GtkCTreeNode *node; 746 GtkCTreeNode *node;
924 char *bud, *grp; 747 char *bud, *grp;
925 struct buddy *b; 748 struct buddy *b;
926 struct group *g; 749 struct group *g;
750 struct gaim_connection *gc;
927 GList *i; 751 GList *i;
928 752
929 i = GTK_CLIST(edittree)->selection; 753 i = GTK_CLIST(edittree)->selection;
930 if (i) { 754 if (i) {
931 node = i->data; 755 node = i->data;
756 gc = (struct gaim_connection *)gtk_ctree_node_get_row_data(GTK_CTREE(edittree), node);
932 757
933 if (GTK_CTREE_ROW(node)->is_leaf) { 758 if (GTK_CTREE_ROW(node)->is_leaf) {
934 gtk_ctree_get_node_info (GTK_CTREE(edittree), node, &bud, 759 gtk_ctree_get_node_info (GTK_CTREE(edittree), node, &bud,
935 NULL, NULL, NULL, NULL, NULL, NULL, NULL); 760 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
936 761
937 b = find_buddy(bud); 762 b = find_buddy(gc, bud);
938 g = find_group_by_buddy(bud); 763 g = find_group_by_buddy(gc, bud);
939 remove_buddy(g, b); 764 remove_buddy(gc, g, b);
940 } else { 765 } else {
941 gtk_ctree_get_node_info (ctree, node, &grp, 766 gtk_ctree_get_node_info (ctree, node, &grp,
942 NULL, NULL, NULL, NULL, NULL, NULL, NULL); 767 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
943 g = find_group(grp); 768 if (strcmp(gc->username, grp)) {
944 remove_group(g); 769 g = find_group(gc, grp);
770 remove_group(gc, g);
771 }
945 } 772 }
946 773
947 build_edit_tree(); 774 build_edit_tree();
948 serv_save_config();
949 775
950 // flush buddy list to cache 776 // flush buddy list to cache
951 777
952 do_export( (GtkWidget *) NULL, 0 ); 778 do_export( (GtkWidget *) NULL, 0 );
953 779
954 } else { 780 } else {
955 /* Nothing selected. */ 781 /* Nothing selected. */
956 } 782 }
957 update_num_groups();
958 } 783 }
959 784
960 785
961 void import_callback(GtkWidget *widget, void *null) 786 void import_callback(GtkWidget *widget, void *null)
962 { 787 {
988 gaim_plugin_remove = dlsym(p->handle, "gaim_plugin_remove"); 813 gaim_plugin_remove = dlsym(p->handle, "gaim_plugin_remove");
989 if ((error = (char *)dlerror()) == NULL) 814 if ((error = (char *)dlerror()) == NULL)
990 (*gaim_plugin_remove)(); 815 (*gaim_plugin_remove)();
991 /* we don't need to worry about removing callbacks since 816 /* we don't need to worry about removing callbacks since
992 * there won't be any more chance to call them back :) */ 817 * there won't be any more chance to call them back :) */
993 dlclose(p->handle);
994 g_free(p->filename); /* why do i bother? */ 818 g_free(p->filename); /* why do i bother? */
995 g_free(p); 819 g_free(p);
996 c = c->next; 820 c = c->next;
997 } 821 }
998 #endif 822 #endif
1006 void add_buddy_callback(GtkWidget *widget, void *dummy) 830 void add_buddy_callback(GtkWidget *widget, void *dummy)
1007 { 831 {
1008 char *grp = NULL; 832 char *grp = NULL;
1009 GtkCTreeNode *node; 833 GtkCTreeNode *node;
1010 GList *i; 834 GList *i;
835 struct gaim_connection *gc = NULL;
1011 836
1012 i = GTK_CLIST(edittree)->selection; 837 i = GTK_CLIST(edittree)->selection;
1013 if (i) { 838 if (i) {
1014 node = i->data; 839 node = i->data;
840 gc = (struct gaim_connection *)gtk_ctree_node_get_row_data(GTK_CTREE(edittree), node);
1015 841
1016 if (GTK_CTREE_ROW(node)->is_leaf) { 842 if (GTK_CTREE_ROW(node)->is_leaf) {
1017 node = GTK_CTREE_ROW(node)->parent; 843 node = GTK_CTREE_ROW(node)->parent;
844 } else if (gc) {
845 gtk_ctree_get_node_info (GTK_CTREE(edittree), node, &grp,
846 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1018 } 847 }
1019 848 }
1020 gtk_ctree_get_node_info (GTK_CTREE(edittree), node, &grp, 849 show_add_buddy(gc, NULL, grp);
1021 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1022 }
1023 show_add_buddy(NULL, grp);
1024 850
1025 } 851 }
1026 852
1027 void add_group_callback(GtkWidget *widget, void *dummy) 853 void add_group_callback(GtkWidget *widget, void *dummy)
1028 { 854 {
1073 void chat_callback(GtkWidget *widget, GtkTree *tree) 899 void chat_callback(GtkWidget *widget, GtkTree *tree)
1074 { 900 {
1075 join_chat(); 901 join_chat();
1076 } 902 }
1077 903
1078 struct group *find_group(char *group) 904 struct group *find_group(struct gaim_connection *gc, char *group)
1079 { 905 {
1080 struct group *g; 906 struct group *g;
1081 GSList *grp = groups; 907 GSList *grp;
908 GSList *c = connections;
909 struct gaim_connection *z;
1082 char *grpname = g_malloc(strlen(group) + 1); 910 char *grpname = g_malloc(strlen(group) + 1);
1083 911
1084 strcpy(grpname, normalize(group)); 912 strcpy(grpname, normalize(group));
1085 while (grp) { 913 if (gc) {
1086 g = (struct group *)grp->data; 914 grp = gc->groups;
1087 if (!strcasecmp(normalize(g->name), grpname)) { 915 while (grp) {
1088 g_free(grpname); 916 g = (struct group *)grp->data;
1089 return g; 917 if (!strcasecmp(normalize(g->name), grpname)) {
918 g_free(grpname);
919 return g;
920 }
921 grp = g_slist_next(grp);
1090 } 922 }
1091 grp = g_slist_next(grp); 923
1092 } 924 g_free(grpname);
1093 925 return NULL;
1094 g_free(grpname); 926 } else {
1095 return NULL; 927 while(c) {
1096 928 z = (struct gaim_connection *)c->data;
1097 } 929 grp = z->groups;
1098 930 while (grp) {
1099 931 g = (struct group *)grp->data;
1100 struct group *find_group_by_buddy(char *who) 932 if (!strcasecmp(normalize(g->name), grpname)) {
933 g_free(grpname);
934 return g;
935 }
936 grp = g_slist_next(grp);
937 }
938
939 c = c->next;
940 }
941 g_free(grpname);
942 return NULL;
943 }
944 }
945
946
947 struct group *find_group_by_buddy(struct gaim_connection *gc, char *who)
1101 { 948 {
1102 struct group *g; 949 struct group *g;
1103 struct buddy *b; 950 struct buddy *b;
1104 GSList *grp = groups; 951 GSList *grp;
1105 GList *mem; 952 GSList *mem;
1106 char *whoname = g_malloc(strlen(who) + 1); 953 char *whoname = g_malloc(strlen(who) + 1);
1107 954
1108 strcpy(whoname, normalize(who)); 955 strcpy(whoname, normalize(who));
1109 956
1110 while(grp) { 957 if (gc) {
1111 g = (struct group *)grp->data; 958 grp = gc->groups;
1112 959 while(grp) {
1113 mem = g->members; 960 g = (struct group *)grp->data;
1114 while(mem) { 961
1115 b = (struct buddy *)mem->data; 962 mem = g->members;
1116 if (!strcasecmp(normalize(b->name), whoname)) { 963 while(mem) {
1117 g_free(whoname); 964 b = (struct buddy *)mem->data;
1118 return g; 965 if (!strcasecmp(normalize(b->name), whoname)) {
966 g_free(whoname);
967 return g;
968 }
969 mem = mem->next;
1119 } 970 }
1120 mem = mem->next; 971 grp = g_slist_next(grp);
1121 } 972 }
1122 grp = g_slist_next(grp); 973 g_free(whoname);
1123 } 974 return NULL;
1124 g_free(whoname); 975 } else {
1125 return NULL; 976 GSList *c = connections;
1126 } 977 struct gaim_connection *z;
1127 978 while (c) {
1128 979 z = (struct gaim_connection *)c->data;
1129 struct buddy *find_buddy(char *who) 980 grp = z->groups;
981 while(grp) {
982 g = (struct group *)grp->data;
983
984 mem = g->members;
985 while(mem) {
986 b = (struct buddy *)mem->data;
987 if (!strcasecmp(normalize(b->name), whoname)) {
988 g_free(whoname);
989 return g;
990 }
991 mem = mem->next;
992 }
993 grp = g_slist_next(grp);
994 }
995 c = c->next;
996 }
997 g_free(whoname);
998 return NULL;
999 }
1000 }
1001
1002
1003 struct buddy *find_buddy(struct gaim_connection *gc, char *who)
1130 { 1004 {
1131 struct group *g; 1005 struct group *g;
1132 struct buddy *b; 1006 struct buddy *b;
1133 GSList *grp = groups; 1007 GSList *grp;
1134 GList *mem; 1008 GSList *c;
1009 struct gaim_connection *z;
1010 GSList *mem;
1135 char *whoname = g_malloc(strlen(who) + 1); 1011 char *whoname = g_malloc(strlen(who) + 1);
1136 1012
1137 strcpy(whoname, normalize(who)); 1013 strcpy(whoname, normalize(who));
1138 1014 if (gc) {
1139 while(grp) { 1015 grp = gc->groups;
1140 g = (struct group *)grp->data; 1016 while(grp) {
1141 1017 g = (struct group *)grp->data;
1142 mem = g->members; 1018
1143 while(mem) { 1019 mem = g->members;
1144 b = (struct buddy *)mem->data; 1020 while(mem) {
1145 if (!strcasecmp(normalize(b->name), whoname)) { 1021 b = (struct buddy *)mem->data;
1146 g_free(whoname); 1022 if (!strcasecmp(normalize(b->name), whoname)) {
1147 return b; 1023 g_free(whoname);
1024 return b;
1025 }
1026 mem = mem->next;
1148 } 1027 }
1149 mem = mem->next; 1028 grp = g_slist_next(grp);
1150 } 1029 }
1151 grp = g_slist_next(grp); 1030 g_free(whoname);
1152 } 1031 return NULL;
1153 g_free(whoname); 1032 } else {
1154 return NULL; 1033 c = connections;
1034 while (c) {
1035 z = (struct gaim_connection *)c->data;
1036 grp = z->groups;
1037 while(grp) {
1038 g = (struct group *)grp->data;
1039
1040 mem = g->members;
1041 while(mem) {
1042 b = (struct buddy *)mem->data;
1043 if (!strcasecmp(normalize(b->name), whoname)) {
1044 g_free(whoname);
1045 return b;
1046 }
1047 mem = mem->next;
1048 }
1049 grp = g_slist_next(grp);
1050 }
1051 c = c->next;
1052 }
1053 g_free(whoname);
1054 return NULL;
1055 }
1155 } 1056 }
1156 1057
1157 1058
1158 void rem_bp(GtkWidget *w, struct buddy_pounce *b) 1059 void rem_bp(GtkWidget *w, struct buddy_pounce *b)
1159 { 1060 {
1304 1205
1305 bp = bp->next; 1206 bp = bp->next;
1306 1207
1307 } 1208 }
1308 1209
1309 }
1310
1311
1312 gint log_timeout(char *name)
1313 {
1314 struct buddy *b;
1315 struct group *g;
1316
1317 b = find_buddy(name);
1318
1319 if(!b)
1320 return FALSE;
1321
1322 b->log_timer = 0;
1323
1324 if (!b->present) {
1325 gtk_widget_hide(b->item);
1326 g = find_group_by_buddy(name);
1327 if (GTK_TREE_ITEM(g->item)->expanded) {
1328 gtk_tree_item_collapse(GTK_TREE_ITEM(g->item));
1329 gtk_tree_item_expand(GTK_TREE_ITEM(g->item));
1330 }
1331 } else
1332 set_buddy(b);
1333
1334 return FALSE;
1335 } 1210 }
1336 1211
1337 1212
1338 static char *caps_string(u_short caps) 1213 static char *caps_string(u_short caps)
1339 { 1214 {
1368 } 1243 }
1369 return buf; 1244 return buf;
1370 } 1245 }
1371 1246
1372 1247
1373 void set_buddy(struct buddy *b) 1248 static struct group_show *find_group_show(char *group) {
1374 { 1249 GSList *m = shows;
1375 char infotip[256]; 1250 struct group_show *g = NULL;
1376 char idlet[16]; 1251
1377 char warn[256]; 1252 while (m) {
1378 char caps[256]; 1253 g = (struct group_show *)m->data;
1379 char *who; 1254 if (!strcmp(g->name, group))
1380 int i; 1255 break;
1381 int ihrs, imin; 1256 g = NULL;
1382 time_t t; 1257 m = m->next;
1258 }
1259
1260 return g;
1261 }
1262
1263 static struct buddy_show *find_buddy_show(struct group_show *gs, char *name) {
1264 GSList *m = gs->members;
1265 struct buddy_show *b = NULL;
1266
1267 while (m) {
1268 b = (struct buddy_show *)m->data;
1269 if (!strcmp(b->name, name))
1270 break;
1271 b = NULL;
1272 m = m->next;
1273 }
1274
1275 return b;
1276 }
1277
1278 static struct group_show *new_group_show(char *group) {
1279 struct group_show *g = g_new0(struct group_show, 1);
1280
1281 g->name = g_strdup(group);
1282
1283 g->item = gtk_tree_item_new();
1284 /* FIXME */
1285 gtk_tree_append(GTK_TREE(buddies), g->item);
1286 gtk_signal_connect(GTK_OBJECT(g->item), "button_press_event",
1287 GTK_SIGNAL_FUNC(handle_click_group), NULL);
1288 gtk_widget_show(g->item);
1289
1290 g->label = gtk_label_new(group);
1291 gtk_misc_set_alignment(GTK_MISC(g->label), 0.0, 0.5);
1292 gtk_container_add(GTK_CONTAINER(g->item), g->label);
1293 gtk_widget_show(g->label);
1294
1295 g->tree = gtk_tree_new();
1296 gtk_tree_item_set_subtree(GTK_TREE_ITEM(g->item), g->tree);
1297 gtk_tree_item_expand(GTK_TREE_ITEM(g->item));
1298 gtk_widget_show(g->tree);
1299
1300 /* FIXME */
1301 shows = g_slist_append(shows, g);
1302 return g;
1303 }
1304
1305 static struct buddy_show *new_buddy_show(struct group_show *gs, char *buddy) {
1306 struct buddy_show *b = g_new0(struct buddy_show, 1);
1307 GtkWidget *box;
1383 GdkPixmap *pm; 1308 GdkPixmap *pm;
1384 GdkBitmap *bm; 1309 GdkBitmap *bm;
1385 char *itime, *sotime; 1310
1386 1311 b->name = g_strdup(buddy);
1387 if (b->present) { 1312
1388 time(&t); 1313 b->item = gtk_tree_item_new();
1389 1314 /* FIXME */
1390 ihrs = (t - b->idle) / 3600; 1315 gtk_tree_append(GTK_TREE(gs->tree), b->item);
1391 imin = ((t - b->idle) / 60) % 60; 1316 gtk_object_set_user_data(GTK_OBJECT(b->item), b);
1392 1317 gtk_signal_connect(GTK_OBJECT(b->item), "button_press_event",
1393 if (ihrs) 1318 GTK_SIGNAL_FUNC(handle_click_buddy), b);
1394 g_snprintf(idlet, sizeof(idlet), "(%d:%02d)", ihrs, imin); 1319 gtk_widget_show(b->item);
1395 else 1320
1396 g_snprintf(idlet, sizeof(idlet), "(%02d)", imin); 1321 box = gtk_hbox_new(FALSE, 1);
1397 1322 gtk_container_add(GTK_CONTAINER(b->item), box);
1398 gtk_widget_hide(b->idletime); 1323 gtk_widget_show(box);
1399 1324
1400 if (b->idle) 1325 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm, NULL, (char **)login_icon_xpm);
1401 gtk_label_set(GTK_LABEL(b->idletime), idlet); 1326 b->pix = gtk_pixmap_new(pm, bm);
1402 else 1327 gtk_box_pack_start(GTK_BOX(box), b->pix, FALSE, FALSE, 1);
1403 gtk_label_set(GTK_LABEL(b->idletime), ""); 1328 gtk_widget_show(b->pix);
1404 if (display_options & OPT_DISP_SHOW_IDLETIME) 1329 gdk_pixmap_unref(pm);
1405 gtk_widget_show(b->idletime); 1330 gdk_bitmap_unref(bm);
1406 1331
1407 1332 b->label = gtk_label_new(buddy);
1408 sotime = sec_to_text(t - b->signon + correction_time); 1333 gtk_misc_set_alignment(GTK_MISC(b->label), 0.0, 0.5);
1409 if (b->idle) { 1334 gtk_box_pack_start(GTK_BOX(box), b->label, TRUE, TRUE, 1);
1410 itime = sec_to_text(t - b->idle); 1335 gtk_widget_show(b->label);
1411 } else { 1336
1412 itime = g_malloc(1); 1337 /* FIXME */
1413 itime[0] = 0; 1338 gs->members = g_slist_append(gs->members, b);
1414 } 1339 return b;
1415 1340 }
1416 if (b->evil) { 1341
1417 g_snprintf(warn, sizeof(warn), _("Warnings: %d%%\n"), b->evil); 1342 static struct group_show *find_gs_by_bs(struct buddy_show *b) {
1418 1343 GSList *m, *n;
1419 } else 1344 struct group_show *g = NULL;
1420 warn[0] = '\0'; 1345 struct buddy_show *h;
1421 1346
1422 if (b->caps) { 1347 m = shows;
1423 g_snprintf(caps, sizeof(caps), _("Capabilities: %s\n"), caps_string(b->caps)); 1348 while (m) {
1424 } else 1349 g = (struct group_show *)m->data;
1425 caps[0] = '\0'; 1350 n = g->members;
1426 1351 while (n) {
1427 i = g_snprintf(infotip, sizeof(infotip), _("Alias: %s \nScreen Name: %s\nLogged in: %s\n%s%s%s%s%s"), b->show, b->name, sotime, warn, ((b->idle) ? _("Idle: ") : ""), itime, ((b->idle) ? "\n" : ""), caps); 1352 h = (struct buddy_show *)n->data;
1428 1353 if (h == b)
1429 gtk_tooltips_set_tip(tips, GTK_WIDGET(b->item), infotip, ""); 1354 return g;
1430 1355 n = n->next;
1431 g_free(sotime); 1356 }
1432 g_free(itime); 1357 g = NULL;
1433 1358 m = m->next;
1434 1359 }
1435 1360
1436 /* this check should also depend on whether they left, 1361 return g;
1437 * and signed on again before they got erased */ 1362 }
1438 if (!GTK_WIDGET_VISIBLE(b->item) || b->present == 1) { 1363
1439 plugin_event(event_buddy_signon, b->name, 0, 0, 0); 1364 static int log_timeout(struct buddy_show *b) {
1440 1365 if (!b->connlist) {
1366 struct group_show *g = find_gs_by_bs(b);
1367 g->members = g_slist_remove(g->members, b);
1368 gtk_widget_destroy(b->item);
1369 if (g->members == NULL && (display_options & OPT_DISP_NO_MT_GRP)) {
1370 shows = g_slist_remove(shows, g);
1371 gtk_widget_destroy(g->item);
1372 g_free(g->name);
1373 g_free(g);
1374 }
1375 g_free(b->name);
1376 g_free(b);
1377 } else {
1378 /* um.... what do we have to do here? just update the pixmap? */
1379 GdkPixmap *pm;
1380 GdkBitmap *bm;
1381 gchar **xpm = NULL;
1382 struct buddy *light = find_buddy(b->connlist->data, b->name);
1383 if (((struct gaim_connection *)b->connlist->data)->prpl->list_icon)
1384 xpm = (*((struct gaim_connection *)b->connlist->data)->prpl->list_icon)(light->uc);
1385 if (xpm == NULL)
1386 xpm = (char **)no_icon_xpm;
1387 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm, NULL, xpm);
1388 gtk_widget_hide(b->pix);
1389 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm);
1390 gtk_widget_show(b->pix);
1391 if (ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER)
1392 BuddyTickerSetPixmap(b->name, pm, bm);
1393 gdk_pixmap_unref(pm);
1394 gdk_bitmap_unref(bm);
1395 }
1396 b->log_timer = -1;
1397 return FALSE;
1398 }
1399
1400 void set_buddy(struct gaim_connection *gc, struct buddy *b)
1401 {
1402 time_t t;
1403 struct group *g = find_group_by_buddy(gc, b->name);
1404 struct group_show *gs;
1405 struct buddy_show *bs;
1406 GdkPixmap *pm;
1407 GdkBitmap *bm;
1408 char **xpm = NULL;
1409 if (b->present) {
1410 if ((gs = find_group_show(g->name)) == NULL)
1411 gs = new_group_show(g->name);
1412 if ((bs = find_buddy_show(gs, b->name)) == NULL)
1413 bs = new_buddy_show(gs, b->name);
1414 if (b->present == 1) {
1441 play_sound(BUDDY_ARRIVE); 1415 play_sound(BUDDY_ARRIVE);
1442 b->present = 2; 1416 b->present = 2;
1443 1417 if (b->log_timer > 0)
1444 who = g_malloc(sizeof(b->show) + 10); 1418 gtk_timeout_remove(b->log_timer);
1445 strcpy(who, b->show); 1419 if (!g_slist_find(bs->connlist, gc))
1446 gtk_label_set(GTK_LABEL(b->label), who); 1420 bs->connlist = g_slist_append(bs->connlist, gc);
1447 g_free(who); 1421 b->log_timer = gtk_timeout_add(10000, (GtkFunction)log_timeout, bs);
1448 1422 } else {
1449 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm, 1423 if (gc->prpl->list_icon)
1450 NULL, (gchar **)login_icon_xpm); 1424 xpm = (*gc->prpl->list_icon)(b->uc);
1451 gtk_widget_hide(b->pix); 1425 if (xpm == NULL)
1452 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm); 1426 xpm = (char **)no_icon_xpm;
1453 if (display_options & OPT_DISP_SHOW_PIXMAPS) 1427 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm, NULL, xpm);
1454 gtk_widget_show(b->pix); 1428 gtk_widget_hide(bs->pix);
1429 gtk_pixmap_set(GTK_PIXMAP(bs->pix), pm, bm);
1430 gtk_widget_show(bs->pix);
1431 if (ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER)
1432 BuddyTickerSetPixmap(b->name, pm, bm);
1455 gdk_pixmap_unref(pm); 1433 gdk_pixmap_unref(pm);
1456 gdk_bitmap_unref(bm); 1434 gdk_bitmap_unref(bm);
1457 1435 }
1458 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1459 NULL, (gchar **)login_icon_xpm);
1460
1461 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1462 BuddyTickerAddUser( b->name, pm, bm );
1463 gdk_pixmap_unref(pm);
1464 gdk_bitmap_unref(bm);
1465
1466 if (display_options & OPT_DISP_SHOW_LOGON) {
1467 struct conversation *c = find_conversation(b->name);
1468 if (c) {
1469 char tmp[1024];
1470
1471
1472 g_snprintf(tmp, sizeof(tmp), _("<HR><B>%s logged in%s%s.</B><BR><HR>"), b->name,
1473 ((display_options & OPT_DISP_SHOW_TIME) ? " @ " : ""),
1474 ((display_options & OPT_DISP_SHOW_TIME) ? date() : ""));
1475
1476
1477 write_to_conv(c, tmp, WFLAG_SYSTEM, NULL);
1478
1479 }
1480 }
1481
1482
1483 { struct group *g = find_group_by_buddy(b->name);
1484 gtk_widget_show(g->item); }
1485 gtk_widget_show(b->item);
1486 gtk_widget_show(b->label);
1487 b->log_timer = gtk_timeout_add(10000, (GtkFunction) log_timeout, b->name);
1488 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1489 gtk_timeout_add(10000, (GtkFunction) BuddyTickerLogonTimeout, b->name);
1490 update_num_groups();
1491 update_show_idlepix();
1492 setup_buddy_chats();
1493 return;
1494 }
1495
1496
1497
1498 if (!b->log_timer) {
1499 gtk_widget_hide(b->pix);
1500 if (b->uc & UC_UNAVAILABLE) {
1501 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1502 NULL, (gchar **)away_icon_xpm);
1503 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm);
1504 gdk_pixmap_unref(pm);
1505 gdk_bitmap_unref(bm);
1506 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1507 {
1508 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1509 NULL, (gchar **)away_icon_xpm);
1510 BuddyTickerSetPixmap(b->name, pm, bm);
1511 gdk_pixmap_unref(pm);
1512 gdk_bitmap_unref(bm);
1513 }
1514 } else if (b->uc & UC_AOL) {
1515 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1516 NULL, (gchar **)aol_icon_xpm);
1517 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm);
1518 gdk_pixmap_unref(pm);
1519 gdk_bitmap_unref(bm);
1520 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1521 {
1522 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1523 NULL, (gchar **)aol_icon_xpm);
1524 BuddyTickerSetPixmap(b->name, pm, bm);
1525 gdk_pixmap_unref(pm);
1526 gdk_bitmap_unref(bm);
1527 }
1528 } else if (b->uc & UC_NORMAL) {
1529 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1530 NULL, (gchar **)free_icon_xpm);
1531 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm);
1532 gdk_pixmap_unref(pm);
1533 gdk_bitmap_unref(bm);
1534 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1535 {
1536 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1537 NULL, (gchar **)free_icon_xpm);
1538 BuddyTickerSetPixmap(b->name, pm, bm);
1539 gdk_pixmap_unref(pm);
1540 gdk_bitmap_unref(bm);
1541 }
1542 } else if (b->uc & UC_ADMIN) {
1543 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1544 NULL, (gchar **)admin_icon_xpm);
1545 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm);
1546 gdk_pixmap_unref(pm);
1547 gdk_bitmap_unref(bm);
1548 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1549 {
1550 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1551 NULL, (gchar **)admin_icon_xpm);
1552 BuddyTickerSetPixmap(b->name, pm, bm);
1553 gdk_pixmap_unref(pm);
1554 gdk_bitmap_unref(bm);
1555 }
1556 } else if (b->uc & UC_UNCONFIRMED) {
1557 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1558 NULL, (gchar **)dt_icon_xpm);
1559 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm);
1560 gdk_pixmap_unref(pm);
1561 gdk_bitmap_unref(bm);
1562 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1563 {
1564 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1565 NULL, (gchar **)dt_icon_xpm);
1566 BuddyTickerSetPixmap(b->name, pm, bm);
1567 gdk_pixmap_unref(pm);
1568 gdk_bitmap_unref(bm);
1569 }
1570 } else {
1571 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1572 NULL, (gchar **)no_icon_xpm);
1573 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm);
1574 gdk_pixmap_unref(pm);
1575 gdk_bitmap_unref(bm);
1576 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1577 {
1578 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm,
1579 NULL, (gchar **)no_icon_xpm);
1580 BuddyTickerSetPixmap(b->name, pm, bm);
1581 gdk_pixmap_unref(pm);
1582 gdk_bitmap_unref(bm);
1583 }
1584 }
1585 if (display_options & OPT_DISP_SHOW_PIXMAPS)
1586 gtk_widget_show(b->pix);
1587 }
1588
1589
1590
1591 } else { 1436 } else {
1592 if (GTK_WIDGET_VISIBLE(b->item)) { 1437 play_sound(BUDDY_LEAVE);
1593 plugin_event(event_buddy_signoff, b->name, 0, 0, 0); 1438 gs = find_group_show(g->name);
1594 play_sound(BUDDY_LEAVE); 1439 bs = find_buddy_show(gs, b->name);
1595 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm, 1440 bs->connlist = g_slist_remove(bs->connlist, gc);
1596 NULL, (gchar **)logout_icon_xpm); 1441 if (b->log_timer > 0)
1597 gtk_widget_hide(b->pix); 1442 gtk_timeout_remove(b->log_timer);
1598 gtk_pixmap_set(GTK_PIXMAP(b->pix), pm, bm); 1443 b->log_timer = gtk_timeout_add(10000, (GtkFunction)log_timeout, bs);
1599 if (display_options & OPT_DISP_SHOW_PIXMAPS) 1444 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm, NULL, logout_icon_xpm);
1600 gtk_widget_show(b->pix); 1445 gtk_widget_hide(bs->pix);
1601 gdk_pixmap_unref(pm); 1446 gtk_pixmap_set(GTK_PIXMAP(bs->pix), pm, bm);
1602 gdk_bitmap_unref(bm); 1447 gtk_widget_show(bs->pix);
1603 pm = gdk_pixmap_create_from_xpm_d(blist->window, &bm, 1448 if (ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER)
1604 NULL, (gchar **)logout_icon_xpm); 1449 BuddyTickerSetPixmap(b->name, pm, bm);
1605 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER ) 1450 gdk_pixmap_unref(pm);
1606 BuddyTickerSetPixmap( b->name, pm, bm ); 1451 gdk_bitmap_unref(bm);
1607 gdk_pixmap_unref(pm); 1452 }
1608 gdk_bitmap_unref(bm);
1609 if (display_options & OPT_DISP_SHOW_LOGON) {
1610 struct conversation *c = find_conversation(b->name);
1611 if (c) {
1612 char tmp[1024];
1613
1614
1615 g_snprintf(tmp, sizeof(tmp), _("<HR><B>%s logged out%s%s.</B><BR><HR>"), b->name,
1616 ((display_options & OPT_DISP_SHOW_TIME) ? " @ " : ""),
1617 ((display_options & OPT_DISP_SHOW_TIME) ? date() : ""));
1618
1619
1620 write_to_conv(c, tmp, WFLAG_SYSTEM, NULL);
1621
1622 }
1623 }
1624 b->log_timer = gtk_timeout_add(10000, (GtkFunction)log_timeout, b->name);
1625 if ( ticker_prefs & OPT_DISP_SHOW_BUDDYTICKER )
1626 gtk_timeout_add(10000, (GtkFunction)BuddyTickerLogoutTimeout, b->name);
1627 update_num_groups();
1628 update_show_idlepix();
1629 }
1630 }
1631 setup_buddy_chats();
1632 } 1453 }
1633 1454
1634 1455
1635 static void move_blist_window(GtkWidget *w, GdkEventConfigure *e, void *dummy) 1456 static void move_blist_window(GtkWidget *w, GdkEventConfigure *e, void *dummy)
1636 { 1457 {
2084 } 1905 }
2085 1906
2086 void refresh_buddy_window() 1907 void refresh_buddy_window()
2087 { 1908 {
2088 build_edit_tree(); 1909 build_edit_tree();
2089 build_permit_tree();
2090 1910
2091 update_button_pix(); 1911 update_button_pix();
2092 gtk_widget_show(blist); 1912 gtk_widget_show(blist);
2093 } 1913 }
2094 1914