configure: add stuff for spell checking
[rofl0r-ixchat.git] / src / common / notify.c
blob04795849640ccbf25bbb72c4184b7405891215ba
1 /* X-Chat
2 * Copyright (C) 1998 Peter Zelezny.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <time.h>
28 #include "xchat.h"
29 #include "notify.h"
30 #include "cfgfiles.h"
31 #include "fe.h"
32 #include "server.h"
33 #include "text.h"
34 #include "util.h"
35 #include "xchatc.h"
38 GSList *notify_list = 0;
39 int notify_tag = 0;
42 static char *
43 despacify_dup (char *str)
45 char *p, *res = malloc (strlen (str) + 1);
47 p = res;
48 while (1)
50 if (*str != ' ')
52 *p = *str;
53 if (*p == 0)
54 return res;
55 p++;
57 str++;
61 static int
62 notify_netcmp (char *str, void *serv)
64 char *net = despacify_dup (server_get_network (serv, TRUE));
66 if (rfc_casecmp (str, net) == 0)
68 free (net);
69 return 0; /* finish & return FALSE from token_foreach() */
72 free (net);
73 return 1; /* keep going... */
76 /* monitor this nick on this particular network? */
78 static gboolean
79 notify_do_network (struct notify *notify, server *serv)
81 if (!notify->networks) /* ALL networks for this nick */
82 return TRUE;
84 if (token_foreach (notify->networks, ',', notify_netcmp, serv))
85 return FALSE; /* network list doesn't contain this one */
87 return TRUE;
90 struct notify_per_server *
91 notify_find_server_entry (struct notify *notify, struct server *serv)
93 GSList *list = notify->server_list;
94 struct notify_per_server *servnot;
96 while (list)
98 servnot = (struct notify_per_server *) list->data;
99 if (servnot->server == serv)
100 return servnot;
101 list = list->next;
104 /* not found, should we add it, or is this not a network where
105 we're monitoring this nick? */
106 if (!notify_do_network (notify, serv))
107 return NULL;
109 servnot = malloc (sizeof (struct notify_per_server));
110 if (servnot)
112 memset (servnot, 0, sizeof (struct notify_per_server));
113 servnot->server = serv;
114 servnot->notify = notify;
115 notify->server_list = g_slist_prepend (notify->server_list, servnot);
117 return servnot;
120 void
121 notify_save (void)
123 int fh;
124 struct notify *notify;
125 GSList *list = notify_list;
127 fh = xchat_open_file ("notify.conf", O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
128 if (fh != -1)
130 while (list)
132 notify = (struct notify *) list->data;
133 write (fh, notify->name, strlen (notify->name));
134 if (notify->networks)
136 write (fh, " ", 1);
137 write (fh, notify->networks, strlen (notify->networks));
139 write (fh, "\n", 1);
140 list = list->next;
142 close (fh);
146 void
147 notify_load (void)
149 int fh;
150 char buf[256];
151 char *sep;
153 fh = xchat_open_file ("notify.conf", O_RDONLY, 0, 0);
154 if (fh != -1)
156 while (waitline (fh, buf, sizeof buf, FALSE) != -1)
158 if (buf[0] != '#' && buf[0] != 0)
160 sep = strchr (buf, ' ');
161 if (sep)
163 sep[0] = 0;
164 notify_adduser (buf, sep + 1);
166 else
167 notify_adduser (buf, NULL);
170 close (fh);
174 static struct notify_per_server *
175 notify_find (server *serv, char *nick)
177 GSList *list = notify_list;
178 struct notify_per_server *servnot;
179 struct notify *notify;
181 while (list)
183 notify = (struct notify *) list->data;
185 servnot = notify_find_server_entry (notify, serv);
186 if (!servnot)
188 list = list->next;
189 continue;
192 if (!serv->p_cmp (notify->name, nick))
193 return servnot;
195 list = list->next;
198 return 0;
201 static void
202 notify_announce_offline (server * serv, struct notify_per_server *servnot,
203 char *nick, int quiet)
205 session *sess;
207 sess = serv->front_session;
209 servnot->ison = FALSE;
210 servnot->lastoff = time (0);
211 if (!quiet)
212 EMIT_SIGNAL (XP_TE_NOTIFYOFFLINE, sess, nick, serv->servername,
213 server_get_network (serv, TRUE), NULL, 0);
214 fe_notify_update (nick);
215 fe_notify_update (0);
218 static void
219 notify_announce_online (server * serv, struct notify_per_server *servnot,
220 char *nick)
222 session *sess;
224 sess = serv->front_session;
226 servnot->lastseen = time (0);
227 if (servnot->ison)
228 return;
230 servnot->ison = TRUE;
231 servnot->laston = time (0);
232 EMIT_SIGNAL (XP_TE_NOTIFYONLINE, sess, nick, serv->servername,
233 server_get_network (serv, TRUE), NULL, 0);
234 fe_notify_update (nick);
235 fe_notify_update (0);
237 if (prefs.whois_on_notifyonline)
240 /* Let's do whois with idle time (like in /quote WHOIS %s %s) */
242 char *wii_str = malloc (strlen (nick) * 2 + 2);
243 sprintf (wii_str, "%s %s", nick, nick);
244 serv->p_whois (serv, wii_str);
245 free (wii_str);
249 /* handles numeric 601 */
251 void
252 notify_set_offline (server * serv, char *nick, int quiet)
254 struct notify_per_server *servnot;
256 servnot = notify_find (serv, nick);
257 if (!servnot)
258 return;
260 notify_announce_offline (serv, servnot, nick, quiet);
263 /* handles numeric 604 and 600 */
265 void
266 notify_set_online (server * serv, char *nick)
268 struct notify_per_server *servnot;
270 servnot = notify_find (serv, nick);
271 if (!servnot)
272 return;
274 notify_announce_online (serv, servnot, nick);
277 static void
278 notify_watch (server * serv, char *nick, int add)
280 char tbuf[256];
282 snprintf (tbuf, sizeof (tbuf), "WATCH +%s", nick);
283 if (!add)
284 tbuf[6] = '-';
285 serv->p_raw (serv, tbuf);
288 static void
289 notify_watch_all (struct notify *notify, int add)
291 server *serv;
292 GSList *list = serv_list;
293 while (list)
295 serv = list->data;
296 if (serv->connected && serv->end_of_motd && serv->supports_watch &&
297 notify_do_network (notify, serv))
298 notify_watch (serv, notify->name, add);
299 list = list->next;
303 static void
304 notify_flush_watches (server * serv, GSList *from, GSList *end)
306 char tbuf[512];
307 GSList *list;
308 struct notify *notify;
310 strcpy (tbuf, "WATCH");
312 list = from;
313 while (list != end)
315 notify = list->data;
316 strcat (tbuf, " +");
317 strcat (tbuf, notify->name);
318 list = list->next;
320 serv->p_raw (serv, tbuf);
323 /* called when logging in. e.g. when End of motd. */
325 void
326 notify_send_watches (server * serv)
328 struct notify *notify;
329 GSList *list;
330 GSList *point;
331 int len;
333 len = 0;
334 point = list = notify_list;
335 while (list)
337 notify = list->data;
339 if (notify_do_network (notify, serv))
341 len += strlen (notify->name) + 2 /* + and space */;
342 if (len > 500)
344 notify_flush_watches (serv, point, list);
345 len = strlen (notify->name) + 2;
346 point = list;
350 list = list->next;
353 if (point)
354 notify_flush_watches (serv, point, NULL);
357 /* called when receiving a ISON 303 - should this func go? */
359 void
360 notify_markonline (server *serv, char *word[])
362 struct notify *notify;
363 struct notify_per_server *servnot;
364 GSList *list = notify_list;
365 int i, seen;
367 while (list)
369 notify = (struct notify *) list->data;
370 servnot = notify_find_server_entry (notify, serv);
371 if (!servnot)
373 list = list->next;
374 continue;
376 i = 4;
377 seen = FALSE;
378 while (*word[i])
380 if (!serv->p_cmp (notify->name, word[i]))
382 seen = TRUE;
383 notify_announce_online (serv, servnot, notify->name);
384 break;
386 i++;
387 /* FIXME: word[] is only a 32 element array, limits notify list to
388 about 27 people */
389 if (i > PDIWORDS - 5)
391 /*fprintf (stderr, _("*** XCHAT WARNING: notify list too large.\n"));*/
392 break;
395 if (!seen && servnot->ison)
397 notify_announce_offline (serv, servnot, notify->name, FALSE);
399 list = list->next;
401 fe_notify_update (0);
404 /* yuck! Old routine for ISON notify */
406 static void
407 notify_checklist_for_server (server *serv)
409 char outbuf[512];
410 struct notify *notify;
411 GSList *list = notify_list;
412 int i = 0;
414 strcpy (outbuf, "ISON ");
415 while (list)
417 notify = list->data;
418 if (notify_do_network (notify, serv))
420 i++;
421 strcat (outbuf, notify->name);
422 strcat (outbuf, " ");
423 if (strlen (outbuf) > 460)
425 /* LAME: we can't send more than 512 bytes to the server, but *
426 * if we split it in two packets, our offline detection wouldn't *
427 work */
428 /*fprintf (stderr, _("*** XCHAT WARNING: notify list too large.\n"));*/
429 break;
432 list = list->next;
435 if (i)
436 serv->p_raw (serv, outbuf);
440 notify_checklist (void) /* check ISON list */
442 struct server *serv;
443 GSList *list = serv_list;
445 while (list)
447 serv = list->data;
448 if (serv->connected && serv->end_of_motd && !serv->supports_watch)
450 notify_checklist_for_server (serv);
452 list = list->next;
454 return 1;
457 void
458 notify_showlist (struct session *sess)
460 char outbuf[256];
461 struct notify *notify;
462 GSList *list = notify_list;
463 struct notify_per_server *servnot;
464 int i = 0;
466 EMIT_SIGNAL (XP_TE_NOTIFYHEAD, sess, NULL, NULL, NULL, NULL, 0);
467 while (list)
469 i++;
470 notify = (struct notify *) list->data;
471 servnot = notify_find_server_entry (notify, sess->server);
472 if (servnot && servnot->ison)
473 snprintf (outbuf, sizeof (outbuf), _(" %-20s online\n"), notify->name);
474 else
475 snprintf (outbuf, sizeof (outbuf), _(" %-20s offline\n"), notify->name);
476 PrintText (sess, outbuf);
477 list = list->next;
479 if (i)
481 sprintf (outbuf, "%d", i);
482 EMIT_SIGNAL (XP_TE_NOTIFYNUMBER, sess, outbuf, NULL, NULL, NULL, 0);
483 } else
484 EMIT_SIGNAL (XP_TE_NOTIFYEMPTY, sess, NULL, NULL, NULL, NULL, 0);
488 notify_deluser (char *name)
490 struct notify *notify;
491 struct notify_per_server *servnot;
492 GSList *list = notify_list;
494 while (list)
496 notify = (struct notify *) list->data;
497 if (!rfc_casecmp (notify->name, name))
499 fe_notify_update (notify->name);
500 /* Remove the records for each server */
501 while (notify->server_list)
503 servnot = (struct notify_per_server *) notify->server_list->data;
504 notify->server_list =
505 g_slist_remove (notify->server_list, servnot);
506 free (servnot);
508 notify_list = g_slist_remove (notify_list, notify);
509 notify_watch_all (notify, FALSE);
510 if (notify->networks)
511 free (notify->networks);
512 free (notify->name);
513 free (notify);
514 fe_notify_update (0);
515 return 1;
517 list = list->next;
519 return 0;
522 void
523 notify_adduser (char *name, char *networks)
525 struct notify *notify = malloc (sizeof (struct notify));
526 if (notify)
528 memset (notify, 0, sizeof (struct notify));
529 if (strlen (name) >= NICKLEN)
531 notify->name = malloc (NICKLEN);
532 safe_strcpy (notify->name, name, NICKLEN);
533 } else
535 notify->name = strdup (name);
537 if (networks)
538 notify->networks = despacify_dup (networks);
539 notify->server_list = 0;
540 notify_list = g_slist_prepend (notify_list, notify);
541 notify_checklist ();
542 fe_notify_update (notify->name);
543 fe_notify_update (0);
544 notify_watch_all (notify, TRUE);
548 gboolean
549 notify_is_in_list (server *serv, char *name)
551 struct notify *notify;
552 GSList *list = notify_list;
554 while (list)
556 notify = (struct notify *) list->data;
557 if (!serv->p_cmp (notify->name, name))
558 return TRUE;
559 list = list->next;
562 return FALSE;
566 notify_isnotify (struct session *sess, char *name)
568 struct notify *notify;
569 struct notify_per_server *servnot;
570 GSList *list = notify_list;
572 while (list)
574 notify = (struct notify *) list->data;
575 if (!sess->server->p_cmp (notify->name, name))
577 servnot = notify_find_server_entry (notify, sess->server);
578 if (servnot && servnot->ison)
579 return TRUE;
581 list = list->next;
584 return FALSE;
587 void
588 notify_cleanup ()
590 GSList *list = notify_list;
591 GSList *nslist, *srvlist;
592 struct notify *notify;
593 struct notify_per_server *servnot;
594 struct server *serv;
595 int valid;
597 while (list)
599 /* Traverse the list of notify structures */
600 notify = (struct notify *) list->data;
601 nslist = notify->server_list;
602 while (nslist)
604 /* Look at each per-server structure */
605 servnot = (struct notify_per_server *) nslist->data;
607 /* Check the server is valid */
608 valid = FALSE;
609 srvlist = serv_list;
610 while (srvlist)
612 serv = (struct server *) srvlist->data;
613 if (servnot->server == serv)
615 valid = serv->connected; /* Only valid if server is too */
616 break;
618 srvlist = srvlist->next;
620 if (!valid)
622 notify->server_list =
623 g_slist_remove (notify->server_list, servnot);
624 free (servnot);
625 nslist = notify->server_list;
626 } else
628 nslist = nslist->next;
631 list = list->next;
633 fe_notify_update (0);