// Play a sound from filesystem void LKSound(const TCHAR *lpName) { #ifdef DISABLEAUDIO return false; #else static bool doinit=true; static bool working=false; static TCHAR sDir[MAX_PATH]; if (doinit) { TCHAR srcfile[MAX_PATH]; LocalPath(sDir,TEXT(LKD_SOUNDS)); _stprintf(srcfile,TEXT("%s\\_SOUNDS"),sDir); if ( GetFileAttributes(srcfile) == 0xffffffff ) { FailStore(_T("ERROR NO SOUNDS DIRECTORY CHECKFILE <%s>%s"),srcfile,NEWLINE); StartupStore(_T("------ LK8000 SOUNDS NOT WORKING!%s"),NEWLINE); } else working=true; doinit=false; } if (!working) return; TCHAR sndfile[MAX_PATH]; _stprintf(sndfile,_T("%s\\%s"),sDir,lpName); sndPlaySound (sndfile, SND_ASYNC| SND_NODEFAULT ); return; #endif }
// Rescale automatically dialogs, using negative values to force rescaling // Notice: SHOULD BE CALLED ONLY IF rWidth is negative, in order to avoid useless SetWindowPos int RescaleWidth(const int rWidth) { // Always rescale negative widths if (rWidth <-1) { // Special case is when width is also the scale unit, which demonstrate we have a bug to fix here! if (rWidth == (int)(-246*InfoBoxLayout::dscale)){ return LKwdlgConfig; } double i=(246.0 / abs(rWidth)); if (i==0) { FailStore(_T("INTERNAL ERROR RESCALEWIDTH rWidth=%d"),rWidth); DoStatusMessage(_T("RESCALE ERR-001")); return rWidth; } int ri=(int)( (LKwdlgConfig/i) *InfoBoxLayout::dscale ); // StartupStore(_T("... RescaleWidth(): rescale %d to %d\n"),rWidth, ri); if (ri>ScreenSizeX) return(ScreenSizeX); return (ri); } // else use the incoming rWidth but it is clearly an error DoStatusMessage(_T("RESCALE WARN-001")); return rWidth; }
// this is called only when ActiveWayPoint is 0, still waiting for start void CheckStart(NMEA_INFO *Basic, DERIVED_INFO *Calculated, int *LastStartSector) { BOOL StartCrossed= false; if (UseGates()) { #if DEBUGATE StartupStore(_T("... CheckStart Timenow=%d OpenTime=%d CloseTime=%d ActiveGate=%d\n"),LocalTime(),PGOpenTime,PGCloseTime,ActiveGate); #endif int gatetimediff=-1; if ( ActiveGate<0 ) { // init activegate: assign first valid gate, current or future ActiveGate=InitActiveGate(); if (ActiveGate<0||ActiveGate>(PGNumberOfGates-1)) { FailStore(_T("INVALID ActiveGate=%d"),ActiveGate); DoStatusMessage(_T("ERR-430 INVALID ACTIVEGATE: DISABLED")); PGNumberOfGates=0; return; } #if DEBUGATE StartupStore(_T("... CheckStart: INIT ActiveGate=%d\n"),ActiveGate); #endif } else { if (HaveGates()) { gatetimediff=GateTimeDiff(ActiveGate); #if DEBUGATE StartupStore(_T("... CheckStart: ActiveGate=%d RunningGate=%d\n"),ActiveGate,RunningGate()); StartupStore(_T("... CheckStart: gatetimediff=%d\n"),gatetimediff); #endif // a gate can be in the future , or already open! // case: first start, activegate is the first gate if (gatetimediff==0) { #if DEBUGATE StartupStore(_T("... CheckStart: ActiveGate=%d now OPEN\n"),ActiveGate); #endif AlertGateOpen(ActiveGate); // nothing else to do: the current activegate has just open } else { // check that also non-armed start is detected if (ActiveGate<(PGNumberOfGates-1)) { if (GateTimeDiff(ActiveGate+1)==0) { #if DEBUGATE StartupStore(_T("... CheckStart: ActiveGate+1=%d now OPEN\n"),ActiveGate); #endif ActiveGate++; AlertGateOpen(ActiveGate); } } } // now check for special alerts on countdown, only on current armed start if (gatetimediff==3600 && ((PGGateIntervalTime>=70)||ActiveGate==0) ) { // 850 FIRST GATE OPEN IN 1 HOUR DoStatusMessage(gettext(TEXT("_@M850_"))); if (EnableSoundModes) { LKSound(_T("LK_DINGDONG.WAV")); } } if (gatetimediff==1800 && ((PGGateIntervalTime>=45)||ActiveGate==0) ) { // 851 FIRST GATE OPEN IN 30 MINUTES DoStatusMessage(gettext(TEXT("_@M851_"))); if (EnableSoundModes) { LKSound(_T("LK_DINGDONG.WAV")); } } if (gatetimediff==600 && ((PGGateIntervalTime>=15)||ActiveGate==0) ) { // 10 minutes to go // 852 10 MINUTES TO GO DoStatusMessage(gettext(TEXT("_@M852_"))); if (EnableSoundModes) { LKSound(_T("LK_HITONE.WAV")); } } if (gatetimediff==300 && ((PGGateIntervalTime>=10)||ActiveGate==0)) { // 5 minutes to go // 853 5 MINUTES TO GO DoStatusMessage(gettext(TEXT("_@M853_"))); if (EnableSoundModes) { LKSound(_T("LK_HITONE.WAV")); } } if (gatetimediff==60) { // 1 minute to go if (EnableSoundModes) { LKSound(_T("LK_3HITONES.WAV")); } } } // HaveGates } // not init } if (ISPARAGLIDER && PGStartOut) { // start OUT and go in if (!InStartSector(Basic,Calculated,*LastStartSector, &StartCrossed)) { Calculated->IsInSector = false; if (ReadyToStart(Calculated)) { aatdistance.AddPoint(Basic->Longitude, Basic->Latitude, 0); } if (ValidStartSpeed(Basic, Calculated, StartMaxSpeedMargin)) { ReadyToAdvance(Calculated, false, true); } } else Calculated->IsInSector = true; } else { // start IN and go out, OLD CLASSIC MODE if (InStartSector(Basic,Calculated,*LastStartSector, &StartCrossed)) { // InSector check calling this function is resetting IsInSector at each run, so it was false. Calculated->IsInSector = true; if (ReadyToStart(Calculated)) { aatdistance.AddPoint(Basic->Longitude, Basic->Latitude, 0); } // ToLo: we are ready to start even when outside start rules but within margin if (ValidStartSpeed(Basic, Calculated, StartMaxSpeedMargin)) { ReadyToAdvance(Calculated, false, true); } // TODO accuracy: monitor start speed throughout time in start sector } } // end start mode if (StartCrossed && ValidGate() ) { // 100509 #if DEBUGTGATES StartupStore(_T("... CheckStart: start crossed and valid gate!\n")); #endif // ToLo: Check weather speed and height are within the rules or not (zero margin) if(!IsFinalWaypoint() && ValidStartSpeed(Basic, Calculated) && InsideStartHeight(Basic, Calculated)) { // This is set whether ready to advance or not, because it will // appear in the flight log, so if it's valid, it's valid. Calculated->ValidStart = true; if (ReadyToAdvance(Calculated, true, true)) { ActiveWayPoint=0; // enforce this since it may be 1 StartTask(Basic,Calculated, true, true); } if (Calculated->Flying) { Calculated->ValidFinish = false; } // JMW TODO accuracy: This causes Vaverage to go bonkers // if the user has already passed the start // but selects the start // Note: pilot must have armed advance // for the start to be registered // ToLo: If speed and height are outside the rules they must be within the margin... } else { if ((ActiveWayPoint<=1) && !IsFinalWaypoint() && (Calculated->ValidStart==false) && (Calculated->Flying)) { #if 0 // 101014 This is called from wrong thread, and cause bad crashes // moved to new GCE event inside InputEvents - paolo // need to detect bad starts, just to get the statistics // in case the bad start is the best available, or the user // manually started StartTask(Basic, Calculated, false, false); // Calculated->ValidStart = false; bool startTaskAnyway = false; if (ReadyToAdvance(Calculated, true, true)) { dlgStartTaskShowModal(&startTaskAnyway, Calculated->TaskStartTime, Calculated->TaskStartSpeed, Calculated->TaskStartAltitude); if (startTaskAnyway) { ActiveWayPoint=0; // enforce this since it may be 1 StartTask(Basic,Calculated, true, true); } } Calculated->ValidStart = startTaskAnyway; #else // 101014 StartTask(Basic, Calculated, false, false); if (ReadyToAdvance(Calculated, true, true)) { InputEvents::processGlideComputer(GCE_TASK_CONFIRMSTART); } #endif if (Calculated->Flying) { Calculated->ValidFinish = false; } } } } }
HWND CreateProgressDialog(TCHAR* text) { static int yFontSize, xFontSize; HDC hTempDC = NULL; if (doinitprogress) { doinitprogress=false; DWORD Style=0; Style = WS_CHILD | ES_MULTILINE | ES_CENTER | ES_READONLY | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; hStartupWindow=CreateWindow(TEXT("STATIC"), TEXT("\0"), Style, 0, 0, ScreenSizeX, ScreenSizeY, hWndMainWindow, NULL, hInst, NULL); if (hStartupWindow==NULL) { StartupStore(_T("***** CRITIC, no startup window!%s"),NEWLINE); FailStore(_T("CRITIC, no startup window!")); return NULL; } if (!(hStartupDC = GetDC(hStartupWindow))) { StartupStore(_T("------ Cannot state startup window%s"),NEWLINE); FailStore(_T("Cannot state startup window")); return(NULL); } /* SHFullScreen(hProgress, SHFS_HIDETASKBAR |SHFS_HIDESIPBUTTON |SHFS_HIDESTARTICON); SetWindowPos(hProgress,HWND_TOP,0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); */ //RECT rt; //GetClientRect(hStartupWindow,&rt); //FillRect(hStartupDC,&rt,(HBRUSH)GetStockObject(BLACK_BRUSH)); //SetWindowPos(hStartupWindow,HWND_TOP,0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); //SHFullScreen(hStartupWindow, SHFS_HIDETASKBAR |SHFS_HIDESIPBUTTON |SHFS_HIDESTARTICON); //SetForegroundWindow(hStartupWindow); //UpdateWindow(hStartupWindow); ShowWindow(hStartupWindow,SW_SHOWNORMAL); BringWindowToTop(hStartupWindow); // Load welcome screen bitmap HBITMAP hWelcomeBitmap=NULL; TCHAR sDir[MAX_PATH]; TCHAR srcfile[MAX_PATH]; LocalPath(sDir,TEXT(LKD_BITMAPS)); // first look for lkstart_480x272.bmp for example _stprintf(srcfile,_T("%s\\LKSTART_%s.BMP"),sDir, GetSizeSuffix() ); if ( GetFileAttributes(srcfile) == 0xffffffff ) { // no custom file, get a generic one switch(ScreenSize) { case ss800x480: case ss640x480: case ss720x408: case ss896x672: _stprintf(srcfile,_T("%s\\LKSTART_LB.BMP"),sDir); break; case ss480x272: case ss480x234: case ss400x240: case ss320x240: _stprintf(srcfile,_T("%s\\LKSTART_LS.BMP"),sDir); break; case ss480x640: case ss480x800: _stprintf(srcfile,_T("%s\\LKSTART_PB.BMP"),sDir); break; case ss240x320: case ss272x480: _stprintf(srcfile,_T("%s\\LKSTART_PS.BMP"),sDir); break; default: _stprintf(srcfile,_T("%s\\LKSTART_DEFAULT.BMP"),sDir); break; } } #if (WINDOWSPC>0) hWelcomeBitmap=(HBITMAP)LoadImage(GetModuleHandle(NULL),srcfile,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); #else hWelcomeBitmap=(HBITMAP)SHLoadDIBitmap(srcfile); #endif // still nothing? use internal (poor man) resource if (hWelcomeBitmap==NULL) hWelcomeBitmap=LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SWIFT)); hTempDC = CreateCompatibleDC(hStartupDC); // AA HBITMAP oldBitmap = (HBITMAP)SelectObject(hTempDC, hWelcomeBitmap); SelectObject(hTempDC, LKSTARTBOTTOMFONT); SIZE TextSize; GetTextExtentPoint(hTempDC, _T("X"),1, &TextSize); yFontSize = TextSize.cy; xFontSize = TextSize.cx; BITMAP bm; GetObject(hWelcomeBitmap,sizeof(bm), &bm); StretchBlt(hStartupDC,0,0, ScreenSizeX,ScreenSizeY-1, hTempDC, 0, 0, 2,2, BLACKNESS); if ( (bm.bmWidth >ScreenSizeX)||(bm.bmHeight>ScreenSizeY)) { StretchBlt(hStartupDC,0,0, ScreenSizeX,ScreenSizeY-NIBLSCALE(2)-(yFontSize*2)-1, hTempDC, 0, 0, bm.bmWidth,bm.bmHeight, SRCCOPY); } else { BitBlt(hStartupDC,(ScreenSizeX-bm.bmWidth)/2,0,bm.bmWidth,bm.bmHeight,hTempDC, 0, 0, SRCCOPY); } DeleteObject(hWelcomeBitmap); // AA SelectObject(hTempDC, oldBitmap); if (DeleteDC(hTempDC)==0) StartupStore(_T("**** Cannot delete hTempDC\n")); } BringWindowToTop(hStartupWindow); // we shall return here also on shutdown and file reloads // RECT is left, top, right, bottom RECT PrintAreaR; PrintAreaR.left = NIBLSCALE(2); PrintAreaR.bottom = ScreenSizeY-NIBLSCALE(2); PrintAreaR.top = PrintAreaR.bottom - (yFontSize*2); PrintAreaR.right = ScreenSizeX - NIBLSCALE(2); HFONT oldFont=(HFONT)SelectObject(hStartupDC,LKSTARTBOTTOMFONT); HBRUSH hB=LKBrush_Petrol; FillRect(hStartupDC,&PrintAreaR, hB); // Create text area // we cannot use LKPen here because they are not still initialised for startup menu. no problem HPEN hP=(HPEN) CreatePen(PS_SOLID,NIBLSCALE(1),RGB_GREEN); SelectObject(hStartupDC,hP); SelectObject(hStartupDC,hB); Rectangle(hStartupDC, PrintAreaR.left,PrintAreaR.top,PrintAreaR.right,PrintAreaR.bottom); DeleteObject(hP); hP=(HPEN) CreatePen(PS_SOLID,NIBLSCALE(1),RGB_BLACK); SelectObject(hStartupDC,hP); Rectangle(hStartupDC, PrintAreaR.left+NIBLSCALE(2),PrintAreaR.top+NIBLSCALE(2),PrintAreaR.right-NIBLSCALE(2),PrintAreaR.bottom-NIBLSCALE(2)); SetTextColor(hStartupDC,RGB_WHITE); SetBkMode(hStartupDC,TRANSPARENT); unsigned int maxchars= (ScreenSizeX/xFontSize)-1; if (_tcslen(text) <maxchars) { maxchars=_tcslen(text); } ExtTextOut(hStartupDC,PrintAreaR.left+(xFontSize/2),PrintAreaR.top + ((PrintAreaR.bottom - PrintAreaR.top)/2)-(yFontSize/2), ETO_OPAQUE,NULL,text,maxchars,NULL); SelectObject(hStartupDC,oldFont); // Sleep(300); // Slow down display of data? No because in case of important things, Sleep is set by calling part DeleteObject(hP); return hStartupWindow; }
// handle custom keys. Input: key pressed (center, left etc.) // Returns true if handled successfully, false if not // // Passthrough mode for keys>=1000 (custom menu keys) // bool CustomKeyHandler(const int key) { int ckeymode; static bool doinit=true; static int oldModeIndex; if (doinit) { oldModeIndex=LKMODE_INFOMODE;; doinit=false; } if (key>=1000) { ckeymode=key-1000; LKASSERT((ckeymode>=0 && ckeymode<ckTOP)); goto passthrough; } switch(key) { case CKI_BOTTOMCENTER: ckeymode=CustomKeyModeCenter; break; case CKI_BOTTOMLEFT: ckeymode=CustomKeyModeLeft; break; case CKI_BOTTOMRIGHT: ckeymode=CustomKeyModeRight; break; case CKI_BOTTOMICON: ckeymode=CustomKeyModeAircraftIcon; break; case CKI_TOPLEFT: ckeymode=CustomKeyModeLeftUpCorner; break; case CKI_TOPRIGHT: ckeymode=CustomKeyModeRightUpCorner; break; case CKI_CENTERSCREEN: ckeymode=CustomKeyModeCenterScreen; break; default: DoStatusMessage(_T("ERR-725 UNKNOWN CUSTOMKEY")); return false; break; } passthrough: switch(ckeymode) { case ckDisabled: break; case ckZoomIn: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif MapWindow::zoom.EventScaleZoom(1); return true; break; case ckZoomInMore: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif MapWindow::zoom.EventScaleZoom(2); return true; break; case ckZoomOut: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif MapWindow::zoom.EventScaleZoom(-1); return true; break; case ckZoomOutMore: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif MapWindow::zoom.EventScaleZoom(-2); return true; break; case ckMenu: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif ShowMenu(); return true; case ckBackMode: PreviousModeIndex(); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckToggleMap: //TODO if (ModeIndex==LKMODE_MAP) SetModeIndex(oldModeIndex); else { oldModeIndex=ModeIndex; SetModeIndex(LKMODE_MAP); } MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckTrueWind: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::setMode(_T("TrueWind")); return true; case ckTeamCode: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventSetup(_T("Teamcode")); return true; case ckToggleOverlays: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif ToggleOverlays(); return true; case ckToggleMapLandable: if (ModeIndex==LKMODE_MAP) SetModeIndex(LKMODE_WP); else SetModeIndex(LKMODE_MAP); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckLandables: SetModeIndex(LKMODE_WP); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckToggleMapCommons: if (ModeIndex==LKMODE_MAP) SetModeIndex(LKMODE_NAV); else SetModeIndex(LKMODE_MAP); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckCommons: SetModeIndex(LKMODE_NAV); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckToggleMapTraffic: if (ModeIndex==LKMODE_MAP) SetModeIndex(LKMODE_TRF); else SetModeIndex(LKMODE_MAP); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckTraffic: SetModeIndex(LKMODE_TRF); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckInvertColors: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventInvertColor(NULL); return true; case ckTimeGates: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventTimeGates(NULL); return true; case ckMarkLocation: InputEvents::eventMarkLocation(_T("")); return true; case ckAutoZoom: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventZoom(_T("auto toggle")); InputEvents::eventZoom(_T("auto show")); return true; case ckActiveMap: InputEvents::eventActiveMap(_T("toggle")); InputEvents::eventActiveMap(_T("show")); return true; case ckBooster: DoStatusMessage(_T("FEEL THE THERMAL")); if (EnableSoundModes) LKSound(_T("LK_BOOSTER.WAV")); return true; case ckGoHome: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif if (ValidWayPoint(HomeWaypoint)) { if ( (ValidTaskPoint(ActiveWayPoint)) && (Task[ActiveWayPoint].Index == HomeWaypoint )) { // LKTOKEN _@M82_ = "Already going home" DoStatusMessage(gettext(TEXT("_@M82_"))); } else { GotoWaypoint(HomeWaypoint); } } else // LKTOKEN _@M465_ = "No Home to go!" DoStatusMessage(gettext(TEXT("_@M465_"))); return true; case ckPanorama: if (PGZoomTrigger==false) PGZoomTrigger=true; else LastZoomTrigger=0; #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif return true; case ckMultitargetRotate: RotateOvertarget(); return true; case ckMultitargetMenu: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::setMode(_T("MTarget")); return true; case ckBaroToggle: ToggleBaroAltitude(); return true; case ckBasicSetup: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventSetup(_T("Basic")); return true; case ckSimMenu: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::setMode(_T("SIMMENU")); return true; case ckToggleMapAirspace: if (ModeIndex==LKMODE_MAP) SetModeType(LKMODE_WP,WP_AIRSPACES); else SetModeIndex(LKMODE_MAP); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckAirspaceAnalysis: SetModeType(LKMODE_MAP,MP_MAPASP); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckOptimizeRoute: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif PGOptimizeRoute=!PGOptimizeRoute; if (ISPARAGLIDER && PGOptimizeRoute) { AATEnabled = true; ClearOptimizedTargetPos(); } return true; case ckLockScreen: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventService(_T("LOCKMODE")); return true; case ckWhereAmI: // no sound here, chime is played by service event InputEvents::eventService(_T("ORACLE")); return true; case ckUseTotalEnergy: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventService(_T("TOTALEN")); return true; case ckNotepad: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventChecklist(_T("")); return true; case ckTerrainColors: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventService(_T("TERRCOL")); return true; case ckNearestAirspace: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventNearestAirspaceDetails(NULL); return true; case ckOlcAnalysis: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventSetup(_T("OlcAnalysis")); return true; case ckTerrainColorsBack: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventService(_T("TERRCOLBACK")); return true; case ckForceFreeFlightRestart: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif if (!CALCULATED_INFO.Flying) { DoStatusMessage(MsgToken(922)); // NOT FLYING } else { if (MessageBoxX(hWndMapWindow, MsgToken(1754), _T(""), MB_YESNO|MB_ICONQUESTION) == IDYES) { LKSW_ForceFreeFlightRestart=true; } } return true; case ckCustomMenu1: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif extern void dlgCustomMenuShowModal(void); InputEvents::eventMode(_T("MYMODE")); return true; case ckTaskCalc: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventCalculator(NULL); return true; case ckTaskTarget: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventSetup(_T("Target")); return true; case ckArmAdvance: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventArmAdvance(_T("toggle")); InputEvents::eventArmAdvance(_T("show")); return true; case ckMessageRepeat: InputEvents::eventRepeatStatusMessage(NULL); return true; case ckWaypointLookup: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventWaypointDetails(_T("select")); return true; case ckPan: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif InputEvents::eventPan(_T("toggle")); return true; case ckWindRose: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif UseWindRose=!UseWindRose; return true; case ckFlarmRadar: SetModeType(LKMODE_MAP,MP_RADAR); MapWindow::RefreshMap(); SoundModeIndex(); return true; case ckDeviceA: if(devA() && devA()->Config) { devA()->Config(); } return true; case ckDeviceB: if(devB() && devB()->Config) { devB()->Config(); } return true; case ckResetOdometer: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif if (MessageBoxX(hWndMapWindow, MsgToken(2229), _T(""), MB_YESNO|MB_ICONQUESTION) == IDYES) { LKSW_ResetOdometer=true; } return true; case ckForceLanding: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif if ( !CALCULATED_INFO.Flying ) { DoStatusMessage(MsgToken(922)); // NOT FLYING } else { if ( (GPS_INFO.Speed > TakeOffSpeedThreshold) && (!GPS_INFO.NAVWarning) ) { DoStatusMessage(MsgToken(1799)); // STOP MOVING! } else { if (MessageBoxX(hWndMapWindow, MsgToken(2230), _T(""), MB_YESNO|MB_ICONQUESTION) == IDYES) { LKSW_ForceLanding=true; } } } return true; case ckResetTripComputer: #ifndef DISABLEAUDIO if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK")); #endif if (MessageBoxX(hWndMapWindow, MsgToken(2236), _T(""), MB_YESNO|MB_ICONQUESTION) == IDYES) { LKSW_ResetTripComputer=true; } return true; case ckSonarToggle: Sonar_IsEnabled = !Sonar_IsEnabled; TCHAR sonarmsg[60]; _stprintf(sonarmsg,_T("%s "),MsgToken(1293)); // SONAR if (Sonar_IsEnabled) _tcscat(sonarmsg,MsgToken(1643)); // ENABLED else _tcscat(sonarmsg,MsgToken(1600)); // DISABLED DoStatusMessage(sonarmsg,NULL,false); if (EnableSoundModes) { if (Sonar_IsEnabled) LKSound(TEXT("LK_TONEUP.WAV")); else LKSound(TEXT("LK_TONEDOWN.WAV")); } return true; default: DoStatusMessage(_T("ERR-726 INVALID CUSTOMKEY")); FailStore(_T("ERR-726 INVALID CUSTOMKEY=%d"),ckeymode); break; } return false; }
//#define DEBUGNPM 1 // run every 5 seconds, approx. void NMEAParser::UpdateMonitor(void) { short active; static short lastactive=0; static bool lastvalidBaro=false; short invalidGps=0; short invalidBaro=0; short validBaro=0; // does anyone have GPS? if (nmeaParser1.gpsValid || nmeaParser2.gpsValid) { if (nmeaParser1.gpsValid && nmeaParser2.gpsValid) { // both valid, just use first nmeaParser2.activeGPS = false; nmeaParser1.activeGPS = true; active=1; } else { nmeaParser1.activeGPS = nmeaParser1.gpsValid; nmeaParser2.activeGPS = nmeaParser2.gpsValid; active= nmeaParser1.activeGPS ? 1 : 2; } } else { // assume device 1 is active nmeaParser2.activeGPS = false; nmeaParser1.activeGPS = true; active=1; } #if 1 // TODO better check if ok if (nmeaParser2.activeGPS==true && active==1) { StartupStore(_T("... GPS Update error: port 1 and 2 are active!%s"),NEWLINE); FailStore(_T("... GPS Update error: port 1 and 2 are active!%s"),NEWLINE); nmeaParser2.activeGPS=false; // force it off active=1; } #endif // wait for some seconds before monitoring, after startup if (LKHearthBeats<20) return; // Check Port 1 with no serial activity in last seconds if ( (LKHearthBeats-ComPortHB[0])>10 ) { #ifdef DEBUGNPM StartupStore(_T("... GPS Port 1 : no activity LKHB=%.0f CBHB=%.0f %s"),LKHearthBeats, ComPortHB[0],NEWLINE); #endif // if this is active and supposed to have a valid fix.., but no HB.. if ( (active==1) && (nmeaParser1.gpsValid) ) { StartupStore(_T("... GPS Port 1 no hearthbeats, but still gpsValid: forced invalid%s"),NEWLINE); } nmeaParser1.gpsValid=false; invalidGps=1; #if DUALBARO // We want to be sure that if this device is silent, and it was providing Baro altitude, // now it is set to off. if (GPS_INFO.BaroAltitudeAvailable==TRUE) { if ( devA() == pDevPrimaryBaroSource || nmeaParser1.RMZAvailable || nmeaParser1.RMAAvailable || nmeaParser1.TASAvailable ) { invalidBaro=1; } } #endif } else { // We have hearth beats, is baro available? if ( devIsBaroSource(devA()) || nmeaParser1.RMZAvailable || nmeaParser1.RMAAvailable || nmeaParser1.TASAvailable ) // 100411 validBaro++; } // now check also port 2 if ( (LKHearthBeats-ComPortHB[1])>10 ) { #ifdef DEBUGNPM StartupStore(_T("... GPS Port 2 : no activity LKHB=%.0f CBHB=%.0f %s"),LKHearthBeats, ComPortHB[1],NEWLINE); #endif if ( (active==2) && (nmeaParser2.gpsValid) ) { StartupStore(_T("... GPS port 2 no hearthbeats, but still gpsValid: forced invalid%s"),NEWLINE); } nmeaParser2.gpsValid=false; invalidGps++; #if DUALBARO if (GPS_INFO.BaroAltitudeAvailable==TRUE) { if ( devB() == pDevPrimaryBaroSource || nmeaParser2.RMZAvailable || nmeaParser2.RMAAvailable || nmeaParser2.TASAvailable ) { invalidBaro++; } } #endif } else { // We have hearth beats, is baro available? if ( devIsBaroSource(devB()) || nmeaParser2.RMZAvailable || nmeaParser2.RMAAvailable || nmeaParser2.TASAvailable ) // 100411 validBaro++; } #ifdef DEBUGNPM if (invalidGps==2) { StartupStore(_T("... GPS no gpsValid available on port 1 and 2, active=%d%s"),active,NEWLINE); } if (invalidBaro>0) { StartupStore(_T("... Baro altitude just lost, current status=%d%s"),GPS_INFO.BaroAltitudeAvailable,NEWLINE); } #endif // do we really still have a baro altitude available? // If some baro source disappeared, let's reset it for safety. Parser will re-enable them immediately if available. // Assuming here that if no Baro is available, no airdata is available also // if (validBaro==0) { if ( GPS_INFO.BaroAltitudeAvailable ) { StartupStore(_T("... GPS no active baro source, and still BaroAltitudeAvailable, forced off%s"),NEWLINE); if (EnableNavBaroAltitude) { // LKTOKEN _@M122_ = "BARO ALTITUDE NOT AVAILABLE, USING GPS ALTITUDE" DoStatusMessage(gettext(TEXT("_@M122_"))); PortMonitorMessages++; // 100911 } else // LKTOKEN _@M121_ = "BARO ALTITUDE NOT AVAILABLE" DoStatusMessage(gettext(TEXT("_@M121_"))); GPS_INFO.BaroAltitudeAvailable=false; GPS_INFO.AirspeedAvailable=false; GPS_INFO.VarioAvailable=false; GPS_INFO.NettoVarioAvailable=false; lastvalidBaro=false; } } else { if ( lastvalidBaro==false) { StartupStore(_T("... GPS baro source back available%s"),NEWLINE); if (EnableNavBaroAltitude) // LKTOKEN _@M755_ = "USING AVAILABLE BARO ALTITUDE" DoStatusMessage(gettext(TEXT("_@M755_"))); else // LKTOKEN _@M120_ = "BARO ALTITUDE IS AVAILABLE" DoStatusMessage(gettext(TEXT("_@M120_"))); lastvalidBaro=true; } #if DUALBARO else { // last baro was Ok, currently we still have a validbaro, but no HBs... // Probably it is a special case when no gps fix was found on the secondary baro source. if (invalidBaro) { GPS_INFO.BaroAltitudeAvailable=FALSE; #ifdef DEBUGNPM StartupStore(_T(".... We still have valid baro, resetting BaroAltitude OFF\n")); #endif } } #endif } // Following diagnostics only if (active == lastactive) return; if (lastactive==0) { lastactive=active; StartupStore(_T(". GPS NMEA init delegated to port %d%s"),active,NEWLINE); return; } lastactive=active; // in case of no gps at all, port 1 is selected but we dont want to tell unless really working if (PortMonitorMessages<10) { // 100221 do not overload pilot with messages! StartupStore(_T("... GPS NMEA source changed to port %d %s"),active,NEWLINE); if (nmeaParser1.gpsValid || nmeaParser2.gpsValid){ TCHAR vbuf[100]; _stprintf(vbuf,_T("%s %d"), // LKTOKEN _@M277_ = "FALLBACK USING GPS ON PORT" gettext(TEXT("_@M277_")),active); DoStatusMessage(vbuf); } PortMonitorMessages++; } else { if (PortMonitorMessages==10) { // 100221 StartupStore(_T("... GOING SILENT on too many Com reportings.%s"),NEWLINE); // LKTOKEN _@M317_ = "GOING SILENT ON COM REPORTING" DoStatusMessage(gettext(TEXT("_@M317_"))); PortMonitorMessages++; } else PortMonitorMessages++; } }
// Rescale automatically dialogs, using negative values to force rescaling // Notice: SHOULD BE CALLED ONLY IF rWidth is negative, in order to avoid useless SetWindowPos int RescaleWidth(const int rWidth) { // Always rescale negative widths if (rWidth <-1) { // Special case is when width is also the scale unit, which demonstrate we have a bug to fix here! #if USEIBOX if (rWidth == (int)(-246*InfoBoxLayout::dscale)){ #else if (rWidth == (int)(-246*ScreenDScale)){ #endif return LKwdlgConfig; } double i=(246.0 / abs(rWidth)); if (i==0) { FailStore(_T("INTERNAL ERROR RESCALEWIDTH rWidth=%d"),rWidth); DoStatusMessage(_T("RESCALE ERR-001")); return rWidth; } #if USEIBOX int ri=(int)( (LKwdlgConfig/i) *InfoBoxLayout::dscale ); #else int ri=(int)( (LKwdlgConfig/i) *ScreenDScale ); #endif // StartupStore(_T("... RescaleWidth(): rescale %d to %d\n"),rWidth, ri); if (ri>ScreenSizeX) return(ScreenSizeX); return (ri); } // else use the incoming rWidth but it is clearly an error DoStatusMessage(_T("RESCALE WARN-001")); return rWidth; } void ChangeWindCalcSpeed(const int newspeed) { WindCalcSpeed += (double)newspeed/SPEEDMODIFY; } // runmode 0: exec inside LocalPath home of LK8000 // runmode 1: exec inside bool LKRun(const TCHAR *prog, const int runmode, const DWORD dwaitime) { if (_tcslen(prog) <5) { StartupStore(_T("... LKRun failure: invalid exec path <%s>%s"),prog,NEWLINE); return false; } TCHAR path[MAX_PATH]; if (runmode<0 || runmode>1) { StartupStore(_T("... LKRun failure: invalid runmode=%d %s"),runmode,NEWLINE); return false; } // mode 0: localpath , forced execution, with warnings if something goes wrong // mode 1: optional execution, no warnings if nothing found if (runmode<2) { LocalPath(path,prog); if (runmode==0) StartupStore(_T(". LKRun: exec <%s> background=%u%s"),path,dwaitime,NEWLINE); PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb=sizeof(STARTUPINFO); si.wShowWindow= SW_SHOWNORMAL; si.dwFlags = STARTF_USESHOWWINDOW; // if (!::CreateProcess(_T("C:\\WINDOWS\\notepad.exe"),_T(""), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) if (!::CreateProcess(path,_T(""), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { if (runmode==0) StartupStore(_T("... LKRun exec FAILED%s"),NEWLINE); return false; } ::WaitForSingleObject(pi.hProcess, dwaitime); StartupStore(_T(". LKRun exec terminated%s"),NEWLINE); return true; } return false; } void GotoWaypoint(const int wpnum) { if (!ValidWayPoint(wpnum)) { DoStatusMessage(_T("ERR-639 INVALID GOTO WPT")); return; } if (ValidTaskPoint(ActiveWayPoint) && ValidTaskPoint(1)) { TCHAR wpname[NAME_SIZE+1]; _tcscpy(wpname,WayPointList[wpnum].Name); wpname[10] = '\0'; if (MessageBoxX(hWndMapWindow, // LKTOKEN _@M158_ = "CONFIRM GOTO, ABORTING TASK?" gettext(TEXT("_@M158_")), // LKTOKEN _@M40_ = "A task is running!" gettext(TEXT("_@M40_")), MB_YESNO|MB_ICONQUESTION) == IDYES) { LockTaskData(); FlyDirectTo(wpnum); OvertargetMode=OVT_TASK; UnlockTaskData(); } } else { LockTaskData(); FlyDirectTo(wpnum); OvertargetMode=OVT_TASK; UnlockTaskData(); } } void ToggleBaroAltitude() { if (!GPS_INFO.BaroAltitudeAvailable) { // LKTOKEN _@M121_ = "BARO ALTITUDE NOT AVAILABLE" DoStatusMessage(gettext(TEXT("_@M121_"))); return; } EnableNavBaroAltitude=!EnableNavBaroAltitude; if (EnableNavBaroAltitude) // LKTOKEN _@M756_ = "USING BARO ALTITUDE" DoStatusMessage(gettext(TEXT("_@M756_"))); else // LKTOKEN _@M757_ = "USING GPS ALTITUDE" DoStatusMessage(gettext(TEXT("_@M757_"))); } TCHAR * GetSizeSuffix(void) { static TCHAR suffixname[12]; _stprintf(suffixname,_T("%03dx%03d"),ScreenSizeX,ScreenSizeY); return(suffixname); } void LKRunStartEnd(bool start) { if (start) { LKRun(_T("PREROTATE1.EXE"),1,5000); LKRun(_T("PREROTATE2.EXE"),1,5000); LKRun(_T("PREROTATE3.EXE"),1,5000); LKRun(_T("PRELOAD_00.EXE"),1,0); LKRun(_T("PRELOAD_05.EXE"),1,5000); LKRun(_T("PRELOAD_30.EXE"),1,30000); LKRun(_T("PRELOAD_60.EXE"),1,60000); LKRun(_T("PRELOAD_99.EXE"),1,INFINITE); } else { LKRun(_T("ENDLOAD_00.EXE"),1,0); LKRun(_T("ENDLOAD_05.EXE"),1,5000); LKRun(_T("ENDLOAD_30.EXE"),1,30000); LKRun(_T("ENDLOAD_60.EXE"),1,60000); LKRun(_T("ENDROTATE1.EXE"),1,5000); LKRun(_T("ENDROTATE2.EXE"),1,5000); LKRun(_T("ENDROTATE3.EXE"),1,5000); LKRun(_T("ENDLOAD_99.EXE"),1,INFINITE); } } // Reads line from UTF-8 encoded text file. // File must be open in binary read mode. bool ReadULine(ZZIP_FILE* fp, TCHAR *unicode, int maxChars) { unsigned char buf[READLINE_LENGTH * 2]; long startPos = zzip_tell(fp); if (startPos < 0) { StartupStore(_T(". ftell() error = %d%s"), errno, NEWLINE); return(false); } size_t nbRead = zzip_fread(buf, 1, sizeof(buf) - 1, fp); if (nbRead == 0) return(false); buf[nbRead] = '\0'; // find new line (CR/LF/CRLF) in the string and terminate string at that position size_t i; for (i = 0; i < nbRead; i++) { if (buf[i] == '\n') { buf[i++] = '\0'; if (buf[i] == '\r') i++; break; } if (buf[i] == '\r') { buf[i++] = '\0'; if (buf[i] == '\n') i++; break; } } // next reading will continue after new line zzip_seek(fp, startPos + i, SEEK_SET); // skip leading BOM char* begin = (char*) buf; if (buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) begin += 3; return(utf2unicode(begin, unicode, maxChars) >= 0); }