diff --git a/include/phone.ca.inc b/include/phone.ca.inc
index 6fa1432..2250699 100644
--- a/include/phone.ca.inc
+++ b/include/phone.ca.inc
@@ -44,10 +44,12 @@ function valid_ca_phone_number($phonenumber) {
 /**
  * Convert a valid North American phone number into standard (444) 867-5309 x1234 format
  *
- * @param $phonenumber must be a valid ten-digit number (with optional extension)
- *
+ * @param string $phonenumber
+ *   Phone number; must be a valid ten-digit number (with optional extension).
+ * @param array $instance_settings
+ * @return string
  */
-function format_ca_phone_number($phonenumber, $field) {
+function format_ca_phone_number($phonenumber, $instance_settings) {
 
   // define regular expression
   $regex = '/
@@ -67,11 +69,11 @@ function format_ca_phone_number($phonenumber, $field) {
   // get digits of phone number
   preg_match($regex, $phonenumber, $matches);
 
-  $separator = isset($field['ca_phone_separator']) ? $field['ca_phone_separator'] : '-';
+  $separator = isset($instance_settings['ca_phone_separator']) ? $instance_settings['ca_phone_separator'] : '-';
 
   // construct ten-digit phone number
   $phonenumber =
-    ( $field['ca_phone_parentheses'] ?
+    ( $instance_settings['ca_phone_parentheses'] ?
       '(' . $matches[2] . ') ' :
       $matches[2] . $separator ) .
       $matches[3] . $separator . $matches[4];
@@ -81,7 +83,7 @@ function format_ca_phone_number($phonenumber, $field) {
       $phonenumber .= ' x' . $matches[5];
   }
 
-  if ($field['phone_country_code']) {
+  if ($instance_settings['phone_country_code']) {
     // This condition check is pointless.  
     if ($matches[1] != '1') {
   	$phonenumber = '1' . ' ' . $phonenumber;
diff --git a/include/phone.int.inc b/include/phone.int.inc
index 68db303..70499dd 100644
--- a/include/phone.int.inc
+++ b/include/phone.int.inc
@@ -3,7 +3,7 @@
 function phone_int_metadata() {
   // These strings are translated using t() on output.
   return array(
-    'error' => '"%value" is not a valid Italian phone number<br>Italian phone numbers should only ...',
+    'error' => '"%value" is not a valid international phone number',
   );
 }
 
@@ -14,21 +14,23 @@ function phone_int_metadata() {
  * @see http://www.itu.int/rec/T-REC-E.123/en
  *
  * @param $phonenumber
- *   International phone number to validate
- * @return
+ *   International phone number to validate.
+ * @param array $instance_settings
+ *   Settings configured in the phone field instance.
+ * @return bool
  *   TRUE if valid, FALSE if otherwise.
  */
-function valid_int_phone_number($phonenumber) {
+function valid_int_phone_number($phonenumber, $instance_settings) {
   $phonenumber = trim($phonenumber);
   if ($phonenumber === '') {
     return FALSE;
   }
   $phonenumber = _normalize_country_code($phonenumber);
   $base_phonenumber = str_replace(array('.', '(', ')', '[', ']', '-', '+', ' '), '', $phonenumber);
-  if (!isset($field['phone_int_max_length'])) {
-    $field['phone_int_max_length'] = 15;
+  if (!isset($instance_settings['phone_int_max_length'])) {
+    $instance_settings['phone_int_max_length'] = 15;
   }
-  if (strlen($base_phonenumber) > $field['phone_int_max_length']) {
+  if (strlen($base_phonenumber) > $instance_settings['phone_int_max_length']) {
     $error = t('Invalid international phone number: Phone number is too long; international phone numbers are limited to 15 digits.');
     return FALSE;
   }
@@ -37,33 +39,40 @@ function valid_int_phone_number($phonenumber) {
     $error = t('Invalid international phone number: Phone number contains invalid characters; only allowed characters are numbers and punctuation.');
     return FALSE;
   }
-  // Extract country code and see if it's correct:
-  preg_match('/^\+(\d+)/', $phonenumber, $matches);
-  $cc = $matches[1];
-  if (strlen($cc) > 3) {
-    $error = array(
-      t('Invalid international phone number: Country code "+%cc" is too long; valid country codes are three digits or less.'),
-      array('%cc' => $cc)
-    );
+
+  if ($phonenumber[0] !== '+') {
     return FALSE;
   }
-  
-  //drupal_set_message('langue cc = ' . $cc, 'error');
+  // Check for correct country code.
+  // TODO: Fix problems with shared country codes. For instance, $countrycode is
+  //       never 'ca' (but always 'us'). One of the following things needs done:
+  //       - all countries sharing the same area need to be validated in the
+  //         same .inc file (e.g. phone.1.inc or phone.61.inc)
+  //       - there will need to be a separate 'pre-validate' function that
+  //         determines which country a phone number belongs to.
+  $codes = array_flip(array_unique(phone_country_codes()));
+  foreach (array(1, 2, 3) as $length) {
+    $nr_start = substr($phonenumber, 1, $length);
+    if (isset($codes[$nr_start])) {
+      $countrycode = $codes[$nr_start];
+      break;
+    }
+  }
 
   // TODO: Check if parentheses/brackets add up.
-  // TODO: Validate the number against the country rules.
   // For now, validate only against a limited number of countries.
 
-  $countrycode = phone_country_code_convert($cc);
-  //drupal_set_message('langue countrycode = ' . $countrycode, 'error');
   if (!empty($countrycode)) {
       $valid_phone_function = 'valid_'. $countrycode . '_phone_number';
-      module_load_include('inc', 'phone', 'phone.'. $countrycode);
+      module_load_include('inc', 'phone', 'include/phone.' . $countrycode);
       if (function_exists($valid_phone_function)) {
-        return $valid_phone_function($phonenumber, $field);
+        return $valid_phone_function($phonenumber, $instance_settings);
       }
       else {
-      	return TRUE; 
+        // Check for any illegal dialing codes, which the 'format' call would
+        // strip.
+        $check = str_replace(array('.', '(', ')', '[', ']', '-', '+', ' '), '', format_int_phone_number($phonenumber));
+        return $check == $base_phonenumber;
       }
   }
   
@@ -74,17 +83,19 @@ function valid_int_phone_number($phonenumber) {
  * Formats $phonenumber into the standard representation of international
  * numbers as per E.123.
  *
- * @param $phonenumber
- *   International phone number to format
- * @return
- *   Formatted international phone number
+ * @param string $phonenumber
+ *   International phone number to format.
+ * @param array $instance_settings
+ *   Settings configured in the phone field instance.
+ * @return string
+ *   Formatted international phone number.
  */
-function format_int_phone_number($phonenumber, $field = array()) {
+function format_int_phone_number($phonenumber, $instance_settings = array()) {
   $phonenumber = trim($phonenumber);
   if ($phonenumber === '') {
     return '';
   }
-  $phonenumber = _normalize_country_code($phonenumber, $field);
+  $phonenumber = _normalize_country_code($phonenumber, $instance_settings);
   $bits = preg_split('/[.()\[\]\- ]/', $phonenumber, -1, PREG_SPLIT_NO_EMPTY);
   // $bits[0] is the country code WITH a plus sign.
   if (isset($bits[1])) {
@@ -109,13 +120,15 @@ function format_int_phone_number($phonenumber, $field = array()) {
  * Adds a country code to a phone number if necessary.
  *
  * @param $phonenumber
- *   International or local phone number to format
- * @return
- *   International phone number with country code
+ *   International or local phone number to format.
+ * @param array $instance_settings
+ *   Settings configured in the phone field instance.
+ * @return string
+ *   International phone number with country code.
  */
-function _normalize_country_code($phonenumber, $field = array()) {
+function _normalize_country_code($phonenumber, $instance_settings = array()) {
   if ($phonenumber[0] !== '+') {
-    $cc = isset($field['phone_default_country_code']) ? $field['phone_default_country_code'] : '1';
+    $cc = isset($instance_settings['phone_default_country_code']) ? $instance_settings['phone_default_country_code'] : '1';
     return "+$cc $phonenumber";
   }
   return $phonenumber;
@@ -134,221 +147,227 @@ function _normalize_country_code($phonenumber, $field = array()) {
  *   Converted country code
  */
 function phone_country_code_convert($code, $input_type = 'digits') {
-   static $codes;
-   if (!$codes) {
-    $codes = array(    
-      '1' => 'ca',
-      '1' => 'us',
-      '7' => 'ru',
-      '20' => 'eg',
-      '27' => 'za',
-      '30' => 'gr',
-      '31' => 'nl',
-      '32' => 'be',
-      '33' => 'fr',
-      '34' => 'es',
-      '36' => 'hu',
-      '39' => 'it',
-      '39' => 'va',
-      '40' => 'ro',
-      '41' => 'ch',
-      '43' => 'at',
-      '44' => 'gb',
-      '45' => 'dk',
-      '46' => 'se',
-      '47' => 'no',
-      '48' => 'pl',
-      '49' => 'de', 
-      '51' => 'pe',
-      '52' => 'mx',
-      '53' => 'cu',
-      '54' => 'ar',
-      '55' => 'br',
-      '56' => 'cl',
-      '57' => 'co',
-      '58' => 've',    
-      '60' => 'my',
-      '61' => 'au',
-      '61' => 'cc',
-      '61' => 'cx',
-      '62' => 'id',
-      '63' => 'ph',
-      '64' => 'nz',
-      '65' => 'sg',
-      '66' => 'th',
-      '81' => 'jp',
-      '82' => 'kr',
-      '84' => 'vn',
-      '86' => 'cn',
-      '90' => 'tr',
-      '91' => 'in',
-      '92' => 'pk',
-      '93' => 'af',
-      '94' => 'lk',
-      '95' => 'mm',
-      '98' => 'ir', 
-      '212' => 'ma',
-      '213' => 'dz',
-      '216' => 'tn',
-      '218' => 'ly',
-      '220' => 'gm',
-      '221' => 'sn',
-      '222' => 'mr',
-      '223' => 'ml',
-      '224' => 'gn',
-      '225' => 'ci',
-      '226' => 'bf',
-      '227' => 'ne',
-      '228' => 'tg',
-      '229' => 'bj',
-      '230' => 'mu',
-      '231' => 'lr',
-      '232' => 'sl',
-      '233' => 'gh',
-      '234' => 'ng',
-      '235' => 'td',
-      '236' => 'cf',
-      '237' => 'cm',
-      '238' => 'cv',
-      '239' => 'st',
-      '240' => 'gq',
-      '241' => 'ga',
-      '242' => 'cg',
-      '243' => 'cd',
-      '244' => 'ao',
-      '245' => 'gw',
-      '246' => 'io',
-      '248' => 'sc',
-      '249' => 'sd',
-      '250' => 'rw',
-      '251' => 'et',
-      '252' => 'so',
-      '253' => 'dj',
-      '254' => 'ke',
-      '255' => 'tz',
-      '256' => 'ug',
-      '257' => 'bi',
-      '258' => 'mz',
-      '260' => 'zm',
-      '261' => 'mg',
-      '263' => 'zw',
-      '264' => 'na',
-      '265' => 'mw',
-      '266' => 'ls',
-      '267' => 'bw',
-      '268' => 'sz',
-      '269' => 'km',
-      '269' => 'yt',
-      '290' => 'sh',
-      '291' => 'er',
-      '297' => 'aw',
-      '298' => 'fo',
-      '299' => 'gl',
-      '350' => 'gi',
-      '351' => 'pt',
-      '352' => 'lu',
-      '353' => 'ie',
-      '354' => 'is',
-      '355' => 'al',
-      '356' => 'mt',
-      '357' => 'cy',
-      '358' => 'fi',
-      '359' => 'bg',
-      '370' => 'lt',
-      '371' => 'lv',
-      '372' => 'ee',
-      '373' => 'md',
-      '374' => 'am',
-      '375' => 'by',
-      '376' => 'ad',
-      '377' => 'mc',
-      '378' => 'sm',
-      '380' => 'ua',
-      '381' => 'rs',
-      '382' => 'me',
-      '385' => 'hr',
-      '386' => 'si',
-      '387' => 'ba',
-      '389' => 'mk',   
-      '420' => 'cz',
-      '421' => 'sk',
-      '423' => 'li',
-      '500' => 'fk',
-      '501' => 'bz',
-      '502' => 'gt',
-      '503' => 'sv',
-      '504' => 'hn',
-      '505' => 'ni',
-      '506' => 'cr',
-      '507' => 'pa',
-      '508' => 'pm',
-      '509' => 'ht',
-      '590' => 'gp',
-      '591' => 'bo',
-      '592' => 'gy',
-      '593' => 'ec',
-      '594' => 'gf',
-      '595' => 'py',
-      '596' => 'mq',
-      '597' => 'sr',
-      '598' => 'uy',
-      '599' => 'an',
-      '670' => 'tp',
-      '672' => 'nf',
-      '673' => 'bn',
-      '674' => 'nr',
-      '675' => 'pg',
-      '676' => 'to',
-      '677' => 'sb',
-      '678' => 'vu',
-      '679' => 'fj',
-      '680' => 'pw',
-      '681' => 'wf',
-      '682' => 'ck',
-      '683' => 'nu',
-      '686' => 'ki',
-      '687' => 'nc',
-      '688' => 'tv',
-      '689' => 'pf',
-      '690' => 'tk',
-      '691' => 'fm',
-      '692' => 'mh', 
-      '850' => 'kp',
-      '852' => 'hk',
-      '853' => 'mo',
-      '855' => 'kh',
-      '856' => 'la',
-      '880' => 'bd',
-      '886' => 'tw', 
-      '960' => 'mv',
-      '961' => 'lb',
-      '962' => 'jo',
-      '963' => 'sy',
-      '964' => 'iq',
-      '965' => 'kw',
-      '966' => 'sa',
-      '967' => 'ye',
-      '968' => 'om',
-      '970' => 'ps',
-      '971' => 'ae',
-      '972' => 'il',
-      '973' => 'bh',
-      '974' => 'qa',
-      '975' => 'bt',
-      '976' => 'mn',
-      '977' => 'np',
-      '992' => 'tj',
-      '993' => 'tm',
-      '994' => 'az',
-      '995' => 'ge',
-      '996' => 'kg',
-      '998' => 'uz',      
-    );
-   }
+  $codes = phone_country_codes();
 
-  if ($input_type == 'alpha') {
-    $codes = array_flip($codes);
+  if ($input_type == 'digits') {
+    $codes = array_flip(array_unique($codes));
   }
   return isset($codes[$code]) ? $codes[$code] : FALSE;
 }
 
+/**
+ * Returns an array of country codes and 2-letter abbreviations for each.
+ *
+ * @return
+ *   An array of country codes.
+ */
+function phone_country_codes() {
+  return array(
+    'us' => '1',
+    'ca' => '1',
+    'ru' => '7',
+    'eg' => '20',
+    'za' => '27',
+    'gr' => '30',
+    'nl' => '31',
+    'be' => '32',
+    'fr' => '33',
+    'es' => '34',
+    'hu' => '36',
+    'it' => '39',
+    'va' => '39',
+    'ro' => '40',
+    'ch' => '41',
+    'at' => '43',
+    'gb' => '44',
+    'dk' => '45',
+    'se' => '46',
+    'no' => '47',
+    'pl' => '48',
+    'de' => '49',
+    'pe' => '51',
+    'mx' => '52',
+    'cu' => '53',
+    'ar' => '54',
+    'br' => '55',
+    'cl' => '56',
+    'co' => '57',
+    've' => '58',
+    'my' => '60',
+    'au' => '61',
+    'cc' => '61',
+    'cx' => '61',
+    'id' => '62',
+    'ph' => '63',
+    'nz' => '64',
+    'sg' => '65',
+    'th' => '66',
+    'jp' => '81',
+    'kr' => '82',
+    'vn' => '84',
+    'cn' => '86',
+    'tr' => '90',
+    'in' => '91',
+    'pk' => '92',
+    'af' => '93',
+    'lk' => '94',
+    'mm' => '95',
+    'ir' => '98',
+    'ma' => '212',
+    'dz' => '213',
+    'tn' => '216',
+    'ly' => '218',
+    'gm' => '220',
+    'sn' => '221',
+    'mr' => '222',
+    'ml' => '223',
+    'gn' => '224',
+    'ci' => '225',
+    'bf' => '226',
+    'ne' => '227',
+    'tg' => '228',
+    'bj' => '229',
+    'mu' => '230',
+    'lr' => '231',
+    'sl' => '232',
+    'gh' => '233',
+    'ng' => '234',
+    'td' => '235',
+    'cf' => '236',
+    'cm' => '237',
+    'cv' => '238',
+    'st' => '239',
+    'gq' => '240',
+    'ga' => '241',
+    'cg' => '242',
+    'cd' => '243',
+    'ao' => '244',
+    'gw' => '245',
+    'io' => '246',
+    'sc' => '248',
+    'sd' => '249',
+    'rw' => '250',
+    'et' => '251',
+    'so' => '252',
+    'dj' => '253',
+    'ke' => '254',
+    'tz' => '255',
+    'ug' => '256',
+    'bi' => '257',
+    'mz' => '258',
+    'zm' => '260',
+    'mg' => '261',
+    'zw' => '263',
+    'na' => '264',
+    'mw' => '265',
+    'ls' => '266',
+    'bw' => '267',
+    'sz' => '268',
+    'km' => '269',
+    'yt' => '269',
+    'sh' => '290',
+    'er' => '291',
+    'aw' => '297',
+    'fo' => '298',
+    'gl' => '299',
+    'gi' => '350',
+    'pt' => '351',
+    'lu' => '352',
+    'ie' => '353',
+    'is' => '354',
+    'al' => '355',
+    'mt' => '356',
+    'cy' => '357',
+    'fi' => '358',
+    'bg' => '359',
+    'lt' => '370',
+    'lv' => '371',
+    'ee' => '372',
+    'md' => '373',
+    'am' => '374',
+    'by' => '375',
+    'ad' => '376',
+    'mc' => '377',
+    'sm' => '378',
+    'ua' => '380',
+    'rs' => '381',
+    'me' => '382',
+    'hr' => '385',
+    'si' => '386',
+    'ba' => '387',
+    'mk' => '389',
+    'cz' => '420',
+    'sk' => '421',
+    'li' => '423',
+    'fk' => '500',
+    'bz' => '501',
+    'gt' => '502',
+    'sv' => '503',
+    'hn' => '504',
+    'ni' => '505',
+    'cr' => '506',
+    'pa' => '507',
+    'pm' => '508',
+    'ht' => '509',
+    'gp' => '590',
+    'bo' => '591',
+    'gy' => '592',
+    'ec' => '593',
+    'gf' => '594',
+    'py' => '595',
+    'mq' => '596',
+    'sr' => '597',
+    'uy' => '598',
+    'an' => '599',
+    'tp' => '670',
+    'nf' => '672',
+    'bn' => '673',
+    'nr' => '674',
+    'pg' => '675',
+    'to' => '676',
+    'sb' => '677',
+    'vu' => '678',
+    'fj' => '679',
+    'pw' => '680',
+    'wf' => '681',
+    'ck' => '682',
+    'nu' => '683',
+    'ki' => '686',
+    'nc' => '687',
+    'tv' => '688',
+    'pf' => '689',
+    'tk' => '690',
+    'fm' => '691',
+    'mh' => '692',
+    'kp' => '850',
+    'hk' => '852',
+    'mo' => '853',
+    'kh' => '855',
+    'la' => '856',
+    'bd' => '880',
+    'tw' => '886',
+    'mv' => '960',
+    'lb' => '961',
+    'jo' => '962',
+    'sy' => '963',
+    'iq' => '964',
+    'kw' => '965',
+    'sa' => '966',
+    'ye' => '967',
+    'om' => '968',
+    'ps' => '970',
+    'ae' => '971',
+    'il' => '972',
+    'bh' => '973',
+    'qa' => '974',
+    'bt' => '975',
+    'mn' => '976',
+    'np' => '977',
+    'tj' => '992',
+    'tm' => '993',
+    'az' => '994',
+    'ge' => '995',
+    'kg' => '996',
+    'uz' => '998',
+  );
+}
diff --git a/phone.module b/phone.module
index 9be0fd0..7d5d2e5 100644
--- a/phone.module
+++ b/phone.module
@@ -62,6 +62,7 @@ function phone_field_info() {
       'label' => t('Phone Number'),
       'instance_settings' => array(
         'phone_country_code' => 0,
+        'phone_default_country_field' => '',
         'phone_default_country_code' => '1',
         'phone_int_max_length' => 15,
         'ca_phone_separator' => '-',
@@ -118,15 +119,56 @@ function phone_field_instance_settings_form($field, $instance) {
       '#type' => 'markup',
       '#value' => t('International phone numbers are in the form +XX YYYYYYY where XX is a country code and YYYYYYY is the local number. This field type is based off of the <a href="http://www.itu.int/rec/T-REC-E.123/en">E.123 specification</a>.'),
     );
+
+    $instance_fields = array('' => '- Choose -');
+    foreach (field_info_instances($instance['entity_type'], $instance['bundle'])
+             as $field_name => $instance_info) {
+      if ($instance_info['id'] != $instance['id']) {
+        $field_info = field_info_field_by_id($instance_info['field_id']);
+        if (in_array($field_info['type'], array(
+          'text',
+          'list_text',
+          'number_integer',
+          'list_integer',
+          'addressfield'
+        ), TRUE)) {
+          $instance_fields[$field_name] = $instance_info['label'];
+        }
+      }
+    }
+    $form['phone_default_country_field'] = array(
+      '#type' => 'select',
+      '#title' => t('Field containing the default country to add / use for verification, for non-international numbers.'),
+      '#description' => t('Phone numbers will be validated for the country (code) value entered in this field. If you need a fixed default country instead, leave this empty and use the text box just below.'),
+      '#options' => $instance_fields,
+      '#default_value' => !empty($settings['phone_default_country_field']) ? $settings['phone_default_country_field'] : '',
+      '#states' => array(
+        'invisible' => array(
+          ':input[name="field[settings][country]"]' => array('!value' => 'int'),
+        ),
+      ),
+    );
+
     $form['phone_default_country_code'] = array(
       '#type' => 'textfield',
       '#title' => t('Default country code to add to international numbers without one (omit + sign)'),
       '#default_value' => $settings['phone_default_country_code'],
+      '#states' => array(
+        'visible' => array(
+          ':input[name="instance[settings][phone_default_country_field]"]' => array('value' => ''),
+          ':input[name="field[settings][country]"]' => array('value' => 'int'),
+        ),
+      ),
     );
     $form['phone_int_max_length'] = array(
       '#type' => 'textfield',
       '#title' => t('Maximum length of international numbers, according to the ITU this is 15'),
       '#default_value' => $settings['phone_int_max_length'],
+      '#states' => array(
+        'invisible' => array(
+          ':input[name="field[settings][country]"]' => array('!value' => 'int'),
+        ),
+      ),
     );
   }
 
@@ -152,9 +194,9 @@ function phone_field_instance_settings_form($field, $instance) {
 function phone_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
   foreach ($items as $delta => $item) {
     if (isset($item['value']) && $item['value'] != '') {
-      $ccode = $field['settings']['country'];
+      $ccode = !empty($item['countrycode']) ? $item['countrycode'] :  $field['settings']['country'];
       $value = $item['value'];
-      if (!valid_phone_number($ccode, $value)) {
+      if (!valid_phone_number($ccode, $value, $instance['settings'])) {
         $country = phone_country_info($ccode);
         $errors[$field['field_name']][$langcode][$delta][] = array(
           'error' => 'phone_invalid_number',
@@ -166,14 +208,19 @@ function phone_field_validate($entity_type, $entity, $field, $instance, $langcod
 }
 
 /**
- * Implements hook_field_presave().
+ * Implements hook_field_prepare_view().
  */
-function phone_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
-  $ccode = $field['settings']['country'];
-  if (phone_countries($ccode) !== NULL) {
-    foreach ($items as $delta => $item) {
+function phone_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
+  foreach ($items as $id => $items_per_entity) {
+    foreach ($items_per_entity as $delta => $item) {
       if (isset($item['value'])) {
-        $items[$delta]['value'] = format_phone_number($ccode, $item['value'], $instance['settings']);
+        // Prefer dynamic country value over field setting. (It's probably only
+        // set by phone_element_validate(), only if field setting is 'int', but
+        // other code could fill it. The same column name is used by v2.x.
+        $ccode = !empty($item['countrycode']) ? $item['countrycode'] :  $field['settings']['country'];
+        if (phone_countries($ccode) !== NULL) {
+          $items[$id][$delta]['value'] = format_phone_number($ccode, $item['value'], $instances[$id]['settings']);
+        }
       }
     }
   }
@@ -234,12 +281,13 @@ function phone_field_widget_form(&$form, &$form_state, $field, $instance, $langc
     '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '',
     '#required' => $element['#required'],
     '#size' => 17,
-    '#maxlength' => (
-      $field['settings']['country'] == 'int' ?
-        (isset($instance['settings']['phone_int_max_length']) ? $instance['settings']['phone_int_max_length'] : NULL)
-        : NULL
-    ),
   );
+  if ($field['settings']['country'] == 'int') {
+    $element += array(
+      '#maxlength' => isset($instance['settings']['phone_int_max_length']) ? $instance['settings']['phone_int_max_length'] : NULL,
+      '#element_validate' => array('phone_element_validate'),
+    );
+  }
   return array('value' => $element);
 }
 
@@ -249,6 +297,63 @@ function phone_field_widget_form(&$form, &$form_state, $field, $instance, $langc
 
 
 /**
+ * element_validate function for a phone field.
+ */
+function phone_element_validate($element, &$form_state, $complete_form) {
+  // An 'international' field needs to know which country to validate against.
+  // If that country comes from another field, we need to make sure that value
+  // is present in phone_field_validate(), so we copy it into the field item.
+
+  if (isset($element['#field_name']) && isset($element['#entity']) && isset($element['#entity_type'])) {
+    $field_info = field_info_field($element['#field_name']);
+    if ($field_info['settings']['country'] == 'int') {
+      // This field is 'international'...
+      list (,,$bundle) = entity_extract_ids($element['#entity_type'], $element['#entity']);
+      $instance_info = field_info_instance($element['#entity_type'], $element['#field_name'], $bundle);
+      if (!empty($instance_info['settings']['phone_default_country_field'])) {
+        // ...and has a country field that is a dependency of this one.
+
+        // Prepare for getting/setting value in $form_state. We assume our
+        // #parents ends with OUR_FIELDNAME / LANGCODE / DELTA / 'value' ...
+        $phone_field_parents = $element['#parents'];
+        array_pop($phone_field_parents);
+        // ...and that $form_state has our country field on the same level.
+        // Get field item.
+        $cc_field_parents = $phone_field_parents;
+        array_splice($cc_field_parents, -3, 1, $instance_info['settings']['phone_default_country_field']);
+        $cc_item = drupal_array_get_nested_value($form_state['values'], $cc_field_parents);
+
+        // Get country code from the field item.
+        $countrycode = '';
+        if (!empty($cc_item['country'])) {
+          // This works for addressfield.
+          $countrycode = $cc_item['country'];
+        }
+        elseif (!empty($cc_item['value'])) {
+          // This works for most fields.
+          $countrycode = $cc_item['value'];
+        }
+        if ($countrycode) {
+
+          if (is_numeric($countrycode)) {
+            // We support numeric phone codes too; convert to 2-letter country.
+            module_load_include('inc', 'phone', 'include/phone.int');
+            $countrycode = phone_country_code_convert($countrycode);
+          }
+          if ($countrycode) {
+            // Insert the value 'next to' the phone number's 'value' value. This
+            // way it will be passed to phone_field_validate().
+            $phone_field_parents[] = 'countrycode';
+            drupal_array_set_nested_value($form_state['values'], $phone_field_parents, strtolower($countrycode));
+          }
+        }
+      }
+    }
+  }
+}
+
+
+/**
  * @defgroup other_hooks Other Hook Implementations
  */
 
@@ -340,10 +445,15 @@ function phone_country_info($countrycode = NULL) {
  * Verification for Phone Numbers.
  *
  * @param string $countrycode
+ *   Country code to validate the number for, or 'int' for international number.
  * @param string $phonenumber
- * @return boolean Returns boolean FALSE if the phone number is not valid.
+ *   Phone number to validate.
+ * @param array $instance_settings
+ *   Settings configured in the phone field instance.
+ * @return boolean
+ *   FALSE if the phone number is not valid.
  */
-function valid_phone_number($countrycode, $phonenumber) {
+function valid_phone_number($countrycode, $phonenumber, $instance_settings = array()) {
 
   $countrycode = trim($countrycode);
   $phonenumber = trim($phonenumber);
@@ -353,7 +463,7 @@ function valid_phone_number($countrycode, $phonenumber) {
     module_load_include('inc', 'phone', 'include/phone.'. $countrycode);
 
     if (function_exists($valid_phone_function)) {
-       return $valid_phone_function($phonenumber);
+      return $valid_phone_function($phonenumber, $instance_settings);
     }
   }
   //Country not taken into account yet
@@ -364,10 +474,15 @@ function valid_phone_number($countrycode, $phonenumber) {
  * Formatting for Phone Numbers.
  *
  * @param string $countrycode
+ *   Country code to validate the number for, or 'int' for international number.
  * @param string $phonenumber
- * @return boolean Returns boolean FALSE if the phone number is not valid.
+ *   Phone number to format.
+ * @param array $instance_settings
+ *   Settings configured in the phone field instance.
+ * @return string
+ *   Formatted phone number.
  */
-function format_phone_number($countrycode, $phonenumber, $field) {
+function format_phone_number($countrycode, $phonenumber, $instance_settings) {
 
   $countrycode = trim($countrycode);
   $phonenumber = trim($phonenumber);
@@ -377,10 +492,10 @@ function format_phone_number($countrycode, $phonenumber, $field) {
     module_load_include('inc', 'phone', 'include/phone.'. $countrycode);
 
     if (function_exists($format_phone_function)) {
-      return $format_phone_function($phonenumber, $field);
+      return $format_phone_function($phonenumber, $instance_settings);
     }
   }
   //Country not taken into account yet
-  return FALSE;
+  return $phonenumber;
 }
 
