* add 'control context'; which will carry information from control elements into...
authorWilfried Göesgens <willi@citadel.org>
Wed, 14 Jan 2009 23:46:21 +0000 (23:46 +0000)
committerWilfried Göesgens <willi@citadel.org>
Wed, 14 Jan 2009 23:46:21 +0000 (23:46 +0000)
* abstract context checking
* make ITERATE:xxx own template callbacks instead of using SVPUT and friends
* replace conditionals in templates leaning on ITERATE:xxx by their native new implementations

14 files changed:
webcit/auth.c
webcit/downloads.c
webcit/graphics.c
webcit/messages.c
webcit/msg_renderers.c
webcit/netconf.c
webcit/notes.c
webcit/roomops.c
webcit/static/t/json_floor.html
webcit/static/t/json_room.html
webcit/static/t/section_files_onefile.html
webcit/subst.c
webcit/subst.h
webcit/useredit.c

index 364a2c3677764cdbce4db9672852f746441d1f96..0823216041913729645afc310dcff9d5be02d919 100644 (file)
@@ -793,7 +793,7 @@ void display_changepw(void)
 
        Buf = NewStrBufPlain(_("Change your password"), -1);
        memset(&SubTP, 0, sizeof(WCTemplputParams));
-       SubTP.ContextType = CTX_STRBUF;
+       SubTP.Filter.ContextType = CTX_STRBUF;
        SubTP.Context = Buf;
        DoTemplate(HKEY("beginbox"), NULL, &SubTP);
 
index b26666744659a9065660b21eaf00a7ec4b33577f..24276dc980c60cdd69acddb7aea051e0d355b767 100644 (file)
@@ -210,7 +210,7 @@ HashList* LoadFileList(StrBuf *Target, WCTemplputParams *TP)
                }
                Put(Files, SKEY(Entry->Filename), Entry, FreeFiles);
        }
-       SubTP.ContextType = CTX_FILELIST;
+       SubTP.Filter.ContextType = CTX_FILELIST;
        SortIt = RetrieveSort(&SubTP, NULL, 0, HKEY("fileunsorted"), 0);
        if (SortIt != NULL)
                SortByPayload(Files, SortIt);
index ba879dc35aac4bd09d9e47da2acff8444d594160..361c19752456bbe4eb81bd8acaa41f8982c58461 100644 (file)
@@ -28,7 +28,7 @@ void display_graphics_upload(char *description, char *filename, char *uplurl)
 
        Buf = NewStrBufPlain(_("Image upload"), -1);
        memset(&SubTP, 0, sizeof(WCTemplputParams));
-       SubTP.ContextType = CTX_STRBUF;
+       SubTP.Filter.ContextType = CTX_STRBUF;
        SubTP.Context = Buf;
        DoTemplate(HKEY("beginbox"), NULL, &SubTP);
 
index 2422629450667ac32b4b4c1e65d124d8f4f1b296..015e36187ac86ab10c84e46a21b379cb660da29f 100644 (file)
@@ -235,7 +235,7 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, in
        }
        DeleteHashPos(&it);
        memset(&SubTP, 0, sizeof(WCTemplputParams));
-       SubTP.ContextType = CTX_MAILSUM;
+       SubTP.Filter.ContextType = CTX_MAILSUM;
        SubTP.Context = Msg;
        DoTemplate(tmpl, tmpllen, Target, &SubTP);
 
@@ -511,7 +511,7 @@ long DrawMessageDropdown(StrBuf *Selector, long maxmsgs, long startmsg, int nMes
        WCTemplputParams SubTP;
 
        memset(&SubTP, 0, sizeof(WCTemplputParams));
-       SubTP.ContextType = CTX_LONGVECTOR;
+       SubTP.Filter.ContextType = CTX_LONGVECTOR;
        SubTP.Context = &vector;
        TmpBuf = NewStrBuf();
        At = GetNewHashPos(WCC->summ, nMessages);
@@ -761,7 +761,7 @@ void readloop(long oper)
        if (sortit) {
                CompareFunc SortIt;
                memset(&SubTP, 0, sizeof(WCTemplputParams));
-               SubTP.ContextType = CTX_NONE;
+               SubTP.Filter.ContextType = CTX_NONE;
                SubTP.Context = NULL;
                SortIt =  RetrieveSort(&SubTP, NULL, 0,
                                       HKEY("date"), defaultsortorder);
@@ -800,7 +800,7 @@ void readloop(long oper)
 
                }
                memset(&SubTP, 0, sizeof(WCTemplputParams));
-               SubTP.ContextType = CTX_STRBUF;
+               SubTP.Filter.ContextType = CTX_STRBUF;
                SubTP.Context = MessageDropdown;
                DoTemplate(HKEY("msg_listselector_top"), BBViewToolBar, &SubTP);
                StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
@@ -890,7 +890,7 @@ void readloop(long oper)
                        displayed_msgs = NULL;
                }
                memset(&SubTP, 0, sizeof(WCTemplputParams));
-               SubTP.ContextType = CTX_STRBUF;
+               SubTP.Filter.ContextType = CTX_STRBUF;
                SubTP.Context = MessageDropdown;
                DoTemplate(HKEY("msg_listselector_bottom"), BBViewToolBar, &SubTP);
                StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
index 22eace1dbd0736321b0ec8bee68fa38784c73ae6..d3b896f60e30413f2e005aead57e5ae7d4e6de2d 100644 (file)
@@ -410,25 +410,29 @@ int Conditional_ROOM_DISPLAY_MSG(StrBuf *Target, WCTemplputParams *TP) {
        wcsubst *subst;
        wcsession *WCC = WC;
   
-       GetHash(WCC->vars, HKEY("ITERATE:N"), (void *)&subst);
-       num_inset = subst->lvalue;
-       if ((num_inset >= WC->startmsg) && (WCC->num_displayed <= WCC->maxmsgs)) {
-               WCC->num_displayed = WCC->num_displayed+1;
-               return 1; /* Pass GO, collect $200 */
-       } 
+       if (GetHash(WCC->vars, HKEY("ITERATE:N"), (void *)&subst) && 
+           (subst != NULL)) {
+               num_inset = subst->lvalue;
+               if ((num_inset >= WC->startmsg) && (WCC->num_displayed <= WCC->maxmsgs)) {
+                       WCC->num_displayed = WCC->num_displayed+1;
+                       return 1; /* Pass GO, collect $200 */
+               } 
+       }
        return 0;
 }
 int Conditional_MAIL_SUMM_LASTMSG(StrBuf *Target, WCTemplputParams *TP) {
        wcsubst *nsubst;
-       long is_last_n;
+       long is_last_n = 0;
   
-       GetHash(WC->vars, HKEY("ITERATE:LASTN"), (void *)&nsubst);
-       is_last_n = nsubst->lvalue;
+       if (GetHash(WC->vars, HKEY("ITERATE:LASTN"), (void *)&nsubst) &&
+           (nsubst != NULL)) {
+               is_last_n = nsubst->lvalue;
 /*
        //GetHash(WC->vars, HKEY("ITERATE:N"), (void *)&n_dsubst);
        //num_inset = n_dsubst->lvalue;
        */
        /* Is the num_displayed higher than maxmsgs? OR last in iterator */
+       }
        return ((WC->num_displayed > WC->maxmsgs) || (is_last_n == 1));
 }
 void examine_time(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
index 5f9087228076de8e9abdd5957c8759f4049839ae..c8add93118d324e876e0a37d2fdce673ba9a5436 100644 (file)
@@ -206,7 +206,7 @@ void display_edit_node(void)
        
        memset(&SubTP, 0, sizeof(WCTemplputParams));
        SVPutBuf("ITERATE:KEY", Index, 1);
-       SubTP.ContextType = CTX_NODECONF;
+       SubTP.Filter.ContextType = CTX_NODECONF;
        SubTP.Context = vNode;
        begin_burst();
        Tmpl = sbstr("template");
index d55fd2f813fabbc9b7eed7d7cd690d5219355854..9e00be85f693977fcae1ffd91fd5c902897b707b 100644 (file)
@@ -342,7 +342,7 @@ void display_note(message_summary *Msg, int unread) {
        WCTemplputParams TP;
 
        memset(&TP, 0, sizeof(WCTemplputParams));
-       TP.ContextType = CTX_VNOTE;
+       TP.Filter.ContextType = CTX_VNOTE;
        v = vnote_new_from_msg(Msg->msgnum);
        if (v) {
 //             display_vnote_div(v);
index c2b6ad9da5a833e77e31a359d33f7a2b1b1ef0a7..c180b529d71ecf83921408d1d6fbd9bcb02a4163 100644 (file)
@@ -278,7 +278,7 @@ void zapped_list(void)
        output_headers(1, 1, 1, 0, 0, 0);
        memset(&SubTP, 0, sizeof(WCTemplputParams));
        Buf = NewStrBufPlain(_("Zapped (forgotten) rooms"), -1);
-       SubTP.ContextType = CTX_STRBUF;
+       SubTP.Filter.ContextType = CTX_STRBUF;
        SubTP.Context = Buf;
        DoTemplate(HKEY("beginbox"), NULL, &SubTP);
 
@@ -2705,7 +2705,7 @@ void display_private(char *rname, int req_pass)
 
        Buf = NewStrBufPlain(_("Go to a hidden room"), -1);
        memset(&SubTP, 0, sizeof(WCTemplputParams));
-       SubTP.ContextType = CTX_STRBUF;
+       SubTP.Filter.ContextType = CTX_STRBUF;
        SubTP.Context = Buf;
        DoTemplate(HKEY("beginbox"), NULL, &SubTP);
 
@@ -3222,7 +3222,7 @@ void do_rooms_view(struct folder *fold, int max_folders, int num_floors) {
 
                        Buf = NewStrBufPlain(floor_name, -1);
                        memset(&SubTP, 0, sizeof(WCTemplputParams));
-                       SubTP.ContextType = CTX_STRBUF;
+                       SubTP.Filter.ContextType = CTX_STRBUF;
                        SubTP.Context = Buf;
                        DoTemplate(HKEY("beginbox"), NULL, &SubTP);
                        
index 2c07901506c7f77ade5836f90147709f2d58b7f9..50d9853eb55a7dc7eab225548b09dc7171f3aef1 100644 (file)
@@ -1 +1 @@
-[<?FLOOR:INFO("ID")>, "<?FLOOR:INFO("NAME")>", <?FLOOR:INFO("ROOMS")>] <??("COND:SUBST", 1, "ITERATE:LASTN", 1)> , <??("X",1)>
\ No newline at end of file
+[<?FLOOR:INFO("ID")>, "<?FLOOR:INFO("NAME")>", <?FLOOR:INFO("ROOMS")>] <??("COND:ITERATE:LASTN", 1)> , <??("X",1)>
index 42450154720e382ed5994491aa0109adc22102b1..4ac6ff3ba5b4f2bd84867cbc7739ba432e1a3bfd 100644 (file)
@@ -1,2 +1 @@
-["<?ROOM:INFO("NAME")>", <?ROOM:INFO("FLAG")>, <?ROOM:INFO("FLOOR")>, <?ROOM:INFO("LISTORDER")>,<?ROOM:INFO("ACL")>, <?ROOM:INFO("CURVIEW")>, <?ROOM:INFO("DEFVIEW")>, <?ROOM:INFO("LASTCHANGE")>] <??("COND:SUBST", 1,
-"ITERATE:LASTN", 1)> , <??("X",1)>
\ No newline at end of file
+["<?ROOM:INFO("NAME")>", <?ROOM:INFO("FLAG")>, <?ROOM:INFO("FLOOR")>, <?ROOM:INFO("LISTORDER")>,<?ROOM:INFO("ACL")>, <?ROOM:INFO("CURVIEW")>, <?ROOM:INFO("DEFVIEW")>, <?ROOM:INFO("LASTCHANGE")>] <??("COND:ITERATE:LASTN", 1)> , <??("X",1)>
index 76d05213521fa2609ebe83339901cb39ebf060ae..3beb8d4dd253da990b0c6673b87554c2443e23cc 100644 (file)
@@ -1,4 +1,4 @@
-<?!("COND:SUBST", 1, "ITERATE:ISGROUPCHANGE", 1)><?!("COND:BSTR", 2, "SortOrder", "filename")>
+<?!("COND:ITERATE:ISGROUPCHANGE", 1)><?!("COND:BSTR", 2, "SortOrder", "filename")>
 <tr class="<?ITERATE:ODDEVEN>"><th colspan = 4><?FILE:NAME("U", 1)></th></tr>
 <?!("X", 2)><?!("X", 1)>
 
@@ -13,7 +13,7 @@
 <td><?FILE:COMMENT("X")></td>
 </tr>
 
-<?!("COND:SUBST", 2, "ITERATE:LASTN", 1)>
+<?!("COND:ITERATE:LASTN", 2)>
 </table>
 <??("COND:FILE:ISPIC", 3)>
 <div class="buttons"><a href="do_template?template=files_jspicview&frame=1"><?_("Slideshow")></a></div>
index 215527a6185bbba3b1ebf3e9eb111d6be47ab45f..3a52342defa32175784b332d11b4f5e7fd5e6108 100644 (file)
@@ -51,9 +51,8 @@ typedef struct _WCTemplate {
 } WCTemplate;
 
 typedef struct _HashHandler {
-       int nMinArgs;
-       int nMaxArgs;
-       int ContextRequired;
+       ContextFilter Filter;
+
        WCHandlerFunc HandlerFunc;
 }HashHandler;
 
@@ -70,6 +69,28 @@ typedef struct _SortStruct {
        long ContextType;
 }SortStruct;
 
+const char *CtxNames[]  = {
+       "Context NONE",
+       "Context SITECFG",
+       "Context SESSION",
+       "Context INETCFG",
+       "Context VNOTE",
+       "Context WHO",
+       "Context PREF",
+       "Context NODECONF",
+       "Context USERLIST",
+       "Context MAILSUM",
+       "Context MIME_ATACH",
+       "Context FILELIST",
+       "Context STRBUF",
+       "Context LONGVECTOR",
+       "Context ROOMS",
+       "Context FLOORS",
+       "Context ITERATE"
+};
+
+
+
 void DestroySortStruct(void *vSort)
 {
        SortStruct *Sort = (SortStruct*) vSort;
@@ -135,13 +156,76 @@ void RegisterNS(const char *NSName,
        HashHandler *NewHandler;
        
        NewHandler = (HashHandler*) malloc(sizeof(HashHandler));
-       NewHandler->nMinArgs = nMinArgs;
-       NewHandler->nMaxArgs = nMaxArgs;
+       NewHandler->Filter.nMinArgs = nMinArgs;
+       NewHandler->Filter.nMaxArgs = nMaxArgs;
+       NewHandler->Filter.ContextType = ContextRequired;
+       NewHandler->Filter.ControlContextType = CTX_NONE;
+
        NewHandler->HandlerFunc = HandlerFunc;  
-       NewHandler->ContextRequired = ContextRequired;
        Put(GlobalNS, NSName, len, NewHandler, NULL);
 }
 
+void RegisterControlNS(const char *NSName, 
+                      long len, 
+                      int nMinArgs, 
+                      int nMaxArgs, 
+                      WCHandlerFunc HandlerFunc, 
+                      int ControlContextRequired)
+{
+       HashHandler *NewHandler;
+       
+       NewHandler = (HashHandler*) malloc(sizeof(HashHandler));
+       NewHandler->Filter.nMinArgs = nMinArgs;
+       NewHandler->Filter.nMaxArgs = nMaxArgs;
+       NewHandler->Filter.ContextType = CTX_NONE;
+       NewHandler->Filter.ControlContextType = ControlContextRequired;
+       NewHandler->HandlerFunc = HandlerFunc;  
+       Put(GlobalNS, NSName, len, NewHandler, NULL);
+}
+
+
+
+int CheckContext(StrBuf *Target, ContextFilter *Need, WCTemplputParams *TP, const char *ErrType)
+{
+       if ((Need->ContextType != CTX_NONE) && 
+           (Need->ContextType != TP->Filter.ContextType)) {
+                LogTemplateError(
+                        Target, ErrType, ERR_PARM1, TP,
+                       "  WARNING: requires Context: [%s], have [%s]!", 
+                       CtxNames[Need->ContextType], 
+                       CtxNames[TP->Filter.ContextType]);
+               return 0;
+       }
+
+       if ((Need->ControlContextType != CTX_NONE) && 
+           (Need->ControlContextType != TP->Filter.ControlContextType)) {
+                LogTemplateError(
+                        Target, ErrType, ERR_PARM1, TP,
+                       "  WARNING: requires Control Context: [%s], have [%s]!", 
+                       CtxNames[Need->ControlContextType], 
+                       CtxNames[TP->Filter.ControlContextType]);
+               return 0;
+       }
+                       
+       if (TP->Tokens->nParameters < Need->nMinArgs) {
+               LogTemplateError(Target, ErrType, ERR_NAME, TP,
+                                "needs at least %ld params, have %ld", 
+                                Need->nMinArgs, 
+                                TP->Tokens->nParameters);
+               return 0;
+
+       }
+       else if (TP->Tokens->nParameters > Need->nMaxArgs) {
+               LogTemplateError(Target, ErrType, ERR_NAME, TP,
+                                "just needs %ld params, you gave %ld",
+                                TP->Tokens->nParameters, 
+                                Need->nMaxArgs);
+               return 0;
+
+       }
+       return 1;
+}
+
 void FreeToken(WCTemplateToken **Token)
 {
        int i; 
@@ -573,7 +657,7 @@ void GetTemplateTokenString(WCTemplputParams *TP,
        case TYPE_SUBTEMPLATE:
                memset(&SubTP, 0, sizeof(WCTemplputParams *));
                SubTP.Context = TP->Context;
-               SubTP.ContextType = TP->ContextType;
+               SubTP.Filter.ContextType = TP->Filter.ContextType;
                Buf = NewStrBuf();
                DoTemplate(TKEY(N), Buf, &SubTP);
                *Value = ChrPtr(Buf);
@@ -1000,8 +1084,8 @@ WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf,
                if (GetHash(GlobalNS, NewToken->pName, NewToken->NameEnd, &vVar)) {
                        HashHandler *Handler;
                        Handler = (HashHandler*) vVar;
-                       if ((NewToken->nParameters < Handler->nMinArgs) || 
-                           (NewToken->nParameters > Handler->nMaxArgs)) {
+                       if ((NewToken->nParameters < Handler->Filter.nMinArgs) || 
+                           (NewToken->nParameters > Handler->Filter.nMaxArgs)) {
                                LogTemplateError(
                                        NULL, "Token", ERR_NAME, &TP,
                                        "doesn't work with %ld params", 
@@ -1286,6 +1370,7 @@ int EvaluateToken(StrBuf *Target, int state, WCTemplputParams *TP)
        long AppendMeLen;
        HashHandler *Handler;
        void *vVar;
+       
 /* much output, since pName is not terminated...
        lprintf(1,"Doing token: %s\n",Token->pName);
 */
@@ -1325,43 +1410,21 @@ int EvaluateToken(StrBuf *Target, int state, WCTemplputParams *TP)
                break;
        case SV_SUBTEMPL:
                if (TP->Tokens->nParameters == 1)
-                       DoTemplate(TKEY(0), NULL, TP);
+                       DoTemplate(TKEY(0), Target, TP);
                break;
        case SV_PREEVALUATED:
                Handler = (HashHandler*) TP->Tokens->PreEval;
-               if ((Handler->ContextRequired != CTX_NONE) &&
-                   (Handler->ContextRequired != TP->ContextType)) {
-                       LogTemplateError(
-                               Target, "Token", ERR_NAME, TP,
-                               "requires context of type %ld, have %ld", 
-                               Handler->ContextRequired, 
-                               TP->ContextType);
+               if (!CheckContext(Target, &Handler->Filter, TP, "Token")) {
                        return -1;
-
                }
                Handler->HandlerFunc(Target, TP);
                break;          
        default:
                if (GetHash(GlobalNS, TP->Tokens->pName, TP->Tokens->NameEnd, &vVar)) {
                        Handler = (HashHandler*) vVar;
-                       if ((Handler->ContextRequired != CTX_NONE) &&
-                           (Handler->ContextRequired != TP->ContextType)) {
-                               LogTemplateError(
-                                       Target, "Token", ERR_NAME, TP,
-                                       "requires context of type %ld, have %ld",
-                                       Handler->ContextRequired, 
-                                       TP->ContextType);
+                       if (!CheckContext(Target, &Handler->Filter, TP, "Token")) {
                                return -1;
                        }
-                       else if ((TP->Tokens->nParameters < Handler->nMinArgs) || 
-                                (TP->Tokens->nParameters > Handler->nMaxArgs)) {
-                               LogTemplateError(
-                                       Target, "Token", ERR_NAME, TP,
-                                       "doesn't work with %ld params need  > %ld  < %ld", 
-                                       TP->Tokens->nParameters, 
-                                       Handler->nMaxArgs,
-                                       Handler->nMinArgs);
-                       }
                        else {
                                Handler->HandlerFunc(Target, TP);
                        }
@@ -1385,7 +1448,7 @@ void ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, void *Context, int Contex
        WCTemplputParams TP;
 
        TP.Context = Context;
-       TP.ContextType = ContextType;
+       TP.Filter.ContextType = ContextType;
 
        if (LoadTemplates != 0) {                       
                if (LoadTemplates > 1)
@@ -1489,7 +1552,7 @@ void DoTemplate(const char *templatename, long len, StrBuf *Target, WCTemplputPa
        }
        if (vTmpl == NULL) 
                return;
-       ProcessTemplate(vTmpl, Target, TP->Context, TP->ContextType);
+       ProcessTemplate(vTmpl, Target, TP->Context, TP->Filter.ContextType);
 }
 
 /*-----------------------------------------------------------------------------
@@ -1528,6 +1591,15 @@ void RegisterITERATOR(const char *Name, long len,
        Put(Iterators, Name, len, It, NULL);
 }
 
+typedef struct _iteratestruct {
+       int GroupChange;
+       int oddeven;
+       const char *Key;
+       long KeyLen;
+       int n;
+       int LastN;
+}IterateStruct;
+
 void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
 {
        void *vIt;
@@ -1538,15 +1610,13 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
        void *vSortBy;
        int DetectGroupChange = 0;
        int nMembersUsed;
-       int nMembersCounted = 0;
-       long len; 
-       const char *Key;
        void *vContext;
        void *vLastContext = NULL;
        StrBuf *SubBuf;
-       int oddeven = 0;
        WCTemplputParams SubTP;
+       IterateStruct Status;
 
+       memset(&Status, 0, sizeof(IterateStruct));
        memcpy (&SubTP, &TP, sizeof(WCTemplputParams));
        
        if (!GetHash(Iterators, TKEY(0), &vIt)) {
@@ -1566,12 +1636,12 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
        }
 
        if ((It->XPectContextType != CTX_NONE) &&
-           (It->XPectContextType != TP->ContextType)) {
+           (It->XPectContextType != TP->Filter.ContextType)) {
                LogTemplateError(
                        Target, "Iterator", ERR_PARM1, TP,
                        "requires context of type %ld, have %ld", 
                        It->XPectContextType, 
-                       TP->ContextType);
+                       TP->Filter.ContextType);
                return ;
                
        }
@@ -1602,20 +1672,15 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
        }
        nMembersUsed = GetCount(List);
        SubBuf = NewStrBuf();
-       SubTP.ContextType = It->ContextType;
+       SubTP.Filter.ContextType = It->ContextType;
+       SubTP.Filter.ControlContextType = CTX_ITERATE;
+       SubTP.ControlContext = &Status;
        it = GetNewHashPos(List, 0);
-       while (GetNextHashPos(List, it, &len, &Key, &vContext)) {
-               if (DetectGroupChange && nMembersCounted > 0) {
-                       if (SortBy->GroupChange(vContext, vLastContext))
-                               svputlong("ITERATE:ISGROUPCHANGE", 1);                  
-                       else
-                               svputlong("ITERATE:ISGROUPCHANGE", 0);
+       while (GetNextHashPos(List, it, &Status.KeyLen, &Status.Key, &vContext)) {
+               if (DetectGroupChange && Status.n > 0) {
+                       Status.GroupChange = (SortBy->GroupChange(vContext, vLastContext))? 1:0;
                }
-               svprintf(HKEY("ITERATE:ODDEVEN"), WCS_STRING, "%s", 
-                        (oddeven) ? "odd" : "even");
-               svprintf(HKEY("ITERATE:KEY"), WCS_STRING, "%s", Key);
-               svputlong("ITERATE:N", nMembersCounted);
-               svputlong("ITERATE:LASTN", ++nMembersCounted == nMembersUsed);
+               Status.LastN = ++Status.LastN == nMembersUsed;
                SubTP.Context = vContext;
                if (It->DoSubTemplate != NULL)
                        It->DoSubTemplate(SubBuf, &SubTP);
@@ -1623,7 +1688,7 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
                        
                StrBufAppendBuf(Target, SubBuf, 0);
                FlushStrBuf(SubBuf);
-               oddeven = ~ oddeven;
+               Status.oddeven = ! Status.oddeven;
                vLastContext = vContext;
        }
        FreeStrBuf(&SubBuf);
@@ -1633,6 +1698,43 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
 }
 
 
+int conditional_ITERATE_ISGROUPCHANGE(StrBuf *Target, WCTemplputParams *TP)
+{
+       IterateStruct *Ctx = CCTX;
+       return Ctx->GroupChange;
+}
+
+void tmplput_ITERATE_ODDEVEN(StrBuf *Target, WCTemplputParams *TP)
+{
+       IterateStruct *Ctx = CCTX;
+       if (Ctx->oddeven)
+               StrBufAppendBufPlain(Target, HKEY("odd"), 0);
+       else
+               StrBufAppendBufPlain(Target, HKEY("even"), 0);
+}
+
+
+void tmplput_ITERATE_KEY(StrBuf *Target, WCTemplputParams *TP)
+{
+       IterateStruct *Ctx = CCTX;
+
+       StrBufAppendBufPlain(Target, Ctx->Key, Ctx->KeyLen, 0);
+}
+
+
+void tmplput_ITERATE_LASTN(StrBuf *Target, WCTemplputParams *TP)
+{
+       IterateStruct *Ctx = CCTX;
+       StrBufAppendPrintf(Target, "%d", Ctx->n);
+}
+
+int conditional_ITERATE_LASTN(StrBuf *Target, WCTemplputParams *TP)
+{
+       IterateStruct *Ctx = CCTX;
+       return Ctx->LastN;
+}
+
+
 
 /*-----------------------------------------------------------------------------
  *                      Conditionals
@@ -1674,12 +1776,8 @@ int ConditionalVar(StrBuf *Target, WCTemplputParams *TP)
        if (!GetHash(WC->vars, TKEY(2), &vsubst))
                return 0;
        subst = (wcsubst*) vsubst;
-       if ((subst->ContextRequired != CTX_NONE) &&
-           (subst->ContextRequired != TP->ContextType)) {
-                LogTemplateError(
-                        Target, "ConditionalVar", ERR_PARM1, TP,
-                       "  WARNING: Conditional requires Context: [%ld], have [%ld]!", 
-                       subst->ContextRequired, CTX);
+       
+       if (!CheckContext(Target, &subst->Filter, TP, "Conditional")) {
                return -1;
        }
 
@@ -1706,7 +1804,6 @@ int ConditionalVar(StrBuf *Target, WCTemplputParams *TP)
        return 0;
 }
 
-
 void RegisterConditional(const char *Name, long len, 
                         int nParams,
                         WCConditionalFunc CondF, 
@@ -1716,7 +1813,22 @@ void RegisterConditional(const char *Name, long len,
        Cond->PlainName = Name;
        Cond->nParams = nParams;
        Cond->CondF = CondF;
-       Cond->ContextRequired = ContextRequired;
+       Cond->Filter.ContextType = ContextRequired;
+       Cond->Filter.ControlContextType = CTX_NONE;
+       Put(Conditionals, Name, len, Cond, NULL);
+}
+
+void RegisterControlConditional(const char *Name, long len, 
+                               int nParams,
+                               WCConditionalFunc CondF, 
+                               int ControlContextRequired)
+{
+       ConditionalStruct *Cond = (ConditionalStruct*)malloc(sizeof(ConditionalStruct));
+       Cond->PlainName = Name;
+       Cond->nParams = nParams;
+       Cond->CondF = CondF;
+       Cond->Filter.ContextType = CTX_NONE;
+       Cond->Filter.ControlContextType = ControlContextRequired;
        Put(Conditionals, Name, len, Cond, NULL);
 }
 
@@ -1763,7 +1875,7 @@ void tmpl_do_boxed(StrBuf *Target, WCTemplputParams *TP)
        }
        memcpy (&SubTP, TP, sizeof(WCTemplputParams));
        SubTP.Context = Headline;
-       SubTP.ContextType = CTX_STRBUF;
+       SubTP.Filter.ContextType = CTX_STRBUF;
        DoTemplate(HKEY("beginbox"), Target, &SubTP);
        DoTemplate(TKEY(0), Target, TP);
        DoTemplate(HKEY("endbox"), Target, TP);
@@ -2175,6 +2287,16 @@ InitModule_SUBST
        RegisterConditional(HKEY("COND:SUBST"), 3, ConditionalVar, CTX_NONE);
        RegisterConditional(HKEY("COND:CONTEXTSTR"), 3, ConditionalContextStr, CTX_STRBUF);
        RegisterConditional(HKEY("COND:LONGVECTOR"), 4, ConditionalLongVector, CTX_LONGVECTOR);
+
+       RegisterControlConditional(HKEY("COND:ITERATE:ISGROUPCHANGE"), 2, 
+                                  conditional_ITERATE_ISGROUPCHANGE, 
+                                  CTX_ITERATE);
+       RegisterControlConditional(HKEY("COND:ITERATE:LASTN"), 2, 
+                                  conditional_ITERATE_LASTN, 
+                                  CTX_ITERATE);
+       RegisterControlNS(HKEY("ITERATE:ODDEVEN"), 0, 0, tmplput_ITERATE_ODDEVEN, CTX_ITERATE);
+       RegisterControlNS(HKEY("ITERATE:KEY"), 0, 0, tmplput_ITERATE_KEY, CTX_ITERATE);
+       RegisterControlNS(HKEY("ITERATE:N"), 0, 0, tmplput_ITERATE_LASTN, CTX_ITERATE);
 }
 
 /*@}*/
index 4a488404e6cbaa9d914bc91be37c2e2f3154b35b..b39ba22dd21fab3f0e2c31143e782edabf43d5b1 100644 (file)
@@ -30,6 +30,14 @@ enum {
        WCS_LONG          /* its an integer */
 };
 
+typedef struct _contexts {
+       int ContextType;                /* do we require a context type? */
+       int ControlContextType;
+       int nMinArgs;
+       int nMaxArgs;
+} ContextFilter;
+
+
 typedef struct WCTemplateToken WCTemplateToken;
 typedef struct WCTemplputParams WCTemplputParams;
 typedef void (*WCHandlerFunc)(StrBuf *Target, WCTemplputParams *TP);
@@ -67,25 +75,27 @@ struct WCTemplateToken {
  * \brief Dynamic content for variable substitution in templates
  */
 typedef struct _wcsubst {
+       ContextFilter Filter;
        int wcs_type;                       /* which type of Substitution are we */
        char wcs_key[32];                   /* copy of our hashkey for debugging */
        StrBuf *wcs_value;                  /* if we're a string, keep it here */
        long lvalue;                        /* type long? keep data here */
-       int ContextRequired;                /* do we require a context type? */
        WCHandlerFunc wcs_function; /* funcion hook ???*/
 } wcsubst;
 
 struct WCTemplputParams {
+       ContextFilter Filter;
+       void *Context;
+       void *ControlContext;
        int nArgs;
        WCTemplateToken *Tokens;
-       void *Context;
-       int ContextType;
 };
 
 
 extern WCTemplputParams NoCtx;
 
 #define CTX TP->Context
+#define CCTX TP->ControlContext
 
 
 
@@ -105,6 +115,7 @@ extern WCTemplputParams NoCtx;
 #define CTX_LONGVECTOR 13
 #define CTX_ROOMS 14
 #define CTX_FLOORS 15
+#define CTX_ITERATE 16
 
 void RegisterNS(const char *NSName, long len, 
                int nMinArgs, 
@@ -115,9 +126,9 @@ void RegisterNS(const char *NSName, long len,
 
 typedef int (*WCConditionalFunc)(StrBuf *Target, WCTemplputParams *TP);
 typedef struct _ConditionalStruct {
+       ContextFilter Filter;
        const char *PlainName;
        int nParams;
-       int ContextRequired;
        WCConditionalFunc CondF;
 } ConditionalStruct;
 void RegisterConditional(const char *Name, long len, 
index 37320a55d2c34836d46019dd3fdb7f52ada3a9f1..42cac326b67b5ea131418970a09241ee06b87f36 100644 (file)
@@ -267,7 +267,7 @@ HashList *iterate_load_userlist(StrBuf *Target, WCTemplputParams *TP)
                        Put(Hash, nnn, nUsed, ul, DeleteUserListEntry); 
                }
                FreeStrBuf(&Buf);
-               SubTP.ContextType = CTX_USERLIST;
+               SubTP.Filter.ContextType = CTX_USERLIST;
                SortIt = RetrieveSort(&SubTP, HKEY("USER"), HKEY("user:uid"), 0);
                if (SortIt != NULL)
                        SortByPayload(Hash, SortIt);
@@ -529,7 +529,7 @@ void display_edituser(char *supplied_username, int is_new) {
                else {
                        WCTemplputParams SubTP;
                        memset(&SubTP, 0, sizeof(WCTemplputParams));
-                       SubTP.ContextType = CTX_USERLIST;
+                       SubTP.Filter.ContextType = CTX_USERLIST;
                        SubTP.Context = UL;
                        output_headers(1, 0, 0, 0, 1, 0);
                        DoTemplate(HKEY("userlist_detailview"), NULL, &SubTP);