void MapWindow::LKCalculateWaypointReachable(const bool forced) { #if USEONEHZLIMITER if (!forced) ONEHZLIMITER; #endif static short multicalc_slot=0; // -1 (which becomes immediately 0) will force full loading on startup, but this is not good // because currently we are not waiting for ProgramStarted=3 // and the first scan is made while still initializing other things short numslots=1; // TODO assign numslots with a function, based also on available CPU time if (NumberOfWayPoints>200) { numslots=NumberOfWayPoints/400; // keep numslots optimal if (numslots<MULTICALC_MINROBIN) numslots=MULTICALC_MINROBIN; // seconds for full scan, as this is executed at 1Hz if (numslots>MULTICALC_MAXROBIN) numslots=MULTICALC_MAXROBIN; // When waypointnumber has changed, we wont be using an exceeded multicalc_slot, which would crash the sw // In this case, we shall probably continue for the first round to calculate without going from the beginning // but this is not a problem, we are round-robin all the time here. if (++multicalc_slot>numslots) multicalc_slot=1; } else { multicalc_slot=0; // forcing full scan } unsigned int i; double waypointDistance, waypointBearing,altitudeRequired,altitudeDifference; // LandableReachable is used only by the thermal bar indicator in MapWindow2, after here // apparently, is used to tell you if you are below final glide but in range for a landable wp // Since nov 2011 we dont user LandableReachable in FinalGlide anymore. // However it is still to be understood what drawbacks we might have by changing calculations here. LandableReachable = false; if (!WayPointList) return; unsigned int scanstart; unsigned int scanend; #if DEBUGCW unsigned int numwpscanned=0; #endif LockTaskData(); if (multicalc_slot==0) { scanstart=0; // including this scanend=NumberOfWayPoints; // will be used -1, so up to this excluded value #if DEBUGCW StartupStore(_T("... wps=%d multicalc_slot=0 ignored numslot=%d, full scan %d < %d%s"),NumberOfWayPoints, numslots,scanstart,scanend,NEWLINE); #endif } else { scanstart=(NumberOfWayPoints/numslots)*(multicalc_slot-1); if (multicalc_slot==numslots) scanend=NumberOfWayPoints; else scanend=scanstart+(NumberOfWayPoints/numslots); #if DEBUGCW StartupStore(_T("... wps=%d multicalc_slot=%d of %d, scan %d < %d%s"),NumberOfWayPoints, multicalc_slot, numslots,scanstart,scanend,NEWLINE); #endif } int overtarg=GetOvertargetIndex(); if (overtarg<0) overtarg=999999; for(i=scanstart;i<scanend;i++) { // signed Overtgarget -1 becomes a very high number, casted unsigned if ( ( ((WayPointCalc[i].AltArriv[AltArrivMode] >=0)||(WayPointList[i].Visible)) && (WayPointCalc[i].IsLandable || (WayPointList[i].Style==STYLE_THERMAL))) || WaypointInTask(i) || (i==(unsigned int)overtarg) ) { DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, WayPointList[i].Latitude, WayPointList[i].Longitude, &waypointDistance, &waypointBearing); WayPointCalc[i].Distance=waypointDistance; WayPointCalc[i].Bearing=waypointBearing; CalculateGlideRatio(waypointDistance, DerivedDrawInfo.NavAltitude - WayPointList[i].Altitude - GetSafetyAltitude(i)); altitudeRequired = GlidePolar::MacCreadyAltitude (GetMacCready(i,0), waypointDistance, waypointBearing, DerivedDrawInfo.WindSpeed, DerivedDrawInfo.WindBearing, 0,0,true,0) + WayPointList[i].Altitude + GetSafetyAltitude(i) - DerivedDrawInfo.EnergyHeight; WayPointCalc[i].AltReqd[AltArrivMode] = altitudeRequired; WayPointList[i].AltArivalAGL = DerivedDrawInfo.NavAltitude - altitudeRequired; if(WayPointList[i].AltArivalAGL >=0){ WayPointList[i].Reachable = TRUE; if (CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, waypointDistance, waypointBearing)) { if ((signed)i!=TASKINDEX) { LandableReachable = true; } } else { WayPointList[i].Reachable = FALSE; } } else { WayPointList[i].Reachable = FALSE; } #if DEBUGCW numwpscanned++; #endif } // if landable or in task } // for all waypoints // This is wrong, because multicalc will not necessarily find the LandableReachable at each pass // As of nov 2011 it is better not to change it, and let further investigation after 3.0 if (!LandableReachable) // indentation wrong here for(i=scanstart;i<scanend;i++) { if(!WayPointList[i].Visible && WayPointList[i].FarVisible) { // visible but only at a distance (limit this to 100km radius) if( WayPointCalc[i].IsLandable ) { #if DEBUGCW numwpscanned++; #endif DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, WayPointList[i].Latitude, WayPointList[i].Longitude, &waypointDistance, &waypointBearing); WayPointCalc[i].Distance=waypointDistance; // VENTA6 WayPointCalc[i].Bearing=waypointBearing; if (waypointDistance<100000.0) { altitudeRequired = GlidePolar::MacCreadyAltitude (GetMacCready(i,0), waypointDistance, waypointBearing, // 091221 DerivedDrawInfo.WindSpeed, DerivedDrawInfo.WindBearing, 0,0,true,0) + WayPointList[i].Altitude + GetSafetyAltitude(i); altitudeDifference = DerivedDrawInfo.NavAltitude + DerivedDrawInfo.EnergyHeight - altitudeRequired; WayPointList[i].AltArivalAGL = altitudeDifference; WayPointCalc[i].AltReqd[AltArrivMode] = altitudeRequired; if(altitudeDifference >=0){ WayPointList[i].Reachable = TRUE; if (CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, waypointDistance, waypointBearing)) { LandableReachable = true; } else WayPointList[i].Reachable = FALSE; } else { WayPointList[i].Reachable = FALSE; } } else { WayPointList[i].Reachable = FALSE; } // <100000 } // landable wp } // visible or far visible } // for all waypoint UnlockTaskData(); #if DEBUGCW StartupStore(_T("...... processed wps: %d\n"),numwpscanned); #endif }
void MapWindow::DrawVisualGlide(LKSurface& Surface, const DiagrammStruct& sDia) { const RECT& rci = sDia.rc; unsigned short numboxrows = 1; #if BUGSTOP LKASSERT(Current_Multimap_SizeY < SIZE4); #endif switch (Current_Multimap_SizeY) { case SIZE0: case SIZE1: numboxrows = 3; break; case SIZE2: numboxrows = 2; break; case SIZE3: numboxrows = 1; break; case SIZE4: return; default: LKASSERT(0); break; } if (!ScreenLandscape) { numboxrows++; if (numboxrows > 3) numboxrows = 3; } TCHAR tmpT[30]; line1Font = LK8VisualTopFont; line2Font = LK8VisualBotFont; SIZE textSizeTop, textSizeBot; Surface.SelectObject(line1Font); _stprintf(tmpT, _T("MMMM")); Surface.GetTextSize(tmpT, &textSizeTop); Surface.SelectObject(line2Font); _stprintf(tmpT, _T("55.5%s 79%s%s "), Units::GetDistanceName(), MsgToken(2179), MsgToken(2183)); Surface.GetTextSize(tmpT, &textSizeBot); // we can cut the waypoint name, but not the value data, so we use the second row of data // to size the box for everything. maxtSizeX = textSizeBot.cx; int a = (rci.right-rci.left) / (textSizeBot.cx+BOXINTERVAL); int b = (rci.right-rci.left) - a * (textSizeBot.cx)-(BOXINTERVAL * (a + 1)); boxSizeX = textSizeBot.cx + (b / (a + 1)); boxSizeY = textSizeTop.cy + 1; // single line (wp name) + distance from bottombar if (numboxrows > 1) { boxSizeY += (textSizeBot.cy * (numboxrows - 1)) - NIBLSCALE(2); if (numboxrows > 2) boxSizeY -= NIBLSCALE(1); } #if DEBUG_SCR StartupStore(_T("boxX=%d boxY=%d \n"), boxSizeX, boxSizeY); #endif #if DEBUG_SCR StartupStore(_T("VG AREA LTRB: %d,%d %d,%d\n"), rci.left, rci.top, rci.right, rci.bottom); #endif const auto oldBrush = Surface.SelectObject(LKBrush_White); const auto oldPen = Surface.SelectObject(LK_BLACK_PEN); BrushReference brush_back; if (!INVERTCOLORS) { brush_back = LKBrush_Black; } else { brush_back = LKBrush_Nlight; } Surface.FillRect(&rci, brush_back); POINT center, p1, p2; center.y = rci.top + (rci.bottom - rci.top) / 2; center.x = rci.left + (rci.right - rci.left) / 2; // numSlotX is the number items we can print horizontally. unsigned short numSlotX = (rci.right - rci.left) / (boxSizeX + BOXINTERVAL); if (numSlotX > MAXBSLOT) numSlotX = MAXBSLOT; #if BUGSTOP LKASSERT(numSlotX > 0); #endif if (numSlotX == 0) return; unsigned short boxInterval = ((rci.right - rci.left)-(boxSizeX * numSlotX)) / (numSlotX + 1); unsigned short oddoffset = ( (rci.right-rci.left) - (boxSizeX * numSlotX) - boxInterval * (numSlotX + 1)) / 2; /* #if BUGSTOP // not really harmful LKASSERT(oddoffset<=boxInterval); #endif */ #if DEBUG_SCR StartupStore(_T("numSlotX=%d ScreenSizeX=%d boxSizeX=%d interval=%d offset=%d\n"), numSlotX, ScreenSizeX, boxSizeX, boxInterval, oddoffset); #endif unsigned int t; // The horizontal grid unsigned int slotCenterX[MAXBSLOT + 1]; for (t = 0; t < numSlotX; t++) { slotCenterX[t] = (t * boxSizeX) + boxInterval * (t + 1)+(boxSizeX / 2) + oddoffset+rci.left; #if DEBUG_SCR StartupStore(_T("slotCenterX[%d]=%d\n"), t, slotCenterX[t]); #endif } // Vertical coordinates of each up/down subwindow, excluding center line int upYtop = rci.top; #if MIDCENTER int upYbottom = center.y + (boxSizeY / 2); int downYtop = center.y - (boxSizeY / 2); #else int upYbottom = center.y - CENTERYSPACE; int downYtop = center.y + CENTERYSPACE; #endif int upSizeY = upYbottom - upYtop - (boxSizeY); ; int downYbottom = rci.bottom; int downSizeY = downYbottom - downYtop - (boxSizeY); ; #if 0 // Reassign dynamically the vertical scale for each subwindow size double vscale = 1000 * (100 - Current_Multimap_SizeY) / 100; #else // Set the vertical range double vscale; if (Units::GetUserAltitudeUnit() == unFeet) vscale = (1000 / TOFEET); else vscale = 300.0; #endif Surface.SetBackgroundTransparent(); RECT trc = rci; // Top part of visual rect, target is over us=unreachable=red trc.top = rci.top; trc.bottom = center.y - 1; #ifndef DITHER RenderSky(Surface, trc, RGB_WHITE, LKColor(150, 255, 150), GC_NO_COLOR_STEPS / 2); #else RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE, GC_NO_COLOR_STEPS / 2); #endif // Bottom part, target is below us=reachable=green trc.top = center.y + 1; trc.bottom = rci.bottom; #ifndef DITHER RenderSky(Surface, trc, LKColor(255, 150, 150), RGB_WHITE, GC_NO_COLOR_STEPS / 2); #else RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE,GC_NO_COLOR_STEPS / 2); #endif // Draw center line p1.x = rci.left + 1; p1.y = center.y; p2.x = rci.right - 1; p2.y = center.y; Surface.SelectObject(LKPen_Black_N1); Surface.DrawSolidLine(p1, p2, rci); #if DEBUG_SCR StartupStore(_T("... Center line: Y=%d\n"), center.y); #endif Surface.SelectObject(line1Font); Surface.SelectObject(LKPen_Black_N0); ResetVisualGlideGlobals(); short res = GetVisualGlidePoints(numSlotX); if (res == INVALID_VALUE) { #if DEBUG_DVG StartupStore(_T("...... GVGP says not ready, wait..\n")); #endif return; } if (res == 0) { #if DEBUG_DVG StartupStore(_T("...... GVGP says no data available!\n")); #endif return; } // Print them all! int offset = (boxSizeY / 2) + CENTERYSPACE; LKBrush bcolor; LKColor rgbcolor, textcolor; int wp; unsigned short zeroslot = 0; double minbrgdiff = 999.0; double minabrgdiff = 999.0; // absolute never negative for (unsigned short n = 0; n < numSlotX; n++) { wp = slotWpIndex[n]; if (!ValidWayPoint(wp)) { // empty slot nothing to print continue; } double brgdiff = WayPointCalc[wp].Bearing - DrawInfo.TrackBearing; // this check is worthless if (brgdiff < -180.0) { brgdiff += 360.0; } else { if (brgdiff > 180.0) brgdiff -= 360.0; } double abrgdiff = brgdiff; if (abrgdiff < 0) abrgdiff *= -1; if (abrgdiff < minabrgdiff) { zeroslot = n; minabrgdiff = abrgdiff; minbrgdiff = brgdiff; } } // Draw vertical line #define DEGRANGE 10 // degrees left and right to perfect target if (minabrgdiff < 1) { p1.x = slotCenterX[zeroslot]; } else { // set fullscale range if (minabrgdiff > DEGRANGE) { minabrgdiff = DEGRANGE; if (minbrgdiff < 0) minbrgdiff = -1 * DEGRANGE; else minbrgdiff = DEGRANGE; } // we shift of course in the opposite direction p1.x = slotCenterX[zeroslot]-(int) ((boxSizeX / (DEGRANGE * 2)) * minbrgdiff); } p2.x = p1.x; p1.y = rci.top + 1; p2.y = rci.bottom - 1; Surface.SelectObject(LKPen_Black_N1); Surface.DrawSolidLine(p1, p2, rci); for (unsigned short n = 0; n < numSlotX; n++) { wp = slotWpIndex[n]; if (!ValidWayPoint(wp)) { // empty slot nothing to print continue; } #if DEBUG_DVG StartupStore(_T("... DVG PRINT [%d]=%d <%s>\n"), n, wp, WayPointList[wp].Name); #endif Sideview_VGWpt[n] = wp; double altdiff = WayPointCalc[wp].AltArriv[AltArrivMode]; int ty; #if DEBUG_SCR StartupStore(_T("... wp=<%s>\n"), WayPointList[wp].Name); #endif // Since terrain can be approximated due to low precision maps, or waypoint position or altitude error, // we have a common problem: we get an obstacle to get to the waypoint because it is // positioned "BELOW" the terrain itself. We try to reduce this problem here. #define SAFETERRAIN 50 // Positive arrival altitude for the waypoint, upper window if (altdiff >= 0) { if (altdiff == 0)altdiff = 1; double d = vscale / altdiff; if (d == 0) d = 1; ty = upYbottom - (int) ((double) upSizeY / d)-(boxSizeY / 2); #if DEBUG_SCR StartupStore(_T("... upYbottom=%d upSizeY=%d / (vscale=%f/altdiff=%f = %f) =- %d ty=%d offset=%d\n"), upYbottom, upSizeY, vscale, altdiff, d, (int) ((double) upSizeY / d), ty, offset); #endif if ((ty - offset) < upYtop) ty = upYtop + offset; if ((ty + offset) > upYbottom) ty = upYbottom - offset; #if DEBUG_SCR StartupStore(_T("... upYtop=%d upYbottom=%d final ty=%d\n"), upYtop, upYbottom, ty); #endif // // This is too confusing. We want simple colors, not shaded // rgbcolor = MixColors( LKColor(50,255,50), LKColor(230,255,230), altdiff/(vscale-50)); // if (altdiff <= SAFETERRAIN) { rgbcolor = RGB_LIGHTYELLOW; } else { if (!CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, WayPointCalc[wp].Distance, WayPointCalc[wp].Bearing)) { rgbcolor = RGB_LIGHTRED; } else { #ifdef DITHER rgbcolor = RGB_WHITE; #else rgbcolor = RGB_LIGHTGREEN; #endif } } bcolor.Create(rgbcolor); } else { double d = vscale / altdiff; if (d == 0) d = -1; ty = downYtop - (int) ((double) downSizeY / d)+(boxSizeY / 2); // - because the left part is negative, we are really adding. if ((ty - offset) < downYtop) ty = downYtop + offset; if ((ty + offset) > downYbottom) ty = downYbottom - offset; #ifdef DITHER rgbcolor = RGB_WHITE; // negative part, no need to render dark #else rgbcolor = RGB_LIGHTRED; #endif bcolor.Create(rgbcolor); } TCHAR line2[40], line3[40]; TCHAR value[40], unit[30]; TCHAR name[NAME_SIZE + 1]; double ar = (WayPointCalc[wp].AltArriv[AltArrivMode] * ALTITUDEMODIFY); _tcscpy(name, WayPointList[wp].Name); CharUpper(name); if (IsSafetyAltitudeInUse(wp)) textcolor = RGB_DARKBLUE; else textcolor = RGB_BLACK; switch (numboxrows) { case 0: #if BUGSTOP LKASSERT(0); #endif return; case 1: // 1 line: waypoint name VGTextInBox(Surface, n, 1, name, NULL, NULL, slotCenterX[n], ty, textcolor, bcolor); break; case 2: // 2 lines: waypoint name + altdiff LKFormatAltDiff(wp, false, value, unit); // Should we print also the GR? if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) { if (ar >= -999 && ar <= 999) _stprintf(line2, _T("%s "), value); else _stprintf(line2, _T("%s "), value); LKFormatGR(wp, false, value, unit); _tcscat(line2, value); } else { _stprintf(line2, _T("%s ---"), value); } VGTextInBox(Surface, n, 2, name, line2, NULL, slotCenterX[n], ty, textcolor, bcolor); break; case 3: // 3 lines: waypoint name + dist + altdiff LKFormatDist(wp, false, value, unit); _stprintf(line2, _T("%s%s"), value, unit); LKFormatBrgDiff(wp, false, value, unit); _stprintf(tmpT, _T(" %s%s"), value, unit); _tcscat(line2, tmpT); LKFormatAltDiff(wp, false, value, unit); // Should we print also the GR? if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) { if (ar >= -999 && ar <= 999) _stprintf(line3, _T("%s "), value); else _stprintf(line3, _T("%s "), value); LKFormatGR(wp, false, value, unit); _tcscat(line3, value); } else { _stprintf(line3, _T("%s ---"), value); } VGTextInBox(Surface, n, 3, name, line2, line3, slotCenterX[n], ty, textcolor, bcolor); break; default: #if BUGSTOP LKASSERT(0); #endif return; } } // for numSlotX // Cleanup and return Surface.SelectObject(oldBrush); Surface.SelectObject(oldPen); return; }
void MapWindow::DrawNearest(HDC hdc, RECT rc) { SIZE WPTextSize, DSTextSize, BETextSize, RETextSize, AATextSize, HLTextSize, MITextSize; TCHAR Buffer[LKSIZEBUFFERLARGE]; static RECT s_sortBox[6]; static TCHAR Buffer1[MAXNEAREST][MAXNUMPAGES][24], Buffer2[MAXNEAREST][MAXNUMPAGES][10], Buffer3[MAXNEAREST][MAXNUMPAGES][10]; static TCHAR Buffer4[MAXNEAREST][MAXNUMPAGES][12], Buffer5[MAXNEAREST][MAXNUMPAGES][12]; static short s_maxnlname; TCHAR text[30]; short i, k, iRaw, wlen, rli=0, curpage, drawn_items_onpage; double value; COLORREF rcolor; // column0 starts after writing 1:2 (ModeIndex:CURTYPE+1) with a different font.. static short Column0; static short Column1, Column2, Column3, Column4, Column5; static POINT p1, p2; static short s_rawspace; // Printable area for live nearest values static short left,right,bottom; // one for each mapspace, no matter if 0 and 1 are unused // we lock to current mapspace for this drawing short curmapspace=MapSpaceMode; // Vertical and horizontal spaces #define INTERRAW 1 #define HEADRAW NIBLSCALE(6) HBRUSH sortbrush; RECT invsel; if (INVERTCOLORS) { sortbrush=LKBrush_LightGreen; } else { sortbrush=LKBrush_DarkGreen; } if (DoInit[MDI_DRAWNEAREST]) { // Set screen borders to avoid writing on extreme pixels if ( ScreenSize < (ScreenSize_t)sslandscape ) { // Portrait mode has tight horizontal margins... left=rc.left+NIBLSCALE(1); right=rc.right-NIBLSCALE(1); bottom=rc.bottom-BottomSize-NIBLSCALE(2); s_maxnlname=MAXNLNAME-5; // 7 chars max, 8 sized _stprintf(Buffer,TEXT("MAKSJSMM")); } else { left=rc.left+NIBLSCALE(5); right=rc.right-NIBLSCALE(5); bottom=rc.bottom-BottomSize; s_maxnlname=MAXNLNAME-3; // 9 chars, sized 10 _stprintf(Buffer,TEXT("ABCDEFGHMx")); } SelectObject(hdc, LK8InfoBigFont); // Text font for Nearest was LK8Title GetTextExtentPoint(hdc, Buffer, _tcslen(Buffer), &WPTextSize); _stprintf(Buffer,TEXT("000.0")); GetTextExtentPoint(hdc, Buffer, _tcslen(Buffer), &DSTextSize); //: Bearing _stprintf(Buffer,TEXT("<<123")); GetTextExtentPoint(hdc, Buffer, _tcslen(Buffer), &BETextSize); //: reqE _stprintf(Buffer,TEXT("5299")); GetTextExtentPoint(hdc, Buffer, _tcslen(Buffer), &RETextSize); //: Altitude Arrival _stprintf(Buffer,TEXT("+9999")); GetTextExtentPoint(hdc, Buffer, _tcslen(Buffer), &AATextSize); SelectObject(hdc, LK8InfoNormalFont); _stprintf(Buffer,TEXT("MMMM")); GetTextExtentPoint(hdc, Buffer, _tcslen(Buffer), &HLTextSize); SelectObject(hdc, LK8PanelMediumFont); _stprintf(Buffer,TEXT("1.1")); GetTextExtentPoint(hdc, Buffer, _tcslen(Buffer), &MITextSize); short afterwpname=left+WPTextSize.cx+NIBLSCALE(5); short intercolumn=(right-afterwpname- DSTextSize.cx-BETextSize.cx-RETextSize.cx-AATextSize.cx)/3; // Col0 is where APTS 1/3 can be written, after ModeIndex:Curtype Column0=MITextSize.cx+LEFTLIMITER+NIBLSCALE(5); Column1=left; // WP align left //Column2=Column1+WPTextSize.cx+intercolumn/2; // DS align right Column2=afterwpname+DSTextSize.cx; // DS align right Column3=Column2+intercolumn+BETextSize.cx; // BE align right Column4=Column3+intercolumn+RETextSize.cx; // RE align right Column5=Column4+intercolumn+AATextSize.cx; // AA align right if ( ScreenSize < (ScreenSize_t)sslandscape ) { TopSize=rc.top+HEADRAW*2+HLTextSize.cy; p1.x=0; p1.y=TopSize; p2.x=rc.right; p2.y=p1.y; //TopSize+=(WPTextSize.cy); TopSize+=HEADRAW; Numraws=(bottom - TopSize) / (WPTextSize.cy+(INTERRAW*2)); if (Numraws>MAXNEAREST) Numraws=MAXNEAREST; s_rawspace=(WPTextSize.cy+INTERRAW); } else { TopSize=rc.top+HEADRAW*2+HLTextSize.cy; p1.x=0; p1.y=TopSize; p2.x=rc.right; p2.y=p1.y; TopSize+=HEADRAW/2; Numraws=(bottom - TopSize) / (WPTextSize.cy+INTERRAW); if (Numraws>MAXNEAREST) Numraws=MAXNEAREST; s_rawspace=(WPTextSize.cy+INTERRAW); } #define INTERBOX intercolumn/2 s_sortBox[0].left=Column0; if ( ScreenSize < (ScreenSize_t)sslandscape ) s_sortBox[0].right=left+WPTextSize.cx-NIBLSCALE(2); else s_sortBox[0].right=left+WPTextSize.cx-NIBLSCALE(10); s_sortBox[0].top=2; s_sortBox[0].bottom=p1.y; SortBoxX[MSM_LANDABLE][0]=s_sortBox[0].right; SortBoxX[MSM_AIRPORTS][0]=s_sortBox[0].right; SortBoxX[MSM_NEARTPS][0]=s_sortBox[0].right; if ( ScreenSize < (ScreenSize_t)sslandscape ) s_sortBox[1].left=Column1+afterwpname-INTERBOX; else s_sortBox[1].left=Column1+afterwpname-INTERBOX-NIBLSCALE(2); s_sortBox[1].right=Column2+INTERBOX; s_sortBox[1].top=2; s_sortBox[1].bottom=p1.y; SortBoxX[MSM_LANDABLE][1]=s_sortBox[1].right; SortBoxX[MSM_AIRPORTS][1]=s_sortBox[1].right; SortBoxX[MSM_NEARTPS][1]=s_sortBox[1].right; s_sortBox[2].left=Column2+INTERBOX; s_sortBox[2].right=Column3+INTERBOX; s_sortBox[2].top=2; s_sortBox[2].bottom=p1.y; SortBoxX[MSM_LANDABLE][2]=s_sortBox[2].right; SortBoxX[MSM_AIRPORTS][2]=s_sortBox[2].right; SortBoxX[MSM_NEARTPS][2]=s_sortBox[2].right; s_sortBox[3].left=Column3+INTERBOX; s_sortBox[3].right=Column4+INTERBOX; s_sortBox[3].top=2; s_sortBox[3].bottom=p1.y; SortBoxX[MSM_LANDABLE][3]=s_sortBox[3].right; SortBoxX[MSM_AIRPORTS][3]=s_sortBox[3].right; SortBoxX[MSM_NEARTPS][3]=s_sortBox[3].right; s_sortBox[4].left=Column4+INTERBOX; s_sortBox[4].right=rc.right-1; s_sortBox[4].top=2; s_sortBox[4].bottom=p1.y; SortBoxX[MSM_LANDABLE][4]=s_sortBox[4].right; SortBoxX[MSM_AIRPORTS][4]=s_sortBox[4].right; SortBoxX[MSM_NEARTPS][4]=s_sortBox[4].right; SortBoxY[MSM_LANDABLE]=p1.y; SortBoxY[MSM_AIRPORTS]=p1.y; SortBoxY[MSM_NEARTPS]=p1.y; Numpages=roundupdivision(MAXNEAREST, Numraws); if (Numpages>MAXNUMPAGES) Numpages=MAXNUMPAGES; else if (Numpages<1) Numpages=1; SelectedRaw[MSM_LANDABLE]=0; SelectedRaw[MSM_AIRPORTS]=0; SelectedRaw[MSM_NEARTPS]=0; SelectedPage[MSM_LANDABLE]=0; SelectedPage[MSM_AIRPORTS]=0; SelectedPage[MSM_NEARTPS]=0; DoInit[MDI_DRAWNEAREST]=false; return; } // doinit Numpages=roundupdivision(SortedNumber, Numraws); if (Numpages>MAXNUMPAGES) Numpages=MAXNUMPAGES; else if (Numpages<1) Numpages=1; curpage=SelectedPage[curmapspace]; if (curpage<0||curpage>=MAXNUMPAGES) { // TODO also >Numpages // DoStatusMessage(_T("ERR-091 curpage invalid!")); // selection while waiting for data ready SelectedPage[curmapspace]=0; LKevent=LKEVENT_NONE; return; } switch (LKevent) { case LKEVENT_NONE: break; case LKEVENT_ENTER: LKevent=LKEVENT_NONE; switch(curmapspace) { case MSM_LANDABLE: i=SortedLandableIndex[SelectedRaw[curmapspace]+(curpage*Numraws)]; break; case MSM_AIRPORTS: i=SortedAirportIndex[SelectedRaw[curmapspace] + (curpage*Numraws)]; break; case MSM_NEARTPS: default: i=SortedTurnpointIndex[SelectedRaw[curmapspace] + (curpage*Numraws)]; break; } if ( !ValidWayPoint(i)) { #if 0 // selection while waiting for data ready if (SortedNumber>0) DoStatusMessage(_T("ERR-019 Invalid selection")); #endif break; } SelectedWaypoint=i; LastDoNearest = DrawInfo.Time+NEARESTONHOLD; PopupWaypointDetails(); LastDoNearest = 0; // SetModeType(LKMODE_MAP,MP_MOVING); EXperimental OFF 101219 LKevent=LKEVENT_NONE; return; break; case LKEVENT_DOWN: if (++SelectedRaw[curmapspace] >=Numraws) SelectedRaw[curmapspace]=0; LastDoNearest=DrawInfo.Time+PAGINGTIMEOUT-1.0; break; case LKEVENT_UP: if (--SelectedRaw[curmapspace] <0) SelectedRaw[curmapspace]=Numraws-1; LastDoNearest=DrawInfo.Time+PAGINGTIMEOUT-1.0; break; case LKEVENT_PAGEUP: LKevent=LKEVENT_NONE; break; case LKEVENT_PAGEDOWN: LKevent=LKEVENT_NONE; break; case LKEVENT_NEWRUN: for (i=0; i<MAXNEAREST; i++) { for (k=0; k<MAXNUMPAGES; k++) { _stprintf(Buffer1[i][k],_T("------------")); // 12 chars _stprintf(Buffer2[i][k],_T("----")); _stprintf(Buffer3[i][k],_T("----")); _stprintf(Buffer4[i][k],_T("----")); _stprintf(Buffer5[i][k],_T("----")); } } break; case LKEVENT_NEWPAGE: break; default: LKevent=LKEVENT_NONE; break; } if (INVERTCOLORS) _DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p1, p2, RGB_GREEN, rc); else _DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p1, p2, RGB_DARKGREEN, rc); SelectObject(hdc, LK8InfoNormalFont); // Heading line short cursortbox=SortedMode[curmapspace]; if ( ScreenSize < (ScreenSize_t)sslandscape ) { // portrait mode FillRect(hdc,&s_sortBox[cursortbox], sortbrush); _stprintf(Buffer,TEXT("%d.%d"),ModeIndex,CURTYPE+1); SelectObject(hdc, LK8PanelMediumFont); LKWriteText(hdc, Buffer, LEFTLIMITER, rc.top+TOPLIMITER , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); SelectObject(hdc, LK8InfoNormalFont); switch(curmapspace) { case MSM_LANDABLE: // LKTOKEN _@M1311_ "LND" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1311_")), curpage+1,Numpages); break; case MSM_AIRPORTS: // LKTOKEN _@M1313_ "APT" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1313_")), curpage+1, Numpages); break; case MSM_NEARTPS: default: // LKTOKEN _@M1315_ "TPS" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1315_")), curpage+1, Numpages); break; } if (cursortbox == 0) LKWriteText(hdc, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); // LKTOKEN _@M1300_ "Dist" _stprintf(Buffer,gettext(TEXT("_@M1300_"))); if (cursortbox==1) LKWriteText(hdc, Buffer, Column2, HEADRAW , 0, WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column2, HEADRAW , 0, WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1301_ "Dir" _stprintf(Buffer,gettext(TEXT("_@M1301_"))); if (cursortbox==2) LKWriteText(hdc, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1302_ "rEff" _stprintf(Buffer,gettext(TEXT("_@M1302_"))); if (cursortbox==3) LKWriteText(hdc, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1303_ "AltA" _stprintf(Buffer,gettext(TEXT("_@M1303_"))); if (cursortbox==4) LKWriteText(hdc, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); } else { FillRect(hdc,&s_sortBox[cursortbox], sortbrush); if ( (ScreenSize == (ScreenSize_t)ss640x480) || (ScreenSize == (ScreenSize_t)ss320x240) || (ScreenSize == ss896x672) ) { _stprintf(Buffer,TEXT("%d.%d"),ModeIndex,CURTYPE+1); SelectObject(hdc, LK8PanelMediumFont); LKWriteText(hdc, Buffer, LEFTLIMITER, rc.top+TOPLIMITER , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); SelectObject(hdc, LK8InfoNormalFont); switch(curmapspace) { case MSM_LANDABLE: // LKTOKEN _@M1312_ "LNDB" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1312_")), curpage+1,Numpages); break; case MSM_AIRPORTS: // LKTOKEN _@M1314_ "APTS" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1314_")), curpage+1, Numpages); break; case MSM_NEARTPS: default: // LKTOKEN _@M1315_ "TPS" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1315_")), curpage+1, Numpages); break; } if (cursortbox==0) LKWriteText(hdc, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0,WTMODE_NORMAL, WTALIGN_LEFT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0,WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); // LKTOKEN _@M1300_ "Dist" _stprintf(Buffer,gettext(TEXT("_@M1300_"))); if (cursortbox==1) LKWriteText(hdc, Buffer, Column2, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column2, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1301_ "Dir" _stprintf(Buffer,gettext(TEXT("_@M1301_"))); if (cursortbox==2) LKWriteText(hdc, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1302_ "rEff" _stprintf(Buffer,gettext(TEXT("_@M1302_"))); if (cursortbox==3) LKWriteText(hdc, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1308_ "Arriv" _stprintf(Buffer,gettext(TEXT("_@M1308_"))); if (cursortbox==4) LKWriteText(hdc, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); } else { _stprintf(Buffer,TEXT("%d.%d"),ModeIndex,CURTYPE+1); SelectObject(hdc, LK8PanelMediumFont); LKWriteText(hdc, Buffer, LEFTLIMITER, rc.top+TOPLIMITER , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); SelectObject(hdc, LK8InfoNormalFont); switch(curmapspace) { case MSM_LANDABLE: // LKTOKEN _@M1312_ "LNDB" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1312_")), curpage+1,Numpages); break; case MSM_AIRPORTS: // LKTOKEN _@M1314_ "APTS" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1314_")), curpage+1, Numpages); break; case MSM_NEARTPS: default: // LKTOKEN _@M1315_ "TPS" _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1315_")), curpage+1, Numpages); break; } if (cursortbox==0) LKWriteText(hdc, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0,WTMODE_NORMAL, WTALIGN_LEFT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0,WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); // LKTOKEN _@M1304_ "Distance" _stprintf(Buffer,gettext(TEXT("_@M1304_"))); if (cursortbox==1) LKWriteText(hdc, Buffer, Column2, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column2, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1305_ "Direction" _stprintf(Buffer,gettext(TEXT("_@M1305_"))); if (cursortbox==2) LKWriteText(hdc, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1306_ "ReqEff" _stprintf(Buffer,gettext(TEXT("_@M1306_"))); if (cursortbox==3) LKWriteText(hdc, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // LKTOKEN _@M1307_ "AltArr" _stprintf(Buffer,gettext(TEXT("_@M1307_"))); if (cursortbox==4) LKWriteText(hdc, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(hdc, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); } } // landscape mode SelectObject(hdc, LK8InfoBigFont); // Text font for Nearest bool ndr=NearestDataReady; NearestDataReady=false; int *psortedindex; switch(curmapspace) { case MSM_LANDABLE: psortedindex=SortedLandableIndex; break; case MSM_AIRPORTS: psortedindex=SortedAirportIndex; break; case MSM_NEARTPS: default: psortedindex=SortedTurnpointIndex; break; } for (i=0, drawn_items_onpage=0; i<Numraws; i++) { iRaw=TopSize+(s_rawspace*i); short curraw=(curpage*Numraws)+i; if (curraw>=MAXNEAREST) break; rli=*(psortedindex+curraw); if (!ndr) { goto KeepOldValues; } if ( ValidWayPoint(rli) ) { wlen=_tcslen(WayPointList[rli].Name); if (wlen>s_maxnlname) { LK_tcsncpy(Buffer, WayPointList[rli].Name, s_maxnlname); } else { LK_tcsncpy(Buffer, WayPointList[rli].Name, wlen); } ConvToUpper(Buffer); _tcscpy(Buffer1[i][curpage],Buffer); value=WayPointCalc[rli].Distance*DISTANCEMODIFY; _stprintf(Buffer2[i][curpage],TEXT("%0.1lf"),value); if (!MapWindow::mode.Is(MapWindow::Mode::MODE_CIRCLING)) { value = WayPointCalc[rli].Bearing - DrawInfo.TrackBearing; if (value < -180.0) value += 360.0; else if (value > 180.0) value -= 360.0; if (value > 1) _stprintf(Buffer3[i][curpage], TEXT("%2.0f\xB0\xBB"), value); else if (value < -1) _stprintf(Buffer3[i][curpage], TEXT("\xAB%2.0f\xB0"), -value); else _tcscpy(Buffer3[i][curpage], TEXT("\xAB\xBB")); } else _stprintf(Buffer3[i][curpage], TEXT("%2.0f\xB0"), WayPointCalc[rli].Bearing); // 101219 value=WayPointCalc[rli].GR; if (value<1 || value>=MAXEFFICIENCYSHOW) _stprintf(Buffer4[i][curpage],_T("---")); else { if (value>99) _stprintf(text,_T("%.0f"),value); else _stprintf(text,_T("%.1f"),value); _stprintf(Buffer4[i][curpage],_T("%s"),text); } value=ALTITUDEMODIFY*WayPointCalc[rli].AltArriv[AltArrivMode]; if (value <-9999 || value >9999 ) _tcscpy(text,_T("---")); else _stprintf(text,_T("%+.0f"),value); _stprintf(Buffer5[i][curpage], TEXT("%s"),text); } else { _stprintf(Buffer1[i][curpage],_T("------------")); _stprintf(Buffer2[i][curpage],_T("---")); _stprintf(Buffer3[i][curpage],_T("---")); _stprintf(Buffer4[i][curpage],_T("---")); _stprintf(Buffer5[i][curpage],_T("---")); } KeepOldValues: if ( ValidWayPoint(rli) ) { drawn_items_onpage++; if (WayPointCalc[rli].IsOutlanding) { rcolor=RGB_LIGHTYELLOW; SelectObject(hdc, LK8InfoBigItalicFont); } else { rcolor=RGB_WHITE; SelectObject(hdc, LK8InfoBigFont); } // 120601 extend search for tps, missing reachable status // If we are listing tps, and the current tp has a positive arrival altitude, // then check if it is really unreachable because we dont calculate tps for that. // Unless they are in a task, common, alternates, of course. if (curmapspace==MSM_NEARTPS) { if ( WayPointCalc[rli].AltArriv[AltArrivMode]>0) { if (CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, WayPointCalc[rli].Distance, WayPointCalc[rli].Bearing )) { rcolor=RGB_WHITE; } else { rcolor=RGB_LIGHTRED; } } else { rcolor=RGB_LIGHTRED; } } else // old stuff as usual if ((WayPointCalc[rli].VGR == 3 )|| (!WayPointList[rli].Reachable)) { rcolor=RGB_LIGHTRED; } } else { rcolor=RGB_GREY; } LKWriteText(hdc, Buffer1[i][curpage], Column1, iRaw , 0, WTMODE_NORMAL, WTALIGN_LEFT, rcolor, false); SelectObject(hdc, LK8InfoBigFont); // Text font for Nearest LKWriteText(hdc, Buffer2[i][curpage], Column2, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); LKWriteText(hdc, Buffer3[i][curpage], Column3, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); LKWriteText(hdc, Buffer4[i][curpage], Column4, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); LKWriteText(hdc, Buffer5[i][curpage], Column5, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); } if (LKevent==LKEVENT_NEWRUN || LKevent==LKEVENT_NEWPAGE ) { LKevent=LKEVENT_NONE; return; } if (drawn_items_onpage>0) { if (SelectedRaw[curmapspace] <0 || SelectedRaw[curmapspace]>(Numraws-1)) { return; } if (SelectedRaw[curmapspace] >= drawn_items_onpage) { if (LKevent==LKEVENT_DOWN) SelectedRaw[curmapspace]=0; else if (LKevent==LKEVENT_UP) SelectedRaw[curmapspace]=drawn_items_onpage-1; else { // Here we are recovering a selection problem caused by a delay while switching. // DoStatusMessage(_T("Cant find valid raw")); // not needed anymore SelectedRaw[curmapspace]=0; } } invsel.left=left; invsel.right=right; invsel.top=TopSize+(s_rawspace*SelectedRaw[curmapspace])+NIBLSCALE(2); invsel.bottom=TopSize+(s_rawspace*(SelectedRaw[curmapspace]+1))-NIBLSCALE(1); InvertRect(hdc,&invsel); } LKevent=LKEVENT_NONE; return; }