/* * tabkey.c: completion for /msg and public chats * * Copyright(c) 1997-2000 - All Rights Reserved * * See the COPYRIGHT file. */ #ifndef lint static char rcsid[] = "@(#)$Id: tabkey.c,v 1.14 2000/07/31 22:33:56 kalt Exp $"; #endif #include "os.h" #include "struct.h" #include "option.h" extern struct server_ *server; struct nlist_ { char *nick; char *uh; time_t ts; struct nlist_ *nextn; struct server_ *svr; }; static struct nlist_ *tablist = NULL, *tabnext = NULL; static struct nlist_ *spacelist = NULL, *spacenext = NULL; static time_t lastg = 0; static void nlist_collect(list) struct nlist_ **list; { struct nlist_ **ntmp = list, *del; lastg = time(NULL); while (*ntmp) { if ((lastg - (del = (*ntmp))->ts) > 3600) { /* no need to worry about nicknext here */ *ntmp = del->nextn; free(del->nick); if (del->uh) free(del->uh); free(del); } else ntmp = &((*ntmp)->nextn); } } static char real_add(list, next, nick, uh) char *nick, *uh; struct nlist_ **list, **next; { struct nlist_ **ntmp = list, *top; char rc = 0; while (*ntmp) { if (!strcasecmp((*ntmp)->nick, nick) && (*ntmp)->svr == server) break; ntmp = &((*ntmp)->nextn); } if (*ntmp) { (*ntmp)->nick = strdup(nick); top = *ntmp; *ntmp = top->nextn; if (uh && *uh && strcmp(top->uh, uh)) { free(top->uh); top->uh = strdup(uh); rc = 1; } else if ((time(NULL) - top->ts) > 600) rc = 1; } else { top = (struct nlist_ *) malloc(sizeof(struct nlist_)); top->nick = strdup(nick); top->uh = (uh) ? strdup(uh) : NULL; top->svr = server; rc = 1; } top->ts = time(NULL); top->nextn = *list; *list = top; *next = NULL; if ((time(NULL) - lastg) > 1800) nlist_collect(list); return rc; } /* tab_add: adds a nickname/servicename to the list. * uh is the nick's u@h, or "" if irrelevant (DCC, unknown) * uh is NULL for services. */ char tab_add(nick, uh) char *nick, *uh; { return real_add(&tablist, &tabnext, nick, uh); } /* space_add: adds a nickname to the list. * uh should be "" */ char space_add(nick, uh) char *nick, *uh; { assert (*uh == '\0'); return real_add(&spacelist, &spacenext, nick, uh); } static char * real_get(list, next) struct nlist_ *list, **next; { struct nlist_ *loop = (*next) ? *next : list; int looped = 0; struct server_ *smatch = server; static char eresult[512]; if (list == tablist && get_option(Z_ETABKEY, NULL)) smatch = NULL; do { if (*next == loop) looped += 1; if (*next) { if ((*next = (*next)->nextn) == NULL) *next = list; } else *next = list; } while ((!*next || ((smatch != NULL && (*next)->svr != smatch) && *((*next)->nick) != '=')) && looped <= 1); if (*next && (*next)->uh == NULL) strcpy(eresult, "@"); /* service */ else eresult[0] = '\0'; /* nickname / dcc chat */ if (smatch != NULL) { if (*next && ((*next)->svr == server || *((*next)->nick) == '=')) strcat(eresult, (*next)->nick); else eresult[0] = '\0'; } else if (*next) { if (*eresult == '@') strcat(eresult, (*next)->nick); else if ((*next)->nick[0] == '=') strcpy(eresult, (*next)->nick); else sprintf(eresult, "%s@[%s]", (*next)->nick, (*next)->svr->sname); } else eresult[0] = '\0'; return eresult; } /* tab_get: returns next nickname in the list. (services prefixed with @) */ char * tab_get() { return real_get(tablist, &tabnext); } /* space_get: returns next nickname in the list */ char * space_get() { return real_get(spacelist, &spacenext); }