diff --git a/gml.inc b/gml.inc
new file mode 100644
index 0000000..9118958
--- /dev/null
+++ b/gml.inc
@@ -0,0 +1,122 @@
+<?php
+// $Id: gml.inc,v 1.1.2.4 2010/05/19 14:29:42 tmcw Exp $
+
+/**
+ * @file WKT to GML converter
+ * Adapted from OpenLayers
+ */
+
+//TODO: namespace or encapsulate into a class
+
+define('NS_GML', 'http://www.opengis.net/gml');
+
+/**
+ * @param $wkt string of WKT data
+ * @return $geometry array of parsed geometry
+ *
+ * This function is not intended to be tested: 
+ * it is parsing geometries into an internal format.
+ */
+function parse_wkt($wkt) {
+  $type_string = '/^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/';
+  $paren_comma = '/\)\s*,\s*\(/';
+  $trim_parens = '/^\s*\(?(.*?)\)?\s*$/';
+
+  $geometry = array();
+  if (preg_match($type_string, $wkt, $matches)) {
+    $type = strtolower($matches[1]);
+    
+    if ($type == 'polygon' || $type == 'geometrycollection') {
+      $content = $matches[2];
+      $rings = preg_split($paren_comma, $content);
+      $rings = preg_replace($trim_parens, '$1', $rings);
+
+      foreach ($rings as $ring) {
+        $r = array();
+        $points = explode(',', $ring);
+
+        foreach ($points as $point) {
+          $r[] = trim($point);
+        }
+        $geometry[] = $r;
+      }
+    }
+  }
+
+  return $geometry;
+}
+
+/**
+ * @param $geometry array of parsed geometry
+ * @return $gml string of GML XML
+ */
+function geometry_to_gml($geometry) {
+  $doc = new SimpleXMLElement(
+    "<gml:polygon xmlns:gml='http://www.opengis.net/gml'></gml:polygon>");
+  $gml = $doc->addChild('Polygon', '', NS_GML);
+  $outer = TRUE;
+
+  foreach ($geometry as $ring) {
+    if ($outer) {
+      $boundary = $gml->addChild('exterior', '', NS_GML);
+      $outer = FALSE;
+    } else {
+      $boundary = $gml->addChild('interior', '', NS_GML);
+    }
+
+    $linear_ring = $boundary->addChild('gml:LinearRing', '', NS_GML);
+    $pos = $linear_ring->addChild('gml:posList', implode(' ', $ring), NS_GML);
+    $pos->addAttribute('decimal', '.');
+  }
+
+  // this workaround required by the fact that 
+  // ->asXML() on root elements will produce XML opening and 
+  // closing tags
+  return $doc->children(NS_GML)->asXML();
+}
+
+
+/**
+ * @param $geometry array of parsed geometry
+ * @return $kml string of KML XML
+ */
+function geometry_to_multigeometry_kml($geometry) {
+  $doc = new SimpleXMLElement("<MultiGeometry></MultiGeometry>");
+  $kml = $doc->addChild('MultiGeometry');
+  foreach ($geometry as $ring) {
+    foreach ($ring as $point) {
+      // Extract coordinates from POINT element 
+      $coordinates = check_plain(str_replace(array('POINT(', ')', ' '), array('', '', ','), $point)).',0';
+      $root_point = $kml->addChild('Point');
+      $coordinates = $root_point->addChild('coordinates', $coordinates);
+    }
+  }
+  return $doc->children()->asXML();
+}
+
+/**
+ * Convert WKT to GML
+ * @param $wkt a string of wkt
+ * @return $gml a string of gml (or FALSE if no features)
+ *
+ * This is a convenience function for converting wkt to gml
+ */
+function wkt_to_gml($wkt) {
+  $geometry = parse_wkt($wkt);
+  return empty($geometry) ? FALSE : geometry_to_gml($geometry);
+}
+
+
+/**
+ * Convert WKT to GML
+ * @param $wkt a string of wkt
+ * @return $gml a string of gml (or FALSE if no features)
+ *
+ * This is a convenience function for converting wkt to MultiGeometry element collection
+ */
+function wkt_to_kml($wkt) {
+  $geometry = parse_wkt($wkt);
+  return empty($geometry) ? FALSE : geometry_to_multigeometry_kml($geometry);
+}
+
+
diff --git a/kml.module b/kml.module
index 2c2c0af..21257b9 100644
--- a/kml.module
+++ b/kml.module
@@ -1,6 +1,7 @@
 <?php
 // $Id: kml.module,v 1.8.2.2 2010/06/10 17:36:50 tmcw Exp $
 
+
 /**
  * @file
  * KML module.
@@ -28,6 +29,12 @@ function kml_theme() {
       'template' => 'kml-placemark',
       'path' => $path . "/views",
     ),
+    'kml_placemark_wkt' => array(
+      'arguments' => array('point' => array(), 'points' => array()),
+      'file' => 'kml_views.theme.inc',
+      'template' => 'kml-placemark-wkt',
+      'path' => $path . "/views",
+    ),
     'kml_style' => array(
       'arguments' => array('id' => array(), 'scale' => array(), 'options' => array()),
       'file' => 'kml_views.theme.inc',
diff --git a/views/kml-placemark-wkt.tpl.php b/views/kml-placemark-wkt.tpl.php
new file mode 100644
index 0000000..bab9a1e
--- /dev/null
+++ b/views/kml-placemark-wkt.tpl.php
@@ -0,0 +1,14 @@
+<?php
+// $Id: kml-placemark.tpl.php,v 1.1.2.1 2010/06/03 14:14:09 tmcw Exp $
+?><Placemark>
+  <name>
+    <![CDATA[<?php print $name ?>]]>
+  </name>
+  <description>
+    <![CDATA[<?php print $description ?>]]>
+  </description>
+  <?php if ($styleURL): ?>
+  <styleUrl><?php echo $styleURL; ?></styleUrl>
+  <?php endif; ?>
+  <?php print $geometry ?>
+</Placemark>
diff --git a/views/kml_views.theme.inc b/views/kml_views.theme.inc
index b9c0ad9..dd27c87 100644
--- a/views/kml_views.theme.inc
+++ b/views/kml_views.theme.inc
@@ -16,11 +16,16 @@ function template_preprocess_views_view_kml(&$vars) {
       $styles .= theme('kml_style', '1', $scale, $vars['options']);
     }
   }
-
+  
   foreach ($points as $point) {
-    $rows .= theme('kml_placemark', $point, $points);
+    if ($vars['options']['data_source']['provider'] == 'openlayers_wkt' && $point['wkt']) {
+      $rows .= theme('kml_placemark_wkt', $point, $points);
+    }
+    elseif ($vars['options']['data_source']['provider'] == 'lat_lon' && $point['point']) {
+      $rows .= theme('kml_placemark', $point, $points);
+    }
   }
-     
+  
   $vars['rows'] = $rows;
   $vars['style'] = $styles;
   $vars['viewtitle'] = $view->name;  
@@ -33,7 +38,7 @@ function template_preprocess_views_view_kml(&$vars) {
 /**
  * Preprocess for theme('kml_placemark').
  */
-function template_preprocess_kml_placemark(&$vars) {  
+function template_preprocess_kml_placemark(&$vars) {
   $vars['name'] = filter_xss_admin($vars['point']['name']);
   $vars['description'] = filter_xss_admin($vars['point']['description']);
   $vars['coords'] = check_plain($vars['point']['point']);
@@ -41,6 +46,16 @@ function template_preprocess_kml_placemark(&$vars) {
 }
 
 /**
+ * Preprocess for theme('kml_placemark_wkt').
+ */
+function template_preprocess_kml_placemark_wkt(&$vars) {
+  $vars['name'] = filter_xss_admin($vars['point']['name']);
+  $vars['description'] = filter_xss_admin($vars['point']['description']);
+  $vars['geometry'] = $vars['point']['wkt'];
+  $vars['styleURL'] = check_plain($vars['point']['styleURL']);
+}
+
+/**
  * Preprocess for theme('kml_style').
  */
 function template_preprocess_kml_style(&$vars) {  
diff --git a/views/views_plugin_style_kml.inc b/views/views_plugin_style_kml.inc
index 4867a90..fcc4f05 100644
--- a/views/views_plugin_style_kml.inc
+++ b/views/views_plugin_style_kml.inc
@@ -14,8 +14,7 @@ class views_plugin_style_kml extends views_plugin_style {
    */
   function init(&$view, &$display, $options = NULL) {
     parent::init($view, $display, $options = NULL);
-    $this->feed_image = drupal_get_path('module', 'views_kml') . 
-      '/images/kml.png';
+    $this->feed_image = drupal_get_path('module', 'kml') . '/images/kml.png';
   }
 
   /**
@@ -26,6 +25,12 @@ class views_plugin_style_kml extends views_plugin_style {
    */
   function attach_to($display_id, $path, $title) {
     $url_options = array('html' => TRUE);
+
+    $query = $this->view->get_exposed_input();
+    if ($query) {
+      $url_options['query'] = $query;
+    }
+
     $image = theme('image', $this->feed_image);
     $this->view->feed_icon .= l($image, $path, $url_options);
   }
@@ -36,8 +41,6 @@ class views_plugin_style_kml extends views_plugin_style {
     $field_options = array(
       'name' => t('Name'),
       'description' => t('Description'),
-      'longitude' => t('Longitude'),
-      'latitude' => t('Latitude'),
     );
     
     foreach ($field_options as $k => $v) {
@@ -91,14 +94,11 @@ class views_plugin_style_kml extends views_plugin_style {
       $field_options = array(
         'name' => t('Name'),
         'description' => t('Description'),
-        'longitude' => t('Longitude'),
-        'latitude' => t('Latitude'),
       );
       $form['fields'] = array(
         '#type' => 'fieldset',
         '#title' => 'Field usage',
-        '#description' => t('Select the fields that contain the latitude,
-        longitude and title of each point. 
+        '#description' => t('Select the fields that contain title of each point. 
         Remaining fields will be available in the 
         "content" region of the point.'),
         '#weight' => -10,
@@ -112,6 +112,63 @@ class views_plugin_style_kml extends views_plugin_style {
           '#required' => ($k == 'class' ? FALSE : TRUE),
         );
       }
+
+
+      $form['data_source'] = array(
+       '#type' => 'fieldset',
+       '#title' => t('Lat/Long source'),
+       '#description' => t('Select the fields that contain latitude and longitude of each point.'),
+       '#tree' => TRUE,
+       '#collapsible' => FALSE,
+      );
+      $form['data_source']['provider'] = array(
+        '#type' => 'select',
+        '#title' => t('Map Data Sources'),
+        '#description' => t('Choose which sources of data to provide latitude and langitude values.'),
+        '#options' => array(
+          'lat_lon' => t('Lat/Lon Points'),
+          'openlayers_wkt' => t('OpenLayers WKT')
+        ),
+        '#default_value' => ($this->options['data_source']['provider'] ? $this->options['data_source']['provider'] : ''),
+        '#required' => TRUE,
+      );
+
+      if (count($field_names > 0)) {
+        $form['data_source']['lat'] = array(
+          '#type' => 'select',
+          '#title' => t('Latitude Field'),
+          '#description' => t('Choose a field for Latitude.  This should be a field that is a decimal or float value.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['lat'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('lat_lon')),
+       //   '#required' => TRUE
+        );
+        $form['data_source']['lon'] = array(
+         '#type' => 'select',
+          '#title' => t('Longitude Field'),
+           '#description' => t('Choose a field for Longitude.  This should be a field that is a decimal or float value.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['lon'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('lat_lon')),
+        //  '#required' => TRUE
+        );
+
+        // Other: WKT
+        $form['data_source']['openlayers_wkt'] = array(
+          '#type' => 'select',
+          '#title' => t('WKT Field'),
+          '#description' => t('Choose the OpenLayers WKT field.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['openlayers_wkt'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('openlayers_wkt')),
+         // '#required' => TRUE
+        );
+      }
+
+
       $form['scaledpoints']['enable'] = array(
        '#type' => 'checkbox',
        '#title' => t('Use Scaled Points'),
@@ -151,6 +208,29 @@ class views_plugin_style_kml extends views_plugin_style {
     }
   }
 
+  function kml_points_prerender($options, $field, &$point) {
+    static $data_source;
+
+    /* Select correct data source to get lat/long values */
+    if (!$data_source) {
+      $data_source = $options['provider'];
+    }
+    
+    switch ($data_source) {
+      case 'openlayers_wkt':
+        include_once(drupal_get_path('module', 'kml').'/gml.inc');
+        $point['wkt'] = wkt_to_kml($field[$options['openlayers_wkt']]);
+      break;
+      case 'lat_lon':
+        $lat = $field[$options['lat']];
+        $lon = $field[$options['lon']];
+        $point['point'] = $lon . ',' . $lat . ',0';
+        unset($point['lat']);
+        unset($point['lon']);
+      break;
+    }    
+  }
+
   function map_rows($rows) {
     // Fields must be rendered in order as of Views 2.3, 
     // so we will pre-render everything.
@@ -164,31 +244,27 @@ class views_plugin_style_kml extends views_plugin_style {
     }  
 
     $points = array();
+
     foreach ($renders as $id => $row) {
       $point = array();
       foreach ($this->view->field as $key => $field) {
         if ($key == $this->options['fields']['name']) {
           $point['name'] = $row[$key];
         }
+
         elseif ($key == $this->options['fields']['description']) {
           $point['description'] = $row[$key];
         }
-        elseif ($key == $this->options['fields']['longitude']) {
-          $point['lon'] = $row[$key];
-        }
-        elseif ($key == $this->options['fields']['latitude']) {
-          $point['lat'] = $row[$key];
-        }
+ 
         elseif ($key == $this->options['scaledpoints']['valuefield']) {
           $point['scalevalue'] = (float) str_replace(',' ,'', $row[$key]);
           $values[] = (float) str_replace(',' ,'', $row[$key]);
         }
       }
 
-      $point['point'] = $point['lon'] . ',' . $point['lat'] . ',0';
-      unset($point['lat']);
-      unset($point['lon']);
-
+      /* Lat/Long pre render */
+      $this->kml_points_prerender($this->options['data_source'], $row, $point);
+      
       if ($this->options['linestring']['enable']) {
         $points[$point['group']][] = $point;
       }
@@ -227,7 +303,7 @@ class views_plugin_style_kml extends views_plugin_style {
       
       $points['scale_ramp'] = $scale_ramp;
     }
-
+    
     return $points;
   }
 }
\ No newline at end of file
