From e2fdc984d034b949255a49443c0b617cfef7bd88 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Tue, 1 Sep 2009 21:15:25 +0000 Subject: [PATCH] * add splitted boxheader templates for ez use in flat templates * add custom states to the groupchange detection API * create sorters for floors & rooms * add templates to replace knrooms boxed version --- webcit/debian/changelog | 19 ++ webcit/roomlist.c | 278 +++++++++++++++++++++++++++-- webcit/roomops.h | 9 +- webcit/static/t/beginbox_1.html | 2 + webcit/static/t/beginbox_2.html | 2 + webcit/static/t/knrooms.html | 32 ++++ webcit/static/t/knrooms_rooms.html | 11 ++ webcit/subst.c | 19 +- 8 files changed, 352 insertions(+), 20 deletions(-) create mode 100644 webcit/static/t/beginbox_1.html create mode 100644 webcit/static/t/beginbox_2.html create mode 100644 webcit/static/t/knrooms.html create mode 100644 webcit/static/t/knrooms_rooms.html diff --git a/webcit/debian/changelog b/webcit/debian/changelog index 9b5b5bf2f..f93842993 100644 --- a/webcit/debian/changelog +++ b/webcit/debian/changelog @@ -1,3 +1,22 @@ +webcit (7.63-84) stable; urgency=low + + * new release + + -- Wilfried Goesgens Tue, 1 Sep 2009 8:00:00 +0002 + +webcit (7.62-82) stable; urgency=low + + * new release + + -- Wilfried Goesgens Mon, 17 Aug 2009 23:00:00 +0002 + +webcit (7.61-81) stable; urgency=low + + * new release + + -- Wilfried Goesgens Tue, 6 Aug 2009 10:00:00 +0002 + + webcit (7.60-80) stable; urgency=low * new release diff --git a/webcit/roomlist.c b/webcit/roomlist.c index 4a5b3227d..e915616a4 100644 --- a/webcit/roomlist.c +++ b/webcit/roomlist.c @@ -15,26 +15,45 @@ void DeleteFloor(void *vFloor) free(Floor); } +int SortFloorsByNameOrder(const void *vfloor1, const void *vfloor2) +{ + floor *f1 = (floor*) GetSearchPayload(vfloor1); + floor *f2 = (floor*) GetSearchPayload(vfloor2); + + /* prefer My floor over alpabetical sort */ + if (f1->ID == VIRTUAL_MY_FLOOR) + return 1; + if (f2->ID == VIRTUAL_MY_FLOOR) + return -1; + + return strcmp(ChrPtr(f1->Name), ChrPtr(f2->Name)); +} + HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) { const char *Err; StrBuf *Buf; HashList *floors; + HashPos *it; floor *Floor; + void *vFloor; const char *Pos; + int i; wcsession *WCC = WC; + const char *HashKey; + long HKLen; + if (WCC->Floors != NULL) return WCC->Floors; WCC->Floors = floors = NewHash(1, NULL); Buf = NewStrBuf(); -/* + Floor = malloc(sizeof(floor)); Floor->ID = VIRTUAL_MY_FLOOR; Floor->Name = NewStrBufPlain(_("My Folders"), -1); Floor->NRooms = 0; Put(floors, IKEY(Floor->ID), Floor, DeleteFloor); -*/ serv_puts("LFLR"); /* get floors */ StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err); /* '100', we hope */ @@ -55,6 +74,16 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) { } } FreeStrBuf(&Buf); + + /* now lets pre-sort them alphabeticaly. */ + i = 1; + SortByPayload(floors, SortFloorsByNameOrder); + it = GetNewHashPos(floors, 0); + while ( GetNextHashPos(floors, it, &HKLen, &HashKey, &vFloor)) + ((floor*) vFloor)->AlphaN = i++; + DeleteHashPos(&it); + SortByHashKeyStr(floors); + return floors; } @@ -90,6 +119,7 @@ HashList *GetRoomListHashLKRA(StrBuf *Target, WCTemplputParams *TP) void DeleteFolder(void *vFolder) { + int i; folder *room; room = (folder*) vFolder; @@ -98,6 +128,12 @@ void DeleteFolder(void *vFolder) //// FreeStrBuf(&room->room); + if (room->RoomNameParts != NULL) + { + for (i=0; i < room->nRoomNameParts; i++) + FreeStrBuf(&room->RoomNameParts[i]); + free(room->RoomNameParts); + } free(room); } @@ -111,6 +147,8 @@ HashList *GetRoomListHash(StrBuf *Target, WCTemplputParams *TP) const char *Err; void *vFloor; wcsession *WCC = WC; + CompareFunc SortIt; + WCTemplputParams SubTP; Buf = NewStrBuf(); rooms = NewHash(1, NULL); @@ -125,6 +163,7 @@ HashList *GetRoomListHash(StrBuf *Target, WCTemplputParams *TP) room = (folder*) malloc (sizeof(folder)); memset(room, 0, sizeof(folder)); + /* Load the base data from the server reply */ room->name = NewStrBufPlain(NULL, StrLength(Buf)); StrBufExtract_NextToken(room->name, Buf, &Pos, '|'); @@ -140,17 +179,47 @@ HashList *GetRoomListHash(StrBuf *Target, WCTemplputParams *TP) room->defview = StrBufExtractNext_long(Buf, &Pos, '|'); room->lastchange = StrBufExtractNext_long(Buf, &Pos, '|'); /* + + /* Evaluate the Server sent data for later use */ + /* find out, whether we are in a sub-room */ + room->nRoomNameParts = StrBufNum_tokens(room->name, '\\'); + if (room->nRoomNameParts > 1) + { + int i; + + Pos = NULL; + room->RoomNameParts = malloc(sizeof(StrBuf*) * (room->nRoomNameParts + 1)); + memset(room->RoomNameParts, 0, sizeof(StrBuf*) * (room->nRoomNameParts + 1)); + for (i=0; i < room->nRoomNameParts; i++) + { + room->RoomNameParts[i] = NewStrBuf(); + StrBufExtract_NextToken(room->RoomNameParts[i], + room->name, &Pos, '\\'); + } + } + + /* Private mailboxes on the main floor get remapped to the personal folder */ if ((room->QRFlags & QR_MAILBOX) && (room->floorid == 0)) room->floorid = VIRTUAL_MY_FLOOR; -*/ + /* get a pointer to the floor we're on: */ GetHash(WCC->Floors, IKEY(room->floorid), &vFloor); room->Floor = (const floor*) vFloor; + + + + /* now we know everything, remember it... */ Put(rooms, SKEY(room->name), room, DeleteFolder); } } - SortByHashKey(rooms, 1); - /*SortByPayload(rooms, SortRoomsByListOrder); */ +/// SortByHashKey(rooms, 1); + + SubTP.Filter.ContextType = CTX_ROOMS; + SortIt = RetrieveSort(&SubTP, NULL, 0, HKEY("fileunsorted"), 0); + if (SortIt != NULL) + SortByPayload(rooms, SortIt); + else + SortByPayload(rooms, SortRoomsByListOrder); FreeStrBuf(&Buf); return rooms; } @@ -158,26 +227,180 @@ HashList *GetRoomListHash(StrBuf *Target, WCTemplputParams *TP) /** Unused function that orders rooms by the listorder flag */ int SortRoomsByListOrder(const void *room1, const void *room2) { - folder *r1 = (folder*) room1; - folder *r2 = (folder*) room2; + folder *r1 = (folder*) GetSearchPayload(room1); + folder *r2 = (folder*) GetSearchPayload(room2); if (r1->listorder == r2->listorder) return 0; if (r1->listorder > r2->listorder) return 1; return -1; } -int SortRoomsByFloorAndName(const void *room1, const void *room2) +int CompareRoomListByFloorRoomPrivFirst(const void *room1, const void *room2) { - folder *r1 = (folder*) room1; - folder *r2 = (folder*) room2; + folder *r1 = (folder*) GetSearchPayload(room1); + folder *r2 = (folder*) GetSearchPayload(room2); + /** + * are we on the same floor? else sort by floor. + */ if (r1->Floor != r2->Floor) - return strcmp(ChrPtr(r1->Floor->Name), - ChrPtr(r2->Floor->Name)); + { + /** + * the private rooms are first in any case. + */ + if (r1->Floor->ID == VIRTUAL_MY_FLOOR) + return -1; + if (r2->Floor->ID == VIRTUAL_MY_FLOOR) + return 1; + /** + * else decide alpaheticaly by floorname + */ + return (r1->Floor->AlphaN > r2->Floor->AlphaN)? 1 : -1; + } + + /** + * if we have different levels of subdirectories, + * we want the toplevel to be first, regardless of sort + * sequence. + */ + if (((r1->nRoomNameParts > 1) || + (r2->nRoomNameParts > 1) )&& + (r1->nRoomNameParts != r2->nRoomNameParts)) + { + int i, ret; + int nparts = (r1->nRoomNameParts > r2->nRoomNameParts)? + r2->nRoomNameParts : r1->nRoomNameParts; + + for (i=0; i < nparts; i++) + { + ret = strcmp (ChrPtr(r1->name), + ChrPtr(r2->name)); + /** + * Deltas in common parts? exit here. + */ + if (ret != 0) + return ret; + } + + /** + * who's a subdirectory of whom? + */ + if (r1->nRoomNameParts > r2->nRoomNameParts) + return 1; + else + return -1; + + } + + /** + * else just sort alphabeticaly. + */ return strcmp (ChrPtr(r1->name), ChrPtr(r2->name)); } +int CompareRoomListByFloorRoomPrivFirstRev(const void *room1, const void *room2) +{ + folder *r1 = (folder*) GetSearchPayload(room1); + folder *r2 = (folder*) GetSearchPayload(room2); + + /** + * are we on the same floor? else sort by floor. + */ + if (r2->Floor != r1->Floor) + { + /** + * the private rooms are first in any case. + */ + if (r1->Floor->ID == VIRTUAL_MY_FLOOR) + return -1; + if (r2->Floor->ID == VIRTUAL_MY_FLOOR) + return 1; + /** + * else decide alpaheticaly by floorname + */ + + return (r1->Floor->AlphaN < r2->Floor->AlphaN)? 1 : -1; + } + + /** + * if we have different levels of subdirectories, + * we want the toplevel to be first, regardless of sort + * sequence. + */ + if (((r1->nRoomNameParts > 1) || + (r2->nRoomNameParts > 1) )&& + (r1->nRoomNameParts != r2->nRoomNameParts)) + { + int i, ret; + int nparts = (r1->nRoomNameParts > r2->nRoomNameParts)? + r2->nRoomNameParts : r1->nRoomNameParts; + + for (i=0; i < nparts; i++) + { + /** + * special cases if one room is top-level... + */ + if (r2->nRoomNameParts == 1) + ret = strcmp (ChrPtr(r2->name), + ChrPtr(r1->RoomNameParts[i])); + else if (r1->nRoomNameParts == 1) + ret = strcmp (ChrPtr(r2->RoomNameParts[i]), + ChrPtr(r1->name)); + else + ret = strcmp (ChrPtr(r2->RoomNameParts[i]), + ChrPtr(r1->RoomNameParts[i])); + /** + * Deltas in common parts? exit here. + */ + if (ret != 0) + return ret; + } + + /** + * who's a subdirectory of whom? + */ + if (r1->nRoomNameParts > r2->nRoomNameParts) + return 1; + else + return -1; + } + + return strcmp (ChrPtr(r2->name), + ChrPtr(r1->name)); +} + +int GroupchangeRoomListByFloorRoomPrivFirst(const void *room1, const void *room2) +{ + folder *r1 = (folder*) room1; + folder *r2 = (folder*) room2; + + + if (r1->Floor == r2->Floor) + return 0; + else + { + wcsession *WCC = WC; + static int columns = 3; + int boxes_per_column = 0; + int nf; + + nf = GetCount(WCC->Floors); + while (nf % columns != 0) ++nf; + boxes_per_column = (nf / columns); + if (boxes_per_column < 1) + boxes_per_column = 1; + if (r1->Floor->AlphaN % boxes_per_column == 0) + return 2; + else + return 1; +/// wprintf("\n"); + } +} + + + + void tmplput_ROOM_NAME(StrBuf *Target, WCTemplputParams *TP) @@ -186,6 +409,31 @@ void tmplput_ROOM_NAME(StrBuf *Target, WCTemplputParams *TP) StrBufAppendTemplate(Target, TP, Folder->name, 0); } +void tmplput_ROOM_BASENAME(StrBuf *Target, WCTemplputParams *TP) +{ + folder *room = (folder *)(TP->Context); + + if (room->nRoomNameParts > 1) + StrBufAppendTemplate(Target, TP, + room->RoomNameParts[room->nRoomNameParts - 1], 0); + else + StrBufAppendTemplate(Target, TP, room->name, 0); +} +void tmplput_ROOM_LEVEL_N_TIMES(StrBuf *Target, WCTemplputParams *TP) +{ + folder *room = (folder *)(TP->Context); + int i; + const char *AppendMe; + long AppendMeLen; + + + if (room->nRoomNameParts > 1) + { + GetTemplateTokenString(Target, TP, 0, &AppendMe, &AppendMeLen); + for (i = 0; i < room->nRoomNameParts; i++) + StrBufAppendBufPlain(Target, AppendMe, AppendMeLen, 0); + } +} void tmplput_ROOM_ACL(StrBuf *Target, WCTemplputParams *TP) { @@ -306,6 +554,9 @@ InitModule_ROOMLIST RegisterNamespace("ROOM:INFO:FLOORID", 0, 1, tmplput_ROOM_FLOORID, CTX_ROOMS); RegisterNamespace("ROOM:INFO:NAME", 0, 1, tmplput_ROOM_NAME, CTX_ROOMS); + RegisterNamespace("ROOM:INFO:BASENAME", 0, 1, tmplput_ROOM_BASENAME, CTX_ROOMS); + RegisterNamespace("ROOM:INFO:LEVELNTIMES", 1, 2, tmplput_ROOM_LEVEL_N_TIMES, CTX_ROOMS); + RegisterNamespace("ROOM:INFO:ACL", 0, 1, tmplput_ROOM_ACL, CTX_ROOMS); RegisterNamespace("ROOM:INFO:QRFLAGS", 0, 1, tmplput_ROOM_QRFLAGS, CTX_ROOMS); RegisterNamespace("ROOM:INFO:LISTORDER", 0, 1, tmplput_ROOM_LISTORDER, CTX_ROOMS); @@ -316,12 +567,11 @@ InitModule_ROOMLIST RegisterNamespace("ROOM:INFO:FLOOR:NAME", 0, 1, tmplput_ROOM_FLOOR_NAME, CTX_ROOMS); RegisterNamespace("ROOM:INFO:FLOOR:NROOMS", 0, 0, tmplput_ROOM_FLOOR_NROOMS, CTX_ROOMS); -/* RegisterSortFunc(HKEY("byfloorroom"), NULL, 0, CompareRoomListByFloorRoomPrivFirst, CompareRoomListByFloorRoomPrivFirstRev, GroupchangeRoomListByFloorRoomPrivFirst, CTX_ROOMS); -*/ + } diff --git a/webcit/roomops.h b/webcit/roomops.h index c569d4e29..50edc6ccf 100644 --- a/webcit/roomops.h +++ b/webcit/roomops.h @@ -32,6 +32,7 @@ typedef struct _floor { long ID; StrBuf *Name; long NRooms; + long AlphaN; } floor; /** @@ -54,7 +55,8 @@ struct __ofolder { * \brief Data structure for roomlist-to-folderlist conversion */ typedef struct _folder { - StrBuf *name; /* which is its own name??? */ + /* Data citserver tells us about the room */ + StrBuf *name; /* the full name of the room we're talking about */ int QRFlags; /* roomflags */ int floorid; /* which floor is it on */ @@ -67,8 +69,9 @@ typedef struct _folder { int defview; int lastchange; /* todo... */ - - + /* later evaluated data from the serverdata */ + long nRoomNameParts; + StrBuf **RoomNameParts; const floor *Floor; /* pint to the floor we're on.. */ StrBuf *room; /* which roomname ??? */ diff --git a/webcit/static/t/beginbox_1.html b/webcit/static/t/beginbox_1.html new file mode 100644 index 000000000..2d425d1ff --- /dev/null +++ b/webcit/static/t/beginbox_1.html @@ -0,0 +1,2 @@ +
+
diff --git a/webcit/static/t/beginbox_2.html b/webcit/static/t/beginbox_2.html new file mode 100644 index 000000000..a36b1078b --- /dev/null +++ b/webcit/static/t/beginbox_2.html @@ -0,0 +1,2 @@ +
+
diff --git a/webcit/static/t/knrooms.html b/webcit/static/t/knrooms.html new file mode 100644 index 000000000..061022315 --- /dev/null +++ b/webcit/static/t/knrooms.html @@ -0,0 +1,32 @@ + + + +
+ + + +
+ + diff --git a/webcit/static/t/knrooms_rooms.html b/webcit/static/t/knrooms_rooms.html new file mode 100644 index 000000000..910ce0276 --- /dev/null +++ b/webcit/static/t/knrooms_rooms.html @@ -0,0 +1,11 @@ + + + + + +
+ + +">
+ diff --git a/webcit/subst.c b/webcit/subst.c index b24ec13f3..fbbb6b8e1 100644 --- a/webcit/subst.c +++ b/webcit/subst.c @@ -1977,7 +1977,7 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP) 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.GroupChange = SortBy->GroupChange(vContext, vLastContext); } Status.LastN = (Status.n + 1) == nMembersUsed; SubTP.Context = vContext; @@ -2002,7 +2002,10 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP) int conditional_ITERATE_ISGROUPCHANGE(StrBuf *Target, WCTemplputParams *TP) { IterateStruct *Ctx = CCTX; - return Ctx->GroupChange; + if (TP->Tokens->nParameters < 3) + return Ctx->GroupChange; + + return TP->Tokens->Params[2]->lvalue == Ctx->GroupChange; } void tmplput_ITERATE_ODDEVEN(StrBuf *Target, WCTemplputParams *TP) @@ -2029,6 +2032,12 @@ void tmplput_ITERATE_LASTN(StrBuf *Target, WCTemplputParams *TP) StrBufAppendPrintf(Target, "%d", Ctx->n); } +int conditional_ITERATE_FIRSTN(StrBuf *Target, WCTemplputParams *TP) +{ + IterateStruct *Ctx = CCTX; + return Ctx->n == 0; +} + int conditional_ITERATE_LASTN(StrBuf *Target, WCTemplputParams *TP) { IterateStruct *Ctx = CCTX; @@ -2175,7 +2184,7 @@ void tmpl_do_boxed(StrBuf *Target, WCTemplputParams *TP) Headline = NewStrBufPlain(Ch, len); } } - memcpy (&SubTP, TP, sizeof(WCTemplputParams)); + memcpy (&SubTP, TP, sizeof(WCTemplputParams)); SubTP.Context = Headline; SubTP.Filter.ContextType = CTX_STRBUF; DoTemplate(HKEY("beginbox"), Target, &SubTP); @@ -2601,6 +2610,10 @@ InitModule_SUBST RegisterControlConditional(HKEY("COND:ITERATE:LASTN"), 2, conditional_ITERATE_LASTN, CTX_ITERATE); + RegisterControlConditional(HKEY("COND:ITERATE:FIRSTN"), 2, + conditional_ITERATE_FIRSTN, + 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); -- 2.30.2