Suppress pointless display of oplevels in ?chaninfo.
authorMichael Poole <mdpoole@troilus.org>
Mon, 15 Feb 2010 22:12:11 +0000 (17:12 -0500)
committerMichael Poole <mdpoole@troilus.org>
Mon, 15 Feb 2010 22:12:11 +0000 (17:12 -0500)
src/hash.* (modeNode_sort): Create as a "natural" sort order.
src/proto-p10.c (modeNode_sort): Rename to modeNode_sort_p10.
src/opserv.c (cmd_chaninfo): Clone and sort the membership array.  Only
    display oplevels if at least one member has a non-default oplevel.

src/hash.c
src/hash.h
src/opserv.c
src/proto-p10.c

index 5a8df93dd53c23f75145ef77976000b67315a230..c214cffcfee5a346bfe59466779115705b5f8886 100644 (file)
@@ -517,6 +517,33 @@ AddChannelUser(struct userNode *user, struct chanNode* channel)
         return mNode;
 }
 
+/* Return negative if *(struct modeNode**)pa is "less than" pb,
+ * positive if pa is "larger than" pb.  Comparison is based on sorting
+ * so that non-voiced/non-opped users are first, voiced-only users are
+ * next, and the "strongest" oplevels are before "weaker" oplevels.
+ * Within those sets, ordering is arbitrary.
+ */
+int
+modeNode_sort(const void *pa, const void *pb)
+{
+        struct modeNode *a = *(struct modeNode**)pa;
+        struct modeNode *b = *(struct modeNode**)pb;
+
+        if (a->modes & MODE_CHANOP) {
+            if (!(b->modes & MODE_CHANOP))
+                return -1;
+            else if ((b->modes & MODE_VOICE) != (a->modes & MODE_VOICE))
+                return (b->modes & MODE_VOICE) - (a->modes & MODE_VOICE);
+            else if (a->oplevel != b->oplevel)
+                return a->oplevel - b->oplevel;
+        } else if (b->modes & MODE_CHANOP)
+            return 1;
+        else if ((b->modes & MODE_VOICE) != (a->modes & MODE_VOICE))
+            return (b->modes & MODE_VOICE) - (a->modes & MODE_VOICE);
+
+        return irccasecmp(a->user->nick, b->user->nick);
+}
+
 static part_func_t *pf_list;
 static unsigned int pf_size = 0, pf_used = 0;
 
index bd7b3353fae7d73a982da612b2a1a86ff3c5f8f8..8d3cb211914f21180b0c8a93a9672245bc260e5e 100644 (file)
@@ -236,6 +236,7 @@ void UnlockChannel(struct chanNode *channel);
 
 struct modeNode* AddChannelUser(struct userNode* user, struct chanNode* channel);
 
+int modeNode_sort(const void *pa, const void *pb);
 typedef void (*part_func_t) (struct modeNode *mn, const char *reason);
 void reg_part_func(part_func_t handler);
 void unreg_part_func(part_func_t handler);
index 30ef2f02d3fe2d4621455d2d2340b3ae1bdfd3a8..7457336a78cb30295f01d605e573405c1662f403 100644 (file)
@@ -442,8 +442,10 @@ static MODCMD_FUNC(cmd_chaninfo)
     const char *fmt;
     struct banNode *ban;
     struct modeNode *moden;
+    struct modeNode **members;
     time_t feh;
     unsigned int n;
+    int show_oplevels;
 
     reply("OSMSG_CHANINFO_HEADER", channel->name);
     fmt = user_find_message(user, "OSMSG_CHANINFO_TIMESTAMP");
@@ -480,25 +482,28 @@ static MODCMD_FUNC(cmd_chaninfo)
         return 1;
     }
     reply("OSMSG_CHANINFO_USER_COUNT", channel->members.used);
+
+    /* Create and sort the members array. */
+    members = alloca(channel->members.used * sizeof(members[0]));
+    for (n=0; n<channel->members.used; n++)
+        members[n] = channel->members.list[n];
+    qsort(members, channel->members.used, sizeof(members[0]), modeNode_sort);
+
+    /* Display the array. */
+    show_oplevels = (members[0]->modes & MODE_CHANOP) && (members[0]->oplevel < MAXOPLEVEL);
     for (n=0; n<channel->members.used; n++) {
-        moden = channel->members.list[n];
+        moden = members[n];
         if (moden->modes & MODE_CHANOP) {
-            if (moden->oplevel >= 0)
+            if (show_oplevels)
                 send_message_type(4, user, cmd->parent->bot, " @%s:%d (%s@%s)", moden->user->nick, moden->oplevel, moden->user->ident, moden->user->hostname);
             else
                 send_message_type(4, user, cmd->parent->bot, " @%s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname);
-        }
-    }
-    for (n=0; n<channel->members.used; n++) {
-        moden = channel->members.list[n];
-        if ((moden->modes & (MODE_CHANOP|MODE_VOICE)) == MODE_VOICE)
+        } else if (moden->modes & MODE_VOICE)
             send_message_type(4, user, cmd->parent->bot, " +%s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname);
-    }
-    for (n=0; n<channel->members.used; n++) {
-        moden = channel->members.list[n];
-        if ((moden->modes & (MODE_CHANOP|MODE_VOICE)) == 0)
+        else
             send_message_type(4, user, cmd->parent->bot, "  %s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname);
     }
+
     return 1;
 }
 
index ec517d142dae628744a441e2b373731ca9e5fca5..48b65274fa8f1bc7a350616fb921318e3f8494db 100644 (file)
@@ -683,7 +683,7 @@ irc_ungline(const char *mask)
  * Within those sets, ordering is arbitrary.
  */
 static int
-modeNode_sort(const void *pa, const void *pb)
+modeNode_sort_p10(const void *pa, const void *pb)
 {
         struct modeNode *a = *(struct modeNode**)pa;
         struct modeNode *b = *(struct modeNode**)pb;
@@ -724,7 +724,7 @@ irc_burst(struct chanNode *chan)
         burst_line[pos++] = ' ';
 
     /* sort the users for oplevel-sending purposes */
-    qsort(chan->members.list, chan->members.used, sizeof(chan->members.list[0]), modeNode_sort);
+    qsort(chan->members.list, chan->members.used, sizeof(chan->members.list[0]), modeNode_sort_p10);
 
     /* dump the users */
     for (n=0; n<chan->members.used; n++) {