void SFZReader::read(const char* text, unsigned int length) { const char* p = text; const char* end = text + length; char c; SFZRegion curGroup; SFZRegion curRegion; SFZRegion* buildingRegion = NULL; bool inControl = false; std::string defaultPath; while (p < end) { // We're at the start of a line; skip any whitespace. while (p < end) { c = *p; if (c != ' ' && c != '\t') break; p += 1; } if (p >= end) break; // Check if it's a comment line. if (c == '/') { // Skip to end of line. while (p < end) { c = *++p; if (c == '\n' || c == '\r') break; } p = handleLineEnd(p); continue; } // Check if it's a blank line. if (c == '\r' || c == '\n') { p = handleLineEnd(p); continue; } // Handle elements on the line. while (p < end) { c = *p; // Tag. if (c == '<') { p += 1; const char* tagStart = p; while (p < end) { c = *p++; if (c == '\n' || c == '\r') { error("Unterminated tag"); goto fatalError; } else if (c == '>') break; } if (p >= end) { error("Unterminated tag"); goto fatalError; } StringSlice tag(tagStart, p - 1); if (tag == "region") { if (buildingRegion && buildingRegion == &curRegion) finishRegion(&curRegion); curRegion = curGroup; buildingRegion = &curRegion; inControl = false; } else if (tag == "group") { if (buildingRegion && buildingRegion == &curRegion) finishRegion(&curRegion); curGroup.clear(); buildingRegion = &curGroup; inControl = false; } else if (tag == "control") { if (buildingRegion && buildingRegion == &curRegion) finishRegion(&curRegion); curGroup.clear(); buildingRegion = NULL; inControl = true; } else error("Illegal tag"); } // Comment. else if (c == '/') { // Skip to end of line. while (p < end) { c = *p; if (c == '\r' || c == '\n') break; p += 1; } } // Parameter. else { // Get the parameter name. const char* parameterStart = p; while (p < end) { c = *p++; if (c == '=' || c == ' ' || c == '\t' || c == '\r' || c == '\n') break; } if (p >= end || c != '=') { error("Malformed parameter"); goto nextElement; } StringSlice opcode(parameterStart, p - 1); if (inControl) { if (opcode == "default_path") p = readPathInto(&defaultPath, p, end); else { const char* valueStart = p; while (p < end) { c = *p; if (c == ' ' || c == '\t' || c == '\n' || c == '\r') break; p++; } std::string value(valueStart, p - valueStart); std::string fauxOpcode = std::string(opcode.start, opcode.length()) + std::string(" (in <control>)"); sound->addUnsupportedOpcode(fauxOpcode); } } else if (opcode == "sample") { std::string path; p = readPathInto(&path, p, end); if (path != "") { if (buildingRegion) buildingRegion->sample = sound->addSample(path, defaultPath); else error("Adding sample outside a group or region"); } else error("Empty sample path"); } else { const char* valueStart = p; while (p < end) { c = *p; if (c == ' ' || c == '\t' || c == '\n' || c == '\r') break; p++; } std::string value(valueStart, p - valueStart); std::istringstream ss(value); if (buildingRegion == NULL) error("Setting a parameter outside a region or group"); else if (opcode == "lokey") buildingRegion->lokey = keyValue(value); else if (opcode == "hikey") buildingRegion->hikey = keyValue(value); else if (opcode == "key") { buildingRegion->hikey = buildingRegion->lokey = buildingRegion->pitch_keycenter = keyValue(value); } else if (opcode == "lovel") { int i; ss >> i; buildingRegion->lovel = i; } else if (opcode == "hivel") { int i; ss >> i; buildingRegion->hivel = i; } else if (opcode == "trigger") buildingRegion->trigger = (SFZRegion::Trigger) triggerValue(value); else if (opcode == "group") { unsigned long l; ss >> l; buildingRegion->group = l; }
/************************************************************************* Handler for when non-printable keys are typed. *************************************************************************/ void MultiLineEditbox::onKeyDown(KeyEventArgs& e) { // base class processing Window::onKeyDown(e); if (hasInputFocus() && !isReadOnly()) { WindowEventArgs args(this); switch (e.scancode) { case Key::LeftShift: case Key::RightShift: if (getSelectionLength() == 0) { d_dragAnchorIdx = getCaratIndex(); } break; case Key::Backspace: handleBackspace(); break; case Key::Delete: handleDelete(); break; case Key::Return: case Key::NumpadEnter: handleNewLine(e.sysKeys); break; case Key::ArrowLeft: if (e.sysKeys & Control) { handleWordLeft(e.sysKeys); } else { handleCharLeft(e.sysKeys); } break; case Key::ArrowRight: if (e.sysKeys & Control) { handleWordRight(e.sysKeys); } else { handleCharRight(e.sysKeys); } break; case Key::ArrowUp: handleLineUp(e.sysKeys); break; case Key::ArrowDown: handleLineDown(e.sysKeys); break; case Key::Home: if (e.sysKeys & Control) { handleDocHome(e.sysKeys); } else { handleLineHome(e.sysKeys); } break; case Key::End: if (e.sysKeys & Control) { handleDocEnd(e.sysKeys); } else { handleLineEnd(e.sysKeys); } break; // default case is now to leave event as (possibly) unhandled. default: return; } e.handled = true; } }