static void ChangeCompetitionId(FlarmDevice &flarm, OperationEnvironment &env) { while (true) { TCHAR old_id[64]; if (flarm.GetCompetitionId(old_id, 64, env)) _tprintf(_T("Old competition id: \"%s\"\n"), old_id); fprintf(stdout, "Please enter the new competition id:\n"); fprintf(stdout, "> "); char id[64]; if (fgets(id, 64, stdin) == NULL || strlen(id) == 0) { fprintf(stdout, "Invalid input\n"); continue; } StripRight(id); fprintf(stdout, "Setting competition id to \"%s\" ...\n", id); const UTF8ToWideConverter value(id); if (flarm.SetCompetitionId(value, env)) fprintf(stdout, "competition id set to \"%s\"\n", id); else fprintf(stdout, "Operation failed!\n"); return; } }
static void ChangeRegistration(FlarmDevice &flarm, OperationEnvironment &env) { while (true) { TCHAR old_registration[64]; if (flarm.GetPlaneRegistration(old_registration, 64, env)) _tprintf(_T("Old plane registratio: \"%s\"\n"), old_registration); fprintf(stdout, "Please enter the new plane registration:\n"); fprintf(stdout, "> "); char registration[64]; if (fgets(registration, 64, stdin) == NULL || strlen(registration) == 0) { fprintf(stdout, "Invalid input\n"); continue; } StripRight(registration); fprintf(stdout, "Setting plane registration to \"%s\" ...\n", registration); const UTF8ToWideConverter value(registration); if (flarm.SetPlaneRegistration(value, env)) fprintf(stdout, "Plane registration set to \"%s\"\n", registration); else fprintf(stdout, "Operation failed!\n"); return; } }
/* Filtern einer Zeile: - Umwandeln von nicht-IGC-Zeichen in Leerzeichen - Entfernen von Leer- und Sonderzeichen am Ende */ char *igc_filter(char *st) { for (char *p = st; *p != 0; ++p) if (!IsAllowedIGCChar(*p)) *p = ' '; StripRight(st); return st; }
static void ChangeCoPilot(FlarmDevice &flarm, OperationEnvironment &env) { while (true) { TCHAR old_copilot_name[64]; if (flarm.GetCoPilot(old_copilot_name, 64, env)) _tprintf(_T("Old copilot name: \"%s\"\n"), old_copilot_name); fprintf(stdout, "Please enter the new copilot name:\n"); fprintf(stdout, "> "); char copilot_name[64]; if (fgets(copilot_name, 64, stdin) == NULL || strlen(copilot_name) == 0) { fprintf(stdout, "Invalid input\n"); continue; } StripRight(copilot_name); fprintf(stdout, "Setting copilot name to \"%s\" ...\n", copilot_name); const UTF8ToWideConverter value(copilot_name); if (flarm.SetCoPilot(value, env)) fprintf(stdout, "CoPilot name set to \"%s\"\n", copilot_name); else fprintf(stdout, "Operation failed!\n"); return; } }
static void ChangePlaneType(FlarmDevice &flarm, OperationEnvironment &env) { while (true) { TCHAR old_plane_type[64]; if (flarm.GetPlaneType(old_plane_type, 64, env)) _tprintf(_T("Old plane type: \"%s\"\n"), old_plane_type); fprintf(stdout, "Please enter the new plane type:\n"); fprintf(stdout, "> "); char plane_type[64]; if (fgets(plane_type, 64, stdin) == NULL || strlen(plane_type) == 0) { fprintf(stdout, "Invalid input\n"); continue; } StripRight(plane_type); fprintf(stdout, "Setting plane type to \"%s\" ...\n", plane_type); const UTF8ToWideConverter value(plane_type); if (flarm.SetPlaneType(value, env)) fprintf(stdout, "Plane type set to \"%s\"\n", plane_type); else fprintf(stdout, "Operation failed!\n"); return; } }
static const char * ParseLine(char *line) { char *separator = strchr(line, '='); if (separator == nullptr) /* malformed line */ return nullptr; char *p = StripRight(line, separator); if (p == line) /* empty name */ return nullptr; *p = 0; char *value = const_cast<char *>(StripLeft(separator + 1)); StripRight(value); return value; }
int main(int argc, char **argv) { NarrowString<1024> usage; usage = "DRIVER\n\n" "Where DRIVER is one of:"; { const DeviceRegister *driver; for (unsigned i = 0; (driver = GetDriverByIndex(i)) != nullptr; ++i) { WideToUTF8Converter driver_name(driver->name); usage.AppendFormat("\n\t%s", (const char *)driver_name); } } Args args(argc, argv, usage); tstring driver_name = args.ExpectNextT(); args.ExpectEnd(); driver = FindDriverByName(driver_name.c_str()); if (driver == nullptr) { _ftprintf(stderr, _T("No such driver: %s\n"), driver_name.c_str()); return 1; } DeviceConfig config; config.Clear(); NullPort port; Device *device = driver->CreateOnPort != nullptr ? driver->CreateOnPort(config, port) : nullptr; NMEAParser parser; NMEAInfo data; data.Reset(); char buffer[1024]; while (fgets(buffer, sizeof(buffer), stdin) != nullptr) { StripRight(buffer); if (device == nullptr || !device->ParseNMEA(buffer, data)) parser.ParseLine(buffer, data); } Dump(data); return EXIT_SUCCESS; }
void Plane::GenerateIndices(GLuint* indices, unsigned int width, unsigned int height){ unsigned int i, j; //Generate initial index i = 0; indices[i++] = 0; //And the rest for (j = 0; j < height; ++j){ if (j % 2 == 0){ StripRight(indices, width, j, i); } else { StripLeft(indices, width, j, i); } } }
/** * Decodes the FlarmNet.org file and puts the wanted * characters into the res pointer * @param file File handle * @param charCount Number of character to decode * @param res Pointer to be written in */ static void LoadString(const char *bytes, size_t length, TCHAR *res, size_t res_size) { const char *const end = bytes + length * 2; #ifndef _UNICODE const char *const limit = res + res_size - 2; #endif TCHAR *p = res; char tmp[3]; tmp[2] = 0; while (bytes < end) { tmp[0] = *bytes++; tmp[1] = *bytes++; /* FLARMNet files are ISO-Latin-1, which is kind of short-sighted */ const unsigned char ch = (unsigned char)strtoul(tmp, NULL, 16); #ifdef _UNICODE /* Latin-1 can be converted to WIN32 wchar_t by casting */ *p++ = ch; #else /* convert to UTF-8 on all other platforms */ if (p >= limit) break; p = Latin1ToUTF8(ch, p); #endif } *p = 0; #ifndef _UNICODE assert(ValidateUTF8(res)); #endif // Trim the string of any additional spaces StripRight(res); }
inline void TeamCodeWidget::OnCodeClicked() { TCHAR newTeammateCode[10]; CopyTruncateString(newTeammateCode, ARRAY_SIZE(newTeammateCode), CommonInterface::GetComputerSettings().team_code.team_code.GetCode()); if (!TextEntryDialog(newTeammateCode, 7)) return; StripRight(newTeammateCode); TeamCodeSettings &settings = CommonInterface::SetComputerSettings().team_code; settings.team_code.Update(newTeammateCode); if (settings.team_code.IsDefined()) settings.team_flarm_id.Clear(); }
void LoadFlarmNameFile(TLineReader &reader, FlarmNameDatabase &db) { TCHAR *line; while ((line = reader.ReadLine()) != NULL) { TCHAR *endptr; FlarmId id = FlarmId::Parse(line, &endptr); if (!id.IsDefined()) /* ignore malformed records */ continue; if (endptr > line && endptr[0] == _T('=') && endptr[1] != _T('\0')) { TCHAR *Name = endptr + 1; StripRight(Name); if (!db.Set(id, Name)) break; // cant add anymore items ! } } }
void LogLastError(const TCHAR *fmt, ...) { const DWORD error = GetLastError(); TCHAR buffer[1024]; va_list ap; va_start(ap, fmt); _vsntprintf(buffer, ARRAY_SIZE(buffer), fmt, ap); va_end(ap); TCHAR msg[256]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error, 0, msg, ARRAY_SIZE(msg), nullptr); StripRight(msg); LogFormat(_T("%s: %s"), buffer, msg); }
void KnobTextEntry(TCHAR *text, size_t width, const TCHAR *caption) { if (width == 0) width = MAX_TEXTENTRY; KnobTextEntryWidget widget(text, width); WidgetDialog dialog(UIGlobals::GetDialogLook()); dialog.CreateFull(UIGlobals::GetMainWindow(), caption, &widget); dialog.AddButton(_("Close"), mrOK); widget.CreateButtons(dialog); if (dialog.ShowModal() == mrOK) { StripRight(widget.GetValue()); CopyTruncateString(text, width, widget.GetValue()); } dialog.StealWidget(); }
static void ChangeBaudRate(FlarmDevice &flarm, OperationEnvironment &env) { while (true) { unsigned baud_id; if (flarm.GetBaudRate(baud_id, env)) printf("Old baud rate setting: \"%d\"\n", baud_id); fprintf(stdout, "Please enter the baud rate setting (2000-25500):\n"); fprintf(stdout, "> "); char buffer[64]; if (fgets(buffer, 64, stdin) == NULL || strlen(buffer) == 0) { fprintf(stdout, "Invalid input\n"); continue; } StripRight(buffer); char *end_ptr; baud_id = strtoul(buffer, &end_ptr, 10); if (end_ptr == buffer) { fprintf(stdout, "Invalid input\n"); continue; } fprintf(stdout, "Setting baud rate to \"%d\" ...\n", baud_id); if (flarm.SetBaudRate(baud_id, env)) fprintf(stdout, "BaudRate set to \"%d\"\n", baud_id); else fprintf(stdout, "Operation failed!\n"); return; } }
static void ChangeRange(FlarmDevice &flarm, OperationEnvironment &env) { while (true) { unsigned num_range; if (flarm.GetRange(num_range, env)) printf("Old range setting: \"%d\"\n", num_range); fprintf(stdout, "Please enter the range setting (2000-25500):\n"); fprintf(stdout, "> "); char range[64]; if (fgets(range, 64, stdin) == NULL || strlen(range) == 0) { fprintf(stdout, "Invalid input\n"); continue; } StripRight(range); char *end_ptr; num_range = strtoul(range, &end_ptr, 10); if (range == end_ptr) { fprintf(stdout, "Invalid input\n"); continue; } fprintf(stdout, "Setting range to \"%d\" ...\n", num_range); if (flarm.SetRange(num_range, env)) fprintf(stdout, "Range set to \"%d\"\n", num_range); else fprintf(stdout, "Operation failed!\n"); return; } }
void ParseInputFile(InputConfig &config, TLineReader &reader) { // TODO code - Safer sizes, strings etc - use C++ (can scanf restrict length?) // Multiple modes (so large string) EventBuilder current; current.clear(); int line = 0; // Read from the file TCHAR *buffer; while ((buffer = reader.ReadLine()) != NULL) { StripRight(buffer); line++; const TCHAR *key, *value; // experimental: if the first line is "#CLEAR" then the whole default config is cleared // and can be overwritten by file if (line == 1 && StringIsEqual(buffer, _T("#CLEAR"))) { config.SetDefaults(); } else if (buffer[0] == _T('\0')) { // Check valid line? If not valid, assume next record (primative, but works ok!) // General checks before continue... current.commit(config, line); // Clear all data. current.clear(); } else if (StringIsEmpty(buffer) || buffer[0] == _T('#')) { // Do nothing - we probably just have a comment line // NOTE: Do NOT display buffer to user as it may contain an invalid stirng ! } else if (parse_assignment(buffer, key, value)) { if (StringIsEqual(key, _T("mode"))) { current.mode = value; } else if (StringIsEqual(key, _T("type"))) { current.type = value; } else if (StringIsEqual(key, _T("data"))) { current.data = value; } else if (StringIsEqual(key, _T("event"))) { if (_tcslen(value) < 256) { TCHAR d_event[256] = _T(""); TCHAR d_misc[256] = _T(""); int ef; #if defined(__BORLANDC__) memset(d_event, 0, sizeof(d_event)); memset(d_misc, 0, sizeof(d_event)); if (StringFind(value, ' ') == nullptr) { _tcscpy(d_event, value); } else { #endif ef = _stscanf(value, _T("%[^ ] %[A-Za-z0-9_ \\/().,]"), d_event, d_misc); #if defined(__BORLANDC__) } #endif if ((ef == 1) || (ef == 2)) { // TODO code: Consider reusing existing identical events pt2Event event = InputEvents::findEvent(d_event); if (event) { TCHAR *allocated = UnescapeBackslash(d_misc); current.event_id = config.AppendEvent(event, allocated, current.event_id); /* not freeing the string, because InputConfig::AppendEvent() stores the string point without duplicating it; strictly speaking, this is a memory leak, but the input file is only loaded once at startup, so this is acceptable; in return, we don't have to duplicate the hard-coded defaults, which saves some memory */ //free(allocated); } else { LogFormat(_T("Invalid event type: %s at %i"), d_event, line); } } else { LogFormat("Invalid event type at %i", line); } } } else if (StringIsEqual(key, _T("label"))) { current.label = value; } else if (StringIsEqual(key, _T("location"))) { current.location = ParseUnsigned(value); } else { LogFormat(_T("Invalid key/value pair %s=%s at %i"), key, value, line); } } else { LogFormat("Invalid line at %i", line); } } current.commit(config, line); }
ButtonLabel::Expanded ButtonLabel::Expand(const TCHAR *text, TCHAR *buffer, size_t size) { Expanded expanded; const TCHAR *dollar; if ((text == nullptr) || (*text == _T('\0')) || (*text == _T(' '))) { expanded.visible = false; return expanded; } else if ((dollar = StringFind(text, '$')) == nullptr) { /* no macro, we can just translate the text */ expanded.visible = true; expanded.enabled = true; const TCHAR *nl; if (((nl = StringFind(text, '\n')) != nullptr) && LacksAlphaASCII(nl + 1)) { /* Quick hack for skipping the translation for second line of a two line label with only digits and punctuation in the second line, e.g. for menu labels like "Config\n2/3" */ /* copy the text up to the '\n' to a new buffer and translate it */ TCHAR translatable[256]; std::copy(text, nl, translatable); translatable[nl - text] = _T('\0'); const TCHAR *translated = StringIsEmpty(translatable) ? _T("") : gettext(translatable); /* concatenate the translated text and the part starting with '\n' */ _tcscpy(buffer, translated); _tcscat(buffer, nl); expanded.text = buffer; } else expanded.text = gettext(text); return expanded; } else { const TCHAR *macros = dollar; /* backtrack until the first non-whitespace character, because we don't want to translate whitespace between the text and the macro */ macros = StripRight(text, macros); TCHAR s[100]; expanded.enabled = !ExpandMacros(text, s, ARRAY_SIZE(s)); if (s[0] == _T('\0') || s[0] == _T(' ')) { expanded.visible = false; return expanded; } /* copy the text (without trailing whitespace) to a new buffer and translate it */ TCHAR translatable[256]; std::copy(text, macros, translatable); translatable[macros - text] = _T('\0'); const TCHAR *translated = StringIsEmpty(translatable) ? _T("") : gettext(translatable); /* concatenate the translated text and the macro output */ _tcscpy(buffer, translated); _tcscat(buffer, s + (macros - text)); expanded.visible = true; expanded.text = buffer; return expanded; } }
void FString::StripRight (const FString &charset) { return StripRight (charset.Chars); }
ButtonLabel::Expanded ButtonLabel::Expand(const TCHAR *text, TCHAR *buffer, size_t size) { Expanded expanded; const TCHAR *dollar; if (text == nullptr || *text == _T('\0') || *text == _T(' ')) { expanded.visible = false; return expanded; } else if ((dollar = StringFind(text, '$')) == nullptr) { /* no macro, we can just translate the text */ expanded.visible = true; expanded.enabled = true; const TCHAR *nl = StringFind(text, '\n'); if (nl != nullptr && LacksAlphaASCII(nl + 1)) { /* Quick hack for skipping the translation for second line of a two line label with only digits and punctuation in the second line, e.g. for menu labels like "Config\n2/3" */ /* copy the text up to the '\n' to a new buffer and translate it */ TCHAR translatable[256]; const TCHAR *translated = GetTextN(text, nl, translatable, ARRAY_SIZE(translatable)); if (translated == nullptr) { /* buffer too small: keep it untranslated */ expanded.text = text; return expanded; } /* concatenate the translated text and the part starting with '\n' */ expanded.text = BuildString(buffer, size, translated, nl); } else expanded.text = gettext(text); return expanded; } else { const TCHAR *macros = dollar; /* backtrack until the first non-whitespace character, because we don't want to translate whitespace between the text and the macro */ macros = StripRight(text, macros); TCHAR s[100]; expanded.enabled = !ExpandMacros(text, s, ARRAY_SIZE(s)); if (s[0] == _T('\0') || s[0] == _T(' ')) { expanded.visible = false; return expanded; } /* copy the text (without trailing whitespace) to a new buffer and translate it */ TCHAR translatable[256]; const TCHAR *translated = GetTextN(text, macros, translatable, ARRAY_SIZE(translatable)); if (translated == nullptr) { /* buffer too small: fail */ // TODO: find a more clever fallback expanded.visible = false; return expanded; } /* concatenate the translated text and the macro output */ expanded.visible = true; expanded.text = BuildString(buffer, size, translated, s + (macros - text)); return expanded; } }
/** * Recursively parse an XML element. */ static bool XML::ParseXMLElement(XMLNode &node, Parser *pXML) { bool is_declaration; const TCHAR *text = nullptr; XMLNode *pNew; enum Status status; // inside or outside a tag enum Attrib attrib = eAttribName; /* the name of the attribute that is currently being */ tstring attribute_name; assert(pXML); // If this is the first call to the function if (pXML->nFirst) { // Assume we are outside of a tag definition pXML->nFirst = false; status = eOutsideTag; } else { // If this is not the first call then we should only be called when inside a tag. status = eInsideTag; } // Iterate through the tokens in the document while (true) { // Obtain the next token NextToken token = GetNextToken(pXML); if (gcc_unlikely(token.type == eTokenError)) return false; // Check the current status switch (status) { // If we are outside of a tag definition case eOutsideTag: // Check what type of token we obtained switch (token.type) { // If we have found text or quoted text case eTokenText: case eTokenQuotedText: case eTokenEquals: if (text == nullptr) text = token.pStr; break; // If we found a start tag '<' and declarations '<?' case eTokenTagStart: case eTokenDeclaration: // Cache whether this new element is a declaration or not is_declaration = token.type == eTokenDeclaration; // If we have node text then add this to the element if (text != nullptr) { size_t length = StripRight(text, token.pStr - text); node.AddText(text, length); text = nullptr; } // Find the name of the tag token = GetNextToken(pXML); // Return an error if we couldn't obtain the next token or // it wasnt text if (token.type != eTokenText) { pXML->error = eXMLErrorMissingTagName; return false; } // If the name of the new element differs from the name of // the current element we need to add the new element to // the current one and recurse pNew = &node.AddChild(token.pStr, token.length, is_declaration); while (true) { // Callself to process the new node. If we return // FALSE this means we dont have any more // processing to do... if (!ParseXMLElement(*pNew, pXML)) { return false; } else { // If the call to recurse this function // evented in a end tag specified in XML then // we need to unwind the calls to this // function until we find the appropriate node // (the element name and end tag name must // match) if (pXML->cbEndTag) { // If we are back at the root node then we // have an unmatched end tag if (node.GetName() == nullptr) { pXML->error = eXMLErrorUnmatchedEndTag; return false; } // If the end tag matches the name of this // element then we only need to unwind // once more... if (CompareTagName(node.GetName(), pXML->lpEndTag)) { pXML->cbEndTag = 0; } return true; } else { // If we didn't have a new element to create break; } } } break; // If we found an end tag case eTokenTagEnd: // If we have node text then add this to the element if (text != nullptr) { size_t length = StripRight(text, token.pStr - text); TCHAR *text2 = FromXMLString(text, length); if (text2 == nullptr) { pXML->error = eXMLErrorUnexpectedToken; return false; } node.AddText(text2); free(text2); text = nullptr; } // Find the name of the end tag token = GetNextToken(pXML); // The end tag should be text if (token.type != eTokenText) { pXML->error = eXMLErrorMissingEndTagName; return false; } // After the end tag we should find a closing tag if (GetNextToken(pXML).type != eTokenCloseTag) { pXML->error = eXMLErrorMissingEndTagName; return false; } // We need to return to the previous caller. If the name // of the tag cannot be found we need to keep returning to // caller until we find a match if (!CompareTagName(node.GetName(), token.pStr)) { pXML->lpEndTag = token.pStr; pXML->cbEndTag = token.length; } // Return to the caller return true; // Errors... case eTokenCloseTag: /* '>' */ case eTokenShortHandClose: /* '/>' */ pXML->error = eXMLErrorUnexpectedToken; return false; default: break; } break; // If we are inside a tag definition we need to search for attributes case eInsideTag: // Check what part of the attribute (name, equals, value) we // are looking for. switch (attrib) { // If we are looking for a new attribute case eAttribName: // Check what the current token type is switch (token.type) { // If the current type is text... // Eg. 'attribute' case eTokenText: // Cache the token then indicate that we are next to // look for the equals attribute_name.assign(token.pStr, token.length); attrib = eAttribEquals; break; // If we found a closing tag... // Eg. '>' case eTokenCloseTag: // We are now outside the tag status = eOutsideTag; break; // If we found a short hand '/>' closing tag then we can // return to the caller case eTokenShortHandClose: return true; // Errors... case eTokenQuotedText: /* '"SomeText"' */ case eTokenTagStart: /* '<' */ case eTokenTagEnd: /* '</' */ case eTokenEquals: /* '=' */ case eTokenDeclaration: /* '<?' */ pXML->error = eXMLErrorUnexpectedToken; return false; default: break; } break; // If we are looking for an equals case eAttribEquals: // Check what the current token type is switch (token.type) { // If the current type is text... // Eg. 'Attribute AnotherAttribute' case eTokenText: // Add the unvalued attribute to the list node.AddAttribute(std::move(attribute_name), _T(""), 0); // Cache the token then indicate. We are next to // look for the equals attribute attribute_name.assign(token.pStr, token.length); break; // If we found a closing tag 'Attribute >' or a short hand // closing tag 'Attribute />' case eTokenShortHandClose: case eTokenCloseTag: assert(!attribute_name.empty()); // If we are a declaration element '<?' then we need // to remove extra closing '?' if it exists if (node.IsDeclaration() && attribute_name.back() == _T('?')) { attribute_name.pop_back(); } if (!attribute_name.empty()) // Add the unvalued attribute to the list node.AddAttribute(std::move(attribute_name), _T(""), 0); // If this is the end of the tag then return to the caller if (token.type == eTokenShortHandClose) return true; // We are now outside the tag status = eOutsideTag; break; // If we found the equals token... // Eg. 'Attribute =' case eTokenEquals: // Indicate that we next need to search for the value // for the attribute attrib = eAttribValue; break; // Errors... case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/ case eTokenTagStart: /* 'Attribute <' */ case eTokenTagEnd: /* 'Attribute </' */ case eTokenDeclaration: /* 'Attribute <?' */ pXML->error = eXMLErrorUnexpectedToken; return false; default: break; } break; // If we are looking for an attribute value case eAttribValue: // Check what the current token type is switch (token.type) { // If the current type is text or quoted text... // Eg. 'Attribute = "Value"' or 'Attribute = Value' or // 'Attribute = 'Value''. case eTokenText: case eTokenQuotedText: // If we are a declaration element '<?' then we need // to remove extra closing '?' if it exists if (node.IsDeclaration() && (token.pStr[token.length - 1]) == _T('?')) { token.length--; } // Add the valued attribute to the list if (token.type == eTokenQuotedText) { token.pStr++; token.length -= 2; } assert(!attribute_name.empty()); { TCHAR *value = FromXMLString(token.pStr, token.length); if (value == nullptr) { pXML->error = eXMLErrorUnexpectedToken; return false; } node.AddAttribute(std::move(attribute_name), value, _tcslen(value)); free(value); } // Indicate we are searching for a new attribute attrib = eAttribName; break; // Errors... case eTokenTagStart: /* 'Attr = <' */ case eTokenTagEnd: /* 'Attr = </' */ case eTokenCloseTag: /* 'Attr = >' */ case eTokenShortHandClose: /* "Attr = />" */ case eTokenEquals: /* 'Attr = =' */ case eTokenDeclaration: /* 'Attr = <?' */ pXML->error = eXMLErrorUnexpectedToken; return false; default: break; } } } } }