From ea827624d203c73af896669e161972fc8be022ed Mon Sep 17 00:00:00 2001 From: BossCode45 Date: Sat, 27 May 2023 16:33:46 +1200 Subject: feat: Made it compile woo Note: doesn't work yet though, as commands haven't all been registered yet --- config.cpp | 15 ++- config.cpp.old | 364 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ config.h | 82 +++++++------ config.h.old | 93 +++++++++++++++ ewmh.cpp | 6 +- ewmh.h | 4 +- main.cpp | 38 +++--- old.config.cpp | 364 --------------------------------------------------------- old.config.h | 93 --------------- 9 files changed, 531 insertions(+), 528 deletions(-) create mode 100644 config.cpp.old create mode 100644 config.h.old delete mode 100644 old.config.cpp delete mode 100644 old.config.h diff --git a/config.cpp b/config.cpp index 6d8215c..422ec19 100644 --- a/config.cpp +++ b/config.cpp @@ -92,6 +92,7 @@ const void Config::addWorkspaceCmd(const CommandArg* argv) int* prefs = new int[argv[1].numArr.size]; memcpy(prefs, argv[1].numArr.arr, argv[1].numArr.size * sizeof(int)); workspaces.push_back({argv[0].str, prefs, argv[1].numArr.size}); + numWS++; } Config::Config(CommandsModule& commandsModule) @@ -118,20 +119,23 @@ Config::Config(CommandsModule& commandsModule) commandsModule.addCommand("addworkspace", &Config::addWorkspaceCmd, 2, addWorkspaceArgs, this); } -Err Config::reloadFile() +std::vector Config::reloadFile() { if(!loaded) - return {CFG_ERR_NON_FATAL, "Not loaded config yet"}; + return {{CFG_ERR_NON_FATAL, "Not loaded config yet"}}; return loadFromFile(file); } -Err Config::loadFromFile(string path) +std::vector Config::loadFromFile(std::string path) { + std::vector ers; + file = path; //Set defaults gaps = 3; outerGaps = 3; logFile = "/tmp/yatlog.txt"; + numWS = 0; //Probably need something for workspaces and binds too... @@ -148,13 +152,12 @@ Err Config::loadFromFile(string path) } catch (Err e) { - cout << "Error in config (line " << line << "): " << e.code << endl; - cout << "\tMessage: " << e.message << endl; + ers.push_back({e.code, "Error in config (line " + std::to_string(line) + "): " + std::to_string(e.code) + "\n\tMessage: " + e.message}); + } line++; } loaded = true; - return {NOERR, ""}; } Config::~Config() diff --git a/config.cpp.old b/config.cpp.old new file mode 100644 index 0000000..74ba0b0 --- /dev/null +++ b/config.cpp.old @@ -0,0 +1,364 @@ +#include "config.h" + +#include "error.h" +#include "toml++/toml.hpp" +#include "util.h" + +#include +#include + +#include +#include + +//Just for testing +#include +#include + +using std::map, std::string, std::to_string; + +// For testing +using std::cout, std::endl, std::cerr; + +map funcNameMap = { + {"exit", exit}, + {"spawn", spawn}, + {"toggle", toggle}, + {"kill", kill}, + {"changeWS", changeWS}, + {"wToWS", wToWS}, + {"focChange", focChange}, + {"wMove", wMove}, + {"bashSpawn", bashSpawn}, + {"reload", reload}, + {"wsDump", wsDump}, + {"nextMonitor", nextMonitor}, +}; + + +Config::Config() +{ +} + +string to_string(string s) +{ + return s; +} +string to_string(bool b) +{ + if(b) + return "true"; + else + return "false"; +} + +template +T Config::getValue(string path, Err* err) +{ + std::optional tblVal = tbl.at_path(path).value(); + if(tblVal) + return *tblVal; + else + { + err->code = ERR_CFG_NON_FATAL; + T val = *defaults.at_path(path).value(); + err->errorMessage += "\n\tValue for " + path + " is invalid, using default (" + to_string(val) + ")"; + return val; + } +} + +void Config::loadWorkspaceArrays(toml::table tbl, toml::table defaults, Err* err) +{ + if(!tbl["Workspaces"]["workspaceNames"].as_array()) + { + err->code = ERR_CFG_NON_FATAL; + err->errorMessage += "\n\tworkspaceNames invalid array, using defaults"; + return loadWorkspaceArrays(defaults, defaults, err); + } + workspaceNamesc = tbl["Workspaces"]["workspaceNames"].as_array()->size(); + workspaceNames = new string[workspaceNamesc]; + for(int i = 0; i < workspaceNamesc; i++) + { + auto element = tbl["Workspaces"]["workspaceNames"][i].value(); + if(element) + workspaceNames[i] = *element; + else + { + err->code = ERR_CFG_NON_FATAL; + err->errorMessage += "\nelement " + to_string(i) + " in workspaceNames invalid, using defaults"; + delete[] workspaceNames; + return loadWorkspaceArrays(defaults, defaults, err); + } + } + if(!tbl["Workspaces"]["screenPreferences"].as_array()) + { + err->code = ERR_CFG_NON_FATAL; + err->errorMessage += "\nscreenPreferences invalid array, using default"; + delete[] workspaceNames; + return loadWorkspaceArrays(defaults, defaults, err); + } + screenPreferencesc = tbl["Workspaces"]["screenPreferences"].as_array()->size(); + if(screenPreferencesc != workspaceNamesc) + { + err->code = ERR_CFG_NON_FATAL; + err->errorMessage += "\nworkspaceNames and screenPreferences aren't the same length, using defaults"; + delete[] workspaceNames; + return loadWorkspaceArrays(defaults, defaults, err); + } + screenPreferences = new int*[screenPreferencesc]; + for(int i = 0; i < screenPreferencesc; i++) + { + if(!tbl["Workspaces"]["screenPreferences"][i].as_array()) + { + err->code = ERR_CFG_NON_FATAL; + err->errorMessage += "\telement " + to_string(i) + " in screenPreferences in invalid, using defaults"; + delete[] workspaceNames; + for(int k = 0; k < i; k++) + { + delete[] screenPreferences[k]; + } + delete[] screenPreferences; + return loadWorkspaceArrays(defaults, defaults, err); + } + int* wsScreens = new int[maxMonitors]; + for(int j = 0; j < maxMonitors; j++) + { + if(tbl["Workspaces"]["screenPreferences"][i].as_array()->size() <= j) + { + wsScreens[j] = 0; + continue; + } + auto element = tbl["Workspaces"]["screenPreferences"][i][j].value(); + if(element) + wsScreens[j] = *element; + else + { + err->code = ERR_CFG_NON_FATAL; + err->errorMessage += "\telement " + to_string(i) + " " + to_string(j) + " in screenPreferences in invalid, using defaults"; + delete[] workspaceNames; + for(int k = 0; k <= i; k++) + { + delete[] screenPreferences[k]; + } + delete[] screenPreferences; + return loadWorkspaceArrays(defaults, defaults, err); + } + } + screenPreferences[i] = wsScreens; + } +} + +void Config::loadStartupBash(toml::table tbl, toml::table defaults, Err* err) +{ + if(!tbl["Startup"]["startupBash"].as_array()) + { + err->code = ERR_CFG_NON_FATAL; + err->errorMessage += "\n\tstartupBash array invalid, using default"; + return loadStartupBash(defaults, defaults, err); + } + startupBashc = tbl["Startup"]["startupBash"].as_array()->size(); + std::vector startupBash; + for(int i = 0; i < startupBashc; i++) + { + auto element = tbl["Startup"]["startupBash"][i].value(); + if(element) + startupBash.push_back(*element); + else + { + err->code = ERR_CFG_NON_FATAL; + err->errorMessage += "\n\tstartupBash element " + to_string(i) + " invalid, skipping"; + } + } + startupBashc = startupBash.size(); + this->startupBash = new string[startupBashc]; + for(int i = 0; i < startupBash.size(); i++) + { + this->startupBash[i] = startupBash[i]; + } +} + +Err Config::reload() +{ + if(!loaded) + return {ERR_CFG_FATAL, "Path not set yet, call loadFromFile before reload"}; + return loadFromFile(path); +} + +Err Config::loadFromFile(string path) +{ + if(loaded) + { + free(); + } + loaded = true; + this->path = path; + Err err; + err.code = NOERR; + err.errorMessage = ""; + defaults = toml::parse_file("/etc/YATwm/config.toml"); + try + { + tbl = toml::parse_file(path); + } + catch (const toml::parse_error& parseErr) + { + err.code = ERR_CFG_FATAL; + string description = (string) parseErr.description(); + string startCol = std::to_string(parseErr.source().begin.column); + string startLine = std::to_string(parseErr.source().begin.line); + string endCol = std::to_string(parseErr.source().end.column); + string endLine = std::to_string(parseErr.source().end.line); + string pos = "Line " + startLine; + string what = parseErr.what(); + err.errorMessage += "\n\t" + description + "\t(" + pos + ")" + "\n\tUsing /etc/YATwm/config.toml instead"; + tbl = defaults; + } + + //Startup + loadStartupBash(tbl, defaults, &err); + + //Main + gaps = getValue("Main.gaps", &err); + outerGaps = getValue("Main.outerGaps", &err); + logFile = getValue("Main.logFile", &err); + + //Workspaces + numWS = getValue("Workspaces.numWS", &err); + maxMonitors = getValue("Workspaces.maxMonitors", &err); + loadWorkspaceArrays(tbl, defaults, &err); + + //Keybinds + bool swapSuperAlt = getValue("Keybinds.swapSuperAlt", &err); + + toml::node_view bindsArr = tbl["Keybinds"]["key"]; + if(!bindsArr.is_array()) + { + err.code = ERR_CFG_NON_FATAL; + err.errorMessage += "\n\tBinds array not valid, using default"; + bindsArr = defaults["Keybinds"]["key"]; + } + std::vector keyBinds; + bindsc = bindsArr.as_array()->size(); + for(int i = 0; i < bindsc; i++) + { + KeyBind bind; + bind.modifiers = 0; + const std::optional potentialBindString = bindsArr[i]["bind"].value(); + string bindString; + if(potentialBindString) + bindString = *potentialBindString; + else + { + err.code = ERR_CFG_NON_FATAL; + err.errorMessage += "\n\tSkipping element " + to_string(i) + " of binds as the bind string is invalid"; + continue; + } + std::vector keys = split(bindString, '+'); + for(string key : keys) + { + if(key == "mod") + { + if(!swapSuperAlt) + bind.modifiers |= Mod4Mask; + else + bind.modifiers |= Mod1Mask; + } + else if(key == "alt") + { + if(swapSuperAlt) + bind.modifiers |= Mod4Mask; + else + bind.modifiers |= Mod1Mask; + } + else if(key == "shift") + { + bind.modifiers |= ShiftMask; + } + else if(key == "control") + { + bind.modifiers |= ControlMask; + } + else + { + bind.keysym = XStringToKeysym(key.c_str()); + if(bind.keysym == NoSymbol) + { + err.code = ERR_CFG_NON_FATAL; + err.errorMessage += "\n\tSkipping element " + to_string(i) + " of binds as the bind string is invalid"; + continue; + } + } + } + std::optional potentialFuncString = bindsArr[i]["func"].value(); + string funcString; + if(potentialFuncString) + funcString = *potentialFuncString; + else + { + err.code = ERR_CFG_NON_FATAL; + err.errorMessage += "\n\tSkipping element " + to_string(i) + " of binds as the func string is invalid"; + continue; + } + if(funcNameMap.count(funcString) == 0) + { + err.code = ERR_CFG_NON_FATAL; + err.errorMessage += "\n\tSkipping element " + to_string(i) + " of binds as the func string is invalid"; + continue; + } + void(* func) (const KeyArg arg) = funcNameMap.find(funcString)->second; + bind.func = func; + + auto args = bindsArr[i]["args"]; + if(args.is()) + { + int num = *args.value(); + bind.args = {.num = num}; + } + else if(args.is()) + { + string str = (string)*args.value(); + if(str == "Up") + bind.args = {.dir = Up}; + else if (str == "Down") + bind.args = {.dir = Down}; + else if (str == "Left") + bind.args = {.dir = Left}; + else if (str == "Right") + bind.args = {.dir = Right}; + else + { + bind.args = {.str = strdup(str.c_str())}; + } + } + else + { + bind.args = {NULL}; + } + keyBinds.push_back(bind); + } + bindsc = keyBinds.size(); + binds = new KeyBind[bindsc]; + for(int i = 0; i < bindsc; i++) + { + binds[i] = keyBinds[i]; + } + if(err.code != NOERR) + err.errorMessage = err.errorMessage.substr(1); + return err; +} + +Config::~Config() +{ + free(); +} +void Config::free() +{ + delete[] startupBash; + delete[] workspaceNames; + for(int i = 0; i < screenPreferencesc; i++) + { + delete[] screenPreferences[i]; + } + delete[] screenPreferences; + delete[] binds; + loaded = false; +} diff --git a/config.h b/config.h index a31c1df..55e55aa 100644 --- a/config.h +++ b/config.h @@ -5,6 +5,7 @@ #include #include +#include struct Workspace { @@ -13,52 +14,47 @@ struct Workspace int screenPreferencesc; }; -#define COMMAND(X) \ +#define COMMAND(X) \ const void X (const CommandArg* argv) class Config { - public: - Config(CommandsModule& commandsModule); - ~Config(); - void free(); +public: + Config(CommandsModule& commandsModule); + ~Config(); + void free(); - Err loadFromFile(std::string path); - Err reloadFile(); - // Startup - std::string* startupBash; - int startupBashc; - - // Main - int gaps; - int outerGaps; - std::string logFile; - - // Workspaces - std::vector workspaces; - int numWS; - std::string* workspaceNames; - int workspaceNamesc; - int maxMonitors; - int** screenPreferences; - int screenPreferencesc; - - // Config Commands - COMMAND(gapsCmd); - COMMAND(outerGapsCmd); - COMMAND(logFileCmd); - COMMAND(addWorkspaceCmd); - - // Keybind Commands - COMMAND(exit); - COMMAND(spawn); - COMMAND(spawn_once); - COMMAND(changeWS); - COMMAND(wToWS); - COMMAND(focChange); - COMMAND(reload); - private: - CommandsModule& commandsModule; - bool loaded = false; - std::string file; + std::vector loadFromFile(std::string path); + std::vector reloadFile(); + // Startup + std::string* startupBash; + int startupBashc; + + // Main + int gaps; + int outerGaps; + std::string logFile; + + // Workspaces + std::vector workspaces; + int numWS; + + // Config Commands + COMMAND(gapsCmd); + COMMAND(outerGapsCmd); + COMMAND(logFileCmd); + COMMAND(addWorkspaceCmd); + + // Keybind Commands + COMMAND(exit); + COMMAND(spawn); + COMMAND(spawn_once); + COMMAND(changeWS); + COMMAND(wToWS); + COMMAND(focChange); + COMMAND(reload); +private: + CommandsModule& commandsModule; + bool loaded = false; + std::string file; }; diff --git a/config.h.old b/config.h.old new file mode 100644 index 0000000..31005e7 --- /dev/null +++ b/config.h.old @@ -0,0 +1,93 @@ +#pragma once + +#include "error.h" + +#include + +#include +#include + +#include + +enum MoveDir +{ + Up, + Right, + Down, + Left +}; + +typedef union +{ + char* str; + int num; + MoveDir dir; +} KeyArg; + +struct KeyBind +{ + unsigned int modifiers; + KeySym keysym; + void(* func) (const KeyArg arg); + KeyArg args; +}; + +//Keybind commands +#define KEYCOM(X) \ + void X (const KeyArg arg) +KEYCOM(exit); +KEYCOM(spawn); +KEYCOM(toggle); +KEYCOM(kill); +KEYCOM(changeWS); +KEYCOM(wToWS); +KEYCOM(focChange); +KEYCOM(wMove); +KEYCOM(bashSpawn); +KEYCOM(reload); +KEYCOM(wsDump); +KEYCOM(nextMonitor); + +class Config +{ + public: + Config(); + ~Config(); + void free(); + + Err loadFromFile(std::string path); + Err reload(); + + // Startup + std::string* startupBash; + int startupBashc; + + // Main + int gaps; + int outerGaps; + std::string logFile; + + // Workspaces + int numWS; + std::string* workspaceNames; + int workspaceNamesc; + int maxMonitors; + int** screenPreferences; + int screenPreferencesc; + + // Keybinds + KeyBind* binds; + int bindsc; + private: + template + T getValue(std::string path, Err* err); + + void loadWorkspaceArrays(toml::table tbl, toml::table defaults, Err* err); + void loadStartupBash(toml::table tbl, toml::table defaults, Err* err); + + toml::table tbl; + toml::table defaults; + + bool loaded = false; + std::string path; +}; diff --git a/ewmh.cpp b/ewmh.cpp index eec5de9..5a7e76c 100644 --- a/ewmh.cpp +++ b/ewmh.cpp @@ -5,7 +5,7 @@ Display** dpy_; Window* root_; -void initEWMH(Display** dpy, Window* root, int numWS, const std::string workspaceNames[]) +void initEWMH(Display** dpy, Window* root, int numWS, std::vector workspaces) { dpy_ = dpy; root_ = root; @@ -14,13 +14,13 @@ void initEWMH(Display** dpy, Window* root, int numWS, const std::string workspac int wsNamesLen = numWS; //For null bytes for(int i = 0; i < numWS; i++) { - wsNamesLen += workspaceNames[i].length(); + wsNamesLen += workspaces[i].name.length(); } char wsNames[wsNamesLen]; int pos = 0; for(int i = 0; i < numWS; i++) { - for(char toAdd : workspaceNames[i]) + for(char toAdd : workspaces[i].name) { wsNames[pos++] = toAdd; } diff --git a/ewmh.h b/ewmh.h index 7b1b5f4..5fbc9a4 100644 --- a/ewmh.h +++ b/ewmh.h @@ -5,10 +5,12 @@ #include #include +#include #include "structs.h" +#include "config.h" -void initEWMH(Display** dpy, Window* root, int numWS, const std::string workspaceNames[]); +void initEWMH(Display** dpy, Window* root, int numWS, std::vector workspaces); void updateClientList(std::map clients); diff --git a/main.cpp b/main.cpp index e4a4bcc..3f541a1 100644 --- a/main.cpp +++ b/main.cpp @@ -82,7 +82,7 @@ int FFCF(int sID); void detectScreens(); void updateMousePos(); void focusRoot(int root); -void handleConfigErrs(Err cfgErr); +void handleConfigErrs(vector cfgErrs); void configureRequest(XConfigureRequestEvent e); void mapRequest(XMapRequestEvent e); @@ -123,9 +123,9 @@ void detectScreens() log("\t\tw: " << screens[i].w << ", h: " << screens[i].h); XFree(name); } - for(int i = 0; i < cfg.numWS; i++) + for(int i = 0; i < cfg.workspaces.size(); i++) { - if(cfg.screenPreferences[i][0] < nscreens && focusedWorkspaces[cfg.screenPreferences[i][0]] == 0) + if(cfg.workspaces[i].screenPreferences[0] < nscreens && focusedWorkspaces[cfg.workspaces[i].screenPreferences[0]] == 0) { //focusedWorkspaces[screenPreferences[i][0]] = i+1; } @@ -162,9 +162,9 @@ void focusRoot(int root) //log("\tFocusing window: " << w); XSetInputFocus(dpy, w, RevertToPointerRoot, CurrentTime); } -void handleConfigErrs(Err cfgErr) +void handleConfigErrs(vector cfgErrs) { - if(cfgErr.code!=NOERR) + for(Err cfgErr : cfgErrs) { if(cfgErr.code == CFG_ERR_FATAL) { @@ -268,19 +268,19 @@ void cWS(int newWS) //log("Changing WS with keybind"); - for(int i = 0; i < cfg.maxMonitors; i++) + for(int i = 0; i < nscreens; i++) { - if(nscreens > cfg.screenPreferences[newWS - 1][i]) + if(nscreens > cfg.workspaces[newWS - 1].screenPreferences[i]) { - int screen = cfg.screenPreferences[newWS - 1][i]; + int screen = cfg.workspaces[newWS - 1].screenPreferences[i]; //log("Found screen (screen " << screenPreferences[arg.num - 1][i] << ")"); - prevWS = focusedWorkspaces[cfg.screenPreferences[newWS - 1][i]]; + prevWS = focusedWorkspaces[screen]; //log("Changed prevWS"); - focusedWorkspaces[cfg.screenPreferences[newWS - 1][i]] = newWS; + focusedWorkspaces[screen] = newWS; //log("Changed focusedWorkspaces"); - if(focusedScreen != cfg.screenPreferences[newWS - 1][i]) + if(focusedScreen != screen) { - focusedScreen = cfg.screenPreferences[newWS - 1][i]; + focusedScreen = screen; XWarpPointer(dpy, root, root, 0, 0, 0, 0, screens[screen].x + screens[screen].w/2, screens[screen].y + screens[screen].h/2); } //log("Changed focusedScreen"); @@ -291,7 +291,8 @@ void cWS(int newWS) //log("Finished changes"); //log(prevWS); - if(prevWS < 1 || prevWS > cfg.numWS) + // LOOK: what is this for????? + if(prevWS < 1 || prevWS > cfg.workspaces.size()) { //untile(prevWS); } @@ -520,7 +521,7 @@ const void reload(const CommandArg* argv) detectScreens(); //Load config again - Err cfgErr = cfg.reloadFile(); + vector cfgErr = cfg.reloadFile(); //Error check handleConfigErrs(cfgErr); @@ -929,8 +930,9 @@ int main(int argc, char** argv) std::string home = getenv("HOME"); std::string pathAfterHome = "/.config/YATwm/config.toml"; std::string file = home + pathAfterHome; - Err cfgErr = cfg.loadFromFile(file); - + // Err cfgErr = cfg.loadFromFile(file); + std::vector cfgErr = cfg.loadFromFile("config"); + //Log yatlog.open(cfg.logFile, std::ios_base::app); @@ -959,7 +961,7 @@ int main(int argc, char** argv) XDefineCursor(dpy, root, XCreateFontCursor(dpy, XC_top_left_arrow)); //EWMH - initEWMH(&dpy, &root, cfg.numWS,cfg. workspaceNames); + initEWMH(&dpy, &root, cfg.workspaces.size(), cfg.workspaces); setCurrentDesktop(1); for(int i = 1; i < cfg.numWS + 1; i++) @@ -990,7 +992,7 @@ int main(int argc, char** argv) switch(e.type) { case KeyPress: - keybindsModule.keyPress(e.xkey); + keybindsModule.handleKeypress(e.xkey); break; case ConfigureRequest: configureRequest(e.xconfigurerequest); diff --git a/old.config.cpp b/old.config.cpp deleted file mode 100644 index 74ba0b0..0000000 --- a/old.config.cpp +++ /dev/null @@ -1,364 +0,0 @@ -#include "config.h" - -#include "error.h" -#include "toml++/toml.hpp" -#include "util.h" - -#include -#include - -#include -#include - -//Just for testing -#include -#include - -using std::map, std::string, std::to_string; - -// For testing -using std::cout, std::endl, std::cerr; - -map funcNameMap = { - {"exit", exit}, - {"spawn", spawn}, - {"toggle", toggle}, - {"kill", kill}, - {"changeWS", changeWS}, - {"wToWS", wToWS}, - {"focChange", focChange}, - {"wMove", wMove}, - {"bashSpawn", bashSpawn}, - {"reload", reload}, - {"wsDump", wsDump}, - {"nextMonitor", nextMonitor}, -}; - - -Config::Config() -{ -} - -string to_string(string s) -{ - return s; -} -string to_string(bool b) -{ - if(b) - return "true"; - else - return "false"; -} - -template -T Config::getValue(string path, Err* err) -{ - std::optional tblVal = tbl.at_path(path).value(); - if(tblVal) - return *tblVal; - else - { - err->code = ERR_CFG_NON_FATAL; - T val = *defaults.at_path(path).value(); - err->errorMessage += "\n\tValue for " + path + " is invalid, using default (" + to_string(val) + ")"; - return val; - } -} - -void Config::loadWorkspaceArrays(toml::table tbl, toml::table defaults, Err* err) -{ - if(!tbl["Workspaces"]["workspaceNames"].as_array()) - { - err->code = ERR_CFG_NON_FATAL; - err->errorMessage += "\n\tworkspaceNames invalid array, using defaults"; - return loadWorkspaceArrays(defaults, defaults, err); - } - workspaceNamesc = tbl["Workspaces"]["workspaceNames"].as_array()->size(); - workspaceNames = new string[workspaceNamesc]; - for(int i = 0; i < workspaceNamesc; i++) - { - auto element = tbl["Workspaces"]["workspaceNames"][i].value(); - if(element) - workspaceNames[i] = *element; - else - { - err->code = ERR_CFG_NON_FATAL; - err->errorMessage += "\nelement " + to_string(i) + " in workspaceNames invalid, using defaults"; - delete[] workspaceNames; - return loadWorkspaceArrays(defaults, defaults, err); - } - } - if(!tbl["Workspaces"]["screenPreferences"].as_array()) - { - err->code = ERR_CFG_NON_FATAL; - err->errorMessage += "\nscreenPreferences invalid array, using default"; - delete[] workspaceNames; - return loadWorkspaceArrays(defaults, defaults, err); - } - screenPreferencesc = tbl["Workspaces"]["screenPreferences"].as_array()->size(); - if(screenPreferencesc != workspaceNamesc) - { - err->code = ERR_CFG_NON_FATAL; - err->errorMessage += "\nworkspaceNames and screenPreferences aren't the same length, using defaults"; - delete[] workspaceNames; - return loadWorkspaceArrays(defaults, defaults, err); - } - screenPreferences = new int*[screenPreferencesc]; - for(int i = 0; i < screenPreferencesc; i++) - { - if(!tbl["Workspaces"]["screenPreferences"][i].as_array()) - { - err->code = ERR_CFG_NON_FATAL; - err->errorMessage += "\telement " + to_string(i) + " in screenPreferences in invalid, using defaults"; - delete[] workspaceNames; - for(int k = 0; k < i; k++) - { - delete[] screenPreferences[k]; - } - delete[] screenPreferences; - return loadWorkspaceArrays(defaults, defaults, err); - } - int* wsScreens = new int[maxMonitors]; - for(int j = 0; j < maxMonitors; j++) - { - if(tbl["Workspaces"]["screenPreferences"][i].as_array()->size() <= j) - { - wsScreens[j] = 0; - continue; - } - auto element = tbl["Workspaces"]["screenPreferences"][i][j].value(); - if(element) - wsScreens[j] = *element; - else - { - err->code = ERR_CFG_NON_FATAL; - err->errorMessage += "\telement " + to_string(i) + " " + to_string(j) + " in screenPreferences in invalid, using defaults"; - delete[] workspaceNames; - for(int k = 0; k <= i; k++) - { - delete[] screenPreferences[k]; - } - delete[] screenPreferences; - return loadWorkspaceArrays(defaults, defaults, err); - } - } - screenPreferences[i] = wsScreens; - } -} - -void Config::loadStartupBash(toml::table tbl, toml::table defaults, Err* err) -{ - if(!tbl["Startup"]["startupBash"].as_array()) - { - err->code = ERR_CFG_NON_FATAL; - err->errorMessage += "\n\tstartupBash array invalid, using default"; - return loadStartupBash(defaults, defaults, err); - } - startupBashc = tbl["Startup"]["startupBash"].as_array()->size(); - std::vector startupBash; - for(int i = 0; i < startupBashc; i++) - { - auto element = tbl["Startup"]["startupBash"][i].value(); - if(element) - startupBash.push_back(*element); - else - { - err->code = ERR_CFG_NON_FATAL; - err->errorMessage += "\n\tstartupBash element " + to_string(i) + " invalid, skipping"; - } - } - startupBashc = startupBash.size(); - this->startupBash = new string[startupBashc]; - for(int i = 0; i < startupBash.size(); i++) - { - this->startupBash[i] = startupBash[i]; - } -} - -Err Config::reload() -{ - if(!loaded) - return {ERR_CFG_FATAL, "Path not set yet, call loadFromFile before reload"}; - return loadFromFile(path); -} - -Err Config::loadFromFile(string path) -{ - if(loaded) - { - free(); - } - loaded = true; - this->path = path; - Err err; - err.code = NOERR; - err.errorMessage = ""; - defaults = toml::parse_file("/etc/YATwm/config.toml"); - try - { - tbl = toml::parse_file(path); - } - catch (const toml::parse_error& parseErr) - { - err.code = ERR_CFG_FATAL; - string description = (string) parseErr.description(); - string startCol = std::to_string(parseErr.source().begin.column); - string startLine = std::to_string(parseErr.source().begin.line); - string endCol = std::to_string(parseErr.source().end.column); - string endLine = std::to_string(parseErr.source().end.line); - string pos = "Line " + startLine; - string what = parseErr.what(); - err.errorMessage += "\n\t" + description + "\t(" + pos + ")" + "\n\tUsing /etc/YATwm/config.toml instead"; - tbl = defaults; - } - - //Startup - loadStartupBash(tbl, defaults, &err); - - //Main - gaps = getValue("Main.gaps", &err); - outerGaps = getValue("Main.outerGaps", &err); - logFile = getValue("Main.logFile", &err); - - //Workspaces - numWS = getValue("Workspaces.numWS", &err); - maxMonitors = getValue("Workspaces.maxMonitors", &err); - loadWorkspaceArrays(tbl, defaults, &err); - - //Keybinds - bool swapSuperAlt = getValue("Keybinds.swapSuperAlt", &err); - - toml::node_view bindsArr = tbl["Keybinds"]["key"]; - if(!bindsArr.is_array()) - { - err.code = ERR_CFG_NON_FATAL; - err.errorMessage += "\n\tBinds array not valid, using default"; - bindsArr = defaults["Keybinds"]["key"]; - } - std::vector keyBinds; - bindsc = bindsArr.as_array()->size(); - for(int i = 0; i < bindsc; i++) - { - KeyBind bind; - bind.modifiers = 0; - const std::optional potentialBindString = bindsArr[i]["bind"].value(); - string bindString; - if(potentialBindString) - bindString = *potentialBindString; - else - { - err.code = ERR_CFG_NON_FATAL; - err.errorMessage += "\n\tSkipping element " + to_string(i) + " of binds as the bind string is invalid"; - continue; - } - std::vector keys = split(bindString, '+'); - for(string key : keys) - { - if(key == "mod") - { - if(!swapSuperAlt) - bind.modifiers |= Mod4Mask; - else - bind.modifiers |= Mod1Mask; - } - else if(key == "alt") - { - if(swapSuperAlt) - bind.modifiers |= Mod4Mask; - else - bind.modifiers |= Mod1Mask; - } - else if(key == "shift") - { - bind.modifiers |= ShiftMask; - } - else if(key == "control") - { - bind.modifiers |= ControlMask; - } - else - { - bind.keysym = XStringToKeysym(key.c_str()); - if(bind.keysym == NoSymbol) - { - err.code = ERR_CFG_NON_FATAL; - err.errorMessage += "\n\tSkipping element " + to_string(i) + " of binds as the bind string is invalid"; - continue; - } - } - } - std::optional potentialFuncString = bindsArr[i]["func"].value(); - string funcString; - if(potentialFuncString) - funcString = *potentialFuncString; - else - { - err.code = ERR_CFG_NON_FATAL; - err.errorMessage += "\n\tSkipping element " + to_string(i) + " of binds as the func string is invalid"; - continue; - } - if(funcNameMap.count(funcString) == 0) - { - err.code = ERR_CFG_NON_FATAL; - err.errorMessage += "\n\tSkipping element " + to_string(i) + " of binds as the func string is invalid"; - continue; - } - void(* func) (const KeyArg arg) = funcNameMap.find(funcString)->second; - bind.func = func; - - auto args = bindsArr[i]["args"]; - if(args.is()) - { - int num = *args.value(); - bind.args = {.num = num}; - } - else if(args.is()) - { - string str = (string)*args.value(); - if(str == "Up") - bind.args = {.dir = Up}; - else if (str == "Down") - bind.args = {.dir = Down}; - else if (str == "Left") - bind.args = {.dir = Left}; - else if (str == "Right") - bind.args = {.dir = Right}; - else - { - bind.args = {.str = strdup(str.c_str())}; - } - } - else - { - bind.args = {NULL}; - } - keyBinds.push_back(bind); - } - bindsc = keyBinds.size(); - binds = new KeyBind[bindsc]; - for(int i = 0; i < bindsc; i++) - { - binds[i] = keyBinds[i]; - } - if(err.code != NOERR) - err.errorMessage = err.errorMessage.substr(1); - return err; -} - -Config::~Config() -{ - free(); -} -void Config::free() -{ - delete[] startupBash; - delete[] workspaceNames; - for(int i = 0; i < screenPreferencesc; i++) - { - delete[] screenPreferences[i]; - } - delete[] screenPreferences; - delete[] binds; - loaded = false; -} diff --git a/old.config.h b/old.config.h deleted file mode 100644 index 31005e7..0000000 --- a/old.config.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -#include "error.h" - -#include - -#include -#include - -#include - -enum MoveDir -{ - Up, - Right, - Down, - Left -}; - -typedef union -{ - char* str; - int num; - MoveDir dir; -} KeyArg; - -struct KeyBind -{ - unsigned int modifiers; - KeySym keysym; - void(* func) (const KeyArg arg); - KeyArg args; -}; - -//Keybind commands -#define KEYCOM(X) \ - void X (const KeyArg arg) -KEYCOM(exit); -KEYCOM(spawn); -KEYCOM(toggle); -KEYCOM(kill); -KEYCOM(changeWS); -KEYCOM(wToWS); -KEYCOM(focChange); -KEYCOM(wMove); -KEYCOM(bashSpawn); -KEYCOM(reload); -KEYCOM(wsDump); -KEYCOM(nextMonitor); - -class Config -{ - public: - Config(); - ~Config(); - void free(); - - Err loadFromFile(std::string path); - Err reload(); - - // Startup - std::string* startupBash; - int startupBashc; - - // Main - int gaps; - int outerGaps; - std::string logFile; - - // Workspaces - int numWS; - std::string* workspaceNames; - int workspaceNamesc; - int maxMonitors; - int** screenPreferences; - int screenPreferencesc; - - // Keybinds - KeyBind* binds; - int bindsc; - private: - template - T getValue(std::string path, Err* err); - - void loadWorkspaceArrays(toml::table tbl, toml::table defaults, Err* err); - void loadStartupBash(toml::table tbl, toml::table defaults, Err* err); - - toml::table tbl; - toml::table defaults; - - bool loaded = false; - std::string path; -}; -- cgit v1.2.3