| 86 g_free(realname); |
86 g_free(realname); |
| 87 |
87 |
| 88 return jb; |
88 return jb; |
| 89 } |
89 } |
| 90 |
90 |
| |
91 static gint resource_compare_cb(gconstpointer a, gconstpointer b) |
| |
92 { |
| |
93 const JabberBuddyResource *jbra = a; |
| |
94 const JabberBuddyResource *jbrb = b; |
| |
95 JabberBuddyState state_a, state_b; |
| |
96 |
| |
97 if (jbra->priority != jbrb->priority) |
| |
98 return jbra->priority > jbrb->priority ? 1 : -1; |
| |
99 |
| |
100 /* Fold the states for easier comparison */ |
| |
101 switch (jbra->state) { |
| |
102 case JABBER_BUDDY_STATE_ONLINE: |
| |
103 case JABBER_BUDDY_STATE_CHAT: |
| |
104 state_a = JABBER_BUDDY_STATE_ONLINE; |
| |
105 break; |
| |
106 case JABBER_BUDDY_STATE_AWAY: |
| |
107 case JABBER_BUDDY_STATE_DND: |
| |
108 state_a = JABBER_BUDDY_STATE_AWAY; |
| |
109 break; |
| |
110 case JABBER_BUDDY_STATE_XA: |
| |
111 state_a = JABBER_BUDDY_STATE_XA; |
| |
112 break; |
| |
113 case JABBER_BUDDY_STATE_UNAVAILABLE: |
| |
114 state_a = JABBER_BUDDY_STATE_UNAVAILABLE; |
| |
115 break; |
| |
116 default: |
| |
117 state_a = JABBER_BUDDY_STATE_UNKNOWN; |
| |
118 break; |
| |
119 } |
| |
120 |
| |
121 switch (jbrb->state) { |
| |
122 case JABBER_BUDDY_STATE_ONLINE: |
| |
123 case JABBER_BUDDY_STATE_CHAT: |
| |
124 state_b = JABBER_BUDDY_STATE_ONLINE; |
| |
125 break; |
| |
126 case JABBER_BUDDY_STATE_AWAY: |
| |
127 case JABBER_BUDDY_STATE_DND: |
| |
128 state_b = JABBER_BUDDY_STATE_AWAY; |
| |
129 break; |
| |
130 case JABBER_BUDDY_STATE_XA: |
| |
131 state_b = JABBER_BUDDY_STATE_XA; |
| |
132 break; |
| |
133 case JABBER_BUDDY_STATE_UNAVAILABLE: |
| |
134 state_b = JABBER_BUDDY_STATE_UNAVAILABLE; |
| |
135 break; |
| |
136 default: |
| |
137 state_b = JABBER_BUDDY_STATE_UNKNOWN; |
| |
138 break; |
| |
139 } |
| |
140 |
| |
141 if (state_a == state_b) { |
| |
142 if (jbra->idle == jbrb->idle) |
| |
143 return 0; |
| |
144 else if ((jbra->idle && !jbrb->idle) || |
| |
145 (jbra->idle && jbrb->idle && jbra->idle < jbrb->idle)) |
| |
146 return -1; |
| |
147 else |
| |
148 return 1; |
| |
149 } |
| |
150 |
| |
151 if (state_a == JABBER_BUDDY_STATE_ONLINE) |
| |
152 return 1; |
| |
153 else if (state_a == JABBER_BUDDY_STATE_AWAY && |
| |
154 (state_b == JABBER_BUDDY_STATE_XA || |
| |
155 state_b == JABBER_BUDDY_STATE_UNAVAILABLE || |
| |
156 state_b == JABBER_BUDDY_STATE_UNKNOWN)) |
| |
157 return 1; |
| |
158 else if (state_a == JABBER_BUDDY_STATE_XA && |
| |
159 (state_b == JABBER_BUDDY_STATE_UNAVAILABLE || |
| |
160 state_b == JABBER_BUDDY_STATE_UNKNOWN)) |
| |
161 return 1; |
| |
162 else if (state_a == JABBER_BUDDY_STATE_UNAVAILABLE && |
| |
163 state_b == JABBER_BUDDY_STATE_UNKNOWN) |
| |
164 return 1; |
| |
165 |
| |
166 return -1; |
| |
167 } |
| 91 |
168 |
| 92 JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb, |
169 JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb, |
| 93 const char *resource) |
170 const char *resource) |
| 94 { |
171 { |
| 95 JabberBuddyResource *jbr = NULL; |
172 JabberBuddyResource *jbr = NULL; |
| 102 { |
179 { |
| 103 JabberBuddyResource *tmp = (JabberBuddyResource *) l->data; |
180 JabberBuddyResource *tmp = (JabberBuddyResource *) l->data; |
| 104 if (!jbr && !resource) { |
181 if (!jbr && !resource) { |
| 105 jbr = tmp; |
182 jbr = tmp; |
| 106 } else if (!resource) { |
183 } else if (!resource) { |
| 107 if (tmp->priority > jbr->priority) |
184 if (resource_compare_cb(tmp, jbr) > 0) |
| 108 jbr = tmp; |
185 jbr = tmp; |
| 109 else if (tmp->priority == jbr->priority) { |
|
| 110 /* Determine if this resource is more available than the one we've currently chosen */ |
|
| 111 switch(tmp->state) { |
|
| 112 case JABBER_BUDDY_STATE_ONLINE: |
|
| 113 case JABBER_BUDDY_STATE_CHAT: |
|
| 114 /* This resource is online/chatty. Prefer to one which isn't either. */ |
|
| 115 if (((jbr->state != JABBER_BUDDY_STATE_ONLINE) && (jbr->state != JABBER_BUDDY_STATE_CHAT)) |
|
| 116 || (jbr->idle && !tmp->idle) |
|
| 117 || (jbr->idle && tmp->idle && tmp->idle > jbr->idle)) |
|
| 118 jbr = tmp; |
|
| 119 break; |
|
| 120 case JABBER_BUDDY_STATE_AWAY: |
|
| 121 case JABBER_BUDDY_STATE_DND: |
|
| 122 /* This resource is away/dnd. Prefer to one which is extended away, unavailable, or unknown. */ |
|
| 123 if (((jbr->state == JABBER_BUDDY_STATE_XA) || (jbr->state == JABBER_BUDDY_STATE_UNAVAILABLE) || |
|
| 124 (jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR)) |
|
| 125 || (jbr->idle && !tmp->idle) |
|
| 126 || (jbr->idle && tmp->idle && tmp->idle > jbr->idle)) |
|
| 127 jbr = tmp; |
|
| 128 break; |
|
| 129 case JABBER_BUDDY_STATE_XA: |
|
| 130 /* This resource is extended away. That's better than unavailable or unknown. */ |
|
| 131 if ((jbr->state == JABBER_BUDDY_STATE_UNAVAILABLE) || (jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR)) |
|
| 132 jbr = tmp; |
|
| 133 break; |
|
| 134 case JABBER_BUDDY_STATE_UNAVAILABLE: |
|
| 135 /* This resource is unavailable. That's better than unknown. */ |
|
| 136 if ((jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR)) |
|
| 137 jbr = tmp; |
|
| 138 break; |
|
| 139 case JABBER_BUDDY_STATE_UNKNOWN: |
|
| 140 case JABBER_BUDDY_STATE_ERROR: |
|
| 141 /* These are never preferable. */ |
|
| 142 break; |
|
| 143 } |
|
| 144 } |
|
| 145 } else if(tmp->name) { |
186 } else if(tmp->name) { |
| 146 if(!strcmp(tmp->name, resource)) { |
187 if(!strcmp(tmp->name, resource)) { |
| 147 jbr = tmp; |
188 jbr = tmp; |
| 148 break; |
189 break; |
| 149 } |
190 } |