diff -p -N -U 2 -r /tmp/horde-2.1/imp/compose.php horde-2.1UM/imp/compose.php
--- /tmp/horde-2.1/imp/compose.php	Wed Jun  5 18:49:02 2002
+++ horde-2.1UM/imp/compose.php	Wed Aug 14 00:21:06 2002
@@ -79,161 +79,11 @@ function findBody(&$attachments)
 }
 
-/**
- * Behaves like explode() except that it ignores $delimiter if
- * preceded by a "\" character, or if it is inside single or double
- * quotes.
- */
-function rfc822_explode($delimiter, $str)
-{
-    $i = 0;
-    $match = 0;
-    $quotes = array('"', "'");
-    $in_quote = null;
-    $prev = null;
-
-    if (in_array($str[0], $quotes)) {
-        $in_quote = $str[0];
-    } elseif ($str[0] == $delimiter) {
-        $arr[] = '';
-        $match = 1;
-    }
-
-    for ($i = 1; $i < strlen($str); $i++) {
-        $char = $str[$i];
-        if (in_array($char, $quotes)) {
-            if ($prev !== "\\") {
-                if ($in_quote === $char) {
-                    $in_quote = null;
-                } elseif ($in_quote === null) {
-                    $in_quote = $char;
-                }
-            }
-        } elseif ($char == $delimiter && $prev !== "\\" && is_null($in_quote)) {
-            $arr[] = substr($str, $match, $i - $match);
-            $match = $i + 1;
-        }
-        $prev = $char;
-    }
-
-    if ($match != $i) {
-        // The string ended without a $delimiter
-        $arr[] = substr($str, $match, $i - $match);
-    }
-
-    return $arr;
-}
-
-/**
- * Use the Registry to expand names and, if $full is true, generate a
- * full, rfc822-valid address list, returning error information for
- * any address that is either not valid or fails to expand.
- */
-function expandAddresses($addrString, $full = false)
-{
-    if (!preg_match('|[^\s]|', $addrString)) {
-        return '';
-    }
-
-    global $registry, $prefs;
-
-    $addrString = preg_replace('/,\s+/', ',', $addrString);
-
-    include_once 'Mail/RFC822.php';
-    $parser = new Mail_RFC822(null, '@INVALID');
-
-    $src = explode("\t", $prefs->getValue('search_sources'));
-    if (count($src) == 1 && empty($src[0])) {
-        $src = array();
-    }
-
-    $search_fields = array();
-    $search_field_pref = $prefs->getValue('search_fields');
-    if (!empty($search_field_pref)) {
-        $field_arr = explode("\n", $prefs->getValue('search_fields'));
-        foreach ($field_arr as $field) {
-            $field = trim($field);
-            if (!empty($field)) {
-                $tmp = explode("\t", $field);
-                if (count($tmp) > 1) {
-                    $source = array_splice($tmp, 0, 1);
-                    $search_fields[$source[0]] = $tmp;
-                }
-            }
-        }
-    }
-
-    $arr = rfc822_explode(',', $addrString);
-    $results = $registry->call('contacts/search', array($arr, $src, $search_fields));
-    if (PEAR::isError($results)) {
-        return $results;
-    }
-    $i = 0;
-    $error = false;
-    $ambiguous = false;
-    $missing = array();
-    foreach ($results as $res) {
-        $tmp = $arr[$i];
-        if ($parser->validateMailbox(MIME::encodeAddress($tmp, null, ''))) {
-            // noop
-        } elseif (count($res) == 1) {
-            if ($full) {
-                if (strpos($res[0]['email'], ',') !== false) {
-                    $arr[$i] = $res[0]['name'] . ': ' . $res[0]['email'] . ';';
-                } else {
-                    list($mbox, $host) = explode('@', $res[0]['email']);
-                    $arr[$i] = imap_rfc822_write_address($mbox, $host, $res[0]['name']);
-                }
-            } else {
-                $arr[$i] = $res[0]['name'];
-            }
-        } elseif (count($res) > 1) {
-            // Handle the multiple case - we return an array with all found addresses.
-            $arr[$i] = array($arr[$i]);
-            foreach ($res as $one_res) {
-                if ($full) {
-                    if (strpos($one_res['email'], ',') !== false) {
-                        $arr[$i][] = $one_res['name'] . ': ' . $one_res['email'] . ';';
-                    } else {
-                        $mbox_host = explode('@', $one_res['email']);
-                        if (isset($mbox_host[1])) {
-                            $arr[$i][] = imap_rfc822_write_address($mbox_host[0], $mbox_host[1], $one_res['name']);
-                        }
-                    }
-                } else {
-                    $arr[$i][] = $one_res['name'];
-                }
-            }
-            $ambiguous = true;
-        } else {
-            // Handle the missing/invalid case - we should return error info
-            // on each address that couldn't be expanded/validated.
-            $error = true;
-            if (!$ambiguous) {
-                $arr[$i] = new PEAR_Error(null, null, null, null, $arr[$i]);
-                $missing[$i] = $arr[$i];
-            }
-        }
-        $i++;
-    }
-
-    if ($ambiguous) {
-        foreach ($missing as $i => $addr) {
-            $arr[$i] = $addr->getUserInfo();
-        }
-        return $arr;
-    } elseif ($error) {
-        return new PEAR_Error(_("Please resolve ambiguous or invalid addresses."), null, null, null, $res);
-    } else {
-        return implode(', ', $arr);
-    }
-}
-
 function expandAllAddresses()
 {
     global $to, $cc, $bcc, $to_errors, $cc_errors, $bcc_errors;
 
-    $to  = expandAddresses(Horde::getFormData('to', getAddressList('to')), true);
-    $cc  = expandAddresses(Horde::getFormData('cc', getAddressList('cc')), true);
-    $bcc = expandAddresses(Horde::getFormData('bcc', getAddressList('bcc')), true);
+    $to  = IMP::expandAddresses(Horde::getFormData('to', getAddressList('to')), true);
+    $cc  = IMP::expandAddresses(Horde::getFormData('cc', getAddressList('cc')), true);
+    $bcc = IMP::expandAddresses(Horde::getFormData('bcc', getAddressList('bcc')), true);
 
     if (is_array($to) || is_array($cc) || is_array($bcc)) {
@@ -421,4 +271,7 @@ switch ($actionID) {
  case NO_ACTION:
      $ACTION_TEXT = _("Message Composition");
+     if ($prefs->getValue('auto_expand') && (! $browser->hasFeature('iframes'))) {
+	 Horde::raiseMessage(_("Your browser does not support automatic name expansion.  Please use the Expand Names button."), HORDE_WARNING);
+     }
      break;

diff -p -N -U 2 -r /tmp/horde-2.1/imp/config/prefs.php.dist horde-2.1UM/imp/config/prefs.php.dist
--- /tmp/horde-2.1/imp/config/prefs.php.dist	Sun May 26 12:50:24 2002
+++ horde-2.1UM/imp/config/prefs.php.dist	Wed Aug 21 10:29:10 2002
@@ -114,5 +114,5 @@ $prefGroups['addressbooks'] = array(
     'label' => _("Addressbooks"),
     'desc' => _("Select addressbook sources for adding and searching for addresses."),
-    'members' => array('sourceselect')
+    'members' => array('auto_expand', 'sourceselect')
 );
 
@@ -728,4 +728,14 @@ $_prefs['nav_popup'] = array(
 
 // Addressbook preferences
+
+// Should names in the compose window be expanded automagically?
+$_prefs['auto_expand'] = array(
+    'value' => 1,
+    'locked' => false,
+    'shared' => false,
+    'type' => 'checkbox',
+    'desc' => _("Expand names in the compose window automatically in the background?")
+);
+
 
 // addressbook selection widget
diff -p -N -U 2 -r /tmp/horde-2.1/imp/expand.php horde-2.1UM/imp/expand.php
--- /tmp/horde-2.1/imp/expand.php	Wed Dec 31 19:00:00 1969
+++ horde-2.1UM/imp/expand.php	Tue Aug 20 16:26:23 2002
@@ -0,0 +1,33 @@
+<?php
+/*
+ * $Horde: imp/expand.php,v 1.6 2002/08/06 15:50:53 chuck Exp $
+ *
+ * Copyright 2002 Jan Schneider <jan@horde.org>
+ *
+ * See the enclosed file COPYING for license information (GPL).  If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ */
+
+$compress_control = 'none';
+$authentication = OP_HALFOPEN;
+
+define('IMP_BASE', dirname(__FILE__));
+require_once IMP_BASE . '/lib/base.php';
+
+$actionID = Horde::getFormData('actionID');
+
+if ($actionID == EXPAND_ADDRESSES) {
+    $field_name  = Horde::getFormData('field_name');
+    $field_value = Horde::getFormData('field_value');
+    $address = IMP::expandAddresses($field_value, true);
+}
+
+if ((PEAR::isError($address)) && ( $conf['msg']['add_maildomain_to_unexpandable'])) {
+    $addrString = preg_replace('/,\s+/', ',', $field_value);
+    $addrString = preg_replace('/\s+/', '.', $addrString);
+    $address = MIME::encodeAddress($addrString, null, $_SESSION['imp']['maildomain']);
+}
+
+require IMP_TEMPLATES . '/compose/expand.inc';
+
+?>
diff -p -N -U 2 -r /tmp/horde-2.1/imp/lib/IMP.php horde-2.1UM/imp/lib/IMP.php
--- /tmp/horde-2.1/imp/lib/IMP.php	Wed Jun  5 18:49:05 2002
+++ horde-2.1UM/imp/lib/IMP.php	Wed Aug 14 00:16:16 2002
@@ -542,4 +542,110 @@ class IMP {
     }
 
+/**
+ * Use the Registry to expand names and, if $full is true, generate a
+ * full, rfc822-valid address list, returning error information for
+ * any address that is either not valid or fails to expand.
+ */
+function expandAddresses($addrString, $full = false)
+{
+    if (!preg_match('|[^\s]|', $addrString)) {
+        return '';
+    }
+
+    global $registry, $prefs;
+
+    $addrString = preg_replace('/,\s+/', ',', $addrString);
+
+    include_once 'Mail/RFC822.php';
+    $parser = new Mail_RFC822(null, '@INVALID');
+
+    $src = explode("\t", $prefs->getValue('search_sources'));
+    if (count($src) == 1 && empty($src[0])) {
+        $src = array();
+    }
+
+    $search_fields = array();
+    $search_field_pref = $prefs->getValue('search_fields');
+    if (!empty($search_field_pref)) {
+        $field_arr = explode("\n", $prefs->getValue('search_fields'));
+        foreach ($field_arr as $field) {
+            $field = trim($field);
+            if (!empty($field)) {
+                $tmp = explode("\t", $field);
+                if (count($tmp) > 1) {
+                    $source = array_splice($tmp, 0, 1);
+                    $search_fields[$source[0]] = $tmp;
+                }
+            }
+        }
+    }
+
+    include_once(HORDE_BASE . '/lib/MIME.php');
+    $arr = MIME::rfc822_explode(',', $addrString);
+    $results = $registry->call('contacts/search', array($arr, $src, $search_fields));
+    if (PEAR::isError($results)) {
+        return $results;
+    }
+    $i = 0;
+    $error = false;
+    $ambiguous = false;
+    $missing = array();
+    foreach ($results as $res) {
+        $tmp = $arr[$i];
+        if ($parser->validateMailbox(MIME::encodeAddress($tmp, null, ''))) {
+            // noop
+        } elseif (count($res) == 1) {
+            if ($full) {
+                if (strpos($res[0]['email'], ',') !== false) {
+                    $arr[$i] = $res[0]['name'] . ': ' . $res[0]['email'] . ';';
+                } else {
+                    list($mbox, $host) = explode('@', $res[0]['email']);
+                    $arr[$i] = imap_rfc822_write_address($mbox, $host, $res[0]['name']);
+                }
+            } else {
+                $arr[$i] = $res[0]['name'];
+            }
+        } elseif (count($res) > 1) {
+            // Handle the multiple case - we return an array with all found addresses.
+            $arr[$i] = array($arr[$i]);
+            foreach ($res as $one_res) {
+                if ($full) {
+                    if (strpos($one_res['email'], ',') !== false) {
+                        $arr[$i][] = $one_res['name'] . ': ' . $one_res['email'] . ';';
+                    } else {
+                        $mbox_host = explode('@', $one_res['email']);
+                        if (isset($mbox_host[1])) {
+                            $arr[$i][] = imap_rfc822_write_address($mbox_host[0], $mbox_host[1], $one_res['name']);
+                        }
+                    }
+                } else {
+                    $arr[$i][] = $one_res['name'];
+                }
+            }
+            $ambiguous = true;
+        } else {
+            // Handle the missing/invalid case - we should return error info
+            // on each address that couldn't be expanded/validated.
+            $error = true;
+            if (!$ambiguous) {
+                $arr[$i] = new PEAR_Error(null, null, null, null, $arr[$i]);
+                $missing[$i] = $arr[$i];
+            }
+        }
+        $i++;
+    }
+
+    if ($ambiguous) {
+        foreach ($missing as $i => $addr) {
+            $arr[$i] = $addr->getUserInfo();
+        }
+        return $arr;
+    } elseif ($error) {
+        return new PEAR_Error(_("Please resolve ambiguous or invalid addresses."), null, null, null, $res);
+    } else {
+        return implode(', ', $arr);
+    }
+}
+
     /**
      * Return an array of folders. This is a wrapper around the
diff -p -N -U 2 -r /tmp/horde-2.1/imp/templates/compose/compose.inc horde-2.1UM/imp/templates/compose/compose.inc
--- /tmp/horde-2.1/imp/templates/compose/compose.inc	Tue May 28 17:56:16 2002
+++ horde-2.1UM/imp/templates/compose/compose.inc	Tue Aug 13 23:25:32 2002
@@ -142,5 +142,11 @@ function uniqSubmit()
 <?php else: ?>
 <tr>
-    <td align="left"><input type="text" size="60" tabindex="<?= $tabindex++ ?>" class="fixed" name="to" value="<?= htmlspecialchars($to) ?>" style="width:500px" /></td>
+    <td align="left"><input type="text" size="60" tabindex="<?= $tabindex++ ?>" class="fixed" name="to" value="<?= htmlspecialchars($to) ?>" style="width:500px"
+    <?php if ($browser->hasFeature('iframes')): ?>
+onchange="expandField(this)" /><span id='expandingto' style='color:red;visibility:hidden;'><?php echo _("Expanding...") ?></span>
+    <?php else: ?>
+    />
+    <?php endif; ?>
+    </td>
 <?php if ($conf['user']['online_help'] && $browser->hasFeature('javascript')): ?>
     <td align="right"><?= Help::link('imp', 'compose-to') ?></td>
@@ -198,5 +204,11 @@ function uniqSubmit()
 <?php else: ?>
 <tr>
-    <td align="left"><input type="text" size="60" tabindex="<?= $tabindex++ ?>" class="fixed" name="cc" value="<?= htmlspecialchars($cc) ?>" style="width:500px" /></td>
+    <td align="left"><input type="text" size="60" tabindex="<?= $tabindex++ ?>" class="fixed" name="cc" value="<?= htmlspecialchars($cc) ?>" style="width:500px"
+    <?php if ($browser->hasFeature('iframes')): ?>
+onchange="expandField(this)" /><span id='expandingcc' style='color:red;visibility:hidden;'><?php echo _("Expanding...") ?></span>
+    <?php else: ?>
+    />
+    <?php endif; ?>
+    </td>
 <?php if ($conf['user']['online_help'] && $browser->hasFeature('javascript')): ?>
     <td align="right"><?= Help::link('imp', 'compose-cc') ?></td>
@@ -254,5 +266,11 @@ function uniqSubmit()
 <?php else: ?>
 <tr>
-    <td align="left"><input type="text" size="60" tabindex="<?= $tabindex++ ?>" class="fixed" name="bcc" value="<?= htmlspecialchars($bcc) ?>" style="width:500px" /></td>
+    <td align="left"><input type="text" size="60" tabindex="<?= $tabindex++ ?>" class="fixed" name="bcc" value="<?= htmlspecialchars($bcc) ?>" style="width:500px" 
+    <?php if ($browser->hasFeature('iframes')): ?>
+onchange="expandField(this)" /><span id='expandingbcc' style='color:red;visibility:hidden;'><?php echo _("Expanding...") ?></span>
+    <?php else: ?>
+    />
+    <?php endif; ?>
+    </td>
 <?php if ($conf['user']['online_help'] && $browser->hasFeature('javascript')): ?>
     <td align="right"><?= Help::link('imp', 'compose-bcc') ?></td>
@@ -510,3 +528,6 @@ if (document.compose.to && document.comp
   <input type="hidden" name="spell_lang" value="" />
 </form>
+<?php endif; ?>
+<?php if ($prefs->getValue('auto_expand')): ?>
+<iframe id="autoexpand" name="autoexpand" style="width:0px;height:0px;border-width:0px" src="<?php echo Horde::url('expand.php') ?>"  ></iframe>
 <?php endif; ?>
diff -p -N -U 2 -r /tmp/horde-2.1/imp/templates/compose/expand.inc horde-2.1UM/imp/templates/compose/expand.inc
--- /tmp/horde-2.1/imp/templates/compose/expand.inc	Wed Dec 31 19:00:00 1969
+++ horde-2.1UM/imp/templates/compose/expand.inc	Tue Aug 13 12:46:06 2002
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
+<html>
+<head></head>
+<body>
+<script language="JavaScript" type="text/javascript">
+<!--
+<?php if (isset($address)): ?>
+<?php if (PEAR::isError($address)): ?>
+alert('<?php echo addslashes(sprintf(_("The field '%s' can't be expanded."), $field_name)) ?>');
+window.setTimeout('var status = window.parent.document.getElementById(\'expanding<?php echo $field_name ?>\'); status.style.visibility = \'hidden\'', 10);
+<?php elseif (is_array($address)): ?>
+alert('<?php echo addslashes(sprintf(_("More than one address found for field '%s'."), $field_name)) ?>');
+window.setTimeout('var status = window.parent.document.getElementById(\'expanding<?php echo $field_name ?>\'); status.style.visibility = \'hidden\'', 10);
+<?php else: ?>
+window.setTimeout('var status = window.parent.document.getElementById(\'expanding<?php echo $field_name ?>\'); status.style.visibility = \'hidden\';window.parent.document.compose.<?php echo $field_name ?>.value = \'<?php echo addslashes($address) ?>\';', 10);
+<?php endif; ?>
+<?php endif; ?>
+window.parent.busyExpanding = false;
+//-->
+</script>
+</body>
+</html>
+    
diff -p -N -U 2 -r /tmp/horde-2.1/imp/templates/compose/javascript.inc horde-2.1UM/imp/templates/compose/javascript.inc
--- /tmp/horde-2.1/imp/templates/compose/javascript.inc	Fri Apr 12 12:57:59 2002
+++ horde-2.1UM/imp/templates/compose/javascript.inc	Tue Aug 13 17:33:29 2002
@@ -163,4 +163,53 @@ function change_identity(id)
 }
 
+var busyExpanding = false;
+var searchFields  = new Array();
+var searchValues  = new Array();
+function expandField(field)
+{
+<?php if ($prefs->getValue('auto_expand')): ?>
+    if (document.frames) {
+        var iframe = document.frames['autoexpand'];
+    } else if (document.getElementById) {
+        var iframe = document.getElementById('autoexpand');
+    } else {
+        return;
+    }
+    if (!iframe) {
+        return;
+    }
+    if (!field) {
+        field = new Object();
+        field.name  = searchFields.slice(0, 1);
+        field.value = searchValues.slice(0, 1);
+    }
+    if (busyExpanding) {
+       searchFields[searchFields.length] = field.name;
+       searchValues[searchValues.length] = field.value;
+       window.setTimeout('expandField()', 500);
+       return;
+    }
+    busyExpanding = true;
+    var doc;
+    if (iframe.contentDocument) {
+      doc = iframe.contentDocument;
+    } else if (iframe.contentWindow) {
+      doc = iframe.contentWindow.document;
+    } else if (iframe.document) {
+      doc = iframe.document;
+    } else {
+      return true;
+    }
+    var url = '<?php echo Horde::url('expand.php?actionID=' . EXPAND_ADDRESSES, true) ?>';
+    url += '&field_name=' + escape(field.name);
+    url += '&field_value=' + escape(field.value);
+
+    var status = document.getElementById('expanding' + field.name);
+    status.style.visibility = "visible";
+    
+    doc.location.replace(url);
+<?php endif; ?>
+}
+
 //-->
 </script>
diff -p -N -U 2 -r /tmp/horde-2.1/lib/Browser.php horde-2.1UM/lib/Browser.php
--- /tmp/horde-2.1/lib/Browser.php	Wed May  1 13:46:06 2002
+++ horde-2.1UM/lib/Browser.php	Thu Aug 15 22:49:43 2002
@@ -38,4 +38,5 @@ class Browser {
                           'wml'        => false,
                           'images'     => true,
+			  'iframes'    => false,
                           'frames'     => true,
                           'tables'     => true,
@@ -97,4 +98,5 @@ class Browser {
                     $this->setFeature('javascript', 1.4);
                     $this->setFeature('dom');
+		    $this->setFeature('iframes');
                     $this->setQuirk('scrollbar_in_way');
                     break;
@@ -104,8 +106,10 @@ class Browser {
                         $this->setQuirk('break_disposition_header');
                     }
+		    $this->setFeature('iframes');
                     $this->setFeature('dom');
                     break;
                 case 4:
                     $this->setFeature('javascript', 1.2);
+		    $this->setFeature('iframes');
                     break;
                 case 3:
@@ -142,4 +146,9 @@ class Browser {
                     $this->setFeature('javascript', 1.4);
                     $this->setFeature('dom');
+                    if (preg_match('|rv:(.*)\)|', $this->agent, $revision)) {
+                        if ( $revision[1] >= 1 ) {
+                            $this->setFeature('iframes');
+                            }
+                        }
                     break;
                 case 4:
diff -p -N -U 2 -r /tmp/horde-2.1/lib/MIME.php horde-2.1UM/lib/MIME.php
--- /tmp/horde-2.1/lib/MIME.php	Sat Apr  6 11:19:19 2002
+++ horde-2.1UM/lib/MIME.php	Tue Aug 13 16:46:25 2002
@@ -221,4 +221,49 @@ class MIME {
     }
 
+
+    /**
+     * Behaves like explode() except that it ignores $delimiter if
+     * preceded by a "\" character, or if it is inside single or double
+     * quotes.
+     */
+    function rfc822_explode($delimiter, $str)
+    {
+	$i = 0;
+	$match = 0;
+	$quotes = array('"', "'");
+	$in_quote = null;
+	$prev = null;
+
+	if (in_array($str[0], $quotes)) {
+	    $in_quote = $str[0];
+	} elseif ($str[0] == $delimiter) {
+	    $arr[] = '';
+	    $match = 1;
+	}
+
+	for ($i = 1; $i < strlen($str); $i++) {
+	    $char = $str[$i];
+	    if (in_array($char, $quotes)) {
+		if ($prev !== "\\") {
+		    if ($in_quote === $char) {
+			$in_quote = null;
+		    } elseif ($in_quote === null) {
+			$in_quote = $char;
+		    }
+		}
+	    } elseif ($char == $delimiter && $prev !== "\\" && is_null($in_quote)) {
+		$arr[] = substr($str, $match, $i - $match);
+		$match = $i + 1;
+	    }
+	    $prev = $char;
+	}
+
+	if ($match != $i) {
+	    // The string ended without a $delimiter
+	    $arr[] = substr($str, $match, $i - $match);
+	}
+
+	return $arr;
+    }
 }
 ?>
