gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r27848 - in gnunet-gtk: contrib src/setup


From: gnunet
Subject: [GNUnet-SVN] r27848 - in gnunet-gtk: contrib src/setup
Date: Wed, 10 Jul 2013 00:36:54 +0200

Author: grothoff
Date: 2013-07-10 00:36:54 +0200 (Wed, 10 Jul 2013)
New Revision: 27848

Modified:
   gnunet-gtk/contrib/gnunet_setup_gns_edit_a.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_aaaa.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_cname.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_leho.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_mx.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_ns.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_pkey.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_ptr.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_soa.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_srv.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_txt.glade
   gnunet-gtk/contrib/gnunet_setup_gns_edit_vpn.glade
   gnunet-gtk/contrib/gnunet_setup_gtk_main_window.glade
   gnunet-gtk/src/setup/gnunet-setup-gns-edit.c
   gnunet-gtk/src/setup/gnunet-setup-gns-edit.h
   gnunet-gtk/src/setup/gnunet-setup-gns.c
Log:
-towards fixing #2931, not finished

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_a.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_a.glade    2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_a.glade    2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -126,7 +126,8 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -134,7 +135,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_aaaa.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_aaaa.glade 2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_aaaa.glade 2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -109,7 +109,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -117,7 +117,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_cname.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_cname.glade        2013-07-09 
21:41:19 UTC (rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_cname.glade        2013-07-09 
22:36:54 UTC (rev 27848)
@@ -109,7 +109,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -117,7 +117,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_leho.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_leho.glade 2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_leho.glade 2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -148,7 +148,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -156,7 +156,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_mx.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_mx.glade   2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_mx.glade   2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -153,7 +153,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -161,7 +161,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_ns.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_ns.glade   2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_ns.glade   2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -148,7 +148,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -156,7 +156,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_pkey.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_pkey.glade 2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_pkey.glade 2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -148,7 +148,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -156,7 +156,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_ptr.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_ptr.glade  2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_ptr.glade  2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -148,7 +148,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -156,7 +156,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_soa.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_soa.glade  2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_soa.glade  2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -177,7 +177,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -185,7 +185,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_srv.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_srv.glade  2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_srv.glade  2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -163,7 +163,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -171,7 +171,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_txt.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_txt.glade  2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_txt.glade  2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -148,7 +148,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -156,7 +156,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gns_edit_vpn.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gns_edit_vpn.glade  2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gns_edit_vpn.glade  2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -148,7 +148,7 @@
                     <child>
                       <object class="GtkEntry" id="edit_dialog_name_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="sensitive">False</property>
                         <property name="tooltip_text" translatable="yes">Name 
of the record in the zone.</property>
                         <property name="max_length">63</property>
                         <property name="invisible_char">●</property>
@@ -156,7 +156,6 @@
                         <property 
name="secondary_icon_activatable">False</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property 
name="secondary_icon_sensitive">True</property>
-                        <signal name="changed" 
handler="GNS_edit_dialog_name_entry_changed_cb" swapped="no"/>
                       </object>
                       <packing>
                         <property name="expand">True</property>

Modified: gnunet-gtk/contrib/gnunet_setup_gtk_main_window.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gtk_main_window.glade       2013-07-09 
21:41:19 UTC (rev 27847)
+++ gnunet-gtk/contrib/gnunet_setup_gtk_main_window.glade       2013-07-09 
22:36:54 UTC (rev 27848)
@@ -4500,7 +4500,7 @@
                               <attributes>
                                 <attribute name="visible">9</attribute>
                                 <attribute name="background">13</attribute>
-                                <attribute name="editable">9</attribute>
+                                <attribute name="editable">16</attribute>
                                 <attribute name="text">0</attribute>
                               </attributes>
                             </child>
@@ -4556,13 +4556,12 @@
                             <property name="sort_column_id">4</property>
                             <child>
                               <object class="GtkCellRendererText" 
id="GNUNET_setup_gns_expiration_cellrenderertext">
-                                <signal name="edited" 
handler="GNUNET_setup_gns_expiration_cellrenderertext_edited_cb" swapped="no"/>
+                               <property name="editable">False</property>
                               </object>
                               <attributes>
                                 <attribute name="sensitive">11</attribute>
                                 <attribute name="visible">10</attribute>
                                 <attribute name="background">12</attribute>
-                                <attribute name="editable">11</attribute>
                                 <attribute name="text">6</attribute>
                               </attributes>
                             </child>
@@ -4576,9 +4575,9 @@
                             <property name="clickable">True</property>
                             <child>
                               <object class="GtkCellRendererToggle" 
id="GNUNET_setup_gns_ispublic_cellrenderertoggle">
-                                <signal name="toggled" 
handler="GNUNET_setup_gns_ispublic_cellrenderertoggle_toggled_cb" swapped="no"/>
+                               <property name="sensitive">False</property>
                               </object>
-                              <attributes>
+                             <attributes>
                                 <attribute name="sensitive">11</attribute>
                                 <attribute name="visible">11</attribute>
                                 <attribute name="active">1</attribute>
@@ -4740,6 +4739,8 @@
       <column type="gboolean"/>
       <!-- column-name is_shadow -->
       <column type="gboolean"/>
+      <!-- column-name name_is_editable -->
+      <column type="gboolean"/>
     </columns>
   </object>
   <object class="GtkListStore" id="GNUNET_setup_gns_type_liststore">

Modified: gnunet-gtk/src/setup/gnunet-setup-gns-edit.c
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-gns-edit.c        2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/src/setup/gnunet-setup-gns-edit.c        2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -100,24 +100,6 @@
 
 
 /**
- * The user has edited the A record value.  Enable/disable 'save'
- * button depending on the validity of the value.
- *
- * @param entry editing widget
- * @param preedit new value
- * @param user_data the 'struct EditDialogContext' of the dialog
- */
-void
-GNS_edit_dialog_name_entry_changed_cb (GtkEditable *entry,
-                                      gpointer user_data)
-{
-  struct EditDialogContext *edc = user_data;
-
-  edc->validator (edc);
-}
-
-
-/**
  * The 'relative' expiration time radiobutton was toggled (on or off).
  *
  * @param button the button
@@ -210,7 +192,7 @@
   }
   gtk_entry_set_text (GTK_ENTRY (gtk_builder_get_object (edc->builder,
                                                         
"edit_dialog_name_entry")),
-                     edc->n_new_name);
+                     edc->name);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object 
(edc->builder,
                                                                           
"edit_dialog_options_public_checkbutton")),
                                edc->n_public);
@@ -327,7 +309,6 @@
 static void
 edit_dialog_putes_common_elements (struct EditDialogContext *edc)
 {
-  GtkEntry *entry;
   const char *rt_s;
   struct GNUNET_TIME_Relative rt;
   GtkComboBox *cb;
@@ -335,12 +316,6 @@
   GtkTreeIter iter; 
   gchar *opt;
 
-  /* record name */
-  entry = GTK_ENTRY (gtk_builder_get_object (edc->builder,
-                                            "edit_dialog_name_entry"));
-  g_free (edc->n_new_name);
-  edc->n_new_name = g_strdup (gtk_entry_get_text (entry));
-
   /* is public flag */
   edc->n_public = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON 
(gtk_builder_get_object (edc->builder,
                                                                                
           "edit_dialog_options_public_checkbutton")));

Modified: gnunet-gtk/src/setup/gnunet-setup-gns-edit.h
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-gns-edit.h        2013-07-09 21:41:19 UTC 
(rev 27847)
+++ gnunet-gtk/src/setup/gnunet-setup-gns-edit.h        2013-07-09 22:36:54 UTC 
(rev 27848)
@@ -64,26 +64,11 @@
 {
 
   /**
-   * If a record move operation is desired, we keep these in a DLL.
-   */
-  struct EditDialogContext *next;
-
-  /**
-   * If a record move operation is desired, we keep these in a DLL.
-   */
-  struct EditDialogContext *prev;
-
-  /**
    * Where in the tree view are we editing?
    */
-  GtkTreeIter it;
+  struct RecordInfo *ri;
 
   /**
-   * Expiration time value (absolute or relative).
-   */
-  guint64 n_exp_time;
-
-  /**
    * Function to call at the end.
    */
   GNS_EditContinuation cont;
@@ -105,38 +90,31 @@
   GtkDialog *dialog;
 
   /**
-   * Context for loading/generating the zone key for the target zone
-   * (used if the edit operation causes the record to be moved).
+   * Name of the record.
    */
-  struct GNUNET_CRYPTO_RsaKeyGenerationContext *rkgc;
+  gchar *name;
 
   /**
-   * Associated namestore operation.
-   * (used if the edit operation causes the record to be moved).
+   * Value of the record in string format.
    */
-  struct GNUNET_NAMESTORE_QueueEntry *qe;
+  gchar *n_value;
 
   /**
-   * Old name of the record (for deletion).
+   * Zone into which the record should be placed.
    */
-  gchar *n_name;
+  gchar *new_zone_option;
 
   /**
-   * New name.
+   * Expiration time value (absolute or relative).
    */
-  gchar *n_new_name;
+  guint64 n_exp_time;
 
   /**
-   * Value of the record in string format.
+   * Offset of the record we are editing in the 'rd' list of 'ri'.
    */
-  gchar *n_value;
+  unsigned int off;
 
   /**
-   * Zone into which the record should be placed.
-   */
-  gchar *new_zone_option;
-
-  /**
    * Flag indicating if the old record was in the namestore.
    */
   int old_record_in_namestore;

Modified: gnunet-gtk/src/setup/gnunet-setup-gns.c
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-gns.c     2013-07-09 21:41:19 UTC (rev 
27847)
+++ gnunet-gtk/src/setup/gnunet-setup-gns.c     2013-07-09 22:36:54 UTC (rev 
27848)
@@ -148,7 +148,12 @@
   /**
    * A gboolean; TRUE if the value is a shadow record.
    */
-  GNS_TREESTORE_COL_IS_SHADOW
+  GNS_TREESTORE_COL_IS_SHADOW,
+
+  /**
+   * A gboolean; TRUE if the name is editable (dummy line).
+   */
+  GNS_TREESTORE_COL_NAME_IS_EDITABLE
 };
 
 
@@ -171,151 +176,89 @@
 };
 
 
-
 /**
- * Context we use for making changes to the namestore.
- * (closure for 'add_new_records_after_removing_old_records').
+ * Closure for 'check_name_validity_and_remove_proc'.
  */
-struct UpdateContext
+struct OperationContext
 {
 
   /**
    * Kept in a DLL.
    */
-  struct UpdateContext *next;
+  struct OperationContext *next;
 
   /**
    * Kept in a DLL.
    */
-  struct UpdateContext *prev;
+  struct OperationContext *prev;
 
   /**
-   * Array of records to add.
-   */
-  struct GNUNET_NAMESTORE_RecordData *rd;
-
-  /**
-   * Name under which we should add the records.
-   */
-  char *name;
-
-  /**
    * Associated namestore operation.
    */
   struct GNUNET_NAMESTORE_QueueEntry *qe;
 
-  /**
-   * Size of the 'rd' array.
-   */
-  unsigned int rd_count;
-
-  /**
-   * Current position for record creation.
-   */
-  unsigned int rd_pos;
 };
 
 
 /**
- * Closure for 'check_name_validity_and_remove_proc'.
+ * Information we keep per name.
  */
-struct RemoveContext
+struct RecordInfo
 {
-
+  
   /**
-   * Kept in a DLL.
+   * Name for this record.
    */
-  struct RemoveContext *next;
+  char *name;
 
   /**
-   * Kept in a DLL.
+   * Location of this record in the tree view.
    */
-  struct RemoveContext *prev;
+  GtkTreeRowReference *rr;
 
   /**
-   * Associated namestore operation.
+   * Serialized records under this name.
    */
-  struct GNUNET_NAMESTORE_QueueEntry *qe;
+  void *data;
 
   /**
-   * Path for 'gtk_tree_model_get_iter_from_string' for removing
-   * the record from the tree view IF the operation was successful.
-   * FIXME: replace with a 'GtkTreeIter'?
-   */
-  char *path;
-};
+   * Number of bytes in 'data'.
+   */ 
+  size_t data_size;
 
-
-/**
- * Handle created for pseudonym-operations.
- */
-struct PseuContext
-{
-
   /**
-   * Kept in a DLL.
+   * Number of records serialized in 'data'.
    */
-  struct PseuContext *next;
+  unsigned int rd_count;
 
-  /**
-   * Kept in a DLL.
-   */
-  struct PseuContext *prev;
-
-  /**
-   * Associated namestore operation.
-   */
-  struct GNUNET_NAMESTORE_QueueEntry *qe;
-
 };
 
 
-/**
- * Our current zone monitor.
- */
-static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
 
-/**
- * Head of linked list of active update operations.
- */
-static struct UpdateContext *uc_head;
 
-/**
- * Tail of linked list of active update operations.
- */
-static struct UpdateContext *uc_tail;
 
 /**
- * Head of linked list of active remove operations.
+ * Hash map from the H(name) in the zone to the 'struct RecordInfo'
+ * for the respective entry in the tree view.
  */
-static struct RemoveContext *rc_head;
+static struct GNUNET_CONTAINER_MultiHashMap *n2r;
 
 /**
- * Tail of linked list of active remove operations.
+ * Our current zone monitor.
  */
-static struct RemoveContext *rc_tail;
+static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
 
 /**
- * Head of linked list of active pseudonym operations.
+ * Head of linked list of active operations.
  */
-static struct PseuContext *pc_head;
+static struct OperationContext *oc_head;
 
 /**
- * Tail of linked list of active pseudonym operations.
+ * Tail of linked list of active operations.
  */
-static struct PseuContext *pc_tail;
+static struct OperationContext *oc_tail;
 
 /**
- * Tail of linked list of active record move operations.
- */
-static struct EditDialogContext *edc_head;
-
-/**
- * Tail of linked list of active record move operations.
- */
-static struct EditDialogContext *edc_tail;
-
-/**
  * Name of our zone as a string.
  */
 static char *zone_as_string;
@@ -343,12 +286,12 @@
 /**
  * Private key of the zone we are currently editing.
  */ 
-static struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
+static struct GNUNET_CRYPTO_EccPrivateKey *pkey;
 
 /**
  * Public key of the zone we are currently editing.
  */ 
-static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
+static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pubkey;
 
 /**
  * Short hash of the public key of the zone we are currently editing.
@@ -367,7 +310,6 @@
 static const char *current_zone_option;
 
 
-
 #if HAVE_QRENCODE_H
 #include <qrencode.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
@@ -571,6 +513,45 @@
 
 
 /**
+ * Function called upon completion of an operation.
+ *
+ * @param cls the 'struct OperationContext' of the operation that completed
+ * @param success GNUNET_OK if the operation succeeded
+ * @param emsg error message if the operation failed
+ */
+static void 
+operation_done_cont (void *cls,
+                    int32_t success,
+                    const char *emsg)
+{
+  struct OperationContext *oc = cls;
+  GtkWidget *dialog;
+  GtkWindow *main_window;
+  
+  oc->qe = NULL;
+  GNUNET_CONTAINER_DLL_remove (oc_head,
+                              oc_tail,
+                              oc);
+  if (GNUNET_SYSERR == success)
+  {
+    main_window = GTK_WINDOW (GNUNET_SETUP_get_object ("GNUNET_setup_dialog"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Operation failed: `%s'\n"), emsg);
+    dialog = gtk_message_dialog_new (main_window,
+                                    GTK_DIALOG_DESTROY_WITH_PARENT,
+                                    GTK_MESSAGE_ERROR,
+                                    GTK_BUTTONS_CLOSE,
+                                    _("Operation failed: `%s'\n"),
+                                    emsg);
+    g_signal_connect_swapped (dialog, "response",
+                              G_CALLBACK (gtk_widget_destroy),
+                              dialog);
+    gtk_widget_show_all (dialog);
+  }
+  GNUNET_free (oc);
+}
+
+
+/**
  * Clear all entries in the zone view and hide the tree view.
  */
 static void
@@ -600,20 +581,6 @@
 
 
 /**
- * Our model is somehow are inconsistent with the namestore database.
- * Clear our model and resync by loading all of it from the namestore.
- * (Naturally, this should never happen in normal operation; however,
- * if multiple users edit the same namestore, it might happen without
- * there being a bug ...).
- */
-static void
-resync_db ()
-{
-  load_zone (current_zone_option);
-}
-
-
-/**
  * Display an error message for the user.
  *
  * @param title title of the error message
@@ -641,379 +608,98 @@
 
 
 /**
- * Release resources of this update context.
- *
- * @param uc context to free
+ * Remove selected record from the namestore.
+ * 
+ * @param edc identifying record to remove
  */
-static void 
-free_update_context (struct UpdateContext *uc)
-{
-  unsigned int c;
-
-  if (NULL != uc->qe)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Setup shutdown before all records could be written. Record 
lost!\n"));
-    GNUNET_NAMESTORE_cancel (uc->qe);
-    uc->qe = NULL;
-  }
-  GNUNET_CONTAINER_DLL_remove (uc_head, uc_tail, uc);
-  for (c = 0; c < uc->rd_count; c++)
-    GNUNET_free ((void *) uc->rd[c].data);
-  GNUNET_free (uc->rd);
-  GNUNET_free (uc->name);
-  GNUNET_free (uc);
-}
-
-
-/**
- * Function called to transmit the next record from this update context
- * to the database.
- *
- * @param uc update context
- */
 static void
-create_next_record (struct UpdateContext *uc);
-
-
-/**
- * Function called after we created a new record.  If the creation was
- * successful, add more records from the update context.
- *
- * @param cls the 'struct UpdateContext'
- * @param success GNUNET_SYSERR on failure (including timeout/queue 
drop/failure to validate)
- *                GNUNET_NO if content was already there or not found
- *                GNUNET_YES (or other positive value) on success
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-create_more_records (void *cls,
-                    int32_t success,
-                    const char *emsg)
+remove_record_at_offset (struct EditDialogContext *edc)
 {
-  struct UpdateContext *uc = cls;
-
-  uc->qe = NULL;
-  switch (success)
+  struct RecordInfo *ri = edc->ri;
+  struct OperationContext *oc;
+  
+  if ( (NULL == ri) ||
+       (edc->off >= ri->rd_count) )
   {
-  case GNUNET_OK:
-    uc->rd_pos++;
-    create_next_record (uc);
-    return;
-  case GNUNET_NO:  
-  case GNUNET_SYSERR:
-    show_error_message (_("Failed to create record"),
-                       emsg);
-    resync_db ();
-    break;
-  default:
     GNUNET_break (0);
-    break;
-  }
-  free_update_context (uc);
-}
-
-
-
-/**
- * Function called to transmit the next record from this update context
- * to the database.
- *
- * @param uc update context
- */
-static void
-create_next_record (struct UpdateContext *uc)
-{
-  if (uc->rd_pos == uc->rd_count)
-  {
-    free_update_context (uc);
     return;
   }
-#if 0
-  /* FIXME: what were we doing here again? */
-  uc->qe = GNUNET_NAMESTORE_record_create (namestore, pkey,
-                                          uc->name, &uc->rd[uc->rd_pos], 
-                                          &create_more_records, uc);
-#endif
-}
-
-
-/**
- * Function called after we removed the old record.  If the
- * removal was successful, add the new records from the
- * update context.
- *
- * @param cls the 'struct UpdateContext'
- * @param success GNUNET_SYSERR on failure (including timeout/queue 
drop/failure to validate)
- *                GNUNET_NO if content was already there or not found
- *                GNUNET_YES (or other positive value) on success
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-add_new_records_after_removing_old_records (void *cls,
-                                            int32_t success,
-                                            const char *emsg)
-{
-  struct UpdateContext *uc = cls;
-
-  uc->qe = NULL;
-  switch (success)
+  
   {
-  case GNUNET_OK:
-  case GNUNET_NO:  
-    create_next_record (uc);
-    return;
-  case GNUNET_SYSERR:
-    show_error_message (_("Failed to remove record"),
-                       emsg);
-    resync_db ();
-    break;
-  default:
-    GNUNET_break (0);
-    resync_db ();
-    break;
-  }
-  free_update_context (uc);
-}
+    struct GNUNET_NAMESTORE_RecordData rd_old[ri->rd_count];
+    struct GNUNET_NAMESTORE_RecordData rd_new[ri->rd_count - 1];
 
-
-/**
- * Check that the data at the given 'path' (see 
gtk_tree_model_get_iter_from_string)
- * is valid, and if so commit it after removing the old data.
- *
- * @param it iter identifying the new record 
- * @param oldname name of the old record, NULL if this is a fresh name
- */
-static void
-check_name_validity_and_commit (GtkTreeIter *it, 
-                               const char *oldname)
-{
-  GtkTreeIter parent; /* parent record with the 'name' */
-  char *name; /* name of the records */
-  struct GNUNET_NAMESTORE_RecordData *rd;
-  unsigned int records; /* number of records in 'rd' */
-  int children; /* number of records below 'parent' */
-  int append_pseu; /* do we need to create a '+' PSEU record? */
-  struct UpdateContext * uc;
-  int c;
-
-  if (! gtk_tree_model_iter_parent (tm, &parent, it))
-  {
-    if (NULL != oldname)
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Name of existing record `%s' was changed, moving associated 
records\n",
-                 oldname); 
-    parent = *it;
-  }
-  gtk_tree_model_get (tm, &parent,
-                     GNS_TREESTORE_COL_NAME, &name,
-                     -1);
-  children = gtk_tree_model_iter_n_children (tm, &parent);
-  if (children < 1)
-  {
+    /* Removing a single record */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Changed name `%s' has no associated records, not committing to 
namestore\n",
-               name);
-    g_free (name);
-    return;
+               "Removing single record for name `%s'\n", 
+               edc->name);
+    GNUNET_break (GNUNET_OK ==
+                 GNUNET_NAMESTORE_records_deserialize (ri->data_size,
+                                                       ri->data,
+                                                       ri->rd_count,
+                                                       rd_old));
+    GNUNET_assert (edc->off < ri->rd_count);
+    memcpy (rd_new, rd_old, (ri->rd_count - 1) * sizeof (struct 
GNUNET_NAMESTORE_RecordData));
+    rd_new[edc->off] = rd_old[ri->rd_count - 1];
+    oc = GNUNET_new (struct OperationContext);
+    GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc);
+    oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, 
+                                                      pkey, edc->name,
+                                                      ri->rd_count - 1,
+                                                      rd_new,
+                                                      &operation_done_cont, 
oc);
   }
-  if ( (0 == strcmp (name, GNUNET_GNS_MASTERZONE_STR)) &&
-       (0 == strcmp (current_zone_option, "ZONEKEY")) )
-  {
-    /* We have to append PSEU RECORD, this is the 'master' zone */
-    append_pseu = GNUNET_YES;
-    records = children + 1;
-  }
-  else
-  {
-    append_pseu = GNUNET_NO;
-    records = children;
-  }
-
-  rd = GNUNET_malloc (records * sizeof (struct GNUNET_NAMESTORE_RecordData)); 
-  GNUNET_assert (gtk_tree_model_iter_children (tm, it, &parent));
-
-  for (c = 0; c < children; c++)
-  {
-    gchar *n_name;
-    gint n_type;
-    gboolean n_public;
-    gboolean n_is_shadow;
-    guint64 n_exp_time;
-    gboolean n_is_relative;
-    gchar *n_value;
-    void * data;
-    size_t data_size;
-
-    gtk_tree_model_get (tm, it,
-                       GNS_TREESTORE_COL_NAME, &n_name,
-                       GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
-                       GNS_TREESTORE_COL_IS_PUBLIC, &n_public,
-                       GNS_TREESTORE_COL_EXP_TIME, &n_exp_time,
-                       GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative,
-                       GNS_TREESTORE_COL_IS_SHADOW, &n_is_shadow,
-                       GNS_TREESTORE_COL_VAL_AS_STR, &n_value,
-                       -1);
-    if ( (NULL == n_name) ||
-        ( (GNUNET_SYSERR == GNUNET_DNSPARSER_check_label (n_name)) &&
-          (0 != strcmp (n_name, GNUNET_GNS_MASTERZONE_STR)) ) ||
-        (0 == n_type) ||
-        (0 == n_exp_time) ||
-        (NULL == n_value) ||
-        (GNUNET_OK != GNUNET_NAMESTORE_string_to_value (n_type, n_value, 
&data, &data_size)) )
-    {
-      GNUNET_break (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Invalid record, skipping\n");
-      records--;
-      children--;
-      c--;
-    }
-    else
-    {
-      if (n_public)
-        rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY;
-      else
-        rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | 
GNUNET_NAMESTORE_RF_PRIVATE;
-      if (n_is_shadow)
-       rd[c].flags |= GNUNET_NAMESTORE_RF_SHADOW_RECORD;
-      rd[c].record_type = n_type;
-      rd[c].expiration_time = n_exp_time;
-      if (n_is_relative)
-        rd[c].flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
-      rd[c].data_size = data_size;
-      rd[c].data = GNUNET_malloc(data_size);
-      memcpy ((void *) rd[c].data, data, data_size);
-    }
-    g_free (n_name);
-    g_free (n_value);
-    GNUNET_assert (gtk_tree_model_iter_next (tm, it) ^ (c + 1 == children));
-  }
-
-  if (GNUNET_YES == append_pseu)
-  {
-    GtkEntry *entry;
-    const gchar *pseu;
-
-    /* Append PSEU record */
-    GNUNET_assert (children == (records -1));
-    entry = GTK_ENTRY (GNUNET_SETUP_get_object 
("GNUNET_setup_gns_pseu_entry"));
-    pseu = gtk_entry_get_text (GTK_ENTRY(entry));    
-    if ( (NULL == pseu) ||
-        (0 == strcmp ("", pseu)) )
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "No zone pseudonym given, not creating PSEU record\n");
-      records--;
-    }
-    else
-    {
-      if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value 
(GNUNET_NAMESTORE_TYPE_PSEU,
-                                                        pseu,
-                                                        (void **) &rd[records 
- 1].data,
-                                                        &rd[records - 
1].data_size))
-      {
-       show_error_message (_("Invalid pseudonym specified for zone"),
-                           pseu);
-       records--;
-      }
-      else
-      {
-        rd[records - 1].record_type = GNUNET_NAMESTORE_TYPE_PSEU;
-        rd[records - 1].expiration_time = UINT64_MAX;
-        rd[records - 1].flags = GNUNET_NAMESTORE_RF_AUTHORITY | 
GNUNET_NAMESTORE_RF_NONE;
-      }
-    }
-  }
-  if (0 == records)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "No valid records remaining, not storing to namestore\n");
-    GNUNET_free (rd);
-    return;
-  }
-
-  /* FIXME: modify entries! */
-#if 0
-  uc = GNUNET_malloc (sizeof (struct UpdateContext));
-  uc->rd = rd;
-  uc->rd_count = records;
-  uc->name = name;
-  GNUNET_CONTAINER_DLL_insert (uc_head, uc_tail, uc);  
-  uc->qe = GNUNET_NAMESTORE_record_remove (namestore, 
-                                          pkey,
-                                          (NULL != oldname) ? oldname : name, 
-                                          NULL, 
-                                          
&add_new_records_after_removing_old_records, uc);
-  if (NULL == uc->qe)
-  {   
-    show_error_message (_("Failed to commit record to database"),
-                       _("Internal error"));
-    resync_db ();
-    free_update_context (uc);
-    return;
-  }
-#endif
 }
 
 
-/**
- * Release resources of the given remove context.
- *
- * @param rc remove context to release
- */
-static void
-free_remove_context (struct RemoveContext *rc)
-{
-  if (NULL != rc->qe)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Setup shutdown before all records could be written. Record 
lost!\n"));
-    GNUNET_NAMESTORE_cancel (rc->qe);
-    rc->qe = NULL;
-  }
-  GNUNET_CONTAINER_DLL_remove (rc_head,
-                              rc_tail,
-                              rc);
-  GNUNET_free (rc->path);
-  GNUNET_free (rc);
-}
 
-
 /**
- * Remove a record from the model (and if it is valid, also from
- * the namestore).   If the given path identifies an entire 'name',
- * remove all records under that name.
+ * Remove a record from the model.  If the given iter identifies an
+ * entire 'name', remove all records under that name.
  * 
- * @param path identifying record(s) to remove; FIXME: consider doing this 
with an 'iter' instead
+ * @param iter identifying record(s) to remove
  */
 static void
-remove_records_by_path (const gchar *path)
+remove_records_by_iter (GtkTreeIter *iter)
 {
-  GtkTreeIter it;
   GtkTreeIter parent;
   char *name;
-  struct GNUNET_NAMESTORE_RecordData rd;
-  struct RemoveContext *rc;
-  char *n_name;
-  int n_type;
-  gboolean n_public;
-  guint64 n_exp_time;
-  gboolean n_is_relative;
-  gboolean n_is_shadow;
-  char *n_value;
-
-  gtk_tree_model_get_iter_from_string (tm, &it, path);
-  gtk_tree_model_get (tm, &it,
+  struct GNUNET_HashCode name_hash;
+  struct RecordInfo *ri;
+  struct OperationContext *oc;
+  
+  gtk_tree_model_get (tm, iter,
                      GNS_TREESTORE_COL_NAME, &name,
                      -1);
-  if (gtk_tree_model_iter_parent (tm, &parent, &it))
+  GNUNET_CRYPTO_hash (name, strlen (name), &name_hash);
+  ri = GNUNET_CONTAINER_multihashmap_get (n2r,
+                                         &name_hash);
+  GNUNET_assert (NULL != ri);
+  
+  if ( (gtk_tree_model_iter_parent (tm, &parent, iter)) &&
+       (ri->rd_count > 0) )
   {
+    struct GNUNET_NAMESTORE_RecordData rd_old[ri->rd_count];
+    struct GNUNET_NAMESTORE_RecordData rd_new[ri->rd_count - 1];
+    struct GNUNET_NAMESTORE_RecordData rd;
+    unsigned int off;
+    int n_type;
+    gboolean n_public;
+    guint64 n_exp_time;
+    gboolean n_is_relative;
+    gboolean n_is_shadow;
+    char *n_value;
+
     /* Removing a single record */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Removing single record for name `%s'\n", name);
-    gtk_tree_model_get (tm, &it,
-                       GNS_TREESTORE_COL_NAME, &n_name,
+               "Removing single record for name `%s'\n", 
+               name);
+    GNUNET_break (GNUNET_OK ==
+                 GNUNET_NAMESTORE_records_deserialize (ri->data_size,
+                                                       ri->data,
+                                                       ri->rd_count,
+                                                       rd_old));
+    gtk_tree_model_get (tm, iter,
                        GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
                        GNS_TREESTORE_COL_IS_PUBLIC, &n_public,
                        GNS_TREESTORE_COL_EXP_TIME, &n_exp_time,
@@ -1021,7 +707,6 @@
                        GNS_TREESTORE_COL_IS_SHADOW, &n_is_shadow,
                        GNS_TREESTORE_COL_VAL_AS_STR, &n_value,
                        -1);
-    
     /* valid name */
     if (n_public)
       rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
@@ -1038,53 +723,42 @@
                                          (void**)&rd.data, &rd.data_size))
     {
       /* can't remove, value invalid */
-      g_free (n_name);
+      GNUNET_assert (0);
       g_free (n_value);
+      g_free (name);
       return;
     }
-
-    /* FIXME: actually apply changes! */
-    GNUNET_free ((void *) rd.data);
-    g_free (n_name);
+    for (off=0;off<ri->rd_count;off++)
+      if (GNUNET_YES ==
+         GNUNET_NAMESTORE_records_cmp (&rd,
+                                       &rd_old[off]))
+       break;
+    GNUNET_assert (off != ri->rd_count);
+    memcpy (rd_new, rd_old, (ri->rd_count - 1) * sizeof (struct 
GNUNET_NAMESTORE_RecordData));
+    rd_new[off] = rd_old[ri->rd_count - 1];
+    oc = GNUNET_new (struct OperationContext);
+    GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc);
+    oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, 
+                                                      pkey, name,
+                                                      ri->rd_count - 1,
+                                                      rd_new,
+                                                      &operation_done_cont, 
oc);
     g_free (n_value);
   }
-  else if (0 != strcmp (name, GNUNET_GNS_MASTERZONE_STR))
+  else
   {
-    /* FIXME: actually apply changes! */
+    oc = GNUNET_new (struct OperationContext);
+    GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc);
+    oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, 
+                                                      pkey, name,
+                                                      0, NULL,
+                                                      &operation_done_cont, 
oc);
   }
   g_free (name);
 }
 
 
 /**
- * Convert an expiration time to a string for display.
- *
- * @param is_relative is the given time relative?
- * @param exp_val expiration value
- * @return string representing the value
- */
-static char *
-exp_time_to_string (gboolean is_relative,
-                   uint64_t exp_val)
-{
-  if (is_relative)
-  {
-    struct GNUNET_TIME_Relative rel_time;
-    
-    rel_time.rel_value = exp_val;
-    return GNUNET_strdup (GNUNET_STRINGS_relative_time_to_string (rel_time, 
GNUNET_NO));
-  }
-  else
-  {
-    struct GNUNET_TIME_Absolute exp_abs;
-
-    exp_abs.abs_value = exp_val;
-    return GNUNET_strdup (GNUNET_STRINGS_absolute_time_to_string (exp_abs));
-  }
-}
-
-
-/**
  * Release resources of an edit dialog context.
  *
  * @param edc resources to free
@@ -1092,8 +766,7 @@
 static void
 free_edit_dialog_context (struct EditDialogContext *edc)
 {
-  g_free (edc->n_name);
-  g_free (edc->n_new_name);
+  g_free (edc->name);
   g_free (edc->n_value);
   g_free (edc->new_zone_option);
   GNUNET_free (edc);  
@@ -1101,97 +774,6 @@
 
 
 /**
- * Function called upon completion of a 'move' operation.
- *
- * @param cls the 'struct EditDialogContext' of the operation that completed
- * @param success GNUNET_OK if the operation succeeded
- * @param emsg error message if the operation failed
- */
-static void 
-record_move_finish (void *cls,
-                   int32_t success,
-                   const char *emsg)
-{
-  struct EditDialogContext *edc = cls;
-  
-  edc->qe = NULL;
-  GNUNET_CONTAINER_DLL_remove (edc_head,
-                              edc_tail,
-                              edc);
-  if (NULL != emsg)
-    show_error_message (_("Failed to move record to target zone"),
-                       emsg);
-  free_edit_dialog_context (edc);
-}
-
-
-/**
- * Function called upon completion of 'GNUNET_CRYPTO_rsa_key_create_async'.
- * Displays an error message upon failure, otherwise stores the moved record
- * in the target zone.
- *
- * @param cls closure with the struct EditDialogContext;
- * @param pk NULL on error, otherwise the private key (which must be free'd by 
the callee)
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-record_move_continuation (void *cls,
-                         struct GNUNET_CRYPTO_RsaPrivateKey *pk,
-                         const char *emsg)
-{
-  struct EditDialogContext *edc = cls;
-  struct GNUNET_NAMESTORE_RecordData rd;
-  void *data;
-  size_t data_size;
-
-  edc->rkgc = NULL;
-  if (NULL != emsg)
-  {
-    show_error_message (_("Failed to access key for target zone"),
-                       emsg);
-    GNUNET_CONTAINER_DLL_remove (edc_head,
-                                edc_tail,
-                                edc);
-    free_edit_dialog_context (edc);
-    return;
-  }
-  if (GNUNET_OK !=
-      GNUNET_NAMESTORE_string_to_value (edc->record_type,
-                                       edc->n_value,
-                                       &data,
-                                       &data_size))
-  {
-    /* edit dialog produced invalid value string!? */
-    GNUNET_break (0);
-    GNUNET_CONTAINER_DLL_remove (edc_head,
-                                edc_tail,
-                                edc);    
-    free_edit_dialog_context (edc);
-    return;
-  }
-  rd.record_type = edc->record_type;
-  rd.expiration_time = UINT64_MAX;
-  if (edc->n_public)
-    rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
-  else
-    rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE;
-  if (edc->n_is_relative)
-    rd.flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
-  if (edc->n_is_shadow)
-    rd.flags |= GNUNET_NAMESTORE_RF_SHADOW_RECORD;
-  rd.data_size = data_size;
-  rd.data = data;
-#if 0
-  /* FIXME: actually apply changes! */
-  edc->qe = GNUNET_NAMESTORE_record_create (namestore, pk, 
-                                           edc->n_new_name,
-                                           &rd,
-                                           &record_move_finish, edc);
-#endif
-}
-
-
-/**
  * The edit dialog completed; update the namestore and the 
  * view based on the new values in 'edc'.
  *
@@ -1202,88 +784,51 @@
 edit_dialog_continuation (struct EditDialogContext *edc,
                          GtkResponseType ret)
 {
-  char *path;
-  char *estr;
-
   switch (ret)
   {
   case GTK_RESPONSE_REJECT: /* code for 'delete' */
     if (GNUNET_YES == edc->old_record_in_namestore)
     {
       /* remove item from tree view and namestore */
-      path = gtk_tree_model_get_string_from_iter (tm, &edc->it);
-      remove_records_by_path (path);
-      g_free (path);  
+      remove_record_at_offset (edc);
     }
     else
     {
       /* invalid choice, 'delete' should have been hidden... */
       GNUNET_break (0);
-      gtk_tree_store_remove (ts, &edc->it);
     }
     break;
   case GTK_RESPONSE_CANCEL:
   case GTK_RESPONSE_DELETE_EVENT: /* window deletion counts as 'cancel' */
-    if (GNUNET_NO == edc->old_record_in_namestore)
-    {
-      /* re-enable type selection */
-      gtk_tree_store_set (ts, &edc->it,
-                         GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
-                         GNS_TREESTORE_COL_VAL_COLOR, "red",
-                         -1);
-    }
-    else
-    {
-      /* do nothing */    
-    }
+    /* do nothing */
     break;
   case GTK_RESPONSE_OK:
     /* update model */
     if (0 == strcmp (edc->new_zone_option,
                     current_zone_option))
     {
-      /* zone stayed the same, update record in current model/zone */
-      estr = exp_time_to_string (edc->n_is_relative,
-                                edc->n_exp_time);
-      gtk_tree_store_set (ts, &edc->it,
-                         GNS_TREESTORE_COL_NAME, edc->n_name,
-                         GNS_TREESTORE_COL_IS_PUBLIC, edc->n_public,
-                         GNS_TREESTORE_COL_EXP_TIME, edc->n_exp_time,
-                         GNS_TREESTORE_COL_EXP_TIME_IS_REL, edc->n_is_relative,
-                         GNS_TREESTORE_COL_EXP_TIME_AS_STR, estr,
-                         GNS_TREESTORE_COL_IS_SHADOW, edc->n_is_shadow,
-                         GNS_TREESTORE_COL_VAL_AS_STR, edc->n_value,
-                         GNS_TREESTORE_COL_VAL_COLOR, NULL,
-                         -1);    
-      GNUNET_free (estr);
       if (GNUNET_YES == edc->old_record_in_namestore)
       {
        /* replace record in database with that from model */
-       check_name_validity_and_commit (&edc->it, edc->n_name);
+       GNUNET_break (0); // not implemented
       }
       else
       {
        /* add record in database based on model */
-       check_name_validity_and_commit (&edc->it, NULL);
+       GNUNET_break (0); // not implemented
       }
     }
     else
     {
       char *keyfile;
+      struct GNUNET_CRYPTO_EccPrivateKey *pk;
 
       /* zone changed, remove record from old zone, add to new zone! */
       if (GNUNET_YES == edc->old_record_in_namestore)
       {
        /* remove item from tree view and namestore */
-       path = gtk_tree_model_get_string_from_iter (tm, &edc->it);
-       remove_records_by_path (path);
-       g_free (path);  
+       remove_record_at_offset (edc);
       }
-      else
-      {
-       /* remove item just from tree view, as it was not in the model */
-       gtk_tree_store_remove (ts, &edc->it);
-      }
 
       /* now add item to target zone */
       if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
@@ -1300,19 +845,17 @@
                            emsg);
        GNUNET_free (emsg);
       }
-      edc->rkgc = GNUNET_CRYPTO_rsa_key_create_start (keyfile,
-                                                     &record_move_continuation,
-                                                     edc);
-      if (NULL == edc->rkgc)
+      pk = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
+      GNUNET_free (keyfile);
+      if (NULL == pk)
       {
-       GNUNET_break (0);
-       GNUNET_free (keyfile);
-       break;
+       show_error_message (_("Failed to load private key for target zone"),
+                           NULL);
+       return;
       }
-      GNUNET_CONTAINER_DLL_insert (edc_head,
-                                  edc_tail,
-                                  edc);    
-      GNUNET_free (keyfile);
+      GNUNET_break (0); // not implemented
+      /* FIXME: get target zone records, merge with new one, commit! */
+      GNUNET_CRYPTO_ecc_key_free (pk);
       return;
     }
     break;
@@ -1324,45 +867,51 @@
 }
 
 
+
 /**
- * Edit the record at the currently selected row.  If the old record
- * exists, allow the user to modify or delete it; if it does not
- * exist, make the record type editable again (by offering the user the
- * 'cancel' option; hide 'delete' in this case).
+ * Launch a record editing dialog.
  *
- * @param old_record_in_namestore GNUNET_YES if the old record exists in the 
namestore,
- *                                GNUNET_NO if this is a new record that 
doesn't exist yet
+ * @param n_type type of the record to edit
+ * @param name name of the record to edit
+ * @param ri record information for this name (can be NULL
+ *        if this is the first record for the name)
+ * @param off offset of the record being edited in the
+ *        ri's list; UINT_MAX if this is a new record
  */
 static void
-edit_selected_row (int old_record_in_namestore)
+launch_edit_dialog (gint n_type,
+                   const char *name,
+                   struct RecordInfo *ri,
+                   unsigned int off)
 {
-  GtkTreeSelection *sel;
-  gint n_type;
   struct EditDialogContext *edc;
 
-  sel = gtk_tree_view_get_selection (tv);
-  edc = GNUNET_malloc (sizeof (struct EditDialogContext));
-  if (! gtk_tree_selection_get_selected (sel, NULL, &edc->it))
+  edc = GNUNET_new (struct EditDialogContext);
+  if ( (NULL != ri) &&
+       (off < ri->rd_count) )
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "No row selected\n");
-    GNUNET_free (edc);
-    return;
+    struct GNUNET_NAMESTORE_RecordData rd_old[ri->rd_count];
+    
+    GNUNET_break (GNUNET_OK ==
+                 GNUNET_NAMESTORE_records_deserialize (ri->data_size,
+                                                       ri->data,
+                                                       ri->rd_count,
+                                                       rd_old));
+    edc->n_value = GNUNET_NAMESTORE_value_to_string (n_type,
+                                                    rd_old[off].data,
+                                                    rd_old[off].data_size);
+    edc->n_public = (0 == (rd_old[off].flags & GNUNET_NAMESTORE_RF_PRIVATE));
+    edc->n_is_relative = (0 != (rd_old[off].flags & 
GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
+    edc->n_is_shadow = (0 != (rd_old[off].flags & 
GNUNET_NAMESTORE_RF_SHADOW_RECORD));
+    edc->n_exp_time = rd_old[off].expiration_time;
+    edc->old_record_in_namestore = GNUNET_YES;
   }
-  gtk_tree_model_get (tm, &edc->it,
-                     GNS_TREESTORE_COL_NAME, &edc->n_name,
-                     GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
-                     GNS_TREESTORE_COL_IS_PUBLIC, &edc->n_public,
-                     GNS_TREESTORE_COL_EXP_TIME, &edc->n_exp_time,
-                     GNS_TREESTORE_COL_EXP_TIME_IS_REL, &edc->n_is_relative,
-                     GNS_TREESTORE_COL_IS_SHADOW, &edc->n_is_shadow,
-                     GNS_TREESTORE_COL_VAL_AS_STR, &edc->n_value,
-                     -1);
-  edc->old_record_in_namestore = old_record_in_namestore;
+  edc->ri = ri;
+  edc->off = off;
+  edc->name = GNUNET_strdup (name);
   edc->new_zone_option = g_strdup (current_zone_option);
-  edc->n_new_name = g_strdup (edc->n_name);
+  edc->record_type = n_type;
   edc->cont = &edit_dialog_continuation;
-  edc->record_type = n_type;
   switch (n_type)
   {
   case GNUNET_DNSPARSER_TYPE_A:
@@ -1404,13 +953,57 @@
   case GNUNET_DNSPARSER_TYPE_TLSA:
   default:
     GNUNET_break (0);
-    edc->cont (edc, GTK_RESPONSE_CANCEL);  /* treat as 'cancel' */
+    edit_dialog_continuation (edc,
+                             GTK_RESPONSE_CANCEL); 
     break;
   }
 }
 
 
 /**
+ * User selected 'edit' in the popup menu.  Edit the
+ * selected row.
+ *
+ * @param widget the GtkTreeView
+ * @param user_data main window builder 
+ */
+void
+GNUNET_setup_gns_popup_edit_button_activate_cb (GtkWidget *widget,
+                                               gpointer user_data)
+{
+  GtkTreeSelection *sel;
+  gint n_type;
+  gchar *n_name;
+  unsigned int off;
+  struct RecordInfo *ri;
+  GtkTreeIter iter;
+
+  /* FIXME: not this easy! Row may still be a 'fresh' row (user
+     can right-click anywhere, right? -- maybe suppress pop-up
+     in that case?? */
+  sel = gtk_tree_view_get_selection (tv);
+  if (! gtk_tree_selection_get_selected (sel, NULL, &iter))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "No row selected\n");
+    return;
+  }
+  gtk_tree_model_get (tm, &iter,
+                     GNS_TREESTORE_COL_NAME, &n_name,
+                     GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
+                     -1);
+  // FIXME: determine 'off', 'ri', ...
+  // Idea: simply store 'off' in model!
+  off = 42;
+  ri = NULL;
+  launch_edit_dialog (n_type, n_name,
+                     ri, off);
+  g_free (n_name);
+}
+
+
+
+/**
  * The user has selected a new record type.  Update the
  * model and then start the 'edit' dialog.
  *
@@ -1425,14 +1018,17 @@
                                                   gchar *new_text,
                                                   gpointer user_data)
 {
-  GtkTreeSelection *sel;
   GtkTreeIter it;
-  GtkTreeIter child;
   guint type;
   char *name_str;
+  struct GNUNET_HashCode name_hash;
+  struct RecordInfo *ri;
 
   if (0 == strcmp (new_text, _(NEW_RECORD_STR)))
+  {
+    GNUNET_break (0);
     return; /* no record type was selected */
+  }
   type = GNUNET_NAMESTORE_typename_to_number (new_text);
   if (UINT32_MAX == type)
   {
@@ -1448,102 +1044,15 @@
   gtk_tree_model_get (tm, &it,
                      GNS_TREESTORE_COL_NAME, &name_str,
                      -1);
-  gtk_tree_store_insert_with_values (ts, &child , &it, -1,
-                                    GNS_TREESTORE_COL_NAME, name_str,
-                                    GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE,
-                                    GNS_TREESTORE_COL_RECORD_TYPE, type,
-                                    GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, 
new_text,
-                                    GNS_TREESTORE_COL_EXP_TIME_AS_STR, 
EXPIRE_NEVER_STRING,
-                                    GNS_TREESTORE_COL_EXP_TIME, 
GNUNET_TIME_UNIT_FOREVER_ABS,
-                                    GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE,
-                                    GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
-                                    GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE,
-                                    GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE,
-                                    -1);
-  /* select new row and start editing 'value' */
-  gtk_tree_view_expand_row (tv, gtk_tree_model_get_path (tm, &it), 0);
-  sel = gtk_tree_view_get_selection (tv);
-  gtk_tree_selection_select_iter (sel, &child);
-  g_free (name_str);
-  edit_selected_row (GNUNET_NO);
-}
-
-
-/**
- * The user has toggled the 'public' checkmark of a cell.  Update the
- * model.
- *
- * @param renderer updated renderer
- * @param path the path identifying the edited cell
- * @param user_data unused
- */
-void
-GNUNET_setup_gns_ispublic_cellrenderertoggle_toggled_cb (GtkCellRendererToggle 
*cell_renderer,
-                                                        gchar *path,
-                                                        gpointer user_data)
-{
-  GtkTreeIter it;
-  gboolean value;
-
-  gtk_tree_model_get_iter_from_string (tm, &it, path);
-  gtk_tree_model_get (tm, &it, GNS_TREESTORE_COL_IS_PUBLIC, &value, -1);
-  gtk_tree_store_set (ts, &it, GNS_TREESTORE_COL_IS_PUBLIC, !value, -1);
-  check_name_validity_and_commit (&it, NULL);
-}
-
-
-/**
- * The user has edited a 'expiration' cell.  Update the model.
- *
- * @param renderer updated renderer
- * @param path the path identifying the edited cell
- * @param new_text the new expiration time
- * @param user_data unused
- */
-void
-GNUNET_setup_gns_expiration_cellrenderertext_edited_cb (GtkCellRendererText 
*renderer,
-                                                       gchar *path,
-                                                       gchar *new_text,
-                                                       gpointer user_data)
-{
-  GtkTreeIter it;
-  struct GNUNET_TIME_Absolute abstime;
-  struct GNUNET_TIME_Relative reltime; 
-
-  if (NULL == new_text)
-    return; /* can this happen? */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "New expiration time: `%s'\n",
-             new_text);
-  gtk_tree_model_get_iter_from_string (tm, &it, path);
-  if (GNUNET_OK ==
-      GNUNET_STRINGS_fancy_time_to_absolute (new_text,
-                                            &abstime))
+  if (NULL == name_str)
   {
-    gtk_tree_store_set (ts, &it,
-                       GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text,
-                       GNS_TREESTORE_COL_EXP_TIME, abstime.abs_value,
-                       GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE,
-                       GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL,
-                       -1);
-    check_name_validity_and_commit (&it, NULL);
+    GNUNET_break (0);
     return;
   }
-  if (GNUNET_OK ==
-      GNUNET_STRINGS_fancy_time_to_relative (new_text,
-                                            &reltime))
-  {
-    gtk_tree_store_set (ts, &it,
-                       GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text,
-                       GNS_TREESTORE_COL_EXP_TIME, reltime.rel_value,
-                       GNS_TREESTORE_COL_EXP_TIME_IS_REL, TRUE,
-                       GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL,
-                       -1);
-    check_name_validity_and_commit (&it, NULL);
-    return;
-  }
-  show_error_message (_("Invalid time value"),
-                     new_text);
+  GNUNET_CRYPTO_hash (name_str, strlen (name_str), &name_hash);
+  ri = GNUNET_CONTAINER_multihashmap_get (n2r, &name_hash);
+  launch_edit_dialog (type, name_str, ri, UINT_MAX);
+  g_free (name_str);
 }
 
 
@@ -1563,7 +1072,6 @@
                                                  gpointer user_data)
 {
   GtkTreeIter it;
-  GtkTreeIter child;
   gboolean not_dummy;
   char *name;
 
@@ -1587,55 +1095,31 @@
                      GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, 
                      GNS_TREESTORE_COL_NAME, &name, 
                      -1);
+  GNUNET_break (! not_dummy);
+  GNUNET_break (0 == strcmp (name, _(NEW_NAME_STR)));
+  g_free (name);
 
-  if (! not_dummy)
-  {
-    /* change dummy line to new name, then add new dummy */
-    gtk_tree_store_set (ts, &it,
-                        GNS_TREESTORE_COL_NAME, new_text,
-                       GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
-                        GNS_TREESTORE_COL_RECORD_TYPE, 0,
-                        GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, 
_(NEW_RECORD_STR),
-                        GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
-                       GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
-                       GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
-                        -1);
-    check_name_validity_and_commit (&it,
-                                   name);
-    if (0 == strcmp (name, _(NEW_NAME_STR)))
-    {
-      /* add a new dummy line */
-      gtk_tree_store_insert_with_values (ts, &it,NULL, 0,
-                                        GNS_TREESTORE_COL_NAME, 
_(NEW_NAME_STR),
-                                        GNS_TREESTORE_COL_NAME_IS_VISIBLE, 
TRUE,
-                                        GNS_TREESTORE_COL_RECORD_TYPE, 
GNUNET_DNSPARSER_TYPE_A,
-                                        GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
-                                        GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE,
-                                        GNS_TREESTORE_COL_TYPE_IS_EDITABLE, 
FALSE,
-                                        -1);
-    }
-  }
-  else
-  {
-    /* update name */
-    gtk_tree_store_set (ts, &it, 
-                       GNS_TREESTORE_COL_NAME, new_text,
-                       -1);
-
-    if (gtk_tree_model_iter_children (tm, &child, &it))
-    {
-      do
-      {
-        gtk_tree_store_set (ts, &child,
-                           GNS_TREESTORE_COL_NAME, new_text,
-                           -1);
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", 
path, new_text);
-      }
-      while (gtk_tree_model_iter_next (tm, &child));
-    }
-
-    check_name_validity_and_commit (&it, name);
-  }
+  /* change dummy line to new name, then add new dummy */
+  gtk_tree_store_set (ts, &it,
+                     GNS_TREESTORE_COL_NAME, new_text,
+                     GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
+                     GNS_TREESTORE_COL_RECORD_TYPE, 0,
+                     GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR),
+                     GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
+                     GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
+                     GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
+                     GNS_TREESTORE_COL_NAME_IS_EDITABLE, FALSE,
+                     -1);
+  /* add a new dummy line */
+  gtk_tree_store_insert_with_values (ts, &it,NULL, 0,
+                                    GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR),
+                                    GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
+                                    GNS_TREESTORE_COL_RECORD_TYPE, 
GNUNET_DNSPARSER_TYPE_A,
+                                    GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
+                                    GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE,
+                                    GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE,
+                                    GNS_TREESTORE_COL_NAME_IS_EDITABLE, TRUE,
+                                    -1);
 }
 
 
@@ -1682,7 +1166,7 @@
  * The zone treeview pop up menu is supposed to be created.
  * (Note: this is not the only method that might need to be
  * written to handle events to create pop up menus; right-clicks
- * might need to be managed separately).
+ * need to be managed separately).
  *
  * @param widget the widget
  * @param user_data unused
@@ -1697,49 +1181,6 @@
 
 
 /**
- * Delete the selected row from the GtkTreeView (unless it is a dummy row).
- */
-static void
-delete_selected_row ()
-{
-  GtkTreeIter it;
-  GtkTreeSelection *sel;
-  int not_dummy;
-  char *path;
-
-  sel = gtk_tree_view_get_selection(tv);
-  if (! gtk_tree_selection_get_selected (sel, NULL, &it))
-    return; /* nothing selected */  
-  gtk_tree_model_get (tm, &it, 
-                     GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, 
-                     -1);
-  if (GNUNET_NO == not_dummy)
-    return; /* do not delete the dummy line */
-  path = gtk_tree_model_get_string_from_iter (tm, &it);
-  remove_records_by_path (path);
-  g_free (path);  
-}
-
-
-/**
- * User selected 'edit' in the popup menu.  Edit the
- * selected row.
- *
- * @param widget the GtkTreeView
- * @param user_data main window builder 
- */
-void
-GNUNET_setup_gns_popup_edit_button_activate_cb (GtkWidget *widget,
-                                               gpointer user_data)
-{
-  /* FIXME: not this easy! Row may still be a 'fresh' row! 
-     Need to check model to determine if argument should
-     be YES or NO! */
-  edit_selected_row (GNUNET_YES);
-}
-
-
-/**
  * A button was pressed in the GtkTreeView, check for right button and
  * if applicable create the popup menu.
  *
@@ -1766,63 +1207,39 @@
 /**
  * User pushed a key in the GtkTreeView.  Check for 'del' and if so, delete
  * the currently selected row.
+ *
+ * @param widget originating widget
+ * @param event event information
+ * @param user_data unused
+ * @return TRUE if the key was processed ('del')
  */
 gboolean
 GNUNET_setup_gns_main_treeview_key_press_event_cb (GtkWidget *widget, 
                                                   GdkEventKey *event, 
                                                   gpointer user_data)
 {
+  GtkTreeIter it;
+  GtkTreeSelection *sel;
+  int not_dummy;
+
   /* Check for delete key */
-  if ( (GDK_KEY_PRESS == event->type) && 
-       (GDK_KEY_Delete == event->keyval) ) 
-  {
-    delete_selected_row ();
-    return TRUE;
-  }
-  return FALSE;
+  if ( (GDK_KEY_PRESS != event->type) ||
+       (GDK_KEY_Delete != event->keyval) ) 
+    return FALSE;
+  sel = gtk_tree_view_get_selection(tv);
+  if (! gtk_tree_selection_get_selected (sel, NULL, &it))
+    return TRUE; /* nothing selected */  
+  gtk_tree_model_get (tm, &it, 
+                     GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, 
+                     -1);
+  if (GNUNET_NO == not_dummy)
+    return TRUE; /* do not delete the dummy line */
+  remove_records_by_iter (&it);
+  return TRUE;
 }
 
 
 /**
- * Function called upon completion of a 'pseu' operation.
- *
- * @param cls the 'struct PseuContext' of the operation that completed
- * @param success GNUNET_OK if the operation succeeded
- * @param emsg error message if the operation failed
- */
-static void 
-pseu_change_cont (void *cls,
-                 int32_t success,
-                 const char *emsg)
-{
-  struct PseuContext *pc = cls;
-  GtkWidget *dialog;
-  GtkWindow *main_window;
-  
-  pc->qe = NULL;
-  GNUNET_CONTAINER_DLL_remove (pc_head,
-                              pc_tail,
-                              pc);
-  if (GNUNET_SYSERR == success)
-  {
-    main_window = GTK_WINDOW (GNUNET_SETUP_get_object ("GNUNET_setup_dialog"));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("New Pseudonym could not be set: 
`%s'\n"), emsg);
-    dialog = gtk_message_dialog_new (main_window,
-                                    GTK_DIALOG_DESTROY_WITH_PARENT,
-                                    GTK_MESSAGE_ERROR,
-                                    GTK_BUTTONS_CLOSE,
-                                    _("New Pseudonym could not be set: 
`%s'\n"),
-                                    emsg);
-    g_signal_connect_swapped (dialog, "response",
-                              G_CALLBACK (gtk_widget_destroy),
-                              dialog);
-    gtk_widget_show_all (dialog);
-    resync_db ();
-  }
-}
-
-
-/**
  * The user edited the preferred name (PSEU) of this namespace.
  * Push the update to the namestore.
  *
@@ -1833,9 +1250,11 @@
 GNUNET_setup_gns_pseu_entry_changed_cb (GtkEditable *editable,
                                        gpointer user_data)
 {
-  struct GNUNET_NAMESTORE_RecordData rd;
   const gchar *pseu;
-  struct PseuContext *pc;
+  struct RecordInfo *ri;
+  struct GNUNET_HashCode hc;
+  unsigned int rd_count;
+  struct OperationContext *oc;
 
   pseu = gtk_entry_get_text (GTK_ENTRY (editable));
   if (GNUNET_OK !=
@@ -1849,47 +1268,61 @@
                        pseu);
     return;
   }
-  if ( (pseu != NULL) && 
-       (0 != strcmp ("", pseu)) )
+  GNUNET_CRYPTO_hash ("+", 1, &hc);
+  ri = GNUNET_CONTAINER_multihashmap_get (n2r, &hc);
+  if (NULL == ri)
+    rd_count = 0;
+  else
+    rd_count = ri->rd_count;
+
+  /* get old records, append new one or update/remove existing one */
   {
-    rd.record_type = GNUNET_NAMESTORE_TYPE_PSEU;
-    rd.expiration_time = UINT64_MAX;
-    rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
-    rd.data_size = strlen (pseu) + 1;
-    rd.data = pseu;
-    pc = GNUNET_malloc (sizeof (struct PseuContext));
-    GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc);
-#if 0
-    /* FIXME: actually apply changes! */
-    pc->qe = GNUNET_NAMESTORE_record_create (namestore, pkey, "+",
-                                            &rd,
-                                            &pseu_change_cont, pc);
-#endif
+    struct GNUNET_NAMESTORE_RecordData rd_old[rd_count];
+    struct GNUNET_NAMESTORE_RecordData rd_new[rd_count + 1];
+    unsigned int off;
+    unsigned int total;
+
+    total = rd_count;
+    if (NULL != ri)
+      GNUNET_break (GNUNET_OK ==
+                   GNUNET_NAMESTORE_records_deserialize (ri->data_size,
+                                                         ri->data,
+                                                         rd_count,
+                                                         rd_old));
+    memcpy (rd_new, rd_old, sizeof (struct GNUNET_NAMESTORE_RecordData) * 
rd_count);
+    for (off=0;off<rd_count;off++)
+      if (GNUNET_NAMESTORE_TYPE_PSEU == rd_new[off].record_type)
+       break;
+    if (off == rd_count)
+      total++;
+    rd_new[off].record_type = GNUNET_NAMESTORE_TYPE_PSEU;
+    rd_new[off].expiration_time = UINT64_MAX;
+    rd_new[off].flags = GNUNET_NAMESTORE_RF_AUTHORITY;
+    rd_new[off].data_size = strlen (pseu) + 1;
+    rd_new[off].data = pseu;
+    if ( (NULL == pseu) ||
+        (0 == strlen (pseu)) )    
+    {
+      rd_new[off] = rd_new[rd_count - 1];
+      total--;
+    } 
+    oc = GNUNET_new (struct OperationContext);
+    GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc);
+    oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, 
+                                                      pkey, "+",
+                                                      total,
+                                                      rd_new,
+                                                      &operation_done_cont, 
oc);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
                "New Pseudonym is `%s' %u\n",
-               (char *) rd.data, rd.data_size);
+               (char *) pseu, rd_new[off].data_size);
     GNUNET_free_non_null (current_pseudonym);
-    current_pseudonym = GNUNET_strdup (pseu);
+    if ( (NULL != pseu) &&
+        (0 != strlen (pseu)) )
+      current_pseudonym = GNUNET_strdup (pseu);
+    else
+      current_pseudonym = NULL;
   }
-  else if (NULL != current_pseudonym)
-  {
-    rd.record_type = GNUNET_NAMESTORE_TYPE_PSEU;
-    rd.expiration_time = UINT64_MAX;
-    rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
-    rd.data_size = strlen (current_pseudonym) + 1;
-    rd.data = current_pseudonym;
-    pc = GNUNET_malloc (sizeof (struct PseuContext));
-    GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc);
-#if 0
-    /* FIXME: actually apply changes! */
-    pc->qe = GNUNET_NAMESTORE_record_remove (namestore, pkey, "+",
-                                            &rd,
-                                            &pseu_change_cont, pc);
-#endif
-    gtk_entry_set_text (GTK_ENTRY(editable), "");
-    GNUNET_free_non_null (current_pseudonym);
-    current_pseudonym = NULL;
-  }
 #if HAVE_QRENCODE_H
   setup_qrcode ();
 #endif
@@ -1925,13 +1358,8 @@
 static void
 zone_sync_proc (void *cls)
 {
-  GtkEntry *pseu_entry;
-
-  pseu_entry = GTK_ENTRY((GNUNET_SETUP_get_object 
("GNUNET_setup_gns_pseu_entry")));
   if (0 == strcmp (current_zone_option, "ZONEKEY"))    
     gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object 
("GNUNET_setup_gns_pseu_hbox")));    
-  GNUNET_setup_gns_pseu_entry_changed_cb (GTK_EDITABLE (pseu_entry),
-                                         NULL);
 #if HAVE_QRENCODE_H
   setup_qrcode ();
   gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object 
("GNUNET_setup_gns_qr_image")));
@@ -1952,9 +1380,6 @@
  * Function called for each record in the current zone.  Update the
  * widgets accordingly. 
  *
- * FIXME: we need to UPDATE records if an existing record is changed,
- * not merely append!
- *
  * @param NULL
  * @param zone_key public key of the zone
  * @param freshness when does the corresponding block in the DHT expire (until
@@ -1976,6 +1401,8 @@
                     const struct GNUNET_NAMESTORE_RecordData *rd,
                     const struct GNUNET_CRYPTO_EccSignature *signature)
 {
+  GtkTreeRowReference *rr;
+  GtkTreePath *path;
   GtkTreeIter iter_name;
   GtkTreeIter iter_record;
   int c;
@@ -1987,6 +1414,8 @@
   guint64 exp_t;
   struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
   GtkEntry *pseu_entry;
+  struct GNUNET_HashCode name_hash;
+  struct RecordInfo *ri;
 
   if ((NULL == zone_key) && (NULL == name))
   {
@@ -2007,18 +1436,78 @@
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
              "Zone `%s' iteration result `%s', %u records\n",
              &shenc, name, rd_count);
-  gtk_tree_store_append (ts, &iter_name, NULL);
-  gtk_tree_store_set (ts, &iter_name,
-                     GNS_TREESTORE_COL_NAME, name,
-                     GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
-                     GNS_TREESTORE_COL_RECORD_TYPE, GNUNET_NAMESTORE_TYPE_ANY,
-                     GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR),
-                     GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
-                     GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
-                     GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
-                     -1);
+  GNUNET_CRYPTO_hash (name,
+                     strlen (name),
+                     &name_hash);
+  ri = GNUNET_CONTAINER_multihashmap_get (n2r, &name_hash);
+  if (NULL != ri)
+  {
+    rr = ri->rr;
+    path = gtk_tree_row_reference_get_path (rr);
+    GNUNET_assert (gtk_tree_model_get_iter (tm,
+                                           &iter_name,
+                                           path));
+    gtk_tree_path_free (path);
+    /* remove all records, we'll re-add those that are left next */
+    if (gtk_tree_model_iter_children (tm, &iter_record, &iter_name))
+    {
+      do
+      {
+        gtk_tree_store_remove (ts, &iter_record);
+      }
+      while (gtk_tree_model_iter_next (tm, &iter_record));
+    }
+  }
+  else
+  {
+    ri = GNUNET_new (struct RecordInfo);
+    gtk_tree_store_append (ts, &iter_name, NULL);
+    gtk_tree_store_set (ts, &iter_name,
+                       GNS_TREESTORE_COL_NAME, name,
+                       GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
+                       GNS_TREESTORE_COL_RECORD_TYPE, 
GNUNET_NAMESTORE_TYPE_ANY,
+                       GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR),
+                       GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
+                       GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
+                       GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
+                       -1);
+    
+    path = gtk_tree_model_get_path (tm,
+                                   &iter_name);
+    rr = gtk_tree_row_reference_new (tm,
+                                    path);
+    ri->rr = rr;
+    ri->name = GNUNET_strdup (name);
+    gtk_tree_path_free (path);
+    GNUNET_assert (GNUNET_OK ==
+                  GNUNET_CONTAINER_multihashmap_put (n2r,
+                                                     &name_hash,
+                                                     ri,
+                                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  }
+  if (0 == rd_count)
+  {
+    /* all records removed, remove name as well */
+    gtk_tree_store_remove (ts, &iter_name);
+    GNUNET_assert (GNUNET_YES == 
+                  GNUNET_CONTAINER_multihashmap_remove (n2r, &name_hash, ri));
+    gtk_tree_row_reference_free (rr);
+    GNUNET_free (ri->name);
+    GNUNET_free_non_null (ri->data);
+    GNUNET_free (ri);
+    return;
+  }
+  /* update record info serialized version of the records */
+  GNUNET_free_non_null (ri->data);
+  ri->rd_count = rd_count;
+  ri->data_size = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
+  if (0 != ri->data_size)
+    ri->data = GNUNET_malloc (ri->data_size);
+  GNUNET_break (GNUNET_OK ==
+               GNUNET_NAMESTORE_records_serialize (rd_count, rd,
+                                                   ri->data_size, ri->data));
 
-  /* Append elements for records */
+  /* Append elements for records in tree view */
   for (c = 0; c < rd_count; c ++)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2065,23 +1554,23 @@
     {
       pseu_entry = GTK_ENTRY((GNUNET_SETUP_get_object 
("GNUNET_setup_gns_pseu_entry")));
       gtk_entry_set_text (pseu_entry, val);
+#if HAVE_QRENCODE_H
+      setup_qrcode ();
+#endif
     }
-    else
-    {
-      gtk_tree_store_insert_with_values (ts, &iter_record , &iter_name, 0,
-                                        GNS_TREESTORE_COL_NAME, name,
-                                        GNS_TREESTORE_COL_NAME_IS_VISIBLE, 
FALSE,
-                                        GNS_TREESTORE_COL_RECORD_TYPE, 
rd[c].record_type,
-                                        GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, 
type_str,
-                                        GNS_TREESTORE_COL_IS_PUBLIC, public,
-                                        GNS_TREESTORE_COL_EXP_TIME, exp_t,
-                                        GNS_TREESTORE_COL_EXP_TIME_AS_STR, exp,
-                                        GNS_TREESTORE_COL_EXP_TIME_IS_REL, 
time_is_relative,
-                                        GNS_TREESTORE_COL_VAL_AS_STR, val,
-                                         GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
-                                        GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE,
-                                         -1);
-    }
+    gtk_tree_store_insert_with_values (ts, &iter_record , &iter_name, 0,
+                                      GNS_TREESTORE_COL_NAME, name,
+                                      GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE,
+                                      GNS_TREESTORE_COL_RECORD_TYPE, 
rd[c].record_type,
+                                      GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, 
type_str,
+                                      GNS_TREESTORE_COL_IS_PUBLIC, public,
+                                      GNS_TREESTORE_COL_EXP_TIME, exp_t,
+                                      GNS_TREESTORE_COL_EXP_TIME_AS_STR, exp,
+                                      GNS_TREESTORE_COL_EXP_TIME_IS_REL, 
time_is_relative,
+                                      GNS_TREESTORE_COL_VAL_AS_STR, val,
+                                      GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
+                                      GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE,
+                                      -1);    
     GNUNET_free (type_str);
     GNUNET_free (val);
   }
@@ -2099,7 +1588,7 @@
 load_zone (const char *zonename)
 {
   char *keyfile;
-  struct GNUNET_CRYPTO_RsaPrivateKey *pk;
+  struct GNUNET_CRYPTO_EccPrivateKey *pk;
   char *emsg;
   struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
   char *label;
@@ -2130,7 +1619,7 @@
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using `%s'\n", keyfile);
-  pk = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+  pk = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
   GNUNET_free (keyfile);
   if (NULL == pk)
   {
@@ -2139,9 +1628,9 @@
     return;
   }
   pkey = pk;
-  GNUNET_CRYPTO_rsa_key_get_public (pkey, &pubkey);
+  GNUNET_CRYPTO_ecc_key_get_public (pkey, &pubkey);
   GNUNET_CRYPTO_short_hash (&pubkey,
-                            sizeof (struct 
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                            sizeof (struct 
GNUNET_CRYPTO_EccPublicKeyBinaryEncoded),
                             &zone);
   GNUNET_CRYPTO_short_hash_to_enc(&zone, &shenc);
 
@@ -2158,9 +1647,13 @@
                                      GNS_TREESTORE_COL_RECORD_TYPE, 
GNUNET_DNSPARSER_TYPE_A,
                                      GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE,
                                      GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
-                                    GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
+                                    GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE,
+                                    GNS_TREESTORE_COL_NAME_IS_EDITABLE, TRUE,
                                      -1);
   /* Load zone from namestore! */
+#if HAVE_QRENCODE_H
+  setup_qrcode ();
+#endif
   zmon = GNUNET_NAMESTORE_zone_monitor_start (cfg, &zone,
                                              &zone_iteration_proc,
                                              &zone_sync_proc,
@@ -2238,42 +1731,67 @@
   ts = GTK_TREE_STORE (GNUNET_SETUP_get_object ("GNUNET_setup_gns_treestore"));
   tv = GTK_TREE_VIEW (GNUNET_SETUP_get_object 
("GNUNET_setup_gns_main_treeview"));
   tm = GTK_TREE_MODEL (ts);  
+  n2r = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO);
   load_zone ("ZONEKEY");
 }
 
 
 /**
+ * Release the record info.
+ *
+ * @param cls NULL
+ * @param key unused
+ * @param value a RecordInfo to release
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+release_ri (void *cls,
+           const struct GNUNET_HashCode *key,
+           void *value)
+{
+  struct RecordInfo *ri = value;
+
+  gtk_tree_row_reference_free (ri->rr);
+  GNUNET_free_non_null (ri->data);
+  GNUNET_free (ri->name);
+  GNUNET_free (ri);
+  return GNUNET_OK;
+}
+
+
+/**
  * Disconnect from the namestore and clean up the main
  * GNS tree view.
  */
 void
 GNUNET_SETUP_gns_done ()
 {
-  struct EditDialogContext *edc;
+  struct OperationContext *oc;
 
   gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object 
("GNUNET_setup_gns_status_label")));
   gtk_widget_hide (GTK_WIDGET (GNUNET_SETUP_get_object 
("GNUNET_setup_gns_main_scrolledwindow")));
-  gtk_tree_store_clear (ts);
   if (NULL != zmon)
   {
     GNUNET_NAMESTORE_zone_monitor_stop (zmon);
     zmon = NULL;
   }
-  while (NULL != uc_head)
-    free_update_context (uc_head);
-  while (NULL != rc_head)
-    free_remove_context (rc_head);
-  while (NULL != (edc = edc_head))
+  while (NULL != (oc = oc_head))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Setup shutdown before all records could be written. Record 
lost!\n"));
-    if (NULL != edc->qe)
-      GNUNET_NAMESTORE_cancel (edc->qe);
-    if (NULL != edc->rkgc)
-      GNUNET_CRYPTO_rsa_key_create_stop (edc->rkgc);
-    GNUNET_CONTAINER_DLL_remove (edc_head, edc_tail, edc);
-    free_edit_dialog_context (edc);
+               _("A pending namestore operation was not transmitted to the 
namestore.\n"));
+    GNUNET_CONTAINER_DLL_remove (oc_head, oc_tail, oc);
+    GNUNET_NAMESTORE_cancel (oc->qe);
+    GNUNET_free (oc);
   }
+  if (NULL != n2r)
+  {
+    GNUNET_CONTAINER_multihashmap_iterate (n2r,
+                                          &release_ri,
+                                          NULL);
+    GNUNET_CONTAINER_multihashmap_destroy (n2r);
+    n2r = NULL;
+  }
+  gtk_tree_store_clear (ts);
   if (NULL != namestore)
   {
     GNUNET_NAMESTORE_disconnect (namestore);
@@ -2281,7 +1799,7 @@
   }
   if (NULL != pkey)
   {
-    GNUNET_CRYPTO_rsa_key_free (pkey);
+    GNUNET_CRYPTO_ecc_key_free (pkey);
     pkey = NULL;
   }
   if (NULL != current_pseudonym)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]