+
+
+
+/*
+ * Convert a room name to a folder-ish-looking name.
+ */
+void room_to_folder(char *folder, char *room, int floor, int is_mailbox)
+{
+ int i;
+
+ /*
+ * For mailboxes, just do it straight...
+ */
+ if (is_mailbox) {
+ sprintf(folder, "My folders|%s", room);
+ }
+
+ /*
+ * Otherwise, prefix the floor name as a "public folders" moniker
+ */
+ else {
+ sprintf(folder, "%s|%s", floorlist[floor], room);
+ }
+
+ /*
+ * Replace "\" characters with "|" for pseudo-folder-delimiting
+ */
+ for (i=0; i<strlen(folder); ++i) {
+ if (folder[i] == '\\') folder[i] = '|';
+ }
+}
+
+
+
+
+/*
+ * Back end for change_view()
+ */
+void do_change_view(int newview) {
+ char buf[SIZ];
+
+ serv_printf("VIEW %d", newview);
+ serv_gets(buf);
+ WC->wc_view = newview;
+ smart_goto(WC->wc_roomname);
+}
+
+
+
+/*
+ * Change the view for this room
+ */
+void change_view(void) {
+ int view;
+
+ view = atol(bstr("view"));
+ do_change_view(view);
+}
+
+
+/*
+ * One big expanded tree list view --- like a folder list
+ */
+void do_folder_view(struct folder *fold, int max_folders, int num_floors) {
+ char buf[SIZ];
+ int levels, oldlevels;
+ int i, t;
+ int actnum = 0;
+ int has_subfolders = 0;
+
+ /* Include the menu expanding/collapsing code */
+ wprintf("<script type=\"text/javascript\" src=\"/static/menuExpandable3.js\"></script>\n");
+
+ /* BEGIN TREE MENU */
+ wprintf("<div style=\"background: white\">\n");
+ wprintf("<div id=\"mainMenu\">\n");
+ wprintf("<UL id=\"menuList\">\n");
+ levels = 0;
+ oldlevels = 0;
+
+ for (i=0; i<max_folders; ++i) {
+
+ has_subfolders = 0;
+ if ((i+1) < max_folders) {
+ if ( (!strncasecmp(fold[i].name, fold[i+1].name, strlen(fold[i].name)))
+ && (fold[i+1].name[strlen(fold[i].name)] == '|') ) {
+ has_subfolders = 1;
+ }
+ }
+
+ levels = num_tokens(fold[i].name, '|');
+
+ if ( (levels < oldlevels) || ((levels==1)&&(i!=0)) ) {
+ for (t=0; t<(oldlevels-levels); ++t) {
+ wprintf("</UL>\n");
+ }
+ }
+
+ if (has_subfolders) {
+ wprintf("<LI");
+ if (levels == 1) wprintf(" class=\"menubar\"");
+ wprintf(">");
+ wprintf("<A href=\"#\" id=\"actuator%d\" class=\"actuator\"></a>\n", actnum);
+ }
+ else {
+ wprintf("<LI>");
+ }
+
+ if (fold[i].selectable) {
+ wprintf("<A HREF=\"/dotgoto?room=");
+ urlescputs(fold[i].room);
+ wprintf("\">");
+ }
+
+ if (levels == 1) {
+ wprintf("<SPAN CLASS=\"roomlist_floor\">");
+ }
+ else if (fold[i].hasnewmsgs) {
+ wprintf("<SPAN CLASS=\"roomlist_new\">");
+ }
+ else {
+ wprintf("<SPAN CLASS=\"roomlist_old\">");
+ }
+ extract_token(buf, fold[i].name, levels-1, '|', sizeof buf);
+ escputs(buf);
+ wprintf("</SPAN>");
+
+ if (!strcasecmp(fold[i].name, "My Folders|Mail")) {
+ wprintf(" (INBOX)");
+ }
+
+ if (fold[i].selectable) {
+ wprintf("</A>");
+ }
+ wprintf("\n");
+
+ if (has_subfolders) {
+ wprintf("<UL id=\"menu%d\" class=\"%s\">\n",
+ actnum++,
+ ( (levels == 1) ? "menu" : "submenu")
+ );
+ }
+
+ oldlevels = levels;
+ }
+ wprintf("</UL></UL>\n");
+ wprintf("<img src=\"/static/blank.gif\" onLoad = ' \n");
+ for (i=0; i<actnum; ++i) {
+ wprintf(" initializeMenu(\"menu%d\", \"actuator%d\");\n", i, i);
+ }
+ wprintf(" ' > \n");
+ wprintf("</DIV>\n");
+ /* END TREE MENU */
+}
+
+/*
+ * Boxes and rooms and lists ... oh my!
+ */
+void do_rooms_view(struct folder *fold, int max_folders, int num_floors) {
+ char buf[SIZ];
+ char boxtitle[SIZ];
+ int levels, oldlevels;
+ int i, t;
+ int num_boxes = 0;
+ static int columns = 3;
+ int boxes_per_column = 0;
+ int current_column = 0;
+ int nf;
+
+ nf = num_floors;
+ while (nf % columns != 0) ++nf;
+ boxes_per_column = (nf / columns);
+ if (boxes_per_column < 1) boxes_per_column = 1;
+
+ /* Outer table (for columnization) */
+ wprintf("<TABLE BORDER=0 WIDTH=96%% CELLPADDING=5>"
+ "<tr><td valign=top>");
+
+ levels = 0;
+ oldlevels = 0;
+ for (i=0; i<max_folders; ++i) {
+
+ levels = num_tokens(fold[i].name, '|');
+
+ if ((levels == 1) && (oldlevels > 1)) {
+
+ /* End inner box */
+ do_template("endbox");
+
+ ++num_boxes;
+ if ((num_boxes % boxes_per_column) == 0) {
+ ++current_column;
+ if (current_column < columns) {
+ wprintf("</td><td valign=top>\n");
+ }
+ }
+ }
+
+ if (levels == 1) {
+
+ /* Begin inner box */
+ extract_token(buf, fold[i].name, levels-1, '|', sizeof buf);
+ stresc(boxtitle, buf, 1, 0);
+ svprintf("BOXTITLE", WCS_STRING, boxtitle);
+ do_template("beginbox");
+
+ }
+
+ oldlevels = levels;
+
+ if (levels > 1) {
+ wprintf(" ");
+ if (levels>2) for (t=0; t<(levels-2); ++t) wprintf(" ");
+ if (fold[i].selectable) {
+ wprintf("<A HREF=\"/dotgoto?room=");
+ urlescputs(fold[i].room);
+ wprintf("\">");
+ }
+ else {
+ wprintf("<i>");
+ }
+ if (fold[i].hasnewmsgs) {
+ wprintf("<SPAN CLASS=\"roomlist_new\">");
+ }
+ else {
+ wprintf("<SPAN CLASS=\"roomlist_old\">");
+ }
+ extract_token(buf, fold[i].name, levels-1, '|', sizeof buf);
+ escputs(buf);
+ wprintf("</SPAN>");
+ if (fold[i].selectable) {
+ wprintf("</A>");
+ }
+ else {
+ wprintf("</i>");
+ }
+ if (!strcasecmp(fold[i].name, "My Folders|Mail")) {
+ wprintf(" (INBOX)");
+ }
+ wprintf("<br />\n");
+ }
+ }
+ /* End the final inner box */
+ do_template("endbox");
+
+ wprintf("</TD></TR></TABLE>\n");
+}
+
+
+/*
+ * Show the room list. (only should get called by
+ * knrooms() because that's where output_headers() is called from)
+ */
+
+void list_all_rooms_by_floor(char *viewpref) {
+ char buf[SIZ];
+ int swap = 0;
+ struct folder *fold = NULL;
+ struct folder ftmp;
+ int max_folders = 0;
+ int alloc_folders = 0;
+ int i, j;
+ int ra_flags = 0;
+ int flags = 0;
+ int num_floors = 1; /* add an extra one for private folders */
+
+ /* Start with the mailboxes */
+ max_folders = 1;
+ alloc_folders = 1;
+ fold = malloc(sizeof(struct folder));
+ memset(fold, 0, sizeof(struct folder));
+ strcpy(fold[0].name, "My folders");
+ fold[0].is_mailbox = 1;
+
+ /* Then add floors */
+ serv_puts("LFLR");
+ serv_gets(buf);
+ if (buf[0]=='1') while(serv_gets(buf), strcmp(buf, "000")) {
+ if (max_folders >= alloc_folders) {
+ alloc_folders = max_folders + 100;
+ fold = realloc(fold,
+ alloc_folders * sizeof(struct folder));
+ }
+ memset(&fold[max_folders], 0, sizeof(struct folder));
+ extract_token(fold[max_folders].name, buf, 1, '|', sizeof fold[max_folders].name);
+ ++max_folders;
+ ++num_floors;
+ }
+
+ /* Now add rooms */
+ serv_puts("LKRA");
+ serv_gets(buf);
+ if (buf[0]=='1') while(serv_gets(buf), strcmp(buf, "000")) {
+ if (max_folders >= alloc_folders) {
+ alloc_folders = max_folders + 100;
+ fold = realloc(fold,
+ alloc_folders * sizeof(struct folder));
+ }
+ memset(&fold[max_folders], 0, sizeof(struct folder));
+ extract_token(fold[max_folders].room, buf, 0, '|', sizeof fold[max_folders].room);
+ ra_flags = extract_int(buf, 5);
+ flags = extract_int(buf, 1);
+ fold[max_folders].floor = extract_int(buf, 2);
+ fold[max_folders].hasnewmsgs =
+ ((ra_flags & UA_HASNEWMSGS) ? 1 : 0 );
+ if (flags & QR_MAILBOX) {
+ fold[max_folders].is_mailbox = 1;
+ }
+ room_to_folder(fold[max_folders].name,
+ fold[max_folders].room,
+ fold[max_folders].floor,
+ fold[max_folders].is_mailbox);
+ fold[max_folders].selectable = 1;
+ ++max_folders;
+ }
+
+ /* Bubble-sort the folder list */
+ for (i=0; i<max_folders; ++i) {
+ for (j=0; j<(max_folders-1)-i; ++j) {
+ if (fold[j].is_mailbox == fold[j+1].is_mailbox) {
+ swap = strcasecmp(fold[j].name, fold[j+1].name);
+ }
+ else {
+ if ( (fold[j+1].is_mailbox)
+ && (!fold[j].is_mailbox)) {
+ swap = 1;
+ }
+ else {
+ swap = 0;
+ }
+ }
+ if (swap > 0) {
+ memcpy(&ftmp, &fold[j], sizeof(struct folder));
+ memcpy(&fold[j], &fold[j+1],
+ sizeof(struct folder));
+ memcpy(&fold[j+1], &ftmp,
+ sizeof(struct folder));
+ }
+ }
+ }
+
+/* test only hackish view
+ wprintf("<table><TR><TD>A Table</TD></TR></table>\n");
+ for (i=0; i<max_folders; ++i) {
+ escputs(fold[i].name);
+ wprintf("<br />\n");
+ }
+ */
+
+ if (!strcasecmp(viewpref, "folders")) {
+ do_folder_view(fold, max_folders, num_floors);
+ }
+ else {
+ do_rooms_view(fold, max_folders, num_floors);
+ }
+
+ free(fold);
+ wDumpContent(1);
+}
+
+
+/* Do either a known rooms list or a folders list, depending on the
+ * user's preference
+ */
+void knrooms() {
+ char listviewpref[SIZ];
+
+ output_headers(1, 1, 2, 0, 0, 0, 0);
+ load_floorlist();
+
+ /* Determine whether the user is trying to change views */
+ if (bstr("view") != NULL) {
+ if (strlen(bstr("view")) > 0) {
+ set_preference("roomlistview", bstr("view"));
+ }
+ }
+
+ get_preference("roomlistview", listviewpref, sizeof listviewpref);
+
+ if ( (strcasecmp(listviewpref, "folders"))
+ && (strcasecmp(listviewpref, "table")) ) {
+ strcpy(listviewpref, "rooms");
+ }
+
+ /* title bar */
+ wprintf("<div id=\"banner\">\n"
+ "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
+ "<SPAN CLASS=\"titlebar\">"
+ );
+ if (!strcasecmp(listviewpref, "rooms")) {
+ wprintf("Room list");
+ }
+ if (!strcasecmp(listviewpref, "folders")) {
+ wprintf("Folder list");
+ }
+ if (!strcasecmp(listviewpref, "table")) {
+ wprintf("Room list");
+ }
+ wprintf("</SPAN></TD>\n");
+
+ /* offer the ability to switch views */
+ wprintf("<TD ALIGN=RIGHT><FORM NAME=\"roomlistomatic\">\n"
+ "<SELECT NAME=\"newview\" SIZE=\"1\" "
+ "OnChange=\"location.href=roomlistomatic.newview.options"
+ "[selectedIndex].value\">\n");
+
+ wprintf("<OPTION %s VALUE=\"/knrooms&view=rooms\">"
+ "View as room list"
+ "</OPTION>\n",
+ ( !strcasecmp(listviewpref, "rooms") ? "SELECTED" : "" )
+ );
+
+ wprintf("<OPTION %s VALUE=\"/knrooms&view=folders\">"
+ "View as folder list"
+ "</OPTION>\n",
+ ( !strcasecmp(listviewpref, "folders") ? "SELECTED" : "" )
+ );
+
+ wprintf("</SELECT><br />");
+ offer_start_page();
+ wprintf("</FORM></TD></TR></TABLE>\n");
+ wprintf("</div>\n"
+ "</div>\n"
+ "<div id=\"content\">\n");
+
+ /* Display the room list in the user's preferred format */
+ list_all_rooms_by_floor(listviewpref);
+}
+
+
+
+/*
+ * Set the message expire policy for this room and/or floor
+ */
+void set_room_policy(void) {
+ char buf[SIZ];
+
+ if (strcmp(bstr("sc"), "OK")) {
+ strcpy(WC->ImportantMessage,
+ "Cancelled. Changes were not saved.");
+ display_editroom();
+ return;
+ }
+
+ serv_printf("SPEX room|%d|%d", atoi(bstr("roompolicy")), atoi(bstr("roomvalue")));
+ serv_gets(buf);
+ strcpy(WC->ImportantMessage, &buf[4]);
+
+ if (WC->axlevel >= 6) {
+ strcat(WC->ImportantMessage, "<br />\n");
+ serv_printf("SPEX floor|%d|%d", atoi(bstr("floorpolicy")), atoi(bstr("floorvalue")));
+ serv_gets(buf);
+ strcat(WC->ImportantMessage, &buf[4]);
+ }
+
+ display_editroom();
+}