comparison src/protocols/irc/irc.c @ 4359:5fb47ec9bfe4

[gaim-migrate @ 4625] Wow, okay, where to begin with this one ;) I rewrote the whole conversation backend. It is now core/UI split. Here's how it works.. Every conversation is represented by a gaim_conversation structure. This branches out into gaim_im and gaim_chat structures. Every conversation lives in (well, normally, but it doesn't have to) a gaim_window structure. This is a _CORE_ representation of a window. There can be multiple gaim_window structures around. The gaim_window and gaim_conversation structures have UI-specific operation structures associated with them. At the moment, the only UI is GTK+, and this will be for some time. Don't start thinking you can write a QT UI now. It's just not going to happen. Everything that is done on a conversation is done through the core API. This API does core processing and then calls the UI operations for the rendering and anything else. Now, what does this give the user? - Multiple windows. - Multiple tabs per window. - Draggable tabs. - Send As menu is moved to the menubar. - Menubar for chats. - Some very cool stuff in the future, like replacing, say, IRC chat windows with an X-Chat interface, or whatever. - Later on, customizable window/conversation positioning. For developers: - Fully documented API - Core/UI split - Variable checking and mostly sane handling of incorrect variables. - Logical structure to conversations, both core and UI. - Some very cool stuff in the future, like replacing, say, IRC chat windows with an X-Chat interface, or whatever. - Later on, customizable window/conversation positioning. - Oh yeah, and the beginning of a stock icon system. Now, there are things that aren't there yet. You will see tabs even if you have them turned off. This will be fixed in time. Also, the preferences will change to work with the new structure. I'm starting school in 2 days, so it may not be done immediately, but hopefully in the next week. Enjoy! committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Mon, 20 Jan 2003 09:10:23 +0000
parents 0c68d402f59f
children dcc6c130c6d9
comparison
equal deleted inserted replaced
4358:2b8abf7f9cc1 4359:5fb47ec9bfe4
202 } 202 }
203 203
204 return (utf8); 204 return (utf8);
205 } 205 }
206 206
207 static struct conversation * 207 static struct gaim_conversation *
208 irc_find_chat(struct gaim_connection *gc, char *name) 208 irc_find_chat(struct gaim_connection *gc, char *name)
209 { 209 {
210 GSList *bcs = gc->buddy_chats; 210 GSList *bcs = gc->buddy_chats;
211 211
212 while (bcs) { 212 while (bcs) {
213 struct conversation *b = bcs->data; 213 struct gaim_conversation *b = bcs->data;
214 if (!g_strcasecmp(b->name, name)) 214 if (!g_strcasecmp(b->name, name))
215 return b;
216 bcs = bcs->next;
217 }
218 return NULL;
219 }
220
221 static struct conversation *
222 irc_find_chat_by_id(struct gaim_connection *gc, int id)
223 {
224 GSList *bcs = gc->buddy_chats;
225
226 while (bcs) {
227 struct conversation *b = bcs->data;
228 if (b->id == id)
229 return b; 215 return b;
230 bcs = bcs->next; 216 bcs = bcs->next;
231 } 217 }
232 return NULL; 218 return NULL;
233 } 219 }
494 { 480 {
495 struct dcc_chat *chat = data; 481 struct dcc_chat *chat = data;
496 gchar buffer[IRC_BUF_LEN]; 482 gchar buffer[IRC_BUF_LEN];
497 gchar buf[128]; 483 gchar buf[128];
498 int n = 0; 484 int n = 0;
499 struct conversation *convo; 485 struct gaim_conversation *convo;
500 debug_printf("THIS IS TOO MUCH EFFORT\n"); 486 debug_printf("THIS IS TOO MUCH EFFORT\n");
501 n = read (chat->fd, buffer, IRC_BUF_LEN); 487 n = read (chat->fd, buffer, IRC_BUF_LEN);
502 if (n > 0) { 488 if (n > 0) {
503 489
504 buffer[n] = 0; 490 buffer[n] = 0;
512 } 498 }
513 } 499 }
514 else { 500 else {
515 g_snprintf (buf, sizeof buf, _("DCC Chat with %s closed"), 501 g_snprintf (buf, sizeof buf, _("DCC Chat with %s closed"),
516 chat->nick); 502 chat->nick);
517 convo = new_conversation (chat->nick); 503 convo = gaim_conversation_new(GAIM_CONV_IM, chat->nick);
518 write_to_conv (convo, buf, WFLAG_SYSTEM, NULL, 504 gaim_conversation_write(convo, NULL, buf, -1, WFLAG_SYSTEM,
519 time ((time_t) NULL), -1); 505 time(NULL));
520 dcc_chat_cancel (chat); 506 dcc_chat_cancel (chat);
521 } 507 }
522 } 508 }
523 509
524 static void 510 static void
571 } 557 }
572 558
573 void 559 void
574 dcc_chat_callback (gpointer data, gint source, GaimInputCondition condition) { 560 dcc_chat_callback (gpointer data, gint source, GaimInputCondition condition) {
575 struct dcc_chat *chat = data; 561 struct dcc_chat *chat = data;
576 struct conversation *convo = new_conversation (chat->nick); 562 struct gaim_conversation *convo;
577 char buf[IRC_BUF_LEN]; 563 char buf[IRC_BUF_LEN];
564
565 convo = gaim_conversation_new(GAIM_CONV_IM, chat->nick);
566
578 chat->fd = source; 567 chat->fd = source;
579 g_snprintf (buf, sizeof buf, 568 g_snprintf (buf, sizeof buf,
580 _("DCC Chat with %s established"), 569 _("DCC Chat with %s established"),
581 chat->nick); 570 chat->nick);
582 write_to_conv (convo, buf, WFLAG_SYSTEM, NULL, 571 gaim_conversation_write(convo, NULL, buf, -1, WFLAG_SYSTEM, time(NULL));
583 time ((time_t) NULL), -1);
584 debug_printf ("Chat with %s established\n", chat->nick); 572 debug_printf ("Chat with %s established\n", chat->nick);
585 dcc_chat_list = g_slist_append (dcc_chat_list, chat); 573 dcc_chat_list = g_slist_append (dcc_chat_list, chat);
586 gaim_input_remove(chat->inpa); 574 gaim_input_remove(chat->inpa);
587 chat->inpa = gaim_input_add(source, GAIM_INPUT_READ, dcc_chat_in, chat); 575 chat->inpa = gaim_input_add(source, GAIM_INPUT_READ, dcc_chat_in, chat);
588 } 576 }
674 } 662 }
675 663
676 static void 664 static void
677 handle_names(struct gaim_connection *gc, char *chan, char *names) 665 handle_names(struct gaim_connection *gc, char *chan, char *names)
678 { 666 {
679 struct conversation *c = irc_find_chat(gc, chan); 667 struct gaim_conversation *c = irc_find_chat(gc, chan);
668 struct gaim_chat *chat;
680 char **buf, **tmp; 669 char **buf, **tmp;
670
681 if (!c) return; 671 if (!c) return;
682 if (*names == ':') names++; 672 if (*names == ':') names++;
673
674 chat = GAIM_CHAT(c);
675
683 buf = g_strsplit(names, " ", -1); 676 buf = g_strsplit(names, " ", -1);
677
684 for (tmp = buf; *tmp; tmp++) 678 for (tmp = buf; *tmp; tmp++)
685 add_chat_buddy(c, *tmp, NULL); 679 gaim_chat_add_user(chat, *tmp, NULL);
680
686 g_strfreev(buf); 681 g_strfreev(buf);
687 } 682 }
688 683
689 static void 684 static void
690 handle_notopic(struct gaim_connection *gc, char *text) 685 handle_notopic(struct gaim_connection *gc, char *text)
691 { 686 {
692 struct conversation *c; 687 struct gaim_conversation *c;
688
693 if ((c = irc_find_chat(gc, text))) { 689 if ((c = irc_find_chat(gc, text))) {
694 char buf[IRC_BUF_LEN]; 690 char buf[IRC_BUF_LEN];
691
695 g_snprintf(buf, sizeof(buf), _("No topic is set")); 692 g_snprintf(buf, sizeof(buf), _("No topic is set"));
696 chat_set_topic(c, NULL, buf); 693
694 gaim_chat_set_topic(GAIM_CHAT(c), NULL, buf);
697 } 695 }
698 } 696 }
699 697
700 static void 698 static void
701 handle_topic(struct gaim_connection *gc, char *text) 699 handle_topic(struct gaim_connection *gc, char *text)
702 { 700 {
703 struct conversation *c; 701 struct gaim_conversation *c;
704 char *po = strchr(text, ' '); 702 char *po = strchr(text, ' ');
705 703
706 if (!po) 704 if (!po)
707 return; 705 return;
708 706
709 *po = 0; 707 *po = 0;
710 po += 2; 708 po += 2;
711 709
712 if ((c = irc_find_chat(gc, text))) { 710 if ((c = irc_find_chat(gc, text))) {
713 char buf[IRC_BUF_LEN]; 711 char buf[IRC_BUF_LEN];
714 chat_set_topic(c, NULL, po); 712 gaim_chat_set_topic(GAIM_CHAT(c), NULL, po);
715 g_snprintf(buf, sizeof(buf), _("<B>%s has changed the topic to: %s</B>"), 713 g_snprintf(buf, sizeof(buf), _("<B>%s has changed the topic to: %s</B>"),
716 text, po); 714 text, po);
717 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); 715
716 gaim_conversation_write(c, NULL, buf, -1, WFLAG_SYSTEM, time(NULL));
718 } 717 }
719 } 718 }
720 719
721 static gboolean 720 static gboolean
722 mode_has_arg(struct gaim_connection *gc, char sign, char mode) 721 mode_has_arg(struct gaim_connection *gc, char sign, char mode)
750 } 749 }
751 750
752 static void 751 static void
753 irc_chan_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *argstr, char *who) 752 irc_chan_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *argstr, char *who)
754 { 753 {
755 struct conversation *c = irc_find_chat(gc, room); 754 struct gaim_conversation *c = irc_find_chat(gc, room);
756 char buf[IRC_BUF_LEN]; 755 char buf[IRC_BUF_LEN];
757 char *nick = g_strndup(who, strchr(who, '!') - who); 756 char *nick = g_strndup(who, strchr(who, '!') - who);
758 757
759 g_snprintf(buf, sizeof(buf), _("-:- mode/%s [%c%c %s] by %s"), 758 g_snprintf(buf, sizeof(buf), _("-:- mode/%s [%c%c %s] by %s"),
760 room, sign, mode, strlen(argstr) ? argstr : "", 759 room, sign, mode, strlen(argstr) ? argstr : "",
761 nick); 760 nick);
762 g_free(nick); 761 g_free(nick);
763 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL), -1); 762
763 gaim_conversation_write(c, NULL, buf, -1, WFLAG_SYSTEM, time(NULL));
764 } 764 }
765 765
766 static void 766 static void
767 irc_user_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *nick) 767 irc_user_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *nick)
768 { 768 {
769 struct conversation *c = irc_find_chat(gc, room); 769 struct gaim_conversation *c = irc_find_chat(gc, room);
770 GList *r; 770 GList *r;
771 771
772 if (mode != 'o' && mode != 'v') 772 if (mode != 'o' && mode != 'v')
773 return; 773 return;
774 774
775 if (!c) 775 if (!c)
776 return; 776 return;
777 777
778 r = c->in_room; 778 r = gaim_chat_get_users(GAIM_CHAT(c));
779 while (r) { 779 while (r) {
780 gboolean op = FALSE, voice = FALSE; 780 gboolean op = FALSE, voice = FALSE;
781 char *who = r->data; 781 char *who = r->data;
782 if (*who == '@') { 782 if (*who == '@') {
783 op = TRUE; 783 op = TRUE;
802 voice = TRUE; 802 voice = TRUE;
803 } 803 }
804 tmp = g_strdup(r->data); 804 tmp = g_strdup(r->data);
805 g_snprintf(buf, sizeof(buf), "%s%s%s", op ? "@" : "", 805 g_snprintf(buf, sizeof(buf), "%s%s%s", op ? "@" : "",
806 voice ? "+" : "", nick); 806 voice ? "+" : "", nick);
807 rename_chat_buddy(c, tmp, buf); 807 gaim_chat_rename_user(GAIM_CHAT(c), tmp, buf);
808 g_free(tmp); 808 g_free(tmp);
809 return; 809 return;
810 } 810 }
811 r = r->next; 811 r = r->next;
812 } 812 }
816 handle_mode(struct gaim_connection *gc, char *word[], char *word_eol[], gboolean n324) 816 handle_mode(struct gaim_connection *gc, char *word[], char *word_eol[], gboolean n324)
817 { 817 {
818 struct irc_data *id = gc->proto_data; 818 struct irc_data *id = gc->proto_data;
819 int offset = n324 ? 4 : 3; 819 int offset = n324 ? 4 : 3;
820 char *chan = word[offset]; 820 char *chan = word[offset];
821 struct conversation *c = irc_find_chat(gc, chan); 821 struct gaim_conversation *c = irc_find_chat(gc, chan);
822 char *modes = word[offset + 1]; 822 char *modes = word[offset + 1];
823 int len = strlen(word_eol[offset]) - 1; 823 int len = strlen(word_eol[offset]) - 1;
824 char sign = *modes++; 824 char sign = *modes++;
825 int arg = 1; 825 int arg = 1;
826 char *argstr; 826 char *argstr;
1099 return TRUE; 1099 return TRUE;
1100 return FALSE; 1100 return FALSE;
1101 } 1101 }
1102 1102
1103 static void 1103 static void
1104 irc_rem_chat_bud(struct gaim_connection *gc, char *nick, struct conversation *b, char *reason) 1104 irc_rem_chat_bud(struct gaim_connection *gc, char *nick, struct gaim_conversation *b, char *reason)
1105 { 1105 {
1106
1107 struct gaim_chat *chat;
1106 1108
1107 if (b) { 1109 if (b) {
1108 GList *r = b->in_room; 1110 GList *r;
1111
1112 chat = GAIM_CHAT(b);
1113
1114 r = gaim_chat_get_users(chat);
1115
1109 while (r) { 1116 while (r) {
1110 char *who = r->data; 1117 char *who = r->data;
1111 if (*who == '@') 1118 if (*who == '@')
1112 who++; 1119 who++;
1113 if (*who == '+') 1120 if (*who == '+')
1114 who++; 1121 who++;
1115 if (!g_strcasecmp(who, nick)) { 1122 if (!g_strcasecmp(who, nick)) {
1116 char *tmp = g_strdup(r->data); 1123 char *tmp = g_strdup(r->data);
1117 remove_chat_buddy(b, tmp, reason); 1124 gaim_chat_remove_user(chat, tmp, reason);
1118 g_free(tmp); 1125 g_free(tmp);
1119 break; 1126 break;
1120 } 1127 }
1121 r = r->next; 1128 r = r->next;
1122 } 1129 }
1123 } else { 1130 } else {
1124 GSList *bcs = gc->buddy_chats; 1131 GSList *bcs = gc->buddy_chats;
1125 while (bcs) { 1132 while (bcs) {
1126 struct conversation *bc = bcs->data; 1133 struct gaim_conversation *bc = bcs->data;
1127 irc_rem_chat_bud(gc, nick, bc, reason); 1134 irc_rem_chat_bud(gc, nick, bc, reason);
1128 bcs = bcs->next; 1135 bcs = bcs->next;
1129 } 1136 }
1130 } 1137 }
1131 } 1138 }
1135 { 1142 {
1136 GSList *bcs = gc->buddy_chats; 1143 GSList *bcs = gc->buddy_chats;
1137 char buf[IRC_BUF_LEN]; 1144 char buf[IRC_BUF_LEN];
1138 1145
1139 while (bcs) { 1146 while (bcs) {
1140 struct conversation *b = bcs->data; 1147 struct gaim_conversation *b = bcs->data;
1141 1148 struct gaim_chat *chat;
1142 GList *r = b->in_room; 1149 GList *r;
1150
1151 chat = GAIM_CHAT(b);
1152
1153 r = gaim_chat_get_users(chat);
1154
1143 while (r) { 1155 while (r) {
1144 char *who = r->data; 1156 char *who = r->data;
1145 int n = 0; 1157 int n = 0;
1146 if (*who == '@') 1158 if (*who == '@')
1147 buf[n++] = *who++; 1159 buf[n++] = *who++;
1148 if (*who == '+') 1160 if (*who == '+')
1149 buf[n++] = *who++; 1161 buf[n++] = *who++;
1150 g_snprintf(buf + n, sizeof(buf) - n, "%s", new); 1162 g_snprintf(buf + n, sizeof(buf) - n, "%s", new);
1151 if (!strcmp(who, old)) { 1163 if (!strcmp(who, old)) {
1152 char *tmp = g_strdup(r->data); 1164 char *tmp = g_strdup(r->data);
1153 rename_chat_buddy(b, tmp, buf); 1165 gaim_chat_rename_user(chat, tmp, buf);
1154 r = b->in_room; 1166 r = gaim_chat_get_users(chat);
1155 g_free(tmp); 1167 g_free(tmp);
1156 break; 1168 break;
1157 } else 1169 } else
1158 r = r->next; 1170 r = r->next;
1159 } 1171 }
1163 1175
1164 static void 1176 static void
1165 handle_privmsg(struct gaim_connection *gc, char *to, char *nick, char *msg) 1177 handle_privmsg(struct gaim_connection *gc, char *to, char *nick, char *msg)
1166 { 1178 {
1167 if (is_channel(gc, to)) { 1179 if (is_channel(gc, to)) {
1168 struct conversation *c = irc_find_chat(gc, to); 1180 struct gaim_conversation *c = irc_find_chat(gc, to);
1169 if (!c) 1181 if (!c)
1170 return; 1182 return;
1171 irc_got_chat_in(gc, c->id, nick, 0, msg, time(NULL)); 1183 irc_got_chat_in(gc, gaim_chat_get_id(GAIM_CHAT(c)),
1184 nick, 0, msg, time(NULL));
1172 } else { 1185 } else {
1173 char *tmp = g_malloc(strlen(nick) + 2); 1186 char *tmp = g_malloc(strlen(nick) + 2);
1174 g_snprintf(tmp, strlen(nick) + 2, "@%s", nick); 1187 g_snprintf(tmp, strlen(nick) + 2, "@%s", nick);
1175 if (find_conversation(tmp)) 1188 if (gaim_find_conversation(tmp))
1176 irc_got_im(gc, tmp, msg, 0, time(NULL)); 1189 irc_got_im(gc, tmp, msg, 0, time(NULL));
1177 else { 1190 else {
1178 *tmp = '+'; 1191 *tmp = '+';
1179 if (find_conversation(tmp)) 1192 if (gaim_find_conversation(tmp))
1180 irc_got_im(gc, tmp, msg, 0, time(NULL)); 1193 irc_got_im(gc, tmp, msg, 0, time(NULL));
1181 else 1194 else
1182 irc_got_im(gc, nick, msg, 0, time(NULL)); 1195 irc_got_im(gc, nick, msg, 0, time(NULL));
1183 } 1196 }
1184 g_free(tmp); 1197 g_free(tmp);
1362 serv_got_chat_invite(gc, chan + 1, nick, NULL, g_list_append(NULL, chan)); 1375 serv_got_chat_invite(gc, chan + 1, nick, NULL, g_list_append(NULL, chan));
1363 } else if (!strcmp(cmd, "JOIN")) { 1376 } else if (!strcmp(cmd, "JOIN")) {
1364 irc_parse_join(gc, nick, word, word_eol); 1377 irc_parse_join(gc, nick, word, word_eol);
1365 } else if (!strcmp(cmd, "KICK")) { 1378 } else if (!strcmp(cmd, "KICK")) {
1366 if (!strcmp(gc->displayname, word[4])) { 1379 if (!strcmp(gc->displayname, word[4])) {
1367 struct conversation *c = irc_find_chat(gc, word[3]); 1380 struct gaim_conversation *c = irc_find_chat(gc, word[3]);
1368 if (!c) 1381 if (!c)
1369 return FALSE; 1382 return FALSE;
1370 gc->buddy_chats = g_slist_remove(gc->buddy_chats, c); 1383 gc->buddy_chats = g_slist_remove(gc->buddy_chats, c);
1371 c->gc = NULL; 1384 gaim_conversation_set_user(c, NULL);
1372 g_snprintf(outbuf, sizeof(outbuf), _("You have been kicked from %s: %s"), 1385 g_snprintf(outbuf, sizeof(outbuf), _("You have been kicked from %s: %s"),
1373 word[3], *word_eol[5] == ':' ? word_eol[5] + 1 : word_eol[5]); 1386 word[3], *word_eol[5] == ':' ? word_eol[5] + 1 : word_eol[5]);
1374 do_error_dialog(outbuf, _("IRC Error"), GAIM_ERROR); 1387 do_error_dialog(outbuf, _("IRC Error"), GAIM_ERROR);
1375 } else { 1388 } else {
1376 char *reason = *word_eol[5] == ':' ? word_eol[5] + 1 : word_eol[5]; 1389 char *reason = *word_eol[5] == ':' ? word_eol[5] + 1 : word_eol[5];
1377 char *msg = g_strdup_printf(_("Kicked by %s: %s"), nick, reason); 1390 char *msg = g_strdup_printf(_("Kicked by %s: %s"), nick, reason);
1378 struct conversation *c = irc_find_chat(gc, word[3]); 1391 struct gaim_conversation *c = irc_find_chat(gc, word[3]);
1379 irc_rem_chat_bud(gc, word[4], c, msg); 1392 irc_rem_chat_bud(gc, word[4], c, msg);
1380 g_free(msg); 1393 g_free(msg);
1381 } 1394 }
1382 } else if (!strcmp(cmd, "KILL")) { /* */ 1395 } else if (!strcmp(cmd, "KILL")) { /* */
1383 } else if (!strcmp(cmd, "MODE")) { 1396 } else if (!strcmp(cmd, "MODE")) {
1483 irc_parse_join(struct gaim_connection *gc, char *nick, 1496 irc_parse_join(struct gaim_connection *gc, char *nick,
1484 char *word[], char *word_eol[]) 1497 char *word[], char *word_eol[])
1485 { 1498 {
1486 char *chan = *word[3] == ':' ? word[3] + 1 : word[3]; 1499 char *chan = *word[3] == ':' ? word[3] + 1 : word[3];
1487 static int id = 1; 1500 static int id = 1;
1488 struct conversation *c; 1501 struct gaim_conversation *c;
1489 char *hostmask, *p; 1502 char *hostmask, *p;
1490 1503
1491 if (!g_strcasecmp(gc->displayname, nick)) { 1504 if (!g_strcasecmp(gc->displayname, nick)) {
1492 serv_got_joined_chat(gc, id++, chan); 1505 serv_got_joined_chat(gc, id++, chan);
1493 } else { 1506 } else {
1494 c = irc_find_chat(gc, chan); 1507 c = irc_find_chat(gc, chan);
1495 if (c) { 1508 if (c) {
1498 if (p) { 1511 if (p) {
1499 char *pend = strchr(p, ' '); 1512 char *pend = strchr(p, ' ');
1500 if (pend) { 1513 if (pend) {
1501 *pend = 0; 1514 *pend = 0;
1502 } 1515 }
1503 add_chat_buddy(c, nick, p+1); 1516
1517 gaim_chat_add_user(GAIM_CHAT(c), nick, p + 1);
1518
1504 g_free(hostmask); 1519 g_free(hostmask);
1505 } 1520 }
1506 } 1521 }
1507 } 1522 }
1508 } 1523 }
1509 1524
1510 static void 1525 static void
1511 irc_parse_topic(struct gaim_connection *gc, char *nick, 1526 irc_parse_topic(struct gaim_connection *gc, char *nick,
1512 char *word[], char *word_eol[]) 1527 char *word[], char *word_eol[])
1513 { 1528 {
1514 struct conversation *c = irc_find_chat(gc, word[3]); 1529 struct gaim_conversation *c = irc_find_chat(gc, word[3]);
1515 char *topic = *word_eol[4] == ':' ? word_eol[4] + 1 : word_eol[4]; 1530 char *topic = *word_eol[4] == ':' ? word_eol[4] + 1 : word_eol[4];
1516 char buf[IRC_BUF_LEN]; 1531 char buf[IRC_BUF_LEN];
1517 1532
1518 if (c) { 1533 if (c) {
1519 chat_set_topic(c, nick, topic); 1534 gaim_chat_set_topic(GAIM_CHAT(c), nick, topic);
1520 g_snprintf(buf, sizeof(buf), 1535 g_snprintf(buf, sizeof(buf),
1521 _("<B>%s has changed the topic to: %s</B>"), nick, topic); 1536 _("<B>%s has changed the topic to: %s</B>"), nick, topic);
1522 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); 1537
1538 gaim_conversation_write(c, NULL, buf, -1, WFLAG_SYSTEM, time(NULL));
1523 } 1539 }
1524 } 1540 }
1525 1541
1526 static gboolean 1542 static gboolean
1527 irc_parse_part(struct gaim_connection *gc, char *nick, char *cmd, 1543 irc_parse_part(struct gaim_connection *gc, char *nick, char *cmd,
1528 char *word[], char *word_eol[]) 1544 char *word[], char *word_eol[])
1529 { 1545 {
1530 char *chan = cmd + 5; 1546 char *chan = cmd + 5;
1531 struct conversation *c; 1547 struct gaim_conversation *c;
1548 struct gaim_chat *chat;
1532 char *reason = word_eol[4]; 1549 char *reason = word_eol[4];
1533 GList *r; 1550 GList *r;
1534 1551
1535 if (*chan == ':') 1552 if (*chan == ':')
1536 chan++; 1553 chan++;
1537 if (*reason == ':') 1554 if (*reason == ':')
1538 reason++; 1555 reason++;
1539 if (!(c = irc_find_chat(gc, chan))) 1556 if (!(c = irc_find_chat(gc, chan)))
1540 return FALSE; 1557 return FALSE;
1541 if (!strcmp(nick, gc->displayname)) { 1558 if (!strcmp(nick, gc->displayname)) {
1542 serv_got_chat_left(gc, c->id); 1559 serv_got_chat_left(gc, gaim_chat_get_id(GAIM_CHAT(c)));
1543 return FALSE; 1560 return FALSE;
1544 } 1561 }
1545 r = c->in_room; 1562
1563 chat = GAIM_CHAT(c);
1564
1565 r = gaim_chat_get_users(GAIM_CHAT(c));
1566
1546 while (r) { 1567 while (r) {
1547 char *who = r->data; 1568 char *who = r->data;
1548 if (*who == '@') 1569 if (*who == '@')
1549 who++; 1570 who++;
1550 if (*who == '+') 1571 if (*who == '+')
1551 who++; 1572 who++;
1552 if (!g_strcasecmp(who, nick)) { 1573 if (!g_strcasecmp(who, nick)) {
1553 char *tmp = g_strdup(r->data); 1574 char *tmp = g_strdup(r->data);
1554 remove_chat_buddy(c, tmp, reason); 1575 gaim_chat_remove_user(chat, tmp, reason);
1555 g_free(tmp); 1576 g_free(tmp);
1556 break; 1577 break;
1557 } 1578 }
1558 r = r->next; 1579 r = r->next;
1559 } 1580 }
1560 return TRUE; 1581 return TRUE;
1561 } 1582 }
1562 1583
1563 static void 1584 static void
1564 irc_callback(gpointer data, gint source, GaimInputCondition condition) 1585 irc_callback(gpointer data, gint source, GaimInputCondition condition)
1565 { 1586 {
1907 GString *str = encode_html(tmp); 1928 GString *str = encode_html(tmp);
1908 char *intl; 1929 char *intl;
1909 int len; 1930 int len;
1910 struct dcc_chat *dccchat = find_dcc_chat(gc, who); 1931 struct dcc_chat *dccchat = find_dcc_chat(gc, who);
1911 struct irc_data *id = gc->proto_data; 1932 struct irc_data *id = gc->proto_data;
1933
1912 g_free(tmp); 1934 g_free(tmp);
1913 what = str->str; 1935 what = str->str;
1936
1914 if (*what != '/') { 1937 if (*what != '/') {
1915 if (dccchat) { 1938 if (dccchat) {
1916 intl = irc_send_convert(gc, what, sizeof(buf), &len); 1939 intl = irc_send_convert(gc, what, sizeof(buf), &len);
1917 g_snprintf(buf, sizeof(buf), "%s\r\n", intl); 1940 g_snprintf(buf, sizeof(buf), "%s\r\n", intl);
1918 g_free(intl); 1941 g_free(intl);
1944 char buf[IRC_BUF_LEN]; 1967 char buf[IRC_BUF_LEN];
1945 g_snprintf(buf, sizeof(buf), "INVITE %s\r\n", word_eol[2]); 1968 g_snprintf(buf, sizeof(buf), "INVITE %s\r\n", word_eol[2]);
1946 irc_write(id->fd, buf, strlen(buf)); 1969 irc_write(id->fd, buf, strlen(buf));
1947 } else if (!g_strcasecmp(pdibuf, "TOPIC")) { 1970 } else if (!g_strcasecmp(pdibuf, "TOPIC")) {
1948 if (!*word_eol[2]) { 1971 if (!*word_eol[2]) {
1949 struct conversation *c; 1972 struct gaim_conversation *c;
1973 struct gaim_chat *chat;
1974
1950 c = irc_find_chat(gc, who); 1975 c = irc_find_chat(gc, who);
1951 g_snprintf(buf, sizeof(buf), _("Topic for %s is %s"), who, c->topic ? c->topic : "(no topic set)"); 1976 chat = GAIM_CHAT(c);
1952 write_to_conv(c, buf, WFLAG_SYSTEM | WFLAG_NOLOG, NULL, time(NULL), -1); 1977
1978 g_snprintf(buf, sizeof(buf), _("Topic for %s is %s"),
1979 who, (gaim_chat_get_topic(chat)
1980 ? gaim_chat_get_topic(chat)
1981 : "(no topic set)"));
1982
1983 gaim_conversation_write(c, NULL, buf, -1,
1984 WFLAG_SYSTEM | WFLAG_NOLOG, time(NULL));
1953 } else { 1985 } else {
1954 /* This could be too long */ 1986 /* This could be too long */
1955 intl = irc_send_convert(gc, word_eol[2], sizeof(buf), &len); 1987 intl = irc_send_convert(gc, word_eol[2], sizeof(buf), &len);
1956 g_snprintf(buf, sizeof(buf), "TOPIC %s :%s\r\n", who, intl); 1988 g_snprintf(buf, sizeof(buf), "TOPIC %s :%s\r\n", who, intl);
1957 g_free(intl); 1989 g_free(intl);
2022 g_snprintf(buf, sizeof(buf), "JOIN %s\r\n", word[2]); 2054 g_snprintf(buf, sizeof(buf), "JOIN %s\r\n", word[2]);
2023 irc_write(id->fd, buf, strlen(buf)); 2055 irc_write(id->fd, buf, strlen(buf));
2024 } else if (!g_strcasecmp(pdibuf, "PART")) { 2056 } else if (!g_strcasecmp(pdibuf, "PART")) {
2025 char *chan = *word[2] ? word[2] : who; 2057 char *chan = *word[2] ? word[2] : who;
2026 char *reason = word_eol[3]; 2058 char *reason = word_eol[3];
2027 struct conversation *c; 2059 struct gaim_conversation *c;
2028 if (!is_channel(gc, chan)) { 2060 if (!is_channel(gc, chan)) {
2029 g_free(what); 2061 g_free(what);
2030 return -EINVAL; 2062 return -EINVAL;
2031 } 2063 }
2032 c = irc_find_chat(gc, chan); 2064 c = irc_find_chat(gc, chan);
2037 } else 2069 } else
2038 g_snprintf(buf, sizeof(buf), "PART %s\r\n", chan); 2070 g_snprintf(buf, sizeof(buf), "PART %s\r\n", chan);
2039 irc_write(id->fd, buf, strlen(buf)); 2071 irc_write(id->fd, buf, strlen(buf));
2040 if (c) { 2072 if (c) {
2041 gc->buddy_chats = g_slist_remove(gc->buddy_chats, c); 2073 gc->buddy_chats = g_slist_remove(gc->buddy_chats, c);
2042 c->gc = NULL; 2074 gaim_conversation_set_user(c, NULL);
2043 g_snprintf(buf, sizeof(buf), _("You have left %s"), chan); 2075 g_snprintf(buf, sizeof(buf), _("You have left %s"), chan);
2044 do_error_dialog(buf, _("IRC Part"), GAIM_INFO); 2076 do_error_dialog(buf, _("IRC Part"), GAIM_INFO);
2045 } 2077 }
2046 } else if (!g_strcasecmp(pdibuf, "WHOIS")) { 2078 } else if (!g_strcasecmp(pdibuf, "WHOIS")) {
2047 g_snprintf(buf, sizeof(buf), "WHOIS %s\r\n", word_eol[2]); 2079 g_snprintf(buf, sizeof(buf), "WHOIS %s\r\n", word_eol[2]);
2082 } else if (!g_strcasecmp(word[2], "PING")) { 2114 } else if (!g_strcasecmp(word[2], "PING")) {
2083 if (word[3]) 2115 if (word[3])
2084 irc_ctcp_ping(gc, word[3]); 2116 irc_ctcp_ping(gc, word[3]);
2085 } 2117 }
2086 } else if (!g_strcasecmp(pdibuf, "DCC")) { 2118 } else if (!g_strcasecmp(pdibuf, "DCC")) {
2087 struct conversation *c = NULL; 2119 struct gaim_conversation *c = NULL;
2088 if (!g_strcasecmp(word[2], "CHAT")) { 2120 if (!g_strcasecmp(word[2], "CHAT")) {
2089 if (word[3]) 2121 if (word[3])
2090 irc_start_chat(gc, word[3]); 2122 irc_start_chat(gc, word[3]);
2091 2123
2092 if (is_channel(gc, who)) { 2124 if (is_channel(gc, who)) {
2093 c = irc_find_chat(gc, who); 2125 c = irc_find_chat(gc, who);
2094 } else { 2126 } else {
2095 c = find_conversation(who); 2127 c = gaim_find_conversation(who);
2096 } 2128 }
2097 if (c) { 2129 if (c) {
2098 write_to_conv(c, _("<I>Requesting DCC CHAT</I>"), 2130 gaim_conversation_write(c, NULL,
2099 WFLAG_SYSTEM, NULL, 2131 _("<I>Requesting DCC CHAT</I>"),
2100 time(NULL), -1); 2132 -1, WFLAG_SYSTEM, time(NULL));
2101 } 2133 }
2102 } 2134 }
2103 } else if (!g_strcasecmp(pdibuf, "HELP")) { 2135 } else if (!g_strcasecmp(pdibuf, "HELP")) {
2104 struct conversation *c = NULL; 2136 struct gaim_conversation *c = NULL;
2105 if (is_channel(gc, who)) { 2137 if (is_channel(gc, who)) {
2106 c = irc_find_chat(gc, who); 2138 c = irc_find_chat(gc, who);
2107 } else { 2139 } else {
2108 c = find_conversation(who); 2140 c = gaim_find_conversation(who);
2109 } 2141 }
2110 if (!c) { 2142 if (!c) {
2111 g_free(what); 2143 g_free(what);
2112 return -EINVAL; 2144 return -EINVAL;
2113 } 2145 }
2114 if (!g_strcasecmp(word[2], "OPER")) { 2146 if (!g_strcasecmp(word[2], "OPER")) {
2115 write_to_conv(c, _("<B>Operator commands:<BR>" 2147 gaim_conversation_write(c, NULL,
2116 "REHASH RESTART</B>"), 2148 _("<B>Operator commands:<BR>"
2117 WFLAG_NOLOG, NULL, time(NULL), -1); 2149 "REHASH RESTART</B>"),
2150 -1, WFLAG_NOLOG, time(NULL));
2118 } else if (!g_strcasecmp(word[2], "CTCP")) { 2151 } else if (!g_strcasecmp(word[2], "CTCP")) {
2119 write_to_conv(c, _("<B>CTCP commands:<BR>" 2152 gaim_conversation_write(c, NULL,
2120 "CLIENTINFO <nick><BR>" 2153 _("<B>CTCP commands:<BR>"
2121 "USERINFO <nick><BR>" 2154 "CLIENTINFO <nick><BR>"
2122 "VERSION <nick><BR>" 2155 "USERINFO <nick><BR>"
2123 "PING <nick></B><BR>"), 2156 "VERSION <nick><BR>"
2124 WFLAG_NOLOG, NULL, time(NULL), -1); 2157 "PING <nick></B><BR>"),
2158 -1, WFLAG_NOLOG, time(NULL));
2125 } else if (!g_strcasecmp(word[2], "DCC")) { 2159 } else if (!g_strcasecmp(word[2], "DCC")) {
2126 write_to_conv(c, _("<B>DCC commands:<BR>" 2160 gaim_conversation_write(c, NULL,
2127 "CHAT <nick></B>"), 2161 _("<B>DCC commands:<BR>"
2128 WFLAG_NOLOG, NULL, time(NULL), -1); 2162 "CHAT <nick></B>"),
2163 -1, WFLAG_NOLOG, time(NULL));
2129 } else { 2164 } else {
2130 write_to_conv(c, _("<B>Currently supported commands:<BR>" 2165 gaim_conversation_write(c, NULL,
2131 "WHOIS INVITE NICK LIST<BR>" 2166 _("<B>Currently supported commands:<BR>"
2132 "JOIN PART TOPIC KICK<BR>" 2167 "WHOIS INVITE NICK LIST<BR>"
2133 "OP DEOP VOICE DEVOICE<BR>" 2168 "JOIN PART TOPIC KICK<BR>"
2134 "ME MSG QUOTE SAY QUIT<BR>" 2169 "OP DEOP VOICE DEVOICE<BR>"
2135 "MODE VERSION W WHOWAS<BR>" 2170 "ME MSG QUOTE SAY QUIT<BR>"
2136 "Type /HELP OPER for operator commands<BR>" 2171 "MODE VERSION W WHOWAS<BR>"
2137 "Type /HELP CTCP for CTCP commands<BR>" 2172 "Type /HELP OPER for operator commands<BR>"
2138 "Type /HELP DCC for DCC commands"), 2173 "Type /HELP CTCP for CTCP commands<BR>"
2139 WFLAG_NOLOG, NULL, time(NULL), -1); 2174 "Type /HELP DCC for DCC commands"),
2175 -1, WFLAG_NOLOG, time(NULL));
2140 } 2176 }
2141 } else { 2177 } else {
2142 struct conversation *c = NULL; 2178 struct gaim_conversation *c = NULL;
2143 if (is_channel(gc, who)) { 2179 if (is_channel(gc, who)) {
2144 c = irc_find_chat(gc, who); 2180 c = irc_find_chat(gc, who);
2145 } else { 2181 } else {
2146 c = find_conversation(who); 2182 c = gaim_find_conversation(who);
2147 } 2183 }
2148 if (!c) { 2184 if (!c) {
2149 g_free(what); 2185 g_free(what);
2150 return -EINVAL; 2186 return -EINVAL;
2151 } 2187 }
2152 write_to_conv(c, _("<B>Unknown command</B>"), WFLAG_NOLOG, NULL, time(NULL), -1); 2188
2189 gaim_conversation_write(c, NULL, _("<B>Unknown command</B>"),
2190 -1, WFLAG_NOLOG, time(NULL));
2153 } 2191 }
2154 g_free(what); 2192 g_free(what);
2155 return 0; 2193 return 0;
2156 } 2194 }
2157 2195
2180 2218
2181 static void 2219 static void
2182 irc_chat_invite(struct gaim_connection *gc, int idn, const char *message, const char *name) { 2220 irc_chat_invite(struct gaim_connection *gc, int idn, const char *message, const char *name) {
2183 char buf[IRC_BUF_LEN]; 2221 char buf[IRC_BUF_LEN];
2184 struct irc_data *id = gc->proto_data; 2222 struct irc_data *id = gc->proto_data;
2185 struct conversation *c = irc_find_chat_by_id(gc, idn); 2223 struct gaim_conversation *c = gaim_find_chat(gc, idn);
2186 g_snprintf(buf, sizeof(buf), "INVITE %s %s\r\n", name, c->name); 2224 g_snprintf(buf, sizeof(buf), "INVITE %s %s\r\n", name, c->name);
2187 irc_write(id->fd, buf, strlen(buf)); 2225 irc_write(id->fd, buf, strlen(buf));
2188 } 2226 }
2189 2227
2190 static int 2228 static int
2238 2276
2239 static void 2277 static void
2240 irc_chat_leave(struct gaim_connection *gc, int id) 2278 irc_chat_leave(struct gaim_connection *gc, int id)
2241 { 2279 {
2242 struct irc_data *idata = gc->proto_data; 2280 struct irc_data *idata = gc->proto_data;
2243 struct conversation *c = irc_find_chat_by_id(gc, id); 2281 struct gaim_conversation *c = gaim_find_chat(gc, id);
2244 char buf[IRC_BUF_LEN]; 2282 char buf[IRC_BUF_LEN];
2245 2283
2246 if (!c) return; 2284 if (!c) return;
2247 2285
2248 g_snprintf(buf, sizeof(buf), "PART %s\r\n", c->name); 2286 g_snprintf(buf, sizeof(buf), "PART %s\r\n", c->name);
2250 } 2288 }
2251 2289
2252 static int 2290 static int
2253 irc_chat_send(struct gaim_connection *gc, int id, char *what) 2291 irc_chat_send(struct gaim_connection *gc, int id, char *what)
2254 { 2292 {
2255 struct conversation *c = irc_find_chat_by_id(gc, id); 2293 struct gaim_conversation *c = gaim_find_chat(gc, id);
2256 if (!c) 2294 if (!c)
2257 return -EINVAL; 2295 return -EINVAL;
2258 if (send_msg(gc, c->name, what) > 0) 2296 if (send_msg(gc, c->name, what) > 0)
2259 serv_got_chat_in(gc, c->id, gc->displayname, 0, what, time(NULL)); 2297 serv_got_chat_in(gc, gaim_chat_get_id(GAIM_CHAT(c)),
2298 gc->displayname, 0, what, time(NULL));
2260 return 0; 2299 return 0;
2261 } 2300 }
2262 2301
2263 static GList * 2302 static GList *
2264 irc_away_states(struct gaim_connection *gc) 2303 irc_away_states(struct gaim_connection *gc)
2317 2356
2318 static void 2357 static void
2319 dcc_chat_connected(gpointer data, gint source, GdkInputCondition condition) 2358 dcc_chat_connected(gpointer data, gint source, GdkInputCondition condition)
2320 { 2359 {
2321 struct dcc_chat *chat = data; 2360 struct dcc_chat *chat = data;
2322 struct conversation *convo; 2361 struct gaim_conversation *convo;
2323 char buf[128]; 2362 char buf[128];
2324 struct sockaddr_in addr; 2363 struct sockaddr_in addr;
2325 int addrlen = sizeof (addr); 2364 int addrlen = sizeof (addr);
2326 addr.sin_family = AF_INET; 2365 addr.sin_family = AF_INET;
2327 addr.sin_port = htons (chat->port); 2366 addr.sin_port = htons (chat->port);
2328 addr.sin_addr.s_addr = INADDR_ANY; 2367 addr.sin_addr.s_addr = INADDR_ANY;
2329 chat->fd = accept (chat->fd, (struct sockaddr *) (&addr), &addrlen); 2368 chat->fd = accept (chat->fd, (struct sockaddr *) (&addr), &addrlen);
2330 if (!chat->fd) { 2369 if (!chat->fd) {
2331 dcc_chat_cancel (chat); 2370 dcc_chat_cancel (chat);
2332 convo = new_conversation (chat->nick); 2371 convo = gaim_conversation_new(GAIM_CONV_IM, chat->nick);
2333 g_snprintf (buf, sizeof buf, _("DCC Chat with %s closed"), 2372 g_snprintf (buf, sizeof buf, _("DCC Chat with %s closed"),
2334 chat->nick); 2373 chat->nick);
2335 write_to_conv (convo, buf, WFLAG_SYSTEM, NULL, 2374 gaim_conversation_write(convo, NULL, buf, -1,
2336 time ((time_t) NULL), -1); 2375 WFLAG_SYSTEM, time(NULL));
2337 return; 2376 return;
2338 } 2377 }
2339 chat->inpa = 2378 chat->inpa =
2340 gaim_input_add (chat->fd, GAIM_INPUT_READ, dcc_chat_in, chat); 2379 gaim_input_add (chat->fd, GAIM_INPUT_READ, dcc_chat_in, chat);
2341 convo = new_conversation (chat->nick); 2380 convo = gaim_conversation_new(GAIM_CONV_IM, chat->nick);
2342 g_snprintf (buf, sizeof buf, _("DCC Chat with %s established"), 2381 g_snprintf (buf, sizeof buf, _("DCC Chat with %s established"),
2343 chat->nick); 2382 chat->nick);
2344 write_to_conv (convo, buf, WFLAG_SYSTEM, NULL, time ((time_t) NULL), -1); 2383 gaim_conversation_write(convo, NULL, buf, -1, WFLAG_SYSTEM, time(NULL));
2345 debug_printf ("Chat with %s established\n", chat->nick); 2384 debug_printf ("Chat with %s established\n", chat->nick);
2346 dcc_chat_list = g_slist_append (dcc_chat_list, chat); 2385 dcc_chat_list = g_slist_append (dcc_chat_list, chat);
2347 } 2386 }
2348 #if 0 2387 #if 0
2349 static void 2388 static void