diff --git a/src/config/parse_config.h b/src/config/parse_config.h index bd7b9b6..cd7d822 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -212,6 +212,54 @@ typedef struct { typedef void (*FuncType)(const Arg *); Config config; +// Helper function to trim whitespace from start and end of a string +void trim_whitespace(char *str) { + if (str == NULL || *str == '\0') return; + + // Trim leading space + char *start = str; + while (isspace((unsigned char)*start)) { + start++; + } + + // Trim trailing space + char *end = str + strlen(str) - 1; + while (end > start && isspace((unsigned char)*end)) { + end--; + } + + // Null-terminate the trimmed string + *(end + 1) = '\0'; + + // Move the trimmed part to the beginning if needed + if (start != str) { + memmove(str, start, end - start + 2); // +2 to include null terminator + } +} + +int parse_double_array(const char *input, double *output, int max_count) { + char *dup = strdup(input); // 复制一份用于修改 + char *token; + int count = 0; + + token = strtok(dup, ","); + while (token != NULL && count < max_count) { + trim_whitespace(token); // 对每一个分割后的 token 去除前后空格 + char *endptr; + double val = strtod(token, &endptr); + if (endptr == token || *endptr != '\0') { + fprintf(stderr, "Error: Invalid number in array: %s\n", token); + free(dup); + return -1; // 解析失败 + } + output[count++] = val; + token = strtok(NULL, ","); + } + + free(dup); + return count; +} + // 清理字符串中的不可见字符(包括 \r, \n, 空格等) char *sanitize_string(char *str) { // 去除首部不可见字符 @@ -611,6 +659,10 @@ void parse_config_line(Config *config, const char *line) { return; } + // Then trim each part separately + trim_whitespace(key); + trim_whitespace(value); + if (strcmp(key, "animations") == 0) { config->animations = atoi(value); } else if (strcmp(key, "animation_type_open") == 0) { @@ -638,34 +690,24 @@ void parse_config_line(Config *config, const char *line) { } else if (strcmp(key, "animation_duration_close") == 0) { config->animation_duration_close = atoi(value); } else if (strcmp(key, "animation_curve_move") == 0) { - if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve_move[0], - &config->animation_curve_move[1], - &config->animation_curve_move[2], - &config->animation_curve_move[3]) != 4) { - fprintf(stderr, "Error: Invalid animation_curve_move format: %s\n", - value); + int num = parse_double_array(value, config->animation_curve_move, 4); + if (num != 4) { + fprintf(stderr, "Error: Failed to parse animation_curve_move: %s\n", value); } } else if (strcmp(key, "animation_curve_open") == 0) { - if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve_open[0], - &config->animation_curve_open[1], - &config->animation_curve_open[2], - &config->animation_curve_open[3]) != 4) { - fprintf(stderr, "Error: Invalid animation_curve_open format: %s\n", - value); + int num = parse_double_array(value, config->animation_curve_open, 4); + if (num != 4) { + fprintf(stderr, "Error: Failed to parse animation_curve_open: %s\n", value); } } else if (strcmp(key, "animation_curve_tag") == 0) { - if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve_tag[0], - &config->animation_curve_tag[1], &config->animation_curve_tag[2], - &config->animation_curve_tag[3]) != 4) { - fprintf(stderr, "Error: Invalid animation_curve_tag format: %s\n", value); + int num = parse_double_array(value, config->animation_curve_tag, 4); + if (num != 4) { + fprintf(stderr, "Error: Failed to parse animation_curve_tag: %s\n", value); } } else if (strcmp(key, "animation_curve_close") == 0) { - if (sscanf(value, "%lf,%lf,%lf,%lf", &config->animation_curve_close[0], - &config->animation_curve_close[1], - &config->animation_curve_close[2], - &config->animation_curve_close[3]) != 4) { - fprintf(stderr, "Error: Invalid animation_curve_close format: %s\n", - value); + int num = parse_double_array(value, config->animation_curve_close, 4); + if (num != 4) { + fprintf(stderr, "Error: Failed to parse animation_curve_close: %s\n", value); } } else if (strcmp(key, "scroller_structs") == 0) { config->scroller_structs = atoi(value); @@ -925,6 +967,9 @@ void parse_config_line(Config *config, const char *line) { config->autostart[1], config->autostart[2]) != 3) { fprintf(stderr, "Error: Invalid autostart format: %s\n", value); } + trim_whitespace(config->autostart[0]); + trim_whitespace(config->autostart[1]); + trim_whitespace(config->autostart[2]); } else if (strcmp(key, "tags") == 0) { config->tag_rules = realloc(config->tag_rules, @@ -949,6 +994,9 @@ void parse_config_line(Config *config, const char *line) { char *key = token; char *val = colon + 1; + trim_whitespace(key); + trim_whitespace(val); + if (strcmp(key, "id") == 0) { rule->id = atoi(val); } else if (strcmp(key, "layout_name") == 0) { @@ -1002,6 +1050,9 @@ void parse_config_line(Config *config, const char *line) { char *key = token; char *val = colon + 1; + trim_whitespace(key); + trim_whitespace(val); + if (strcmp(key, "isfloating") == 0) { rule->isfloating = atoi(val); } else if (strcmp(key, "title") == 0) { @@ -1043,6 +1094,8 @@ void parse_config_line(Config *config, const char *line) { } else if (strcmp(key, "globalkeybinding") == 0) { char mod_str[256], keysym_str[256]; sscanf(val, "%[^-]-%[a-zA-Z]", mod_str, keysym_str); + trim_whitespace(mod_str); + trim_whitespace(keysym_str); rule->globalkeybinding.mod = parse_mod(mod_str); rule->globalkeybinding.keysym = parse_keysym(keysym_str); } @@ -1051,37 +1104,58 @@ void parse_config_line(Config *config, const char *line) { } 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; - } +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)); +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); +// 临时存储每个字段的原始字符串 +char raw_name[256], raw_layout[256]; +char raw_mfact[256], raw_nmaster[256], raw_rr[256]; +char raw_scale[256], raw_x[256], raw_y[256]; - if (parsed == 8) { - rule->name = strdup(name); - rule->layout = strdup(layout); +// 先读取所有字段为字符串 +int parsed = sscanf(value, "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255s", + raw_name, raw_mfact, raw_nmaster, raw_layout, + raw_rr, raw_scale, raw_x, raw_y); - if (!rule->name || !rule->layout) { +if (parsed == 8) { + // 修剪每个字段的空格 + trim_whitespace(raw_name); + trim_whitespace(raw_mfact); + trim_whitespace(raw_nmaster); + trim_whitespace(raw_layout); + trim_whitespace(raw_rr); + trim_whitespace(raw_scale); + trim_whitespace(raw_x); + trim_whitespace(raw_y); + + // 转换修剪后的字符串为特定类型 + rule->name = strdup(raw_name); + rule->layout = strdup(raw_layout); + rule->mfact = atof(raw_mfact); + rule->nmaster = atoi(raw_nmaster); + rule->rr = atoi(raw_rr); + rule->scale = atof(raw_scale); + rule->x = atoi(raw_x); + rule->y = atoi(raw_y); + + if (!rule->name || !rule->layout) { if (rule->name) - free((void *)rule->name); + free((void *)rule->name); if (rule->layout) - free((void *)rule->layout); + free((void *)rule->layout); fprintf(stderr, "Error: Failed to allocate memory for monitor rule\n"); return; - } + } - config->monitor_rules_count++; + config->monitor_rules_count++; } else { fprintf(stderr, "Error: Invalid monitorrule format: %s\n", value); } @@ -1092,6 +1166,8 @@ void parse_config_line(Config *config, const char *line) { fprintf(stderr, "Error: Invalid bind format: %s\n", value); return; } + trim_whitespace(env_type); + trim_whitespace(env_value); setenv(env_type, env_value, 1); } else if (strncmp(key, "exec", 9) == 0) { @@ -1150,6 +1226,13 @@ void parse_config_line(Config *config, const char *line) { fprintf(stderr, "Error: Invalid bind format: %s\n", value); return; } + trim_whitespace(mod_str); + trim_whitespace(keysym_str); + trim_whitespace(func_name); + trim_whitespace(arg_value); + trim_whitespace(arg_value2); + trim_whitespace(arg_value3); + trim_whitespace(arg_value4); binding->mod = parse_mod(mod_str); binding->keysym = parse_keysym(keysym_str); @@ -1193,6 +1276,13 @@ void parse_config_line(Config *config, const char *line) { fprintf(stderr, "Error: Invalid mousebind format: %s\n", value); return; } + trim_whitespace(mod_str); + trim_whitespace(button_str); + trim_whitespace(func_name); + trim_whitespace(arg_value); + trim_whitespace(arg_value2); + trim_whitespace(arg_value3); + trim_whitespace(arg_value4); binding->mod = parse_mod(mod_str); binding->button = parse_button(button_str); @@ -1235,6 +1325,14 @@ void parse_config_line(Config *config, const char *line) { return; } + trim_whitespace(mod_str); + trim_whitespace(dir_str); + trim_whitespace(func_name); + trim_whitespace(arg_value); + trim_whitespace(arg_value2); + trim_whitespace(arg_value3); + trim_whitespace(arg_value4); + binding->mod = parse_mod(mod_str); binding->dir = parse_direction(dir_str); binding->arg.v = NULL; @@ -1280,6 +1378,15 @@ void parse_config_line(Config *config, const char *line) { return; } + trim_whitespace(mod_str); + trim_whitespace(motion_str); + trim_whitespace(fingers_count_str); + trim_whitespace(func_name); + trim_whitespace(arg_value); + trim_whitespace(arg_value2); + trim_whitespace(arg_value3); + trim_whitespace(arg_value4); + binding->mod = parse_mod(mod_str); binding->motion = parse_direction(motion_str); binding->fingers_count = atoi(fingers_count_str);