Mercurial > pidgin.yaz
annotate finch/finch.c @ 16307:9326d4cf5497
If anyone sees the "Unable to add buddy 1" message after
this commit, please let me know.
More changes in an effort to get rid of the "Unable to Add,
Could not add the buddy 1 for an unknown reason. The
most common reason for this is that you have the
maximum number of allowed buddies in your buddy list" message.
My previous checkin fixed a problem that resulted in the same
error, but the cause was completely different. The important
change in this commit is the one in aim_ssi_itemlist_add().
Apparently there's this funky thing where items in the master
group can't have a buddy ID equal to any group ID. Who knew?
There are a few other minor changes in this commit. I added
a "break" when looping through the items making sure we don't
pick a buddy ID that's already in use. And added some checks
to make sure we never try to update our data if we haven't
received the list from the server yet. Oh, and the 2 bytes
that specify the length of the checksum for the icon are
two separate values. The first byte is either a 0 or a 1 and
I don't know what it means. The second byte is the length of
the checksum.
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 23 Apr 2007 01:05:27 +0000 |
parents | 634b96915d2e |
children | 6c97924af83b 4999bbc52881 |
rev | line source |
---|---|
15823 | 1 /** |
15871
66dff3dfdea6
Re-sed the copyright notices so they don't all talk about Purple.
Richard Laager <rlaager@wiktel.com>
parents:
15823
diff
changeset
|
2 * finch |
15823 | 3 * |
15871
66dff3dfdea6
Re-sed the copyright notices so they don't all talk about Purple.
Richard Laager <rlaager@wiktel.com>
parents:
15823
diff
changeset
|
4 * Finch is the legal property of its developers, whose names are too numerous |
15823 | 5 * to list here. Please refer to the COPYRIGHT file distributed with this |
6 * source distribution. | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 */ | |
22 #include "account.h" | |
23 #include "conversation.h" | |
24 #include "core.h" | |
25 #include "debug.h" | |
26 #include "eventloop.h" | |
27 #include "ft.h" | |
28 #include "log.h" | |
29 #include "notify.h" | |
30 #include "prefs.h" | |
31 #include "prpl.h" | |
32 #include "pounce.h" | |
33 #include "savedstatuses.h" | |
34 #include "sound.h" | |
35 #include "status.h" | |
36 #include "util.h" | |
37 #include "whiteboard.h" | |
38 | |
39 #include "gntdebug.h" | |
40 #include "finch.h" | |
41 #include "gntprefs.h" | |
42 #include "gntui.h" | |
43 #include "gntidle.h" | |
44 | |
45 #define _GNU_SOURCE | |
46 #include <getopt.h> | |
47 | |
48 #include "config.h" | |
49 | |
50 static void | |
51 debug_init() | |
52 { | |
53 finch_debug_init(); | |
54 purple_debug_set_ui_ops(finch_debug_get_ui_ops()); | |
55 } | |
56 | |
57 static PurpleCoreUiOps core_ops = | |
58 { | |
59 finch_prefs_init, | |
60 debug_init, | |
61 gnt_ui_init, | |
62 gnt_ui_uninit | |
63 }; | |
64 | |
65 static PurpleCoreUiOps * | |
66 gnt_core_get_ui_ops() | |
67 { | |
68 return &core_ops; | |
69 } | |
70 | |
71 /* Anything IO-related is directly copied from gtkpurple's source tree */ | |
72 | |
73 #define FINCH_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) | |
74 #define FINCH_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) | |
75 | |
76 typedef struct _PurpleGntIOClosure { | |
77 PurpleInputFunction function; | |
78 guint result; | |
79 gpointer data; | |
80 | |
81 } PurpleGntIOClosure; | |
82 | |
83 static void purple_gnt_io_destroy(gpointer data) | |
84 { | |
85 g_free(data); | |
86 } | |
87 | |
88 static gboolean purple_gnt_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) | |
89 { | |
90 PurpleGntIOClosure *closure = data; | |
91 PurpleInputCondition purple_cond = 0; | |
92 | |
93 if (condition & FINCH_READ_COND) | |
94 purple_cond |= PURPLE_INPUT_READ; | |
95 if (condition & FINCH_WRITE_COND) | |
96 purple_cond |= PURPLE_INPUT_WRITE; | |
97 | |
98 #if 0 | |
99 purple_debug(PURPLE_DEBUG_MISC, "gtk_eventloop", | |
100 "CLOSURE: callback for %d, fd is %d\n", | |
101 closure->result, g_io_channel_unix_get_fd(source)); | |
102 #endif | |
103 | |
104 #ifdef _WIN32 | |
105 if(! purple_cond) { | |
106 #if DEBUG | |
107 purple_debug_misc("gnt_eventloop", | |
108 "CLOSURE received GIOCondition of 0x%x, which does not" | |
109 " match 0x%x (READ) or 0x%x (WRITE)\n", | |
110 condition, FINCH_READ_COND, FINCH_WRITE_COND); | |
111 #endif /* DEBUG */ | |
112 | |
113 return TRUE; | |
114 } | |
115 #endif /* _WIN32 */ | |
116 | |
117 closure->function(closure->data, g_io_channel_unix_get_fd(source), | |
118 purple_cond); | |
119 | |
120 return TRUE; | |
121 } | |
122 | |
123 static guint gnt_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function, | |
124 gpointer data) | |
125 { | |
126 PurpleGntIOClosure *closure = g_new0(PurpleGntIOClosure, 1); | |
127 GIOChannel *channel; | |
128 GIOCondition cond = 0; | |
129 | |
130 closure->function = function; | |
131 closure->data = data; | |
132 | |
133 if (condition & PURPLE_INPUT_READ) | |
134 cond |= FINCH_READ_COND; | |
135 if (condition & PURPLE_INPUT_WRITE) | |
136 cond |= FINCH_WRITE_COND; | |
137 | |
138 channel = g_io_channel_unix_new(fd); | |
139 closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, | |
140 purple_gnt_io_invoke, closure, purple_gnt_io_destroy); | |
141 | |
142 g_io_channel_unref(channel); | |
143 return closure->result; | |
144 } | |
145 | |
146 static PurpleEventLoopUiOps eventloop_ops = | |
147 { | |
148 g_timeout_add, | |
149 g_source_remove, | |
150 gnt_input_add, | |
151 g_source_remove, | |
152 NULL /* input_get_error */ | |
153 }; | |
154 | |
155 static PurpleEventLoopUiOps * | |
156 gnt_eventloop_get_ui_ops(void) | |
157 { | |
158 return &eventloop_ops; | |
159 } | |
160 | |
161 /* This is mostly copied from gtkpurple's source tree */ | |
162 static void | |
163 show_usage(const char *name, gboolean terse) | |
164 { | |
165 char *text; | |
166 | |
167 if (terse) { | |
168 text = g_strdup_printf(_("%s. Try `%s -h' for more information.\n"), VERSION, name); | |
169 } else { | |
170 text = g_strdup_printf(_("%s\n" | |
171 "Usage: %s [OPTION]...\n\n" | |
172 " -c, --config=DIR use DIR for config files\n" | |
173 " -d, --debug print debugging messages to stdout\n" | |
174 " -h, --help display this help and exit\n" | |
175 " -n, --nologin don't automatically login\n" | |
176 " -v, --version display the current version and exit\n"), VERSION, name); | |
177 } | |
178 | |
179 purple_print_utf8_to_console(stdout, text); | |
180 g_free(text); | |
181 } | |
182 | |
183 static int | |
184 init_libpurple(int argc, char **argv) | |
185 { | |
186 char *path; | |
187 int opt; | |
188 gboolean opt_help = FALSE; | |
189 gboolean opt_nologin = FALSE; | |
190 gboolean opt_version = FALSE; | |
191 char *opt_config_dir_arg = NULL; | |
192 char *opt_session_arg = NULL; | |
193 gboolean debug_enabled = FALSE; | |
194 | |
195 struct option long_options[] = { | |
196 {"config", required_argument, NULL, 'c'}, | |
197 {"debug", no_argument, NULL, 'd'}, | |
198 {"help", no_argument, NULL, 'h'}, | |
199 {"nologin", no_argument, NULL, 'n'}, | |
200 {"session", required_argument, NULL, 's'}, | |
201 {"version", no_argument, NULL, 'v'}, | |
202 {0, 0, 0, 0} | |
203 }; | |
204 | |
205 #ifdef ENABLE_NLS | |
206 bindtextdomain(PACKAGE, LOCALEDIR); | |
207 bind_textdomain_codeset(PACKAGE, "UTF-8"); | |
208 textdomain(PACKAGE); | |
209 #endif | |
210 | |
211 #ifdef HAVE_SETLOCALE | |
212 setlocale(LC_ALL, ""); | |
213 #endif | |
214 | |
215 /* scan command-line options */ | |
216 opterr = 1; | |
217 while ((opt = getopt_long(argc, argv, | |
218 #ifndef _WIN32 | |
219 "c:dhn::s:v", | |
220 #else | |
221 "c:dhn::v", | |
222 #endif | |
223 long_options, NULL)) != -1) { | |
224 switch (opt) { | |
225 case 'c': /* config dir */ | |
226 g_free(opt_config_dir_arg); | |
227 opt_config_dir_arg = g_strdup(optarg); | |
228 break; | |
229 case 'd': /* debug */ | |
230 debug_enabled = TRUE; | |
231 break; | |
232 case 'h': /* help */ | |
233 opt_help = TRUE; | |
234 break; | |
235 case 'n': /* no autologin */ | |
236 opt_nologin = TRUE; | |
237 break; | |
238 case 's': /* use existing session ID */ | |
239 g_free(opt_session_arg); | |
240 opt_session_arg = g_strdup(optarg); | |
241 break; | |
242 case 'v': /* version */ | |
243 opt_version = TRUE; | |
244 break; | |
245 case '?': /* show terse help */ | |
246 default: | |
247 show_usage(argv[0], TRUE); | |
248 return 0; | |
249 break; | |
250 } | |
251 } | |
252 | |
253 /* show help message */ | |
254 if (opt_help) { | |
255 show_usage(argv[0], FALSE); | |
256 return 0; | |
257 } | |
258 /* show version message */ | |
259 if (opt_version) { | |
16081 | 260 printf("Finch %s\n", VERSION); |
15823 | 261 return 0; |
262 } | |
263 | |
264 /* set a user-specified config directory */ | |
265 if (opt_config_dir_arg != NULL) { | |
266 purple_util_set_user_dir(opt_config_dir_arg); | |
267 g_free(opt_config_dir_arg); | |
268 } | |
269 | |
270 /* | |
271 * We're done piddling around with command line arguments. | |
272 * Fire up this baby. | |
273 */ | |
274 | |
275 /* Because we don't want debug-messages to show up and corrup the display */ | |
276 purple_debug_set_enabled(debug_enabled); | |
277 | |
278 purple_core_set_ui_ops(gnt_core_get_ui_ops()); | |
279 purple_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops()); | |
280 purple_idle_set_ui_ops(finch_idle_get_ui_ops()); | |
281 | |
282 path = g_build_filename(purple_user_dir(), "plugins", NULL); | |
283 purple_plugins_add_search_path(path); | |
284 g_free(path); | |
285 | |
286 purple_plugins_add_search_path(LIBDIR); | |
287 | |
288 if (!purple_core_init(FINCH_UI)) | |
289 { | |
290 fprintf(stderr, | |
291 "Initialization of the Purple core failed. Dumping core.\n" | |
292 "Please report this!\n"); | |
293 abort(); | |
294 } | |
295 | |
296 /* TODO: Move blist loading into purple_blist_init() */ | |
297 purple_set_blist(purple_blist_new()); | |
298 purple_blist_load(); | |
299 | |
300 /* TODO: Move prefs loading into purple_prefs_init() */ | |
301 purple_prefs_load(); | |
302 purple_prefs_update_old(); | |
303 | |
304 /* load plugins we had when we quit */ | |
305 purple_plugins_load_saved("/purple/gnt/plugins/loaded"); | |
306 | |
307 /* TODO: Move pounces loading into purple_pounces_init() */ | |
308 purple_pounces_load(); | |
309 | |
310 if (opt_nologin) | |
311 { | |
312 /* Set all accounts to "offline" */ | |
313 PurpleSavedStatus *saved_status; | |
314 | |
315 /* If we've used this type+message before, lookup the transient status */ | |
316 saved_status = purple_savedstatus_find_transient_by_type_and_message( | |
317 PURPLE_STATUS_OFFLINE, NULL); | |
318 | |
319 /* If this type+message is unique then create a new transient saved status */ | |
320 if (saved_status == NULL) | |
321 saved_status = purple_savedstatus_new(NULL, PURPLE_STATUS_OFFLINE); | |
322 | |
323 /* Set the status for each account */ | |
324 purple_savedstatus_activate(saved_status); | |
325 } | |
326 else | |
327 { | |
328 /* Everything is good to go--sign on already */ | |
329 if (!purple_prefs_get_bool("/core/savedstatus/startup_current_status")) | |
330 purple_savedstatus_activate(purple_savedstatus_get_startup()); | |
331 purple_accounts_restore_current_statuses(); | |
332 } | |
333 | |
334 return 1; | |
335 } | |
336 | |
337 int main(int argc, char **argv) | |
338 { | |
339 signal(SIGPIPE, SIG_IGN); | |
340 | |
341 /* Initialize the libpurple stuff */ | |
342 if (!init_libpurple(argc, argv)) | |
343 return 0; | |
344 | |
345 purple_blist_show(); | |
346 gnt_main(); | |
347 | |
348 #ifdef STANDALONE | |
349 purple_core_quit(); | |
350 #endif | |
351 | |
352 return 0; | |
353 } | |
354 |