diff -urp /home/jonny/drupal/data_cck/data_cck.module data_cck/data_cck.module
--- /home/jonny/drupal/data_cck/data_cck.module	2010-06-08 22:13:07.000000000 +0100
+++ data_cck/data_cck.module	2010-08-04 02:27:55.000000000 +0100
@@ -15,6 +15,46 @@ if (module_exists('hierarchical_select')
   module_load_include('inc', 'data_cck', 'data_cck.hierarchical_select');
 }
 
+/**
+* Implementation of hook_menu().
+*/
+function data_cck_menu() {
+
+  $items['system/data_cck/autocomplete'] = array(
+    'type' => MENU_CALLBACK,
+    'page callback' => 'data_cck_autocomplete', 
+    'page arguments' => array(3, 4, 5, 6, 7),
+    'access callback' => TRUE,
+  );
+
+  return $items;
+}
+
+function data_cck_autocomplete($data_cck_field, $select_field, $search_type, $text) {
+  $options = array();
+
+  $ref_field = data_cck_get_field($data_cck_field);
+  $ref_table = data_cck_get_table($data_cck_field);
+  $select_field = data_cck_get_field($select_field);
+  
+  $search = ($search_type ? '%' : '') . $text . '%';
+  
+  $options_db = db_query("
+    SELECT %s as val, %s as display 
+    FROM {%s}
+    WHERE %s LIKE '%s'
+  ",
+    $ref_field, $select_field, $ref_table, $select_field, $search
+  );
+    
+  while ($row = db_fetch_array($options_db)) {
+    $options[$row['display']] = $row['display'];
+  }
+
+  print json_encode($options);
+  exit();
+}
+
 //==========================================//
 // DEFINING FIELD
 //==========================================//
@@ -50,8 +90,8 @@ function data_cck_get_field_options($uni
     
     if (!$meta) { // this happens when a regular table is "adopted" via Data module
       $query = db_query('describe {'.$tablename.'}');
-      while ($row = db_fetch_object($query)) {
-        $field_id=$row->Field;
+      while ($row = db_fetch_array($query)) {
+        $field_id=$row['Field'];
         
         // If we require a field with only unique values, and this field 
         // is not unique, then skip it and continue.
@@ -163,36 +203,81 @@ function data_cck_field($op, &$node, $fi
     // will do its own validation and you cannot make any 
     // assumptions about what kind of widget has been used, 
     // so don't validate widget values, only field values.
-    case 'validate':   
+    case 'validate':
       if (is_array($items)) {
-        foreach ($items as $delta => $item) {
+        foreach ($items as $delta => &$item) {
           // The error_element is needed so that CCK can 
           // set an error on the right sub-element when 
           // fields are deeply nested in the form.
           
           $reffield = data_cck_get_field($field['data_cck_field']);
           $table = data_cck_get_table($field['data_cck_field']);
+          $select_field = data_cck_get_field($field['widget']['select_field']);
           
           $error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
           if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
-          if (!empty($item['value'])) {
-            // Check to make sure the user has selected a valid reference
-            $result=db_query("show columns from {$table}");
-
-            while($columns = db_fetch_array($result)) {
-             $tablefields[]=$columns['Field'];
-            }
+          
+          if (!empty($item['display'])) {
+            $item['value'] = db_result(db_query("
+              SELECT %s as val
+              FROM {%s}
+              WHERE %s = '%s'
+            ",
+              $reffield, $table, $select_field, $item['display']
+            ));
             
-            $reffield = data_cck_get_field($field['data_cck_field']);
+            if (!$item['value'])
+              $error = TRUE;
+          }
+          elseif (!empty($item['value'])) {
             
-            if (!in_array($reffield,$tablefields)) {
-              form_set_error('', 'Submitted reference field does not exist in selected table.');  
+            $found = db_result(db_query("
+              SELECT COUNT(*)
+              FROM {%s}
+              WHERE %s = '%s'
+            ",
+              $table, $reffield, $item['value']
+            ));
+            
+            if (!$found) {
+              $error = TRUE;
             }
           }
+          
+          if ($error) {
+            form_set_error('', 'Submitted reference field does not exist in selected table.');  
+          }
         }
       }
       return $items;
 
+    case 'presave':
+      if (is_array($items)) {
+        foreach ($items as $delta => &$item) {
+          // The error_element is needed so that CCK can 
+          // set an error on the right sub-element when 
+          // fields are deeply nested in the form.
+          
+          $reffield = data_cck_get_field($field['data_cck_field']);
+          $table = data_cck_get_table($field['data_cck_field']);
+          $select_field = data_cck_get_field($field['widget']['select_field']);
+          
+          $error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
+          if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
+          
+          if (!empty($item['display'])) {
+            $item['value'] = db_result(db_query("
+              SELECT %s as val
+              FROM {%s}
+              WHERE %s = '%s'
+            ",
+              $reffield, $table, $select_field, $item['display']
+            ));
+          }
+        }
+      }
+      break;
+
     // We make sure that user-provided 
     // data is sanitized before being displayed.
     case 'sanitize':
@@ -344,6 +429,15 @@ function data_cck_widget_info() {
     ),
   );
   
+  $widgets['data_cck_autocomplete'] = array(
+    'label' => t('Autocomplete'),
+    'field types' => array('data_reference'),
+    'multiple values' => CONTENT_HANDLE_CORE,
+    'callbacks' => array(
+      'default value' => CONTENT_CALLBACK_DEFAULT,
+    ),
+  );
+  
   if (module_exists('hierarchical_select')) {
     $widgets['data_cck_hierarchical'] = array(
       'label' => t('Hierarchical Select'),
@@ -365,49 +459,74 @@ function data_cck_widget_settings($op, $
   switch ($op) {
     case 'form':
       $form = array();
-        
-      if ($widget['type'] == 'data_cck_select') {
-        $form['select_field'] = array(
-          '#type' => 'select',
-          '#title' => t('User Select Field'),
-          '#default_value' => $widget['select_field'] ? $widget['select_field'] : '',
-          '#options' => data_cck_get_field_options(),
-          '#description' => 'Which field should be made available to the user to select?',
-          '#attributes' => array('class' => 'data-cck-select-field select'),
-          '#required' => TRUE,
-        );
-      }
       
-      if ($widget['type'] == 'data_cck_hierarchical') {
-        $form['select_field'] = array(
-          '#type' => 'checkboxes',
-          '#title' => t('User Select Field'),
-          '#default_value' => $widget['select_field'] ? $widget['select_field'] : array(),
-          '#options' => data_cck_get_field_options(),
-          '#description' => 'Select all fields that should be part of the hierarchy.',
-          '#attributes' => array('class' => 'data-cck-select-field hierarchical'),
-          '#required' => TRUE,
-        );
+      switch ($widget['type']) {
+      
+        case 'data_cck_select':
+          $form['select_field'] = array(
+            '#type' => 'radios',
+            '#title' => t('User Select Field'),
+            '#default_value' => $widget['select_field'] ? $widget['select_field'] : '',
+            '#options' => data_cck_get_field_options(),
+            '#description' => t('Which field should be made available to the user to select?'),
+            '#attributes' => array('class' => 'data-cck-select-field select'),
+            '#required' => TRUE,
+          );
+          break;
+      
+        case 'data_cck_autocomplete':
+          $form['select_field'] = array(
+            '#type' => 'radios',
+            '#title' => t('User Select Field'),
+            '#default_value' => $widget['select_field'] ? $widget['select_field'] : '',
+            '#options' => data_cck_get_field_options(),
+            '#description' => t('Which field should the autocomplete be based on?'),
+            '#attributes' => array('class' => 'data-cck-select-field select'),
+            '#required' => TRUE,
+          );
+          $form['search_type'] = array(
+            '#type' => 'radios',
+            '#title' => t('Autocomplete search type'),
+            '#options' => array(
+              0 => t('Starts with'),
+              1 => t('Contains'),
+            ),
+            '#default_value' => isset($widget['search_type']) ? $widget['search_type'] : 0,
+            '#description' => t('Which search technique to use for autocompletion.'),
+          );
+          break;
+      
+        case 'data_cck_hierarchical':
+          $form['select_field'] = array(
+            '#type' => 'checkboxes',
+            '#title' => t('User Select Field'),
+            '#default_value' => $widget['select_field'] ? $widget['select_field'] : array(),
+            '#options' => data_cck_get_field_options(),
+            '#description' => t('Select all fields that should be part of the hierarchy.'),
+            '#attributes' => array('class' => 'data-cck-select-field hierarchical'),
+            '#required' => TRUE,
+          );
+          break;
       }
       
       return $form;
       
     case 'save':
-      return array('select_field');
+      return array('select_field', 'search_type');
 
     case 'validate':
       // validate the widget settings, make sure we are not picking mismatched fields and tables
       $table = data_cck_get_table($widget['data_cck_field']);
       
-      $result=db_query("show columns from {$table}");
+      $result = db_query("show columns from {$table}");
 
       while($columns = db_fetch_array($result)) {
-       $tablefields[]=$columns['Field'];
+       $tablefields[] = $columns['Field'];
       }
       
-      if ($widget['widget_type'] == "data_cck_select") {  // select
+      if ($widget['widget_type'] == "data_cck_select" || $widget['widget_type'] == "data_cck_autocomplete") {  // select
         $select_field = data_cck_get_field($widget['select_field']);
-        if (!in_array($select_field,$tablefields)) {
+        if (!in_array($select_field, $tablefields)) {
           form_set_error('', 'Selected field(s) does not exist in selected table.');
         }
       }
@@ -464,7 +583,7 @@ function data_cck_widget(&$form, &$form_
   if (!($field['data_cck_field'] && $field['widget']['select_field'])) {
     return array();
   }
-  
+
   // Pull out fieldnames and table names from settings
   $ref_field = data_cck_get_field($field['data_cck_field']);
   $ref_table = data_cck_get_table($field['data_cck_field']);
@@ -473,10 +592,10 @@ function data_cck_widget(&$form, &$form_
   // set field title
   if($field['widget']['type'] == 'data_cck_select') {
     $options_db = db_query("SELECT %s as val, %s as display FROM {".$ref_table."}",$ref_field,$select_field);
-      
+
     $options = array();
-    while ($row = db_fetch_object($options_db)) {
-      $options[$row->val] = $row->display;
+    while ($row = db_fetch_array($options_db)) {
+      $options[$row['val']] = $row['display'];
     }
     
     $element['value'] = array(
@@ -487,7 +606,29 @@ function data_cck_widget(&$form, &$form_
       '#attributes' => array('class' => 'data-cck'),
     );
   }
-  
+
+  if($field['widget']['type'] == 'data_cck_autocomplete') {
+
+    if (!empty($items[$delta]['value'])) {
+    
+      $display = db_result(db_query("
+        SELECT %s
+        FROM {%s}
+        WHERE %s = %s
+      ",
+        $select_field, $ref_table, $ref_field, $items[$delta]['value']
+      ));
+    }
+
+    $element['display'] = array(
+      '#type' => 'textfield',
+      '#title' => check_plain($field['widget']['label']),
+      '#autocomplete_path' => 'system/data_cck/autocomplete/' . 
+        $field['data_cck_field'] .'/' . $field['widget']['select_field'] . '/' . $field['widget']['search_type'],
+      '#default_value' => $display,
+    );
+  }
+
   if ($field['widget']['type'] == 'data_cck_hierarchical' && module_exists('hierarchical_select')) {
     // Filter our widget select_field settings of null values
     foreach ($select_field as $key => $select_field_item) {
@@ -510,9 +651,8 @@ function data_cck_widget(&$form, &$form_
         'save_lineage' => 1,
       ),
     );
-    
   }
-  
+
   // Used so that hook_field('validate') knows where to 
   // flag an error in deeply nested forms.
   if (empty($form['#parents'])) {
@@ -522,7 +662,6 @@ function data_cck_widget(&$form, &$form_
     '#type' => 'value',
     '#value' => implode('][', array_merge($form['#parents'], array('value'))),
   );
-  
+
   return $element;
 }
-?>
\ No newline at end of file
