private void doGpsCommand(string command)
        {
            allButtonsDisable();
            progressBar.Visible = true;
            setMessageText("IP: ...command " + command + "\n\n");
            trkptCountLabel.Text = "";

            //if("startRealtime".Equals(command))
            if(!Project.drawVehicles || !Project.drawWaypoints)
            {
                m_pictureManager.LayersManager.ShowVehicles = true;
                Project.drawVehicles = true;
                m_pictureManager.LayersManager.ShowWaypoints = true;
                Project.drawWaypoints = true;
            }

            try
            {
                m_gps = AllGpsDevices.MakeGpsDriver();
                if(m_gps != null)		// null should never happen here anyway
                {
                    if(m_waypoints == null)
                    {
                        m_waypoints = WaypointsCache.WaypointsAll;
                    }

                    if(m_routes == null)
                    {
                        m_routes = WaypointsCache.RoutesAll;
                    }

                    ThreadGpsControl gt = new ThreadGpsControl(m_gps, m_insertWaypoint, m_waypoints, m_routes);

                    gt.MessageCallback  += new GpsMessageHandler( messageCallback );
                    gt.ProgressCallback += new GpsProgressHandler( progressCallback );
                    gt.CompleteCallback += new GpsCompleteHandler( completeCallback );
                    gt.RealTimeCallback += new GpsRealTimeHandler( realtimeCallback );
                    gt.RealTimeCallback += new GpsRealTimeHandler( vehicleMovedCallback );
                    gt.command = command;

                    m_commandThread = new Thread( new System.Threading.ThreadStart(gt.communicate ));
                    m_commandThread.Name = "GpsController";
                    m_commandThread.IsBackground = true;
                    // see Entry.cs for how the current culture is set:
                    m_commandThread.CurrentCulture = Thread.CurrentThread.CurrentCulture; //new CultureInfo("en-US", false);
                    m_commandThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture; //new CultureInfo("en-US", false);
                    m_commandThread.Priority = ThreadPriority.Highest; //.AboveNormal;
                    m_started = DateTime.Now;
                    m_commandThread.Start();
                    Thread.Sleep(0); //Give thread time to start. By documentation, 0 should work, but it does not!
                }
            }
            catch (Exception exc)
            {
                switch(ThreadGpsControl.m_errorAdviceTry++)
                {
                    case 0:
                        appendMessageText("\n" + exc.Message + "  --  make sure your GPS communication protocol is set to " + AllGpsDevices.AllMakesNames[Project.gpsMakeIndex] + ".");
                        break;
                    default:
                        appendMessageText("\n" + exc.Message);
                        break;
                }
            }
        }
        // we want this one to run in the dialog's thread.
        private void _completeCallback()
        {
            //LibSys.StatusBar.Trace("_completeCallback()");

            //string deviceType = m_gps.ToString();
            m_commandThread = null;
            m_gps = null;
            cleanGpsVehicle();

            Project.inhibitRefresh = false;

            TimeSpan duration = DateTime.Now - m_started;
            string sDuration = duration.ToString();
            sDuration = sDuration.Substring(0, Math.Min(sDuration.IndexOf(".")+3, sDuration.Length));
            appendMessageText("\n\n" + message + "   (" + sDuration + ")");
            //if(!closing)
            {
                allButtonsEnable();
                rtStopButton.Visible = false;
                rtStartButton.Visible = false;
            }

            //LibSys.StatusBar.Trace("completeCallback: 1");
            if((closing || isSuccess) && doRefresh && m_pictureManager != null)
            {
                //LibSys.StatusBar.Trace("completeCallback: 2");
                Cursor.Current = Cursors.WaitCursor;
                Project.drawWaypoints = true;	// force draw - it is frustrating to not see freshly imported track on the map...
                m_pictureManager.LayersManager.ShowWaypoints = true;
                LayerWaypoints.This.init();

                //LibSys.StatusBar.Trace("completeCallback: 3");
                if(Project.gpsZoomIntoTracks && mayZoom)
                {
                    try
                    {
                        m_cameraManager.zoomToCorners();
                    }
                    catch
                    {
                    }
                }

                //LibSys.StatusBar.Trace("completeCallback: 4");
                if(doRefreshFull)
                {
                    m_cameraManager.ProcessCameraMove();
                }
                else
                {
                    m_pictureManager.Refresh();
                }
                Cursor.Current = Cursors.Default;
                doRefresh = doRefreshFull = false;
            }
            mayZoom = false;

            //			this.setupTabPage.Enabled = true;
            //			this.dataTabPage.Enabled = true;
            //			this.optionsTabPage.Enabled = true;

            rtStartButton.Visible = true;
            closeButton.Enabled = true;
            closing = false;

            /*
            if(closing)
            {
                //LibSys.StatusBar.Trace("_completeCallback - in closing");
                closing = false;
                this.closeButton.Enabled = false;
                //this.Close();		// causes interrupted Main after several cycles
            }
            else
            {
                rtStartButton.Visible = true;
            }
            */
            //LibSys.StatusBar.Trace("completeCallback: end");
        }