gcc_pure static Path::const_pointer LastSeparator(Path::const_pointer path) { const auto *p = StringFindLast(path, _T('/')); #ifdef WIN32 const auto *backslash = StringFindLast(path, _T('\\')); if (p == nullptr || backslash > p) p = backslash; #endif return p; }
gcc_pure static const TCHAR * LastSeparator(const TCHAR *path) { const auto *p = StringFindLast(path, _T('/')); #ifdef WIN32 const auto *backslash = StringFindLast(path, _T('\\')); if (p == nullptr || backslash > p) p = backslash; #endif return p; }
Path::const_pointer Path::GetExtension() const { auto base = GetBase(); if (base == nullptr) return nullptr; assert(!StringIsEmpty(base.c_str())); return StringFindLast(base.c_str() + 1, _T('.')); }
gcc_pure static const TCHAR * BackslashBaseName(const TCHAR *p) { if (DIR_SEPARATOR != '\\') { const auto *backslash = StringFindLast(p, _T('\\')); if (backslash != NULL) p = backslash + 1; } return BaseName(p); }
const TCHAR * ProfileMap::GetPathBase(const char *key) const { TCHAR buffer[MAX_PATH]; if (!Get(key, buffer, ARRAY_SIZE(buffer))) return nullptr; const TCHAR *p = buffer; if (DIR_SEPARATOR != '\\') { const auto *backslash = StringFindLast(p, _T('\\')); if (backslash != NULL) p = backslash + 1; } return BaseName(p); }
static bool ParseRunwayDirection(const TCHAR* src, Runway &dest) { // WELT2000 written files contain a 4-digit runway direction specification // at the end of the comment, e.g. "123.50 0927" const auto *start = StringFindLast(src, _T(' ')); if (start) start++; else start = src; TCHAR *end; int value = _tcstol(start, &end, 10); if (start == end || *end != _T('\0') || end - start != 4 ) return false; int a1 = (value / 100) * 10; int a2 = (value % 100) * 10; if (a1 < 0 || a1 > 360 || a2 < 0 || a2 > 360) return false; if (a1 == 360) a1 = 0; if (a2 == 360) a2 = 0; // TODO: WELT2000 generates quite a few entries where // a) a1 == a2 (accept those) and // b) the angles are neither equal or reciprocal (discard those) // Try finding a logic behind this behaviour. if (a1 != a2 && (a1 + 180) % 360 != a2) return false; dest.SetDirectionDegrees(a1); return true; }
void Canvas::DrawFormattedText(PixelRect *rc, const TCHAR *text, unsigned format) { assert(text != nullptr); #ifndef UNICODE assert(ValidateUTF8(text)); #endif if (font == nullptr) return; unsigned skip = font->GetLineSpacing(); unsigned max_lines = (format & DT_CALCRECT) ? -1 : (rc->bottom - rc->top + skip - 1) / skip; size_t len = _tcslen(text); TCHAR *duplicated = new TCHAR[len + 1], *p = duplicated; unsigned lines = 1; for (const TCHAR *i = text; *i != _T('\0'); ++i) { TCHAR ch = *i; if (ch == _T('\n')) { /* explicit line break */ if (++lines >= max_lines) break; ch = _T('\0'); } else if (ch == _T('\r')) /* skip */ continue; else if ((unsigned)ch < 0x20) /* replace non-printable characters */ ch = _T(' '); *p++ = ch; } *p = _T('\0'); len = p - duplicated; // simple wordbreak algorithm. looks for single spaces only, no tabs, // no grouping of multiple spaces if (format & DT_WORDBREAK) { for (size_t i = 0; i < len; i += _tcslen(duplicated + i) + 1) { PixelSize sz = CalcTextSize(duplicated + i); TCHAR *prev_p = nullptr; // remove words from behind till line fits or no more space is found while (sz.cx > rc->right - rc->left && (p = StringFindLast(duplicated + i, _T(' '))) != nullptr) { if (prev_p) *prev_p = _T(' '); *p = _T('\0'); prev_p = p; sz = CalcTextSize(duplicated + i); } if (prev_p) { lines++; if (lines >= max_lines) break; } } } if (format & DT_CALCRECT) { rc->bottom = rc->top + lines * skip; delete[] duplicated; return; } int y = (format & DT_VCENTER) && lines < max_lines ? (rc->top + rc->bottom - lines * skip) / 2 : rc->top; for (size_t i = 0; i < len; i += _tcslen(duplicated + i) + 1) { if (duplicated[i] != _T('\0')) { int x; if (format & (DT_RIGHT | DT_CENTER)) { PixelSize sz = CalcTextSize(duplicated + i); x = (format & DT_CENTER) ? (rc->left + rc->right - sz.cx)/2 : rc->right - sz.cx; // DT_RIGHT } else { // default is DT_LEFT x = rc->left; } TextAutoClipped(x, y, duplicated + i); if (format & DT_UNDERLINE) DrawHLine(x, x + CalcTextWidth(duplicated + i), y + font->GetAscentHeight() + 1, text_color); } y += skip; if (y >= rc->bottom) break; } delete[] duplicated; }