src/conversation.c

changeset 9554
1609ba3612c3
parent 9528
fda6e5341bf2
child 9587
e015e91f6a3e
equal deleted inserted replaced
9553:146d83b7512b 9554:1609ba3612c3
28 #include "prefs.h" 28 #include "prefs.h"
29 #include "prpl.h" 29 #include "prpl.h"
30 #include "signals.h" 30 #include "signals.h"
31 #include "util.h" 31 #include "util.h"
32 32
33 /* XXX CORE/UI, waiting for away splittage */
34 #include "gtkinternal.h"
35 #include "ui.h"
36
37 typedef struct 33 typedef struct
38 { 34 {
39 char *id; 35 char *id;
40 char *name; 36 char *name;
41 GaimConvPlacementFunc fnc; 37 GaimConvPlacementFunc fnc;
53 static GList *conv_placement_fncs = NULL; 49 static GList *conv_placement_fncs = NULL;
54 static GaimConvPlacementFunc place_conv = NULL; 50 static GaimConvPlacementFunc place_conv = NULL;
55 51
56 static void ensure_default_funcs(void); 52 static void ensure_default_funcs(void);
57 static void conv_placement_last_created_win(GaimConversation *conv); 53 static void conv_placement_last_created_win(GaimConversation *conv);
58
59 static gint
60 insertname_compare(gconstpointer one, gconstpointer two)
61 {
62 const char *a = (const char *)one;
63 const char *b = (const char *)two;
64
65 if (*a == '@') {
66 if (*b != '@') return -1;
67
68 return g_ascii_strcasecmp(a + 1, b + 1);
69
70 } else if (*a == '%') {
71 if (*b != '%') return -1;
72
73 return g_ascii_strcasecmp(a + 1, b + 1);
74
75 } else if (*a == '+') {
76 if (*b == '@') return 1;
77 if (*b != '+') return -1;
78
79 return g_ascii_strcasecmp(a + 1, b + 1);
80
81 } else if (*b == '@' || *b == '%' || *b == '+')
82 return 1;
83
84 return g_ascii_strcasecmp(a, b);
85 }
86 54
87 static gboolean 55 static gboolean
88 find_nick(const char *nick, const char *message) 56 find_nick(const char *nick, const char *message)
89 { 57 {
90 char *msg, *who, *p; 58 char *msg, *who, *p;
1925 1893
1926 common_send(gaim_conv_chat_get_conversation(chat), message); 1894 common_send(gaim_conv_chat_get_conversation(chat), message);
1927 } 1895 }
1928 1896
1929 void 1897 void
1930 gaim_conv_chat_add_user(GaimConvChat *chat, const char *user, const char *extra_msg) 1898 gaim_conv_chat_add_user(GaimConvChat *chat, const char *user, const char *extra_msg,
1899 GaimConvChatBuddyFlags flags)
1931 { 1900 {
1932 GaimConversation *conv; 1901 GaimConversation *conv;
1933 GaimConversationUiOps *ops; 1902 GaimConversationUiOps *ops;
1903 GaimConvChatBuddy *cb;
1934 char tmp[BUF_LONG]; 1904 char tmp[BUF_LONG];
1935 1905
1936 g_return_if_fail(chat != NULL); 1906 g_return_if_fail(chat != NULL);
1937 g_return_if_fail(user != NULL); 1907 g_return_if_fail(user != NULL);
1938 1908
1940 ops = gaim_conversation_get_ui_ops(conv); 1910 ops = gaim_conversation_get_ui_ops(conv);
1941 1911
1942 gaim_signal_emit(gaim_conversations_get_handle(), 1912 gaim_signal_emit(gaim_conversations_get_handle(),
1943 "chat-buddy-joining", conv, user); 1913 "chat-buddy-joining", conv, user);
1944 1914
1915 cb = gaim_conv_chat_cb_new(user, flags);
1916
1945 gaim_conv_chat_set_users(chat, 1917 gaim_conv_chat_set_users(chat,
1946 g_list_insert_sorted(gaim_conv_chat_get_users(chat), g_strdup(user), 1918 g_list_append(gaim_conv_chat_get_users(chat), cb));
1947 insertname_compare));
1948 1919
1949 if (ops != NULL && ops->chat_add_user != NULL) 1920 if (ops != NULL && ops->chat_add_user != NULL)
1950 ops->chat_add_user(conv, user); 1921 ops->chat_add_user(conv, user);
1951 1922
1952 if (extra_msg == NULL) 1923 if (extra_msg == NULL)
1961 gaim_signal_emit(gaim_conversations_get_handle(), 1932 gaim_signal_emit(gaim_conversations_get_handle(),
1962 "chat-buddy-joined", conv, user); 1933 "chat-buddy-joined", conv, user);
1963 } 1934 }
1964 1935
1965 void 1936 void
1966 gaim_conv_chat_add_users(GaimConvChat *chat, GList *users) 1937 gaim_conv_chat_add_users(GaimConvChat *chat, GList *users, GList *flags)
1967 { 1938 {
1968 GaimConversation *conv; 1939 GaimConversation *conv;
1969 GaimConversationUiOps *ops; 1940 GaimConversationUiOps *ops;
1970 GList *l; 1941 GaimConvChatBuddy *cb;
1942 GList *ul, *fl;
1971 1943
1972 g_return_if_fail(chat != NULL); 1944 g_return_if_fail(chat != NULL);
1973 g_return_if_fail(users != NULL); 1945 g_return_if_fail(users != NULL);
1974 1946
1975 conv = gaim_conv_chat_get_conversation(chat); 1947 conv = gaim_conv_chat_get_conversation(chat);
1976 ops = gaim_conversation_get_ui_ops(conv); 1948 ops = gaim_conversation_get_ui_ops(conv);
1977 1949
1978 for (l = users; l != NULL; l = l->next) { 1950 ul = users;
1979 const char *user = (const char *)l->data; 1951 fl = flags;
1952 while ((ul != NULL) && (fl != NULL)) {
1953 const char *user = (const char *)ul->data;
1954 GaimConvChatBuddyFlags f = GPOINTER_TO_INT(fl->data);
1980 1955
1981 gaim_signal_emit(gaim_conversations_get_handle(), 1956 gaim_signal_emit(gaim_conversations_get_handle(),
1982 "chat-buddy-joining", conv, user); 1957 "chat-buddy-joining", conv, user, f);
1983 1958
1959 cb = gaim_conv_chat_cb_new(user, f);
1984 gaim_conv_chat_set_users(chat, 1960 gaim_conv_chat_set_users(chat,
1985 g_list_insert_sorted(gaim_conv_chat_get_users(chat), 1961 g_list_append(gaim_conv_chat_get_users(chat), cb));
1986 g_strdup((char *)l->data),
1987 insertname_compare));
1988 1962
1989 gaim_signal_emit(gaim_conversations_get_handle(), 1963 gaim_signal_emit(gaim_conversations_get_handle(),
1990 "chat-buddy-joined", conv, user); 1964 "chat-buddy-joined", conv, user, f);
1965 ul = ul->next;
1966 fl = fl->next;
1991 } 1967 }
1992 1968
1993 if (ops != NULL && ops->chat_add_users != NULL) 1969 if (ops != NULL && ops->chat_add_users != NULL)
1994 ops->chat_add_users(conv, users); 1970 ops->chat_add_users(conv, users);
1995 } 1971 }
1998 gaim_conv_chat_rename_user(GaimConvChat *chat, const char *old_user, 1974 gaim_conv_chat_rename_user(GaimConvChat *chat, const char *old_user,
1999 const char *new_user) 1975 const char *new_user)
2000 { 1976 {
2001 GaimConversation *conv; 1977 GaimConversation *conv;
2002 GaimConversationUiOps *ops; 1978 GaimConversationUiOps *ops;
1979 GaimConvChatBuddy *cb;
1980 GaimConvChatBuddyFlags flags;
2003 char tmp[BUF_LONG]; 1981 char tmp[BUF_LONG];
2004 GList *names;
2005 gboolean its_me = FALSE; 1982 gboolean its_me = FALSE;
2006 1983
2007 g_return_if_fail(chat != NULL); 1984 g_return_if_fail(chat != NULL);
2008 g_return_if_fail(old_user != NULL); 1985 g_return_if_fail(old_user != NULL);
2009 g_return_if_fail(new_user != NULL); 1986 g_return_if_fail(new_user != NULL);
2010 1987
2011 conv = gaim_conv_chat_get_conversation(chat); 1988 conv = gaim_conv_chat_get_conversation(chat);
2012 ops = gaim_conversation_get_ui_ops(conv); 1989 ops = gaim_conversation_get_ui_ops(conv);
2013 1990
1991 flags = gaim_conv_chat_user_get_flags(chat, old_user);
1992 cb = gaim_conv_chat_cb_new(new_user, flags);
2014 gaim_conv_chat_set_users(chat, 1993 gaim_conv_chat_set_users(chat,
2015 g_list_insert_sorted(gaim_conv_chat_get_users(chat), g_strdup(new_user), 1994 g_list_append(gaim_conv_chat_get_users(chat), cb));
2016 insertname_compare));
2017 1995
2018 if (ops != NULL && ops->chat_rename_user != NULL) 1996 if (ops != NULL && ops->chat_rename_user != NULL)
2019 ops->chat_rename_user(conv, old_user, new_user); 1997 ops->chat_rename_user(conv, old_user, new_user);
2020 1998
2021 for (names = gaim_conv_chat_get_users(chat); 1999 cb = gaim_conv_chat_cb_find(chat, old_user);
2022 names != NULL; 2000
2023 names = names->next) { 2001 if (cb) {
2024 2002 gaim_conv_chat_set_users(chat,
2025 if (!gaim_utf8_strcasecmp((char *)names->data, old_user)) { 2003 g_list_remove(gaim_conv_chat_get_users(chat), cb));
2026 gaim_conv_chat_set_users(chat, 2004 gaim_conv_chat_cb_destroy(cb);
2027 g_list_remove(gaim_conv_chat_get_users(chat), names->data));
2028 break;
2029 }
2030 } 2005 }
2031 2006
2032 if (gaim_conv_chat_is_user_ignored(chat, old_user)) { 2007 if (gaim_conv_chat_is_user_ignored(chat, old_user)) {
2033 gaim_conv_chat_unignore(chat, old_user); 2008 gaim_conv_chat_unignore(chat, old_user);
2034 gaim_conv_chat_ignore(chat, new_user); 2009 gaim_conv_chat_ignore(chat, new_user);
2057 void 2032 void
2058 gaim_conv_chat_remove_user(GaimConvChat *chat, const char *user, const char *reason) 2033 gaim_conv_chat_remove_user(GaimConvChat *chat, const char *user, const char *reason)
2059 { 2034 {
2060 GaimConversation *conv; 2035 GaimConversation *conv;
2061 GaimConversationUiOps *ops; 2036 GaimConversationUiOps *ops;
2037 GaimConvChatBuddy *cb;
2062 char tmp[BUF_LONG]; 2038 char tmp[BUF_LONG];
2063 GList *names;
2064 2039
2065 g_return_if_fail(chat != NULL); 2040 g_return_if_fail(chat != NULL);
2066 g_return_if_fail(user != NULL); 2041 g_return_if_fail(user != NULL);
2067 2042
2068 conv = gaim_conv_chat_get_conversation(chat); 2043 conv = gaim_conv_chat_get_conversation(chat);
2072 conv, user, reason); 2047 conv, user, reason);
2073 2048
2074 if (ops != NULL && ops->chat_remove_user != NULL) 2049 if (ops != NULL && ops->chat_remove_user != NULL)
2075 ops->chat_remove_user(conv, user); 2050 ops->chat_remove_user(conv, user);
2076 2051
2077 for (names = gaim_conv_chat_get_users(chat); 2052 cb = gaim_conv_chat_cb_find(chat, user);
2078 names != NULL; 2053
2079 names = names->next) { 2054 if (cb) {
2080 2055 gaim_conv_chat_set_users(chat,
2081 if (!gaim_utf8_strcasecmp((char *)names->data, user)) { 2056 g_list_remove(gaim_conv_chat_get_users(chat), cb));
2082 gaim_conv_chat_set_users(chat, 2057 gaim_conv_chat_cb_destroy(cb);
2083 g_list_remove(gaim_conv_chat_get_users(chat), names->data));
2084 break;
2085 }
2086 } 2058 }
2087 2059
2088 /* NOTE: Don't remove them from ignored in case they re-enter. */ 2060 /* NOTE: Don't remove them from ignored in case they re-enter. */
2089 2061
2090 if (reason != NULL && *reason != '\0') 2062 if (reason != NULL && *reason != '\0')
2102 void 2074 void
2103 gaim_conv_chat_remove_users(GaimConvChat *chat, GList *users, const char *reason) 2075 gaim_conv_chat_remove_users(GaimConvChat *chat, GList *users, const char *reason)
2104 { 2076 {
2105 GaimConversation *conv; 2077 GaimConversation *conv;
2106 GaimConversationUiOps *ops; 2078 GaimConversationUiOps *ops;
2079 GaimConvChatBuddy *cb;
2107 char tmp[BUF_LONG]; 2080 char tmp[BUF_LONG];
2108 GList *names, *l; 2081 GList *l;
2109 2082
2110 g_return_if_fail(chat != NULL); 2083 g_return_if_fail(chat != NULL);
2111 g_return_if_fail(users != NULL); 2084 g_return_if_fail(users != NULL);
2112 2085
2113 conv = gaim_conv_chat_get_conversation(chat); 2086 conv = gaim_conv_chat_get_conversation(chat);
2124 ops->chat_remove_users(conv, users); 2097 ops->chat_remove_users(conv, users);
2125 2098
2126 for (l = users; l != NULL; l = l->next) { 2099 for (l = users; l != NULL; l = l->next) {
2127 const char *user = (const char *)l->data; 2100 const char *user = (const char *)l->data;
2128 2101
2129 for (names = gaim_conv_chat_get_users(chat); 2102 cb = gaim_conv_chat_cb_find(chat, user);
2130 names != NULL; 2103
2131 names = names->next) { 2104 if (cb) {
2132 2105 gaim_conv_chat_set_users(chat,
2133 if (!gaim_utf8_strcasecmp((char *)names->data, user)) 2106 g_list_remove(gaim_conv_chat_get_users(chat), cb));
2134 { 2107 gaim_conv_chat_cb_destroy(cb);
2135 gaim_conv_chat_set_users(chat,
2136 g_list_remove(gaim_conv_chat_get_users(chat), names->data));
2137
2138 break;
2139 }
2140 } 2108 }
2141 2109
2142 gaim_signal_emit(gaim_conversations_get_handle(), "chat-buddy-left", 2110 gaim_signal_emit(gaim_conversations_get_handle(), "chat-buddy-left",
2143 conv, user, reason); 2111 conv, user, reason);
2144 } 2112 }
2174 void 2142 void
2175 gaim_conv_chat_clear_users(GaimConvChat *chat) 2143 gaim_conv_chat_clear_users(GaimConvChat *chat)
2176 { 2144 {
2177 GaimConversation *conv; 2145 GaimConversation *conv;
2178 GaimConversationUiOps *ops; 2146 GaimConversationUiOps *ops;
2179 GList *users; 2147 GList *users, *names = NULL;
2180 GList *l, *l_next; 2148 GList *l;
2181 2149
2182 g_return_if_fail(chat != NULL); 2150 g_return_if_fail(chat != NULL);
2183 2151
2184 conv = gaim_conv_chat_get_conversation(chat); 2152 conv = gaim_conv_chat_get_conversation(chat);
2185 ops = gaim_conversation_get_ui_ops(conv); 2153 ops = gaim_conversation_get_ui_ops(conv);
2186 users = gaim_conv_chat_get_users(chat); 2154 users = gaim_conv_chat_get_users(chat);
2187 2155
2188 if (ops != NULL && ops->chat_remove_users != NULL) 2156 if (ops != NULL && ops->chat_remove_users != NULL) {
2189 ops->chat_remove_users(conv, users); 2157 for (l = users; l; l = l->next) {
2190 2158 GaimConvChatBuddy *cb = l->data;
2191 for (l = users; l != NULL; l = l_next) 2159 names = g_list_append(names, cb->name);
2160 }
2161 ops->chat_remove_users(conv, names);
2162 g_list_free(names);
2163 }
2164
2165 for (l = users; l; l = l->next)
2192 { 2166 {
2193 char *user = (char *)l->data; 2167 GaimConvChatBuddy *cb = l->data;
2194
2195 l_next = l->next;
2196 2168
2197 gaim_signal_emit(gaim_conversations_get_handle(), 2169 gaim_signal_emit(gaim_conversations_get_handle(),
2198 "chat-buddy-leaving", conv, user, NULL); 2170 "chat-buddy-leaving", conv, cb->name, NULL);
2199 gaim_signal_emit(gaim_conversations_get_handle(), 2171 gaim_signal_emit(gaim_conversations_get_handle(),
2200 "chat-buddy-left", conv, user, NULL); 2172 "chat-buddy-left", conv, cb->name, NULL);
2201 2173
2202 g_free(user); 2174 gaim_conv_chat_cb_destroy(cb);
2203 } 2175 }
2204 2176
2205 g_list_free(users); 2177 g_list_free(users);
2206 gaim_conv_chat_set_users(chat, NULL); 2178 gaim_conv_chat_set_users(chat, NULL);
2179 }
2180
2181
2182 gboolean
2183 gaim_conv_chat_find_user(GaimConvChat *chat, const char *user)
2184 {
2185 g_return_val_if_fail(chat != NULL, FALSE);
2186 g_return_val_if_fail(user != NULL, FALSE);
2187
2188 return (gaim_conv_chat_cb_find(chat, user) != NULL);
2189 }
2190
2191 void
2192 gaim_conv_chat_user_set_flags(GaimConvChat *chat, const char *user,
2193 GaimConvChatBuddyFlags flags)
2194 {
2195 GaimConversation *conv;
2196 GaimConversationUiOps *ops;
2197 GaimConvChatBuddy *cb;
2198 GaimConvChatBuddyFlags oldflags;
2199
2200 g_return_if_fail(chat != NULL);
2201 g_return_if_fail(user != NULL);
2202
2203 cb = gaim_conv_chat_cb_find(chat, user);
2204
2205 if (!cb)
2206 return;
2207
2208 if (flags == cb->flags)
2209 return;
2210
2211 oldflags = cb->flags;
2212 cb->flags = flags;
2213
2214 conv = gaim_conv_chat_get_conversation(chat);
2215 ops = gaim_conversation_get_ui_ops(conv);
2216
2217 if (ops != NULL && ops->chat_update_user != NULL)
2218 ops->chat_update_user(conv, user);
2219
2220 gaim_signal_emit(gaim_conversations_get_handle(),
2221 "chat-buddy-flags", conv, user, oldflags, flags);
2222 }
2223
2224 GaimConvChatBuddyFlags
2225 gaim_conv_chat_user_get_flags(GaimConvChat *chat, const char *user)
2226 {
2227 GaimConvChatBuddy *cb;
2228
2229 g_return_val_if_fail(chat != NULL, 0);
2230 g_return_val_if_fail(user != NULL, 0);
2231
2232 cb = gaim_conv_chat_cb_find(chat, user);
2233
2234 if (!cb)
2235 return GAIM_CBFLAGS_NONE;
2236
2237 return cb->flags;
2207 } 2238 }
2208 2239
2209 void gaim_conv_chat_set_nick(GaimConvChat *chat, const char *nick) { 2240 void gaim_conv_chat_set_nick(GaimConvChat *chat, const char *nick) {
2210 g_return_if_fail(chat != NULL); 2241 g_return_if_fail(chat != NULL);
2211 2242
2250 gaim_conv_chat_has_left(GaimConvChat *chat) 2281 gaim_conv_chat_has_left(GaimConvChat *chat)
2251 { 2282 {
2252 g_return_val_if_fail(chat != NULL, TRUE); 2283 g_return_val_if_fail(chat != NULL, TRUE);
2253 2284
2254 return chat->left; 2285 return chat->left;
2286 }
2287
2288 GaimConvChatBuddy *
2289 gaim_conv_chat_cb_new(const char *name, GaimConvChatBuddyFlags flags)
2290 {
2291 GaimConvChatBuddy *cb;
2292
2293 g_return_val_if_fail(name != NULL, NULL);
2294
2295 cb = g_new0(GaimConvChatBuddy, 1);
2296 cb->name = g_strdup(name);
2297 cb->flags = flags;
2298
2299 return cb;
2300 }
2301
2302 GaimConvChatBuddy *
2303 gaim_conv_chat_cb_find(GaimConvChat *chat, const char *name)
2304 {
2305 GList *l;
2306 GaimConvChatBuddy *cb = NULL;
2307
2308 g_return_val_if_fail(chat != NULL, NULL);
2309 g_return_val_if_fail(name != NULL, NULL);
2310
2311 for (l = gaim_conv_chat_get_users(chat); l; l = l->next) {
2312 cb = l->data;
2313 if (!gaim_utf8_strcasecmp(cb->name, name))
2314 return cb;
2315 }
2316
2317 return NULL;
2318 }
2319
2320 void
2321 gaim_conv_chat_cb_destroy(GaimConvChatBuddy *cb)
2322 {
2323 g_return_if_fail(cb != NULL);
2324
2325 if (cb->name)
2326 g_free(cb->name);
2327 cb->name = NULL;
2328 cb->flags = 0;
2329 g_free(cb);
2330 }
2331
2332 const char *
2333 gaim_conv_chat_cb_get_name(GaimConvChatBuddy *cb)
2334 {
2335 g_return_val_if_fail(cb != NULL, NULL);
2336
2337 return cb->name;
2255 } 2338 }
2256 2339
2257 /************************************************************************** 2340 /**************************************************************************
2258 * Conversation placement functions 2341 * Conversation placement functions
2259 **************************************************************************/ 2342 **************************************************************************/
2796 gaim_marshal_VOID__POINTER, NULL, 1, 2879 gaim_marshal_VOID__POINTER, NULL, 1,
2797 gaim_value_new(GAIM_TYPE_SUBTYPE, 2880 gaim_value_new(GAIM_TYPE_SUBTYPE,
2798 GAIM_SUBTYPE_CONVERSATION)); 2881 GAIM_SUBTYPE_CONVERSATION));
2799 2882
2800 gaim_signal_register(handle, "chat-buddy-joining", 2883 gaim_signal_register(handle, "chat-buddy-joining",
2801 gaim_marshal_VOID__POINTER_POINTER, NULL, 2, 2884 gaim_marshal_VOID__POINTER_POINTER_UINT, NULL, 3,
2802 gaim_value_new(GAIM_TYPE_SUBTYPE, 2885 gaim_value_new(GAIM_TYPE_SUBTYPE,
2803 GAIM_SUBTYPE_CONVERSATION), 2886 GAIM_SUBTYPE_CONVERSATION),
2804 gaim_value_new(GAIM_TYPE_STRING)); 2887 gaim_value_new(GAIM_TYPE_STRING),
2888 gaim_value_new(GAIM_TYPE_UINT));
2805 2889
2806 gaim_signal_register(handle, "chat-buddy-joined", 2890 gaim_signal_register(handle, "chat-buddy-joined",
2807 gaim_marshal_VOID__POINTER_POINTER, NULL, 2, 2891 gaim_marshal_VOID__POINTER_POINTER_UINT, NULL, 3,
2808 gaim_value_new(GAIM_TYPE_SUBTYPE, 2892 gaim_value_new(GAIM_TYPE_SUBTYPE,
2809 GAIM_SUBTYPE_CONVERSATION), 2893 GAIM_SUBTYPE_CONVERSATION),
2810 gaim_value_new(GAIM_TYPE_STRING)); 2894 gaim_value_new(GAIM_TYPE_STRING),
2895 gaim_value_new(GAIM_TYPE_UINT));
2896
2897 gaim_signal_register(handle, "chat-buddy-flags",
2898 gaim_marshal_VOID__POINTER_POINTER_UINT_UINT, NULL, 4,
2899 gaim_value_new(GAIM_TYPE_SUBTYPE,
2900 GAIM_SUBTYPE_CONVERSATION),
2901 gaim_value_new(GAIM_TYPE_STRING),
2902 gaim_value_new(GAIM_TYPE_UINT),
2903 gaim_value_new(GAIM_TYPE_UINT));
2811 2904
2812 gaim_signal_register(handle, "chat-buddy-leaving", 2905 gaim_signal_register(handle, "chat-buddy-leaving",
2813 gaim_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, 2906 gaim_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3,
2814 gaim_value_new(GAIM_TYPE_SUBTYPE, 2907 gaim_value_new(GAIM_TYPE_SUBTYPE,
2815 GAIM_SUBTYPE_CONVERSATION), 2908 GAIM_SUBTYPE_CONVERSATION),

mercurial