00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef lint
00029
00030 #endif
00031
00032 #include <PalmOS.h>
00033 #include <PalmCompatibility.h>
00034 #include "gtalkRsc.h"
00035 #include "gpslib.h"
00036 #include "gtalk.h"
00037 #include "track.h"
00038 #include "gpsutil.h"
00039 #include "log.h"
00040 #include "dbio.h"
00041 #include "map.h"
00042 #include "ExgMgr.h"
00043
00044 static void DrawSpeed (VoidHand RecH) TRACK_SECTION;
00045 static double TrackDistance(VoidHand RecH, Boolean WithHoles) TRACK_SECTION;
00046
00054 Boolean
00055 TrackFormHandleEvent (EventPtr e)
00056 {
00057 Boolean Edited,
00058 handled = false;
00059 static FormPtr frm;
00060 UInt n;
00061 Object *RecP;
00062 static VoidHand RecH;
00063 UInt category,
00064 attributes;
00065 static UInt MyCategory;
00066 Err error;
00067 FieldPtr fdPtr;
00068 char CategoryName[dmCategoryLength];
00069 RectangleType r;
00070 double dist;
00071
00072 debug_in (GTALKDBG_CALLS, ("->TrackFormHandleEvent(%s)", e->eType > LASTVALIDEVTNAME ?StrIToA(gbuf1,e->eType):EvtNames[e->eType]));
00073 switch (e->eType)
00074 {
00075 case frmOpenEvent:
00076 frm = FrmGetActiveForm ();
00077
00078 error = DmRecordInfo (TrkDB, CurrentRecordIndex, &attributes, NULL, NULL);
00079 MyCategory = attributes & dmRecAttrCategoryMask;
00080 CategoryGetName (TrkDB, MyCategory, CategoryName);
00081 CategorySetTriggerLabel (GetObjPtr (TrkCatPopupID), CategoryName);
00082 if (Prefs.PermTrackIndex == (CurrentRecordIndex + 1))
00083 SetControlValue (TrkSelID, 1);
00084
00085 FrmDrawForm (frm);
00086 GetObjectBounds (TrkDrawingID, &DrawRect);
00087
00088 RecH = DmQueryRecord (TrkDB, CurrentRecordIndex);
00089 if (RecH)
00090 {
00091 RecP = MemHandleLock (RecH);
00092 StrNToField (RecP->d.CustTrkHdr.name, StrLen (RecP->d.CustTrkHdr.name), TrkFdNameID);
00093 MemHandleUnlock (RecH);
00094 }
00095 MapFlags.DrawTrk = 1;
00096 DrawTrack (CurrentRecordIndex, 1, 1);
00097 handled = true;
00098 break;
00099
00100 case penDownEvent:
00101 FrmGetObjectBounds (frm, FrmGetObjectIndex (frm, TrkDrawingID) , &r);
00102 if (RctPtInRectangle (e->screenX, e->screenY, &r)) {
00103 Prefs.PermTrackIndex = CurrentRecordIndex + 1;
00104 MapFlags.AllowedOps = MapOpMapTrack;
00105 FrmGotoForm (MapForm);
00106 handled=true;
00107 }
00108 break;
00109
00110 case menuEvent:
00111 MenuEraseStatus (NULL);
00112 switch (e->data.menu.itemID)
00113 {
00114 case MenuEraseID:
00115 SysCopyStringResource (gbuf1, StrRemoveTrkID);
00116 if (FrmCustomAlert (ConfID, gbuf1, " ?", " "))
00117 {
00118 n = CurrentRecordIndex;
00119 error =
00120 DmSeekRecordInCategory (TrkDB, &CurrentRecordIndex, 1, dmSeekBackward,
00121 *CurrentCategory);
00122 DmRemoveRecord (TrkDB, n);
00123 MainListDirty = 1;
00124 FrmReturnToForm (0);
00125 }
00126 break;
00127
00128 case MenuSpProfID:
00129 DrawSpeed (RecH);
00130 break;
00131
00132 case MenuTrkDistID: {
00133 FormPtr fp = NULL;
00134 fp = FrmInitForm (WaitForm);
00135 FrmDrawForm (fp);
00136 dist=TrackDistance(RecH,0);
00137 n=StrPrintF (gbuf1, "%s", DToA(dist,0,1));
00138 dist=TrackDistance(RecH,1);
00139 n+=StrPrintF (gbuf1+n, "/%s %s", DToA(dist,0,1), DistanceUnitNames[Prefs.distunit]);
00140 FrmEraseForm (fp);
00141 FrmDeleteForm (fp);
00142 WinDrawChars (gbuf1, n,1, DrawRect.extent.y);
00143 }
00144 break;
00145
00146 case MenuMapID:
00147 Prefs.PermTrackIndex = CurrentRecordIndex + 1;
00148
00149 MapFlags.AllowedOps = MapOpMapTrack;
00150 FrmGotoForm (MapForm);
00151 break;
00152 #ifdef BEAM
00153 case MenuBeamID:
00154 {
00155 ExgSocketType sock;
00156 RecordSeparator RecSep;
00157 void *RecP;
00158 ULong len;
00159
00160 if (!RecH) break;
00161 RecP = MemHandleLock (RecH);
00162 MemSet (&sock, sizeof (sock), 0);
00163 sock.target = GPilotSID;
00164 sock.count = 1;
00165 sock.length = MemHandleSize (RecH);
00166 sock.appData = DispTrk;
00167 sock.time = DispTrk;
00168 sock.description = "Track";
00169 sock.name = BeamTypes[DispTrk];
00170
00171 RecSep.length = MemHandleSize (RecH);
00172 RecSep.reserved = 0;
00173
00174 error = ExgPut (&sock);
00175 if (!error)
00176 {
00177 len=ExgSend (&sock, &RecSep, sizeof (RecSep), &error);
00178 len=0;
00179 while (!error && len < MemHandleSize (RecH)){
00180 len+=ExgSend (&sock, RecP, MemHandleSize (RecH), &error);
00181 }
00182 error=ExgDisconnect (&sock, error);
00183 }
00184 MemHandleUnlock (RecH);
00185 }
00186 break;
00187 #endif
00188
00189 case MenuPrefID:
00190 SetPreferences ();
00191 MainListDirty = 1;
00192 break;
00193
00194 case MenuAboutID:
00195 FrmAlert (idAbout);
00196 break;
00197 }
00198 handled = true;
00199 break;
00200
00201 case ctlSelectEvent:
00202 switch (e->data.ctlSelect.controlID)
00203 {
00204 case TrkBtOKID:
00205 fdPtr = (FieldPtr) (GetObjPtr (TrkFdNameID));
00206 if (FldDirty (fdPtr) && (RecH = DmGetRecord (TrkDB, CurrentRecordIndex)))
00207 {
00208 RecP = MemHandleLock (RecH);
00209 n = FldGetTextLength (fdPtr);
00210 if (n >= sizeof (RecP->d.CustTrkHdr.name))
00211 n = sizeof (RecP->d.CustTrkHdr.name) - 1;
00212 DmWrite (RecP, OffsetOf (Object, d.CustTrkHdr.name), FldGetTextPtr (fdPtr), n + 1);
00213 MemHandleUnlock (RecH);
00214 DmReleaseRecord (TrkDB, CurrentRecordIndex, 1);
00215 MainListDirty = 1;
00216 }
00217 if (CurrentRecordIndex != dmMaxRecordIndex)
00218 error = SetCategory (TrkDB, CurrentRecordIndex, MyCategory);
00219
00220 case BtCancelID:
00221 FrmReturnToForm (0);
00222 handled = true;
00223 break;
00224
00225 #if 0
00226 case TrkBtDeleteID:
00227 SysCopyStringResource (gbuf1, StrRemoveTrkID);
00228 if (FrmCustomAlert (ConfID, gbuf1, " ?", " "))
00229 {
00230 n = CurrentRecordIndex;
00231 error =
00232 DmSeekRecordInCategory (TrkDB, &CurrentRecordIndex, 1, dmSeekBackward,
00233 *CurrentCategory);
00234 DmRemoveRecord (TrkDB, n);
00235 MainListDirty = 1;
00236
00237 FrmReturnToForm (0);
00238 }
00239 handled = true;
00240 break;
00241
00242 case TrkMapID:
00243 Prefs.PermTrackIndex = CurrentRecordIndex + 1;
00244 MapFlags.AllowedOps = 0;
00245 FrmGotoForm (MapForm);
00246 handled = true;
00247 break;
00248 #endif
00249 case TrkSelID:
00250 Prefs.PermTrackIndex = e->data.ctlSelect.on ? CurrentRecordIndex + 1 : 0;
00251
00252
00253 MainListDirty = 1;
00254 handled = true;
00255 break;
00256 #if 0
00257 case TrkSpdID:
00258 DrawSpeed (RecH);
00259 handled = true;
00260 break;
00261 #endif
00262 case TrkCatPopupID:
00263 category = MyCategory;
00264 Edited =
00265 CategorySelect (TrkDB, frm, TrkCatPopupID, TrkCatListID, false, &MyCategory,
00266 CtlGetLabel (e->data.ctlSelect.pControl), 1, 0);
00267
00268
00269
00270 handled = true;
00271 break;
00272 }
00273 break;
00274
00275 default:
00276 break;
00277 }
00278
00279 debug_out (GTALKDBG_CALLS, ("<-TrackFormHandleEvent()=%d", handled));
00280 return handled;
00281 }
00282
00283
00291 static void DrawSpeed (VoidHand RecH)
00292 {
00293 #define DRAWW 128
00294 #define DRAWH 90
00295 #define DRAWX 20
00296 #define DRAWY 15
00297 #define DISPELT 10 // minimum space between lines
00298 #define TIMEOFFSET 15
00299
00300 Object *RecP;
00301 Custom_Trk_Point_Type *ht=NULL;
00302 unsigned long prevlat = 0,
00303 prevlon = 0,
00304 prevtime = 0,
00305 elapsedtime = 0,
00306 t0 = 0;
00307 double dist = 0;
00308 float f,
00309 pu=0;
00310 FormPtr frm;
00311 DateTimeType dtp;
00312 static char date[dateStringLength];
00313 static char time[timeStringLength];
00314
00315 UInt n,m,
00316 k,
00317 i,l,
00318 prevxtime,
00319 U = DRAWH/DISPELT,
00320 speed,
00321 speeds[DRAWW],
00322 maxspeed = 0;
00323
00324 if (!RecH)
00325 return;
00326 frm = FrmInitForm (ChartForm);
00327
00328 FrmDrawForm(frm);
00329
00330 n = TrkptsInTrkDB (RecH);
00331 k = (n-1) / DRAWW + 1;
00332 RecP = MemHandleLock (RecH);
00333 WinDrawChars (RecP->d.CustTrkHdr.name,StrLen (RecP->d.CustTrkHdr.name),45, 1);
00334 SysCopyStringResource (gbuf1, StrNoTimeInTrack);
00335 if (RecP->d.CustTrkHdr.type == CompactTrkPt) {
00336
00337 WinDrawChars (gbuf1, StrLen (gbuf1), 2, 50);
00338 n=0;
00339 }
00340 else {
00341 ht = (Custom_Trk_Point_Type *) ((void *) RecP + SizeOfObject (RecP));
00342 if (ht->time==0) {
00343
00344 WinDrawChars (gbuf1, StrLen (gbuf1),DRAWX, 50);
00345 n=0;
00346 }
00347 }
00348 if(n>=2) {
00349 t0=ht->time;
00350 elapsedtime=(ht+n-1)->time-t0;
00351
00352 TimSecondsToDateTime (GarminTime2PalmSeconds (t0), &dtp);
00353 DateToAscii (dtp.month, dtp.day, dtp.year, dfDMYWithDashes, date);
00354 TimeToAscii (dtp.hour, dtp.minute, tfColon24h, time);
00355 WinDrawChars (date,StrLen (date),5, DRAWY+DRAWH+TIMEOFFSET+3);
00356 WinDrawChars (time,StrLen (time),5, DRAWY+DRAWH+TIMEOFFSET+3+FntCharHeight());
00357 WinDrawChars ("UTC",3, 5, DRAWY+DRAWH+TIMEOFFSET+3+2*FntCharHeight());
00358 TimSecondsToDateTime (GarminTime2PalmSeconds ((ht+n-1)->time), &dtp);
00359 DateToAscii (dtp.month, dtp.day, dtp.year, dfDMYWithDashes, date);
00360 TimeToAscii (dtp.hour, dtp.minute, tfColon24h, time);
00361 WinDrawChars (date,StrLen (date),DRAWX+DRAWW-20, DRAWY+DRAWH+TIMEOFFSET+3);
00362 WinDrawChars (time,StrLen (time),DRAWX+DRAWW-20, DRAWY+DRAWH+TIMEOFFSET+3+FntCharHeight());
00363 }
00364 else n=0;
00365 prevlat = ht->posn.lat;
00366 prevlon = ht->posn.lon;
00367 prevtime = ht->time;
00368 prevxtime=DRAWX;
00369
00370 for (i = 1; i < n; i++, ht++)
00371 {
00372 if (ht->new_trk)
00373 {
00374 WinDrawGrayLine (DRAWX + (i-1) / k, DRAWY+DRAWH,
00375 DRAWX + ((float)DRAWW*(float)(prevtime-t0))/(float)elapsedtime, DRAWY+DRAWH+TIMEOFFSET);
00376 WinDrawGrayLine (DRAWX + i / k, DRAWY+DRAWH,
00377 DRAWX + ((float)DRAWW*(float)(ht->time-t0))/(float)elapsedtime, DRAWY+DRAWH+TIMEOFFSET);
00378
00379
00380
00381 prevtime = ht->time;
00382 dist = 0;
00383 prevxtime=DRAWX + ((float)DRAWW*(float)(ht->time-t0))/(float)elapsedtime;
00384 }
00385 else
00386 {
00387 dist += Distance (prevlat, prevlon, ht->posn.lat, ht->posn.lon, Prefs.distunit);
00388 }
00389
00390 if (!(i % k))
00391 {
00392 speed = ht->time == prevtime ? 0 :
00393 (UInt) (dist / (double) (ht->time - prevtime) * 36000. + 0.5);
00394 speeds[i / k] = speed;
00395
00396 if (speed > maxspeed)
00397 maxspeed = speed;
00398 prevtime = ht->time;
00399 dist = 0;
00400 WinDrawLine (DRAWX + i / k, DRAWY+DRAWH, DRAWX + i / k, DRAWY+DRAWH);
00401 WinDrawLine(prevxtime, DRAWY+DRAWH+TIMEOFFSET,
00402 DRAWX + ((float)DRAWW*(float)(ht->time-t0))/(float)elapsedtime, DRAWY+DRAWH+TIMEOFFSET);
00403 prevxtime=DRAWX + ((float)DRAWW*(float)(ht->time-t0))/(float)elapsedtime;
00404 }
00405 prevlat = ht->posn.lat;
00406 prevlon = ht->posn.lon;
00407 }
00408 MemHandleUnlock (RecH);
00409 if (n){
00410
00411
00412 WinDrawGrayLine (DRAWX + (i-1) / k, DRAWY+DRAWH,
00413 DRAWX + DRAWW , DRAWY+DRAWH+TIMEOFFSET);
00414 for (f=1e-6;f<1e6;f*=10.){
00415 pu=f;m=1;
00416 if ((pu*U)>=maxspeed)break;
00417 pu=f*2.;m=2;
00418 if ((pu*U)>=maxspeed)break;
00419 pu=f*5.;m=5;
00420 if ((pu*U)>=maxspeed)break;
00421 }
00422 WinDrawLine (DRAWX, DRAWY+DRAWH, DRAWX, DRAWY);
00423 for(i=0;i<=(U);i++) {
00424 WinDrawLine (DRAWX-2, DRAWY+DRAWH-(i*DISPELT),
00425 DRAWX,DRAWY+DRAWH-(i*DISPELT) );
00426 WinDrawGrayLine (DRAWX, DRAWY+DRAWH-(i*DISPELT),
00427 DRAWX+DRAWW, DRAWY+DRAWH-(i*DISPELT) );
00428 l=StrPrintF (gbuf1, "%s", DToA(pu*i/10.,0,1));
00429 WinDrawChars (gbuf1, StrLen (gbuf1),DRAWX-FntCharsWidth(gbuf1,l)-2, DRAWY+DRAWH-FntCharHeight()/2-(i*DISPELT));
00430 }
00431
00432 f=(float)DRAWH/(pu*U);
00433 for (i = 1; (i * k) < n; i++)
00434 WinDrawLine (DRAWX + i, DRAWY+DRAWH, DRAWX + i, DRAWY+DRAWH - (long) (speeds[i] * f) );
00435 StrPrintF (gbuf1, "%s/h", DistanceUnitNames[Prefs.distunit]);
00436 WinDrawChars (gbuf1, StrLen (gbuf1), 1, 1);
00437 }
00438 FrmDoDialog (frm) ;
00439 FrmDeleteForm (frm);
00440 }
00441
00442
00451 static double TrackDistance(VoidHand RecH, Boolean WithHoles){
00452 UInt n,i;
00453 Custom_Trk_Point_Type *ht;
00454 double dist = 0;
00455 Object *RecP;
00456 unsigned long prevlat = 0,
00457 prevlon = 0;
00458 static VoidHand oldRecH;
00459 static double distwithholes, distwithoutholes;
00460 static UInt oldcount;
00461
00462 if (!RecH)
00463 return(0.0);
00464 n = TrkptsInTrkDB (RecH);
00465 if ( (RecH==oldRecH) && (n==oldcount))
00466 return (WithHoles?distwithholes:distwithoutholes);
00467 oldcount=n;
00468 oldRecH=RecH;
00469 distwithholes= distwithoutholes=0.0;
00470 RecP = MemHandleLock (RecH);
00471 ht = (Custom_Trk_Point_Type *) ((void *) RecP + SizeOfObject (RecP));
00472 prevlat = ht->posn.lat;
00473 prevlon = ht->posn.lon;
00474 if(n>=2)for (i = 1; i < n; i++, ht++)
00475 {
00476 dist = Distance (prevlat, prevlon, ht->posn.lat, ht->posn.lon, Prefs.distunit);
00477 distwithholes+=dist;
00478 if (!(ht->new_trk) ) distwithoutholes +=dist;
00479 prevlat = ht->posn.lat;
00480 prevlon = ht->posn.lon;
00481 }
00482 MemHandleUnlock (RecH);
00483
00484 return(WithHoles?distwithholes:distwithoutholes);
00485 }
00486
00487
00488 #ifdef EXPORT
00489
00490 ExportTrack(){
00491 double latitude,
00492 longitude;
00493 char *p;
00494
00495 memo_open ("Track\n");
00496 m_speed=Distance (prevlat, prevlon, ht->posn.lat, ht->posn.lon, Prefs.distunit)/(double) (ht->time - m_prevtime) * 3600.;
00497 SemiToDegre (&ht->posn, &latitude, &longitude);
00498 p = DegreToChars (latitude, 0, Prefs.displaymode);
00499 l = StrPrintF (gbuf1, "T%s\t",ht->new_trk?">":" ", p);
00500 p = DegreToChars (longitude, 1, Prefs.displaymode);
00501 l += StrPrintF (gbuf1 + l, "%ld, s=%s\n",ht->time-m_prevtime,DToA(m_speed,0,2) );
00502 memo_write (gbuf1);
00503 m_prevtime=ht->time;
00504 memo_close (NULL);
00505 }
00506 #endif