bool LoadCupTask(LPCTSTR szFileName) { // LockTaskData(); mapCode2Waypoint_t mapWaypoint; // ClearTask(); size_t idxTP = 0; bool bTakeOff = true; bool bLoadComplet = true; bool bLastInvalid=true; TCHAR szString[READLINE_LENGTH + 1]; TCHAR TpCode[NAME_SIZE + 1]; szString[READLINE_LENGTH] = _T('\0'); TpCode[NAME_SIZE] = _T('\0'); memset(szString, 0, sizeof (szString)); // clear Temp Buffer WAYPOINT newPoint = {0}; WAYPOINT* WPtoAdd=NULL; enum { none, Waypoint, TaskTp, Option } FileSection = none; zzip_stream stream(szFileName, "rt"); iNO_Tasks =0; TaskIndex =0; for (int i =0 ; i< MAX_TASKS;i++) szTaskStrings[ i] = NULL; #define MULTITASKS_CUP #ifdef MULTITASKS_CUP if (stream) { while (stream.read_line(szString)) { if ((FileSection == none) && ((_tcsncmp(_T("name,code,country"), szString, 17) == 0) || (_tcsncmp(_T("Title,Code,Country"), szString, 18) == 0))) { FileSection = Waypoint; continue; } else if ((FileSection == Waypoint) && (_tcscmp(szString, _T("-----Related Tasks-----")) == 0)) { FileSection = TaskTp; continue; } if( FileSection == TaskTp) { if(_tcsstr(szString, _T("\",\""))!= NULL) // really a task? (not an option) { if(iNO_Tasks < MAX_TASKS) // Space in List left {//[READLINE_LENGTH + 1]; szTaskStrings[ iNO_Tasks] = new TCHAR[READLINE_LENGTH + 1]; if( szTaskStrings[ iNO_Tasks] != NULL) { _tcscpy(szTaskStrings[ iNO_Tasks] , szString); // copy task string // StartupStore(_T("..Cup Task : %s %s"), szTaskStrings[ iNO_Tasks], NEWLINE); iNO_Tasks++; } else StartupStore(_T("..Cup Task: no memory %s"), NEWLINE); } else StartupStore(_T("..Cup Task Too many Tasks (more than %i) %s"), MAX_TASKS, NEWLINE); } } } stream.close(); StartupStore(_T("..Cup Selected Task:%i %s %s"), TaskIndex, szTaskStrings[ TaskIndex] , NEWLINE); } int res = 0; if(iNO_Tasks >1) // Selection only if more than one task found res = dlgTaskSelectListShowModal(); for (int i =0 ; i< MAX_TASKS;i++) // free dynamic memory if(szTaskStrings[i] != NULL) { // StartupStore(_T("..Cup Task : delete dynamic memoryLine %i %s"), i,NEWLINE); delete[] szTaskStrings[i]; szTaskStrings[i] = NULL; } if(res == mrCancel) return false; /***********************************************************************************/ LockTaskData(); ClearTask(); stream.open(szFileName, "rt"); #endif FileSection = none; int i=0; if (stream) { while (stream.read_line(szString)) { if ((FileSection == none) && ((_tcsncmp(_T("name,code,country"), szString, 17) == 0) || (_tcsncmp(_T("Title,Code,Country"), szString, 18) == 0))) { FileSection = Waypoint; continue; } else if ((FileSection == Waypoint) && (_tcscmp(szString, _T("-----Related Tasks-----")) == 0)) { FileSection = TaskTp; continue; } TCHAR *pToken = NULL; TCHAR *pWClast = NULL; switch (FileSection) { case Waypoint: memset(&newPoint, 0, sizeof(newPoint)); if (ParseCUPWayPointString(szString, &newPoint)) { mapWaypoint[newPoint.Name] = newPoint; } break; case TaskTp: // 1. Description // First column is the description of the task. If filled it should be double quoted. // If left empty, then SeeYou will determine the task type on runtime. if ((pToken = strsep_r(szString, TEXT(","), &pWClast)) == NULL) { // UnlockTaskData(); // no need to skip if only name missing!!! // return false; } // 2. and all successive columns, separated by commas // Each column represents one waypoint name double quoted. The waypoint name must be exactly the // same as the Long name of a waypoint listed above the Related tasks. WPtoAdd=NULL; if (i++ == TaskIndex) // load selected task { while (bLoadComplet && (pToken = strsep_r(NULL, TEXT(","), &pWClast)) != NULL) { if (idxTP < MAXTASKPOINTS) { _tcsncpy(TpCode, pToken, NAME_SIZE); CleanCupCode(TpCode); mapCode2Waypoint_t::iterator It = mapWaypoint.find(TpCode); if(!ISGAAIRCRAFT) { if (It != mapWaypoint.end()) { if (bTakeOff) { // skip TakeOff Set At Home Waypoint int ix = FindOrAddWaypoint(&(It->second),false); if (ix>=0) { #if 0 // REMOVE // We must not change HomeWaypoint without user knowing! // The takeoff and homewaypoint are independent from task. // In addition, this is a bug because on next run the index is invalid // and we have no more HowWaypoint! HomeWaypoint = ix; #endif bTakeOff = false; } #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } else { int ix = FindOrAddWaypoint(&(It->second),false); if (ix>=0) Task[idxTP++].Index = ix; #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } bLastInvalid=false; } else { // An invalid takeoff, probably a "???" , which we ignore #if TESTBENCH if (bTakeOff) StartupStore(_T("....... CUP Takeoff not found: <%s>\n"),TpCode); #endif // in any case bTakeOff now is false bTakeOff=false; bLastInvalid=true; } } else { //ISGAIRRCRAFT if(It != mapWaypoint.end()) { if(WPtoAdd!=NULL) { //add what we found in previous cycle: it was not the last one int ix = FindOrAddWaypoint(WPtoAdd,false); if (ix>=0) Task[idxTP++].Index = ix; #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } if (bTakeOff) { //it's the first: may be we have a corresponding airfield //look for departure airfield and add it int ix = FindOrAddWaypoint(&(It->second),true); if (ix>=0) { Task[idxTP++].Index = ix; bTakeOff = false; } #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } else WPtoAdd=&(It->second); //store it for next cycle (may be it is the last one) } } } else { bLoadComplet = false; } } if(ISGAAIRCRAFT) { //For GA: check if we have an airport corresponding to the last WP if(WPtoAdd!=NULL) { //if we have the last one (probably an airfield) still to add... if(idxTP<MAXTASKPOINTS) { int ix=FindOrAddWaypoint(WPtoAdd,true); //look for arrival airport and add it if (ix>=0) { Task[idxTP++].Index= ix; } #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } else bLoadComplet=false; } } FileSection = Option; } break; case Option: if ((pToken = strsep_r(szString, TEXT(","), &pWClast)) != NULL) { if (_tcscmp(pToken, _T("Options")) == 0) { while ((pToken = strsep_r(NULL, TEXT(","), &pWClast)) != NULL) { if (_tcsstr(pToken, _T("NoStart=")) == pToken) { // Opening of start line PGNumberOfGates = 1; StrToTime(pToken + 8, &PGOpenTimeH, &PGOpenTimeM); } else if (_tcsstr(pToken, _T("TaskTime=")) == pToken) { // Designated Time for the task // TODO : } else if (_tcsstr(pToken, _T("WpDis=")) == pToken) { // Task distance calculation. False = use fixes, True = use waypoints // TODO : } else if (_tcsstr(pToken, _T("NearDis=")) == pToken) { // Distance tolerance // TODO : } else if (_tcsstr(pToken, _T("NearAlt=")) == pToken) { // Altitude tolerance // TODO : } else if (_tcsstr(pToken, _T("MinDis=")) == pToken) { // Uncompleted leg. // False = calculate maximum distance from last observation zone. // TODO : } else if (_tcsstr(pToken, _T("RandomOrder=")) == pToken) { // if true, then Random order of waypoints is checked // TODO : } else if (_tcsstr(pToken, _T("MaxPts=")) == pToken) { // Maximum number of points // TODO : } else if (_tcsstr(pToken, _T("BeforePts=")) == pToken) { // Number of mandatory waypoints at the beginning. 1 means start line only, two means // start line plus first point in task sequence (Task line). // TODO : } else if (_tcsstr(pToken, _T("AfterPts=")) == pToken) { // Number of mandatory waypoints at the end. 1 means finish line only, two means finish line // and one point before finish in task sequence (Task line). // TODO : } else if (_tcsstr(pToken, _T("Bonus=")) == pToken) { // Bonus for crossing the finish line // TODO : } } } else if (_tcsstr(pToken, _T("ObsZone=")) == pToken) { TCHAR *sz = NULL; CupObsZoneUpdater TmpZone; TmpZone.mIdx = _tcstol(pToken + 8, &sz, 10); if (TmpZone.mIdx < MAXTASKPOINTS) { while ((pToken = strsep_r(NULL, TEXT(","), &pWClast)) != NULL) { if (_tcsstr(pToken, _T("Style=")) == pToken) { // Direction. 0 - Fixed value, 1 - Symmetrical, 2 - To next point, 3 - To previous point, 4 - To start point TmpZone.mType = _tcstol(pToken + 6, &sz, 10); } else if (_tcsstr(pToken, _T("R1=")) == pToken) { // Radius 1 TmpZone.mR1 = ReadLength(pToken + 3); } else if (_tcsstr(pToken, _T("A1=")) == pToken) { // Angle 1 in degrees TmpZone.mA1 = _tcstod(pToken + 3, &sz); } else if (_tcsstr(pToken, _T("R2=")) == pToken) { // Radius 2 TmpZone.mR2 = ReadLength(pToken + 3); } else if (_tcsstr(pToken, _T("A2=")) == pToken) { // Angle 2 in degrees TmpZone.mA2 = _tcstod(pToken + 3, &sz); } else if (_tcsstr(pToken, _T("A12=")) == pToken) { // Angle 12 TmpZone.mA12 = _tcstod(pToken + 4, &sz); } else if (_tcsstr(pToken, _T("Line=")) == pToken) { // true For Line Turmpoint type // Exist only for start an Goalin LK TmpZone.mLine = (_tcstol(pToken + 5, &sz, 10) == 1); } } TmpZone.UpdateTask(); } } } break; case none: default: break; } memset(szString, 0, sizeof (szString)); // clear Temp Buffer } } if(!ISGAAIRCRAFT) { // Landing don't exist in LK Task Systems, so Remove It; if ( bLoadComplet && !bLastInvalid ) { RemoveTaskPoint(getFinalWaypoint()); } } UnlockTaskData(); for (mapCode2Waypoint_t::iterator It = mapWaypoint.begin(); It != mapWaypoint.end(); ++It) { if (It->second.Comment) { free(It->second.Comment); } if (It->second.Details) { free(It->second.Details); } } mapWaypoint.clear(); return ValidTaskPoint(0); }
// returns -1 if error, or the WpFileType int ReadWayPointFile(ZZIP_FILE *fp, TCHAR *CurrentWpFileName) { WAYPOINT *new_waypoint; TCHAR szTemp[100]; DWORD fSize, fPos=0; int nLineNumber=0; short fileformat=LKW_DAT; HWND hProgress; hProgress = CreateProgressDialog(gettext(TEXT("_@M903_"))); // Loading Waypoints File... fSize = zzip_file_size(fp); fileformat=GetWaypointFileFormatType(CurrentWpFileName); if (fileformat<0) { StartupStore(_T("... Unknown file format in waypoint file <%s\n"),CurrentWpFileName); // We do NOT return, because first we analyze the content. } if (fSize <10) { StartupStore(_T("... ReadWayPointFile: waypoint file %s type=%d is empty%s"), CurrentWpFileName,fileformat,NEWLINE); return -1; } if (!AllocateWaypointList()) { StartupStore(_T("!!!!!! ReadWayPointFile: AllocateWaypointList FAILED%s"),NEWLINE); return -1; } new_waypoint = WayPointList+NumberOfWayPoints; memset(nTemp2String, 0, sizeof(nTemp2String)); // clear Temp Buffer // check file format bool fempty=true; int slen=0; // 100204 WIP while ( ReadString(fp,READLINE_LENGTH,nTemp2String) ) { slen=_tcslen(nTemp2String); if (slen<1) continue; if ( _tcsncmp(_T("G WGS 84"),nTemp2String,9) == 0 || _tcsncmp(_T("G WGS 84"),nTemp2String,8) == 0 || // consider UCS header, 3 bytes in fact. This is a workaround. _tcsncmp(_T("G WGS 84"),&nTemp2String[3],9) == 0) { if ( !ReadString(fp,READLINE_LENGTH,nTemp2String) ) { StartupStore(_T(". Waypoint file %d format: CompeGPS truncated, rejected%s"),globalFileNum+1,NEWLINE); return -1; } slen=_tcslen(nTemp2String); if (slen<1) { StartupStore(_T(". Waypoint file %d format: CompeGPS MISSING second U line, rejected%s"),globalFileNum+1,NEWLINE); return -1; } if ( (_tcsncmp(_T("U 0"),nTemp2String,4) == 0) || (_tcsncmp(_T("U 0"),nTemp2String,3) == 0)) { StartupStore(_T(". Waypoint file %d format: CompeGPS with UTM coordinates UNSUPPORTED%s"),globalFileNum+1,NEWLINE); return -1; } if ( _tcsncmp(_T("U 1"),nTemp2String,4) != 0 && _tcsncmp(_T("U 1"),nTemp2String,3) != 0 ) { StartupStore(_T(". Waypoint file %d format: CompeGPS unknown U field, rejected%s"),globalFileNum+1,NEWLINE); return -1; } StartupStore(_T(". Waypoint file %d format: CompeGPS, LatLon coordinates%s"),globalFileNum+1,NEWLINE); fempty=false; fileformat=LKW_COMPE; break; } if ( (_tcsncmp(_T("name,code,country"),nTemp2String,17) == 0) || (_tcsncmp(_T("Title,Code,Country"),nTemp2String,18) == 0) // 100314 ) { StartupStore(_T(". Waypoint file %d format: SeeYou%s"),globalFileNum+1,NEWLINE); fempty=false; fileformat=LKW_CUP; break; } if ( ( _tcsstr(nTemp2String, _T("OziExplorer Waypoint File")) == nTemp2String )|| // consider UCS header, 3 bytes in fact. This is a workaround. (_tcsstr(&nTemp2String[3], _T("OziExplorer Waypoint File")) == &nTemp2String[3]) ) { StartupStore(_T(". Waypoint file %d format: OziExplorer%s"),globalFileNum+1,NEWLINE); fempty=false; fileformat=LKW_OZI; break; } // consider also the case of empty file, when a waypoint if saved starting with numbering after // the virtual wps (including the 0); // Warning, using virtualdatheader 3 tcsncmp because virtuals are now more than 9. TCHAR virtualdatheader[5]; wsprintf(virtualdatheader,_T("%d,"),RESWP_END+2); if ( _tcsncmp(_T("1,"),nTemp2String,2) == 0 || _tcsncmp(virtualdatheader,nTemp2String,3) == 0) { StartupStore(_T(". Waypoint file %d format: WinPilot%s"),globalFileNum+1,NEWLINE); fempty=false; fileformat=LKW_DAT; break; } // Otherwise we use the fileformat .xxx suffix. // Why we did not do it since the beginning? Simply because we should not rely on .xxx suffix // because some formats like CompeGPS and OZI, for example, share the same .WPT suffix. // if (fileformat<0) { StartupStore(_T(".. Unknown WP header, unknown format in <%s>%s"),nTemp2String,NEWLINE); // leaving fempty true, so no good file available break; } else { fempty=false; StartupStore(_T(".. Unknown WP header, using format %d. Header: <%s>%s"),fileformat,nTemp2String,NEWLINE); break; } } if (fempty) { return -1; } // SetFilePointer(hFile,0,NULL,FILE_BEGIN); fPos = 0; // a real shame, too lazy to change into do while loop // Skip already read lines containing header, unless we are using DAT, which has no header if ( fileformat==LKW_DAT) goto goto_inloop; memset(nTemp2String, 0, sizeof(nTemp2String)); // clear Temp Buffer while(ReadString(fp, READLINE_LENGTH, nTemp2String)){ goto_inloop: nLineNumber++; nTemp2String[READLINE_LENGTH]=_T('\0'); nTemp2String[READLINE_LENGTH-1]=_T('\n'); nTemp2String[READLINE_LENGTH-2]=_T('\r'); fPos += _tcslen(nTemp2String); if (_tcsstr(nTemp2String, TEXT("**")) == nTemp2String) // Look For Comment continue; if (_tcsstr(nTemp2String, TEXT("*")) == nTemp2String) // Look For SeeYou Comment continue; if (nTemp2String[0] == '\0') continue; new_waypoint->Details = NULL; new_waypoint->Comment = NULL; if ( fileformat == LKW_DAT || fileformat== LKW_XCW ) { if (ParseDAT(nTemp2String, new_waypoint)) { if ( (_tcscmp(new_waypoint->Name, gettext(TEXT(RESWP_TAKEOFF_NAME)))==0) && (new_waypoint->Number==RESWP_ID)) { StartupStore(_T("... FOUND TAKEOFF (%s) INSIDE WAYPOINTS FILE%s"), gettext(TEXT(RESWP_TAKEOFF_NAME)), NEWLINE); memcpy(WayPointList,new_waypoint,sizeof(WAYPOINT)); continue; } if (WaypointInTerrainRange(new_waypoint)) { new_waypoint = GrowWaypointList(); if (!new_waypoint) { return -1; // failed to allocate } new_waypoint++; // we want the next blank one } } } if ( fileformat == LKW_CUP ) { if ( _tcsncmp(_T("-----Related Tasks"),nTemp2String,18)==0) { break; } if (ParseCUPWayPointString(nTemp2String, new_waypoint)) { if ( (_tcscmp(new_waypoint->Name, gettext(TEXT(RESWP_TAKEOFF_NAME)))==0) && (new_waypoint->Number==RESWP_ID)) { StartupStore(_T("... FOUND TAKEOFF (%s) INSIDE WAYPOINTS FILE%s"), gettext(TEXT(RESWP_TAKEOFF_NAME)), NEWLINE); memcpy(WayPointList,new_waypoint,sizeof(WAYPOINT)); continue; } if (WaypointInTerrainRange(new_waypoint)) { new_waypoint = GrowWaypointList(); if (!new_waypoint) { return -1; // failed to allocate } new_waypoint++; // we want the next blank one } } } if ( fileformat == LKW_COMPE ) { if (ParseCOMPEWayPointString(nTemp2String, new_waypoint)) { if ( (_tcscmp(new_waypoint->Name, gettext(TEXT(RESWP_TAKEOFF_NAME)))==0) && (new_waypoint->Number==RESWP_ID)) { StartupStore(_T("... FOUND TAKEOFF (%s) INSIDE WAYPOINTS FILE%s"), gettext(TEXT(RESWP_TAKEOFF_NAME)), NEWLINE); memcpy(WayPointList,new_waypoint,sizeof(WAYPOINT)); continue; } if (WaypointInTerrainRange(new_waypoint)) { new_waypoint = GrowWaypointList(); if (!new_waypoint) { return -1; // failed to allocate } new_waypoint++; // we want the next blank one } } } if(fileformat == LKW_OZI){ // Ignore first four header lines if(nLineNumber <= 3) continue; if(ParseOZIWayPointString(nTemp2String, new_waypoint)){ if ( (_tcscmp(new_waypoint->Name, gettext(TEXT(RESWP_TAKEOFF_NAME)))==0) && (new_waypoint->Number==RESWP_ID)) { StartupStore(_T("... FOUND TAKEOFF (%s) INSIDE WAYPOINTS FILE%s"), gettext(TEXT(RESWP_TAKEOFF_NAME)), NEWLINE); memcpy(WayPointList,new_waypoint,sizeof(WAYPOINT)); continue; } if (WaypointInTerrainRange(new_waypoint)) { new_waypoint = GrowWaypointList(); if (!new_waypoint) { return -1; // failed to allocate } new_waypoint++; // we want the next blank one } } } memset(nTemp2String, 0, sizeof(nTemp2String)); // clear Temp Buffer continue; } if (hProgress) { _stprintf(szTemp,TEXT("100%%")); SetDlgItemText(hProgress,IDC_PROGRESS,szTemp); } return fileformat; }