--- blist.c.old	2004-07-31 22:29:38.000000000 +0100
+++ blist.c	2004-08-08 18:42:05.000000000 +0100
@@ -270,6 +270,7 @@
 		buddy->present = GAIM_BUDDY_ONLINE;
 	} else if (buddy->present == GAIM_BUDDY_SIGNING_OFF) {
 		buddy->present = GAIM_BUDDY_OFFLINE;
+		gaim_buddy_update_last_seen(buddy);
 		((GaimContact*)((GaimBlistNode*)buddy)->parent)->online--;
 		if (((GaimContact*)((GaimBlistNode*)buddy)->parent)->online == 0)
 			((GaimGroup *)((GaimBlistNode *)buddy)->parent->parent)->online--;
@@ -326,6 +327,59 @@
 	}
 }
 
+void gaim_buddy_update_last_seen(GaimBuddy *buddy)
+{
+	time_t now = time(NULL);
+	char now_str[11];
+
+	if(!buddy)
+		return;
+
+	g_snprintf(now_str, 11, "%ld", now);
+	gaim_blist_node_set_string((GaimBlistNode*)buddy, "last_seen", now_str);
+	gaim_blist_schedule_save();
+}
+
+time_t gaim_buddy_get_last_seen(GaimBuddy *buddy)
+{
+	time_t last = 0;
+	const char* last_str;
+
+	if(!buddy || GAIM_BUDDY_IS_ONLINE(buddy))
+		return 0;
+
+	last_str = gaim_blist_node_get_string((GaimBlistNode*)buddy, "last_seen");
+	if(last_str)
+		last = strtol(last_str, NULL, 10);
+
+	return last;
+}
+
+time_t  gaim_contact_get_last_seen(GaimContact *contact) {
+	GaimBlistNode *bnode;
+	time_t most_recent = 0;
+
+	if(!contact)
+		return 0;
+
+	for(bnode = ((GaimBlistNode*)contact)->child; bnode; bnode = bnode->next) {
+		time_t score;
+		GaimBuddy *buddy;
+
+		if (!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+			continue;
+		buddy = (GaimBuddy*)bnode;
+		if (GAIM_BUDDY_IS_ONLINE(buddy))
+			return 0;
+
+		score = gaim_buddy_get_last_seen(buddy);
+		if (score > most_recent)
+			most_recent = score;
+	}
+
+	return most_recent;
+}
+
 void gaim_blist_update_buddy_signon(GaimBuddy *buddy, time_t signon)
 {
 	GaimBlistUiOps *ops = gaimbuddylist->ui_ops;
@@ -1696,6 +1750,7 @@
 							((GaimContact*)cnode)->online--;
 							if (((GaimContact*)cnode)->online == 0)
 								((GaimGroup*)gnode)->online--;
+							gaim_buddy_update_last_seen(bnode);
 						}
 						((GaimContact*)cnode)->currentsize--;
 						if (((GaimContact*)cnode)->currentsize == 0)
--- blist.h.old	2004-08-01 19:32:03.000000000 +0100
+++ blist.h	2004-08-08 18:43:08.000000000 +0100
@@ -260,6 +260,30 @@
 void gaim_blist_update_buddy_presence(GaimBuddy *buddy, int presence);
 
 /**
+ * Updates the timestamp indicating when a buddy was last seen online.
+ * 
+ * @param buddy    The buddy whose timestamp should be updated
+ */
+void gaim_buddy_update_last_seen(GaimBuddy *buddy);
+
+/**
+ * Retrieve the timestamp indicating when a buddy was last seen online.
+ *
+ * @param buddy    The buddy whose timestamp should be retrieved
+ * @return         The timestamp, or 0 if never or currently online
+ */
+time_t gaim_buddy_get_last_seen(GaimBuddy *buddy);
+
+/**
+ * Retrieve the timestamp indicating when a contact was last seen online.
+ *
+ * @param contact  The contact whose timestamp should be retrieved
+ * @return         The timestamp, or 0 if never or currently online
+ */
+time_t gaim_contact_get_last_seen(GaimContact *contact);
+
+
+/**
  * Updates a buddy's signon time.
  *
  * @param buddy  The buddy whose idle time has changed.
--- gtkblist.c.old	2004-08-06 00:04:16.000000000 +0100
+++ gtkblist.c	2004-08-08 18:47:23.000000000 +0100
@@ -2439,14 +2439,18 @@
 		char *loggedin = NULL, *idletime = NULL;
 		char *warning = NULL;
 		char *accounttext = NULL;
+		char *lastseen = NULL;
+		time_t lasttime = 0;
 
 		if(GAIM_BLIST_NODE_IS_CONTACT(node)) {
 			GaimContact *contact = (GaimContact*)node;
 			b = gaim_contact_get_priority_buddy(contact);
+			lasttime = gaim_contact_get_last_seen(contact);
 			if(contact->alias)
 				contactaliastext = g_markup_escape_text(contact->alias, -1);
 		} else {
 			b = (GaimBuddy *)node;
+			lasttime = gaim_buddy_get_last_seen(b);
 		}
 
 		prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account));
@@ -2464,6 +2468,9 @@
 			}
 		}
 
+		if (!GAIM_BUDDY_IS_ONLINE(b))
+			lastseen = ((!lasttime) ? g_strdup(_("Never")) : gaim_str_seconds_to_string(time(NULL) - lasttime));
+
 		if (!statustext && !GAIM_BUDDY_IS_ONLINE(b))
 			statustext = g_strdup(_("\n<b>Status:</b> Offline"));
 
@@ -2491,6 +2498,7 @@
 				       "%s %s"  /* Alias */
 				       "%s %s"  /* Nickname */
 				       "%s %s"  /* Logged In */
+					   "%s %s"  /* Last Seen */
 				       "%s %s"  /* Idle */
 				       "%s %s"  /* Warning */
 				       "%s"     /* Status */
@@ -2501,6 +2509,7 @@
 				       aliastext ? _("\n<b>Alias:</b>") : "", aliastext ? aliastext : "",
 				       nicktext ? _("\n<b>Nickname:</b>") : "", nicktext ? nicktext : "",
 				       loggedin ? _("\n<b>Logged In:</b>") : "", loggedin ? loggedin : "",
+					   lastseen ? _("\n<b>Last Seen:</b>") : "", lastseen ? lastseen : "",
 				       idletime ? _("\n<b>Idle:</b>") : "", idletime ? idletime : "",
 				       b->evil ? _("\n<b>Warned:</b>") : "", b->evil ? warning : "",
 				       statustext ? statustext : "",
@@ -2512,6 +2521,8 @@
 			g_free(warning);
 		if(loggedin)
 			g_free(loggedin);
+		if(lastseen)
+			g_free(lastseen);
 		if(idletime)
 			g_free(idletime);
 		if(statustext)

