commit 6c59c626b1330d21ab6298e57a55e9568472a3e4
parent f6e41f6af8e9d3e8c07ba722d00679840324285f
Author: hhvn <dev@hhvn.uk>
Date: Mon, 25 Oct 2021 15:38:39 +0100
handle.c hirc.h nick.c: sorted nicklist, and fixed NICK handling
Diffstat:
M | handle.c | | | 5 | ++++- |
M | hirc.h | | | 1 | + |
M | nick.c | | | 94 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 99 insertions(+), 1 deletion(-)
diff --git a/handle.c b/handle.c
@@ -253,6 +253,7 @@ void
handle_NICK(char *msg, char **params, struct Server *server, time_t timestamp) {
struct Nick *nick, *chnick;
struct Channel *chan;
+ char prefix[128];
char *newnick;
if (**params != ':' || !*(params+1) || !*(params+2))
@@ -273,7 +274,9 @@ handle_NICK(char *msg, char **params, struct Server *server, time_t timestamp) {
for (chan = server->channels; chan; chan = chan->next) {
if ((chnick = nick_get(&chan->nicks, nick->nick)) != NULL) {
- nick_add(&chan->nicks, newnick, chnick->priv, server);
+ snprintf(prefix, sizeof(prefix), ":%s!%s@%s",
+ newnick, chnick->ident, chnick->host);
+ nick_add(&chan->nicks, prefix, chnick->priv, server);
nick_remove(&chan->nicks, nick->nick);
if (selected.channel == chan)
ui_draw_nicklist();
diff --git a/hirc.h b/hirc.h
@@ -45,6 +45,7 @@ int nick_isself(struct Nick *nick);
int nick_isself_server(struct Nick *nick, struct Server *server);
int nick_remove(struct Nick **head, char *nick);
char * nick_strprefix(struct Nick *nick);
+void nick_sort(struct Nick **head, struct Server *server);
/* hist.c */
void hist_free(struct History *history);
diff --git a/nick.c b/nick.c
@@ -2,6 +2,7 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "hirc.h"
#define MAX(var1, var2) (var1 > var2 ? var1 : var2)
@@ -136,6 +137,7 @@ nick_add(struct Nick **head, char *prefix, char priv, struct Server *server) {
p->next = nick;
nick->prev = p;
+ nick_sort(head, server);
return nick;
}
@@ -199,3 +201,95 @@ nick_strprefix(struct Nick *nick) {
return ret;
}
+
+static void
+nick_swap(struct Nick **head, struct Nick *first, struct Nick *second) {
+ struct Nick *next[2];
+ struct Nick *prev[2];
+
+ next[0] = first->next != second ? first->next : first;
+ next[1] = second->next != first ? second->next : second;
+ prev[0] = first->prev != second ? first->prev : first;
+ prev[1] = second->prev != first ? second->prev : second;
+
+ if (*head == first)
+ *head = second;
+ else if (*head == second)
+ *head = first;
+
+ first->next = next[1];
+ first->prev = prev[1];
+ if (first->next)
+ first->next->prev = first;
+ if (first->prev)
+ first->prev->next = first;
+
+ second->next = next[0];
+ second->prev = prev[0];
+ if (second->next)
+ second->next->prev = second;
+ if (second->prev)
+ second->prev->next = second;
+}
+
+enum {
+ S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, S_8, S_9,
+ S_a, S_b, S_c, S_d, S_e, S_f, S_g, S_h, S_i, S_j, S_k,
+ S_l, S_m, S_n, S_o, S_p, S_q, S_r, S_s, S_t, S_u, S_v,
+ S_dash, S_lbrace, S_rbrace, S_pipe, S_grave, S_caret,
+ S_null,
+};
+
+void
+nick_sort(struct Nick **head, struct Server *server) {
+ char *supportedprivs, *s[2];
+ struct Nick *p, *next;
+ int i, swapped;
+ int map[CHAR_MAX] = {
+ ['\0'] = S_null,
+ ['-'] = S_dash,
+ ['{'] = S_lbrace, ['['] = S_lbrace,
+ ['}'] = S_rbrace, ['}'] = S_rbrace,
+ ['|'] = S_pipe, ['\\'] = S_pipe,
+ ['`'] = S_grave,
+ ['^'] = S_caret,
+ ['a'] = S_a, S_b, S_c, S_d, S_e, S_f,
+ S_g, S_h, S_i, S_j, S_k, S_l,
+ S_m, S_n, S_o, S_p, S_q, S_r,
+ S_s, S_t, S_u, S_v,
+ ['A'] = S_a, S_b, S_c, S_d, S_e, S_f,
+ S_g, S_h, S_i, S_j, S_k, S_l,
+ S_m, S_n, S_o, S_p, S_q, S_r,
+ S_s, S_t, S_u, S_v,
+ ['0'] = S_0, S_1, S_2, S_3, S_4, S_5,
+ S_6, S_7, S_8, S_9,
+ };
+
+ supportedprivs = strchr(support_get(server, "PREFIX"), ')');
+ if (supportedprivs == NULL || supportedprivs[0] == '\0')
+ supportedprivs = "";
+ else
+ supportedprivs++;
+
+ for (i=0; *supportedprivs; supportedprivs++)
+ map[*supportedprivs] = S_0 - i;
+
+ /* TODO: something better than bubblesort */
+ do {
+ swapped = 0;
+ for (p = (*head)->next; p; p = next) {
+ next = p->next;
+ if (map[p->priv] < map[p->prev->priv]) {
+ nick_swap(head, p, p->prev);
+ swapped = 1;
+ } else {
+ for (s[0] = p->nick, s[1] = p->prev->nick; s[0] && s[1] && map[*s[0]] == map[*s[1]]; s[0]++, s[1]++);
+ if (s[0] && s[1] && map[*s[0]] < map[*s[1]]) {
+ nick_swap(head, p, p->prev);
+ swapped = 1;
+ }
+ }
+ }
+ } while (swapped);
+ ui_draw_nicklist();
+}