Enlightenment CVS committal

Author  : kwo
Project : e16
Module  : e

Dir     : e16/e/src


Modified Files:
        E.h aclass.c borders.c config.c draw.c iconify.c ipc.c 
        mod-misc.c pager.c session.c theme.c windowmatch.c 


Log Message:
Merge windowmatches and icondefs.
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/E.h,v
retrieving revision 1.357
retrieving revision 1.358
diff -u -3 -r1.357 -r1.358
--- E.h 2 Feb 2005 17:11:25 -0000       1.357
+++ E.h 6 Feb 2005 19:13:12 -0000       1.358
@@ -789,25 +789,6 @@
    GroupConfig         cfg;
 };
 
-typedef struct _windowmatch
-{
-   char               *name;
-   char               *win_title;
-   char               *win_name;
-   char               *win_class;
-   Constraints         width;
-   Constraints         height;
-   signed char         transient;
-   signed char         no_resize_h;
-   signed char         no_resize_v;
-   signed char         shaped;
-   Border             *border;
-   ImageClass         *icon;
-   int                 desk;
-   char                make_sticky;
-}
-WindowMatch;
-
 /* Configuration parameters */
 typedef struct
 {
@@ -1238,6 +1219,9 @@
 /* borders.c */
 Border             *BorderCreate(const char *name);
 void                BorderDestroy(Border * b);
+void                BorderIncRefcount(const Border * b);
+void                BorderDecRefcount(const Border * b);
+const char         *BorderGetName(const Border * b);
 int                 BorderConfigLoad(FILE * fs);
 void                BorderWinpartAdd(Border * b, ImageClass * ic,
                                     ActionClass * aclass, TextClass * tclass,
@@ -1343,7 +1327,7 @@
 int                 ConfigFileLoad(const char *name, const char *themepath,
                                   int (*parse) (FILE * fs));
 int                 ThemeConfigLoad(void);
-void                SaveUserControlConfig(const char *file);
+void                SaveUserControlConfig(void);
 void                RecoverUserConfig(void);
 
 /* coords.c */
@@ -1500,7 +1484,7 @@
 void                ScaleRect(Pixmap dest, Window src, int sx, int sy, int dx,
                              int dy, int sw, int sh, int dw, int dh);
 
-Imlib_Image        *ELoadImage(char *file);
+Imlib_Image        *ELoadImage(const char *file);
 void                DrawEwinShape(EWin * ewin, int md, int x, int y, int w,
                                  int h, char firstlast);
 void                PropagateShapes(Window win);
@@ -2199,14 +2183,11 @@
 void                WarpFocus(int delta);
 
 /* windowmatch.c */
-int                 WindowMatchConfigLoad(FILE * fs);
-Border             *MatchEwinBorder(EWin * ewin, WindowMatch * b);
-ImageClass         *MatchEwinIcon(EWin * ewin, WindowMatch * b);
-int                 MatchEwinDesktop(EWin * ewin, WindowMatch * b);
-void               *MatchEwinByFunction(EWin * ewin,
-                                       void *(*FunctionToTest) (EWin *,
-                                                                WindowMatch
-                                                                *));
+typedef struct _windowmatch WindowMatch;
+
+void               *WindowMatchEwin(EWin * ewin);
+Border             *WindowMatchEwinBorder(const EWin * ewin);
+const char         *WindowMatchEwinIcon(const EWin * ewin);
 
 /* x.c */
 Display            *EDisplayOpen(const char *dstr);
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/aclass.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -3 -r1.7 -r1.8
--- aclass.c    6 Feb 2005 08:18:50 -0000       1.7
+++ aclass.c    6 Feb 2005 19:13:28 -0000       1.8
@@ -618,7 +618,9 @@
        if (!ss)
           break;
 
-       len = strcspn(s, "\r\n");
+       len = strcspn(s, "#\r\n");
+       if (len <= 0)
+          continue;
        s[len] = '\0';
 
        prm3[0] = '\0';
@@ -1002,9 +1004,6 @@
      {
      case ESIGNAL_INIT:
        AclassSetupFallback();
-#if 0
-       ConfigFileLoad("keybindings.cfg", NULL, AclassConfigLoad);
-#endif
        AclassConfigLoadConfig();
        AclassConfigLoadUser();
        break;
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/borders.c,v
retrieving revision 1.248
retrieving revision 1.249
diff -u -3 -r1.248 -r1.249
--- borders.c   2 Feb 2005 17:11:30 -0000       1.248
+++ borders.c   6 Feb 2005 19:13:28 -0000       1.249
@@ -471,18 +471,24 @@
    Efree(a);
 }
 
-static void
+void
 BorderIncRefcount(const Border * b)
 {
    ((Border *) b)->ref_count++;
 }
 
-static void
+void
 BorderDecRefcount(const Border * b)
 {
    ((Border *) b)->ref_count--;
 }
 
+const char         *
+BorderGetName(const Border * b)
+{
+   return (b) ? b->name : NULL;
+}
+
 void
 EwinBorderSelect(EWin * ewin)
 {
@@ -495,18 +501,14 @@
 
    ICCCM_GetShapeInfo(ewin);
 
-   if ((!ewin->client.mwm_decor_title) && (!ewin->client.mwm_decor_border))
-      b = (Border *) FindItem("BORDERLESS", 0, LIST_FINDBY_NAME,
-                             LIST_TYPE_BORDER);
+   if ((!ewin->client.mwm_decor_title && !ewin->client.mwm_decor_border) ||
+       (Conf.dock.enable && ewin->docked))
+      b = FindItem("BORDERLESS", 0, LIST_FINDBY_NAME, LIST_TYPE_BORDER);
    else
-      b = MatchEwinByFunction(ewin,
-                             (void
-                              *(*)(EWin *, WindowMatch *))(MatchEwinBorder));
-   if (Conf.dock.enable && ewin->docked)
-      b = (Border *) FindItem("BORDERLESS", 0, LIST_FINDBY_NAME,
-                             LIST_TYPE_BORDER);
+      b = WindowMatchEwinBorder(ewin);
+
    if (!b)
-      b = (Border *) FindItem("DEFAULT", 0, LIST_FINDBY_NAME, 
LIST_TYPE_BORDER);
+      b = FindItem("DEFAULT", 0, LIST_FINDBY_NAME, LIST_TYPE_BORDER);
 
    if (!b)
       b = FindItem("__FALLBACK_BORDER", 0, LIST_FINDBY_NAME, LIST_TYPE_BORDER);
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/config.c,v
retrieving revision 1.124
retrieving revision 1.125
diff -u -3 -r1.124 -r1.125
--- config.c    29 Jan 2005 07:11:56 -0000      1.124
+++ config.c    6 Feb 2005 19:13:29 -0000       1.125
@@ -351,11 +351,6 @@
                       if (err)
                          ConfigAlertLoad(_("Background"));
                       break;
-                   case CONFIG_WINDOWMATCH:
-                      err = WindowMatchConfigLoad(fs);
-                      if (err)
-                         ConfigAlertLoad(_("Window match"));
-                      break;
                    case CONFIG_COLORMOD:
 #if 0                          /* FIXME - ? */
                       Config_ColorModifier(fs);
@@ -510,7 +505,6 @@
       "slideouts.cfg",
       "borders.cfg",
       "backup-borders.cfg",
-      "windowmatches.cfg",
       "tooltips.cfg",
       "backup-tooltips.cfg",
       "menustyles.cfg",
@@ -552,7 +546,8 @@
    FontConfigUnload();
 
    /* Loose ends... */
-   ConfigFileLoad(EGetSavePrefix(), NULL, ConfigFileRead);
+   Esnprintf(s, sizeof(s), "%s.misc", EGetSavePrefix());
+   ConfigFileLoad(s, NULL, ConfigFileRead);
 
    BordersSetupFallback();
 
@@ -560,13 +555,17 @@
 }
 
 void
-SaveUserControlConfig(const char *file)
+SaveUserControlConfig(void)
 {
+   char                s[4096], s2[4096];
    FILE               *fs;
 
+   /* Save the configuration parameters */
    ConfigurationSave();
 
-   fs = fopen(file, "w");
+   /* Save odd bits */
+   Etmp(s2);
+   fs = fopen(s2, "w");
    if (!fs)
       return;
 
@@ -576,6 +575,12 @@
    ButtonsConfigSave(fs);
 
    fclose(fs);
+
+   Esnprintf(s, sizeof(s), "%s.misc", EGetSavePrefix());
+   E_mv(s2, s);
+   if (!isfile(s))
+      Alert(_("There was an error saving your autosave data - filing\n"
+             "system problems.\n"));
 }
 
 void
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/draw.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -3 -r1.54 -r1.55
--- draw.c      2 Feb 2005 17:11:51 -0000       1.54
+++ draw.c      6 Feb 2005 19:13:30 -0000       1.55
@@ -1750,7 +1750,7 @@
 }
 
 Imlib_Image        *
-ELoadImage(char *file)
+ELoadImage(const char *file)
 {
    Imlib_Image        *im;
    char               *f = NULL;
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/iconify.c,v
retrieving revision 1.125
retrieving revision 1.126
diff -u -3 -r1.125 -r1.126
--- iconify.c   6 Feb 2005 12:37:47 -0000       1.125
+++ iconify.c   6 Feb 2005 19:13:31 -0000       1.126
@@ -104,14 +104,6 @@
 
 };
 
-typedef struct
-{
-   char               *title_match;
-   char               *name_match;
-   char               *class_match;
-   char               *icon_file;
-} Icondef;
-
 /* Silly hack to avoid name clash warning when using -Wshadow */
 #define y1 y1_
 
@@ -543,7 +535,7 @@
    HintsSetWindowName(ib->win, "Iconbox");
    HintsSetWindowClass(ib->win, ib->name, "Enlightenment_IconBox");
 
-   ewin = AddInternalToFamily(ib->win, "ICONBOX", EWIN_TYPE_ICONBOX, ib,
+   ewin = AddInternalToFamily(ib->win, NULL, EWIN_TYPE_ICONBOX, ib,
                              IconboxEwinInit);
    if (ewin)
      {
@@ -833,73 +825,18 @@
    ewin->icon_type = EWIN_ICON_TYPE_APP;
 }
 
-static Icondef    **
-IB_ListIcondef(int *num)
-{
-   return (Icondef **) ListItemType(num, LIST_TYPE_ICONDEF);
-}
-
-static Icondef     *
-IB_MatchIcondef(char *title, char *name, char *class)
-{
-   /* return an icondef that matches the data given */
-   Icondef           **il, *idef;
-   int                 i, num;
-
-   il = IB_ListIcondef(&num);
-   if (il)
-     {
-       for (i = 0; i < num; i++)
-         {
-            char                match = 1;
-
-            if ((il[i]->title_match) && (!title))
-               match = 0;
-            if ((il[i]->name_match) && (!name))
-               match = 0;
-            if ((il[i]->class_match) && (!class))
-               match = 0;
-            if ((il[i]->title_match) && (title))
-              {
-                 if (!matchregexp(il[i]->title_match, title))
-                    match = 0;
-              }
-            if ((il[i]->name_match) && (name))
-              {
-                 if (!matchregexp(il[i]->name_match, name))
-                    match = 0;
-              }
-            if ((il[i]->class_match) && (class))
-              {
-                 if (!matchregexp(il[i]->class_match, class))
-                    match = 0;
-              }
-            if (match)
-              {
-                 idef = il[i];
-                 Efree(il);
-                 return idef;
-              }
-         }
-       Efree(il);
-     }
-   return NULL;
-}
-
 static void
 IB_GetEIcon(EWin * ewin)
 {
    /* get the icon defined for this window in E's iconf match file */
-   Icondef            *idef;
+   const char         *file;
    Imlib_Image        *im;
 
-   idef = IB_MatchIcondef(ewin->icccm.wm_name, ewin->icccm.wm_res_name,
-                         ewin->icccm.wm_res_class);
-
-   if (!idef)
+   file = WindowMatchEwinIcon(ewin);
+   if (!file)
       return;
 
-   im = ELoadImage(idef->icon_file);
+   im = ELoadImage(file);
    if (!im)
       return;
 
@@ -907,175 +844,6 @@
    ewin->icon_type = EWIN_ICON_TYPE_IMG;
 }
 
-static void
-IB_AddIcondef(char *title, char *name, char *class, char *file)
-{
-   /* add match for a window pointing to an iconfile */
-   /* form: "*term*" "name*" "*class" "path/to_image.png" */
-   Icondef            *idef;
-
-   idef = Emalloc(sizeof(Icondef));
-   if (!idef)
-      return;
-   idef->title_match = Estrdup(title);
-   idef->name_match = Estrdup(name);
-   idef->class_match = Estrdup(class);
-   idef->icon_file = Estrdup(file);
-   AddItem(idef, "", 0, LIST_TYPE_ICONDEF);
-}
-
-static void
-IB_RemoveIcondef(Icondef * idef)
-{
-   /* remove the pointed to icondef from our database */
-   Icondef            *idef2;
-
-   idef2 = RemoveItem((char *)idef, 0, LIST_FINDBY_POINTER, LIST_TYPE_ICONDEF);
-   if (!idef2)
-      return;
-   if (idef->title_match)
-      Efree(idef->title_match);
-   if (idef->name_match)
-      Efree(idef->name_match);
-   if (idef->class_match)
-      Efree(idef->class_match);
-   if (idef->icon_file)
-      Efree(idef->icon_file);
-   Efree(idef);
-}
-
-static time_t       last_icondefs_time = 0;
-
-static void
-IB_LoadIcondefs(void)
-{
-   /* load the icon defs */
-   char               *ff = NULL, s[1024], *s1, *s2, *s3, *s4;
-   FILE               *f;
-
-   ff = ThemeFileFind("icondefs.cfg");
-   if (!ff)
-      return;
-   f = fopen(ff, "r");
-   while (fgets(s, 1024, f))
-     {
-       s[strlen(s) - 1] = 0;
-       /* file format : */
-       /* "icon/image.png" "*title*" "*name*" "*class*" */
-       /* any field except field 1 can be NULL if you dont care */
-       /* the default match is: */
-       /* "icon/defailt_image.png" NULL NULL NULL */
-       /* and must be first in the file */
-       s1 = field(s, 0);
-       s2 = field(s, 1);
-       s3 = field(s, 2);
-       s4 = field(s, 3);
-       if (s1)
-          IB_AddIcondef(s2, s3, s4, s1);
-       if (s1)
-          Efree(s1);
-       if (s2)
-          Efree(s2);
-       if (s3)
-          Efree(s3);
-       if (s4)
-          Efree(s4);
-     }
-   fclose(f);
-   last_icondefs_time = moddate(ff);
-   Efree(ff);
-}
-
-static void
-IB_ReLoadIcondefs(void)
-{
-   /* stat the icondefs and compare mod date to last known mod date - if */
-   /* modified, delete all icondefs and load again */
-   char               *ff = NULL;
-   Icondef           **idef;
-   int                 i, num;
-
-   ff = ThemeFileFind("icondefs.cfg");
-   if (!ff)
-     {
-       idef = IB_ListIcondef(&num);
-       if (idef)
-         {
-            for (i = 0; i < num; i++)
-               IB_RemoveIcondef(idef[i]);
-            Efree(idef);
-         }
-       return;
-     }
-   if (moddate(ff) > last_icondefs_time)
-     {
-       idef = IB_ListIcondef(&num);
-       if (idef)
-         {
-            for (i = 0; i < num; i++)
-               IB_RemoveIcondef(idef[i]);
-            Efree(idef);
-         }
-       IB_LoadIcondefs();
-     }
-   Efree(ff);
-}
-
-static void
-IcondefChecker(int val __UNUSED__, void *data __UNUSED__)
-{
-   IB_ReLoadIcondefs();
-   DoIn("ICONDEF_CHECK", 2.0, IcondefChecker, 0, NULL);
-}
-
-#if 0                          /* Not used */
-static void
-IB_SaveIcondefs(void)
-{
-   /* save the icondefs */
-   char                s[1024];
-   FILE               *f;
-
-   Esnprintf(s, sizeof(s), "%s/icondefs.cfg", EDirUser());
-   f = fopen(s, "w");
-   if (f)
-     {
-       Icondef           **idef;
-       int                 i, num;
-
-       idef = IB_ListIcondef(&num);
-       for (i = num - 1; i >= 0; i--)
-         {
-            char               *f1, *f2, *f3, *f4;
-
-            f1 = idef[i]->icon_file;
-            f2 = idef[i]->title_match;
-            f3 = idef[i]->name_match;
-            f4 = idef[i]->class_match;
-
-            if (f1)
-              {
-                 fprintf(f, "\"%s\" ", f1);
-                 if (f2)
-                    fprintf(f, "\"%s\" ", f2);
-                 else
-                    fprintf(f, "NULL ");
-                 if (f3)
-                    fprintf(f, "\"%s\" ", f3);
-                 else
-                    fprintf(f, "NULL ");
-                 if (f4)
-                    fprintf(f, "\"%s\"\n", f4);
-                 else
-                    fprintf(f, "NULL\n");
-              }
-         }
-       fclose(f);
-       last_icondefs_time = moddate(s);
-     }
-}
-#endif
-
 static Iconbox    **
 IconboxesList(int *num)
 {
@@ -2280,7 +2048,6 @@
    int                 i, num;
    Iconbox           **ibl;
 
-   IcondefChecker(0, NULL);
    ibl = IconboxesList(&num);
    if (ibl)
      {
@@ -3132,11 +2899,10 @@
    switch (sig)
      {
      case ESIGNAL_CONFIGURE:
-       IconboxesConfigLoad();
-       IconboxesShow();
        break;
      case ESIGNAL_START:
-       /* We should create one if enabled and none existing */
+       IconboxesConfigLoad();
+       IconboxesShow();
        break;
 #if 0
      case ESIGNAL_EXIT:
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/ipc.c,v
retrieving revision 1.196
retrieving revision 1.197
diff -u -3 -r1.196 -r1.197
--- ipc.c       1 Feb 2005 20:35:59 -0000       1.196
+++ ipc.c       6 Feb 2005 19:13:31 -0000       1.197
@@ -473,18 +473,29 @@
          case '\0':
             IpcPrintf("%#lx : %s\n", e->client.win, SS(e->icccm.wm_name));
             break;
+
          default:
             IpcPrintf("%#lx : %s :: %d : %d %d : %d %d %dx%d\n",
                       e->client.win, SS(e->icccm.wm_name),
                       (EoIsSticky(e)) ? -1 : EoGetDesk(e), e->area_x,
                       e->area_y, EoGetX(e), EoGetY(e), EoGetW(e), EoGetH(e));
             break;
+
          case 'a':
             IpcPrintf("%#10lx : %4d %4d %4dx%4d :: %2d : %d %d : %s\n",
                       e->client.win, EoGetX(e), EoGetY(e), EoGetW(e),
                       EoGetH(e), (EoIsSticky(e)) ? -1 : EoGetDesk(e),
                       e->area_x, e->area_y, SS(e->icccm.wm_name));
             break;
+
+         case 'p':
+            IpcPrintf("%#10lx : %4d %4d %4dx%4d :: %2d : \"%s\" \"%s\" %s\n",
+                      e->client.win,
+                      EoGetX(e), EoGetY(e), EoGetW(e), EoGetH(e),
+                      (EoIsSticky(e)) ? -1 : EoGetDesk(e),
+                      SS(e->icccm.wm_res_name), SS(e->icccm.wm_res_class),
+                      SS(e->icccm.wm_name));
+            break;
          }
      }
    if (num <= 0)
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/mod-misc.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -3 -r1.6 -r1.7
--- mod-misc.c  29 Jan 2005 07:11:58 -0000      1.6
+++ mod-misc.c  6 Feb 2005 19:13:33 -0000       1.7
@@ -52,6 +52,7 @@
 extern EModule      ModTooltips;
 extern EModule      ModTransparency;
 extern EModule      ModWarplist;
+extern EModule      ModWindowMatch;
 
 const EModule      *p_modules[] = {
    &ModDesktops,
@@ -78,6 +79,7 @@
    &ModTooltips,
    &ModTransparency,
    &ModWarplist,
+   &ModWindowMatch,
 };
 int                 n_modules = sizeof(p_modules) / sizeof(EModule *);
 
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/pager.c,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -3 -r1.112 -r1.113
--- pager.c     2 Feb 2005 17:12:01 -0000       1.112
+++ pager.c     6 Feb 2005 19:13:33 -0000       1.113
@@ -34,7 +34,6 @@
    char                visible;
    int                 update_phase;
    EWin               *ewin;
-   char               *border_name;
    Window              sel_win;
    char                hi_visible;
    Window              hi_win;
@@ -97,7 +96,6 @@
    p->visible = 0;
    p->update_phase = 0;
    p->ewin = NULL;
-   p->border_name = NULL;
    p->sel_win = ECreateWindow(p->win, 0, 0, p->w / ax, p->h / ay, 0);
    pq = Mode.queue_up;
    Mode.queue_up = 0;
@@ -125,8 +123,6 @@
    if (p->pmap)
       ecore_x_pixmap_del(p->pmap);
    FreePmapMask(&p->bgpmap);
-   if (p->border_name)
-      Efree(p->border_name);
    Efree(p);
 }
 
@@ -605,8 +601,7 @@
    pq = Mode.queue_up;
    Mode.queue_up = 0;
 
-   ewin = AddInternalToFamily(p->win, (p->border_name) ? p->border_name :
-                             "PAGER", EWIN_TYPE_PAGER, p, PagerEwinInit);
+   ewin = AddInternalToFamily(p->win, NULL, EWIN_TYPE_PAGER, p, PagerEwinInit);
    if (ewin)
      {
        int                 ax, ay, w, h;
@@ -2190,6 +2185,8 @@
        EDirMake(EDirUserCache(), "cached/pager");
        break;
      case ESIGNAL_CONFIGURE:
+       break;
+     case ESIGNAL_START:
        if (!Conf.pagers.enable)
           break;
        Conf.pagers.enable = 0;
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/session.c,v
retrieving revision 1.86
retrieving revision 1.87
diff -u -3 -r1.86 -r1.87
--- session.c   6 Feb 2005 08:02:11 -0000       1.86
+++ session.c   6 Feb 2005 19:13:33 -0000       1.87
@@ -296,22 +296,15 @@
 void
 autosave(void)
 {
-   char                s[4096];
-
    if (!Mode.wm.save_ok || !Conf.autosave)
       return;
 
    if (EventDebug(EDBUG_TYPE_SESSION))
-      Eprintf("autosave: save %s\n", EGetSavePrefix());
+      Eprintf("autosave\n");
 
    Real_SaveSnapInfo(0, NULL);
 
-   Etmp(s);
-   SaveUserControlConfig(s);
-   E_mv(s, EGetSavePrefix());
-   if (!isfile(EGetSavePrefix()))
-      Alert(_("There was an error saving your autosave data - filing\n"
-             "system problems.\n"));
+   SaveUserControlConfig();
 }
 
 #ifdef HAVE_X11_SM_SMLIB_H
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/theme.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -3 -r1.41 -r1.42
--- theme.c     29 Jan 2005 07:11:59 -0000      1.41
+++ theme.c     6 Feb 2005 19:13:34 -0000       1.42
@@ -32,20 +32,15 @@
 #if ENABLE_THEME_SANITY_CHECKING
    "borders.cfg",
    "buttons.cfg",
-   "colormodifiers.cfg",
-   "control.cfg",
    "cursors.cfg",
    "desktops.cfg",
    "imageclasses.cfg",
 #endif
    "init.cfg",
 #if ENABLE_THEME_SANITY_CHECKING
-   "menus.cfg",
    "menustyles.cfg",
    "slideouts.cfg",
-   "sound.cfg",
    "tooltips.cfg",
-   "windowmatches.cfg",
 #endif
    NULL
 };
===================================================================
RCS file: /cvsroot/enlightenment/e16/e/src/windowmatch.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -3 -r1.23 -r1.24
--- windowmatch.c       25 Jan 2005 21:58:26 -0000      1.23
+++ windowmatch.c       6 Feb 2005 19:13:34 -0000       1.24
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2000-2004 Carsten Haitzler, Geoff Harrison and various 
contributors
+ * Copyright (C) 2005 Kim Woelders
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -23,36 +24,80 @@
 #include "E.h"
 #include "conf.h"
 
+struct _windowmatch
+{
+   char               *name;
+   /* Match criteria */
+   char                match;
+   char                op;
+   char                prop;
+   char                qual;
+   char               *value;
+   Constraints         width;
+   Constraints         height;
+   /* Match actions */
+   char               *args;
+   Border             *border;
+};
+
+#define MATCH_TYPE_TITLE        1
+#define MATCH_TYPE_WM_NAME      2
+#define MATCH_TYPE_WM_CLASS     3
+#define MATCH_TYPE_SIZE         4
+#define MATCH_TYPE_SIZE_H       5
+#define MATCH_TYPE_SIZE_V       6
+#define MATCH_TYPE_PROP         7
+
+#define MATCH_PROP_TRANSIENT    1
+#define MATCH_PROP_SHAPED       2
+#define MATCH_PROP_FIXEDSIZE    3
+#define MATCH_PROP_FIXEDSIZE_H  4
+#define MATCH_PROP_FIXEDSIZE_V  5
+
+#define MATCH_OP_BORDER         1
+#define MATCH_OP_ICON           2
+#define MATCH_OP_WINOP          3
+
+const char         *MatchType[] = {
+   NULL, "Title", "Name", "Class", "Size", "Width", "Height", "Prop", NULL
+};
+
+const char         *MatchProp[] = {
+   NULL, "Transient", "Shaped", "FixedSize", "FixedWidth", "FixedHeight", NULL
+};
+
+const char         *MatchOp[] = {
+   NULL, "Border", "Icon", "Winop", NULL
+};
+
+static int
+MatchFind(const char **list, const char *str)
+{
+   int                 i;
+
+   for (i = 1; list[i]; i++)
+      if (!strcmp(str, list[i]))
+        return i;
+
+   return 0;
+}
+
 static WindowMatch *
 WindowMatchCreate(const char *name)
 {
    WindowMatch        *b;
 
-   b = Emalloc(sizeof(WindowMatch));
+   b = Ecalloc(1, sizeof(WindowMatch));
    if (!b)
       return NULL;
 
    b->name = Estrdup(name);
-   b->win_title = NULL;
-   b->win_name = NULL;
-   b->win_class = NULL;
-   b->width.min = 0;
    b->width.max = 99999;
-   b->height.min = 0;
    b->height.max = 99999;
-   b->transient = -1;
-   b->no_resize_h = -1;
-   b->no_resize_v = -1;
-   b->shaped = -1;
-   b->border = NULL;
-   b->icon = NULL;
-   b->desk = 0;
-   b->make_sticky = 0;
 
    return b;
 }
 
-#if 0
 static void
 WindowMatchDestroy(WindowMatch * wm)
 {
@@ -61,26 +106,23 @@
 
    while (RemoveItemByPtr(wm, LIST_TYPE_WINDOWMATCH));
 
-   if (wm->icon)
-      wm->icon->ref_count--;
-   if (wm->border)
-      wm->border->ref_count--;
    if (wm->name)
       Efree(wm->name);
-   if (wm->win_title)
-      Efree(wm->win_title);
-   if (wm->win_name)
-      Efree(wm->win_name);
-   if (wm->win_class)
-      Efree(wm->win_class);
+   if (wm->value)
+      Efree(wm->value);
+   if (wm->border)
+      BorderDecRefcount(wm->border);
+   if (wm->args)
+      Efree(wm->args);
+
+   Efree(wm);
 }
-#endif
 
-int
+static int
 WindowMatchConfigLoad(FILE * fs)
 {
    int                 err = 0;
-   WindowMatch        *bm = 0;
+   WindowMatch        *wm = 0;
    char                s[FILEPATH_LEN_MAX];
    char                s2[FILEPATH_LEN_MAX];
    int                 i1;
@@ -102,76 +144,135 @@
        else if (i1 != CONFIG_INVALID)
          {
             if (fields != 2)
-              {
-                 Alert(_("CONFIG: missing required data in \"%s\"\n"), s);
-              }
+               Alert(_("CONFIG: missing required data in \"%s\"\n"), s);
          }
+
        switch (i1)
          {
-         case CONFIG_CLOSE:
-            AddItem(bm, bm->name, 0, LIST_TYPE_WINDOWMATCH);
-            goto done;
+         case CONFIG_VERSION:
+         case CONFIG_WINDOWMATCH:
+            err = -1;
+            break;
+
          case CONFIG_CLASSNAME:
-            bm = WindowMatchCreate(s2);
+            wm = WindowMatchCreate(s2);
             break;
-         case CONFIG_BORDER:
-         case WINDOWMATCH_USEBORDER:
-            bm->border = FindItem(s2, 0, LIST_FINDBY_NAME, LIST_TYPE_BORDER);
-            if (bm->border)
-               bm->border->ref_count++;
+
+         case CONFIG_CLOSE:
+            if (!wm)
+               break;
+            if (wm->match && wm->op)
+               AddItemEnd(wm, wm->name, 0, LIST_TYPE_WINDOWMATCH);
+            else
+              {
+                 WindowMatchDestroy(wm);
+              }
+            wm = NULL;
+            err = 0;
+            break;
+
+         case WINDOWMATCH_MATCHTITLE:
+            if (!wm)
+               break;
+            wm->match = MATCH_TYPE_TITLE;
+            wm->value = Estrdup(atword(s, 2));
             break;
          case WINDOWMATCH_MATCHNAME:
-            bm->win_name = Estrdup(atword(s, 2));
+            if (!wm)
+               break;
+            wm->match = MATCH_TYPE_WM_NAME;
+            wm->value = Estrdup(atword(s, 2));
             break;
          case WINDOWMATCH_MATCHCLASS:
-            bm->win_class = Estrdup(atword(s, 2));
-            break;
-         case WINDOWMATCH_MATCHTITLE:
-            bm->win_title = Estrdup(atword(s, 2));
+            if (!wm)
+               break;
+            wm->match = MATCH_TYPE_WM_CLASS;
+            wm->value = Estrdup(atword(s, 2));
             break;
+#if 0                          /* FIXME */
          case WINDOWMATCH_DESKTOP:
          case CONFIG_DESKTOP:
-            bm->desk = atoi(s2);
+            wm->desk = atoi(s2);
             break;
          case WINDOWMATCH_ICON:
          case CONFIG_ICONBOX:
-            bm->icon = ImageclassFind(s2, 0);
-            if (bm->icon)
-               bm->icon->ref_count++;
+            wm->icon = ImageclassFind(s2, 0);
+            if (wm->icon)
+               wm->icon->ref_count++;
             break;
-         case WINDOWMATCH_WIDTH:
-            {
-               char                s3[FILEPATH_LEN_MAX];
+#endif
 
-               sscanf(s, "%*s %4000s %4000s", s2, s3);
-               bm->width.min = atoi(s2);
-               bm->width.max = atoi(s3);
-            }
+         case WINDOWMATCH_WIDTH:
+            if (!wm)
+               break;
+            if (wm->match == MATCH_TYPE_SIZE_V)
+               wm->match = MATCH_TYPE_SIZE;
+            else
+               wm->match = MATCH_TYPE_SIZE_H;
+            sscanf(s, "%*s %u %u", &(wm->width.min), &(wm->width.max));
             break;
          case WINDOWMATCH_HEIGHT:
-            {
-               char                s3[FILEPATH_LEN_MAX];
-
-               sscanf(s, "%*s %4000s %4000s", s2, s3);
-               bm->height.min = atoi(s2);
-               bm->height.max = atoi(s3);
-            }
+            if (!wm)
+               break;
+            if (wm->match == MATCH_TYPE_SIZE_H)
+               wm->match = MATCH_TYPE_SIZE;
+            else
+               wm->match = MATCH_TYPE_SIZE_V;
+            sscanf(s, "%*s %u %u", &(wm->height.min), &(wm->height.max));
             break;
+
          case WINDOWMATCH_TRANSIENT:
-            bm->transient = atoi(s2);
+            if (!wm)
+               break;
+            wm->match = MATCH_TYPE_PROP;
+            wm->prop = MATCH_PROP_TRANSIENT;
+            wm->qual = !atoi(s2);
+            break;
+         case WINDOWMATCH_SHAPED:
+            if (!wm)
+               break;
+            wm->match = MATCH_TYPE_PROP;
+            wm->prop = MATCH_PROP_SHAPED;
+            wm->qual = !atoi(s2);
             break;
          case WINDOWMATCH_NO_RESIZE_H:
-            bm->no_resize_h = atoi(s2);
+            if (!wm)
+               break;
+            wm->match = MATCH_TYPE_PROP;
+            if (wm->prop == MATCH_PROP_FIXEDSIZE_V)
+               wm->prop = MATCH_PROP_FIXEDSIZE;
+            else
+               wm->prop = MATCH_PROP_FIXEDSIZE_H;
+            wm->qual = !atoi(s2);
             break;
          case WINDOWMATCH_NO_RESIZE_V:
-            bm->no_resize_v = atoi(s2);
+            if (!wm)
+               break;
+            wm->match = MATCH_TYPE_PROP;
+            if (wm->prop == MATCH_PROP_FIXEDSIZE_H)
+               wm->prop = MATCH_PROP_FIXEDSIZE;
+            else
+               wm->prop = MATCH_PROP_FIXEDSIZE_V;
+            wm->qual = !atoi(s2);
             break;
-         case WINDOWMATCH_SHAPED:
-            bm->shaped = atoi(s2);
+
+         case CONFIG_BORDER:
+         case WINDOWMATCH_USEBORDER:
+            if (!wm)
+               break;
+            wm->border = FindItem(s2, 0, LIST_FINDBY_NAME, LIST_TYPE_BORDER);
+            if (!wm->border)
+               break;
+            wm->op = MATCH_OP_BORDER;
+            BorderIncRefcount(wm->border);
             break;
+
          case WINDOWMATCH_MAKESTICKY:
-            bm->make_sticky = atoi(s2);
+            if (!wm)
+               break;
+            wm->args = Estrdupcat2(wm->args, ":", "stick");
             break;
+
          default:
             Alert(_("Warning: unable to determine what to do with\n"
                     "the following text in the middle of current "
@@ -180,119 +281,438 @@
             break;
          }
      }
-   err = -1;
 
- done:
    return err;
 }
 
-static int
-WindowMatchTest(EWin * ewin, WindowMatch * b)
+static WindowMatch *
+WindowMatchDecode(const char *line)
 {
+   char                match[32], value[1024], op[32], args[1024];
+   WindowMatch        *wm = NULL;
+   int                 err, num, a, b;
+
+   match[0] = value[0] = op[0] = args[0] = '\0';
+   num = sscanf(line, "%32s %1024s %32s %1024s", match, value, op, args);
+   if (num < 4)
+      return NULL;
 
-   if ((b->win_title) && (ewin->icccm.wm_name)
-       && (!matchregexp(b->win_title, ewin->icccm.wm_name)))
-      return 0;
-
-   if ((b->win_name) && (ewin->icccm.wm_res_name)
-       && (!matchregexp(b->win_name, ewin->icccm.wm_res_name)))
-      return 0;
+#if 0
+   Eprintf("-- %s\n", s);
+   Eprintf("++ %s %s %s %s\n", match, value, op, args);
+#endif
 
-   if ((b->win_class) && (ewin->icccm.wm_res_class)
-       && (!matchregexp(b->win_class, ewin->icccm.wm_res_class)))
-      return 0;
+   err = 0;
 
-   if ((ewin->client.w > b->width.max) || (ewin->client.w < b->width.min))
-      return 0;
+   num = MatchFind(MatchType, match);
+   if (num <= 0)
+     {
+       Eprintf("WindowMatchDecode: Error (%s): %s\n", match, line);
+       err = 1;
+       goto done;
+     }
 
-   if ((ewin->client.h > b->height.max) || (ewin->client.h < b->height.min))
-      return 0;
+   wm = WindowMatchCreate(NULL);
+   if (!wm)
+      return NULL;
 
-   if ((b->transient >= 0) && (b->transient != ewin->client.transient))
-      return 0;
+   wm->match = num;
 
-   if ((b->no_resize_h >= 0) && (b->no_resize_h != ewin->client.no_resize_h))
-      return 0;
+   switch (wm->match)
+     {
+     case MATCH_TYPE_TITLE:
+     case MATCH_TYPE_WM_NAME:
+     case MATCH_TYPE_WM_CLASS:
+       wm->value = Estrdup(value);
+       break;
+
+     case MATCH_TYPE_SIZE:
+       num = sscanf(value, "%c%ux%u", match, &a, &b);
+       if (num < 3)
+          goto case_error;
+       if (*match == '<')
+          wm->qual = 1;
+       else if (*value == '>')
+          wm->qual = 0;
+       else
+          goto case_error;
+       wm->width.max = a;
+       wm->height.max = b;
+       break;
+     case MATCH_TYPE_SIZE_H:
+       num = sscanf(value, "%u-%u", &a, &b);
+       if (num < 2)
+          goto case_error;
+       wm->width.min = a;
+       wm->width.max = b;
+       break;
+     case MATCH_TYPE_SIZE_V:
+       num = sscanf(value, "%u-%u", &a, &b);
+       if (num < 2)
+          goto case_error;
+       wm->height.min = a;
+       wm->height.max = b;
+       break;
+
+     case MATCH_TYPE_PROP:
+       num = 0;
+       if (*value == '!')
+         {
+            wm->qual = 1;
+            num = 1;
+         }
+       wm->prop = MatchFind(MatchProp, value + num);
+       if (wm->prop <= 0)
+          goto case_error;
+       break;
+
+      case_error:
+       Eprintf("WindowMatchDecode: Error (%s): %s\n", value, line);
+       err = 1;
+       goto done;
+     }
 
-   if ((b->no_resize_v >= 0) && (b->no_resize_v != ewin->client.no_resize_v))
-      return 0;
+   wm->op = MatchFind(MatchOp, op);
+   if (wm->op <= 0)
+     {
+       Eprintf("WindowMatchDecode: Error (%s): %s\n", op, line);
+       err = 1;
+       goto done;
+     }
 
-   if ((b->shaped >= 0) && (b->shaped != ewin->client.shaped))
-      return 0;
+   switch (wm->op)
+     {
+     case MATCH_OP_BORDER:
+       wm->border = FindItem(args, 0, LIST_FINDBY_NAME, LIST_TYPE_BORDER);
+       if (!wm->border)
+         {
+            err = 1;
+            goto done;
+         }
+       BorderIncRefcount(wm->border);
+       break;
 
-   return 1;
-}
+     case MATCH_OP_ICON:
+       wm->args = Estrdup(args);
+       break;
+
+     case MATCH_OP_WINOP:
+       wm->args = Estrdup(args);
+       break;
+     }
 
-Border             *
-MatchEwinBorder(EWin * ewin, WindowMatch * b)
-{
-   if (WindowMatchTest(ewin, b))
+ done:
+   if (err)
      {
-       if (b->make_sticky)
-          EoSetSticky(ewin, 1);
-
-       return b->border;
+       if (wm)
+          WindowMatchDestroy(wm);
      }
    else
      {
-       return 0;
+       AddItemEnd(wm, wm->name, 0, LIST_TYPE_WINDOWMATCH);
      }
+   return wm;
 }
 
-ImageClass         *
-MatchEwinIcon(EWin * ewin, WindowMatch * b)
+static char        *
+WindowMatchEncode(WindowMatch * wm, char *buf, int len)
 {
-   if (WindowMatchTest(ewin, b))
-     {
-       if (b->make_sticky)
-          EoSetSticky(ewin, 1);
+   char                s[1024];
+   const char         *qual, *value, *args;
 
-       return b->icon;
+   qual = " ";
+
+   switch (wm->match)
+     {
+     default:
+       value = wm->value;
+       break;
+
+     case MATCH_TYPE_SIZE:
+       value = s;
+       qual = (wm->qual) ? "<" : ">";
+       sprintf(s, "%ux%u", wm->width.max, wm->height.max);
+       break;
+     case MATCH_TYPE_SIZE_H:
+       value = s;
+       sprintf(s, "%u-%u", wm->width.min, wm->width.max);
+       break;
+     case MATCH_TYPE_SIZE_V:
+       value = s;
+       sprintf(s, "%u-%u", wm->height.min, wm->height.max);
+       break;
+
+     case MATCH_TYPE_PROP:
+       qual = (wm->qual) ? "!" : " ";
+       value = MatchProp[(int)wm->prop];
+       break;
      }
-   else
+
+   switch (wm->op)
      {
-       return 0;
+     default:
+       args = wm->args;
+       break;
+
+     case MATCH_OP_BORDER:
+       args = BorderGetName(wm->border);
+       break;
      }
+
+   Esnprintf(buf, len, "%-8s %s%-16s %s %s", MatchType[(int)wm->match],
+            qual, value, MatchOp[(int)wm->op], args);
+
+   return buf;
 }
 
-int
-MatchEwinDesktop(EWin * ewin, WindowMatch * b)
+static void
+WindowMatchConfigLoad2(FILE * fs)
 {
-   if (WindowMatchTest(ewin, b))
+   char                s[FILEPATH_LEN_MAX], *ss;
+   int                 len;
+
+   for (;;)
      {
-       if (b->make_sticky)
-          EoSetSticky(ewin, 1);
+       ss = fgets(s, sizeof(s), fs);
+       if (!ss)
+          break;
+
+       len = strcspn(s, "#\r\n");
+       if (len <= 0)
+          continue;
+       s[len] = '\0';
 
-       return b->desk;
+       WindowMatchDecode(s);
      }
-   else
+}
+
+static void
+WindowMatchConfigLoadConfig(void)
+{
+   char               *file;
+   FILE               *fs;
+
+   file = ConfigFileFind("matches.cfg", NULL, 0);
+   if (!file)
+      return;
+
+   fs = fopen(file, "r");
+   Efree(file);
+   if (!fs)
+      return;
+
+   WindowMatchConfigLoad2(fs);
+
+   fclose(fs);
+}
+
+static int
+WindowMatchTest(const EWin * ewin, const WindowMatch * wm)
+{
+   int                 match;
+
+   match = 0;
+
+   switch (wm->match)
      {
-       return 0;
+     case MATCH_TYPE_TITLE:
+       return matchregexp(wm->value, ewin->icccm.wm_name);
+
+     case MATCH_TYPE_WM_NAME:
+       return matchregexp(wm->value, ewin->icccm.wm_res_name);
+
+     case MATCH_TYPE_WM_CLASS:
+       return matchregexp(wm->value, ewin->icccm.wm_res_class);
+
+     case MATCH_TYPE_SIZE:
+       match = (ewin->client.w >= wm->width.min &&
+                ewin->client.w <= wm->width.max &&
+                ewin->client.h >= wm->height.min &&
+                ewin->client.h <= wm->height.max);
+       break;
+     case MATCH_TYPE_SIZE_H:
+       match = (ewin->client.w >= wm->width.min &&
+                ewin->client.w <= wm->width.max);
+       break;
+     case MATCH_TYPE_SIZE_V:
+       match = (ewin->client.h >= wm->height.min &&
+                ewin->client.h <= wm->height.max);
+       break;
+
+     case MATCH_TYPE_PROP:
+       switch (wm->prop)
+         {
+         case MATCH_PROP_TRANSIENT:
+            match = ewin->client.transient;
+            break;
+
+         case MATCH_PROP_SHAPED:
+            match = ewin->client.shaped;
+            break;
+
+         case MATCH_PROP_FIXEDSIZE:
+            match = ewin->client.no_resize_h && ewin->client.no_resize_v;
+            break;
+         case MATCH_PROP_FIXEDSIZE_H:
+            match = ewin->client.no_resize_h;
+            break;
+         case MATCH_PROP_FIXEDSIZE_V:
+            match = ewin->client.no_resize_v;
+            break;
+         }
      }
+
+   if (wm->qual)
+      match = !match;
+   return match;
 }
 
-void               *
-MatchEwinByFunction(EWin * ewin,
-                   void *(*FunctionToTest) (EWin *, WindowMatch *))
+static WindowMatch *
+WindowMatchType(const EWin * ewin, int type)
 {
-   WindowMatch       **lst;
+   WindowMatch       **lst, *wm;
    int                 i, num;
-   void               *retval;
-
-   retval = 0;
 
    lst = (WindowMatch **) ListItemType(&num, LIST_TYPE_WINDOWMATCH);
-   if (lst)
+   for (i = 0; i < num; i++)
      {
-       for (i = 0; i < num; i++)
+       wm = lst[i];
+
+       switch (type)
          {
-            if ((retval = (*FunctionToTest) (ewin, lst[i])))
-              {
-                 i = num;
-              }
+         default:
+            continue;
+
+         case MATCH_OP_BORDER:
+            if (!wm->border)
+               continue;
+            break;
+
+         case MATCH_OP_ICON:
+         case MATCH_OP_WINOP:
+            if (!wm->args)
+               continue;
+            break;
          }
-       Efree(lst);
+
+       if (!WindowMatchTest(ewin, lst[i]))
+          continue;
+       goto done;
      }
+   wm = NULL;
+
+ done:
+   if (lst)
+      Efree(lst);
 
-   return retval;
+   return wm;
 }
+
+Border             *
+WindowMatchEwinBorder(const EWin * ewin)
+{
+   WindowMatch        *wm;
+
+   wm = WindowMatchType(ewin, MATCH_OP_BORDER);
+#if 0
+   Eprintf("WindowMatchEwinBorder %s %s\n", EwinGetName(ewin),
+          (wm) ? BorderGetName(wm->border) : "???");
+#endif
+   if (wm)
+      return wm->border;
+   return NULL;
+}
+
+const char         *
+WindowMatchEwinIcon(const EWin * ewin)
+{
+   WindowMatch        *wm;
+
+   wm = WindowMatchType(ewin, MATCH_OP_ICON);
+#if 0
+   Eprintf("WindowMatchEwinIcon %s %s\n", EwinGetName(ewin),
+          (wm) ? wm->args : "???");
+#endif
+   if (wm)
+      return wm->args;
+   return NULL;
+}
+
+/*
+ * Winmatch module
+ */
+
+static void
+WindowMatchSighan(int sig, void *prm __UNUSED__)
+{
+   switch (sig)
+     {
+     case ESIGNAL_CONFIGURE:
+#if 1
+       ConfigFileLoad("windowmatches.cfg", Mode.theme.path,
+                      WindowMatchConfigLoad);
+#endif
+       WindowMatchConfigLoadConfig();
+#if 0
+       WindowMatchConfigLoadUser();
+#endif
+#if 0
+       IcondefChecker(0, NULL);
+#endif
+       break;
+     case ESIGNAL_EXIT:
+       break;
+     }
+}
+
+static void
+WindowMatchIpc(const char *params, Client * c __UNUSED__)
+{
+   const char         *p;
+   char                cmd[128], prm[4096], buf[4096];
+   int                 i, len, num;
+
+   cmd[0] = prm[0] = '\0';
+   p = params;
+   if (p)
+     {
+       len = 0;
+       sscanf(p, "%100s %4000s %n", cmd, prm, &len);
+       p += len;
+     }
+
+   if (!p || cmd[0] == '?')
+     {
+     }
+   else if (!strncmp(cmd, "list", 2))
+     {
+       WindowMatch       **lst;
+
+       lst = (WindowMatch **) ListItemType(&num, LIST_TYPE_WINDOWMATCH);
+       for (i = 0; i < num; i++)
+          IpcPrintf("%s\n", WindowMatchEncode(lst[i], buf, sizeof(buf)));
+       if (lst)
+          Efree(lst);
+     }
+}
+
+IpcItem             WindowMatchIpcArray[] = {
+   {
+    WindowMatchIpc,
+    "wmatch", "wma",
+    "Window match functions",
+    "  wmatch list               List window matches\n"}
+   ,
+};
+#define N_IPC_FUNCS (sizeof(WindowMatchIpcArray)/sizeof(IpcItem))
+
+/*
+ * Module descriptor
+ */
+EModule             ModWindowMatch = {
+   "winmatch", NULL,
+   WindowMatchSighan,
+   {N_IPC_FUNCS, WindowMatchIpcArray}
+   ,
+   {0, NULL}
+};




-------------------------------------------------------
This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting
Tool for open source databases. Create drag-&-drop reports. Save time
by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc.
Download a FREE copy at http://www.intelliview.com/go/osdn_nl
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to