Enlightenment CVS committal

Author  : moom
Project : e17
Module  : libs/etk

Dir     : e17/libs/etk/src/lib


Modified Files:
        etk_string.c etk_string.h 


Log Message:
* [Etk_String] Make it faster when manipulating big texts. It also does 
      less memory allocations now.
* [Etk_String] Add property_set/get() functions
* [Etk_String] Fix the documentation


===================================================================
RCS file: /cvs/e/e17/libs/etk/src/lib/etk_string.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -3 -r1.19 -r1.20
--- etk_string.c        28 Sep 2007 19:47:51 -0000      1.19
+++ etk_string.c        31 Oct 2007 18:46:16 -0000      1.20
@@ -16,18 +16,29 @@
  * @{
  */
 
-#define ETK_STRING_BLOCK_SIZE 128
-#define ETK_STRING_SIZE_TO_ALLOC(length) \
-   (((length) + (ETK_STRING_BLOCK_SIZE - 1)) / ETK_STRING_BLOCK_SIZE) * 
ETK_STRING_BLOCK_SIZE
+#define BLOCK_SIZE 128
+#define SIZE_TO_ALLOC(length) \
+   (((length) + (BLOCK_SIZE - 1)) / BLOCK_SIZE) * BLOCK_SIZE
 
 enum _Etk_String_Property_Id
 {
    ETK_STRING_STRING_PROPERTY
 };
 
-static void _etk_string_constructor(Etk_String *string);
-static void _etk_string_destructor(Etk_String *string);
+static void  _etk_string_constructor(Etk_String *string);
+static void  _etk_string_destructor(Etk_String *string);
+static void  _etk_string_property_set(Etk_Object *object, int property_id, 
Etk_Property_Value *value);
+static void  _etk_string_property_get(Etk_Object *object, int property_id, 
Etk_Property_Value *value);
 static char *_etk_string_vprintf(const char *format, va_list args);
+static int   _etk_string_strlen_max(const char *string, int max_len);
+
+static char *_empty_string = "";
+
+/**************************
+ *
+ * Implementation
+ *
+ **************************/
 
 /**
  * @internal
@@ -41,9 +52,12 @@
    if (!string_type)
    {
       string_type = etk_type_new("Etk_String", ETK_OBJECT_TYPE, 
sizeof(Etk_String),
-         ETK_CONSTRUCTOR(_etk_string_constructor), 
ETK_DESTRUCTOR(_etk_string_destructor), NULL);
+            ETK_CONSTRUCTOR(_etk_string_constructor), 
ETK_DESTRUCTOR(_etk_string_destructor), NULL);
       etk_type_property_add(string_type, "string", ETK_STRING_STRING_PROPERTY,
-         ETK_PROPERTY_STRING, ETK_PROPERTY_READABLE_WRITABLE,  
etk_property_value_string(NULL));
+            ETK_PROPERTY_STRING, ETK_PROPERTY_READABLE_WRITABLE, 
etk_property_value_string(NULL));
+      
+      string_type->property_set = _etk_string_property_set;
+      string_type->property_get = _etk_string_property_get;
    }
 
    return string_type;
@@ -51,61 +65,69 @@
 
 /**
  * @brief Creates a new string
- * @param value the default value of the string. Can be NULL
+ * @param value the default value of the string. It can be NULL
  * @return Returns the new string
  */
 Etk_String *etk_string_new(const char *value)
 {
-   return etk_string_set(ETK_STRING(etk_object_new(ETK_STRING_TYPE, NULL)), 
value);
+   Etk_String *string;
+   
+   string = ETK_STRING(etk_object_new(ETK_STRING_TYPE, NULL));
+   return etk_string_set(string, value);
 }
 
 /**
  * @brief Creates a new string, with a specific size.
- * @param value the default value of the string. Can be NULL
- * @param size If @a size is lower than the length of @a value, the string 
will be truncated. @n
- * Otherwise, extra memory will be allocated (useful if you planned to insert 
text often
- * and want to avoid too many reallocations)
+ * @param value the default value of the string. It can be NULL
+ * @param size If @a size is lower than the length of @a value, the value will 
be truncated.
+ * Otherwise, if @a size is greater than the length of @a value, extra memory 
will be allocated.
+ * It may be useful if you plan to often insert text and want to avoid too 
many reallocations.
  * @return Returns the new string
  */
 Etk_String *etk_string_new_sized(const char *value, int size)
 {
-   return etk_string_set_sized(ETK_STRING(etk_object_new(ETK_STRING_TYPE, 
NULL)), value, size);
+   Etk_String *string;
+   
+   string = ETK_STRING(etk_object_new(ETK_STRING_TYPE, NULL));
+   return etk_string_set_sized(string, value, size);
 }
 
 /**
- * @brief Creates a new string, and sets its default value from the format and 
the arguments
- * @param format the format to set to the string. It uses the same arguments 
than printf()
+ * @brief Creates a new string, and sets its default value from the given 
format and arguments
+ * @param format the format to set to the string. It uses the same arguments 
as printf()
  * @param ... the arguments corresponding to the format
  * @return Returns the new string
  */
 Etk_String *etk_string_new_printf(const char *format, ...)
 {
-   Etk_String *new_string;
+   Etk_String *string;
    va_list args;
 
    va_start(args, format);
-   new_string = 
etk_string_set_vprintf(ETK_STRING(etk_object_new(ETK_STRING_TYPE, NULL)), 
format, args);
+   string = ETK_STRING(etk_object_new(ETK_STRING_TYPE, NULL));
+   string = etk_string_set_vprintf(string, format, args);
    va_end(args);
 
-   return new_string;
+   return string;
 }
 
 /**
- * @brief Creates a new string, and sets its default value from the format and 
the arguments
- * @param format the format to set to the string. It uses the same arguments 
than printf()
+ * @brief Creates a new string, and sets its default value from the given 
format and arguments
+ * @param format the format to set to the string. It uses the same arguments 
as printf()
  * @param args the arguments corresponding to the format
  * @return Returns the new string
  */
 Etk_String *etk_string_new_vprintf(const char *format, va_list args)
 {
-   Etk_String *new_string;
+   Etk_String *string;
    va_list args2;
 
    va_copy(args2, args);
-   new_string = 
etk_string_set_vprintf(ETK_STRING(etk_object_new(ETK_STRING_TYPE, NULL)), 
format, args2);
+   string = ETK_STRING(etk_object_new(ETK_STRING_TYPE, NULL));
+   string = etk_string_set_vprintf(string, format, args2);
    va_end(args2);
 
-   return new_string;
+   return string;
 }
 
 /**
@@ -122,15 +144,15 @@
 }
 
 /**
- * @brief Gets the string as an array of char
+ * @brief Gets the string as an array of chars
  * @param string a string
- * @param Returns the string as an array of char (a pointer on the first 
character)
+ * @param Returns the string as an array of chars (i.e a pointer on the first 
character)
  */
 const char *etk_string_get(Etk_String *string)
 {
    if (!string)
       return NULL;
-   return string->string;
+   return string->string ? string->string : _empty_string;
 }
 
 /**
@@ -148,28 +170,30 @@
 /**
  * @brief Truncates the string
  * @param string a string
- * @param length the new length of the string. If @a length is greater than 
the current length of the string, the function does nothing
+ * @param length the new length of the string. If @a length is greater than
+ * the current length of the string, the function does nothing
  * @return Returns the truncated string
  */
 Etk_String *etk_string_truncate(Etk_String *string, int length)
 {
-   if (!string)
+   if (!string || length < 0)
       return NULL;
 
    if (length < string->length)
    {
-      string->string[length] = 0;
+      string->string[length] = '\0';
       string->length = length;
       etk_object_notify(ETK_OBJECT(string), "string");
    }
+   
    return string;
 }
 
 /**
- * @brief Removes from the string a segment of size "size" from the position 
"pos"
+ * @brief Removes from the string a segment of @a size chars from the position 
@a pos
  * @param string a string
- * @param pos the position where to start the deletion
- * @param size the size of the segment of text to remove
+ * @param pos the position where to start the deletion (starting from 0)
+ * @param size the number of chars to remove
  * @return Returns the string
  */
 Etk_String *etk_string_delete(Etk_String *string, int pos, int size)
@@ -189,9 +213,10 @@
 }
 
 /**
- * @brief Clears the string: all the allocated memory will be freed, and the 
length of the string will be 0
+ * @brief Clears the string: all the allocated memory will be freed,
+ * and the length of the string will be set to 0
  * @param string the string to clear
- * @return Returns the string
+ * @return Returns the cleared string
  */
 Etk_String *etk_string_clear(Etk_String *string)
 {
@@ -199,7 +224,7 @@
       return NULL;
 
    free(string->string);
-   string->string = strdup("");
+   string->string = NULL;
    string->length = 0;
    string->allocated_length = 0;
 
@@ -221,8 +246,9 @@
  * @brief Sets the value of a string, with a specific size.
  * @param string a string. If @a string is NULL, a new string is created
  * @param value the value to assign to the string
- * @param size If @a size is lower than the length of @a value, the string 
will be truncated. @n
- * Otherwise, extra memory will be allocated (useful if you planned to insert 
text often and want to avoid too many reallocations)
+ * @param size If @a size is lower than the length of @a value, the value will 
be truncated.
+ * Otherwise, if @a size is greater than the length of @a value, extra memory 
will be allocated.
+ * It may be useful if you plan to often insert text and want to avoid too 
many reallocations.
  * @return Returns the string
  */
 Etk_String *etk_string_set_sized(Etk_String *string, const char *value, int 
size)
@@ -230,26 +256,20 @@
    if (!string)
       return etk_string_new_sized(value, size);
 
-   if (!value || *value == 0 || size <= 0)
-   {
-      *string->string = 0;
-      string->length = 0;
-   }
+   if (!value || value[0] == '\0' || size <= 0)
+      return etk_string_clear(string);
    else
    {
-      int length;
-
       if (size > string->allocated_length)
       {
          free(string->string);
-         string->string = malloc(ETK_STRING_SIZE_TO_ALLOC(size) + 1);
-         string->allocated_length = ETK_STRING_SIZE_TO_ALLOC(size);
+         string->string = malloc(SIZE_TO_ALLOC(size) + 1);
+         string->allocated_length = SIZE_TO_ALLOC(size);
       }
 
-      length = strlen(value);
-      string->length = ETK_MIN(length, size);
+      string->length = _etk_string_strlen_max(value, size);
       strncpy(string->string, value, string->length);
-      string->string[string->length] = 0;
+      string->string[string->length] = '\0';
    }
 
    etk_object_notify(ETK_OBJECT(string), "string");
@@ -257,22 +277,21 @@
 }
 
 /**
- * @brief Sets the value of the string from the format and the arguments
+ * @brief Sets the value of the string from the given format and arguments
  * @param string a string. If @a string is NULL, a new string is created
- * @param format the format to set to the string. It uses the same arguments 
than printf()
+ * @param format the format to set to the string. It uses the same arguments 
as printf()
  * @param ... the arguments corresponding to the format
  * @return Returns the string
  */
 Etk_String *etk_string_set_printf(Etk_String *string, const char *format, ...)
 {
    va_list args;
-   Etk_String *result;
 
    va_start(args, format);
-   result = etk_string_set_vprintf(string, format, args);
+   string = etk_string_set_vprintf(string, format, args);
    va_end(args);
 
-   return result;
+   return string;
 }
 
 /**
@@ -286,15 +305,14 @@
 {
    va_list args2;
    char *text;
-   Etk_String *result;
 
    va_copy(args2, args);
    text = _etk_string_vprintf(format, args2);
-   result = etk_string_set(string, text);
+   string = etk_string_set(string, text);
    free(text);
    va_end(args2);
 
-   return result;
+   return string;
 }
 
 /**
@@ -309,7 +327,7 @@
 }
 
 /**
- * @brief Prepends a text with a specific length  to a string
+ * @brief Prepends a text with a specific length to a string
  * @param string a string. If @a string is NULL, a new string is created
  * @param text the text to prepend to the string
  * @param length the length of the text to prepend
@@ -332,41 +350,41 @@
 }
 
 /**
- * @brief Prepends a text to a string from the format and the arguments
+ * @brief Prepends a text to the string, from the given format and arguments
  * @param string a string. If @a string is NULL, a new string is created
- * @param format the format to prepend to the string. It uses the same 
arguments than printf()
+ * @param format the format of the text to prepend to the string.
+ * It uses the same arguments than printf()
  * @param ... the arguments corresponding to the format
  * @return Returns the string
  */
 Etk_String *etk_string_prepend_printf(Etk_String *string, const char *format, 
...)
 {
    va_list args;
-   Etk_String *result;
 
    va_start(args, format);
-   result = etk_string_prepend_vprintf(string, format, args);
+   string = etk_string_prepend_vprintf(string, format, args);
    va_end(args);
 
-   return result;
+   return string;
 }
 
 /**
- * @brief Prepends a text to a string from the format and the arguments
+ * @brief Prepends a text to the string, from the given format and arguments
  * @param string a string. If @a string is NULL, a new string is created
- * @param format the format to prepend to the string. It uses the same 
arguments than printf()
+ * @param format the format of the text to prepend to the string.
+ * It uses the same arguments than printf()
  * @param args the arguments corresponding to the format
  * @return Returns the string
  */
 Etk_String *etk_string_prepend_vprintf(Etk_String *string, const char *format, 
va_list args)
 {
    va_list args2;
-   Etk_String *result;
 
    va_copy(args2, args);
-   result = etk_string_insert_vprintf(string, 0, format, args2);
+   string = etk_string_insert_vprintf(string, 0, format, args2);
    va_end(args2);
 
-   return result;
+   return string;
 }
 
 /**
@@ -381,7 +399,7 @@
 }
 
 /**
- * @brief Appends a text with a specific length  to a string
+ * @brief Appends a text with a specific length to a string
  * @param string a string. If @a string is NULL, a new string is created
  * @param text the text to append to the string
  * @param length the length of the text to append
@@ -404,47 +422,47 @@
 }
 
 /**
- * @brief Appends a text to a string from the format and the arguments
+ * @brief Appends a text to the string, from the given format and arguments
  * @param string a string. If @a string is NULL, a new string is created
- * @param format the format to append to the string. It uses the same 
arguments than printf()
+ * @param format the format of the text to append to the string.
+ * It uses the same arguments than printf()
  * @param ... the arguments corresponding to the format
  * @return Returns the string
  */
 Etk_String *etk_string_append_printf(Etk_String *string, const char *format, 
...)
 {
    va_list args;
-   Etk_String *result;
 
    va_start(args, format);
-   result = etk_string_append_vprintf(string, format, args);
+   string = etk_string_append_vprintf(string, format, args);
    va_end(args);
 
-   return result;
+   return string;
 }
 
 /**
- * @brief Appends a text to a string from the format and the arguments
+ * @brief Appends a text to the string, from the given format and arguments
  * @param string a string. If @a string is NULL, a new string is created
- * @param format the format to append to the string. It uses the same 
arguments than printf()
+ * @param format the format of the text to append to the string.
+ * It uses the same arguments than printf()
  * @param args the arguments corresponding to the format
  * @return Returns the string
  */
 Etk_String *etk_string_append_vprintf(Etk_String *string, const char *format, 
va_list args)
 {
    va_list args2;
-   Etk_String *result;
 
    va_copy(args2, args);
-   result = etk_string_insert_vprintf(string, string->length, format, args2);
+   string = etk_string_insert_vprintf(string, string->length, format, args2);
    va_end(args2);
 
-   return result;
+   return string;
 }
 
 /**
- * @brief Inserts a text into a string
+ * @brief Inserts a text into a string, at a given position
  * @param string a string. If @a string is NULL, a new string is created
- * @param pos the position where to insert the text
+ * @param pos the position where to insert the text (starting from 0)
  * @param text the text to insert into the string
  * @return Returns the string
  */
@@ -454,41 +472,41 @@
 }
 
 /**
- * @brief Inserts a text with a specific length into a string
+ * @brief Inserts a text with a specific length into a string, at a given 
position
  * @param string a string. If @a string is NULL, a new string is created
- * @param pos the position where to insert the text
+ * @param pos the position where to insert the text (starting from 0)
  * @param text the text to insert into the string
- * @param length the length of the text to insert
+ * @param length the maximum length of the text to insert
  * @return Returns the string
  */
 Etk_String *etk_string_insert_sized(Etk_String *string, int pos, const char 
*text, int length)
 {
    if (!string)
       return etk_string_new_sized(text, length);
-   if (!text || *text == 0 || length <= 0)
+   if (!text || text[0] == '\0' || length <= 0)
       return string;
 
    pos = ETK_CLAMP(pos, 0, string->length);
-   length = ETK_MIN(length, strlen(text));
+   length = _etk_string_strlen_max(text, length);
    if (string->length + length > string->allocated_length)
    {
-      string->string = realloc(string->string, 
ETK_STRING_SIZE_TO_ALLOC(string->length + length) + 1);
-      string->allocated_length = ETK_STRING_SIZE_TO_ALLOC(string->length + 
length);
+      string->string = realloc(string->string, SIZE_TO_ALLOC(string->length + 
length) + 1);
+      string->allocated_length = SIZE_TO_ALLOC(string->length + length);
    }
 
    memmove(&string->string[pos + length], &string->string[pos], string->length 
- pos);
    strncpy(&string->string[pos], text, length);
    string->length += length;
-   string->string[string->length] = 0;
+   string->string[string->length] = '\0';
 
    etk_object_notify(ETK_OBJECT(string), "string");
    return string;
 }
 
 /**
- * @brief Inserts a character into a string
+ * @brief Inserts a character into a string, at a given position
  * @param string a string. If @a string is NULL, a new string is created
- * @param pos the positon where to insert the char
+ * @param pos the position where to insert the char
  * @param c the character to insert into the string
  * @return Returns the string
  */
@@ -498,30 +516,30 @@
 
    if (!string)
       return etk_string_insert_char(etk_string_new(NULL), pos, c);
-   if (c == 0)
+   if (c == '\0')
       return etk_string_truncate(string, pos);
 
    pos = ETK_CLAMP(pos, 0, string->length);
    if (string->length + 1 > string->allocated_length)
    {
-      string->string = realloc(string->string, 
ETK_STRING_SIZE_TO_ALLOC(string->length + 1) + 1);
-      string->allocated_length = ETK_STRING_SIZE_TO_ALLOC(string->length + 1);
+      string->string = realloc(string->string, SIZE_TO_ALLOC(string->length + 
1) + 1);
+      string->allocated_length = SIZE_TO_ALLOC(string->length + 1);
    }
    for (i = string->length - 1; i >= pos; i--)
       string->string[i + 1] = string->string[i];
 
    string->string[pos] = c;
    string->length++;
-   string->string[string->length] = 0;
+   string->string[string->length] = '\0';
 
    etk_object_notify(ETK_OBJECT(string), "string");
    return string;
 }
 
 /**
- * @brief Inserts a text into a string from the format and the arguments
+ * @brief Inserts a text into a string, from the given format and arguments, 
at a given position
  * @param string a string. If @a string is NULL, a new string is created
- * @param pos the positon where to insert the char
+ * @param pos the position where to insert the text
  * @param format the format to insert into the string. It uses the same 
arguments than printf()
  * @param ... the arguments corresponding to the format
  * @return Returns the string
@@ -529,19 +547,18 @@
 Etk_String *etk_string_insert_printf(Etk_String *string, int pos, const char 
*format, ...)
 {
    va_list args;
-   Etk_String *result;
 
    va_start(args, format);
-   result = etk_string_insert_vprintf(string, pos, format, args);
+   string = etk_string_insert_vprintf(string, pos, format, args);
    va_end(args);
 
-   return result;
+   return string;
 }
 
 /**
- * @brief Inserts a text into a string from the format and the arguments
+ * @brief Inserts a text into a string, from the given format and arguments, 
at a given position
  * @param string a string. If @a string is NULL, a new string is created
- * @param pos the positon where to insert the char
+ * @param pos the position where to insert the text
  * @param format the format to insert into the string. It uses the same 
arguments than printf()
  * @param args the arguments corresponding to the format
  * @return Returns the string
@@ -549,16 +566,15 @@
 Etk_String *etk_string_insert_vprintf(Etk_String *string, int pos, const char 
*format, va_list args)
 {
    va_list args2;
-   char *text_to_append;
-   Etk_String *result;
+   char *text;
 
    va_copy(args2, args);
-   text_to_append = _etk_string_vprintf(format, args2);
-   result = etk_string_insert(string, pos, text_to_append);
-   free(text_to_append);
+   text = _etk_string_vprintf(format, args2);
+   string = etk_string_insert(string, pos, text);
+   free(text);
    va_end(args2);
 
-   return result;
+   return string;
 }
 
 /**************************
@@ -573,7 +589,7 @@
    if (!string)
       return;
 
-   string->string = strdup("");
+   string->string = NULL;
    string->length = 0;
    string->allocated_length = 0;
 }
@@ -586,13 +602,49 @@
    free(string->string);
 }
 
+/* Sets the property whose id is "property_id" to the value "value" */
+static void _etk_string_property_set(Etk_Object *object, int property_id, 
Etk_Property_Value *value)
+{
+   Etk_String *string;
+
+   if (!(string = ETK_STRING(object)) || !value)
+      return;
+
+   switch (property_id)
+   {
+      case ETK_STRING_STRING_PROPERTY:
+         etk_string_set(string, etk_property_value_string_get(value));
+         break;
+      default:
+         break;
+   }
+}
+
+/* Gets the value of the property whose id is "property_id" */
+static void _etk_string_property_get(Etk_Object *object, int property_id, 
Etk_Property_Value *value)
+{
+   Etk_String *string;
+
+   if (!(string = ETK_STRING(object)) || !value)
+      return;
+
+   switch (property_id)
+   {
+      case ETK_STRING_STRING_PROPERTY:
+         etk_property_value_string_set(value, string->string);
+         break;
+      default:
+         break;
+   }
+}
+
 /**************************
  *
  * Private functions
  *
  **************************/
 
-/* Creates a new string (char *) from the format and the args, and returns it.
+/* Creates a new string (char *) from the given format and args, and returns 
it.
  * The returned string will have to be freed */
 static char *_etk_string_vprintf(const char *format, va_list args)
 {
@@ -615,4 +667,39 @@
    return text;
 }
 
+/* Calculates the length of the given string.
+ * The returned length can not be greater than "max_len" */
+static int _etk_string_strlen_max(const char *string, int max_len)
+{
+   int i;
+   
+   if (!string)
+      return 0;
+   
+   for (i = 0; i < max_len && string[i] != '\0'; i++);
+   return i;
+}
+
 /** @} */
+
+/**************************
+ *
+ * Documentation
+ *
+ **************************/
+
+/**
+ * @addtogroup Etk_String
+ *
+ * TODOC
+ *
+ * \par Object Hierarchy:
+ * - Etk_Object
+ *   - Etk_String
+ *
+ * \par Properties:
+ * @prop_name "string": the value of the string
+ * @prop_type String (char *)
+ * @prop_rw
+ * @prop_val NULL
+ */
===================================================================
RCS file: /cvs/e/e17/libs/etk/src/lib/etk_string.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -3 -r1.9 -r1.10
--- etk_string.h        19 Sep 2007 20:16:26 -0000      1.9
+++ etk_string.h        31 Oct 2007 18:46:16 -0000      1.10
@@ -11,21 +11,25 @@
 extern "C" {
 #endif
 
+/* TODO: Etk_Object is a little too heavy for a string...
+   maybe we could use Etk_Base instead? */
+
 /**
  * @defgroup Etk_String Etk_String
+ * @brief An object that offers convenient methods to manipulate a string
  * @{
  */
 
-/** @brief Gets the type of a string */
+/** Gets the type of a string */
 #define ETK_STRING_TYPE            (etk_string_type_get())
-/** @brief Casts the object to an Etk_String */
+/** Casts the object to an Etk_String */
 #define ETK_STRING(obj)            (ETK_OBJECT_CAST((obj), ETK_STRING_TYPE, 
Etk_String))
-/** @brief Checks if the object is an Etk_Text_Buffer */
+/** Checks if the object is an Etk_String */
 #define ETK_IS_STRING(obj)         (ETK_OBJECT_CHECK_TYPE((obj), 
ETK_STRING_TYPE))
 
 /**
- * @struct Etk_String
- * @brief An Etk_String is an easy way to manipulate a string
+ * @brief @widget Etk_String is an object that offers convenient methods to 
manipulate a string
+ * @structinfo
  */
 struct Etk_String
 {



-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to