HashList *SortHash;
int LoadTemplates = 0;
+int dbg_bactrace_template_errors = 0;
WCTemplputParams NoCtx;
#define SV_GETTEXT 1
StrBuf *FileName;
int nTokensUsed;
int TokenSpace;
+ StrBuf *MimeType;
WCTemplateToken **Tokens;
} WCTemplate;
typedef struct _HashHandler {
- int nMinArgs;
- int nMaxArgs;
- int ContextRequired;
+ ContextFilter Filter;
+
WCHandlerFunc HandlerFunc;
}HashHandler;
void *load_template(StrBuf *filename, StrBuf *Key, HashList *PutThere);
int EvaluateConditional(StrBuf *Target, int Neg, int state, WCTemplputParams *TP);
+
+
typedef struct _SortStruct {
StrBuf *Name;
StrBuf *PrefPrepend;
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",
+ "Context UNKNOWN"
+};
+
+
+
void DestroySortStruct(void *vSort)
{
SortStruct *Sort = (SortStruct*) vSort;
free (Sort);
}
+const char *ContextName(int ContextType)
+{
+ if (ContextType < CTX_UNKNOWN)
+ return CtxNames[ContextType];
+ else
+ return CtxNames[CTX_UNKNOWN];
+}
+
void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplputParams *TP, const char *Format, ...)
{
+ wcsession *WCC;
+ StrBuf *Header;
StrBuf *Error;
StrBuf *Info;
va_list arg_ptr;
switch (ErrorPos) {
default:
case ERR_NAME: /* the main token name... */
- Err = TP->Tokens->pName;
+ Err = (TP->Tokens!= NULL)? TP->Tokens->pName:"";
break;
case ERR_PARM1:
- Err = TP->Tokens->Params[0]->Start;
+ Err = (TP->Tokens!= NULL)? TP->Tokens->Params[0]->Start:"";
break;
case ERR_PARM2:
- Err = TP->Tokens->Params[1]->Start;
+ Err = (TP->Tokens!= NULL)? TP->Tokens->Params[1]->Start:"";
break;
}
- lprintf(1, "%s [%s] (in '%s' line %ld); %s; [%s]\n",
- Type,
- Err,
- ChrPtr(TP->Tokens->FileName),
- TP->Tokens->Line,
- ChrPtr(Error),
- ChrPtr(TP->Tokens->FlatToken));
- if (Target != NULL) {
+ if (TP->Tokens != NULL)
+ {
+ lprintf(1, "%s [%s] (in '%s' line %ld); %s; [%s]\n",
+ Type,
+ Err,
+ ChrPtr(TP->Tokens->FileName),
+ TP->Tokens->Line,
+ ChrPtr(Error),
+ ChrPtr(TP->Tokens->FlatToken));
+ }
+ else
+ {
+ lprintf(1, "%s: %s;\n",
+ Type,
+ ChrPtr(Error));
+ }
+ if (Target == NULL)
+ return;
+ WCC = WC;
+ Header = NewStrBuf();
+ if (TP->Tokens != NULL)
+ {
+ /* deprecated:
StrBufAppendPrintf(
Target,
"<pre>\n%s [%s] (in '%s' line %ld); %s\n[%s]\n</pre>\n",
TP->Tokens->Line,
ChrPtr(Error),
ChrPtr(TP->Tokens->FlatToken));
+ */
+ StrBufPrintf(Info, "%s [%s] %s; [%s]",
+ Type,
+ Err,
+ ChrPtr(Error),
+ ChrPtr(TP->Tokens->FlatToken));
+
+
+ SerializeJson(Header, WildFireException(SKEY(TP->Tokens->FileName),
+ TP->Tokens->Line,
+ Info,
+ 1), 1);
+/*
+ SerializeJson(Header, WildFireMessage(SKEY(TP->Tokens->FileName),
+ TP->Tokens->Line,
+ Error,
+ eERROR), 1);
+*/
+ WildFireSerializePayload(Header, WCC->HBuf, &WCC->nWildfireHeaders, NULL);
}
+ else
+ {
+ /* deprecated.
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\n%s: %s\n</pre>\n",
+ Type,
+ ChrPtr(Error));
+ */
+ StrBufPrintf(Info, "%s [%s] %s; [%s]",
+ Type,
+ Err,
+ ChrPtr(Error),
+ ChrPtr(TP->Tokens->FlatToken));
+ SerializeJson(Header, WildFireException(HKEY(__FILE__), __LINE__, Info, 1), 1);
+ WildFireSerializePayload(Header, WCC->HBuf, &WCC->nWildfireHeaders, NULL);
+ }
+ FreeStrBuf(&Header);
+ FreeStrBuf(&Info);
+ FreeStrBuf(&Error);
+/*
+ if (dbg_bactrace_template_errors)
+ wc_backtrace();
+*/
}
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;
+ 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;
- NewHandler->ContextRequired = ContextRequired;
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]!",
+ ContextName(Need->ContextType),
+ ContextName(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]!",
+ ContextName(Need->ControlContextType),
+ ContextName(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",
+ Need->nMaxArgs,
+ TP->Tokens->nParameters);
+ return 0;
+
+ }
+*/
+ return 1;
+}
+
void FreeToken(WCTemplateToken **Token)
{
int i;
}
FreeStrBuf(&FreeMe->FileName);
FreeStrBuf(&FreeMe->Data);
+ FreeStrBuf(&FreeMe->MimeType);
free(FreeMe);
}
}
}
-void GetTemplateTokenString(WCTemplputParams *TP,
+void GetTemplateTokenString(StrBuf *Target,
+ WCTemplputParams *TP,
int N,
const char **Value,
long *len)
WCTemplputParams SubTP;
if (TP->Tokens->nParameters < N) {
- lprintf(1, "invalid token. this shouldn't have come till here.\n");
- wc_backtrace();
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "invalid token %d. this shouldn't have come till here.\n", N);
*Value = "";
*len = 0;
return;
*len = StrLength(Buf);
break;
case TYPE_LONG:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "Requesting parameter %d; of type LONG, want string.", N);
+ break;
case TYPE_PREFINT:
- break; /* todo: string to text? */
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "Requesting parameter %d; of type PREFINT, want string.", N);
+ break;
case TYPE_GETTEXT:
*Value = _(TP->Tokens->Params[N]->Start);
*len = strlen(*Value);
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);
break;
default:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "unknown param type %d; [%d]", N, TP->Tokens->Params[N]->Type);
+ break;
+ }
+}
+
+long GetTemplateTokenNumber(StrBuf *Target, WCTemplputParams *TP, int N, long dflt)
+{
+ long Ret;
+ if (TP->Tokens->nParameters < N) {
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "invalid token %d. this shouldn't have come till here.\n", N);
+ wc_backtrace();
+ return 0;
+ }
+
+ switch (TP->Tokens->Params[N]->Type) {
+
+ case TYPE_STR:
+ return atol(TP->Tokens->Params[N]->Start);
break;
-/*/todo log error */
+ case TYPE_BSTR:
+ return LBstr(TKEY(N));
+ break;
+ case TYPE_PREFSTR:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "requesting a prefstring in param %d want a number", N);
+ if (get_PREF_LONG(TKEY(N), &Ret, dflt))
+ return Ret;
+ return 0;
+ case TYPE_LONG:
+ return TP->Tokens->Params[N]->lvalue;
+ case TYPE_PREFINT:
+ if (get_PREF_LONG(TKEY(N), &Ret, dflt))
+ return Ret;
+ return 0;
+ case TYPE_GETTEXT:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "requesting a I18N string in param %d; want a number", N);
+ return 0;
+ case TYPE_SUBTEMPLATE:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "requesting a subtemplate in param %d; not supported for numbers", N);
+ return 0;
+ default:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "unknown param type %d; [%d]", N, TP->Tokens->Params[N]->Type);
+ return 0;
}
}
else {
LogTemplateError(
Target, "Token", ERR_NAME, TP,
- "didn't find Handler");
+ "didn't find Handler \"%s\"", TP->Tokens->pName);
wc_backtrace();
}
}
const StrBuf *Source, int FormatTypeIndex)
{
wcsession *WCC;
- StrBuf *Buf;
char EscapeAs = ' ';
if ((FormatTypeIndex < TP->Tokens->nParameters) &&
{
case 'H':
WCC = WC;
- Buf = NewStrBufPlain(NULL, StrLength(Source));
- StrBuf_RFC822_to_Utf8(Buf,
- Source,
- (WCC!=NULL)? WCC->DefaultCharset : NULL,
- NULL);
- StrEscAppend(Target, Buf, NULL, 0, 0);
- FreeStrBuf(&Buf);
+ StrEscAppend(Target, Source, NULL, 0, 2);
break;
case 'X':
StrEscAppend(Target, Source, NULL, 0, 0);
if (NewToken->nParameters > MAXPARAM) {
LogTemplateError(
NULL, "Parseerror", ERR_NAME, &TP,
- "only [%ld] Params allowed in Tokens",
+ "only [%d] Params allowed in Tokens",
MAXPARAM);
free(Param);
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",
+ "doesn't work with %d params",
NewToken->nParameters);
}
if (NewToken->nParameters !=1) {
LogTemplateError(
NULL, "Gettext", ERR_NAME, &TP,
- "requires exactly 1 parameter, you gave %ld params",
+ "requires exactly 1 parameter, you gave %d params",
NewToken->nParameters);
NewToken->Flags = 0;
break;
if (NewToken->nParameters != 1) {
LogTemplateError(
NULL, "Subtemplates", ERR_NAME, &TP,
- "require exactly 1 parameter, you gave %ld params",
+ "require exactly 1 parameter, you gave %d params",
NewToken->nParameters);
break;
}
if (NewToken->nParameters <2) {
LogTemplateError(
NULL, "Conditional", ERR_NAME, &TP,
- "require at least 2 parameters, you gave %ld params",
+ "require at least 2 parameters, you gave %d params",
NewToken->nParameters);
NewToken->Flags = 0;
break;
NewTemplate->nTokensUsed = 0;
NewTemplate->TokenSpace = 0;
NewTemplate->Tokens = NULL;
+ NewTemplate->MimeType = NewStrBufPlain(GuessMimeByFilename (SKEY(NewTemplate->FileName)), -1);
+ if (strstr(ChrPtr(NewTemplate->MimeType), "text") != NULL) {
+ StrBufAppendBufPlain(NewTemplate->MimeType, HKEY("; charset=utf-8"), 0);
+ }
Put(PutThere, ChrPtr(Key), StrLength(Key), NewTemplate, FreeWCTemplate);
return NewTemplate;
NewTemplate->nTokensUsed = 0;
NewTemplate->TokenSpace = 0;
NewTemplate->Tokens = NULL;
+ NewTemplate->MimeType = NewStrBufPlain(GuessMimeByFilename (SKEY(NewTemplate->FileName)), -1);
+ if (strstr(ChrPtr(NewTemplate->MimeType), "text") != NULL) {
+ StrBufAppendBufPlain(NewTemplate->MimeType, HKEY("; charset=utf-8"), 0);
+ }
+
if (StrBufReadBLOB(NewTemplate->Data, &fd, 1, statbuf.st_size, &Err) < 0) {
close(fd);
FreeWCTemplate(NewTemplate);
long AppendMeLen;
HashHandler *Handler;
void *vVar;
+
/* much output, since pName is not terminated...
lprintf(1,"Doing token: %s\n",Token->pName);
*/
case SV_CUST_STR_CONDITIONAL: /** Conditional put custom strings from params */
if (TP->Tokens->nParameters >= 6) {
if (EvaluateConditional(Target, 0, state, TP)) {
- GetTemplateTokenString(TP, 5, &AppendMe, &AppendMeLen);
+ GetTemplateTokenString(Target, TP, 5, &AppendMe, &AppendMeLen);
StrBufAppendBufPlain(Target,
AppendMe,
AppendMeLen,
0);
}
else{
- GetTemplateTokenString(TP, 4, &AppendMe, &AppendMeLen);
+ GetTemplateTokenString(Target, TP, 4, &AppendMe, &AppendMeLen);
StrBufAppendBufPlain(Target,
AppendMe,
AppendMeLen,
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);
}
-void ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, void *Context, int ContextType)
+const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams *CallingTP)
{
WCTemplate *pTmpl = Tmpl;
int done = 0;
long len;
WCTemplputParams TP;
- TP.Context = Context;
- TP.ContextType = ContextType;
+ memcpy(&TP.Filter, &CallingTP->Filter, sizeof(ContextFilter));
+
+ TP.Context = CallingTP->Context;
+ TP.ControlContext = CallingTP->ControlContext;
if (LoadTemplates != 0) {
if (LoadTemplates > 1)
Target,
"<pre>\nError loading Template [%s]\n See Logfile for details\n</pre>\n",
ChrPtr(Tmpl->FileName));
- return;
+ return NULL;
}
}
if (LoadTemplates != 0) {
FreeWCTemplate(pTmpl);
}
+ return Tmpl->MimeType;
+
}
/**
* \brief Display a variable-substituted template
* \param templatename template file to load
+ * \returns the mimetype of the template its doing
*/
-void DoTemplate(const char *templatename, long len, StrBuf *Target, WCTemplputParams *TP)
+const StrBuf *DoTemplate(const char *templatename, long len, StrBuf *Target, WCTemplputParams *TP)
{
+ WCTemplputParams LocalTP;
HashList *Static;
HashList *StaticLocal;
void *vTmpl;
if (Target == NULL)
Target = WC->WBuf;
+ if (TP == NULL) {
+ memset(&LocalTP, 0, sizeof(WCTemplputParams));
+ TP = &LocalTP;
+ }
+
if (WC->is_mobile) {
Static = WirelessTemplateCache;
StaticLocal = WirelessLocalTemplateCache;
{
lprintf (1, "Can't to load a template with empty name!\n");
StrBufAppendPrintf(Target, "<pre>\nCan't to load a template with empty name!\n</pre>");
- return;
+ return NULL;
}
if (!GetHash(StaticLocal, templatename, len, &vTmpl) &&
dbg_PrintHash(Static, PrintTemplate, NULL);
PrintHash(Static, VarPrintTransition, PrintTemplate);
#endif
- return;
+ return NULL;
}
if (vTmpl == NULL)
- return;
- ProcessTemplate(vTmpl, Target, TP->Context, TP->ContextType);
+ return NULL;
+ return ProcessTemplate(vTmpl, Target, TP);
+
}
/*-----------------------------------------------------------------------------
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;
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;
+ long StartAt = 0;
+ long StepWidth = 0;
+ long StopAt = -1;
+
+ memset(&Status, 0, sizeof(IterateStruct));
memcpy (&SubTP, &TP, sizeof(WCTemplputParams));
if (!GetHash(Iterators, TKEY(0), &vIt)) {
if (TP->Tokens->nParameters < It->AdditionalParams + 2) {
LogTemplateError(
Target, "Iterator", ERR_PARM1, TP,
- "doesn't work with %ld params",
+ "doesn't work with %d params",
TP->Tokens->nParameters);
return;
}
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",
+ "requires context of type %d, have %d",
It->XPectContextType,
- TP->ContextType);
+ TP->Filter.ContextType);
return ;
}
}
nMembersUsed = GetCount(List);
SubBuf = NewStrBuf();
- SubTP.ContextType = It->ContextType;
- 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);
- }
- 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);
- SubTP.Context = vContext;
- if (It->DoSubTemplate != NULL)
- It->DoSubTemplate(SubBuf, &SubTP);
- DoTemplate(TKEY(1), SubBuf, &SubTP);
+ SubTP.Filter.ContextType = It->ContextType;
+ SubTP.Filter.ControlContextType = CTX_ITERATE;
+ SubTP.ControlContext = &Status;
+
+ if (HAVE_PARAM(2)) {
+ StartAt = GetTemplateTokenNumber(Target, TP, 2, 0);
+ }
+ if (HAVE_PARAM(3)) {
+ StepWidth = GetTemplateTokenNumber(Target, TP, 3, 0);
+ }
+ if (HAVE_PARAM(4)) {
+ StopAt = GetTemplateTokenNumber(Target, TP, 4, -1);
+ }
+ it = GetNewHashPos(List, StepWidth);
+ if (StopAt < 0) {
+ StopAt = GetCount(List);
+ }
+ while (GetNextHashPos(List, it, &Status.KeyLen, &Status.Key, &vContext)) {
+ if ((Status.n >= StartAt) && (Status.n <= StopAt)) {
+ if (DetectGroupChange && Status.n > 0) {
+ Status.GroupChange = (SortBy->GroupChange(vContext, vLastContext))? 1:0;
+ }
+ Status.LastN = (Status.n + 1) == nMembersUsed;
+ SubTP.Context = vContext;
+ if (It->DoSubTemplate != NULL)
+ It->DoSubTemplate(SubBuf, &SubTP);
+ DoTemplate(TKEY(1), SubBuf, &SubTP);
- StrBufAppendBuf(Target, SubBuf, 0);
- FlushStrBuf(SubBuf);
- oddeven = ~ oddeven;
- vLastContext = vContext;
+ StrBufAppendBuf(Target, SubBuf, 0);
+ FlushStrBuf(SubBuf);
+ Status.oddeven = ! Status.oddeven;
+ vLastContext = vContext;
+ }
+ Status.n++;
}
FreeStrBuf(&SubBuf);
DeleteHashPos(&it);
}
+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
return 1;
}
- if (TP->Tokens->nParameters < Cond->nParams) {
- LogTemplateError(
- Target, "Conditional", ERR_PARM1, TP,
- "needs %ld Params, have %ld!",
- Cond->nParams,
- TP->Tokens->nParameters);
+ if (!CheckContext(Target, &Cond->Filter, TP, "Conditional")) {
return 0;
}
+
if (Cond->CondF(Target, TP) == Neg)
return TP->Tokens->Params[1]->lvalue;
return 0;
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);
- return -1;
- }
-
+
switch(subst->wcs_type) {
case WCS_FUNCTION:
return (subst->wcs_function!=NULL);
return 0;
}
-
void RegisterConditional(const char *Name, long len,
int nParams,
WCConditionalFunc CondF,
{
ConditionalStruct *Cond = (ConditionalStruct*)malloc(sizeof(ConditionalStruct));
Cond->PlainName = Name;
- Cond->nParams = nParams;
+ Cond->Filter.nMaxArgs = nParams;
+ Cond->Filter.nMinArgs = nParams;
+ Cond->CondF = CondF;
+ 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->Filter.nMaxArgs = nParams;
+ Cond->Filter.nMinArgs = nParams;
Cond->CondF = CondF;
- Cond->ContextRequired = ContextRequired;
+ Cond->Filter.ContextType = CTX_NONE;
+ Cond->Filter.ControlContextType = ControlContextRequired;
Put(Conditionals, Name, len, Cond, NULL);
}
const char *CompareToken;
long len;
- GetTemplateTokenString(TP, 2, &CompareToken, &len);
+ GetTemplateTokenString(Target, TP, 2, &CompareToken, &len);
return strcmp(ChrPtr(TokenText), CompareToken) == 0;
}
else {
const char *Ch;
long len;
- GetTemplateTokenString(TP,
+ GetTemplateTokenString(Target,
+ TP,
1,
&Ch,
&len);
}
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);
else if (TP->Tokens->Params[i * 2]->Type == TYPE_GETTEXT) {
const char *Ch;
long len;
- GetTemplateTokenString(TP,
+ GetTemplateTokenString(Target,
+ TP,
i * 2,
&Ch,
&len);
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);
}
/*@}*/