+public:
+ bool operator()(FGPositioned* a, FGPositioned* b) const
+ {
+ return a->name() < b->name();
+ }
+};
+
+/**
+ * A special purpose helper (imported by FGAirport::searchNamesAndIdents) to
+ * implement the AirportList dialog. It's unfortunate that it needs to reside
+ * here, but for now it's least ugly solution.
+ */
+char** searchAirportNamesAndIdents(const std::string& aFilter)
+{
+ const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(std::locale());
+ std::string filter(aFilter);
+ bool hasFilter = !filter.empty();
+ if (hasFilter) {
+ ct.toupper((char *)filter.data(), (char *)filter.data() + filter.size());
+ }
+
+ NamedPositionedIndex::const_iterator it = global_namedIndex.begin();
+ NamedPositionedIndex::const_iterator end = global_namedIndex.end();
+
+ // note this is a vector of raw pointers, not smart pointers, because it
+ // may get very large and smart-pointer-atomicity-locking then becomes a
+ // bottleneck for this case.
+ std::vector<FGPositioned*> matches;
+ std::string upper;
+
+ for (; it != end; ++it) {
+ FGPositioned::Type ty = it->second->type();
+ if ((ty < FGPositioned::AIRPORT) || (ty > FGPositioned::SEAPORT)) {
+ continue;
+ }
+
+ if (hasFilter && (it->second->ident().find(aFilter) == std::string::npos)) {
+ upper = it->second->name(); // string copy, sadly
+ ct.toupper((char *)upper.data(), (char *)upper.data() + upper.size());
+ if (upper.find(aFilter) == std::string::npos) {
+ continue;
+ }
+ }
+
+ matches.push_back(it->second);
+ }
+
+ // sort alphabetically on name
+ std::sort(matches.begin(), matches.end(), OrderByName());
+
+ // convert results to format comptible with puaList
+ unsigned int numMatches = matches.size();
+ char** result = new char*[numMatches + 1];
+ result[numMatches] = NULL; // end-of-list marker
+
+ // nasty code to avoid excessive string copying and allocations.
+ // We format results as follows (note whitespace!):
+ // ' name-of-airport-chars (ident)'
+ // so the total length is:
+ // 1 + strlen(name) + 4 + 4 (for the ident) + 1 + 1 (for the null)
+ // which gives a grand total of 11 + the length of the name.
+ // note the ident is sometimes only three letters for non-ICAO small strips
+ for (unsigned int i=0; i<numMatches; ++i) {
+ int nameLength = matches[i]->name().size();
+ int icaoLength = matches[i]->ident().size();
+ char* entry = new char[nameLength + 11];
+ char* dst = entry;
+ *dst++ = ' ';
+ memcpy(dst, matches[i]->name().c_str(), nameLength);
+ dst += nameLength;
+ *dst++ = ' ';
+ *dst++ = ' ';
+ *dst++ = ' ';
+ *dst++ = '(';
+ memcpy(dst, matches[i]->ident().c_str(), icaoLength);
+ dst += icaoLength;
+ *dst++ = ')';
+ *dst++ = 0;
+ result[i] = entry;
+ }
+
+ return result;