Index: rules/rules.export.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules/Attic/rules.export.inc,v
retrieving revision 1.1.2.11
diff -u -p -r1.1.2.11 rules.export.inc
--- rules/rules.export.inc	5 Aug 2010 14:51:41 -0000	1.1.2.11
+++ rules/rules.export.inc	10 Oct 2010 17:01:52 -0000
@@ -58,24 +58,6 @@ function rules_item_rule_export($rule_na
     if (empty($rule['#categories']) || !in_array($module, $rule['#categories'])) {
       $rule['#categories'][$module] = $module;
     }
-
-    // We increase the counter in any case. As already renamed rules are passed
-    // in first, this makes sure to not overwrite the names of those even if
-    // they aren't saved yet.
-    $counter++;
-
-    if (strpos($rule_name, $module) !== 0) {
-      // Make sure the name isn't already taken.
-      $rules = rules_get_configured_items('rules');
-      while (isset($rules[$module .'_'. $counter])) {
-        $counter++;
-      }
-
-      // Rename the rule.
-      $export['rules'][$module .'_'. $counter] = $rule;
-      // Unset the non-prefixed item.
-      unset($export['rules'][$rule_name]);
-    }
   }
 }
 
Index: rules/rules.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules/Attic/rules.module,v
retrieving revision 1.1.2.74
diff -u -p -r1.1.2.74 rules.module
--- rules/rules.module	10 Aug 2010 08:28:00 -0000	1.1.2.74
+++ rules/rules.module	10 Oct 2010 17:01:52 -0000
@@ -818,6 +818,15 @@ function rules_item_save($item_type, $na
 }
 
 /**
+ * Change the name of a rules item.
+ */
+function rules_item_change_name($item_type, $old_name, $new_name) {
+  if ($info = rules_get_items($item_type)) {
+    db_query("UPDATE {". $info['db_table'] ."} SET name = '%s' WHERE name = '%s' ", $new_name, $old_name);
+  }
+}
+
+/**
  * Deletes the given item from the database
  */
 function rules_item_delete($item_type, $name) {
Index: rules_admin/rules_admin.export.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_admin/Attic/rules_admin.export.inc,v
retrieving revision 1.1.2.9
diff -u -p -r1.1.2.9 rules_admin.export.inc
--- rules_admin/rules_admin.export.inc	25 Aug 2009 13:01:03 -0000	1.1.2.9
+++ rules_admin/rules_admin.export.inc	10 Oct 2010 17:01:52 -0000
@@ -62,10 +62,6 @@ function rules_item_rule_import(&$name, 
     }
   }
   if (isset($rule['#status']) && $rule['#status'] == 'custom' && (!isset($rules[$name]) || $rules[$name]['#label'] != $rule['#label'] || $rules[$name]['#set'] != $rule['#set'])) {
-    if (strpos($name, 'rules_') === 0) {
-      // Generate a new unique name for this rule, but only if it's "our rule".
-      $name = _rules_admin_rule_get_new_unique_name();
-    }
     $rule['#status'] = 'custom';
   }
   rules_import_hook($rule);
Index: rules_admin/rules_admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_admin/Attic/rules_admin.inc,v
retrieving revision 1.1.2.13
diff -u -p -r1.1.2.13 rules_admin.inc
--- rules_admin/rules_admin.inc	2 Nov 2009 11:34:33 -0000	1.1.2.13
+++ rules_admin/rules_admin.inc	10 Oct 2010 17:01:52 -0000
@@ -220,16 +220,6 @@ function rules_admin_get_categories($ite
 }
 
 /**
- * Gets an unique name for a newly added rule.
- */
-function _rules_admin_rule_get_new_unique_name() {
-  $id = variable_get('rules_counter', 0);
-  $id++;
-  variable_set('rules_counter', $id);
-  return 'rules_'. $id;
-}
-
-/**
  * Gets the label for the info of the given element by apply label callbacks.
  * Note that this is also used for argument infos.
  *
Index: rules_admin/rules_admin.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_admin/Attic/rules_admin.js,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 rules_admin.js
--- rules_admin/rules_admin.js	28 Aug 2009 16:37:49 -0000	1.1.2.2
+++ rules_admin/rules_admin.js	10 Oct 2010 17:01:52 -0000
@@ -13,3 +13,26 @@ Drupal.behaviors.RulesAdminSetAddArg = f
     });
   });
 };
+
+Drupal.behaviors.RulesAdminMachineName = function (context) {
+  // Add rule form machine-readable JS
+  $('#edit-label').addClass('processed').after(' <small class="rules-name-suffix">&nbsp;</small>');
+  $('#edit-name').parents('.form-item').hide();
+  $('#edit-label').keyup(function() {
+    var machine = $(this).val().toLowerCase().replace(/[^a-z0-9]/g, '_').replace(/_+/g, '_').replace(/^[^a-z]/, 'a');
+    if (machine !== '') {
+      $('#edit-name').val(machine);
+      $('.rules-name-suffix').empty().append(' ' + Drupal.t('Machine name:') + ' ' + machine + ' [').append($('<a href="#">'+ Drupal.t('Edit') +'</a>').click(function() {
+        $('#edit-name').parents('.form-item').show();
+        $('.rules-name-suffix').hide();
+        $('#edit-label').unbind('keyup');
+        return false;
+      })).append(']');
+    }
+    else {
+      $('#edit-name').val(machine);
+      $('.rules-name-suffix').text('');
+    }
+  });
+  $('#edit-label').keyup();
+}
Index: rules_admin/rules_admin.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_admin/Attic/rules_admin.module,v
retrieving revision 1.1.2.7
diff -u -p -r1.1.2.7 rules_admin.module
--- rules_admin/rules_admin.module	28 Aug 2009 19:11:16 -0000	1.1.2.7
+++ rules_admin/rules_admin.module	10 Oct 2010 17:01:53 -0000
@@ -260,6 +260,24 @@ function rules_admin_rule_title($text, $
   return t($text, array('@label' => $rule['#label']));
 }
 
+/**
+ * Validate the machine name.
+ */
+function rules_admin_validate_machine_name($item_type, $element_name, $machine_name) {
+  // Check that the machine name is valid. We only
+  if (!preg_match('/^[a-z][a-z0-9_]*$/', $machine_name)) {
+    form_set_error($element_name, t('Machine name must be alphanumeric and underscores only, and the first character must be a lower case letter.'));
+    return;
+  }
+  // Fetch information about table.
+  $info = rules_get_items($item_type);
+  // Check that the machine name doesn't exist.
+  $count = db_result(db_query("SELECT COUNT(*) FROM {" . $info['db_table'] . "} WHERE name = '%s'", 'rules_' . $machine_name));
+  if ($count) {
+    form_set_error($element_name, t('The given machine name already exists.'));
+  }
+}
+
 function rules_item_load($name, $item_type) {
   $items = rules_get_configured_items($item_type);
   if (!isset($items[$name])) {
Index: rules_admin/rules_admin.rule_forms.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_admin/Attic/rules_admin.rule_forms.inc,v
retrieving revision 1.1.2.9
diff -u -p -r1.1.2.9 rules_admin.rule_forms.inc
--- rules_admin/rules_admin.rule_forms.inc	2 Nov 2009 13:34:46 -0000	1.1.2.9
+++ rules_admin/rules_admin.rule_forms.inc	10 Oct 2010 17:01:53 -0000
@@ -72,12 +72,16 @@ function rules_admin_check_token() {
  * Returns the add rule form
  */
 function rules_admin_form_add_rule(&$form_state, $set_info = FALSE) {
-
+  drupal_add_js(drupal_get_path('module', 'rules_admin') . '/rules_admin.js');
   $form = rules_admin_form_rule_settings(array(), (boolean)$set_info);
   $form['settings']['set']['#default_value'] = $set_info['name'];
   return $form;
 }
 
+function rules_admin_form_add_rule_validate($form_id, &$form_state) {
+  rules_admin_validate_machine_name('rules', 'name', $form_state['values']['name']);
+}
+
 function rules_admin_form_add_rule_submit($form_id, &$form_state) {
   $rule = isset($form_state['proxy']) ? $form_state['proxy']->get_rule() : array('#type' => 'rule');
 
@@ -87,8 +91,8 @@ function rules_admin_form_add_rule_submi
   $rule['#categories'] = array_filter(array_map('trim', explode(',', $form_state['values']['categories'])));
   $rule['#status'] = 'custom';
 
-  //get an unique name
-  $rule_name = _rules_admin_rule_get_new_unique_name();
+  // Get the name of the rule.
+  $rule_name = 'rules_' . $form_state['values']['name'];
 
   rules_item_save('rules', $rule_name, $rule);
   rules_clear_cache();
@@ -115,6 +119,13 @@ function rules_admin_form_rule_settings(
     '#default_value' => isset($rule['#label']) ? $rule['#label'] : '',
     '#required' => TRUE,
   );
+  $form['settings']['name'] = array(
+    '#title' => t('Machine readable name'),
+    '#type' => 'textfield',
+    '#description' => t('Specify a unique name containing only alphanumeric characters, and underscores.'),
+    '#default_value' => isset($rule['#name']) ? $rule['#name'] : '',
+    '#required' => TRUE,
+  );
   $form['settings']['set'] = array(
     '#type' => 'select',
     '#default_value' => isset($rule['#set']) ? $rule['#set'] : '',
@@ -160,11 +171,10 @@ function rules_admin_form_rule_settings(
  * Returns the form for editing a rule
  */
 function rules_admin_form_edit_rule(&$form_state, $proxy) {
-
   $form_state['proxy'] = &$proxy;
   $rule = $proxy->get_rule();
   _rules_element_defaults($rule);
-
+  $rule['#name'] = drupal_substr($proxy->get_rule_name(), drupal_strlen('rules_'));
   $is_set = strpos($rule['#set'], 'event_') !== 0;
   $form = rules_admin_form_rule_settings($rule, $is_set);
   $form['settings']['#collapsed'] = TRUE;
@@ -192,15 +202,39 @@ function rules_admin_form_edit_rule(&$fo
   return $form;
 }
 
+function rules_admin_form_edit_rule_validate($form, &$form_state) {
+  // Get the name of the rule.
+  $name = $form_state['proxy']->get_rule_name();
+  // We only need to check this if the name differs.
+  if ('rules_' . $form_state['values']['name'] != $name) {
+    rules_admin_validate_machine_name('rules', 'name', $form_state['values']['name']);
+  }
+}
+
+/**
+ * Rules submit function. If you add your own submit handler,
+ * make sure that this function is called last, since it
+ * will call drupal_goto() if the rule name has been changed.
+ */
 function rules_admin_form_edit_rule_submit($form, &$form_state) {
   $rule_ref = &$form_state['proxy']->get_rule();
   foreach (array('label', 'active', 'weight', 'set') as $key) {
     $rule_ref['#'. $key] = $form_state['values'][$key];
   }
   $rule_ref['#categories'] = array_filter(array_map('trim', explode(',', $form_state['values']['categories'])));
-
+  // Set the new rule name if needed.
+  if ($form_state['values']['name'] != $form_state['proxy']->get_rule_name()) {
+    $name = 'rules_' . $form_state['values']['name'];
+    $form_state['proxy']->set_rule_name($name);
+    $redirect = '/admin/rules/rules/' . $name . '/edit';
+  }
   $form_state['proxy']->save_changes();
   drupal_set_message(t("The rule %label has been updated.", array('%label' => $rule_ref['#label'])));
+  // If we changed the name, then we need to redirect to the correct position.
+  if (isset($redirect)) {
+    drupal_goto($redirect);
+  }
+
 }
 
 /**
Index: rules_admin/rules_admin.rule_proxy.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_admin/Attic/rules_admin.rule_proxy.inc,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 rules_admin.rule_proxy.inc
--- rules_admin/rules_admin.rule_proxy.inc	19 Apr 2009 15:03:43 -0000	1.1.2.2
+++ rules_admin/rules_admin.rule_proxy.inc	10 Oct 2010 17:01:53 -0000
@@ -14,6 +14,7 @@ class rules_admin_rule_proxy {
 
   var $_rule;
   var $_rule_name;
+  var $_new_name;
   var $_counter;      //used when generating ids
   var $_variables;    //variables defined by previous rules
   var $map = array(); //stores the id => element map
@@ -53,6 +54,10 @@ class rules_admin_rule_proxy {
     return $this->_rule_name;
   }
 
+  function set_rule_name($name) {
+    $this->_new_name = $name;
+  }
+
   /**
    * Gets an element of the referenced rule by id
    */
@@ -88,7 +93,7 @@ class rules_admin_rule_proxy {
   function save_changes() {
     $rule = $this->get_rule();
     $orig_rule = $this->_rule;
-    if ($orig_rule != $rule) {
+    if ($orig_rule != $rule || isset($this->_new_name)) {
       $this->save_rule();
       rules_clear_cache();
     }
@@ -146,6 +151,11 @@ class rules_admin_rule_proxy {
     rules_sort_elements($rule['#actions']);
 
     rules_item_save('rules', $this->get_rule_name(), $rule);
+    if (isset($this->_new_name)) {
+      rules_item_change_name('rules', $this->get_rule_name(), $this->_new_name);
+      $this->_rule_name = $this->_new_name;
+      unset($this->_new_name);
+    }
   }
 
   /**
Index: rules_admin/rules_admin.sets.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_admin/Attic/rules_admin.sets.inc,v
retrieving revision 1.1.2.9
diff -u -p -r1.1.2.9 rules_admin.sets.inc
--- rules_admin/rules_admin.sets.inc	3 Aug 2009 16:42:25 -0000	1.1.2.9
+++ rules_admin/rules_admin.sets.inc	10 Oct 2010 17:01:53 -0000
@@ -113,8 +113,8 @@ function rules_item_rule_set_delete($set
  */
 function rules_admin_form_edit_rule_set(&$form_state, $set_info) {
   $form_state['set'] = $set_info;
+  $set_info['name'] = drupal_substr($set_info['name'], drupal_strlen('rules_'));
   $form = rules_admin_form_rule_set_settings($set_info);
-
   $form['active_header'] = array('#value' => '<br /><h3>'. t('Active rules') .'</h3>');
   $form['active'] = rules_admin_overview_table(array('set' => $set_info['name'], 'active' => TRUE));
   $form['active']['#suffix'] = '<br />';
@@ -131,7 +131,7 @@ function rules_admin_form_edit_rule_set(
 /**
  * Returns the form for the settings of a rule set
  */
-function rules_admin_form_rule_set_settings($set_info = array(), $add = FALSE) {
+function rules_admin_form_rule_set_settings($set_info = array()) {
   $form['settings'] = array(
     '#type' => 'fieldset',
     '#title' => t('Rule set settings'),
@@ -144,15 +144,13 @@ function rules_admin_form_rule_set_setti
     '#default_value' => isset($set_info['label']) ? $set_info['label'] : '',
     '#required' => TRUE,
   );
-  if ($add) {
-    $form['settings']['name'] = array(
-      '#title' => t('Machine readable name'),
-      '#type' => 'textfield',
-      '#description' => t('Specify a unique name containing only alphanumeric characters, and underscores.'),
-      '#default_value' => isset($set_info['name']) ? $set_info['name'] : '',
-      '#required' => TRUE,
-    );
-  }
+  $form['settings']['name'] = array(
+    '#title' => t('Machine readable name'),
+    '#type' => 'textfield',
+    '#description' => t('Specify a unique name containing only alphanumeric characters, and underscores.'),
+    '#default_value' => isset($set_info['name']) ? $set_info['name'] : '',
+    '#required' => TRUE,
+  );
   $form['settings']['categories'] = array(
     '#type' => 'textfield',
     '#title' => t('Categories'),
@@ -164,6 +162,17 @@ function rules_admin_form_rule_set_setti
   return $form;
 }
 
+function rules_admin_form_edit_rule_set_validate($form, &$form_state) {
+  if ($form_state['set']['name'] != 'rules_' . $form_state['values']['name']) {
+    rules_admin_validate_machine_name('rule_sets', 'name', $form_state['values']['name']);
+  }
+}
+
+/**
+ * Rule set submit function. If you add your own submit handler,
+ * make sure that this function is called last, since it
+ * will call drupal_goto() if the rule set name has been changed.
+ */
 function rules_admin_form_edit_rule_set_submit($form, &$form_state) {
   $set_info = $form_state['set'];
   $set_info['label'] = $form_state['values']['label'];
@@ -174,6 +183,11 @@ function rules_admin_form_edit_rule_set_
   unset($set_info['name']);
   rules_item_save('rule_sets', $form_state['set']['name'], $set_info);
   drupal_set_message(t("The rule set %label has been updated.", array('%label' => $set_info['label'])));
+  $name = 'rules_' . $form_state['values']['name'];
+  if ($form_state['set']['name'] != $name) {
+    rules_item_change_name('rule_sets', $form_state['set']['name'], $name);
+    drupal_goto('admin/rules/rule_sets/' . $name . '/edit');
+  }
 }
 
 /**
@@ -183,7 +197,7 @@ function rules_admin_form_add_rule_set(&
   //in case of non-js we degrade to a multistep form
   $set_info = isset($form_state['set']) ? $form_state['set'] : array('arguments' => array());
 
-  $form = rules_admin_form_rule_set_settings($set_info, TRUE);
+  $form = rules_admin_form_rule_set_settings($set_info);
   unset($form['settings']['button']);
 
   //add form for specifying arguments
@@ -224,10 +238,8 @@ function rules_admin_form_add_rule_set(&
  * Validates the set and builds it -> $form_state['set']
  */
 function rules_admin_form_add_rule_set_validate($form, &$form_state) {
-
-  if (!eregi('^[0-9a-z_]*$', $form_state['values']['name'])) {
-    form_set_error('name', t('The name may contain only digits, numbers and underscores.'));
-  }
+  // Validate machine name.
+  rules_admin_validate_machine_name('rule_sets', 'name', $form_state['values']['name']);
 
   //validate the arguments
   unset($form_state['values']['args']['rules_more']);
@@ -238,7 +250,7 @@ function rules_admin_form_add_rule_set_v
           form_set_error(implode('][', array('args', $i, $key)), t('All fields of an argument are required.'));
         }
       }
-      if (!eregi('^[0-9a-z_]*$', $values['name'])) {
+      if (!preg_match('/^[a-z][a-z0-9_]*$/', $values['name'])) {
         form_set_error(implode('][', array('args', $i, 'name')), t('The name may contain only digits, numbers and underscores.'));
       }
     }
