mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2025-10-29 05:40:21 -04:00
699 lines
No EOL
25 KiB
C
699 lines
No EOL
25 KiB
C
#include <stdint.h>
|
||
#include <string.h>
|
||
#include <ctype.h>
|
||
#include <stdbool.h>
|
||
|
||
typedef struct {
|
||
const char *id;
|
||
const char *title;
|
||
unsigned int tags;
|
||
int isfloating;
|
||
int isfullscreen;
|
||
float scroller_proportion;
|
||
const char *animation_type;
|
||
int isnoborder;
|
||
int monitor;
|
||
int width;
|
||
int height;
|
||
} ConfigWinRule;
|
||
|
||
typedef struct {
|
||
const char *name; // 显示器名称
|
||
float mfact; // 主区域比例
|
||
int nmaster; // 主区域窗口数量
|
||
const char *layout; // 布局名称(字符串)
|
||
int rr; // 旋转和翻转(假设为整数)
|
||
float scale; // 显示器缩放比例
|
||
int x, y; // 显示器位置
|
||
} ConfigMonitorRule;
|
||
|
||
typedef struct {
|
||
uint32_t mod;
|
||
xkb_keysym_t keysym;
|
||
void (*func)(const Arg *);
|
||
Arg arg;
|
||
} KeyBinding;
|
||
|
||
typedef struct {
|
||
unsigned int mod;
|
||
unsigned int button;
|
||
void (*func)(const Arg *);
|
||
Arg arg;
|
||
} MouseBinding;
|
||
|
||
typedef struct {
|
||
unsigned int mod;
|
||
unsigned int dir;
|
||
void (*func)(const Arg *);
|
||
Arg arg;
|
||
} AxisBinding;
|
||
|
||
|
||
typedef struct {
|
||
int animations;
|
||
char animation_type[10];
|
||
char animation_fade_in;
|
||
float zoom_initial_ratio;
|
||
float fadein_begin_opacity;
|
||
uint32_t animation_duration_move;
|
||
uint32_t animation_duration_open;
|
||
uint32_t animation_duration_tag;
|
||
double animation_curve[4];
|
||
|
||
int scroller_structs;
|
||
float scroller_default_proportion;
|
||
int scoller_focus_center;
|
||
float scroller_proportion_preset[3];
|
||
|
||
unsigned int new_is_master;
|
||
float default_mfact;
|
||
unsigned int default_nmaster;
|
||
|
||
unsigned int hotarea_size;
|
||
unsigned int enable_hotarea;
|
||
unsigned int ov_tab_mode;
|
||
int overviewgappi;
|
||
int overviewgappo;
|
||
|
||
unsigned int axis_bind_apply_timeout;
|
||
unsigned int focus_on_activate;
|
||
unsigned int numlockon;
|
||
int bypass_surface_visibility;
|
||
int sloppyfocus;
|
||
int warpcursor;
|
||
|
||
int smartgaps;
|
||
unsigned int gappih;
|
||
unsigned int gappiv;
|
||
unsigned int gappoh;
|
||
unsigned int gappov;
|
||
unsigned int borderpx;
|
||
float rootcolor[4];
|
||
float bordercolor[4];
|
||
float focuscolor[4];
|
||
float maxmizescreencolor[4];
|
||
float urgentcolor[4];
|
||
float scratchpadcolor[4];
|
||
float globalcolor[4];
|
||
|
||
char autostart[3][256];
|
||
|
||
struct {
|
||
int id;
|
||
char name[256];
|
||
} tags[9];
|
||
|
||
ConfigWinRule *window_rules;
|
||
int window_rules_count;
|
||
|
||
ConfigMonitorRule *monitor_rules; // 动态数组
|
||
int monitor_rules_count; // 条数
|
||
|
||
KeyBinding *key_bindings;
|
||
int key_bindings_count;
|
||
|
||
MouseBinding *mouse_bindings;
|
||
int mouse_bindings_count;
|
||
|
||
AxisBinding *axis_bindings;
|
||
int axis_bindings_count;
|
||
|
||
} Config;
|
||
|
||
int parseDirection(const char* str) {
|
||
// 将输入字符串转换为小写
|
||
char lowerStr[10];
|
||
int i = 0;
|
||
while (str[i] && i < 9) {
|
||
lowerStr[i] = tolower(str[i]);
|
||
i++;
|
||
}
|
||
lowerStr[i] = '\0';
|
||
|
||
// 根据转换后的小写字符串返回对应的枚举值
|
||
if (strcmp(lowerStr, "up") == 0) {
|
||
return UP;
|
||
} else if (strcmp(lowerStr, "down") == 0) {
|
||
return DOWN;
|
||
} else if (strcmp(lowerStr, "left") == 0) {
|
||
return LEFT;
|
||
} else if (strcmp(lowerStr, "right") == 0) {
|
||
return RIGHT;
|
||
} else {
|
||
return UNDIR;
|
||
}
|
||
}
|
||
|
||
long int parse_color(const char *hex_str) {
|
||
char *endptr;
|
||
long int hex_num = strtol(hex_str, &endptr, 16);
|
||
if (*endptr != '\0') {
|
||
return -1;
|
||
}
|
||
return hex_num;
|
||
}
|
||
|
||
// 辅助函数:检查字符串是否以指定的前缀开头(忽略大小写)
|
||
static bool starts_with_ignore_case(const char *str, const char *prefix) {
|
||
while (*prefix) {
|
||
if (tolower(*str) != tolower(*prefix)) {
|
||
return false;
|
||
}
|
||
str++;
|
||
prefix++;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
uint32_t parse_mod(const char *mod_str) {
|
||
uint32_t mod = 0;
|
||
char lower_str[64]; // 假设输入的字符串长度不超过 64
|
||
int i = 0;
|
||
|
||
// 将 mod_str 转换为全小写
|
||
for (i = 0; mod_str[i] && i < sizeof(lower_str) - 1; i++) {
|
||
lower_str[i] = tolower(mod_str[i]);
|
||
}
|
||
lower_str[i] = '\0'; // 确保字符串以 NULL 结尾
|
||
|
||
// 检查修饰键,忽略左右键标识(如 "_l" 和 "_r")
|
||
if (strstr(lower_str, "super") || strstr(lower_str, "super_l") || strstr(lower_str, "super_r")) {
|
||
mod |= WLR_MODIFIER_LOGO;
|
||
}
|
||
if (strstr(lower_str, "ctrl") || strstr(lower_str, "ctrl_l") || strstr(lower_str, "ctrl_r")) {
|
||
mod |= WLR_MODIFIER_CTRL;
|
||
}
|
||
if (strstr(lower_str, "shift") || strstr(lower_str, "shift_l") || strstr(lower_str, "shift_r")) {
|
||
mod |= WLR_MODIFIER_SHIFT;
|
||
}
|
||
if (strstr(lower_str, "alt") || strstr(lower_str, "alt_l") || strstr(lower_str, "alt_r")) {
|
||
mod |= WLR_MODIFIER_ALT;
|
||
}
|
||
|
||
return mod;
|
||
}
|
||
|
||
xkb_keysym_t parse_keysym(const char *keysym_str) {
|
||
return xkb_keysym_from_name(keysym_str, XKB_KEYSYM_NO_FLAGS);
|
||
}
|
||
|
||
typedef void (*FuncType)(const Arg *);
|
||
|
||
|
||
int parseButton(const char *str) {
|
||
// 将输入字符串转换为小写
|
||
char lowerStr[20];
|
||
int i = 0;
|
||
while (str[i] && i < 19) {
|
||
lowerStr[i] = tolower(str[i]);
|
||
i++;
|
||
}
|
||
lowerStr[i] = '\0'; // 确保字符串正确终止
|
||
|
||
// 根据转换后的小写字符串返回对应的按钮编号
|
||
if (strcmp(lowerStr, "btn_left") == 0) {
|
||
return BTN_LEFT;
|
||
} else if (strcmp(lowerStr, "btn_right") == 0) {
|
||
return BTN_RIGHT;
|
||
} else if (strcmp(lowerStr, "btn_middle") == 0) {
|
||
return BTN_MIDDLE;
|
||
} else if (strcmp(lowerStr, "btn_side") == 0) {
|
||
return BTN_SIDE;
|
||
} else if (strcmp(lowerStr, "btn_extra") == 0) {
|
||
return BTN_EXTRA;
|
||
} else if (strcmp(lowerStr, "btn_forward") == 0) {
|
||
return BTN_FORWARD;
|
||
} else if (strcmp(lowerStr, "btn_back") == 0) {
|
||
return BTN_BACK;
|
||
} else if (strcmp(lowerStr, "btn_task") == 0) {
|
||
return BTN_TASK;
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
|
||
int parseMouseAction(const char *str) {
|
||
// 将输入字符串转换为小写
|
||
char lowerStr[20];
|
||
int i = 0;
|
||
while (str[i] && i < 19) {
|
||
lowerStr[i] = tolower(str[i]);
|
||
i++;
|
||
}
|
||
lowerStr[i] = '\0'; // 确保字符串正确终止
|
||
|
||
// 根据转换后的小写字符串返回对应的按钮编号
|
||
if (strcmp(lowerStr, "curmove") == 0) {
|
||
return CurMove;
|
||
} else if (strcmp(lowerStr, "curresize") == 0) {
|
||
return CurResize;
|
||
} else if (strcmp(lowerStr, "curnormal") == 0) {
|
||
return CurNormal;
|
||
} else if (strcmp(lowerStr, "curpressed") == 0) {
|
||
return CurPressed;
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
void parseColoer(float *color,unsigned long int hex) {
|
||
color[0] = ((hex >> 24) & 0xFF) / 255.0f;
|
||
color[1] = ((hex >> 16) & 0xFF) / 255.0f;
|
||
color[2] = ((hex >> 8) & 0xFF) / 255.0f;
|
||
color[3] = (hex & 0xFF) / 255.0f;
|
||
}
|
||
|
||
FuncType parse_func_name(char *func_name,Arg *arg, char *arg_value) {
|
||
|
||
FuncType func = NULL;
|
||
(*arg).v = NULL;
|
||
|
||
if (strcmp(func_name, "focusstack") == 0) {
|
||
func = focusstack;
|
||
(*arg).i = atoi(arg_value);
|
||
} else if (strcmp(func_name, "focusdir") == 0) {
|
||
func = focusdir;
|
||
(*arg).i = parseDirection(arg_value);
|
||
} else if (strcmp(func_name, "incnmaster") == 0) {
|
||
func = incnmaster;
|
||
(*arg).i = atoi(arg_value);
|
||
} else if (strcmp(func_name, "setmfact") == 0) {
|
||
func = setmfact;
|
||
(*arg).f = atof(arg_value);
|
||
} else if (strcmp(func_name, "zoom") == 0) {
|
||
func = zoom;
|
||
} else if (strcmp(func_name, "exchange_client") == 0) {
|
||
func = exchange_client;
|
||
(*arg).i = parseDirection(arg_value);
|
||
} else if (strcmp(func_name, "toggleglobal") == 0) {
|
||
func = toggleglobal;
|
||
} else if (strcmp(func_name, "toggleoverview") == 0) {
|
||
func = toggleoverview;
|
||
} else if (strcmp(func_name, "set_proportion") == 0) {
|
||
func = set_proportion;
|
||
(*arg).f = atof(arg_value);
|
||
} else if (strcmp(func_name, "switch_proportion_preset") == 0) {
|
||
func = switch_proportion_preset;
|
||
} else if (strcmp(func_name, "viewtoleft") == 0) {
|
||
func = viewtoleft;
|
||
} else if (strcmp(func_name, "viewtoright") == 0) {
|
||
func = viewtoright;
|
||
} else if (strcmp(func_name, "tagtoleft") == 0) {
|
||
func = tagtoleft;
|
||
} else if (strcmp(func_name, "tagtoright") == 0) {
|
||
func = tagtoright;
|
||
} else if (strcmp(func_name, "killclient") == 0) {
|
||
func = killclient;
|
||
} else if (strcmp(func_name, "setlayout") == 0) {
|
||
func = setlayout;
|
||
(*arg).v = strdup(arg_value);
|
||
} else if (strcmp(func_name, "switch_layout") == 0) {
|
||
func = switch_layout;
|
||
} else if (strcmp(func_name, "togglefloating") == 0) {
|
||
func = togglefloating;
|
||
} else if (strcmp(func_name, "togglefullscreen") == 0) {
|
||
func = togglefullscreen;
|
||
} else if (strcmp(func_name, "minized") == 0) {
|
||
func = minized;
|
||
} else if (strcmp(func_name, "restore_minized") == 0) {
|
||
func = restore_minized;
|
||
} else if (strcmp(func_name, "toggle_scratchpad") == 0) {
|
||
func = toggle_scratchpad;
|
||
} else if (strcmp(func_name, "focusmon") == 0) {
|
||
func = focusmon;
|
||
(*arg).i = atoi(arg_value);
|
||
} else if (strcmp(func_name, "tagmon") == 0) {
|
||
func = tagmon;
|
||
(*arg).i = atoi(arg_value);
|
||
} else if (strcmp(func_name, "incgaps") == 0) {
|
||
func = incgaps;
|
||
(*arg).i = atoi(arg_value);
|
||
} else if (strcmp(func_name, "togglegaps") == 0) {
|
||
func = togglegaps;
|
||
} else if (strcmp(func_name, "chvt") == 0) {
|
||
func = chvt;
|
||
(*arg).i = atoi(arg_value);
|
||
} else if (strcmp(func_name, "spawn") == 0) {
|
||
func = spawn;
|
||
(*arg).v = strdup(arg_value);
|
||
} else if (strcmp(func_name, "quit") == 0) {
|
||
func = quit;
|
||
} else if (strcmp(func_name, "moveresize") == 0) {
|
||
func = moveresize;
|
||
(*arg).ui = parseMouseAction(arg_value);
|
||
} else if (strcmp(func_name, "togglemaxmizescreen") == 0) {
|
||
func = togglemaxmizescreen;
|
||
} else if (strcmp(func_name, "viewtoleft_have_client") == 0) {
|
||
func = viewtoleft_have_client;
|
||
} else if (strcmp(func_name, "viewtoright_have_client") == 0) {
|
||
func = viewtoright_have_client;
|
||
} else if (strcmp(func_name, "reload_config") == 0) {
|
||
func = reload_config;
|
||
} else if (strcmp(func_name, "tag") == 0) {
|
||
func = tag;
|
||
(*arg).ui = 1 << (atoi(arg_value) -1);
|
||
} else if (strcmp(func_name, "view") == 0) {
|
||
func = bind_to_view;
|
||
(*arg).ui = 1 << (atoi(arg_value) - 1);
|
||
} else {
|
||
return NULL;
|
||
}
|
||
return func;
|
||
}
|
||
|
||
void parse_config_line(Config *config, const char *line) {
|
||
char key[256], value[256];
|
||
if (sscanf(line, "%[^=]=%[^\n]", key, value) != 2) {
|
||
fprintf(stderr, "Error: Invalid line format: %s\n", line);
|
||
return;
|
||
}
|
||
|
||
if (strcmp(key, "animations") == 0) {
|
||
config->animations = atoi(value);
|
||
} else if (strcmp(key, "animation_type") == 0) {
|
||
strncpy(config->animation_type, value, sizeof(config->animation_type));
|
||
} else if (strcmp(key, "animation_fade_in") == 0) {
|
||
config->animation_fade_in = atoi(value);
|
||
} else if (strcmp(key, "zoom_initial_ratio") == 0) {
|
||
config->zoom_initial_ratio = atof(value);
|
||
} else if (strcmp(key, "fadein_begin_opacity") == 0) {
|
||
config->fadein_begin_opacity = atof(value);
|
||
} else if (strcmp(key, "animation_duration_move") == 0) {
|
||
config->animation_duration_move = atoi(value);
|
||
} else if (strcmp(key, "animation_duration_open") == 0) {
|
||
config->animation_duration_open = atoi(value);
|
||
} else if (strcmp(key, "animation_duration_tag") == 0) {
|
||
config->animation_duration_tag = atoi(value);
|
||
} else if (strcmp(key, "animation_curve") == 0) {
|
||
if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve[0], &config->animation_curve[1], &config->animation_curve[2], &config->animation_curve[3]) != 4) {
|
||
fprintf(stderr, "Error: Invalid animation_curve format: %s\n", value);
|
||
}
|
||
} else if (strcmp(key, "scroller_structs") == 0) {
|
||
config->scroller_structs = atoi(value);
|
||
} else if (strcmp(key, "scroller_default_proportion") == 0) {
|
||
config->scroller_default_proportion = atof(value);
|
||
} else if (strcmp(key, "scoller_focus_center") == 0) {
|
||
config->scoller_focus_center = atoi(value);
|
||
} else if (strcmp(key, "scroller_proportion_preset") == 0) {
|
||
if (sscanf(value, "%f,%f,%f", &config->scroller_proportion_preset[0], &config->scroller_proportion_preset[1], &config->scroller_proportion_preset[2]) != 3) {
|
||
fprintf(stderr, "Error: Invalid scroller_proportion_preset format: %s\n", value);
|
||
}
|
||
} else if (strcmp(key, "new_is_master") == 0) {
|
||
config->new_is_master = atoi(value);
|
||
} else if (strcmp(key, "default_mfact") == 0) {
|
||
config->default_mfact = atof(value);
|
||
} else if (strcmp(key, "default_nmaster") == 0) {
|
||
config->default_nmaster = atoi(value);
|
||
} else if (strcmp(key, "hotarea_size") == 0) {
|
||
config->hotarea_size = atoi(value);
|
||
} else if (strcmp(key, "enable_hotarea") == 0) {
|
||
config->enable_hotarea = atoi(value);
|
||
} else if (strcmp(key, "ov_tab_mode") == 0) {
|
||
config->ov_tab_mode = atoi(value);
|
||
} else if (strcmp(key, "overviewgappi") == 0) {
|
||
config->overviewgappi = atoi(value);
|
||
} else if (strcmp(key, "overviewgappo") == 0) {
|
||
config->overviewgappo = atoi(value);
|
||
} else if (strcmp(key, "axis_bind_apply_timeout") == 0) {
|
||
config->axis_bind_apply_timeout = atoi(value);
|
||
} else if (strcmp(key, "focus_on_activate") == 0) {
|
||
config->focus_on_activate = atoi(value);
|
||
} else if (strcmp(key, "numlockon") == 0) {
|
||
config->numlockon = atoi(value);
|
||
} else if (strcmp(key, "bypass_surface_visibility") == 0) {
|
||
config->bypass_surface_visibility = atoi(value);
|
||
} else if (strcmp(key, "sloppyfocus") == 0) {
|
||
config->sloppyfocus = atoi(value);
|
||
} else if (strcmp(key, "warpcursor") == 0) {
|
||
config->warpcursor = atoi(value);
|
||
} else if (strcmp(key, "smartgaps") == 0) {
|
||
config->smartgaps = atoi(value);
|
||
} else if (strcmp(key, "gappih") == 0) {
|
||
config->gappih = atoi(value);
|
||
} else if (strcmp(key, "gappiv") == 0) {
|
||
config->gappiv = atoi(value);
|
||
} else if (strcmp(key, "gappoh") == 0) {
|
||
config->gappoh = atoi(value);
|
||
} else if (strcmp(key, "gappov") == 0) {
|
||
config->gappov = atoi(value);
|
||
} else if (strcmp(key, "borderpx") == 0) {
|
||
config->borderpx = atoi(value);
|
||
} else if (strcmp(key, "rootcolor") == 0) {
|
||
long int color = parse_color(value);
|
||
if (color == -1) {
|
||
fprintf(stderr, "Error: Invalid rootcolor format: %s\n", value);
|
||
} else {
|
||
parseColoer(config->rootcolor,color);
|
||
}
|
||
} else if (strcmp(key, "bordercolor") == 0) {
|
||
long int color = parse_color(value);
|
||
if (color == -1) {
|
||
fprintf(stderr, "Error: Invalid bordercolor format: %s\n", value);
|
||
} else {
|
||
parseColoer(config->bordercolor,color);
|
||
}
|
||
} else if (strcmp(key, "focuscolor") == 0) {
|
||
long int color = parse_color(value);
|
||
if (color == -1) {
|
||
fprintf(stderr, "Error: Invalid focuscolor format: %s\n", value);
|
||
} else {
|
||
parseColoer(config->focuscolor,color);
|
||
}
|
||
} else if (strcmp(key, "maxmizescreencolor") == 0) {
|
||
long int color = parse_color(value);
|
||
if (color == -1) {
|
||
fprintf(stderr, "Error: Invalid maxmizescreencolor format: %s\n", value);
|
||
} else {
|
||
parseColoer(config->maxmizescreencolor,color);
|
||
}
|
||
} else if (strcmp(key, "urgentcolor") == 0) {
|
||
long int color = parse_color(value);
|
||
if (color == -1) {
|
||
fprintf(stderr, "Error: Invalid urgentcolor format: %s\n", value);
|
||
} else {
|
||
parseColoer(config->urgentcolor,color);
|
||
}
|
||
} else if (strcmp(key, "scratchpadcolor") == 0) {
|
||
long int color = parse_color(value);
|
||
if (color == -1) {
|
||
fprintf(stderr, "Error: Invalid scratchpadcolor format: %s\n", value);
|
||
} else {
|
||
parseColoer(config->scratchpadcolor,color);
|
||
}
|
||
} else if (strcmp(key, "globalcolor") == 0) {
|
||
long int color = parse_color(value);
|
||
if (color == -1) {
|
||
fprintf(stderr, "Error: Invalid globalcolor format: %s\n", value);
|
||
} else {
|
||
parseColoer(config->globalcolor,color);
|
||
}
|
||
} else if (strcmp(key, "autostart") == 0) {
|
||
if (sscanf(value, "%[^,],%[^,],%[^,]", config->autostart[0], config->autostart[1], config->autostart[2]) != 3) {
|
||
fprintf(stderr, "Error: Invalid autostart format: %s\n", value);
|
||
}
|
||
} else if (strcmp(key, "tags") == 0) {
|
||
int id;
|
||
char name[256];
|
||
if (sscanf(value, "id:%d,name:%255[^\n]", &id, name) == 2) {
|
||
if (id >= 1 && id <= 9) {
|
||
config->tags[id - 1].id = id;
|
||
strncpy(config->tags[id - 1].name, name, sizeof(config->tags[id - 1].name));
|
||
} else {
|
||
fprintf(stderr, "Error: Invalid tag id: %d\n", id);
|
||
}
|
||
} else {
|
||
fprintf(stderr, "Error: Invalid tags format: %s\n", value);
|
||
}
|
||
} else if (strcmp(key, "windowrule") == 0) {
|
||
config->window_rules = realloc(config->window_rules, (config->window_rules_count + 1) * sizeof(ConfigWinRule));
|
||
if (!config->window_rules) {
|
||
fprintf(stderr, "Error: Failed to allocate memory for window rules\n");
|
||
return;
|
||
}
|
||
|
||
ConfigWinRule *rule = &config->window_rules[config->window_rules_count];
|
||
memset(rule, 0, sizeof(ConfigWinRule));
|
||
|
||
rule->isfloating = -1;
|
||
rule->isfullscreen = -1;
|
||
rule->isnoborder = -1;
|
||
rule->monitor = -1;
|
||
rule->width = -1;
|
||
rule->height = -1;
|
||
rule->animation_type = NULL;
|
||
rule->scroller_proportion = -1;
|
||
rule->id = NULL;
|
||
rule->title = NULL;
|
||
rule->tags = 0;
|
||
|
||
|
||
char *token = strtok(value, ",");
|
||
while (token != NULL) {
|
||
char *colon = strchr(token, ':');
|
||
if (colon != NULL) {
|
||
*colon = '\0';
|
||
char *key = token;
|
||
char *val = colon + 1;
|
||
|
||
if (strcmp(key, "isfloating") == 0) {
|
||
rule->isfloating = atoi(val);
|
||
} else if (strcmp(key, "title") == 0) {
|
||
rule->title = strdup(val);
|
||
} else if (strcmp(key, "appid") == 0) {
|
||
rule->id = strdup(val);
|
||
} else if (strcmp(key, "animation_type") == 0) {
|
||
rule->animation_type = strdup(val);
|
||
} else if (strcmp(key, "tags") == 0) {
|
||
rule->tags = 1 << (atoi(val) - 1);
|
||
} else if (strcmp(key, "monitor") == 0) {
|
||
rule->monitor = atoi(val);
|
||
} else if (strcmp(key, "width") == 0) {
|
||
rule->width = atoi(val);
|
||
} else if (strcmp(key, "height") == 0) {
|
||
rule->height = atoi(val);
|
||
} else if (strcmp(key, "isnoborder") == 0) {
|
||
rule->isnoborder = atoi(val);
|
||
} else if (strcmp(key, "scroller_proportion") == 0) {
|
||
rule->scroller_proportion = atof(val);
|
||
} else if (strcmp(key, "isfullscreen") == 0) {
|
||
rule->isfullscreen = atoi(val);
|
||
}
|
||
}
|
||
token = strtok(NULL, ",");
|
||
}
|
||
config->window_rules_count++;
|
||
} else if (strcmp(key, "monitorrule") == 0) {
|
||
config->monitor_rules = realloc(config->monitor_rules, (config->monitor_rules_count + 1) * sizeof(ConfigMonitorRule));
|
||
if (!config->monitor_rules) {
|
||
fprintf(stderr, "Error: Failed to allocate memory for monitor rules\n");
|
||
return;
|
||
}
|
||
|
||
ConfigMonitorRule *rule = &config->monitor_rules[config->monitor_rules_count];
|
||
memset(rule, 0, sizeof(ConfigMonitorRule));
|
||
|
||
char layout[256], name[256];
|
||
int parsed = sscanf(value, "%255[^,],%f,%d,%255[^,],%d,%f,%d,%d",
|
||
name,
|
||
&rule->mfact,
|
||
&rule->nmaster,
|
||
layout,
|
||
&rule->rr,
|
||
&rule->scale,
|
||
&rule->x,
|
||
&rule->y);
|
||
|
||
if (parsed == 8) {
|
||
rule->name = strdup(name);
|
||
rule->layout = strdup(layout);
|
||
|
||
if (!rule->name || !rule->layout) {
|
||
if (rule->name) free((void *)rule->name);
|
||
if (rule->layout) free((void *)rule->layout);
|
||
fprintf(stderr, "Error: Failed to allocate memory for monitor rule\n");
|
||
return;
|
||
}
|
||
|
||
config->monitor_rules_count++;
|
||
} else {
|
||
fprintf(stderr, "Error: Invalid monitorrule format: %s\n", value);
|
||
}
|
||
} else if (strncmp(key, "bind", 4) == 0) {
|
||
config->key_bindings = realloc(config->key_bindings, (config->key_bindings_count + 1) * sizeof(KeyBinding));
|
||
if (!config->key_bindings) {
|
||
fprintf(stderr, "Error: Failed to allocate memory for key bindings\n");
|
||
return;
|
||
}
|
||
|
||
KeyBinding *binding = &config->key_bindings[config->key_bindings_count];
|
||
memset(binding, 0, sizeof(KeyBinding));
|
||
|
||
char mod_str[256], keysym_str[256], func_name[256], arg_value[256] = "none";
|
||
if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, keysym_str, func_name, arg_value) < 3) {
|
||
fprintf(stderr, "Error: Invalid bind format: %s\n", value);
|
||
return;
|
||
}
|
||
|
||
binding->mod = parse_mod(mod_str);
|
||
binding->keysym = parse_keysym(keysym_str);
|
||
binding->arg.v = NULL;
|
||
binding->func = parse_func_name(func_name, &binding->arg, arg_value);
|
||
if (!binding->func){
|
||
fprintf(stderr, "Error: Unknown function in bind: %s\n", func_name);
|
||
} else {
|
||
config->key_bindings_count++;
|
||
}
|
||
|
||
} else if (strncmp(key, "mousebind", 9) == 0) {
|
||
config->mouse_bindings = realloc(config->mouse_bindings, (config->mouse_bindings_count + 1) * sizeof(MouseBinding));
|
||
if (!config->mouse_bindings) {
|
||
fprintf(stderr, "Error: Failed to allocate memory for mouse bindings\n");
|
||
return;
|
||
}
|
||
|
||
MouseBinding *binding = &config->mouse_bindings[config->mouse_bindings_count];
|
||
memset(binding, 0, sizeof(MouseBinding));
|
||
|
||
char mod_str[256], button_str[256], func_name[256], arg_value[256] = "none";
|
||
if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, button_str, func_name, arg_value) < 3) {
|
||
fprintf(stderr, "Error: Invalid mousebind format: %s\n", value);
|
||
return;
|
||
}
|
||
|
||
binding->mod = parse_mod(mod_str);
|
||
binding->button = parseButton(button_str);
|
||
binding->arg.v = NULL;
|
||
binding->func = parse_func_name(func_name, &binding->arg, arg_value);
|
||
if (!binding->func){
|
||
fprintf(stderr, "Error: Unknown function in mousebind: %s\n", func_name);
|
||
} else {
|
||
config->mouse_bindings_count++;
|
||
}
|
||
} else if (strncmp(key, "axisbind", 8) == 0) {
|
||
config->axis_bindings = realloc(config->axis_bindings, (config->axis_bindings_count + 1) * sizeof(AxisBinding));
|
||
if (!config->axis_bindings) {
|
||
fprintf(stderr, "Error: Failed to allocate memory for axis bindings\n");
|
||
return;
|
||
}
|
||
|
||
AxisBinding *binding = &config->axis_bindings[config->axis_bindings_count];
|
||
memset(binding, 0, sizeof(AxisBinding));
|
||
|
||
char mod_str[256], dir_str[256], func_name[256], arg_value[256] = "none";
|
||
if (sscanf(value, "%[^,],%[^,],%[^,],%[^\n]", mod_str, dir_str, func_name, arg_value) < 3) {
|
||
fprintf(stderr, "Error: Invalid axisbind format: %s\n", value);
|
||
return;
|
||
}
|
||
|
||
binding->mod = parse_mod(mod_str);
|
||
binding->dir = parseDirection(dir_str);
|
||
binding->arg.v = NULL;
|
||
binding->func = parse_func_name(func_name, &binding->arg, arg_value);
|
||
|
||
if (!binding->func){
|
||
fprintf(stderr, "Error: Unknown function in axisbind: %s\n", func_name);
|
||
} else {
|
||
config->axis_bindings_count++;
|
||
}
|
||
|
||
} else {
|
||
fprintf(stderr, "Error: Unknown key: %s\n", key);
|
||
}
|
||
}
|
||
|
||
void parse_config_file(Config *config, const char *file_path) {
|
||
FILE *file = fopen(file_path, "r");
|
||
if (!file) {
|
||
perror("Error opening file");
|
||
return;
|
||
}
|
||
|
||
char line[512];
|
||
while (fgets(line, sizeof(line), file)) {
|
||
if (line[0] == '#' || line[0] == '\n') continue;
|
||
parse_config_line(config, line);
|
||
}
|
||
|
||
fclose(file);
|
||
} |