* complete the sorting api by non-room based preferences
authorWilfried Göesgens <willi@citadel.org>
Sun, 11 Jan 2009 20:17:57 +0000 (20:17 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 11 Jan 2009 20:17:57 +0000 (20:17 +0000)
* add saving of sort orders to preferences
* migrate sorting of users to new sorting API.

webcit/downloads.c
webcit/messages.c
webcit/preferences.c
webcit/preferences.h
webcit/subst.c
webcit/subst.h
webcit/useredit.c

index ea6ad4d9b218c5befe7c4233b394106bef2f51c2..b26666744659a9065660b21eaf00a7ec4b33577f 100644 (file)
@@ -211,7 +211,7 @@ HashList* LoadFileList(StrBuf *Target, WCTemplputParams *TP)
                Put(Files, SKEY(Entry->Filename), Entry, FreeFiles);
        }
        SubTP.ContextType = CTX_FILELIST;
-       SortIt = RetrieveSort(&SubTP, NULL, HKEY("fileunsorted"), 0);
+       SortIt = RetrieveSort(&SubTP, NULL, 0, HKEY("fileunsorted"), 0);
        if (SortIt != NULL)
                SortByPayload(Files, SortIt);
        else 
index 06a69f7b7992b6c6fba9f112f98369e5e16ddeea..3e8d1d0545fac8ec0fe5433ae362c13189fe705b 100644 (file)
@@ -757,7 +757,7 @@ void readloop(long oper)
                memset(&SubTP, 0, sizeof(WCTemplputParams));
                SubTP.ContextType = CTX_NONE;
                SubTP.Context = NULL;
-               SortIt =  RetrieveSort(&SubTP, NULL, 
+               SortIt =  RetrieveSort(&SubTP, NULL, 0,
                                       HKEY("date"), defaultsortorder);
                if (SortIt != NULL)
                        SortByPayload(WCC->summ, SortIt);
index ad55f0483296f5e6ba9c28c38f85dc1d9c5987e9..e56100900975d48fae2ecff8eb6089d5899cc0ec 100644 (file)
@@ -493,19 +493,53 @@ void set_PREF_YESNO(const char *key, size_t keylen, long value, int save_to_serv
        set_preference_backend(key, keylen, value, NULL, PRF_YESNO, save_to_server, NULL);
 }
 
-int get_room_prefs_backend(const char *key, size_t keylen, Preference **Pref)
+int get_room_prefs_backend(const char *key, size_t keylen, 
+                          Preference **Pref)
 {
        StrBuf *pref_name;
        int Ret;
 
-       pref_name = NewStrBuf ();
-       StrBufPrintf(pref_name, "%s:%s", key, ChrPtr(WC->wc_roomname));
+       pref_name = NewStrBufPlain (HKEY("ROOM:"));
+       StrBufAppendBuf(pref_name, WC->wc_roomname, 0);
+       StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
+       StrBufAppendBufPlain(pref_name, key, keylen, 0);
        Ret = get_pref_backend(SKEY(pref_name), Pref);
        FreeStrBuf(&pref_name);
 
        return Ret;
 }
 
+const StrBuf *get_X_PREFS(const char *key, size_t keylen, 
+                         const char *xkey, size_t xkeylen)
+{
+       StrBuf *pref_name;
+       Preference *Prf;
+       
+       pref_name = NewStrBufPlain (HKEY("XPREF:"));
+       StrBufAppendBufPlain(pref_name, xkey, xkeylen, 0);
+       StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
+       StrBufAppendBufPlain(pref_name, key, keylen, 0);
+
+       get_pref_backend(SKEY(pref_name), &Prf);
+       FreeStrBuf(&pref_name);
+
+       return Prf->Val;
+}
+
+void set_X_PREFS(const char *key, size_t keylen, const char *xkey, size_t xkeylen, StrBuf *value, int save_to_server)
+{
+       StrBuf *pref_name;
+       
+       pref_name = NewStrBufPlain (HKEY("XPREF:"));
+       StrBufAppendBufPlain(pref_name, xkey, xkeylen, 0);
+       StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
+       StrBufAppendBufPlain(pref_name, key, keylen, 0);
+
+       set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL);
+       FreeStrBuf(&pref_name);
+}
+
+
 StrBuf *get_ROOM_PREFS(const char *key, size_t keylen)
 {
        Preference *Pref;
@@ -524,8 +558,10 @@ void set_ROOM_PREFS(const char *key, size_t keylen, StrBuf *value, int save_to_s
 {
        StrBuf *pref_name;
        
-       pref_name = NewStrBuf ();
-       StrBufPrintf(pref_name, "%s:%s", key, ChrPtr(WC->wc_roomname));
+       pref_name = NewStrBufPlain (HKEY("ROOM:"));
+       StrBufAppendBuf(pref_name, WC->wc_roomname, 0);
+       StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
+       StrBufAppendBufPlain(pref_name, key, keylen, 0);
        set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL);
        FreeStrBuf(&pref_name);
 }
index 779ad3c2a9dec6773b678bef78d90712ea3fa694..70db2e36caa1dec16664bb7a6cba3c638eeef280 100644 (file)
@@ -38,3 +38,11 @@ StrBuf *get_ROOM_PREFS(const char *key, size_t keylen);
 
 #define set_room_pref(a, b, c) set_ROOM_PREFS(a, sizeof(a) - 1, b, c)
 void set_ROOM_PREFS(const char *key, size_t keylen, StrBuf *value, int save_to_server);
+
+
+#define get_x_pref(a, b) get_ROOM_PREFS(a, sizeof(a) - 1, b, sizeof(b) - 1)
+const StrBuf *get_X_PREFS(const char *key, size_t keylen, 
+                         const char *xkey, size_t xkeylen);
+
+#define set_x_pref(a, b, c) set_ROOM_PREFS(a, sizeof(a) - 1, b, sizeof(b) - 1, c, d)
+void set_X_PREFS(const char *key, size_t keylen, const char *xkey, size_t xkeylen, StrBuf *value, int save_to_server);
index 351793545f0d95e6bd4f64c3fb9711e183ad814c..5259828cf0bb35b5c93e43e8c8114e5e2eee219b 100644 (file)
@@ -1799,7 +1799,8 @@ void RegisterSortFunc(const char *name, long len,
        Put(SortHash, name, len, NewSort, DestroySortStruct);
 }
 
-CompareFunc RetrieveSort(WCTemplputParams *TP, const char *OtherPrefix, 
+CompareFunc RetrieveSort(WCTemplputParams *TP, 
+                        const char *OtherPrefix, long OtherPrefixLen,
                         const char *Default, long ldefault, long DefaultDirection)
 {
        int isdefault = 0;
@@ -1810,13 +1811,19 @@ CompareFunc RetrieveSort(WCTemplputParams *TP, const char *OtherPrefix,
        
        if (havebstr("SortBy")) {
                BSort = sbstr("SortBy");
+               if (OtherPrefix == NULL) {
+                       set_room_pref("sort", NewStrBufDup(BSort), 0);
+               }
+               else {
+                       set_X_PREFS(HKEY("sort"), OtherPrefix, OtherPrefixLen, NewStrBufDup(BSort), 0);
+               }
        }
        else { /** Try to fallback to our remembered values... */
                if (OtherPrefix == NULL) {
                        BSort = get_room_pref("sort");
                }
                else {
-                       /*TODO: nail prefprepend to sort, and lookup this! */
+                       BSort = get_X_PREFS(HKEY("sort"), OtherPrefix, OtherPrefixLen);
                }
                if (BSort != NULL)
                        putbstr("SortBy", NewStrBufDup(BSort));
@@ -1852,7 +1859,7 @@ CompareFunc RetrieveSort(WCTemplputParams *TP, const char *OtherPrefix,
                        SortOrder = StrTol(Buf);
                }
                else {
-                       /* TODO: nail prefprepend to sort, and lookup this! */
+                       BSort = get_X_PREFS(HKEY("SortOrder"), OtherPrefix, OtherPrefixLen);
                }
 
                if (Buf == NULL)
@@ -1894,7 +1901,7 @@ ConstStr SortNextOrder[] = {
 };
 
 
-int GetSortMetric(WCTemplputParams *TP, SortStruct **Next, SortStruct **Param, long *SortOrder)
+int GetSortMetric(WCTemplputParams *TP, SortStruct **Next, SortStruct **Param, long *SortOrder, int N)
 {
        int bSortError = eNOT_SPECIFIED;
        const StrBuf *BSort;
@@ -1911,13 +1918,19 @@ int GetSortMetric(WCTemplputParams *TP, SortStruct **Next, SortStruct **Param, l
        if (havebstr("SortBy")) {
                BSort = sbstr("SortBy");
                bSortError = eINVALID_PARAM;
+               if ((*Param)->PrefPrepend == NULL) {
+                       set_room_pref("sort", NewStrBufDup(BSort), 0);
+               }
+               else {
+                       set_X_PREFS(HKEY("sort"), TKEY(N), NewStrBufDup(BSort), 0);
+               }
        }
        else { /** Try to fallback to our remembered values... */
                if ((*Param)->PrefPrepend == NULL) {
                        BSort = get_room_pref("sort");
                }
                else {
-                       BSort = NULL;/* TODO: nail prefprepend to sort, and lookup this! */
+                       BSort = get_X_PREFS(HKEY("sort"), TKEY(N));
                }
        }
 
@@ -1936,7 +1949,7 @@ int GetSortMetric(WCTemplputParams *TP, SortStruct **Next, SortStruct **Param, l
                        *SortOrder = StrTol(get_room_pref("SortOrder"));
                }
                else {
-                       *SortOrder = 0;/* TODO: nail prefprepend to sort, and lookup this! */
+                       *SortOrder = StrTol(get_X_PREFS(HKEY("SortOrder"), TKEY(N)));
                }
        }
        if (*SortOrder > 2)
@@ -1953,7 +1966,7 @@ void tmplput_SORT_ICON(StrBuf *Target, WCTemplputParams *TP)
        SortStruct *Param;
        const ConstStr *SortIcon;
 
-       switch (GetSortMetric(TP, &Next, &Param, &SortOrder)){
+       switch (GetSortMetric(TP, &Next, &Param, &SortOrder, 2)){
        case eNO_SUCH_SORT:
                 LogTemplateError(
                         Target, "Sorter", ERR_PARM1, TP,
@@ -1982,7 +1995,7 @@ void tmplput_SORT_NEXT(StrBuf *Target, WCTemplputParams *TP)
        SortStruct *Next;
        SortStruct *Param;
 
-       switch (GetSortMetric(TP, &Next, &Param, &SortOrder)){
+       switch (GetSortMetric(TP, &Next, &Param, &SortOrder, 2)){
        case eNO_SUCH_SORT:
                 LogTemplateError(
                         Target, "Sorter", ERR_PARM1, TP,                                  
@@ -2008,7 +2021,7 @@ void tmplput_SORT_ORDER(StrBuf *Target, WCTemplputParams *TP)
        SortStruct *Next;
        SortStruct *Param;
 
-       switch (GetSortMetric(TP, &Next, &Param, &SortOrder)){
+       switch (GetSortMetric(TP, &Next, &Param, &SortOrder, 2)){
        case eNO_SUCH_SORT:
                 LogTemplateError(
                         Target, "Sorter", ERR_PARM1, TP,
@@ -2113,9 +2126,9 @@ InitModule_SUBST
 (void)
 {
        memset(&NoCtx, 0, sizeof(WCTemplputParams));
-       RegisterNamespace("SORT:ICON", 1, 1, tmplput_SORT_ICON, CTX_NONE);
-       RegisterNamespace("SORT:ORDER", 1, 1, tmplput_SORT_ORDER, CTX_NONE);
-       RegisterNamespace("SORT:NEXT", 1, 1, tmplput_SORT_NEXT, CTX_NONE);
+       RegisterNamespace("SORT:ICON", 1, 2, tmplput_SORT_ICON, CTX_NONE);
+       RegisterNamespace("SORT:ORDER", 1, 2, tmplput_SORT_ORDER, CTX_NONE);
+       RegisterNamespace("SORT:NEXT", 1, 2, tmplput_SORT_NEXT, CTX_NONE);
        RegisterNamespace("CONTEXTSTR", 0, 1, tmplput_ContextString, CTX_STRBUF);
        RegisterNamespace("ITERATE", 2, 100, tmpl_iterate_subtmpl, CTX_NONE);
        RegisterNamespace("DOBOXED", 1, 2, tmpl_do_boxed, CTX_NONE);
index 2d669b3e9d8036493c45844c9a8480d6296b0151..fa599ebcb969c312e0ada6ee30d54d7b7b87c248 100644 (file)
@@ -173,8 +173,10 @@ void StrBufAppendTemplate(StrBuf *Target,
                          WCTemplputParams *TP,
                          const StrBuf *Source, 
                          int FormatTypeIndex);
-CompareFunc RetrieveSort(WCTemplputParams *TP, const char *OtherPrefix, 
-                        const char *Default, long ldefault, long DefaultDirection);
+CompareFunc RetrieveSort(WCTemplputParams *TP, 
+                        const char *OtherPrefix, long OtherPrefixLen,  
+                        const char *Default, long ldefault, 
+                        long DefaultDirection);
 void RegisterSortFunc(const char *name, long len, 
                      const char *prepend, long preplen,
                      CompareFunc Forward, 
index f4f136ebb9a9a0f149f26acc0b94188a88dbd70d..37320a55d2c34836d46019dd3fdb7f52ada3a9f1 100644 (file)
@@ -93,16 +93,22 @@ UserListEntry* NewUserListEntry(StrBuf *SerializedUserList)
  */
 int CompareUserListName(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return strcmp(ChrPtr(u1->UserName), ChrPtr(u2->UserName));
 }
 int CompareUserListNameRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+       return strcmp(ChrPtr(u2->UserName), ChrPtr(u1->UserName));
+}
+int GroupchangeUserListName(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
-       return strcmp(ChrPtr(u2->UserName), ChrPtr(u1->UserName));
+       return ChrPtr(u2->UserName)[0] != ChrPtr(u1->UserName)[0];
 }
 
 /*
@@ -110,17 +116,24 @@ int CompareUserListNameRev(const void *vUser1, const void *vUser2)
  */
 int CompareAccessLevel(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->AccessLevel > u2->AccessLevel);
 }
 int CompareAccessLevelRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->AccessLevel > u1->AccessLevel);
+}
+int GroupchangeAccessLevel(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->AccessLevel > u1->AccessLevel);
+       return u2->AccessLevel != u1->AccessLevel;
 }
 
 
@@ -129,17 +142,24 @@ int CompareAccessLevelRev(const void *vUser1, const void *vUser2)
  */
 int CompareUID(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->UID > u2->UID);
 }
 int CompareUIDRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->UID > u1->UID);
+}
+int GroupchangeUID(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->UID > u1->UID);
+       return (u2->UID / 10) != (u1->UID / 10);
 }
 
 /*
@@ -147,17 +167,24 @@ int CompareUIDRev(const void *vUser1, const void *vUser2)
  */
 int CompareLastLogon(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->LastLogonT > u2->LastLogonT);
 }
 int CompareLastLogonRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->LastLogonT > u1->LastLogonT);
+}
+int GroupchangeLastLogon(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->LastLogonT > u1->LastLogonT);
+       return (u2->LastLogonT != u1->LastLogonT);
 }
 
 /*
@@ -165,17 +192,24 @@ int CompareLastLogonRev(const void *vUser1, const void *vUser2)
  */
 int ComparenLogons(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->nLogons > u2->nLogons);
 }
 int ComparenLogonsRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->nLogons > u1->nLogons);
+}
+int GroupchangenLogons(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->nLogons > u1->nLogons);
+       return (u2->nLogons / 100) != (u1->nLogons / 100);
 }
 
 /*
@@ -183,31 +217,40 @@ int ComparenLogonsRev(const void *vUser1, const void *vUser2)
  */
 int ComparenPosts(const void *vUser1, const void *vUser2)
 {
-       UserListEntry *u1 = (UserListEntry*) vUser1;
-       UserListEntry *u2 = (UserListEntry*) vUser2;
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
 
        return (u1->nPosts > u2->nPosts);
 }
 int ComparenPostsRev(const void *vUser1, const void *vUser2)
+{
+       UserListEntry *u1 = (UserListEntry*) GetSearchPayload(vUser1);
+       UserListEntry *u2 = (UserListEntry*) GetSearchPayload(vUser2);
+
+       return (u2->nPosts > u1->nPosts);
+}
+int GroupchangenPosts(const void *vUser1, const void *vUser2)
 {
        UserListEntry *u1 = (UserListEntry*) vUser1;
        UserListEntry *u2 = (UserListEntry*) vUser2;
 
-       return (u2->nPosts > u1->nPosts);
+       return (u2->nPosts / 100) != (u1->nPosts / 100);
 }
 
 
 HashList *iterate_load_userlist(StrBuf *Target, WCTemplputParams *TP)
 {
+       CompareFunc SortIt;
        HashList *Hash;
        char buf[SIZ];
        StrBuf *Buf;
        UserListEntry* ul;
        char nnn[64];
        int nUsed;
-       int Order;
        int len;
-       
+       WCTemplputParams SubTP;
+
+       memset(&TP, 0, sizeof(WCTemplputParams));       
         serv_puts("LIST");
         serv_getln(buf, sizeof buf);
         if (buf[0] == '1') {
@@ -224,44 +267,12 @@ HashList *iterate_load_userlist(StrBuf *Target, WCTemplputParams *TP)
                        Put(Hash, nnn, nUsed, ul, DeleteUserListEntry); 
                }
                FreeStrBuf(&Buf);
-               Order = ibstr("SortOrder");
-               switch (ibstr("SortBy")){
-               case 1: /*NAME*/
-                       SortByPayload(Hash, (Order)? 
-                                     CompareUserListName:
-                                     CompareUserListNameRev);
-                       break;
-               case 2: /*AccessLevel*/
-                       SortByPayload(Hash, (Order)? 
-                                     CompareAccessLevel:
-                                     CompareAccessLevelRev);
-                       break;
-               case 3: /*nLogons*/
-                       SortByPayload(Hash, (Order)? 
-                                     ComparenLogons:
-                                     ComparenLogonsRev);
-                       break;
-               case 4: /*UID*/
-                       SortByPayload(Hash, (Order)? 
-                                     CompareUID:
-                                     CompareUIDRev);
-                       break;
-               case 5: /*LastLogon*/
-                       SortByPayload(Hash, (Order)? 
-                                     CompareLastLogon:
-                                     CompareLastLogonRev);
-                       break;
-               case 6: /* nLogons */
-                       SortByPayload(Hash, (Order)? 
-                                     ComparenLogons:
-                                     ComparenLogonsRev);
-                       break;
-               case 7: /* Posts */
-                       SortByPayload(Hash, (Order)? 
-                                     ComparenPosts:
-                                     ComparenPostsRev);
-                       break;
-               }
+               SubTP.ContextType = CTX_USERLIST;
+               SortIt = RetrieveSort(&SubTP, HKEY("USER"), HKEY("user:uid"), 0);
+               if (SortIt != NULL)
+                       SortByPayload(Hash, SortIt);
+               else 
+                       SortByPayload(Hash, CompareUID);
                return Hash;
         }
        return NULL;
@@ -691,4 +702,47 @@ InitModule_USEREDIT
        RegisterConditional(HKEY("COND:USERLIST:FLAG:USE_INTERNET"), 0, ConditionalFlagINetEmail, CTX_USERLIST);
 
        RegisterIterator("USERLIST", 0, NULL, iterate_load_userlist, NULL, DeleteHash, CTX_USERLIST, CTX_NONE, IT_NOFLAG);
+
+
+       RegisterSortFunc(HKEY("user:name"),
+                        HKEY("userlist"),
+                        CompareUserListName,
+                        CompareUserListNameRev,
+                        GroupchangeUserListName,
+                        CTX_USERLIST);
+       RegisterSortFunc(HKEY("user:accslvl"),
+                        HKEY("userlist"),
+                        CompareAccessLevel,
+                        CompareAccessLevelRev,
+                        GroupchangeAccessLevel,
+                        CTX_USERLIST);
+
+       RegisterSortFunc(HKEY("user:nlogons"),
+                        HKEY("userlist"),
+                        ComparenLogons,
+                        ComparenLogonsRev,
+                        GroupchangenLogons,
+                        CTX_USERLIST);
+
+       RegisterSortFunc(HKEY("user:uid"),
+                        HKEY("userlist"),
+                        CompareUID,
+                        CompareUIDRev,
+                        GroupchangeUID,
+                        CTX_USERLIST);
+
+       RegisterSortFunc(HKEY("user:lastlogon"),
+                        HKEY("userlist"),
+                        CompareLastLogon,
+                        CompareLastLogonRev,
+                        GroupchangeLastLogon,
+                        CTX_USERLIST);
+
+       RegisterSortFunc(HKEY("user:nmsgposts"),
+                        HKEY("userlist"),
+                        ComparenPosts,
+                        ComparenPostsRev,
+                        GroupchangenPosts,
+                        CTX_USERLIST);
+
 }