| 235 |
227 |
| 236 g_free(displayed); |
228 g_free(displayed); |
| 237 g_free(sent); |
229 g_free(sent); |
| 238 } |
230 } |
| 239 |
231 |
| 240 GaimConvWindow * |
|
| 241 gaim_conv_window_new(void) |
|
| 242 { |
|
| 243 GaimConvWindow *win; |
|
| 244 |
|
| 245 win = g_new0(GaimConvWindow, 1); |
|
| 246 GAIM_DBUS_REGISTER_POINTER(win, GaimConvWindow); |
|
| 247 |
|
| 248 windows = g_list_append(windows, win); |
|
| 249 |
|
| 250 win->ui_ops = gaim_conversations_get_win_ui_ops(); |
|
| 251 |
|
| 252 if (win->ui_ops != NULL && win->ui_ops->new_window != NULL) |
|
| 253 win->ui_ops->new_window(win); |
|
| 254 |
|
| 255 return win; |
|
| 256 } |
|
| 257 |
|
| 258 void |
|
| 259 gaim_conv_window_destroy(GaimConvWindow *win) |
|
| 260 { |
|
| 261 GaimConvWindowUiOps *ops; |
|
| 262 GList *node; |
|
| 263 |
|
| 264 g_return_if_fail(win != NULL); |
|
| 265 |
|
| 266 ops = gaim_conv_window_get_ui_ops(win); |
|
| 267 |
|
| 268 /* |
|
| 269 * If there are any conversations in this, destroy them all. The last |
|
| 270 * conversation will call gaim_conv_window_destroy(), but this time, this |
|
| 271 * check will fail and the window will actually be destroyed. |
|
| 272 * |
|
| 273 * This is needed because chats may not close right away. They may |
|
| 274 * wait for notification first. When they get that, the window is |
|
| 275 * already destroyed, and gaim either crashes or spits out gtk warnings. |
|
| 276 * The problem is fixed with this check. |
|
| 277 */ |
|
| 278 if (gaim_conv_window_get_conversation_count(win) > 0) { |
|
| 279 |
|
| 280 node = g_list_first(gaim_conv_window_get_conversations(win)); |
|
| 281 while(node != NULL) |
|
| 282 { |
|
| 283 GaimConversation *conv = node->data; |
|
| 284 |
|
| 285 node = g_list_next(node); |
|
| 286 |
|
| 287 gaim_conversation_destroy(conv); |
|
| 288 } |
|
| 289 } |
|
| 290 else |
|
| 291 { |
|
| 292 if (ops != NULL && ops->destroy_window != NULL) |
|
| 293 ops->destroy_window(win); |
|
| 294 |
|
| 295 g_list_free(gaim_conv_window_get_conversations(win)); |
|
| 296 |
|
| 297 windows = g_list_remove(windows, win); |
|
| 298 |
|
| 299 GAIM_DBUS_UNREGISTER_POINTER(win); |
|
| 300 g_free(win); |
|
| 301 } |
|
| 302 } |
|
| 303 |
|
| 304 void |
|
| 305 gaim_conv_window_show(GaimConvWindow *win) |
|
| 306 { |
|
| 307 GaimConvWindowUiOps *ops; |
|
| 308 |
|
| 309 g_return_if_fail(win != NULL); |
|
| 310 |
|
| 311 ops = gaim_conv_window_get_ui_ops(win); |
|
| 312 |
|
| 313 if (ops == NULL || ops->show == NULL) |
|
| 314 return; |
|
| 315 |
|
| 316 ops->show(win); |
|
| 317 } |
|
| 318 |
|
| 319 void |
|
| 320 gaim_conv_window_hide(GaimConvWindow *win) |
|
| 321 { |
|
| 322 GaimConvWindowUiOps *ops; |
|
| 323 |
|
| 324 g_return_if_fail(win != NULL); |
|
| 325 |
|
| 326 ops = gaim_conv_window_get_ui_ops(win); |
|
| 327 |
|
| 328 if (ops == NULL || ops->hide == NULL) |
|
| 329 return; |
|
| 330 |
|
| 331 ops->hide(win); |
|
| 332 } |
|
| 333 |
|
| 334 void |
|
| 335 gaim_conv_window_raise(GaimConvWindow *win) |
|
| 336 { |
|
| 337 GaimConvWindowUiOps *ops; |
|
| 338 |
|
| 339 g_return_if_fail(win != NULL); |
|
| 340 |
|
| 341 ops = gaim_conv_window_get_ui_ops(win); |
|
| 342 |
|
| 343 if (ops == NULL || ops->raise == NULL) |
|
| 344 return; |
|
| 345 |
|
| 346 ops->raise(win); |
|
| 347 } |
|
| 348 |
|
| 349 gboolean |
|
| 350 gaim_conv_window_has_focus(GaimConvWindow *win) |
|
| 351 { |
|
| 352 gboolean ret = FALSE; |
|
| 353 GaimConvWindowUiOps *ops; |
|
| 354 |
|
| 355 g_return_val_if_fail(win != NULL, FALSE); |
|
| 356 |
|
| 357 ops = gaim_conv_window_get_ui_ops(win); |
|
| 358 |
|
| 359 if (ops != NULL && ops->has_focus != NULL) |
|
| 360 ret = ops->has_focus(win); |
|
| 361 |
|
| 362 return ret; |
|
| 363 } |
|
| 364 |
|
| 365 void |
|
| 366 gaim_conv_window_set_ui_ops(GaimConvWindow *win, GaimConvWindowUiOps *ops) |
|
| 367 { |
|
| 368 GaimConversationUiOps *conv_ops = NULL; |
|
| 369 GList *l; |
|
| 370 |
|
| 371 g_return_if_fail(win != NULL); |
|
| 372 |
|
| 373 if (win->ui_ops == ops) |
|
| 374 return; |
|
| 375 |
|
| 376 if (ops != NULL && ops->get_conversation_ui_ops != NULL) |
|
| 377 conv_ops = ops->get_conversation_ui_ops(); |
|
| 378 |
|
| 379 if (win->ui_ops != NULL && win->ui_ops->destroy_window != NULL) |
|
| 380 win->ui_ops->destroy_window(win); |
|
| 381 |
|
| 382 win->ui_ops = ops; |
|
| 383 |
|
| 384 if (win->ui_ops != NULL && win->ui_ops->new_window != NULL) |
|
| 385 win->ui_ops->new_window(win); |
|
| 386 |
|
| 387 for (l = gaim_conv_window_get_conversations(win); |
|
| 388 l != NULL; |
|
| 389 l = l->next) { |
|
| 390 |
|
| 391 GaimConversation *conv = (GaimConversation *)l; |
|
| 392 |
|
| 393 gaim_conversation_set_ui_ops(conv, conv_ops); |
|
| 394 |
|
| 395 if (win->ui_ops != NULL && win->ui_ops->add_conversation != NULL) |
|
| 396 win->ui_ops->add_conversation(win, conv); |
|
| 397 } |
|
| 398 } |
|
| 399 |
|
| 400 GaimConvWindowUiOps * |
|
| 401 gaim_conv_window_get_ui_ops(const GaimConvWindow *win) |
|
| 402 { |
|
| 403 g_return_val_if_fail(win != NULL, NULL); |
|
| 404 |
|
| 405 return win->ui_ops; |
|
| 406 } |
|
| 407 |
|
| 408 int |
|
| 409 gaim_conv_window_add_conversation(GaimConvWindow *win, GaimConversation *conv) |
|
| 410 { |
|
| 411 GaimConvWindowUiOps *ops; |
|
| 412 |
|
| 413 g_return_val_if_fail(win != NULL, -1); |
|
| 414 g_return_val_if_fail(conv != NULL, -1); |
|
| 415 |
|
| 416 if (gaim_conversation_get_window(conv) != NULL) { |
|
| 417 gaim_conv_window_remove_conversation( |
|
| 418 gaim_conversation_get_window(conv), |
|
| 419 conv); |
|
| 420 } |
|
| 421 |
|
| 422 ops = gaim_conv_window_get_ui_ops(win); |
|
| 423 |
|
| 424 win->conversations = g_list_append(win->conversations, conv); |
|
| 425 win->conversation_count++; |
|
| 426 |
|
| 427 if (ops != NULL) { |
|
| 428 conv->window = win; |
|
| 429 |
|
| 430 if (ops->get_conversation_ui_ops != NULL) |
|
| 431 gaim_conversation_set_ui_ops(conv, ops->get_conversation_ui_ops()); |
|
| 432 |
|
| 433 if (ops->add_conversation != NULL) |
|
| 434 ops->add_conversation(win, conv); |
|
| 435 } |
|
| 436 |
|
| 437 return win->conversation_count - 1; |
|
| 438 } |
|
| 439 |
|
| 440 GaimConversation * |
|
| 441 gaim_conv_window_remove_conversation(GaimConvWindow *win, GaimConversation *conv) |
|
| 442 { |
|
| 443 GaimConvWindowUiOps *ops; |
|
| 444 GList *node; |
|
| 445 |
|
| 446 g_return_val_if_fail(win != NULL, NULL); |
|
| 447 g_return_val_if_fail(conv != NULL, NULL); |
|
| 448 |
|
| 449 ops = gaim_conv_window_get_ui_ops(win); |
|
| 450 |
|
| 451 node = g_list_find(gaim_conv_window_get_conversations(win), conv); |
|
| 452 |
|
| 453 if (!node) |
|
| 454 return NULL; |
|
| 455 |
|
| 456 if (ops != NULL && ops->remove_conversation != NULL) |
|
| 457 ops->remove_conversation(win, conv); |
|
| 458 |
|
| 459 win->conversations = g_list_remove_link(win->conversations, node); |
|
| 460 |
|
| 461 g_list_free_1(node); |
|
| 462 |
|
| 463 win->conversation_count--; |
|
| 464 |
|
| 465 conv->window = NULL; |
|
| 466 |
|
| 467 if (gaim_conv_window_get_conversation_count(win) == 0) |
|
| 468 gaim_conv_window_destroy(win); |
|
| 469 |
|
| 470 return conv; |
|
| 471 } |
|
| 472 |
|
| 473 size_t |
|
| 474 gaim_conv_window_get_conversation_count(const GaimConvWindow *win) |
|
| 475 { |
|
| 476 g_return_val_if_fail(win != NULL, 0); |
|
| 477 |
|
| 478 return win->conversation_count; |
|
| 479 } |
|
| 480 |
|
| 481 void |
|
| 482 gaim_conv_window_switch_conversation(GaimConvWindow *win, GaimConversation *conv) |
|
| 483 { |
|
| 484 GaimConvWindowUiOps *ops; |
|
| 485 GaimConversation *old_conv; |
|
| 486 |
|
| 487 g_return_if_fail(win != NULL); |
|
| 488 g_return_if_fail(conv != NULL); |
|
| 489 |
|
| 490 old_conv = gaim_conv_window_get_active_conversation(win); |
|
| 491 |
|
| 492 gaim_signal_emit(gaim_conversations_get_handle(), |
|
| 493 "conversation-switching", old_conv, conv); |
|
| 494 |
|
| 495 ops = gaim_conv_window_get_ui_ops(win); |
|
| 496 |
|
| 497 if (ops != NULL && ops->switch_conversation != NULL) |
|
| 498 ops->switch_conversation(win, conv); |
|
| 499 |
|
| 500 gaim_signal_emit(gaim_conversations_get_handle(), |
|
| 501 "conversation-switched", old_conv, conv); |
|
| 502 } |
|
| 503 |
|
| 504 GaimConversation * |
|
| 505 gaim_conv_window_get_active_conversation(const GaimConvWindow *win) |
|
| 506 { |
|
| 507 GaimConvWindowUiOps *ops; |
|
| 508 |
|
| 509 g_return_val_if_fail(win != NULL, NULL); |
|
| 510 |
|
| 511 if (gaim_conv_window_get_conversation_count(win) == 0) |
|
| 512 return NULL; |
|
| 513 |
|
| 514 ops = gaim_conv_window_get_ui_ops(win); |
|
| 515 |
|
| 516 if (ops != NULL && ops->get_active_conversation != NULL) |
|
| 517 return ops->get_active_conversation(win); |
|
| 518 |
|
| 519 return NULL; |
|
| 520 } |
|
| 521 |
|
| 522 GList * |
|
| 523 gaim_conv_window_get_conversations(const GaimConvWindow *win) |
|
| 524 { |
|
| 525 g_return_val_if_fail(win != NULL, NULL); |
|
| 526 |
|
| 527 return win->conversations; |
|
| 528 } |
|
| 529 |
|
| 530 GList * |
|
| 531 gaim_get_windows(void) |
|
| 532 { |
|
| 533 return windows; |
|
| 534 } |
|
| 535 |
|
| 536 GaimConvWindow * |
|
| 537 gaim_get_first_window_with_type(GaimConversationType type) |
|
| 538 { |
|
| 539 GList *wins, *convs; |
|
| 540 GaimConvWindow *win; |
|
| 541 GaimConversation *conv; |
|
| 542 |
|
| 543 if (type == GAIM_CONV_TYPE_UNKNOWN) |
|
| 544 return NULL; |
|
| 545 |
|
| 546 for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) { |
|
| 547 win = (GaimConvWindow *)wins->data; |
|
| 548 |
|
| 549 for (convs = gaim_conv_window_get_conversations(win); |
|
| 550 convs != NULL; |
|
| 551 convs = convs->next) { |
|
| 552 |
|
| 553 conv = (GaimConversation *)convs->data; |
|
| 554 |
|
| 555 if (gaim_conversation_get_type(conv) == type) |
|
| 556 return win; |
|
| 557 } |
|
| 558 } |
|
| 559 |
|
| 560 return NULL; |
|
| 561 } |
|
| 562 |
|
| 563 GaimConvWindow * |
|
| 564 gaim_get_last_window_with_type(GaimConversationType type) |
|
| 565 { |
|
| 566 GList *wins, *convs; |
|
| 567 GaimConvWindow *win; |
|
| 568 GaimConversation *conv; |
|
| 569 |
|
| 570 if (type == GAIM_CONV_TYPE_UNKNOWN) |
|
| 571 return NULL; |
|
| 572 |
|
| 573 for (wins = g_list_last(gaim_get_windows()); |
|
| 574 wins != NULL; |
|
| 575 wins = wins->prev) { |
|
| 576 |
|
| 577 win = (GaimConvWindow *)wins->data; |
|
| 578 |
|
| 579 for (convs = gaim_conv_window_get_conversations(win); |
|
| 580 convs != NULL; |
|
| 581 convs = convs->next) { |
|
| 582 |
|
| 583 conv = (GaimConversation *)convs->data; |
|
| 584 |
|
| 585 if (gaim_conversation_get_type(conv) == type) |
|
| 586 return win; |
|
| 587 } |
|
| 588 } |
|
| 589 |
|
| 590 return NULL; |
|
| 591 } |
|
| 592 |
|
| 593 /************************************************************************** |
232 /************************************************************************** |
| 594 * Conversation API |
233 * Conversation API |
| 595 **************************************************************************/ |
234 **************************************************************************/ |
| 596 static void |
235 static void |
| 597 gaim_conversation_chat_cleanup_for_rejoin(GaimConversation *conv) |
236 gaim_conversation_chat_cleanup_for_rejoin(GaimConversation *conv) |
| 705 conversations = g_list_append(conversations, conv); |
348 conversations = g_list_append(conversations, conv); |
| 706 |
349 |
| 707 /* Auto-set the title. */ |
350 /* Auto-set the title. */ |
| 708 gaim_conversation_autoset_title(conv); |
351 gaim_conversation_autoset_title(conv); |
| 709 |
352 |
| 710 /* |
|
| 711 * Place the conversation somewhere. If there are no conversation |
|
| 712 * windows open, or if tabbed conversations are not enabled, then |
|
| 713 * place the conversation in a new window by itself. Otherwise use |
|
| 714 * the chosen conversation placement function. |
|
| 715 */ |
|
| 716 if ((windows == NULL) || (!gaim_prefs_get_bool("/gaim/gtk/conversations/tabs"))) |
|
| 717 { |
|
| 718 GaimConvWindow *win; |
|
| 719 |
|
| 720 win = gaim_conv_window_new(); |
|
| 721 |
|
| 722 gaim_conv_window_add_conversation(win, conv); |
|
| 723 |
|
| 724 /* Ensure the window is visible. */ |
|
| 725 gaim_conv_window_show(win); |
|
| 726 } |
|
| 727 else |
|
| 728 { |
|
| 729 if (place_conv == NULL) |
|
| 730 { |
|
| 731 ensure_default_funcs(); |
|
| 732 |
|
| 733 place_conv = conv_placement_last_created_win; |
|
| 734 } |
|
| 735 |
|
| 736 if (place_conv == NULL) |
|
| 737 gaim_debug(GAIM_DEBUG_ERROR, "conversation", |
|
| 738 "This is about to suck.\n"); |
|
| 739 |
|
| 740 place_conv(conv); |
|
| 741 } |
|
| 742 |
|
| 743 gaim_signal_emit(gaim_conversations_get_handle(), |
353 gaim_signal_emit(gaim_conversations_get_handle(), |
| 744 "conversation-created", conv); |
354 "conversation-created", conv); |
| 745 |
355 |
| 746 return conv; |
356 return conv; |
| 747 } |
357 } |
| 748 |
358 |
| 749 void |
359 void |
| 750 gaim_conversation_destroy(GaimConversation *conv) |
360 gaim_conversation_destroy(GaimConversation *conv) |
| 751 { |
361 { |
| 752 GaimPluginProtocolInfo *prpl_info = NULL; |
362 GaimPluginProtocolInfo *prpl_info = NULL; |
| 753 GaimConvWindow *win; |
|
| 754 GaimConversationUiOps *ops; |
363 GaimConversationUiOps *ops; |
| 755 GaimConnection *gc; |
364 GaimConnection *gc; |
| 756 const char *name; |
365 const char *name; |
| 757 GList *node; |
366 GList *node; |
| 758 |
367 |
| 759 g_return_if_fail(conv != NULL); |
368 g_return_if_fail(conv != NULL); |
| 760 |
369 |
| 761 win = gaim_conversation_get_window(conv); |
|
| 762 ops = gaim_conversation_get_ui_ops(conv); |
370 ops = gaim_conversation_get_ui_ops(conv); |
| 763 gc = gaim_conversation_get_gc(conv); |
371 gc = gaim_conversation_get_gc(conv); |
| 764 name = gaim_conversation_get_name(conv); |
372 name = gaim_conversation_get_name(conv); |
| 765 |
373 |
| 766 if (gc != NULL) |
374 if (gc != NULL) |
| 1350 else |
938 else |
| 1351 unseen = GAIM_UNSEEN_TEXT; |
939 unseen = GAIM_UNSEEN_TEXT; |
| 1352 } |
940 } |
| 1353 |
941 |
| 1354 gaim_conversation_set_unseen(conv, unseen); |
942 gaim_conversation_set_unseen(conv, unseen); |
| 1355 |
|
| 1356 /* |
|
| 1357 * TODO: This is #if 0'ed out because we don't have a way of |
|
| 1358 * telling if a conversation window is minimized. This |
|
| 1359 * should probably be done in gtkconv.c anyway. |
|
| 1360 */ |
|
| 1361 #if 0 |
|
| 1362 /* |
|
| 1363 * This is auto-tab switching. |
|
| 1364 * |
|
| 1365 * If we received an IM, and the GaimConvWindow is not active, |
|
| 1366 * then make this conversation the active tab in this GaimConvWindow. |
|
| 1367 * |
|
| 1368 * We do this so that, when the user comes back to the conversation |
|
| 1369 * window, the first thing they'll see is the new message. This is |
|
| 1370 * especially important when the IM window is flashing in their |
|
| 1371 * taskbar--we want the title of the window to be set to the name |
|
| 1372 * of the person that IMed them most recently. |
|
| 1373 */ |
|
| 1374 if ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) && |
|
| 1375 (flags & (GAIM_MESSAGE_RECV | GAIM_MESSAGE_ERROR)) && |
|
| 1376 (!gaim_conv_window_has_focus(win)) && |
|
| 1377 (gaim_conv_window_is_minimized(win))) |
|
| 1378 { |
|
| 1379 gaim_conv_window_switch_conversation(win, conv); |
|
| 1380 } |
|
| 1381 #endif |
|
| 1382 } |
|
| 1383 |
|
| 1384 void |
|
| 1385 gaim_conversation_update_progress(GaimConversation *conv, float percent) |
|
| 1386 { |
|
| 1387 GaimConversationUiOps *ops; |
|
| 1388 |
|
| 1389 g_return_if_fail(conv != NULL); |
|
| 1390 g_return_if_fail(percent >= 0 && percent <= 1); |
|
| 1391 |
|
| 1392 /* |
|
| 1393 * NOTE: A percent == 1 indicates that the progress bar should be |
|
| 1394 * closed. |
|
| 1395 */ |
|
| 1396 ops = gaim_conversation_get_ui_ops(conv); |
|
| 1397 |
|
| 1398 if (ops != NULL && ops->update_progress != NULL) |
|
| 1399 ops->update_progress(conv, percent); |
|
| 1400 } |
943 } |
| 1401 |
944 |
| 1402 gboolean |
945 gboolean |
| 1403 gaim_conversation_has_focus(GaimConversation *conv) |
946 gaim_conversation_has_focus(GaimConversation *conv) |
| 1404 { |
947 { |
| 1405 gboolean ret = FALSE; |
948 gboolean ret = FALSE; |
| 1406 GaimConvWindow *win; |
|
| 1407 GaimConversationUiOps *ops; |
949 GaimConversationUiOps *ops; |
| 1408 |
950 |
| 1409 g_return_val_if_fail(conv != NULL, FALSE); |
951 g_return_val_if_fail(conv != NULL, FALSE); |
| 1410 |
|
| 1411 win = gaim_conversation_get_window(conv); |
|
| 1412 if (gaim_conv_window_get_active_conversation(win) != conv) |
|
| 1413 return FALSE; |
|
| 1414 |
952 |
| 1415 ops = gaim_conversation_get_ui_ops(conv); |
953 ops = gaim_conversation_get_ui_ops(conv); |
| 1416 |
954 |
| 1417 if (ops != NULL && ops->has_focus != NULL) |
955 if (ops != NULL && ops->has_focus != NULL) |
| 1418 ret = ops->has_focus(conv); |
956 ret = ops->has_focus(conv); |
| 2441 g_return_val_if_fail(cb != NULL, NULL); |
1967 g_return_val_if_fail(cb != NULL, NULL); |
| 2442 |
1968 |
| 2443 return cb->name; |
1969 return cb->name; |
| 2444 } |
1970 } |
| 2445 |
1971 |
| 2446 /************************************************************************** |
|
| 2447 * Conversation placement functions |
|
| 2448 **************************************************************************/ |
|
| 2449 /* This one places conversations in the last made window. */ |
|
| 2450 static void |
|
| 2451 conv_placement_last_created_win(GaimConversation *conv) |
|
| 2452 { |
|
| 2453 GaimConvWindow *win; |
|
| 2454 |
|
| 2455 win = g_list_last(gaim_get_windows())->data; |
|
| 2456 |
|
| 2457 if (win == NULL) { |
|
| 2458 win = gaim_conv_window_new(); |
|
| 2459 |
|
| 2460 gaim_conv_window_add_conversation(win, conv); |
|
| 2461 gaim_conv_window_show(win); |
|
| 2462 } |
|
| 2463 else |
|
| 2464 gaim_conv_window_add_conversation(win, conv); |
|
| 2465 } |
|
| 2466 |
|
| 2467 /* This one places conversations in the last made window of the same type. */ |
|
| 2468 static void |
|
| 2469 conv_placement_last_created_win_type(GaimConversation *conv) |
|
| 2470 { |
|
| 2471 GaimConvWindow *win; |
|
| 2472 |
|
| 2473 win = gaim_get_last_window_with_type(gaim_conversation_get_type(conv)); |
|
| 2474 |
|
| 2475 if (win == NULL) { |
|
| 2476 win = gaim_conv_window_new(); |
|
| 2477 |
|
| 2478 gaim_conv_window_add_conversation(win, conv); |
|
| 2479 gaim_conv_window_show(win); |
|
| 2480 } |
|
| 2481 else |
|
| 2482 gaim_conv_window_add_conversation(win, conv); |
|
| 2483 } |
|
| 2484 |
|
| 2485 /* This one places each conversation in its own window. */ |
|
| 2486 static void |
|
| 2487 conv_placement_new_window(GaimConversation *conv) |
|
| 2488 { |
|
| 2489 GaimConvWindow *win; |
|
| 2490 |
|
| 2491 win = gaim_conv_window_new(); |
|
| 2492 |
|
| 2493 gaim_conv_window_add_conversation(win, conv); |
|
| 2494 |
|
| 2495 gaim_conv_window_show(win); |
|
| 2496 } |
|
| 2497 |
|
| 2498 static GaimGroup * |
|
| 2499 conv_get_group(GaimConversation *conv) |
|
| 2500 { |
|
| 2501 GaimGroup *group = NULL; |
|
| 2502 |
|
| 2503 if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) |
|
| 2504 { |
|
| 2505 GaimBuddy *buddy; |
|
| 2506 |
|
| 2507 buddy = gaim_find_buddy(gaim_conversation_get_account(conv), |
|
| 2508 gaim_conversation_get_name(conv)); |
|
| 2509 |
|
| 2510 if (buddy != NULL) |
|
| 2511 group = gaim_find_buddys_group(buddy); |
|
| 2512 |
|
| 2513 } |
|
| 2514 else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) |
|
| 2515 { |
|
| 2516 GaimChat *chat; |
|
| 2517 |
|
| 2518 chat = gaim_blist_find_chat(gaim_conversation_get_account(conv), |
|
| 2519 gaim_conversation_get_name(conv)); |
|
| 2520 |
|
| 2521 if (chat != NULL) |
|
| 2522 group = gaim_chat_get_group(chat); |
|
| 2523 } |
|
| 2524 |
|
| 2525 return group; |
|
| 2526 } |
|
| 2527 |
|
| 2528 /* |
|
| 2529 * This groups things by, well, group. Buddies from groups will always be |
|
| 2530 * grouped together, and a buddy from a group not belonging to any currently |
|
| 2531 * open windows will get a new window. |
|
| 2532 */ |
|
| 2533 static void |
|
| 2534 conv_placement_by_group(GaimConversation *conv) |
|
| 2535 { |
|
| 2536 GaimConversationType type; |
|
| 2537 GaimGroup *group = NULL; |
|
| 2538 GList *wl, *cl; |
|
| 2539 |
|
| 2540 type = gaim_conversation_get_type(conv); |
|
| 2541 |
|
| 2542 group = conv_get_group(conv); |
|
| 2543 |
|
| 2544 /* Go through the list of IMs and find one with this group. */ |
|
| 2545 for (wl = gaim_get_windows(); wl != NULL; wl = wl->next) |
|
| 2546 { |
|
| 2547 GaimConvWindow *win2; |
|
| 2548 GaimConversation *conv2; |
|
| 2549 GaimGroup *group2 = NULL; |
|
| 2550 |
|
| 2551 win2 = (GaimConvWindow *)wl->data; |
|
| 2552 |
|
| 2553 for (cl = gaim_conv_window_get_conversations(win2); |
|
| 2554 cl != NULL; |
|
| 2555 cl = cl->next) |
|
| 2556 { |
|
| 2557 conv2 = (GaimConversation *)cl->data; |
|
| 2558 |
|
| 2559 group2 = conv_get_group(conv2); |
|
| 2560 |
|
| 2561 if (group == group2) |
|
| 2562 { |
|
| 2563 gaim_conv_window_add_conversation(win2, conv); |
|
| 2564 |
|
| 2565 return; |
|
| 2566 } |
|
| 2567 } |
|
| 2568 } |
|
| 2569 |
|
| 2570 /* Make a new window. */ |
|
| 2571 conv_placement_new_window(conv); |
|
| 2572 } |
|
| 2573 |
|
| 2574 /* This groups things by account. Otherwise, the same semantics as above */ |
|
| 2575 static void |
|
| 2576 conv_placement_by_account(GaimConversation *conv) |
|
| 2577 { |
|
| 2578 GaimConversationType type; |
|
| 2579 GList *wins, *convs; |
|
| 2580 GaimAccount *account; |
|
| 2581 |
|
| 2582 account = gaim_conversation_get_account(conv); |
|
| 2583 type = gaim_conversation_get_type(conv); |
|
| 2584 |
|
| 2585 /* Go through the list of IMs and find one with this group. */ |
|
| 2586 for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) |
|
| 2587 { |
|
| 2588 GaimConvWindow *win2; |
|
| 2589 GaimConversation *conv2; |
|
| 2590 |
|
| 2591 win2 = (GaimConvWindow *)wins->data; |
|
| 2592 |
|
| 2593 for (convs = gaim_conv_window_get_conversations(win2); |
|
| 2594 convs != NULL; |
|
| 2595 convs = convs->next) |
|
| 2596 { |
|
| 2597 conv2 = (GaimConversation *)convs->data; |
|
| 2598 |
|
| 2599 if (account == gaim_conversation_get_account(conv2)) |
|
| 2600 { |
|
| 2601 gaim_conv_window_add_conversation(win2, conv); |
|
| 2602 return; |
|
| 2603 } |
|
| 2604 } |
|
| 2605 } |
|
| 2606 |
|
| 2607 /* Make a new window. */ |
|
| 2608 conv_placement_new_window(conv); |
|
| 2609 } |
|
| 2610 |
|
| 2611 static ConvPlacementData * |
|
| 2612 get_conv_placement_data(const char *id) |
|
| 2613 { |
|
| 2614 ConvPlacementData *data = NULL; |
|
| 2615 GList *n; |
|
| 2616 |
|
| 2617 for(n = conv_placement_fncs; n; n = n->next) { |
|
| 2618 data = n->data; |
|
| 2619 if(!strcmp(data->id, id)) |
|
| 2620 return data; |
|
| 2621 } |
|
| 2622 |
|
| 2623 return NULL; |
|
| 2624 } |
|
| 2625 |
|
| 2626 static void |
|
| 2627 add_conv_placement_fnc(const char *id, const char *name, |
|
| 2628 GaimConvPlacementFunc fnc) |
|
| 2629 { |
|
| 2630 ConvPlacementData *data; |
|
| 2631 |
|
| 2632 data = g_new(ConvPlacementData, 1); |
|
| 2633 |
|
| 2634 data->id = g_strdup(id); |
|
| 2635 data->name = g_strdup(name); |
|
| 2636 data->fnc = fnc; |
|
| 2637 |
|
| 2638 conv_placement_fncs = g_list_append(conv_placement_fncs, data); |
|
| 2639 } |
|
| 2640 |
|
| 2641 static void |
|
| 2642 ensure_default_funcs(void) |
|
| 2643 { |
|
| 2644 if (conv_placement_fncs == NULL) |
|
| 2645 { |
|
| 2646 add_conv_placement_fnc("last", _("Last created window"), |
|
| 2647 conv_placement_last_created_win); |
|
| 2648 add_conv_placement_fnc("im_chat", _("Separate IM and Chat windows"), |
|
| 2649 conv_placement_last_created_win_type); |
|
| 2650 add_conv_placement_fnc("new", _("New window"), |
|
| 2651 conv_placement_new_window); |
|
| 2652 add_conv_placement_fnc("group", _("By group"), |
|
| 2653 conv_placement_by_group); |
|
| 2654 add_conv_placement_fnc("account", _("By account"), |
|
| 2655 conv_placement_by_account); |
|
| 2656 } |
|
| 2657 } |
|
| 2658 |
|
| 2659 GList * |
|
| 2660 gaim_conv_placement_get_options(void) |
|
| 2661 { |
|
| 2662 GList *n, *list = NULL; |
|
| 2663 ConvPlacementData *data; |
|
| 2664 |
|
| 2665 ensure_default_funcs(); |
|
| 2666 |
|
| 2667 for (n = conv_placement_fncs; n; n = n->next) { |
|
| 2668 data = n->data; |
|
| 2669 list = g_list_append(list, data->name); |
|
| 2670 list = g_list_append(list, data->id); |
|
| 2671 } |
|
| 2672 |
|
| 2673 return list; |
|
| 2674 } |
|
| 2675 |
|
| 2676 |
|
| 2677 void |
|
| 2678 gaim_conv_placement_add_fnc(const char *id, const char *name, |
|
| 2679 GaimConvPlacementFunc fnc) |
|
| 2680 { |
|
| 2681 g_return_if_fail(id != NULL); |
|
| 2682 g_return_if_fail(name != NULL); |
|
| 2683 g_return_if_fail(fnc != NULL); |
|
| 2684 |
|
| 2685 ensure_default_funcs(); |
|
| 2686 |
|
| 2687 add_conv_placement_fnc(id, name, fnc); |
|
| 2688 } |
|
| 2689 |
|
| 2690 void |
|
| 2691 gaim_conv_placement_remove_fnc(const char *id) |
|
| 2692 { |
|
| 2693 ConvPlacementData *data = get_conv_placement_data(id); |
|
| 2694 |
|
| 2695 if (data == NULL) |
|
| 2696 return; |
|
| 2697 |
|
| 2698 conv_placement_fncs = g_list_remove(conv_placement_fncs, data); |
|
| 2699 |
|
| 2700 g_free(data->id); |
|
| 2701 g_free(data->name); |
|
| 2702 g_free(data); |
|
| 2703 } |
|
| 2704 |
|
| 2705 const char * |
|
| 2706 gaim_conv_placement_get_name(const char *id) |
|
| 2707 { |
|
| 2708 ConvPlacementData *data; |
|
| 2709 |
|
| 2710 ensure_default_funcs(); |
|
| 2711 |
|
| 2712 data = get_conv_placement_data(id); |
|
| 2713 |
|
| 2714 if (data == NULL) |
|
| 2715 return NULL; |
|
| 2716 |
|
| 2717 return data->name; |
|
| 2718 } |
|
| 2719 |
|
| 2720 GaimConvPlacementFunc |
|
| 2721 gaim_conv_placement_get_fnc(const char *id) |
|
| 2722 { |
|
| 2723 ConvPlacementData *data; |
|
| 2724 |
|
| 2725 ensure_default_funcs(); |
|
| 2726 |
|
| 2727 data = get_conv_placement_data(id); |
|
| 2728 |
|
| 2729 if (data == NULL) |
|
| 2730 return NULL; |
|
| 2731 |
|
| 2732 return data->fnc; |
|
| 2733 } |
|
| 2734 |
|
| 2735 void |
|
| 2736 gaim_conv_placement_set_current_func(GaimConvPlacementFunc func) |
|
| 2737 { |
|
| 2738 g_return_if_fail(func != NULL); |
|
| 2739 |
|
| 2740 place_conv = func; |
|
| 2741 } |
|
| 2742 |
|
| 2743 GaimConvPlacementFunc |
|
| 2744 gaim_conv_placement_get_current_func(void) |
|
| 2745 { |
|
| 2746 return place_conv; |
|
| 2747 } |
|
| 2748 |
|
| 2749 void |
|
| 2750 gaim_conversations_set_win_ui_ops(GaimConvWindowUiOps *ops) |
|
| 2751 { |
|
| 2752 win_ui_ops = ops; |
|
| 2753 } |
|
| 2754 |
|
| 2755 GaimConvWindowUiOps * |
|
| 2756 gaim_conversations_get_win_ui_ops(void) |
|
| 2757 { |
|
| 2758 return win_ui_ops; |
|
| 2759 } |
|
| 2760 |
|
| 2761 void * |
1972 void * |
| 2762 gaim_conversations_get_handle(void) |
1973 gaim_conversations_get_handle(void) |
| 2763 { |
1974 { |
| 2764 static int handle; |
1975 static int handle; |
| 2765 |
1976 |