Rewrote o_attrib_get_name_value(): it now has support for UTF-8
attribute strings ; plus it can return only the name or the value or
both name and value.

Finally adapted code wherever it can benefits this new feature.
---
 gnetlist/src/vams_misc.c      |    4 +-
 gschem/src/g_hook.c           |    5 +-
 gschem/src/o_misc.c           |    5 +-
 gschem/src/o_slot.c           |    7 +---
 gschem/src/x_dialog.c         |    5 +--
 gschem/src/x_multiattrib.c    |   22 +++------
 libgeda/include/prototype.h   |    2 +-
 libgeda/src/g_smob.c          |    4 +-
 libgeda/src/o_attrib.c        |   96 ++++++++++++++---------------------------
 libgeda/src/o_complex_basic.c |    4 +-
 10 files changed, 51 insertions(+), 103 deletions(-)

diff --git a/gnetlist/src/vams_misc.c b/gnetlist/src/vams_misc.c
index 9b0d0ed..fb7094c 100644
--- a/gnetlist/src/vams_misc.c
+++ b/gnetlist/src/vams_misc.c
@@ -45,7 +45,6 @@ vams_get_attribs_list(OBJECT *object, SCM *list, OBJECT 
**return_found)
   OBJECT *found;
   int val;
   char* found_name = NULL;
-  char* found_value = NULL;
 
   o_current = object;
 
@@ -55,14 +54,13 @@ vams_get_attribs_list(OBJECT *object, SCM *list, OBJECT 
**return_found)
     found = a_current->object;
     if (found != NULL && found->text && found->text->string) {
       val = o_attrib_get_name_value(found->text->string,
-                                    &found_name, &found_value);
+                                    &found_name, NULL);
 
       if (val) {
         *list = scm_cons (scm_makfrom0str (found_name), *list);
       }
 
      g_free(found_name);
-     g_free(found_value);
 #if DEBUG
       printf("0 _%s_\n", found->text->string);
       printf("1 _%s_\n", found_name);
diff --git a/gschem/src/g_hook.c b/gschem/src/g_hook.c
index 6368fe0..bb5963a 100644
--- a/gschem/src/g_hook.c
+++ b/gschem/src/g_hook.c
@@ -416,7 +416,7 @@ static void custom_world_get_single_object_bounds
     GList *a_iter;
     int rleft, rright, rbottom, rtop;
     char *text_value; 
-    char *name_ptr, *value_ptr, aux_ptr[2];
+    char *name_ptr, aux_ptr[2];
     gboolean include_text;
 
     *left = rleft = toplevel->init_right;
@@ -437,7 +437,7 @@ static void custom_world_get_single_object_bounds
           case (OBJ_TEXT):
            if (obj_ptr->text && obj_ptr->text->string) {
              text_value = obj_ptr->text->string;
-             if (o_attrib_get_name_value(text_value, &name_ptr, &value_ptr) &&
+             if (o_attrib_get_name_value(text_value, &name_ptr, NULL) &&
                  g_list_find_custom(exclude_attrib_list, name_ptr, 
(GCompareFunc) &strcmp)) {
                include_text = FALSE;
              }
@@ -450,7 +450,6 @@ static void custom_world_get_single_object_bounds
                                                &rleft, &rtop, &rright, 
&rbottom);
              }
              g_free(name_ptr);
-             g_free(value_ptr);
            }
            break;
           case (OBJ_COMPLEX):
diff --git a/gschem/src/o_misc.c b/gschem/src/o_misc.c
index b548d34..36a8bc0 100644
--- a/gschem/src/o_misc.c
+++ b/gschem/src/o_misc.c
@@ -817,17 +817,16 @@ void o_update_component(GSCHEM_TOPLEVEL *w_current, 
OBJECT *o_current)
   while (a_iter != NULL) {
     a_current = a_iter->data;
     OBJECT *o_attrib;
-    gchar *name, *value;
+    gchar *name;
     char *attrfound;
     g_assert (a_current->object->type == OBJ_TEXT);
     o_attrib_get_name_value (a_current->object->text->string,
-                             &name, &value);
+                             &name, NULL);
 
     attrfound = o_attrib_search_name_single(o_current, name, NULL);
 
     /* free these now since they are no longer being used */
     g_free(name);
-    g_free(value);
 
     if (attrfound == NULL) {
       /* attribute with same name not found in old component: */
diff --git a/gschem/src/o_slot.c b/gschem/src/o_slot.c
index d8363d7..a47d7c4 100644
--- a/gschem/src/o_slot.c
+++ b/gschem/src/o_slot.c
@@ -113,13 +113,12 @@ void o_slot_end(GSCHEM_TOPLEVEL *w_current, char *string, 
int len)
   char *slot_value;
   char *numslots_value;
   OBJECT *slot_text_object;
-  char *name = NULL;
   char *value = NULL;
   int numslots;
   int new_slot_number;
   int status;
 
-  status = o_attrib_get_name_value(string, &name, &value);
+  status = o_attrib_get_name_value(string, NULL, &value);
   if (!status) {
     s_log_message(_("Slot attribute malformed\n"));
     return;
@@ -142,7 +141,6 @@ void o_slot_end(GSCHEM_TOPLEVEL *w_current, char *string, 
int len)
       s_log_message(_("numslots attribute missing\n"));
       s_log_message(
                     _("Slotting not allowed for this component\n"));
-      g_free(name);
       g_free(value);
       return;
     }
@@ -158,7 +156,6 @@ void o_slot_end(GSCHEM_TOPLEVEL *w_current, char *string, 
int len)
 
     if (new_slot_number > numslots || new_slot_number <=0 ) {
       s_log_message(_("New slot number out of range\n"));
-      g_free(name);
       g_free(value);
       return;
     }
@@ -223,13 +220,11 @@ void o_slot_end(GSCHEM_TOPLEVEL *w_current, char *string, 
int len)
     o_redraw_single(w_current,object);
 
     toplevel->page_current->CHANGED = 1;
-    g_free(name);
     g_free(value);
 
   } else {
     fprintf(stderr,
             _("uggg! you tried to slot edit something that doesn't exist!\n"));
-    g_free(name);
     g_free(value);
     exit(-1);
   }
diff --git a/gschem/src/x_dialog.c b/gschem/src/x_dialog.c
index 180fbbf..c25f468 100644
--- a/gschem/src/x_dialog.c
+++ b/gschem/src/x_dialog.c
@@ -4072,10 +4072,9 @@ x_dialog_close_window (GSCHEM_TOPLEVEL *w_current)
 int x_dialog_validate_attribute(GtkWindow* parent, char *attribute)
 {
   GtkWidget* message_box;
-  char *name_ptr, *value_ptr;
 
   /* validate the new attribute */
-  if (!o_attrib_get_name_value(attribute, &name_ptr, &value_ptr)) {
+  if (!o_attrib_get_name_value(attribute, NULL, NULL)) {
       message_box = gtk_message_dialog_new_with_markup (parent,
                                   GTK_DIALOG_DESTROY_WITH_PARENT,
                                   GTK_MESSAGE_ERROR,
@@ -4087,8 +4086,6 @@ int x_dialog_validate_attribute(GtkWindow* parent, char 
*attribute)
      gtk_widget_destroy (message_box);
      return FALSE;
   }
-  g_free(name_ptr);
-  g_free(value_ptr);
   return TRUE;
 }
 /***************** End of misc helper dialog boxes **************/
diff --git a/gschem/src/x_multiattrib.c b/gschem/src/x_multiattrib.c
index 4aeebe8..679d428 100644
--- a/gschem/src/x_multiattrib.c
+++ b/gschem/src/x_multiattrib.c
@@ -536,19 +536,18 @@ static void 
multiattrib_column_set_data_name(GtkTreeViewColumn *tree_column,
                                             gpointer data)
 {
   OBJECT *o_attrib;
-  gchar *name, *value;
+  gchar *name;
 
   gtk_tree_model_get (tree_model, iter,
                       COLUMN_ATTRIBUTE, &o_attrib,
                       -1);
   g_assert (o_attrib->type == OBJ_TEXT);
   
-  o_attrib_get_name_value (o_attrib->text->string, &name, &value);
+  o_attrib_get_name_value (o_attrib->text->string, &name, NULL);
   g_object_set (cell,
                 "text", name,
                 NULL);
   g_free (name);
-  g_free (value);
   
 }
 
@@ -564,18 +563,17 @@ static void 
multiattrib_column_set_data_value(GtkTreeViewColumn *tree_column,
                                              gpointer data)           
 {
   OBJECT *o_attrib;
-  gchar *name, *value;
+  gchar *value;
 
   gtk_tree_model_get (tree_model, iter,
                       COLUMN_ATTRIBUTE, &o_attrib,
                       -1);
   g_assert (o_attrib->type == OBJ_TEXT);
   
-  o_attrib_get_name_value (o_attrib->text->string, &name, &value);
+  o_attrib_get_name_value (o_attrib->text->string, NULL, &value);
   g_object_set (cell,
                 "text", value,
                 NULL);
-  g_free (name);
   g_free (value);
   
 }
@@ -690,7 +688,7 @@ static void 
multiattrib_callback_edited_name(GtkCellRendererText *cellrendererte
   GtkTreeIter iter;
   OBJECT *o_attrib;
   GSCHEM_TOPLEVEL *w_current;
-  gchar *name, *value, *newtext;
+  gchar *value, *newtext;
 
   model = gtk_tree_view_get_model (multiattrib->treeview);
   w_current = GSCHEM_DIALOG (multiattrib)->w_current;
@@ -717,11 +715,10 @@ static void 
multiattrib_callback_edited_name(GtkCellRendererText *cellrendererte
                       -1);
   g_assert (o_attrib->type == OBJ_TEXT);
 
-  o_attrib_get_name_value (o_attrib->text->string, &name, &value);
+  o_attrib_get_name_value (o_attrib->text->string, NULL, &value);
   newtext = g_strdup_printf ("%s=%s", arg2, value);
 
   if (!x_dialog_validate_attribute(GTK_WINDOW(multiattrib), newtext)) {
-    g_free (name);
     g_free (value);
     g_free(newtext);
     return;
@@ -732,7 +729,6 @@ static void 
multiattrib_callback_edited_name(GtkCellRendererText *cellrendererte
   o_text_change (w_current, o_attrib,
                  newtext, o_attrib->visibility, o_attrib->show_name_value);
 
-  g_free (name);
   g_free (value);
   g_free (newtext);
   
@@ -753,7 +749,7 @@ static void 
multiattrib_callback_edited_value(GtkCellRendererText *cell_renderer
   GtkTreeIter iter;
   OBJECT *o_attrib;
   GSCHEM_TOPLEVEL *w_current;
-  gchar *name, *value, *newtext;
+  gchar *name, *newtext;
 
   model = gtk_tree_view_get_model (multiattrib->treeview);
   w_current = GSCHEM_DIALOG (multiattrib)->w_current;
@@ -767,12 +763,11 @@ static void 
multiattrib_callback_edited_value(GtkCellRendererText *cell_renderer
                       -1);
   g_assert (o_attrib->type == OBJ_TEXT);
 
-  o_attrib_get_name_value (o_attrib->text->string, &name, &value);
+  o_attrib_get_name_value (o_attrib->text->string, &name, NULL);
   newtext = g_strdup_printf ("%s=%s", name, arg2);
 
   if (!x_dialog_validate_attribute(GTK_WINDOW(multiattrib), newtext)) {
     g_free (name);
-    g_free (value);
     g_free(newtext);
     return;
   }
@@ -785,7 +780,6 @@ static void 
multiattrib_callback_edited_value(GtkCellRendererText *cell_renderer
   update_row_display (model, &iter);
   
   g_free (name);
-  g_free (value);
   g_free (newtext);
   
 }
diff --git a/libgeda/include/prototype.h b/libgeda/include/prototype.h
index f1c08d3..82e69d8 100644
--- a/libgeda/include/prototype.h
+++ b/libgeda/include/prototype.h
@@ -106,7 +106,7 @@ void o_attrib_attach(TOPLEVEL *toplevel, OBJECT 
*parent_list, OBJECT *text_objec
 void o_attrib_free_all(TOPLEVEL *toplevel, GList *list);
 void o_attrib_print(GList *attributes);
 void o_attrib_remove(GList **list, OBJECT *remove);
-int o_attrib_get_name_value(char *string, char **name, char **value);
+gboolean o_attrib_get_name_value (const gchar *string, gchar **name_ptr, gchar 
**value_ptr);
 void o_attrib_free_current(TOPLEVEL *toplevel);
 void o_attrib_set_string(TOPLEVEL *toplevel, char *string);
 void o_attrib_set_color(TOPLEVEL *toplevel, GList *attributes);
diff --git a/libgeda/src/g_smob.c b/libgeda/src/g_smob.c
index ca2527e..fc1b0c9 100644
--- a/libgeda/src/g_smob.c
+++ b/libgeda/src/g_smob.c
@@ -164,7 +164,6 @@ SCM g_set_attrib_value_internal(SCM attrib_smob, SCM 
scm_value,
   struct st_attrib_smob *attribute;
   char *name = NULL;
   char *value = NULL;
-  char *old_value = NULL;
 
   SCM_ASSERT ( SCM_NIMP(attrib_smob) && 
                ((long) SCM_CAR(attrib_smob) == attrib_smob_tag),
@@ -182,7 +181,7 @@ SCM g_set_attrib_value_internal(SCM attrib_smob, SCM 
scm_value,
       attribute->attribute->object->text->string ) {
 
     o_attrib_get_name_value(attribute->attribute->object->text->string, 
-                            &name, &old_value );
+                            &name, NULL);
 
     *new_string = g_strconcat (name, "=", value, NULL);
                
@@ -190,7 +189,6 @@ SCM g_set_attrib_value_internal(SCM attrib_smob, SCM 
scm_value,
     *o_attrib = attribute->attribute->object;
 
     g_free(name);
-    g_free(old_value);
   }
 
   return SCM_UNDEFINED;
diff --git a/libgeda/src/o_attrib.c b/libgeda/src/o_attrib.c
index eb29775..962789c 100644
--- a/libgeda/src/o_attrib.c
+++ b/libgeda/src/o_attrib.c
@@ -571,79 +571,52 @@ gchar *o_save_attribs(GList *attribs)
   return g_string_free(acc, FALSE);
 }
 
-/*! \brief Get name and value from name=value attribute.
+/*! \brief Get name and value from an attribute 'name=value' string.
  *  \par Function Description
- *  Get name and value from a name=value attribute.
+ *  This function parses the character string \a string expected to be
+ *  an attribute string of the form 'name=value'.
  *
- *  \param [in]  string     String to split into name/value pair.
- *  \param [out] name_ptr   Name if found in string, NULL otherwise.
- *  \param [out] value_ptr  Value if found in string, NULL otherwise.
- *  \return TRUE if string had equals in it, FALSE otherwise.
+ *  It returns TRUE if it has been able to parse the string into the
+ *  name and value parts of an attribute. Otherwise it returns FALSE,
+ *  in that case \a *name_ptr and \a *value_ptr are unset.
  *
- *  \note
- *  both name and value must be pre allocated
- *  And if you get an invalid attribute (improper) with a name and no
- *  value, then it is NOT an attribute.
- *  Also, there cannot be any spaces beside the equals sign
- *  Changed: now it allocates memory for name and value strings.
- *  \warning
- *  Caller must g_free these strings when not needed.
+ *  \a name_ptr and/or \a value_ptr can be NULL.
+ *
+ *  \param [in]  string     String to split into name/value pair.
+ *  \param [out] name_ptr   The return location for the name, or NULL.
+ *  \param [out] value_ptr  The return location for the value, or NULL.
+ *  \return TRUE on success, FALSE otherwise.
  */
-int o_attrib_get_name_value(char *string, char **name_ptr, char **value_ptr )
+gboolean
+o_attrib_get_name_value (const gchar *string, gchar **name_ptr, gchar 
**value_ptr)
 {
-  char *equal_ptr;
-  char **str_array;
+  gchar *ptr, *prev_char, *next_char;
+  
+  g_return_val_if_fail (string != NULL, FALSE);
 
-  if (name_ptr == NULL || value_ptr == NULL) {
-    return(FALSE);
+  ptr = g_utf8_strchr (string, -1, g_utf8_get_char ("="));
+  if (ptr == NULL) {
+    return FALSE;
   }
 
-  *name_ptr = NULL;  /* force these values to null */
-  *value_ptr = NULL;
-
-  if (!string) {
-    return(FALSE);
+  prev_char = g_utf8_find_prev_char (string, ptr);
+  next_char = g_utf8_find_next_char (ptr, NULL);
+  if ((prev_char == NULL) ||
+      g_unichar_isspace (g_utf8_get_char (prev_char)) ||
+      ((next_char != NULL) &&
+       g_unichar_isspace (g_utf8_get_char (next_char)))) {
+    return FALSE;
   }
 
-  /* make sure there are no spaces in between equals */
-  equal_ptr = strchr(string, '=');
-  if (equal_ptr == NULL) {
-    return(FALSE);
+  if (name_ptr != NULL) {
+    *name_ptr = g_strndup (string, (ptr - string));
   }
 
-
-  /*! \todo Technically this isn't a correct if statement.  This if will 
-   * cause an invalid read for strings:  =name and value= 
-   */
-  if ( (*(equal_ptr + 1) == ' ') || (*(equal_ptr - 1) == ' ') ) {
-     /* sometimes you have text with an ='s in it, it shouldn't be */
-     /* treated like an attribute */
-
-#if DEBUG 
-    s_log_message("Found attrib/text with spaces beside the ='s [%s]\n", 
-                 string);
-    s_log_message("You can ignore the above message if the text is not 
intended to be an attribute\n");
-#endif
-
-    return(FALSE);
+  if (value_ptr != NULL) {
+    *value_ptr = g_strdup (next_char != NULL ? next_char : "");
   }
 
-  str_array = g_strsplit (string, "=", 2);
-  
-  *name_ptr = g_strdup(str_array[0]);
-  *value_ptr = g_strdup(str_array[1]);
-  g_strfreev(str_array);
-  
-  if (*value_ptr && (*value_ptr)[0] == '\0') {
-    s_log_message(_("Found an improper attribute: _%s_\n"), string);
-#if 0 /* for now leak this memory till this is verified correct everywhere */
-    g_free(*name_ptr); *name_ptr = NULL;
-    g_free(*value_ptr); *value_ptr = NULL;
-#endif
-    return(FALSE);
-  } else {
-    return(TRUE);
-  }
+  return TRUE;
 }
 
 /*! \brief Free the currently selected attribute.
@@ -934,7 +907,6 @@ char *o_attrib_search_string_partial(OBJECT *object, char 
*search_for,
   OBJECT *o_current;
   int val;
   int internal_counter=0;
-  char *found_name = NULL;
   char *found_value = NULL;
   char *return_string = NULL;
 
@@ -950,10 +922,9 @@ char *o_attrib_search_string_partial(OBJECT *object, char 
*search_for,
         internal_counter++;    
       } else {
         val = o_attrib_get_name_value(o_current->text->string, 
-                                      &found_name, &found_value);
+                                      NULL, &found_value);
         if (val) {
           return_string = g_strdup(found_value);
-         g_free(found_name);
          g_free(found_value);
          return(return_string);
         }
@@ -961,7 +932,6 @@ char *o_attrib_search_string_partial(OBJECT *object, char 
*search_for,
     }
   }    
        
-  g_free(found_name);
   g_free(found_value);
   return (NULL);
 } 
diff --git a/libgeda/src/o_complex_basic.c b/libgeda/src/o_complex_basic.c
index 03cd837..0b8bddb 100644
--- a/libgeda/src/o_complex_basic.c
+++ b/libgeda/src/o_complex_basic.c
@@ -231,7 +231,6 @@ int o_complex_is_eligible_attribute (TOPLEVEL *toplevel, 
OBJECT *object,
                                     int promote_invisible) 
 {
   char *name = NULL;
-  char *value = NULL;
   char *padded_name = NULL;
   int promotableAttribute = FALSE;
   char *ptr;
@@ -260,7 +259,7 @@ int o_complex_is_eligible_attribute (TOPLEVEL *toplevel, 
OBJECT *object,
   if (toplevel->always_promote_attributes &&
       (strlen(toplevel->always_promote_attributes) != 0))
   {
-    if (o_attrib_get_name_value(object->text->string, &name, &value))
+    if (o_attrib_get_name_value(object->text->string, &name, NULL))
     {
       padded_name = g_strdup_printf(" %s ", name);
       if (strstr(toplevel->always_promote_attributes, padded_name))
@@ -272,7 +271,6 @@ int o_complex_is_eligible_attribute (TOPLEVEL *toplevel, 
OBJECT *object,
       
       g_free(padded_name);
       g_free(name);
-      g_free(value);
       if (promotableAttribute)
        return TRUE;
     }
-- 
1.5.6




_______________________________________________
geda-dev mailing list
[email protected]
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev

Reply via email to