diff -urp nodeaccess/nodeaccess.install nodeaccess_new/nodeaccess.install
--- nodeaccess/nodeaccess.install	2007-04-27 21:30:18.000000000 +0300
+++ nodeaccess_new/nodeaccess.install	2008-06-25 20:47:11.000000000 +0300
@@ -5,15 +5,20 @@ function nodeaccess_install() {
     case 'mysql':
     case 'mysqli':
       db_query("CREATE TABLE {nodeaccess} (
-          nid int(10) unsigned NOT NULL default '0',
-          gid int(10) unsigned NOT NULL default '0',
-          realm varchar(255) NOT NULL default '',
-          grant_view tinyint(1) unsigned NOT NULL default '0',
-          grant_update tinyint(1) unsigned NOT NULL default '0',
-          grant_delete tinyint(1) unsigned NOT NULL default '0',
-          PRIMARY KEY  (nid,gid,realm)
-        ) /*!40100 DEFAULT CHARACTER SET utf8 */;");
-      break;
+        nid int(10) unsigned NOT NULL default '0',
+        gid int(10) unsigned NOT NULL default '0',
+        realm varchar(255) NOT NULL default '',
+        grant_view tinyint(1) unsigned NOT NULL default '0',
+        grant_update tinyint(1) unsigned NOT NULL default '0',
+        grant_delete tinyint(1) unsigned NOT NULL default '0',
+        PRIMARY KEY (nid,gid,realm)
+      )"); /*!40100 DEFAULT CHARACTER SET utf8 */
+      db_query("CREATE TABLE {nodeaccess_role_alias} (
+        rid int(10) unsigned NOT NULL default '0',
+        name varchar(50) NOT NULL default '',
+        weight int(3) NOT NULL default '0'
+      )");
+    break;
     case 'pgsql':
       db_query("CREATE TABLE {nodeaccess} (
         nid int_unsigned NOT NULL default '0',
@@ -24,9 +29,14 @@ function nodeaccess_install() {
         grant_delete smallint_unsigned NOT NULL default '0',
         PRIMARY KEY (nid,gid,realm)
       )");
+      db_query("CREATE TABLE {nodeaccess_role_alias} (
+        rid int_unsigned NOT NULL default '0',
+        name varchar(50) NOT NULL default '',
+        weight smallint NOT NULL default '0'
+      )");
     break;
   }
-  // set up default permissions to be view for authenticated and anonymouse users
+  // set up default permissions to be view for authenticated and anonymous users
   $grants = array();
   $grants[] = array('gid' => 1, 'realm' => 'nodeaccess_rid', 'grant_view' => 1,
               'grant_update' => 0, 'grant_delete' => 0);
@@ -45,15 +55,15 @@ function nodeaccess_update_1() {
     case 'mysql':
     case 'mysqli':
       db_query("CREATE TABLE {nodeaccess} (
-          nid int(10) unsigned NOT NULL default '0',
-          gid int(10) unsigned NOT NULL default '0',
-          realm varchar(255) NOT NULL default '',
-          grant_view tinyint(1) unsigned NOT NULL default '0',
-          grant_update tinyint(1) unsigned NOT NULL default '0',
-          grant_delete tinyint(1) unsigned NOT NULL default '0',
-          PRIMARY KEY  (nid,gid,realm)
-        ) /*!40100 DEFAULT CHARACTER SET utf8 */;");
-      break;
+        nid int(10) unsigned NOT NULL default '0',
+        gid int(10) unsigned NOT NULL default '0',
+        realm varchar(255) NOT NULL default '',
+        grant_view tinyint(1) unsigned NOT NULL default '0',
+        grant_update tinyint(1) unsigned NOT NULL default '0',
+        grant_delete tinyint(1) unsigned NOT NULL default '0',
+        PRIMARY KEY (nid,gid,realm)
+      )"); /*!40100 DEFAULT CHARACTER SET utf8 */
+    break;
     case 'pgsql':
       db_query("CREATE TABLE {nodeaccess} (
         nid int_unsigned NOT NULL default '0',
@@ -91,7 +101,7 @@ function nodeaccess_update_1() {
     if ($default['grant_view'] != $row->grant_view &&
         $default['grant_update'] != $row->grant_update &&
         $default['grant_delete'] != $row->grant_delete) {
-      db_query("INSERT into {nodeaccess} (nid, gid, realm, grant_view, grant_update, grant_delete) values (%d, %d, '%s', %d, %d, %d)",
+      db_query("INSERT INTO {nodeaccess} (nid, gid, realm, grant_view, grant_update, grant_delete) values (%d, %d, '%s', %d, %d, %d)",
         $row->nid, $row->gid, $row->realm, $row->grant_view, $row->grant_update, $row->grant_delete);
     }
   }
@@ -102,16 +112,43 @@ function nodeaccess_update_2() {
   cache_clear_all(NULL, 'cache_menu');
 }
 
+function nodeaccess_update_3() {
+  switch ($GLOBALS['db_type']) {
+    case 'mysql':
+    case 'mysqli':
+      db_query("CREATE TABLE {nodeaccess_role_alias} (
+        rid int(10) unsigned NOT NULL default '0',
+        name varchar(50) NOT NULL default '',
+        weight int(3) NOT NULL default '0'
+      )");
+    break;
+    case 'pgsql':
+      db_query("CREATE TABLE {nodeaccess_role_alias} (
+        rid int_unsigned NOT NULL default '0',
+        name varchar(50) NOT NULL default '',
+        weight smallint NOT NULL default '0'
+      )");
+    break;
+  }
+  db_query("INSERT INTO {nodeaccess_role_alias} SELECT *, 0 FROM {role}");
+  $grantpref = array('view' => 1, 'edit' => 1, 'delete' => 1);
+  variable_set('nodeaccess-grants', $grantpref);
+}
+
 function nodeaccess_uninstall() {
   db_query("DELETE FROM {nodeaccess}");
-  variable_del('nodeaccess-types');
-  variable_del('nodeaccess-roles');
+  db_query("DELETE FROM {nodeaccess_role_alias}");
   variable_del('nodeaccess-priority');
+  variable_del('nodeaccess-preserve');
+  variable_del('nodeaccess-grants');
+  variable_del('nodeaccess-roles');
+  variable_del('nodeaccess-types');
   variable_del('nodeaccess_authors');
   foreach (node_get_types() as $type => $name) {
     variable_del('nodeaccess_' . $type);
   }
-  db_query('DROP TABLE {nodeaccess}'); 
+  db_query("DROP TABLE {nodeaccess}"); 
+  db_query("DROP TABLE {nodeaccess_role_alias}");
 }
 
 ?>
diff -urp nodeaccess/nodeaccess.module nodeaccess_new/nodeaccess.module
--- nodeaccess/nodeaccess.module	2007-06-08 19:24:51.000000000 +0300
+++ nodeaccess_new/nodeaccess.module	2008-06-25 15:43:04.000000000 +0300
@@ -80,17 +80,37 @@ function nodeaccess_grants_form($nid) {
   $users = $edit['uid'];
 
   $form['nid'] = array('#type' => 'value', '#value' => $nid);
-	
+
+  $allowedrole = variable_get('nodeaccess-roles', array());
+  $allowedgrant = variable_get('nodeaccess-grants', array());
+  $preserve = variable_get('nodeaccess-preserve', 1);
+
   // roles table
   if (is_array($roles)) {
     $form['rid'] = array('#tree' => TRUE);
-    $allowed = variable_get('nodeaccess-roles', array());
     foreach ($roles as $key => $field) {
-    if ($allowed[$key]) {
-      $form['rid'][$key]['name'] = array('#type' => 'hidden', '#value' => $field['name']);
-      $form['rid'][$key]['grant_view'] = array('#type' => 'checkbox', '#default_value' => $field['grant_view']);
-      $form['rid'][$key]['grant_update'] = array('#type' => 'checkbox', '#default_value' => $field['grant_update']);
-      $form['rid'][$key]['grant_delete'] = array('#type' => 'checkbox', '#default_value' => $field['grant_delete']);
+      if ($allowedrole[$key]) {
+        $form['rid'][$key]['name'] = array('#type' => 'hidden', '#value' => $field['name']);
+        if ($allowedgrant['view']) {
+          $form['rid'][$key]['grant_view'] = array('#type' => 'checkbox', '#default_value' => $field['grant_view']);
+        } else if ($preserve) {
+          $form['rid'][$key]['grant_view'] = array('#type' => 'hidden', '#value' => $field['grant_view']);
+        }
+        if ($allowedgrant['edit']) {
+          $form['rid'][$key]['grant_update'] = array('#type' => 'checkbox', '#default_value' => $field['grant_update']);
+        } else if ($preserve) {
+          $form['rid'][$key]['grant_update'] = array('#type' => 'hidden', '#value' => $field['grant_update']);
+        }
+        if ($allowedgrant['delete']) {
+          $form['rid'][$key]['grant_delete'] = array('#type' => 'checkbox', '#default_value' => $field['grant_delete']);
+        } else if ($preserve) {
+          $form['rid'][$key]['grant_delete'] = array('#type' => 'hidden', '#value' => $field['grant_delete']);
+        }
+      } else if ($preserve) {
+        $form['rid'][$key]['name'] = array('#type' => 'hidden', '#value' => $field['name']);
+        $form['rid'][$key]['grant_view'] = array('#type' => 'hidden', '#value' => $field['grant_view']);
+        $form['rid'][$key]['grant_update'] = array('#type' => 'hidden', '#value' => $field['grant_update']);
+        $form['rid'][$key]['grant_delete'] = array('#type' => 'hidden', '#value' => $field['grant_delete']);
       }
     }
   }
@@ -101,9 +121,21 @@ function nodeaccess_grants_form($nid) {
     foreach ($users as $key => $field) {
       $form['uid'][$key]['name'] = array('#type' => 'hidden', '#value' => $field['name']);
       $form['uid'][$key]['keep'] = array('#type' => 'checkbox', '#default_value' => $field['keep']);
-      $form['uid'][$key]['grant_view'] = array('#type' => 'checkbox', '#default_value' => $field['grant_view']);
-      $form['uid'][$key]['grant_update'] = array('#type' => 'checkbox', '#default_value' => $field['grant_update']);
-      $form['uid'][$key]['grant_delete'] = array('#type' => 'checkbox', '#default_value' => $field['grant_delete']);
+      if ($allowedgrant['view']) {
+        $form['uid'][$key]['grant_view'] = array('#type' => 'checkbox', '#default_value' => $field['grant_view']);
+      } else if ($preserve) {
+        $form['uid'][$key]['grant_view'] = array('#type' => 'hidden', '#value' => $field['grant_view']);
+      }
+      if ($allowedgrant['edit']) {
+        $form['uid'][$key]['grant_update'] = array('#type' => 'checkbox', '#default_value' => $field['grant_update']);
+      } else if ($preserve) {
+        $form['uid'][$key]['grant_update'] = array('#type' => 'hidden', '#value' => $field['grant_update']);
+      }
+      if ($allowedgrant['delete']) {
+        $form['uid'][$key]['grant_delete'] = array('#type' => 'checkbox', '#default_value' => $field['grant_delete']);
+      } else if ($preserve) {
+        $form['uid'][$key]['grant_delete'] = array('#type' => 'hidden', '#value' => $field['grant_delete']);
+      }
     }
   }
 
@@ -126,17 +158,38 @@ function nodeaccess_grants_form($nid) {
 }
 
 function theme_nodeaccess_grants_form($form) {
+  $allowedrole = variable_get('nodeaccess-roles', array());
+  $allowedgrant = variable_get('nodeaccess-grants', array());
+
   // role table
   $roles = element_children($form['rid']);
   if (count($roles) > 0) {
-    $header = array(t('Role'), t('View'), t('Edit'), t('Delete'));
+    $header = array();
+    $header[] = t('Role');
+    if ($allowedgrant['view']) {
+      $header[] = t('View');
+    }
+    if ($allowedgrant['edit']) {
+      $header[] = t('Edit');
+    }
+    if ($allowedgrant['delete']) {
+      $header[] = t('Delete');
+    }
     foreach ($roles as $key) {
-      $row = array();
-      $row[] = $form['rid'][$key]['name']['#value'] . drupal_render($form['rid'][$key]['name']);
-      $row[] = drupal_render($form['rid'][$key]['grant_view']);
-      $row[] = drupal_render($form['rid'][$key]['grant_update']);
-      $row[] = drupal_render($form['rid'][$key]['grant_delete']);
-      $rows[] = $row;
+      if ($allowedrole[$key]) {
+        $row = array();
+        $row[] = $form['rid'][$key]['name']['#value'] . drupal_render($form['rid'][$key]['name']);
+        if ($allowedgrant['view']) {
+          $row[] = drupal_render($form['rid'][$key]['grant_view']);
+        }
+        if ($allowedgrant['edit']) {
+          $row[] = drupal_render($form['rid'][$key]['grant_update']);
+        }
+        if ($allowedgrant['delete']) {
+          $row[] = drupal_render($form['rid'][$key]['grant_delete']);
+        }
+        $rows[] = $row;
+      }
     }
     $output .= theme('table', $header, $rows);
   }
@@ -154,14 +207,31 @@ function theme_nodeaccess_grants_form($f
   unset($rows);
   $users = element_children($form['uid']);
   if (count($users) > 0) {
-    $header = array(t('User'), t('Keep?'), t('View'), t('Edit'), t('Delete'));
+    $header = array();
+    $header[] = t('User');
+    $header[] = t('Keep?');
+    if ($allowedgrant['view']) {
+      $header[] = t('View');
+    }
+    if ($allowedgrant['edit']) {
+      $header[] = t('Edit');
+    }
+    if ($allowedgrant['delete']) {
+      $header[] = t('Delete');
+    }
     foreach ($users as $key) {
       $row = array();
       $row[] = $form['uid'][$key]['name']['#value'];
       $row[] = drupal_render($form['uid'][$key]['keep']);
-      $row[] = drupal_render($form['uid'][$key]['grant_view']);
-      $row[] = drupal_render($form['uid'][$key]['grant_update']);
-      $row[] = drupal_render($form['uid'][$key]['grant_delete']);
+      if ($allowedgrant['view']) {
+        $row[] = drupal_render($form['uid'][$key]['grant_view']);
+      }
+      if ($allowedgrant['edit']) {
+        $row[] = drupal_render($form['uid'][$key]['grant_update']);
+      }
+      if ($allowedgrant['delete']) {
+        $row[] = drupal_render($form['uid'][$key]['grant_delete']);
+      }
       $rows[] = $row;
     }
     $output .= theme('table', $header, $rows);
@@ -224,7 +294,7 @@ function nodeaccess_grants_form_submit($
 }
 
 /**
- * Popupate $edit. Loads all roles, gathers uids from node_access and search,
+ * Populate $edit. Loads all roles, gathers uids from node_access and search,
  * and calculates the grants for the users.
  *
  * This queries the node_access tables, but it doesn't write so hopefully that's ok
@@ -244,7 +314,7 @@ function _nodeaccess_populate($nid) {
   if (!$edit) {
     $edit = array();
     // load all roles
-    $result = db_query("SELECT rid, name, na.* FROM {role} LEFT JOIN {node_access} na ON rid=gid AND realm='%s' AND nid=%d ORDER BY name", 'nodeaccess_rid', $nid);
+    $result = db_query("SELECT r.rid, nra.name, na.* FROM {role} r LEFT JOIN {nodeaccess_role_alias} nra ON r.rid = nra.rid LEFT JOIN {node_access} na ON r.rid = na.gid AND na.realm='%s' AND na.nid=%d ORDER BY nra.weight, nra.name", 'nodeaccess_rid', $nid);
     while ($grant = db_fetch_object($result)) {
       $edit['rid'][$grant->rid] = array('name' => $grant->name, 'grant_view' => $grant->grant_view, 'grant_update' => $grant->grant_update, 'grant_delete' => $grant->grant_delete);
     }
@@ -313,20 +383,47 @@ function nodeaccess_admin() {
 
 function nodeaccess_admin_form() {
   $show = variable_get('nodeaccess-types', array());
-  $roles = user_roles();
-  $useroles = variable_get('nodeaccess-roles', array());
+  $roles = nodeaccess_get_role_aliases();
+  $allowedrole = variable_get('nodeaccess-roles', array());
+  $allowedgrant = variable_get('nodeaccess-grants', array());
 
   $form['priority'] = array('#type' => 'checkbox',
                             '#title' => t('Give node grants priority'),
                             '#default_value' => variable_get('nodeaccess-priority', 0),
                             '#description' => t('If you are only using this access control module, you can safely ignore this. If you are using multiple access control modules, and you want the grants given on individual nodes to override any grants given by other modules, you should check this box.'));
 
-  $form['role'] =  array('#type' => 'fieldset', '#collapsible' => TRUE, '#collapsed' => TRUE, '#title' => t('Allowed Roles'), '#tree' => TRUE, '#description' => t('The selected roles will be listed on individual node grants. If you wish for certain roles to be hidden from users on the node grants tab, make sure they are not selected here'));
+  // select whether to preserve hidden grants
+  $form['preserve'] = array('#type' => 'checkbox',
+                            '#title' => t('Preserve hidden grants'),
+                            '#default_value' => variable_get('nodeaccess-preserve', 1),
+                            '#description' => t('If you check this box, any hidden grants are preserved when you save grants. Otherwise all grants users are not allowed to view or edit are revoked on save.'));
+
+  // select grants you want to allow users to manage
+  $form['grant'] = array('#type' => 'fieldset',
+                         '#collapsible' => TRUE,
+                         '#collapsed' => TRUE,
+                         '#title' => t('Allowed Grants'),
+                         '#tree' => TRUE,
+                         '#description' => t('The selected grants will be listed on individual node grants. If you wish for certain grants to be hidden from users on the node grants tab, make sure they are not selected here.'));
+  $form['grant']['view'] = array('#type' => 'checkbox', '#title' => t('View'), '#default_value' => $allowedgrant['view']);
+  $form['grant']['edit'] = array('#type' => 'checkbox', '#title' => t('Edit'), '#default_value' => $allowedgrant['edit']);
+  $form['grant']['delete'] = array('#type' => 'checkbox', '#title' => t('Delete'), '#default_value' => $allowedgrant['delete']);
+
+  // select roles you want to allow users to manage, and the aliases and weights of those roles
+  $form['role'] = array('#type' => 'fieldset',
+                        '#collapsible' => TRUE,
+                        '#collapsed' => TRUE,
+                        '#title' => t('Allowed Roles'),
+                        '#tree' => TRUE,
+                        '#theme' => 'nodeaccess_admin_role_fieldset',
+                        '#description' => t('The selected roles will be listed on individual node grants. If you wish for certain roles to be hidden from users on the node grants tab, make sure they are not selected here. You may also provide an alias for each role to be displayed to the user and a weight to order them by. This is useful if your roles have machine-readable names not intended for human users.'));
   foreach ($roles as $id => $role) {
-    $form['role'][$id] = array('#type' => 'checkbox', '#title' => $role, '#default_value' => $useroles[$id]);
+    $form['role'][$id]['name'] = array('#type' => 'hidden', '#value' => $role['name']);
+    $form['role'][$id]['allow'] = array('#type' => 'checkbox', '#title' => $role['name'], '#default_value' => $allowedrole[$id]);
+    $form['role'][$id]['alias'] = array('#type' => 'textfield', '#default_value' => $role['alias'], '#size' => 50, '#maxlength' => 50);
+    $form['role'][$id]['weight'] = array('#type' => 'weight', '#default_value' => $role['weight'], '#delta' => 10);
   }
 
-
   foreach (node_get_types() as $type => $name) {
     $form['nodeaccess'][$type] = array('#type' => 'fieldset',
                                        '#collapsible' => TRUE,
@@ -361,6 +458,20 @@ function nodeaccess_admin_form() {
   return $form;
 }
 
+function theme_nodeaccess_admin_role_fieldset($form) {
+  $roles = element_children($form);
+  $header = array(t('Allow Role'), t('Alias'), t('Weight'));
+  foreach ($roles as $role) {
+    $row = array();
+    $row[] = drupal_render($form[$role]['allow']);
+    $row[] = drupal_render($form[$role]['alias']);
+    $row[] = drupal_render($form[$role]['weight']);
+    $rows[] = $row;
+  }
+  $output .= theme('table', $header, $rows);
+  return $output;
+}
+
 function theme_nodeaccess_admin_fieldset($form) {
   $output = drupal_render($form['show']);
   $roles = element_children($form['roles']);
@@ -383,7 +494,7 @@ function theme_nodeaccess_admin_fieldset
   $row[] = drupal_render($form['author']['grant_delete']);
 
   $output .= theme('table', $header, array($row));
-  $output .= '<small>' . t('The settings selected for the node author will define what permissions the node author has. This cannot be changed on individual node grants') . '</small>';
+  $output .= '<small>' . t('The settings selected for the node author will define what permissions the node author has. This cannot be changed on individual node grants.') . '</small>';
   return $output;
 }
 
@@ -391,11 +502,31 @@ function nodeaccess_admin_form_submit($f
 
   variable_set('nodeaccess-priority', $form_values['priority']);
 
+  variable_set('nodeaccess-preserve', $form_values['preserve']);
+
+  foreach ($form_values['grant'] as $id => $val) {
+    $grantpref[$id] = $val;
+  }
+
+  variable_set('nodeaccess-grants', $grantpref);
+
   foreach ($form_values['role'] as $id => $val) {
-    $pref[$id] = $val;
+    $rolepref[$id] = $val['allow'];
+    // save alias and weight only for allowed roles
+    if ($val['allow']) {
+      // if alias is empty, default to role name
+      if ($val['alias']) {
+        $aliaspref[$id]['name'] = $val['alias'];
+      } else {
+        $aliaspref[$id]['name'] = $val['name'];
+      }
+      $aliaspref[$id]['weight'] = $val['weight'];
+    }
   }
 
-  variable_set('nodeaccess-roles', $pref);
+  variable_set('nodeaccess-roles', $rolepref);
+
+  nodeaccess_save_role_aliases($aliaspref);
 
   $author_prefs = array();
   
@@ -509,9 +640,8 @@ function nodeaccess_node_type($op, $info
       break;
     case 'insert':
       // new node type, default to all viewing
-      $grants[] = array('gid' => 1, 'realm' => 'nodeaccess_rid', 'grant_view' => 1, 
-                  'grant_update' => 0, 'grant_delete' => 0);
-      $grants[] = array('gid' => 2, 'realm' => 'nodeaccess_rid', 'grant_view' => 1,                                        'grant_update' => 0, 'grant_delete' => 0);
+      $grants[] = array('gid' => 1, 'realm' => 'nodeaccess_rid', 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0);
+      $grants[] = array('gid' => 2, 'realm' => 'nodeaccess_rid', 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0);
       $author_prefs = variable_get('nodeaccess_authors', array());
       $author_prefs[$info->type] = array('grant_view' => 1, 'grant_update' => 1, 'grant_delete' => 1);
       variable_set('nodeaccess_' . $info->type, $grants); 
@@ -520,4 +650,29 @@ function nodeaccess_node_type($op, $info
   }
 }
 
+function nodeaccess_get_role_aliases() {
+  $aliases = array();
+  $sql = db_query('SELECT r.rid, r.name, a.name AS alias, a.weight FROM {role} r LEFT JOIN {nodeaccess_role_alias} a ON r.rid = a.rid ORDER BY r.rid');
+  while ($a = db_fetch_object($sql)) {
+    $aliases[$a->rid]['name'] = $a->name;
+    $aliases[$a->rid]['alias'] = $a->alias;
+    $aliases[$a->rid]['weight'] = $a->weight;
+  }
+  return $aliases;
+}
+
+function nodeaccess_save_role_aliases($edit) {
+  db_query('DELETE FROM {nodeaccess_role_alias}');
+  $success = TRUE;
+  if (is_array($edit)) {
+    foreach ($edit as $key => $value) {
+      $success = $success && db_query("INSERT INTO {nodeaccess_role_alias} (rid, name, weight) VALUES (%d, '%s', %d)", $key, $value['name'], $value['weight']);
+    }
+  }
+  if (!$success) {
+    drupal_set_message(t("There was a problem saving to the database"));
+  }
+  return $success;
+}
+
 ?>
