ICONTHEME: add a way to store a selected icontheme in the users preferences.
[citadel.git] / webcit / icontheme.c
diff --git a/webcit/icontheme.c b/webcit/icontheme.c
new file mode 100644 (file)
index 0000000..d8c9984
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Displays and customizes the iconbar.
+ *
+ * Copyright (c) 1996-2012 by the citadel.org team
+ *
+ * This program is open source software.  You can redistribute it and/or
+ * modify it under the terms of the GNU General Public License, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "webcit.h"
+#include "webserver.h"
+
+HashList *AvailableThemes = NULL;
+
+const StrBuf *DefaultTheme = NULL;
+void LoadIconthemeSettings(StrBuf *icontheme, long lvalue)
+{
+       wcsession *WCC = WC;
+       void *vTheme;
+       const StrBuf *theme;
+
+       if (GetHash(AvailableThemes, SKEY(icontheme), &vTheme))
+               theme = (StrBuf*)vTheme;
+       else
+               theme = DefaultTheme;
+
+       if (WCC->IconTheme != NULL) 
+               StrBufPlain(WCC->IconTheme, SKEY(theme));
+       else
+               WCC->IconTheme = NewStrBufDup(theme);
+}
+
+
+void tmplput_icontheme(StrBuf *Target, WCTemplputParams *TP)
+{
+       wcsession *WCC = WC;
+       if ( (WCC != NULL)     &&
+            (WCC->IconTheme != NULL))
+       {
+                StrBufAppendTemplate(Target, TP, WCC->IconTheme, 0);
+       }
+       else
+       {
+                StrBufAppendTemplate(Target, TP, DefaultTheme, 0);
+       }
+}
+
+
+int LoadThemeDir(const char *DirName)
+{
+       StrBuf *Dir = NULL;
+       DIR *filedir = NULL;
+       struct dirent *d;
+       struct dirent *filedir_entry;
+       int d_type = 0;
+        int d_namelen;
+               
+       filedir = opendir (DirName);
+       if (filedir == NULL) {
+               return 0;
+       }
+
+       d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1);
+       if (d == NULL) {
+               return 0;
+       }
+
+       while ((readdir_r(filedir, d, &filedir_entry) == 0) &&
+              (filedir_entry != NULL))
+       {
+#ifdef _DIRENT_HAVE_D_NAMELEN
+               d_namelen = filedir_entry->d_namelen;
+               d_type = filedir_entry->d_type;
+#else
+
+#ifndef DT_UNKNOWN
+#define DT_UNKNOWN     0
+#define DT_DIR         4
+#define DT_REG         8
+#define DT_LNK         10
+
+#define IFTODT(mode)   (((mode) & 0170000) >> 12)
+#define DTTOIF(dirtype)        ((dirtype) << 12)
+#endif
+               d_namelen = strlen(filedir_entry->d_name);
+               d_type = DT_UNKNOWN;
+#endif
+               if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~')
+                       continue; /* Ignore backup files... */
+
+               if ((d_namelen == 1) && 
+                   (filedir_entry->d_name[0] == '.'))
+                       continue;
+
+               if ((d_namelen == 2) && 
+                   (filedir_entry->d_name[0] == '.') &&
+                   (filedir_entry->d_name[1] == '.'))
+                       continue;
+
+               if (d_type == DT_UNKNOWN) {
+                       struct stat s;
+                       char path[PATH_MAX];
+                       snprintf(path, PATH_MAX, "%s/%s", 
+                               DirName, filedir_entry->d_name);
+                       if (stat(path, &s) == 0) {
+                               d_type = IFTODT(s.st_mode);
+                       }
+               }
+
+               switch (d_type)
+               {
+               case DT_LNK: /* TODO: check whether its a file or a directory */
+               case DT_DIR:
+                       /* Skip directories we are not interested in... */
+                       if ((strcmp(filedir_entry->d_name, ".svn") == 0) ||
+                           (strcmp(filedir_entry->d_name, "t") == 0))
+                               break;
+                       
+                       Dir = NewStrBufPlain (filedir_entry->d_name, d_namelen);
+                       if (DefaultTheme == NULL)
+                               DefaultTheme = Dir;
+                       Put(AvailableThemes, SKEY(Dir), Dir, HFreeStrBuf);
+                       break;
+               case DT_REG:
+               default:
+                       break;
+               }
+
+
+       }
+       free(d);
+       closedir(filedir);
+
+       return 1;
+}
+
+HashList *GetValidThemeHash(StrBuf *Target, WCTemplputParams *TP)
+{
+       return AvailableThemes;
+}
+void 
+ServerStartModule_ICONTHEME
+(void)
+{
+       AvailableThemes = NewHash(1, NULL);
+}
+void 
+InitModule_ICONTHEME
+(void)
+{
+       StrBuf *Themes = NewStrBufPlain(static_dirs[0], -1);
+
+       StrBufAppendBufPlain(Themes, HKEY("/"), 0);
+       StrBufAppendBufPlain(Themes, HKEY("webcit_icons"), 0);
+       LoadThemeDir(ChrPtr(Themes));
+       FreeStrBuf(&Themes);
+
+       RegisterPreference("icontheme", _("Icon Theme"), PRF_STRING, LoadIconthemeSettings);
+       RegisterNamespace("ICONTHEME", 0, 0, tmplput_icontheme, NULL, CTX_NONE);
+
+       RegisterIterator("PREF:VALID:THEME", 0, NULL, 
+                        GetValidThemeHash, NULL, NULL, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
+}
+
+void 
+ServerShutdownModule_ICONTHEME
+(void)
+{
+       DeleteHash(&AvailableThemes);
+}
+
+void 
+SessionDestroyModule_ICONTHEME
+(wcsession *sess)
+{
+       FreeStrBuf(&sess->IconTheme);
+}
+