diff options
Diffstat (limited to 'src/irc/core/modes.c')
-rw-r--r-- | src/irc/core/modes.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c index 994a55f3..5c4a45da 100644 --- a/src/irc/core/modes.c +++ b/src/irc/core/modes.c @@ -46,8 +46,12 @@ static void nick_mode_change(IRC_CHANNEL_REC *channel, const char *nick, if (mode == '@') nickrec->op = type == '+'; else if (mode == '+') nickrec->voice = type == '+'; else if (mode == '%') nickrec->halfop = type == '+'; - else if (channel->server->prefix[(unsigned char) mode] != '\0') - nickrec->other = (type == '+' ? mode : '\0'); + if (channel->server->prefix[(unsigned char) mode] != '\0') { + if (type == '+') + prefix_add(nickrec->prefixes, mode, (SERVER_REC *) channel->server); + else + prefix_del(nickrec->prefixes, mode); + } modestr[0] = mode; modestr[1] = '\0'; typestr[0] = type; typestr[1] = '\0'; @@ -55,6 +59,57 @@ static void nick_mode_change(IRC_CHANNEL_REC *channel, const char *nick, channel, nickrec, setby, modestr, typestr); } +void prefix_add(char *prefixes, char newprefix, SERVER_REC *server) +{ + const char *prefixlst; + char newprefixes[MAX_USER_PREFIXES+1]; /* to hold the new prefixes */ + unsigned int newpos = 0; /* to hold our position in the new prefixes */ + unsigned int oldpos = 0; /* to hold our position in the old prefixes */ + + prefixlst = server->get_nick_flags(server); + + /* go through the possible prefixes, copy higher ones, and find this one's place + * always leave room for the current prefix to be added, though. + */ + while (*prefixlst != '\0' && prefixes[oldpos] != '\0' && + newpos < MAX_USER_PREFIXES - 1) { + if (prefixes[oldpos] == newprefix) + return; /* already inserted. why are we here? */ + + if (*prefixlst == newprefix) + break; /* insert the new prefix here */ + + if (*prefixlst == prefixes[oldpos]) { + /* this prefix is present. + * the one we are inserting goes after it. + * copy it over, and continue searching. + */ + newprefixes[newpos++] = prefixes[oldpos++]; + } + prefixlst++; + } + + /* newpos is now the position in which we wish to insert the prefix */ + newprefixes[newpos++] = newprefix; + + /* finish copying the remaining prefixes */ + while (prefixes[oldpos] != '\0' && newpos < MAX_USER_PREFIXES) + newprefixes[newpos++] = prefixes[oldpos++]; + + newprefixes[newpos] = '\0'; + + memcpy(prefixes, newprefixes, sizeof(prefixes)); +} + +void prefix_del(char *prefixes, char oldprefix) +{ + char *todel; + + todel = strchr(prefixes, oldprefix); + if (todel) + memmove(todel, todel+1, strlen(todel)); +} + static int mode_is_set(const char *str, char mode) { char *end, *pos; |