mcabber/mcabber/roster.c
changeset 2337 ffd0e57e9563
parent 2324 4ddd6f5c3ffc
child 2346 7921c8d671c8
equal deleted inserted replaced
2336:0dc317b5599d 2337:ffd0e57e9563
    77   struct xep0085 xep85;
    77   struct xep0085 xep85;
    78 #endif
    78 #endif
    79 #ifdef HAVE_GPGME
    79 #ifdef HAVE_GPGME
    80   struct pgp_data pgpdata;
    80   struct pgp_data pgpdata;
    81 #endif
    81 #endif
    82 } res;
    82 } res_t;
    83 
    83 
    84 /* This is a private structure type for the roster */
    84 /* This is a private structure type for the roster_t */
    85 
    85 
    86 typedef struct {
    86 typedef struct {
    87   gchar *name;
    87   gchar *name;
    88   gchar *jid;
    88   gchar *jid;
    89   guint type;
    89   guint type;
    90   enum subscr subscription;
    90   enum subscr subscription;
    91   GSList *resource;
    91   GSList *resource;
    92   res *active_resource;
    92   res_t *active_resource;
    93 
    93 
    94   /* For groupchats */
    94   /* For groupchats */
    95   gchar *nickname;
    95   gchar *nickname;
    96   gchar *topic;
    96   gchar *topic;
    97   guint inside_room;
    97   guint inside_room;
   110   guint ui_prio;  // Boolean, positive if "attention" is requested
   110   guint ui_prio;  // Boolean, positive if "attention" is requested
   111   guint unread;
   111   guint unread;
   112 
   112 
   113   // list: user -> points to his group; group -> points to its users list
   113   // list: user -> points to his group; group -> points to its users list
   114   GSList *list;
   114   GSList *list;
   115 } roster;
   115 } roster_t;
   116 
   116 
   117 
   117 
   118 /* ### Variables ### */
   118 /* ### Variables ### */
   119 
   119 
   120 static guchar display_filter;
   120 static guchar display_filter;
   125 static gboolean _rebuild_buddylist = FALSE;
   125 static gboolean _rebuild_buddylist = FALSE;
   126 GList *current_buddy;
   126 GList *current_buddy;
   127 GList *alternate_buddy;
   127 GList *alternate_buddy;
   128 GList *last_activity_buddy;
   128 GList *last_activity_buddy;
   129 
   129 
   130 static roster roster_special;
   130 static roster_t roster_special;
   131 
   131 
   132 static int  unread_jid_del(const char *jid);
   132 static int  unread_jid_del(const char *jid);
   133 
   133 
   134 #define DFILTER_ALL     63
   134 #define DFILTER_ALL     63
   135 #define DFILTER_ONLINE  62
   135 #define DFILTER_ONLINE  62
   143   roster_special.type = ROSTER_TYPE_SPECIAL;
   143   roster_special.type = ROSTER_TYPE_SPECIAL;
   144 }
   144 }
   145 
   145 
   146 /* ### Resources functions ### */
   146 /* ### Resources functions ### */
   147 
   147 
   148 static inline void free_resource_data(res *p_res)
   148 static inline void free_resource_data(res_t *p_res)
   149 {
   149 {
   150   if (!p_res)
   150   if (!p_res)
   151     return;
   151     return;
   152   g_free((gchar*)p_res->status_msg);
   152   g_free((gchar*)p_res->status_msg);
   153   g_free((gchar*)p_res->name);
   153   g_free((gchar*)p_res->name);
   162 static void free_all_resources(GSList **reslist)
   162 static void free_all_resources(GSList **reslist)
   163 {
   163 {
   164   GSList *lip;
   164   GSList *lip;
   165 
   165 
   166   for (lip = *reslist; lip ; lip = g_slist_next(lip))
   166   for (lip = *reslist; lip ; lip = g_slist_next(lip))
   167     free_resource_data((res*)lip->data);
   167     free_resource_data((res_t *)lip->data);
   168   // Free all nodes but the first (which is static)
   168   // Free all nodes but the first (which is static)
   169   g_slist_free(*reslist);
   169   g_slist_free(*reslist);
   170   *reslist = NULL;
   170   *reslist = NULL;
   171 }
   171 }
   172 
   172 
   173 // Resources are sorted in ascending order
   173 // Resources are sorted in ascending order
   174 static gint resource_compare_prio(res *a, res *b) {
   174 static gint resource_compare_prio(res_t *a, res_t *b) {
   175   if (a->prio < b->prio) return -1;
   175   if (a->prio < b->prio) return -1;
   176   else                   return 1;
   176   else                   return 1;
   177 }
   177 }
   178 
   178 
   179 //  get_resource(rost, resname)
   179 //  get_resource(rost, resname)
   182 // - if resname is defined, return the match or NULL
   182 // - if resname is defined, return the match or NULL
   183 // - if resname is NULL, the last resource is returned, currently
   183 // - if resname is NULL, the last resource is returned, currently
   184 //   This could change in the future, because we should return the best one
   184 //   This could change in the future, because we should return the best one
   185 //   (priority? last used? and fall back to the first resource)
   185 //   (priority? last used? and fall back to the first resource)
   186 //
   186 //
   187 static res *get_resource(roster *rost, const char *resname)
   187 static res_t *get_resource(roster_t *rost, const char *resname)
   188 {
   188 {
   189   GSList *p;
   189   GSList *p;
   190   res *r = NULL;
   190   res_t *r = NULL;
   191 
   191 
   192   for (p = rost->resource; p; p = g_slist_next(p)) {
   192   for (p = rost->resource; p; p = g_slist_next(p)) {
   193     r = p->data;
   193     r = p->data;
   194     if (resname && !strcmp(r->name, resname))
   194     if (resname && !strcmp(r->name, resname))
   195       return r;
   195       return r;
   204 //  get_or_add_resource(rost, resname, priority)
   204 //  get_or_add_resource(rost, resname, priority)
   205 // - if there is a "resname" resource in rost's resources, return a pointer
   205 // - if there is a "resname" resource in rost's resources, return a pointer
   206 //   on this resource
   206 //   on this resource
   207 // - if not, add the resource, set the name, and return a pointer on this
   207 // - if not, add the resource, set the name, and return a pointer on this
   208 //   new resource
   208 //   new resource
   209 static res *get_or_add_resource(roster *rost, const char *resname, gchar prio)
   209 static res_t *get_or_add_resource(roster_t *rost, const char *resname, gchar prio)
   210 {
   210 {
   211   GSList *p;
   211   GSList *p;
   212   res *nres;
   212   res_t *nres;
   213 
   213 
   214   if (!resname) return NULL;
   214   if (!resname) return NULL;
   215 
   215 
   216   for (p = rost->resource; p; p = g_slist_next(p)) {
   216   for (p = rost->resource; p; p = g_slist_next(p)) {
   217     res *r = p->data;
   217     res_t *r = p->data;
   218     if (!strcmp(r->name, resname)) {
   218     if (!strcmp(r->name, resname)) {
   219       if (prio != r->prio) {
   219       if (prio != r->prio) {
   220         r->prio = prio;
   220         r->prio = prio;
   221         rost->resource = g_slist_sort(rost->resource,
   221         rost->resource = g_slist_sort(rost->resource,
   222                                       (GCompareFunc)&resource_compare_prio);
   222                                       (GCompareFunc)&resource_compare_prio);
   224       return r;
   224       return r;
   225     }
   225     }
   226   }
   226   }
   227 
   227 
   228   // Resource not found
   228   // Resource not found
   229   nres = g_new0(res, 1);
   229   nres = g_new0(res_t, 1);
   230   nres->name = g_strdup(resname);
   230   nres->name = g_strdup(resname);
   231   nres->prio = prio;
   231   nres->prio = prio;
   232   rost->resource = g_slist_insert_sorted(rost->resource, nres,
   232   rost->resource = g_slist_insert_sorted(rost->resource, nres,
   233                                          (GCompareFunc)&resource_compare_prio);
   233                                          (GCompareFunc)&resource_compare_prio);
   234   return nres;
   234   return nres;
   235 }
   235 }
   236 
   236 
   237 static void del_resource(roster *rost, const char *resname)
   237 static void del_resource(roster_t *rost, const char *resname)
   238 {
   238 {
   239   GSList *p;
   239   GSList *p;
   240   GSList *p_res_elt = NULL;
   240   GSList *p_res_elt = NULL;
   241   res *p_res;
   241   res_t *p_res;
   242 
   242 
   243   if (!resname) return;
   243   if (!resname) return;
   244 
   244 
   245   for (p = rost->resource; p; p = g_slist_next(p)) {
   245   for (p = rost->resource; p; p = g_slist_next(p)) {
   246     res *r = p->data;
   246     res_t *r = p->data;
   247     if (!strcmp(r->name, resname))
   247     if (!strcmp(r->name, resname))
   248       p_res_elt = p;
   248       p_res_elt = p;
   249   }
   249   }
   250 
   250 
   251   if (!p_res_elt) return;   // Resource not found
   251   if (!p_res_elt) return;   // Resource not found
   269 }
   269 }
   270 
   270 
   271 
   271 
   272 /* ### Roster functions ### */
   272 /* ### Roster functions ### */
   273 
   273 
   274 static inline void free_roster_user_data(roster *roster_usr)
   274 static inline void free_roster_user_data(roster_t *roster_usr)
   275 {
   275 {
   276   if (!roster_usr)
   276   if (!roster_usr)
   277     return;
   277     return;
   278   g_free((gchar*)roster_usr->jid);
   278   g_free((gchar*)roster_usr->jid);
   279   //g_free((gchar*)roster_usr->active_resource);
   279   //g_free((gchar*)roster_usr->active_resource);
   284   free_all_resources(&roster_usr->resource);
   284   free_all_resources(&roster_usr->resource);
   285   g_free(roster_usr);
   285   g_free(roster_usr);
   286 }
   286 }
   287 
   287 
   288 // Comparison function used to search in the roster (compares jids and types)
   288 // Comparison function used to search in the roster (compares jids and types)
   289 static gint roster_compare_jid_type(roster *a, roster *b) {
   289 static gint roster_compare_jid_type(roster_t *a, roster_t *b) {
   290   if (! (a->type & b->type))
   290   if (! (a->type & b->type))
   291     return -1; // arbitrary (but should be != 0, of course)
   291     return -1; // arbitrary (but should be != 0, of course)
   292   return strcasecmp(a->jid, b->jid);
   292   return strcasecmp(a->jid, b->jid);
   293 }
   293 }
   294 
   294 
   295 // Comparison function used to search in the roster (compares names and types)
   295 // Comparison function used to search in the roster (compares names and types)
   296 static gint roster_compare_name_type(roster *a, roster *b) {
   296 static gint roster_compare_name_type(roster_t *a, roster_t *b) {
   297   if (! (a->type & b->type))
   297   if (! (a->type & b->type))
   298     return -1; // arbitrary (but should be != 0, of course)
   298     return -1; // arbitrary (but should be != 0, of course)
   299   return strcmp(a->name, b->name);
   299   return strcmp(a->name, b->name);
   300 }
   300 }
   301 
   301 
   302 // Comparison function used to sort the roster (by name)
   302 // Comparison function used to sort the roster (by name)
   303 static gint roster_compare_name(roster *a, roster *b) {
   303 static gint roster_compare_name(roster_t *a, roster_t *b) {
   304   return strcmp(a->name, b->name);
   304   return strcmp(a->name, b->name);
   305 }
   305 }
   306 
   306 
   307 // Finds a roster element (user, group, agent...), by jid or name
   307 // Finds a roster element (user, group, agent...), by jid or name
   308 // If roster_type is 0, returns match of any type.
   308 // If roster_type is 0, returns match of any type.
   309 // Returns the roster GSList element, or NULL if jid/name not found
   309 // Returns the roster GSList element, or NULL if jid/name not found
   310 GSList *roster_find(const char *jidname, enum findwhat type, guint roster_type)
   310 GSList *roster_find(const char *jidname, enum findwhat type, guint roster_type)
   311 {
   311 {
   312   GSList *sl_roster_elt = groups;
   312   GSList *sl_roster_elt = groups;
   313   GSList *resource;
   313   GSList *resource;
   314   roster sample;
   314   roster_t sample;
   315   GCompareFunc comp;
   315   GCompareFunc comp;
   316 
   316 
   317   if (!jidname) return NULL;
   317   if (!jidname) return NULL;
   318 
   318 
   319   if (!roster_type)
   319   if (!roster_type)
   329     comp = (GCompareFunc)&roster_compare_name_type;
   329     comp = (GCompareFunc)&roster_compare_name_type;
   330   } else
   330   } else
   331     return NULL;    // Should not happen...
   331     return NULL;    // Should not happen...
   332 
   332 
   333   while (sl_roster_elt) {
   333   while (sl_roster_elt) {
   334     roster *roster_elt = (roster*)sl_roster_elt->data;
   334     roster_t *roster_elt = (roster_t *)sl_roster_elt->data;
   335     if (roster_type & ROSTER_TYPE_GROUP) {
   335     if (roster_type & ROSTER_TYPE_GROUP) {
   336       if ((type == namesearch) && !strcmp(jidname, roster_elt->name))
   336       if ((type == namesearch) && !strcmp(jidname, roster_elt->name))
   337         return sl_roster_elt;
   337         return sl_roster_elt;
   338     }
   338     }
   339     resource = g_slist_find_custom(roster_elt->list, &sample, comp);
   339     resource = g_slist_find_custom(roster_elt->list, &sample, comp);
   344 }
   344 }
   345 
   345 
   346 // Returns pointer to new group, or existing group with that name
   346 // Returns pointer to new group, or existing group with that name
   347 GSList *roster_add_group(const char *name)
   347 GSList *roster_add_group(const char *name)
   348 {
   348 {
   349   roster *roster_grp;
   349   roster_t *roster_grp;
   350   GSList *p_group;
   350   GSList *p_group;
   351 
   351 
   352   // #1 Check name doesn't already exist
   352   // #1 Check name doesn't already exist
   353   p_group = roster_find(name, namesearch, ROSTER_TYPE_GROUP);
   353   p_group = roster_find(name, namesearch, ROSTER_TYPE_GROUP);
   354   if (!p_group) {
   354   if (!p_group) {
   355     // #2 Create the group node
   355     // #2 Create the group node
   356     roster_grp = g_new0(roster, 1);
   356     roster_grp = g_new0(roster_t, 1);
   357     roster_grp->name = g_strdup(name);
   357     roster_grp->name = g_strdup(name);
   358     roster_grp->type = ROSTER_TYPE_GROUP;
   358     roster_grp->type = ROSTER_TYPE_GROUP;
   359     // #3 Insert (sorted)
   359     // #3 Insert (sorted)
   360     groups = g_slist_insert_sorted(groups, roster_grp,
   360     groups = g_slist_insert_sorted(groups, roster_grp,
   361             (GCompareFunc)&roster_compare_name);
   361             (GCompareFunc)&roster_compare_name);
   363   }
   363   }
   364   return p_group;
   364   return p_group;
   365 }
   365 }
   366 
   366 
   367 // Comparison function used to sort the unread list by ui (attn) priority
   367 // Comparison function used to sort the unread list by ui (attn) priority
   368 static gint _roster_compare_uiprio(roster *a, roster *b) {
   368 static gint _roster_compare_uiprio(roster_t *a, roster_t *b) {
   369   return (b->ui_prio - a->ui_prio);
   369   return (b->ui_prio - a->ui_prio);
   370 }
   370 }
   371 
   371 
   372 // Returns a pointer to the new user, or existing user with that name
   372 // Returns a pointer to the new user, or existing user with that name
   373 // Note: if onserver is -1, the flag won't be changed.
   373 // Note: if onserver is -1, the flag won't be changed.
   374 GSList *roster_add_user(const char *jid, const char *name, const char *group,
   374 GSList *roster_add_user(const char *jid, const char *name, const char *group,
   375                         guint type, enum subscr esub, gint onserver)
   375                         guint type, enum subscr esub, gint onserver)
   376 {
   376 {
   377   roster *roster_usr;
   377   roster_t *roster_usr;
   378   roster *my_group;
   378   roster_t *my_group;
   379   GSList *slist;
   379   GSList *slist;
   380 
   380 
   381   if ((type != ROSTER_TYPE_USER) &&
   381   if ((type != ROSTER_TYPE_USER) &&
   382       (type != ROSTER_TYPE_ROOM) &&
   382       (type != ROSTER_TYPE_ROOM) &&
   383       (type != ROSTER_TYPE_AGENT)) {
   383       (type != ROSTER_TYPE_AGENT)) {
   398     if (onserver >= 0)
   398     if (onserver >= 0)
   399       buddy_setonserverflag(slist->data, onserver);
   399       buddy_setonserverflag(slist->data, onserver);
   400     if (name)
   400     if (name)
   401       buddy_setname(slist->data, (char*)name);
   401       buddy_setname(slist->data, (char*)name);
   402     // Let's check if the group name has changed
   402     // Let's check if the group name has changed
   403     oldgroupname = ((roster*)((GSList*)roster_usr->list)->data)->name;
   403     oldgroupname = ((roster_t *)((GSList*)roster_usr->list)->data)->name;
   404     if (group && strcmp(oldgroupname, group)) {
   404     if (group && strcmp(oldgroupname, group)) {
   405       buddy_setgroup(slist->data, (char*)group);
   405       buddy_setgroup(slist->data, (char*)group);
   406       // Note: buddy_setgroup() updates the user lists so we cannot
   406       // Note: buddy_setgroup() updates the user lists so we cannot
   407       // use slist anymore.
   407       // use slist anymore.
   408       return roster_find(jid, jidsearch, 0);
   408       return roster_find(jid, jidsearch, 0);
   410     return slist;
   410     return slist;
   411   }
   411   }
   412   // #2 add group if necessary
   412   // #2 add group if necessary
   413   slist = roster_add_group(group);
   413   slist = roster_add_group(group);
   414   if (!slist) return NULL;
   414   if (!slist) return NULL;
   415   my_group = (roster*)slist->data;
   415   my_group = (roster_t *)slist->data;
   416   // #3 Create user node
   416   // #3 Create user node
   417   roster_usr = g_new0(roster, 1);
   417   roster_usr = g_new0(roster_t, 1);
   418   roster_usr->jid   = g_strdup(jid);
   418   roster_usr->jid   = g_strdup(jid);
   419   if (name) {
   419   if (name) {
   420     roster_usr->name  = g_strdup(name);
   420     roster_usr->name  = g_strdup(name);
   421   } else {
   421   } else {
   422     gchar *p, *str = g_strdup(jid);
   422     gchar *p, *str = g_strdup(jid);
   446 // Removes user (jid) from roster, frees allocated memory
   446 // Removes user (jid) from roster, frees allocated memory
   447 void roster_del_user(const char *jid)
   447 void roster_del_user(const char *jid)
   448 {
   448 {
   449   GSList *sl_user, *sl_group;
   449   GSList *sl_user, *sl_group;
   450   GSList **sl_group_listptr;
   450   GSList **sl_group_listptr;
   451   roster *roster_usr;
   451   roster_t *roster_usr;
   452   GSList *node;
   452   GSList *node;
   453 
   453 
   454   sl_user = roster_find(jid, jidsearch,
   454   sl_user = roster_find(jid, jidsearch,
   455                         ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM);
   455                         ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM);
   456   if (sl_user == NULL)
   456   if (sl_user == NULL)
   457     return;
   457     return;
   458   roster_usr = (roster*)sl_user->data;
   458   roster_usr = (roster_t *)sl_user->data;
   459 
   459 
   460   // Remove (if present) from unread messages list
   460   // Remove (if present) from unread messages list
   461   node = g_slist_find(unread_list, roster_usr);
   461   node = g_slist_find(unread_list, roster_usr);
   462   if (node) unread_list = g_slist_delete_link(unread_list, node);
   462   if (node) unread_list = g_slist_delete_link(unread_list, node);
   463   // If there is a pending unread message, keep track of it
   463   // If there is a pending unread message, keep track of it
   468 
   468 
   469   // Let's free roster_usr memory (jid, name, status message...)
   469   // Let's free roster_usr memory (jid, name, status message...)
   470   free_roster_user_data(roster_usr);
   470   free_roster_user_data(roster_usr);
   471 
   471 
   472   // That's a little complex, we need to dereference twice
   472   // That's a little complex, we need to dereference twice
   473   sl_group_listptr = &((roster*)(sl_group->data))->list;
   473   sl_group_listptr = &((roster_t *)(sl_group->data))->list;
   474   *sl_group_listptr = g_slist_delete_link(*sl_group_listptr, sl_user);
   474   *sl_group_listptr = g_slist_delete_link(*sl_group_listptr, sl_user);
   475 
   475 
   476   // We need to rebuild the list
   476   // We need to rebuild the list
   477   if (current_buddy)
   477   if (current_buddy)
   478     buddylist_defer_build();
   478     buddylist_defer_build();
   492     unread_list = NULL;
   492     unread_list = NULL;
   493   }
   493   }
   494 
   494 
   495   // Walk through groups
   495   // Walk through groups
   496   while (sl_grp) {
   496   while (sl_grp) {
   497     roster *roster_grp = (roster*)sl_grp->data;
   497     roster_t *roster_grp = (roster_t *)sl_grp->data;
   498     GSList *sl_usr = roster_grp->list;
   498     GSList *sl_usr = roster_grp->list;
   499     // Walk through this group users
   499     // Walk through this group users
   500     while (sl_usr) {
   500     while (sl_usr) {
   501       roster *roster_usr = (roster*)sl_usr->data;
   501       roster_t *roster_usr = (roster_t *)sl_usr->data;
   502       // If there is a pending unread message, keep track of it
   502       // If there is a pending unread message, keep track of it
   503       if (roster_usr->flags & ROSTER_FLAG_MSG)
   503       if (roster_usr->flags & ROSTER_FLAG_MSG)
   504         unread_jid_add(roster_usr->jid);
   504         unread_jid_add(roster_usr->jid);
   505       // Free roster_usr data (jid, name, status message...)
   505       // Free roster_usr data (jid, name, status message...)
   506       free_roster_user_data(roster_usr);
   506       free_roster_user_data(roster_usr);
   532                       time_t status_time,
   532                       time_t status_time,
   533                       enum imrole role, enum imaffiliation affil,
   533                       enum imrole role, enum imaffiliation affil,
   534                       const char *realjid)
   534                       const char *realjid)
   535 {
   535 {
   536   GSList *sl_user;
   536   GSList *sl_user;
   537   roster *roster_usr;
   537   roster_t *roster_usr;
   538   res *p_res;
   538   res_t *p_res;
   539 
   539 
   540   sl_user = roster_find(jid, jidsearch,
   540   sl_user = roster_find(jid, jidsearch,
   541                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   541                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   542   // If we can't find it, we add it
   542   // If we can't find it, we add it
   543   if (sl_user == NULL)
   543   if (sl_user == NULL)
   545                               sub_none, -1);
   545                               sub_none, -1);
   546 
   546 
   547   // If there is no resource name, we can leave now
   547   // If there is no resource name, we can leave now
   548   if (!resname) return;
   548   if (!resname) return;
   549 
   549 
   550   roster_usr = (roster*)sl_user->data;
   550   roster_usr = (roster_t *)sl_user->data;
   551 
   551 
   552   // New or updated resource
   552   // New or updated resource
   553   p_res = get_or_add_resource(roster_usr, resname, prio);
   553   p_res = get_or_add_resource(roster_usr, resname, prio);
   554   p_res->status = bstat;
   554   p_res->status = bstat;
   555   if (p_res->status_msg) {
   555   if (p_res->status_msg) {
   582 //  roster_setflags()
   582 //  roster_setflags()
   583 // Set one or several flags to value (TRUE/FALSE)
   583 // Set one or several flags to value (TRUE/FALSE)
   584 void roster_setflags(const char *jid, guint flags, guint value)
   584 void roster_setflags(const char *jid, guint flags, guint value)
   585 {
   585 {
   586   GSList *sl_user;
   586   GSList *sl_user;
   587   roster *roster_usr;
   587   roster_t *roster_usr;
   588 
   588 
   589   sl_user = roster_find(jid, jidsearch,
   589   sl_user = roster_find(jid, jidsearch,
   590                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   590                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   591   if (sl_user == NULL)
   591   if (sl_user == NULL)
   592     return;
   592     return;
   593 
   593 
   594   roster_usr = (roster*)sl_user->data;
   594   roster_usr = (roster_t *)sl_user->data;
   595   if (value)
   595   if (value)
   596     roster_usr->flags |= flags;
   596     roster_usr->flags |= flags;
   597   else
   597   else
   598     roster_usr->flags &= ~flags;
   598     roster_usr->flags &= ~flags;
   599 }
   599 }
   633 // It will update the buddy's group message flag.
   633 // It will update the buddy's group message flag.
   634 // Update the unread messages list too.
   634 // Update the unread messages list too.
   635 void roster_msg_setflag(const char *jid, guint special, guint value)
   635 void roster_msg_setflag(const char *jid, guint special, guint value)
   636 {
   636 {
   637   GSList *sl_user;
   637   GSList *sl_user;
   638   roster *roster_usr, *roster_grp;
   638   roster_t *roster_usr, *roster_grp;
   639   int new_roster_item = FALSE;
   639   int new_roster_item = FALSE;
   640   guint unread_list_modified = FALSE;
   640   guint unread_list_modified = FALSE;
   641 
   641 
   642   if (special) {
   642   if (special) {
   643     //sl_user = roster_find(jid, namesearch, ROSTER_TYPE_SPECIAL);
   643     //sl_user = roster_find(jid, namesearch, ROSTER_TYPE_SPECIAL);
   644     //if (!sl_user) return;
   644     //if (!sl_user) return;
   645     //roster_usr = (roster*)sl_user->data;
   645     //roster_usr = (roster_t *)sl_user->data;
   646     roster_usr = &roster_special;
   646     roster_usr = &roster_special;
   647     if (value) {
   647     if (value) {
   648       if (!(roster_usr->flags & ROSTER_FLAG_MSG))
   648       if (!(roster_usr->flags & ROSTER_FLAG_MSG))
   649         unread_list_modified = TRUE;
   649         unread_list_modified = TRUE;
   650       roster_usr->flags |= ROSTER_FLAG_MSG;
   650       roster_usr->flags |= ROSTER_FLAG_MSG;
   672   if (sl_user == NULL) {
   672   if (sl_user == NULL) {
   673     sl_user = roster_add_user(jid, NULL, NULL, ROSTER_TYPE_USER, sub_none, -1);
   673     sl_user = roster_add_user(jid, NULL, NULL, ROSTER_TYPE_USER, sub_none, -1);
   674     new_roster_item = TRUE;
   674     new_roster_item = TRUE;
   675   }
   675   }
   676 
   676 
   677   roster_usr = (roster*)sl_user->data;
   677   roster_usr = (roster_t *)sl_user->data;
   678   roster_grp = (roster*)roster_usr->list->data;
   678   roster_grp = (roster_t *)roster_usr->list->data;
   679   if (value) {
   679   if (value) {
   680     if (!(roster_usr->flags & ROSTER_FLAG_MSG))
   680     if (!(roster_usr->flags & ROSTER_FLAG_MSG))
   681       unread_list_modified = TRUE;
   681       unread_list_modified = TRUE;
   682     // Message flag is TRUE.  This is easy, we just have to set both flags
   682     // Message flag is TRUE.  This is easy, we just have to set both flags
   683     // to TRUE...
   683     // to TRUE...
   703     // if one is flagged, then the group will be flagged.
   703     // if one is flagged, then the group will be flagged.
   704     // I will re-use sl_user and roster_usr here, as they aren't used
   704     // I will re-use sl_user and roster_usr here, as they aren't used
   705     // anymore.
   705     // anymore.
   706     sl_user = roster_grp->list;
   706     sl_user = roster_grp->list;
   707     while (sl_user) {
   707     while (sl_user) {
   708       roster_usr = (roster*)sl_user->data;
   708       roster_usr = (roster_t *)sl_user->data;
   709       if (roster_usr->flags & ROSTER_FLAG_MSG) {
   709       if (roster_usr->flags & ROSTER_FLAG_MSG) {
   710         msg = TRUE;
   710         msg = TRUE;
   711         break;
   711         break;
   712       }
   712       }
   713       sl_user = g_slist_next(sl_user);
   713       sl_user = g_slist_next(sl_user);
   734 // If increment is true, increment the unread messages count for jid by 1.
   734 // If increment is true, increment the unread messages count for jid by 1.
   735 // If increment is false, reset the unread messages count for jid to 0.
   735 // If increment is false, reset the unread messages count for jid to 0.
   736 void roster_msg_update_unread(const char *jid, gboolean increment)
   736 void roster_msg_update_unread(const char *jid, gboolean increment)
   737 {
   737 {
   738   GSList *sl_user;
   738   GSList *sl_user;
   739   roster *roster_usr;
   739   roster_t *roster_usr;
   740 
   740 
   741   sl_user = roster_find(jid, jidsearch,
   741   sl_user = roster_find(jid, jidsearch,
   742                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   742                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   743   if (!sl_user)
   743   if (!sl_user)
   744     return;
   744     return;
   745 
   745 
   746   roster_usr = (roster*)sl_user->data;
   746   roster_usr = (roster_t *)sl_user->data;
   747 
   747 
   748   if (increment)
   748   if (increment)
   749     roster_usr->unread++;
   749     roster_usr->unread++;
   750   else
   750   else
   751     roster_usr->unread = 0;
   751     roster_usr->unread = 0;
   756 // Note that this function doesn't create the roster item if it doesn't exist.
   756 // Note that this function doesn't create the roster item if it doesn't exist.
   757 void roster_setuiprio(const char *jid, guint special, guint value,
   757 void roster_setuiprio(const char *jid, guint special, guint value,
   758                       enum setuiprio_ops action)
   758                       enum setuiprio_ops action)
   759 {
   759 {
   760   guint oldval, newval;
   760   guint oldval, newval;
   761   roster *roster_usr;
   761   roster_t *roster_usr;
   762 
   762 
   763   if (special) {
   763   if (special) {
   764     roster_usr = &roster_special;
   764     roster_usr = &roster_special;
   765   } else {
   765   } else {
   766     GSList *sl_user = roster_find(jid, jidsearch,
   766     GSList *sl_user = roster_find(jid, jidsearch,
   767                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   767                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   768     if (!sl_user)
   768     if (!sl_user)
   769       return;
   769       return;
   770 
   770 
   771     roster_usr = (roster*)sl_user->data;
   771     roster_usr = (roster_t *)sl_user->data;
   772   }
   772   }
   773   oldval = roster_usr->ui_prio;
   773   oldval = roster_usr->ui_prio;
   774 
   774 
   775   if (action == prio_max)
   775   if (action == prio_max)
   776     newval = MAX(oldval, value);
   776     newval = MAX(oldval, value);
   785   roster_unread_check();
   785   roster_unread_check();
   786 }
   786 }
   787 
   787 
   788 guint roster_getuiprio(const char *jid, guint special)
   788 guint roster_getuiprio(const char *jid, guint special)
   789 {
   789 {
   790   roster *roster_usr;
   790   roster_t *roster_usr;
   791   GSList *sl_user;
   791   GSList *sl_user;
   792 
   792 
   793   if (special) {
   793   if (special) {
   794     roster_usr = &roster_special;
   794     roster_usr = &roster_special;
   795     return roster_usr->ui_prio;
   795     return roster_usr->ui_prio;
   797 
   797 
   798   sl_user = roster_find(jid, jidsearch,
   798   sl_user = roster_find(jid, jidsearch,
   799                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   799                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   800   if (!sl_user)
   800   if (!sl_user)
   801     return 0;
   801     return 0;
   802   roster_usr = (roster*)sl_user->data;
   802   roster_usr = (roster_t *)sl_user->data;
   803   return roster_usr->ui_prio;
   803   return roster_usr->ui_prio;
   804 }
   804 }
   805 
   805 
   806 const char *roster_getname(const char *jid)
   806 const char *roster_getname(const char *jid)
   807 {
   807 {
   808   GSList *sl_user;
   808   GSList *sl_user;
   809   roster *roster_usr;
   809   roster_t *roster_usr;
   810 
   810 
   811   sl_user = roster_find(jid, jidsearch,
   811   sl_user = roster_find(jid, jidsearch,
   812                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   812                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   813   if (sl_user == NULL)
   813   if (sl_user == NULL)
   814     return NULL; // Not in the roster...
   814     return NULL; // Not in the roster...
   815 
   815 
   816   roster_usr = (roster*)sl_user->data;
   816   roster_usr = (roster_t *)sl_user->data;
   817   return roster_usr->name;
   817   return roster_usr->name;
   818 }
   818 }
   819 
   819 
   820 const char *roster_getnickname(const char *jid)
   820 const char *roster_getnickname(const char *jid)
   821 {
   821 {
   822   GSList *sl_user;
   822   GSList *sl_user;
   823   roster *roster_usr;
   823   roster_t *roster_usr;
   824 
   824 
   825   sl_user = roster_find(jid, jidsearch,
   825   sl_user = roster_find(jid, jidsearch,
   826                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   826                         ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
   827   if (sl_user == NULL)
   827   if (sl_user == NULL)
   828     return NULL; // Not in the roster...
   828     return NULL; // Not in the roster...
   829 
   829 
   830   roster_usr = (roster*)sl_user->data;
   830   roster_usr = (roster_t *)sl_user->data;
   831   return roster_usr->nickname;
   831   return roster_usr->nickname;
   832 }
   832 }
   833 
   833 
   834 void roster_settype(const char *jid, guint type)
   834 void roster_settype(const char *jid, guint type)
   835 {
   835 {
   836   GSList *sl_user;
   836   GSList *sl_user;
   837   roster *roster_usr;
   837   roster_t *roster_usr;
   838 
   838 
   839   if ((sl_user = roster_find(jid, jidsearch, 0)) == NULL)
   839   if ((sl_user = roster_find(jid, jidsearch, 0)) == NULL)
   840     return;
   840     return;
   841 
   841 
   842   roster_usr = (roster*)sl_user->data;
   842   roster_usr = (roster_t *)sl_user->data;
   843   roster_usr->type = type;
   843   roster_usr->type = type;
   844 }
   844 }
   845 
   845 
   846 enum imstatus roster_getstatus(const char *jid, const char *resname)
   846 enum imstatus roster_getstatus(const char *jid, const char *resname)
   847 {
   847 {
   848   GSList *sl_user;
   848   GSList *sl_user;
   849   roster *roster_usr;
   849   roster_t *roster_usr;
   850   res *p_res;
   850   res_t *p_res;
   851 
   851 
   852   sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
   852   sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
   853   if (sl_user == NULL)
   853   if (sl_user == NULL)
   854     return offline; // Not in the roster, anyway...
   854     return offline; // Not in the roster, anyway...
   855 
   855 
   856   roster_usr = (roster*)sl_user->data;
   856   roster_usr = (roster_t *)sl_user->data;
   857   p_res = get_resource(roster_usr, resname);
   857   p_res = get_resource(roster_usr, resname);
   858   if (p_res)
   858   if (p_res)
   859     return p_res->status;
   859     return p_res->status;
   860   return offline;
   860   return offline;
   861 }
   861 }
   862 
   862 
   863 const char *roster_getstatusmsg(const char *jid, const char *resname)
   863 const char *roster_getstatusmsg(const char *jid, const char *resname)
   864 {
   864 {
   865   GSList *sl_user;
   865   GSList *sl_user;
   866   roster *roster_usr;
   866   roster_t *roster_usr;
   867   res *p_res;
   867   res_t *p_res;
   868 
   868 
   869   sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
   869   sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
   870   if (sl_user == NULL)
   870   if (sl_user == NULL)
   871     return NULL; // Not in the roster, anyway...
   871     return NULL; // Not in the roster, anyway...
   872 
   872 
   873   roster_usr = (roster*)sl_user->data;
   873   roster_usr = (roster_t *)sl_user->data;
   874   p_res = get_resource(roster_usr, resname);
   874   p_res = get_resource(roster_usr, resname);
   875   if (p_res)
   875   if (p_res)
   876     return p_res->status_msg;
   876     return p_res->status_msg;
   877   return roster_usr->offline_status_message;
   877   return roster_usr->offline_status_message;
   878 }
   878 }
   879 
   879 
   880 char roster_getprio(const char *jid, const char *resname)
   880 char roster_getprio(const char *jid, const char *resname)
   881 {
   881 {
   882   GSList *sl_user;
   882   GSList *sl_user;
   883   roster *roster_usr;
   883   roster_t *roster_usr;
   884   res *p_res;
   884   res_t *p_res;
   885 
   885 
   886   sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
   886   sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
   887   if (sl_user == NULL)
   887   if (sl_user == NULL)
   888     return offline; // Not in the roster, anyway...
   888     return offline; // Not in the roster, anyway...
   889 
   889 
   890   roster_usr = (roster*)sl_user->data;
   890   roster_usr = (roster_t *)sl_user->data;
   891   p_res = get_resource(roster_usr, resname);
   891   p_res = get_resource(roster_usr, resname);
   892   if (p_res)
   892   if (p_res)
   893     return p_res->prio;
   893     return p_res->prio;
   894   return 0;
   894   return 0;
   895 }
   895 }
   896 
   896 
   897 guint roster_gettype(const char *jid)
   897 guint roster_gettype(const char *jid)
   898 {
   898 {
   899   GSList *sl_user;
   899   GSList *sl_user;
   900   roster *roster_usr;
   900   roster_t *roster_usr;
   901 
   901 
   902   if ((sl_user = roster_find(jid, jidsearch, 0)) == NULL)
   902   if ((sl_user = roster_find(jid, jidsearch, 0)) == NULL)
   903     return 0;
   903     return 0;
   904 
   904 
   905   roster_usr = (roster*)sl_user->data;
   905   roster_usr = (roster_t *)sl_user->data;
   906   return roster_usr->type;
   906   return roster_usr->type;
   907 }
   907 }
   908 
   908 
   909 guint roster_getsubscription(const char *jid)
   909 guint roster_getsubscription(const char *jid)
   910 {
   910 {
   911   GSList *sl_user;
   911   GSList *sl_user;
   912   roster *roster_usr;
   912   roster_t *roster_usr;
   913 
   913 
   914   if ((sl_user = roster_find(jid, jidsearch, 0)) == NULL)
   914   if ((sl_user = roster_find(jid, jidsearch, 0)) == NULL)
   915     return 0;
   915     return 0;
   916 
   916 
   917   roster_usr = (roster*)sl_user->data;
   917   roster_usr = (roster_t *)sl_user->data;
   918   return roster_usr->subscription;
   918   return roster_usr->subscription;
   919 }
   919 }
   920 
   920 
   921 //  roster_unsubscribed()
   921 //  roster_unsubscribed()
   922 // We have lost buddy's presence updates; this function clears the status
   922 // We have lost buddy's presence updates; this function clears the status
   923 // message, sets the buddy offline and frees the resources
   923 // message, sets the buddy offline and frees the resources
   924 void roster_unsubscribed(const char *jid)
   924 void roster_unsubscribed(const char *jid)
   925 {
   925 {
   926   GSList *sl_user;
   926   GSList *sl_user;
   927   roster *roster_usr;
   927   roster_t *roster_usr;
   928 
   928 
   929   sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
   929   sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
   930   if (sl_user == NULL)
   930   if (sl_user == NULL)
   931     return;
   931     return;
   932 
   932 
   933   roster_usr = (roster*)sl_user->data;
   933   roster_usr = (roster_t *)sl_user->data;
   934   free_all_resources(&roster_usr->resource);
   934   free_all_resources(&roster_usr->resource);
   935 }
   935 }
   936 
   936 
   937 
   937 
   938 /* ### BuddyList functions ### */
   938 /* ### BuddyList functions ### */
   982 //  buddylist_build()
   982 //  buddylist_build()
   983 // Creates the buddylist from the roster entries.
   983 // Creates the buddylist from the roster entries.
   984 void buddylist_build(void)
   984 void buddylist_build(void)
   985 {
   985 {
   986   GSList *sl_roster_elt = groups;
   986   GSList *sl_roster_elt = groups;
   987   roster *roster_elt;
   987   roster_t *roster_elt;
   988   roster *roster_current_buddy = NULL;
   988   roster_t *roster_current_buddy = NULL;
   989   roster *roster_alternate_buddy = NULL;
   989   roster_t *roster_alternate_buddy = NULL;
   990   roster *roster_last_activity_buddy = NULL;
   990   roster_t *roster_last_activity_buddy = NULL;
   991   int shrunk_group;
   991   int shrunk_group;
   992 
   992 
   993   if (_rebuild_buddylist == FALSE)
   993   if (_rebuild_buddylist == FALSE)
   994     return;
   994     return;
   995   _rebuild_buddylist = FALSE;
   995   _rebuild_buddylist = FALSE;
  1014   buddylist = g_list_append(buddylist, &roster_special);
  1014   buddylist = g_list_append(buddylist, &roster_special);
  1015 
  1015 
  1016   // Create the new list
  1016   // Create the new list
  1017   while (sl_roster_elt) {
  1017   while (sl_roster_elt) {
  1018     GSList *sl_roster_usrelt;
  1018     GSList *sl_roster_usrelt;
  1019     roster *roster_usrelt;
  1019     roster_t *roster_usrelt;
  1020     guint pending_group = TRUE;
  1020     guint pending_group = TRUE;
  1021     roster_elt = (roster*) sl_roster_elt->data;
  1021     roster_elt = (roster_t *) sl_roster_elt->data;
  1022 
  1022 
  1023     shrunk_group = roster_elt->flags & ROSTER_FLAG_HIDE;
  1023     shrunk_group = roster_elt->flags & ROSTER_FLAG_HIDE;
  1024 
  1024 
  1025     sl_roster_usrelt = roster_elt->list;
  1025     sl_roster_usrelt = roster_elt->list;
  1026     while (sl_roster_usrelt) {
  1026     while (sl_roster_usrelt) {
  1027       roster_usrelt = (roster*) sl_roster_usrelt->data;
  1027       roster_usrelt = (roster_t *) sl_roster_usrelt->data;
  1028 
  1028 
  1029       // Buddy will be added if either:
  1029       // Buddy will be added if either:
  1030       // - buddy's status matches the display_filter
  1030       // - buddy's status matches the display_filter
  1031       // - buddy has a lock (for example the buddy window is currently open)
  1031       // - buddy has a lock (for example the buddy window is currently open)
  1032       // - buddy has a pending (non-read) message
  1032       // - buddy has a pending (non-read) message
  1070 
  1070 
  1071 //  buddy_hide_group(roster, hide)
  1071 //  buddy_hide_group(roster, hide)
  1072 // "hide" values: 1=hide 0=show_all -1=invert
  1072 // "hide" values: 1=hide 0=show_all -1=invert
  1073 void buddy_hide_group(gpointer rosterdata, int hide)
  1073 void buddy_hide_group(gpointer rosterdata, int hide)
  1074 {
  1074 {
  1075   roster *roster_usr = rosterdata;
  1075   roster_t *roster_usr = rosterdata;
  1076   if (hide > 0)                     // TRUE   (hide)
  1076   if (hide > 0)                     // TRUE   (hide)
  1077     roster_usr->flags |= ROSTER_FLAG_HIDE;
  1077     roster_usr->flags |= ROSTER_FLAG_HIDE;
  1078   else if (hide < 0)                // NEG    (invert)
  1078   else if (hide < 0)                // NEG    (invert)
  1079     roster_usr->flags ^= ROSTER_FLAG_HIDE;
  1079     roster_usr->flags ^= ROSTER_FLAG_HIDE;
  1080   else                              // FALSE  (don't hide)
  1080   else                              // FALSE  (don't hide)
  1081     roster_usr->flags &= ~ROSTER_FLAG_HIDE;
  1081     roster_usr->flags &= ~ROSTER_FLAG_HIDE;
  1082 }
  1082 }
  1083 
  1083 
  1084 const char *buddy_getjid(gpointer rosterdata)
  1084 const char *buddy_getjid(gpointer rosterdata)
  1085 {
  1085 {
  1086   roster *roster_usr = rosterdata;
  1086   roster_t *roster_usr = rosterdata;
  1087   if (!rosterdata)
  1087   if (!rosterdata)
  1088     return NULL;
  1088     return NULL;
  1089   return roster_usr->jid;
  1089   return roster_usr->jid;
  1090 }
  1090 }
  1091 
  1091 
  1094 //
  1094 //
  1095 // Note: buddy_setgroup() updates the user lists.
  1095 // Note: buddy_setgroup() updates the user lists.
  1096 //
  1096 //
  1097 void buddy_setgroup(gpointer rosterdata, char *newgroupname)
  1097 void buddy_setgroup(gpointer rosterdata, char *newgroupname)
  1098 {
  1098 {
  1099   roster *roster_usr = rosterdata;
  1099   roster_t *roster_usr = rosterdata;
  1100   GSList **sl_group;
  1100   GSList **sl_group;
  1101   GSList *sl_newgroup;
  1101   GSList *sl_newgroup;
  1102   roster *my_newgroup;
  1102   roster_t *my_newgroup;
  1103 
  1103 
  1104   // A group has no group :)
  1104   // A group has no group :)
  1105   if (roster_usr->type & ROSTER_TYPE_GROUP) return;
  1105   if (roster_usr->type & ROSTER_TYPE_GROUP) return;
  1106 
  1106 
  1107   // Add newgroup if necessary
  1107   // Add newgroup if necessary
  1108   if (!newgroupname)  newgroupname = "";
  1108   if (!newgroupname)  newgroupname = "";
  1109   sl_newgroup = roster_add_group(newgroupname);
  1109   sl_newgroup = roster_add_group(newgroupname);
  1110   if (!sl_newgroup) return;
  1110   if (!sl_newgroup) return;
  1111   my_newgroup = (roster*)sl_newgroup->data;
  1111   my_newgroup = (roster_t *)sl_newgroup->data;
  1112 
  1112 
  1113   // Remove the buddy from current group
  1113   // Remove the buddy from current group
  1114   sl_group = &((roster*)((GSList*)roster_usr->list)->data)->list;
  1114   sl_group = &((roster_t *)((GSList*)roster_usr->list)->data)->list;
  1115   *sl_group = g_slist_remove(*sl_group, rosterdata);
  1115   *sl_group = g_slist_remove(*sl_group, rosterdata);
  1116 
  1116 
  1117   // Remove old group if it is empty
  1117   // Remove old group if it is empty
  1118   if (!*sl_group) {
  1118   if (!*sl_group) {
  1119     roster *roster_grp = (roster*)((GSList*)roster_usr->list)->data;
  1119     roster_t *roster_grp = (roster_t *)((GSList*)roster_usr->list)->data;
  1120     g_free((gchar*)roster_grp->jid);
  1120     g_free((gchar*)roster_grp->jid);
  1121     g_free((gchar*)roster_grp->name);
  1121     g_free((gchar*)roster_grp->name);
  1122     g_free(roster_grp);
  1122     g_free(roster_grp);
  1123     groups = g_slist_remove(groups, roster_grp);
  1123     groups = g_slist_remove(groups, roster_grp);
  1124   }
  1124   }
  1131   buddylist_defer_build();
  1131   buddylist_defer_build();
  1132 }
  1132 }
  1133 
  1133 
  1134 void buddy_setname(gpointer rosterdata, char *newname)
  1134 void buddy_setname(gpointer rosterdata, char *newname)
  1135 {
  1135 {
  1136   roster *roster_usr = rosterdata;
  1136   roster_t *roster_usr = rosterdata;
  1137   GSList **sl_group;
  1137   GSList **sl_group;
  1138 
  1138 
  1139   // TODO For groups, we need to check for unicity
  1139   // TODO For groups, we need to check for unicity
  1140   // However, renaming a group boils down to moving all its buddies to
  1140   // However, renaming a group boils down to moving all its buddies to
  1141   // another group, so calling this function is not really necessary...
  1141   // another group, so calling this function is not really necessary...
  1147   }
  1147   }
  1148   if (newname)
  1148   if (newname)
  1149     roster_usr->name = g_strdup(newname);
  1149     roster_usr->name = g_strdup(newname);
  1150 
  1150 
  1151   // We need to resort the group list
  1151   // We need to resort the group list
  1152   sl_group = &((roster*)((GSList*)roster_usr->list)->data)->list;
  1152   sl_group = &((roster_t *)((GSList*)roster_usr->list)->data)->list;
  1153   *sl_group = g_slist_sort(*sl_group, (GCompareFunc)&roster_compare_name);
  1153   *sl_group = g_slist_sort(*sl_group, (GCompareFunc)&roster_compare_name);
  1154 
  1154 
  1155   buddylist_defer_build();
  1155   buddylist_defer_build();
  1156 }
  1156 }
  1157 
  1157 
  1158 const char *buddy_getname(gpointer rosterdata)
  1158 const char *buddy_getname(gpointer rosterdata)
  1159 {
  1159 {
  1160   roster *roster_usr = rosterdata;
  1160   roster_t *roster_usr = rosterdata;
  1161   return roster_usr->name;
  1161   return roster_usr->name;
  1162 }
  1162 }
  1163 
  1163 
  1164 //  buddy_setnickname(buddy, newnickname)
  1164 //  buddy_setnickname(buddy, newnickname)
  1165 // Only for chatrooms
  1165 // Only for chatrooms
  1166 void buddy_setnickname(gpointer rosterdata, const char *newname)
  1166 void buddy_setnickname(gpointer rosterdata, const char *newname)
  1167 {
  1167 {
  1168   roster *roster_usr = rosterdata;
  1168   roster_t *roster_usr = rosterdata;
  1169 
  1169 
  1170   if (!(roster_usr->type & ROSTER_TYPE_ROOM)) return; // XXX Error message?
  1170   if (!(roster_usr->type & ROSTER_TYPE_ROOM)) return; // XXX Error message?
  1171 
  1171 
  1172   if (roster_usr->nickname) {
  1172   if (roster_usr->nickname) {
  1173     g_free((gchar*)roster_usr->nickname);
  1173     g_free((gchar*)roster_usr->nickname);
  1177     roster_usr->nickname = g_strdup(newname);
  1177     roster_usr->nickname = g_strdup(newname);
  1178 }
  1178 }
  1179 
  1179 
  1180 const char *buddy_getnickname(gpointer rosterdata)
  1180 const char *buddy_getnickname(gpointer rosterdata)
  1181 {
  1181 {
  1182   roster *roster_usr = rosterdata;
  1182   roster_t *roster_usr = rosterdata;
  1183   return roster_usr->nickname;
  1183   return roster_usr->nickname;
  1184 }
  1184 }
  1185 
  1185 
  1186 //  buddy_setinsideroom(buddy, inside)
  1186 //  buddy_setinsideroom(buddy, inside)
  1187 // Only for chatrooms
  1187 // Only for chatrooms
  1188 void buddy_setinsideroom(gpointer rosterdata, guint inside)
  1188 void buddy_setinsideroom(gpointer rosterdata, guint inside)
  1189 {
  1189 {
  1190   roster *roster_usr = rosterdata;
  1190   roster_t *roster_usr = rosterdata;
  1191 
  1191 
  1192   if (!(roster_usr->type & ROSTER_TYPE_ROOM)) return;
  1192   if (!(roster_usr->type & ROSTER_TYPE_ROOM)) return;
  1193 
  1193 
  1194   roster_usr->inside_room = inside;
  1194   roster_usr->inside_room = inside;
  1195 }
  1195 }
  1196 
  1196 
  1197 guint buddy_getinsideroom(gpointer rosterdata)
  1197 guint buddy_getinsideroom(gpointer rosterdata)
  1198 {
  1198 {
  1199   roster *roster_usr = rosterdata;
  1199   roster_t *roster_usr = rosterdata;
  1200   return roster_usr->inside_room;
  1200   return roster_usr->inside_room;
  1201 }
  1201 }
  1202 
  1202 
  1203 //  buddy_settopic(buddy, newtopic)
  1203 //  buddy_settopic(buddy, newtopic)
  1204 // Only for chatrooms
  1204 // Only for chatrooms
  1205 void buddy_settopic(gpointer rosterdata, const char *newtopic)
  1205 void buddy_settopic(gpointer rosterdata, const char *newtopic)
  1206 {
  1206 {
  1207   roster *roster_usr = rosterdata;
  1207   roster_t *roster_usr = rosterdata;
  1208 
  1208 
  1209   if (!(roster_usr->type & ROSTER_TYPE_ROOM)) return;
  1209   if (!(roster_usr->type & ROSTER_TYPE_ROOM)) return;
  1210 
  1210 
  1211   if (roster_usr->topic) {
  1211   if (roster_usr->topic) {
  1212     g_free((gchar*)roster_usr->topic);
  1212     g_free((gchar*)roster_usr->topic);
  1216     roster_usr->topic = g_strdup(newtopic);
  1216     roster_usr->topic = g_strdup(newtopic);
  1217 }
  1217 }
  1218 
  1218 
  1219 const char *buddy_gettopic(gpointer rosterdata)
  1219 const char *buddy_gettopic(gpointer rosterdata)
  1220 {
  1220 {
  1221   roster *roster_usr = rosterdata;
  1221   roster_t *roster_usr = rosterdata;
  1222   return roster_usr->topic;
  1222   return roster_usr->topic;
  1223 }
  1223 }
  1224 
  1224 
  1225 void buddy_setprintstatus(gpointer rosterdata, enum room_printstatus pstatus)
  1225 void buddy_setprintstatus(gpointer rosterdata, enum room_printstatus pstatus)
  1226 {
  1226 {
  1227   roster *roster_usr = rosterdata;
  1227   roster_t *roster_usr = rosterdata;
  1228   roster_usr->print_status = pstatus;
  1228   roster_usr->print_status = pstatus;
  1229 }
  1229 }
  1230 
  1230 
  1231 enum room_printstatus buddy_getprintstatus(gpointer rosterdata)
  1231 enum room_printstatus buddy_getprintstatus(gpointer rosterdata)
  1232 {
  1232 {
  1233   roster *roster_usr = rosterdata;
  1233   roster_t *roster_usr = rosterdata;
  1234   return roster_usr->print_status;
  1234   return roster_usr->print_status;
  1235 }
  1235 }
  1236 
  1236 
  1237 void buddy_setautowhois(gpointer rosterdata, enum room_autowhois awhois)
  1237 void buddy_setautowhois(gpointer rosterdata, enum room_autowhois awhois)
  1238 {
  1238 {
  1239   roster *roster_usr = rosterdata;
  1239   roster_t *roster_usr = rosterdata;
  1240   roster_usr->auto_whois = awhois;
  1240   roster_usr->auto_whois = awhois;
  1241 }
  1241 }
  1242 
  1242 
  1243 enum room_autowhois buddy_getautowhois(gpointer rosterdata)
  1243 enum room_autowhois buddy_getautowhois(gpointer rosterdata)
  1244 {
  1244 {
  1245   roster *roster_usr = rosterdata;
  1245   roster_t *roster_usr = rosterdata;
  1246   return roster_usr->auto_whois;
  1246   return roster_usr->auto_whois;
  1247 }
  1247 }
  1248 
  1248 
  1249 void buddy_setflagjoins(gpointer rosterdata, enum room_flagjoins fjoins)
  1249 void buddy_setflagjoins(gpointer rosterdata, enum room_flagjoins fjoins)
  1250 {
  1250 {
  1251   roster *roster_usr = rosterdata;
  1251   roster_t *roster_usr = rosterdata;
  1252   roster_usr->flag_joins = fjoins;
  1252   roster_usr->flag_joins = fjoins;
  1253 }
  1253 }
  1254 
  1254 
  1255 enum room_flagjoins buddy_getflagjoins(gpointer rosterdata)
  1255 enum room_flagjoins buddy_getflagjoins(gpointer rosterdata)
  1256 {
  1256 {
  1257   roster *roster_usr = rosterdata;
  1257   roster_t *roster_usr = rosterdata;
  1258   return roster_usr->flag_joins;
  1258   return roster_usr->flag_joins;
  1259 }
  1259 }
  1260 
  1260 
  1261 //  buddy_getgroupname()
  1261 //  buddy_getgroupname()
  1262 // Returns a pointer on buddy's group name.
  1262 // Returns a pointer on buddy's group name.
  1263 const char *buddy_getgroupname(gpointer rosterdata)
  1263 const char *buddy_getgroupname(gpointer rosterdata)
  1264 {
  1264 {
  1265   roster *roster_usr = rosterdata;
  1265   roster_t *roster_usr = rosterdata;
  1266 
  1266 
  1267   if (roster_usr->type & ROSTER_TYPE_GROUP)
  1267   if (roster_usr->type & ROSTER_TYPE_GROUP)
  1268     return roster_usr->name;
  1268     return roster_usr->name;
  1269 
  1269 
  1270   if (roster_usr->type & ROSTER_TYPE_SPECIAL)
  1270   if (roster_usr->type & ROSTER_TYPE_SPECIAL)
  1271     return NULL;
  1271     return NULL;
  1272 
  1272 
  1273   // This is a user
  1273   // This is a user
  1274   return ((roster*)((GSList*)roster_usr->list)->data)->name;
  1274   return ((roster_t *)((GSList*)roster_usr->list)->data)->name;
  1275 }
  1275 }
  1276 
  1276 
  1277 //  buddy_getgroup()
  1277 //  buddy_getgroup()
  1278 // Returns a pointer on buddy's group.
  1278 // Returns a pointer on buddy's group.
  1279 gpointer buddy_getgroup(gpointer rosterdata)
  1279 gpointer buddy_getgroup(gpointer rosterdata)
  1280 {
  1280 {
  1281   roster *roster_usr = rosterdata;
  1281   roster_t *roster_usr = rosterdata;
  1282 
  1282 
  1283   if (roster_usr->type & ROSTER_TYPE_GROUP)
  1283   if (roster_usr->type & ROSTER_TYPE_GROUP)
  1284     return rosterdata;
  1284     return rosterdata;
  1285 
  1285 
  1286   if (roster_usr->type & ROSTER_TYPE_SPECIAL)
  1286   if (roster_usr->type & ROSTER_TYPE_SPECIAL)
  1290   return (gpointer)((GSList*)roster_usr->list)->data;
  1290   return (gpointer)((GSList*)roster_usr->list)->data;
  1291 }
  1291 }
  1292 
  1292 
  1293 void buddy_settype(gpointer rosterdata, guint type)
  1293 void buddy_settype(gpointer rosterdata, guint type)
  1294 {
  1294 {
  1295   roster *roster_usr = rosterdata;
  1295   roster_t *roster_usr = rosterdata;
  1296   roster_usr->type = type;
  1296   roster_usr->type = type;
  1297 }
  1297 }
  1298 
  1298 
  1299 guint buddy_gettype(gpointer rosterdata)
  1299 guint buddy_gettype(gpointer rosterdata)
  1300 {
  1300 {
  1301   roster *roster_usr = rosterdata;
  1301   roster_t *roster_usr = rosterdata;
  1302   return roster_usr->type;
  1302   return roster_usr->type;
  1303 }
  1303 }
  1304 
  1304 
  1305 guint buddy_getsubscription(gpointer rosterdata)
  1305 guint buddy_getsubscription(gpointer rosterdata)
  1306 {
  1306 {
  1307   roster *roster_usr = rosterdata;
  1307   roster_t *roster_usr = rosterdata;
  1308   return roster_usr->subscription;
  1308   return roster_usr->subscription;
  1309 }
  1309 }
  1310 
  1310 
  1311 enum imstatus buddy_getstatus(gpointer rosterdata, const char *resname)
  1311 enum imstatus buddy_getstatus(gpointer rosterdata, const char *resname)
  1312 {
  1312 {
  1313   roster *roster_usr = rosterdata;
  1313   roster_t *roster_usr = rosterdata;
  1314   res *p_res = get_resource(roster_usr, resname);
  1314   res_t *p_res = get_resource(roster_usr, resname);
  1315   if (p_res)
  1315   if (p_res)
  1316     return p_res->status;
  1316     return p_res->status;
  1317   return offline;
  1317   return offline;
  1318 }
  1318 }
  1319 
  1319 
  1320 const char *buddy_getstatusmsg(gpointer rosterdata, const char *resname)
  1320 const char *buddy_getstatusmsg(gpointer rosterdata, const char *resname)
  1321 {
  1321 {
  1322   roster *roster_usr = rosterdata;
  1322   roster_t *roster_usr = rosterdata;
  1323   res *p_res = get_resource(roster_usr, resname);
  1323   res_t *p_res = get_resource(roster_usr, resname);
  1324   if (p_res)
  1324   if (p_res)
  1325     return p_res->status_msg;
  1325     return p_res->status_msg;
  1326   return roster_usr->offline_status_message;
  1326   return roster_usr->offline_status_message;
  1327 }
  1327 }
  1328 
  1328 
  1329 time_t buddy_getstatustime(gpointer rosterdata, const char *resname)
  1329 time_t buddy_getstatustime(gpointer rosterdata, const char *resname)
  1330 {
  1330 {
  1331   roster *roster_usr = rosterdata;
  1331   roster_t *roster_usr = rosterdata;
  1332   res *p_res = get_resource(roster_usr, resname);
  1332   res_t *p_res = get_resource(roster_usr, resname);
  1333   if (p_res)
  1333   if (p_res)
  1334     return p_res->status_timestamp;
  1334     return p_res->status_timestamp;
  1335   return 0;
  1335   return 0;
  1336 }
  1336 }
  1337 
  1337 
  1338 gchar buddy_getresourceprio(gpointer rosterdata, const char *resname)
  1338 gchar buddy_getresourceprio(gpointer rosterdata, const char *resname)
  1339 {
  1339 {
  1340   roster *roster_usr = rosterdata;
  1340   roster_t *roster_usr = rosterdata;
  1341   res *p_res = get_resource(roster_usr, resname);
  1341   res_t *p_res = get_resource(roster_usr, resname);
  1342   if (p_res)
  1342   if (p_res)
  1343     return p_res->prio;
  1343     return p_res->prio;
  1344   return 0;
  1344   return 0;
  1345 }
  1345 }
  1346 
  1346 
  1347 guint buddy_resource_getevents(gpointer rosterdata, const char *resname)
  1347 guint buddy_resource_getevents(gpointer rosterdata, const char *resname)
  1348 {
  1348 {
  1349   roster *roster_usr = rosterdata;
  1349   roster_t *roster_usr = rosterdata;
  1350   res *p_res = get_resource(roster_usr, resname);
  1350   res_t *p_res = get_resource(roster_usr, resname);
  1351   if (p_res)
  1351   if (p_res)
  1352     return p_res->events;
  1352     return p_res->events;
  1353   return ROSTER_EVENT_NONE;
  1353   return ROSTER_EVENT_NONE;
  1354 }
  1354 }
  1355 
  1355 
  1356 void buddy_resource_setevents(gpointer rosterdata, const char *resname,
  1356 void buddy_resource_setevents(gpointer rosterdata, const char *resname,
  1357                               guint events)
  1357                               guint events)
  1358 {
  1358 {
  1359   roster *roster_usr = rosterdata;
  1359   roster_t *roster_usr = rosterdata;
  1360   res *p_res = get_resource(roster_usr, resname);
  1360   res_t *p_res = get_resource(roster_usr, resname);
  1361   if (p_res)
  1361   if (p_res)
  1362     p_res->events = events;
  1362     p_res->events = events;
  1363 }
  1363 }
  1364 
  1364 
  1365 char *buddy_resource_getcaps(gpointer rosterdata, const char *resname)
  1365 char *buddy_resource_getcaps(gpointer rosterdata, const char *resname)
  1366 {
  1366 {
  1367   roster *roster_usr = rosterdata;
  1367   roster_t *roster_usr = rosterdata;
  1368   res *p_res = get_resource(roster_usr, resname);
  1368   res_t *p_res = get_resource(roster_usr, resname);
  1369   if (p_res)
  1369   if (p_res)
  1370     return p_res->caps;
  1370     return p_res->caps;
  1371   return NULL;
  1371   return NULL;
  1372 }
  1372 }
  1373 
  1373 
  1374 void buddy_resource_setcaps(gpointer rosterdata, const char *resname,
  1374 void buddy_resource_setcaps(gpointer rosterdata, const char *resname,
  1375                             const char *caps)
  1375                             const char *caps)
  1376 {
  1376 {
  1377   roster *roster_usr = rosterdata;
  1377   roster_t *roster_usr = rosterdata;
  1378   res *p_res = get_resource(roster_usr, resname);
  1378   res_t *p_res = get_resource(roster_usr, resname);
  1379   if (p_res) {
  1379   if (p_res) {
  1380     g_free(p_res->caps);
  1380     g_free(p_res->caps);
  1381     p_res->caps = g_strdup(caps);
  1381     p_res->caps = g_strdup(caps);
  1382   }
  1382   }
  1383 }
  1383 }
  1384 
  1384 
  1385 struct xep0085 *buddy_resource_xep85(gpointer rosterdata, const char *resname)
  1385 struct xep0085 *buddy_resource_xep85(gpointer rosterdata, const char *resname)
  1386 {
  1386 {
  1387 #ifdef XEP0085
  1387 #ifdef XEP0085
  1388   roster *roster_usr = rosterdata;
  1388   roster_t *roster_usr = rosterdata;
  1389   res *p_res = get_resource(roster_usr, resname);
  1389   res_t *p_res = get_resource(roster_usr, resname);
  1390   if (p_res)
  1390   if (p_res)
  1391     return &p_res->xep85;
  1391     return &p_res->xep85;
  1392 #endif
  1392 #endif
  1393   return NULL;
  1393   return NULL;
  1394 }
  1394 }
  1395 
  1395 
  1396 struct pgp_data *buddy_resource_pgp(gpointer rosterdata, const char *resname)
  1396 struct pgp_data *buddy_resource_pgp(gpointer rosterdata, const char *resname)
  1397 {
  1397 {
  1398 #ifdef HAVE_GPGME
  1398 #ifdef HAVE_GPGME
  1399   roster *roster_usr = rosterdata;
  1399   roster_t *roster_usr = rosterdata;
  1400   res *p_res = get_resource(roster_usr, resname);
  1400   res_t *p_res = get_resource(roster_usr, resname);
  1401   if (p_res)
  1401   if (p_res)
  1402     return &p_res->pgpdata;
  1402     return &p_res->pgpdata;
  1403 #endif
  1403 #endif
  1404   return NULL;
  1404   return NULL;
  1405 }
  1405 }
  1406 
  1406 
  1407 enum imrole buddy_getrole(gpointer rosterdata, const char *resname)
  1407 enum imrole buddy_getrole(gpointer rosterdata, const char *resname)
  1408 {
  1408 {
  1409   roster *roster_usr = rosterdata;
  1409   roster_t *roster_usr = rosterdata;
  1410   res *p_res = get_resource(roster_usr, resname);
  1410   res_t *p_res = get_resource(roster_usr, resname);
  1411   if (p_res)
  1411   if (p_res)
  1412     return p_res->role;
  1412     return p_res->role;
  1413   return role_none;
  1413   return role_none;
  1414 }
  1414 }
  1415 
  1415 
  1416 enum imaffiliation buddy_getaffil(gpointer rosterdata, const char *resname)
  1416 enum imaffiliation buddy_getaffil(gpointer rosterdata, const char *resname)
  1417 {
  1417 {
  1418   roster *roster_usr = rosterdata;
  1418   roster_t *roster_usr = rosterdata;
  1419   res *p_res = get_resource(roster_usr, resname);
  1419   res_t *p_res = get_resource(roster_usr, resname);
  1420   if (p_res)
  1420   if (p_res)
  1421     return p_res->affil;
  1421     return p_res->affil;
  1422   return affil_none;
  1422   return affil_none;
  1423 }
  1423 }
  1424 
  1424 
  1425 const char *buddy_getrjid(gpointer rosterdata, const char *resname)
  1425 const char *buddy_getrjid(gpointer rosterdata, const char *resname)
  1426 {
  1426 {
  1427   roster *roster_usr = rosterdata;
  1427   roster_t *roster_usr = rosterdata;
  1428   res *p_res = get_resource(roster_usr, resname);
  1428   res_t *p_res = get_resource(roster_usr, resname);
  1429   if (p_res)
  1429   if (p_res)
  1430     return p_res->realjid;
  1430     return p_res->realjid;
  1431   return NULL;
  1431   return NULL;
  1432 }
  1432 }
  1433 
  1433 
  1435 // Return a singly-linked-list of resource names
  1435 // Return a singly-linked-list of resource names
  1436 // Note: the caller should free the list (and data) after use
  1436 // Note: the caller should free the list (and data) after use
  1437 // If roster_data is null, the current buddy is selected
  1437 // If roster_data is null, the current buddy is selected
  1438 GSList *buddy_getresources(gpointer rosterdata)
  1438 GSList *buddy_getresources(gpointer rosterdata)
  1439 {
  1439 {
  1440   roster *roster_usr = rosterdata;
  1440   roster_t *roster_usr = rosterdata;
  1441   GSList *reslist = NULL, *lp;
  1441   GSList *reslist = NULL, *lp;
  1442 
  1442 
  1443   if (!roster_usr) {
  1443   if (!roster_usr) {
  1444     if (!current_buddy) return NULL;
  1444     if (!current_buddy) return NULL;
  1445     roster_usr = BUDDATA(current_buddy);
  1445     roster_usr = BUDDATA(current_buddy);
  1446   }
  1446   }
  1447   for (lp = roster_usr->resource; lp; lp = g_slist_next(lp))
  1447   for (lp = roster_usr->resource; lp; lp = g_slist_next(lp))
  1448     reslist = g_slist_append(reslist, g_strdup(((res*)lp->data)->name));
  1448     reslist = g_slist_append(reslist, g_strdup(((res_t *)lp->data)->name));
  1449 
  1449 
  1450   return reslist;
  1450   return reslist;
  1451 }
  1451 }
  1452 
  1452 
  1453 //  buddy_getresources_locale(roster_data)
  1453 //  buddy_getresources_locale(roster_data)
  1472 
  1472 
  1473 //  buddy_getactiveresource(roster_data)
  1473 //  buddy_getactiveresource(roster_data)
  1474 // Returns name of active (selected for chat) resource
  1474 // Returns name of active (selected for chat) resource
  1475 const char *buddy_getactiveresource(gpointer rosterdata)
  1475 const char *buddy_getactiveresource(gpointer rosterdata)
  1476 {
  1476 {
  1477   roster *roster_usr = rosterdata;
  1477   roster_t *roster_usr = rosterdata;
  1478   res *resource;
  1478   res_t *resource;
  1479 
  1479 
  1480   if (!roster_usr) {
  1480   if (!roster_usr) {
  1481     if (!current_buddy) return NULL;
  1481     if (!current_buddy) return NULL;
  1482     roster_usr = BUDDATA(current_buddy);
  1482     roster_usr = BUDDATA(current_buddy);
  1483   }
  1483   }
  1487   return resource->name;
  1487   return resource->name;
  1488 }
  1488 }
  1489 
  1489 
  1490 void buddy_setactiveresource(gpointer rosterdata, const char *resname)
  1490 void buddy_setactiveresource(gpointer rosterdata, const char *resname)
  1491 {
  1491 {
  1492   roster *roster_usr = rosterdata;
  1492   roster_t *roster_usr = rosterdata;
  1493   res *p_res = NULL;
  1493   res_t *p_res = NULL;
  1494   if (resname)
  1494   if (resname)
  1495     p_res = get_resource(roster_usr, resname);
  1495     p_res = get_resource(roster_usr, resname);
  1496   roster_usr->active_resource = p_res;
  1496   roster_usr->active_resource = p_res;
  1497 }
  1497 }
  1498 
  1498 
  1500 //  buddy_isresource(roster_data)
  1500 //  buddy_isresource(roster_data)
  1501 // Return true if there is at least one resource
  1501 // Return true if there is at least one resource
  1502 // (which means, for a room, that it isn't empty)
  1502 // (which means, for a room, that it isn't empty)
  1503 int buddy_isresource(gpointer rosterdata)
  1503 int buddy_isresource(gpointer rosterdata)
  1504 {
  1504 {
  1505   roster *roster_usr = rosterdata;
  1505   roster_t *roster_usr = rosterdata;
  1506   if (!roster_usr)
  1506   if (!roster_usr)
  1507     return FALSE;
  1507     return FALSE;
  1508   if (roster_usr->resource)
  1508   if (roster_usr->resource)
  1509     return TRUE;
  1509     return TRUE;
  1510   return FALSE;
  1510   return FALSE;
  1514 //  buddy_resource_setname(roster_data, oldname, newname)
  1514 //  buddy_resource_setname(roster_data, oldname, newname)
  1515 // Useful for nickname change in a MUC room
  1515 // Useful for nickname change in a MUC room
  1516 void buddy_resource_setname(gpointer rosterdata, const char *resname,
  1516 void buddy_resource_setname(gpointer rosterdata, const char *resname,
  1517                             const char *newname)
  1517                             const char *newname)
  1518 {
  1518 {
  1519   roster *roster_usr = rosterdata;
  1519   roster_t *roster_usr = rosterdata;
  1520   res *p_res = get_resource(roster_usr, resname);
  1520   res_t *p_res = get_resource(roster_usr, resname);
  1521   if (p_res) {
  1521   if (p_res) {
  1522     if (p_res->name) {
  1522     if (p_res->name) {
  1523       g_free((gchar*)p_res->name);
  1523       g_free((gchar*)p_res->name);
  1524       p_res->name = NULL;
  1524       p_res->name = NULL;
  1525     }
  1525     }
  1530 
  1530 
  1531 //  buddy_del_all_resources()
  1531 //  buddy_del_all_resources()
  1532 // Remove all resources from the specified buddy
  1532 // Remove all resources from the specified buddy
  1533 void buddy_del_all_resources(gpointer rosterdata)
  1533 void buddy_del_all_resources(gpointer rosterdata)
  1534 {
  1534 {
  1535   roster *roster_usr = rosterdata;
  1535   roster_t *roster_usr = rosterdata;
  1536 
  1536 
  1537   while (roster_usr->resource) {
  1537   while (roster_usr->resource) {
  1538     res *r = roster_usr->resource->data;
  1538     res_t *r = roster_usr->resource->data;
  1539     del_resource(roster_usr, r->name);
  1539     del_resource(roster_usr, r->name);
  1540   }
  1540   }
  1541 }
  1541 }
  1542 
  1542 
  1543 //  buddy_setflags()
  1543 //  buddy_setflags()
  1544 // Set one or several flags to value (TRUE/FALSE)
  1544 // Set one or several flags to value (TRUE/FALSE)
  1545 void buddy_setflags(gpointer rosterdata, guint flags, guint value)
  1545 void buddy_setflags(gpointer rosterdata, guint flags, guint value)
  1546 {
  1546 {
  1547   roster *roster_usr = rosterdata;
  1547   roster_t *roster_usr = rosterdata;
  1548   if (value)
  1548   if (value)
  1549     roster_usr->flags |= flags;
  1549     roster_usr->flags |= flags;
  1550   else
  1550   else
  1551     roster_usr->flags &= ~flags;
  1551     roster_usr->flags &= ~flags;
  1552 }
  1552 }
  1553 
  1553 
  1554 guint buddy_getflags(gpointer rosterdata)
  1554 guint buddy_getflags(gpointer rosterdata)
  1555 {
  1555 {
  1556   roster *roster_usr = rosterdata;
  1556   roster_t *roster_usr = rosterdata;
  1557   return roster_usr->flags;
  1557   return roster_usr->flags;
  1558 }
  1558 }
  1559 
  1559 
  1560 guint buddy_getuiprio(gpointer rosterdata)
  1560 guint buddy_getuiprio(gpointer rosterdata)
  1561 {
  1561 {
  1562   roster *roster_usr = rosterdata;
  1562   roster_t *roster_usr = rosterdata;
  1563   return roster_usr->ui_prio;
  1563   return roster_usr->ui_prio;
  1564 }
  1564 }
  1565 
  1565 
  1566 guint buddy_getunread(gpointer rosterdata)
  1566 guint buddy_getunread(gpointer rosterdata)
  1567 {
  1567 {
  1568   roster *roster_usr = rosterdata;
  1568   roster_t *roster_usr = rosterdata;
  1569   return roster_usr->unread;
  1569   return roster_usr->unread;
  1570 }
  1570 }
  1571 
  1571 
  1572 //  buddy_setonserverflag()
  1572 //  buddy_setonserverflag()
  1573 // Set the on_server flag
  1573 // Set the on_server flag
  1574 void buddy_setonserverflag(gpointer rosterdata, guint onserver)
  1574 void buddy_setonserverflag(gpointer rosterdata, guint onserver)
  1575 {
  1575 {
  1576   roster *roster_usr = rosterdata;
  1576   roster_t *roster_usr = rosterdata;
  1577   roster_usr->on_server = onserver;
  1577   roster_usr->on_server = onserver;
  1578 }
  1578 }
  1579 
  1579 
  1580 guint buddy_getonserverflag(gpointer rosterdata)
  1580 guint buddy_getonserverflag(gpointer rosterdata)
  1581 {
  1581 {
  1582   roster *roster_usr = rosterdata;
  1582   roster_t *roster_usr = rosterdata;
  1583   return roster_usr->on_server;
  1583   return roster_usr->on_server;
  1584 }
  1584 }
  1585 
  1585 
  1586 //  buddy_search_jid(jid)
  1586 //  buddy_search_jid(jid)
  1587 // Look for a buddy with specified jid.
  1587 // Look for a buddy with specified jid.
  1588 // Search begins at buddylist; if no match is found in the the buddylist,
  1588 // Search begins at buddylist; if no match is found in the the buddylist,
  1589 // return NULL;
  1589 // return NULL;
  1590 GList *buddy_search_jid(const char *jid)
  1590 GList *buddy_search_jid(const char *jid)
  1591 {
  1591 {
  1592   GList *buddy;
  1592   GList *buddy;
  1593   roster *roster_usr;
  1593   roster_t *roster_usr;
  1594 
  1594 
  1595   buddylist_build();
  1595   buddylist_build();
  1596   if (!buddylist) return NULL;
  1596   if (!buddylist) return NULL;
  1597 
  1597 
  1598   for (buddy = buddylist; buddy; buddy = g_list_next(buddy)) {
  1598   for (buddy = buddylist; buddy; buddy = g_list_next(buddy)) {
  1599     roster_usr = (roster*)buddy->data;
  1599     roster_usr = (roster_t *)buddy->data;
  1600     if (roster_usr->jid && !strcasecmp(roster_usr->jid, jid))
  1600     if (roster_usr->jid && !strcasecmp(roster_usr->jid, jid))
  1601       return buddy;
  1601       return buddy;
  1602   }
  1602   }
  1603   return NULL;
  1603   return NULL;
  1604 }
  1604 }
  1608 // Search begins at current_buddy; if no match is found in the the buddylist,
  1608 // Search begins at current_buddy; if no match is found in the the buddylist,
  1609 // return NULL;
  1609 // return NULL;
  1610 GList *buddy_search(char *string)
  1610 GList *buddy_search(char *string)
  1611 {
  1611 {
  1612   GList *buddy = current_buddy;
  1612   GList *buddy = current_buddy;
  1613   roster *roster_usr;
  1613   roster_t *roster_usr;
  1614   buddylist_build();
  1614   buddylist_build();
  1615   if (!buddylist || !current_buddy) return NULL;
  1615   if (!buddylist || !current_buddy) return NULL;
  1616   for (;;) {
  1616   for (;;) {
  1617     gchar *jid_locale, *name_locale;
  1617     gchar *jid_locale, *name_locale;
  1618     char *found = NULL;
  1618     char *found = NULL;
  1619 
  1619 
  1620     buddy = g_list_next(buddy);
  1620     buddy = g_list_next(buddy);
  1621     if (!buddy)
  1621     if (!buddy)
  1622       buddy = buddylist;
  1622       buddy = buddylist;
  1623 
  1623 
  1624     roster_usr = (roster*)buddy->data;
  1624     roster_usr = (roster_t *)buddy->data;
  1625 
  1625 
  1626     jid_locale = from_utf8(roster_usr->jid);
  1626     jid_locale = from_utf8(roster_usr->jid);
  1627     if (jid_locale) {
  1627     if (jid_locale) {
  1628       found = strcasestr(jid_locale, string);
  1628       found = strcasestr(jid_locale, string);
  1629       g_free(jid_locale);
  1629       g_free(jid_locale);
  1649 void foreach_buddy(guint roster_type,
  1649 void foreach_buddy(guint roster_type,
  1650                    void (*pfunc)(gpointer rosterdata, void *param),
  1650                    void (*pfunc)(gpointer rosterdata, void *param),
  1651                    void *param)
  1651                    void *param)
  1652 {
  1652 {
  1653   GSList *sl_roster_elt = groups;
  1653   GSList *sl_roster_elt = groups;
  1654   roster *roster_elt;
  1654   roster_t *roster_elt;
  1655   GSList *sl_roster_usrelt;
  1655   GSList *sl_roster_usrelt;
  1656   roster *roster_usrelt;
  1656   roster_t *roster_usrelt;
  1657 
  1657 
  1658   while (sl_roster_elt) {       // group list loop
  1658   while (sl_roster_elt) {       // group list loop
  1659     roster_elt = (roster*) sl_roster_elt->data;
  1659     roster_elt = (roster_t *) sl_roster_elt->data;
  1660     if (roster_elt->type & ROSTER_TYPE_SPECIAL)
  1660     if (roster_elt->type & ROSTER_TYPE_SPECIAL)
  1661       continue; // Skip special items
  1661       continue; // Skip special items
  1662     sl_roster_usrelt = roster_elt->list;
  1662     sl_roster_usrelt = roster_elt->list;
  1663     while (sl_roster_usrelt) {  // user list loop
  1663     while (sl_roster_usrelt) {  // user list loop
  1664       roster_usrelt = (roster*) sl_roster_usrelt->data;
  1664       roster_usrelt = (roster_t *) sl_roster_usrelt->data;
  1665 
  1665 
  1666       if (roster_usrelt->type & roster_type)
  1666       if (roster_usrelt->type & roster_type)
  1667         pfunc(roster_usrelt, param);
  1667         pfunc(roster_usrelt, param);
  1668 
  1668 
  1669       sl_roster_usrelt = g_slist_next(sl_roster_usrelt);
  1669       sl_roster_usrelt = g_slist_next(sl_roster_usrelt);
  1676 // Call pfunction(buddy, param) for each buddy in the specified group.
  1676 // Call pfunction(buddy, param) for each buddy in the specified group.
  1677 void foreach_group_member(gpointer groupdata,
  1677 void foreach_group_member(gpointer groupdata,
  1678                    void (*pfunc)(gpointer rosterdata, void *param),
  1678                    void (*pfunc)(gpointer rosterdata, void *param),
  1679                    void *param)
  1679                    void *param)
  1680 {
  1680 {
  1681   roster *roster_elt;
  1681   roster_t *roster_elt;
  1682   GSList *sl_roster_usrelt;
  1682   GSList *sl_roster_usrelt;
  1683   roster *roster_usrelt;
  1683   roster_t *roster_usrelt;
  1684 
  1684 
  1685   roster_elt = groupdata;
  1685   roster_elt = groupdata;
  1686 
  1686 
  1687   if (!(roster_elt->type & ROSTER_TYPE_GROUP))
  1687   if (!(roster_elt->type & ROSTER_TYPE_GROUP))
  1688     return;
  1688     return;
  1689 
  1689 
  1690   sl_roster_usrelt = roster_elt->list;
  1690   sl_roster_usrelt = roster_elt->list;
  1691   while (sl_roster_usrelt) {  // user list loop
  1691   while (sl_roster_usrelt) {  // user list loop
  1692     GSList *next_sl_usrelt;
  1692     GSList *next_sl_usrelt;
  1693     roster_usrelt = (roster*) sl_roster_usrelt->data;
  1693     roster_usrelt = (roster_t *) sl_roster_usrelt->data;
  1694 
  1694 
  1695     next_sl_usrelt = g_slist_next(sl_roster_usrelt);
  1695     next_sl_usrelt = g_slist_next(sl_roster_usrelt);
  1696     pfunc(roster_usrelt, param);
  1696     pfunc(roster_usrelt, param);
  1697     sl_roster_usrelt = next_sl_usrelt;
  1697     sl_roster_usrelt = next_sl_usrelt;
  1698   }
  1698   }
  1704 // The list should be freed by the caller after use.
  1704 // The list should be freed by the caller after use.
  1705 GSList *compl_list(guint type)
  1705 GSList *compl_list(guint type)
  1706 {
  1706 {
  1707   GSList *list = NULL;
  1707   GSList *list = NULL;
  1708   GSList *sl_roster_elt = groups;
  1708   GSList *sl_roster_elt = groups;
  1709   roster *roster_elt;
  1709   roster_t *roster_elt;
  1710   GSList *sl_roster_usrelt;
  1710   GSList *sl_roster_usrelt;
  1711   roster *roster_usrelt;
  1711   roster_t *roster_usrelt;
  1712 
  1712 
  1713   while (sl_roster_elt) {       // group list loop
  1713   while (sl_roster_elt) {       // group list loop
  1714     roster_elt = (roster*) sl_roster_elt->data;
  1714     roster_elt = (roster_t *) sl_roster_elt->data;
  1715 
  1715 
  1716     if (roster_elt->type & ROSTER_TYPE_SPECIAL)
  1716     if (roster_elt->type & ROSTER_TYPE_SPECIAL)
  1717       continue; // Skip special items
  1717       continue; // Skip special items
  1718 
  1718 
  1719     if (type == ROSTER_TYPE_GROUP) { // (group names)
  1719     if (type == ROSTER_TYPE_GROUP) { // (group names)
  1720       if (roster_elt->name && *(roster_elt->name))
  1720       if (roster_elt->name && *(roster_elt->name))
  1721         list = g_slist_append(list, from_utf8(roster_elt->name));
  1721         list = g_slist_append(list, from_utf8(roster_elt->name));
  1722     } else { // ROSTER_TYPE_USER (jid) (or agent, or chatroom...)
  1722     } else { // ROSTER_TYPE_USER (jid) (or agent, or chatroom...)
  1723       sl_roster_usrelt = roster_elt->list;
  1723       sl_roster_usrelt = roster_elt->list;
  1724       while (sl_roster_usrelt) {  // user list loop
  1724       while (sl_roster_usrelt) {  // user list loop
  1725         roster_usrelt = (roster*) sl_roster_usrelt->data;
  1725         roster_usrelt = (roster_t *) sl_roster_usrelt->data;
  1726 
  1726 
  1727         if (roster_usrelt->jid)
  1727         if (roster_usrelt->jid)
  1728           list = g_slist_append(list, from_utf8(roster_usrelt->jid));
  1728           list = g_slist_append(list, from_utf8(roster_usrelt->jid));
  1729 
  1729 
  1730         sl_roster_usrelt = g_slist_next(sl_roster_usrelt);
  1730         sl_roster_usrelt = g_slist_next(sl_roster_usrelt);