[cairo-commit] roadster/src Makefile.am, 1.5, 1.6 datasetwindow.c, 1.3, 1.4 db.c, 1.8, 1.9 db.h, 1.3, 1.4 geometryset.c, 1.6, 1.7 gotowindow.c, 1.3, 1.4 gui.c, 1.3, 1.4 main.c, 1.5, 1.6 mainwindow.c, 1.7, 1.8 mainwindow.h, 1.1, 1.2 map.c, 1.10, 1.11 map.h, 1.1, 1.2 pointstring.c, 1.1, 1.2 pointstring.h, 1.1, 1.2 search_location.c, 1.4, 1.5 search_road.c, 1.8, 1.9 searchwindow.c, 1.5, 1.6

Ian McIntosh commit at pdx.freedesktop.org
Sun Feb 27 19:25:25 PST 2005


Committed by: ian

Update of /cvs/cairo/roadster/src
In directory gabe:/tmp/cvs-serv17134/src

Modified Files:
	Makefile.am datasetwindow.c db.c db.h geometryset.c 
	gotowindow.c gui.c main.c mainwindow.c mainwindow.h map.c 
	map.h pointstring.c pointstring.h search_location.c 
	search_road.c searchwindow.c 
Log Message:
	* configure.ac: Added libsvg-cairo as dependency. (Not quite correct? Nate will fix it.:)
	* Makefile.am: Added glyph.c.
	* datasetwindow.c: Removed Import button.
	* db.c: Removed debugging comments.  City with the same name are no longer shared between states.
	* geometryset.c: Expired a bunch of old code.
	* gotowindow.c: Use mappoint_t instead of loose lat/lon variables.
	* gui.c: Changed an error message.
	* main.c: Move init/deinit code from main() to main_init() and main_deinit()
	* mainwindow.c: Some cleanup and early support for SVG icon loading.
	* map.c: Renamed some variables and functions.  Moved start location from arbitrary spot in MA, USA to (0,0)
	* pointstring.c: Clean up.
	* search_location.c: Use new map_* function names.
	* search_road.c: Use city, state, and zip if present.
	* searchwindow.c: Correctly use G_TYPE_DOUBLE to store coordinates.  Use mappoint_t instead of loose variables.


Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/roadster/src/Makefile.am,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Makefile.am	26 Feb 2005 04:41:40 -0000	1.5
+++ Makefile.am	28 Feb 2005 03:25:23 -0000	1.6
@@ -41,12 +41,14 @@
 	databasewindow.c\
 	point.c\
 	pointstring.c\
-	track.c
+	track.c\
+	glyph.c
 
 roadster_LDADD = \
 	$(GNOME_LIBS) \
 	$(CAIRO_LIBS) \
 	$(MYSQL_LIBS) \
 	$(GPSD_LIBS) \
+	-lsvg-cairo \
 	$(NULL)
 

Index: datasetwindow.c
===================================================================
RCS file: /cvs/cairo/roadster/src/datasetwindow.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- datasetwindow.c	23 Feb 2005 17:22:07 -0000	1.3
+++ datasetwindow.c	28 Feb 2005 03:25:23 -0000	1.4
@@ -20,7 +20,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
- 
+
 #include <glade/glade.h>
 
 #ifdef HAVE_CONFIG_H
@@ -43,7 +43,7 @@
 	GtkTreeView* m_pDataSetListTreeView;
 	GtkListStore* m_pDataSetListModel;
 	GtkButton* m_pDeleteButton;
-	GtkButton* m_pImportButton;
+	// GtkButton* m_pImportButton;
 } g_DataSetWindow;
 
 void datasetwindow_on_dataset_list_selection_changed(GtkTreeSelection *treeselection, gpointer user_data);
@@ -53,14 +53,14 @@
 	/* Find all widgets */
 	g_DataSetWindow.m_pWindow						= GTK_WINDOW(glade_xml_get_widget(pGladeXML, "datasetwindow")); g_return_if_fail(g_DataSetWindow.m_pWindow != NULL);
 	g_DataSetWindow.m_pDeleteButton					= GTK_BUTTON(glade_xml_get_widget(pGladeXML, "datasetdeletebutton")); g_return_if_fail(g_DataSetWindow.m_pDeleteButton != NULL);
-	g_DataSetWindow.m_pImportButton					= GTK_BUTTON(glade_xml_get_widget(pGladeXML, "datasetimportbutton")); g_return_if_fail(g_DataSetWindow.m_pImportButton != NULL);
+	// g_DataSetWindow.m_pImportButton					= GTK_BUTTON(glade_xml_get_widget(pGladeXML, "datasetimportbutton")); g_return_if_fail(g_DataSetWindow.m_pImportButton != NULL);
 	g_DataSetWindow.m_pDataSetListTreeView			= GTK_TREE_VIEW(glade_xml_get_widget(pGladeXML, "datasettreeview")); g_return_if_fail(g_DataSetWindow.m_pDataSetListTreeView != NULL);;
 
 	/* when user hits X, just hide the window */
     g_signal_connect(G_OBJECT(g_DataSetWindow.m_pWindow), "delete_event", G_CALLBACK(gtk_widget_hide), NULL);
 	
 	/* create a model for the data set list (treeview) */
-	g_DataSetWindow.m_pDataSetListModel = gtk_list_store_new(DATASETLIST_NUM_COLUMNS, 
+	g_DataSetWindow.m_pDataSetListModel = gtk_list_store_new(DATASETLIST_NUM_COLUMNS,
 		G_TYPE_INT,
 		G_TYPE_STRING,
 		G_TYPE_STRING);
@@ -97,7 +97,7 @@
 	for(i=0 ; i<NUM_ELEMS(list) ;i++) {
 		gtk_list_store_append(g_DataSetWindow.m_pDataSetListModel, &iter);
 
-		gtk_list_store_set(g_DataSetWindow.m_pDataSetListModel, &iter, 
+		gtk_list_store_set(g_DataSetWindow.m_pDataSetListModel, &iter,
 		DATASETLIST_COLUMN_ID, list[i].ID,
 		DATASETLIST_COLUMN_NAME, list[i].name,
 		DATASETLIST_COLUMN_IMPORT_DATE, list[i].date,
@@ -157,8 +157,3 @@
 		g_print("none selected\n");
 	}
 }
-
-void datasetwindow_on_datasetimportbutton_clicked(GtkWidget *widget, gpointer user_data)
-{
-	mainwindow_begin_import_geography_data();
-}

Index: db.c
===================================================================
RCS file: /cvs/cairo/roadster/src/db.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- db.c	26 Feb 2005 09:37:36 -0000	1.8
+++ db.c	28 Feb 2005 03:25:23 -0000	1.9
@@ -42,28 +42,11 @@
 #include "layers.h"
 #include "locationset.h"
 
-/*
-Notes on the database:
-	- MySQL uses an R-TREE to find the data we want, this is fast
-
-	For a query that matches 690 of 85840 rows:
-	- The query takes about 0.03 seconds
-	- Clearing out previous query's data takes about 0.001 seconds
-	- Retrieving and storing rows takes about 0.07 seconds
-	- Rendering takes 0.5 seconds
-	 Total: 0.6 seconds
-
-	getting just ID but not storing it for 85840 rows: 1.089513
-	getting geography data but not storing it for 85840 rows: 4.006307
-	getting and storing: 4.200560
-*/
 #define MYSQL_RESULT_SUCCESS  	(0)		// for clearer code
 
 #define MAX_SQLBUFFER_LEN		(132000)	// must be big for lists of coordinates
 #define COORD_LIST_MAX 			(128000)
 
-// #define EMBEDDED_DATABASE_NAME	("embedded")
-
 // mysql_use_result - 	less client memory, ties up the server (other clients can't do updates)
 //						better for embedded or local servers
 // mysql_store_result - more client memory, gets all results right away and frees up server
@@ -77,13 +60,10 @@
 	g_assert(pszSQL != NULL);
 	if(g_pDB == NULL) return FALSE;
 	
-//g_print("doing? A - %s\n", pszSQL);
 	if(mysql_query(g_pDB->m_pMySQLConnection, pszSQL) != MYSQL_RESULT_SUCCESS) {
-//g_print("doing? Aaa\n");
 		g_warning("db_query: %s (SQL: %s)\n", mysql_error(g_pDB->m_pMySQLConnection), pszSQL);
 		return FALSE;
 	}
-//g_print("doing? B\n");
 
 	// get result?
 	if(ppResultSet != NULL) {
@@ -148,20 +128,17 @@
 	return mysql_get_host_info(g_pDB->m_pMySQLConnection);
 }
 
-/* String Escaping */
+// call db_free_escaped_string() on returned string
 gchar* db_make_escaped_string(const gchar* pszString)
 {
-	if(!db_is_connected()) return NULL;
+	// make given string safe for inclusion in a SQL string
+	if(!db_is_connected()) return g_strdup("");
 
-//	g_assert_not_reached();	// doesn't do escaping..?
 	gint nLength = (strlen(pszString)*2) + 1;
-//	g_print("length: %s (%d)\n", pszString, nLength);
-	
 	gchar* pszNew = g_malloc(nLength);
 	mysql_real_escape_string(g_pDB->m_pMySQLConnection, pszNew, pszString, strlen(pszString));
 
-//	g_print("huh: %s\n", pszNew);
-	return pszNew;
+	return pszNew; 		
 }
 
 void db_free_escaped_string(gchar* pszString)
@@ -177,7 +154,7 @@
 	MYSQL_ROW aRow;
 	gchar azQuery[MAX_SQLBUFFER_LEN];
 	guint uRows = 0;
-	
+
 	// count rows
 	g_snprintf(azQuery, MAX_SQLBUFFER_LEN, "SELECT COUNT(*) FROM %s;", pszTable);
 	if(mysql_query(g_pDB->m_pMySQLConnection, azQuery) != MYSQL_RESULT_SUCCESS) {
@@ -195,7 +172,7 @@
 
 gboolean db_is_empty()
 {
-	return 	(db_count_table_rows(DB_ROADS_TABLENAME) == 0);
+	return (db_count_table_rows(DB_ROADS_TABLENAME) == 0);
 }
 
 /******************************************************
@@ -206,15 +183,12 @@
 void db_init()
 {
 #ifdef HAVE_MYSQL_EMBED
-	g_print("Initializing embedded MySQL server: ");
-
 	gchar* pszDataDir = g_strdup_printf("%s/.roadster/data", g_get_home_dir());
 	gchar* pszSetDataDirCommand = g_strdup_printf("--datadir=%s", pszDataDir);
 
 	// Create directory if it doesn't exist
-	g_print("creating directory: %s\n", pszDataDir);
 	if(GNOME_VFS_OK != gnome_vfs_make_directory(pszDataDir, 0700)) {
-		g_print("failed to create directory: %s\n", pszDataDir);
+		// no big deal, probably already exists (should we check?)
 	}
 
 	gchar* apszServerOptions[] = {
@@ -228,13 +202,10 @@
 	// Initialize the embedded server
 	// NOTE: if not linked with libmysqld, this call will do nothing (but will succeed)
  	if(mysql_server_init(NUM_ELEMS(apszServerOptions), apszServerOptions, NULL) != 0) {
-		g_print("failed\n");
 		return;
 	}
 	g_free(pszDataDir);
 	g_free(pszSetDataDirCommand);
-
-	g_print("success\n");
 #endif
 }
 
@@ -280,24 +251,6 @@
 	return TRUE;
 }
 
-#if 0
-static void db_disconnect(void)
-{
-	g_return_if_fail(g_pDB != NULL);
-
-	// close database and free all strings
-	mysql_close(g_pDB->m_pMySQLConnection);
-	g_free(g_pDB->m_pzHost);
-	g_free(g_pDB->m_pzUserName);
-	g_free(g_pDB->m_pzPassword);
-	g_free(g_pDB->m_pzDatabase);
-
-	// free structure itself
-	g_free(g_pDB);
-	g_pDB = NULL;
-}
-#endif
-
 /******************************************************
 ** data inserting
 ******************************************************/
@@ -406,13 +359,14 @@
 //
 
 // lookup numerical ID of a city by name
-static gboolean db_city_get_id(const gchar* pszName, gint* pnReturnID)
+gboolean db_city_get_id(const gchar* pszName, gint nStateID, gint* pnReturnID)
 {
-	gint nReturnID = 0;
+	g_assert(pnReturnID != NULL);
 
+	gint nReturnID = 0;
 	// create SQL for selecting City.ID
 	gchar* pszSafeName = db_make_escaped_string(pszName);
-	gchar* pszSQL = g_strdup_printf("SELECT City.ID FROM City WHERE City.Name='%s';", pszSafeName);
+	gchar* pszSQL = g_strdup_printf("SELECT City.ID FROM City WHERE City.Name='%s' AND City.StateID=%d;", pszSafeName, nStateID);
 	db_free_escaped_string(pszSafeName);
 
 	// try query
@@ -440,7 +394,7 @@
 	gint nCityID = 0;
 
 	// Step 1. Insert into RoadName
-	if(db_city_get_id(pszName, &nCityID) == FALSE) {
+	if(db_city_get_id(pszName, nStateID, &nCityID) == FALSE) {
 		gchar* pszSafeName = db_make_escaped_string(pszName);
 		gchar* pszSQL = g_strdup_printf("INSERT INTO City SET Name='%s', StateID=%d", pszSafeName, nStateID);
 		db_free_escaped_string(pszSafeName);
@@ -462,13 +416,13 @@
 // insert / select state
 //
 // lookup numerical ID of a city by name
-static gboolean db_state_get_id(const gchar* pszName, gint* pnReturnID)
+gboolean db_state_get_id(const gchar* pszName, gint* pnReturnID)
 {
 	gint nReturnID = 0;
 
 	// create SQL for selecting City.ID
 	gchar* pszSafeName = db_make_escaped_string(pszName);
-	gchar* pszSQL = g_strdup_printf("SELECT State.ID FROM State WHERE State.Name='%s';", pszSafeName);
+	gchar* pszSQL = g_strdup_printf("SELECT State.ID FROM State WHERE State.Name='%s' OR State.Code='%s';", pszSafeName, pszSafeName);
 	db_free_escaped_string(pszSafeName);
 
 	// try query
@@ -515,106 +469,6 @@
 	return TRUE;
 }
 
-
-/******************************************************
-** data loading
-******************************************************/
-
-/*
-gboolean db_load_geometry(db_connection_t* pConnection, maprect_t* pRect, layer_t* pLayers, gint nNumLayers) //, geometryset_t* pGeometrySet)
-{
-	TIMER_BEGIN(mytimer, "BEGIN DB LOAD");
-
-//	g_return_val_if_fail(pGeometrySet != NULL, FALSE);
-	gint nZoomLevel = map_get_zoomlevel();
-	
-	if(!db_is_connected(pConnection)) return FALSE;
-
-	gchar* pszTable = DB_ROADS_TABLENAME; 	// use a hardcoded table name for now
-	
-	// HACKY: make a list of layer IDs "2,3,5,6"
-	gchar azLayerNumberList[200] = {0};
-	gint nActiveLayerCount = 0;
-	gint i;
-	for(i=LAYER_FIRST ; i <= LAYER_LAST ;i++) {
-		if(g_aLayers[i].m_Style.m_aSubLayers[0].m_afLineWidths[nZoomLevel-1] != 0.0 ||
-		   g_aLayers[i].m_Style.m_aSubLayers[1].m_afLineWidths[nZoomLevel-1] != 0.0)
-		{
-			gchar azLayerNumber[10];
-			if(nActiveLayerCount > 0) g_snprintf(azLayerNumber, 10, ",%d", i);
-			else g_snprintf(azLayerNumber, 10, "%d", i);
-			g_strlcat(azLayerNumberList, azLayerNumber, 200);
-			nActiveLayerCount++;
-		}
-	}
-	if(nActiveLayerCount == 0) {
-		g_print("no visible layers!\n");
-		layers_clear();
-		return TRUE;
-	}
-
-	// generate SQL
-	gchar azQuery[MAX_SQLBUFFER_LEN];
-	g_snprintf(azQuery, MAX_SQLBUFFER_LEN,
-		"SELECT ID, TypeID, AsText(Coordinates) FROM %s WHERE"
-		" TypeID IN (%s) AND" //
-		" MBRIntersects(GeomFromText('Polygon((%f %f,%f %f,%f %f,%f %f,%f %f))'), Coordinates)",
-		pszTable,
-		azLayerNumberList,
-		//~ (nZoomLevel >= 9) ? 2 : 0,
-		pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude, 	// upper left
-		pRect->m_A.m_fLatitude, pRect->m_B.m_fLongitude, 	// upper right
-		pRect->m_B.m_fLatitude, pRect->m_B.m_fLongitude, 	// bottom right
-		pRect->m_B.m_fLatitude, pRect->m_A.m_fLongitude, 	// bottom left
-		pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude		// upper left again
-		);
-	TIMER_SHOW(mytimer, "after SQL generation");
-g_print("sql: %s\n", azQuery);
-	mysql_query(pConnection->m_pMySQLConnection, azQuery);
-	TIMER_SHOW(mytimer, "after query");
-
-	MYSQL_RES* pResultSet = MYSQL_GET_RESULT(pConnection->m_pMySQLConnection);
-	guint32 uRowCount = 0;
-
-	MYSQL_ROW aRow;
-	if(pResultSet) {
-		// HACK: empty out old data, since we don't know how to merge yet
-		layers_clear();
-		TIMER_SHOW(mytimer, "after clear layers");
-
-		while((aRow = mysql_fetch_row(pResultSet))) {
-			uRowCount++;
-
-			// aRow[0] is ID
-			// aRow[1] is TypeID
-			// aRow[2] is Coordinates in mysql's text format
-			//g_print("data: %s, %s, %s\n", aRow[0], aRow[1], aRow[2]);
-
-			gint nTypeID = atoi(aRow[1]);
-			if(nTypeID < LAYER_FIRST || nTypeID > LAYER_LAST) {
-				g_warning("geometry record '%s' has bad type '%s'\n", aRow[0], aRow[1]);
-				continue;
-			}
-
-			//~ // add it to layer
-			geometryset_add_from_mysql_geometry(pLayers[nTypeID].m_pGeometrySet, aRow[2]);
-		} // end while loop on rows
-		g_print(" -- got %d rows\n", uRowCount);
-		TIMER_SHOW(mytimer, "after rows retrieved");
-
-		mysql_free_result(pResultSet);
-		TIMER_SHOW(mytimer, "after free results");
-		TIMER_END(mytimer, "END DB LOAD");
-
-		return TRUE;
-	}
-	else {
-		g_print(" no rows\n");
-		return FALSE;
-	}
-}
-*/
-
 void db_parse_point(const gchar* pszText, mappoint_t* pPoint)
 {
 	const gchar* p;
@@ -686,116 +540,9 @@
 	}
 }
 
-//
-// WordHash functionality
-//
-//~ #define DB_WORDHASH_TABLENAME 	"WordHash"
-
-//~ gint32 db_wordhash_insert(db_connection_t* pConnection, const gchar* pszWord)
-//~ {
-	//~ gchar azQuery[MAX_SQLBUFFER_LEN];
-	//~ int nResult;
-
-	//~ g_snprintf(azQuery, MAX_SQLBUFFER_LEN,
-		//~ "INSERT INTO %s SET ID=NULL, Value='%s';",
-		//~ DB_WORDHASH_TABLENAME, pszWord);
-
-	//~ if((nResult = mysql_query(pConnection->m_pMySQLConnection, azQuery)) != MYSQL_RESULT_SUCCESS) {
-		//~ g_message("db_word_to_int failed to insert: %s\n", mysql_error(pConnection->m_pMySQLConnection));
-		//~ return 0;
-	//~ }
-	//~ return mysql_insert_id(pConnection->m_pMySQLConnection);
-//~ }
-
-//~ gint32 db_wordhash_lookup(db_connection_t* pConnection, const gchar* pszWord)
-//~ {
-	//~ MYSQL_RES* pResultSet;
-	//~ MYSQL_ROW aRow;
-	//~ gint nWordNumber = 0;
-	//~ int nResult;
-	//~ gchar azQuery[MAX_SQLBUFFER_LEN];
-
-	//~ if(!db_is_connected(pConnection)) return FALSE;
-
-	//~ // generate SQL
-	//~ g_snprintf(azQuery, MAX_SQLBUFFER_LEN, "SELECT ID FROM %s WHERE Value='%s';", DB_WORDHASH_TABLENAME, pszWord);
-
-	//~ // get row
-	//~ if((nResult = mysql_query(pConnection->m_pMySQLConnection, azQuery)) != MYSQL_RESULT_SUCCESS) {
-		//~ g_message("db_word_to_int failed to select: %s\n", mysql_error(pConnection->m_pMySQLConnection));
-		//~ return 0;
-	//~ }
-	//~ if((pResultSet = MYSQL_GET_RESULT(pConnection->m_pMySQLConnection)) != NULL) {
-		//~ if((aRow = mysql_fetch_row(pResultSet)) != NULL) {
-			//~ nWordNumber = atoi(aRow[0]);
-		//~ }
-		//~ mysql_free_result(pResultSet);
-	//~ }
-
-	//~ // Successful?  Return it.
-	//~ if(nWordNumber != 0) return nWordNumber;
-	//~ else return 0;
-//~ }
-
-//=======================================================
-// table creation functions
-//=======================================================
-
-//~ TABLES:
-//~ Geometry (lines [roads, rail, rivers], polygons [parks, cemetaries, ponds])
-//~ Points (points)
-//~ Paths (lines)
-
-//~ CREATE TABLE Points (
-	//~ ID INT8 UNSIGNED NOT NULL AUTO_INCREMENT,
-	//~ SetID INT4 UNSIGNED NOT NULL,
-
-	//~ Coordinates POINT NOT NULL,
-	//~ PRIMARY KEY(ID),
-	//~ SPATIAL INDEX(Coordinates)
-//~ );
-
-// TODO: make sure dataset name is clean
-//~ gboolean db_create_points_table(db_connection_t* pConnection, const gchar* szDatasetName)
-//~ {
-	//~ if(!db_is_connected(pConnection)) return FALSE;
-
-	//~ // generate SQL
-	//~ gchar azQuery[MAX_SQLBUFFER_LEN];
-	//~ g_snprintf(azQuery, MAX_SQLBUFFER_LEN, "CREATE TABLE points_%s (ID INT8 UNSIGNED NOT NULL AUTO_INCREMENT, Coordinates POINT NOT NULL, PRIMARY KEY(ID, SPATIAL INDEX(Coordinates));",
-		//~ szDatasetName);
-
-	//~ // execute and return status
-	//~ return (mysql_query(pConnection->m_pMySQLConnection, azQuery) == MYSQL_RESULT_SUCCESS);
-//~ }
-
-//~ GList db_get_table_list(db_connection_t* pConnection)
-//~ {
-	//~ if(!db_is_connected(pConnection)) return FALSE;
-
-	//~ // generate SQL
-	//~ gchar azQuery[MAX_SQLBUFFER_LEN];
-	//~ g_snprintf(azQuery, MAX_SQLBUFFER_LEN, "SHOW TABLES;");
-
-	//~ MYSQL_RES* pResultSet = mysql_list_tables(pConnection->m_pMySQLConnection, "points_%");
-
-	//~ MYSQL_ROW aRow;
-	//~ if(pResultSet) {
-		//~ while((aRow = mysql_fetch_row(pResultSet))) {
-			//~ g_print("table: %s\n", aRow[0]);
-		//~ }		
-		//~ mysql_free_result(pResultSet);
-		//~ return TRUE;
-	//~ }
-	//~ else {
-		//~ return FALSE;
-	//~ }
-//~ }
-
 void db_create_tables()
 {
 	db_query("CREATE DATABASE IF NOT EXISTS roadster;", NULL);
-
 	db_query("USE roadster;", NULL);
 
 	// Road
@@ -825,7 +572,7 @@
 		" Name VARCHAR(30) NOT NULL,"
 		" SuffixID INT1 UNSIGNED NOT NULL,"
 		" PRIMARY KEY (ID),"
-		" UNIQUE KEY (Name, SuffixID));", NULL);
+		" UNIQUE KEY (Name(30), SuffixID));", NULL);
 
 	// Road_RoadName
 	db_query("CREATE TABLE IF NOT EXISTS Road_RoadName("
@@ -897,7 +644,6 @@
 void db_enable_keys(void)
 {
 //	g_print("Enabling keys\n");
-
 //	db_query("ALTER TABLE Road ENABLE KEYS", NULL);
 //	db_query("ALTER TABLE RoadName ENABLE KEYS", NULL);
 //	db_query("ALTER TABLE Road_RoadName ENABLE KEYS", NULL);
@@ -906,14 +652,172 @@
 void db_disable_keys(void)
 {
 //	g_print("Disabling keys\n");
-	
 //	db_query("ALTER TABLE Road DISABLE KEYS", NULL);
 //	db_query("ALTER TABLE RoadName DISABLE KEYS", NULL);
 //	db_query("ALTER TABLE Road_RoadName DISABLE KEYS", NULL);
 }
 
+#ifdef ROADSTER_DEAD_CODE
 /*
-TABLES
-======
+static void db_disconnect(void)
+{
+	g_return_if_fail(g_pDB != NULL);
+
+	// close database and free all strings
+	mysql_close(g_pDB->m_pMySQLConnection);
+	g_free(g_pDB->m_pzHost);
+	g_free(g_pDB->m_pzUserName);
+	g_free(g_pDB->m_pzPassword);
+	g_free(g_pDB->m_pzDatabase);
+
+	// free structure itself
+	g_free(g_pDB);
+	g_pDB = NULL;
+}
+
+//
+// WordHash functionality
+//
+#define DB_WORDHASH_TABLENAME 	"WordHash"
+
+gint32 db_wordhash_insert(db_connection_t* pConnection, const gchar* pszWord)
+{
+	gchar azQuery[MAX_SQLBUFFER_LEN];
+	int nResult;
+
+	g_snprintf(azQuery, MAX_SQLBUFFER_LEN,
+		"INSERT INTO %s SET ID=NULL, Value='%s';",
+		DB_WORDHASH_TABLENAME, pszWord);
+
+	if((nResult = mysql_query(pConnection->m_pMySQLConnection, azQuery)) != MYSQL_RESULT_SUCCESS) {
+		g_message("db_word_to_int failed to insert: %s\n", mysql_error(pConnection->m_pMySQLConnection));
+		return 0;
+	}
+	return mysql_insert_id(pConnection->m_pMySQLConnection);
+}
+
+gint32 db_wordhash_lookup(db_connection_t* pConnection, const gchar* pszWord)
+{
+	MYSQL_RES* pResultSet;
+	MYSQL_ROW aRow;
+	gint nWordNumber = 0;
+	int nResult;
+	gchar azQuery[MAX_SQLBUFFER_LEN];
+
+	if(!db_is_connected(pConnection)) return FALSE;
+
+	// generate SQL
+	g_snprintf(azQuery, MAX_SQLBUFFER_LEN, "SELECT ID FROM %s WHERE Value='%s';", DB_WORDHASH_TABLENAME, pszWord);
+
+	// get row
+	if((nResult = mysql_query(pConnection->m_pMySQLConnection, azQuery)) != MYSQL_RESULT_SUCCESS) {
+		g_message("db_word_to_int failed to select: %s\n", mysql_error(pConnection->m_pMySQLConnection));
+		return 0;
+	}
+	if((pResultSet = MYSQL_GET_RESULT(pConnection->m_pMySQLConnection)) != NULL) {
+		if((aRow = mysql_fetch_row(pResultSet)) != NULL) {
+			nWordNumber = atoi(aRow[0]);
+		}
+		mysql_free_result(pResultSet);
+	}
+
+	// Successful?  Return it.
+	if(nWordNumber != 0) return nWordNumber;
+	else return 0;
+}
+
+gboolean db_load_geometry(db_connection_t* pConnection, maprect_t* pRect, layer_t* pLayers, gint nNumLayers) //, geometryset_t* pGeometrySet)
+{
+	TIMER_BEGIN(mytimer, "BEGIN DB LOAD");
+
+//	g_return_val_if_fail(pGeometrySet != NULL, FALSE);
+	gint nZoomLevel = map_get_zoomlevel();
+	
+	if(!db_is_connected(pConnection)) return FALSE;
+
+	gchar* pszTable = DB_ROADS_TABLENAME; 	// use a hardcoded table name for now
+	
+	// HACKY: make a list of layer IDs "2,3,5,6"
+	gchar azLayerNumberList[200] = {0};
+	gint nActiveLayerCount = 0;
+	gint i;
+	for(i=LAYER_FIRST ; i <= LAYER_LAST ;i++) {
+		if(g_aLayers[i].m_Style.m_aSubLayers[0].m_afLineWidths[nZoomLevel-1] != 0.0 ||
+		   g_aLayers[i].m_Style.m_aSubLayers[1].m_afLineWidths[nZoomLevel-1] != 0.0)
+		{
+			gchar azLayerNumber[10];
+			if(nActiveLayerCount > 0) g_snprintf(azLayerNumber, 10, ",%d", i);
+			else g_snprintf(azLayerNumber, 10, "%d", i);
+			g_strlcat(azLayerNumberList, azLayerNumber, 200);
+			nActiveLayerCount++;
+		}
+	}
+	if(nActiveLayerCount == 0) {
+		g_print("no visible layers!\n");
+		layers_clear();
+		return TRUE;
+	}
+
+	// generate SQL
+	gchar azQuery[MAX_SQLBUFFER_LEN];
+	g_snprintf(azQuery, MAX_SQLBUFFER_LEN,
+		"SELECT ID, TypeID, AsText(Coordinates) FROM %s WHERE"
+		" TypeID IN (%s) AND" //
+		" MBRIntersects(GeomFromText('Polygon((%f %f,%f %f,%f %f,%f %f,%f %f))'), Coordinates)",
+		pszTable,
+		azLayerNumberList,
+		(nZoomLevel >= 9) ? 2 : 0,
+		pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude, 	// upper left
+		pRect->m_A.m_fLatitude, pRect->m_B.m_fLongitude, 	// upper right
+		pRect->m_B.m_fLatitude, pRect->m_B.m_fLongitude, 	// bottom right
+		pRect->m_B.m_fLatitude, pRect->m_A.m_fLongitude, 	// bottom left
+		pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude		// upper left again
+		);
+	TIMER_SHOW(mytimer, "after SQL generation");
+g_print("sql: %s\n", azQuery);
+	mysql_query(pConnection->m_pMySQLConnection, azQuery);
+	TIMER_SHOW(mytimer, "after query");
+
+	MYSQL_RES* pResultSet = MYSQL_GET_RESULT(pConnection->m_pMySQLConnection);
+	guint32 uRowCount = 0;
+
+	MYSQL_ROW aRow;
+	if(pResultSet) {
+		// HACK: empty out old data, since we don't know how to merge yet
+		layers_clear();
+		TIMER_SHOW(mytimer, "after clear layers");
+
+		while((aRow = mysql_fetch_row(pResultSet))) {
+			uRowCount++;
+
+			// aRow[0] is ID
+			// aRow[1] is TypeID
+			// aRow[2] is Coordinates in mysql's text format
+			//g_print("data: %s, %s, %s\n", aRow[0], aRow[1], aRow[2]);
+
+			gint nTypeID = atoi(aRow[1]);
+			if(nTypeID < LAYER_FIRST || nTypeID > LAYER_LAST) {
+				g_warning("geometry record '%s' has bad type '%s'\n", aRow[0], aRow[1]);
+				continue;
+			}
+
+			// add it to layer
+			geometryset_add_from_mysql_geometry(pLayers[nTypeID].m_pGeometrySet, aRow[2]);
+		} // end while loop on rows
+		g_print(" -- got %d rows\n", uRowCount);
+		TIMER_SHOW(mytimer, "after rows retrieved");
 
+		mysql_free_result(pResultSet);
+		TIMER_SHOW(mytimer, "after free results");
+		TIMER_END(mytimer, "END DB LOAD");
+
+		return TRUE;
+	}
+	else {
+		g_print(" no rows\n");
+		return FALSE;
+	}
+}
 */
+#endif
+

Index: db.h
===================================================================
RCS file: /cvs/cairo/roadster/src/db.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- db.h	26 Feb 2005 09:37:36 -0000	1.3
+++ db.h	28 Feb 2005 03:25:23 -0000	1.4
@@ -90,4 +90,7 @@
 							const gchar* pszZIPCodeLeft, const gchar* pszZIPCodeRight,
 							GPtrArray* pPointsArray, gint* pReturnID);
 
+gboolean db_city_get_id(const gchar* pszName, gint nStateID, gint* pnReturnID);
+gboolean db_state_get_id(const gchar* pszName, gint* pnReturnID);
+
 #endif

Index: geometryset.c
===================================================================
RCS file: /cvs/cairo/roadster/src/geometryset.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- geometryset.c	26 Feb 2005 04:41:40 -0000	1.6
+++ geometryset.c	28 Feb 2005 03:25:23 -0000	1.7
@@ -33,6 +33,8 @@
 #include "util.h"
 #include "point.h"
 #include "pointstring.h"
+#include "db.h"
+#include "layers.h"
 
 
 /*******************************************************
@@ -133,7 +135,7 @@
 		pRect->m_B.m_fLatitude, pRect->m_A.m_fLongitude, 	// bottom left
 		pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude		// upper left again
 		);
-//g_print("sql: %s\n", pszSQL);
+	//g_print("sql: %s\n", pszSQL);
 
 	db_query(pszSQL, &pResultSet);
 	g_free(pszSQL);
@@ -176,7 +178,7 @@
 			// does it have a name?			
 			if(aRow[3] != NULL && aRow[4] != NULL) {
 				gint nSuffixID = atoi(aRow[4]);
-				const gchar* pszSuffix = map_road_suffix_itoa(nSuffixID, SUFFIX_TYPE_SHORT);
+				const gchar* pszSuffix = map_road_suffix_itoa(nSuffixID, SUFFIX_LENGTH_SHORT);
 				g_snprintf(azFullName, 100, "%s%s%s",
 					aRow[3], (pszSuffix[0] != '\0') ? " " : "", pszSuffix);
 			}
@@ -200,31 +202,31 @@
 	}	
 }
 
-/*******************************************************
-** Manipulate a geometryset_t
-*******************************************************/
-
+#ifdef ROADSTER_DEAD_CODE
 /*******************************************************
 ** Debug functions
 *******************************************************/
-// void geometryset_debug_print(geometryset_t* pGeometrySet)
-// {
-//     if(pGeometrySet->m_pPointStringsArray == NULL) {
-//         g_print("m_pPointStringsArray is NULL\n");
-//     }
-//     else {
-//         g_print("pointstring list (%d items):\n", pGeometrySet->m_pPointStringsArray->len);
-//         int i;
-//         for(i=0 ; i<pGeometrySet->m_pPointStringsArray->len ; i++) {
-//             pointstring_t* pPointString = g_ptr_array_index(pGeometrySet->m_pPointStringsArray, i);
-//
-//             g_print("- string (%d items): ", pPointString->m_pPointsArray->len);
-//             int j;
-//             for(j=0 ; j<pPointString->m_pPointsArray->len ; j++) {
-//                 mappoint_t* pPoint = g_ptr_array_index(pPointString->m_pPointsArray, j);
-//                 g_print("(%.5f,%.5f), ", pPoint->m_fLatitude, pPoint->m_fLongitude);
-//             }
-//             g_print("\n");
-//         }
-//     }
-// }
+/*
+void geometryset_debug_print(geometryset_t* pGeometrySet)
+{
+	if(pGeometrySet->m_pPointStringsArray == NULL) {
+		g_print("m_pPointStringsArray is NULL\n");
+	}
+	else {
+		g_print("pointstring list (%d items):\n", pGeometrySet->m_pPointStringsArray->len);
+		int i;
+		for(i=0 ; i<pGeometrySet->m_pPointStringsArray->len ; i++) {
+			pointstring_t* pPointString = g_ptr_array_index(pGeometrySet->m_pPointStringsArray, i);
+
+			g_print("- string (%d items): ", pPointString->m_pPointsArray->len);
+			int j;
+			for(j=0 ; j<pPointString->m_pPointsArray->len ; j++) {
+				mappoint_t* pPoint = g_ptr_array_index(pPointString->m_pPointsArray, j);
+				g_print("(%.5f,%.5f), ", pPoint->m_fLatitude, pPoint->m_fLongitude);
+			}
+			g_print("\n");
+		}
+	}
+}
+*/
+#endif

Index: gotowindow.c
===================================================================
RCS file: /cvs/cairo/roadster/src/gotowindow.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- gotowindow.c	23 Feb 2005 17:22:07 -0000	1.3
+++ gotowindow.c	28 Feb 2005 03:25:23 -0000	1.4
@@ -20,7 +20,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
- 
+
 #include <glade/glade.h>
 #include <gnome.h>
 #include "util.h"
@@ -59,7 +59,7 @@
 	// don't delete window on X, just hide it
     g_signal_connect(G_OBJECT(g_GotoWindow.m_pWindow), "delete_event", G_CALLBACK(gtk_widget_hide), NULL);
 
-	g_GotoWindow.m_pLocationListModel = gtk_list_store_new(LOCATIONLIST_NUM_COLUMNS, 
+	g_GotoWindow.m_pLocationListModel = gtk_list_store_new(LOCATIONLIST_NUM_COLUMNS,
 		G_TYPE_STRING,
 		G_TYPE_STRING,
 		G_TYPE_DOUBLE,
@@ -96,7 +96,7 @@
 	for(i=0 ; i<NUM_ELEMS(list) ;i++) {
 		gtk_list_store_append(g_GotoWindow.m_pLocationListModel, &iter);
 
-		gtk_list_store_set(g_GotoWindow.m_pLocationListModel, &iter, 
+		gtk_list_store_set(g_GotoWindow.m_pLocationListModel, &iter,
 		LOCATIONLIST_COLUMN_NAME, list[i].name,
 		LOCATIONLIST_COLUMN_LOCATION, g_strdup_printf("(%8.5f, %8.5f)", list[i].lat, list[i].lon),
 		LOCATIONLIST_COLUMN_LATITUDE, list[i].lat,
@@ -146,14 +146,14 @@
 {
 	const gchar* pszLatitude = gtk_entry_get_text(g_GotoWindow.m_pLatitudeEntry);
 	const gchar* pszLongitude = gtk_entry_get_text(g_GotoWindow.m_pLongitudeEntry);
-	double fLatitude;
-	if(!util_string_to_double(pszLatitude, &fLatitude)) return FALSE;
-	double fLongitude;
-	if(!util_string_to_double(pszLongitude, &fLongitude)) return FALSE;
+
+	mappoint_t pt;
+	if(!util_string_to_double(pszLatitude, &(pt.m_fLatitude))) return FALSE;
+	if(!util_string_to_double(pszLongitude, &(pt.m_fLongitude))) return FALSE;
 
 	// TODO: error checking for 0 (meaning either bad text "3a21" or "000" etc.
 
-	map_center_on_worldpoint(fLatitude, fLongitude);
+	map_set_centerpoint(&pt);
 	mainwindow_draw_map();
 	mainwindow_statusbar_update_position();
 	return TRUE;

Index: gui.c
===================================================================
RCS file: /cvs/cairo/roadster/src/gui.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- gui.c	26 Feb 2005 04:41:40 -0000	1.3
+++ gui.c	28 Feb 2005 03:25:23 -0000	1.4
@@ -53,7 +53,7 @@
 		pGladeXML = glade_xml_new (PACKAGE_SOURCE_DIR"/data/roadster.glade", NULL, NULL);
 
 		if(pGladeXML == NULL) {
-			g_message("can't find glade xml file");
+			g_message("cannot find file roadster.glade\n");
 			gtk_exit(0);
 		}
 	}
@@ -88,3 +88,4 @@
 
 	gtk_exit(0);
 }
+

Index: main.c
===================================================================
RCS file: /cvs/cairo/roadster/src/main.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- main.c	26 Feb 2005 04:41:40 -0000	1.5
+++ main.c	28 Feb 2005 03:25:23 -0000	1.6
@@ -39,50 +39,71 @@
 #include "pointstring.h"
 #include "track.h"
 
+static void main_deinit(void);
+static void main_init(void);
+
 int main (int argc, char *argv[])
 {
 	#ifdef ENABLE_NLS
 		bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
 		textdomain(PACKAGE);
 	#endif
-
 	gnome_init(PACKAGE, VERSION, argc, argv);
 
+	main_init();
+	gui_run();
+	main_deinit();	// usually doesn't get here
+	return 0;
+}
+
+void main_init(void)
+{
 	if(!gnome_vfs_init()) {	
 		g_warning("gnome_vfs_init failed\n");
 		return 1;
 	}
 	gchar* pszApplicationDir = g_strdup_printf("%s/.roadster", g_get_home_dir());
 	if(GNOME_VFS_OK != gnome_vfs_make_directory(pszApplicationDir, 0700)) {
-		g_print("failed to create directory: %s\n", pszApplicationDir);
+		// no big deal, it probably exists.
 	}
 
 	/*
 	** init our modules
 	*/
+	g_print("initializing points\n");
 	point_init();
+	g_print("initializing pointstrings\n");
 	pointstring_init();
+	g_print("initializing tracks\n");
 	track_init();
+	g_print("initializing glyphs\n");
+	glyph_init();
 
+	g_print("initializing scenemanager\n");
 	scenemanager_init();
 	//geometryset_init();
+	g_print("initializing locationsets\n");
 	locationset_init();
+	g_print("initializing gpsclient\n");
 	gpsclient_init();
+	g_print("initializing gui\n");
 	gui_init();
+	g_print("initializing layers\n");
 	layers_init();
+	g_print("initializing db\n");
 	db_init();
 
+	g_print("connecting to db\n");
 	gboolean bConnected = db_connect(NULL, NULL, NULL, "");
-	db_create_tables();
 
-	map_set_zoomlevel(7);
-	mainwindow_statusbar_update_zoomscale();
+	g_print("creating needed tables\n");
+	db_create_tables();
 
-	/* Go! */
-	gui_run();
+	g_print("initialization complete\n");
+}
 
-	/* deinit -- never gets here? :( */
-	g_message("shutting down...");
+static void main_deinit(void)
+{
 	db_deinit();
-	return 0;
+	// others?
 }

Index: mainwindow.c
===================================================================
RCS file: /cvs/cairo/roadster/src/mainwindow.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- mainwindow.c	26 Feb 2005 04:48:39 -0000	1.7
+++ mainwindow.c	28 Feb 2005 03:25:23 -0000	1.8
@@ -41,6 +41,8 @@
 #include "databasewindow.h"
 #include "mainwindow.h"
 
+#include "glyph.h"
+
 #include <gdk/gdkx.h>
 #include <cairo.h>
 
@@ -81,16 +83,10 @@
 } EToolType;
 
 // Prototypes
-gboolean mainwindow_on_mouse_button_click(GtkWidget* w, GdkEventButton *event);
-gboolean mainwindow_on_expose_event(GtkWidget *pDrawingArea, GdkEventExpose *event, gpointer data);
-gint mainwindow_on_configure_event(GtkWidget *pDrawingArea, GdkEventConfigure *event);
-void mainwindow_draw_map(void);
-
-void mainwindow_statusbar_update_zoomscale(void);
-void mainwindow_statusbar_update_position(void);
-void mainwindow_setup_selected_tool(void);
-
-gboolean mainwindow_callback_on_gps_redraw_timeout(gpointer pData);
+static gboolean mainwindow_on_mouse_button_click(GtkWidget* w, GdkEventButton *event);
+static gboolean mainwindow_on_expose_event(GtkWidget *pDrawingArea, GdkEventExpose *event, gpointer data);
+static gint mainwindow_on_configure_event(GtkWidget *pDrawingArea, GdkEventConfigure *event);
+static gboolean mainwindow_callback_on_gps_redraw_timeout(gpointer pData);
 
 struct {
 	GtkWindow* m_pWindow;
@@ -136,6 +132,7 @@
 	EToolType m_eSelectedTool;
 
 	gint m_nCurrentGPSPath;
+	gint m_nGPSLocationGlyph;
 } g_MainWindow = {0};
 
 // Data
@@ -237,6 +234,9 @@
 
 	cursor_init();
 
+	g_print("loading at %s\n", PACKAGE_DATA_DIR);
+	g_MainWindow.m_nGPSLocationGlyph = glyph_load(PACKAGE_DATA_DIR"/car.svg");
+
 	/*
 	**
 	*/
@@ -401,9 +401,9 @@
 void mainwindow_statusbar_update_position(void)
 {
 	char buf[200];
-	float fLatitude, fLongitude;
-	map_get_world_coordinates(&fLatitude, &fLongitude);
-	g_snprintf(buf, 200, "Lat: %.5f, Lon: %.5f", fLatitude, fLongitude);
+	mappoint_t pt;
+	map_get_centerpoint(&pt);
+	g_snprintf(buf, 200, "Lat: %.5f, Lon: %.5f", pt.m_fLatitude, pt.m_fLongitude);
 	mainwindow_set_statusbar_position(buf);
 }
 
@@ -607,29 +607,18 @@
 	mainwindow_toggle_fullscreen();
 }
 
-void mainwindow_on_gotomenuitem_activate(GtkMenuItem     *menuitem, gpointer user_data)
+void mainwindow_on_gotomenuitem_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
+//	g_print("mainwindow_on_gotomenuitem_activate\n");
 	gotowindow_show();
 }
 
-void on_importmenuitem_activate(GtkMenuItem *menuitem, gpointer user_data)
-{
-	importwindow_show();
-}
-
 void on_gotobutton_clicked(GtkToolButton *toolbutton,  gpointer user_data)
 {
 	gotowindow_show();
 }
 
-#if ROADSTER_DEAD_CODE
-static void on_gotodialoggobutton_activate(GtkButton *button, gpointer user_data)
-{
-	gotowindow_show();
-}
-#endif /* ROADSTER_DEAD_CODE */
-
-gboolean mainwindow_on_mouse_button_click(GtkWidget* w, GdkEventButton *event)
+static gboolean mainwindow_on_mouse_button_click(GtkWidget* w, GdkEventButton *event)
 {
 	gint nX;
 	gint nY;
@@ -666,7 +655,7 @@
 	return TRUE;
 }
 
-void mainwindow_begin_import_geography_data(void)
+static void mainwindow_begin_import_geography_data(void)
 {
 	GtkWidget* pDialog = gtk_file_chooser_dialog_new(
 				"Select Map Data for Import",
@@ -705,7 +694,7 @@
 	mainwindow_begin_import_geography_data();
 }
 
-void mainwindow_setup_selected_tool(void)
+static void mainwindow_setup_selected_tool(void)
 {
 	if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(g_MainWindow.m_pPointerToolButton))) {
 		gui_set_tool(kToolPointer);
@@ -727,7 +716,7 @@
 //	g_print("mainwindow_draw_map()\n");
 
 	void* pBusy = mainwindow_set_busy();
-	
+
     Display* dpy;
     Drawable drawable;
 
@@ -737,15 +726,15 @@
 	cairo_t *pCairoInstance;
 	pCairoInstance = cairo_create ();
 		// draw on an off-screen buffer
-		
 		cairo_set_target_drawable(pCairoInstance, dpy, drawable);
 		map_draw(pCairoInstance);
-	
+
 		pointstring_t* pTrackPointString = track_get_pointstring(g_MainWindow.m_nCurrentGPSPath);
 		if(pTrackPointString) {
 			map_draw_gps_trail(pCairoInstance, pTrackPointString);
 		}
 
+		// glyph_draw_centered(pCairoInstance, g_MainWindow.m_nGPSLocationGlyph, 200, 200);
 	cairo_destroy(pCairoInstance);
 
 	gtk_widget_queue_draw(GTK_WIDGET(g_MainWindow.m_pDrawingArea));
@@ -753,10 +742,9 @@
 	mainwindow_set_not_busy(&pBusy);
 }
 	
-// Create a new backing pixmap of the appropriate size
-gint mainwindow_on_configure_event(GtkWidget *pDrawingArea, GdkEventConfigure *event)
+static gint mainwindow_on_configure_event(GtkWidget *pDrawingArea, GdkEventConfigure *event)
 {
-//	g_print("on_configure_event()\n");
+	// Create a new backing pixmap of the appropriate size
 
 	if(g_MainWindow.m_pOffscreenPixmap != NULL) {
 		gdk_pixmap_unref(g_MainWindow.m_pOffscreenPixmap);
@@ -767,13 +755,17 @@
 						GTK_WIDGET(g_MainWindow.m_pDrawingArea)->allocation.height,
 						-1);
 
-	map_set_view_dimensions(GTK_WIDGET(g_MainWindow.m_pDrawingArea)->allocation.width, GTK_WIDGET(g_MainWindow.m_pDrawingArea)->allocation.height);
+	// tell the map how big to draw
+	dimensions_t dim;
+	dim.m_uWidth = GTK_WIDGET(g_MainWindow.m_pDrawingArea)->allocation.width;
+	dim.m_uHeight = GTK_WIDGET(g_MainWindow.m_pDrawingArea)->allocation.height;
+	map_set_dimensions(&dim);
 
 	mainwindow_draw_map();
 	return TRUE;
 }
 
-gboolean mainwindow_on_expose_event(GtkWidget *pDrawingArea, GdkEventExpose *event, gpointer data)
+static gboolean mainwindow_on_expose_event(GtkWidget *pDrawingArea, GdkEventExpose *event, gpointer data)
 {
 //	g_print("mainwindow_on_expose_event(x=%d,y=%d,w=%d,h=%d)\n", event->area.x, event->area.y, event->area.width, event->area.height);
 
@@ -806,16 +798,7 @@
 	}
 }
 
-void mainwindow_on_datasetmenuitem_activate(GtkWidget *pWidget, gpointer* p)
-{
-	datasetwindow_show();
-}
-
-void mainwindow_show_on_startup(void)
-{
-}
-
-gboolean mainwindow_callback_on_gps_redraw_timeout(gpointer __unused)
+static gboolean mainwindow_callback_on_gps_redraw_timeout(gpointer __unused)
 {
 	// NOTE: we're setting tooltips on the image's
 	GtkWidget* pWidget = gtk_widget_get_parent(GTK_WIDGET(g_MainWindow.m_pStatusbarGPSIcon));
@@ -887,7 +870,16 @@
 	return TRUE;
 }
 
-#if 0
+
+
+
+#ifdef ROADSTER_DEAD_CODE
+void on_importmenuitem_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+	g_print("on_importmenuitem_activate\n");
+	importwindow_show();
+}
+
 static void on_layervisible_checkbox_clicked(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
 {
 	GtkTreeModel *model = (GtkTreeModel *)data;
@@ -912,4 +904,10 @@
 	/* clean up */
 	gtk_tree_path_free (path);
 }
-#endif
+
+void mainwindow_on_datasetmenuitem_activate(GtkWidget *pWidget, gpointer* p)
+{
+	datasetwindow_show();
+}
+
+#endif /* ROADSTER_DEAD_CODE */

Index: mainwindow.h
===================================================================
RCS file: /cvs/cairo/roadster/src/mainwindow.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- mainwindow.h	23 Feb 2005 17:43:50 -0000	1.1
+++ mainwindow.h	28 Feb 2005 03:25:23 -0000	1.2
@@ -20,7 +20,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
- 
+
 #ifndef _MAINWINDOW_H
 #define _MAINWINDOW_H
 
@@ -30,18 +30,27 @@
 extern "C"
 {
 #endif
-	
+
 void mainwindow_init(GladeXML* pGladeXML);
 void mainwindow_draw_map(void);
+GtkWidget* mainwindow_get_window(void);
 
+// Visibility
 void mainwindow_show(void);
 void mainwindow_show_on_startup(void);
 void mainwindow_hide(void);
 
+// Sensitivity
 void mainwindow_set_sensitive(gboolean bSensitive);
 
+// Full screen
 void mainwindow_toggle_fullscreen(void);
 
+// Busy
+void* mainwindow_set_busy(void);
+void mainwindow_set_not_busy(void** pCursor);
+
+// Toolbar / Statusbar / Sidebox
 void mainwindow_set_toolbar_visible(gboolean);
 gboolean mainwindow_get_toolbar_visible(void);
 
@@ -51,19 +60,14 @@
 void mainwindow_set_sidebox_visible(gboolean);
 gboolean mainwindow_get_sidebox_visible(void);
 
-GtkWidget* mainwindow_get_window(void);
-
 void mainwindow_statusbar_update_zoomscale(void);
 void mainwindow_statusbar_update_position(void);
 
 void mainwindow_statusbar_progressbar_set_text(const gchar* pszText);
 void mainwindow_statusbar_progressbar_pulse(void);
 void mainwindow_statusbar_progressbar_clear(void);
-
-void mainwindow_begin_import_geography_data(void);
-
-void* mainwindow_set_busy(void);
-void mainwindow_set_not_busy(void** pCursor);
+void mainwindow_statusbar_update_zoomscale(void);
+void mainwindow_statusbar_update_position(void);
 
 /* Funky, auto-lookup glade signal handlers.
 
@@ -81,10 +85,11 @@
 void on_zoomin_activate(GtkMenuItem *menuitem, gpointer user_data);
 void on_zoomout_activate(GtkMenuItem *menuitem, gpointer user_data);
 void on_fullscreenmenuitem_activate(GtkMenuItem *menuitem, gpointer user_data);
-void mainwindow_on_gotomenuitem_activate(GtkMenuItem     *menuitem, gpointer user_data);
 void on_importmenuitem_activate(GtkMenuItem *menuitem, gpointer user_data);
 void on_gotobutton_clicked(GtkToolButton *toolbutton,  gpointer user_data);
 void on_toolbutton_clicked(GtkToolButton *toolbutton, gpointer user_data);
+
+void mainwindow_on_gotomenuitem_activate(GtkMenuItem     *menuitem, gpointer user_data);
 void mainwindow_on_addpointmenuitem_activate(GtkWidget *_unused, gpointer* __unused);
 void mainwindow_on_datasetmenuitem_activate(GtkWidget *pWidget, gpointer* p);
 

Index: map.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- map.c	26 Feb 2005 04:41:40 -0000	1.10
+++ map.c	28 Feb 2005 03:25:23 -0000	1.11
@@ -31,7 +31,6 @@
 #define ROAD_FONT	"Bitstream Vera Sans"
 #define AREA_FONT	"Bitstream Vera Sans" // "Bitstream Charter"
 
-
 #include "gui.h"
 #include "map.h"
 #include "geometryset.h"
@@ -42,19 +41,16 @@
 #include "locationset.h"
 #include "scenemanager.h"
 
-// 4,382,755 inches per degree
-// 363 inches of world represented in 3.63 inches
-
 struct {
-	mappoint_t 			m_MapCenter;	// XXX
-	windowdimensions_t 	m_WindowDimensions;					// XXX
-	guint16 			m_uZoomLevel;							// XXX
+	mappoint_t 			m_MapCenter;				// XXX
+	dimensions_t 			m_MapDimensions;			// XXX
+	guint16 			m_uZoomLevel;				// XXX
 	gboolean 			m_bRedrawNeeded;
 } g_Map =
 {
-	{42.29886, -73.24393},
-	{0,0},
-	7,
+	{0.0,0.0},	// starting position
+	{0,0},		// map dimensions
+	7,			// starting zoomlevel
 	TRUE
 };
 
@@ -274,14 +270,13 @@
 
 /* Prototypes */
 
-void map_draw_layer_polygons(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle);
-void map_draw_layer_lines(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle);
-void map_draw_layer_line_labels(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle);
-void map_draw_layer_polygon_labels(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle);
-
-void map_draw_polygon_label(cairo_t *pCairo, textlabelstyle_t* pLabelStyle, rendermetrics_t* pRenderMetrics, pointstring_t* pPointString, const gchar* pszLabel);
-void map_draw_layer_points(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pLocationsArray);
-
+static void map_draw_layer_polygons(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle);
+static void map_draw_layer_lines(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle);
+static void map_draw_layer_line_labels(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle);
+static void map_draw_layer_polygon_labels(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle);
+static void map_draw_polygon_label(cairo_t *pCairo, textlabelstyle_t* pLabelStyle, rendermetrics_t* pRenderMetrics, pointstring_t* pPointString, const gchar* pszLabel);
+static void map_draw_layer_points(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pLocationsArray);
+static void map_draw_crosshair(cairo_t* pCairo, rendermetrics_t* pRenderMetrics);
 
 // Each zoomlevel has a scale and an optional name (name isn't used for anything)
 zoomlevel_t g_sZoomLevels[NUM_ZOOMLEVELS+1] = {
@@ -421,8 +416,8 @@
 void map_windowpoint_to_mappoint(screenpoint_t* pScreenPoint, mappoint_t* pMapPoint)
 {
 	// Calculate the # of pixels away from the center point the click was
-	gint16 nPixelDeltaX = (gint)(pScreenPoint->m_nX) - (g_Map.m_WindowDimensions.m_uWidth / 2);
-	gint16 nPixelDeltaY = (gint)(pScreenPoint->m_nY) - (g_Map.m_WindowDimensions.m_uHeight / 2);
+	gint16 nPixelDeltaX = (gint)(pScreenPoint->m_nX) - (g_Map.m_MapDimensions.m_uWidth / 2);
+	gint16 nPixelDeltaY = (gint)(pScreenPoint->m_nY) - (g_Map.m_MapDimensions.m_uHeight / 2);
 
 	// Convert pixels to world coordinates
 	pMapPoint->m_fLongitude = g_Map.m_MapCenter.m_fLongitude + map_pixels_to_degrees(nPixelDeltaX, g_Map.m_uZoomLevel);
@@ -434,8 +429,8 @@
 void map_center_on_windowpoint(guint16 uX, guint16 uY)
 {
 	// Calculate the # of pixels away from the center point the click was
-	gint16 nPixelDeltaX = uX - (g_Map.m_WindowDimensions.m_uWidth / 2);
-	gint16 nPixelDeltaY = uY - (g_Map.m_WindowDimensions.m_uHeight / 2);
+	gint16 nPixelDeltaX = uX - (g_Map.m_MapDimensions.m_uWidth / 2);
+	gint16 nPixelDeltaY = uY - (g_Map.m_MapDimensions.m_uHeight / 2);
 
 	// Convert pixels to world coordinates
 	double fWorldDeltaX = map_pixels_to_degrees(nPixelDeltaX, g_Map.m_uZoomLevel);
@@ -444,37 +439,37 @@
 
 //	g_message("panning %d,%d pixels (%.10f,%.10f world coords)\n", nPixelDeltaX, nPixelDeltaY, fWorldDeltaX, fWorldDeltaY);
 
-	map_center_on_worldpoint(g_Map.m_MapCenter.m_fLatitude + fWorldDeltaY, g_Map.m_MapCenter.m_fLongitude + fWorldDeltaX);
+	mappoint_t pt;
+	pt.m_fLatitude = g_Map.m_MapCenter.m_fLatitude + fWorldDeltaY;
+	pt.m_fLongitude = g_Map.m_MapCenter.m_fLongitude + fWorldDeltaX;
+	map_set_centerpoint(&pt);
 }
 
-void map_center_on_worldpoint(double fLatitude, double fLongitude)
+void map_set_centerpoint(const mappoint_t* pPoint)
 {
-	g_Map.m_MapCenter.m_fLatitude = fLatitude;
-	g_Map.m_MapCenter.m_fLongitude = fLongitude;
+	g_assert(pPoint != NULL);
 
-	map_set_redraw_needed(TRUE);
-}
+	g_Map.m_MapCenter.m_fLatitude = pPoint->m_fLatitude;
+	g_Map.m_MapCenter.m_fLongitude = pPoint->m_fLongitude;
 
-void map_get_world_coordinate_point(mappoint_t* pPoint)
-{
-	pPoint->m_fLatitude = g_Map.m_MapCenter.m_fLatitude;
-	pPoint->m_fLongitude = g_Map.m_MapCenter.m_fLongitude;
+	map_set_redraw_needed(TRUE);
 }
 
-void map_get_world_coordinates(float* pLatitude, float* pLongitude)
+void map_get_centerpoint(mappoint_t* pReturnPoint)
 {
-	g_return_if_fail(pLatitude != NULL);
-	g_return_if_fail(pLongitude != NULL);
+	g_assert(pReturnPoint != NULL);
 
-	*pLatitude = g_Map.m_MapCenter.m_fLatitude;
-	*pLongitude = g_Map.m_MapCenter.m_fLongitude;
+	pReturnPoint->m_fLatitude = g_Map.m_MapCenter.m_fLatitude;
+	pReturnPoint->m_fLongitude = g_Map.m_MapCenter.m_fLongitude;
 }
 
-// Call this on init and every time the window changes size
-void map_set_view_dimensions(guint16 uWidth, guint16 uHeight)
+//
+void map_set_dimensions(const dimensions_t* pDimensions)
 {
-	g_Map.m_WindowDimensions.m_uWidth = uWidth;
-	g_Map.m_WindowDimensions.m_uHeight = uHeight;
+	g_assert(pDimensions != NULL);
+
+	g_Map.m_MapDimensions.m_uWidth = pDimensions->m_uWidth;
+	g_Map.m_MapDimensions.m_uHeight = pDimensions->m_uHeight;
 }
 
 #if ROADSTER_DEAD_CODE
@@ -488,7 +483,7 @@
 	// When we multiply this angle (in radians) by the radius, we get the length of the arc.
 
 	// NOTE: This algorithm wrongly assumes that Earth is a perfect sphere.
-	//       It is actually slightly egg shaped.
+	//       It is actually slightly egg shaped.  But it's good enough.
 
 	// All trig functions expect arguments in radians.
 	double fLonA_Rad = DEG2RAD(pA->m_fLongitude);
@@ -506,10 +501,6 @@
 #endif /* ROADSTER_DEAD_CODE */
 
 // ========================================================
-//  Draw Functions
-// ========================================================
-
-// ========================================================
 //  Redraw
 // ========================================================
 
@@ -518,21 +509,42 @@
 	g_Map.m_bRedrawNeeded = bNeeded;
 }
 
-gboolean map_is_redraw_needed()
+gboolean map_get_redraw_needed()
 {
 	return g_Map.m_bRedrawNeeded;
 }
 
-gboolean map_redraw_if_needed()
+// ========================================================
+//  Draw Functions
+// ========================================================
+
+void map_get_render_metrics(rendermetrics_t* pMetrics)
 {
-	return TRUE;
+	g_assert(pMetrics != NULL);
+
+	//
+	// Set up renderMetrics array
+	//
+	pMetrics->m_nZoomLevel = map_get_zoomlevel();
+	pMetrics->m_nWindowWidth = g_Map.m_MapDimensions.m_uWidth;
+	pMetrics->m_nWindowHeight = g_Map.m_MapDimensions.m_uHeight;
+
+	// Calculate how many world degrees we'll be drawing
+	pMetrics->m_fScreenLatitude = map_pixels_to_degrees(g_Map.m_MapDimensions.m_uHeight, pMetrics->m_nZoomLevel);
+	pMetrics->m_fScreenLongitude = map_pixels_to_degrees(g_Map.m_MapDimensions.m_uWidth, pMetrics->m_nZoomLevel);
+
+	// The world bounding box (expressed in lat/lon) of the data we will be drawing
+	pMetrics->m_rWorldBoundingBox.m_A.m_fLongitude = g_Map.m_MapCenter.m_fLongitude - pMetrics->m_fScreenLongitude/2;
+	pMetrics->m_rWorldBoundingBox.m_A.m_fLatitude = g_Map.m_MapCenter.m_fLatitude - pMetrics->m_fScreenLatitude/2;
+	pMetrics->m_rWorldBoundingBox.m_B.m_fLongitude = g_Map.m_MapCenter.m_fLongitude + pMetrics->m_fScreenLongitude/2;
+	pMetrics->m_rWorldBoundingBox.m_B.m_fLatitude = g_Map.m_MapCenter.m_fLatitude + pMetrics->m_fScreenLatitude/2;	
 }
 
 static void map_draw_background(cairo_t *pCairo)
 {
 	cairo_save(pCairo);
 		cairo_set_rgb_color(pCairo, 247/255.0, 235/255.0, 230/255.0);
-		cairo_rectangle(pCairo, 0, 0, g_Map.m_WindowDimensions.m_uWidth, g_Map.m_WindowDimensions.m_uHeight);
+		cairo_rectangle(pCairo, 0, 0, g_Map.m_MapDimensions.m_uWidth, g_Map.m_MapDimensions.m_uHeight);
 		cairo_fill(pCairo);
 	cairo_restore(pCairo);
 }
@@ -882,137 +894,6 @@
 	
 	scenemanager_label_drawn(pszLabel);
 }
-// g_print("map (%f,%f)->(%f,%f) screen (%f,%f)->(%f,%f) center (%f,%f)\n",pMapPoint1->m_fLatitude,pMapPoint1->m_fLongitude,  pMapPoint2->m_fLatitude,pMapPoint2->m_fLongitude,  fX1,fY1,  fX2,fY2,  fX,fY);
-		// Calculate line length (in screen pixels)
-
-/*
-void map_draw_line_label(cairo_t *pCairo, rendermetrics_t* pRenderMetrics, pointstring_t* pPointString, gdouble fLineWidth, const gchar* pszLabel)
-{
-	
-	// HACK
-	if(random()%1000 > 100) return;
-	
-	if(pPointString->m_pPointsArray->len < 2) return;
-
-//	if(pPointString->m_pPointsArray->len > 2) {
-//		g_print("(has %d)\n", pPointString->m_pPointsArray->len);
-//	}
-		
-	// for now just take the first line segment
-	mappoint_t* pMapPoint1 = g_ptr_array_index(pPointString->m_pPointsArray, 0);
-	mappoint_t* pMapPoint2 = g_ptr_array_index(pPointString->m_pPointsArray, 1);
-	mappoint_t* pTemp;
-	
-	if(pMapPoint1->m_fLongitude > pMapPoint2->m_fLongitude) {
-		// swap them so point 1 is to the left
-		pTemp = pMapPoint1;
-		pMapPoint1 = pMapPoint2;
-		pMapPoint2 = pTemp;
-	}
-
-	gdouble fX1 = SCALE_X(pRenderMetrics, pMapPoint1->m_fLongitude);
-	gdouble fY1 = SCALE_Y(pRenderMetrics, pMapPoint1->m_fLatitude);
-	gdouble fX2 = SCALE_X(pRenderMetrics, pMapPoint2->m_fLongitude);
-	gdouble fY2 = SCALE_Y(pRenderMetrics, pMapPoint2->m_fLatitude);
-
-	// determine slope of the line
-	gdouble fRise = fY2 - fY1;
-	gdouble fRun = fX2 - fX1;
-
-	gdouble fAngleInRadians = atan(fRise / fRun); // * (M_PI/180.0);
-
-// g_print("map (%f,%f)->(%f,%f) screen (%f,%f)->(%f,%f) center (%f,%f)\n",pMapPoint1->m_fLatitude,pMapPoint1->m_fLongitude,  pMapPoint2->m_fLatitude,pMapPoint2->m_fLongitude,  fX1,fY1,  fX2,fY2,  fX,fY);
-		// Calculate line length (in screen pixels)
-	gdouble fLineLength = sqrt((fRun*fRun) + (fRise*fRise));
-	gfloat fFontSize;
-	cairo_text_extents_t extents;
-
-	// try several font sizes until one fits
-	gboolean bFound = FALSE;
-	for(fFontSize = 12.0 ; fFontSize >= 10.0 ; fFontSize -= 0.5) {
-		cairo_save(pCairo);
-		cairo_select_font(pCairo, "Monospace", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-		cairo_scale_font(pCairo, fFontSize);
-		cairo_text_extents(pCairo, pszLabel, &extents);
-
-		if(extents.width > fLineLength) {
-			cairo_restore(pCairo);
-			continue;
-		}
-		else {
-			bFound = TRUE;
-			break;	
-		}
-	}
-	if(!bFound) {
-		//cairo_restore(pCairo);
-		return;
-	}
-
-		// Normalize (make length = 1.0) by dividing by line length
-		// This makes a line with length 1 from the origin (0,0)
-		gdouble fNormalizedX = fRun / fLineLength;
-		gdouble fNormalizedY = fRise / fLineLength;
-
-		// (buffer space) |-text-| (buffer space)
-		// ======================================
-		gdouble fHalfBufferSpace = ((fLineLength - extents.width)/2);
-		gdouble fDrawX = fX1 + (fNormalizedX * fHalfBufferSpace);
-		gdouble fDrawY = fY1 + (fNormalizedY * fHalfBufferSpace);
-
-		// *Swap the X and Y* and normalize (make length = 1.0) by dividing by line length
-		// This makes a perpendicular line with length 1 from the origin (0,0)
-		gdouble fPerpendicularNormalizedX = fRise / fLineLength;
-		gdouble fPerpendicularNormalizedY = fRun / fLineLength;
-		// we want the normal pointing towards the top of the screen.  that's the negative Y direction.
-		if(fPerpendicularNormalizedY > 0) fPerpendicularNormalizedY = -fPerpendicularNormalizedY;	
-		
-		// text too big to fit?  then move the text "up"
-		if(extents.height > (fLineWidth - LABEL_PIXEL_RELIEF_INSIDE_LINE)) {
-			// Raise the text "up" (away from center of line) half the width of the line
-			// This leaves it resting on the line.  Then add a few pixels of relief.
-
-			// NOTE: the point started in the dead-center of the line
-			fDrawX += (fPerpendicularNormalizedX * ((fLineWidth / 2) + LABEL_PIXELS_ABOVE_LINE));
-			fDrawY += (fPerpendicularNormalizedY * ((fLineWidth / 2) + LABEL_PIXELS_ABOVE_LINE));
-		}
-		else {
-			// just nudge it down slightly-- the text shows up "ABOVE" and to the "RIGHT" of the point
-			fDrawX -= (fPerpendicularNormalizedX * extents.height/2);
-			fDrawY -= (fPerpendicularNormalizedY * extents.height/2);
-		}
-
-		// draw!
-		cairo_move_to(pCairo, fDrawX, fDrawY);
-		cairo_rotate(pCairo, fAngleInRadians);
-		cairo_text_path(pCairo, pszLabel);
-		cairo_set_rgb_color(pCairo, 0.1,0.1,0.1);
-		cairo_set_alpha(pCairo, 1.0);
-		cairo_fill(pCairo);
-	cairo_restore(pCairo);
-}
-*/
-void map_get_render_metrics(rendermetrics_t* pMetrics)
-{
-	g_assert(pMetrics != NULL);
-
-	//
-	// Set up renderMetrics array
-	//
-	pMetrics->m_nZoomLevel = map_get_zoomlevel();
-	pMetrics->m_nWindowWidth = g_Map.m_WindowDimensions.m_uWidth;
-	pMetrics->m_nWindowHeight = g_Map.m_WindowDimensions.m_uHeight;
-
-	// Calculate how many world degrees we'll be drawing
-	pMetrics->m_fScreenLatitude = map_pixels_to_degrees(g_Map.m_WindowDimensions.m_uHeight, pMetrics->m_nZoomLevel);
-	pMetrics->m_fScreenLongitude = map_pixels_to_degrees(g_Map.m_WindowDimensions.m_uWidth, pMetrics->m_nZoomLevel);
-
-	// The world bounding box (expressed in lat/lon) of the data we will be drawing
-	pMetrics->m_rWorldBoundingBox.m_A.m_fLongitude = g_Map.m_MapCenter.m_fLongitude - pMetrics->m_fScreenLongitude/2;
-	pMetrics->m_rWorldBoundingBox.m_A.m_fLatitude = g_Map.m_MapCenter.m_fLatitude - pMetrics->m_fScreenLatitude/2;
-	pMetrics->m_rWorldBoundingBox.m_B.m_fLongitude = g_Map.m_MapCenter.m_fLongitude + pMetrics->m_fScreenLongitude/2;
-	pMetrics->m_rWorldBoundingBox.m_B.m_fLatitude = g_Map.m_MapCenter.m_fLatitude + pMetrics->m_fScreenLatitude/2;	
-}
 
 void map_draw(cairo_t *pCairo)
 {
@@ -1065,17 +946,25 @@
 		}			
 	TIMER_END(loctimer, "END RENDER LOCATIONS");
 
-	//
-	// crosshair
-	//
-#define CROSSHAIR_LINE_RELIEF	(6)
-#define CROSSHAIR_LINE_LENGTH	(12)
+	map_draw_crosshair(pCairo, pRenderMetrics);
+	
+	cairo_restore(pCairo);
+
+	// We don't need another redraw until something changes
+	map_set_redraw_needed(FALSE);
+}
+
+#define CROSSHAIR_LINE_RELIEF   (6)
+#define CROSSHAIR_LINE_LENGTH   (12)
 #define CROSSHAIR_CIRCLE_RADIUS (12)
 
+static void map_draw_crosshair(cairo_t* pCairo, rendermetrics_t* pRenderMetrics)
+{
+	cairo_save(pCairo);
 		cairo_set_line_width(pCairo, 1.0);
 		cairo_set_rgb_color(pCairo, 0.1, 0.1, 0.1);
 		cairo_set_alpha(pCairo, 1.0);
-
+		
 		// left line
 		cairo_move_to(pCairo, (pRenderMetrics->m_nWindowWidth/2) - (CROSSHAIR_LINE_RELIEF + CROSSHAIR_LINE_LENGTH), (pRenderMetrics->m_nWindowHeight/2));
 		cairo_line_to(pCairo, (pRenderMetrics->m_nWindowWidth/2) - (CROSSHAIR_LINE_RELIEF), (pRenderMetrics->m_nWindowHeight/2));
@@ -1084,19 +973,15 @@
 		cairo_line_to(pCairo, (pRenderMetrics->m_nWindowWidth/2) + (CROSSHAIR_LINE_RELIEF), (pRenderMetrics->m_nWindowHeight/2));
 		// top line
 		cairo_move_to(pCairo, (pRenderMetrics->m_nWindowWidth/2), (pRenderMetrics->m_nWindowHeight/2) - (CROSSHAIR_LINE_RELIEF + CROSSHAIR_LINE_LENGTH));
-		cairo_line_to(pCairo, (pRenderMetrics->m_nWindowWidth/2), (pRenderMetrics->m_nWindowHeight/2) - (CROSSHAIR_LINE_RELIEF));		
+		cairo_line_to(pCairo, (pRenderMetrics->m_nWindowWidth/2), (pRenderMetrics->m_nWindowHeight/2) - (CROSSHAIR_LINE_RELIEF));
 		// bottom line
 		cairo_move_to(pCairo, (pRenderMetrics->m_nWindowWidth/2), (pRenderMetrics->m_nWindowHeight/2) + (CROSSHAIR_LINE_RELIEF + CROSSHAIR_LINE_LENGTH));
 		cairo_line_to(pCairo, (pRenderMetrics->m_nWindowWidth/2), (pRenderMetrics->m_nWindowHeight/2) + (CROSSHAIR_LINE_RELIEF));
 		cairo_stroke(pCairo);
-
-		cairo_arc(pCairo, pRenderMetrics->m_nWindowWidth/2, pRenderMetrics->m_nWindowHeight/2, CROSSHAIR_CIRCLE_RADIUS, 0, 2*M_PI);		
+		
+		cairo_arc(pCairo, pRenderMetrics->m_nWindowWidth/2, pRenderMetrics->m_nWindowHeight/2, CROSSHAIR_CIRCLE_RADIUS, 0, 2*M_PI);
 		cairo_stroke(pCairo);
-	
 	cairo_restore(pCairo);
-
-	// We don't need another redraw until something changes
-	map_set_redraw_needed(FALSE);
 }
 
 void map_draw_layer_points(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pLocationsArray)
@@ -1145,8 +1030,6 @@
 {
 	mappoint_t* pPoint;
 	pointstring_t* pPointString;
-	gint iString;
-	gint iPoint;
 
 	gdouble fLineWidth = pSubLayerStyle->m_afLineWidths[pRenderMetrics->m_nZoomLevel-1];
 	if(fLineWidth == 0.0) return;	// Don't both drawing with line width 0
@@ -1162,6 +1045,7 @@
 	cairo_set_line_cap(pCairo, pSubLayerStyle->m_nCapStyle);	/* CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_ROUND, CAIRO_LINE_CAP_CAP */
 //	cairo_set_dash(pCairo, g_aDashStyles[pSubLayerStyle->m_nDashStyle].m_pfList, g_aDashStyles[pSubLayerStyle->m_nDashStyle].m_nCount, 0.0);
 
+	gint iString;
 	for(iString=0 ; iString<pGeometry->m_pPointStringsArray->len ; iString++) {
 		pPointString = g_ptr_array_index(pGeometry->m_pPointStringsArray, iString);
 
@@ -1172,6 +1056,7 @@
 			cairo_move_to(pCairo, SCALE_X(pRenderMetrics, pPoint->m_fLongitude), SCALE_Y(pRenderMetrics, pPoint->m_fLatitude));
 
 			// start at index 1 (0 was used above)
+			gint iPoint;
 			for(iPoint=1 ; iPoint<pPointString->m_pPointsArray->len ; iPoint++) {
 				pPoint = g_ptr_array_index(pPointString->m_pPointsArray, iPoint);				
 				cairo_line_to(pCairo, SCALE_X(pRenderMetrics, pPoint->m_fLongitude), SCALE_Y(pRenderMetrics, pPoint->m_fLatitude));
@@ -1238,12 +1123,12 @@
 			nCapStyle = CAIRO_LINE_CAP_SQUARE;
 		}
 
-//         if(fLineWidth >= 3.0) {
-//             fTolerance = 1.2;
-//         }
-//         else {  // smaller...
-//             fTolerance = 10;
-//         }
+		if(fLineWidth >= 3.0) {
+			fTolerance = 1.2;
+		}
+		else {  // smaller...
+			fTolerance = 10;
+		}
 	}
 	cairo_set_tolerance(pCairo, fTolerance);
 	cairo_set_line_join(pCairo, pSubLayerStyle->m_nJoinStyle);
@@ -1260,11 +1145,6 @@
 	for(iString=0 ; iString<pGeometry->m_pPointStringsArray->len ; iString++) {
 		pPointString = g_ptr_array_index(pGeometry->m_pPointStringsArray, iString);
 
-//~ cairo_set_rgb_color(pCairo, pSubLayerStyle->m_clrColor.m_fRed, pSubLayerStyle->m_clrColor.m_fGreen, pSubLayerStyle->m_clrColor.m_fBlue);
-//~ if(pPointString->m_pPointsArray->len >= 3) {
-	//~ cairo_set_rgb_color(pCairo, 1, 0, 0);
-//~ }
-	
 		if(pPointString->m_pPointsArray->len >= 2) {
 			pPoint = g_ptr_array_index(pPointString->m_pPointsArray, 0);
 
@@ -1293,11 +1173,11 @@
 
 void map_draw_layer_line_labels(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle)
 {
-	gint iString;
+	gint i;
 	gdouble fLineWidth = pSubLayerStyle->m_afLineWidths[pRenderMetrics->m_nZoomLevel-1];
 
-	for(iString=0 ; iString<pGeometry->m_pPointStringsArray->len ; iString++) {
-		pointstring_t* pPointString = g_ptr_array_index(pGeometry->m_pPointStringsArray, iString);
+	for(i=0 ; i<pGeometry->m_pPointStringsArray->len ; i++) {
+		pointstring_t* pPointString = g_ptr_array_index(pGeometry->m_pPointStringsArray, i);
 		if(pPointString->m_pszName[0] != '\0') {
 			map_draw_line_label(pCairo, pLabelStyle, pRenderMetrics, pPointString, fLineWidth, pPointString->m_pszName);
 		}
@@ -1307,7 +1187,6 @@
 void map_draw_layer_polygon_labels(cairo_t* pCairo, rendermetrics_t* pRenderMetrics, geometryset_t* pGeometry, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle)
 {
 	gint i;
-
 	for(i=0 ; i<pGeometry->m_pPointStringsArray->len ; i++) {
 		pointstring_t* pPointString = g_ptr_array_index(pGeometry->m_pPointStringsArray, i);
 		
@@ -1317,32 +1196,6 @@
 	}
 }
 
-const gchar* map_road_suffix_itoa(gint nSuffixID, gint nSuffixType)
-{
-	if(nSuffixID >= ROAD_SUFFIX_FIRST && nSuffixID <= ROAD_SUFFIX_LAST) {
-		if(nSuffixType == SUFFIX_TYPE_SHORT) {
-			return g_RoadNameSuffix[nSuffixID].m_pszShort;
-		}
-		else {
-			return g_RoadNameSuffix[nSuffixID].m_pszLong;			
-		}
-	}
-	if(nSuffixID != ROAD_SUFFIX_NONE) return "???";
-	return "";
-}
-
-gboolean map_road_suffix_atoi(const gchar* pszSuffix, gint* pReturnSuffixID)
-{
-	gint i;
-	for(i=0 ; i<NUM_ELEMS(g_RoadNameSuffixLookup) ; i++) {
-		if(g_ascii_strcasecmp(pszSuffix, g_RoadNameSuffixLookup[i].m_pszName) == 0) {
-			*pReturnSuffixID = g_RoadNameSuffixLookup[i].m_nID;
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
 void map_draw_gps_trail(cairo_t* pCairo, pointstring_t* pPointString)
 {
 	rendermetrics_t renderMetrics = {0};
@@ -1364,7 +1217,40 @@
 
 		cairo_set_rgb_color(pCairo, 0.0, 0.0, 0.7);
 		cairo_set_alpha(pCairo, 0.6);
-		cairo_set_line_width(pCairo, 10);
+		cairo_set_line_width(pCairo, 6);
+		cairo_set_line_cap(pCairo, CAIRO_LINE_CAP_ROUND);
+		cairo_set_line_join(pCairo, CAIRO_LINE_JOIN_ROUND);
+		cairo_set_miter_limit(pCairo, 5);
 		cairo_stroke(pCairo);
 	}
 }
+
+// ========================================================
+//	Road Direction / Suffix conversions
+// ========================================================
+
+const gchar* map_road_suffix_itoa(gint nSuffixID, ESuffixLength eSuffixLength)
+{
+	if(nSuffixID >= ROAD_SUFFIX_FIRST && nSuffixID <= ROAD_SUFFIX_LAST) {
+		if(eSuffixLength == SUFFIX_LENGTH_SHORT) {
+			return g_RoadNameSuffix[nSuffixID].m_pszShort;
+		}
+		else {
+			return g_RoadNameSuffix[nSuffixID].m_pszLong;			
+		}
+	}
+	if(nSuffixID != ROAD_SUFFIX_NONE) return "???";
+	return "";
+}
+
+gboolean map_road_suffix_atoi(const gchar* pszSuffix, gint* pReturnSuffixID)
+{
+	gint i;
+	for(i=0 ; i<NUM_ELEMS(g_RoadNameSuffixLookup) ; i++) {
+		if(g_ascii_strcasecmp(pszSuffix, g_RoadNameSuffixLookup[i].m_pszName) == 0) {
+			*pReturnSuffixID = g_RoadNameSuffixLookup[i].m_nID;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}

Index: map.h
===================================================================
RCS file: /cvs/cairo/roadster/src/map.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- map.h	23 Feb 2005 17:43:50 -0000	1.1
+++ map.h	28 Feb 2005 03:25:23 -0000	1.2
@@ -53,11 +53,10 @@
 	screenpoint_t m_B;
 } screenrect_t;
 
-// Window space (0,0 being upper left of the draw area)
 typedef struct windowdimensions {
 	guint16 m_uWidth;
 	guint16 m_uHeight;
-} windowdimensions_t;
+} dimensions_t;
 
 typedef struct zoomlevel {
 	guint32 m_uScale;		// ex. 10000 for 1:10000 scale
@@ -128,16 +127,7 @@
 	ROAD_SUFFIX_LAST = ROAD_SUFFIX_ARC
 };
 
-//~ type 'Ctr' couldn't be looked up
-//~ type 'Walk' couldn't be looked up
-//~ type 'Ramp' couldn't be looked up
-//~ type 'Cv' couldn't be looked up
-//~ type 'Byp' couldn't be looked up
-//~ type 'Ramp' couldn't be looked up
-//~ type 'Br' couldn't be looked up
-//~ type 'Trce' couldn't be looked up
-
-typedef struct rendermetrics {
+typedef struct {
 	gint m_nZoomLevel;
 	gdouble m_fScreenLatitude;
 	gdouble m_fScreenLongitude;
@@ -146,43 +136,38 @@
 	gint m_nWindowHeight;
 } rendermetrics_t;
 
-// SuffixTypes
-#define SUFFIX_TYPE_SHORT	(0)
-#define SUFFIX_TYPE_LONG		(1)
-
-const gchar* map_road_suffix_itoa(gint nSuffixID, gint nSuffixType);
-gboolean map_road_suffix_atoi(const gchar* pszSuffix, gint* pReturnSuffixID);
+// ESuffixLength
+typedef enum {
+	SUFFIX_LENGTH_SHORT,
+    SUFFIX_LENGTH_LONG
+} ESuffixLength;
 
-#include "db.h"
+void map_draw(cairo_t *cr);
 
-GtkWidget* map_create_canvas(void);
+const gchar* map_road_suffix_itoa(gint nSuffixID, ESuffixLength eSuffixLength);
+gboolean map_road_suffix_atoi(const gchar* pszSuffix, gint* pReturnSuffixID);
 
-void map_set_zoomlevel(guint16 uZoomLevel);
+// Gets and Sets
 guint16 map_get_zoomlevel(void);
 guint32 map_get_zoomlevel_scale(void);
+void map_set_zoomlevel(guint16 uZoomLevel);
+//void map_get_render_metrics(rendermetrics_t* pMetrics);
 
 void map_set_redraw_needed(gboolean bNeeded);
-gboolean map_is_redraw_needed(void);
-guint32 map_get_scale(void);
-//void map_draw(void* pDBConnection, cairo_t * cr);
-
-void map_get_world_coordinates(float* pLongitude, float* pLatitude);
-void map_get_world_coordinate_point(mappoint_t* pPoint);
+gboolean map_get_redraw_needed(void);
 
-void map_center_on_worldpoint(double fX, double fY);
-void map_center_on_windowpoint(guint16 uX, guint16 uY);
-void map_set_window_dimensions(guint16 uWidth, guint16 uHeight);
+guint32 map_get_scale(void);
 
-gboolean map_redraw_if_needed(void);
+void map_set_centerpoint(const mappoint_t* pPoint);
+void map_get_centerpoint(mappoint_t* pReturnPoint);
+void map_set_dimensions(const dimensions_t* pDimensions);
 
-void map_set_view_dimensions(guint16 uWidth, guint16 uHeight);
+// Conversions
 void map_windowpoint_to_mappoint(screenpoint_t* pScreenPoint, mappoint_t* pMapPoint);
+gdouble map_distance_in_units_to_degrees(gdouble fDistance, gint nDistanceUnit);
 
 
-void map_draw(cairo_t *cr);
-
-void map_get_render_metrics(rendermetrics_t* pMetrics);
-
-gdouble map_distance_in_units_to_degrees(gdouble fDistance, gint nDistanceUnit);
+// remove this!
+void map_center_on_windowpoint(guint16 uX, guint16 uY);
 
 #endif

Index: pointstring.c
===================================================================
RCS file: /cvs/cairo/roadster/src/pointstring.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- pointstring.c	26 Feb 2005 04:41:40 -0000	1.1
+++ pointstring.c	28 Feb 2005 03:25:23 -0000	1.2
@@ -70,7 +70,7 @@
 }
 
 // copies pPoint and adds it
-void pointstring_append_point(pointstring_t* pPointString, mappoint_t* pPoint)
+void pointstring_append_point(pointstring_t* pPointString, const mappoint_t* pPoint)
 {
 	mappoint_t* pNewPoint = NULL;
 	point_alloc(&pNewPoint);

Index: pointstring.h
===================================================================
RCS file: /cvs/cairo/roadster/src/pointstring.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- pointstring.h	26 Feb 2005 04:41:40 -0000	1.1
+++ pointstring.h	28 Feb 2005 03:25:23 -0000	1.2
@@ -33,6 +33,6 @@
 void pointstring_init(void);
 gboolean pointstring_alloc(pointstring_t** ppPointString);
 void pointstring_free(pointstring_t* pPointString);
-void pointstring_append_point(pointstring_t* pPointString, mappoint_t* pPoint);
+void pointstring_append_point(pointstring_t* pPointString, const mappoint_t* pPoint);
 
 #endif

Index: search_location.c
===================================================================
RCS file: /cvs/cairo/roadster/src/search_location.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- search_location.c	23 Feb 2005 17:22:07 -0000	1.4
+++ search_location.c	28 Feb 2005 03:25:23 -0000	1.5
@@ -82,7 +82,7 @@
 	gchar* pszCoordinatesMatch = NULL;
 	if(TRUE) {
 		mappoint_t ptCenter;
-		map_get_world_coordinate_point(&ptCenter);
+		map_get_centerpoint(&ptCenter);
 
 		gdouble fDegrees = pLocationSearch->m_fRadiusInDegrees;
 		pszCoordinatesMatch = g_strdup_printf(

Index: search_road.c
===================================================================
RCS file: /cvs/cairo/roadster/src/search_road.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- search_road.c	26 Feb 2005 09:37:36 -0000	1.8
+++ search_road.c	28 Feb 2005 03:25:23 -0000	1.9
@@ -36,8 +36,10 @@
 
 typedef struct {
 	gint m_nNumber;			// house number	eg. 51
-	gchar* m_pszRoadName;	// road name eg. Washington
-
+	gchar* m_pszRoadName;	// road name eg. "Washington"
+	gint m_nCityID;			//
+	gint m_nStateID;
+	gint m_pszZIPCode;
 	gint m_nSuffixID;		// a number representing eg. Ave
 } roadsearch_t;
 
@@ -59,6 +61,41 @@
 }
 #endif
 
+gchar* g_strjoinv_limit(const gchar* separator, gchar** a, gint iFirst, gint iLast)
+{
+	g_assert(iFirst <= iLast);
+	g_assert(iLast < g_strv_length(a));
+
+	gchar* pszSave;
+
+	// replace first unwanted string with NULL (save old value)
+	pszSave = a[iLast+1];
+	a[iLast+1] = NULL;
+
+	// use built-in function for joining
+	gchar* pszReturn = g_strjoinv(separator, &a[iFirst]);
+
+	// restore old value
+	a[iLast+1] = pszSave;
+	return pszReturn;
+}
+
+gboolean search_address_match_zipcode(const gchar* pszWord)
+{
+	// very US-centric right now
+	gint nLen = strlen(pszWord);
+	if(nLen < 4 || nLen > 5) return FALSE;
+
+	gint i;
+	for(i=0 ; i<nLen ; i++) {
+		// XXX: is g_ascii_isalnum the right function? we should be testing for numbers only
+		if(!g_ascii_isdigit(pszWord[i])) {
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
 // prototypes
 
 void search_road_on_cleaned_sentence(const gchar* pszCleanedSentence);
@@ -105,14 +142,6 @@
 	g_assert(nWordCount > 0);
 	roadsearch_t roadsearch = {0};
 
-	/*  Match these:
-	First
-	First St.
-	101 First
-	101 First St.
-	101 First Street
-	*/
-
 	// index of first and last words of road name (the bit in the middle)
 	gint iFirst = 0;
 	gint iLast = nWordCount-1;
@@ -120,7 +149,7 @@
 	// Start stripping off words as we identify roadsearch_t structure members
 	gint nRemainingWordCount = nWordCount;
 
-	// house number
+	// Claim house number if present
 	roadsearch.m_nNumber = ROADSEARCH_NUMBER_NONE;
 	if(nRemainingWordCount >= 2) {
 		if(search_address_number_atoi(aWords[iFirst], &roadsearch.m_nNumber)) {
@@ -129,30 +158,99 @@
 		}
 	}
 
+	// Claim zip code, if present
+	if(search_address_match_zipcode(aWords[iLast])) {
+		g_print("matched ZIP %s\n", aWords[iLast]);
+		roadsearch.m_pszZIPCode = aWords[iLast];
+
+		iLast--;	// last word taken
+		nRemainingWordCount--;
+	}
+
+	if(nRemainingWordCount == 0) {
+		// do a zip code search and return
+		g_print("TODO: zip code search\n");
+		return;
+	}
+
+	// See if we can match a state name   XXX: We need to match multi-word state names
+	gboolean bGotStateName = FALSE;
+	if(nRemainingWordCount >= 3) {
+		// try two-word state name
+		gchar* pszStateName = g_strjoinv_limit(" ", aWords, iLast-1, iLast);
+		g_print("trying two-word state name '%s'\n", pszStateName);
+
+		if(db_state_get_id(pszStateName, &roadsearch.m_nStateID)) {
+			g_print("matched state name!\n");
+			iLast -= 2;	// last TWO words taken
+			nRemainingWordCount -= 2;
+		}
+		g_free(pszStateName);
+	}
+	// try a one-word state name
+	if(bGotStateName == FALSE && nRemainingWordCount >= 2) {
+		g_print("trying one-word state name '%s'\n", aWords[iLast]);
+		if(db_state_get_id(aWords[iLast], &roadsearch.m_nStateID)) {
+			g_print("matched state name!\n");
+			iLast--;	// last word taken
+			nRemainingWordCount--;
+		}
+	}
+
+	// try to match city name
+	gint nCityNameLength;
+	for(nCityNameLength = 5 ; nCityNameLength >= 1 ; nCityNameLength--) {
+		if(nRemainingWordCount > nCityNameLength) {
+			gchar* pszCityName = g_strjoinv_limit(" ", aWords, iLast - (nCityNameLength-1), iLast);
+
+			if(db_city_get_id(pszCityName, roadsearch.m_nStateID, &roadsearch.m_nCityID)) {
+				iLast -= nCityNameLength;	// several words taken :)
+				nRemainingWordCount -= nCityNameLength;
+
+				// success
+				g_free(pszCityName);
+				break;
+			}
+			else {
+				// failure
+				g_free(pszCityName);
+				continue;
+			}
+		}
+	}
+
 	// road name suffix (eg. "ave")
 	if(nRemainingWordCount >= 2) {
 		gint nSuffixID;
+
 		if(map_road_suffix_atoi(aWords[iLast], &nSuffixID)) {
+			// matched
 			roadsearch.m_nSuffixID = nSuffixID;
 			iLast--;
 			nRemainingWordCount--;
 		}
 	}
 
-	// finally, take remaining words and consider that the street name
-	// TODO: concat the words from iFirst to iLast together.. do NOT just use iLast!!!!
-	roadsearch.m_pszRoadName = g_strdup(aWords[iLast]);
-	search_road_on_roadsearch_struct(&roadsearch);
-
+	if(nRemainingWordCount > 0) {
+		roadsearch.m_pszRoadName = g_strjoinv_limit(" ", aWords, iFirst, iLast);
+		search_road_on_roadsearch_struct(&roadsearch);
+	}
+	else {
+		// oops, no street name
+		g_print("no street name found in search\n");
+	}
 	g_free(roadsearch.m_pszRoadName);
 }
 
 void search_road_on_roadsearch_struct(const roadsearch_t* pRoadSearch)
 {
+	//
+	// Assemble the various optional clauses for the SQL statement
+	//
 	gchar* pszAddressClause;
 	if(pRoadSearch->m_nNumber != ROADSEARCH_NUMBER_NONE) {
 		pszAddressClause = g_strdup_printf(
-			"AND ("
+			" AND ("
 			"(%d BETWEEN Road.AddressLeftStart AND Road.AddressLeftEnd)"
 			" OR (%d BETWEEN Road.AddressLeftEnd AND Road.AddressLeftStart)"
 			" OR (%d BETWEEN Road.AddressRightStart AND Road.AddressRightEnd)"
@@ -167,14 +265,38 @@
 	gchar* pszSuffixClause;
 	if(pRoadSearch->m_nSuffixID != ROAD_SUFFIX_NONE) {
 		pszSuffixClause = g_strdup_printf(
-			"AND (RoadName.SuffixID = %d)",
+			" AND (RoadName.SuffixID = %d)",
 			pRoadSearch->m_nSuffixID);
 	}
 	else {
 		pszSuffixClause = g_strdup("");
 	}
 
-	// if doing a road search, only show 1 hit per road
+	gchar* pszZIPClause;
+	if(pRoadSearch->m_pszZIPCode != NULL) {
+		pszZIPClause = g_strdup_printf(" AND (Road.ZIPCodeLeft='%s' OR Road.ZIPCodeRight='%s')", pRoadSearch->m_pszZIPCode, pRoadSearch->m_pszZIPCode);
+	}
+	else {
+		pszZIPClause = g_strdup("");
+	}
+
+	gchar* pszCityClause;
+	if(pRoadSearch->m_nCityID != 0) {
+		pszCityClause = g_strdup_printf(" AND (Road.CityLeftID=%d OR Road.CityRightID=%d)", pRoadSearch->m_nCityID, pRoadSearch->m_nCityID);
+	}
+	else {
+		pszCityClause = g_strdup("");
+	}
+
+	gchar* pszStateClause;
+	if(pRoadSearch->m_nStateID != 0) {
+		pszStateClause = g_strdup_printf(" AND (CityLeft.StateID=%d OR CityRight.StateID=%d)", pRoadSearch->m_nStateID, pRoadSearch->m_nStateID);
+	}
+	else {
+		pszStateClause = g_strdup("");
+	}
+
+	// if doing a road search, only show 1 hit per road?
 	//~ gchar* pszGroupClause;
 	//~ if(pRoadSearch->m_nSuffixID == ROAD_SUFFIX_NONE) {
 		//~ pszGroupClause = g_strdup("GROUP BY (RoadName.ID, RoadName.SuffixID)");
@@ -192,7 +314,7 @@
 		", StateLeft.Code, StateRight.Code, Road.ZIPCodeLeft, Road.ZIPCodeRight"
 		" FROM RoadName"
 		" LEFT JOIN Road_RoadName ON (RoadName.ID=Road_RoadName.RoadNameID)"
- 	    " LEFT JOIN Road ON (Road_RoadName.RoadID=Road.ID %s)"	// address # clause
+ 	    " LEFT JOIN Road ON (Road_RoadName.RoadID=Road.ID%s)"					// address # clause
 		// left side
 	    " LEFT JOIN City AS CityLeft ON (Road.CityLeftID=CityLeft.ID)"
 		" LEFT JOIN State AS StateLeft ON (CityLeft.StateID=StateLeft.ID)"
@@ -202,18 +324,30 @@
 		" WHERE RoadName.Name LIKE '%s%%'"
 //		" WHERE RoadName.Name='%s'"
 		" AND Road.ID IS NOT NULL"	// don't include rows where the Road didn't match
-		" %s"
-//		" %s"
-		" ORDER BY RoadName.Name"
-		" LIMIT %d;", pszAddressClause, pszSafeRoadName, pszSuffixClause,
-			// pszGroupClause,
+		// begin clauses
+		"%s"
+		"%s"
+  	    "%s"
+ 	    "%s"
+//		" ORDER BY RoadName.Name"
+		" LIMIT %d;",
+			   pszAddressClause,
+			   pszSafeRoadName,
+
+			   // clauses
+			   pszSuffixClause,
+			   pszZIPClause,
+			   pszCityClause,
+			   pszStateClause,
 			SEARCH_RESULT_COUNT_LIMIT + 1);
 	
 	// free strings
 	db_free_escaped_string(pszSafeRoadName);
 	g_free(pszAddressClause);
 	g_free(pszSuffixClause);
-//	g_free(pszGroupClause);
+	g_free(pszZIPClause);
+	g_free(pszCityClause);
+	g_free(pszStateClause);
 
 //	g_strlcpy(azQuery, , MAX_QUERY);
 	g_print("SQL: %s\n", azQuery);
@@ -366,6 +500,11 @@
 }
 #endif /* ROADSTER_DEAD_CODE */
 
+
+//
+// XXX: the SQL doesn't require all fields be set for THE SAME SIDE
+// 		do we need to filter out records where each side matches some of the criteria but not all?
+//
 #define BUFFER_SIZE 200
 void search_road_filter_result(
 		const gchar* pszRoadName, gint nRoadNumber, gint nRoadSuffixID,
@@ -398,6 +537,9 @@
 										 (pszStateNameRight != NULL) ? pszStateNameRight : "",
 										 (strcmp(pszZIPRight, "00000") == 0) ? "" : ", ",
 										 (strcmp(pszZIPRight, "00000") == 0) ? "" : pszZIPRight);
+	
+	// consider the longer of the two to be better-- (for joined results)
+//	gchar* pszCSZBetter = (strlen(pszCSZLeft) > strlen(pszCSZRight)) ? pszCSZLeft : pszCSZRight;
 
 	if(nRoadNumber == ROADSEARCH_NUMBER_NONE) {
 		// Right in the center
@@ -408,34 +550,37 @@
 
 		if(nAddressRightStart == 0 && nAddressRightEnd == 0) {
 			// show no numbers if they're both 0
-			g_snprintf(azBuffer, BUFFER_SIZE, "%s %s\n%s", pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZRight);
+			g_snprintf(azBuffer, BUFFER_SIZE, "%s %s\n%s",
+					   pszRoadName,
+					   map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG),
+					   pszCSZRight);
 		}
 		else if(nAddressRightStart < nAddressRightEnd) {
-			g_snprintf(azBuffer, BUFFER_SIZE, "(%d-%d) %s %s\n%s", nAddressRightStart, nAddressRightEnd, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZRight);
+			g_snprintf(azBuffer, BUFFER_SIZE, "%d-%d %s %s\n%s", nAddressRightStart, nAddressRightEnd, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZRight);
 		}
 		else {
 			// reverse start/end for the dear user :)
-			g_snprintf(azBuffer, BUFFER_SIZE, "(%d-%d) %s %s\n%s", nAddressRightEnd, nAddressRightStart, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZRight);
+			g_snprintf(azBuffer, BUFFER_SIZE, "%d-%d %s %s\n%s", nAddressRightEnd, nAddressRightStart, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZRight);
 		}
 		searchwindow_add_result(nRoadID, azBuffer, &ptAddress);
 
 		// do left side, same as right side (see above)
 		if(nAddressLeftStart == 0 && nAddressLeftEnd == 0) {
-			g_snprintf(azBuffer, BUFFER_SIZE, "%s %s\n%s", pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZLeft);
+			g_snprintf(azBuffer, BUFFER_SIZE, "%s %s\n%s", pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZLeft);
 		}
 		else if(nAddressLeftStart < nAddressLeftEnd) {
-			g_snprintf(azBuffer, BUFFER_SIZE, "(%d-%d) %s %s\n%s", nAddressLeftStart, nAddressLeftEnd, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZLeft);
+			g_snprintf(azBuffer, BUFFER_SIZE, "%d-%d %s %s\n%s", nAddressLeftStart, nAddressLeftEnd, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZLeft);
 		}
 		else {
 			// swap address to keep smaller number to the left
-			g_snprintf(azBuffer, BUFFER_SIZE, "(%d-%d) %s %s\n%s", nAddressLeftEnd, nAddressLeftStart, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZLeft);
+			g_snprintf(azBuffer, BUFFER_SIZE, "%d-%d %s %s\n%s", nAddressLeftEnd, nAddressLeftStart, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZLeft);
 		}
 		searchwindow_add_result(nRoadID, azBuffer, &ptAddress);		
 	}
 	else {	// else the search had a road number
 		// NOTE: we have to filter out results like "97-157" when searching for "124" because it's
 		// on the wrong side of the road.
-//g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG));
+//g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG));
 
 		// check left side of street
 		// NOTE: if search was for an even, at least one (and hopefully both) of the range should be even
@@ -454,7 +599,7 @@
 					gfloat fPercent = (gfloat)(nRoadNumber - nAddressLeftStart) / (gfloat)nRange;
 					pointstring_walk_percentage(pPointString, fPercent, ROADSIDE_LEFT, &ptAddress);
 				}
-				g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s\n%s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZLeft);
+				g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s\n%s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZLeft);
 				searchwindow_add_result(nRoadID, azBuffer, &ptAddress);				
 			}
 			else if(nRoadNumber >= nAddressLeftEnd && nRoadNumber <= nAddressLeftStart) {
@@ -470,7 +615,7 @@
 					// flip percent (23 becomes 77, etc.)
 					pointstring_walk_percentage(pPointString, (100.0 - fPercent), ROADSIDE_RIGHT, &ptAddress);
 				}
-				g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s\n%s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZLeft);
+				g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s\n%s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZLeft);
 				searchwindow_add_result(nRoadID, azBuffer, &ptAddress);
 			}
 		}
@@ -491,7 +636,7 @@
 					gfloat fPercent = (gfloat)(nRoadNumber - nAddressRightStart) / (gfloat)nRange;
 					pointstring_walk_percentage(pPointString, fPercent, ROADSIDE_RIGHT, &ptAddress);
 				}
-				g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s\n%s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZRight);
+				g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s\n%s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZRight);
 				searchwindow_add_result(nRoadID, azBuffer, &ptAddress);				
 			}
 			else if(nRoadNumber >= nAddressRightEnd && nRoadNumber <= nAddressRightStart) {
@@ -507,7 +652,7 @@
 					// flip percent (23 becomes 77, etc.)
 					pointstring_walk_percentage(pPointString, (100.0 - fPercent), ROADSIDE_LEFT, &ptAddress);
 				}
-				g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s\n%s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_TYPE_LONG), pszCSZRight);
+				g_snprintf(azBuffer, BUFFER_SIZE, "%d %s %s\n%s", nRoadNumber, pszRoadName, map_road_suffix_itoa(nRoadSuffixID, SUFFIX_LENGTH_LONG), pszCSZRight);
 				searchwindow_add_result(nRoadID, azBuffer, &ptAddress);				
 			}
 		}

Index: searchwindow.c
===================================================================
RCS file: /cvs/cairo/roadster/src/searchwindow.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- searchwindow.c	23 Feb 2005 17:22:07 -0000	1.5
+++ searchwindow.c	28 Feb 2005 03:25:23 -0000	1.6
@@ -141,7 +141,7 @@
 	}
 
 	// create results tree view
-	g_SearchWindow.m_pResultsListStore = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_FLOAT, G_TYPE_FLOAT);
+	g_SearchWindow.m_pResultsListStore = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
 	gtk_tree_view_set_model(g_SearchWindow.m_pResultsTreeView, GTK_TREE_MODEL(g_SearchWindow.m_pResultsListStore));
 
 	GtkCellRenderer* pCellRenderer;
@@ -161,7 +161,7 @@
 {
 	gint nID;
 	GtkTreeIter iter;
-	
+
 	if(gtk_combo_box_get_active_iter(g_SearchWindow.m_pLocationSetComboBox, &iter)) {
 		gtk_tree_model_get(GTK_TREE_MODEL(g_SearchWindow.m_pLocationSetComboBoxModel), &iter,
 			LOCATIONSETLIST_COLUMN_ID, &nID,
@@ -257,14 +257,16 @@
 	GtkTreeModel* pModel = GTK_TREE_MODEL(g_SearchWindow.m_pResultsListStore);
 	if(gtk_tree_selection_get_selected(pSelection, &pModel, &iter)) {
 //		gchar* pszText;
-		gfloat fLatitude;
-		gfloat fLongitude;
+		mappoint_t pt;
 		gtk_tree_model_get(GTK_TREE_MODEL(g_SearchWindow.m_pResultsListStore), &iter,
 //			RESULTLIST_COLUMN_NAME, &pszText,
-			RESULTLIST_LATITUDE, &fLatitude,
-			RESULTLIST_LONGITUDE, &fLongitude,
+			RESULTLIST_LATITUDE, &pt.m_fLatitude,
+			RESULTLIST_LONGITUDE, &pt.m_fLongitude,
 			-1);
-		map_center_on_worldpoint(fLatitude, fLongitude);
+
+		g_print("%f,%f\n", pt.m_fLatitude, pt.m_fLongitude);
+
+		map_set_centerpoint(&pt);
 		mainwindow_draw_map();
 		mainwindow_statusbar_update_position();
 //		g_print("yay: %s\n", pszText);




More information about the cairo-commit mailing list