+ for (i = 0; i < ntabs; i++)
+ FreeStrBuf(&TabNames[i]);
+}
+
+void tmplput_TAB_N(StrBuf *Target, WCTemplputParams *TP)
+{
+ tab_struct *Ctx = CCTX;
+
+ StrBufAppendPrintf(Target, "%d", Ctx->CurrentTab);
+}
+
+void tmplput_TAB_TITLE(StrBuf *Target, WCTemplputParams *TP)
+{
+ tab_struct *Ctx = CCTX;
+ StrBufAppendTemplate(Target, TP, Ctx->TabTitle, 0);
+}
+
+/*-----------------------------------------------------------------------------
+ * Sorting-API
+ */
+
+
+void RegisterSortFunc(const char *name, long len,
+ const char *prepend, long preplen,
+ CompareFunc Forward,
+ CompareFunc Reverse,
+ CompareFunc GroupChange,
+ long ContextType)
+{
+ SortStruct *NewSort;
+
+ NewSort = (SortStruct*) malloc(sizeof(SortStruct));
+ memset(NewSort, 0, sizeof(SortStruct));
+ NewSort->Name = NewStrBufPlain(name, len);
+ if (prepend != NULL)
+ NewSort->PrefPrepend = NewStrBufPlain(prepend, preplen);
+ else
+ NewSort->PrefPrepend = NULL;
+ NewSort->Forward = Forward;
+ NewSort->Reverse = Reverse;
+ NewSort->GroupChange = GroupChange;
+ NewSort->ContextType = ContextType;
+ if (ContextType == CTX_NONE) {
+ lprintf(1, "sorting requires a context. CTX_NONE won't make it.\n");
+ exit(1);
+ }
+
+ Put(SortHash, name, len, NewSort, DestroySortStruct);
+}
+
+CompareFunc RetrieveSort(WCTemplputParams *TP,
+ const char *OtherPrefix, long OtherPrefixLen,
+ const char *Default, long ldefault, long DefaultDirection)
+{
+ int isdefault = 0;
+ const StrBuf *BSort = NULL;
+ SortStruct *SortBy;
+ void *vSortBy;
+ long SortOrder = -1;
+
+ 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 {
+ BSort = get_X_PREFS(HKEY("sort"), OtherPrefix, OtherPrefixLen);
+ }
+ if (BSort != NULL)
+ putbstr("SortBy", NewStrBufDup(BSort));
+ else {
+ StrBuf *Buf;
+
+ BSort = Buf = NewStrBufPlain(Default, ldefault);
+ putbstr("SortBy", Buf);
+ }
+ }
+
+ if (!GetHash(SortHash, SKEY(BSort), &vSortBy) ||
+ (vSortBy == NULL)) {
+ isdefault = 1;
+ if (!GetHash(SortHash, Default, ldefault, &vSortBy) ||
+ (vSortBy == NULL)) {
+ LogTemplateError(
+ NULL, "Sorting", ERR_PARM1, TP,
+ "Illegal default sort: [%s]", Default);
+ wc_backtrace();
+ }
+ }
+ SortBy = (SortStruct*)vSortBy;
+
+ if (SortBy->ContextType != TP->Filter.ContextType)
+ return NULL;
+
+ /** Ok, its us, lets see in which direction we should sort... */
+ if (havebstr("SortOrder")) {
+ SortOrder = LBSTR("SortOrder");
+ }
+ else { /** Try to fallback to our remembered values... */
+ StrBuf *Buf = NULL;
+ if (SortBy->PrefPrepend == NULL) {
+ Buf = get_room_pref("SortOrder");
+ SortOrder = StrTol(Buf);
+ }
+ else {
+ BSort = get_X_PREFS(HKEY("SortOrder"), OtherPrefix, OtherPrefixLen);
+ }
+
+ if (Buf == NULL)
+ SortOrder = DefaultDirection;
+
+ Buf = NewStrBufPlain(NULL, 64);
+ StrBufPrintf(Buf, "%ld", SortOrder);
+ putbstr("SortOrder", Buf);
+ }
+ switch (SortOrder) {
+ default:
+ case 0:
+ return NULL;
+ case 1:
+ return SortBy->Forward;
+ case 2:
+ return SortBy->Reverse;
+ }
+}
+
+
+enum {
+ eNO_SUCH_SORT,
+ eNOT_SPECIFIED,
+ eINVALID_PARAM,
+ eFOUND
+};
+
+ConstStr SortIcons[] = {
+ {HKEY("static/sort_none.gif")},
+ {HKEY("static/up_pointer.gif")},
+ {HKEY("static/down_pointer.gif")},
+};
+
+ConstStr SortNextOrder[] = {
+ {HKEY("1")},
+ {HKEY("2")},
+ {HKEY("0")},
+};
+
+
+int GetSortMetric(WCTemplputParams *TP, SortStruct **Next, SortStruct **Param, long *SortOrder, int N)
+{
+ int bSortError = eNOT_SPECIFIED;
+ const StrBuf *BSort;
+ void *vSort;
+
+ *SortOrder = 0;
+ *Next = NULL;
+ if (!GetHash(SortHash, TKEY(0), &vSort) ||
+ (vSort == NULL))
+ return eNO_SUCH_SORT;
+ *Param = (SortStruct*) vSort;
+
+
+ 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 = get_X_PREFS(HKEY("sort"), TKEY(N));
+ }
+ }
+
+ if (!GetHash(SortHash, SKEY(BSort), &vSort) ||
+ (vSort == NULL))
+ return bSortError;
+
+ *Next = (SortStruct*) vSort;
+
+ /** Ok, its us, lets see in which direction we should sort... */
+ if (havebstr("SortOrder")) {
+ *SortOrder = LBSTR("SortOrder");
+ }
+ else { /** Try to fallback to our remembered values... */
+ if ((*Param)->PrefPrepend == NULL) {
+ *SortOrder = StrTol(get_room_pref("SortOrder"));
+ }
+ else {
+ *SortOrder = StrTol(get_X_PREFS(HKEY("SortOrder"), TKEY(N)));
+ }
+ }
+ if (*SortOrder > 2)
+ *SortOrder = 0;
+
+ return eFOUND;
+}
+
+
+void tmplput_SORT_ICON(StrBuf *Target, WCTemplputParams *TP)
+{
+ long SortOrder;
+ SortStruct *Next;
+ SortStruct *Param;
+ const ConstStr *SortIcon;
+
+ switch (GetSortMetric(TP, &Next, &Param, &SortOrder, 2)){
+ case eNO_SUCH_SORT:
+ LogTemplateError(
+ Target, "Sorter", ERR_PARM1, TP,
+ " Sorter [%s] unknown!",
+ TP->Tokens->Params[0]->Start);
+ break;
+ case eINVALID_PARAM:
+ LogTemplateError(NULL, "Sorter", ERR_PARM1, TP,
+ " Sorter specified by BSTR 'SortBy' [%s] unknown!",
+ bstr("SortBy"));
+ case eNOT_SPECIFIED:
+ case eFOUND:
+ if (Next == Param) {
+ SortIcon = &SortIcons[SortOrder];
+ }
+ else { /** Not Us... */
+ SortIcon = &SortIcons[0];
+ }
+ StrBufAppendBufPlain(Target, SortIcon->Key, SortIcon->len, 0);
+ }
+}
+
+void tmplput_SORT_NEXT(StrBuf *Target, WCTemplputParams *TP)
+{
+ long SortOrder;
+ SortStruct *Next;
+ SortStruct *Param;
+
+ switch (GetSortMetric(TP, &Next, &Param, &SortOrder, 2)){
+ case eNO_SUCH_SORT:
+ LogTemplateError(
+ Target, "Sorter", ERR_PARM1, TP,
+ " Sorter [%s] unknown!",
+ TP->Tokens->Params[0]->Start);
+ break;
+ case eINVALID_PARAM:
+ LogTemplateError(
+ NULL, "Sorter", ERR_PARM1, TP,
+ " Sorter specified by BSTR 'SortBy' [%s] unknown!",
+ bstr("SortBy"));
+ case eNOT_SPECIFIED:
+ case eFOUND:
+ StrBufAppendBuf(Target, Param->Name, 0);
+
+ }
+}
+
+void tmplput_SORT_ORDER(StrBuf *Target, WCTemplputParams *TP)
+{
+ long SortOrder;
+ const ConstStr *SortOrderStr;
+ SortStruct *Next;
+ SortStruct *Param;
+
+ switch (GetSortMetric(TP, &Next, &Param, &SortOrder, 2)){
+ case eNO_SUCH_SORT:
+ LogTemplateError(
+ Target, "Sorter", ERR_PARM1, TP,
+ " Sorter [%s] unknown!",
+ TP->Tokens->Params[0]->Start);
+ break;
+ case eINVALID_PARAM:
+ LogTemplateError(
+ NULL, "Sorter", ERR_PARM1, TP,
+ " Sorter specified by BSTR 'SortBy' [%s] unknown!",
+ bstr("SortBy"));
+ case eNOT_SPECIFIED:
+ case eFOUND:
+ if (Next == Param) {
+ SortOrderStr = &SortNextOrder[SortOrder];
+ }
+ else { /** Not Us... */
+ SortOrderStr = &SortNextOrder[0];
+ }
+ StrBufAppendBufPlain(Target, SortOrderStr->Key, SortOrderStr->len, 0);
+ }
+}
+
+
+void tmplput_long_vector(StrBuf *Target, WCTemplputParams *TP)
+{
+ long *LongVector = (long*) CTX;
+
+ if ((TP->Tokens->Params[0]->Type == TYPE_LONG) &&
+ (TP->Tokens->Params[0]->lvalue <= LongVector[0]))
+ {
+ StrBufAppendPrintf(Target, "%ld", LongVector[TP->Tokens->Params[0]->lvalue]);
+ }
+ else
+ {
+ if (TP->Tokens->Params[0]->Type != TYPE_LONG) {
+ LogTemplateError(
+ Target, "Longvector", ERR_NAME, TP,
+ "needs a numerical Parameter!");
+ }
+ else {
+ LogTemplateError(
+ Target, "LongVector", ERR_PARM1, TP,
+ "doesn't have %ld Parameters, its just the size of %ld!",
+ TP->Tokens->Params[0]->lvalue,
+ LongVector[0]);
+ }
+ }
+}
+
+void dbg_print_longvector(long *LongVector)
+{
+ StrBuf *Buf = NewStrBufPlain(HKEY("Longvector: ["));
+ int nItems = LongVector[0];
+ int i;
+
+ for (i = 0; i < nItems; i++) {
+ if (i + 1 < nItems)
+ StrBufAppendPrintf(Buf, "%d: %ld | ", i, LongVector[i]);
+ else
+ StrBufAppendPrintf(Buf, "%d: %ld]\n", i, LongVector[i]);
+
+ }
+ lprintf(1, ChrPtr(Buf));
+ FreeStrBuf(&Buf);
+}
+
+int ConditionalLongVector(StrBuf *Target, WCTemplputParams *TP)
+{
+ long *LongVector = (long*) CTX;
+
+ if ((TP->Tokens->Params[2]->Type == TYPE_LONG) &&
+ (TP->Tokens->Params[2]->lvalue <= LongVector[0])&&
+ (TP->Tokens->Params[3]->Type == TYPE_LONG) &&
+ (TP->Tokens->Params[3]->lvalue <= LongVector[0]))
+ {
+ return LongVector[TP->Tokens->Params[2]->lvalue] ==
+ LongVector[TP->Tokens->Params[3]->lvalue];
+ }
+ else
+ {
+ if ((TP->Tokens->Params[2]->Type == TYPE_LONG) ||
+ (TP->Tokens->Params[2]->Type == TYPE_LONG)) {
+ LogTemplateError(
+ Target, "ConditionalLongvector", ERR_PARM1, TP,
+ "needs two long Parameter!");
+ }
+ else {
+ LogTemplateError(
+ Target, "Longvector", ERR_PARM1, TP,
+ "doesn't have %ld / %ld Parameters, its just the size of %ld!",
+ TP->Tokens->Params[2]->lvalue,
+ TP->Tokens->Params[3]->lvalue,
+ LongVector[0]);
+ }
+ }
+ return 0;
+}
+
+
+void tmplput_CURRENT_FILE(StrBuf *Target, WCTemplputParams *TP)
+{
+ StrBufAppendTemplate(Target, TP, TP->Tokens->FileName, 0);