| 1 /** |
|
| 2 * @file notify.c Notification API |
|
| 3 * @ingroup core |
|
| 4 * |
|
| 5 * gaim |
|
| 6 * |
|
| 7 * Gaim is the legal property of its developers, whose names are too numerous |
|
| 8 * to list here. Please refer to the COPYRIGHT file distributed with this |
|
| 9 * source distribution. |
|
| 10 * |
|
| 11 * This program is free software; you can redistribute it and/or modify |
|
| 12 * it under the terms of the GNU General Public License as published by |
|
| 13 * the Free Software Foundation; either version 2 of the License, or |
|
| 14 * (at your option) any later version. |
|
| 15 * |
|
| 16 * This program is distributed in the hope that it will be useful, |
|
| 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 19 * GNU General Public License for more details. |
|
| 20 * |
|
| 21 * You should have received a copy of the GNU General Public License |
|
| 22 * along with this program; if not, write to the Free Software |
|
| 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
| 24 */ |
|
| 25 #include "notify.h" |
|
| 26 |
|
| 27 static GaimNotifyUiOps *notify_ui_ops = NULL; |
|
| 28 static GList *handles = NULL; |
|
| 29 |
|
| 30 typedef struct |
|
| 31 { |
|
| 32 GaimNotifyType type; |
|
| 33 void *handle; |
|
| 34 void *ui_handle; |
|
| 35 GaimNotifyCloseCallback cb; |
|
| 36 gpointer cb_user_data; |
|
| 37 } GaimNotifyInfo; |
|
| 38 |
|
| 39 void * |
|
| 40 gaim_notify_message(void *handle, GaimNotifyMsgType type, |
|
| 41 const char *title, const char *primary, |
|
| 42 const char *secondary, GaimNotifyCloseCallback cb, gpointer user_data) |
|
| 43 { |
|
| 44 GaimNotifyUiOps *ops; |
|
| 45 |
|
| 46 g_return_val_if_fail(primary != NULL, NULL); |
|
| 47 |
|
| 48 ops = gaim_notify_get_ui_ops(); |
|
| 49 |
|
| 50 if (ops != NULL && ops->notify_message != NULL) { |
|
| 51 GaimNotifyInfo *info; |
|
| 52 |
|
| 53 info = g_new0(GaimNotifyInfo, 1); |
|
| 54 info->type = GAIM_NOTIFY_MESSAGE; |
|
| 55 info->handle = handle; |
|
| 56 info->ui_handle = ops->notify_message(type, title, primary, |
|
| 57 secondary); |
|
| 58 info->cb = cb; |
|
| 59 info->cb_user_data = user_data; |
|
| 60 |
|
| 61 if (info->ui_handle != NULL) { |
|
| 62 handles = g_list_append(handles, info); |
|
| 63 |
|
| 64 return info->ui_handle; |
|
| 65 |
|
| 66 } else { |
|
| 67 if (info->cb != NULL) |
|
| 68 info->cb(info->cb_user_data); |
|
| 69 |
|
| 70 g_free(info); |
|
| 71 |
|
| 72 return NULL; |
|
| 73 } |
|
| 74 |
|
| 75 } else { |
|
| 76 if (cb != NULL) |
|
| 77 cb(user_data); |
|
| 78 } |
|
| 79 |
|
| 80 return NULL; |
|
| 81 } |
|
| 82 |
|
| 83 void * |
|
| 84 gaim_notify_email(void *handle, const char *subject, const char *from, |
|
| 85 const char *to, const char *url, GaimNotifyCloseCallback cb, |
|
| 86 gpointer user_data) |
|
| 87 { |
|
| 88 GaimNotifyUiOps *ops; |
|
| 89 |
|
| 90 ops = gaim_notify_get_ui_ops(); |
|
| 91 |
|
| 92 if (ops != NULL && ops->notify_email != NULL) { |
|
| 93 GaimNotifyInfo *info; |
|
| 94 |
|
| 95 info = g_new0(GaimNotifyInfo, 1); |
|
| 96 info->type = GAIM_NOTIFY_EMAIL; |
|
| 97 info->handle = handle; |
|
| 98 info->ui_handle = ops->notify_email(handle, subject, from, to, url); |
|
| 99 info->cb = cb; |
|
| 100 info->cb_user_data = user_data; |
|
| 101 |
|
| 102 if (info->ui_handle != NULL) { |
|
| 103 handles = g_list_append(handles, info); |
|
| 104 |
|
| 105 return info->ui_handle; |
|
| 106 |
|
| 107 } else { |
|
| 108 if (info->cb != NULL) |
|
| 109 info->cb(info->cb_user_data); |
|
| 110 |
|
| 111 g_free(info); |
|
| 112 |
|
| 113 return NULL; |
|
| 114 } |
|
| 115 } else { |
|
| 116 if (cb != NULL) |
|
| 117 cb(user_data); |
|
| 118 } |
|
| 119 |
|
| 120 return NULL; |
|
| 121 } |
|
| 122 |
|
| 123 void * |
|
| 124 gaim_notify_emails(void *handle, size_t count, gboolean detailed, |
|
| 125 const char **subjects, const char **froms, |
|
| 126 const char **tos, const char **urls, |
|
| 127 GaimNotifyCloseCallback cb, gpointer user_data) |
|
| 128 { |
|
| 129 GaimNotifyUiOps *ops; |
|
| 130 |
|
| 131 g_return_val_if_fail(count != 0, NULL); |
|
| 132 |
|
| 133 if (count == 1) { |
|
| 134 return gaim_notify_email(handle, |
|
| 135 (subjects == NULL ? NULL : *subjects), |
|
| 136 (froms == NULL ? NULL : *froms), |
|
| 137 (tos == NULL ? NULL : *tos), |
|
| 138 (urls == NULL ? NULL : *urls), |
|
| 139 cb, user_data); |
|
| 140 } |
|
| 141 |
|
| 142 ops = gaim_notify_get_ui_ops(); |
|
| 143 |
|
| 144 if (ops != NULL && ops->notify_emails != NULL) { |
|
| 145 GaimNotifyInfo *info; |
|
| 146 |
|
| 147 info = g_new0(GaimNotifyInfo, 1); |
|
| 148 info->type = GAIM_NOTIFY_EMAILS; |
|
| 149 info->handle = handle; |
|
| 150 info->ui_handle = ops->notify_emails(handle, count, detailed, subjects, |
|
| 151 froms, tos, urls); |
|
| 152 info->cb = cb; |
|
| 153 info->cb_user_data = user_data; |
|
| 154 |
|
| 155 if (info->ui_handle != NULL) { |
|
| 156 handles = g_list_append(handles, info); |
|
| 157 |
|
| 158 return info->ui_handle; |
|
| 159 |
|
| 160 } else { |
|
| 161 if (info->cb != NULL) |
|
| 162 info->cb(info->cb_user_data); |
|
| 163 |
|
| 164 g_free(info); |
|
| 165 |
|
| 166 return NULL; |
|
| 167 } |
|
| 168 |
|
| 169 } else { |
|
| 170 if (cb != NULL) |
|
| 171 cb(user_data); |
|
| 172 } |
|
| 173 |
|
| 174 return NULL; |
|
| 175 } |
|
| 176 |
|
| 177 void * |
|
| 178 gaim_notify_formatted(void *handle, const char *title, const char *primary, |
|
| 179 const char *secondary, const char *text, |
|
| 180 GaimNotifyCloseCallback cb, gpointer user_data) |
|
| 181 { |
|
| 182 GaimNotifyUiOps *ops; |
|
| 183 |
|
| 184 g_return_val_if_fail(primary != NULL, NULL); |
|
| 185 |
|
| 186 ops = gaim_notify_get_ui_ops(); |
|
| 187 |
|
| 188 if (ops != NULL && ops->notify_formatted != NULL) { |
|
| 189 GaimNotifyInfo *info; |
|
| 190 |
|
| 191 info = g_new0(GaimNotifyInfo, 1); |
|
| 192 info->type = GAIM_NOTIFY_FORMATTED; |
|
| 193 info->handle = handle; |
|
| 194 info->ui_handle = ops->notify_formatted(title, primary, secondary, text); |
|
| 195 info->cb = cb; |
|
| 196 info->cb_user_data = user_data; |
|
| 197 |
|
| 198 if (info->ui_handle != NULL) { |
|
| 199 handles = g_list_append(handles, info); |
|
| 200 |
|
| 201 return info->ui_handle; |
|
| 202 |
|
| 203 } else { |
|
| 204 if (info->cb != NULL) |
|
| 205 info->cb(info->cb_user_data); |
|
| 206 |
|
| 207 g_free(info); |
|
| 208 |
|
| 209 return NULL; |
|
| 210 } |
|
| 211 |
|
| 212 } else { |
|
| 213 if (cb != NULL) |
|
| 214 cb(user_data); |
|
| 215 } |
|
| 216 |
|
| 217 return NULL; |
|
| 218 } |
|
| 219 |
|
| 220 void * |
|
| 221 gaim_notify_searchresults(GaimConnection *gc, const char *title, |
|
| 222 const char *primary, const char *secondary, |
|
| 223 GaimNotifySearchResults *results, GaimNotifyCloseCallback cb, |
|
| 224 gpointer user_data) |
|
| 225 { |
|
| 226 GaimNotifyUiOps *ops; |
|
| 227 |
|
| 228 ops = gaim_notify_get_ui_ops(); |
|
| 229 |
|
| 230 if (ops != NULL && ops->notify_searchresults != NULL) { |
|
| 231 GaimNotifyInfo *info; |
|
| 232 |
|
| 233 info = g_new0(GaimNotifyInfo, 1); |
|
| 234 info->type = GAIM_NOTIFY_SEARCHRESULTS; |
|
| 235 info->handle = gc; |
|
| 236 info->ui_handle = ops->notify_searchresults(gc, title, primary, |
|
| 237 secondary, results, user_data); |
|
| 238 info->cb = cb; |
|
| 239 info->cb_user_data = user_data; |
|
| 240 |
|
| 241 if (info->ui_handle != NULL) { |
|
| 242 handles = g_list_append(handles, info); |
|
| 243 |
|
| 244 return info->ui_handle; |
|
| 245 |
|
| 246 } else { |
|
| 247 if (info->cb != NULL) |
|
| 248 info->cb(info->cb_user_data); |
|
| 249 |
|
| 250 g_free(info); |
|
| 251 |
|
| 252 return NULL; |
|
| 253 } |
|
| 254 |
|
| 255 } else { |
|
| 256 if (cb != NULL) |
|
| 257 cb(user_data); |
|
| 258 } |
|
| 259 |
|
| 260 return NULL; |
|
| 261 } |
|
| 262 |
|
| 263 void |
|
| 264 gaim_notify_searchresults_free(GaimNotifySearchResults *results) |
|
| 265 { |
|
| 266 GList *l; |
|
| 267 |
|
| 268 g_return_if_fail(results != NULL); |
|
| 269 |
|
| 270 for (l = results->buttons; l; l = g_list_delete_link(l, l)) { |
|
| 271 GaimNotifySearchButton *button = l->data; |
|
| 272 g_free(button->label); |
|
| 273 g_free(button); |
|
| 274 } |
|
| 275 |
|
| 276 for (l = results->rows; l; l = g_list_delete_link(l, l)) { |
|
| 277 GList *row = l->data; |
|
| 278 g_list_foreach(row, (GFunc)g_free, NULL); |
|
| 279 g_list_free(row); |
|
| 280 } |
|
| 281 |
|
| 282 for (l = results->columns; l; l = g_list_delete_link(l, l)) { |
|
| 283 GaimNotifySearchColumn *column = l->data; |
|
| 284 g_free(column->title); |
|
| 285 g_free(column); |
|
| 286 } |
|
| 287 |
|
| 288 g_free(results); |
|
| 289 } |
|
| 290 |
|
| 291 void |
|
| 292 gaim_notify_searchresults_new_rows(GaimConnection *gc, |
|
| 293 GaimNotifySearchResults *results, |
|
| 294 void *data) |
|
| 295 { |
|
| 296 GaimNotifyUiOps *ops; |
|
| 297 |
|
| 298 ops = gaim_notify_get_ui_ops(); |
|
| 299 |
|
| 300 if (ops != NULL && ops->notify_searchresults != NULL) { |
|
| 301 ops->notify_searchresults_new_rows(gc, results, data); |
|
| 302 } |
|
| 303 } |
|
| 304 |
|
| 305 void |
|
| 306 gaim_notify_searchresults_button_add(GaimNotifySearchResults *results, |
|
| 307 GaimNotifySearchButtonType type, |
|
| 308 GaimNotifySearchResultsCallback cb) |
|
| 309 { |
|
| 310 GaimNotifySearchButton *button; |
|
| 311 |
|
| 312 g_return_if_fail(results != NULL); |
|
| 313 g_return_if_fail(cb != NULL); |
|
| 314 |
|
| 315 button = g_new0(GaimNotifySearchButton, 1); |
|
| 316 button->callback = cb; |
|
| 317 button->type = type; |
|
| 318 |
|
| 319 results->buttons = g_list_append(results->buttons, button); |
|
| 320 } |
|
| 321 |
|
| 322 |
|
| 323 void |
|
| 324 gaim_notify_searchresults_button_add_labeled(GaimNotifySearchResults *results, |
|
| 325 const char *label, |
|
| 326 GaimNotifySearchResultsCallback cb) { |
|
| 327 GaimNotifySearchButton *button; |
|
| 328 |
|
| 329 g_return_if_fail(results != NULL); |
|
| 330 g_return_if_fail(cb != NULL); |
|
| 331 g_return_if_fail(label != NULL); |
|
| 332 g_return_if_fail(*label != '\0'); |
|
| 333 |
|
| 334 button = g_new0(GaimNotifySearchButton, 1); |
|
| 335 button->callback = cb; |
|
| 336 button->type = GAIM_NOTIFY_BUTTON_LABELED; |
|
| 337 button->label = g_strdup(label); |
|
| 338 |
|
| 339 results->buttons = g_list_append(results->buttons, button); |
|
| 340 } |
|
| 341 |
|
| 342 |
|
| 343 GaimNotifySearchResults * |
|
| 344 gaim_notify_searchresults_new() |
|
| 345 { |
|
| 346 GaimNotifySearchResults *rs = g_new0(GaimNotifySearchResults, 1); |
|
| 347 |
|
| 348 return rs; |
|
| 349 } |
|
| 350 |
|
| 351 void |
|
| 352 gaim_notify_searchresults_column_add(GaimNotifySearchResults *results, |
|
| 353 GaimNotifySearchColumn *column) |
|
| 354 { |
|
| 355 g_return_if_fail(results != NULL); |
|
| 356 g_return_if_fail(column != NULL); |
|
| 357 |
|
| 358 results->columns = g_list_append(results->columns, column); |
|
| 359 } |
|
| 360 |
|
| 361 void gaim_notify_searchresults_row_add(GaimNotifySearchResults *results, |
|
| 362 GList *row) |
|
| 363 { |
|
| 364 g_return_if_fail(results != NULL); |
|
| 365 g_return_if_fail(row != NULL); |
|
| 366 |
|
| 367 results->rows = g_list_append(results->rows, row); |
|
| 368 } |
|
| 369 |
|
| 370 GaimNotifySearchColumn * |
|
| 371 gaim_notify_searchresults_column_new(const char *title) |
|
| 372 { |
|
| 373 GaimNotifySearchColumn *sc; |
|
| 374 |
|
| 375 g_return_val_if_fail(title != NULL, NULL); |
|
| 376 |
|
| 377 sc = g_new0(GaimNotifySearchColumn, 1); |
|
| 378 sc->title = g_strdup(title); |
|
| 379 |
|
| 380 return sc; |
|
| 381 } |
|
| 382 |
|
| 383 guint |
|
| 384 gaim_notify_searchresults_get_columns_count(GaimNotifySearchResults *results) |
|
| 385 { |
|
| 386 g_return_val_if_fail(results != NULL, 0); |
|
| 387 |
|
| 388 return g_list_length(results->columns); |
|
| 389 } |
|
| 390 |
|
| 391 guint |
|
| 392 gaim_notify_searchresults_get_rows_count(GaimNotifySearchResults *results) |
|
| 393 { |
|
| 394 g_return_val_if_fail(results != NULL, 0); |
|
| 395 |
|
| 396 return g_list_length(results->rows); |
|
| 397 } |
|
| 398 |
|
| 399 char * |
|
| 400 gaim_notify_searchresults_column_get_title(GaimNotifySearchResults *results, |
|
| 401 unsigned int column_id) |
|
| 402 { |
|
| 403 g_return_val_if_fail(results != NULL, NULL); |
|
| 404 |
|
| 405 return ((GaimNotifySearchColumn *)g_list_nth_data(results->columns, column_id))->title; |
|
| 406 } |
|
| 407 |
|
| 408 GList * |
|
| 409 gaim_notify_searchresults_row_get(GaimNotifySearchResults *results, |
|
| 410 unsigned int row_id) |
|
| 411 { |
|
| 412 g_return_val_if_fail(results != NULL, NULL); |
|
| 413 |
|
| 414 return g_list_nth_data(results->rows, row_id); |
|
| 415 } |
|
| 416 |
|
| 417 void * |
|
| 418 gaim_notify_userinfo(GaimConnection *gc, const char *who, |
|
| 419 const char *text, GaimNotifyCloseCallback cb, gpointer user_data) |
|
| 420 { |
|
| 421 GaimNotifyUiOps *ops; |
|
| 422 |
|
| 423 g_return_val_if_fail(who != NULL, NULL); |
|
| 424 |
|
| 425 ops = gaim_notify_get_ui_ops(); |
|
| 426 |
|
| 427 if (ops != NULL && ops->notify_userinfo != NULL) { |
|
| 428 GaimNotifyInfo *info; |
|
| 429 char *infotext = g_strdup(text); |
|
| 430 |
|
| 431 info = g_new0(GaimNotifyInfo, 1); |
|
| 432 info->type = GAIM_NOTIFY_USERINFO; |
|
| 433 info->handle = gc; |
|
| 434 |
|
| 435 gaim_signal_emit(gaim_notify_get_handle(), "displaying-userinfo", |
|
| 436 gaim_connection_get_account(gc), who, &infotext); |
|
| 437 |
|
| 438 info->ui_handle = ops->notify_userinfo(gc, who, infotext); |
|
| 439 info->cb = cb; |
|
| 440 info->cb_user_data = user_data; |
|
| 441 |
|
| 442 g_free(infotext); |
|
| 443 |
|
| 444 if (info->ui_handle != NULL) { |
|
| 445 handles = g_list_append(handles, info); |
|
| 446 |
|
| 447 return info->ui_handle; |
|
| 448 |
|
| 449 } else { |
|
| 450 if (info->cb != NULL) |
|
| 451 info->cb(info->cb_user_data); |
|
| 452 |
|
| 453 g_free(info); |
|
| 454 |
|
| 455 return NULL; |
|
| 456 } |
|
| 457 |
|
| 458 } else { |
|
| 459 if (cb != NULL) |
|
| 460 cb(user_data); |
|
| 461 } |
|
| 462 |
|
| 463 return NULL; |
|
| 464 } |
|
| 465 |
|
| 466 void * |
|
| 467 gaim_notify_uri(void *handle, const char *uri) |
|
| 468 { |
|
| 469 GaimNotifyUiOps *ops; |
|
| 470 |
|
| 471 g_return_val_if_fail(uri != NULL, NULL); |
|
| 472 |
|
| 473 ops = gaim_notify_get_ui_ops(); |
|
| 474 |
|
| 475 if (ops != NULL && ops->notify_uri != NULL) { |
|
| 476 GaimNotifyInfo *info; |
|
| 477 |
|
| 478 info = g_new0(GaimNotifyInfo, 1); |
|
| 479 info->type = GAIM_NOTIFY_URI; |
|
| 480 info->handle = handle; |
|
| 481 info->ui_handle = ops->notify_uri(uri); |
|
| 482 |
|
| 483 if (info->ui_handle != NULL) { |
|
| 484 handles = g_list_append(handles, info); |
|
| 485 |
|
| 486 return info->ui_handle; |
|
| 487 |
|
| 488 } else { |
|
| 489 g_free(info); |
|
| 490 |
|
| 491 return NULL; |
|
| 492 } |
|
| 493 } |
|
| 494 |
|
| 495 return NULL; |
|
| 496 } |
|
| 497 |
|
| 498 void |
|
| 499 gaim_notify_close(GaimNotifyType type, void *ui_handle) |
|
| 500 { |
|
| 501 GList *l; |
|
| 502 GaimNotifyUiOps *ops; |
|
| 503 |
|
| 504 g_return_if_fail(ui_handle != NULL); |
|
| 505 |
|
| 506 ops = gaim_notify_get_ui_ops(); |
|
| 507 |
|
| 508 for (l = handles; l != NULL; l = l->next) { |
|
| 509 GaimNotifyInfo *info = l->data; |
|
| 510 |
|
| 511 if (info->ui_handle == ui_handle) { |
|
| 512 handles = g_list_remove(handles, info); |
|
| 513 |
|
| 514 if (ops != NULL && ops->close_notify != NULL) |
|
| 515 ops->close_notify(info->type, ui_handle); |
|
| 516 |
|
| 517 if (info->cb != NULL) |
|
| 518 info->cb(info->cb_user_data); |
|
| 519 |
|
| 520 g_free(info); |
|
| 521 |
|
| 522 break; |
|
| 523 } |
|
| 524 } |
|
| 525 } |
|
| 526 |
|
| 527 void |
|
| 528 gaim_notify_close_with_handle(void *handle) |
|
| 529 { |
|
| 530 GList *l, *l_next; |
|
| 531 GaimNotifyUiOps *ops; |
|
| 532 |
|
| 533 g_return_if_fail(handle != NULL); |
|
| 534 |
|
| 535 ops = gaim_notify_get_ui_ops(); |
|
| 536 |
|
| 537 for (l = handles; l != NULL; l = l_next) { |
|
| 538 GaimNotifyInfo *info = l->data; |
|
| 539 |
|
| 540 l_next = l->next; |
|
| 541 |
|
| 542 if (info->handle == handle) { |
|
| 543 handles = g_list_remove(handles, info); |
|
| 544 |
|
| 545 if (ops != NULL && ops->close_notify != NULL) |
|
| 546 ops->close_notify(info->type, info->ui_handle); |
|
| 547 |
|
| 548 if (info->cb != NULL) |
|
| 549 info->cb(info->cb_user_data); |
|
| 550 |
|
| 551 g_free(info); |
|
| 552 } |
|
| 553 } |
|
| 554 } |
|
| 555 |
|
| 556 void |
|
| 557 gaim_notify_set_ui_ops(GaimNotifyUiOps *ops) |
|
| 558 { |
|
| 559 notify_ui_ops = ops; |
|
| 560 } |
|
| 561 |
|
| 562 GaimNotifyUiOps * |
|
| 563 gaim_notify_get_ui_ops(void) |
|
| 564 { |
|
| 565 return notify_ui_ops; |
|
| 566 } |
|
| 567 |
|
| 568 void * |
|
| 569 gaim_notify_get_handle(void) |
|
| 570 { |
|
| 571 static int handle; |
|
| 572 |
|
| 573 return &handle; |
|
| 574 } |
|
| 575 |
|
| 576 void |
|
| 577 gaim_notify_init(void) |
|
| 578 { |
|
| 579 gpointer handle = gaim_notify_get_handle(); |
|
| 580 |
|
| 581 gaim_signal_register(handle, "displaying-userinfo", |
|
| 582 gaim_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, |
|
| 583 gaim_value_new(GAIM_TYPE_SUBTYPE, |
|
| 584 GAIM_SUBTYPE_ACCOUNT), |
|
| 585 gaim_value_new(GAIM_TYPE_STRING), |
|
| 586 gaim_value_new_outgoing(GAIM_TYPE_STRING)); |
|
| 587 } |
|
| 588 |
|
| 589 void |
|
| 590 gaim_notify_uninit(void) |
|
| 591 { |
|
| 592 gaim_signals_unregister_by_instance(gaim_notify_get_handle()); |
|
| 593 } |
|