00001 /***************************************************************************** 00002 * 00003 * $RCSfile: Data_8c-source.html,v $ 00004 * 00005 * GPS4Palm Data Base Functions 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:32 $ 00015 * 00016 * $Revision: 1.7.2.1 $ 00017 * 00018 * $Log: Data_8c-source.html,v $ 00018 * Revision 1.7.2.1 2007-10-08 20:40:32 mp 00018 * updated for gps4palm V0.9.5 beta 00018 * 00019 * Revision 1.23 2005-04-02 17:55:16 mp 00020 * removed test code 00021 * 00022 * Revision 1.22 2005/04/02 17:28:21 mp 00023 * added CompareStringFunc() and Position2Geodb(), removed CompareIDFunc() 00024 * 00025 * Revision 1.21 2005/02/05 17:33:42 mp 00026 * added DeleteTracks() 00027 * 00028 * Revision 1.20 2004/12/12 21:01:08 mp 00029 * fixed track log wrap around 00030 * 00031 * Revision 1.19 2004/12/10 19:52:23 mp 00032 * replaced DmGet1Resource by DmGetResource 00033 * 00034 * Revision 1.18 2004/12/09 17:32:44 mp 00035 * replaced default track comment string by string resource, 00036 * implemented wrapping when track log database full 00037 * 00038 * Revision 1.17 2004/12/08 20:51:07 mp 00039 * added TrackIntervalCheck() 00040 * 00041 * Revision 1.16 2004/12/07 18:51:09 mp 00042 * added TrackWriteLog() 00043 * 00044 * Revision 1.15 2004/12/04 09:40:49 mp 00045 * added gTrackHdrDB, StoreTrkHdr(), StoreTrkPoint(), TrackDBName(), and 00046 * TrackIdent() 00047 * 00048 * Revision 1.14 2004/11/27 10:16:08 mp 00049 * replaced ErrFatalDisplay() by Die() for memory allocation failures 00050 * 00051 * Revision 1.13 2004/11/25 20:04:45 mp 00052 * added NotifyApproach() 00053 * 00054 * Revision 1.12 2004/11/25 16:59:22 mp 00055 * added CheckApproach() 00056 * 00057 * Revision 1.11 2004/11/24 21:03:43 mp 00058 * modified error handling in UpdateActWpt() 00059 * 00060 * Revision 1.10 2004/11/23 17:53:09 mp 00061 * removed unused variable 00062 * 00063 * Revision 1.9 2004/11/20 15:53:12 mp 00064 * added UpdateActWpt() 00065 * 00066 * Revision 1.8 2004/11/17 19:47:10 mp 00067 * code cleanup 00068 * 00069 * Revision 1.7 2004/11/16 21:05:53 mp 00070 * modified route/waypoint record write functions: pass record index instead 00071 * of handle, this allows to call DmGetRecord() / DmReleaseRecord 00072 * 00073 * Revision 1.6 2004/11/16 19:21:40 mp 00074 * added InsertRouteWpt(), DelRouteWpt(), and MoveRouteWpt(), 00075 * modified PackWaypoint() (removed debug output) 00076 * 00077 * Revision 1.5 2004/06/23 17:58:14 mp 00078 * Added comments, removed example functions from Sales application. 00079 * 00080 * Revision 1.4 2004/04/21 18:34:36 mp 00081 * modified macro DEG2SEMI() 00082 * 00083 * Revision 1.3 2004/03/12 21:16:26 mp 00084 * added InitializeWaypoints(void) 00085 * 00086 * Revision 1.2 2004/03/10 17:23:37 mp 00087 * modified due to changes in Data.h 00088 * 00089 * Revision 1.1 2004/03/07 14:28:49 mp 00090 * initial version 00091 * 00092 * 00093 ****************************************************************************/ 00094 #include <PalmOS.h> 00095 #include "Garmin.h" 00096 #include "Data.h" 00097 #include "geo.h" /* gc_dist_sphere() */ 00098 #include "common.h" 00099 #include "gpslib.h" /* Palm2GarminTimeDiff */ 00100 #include "Utils.h" 00101 #include "ResourceDefines.h" 00102 00103 /** Convert degrees (double) to semicircles (fix-point) */ 00104 #define DEG2SEMI(x) ((G_long)(x * ((1UL<<31)/180.0))) 00105 00106 /* Global Variables */ 00107 DmOpenRef gWaypointDB; /**< Waypoint Database Reference */ 00108 DmOpenRef gRouteDB; /**< Route Database Reference */ 00109 DmOpenRef gTrackHdrDB; /**< Track Header Database Reference */ 00110 DmOpenRef gTrackDB = 0; /**< Track Database Reference */ 00111 00112 extern PrefsType gPrefs; /* Preferences data structure */ 00113 extern GPSType gGPSData; /* GPS Data */ 00114 00115 /* 00116 * Track Log time interval in seconds 00117 * (must match TrkIntTimeList in GPS4Palm.rcp) 00118 */ 00119 static const UInt16 log_interval_time[] = { 00120 1, 2, 5, 10, 20, 30, 60, 120 00121 }; 00122 00123 /* 00124 * Track Log distance interval in meters 00125 * (must match TrkIntDstList in GPS4Palm.rcp) 00126 */ 00127 static const UInt16 log_interval_dist[] = { 00128 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000 00129 }; 00130 00131 /* Memo Name (keep it short, this has to be entered by the user in GeoDB) */ 00132 static const Char memo_name[] = "Gps4"; 00133 00134 /* Location Name (has to be edited anyway) */ 00135 static const Char location_name[] = "_GPS4Palm"; 00136 00137 00138 /***************************************************************************** 00139 * FUNCTION: CheckDatabases 00140 * 00141 * DESCRIPTION: Check lock state of databases. 00142 * 00143 * PARAMETERS: % 00144 * 00145 * RETURNED: % 00146 ****************************************************************************/ 00147 #ifdef DEBUG_BUILD 00148 void CheckDatabases(void) 00149 { 00150 UInt8 highest; 00151 UInt32 count; 00152 UInt32 busy; 00153 00154 return; 00155 DmGetDatabaseLockState(gWaypointDB, &highest, &count, &busy); 00156 if (highest || busy) 00157 ErrFatalDisplay("Waypoint db not quiescent"); 00158 DmGetDatabaseLockState(gRouteDB, &highest, &count, &busy); 00159 if (highest || busy) 00160 ErrFatalDisplay("Route db not quiescent"); 00161 DmGetDatabaseLockState(gTrackDB, &highest, &count, &busy); 00162 if (highest || busy) 00163 ErrFatalDisplay("Track db not quiescent"); 00164 } 00165 #endif 00166 00167 00168 /****************************************************************************/ 00169 /** 00170 * \brief Compare Strings 00171 * 00172 * 00173 * PARAMETERS: see DmComparF() in PalmOS Reference 00174 * 00175 * \return 00176 * - -1 if str1 < str2 00177 * - 1 if str1 > str2 00178 * - 0 if str1 = str2 00179 ****************************************************************************/ 00180 Int16 CompareStringFunc(const Char *str1, const Char *str2, Int16 i, 00181 SortRecordInfoPtr s1, SortRecordInfoPtr s2, MemHandle appInfoH) 00182 { 00183 return StrCompare(str1, str2); 00184 } 00185 00186 00187 /****************************************************************************/ 00188 /** 00189 * \brief Compare Waypoint Identifiers 00190 * 00191 * \note The identifiers are not necessarily null-terminated, 00192 * therefore StrCompare() cannot be used. 00193 * 00194 * PARAMETERS: see DmComparF() in PalmOS Reference 00195 * 00196 * \return 00197 * - -1 if ident1 < ident2 00198 * - 1 if ident1 > ident2 00199 * - 0 if ident1 = ident2 00200 ****************************************************************************/ 00201 Int16 CompareWayptIdent(waypoint_t *rec1, packed_waypoint_t *rec2, 00202 Int16 i, SortRecordInfoPtr s1, SortRecordInfoPtr s2, MemHandle appInfoH) 00203 { 00204 #pragma unused(i, s1, s2, appInfoH) 00205 UInt16 n; 00206 00207 for (n=0; n<6; n++) { 00208 if (rec1->ident[n] < rec2->ident[n]) { 00209 return -1; 00210 } else if (rec1->ident[n] > rec2->ident[n]) { 00211 return 1; 00212 } else if ((rec1->ident[n] == '\0') && (rec2->ident[n] == '\0')) { 00213 break; 00214 } 00215 } 00216 00217 /* Identifiers are equal */ 00218 return 0; 00219 } 00220 00221 00222 /****************************************************************************/ 00223 /** 00224 * \brief Compare Route Numbers 00225 * 00226 * \note see DmComparF() in PalmOS Reference for parameters 00227 * 00228 * \return 00229 * - -1 if nmbr1 < nmbr2 00230 * - 1 if nmbr1 > nmbr2 00231 * - 0 if nmbr1 = nmbr2 00232 ****************************************************************************/ 00233 Int16 CompareRteNmbr(route_t *rec1, route_t *rec2, 00234 Int16 i, SortRecordInfoPtr s1, SortRecordInfoPtr s2, MemHandle appInfoH) 00235 { 00236 #pragma unused(i, s1, s2, appInfoH) 00237 00238 if (rec1->nmbr < rec2->nmbr) { 00239 return -1; 00240 } else if (rec1->nmbr > rec2->nmbr) { 00241 return 1; 00242 } 00243 00244 /* Identifiers are equal */ 00245 return 0; 00246 } 00247 00248 00249 00250 /****************************************************************************/ 00251 /** 00252 * \brief Pack Waypoint and store it in Database 00253 * 00254 * \param waypoint ptr to waypoint structure 00255 * \param index waypoint record index 00256 * 00257 ****************************************************************************/ 00258 void PackWaypoint(waypoint_t *waypoint, UInt16 index) 00259 { 00260 MemHandle waypointDBEntry; /* waypoint record handle */ 00261 UInt16 length = 0; /* record length */ 00262 Char *s; /* record ptr */ 00263 UInt16 offset = 0; /* offset into record */ 00264 00265 /* get waypoint record */ 00266 waypointDBEntry = DmGetRecord(gWaypointDB, index); 00267 00268 /* figure out necessary size */ 00269 length = (UInt16) ( sizeof(waypoint->ident) + 00270 sizeof(waypoint->posn) + 00271 sizeof(waypoint->dst) + 00272 sizeof(waypoint->smbl) + 00273 sizeof(waypoint->dspl) + 00274 StrLen(waypoint->cmnt) + 00275 1 /* 1 for string terminator */ 00276 ); 00277 00278 /* resize the MemHandle */ 00279 if (MemHandleResize(waypointDBEntry, length) == 0) { 00280 /* copy the fields */ 00281 s = (Char *) MemHandleLock(waypointDBEntry); 00282 offset = 0; 00283 DmWrite(s, offset, &waypoint->ident, 00284 sizeof(waypoint->ident)); 00285 offset += sizeof(waypoint->ident); 00286 DmWrite(s, offset, &waypoint->posn.lat, 00287 sizeof(waypoint->posn.lat)); 00288 offset += sizeof(waypoint->posn.lat); 00289 DmWrite(s, offset, &waypoint->posn.lon, 00290 sizeof(waypoint->posn.lon)); 00291 offset += sizeof(waypoint->posn.lon); 00292 DmWrite(s, offset, &waypoint->dst, 00293 sizeof(waypoint->dst)); 00294 offset += sizeof(waypoint->dst); 00295 DmWrite(s, offset, &waypoint->smbl, 00296 sizeof(waypoint->smbl)); 00297 offset += sizeof(waypoint->smbl); 00298 DmWrite(s, offset, &waypoint->dspl, 00299 sizeof(waypoint->dspl)); 00300 offset += sizeof(waypoint->dspl); 00301 DmStrCopy(s, offset, waypoint->cmnt); 00302 MemHandleUnlock(waypointDBEntry); 00303 } else { 00304 Die("Cannot resize waypoint DB record!"); 00305 } 00306 00307 /* release record */ 00308 DmReleaseRecord(gWaypointDB, index, true /* dirty */); 00309 } 00310 00311 00312 /****************************************************************************/ 00313 /** 00314 * \brief Store Route Header in Database 00315 * 00316 * \param route ptr to route structure 00317 * \param index route record index 00318 * 00319 ****************************************************************************/ 00320 void PackRouteHdr(route_t *route, UInt16 index) 00321 { 00322 MemHandle routeDBEntry; /* route record handle */ 00323 UInt16 length = 0; /* record length */ 00324 Char *s; /* record ptr */ 00325 UInt16 offset = 0; /* offset into record */ 00326 00327 routeDBEntry = DmGetRecord(gRouteDB, index); 00328 00329 /* figure out necessary size */ 00330 length = (UInt16) ( sizeof(route->nmbr) + 00331 sizeof(route->cmnt) + 00332 sizeof(route->items) + 00333 route->items * sizeof(route->wpt_rec_id[0]) 00334 ); 00335 00336 /* resize the MemHandle */ 00337 if (MemHandleResize(routeDBEntry, length) == 0) { 00338 /* copy the fields */ 00339 s = (Char *)MemHandleLock(routeDBEntry); 00340 offset = 0; 00341 00342 DmWrite(s, offset, &route->nmbr, 00343 sizeof(route->nmbr)); 00344 offset += sizeof(route->nmbr); 00345 DmStrCopy(s, offset, route->cmnt); 00346 offset += sizeof(route->cmnt); 00347 DmWrite(s, offset, &route->items, 00348 sizeof(route->items)); 00349 MemHandleUnlock(routeDBEntry); 00350 } else { 00351 Die("Cannot resize route DB record (header)!"); 00352 } 00353 00354 /* release record */ 00355 DmReleaseRecord(gRouteDB, index, true /* dirty */); 00356 } 00357 00358 00359 /****************************************************************************/ 00360 /** 00361 * \brief Store Route Waypoint in Database (append) 00362 * 00363 * \param wpt_rec_id waypoint record ID 00364 * \param index route record index 00365 * 00366 ****************************************************************************/ 00367 void PackRouteWpt(UInt32 wpt_rec_id, UInt16 index) 00368 { 00369 MemHandle routeDBEntry; /* route record handle */ 00370 UInt16 items; /* number of waypoints on route */ 00371 UInt16 length = 0; /* record length */ 00372 UInt16 offset = 0; /* offset into record */ 00373 route_t *route; /* record ptr */ 00374 00375 /* get record handle */ 00376 routeDBEntry = DmGetRecord(gRouteDB, index); 00377 00378 /* figure out necessary size: original size + new wpt_rec_id */ 00379 route = MemHandleLock(routeDBEntry); 00380 items = route->items + 1; 00381 MemHandleUnlock(routeDBEntry); 00382 00383 length = (UInt16) ( sizeof(route->nmbr) + 00384 sizeof(route->cmnt) + 00385 sizeof(route->items) + 00386 (sizeof(route->wpt_rec_id[0]) * items) 00387 ); 00388 00389 /* resize the MemHandle */ 00390 if (MemHandleResize(routeDBEntry, length) == 0) { 00391 /* copy the fields */ 00392 route = MemHandleLock(routeDBEntry); 00393 offset = length - sizeof(route->wpt_rec_id[0]); 00394 DmWrite(route, offset, &wpt_rec_id, 00395 sizeof(wpt_rec_id)); 00396 00397 DmWrite(route, OffsetOf(route_t, items), &items, sizeof(route->items)); 00398 MemHandleUnlock(routeDBEntry); 00399 } else { 00400 Die("Cannot resize route DB record (waypoints)!"); 00401 } 00402 00403 /* release record */ 00404 DmReleaseRecord(gRouteDB, index, true /* dirty */); 00405 } 00406 00407 00408 /****************************************************************************/ 00409 /** 00410 * \brief Store Route Waypoint in Database (insert after selection) 00411 * 00412 * \param rec route record index 00413 * \param wpt_rec_id waypoint record ID 00414 * \param wpt_index waypoint array index 00415 * 00416 ****************************************************************************/ 00417 void InsertRouteWpt(UInt16 rec, UInt32 wpt_rec_id, UInt16 wpt_index) 00418 { 00419 MemHandle routeDBEntry; /* route record handle */ 00420 route_t *route; /* route record ptr */ 00421 UInt16 items; /* no. of waypoints */ 00422 UInt16 length; /* length of record */ 00423 UInt16 offset; /* offset within record */ 00424 UInt16 i; /* loop index */ 00425 00426 /* get record handle */ 00427 routeDBEntry = DmGetRecord(gRouteDB, rec); 00428 00429 /* figure out necessary size: original size + new wpt_rec_id */ 00430 route = MemHandleLock(routeDBEntry); 00431 items = route->items + 1; 00432 MemHandleUnlock(routeDBEntry); 00433 00434 length = (UInt16) ( sizeof(route->nmbr) + 00435 sizeof(route->cmnt) + 00436 sizeof(route->items) + 00437 (sizeof(route->wpt_rec_id[0]) * items) 00438 ); 00439 00440 /* set offset to last item */ 00441 offset = length - sizeof(route->wpt_rec_id[0]); 00442 00443 /* resize the MemHandle */ 00444 if (MemHandleResize(routeDBEntry, length) == 0) { 00445 /* lock record handle */ 00446 route = MemHandleLock(routeDBEntry); 00447 00448 /* move array items down */ 00449 for (i=items-1; i>wpt_index+1; i--) { 00450 DmWrite(route, offset, &route->wpt_rec_id[i-1], 00451 sizeof(route->wpt_rec_id[i-1])); 00452 offset -= sizeof(route->wpt_rec_id[0]); 00453 } 00454 00455 /* write new item */ 00456 DmWrite(route, offset, &wpt_rec_id, sizeof(wpt_rec_id)); 00457 00458 /* store new number of items */ 00459 DmWrite(route, OffsetOf(route_t, items), &items, sizeof(items)); 00460 00461 /* unlock record handle */ 00462 MemHandleUnlock(routeDBEntry); 00463 00464 } else { 00465 Die("Cannot resize route DB record (waypoints)!"); 00466 } 00467 00468 /* release record */ 00469 DmReleaseRecord(gRouteDB, rec, true /* dirty */); 00470 } 00471 00472 00473 /****************************************************************************/ 00474 /** 00475 * \brief Delete Route Waypoint from Database 00476 * 00477 * \param rec route record index 00478 * \param wpt_index waypoint array index 00479 * 00480 ****************************************************************************/ 00481 void DelRouteWpt(UInt16 rec, UInt16 wpt_index) 00482 { 00483 MemHandle routeDBEntry; /* route record handle */ 00484 route_t *route; /* route record ptr */ 00485 UInt16 i; /* loop index */ 00486 UInt16 offset; /* offset within record */ 00487 UInt16 items; /* new no. of items */ 00488 UInt16 length = 0; /* length of record */ 00489 00490 /* get record handle */ 00491 routeDBEntry = DmGetRecord(gRouteDB, rec); 00492 00493 /* offset to waypoint record ID to be deleted */ 00494 offset = sizeof(route->nmbr) + 00495 sizeof(route->cmnt) + 00496 sizeof(route->items) + 00497 sizeof(route->wpt_rec_id[0]) * wpt_index; 00498 00499 /* lock record */ 00500 route = MemHandleLock(routeDBEntry); 00501 00502 /* move array items up */ 00503 for (i=wpt_index; i<route->items-1; i++) { 00504 DmWrite(route, offset, &route->wpt_rec_id[i+1], 00505 sizeof(route->wpt_rec_id[i+1])); 00506 offset += sizeof(route->wpt_rec_id[0]); 00507 } 00508 00509 /* calculate offset to route->items */ 00510 offset = sizeof(route->nmbr) + 00511 sizeof(route->cmnt); 00512 00513 /* new no. of items */ 00514 items = route->items - 1; 00515 00516 /* write new no. of items to record */ 00517 DmWrite(route, offset, &items, sizeof(items)); 00518 00519 /* unlock record */ 00520 MemHandleUnlock(routeDBEntry); 00521 00522 /* release record */ 00523 DmReleaseRecord(gRouteDB, rec, true /* dirty */); 00524 00525 /* resize the MemHandle */ 00526 length = (UInt16) ( sizeof(route->nmbr) + 00527 sizeof(route->cmnt) + 00528 sizeof(route->items) + 00529 (sizeof(route->wpt_rec_id[0]) * items) 00530 ); 00531 00532 MemHandleResize(routeDBEntry, length); 00533 } 00534 00535 00536 /****************************************************************************/ 00537 /** 00538 * \brief Move Route Waypoint in Database 00539 * 00540 * \param rec route record index 00541 * \param wpt_index waypoint array index 00542 * \param up direction: true - up / false - down 00543 * 00544 ****************************************************************************/ 00545 void MoveRouteWpt(UInt16 rec, UInt16 wpt_index, Boolean up) 00546 { 00547 MemHandle routeDBEntry; /* route record handle */ 00548 route_t *route; /* route record ptr */ 00549 UInt16 offset; /* offset within record */ 00550 UInt32 wpt_rec_id; /* unique waypoint record ID */ 00551 00552 /* get record handle */ 00553 routeDBEntry = DmGetRecord(gRouteDB, rec); 00554 00555 /* offset to waypoint record ID to be moved */ 00556 offset = sizeof(route->nmbr) + 00557 sizeof(route->cmnt) + 00558 sizeof(route->items) + 00559 sizeof(route->wpt_rec_id[0]) * wpt_index; 00560 00561 /* lock record */ 00562 route = MemHandleLock(routeDBEntry); 00563 00564 if (up) { 00565 wpt_rec_id = route->wpt_rec_id[wpt_index-1]; 00566 DmWrite(route, offset-sizeof(wpt_rec_id), 00567 &route->wpt_rec_id[wpt_index], sizeof(wpt_rec_id)); 00568 DmWrite(route, offset, 00569 &wpt_rec_id, sizeof(wpt_rec_id)); 00570 } else { 00571 wpt_rec_id = route->wpt_rec_id[wpt_index+1]; 00572 DmWrite(route, offset+sizeof(wpt_rec_id), 00573 &route->wpt_rec_id[wpt_index], sizeof(wpt_rec_id)); 00574 DmWrite(route, offset, 00575 &wpt_rec_id, sizeof(wpt_rec_id)); 00576 } 00577 00578 /* unlock record */ 00579 MemHandleUnlock(routeDBEntry); 00580 00581 /* release record */ 00582 DmReleaseRecord(gRouteDB, rec, true /* dirty */); 00583 } 00584 00585 /**********************************************************************/ 00586 /** 00587 * Unpack waypoint retrieved from database. 00588 * 00589 * \note The packed_waypoint must remain locked while 00590 * the waypoint is in use. 00591 * \param waypoint ptr to unpacked waypoint structure 00592 * \param packed_waypoint ptr to packed waypoint structure 00593 *********************************************************************/ 00594 void UnpackWaypoint(waypoint_t *waypoint, 00595 const packed_waypoint_t *packed_waypoint) 00596 { 00597 StrNCopy(waypoint->ident, packed_waypoint->ident, 6); 00598 waypoint->posn.lat = packed_waypoint->posn.lat; 00599 waypoint->posn.lon = packed_waypoint->posn.lon; 00600 waypoint->unused = 0; 00601 waypoint->dst = packed_waypoint->dst; 00602 waypoint->smbl = packed_waypoint->smbl; 00603 waypoint->dspl = packed_waypoint->dspl; 00604 StrCopy(waypoint->cmnt, packed_waypoint->cmnt); 00605 } 00606 00607 /**********************************************************************/ 00608 /** 00609 * Store track header in database. 00610 * 00611 * \param trkhdr ptr to track header structure 00612 * \param index track header record index 00613 **********************************************************************/ 00614 void StoreTrkHdr(trk_header_t *trkhdr, UInt16 index) 00615 { 00616 MemHandle trkhDBEntry; /* track point record handle */ 00617 UInt16 length = 0; /* record length */ 00618 UInt16 offset = 0; /* offset into record */ 00619 trk_header_t *trkP; /* record ptr */ 00620 00621 length = (UInt16) ( sizeof(trkhdr->dspl) + 00622 sizeof(trkhdr->color) + 00623 sizeof(trkhdr->trk_ident) 00624 ); 00625 00626 /* get record handle */ 00627 trkhDBEntry = DmGetRecord(gTrackHdrDB, index); 00628 00629 /* resize the MemHandle */ 00630 if (MemHandleResize(trkhDBEntry, length) == 0) { 00631 /* copy the fields */ 00632 trkP = MemHandleLock(trkhDBEntry); 00633 offset = 0; 00634 DmWrite(trkP, offset, &trkhdr->dspl, 00635 sizeof(trkhdr->dspl)); 00636 offset += sizeof(trkhdr->dspl); 00637 DmWrite(trkP, offset, &trkhdr->color, 00638 sizeof(trkhdr->color)); 00639 offset += sizeof(trkhdr->color); 00640 DmWrite(trkP, offset, &trkhdr->trk_ident, 00641 sizeof(trkhdr->trk_ident)); 00642 MemHandleUnlock(trkhDBEntry); 00643 } else { 00644 Die("Cannot resize track header DB record!"); 00645 } 00646 00647 /* release record */ 00648 DmReleaseRecord(gTrackHdrDB, index, true /* dirty */); 00649 } 00650 00651 00652 /**********************************************************************/ 00653 /** 00654 * Store track point in database. 00655 * 00656 * \param trkpoint ptr to track point structure 00657 * \param index track point record index 00658 **********************************************************************/ 00659 void StoreTrkPoint(trk_point_t *trkpoint, UInt16 index) 00660 { 00661 MemHandle trkpDBEntry; /* track point record handle */ 00662 UInt16 length = 0; /* record length */ 00663 UInt16 offset = 0; /* offset into record */ 00664 trk_point_t *trkP; /* record ptr */ 00665 00666 length = (UInt16) ( sizeof(trkpoint->posn) + 00667 sizeof(trkpoint->time) + 00668 sizeof(trkpoint->new_trk) 00669 ); 00670 00671 /* get record handle */ 00672 trkpDBEntry = DmGetRecord(gTrackDB, index); 00673 00674 /* resize the MemHandle */ 00675 if (MemHandleResize(trkpDBEntry, length) == 0) { 00676 /* copy the fields */ 00677 trkP = MemHandleLock(trkpDBEntry); 00678 offset = 0; 00679 DmWrite(trkP, offset, &trkpoint->posn, 00680 sizeof(trkpoint->posn)); 00681 offset += sizeof(trkpoint->posn); 00682 DmWrite(trkP, offset, &trkpoint->time, 00683 sizeof(trkpoint->time)); 00684 offset += sizeof(trkpoint->time); 00685 DmWrite(trkP, offset, &trkpoint->new_trk, 00686 sizeof(trkpoint->new_trk)); 00687 MemHandleUnlock(trkpDBEntry); 00688 } else { 00689 Die("Cannot resize track point DB record!"); 00690 } 00691 00692 /* release record */ 00693 DmReleaseRecord(gTrackDB, index, true /* dirty */); 00694 } 00695 00696 00697 /****************************************************************************/ 00698 /** 00699 * \brief Generate Track Point Data Base Name 00700 * 00701 * \param dbname pointer to destination string buffer 00702 * \param trackID track header unique record ID 00703 * 00704 ****************************************************************************/ 00705 void TrackDBName(Char *dbname, UInt32 trackID) 00706 { 00707 UInt16 i; /* loop index */ 00708 00709 /* copy fixed part of track data base name */ 00710 StrPrintF(dbname, "%s", kTrkDBName); 00711 00712 for (i=0; i<6; i++) { 00713 StrPrintF(&dbname[StrLen(dbname)], "%c", nibble2hex((trackID >> 20) & 0xF)); 00714 trackID <<= 4; 00715 } 00716 } 00717 00718 /****************************************************************************/ 00719 /** 00720 * \brief Generate Track Identifier from current Time and Date 00721 * 00722 * \param ident pointer to destination string buffer 00723 * 00724 ****************************************************************************/ 00725 void TrackIdent(Char *ident) 00726 { 00727 UInt32 seconds; /* current time */ 00728 DateTimeType dt; /* date/time structure */ 00729 MemHandle strH; /* string handle */ 00730 MemPtr strP; /* string ptr */ 00731 00732 00733 /* 00734 * create comment: <Track yy-mm-dd hh:mm> 00735 */ 00736 MemSet(ident, sizeof(ident), 0); 00737 00738 /* get string from resource */ 00739 strH = DmGetResource(strRsc, TrackStr); 00740 if (strH != NULL) { 00741 /* string handle valid, lock it */ 00742 strP = MemHandleLock(strH); 00743 00744 /* copy string */ 00745 StrCopy(ident, strP); 00746 00747 /* unlock string handle */ 00748 MemHandleUnlock(strH); 00749 00750 /* release string resource */ 00751 DmReleaseResource(strH); 00752 } 00753 00754 /* get current time and date */ 00755 seconds = TimGetSeconds(); 00756 TimSecondsToDateTime(seconds, &dt); 00757 00758 /* write date to string */ 00759 DateToAscii(dt.month, dt.day, dt.year, dfYMDWithDashes, 00760 &ident[StrLen(ident)]); 00761 00762 /* append space */ 00763 StrCat(ident, " "); 00764 00765 /* write time to string */ 00766 TimeToAscii(dt.hour, dt.minute, tfColon24h, 00767 &ident[StrLen(ident)]); 00768 00769 /* append bracket */ 00770 StrCat(ident, ">"); 00771 } 00772 00773 00774 /****************************************************************************/ 00775 /** 00776 * \brief Delete all track point databases 00777 * 00778 ****************************************************************************/ 00779 void DeleteTracks(void) 00780 { 00781 DmSearchStateType state; /* DmSearchState */ 00782 UInt16 card; /* card no. */ 00783 LocalID currentDB = 0; /* local ID of current DB */ 00784 Err err; /* error code */ 00785 00786 do { 00787 err = DmGetNextDatabaseByTypeCreator( 00788 true /* newSearch */, 00789 &state /* stateInfoP */, 00790 kTrkDBType /* type */, 00791 kCreatorId /* creator */, 00792 false /* onlyLatestVers */, 00793 &card /* cardNoP */, 00794 ¤tDB /* dbIDP */ 00795 ); 00796 00797 if (!err) { 00798 DmDeleteDatabase(card, currentDB); 00799 } 00800 } while (!err); 00801 } 00802 00803 00804 /****************************************************************************/ 00805 /** 00806 * \brief Add Position to Memo for Import to GeoDB 00807 * 00808 * \param gps_data GPS Data (Time of Fix, Position, ...) 00809 * 00810 * \return True if GPS data is valid. 00811 * 00812 * \note GeoDB expects the following format in the Memo: 00813 * 00814 * < memo_name >\n 00815 * < location_name >,< latitude >,< N|S >,< longitude >,< E|W >, 00816 * < elevation >,< gmt_offset >,< E|W >,< daylight_time > 00817 * 00818 * Example: 00819 * 00820 * AA 00821 * Adana,37:0.6,N,35:16.8,E,,2,E,0 00822 * 00823 + (GPS4Palm only knows the position) 00824 * 00825 ****************************************************************************/ 00826 Boolean Position2Geodb(GPSType gps_data) 00827 { 00828 Char clp_str[100]; /* clipboard string buffer */ 00829 Char lat_str[20]; /* latitude string buffer */ 00830 Char lon_str[20]; /* longitude string buffer */ 00831 DmOpenRef memoDB; 00832 MemHandle recH; 00833 MemPtr recP; 00834 UInt16 index; 00835 00836 if (!gps_data.valid) 00837 return false; 00838 00839 /* convert double lat/lon to string */ 00840 deg_to_geodb_str(gps_data.lat, gps_data.lon, lat_str, lon_str); 00841 00842 /* 00843 * TODO: 00844 * Elevation (or "Altitude") is actually known, but not a 00845 * Member of GPSType yet. 00846 */ 00847 00848 /* format output string */ 00849 StrPrintF(clp_str, "%s\n%s,%s,%s,,,,,", 00850 memo_name, 00851 location_name, 00852 lat_str, 00853 lon_str); 00854 00855 /* 00856 * Note: optionally we could add it to clipboard 00857 ClipboardAddItem(clipboardText, clp_str, StrLen(clp_str)); 00858 */ 00859 00860 /* Open Memo DB */ 00861 memoDB = DmOpenDatabaseByTypeCreator('DATA', sysFileCMemo, dmModeReadWrite); 00862 00863 /* Find sort position of new record in memo DB */ 00864 index = DmFindSortPosition(memoDB, clp_str, 0 /* newRecordInfo */, 00865 (DmComparF *)CompareStringFunc /* DmComparF *compar */, 0 /* other */); 00866 00867 /* Create new memo record */ 00868 recH = DmNewRecord(memoDB, &index, StrLen(clp_str) + 1); 00869 recP = MemHandleLock(recH); 00870 DmStrCopy(recP, 0, clp_str); 00871 MemHandleUnlock(recH); 00872 DmReleaseRecord(memoDB, index, true); 00873 00874 /* Close Memo DB */ 00875 DmCloseDatabase(memoDB); 00876 00877 return true; 00878 } 00879 00880 00881 /****************************************************************************/ 00882 /** 00883 * \brief Update active (route) waypoint according to distance to 00884 * current and next waypoint. 00885 * 00886 * The current implementation switches to the next route 00887 * waypoint even if the current waypoint is just "passed by", 00888 * i.e. the distance to the current waypoint is increasing 00889 * while the distance to the next waypoint is decreasing. 00890 * 00891 * A different implementation could require the current 00892 * waypoint to be "visited" with the proximity information 00893 * stored in the waypoint record as the criterion. 00894 * 00895 * \param lat current latitude 00896 * \param lon current longitude 00897 * \param init initialize function (after changing route) 00898 * 00899 * \return 00900 * - true if next waypoint has been select as active waypoint 00901 * - false if current waypoint is still active waypoint 00902 * 00903 * \note After changing the active route, the finction must be called 00904 * with init=true (lat/lon may be invalid). This marks the 00905 * distance values stored previously invalid. The next call 00906 * which must occur with a valid position updates the stored 00907 * distance values. Any subsequent call will then provide 00908 * a correct waypoint selection. 00909 * 00910 ****************************************************************************/ 00911 Boolean UpdateActWpt(double lat, double lon, Boolean init) 00912 { 00913 route_t *route; /* route */ 00914 MemHandle routeDBEntry; /* route record handle */ 00915 packed_waypoint_t *packed_waypoint; /* packed waypoint ptr */ 00916 waypoint_t waypoint; /* unpacked waypoint */ 00917 MemHandle waypointDBEntry; /* waypoint record handle */ 00918 UInt16 rec; /* record index */ 00919 static Boolean init_ok = false; /* flag: initialization o.k. */ 00920 static double dst_act_old; /* old dist. to active wpt. */ 00921 static double dst_next_old; /* dist. to next wpt. */ 00922 double dst_act; /* dist. to active waypoint */ 00923 double dst_next; /* dist. to next waypoint */ 00924 double wpt_lat; /* waypoint longitude */ 00925 double wpt_lon; /* waypoint latitude */ 00926 Boolean updated = false; /* flag: act. wpt. updated */ 00927 Err err; /* error code */ 00928 00929 if (init) { 00930 init_ok = false; 00931 return false; 00932 } 00933 00934 /* get active route */ 00935 err = DmFindRecordByID(gRouteDB, gPrefs.act_rte.routeID, 00936 &rec); 00937 00938 if (!err) { 00939 /* active route found */ 00940 routeDBEntry = DmQueryRecord(gRouteDB, rec); 00941 00942 /* lock route record */ 00943 route = (route_t *)MemHandleLock(routeDBEntry); 00944 00945 if (gPrefs.act_rte.wpt_index == route->items-1) { 00946 /* last waypoint already active */ 00947 MemHandleUnlock(routeDBEntry); 00948 return false; 00949 } 00950 00951 /* get active waypoint */ 00952 err = DmFindRecordByID(gWaypointDB, 00953 route->wpt_rec_id[gPrefs.act_rte.wpt_index], 00954 &rec); 00955 00956 if (!err) { 00957 /* active waypoint found */ 00958 waypointDBEntry = DmQueryRecord(gWaypointDB, rec); 00959 packed_waypoint = 00960 (packed_waypoint_t *)MemHandleLock(waypointDBEntry); 00961 UnpackWaypoint(&waypoint, packed_waypoint); 00962 00963 wpt_lat = semi2deg(waypoint.posn.lat); 00964 wpt_lon = semi2deg(waypoint.posn.lon); 00965 00966 MemHandleUnlock(waypointDBEntry); 00967 dst_act = gc_dist_sphere(lat, lon, wpt_lat, wpt_lon); 00968 } else { 00969 return false; 00970 } 00971 00972 /* get next waypoint */ 00973 err = DmFindRecordByID(gWaypointDB, 00974 route->wpt_rec_id[gPrefs.act_rte.wpt_index + 1], 00975 &rec); 00976 00977 if (!err) { 00978 /* next waypoint found */ 00979 waypointDBEntry = DmQueryRecord(gWaypointDB, rec); 00980 packed_waypoint = 00981 (packed_waypoint_t *)MemHandleLock(waypointDBEntry); 00982 UnpackWaypoint(&waypoint, packed_waypoint); 00983 00984 wpt_lat = semi2deg(waypoint.posn.lat); 00985 wpt_lon = semi2deg(waypoint.posn.lon); 00986 00987 MemHandleUnlock(waypointDBEntry); 00988 dst_next = gc_dist_sphere(lat, lon, wpt_lat, wpt_lon); 00989 } else { 00990 return false; 00991 } 00992 00993 if (init_ok && (dst_act > dst_act_old) && (dst_next < dst_next_old)) { 00994 /* next waypoint selected */ 00995 gPrefs.act_rte.wpt_index++; 00996 00997 /* update active waypoint record ID */ 00998 gPrefs.act_wpt.waypointID = 00999 route->wpt_rec_id[gPrefs.act_rte.wpt_index]; 01000 updated = true; 01001 01002 } else { 01003 /* current waypoint still active */ 01004 updated = false; 01005 } 01006 01007 /* save current distances */ 01008 dst_act_old = dst_act; 01009 dst_next_old = dst_next; 01010 init_ok = true; 01011 01012 /* unlock route record */ 01013 MemHandleUnlock(routeDBEntry); 01014 } /* if (!err) */ 01015 01016 return updated; 01017 } 01018 01019 01020 /****************************************************************************/ 01021 /** 01022 * \brief Write Track Point to Track Log Data Base 01023 * 01024 * \param new_trk new track or track segment 01025 * 01026 * \return - true if successful 01027 * - false if data base is full and wrapping is disabled 01028 ****************************************************************************/ 01029 Boolean TrackWriteLog(Boolean new_trk) 01030 { 01031 Char dbname[dmDBNameLength]; /* data base name */ 01032 MemHandle trkDBEntry; /* record handle */ 01033 UInt16 index; /* record index */ 01034 trk_point_t trkpoint; /* track point */ 01035 01036 if (!gTrackDB) { 01037 /* data base not yet open */ 01038 01039 /* generate data base name */ 01040 TrackDBName(dbname, gPrefs.act_trk.trackID); 01041 01042 /* open track DB */ 01043 gTrackDB = DmOpenDatabase(0 /* cardNo */, 01044 DmFindDatabase(0 /* cardNo */, dbname), dmModeReadWrite); 01045 } 01046 01047 if ( DmNumRecords(gTrackDB) < dmMaxRecordIndex) { 01048 01049 /* add at the end of the database */ 01050 index = dmMaxRecordIndex; 01051 01052 trkDBEntry = DmNewRecord(gTrackDB, &index, sizeof(trk_point_t)); 01053 01054 if (trkDBEntry) { 01055 DmReleaseRecord(gTrackDB, index, false /* dirty */); 01056 } else { 01057 Die("Cannot create track record!"); 01058 return false; 01059 } 01060 01061 } else { 01062 /* Data Base is full */ 01063 01064 if (!gPrefs.trk_log.wrap) { 01065 /* stop or wrap */ 01066 if (FrmAlert(TrackFullAlert) == 1) { 01067 /* change to wrapping */ 01068 gPrefs.trk_log.wrap = true; 01069 } 01070 } 01071 01072 if (gPrefs.trk_log.wrap) { 01073 /* wrap around */ 01074 01075 /* delete first record, overwrite last record */ 01076 DmRemoveRecord(gTrackDB, 0); 01077 01078 /* add at the end of the database */ 01079 index = dmMaxRecordIndex; 01080 01081 /* seek last record (will be overwritten) */ 01082 DmSeekRecordInCategory(gTrackDB, &index, 0 /* offset */, 01083 dmSeekBackward, dmAllCategories); 01084 01085 } else { 01086 /* stop logging */ 01087 gPrefs.act_trk.log_state = false; 01088 gPrefs.act_trk.valid = false; 01089 DmCloseDatabase(gTrackDB); 01090 return false; 01091 01092 } 01093 } 01094 01095 /* copy track point data to struct */ 01096 trkpoint.new_trk = new_trk; 01097 trkpoint.posn.lat = deg2semi(gGPSData.lat); 01098 trkpoint.posn.lon = deg2semi(gGPSData.lon); 01099 trkpoint.time = gGPSData.time - Palm2GarminTimeDiff; 01100 01101 /* store track point in DB */ 01102 StoreTrkPoint(&trkpoint, index); 01103 01104 return true; 01105 } 01106 01107 01108 /****************************************************************************/ 01109 /** 01110 * \brief check if track log interval reached 01111 * 01112 * Checks if a new track point has to be logged depending on 01113 * the selected track log mode (time or distance) and interval. 01114 * A new track segment is started upon initialization or after 01115 * loosing and regaining coverage. 01116 * 01117 * \param init init track interval accumulation and 01118 * start new track segment 01119 * \param new_trk new track segment (returned by reference) 01120 * 01121 * \return 01122 * - true if track point log interval passed 01123 * - false if track point log interval not yet passed 01124 * 01125 ****************************************************************************/ 01126 Boolean TrackIntervalCheck(Boolean init, Boolean *new_trk) 01127 { 01128 static Boolean gps_valid; /* GPS fix valid */ 01129 static UInt16 acc_time; /* accumulated time */ 01130 static UInt16 acc_dist; /* accumulated distance */ 01131 static UInt32 prev_time; /* previous time */ 01132 static double prev_lat; /* previous latitude */ 01133 static double prev_lon; /* previous longitude */ 01134 static Boolean init_flag = true; /* flag: init */ 01135 Boolean log_now = false; /* flag: log now */ 01136 01137 if (init || (gps_valid == false && gGPSData.valid)) { 01138 /* start new track segment as soon as GPS fix available */ 01139 init_flag = true; 01140 acc_time = 0; 01141 acc_dist = 0; 01142 } 01143 01144 if (gGPSData.valid) { 01145 if (init_flag) { 01146 *new_trk = true; 01147 log_now = true; 01148 init_flag = false; 01149 } else { 01150 *new_trk = false; 01151 01152 if (gPrefs.trk_log.mode == 1) { 01153 /* log interval mode: time */ 01154 acc_time += TimGetSeconds() - prev_time; 01155 01156 if (acc_time >= log_interval_time[gPrefs.trk_log.ival]) { 01157 acc_time = 0; 01158 log_now = true; 01159 } 01160 01161 } else { 01162 /* log interval mode: distance */ 01163 acc_dist += (UInt16)(gc_dist_sphere(gGPSData.lat, gGPSData.lon, 01164 prev_lat, prev_lon) * calcR(gGPSData.lat)); 01165 01166 if (acc_dist >= log_interval_dist[gPrefs.trk_log.ival]) { 01167 acc_dist = 0; 01168 log_now = true; 01169 } 01170 01171 } /* if (gPrefs.trk_log.mode == 0) */ 01172 } /* if (*new_trk) */ 01173 01174 /* save current position */ 01175 prev_lat = gGPSData.lat; 01176 prev_lon = gGPSData.lon; 01177 01178 /* save current time */ 01179 prev_time = TimGetSeconds(); 01180 } /* if (gGPSData.valid) */ 01181 01182 /* save current GPS fix state */ 01183 gps_valid = gGPSData.valid; 01184 01185 return log_now; 01186 } 01187 01188 01189 /****************************************************************************/ 01190 /** 01191 * \brief check if active waypoint is within proximity distance 01192 * 01193 * If no proximity distance is stored in the waypoint data base 01194 * (i.e. the proximity distance is zero), a default value is 01195 * used. 01196 * 01197 * \param lat current latitude 01198 * \param lon current longitude 01199 * 01200 * \return 01201 * - true if active waypoint is within proximity distance 01202 * - false if active waypoint is not within proximity distance 01203 * 01204 ****************************************************************************/ 01205 Boolean CheckApproach(double lat, double lon) 01206 { 01207 packed_waypoint_t *packed_waypoint; /* packed waypoint ptr */ 01208 waypoint_t waypoint; /* unpacked waypoint */ 01209 MemHandle waypointDBEntry; /* waypoint record handle */ 01210 UInt16 rec; /* record index */ 01211 double wpt_lat; /* waypoint latitude */ 01212 double wpt_lon; /* waypoint longitude */ 01213 double wpt_dst; /* distance to waypoint */ 01214 double prox_dst; /* wpt's proximity distance */ 01215 Err err; /* error code */ 01216 01217 /* find active waypoint */ 01218 err = DmFindRecordByID(gWaypointDB, gPrefs.act_wpt.waypointID, 01219 &rec); 01220 01221 if (!err) { 01222 /* active waypoint found */ 01223 waypointDBEntry = DmQueryRecord(gWaypointDB, rec); 01224 packed_waypoint = 01225 (packed_waypoint_t *)MemHandleLock(waypointDBEntry); 01226 UnpackWaypoint(&waypoint, packed_waypoint); 01227 wpt_lat = semi2deg(waypoint.posn.lat); 01228 wpt_lon = semi2deg(waypoint.posn.lon); 01229 prox_dst = (double)waypoint.dst; 01230 MemHandleUnlock(waypointDBEntry); 01231 01232 /* get distance to active waypoint */ 01233 wpt_dst = gc_dist_sphere(lat, lon, wpt_lat, wpt_lon) * calcR(lat); 01234 01235 /* use default if waypoint has no proximity distance set */ 01236 if (prox_dst == 0.0) 01237 prox_dst = APPROACH_DST; 01238 01239 /* compare current distance with proximity distance */ 01240 if (wpt_dst <= prox_dst) { 01241 return true; 01242 } 01243 } 01244 01245 return false; 01246 } 01247 01248 01249 /****************************************************************************/ 01250 /** 01251 * \brief generate notification if Active Waypoint is within 01252 * proximity distance 01253 * 01254 * Depending on the user settings, audible and/or visible 01255 * notification is triggered. In audible only mode, just one 01256 * alarm sound is played. Otherwise an alert form is opened 01257 * and has to be acknowledged by the user. After achnowledgement, 01258 * the notification will not be repeated for this waypoint. 01259 * 01260 ****************************************************************************/ 01261 void NotifyApproach(void) 01262 { 01263 static Boolean alarm_ok = false; /* flag: alarm done */ 01264 static UInt32 wpt_id_old = 0; /* saved act. wpt. ID */ 01265 01266 if (gGPSData.valid && gPrefs.act_wpt.valid) { 01267 01268 if (gPrefs.act_wpt.waypointID != wpt_id_old) { 01269 /* new active waypoint - reset approach alert */ 01270 alarm_ok = false; 01271 } 01272 01273 if ( CheckApproach(gGPSData.lat, gGPSData.lon) && !alarm_ok) { 01274 /* 01275 * Trigger approach notification, audible and/or visible. 01276 * The alert is generated once. To retrigger the detection, the 01277 * active waypoint ID has to change. 01278 */ 01279 if (gPrefs.approach_sound) { 01280 SndPlaySystemSound(sndAlarm); 01281 } 01282 if (gPrefs.approach_alert) { 01283 FrmGotoForm(ApproachForm); 01284 } 01285 01286 alarm_ok = true; 01287 } 01288 01289 /* save active waypoint ID for change detection */ 01290 wpt_id_old = gPrefs.act_wpt.waypointID; 01291 } 01292 } 01293 01294 01295 /****************************************************************************/ 01296 /** 01297 * \brief Open a database. 01298 * 01299 * If it doesn't exist, create it. 01300 * 01301 * \param dbP Database reference ptr 01302 * \param type Type of the database 01303 * \param creator Creator of the database 01304 * \param mode Open mode 01305 * \param cardNo Card number 01306 * \param name Database name 01307 * \param created Flag: new database has been created (return value) 01308 * 01309 * \return Error code of DmOpenDatabaseByTypeCreator() or 01310 * DmCreateDatabase(), respectively. 01311 * created -- Flag: new database has been created 01312 * (returned by reference) 01313 *****************************************************************************/ 01314 Err OpenOrCreateDB(DmOpenRef *dbP, UInt32 type, UInt32 creator, 01315 UInt16 mode, UInt16 cardNo, char *name, Boolean *created) 01316 { 01317 Err err = errNone; 01318 01319 *created = false; 01320 *dbP = DmOpenDatabaseByTypeCreator(type, creator, mode); 01321 if (! *dbP) 01322 { 01323 err = DmGetLastErr(); 01324 if (err == dmErrCantFind) 01325 err = DmCreateDatabase(cardNo, name, creator, type, false); 01326 if (err != errNone) 01327 return err; 01328 *created = true; 01329 01330 *dbP = DmOpenDatabaseByTypeCreator(type, creator, mode); 01331 if (! *dbP) 01332 return DmGetLastErr(); 01333 } 01334 return err; 01335 } 01336 01337 01338 /****************************************************************************/ 01339 /** 01340 * \brief Creates a Waypoint Database. 01341 * 01342 * The Database contains the capitals of all states of the 01343 * European Community (as of 03/2004). 01344 * The waypoints were taken from http://wayhoo.com, which in turn 01345 * uses GNS (http://gnswww.nima.mil/geonames/GNS/index.jsp). 01346 * 01347 * Quoted from Wayhoo: 01348 * Note: GNS coordinates have a low degree of precision, 01349 * latitude and longitude. 01350 * 01351 * The Waypoint Identifiers (i.e. short names) are comprised of 01352 * the ISO Country Code and the IATA (International Air 01353 * Transport Association) Location ID. 01354 * (see http://www.iata.org/codes/index.htm) 01355 * 01356 * This is just an example after all. 01357 * 01358 *****************************************************************************/ 01359 void InitializeWaypoints(void) 01360 { 01361 waypoint_t waypoints[] = { 01362 {"AT-VIE", {DEG2SEMI(48.20000), DEG2SEMI(16.36667)} , 0, 01363 "Vienna, Austria (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01364 {"BE-BRU", {DEG2SEMI(50.83333), DEG2SEMI(4.33333)} , 0, 01365 "Brussels, Belgium (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01366 {"DK-CPH", {DEG2SEMI(55.66667), DEG2SEMI(12.58333)} , 0, 01367 "Copenhagen, Denmark (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01368 {"FI-HEL", {DEG2SEMI(60.17556), DEG2SEMI(24.93417)} , 0, 01369 "Helsinki, Finland (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01370 {"FR-PAR", {DEG2SEMI(48.86667), DEG2SEMI(2.33333)} , 0, 01371 "Paris, France (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01372 {"DE-BER", {DEG2SEMI(52.51667), DEG2SEMI(13.40000)} , 0, 01373 "Berlin, Germany (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01374 {"GR-ATH", {DEG2SEMI(37.98333), DEG2SEMI(23.73333)} , 0, 01375 "Athens, Greece (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01376 {"IE-DUB", {DEG2SEMI(53.33306), DEG2SEMI(-6.24889)} , 0, 01377 "Dublin, Ireland (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01378 {"IT-ROM", {DEG2SEMI(41.90000), DEG2SEMI(12.48333)} , 0, 01379 "Rome, Italy (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01380 {"LU-LUX", {DEG2SEMI(49.61167), DEG2SEMI(6.13000)} , 0, 01381 "Luxembourg, Luxembourg (Capital)", 4000.0, sym_lrg_cty, dspl_smbl_only }, 01382 {"NL-HAG", {DEG2SEMI(52.08333), DEG2SEMI(4.30000)} , 0, 01383 "The Hague, Netherlands (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01384 {"PT-LIS", {DEG2SEMI(38.71667), DEG2SEMI(-9.13333)} , 0, 01385 "Lisbon, Portugal (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01386 {"ES-MAD", {DEG2SEMI(40.40000), DEG2SEMI(-3.68333)} , 0, 01387 "Madrid, Spain (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01388 {"SE-STO", {DEG2SEMI(59.33333), DEG2SEMI(18.05000)} , 0, 01389 "Stockholm, Sweden (Capital)", 5000.0, sym_lrg_cty, dspl_smbl_only }, 01390 {"GB-LON", {DEG2SEMI(51.50000), DEG2SEMI(-0.11667)} , 0, 01391 "London, United Kingdom (Capital)", 10000.0, sym_lrg_cty, dspl_smbl_only } 01392 }; 01393 01394 // {"BS", {DEG2SEMI(52.2692), DEG2SEMI(10.52111)} , 0, 01395 // "Braunschweig, Germany", 5000.0, sym_med_cty, dspl_smbl_only }; 01396 // {"DE-BWE", {DEG2SEMI(52.319168), DEG2SEMI(10.556167)} , 0, 01397 // "Airport Braunschweig, Germany ICAO:EDVE", 1000.0, sym_airport, 01398 // dspl_smbl_only }; 01399 01400 UInt16 numWaypoints = sizeof(waypoints) / sizeof(waypoints[0]); 01401 UInt16 i; 01402 01403 for (i = 0; i < numWaypoints; i++) { 01404 UInt16 index; 01405 MemHandle h; 01406 01407 index = DmFindSortPosition(gWaypointDB, 01408 &waypoints[i], 01409 0 /* newRecordInfo */, 01410 (DmComparF *)CompareWayptIdent /* DmComparF *compar */, 01411 0 /* other */); 01412 01413 h = DmNewRecord(gWaypointDB, &index, 1); 01414 01415 if (h) { 01416 DmReleaseRecord(gWaypointDB, index, false /* dirty */); 01417 PackWaypoint(&waypoints[i], index); 01418 } else { 01419 Die("Cannot create waypoint record (init)!"); 01420 } 01421 } 01422 }