diff --git a/include/core/import_export.h b/include/core/import_export.h index 01d3b67..954f4a0 100644 --- a/include/core/import_export.h +++ b/include/core/import_export.h @@ -5,10 +5,15 @@ #define EXPORT_VERSION "1.0" -// 导出 PATH 到文件 -int export_paths_to_file(const StringList *list, const char *filepath, int is_system); +typedef struct { + StringList system; + StringList user; +} ExportData; -// 从文件导入 PATH -int import_paths_from_file(const char *filepath, StringList *list); +// 导出 PATH 到文件 +int export_paths_to_file(const ExportData *data, const char *filepath); + +// 从文件导入 PATH (返回是否包含全部格式) +int import_paths_from_file(const char *filepath, ExportData *data); #endif // IMPORT_EXPORT_H \ No newline at end of file diff --git a/src/controller/callbacks.c b/src/controller/callbacks.c index f395558..7943e5e 100644 --- a/src/controller/callbacks.c +++ b/src/controller/callbacks.c @@ -386,18 +386,61 @@ int btn_import_cb(Ihandle *self) char *filepath = IupGetAttribute(filedlg, "VALUE"); if (filepath) { - Ihandle *tabs_main = IupGetDialogChild(dlg, "TABS_MAIN"); - int pos = IupGetInt(tabs_main, "VALUEPOS"); - - StringList *target_list = (pos == 0) ? &ctx->sys_paths : &ctx->user_paths; - - if (import_paths_from_file(filepath, target_list) == 0) + ExportData imported; + if (import_paths_from_file(filepath, &imported) == 0) { - Ihandle *current_list = get_current_list(dlg); - sync_string_list_to_ui(current_list, target_list); + int has_system = imported.system.count > 0; + int has_user = imported.user.count > 0; + + if (!has_system && !has_user) + { + IupMessage("错误", "文件中没有找到有效的路径!"); + return IUP_DEFAULT; + } + + int choice = 0; + if (has_system && has_user) + { + choice = IupAlarm("导入选项", "请选择导入目标:", + "仅系统变量", "仅用户变量", "全部导入"); + } + else if (has_system) + { + choice = 3; + } + else + { + choice = 2; + } + + int total_imported = 0; + + if (choice == 1 || choice == 3) + { + clear_string_list(&ctx->sys_paths); + for (int i = 0; i < imported.system.count; i++) + { + add_string_list(&ctx->sys_paths, imported.system.items[i]); + } + Ihandle *list_sys = IupGetDialogChild(dlg, "LIST_SYS"); + sync_string_list_to_ui(list_sys, &ctx->sys_paths); + total_imported += imported.system.count; + } + + if (choice == 2 || choice == 3) + { + clear_string_list(&ctx->user_paths); + for (int i = 0; i < imported.user.count; i++) + { + add_string_list(&ctx->user_paths, imported.user.items[i]); + } + Ihandle *list_user = IupGetDialogChild(dlg, "LIST_USER"); + sync_string_list_to_ui(list_user, &ctx->user_paths); + total_imported += imported.user.count; + } char msg[256]; - snprintf(msg, sizeof(msg), "成功导入 %d 个路径!", target_list->count); + snprintf(msg, sizeof(msg), "成功导入 %d 个路径!", total_imported); IupMessage("导入成功", msg); Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); @@ -422,11 +465,9 @@ int btn_export_cb(Ihandle *self) if (!ctx) return IUP_DEFAULT; - Ihandle *tabs_main = IupGetDialogChild(dlg, "TABS_MAIN"); - int pos = IupGetInt(tabs_main, "VALUEPOS"); - - StringList *source_list = (pos == 0) ? &ctx->sys_paths : &ctx->user_paths; - int is_system = (pos == 0); + ExportData data; + data.system = ctx->sys_paths; + data.user = ctx->user_paths; Ihandle *filedlg = IupFileDlg(); IupSetAttribute(filedlg, "DIALOGTYPE", "SAVE"); @@ -436,7 +477,7 @@ int btn_export_cb(Ihandle *self) IupSetAttribute(filedlg, "DEFAULTEXT", "json"); char default_name[64]; - snprintf(default_name, sizeof(default_name), "path_%s.json", is_system ? "system" : "user"); + snprintf(default_name, sizeof(default_name), "path_all.json"); IupSetAttribute(filedlg, "VALUE", default_name); IupPopup(filedlg, IUP_CENTER, IUP_CENTER); @@ -446,10 +487,23 @@ int btn_export_cb(Ihandle *self) char *filepath = IupGetAttribute(filedlg, "VALUE"); if (filepath) { - if (export_paths_to_file(source_list, filepath, is_system) == 0) + char final_path[MAX_PATH]; + if (strchr(filepath, '.') == NULL) { - char msg[256]; - snprintf(msg, sizeof(msg), "成功导出 %d 个路径到:\n%s", source_list->count, filepath); + snprintf(final_path, sizeof(final_path), "%s.json", filepath); + } + else + { + strncpy(final_path, filepath, sizeof(final_path) - 1); + final_path[sizeof(final_path) - 1] = '\0'; + } + filepath = final_path; + + if (export_paths_to_file(&data, filepath) == 0) + { + char msg[512]; + snprintf(msg, sizeof(msg), "成功导出!\n系统变量: %d 个\n用户变量: %d 个\n\n保存位置: %s", + data.system.count, data.user.count, filepath); IupMessage("导出成功", msg); } else @@ -509,5 +563,6 @@ int btn_help_cb(Ihandle *self) "邮箱:3364451258@qq.com\n" "GitHub:https://github.com/LHY0125/PathEditor\n" "记得给我的项目点个star!"); + return IUP_DEFAULT; } \ No newline at end of file diff --git a/src/core/import_export.c b/src/core/import_export.c index 08a862c..3712a1f 100644 --- a/src/core/import_export.c +++ b/src/core/import_export.c @@ -58,39 +58,56 @@ static char *escape_json_string(const char *str) return result; } -// 导出 PATH 到 JSON 文件 -int export_paths_to_file(const StringList *list, const char *filepath, int is_system) +// 导出路径数据到 JSON 文件 +int export_paths_to_file(const ExportData *data, const char *filepath) { - if (!list || !filepath) + if (!data || !filepath) return -1; - FILE *fp = fopen(filepath, "w, ccs=UTF-8"); + FILE *fp = fopen(filepath, "w"); if (!fp) return -1; + fprintf(fp, "\xEF\xBB\xBF"); + char datetime[64]; get_current_datetime(datetime, sizeof(datetime)); fprintf(fp, "{\n"); fprintf(fp, " \"version\": \"%s\",\n", EXPORT_VERSION); - fprintf(fp, " \"type\": \"%s\",\n", is_system ? "SYSTEM" : "USER"); + fprintf(fp, " \"type\": \"ALL\",\n"); fprintf(fp, " \"exported\": \"%s\",\n", datetime); - fprintf(fp, " \"paths\": [\n"); - for (int i = 0; i < list->count; i++) + fprintf(fp, " \"system\": [\n"); + for (int i = 0; i < data->system.count; i++) { - if (list->items[i]) + if (data->system.items[i]) { - char *escaped = escape_json_string(list->items[i]); + char *escaped = escape_json_string(data->system.items[i]); if (escaped) { - fprintf(fp, " \"%s\"%s\n", escaped, (i < list->count - 1) ? "," : ""); + fprintf(fp, " \"%s\"%s\n", escaped, (i < data->system.count - 1) ? "," : ""); free(escaped); } } } + fprintf(fp, " ],\n"); + fprintf(fp, " \"user\": [\n"); + for (int i = 0; i < data->user.count; i++) + { + if (data->user.items[i]) + { + char *escaped = escape_json_string(data->user.items[i]); + if (escaped) + { + fprintf(fp, " \"%s\"%s\n", escaped, (i < data->user.count - 1) ? "," : ""); + free(escaped); + } + } + } fprintf(fp, " ]\n"); + fprintf(fp, "}\n"); fclose(fp); @@ -112,7 +129,7 @@ static void trim_whitespace(char *str) memmove(str, start, strlen(start) + 1); } -// 检查是否为注释行或空行 +// 检查字符串是否为注释行或空行 static int is_comment_or_empty(const char *line) { while (*line == ' ' || *line == '\t') @@ -124,118 +141,156 @@ static int is_comment_or_empty(const char *line) return 0; } -// 检查是否为 JSON 文件 +// 检查文件是否为 JSON 格式 static int is_json_file(const char *filepath) { const char *ext = strrchr(filepath, '.'); return ext && strcasecmp(ext, ".json") == 0; } -// 从文件导入 PATH -int import_paths_from_file(const char *filepath, StringList *list) +// 从文件导入 PATH (返回是否包含全部格式) +int import_paths_from_file(const char *filepath, ExportData *data) { - if (!filepath || !list) + if (!filepath || !data) return -1; - if (is_json_file(filepath)) + init_string_list(&data->system); + init_string_list(&data->user); + + if (!is_json_file(filepath)) { - FILE *fp = fopen(filepath, "r, ccs=UTF-8"); + FILE *fp = fopen(filepath, "rb"); if (!fp) return -1; - clear_string_list(list); - - char buffer[8192]; - int in_paths = 0; - int depth = 0; - int in_string = 0; - char path_buffer[4096]; - int path_len = 0; - - while (fgets(buffer, sizeof(buffer), fp)) - { - char *p = buffer; - while (*p) - { - if (*p == '"' && (p == buffer || *(p - 1) != '\\')) - { - in_string = !in_string; - } - else if (in_string && *p == '\\') - { - p++; - if (*p) - { - if (*p == 'n') - *p = '\n'; - else if (*p == 'r') - *p = '\r'; - else if (*p == 't') - *p = '\t'; - } - } - else if (!in_string) - { - if (*p == '{' || *p == '[') - depth++; - else if (*p == '}' || *p == ']') - depth--; - else if (*p == ':') - in_paths = (depth == 1); - else if (in_paths && depth == 2 && *p == '"') - { - path_len = 0; - p++; - while (*p && path_len < (int)sizeof(path_buffer) - 1) - { - if (*p == '"' && *(p - 1) != '\\') - break; - if (*p == '\\' && *(p + 1)) - { - p++; - if (*p == 'n') - *p = '\n'; - else if (*p == 'r') - *p = '\r'; - else if (*p == 't') - *p = '\t'; - } - path_buffer[path_len++] = *p++; - } - if (path_len > 0) - { - path_buffer[path_len] = '\0'; - add_string_list(list, path_buffer); - } - } - } - p++; - } - } - - fclose(fp); - return 0; - } - else - { - FILE *fp = fopen(filepath, "r, ccs=UTF-8"); - if (!fp) - return -1; - - clear_string_list(list); + StringList list; + init_string_list(&list); char line[4096]; while (fgets(line, sizeof(line), fp)) { trim_whitespace(line); - if (is_comment_or_empty(line)) continue; - - add_string_list(list, line); + add_string_list(&list, line); } fclose(fp); + + data->system = list; return 0; } + + FILE *fp = fopen(filepath, "rb"); + if (!fp) + return -1; + + char buffer[8192]; + int in_system = 0; + int in_user = 0; + int depth = 0; + int in_string = 0; + char path_buffer[4096]; + int path_len = 0; + + while (fgets(buffer, sizeof(buffer), fp)) + { + char *p = buffer; + while (*p) + { + if (*p == '"' && (p == buffer || *(p - 1) != '\\')) + { + in_string = !in_string; + } + else if (in_string && *p == '\\') + { + p++; + if (*p) + { + if (*p == 'n') + *p = '\n'; + else if (*p == 'r') + *p = '\r'; + else if (*p == 't') + *p = '\t'; + } + } + else if (!in_string) + { + if (*p == '{' || *p == '[') + depth++; + else if (*p == '}' || *p == ']') + depth--; + else if (depth == 1 && *p == '"') + { + if (strncmp(p, "\"system\"", 8) == 0) + { + in_system = 1; + in_user = 0; + } + else if (strncmp(p, "\"user\"", 6) == 0) + { + in_user = 1; + in_system = 0; + } + } + else if (in_system && depth == 2 && *p == '"') + { + path_len = 0; + p++; + while (*p && path_len < (int)sizeof(path_buffer) - 1) + { + if (*p == '"' && *(p - 1) != '\\') + break; + if (*p == '\\' && *(p + 1)) + { + p++; + if (*p == 'n') + *p = '\n'; + else if (*p == 'r') + *p = '\r'; + else if (*p == 't') + *p = '\t'; + } + path_buffer[path_len++] = *p++; + } + if (path_len > 0) + { + path_buffer[path_len] = '\0'; + add_string_list(&data->system, path_buffer); + } + } + else if (in_user && depth == 2 && *p == '"') + { + path_len = 0; + p++; + while (*p && path_len < (int)sizeof(path_buffer) - 1) + { + if (*p == '"' && *(p - 1) != '\\') + break; + if (*p == '\\' && *(p + 1)) + { + p++; + if (*p == 'n') + *p = '\n'; + else if (*p == 'r') + *p = '\r'; + else if (*p == 't') + *p = '\t'; + } + path_buffer[path_len++] = *p++; + } + if (path_len > 0) + { + path_buffer[path_len] = '\0'; + add_string_list(&data->user, path_buffer); + } + } + } + p++; + } + } + + fclose(fp); + return 0; } \ No newline at end of file