1 /*
2 * tabkey.c: completion for /msg and public chats
3 *
4 * Copyright(c) 1997-2000 - All Rights Reserved
5 *
6 * See the COPYRIGHT file.
7 */
8
9 #ifndef lint
10 static char rcsid[] = "@(#)$Id: tabkey.c,v 1.14 2000/07/31 22:33:56 kalt Exp $";
11 #endif
12
13 #include "os.h"
14
15 #include "struct.h"
16 #include "option.h"
17
18 extern struct server_ *server;
19
20 struct nlist_
21 {
22 char *nick;
23 char *uh;
24 time_t ts;
25 struct nlist_ *nextn;
26 struct server_ *svr;
27 };
28
29 static struct nlist_ *tablist = NULL, *tabnext = NULL;
30 static struct nlist_ *spacelist = NULL, *spacenext = NULL;
31
32 static time_t lastg = 0;
33
34 static void
nlist_collect(list)35 nlist_collect(list)
36 struct nlist_ **list;
37 {
38 struct nlist_ **ntmp = list, *del;
39
40 lastg = time(NULL);
41 while (*ntmp)
42 {
43 if ((lastg - (del = (*ntmp))->ts) > 3600)
44 {
45 /* no need to worry about nicknext here */
46 *ntmp = del->nextn;
47 free(del->nick);
48 if (del->uh)
49 free(del->uh);
50 free(del);
51 }
52 else
53 ntmp = &((*ntmp)->nextn);
54 }
55 }
56
57 static char
real_add(list,next,nick,uh)58 real_add(list, next, nick, uh)
59 char *nick, *uh;
60 struct nlist_ **list, **next;
61 {
62 struct nlist_ **ntmp = list, *top;
63 char rc = 0;
64
65 while (*ntmp)
66 {
67 if (!strcasecmp((*ntmp)->nick, nick) && (*ntmp)->svr == server)
68 break;
69 ntmp = &((*ntmp)->nextn);
70 }
71 if (*ntmp)
72 {
73 (*ntmp)->nick = strdup(nick);
74 top = *ntmp;
75 *ntmp = top->nextn;
76 if (uh && *uh && strcmp(top->uh, uh))
77 {
78 free(top->uh);
79 top->uh = strdup(uh);
80 rc = 1;
81 }
82 else if ((time(NULL) - top->ts) > 600)
83 rc = 1;
84 }
85 else
86 {
87 top = (struct nlist_ *) malloc(sizeof(struct nlist_));
88 top->nick = strdup(nick);
89 top->uh = (uh) ? strdup(uh) : NULL;
90 top->svr = server;
91 rc = 1;
92 }
93 top->ts = time(NULL);
94 top->nextn = *list;
95 *list = top;
96 *next = NULL;
97 if ((time(NULL) - lastg) > 1800)
98 nlist_collect(list);
99 return rc;
100 }
101
102 /* tab_add: adds a nickname/servicename to the list.
103 * uh is the nick's u@h, or "" if irrelevant (DCC, unknown)
104 * uh is NULL for services.
105 */
106 char
tab_add(nick,uh)107 tab_add(nick, uh)
108 char *nick, *uh;
109 {
110 return real_add(&tablist, &tabnext, nick, uh);
111 }
112
113 /* space_add: adds a nickname to the list.
114 * uh should be ""
115 */
116 char
space_add(nick,uh)117 space_add(nick, uh)
118 char *nick, *uh;
119 {
120 assert (*uh == '\0');
121
122 return real_add(&spacelist, &spacenext, nick, uh);
123 }
124
125 static char *
real_get(list,next)126 real_get(list, next)
127 struct nlist_ *list, **next;
128 {
129 struct nlist_ *loop = (*next) ? *next : list;
130 int looped = 0;
131 struct server_ *smatch = server;
132 static char eresult[512];
133
134 if (list == tablist && get_option(Z_ETABKEY, NULL))
135 smatch = NULL;
136
137 do
138 {
139 if (*next == loop)
140 looped += 1;
141 if (*next)
142 {
143 if ((*next = (*next)->nextn) == NULL)
144 *next = list;
145 }
146 else
147 *next = list;
148 }
149 while ((!*next || ((smatch != NULL && (*next)->svr != smatch)
150 && *((*next)->nick) != '='))
151 && looped <= 1);
152
153 if (*next && (*next)->uh == NULL)
154 strcpy(eresult, "@"); /* service */
155 else
156 eresult[0] = '\0'; /* nickname / dcc chat */
157
158 if (smatch != NULL)
159 {
160 if (*next && ((*next)->svr == server || *((*next)->nick) == '='))
161 strcat(eresult, (*next)->nick);
162 else
163 eresult[0] = '\0';
164 }
165 else
166 if (*next)
167 {
168 if (*eresult == '@')
169 strcat(eresult, (*next)->nick);
170 else if ((*next)->nick[0] == '=')
171 strcpy(eresult, (*next)->nick);
172 else
173 sprintf(eresult, "%s@[%s]", (*next)->nick, (*next)->svr->sname);
174 }
175 else
176 eresult[0] = '\0';
177
178 return eresult;
179 }
180
181 /* tab_get: returns next nickname in the list. (services prefixed with @) */
182 char *
tab_get()183 tab_get()
184 {
185 return real_get(tablist, &tabnext);
186 }
187
188 /* space_get: returns next nickname in the list */
189 char *
space_get()190 space_get()
191 {
192 return real_get(spacelist, &spacenext);
193 }
194