### Eclipse Workspace Patch 1.0
#P drupal
Index: modules/profile/profile.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.install,v
retrieving revision 1.8
diff -u -r1.8 profile.install
--- modules/profile/profile.install	28 Nov 2006 14:37:44 -0000	1.8
+++ modules/profile/profile.install	4 May 2007 17:25:15 -0000
@@ -8,12 +8,21 @@
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+      db_query("CREATE TABLE {profile_categories} (
+        cid int NOT NULL auto_increment,
+        title varchar(255) default NULL,
+        name varchar(128) default NULL,
+        explanation text,
+        weight tinyint(4) DEFAULT '0' NOT NULL,
+        PRIMARY KEY (cid)
+      ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
+      
       db_query("CREATE TABLE {profile_fields} (
         fid int NOT NULL auto_increment,
+        cid int NOT NULL DEFAULT '0',
         title varchar(255) default NULL,
         name varchar(128) default NULL,
         explanation TEXT,
-        category varchar(255) default NULL,
         page varchar(255) default NULL,
         type varchar(128) default NULL,
         weight tinyint DEFAULT '0' NOT NULL,
@@ -22,7 +31,7 @@
         visibility tinyint DEFAULT '0' NOT NULL,
         autocomplete tinyint DEFAULT '0' NOT NULL,
         options text,
-        KEY category (category),
+        KEY(cid),
         UNIQUE KEY name (name),
         PRIMARY KEY (fid)
       ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
@@ -71,6 +80,7 @@
  * Implementation of hook_uninstall().
  */
 function profile_uninstall() {
+  db_query('DROP TABLE {profile_categories}');
   db_query('DROP TABLE {profile_fields}');
   db_query('DROP TABLE {profile_values}');
   variable_del('profile_block_author_fields');
Index: modules/profile/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v
retrieving revision 1.200
diff -u -r1.200 profile.module
--- modules/profile/profile.module	30 Apr 2007 17:03:27 -0000	1.200
+++ modules/profile/profile.module	4 May 2007 17:25:16 -0000
@@ -79,24 +79,44 @@
     'description' => 'Create customizable fields for your users.',
     'page callback' => 'profile_admin_overview',
   );
-  $items['admin/user/profile/add'] = array(
+  $items['admin/user/profile/list'] = array(
+    'title' => 'List',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );  
+  $items['admin/user/profile/add/category'] = array(
+    'title' => 'Add category',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('profile_category_form'),
+    'type' => MENU_LOCAL_TASK,
+    'parent' => 'admin/user/profile',
+  );  
+  $items['admin/user/profile/add/field'] = array(
     'title' => 'Add field',
+    'page callback' => 'profile_admin_add_field_page',
+    'access callback' => '_profile_add_field_access',
+    'type' => MENU_LOCAL_TASK,
+    'parent' => 'admin/user/profile',
+  );
+  $items['admin/user/profile/edit/category'] = array(
+    'title' => 'Edit category',
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('profile_field_form'),
+    'page arguments' => array('profile_category_form'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/user/profile/autocomplete'] = array(
-    'title' => 'Profile category autocomplete',
-    'page callback' => 'profile_admin_settings_autocomplete',
+  $items['admin/user/profile/delete/category'] = array(
+    'title' => 'Delete category',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('profile_category_delete'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/user/profile/edit'] = array(
+  $items['admin/user/profile/edit/field'] = array(
     'title' => 'Edit field',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('profile_field_form'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/user/profile/delete'] = array(
+  $items['admin/user/profile/delete/field'] = array(
     'title' => 'Delete field',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('profile_field_delete'),
@@ -111,6 +131,14 @@
   return $items;
 }
 
+function _profile_add_field_access() {
+  // Access is allowed if there are existing categories
+  if ( _profile_categories()) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
 /**
  * Implementation of hook_block().
  */
@@ -205,6 +233,120 @@
 }
 
 /**
+ * Menu callback: Generate a form to add/edit a user profile category.
+ */
+function profile_category_form($arg = NULL) {
+  if (arg(3) == 'edit') {
+    if (is_numeric($arg)) {
+      $fid = $arg;
+
+      $edit = db_fetch_array(db_query('SELECT * FROM {profile_categories} WHERE cid = %d', $fid));
+
+      if (!$edit) {
+        drupal_not_found();
+        return;
+      }
+      drupal_set_title(t('edit %title', array('%title' => $edit['title'])));
+      $form['cid'] = array('#type' => 'value',
+        '#value' => $fid,
+      );
+    }
+    else {
+      drupal_not_found();
+      return;
+    }
+  } else {
+    $edit = array();
+  }
+  $edit += array(
+    'name' => '',
+    'title' => '',
+    'explanation' => '',
+    'weight' => '',
+  );
+  $form['fields'] = array('#type' => 'fieldset',
+    '#title' => t('Category settings'),
+  );
+  $form['fields']['title'] = array('#type' => 'textfield',
+    '#title' => t('Title'),
+    '#default_value' => $edit['title'],
+    '#description' => t('The title of the new category. The title will be shown to the user. An example title is "Personal information".'),
+    '#required' => TRUE,
+  );
+  $form['fields']['name'] = array('#type' => 'textfield',
+    '#title' => t('Form name'),
+    '#default_value' => $edit['name'],
+    '#description' => t('The name of the category. The form name is not shown to the user but used internally in the HTML code and URLs.
+Unless you know what you are doing, it is highly recommended that you prefix the form name with <code>profile_</code> to avoid name clashes with other categories. Spaces or any other special characters except dash (-) and underscore (_) are not allowed. An example name is "profile_favorite_color" or perhaps just "profile_color".'),
+    '#required' => TRUE,
+  );  
+  $form['fields']['explanation'] = array('#type' => 'textarea',
+    '#title' => t('Explanation'),
+    '#default_value' => $edit['explanation'],
+    '#description' => t('An optional explanation to go with the new category. The explanation will be shown to the user.'),
+  );
+  $form['fields']['weight'] = array('#type' => 'weight',
+    '#title' => t('Weight'),
+    '#default_value' => $edit['weight'],
+    '#delta' => 5,
+    '#description' => t('The weights define the order in which the categories are shown. Lighter categories are shown first.'),
+  );
+  $form['submit'] = array('#type' => 'submit',
+    '#value' => t('Save category'),
+  );
+  return $form;
+}
+
+/**
+ * Validate profile_category_form submissions.
+ */
+function profile_category_form_validate($form_id, $form_values) {
+  // Validate the 'field name':
+  if (preg_match('/[^a-zA-Z0-9_-]/', $form_values['name'])) {
+    form_set_error('name', t('The specified form name contains one or more illegal characters. Spaces or any other special characters except dash (-) and underscore (_) are not allowed.'));
+  }
+  // Validate the category name
+  if ($form_values['name'] == 'account' || in_array($form_values['name'], user_fields())) {
+    form_set_error('name', t('The specified form name is reserved for use by Drupal.'));
+  }
+
+  $args1 = array($form_values['title']);
+  $args2 = array($form_values['name']);
+  $query_suffix = '';
+
+  if (isset($form_values['cid'])) {
+    $args1[] = $args2[] = $form_values['cid'];
+    $query_suffix = ' AND cid != %d';
+  }
+
+  if (db_result(db_query("SELECT cid FROM {profile_categories} WHERE title = '%s'". $query_suffix, $args1))) {
+    form_set_error('title', t('The specified title is already in use.'));
+  }
+  if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'". $query_suffix, $args2))) {
+    form_set_error('name', t('The specified name is already in use.'));
+  }
+}
+/**
+ * Process profile_category_form submissions.
+ */
+function profile_category_form_submit($form_id, $form_values) {
+  if (!isset($form_values['cid'])) {
+    db_query("INSERT INTO {profile_categories} (title, name, explanation, weight) VALUES ('%s', '%s', '%s', %d)", $form_values['title'], $form_values['name'], $form_values['explanation'], $form_values['weight']);
+
+    drupal_set_message(t('The category has been created.'));
+    watchdog('profile', 'Profile category %title added.', array('%title' => $form_values['title']), WATCHDOG_NOTICE, l(t('view'), 'admin/user/profile'));
+  }
+  else {
+    db_query("UPDATE {profile_categories} SET title = '%s', name = '%s', explanation = '%s', weight = %d WHERE cid = %d", $form_values['title'], $form_values['name'], $form_values['explanation'], $form_values['weight'], $form_values['cid']);
+
+    drupal_set_message(t('The category has been updated.'));
+  }
+  cache_clear_all();
+  menu_rebuild();
+
+  return 'admin/user/profile';
+}
+/**
  * Menu callback: Generate a form to add/edit a user profile field.
  */
 function profile_field_form($arg = NULL) {
@@ -230,18 +372,13 @@
     }
   }
   else {
-    $types = _profile_field_types();
-    if (!isset($types[$arg])) {
-      drupal_not_found();
-      return;
-    }
     $type = $arg;
-    drupal_set_title(t('add new %type', array('%type' => $types[$type])));
+    drupal_set_title(t('add new %type', array('%type' => _profile_field_types($type))));
     $edit = array('name' => 'profile_');
     $form['type'] = array('#type' => 'value', '#value' => $type);
   }
   $edit += array(
-    'category' => '',
+    'cid' => '',
     'title' => '',
     'explanation' => '',
     'weight' => '',
@@ -253,10 +390,10 @@
   $form['fields'] = array('#type' => 'fieldset',
     '#title' => t('Field settings'),
   );
-  $form['fields']['category'] = array('#type' => 'textfield',
+  $form['fields']['cid'] = array('#type' => 'select',
     '#title' => t('Category'),
-    '#default_value' => $edit['category'],
-    '#autocomplete_path' => 'admin/user/profile/autocomplete',
+    '#default_value' => $edit['cid'],
+    '#options' => _profile_categories(),
     '#description' => t('The category the new field should be part of. Categories are used to group fields logically. An example category is "Personal information".'),
     '#required' => TRUE,
   );
@@ -340,14 +477,8 @@
   if (in_array($form_values['name'], user_fields())) {
     form_set_error('name', t('The specified form name is reserved for use by Drupal.'));
   }
-  // Validate the category:
-  if (!$form_values['category']) {
-    form_set_error('category', t('You must enter a category.'));
-  }
-  if ($form_values['category'] == 'account') {
-    form_set_error('category', t('The specified category name is reserved for use by Drupal.'));
-  }
-  $args1 = array($form_values['title'], $form_values['category']);
+
+  $args1 = array($form_values['title'], $form_values['cid']);
   $args2 = array($form_values['name']);
   $query_suffix = '';
 
@@ -356,7 +487,7 @@
     $query_suffix = ' AND fid != %d';
   }
 
-  if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE title = '%s' AND category = '%s'". $query_suffix, $args1))) {
+  if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE title = '%s' AND cid = %d". $query_suffix, $args1))) {
     form_set_error('title', t('The specified title is already in use.'));
   }
   if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'". $query_suffix, $args2))) {
@@ -369,13 +500,13 @@
  */
 function profile_field_form_submit($form_id, $form_values) {
   if (!isset($form_values['fid'])) {
-    db_query("INSERT INTO {profile_fields} (title, name, explanation, category, type, weight, required, register, visibility, autocomplete, options, page) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, %d, '%s', '%s')", $form_values['title'], $form_values['name'], $form_values['explanation'], $form_values['category'], $form_values['type'], $form_values['weight'], $form_values['required'], $form_values['register'], $form_values['visibility'], $form_values['autocomplete'], $form_values['options'], $form_values['page']);
+    db_query("INSERT INTO {profile_fields} (title, name, explanation, cid, type, weight, required, register, visibility, autocomplete, options, page) VALUES ('%s', '%s', '%s', %d, '%s', %d, %d, %d, %d, %d, '%s', '%s')", $form_values['title'], $form_values['name'], $form_values['explanation'], $form_values['cid'], $form_values['type'], $form_values['weight'], $form_values['required'], $form_values['register'], $form_values['visibility'], $form_values['autocomplete'], $form_values['options'], $form_values['page']);
 
     drupal_set_message(t('The field has been created.'));
-    watchdog('profile', 'Profile field %field added under category %category.', array('%field' => $form_values['title'], '%category' => $form_values['category']), WATCHDOG_NOTICE, l(t('view'), 'admin/user/profile'));
+    watchdog('profile', 'Profile field %field added under category %category.', array('%field' => $form_values['title'], '%category' => _profile_categories($form_values['category'])), WATCHDOG_NOTICE, l(t('view'), 'admin/user/profile'));
   }
   else {
-    db_query("UPDATE {profile_fields} SET title = '%s', name = '%s', explanation = '%s', category = '%s', weight = %d, required = %d, register = %d, visibility = %d, autocomplete = %d, options = '%s', page = '%s' WHERE fid = %d", $form_values['title'], $form_values['name'], $form_values['explanation'], $form_values['category'], $form_values['weight'], $form_values['required'], $form_values['register'], $form_values['visibility'], $form_values['autocomplete'], $form_values['options'], $form_values['page'], $form_values['fid']);
+    db_query("UPDATE {profile_fields} SET title = '%s', name = '%s', explanation = '%s', cid = %d, weight = %d, required = %d, register = %d, visibility = %d, autocomplete = %d, options = '%s', page = '%s' WHERE fid = %d", $form_values['title'], $form_values['name'], $form_values['explanation'], $form_values['cid'], $form_values['weight'], $form_values['required'], $form_values['register'], $form_values['visibility'], $form_values['autocomplete'], $form_values['options'], $form_values['page'], $form_values['fid']);
 
     drupal_set_message(t('The field has been updated.'));
   }
@@ -386,6 +517,44 @@
 }
 
 /**
+ * Menu callback; deletes a category and all related fields from all user profiles.
+ */
+function profile_category_delete($cid) {
+  $category = db_fetch_object(db_query("SELECT title FROM {profile_categories} WHERE cid = %d", $cid));
+  if (!$category) {
+    drupal_not_found();
+    return;
+  }
+  $form['cid'] = array('#type' => 'value', '#value' => $cid);
+  $form['title'] = array('#type' => 'value', '#value' => $category->title);
+
+  return confirm_form($form,
+    t('Are you sure you want to delete the category %category and all the fields in this category?', array('%category' => $category->title)), 'admin/user/profile',
+    t('This action cannot be undone. If users have entered values into this category\'s fields in their profile, these entries will also be deleted.'),
+    t('Delete'), t('Cancel'));
+}
+
+/**
+ * Process a category delete form submission.
+ */
+function profile_category_delete_submit($form_id, $form_values) {
+  // Delete all fields for this category first
+  $result = db_query('SELECT * FROM {profile_fields} WHERE cid = %d', $form_values['cid']);
+  while ($field = db_fetch_object($result)) {
+    db_query('DELETE FROM {profile_values} WHERE fid = %d', $field->fid);
+    drupal_set_message(t('The field %field has been deleted.', array('%field' => $field->title)));
+  }
+  db_query('DELETE FROM {profile_fields} WHERE cid = %d', $form_values['cid']);  
+  db_query('DELETE FROM {profile_categories} WHERE cid = %d', $form_values['cid']);
+  cache_clear_all();
+
+  drupal_set_message(t('The category %category has been deleted.', array('%category' => $form_values['title'])));
+  watchdog('profile', 'Profile category %category deleted.', array('%category' => $form_values['title']), WATCHDOG_NOTICE, l(t('view'), 'admin/user/profile'));
+
+  return 'admin/user/profile';
+}
+
+/**
  * Menu callback; deletes a field from all user profiles.
  */
 function profile_field_delete($fid) {
@@ -422,30 +591,58 @@
  * Menu callback; display a listing of all editable profile fields.
  */
 function profile_admin_overview() {
-
-  $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight');
+  // List categories
+  $output = '<h3>'. t('Category overview') .'</h3>';
+  $header = array(t('Title'), t('Name'), array('data' => t('Operations'), 'colspan' => '2'));
   $rows = array();
-  while ($field = db_fetch_object($result)) {
-    $rows[] = array(check_plain($field->title), $field->name, _profile_field_types($field->type), $field->category, l(t('edit'), "admin/user/profile/edit/$field->fid"), l(t('delete'), "admin/user/profile/delete/$field->fid"));
-  }
-  if (count($rows) == 0) {
-    $rows[] = array(array('data' => t('No fields defined.'), 'colspan' => '6'));
-  }
-
-  $header = array(t('Title'), t('Name'), t('Type'), t('Category'), array('data' => t('Operations'), 'colspan' => '2'));
-
-  $output  = theme('table', $header, $rows);
-  $output .= '<h2>'. t('Add new field') .'</h2>';
-  $output .= '<ul>';
-  foreach (_profile_field_types() as $key => $value) {
-    $output .= '<li>'. l($value, "admin/user/profile/add/$key") .'</li>';
+  $categories = profile_categories();
+  foreach ($categories as $category) {
+    $rows[] = array(array('data' => check_plain($category['title'])), $category['name'], l(t('edit'), 'admin/user/profile/edit/category/'.$category['cid']), l(t('delete'), 'admin/user/profile/delete/category/'.$category['cid']));
+  }
+  $output  .= theme('table', $header, $rows);
+  
+  // List fields
+  $output .= '<h3>'. t('Field overview') .'</h3>';
+  $header = array(t('Category'), t('Field'), t('Name'), t('Type'),  array('data' => t('Operations'), 'colspan' => '2'));
+  $rows = array();
+  foreach ($categories as $category) {
+    $result = db_query('SELECT * FROM {profile_fields} WHERE cid = %d ORDER BY weight', $category['cid']);
+    if ($count = db_num_rows($result)) {
+      for($i = 1; $i <= $count; $i++) {
+        $field = db_fetch_object($result);
+        $row = ($i == 1) ? array(array('data' => check_plain($category['title']), 'rowspan' => $count)): array();
+        $row[] = check_plain($field->title);
+        $row[] = $field->name;
+        $row[] = _profile_field_types($field->type);
+        $row[] = l(t('edit'), "admin/user/profile/edit/field/$field->fid");
+        $row[] = l(t('delete'), "admin/user/profile/delete/field/$field->fid");
+        $rows[] = $row;
+      } 
+    } else {
+      $rows[] = array(check_plain($category['title']), array('data' => t('No fields defined for this category.'), 'colspan' => '6'));
+    }
   }
-  $output .= '</ul>';
-
+  $output  .= theme('table', $header, $rows);
   return $output;
 }
 
 /**
+ * Menu callback; add field page
+ */
+function profile_admin_add_field_page($arg = NULL) {
+  $types = _profile_field_types();
+  if ($arg && isset($types[$arg])) {
+    return drupal_get_form('profile_field_form', $arg);
+  } else {
+    $output = '<ul>';
+    foreach ($types as $key => $value) {
+      $output .= '<li>'. l($value, "admin/user/profile/add/field/$key") .'</li>';
+    }
+    $output .= '</ul>';
+    return $output;    
+  }
+}
+/**
  * Menu callback; display a list of user information.
  */
 function profile_browse() {
@@ -611,15 +808,15 @@
 }
 
 function profile_view_profile($user) {
-
+  $categories = _profile_categories();
   profile_load_profile($user);
 
   // Show private fields to administrators and people viewing their own account.
   if (user_access('administer users') || $GLOBALS['user']->uid == $user->uid) {
-    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY category, weight', PROFILE_HIDDEN);
+    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY cid, weight', PROFILE_HIDDEN);
   }
   else {
-    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d AND visibility != %d ORDER BY category, weight', PROFILE_PRIVATE, PROFILE_HIDDEN);
+    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d AND visibility != %d ORDER BY cid, weight', PROFILE_PRIVATE, PROFILE_HIDDEN);
   }
 
   $fields = array();
@@ -630,7 +827,7 @@
         'value' => $value,
         'class' => $field->name,
       );
-      $fields[$field->category][$field->name] = $item;
+      $fields[$categories[$field->cid]][$field->name] = $item;
     }
   }
   return $fields;
@@ -655,14 +852,14 @@
   $w = 0;
   $fields = array();
   while ($field = db_fetch_object($result)) {
-    $category = $field->category;
-    if (!isset($fields[$category])) {
-      $fields[$category] = array('#type' => 'fieldset', '#title' => $category, '#weight' => $w++);
+    $category = db_fetch_object(db_query("SELECT * FROM {profile_categories} WHERE name = '%s'", $category));
+    if (!isset($fields[$category->name])) {
+      $fields[$category->name] = array('#type' => 'fieldset', '#title' => $category->title, '#weight' => $w++, '#description' => $category->explanation);
     }
     switch ($field->type) {
       case 'textfield':
       case 'url':
-        $fields[$category][$field->name] = array('#type' => 'textfield',
+        $fields[$category->name][$field->name] = array('#type' => 'textfield',
           '#title' => check_plain($field->title),
           '#default_value' => $edit[$field->name],
           '#maxlength' => 255,
@@ -674,7 +871,7 @@
         }
         break;
       case 'textarea':
-        $fields[$category][$field->name] = array('#type' => 'textarea',
+        $fields[$category->name][$field->name] = array('#type' => 'textarea',
           '#title' => check_plain($field->title),
           '#default_value' => $edit[$field->name],
           '#description' => _profile_form_explanation($field),
@@ -682,7 +879,7 @@
         );
         break;
       case 'list':
-        $fields[$category][$field->name] = array('#type' => 'textarea',
+        $fields[$category->name][$field->name] = array('#type' => 'textarea',
           '#title' => check_plain($field->title),
           '#default_value' => $edit[$field->name],
           '#description' => _profile_form_explanation($field),
@@ -690,7 +887,7 @@
         );
         break;
       case 'checkbox':
-        $fields[$category][$field->name] = array('#type' => 'checkbox',
+        $fields[$category->name][$field->name] = array('#type' => 'checkbox',
           '#title' => check_plain($field->title),
           '#default_value' => $edit[$field->name],
           '#description' => _profile_form_explanation($field),
@@ -705,7 +902,7 @@
             $options[$line] = $line;
           }
         }
-        $fields[$category][$field->name] = array('#type' => 'select',
+        $fields[$category->name][$field->name] = array('#type' => 'select',
           '#title' => check_plain($field->title),
           '#default_value' => $edit[$field->name],
           '#options' => $options,
@@ -714,7 +911,7 @@
         );
         break;
       case 'date':
-        $fields[$category][$field->name] = array('#type' => 'date',
+        $fields[$category->name][$field->name] = array('#type' => 'date',
           '#title' => check_plain($field->title),
           '#default_value' => $edit[$field->name],
           '#description' => _profile_form_explanation($field),
@@ -771,10 +968,10 @@
 }
 
 function profile_categories() {
-  $result = db_query("SELECT DISTINCT(category) FROM {profile_fields}");
+  $result = db_query("SELECT * FROM {profile_categories} ORDER BY weight");
   $data = array();
-  while ($category = db_fetch_object($result)) {
-    $data[] = array('name' => $category->category, 'title' => $category->category, 'weight' => 3);
+  while ($category = db_fetch_array($result)) {
+    $data[] = $category;
   }
   return $data;
 }
@@ -814,6 +1011,15 @@
   return $output;
 }
 
+function _profile_categories() {
+  $categories = array();
+  $result = db_query("SELECT * FROM {profile_categories}");
+  while($category = db_fetch_object($result)) {
+    $categories[$category->cid] = $category->title;
+  }
+  return $categories;
+}
+
 function _profile_field_types($type = NULL) {
   $types = array('textfield' => t('single-line textfield'),
                  'textarea' => t('multi-line textfield'),
@@ -831,34 +1037,19 @@
 
 function _profile_get_fields($category, $register = FALSE) {
   $args = array();
-  $sql = 'SELECT * FROM {profile_fields} WHERE ';
-  $filters = array();
+  $filters = $joins = array();
   if ($register) {
-    $filters[] = 'register = 1';
+    $filters[] = 'f.register = 1';
   }
   else {
-    // Use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues.
-    $filters[] = "LOWER(category) = LOWER('%s')";
+    $joins[] = ' INNER JOIN {profile_categories} c ON f.cid = c.cid';
+    $filters[] = "c.name = '%s'";
     $args[] = $category;
   }
   if (!user_access('administer users')) {
     $filters[] = 'visibility != %d';
     $args[] = PROFILE_HIDDEN;
   }
-  $sql .= implode(' AND ', $filters);
-  $sql .= ' ORDER BY category, weight';
+  $sql = 'SELECT f.* FROM {profile_fields} f '. implode(' ', $joins). ' WHERE '. implode(' AND ', $filters).' ORDER BY cid, weight';
   return db_query($sql, $args);
 }
-
-/**
- * Retrieve a pipe delimited string of autocomplete suggestions for profile categories
- */
-function profile_admin_settings_autocomplete($string) {
-  $matches = array();
-  $result = db_query_range("SELECT category FROM {profile_fields} WHERE LOWER(category) LIKE LOWER('%s%%')", $string, 0, 10);
-  while ($data = db_fetch_object($result)) {
-    $matches[$data->category] = check_plain($data->category);
-  }
-  print drupal_to_js($matches);
-  exit();
-}
