Index: protocols/twitter/twitter.c
===================================================================
--- protocols/twitter/twitter.c	(revision b4dd25398db477b06452be195de14ca352008665)
+++ protocols/twitter/twitter.c	(revision 62d2cfb0b7b5e7f3eda9ca13b1877d3ad74fcd5e)
@@ -29,6 +29,6 @@
 
 /**
- *  * Main loop function
- *   */
+ * Main loop function
+ */
 gboolean twitter_main_loop(gpointer data, gint fd, b_input_condition cond)
 {
@@ -38,4 +38,9 @@
 		return 0;
 
+	// If the user uses multiple private message windows we need to get the 
+	// users buddies.
+	if (!set_getbool( &ic->acc->set, "use_groupchat" ))
+		twitter_get_statuses_friends(ic, -1);
+
 	// Do stuff..
 	twitter_get_home_timeline(ic, -1);
@@ -48,4 +53,6 @@
 static void twitter_init( account_t *acc )
 {
+	set_t *s;
+	s = set_add( &acc->set, "use_groupchat", "false", set_eval_bool, acc );
 }
 
@@ -58,5 +65,5 @@
 	struct im_connection *ic = imcb_new( acc );
 	struct twitter_data *td = g_new0( struct twitter_data, 1 );
-	
+
 	td->user = acc->user;
 	td->pass = acc->pass;
@@ -68,9 +75,4 @@
 	ic->flags = OPT_LOGGED_IN;
 
-	// Try to get the buddies...
-	//twitter_get_friends_ids(ic, -1);
-
-	//twitter_get_home_timeline(ic, -1);
-
 	// Run this once. After this queue the main loop function.
 	twitter_main_loop(ic, -1, 0);
@@ -81,4 +83,6 @@
 	imcb_log( ic, "Connecting to twitter" );
 	imcb_connected(ic);
+
+	twitter_connections = g_slist_append( twitter_connections, ic );
 }
 
@@ -97,4 +101,6 @@
 		g_free( td );
 	}
+
+	twitter_connections = g_slist_remove( twitter_connections, ic );
 }
 
@@ -104,6 +110,9 @@
 static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message, int away )
 {
-	imcb_log( ic, "In twitter_buddy_msg...");
-	twitter_post_status(ic, message);
+	// Let's just update the status.
+//	if ( g_strcasecmp(who, ic->acc->user) == 0 )
+		twitter_post_status(ic, message);
+//	else
+//		twitter_direct_messages_new(ic, who, message);
 	return( 0 );
 }
@@ -124,9 +133,4 @@
 static void twitter_set_my_name( struct im_connection *ic, char *info )
 {
-	imcb_log( ic, "In twitter_set_my_name..." );
-//	char * aap = twitter_http("http://gertje.org", NULL, ic, 1, "geert", "poep", NULL, 0);
-
-//	imcb_log( ic, aap );
-//	g_free(aap);
 }
 
@@ -218,4 +222,7 @@
 
 	register_protocol(ret);
-}
-
+
+	// Initialise the twitter_connections GSList.
+	twitter_connections = NULL;
+}
+
Index: protocols/twitter/twitter.h
===================================================================
--- protocols/twitter/twitter.h	(revision b4dd25398db477b06452be195de14ca352008665)
+++ protocols/twitter/twitter.h	(revision 62d2cfb0b7b5e7f3eda9ca13b1877d3ad74fcd5e)
@@ -41,3 +41,10 @@
 };
 
+/**
+ * This has the same function as the msn_connections GSList. We use this to 
+ * make sure the connection is still alive in callbacks before we do anything
+ * else.
+ */
+GSList *twitter_connections;
+
 #endif //_TWITTER_H
Index: protocols/twitter/twitter_lib.c
===================================================================
--- protocols/twitter/twitter_lib.c	(revision b4dd25398db477b06452be195de14ca352008665)
+++ protocols/twitter/twitter_lib.c	(revision 62d2cfb0b7b5e7f3eda9ca13b1877d3ad74fcd5e)
@@ -34,7 +34,11 @@
 
 #define TXL_STATUS 1
-#define TXL_ID 1
+#define TXL_USER 2
+#define TXL_ID 3
+
+static void twitter_imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at );
 
 struct twitter_xml_list {
+	int type;
 	int next_cursor;
 	GSList *list;
@@ -54,7 +58,52 @@
 };
 
-void txl_free(struct twitter_xml_list *txl, int type);
-void txs_free(struct twitter_xml_status *txs);
-void txu_free(struct twitter_xml_user *txu);
+/**
+ * Frees a twitter_xml_user struct.
+ */
+static void txu_free(struct twitter_xml_user *txu)
+{
+	g_free(txu->name);
+	g_free(txu->screen_name);
+}
+
+
+/**
+ * Frees a twitter_xml_status struct.
+ */
+static void txs_free(struct twitter_xml_status *txs)
+{
+	g_free(txs->created_at);
+	g_free(txs->text);
+	txu_free(txs->user);
+}
+
+/**
+ * Free a twitter_xml_list struct.
+ * type is the type of list the struct holds.
+ */
+static void txl_free(struct twitter_xml_list *txl)
+{
+	GSList *l;
+	for ( l = txl->list; l ; l = g_slist_next(l) )
+		if (txl->type == TXL_STATUS)
+			txs_free((struct twitter_xml_status *)l->data);
+		else if (txl->type == TXL_ID)
+			g_free(l->data);
+	g_slist_free(txl->list);
+}
+
+/**
+ * Add a buddy if it is not allready added, set the status to logged in.
+ */
+static void twitter_add_buddy(struct im_connection *ic, char *name)
+{
+	// Check if the buddy is allready in the buddy list.
+	if (!user_findhandle( ic, name ))
+	{
+		// The buddy is not in the list, add the buddy and set the status to logged in.
+		imcb_add_buddy( ic, name, NULL );
+		imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
+	}
+}
 
 static void twitter_http_get_friends_ids(struct http_request *req);
@@ -93,4 +142,7 @@
 {
 	struct xt_node *child;
+	
+	// Set the list type.
+	txl->type = TXL_ID;
 
 	// The root <statuses> node should hold the list of statuses <status>
@@ -122,4 +174,8 @@
 
 	ic = req->data;
+
+	// Check if the connection is still active.
+	if( !g_slist_find( twitter_connections, ic ) )
+		return;
 
 	// Check if the HTTP request went well.
@@ -142,5 +198,5 @@
 		twitter_get_friends_ids(ic, txl->next_cursor);
 
-	txl_free(txl, TXL_ID);
+	txl_free(txl);
 	g_free(txl);
 }
@@ -170,4 +226,64 @@
 	return XT_HANDLED;
 }
+
+/**
+ * Function to fill a twitter_xml_list struct.
+ * It sets:
+ *  - all <user>s from the <users> element.
+ */
+static xt_status twitter_xt_get_users( struct xt_node *node, struct twitter_xml_list *txl )
+{
+	struct twitter_xml_user *txu;
+	struct xt_node *child;
+
+	// Set the type of the list.
+	txl->type = TXL_USER;
+
+	// The root <users> node should hold the list of users <user>
+	// Walk over the nodes children.
+	for( child = node->children ; child ; child = child->next )
+	{
+		if ( g_strcasecmp( "user", child->name ) == 0)
+		{
+			txu = g_new0(struct twitter_xml_user, 1);
+			twitter_xt_get_user(child, txu);
+			// Put the item in the front of the list.
+			txl->list = g_slist_prepend (txl->list, txu);
+		}
+	}
+
+	return XT_HANDLED;
+}
+
+/**
+ * Function to fill a twitter_xml_list struct.
+ * It calls twitter_xt_get_users to get the <user>s from a <users> element.
+ * It sets:
+ *  - the next_cursor.
+ */
+static xt_status twitter_xt_get_user_list( struct xt_node *node, struct twitter_xml_list *txl )
+{
+	struct xt_node *child;
+
+	// Set the type of the list.
+	txl->type = TXL_USER;
+
+	// The root <user_list> node should hold a users <users> element
+	// Walk over the nodes children.
+	for( child = node->children ; child ; child = child->next )
+	{
+		if ( g_strcasecmp( "users", child->name ) == 0)
+		{
+			twitter_xt_get_users(child, txl);
+		}
+		else if ( g_strcasecmp( "next_cursor", child->name ) == 0)
+		{
+			twitter_xt_next_cursor(child, txl);
+		}
+	}
+
+	return XT_HANDLED;
+}
+
 
 /**
@@ -218,4 +334,7 @@
 	struct xt_node *child;
 
+	// Set the type of the list.
+	txl->type = TXL_STATUS;
+
 	// The root <statuses> node should hold the list of statuses <status>
 	// Walk over the nodes children.
@@ -264,13 +383,68 @@
 
 /**
+ * Function that is called to see the statuses in a groupchat window.
+ */
+static void twitter_groupchat(struct im_connection *ic, GSList *list)
+{
+	struct twitter_data *td = ic->proto_data;
+	GSList *l = NULL;
+	struct twitter_xml_status *status;
+	struct groupchat *gc;
+
+	// Create a new groupchat if it does not exsist.
+	if (!td->home_timeline_gc)
+	{   
+		td->home_timeline_gc = gc = imcb_chat_new( ic, "home/timeline" );
+		// Add the current user to the chat...
+		imcb_chat_add_buddy( gc, ic->acc->user );
+	}
+	else
+	{   
+		gc = td->home_timeline_gc;
+	}
+
+	for ( l = list; l ; l = g_slist_next(l) )
+	{
+		status = l->data;
+		twitter_add_buddy(ic, status->user->screen_name);
+		// Say it!
+		twitter_imcb_chat_msg (gc, status->user->screen_name, status->text, 0, 0 );
+		// Update the home_timeline_id to hold the highest id, so that by the next request
+		// we won't pick up the updates allready in the list.
+		td->home_timeline_id = td->home_timeline_id < status->id ? status->id : td->home_timeline_id;
+	}
+}
+
+/**
+ * Function that is called to see statuses as private messages.
+ */
+static void twitter_private_message_chat(struct im_connection *ic, GSList *list)
+{
+	struct twitter_data *td = ic->proto_data;
+	GSList *l = NULL;
+	struct twitter_xml_status *status;
+
+	for ( l = list; l ; l = g_slist_next(l) )
+	{
+		status = l->data;
+		imcb_buddy_msg( ic, status->user->screen_name, status->text, 0, 0 );
+		// Update the home_timeline_id to hold the highest id, so that by the next request
+		// we won't pick up the updates allready in the list.
+		td->home_timeline_id = td->home_timeline_id < status->id ? status->id : td->home_timeline_id;
+	}
+}
+
+/**
  * Callback for getting the home timeline.
  */
 static void twitter_http_get_home_timeline(struct http_request *req)
 {
-	struct im_connection *ic = req->data;;
+	struct im_connection *ic = req->data;
 	struct xt_parser *parser;
 	struct twitter_xml_list *txl;
-	struct twitter_data *td = ic->proto_data;
-	struct groupchat *gc;
+
+	// Check if the connection is still active.
+	if( !g_slist_find( twitter_connections, ic ) )
+		return;
 
 	// Check if the HTTP request went well.
@@ -283,5 +457,5 @@
 	txl = g_new0(struct twitter_xml_list, 1);
 	txl->list = NULL;
-	
+
 	// Parse the data.
 	parser = xt_new( NULL, txl );
@@ -290,85 +464,83 @@
 	twitter_xt_get_status_list(parser->root, txl);
 	xt_free( parser );
-	
-	GSList *l;
-	struct twitter_xml_status *status;
-
-	// Create a new groupchat if it does not exsist.
-	if (!td->home_timeline_gc)
-	{
-		td->home_timeline_gc = gc = imcb_chat_new( ic, "home/timeline" );
-		// Add the current user to the chat...
-		imcb_chat_add_buddy( gc, ic->acc->user );
-	}
+
+	// See if the user wants to see the messages in a groupchat window or as private messages.
+	if (set_getbool( &ic->acc->set, "use_groupchat" ))
+		twitter_groupchat(ic, txl->list);
 	else
-	{
-		gc = td->home_timeline_gc;
-	}
-
+		twitter_private_message_chat(ic, txl->list);
+
+	// Free the structure.	
+	txl_free(txl);
+	g_free(txl);
+}
+
+/**
+ * Callback for getting (twitter)friends...
+ *
+ * Be afraid, be very afraid! This function will potentially add hundreds of "friends". "Who has 
+ * hundreds of friends?" you wonder? You probably not, since you are reading the source of 
+ * BitlBee... Get a life and meet new people!
+ */
+static void twitter_http_get_statuses_friends(struct http_request *req)
+{
+	struct im_connection *ic = req->data;
+	struct xt_parser *parser;
+	struct twitter_xml_list *txl;
+
+	// Check if the connection is still active.
+	if( !g_slist_find( twitter_connections, ic ) )
+		return;
+
+	// Check if the HTTP request went well.
+	if (req->status_code != 200) {
+		// It didn't go well, output the error and return.
+		imcb_error(ic, "Could not retrieve home/timeline. HTTP STATUS: %d", req->status_code);
+		return;
+	}
+
+	txl = g_new0(struct twitter_xml_list, 1);
+	txl->list = NULL;
+
+	// Parse the data.
+	parser = xt_new( NULL, txl );
+	xt_feed( parser, req->reply_body, req->body_size );
+
+	// Get the user list from the parsed xml feed.
+	twitter_xt_get_user_list(parser->root, txl);
+	xt_free( parser );
+
+	GSList *l = NULL;
+	struct twitter_xml_user *user;
+	// Add the users as buddies.
 	for ( l = txl->list; l ; l = g_slist_next(l) )
 	{
-		status = l->data;
-		// TODO Put the next part in a new function....
-
-		// Ugly hack, to show current user in chat...
-		if ( g_strcasecmp(status->user->screen_name, ic->acc->user) == 0)
-		{
-			char *tmp = g_strdup_printf ("_%s_", status->user->screen_name);
-			g_free(status->user->screen_name);
-			status->user->screen_name = tmp;
-		}
-
-		// Check if the buddy is allready in the buddy list.
-		if (!user_findhandle( ic, status->user->screen_name ))
-		{
-			// The buddy is not in the list, add the buddy...
-			imcb_add_buddy( ic, status->user->screen_name, NULL );
-			imcb_buddy_status( ic, status->user->screen_name, OPT_LOGGED_IN, NULL, NULL );
-		}
-
-		// Say it!
-		imcb_chat_msg (gc, status->user->screen_name, status->text, 0, 0 );
-		// Update the home_timeline_id to hold the highest id, so that by the next request
-		// we won't pick up the updates allready in the list.
-		td->home_timeline_id = td->home_timeline_id < status->id ? status->id : td->home_timeline_id;
-	}
-
-	// Free the structure.	
-	txl_free(txl, TXL_STATUS);
+		user = l->data;
+		twitter_add_buddy(ic, user->screen_name);
+	}
+
+	// if the next_cursor is set to something bigger then 0 there are more friends to gather.
+	if (txl->next_cursor > 0)
+		twitter_get_statuses_friends(ic, txl->next_cursor);
+
+	// Free the structure.
+	txl_free(txl);
 	g_free(txl);
 }
 
 /**
- * Free a twitter_xml_list struct.
- * type is the type of list the struct holds.
- */
-void txl_free(struct twitter_xml_list *txl, int type)
-{
-	GSList *l;
-	for ( l = txl->list; l ; l = g_slist_next(l) )
-		if (type == TXL_STATUS)
-			txs_free((struct twitter_xml_status *)l->data);
-		else if (type == TXL_ID)
-			g_free(l->data);
-	g_slist_free(txl->list);
-}
-
-/**
- * Frees a twitter_xml_status struct.
- */
-void txs_free(struct twitter_xml_status *txs)
-{
-	g_free(txs->created_at);
-	g_free(txs->text);
-	txu_free(txs->user);
-}
-
-/**
- * Frees a twitter_xml_user struct.
- */
-void txu_free(struct twitter_xml_user *txu)
-{
-	g_free(txu->name);
-	g_free(txu->screen_name);
+ * Get the friends.
+ */
+void twitter_get_statuses_friends(struct im_connection *ic, int next_cursor)
+{
+	struct twitter_data *td = ic->proto_data;
+
+	char* args[2];
+	args[0] = "cursor";
+	args[1] = g_strdup_printf ("%d", next_cursor);
+
+	twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, args, 2);
+
+	g_free(args[1]);
 }
 
@@ -379,4 +551,8 @@
 {
 	struct im_connection *ic = req->data;
+
+	// Check if the connection is still active.
+	if( !g_slist_find( twitter_connections, ic ) )
+		return;
 
 	// Check if the HTTP request went well.
@@ -400,6 +576,51 @@
 	args[1] = msg;
 	twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, args, 2);
-	g_free(args[1]);
-}
-
-
+//	g_free(args[1]);
+}
+
+
+/**
+ * Function to POST a new message to twitter.
+ */
+void twitter_direct_messages_new(struct im_connection *ic, char *who, char *msg)
+{
+	struct twitter_data *td = ic->proto_data;
+
+	char* args[4];
+	args[0] = "screen_name";
+	args[1] = who;
+	args[2] = "text";
+	args[3] = msg;
+	// Use the same callback as for twitter_post_status, since it does basically the same.
+	twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, args, 4);
+//	g_free(args[1]);
+//	g_free(args[3]);
+}
+
+
+/**
+ * This function "overwrites" the imcb_chat_msg function. Because in the original the logged in user is filtered out.
+ */
+static void twitter_imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at )
+{
+	struct im_connection *ic = c->ic;
+	char *wrapped;
+	user_t *u;
+
+	u = user_findhandle( ic, who );
+	if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) 
+			|| ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
+		strip_html( msg );
+
+	wrapped = word_wrap( msg, 425 );
+	if( c && u )
+	{   
+		irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", wrapped );
+	}
+	else
+	{   
+		imcb_log( ic, "Message from/to conversation %s@%p (unknown conv/user): %s", who, c, wrapped );
+	}
+	g_free( wrapped );
+}
+
Index: protocols/twitter/twitter_lib.h
===================================================================
--- protocols/twitter/twitter_lib.h	(revision b4dd25398db477b06452be195de14ca352008665)
+++ protocols/twitter/twitter_lib.h	(revision 62d2cfb0b7b5e7f3eda9ca13b1877d3ad74fcd5e)
@@ -51,7 +51,7 @@
 /* Direct messages URLs */
 #define TWITTER_DIRECT_MESSAGES_URL TWITTER_API_URL "/direct_messages.xml"
-#define TWITTER_DIRECT_MESSAGENEW_URL TWITTER_API_URL "/direct_messages/new.xml"
-#define TWITTER_DIRECT_MESSAGESSENT_URL TWITTER_API_URL "/direct_messages/sent.xml"
-#define TWITTER_DIRECT_MESSAGEDESTROY_URL TWITTER_API_URL "/direct_messages/destroy/"
+#define TWITTER_DIRECT_MESSAGES_NEW_URL TWITTER_API_URL "/direct_messages/new.xml"
+#define TWITTER_DIRECT_MESSAGES_SENT_URL TWITTER_API_URL "/direct_messages/sent.xml"
+#define TWITTER_DIRECT_MESSAGES_DESTROY_URL TWITTER_API_URL "/direct_messages/destroy/"
 
 /* Friendships URLs */
@@ -78,6 +78,8 @@
 void twitter_get_friends_ids(struct im_connection *ic, int next_cursor);
 void twitter_get_home_timeline(struct im_connection *ic, int next_cursor);
+void twitter_get_statuses_friends(struct im_connection *ic, int next_cursor);
 
-void twitter_post_status(struct im_connection *ic, char* msg);
+void twitter_post_status(struct im_connection *ic, char *msg);
+void twitter_direct_messages_new(struct im_connection *ic, char *who, char *message);
 
 #endif //_TWITTER_LIB_H
