예제 #1
0
static int OnTimer(WindowControl * Sender){
  (void)Sender;
#ifdef LKAIRSPACE
  airspaces.clear();
  airspaces = CAirspaceManager::Instance().GetAirspacesInWarning();
  Count = airspaces.size();
  wAirspaceList->Redraw();
#endif
  return(0);
}
예제 #2
0
bool MapWindow::Event_InteriorAirspaceDetails(double lon, double lat) {
  bool found=false;
  CAirspaceList reslist = CAirspaceManager::Instance().GetVisibleAirspacesAtPoint(lon, lat);
  CAirspaceList::iterator it;
  for (it = reslist.begin(); it != reslist.end(); ++it) {
	dlgAirspaceDetails(*it);
	found = true;
  }
  return found; // nothing found..
}
예제 #3
0
static void PrepareData(void){

  TCHAR sTmp[5];

  if (NumberOfAirspaces==0) return;

  sNameFilter[0] =_T('\0');
  AirspaceSelectInfo = (AirspaceSelectInfo_t*)
    malloc(sizeof(AirspaceSelectInfo_t) * NumberOfAirspaces);

  if (AirspaceSelectInfo==NULL) {
	OutOfMemory(_T(__FILE__),__LINE__);
	return;
  }

  StrIndex = (int*)malloc(sizeof(int)*(NumberOfAirspaces+1));
  if (StrIndex==NULL) {
        OutOfMemory(_T(__FILE__),__LINE__);

        return;
  }

  int index=0;
  double bearing;
  double distance;
  CAirspaceList Airspaces = CAirspaceManager::Instance().GetAllAirspaces();
  CAirspaceList::const_iterator it;
  for (it=Airspaces.begin(); it != Airspaces.end(); ++it) {
    AirspaceSelectInfo[index].airspace = *it;

	distance = DISTANCEMODIFY * (*it)->Range(Longitude, Latitude, bearing);
	if (distance<0) distance=0;
    AirspaceSelectInfo[index].Distance = distance;
	AirspaceSelectInfo[index].Direction = bearing;

    LK_tcsncpy(sTmp, (*it)->Name(), 4);
    CharUpper(sTmp);

    AirspaceSelectInfo[index].FourChars =
                    (((unsigned)sTmp[0] & 0xff) << 24)
                  + (((unsigned)sTmp[1] & 0xff) << 16)
                  + (((unsigned)sTmp[2] & 0xff) << 8)
                  + (((unsigned)sTmp[3] & 0xff) );

    AirspaceSelectInfo[index].Type = (*it)->Type();

    index++;
  }

  qsort(AirspaceSelectInfo, UpLimit,
      sizeof(AirspaceSelectInfo_t), AirspaceNameCompare);

}
예제 #4
0
bool dlgAirspaceWarningIsEmpty(void) {
#ifdef LKAIRSPACE
    return (airspaces.size() == 0);
#else
  return (AirspaceWarnGetItemCount()==0);
#endif
}
예제 #5
0
int UserMsgNotify(WindowControl *Sender, MSG *msg){

  if (msg->message != WM_USER+1)
    return(1);

  if (!wf->GetVisible())
    return(0);
#ifndef LKAIRSPACE
  bool do_refocus = false;

  if (actListSizeChange){
    actListSizeChange = false;
#ifdef LKAIRSPACE
    Count = airspaces.size();
#else
    Count = AirspaceWarnGetItemCount();
#endif
    do_refocus = FindFocus();

    wAirspaceList->ResetList();

    if (Count == 0) {
      // auto close
      OnCloseClicked(Sender);
    }
  }

  if (actShow){
    actShow = false;
    if (!do_refocus) {
      do_refocus = FindFocus();
    }

    /*
    if (!wf->GetVisible()){
      Count = AirspaceWarnGetItemCount();
      wAirspaceList->ResetList();
      FocusedIdx = 0;
      FocusedID = -1;
      wf->Show();
      SetFocus(wAirspaceListEntry->GetHandle());
    } else {
      SetFocus(wAirspaceListEntry->GetHandle());
    }
    */
    //    return(0);
  }

  if (actListChange) {
    actListChange = false;
    wAirspaceList->Redraw();
  }

  if (do_refocus) {
    SetFocus(wAirspaceListEntry->GetHandle());    
  }
#endif
  // this is our message, we have handled it.
  return(0);
}
예제 #6
0
static void DoAck(int Ack){
  int Idx;

  Idx = SelectedIdx;				//use selected list entry
  if (Idx < 0) Idx = FocusedIdx;	//if none selected use focused
  if (Idx < 0) Idx = 0;				//if none focused?
  if (Idx>=(int)airspaces.size()) return;
  
  CAirspace *p;
  p = airspaces[Idx];
  
	switch (Ack) {
	  default:
	  case -1:		//-1 Ack warning
		CAirspaceManager::Instance().AirspaceAckWarn(*p);
		break;

	  case 3:		//3 Ack airspace
		CAirspaceManager::Instance().AirspaceAckSpace(*p);
		break;

	  case 4:		//4 Dailyack clicked 
		CAirspaceManager::Instance().AirspaceDisable(*p);
		break;

	  case 0:		//0 Enable clicked 
		CAirspaceManager::Instance().AirspaceEnable(*p);
		break;
	}//sw
    wAirspaceList->Redraw();
}
예제 #7
0
bool MapWindow::Event_NearestWaypointDetails(double lon, double lat) {

    double Dist;
    unsigned int i;
    const double range = zoom.RealScale()*500;  
    double dyn_range = std::max(5000.0, range*3.5);

    //StartupStore(_T("RANGE=%f\n"),dyn_range);
    LKSound(TEXT("LK_BELL.WAV"));

start_search:

#ifdef BUTTONS_MS
    LockFlightData();
    DistanceBearing(lat,lon, GPS_INFO.Latitude,GPS_INFO.Longitude, &Dist, NULL);
    UnlockFlightData();

    if(Dist < dyn_range) {
	#ifdef OWN_POS_MS
  	dlgAddMultiSelectListItem(NULL,0, IM_OWN_POS, Dist);
	#endif
	#ifdef ORACLE_MS
  	dlgAddMultiSelectListItem(NULL,0, IM_ORACLE, Dist);
	#endif
	#ifdef TEAM_CODE_MS
  	dlgAddMultiSelectListItem(NULL,0, IM_TEAM, Dist);
	#endif
    }
#endif	// BUTTONS_MS


    for(size_t i=NUMRESWP;i<WayPointList.size();++i) {    // Consider only valid markers
        if ((WayPointCalc[i].WpType==WPT_AIRPORT)|| (WayPointCalc[i].WpType==WPT_OUTLANDING)) {
            DistanceBearing(lat,lon, WayPointList[i].Latitude, WayPointList[i].Longitude, &Dist, NULL);
            if(Dist < dyn_range) {
    	        dlgAddMultiSelectListItem(NULL,i, IM_WAYPOINT, Dist);
            }
        }
    }

#ifdef FLARM_MS
    if((MapWindow::mode.Is(MapWindow::Mode::MODE_PAN) || MapWindow::mode.Is(MapWindow::Mode::MODE_TARGET_PAN))) {
        LastDoTraffic=0;
        DoTraffic(&DrawInfo,&DerivedDrawInfo);
        for (unsigned i=0; i<FLARM_MAX_TRAFFIC; ++i) {
	    if (LKTraffic[i].Status != LKT_EMPTY) {
                DistanceBearing(lat,lon, LKTraffic[i].Latitude, LKTraffic[i].Longitude, &Dist, NULL);
                if(Dist < range) {
    	            dlgAddMultiSelectListItem((long*)&LKTraffic[i],i, IM_FLARM, Dist);
                }
            }
        }
    }
#endif

    int  HorDist=0, Bearing=0, VertDist=0; 
    CAirspaceList reslist = CAirspaceManager::Instance().GetNearAirspacesAtPoint(lon, lat, (int)(dyn_range/2));

    for (CAirspaceList::const_iterator it = reslist.begin(); it != reslist.end(); ++it) {
        LKASSERT((*it));
        (*it)->CalculateDistance(&HorDist, &Bearing, &VertDist,lon, lat);
        dlgAddMultiSelectListItem((long*) (*it),0, IM_AIRSPACE, HorDist);
    }


    for(i=1;i<WayPointList.size();i++) {    // Consider only valid markers
        if ((WayPointCalc[i].WpType != WPT_AIRPORT)|| (WayPointCalc[i].WpType != WPT_OUTLANDING)) {
            DistanceBearing(lat,lon, WayPointList[i].Latitude, WayPointList[i].Longitude, &Dist, NULL);
            if(Dist < (dyn_range)) {
    	        dlgAddMultiSelectListItem(NULL,i, IM_WAYPOINT, Dist);
            }
        }
    }


    // TASK MULTISELECT
    int SecType= DAe;
    double SecRadius =0;
    double Bear=0;
    bool Angleinside = false;

    LockTaskData();
    for(i=0; ValidTaskPoint(i); i++) {
        LKASSERT(Task[i].Index <=(int)WayPointList.size());
        DistanceBearing(lat,lon,
            WayPointList[Task[i].Index].Latitude,
            WayPointList[Task[i].Index].Longitude, &Dist, &Bear);

        GetTaskSectorParameter(i, &SecType, &SecRadius);

        Angleinside = true;
        if( SecRadius < (dyn_range)) SecRadius =dyn_range;

        if((Dist < SecRadius) && Angleinside) {
  	    dlgAddMultiSelectListItem(NULL,i, IM_TASK_PT, Dist);
        }
    }
    UnlockTaskData();

    #if (WINDOWSPC>0)
    if (EnableSoundModes) Poco::Thread::sleep(1000); // let the sound be heard in sequence
    #endif
    if(dlgGetNoElements() ==0) { 
        if(dyn_range < 120000) {
            dyn_range *=2;
            goto start_search;
        } else {
            DoStatusMessage(gettext(TEXT("_@M2248_")));  // _@M2248_  "No Near Object found!"
        }
    } else {
        LKSound(TEXT("LK_GREEN.WAV"));
        dlgMultiSelectListShowModal();
        if(ValidTaskPoint(PanTaskEdit)) {
            MapWindow::Event_Pan(1);
        }
        return true;
    }

    return false;
}
예제 #8
0
//
// Running every n seconds ONLY when the nearest airspace page is active and we are not drawing map.
// Returns true if did calculations, false if ok to use old values
bool DoAirspaces(NMEA_INFO *Basic, DERIVED_INFO *Calculated)
{

   static int step = 0;
   bool ret = false;
   
   if (DoInit[MDI_DOAIRSPACES]) {
	memset(LKAirspaces, 0, sizeof(LKAirspaces));
	LKNumAirspaces=0;
	memset(LKSortedAirspaces, -1, sizeof(LKSortedAirspaces));
    for (int i=0; i<MAXNEARAIRSPACES; i++) {
      LKAirspaces[i].Valid = false;
      LKAirspaces[i].Pointer = NULL;
    }
	DoInit[MDI_DOAIRSPACES]=false;
	return true;
   }

   // DoAirspaces is called from MapWindow, in real time. We have enough CPU power there now
   // Consider replay mode...
   // Multicalc used below, we don't need this
   //if (  LastDoAirspaces > Basic->Time ) LastDoAirspaces=Basic->Time;
   //if ( Basic->Time < (LastDoAirspaces+PAGINGTIMEOUT) ) { 
   //  return false;
   //}

   // We need a valid GPS fix in FLY mode
   if (Basic->NAVWarning && !SIMMODE) return true;

   LastDoAirspaces=Basic->Time;
   
   #ifdef DEBUG_LKT
   StartupStore(_T("... DoAirspaces step%d started\n"),step);
   #endif


   switch (step) {
     // MULTICALC STEP0 - select airspaces in range based on bounds
     default:
     case 0:
        CAirspaceManager::Instance().SelectAirspacesForPage24(Basic->Latitude, Basic->Longitude, 100000.0);        // 100km
        ++step;
        break;
          
     // MULTICALC STEP1 - Do distance calculations on selected airspaces
     case 1:
        CAirspaceManager::Instance().CalculateDistancesForPage24();
        ++step;
        break;
        
     // MULTICALC STEP2 - Sort by different keys, and fill up result struct array
     case 2:
        // Lock airspace instances externally
        CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef());
        // Get selected list from airspacemanager
        CAirspaceList airspaces = CAirspaceManager::Instance().GetAirspacesForPage24();
        // Sort selected airspaces by distance first
        std::sort(airspaces.begin(), airspaces.end(), airspace_distance_sorter);
        // get first MAXNEARAIRSPACES to a new list
        CAirspaceList nearest_airspaces;
        CAirspaceList::iterator it = airspaces.begin();
        for (int i=0; (i<MAXNEARAIRSPACES) && (it!=airspaces.end()); ++i, ++it) nearest_airspaces.push_back(*it);
        airspaces.clear();

        //sort by given key
          switch (SortedMode[MSM_AIRSPACES]) {
              case 0: 
                  // ASP NAME
                  std::sort(nearest_airspaces.begin(), nearest_airspaces.end(), airspace_name_sorter);
                  break;
              case 1:
                  // ASP TYPE
                  std::sort(nearest_airspaces.begin(), nearest_airspaces.end(), airspace_type_sorter);
                  break;
                  
              default:
              case 2:
                  // ASP DISTANCE
                  // we don't need sorting, already sorted by distance
                  break;
              case 3:
                  // ASP BEARING
                  std::sort(nearest_airspaces.begin(), nearest_airspaces.end(), airspace_bearing_sorter);
                  break;
              case 4:
                  // ACTIVE / NOT ACTIVE
                  std::sort(nearest_airspaces.begin(), nearest_airspaces.end(), airspace_enabled_sorter);
                  break;
          } //sw

          // Clear results
          memset(LKSortedAirspaces, -1, sizeof(LKSortedAirspaces));
          LKNumAirspaces=0;
          for (int i=0; i<MAXNEARAIRSPACES; i++) {
              LKAirspaces[i].Valid = false;
              LKAirspaces[i].Pointer = NULL;
          }
          //copy result data to interface structs
          // we dont need LKSortedAirspaces[] array, every item will be
          // in correct order in airspaces list, thanks to std::sort,
          // we just fill up LKAirspaces[] array in the right order.
          int i = 0;
          for (it=nearest_airspaces.begin(); it!=nearest_airspaces.end(); ++it) {
              // sort key not used, iterator goes in right order after std::sort
              LKSortedAirspaces[i] = i;
              // copy name
              LK_tcsncpy(LKAirspaces[i].Name, (*it)->Name(), NAME_SIZE);
              // copy type string (type string comes from centralized type->str conversion function of CAirspaceManager)
              LK_tcsncpy(LKAirspaces[i].Type, CAirspaceManager::Instance().GetAirspaceTypeShortText((*it)->Type()), 4);

              // copy distance
              LKAirspaces[i].Distance = max((*it)->LastCalculatedHDistance(),0);
              // copy bearing
              LKAirspaces[i].Bearing = (*it)->LastCalculatedBearing();
              // copy Enabled()
              LKAirspaces[i].Enabled = (*it)->Enabled();
              // copy Selected()
              LKAirspaces[i].Selected = (*it)->Selected();
              // copy Flyzone()
              LKAirspaces[i].Flyzone = (*it)->Flyzone();
              // copy WarningLevel()
              LKAirspaces[i].WarningLevel = (*it)->WarningLevel();
              // copy WarningAckLevel()
              LKAirspaces[i].WarningAckLevel = (*it)->WarningAckLevel();
              
              // copy pointer
              LKAirspaces[i].Pointer = (*it);
              
              // Record is valid now.
              LKAirspaces[i].Valid = true;
              
              i++;
              if (i>=MAXNEARAIRSPACES) break;
          }
          LKNumAirspaces=i;
          ret = true;       // ok to use new values.
          step = 0;
          break;
   } //sw step
   
   #ifdef DEBUG_LKT
   StartupStore(_T("... DoAirspaces finished, LKNumAirspaces=%d :\n"), LKNumAirspaces);
   // For sorting debug only
   /*for (i=0; i<MAXNEARAIRSPACES; i++) {
	if (LKSortedAirspaces[i]>=0)
		StartupStore(_T("... LKSortedAirspaces[%d]=LKAirspaces[%d] Name=<%s> Type=<%s> Dist=%2.0f beardiff=%2.0f enabled=%s\n"), i, 
			LKSortedAirspaces[i],
			LKAirspaces[LKSortedAirspaces[i]].Name,
			LKAirspaces[LKSortedAirspaces[i]].Type,
            LKAirspaces[LKSortedAirspaces[i]].Distance,
            LKAirspaces[LKSortedAirspaces[i]].Bearing_difference,
            LKAirspaces[LKSortedAirspaces[i]].Enabled ? _TEXT("true"):_TEXT("false"));
   }*/
   #endif

   return ret;
}
예제 #9
0
bool dlgAirspaceWarningShowDlg(bool Force){

  if (fDialogOpen)
    return(false);
#ifndef LKAIRSPACE
  if (!actShow && !Force)
    return false;
#endif
#ifdef LKAIRSPACE
	airspaces = CAirspaceManager::Instance().GetAirspacesInWarning();
    Count = airspaces.size();
#else
  Count = AirspaceWarnGetItemCount();
#endif
  if (Count == 0)
    return(false);

  if (wf==NULL) {
	StartupStore(_T("------ BAD SW ERROR AirspaceWarningDlg problem no window!%s"),NEWLINE);
	FailStore(_T("BAD SW ERROR AirspaceWarningDlg problem no window!"));
	return(false);
  }
  if (wAirspaceList==NULL) {
	StartupStore(_T("------ BAD SW ERROR AirspaceList empty!%s"),NEWLINE);
	FailStore(_T("BAD SW ERROR AirspaceList empty!"));
	return(false);
  }

  wAirspaceList->ResetList();

  if (!fDialogOpen) {
    fDialogOpen = true;
    #ifndef DISABLEAUDIO
    if (EnableSoundModes) LKSound(_T("LK_AIRSPACE.WAV")); // 100819
    #endif
    HWND oldFocusHwnd = GetFocus();
    wf->ShowModal();
    if (oldFocusHwnd) {
      SetFocus(oldFocusHwnd);
    }


    // JMW need to deselect everything on new reopening of dialog
#ifndef LKAIRSPACE
    SelectedID = -1;
#endif
    SelectedIdx = -1;
#ifndef LKAIRSPACE
    FocusedID = -1;
#endif
    FocusedIdx = -1;
#ifdef LKAIRSPACE
	airspaces.clear();
#endif
    fDialogOpen = false;

    //    SetFocus(hWndMapWindow);
    // JMW why do this? --- not necessary?
    // concerned it may interfere if a dialog is already open
  }

  return(true);
}
예제 #10
0
static void OnAirspaceListItemPaint(WindowControl * Sender, HDC hDC){
  TCHAR sTmp[128];

  if (Count != 0){

#ifndef LKAIRSPACE
    TCHAR sAckIndicator[6] = TEXT(" -++*");
#endif
	TCHAR sName[21];
    TCHAR sTop[32];
    TCHAR sBase[32];
    TCHAR sType[32];
    AIRSPACE_ALT Base;
    AIRSPACE_ALT Top;
    int i = DrawListIndex;
#ifndef LKAIRSPACE
    AirspaceInfo_c pAS;
#endif
    int          Type;
    int          TextHeight = 12;
    int          TextTop = 1;
    int          Col0Left = 3;
    int          Col1Left = 120;
    RECT         rc;
    RECT         rcTextClip;
    HBRUSH       hBrushBk = NULL;

    if (i>=Count) return;

    CopyRect(&rc, Sender->GetBoundRect());
    CopyRect(&rcTextClip, Sender->GetBoundRect());
    rcTextClip.right = IBLSCALE(Col1Left - 2);

    InflateRect(&rc, IBLSCALE(-2), IBLSCALE(-2));
#ifdef LKAIRSPACE
	if (i>=(int)airspaces.size()) return;
	// Method: get an airspace object copy from CAirspaceManager to use it in this thread indepently
	CAirspace airspace_copy = CAirspaceManager::Instance().GetAirspaceCopy(airspaces[i]);
    if (ItemIndex == DrawListIndex) {
      FocusedIdx = ItemIndex;
    }
#else
    if (!AirspaceWarnGetItem(i, pAS)) return;
    if (ItemIndex == DrawListIndex){
      FocusedID = pAS.ID;
    }
#endif

#ifdef LKAIRSPACE
	_tcsncpy(sName, airspace_copy.Name(), sizeof(sName)/sizeof(sName[0]));
    sName[sizeof(sName)/sizeof(sName[0])-1] = '\0';
	memcpy(&Base, airspace_copy.Base(), sizeof(Base));
	memcpy(&Top, airspace_copy.Top(), sizeof(Top));
	Type = airspace_copy.Type();

	CAirspaceManager::Instance().GetAirspaceAltText(sTop, sizeof(sTop)/sizeof(sTop[0]), &Top); 
	CAirspaceManager::Instance().GetAirspaceAltText(sBase, sizeof(sBase)/sizeof(sBase[0]), &Base); 
	_tcsncpy(sType, CAirspaceManager::Instance().GetAirspaceTypeShortText(Type), 4);
#else
    if (pAS.IsCircle){
      _tcsncpy(sName, AirspaceCircle[pAS.AirspaceIndex].Name, 
	       sizeof(sName)/sizeof(sName[0]));
      Base = AirspaceCircle[pAS.AirspaceIndex].Base;
      Top  = AirspaceCircle[pAS.AirspaceIndex].Top;
      Type = AirspaceCircle[pAS.AirspaceIndex].Type;
    } else {
      _tcsncpy(sName, AirspaceArea[pAS.AirspaceIndex].Name, 
	       sizeof(sName)/sizeof(sName[0]));
      Base = AirspaceArea[pAS.AirspaceIndex].Base;
      Top  = AirspaceArea[pAS.AirspaceIndex].Top;
      Type = AirspaceArea[pAS.AirspaceIndex].Type;
    }

    if (_tcslen(sName)>0) // 100324
    sName[sizeof(sName)/sizeof(sName[0])-1] = '\0';

    fmtAirspaceAlt(sTop, &Top);
    fmtAirspaceAlt(sBase, &Base);
    getAirspaceType(sType, Type);
#endif

#ifdef LKAIRSPACE
	// Select brush based on warning and ack level
	hBrushBk = hBrushNormal;
	  if (airspace_copy.WarningLevel() == awYellow) {
		if (airspace_copy.WarningAckLevel() >= awYellow) {
		  hBrushBk = hBrushNearAckBk;
		} else {
		  hBrushBk = hBrushNearBk;
		}
	  }
	  
	  if (airspace_copy.WarningLevel() == awRed) {
		if (airspace_copy.WarningAckLevel() >= awRed) {
		  hBrushBk = hBrushInsideAckBk;
		} else {
		  hBrushBk = hBrushInsideBk;
		}
	  }
#else
    if (pAS.Inside){
      if (pAS.Acknowledge >= 3)
        hBrushBk = hBrushInsideAckBk;
      else
        hBrushBk = hBrushInsideBk;
    } else { 
      if ((pAS.hDistance < 2500) && (abs(pAS.vDistance) < 250)) {
        if (pAS.Acknowledge >= 1) 
          hBrushBk = hBrushNearAckBk;
        else
          hBrushBk = hBrushNearBk;
	  }
    }
#endif
    
    if (SelectedIdx == DrawListIndex){
      InflateRect(&rc, 1, 1);
      SelectObject(hDC, (HPEN)GetStockObject(BLACK_PEN));
      Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
    } else {
      FillRect(hDC, &rc, hBrushBk);
    }

#ifdef LKAIRSPACE
    if ((airspace_copy.WarningAckLevel() > 0) && (airspace_copy.WarningAckLevel() >= airspace_copy.WarningLevel())) {
      SetTextColor(hDC, clGray);
    }

    #if defined(DEBUG)
    wsprintf(sTmp, TEXT("%-20s%d"), sName , airspace_copy.WarningLevel() - airspace_copy.WarningAckLevel() );
    #else
    if (_tcslen(sName)>0) wsprintf(sTmp, TEXT("%-20s"), sName);  //@ FIX ATTEMPT 101027
	else _tcscpy(sTmp,_T("UNKNOWN")); //@ 101027
    #endif
#else
    if ((pAS.Acknowledge > 0) && (pAS.Acknowledge >= pAS.WarnLevel)){
      SetTextColor(hDC, clGray);
    }

    #if defined(DEBUG)
    wsprintf(sTmp, TEXT("%-20s%d"), sName , pAS.WarnLevel - pAS.Acknowledge);
    #else
    if (_tcslen(sName)>0) wsprintf(sTmp, TEXT("%-20s"), sName);  //@ FIX ATTEMPT 101027
	else _tcscpy(sTmp,_T("UNKNOWN")); //@ 101027
    #endif
#endif
	
    ExtTextOut(hDC, IBLSCALE(Col0Left), IBLSCALE(TextTop),
      ETO_CLIPPED, &rcTextClip, sTmp, _tcslen(sTmp), NULL);

    wsprintf(sTmp, TEXT("%-20s"), sTop);

    ExtTextOut(hDC, IBLSCALE(Col1Left), IBLSCALE(TextTop),
      ETO_OPAQUE, NULL, sTmp, _tcslen(sTmp), NULL);

    wsprintf(sTmp, TEXT("%-20s"), sBase);

    ExtTextOut(hDC, IBLSCALE(Col1Left), IBLSCALE(TextTop+TextHeight),
      ETO_OPAQUE, NULL, sTmp, _tcslen(sTmp), NULL);
#ifdef LKAIRSPACE
	int hdistance;
	int vdistance;
	int bearing;
	bool inside;
	
	// Unfortunatelly virtual methods don't work on copied instances
	// we have to ask airspacemanager to perform the required calculations
	//inside = airspace_copy.CalculateDistance(&hdistance, &bearing, &vdistance);
	//inside = CAirspaceManager::Instance().AirspaceCalculateDistance(airspaces[i], &hdistance, &bearing, &vdistance);
	bool distances_ready = airspace_copy.GetDistanceInfo(inside, hdistance, bearing, vdistance);
	
	switch (airspace_copy.WarningLevel()) {
	  default:
		if (inside) {
		  wsprintf(sTmp, TEXT("> %c %s"), GetAckIndicator(airspace_copy.WarningAckLevel()), sType );
		} else {
		  wsprintf(sTmp, TEXT("< %c %s"), GetAckIndicator(airspace_copy.WarningAckLevel()), sType );
		}
		break;
	  case awRed:
		if (inside) {
		  wsprintf(sTmp, TEXT("> %c %s %s"), GetAckIndicator(airspace_copy.WarningAckLevel()), sType, gettext(TEXT("_@M789_")));	//LKTOKEN _@M789_ "Warn"
		} else {
		  wsprintf(sTmp, TEXT("< %c %s %s"), GetAckIndicator(airspace_copy.WarningAckLevel()), sType, gettext(TEXT("_@M789_")));	//LKTOKEN _@M789_ "Warn"
		}
		break;
		
	  case awYellow:
		TCHAR DistanceText[MAX_PATH];
		if (!airspace_copy.Flyzone()) {
		  //Non fly zone
		  if (distances_ready) {
			if (hdistance <= 0) {
			  // Directly above or below airspace
			  Units::FormatUserAltitude(fabs(vdistance),DistanceText, 7);
			  if (vdistance > 0) {
				wsprintf(sTmp, TEXT("< %c %s ab %s"), 
						GetAckIndicator(airspace_copy.WarningAckLevel()), 
						sType, DistanceText);
			  } else {
				wsprintf(sTmp, TEXT("< %c %s bl %s"), 
						GetAckIndicator(airspace_copy.WarningAckLevel()), 
						sType, DistanceText);
			  }
			} else {
				// Horizontally separated
				Units::FormatUserDistance(fabs(hdistance),DistanceText, 7);
				wsprintf(sTmp, TEXT("< %c %s H %s"), GetAckIndicator(airspace_copy.WarningAckLevel()),
						sType, DistanceText);
			}
		  } else {
			// distance info not available
			wsprintf(sTmp, TEXT("< %c %s ---"), GetAckIndicator(airspace_copy.WarningAckLevel()), sType );
		  }
		} else {
		  //Fly zone
		  if (distances_ready) {
			if ( abs(hdistance) > abs(vdistance)*30) {
			  // vDist smaller than horizontal
			  Units::FormatUserAltitude(fabs(vdistance),DistanceText, 7);
			  if (vdistance > 0) {
				wsprintf(sTmp, TEXT("> %c %s ab %s"), 
						GetAckIndicator(airspace_copy.WarningAckLevel()), 
						sType, DistanceText);
			  } else {
				wsprintf(sTmp, TEXT("> %c %s bl %s"), 
						GetAckIndicator(airspace_copy.WarningAckLevel()), 
						sType, DistanceText);
			  }
			} else {
				// Horizontally separated
				Units::FormatUserDistance(fabs(hdistance),DistanceText, 7);
				wsprintf(sTmp, TEXT("> %c %s H %s"), GetAckIndicator(airspace_copy.WarningAckLevel()),
						sType, DistanceText);
			}
		  } else {
			// distance info not available
			wsprintf(sTmp, TEXT("> %c %s ---"), GetAckIndicator(airspace_copy.WarningAckLevel()), sType );
		  }
		}
		break;
    }//sw
#else
    if (pAS.Inside){
      wsprintf(sTmp, TEXT("> %c %s"), sAckIndicator[pAS.Acknowledge], sType);
    } else {
      TCHAR DistanceText[MAX_PATH];
      if (pAS.hDistance == 0) {

        // Directly above or below airspace

        Units::FormatUserAltitude(fabs((double)pAS.vDistance),DistanceText, 7);
        if (pAS.vDistance > 0) {
          wsprintf(sTmp, TEXT("< %c %s ab %s"), 
                   sAckIndicator[pAS.Acknowledge], 
                   sType, DistanceText);
        }
        if (pAS.vDistance < 0) {
          Units::FormatUserAltitude(fabs((double)pAS.vDistance),DistanceText, 7);
          wsprintf(sTmp, TEXT("< %c %s bl %s"), 
                   sAckIndicator[pAS.Acknowledge], 
                   sType, DistanceText);
        }
      } else {
        if ((pAS.vDistance == 0) || 
            (pAS.hDistance < abs(pAS.vDistance)*30 )) {

          // Close to airspace altitude, horizontally separated

          Units::FormatUserDistance(fabs((double)pAS.hDistance),DistanceText, 7);
          wsprintf(sTmp, TEXT("< %c %s H %s"), sAckIndicator[pAS.Acknowledge],
                   sType, DistanceText);
        } else {

          // Effectively above or below airspace, steep climb or descent 
          // necessary to enter

          Units::FormatUserAltitude(fabs((double)pAS.vDistance),DistanceText, 7);
          if (pAS.vDistance > 0) {
            wsprintf(sTmp, TEXT("< %c %s ab %s"), 
                     sAckIndicator[pAS.Acknowledge], 
                     sType, DistanceText); 
          } else {
            wsprintf(sTmp, TEXT("< %c %s bl %s"), 
                     sAckIndicator[pAS.Acknowledge], sType, 
                     DistanceText);
          }
        }
      }
    }
#endif  
    ExtTextOut(hDC, IBLSCALE(Col0Left), IBLSCALE(TextTop+TextHeight),
      ETO_CLIPPED, &rcTextClip, sTmp, _tcslen(sTmp), NULL);

  } else {
    if (DrawListIndex == 0){
	// LKTOKEN  _@M469_ = "No Warnings" 
      _stprintf(sTmp, TEXT("%s"), gettext(TEXT("_@M469_")));
      ExtTextOut(hDC, NIBLSCALE(2), NIBLSCALE(2),
        ETO_OPAQUE, NULL,
        sTmp, _tcslen(sTmp), NULL);
    }
  }
}