diff -upr terms_of_use.orig/terms_of_use.install terms_of_use/terms_of_use.install
--- terms_of_use.orig/terms_of_use.install	2009-03-23 14:19:34.000000000 -0700
+++ terms_of_use/terms_of_use.install	2010-03-29 12:27:16.000000000 -0700
@@ -10,5 +10,6 @@ function terms_of_use_uninstall() {
   variable_del('terms_of_use_fieldset_name');
   variable_del('terms_of_use_checkbox_label');
   variable_del('terms_of_use_node_id');
+  variable_del('terms_of_use_version');
 }
 
diff -upr terms_of_use.orig/terms_of_use.module terms_of_use/terms_of_use.module
--- terms_of_use.orig/terms_of_use.module	2009-03-23 14:20:27.000000000 -0700
+++ terms_of_use/terms_of_use.module	2010-03-31 20:51:12.482529294 -0700
@@ -29,13 +29,21 @@ function terms_of_use_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'terms_of_use.pages.inc',
   );
-  
+
   $items['terms_of_use/js'] = array(
     'page callback' => 'terms_of_use_js',
     'access arguments' => array('administer site configuration'),
     'type' => MENU_CALLBACK,
     'file' => 'terms_of_use.pages.inc',
   );
+
+  $items['_terms_of_use'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('terms_of_use_confirm'),
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+    'file' => 'terms_of_use.pages.inc',
+  );
   
   return $items;
 }
@@ -46,7 +54,7 @@ function terms_of_use_menu() {
  *
  */
 function terms_of_use_admin_settings() {
-  
+
   // Adding the fieldset for node specification.
   $form['terms_of_use_text'] = array(
     '#type' => 'fieldset',
@@ -84,9 +92,47 @@ function terms_of_use_admin_settings() {
     '#type' => 'textfield',
     '#title' => t('Label for the ckeckbox'),
     '#default_value' => variable_get('terms_of_use_checkbox_label', t('I agree with these terms.')),
-    '#description' => t('Type here something like "I agree with these terms." or "I CERTIFY THAT I AM OVER THE AGE OF 18 YEARS OLD.", without quotes. You can use the token @link to insert a link to the Terms in this label. For example, the label can be: "I agree with the @link.", without quotes. You may want to link to the Terms if you prefer not to show the full text of the Terms in the registration form. If you use the token, the Terms will not be shown.'),
+    '#description' => t('Type here something like "I agree with these terms." or "I CERTIFY THAT I AM OVER THE AGE OF 18 YEARS OLD.", without quotes.<br>You can use the token @link to insert a link to the Terms in this label, or @"Post Title" to insert a link to a post with title "Post Title" (without quotes).<br>For example, the label can be: "I agree with the @link.", without quotes. You may want to link to the Terms if you prefer not to show the full text of the Terms in the registration form.<br>If you use any tokens, the Terms will not be shown.'),
+  );
+  $form['terms_of_use_form']['terms_of_use_node_height'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Limit height of the full text of the Terms'),
+    '#default_value' => variable_get('terms_of_use_node_height', ''),
+    '#description' => t('Leave empty to show Terms text in full height. Type here something like "20em" or "120px" without quotes to set the height of the full text and use vertical scrollbar.'),
+  );
+  
+  $form['terms_of_use_advanced'] = array(
+    '#type' => 'fieldset',
+  );
+  $version = variable_get('terms_of_use_version', 1);
+  $options = array(
+    $version => t('@version (current version)', array('@version' => $version)),
+    $version + 1 => t('@version (add a new version)', array('@version' => $version + 1)),
+  );
+  
+  $form['terms_of_use_advanced']['terms_of_use_version'] = array(
+    '#type' => 'radios',
+    '#title' => t('Terms of use version'),
+    '#description' => t('WARNING: Changing this value will force all logged-in users to accept the new terms of use before they can do anything else on the site.'),
+    '#options' => $options,
+    '#default_value' => $version,
   );
 
+  //Show a preview of terms of use form
+  $preview_form = array();
+  $form_state = array();
+  terms_of_use_form_user_register_alter($preview_form, $form_state);
+  unset($preview_form['terms_of_use']['I_agree']['#element_validate']);
+
+  $form['terms_of_use_preview'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Preview'),
+    '#description' => t('This is a preview of current configuration. To see how your changes will look, you have to save configuration.'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $form['terms_of_use_preview'] += $preview_form;
+
   return system_settings_form($form);
 }
 
@@ -99,12 +145,12 @@ function terms_of_use_admin_settings_val
   $nid = $form_state['values']['terms_of_use_node_id'];
   if (isset($nid)) {
     if (empty($nid)) {
-      form_set_error('terms_of_use_node_id', t('You must specify a node <em>nid</em>.'));   
+      form_set_error('terms_of_use_node_id', t('You must specify a node <em>nid</em>.'));
     }
     else {
       $node = node_load($nid);
       if ($node == FALSE) {
-        form_set_error('terms_of_use_node_id', t('No post was published with <em>nid</em> !nid.', array('!nid' => $nid))); 
+        form_set_error('terms_of_use_node_id', t('No post was published with <em>nid</em> !nid.', array('!nid' => $nid)));
       }
       else {
         variable_set('terms_of_use_node_title', $node->title);
@@ -129,6 +175,19 @@ function terms_of_use_admin_settings_val
  * Implementation of hook_form_form_id_alter().
  */
 function terms_of_use_form_user_register_alter(&$form, $form_state) {
+  // Only change the registration form. There is also form at /admin/user/user/create path, but we leave it alone.
+  if (isset($form['#action']) && strpos($form['#action'], url('user/register')) !== 0)
+    return;
+  
+  $height = variable_get('terms_of_use_node_height', '');
+  if ($height) {
+    $css = '#terms-of-use { height:' . check_plain($height) .'; overflow:auto; }';
+    drupal_set_html_head('<style type="text/css">' . $css . '</style>');
+    // Revert the styling so print shows full text.
+    $css = '#terms-of-use { height:auto; overflow:visible; }';
+    drupal_set_html_head('<style type="text/css" media="print">' . $css . '</style>');
+  }
+  
   // Adding the fieldset.
   $form['terms_of_use'] = array(
     '#type' => 'fieldset',
@@ -146,17 +205,14 @@ function terms_of_use_form_user_register
     }
   }
   $node = node_load($terms_of_use_node_id);
-  
+
   // Will we show the full text of the Terms or only provide a link to the Terms.
   // Reading the checkbox label to find out.
-  $show_terms = TRUE;
   $checkbox_label = check_plain(variable_get('terms_of_use_checkbox_label', t('I agree with these terms.')));
-  if (strpos($checkbox_label, '@link') !== FALSE) {
-    $checkbox_label = str_replace('@link', l(check_plain($node->title), 'node/'. $node->nid), $checkbox_label);
-    $show_terms = FALSE;
-  }  
-    
-  // Adding the Terms of Use to the fieldset. 
+  $show_terms = (strpos($checkbox_label, '@link') === FALSE && strpos($checkbox_label, '@&quot;') === FALSE);
+  $checkbox_label = theme('terms_of_use_checkbox_label', $checkbox_label, $node->title, $node->nid, $show_terms);
+
+  // Adding the Terms of Use to the fieldset.
   if ($show_terms && $node) {
     $terms = node_prepare($node);
     $form['terms_of_use']['terms_of_use_text'] = array(
@@ -167,9 +223,11 @@ function terms_of_use_form_user_register
   // Adding the checkbox to the fieldset.
   $form['terms_of_use']['I_agree'] = array(
     '#type' => 'checkbox',
-    '#title' => $checkbox_label . '&nbsp;<span class="form-required" title="' . t('This field is required') . '">*</span>',
+    '#title' => $checkbox_label,
     '#required' => TRUE,
+    // The following adds "required" validation to the checkbox (patches core missing functionality as of D6.16)
     '#element_validate' => array('_terms_of_use_validate_checkbox'),
+    '#return_value' => variable_get('terms_of_use_version', 1),
   );
 
   return $form;
@@ -180,11 +238,65 @@ function terms_of_use_form_user_register
  */
 function _terms_of_use_validate_checkbox($form, &$form_state) {
   $value = $form_state['values']['I_agree'];
-  if ($value == 0) {
+  if ($value != variable_get('terms_of_use_version', 1)) {
     form_set_error('I_agree', t('You must agree with the !terms to get an account.', array('!terms' => variable_get('terms_of_use_fieldset_name', t('Terms of Use')))));
   }
 }
 
+/**
+ * Implementation of hook_user().
+ */
+function terms_of_use_user($op, &$edit, &$account, $category = NULL) {
+  switch ($op) {
+    case 'insert':
+//drupal_set_message(print_r($account, TRUE));
+//drupal_set_message(print_r($edit, TRUE));
+      
+      if (isset($edit['I_agree'])) {
+        $edit['terms_of_use'] = $edit['I_agree'];
+        unset ($edit['I_agree']);
+      }
+//drupal_set_message(print_r($account, TRUE));
+      break;
+  }
+}
+
+function _terms_of_use_i18n() {
+  $variables = array(
+// Rely on node translations.
+//    'terms_of_use_node_title',
+//    'terms_of_use_node_id',
+    'terms_of_use_fieldset_name',
+    'terms_of_use_checkbox_label',
+  );
+  $i18n_variables = variable_get('i18n_variables', array());
+  $i18n_variables = array_merge($i18n_variables, $variables);
+  variable_set('i18n_variables', $i18n_variables);
+}
+
+/**
+ * Implementation of hook_init().
+ */
+function terms_of_use_init() {
+  global $user;
+
+  // http://drupal.org/node/313272#comment-2786004
+  // This is a performance hit. We need it here because $conf in settings.php 
+  // overrides database variable value in variable_init().
+  // Faster performance will be achieved if the variables in 
+  // _terms_of_use_i18n() are added to $conf in settings.php.
+  _terms_of_use_i18n();
+  
+  if ($user->uid > 0) {
+    $terms_of_use_version = variable_get('terms_of_use_version', 1);
+    $terms_of_use_node_id = variable_get('terms_of_use_node_id', '');
+    if ($terms_of_use_node_id > 0 && (!isset($user->terms_of_use) || $user->terms_of_use < $terms_of_use_version)) {
+      if (arg(0) != '_terms_of_use') {
+        drupal_goto('_terms_of_use', drupal_get_destination());
+      }
+    }
+  }
+}
 
 /**
  * Implementation of hook_theme().
@@ -194,6 +306,9 @@ function terms_of_use_theme() {
     'terms_of_use' => array(
       'arguments' => array('terms' => NULL, 'node' => NULL),
     ),
+    'terms_of_use_checkbox_label' => array(
+      'arguments' => array('checkbox_label' => '', 'node_title' => '', 'node_nid' => 0, 'show_terms' => TRUE),
+    ),
   );
 }
 
@@ -215,3 +330,55 @@ function theme_terms_of_use($terms, $nod
 
   return $output;
 }
+
+/**
+ * Output the terms of service checkbox label.
+ *
+ * @param $checkbox_label
+ *  The label from the admin form saved in the DB.
+ * @param $node_title
+ *  The Terms of Use $node title, in case we need it.
+ * @param $node_nid
+ *  The Terms of Use $node nid, in case we need it.
+ * @param $show_terms
+ *  If false, we must add the link to the Terms of Use node
+ * @return
+ *  HTML output.
+ * @ingroup themeable
+ */
+function theme_terms_of_use_checkbox_label($checkbox_label = '', $node_title = '', $node_nid = 0, $show_terms = TRUE){
+  if (!strlen($checkbox_label)) { return ''; }
+
+  $output = $checkbox_label;
+  if (!$show_terms && $node_nid && strlen($node_title)) {
+    //We are linking to the terms instead, replace the link.
+    $output = str_replace('@link', l(check_plain($node_title), 'node/'. $node_nid), $checkbox_label);
+  }
+  // Go through the $output string, replacing @"Terms Link" with an actual node link
+  $output = str_replace('&quot;', '"', $output);
+  while ( $i < strlen($output) ) {
+    if (substr($output, $i, 2) == '@"') {
+      $start = $i+2;
+      $end = strpos($output, '"', $start);
+      while(substr($output, $end-1, 1) == "\\") {
+        $end = strpos($output, '"', $end+1);
+      }
+      $title = substr($output, $start, ($end-$start));
+      $node = node_load(array('title' => str_replace('\\"', '"', $title) ) );
+      if ($node) {
+        $link = l($node->title, 'node/' . $node->nid);
+        $output = str_replace('@"'.$title.'"', $link, $output);
+        $i += strlen($link) - 1;
+      }
+    }
+    $i++;
+  }
+
+  // The following adds "required" styling to the checkbox (patches core missing functionality as of D6.16)
+  // Checkbox validate handles denoting required checkboxes for us
+  if (!module_exists('checkbox_validate')) {
+    $output .= '&nbsp;<span class="form-required" title="' . t('This field is required') . '">*</span>';
+  }
+
+  return $output;
+}
diff -upr terms_of_use.orig/terms_of_use.pages.inc terms_of_use/terms_of_use.pages.inc
--- terms_of_use.orig/terms_of_use.pages.inc	2008-06-06 14:19:28.000000000 -0700
+++ terms_of_use/terms_of_use.pages.inc	2010-03-29 19:08:50.000000000 -0700
@@ -12,7 +12,9 @@
 function terms_of_use_autocomplete($string = '') {
   $matches = array();
   if ($string != '') {
-    $result = db_query_range(db_rewrite_sql("SELECT nr.title FROM {node_revisions} nr WHERE LOWER(nr.title) LIKE LOWER('%%%s%%')"), $string, 0, 10);
+    $result = db_query_range(
+      db_rewrite_sql("SELECT nr.title FROM {node_revisions} nr WHERE LOWER(nr.title) LIKE LOWER('%%%s%%')", 'nr'),
+	  $string, 0, 10);
 
     while ($node = db_fetch_object($result)) {
       $matches[$node->title] = $node->title;
@@ -39,6 +41,7 @@ function terms_of_use_js() {
     $form['terms_of_use_text']['terms_of_use_node_id'] = array(
       '#type' => 'textfield',
       '#title' => t('Node id where your Terms of Use are published'),
+      '#value' => variable_get('terms_of_use_node_id', ''),
       '#default_value' => variable_get('terms_of_use_node_id', ''),
       '#description' => t('Node <em>id</em> of the page or story (or blog entry or book page) where your Terms of Use are published.'),
     );  
@@ -50,6 +53,7 @@ function terms_of_use_js() {
     $form['terms_of_use_text']['terms_of_use_node_title'] = array(
       '#type' => 'textfield',
       '#title' => t('Title of the post where your Terms of Use are published'),
+      '#value' => variable_get('terms_of_use_node_title', ''),
       '#default_value' => variable_get('terms_of_use_node_title', ''),
       '#description' => t('Node <em>title</em> of the page or story (or blog entry or book page) where your Terms of Use are published.'),
       '#autocomplete_path' => 'node/autocomplete',
@@ -71,4 +75,40 @@ function terms_of_use_js() {
   $output = drupal_render($form['terms_of_use_text']);
   
   drupal_json(array('status' => TRUE, 'data' => $output));      
-}
\ No newline at end of file
+}
+
+/**
+ * Display the terms of use, when a user needs to confirm them after registering.
+ */
+function terms_of_use_confirm($form_state) {
+  $form = array();
+  terms_of_use_form_user_register_alter($form, $form_state);
+  drupal_set_title($form['terms_of_use']['#title']);
+  $changes = '.';	// No changes, put a period to finish sentence.
+// [iva2k] FIXME: combine a list of changes into $changes:
+//$changes = ':<ul><li>Item 1</ul>';
+  $form['intro'] = array(
+    '#type' => 'item',
+	'#value' => t('There were recent changes to !terms!changes You must accept below to continue.',
+	   array(
+	     '!terms' => variable_get('terms_of_use_fieldset_name', t('Terms of Use')),
+		 '!changes' => $changes,
+	   )),
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Continue'),
+    '#weight' => 50, 
+  );
+  
+  return $form;
+}
+
+function terms_of_use_confirm_submit($form, &$form_state) {
+  global $user;
+  $edit = array(
+    'terms_of_use' => $form_state['values']['I_agree'],
+  );
+  user_save($user, $edit);
+}
+
