]>
Commit | Line | Data |
---|---|---|
dd33b9ca GB |
1 | #include <string.h> |
2 | #include <assert.h> | |
8471c9df | 3 | #include <stdint.h> |
01897a81 | 4 | #include "../lib/version.h" |
dd33b9ca GB |
5 | #include "../nick/nick.h" |
6 | #include "../chanindex/chanindex.h" | |
7 | #include "../channel/channel.h" | |
8 | #include "../core/hooks.h" | |
9 | #include "whowas.h" | |
10 | ||
01897a81 GB |
11 | MODULE_VERSION(""); |
12 | ||
dd33b9ca GB |
13 | static int wwcnext, wwccext; |
14 | ||
15 | static void wwc_refchannel(chanindex *cip) { | |
16 | uintptr_t *refcount = (uintptr_t *)&cip->exts[wwccext]; | |
17 | (*refcount)++; | |
18 | } | |
19 | ||
20 | static void wwc_derefchannel(chanindex *cip) { | |
21 | uintptr_t *refcount = (uintptr_t *)&cip->exts[wwccext]; | |
22 | (*refcount)--; | |
23 | ||
dd33b9ca GB |
24 | if (*refcount == 0) |
25 | releasechanindex(cip); | |
26 | } | |
27 | ||
28 | static void wwc_hook_joincreate(int hooknum, void *arg) { | |
29 | void **args = arg; | |
30 | channel *cp = args[0]; | |
31 | nick *np = args[1]; | |
32 | chanindex **wchans = np->exts[wwcnext]; | |
33 | ||
34 | if (!wchans) { | |
35 | wchans = calloc(sizeof(chanindex *), WW_MAXCHANNELS); | |
36 | np->exts[wwcnext] = wchans; | |
37 | } | |
38 | ||
39 | wwc_refchannel(cp->index); | |
40 | ||
41 | memmove(&wchans[1], &wchans[0], sizeof(chanindex *) * (WW_MAXCHANNELS - 1)); | |
42 | wchans[0] = cp->index; | |
43 | } | |
44 | ||
45 | static void wwc_hook_lostnick(int hooknum, void *arg) { | |
46 | nick *np = arg; | |
47 | chanindex **wchans = np->exts[wwcnext]; | |
48 | int i; | |
49 | ||
50 | if (!wchans) | |
51 | return; | |
52 | ||
53 | for (i = 0; i < WW_MAXCHANNELS; i++) { | |
54 | if (!wchans[i]) | |
55 | break; | |
56 | ||
57 | wwc_derefchannel(wchans[i]); | |
58 | } | |
59 | ||
60 | free(wchans); | |
84751a9d | 61 | np->exts[wwcnext] = NULL; |
dd33b9ca GB |
62 | } |
63 | ||
64 | static void wwc_hook_newrecord(int hooknum, void *arg) { | |
65 | void **args = arg; | |
66 | whowas *ww = args[0]; | |
67 | nick *np = args[1]; | |
68 | chanindex **wchans = np->exts[wwcnext]; | |
69 | int i; | |
70 | ||
71 | memset(ww->channels, 0, sizeof(ww->channels)); | |
72 | ||
73 | if (!wchans) | |
74 | return; | |
75 | ||
76 | for (i = 0; i < WW_MAXCHANNELS; i++) { | |
77 | if (!wchans[i]) | |
78 | break; | |
79 | ||
80 | wwc_refchannel(wchans[i]); | |
81 | ww->channels[i] = wchans[i]; | |
82 | } | |
83 | } | |
84 | ||
85 | static void wwc_hook_lostrecord(int hooknum, void *arg) { | |
86 | whowas *ww = arg; | |
87 | int i; | |
88 | ||
89 | for (i = 0; i < WW_MAXCHANNELS; i++) { | |
90 | if (!ww->channels[i]) | |
91 | break; | |
92 | ||
93 | wwc_derefchannel(ww->channels[i]); | |
94 | } | |
95 | } | |
96 | ||
97 | void _init(void) { | |
98 | wwcnext = registernickext("whowas_channels"); | |
99 | wwccext = registerchanext("whowas_channels"); | |
100 | ||
101 | registerhook(HOOK_CHANNEL_JOIN, &wwc_hook_joincreate); | |
102 | registerhook(HOOK_CHANNEL_CREATE, &wwc_hook_joincreate); | |
103 | registerhook(HOOK_NICK_LOSTNICK, &wwc_hook_lostnick); | |
104 | registerhook(HOOK_WHOWAS_NEWRECORD, &wwc_hook_newrecord); | |
105 | registerhook(HOOK_WHOWAS_LOSTRECORD, &wwc_hook_lostrecord); | |
106 | } | |
107 | ||
108 | void _fini(void) { | |
109 | releasenickext(wwcnext); | |
110 | releasechanext(wwccext); | |
111 | ||
112 | deregisterhook(HOOK_CHANNEL_JOIN, &wwc_hook_joincreate); | |
113 | deregisterhook(HOOK_CHANNEL_CREATE, &wwc_hook_joincreate); | |
114 | deregisterhook(HOOK_NICK_LOSTNICK, &wwc_hook_lostnick); | |
115 | deregisterhook(HOOK_WHOWAS_NEWRECORD, &wwc_hook_newrecord); | |
116 | deregisterhook(HOOK_WHOWAS_LOSTRECORD, &wwc_hook_lostrecord); | |
117 | } |