Index: modules/field/field.attach.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v
retrieving revision 1.96
diff -u -p -r1.96 field.attach.inc
--- modules/field/field.attach.inc	3 Oct 2010 01:15:33 -0000	1.96
+++ modules/field/field.attach.inc	17 Oct 2010 08:20:42 -0000
@@ -170,7 +170,7 @@ define('FIELD_STORAGE_INSERT', 'insert')
  *    name. It will be used to narrow down to a single value the available
  *    languages to act on.
  */
-function _field_invoke($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $options = array()) {
+function _field_invoke($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $options = array(), $parents = array()) {
   // Merge default options.
   $default_options = array(
     'default' => FALSE,
@@ -196,7 +196,7 @@ function _field_invoke($op, $entity_type
 
       foreach ($languages as $langcode) {
         $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
-        $result = $function($entity_type, $entity, $field, $instance, $langcode, $items, $a, $b);
+        $result = $function($entity_type, $entity, $field, $instance, $langcode, $items, $a, $b, $parents);
         if (isset($result)) {
           // For hooks with array results, we merge results together.
           // For hooks with scalar results, we collect results in an array.
@@ -367,9 +367,9 @@ function _field_invoke_multiple($op, $en
  *
  * @see _field_invoke()
  */
-function _field_invoke_default($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $options = array()) {
+function _field_invoke_default($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $options = array(), $parents = array()) {
   $options['default'] = TRUE;
-  return _field_invoke($op, $entity_type, $entity, $a, $b, $options);
+  return _field_invoke($op, $entity_type, $entity, $a, $b, $options, $parents = array());
 }
 
 /**
@@ -531,15 +531,19 @@ function _field_invoke_get_instances($en
  * @param $langcode
  *   The language the field values are going to be entered, if no language
  *   is provided the default site language will be used.
+ * @param $parents
+ *   The array of parents representing position of $entity and its fields in
+ *   form array. This will be used as unique namespace for entity fields, their
+ *   values and settings.
  * @return
  *   The form elements are added by reference at the top level of the $form
  *   parameter. Processing information is added by reference in
  *   $form_state['field'].
  */
-function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL) {
+function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL, $parents = array()) {
   // If no language is provided use the default site language.
   $options = array('language' => field_valid_language($langcode));
-  $form += (array) _field_invoke_default('form', $entity_type, $entity, $form, $form_state, $options);
+  $form += (array) _field_invoke_default('form', $entity_type, $entity, $form, $form_state, $options, $parents);
 
   // Add custom weight handling.
   list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
@@ -786,9 +790,9 @@ function field_attach_validate($entity_t
  * @param $form_state
  *   An associative array containing the current state of the form.
  */
-function field_attach_form_validate($entity_type, $entity, $form, &$form_state) {
+function field_attach_form_validate($entity_type, $entity, $form, &$form_state, $parents = array()) {
   // Extract field values from submitted values.
-  _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state);
+  _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state, $parents);
 
   // Perform field_level validation.
   try {
@@ -799,10 +803,10 @@ function field_attach_form_validate($ent
     // flagging.
     foreach ($e->errors as $field_name => $field_errors) {
       foreach ($field_errors as $langcode => $language_errors) {
-        $form_state['field'][$field_name][$langcode]['errors'] = $language_errors;
+        drupal_array_set_nested_value($form_state['field'][$field_name][$langcode], array_merge($parents, array('errors')), $language_errors);
       }
     }
-    _field_invoke_default('form_errors', $entity_type, $entity, $form, $form_state);
+    _field_invoke_default('form_errors', $entity_type, $entity, $form, $form_state, $parents);
   }
 }
 
Index: modules/field/field.default.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.default.inc,v
retrieving revision 1.39
diff -u -p -r1.39 field.default.inc
--- modules/field/field.default.inc	4 Aug 2010 06:55:35 -0000	1.39
+++ modules/field/field.default.inc	17 Oct 2010 08:20:42 -0000
@@ -11,11 +11,13 @@
  * the corresponding field_attach_[operation]() function.
  */
 
-function field_default_extract_form_values($entity_type, $entity, $field, $instance, $langcode, &$items, $form, &$form_state) {
+function field_default_extract_form_values($entity_type, $entity, $field, $instance, $langcode, &$items, $form, &$form_state, $parents = array()) {
   $field_name = $field['field_name'];
 
-  if (isset($form_state['values'][$field_name][$langcode])) {
-    $items = $form_state['values'][$field_name][$langcode];
+  $values_exists = FALSE;
+  $values = drupal_array_get_nested_value($form_state['values'], array_merge($parents, array($field_name, $langcode)), $values_exists);
+  if ($values_exists) {
+    $items = $values;
     // Remove the 'value' of the 'add more' button.
     unset($items['add_more']);
   }
Index: modules/field/field.form.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.form.inc,v
retrieving revision 1.50
diff -u -p -r1.50 field.form.inc
--- modules/field/field.form.inc	17 Jun 2010 13:44:45 -0000	1.50
+++ modules/field/field.form.inc	17 Oct 2010 08:20:42 -0000
@@ -9,7 +9,7 @@
 /**
  * Create a separate form element for each field.
  */
-function field_default_form($entity_type, $entity, $field, $instance, $langcode, $items, &$form, &$form_state, $get_delta = NULL) {
+function field_default_form($entity_type, $entity, $field, $instance, $langcode, $items, &$form, &$form_state, $parents = array(), $get_delta = NULL) {
   // This could be called with no entity, as when a UI module creates a
   // dummy form to set default values.
   if ($entity) {
@@ -31,7 +31,7 @@ function field_default_form($entity_type
     // If field module handles multiple values for this form element, and we
     // are displaying an individual element, process the multiple value form.
     if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
-      $elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state);
+      $elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state, $parents);
     }
     // If the widget is handling multiple values (e.g Options), or if we are
     // displaying an individual element, just get a single form element and
@@ -101,6 +101,7 @@ function field_default_form($entity_type
   $elements['#after_build'][] = 'field_form_element_after_build';
   $elements['#field_name'] = $field_name;
   $elements['#language'] = $langcode;
+  $elements['#field_parents'] = $parents;
 
   $addition[$field_name] += array(
     '#tree' => TRUE,
@@ -121,16 +122,19 @@ function field_default_form($entity_type
  * - AHAH-'add more' button
  * - drag-n-drop value reordering
  */
-function field_multiple_value_form($field, $instance, $langcode, $items, &$form, &$form_state) {
+function field_multiple_value_form($field, $instance, $langcode, $items, &$form, &$form_state, $parents = array()) {
   $field_name = $field['field_name'];
 
   // Determine the number of widgets to display.
   switch ($field['cardinality']) {
     case FIELD_CARDINALITY_UNLIMITED:
       $filled_items = _field_filter_items($field, $items);
-      $current_item_count = isset($form_state['field_item_count'][$field_name])
-                            ? $form_state['field_item_count'][$field_name]
-                            : count($items);
+      $key_exists = FALSE;
+      if (isset($form_state['field'][$field_name][$langcode])) {
+        $field_item_count = drupal_array_get_nested_value($form_state['field'][$field_name][$langcode], array_merge($parents, array('field_item_count')), $key_exists);
+      }
+      $current_item_count = $key_exists ? $field_item_count : count($items);
+
       // We always want at least one empty icon for the user to fill in.
       $max = ($current_item_count > count($filled_items))
               ? $current_item_count - 1
@@ -144,7 +148,8 @@ function field_multiple_value_form($fiel
 
   $title = check_plain(t($instance['label']));
   $description = field_filter_xss(t($instance['description']));
-  $wrapper_id = drupal_html_id($field_name . '-add-more-wrapper');
+  $wrapper_id_prefix = count($parents) ? implode('-', $parents) . '-' : '';
+  $wrapper_id = drupal_html_id($wrapper_id_prefix . $field_name . '-add-more-wrapper');
   $field_elements = array();
 
   $function = $instance['widget']['module'] . '_field_widget_form';
@@ -198,10 +203,10 @@ function field_multiple_value_form($fiel
       if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
         $field_elements['add_more'] = array(
           '#type' => 'submit',
-          '#name' => $field_name . '_add_more',
+          '#name' => strtr($wrapper_id_prefix, '-', '_') . $field_name . '_add_more',
           '#value' => t('Add another item'),
           '#attributes' => array('class' => array('field-add-more-submit')),
-          '#limit_validation_errors' => array(array($field_name, $langcode)),
+          '#limit_validation_errors' => array(array_merge($parents, array($field_name, $langcode))),
           '#submit' => array('field_add_more_submit'),
           '#ajax' => array(
             'callback' => 'field_add_more_js',
@@ -212,6 +217,7 @@ function field_multiple_value_form($fiel
           // find the relevant field using those entries.
           '#field_name' => $field_name,
           '#language' => $langcode,
+          '#field_parents' => $parents,
         );
       }
     }
@@ -308,7 +314,11 @@ function theme_field_multiple_value_form
 function field_form_element_after_build($element, &$form_state) {
   $field_name = $element['#field_name'];
   $langcode = $element['#language'];
-  $form_state['field'][$field_name][$langcode]['array_parents'] = $element['#array_parents'];
+  $parents = $element['#field_parents'];
+  $parents[] = 'array_parents';
+  if (isset($form_state['field'][$field_name][$langcode])) {
+    drupal_array_set_nested_value($form_state['field'][$field_name][$langcode], $parents, $element['#array_parents']);
+  }
 
   return $element;
 }
@@ -316,9 +326,9 @@ function field_form_element_after_build(
 /**
  * Transfer field-level validation errors to widgets.
  */
-function field_default_form_errors($entity_type, $entity, $field, $instance, $langcode, $items, $form, &$form_state) {
+function field_default_form_errors($entity_type, $entity, $field, $instance, $langcode, $items, $form, &$form_state, $parents = array()) {
   $field_name = $field['field_name'];
-  $field_info = $form_state['field'][$field_name][$langcode];
+  $field_info = drupal_array_get_nested_value($form_state['field'][$field_name][$langcode], $parents);
 
   if (!empty($field_info['errors'])) {
     $function = $instance['widget']['module'] . '_field_widget_error';
@@ -361,8 +371,14 @@ function field_default_form_errors($enti
 function field_add_more_submit($form, &$form_state) {
   $field_name = $form_state['clicked_button']['#field_name'];
   $langcode = $form_state['clicked_button']['#language'];
-  if ($form_state['values'][$field_name . '_add_more']) {
-    $form_state['field_item_count'][$field_name] = count($form_state['values'][$field_name][$langcode]);
+  $parents = $form_state['clicked_button']['#field_parents'];
+
+  $button_name = count($parents) ? implode('_', $parents) . '_' : '';
+  $button_name .= $field_name . '_add_more';
+  if ($form_state['values'][$button_name]) {
+    $values = drupal_array_get_nested_value($form_state['values'], array_merge($parents, array($field_name, $langcode)));
+    drupal_set_message(print_r($form_state['values'], TRUE));
+    drupal_array_set_nested_value($form_state['field'][$field_name][$langcode], array_merge($parents, array('field_item_count')), count($values));
   }
   $form_state['rebuild'] = TRUE;
 }
@@ -379,6 +395,7 @@ function field_add_more_js($form, $form_
   // Retrieve field information.
   $field_name = $form_state['clicked_button']['#field_name'];
   $langcode = $form_state['clicked_button']['#language'];
+  $parents = $form_state['clicked_button']['#field_parents'];
   $field_info = $form_state['field'][$field_name][$langcode];
   $field = $field_info['field'];
 
@@ -388,8 +405,8 @@ function field_add_more_js($form, $form_
 
   // Navigate to the right element in the the form.
   $element = $form;
-
-  foreach ($field_info['array_parents'] as $key) {
+  $array_parents = drupal_array_get_nested_value($field_info, array_merge($parents, array('array_parents')));
+  foreach ($array_parents as $key) {
     $element = $element[$key];
   }
 
Index: modules/field_ui/field_ui.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.admin.inc,v
retrieving revision 1.73
diff -u -p -r1.73 field_ui.admin.inc
--- modules/field_ui/field_ui.admin.inc	14 Oct 2010 18:50:27 -0000	1.73
+++ modules/field_ui/field_ui.admin.inc	17 Oct 2010 08:20:44 -0000
@@ -1828,7 +1828,7 @@ function field_ui_default_value_widget($
   $instance['required'] = FALSE;
   $instance['description'] = '';
   // @todo Allow multiple values (requires more work on 'add more' JS handler).
-  $element += field_default_form(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state, 0);
+  $element += field_default_form(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state, array(), 0);
 
   return $element;
 }
