+
+/*-----------------------------------------------------------------------------
+ * Sorting-API
+ */
+
+typedef struct _SortStruct {
+ StrBuf *Name;
+ StrBuf *PrefPrepend;
+ CompareFunc Forward;
+ CompareFunc Reverse;
+
+ long ContextType;
+}SortStruct;
+
+void DestroySortStruct(void *vSort)
+{
+ SortStruct *Sort = (SortStruct*) vSort;
+ FreeStrBuf(&Sort->Name);
+ FreeStrBuf(&Sort->PrefPrepend);
+ free (Sort);
+}
+
+void RegisterSortFunc(const char *name, long len,
+ const char *prepend, long preplen,
+ CompareFunc Forward,
+ CompareFunc Reverse,
+ long ContextType)
+{
+ SortStruct *NewSort = (SortStruct*) malloc(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->ContextType = ContextType;
+ Put(SortHash, name, len, NewSort, DestroySortStruct);
+}
+
+CompareFunc RetrieveSort(long ContextType, const char *OtherPrefix,
+ const char *Default, long ldefault, long DefaultDirection)
+{
+ int isdefault = 0;
+ const StrBuf *BSort;
+ SortStruct *SortBy;
+ void *vSortBy;
+ long SortOrder;
+
+ if (havebstr("SortBy")) {
+ BSort = sbstr("SortBy");
+ }
+ 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!
+ }
+ }
+
+ if (!GetHash(SortHash, SKEY(BSort), &vSortBy) ||
+ (vSortBy == NULL)) {
+ isdefault = 1;
+ if (!GetHash(SortHash, Default, ldefault, &vSortBy) ||
+ (vSortBy == NULL)) {
+ lprintf(1, "Illegal default sort: [%s]\n", Default);
+ wc_backtrace();
+ }
+ }
+ SortBy = (SortStruct*)vSortBy;
+
+ /** 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 (SortBy->PrefPrepend == NULL) {
+ SortOrder = StrTol(get_room_pref("SortOrder"));
+ }
+ else {
+ ////todo: nail prefprepend to sort, and lookup this!
+ }
+ }
+ 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(WCTemplateToken *Tokens, SortStruct **Next, SortStruct **Param, long *SortOrder)
+{
+ int bSortError = eNOT_SPECIFIED;
+ const StrBuf *BSort;
+ void *vSort;
+
+ *SortOrder = 0;
+ *Next = NULL;
+ if (!GetHash(SortHash, Tokens->Params[0]->Start, Tokens->Params[0]->len, &vSort) ||
+ (vSort == NULL))
+ return eNO_SUCH_SORT;
+ *Param = (SortStruct*) vSort;
+
+
+ if (havebstr("SortBy")) {
+ BSort = sbstr("SortBy");
+ bSortError = eINVALID_PARAM;
+ }
+ else { /** Try to fallback to our remembered values... */
+ if ((*Param)->PrefPrepend == NULL) {
+ BSort = get_room_pref("sort");
+ }
+ else {
+ ////todo: nail prefprepend to sort, and lookup this!
+ }
+ }
+
+ 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 {
+ ////todo: nail prefprepend to sort, and lookup this!
+ }
+ }
+ if (*SortOrder > 2)
+ *SortOrder = 0;
+
+ return eFOUND;
+}
+
+
+void tmplput_SORT_ICON(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+ long SortOrder;
+ SortStruct *Next;
+ SortStruct *Param;
+ const ConstStr *SortIcon;
+
+ switch (GetSortMetric(Tokens, &Next, &Param, &SortOrder)){
+ case eNO_SUCH_SORT:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\n [%s] (in '%s' line %ld);"
+ " Sorter [%s] unknown!\n[%s]\n</pre>\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ break;
+ case eINVALID_PARAM:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter specified by BSTR 'SortBy' [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ bstr("SortBy"),
+ ChrPtr(Tokens->FlatToken));
+ 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, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+ long SortOrder;
+ SortStruct *Next;
+ SortStruct *Param;
+
+ switch (GetSortMetric(Tokens, &Next, &Param, &SortOrder)){
+ case eNO_SUCH_SORT:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\n [%s] (in '%s' line %ld);"
+ " Sorter [%s] unknown!\n[%s]\n</pre>\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ break;
+ case eINVALID_PARAM:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter specified by BSTR 'SortBy' [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ bstr("SortBy"),
+ ChrPtr(Tokens->FlatToken));
+
+ case eNOT_SPECIFIED:
+ case eFOUND:
+ StrBufAppendBuf(Target, Param->Name, 0);
+
+ }
+}
+
+void tmplput_SORT_ORDER(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+ long SortOrder;
+ const ConstStr *SortOrderStr;
+ SortStruct *Next;
+ SortStruct *Param;
+
+ switch (GetSortMetric(Tokens, &Next, &Param, &SortOrder)){
+ case eNO_SUCH_SORT:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\n [%s] (in '%s' line %ld);"
+ " Sorter [%s] unknown!\n[%s]\n</pre>\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ break;
+ case eINVALID_PARAM:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter specified by BSTR 'SortBy' [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ bstr("SortBy"),
+ ChrPtr(Tokens->FlatToken));
+
+ case eNOT_SPECIFIED:
+ case eFOUND:
+ if (Next == Param) {
+ SortOrderStr = &SortNextOrder[SortOrder];
+ }
+ else { /** Not Us... */
+ SortOrderStr = &SortNextOrder[0];
+ }
+ StrBufAppendBufPlain(Target, SortOrderStr->Key, SortOrderStr->len, 0);
+ }
+}
+
+
+