diff --git a/payment/uc_google_checkout/uc_google_checkout.admin.inc b/payment/uc_google_checkout/uc_google_checkout.admin.inc
index 4205002..b2f4388 100644
--- a/payment/uc_google_checkout/uc_google_checkout.admin.inc
+++ b/payment/uc_google_checkout/uc_google_checkout.admin.inc
@@ -96,21 +96,22 @@ function uc_google_checkout_settings($form, &$form_state) {
   return system_settings_form($form);
 }
 
-function uc_google_checkout_shipping_settings($form) {
+function uc_google_checkout_shipping_settings($form, &$form_state) {
   $form['help'] = array(
     '#value' => t("For merchant-calculated shipping, Google Checkout requires a fallback price in case it can't get a calculated shipping rate in time. When the cart request is sent to Google Checkout, Ubercart pre-calculates the shipping rates using this default address. Choose a location that will cause an average shipping cost to be returned."),
   );
 
-  $form['uc_google_checkout_delivery_city'] = uc_textfield(uc_get_field_name('city'), variable_get('uc_google_checkout_delivery_city', ''), TRUE);
-  if (isset($_POST['country'])) {
-    $country = $_POST['country'];
-  }
-  else {
-    $country = variable_get('uc_google_checkout_delivery_country', 0);
-  }
-  $form['uc_google_checkout_delivery_country'] = uc_country_select(uc_get_field_name('country'), variable_get('uc_google_checkout_delivery_country', 0));
-  $form['uc_google_checkout_delivery_zone'] = uc_zone_select(uc_get_field_name('zone'), variable_get('uc_google_checkout_delivery_zone', 0), NULL, $country);
-  $form['uc_google_checkout_delivery_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), variable_get('uc_google_checkout_delivery_postal_code', ''), TRUE, NULL, 10, 10);
+  $form['address'] = array(
+    '#type' => 'uc_address',
+    '#default_value' => array(
+      'uc_google_checkout_delivery_city' => variable_get('uc_google_checkout_delivery_city', ''),
+      'uc_google_checkout_delivery_zone' => variable_get('uc_google_checkout_delivery_zone', ''),
+      'uc_google_checkout_delivery_country' => isset($form_state['values']['uc_google_checkout_delivery_country']) ? $form_state['values']['uc_google_checkout_delivery_country'] : variable_get('uc_google_checkout_delivery_country', ''),
+      'uc_google_checkout_delivery_postal_code' => variable_get('uc_google_checkout_delivery_postal_code', ''),
+    ),
+    '#required' => FALSE,
+    '#key_prefix' => 'uc_google_checkout_delivery',
+  );
 
   return system_settings_form($form);
 }
diff --git a/payment/uc_payment_pack/uc_payment_pack.module b/payment/uc_payment_pack/uc_payment_pack.module
index e6c49d4..de531d6 100644
--- a/payment/uc_payment_pack/uc_payment_pack.module
+++ b/payment/uc_payment_pack/uc_payment_pack.module
@@ -453,20 +453,21 @@ function uc_payment_method_check($op, &$order, $form = NULL, &$form_state = NULL
       $form['check_address_info'] = array(
         '#markup' => '<div>' . t('Set the mailing address to display to customers who choose this payment method during checkout.') . '</div>',
       );
-      $form['uc_check_mailing_company'] = uc_textfield(uc_get_field_name('company'), variable_get('uc_check_mailing_company', ''), FALSE, NULL, 128);
       $form['uc_check_mailing_name'] = uc_textfield(t('Contact'), variable_get('uc_check_mailing_name', ''), FALSE, t('Direct checks to a person or department.'), 128);
-      $form['uc_check_mailing_street1'] = uc_textfield(uc_get_field_name('street1'), variable_get('uc_check_mailing_street1', ''), FALSE, NULL, 128);
-      $form['uc_check_mailing_street2'] = uc_textfield(uc_get_field_name('street2'), variable_get('uc_check_mailing_street2', ''), FALSE, NULL, 128);
-      $form['uc_check_mailing_city'] = uc_textfield(uc_get_field_name('city'), variable_get('uc_check_mailing_city', ''), FALSE);
-      $form['uc_check_mailing_country'] = uc_country_select(uc_get_field_name('country'), variable_get('uc_check_mailing_country', uc_store_default_country()));
-      if (isset($_POST['uc_check_mailing_country'])) {
-        $country_id = intval($_POST['uc_check_mailing_country']);
-      }
-      else {
-        $country_id = variable_get('uc_check_mailing_country', uc_store_default_country());
-      }
-      $form['uc_check_mailing_zone'] = uc_zone_select(uc_get_field_name('zone'), variable_get('uc_check_mailing_zone', ''), FALSE, $country_id);
-      $form['uc_check_mailing_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), variable_get('uc_check_mailing_postal_code', ''), FALSE, NULL, 10, 10);
+      $form['uc_check_address'] = array(
+        '#type' => 'uc_address',
+        '#default_value' => array(
+          'uc_check_mailing_company' => variable_get('uc_check_mailing_company', ''),
+          'uc_check_mailing_street1' => variable_get('uc_check_mailing_street1', ''),
+          'uc_check_mailing_street2' => variable_get('uc_check_mailing_street2', ''),
+          'uc_check_mailing_city' => variable_get('uc_check_mailing_city', ''),
+          'uc_check_mailing_zone' => variable_get('uc_check_mailing_zone', ''),
+          'uc_check_mailing_country' => isset($form_state['values']['uc_check_mailing_country']) ? $form_state['values']['uc_check_mailing_country'] : variable_get('uc_check_mailing_country', ''),
+          'uc_check_mailing_postal_code' => variable_get('uc_check_mailing_postal_code', ''),
+        ),
+        '#required' => FALSE,
+        '#key_prefix' => 'uc_check_mailing',
+      );
       $form['uc_check_policy'] = array(
         '#type' => 'textarea',
         '#title' => t('Check payment policy', array(), array('context' => 'cheque')),
diff --git a/shipping/uc_quote/uc_quote.admin.inc b/shipping/uc_quote/uc_quote.admin.inc
index 7f6e47b..3f476cc 100644
--- a/shipping/uc_quote/uc_quote.admin.inc
+++ b/shipping/uc_quote/uc_quote.admin.inc
@@ -113,22 +113,11 @@ function uc_quote_admin_settings($form, &$form_state) {
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
   );
-  $form['default_address']['first_name'] = uc_textfield(uc_get_field_name('first_name'), $address->first_name, FALSE);
-  $form['default_address']['last_name'] = uc_textfield(uc_get_field_name('last_name'), $address->last_name, FALSE);
-  $form['default_address']['company'] = uc_textfield(uc_get_field_name('company'), $address->company, FALSE);
-  $form['default_address']['phone'] = uc_textfield(uc_get_field_name('phone'), $address->phone, FALSE, NULL, 32, 16);
-  $form['default_address']['street1'] = uc_textfield(uc_get_field_name('street1'), $address->street1, FALSE, NULL, 64);
-  $form['default_address']['street2'] = uc_textfield(uc_get_field_name('street2'), $address->street2, FALSE, NULL, 64);
-  $form['default_address']['city'] = uc_textfield(uc_get_field_name('city'), $address->city, FALSE);
-  if (isset($_POST['country'])) {
-    $country = $_POST['country'];
-  }
-  else {
-    $country = $address->country;
-  }
-  $form['default_address']['country'] = uc_country_select(uc_get_field_name('country'), $address->country);
-  $form['default_address']['zone'] = uc_zone_select(uc_get_field_name('zone'), $address->zone, NULL, $country);
-  $form['default_address']['postal_code'] = uc_textfield(uc_get_field_name('postal_code'), $address->postal_code, FALSE, NULL, 10, 10);
+  $form['default_address']['address'] = array(
+    '#type' => 'uc_address',
+    '#default_value' => isset($form_state['values']) ? $form_state['values'] : $address,
+    '#required' => FALSE,
+  );
 
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
diff --git a/shipping/uc_quote/uc_quote.css b/shipping/uc_quote/uc_quote.css
index 2cc96e2..2b490ee 100644
--- a/shipping/uc_quote/uc_quote.css
+++ b/shipping/uc_quote/uc_quote.css
@@ -7,6 +7,14 @@
   white-space: normal;
 }
 
+#uc-cart-pane-quotes .uc-store-address-field .form-item label {
+  padding: 5px 6px 6px;
+}
+
+#uc-cart-pane-quotes .form-submit {
+  margin-left: 16em;
+}
+
 .solid-border#quote {
   margin-top: 1em;
 }
diff --git a/shipping/uc_quote/uc_quote.module b/shipping/uc_quote/uc_quote.module
index 7ec7097..7d2347d 100644
--- a/shipping/uc_quote/uc_quote.module
+++ b/shipping/uc_quote/uc_quote.module
@@ -211,16 +211,6 @@ function uc_quote_form_alter(&$form, &$form_state, $form_id) {
       $address = variable_get('uc_quote_store_default_address', new UcAddress());
     }
 
-    // Store the country to use for the zone select based on $_POST.
-    // TODO: Fix this for D6!  Neither the $_POST or $form_state are available
-    // when the node form is being processed. : (
-    if (isset($_POST['country'])) {
-      $country = $_POST['country'];
-    }
-    else {
-      $country = $address->country;
-    }
-
     // Initialize the shipping fieldset array.
     if (!isset($form['shipping'])) {
       $form['shipping'] = array();
@@ -254,15 +244,11 @@ function uc_quote_form_alter(&$form, &$form_state, $form_id) {
       '#collapsed' => TRUE,
       '#weight' => -6,
     );
-    $form['shipping']['default_address']['first_name'] = uc_textfield(uc_get_field_name('first_name'), $address->first_name, FALSE);
-    $form['shipping']['default_address']['last_name'] = uc_textfield(uc_get_field_name('last_name'), $address->last_name, FALSE);
-    $form['shipping']['default_address']['company'] = uc_textfield(uc_get_field_name('company'), $address->company, FALSE);
-    $form['shipping']['default_address']['street1'] = uc_textfield(uc_get_field_name('street1'), $address->street1, FALSE, NULL, 64);
-    $form['shipping']['default_address']['street2'] = uc_textfield(uc_get_field_name('street2'), $address->street2, FALSE, NULL, 64);
-    $form['shipping']['default_address']['city'] = uc_textfield(uc_get_field_name('city'), $address->city, FALSE);
-    $form['shipping']['default_address']['zone'] = uc_zone_select(uc_get_field_name('zone'), $address->zone, NULL, $country);
-    $form['shipping']['default_address']['postal_code'] = uc_textfield(uc_get_field_name('postal_code'), $address->postal_code, FALSE, NULL, 10, 10);
-    $form['shipping']['default_address']['country'] = uc_country_select(uc_get_field_name('country'), $address->country);
+    $form['shipping']['default_address']['address'] = array(
+      '#type' => 'uc_address',
+      '#default_value' => isset($form_state['values']) ? $form_state['values'] : $address,
+      '#required' => FALSE,
+    );
   }
 }
 
@@ -529,10 +515,24 @@ function uc_quote_get_default_shipping_address($nid) {
 function uc_cart_pane_quotes($form, &$form_state, $items) {
   global $user;
 
-  $form['delivery_country'] = uc_country_select(uc_get_field_name('country'), isset($form_state['values']['delivery_country']) ? $form_state['values']['delivery_country'] : uc_store_default_country(), NULL, 'name', TRUE);
-  $country_id = isset($_POST['delivery_country']) ? intval($_POST['delivery_country']) : uc_store_default_country();
-  $form['delivery_zone'] = uc_zone_select(uc_get_field_name('zone'), isset($form_state['values']['delivery_zone']) ? $form_state['values']['delivery_zone'] : NULL, NULL, $country_id, 'name', TRUE);
-  $form['delivery_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), isset($form_state['values']['delivery_postal_code']) ? $form_state['values']['delivery_postal_code'] : '', TRUE, NULL, 10, 10);
+  $order = new UcOrder();
+  $order->uid = $user->uid;
+  $order->delivery_country = isset($form_state['values']['delivery_country']) ? $form_state['values']['delivery_country'] : uc_store_default_country();
+  $order->delivery_zone = isset($form_state['values']['delivery_zone']) ? $form_state['values']['delivery_zone'] : '';
+  $order->delivery_postal_code = isset($form_state['values']['delivery_postal_code']) ? $form_state['values']['delivery_postal_code'] : '';
+  $order->products = $items;
+
+  $form['address'] = array(
+    '#type' => 'uc_address',
+    '#default_value' => array(
+      'delivery_country' => $order->delivery_country,
+      'delivery_zone' => $order->delivery_zone,
+      'delivery_postal_code' => $order->delivery_postal_code,
+    ),
+    '#required' => TRUE,
+    '#key_prefix' => 'delivery',
+  );
+
   $form['get_quote'] = array(
     '#type' => 'button',
     '#value' => t('Calculate'),
@@ -546,13 +546,6 @@ function uc_cart_pane_quotes($form, &$form_state, $items) {
     '#value' => 'cart',
   );
 
-  $order = new UcOrder();
-  $order->uid = $user->uid;
-  $order->delivery_country = $form['delivery_country']['#default_value'];
-  $order->delivery_zone = $form['delivery_zone']['#default_value'];
-  $order->delivery_postal_code = $form['delivery_postal_code']['#default_value'];
-  $order->products = $items;
-
   module_load_include('inc', 'uc_quote', 'uc_quote.pages');
   $quotes = uc_quote_assemble_quotes($order);
 
@@ -588,11 +581,7 @@ function theme_uc_cart_pane_quotes($variables) {
   $form = $variables['form'];
 
   $output = '<div class="solid-border">';
-  $output .= '<strong>' . t('Estimated shipping cost:') . '</strong>';
-  $output .= drupal_render($form['delivery_country']);
-  $output .= drupal_render($form['delivery_zone']);
-  $output .= drupal_render($form['delivery_postal_code']);
-  $output .= drupal_render($form['get_quote']);
+  $output .= '<p><strong>' . t('Estimated shipping cost:') . '</strong></p>';
   $output .= drupal_render_children($form);
   $output .= '</div>';
 
diff --git a/shipping/uc_shipping/uc_shipping.admin.inc b/shipping/uc_shipping/uc_shipping.admin.inc
index 1cc856b..8d76e0d 100644
--- a/shipping/uc_shipping/uc_shipping.admin.inc
+++ b/shipping/uc_shipping/uc_shipping.admin.inc
@@ -704,12 +704,9 @@ function uc_shipping_shipment_view($order, $shipment) {
  * @see uc_shipping_shipment_edit_validate()
  * @see uc_shipping_shipment_edit_submit()
  * @see theme_uc_shipping_package_dimensions()
- * @see theme_uc_shipping_address()
  * @ingroup forms
  */
 function uc_shipping_shipment_edit($form, &$form_state, $order, $shipment) {
-  drupal_add_css(drupal_get_path('module', 'uc_shipping') . '/uc_shipping.css');
-
   $form['order_id'] = array('#type' => 'value', '#value' => $order->order_id);
   if (isset($shipment->sid)) {
     $form['sid'] = array('#type' => 'value', '#value' => $shipment->sid);
@@ -910,14 +907,9 @@ function uc_shipping_shipment_edit_submit($form, &$form_state) {
   if (isset($form_state['values']['sid'])) {
     $shipment->sid = $form_state['values']['sid'];
   }
-  $shipment->origin = new stdClass();
-  $shipment->destination = new stdClass();
+  $shipment->origin = (object) $form_state['values']['pickup_address'];
   foreach ($form_state['values'] as $key => $value) {
-    if (substr($key, 0, 7) == 'pickup_') {
-      $field = substr($key, 7);
-      $shipment->origin->$field = $value;
-    }
-    elseif (substr($key, 0, 9) == 'delivery_') {
+    if (substr($key, 0, 9) == 'delivery_') {
       $field = substr($key, 9);
       $shipment->destination->$field = $value;
     }
diff --git a/shipping/uc_shipping/uc_shipping.css b/shipping/uc_shipping/uc_shipping.css
deleted file mode 100644
index b14c0b8..0000000
--- a/shipping/uc_shipping/uc_shipping.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * @file
- * Styles for uc_shipping module.
- */
-.pane-table .form-item {
-  display: inline;
-}
diff --git a/shipping/uc_shipping/uc_shipping.js b/shipping/uc_shipping/uc_shipping.js
index ab4a1e7..a35d949 100644
--- a/shipping/uc_shipping/uc_shipping.js
+++ b/shipping/uc_shipping/uc_shipping.js
@@ -25,10 +25,6 @@ function apply_address(type, json_address) {
 
     if (jQuery('#edit-' + type + '-country').val() != address.country) {
       jQuery('#edit-' + type + '-country').val(address.country);
-      try {
-        uc_update_zone_select('edit-' + type + '-country', address.zone);
-      }
-      catch (err) {}
     }
 
     jQuery('#edit-' + type + '-zone').val(address.zone);
diff --git a/shipping/uc_shipping/uc_shipping.module b/shipping/uc_shipping/uc_shipping.module
index 05d7a3a..b718ad6 100644
--- a/shipping/uc_shipping/uc_shipping.module
+++ b/shipping/uc_shipping/uc_shipping.module
@@ -195,9 +195,6 @@ function uc_shipping_theme() {
     'uc_shipping_package_dimensions' => array(
       'render element' => 'form',
     ),
-    'uc_shipping_address' => array(
-      'render element' => 'address',
-    ),
     'uc_shipping_shipment_print' => array(
       'variables' => array('order' => NULL, 'shipment' => NULL, 'labels' => TRUE),
     ),
@@ -370,48 +367,6 @@ function theme_uc_shipping_package_dimensions($variables) {
   return theme('table', array('rows' => array($row)));
 }
 
-/**
- * Compacts the address into a table.
- *
- * @ingroup themeable
- */
-function theme_uc_shipping_address($variables) {
-  $address = $variables['address'];
-
-  drupal_add_css(drupal_get_path('module', 'uc_cart') . '/uc_cart.css');
-  if ($address['#collapsed']) {
-    $collapsed = ' collapsed';
-  }
-  $output = '<table class="pane-table" cellpadding="2">';
-  $req = '<span class="form-required">*</span>';
-
-  foreach (element_children($address) as $field) {
-    list($type, $name) = explode('_', $field, 2);
-    if ($address !== NULL) {
-      $title = $address[$field]['#title'] . ':';
-      unset($address[$field]['#title']);
-      if ($name == 'street1') {
-        $title = uc_get_field_name('street') . ':';
-      }
-      elseif ($name == 'street2') {
-        $title = ' ';
-      }
-      $output .= '<tr><td class="field-label">';
-      if ($address[$field]['#required']) {
-        $output .= $req;
-      }
-      $output .= $title . '</td><td>'
-        . drupal_render($address[$field])
-        . '</td></tr>';
-    }
-  }
-  $output .= '</table>';
-
-  $output .= drupal_render_children($address);
-
-  return $output;
-}
-
 /******************************************************************************
  * Module and helper functions                                                *
  ******************************************************************************/
@@ -750,44 +705,45 @@ function uc_shipping_select_address($addresses, $onchange = '', $title = NULL, $
 function uc_shipping_address_form($form, &$form_state, $addresses, $order) {
   drupal_add_js(drupal_get_path('module', 'uc_shipping') . '/uc_shipping.js');
 
-  $form['origin'] = array('#type' => 'fieldset',
+  $form['origin'] = array(
+    '#type' => 'fieldset',
     '#title' => t('Origin address'),
     '#collapsible' => TRUE,
     '#collapsed' => FALSE,
     '#weight' => -2,
-    '#theme' => 'uc_shipping_address',
   );
   $address = reset($addresses);
+  if (isset($form_state['values']['pickup_address']['country'])) {
+    $address->country = $form_state['values']['pickup_address']['country'];
+  }
   $form['origin']['pickup_address_select'] = uc_shipping_select_address($addresses, 'apply_address(\'pickup\', this.value);', t('Saved Addresses'), TRUE);
   $form['origin']['pickup_address_select']['#weight'] = -2;
   $form['origin']['pickup_email'] = uc_textfield(uc_get_field_name('email'), variable_get('uc_store_email', NULL), FALSE, NULL, 255);
   $form['origin']['pickup_email']['#weight'] = -1;
-  $form['origin']['pickup_first_name'] = uc_textfield(uc_get_field_name('first_name'), $address->first_name, FALSE);
-  $form['origin']['pickup_last_name'] = uc_textfield(uc_get_field_name('last_name'), $address->last_name, FALSE);
-  $form['origin']['pickup_phone'] = uc_textfield(uc_get_field_name('phone'), variable_get('uc_store_phone', NULL), FALSE, NULL, 32, 16);
-  $form['origin']['pickup_company'] = uc_textfield(uc_get_field_name('company'), $address->company, FALSE);
-  $form['origin']['pickup_street1'] = uc_textfield(uc_get_field_name('street1'), $address->street1, FALSE, NULL, 64);
-  $form['origin']['pickup_street2'] = uc_textfield(uc_get_field_name('street2'), $address->street2, FALSE, NULL, 64);
-  $form['origin']['pickup_city'] = uc_textfield(uc_get_field_name('city'), $address->city, FALSE);
-  $form['origin']['pickup_country'] = uc_country_select(uc_get_field_name('country'), $address->country);
-  if (isset($_POST['pickup_country'])) {
-    $country = $_POST['pickup_country'];
-  }
-  else {
-    $country = $address->country;
-  }
-  $form['origin']['pickup_zone'] = uc_zone_select(uc_get_field_name('zone'), $address->zone, NULL, $country);
-  $form['origin']['pickup_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), $address->postal_code, FALSE, NULL, 10, 10);
+  $form['origin']['pickup_address'] = array(
+    '#type' => 'uc_address',
+    '#default_value' => $address,
+    '#required' => FALSE,
+    '#tree' => TRUE,
+  );
 
-  $order_form = uc_order_pane_ship_to('edit-form', $order);
-  $form['destination'] = $order_form['ship_to'];
+  $form['destination'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Destination address'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+    '#weight' => -1,
+  );
+  if (isset($form_state['values']['delivery_country'])) {
+    $order->delivery_country = $form_state['values']['delivery_country'];
+  }
   $form['destination']['delivery_email'] = uc_textfield(uc_get_field_name('email'), $order->primary_email, FALSE, NULL, 255);
   $form['destination']['delivery_email']['#weight'] = -1;
-  $form['destination']['#type'] = 'fieldset';
-  $form['destination']['#title'] = t('Destination address');
-  $form['destination']['#collapsible'] = TRUE;
-  $form['destination']['#weight'] = -1;
-  $form['destination']['#theme'] = 'uc_shipping_address';
-
+  $form['destination']['delivery_address'] = array(
+    '#type' => 'uc_address',
+    '#default_value' => $order,
+    '#required' => FALSE,
+    '#key_prefix' => 'delivery',
+  );
   return $form;
 }
diff --git a/uc_cart/uc_cart.css b/uc_cart/uc_cart.css
index bed83d1..33ebd00 100644
--- a/uc_cart/uc_cart.css
+++ b/uc_cart/uc_cart.css
@@ -194,26 +194,8 @@ td.subtotal {
 /**
  * CSS rules for the default checkout panes.
  */
-.address-pane-table tbody {
-  border-top: 0px;
-}
-
-.address-pane-table table td {
-  padding: 2px;
-}
-
-.field-label {
-  font-weight: bold;
-  text-align: right;
-}
-
-.address-pane-table {
-  margin-left: auto;
-  margin-right: auto;
-}
-
-.address-pane-table .form-item {
-  display: inline;
+#uc-cart-checkout-form .uc-store-address-field .form-item label {
+  padding: 5px 6px 6px;
 }
 
 /**
diff --git a/uc_cart/uc_cart.js b/uc_cart/uc_cart.js
index d82bb0b..f52e535 100644
--- a/uc_cart/uc_cart.js
+++ b/uc_cart/uc_cart.js
@@ -3,13 +3,9 @@
  * Adds effects and behaviors to elements on the checkout page.
  */
 
-var copy_box_checked = false;
-
-/**
- * Adds a throbber to the submit order button on the review order form.
- */
-Drupal.behaviors.ucSubmitOrderThrobber = {
+Drupal.behaviors.ucCart = {
   attach: function(context, settings) {
+    // Add a throbber to the submit order button on the review order form.
     jQuery('form#uc-cart-checkout-review-form input#edit-submit:not(.ucSubmitOrderThrobber-processed)', context).addClass('ucSubmitOrderThrobber-processed').click(function() {
       jQuery(this).clone().insertAfter(this).attr('disabled', true).after('<span class="ubercart-throbber">&nbsp;&nbsp;&nbsp;&nbsp;</span>').end().hide();
       jQuery('#uc-cart-checkout-review-form #edit-back').attr('disabled', true);
@@ -37,110 +33,3 @@ function uc_cart_next_button_click(button, pane_id, current) {
 
   return false;
 }
-
-/**
- * Behaviors for the copy address checkbox.
- *
- * Copy the delivery information to the payment information on the checkout
- * screen if corresponding fields exist.
- */
-function uc_cart_copy_address(checked, source, target) {
-  if (!checked) {
-    jQuery('#' + target + '-pane div.address-pane-table').slideDown();
-    copy_box_checked = false;
-    return false;
-  }
-
-  if (target == 'billing') {
-    var x = 28;
-  }
-  else {
-    var x = 26;
-  }
-
-  // Hide the target information fields.
-  jQuery('#' + target + '-pane div.address-pane-table').slideUp();
-  copy_box_checked = true;
-
-  // Copy over the zone options manually.
-  if (jQuery('#edit-panes-' + target + '-' + target + '-zone').html() != jQuery('#edit-panes-' + source + '-' + source + '-zone').html()) {
-    jQuery('#edit-panes-' + target + '-' + target + '-zone').empty().append(jQuery('#edit-panes-' + source + '-' + source + '-zone').children().clone());
-    jQuery('#edit-panes-' + target + '-' + target + '-zone').attr('disabled', jQuery('#edit-panes-' + source + '-' + source + '-zone').attr('disabled'));
-  }
-
-  // Copy over the information and set it to update if delivery info changes.
-  jQuery('#' + source + '-pane input, select, textarea').each(
-    function() {
-      if (this.id.substring(0, x) == 'edit-panes-' + source + '-' + source) {
-        jQuery('#edit-panes-' + target + '-' + target + this.id.substring(x)).val(jQuery(this).val());
-        if (target == 'billing') {
-          jQuery(this).change(function () { update_billing_field(this); });
-        }
-        else {
-          jQuery(this).change(function () { update_delivery_field(this); });
-        }
-      }
-    }
-  );
-
-  return false;
-}
-
-/**
- * Copies a value from the delivery address to the billing address.
- */
-function update_billing_field(field) {
-  if (copy_box_checked) {
-    if (field.id.substring(29) == 'zone') {
-      jQuery('#edit-panes-billing-billing-zone').empty().append(jQuery('#edit-panes-delivery-delivery-zone').children().clone());
-      jQuery('#edit-panes-billing-billing-zone').attr('disabled', jQuery('#edit-panes-delivery-delivery-zone').attr('disabled'));
-    }
-
-    jQuery('#edit-panes-billing-billing' + field.id.substring(28)).val(jQuery(field).val()).change();
-  }
-}
-
-/**
- * Copies a value from the billing address to the delivery address.
- */
-function update_delivery_field(field) {
-  if (copy_box_checked) {
-    if (field.id.substring(27) == 'zone') {
-      jQuery('#edit-panes-delivery-delivery-zone').empty().append(jQuery('#edit-panes-billing-billing-zone').children().clone());
-      jQuery('#edit-panes-delivery-delivery-zone').attr('disabled', jQuery('#edit-panes-billing-billing-zone').attr('disabled'));
-    }
-
-    jQuery('#edit-panes-delivery-delivery' + field.id.substring(26)).val(jQuery(field).val()).change();
-  }
-}
-
-/**
- * Applies the selected address to the appropriate fields in the cart form.
- */
-function apply_address(type, address_str) {
-  if (address_str == '0') {
-    return;
-  }
-
-  eval('var address = ' + address_str + ';');
-  var temp = type + '-' + type;
-
-  jQuery('#edit-panes-' + temp + '-first-name').val(address.first_name).trigger('change');
-  jQuery('#edit-panes-' + temp + '-last-name').val(address.last_name).trigger('change');
-  jQuery('#edit-panes-' + temp + '-phone').val(address.phone).trigger('change');
-  jQuery('#edit-panes-' + temp + '-company').val(address.company).trigger('change');
-  jQuery('#edit-panes-' + temp + '-street1').val(address.street1).trigger('change');
-  jQuery('#edit-panes-' + temp + '-street2').val(address.street2).trigger('change');
-  jQuery('#edit-panes-' + temp + '-city').val(address.city).trigger('change');
-  jQuery('#edit-panes-' + temp + '-postal-code').val(address.postal_code).trigger('change');
-
-  if (jQuery('#edit-panes-' + temp + '-country').val() != address.country) {
-    jQuery('#edit-panes-' + temp + '-country').val(address.country).trigger('change');
-    try {
-      uc_update_zone_select('edit-panes-' + temp + '-country', address.zone);
-    }
-    catch (err) { }
-  }
-
-  jQuery('#edit-panes-' + temp + '-zone').val(address.zone).trigger('change');
-}
diff --git a/uc_cart/uc_cart_checkout_pane.inc b/uc_cart/uc_cart_checkout_pane.inc
index bc13c1a..2eec715 100644
--- a/uc_cart/uc_cart_checkout_pane.inc
+++ b/uc_cart/uc_cart_checkout_pane.inc
@@ -212,192 +212,108 @@ function uc_checkout_pane_customer($op, $order, $form = NULL, &$form_state = NUL
  * Gets the delivery information.
  */
 function uc_checkout_pane_delivery($op, $order, $form = NULL, &$form_state = NULL) {
-  global $user;
-
-  switch ($op) {
-    case 'view':
-      $description = t('Enter your delivery address and information here.');
-
-      if ((uc_cart_is_shippable() || !variable_get('uc_cart_delivery_not_shippable', TRUE)) &&
-           _uc_checkout_pane_data('billing', 'weight') < _uc_checkout_pane_data('delivery', 'weight') &&
-           _uc_checkout_pane_data('billing', 'enabled')) {
-        $contents['copy_address'] = array(
-          '#type' => 'checkbox',
-          '#title' => t('My delivery information is the same as my billing information.'),
-          '#attributes' => array('onclick' => "uc_cart_copy_address(this.checked, 'billing', 'delivery');"),
-        );
-      }
-
-      if ($user->uid) {
-        $addresses = uc_select_address($user->uid, 'delivery', 'apply_address(\'delivery\', this.value);', t('Saved addresses'), TRUE);
-        if (!empty($addresses)) {
-          $contents['delivery_address_select'] = $addresses;
-        }
-      }
-
-      if (uc_address_field_enabled('first_name')) {
-        $delivery_first_name = $order ? $order->delivery_first_name : '';
-        $contents['delivery_first_name'] = uc_textfield(uc_get_field_name('first_name'), $delivery_first_name, uc_address_field_required('first_name'));
-      }
-      if (uc_address_field_enabled('last_name')) {
-        $delivery_last_name = $order ? $order->delivery_last_name : '';
-        $contents['delivery_last_name'] = uc_textfield(uc_get_field_name('last_name'), $delivery_last_name, uc_address_field_required('last_name'));
-      }
-      if (uc_address_field_enabled('company')) {
-        $delivery_company = $order ? $order->delivery_company : '';
-        $contents['delivery_company'] = uc_textfield(uc_get_field_name('company'), $delivery_company, uc_address_field_required('company'), NULL, 64);
-      }
-      if (uc_address_field_enabled('street1')) {
-        $delivery_street1 = $order ? $order->delivery_street1 : '';
-        $contents['delivery_street1'] = uc_textfield(uc_get_field_name('street1'), $delivery_street1, uc_address_field_required('street1'), NULL, 64);
-      }
-      if (uc_address_field_enabled('street2')) {
-        $delivery_street2 = $order ? $order->delivery_street2 : '';
-        $contents['delivery_street2'] = uc_textfield(uc_get_field_name('street2'), $delivery_street2, uc_address_field_required('street2'), NULL, 64);
-      }
-      if (uc_address_field_enabled('city')) {
-        $delivery_city = $order ? $order->delivery_city : '';
-        $contents['delivery_city'] = uc_textfield(uc_get_field_name('city'), $delivery_city, uc_address_field_required('city'));
-      }
-      if (uc_address_field_enabled('country')) {
-        $delivery_country = $order ? $order->delivery_country : NULL;
-        $contents['delivery_country'] = uc_country_select(uc_get_field_name('country'), $delivery_country, NULL, 'name', uc_address_field_required('country'));
-      }
-      if (uc_address_field_enabled('zone')) {
-        if (isset($_POST['panes']['delivery']['delivery_country'])) {
-          $country_id = intval($_POST['panes']['delivery']['delivery_country']);
-        }
-        else {
-          $country_id = $delivery_country;
-        }
-        $delivery_zone = $order ? $order->delivery_zone : NULL;
-        $contents['delivery_zone'] = uc_zone_select(uc_get_field_name('zone'), $delivery_zone, NULL, $country_id, 'name', uc_address_field_required('zone'));
-        if (isset($_POST['panes']) && count($contents['delivery_zone']['#options']) == 1) {
-          $contents['delivery_zone']['#required'] = FALSE;
-        }
-      }
-      if (uc_address_field_enabled('postal_code')) {
-        $delivery_postal_code = $order ? $order->delivery_postal_code : '';
-        $contents['delivery_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), $delivery_postal_code, uc_address_field_required('postal_code'), NULL, 10, 10);
-      }
-      if (uc_address_field_enabled('phone')) {
-        $delivery_phone = $order ? $order->delivery_phone : '';
-        $contents['delivery_phone'] = uc_textfield(uc_get_field_name('phone'), $delivery_phone, uc_address_field_required('phone'), NULL, 32, 16);
-      }
-
-      return array('description' => $description, 'contents' => $contents, 'theme' => 'uc_address_pane');
-
-    case 'process':
-      foreach (uc_address_field_enabled() as $field) {
-        $field = 'delivery_' . $field;
-        $order->$field = $form_state['values']['panes']['delivery'][$field];
-      }
-      return TRUE;
-
-    case 'review':
-      $review[] = array('title' => t('Address'), 'data' => uc_order_address($order, 'delivery', FALSE));
-      if (uc_address_field_enabled('phone') && !empty($order->delivery_phone)) {
-        $review[] = array('title' => t('Phone'), 'data' => check_plain($order->delivery_phone));
-      }
-      return $review;
-  }
+  $description = t('Enter your delivery address and information here.');
+  $copy = t('My delivery information is the same as my billing information.');
+  return uc_checkout_pane_address('delivery', $op, $order, $form_state, $description, $copy);
 }
 
 /**
  * Gets the billing information.
  */
 function uc_checkout_pane_billing($op, $order, $form = NULL, &$form_state = NULL) {
+  $description = t('Enter your billing address and information here.');
+  $copy = t('My billing information is the same as my delivery information.');
+  return uc_checkout_pane_address('billing', $op, $order, $form_state, $description, $copy);
+}
+
+/**
+ * Generic address pane handler.
+ */
+function uc_checkout_pane_address($pane, $op, $order, &$form_state, $description, $copy) {
   global $user;
 
+  // Source pane for "copy address" checkbox.
+  static $source;
+  if (!isset($source)) {
+    $source = $pane;
+  }
+
   switch ($op) {
     case 'view':
-      $description = t('Enter your billing address and information here.');
-
-      if ((uc_cart_is_shippable() || !variable_get('uc_cart_delivery_not_shippable', TRUE)) &&
-           _uc_checkout_pane_data('delivery', 'weight') < _uc_checkout_pane_data('billing', 'weight') &&
-           _uc_checkout_pane_data('delivery', 'enabled')) {
+      if ($source != $pane) {
         $contents['copy_address'] = array(
           '#type' => 'checkbox',
-          '#title' => t('My billing information is the same as my delivery information.'),
-          '#attributes' => array('onclick' => "uc_cart_copy_address(this.checked, 'delivery', 'billing');"),
+          '#title' => $copy,
+          '#ajax' => array(
+            'callback' => '', // Dummy callback, as no action is needed.
+            'progress' => array(
+              'type' => 'throbber',
+            ),
+          ),
         );
       }
 
-      if ($user->uid) {
-        $addresses = uc_select_address($user->uid, 'billing', 'apply_address(\'billing\', this.value);', t('Saved addresses'), TRUE);
-        if (!empty($addresses)) {
-          $contents['billing_address_select'] = $addresses;
-        }
-      }
-      if (uc_address_field_enabled('first_name')) {
-        $billing_first_name = $order ? $order->billing_first_name : '';
-        $contents['billing_first_name'] = uc_textfield(uc_get_field_name('first_name'), $billing_first_name, uc_address_field_required('first_name'));
-      }
-      if (uc_address_field_enabled('last_name')) {
-        $billing_last_name = $order ? $order->billing_last_name : '';
-        $contents['billing_last_name'] = uc_textfield(uc_get_field_name('last_name'), $billing_last_name, uc_address_field_required('last_name'));
-      }
-      if (uc_address_field_enabled('company')) {
-        $billing_company = $order ? $order->billing_company : '';
-        $contents['billing_company'] = uc_textfield(uc_get_field_name('company'), $billing_company, uc_address_field_required('company'), NULL, 64);
-      }
-      if (uc_address_field_enabled('street1')) {
-        $billing_street1 = $order ? $order->billing_street1 : '';
-        $contents['billing_street1'] = uc_textfield(uc_get_field_name('street1'), $billing_street1, uc_address_field_required('street1'), NULL, 64);
-      }
-      if (uc_address_field_enabled('street2')) {
-        $billing_street2 = $order ? $order->billing_street2 : '';
-        $contents['billing_street2'] = uc_textfield(uc_get_field_name('street2'), $billing_street2, uc_address_field_required('street2'), NULL, 64);
-      }
-      if (uc_address_field_enabled('city')) {
-        $billing_city = $order ? $order->billing_city : '';
-        $contents['billing_city'] = uc_textfield(uc_get_field_name('city'), $billing_city, uc_address_field_required('city'));
-      }
-      if (uc_address_field_enabled('country')) {
-        $billing_country = $order ? $order->billing_country : NULL;
-        $contents['billing_country'] = uc_country_select(uc_get_field_name('country'), $billing_country, NULL, 'name', uc_address_field_required('country'));
-      }
-      if (uc_address_field_enabled('zone')) {
-        if (isset($_POST['panes']['billing']['billing_country'])) {
-          $country_id = intval($_POST['panes']['billing']['billing_country']);
-        }
-        else {
-          $country_id = $billing_country;
-        }
-        $billing_zone = $order ? $order->billing_zone : NULL;
-        $contents['billing_zone'] = uc_zone_select(uc_get_field_name('zone'), $billing_zone, NULL, $country_id, 'name', uc_address_field_required('zone'));
-        if (isset($_POST['panes']) && count($contents['billing_zone']['#options']) == 1) {
-          $contents['billing_zone']['#required'] = FALSE;
-        }
-      }
-      if (uc_address_field_enabled('postal_code')) {
-        $billing_postal_code = $order ? $order->billing_postal_code : '';
-        $contents['billing_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), $billing_postal_code, uc_address_field_required('postal_code'), NULL, 10, 10);
-      }
-      if (uc_address_field_enabled('phone')) {
-        $billing_phone = $order ? $order->billing_phone : '';
-        $contents['billing_phone'] = uc_textfield(uc_get_field_name('phone'), $billing_phone, uc_address_field_required('phone'), NULL, 32, 16);
+      if ($user->uid && $addresses = uc_select_addresses($user->uid, $pane)) {
+        $contents['select_address'] = array(
+          '#type' => 'select',
+          '#title' => t('Saved addresses'),
+          '#options' => $addresses,
+          '#ajax' => array(
+            'callback' => 'uc_cart_select_address',
+            'progress' => array(
+              'type' => 'throbber',
+            ),
+          ),
+          '#states' => array(
+            'invisible' => array(
+              'input[name="panes[' . $pane . '][copy_address]"]' => array('checked' => TRUE),
+            ),
+          ),
+        );
       }
 
-      return array('description' => $description, 'contents' => $contents, 'theme' => 'uc_address_pane');
+      $contents['address'] = array(
+        '#type' => 'uc_address',
+        '#default_value' => $order,
+        '#key_prefix' => $pane,
+        '#states' => array(
+          'invisible' => array(
+            'input[name="panes[' . $pane . '][copy_address]"]' => array('checked' => TRUE),
+          ),
+        ),
+        '#required' => empty($form_state['values']['panes'][$pane]['copy_address']),
+      );
+
+      return array('description' => $description, 'contents' => $contents);
 
     case 'process':
-      foreach (uc_address_field_enabled() as $field) {
-        $field = 'billing_' . $field;
-        $order->$field = $form_state['values']['panes']['billing'][$field];
+      $panes = &$form_state['values']['panes'];
+      foreach ($panes[$pane]['address'] as $key => $value) {
+        if (!empty($panes[$pane]['copy_address'])) {
+          $value = $panes[$source]['address'][str_replace($pane, $source, $key)];
+        }
+
+        $order->$key = $value;
       }
       return TRUE;
 
     case 'review':
-      $review[] = array('title' => t('Address'), 'data' => uc_order_address($order, 'billing', FALSE));
-      if (uc_address_field_enabled('phone') && !empty($order->billing_phone)) {
-        $review[] = array('title' => t('Phone'), 'data' => check_plain($order->billing_phone));
+      $review[] = array('title' => t('Address'), 'data' => uc_order_address($order, $pane, FALSE));
+      if (uc_address_field_enabled('phone') && !empty($order->{$pane . '_phone'})) {
+        $review[] = array('title' => t('Phone'), 'data' => check_plain($pane . '_phone'));
       }
       return $review;
   }
 }
 
 /**
+ * Ajax callback; select previous address.
+ */
+function uc_cart_select_address($form, &$form_state) {
+  // unfinished
+}
+
+/**
  * Allows a customer to make comments on the order.
  */
 function uc_checkout_pane_comments($op, $order, $form = NULL, &$form_state = NULL) {
@@ -439,49 +355,6 @@ function uc_checkout_pane_comments($op, $order, $form = NULL, &$form_state = NUL
 }
 
 /**
- * Themes the delivery/billing address forms in tables.
- *
- * @see uc_checkout_pane_delivery()
- * @see uc_checkout_pane_billing()
- * @ingroup themeable
- */
-function theme_uc_address_pane($variables) {
-  $form = $variables['form'];
-  $output = '';
-
-  $req = '<span class="form-required">*</span>';
-
-  if (isset($form['copy_address'])) {
-    $output = drupal_render($form['copy_address']);
-  }
-
-  $output .= '<div class="address-pane-table"><table>';
-
-  foreach (element_children($form) as $field) {
-    if (substr($field, 0, 9) == 'delivery_' || substr($field, 0, 8) == 'billing_') {
-      $title = $form[$field]['#title'] . ':';
-      unset($form[$field]['#title']);
-      if (substr($field, -7) == 'street1') {
-        $title = uc_get_field_name('street') . ':';
-      }
-      elseif (substr($field, -7) == 'street2') {
-        $title = ' ';
-      }
-      $output .= '<tr><td class="field-label">';
-      if ($form[$field]['#required']) {
-        $output .= $req;
-      }
-      $output .= $title . '</td><td>' . drupal_render($form[$field]) . '</td></tr>';
-    }
-  }
-  $output .= '</table></div>';
-
-  $output .= drupal_render_children($form);
-
-  return $output;
-}
-
-/**
  * Finds the collapsible pane displayed above the pane with an ID of $pane_id.
  */
 function _uc_cart_checkout_prev_pane($panes, $pane_id = NULL) {
diff --git a/uc_order/uc_order.css b/uc_order/uc_order.css
index 9a035f5..63c7361 100644
--- a/uc_order/uc_order.css
+++ b/uc_order/uc_order.css
@@ -100,6 +100,15 @@
   width: 100%;
 }
 
+.order-pane .uc-store-address-field .form-item {
+  padding: 0;
+}
+
+.order-pane .uc-store-address-field .form-item label {
+  padding: 2px 4px;
+  width: 12em;
+}
+
 .order-pane-table {
   width: 100%;
 }
diff --git a/uc_order/uc_order.js b/uc_order/uc_order.js
index 3b6660e..e259705 100644
--- a/uc_order/uc_order.js
+++ b/uc_order/uc_order.js
@@ -133,10 +133,6 @@ function apply_address(type, address_str) {
 
   if (jQuery('#edit-' + type + '-country').val() != address['country']) {
     jQuery('#edit-' + type + '-country').val(address['country']);
-    try {
-      uc_update_zone_select('edit-' + type + '-country', address['zone']);
-    }
-    catch (err) {}
   }
 
   jQuery('#edit-' + type + '-zone').val(address['zone']);
diff --git a/uc_order/uc_order.module b/uc_order/uc_order.module
index 52ff9e5..f00f048 100644
--- a/uc_order/uc_order.module
+++ b/uc_order/uc_order.module
@@ -56,6 +56,8 @@ class UcOrder {
 
   function __construct() {
     $this->order_status = uc_order_state_default('in_checkout');
+    $this->billing_country = variable_get('uc_store_country', 840);
+    $this->delivery_country = variable_get('uc_store_country', 840);
   }
 
 }
diff --git a/uc_order/uc_order.order_pane.inc b/uc_order/uc_order.order_pane.inc
index 63d421b..16e5654 100644
--- a/uc_order/uc_order.order_pane.inc
+++ b/uc_order/uc_order.order_pane.inc
@@ -24,44 +24,13 @@ function uc_order_pane_ship_to($op, $order, &$form = NULL, &$form_state = NULL)
       return $build;
 
     case 'edit-form':
-      $form['ship_to'] = array();
-
-      if (uc_address_field_enabled('first_name')) {
-        $form['ship_to']['delivery_first_name'] = uc_textfield(uc_get_field_name('first_name'), $order->delivery_first_name, FALSE);
-      }
-      if (uc_address_field_enabled('last_name')) {
-        $form['ship_to']['delivery_last_name'] = uc_textfield(uc_get_field_name('last_name'), $order->delivery_last_name, FALSE);
-      }
-      if (uc_address_field_enabled('phone')) {
-        $form['ship_to']['delivery_phone'] = uc_textfield(uc_get_field_name('phone'), $order->delivery_phone, FALSE, NULL, 32, 16);
-      }
-      if (uc_address_field_enabled('company')) {
-        $form['ship_to']['delivery_company'] = uc_textfield(uc_get_field_name('company'), $order->delivery_company, FALSE, NULL, 64);
-      }
-      if (uc_address_field_enabled('street1')) {
-        $form['ship_to']['delivery_street1'] = uc_textfield(uc_get_field_name('street1'), $order->delivery_street1, FALSE, NULL, 64);
-      }
-      if (uc_address_field_enabled('street2')) {
-        $form['ship_to']['delivery_street2'] = uc_textfield(uc_get_field_name('street2'), $order->delivery_street2, FALSE, NULL, 64);
-      }
-      if (uc_address_field_enabled('city')) {
-        $form['ship_to']['delivery_city'] = uc_textfield(uc_get_field_name('city'), $order->delivery_city, FALSE);
-      }
-      if (uc_address_field_enabled('country')) {
-        $form['ship_to']['delivery_country'] = uc_country_select(uc_get_field_name('country'), $order->delivery_country);
-      }
-      if (uc_address_field_enabled('zone')) {
-        if (isset($_POST['delivery_country'])) {
-          $country_id = intval($_POST['delivery_country']);
-        }
-        else {
-          $country_id = $order->delivery_country;
-        }
-        $form['ship_to']['delivery_zone'] = uc_zone_select(uc_get_field_name('zone'), $order->delivery_zone, NULL, $country_id);
-      }
-      if (uc_address_field_enabled('postal_code')) {
-        $form['ship_to']['delivery_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), $order->delivery_postal_code, FALSE, NULL, 10, 10);
-      }
+      $form['ship_to'] = array(
+        '#type' => 'uc_address',
+        '#default_value' => isset($form_state['values']) ? $form_state['values'] : $order,
+        '#required' => FALSE,
+        '#attributes' => array('class' => array('uc-store-address-field')),
+        '#key_prefix' => 'delivery',
+      );
       return $form;
 
     case 'edit-title':
@@ -78,15 +47,7 @@ function uc_order_pane_ship_to($op, $order, &$form = NULL, &$form_state = NULL)
       return $output;
 
     case 'edit-theme':
-      $output = '<div id="delivery_address_select"></div><table class="order-edit-table">';
-      foreach (element_children($form['ship_to']) as $field) {
-        $title = $form['ship_to'][$field]['#title'];
-        $form['ship_to'][$field]['#title'] = NULL;
-        $output .= '<tr><td class="oet-label">' . $title . ':</td><td>'
-                 . drupal_render($form['ship_to'][$field]) . '</td></tr>';
-      }
-      $output .= '</table>';
-      return $output;
+      return drupal_render($form['ship_to']);
 
     case 'edit-process':
       foreach ($form_state['values'] as $key => $value) {
@@ -111,44 +72,13 @@ function uc_order_pane_bill_to($op, $order, &$form = NULL, &$form_state = NULL)
       return $build;
 
     case 'edit-form':
-      $form['bill_to'] = array();
-
-      if (uc_address_field_enabled('first_name')) {
-        $form['bill_to']['billing_first_name'] = uc_textfield(uc_get_field_name('first_name'), $order->billing_first_name, FALSE);
-      }
-      if (uc_address_field_enabled('last_name')) {
-        $form['bill_to']['billing_last_name'] = uc_textfield(uc_get_field_name('last_name'), $order->billing_last_name, FALSE);
-      }
-      if (uc_address_field_enabled('phone')) {
-        $form['bill_to']['billing_phone'] = uc_textfield(uc_get_field_name('phone'), $order->billing_phone, FALSE, NULL, 32, 16);
-      }
-      if (uc_address_field_enabled('company')) {
-        $form['bill_to']['billing_company'] = uc_textfield(uc_get_field_name('company'), $order->billing_company, FALSE, NULL, 64);
-      }
-      if (uc_address_field_enabled('street1')) {
-        $form['bill_to']['billing_street1'] = uc_textfield(uc_get_field_name('street1'), $order->billing_street1, FALSE, NULL, 64);
-      }
-      if (uc_address_field_enabled('street2')) {
-        $form['bill_to']['billing_street2'] = uc_textfield(uc_get_field_name('street2'), $order->billing_street2, FALSE, NULL, 64);
-      }
-      if (uc_address_field_enabled('city')) {
-        $form['bill_to']['billing_city'] = uc_textfield(uc_get_field_name('city'), $order->billing_city, FALSE);
-      }
-      if (uc_address_field_enabled('country')) {
-        $form['bill_to']['billing_country'] = uc_country_select(uc_get_field_name('country'), $order->billing_country);
-      }
-      if (uc_address_field_enabled('zone')) {
-        if (isset($_POST['billing_country'])) {
-          $country_id = intval($_POST['billing_country']);
-        }
-        else {
-          $country_id = $order->billing_country;
-        }
-        $form['bill_to']['billing_zone'] = uc_zone_select(uc_get_field_name('zone'), $order->billing_zone, NULL, $country_id);
-      }
-      if (uc_address_field_enabled('postal_code')) {
-        $form['bill_to']['billing_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), $order->billing_postal_code, FALSE, NULL, 10, 10);
-      }
+      $form['bill_to'] = array(
+        '#type' => 'uc_address',
+        '#default_value' => isset($form_state['values']) ? $form_state['values'] : $order,
+        '#required' => FALSE,
+        '#attributes' => array('class' => array('uc-store-address-field')),
+        '#key_prefix' => 'billing',
+      );
       return $form;
 
     case 'edit-title':
@@ -163,15 +93,7 @@ function uc_order_pane_bill_to($op, $order, &$form = NULL, &$form_state = NULL)
       return $output;
 
     case 'edit-theme':
-      $output = '<div id="billing_address_select"></div><table class="order-edit-table">';
-      foreach (element_children($form['bill_to']) as $field) {
-        $title = $form['bill_to'][$field]['#title'];
-        $form['bill_to'][$field]['#title'] = NULL;
-        $output .= '<tr><td class="oet-label">' . $title . ':</td><td>'
-                 . drupal_render($form['bill_to'][$field]) . '</td></tr>';
-      }
-      $output .= '</table>';
-      return $output;
+      return drupal_render($form['bill_to']);
 
     case 'edit-process':
       foreach ($form_state['values'] as $key => $value) {
diff --git a/uc_store/classes/address.inc b/uc_store/classes/address.inc
index be33369..fa89a4d 100644
--- a/uc_store/classes/address.inc
+++ b/uc_store/classes/address.inc
@@ -16,12 +16,14 @@ class UcAddress {
   public $street1 = '';
   public $street2 = '';
   public $city = '';
-  public $zone = 0;
-  public $postal_code = '';
+  public $zone = '';
   public $country = 0;
+  public $postal_code = '';
   public $phone = '';
   public $email = '';
 
-  function __construct() { }
+  function __construct() {
+    $this->country = variable_get('uc_store_country', 840);
+  }
 
 }
diff --git a/uc_store/uc_country_select.js b/uc_store/uc_country_select.js
deleted file mode 100644
index d845cb5..0000000
--- a/uc_store/uc_country_select.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * @file
- * Switches the zones list when a country is chosen for an address.
- */
-
-/**
- * Sets the select box change behavior for the country selector
- */
-Drupal.behaviors.ucCountrySelect = {
-  attach: function(context, settings) {
-    jQuery('select[id$=-country]:not(.ucCountrySelect-processed)', context).addClass('ucCountrySelect-processed').change(
-      function() {
-        uc_update_zone_select(this.id, '', settings);
-      }
-    );
-  }
-}
-
-/**
- * Updates the zone select element with new options.
- */
-function uc_update_zone_select(country_select, default_zone, settings) {
-  settings = settings || Drupal.settings;
-
-  var zone_select = country_select.substr(0, country_select.length - 8) + '-zone';
-
-  var options = { 'country_id' : jQuery('#' + country_select).val() };
-
-  jQuery('#' + zone_select).parent().siblings('.zone-throbber').attr('style', 'background-image: url(' + settings.basePath + 'misc/throbber.gif); background-repeat: no-repeat; background-position: 100% -20px;').html('&nbsp;&nbsp;&nbsp;&nbsp;');
-
-  jQuery.post(settings.basePath + '?q=uc_js_util/zone_select', options,
-         function (contents) {
-           if (contents.match('value="-1"') != null) {
-             jQuery('#' + zone_select).attr('disabled', 'disabled');
-           }
-           else {
-             jQuery('#' + zone_select).removeAttr('disabled');
-           }
-           jQuery('#' + zone_select).empty().append(contents).val(default_zone).change();
-           jQuery('#' + zone_select).parent().siblings('.zone-throbber').removeAttr('style').empty();
-         }
-  );
-}
diff --git a/uc_store/uc_store.admin.inc b/uc_store/uc_store.admin.inc
index 8da52ae..5254da6 100644
--- a/uc_store/uc_store.admin.inc
+++ b/uc_store/uc_store.admin.inc
@@ -638,19 +638,19 @@ function uc_store_settings_form($form, &$form_state) {
     '#title' => t('Store address'),
     '#group' => 'store',
   );
-  $form['address']['uc_store_street1'] = uc_textfield(uc_get_field_name('street1'), variable_get('uc_store_street1', NULL), FALSE, NULL, 128);
-  $form['address']['uc_store_street2'] = uc_textfield(uc_get_field_name('street2'), variable_get('uc_store_street2', NULL), FALSE, NULL, 128);
-  $form['address']['uc_store_city'] = uc_textfield(uc_get_field_name('city'), variable_get('uc_store_city', NULL), FALSE);
-  $form['address']['uc_store_country'] = uc_country_select(uc_get_field_name('country'), uc_store_default_country());
-
-  if (isset($_POST['uc_store_country'])) {
-    $country_id = intval($_POST['uc_store_country']);
-  }
-  else {
-    $country_id = uc_store_default_country();
-  }
-  $form['address']['uc_store_zone'] = uc_zone_select(uc_get_field_name('zone'), variable_get('uc_store_zone', NULL), NULL, $country_id);
-  $form['address']['uc_store_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), variable_get('uc_store_postal_code', NULL), FALSE, NULL, 10);
+  $form['address']['address'] = array(
+    '#type' => 'uc_address',
+    '#default_value' => array(
+      'uc_store_street1' => variable_get('uc_store_street1', ''),
+      'uc_store_street2' => variable_get('uc_store_street2', ''),
+      'uc_store_city' => variable_get('uc_store_city', ''),
+      'uc_store_zone' => variable_get('uc_store_zone', 0),
+      'uc_store_country' => isset($form_state['values']) ? $form_state['values']['uc_store_country'] : uc_store_default_country(),
+      'uc_store_postal_code' => variable_get('uc_store_postal_code', ''),
+    ),
+    '#required' => FALSE,
+    '#key_prefix' => 'uc_store',
+  );
 
   $form['currency'] = array(
     '#type' => 'fieldset',
diff --git a/uc_store/uc_store.css b/uc_store/uc_store.css
index 8d82af7..15ce1b2 100644
--- a/uc_store/uc_store.css
+++ b/uc_store/uc_store.css
@@ -47,6 +47,21 @@
 }
 
 /**
+ * CSS rules for address fields.
+ */
+
+.uc-store-address-field .form-item {
+  clear: left;
+}
+
+.uc-store-address-field .form-item label {
+  float: left;
+  text-align: right;
+  width: 15em;
+  padding-right: 4px;
+}
+
+/**
  * CSS enhancements for Ubercart summary overviews.
  */
 .summary-overview {
diff --git a/uc_store/uc_store.module b/uc_store/uc_store.module
index 625ab4b..4e07d45 100644
--- a/uc_store/uc_store.module
+++ b/uc_store/uc_store.module
@@ -172,13 +172,6 @@ function uc_store_menu() {
     'file' => 'uc_store.admin.inc',
   );
 
-  $items['uc_js_util/%'] = array(
-    'title' => 'JS utilities',
-    'page callback' => 'uc_store_js_util',
-    'page arguments' => array(1),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
-  );
   $items['admin/store/customers/orders/%'] = array(
     'title' => 'Customer orders',
     'description' => 'View a list of orders placed by this customer.',
@@ -281,10 +274,153 @@ function uc_store_element_info() {
     '#process' => array('ajax_process_form'),
   );
 
+  $types['uc_address'] = array(
+    '#input' => TRUE,
+    '#required' => TRUE,
+    '#process' => array('uc_store_process_address_field'),
+    '#attributes' => array('class' => array('uc-store-address-field')),
+    '#theme_wrappers' => array('container'),
+    '#key_prefix' => '',
+  );
+
   return $types;
 }
 
 /**
+ * Element process hook for address fields.
+ */
+function uc_store_process_address_field($element, $form_state) {
+  $prefix = $element['#key_prefix'] ? ($element['#key_prefix'] . '_') : '';
+
+  // Ensure the value is an array.
+  if (is_array($element['#value']) || is_object($element['#value'])) {
+    $value = (array) $element['#value'];
+  }
+  else {
+    $value = array();
+  }
+
+  // Base fields on the UcAddress object.
+  $address = (array) new UcAddress();
+  $fields = array_keys($address);
+
+  foreach (array_keys($address) as $field) {
+    if (!isset($value[$prefix . $field])) {
+      continue;
+    }
+
+    $default = $value[$prefix . $field];
+
+    switch ($field) {
+      case 'country':
+        $countries = db_query("SELECT country_id, country_name FROM {uc_countries} WHERE version > :version", array(':version' => 0))->fetchAllKeyed();
+        natcasesort($countries);
+
+        $subelement = array(
+          '#type' => 'select',
+          '#options' => $countries,
+          '#ajax' => array(
+            'callback' => 'uc_store_update_address_field_zones',
+            'wrapper' => 'uc-store-address-' . str_replace('_', '-', $prefix) . 'zone-wrapper',
+            'progress' => array(
+              'type' => 'throbber',
+            ),
+          ),
+        );
+        break;
+
+      case 'zone':
+        $subelement = array(
+          '#type' => 'select',
+          '#prefix' => '<div id="uc-store-address-' . str_replace('_', '-', $prefix) . 'zone-wrapper">',
+          '#suffix' => '</div>',
+        );
+
+        $zones = db_query("SELECT zone_id, zone_name FROM {uc_zones} WHERE zone_country_id = :country", array(':country' => $value[$prefix . 'country']))->fetchAllKeyed();
+        if (!empty($zones)) {
+          natcasesort($zones);
+          $subelement += array(
+            '#options' => array('0' => t('Please select')) + $zones,
+          );
+        }
+        else {
+          $subelement += array(
+            '#options' => array('0' => t('Not applicable')),
+            '#disabled' => TRUE,
+            '#required' => FALSE,
+          );
+        }
+
+        // Avoid "illegal choice detected" errors when country field is changed.
+        if ($form_state['process_input'] && !$form_state['submitted'] && isset($value[$prefix . 'zone']) && !isset($subelement['#options'][$value[$prefix . 'zone']])) {
+          $subelement['#value'] = 0;
+        }
+        break;
+
+      case 'postal_code':
+        $subelement = array(
+          '#type' => 'textfield',
+          '#size' => 10,
+          '#maxlength' => 10,
+        );
+        break;
+
+      case 'phone':
+        $subelement = array(
+          '#type' => 'textfield',
+          '#size' => 16,
+          '#maxlength' => 32,
+        );
+        break;
+
+      default:
+        $subelement = array(
+          '#type' => 'textfield',
+          '#size' => 32,
+        );
+    }
+
+    // Copy JavaScript states from the parent element.
+    if (isset($element['#states'])) {
+      $subelement['#states'] = $element['#states'];
+    }
+
+    // Set common values for all address fields.
+    $element[$prefix . $field] = $subelement + array(
+      '#title' => uc_get_field_name($field),
+      '#default_value' => $default,
+      '#pre_render' => array('uc_store_pre_render_address_field'),
+      '#access' => uc_address_field_enabled($field),
+      '#required' => $element['#required'] ? uc_address_field_required($field) : FALSE,
+    );
+  }
+  return $element;
+}
+
+/**
+ * Ajax callback: updates the zone select box when the country is changed.
+ */
+function uc_store_update_address_field_zones($form, &$form_state) {
+  $element = &$form;
+  foreach (array_slice($form_state['triggering_element']['#array_parents'], 0, -1) as $field) {
+    $element = &$element[$field];
+  }
+  $prefix = isset($element['#key_prefix']) ? ($element['#key_prefix'] . '_') : '';
+  return $element[$prefix . 'zone'];
+}
+
+/**
+ * Prerenders address field elements to move the required marker when needed.
+ */
+function uc_store_pre_render_address_field($element) {
+  if (!empty($element['#required'])) {
+    $element['#title'] = theme('form_required_marker', $element) . ' ' . $element['#title'];
+    unset($element['#required']);
+  }
+  return $element;
+}
+
+/**
  * Implements hook_theme().
  */
 function uc_store_theme() {
@@ -693,26 +829,6 @@ function uc_store_address_fields_form_reset($form_id, &$form_state) {
   drupal_set_message(t('The configuration options have been reset to their default values.'));
 }
 
-/**
- * A handler for Javascript helper functions...
- */
-function uc_store_js_util($func) {
-  switch ($func) {
-    case 'zone_select':
-      $country_id = intval($_POST['country_id']) > 0 ? intval($_POST['country_id']) : uc_store_default_country();
-      $title = isset($_POST['title']) ? check_plain($_POST['title']) : NULL;
-      $display = isset($_POST['display']) ? check_plain($_POST['display']) : 'name';
-      $select = uc_zone_select($title, NULL, NULL, $country_id, $display);
-      $select['#parents'] = array();
-      $match = array('`<[/]*div[^>]*>`', '`<[/]*select[^>]*>`', '`\n|\r`');
-      $replace = array('', '', '');
-      $output = preg_replace($match, $replace, theme('select', array('element' => $select)));
-  }
-
-  print $output;
-  exit();
-}
-
 /*******************************************************************************
  * Module and Helper Functions
  ******************************************************************************/
@@ -1144,37 +1260,60 @@ function uc_zone_get_by_id($id) {
 /**
  * Creates a zone select box for a form.
  *
- * @param $display
- *   Can be 'code' or 'name'.
- */
-function uc_zone_select($title, $default = NULL, $description = NULL, $country_id = NULL, $display = 'name', $required = FALSE) {
+ * @param $title
+ *   The label for the field.
+ * @param $default
+ *   The default zone ID.
+ * @param $country_id
+ *   The country ID
+ * @param array $options
+ *   An associative array of additional options, with the following elements:
+ *   - 'description': The description for the field (defaults to none).
+ *   - 'display': The values to display, either 'name' (default) or 'code'.
+ *   - 'required': TRUE if the field is required (defaults to FALSE).
+ *   - 'ajax': If set, this should be the Form API reference to this element,
+ *     so it can be updated using Ajax when the country is changed.
+ *
+ * @return
+ *   A Form API select element.
+ */
+function uc_zone_select($title = '', $default = NULL, $country_id = NULL, $options = array()) {
+  $options += array(
+    'description' => NULL,
+    'display' => 'name',
+    'required' => FALSE,
+    'ajax' => '',
+  );
+
   if (empty($country_id)) {
     $country_id = uc_store_default_country();
   }
-  $order_by = ($display == 'code') ? 'zone_code' : 'zone_name';
 
-  $zones = db_query("SELECT * FROM {uc_zones} WHERE zone_country_id = :id ORDER BY $order_by", array(':id' => $country_id));
+  $order_by = ($options['display'] == 'code') ? 'zone_code' : 'zone_name';
+  $result = db_query("SELECT * FROM {uc_zones} WHERE zone_country_id = :id ORDER BY $order_by", array(':id' => $country_id));
 
-  $options[''] = t('Please select');
-  foreach ($zones as $zone) {
-    $options[$zone->zone_id] = ($display == 'code') ? $zone->zone_code : $zone->zone_name;
+  $zones = array('' => t('Please select'));
+  foreach ($result as $zone) {
+    $zones[$zone->zone_id] = $zone->$order_by;
   }
-
-  if (count($options) == 1) {
-    $options = array(-1 => t('Not applicable'));
+  if (count($zones) == 1) {
+    $zones = array(-1 => t('Not applicable'));
   }
 
   $select = array(
     '#type' => 'select',
     '#title' => $title,
-    '#description' => $description,
-    '#options' => $options,
+    '#description' => $options['description'],
+    '#options' => $zones,
     '#default_value' => $default,
-    '#required' => $required,
-    '#disabled' => isset($options[-1]) ? TRUE : FALSE,
-    '#suffix' => '<span class="zone-throbber"></span>',
+    '#required' => $options['required'],
+    '#disabled' => isset($zones[-1]),
   );
 
+  if ($options['ajax']) {
+    $select['#prefix'] = '<div id="ajax-' . str_replace('][', '-', $options['ajax']) . '">';
+    $select['#suffix'] = '</div>';
+  }
   return $select;
 }
 
@@ -1204,14 +1343,34 @@ function uc_country_get_by_id($id) {
 /**
  * Creates a country select box for a form.
  *
- * @param $display
- *   Can be 'name', 'code2' for the 2-digit code, or 'code3' for the 3-digit code.
- */
-function uc_country_select($title, $default = NULL, $description = NULL, $display = 'name', $required = FALSE) {
-  if ($display == 'code2') {
+ * @param $title
+ *   The label for the field.
+ * @param $default
+ *   The default country ID, or NULL to use the store default country.
+ * @param array $options
+ *   An associative array of additional options, with the following elements:
+ *   - 'description': The description for the field (defaults to none).
+ *   - 'display': The values to display, either 'name' (default), 'code2' for
+ *     the 2-character ISO code, or 'code3' for the 3-character ISO code.
+ *   - 'required': TRUE if the field is required (defaults to FALSE).
+ *   - 'ajax': If set, changing the country will update this related element
+ *     with a list of zones for this country.
+ *
+ * @return
+ *   A Form API select element.
+ */
+function uc_country_select($title, $default = NULL, $options = array()) {
+  $options += array(
+    'description' => NULL,
+    'display' => 'name',
+    'required' => FALSE,
+    'ajax' => '',
+  );
+
+  if ($options['display'] == 'code2') {
     $order_by = 'country_iso_code_2';
   }
-  elseif ($display == 'code3') {
+  elseif ($options['display'] == 'code3') {
     $order_by = 'country_iso_code_3';
   }
   else {
@@ -1220,31 +1379,53 @@ function uc_country_select($title, $default = NULL, $description = NULL, $displa
 
   $result = db_query("SELECT * FROM {uc_countries} WHERE version > :version ORDER BY $order_by", array(':version' => 0));
 
-  $options = array();
-  while ($country = $result->fetchAssoc()) {
-    $options[$country['country_id']] = $country[$order_by];
+  $countries = array();
+  foreach ($result as $country) {
+    $countries[$country->country_id] = $country->$order_by;
   }
-  if (count($options) == 0) {
-    $options[] = t('No countries found.');
+  if (empty($countries)) {
+    $countries[] = t('No countries found.');
   }
 
-  $default = db_query("SELECT country_id FROM {uc_countries} WHERE country_id = :id AND version > :version", array(':id' => empty($default) ? 0 : intval($default), ':version' => 0))->fetchField();
+  if (!$default || !isset($countries[$default])) {
+    $default = uc_store_default_country();
+  }
 
   $select = array(
     '#type' => 'select',
     '#title' => $title,
-    '#description' => $description,
-    '#options' => $options,
-    '#default_value' => empty($default) ? uc_store_default_country() : $default,
-    '#required' => $required,
+    '#description' => $options['description'],
+    '#options' => $countries,
+    '#default_value' => $default,
+    '#required' => $options['required'],
   );
 
-  drupal_add_js(drupal_get_path('module', 'uc_store') . '/uc_country_select.js');
+  if ($options['ajax']) {
+    $select['#ajax'] = array(
+      'callback' => 'uc_country_ajax_zone',
+      'wrapper' => 'ajax-' . str_replace('][', '-', $options['ajax']),
+      'progress' => array(
+        'type' => 'throbber',
+      ),
+    );
+  }
 
   return $select;
 }
 
 /**
+ * Ajax callback to updates the zone select box when the country is changed.
+ */
+function uc_country_ajax_zone($form, &$form_state) {
+  $keys = explode('-', substr($form_state['triggering_element']['#ajax']['wrapper'], 5));
+  while ($keys) {
+    $form = $form[array_shift($keys)];
+  }
+
+  return $form;
+}
+
+/**
  * Returns a list of available countries.
  */
 function uc_country_option_list() {
@@ -1356,6 +1537,34 @@ function uc_select_address($uid, $type = 'billing', $onchange = '', $title = NUL
 }
 
 /**
+ * Creates an address select box based on a user's previous orders.
+ *
+ * @param $uid
+ *   The user's ID to search for in the orders table.
+ * @param $type
+ *   Choose either 'shipping' or 'billing'.
+ */
+function uc_select_addresses($uid, $type = 'billing') {
+  $addresses = uc_get_addresses($uid, $type);
+
+  if (empty($addresses)) {
+    return array();
+  }
+
+  $options = array(-1 => t('Select one...'));
+  foreach ($addresses as $key => $address) {
+    $option = $address['street1'];
+    // Check if the address is a duplicate (i.e. same address, but sent to different person)
+    if ((isset($addresses[$key - 1]) && $option == $addresses[$key - 1]['street1']) ||
+        (isset($addresses[$key + 1]) && $option == $addresses[$key + 1]['street1'])) {
+      $option .= ' - ' . $address['first_name'] . ' ' . $address['last_name'];
+    }
+    $options[$key] = check_plain($option);
+  }
+  return $options;
+}
+
+/**
  * Loads a customer's previously given addresses.
  */
 function uc_get_addresses($uid, $type = 'billing') {
