Enlightenment CVS committal

Author  : codewarrior
Project : e17
Module  : proto

Dir     : e17/proto/etk/src/lib


Modified Files:
        Etk.h Makefile.am etk_main.c etk_types.h etk_widget.c 
        etk_widget.h etk_window.c 
Added Files:
        etk_spin_button.c etk_spin_button.h 


Log Message:
- add skeleton for spin button widget (doesnt work yet!)
- add xdnd drop support per widget - see test.


===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/Etk.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -3 -r1.16 -r1.17
--- Etk.h       19 Jan 2006 13:56:10 -0000      1.16
+++ Etk.h       8 Feb 2006 12:49:38 -0000       1.17
@@ -57,5 +57,6 @@
 #include "etk_filechooser_widget.h"
 #include "etk_notebook.h"
 #include "etk_progress_bar.h"
+#include "etk_spin_button.h"
 
 #endif
===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/Makefile.am,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -3 -r1.19 -r1.20
--- Makefile.am 19 Jan 2006 13:56:10 -0000      1.19
+++ Makefile.am 8 Feb 2006 12:49:38 -0000       1.20
@@ -40,7 +40,8 @@
 etk_statusbar.h \
 etk_filechooser_widget.h \
 etk_notebook.h \
-etk_progress_bar.h
+etk_progress_bar.h \
+etk_spin_button.h
 
 libetk_la_SOURCES = \
 etk_main.c etk_utils.c \
@@ -68,6 +69,7 @@
 etk_filechooser_widget.c \
 etk_notebook.c \
 etk_progress_bar.c \
+etk_spin_button.c \
 $(ETKHEADERS)
 
 installed_headersdir = $(prefix)/include/etk
===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/etk_main.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -3 -r1.10 -r1.11
--- etk_main.c  15 Jan 2006 11:07:16 -0000      1.10
+++ etk_main.c  8 Feb 2006 12:49:38 -0000       1.11
@@ -1,7 +1,10 @@
 /** @file etk_main.c */
 #include "etk_main.h"
 #include <locale.h>
+#include <string.h>
+#include <stdlib.h>
 #include <Ecore.h>
+#include <Ecore_X.h>
 #include <Ecore_Job.h>
 #include <Ecore_Evas.h>
 #include <Evas.h>
@@ -12,6 +15,7 @@
 #include "etk_toplevel_widget.h"
 #include "etk_utils.h"
 #include "etk_theme.h"
+#include "etk_window.h"
 #include "config.h"
 
 /**
@@ -23,10 +27,19 @@
 static void _etk_main_size_request_recursive(Etk_Widget *widget);
 static void _etk_main_size_allocate_recursive(Etk_Widget *widget, Etk_Bool 
is_top_level);
 
+#if HAVE_ECORE_X
+static int _etk_xdnd_enter_handler(void *data, int type, void *event);
+static int _etk_xdnd_position_handler(void *data, int type, void *event);
+static int _etk_xdnd_drop_handler(void *data, int type, void *event);
+static int _etk_xdnd_leave_handler(void *data, int type, void *event);
+static int _etk_xdnd_selection_handler(void *data, int type, void *event);
+#endif   
+
 static Evas_List *_etk_main_toplevel_widgets = NULL;
 static Etk_Bool _etk_main_running = ETK_FALSE;
 static Etk_Bool _etk_main_initialized = ETK_FALSE;
 static Ecore_Job *_etk_main_iterate_job = NULL;
+static Etk_Widget *_etk_dnd_widget = NULL;
 
 /**************************
  *
@@ -63,6 +76,15 @@
       ETK_WARNING("Edje initialization failed!");
       return ETK_FALSE;
    }
+   
+#if HAVE_ECORE_X
+   if (!ecore_x_init(NULL))
+     {
+       ETK_WARNING("Ecore_X initialzation failed!");
+       return ETK_FALSE;
+     }
+#endif   
+   
    etk_theme_init();
 
    /* Gettext */
@@ -70,6 +92,14 @@
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
 
+#if HAVE_ECORE_X
+   ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER, _etk_xdnd_enter_handler, 
NULL);
+   ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION, 
_etk_xdnd_position_handler, NULL);
+   ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP, _etk_xdnd_drop_handler, 
NULL);
+   ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE, _etk_xdnd_leave_handler, 
NULL);
+   ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, 
_etk_xdnd_selection_handler, NULL);
+#endif
+   
    _etk_main_initialized = ETK_TRUE;
    return ETK_TRUE;
 }
@@ -214,4 +244,205 @@
    }
 }
 
+
+#if HAVE_ECORE_X
+#define E_INSIDE(x, y, xx, yy, ww, hh) (((x) < ((xx) + (ww))) && ((y) < ((yy) 
+ (hh))) && ((x) >= (xx)) && ((y) >= (yy)))
+static int _etk_xdnd_enter_handler(void *data, int type, void *event)
+{
+   Ecore_X_Event_Xdnd_Enter *ev;
+   int i;
+   
+   /* printf("enter\n"); */
+   ev = event;
+   /* 
+    for (i = 0; i < ev->num_types; i++)
+     printf("type: %s\n", ev->types[i]);
+    */
+   return 1;
+}
+
+/* Search the container recursively for the widget that accepts xdnd */
+static void _etk_xdnd_container_get_widgets_at(Etk_Container *cont, int x, int 
y, int offx, int offy, Evas_List **list)
+{
+   Evas_List *child;
+     
+   for(child = etk_container_children_get(cont); child; child = child->next)
+     {
+       Etk_Widget *widget;
+       
+       if(!(widget = ETK_WIDGET(child->data)))
+         continue;
+       
+       if(E_INSIDE(x, y, 
+                   widget->inner_geometry.x + offx,
+                   widget->inner_geometry.y + offy,
+                   widget->inner_geometry.w, 
+                   widget->inner_geometry.h))
+         {
+            if(widget->accepts_xdnd)
+              {
+                 *list = evas_list_append(*list, widget);
+              }
+            
+            if(ETK_IS_CONTAINER(widget))
+              _etk_xdnd_container_get_widgets_at(ETK_CONTAINER(widget), x, y, 
offx, offy, list);
+         }
+     }   
+}
+
+static int _etk_xdnd_position_handler(void *data, int type, void *event)
+{
+   Ecore_X_Event_Xdnd_Position *ev;
+   Etk_Window *window;
+   Evas_List *l;
+   Evas_List *children = NULL;
+   Etk_Widget *widget;
+   ev = event;
+   
+   /* loop top level widgets (windows) */
+   for(l = _etk_main_toplevel_widgets; l; l = l->next)
+     {
+       int x, y;
+         
+       if (!(window = ETK_WINDOW(l->data)))
+         continue;
+       
+       /* if this isnt the active window, dont waste time */
+       if(ev->win != window->x_window)
+         continue;       
+       
+       ecore_evas_geometry_get(window->ecore_evas, &x, &y, NULL, NULL);
+       
+       /* find the widget we want to drop on */
+       _etk_xdnd_container_get_widgets_at(ETK_CONTAINER(window), 
ev->position.x, ev->position.y, x, y, &children);
+     }
+   
+   /* if we found a widget, emit signals */
+   if(children != NULL)
+     {
+       Ecore_X_Rectangle rect;
+       widget = (evas_list_last(children))->data;
+       _etk_dnd_widget = widget;
+       /* TODO: filter types according to what widget wants */
+       rect.x = widget->inner_geometry.x;
+       rect.y = widget->inner_geometry.y;
+       rect.width = widget->inner_geometry.w;
+       rect.height = widget->inner_geometry.h; 
+       ecore_x_dnd_send_status(1, 1, rect, ECORE_X_DND_ACTION_PRIVATE);
+     }
+   
+   return 1;
+}
+
+static int _etk_xdnd_drop_handler(void *data, int type, void *event)
+{
+   Ecore_X_Event_Xdnd_Drop *ev;
+   
+   /* printf("drop\n"); */
+   ev = event;
+   
+   ecore_x_selection_xdnd_request(ev->win, "text/uri-list");
+   return 1;
+}
+
+static int _etk_xdnd_leave_handler(void *data, int type, void *event)
+{
+   /* printf("leave\n"); */
+   return 1;
+}
+
+static int _etk_xdnd_selection_handler(void *data, int type, void *event)
+{
+   Ecore_X_Event_Selection_Notify *ev;
+   Ecore_X_Selection_Data *sel;
+   Ecore_X_Selection_Data_Files *files;
+   Ecore_X_Selection_Data_Text *text;
+   Ecore_X_Selection_Data_Targets *targets;
+   int i;
+
+   /* printf("selection\n"); */
+   ev = event;
+   switch (ev->selection) 
+     {
+      case ECORE_X_SELECTION_PRIMARY:
+       if (!strcmp(ev->target, ECORE_X_SELECTION_TARGET_TARGETS)) 
+         {
+            /* printf("primary: %s\n", ev->target); */
+            targets = ev->data;
+            /* 
+            for (i = 0; i < targets->num_targets; i++)
+              printf("target: %s\n", targets->targets[i]);
+            */
+         } 
+       else 
+         {
+            text = ev->data;
+            /* printf("primary: %s %s\n", ev->target, text->text); */
+         }
+       break;
+       
+      case ECORE_X_SELECTION_SECONDARY:
+       sel = ev->data;
+        /* printf("secondary: %s %s\n", ev->target, sel->data); */
+       break;
+       
+      case ECORE_X_SELECTION_XDND:
+        /* printf("xdnd: %s\n", ev->target); */
+
+       files = ev->data;
+       
+       if(!_etk_dnd_widget || files->num_files < 1)
+         break;        
+       
+       /* free old data, should this be done here? */
+       for (i = 0; i < _etk_dnd_widget->xdnd_files_num; i++)
+         {
+            if(_etk_dnd_widget->xdnd_files[i])
+              free(_etk_dnd_widget->xdnd_files[i]);         
+         }
+       
+       if(_etk_dnd_widget->xdnd_files)
+         free(_etk_dnd_widget->xdnd_files);        
+       
+       _etk_dnd_widget->xdnd_files = calloc(files->num_files, sizeof(char*));
+               
+       /* printf("num_files: %d\n", files->num_files); */
+       
+       /* Fill in the drop data into the widget */
+       _etk_dnd_widget->xdnd_files_num = files->num_files;
+       for (i = 0; i < files->num_files; i++)
+         {
+            /* printf("file: %s\n", files->files[i]); */
+            _etk_dnd_widget->xdnd_files[i] = strdup(files->files[i]);
+         }
+       
+       /* emit the drop signal so the widget can react */
+       etk_widget_drag_drop(_etk_dnd_widget);
+       
+       ecore_x_dnd_send_finished();
+       break;
+       
+      case ECORE_X_SELECTION_CLIPBOARD:
+       if (!strcmp(ev->target, ECORE_X_SELECTION_TARGET_TARGETS)) 
+         {
+            printf("clipboard: %s\n", ev->target);
+            targets = ev->data;
+            /*
+            for (i = 0; i < targets->num_targets; i++)
+              printf("target: %s\n", targets->targets[i]);
+            */
+         } 
+       else 
+         {
+            text = ev->data;
+            /* printf("clipboard: %s %s\n", ev->target, text->text); */
+         }
+       break;
+     }
+   
+   return 1;
+}
+
+#endif
+
 /** @} */
===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/etk_types.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -3 -r1.22 -r1.23
--- etk_types.h 19 Jan 2006 23:09:24 -0000      1.22
+++ etk_types.h 8 Feb 2006 12:49:38 -0000       1.23
@@ -105,6 +105,7 @@
 typedef struct _Etk_Notebook Etk_Notebook;
 typedef struct _Etk_Progress_Bar Etk_Progress_Bar;
 typedef enum _Etk_Progress_Bar_Orientation Etk_Progress_Bar_Orientation;
+typedef struct _Etk_Spin_Button Etk_Spin_Button;
 
 /**
  * @enum Etk_Fill_Policy_Flags
===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/etk_widget.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -3 -r1.18 -r1.19
--- etk_widget.c        15 Jan 2006 11:07:17 -0000      1.18
+++ etk_widget.c        8 Feb 2006 12:49:38 -0000       1.19
@@ -13,6 +13,7 @@
 #include "etk_marshallers.h"
 #include "etk_signal.h"
 #include "etk_signal_callback.h"
+#include "config.h"
 
 /**
  * @addtogroup Etk_Widget
@@ -60,6 +61,7 @@
    ETK_WIDGET_FOCUS_SIGNAL,
    ETK_WIDGET_UNFOCUS_SIGNAL,
    ETK_WIDGET_SCROLL_SIZE_CHANGED_SIGNAL,
+   ETK_WIDGET_DRAG_DROP_SIGNAL,
    ETK_WIDGET_NUM_SIGNALS
 };
 
@@ -90,6 +92,7 @@
 static void _etk_widget_leave_handler(Etk_Widget *widget);
 static void _etk_widget_focus_handler(Etk_Widget *widget);
 static void _etk_widget_unfocus_handler(Etk_Widget *widget);
+static void _etk_widget_drag_drop_handler(Etk_Widget *widget);
 
 static void _etk_widget_mouse_in_cb(void *data, Evas *evas, Evas_Object 
*object, void *event_info);
 static void _etk_widget_signal_mouse_in_cb(Etk_Object *object, 
Etk_Event_Mouse_In_Out *event, void *data);
@@ -167,6 +170,7 @@
       _etk_widget_signals[ETK_WIDGET_FOCUS_SIGNAL] =         
etk_signal_new("focus",         widget_type, ETK_MEMBER_OFFSET(Etk_Widget, 
focus),   etk_marshaller_VOID__VOID,    NULL, NULL);
       _etk_widget_signals[ETK_WIDGET_UNFOCUS_SIGNAL] =       
etk_signal_new("unfocus",       widget_type, ETK_MEMBER_OFFSET(Etk_Widget, 
unfocus), etk_marshaller_VOID__VOID,    NULL, NULL);
       _etk_widget_signals[ETK_WIDGET_SCROLL_SIZE_CHANGED_SIGNAL] = 
etk_signal_new("scroll_size_changed", widget_type, -1, 
etk_marshaller_VOID__VOID, NULL, NULL);
+      _etk_widget_signals[ETK_WIDGET_DRAG_DROP_SIGNAL] =     
etk_signal_new("drag_drop",     widget_type, ETK_MEMBER_OFFSET(Etk_Widget, 
drag_drop),etk_marshaller_VOID__VOID,    NULL, NULL);
       
       etk_type_property_add(widget_type, "name",              
ETK_WIDGET_NAME_PROPERTY,              ETK_PROPERTY_STRING,  
ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_string(NULL));
       etk_type_property_add(widget_type, "parent",            
ETK_WIDGET_PARENT_PROPERTY,            ETK_PROPERTY_POINTER, 
ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_pointer(NULL));
@@ -1395,6 +1399,19 @@
    return widget->clip;
 }
 
+#if HAVE_ECORE_X
+/**
+ * @brief Sends the "drag_drop" signal
+ * @param widget a widget
+ */
+void etk_widget_drag_drop(Etk_Widget *widget)
+{
+   if (!widget)
+     return;
+   etk_signal_emit(_etk_widget_signals[ETK_WIDGET_DRAG_DROP_SIGNAL], 
ETK_OBJECT(widget), NULL);
+}
+
+#endif
 
 /**************************
  *
@@ -1429,7 +1446,8 @@
    widget->leave = _etk_widget_leave_handler;
    widget->focus = _etk_widget_focus_handler;
    widget->unfocus = _etk_widget_unfocus_handler;
-
+   widget->drag_drop = _etk_widget_drag_drop_handler;
+   
    widget->left_inset = 0;
    widget->right_inset = 0;
    widget->top_inset = 0;
@@ -1460,7 +1478,12 @@
    widget->need_redraw = ETK_FALSE;
    widget->need_theme_min_size_recalc = ETK_FALSE;
    widget->swallowed = ETK_FALSE;
-
+#if HAVE_ECORE_X   
+   widget->accepts_xdnd = ETK_FALSE;
+   widget->xdnd_files = NULL;
+   widget->xdnd_files_num = 0;
+#endif   
+   
    etk_signal_connect_full(_etk_widget_signals[ETK_WIDGET_MOUSE_IN_SIGNAL], 
ETK_OBJECT(widget), ETK_CALLBACK(_etk_widget_signal_mouse_in_cb), NULL, 
ETK_FALSE, ETK_FALSE);
    etk_signal_connect_full(_etk_widget_signals[ETK_WIDGET_MOUSE_OUT_SIGNAL], 
ETK_OBJECT(widget), ETK_CALLBACK(_etk_widget_signal_mouse_out_cb), NULL, 
ETK_FALSE, ETK_FALSE);
    etk_signal_connect_full(_etk_widget_signals[ETK_WIDGET_MOUSE_DOWN_SIGNAL], 
ETK_OBJECT(widget), ETK_CALLBACK(_etk_widget_signal_mouse_down_cb), NULL, 
ETK_FALSE, ETK_FALSE);
@@ -1633,6 +1656,15 @@
    etk_widget_theme_object_signal_emit(widget, "unfocus");
 }
 
+/* Default handler for the "drag_drop" signal */
+static void _etk_widget_drag_drop_handler(Etk_Widget *widget)
+{
+   if (!widget)
+     return;
+   etk_widget_theme_object_signal_emit(widget, "drag_drop");
+}
+
+
 /* Sets the widget as visible and queues a visibility update */
 static void _etk_widget_show_handler(Etk_Widget *widget)
 {
@@ -1926,6 +1958,35 @@
       _etk_widget_key_up_cb(widget->parent, evas, NULL, event_info);
 }
 
+#if HAVE_ECORE_X
+void etk_widget_xdnd_set(Etk_Widget *widget, Etk_Bool on)
+{
+   if(on)
+     widget->accepts_xdnd = 1;
+   else
+     widget->accepts_xdnd = 0;
+}
+
+Etk_Bool etk_widget_xdnd_get(Etk_Widget *widget)
+{
+   if(widget->accepts_xdnd) return ETK_TRUE;
+
+   return ETK_FALSE;
+}
+
+const char ** etk_widget_xdnd_files_get(Etk_Widget *widget, int *num_files)
+{
+   if(!widget->accepts_xdnd || widget->xdnd_files == NULL)
+     return NULL;
+   
+   if(num_files)
+     *num_files = widget->xdnd_files_num;
+     
+   return widget->xdnd_files;
+}
+#endif
+
+
 /**************************
  *
  * Private functions
@@ -2164,8 +2225,8 @@
          evas_object_move(widget->theme_object, widget->geometry.x, 
widget->geometry.y);
          evas_object_resize(widget->theme_object, widget->geometry.w, 
widget->geometry.h);
       }
-      if (widget->size_allocate)
-         widget->size_allocate(widget, widget->inner_geometry);
+      if (widget->size_allocate)       
+       widget->size_allocate(widget, widget->inner_geometry);  
       
       widget->need_redraw = ETK_FALSE;
    }
===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/etk_widget.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -3 -r1.12 -r1.13
--- etk_widget.h        19 Dec 2005 13:30:32 -0000      1.12
+++ etk_widget.h        8 Feb 2006 12:49:38 -0000       1.13
@@ -3,6 +3,7 @@
 #define _ETK_WIDGET_H_
 
 #include <Evas.h>
+#include <Ecore_X.h>
 #include <stdarg.h>
 #include "etk_object.h"
 #include "etk_types.h"
@@ -165,7 +166,8 @@
    void (*scroll_size_get)(Etk_Widget *widget, Etk_Size *scroll_size);
    void (*scroll_margins_get)(Etk_Widget *widget, Etk_Size *margin_size);
    void (*scroll)(Etk_Widget *widget, int x, int y);
-
+   void (*drag_drop)(Etk_Widget *widget);
+   
    void (*show)(Etk_Widget *widget);
    void (*enter)(Etk_Widget *widget);
    void (*leave)(Etk_Widget *widget);
@@ -184,6 +186,12 @@
    unsigned char need_redraw : 1;
    unsigned char need_theme_min_size_recalc : 1;
    unsigned char swallowed : 1;
+//#if HAVE_ECORE_X   
+   unsigned char accepts_xdnd : 1;   
+   
+   char **xdnd_files;
+   int    xdnd_files_num;
+//#endif
 };
 
 Etk_Type *etk_widget_type_get();
@@ -255,6 +263,13 @@
 void etk_widget_clip_unset(Etk_Widget *widget);
 Evas_Object *etk_widget_clip_get(Etk_Widget *widget);
 
+//#if HAVE_ECORE_X
+void          etk_widget_xdnd_set(Etk_Widget *widget, Etk_Bool on);
+Etk_Bool      etk_widget_xdnd_get(Etk_Widget *widget);
+const char  **etk_widget_xdnd_files_get(Etk_Widget *e, int *num_files);
+void          etk_widget_drag_drop(Etk_Widget *widget);
+//#endif
+
 /** @} */
 
 #endif
===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/etk_window.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -3 -r1.9 -r1.10
--- etk_window.c        15 Jan 2006 11:07:17 -0000      1.9
+++ etk_window.c        8 Feb 2006 12:49:38 -0000       1.10
@@ -1,6 +1,7 @@
 /** @file etk_window.c */
 #include "etk_window.h"
 #include <stdlib.h>
+#include <string.h>
 #include <Ecore_X.h>
 #include <Ecore_X_Cursor.h>
 #include "etk_main.h"
@@ -447,6 +448,22 @@
    return ETK_TRUE;
 }
 
+#if HAVE_ECORE_X
+/**
+ * @brief A utility function to use as a callback for the "delete_event" 
signal. It will hide the window and return ETK_TRUE to prevent the program to 
quit
+ * @param window the window to hide
+ * @param data the data passed when the signal is emitted - unused
+ * @return Return ETK_TRUE so the the program won't quit
+ */
+void etk_window_xdnd_aware_set(Etk_Window *window, Etk_Bool on)
+{
+   if(on)
+     ecore_x_dnd_aware_set(window->x_window, 1);
+   else
+     ecore_x_dnd_aware_set(window->x_window, 0);
+}
+#endif
+
 /**************************
  *
  * Etk specific functions
@@ -463,6 +480,25 @@
 
    window->ecore_evas = ecore_evas_software_x11_new(NULL, 0, 0, 0, 0, 0);
    window->x_window = ecore_evas_software_x11_window_get(window->ecore_evas);
+   
+#if HAVE_ECORE_X      
+     {   
+       const char *types[] = { "*" };
+       char **drop_types;
+       int i;
+       
+       ecore_x_dnd_aware_set(window->x_window, 1);     
+       
+       drop_types = calloc(1, sizeof(char *));
+       
+       for (i = 0; i < 1; i++)
+         drop_types[i] = strdup(types[i]);
+       
+       ecore_x_dnd_types_set(window->x_window, drop_types , 1);        
+     }
+   
+#endif   
+   
    ETK_TOPLEVEL_WIDGET(window)->evas = ecore_evas_get(window->ecore_evas);
    ETK_TOPLEVEL_WIDGET(window)->pointer_set = _etk_window_pointer_set;
    ETK_TOPLEVEL_WIDGET(window)->geometry_get = 
_etk_window_toplevel_geometry_get;




-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to