diff -aburN OpenLayers-2.4.old/lib/OpenLayers/Layer/GPX.js lib/OpenLayers/Layer/GPX.js
--- OpenLayers-2.4.old/lib/OpenLayers/Layer/GPX.js	1970-01-01 01:00:00.000000000 +0100
+++ lib/OpenLayers/Layer/GPX.js	2007-09-15 21:16:50.000000000 +0200
@@ -0,0 +1,309 @@
+/* Copyright (c) 2007, GnunuX (http://gnunux.info), published under the BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/release-license.txt 
+ * for the full text of the license. */
+
+
+/**
+ * @class
+ * 
+ * @requires OpenLayers/Layer/Markers.js
+ * @requires OpenLayers/Ajax.js
+ */
+OpenLayers.Layer.GPX = OpenLayers.Class.create();
+OpenLayers.Layer.GPX.prototype = 
+  OpenLayers.Class.inherit( OpenLayers.Layer.Markers, OpenLayers.Layer.Vector, {
+
+    /** store url of text file
+    * @type str */
+    url:null,
+    /** @type Array(OpenLayers.Feature) */
+    featuresWPT: null,
+
+    /** @type OpenLayers.Feature */
+    selectedFeature: null,
+
+    /**
+    * @constructor
+    *
+    * @param {String} name
+    * @param {String} location
+    */
+    initialize: function(name, url, options) {
+	var newArguments = new Array()
+	newArguments.push(name, options);
+	OpenLayers.Layer.Vector.prototype.initialize.apply(this, newArguments);
+        OpenLayers.Layer.Markers.prototype.initialize.apply(this, [name]);
+        this.url = url;
+        this.featuresWPT = new Array();
+	var results = OpenLayers.loadURL(this.url, null, this, this.requestSuccess, this.requestFailure);
+    },
+
+    /**
+     * 
+     */
+
+    destroy: function() {
+        this.clearFeatures();
+        this.featuresWPT = null;
+        OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments);
+    },
+        
+    /**
+     * @param {XMLHttpRequest} ajaxRequest
+     */
+    requestSuccess:function(request) {
+	var gpxns = "http://www.topografix.com/GPX/1/0";
+        var doc = request.responseXML;
+        if (!doc || request.fileType!="XML") {
+            doc = OpenLayers.parseXMLString(request.responseText);
+        }
+        if (typeof doc == "string") {
+            doc = OpenLayers.parseXMLString(doc);
+        }
+        var wpt = OpenLayers.Ajax.getElementsByTagNameNS(doc, gpxns, "", "wpt");
+	
+	/* search and display track */
+	var trk = OpenLayers.Ajax.getElementsByTagNameNS(doc, gpxns, "", "trk");
+	var featureTRK = [];
+	for (var i = 0; i< trk.length; i++) {
+		var color = '';
+		for (var j = 0; j < trk[i].childNodes.length; j++) {
+                        switch (trk[i].childNodes[j].nodeName)
+                        {
+                                case 'topografix:color':
+                                        color = '#' + OpenLayers.Util.getXmlNodeValue(trk[i].childNodes[j]);
+                                        break;
+                                case 'trkseg':
+					if (color == '')
+						color=this.randomColor();
+                                        featureTRK.push(this.addLineGPX(trk[i].childNodes[j], color));
+                                        break;
+                                case '#text':
+                                        break;
+                                case 'name':
+//FIXME: label the way
+                                        break;
+                                default:
+//                                      alert('unknown ' + trk[i].childNodes[j].nodeName);
+                                        break;
+                        }
+                }
+        }
+	this.addFeatures(featureTRK);
+	/* search and display route */
+	var rte = OpenLayers.Ajax.getElementsByTagNameNS(doc, gpxns, "", "rte");
+	var featureRTE = [];
+	for (var i = 0; i< rte.length; i++) {
+		var color = this.randomColor();
+		var style_green = {
+			strokeColor: color,
+			strokeOpacity: 1,
+			strokeWidth: 4,
+			pointRadius: 6,
+			pointerEvents: "visiblePainted"
+		};
+		var pointList = [];
+		for (var j = 0; j < rte[i].childNodes.length; j++) {
+			switch (rte[i].childNodes[j].nodeName)
+			{
+				case 'rtept':
+					var feature = this.parseFeature(rte[i].childNodes[j]);
+					if (feature) {
+						pointList.push(feature);
+					}
+					break;
+				default:
+					break;
+			}
+                }
+		featureRTE.push(new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(pointList),null,style_green));
+        };
+	this.addFeatures(featureRTE);
+	/* search and display waypoint */
+        for (var i = 0; i< wpt.length; i++) {
+		var point = this.setToMercator(wpt[i].getAttribute('lon'),wpt[i].getAttribute('lat'));
+		/* Provide defaults for title and description */
+		var desc = '<p>';
+		desc += '<strong>';
+		try { for (var m = 0; m<OpenLayers.Util.getNodes(wpt[i], 'name')[0].childNodes.length; m++) {
+			desc += OpenLayers.Util.getNodes(wpt[i], 'name')[0].childNodes[m].nodeValue;
+			}
+		} catch (e) { };
+		desc += '</strong><br />';
+
+		/* GPX descriptions */
+		try {
+			desc += OpenLayers.Util.getNodes(wpt[i],
+				'desc')[0].firstChild.nodeValue;
+		} catch (e) { };
+		desc += '</p>';
+		if ( OpenLayers.Util.getNodes(wpt[i], 'link').length != 0 ) {
+			link = OpenLayers.Util.getNodes(wpt[i], 'link')[0].firstChild.nodeValue;
+			var size = new OpenLayers.Size(21,25);
+			var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
+			var icon = new OpenLayers.Icon(link,size,offset);
+		} else {
+			var icon = null;
+		}
+		if ( desc == '<p><strong></strong><br /></p>' ) { desc = null;};
+		this.addMarkerGPX(point[0], point[1], desc, icon); 
+        }
+
+    },
+    /**
+     * @param {Event} evt
+     */
+    randomColor: function() {
+	var hex=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");
+	var color = '#';
+	for (i=0;i<6;i++){
+		color += hex[Math.floor(Math.random()*hex.length)];
+	}
+	return color;
+    },
+    markerClick: function(evt) {
+        sameMarkerClicked = (this == this.layer.selectedFeature);
+        this.layer.selectedFeature = (!sameMarkerClicked) ? this : null;
+        for(var i=0; i < this.layer.map.popups.length; i++) {
+            this.layer.map.removePopup(this.layer.map.popups[i]);
+        }
+        if (!sameMarkerClicked) {
+            var popup = this.createPopup(true);
+            OpenLayers.Event.observe(popup.div, "click",
+            function() { 
+              for(var i=0; i < this.layer.map.popups.length; i++) { 
+                this.layer.map.removePopup(this.layer.map.popups[i]); 
+              } 
+            }.bindAsEventListener(this));
+            this.layer.map.addPopup(popup); 
+        }
+        OpenLayers.Event.stop(evt);
+    },
+    addMarkerGPX: function(lon, lat, desc, icon) {
+                var data = {};
+                var location =  new OpenLayers.LonLat(lon, lat);
+		if ( icon == null ) {
+                	data.icon = OpenLayers.Marker.defaultIcon();
+		} else {
+			data.icon = icon;
+		}
+//              data.popupSize = new OpenLayers.Size(250, 120);
+		if ( desc != null) {              
+			data['popupContentHTML'] = desc;
+		}
+		var featureWPT = new OpenLayers.Feature(this, location, data);
+		this.featuresWPT.push(featureWPT);
+		var marker = featureWPT.createMarker();
+		if ( desc != null) {
+			marker.events.register('click', featureWPT, this.markerClick);
+		}
+		this.addMarker(marker);
+    },
+    addLineGPX: function(xmlNode, color) {
+        var style_green = {
+                strokeColor: color,
+                strokeOpacity: 0.6,
+                strokeWidth: 5,
+                pointRadius: 6,
+                pointerEvents: "visiblePainted"
+        };
+        var pointList = [];
+        for (var i = 0; i < xmlNode.childNodes.length; i++) {
+//	for (var i = 0; i < 4; i++) {
+                if (xmlNode.childNodes[i].nodeName == "trkpt")
+                {
+                        var feature = this.parseFeature(xmlNode.childNodes[i]);
+                        if (feature) {
+                                pointList.push(feature);
+                        }
+                }
+        };
+        return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(pointList),null,style_green);
+    },
+
+     /**
+      * This function is the core of the GPX parsing code in OpenLayers.
+      * It creates the geometries that are then attached to the returned
+      * feature, and calls parseAttributes() to get attribute data out.
+      * @param DOMElement xmlNode
+      */
+     parseFeature: function(xmlNode) {
+        if (xmlNode.getAttribute('lat') && xmlNode.getAttribute('lon')) {
+		var point = this.setToMercator(xmlNode.getAttribute('lon'),xmlNode.getAttribute('lat'));
+		if (xmlNode.childNodes.length > 1) {
+			for(i=0; i < xmlNode.childNodes.length; i++) {
+				switch (xmlNode.childNodes[i].nodeName) {
+					case 'desc':
+						this.addMarkerGPX(point[0], point[1], OpenLayers.Util.getXmlNodeValue(xmlNode.childNodes[i]), null);
+						break;
+					default:
+						break;
+				}
+			}
+		}					
+		return new OpenLayers.Geometry.Point(point[0], point[1]);
+        }
+        return false;
+    },
+    setToMercator: function(lon, lat) {
+    	x = parseFloat(lon);
+	y = parseFloat(lat);
+	var PI = 3.14159265358979323846;
+	x = x * 20037508.34 / 180;
+	y = Math.log (Math.tan ((90 + y) * PI / 360)) / (PI / 180);
+	y = y * 20037508.34 / 180;
+	return new Array(x,y);
+    },
+    /**
+     * 
+     */
+    clearFeatures: function() {
+        if (this.featuresWPT != null) {
+            while(this.featuresWPT.length > 0) {
+                var feature = this.featuresWPT[0];
+                OpenLayers.Util.removeItem(this.featuresWPT, feature);
+                feature.destroy();
+            }
+        }        
+    },
+    requestFailure: function(request) {
+    },
+    moveTo:function(bounds, zoomChanged, dragging) { 
+	OpenLayers.Layer.Vector.prototype.moveTo.apply(this, arguments);
+	OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments);
+        if (!dragging) {
+            this.div.style.left = - parseInt(this.map.layerContainerDiv.style.left) + "px";
+            this.div.style.top = - parseInt(this.map.layerContainerDiv.style.top) + "px";
+            var extent = this.map.getExtent();
+            this.renderer.setExtent(extent);
+	    for(i=0; i < this.markers.length; i++) {
+		marker = this.markers[i];
+		lonlat = this.map.getLayerPxFromLonLat(marker.lonlat);
+                if (marker.icon.calculateOffset) {
+                    marker.icon.offset = marker.icon.calculateOffset(marker.icon.size);
+                }
+                var offsetPx = lonlat.offset(marker.icon.offset);
+		marker.icon.imageDiv.style.left = offsetPx.x+parseInt(this.map.layerContainerDiv.style.left) + "px";
+		marker.icon.imageDiv.style.top = offsetPx.y+parseInt(this.map.layerContainerDiv.style.top) + "px";
+	    }
+		
+        }
+
+    },
+    setMap: function(map) {
+//		OpenLayers.Layer.Markers.prototype.setMap.apply(this, arguments);
+        OpenLayers.Layer.prototype.setMap.apply(this, arguments);
+
+        if (!this.renderer) {
+            this.map.removeLayer(this);
+        } else {
+            this.renderer.map = this.map;
+            this.renderer.setSize(this.map.getSize());
+        }
+
+    },
+    /** @final @type String */
+    CLASS_NAME: "OpenLayers.Layer.GPX"
+});
+     
+    
diff -aburN OpenLayers-2.4.old/lib/OpenLayers.js lib/OpenLayers.js
--- OpenLayers-2.4.old/lib/OpenLayers.js	2007-05-29 15:38:23.000000000 +0200
+++ lib/OpenLayers.js	2007-09-15 10:46:12.000000000 +0200
@@ -138,6 +138,7 @@
         "OpenLayers/Renderer/VML.js",
         "OpenLayers/Layer/Vector.js",
         "OpenLayers/Layer/GML.js",
+	"OpenLayers/Layer/GPX.js",
         "OpenLayers/Format.js",
         "OpenLayers/Format/GML.js",
         "OpenLayers/Format/KML.js",

