diff --git a/config.cpp b/config.cpp index 7a27ba1..a23ac44 100644 --- a/config.cpp +++ b/config.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include #include @@ -32,6 +34,42 @@ static bool write(const char* ptr, FILE* file) { return fwrite(ptr, 1, strlen(ptr), file) == strlen(ptr); } +static inline float to_float(const char* str) { + char* endptr; + + while (isspace(str[0])) { + str++; + } + if (str[0] == '\0') { + throw std::invalid_argument("float string is empty"); + } + + errno = 0; + float res = strtof(str, &endptr); + if (res == HUGE_VALF && errno == ERANGE) { + throw std::overflow_error(std::string(str) + " is bigger than HUGE_VALF"); + } else if (res == FLT_MIN && errno == ERANGE) { + throw std::underflow_error(std::string(str) + " is smaller than FLT_MIN"); + } else if (endptr[0] != '\0') { + throw std::invalid_argument(std::string(str) + " has trailing text"); + } + return res; +} + +static bool validate_font_size_or_log(float size) { + if (size <= 0.0f) { + log(std::string("Font size ") + std::to_string(size) + " is lower or equal to 0"); + return false; + } else if (std::isnan(size)) { + log(std::string("Font size ") + std::to_string(size) + " is NaN"); + return false; + } else if (std::isinf(size)) { + log(std::string("Font size ") + std::to_string(size) + " is infinity or negative infinity"); + return false; + } + return true; +} + std::string get_config_folder() { const char* path; @@ -75,6 +113,24 @@ void create_config_folders_if_necessary() { } +static inline void parse_config_line(Config& config, char* line) { + if (strncmp(line, "logcat_command=", 15 * sizeof(char)) == 0) { + config.logcat_command = &line[15]; + } else if (strncmp(line, "normal_font_size=", 17 * sizeof(char)) == 0) { + float size = to_float(&line[17]); + if (validate_font_size_or_log(size)) { + config.normal_font_size = size; + } + } else if (strncmp(line, "monospace_font_size=", 20 * sizeof(char)) == 0) { + float size = to_float(&line[20]); + if (validate_font_size_or_log(size)) { + config.monospace_font_size = size; + } + } else if (line[0] != '\0') { + throw std::invalid_argument(std::string("unknown config line: ") + line); + } +} + static inline Config load_config(FILE* file) { size_t line_capacity_size = 128 * sizeof(char); char* line = static_cast(malloc(line_capacity_size)); @@ -103,12 +159,11 @@ static inline Config load_config(FILE* file) { *newline = '\0'; } - if (strncmp(line, "logcat_command=", 15 * sizeof(char)) == 0) { - config.logcat_command = &line[15]; - } else if (line[0] != '\0') { - std::invalid_argument e = std::invalid_argument(std::string("unknown config line: ") + line); + try { + parse_config_line(config, line); + } catch (const std::exception& e) { free(line); - throw e; + throw; } } @@ -141,6 +196,19 @@ static inline void write_config(FILE* file, const Config& config) { if (!write(config.logcat_command, file)) { throw std::runtime_error("Failed to write logcat command value"); } + + if (!write("\nnormal_font_size=", file)) { + throw std::runtime_error("Failed to write normal font size key"); + } + if (!write(std::to_string(config.normal_font_size), file)) { + throw std::runtime_error("Failed to write normal font size value"); + } + if (!write("\nmonospace_font_size=", file)) { + throw std::runtime_error("Failed to write monospace font size key"); + } + if (!write(std::to_string(config.monospace_font_size), file)) { + throw std::runtime_error("Failed to write monospace font size value"); + } } void write_config(const Config& config) { diff --git a/config.h b/config.h index 60de355..0b8f545 100644 --- a/config.h +++ b/config.h @@ -4,6 +4,8 @@ struct Config { std::string logcat_command; + float normal_font_size = 13.0f; + float monospace_font_size = 13.0f; }; std::string get_config_folder(); diff --git a/event_loop.cpp b/event_loop.cpp index 2c9fb04..45e2627 100644 --- a/event_loop.cpp +++ b/event_loop.cpp @@ -24,6 +24,15 @@ static inline void settings_window(Config& config, float* config_write_timer, bo if (ImGui::InputTextWithHint("Logcat command", "adb logcat -Dv 'threadtime UTC epoch usec'", &config.logcat_command)) { *config_write_timer = *config_write_timer > 0.0f ? *config_write_timer : 5.0f; } + ImGui::Text("Font sizes only take effect when LogMeow is restarted"); +#ifdef USE_FONTCONFIG + if (ImGui::InputFloat("Normal font size", &config.normal_font_size, 0.5f, 1.0f, "%.3f")) { + *config_write_timer = *config_write_timer > 0.0f ? *config_write_timer : 5.0f; + } +#endif + if (ImGui::InputFloat("Monospace font size", &config.monospace_font_size, 0.5f, 1.0f, "%.3f")) { + *config_write_timer = *config_write_timer > 0.0f ? *config_write_timer : 5.0f; + } ImGui::End(); } diff --git a/main.cpp b/main.cpp index 20e409c..35f4a92 100644 --- a/main.cpp +++ b/main.cpp @@ -114,17 +114,17 @@ int main(int, char**) { #ifdef USE_FONTCONFIG try { std::pair fonts = get_fonts(); - io.Fonts->AddFontFromFileTTF(fonts.first.c_str(), 16.0f); - monospace_font = io.Fonts->AddFontFromFileTTF(fonts.second.c_str(), 15.0f); + io.Fonts->AddFontFromFileTTF(fonts.first.c_str(), config.normal_font_size); + monospace_font = io.Fonts->AddFontFromFileTTF(fonts.second.c_str(), config.monospace_font_size); } catch (const std::exception& e) { log("Failed to get fonts", e); } - if (!monospace_font) { - monospace_font = io.Fonts->AddFontDefault(); - } -#else - monospace_font = io.Fonts->AddFontDefault(); #endif + if (!monospace_font) { + ImFontConfig font_config; + font_config.SizePixels = config.monospace_font_size; + monospace_font = io.Fonts->AddFontDefault(&font_config); + } // Main loop bool run_event_loop = true;