[gaim-migrate @ 3006]
[pidgin-git.git] / HACKING
bloba46e3e81a8e377ac3d645be6ae7ada40b4aff43e
1 A lot of people have tried to hack gaim, but haven't been able to because
2 the code is just so horrid. Well, the code isn't getting better anytime
3 soon (I hate GNU indent), so to help all you would-be hackers help out
4 gaim, here's a brief tutorial on how gaim works. I'll quickly describe
5 the logical flow of things, then what you'll find in each of the source
6 files. As an added bonus, I'll try and describe as best I can how multiple
7 connections and multiple protocols work. Depending on how much I want to
8 avoid my final tomorrow I may even describe other parts of gaim that I
9 particularly want to brag about. Hopefully that's enough to get most of
10 you going.
12 If you don't know how event-driven programs work, stop right now. Gaim
13 uses GTK+'s main loop (actually GLib's but I won't talk about how GTK
14 works) and uses GLib functions for timeouts and socket notification. If
15 you don't know GTK you should go learn that first.
17 If you're going to hack gaim, PLEASE, PLEASE PLEASE PLEASE send patches
18 against the absolute latest CVS. I get really annoyed when I get patches
19 against the last released version, especially since I don't usually have
20 a copy of it on my computer, and gaim tends to change a lot between
21 versions. (I sometimes get annoyed when they're against CVS from 3 days
22 ago, but can't complain because it's usually my fault that I haven't
23 looked at the patch yet.) To get gaim from CVS (if you haven't already),
24 run the following commands:
26 $ export CVSROOT=:pserver:anonymous@cvs.gaim.sourceforge.net:/cvsroot/gaim
27 $ cvs login (hit enter as the password)
28 $ cvs co gaim (you'll see it getting all of the files)
29 $ cd gaim
30 $ ./autogen.sh
32 You'll now have your normal gaim tree with ./configure and all (which
33 ./autogen.sh takes the liberty of running for you). (If you want to make
34 your life really simple, learn how CVS works. CVS is your friend.) To make
35 a patch, just edit the files right there in that tree (don't bother with
36 two trees, or even two copies of the same file). Then when you're ready to
37 make your patch, simply run 'cvs diff -u >my.patch' and send it off;
38 either post it on sf.net/projects/gaim in the patches section, or email it
39 to gaim@marko.net.
41 This file was last modified by $Author: warmenhoven $ on
42 $Date: 2001-12-09 09:06:36 -0500 (Sun, 09 Dec 2001) $. Do not expect any information contained
43 within to be current or correct.
45 Here's something new. Someone requested that I comment the code. No. I'm a
46 lazy bastard, and I understand most of the code, so I don't need the
47 comments. I understand that some of you do though. So give me the names of
48 specific functions that you'd like commented and I'll see what I can do.
49 It's more likely that those comments will be updated with the code than
50 this file is, though even that is still unlikely.
53 CODING STYLE
54 ============
56 Coding styles are like assholes, everyone has one and no one likes anyone
57 elses. This is mine and if you want me to accept a patch from you without
58 getting annoyed you'll follow this coding style. :)
60 It would probably just be easier for me to include CodingStyle from the
61 linux kernel source.
63 Tab indents. I *HATE* 2-space indents, and I strongly dislike 8-space
64 indents. Use a tab character. I'm likely to refuse a patch if it has
65 2-space indents.
67 K&R style for braces. Braces always go on the same line as the if, etc.
68 that they're associated with; the only exception is functions. Braces
69 for else statements should have both braces on the same line as the else
70 (i.e. "} else {").
72 No functionOrVariableNamesLikeThis. Save it for Java. Underscores are your
73 friend. "tmp" is an excellent variable name. Hungarian style will not be
74 tolerated. Go back to Microsoft.
76 I have a 105-char wide Eterm. Deal with it.
78 NO goto. I'm very likely to refuse a patch if it makes use of goto. If you
79 feel the need to use goto, you need to rethink your design and flow.
82 PROGRAM FLOW
83 ============
85 Before gaim does anything you can see, it initializes itself, which is
86 mostly just reading .gaimrc (handled by the functions in gaimrc.c) and
87 parsing command-line options. It then draws the login window by calling
88 show_login, and waits for input.
90 At the login window, when "Accounts" is clicked, account_editor() is
91 called. This then displays all of the users and various information
92 about them. (Don't ask about what happens when "Sign On" is called. It's
93 quite hackish. The only reason the login window is there anymore is to
94 make it more palatable to people so used to WinAIM that they can't accept
95 anything else.)
97 When the "Sign on/off" button is clicked, serv_login is passed the
98 username and the password for the account. If the password length is
99 zero (the password field is a character array rather than pointer so it
100 will not be NULL) then the Signon callback will prompt for the password
101 before calling serv_login. serv_login then signs in the user using the
102 appropriate protocol.
104 After you're signed in, Gaim draws the buddy list by calling
105 show_buddy_list. Assuming the user has a buddy list (all buddy list
106 functions are controlled by list.c; when you sign on do_import is called
107 and that loads the locally saved list), the protocol calls
108 serv_got_update, which sets the information in the appropriate struct
109 buddy and then passes it off to set_buddy.
111 set_buddy is responsible for a lot of stuff, but most of it is done
112 implicitly. It's responsible for the sounds (which is just a call to
113 play_sound), but the biggest thing it does is call new_group_show and
114 new_buddy_show if necessary. There's only one group_show per group name,
115 even between connections, and only one buddy_show per group_show per
116 buddy name, even between connections. (If that's not confusing enough,
117 wait until I really start describing how the buddy list works.)
119 New connections happen the exact same way as described above. Each
120 aim_user can have one gaim_connection associated with it. aim_user and
121 gaim_connection both have a protocol field. This is kind of confusing:
122 gaim, except for the account editor screen and when the user signs on,
123 ignores the user's protocl field, and only uses the connection's protocol
124 field. You can change the connection's protocol field once it's created
125 and been assigned a PRPL to use to change certain behavior (Oscar does
126 this because it handles both AIM and ICQ). I'll talk about the
127 gaim_connection struct more later.
129 When the user opens a new conversation window, new_conversation is called.
130 That's easy enough. If there isn't a conversation with the person already
131 open (checked by calling find_conversation), show_conv is called to
132 create the new window. All sorts of neat things happen there, but it's
133 mostly drawing the window. show_conv is the best place to edit the UI.
135 That's pretty much it for the quick tutorial. I know it wasn't much but
136 it's enough to get you started. Make sure you know GTK before you get too
137 involved. Most of the back-end stuff is pretty basic; most of gaim is GTK.
140 SOURCE FILES
141 ============
143 about.c:
144   Not much to say here, just a few basic functions.
146 aim.c:
147   This is where the main() function is. It takes care of a lot of the
148   initialization stuff, and showing the login window. It's pretty tiny
149   and there's not really much to edit in it. This has some of the most
150   pointless functions, like gaim_setup, which optionally turns off sounds
151   on signon. A lot of this file should actually be part of other files.
153 applet.c:
154   This controls most things that are related to the applet. I don't like
155   looking at this file because it still has functionsLikeThis. But at
156   least it doesn't have many of them anymore. Anyway, this file isn't
157   very big because there's really not much difference between the panel
158   version and the app version.
160 away.c:
161   This takes care of most of the away stuff: setting the away message
162   (do_away_message); coming back (do_im_back); drawing the away window;
163   etc. Away messages work really oddly due to multiple connections and
164   multiple protocols; I think there are really only two or three people
165   who know how it works and I don't think any of us know why it works
166   that way.
168 browser.c:
169   Code for opening a browser window. Most of the code is trying to deal
170   with Netscape. The most important function here is open_url. Have fun.
172 buddy.c:
173   This takes care of the buddy list window and most things related to it.
174   It still has some functions that manage the list, but not many.
176 buddy_chat.c:
177   This takes care of the buddy chat stuff. This used to be a lot bigger
178   until the chat and IM windows got merged in the code. Now it mostly
179   just takes care of chat-specific stuff, like ignoring people and
180   keeping track of who's in the room. This is also where the chat window
181   is created.
183 conversation.c:
184   This is where most of the functions dealing with the IM and chat windows
185   are hidden. It tries to abstract things as much as possible, but doesn't
186   do a very good job. This is also where things like "Enter sends" and
187   "Ctrl-{B/I/U/S}" options get carried out (look for send_callback). The
188   chat and IM toolbar (with the B/I/U/S buttons) are both built from
189   the same function, build_conv_toolbar.
191 core.c:
192   This is the start of what will become the main() for gaim-core.
194 dialogs.c:
195   A massive file with a lot of little utility functions. This is where all
196   of those little dialog windows are created. Things like the warn dialog
197   and the add buddy dialog are here. Not all of the dialogs in gaim are in
198   this file, though. But most of them are. This is also where do_import
199   is housed, to import buddy lists. (The actual buddy list parsing code
200   is in util.c for winaim lists and buddy.c for gaim's own lists.)
202 gaimrc.c:
203   This controls everything about the .gaimrc file. There's not really much
204   to say about it; this is probably one of the better designed and easier
205   to follow files in gaim. The important functions are towards the bottom.
207 gtkimhtml.c:
208   This is gaim's HTML widget. It replaced the old widget, GtkHtml (which
209   was different than GNOME's GtkHTML). It's self-contained (it doesn't
210   use any of gaim's code) and is actually a separate project from gaim
211   (but is maintained by Eric).
213 gtkspell.c:
214   This controls spell checking. It's not a widget per se but it does have
215   some influence over the GtkText widget. It's a separate project from
216   gaim; if you have a patch for this file send it to the author (the
217   contact info is in the file).
219 gtkticker.c:
220   Syd, our resident GTK God, wrote a GtkWidget, GtkTicker. This is that
221   widget. It's cool, and it's tiny. This is actually a really good example
222   widget for those of you looking to write your own.
224 html.c:
225   Don't ask my why this is called html.c. Most of it is just grab_url,
226   which does like the name says; it downloads a URL to show in the
227   GtkHTML widget.  http.c would be a more appropriate name, but that's OK.
229 idle.c:
230   This file used to be entirely #if 0'd out of existance. However, thanks
231   to some very generous people who submitted patches, this takes care of
232   reporting idle time (imagine that). It's a pretty straight-forward file.
233   This also takes care of the auto-away stuff.
235 list.c:
236   This file contains all of the routines for managing buddy lists,
237   including importing them from a file, saving them, adding and removing
238   buddies and groups, etc.
240 md5.c:
241   Oscar, Yahoo, and MSN all require md5 hashing, so better to put it in
242   the core than have the same thing in three different places.
244 module.c:
245   This contains all of the plugin code, except for the UI. This is what
246   actually loads the plugins, makes sure they're valid, has the code for
247   setting up plugin event handlers, and contains the plugin_event method
248   that gaim calls on events.
250 multi.c:
251   This is the file that tries to take care of most of the major issues
252   with multiple connections. The best function in here by far is the
253   account_editor(). auto_login() is also in here (I'm just reading multi.h
254   now...). account_editor is really the only function that the UI needs
255   to be concerned with.
257 perl.c:
258   This was basically copied straight from X-Chat through the power of
259   the GPL.  Perl is the biggest, most confusing piece of C code I've ever
260   seen in my life (and keep in mind I'm a gaim hacker). I have a basic
261   idea of what's going on in it, but I couldn't tell you exactly. The
262   top half sets up perl and tells it what's going on and the bottom half
263   implements the AIM module.
265 plugins.c:
266   This contains the UI for the plugins dialog. It's mostly GTK.
268 prefs.c:
269   The important function in here is build_prefs, but the most useful
270   function is gaim_button. build_prefs draws the window, and calls
271   gaim_button probably 30 or 40 times. (I don't really wanna run grep
272   | wc to count.) This is where you add the toggle button for gaim
273   preferences. It's very simple, and if you look at a couple of the
274   calls to gaim_button you'll figure it out right away. The new prefs
275   window uses a CList instead of a Notebook, and there's a pretty bad
276   hack to get it to work. I won't tell you what though.
278 proxy.c:
279   Adam (of libfaim glory) got bored one day and rewrote this file, so
280   now everything actually works. The main function is proxy_connect,
281   which figures out which proxy you want to use (if you want to use one
282   at all) and passes off the data to the appropriate function. This file
283   should be pretty straight-forward.
285 prpl.c:
286   This file is what lets gaim dynamically load protocols, sort of. All
287   of the actual dlopen(), dlsym() stuff is in module.c. But this contains
288   all of the functions that the protocol plugin needs to call, and manages
289   all of the protocols. It's a pretty simple file actually.
291 server.c:
292   This is where all of the differentiation between the different protocols
293   is done.  Nearly everything that's network related goes through here
294   at one point or another. This has good things like serv_send_im and
295   serv_got_update. Most of it should be pretty self-explanatory.
297 sound.c:
298   The main function in this file is play_sound, which plays one of 8
299   (maybe 9?) sounds based on preferences. All that the rest of the code
300   should have to do is call play_sound(BUDDY_ARRIVE), for example, and
301   this file will take care of determining if a sound should be played
302   and which file should be played.
304 ticker.c:
305   Syd is just so cool. I really can't get over it. He let me come
306   visit him at Netscape one day, and I got to see all of their toys
307   (don't worry, I'm under an NDA). Anyway, this file is for the buddy
308   ticker. This is also a damn cool file because it's got all of the
309   functions that you'd want right up at the top. Someday I want to be
310   as cool as Syd.
312 util.c:
313   There's not really a lot of cohesion to this file; it's just a lot of
314   stuff that happened to be thrown into it for no apparent reason. None
315   of it is particularly tasty; it's all just utility functions. Just
316   like the name says.
318 For the PRPLs, the only protocol whose "main" gaim file isn't the same as
319 the name of the protocol is ICQ; for that it's gaim_icq.c. But ICQ is
320 deprecated and you should be using Oscar for ICQ anyway.
322 HOW BUDDY LISTS WORK
323 ====================
325 The buddy list is a pain in the ass. Let me start off by saying that. The
326 most difficult part about getting gaim to do multiple connections was
327 the buddy list. In its current state it's very much like the UI for
328 0.10.x and earlier, which is what I was aiming for. However, the code
329 is completely different. And not much better.
331 There are two parts to the buddy list: the lists for the connections and
332 the Buddy List window. list.c contains code to manage the lists themselves
333 and buddy.c contains the code for the Buddy List window.
335 Each buddy needs to belong to a connection, it cannot belong to a
336 "protocol" like in EveryBuddy. The reason is because when you are adding
337 buddies, you tell the server who is on your buddy list so it can tell you
338 about them; in order to tell the server, it needs to go out over a
339 connection. Going out over all connections would not be good, so you need
340 to specify which connection they go out on.
342 Managing lists is therefore fairly easy, each group and buddy has an
343 associated connection. Management functions like add_buddy/remove_buddy
344 and add_group/remove_group all take a gaim_connection. These are all in
345 list.c. They're boring.
347 The window is a lot more fun. There's really only one function that
348 does anything interesting, and that's set_buddy. (There's also things
349 like build_edit_tree, but that's boring.) set_buddy is called by
350 serv_got_update (and should only be called by that function) any time
351 a user signs on, signs off, goes away, comes back, goes idle, etc, etc,
352 etc. Various things happen depending on the new state of the buddy.
354 struct buddy has a member, present, which is set to either 0, 1, or
355 2. You can check if the buddy is online with "if (b->present)". This
356 becomes important. present is set to either 0 or 1 by serv_got_update,
357 or is not set at all. When the buddy is passed to set_buddy, if present
358 is 1 then set_buddy plays the BUDDY_ARRIVE sound, and sets present to 2,
359 to indicate it has already received notification of arrival. It then
360 does other signin-related stuff: setting the pixmap to the login icon;
361 updating the conversation windows; etc.
363 The most important thing it does though, if a buddy is present, is it
364 checks for the existance of the appropriate group_show and buddy_show for
365 that buddy.  Each buddy must belong to a group. group_shows are based on
366 name; there can only be one group_show for each group name. buddy_shows
367 are based both on name and on group_show; there can only be one buddy_show
368 in a group_show for each name. However, there can be two buddy_shows
369 with the same name as long as they have different group_shows.
371 Each buddy_show has a GList of connections that has registered its related
372 buddy as being online. set_buddy makes sure that the connection that it's
373 being passed is part of the connlist for the buddy_show associated with
374 the struct buddy that it's passed (it helps to know your data structures).
376 If a buddy logs off (b->present == 0), and a buddy_show exists for
377 that buddy, then set_buddy will play the logoff sound, change the icon,
378 remove the connection from the connlist for the buddy_show, etc.
380 And that's how that works. For the buddy lists, connections own buddies;
381 for the window, the buddies own the connections. When the buddy_show
382 connlist count drops to zero it disappears from existance.
385 PLUGINS
386 =======
388 OK, so you want to load a plugin. You go through whatever UI (you
389 can read all about the UI in plugins.c or whereever). You finally get
390 to load_plugin, the meat of the plugins stuff (plugins can actually
391 call load_plugin themselves to load other plugins). load_plugin
392 is passed the full path to the plugin you want to load
393 (e.g. /usr/local/lib/gaim/irc.so).
395 load_plugin does a few things with that filename. The first is to see
396 if you've already loaded that plugin. If you have, load_plugin unloads
397 the one that is currently loaded. You might wonder why; it's because
398 the same plugin can't be loaded twice. If you call g_module_open on a
399 filename twice, both times it will return the same pointer, and both times
400 increment the reference count on the GModule * that it returns. This
401 means you really do have the same plugin twice, which fucks up the
402 callback system to no end.  So it's better that you can only have it
403 loaded once at any given time.
405 Now that we're assured that we don't have this particular plugin loaded
406 yet, we better load it. g_module_open, baby. Much more portable than
407 dlopen().  In fact, for Linux it actually is the equivalent of dlopen()
408 (you can read the gmodule source and see for yourself). There's only one
409 quirk. It always logically ORs the options you pass with RTLD_GLOBAL,
410 which means that plugins share symbols. I haven't figured out yet if
411 this means just functions or variables too; but in either case make every
412 function and variable in your plugin static except for gaim_plugin_*(),
413 name(), and description().  It's good coding practice anyway.
415 So, assuming we didn't get NULL back from g_module_open, we then make sure
416 it's a valid gaim plugin by looking for and calling gaim_plugin_init,
417 courtesy g_module_symbol (g_module_symbol is actually what's portable
418 about gmodule as opposed to dl*; some BSD's require '_' prepended to
419 symbol names and g_module_symbol guarantees we do The Right Thing).
421 Assuming we've found gaim_plugin_init and it hasn't returned non-NULL
422 to us, we then add it to our list of plugins and go merrily about our way.
424 So when do the callbacks happen?! plugin_event, baby, plugin_event. Any
425 time you want to trigger a plugin event simply call plugin_even with the
426 parameters to be passed to any event handlers and you're set. plugin_event
427 then makes sure that any plugins waiting for the event get passed the
428 arguments properly and passes it on to perl.
430 Speaking of perl. If you really want to know how this works, you're
431 better off reading X-Chat's documentation of it, because it's better
432 than what I could provide.
435 MULTIPLE CONNECTIONS AND PRPLS
436 ==============================
438 OK, let's start with the basics. There are users. Each user is contained
439 in an aim_user struct, and kept track of in the aim_users GList (GSList?).
440 Each aim_user has certain features: a username, a password, and user_info.
441 It also has certain options, and the protocol it uses to sign on (kept
442 as an int which is #define'd in prpl.h).
444 Now then, there are protocols that gaim knows about. Each protocol is
445 in a prpl struct and kept track of in the protocols GSList. The way the
446 management of the protocols is, there will only ever be one prpl per
447 numeric protocol. Each prpl defines a basic set of functions: login,
448 logout, send_im, etc. The prpl is responsible not only for handling
449 these functions, but also for calling the appropriate serv_got functions
450 (e.g. serv_got_update when a buddy comes online/goes offline/goes
451 idle/etc). It handles each of these on a per-connection basis.
453 So why's it called a PRPL? It stands for PRotocol PLugin. That means
454 that it's possible to dynamically add new protocols to gaim. However,
455 all protocols must be implemented the same way: by using a prpl struct
456 and being loaded, regardless of whether they are static or dynamic.
458 Here's how struct gaim_connection fits into all of this. At some point
459 the User (capitalized to indicate a person and not a name) will try to
460 sign on one of Their users. serv_login is then called for that user. It
461 searches for the prpl that is assigned to that user, and calls that prpl's
462 login function, passing it the aim_user struct that is attempting to sign
463 on. The prpl is then responsible for seeing that the gaim_connection
464 is created (by calling new_gaim_connection), and registering it as
465 being online (by calling account_online and passing it the aim_user and
466 gaim_connection structs). At that point, the aim_user and gaim_connection
467 structs have pointers to each other, and the gaim_connection struct has
468 a pointer to the prpl struct that it is using. The gaim_connections are
469 stored in the connections GSList.  The way connection management works is,
470 there will always only be one gaim_connection per user, and the prpl that
471 the gaim_connection uses will be constant for the gaim_connection's life.
473 So at certain points the User is going to want to do certain things,
474 like send a message. They must send the message on a connection. So the UI
475 figures out which gaim_connection the User want to send a message on (for
476 our example), and calls serv_send_im, telling it which gaim_connection to
477 use, and the necessary information (who to send it to, etc). The serv_
478 function then calls the handler of the prpl of the connection for that
479 event (that was way too many prepositions). OK, each prpl has a send_im
480 function. Each connection has a prpl. so you call gc->prpl->send_im and
481 pass it the connection and all the necessary info. And that's how things
482 get done.
484 I hope some of that made sense. Looking back at it it makes absolutely no
485 sense to me. Thank god I wrote the code; otherwise I'm sure I'd be lost.
488 WRITING PRPLS
489 =============
491 Start off with a protocol that you want to implement; make sure it has a
492 number defined in prpl.h. If it doesn't, talk to Rob or Eric about adding
493 it. *NEVER* use an unassigned number, not even for testing or personal
494 use. It's possible that number will be used later by something else and
495 that would cause quite a few head-scratchers.
497 Start off with the following boiler plate:
499 static struct prpl *my_protocol = NULL;
501 void newproto_init(struct prpl *ret) {
502         ret->protocol = PROTO_NEWPROTO;
504         my_protocol = ret;
507 #ifndef STATIC
509 char *gaim_plugin_init(GModule *handle)
511         load_protocol(newproto_init, sizeof(struct prpl));
512         return NULL;
515 void gaim_plugin_remove()
517         struct prpl *p = find_prpl(PROTO_NEWPROTO);
518         if (p == my_protocol)
519                 unload_protocol(p);
522 char *name()
524         return "New Protocol";
527 char *description()
529         return PRPL_DESC("New Protocol");
532 #endif
534 Replace all NEWPROTO things with your protocol name (e.g. PROTO_OSCAR
535 instead of PROTO_NEWPROTO, oscar_init instead of newproto_init). Then
536 populate your struct prpl; the most important function is actually name(),
537 because without it, Gaim will most likely segfault. The second most
538 important function is login(). Not all functions need to be implemented.
540 There should be absolutely *ZERO* GTK in the PRPLs. PRPLs should *NEVER*
541 say what the UI *looks* like, only what information needs to be there.
542 There's currently an effort to get the GTK that is contained in the PRPLs
543 directory out of there. If you submit a patch that adds GTK to those
544 directories it's very likely to be refused, unless if I'm in a good mood
545 and decide to relocate things for you. That's not likely.
547 You're probably wondering how you can do certain things without GTK. Well,
548 you're just going to have to make do. Rely on the UI, that's why it's
549 there.  A PRPL should have absolutely ZERO interaction with the user, it
550 should all be handled by the UI.
552 Don't use the _options variables at all. The core should take care of all
553 of that. There are several proto_opt fields that you can use on a per-user
554 basis. Check out existing protocols for more details.