GPS4Palm

Source Code Documentation


NavigationForm.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * $RCSfile: NavigationForm_8c-source.html,v $
00004  *
00005  * GPS4Palm Navigation Form
00006  *
00007  * This program is Copyright (C) 03/2003 Matthias Prinke
00008  * <matthias.prinke@surfeu.de> and covered by GNU's GPL.
00009  * In particular, this program is free software and comes WITHOUT
00010  * ANY WARRANTY.
00011  *
00012  * $Author: mp $
00013  *
00014  * $Date: 2007-10-08 20:40:34 $
00015  *
00016  * $Revision: 1.7.2.1 $
00017  *
00018  * $Log: NavigationForm_8c-source.html,v $
00018  * Revision 1.7.2.1  2007-10-08 20:40:34  mp
00018  * updated for gps4palm V0.9.5 beta
00018  *
00019  * Revision 1.26  2005-05-06 13:38:34  mp
00020  * removed assignment to gHdFtrSet
00021  *
00022  * Revision 1.25  2005/04/24 14:06:43  mp
00023  * added High-Density Display support
00024  *
00025  * Revision 1.24  2005/04/02 10:09:43  mp
00026  * modified Position2Clipboard() and Position2Geodb() to return 'handled'
00027  *
00028  * Revision 1.23  2005/04/02 07:26:59  mp
00029  * added PosgeodbMenu event handling
00030  *
00031  * Revision 1.22  2005/03/25 13:45:11  mp
00032  * added PosclipMenu event handling
00033  *
00034  * Revision 1.21  2005/01/23 18:40:10  mp
00035  * added PortsMenu event handling
00036  *
00037  * Revision 1.20  2004/12/10 20:03:04  mp
00038  * added waypoint selection with up/down keys,
00039  * replaced DmGet1Resource by DmGetResource
00040  *
00041  * Revision 1.19  2004/12/09 17:33:37  mp
00042  * replaced strings by string resources
00043  *
00044  * Revision 1.18  2004/12/08 20:49:22  mp
00045  * added track logging
00046  *
00047  * Revision 1.17  2004/11/30 20:44:06  mp
00048  * added TrackMenu event handling
00049  *
00050  * Revision 1.16  2004/11/27 10:20:31  mp
00051  * replaced error handling code by calling Die()
00052  *
00053  * Revision 1.15  2004/11/26 20:09:40  mp
00054  * added error handling for WinCreateOffscreenWindow(), fixed comments
00055  *
00056  * Revision 1.14  2004/11/25 20:06:20  mp
00057  * added NotifyApproach()
00058  *
00059  * Revision 1.13  2004/11/24 21:15:20  mp
00060  * moved static function declarations from header to implementation file
00061  *
00062  * Revision 1.12  2004/11/23 17:48:33  mp
00063  * removed unused variables
00064  *
00065  * Revision 1.11  2004/11/20 15:51:25  mp
00066  * added display_wpt(), NavigationPrevWptButton/NavigationNextWptButton
00067  * handling, and automatic route waypoint selection
00068  *
00069  * Revision 1.10  2004/11/11 21:36:25  mp
00070  * implemented active Route Information
00071  *
00072  * Revision 1.9  2004/04/29 19:02:05  mp
00073  * added RouteForm, modified for doxygen
00074  *
00075  * Revision 1.8  2004/03/16 20:00:42  mp
00076  * Fixed waypoint ID display. Added deletion of window handle upon
00077  * frmCloseEvent. Modified bearing pointer.
00078  *
00079  * Revision 1.7  2004/03/13 14:59:28  mp
00080  * added/modified data display
00081  *
00082  * Revision 1.6  2004/03/11 21:40:06  mp
00083  * added data display and DTK pointer
00084  *
00085  * Revision 1.5  2004/02/28 17:21:43  mp
00086  * added menuEvent WaypointMenu
00087  *
00088  * Revision 1.4  2003/11/20 20:45:01  mp
00089  * added status redraw on frmOpenEvent
00090  *
00091  * Revision 1.3  2003/11/18 20:55:40  mp
00092  * added MiscOptsMenu, added current Form to Application Preferences
00093  *
00094  * Revision 1.2  2003/10/20 17:25:50  mp
00095  * added field deallocation on frmCloseEvent
00096  *
00097  * Revision 1.1.1.1  2003/07/14 18:59:29  mp
00098  * Imported GPS4Palm to CVS revision control.
00099  *
00100  *
00101  ****************************************************************************/
00102 #include <PalmOS.h>
00103 #include <PalmCompatibility.h>
00104 #include "MathLib.h"
00105 #include "ResourceDefines.h"
00106 #include "Serial.h"
00107 #include "Sinetab.h"
00108 #include "NavigationForm.h"
00109 #include "GPS.h"
00110 #include "HandleMessage.h"
00111 #include "Utils.h"
00112 #include "Data.h"
00113 #include "fp.h"
00114 #include "geo.h"
00115 #include "Clip.h"
00116 #include "common.h"
00117 
00118 /* Global Variables */
00119 
00120 /** Navigation window handle for save-behind (Compass). */
00121 WinHandle               gNavigationH;
00122 
00123 extern PrefsType        gPrefs;                 /* Preferences data structure */
00124 extern DmOpenRef        gWaypointDB;            /* Data Base reference */
00125 extern GPSType          gGPSData;               /* GPS Data */
00126 extern Boolean          gHdFtrSet;              /* High-Density Display */
00127 
00128 /** Constants for distance unit conversions and display */
00129 extern const struct {
00130   char          *unit;
00131   double        conv;
00132 } dst_c[];
00133 
00134 /** Constants for speed unit conversions and display */
00135 extern const struct {
00136   char          *unit;
00137   double        conv;
00138 } spd_c[];
00139 
00140 #ifndef WinDrawPixel
00141 #define WinDrawPixel(x,y) WinDrawLine((x),(y),(x),(y))
00142 #endif
00143 
00144 /* Static Functions */
00145 static void display_sog(void)                                   NAV_SECTION;
00146 static void display_cmg(void)                                   NAV_SECTION;
00147 static void display_dst(double dist)                            NAV_SECTION;
00148 static void display_trn(double turn)                            NAV_SECTION;
00149 static void display_vmg(double vmg)                             NAV_SECTION;
00150 static void display_wpt(double *lat, double *lon)               NAV_SECTION;
00151 static void hours_to_hms(double hours, UInt16 *hh, UInt16 *mm,
00152   UInt16 *ss)                                                   NAV_SECTION;
00153 static void NavigationFormInit(void)                            NAV_SECTION;
00154 static void DrawNavigation(void)                                NAV_SECTION;
00155 
00156 
00157 /*****************************************************************************
00158  * FUNCTION:    WayptEditFormInit
00159  *
00160  * DESCRIPTION: Navigation Form Init Function
00161  *
00162  * GLOBALS:     gFormOpened     -- indicates if a form (using GPS data)
00163  *                                 has been opened
00164  ****************************************************************************/
00165 static 
00166 void NavigationFormInit(void)
00167 {  
00168   gFormOpened = true;
00169 }
00170 
00171 
00172 /*****************************************************************************
00173  * FUNCTION:    hours_to_hms
00174  *
00175  * DESCRIPTION: Convert fractional hours to integer hours, minutes and seconds 
00176  *
00177  * PARAMETERS:  hours           -- decimal hours
00178  *              hh              -- integer hours   (returned by ref)
00179  *              mm              -- integer minutes (returned by ref)
00180  *              ss              -- integer seconds (returned by ref)
00181  *
00182  * RETURNED:    %
00183  ****************************************************************************/
00184 static
00185 void hours_to_hms(double hours, UInt16 *hh, UInt16 *mm, UInt16 *ss)
00186 {
00187   double        sec;            /* seconds */
00188   double        frac;           /* fractional part */
00189   double        ipart;          /* integer part */
00190   
00191   /* hours */
00192   frac = modf(hours, &ipart) * 60.0;
00193   *hh = (UInt16)ipart;
00194   
00195   /* minutes */
00196   sec = modf(frac, &ipart) * 60.0;
00197   *mm = (UInt16)ipart;
00198   
00199   /* seconds */
00200   *ss = (UInt16)sec;
00201 }
00202 
00203 
00204 /*****************************************************************************
00205  * FUNCTION:    DrawNavigation
00206  *
00207  * DESCRIPTION: Draw Navigation Form ("Compass") and save it to off-screen
00208  *              window.
00209  *
00210  * GLOBALS:     gNavigationH    -- Off-screen window handle
00211  *
00212  * PARAMETERS:  -
00213  *
00214  * RETURNED:    -
00215  ****************************************************************************/
00216 static
00217 void DrawNavigation(void)
00218 {
00219   UInt16        x;              /* x-coordinate */
00220   UInt16        y;              /* y-coordinate */
00221   PointType     p1;             /* point 1 */
00222   PointType     p2;             /* point 2 */
00223   UInt16        r;              /* radius */
00224   UInt16        phi;            /* angle */
00225   UInt16        err;            /* error code */
00226   RectangleType rect;           /* rectangle structure */
00227 
00228   if (gHdFtrSet) {
00229     WinPushDrawState();
00230     WinSetCoordinateSystem(kCoordinatesNative);
00231   } 
00232 
00233   /* Outer circle */
00234   r    = (gHdFtrSet) ? WinScaleCoord(NAV_R2, false) : NAV_R2;
00235   p1.x = (gHdFtrSet) ? WinScaleCoord(NAV_X, false) : NAV_X;
00236   p1.y = (gHdFtrSet) ? WinScaleCoord(NAV_Y, false) : NAV_Y;
00237   for (phi=0; phi<360; phi++) {
00238     /* Sinus/Cosinus functions using table lookup */
00239     x = p1.x + r * icos(phi) / 32768;
00240     y = p1.y - r * isin(phi) / 32768;
00241    
00242     /*
00243      * Note:
00244      * For High-Density, a step size of one degree does not provide
00245      * enough points for a continuous circle. Connecting the points
00246      * with a line seems to work good enough. (and is still fast) 
00247      */
00248     if (phi == 0) {
00249       WinDrawPixel(x, y);
00250     } else {
00251       WinDrawLine(x, y, p2.x, p2.y);
00252     }
00253     p2.x = x;
00254     p2.y = y;
00255   }
00256 
00257   /* Inner circle */
00258   r = (gHdFtrSet) ? WinScaleCoord(NAV_R1, false) : NAV_R1;
00259   for (phi=0; phi<360; phi++) {
00260     /* Sinus/Cosinus functions using table lookup */
00261     x = p1.x + r * icos(phi) / 32768;
00262     y = p1.y - r * isin(phi) / 32768;
00263     
00264     WinDrawPixel(x, y);
00265   }
00266   
00267   /* Center */
00268   p1.x = NAV_X-2;
00269   p1.y = NAV_Y;
00270   p2.x = NAV_X+2;
00271   p2.y = NAV_Y;
00272   if (gHdFtrSet) {
00273     WinScalePoint(&p1, false);
00274     WinScalePoint(&p2, false);
00275   }
00276   WinDrawLine(p1.x, p1.y, p2.x, p2.y);
00277 
00278   p1.x = NAV_X;
00279   p1.y = NAV_Y-2;
00280   p2.x = NAV_X;
00281   p2.y = NAV_Y+2;
00282   if (gHdFtrSet) {
00283     WinScalePoint(&p1, false);
00284     WinScalePoint(&p2, false);
00285   }
00286   WinDrawLine(p1.x, p1.y, p2.x, p2.y);
00287 
00288   p1.x = 2 * NAV_R2;
00289   p1.y = 2 * NAV_R2;
00290   if (gHdFtrSet) WinScalePoint(&p1, false);
00291   gNavigationH = WinCreateOffscreenWindow(p1.x, p1.y, nativeFormat, &err);
00292   
00293   if (!gNavigationH) {
00294     /* error handling */
00295     if (gHdFtrSet) {
00296       WinPopDrawState();
00297     } 
00298     Die("Cannot create OffscreenWindow in NavigationForm!");
00299     return;
00300   }
00301   
00302   p1.x = NAV_X-NAV_R2;
00303   p1.y = NAV_Y-NAV_R2;
00304   if (gHdFtrSet) WinScalePoint(&p1, false);
00305   x = (gHdFtrSet) ? WinScaleCoord(2 * NAV_R2, false) : 2 * NAV_R2;
00306   y = (gHdFtrSet) ? WinScaleCoord(2 * NAV_R2, false) : 2 * NAV_R2;
00307   RctSetRectangle(&rect, p1.x, p1.y, x /* w */, y /* h */);
00308 
00309   WinCopyRectangle(     NULL, /* WinHandle srcWin, draw window */
00310                         gNavigationH, /* WinHandle dstWin, draw window */
00311                         &rect, /* RectangleType *srcRect */
00312                         0, /* Coord destX */
00313                         0, /* Coord destY */
00314                         winPaint /* WinDrawOperation mode */);
00315 
00316   if (gHdFtrSet) {
00317     WinPopDrawState();
00318   } 
00319 }
00320 
00321 
00322 /*****************************************************************************
00323  * FUNCTION:    display_sog
00324  *
00325  * DESCRIPTION: Displays Speed Over Ground
00326  *
00327  * GLOBALS:     gPrefs          -- application preferences
00328  *              gGPSData        -- GPS data
00329  *
00330  * PARAMETERS:  %
00331  *
00332  * RETURNED:    %
00333  ****************************************************************************/
00334 static
00335 void display_sog(void)
00336 {
00337   double        tmp;
00338   Char          sog_str[12];
00339 
00340   /* convert to preferred unit */
00341   tmp = gGPSData.sog * spd_c[gPrefs.units.spd_unit].conv;
00342 
00343   /* convert to string, adapt number of decimals to value */
00344   if (tmp < 100.0) {
00345     format_number(tmp, 2, sog_str);
00346   } else if (tmp < 1000.0) {
00347     format_number(tmp, 1, sog_str);
00348   } else {
00349     format_number(tmp, 0, sog_str);
00350   }
00351   
00352   /* append unit to string */
00353   StrCat(sog_str, " ");
00354   StrCat(sog_str, spd_c[gPrefs.units.spd_unit].unit);
00355 
00356   /* display string */
00357   SetFieldText(NavigationSogField, sog_str, false, true);
00358 }
00359 
00360 
00361 /*****************************************************************************
00362  * FUNCTION:    display_cmg
00363  *
00364  * DESCRIPTION: Displays Course Made Good (= Course Over Ground)
00365  *
00366  * GLOBALS:     gGPSData        -- GPS data
00367  *
00368  * PARAMETERS:  %
00369  *
00370  * RETURNED:    %
00371  ****************************************************************************/
00372 static
00373 void display_cmg(void)
00374 {
00375   Char          cmg_str[12];
00376   
00377   /* convert to string */
00378   format_number(gGPSData.cmg, 1, cmg_str);
00379 
00380   /* append unit to string */
00381   StrCat(cmg_str, "°");
00382 
00383   /* display string */
00384   SetFieldText(NavigationCmgField, cmg_str, false, true);
00385 }
00386 
00387 
00388 /*****************************************************************************
00389  * FUNCTION:    display_dst
00390  *
00391  * DESCRIPTION: Displays Distance To Waypoint
00392  *
00393  * GLOBALS:     gPrefs          -- application preferences
00394  *
00395  * PARAMETERS:  dist            -- distance in km
00396  *
00397  * RETURNED:    %
00398  ****************************************************************************/
00399 static
00400 void display_dst(double dist)
00401 {
00402   Char  dist_str[8];
00403 
00404   /* convert to preferred unit */
00405   dist *= dst_c[gPrefs.units.dst_unit].conv;
00406 
00407   /* adapt number of decimals to value */
00408   if (dist < 2.0) {
00409     format_number(dist, 3, dist_str);
00410   } else if (dist < 10.0) {
00411     format_number(dist, 2, dist_str);
00412   } else if (dist < 100.0) {
00413     format_number(dist, 1, dist_str);
00414   } else {
00415     format_number(dist, 0, dist_str);
00416   }
00417         
00418   /* append unit to string */
00419   StrCat(dist_str, " ");
00420   StrCat(dist_str, dst_c[gPrefs.units.dst_unit].unit);
00421 
00422   /* display DST string */
00423   SetFieldText(NavigationDstField, dist_str, false, true);
00424 }
00425 
00426 
00427 /*****************************************************************************
00428  * FUNCTION:    display_trn
00429  *
00430  * DESCRIPTION: Displays Turn Angle
00431  *
00432  * PARAMETERS:  turn            -- turn in degrees, (pos: right/neg: left)
00433  *
00434  * RETURNED:    %
00435  ****************************************************************************/
00436 static
00437 void display_trn(double turn)
00438 {
00439   Char  trn_str[8];
00440   
00441   if (turn < 0.0) {
00442     format_number(-turn, 1, trn_str);
00443     StrCat(trn_str, "°L");
00444   } else {
00445     format_number(turn, 1, trn_str);
00446     StrCat(trn_str, "°R");
00447   }
00448   SetFieldText(NavigationTrnField, trn_str, false, true);
00449 }
00450 
00451 
00452 /*****************************************************************************
00453  * FUNCTION:    display_vmg
00454  *
00455  * DESCRIPTION: Displays Velocity Made Good
00456  *
00457  * GLOBALS:     gPrefs          -- application preferences
00458  *
00459  * PARAMETERS:  vmg             -- velocity made good (in kts)
00460  *
00461  * RETURNED:    %
00462  ****************************************************************************/
00463 static
00464 void display_vmg(double vmg)
00465 {
00466   Char          vmg_str[10];
00467   double        tmp;
00468 
00469   /* convert to preferred unit */
00470   tmp = vmg * spd_c[gPrefs.units.spd_unit].conv;
00471   
00472   /* convert to string, adapt number of decimals to value */
00473   if (tmp < 100.0) {
00474     format_number(tmp, 2, vmg_str);
00475   } else if (tmp < 1000.0) {
00476     format_number(tmp, 1, vmg_str);
00477   } else {
00478     format_number(tmp, 0, vmg_str);
00479   }
00480   
00481   /* append unit to string */
00482   StrCat(vmg_str, " ");
00483   StrCat(vmg_str, spd_c[gPrefs.units.spd_unit].unit);
00484 
00485   /* display string */
00486   SetFieldText(NavigationVmgField, vmg_str, false, true);         
00487 }
00488 
00489 
00490 /****************************************************************************/
00491 /**
00492  * \brief       Display waypoint ID and update waypoint position
00493  *
00494  * \param       lat             latitude returned by reference
00495  * \param       lon             longitude returned by reference
00496  *
00497  ****************************************************************************/
00498 static
00499 void display_wpt(double *lat, double *lon)
00500 {
00501   packed_waypoint_t     *packed_waypoint;       /* packed waypoint ptr */
00502   waypoint_t            waypoint;               /* unpacked waypoint */
00503   MemHandle             waypointDBEntry;        /* waypoint record handle */
00504   UInt16                rec;                    /* record index */
00505   Err                   err;                    /* error code */
00506   Char                  tmp[7];                 /* waypoint identifier */ 
00507   MemHandle             strH;                   /* string handle */
00508   MemPtr                strP;                   /* string ptr */
00509   
00510   /* default "Waypoint Identifier" */ 
00511   /* get string from resource */
00512   strH = DmGetResource(strRsc, NoWptStr);
00513 
00514   if (strH != NULL) {
00515     /* string handle valid, lock it */
00516     strP = MemHandleLock(strH);
00517   
00518     /* copy string */
00519     StrCopy(tmp, strP);
00520 
00521     /* unlock string handle */
00522     MemHandleUnlock(strH);
00523 
00524     /* release string resource */
00525     DmReleaseResource(strH);
00526   }
00527 
00528   /* display active waypoint */
00529   err = DmFindRecordByID(gWaypointDB, gPrefs.act_wpt.waypointID,
00530     &rec);
00531         
00532   if (!err) {
00533     /* active waypoint found */
00534     waypointDBEntry = DmQueryRecord(gWaypointDB, rec);
00535     packed_waypoint =
00536       (packed_waypoint_t *)MemHandleLock(waypointDBEntry);
00537     UnpackWaypoint(&waypoint, packed_waypoint);
00538     MemSet((Char *)tmp, 7, 0);
00539     StrNCopy(tmp, (Char *)&waypoint.ident, 6);
00540     *lat = semi2deg(waypoint.posn.lat);
00541     *lon = semi2deg(waypoint.posn.lon);
00542     MemHandleUnlock(waypointDBEntry);
00543   }
00544 
00545   CtlSetLabel((ControlPtr)GetObjectFromActiveForm(NavigationWptIDSel), tmp);
00546 }
00547 
00548 
00549 /****************************************************************************/
00550 /**
00551  * \brief       Navigation Form event handler
00552  *
00553  * \param       eventP          pointer to event structure
00554  *
00555  * \return      Status flag: event handled
00556  ****************************************************************************/
00557 Boolean NavigationFormHandleEvent(EventPtr eventP)
00558 {
00559   Boolean               handled;                /* flag: event handled */
00560   Boolean               updatedDisplay;         /* flag: updated display */
00561   Err                   err;                    /* error code */
00562   UInt16                rec;                    /* record index */
00563   packed_waypoint_t     *packed_waypoint;       /* packed waypoint ptr */
00564   waypoint_t            waypoint;               /* unpacked waypoint */
00565   MemHandle             waypointDBEntry;        /* waypoint record handle */
00566   route_t               *route;                 /* route */
00567   MemHandle             routeDBEntry;           /* route record handle */
00568   static Char           tmp[10];                /* temp. string buffer */
00569   static double         wpt_lat;                /* lat of waypoint */
00570   static double         wpt_lon;                /* lon of waypoint */
00571   double                dist;                   /* distance to waypoint */
00572   double                brg;                    /* bearing */
00573   double                turn;                   /* turn */
00574   double                vmg;                    /* velocity made good */
00575   double                ttg;                    /* time to go in dec. hours */
00576   Int32                 trk;                    /* track as integer */
00577   static Int32          otrk;                   /* old track */
00578   Int32                 x, y;                   /* screen coordinates */
00579   Int32                 r;                      /* radius for track pointer */
00580   PointType             p1;                     /* point for track pointer */
00581   MemHandle             strH;                   /* string handle */
00582   MemPtr                strP;                   /* string ptr */
00583 
00584   handled = false;
00585 
00586   switch (eventP->eType)
00587   {
00588     case frmOpenEvent:
00589       gPrefs.form = NavigationForm;
00590 
00591       NavigationFormInit();
00592       FrmDrawForm(FrmGetActiveForm());
00593       DrawNavigation();
00594       UpdateStatus(STAT_REDRAW);
00595 
00596       if (gPrefs.act_rte.valid || gPrefs.act_wpt.valid) {
00597         /* display waypoint and get position */
00598         display_wpt(&wpt_lat, &wpt_lon);
00599       }
00600 
00601       /* default "Route Identifier" */ 
00602       /* get string from resource */
00603       strH = DmGetResource(strRsc, NoRteStr);
00604 
00605       if (strH != NULL) {
00606         /* string handle valid, lock it */
00607         strP = MemHandleLock(strH);
00608 
00609         /* copy string */
00610         StrCopy(tmp, strP);
00611 
00612         /* unlock string handle */
00613         MemHandleUnlock(strH);
00614 
00615         /* release string resource */
00616         DmReleaseResource(strH);
00617       }
00618       
00619       if (gPrefs.act_rte.valid) {
00620         /* display active route */
00621         err = DmFindRecordByID(gRouteDB, gPrefs.act_rte.routeID,
00622           &rec);
00623         
00624         if (!err) {
00625           /* active route found */
00626           routeDBEntry = DmQueryRecord(gRouteDB, rec);
00627           route = (route_t *)MemHandleLock(routeDBEntry);
00628           MemSet((Char *)tmp, 9, 0);
00629 
00630           /* get string from resource */
00631           strH = DmGetResource(strRsc, RteNoStr);
00632 
00633           if (strH != NULL) {
00634             /* string handle valid, lock it */
00635             strP = MemHandleLock(strH);
00636             
00637             StrPrintF(tmp, "%s%-3d", strP, route->nmbr);
00638 
00639             /* unlock string handle */
00640             MemHandleUnlock(strH);
00641 
00642             /* release string resource */
00643             DmReleaseResource(strH);
00644           }               
00645           MemHandleUnlock(routeDBEntry);
00646         }
00647       }
00648       CtlSetLabel((ControlPtr)GetObjectFromActiveForm(NavigationRteIDSel), tmp);
00649      
00650       handled = true;
00651       break;
00652 
00653     case menuEvent:
00654       switch (eventP->data.menu.itemID) {
00655 
00656         case PositionMenu:
00657           FrmGotoForm(GPSMainForm);
00658           handled = true;
00659           break;
00660 
00661         case SkyviewMenu:
00662           FrmGotoForm(SkyviewForm);
00663           handled = true;
00664           break;
00665 
00666         case MapMenu:
00667           FrmGotoForm(MapForm);
00668           handled = true;
00669           break;
00670 
00671         case MiscOptsMenu:
00672           FrmGotoForm(MiscOptsForm);
00673           handled = true;
00674           break;
00675 
00676         case MapOptsMenu:
00677           FrmGotoForm(MapOptsForm);
00678           handled = true;
00679           break;
00680 
00681         case PortsMenu:
00682           if (gNewSerialManager) {
00683             FrmGotoForm(GPSPortForm);
00684           }
00685           handled = true;
00686           break;
00687             
00688         case WaypointMenu:
00689           FrmGotoForm(WaypointForm);
00690           handled = true;
00691           break;
00692 
00693         case RouteMenu:
00694           FrmGotoForm(RouteForm);
00695           handled = true;
00696           break;
00697 
00698         case TrackMenu:
00699           FrmGotoForm(TrackForm);
00700           handled = true;
00701           break;
00702                
00703         case PosclipMenu:
00704           handled = Position2Clipboard(gGPSData, gPrefs.units);
00705           break;
00706 
00707         case PosgeodbMenu:
00708           handled = Position2Geodb(gGPSData);
00709           break;
00710 
00711         case AboutMenu:
00712           FrmGotoForm(AboutForm);
00713           handled = true;
00714           break;
00715               
00716 #ifdef DEBUG_FORM
00717         case DebugMenu:
00718           FrmGotoForm(DebugForm);
00719           handled = true;
00720           break;
00721 #endif
00722       }
00723       break;
00724     
00725     case ctlSelectEvent:
00726     case keyDownEvent:
00727       
00728       /* Previous Waypoint */
00729       if ((eventP->eType == ctlSelectEvent &&
00730            eventP->data.ctlSelect.controlID == NavigationPrevWptButton) ||
00731           (eventP->eType == keyDownEvent &&
00732            eventP->data.keyDown.chr == pageUpChr)) {
00733 
00734         if (gPrefs.act_rte.valid) {
00735           if (gPrefs.act_rte.wpt_index == 0)
00736             break;
00737 
00738           /* select previous waypoint */
00739           gPrefs.act_rte.wpt_index--;
00740 
00741           /* get active route */
00742           err = DmFindRecordByID(gRouteDB, gPrefs.act_rte.routeID,
00743             &rec);
00744 
00745           if (!err) {
00746             /* active route found */
00747             routeDBEntry = DmQueryRecord(gRouteDB, rec);
00748 
00749             /* lock record */
00750             route = (route_t *)MemHandleLock(routeDBEntry);
00751 
00752             /* update active waypoint record ID */
00753             gPrefs.act_wpt.waypointID = 
00754               route->wpt_rec_id[gPrefs.act_rte.wpt_index];
00755 
00756             /* unlock route record */
00757             MemHandleUnlock(routeDBEntry);
00758 
00759             /* display new active waypoint */
00760             display_wpt(&wpt_lat, &wpt_lon);
00761 
00762           } else {
00763             gPrefs.act_wpt.valid = false;
00764           } /* if (!err) */
00765         } /* if (gPrefs.act_rte.valid) */
00766       }
00767       
00768       /* Next Waypoint */
00769       if ((eventP->eType == ctlSelectEvent &&
00770            eventP->data.ctlSelect.controlID == NavigationNextWptButton) ||
00771          (eventP->eType == keyDownEvent &&
00772           eventP->data.keyDown.chr == pageDownChr)) {     
00773 
00774         if (gPrefs.act_rte.valid) {
00775 
00776           /* get active route */
00777           err = DmFindRecordByID(gRouteDB, gPrefs.act_rte.routeID,
00778             &rec);
00779 
00780           if (!err) {
00781             /* active route found */
00782             routeDBEntry = DmQueryRecord(gRouteDB, rec);
00783 
00784             /* lock record */
00785             route = (route_t *)MemHandleLock(routeDBEntry);
00786 
00787             if (gPrefs.act_rte.wpt_index == route->items-1) {
00788               /* last waypoint already active */
00789               MemHandleUnlock(routeDBEntry);
00790               break;
00791             }
00792 
00793             /* select next waypoint */
00794             gPrefs.act_rte.wpt_index++;
00795 
00796             /* update active waypoint record ID */
00797             gPrefs.act_wpt.waypointID = 
00798               route->wpt_rec_id[gPrefs.act_rte.wpt_index];
00799 
00800             /* unlock route record */
00801             MemHandleUnlock(routeDBEntry);
00802 
00803             /* display new active waypoint */
00804             display_wpt(&wpt_lat, &wpt_lon);
00805 
00806           } else {
00807             gPrefs.act_wpt.valid = false;
00808           } /* if (!err) */
00809         } /* if (gPrefs.act_rte.valid) */
00810       }
00811           
00812       if (eventP->eType == ctlSelectEvent) {
00813         if (eventP->data.ctlSelect.controlID == NavigationWptIDSel) {
00814           if (gPrefs.act_wpt.valid) {
00815             /* display active waypoint */
00816             err = DmFindRecordByID(gWaypointDB, gPrefs.act_wpt.waypointID,
00817               &rec);
00818         
00819             if (!err) {
00820               Char      prox_str[10];
00821               
00822               /* active waypoint found */
00823               waypointDBEntry = DmQueryRecord(gWaypointDB, rec);
00824               packed_waypoint =
00825                 (packed_waypoint_t *)MemHandleLock(waypointDBEntry);
00826               UnpackWaypoint(&waypoint, packed_waypoint);
00827               MemSet((Char *)tmp, 7, 0);
00828               StrNCopy(tmp, (Char *)&waypoint.ident, 6);
00829               format_number(waypoint.dst, 0, prox_str);
00830               FrmCustomAlert(NavigationWptAlert,
00831                 tmp, (Char *)waypoint.cmnt, prox_str);
00832               
00833               MemHandleUnlock(waypointDBEntry);
00834             } /* if (!err) */
00835           } /* if (gPrefs.act_wpt.valid) */
00836         } /* if (eventP->data.ctlSelect.controlID == NavigationWptIDSel) */
00837 
00838         if (eventP->data.ctlSelect.controlID ==  NavigationRteIDSel) {
00839           if (gPrefs.act_rte.valid) {
00840             /* display active route */
00841             err = DmFindRecordByID(gRouteDB, gPrefs.act_rte.routeID,
00842               &rec);
00843         
00844             if (!err) {
00845               Char      rte_str[4];     /* route items string */
00846               Char      wpt_str[16];    /* start/dst. waypoint ID string */
00847               UInt16    i;              /* loop index */
00848               UInt16    n;              /* last waypoint array index */
00849               
00850               /* clear string buffer */
00851               MemSet((Char *)wpt_str, 16, 0);
00852               
00853               /* active route found */
00854               routeDBEntry = DmQueryRecord(gRouteDB, rec);
00855 
00856               /* lock record */
00857               route = (route_t *)MemHandleLock(routeDBEntry);
00858 
00859               /* print route number to string */
00860               StrPrintF(rte_str, "%-3d", route->items);
00861               
00862               /* get destination waypoint's index*/
00863               n = route->items-1;
00864               
00865               /* do first index, last index */
00866               for (i=0; i<=n; i+=n) {
00867               
00868                 /* get waypoint record ID from route record */
00869                 err = DmFindRecordByID(gWaypointDB,
00870                   route->wpt_rec_id[i], &rec);
00871 
00872                 /* get waypoint record */
00873                 waypointDBEntry = DmQueryNextInCategory(gWaypointDB, &rec, 
00874                   dmAllCategories);
00875 
00876                 /* lock waypoint record */
00877                 packed_waypoint =
00878                   (packed_waypoint_t *)MemHandleLock(waypointDBEntry);
00879 
00880                 /* unpack waypoint record */
00881                 UnpackWaypoint(&waypoint, packed_waypoint);
00882 
00883                 /* Copy Identifier to first/second half of buffer */
00884                 StrNCopy(&wpt_str[(i==0) ? 0 : 8], waypoint.ident, 6);
00885 
00886                 /* unlock waypoint record */
00887                 MemHandleUnlock(waypointDBEntry);
00888               } /* for (i=0; i<=n; i+=n) */
00889               FrmCustomAlert(NavigationRteAlert,
00890                 rte_str, wpt_str, &wpt_str[8]);
00891               
00892               /* unlock route record */
00893               MemHandleUnlock(routeDBEntry);
00894             } /*if (!err) */
00895           } /* if (gPrefs.act_rte.valid) */
00896         } /* if (eventP->data.ctlSelect.controlID ==  NavigationRteIDSel) */
00897       } /* if (eventP->eType == ctlSelectEvent) */
00898       handled = true;
00899       break;
00900       
00901     case nilEvent:
00902       handled = true;
00903       
00904       /* throw away anything in the buffer-- we want fresh data */
00905       DoReceiveFlush(gPortID, 1);
00906 
00907       /*
00908        * Get GPS Data and update compass (COG)
00909        */
00910       updatedDisplay = ReadFromGPS();
00911 
00912       if (gHdFtrSet) {
00913         WinPushDrawState();
00914         WinSetCoordinateSystem(kCoordinatesNative);
00915       } 
00916 
00917       /*
00918        * Remove old pointer
00919        */
00920       r = (gHdFtrSet) ? WinScaleCoord(NAV_R1 - 5, false) : NAV_R1 - 5;
00921       p1.x = (gHdFtrSet) ? WinScaleCoord(NAV_X, false) : NAV_X;
00922       p1.y = (gHdFtrSet) ? WinScaleCoord(NAV_Y, false) : NAV_Y;
00923       x = p1.x + r * icos(otrk) / 32768;
00924       y = p1.y + r * isin(otrk) / 32768;
00925 
00926       WinEraseLine(p1.x, p1.y, x, y);
00927 
00928       if (gHdFtrSet) {
00929         WinPopDrawState();
00930       } 
00931       
00932       if (gGPSData.valid) {
00933         
00934         /* Speed Over Ground */
00935         display_sog();
00936         
00937         /* Course Made Good (= Course Over Ground = Track) */
00938         display_cmg();
00939         
00940       } else {
00941         SetFieldText(NavigationSogField, NULL, false, true);
00942         SetFieldText(NavigationCmgField, NULL, false, true);
00943       } /* if (gGPSData.valid) */
00944       
00945       if (gGPSData.valid && gPrefs.act_rte.valid && gPrefs.auto_wpt) {
00946         if ( UpdateActWpt(gGPSData.lat, gGPSData.lon, false /* init */) ) {
00947           /* update and display new active waypoint */
00948           display_wpt(&wpt_lat, &wpt_lon);
00949         }
00950       }
00951       
00952       /* Active Waypoint approach detection and display */
00953       NotifyApproach();
00954 
00955       /* Track Logging */
00956       if (gPrefs.act_trk.log_state) {
00957         Boolean new_trk;
00958 
00959         if (TrackIntervalCheck(false /* init */, &new_trk)) {
00960           TrackWriteLog(new_trk);
00961         }
00962       }         
00963        
00964       if (gGPSData.valid && gPrefs.act_wpt.valid) {
00965         Char    brg_str[8];
00966 
00967         /*
00968          * Distance to Waypoint
00969          */
00970         dist = gc_dist_sphere(gGPSData.lat, gGPSData.lon, wpt_lat, wpt_lon);
00971         
00972         /* calculate distance in km */
00973         dist = dist * calcR(gGPSData.lat) / 1000.0;
00974         display_dst(dist);      
00975         
00976         /*
00977          * Bearing (= Direction to Waypoint)
00978          */
00979         brg = gc_course_sphere(gGPSData.lat, gGPSData.lon, wpt_lat, wpt_lon);
00980         brg = rad2deg(brg);
00981 
00982         /*
00983          * Turn = bearing - track (pos: right/neg: left)
00984          */
00985         turn = brg - gGPSData.cmg;
00986         display_trn(turn);
00987 
00988         trk = (Int32)turn - 90;
00989 
00990         format_number(brg, 1, brg_str);
00991         StrCat(brg_str, "°");
00992         SetFieldText(NavigationBrgField, brg_str, false, true);
00993 
00994         if (gHdFtrSet) {
00995           WinPushDrawState();
00996           WinSetCoordinateSystem(kCoordinatesNative);
00997         } 
00998 
00999         /*
01000          * Draw new  pointer
01001          */
01002         r = (gHdFtrSet) ? WinScaleCoord(NAV_R1 - 5, false) : NAV_R1 - 5;
01003         p1.x = (gHdFtrSet) ? WinScaleCoord(NAV_X, false) : NAV_X;
01004         p1.y = (gHdFtrSet) ? WinScaleCoord(NAV_Y, false) : NAV_Y;
01005         x = p1.x + r * icos(trk) / 32768;
01006         y = p1.y + r * isin(trk) / 32768;
01007 
01008         WinDrawLine(p1.x, p1.y, x, y);
01009 
01010         if (gHdFtrSet) {
01011           WinPopDrawState();
01012         } 
01013         
01014         /* save old track */
01015         otrk = trk;
01016                 
01017         /* velocity made good: velocity in direction to waypoint (in kts) */
01018         vmg = gGPSData.sog * cos( deg2rad(turn) );
01019         
01020         /*
01021          * VMG is negative if leaving waypoint. Additionally,
01022          * we set a threshold (0.5 kts) to determine if we are
01023          * really approaching the waypoint.
01024          */
01025         if (vmg > 0.5) {
01026           UInt16        h;
01027           UInt16        m;
01028           UInt16        s;
01029           Char          ttg_str[10];    /* 999:59:59 */
01030           
01031           display_vmg(vmg);
01032           
01033           /*
01034            * time to go: dist / vmg
01035            *   Averaging VMG would yield more meaningful results...
01036            */
01037           ttg = dist / (vmg * spd_c[SPD_KMH].conv);
01038           
01039           hours_to_hms(ttg, &h, &m, &s);
01040           
01041           if (h < 999) {
01042             StrPrintF(ttg_str, "%u:%02u:%02u", h, m, s);
01043             SetFieldText(NavigationTtgField, ttg_str, false, true);
01044           } else {
01045             /*
01046              * More than 999 hours are considered to be an overflow,
01047              * due to limited screen space. And most likely the result
01048              * will be inaccurate, anyway...
01049              */
01050             SetFieldText(NavigationTtgField, "Overflow", false, true);
01051           }
01052         } else {
01053           /* leaving waypoint or not moving */
01054           SetFieldText(NavigationVmgField, "--", false, true);
01055           SetFieldText(NavigationTtgField, "--:--:--", false, true);
01056         } /* if (vmg > 1) */
01057       } else {
01058         /* no active WPT or GPS invalid */
01059         SetFieldText(NavigationDstField, NULL, false, true);
01060         SetFieldText(NavigationBrgField, NULL, false, true);
01061         SetFieldText(NavigationTrnField, NULL, false, true);
01062         SetFieldText(NavigationVmgField, NULL, false, true);
01063         SetFieldText(NavigationTtgField, NULL, false, true);
01064       } /* if (gGPSData.valid && gPrefs.act_wpt.valid) */
01065       break;
01066 
01067     case frmCloseEvent:
01068       /* Deallocate Fields' Text Memory */
01069       SetFieldText(NavigationStatusField, NULL, false, true);
01070       SetFieldText(TimeField, NULL, false, true);
01071       SetFieldText(NavigationDstField, NULL, false, true);
01072       SetFieldText(NavigationSogField, NULL, false, true);
01073       SetFieldText(NavigationVmgField, NULL, false, true);
01074       SetFieldText(NavigationTtgField, NULL, false, true);
01075       SetFieldText(NavigationCmgField, NULL, false, true);
01076       SetFieldText(NavigationBrgField, NULL, false, true);
01077       SetFieldText(NavigationTrnField, NULL, false, true);
01078       WinDeleteWindow(gNavigationH, true /* eraseIt */);
01079       break;
01080 
01081   }
01082   return(handled);
01083 } /* NavigationFormHandleEvent() */

Created: Mon, 08 Oct 2007 22:33:16 +0200
Copyright ©2004 M. Prinke