--- a/ur_autocomplete.module	2011-02-25 03:13:11.000000000 +0100
+++ b/ur_autocomplete.module	2011-06-25 18:17:11.760340396 +0200
@@ -1,4 +1,4 @@
-<?php 
+<?php
 
 /**
  * @file
@@ -31,180 +31,82 @@
 /**
  * Implementation of hook_widget_info().
  */
-function ur_autocomplete_widget_info() {
+
+function ur_autocomplete_field_widget_info() {
   return array(
     'ur_autocomplete' => array(
       'label' => t('Enhanced Userreference Autocomplete'),
-      'field types' => array('userreference'),
-      'multiple values' => CONTENT_HANDLE_MODULE,
-      'callbacks' => array(
-        'default value' => CONTENT_CALLBACK_DEFAULT,
+      'field types' => array('user_reference'),
+      'behaviors' => array(
+        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
       ),
     ),
   );
 }
 
-/**
- * Implementation of FAPI hook_elements().
- *
- * Any FAPI callbacks needed for individual widgets can be declared here,
- * and the element will be passed to those callbacks for processing.
- *
- * Drupal will automatically theme the element using a theme with
- * the same name as the hook_elements key.
- *
- * Autocomplete_path is not used by text_widget but other widgets can use it
- * (see nodereference and userreference).
- */
-function ur_autocomplete_elements() {
-  return array(
-    'ur_autocomplete' => array(
-      '#input' => TRUE,
-      '#columns' => array('name'),
-      '#delta' => 0,
-      '#process' => array('ur_autocomplete_process'),
-      '#autocomplete_path' => FALSE,
-    ),
-  );
-}
 
 /**
- * Implementation of hook_widget_settings().
+ * Implementation of hook_field_widget_form().
  */
-function ur_autocomplete_widget_settings($op, $widget) {
-  switch ($op) {
-    case 'form':
-      $form = array();
-      $match = isset($widget['autocomplete_match']) ? $widget['autocomplete_match'] : 'contains';
-      if ($widget['type'] == 'ur_autocomplete') {
-        $form['autocomplete_match'] = array(
-          '#type' => 'select',
-          '#title' => t('Autocomplete matching'),
-          '#default_value' => $match,
-          '#options' => array(
-            'starts_with' => t('Starts with'),
-            'contains' => t('Contains'),
-          ),
-          '#description' => t('Select the method used to collect autocomplete suggestions. Note that <em>Contains</em> can cause performance issues on sites with thousands of users.'),
-        );
-      }
-      else {
-        $form['autocomplete_match'] = array('#type' => 'hidden', '#value' => $match);
-      }
-      return $form;
-
-    case 'save':
-      return array('autocomplete_match');
-  }
-}
-
-/**
- * Implementation of hook_widget().
- */
-function ur_autocomplete_widget(&$form, &$form_state, $field, $items, $delta = 0) {
-  $element = array(
-    '#type' => $field['widget']['type'],
+function ur_autocomplete_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+  $element += array(
+    '#type' => 'textfield',
     '#default_value' => $items,
+    '#autocomplete_path' => 'ur_autocomplete/autocomplete/' . $field['field_name'],
     '#value_callback' => 'ur_autocomplete_value',
+    '#element_validate' => array('_ur_validate_element'),
   );
-  return $element;
+
+  return array('uid' => $element);
 }
 
+
 /**
  * Value for a userreference autocomplete element.
  *
  * Substitute in the user name for the user uid.
  */
 function ur_autocomplete_value($element, $edit = FALSE) {
+
   $names = array();
   $field_key  = $element['#columns'][0];
   foreach ($element['#default_value'] as $delta => $item) {
     if (!empty($item['uid'])) {
-      $n = db_result(db_query(db_rewrite_sql('SELECT u.name FROM {users} u WHERE u.uid = %d'), $item['uid']));
+      $n = db_query('SELECT u.name FROM {users} u WHERE u.uid = ?', array($item['uid']))->fetchField();
       $names[] = ur_autocomplete_encode($n);
     }
   }
   return array($field_key => implode(', ', $names));
 }
 
-/**
- * Process an individual element.
- *
- * Build the form element. When creating a form using FAPI #process,
- * note that $element['#value'] is already set.
- *
- */
-function ur_autocomplete_process($element, $edit, $form_state, $form) {
-  // The userreference autocomplete widget doesn't need to create its own
-  // element, it can wrap around the text_textfield element and add an autocomplete
-  // path and some extra processing to it.
-  // Add a validation step where the value can be unwrapped.
-  $field_name = $element['#field_name'];
-  $field = $form['#field_info'][$field_name];
-
-  if (!$field['multiple']) {
-    $autocomplete = 'userreference/autocomplete/';
-  }
-  else {
-    $autocomplete = 'ur_autocomplete/autocomplete/';
-  }
-  $field_key  = $element['#columns'][0];
-
-  $element[$field_key] = array(
-    '#type' => 'text_textfield',
-    '#default_value' => isset($element['#value']) ? $element['#value'] : '',
-    '#autocomplete_path' => $autocomplete . $element['#field_name'],
-    // The following values were set by the content module and need
-    // to be passed down to the nested element.
-    '#title' => $element['#title'],
-    '#required' => $element['#required'],
-    '#description' => $element['#description'],
-    '#field_name' => $element['#field_name'],
-    '#type_name' => $element['#type_name'],
-    '#delta' => $element['#delta'],
-    '#columns' => $element['#columns'],
-  );
-  if (empty($element[$field_key]['#element_validate'])) {
-    $element[$field_key]['#element_validate'] = array();
-  }
-  array_unshift($element[$field_key]['#element_validate'], 'ur_autocomplete_validate');
-
-  // Used so that hook_field('validate') knows where to flag an error.
-  $element['_error_element'] = array(
-    '#type' => 'value',
-    // Wrapping the element around a text_textfield element creates a
-    // nested element, so the final id will look like 'field-name-0-nid-nid'.
-    '#value' => implode('][', array_merge($element['#parents'], array($field_key, $field_key))),
-  );
-  return $element;
-}
 
 /**
  * Validate an autocomplete element.
  *
  * Remove the wrapper layer and set the right element's value.
- * This will move the nested value at 'field-name-0-nid-nid'
- * back to its original location, 'field-name-0-nid'.
  */
-function ur_autocomplete_validate($element, &$form_state) {
+function _ur_validate_element($element, &$form_state) {
+
   $field_name = $element['#field_name'];
-  $type_name = $element['#type_name'];
-  $field = content_fields($field_name, $type_name);
+
   $field_key = $element['#columns'][0];
-  $value = $element['#value'][$field_key];
+
+  // TODO: Why is $element['#value'] not set?!
+  $value = $form_state['input'][$field_name]['und'][$field_key];
+
+  // Loop through all of the comma-separated values.
   $values = array();
-  $uid = NULL;
-  $typed_names = ur_autocomplete_parse_input($value);
-  foreach ($typed_names as $delta => $name) {
-    if (!empty($name)) {
-      if (($u = user_load(array('name' => $name))) && ur_autocomplete_encode($name) != $u->name && $name != $u->name) {
-        form_error($element[$field_key], t('%name: name mismatch. Please check your selection.', array('%name' => t($field['widget']['label']))));
-      }
-      else {
+  $usernames = ur_autocomplete_parse_input($value);
+  foreach ($usernames as $delta => $name) {
+    $uid = db_query('SELECT uid FROM {users} WHERE name = ?', array($name))->fetchField();
+      if (!($u = user_load($uid)) || (ur_autocomplete_encode($name) != $u->name && $name != $u->name)) {
+        form_set_error($field_name, t('%name is not a registered user.', array('%name' => $name)));
+      } else {
         $values[] = array('uid' => $u->uid);
       }
-    }
   }
+
+  // Reassign the field's values.
   $new_parents = array();
   foreach ($element['#parents'] as $parent) {
     $value = $value[$parent];
@@ -219,62 +121,58 @@
 }
 
 /**
- * Implementation of hook_allowed_values().
- */
-function ur_autocomplete_allowed_values($field) {
-  $references = _userreference_potential_references($field);
-
-  $options = array();
-  foreach ($references as $key => $value) {
-    $options[$key] = $value['rendered'];
-  }
-  return $options;
-}
-
-/**
  * Retrieve a pipe delimited string of autocomplete suggestions
  *
  * Unholy union of taxonomy.module's taxonomy_autocomplete() and
- * userreference.module's userreference_autocomplete().
+ * user_reference.module's user_reference_autocomplete().
  */
 function ur_autocomplete_autocomplete($field_name, $string = '') {
+
   // The user enters a comma-separated list of users. We only autocomplete the last user.
-  $array = drupal_explode_tags($string);
+
+  $array = explode(', ', $string);
+
   // Fetch last user.
   $last_string = trim(array_pop($array));
 
+
   if ($last_string != '') {
-    $fields = content_fields();
-    $field = $fields[$field_name];
+
+    $field = field_info_field($field_name);
+
     $count = count($array);
-    if ($count && empty($field['multiple'])) {
-      drupal_json(array());
-      return;
+    if ($field['cardinality'] !== '-1' && $count >= $field['cardinality']) {
+      drupal_json_output(array()); exit;
     }
     $match = isset($field['widget']['autocomplete_match']) ? $field['widget']['autocomplete_match'] : 'contains';
     $matches = array();
 
     $prefix = $count ? implode(', ', $array) . ', ' : '';
+   // $suffix = $count ? '' : ', ';
+    $suffix =  ', ';
+
+    $options = array(
+      'string' => $last_string,
+      'match'  => 'contains',
+      'ids'  => false,
+      'limit'  => 3
+    );
+
+    $references = _user_reference_potential_references_standard($field, $options);
 
-    $references = _userreference_potential_references($field, $last_string, $match, array(), 10);
     foreach ($references as $id => $row) {
       $u = ur_autocomplete_encode($row['title']);
       // Add a class wrapper for a few required CSS overrides.
-      $matches[$prefix . $u] = '<div class="reference-autocomplete">'. $row['rendered'] . '</div>';
+      $matches[$prefix . $u . $suffix] = '<div class="reference-autocomplete">'. $row['rendered'] . '</div>';
     }
-    drupal_json($matches);
+    drupal_json_output($matches); exit;
   }
 }
 
 /**
  * Escapes commas and quotes in user names.
- * 
- * Based on code found in taxonomy.module
  *
- * @param string $string
- *  String to encode
- * @return string
- *  Encoded string
+ * Based on code found in taxonomy.module
  */
 function ur_autocomplete_encode($string) {
   $n = $string;
@@ -285,12 +183,8 @@
 }
 
 /**
- * Returns array containing all of the typed user names.
  *
- * @param string $typed_input
- *  What the user put into the autocomplete field
- * @return array
- *  Array containing each user name
+ * Returns array containing all of the typed user names.
  */
 function ur_autocomplete_parse_input($typed_input) {
   // This regexp allows the following types of user input:
