--- /Users/vectoroc/Desktop/htmltidy/htmltidy.module
+++ htmltidy.module
@@ -31,18 +31,14 @@
 /**
  * Implementation of hook_menu().
  */
-function htmltidy_menu($may_cache) {
-  $items = array();
-  if ($may_cache) {
-    $items[] = array(
-      'path' => 'admin/settings/htmltidy',
-      'title' => t('HTML Tidy'),
-      'description' => t('Configure settings for HTML Tidy.'),
-      'callback' => 'drupal_get_form',
-      'callback arguments' => 'htmltidy_settings',
-      'access' => user_access('administer htmltidy')
-    );
-  }
+function htmltidy_menu() {
+  $items['admin/settings/htmltidy'] = array(
+    'title' => t('HTML Tidy'),
+    'description' => t('Configure settings for HTML Tidy.'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('htmltidy_settings'),
+    'access arguments' => array('administer htmltidy')
+  );
   return $items;
 }
 
@@ -53,7 +49,7 @@
  *
  * @return The formatted help text.
  */
-function htmltidy_help($section) {
+function htmltidy_help($section, $arg) {
   switch($section) {
     case 'admin/help#htmltidy':
       return t("
@@ -128,8 +124,6 @@
       break;
 
   }
-
-  return t($output);
 }
 
 /**
@@ -159,7 +153,7 @@
    * documentation for tidy (http://www.w3.org/People/Raggett/tidy/), or weird
    * stuff starts to happen.
    */
-  if (variable_get('htmltidy_indent', 1))           $args[] = '--indent auto';
+  if (variable_get('htmltidy_indent', 1))           $args[] = '-i';
   if (!variable_get('htmltidy_verbose', 0))         $args[] = '-q';
   if (!variable_get('htmltidy_wrapphp', 1))         $args[] = '--wrap-php no';
   if (!variable_get('htmltidy_tidymark', 1))        $args[] = '--tidy-mark no';
@@ -184,7 +178,6 @@
   $args[] = '--doctype '. variable_get('htmltidy_doctype', 'auto');
   $args[] = '-wrap '. variable_get('htmltidy_wordwrap', 0);
   $args[] = '-utf8';
-  $args[] = '-modify'; // modify the input file instead of outputting to stdout.
 
   htmltidy_run($input, $args, $output, $errors, $warnings);
 
@@ -210,7 +203,7 @@
 /**
  * Implimentation of hook_filter()
  */
-function htmltidy_filter($op, $delta = 0, $format = NULL, $text = '') {
+function htmltidy_filter($op, $delta = 0, $format = NULL, $text = '', $cache_id = 0) {
   switch ($op) {
     case 'list':
       return array(0 => t('HTML Tidy'));
@@ -293,7 +286,7 @@
 }
 
 // TODO: need to make sure teaser is valid...
-function htmltidy_nodeapi(&$node, $op, $a3 = NULL, $page = NULL) {
+function htmltidy_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
   if (variable_get('htmltidy_process_input', TRUE)) {
     switch ($op) {
     case 'prepare':
@@ -304,40 +297,48 @@
         form_set_error('body', theme('item_list', $errors));
       }
       break;
+    }
+  }
+}
 
-    case 'validate':
-      global $htmltidy_filter;
+function htmltidy_form_alter(&$form, &$form_state, $form_id)
+{
+  $base_id = 'node_form';
+  if (substr($form_id, -1 * strlen($base_id)) == $base_id) {
+	$form['#validate'][] = 'htmltidy_node_validate';
+  }
+}
+
+function htmltidy_node_validate($form, &$form_state) {
+  global $htmltidy_filter;
+
+  if (variable_get('htmltidy_process_input', TRUE) && $form_state['values']['body']) {
+	$body = $form_state['values']['body'];
+    // call the filters so if they're using html tidy as a filter it'll
+    // be called in order
+    check_markup($body, $form_state['values']['format']);
+    if (isset($htmltidy_filter['filtered']) && $htmltidy_filter['filtered']) {
+      $errors = $htmltidy_filter['errors'];
+      $warnings = $htmltidy_filter['warnings'];
+    }
+    else {
+	  $clean = htmltidy_fragment($body, $errors, $warnings);
+	  form_set_value(array('#parents' => array('body')), $clean, $form_state);
+    }
 
-      if ($node->body) {
-        // call the filters so if they're using html tidy as a filter it'll
-        // be called in order
-        check_markup($node->body, $node->format);
-        if (isset($htmltidy_filter['filtered']) && $htmltidy_filter['filtered']) {
-          $errors = $htmltidy_filter['errors'];
-          $warnings = $htmltidy_filter['warnings'];
-        }
-        else {
-          $clean = htmltidy_fragment($node->body, $errors, $warnings);
-          form_set_value(array('#parents' => array('body')), $clean);
-        }
-
-        if ($errors || $warnings) {
-          $message = '<p>Original body:</p><pre>'. htmlentities($node->body) .'</pre>';
-          if ($errors) {
-            $message .= theme('item_list', array_map('htmlentities', $errors));
-            form_set_error('body', $message);
-          }
-          if ($warnings) {
-            drupal_set_message(theme('item_list', array_map('htmlentities', $warnings)));
-          }
-        }
+    if ($errors || $warnings) {
+      $message = '<p>Original body:</p><pre>'. htmlentities($body) .'</pre>';
+      if ($errors) {
+        $message .= theme('item_list', array_map('htmlentities', $errors));
+        form_set_error('body', $message);
+      }
+      if ($warnings) {
+        drupal_set_message(theme('item_list', array_map('htmlentities', $warnings)));
       }
-      break;
     }
   }
 }
 
-
 /**
  * Drupal hook that returns an array of valid permissions for the htmltidy module.
  *
@@ -551,38 +552,43 @@
     $output = '';
     return 2;
   }
-
-  // write input to a file because tidy doesn't take input from stdin.
-  $dirtyFilename = tempnam(file_directory_temp(), 'drup');
-  $f = fopen($dirtyFilename, 'w');
-  fwrite($f, $input);
-  fclose($f);
-
-  // warnings are saved to file
-  $warningsFilename = tempnam(file_directory_temp(), 'warn');
-  $args[] = '-f ' . $warningsFilename;
-
+  
   // Run Tidy with the right options.
-  $command = $tidypath .' '. implode(' ', $args) .' '. $dirtyFilename;
-  system($command, $return_value);
-
+  $command = $tidypath .' '. implode(' ', $args);
+  
+  $descriptorspec = array(
+    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
+    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
+    2 => array("pipe", "w")   // stderr is a file to write to
+  );
+  
+  $process = proc_open($command, $descriptorspec, $pipes);
+  fwrite($pipes[0], $input);
+  fclose($pipes[0]);
+  $stdout = stream_get_contents($pipes[1]);
+  $stderr = stream_get_contents($pipes[2]);
+  $return_value = proc_close($process);  
+  
   // return_value 0 means success. 1 means warning. 2 means error, the file
   // will be there, but not have been touched.
   switch ($return_value) {
   case 0:
     $warnings = $errors = array();
-    $output = file_get_contents($dirtyFilename);
+    $output = $stdout;
     break;
 
   case 1:
     $errors = array();
-    $warnings = array_map('trim', file($warningsFilename));
-    $output = file_get_contents($dirtyFilename);
+    foreach(array_filter(split("\n", $stderr)) as $line) { 
+      $warnings[] = trim($line); 
+    }
+    $output = $stdout;
     break;
 
   case 2:
     // separate errors and warnings into two different arrays
-    foreach(file($warningsFilename) as $line) {
+    
+    foreach(array_filter(split("\n", $stdout)) as $line) {
       $line = trim($line);
       if (preg_match('|^line \d+ column \d+ - Warning:|', $line)) {
         $warnings[] = $line;
@@ -595,9 +601,5 @@
     break;
   }
 
-  // delete the temporary files.
-  unlink($dirtyFilename);
-  unlink($warningsFilename);
-
   return $return_value;
 }
