/*
* 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);
}
syntax highlighted by Code2HTML, v. 0.9.1