<?php
/**
 * Google map module for phpGedView
 *
 * phpGedView: Genealogy Viewer
 * Copyright (C) 2002 to 2016  PGV Development Team.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * @package PhpGedView
 * @subpackage Module
 * $Id: googlemap.php 7146 2016-12-06 20:06:25Z canajun2eh $
 * @author Johan Borkhuis
 */

if (!defined('PGV_PHPGEDVIEW')) {
	header('HTTP/1.0 403 Forbidden');
	exit;
}

require PGV_ROOT.'modules/googlemap/defaultconfig.php';

global $SESSION_HIDE_GOOGLEMAP;
$SESSION_HIDE_GOOGLEMAP = "empty";
if ((isset($_REQUEST["HIDE_GOOGLEMAP"])) && (empty($SEARCH_SPIDER))) {
	if(stristr("true", $_REQUEST["HIDE_GOOGLEMAP"])) {
		$SESSION_HIDE_GOOGLEMAP = "true";
	}
	if(stristr("false", $_REQUEST["HIDE_GOOGLEMAP"])) {
		$SESSION_HIDE_GOOGLEMAP = "false";
	}
}

// change the session values and store if needed.
if($SESSION_HIDE_GOOGLEMAP == "true") $_SESSION['hide_googlemap'] = true;
if($SESSION_HIDE_GOOGLEMAP == "false") $_SESSION['hide_googlemap'] = false;
if($SESSION_HIDE_GOOGLEMAP == "empty") {
	if((isset($_SESSION['hide_googlemap'])) && ($_SESSION['hide_googlemap'] == true))
		$SESSION_HIDE_GOOGLEMAP = "true";
	else
		$SESSION_HIDE_GOOGLEMAP = "false";
}

loadLangFile("googlemap:lang");

// functions copied from print_fact_place
function print_fact_place_map($factrec) {
	global $countries;
	$ct = preg_match("/2 PLAC (.*)/", $factrec, $match);
	if ($ct>0) {
		$retStr = " ";
		$levels = explode(",", $match[1]);
		$place = trim($match[1]);
		// reverse the array so that we get the top level first
		$levels = array_reverse($levels);
		loadLangFile("pgv_country");
		if (isset($countries[trim($levels[0])])) $place = str_replace(trim($levels[0]), $countries[trim($levels[0])], $place);
		$retStr .= "<a href=\"placelist.php?action=show&amp;";
		foreach($levels as $pindex=>$ppart) {
			// routine for replacing ampersands
			$ppart = preg_replace("/amp\%3B/", "", trim($ppart));
			$retStr .= "parent[$pindex]=".PrintReady($ppart)."&amp;";
		}
		$retStr .= "level=".count($levels);
		$retStr .= "\"> ".PrintReady($place)."</a>";
		return $retStr;
	}
	return "";
}


function print_address_structure_map($factrec, $level) {
	global $pgv_lang;
	global $factarray;
	global $WORD_WRAPPED_NOTES;
	global $POSTAL_CODE;

	//  $POSTAL_CODE = 'false' - before city, 'true' - after city and/or state
	//-- define per gedcom till can do per address countries in address languages
	//-- then this will be the default when country not recognized or does not exist
	//-- both Finland and Suomi are valid for Finland etc.
	//-- see http://www.bitboost.com/ref/international-address-formats.html

	$nlevel = $level+1;
	$ct = preg_match_all("/$level ADDR(.*)/", $factrec, $omatch, PREG_SET_ORDER);
	for($i=0; $i<$ct; $i++) {
		$arec = get_sub_record($level, "$level ADDR", $factrec, $i+1);
		$resultText = "";
		$cn = preg_match("/$nlevel _NAME (.*)/", $arec, $cmatch);
		if ($cn>0) $resultText .= str_replace("/", "", $cmatch[1])."<br />";
		$resultText .= PrintReady(trim($omatch[$i][1]));
		$cont = get_cont($nlevel, $arec);
		if (!empty($cont)) $resultText .= str_replace(array(" ", "<br&nbsp;"), array("&nbsp;", "<br "), PrintReady($cont));
		else {
			if (strlen(trim($omatch[$i][1])) > 0) echo "<br />";
				$cs = preg_match("/$nlevel ADR1 (.*)/", $arec, $cmatch);
			if ($cs>0) {
				if ($cn==0) {
					$resultText .= "<br />";
					$cn=0;
				}
				$resultText .= PrintReady($cmatch[1]);
			}
			$cs = preg_match("/$nlevel ADR2 (.*)/", $arec, $cmatch);
			if ($cs>0) {
				if ($cn==0) {
					$resultText .= "<br />";
					$cn=0;
				}
				$resultText .= PrintReady($cmatch[1]);
			}

			if ($POSTAL_CODE) {
				if (preg_match("/$nlevel CITY (.*)/", $arec, $cmatch))
					$resultText.=" ".PrintReady($cmatch[1]);
				if (preg_match("/$nlevel STAE (.*)/", $arec, $cmatch))
					$resultText.=", ".PrintReady($cmatch[1]);
				if (preg_match("/$nlevel POST (.*)/", $arec, $cmatch))
					$resultText.="<br />".PrintReady($cmatch[1]);
			} else {
				if (preg_match("/$nlevel POST (.*)/", $arec, $cmatch))
					$resultText.="<br />".PrintReady($cmatch[1]);
				if (preg_match("/$nlevel CITY (.*)/", $arec, $cmatch))
					$resultText.=" ".PrintReady($cmatch[1]);
				if (preg_match("/$nlevel STAE (.*)/", $arec, $cmatch))
					$resultText.=", ".PrintReady($cmatch[1]);
			}
		}
		if (preg_match("/$nlevel CTRY (.*)/", $arec, $cmatch))
			$resultText.="<br />".PrintReady($cmatch[1]);
		$resultText.= "<br />";
		// Here we can examine the resultant text and remove empty tags
		echo str_replace(chr(10), ' ' , $resultText);
	}
	$resultText = "<table>";
	$ct = preg_match_all("/$level PHON (.*)/", $factrec, $omatch, PREG_SET_ORDER);
	for($i=0; $i<$ct; $i++) {
		$resultText .= "<tr><td><span class=\"label\"><b>".$factarray["PHON"].": </b></span></td><td><span class=\"field\">";
		$resultText .= getLRM() . $omatch[$i][1]. getLRM();
		$resultText .= "</span></td></tr>";
	}
	$ct = preg_match_all("/$level FAX (.*)/", $factrec, $omatch, PREG_SET_ORDER);
	for($i=0; $i<$ct; $i++) {
		$resultText .= "<tr><td><span class=\"label\"><b>".$factarray["FAX"].": </b></span></td><td><span class=\"field\">";
		$resultText .= getLRM() . $omatch[$i][1] . getLRM();
		$resultText .= "</span></td></tr>";
	}
	$ct = preg_match_all("/$level EMAIL (.*)/", $factrec, $omatch, PREG_SET_ORDER);
	for($i=0; $i<$ct; $i++) {
		$resultText .= "<tr><td><span class=\"label\"><b>".$factarray["EMAIL"].": </b></span></td><td><span class=\"field\">";
		$resultText .= "<a href=\"mailto:".$omatch[$i][1]."\">".$omatch[$i][1]."</a>";
		$resultText .= "</span></td></tr>";
	}
	$ct = preg_match_all("/$level (WWW|URL) (.*)/", $factrec, $omatch, PREG_SET_ORDER);
	for($i=0; $i<$ct; $i++) {
		$resultText .= "<tr><td><span class=\"label\"><b>".$factarray["URL"].": </b></span></td><td><span class=\"field\">";
		$resultText .= "<a href=\"".$omatch[$i][2]."\" target=\"_blank\">".$omatch[$i][2]."</a>";
		$resultText .= "</span></td></tr>";
	}
	$resultText .= "</table>";
	if ($resultText!="<table></table>") echo str_replace(chr(10), ' ' , $resultText);
}

function rem_prefix_from_placename($prefix_list, $place, $placelist) {
	$prefix_split = explode(";", $prefix_list);
	foreach ($prefix_split as $prefix) {
		if (!empty($prefix)) {
			if (preg_match('/^'.$prefix.' (.*)/', $place, $matches) != 0) {
				$placelist[] = $matches[1];
			}
		}
	}
	return $placelist;
}

function rem_postfix_from_placename($postfix_list, $place, $placelist) {
	$postfix_split = explode (";", $postfix_list);
	foreach ($postfix_split as $postfix) {
		if (!empty($postfix)) {
			if (preg_match('/^(.*) '.$postfix.'$/', $place, $matches) != 0) {
				$placelist[] = $matches[1];
			}
		}
	}
	return $placelist;
}

function rem_prefix_postfix_from_placename($prefix_list, $postfix_list, $place, $placelist) {
	$prefix_split = explode (";", $prefix_list);
	$postfix_split = explode (";", $postfix_list);
	foreach ($prefix_split as $prefix) {
		if (!empty($prefix)) {
			foreach ($postfix_split as $postfix) {
				if (!empty($postfix)) {
					if (preg_match('/^'.$prefix.' (.*) '.$postfix.'$/', $place, $matches) != 0) {
						$placelist[] = $matches[1];
					}
				}
			}
		}
	}
	return $placelist;
}

function create_possible_place_names ($placename, $level) {
	global $GM_PREFIX, $GM_POSTFIX, $GM_PRE_POST_MODE;

	$retlist = array();

	switch (@$GM_PRE_POST_MODE[$level]) {
	case 0:     // 0: no pre/postfix
		$retlist[] = $placename;
		break;
	case 1:     // 1 = Normal name, Prefix, Postfix, Both
		$retlist[] = $placename;
		$retlist = rem_prefix_from_placename($GM_PREFIX[$level], $placename, $retlist);
		$retlist = rem_postfix_from_placename($GM_POSTFIX[$level], $placename, $retlist);
		$retlist = rem_prefix_postfix_from_placename($GM_PREFIX[$level], $GM_POSTFIX[$level], $placename, $retlist);
		break;
	case 2:     // 2 = Normal name, Postfix, Prefxi, Both
		$retlist[] = $placename;
		$retlist = rem_postfix_from_placename($GM_POSTFIX[$level], $placename, $retlist);
		$retlist = rem_prefix_from_placename($GM_PREFIX[$level], $placename, $retlist);
		$retlist = rem_prefix_postfix_from_placename($GM_PREFIX[$level], $GM_POSTFIX[$level], $placename, $retlist);
		break;
	case 3:     // 3 = Prefix, Postfix, Both, Normal name
		$retlist = rem_prefix_from_placename($GM_PREFIX[$level], $placename, $retlist);
		$retlist = rem_postfix_from_placename($GM_POSTFIX[$level], $placename, $retlist);
		$retlist = rem_prefix_postfix_from_placename($GM_PREFIX[$level], $GM_POSTFIX[$level], $placename, $retlist);
		$retlist[] = $placename;
		break;
	case 4:     // 4 = Postfix, Prefix, Both, Normal name
		$retlist = rem_postfix_from_placename($GM_POSTFIX[$level], $placename, $retlist);
		$retlist = rem_prefix_from_placename($GM_PREFIX[$level], $placename, $retlist);
		$retlist = rem_prefix_postfix_from_placename($GM_PREFIX[$level], $GM_POSTFIX[$level], $placename, $retlist);
		$retlist[] = $placename;
		break;
	case 5:     // 5 = Prefix, Postfix, Normal name, Both
		$retlist = rem_prefix_from_placename($GM_PREFIX[$level], $placename, $retlist);
		$retlist = rem_postfix_from_placename($GM_POSTFIX[$level], $placename, $retlist);
		$retlist[] = $placename;
		$retlist = rem_prefix_postfix_from_placename($GM_PREFIX[$level], $GM_POSTFIX[$level], $placename, $retlist);
		break;
	case 6:     // 6 = Postfix, Prefix, Normal name, Both
		$retlist = rem_postfix_from_placename($GM_POSTFIX[$level], $placename, $retlist);
		$retlist = rem_prefix_from_placename($GM_PREFIX[$level], $placename, $retlist);
		$retlist[] = $placename;
		$retlist = rem_prefix_postfix_from_placename($GM_PREFIX[$level], $GM_POSTFIX[$level], $placename, $retlist);
		break;
	}
	return $retlist;
}

function abbreviate($text) {
	if (UTF8_strlen($text)>13) {
		if (trim(UTF8_substr($text, 10, 1))!="")
			$desc = UTF8_substr($text, 0, 11).".";
		else $desc = trim(UTF8_substr($text, 0, 11));
	}
	else $desc = $text;
	return $desc;
}

function get_lati_long_placelocation ($place) {
	global $TBLPREFIX;
	$parent = explode (",", $place);
	$parent = array_reverse($parent);
	$place_id = 0;
	for($i=0; $i<count($parent); $i++) {
		$parent[$i] = trim($parent[$i]);
		if (empty($parent[$i])) $parent[$i]="unknown";// GoogleMap module uses "unknown" while GEDCOM uses , ,
		$placelist = create_possible_place_names($parent[$i], $i+1);
		foreach ($placelist as $key => $placename) {
			$pl_id=
				PGV_DB::prepare("SELECT pl_id FROM {$TBLPREFIX}placelocation WHERE pl_level=? AND pl_parent_id=? AND pl_place ".PGV_DB::$LIKE." ? ORDER BY pl_place")
				->execute(array($i, $place_id, $placename))
				->fetchOne();
			if (!empty($pl_id)) break;
		}
		if (empty($pl_id)) break;
		$place_id = $pl_id;
	}

	$row=
		PGV_DB::prepare("SELECT pl_lati, pl_long, pl_zoom, pl_icon, pl_level FROM {$TBLPREFIX}placelocation WHERE pl_id=? ORDER BY pl_place")
		->execute(array($place_id))
		->fetchOneRow();
	if ($row) {
		return array('lati'=>$row->pl_lati, 'long'=>$row->pl_long, 'zoom'=>$row->pl_zoom, 'icon'=>$row->pl_icon, 'level'=>$row->pl_level);
	} else {
		return array();
	}
}

function setup_map() {
	global $GOOGLEMAP_ENABLED, $GOOGLEMAP_API_KEY, $GOOGLEMAP_MAP_TYPE, $GOOGLEMAP_MIN_ZOOM, $GOOGLEMAP_MAX_ZOOM, $pgv_lang, $language_settings, $LANGUAGE;
	if (!$GOOGLEMAP_ENABLED) {
		return;
	}
	?>
	<script async defer src="https://maps.googleapis.com/maps/api/js?key=<?php echo $GOOGLEMAP_API_KEY; ?>&language=<?php echo $language_settings[$LANGUAGE]['lang_short_cut']; ?>" type="text/javascript"></script>
	<script src="modules/googlemap/pgvGoogleMap.js" type="text/javascript"></script>
        <script src="modules/googlemap/infobubble.js" type="text/javascript"></script>
	<script type="text/javascript">
	  var GOOGLEMAP_MAP_TYPE = 0; //<?php echo $GOOGLEMAP_MAP_TYPE;?>;
	  var minZoomLevel = <?php echo $GOOGLEMAP_MIN_ZOOM;?>;
	  var maxZoomLevel = <?php echo $GOOGLEMAP_MAX_ZOOM;?>;
	  var startZoomLevel = <?php echo $GOOGLEMAP_MAX_ZOOM;?>;
	</script>
	<?php

}

function tool_tip_text($marker) {
	$tool_tip=$marker['fact'];
	if (!empty($marker['info']))
		$tool_tip.=": {$marker['info']}";
	if (!empty($marker['name'])) {
		$person=Person::getInstance($marker['name']);
		if ($person && $person->canDisplayName()) {
			$tool_tip.=": ".PrintReady($person->getFullName());
		}
	}
	if (!empty($marker['date'])) {
		$date=new GedcomDate($marker['date']);
		$tool_tip.=" - ".$date->Display(false);
	}
	return $tool_tip;
// dates & RTL is not OK - adding PrintReady does not solve it
}

function create_indiv_buttons() {
	global $pgv_lang;
	?>
	<style type="text/css">
	#map_type
	{
		margin: 0;
		padding: 0;
		font-family: Arial;
		font-size: 10px;
		list-style: none;
	}
	#map_type li
	{
		display: block;
		width: 70px;
		text-align: center;
		padding: 2px;
		border: 1px solid black;
		cursor: pointer;
		float: left;
		margin-left: 2px;
	}
	#map_type li.non_active
	{
		background: white;
		color: black;
		font-weight: normal;
	}
	#map_type li.active
	{
		background: gray;
		color: white;
		font-weight: bold;
	}
	#map_type li:hover
	{
		background: #ddd;
	}
	#map_nav
	{
		position: relative;
		top: -484px;
		left: 101%;
	}

	</style>
	<script type='text/javascript'>
	    var map_type;
	</script>
	<?php
}

function build_indiv_map($indifacts, $famids) {
	global $GOOGLEMAP_API_KEY, $GOOGLEMAP_MAP_TYPE, $GOOGLEMAP_MIN_ZOOM, $GOOGLEMAP_MAX_ZOOM, $GEDCOM;
	global $GOOGLEMAP_XSIZE, $GOOGLEMAP_YSIZE, $pgv_lang, $factarray, $SHOW_LIVING_NAMES, $PRIV_PUBLIC;
	global $GOOGLEMAP_ENABLED, $TBLPREFIX, $TEXT_DIRECTION, $GM_DEFAULT_TOP_VALUE, $GOOGLEMAP_COORD;

	if (!$GOOGLEMAP_ENABLED) {
		echo "<table class=\"facts_table\">\n";
		echo "<tr><td colspan=\"2\" class=\"facts_value\">", $pgv_lang["gm_disabled"], "<script language=\"JavaScript\" type=\"text/javascript\">tabstyles[5]='tab_cell_inactive_empty'; document.getElementById('pagetab5').className='tab_cell_inactive_empty';</script></td></tr>\n";
		echo "<script type=\"text/javascript\">\n";
		echo "function ResizeMap ()\n{\n}\nfunction SetMarkersAndBounds ()\n{\n}\n</script>\n";
		if (PGV_USER_IS_ADMIN) {
			echo "<tr><td align=\"center\" colspan=\"2\">\n";
			echo "<a href=\"module.php?mod=googlemap&pgvaction=editconfig\">", $pgv_lang["gm_manage"], "</a>";
			echo "</td></tr>\n";
		}
		echo "\n\t</table>\n<br />";
		?>
		<script type="text/javascript">
			document.getElementById("googlemap_left").innerHTML = document.getElementById("googlemap_content").innerHTML;
			document.getElementById("googlemap_content").innerHTML = "";
		</script>
		<?php
		return;
	}

	$markers=array();

	$zoomLevel = $GOOGLEMAP_MAX_ZOOM;
	$placelocation=PGV_DB::table_exists("{$TBLPREFIX}placelocation");
	//-- sort the facts
	//sort_facts($indifacts); facts should already be sorted
	$i = 0;
	foreach ($indifacts as $key => $value) {
			$fact = $value->getTag();
			$fact_data=$value->getDetail();
			$factrec = $value->getGedComRecord();
			$placerec = null;
			if ($value->getPlace()!=null) {
				$placerec = get_sub_record(2, "2 PLAC", $factrec);
				$addrFound = false;
			} else {
				if (preg_match("/\d ADDR (.*)/", $factrec, $match)) {
					$placerec = get_sub_record(1, "\d ADDR", $factrec);
					$addrFound = true;
				}
			}
			if (!empty($placerec)) {
				$ctla = preg_match("/\d LATI (.*)/", $placerec, $match1);
				$ctlo = preg_match("/\d LONG (.*)/", $placerec, $match2);
				$spouserec = get_sub_record(2, "2 _PGVS", $factrec);
				$ctlp = preg_match("/\d _PGVS @(.*)@/", $spouserec, $spouseid);
				if ($ctlp>0) {
					$useThisItem = displayDetailsById($spouseid[1]);
				} else {
					$useThisItem = true;
				}
				if (($ctla>0) && ($ctlo>0) && ($useThisItem==true)) {
					$i = $i + 1;
					$markers[$i]=array('class'=>'optionbox', 'index'=>'', 'tabindex'=>'', 'placed'=>'no');
					if ($fact == "EVEN" || $fact=="FACT") {
						$eventrec = get_sub_record(1, "2 TYPE", $factrec);
						if (preg_match("/\d TYPE (.*)/", $eventrec, $match3)) {
							if (isset($factarray[$match3[1]])) {
								$markers[$i]["fact"]=$factarray[$match3[1]];
							} else {
								$markers[$i]["fact"]=$match3[1];
							}
						} else {
							$markers[$i]["fact"]=$factarray[$fact];
						}
					} else {
						$markers[$i]["fact"]=$factarray[$fact];
					}
					if (!empty($fact_data) && $fact_data!='Y')
						$markers[$i]["info"] = $fact_data;
					$markers[$i]["placerec"] = $placerec;
					$match1[1] = trim($match1[1]);
					$match2[1] = trim($match2[1]);
					$markers[$i]["zoom"] = 12;
					$markers[$i]["lati"] = str_replace(array('N', 'S', ','), array('', '-', '.') , $match1[1]);
					$markers[$i]["lng"] = str_replace(array('E', 'W', ','), array('', '-', '.') , $match2[1]);
					$ctd = preg_match("/2 DATE (.+)/", $factrec, $match);
					if ($ctd>0)
						$markers[$i]["date"] = $match[1];
					if ($ctlp>0)
						$markers[$i]["name"]=$spouseid[1];
				} else {
					if (($placelocation == true) && ($useThisItem==true) && ($addrFound==false)) {
						$ctpl = preg_match("/\d PLAC (.*)/", $placerec, $match1);
						$latlongval = get_lati_long_placelocation($match1[1]);
						if ((count($latlongval) == 0) && (!empty($GM_DEFAULT_TOP_VALUE))) {
							$latlongval = get_lati_long_placelocation($match1[1].", ".$GM_DEFAULT_TOP_VALUE);
							if ((count($latlongval) != 0) && ($latlongval["level"] == 0)) {
								$latlongval["lati"] = NULL;
								$latlongval["long"] = NULL;
							}
						}
						if ((count($latlongval) != 0) && ($latlongval["lati"] != NULL) && ($latlongval["long"] != NULL)) {
							$i = $i + 1;
							$markers[$i]=array('class'=>'optionbox', 'index'=>'', 'tabindex'=>'', 'placed'=>'no');
							if ($fact == "EVEN" || $fact=="FACT") {
								$eventrec = get_sub_record(1, "2 TYPE", $factrec);
								if (preg_match("/\d TYPE (.*)/", $eventrec, $match3)) {
									if (isset($factarray[$match3[1]])) {
										$markers[$i]["fact"]=$factarray[$match3[1]];
									} else {
										$markers[$i]["fact"]=$match3[1];
									}
								} else {
									$markers[$i]["fact"]=$factarray[$fact];
								}
							} else {
								$markers[$i]["fact"]=$factarray[$fact];
							}
							if (!empty($fact_data) && $fact_data!='Y')
								$markers[$i]["info"] = $fact_data;
							$markers[$i]["icon"] = $latlongval["icon"];
							$markers[$i]["placerec"] = $placerec;
							if ($zoomLevel > $latlongval["zoom"]) $zoomLevel = $latlongval["zoom"];
							$markers[$i]["zoom"] = $latlongval["zoom"];
							$markers[$i]["lati"] = str_replace(array('N', 'S', ','), array('', '-', '.') , $latlongval["lati"]);
							$markers[$i]["lng"] = str_replace(array('E', 'W', ','), array('', '-', '.') , $latlongval["long"]);
							$ctd = preg_match("/2 DATE (.+)/", $factrec, $match);
							if ($ctd>0)
								$markers[$i]["date"] = $match[1];
							if ($ctlp>0)
								$markers[$i]["name"]=$spouseid[1];
						}
					}
				}
			}
	}

	// Add children to the list
	if (count($famids)>0) {
		$hparents=false;
		for($f=0; $f<count($famids); $f++) {
			if (!empty($famids[$f])) {
				$famrec = find_family_record($famids[$f], PGV_GED_ID);
				if (empty($famrec)) $famrec = find_updated_record($famids[$f], PGV_GED_ID);
				if ($famrec) {
					$num = preg_match_all("/1\s*CHIL\s*@(.*)@/", $famrec, $smatch, PREG_SET_ORDER);
					for($j=0; $j<$num; $j++) {
						$person=Person::getInstance($smatch[$j][1]);
						if ($person->canDisplayDetails()) {
							$srec = find_person_record($smatch[$j][1], PGV_GED_ID);
							$birthrec = '';
							$placerec = '';
							foreach ($person->getAllFactsByType('BIRT') as $sEvent) {
								$birthrec = $sEvent->getGedcomRecord();
								$placerec = get_sub_record(2, "2 PLAC", $birthrec);
								if (!empty($placerec)) {
									$ctd = preg_match("/\d DATE (.*)/", $birthrec, $matchd);
									$ctla = preg_match("/\d LATI (.*)/", $placerec, $match1);
									$ctlo = preg_match("/\d LONG (.*)/", $placerec, $match2);
									if (($ctla>0) && ($ctlo>0)) {
										$i = $i + 1;
										$markers[$i]=array('index'=>'', 'tabindex'=>'', 'placed'=>'no');
										if (strpos($srec, "\n1 SEX F")!==false) {
											$markers[$i]["fact"] = $pgv_lang["daughter"];
											$markers[$i]["class"]  = "person_boxF";
										} else
											if (strpos($srec, "\n1 SEX M")!==false) {
												$markers[$i]["fact"] = $pgv_lang["son"];
												$markers[$i]["class"]  = "person_box";
											} else {
												$markers[$i]["fact"]     = $factarray["CHIL"];
												$markers[$i]["class"]    = "person_boxNN";
											}
										$markers[$i]["placerec"] = $placerec;
										$match1[1] = trim($match1[1]);
										$match2[1] = trim($match2[1]);
										$markers[$i]["zoom"] = 12;
										$markers[$i]["lati"] = str_replace(array('N', 'S', ','), array('', '-', '.'), $match1[1]);
										$markers[$i]["lng"]  = str_replace(array('E', 'W', ','), array('', '-', '.'), $match2[1]);
										if ($ctd > 0)
											$markers[$i]["date"] = $matchd[1];
										$markers[$i]["name"] = $smatch[$j][1];
									} else {
										if ($placelocation == true) {
											$ctpl = preg_match("/\d PLAC (.*)/", $placerec, $match1);
											$latlongval = get_lati_long_placelocation($match1[1]);
											if ((count($latlongval) == 0) && (!empty($GM_DEFAULT_TOP_VALUE))) {
												$latlongval = get_lati_long_placelocation($match1[1].", ".$GM_DEFAULT_TOP_VALUE);
												if ((count($latlongval) != 0) && ($latlongval["level"] == 0)) {
													$latlongval["lati"] = NULL;
													$latlongval["long"] = NULL;
												}
											}
											if ((count($latlongval) != 0) && ($latlongval["lati"] != NULL) && ($latlongval["long"] != NULL)) {
												$i = $i + 1;
												$markers[$i]=array('index'=>'', 'tabindex'=>'', 'placed'=>'no');
												$markers[$i]["fact"]     = $factarray["CHIL"];
												$markers[$i]["class"]    = "option_boxNN";
												if (strpos($srec, "\n1 SEX F")!==false) {
													$markers[$i]["fact"] = $pgv_lang["daughter"];
													$markers[$i]["class"]  = "person_boxF";
												}
												if (strpos($srec, "\n1 SEX M")!==false) {
													$markers[$i]["fact"] = $pgv_lang["son"];
													$markers[$i]["class"]  = "person_box";
												}
												$markers[$i]["icon"] = $latlongval["icon"];
												$markers[$i]["placerec"] = $placerec;
												if ($zoomLevel > $latlongval["zoom"]) $zoomLevel = $latlongval["zoom"];
												$markers[$i]["zoom"] = $latlongval["zoom"];
												$markers[$i]["lati"]     = str_replace(array('N', 'S', ','), array('', '-', '.'), $latlongval["lati"]);
												$markers[$i]["lng"]      = str_replace(array('E', 'W', ','), array('', '-', '.'), $latlongval["long"]);
												if ($ctd > 0)
													$markers[$i]["date"] = $matchd[1];
												$markers[$i]["name"]   = $smatch[$j][1];
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}

	if ($i == 0) {
		echo "<table class=\"facts_table\">\n";
		echo "<tr><td colspan=\"2\" class=\"facts_value\">", $pgv_lang["no_gmtab"], "<script language=\"JavaScript\" type=\"text/javascript\">tabstyles[5]='tab_cell_inactive_empty'; document.getElementById('pagetab5').className='tab_cell_inactive_empty';</script></td></tr>\n";
		echo "<script type=\"text/javascript\">\n";
		echo "function ResizeMap ()\n{\n}\n</script>\n";
		if (PGV_USER_IS_ADMIN) {
			echo "<tr><td align=\"center\" colspan=\"2\">\n";
			echo "<a href=\"module.php?mod=googlemap&pgvaction=editconfig\">", $pgv_lang["gm_manage"], "</a>";
			echo "</td></tr>\n";
		}
	} else {
		?>
		<script type="text/javascript">
		            function SetBounds (){
                        Boundaries = new google.maps.LatLngBounds();
		<?php
		foreach ($markers as $marker)
			echo "                        Boundaries.extend(new google.maps.LatLng(".$marker["lati"].", ".$marker["lng"]."));\n";
		echo "                        if (Boundaries.getNorthEast().equals(Boundaries.getSouthWest())) {
                            var extendPoint1 = new google.maps.LatLng(Boundaries.getNorthEast().lat() + 0.01, Boundaries.getNorthEast().lng() + 0.01);
                            var extendPoint2 = new google.maps.LatLng(Boundaries.getNorthEast().lat() - 0.01, Boundaries.getNorthEast().lng() - 0.01);
                            Boundaries.extend(extendPoint1);
                            Boundaries.extend(extendPoint2);
                        }
                    }

                    function SetMarkers (){\n\n";

		$indexcounter = 0;
		for ($j=1; $j<=$i; $j++) {
			// Use @ because some installations give warnings (but not errors?) about UTF-8
			$tooltip=@html_entity_decode(strip_tags(tool_tip_text($markers[$j])), ENT_QUOTES, 'UTF-8');
			if ($markers[$j]["placed"] == "no") {
					$tabcounter = 0;
					$markers[$j]["placed"] = "yes";
					if (empty($markers[$j]["icon"])) {
						echo "
                        var Marker{$j} = new google.maps.Marker({
                            position: {lat: ".$markers[$j]["lati"].", lng: ".$markers[$j]["lng"]."},
                            map: map,
                            title: '".addslashes($tooltip)."'
                        });\n";
					} else {
						echo "
                        var Marker{$j} = new google.maps.Marker({
                            position: {lat: ".$markers[$j]["lati"].", lng: ".$markers[$j]["lng"]."},
                            map: map,
                            title: '".addslashes($tooltip)."',
                            icon: '".$markers[$j]["icon"]."'
                        });\n";
					}
					echo "
                        var infoBubble{$j} = new InfoBubble({ disableAutoPan: true });";
					$markers[$j]["index"] = $indexcounter;
					$markers[$j]["tabindex"] = $tabcounter;
					$tabcounter = $tabcounter + 1;
					echo "
                        infoBubble{$j}.addTab(\"", abbreviate($markers[$j]["fact"]), "\", \"<div class='iwstyle'>", PrintReady($markers[$j]["fact"]);
					if (!empty($markers[$j]['info']))
						echo ': ', addslashes($markers[$j]['info']);
					if (!empty($markers[$j]["name"])) {
						$person=Person::getInstance($markers[$j]['name']);
						if ($person) {
							echo ': <a href=\"', $person->getLinkUrl(), '\">', $person->canDisplayName() ? PrintReady(addcslashes($person->getFullName(), '"')) : $pgv_lang['private'], '</a>';
						}
					}
					echo "<br />";
					if (preg_match("/2 PLAC (.*)/", $markers[$j]["placerec"]) == 0) {
						print_address_structure_map($markers[$j]["placerec"], 1);
					} else {
						echo preg_replace("/\"/", "\\\"", print_fact_place_map($markers[$j]["placerec"]));
					}
					if (!empty($markers[$j]["date"])) {
						$date=new GedcomDate($markers[$j]["date"]);
						echo "<br />", addslashes($date->Display(true));
					}
					if (!$GOOGLEMAP_COORD){
						echo "\")";
					} else {
						echo "<br /><br />";
						if ($markers[$j]["lati"]>='0'){echo "N", str_replace('-', '', $markers[$j]["lati"]);}else{ echo str_replace('-', 'S', $markers[$j]["lati"]);}
						echo ", ";
						if ($markers[$j]["lng"]>='0'){echo "E", str_replace('-', '', $markers[$j]["lng"]);}else{ echo str_replace('-', 'W', $markers[$j]["lng"]);}
						echo "\")";
					}
					echo ";\n";
					for($k=$j+1; $k<=$i; $k++) {
						if (($markers[$j]["lati"] == $markers[$k]["lati"]) && ($markers[$j]["lng"] == $markers[$k]["lng"])) {
							$markers[$k]["placed"] = "yes";
							$markers[$k]["index"] = $indexcounter;
							$markers[$k]["index"] = $indexcounter;
							$markers[$k]["tabindex"] = $tabcounter;
							$tabcounter = $tabcounter + 1;
							echo "infoBubble{$j}.addTab(\"", abbreviate($markers[$k]["fact"]), "\", \"<div class='iwstyle'>", $markers[$k]["fact"];
							if (!empty($markers[$k]['info']))
								echo ': ', addslashes($markers[$k]['info']);
							if (!empty($markers[$k]["name"])) {
								$person=Person::getInstance($markers[$k]['name']);
								if ($person) {
									echo ': <a href=\"', $person->getLinkUrl(), '\">', $person->canDisplayName() ? PrintReady(addcslashes($person->getFullName(), '"')) : $pgv_lang['private'], '</a>';
								}
							}
							echo "<br />";
							if (preg_match("/2 PLAC (.*)/", $markers[$k]["placerec"]) == 0) {
								print_address_structure_map($markers[$k]["placerec"], 1);
							} else {
								echo preg_replace("/\"/", "\\\"", print_fact_place_map($markers[$k]["placerec"]));
							}
							if (!empty($markers[$k]["date"])) {
								$date=new GedcomDate($markers[$k]["date"]);
								echo "<br />", addslashes($date->Display(true));
							}
							if (!$GOOGLEMAP_COORD){
								echo "\")";
							} else {
								echo "<br /><br />";
								if ($markers[$j]["lati"]>='0'){echo "N", str_replace('-', '', $markers[$j]["lati"]);}else{ echo str_replace('-', 'S', $markers[$j]["lati"]);}
								echo ", ";
								if ($markers[$j]["lng"]>='0'){echo "E", str_replace('-', '', $markers[$j]["lng"]);}else{ echo str_replace('-', 'W', $markers[$j]["lng"]);}
								echo "\")";
							}
							echo ";\n";
						}
					}
					echo "
						google.maps.event.addListener(Marker{$j}, 'click', function() {
                                                    if (infoBubble{$j}.isOpen()) {
                                                        infoBubble{$j}.close(map, Marker{$j});
                                                    } else {
                                                        infoBubble{$j}.open(map, Marker{$j});
                                                    }
                                                });
                                                infoBubbles.push(infoBubble{$j});
                                                markers.push(Marker{$j});\n";
					$indexcounter = $indexcounter + 1;
			}
		}
		echo "}\n</script>\n";
		echo "<div style=\"overflow: auto; overflow-x: hidden; overflow-y: auto; height: {$GOOGLEMAP_YSIZE}px;\"><table class=\"facts_table\">\n";
		foreach($markers as $marker) {
			echo "<tr><td class=\"facts_label\">\n";
			echo "<a href=\"javascript:highlight({$marker["index"]}, {$marker["tabindex"]}, {$marker["zoom"]})\">{$marker["fact"]}</a></td>\n";
			echo "<td class=\"{$marker['class']}\" style=\"white-space: normal\">\n";
			if (!empty($marker["info"]))
				echo "<span class=\"field\">{$marker["info"]}</span><br />\n";
			if (!empty($marker["name"])) {
				$person=Person::getInstance($marker['name']);
				if ($person) {
					echo '<a href="', $person->getLinkUrl(), '">', $person->canDisplayName() ? PrintReady($person->getFullName()) : $pgv_lang['private'], "</a>\n";
				}
				echo '<br />';
			}
			if (preg_match("/2 PLAC (.*)/", $marker["placerec"]) == 0) {
				print_address_structure_map($marker["placerec"], 1);
			} else {
				echo print_fact_place_map($marker["placerec"]), "<br />\n";
			}
			if (!empty($marker['date'])) {
				$date=new GedcomDate($marker['date']);
				echo $date->Display(true), "<br />\n";
			}
			echo "</td></tr>\n";
		}
        echo "<tr><td><a href=\"javascript:map.fitBounds(Boundaries);\">reset map</a></td></tr>\n";
		echo "</table></div><br />\n";
	}
	echo "\n<br />\n";

	return $i;
}

?>
