Updated several components. I really gotta remember I split this off into a submodule.
This commit is contained in:
+12
-6
@@ -47,12 +47,18 @@ void log_unhandled_exception_to_file(const string&in logPath = "crash.log", cons
|
||||
string stack = log_flatten_multiline(last_exception_call_stack);
|
||||
|
||||
string message = "Unhandled exception";
|
||||
if (context != "") message += " (" + context + ")";
|
||||
if (info != "") message += ": " + info;
|
||||
if (filePath != "") message += " at " + filePath;
|
||||
if (line > 0) message += ":" + line;
|
||||
if (func != "") message += " in " + func;
|
||||
if (stack != "") message += " | stack: " + stack;
|
||||
if (context != "")
|
||||
message += " (" + context + ")";
|
||||
if (info != "")
|
||||
message += ": " + info;
|
||||
if (filePath != "")
|
||||
message += " at " + filePath;
|
||||
if (line > 0)
|
||||
message += ":" + line;
|
||||
if (func != "")
|
||||
message += " in " + func;
|
||||
if (stack != "")
|
||||
message += " | stack: " + stack;
|
||||
|
||||
log_append_line(logPath, message);
|
||||
}
|
||||
|
||||
+28
-14
@@ -2,11 +2,14 @@
|
||||
|
||||
double dict_get_number(dictionary @data, const string& in key, double defaultValue) {
|
||||
double value = 0.0;
|
||||
if (@data is null) return defaultValue;
|
||||
if (data.get(key, value)) return value;
|
||||
if (@data is null)
|
||||
return defaultValue;
|
||||
if (data.get(key, value))
|
||||
return value;
|
||||
|
||||
int valueInt = 0;
|
||||
if (data.get(key, valueInt)) return valueInt;
|
||||
if (data.get(key, valueInt))
|
||||
return valueInt;
|
||||
|
||||
string valueString = "";
|
||||
if (data.get(key, valueString)) {
|
||||
@@ -18,41 +21,52 @@ double dict_get_number(dictionary@ data, const string&in key, double defaultValu
|
||||
|
||||
bool dict_get_bool(dictionary @data, const string& in key, bool defaultValue) {
|
||||
bool value = false;
|
||||
if (@data is null) return defaultValue;
|
||||
if (data.get(key, value)) return value;
|
||||
if (@data is null)
|
||||
return defaultValue;
|
||||
if (data.get(key, value))
|
||||
return value;
|
||||
|
||||
int valueInt = 0;
|
||||
if (data.get(key, valueInt)) return valueInt != 0;
|
||||
if (data.get(key, valueInt))
|
||||
return valueInt != 0;
|
||||
|
||||
string valueString = "";
|
||||
if (data.get(key, valueString)) return valueString == "1" || valueString == "true";
|
||||
if (data.get(key, valueString))
|
||||
return valueString == "1" || valueString == "true";
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
bool dict_has_keys(dictionary @data) {
|
||||
if (@data is null) return false;
|
||||
if (@data is null)
|
||||
return false;
|
||||
string[] @keys = data.get_keys();
|
||||
return @keys !is null && keys.length() > 0;
|
||||
}
|
||||
|
||||
bool dict_has_number_key(dictionary @data, const string& in key) {
|
||||
double value = 0.0;
|
||||
if (@data is null) return false;
|
||||
if (data.get(key, value)) return true;
|
||||
if (@data is null)
|
||||
return false;
|
||||
if (data.get(key, value))
|
||||
return true;
|
||||
|
||||
int valueInt = 0;
|
||||
if (data.get(key, valueInt)) return true;
|
||||
if (data.get(key, valueInt))
|
||||
return true;
|
||||
|
||||
string valueString = "";
|
||||
if (data.get(key, valueString)) return valueString.length() > 0;
|
||||
if (data.get(key, valueString))
|
||||
return valueString.length() > 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string[] dict_get_string_list(dictionary @data, const string& in key) {
|
||||
string[] result;
|
||||
if (@data is null) return result;
|
||||
if (!data.get(key, result)) return result;
|
||||
if (@data is null)
|
||||
return result;
|
||||
if (!data.get(key, result))
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
+18
-9
@@ -38,7 +38,8 @@ void docs_browser_set_wrap(bool wrap) {
|
||||
|
||||
void docs_browser_set_extensions(string[] @extensions) {
|
||||
docsBrowserExtensions.resize(0);
|
||||
if (@extensions is null) return;
|
||||
if (@extensions is null)
|
||||
return;
|
||||
for (uint extIndex = 0; extIndex < extensions.length(); extIndex++) {
|
||||
docsBrowserExtensions.insert_last(extensions[extIndex]);
|
||||
}
|
||||
@@ -70,7 +71,8 @@ bool docs_browser_sort_case_insensitive(const string &in a, const string &in b)
|
||||
void docs_browser_append_unique_case_insensitive(string[] @items, const string& in value) {
|
||||
string lowerValue = value.lower();
|
||||
for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) {
|
||||
if (items[itemIndex].lower() == lowerValue) return;
|
||||
if (items[itemIndex].lower() == lowerValue)
|
||||
return;
|
||||
}
|
||||
items.insert_last(value);
|
||||
}
|
||||
@@ -96,9 +98,11 @@ string docs_browser_format_label(const string&in filename) {
|
||||
name = name.lower();
|
||||
name.trim_whitespace_this();
|
||||
|
||||
if (name.length() == 0) return "Document";
|
||||
if (name.length() == 0)
|
||||
return "Document";
|
||||
string first = name.substr(0, 1).upper();
|
||||
if (name.length() == 1) return first;
|
||||
if (name.length() == 1)
|
||||
return first;
|
||||
return first + name.substr(1);
|
||||
}
|
||||
|
||||
@@ -106,18 +110,21 @@ void docs_browser_collect_entries(string[]@ labels, string[]@ paths) {
|
||||
labels.resize(0);
|
||||
paths.resize(0);
|
||||
|
||||
if (!directory_exists(docsBrowserDirectory)) return;
|
||||
if (!directory_exists(docsBrowserDirectory))
|
||||
return;
|
||||
|
||||
string[] docFiles;
|
||||
for (uint extIndex = 0; extIndex < docsBrowserExtensions.length(); extIndex++) {
|
||||
string ext = docsBrowserExtensions[extIndex];
|
||||
if (ext == "") continue;
|
||||
if (ext == "")
|
||||
continue;
|
||||
if (ext.substr(0, 1) == ".") {
|
||||
ext = ext.substr(1);
|
||||
}
|
||||
|
||||
string[] @found = find_files(docsBrowserDirectory + "/*." + ext);
|
||||
if (@found is null) continue;
|
||||
if (@found is null)
|
||||
continue;
|
||||
for (uint fileIndex = 0; fileIndex < found.length(); fileIndex++) {
|
||||
docs_browser_append_unique_case_insensitive(docFiles, found[fileIndex]);
|
||||
}
|
||||
@@ -147,10 +154,12 @@ void docs_browser_add_entries(string[]@ labels, string[]@ paths, int[]@ types, c
|
||||
|
||||
void docs_browser_play_ui_sound(sound& inout soundObj, const string basePath) {
|
||||
string soundPath = resolve_audio_path(basePath);
|
||||
if (soundPath == "") return;
|
||||
if (soundPath == "")
|
||||
return;
|
||||
|
||||
soundObj.close();
|
||||
if (!soundObj.load(soundPath)) return;
|
||||
if (!soundObj.load(soundPath))
|
||||
return;
|
||||
soundObj.play();
|
||||
}
|
||||
|
||||
|
||||
+2
-9
@@ -6,15 +6,8 @@ string file_viewer(string content, string title = "Text Reader", bool readOnly =
|
||||
audio_form f;
|
||||
f.create_window(title, false, true);
|
||||
|
||||
int textControl = f.create_input_box(
|
||||
(readOnly ? "Document (read only)" : "Document (editable)"),
|
||||
content,
|
||||
"",
|
||||
0,
|
||||
readOnly,
|
||||
true,
|
||||
true
|
||||
);
|
||||
int textControl = f.create_input_box((readOnly ? "Document (read only)" : "Document (editable)"), content, "", 0,
|
||||
readOnly, true, true);
|
||||
|
||||
int okButton = -1;
|
||||
int closeButton = -1;
|
||||
|
||||
+95
-24
@@ -112,8 +112,10 @@ string learn_sounds_normalize_path(const string&in path) {
|
||||
}
|
||||
|
||||
bool learn_sounds_is_directory_skip_entry(const string& in entry) {
|
||||
if (entry.length() == 0) return false;
|
||||
if (entry.substr(entry.length() - 1) == "/") return true;
|
||||
if (entry.length() == 0)
|
||||
return false;
|
||||
if (entry.substr(entry.length() - 1) == "/")
|
||||
return true;
|
||||
return directory_exists(entry);
|
||||
}
|
||||
|
||||
@@ -121,19 +123,21 @@ bool learn_sounds_should_skip_path(const string&in path) {
|
||||
string normalizedPath = learn_sounds_normalize_path(path);
|
||||
for (uint skipIndex = 0; skipIndex < learnSoundsSkipList.length(); skipIndex++) {
|
||||
string entry = learn_sounds_normalize_path(learnSoundsSkipList[skipIndex]);
|
||||
if (entry.length() == 0) continue;
|
||||
if (entry.length() == 0)
|
||||
continue;
|
||||
|
||||
bool isDirectory = learn_sounds_is_directory_skip_entry(entry);
|
||||
if (isDirectory) {
|
||||
if (entry.substr(entry.length() - 1) != "/") entry += "/";
|
||||
if (normalizedPath.length() >= entry.length() &&
|
||||
normalizedPath.substr(0, entry.length()) == entry) {
|
||||
if (entry.substr(entry.length() - 1) != "/")
|
||||
entry += "/";
|
||||
if (normalizedPath.length() >= entry.length() && normalizedPath.substr(0, entry.length()) == entry) {
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (normalizedPath == entry) return true;
|
||||
if (normalizedPath == entry)
|
||||
return true;
|
||||
|
||||
if (entry.find_first("/") < 0 && entry.find_first("\\") < 0) {
|
||||
if (normalizedPath.length() >= entry.length() + 1 &&
|
||||
@@ -161,32 +165,95 @@ string learn_sounds_get_description(const string&in path) {
|
||||
return "";
|
||||
}
|
||||
|
||||
bool learn_sounds_contains_path_ci(string[] @paths, const string& in path) {
|
||||
string normalizedPath = learn_sounds_normalize_path(path).lower();
|
||||
for (uint pathIndex = 0; pathIndex < paths.length(); pathIndex++) {
|
||||
if (learn_sounds_normalize_path(paths[pathIndex]).lower() == normalizedPath) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void learn_sounds_add_path_if_missing(string[] @paths, const string& in path) {
|
||||
if (learn_sounds_contains_path_ci(paths, path)) {
|
||||
return;
|
||||
}
|
||||
paths.insert_last(path);
|
||||
}
|
||||
|
||||
bool learn_sounds_has_audio_extension(const string& in path) {
|
||||
string lowerPath = path.lower();
|
||||
if (lowerPath.length() < 4)
|
||||
return false;
|
||||
string suffix = lowerPath.substr(lowerPath.length() - 4);
|
||||
return suffix == ".ogg" || suffix == ".wav";
|
||||
}
|
||||
|
||||
void learn_sounds_gather_files_from_pack(const string& in basePath, string[] @outFiles) {
|
||||
pack @activePack = cast<pack @>(sound_default_pack);
|
||||
if (@activePack is null)
|
||||
return;
|
||||
|
||||
string[] @packFiles = activePack.list_files();
|
||||
if (@packFiles is null)
|
||||
return;
|
||||
|
||||
string normalizedBasePath = learn_sounds_normalize_path(basePath);
|
||||
if (normalizedBasePath != "" && normalizedBasePath.substr(normalizedBasePath.length() - 1) != "/") {
|
||||
normalizedBasePath += "/";
|
||||
}
|
||||
string normalizedBasePathLower = normalizedBasePath.lower();
|
||||
|
||||
for (uint fileIndex = 0; fileIndex < packFiles.length(); fileIndex++) {
|
||||
string normalizedPath = learn_sounds_normalize_path(packFiles[fileIndex]);
|
||||
if (normalizedPath.find("./") == 0) {
|
||||
normalizedPath = normalizedPath.substr(2);
|
||||
}
|
||||
|
||||
if (!learn_sounds_has_audio_extension(normalizedPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (normalizedBasePathLower != "") {
|
||||
if (normalizedPath.length() < normalizedBasePathLower.length()) {
|
||||
continue;
|
||||
}
|
||||
if (normalizedPath.substr(0, normalizedBasePathLower.length()).lower() != normalizedBasePathLower) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
learn_sounds_add_path_if_missing(outFiles, normalizedPath);
|
||||
}
|
||||
}
|
||||
|
||||
void learn_sounds_gather_files_recursive(const string& in basePath, string[] @outFiles) {
|
||||
string[] @oggFiles = find_files(basePath + "/*.ogg");
|
||||
if (@oggFiles !is null) {
|
||||
for (uint fileIndex = 0; fileIndex < oggFiles.length(); fileIndex++) {
|
||||
outFiles.insert_last(basePath + "/" + oggFiles[fileIndex]);
|
||||
learn_sounds_add_path_if_missing(outFiles, basePath + "/" + oggFiles[fileIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
string[] @oggUpperFiles = find_files(basePath + "/*.OGG");
|
||||
if (@oggUpperFiles !is null) {
|
||||
for (uint fileIndex = 0; fileIndex < oggUpperFiles.length(); fileIndex++) {
|
||||
outFiles.insert_last(basePath + "/" + oggUpperFiles[fileIndex]);
|
||||
learn_sounds_add_path_if_missing(outFiles, basePath + "/" + oggUpperFiles[fileIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
string[] @wavFiles = find_files(basePath + "/*.wav");
|
||||
if (@wavFiles !is null) {
|
||||
for (uint fileIndex = 0; fileIndex < wavFiles.length(); fileIndex++) {
|
||||
outFiles.insert_last(basePath + "/" + wavFiles[fileIndex]);
|
||||
learn_sounds_add_path_if_missing(outFiles, basePath + "/" + wavFiles[fileIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
string[] @wavUpperFiles = find_files(basePath + "/*.WAV");
|
||||
if (@wavUpperFiles !is null) {
|
||||
for (uint fileIndex = 0; fileIndex < wavUpperFiles.length(); fileIndex++) {
|
||||
outFiles.insert_last(basePath + "/" + wavUpperFiles[fileIndex]);
|
||||
learn_sounds_add_path_if_missing(outFiles, basePath + "/" + wavUpperFiles[fileIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +295,8 @@ string learn_sounds_label_from_path(const string&in soundPath) {
|
||||
name = name.lower();
|
||||
name.trim_whitespace_this();
|
||||
|
||||
if (name.length() == 0) return "Sound";
|
||||
if (name.length() == 0)
|
||||
return "Sound";
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -236,12 +304,11 @@ void learn_sounds_collect_entries(string[]@ labels, string[]@ soundPaths) {
|
||||
labels.resize(0);
|
||||
soundPaths.resize(0);
|
||||
|
||||
if (!directory_exists(learnSoundsRootDir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
string[] discoveredFiles;
|
||||
if (directory_exists(learnSoundsRootDir)) {
|
||||
learn_sounds_gather_files_recursive(learnSoundsRootDir, discoveredFiles);
|
||||
}
|
||||
learn_sounds_gather_files_from_pack(learnSoundsRootDir, discoveredFiles);
|
||||
if (discoveredFiles.length() > 1) {
|
||||
discoveredFiles.sort(learn_sounds_sort_case_insensitive);
|
||||
}
|
||||
@@ -264,15 +331,23 @@ void learn_sounds_collect_entries(string[]@ labels, string[]@ soundPaths) {
|
||||
}
|
||||
|
||||
void learn_sounds_play_ui_sound(sound& inout soundObj, const string basePath) {
|
||||
string soundPath = resolve_audio_path(basePath);
|
||||
if (soundPath == "") {
|
||||
soundObj.close();
|
||||
|
||||
// Avoid file_exists()-only path checks so packaged Android assets can still load.
|
||||
if (soundObj.load(basePath)) {
|
||||
soundObj.play();
|
||||
return;
|
||||
}
|
||||
|
||||
soundObj.close();
|
||||
if (!soundObj.load(soundPath)) {
|
||||
if (soundObj.load(basePath + ".ogg")) {
|
||||
soundObj.play();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!soundObj.load(basePath + ".wav")) {
|
||||
return;
|
||||
}
|
||||
|
||||
soundObj.play();
|
||||
}
|
||||
|
||||
@@ -324,10 +399,6 @@ void learn_sounds_run_menu() {
|
||||
learn_sounds_play_ui_sound(learnSoundsSelectSound, learnSoundsMenuSoundDir + "/menu_select");
|
||||
}
|
||||
string selectedPath = soundPaths[selection];
|
||||
if (!file_exists(selectedPath)) {
|
||||
learn_sounds_speak("Sound not found.", true);
|
||||
continue;
|
||||
}
|
||||
|
||||
learnSoundsPreviewSound.close();
|
||||
if (!learnSoundsPreviewSound.load(selectedPath)) {
|
||||
|
||||
+60
-30
@@ -18,7 +18,8 @@ void menu_apply_default_sounds(menu@ menuRef, const string soundDir = "sounds/me
|
||||
|
||||
// Minimal blocking list menu.
|
||||
// Returns selected index or -1 on empty input/escape.
|
||||
int menu_run_simple(const string introText, string[]@ options, bool wrap = true, int startIndex = 0, const string soundDir = "sounds/menu") {
|
||||
int menu_run_simple(const string introText, string[] @options, bool wrap = true, int startIndex = 0,
|
||||
const string soundDir = "sounds/menu") {
|
||||
if (@options is null || options.length() == 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -39,37 +40,64 @@ int menu_run_simple(const string introText, string[]@ options, bool wrap = true,
|
||||
|
||||
// Returns a-z for menu prefix filtering, or empty string when no letter key was pressed.
|
||||
string menu_get_filter_letter() {
|
||||
if (key_pressed(KEY_A)) return "a";
|
||||
if (key_pressed(KEY_B)) return "b";
|
||||
if (key_pressed(KEY_C)) return "c";
|
||||
if (key_pressed(KEY_D)) return "d";
|
||||
if (key_pressed(KEY_E)) return "e";
|
||||
if (key_pressed(KEY_F)) return "f";
|
||||
if (key_pressed(KEY_G)) return "g";
|
||||
if (key_pressed(KEY_H)) return "h";
|
||||
if (key_pressed(KEY_I)) return "i";
|
||||
if (key_pressed(KEY_J)) return "j";
|
||||
if (key_pressed(KEY_K)) return "k";
|
||||
if (key_pressed(KEY_L)) return "l";
|
||||
if (key_pressed(KEY_M)) return "m";
|
||||
if (key_pressed(KEY_N)) return "n";
|
||||
if (key_pressed(KEY_O)) return "o";
|
||||
if (key_pressed(KEY_P)) return "p";
|
||||
if (key_pressed(KEY_Q)) return "q";
|
||||
if (key_pressed(KEY_R)) return "r";
|
||||
if (key_pressed(KEY_S)) return "s";
|
||||
if (key_pressed(KEY_T)) return "t";
|
||||
if (key_pressed(KEY_U)) return "u";
|
||||
if (key_pressed(KEY_V)) return "v";
|
||||
if (key_pressed(KEY_W)) return "w";
|
||||
if (key_pressed(KEY_X)) return "x";
|
||||
if (key_pressed(KEY_Y)) return "y";
|
||||
if (key_pressed(KEY_Z)) return "z";
|
||||
if (key_pressed(KEY_A))
|
||||
return "a";
|
||||
if (key_pressed(KEY_B))
|
||||
return "b";
|
||||
if (key_pressed(KEY_C))
|
||||
return "c";
|
||||
if (key_pressed(KEY_D))
|
||||
return "d";
|
||||
if (key_pressed(KEY_E))
|
||||
return "e";
|
||||
if (key_pressed(KEY_F))
|
||||
return "f";
|
||||
if (key_pressed(KEY_G))
|
||||
return "g";
|
||||
if (key_pressed(KEY_H))
|
||||
return "h";
|
||||
if (key_pressed(KEY_I))
|
||||
return "i";
|
||||
if (key_pressed(KEY_J))
|
||||
return "j";
|
||||
if (key_pressed(KEY_K))
|
||||
return "k";
|
||||
if (key_pressed(KEY_L))
|
||||
return "l";
|
||||
if (key_pressed(KEY_M))
|
||||
return "m";
|
||||
if (key_pressed(KEY_N))
|
||||
return "n";
|
||||
if (key_pressed(KEY_O))
|
||||
return "o";
|
||||
if (key_pressed(KEY_P))
|
||||
return "p";
|
||||
if (key_pressed(KEY_Q))
|
||||
return "q";
|
||||
if (key_pressed(KEY_R))
|
||||
return "r";
|
||||
if (key_pressed(KEY_S))
|
||||
return "s";
|
||||
if (key_pressed(KEY_T))
|
||||
return "t";
|
||||
if (key_pressed(KEY_U))
|
||||
return "u";
|
||||
if (key_pressed(KEY_V))
|
||||
return "v";
|
||||
if (key_pressed(KEY_W))
|
||||
return "w";
|
||||
if (key_pressed(KEY_X))
|
||||
return "x";
|
||||
if (key_pressed(KEY_Y))
|
||||
return "y";
|
||||
if (key_pressed(KEY_Z))
|
||||
return "z";
|
||||
return "";
|
||||
}
|
||||
|
||||
// Applies a prefix filter to menu options.
|
||||
void menu_apply_prefix_filter(const string &in filterText, const string[]@ options, int[]@ filteredIndices, string[]@ filteredOptions) {
|
||||
void menu_apply_prefix_filter(const string& in filterText, const string[] @options, int[] @filteredIndices,
|
||||
string[] @filteredOptions) {
|
||||
filteredIndices.resize(0);
|
||||
filteredOptions.resize(0);
|
||||
|
||||
@@ -86,7 +114,8 @@ void menu_apply_prefix_filter(const string &in filterText, const string[]@ optio
|
||||
}
|
||||
|
||||
string optionLower = options[optionIndex].lower();
|
||||
if (optionLower.length() >= filterLower.length() && optionLower.substr(0, filterLower.length()) == filterLower) {
|
||||
if (optionLower.length() >= filterLower.length() &&
|
||||
optionLower.substr(0, filterLower.length()) == filterLower) {
|
||||
filteredIndices.insert_last(optionIndex);
|
||||
filteredOptions.insert_last(options[optionIndex]);
|
||||
}
|
||||
@@ -94,7 +123,8 @@ void menu_apply_prefix_filter(const string &in filterText, const string[]@ optio
|
||||
}
|
||||
|
||||
// Updates filter text from keyboard input and reapplies filtering.
|
||||
bool menu_update_prefix_filter(string &inout filterText, const string[]@ options, int[]@ filteredIndices, string[]@ filteredOptions, int &inout selection) {
|
||||
bool menu_update_prefix_filter(string& inout filterText, const string[] @options, int[] @filteredIndices,
|
||||
string[] @filteredOptions, int& inout selection) {
|
||||
bool filterChanged = false;
|
||||
|
||||
if (key_pressed(KEY_BACK) && filterText.length() > 0) {
|
||||
|
||||
+8
-4
@@ -27,16 +27,19 @@ string normalize_name_whitespace(string name) {
|
||||
}
|
||||
|
||||
bool is_windows_reserved_filename(const string& in upperName) {
|
||||
if (upperName == "CON" || upperName == "PRN" || upperName == "AUX" || upperName == "NUL") return true;
|
||||
if (upperName == "CON" || upperName == "PRN" || upperName == "AUX" || upperName == "NUL")
|
||||
return true;
|
||||
|
||||
if (upperName.length() == 4 && upperName.substr(0, 3) == "COM") {
|
||||
int num = parse_int(upperName.substr(3));
|
||||
if (num >= 1 && num <= 9) return true;
|
||||
if (num >= 1 && num <= 9)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (upperName.length() == 4 && upperName.substr(0, 3) == "LPT") {
|
||||
int num = parse_int(upperName.substr(3));
|
||||
if (num >= 1 && num <= 9) return true;
|
||||
if (num >= 1 && num <= 9)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -96,6 +99,7 @@ string sanitize_filename_base(string name, const int maxLength = 40, const strin
|
||||
return result;
|
||||
}
|
||||
|
||||
string build_filename_from_name(const string&in name, const string&in extension = ".dat", const int maxBaseLength = 40, const string fallback = "item") {
|
||||
string build_filename_from_name(const string& in name, const string& in extension = ".dat",
|
||||
const int maxBaseLength = 40, const string fallback = "item") {
|
||||
return sanitize_filename_base(name, maxBaseLength, fallback) + extension;
|
||||
}
|
||||
|
||||
+20
-7
@@ -76,13 +76,22 @@ void notifications_enqueue(const string &in message) {
|
||||
}
|
||||
|
||||
bool notifications_try_play_sound() {
|
||||
string resolvedPath = resolve_audio_path(notificationsSoundPath);
|
||||
if (resolvedPath == "") {
|
||||
return false;
|
||||
notificationsSound.close();
|
||||
|
||||
// Avoid file_exists()-only checks so packaged Android assets can still load.
|
||||
if (notificationsSound.load(notificationsSoundPath)) {
|
||||
notificationsSound.play();
|
||||
return true;
|
||||
}
|
||||
|
||||
notificationsSound.close();
|
||||
if (!notificationsSound.load(resolvedPath)) {
|
||||
string oggPath = notificationsSoundPath + ".ogg";
|
||||
if (notificationsSound.load(oggPath)) {
|
||||
notificationsSound.play();
|
||||
return true;
|
||||
}
|
||||
|
||||
string wavPath = notificationsSoundPath + ".wav";
|
||||
if (!notificationsSound.load(wavPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -141,7 +150,9 @@ void notifications_check_keys() {
|
||||
}
|
||||
|
||||
int position = notificationsCurrentIndex + 1;
|
||||
notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " + notificationsHistory.length(), true);
|
||||
notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " +
|
||||
notificationsHistory.length(),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -159,7 +170,9 @@ void notifications_check_keys() {
|
||||
}
|
||||
|
||||
int position = notificationsCurrentIndex + 1;
|
||||
notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " + notificationsHistory.length(), true);
|
||||
notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " +
|
||||
notificationsHistory.length(),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+8
-7
@@ -6,7 +6,8 @@ bool save_utils_sort_string_case_insensitive(const string &in a, const string &i
|
||||
|
||||
string[] list_files_with_extension(const string& in extension, const string& in directory = "") {
|
||||
string[] result;
|
||||
if (extension == "") return result;
|
||||
if (extension == "")
|
||||
return result;
|
||||
|
||||
string dirPrefix = directory;
|
||||
if (dirPrefix != "" && dirPrefix.substr(dirPrefix.length() - 1) != "/") {
|
||||
@@ -14,12 +15,12 @@ string[] list_files_with_extension(const string&in extension, const string&in di
|
||||
}
|
||||
|
||||
string[] @items = glob(dirPrefix + "*" + extension);
|
||||
if (@items is null) return result;
|
||||
if (@items is null)
|
||||
return result;
|
||||
|
||||
for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) {
|
||||
string item = items[itemIndex];
|
||||
if (item.length() >= extension.length() &&
|
||||
item.substr(item.length() - extension.length()) == extension) {
|
||||
if (item.length() >= extension.length() && item.substr(item.length() - extension.length()) == extension) {
|
||||
result.insert_last(item);
|
||||
}
|
||||
}
|
||||
@@ -35,8 +36,7 @@ bool has_files_with_extension(const string&in extension, const string&in directo
|
||||
}
|
||||
|
||||
string strip_file_extension(const string& in filename, const string& in extension) {
|
||||
if (extension != "" &&
|
||||
filename.length() >= extension.length() &&
|
||||
if (extension != "" && filename.length() >= extension.length() &&
|
||||
filename.substr(filename.length() - extension.length()) == extension) {
|
||||
return filename.substr(0, filename.length() - extension.length());
|
||||
}
|
||||
@@ -86,7 +86,8 @@ bool save_encrypted_file(const string&in filename, const string&in rawData, cons
|
||||
return save_string_file(filename, encryptedData);
|
||||
}
|
||||
|
||||
bool read_encrypted_file(const string&in filename, const string&in key, string&out rawData, const bool allowPlaintextFallback = true) {
|
||||
bool read_encrypted_file(const string& in filename, const string& in key, string& out rawData,
|
||||
const bool allowPlaintextFallback = true) {
|
||||
string encryptedData = "";
|
||||
if (!read_string_file(filename, encryptedData, false)) {
|
||||
return false;
|
||||
|
||||
+4
-2
@@ -75,7 +75,8 @@ void check_speech_history_keys() {
|
||||
}
|
||||
|
||||
int position = speechHistoryCurrentIndex + 1;
|
||||
screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(), true);
|
||||
screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -94,7 +95,8 @@ void check_speech_history_keys() {
|
||||
}
|
||||
|
||||
int position = speechHistoryCurrentIndex + 1;
|
||||
screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(), true);
|
||||
screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ void ui_restore_window(const string windowTitle = "") {
|
||||
}
|
||||
}
|
||||
|
||||
string ui_input_box(const string title, const string prompt, const string defaultValue = "", const string windowTitle = "") {
|
||||
string ui_input_box(const string title, const string prompt, const string defaultValue = "",
|
||||
const string windowTitle = "") {
|
||||
string dialogTitle = ui_resolve_dialog_title(title, prompt);
|
||||
string result = virtual_input_box(dialogTitle, prompt, defaultValue);
|
||||
ui_restore_window(windowTitle);
|
||||
|
||||
+14
-7
@@ -31,12 +31,15 @@ void volume_controls_configure(float minDb = -60.0f, float maxDb = 0.0f, float s
|
||||
|
||||
int volume_controls_percent_from_db(float volumeDb) {
|
||||
float range = volumeControlsMaxDb - volumeControlsMinDb;
|
||||
if (range <= 0.0f) return 100;
|
||||
if (range <= 0.0f)
|
||||
return 100;
|
||||
|
||||
float normalized = (volumeDb - volumeControlsMinDb) / range;
|
||||
int volumePercent = int(normalized * 100.0f + 0.5f);
|
||||
if (volumePercent < 0) volumePercent = 0;
|
||||
if (volumePercent > 100) volumePercent = 100;
|
||||
if (volumePercent < 0)
|
||||
volumePercent = 0;
|
||||
if (volumePercent > 100)
|
||||
volumePercent = 100;
|
||||
return volumePercent;
|
||||
}
|
||||
|
||||
@@ -52,10 +55,13 @@ void volume_controls_apply(float volumeDb) {
|
||||
|
||||
void volume_controls_set_current_db(float volumeDb, bool announce = true) {
|
||||
float clamped = volumeDb;
|
||||
if (clamped > volumeControlsMaxDb) clamped = volumeControlsMaxDb;
|
||||
if (clamped < volumeControlsMinDb) clamped = volumeControlsMinDb;
|
||||
if (clamped > volumeControlsMaxDb)
|
||||
clamped = volumeControlsMaxDb;
|
||||
if (clamped < volumeControlsMinDb)
|
||||
clamped = volumeControlsMinDb;
|
||||
|
||||
if (clamped == volumeControlsCurrentDb) return;
|
||||
if (clamped == volumeControlsCurrentDb)
|
||||
return;
|
||||
|
||||
volumeControlsCurrentDb = clamped;
|
||||
volume_controls_apply(volumeControlsCurrentDb);
|
||||
@@ -84,7 +90,8 @@ void volume_controls_handle_keys(int downKey = KEY_PAGEDOWN, int upKey = KEY_PAG
|
||||
}
|
||||
|
||||
void safe_destroy_sound_in_pool(sound_pool @poolRef, int& inout handle) {
|
||||
if (handle == -1) return;
|
||||
if (handle == -1)
|
||||
return;
|
||||
if (@poolRef is null) {
|
||||
handle = -1;
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user