void StatusMessageList::LoadFile(TLineReader &reader) { // Init first entry StatusMessage current; current.Clear(); /* Read from the file */ TCHAR *buffer; const TCHAR *key, *value; while ((buffer = reader.ReadLine()) != NULL) { // Check valid line? If not valid, assume next record (primative, but works ok!) if (*buffer == _T('#') || !parse_assignment(buffer, key, value)) { // Global counter (only if the last entry had some data) if (!current.IsEmpty()) { list.append(current); current.Clear(); if (list.full()) break; } } else { if (_tcscmp(key, _T("key")) == 0) { if (current.key == NULL) current.key = UnescapeBackslash(value); } else if (_tcscmp(key, _T("sound")) == 0) { if (current.sound == NULL) current.sound = UnescapeBackslash(value); } else if (_tcscmp(key, _T("delay")) == 0) { TCHAR *endptr; unsigned ms = ParseUnsigned(value, &endptr); if (endptr > value) current.delay_ms = ms; } else if (_tcscmp(key, _T("hide")) == 0) { if (_tcscmp(value, _T("yes")) == 0) current.visible = false; } } } if (!current.IsEmpty()) list.append(current); }
void commit(InputConfig &config, unsigned line) { if (empty()) return; TCHAR *token; // For each mode token = mode.first_token(_T(" ")); // General errors - these should be true assert(location < 1024); const TCHAR *new_label = NULL; while (token != NULL) { // All modes are valid at this point int mode_id = config.MakeMode(token); assert(mode_id >= 0); // Make label event // TODO code: Consider Reuse existing entries... if (location > 0) { // Only copy this once per object - save string space if (!new_label) { new_label = UnescapeBackslash(label); } config.AppendMenu(mode_id, new_label, location, event_id); } // Make key (Keyboard input) // key - Hardware key or keyboard if (type.equals(_T("key"))) { // Get the int key (eg: APP1 vs 'a') unsigned key = ParseKeyCode(data); if (key > 0) config.Key2Event[mode_id][key] = event_id; else LogStartUp(_T("Invalid key data: %s at %u"), data.c_str(), line); // Make gce (Glide Computer Event) // GCE - Glide Computer Event } else if (type.equals(_T("gce"))) { // Get the int key (eg: APP1 vs 'a') int key = InputEvents::findGCE(data); if (key >= 0) config.GC2Event[key] = event_id; else LogStartUp(_T("Invalid GCE data: %s at %u"), data.c_str(), line); // Make gesture (Gesture Event) // Key - Key Event } else if (type.equals(_T("gesture"))) { // Check data for invalid characters: bool valid = true; for (const TCHAR* c = data; *c; c++) if (*c != _T('U') && *c != _T('D') && *c != _T('R') && *c != _T('L')) valid = false; if (valid) { // One entry per key: delete old, create new config.Gesture2Event.Remove(data.c_str()); config.Gesture2Event.Add(data.c_str(), event_id); } else LogStartUp(_T("Invalid gesture data: %s at %u"), data.c_str(), line); // Make ne (NMEA Event) // NE - NMEA Event } else if (type.equals(_T("ne"))) { // Get the int key (eg: APP1 vs 'a') int key = InputEvents::findNE(data); if (key >= 0) config.N2Event[key] = event_id; else LogStartUp(_T("Invalid GCE data: %s at %u"), data.c_str(), line); // label only - no key associated (label can still be touch screen) } else if (type.equals(_T("label"))) { // Nothing to do here... } else { LogStartUp(_T("Invalid type: %s at %u"), type.c_str(), line); } token = mode.next_token(_T(" ")); } }
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) { TrimRight(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 (_tcschr(value, ' ') == NULL) { _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 { LogStartUp(_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 { LogStartUp(_T("Invalid key/value pair %s=%s at %i"), key, value, line); } } else { LogFormat("Invalid line at %i", line); } } current.commit(config, line); }
void StatusMessageList::LoadFile(TLineReader &reader) { int ms; // Found ms for delay const TCHAR **location; // Where to put the data bool some_data; // Did we find some in the last loop... // Init first entry StatusMessageSTRUCT current; _init_Status(current); some_data = false; /* Read from the file */ TCHAR *buffer; const TCHAR *key, *value; while ((buffer = reader.read()) != NULL) { // Check valid line? If not valid, assume next record (primative, but works ok!) if (*buffer == _T('#') || !parse_assignment(buffer, key, value)) { // Global counter (only if the last entry had some data) if (some_data) { StatusMessageData.append(current); some_data = false; _init_Status(current); if (StatusMessageData.full()) break; } } else { location = NULL; if (_tcscmp(key, _T("key")) == 0) { some_data = true; // Success, we have a real entry location = ¤t.key; } else if (_tcscmp(key, _T("sound")) == 0) { current.doSound = true; location = ¤t.sound; } else if (_tcscmp(key, _T("delay")) == 0) { TCHAR *endptr; ms = _tcstol(value, &endptr, 10); if (endptr > value) current.delay_ms = ms; } else if (_tcscmp(key, _T("hide")) == 0) { if (_tcscmp(value, _T("yes")) == 0) current.doStatus = false; } // Do we have somewhere to put this && // is it currently empty ? (prevent lost at startup) if (location && (_tcscmp(*location, _T("")) == 0)) { // TODO code: this picks up memory lost from no entry, but not duplicates - fix. if (*location) { // JMW fix memory leak free((void*)const_cast<TCHAR *>(*location)); } *location = UnescapeBackslash(value); } } } if (some_data) StatusMessageData.append(current); }