diff --git a/sane/DlgArea.cpp b/sane/DlgArea.cpp index c850a83..2b7e9fa 100644 --- a/sane/DlgArea.cpp +++ b/sane/DlgArea.cpp @@ -14,20 +14,20 @@ int dlg_area::area_min_pixel = 50; dlg_area::dlg_area(HWND parent) : dlg_base(parent, IDD_AREA) , unit_(PAPER_UNIT_MM), paper_w_(210), paper_h_(297), dpi_(200) , x_(0), y_(0), w_(paper_w_), h_(paper_h_) - , exit_code_(0), paper_(L"A4") + , paper_(L"A4") , paper_w_0_(paper_w_), paper_h_0_(paper_h_), cursor_(NULL), drag_(DRAG_POS_NONE) , in_set_func_(false) { - std::wstring title(dlg_base::language_from_hz936(L"\u81EA\u5B9A\u4E49\u626B\u63CF\u533A\u57DF")); + std::wstring title(local_trans::lang_trans_between_hz936(CONST_STRING_CUSTOM_AREA)); create(); SetWindowTextW(hwnd(), title.c_str()); - title = dlg_base::language_from_hz936(L"\u6BEB\u7C73") + L" (mm)"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_UNIT_MM) + L" (mm)"; SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)&title[0]); - title = dlg_base::language_from_hz936(L"\u82F1\u5BF8") + L" (inch)"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_UNIT_INCH) + L" (inch)"; SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)&title[0]); - title = dlg_base::language_from_hz936(L"\u50CF\u7D20") + L" (px)"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_UNIT_PIXEL) + L" (px)"; SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)&title[0]); SendMessage(get_item(IDC_UNIT), CB_SETCURSEL, 0, 0); @@ -37,28 +37,28 @@ dlg_area::dlg_area(HWND parent) : dlg_base(parent, IDD_AREA) int width_diff = 0, w = 0; RECT r = { 0 }, rp = { 0 }; - title = dlg_base::language_from_hz936(L"\u7EB8\u5F20\u5C3A\u5BF8") + L":"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_OPT_PAPER) + L":"; set_item_text(IDC_STATIC_PAPER, title.c_str()); - title = dlg_base::language_from_hz936(L"\u5355\u4F4D") + L":"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_UNIT) + L":"; set_item_text(IDC_STATIC_UNIT, title.c_str()); - title = L"DPI (" + dlg_base::language_from_hz936(L"\u50CF\u7D20") + L"/" + dlg_base::language_from_hz936(L"\u82F1\u5BF8") + L"):"; + title = L"DPI (" + local_trans::lang_trans_between_hz936(CONST_STRING_UNIT_PIXEL) + L"/" + local_trans::lang_trans_between_hz936(CONST_STRING_UNIT_INCH) + L"):"; set_item_text(IDC_STATIC_DPI, title.c_str()); - title = dlg_base::language_from_hz936(L"\u533A\u57DF\u8BBE\u7F6E") + L":"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_AREA_SET) + L":"; set_item_text(IDC_STATIC_AREA, title.c_str()); - title = dlg_base::language_from_hz936(L"\u5DE6") + L":"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_LEFT) + L":"; set_item_text(IDC_STATIC_LEFT, title.c_str()); - title = dlg_base::language_from_hz936(L"\u4E0A") + L":"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_TOP) + L":"; set_item_text(IDC_STATIC_TOP, title.c_str()); - title = dlg_base::language_from_hz936(L"\u5BBD") + L":"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_WIDTH) + L":"; set_item_text(IDC_STATIC_W, title.c_str()); - title = dlg_base::language_from_hz936(L"\u9AD8") + L":"; + title = local_trans::lang_trans_between_hz936(CONST_STRING_HEIGHT) + L":"; set_item_text(IDC_STATIC_H, title.c_str()); - title = dlg_base::language_from_hz936(L"\u6062\u590D\u533A\u57DF"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_RESTORE_AREA); set_item_text(IDC_BUTTON_RESET, title.c_str()); - title = dlg_base::language_from_hz936(L"\u53D6\u6D88"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_CANCEL); set_item_text(IDCANCEL, title.c_str()); - title = dlg_base::language_from_hz936(L"\u786E\u5B9A"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_OK); set_item_text(IDOK, title.c_str()); layout(); @@ -142,11 +142,11 @@ void dlg_area::handle_command(WORD code, WORD id, HANDLE ctrl) } else if (id == IDCANCEL) { - exit_code_ = id; + quit_modal(id); } else if (id == IDOK) { - exit_code_ = id; + quit_modal(id); } else if (id == IDC_BUTTON_RESET) { @@ -344,7 +344,7 @@ std::wstring dlg_area::format_number(float v) } void dlg_area::refresh_paper_info(void) { - SetWindowTextW(get_item(IDC_EDIT_PAPER), (paper_ + L"(" + format_number(paper_w_) + L"\u00d7" + format_number(paper_h_) + L")").c_str()); + SetWindowTextW(get_item(IDC_EDIT_PAPER), (paper_ + L"(" + format_number(paper_w_) + local_trans::lang_trans_between_hz936(CONST_STRING_MULTIPLE) + format_number(paper_h_) + L")").c_str()); SetDlgItemInt(hwnd(), IDC_EDIT_DPI, UINT(dpi_), FALSE); in_set_func_ = true; @@ -796,43 +796,6 @@ void dlg_area::set_area(float x, float y, float w, float h) refresh_paper_info(); } -int dlg_area::do_modal(HWND parent) -{ - BOOL enable_parent = FALSE, - got = TRUE; - MSG msg = { 0 }; - - if (IsWindow(parent) && parent != GetDesktopWindow()) - { - EnableWindow(parent, FALSE); - enable_parent = TRUE; - } - - ShowWindow(hwnd(), SW_SHOW); - while ((got = GetMessage(&msg, NULL, 0, 0))) - { - if ((DWORD)got == -1) - break; - - //if (enable_parent && msg.hwnd == parent && - // msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST && - // msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) - // continue; - - TranslateMessage(&msg); - DispatchMessage(&msg); - if (exit_code_ == IDOK || exit_code_ == IDCANCEL) - break; - } - ShowWindow(hwnd(), SW_HIDE); - - if (enable_parent) - { - EnableWindow(parent, TRUE); - } - - return exit_code_; -} float dlg_area::x_in_mm(void) { return as_mm(x_); diff --git a/sane/DlgArea.h b/sane/DlgArea.h index 7c0feaf..1067cad 100644 --- a/sane/DlgArea.h +++ b/sane/DlgArea.h @@ -43,7 +43,6 @@ class dlg_area: public dlg_base float y_; float w_; float h_; - int exit_code_; RECT whole_; RECT user_sel_; @@ -92,7 +91,6 @@ public: public: void set_paper(const wchar_t* name, float width_mm, float height_mm, float dpi); void set_area(float x, float y, float w, float h); - int do_modal(HWND parent); // return IDOK or IDCANCEL float x_in_mm(void); float y_in_mm(void); float w_in_mm(void); diff --git a/sane/DlgCfgMgr.cpp b/sane/DlgCfgMgr.cpp new file mode 100644 index 0000000..7a9ce52 --- /dev/null +++ b/sane/DlgCfgMgr.cpp @@ -0,0 +1,201 @@ +// DlgIndicator.cpp: 实现文件 +// + +#include "DlgCfgMgr.h" +#include "resource.h" +#include "scanned_img.h" // for local_trans +#include "mem_dc.h" +#include "gb_json.h" + +// CDlgIndicator 对话框 + +dlg_cfg_mgr::dlg_cfg_mgr(gb::scanner_cfg* cfg, HWND parent) : cfg_(cfg), dlg_base(parent, IDD_CFG_MGR) +{ + create(); + + std::wstring title(local_trans::lang_trans_between_hz936(CONST_STRING_CFG_MANAGER)); + int dif = 0; + + SetWindowTextW(hwnd(), title.c_str()); + + title = local_trans::lang_trans_between_hz936(CONST_STRING_CFG_SCHEME); + set_item_text(IDC_STATIC_PAPER, title.c_str()); + set_item_fit_to_text(IDC_STATIC_PAPER); + + title = local_trans::lang_trans_between_hz936(CONST_STRING_DEL_SELECTED); + set_item_text(IDC_BUTTON_DEL_SEL, title.c_str()); + dif = set_item_fit_to_text(IDC_BUTTON_DEL_SEL); + if (dif) + offset_item(IDC_BUTTON_DEL_SEL, -dif, 0); + + title = local_trans::lang_trans_between_hz936(CONST_STRING_DEL_ALL); + set_item_text(IDC_BUTTON_DEL_ALL, title.c_str()); + set_item_fit_to_text(IDC_BUTTON_DEL_ALL); + + title = local_trans::lang_trans_between_hz936(CONST_STRING_CFG_CONTENT); + set_item_text(IDC_STATIC_SKETCH, title.c_str()); + + title = local_trans::lang_trans_between_hz936(CONST_STRING_OK); + set_item_text(IDOK, title.c_str()); +} +dlg_cfg_mgr::~dlg_cfg_mgr() +{ +} + + +BOOL dlg_cfg_mgr::handle_message(UINT msg, WPARAM wp, LPARAM lp) +{ + wchar_t text[40] = { 0 }; + BOOL ret = TRUE; + + switch (msg) + { + case WM_INITDIALOG: + on_init_dlg(); + UpdateWindow(hwnd()); + break; + case WM_COMMAND: + handle_command(HIWORD(wp), LOWORD(wp), (HWND)lp); + break; + case WM_NOTIFY: + handle_notify(wp, (LPNMHDR)lp); + break; + case WM_PAINT: + { + PAINTSTRUCT ps = { 0 }; + HDC hdc = BeginPaint(hwnd(), &ps); + { + compatible_dc dc(hdc); + on_paint(dc.get_dc()); + } + EndPaint(hwnd(), &ps); + } + break; + default: + ret = FALSE; + } + return ret; +} +void dlg_cfg_mgr::handle_command(WORD code, WORD id, HANDLE ctrl) +{ + wchar_t cls[128] = { 0 }; + + GetClassNameW((HWND)ctrl, cls, _countof(cls) - 1); + if (IS_BUTTON(cls)) + { + if (code == BN_CLICKED) + { + if (id == IDOK || id == IDCANCEL) + quit_modal(id); + else if (id == IDC_BUTTON_DEL_SEL) + on_del_selected(); + else if (id == IDC_BUTTON_DEL_ALL) + on_del_all(); + } + } + else if (IS_EDIT(cls)) + { + //if (code == EN_SETFOCUS) + // label_edit_ = (HWND)ctrl; + } +} +void dlg_cfg_mgr::handle_notify(UINT id, LPNMHDR pnhdr) +{ + if (id == IDC_LIST1) + { + if (pnhdr->code == LVN_BEGINLABELEDITW) + { + LPNMLVDISPINFOW pdisp = (LPNMLVDISPINFOW)pnhdr; + + label_ = pdisp->item.pszText; + } + else if (pnhdr->code == LVN_ENDLABELEDITW) + { + LPNMLVDISPINFOW pdisp = (LPNMLVDISPINFOW)pnhdr; + + if (pdisp->item.pszText && label_ != pdisp->item.pszText) + { + ListView_SetItemText(get_item(IDC_LIST1), pdisp->item.iItem, pdisp->item.iSubItem, pdisp->item.pszText); + + if (cfg_) + { + cfg_->rename_scheme(local_trans::u2a(label_.c_str(), CP_UTF8).c_str(), local_trans::u2a(pdisp->item.pszText, CP_UTF8).c_str()); + } + } + } + else if (pnhdr->code == LVN_ITEMCHANGED) + { + LPNMLISTVIEW pv = (LPNMLISTVIEW)pnhdr; + if ((pv->uNewState & LVIS_SELECTED) && (pv->uOldState & LVIS_SELECTED) == 0) + on_sel_changed(pv->iItem); + } + } +} +void dlg_cfg_mgr::layout(void) +{ +} + + +void dlg_cfg_mgr::on_init_dlg(void) +{ + HWND lstwnd = get_item(IDC_LIST1); + std::vector schemes; + + cfg_->get_all_schemes(schemes); + dlg_base::list_insert_column(lstwnd, local_trans::lang_trans_between_hz936(CONST_STRING_CFG_NAME).c_str(), 270); + for (size_t i = 1; i < schemes.size(); ++i) // 0 is default scheme + { + dlg_base::list_insert_item(lstwnd, local_trans::a2u(schemes[i].c_str(), CP_UTF8).c_str()); + } +} +void dlg_cfg_mgr::on_paint(HDC hdc) +{ +} +void dlg_cfg_mgr::on_sel_changed(int sel) +{ + std::wstring name(dlg_base::list_get_text(get_item(IDC_LIST1), sel)); + gb::sane_config_schm* schm = cfg_->get_scheme(local_trans::u2a(name.c_str(), CP_UTF8).c_str()); + + name = L""; + if (schm) + { + std::string key(""), val(""); + int cnt = 1; + + if (schm->first_config(key, val)) + { + do + { + std::string v(gb::sane_config_schm::sane_option_value_2_string(&val[0], val.length(), (SANE_Value_Type)cfg_->option_value_type(key.c_str()))); + + name += std::to_wstring(cnt++) + L" - " + local_trans::a2u(cfg_->option_title(key.c_str()).c_str(), CP_UTF8) + L"\r\n "; + if (cfg_->option_value_type(key.c_str()) == SANE_TYPE_STRING) + v = local_trans::u2a(local_trans::lang_trans_between_hz936(local_trans::a2u(v.c_str(), CP_UTF8).c_str()).c_str(), CP_UTF8); + name += local_trans::a2u(v.c_str(), CP_UTF8) + L"\r\n\r\n"; + } while (schm->next_config(key, val)); + } + schm->release(); + } + dlg_base::set_item_text(IDC_EDIT1, name.c_str()); +} +void dlg_cfg_mgr::on_del_selected(void) +{ + std::vector sels; + HWND lwnd = get_item(IDC_LIST1); + bool changed = false; + + dlg_base::list_get_selected_items(lwnd, sels); + for(int i = sels.size() - 1; i >= 0; i--) + { + std::string name(local_trans::u2a(dlg_base::list_get_text(lwnd, sels[i]).c_str(), CP_UTF8)); + if (cfg_->remove_scheme(name.c_str())) + { + changed = true; + ListView_DeleteItem(lwnd, sels[i]); + } + } +} +void dlg_cfg_mgr::on_del_all(void) +{ + cfg_->remove_all_schemes(); +} diff --git a/sane/DlgCfgMgr.h b/sane/DlgCfgMgr.h new file mode 100644 index 0000000..04accf3 --- /dev/null +++ b/sane/DlgCfgMgr.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include "DlgPage.h" + +// CDlgIndicator 对话框 +namespace gb +{ + class scanner_cfg; +} + +class dlg_cfg_mgr: public dlg_base +{ + gb::scanner_cfg* cfg_; + std::wstring label_; + + BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp) override; + void handle_command(WORD code, WORD id, HANDLE ctrl); + void handle_notify(UINT id, LPNMHDR pnhdr); + void layout(void); + + void on_init_dlg(void); + void on_paint(HDC hdc); + void on_sel_changed(int sel); + void on_del_selected(void); + void on_del_all(void); + +public: + dlg_cfg_mgr(gb::scanner_cfg* cfg, HWND parent); + ~dlg_cfg_mgr(); + +public: +}; diff --git a/sane/DlgGamma.cpp b/sane/DlgGamma.cpp index 7695c16..6019e20 100644 --- a/sane/DlgGamma.cpp +++ b/sane/DlgGamma.cpp @@ -5,6 +5,7 @@ #include "resource.h" #include "mem_dc.h" +#include "scanned_img.h" #define MAX_KEY_POINTS 4 // not include (0, 0) and (255, 255) @@ -94,35 +95,35 @@ namespace calc /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // dlg_gamma -dlg_gamma::dlg_gamma(HWND parent, bool color) : dlg_base(parent, IDD_GAMMA), exit_code_(0), is_color_(color), bkgnd_(NULL) +dlg_gamma::dlg_gamma(HWND parent, bool color) : dlg_base(parent, IDD_GAMMA), is_color_(color), bkgnd_(NULL) , show_all_(false) { - std::wstring title(dlg_base::language_from_hz936(L"\u81EA\u5B9A\u4E49\u8272\u8C03\u66F2\u7EBF")); + std::wstring title(local_trans::lang_trans_between_hz936(CONST_STRING_CUSTOM_TONE)); create(); SetWindowTextW(hwnd(), title.c_str()); if (!dlg_base::is_language_pack_default_code_page()) { - title = dlg_base::language_from_hz936(L"\u8272\u8C03\u65B9\u6848"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_TONE_SCHEME); set_item_text(IDC_STATIC_SCHEME, title.c_str()); - title = dlg_base::language_from_hz936(L"\u989C\u8272\u901A\u9053"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_COLOR_CHANNEL); set_item_text(IDC_STATIC_COLOR, title.c_str()); - title = dlg_base::language_from_hz936(L"\u521D\u59CB\u5316"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_INITIALIZE); set_item_text(IDC_BUTTON_RESET, title.c_str()); - title = dlg_base::language_from_hz936(L"\u8F93\u5165"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_INPUT); set_item_text(IDC_STATIC_INPUT, title.c_str()); - title = dlg_base::language_from_hz936(L"\u8F93\u51FA"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_OUTPUT); set_item_text(IDC_STATIC_OUTPUT, title.c_str()); - title = dlg_base::language_from_hz936(L"\u53D6\u6D88"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_CANCEL); set_item_text(IDCANCEL, title.c_str()); - title = dlg_base::language_from_hz936(L"\u786E\u5B9A"); + title = local_trans::lang_trans_between_hz936(CONST_STRING_OK); set_item_text(IDOK, title.c_str()); layout(); @@ -184,7 +185,7 @@ void dlg_gamma::handle_command(WORD code, WORD id, HANDLE ctrl) } else { - exit_code_ = id; + quit_modal(id); } } else if (code == EN_CHANGE) @@ -490,15 +491,15 @@ void dlg_gamma::on_init_dlg(void) init_curve(&green_, RGB(0, 255, 0)); init_curve(&blue_, RGB(0, 0, 255)); - std::wstring lang(dlg_base::language_from_hz936(L"\u81ea\u5b9a\u4e49")); + std::wstring lang(local_trans::lang_trans_between_hz936(CONST_STRING_CUSTOM)); SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); - lang = dlg_base::language_from_hz936(L"\u8d1f\u7247") + L" (RGB)"; + lang = local_trans::lang_trans_between_hz936(CONST_STRING_NEG_PHOTO) + L" (RGB)"; SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); - lang = dlg_base::language_from_hz936(L"\u5f69\u8272\u8d1f\u7247") + L" (RGB)"; + lang = local_trans::lang_trans_between_hz936(CONST_STRING_COLOR_NEG_PHOTO) + L" (RGB)"; SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); - lang = dlg_base::language_from_hz936(L"\u8f83\u6697") + L" (RGB)"; + lang = local_trans::lang_trans_between_hz936(CONST_STRING_DARKER) + L" (RGB)"; SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); - lang = dlg_base::language_from_hz936(L"\u8f83\u4eae") + L" (RGB)"; + lang = local_trans::lang_trans_between_hz936(CONST_STRING_BRIGHTER) + L" (RGB)"; SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); SendMessage(combo, CB_SETCURSEL, 0, 0); @@ -506,16 +507,16 @@ void dlg_gamma::on_init_dlg(void) if (is_color_) { SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"RGB"); - lang = dlg_base::language_from_hz936(L"\u7ea2"); + lang = local_trans::lang_trans_between_hz936(CONST_STRING_RED); SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); - lang = dlg_base::language_from_hz936(L"\u7eff"); + lang = local_trans::lang_trans_between_hz936(CONST_STRING_GREEN); SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); - lang = dlg_base::language_from_hz936(L"\u84dd"); + lang = local_trans::lang_trans_between_hz936(CONST_STRING_BLUE); SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); } else { - lang = dlg_base::language_from_hz936(L"\u7070"); + lang = local_trans::lang_trans_between_hz936(CONST_STRING_GRAY); SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)&lang[0]); } SendMessage(combo, CB_SETCURSEL, 0, 0); @@ -702,43 +703,6 @@ void dlg_gamma::on_combo_sel_changed(int id, int sel) } } -int dlg_gamma::do_modal(HWND parent) -{ - BOOL enable_parent = FALSE, - got = TRUE; - MSG msg = { 0 }; - - if (IsWindow(parent) && parent != GetDesktopWindow()) - { - EnableWindow(parent, FALSE); - enable_parent = TRUE; - } - - ShowWindow(hwnd(), SW_SHOW); - while ((got = GetMessage(&msg, NULL, 0, 0))) - { - if ((DWORD)got == -1) - break; - - //if (enable_parent && msg.hwnd == parent && - // msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST && - // msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) - // continue; - - TranslateMessage(&msg); - DispatchMessage(&msg); - if (exit_code_ == IDOK || exit_code_ == IDCANCEL) - break; - } - ShowWindow(hwnd(), SW_HIDE); - - if (enable_parent) - { - EnableWindow(parent, TRUE); - } - - return exit_code_; -} void dlg_gamma::get_gamma(SANE_Gamma* gamma) { gamma->apply_to_back = SANE_FALSE; @@ -812,7 +776,7 @@ void dlg_gamma::set_gamma(const SANE_Gamma* gamma, bool gray) } else { - text = dlg_base::language_from_hz936(L"\u7070"); + text = local_trans::lang_trans_between_hz936(CONST_STRING_GRAY); SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)&text[0]); } @@ -847,11 +811,11 @@ void dlg_gamma::set_gamma(const SANE_Gamma* gamma, bool gray) cur_->coefs = calc::coefs_from_points(cur_->points); // SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)L"RGB"); - text = dlg_base::language_from_hz936(L"\u7ea2"); + text = local_trans::lang_trans_between_hz936(CONST_STRING_RED); SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)&text[0]); - text = dlg_base::language_from_hz936(L"\u7eff"); + text = local_trans::lang_trans_between_hz936(CONST_STRING_GREEN); SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)&text[0]); - text = dlg_base::language_from_hz936(L"\u84dd"); + text = local_trans::lang_trans_between_hz936(CONST_STRING_BLUE); SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)&text[0]); } cur_ = &rgb_gray_; diff --git a/sane/DlgGamma.h b/sane/DlgGamma.h index e96b096..e18ba4d 100644 --- a/sane/DlgGamma.h +++ b/sane/DlgGamma.h @@ -9,7 +9,6 @@ class dlg_gamma: public dlg_base { - int exit_code_; bool is_color_; bool show_all_; RECT paint_area_; @@ -54,7 +53,6 @@ public: ~dlg_gamma(); public: - int do_modal(HWND parent); void get_gamma(SANE_Gamma* gamma); void set_gamma(const SANE_Gamma* gamma, bool gray); }; diff --git a/sane/DlgIndicator.cpp b/sane/DlgIndicator.cpp index 3ed8745..6df089f 100644 --- a/sane/DlgIndicator.cpp +++ b/sane/DlgIndicator.cpp @@ -20,17 +20,17 @@ dlg_indicator::dlg_indicator(HWND parent) : dlg_base(parent, IDD_INDICATOR) if (!dlg_base::is_language_pack_default_code_page()) { - std::wstring text(dlg_base::language_from_hz936(L"\u6B63\u5728\u626B\u63CF\u2026\u2026")); + std::wstring text(local_trans::lang_trans_between_hz936(CONST_STRING_SCANNING)); SetWindowTextW(hwnd(), text.c_str()); - text = dlg_base::language_from_hz936(L"\u7EB8\u5F20"); + text = local_trans::lang_trans_between_hz936(CONST_STRING_PAPER); set_item_text(IDC_STATIC_PAPER, text.c_str()); - text = dlg_base::language_from_hz936(L"\u56FE\u7247"); + text = local_trans::lang_trans_between_hz936(CONST_STRING_IMAGE); set_item_text(IDC_STATIC_IMAGE, text.c_str()); - text = dlg_base::language_from_hz936(L"\u53D6\u6D88"); + text = local_trans::lang_trans_between_hz936(CONST_STRING_CANCEL); set_item_text(IDCANCEL, text.c_str()); int paper = get_width_diff_as_text_length(IDC_STATIC_PAPER), @@ -122,20 +122,20 @@ BOOL dlg_indicator::handle_message(UINT msg, WPARAM wp, LPARAM lp) else { std::string* str = (std::string*)wp; - std::wstring txt(dlg_base::language_from_hz936(L"\u603b\u8ba1\u626b\u63cf\u56fe\u7247")); + std::wstring txt(local_trans::lang_trans_between_hz936(CONST_STRING_TOTAL_SCANNED)); txt += L": " + std::to_wstring(images_); SetDlgItemTextW(hwnd_, IDC_STATIC_ERR, txt.c_str()); delete str; SetTimer(hwnd_, 1, 3000, NULL); } - SetDlgItemTextW(hwnd_, IDCANCEL, dlg_base::language_from_hz936(L"\u5173\u95ed").c_str()); + SetDlgItemTextW(hwnd_, IDCANCEL, local_trans::lang_trans_between_hz936(CONST_STRING_CLOSE).c_str()); ShowWindow(GetDlgItem(hwnd_, IDC_STATIC_PAPER), SW_HIDE); ShowWindow(GetDlgItem(hwnd_, IDC_STATIC_IMAGE), SW_HIDE); ShowWindow(GetDlgItem(hwnd_, IDC_EDIT_PAPER), SW_HIDE); ShowWindow(GetDlgItem(hwnd_, IDC_EDIT_IMAGE), SW_HIDE); ShowWindow(GetDlgItem(hwnd_, IDC_STATIC_ERR), SW_SHOW); - SetWindowTextW(hwnd_, dlg_base::language_from_hz936(L"\u626b\u63cf\u7ed3\u675f").c_str()); + SetWindowTextW(hwnd_, local_trans::lang_trans_between_hz936(CONST_STRING_SCAN_OVER).c_str()); UpdateWindow(hwnd_); break; case WM_TIMER: @@ -204,17 +204,17 @@ dlg_choose_dev::dlg_choose_dev(HWND parent, const std::map& vals) +{ + no_repeats_ = vals; +} +std::wstring dlg_input::get_value(void) +{ + return val_; +} diff --git a/sane/DlgInput.h b/sane/DlgInput.h new file mode 100644 index 0000000..3b11497 --- /dev/null +++ b/sane/DlgInput.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +#include "DlgPage.h" + +// CDlgIndicator 对话框 + +class dlg_input: public dlg_base +{ + std::vector no_repeats_; + std::wstring val_; + + BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp) override; + void handle_command(WORD code, WORD id, HANDLE ctrl); + + void on_init_dlg(void); + +public: + dlg_input(HWND parent, const wchar_t* init_val); + ~dlg_input(); + +public: + void set_no_repeats(const std::vector& vals); + std::wstring get_value(void); +}; diff --git a/sane/DlgPage.cpp b/sane/DlgPage.cpp index b0b6895..c4229a0 100644 --- a/sane/DlgPage.cpp +++ b/sane/DlgPage.cpp @@ -16,13 +16,6 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -#define FLOAT_FORMAT L"%.2f" -#define IS_STR_EQUAL(s1, s2) (wcscmp(s1, s2) == 0) -#define IS_EDIT(cls) IS_STR_EQUAL(cls, WC_EDITW) -#define IS_COMBOX(cls) IS_STR_EQUAL(cls, WC_COMBOBOXW) -#define IS_BUTTON(cls) IS_STR_EQUAL(cls, WC_BUTTONW) -#define IS_TRACKBAR(cls) IS_STR_EQUAL(cls, TRACKBAR_CLASSW) -#define IS_UPDOWN_ARROW(cls) IS_STR_EQUAL(cls, UPDOWN_CLASSW) static IMPLEMENT_OPTION_STRING_COMPARE(is_sane_opt); @@ -140,13 +133,6 @@ int dlg_base::select_combo_text(HWND combo, const wchar_t* text) return ret; } -std::wstring dlg_base::language_from_hz936(const wchar_t* hz936) -{ - std::string utf8(local_trans::u2a(hz936, CP_UTF8)); - std::wstring lang(local_trans::a2u(from_default_language(utf8.c_str(), nullptr), CP_UTF8)); - - return std::move(lang); -} std::wstring dlg_base::get_wnd_text(HWND h) { int len = GetWindowTextLengthW(h); @@ -164,6 +150,80 @@ bool dlg_base::is_language_pack_default_code_page(void) { return lang_get_cur_code_page() == DEFAULT_CODE_PAGE; } +std::wstring dlg_base::get_menu_text(HMENU menu, int ind) +{ + MENUITEMINFOW mi = { 0 }; + wchar_t text[128] = { 0 }; + + mi.cbSize = sizeof(mi); + mi.fMask = mi.fType = MIIM_STRING; // MFT_STRING; + mi.dwTypeData = text; + mi.cch = _countof(text) - 1; + GetMenuItemInfoW(menu, ind, MF_BYPOSITION, &mi); + + return text; +} +int dlg_base::list_insert_column(HWND list_wnd, const wchar_t* text, int cx, int ind) +{ + LVCOLUMNW col = { 0 }; + + if (ind == -1) + ind = dlg_base::list_get_column_count(list_wnd); + col.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + col.pszText = (LPWSTR)text; + col.iSubItem = 0; + col.cx = cx; + + return ListView_InsertColumn(list_wnd, ind, &col); +} +int dlg_base::list_insert_item(HWND list_wnd, const wchar_t* text, int ind) +{ + LV_ITEMW item = { 0 }; + + if (ind == -1) + ind = dlg_base::list_get_item_count(list_wnd); + item.mask = LVIF_TEXT; + item.pszText = (PWSTR)text; + item.iItem = ind; + + return ListView_InsertItem(list_wnd, &item); +} +int dlg_base::list_get_item_count(HWND list_wnd) +{ + return ListView_GetItemCount(list_wnd); +} +int dlg_base::list_get_column_count(HWND list_wnd) +{ + return ListView_GetItemCount((HWND)ListView_GetHeader(list_wnd)); +} +std::wstring dlg_base::list_get_text(HWND list_wnd, int ind, int sub) +{ + LV_ITEMW item = { 0 }; + wchar_t text[128] = { 0 }; + + item.mask = LVIF_TEXT; + item.pszText = (PWSTR)text; + item.iItem = ind; + item.iSubItem = sub; + item.cchTextMax = _countof(text) - 1; + ListView_GetItem(list_wnd, &item); + + return text; +} +void dlg_base::list_get_selected_items(HWND list_wnd, std::vector& sels) +{ + LV_ITEMW item = { 0 }; + + item.mask = LVIF_STATE; + for (int i = 0; i < dlg_base::list_get_item_count(list_wnd); ++i) + { + item.iItem = i; + item.stateMask = LVIS_SELECTED; + ListView_GetItem(list_wnd, &item); + if (item.state & LVIS_SELECTED) + sels.push_back(i); + } +} BOOL dlg_base::handle_message(UINT msg, WPARAM wp, LPARAM lp) { @@ -183,11 +243,11 @@ void dlg_base::notify_ui_event(int ev) if (ui_event_notify_) ui_event_notify_(ev, this, ui_notify_param_); } -gb::sane_config_schm* dlg_base::get_config(void) +gb::sane_config_schm* dlg_base::get_config(bool* create) { gb::sane_config_schm* cfg = NULL; - SendMessage(parent_, WM_GET_CONFIG_OBJ, 0, (LPARAM)&cfg); + SendMessage(parent_, WM_GET_CONFIG_OBJ, (WPARAM)create, (LPARAM)&cfg); return cfg; } @@ -264,6 +324,49 @@ void dlg_base::show(bool visible, bool hold) } } } +int dlg_base::do_modal(HWND parent) +{ + BOOL enable_parent = FALSE, + got = TRUE; + MSG msg = { 0 }; + + modal_exit_ = 0; + if (IsWindow(parent) && parent != GetDesktopWindow()) + { + EnableWindow(parent, FALSE); + enable_parent = TRUE; + } + + ShowWindow(hwnd(), SW_SHOW); + while ((got = GetMessage(&msg, NULL, 0, 0))) + { + if ((DWORD)got == -1) + break; + + //if (enable_parent && msg.hwnd == parent && + // msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST && + // msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) + // continue; + + TranslateMessage(&msg); + DispatchMessage(&msg); + if (modal_exit_) + break; + } + ShowWindow(hwnd(), SW_HIDE); + + if (enable_parent) + { + EnableWindow(parent, TRUE); + } + + return modal_exit_; +} +void dlg_base::quit_modal(int non_zero_code) +{ + // assert ( non_zero_code ); + modal_exit_ = non_zero_code; +} void dlg_base::enable(bool enable) { EnableWindow(hwnd_, enable); @@ -299,13 +402,16 @@ HFONT dlg_base::get_font(void) { return (HFONT)SendMessage(hwnd_, WM_GETFONT, 0, 0); } -int dlg_base::get_string_width(const wchar_t* str) +int dlg_base::get_string_width(const wchar_t* str, HWND wnd) { - HDC hdc = GetWindowDC(hwnd_); + if (!wnd) + wnd = hwnd_; + + HDC hdc = GetWindowDC(wnd); SIZE size = { 0 }; GetTextExtentPointW(hdc, str, lstrlenW(str), &size); - ReleaseDC(hwnd_, hdc); + ReleaseDC(wnd, hdc); return size.cx; } @@ -351,6 +457,27 @@ bool dlg_base::set_item_text(UINT id, const wchar_t* text) { return SetWindowTextW(GetDlgItem(hwnd_, id), text) == TRUE; } +int dlg_base::set_item_fit_to_text(UINT id) +{ + HWND wnd = get_item(id); + std::wstring text(get_item_text(id)); + RECT r = { 0 }; + int w = get_string_width(text.c_str(), wnd); + + get_item_rect(id, &r, false); + if (w > RECT_W(r) || w <= RECT_W(r) / 2) + { + if (w > RECT_W(r)) + w -= RECT_W(r); + else + w -= RECT_W(r) / 2; + expand_item(id, w, 0); + } + else + w = 0; + + return w; +} void dlg_base::show_scroll_bar(int bar, bool show) { DWORD style = GetWindowLong(hwnd(), GWL_STYLE); @@ -863,7 +990,8 @@ void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl) { SANE_Fixed val = SANE_FIX(dlg.x_in_mm()); SANE_Int after = 0; - gb::sane_config_schm* cfg = get_config(); + bool created = true; + gb::sane_config_schm* cfg = get_config(&created); sane_.sane_control_option_api(dev_, id_custom_left_, SANE_ACTION_SET_VALUE, &val, &after); if (cfg) @@ -882,7 +1010,10 @@ void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl) val = SANE_FIX(dlg.y_in_mm() + dlg.h_in_mm()); sane_.sane_control_option_api(dev_, id_custom_bottom_, SANE_ACTION_SET_VALUE, &val, &after); if (cfg) + { cfg->config_changed(id_custom_bottom_, (char*)&val, sizeof(val)); + cfg->release(); + } } return; } @@ -891,6 +1022,7 @@ void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl) dlg_gamma dlg(parent_, true); SANE_Gamma gamma = { 0 }; unsigned int len = sizeof(gamma); + bool created = true; sane_.sane_io_control_api(dev_, IO_CTRL_CODE_GET_CUSTOM_GAMMA, &gamma, &len); dlg.set_gamma(&gamma, len < 2); @@ -900,9 +1032,12 @@ void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl) dlg.get_gamma(&gamma); sane_.sane_io_control_api(dev_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &gamma, &len); - gb::sane_config_schm* cfg = get_config(); + gb::sane_config_schm* cfg = get_config(&created); if (cfg) + { cfg->config_changed(id_custom_gamma_, (char*)&gamma, sizeof(gamma), true); + cfg->release(); + } } return; @@ -1149,7 +1284,8 @@ void dlg_page::control_action(HWND wnd) SANE_Int after = 0; std::string to_v(hg_sane_middleware::option_value_2_string(type, val)); SANE_Status statu = sane_.sane_control_option_api(dev_, id - dlg_page::dyn_id_base, SANE_ACTION_SET_VALUE, val, &after); - gb::sane_config_schm* cfg = get_config(); + bool created = true; + gb::sane_config_schm* cfg = get_config(&created); done_ = false; if (cfg) { @@ -1181,14 +1317,15 @@ void dlg_page::control_action(HWND wnd) else cfg->config_changed(id - dlg_page::dyn_id_base, (char*)val, len); } + cfg->release(); } if (statu == SANE_STATUS_INVAL) { - std::wstring attr(dlg_base::language_from_hz936(L"\u6B64\u8BBE\u5907\u4E0D\u652F\u6301\u5C06") + L" \"" + std::wstring attr(local_trans::lang_trans_between_hz936(CONST_STRING_NOT_SUPPORT_SET) + L" \"" + local_trans::a2u(sane_.sane_get_option_descriptor_api(dev_, id - dlg_page::dyn_id_base)->title, CP_UTF8) - + L"\" " + dlg_base::language_from_hz936(L"\u8BBE\u7F6E\u4E3A") + L": "), + + L"\" " + local_trans::lang_trans_between_hz936(CONST_STRING_SET_TO_BE) + L": "), attr_v(local_trans::a2u(to_v.c_str(), CP_UTF8)); - MessageBoxW(hwnd(), (attr + attr_v).c_str(), dlg_base::language_from_hz936(L"\u53C2\u6570\u9519\u8BEF").c_str(), MB_OK); + MessageBoxW(hwnd(), (attr + attr_v).c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_PARAMETER_ERROR).c_str(), MB_OK); set_ctrl_value(wnd, type, val, true); } else @@ -1196,11 +1333,11 @@ void dlg_page::control_action(HWND wnd) std::string tov(hg_sane_middleware::option_value_2_string(type, val)); if (tov != to_v) { - std::wstring attr(dlg_base::language_from_hz936(L"\u539F\u53C2\u6570") + L" \"" + std::wstring attr(local_trans::lang_trans_between_hz936(CONST_STRING_PARAMETER_ORIGIN) + L" \"" + local_trans::a2u(to_v.c_str(), CP_UTF8) + L"\" " - + dlg_base::language_from_hz936(L"\u4E0D\u7CBE\u786E\u6216\u8BBE\u5907\u4E0D\u652F\u6301\uFF0C\u5DF2\u8C03\u6574\u4E3A")), + + local_trans::lang_trans_between_hz936(CONST_STRING_PARAMETER_INEXACT)), attr_v(local_trans::a2u(tov.c_str(), CP_UTF8)); - MessageBoxW(hwnd(), (attr + attr_v).c_str(), dlg_base::language_from_hz936(L"\u53C2\u6570\u8C03\u6574").c_str(), MB_OK); + MessageBoxW(hwnd(), (attr + attr_v).c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_PARAMETER_ADJUSTED).c_str(), MB_OK); } set_ctrl_value(wnd, type, val, false, !(after || statu)); } @@ -1389,7 +1526,7 @@ bool dlg_page::add_control(int sn, const SANE_Option_Descriptor* desc, void* cur // custom area ... int w = 69; HWND host = wnd; - std::wstring t(dlg_base::language_from_hz936(L"\u8bbe\u7f6e\u533a\u57df")); + std::wstring t(local_trans::lang_trans_between_hz936(CONST_STRING_SET_AREA)); id_custom_area_ = sn; wnd = CreateWindowW(WC_BUTTONW, t.c_str(), WS_CHILD | WS_VISIBLE, pos_.x + text.cx, pos_.y - 1, w, text.cy + 3, hwnd(), NULL, g_my_inst, NULL); @@ -1418,7 +1555,7 @@ bool dlg_page::add_control(int sn, const SANE_Option_Descriptor* desc, void* cur // custom gamma control ... int w = 78; HWND host = wnd; - std::wstring t(dlg_base::language_from_hz936(L"\u8bbe\u7f6e\u8272\u8c03\u66f2\u7ebf")); + std::wstring t(local_trans::lang_trans_between_hz936(CONST_STRING_SET_TONE)); id_custom_gamma_ = sn; wnd = CreateWindowW(WC_BUTTONW, t.c_str(), WS_CHILD | WS_VISIBLE, pos_.x + text.cx, pos_.y - 1, w, text.cy + 3, hwnd(), NULL, g_my_inst, NULL); diff --git a/sane/DlgPage.h b/sane/DlgPage.h index d9bd119..b32eaed 100644 --- a/sane/DlgPage.h +++ b/sane/DlgPage.h @@ -6,17 +6,26 @@ #include #include #include +#include "const_str.h" // CDlgIndicator 对话框 -#define RECT_W(r) (r.right - r.left) -#define RECT_H(r) (r.bottom - r.top) +#define FLOAT_FORMAT L"%.2f" +#define IS_STR_EQUAL(s1, s2) (wcscmp(s1, s2) == 0) +#define IS_EDIT(cls) IS_STR_EQUAL(cls, WC_EDITW) +#define IS_COMBOX(cls) IS_STR_EQUAL(cls, WC_COMBOBOXW) +#define IS_BUTTON(cls) IS_STR_EQUAL(cls, WC_BUTTONW) +#define IS_TRACKBAR(cls) IS_STR_EQUAL(cls, TRACKBAR_CLASSW) +#define IS_UPDOWN_ARROW(cls) IS_STR_EQUAL(cls, UPDOWN_CLASSW) + +#define RECT_W(r) (r.right - r.left) +#define RECT_H(r) (r.bottom - r.top) #define WM_SCAN_WORKING WM_USER + 301 // WPARAM: unused; LPARAM: unsed #define WM_USB_PACKET_RECEIVED WM_USER + 302 #define WM_IMAGE_RECEIVED WM_USER + 303 #define WM_SCAN_FINISHED WM_USER + 304 // WPARAM: std::string* msg; LPARAM: boo err #define WM_REFRESH_OPTION WM_USER + 311 // WPARAM: source option SN, LPARAM: unused now -#define WM_GET_CONFIG_OBJ WM_USER + 312 // WPARAM: not use, LPARAM: to receive the gb::sane_config* object +#define WM_GET_CONFIG_OBJ WM_USER + 312 // WPARAM: bool*, [in]create new if NULL; [out]created, LPARAM: to receive the gb::sane_config* object extern HMODULE g_my_inst; @@ -27,6 +36,8 @@ namespace gb class dlg_base { + int modal_exit_; // set non-ZERO code to exit modal dialog + protected: HWND hwnd_; HWND parent_; @@ -41,7 +52,7 @@ protected: virtual void on_font_changed(void); void create(void); void notify_ui_event(int ev); - gb::sane_config_schm* get_config(void); + gb::sane_config_schm* get_config(bool* create); public: dlg_base(HWND parent, UINT idd); @@ -52,27 +63,37 @@ public: static bool get_max_size(SIZE& dst, const SIZE& src); // return whether changed dst static bool get_max_size(SIZE& dst, int cx, int cy); // return whether changed dst static int select_combo_text(HWND combo, const wchar_t* text); - static std::wstring language_from_hz936(const wchar_t* hz936); static std::wstring get_wnd_text(HWND h); static bool is_language_pack_default_code_page(void); + static std::wstring get_menu_text(HMENU menu, int ind); + + static int list_insert_column(HWND list_wnd, const wchar_t* text, int cx = 20, int ind = -1); + static int list_insert_item(HWND list_wnd, const wchar_t* text, int ind = -1); + static int list_get_item_count(HWND list_wnd); + static int list_get_column_count(HWND list_wnd); + static std::wstring list_get_text(HWND list_wnd, int ind, int sub = 0); + static void list_get_selected_items(HWND list_wnd, std::vector& sels); public: void set_ui_event_notify(void(__stdcall* notify)(int, void*, void*), void* param); HWND hwnd(void); void show(bool visible, bool hold = false); + int do_modal(HWND parent); + void quit_modal(int non_zero_code); void enable(bool enable); void screen_2_client(LPRECT r); void client_2_screen(LPRECT r); HWND get_item(UINT id); BOOL set_font(HFONT font); HFONT get_font(void); - int get_string_width(const wchar_t* str); + int get_string_width(const wchar_t* str, HWND wnd = NULL); bool get_item_rect(UINT id, LPRECT r, bool client = true); std::wstring get_item_text(UINT id); int get_width_diff_as_text_length(UINT id); // void offset_item(UINT id, int dx, int dy); void expand_item(UINT id, int dx, int dy); bool set_item_text(UINT id, const wchar_t* text); + int set_item_fit_to_text(UINT id); // return difference void show_scroll_bar(int bar = SB_VERT, bool show = true); bool track_mouse_hover(void); }; diff --git a/sane/DlgSetting.cpp b/sane/DlgSetting.cpp index ba76acb..645574d 100644 --- a/sane/DlgSetting.cpp +++ b/sane/DlgSetting.cpp @@ -10,7 +10,10 @@ #include "../../sdk/include/lang/app_language.h" // CDlgIndicator 对话框 +#include "DlgCfgMgr.h" +#include "DlgInput.h" +#define MENU_CMD_0 ((unsigned short)0x8888) static IMPLEMENT_OPTION_STRING_COMPARE(cmp_sane_opt); @@ -19,10 +22,13 @@ dlg_setting::dlg_setting(HWND parent, LPSANEAPI api, SANE_Handle dev, bool with_ , sane_api_(*api), sane_dev_(dev), with_scan_(with_scan) , papers_(0), images_(0), err_(false), tab_(NULL), cfg_(NULL), cfg_file_(L"") { - std::wstring setting(local_trans::a2u(from_default_language("\350\256\276\347\275\256", nullptr), CP_UTF8)); + std::wstring setting(local_trans::lang_trans_between_hz936(CONST_STRING_SETTING)); create(); SetWindowTextW(hwnd(), (std::wstring(name) + L" " + setting).c_str()); + cfg_menu_ = CreatePopupMenu(); + InsertMenuW(cfg_menu_, 0, MF_BYPOSITION, MENU_CMD_0, local_trans::lang_trans_between_hz936(CONST_STRING_SAVE_CUR_CFG_AS).c_str()); + InsertMenuA(cfg_menu_, 1, MF_BYPOSITION | MF_SEPARATOR, MENU_CMD_0 + 1, ""); } dlg_setting::~dlg_setting() { @@ -39,7 +45,15 @@ dlg_setting::~dlg_setting() } DestroyWindow(tab_); } - cfg_->end_setting(false); + + gb::sane_config_schm* schm = cfg_->get_scheme(); + if (schm) + { + schm->end_setting(false); + schm->release(); + } + cfg_->save(local_trans::u2a(cfg_file_.c_str()).c_str()); + DestroyMenu(cfg_menu_); } BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp) @@ -62,7 +76,19 @@ BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp) refresh_controls((int)wp); break; case WM_GET_CONFIG_OBJ: - *((gb::sane_config_schm**)lp) = cfg_; + { + gb::sane_config_schm* schm = cfg_->get_scheme(); + if (wp) + { + if (!schm && *(bool*)wp) + { + schm = cfg_->create_empty_scheme(true); + } + else + *(bool*)wp = false; + } + *((gb::sane_config_schm**)lp) = schm; + } break; default: ret = FALSE; @@ -73,11 +99,70 @@ BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp) } void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) { - if (id == IDOK) + if (ctrl == NULL) { - if (cfg_) - cfg_->save_to(NULL); + // menu command ... + if (id == MENU_CMD_0) + { + // save current scheme as ... + gb::sane_config_schm* s = cfg_->get_scheme(); + if (!s) + s = cfg_->copy_scheme(nullptr); + if (s) + { + std::vector all; + std::vector allw; + std::wstring cur(local_trans::a2u(s->get_scheme_name().c_str(), CP_UTF8)); + dlg_input dlg(hwnd(), cur.c_str()); + + cfg_->get_all_schemes(all); + for (auto& v : all) + allw.push_back(local_trans::a2u(v.c_str(), CP_UTF8)); + dlg.set_no_repeats(allw); + if (dlg.do_modal(hwnd()) == IDOK) + { + std::string name(local_trans::u2a(dlg.get_value().c_str(), CP_UTF8)); + gb::sane_config_schm* n = s->copy(); + if (cfg_->add_scheme(n, name.c_str())) + { + cfg_->select_scheme(name.c_str()); + } + n->release(); + } + s->release(); + } + } + else if(id > MENU_CMD_0 + 1) + { + // config scheme changed ... + std::string schm(local_trans::u2a(dlg_base::get_menu_text(cfg_menu_, id - MENU_CMD_0).c_str(), CP_UTF8)); + + if (cfg_->get_current_scheme_name() != schm) + { + gb::sane_config_schm* s = cfg_->get_scheme(); + if (s) + { + s->end_setting(true); + s->release(); + } + + if (cfg_->select_scheme(schm.c_str())) + { + s = cfg_->get_scheme(); + apply_scheme_(s, apply_param_); + if (s) + { + s->release(); + } + refresh_controls(-1); + // cfg_->save(); + } + } + } + } + else if (id == IDOK) + { notify_over(); } else if (id == IDC_BUTTON_HELP) @@ -92,9 +177,13 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) refresh_controls(id_restore_); if (cfg_) { - cfg_->begin_setting(true); - cfg_->end_setting(false); - cfg_->begin_setting(); + gb::sane_config_schm* schm = cfg_->get_scheme(); + if (schm) + { + schm->end_setting(true); + schm->release(); + } + cfg_->select_scheme(nullptr); } } else if (id == IDC_BUTTON_SCAN) @@ -102,6 +191,33 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) // enable(false); notify_ui_event(SANE_EVENT_UI_SCAN_COMMAND); } + else if (id == IDC_BUTTON_CONFIG_MGR) + { + dlg_cfg_mgr dlg(cfg_, hwnd()); + dlg.do_modal(hwnd()); + } + else if (id == IDC_BUTTON_CONFIG_MENU) + { + HMENU sub = cfg_menu_; // GetSubMenu(cfg_menu_, 0); + int ind = 2; + std::vector schemes; + + while (DeleteMenu(sub, 2, MF_BYPOSITION)); + cfg_->get_all_schemes(schemes); + for (auto& v : schemes) + { + UINT flag = MF_BYPOSITION; + + if (v == cfg_->get_current_scheme_name()) + flag |= MF_CHECKED; + InsertMenuW(sub, ind, flag, MENU_CMD_0 + ind, local_trans::a2u(v.c_str(), CP_UTF8).c_str()); + ind++; + } + + RECT r = { 0 }; + GetWindowRect(get_item(IDC_BUTTON_CONFIG_MENU), &r); + TrackPopupMenu(cfg_menu_, TPM_LEFTALIGN | TPM_BOTTOMALIGN, r.left, r.top, 0, hwnd(), NULL); + } } void dlg_setting::notify_over(void) { @@ -197,35 +313,32 @@ void dlg_setting::on_init_dialog(void) page->set_view_size(size); } - GetWindowRect(get_item(IDC_BUTTON_SCAN), &r); - OffsetRect(&r, 0, size.cy); - screen_2_client(&r); - MoveWindow(get_item(IDC_BUTTON_SCAN), r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE); + offset_item(IDC_BUTTON_SCAN, 0, size.cy); + offset_item(IDC_BUTTON_CONFIG_MGR, size.cx - RECT_W(rme), size.cy); + offset_item(IDC_BUTTON_CONFIG_MENU, size.cx - RECT_W(rme), size.cy); + offset_item(IDC_BUTTON_HELP, size.cx - RECT_W(rme), size.cy); + offset_item(IDC_BUTTON_RESTORE, size.cx - RECT_W(rme), size.cy); + offset_item(IDOK, size.cx - RECT_W(rme), size.cy); - GetWindowRect(get_item(IDC_BUTTON_HELP), &r); - OffsetRect(&r, size.cx - (rme.right - rme.left), size.cy); - screen_2_client(&r); - MoveWindow(get_item(IDC_BUTTON_HELP), r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE); - - GetWindowRect(get_item(IDC_BUTTON_RESTORE), &r); - OffsetRect(&r, size.cx - (rme.right - rme.left), size.cy); - screen_2_client(&r); - MoveWindow(get_item(IDC_BUTTON_RESTORE), r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE); - - GetWindowRect(get_item(IDOK), &r); - OffsetRect(&r, size.cx - (rme.right - rme.left), size.cy); - screen_2_client(&r); - MoveWindow(get_item(IDOK), r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE); + ShowWindow(get_item(IDC_BUTTON_CONFIG_MGR), SW_SHOW); + ShowWindow(get_item(IDC_BUTTON_CONFIG_MENU), SW_SHOW); } if (with_scan_) ShowWindow(get_item(IDC_BUTTON_SCAN), SW_SHOW); if (!dlg_base::is_language_pack_default_code_page()) { - ::SetDlgItemTextW(hwnd(), IDC_BUTTON_SCAN, dlg_base::language_from_hz936(L"\u626B\u63CF").c_str()); - ::SetDlgItemTextW(hwnd(), IDC_BUTTON_RESTORE, dlg_base::language_from_hz936(L"\u6062\u590D\u9ED8\u8BA4\u503C").c_str()); - ::SetDlgItemTextW(hwnd(), IDC_BUTTON_HELP, dlg_base::language_from_hz936(L"\u5E2E\u52A9").c_str()); - ::SetDlgItemTextW(hwnd(), IDOK, dlg_base::language_from_hz936(L"\u786E\u5B9A").c_str()); + std::wstring title(local_trans::lang_trans_between_hz936(CONST_STRING_CFG_MANAGER)); + + ::SetDlgItemTextW(hwnd(), IDC_BUTTON_CONFIG_MGR, title.c_str()); + y = set_item_fit_to_text(IDC_BUTTON_CONFIG_MGR); + if (y) + offset_item(IDC_BUTTON_CONFIG_MGR, -y, 0); + + ::SetDlgItemTextW(hwnd(), IDC_BUTTON_SCAN, local_trans::lang_trans_between_hz936(CONST_STRING_SCAN).c_str()); + ::SetDlgItemTextW(hwnd(), IDC_BUTTON_RESTORE, local_trans::lang_trans_between_hz936(CONST_STRING_RESTORE).c_str()); + ::SetDlgItemTextW(hwnd(), IDC_BUTTON_HELP, local_trans::lang_trans_between_hz936(CONST_STRING_HELP).c_str()); + ::SetDlgItemTextW(hwnd(), IDOK, local_trans::lang_trans_between_hz936(CONST_STRING_OK).c_str()); } select_page(0); @@ -363,10 +476,12 @@ void dlg_setting::refresh_controls(int src_sn) } } -void dlg_setting::set_config(gb::sane_config_schm* cfg, const wchar_t* file) +void dlg_setting::set_config(gb::scanner_cfg* cfg, const wchar_t* file, void(__stdcall* apply)(gb::sane_config_schm*, void*), void* param) { cfg_ = cfg; cfg_file_ = file; + apply_scheme_ = apply; + apply_param_ = param; } HWND dlg_setting::window(void) { diff --git a/sane/DlgSetting.h b/sane/DlgSetting.h index efc005f..f37d944 100644 --- a/sane/DlgSetting.h +++ b/sane/DlgSetting.h @@ -17,7 +17,7 @@ namespace gb { - class sane_config_schm; + class scanner_cfg; } class dlg_setting : public dlg_base { @@ -29,8 +29,12 @@ class dlg_setting : public dlg_base bool err_; int id_help_; int id_restore_; - gb::sane_config_schm* cfg_; - std::wstring cfg_file_; + gb::scanner_cfg *cfg_; + std::wstring cfg_file_; + + HMENU cfg_menu_; + void(__stdcall* apply_scheme_)(gb::sane_config_schm*, void*); + void* apply_param_; HWND tab_; @@ -55,7 +59,7 @@ public: ~dlg_setting(); public: - void set_config(gb::sane_config_schm* cfg, const wchar_t* file); + void set_config(gb::scanner_cfg* cfg, const wchar_t* file, void(__stdcall* apply)(gb::sane_config_schm*, void*), void* param); HWND window(void); HWND parent(void); //void show(void); diff --git a/sane/const_str.h b/sane/const_str.h new file mode 100644 index 0000000..21f9f2e --- /dev/null +++ b/sane/const_str.h @@ -0,0 +1,85 @@ +// For: const string list +// +// Date: 2023-02-07 +// +// Format: all strings are defined in unicode +// + +#pragma once + +#define CONST_STRING_CUSTOM_AREA L"\u81EA\u5B9A\u4E49\u626B\u63CF\u533A\u57DF" +#define CONST_STRING_UNIT L"\u5355\u4F4D" +#define CONST_STRING_UNIT_MM L"\u6BEB\u7C73" +#define CONST_STRING_UNIT_INCH L"\u82F1\u5BF8" +#define CONST_STRING_UNIT_PIXEL L"\u50CF\u7D20" +#define CONST_STRING_AREA_SET L"\u533A\u57DF\u8BBE\u7F6E" +#define CONST_STRING_LEFT L"\u5DE6" +#define CONST_STRING_TOP L"\u4E0A" +#define CONST_STRING_WIDTH L"\u5BBD" +#define CONST_STRING_HEIGHT L"\u9AD8" +#define CONST_STRING_RESTORE_AREA L"\u6062\u590D\u533A\u57DF" +#define CONST_STRING_OK L"\u786E\u5B9A" +#define CONST_STRING_CANCEL L"\u53D6\u6D88" +#define CONST_STRING_MULTIPLE L"\u00d7" +#define CONST_STRING_OPT_PAPER L"\u7EB8\u5F20\u5C3A\u5BF8" + +#define CONST_STRING_CFG_MANAGER L"\u914D\u7F6E\u7BA1\u7406" +#define CONST_STRING_CFG_SCHEME L"\u914D\u7F6E\u65B9\u6848" +#define CONST_STRING_DEL_SELECTED L"\u5220\u9664\u9009\u4E2D\u9879" +#define CONST_STRING_DEL_ALL L"\u5168\u90E8\u5220\u9664" +#define CONST_STRING_CFG_CONTENT L"\u914D\u7F6E\u5185\u5BB9" +#define CONST_STRING_CFG_NAME L"\u914D\u7F6E\u540D\u79F0" + +#define CONST_STRING_CUSTOM_TONE L"\u81EA\u5B9A\u4E49\u8272\u8C03\u66F2\u7EBF" +#define CONST_STRING_TONE_SCHEME L"\u8272\u8C03\u65B9\u6848" +#define CONST_STRING_COLOR_CHANNEL L"\u989C\u8272\u901A\u9053" +#define CONST_STRING_INITIALIZE L"\u521D\u59CB\u5316" +#define CONST_STRING_INPUT L"\u8F93\u5165" +#define CONST_STRING_OUTPUT L"\u8F93\u51FA" +#define CONST_STRING_CUSTOM L"\u81EA\u5B9A\u4E49" +#define CONST_STRING_NEG_PHOTO L"\u8d1f\u7247" +#define CONST_STRING_COLOR_NEG_PHOTO L"\u5f69\u8272\u8d1f\u7247" +#define CONST_STRING_DARKER L"\u8f83\u6697" +#define CONST_STRING_BRIGHTER L"\u8f83\u4eae" +#define CONST_STRING_RED L"\u7ea2" +#define CONST_STRING_GREEN L"\u7eff" +#define CONST_STRING_BLUE L"\u84dd" +#define CONST_STRING_GRAY L"\u7070" + +#define CONST_STRING_SCANNING L"\u6B63\u5728\u626B\u63CF\u2026\u2026" +#define CONST_STRING_PAPER L"\u7EB8\u5F20" +#define CONST_STRING_IMAGE L"\u56FE\u7247" +#define CONST_STRING_TOTAL_SCANNED L"\u603b\u8ba1\u626b\u63cf\u56fe\u7247" +#define CONST_STRING_CLOSE L"\u5173\u95ed" +#define CONST_STRING_SCAN_OVER L"\u626b\u63cf\u7ed3\u675f" + +#define CONST_STRING_CHOOSE_DEVICE L"\u8BF7\u9009\u62E9\u8BBE\u5907" +#define CONST_STRING_DEVICE_NAME L"\u8BBE\u5907\u540D\u79F0" +#define CONST_STRING_SERIAL_NUM L"\u5E8F\u5217\u53F7" + +#define CONST_STRING_INPUT_VAL L"\u8BF7\u8F93\u5165\u65B0\u503C" +#define CONST_STRING_RE_INPUT L"\u8BF7\u91CD\u65B0\u8F93\u5165" +#define CONST_STRING_NO_INPUT L"\u6CA1\u6709\u8F93\u5165\u5185\u5BB9" +#define CONST_STRING_ALREADY_EXISTS L"\u5DF2\u7ECF\u5B58\u5728" + +#define CONST_STRING_NOT_SUPPORT_SET L"\u6B64\u8BBE\u5907\u4E0D\u652F\u6301\u5C06" +#define CONST_STRING_SET_TO_BE L"\u8BBE\u7F6E\u4E3A" +#define CONST_STRING_PARAMETER_ERROR L"\u53C2\u6570\u9519\u8BEF" +#define CONST_STRING_PARAMETER_ORIGIN L"\u539F\u53C2\u6570" +#define CONST_STRING_PARAMETER_INEXACT L"\u4E0D\u7CBE\u786E\u6216\u8BBE\u5907\u4E0D\u652F\u6301\uFF0C\u5DF2\u8C03\u6574\u4E3A" +#define CONST_STRING_PARAMETER_ADJUSTED L"\u53C2\u6570\u8C03\u6574" +#define CONST_STRING_SET_AREA L"\u8bbe\u7f6e\u533a\u57df" +#define CONST_STRING_SET_TONE L"\u8bbe\u7f6e\u8272\u8c03\u66f2\u7ebf" + +#define CONST_STRING_SETTING L"\u8BBE\u7F6E" +#define CONST_STRING_SAVE_CUR_CFG_AS L"\u5F53\u524D\u914D\u7F6E\u53E6\u5B58\u4E3A" +#define CONST_STRING_SCAN L"\u626B\u63CF" +#define CONST_STRING_RESTORE L"\u6062\u590D\u9ED8\u8BA4\u503C" +#define CONST_STRING_HELP L"\u5E2E\u52A9" + + + +#define CONST_STRING_OPEN_FAILED L"\u6253\u5F00\u5931\u8D25" +#define CONST_STRING_START_FAILED L"\u542F\u52A8\u5931\u8D25" +#define CONST_STRING_ERROR L"\u9519\u8BEF" + diff --git a/sane/gb_json.cpp b/sane/gb_json.cpp index 78bcedb..0964150 100644 --- a/sane/gb_json.cpp +++ b/sane/gb_json.cpp @@ -4,12 +4,89 @@ #include #include "../../sdk/include/huagao/brand.h" +#include "../../sdk/include/sane/sane_ex.h" #if defined(WIN32) || defined(_WIN64) #define bzero(b, s) memset(b, 0, s) #endif +namespace special_char_trans +{ + struct + { + const char* writedown_text; + char readable_char; + }transferred_chars[] = { { "\\\"", '\"' } + , { "\\'", '\'' } + , { "\\a", '\a' } + , { "\\b", '\b' } + , { "\\f", '\f' } + , { "\\n", '\n' } + , { "\\r", '\r' } + , { "\\t", '\t' } + , { "\\v", '\v' } + // , { "\\?", '\?' } + , { "\\\\", '\\' } + , { "\\/", '/' } + // , { "\\0", '\0' } + }; + + void to_writedown(std::string& str) + { + std::string trans(str); + const char* ptr = trans.c_str(); + + str.clear(); + while (*ptr) + { + bool rep = false; + if (*ptr == '\\') + { + if (ptr[1] == '\\') + { + str += "\\\\"; + ptr++; + rep = true; + } + else if (ptr[1] == '/' || + ptr[1] == 'a' || + ptr[1] == 'b' || + ptr[1] == 'f' || + ptr[1] == 'n' || + ptr[1] == 'r' || + ptr[1] == 't' || + ptr[1] == 'u' || + ptr[1] == 'v') + { + str += "\\"; + ptr++; + } + else + { + str += "\\\\"; + rep = true; + } + } + else + { + for (size_t i = 0; i < sizeof(transferred_chars) / sizeof(transferred_chars[0]); ++i) + { + if (*ptr == transferred_chars[i].readable_char) + { + str += transferred_chars[i].writedown_text; + rep = true; + break; + } + } + } + if (!rep) + str.append(1, *ptr); + ptr++; + } + } +} + namespace gb { static std::vector split_with(const char* str, const char* splitor = "/") @@ -82,597 +159,723 @@ namespace gb } - json::json(char* json_txt) : obj_(0), cur_child_(0), is_array_(false) + json::json(char* json_txt) : type_(VAL_TYPE_OBJECT), key_(""), strval_(""), cur_child_(-1) { - memset(&walk_head_, 0, sizeof(walk_head_)); - attach_text(json_txt); + simple_val_.dval = .0f; + if (json_txt) + attach_text(json_txt); + } + json::json(const char* key, bool val) : type_(VAL_TYPE_BOOL), key_(key ? key : ""), strval_(""), cur_child_(-1) + { + simple_val_.bval = val; + } + json::json(const char* key, int val) : type_(VAL_TYPE_INT), key_(key ? key : ""), strval_(""), cur_child_(-1) + { + simple_val_.nval = val; + } + json::json(const char* key, double val) : type_(VAL_TYPE_FLOAT), key_(key ? key : ""), strval_(""), cur_child_(-1) + { + simple_val_.dval = val; + } + json::json(const char* key, const char* val) : type_(VAL_TYPE_STRING), key_(key ? key : ""), strval_(val ? val : ""), cur_child_(-1) + {} + json::json(json& r) + { + copy_from(r); } json::~json() { - memset(&walk_head_, 0, sizeof(walk_head_)); clear(); } - std::string json::to_string(cJSON* root, bool formatted) + std::string json::object_key(json* jsn) { - char* txt = formatted ? cJSON_Print(root) : cJSON_PrintUnformatted(root); - std::string ret(txt ? txt : ""); - - if (txt) - free(txt); - - return ret; + return "\"" + jsn->key() + "\":"; } - std::string json::get_value_as_string(cJSON* root, bool integer) + std::string json::array_key(json* jsn) { - std::string ret(""); + return ""; + } - switch (root->type) + void json::from_cjson(cJSON* cj) + { + key_ = cj && cj->string ? cj->string : ""; + while (cj) { - case cJSON_False: - ret = "false"; - break; - case cJSON_True: - ret = "true"; - break; - case cJSON_NULL: - ret = "null"; - break; - case cJSON_Number: - { - char buf[40]; - if (integer) - sprintf(buf, "%d", root->valueint); - else - sprintf(buf, "%f", root->valuedouble); - ret = buf; + json* child = nullptr; + if (cj->type == cJSON_True) + { + child = new json(cj->string, true); + } + else if (cj->type == cJSON_False) + { + child = new json(cj->string, false); + } + else if (cj->type == cJSON_Number) + { + if (cj->valuedouble - (int)cj->valuedouble < .00001) + { + child = new json(cj->string, cj->valueint); + } + else + { + child = new json(cj->string, cj->valuedouble); + } + } + else if (cj->type == cJSON_String) + { + child = new json(cj->string, cj->valuestring); + } + else if (cj->type == cJSON_Object || cj->type == cJSON_Array) + { + child = new json(); + child->from_cjson(cj->child); + child->key_ = cj->string ? cj->string : ""; + } + arr_val_.push_back(child); + cj = cj->next; } - break; - case cJSON_String: - if (root->valuestring) - ret = root->valuestring; - break; - default: - ret = json::to_string(root, false); - break; + + if (arr_val_.size() == 1 && arr_val_[0]->arr_val_.size() == 0) + { + json* child = arr_val_[0]; + + if (!child->key_.empty()) // array + { + arr_val_.clear(); + type_ = child->type_; + key_ = child->key_; + simple_val_.dval = child->simple_val_.dval; + strval_ = child->strval_; + for (auto& v : child->arr_val_) + arr_val_.push_back(v); + child->arr_val_.clear(); + child->release(); + } + } + + if (arr_val_.size()) + { + type_ = arr_val_[0]->key().empty() ? VAL_TYPE_ARRAY : VAL_TYPE_OBJECT; + } + } + json* json::find_child(const char* key, bool remove) + { + json* ret = nullptr; + + if (type_ == VAL_TYPE_OBJECT) + { + for (size_t i = 0; i < arr_val_.size(); ++i) + { + if (arr_val_[i]->key() == key) + { + ret = arr_val_[i]; + if (remove) + arr_val_.erase(arr_val_.begin() + i); + else + ret->add_ref(); + + break; + } + } } return ret; } - void json::free_node_data(cJSON* node) + + void json::copy_from(json& r) { - if (node->type == cJSON_String && node->valuestring) - free(node->valuestring); - else if((node->type == cJSON_Object || node->type == cJSON_Array) && node->child) - cJSON_Delete(node->child); + clear(); - node->type = cJSON_NULL; - node->valuestring = NULL; - node->child = NULL; + type_ = r.type_; + key_ = r.key_; + simple_val_.dval = r.simple_val_.dval; + strval_ = r.strval_; + for (auto& v : r.arr_val_) + arr_val_.push_back(new json(*v)); } - cJSON* json::create_element(bool is_array) - { - cJSON* obj = is_array ? cJSON_CreateArray() : cJSON_CreateObject(); - - // bzero(obj, sizeof(*obj)); // cleared in constructor already ! - - return obj; - } - cJSON* json::create_element_with_name(const char* name) - { - cJSON* obj = json::create_element(); - - if(name) - { - obj->string = (char*)malloc(strlen(name) + 4); - bzero(obj->string, strlen(name) + 4); - strcpy(obj->string, name); - } - - return obj; - } - - cJSON* json::find_sibling(cJSON* first, const char* name, cJSON*** prev) - { - cJSON* now = first, **prv = NULL; - while(now) - { - if(now->string && strcmp(now->string, name) == 0) - { - break; - } - prv = &now->next; - now = now->next; - } - if(prev) - *prev = prv; - - return now; - } - cJSON* json::find_child(cJSON *parent, std::vector& path, bool create, cJSON*** addr) - { - if(!parent->child) - { - if(!create) - return NULL; - - parent->child = json::create_element_with_name(path[0].c_str()); - if(path.size() == 1) - { - if(addr) - *addr = &parent->child; - - return parent->child; - } - } - - cJSON** prev = NULL, - *now = find_sibling(parent->child, path[0].c_str(), &prev); - if(!now) - { - if(!create) - return now; - - now = json::create_element_with_name(path[0].c_str()); - if (prev) - { - cJSON* pr = (cJSON*)((DWORD_PTR)prev - (DWORD_PTR)&((cJSON*)0)->next); - pr->next = now; - now->prev = pr; - // *prev = now; - } - else - { - obj_->child = now; - prev = &obj_->child; - } - } - - path.erase(path.begin()); - if(path.empty()) - { - if(addr) - *addr = prev ? prev : &parent->child; - - return now; - } - - return find_child(now, path, create, addr); - } - cJSON* json::find(const char* path, bool create, cJSON*** addr) - { - std::vector tree(split_with(path)); - - if(tree.empty()) - return NULL; - - if(!obj_) - { - if(!create) - return NULL; - - obj_ = json::create_element(); - obj_->child = json::create_element_with_name(tree[0].c_str()); - } - - return find_child(obj_, tree, create, addr); - } - bool json::attach_text(char* json_txt) { clear(); - obj_ = cJSON_Parse(json_txt); - if(obj_) - is_array_ = obj_->type == cJSON_Array; - - return obj_ != 0; - } - bool json::attach_cjson(cJSON* cjson) - { - clear(); - - if (cjson) + cJSON* jsn = cJSON_Parse(json_txt); + if (jsn) { - std::string txt(json::to_string(cjson, false)); - if (txt.length()) - obj_ = cJSON_Parse(txt.c_str()); - } - if(obj_) - is_array_ = obj_->type == cJSON_Array; + char* text = cJSON_Print(jsn); + if (text) + free(text); - return obj_ != 0; - } - bool json::create_empty(bool array) - { - clear(); - - obj_ = json::create_element(array); - is_array_ = array; - - return true; - } - void json::clear(void) - { - if (obj_) - { - cJSON_Delete(obj_); - obj_ = 0; - } - } - std::string json::to_string(bool formatted) - { - if (obj_) - return json::to_string(obj_, formatted); - else - return ""; - } - - bool json::get_value(const char* key, bool& val) - { - cJSON* obj = find(key); - - if (!obj) - return false; - - if (obj->type == cJSON_True) - val = true; - else if (obj->type == cJSON_False) - val = false; - else - return false; - - return true; - } - bool json::get_value(const char* key, int& val) - { - cJSON* obj = find(key); - - if (!obj) - return false; - - if (obj->type != cJSON_Number) - return false; - - val = obj->valueint; - - return true; - } - bool json::get_value(const char* key, double& val) - { - cJSON *obj = find(key); - - if (!obj) - return false; - - if (obj->type != cJSON_Number) - return false; - - val = obj->valuedouble; - - return true; - } - bool json::get_value(const char* key, std::string& val) - { - cJSON *obj = find(key); - - if (!obj) - return false; - - if (obj->type != cJSON_String) - return false; - - val = obj->valuestring ? obj->valuestring : ""; - - return true; - } - bool json::get_value(const char* key, json*& val) - { - cJSON *obj = find(key); - - if (!obj) - return false; - - val = new json(); - if (!val->attach_cjson(obj)) - { - val->release(); - - return false; - } - - return true; - } - bool json::get_value_as_string(const char* key, std::string& val, bool integer) - { - cJSON* obj = find(key); - - if (!obj) - return false; - - val = json::get_value_as_string(obj, integer); - - return true; - } - bool json::get_as_array(const char* key, std::vector& val) - { - cJSON *obj = find(key); - - val.clear(); - if (obj && obj->type == cJSON_Array) - { - cJSON *child = obj->child; - while (child) - { - if (child->type == cJSON_Number) - { - char buf[40]; - sprintf(buf, "%d", child->valueint); - val.push_back(buf); - } - else if (child->type == cJSON_String) - val.push_back(child->valuestring ? child->valuestring : ""); - else - { - char *text = cJSON_Print(child); - val.push_back(text); - free(text); - } - - child = child->next; - } + from_cjson(jsn->child); + cJSON_Delete(jsn); return true; } return false; } - - bool json::first_child(std::string& val, std::string* name) + void json::clear(bool as_array) { - cur_child_ = obj_->child; - val = ""; - if (cur_child_) + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) { - val = json::get_value_as_string(cur_child_); - if (name && cur_child_->string) - *name = cur_child_->string; - - return true; - } - else - { - return false; + for (auto& v : arr_val_) + v->release(); } + type_ = as_array ? VAL_TYPE_ARRAY : VAL_TYPE_OBJECT; + simple_val_.dval = .0f; + key_ = ""; + strval_ = ""; + arr_val_.clear(); + cur_child_ = -1; } - bool json::next_child(std::string& val, std::string* name) + std::string json::to_string(void) { - if (cur_child_) - cur_child_ = cur_child_->next; - - val = ""; - if (cur_child_) + if (type_ == VAL_TYPE_NULL) + return ""; + if (type_ == VAL_TYPE_BOOL) + return (simple_val_.bval ? "true" : "false"); + if (type_ == VAL_TYPE_INT) + return std::to_string(simple_val_.nval); + if (type_ == VAL_TYPE_FLOAT) + return std::to_string(simple_val_.dval); + if (type_ == VAL_TYPE_STRING) { - val = json::get_value_as_string(cur_child_); - if (name && cur_child_->string) - *name = cur_child_->string; + char* u = cJSON_utf8_2_unic(strval_.c_str()); + std::string r(u); - return true; + free(u); + special_char_trans::to_writedown(r); + + return "\"" + r + "\""; } + + std::string(*k)(json*) = type_ == VAL_TYPE_OBJECT ? json::object_key : json::array_key; + std::string str(type_ == VAL_TYPE_OBJECT ? "{" : "["); + + if (arr_val_.size()) + { + str += k(arr_val_[0]) + arr_val_[0]->to_string(); + for (size_t i = 1; i < arr_val_.size(); ++i) + str += "," + k(arr_val_[i]) + arr_val_[i]->to_string(); + } + str += type_ == VAL_TYPE_OBJECT ? "}" : "]"; + + return str; + } + + std::string& json::key(void) + { + return key_; + } + bool json::is_array(void) + { + return type_ == VAL_TYPE_ARRAY; + } + bool json::is_leaf_node(void) + { + return type_ == VAL_TYPE_BOOL || + type_ == VAL_TYPE_INT || + type_ == VAL_TYPE_FLOAT || + type_ == VAL_TYPE_STRING; + } + + bool json::get_value(const char* key, bool& val) + { + bool ret = false; + json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_BOOL) + { + val = child->simple_val_.bval; + ret = true; + } + child->release(); + } + else if (type_ == VAL_TYPE_BOOL && key_ == key) + { + val = simple_val_.bval; + ret = true; + } + + return ret; + } + bool json::get_value(const char* key, int& val) + { + bool ret = false; + json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_INT) + { + val = child->simple_val_.nval; + ret = true; + } + child->release(); + } + else if (type_ == VAL_TYPE_INT && key_ == key) + { + val = simple_val_.nval; + ret = true; + } + + return ret; + } + bool json::get_value(const char* key, double& val) + { + bool ret = false; + json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_FLOAT) + { + val = child->simple_val_.dval; + ret = true; + } + child->release(); + } + else if (type_ == VAL_TYPE_FLOAT && key_ == key) + { + val = simple_val_.dval; + ret = true; + } + + return ret; + } + bool json::get_value(const char* key, std::string& val) + { + bool ret = false; + json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_STRING) + { + val = child->strval_; + ret = true; + } + child->release(); + } + else if (type_ == VAL_TYPE_STRING && key_ == key) + { + val = strval_; + ret = true; + } + + return ret; + } + bool json::get_value(const char* key, json*& val) + { + bool ret = false; + json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_OBJECT) + { + val = child; + ret = true; + } + else + { + child->release(); + } + } + + return ret; + } + + size_t json::children(void) + { + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + return arr_val_.size(); else + return -1; + } + json* json::child(size_t ind) + { + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) { - return false; + if (ind >= 0 && ind < arr_val_.size()) + { + arr_val_[ind]->add_ref(); + + return arr_val_[ind]; + } } + + return nullptr; + } + json* json::first_child(void) + { + if (type_ == VAL_TYPE_OBJECT || type_ == VAL_TYPE_ARRAY) + { + cur_child_ = 0; + if (arr_val_.size()) + { + arr_val_[0]->add_ref(); + + return arr_val_[0]; + } + } + + return nullptr; + } + json* json::next_child(void) + { + if (type_ == VAL_TYPE_OBJECT || type_ == VAL_TYPE_ARRAY) + { + if (++cur_child_ < arr_val_.size()) + { + arr_val_[cur_child_]->add_ref(); + + return arr_val_[cur_child_]; + } + } + + return nullptr; } bool json::set_value(const char* key, bool val) { - if(!key) - { - if(is_array_) - { - if(!obj_) - obj_ = json::create_element(true); - cJSON_AddItemToArray(obj_, val ? cJSON_CreateTrue() : cJSON_CreateFalse()); - } - - return is_array_; - } - - cJSON* ele = this->find(key, true); - - if (!ele) + if (type_ != VAL_TYPE_OBJECT) return false; - json::free_node_data(ele); + json* child = find_child(key); - if (val) - ele->type = cJSON_True; + if (child) + { + child->clear(); + child->type_ = VAL_TYPE_BOOL; + child->key() = key ? key : ""; + child->simple_val_.bval = val; + child->release(); + } else - ele->type = cJSON_False; + { + child = new json(key, val); + arr_val_.push_back(child); + } return true; } bool json::set_value(const char* key, int val) { - if(!key) - { - if(is_array_) - { - if(!obj_) - obj_ = json::create_element(true); - cJSON_AddItemToArray(obj_, cJSON_CreateNumber(val)); - } - - return is_array_; - } - - cJSON* ele = this->find(key, true); - - if (!ele) + if (type_ != VAL_TYPE_OBJECT) return false; - json::free_node_data(ele); + json* child = find_child(key); - ele->type = cJSON_Number; - ele->valuedouble = ele->valueint = val; + if (child) + { + child->clear(); + child->type_ = VAL_TYPE_INT; + child->key() = key ? key : ""; + child->simple_val_.nval = val; + child->release(); + } + else + { + child = new json(key, val); + arr_val_.push_back(child); + } return true; } bool json::set_value(const char* key, double val) { - if(!key) - { - if(is_array_) - { - if(!obj_) - obj_ = json::create_element(true); - cJSON_AddItemToArray(obj_, cJSON_CreateNumber(val)); - } - - return is_array_; - } - - cJSON* ele = this->find(key, true); - - if (!ele) + if (type_ != VAL_TYPE_OBJECT) return false; - json::free_node_data(ele); + json* child = find_child(key); - ele->type = cJSON_Number; - ele->valuedouble = val; - - return true; - } - bool json::set_value(const char* key, std::string val) - { - if(!key) + if (child) { - if(is_array_) - { - if(!obj_) - obj_ = json::create_element(true); - cJSON_AddItemToArray(obj_, cJSON_CreateString(val.c_str())); - } - - return is_array_; + child->clear(); + child->type_ = VAL_TYPE_FLOAT; + child->key() = key ? key : ""; + child->simple_val_.dval = val; + child->release(); + } + else + { + child = new json(key, val); + arr_val_.push_back(child); } - - cJSON* ele = this->find(key, true); - - if (!ele) - return false; - - json::free_node_data(ele); - - ele->type = cJSON_String; - ele->valuestring = (char*)malloc(val.length() + 4); - bzero(ele->valuestring, val.length() + 4); - strcpy(ele->valuestring, val.c_str()); return true; } bool json::set_value(const char* key, const char* val) { - return set_value(key, std::string(val)); - } - bool json::set_value(const char* key, json* obj) - { - if(!key) + if (type_ != VAL_TYPE_OBJECT) + return false; + + json* child = find_child(key); + + if (child) { - if(is_array_) + child->clear(); + child->type_ = VAL_TYPE_STRING; + child->key() = key ? key : ""; + child->strval_ = val ? val : ""; + child->release(); + } + else + { + child = new json(key, val); + arr_val_.push_back(child); + } + + return true; + } + bool json::set_value(const char* key, json* val) + { + if (type_ != VAL_TYPE_OBJECT) + return false; + + for (size_t i = 0; i < arr_val_.size(); ++i) + { + if (arr_val_[i]->key() == key) { - if(!obj_) - obj_ = json::create_element(true); - if(obj && obj->obj_) - { - cJSON_AddItemToArray(obj_, obj->obj_); - obj->obj_ = NULL; - } + arr_val_[i]->release(); + arr_val_[i] = val; + val->add_ref(); + return true; } - - return is_array_; } - cJSON** addr = NULL; - cJSON* ele = this->find(key, true, &addr); - - if (!ele) - return false; - -// json::free_node_data(ele); - cJSON_Delete(ele); - *addr = obj->obj_; - ele = obj->obj_; - if(ele->string) - free(ele->string); - ele->string = (char*)malloc(strlen(key) + 4); - bzero(ele->string, strlen(key) + 4); - strcpy(ele->string, key); - obj->obj_ = NULL; + arr_val_.push_back(val); + val->key() = key; + val->add_ref(); return true; } - bool json::change_key(const char* old_key, const char* new_key) + json& json::operator+=(bool val) { - if (!obj_ || !new_key || *new_key == 0 || !old_key || *old_key == 0) - return false; - - cJSON** addr = NULL, - *ele = find(old_key, false, &addr); - - if (!ele) - return false; - - if (strlen(ele->string) < strlen(new_key)) + if (type_ == VAL_TYPE_ARRAY) { - int l = strlen(new_key) + 4; - free(ele->string); - ele->string = (char*)malloc(l); - memset(ele->string, 0, l); + json* child = new json(nullptr, val); + arr_val_.push_back(child); } - strcpy(ele->string, new_key); - return true; + return *this; + } + json& json::operator+=(int val) + { + if (type_ == VAL_TYPE_ARRAY) + { + json* child = new json(nullptr, val); + arr_val_.push_back(child); + } + + return *this; + } + json& json::operator+=(double val) + { + if (type_ == VAL_TYPE_ARRAY) + { + json* child = new json(nullptr, val); + arr_val_.push_back(child); + } + + return *this; + } + json& json::operator+=(const char* val) + { + if (type_ == VAL_TYPE_ARRAY) + { + json* child = new json(nullptr, val); + arr_val_.push_back(child); + } + + return *this; + } + json& json::operator+=(json* val) + { + if (type_ == VAL_TYPE_ARRAY) + { + val->add_ref(); + arr_val_.push_back(val); + } + + return *this; + } + + json& json::operator-=(int ind) + { + remove(ind); + + return *this; } bool json::remove(const char* key) { - if(!obj_) - return false; + json* child = find_child(key, true); - cJSON **addr = NULL, - *ele = find(key, false, &addr); - - if(ele) + if (child) { - bool cur_child = cur_child_ == obj_->child; - - if(addr) - *addr = ele->next; - if (cur_child_ == ele) - { - if (cur_child) - { - walk_head_.next = obj_->child; - cur_child_ = &walk_head_; - } - else - cur_child_ = ele->prev; - } - if (ele->prev) - ele->prev->next = ele->next; - if (ele->next) - ele->next->prev = ele->prev; - ele->prev = NULL; - ele->next = NULL; - cJSON_Delete(ele); - + child->release(); return true; } else + { return false; + } + } + bool json::remove(json* child) + { + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + { + for (size_t i = 0; i < arr_val_.size(); ++i) + { + if (arr_val_[i] == child) + { + arr_val_[i]->release(); + arr_val_.erase(arr_val_.begin() + i); + + return true; + } + } + } + + return false; + } + bool json::remove(int ind) + { + bool ret = false; + + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + { + if (ind >= 0 && ind < arr_val_.size()) + { + arr_val_[ind]->release(); + arr_val_.erase(arr_val_.begin() + ind); + ret = true; + } + } + + return ret; + } + + int json::index(json* child) + { + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + { + for (int i = 0; i < arr_val_.size(); ++i) + { + if (arr_val_[i] == child) + return i; + } + } + + return -1; + } + int json::index_move_to(json* child, int ind) + { + int i = index(child); + + if (i == -1) + return -1; + + arr_val_.erase(arr_val_.begin() + i); + if (ind < 0) + ind = 0; + if (ind > arr_val_.size()) + ind = arr_val_.size(); + arr_val_.insert(arr_val_.begin() + ind, child); + + return ind; + } + + bool json::value(bool& val) + { + bool ret = false; + + if (is_leaf_node() && type_ == VAL_TYPE_BOOL) + { + val = simple_val_.bval; + ret = true; + } + + return ret; + } + bool json::value(int& val) + { + bool ret = false; + + if (is_leaf_node() && type_ == VAL_TYPE_INT) + { + val = simple_val_.nval; + ret = true; + } + + return ret; + } + bool json::value(double& val) + { + bool ret = false; + + if (is_leaf_node() && type_ == VAL_TYPE_FLOAT) + { + val = simple_val_.dval; + ret = true; + } + + return ret; + } + bool json::value(std::string& val) + { + bool ret = false; + + if (is_leaf_node() && type_ == VAL_TYPE_STRING) + { + val = strval_; + ret = true; + } + + return ret; + } + json& json::operator=(bool val) + { + if (is_leaf_node()) + { + simple_val_.bval = val; + type_ = VAL_TYPE_BOOL; + } + + return *this; + } + json& json::operator=(int val) + { + if (is_leaf_node()) + { + simple_val_.nval = val; + type_ = VAL_TYPE_INT; + } + + return *this; + } + json& json::operator=(double val) + { + if (is_leaf_node()) + { + simple_val_.dval = val; + type_ = VAL_TYPE_FLOAT; + } + + return *this; + } + json& json::operator=(const char* val) + { + if (is_leaf_node()) + { + strval_ = val ? val : ""; + type_ = VAL_TYPE_STRING; + } + + return *this; } } @@ -822,7 +1025,7 @@ namespace gb } free(str); - return ret; + return std::move(ret); } std::string base64::decode(const char* data, size_t bytes) { @@ -875,7 +1078,7 @@ namespace gb } free(str); - return ret; + return std::move(ret); } } @@ -956,125 +1159,28 @@ namespace updater return model; } - static int update_app_config(const char* scanner_name, const char* jsn_txt, const char* path, gb::scanner_cfg::LPUDF lpfunc) - { - std::string scanner(""), jsn_str(jsn_txt); - std::vector efiles; - - if ((unsigned char)scanner_name[0] > 0x7f) - scanner = scanner_chinese_name_2_model(scanner_name); - else - scanner = scanner_name; - - gb::json* jsn = new gb::json(); - int cur_sel = -1, ret = 0; - gb::scanner_cfg* cfg = nullptr; - if (!jsn->attach_text(&jsn_str[0])) - { - jsn->release(); - return EINVAL; - } - - if (jsn->first_child(jsn_str)) - { - gb::json* child = new gb::json(); - if (child->attach_text(&jsn_str[0])) - { - if (!child->get_value("cur_sel", cur_sel)) - ret = EINVAL; - } - if (ret == 0) - { - cfg = new gb::scanner_cfg(); - int ind = 0; - while (jsn->next_child(jsn_str)) - { - if (!child->attach_text(&jsn_str[0])) - { - ret = EINVAL; - break; - } - - std::string schm_name(""); - if (!child->get_value("scheme", schm_name)) - { - ret = EINVAL; - break; - } - - gb::json* items = nullptr; - if (!child->get_value("opts", items) || !items) - { - ret = EINVAL; - break; - } - - gb::sane_config_schm* schm = new gb::sane_config_schm(); - if (items->first_child(jsn_str)) - { - do - { - std::string name(""), val(""); - gb::json* item = new gb::json(); - if (item->attach_text(&jsn_str[0])) - { - if (item->get_value("name", name) && item->get_value("value", val)) - { - name = lpfunc->title2name(name.c_str(), lpfunc->func_param); - lpfunc->trans_number(name.c_str(), val, lpfunc->func_param); - schm->set_value(name.c_str(), val.c_str(), val.length()); - - val = ""; - item->get_value("extra", val); - if (val.length() && gb::load_mini_file(val.c_str(), val) == 0) - { - schm->set_value(name.c_str(), val.c_str(), val.length(), true); - item->get_value("extra", val); - efiles.push_back(val); - } - } - } - item->release(); - } while (items->next_child(jsn_str)); - } - items->release(); - - cfg->add_scheme(schm, schm_name.c_str()); - schm->release(); - if (ind++ == cur_sel) - cfg->select_scheme(schm_name.c_str()); - } - } - child->release(); - } - jsn->release(); - if (cfg) - { - if (ret == 0) - { - cfg->save((path + scanner + ".cfg").c_str()); - for (auto& v : efiles) - rename(v.c_str(), (v + "_bk").c_str()); - } - cfg->release(); - } - - return ret; - } } namespace gb { std::string sane_config_schm::opt_data_appendix_("_data"); + std::string sane_config_schm::opt_def_id_appendix_("_id"); + std::string sane_config_schm::opt_def_val_appendix_("_val"); + std::string sane_config_schm::opt_def_type_appendix_("_type"); + std::string sane_config_schm::opt_def_title_appendix_("_title"); - sane_config_schm::sane_config_schm(scanner_cfg* scanner) : jsn_(NULL), bkp_(NULL), in_setting_(false), scheme_name_("") + sane_config_schm::sane_config_schm(scanner_cfg* scanner) : jsn_(nullptr), bkp_(nullptr), in_setting_(false), scheme_name_("") , scanner_(scanner) { char empty[8] = { "{}" }; jsn_ = new gb::json(); jsn_->attach_text(empty); - def_val_ = new gb::json(); if (scanner_) + { scanner_->add_ref(); + def_val_ = scanner_->get_option_default_value(); + } + else + def_val_ = new gb::json(); } sane_config_schm::~sane_config_schm() { @@ -1124,33 +1230,6 @@ namespace gb return ret; } - bool sane_config_schm::is_option_data(std::string& name) - { - size_t pos = name.find(sane_config_schm::opt_data_appendix_); - - if (pos != std::string::npos) - { - if (pos + sane_config_schm::opt_data_appendix_.length() == name.length()) - { - name.erase(pos); - - return true; - } - } - - return false; - } - - void sane_config_schm::clear() - { - if (jsn_) - jsn_->release(); - jsn_ = NULL; - if (bkp_) - bkp_->release(); - bkp_ = NULL; - // file_ = ""; - } std::string sane_config_schm::to_hex_letter(const char* data, size_t bytes) { std::string hex(""); @@ -1181,26 +1260,105 @@ namespace gb return stream; } - std::string sane_config_schm::default_value(const char* hex_title) + bool sane_config_schm::is_option_data(std::string& name) + { + size_t pos = name.find(sane_config_schm::opt_data_appendix_); + + if (pos != std::string::npos) + { + if (pos + sane_config_schm::opt_data_appendix_.length() == name.length()) + { + name.erase(pos); + + return true; + } + } + + return false; + } + void sane_config_schm::set_default_value(json* jsn, int id, const char* name, const char* title, void* data, size_t bytes, int type) + { + std::string key(name); + + jsn->set_value(std::to_string(id).c_str(), name); + jsn->set_value((name + sane_config_schm::opt_def_id_appendix_).c_str(), id); + jsn->set_value((name + sane_config_schm::opt_def_val_appendix_).c_str(), sane_config_schm::to_hex_letter((const char*)data, bytes).c_str()); + jsn->set_value((name + sane_config_schm::opt_def_type_appendix_).c_str(), type); + jsn->set_value((name + sane_config_schm::opt_def_title_appendix_).c_str(), title); + } + int sane_config_schm::option_name_2_id(json* jsn, const char* name) + { + int id = -1; + + return jsn->get_value((std::string(name) + sane_config_schm::opt_def_id_appendix_).c_str(), id) ? id : -1; + } + int sane_config_schm::option_type(json* jsn, const char* name) + { + int id = -1; + + return jsn->get_value((std::string(name) + sane_config_schm::opt_def_type_appendix_).c_str(), id) ? id : -1; + } + std::string sane_config_schm::option_title(json* jsn, const char* name) + { + std::string title(""); + + jsn->get_value((std::string(name) + sane_config_schm::opt_def_title_appendix_).c_str(), title); + + return std::move(title); + } + std::string sane_config_schm::option_default_value(json* jsn, const char* name) { std::string val(""); - def_val_->get_value(hex_title, val); + return jsn->get_value((std::string(name) + sane_config_schm::opt_def_val_appendix_).c_str(), val) ? std::move(val) : ""; + } + std::string sane_config_schm::sane_option_value_2_string(void* val, size_t bytes, int type) + { + char buf[80] = { 0 }; - return val; + switch (type) + { + case SANE_TYPE_BOOL: + return *((SANE_Bool*)val) == SANE_TRUE ? "true" : "false"; + break; + case SANE_TYPE_INT: + return std::to_string(*(SANE_Int*)val); + break; + case SANE_TYPE_FIXED: + sprintf_s(buf, _countof(buf) - 1, "%f", SANE_UNFIX(*(SANE_Fixed*)val)); + break; + case SANE_TYPE_STRING: + return std::string((char*)val, bytes); + } + + return buf; + } + + void sane_config_schm::clear() + { + if (jsn_) + jsn_->release(); + jsn_ = nullptr; + if (bkp_) + bkp_->release(); + bkp_ = nullptr; + } + std::string sane_config_schm::default_value(const char* hex_title) + { + return sane_config_schm::option_default_value(def_val_, hex_title); } sane_config_schm* sane_config_schm::copy(void) { sane_config_schm *cp = new sane_config_schm(scanner_); - std::string val(jsn_->to_string(false)); cp->scheme_name_ = scheme_name_; cp->file_ = file_; - cp->jsn_->attach_text(&val[0]); - cp->id_name_ = id_name_; - val = def_val_->to_string(false); - cp->def_val_->attach_text(&val[0]); + if(jsn_) + cp->jsn_->copy_from(*jsn_); + cp->def_val_->release(); + cp->def_val_ = def_val_; + def_val_->add_ref(); return cp; } @@ -1255,28 +1413,20 @@ namespace gb return ret; } - void sane_config_schm::set_default_value(int sn, const char* name, const char* val, size_t bytes) + void sane_config_schm::set_default_value(int sn, const char* name, const char* title, const char* val, size_t bytes, int type) { - id_name_[sn] = name; - def_val_->set_value(name, to_hex_letter(val, bytes).c_str()); - } - void sane_config_schm::copy_default_value(sane_config_schm* from) - { - if(from) - { - std::string t(from->def_val_->to_string(false)); - - id_name_ = from->id_name_; - def_val_->attach_text(&t[0]); - } + sane_config_schm::set_default_value(def_val_, sn, name, title, (void*)val, bytes, type); } bool sane_config_schm::first_config(std::string& name, std::string& val) { bool ret = false; + json* child = nullptr; std::string raw_v(""); - if (jsn_ && jsn_->first_child(raw_v, &name)) + if (jsn_ && (child = jsn_->first_child())) { + name = child->key(); + child->value(raw_v); val = sane_config_schm::from_hex_letter(raw_v.c_str(), raw_v.length()); ret = true; @@ -1287,10 +1437,13 @@ namespace gb bool sane_config_schm::next_config(std::string& name, std::string& val) { bool ret = false; + json* child = nullptr; std::string raw_v(""); - if (jsn_ && jsn_->next_child(raw_v, &name)) + if (jsn_ && (child = jsn_->next_child())) { + name = child->key(); + child->value(raw_v); val = sane_config_schm::from_hex_letter(raw_v.c_str(), raw_v.length()); ret = true; @@ -1319,9 +1472,7 @@ namespace gb jsn_ = new gb::json(); if (!restore && bkp_) { - std::string stream(bkp_->to_string(false)); - if(stream.length()) - jsn_->attach_text(&stream[0]); + jsn_->copy_from(*bkp_); } } void sane_config_schm::config_changed(const char* name, const char* val, size_t bytes, bool extra) @@ -1348,9 +1499,9 @@ namespace gb { std::string name(""); - if (id_name_.count(sn)) + def_val_->get_value(std::to_string(sn).c_str(), name); + if (!name.empty()) { - name = id_name_[sn]; config_changed(name.c_str(), val, bytes, extra); } } @@ -1368,32 +1519,47 @@ namespace gb else jsn_->set_value(name, hex_v.c_str()); } - bool sane_config_schm::has_changed(void) + bool sane_config_schm::has_changed(int* items) { + if(items) + *items = jsn_ ? jsn_->children() : 0; + if(!bkp_) return false; std::map old; std::string n(""), v(""); - if(bkp_->first_child(v, &n)) + json* child = nullptr; + if((child = bkp_->first_child())) { do { - old[n] = v; - }while(bkp_->next_child(v, &n)); + child->value(v); + old[child->key()] = std::move(v); + child->release(); + }while((child = bkp_->next_child())); } - if(jsn_->first_child(v, &n)) + if((child = jsn_->first_child())) { do { + n = child->key(); if(old.count(n) == 0) + { + child->release(); return true; + } + child->value(v); if(old[n]!=v) + { + child->release(); return true; + } + child->release(); old.erase(n); - }while(jsn_->next_child(v, &n)); + } while ((child = jsn_->next_child())); } return old.size() > 0; @@ -1406,25 +1572,19 @@ namespace gb { jsn_->release(); jsn_ = bkp_; - bkp_ = NULL; + bkp_ = nullptr; } else if (bkp_) { bkp_->release(); - bkp_ = NULL; + bkp_ = nullptr; } } in_setting_ = false; } int sane_config_schm::id_from_name(const char* name) { - for (const auto& v : id_name_) - { - if (v.second == name) - return v.first; - } - - return -1; + return sane_config_schm::option_name_2_id(def_val_, name); } std::string sane_config_schm::to_text_stream(bool b64, bool with_ver) { @@ -1437,7 +1597,7 @@ namespace gb jsn_->set_value("ver", ver); } - std::string cont(jsn_->to_string(false)); + std::string cont(jsn_->to_string()); if (b64) { gb::base64 b64; @@ -1467,71 +1627,60 @@ namespace gb { scheme_name_ = name ? name : ""; } - void sane_config_schm::update(bool(* is_float)(int, void*), void* param, const char* (* t2n)(const char*), std::string* discard) + + std::string sane_config_schm::auto_gen_scheme_name(const char* (__stdcall* lang_trans)(const char*, bool/*true - default language to cur language*/, void*), void* param) { - if (!jsn_) - return; + std::string name(""), old(std::move(scheme_name_)), key(""), val(""), add(""); + int cnt = 0; - std::string ver(get_version()), - name(""), - val(""); - int mv = atoi(ver.c_str()), - sv = ver.find("."); - bool changed = false; - char vs[40] = { 0 }; - - if (sv++ != -1) - sv = atoi(ver.c_str() + sv); - - // change title to name ... - if (mv <= 4 && sv < 30) + if (first_config(key, val)) { - if (jsn_->first_child(val, &name)) + do { - changed = true; - do - { - jsn_->change_key(name.c_str(), t2n(sane_config_schm::from_hex_letter(name.c_str(), name.length()).c_str())); - } while (jsn_->next_child(val, &name)); - } - } + if (cnt++ > 3) + break; - // fix float does not convert to SANE_Fixed bug in eldest version .... (discard them) - if (ver.empty()) + SANE_Value_Type type = (SANE_Value_Type)sane_config_schm::option_type(def_val_, key.c_str()); + if (type == SANE_TYPE_STRING) + name += add + lang_trans(val.c_str(), true, param); + else + name += add + sane_config_schm::option_title(def_val_, key.c_str()) + "(" + sane_config_schm::sane_option_value_2_string(&val[0], val.length(), type) + ")"; + add = "+"; + } while (next_config(key, val)); + } + + if (name.empty()) + name = lang_trans(scanner_cfg::default_setting_name_.c_str(), true, param); + + cnt = 0; + if (scanner_) { - if (jsn_->first_child(val, &name)) + sane_config_schm* cfg = scanner_->get_scheme(name.c_str()); + while (cfg) { - do - { - int id = id_from_name(name.c_str()); - if (id == -1 || is_float(id, param)) - { - jsn_->remove(name.c_str()); - if (discard) - *discard += name + "\r\n"; - changed = true; - } - } while (jsn_->next_child(val, &name)); + cfg->release(); + cfg = scanner_->get_scheme((name + "(" + std::to_string(++cnt) + ")").c_str()); } + if (cnt) + name += "(" + std::to_string(++cnt) + ")"; } - sprintf(vs, "%u.%u", VERSION_MAIN, VERSION_SUB); - jsn_->set_value("ver", vs); + scheme_name_ = name; - if (changed) - save_to(NULL); + return std::move(name); } - /////////////////////////////////////////////////////////////////////////////////// // scanner_cfg std::string scanner_cfg::global_name_ = "global"; std::string scanner_cfg::cur_sel_ = "cur"; - std::string scanner_cfg::default_setting_name_ = "\351\273\230\350\256\244\350\256\276\347\275\256"; // utf-8: 默认设置 + std::string scanner_cfg::default_setting_name_ = "\xE9\xBB\x98\xE8\xAE\xA4\xE8\xAE\xBE\xE7\xBD\xAE"; // utf-8: 默认设置 - scanner_cfg::scanner_cfg() : path_(""), scanner_name_(""), global_(new json()) + scanner_cfg::scanner_cfg() : path_(""), scanner_name_(""), global_(new json()), lang_trans_(scanner_cfg::language_trans), lang_param_(nullptr) { + opt_default_value_ = new json(); + init_version(); init_select(); } @@ -1543,41 +1692,12 @@ namespace gb bool scanner_cfg::update(const char* file, LPUDF func) { - std::string cont(""), name(""), path(file); - int ret = gb::load_mini_file(file, cont); - base64 b64; - json *jsn = nullptr; - bool ok = true; + return false; + } - if (ret) - return false; - else if (cont.empty()) - return true; - - cont = b64.decode(cont.c_str(), cont.length()); - jsn = new json(); - if (!jsn->attach_text(&cont[0])) - { - jsn->release(); - return false; - } - - cont = ""; - ret = path.rfind(PATH_SYMBOL[0]); - if (ret++ != std::string::npos) - path.erase(ret); - if (jsn->first_child(cont, &name)) - { - do - { - ok &= updater::update_app_config(name.c_str(), cont.c_str(), path.c_str(), func) == 0; - } while (jsn->next_child(cont, &name)); - } - jsn->release(); - if (ok) - rename(file, (std::string(file) + "_bk").c_str()); - - return true; + const char* __stdcall scanner_cfg::language_trans(const char* in, bool from_def, void* param) + { + return in; } void scanner_cfg::clear(void) @@ -1601,37 +1721,9 @@ namespace gb { global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); } - void scanner_cfg::walk_sibling_schemes(cJSON* first) + const char* scanner_cfg::trans_language(const char* in, bool from_default) { - if (!first) - return; - - cJSON* next = first->next; - std::string name(first->string ? first->string : ""), - cont(""); - CFGSCHM sch; - - first->next = nullptr; - cont = json::to_string(first, false); - if (name == scanner_cfg::global_name_) - { - global_->attach_text(&cont[0]); - } - else - { - sch.schm = new sane_config_schm(); - if (sch.schm->load_from_mem(cont.c_str(), false)) - { - sch.name = sane_config_schm::from_hex_letter(name.c_str(), name.length()); - sch.schm->set_scheme_name(sch.name.c_str()); - schemes_.push_back(sch); - } - else - sch.schm->release(); - } - - first->next = next; - walk_sibling_schemes(next); + return lang_trans_(in, from_default, lang_param_); } int scanner_cfg::load_file(const char* file) @@ -1639,10 +1731,7 @@ namespace gb std::string cont(""); int ret = gb::load_mini_file(file, cont); - if (ret == 0) - ret = load_mem(cont.c_str()); - - // if (ret == 0 && scanner_name_.empty()) + if (ret == 0) { const char* name = strrchr(file, PATH_SYMBOL[0]); if (name++ == nullptr) @@ -1654,28 +1743,56 @@ namespace gb ret = scanner_name_.rfind('.'); if (ret != std::string::npos) scanner_name_.erase(ret); - ret = 0; + ret = load_mem(cont.c_str());; } return ret; } int scanner_cfg::load_mem(const char* mem) { - base64 b64; - std::string text(b64.decode(mem, strlen(mem))); - cJSON* root = cJSON_Parse(text.c_str()); + json* jsn = new json(*(char**)&mem), * glb = nullptr; - if (!root) + if (jsn->get_value("global", glb)) { - FILE* dst = fopen((path_ + "err_cfg.txt").c_str(), "wb"); - fwrite(text.c_str(), 1, text.length(), dst); - fclose(dst); - return EINVAL; - } + int sel = -1; + glb->get_value(scanner_cfg::cur_sel_.c_str(), sel); + glb->release(); + glb = jsn->first_child(); + while ((glb = jsn->next_child())) + { + std::string val(""); + sane_config_schm * cfg = new sane_config_schm(this); - clear(); - walk_sibling_schemes(root->child); - cJSON_Delete(root); + glb->value(val); + if (cfg->load_from_mem(val.c_str())) + { + val = glb->key(); + val = sane_config_schm::from_hex_letter(val.c_str(), val.length()); + add_scheme(cfg, val.c_str()); + cfg->set_scheme_name(val.c_str()); + } + cfg->release(); + glb->release(); + } + if (sel < 0 || sel >= schemes_.size()) + sel = -1; + global_->set_value(scanner_cfg::cur_sel_.c_str(), sel); + } + else + { + sane_config_schm* cfg = new sane_config_schm(this); + if (cfg->load_from_mem(mem)) + { + cfg->remove_config("ver"); + + std::string name(cfg->auto_gen_scheme_name(lang_trans_, lang_param_)); + add_scheme(cfg); + select_scheme(name.c_str()); + save(); + } + cfg->release(); + } + jsn->release(); return 0; } @@ -1684,40 +1801,33 @@ namespace gb if (!file && path_.empty() && scanner_name_.empty()) return EINVAL; - std::string cont("{\"" + scanner_cfg::global_name_ + "\":"), - f(file ? file : path_ + scanner_name_ + ".cfg"), - v(""); - int sel = -1; - - if (!global_->get_value("ver", v) || v.empty()) - init_version(); - if (!global_->get_value(scanner_cfg::cur_sel_.c_str(), sel) || sel >= schemes_.size()) - init_select(); - - cont += global_->to_string(false); - for (auto& v: schemes_) - { - cont += ",\"" + sane_config_schm::to_hex_letter(v.name.c_str(), v.name.length()) + "\":"; - cont += v.schm->to_text_stream(false, false); - } - cont += "}"; - - base64 b64; - FILE* dst = fopen(f.c_str(), "wb"); + std::string cont(to_text_stream()), + f(file ? file : path_ + scanner_name_ + ".cfg"); + FILE* dst = fopen(f.c_str(), "wb"); if (!dst) return errno; - f = b64.encode(cont.c_str(), cont.length()); - fwrite(f.c_str(), 1, f.length(), dst); + fwrite(cont.c_str(), 1, cont.length(), dst); fclose(dst); return 0; } + void scanner_cfg::set_language_transform(const char* (__stdcall* lang_trans)(const char*, bool/*true - default language to cur language*/, void*), void* param) + { + lang_trans_ = lang_trans ? lang_trans : &scanner_cfg::language_trans; + lang_param_ = param; + } + json* scanner_cfg::get_option_default_value(void) + { + opt_default_value_->add_ref(); + + return opt_default_value_; + } void scanner_cfg::get_all_schemes(std::vector& schemes) { - schemes.push_back(scanner_cfg::default_setting_name_); + schemes.push_back(trans_language(scanner_cfg::default_setting_name_.c_str(), true)); for (auto& v : schemes_) schemes.push_back(v.name); } @@ -1745,6 +1855,22 @@ namespace gb return found; } + sane_config_schm* scanner_cfg::create_empty_scheme(bool selected) + { + sane_config_schm* schm = new sane_config_schm(this); + int ind = 1; + std::string prev(trans_language(scanner_cfg::default_setting_name_.c_str(), true)); + + while (std::find(schemes_.begin(), schemes_.end(), (prev + "-" + std::to_string(ind)).c_str()) != schemes_.end()) + ind++; + + prev += "-" + std::to_string(ind); + add_scheme(schm, prev.c_str(), true); + if (selected) + select_scheme(prev.c_str()); + + return schm; + } std::string scanner_cfg::get_current_scheme_name(void) { int ind = -1; @@ -1753,7 +1879,44 @@ namespace gb if (ind >= 0 && ind < schemes_.size()) return schemes_[ind].name; else - return scanner_cfg::default_setting_name_; + return trans_language(scanner_cfg::default_setting_name_.c_str(), true); + } + std::string scanner_cfg::to_text_stream(void) + { + std::string text(""), val(""); + int sel = -1; + + if (!global_->get_value("ver", val) || val.empty()) + init_version(); + if (!global_->get_value(scanner_cfg::cur_sel_.c_str(), sel) || sel >= schemes_.size()) + init_select(); + text = "{\"" + scanner_cfg::global_name_ + "\":" + global_->to_string(); + + for (auto& v : schemes_) + { + if (v.should_rename) + { + v.schm->auto_gen_scheme_name(lang_trans_, lang_param_); + v.name = v.schm->get_scheme_name(); + v.should_rename = false; + } + text += ",\"" + sane_config_schm::to_hex_letter(v.name.c_str(), v.name.length()) + "\":\"" + v.schm->to_text_stream(true, false) + "\""; + } + text += "}"; + + return std::move(text); + } + void scanner_cfg::set_default_value(int id, const char* name, const char* title, void* data, size_t bytes, int type) + { + sane_config_schm::set_default_value(opt_default_value_, id, name, title, data, bytes, type); + } + int scanner_cfg::option_value_type(const char* name) + { + return sane_config_schm::option_type(opt_default_value_, name); + } + std::string scanner_cfg::option_title(const char* name) + { + return sane_config_schm::option_title(opt_default_value_, name); } bool scanner_cfg::remove_scheme(const char* scheme_name) { @@ -1798,24 +1961,25 @@ namespace gb sane_config_schm* scanner_cfg::copy_scheme(const char* cp_from_name) // for UI setting, call release() if not use anymore { - if (!cp_from_name) - return nullptr; - else if (scanner_cfg::default_setting_name_ == cp_from_name) - return new sane_config_schm(); + if (!cp_from_name || *cp_from_name == 0 || + std::string(trans_language(scanner_cfg::default_setting_name_.c_str(), true)) == cp_from_name) + { + sane_config_schm* schm = new sane_config_schm(this); + + schm->set_scheme_name(trans_language(scanner_cfg::default_setting_name_.c_str(), true)); + + return schm; + } else { std::vector::iterator it = std::find(schemes_.begin(), schemes_.end(), cp_from_name); if (it == schemes_.end()) return nullptr; - std::string cont(it->schm->to_text_stream()); - sane_config_schm* schm = new sane_config_schm(); - schm->load_from_mem(cont.c_str()); - - return schm; + return it->schm->copy(); } } - bool scanner_cfg::add_scheme(sane_config_schm* schm, const char* name) + bool scanner_cfg::add_scheme(sane_config_schm* schm, const char* name, bool should_rename) { CFGSCHM cs; @@ -1827,6 +1991,7 @@ namespace gb return false; cs.schm = schm; + cs.should_rename = should_rename; schemes_.push_back(cs); schm->set_scheme_name(cs.name.c_str()); @@ -1844,6 +2009,7 @@ namespace gb if(v.name == from) { v.name = to; + v.should_rename = false; v.schm->set_scheme_name(to); return true; } diff --git a/sane/gb_json.h b/sane/gb_json.h index 021d1cb..6d6fc7b 100644 --- a/sane/gb_json.h +++ b/sane/gb_json.h @@ -37,55 +37,103 @@ namespace gb class json : public refer { - cJSON *obj_; - cJSON *cur_child_; - cJSON walk_head_; - bool is_array_; + enum val_type + { + VAL_TYPE_NULL = 0, + VAL_TYPE_BOOL, + VAL_TYPE_INT, + VAL_TYPE_FLOAT, + VAL_TYPE_STRING, + VAL_TYPE_OBJECT, + VAL_TYPE_ARRAY, + }; + val_type type_; + std::string key_; + union + { + bool bval; + int nval; + double dval; + }simple_val_; + std::string strval_; + std::vector arr_val_; + size_t cur_child_; - cJSON* find_sibling(cJSON* first, const char* name, cJSON*** addr); - cJSON* find_child(cJSON *parent, std::vector& path, bool create, cJSON*** addr = NULL); - cJSON* find(const char* path, bool create = false, cJSON*** addr = NULL); + static std::string object_key(json* jsn); + static std::string array_key(json* jsn); - protected: - ~json(); + void from_cjson(cJSON* cj); + json* find_child(const char* key, bool remove = false); public: json(char* json_txt = 0); - static std::string to_string(cJSON* root, bool formatted); - static std::string get_value_as_string(cJSON* root, bool integer = false); - static void free_node_data(cJSON* node); - static cJSON* create_element(bool is_array = false); - static cJSON* create_element_with_name(const char* name); + protected: + json(const char* key, bool val); + json(const char* key, int val); + json(const char* key, double val); + json(const char* key, const char* val); + json(json& r); + ~json(); public: + // parse/un-parse ... + void copy_from(json& r); bool attach_text(char* json_txt); - bool attach_cjson(cJSON* cjson); - bool create_empty(bool array = false); - void clear(void); - std::string to_string(bool formatted); + void clear(bool as_array = false); + std::string to_string(void); - // can be path: child/value ... + // attributes ... + std::string& key(void); + bool is_array(void); + bool is_leaf_node(void); // whether this object is a leaf node contains final value + + // value access ... bool get_value(const char* key, bool& val); bool get_value(const char* key, int& val); bool get_value(const char* key, double& val); bool get_value(const char* key, std::string& val); - bool get_value(const char* key, json*& val); // caller shoud call "delete" to free the returned object !!! - bool get_value_as_string(const char* key, std::string& val, bool integer); - bool get_as_array(const char* key, std::vector& val); + bool get_value(const char* key, json*& val); - bool first_child(std::string& val, std::string* name = NULL); - bool next_child(std::string& val, std::string* name = NULL); + // enumeration ... + size_t children(void); // return children count if was object or array, or else -1 returned + json* child(size_t ind); + json* first_child(void); + json* next_child(void); + // change the item matching 'key', otherwise add a new item bool set_value(const char* key, bool val); bool set_value(const char* key, int val); bool set_value(const char* key, double val); - bool set_value(const char* key, std::string val); bool set_value(const char* key, const char* val); - bool set_value(const char* key, json* obj); + bool set_value(const char* key, json* val); - bool change_key(const char* old_key, const char* new_key); + // operator+= only for array + json& operator+=(bool val); + json& operator+=(int val); + json& operator+=(double val); + json& operator+=(const char* val); + json& operator+=(json* val); + + // remove item + json& operator-=(int ind); bool remove(const char* key); + bool remove(json* child); + bool remove(int ind); + + // position management + int index(json* child); + int index_move_to(json* child, int ind); + + // leaf node value ... + bool value(bool& val); + bool value(int& val); + bool value(double& val); + bool value(std::string& val); + json& operator=(bool val); + json& operator=(int val); + json& operator=(double val); + json& operator=(const char* val); }; class base64 @@ -115,9 +163,8 @@ namespace gb std::string file_; json* jsn_; json* bkp_; - json* def_val_; + json* def_val_; // name_id: id, name_val: val bool in_setting_; - std::map id_name_; // (id, default-val) void clear(); std::string default_value(const char* name); @@ -129,19 +176,30 @@ namespace gb sane_config_schm(scanner_cfg* scanner = nullptr); static std::string opt_data_appendix_; + static std::string opt_def_id_appendix_; + static std::string opt_def_val_appendix_; + static std::string opt_def_type_appendix_; + static std::string opt_def_title_appendix_; + static bool hex(unsigned char ch, unsigned char* val); static bool hex_char(const char* data, unsigned char* val); static std::string to_hex_letter(const char* data, size_t bytes); static std::string from_hex_letter(const char* data, size_t bytes); static bool is_option_data(std::string& name); // reset baase option name into 'name' if name was option data, and return true + static void set_default_value(json* jsn, int id, const char* name, const char* title, void* data, size_t bytes, int type); + static int option_name_2_id(json* jsn, const char* name); + static int option_type(json* jsn, const char* name); + static std::string option_title(json* jsn, const char* name); + static std::string option_default_value(json* jsn, const char* name); + static std::string sane_option_value_2_string(void* val, size_t bytes, int type); + public: sane_config_schm* copy(void); bool load_from_file(const char* file); bool load_from_mem(const char* mem, bool in_b64 = true); bool save_to(const char* file); - void set_default_value(int sn, const char* name, const char* val, size_t bytes); - void copy_default_value(sane_config_schm* from); + void set_default_value(int sn, const char* name, const char* title, const char* val, size_t bytes, int type); bool first_config(std::string& name, std::string& val); bool next_config(std::string& name, std::string& val); bool get_config(const char* name, std::string& val); @@ -150,14 +208,15 @@ namespace gb void config_changed(int sn, const char* val, size_t bytes, bool extra = false); void remove_config(const char* name); void set_value(const char* name, const char* val, size_t bytes, bool extra = false); - bool has_changed(void); + bool has_changed(int* items = nullptr); void end_setting(bool cancel); int id_from_name(const char* name); std::string to_text_stream(bool b64 = true, bool with_ver = true); std::string get_version(void); std::string get_scheme_name(void); void set_scheme_name(const char* name); - void update(bool(* is_float)(int, void*), void* param, const char*(* t2n)(const char*), std::string* discard = NULL); + + std::string auto_gen_scheme_name(const char* (__stdcall* lang_trans)(const char*, bool/*true - default language to cur language*/, void*), void* param); }; class scanner_cfg : public refer @@ -178,12 +237,23 @@ namespace gb std::string path_; std::string scanner_name_; // scanner type: HUAGOSCAN G100 - 0100 json *global_; // version, current scheme, ... + json *opt_default_value_; + const char* (__stdcall* lang_trans_)(const char*, bool/*true - default language to cur language*/, void*); + void* lang_param_; + typedef struct _cfg_schm { std::string name; + bool should_rename; sane_config_schm* schm; + struct _cfg_schm() + { + name = ""; + should_rename = false; + schm = nullptr; + } bool operator==(const char* n) { return name == n; @@ -191,14 +261,12 @@ namespace gb }CFGSCHM; std::vector schemes_; - static std::string global_name_; - static std::string cur_sel_; - static std::string default_setting_name_; + static const char* __stdcall language_trans(const char* in, bool from_def, void* param); void clear(void); void init_version(void); void init_select(void); - void walk_sibling_schemes(cJSON* first); + const char* trans_language(const char* in, bool from_default); protected: ~scanner_cfg(); @@ -215,20 +283,31 @@ namespace gb }UDF, *LPUDF; static bool update(const char* file, LPUDF func); + static std::string global_name_; + static std::string cur_sel_; + static std::string default_setting_name_; + public: int load_file(const char* file); int load_mem(const char* mem); int save(const char* file = nullptr); + void set_language_transform(const char* (__stdcall* lang_trans)(const char*, bool/*true - default language to cur language*/, void*), void* param); + json* get_option_default_value(void); void get_all_schemes(std::vector& schemes); // return all schemes name queue, the first is always be 'Default settings' sane_config_schm* get_scheme(const char* scheme_name = nullptr/*return current scheme if was null*/); // call sane_config_schm::release() if not use anymore + sane_config_schm* create_empty_scheme(bool selected); // create an empty scheme and add to scheme queue std::string get_current_scheme_name(void); + std::string to_text_stream(void); + void set_default_value(int id, const char* name, const char* title, void* data, size_t bytes, int type); + int option_value_type(const char* name); + std::string option_title(const char* name); bool remove_scheme(const char* scheme_name); void remove_all_schemes(void); bool select_scheme(const char* scheme_name); sane_config_schm* copy_scheme(const char* cp_from_name); // for UI setting, call release() if not use anymore - bool add_scheme(sane_config_schm* schm, const char* name = nullptr); + bool add_scheme(sane_config_schm* schm, const char* name = nullptr, bool should_rename = false); bool rename_scheme(const char* from, const char* to); }; }; diff --git a/sane/resource.h b/sane/resource.h index d033bfc..3b6ebee 100644 --- a/sane/resource.h +++ b/sane/resource.h @@ -9,6 +9,8 @@ #define IDD_AREA 106 #define IDD_GAMMA 107 #define IDD_CHOOSE_DEV 108 +#define IDD_CFG_MGR 109 +#define IDD_INPUT 110 #define IDC_EDIT_PAPER 1001 #define IDC_EDIT_IMAGE 1002 #define IDC_STATIC_PAPER 1003 @@ -21,8 +23,11 @@ #define IDC_UNIT2 1009 #define IDC_SCHEME 1009 #define IDC_EDIT_DPI 1010 +#define IDC_BUTTON_CONFIG_MGR 1010 #define IDC_BUTTON_RESET 1011 +#define IDC_BUTTON_CONFIG_MENU 1011 #define IDC_EDIT_x 1012 +#define IDC_BUTTON_DEL_SEL 1012 #define IDC_EDIT_y 1013 #define IDC_EDIT_W 1014 #define IDC_EDIT_H 1015 @@ -42,6 +47,9 @@ #define IDC_STATIC_COLOR 1029 #define IDC_STATIC_INPUT 1030 #define IDC_STATIC_OUTPUT 1031 +#define IDC_BUTTON_DEL_ALL 1032 +#define IDC_EDIT1 1033 +#define IDC_STATIC_SKETCH 1034 // Next default values for new objects // @@ -49,7 +57,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 109 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1032 +#define _APS_NEXT_CONTROL_VALUE 1035 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/sane/sane.rc b/sane/sane.rc index e1484c0..decac46 100644 --- a/sane/sane.rc +++ b/sane/sane.rc @@ -68,10 +68,12 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION CAPTION "Dialog" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "ȷ",IDOK,223,8,33,13 + DEFPUSHBUTTON "ȷ",IDOK,223,7,33,14 PUSHBUTTON "ɨ",IDC_BUTTON_SCAN,7,7,39,14,NOT WS_VISIBLE - PUSHBUTTON "ָĬֵ",IDC_BUTTON_RESTORE,113,7,48,14,NOT WS_VISIBLE - PUSHBUTTON "",IDC_BUTTON_HELP,167,7,48,14,NOT WS_VISIBLE + PUSHBUTTON "ָĬֵ",IDC_BUTTON_RESTORE,121,7,45,14,NOT WS_VISIBLE + PUSHBUTTON "",IDC_BUTTON_HELP,167,7,45,14,NOT WS_VISIBLE + PUSHBUTTON "ù",IDC_BUTTON_CONFIG_MGR,57,7,38,14,NOT WS_VISIBLE + PUSHBUTTON ">",IDC_BUTTON_CONFIG_MENU,94,7,8,14,NOT WS_VISIBLE END IDD_PAGE DIALOGEX 0, 0, 258, 133 @@ -135,6 +137,30 @@ BEGIN CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,253,62 END +IDD_CFG_MGR DIALOGEX 0, 0, 229, 218 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +CAPTION "ù" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "ȫɾ",IDC_BUTTON_DEL_ALL,172,7,50,14 + DEFPUSHBUTTON "ȷ",IDOK,189,198,33,13 + LTEXT "÷:",IDC_STATIC_PAPER,7,9,40,8 + CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_EDITLABELS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,22,215,62 + PUSHBUTTON "ɾѡ",IDC_BUTTON_DEL_SEL,115,7,50,14 + GROUPBOX ":",IDC_STATIC_SKETCH,7,95,215,101 + EDITTEXT IDC_EDIT1,14,109,204,82,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_VSCROLL +END + +IDD_INPUT DIALOGEX 0, 0, 193, 41 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +CAPTION "ֵ:" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT1,7,7,179,12,ES_AUTOHSCROLL + PUSHBUTTON "ȷ",IDOK,144,22,42,12 + PUSHBUTTON "ȡ",IDCANCEL,7,22,42,12 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -191,6 +217,22 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 89 END + + IDD_CFG_MGR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 222 + TOPMARGIN, 7 + BOTTOMMARGIN, 211 + END + + IDD_INPUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 186 + TOPMARGIN, 7 + BOTTOMMARGIN, 34 + END END #endif // APSTUDIO_INVOKED @@ -230,6 +272,16 @@ BEGIN 0 END +IDD_CFG_MGR AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_INPUT AFX_DIALOG_LAYOUT +BEGIN + 0 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -271,8 +323,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,34,10000,22310 - PRODUCTVERSION 4,34,10000,22310 + FILEVERSION 4,37,20000,23034 + PRODUCTVERSION 4,37,20000,23034 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -287,14 +339,14 @@ BEGIN BEGIN BLOCK "080404b0" BEGIN - VALUE "CompanyName", "ϢƼ޹˾" - VALUE "FileDescription", "ɨӦó" - VALUE "FileVersion", "4.34.10000.22310" + VALUE "CompanyName", "ϺоƼ޹˾" + VALUE "FileDescription", "оɨӦó" + VALUE "FileVersion", "4.37.20000.23034" VALUE "InternalName", "sane.dll" - VALUE "LegalCopyright", "Copyright (C) HUAGOScan 2022" + VALUE "LegalCopyright", "Copyright (C) MICROTEKScan 2023" VALUE "OriginalFilename", "sane.dll" - VALUE "ProductName", "HUAGOScan" - VALUE "ProductVersion", "4.34.10000.22310" + VALUE "ProductName", "MICROTEKScan" + VALUE "ProductVersion", "4.37.20000.23034" END END BLOCK "VarFileInfo" diff --git a/sane/sane.vcxproj b/sane/sane.vcxproj index 00fef52..71e84fa 100644 --- a/sane/sane.vcxproj +++ b/sane/sane.vcxproj @@ -200,8 +200,10 @@ + + @@ -223,9 +225,12 @@ + + + diff --git a/sane/sane.vcxproj.filters b/sane/sane.vcxproj.filters index 4edc5da..9eba608 100644 --- a/sane/sane.vcxproj.filters +++ b/sane/sane.vcxproj.filters @@ -66,6 +66,12 @@ sane2twain\UI + + sane2twain\UI + + + sane2twain\UI + @@ -140,6 +146,15 @@ sane2twain\UI + + sane2twain\UI + + + sane2twain\UI + + + sane2twain\UI + diff --git a/sane/scanned_img.cpp b/sane/scanned_img.cpp index a186f1c..e46c3f3 100644 --- a/sane/scanned_img.cpp +++ b/sane/scanned_img.cpp @@ -5,7 +5,7 @@ #pragma comment(lib, "Shlwapi.lib") #include "../../code_device/hgsane/sane_hg_mdw.h" - +#include "../../sdk/include/lang/app_language.h" @@ -30,7 +30,7 @@ namespace local_trans delete[] ansi; } - return a; + return std::move(a); } std::wstring a2u(const char* asc, UINT cp) { @@ -49,7 +49,23 @@ namespace local_trans delete[] buf; } - return u; + return std::move(u); + } + + std::wstring lang_trans_between_hz936(const wchar_t* in, bool from_hz) + { + std::string a(u2a(in, CP_UTF8)); + + if (from_hz) + a = from_default_language(a.c_str(), nullptr); + else + a = to_default_language(a.c_str(), nullptr); + + return std::move(a2u(a.c_str(), CP_UTF8)); + } + const char* __stdcall lang_trans_between_hz936(const char* in, bool from_hz, void* param) + { + return from_hz ? from_default_language(in, nullptr) : to_default_language(in, nullptr); } } diff --git a/sane/scanned_img.h b/sane/scanned_img.h index 6f93bfe..4beb9bd 100644 --- a/sane/scanned_img.h +++ b/sane/scanned_img.h @@ -195,4 +195,7 @@ namespace local_trans { std::string u2a(const wchar_t* unic, UINT cp = CP_ACP); std::wstring a2u(const char* asc, UINT cp = CP_ACP); + + std::wstring lang_trans_between_hz936(const wchar_t* in, bool from_hz = true); + const char* __stdcall lang_trans_between_hz936(const char* in, bool from_hz, void* param); } diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 1bb0eb6..db88809 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -315,6 +315,14 @@ namespace callback else delete t; } + + static const char* __stdcall language_trans(const char* in, bool from_hz, void* param) + { + if (from_hz) + return from_default_language(in, nullptr); + else + return to_default_language(in, nullptr); + } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -325,7 +333,9 @@ scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BAS , scanner_ev_handler_(NULL), evh_param_(NULL), app_wnd_(NULL), user_cancel_(false) , max_img_mem_(1 * 1024) { - cfg_ = new gb::sane_config_schm(); + cfg_ = new gb::scanner_cfg(); + cfg_->set_language_transform(&callback::language_trans, NULL); + tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str()); { char* tmp = getenv("LOCALAPPDATA"); @@ -516,6 +526,10 @@ bool scanner::is_option_float(int sn, void* param) else return false; } +void __stdcall scanner::apply_scheme(gb::sane_config_schm* schm, void* param) +{ + ((scanner*)param)->apply_scheme(schm); +} // IRef COM_API_IMPLEMENT(scanner, long, add_ref(void)) @@ -538,11 +552,11 @@ void scanner::transport_config_file(void) pid += scanner_name_.substr(pos + 3); if (scanner_name_.find(L"HUAGOSCAN ") != std::wstring::npos) { - old = dlg_base::language_from_hz936(L"\u534E\u9AD8\u626B\u63CF\u4EEA\u2014"); + old = local_trans::lang_trans_between_hz936(L"\u534E\u9AD8\u626B\u63CF\u4EEA\u2014"); } else if (scanner_name_.find(L"LANXUMSCAN ") != std::wstring::npos) { - old = dlg_base::language_from_hz936(L"\u7ACB\u601D\u8FB0\u626B\u63CF\u4EEA\u2014"); + old = local_trans::lang_trans_between_hz936(L"\u7ACB\u601D\u8FB0\u626B\u63CF\u4EEA\u2014"); pid += L"S"; } old += pid; @@ -554,89 +568,48 @@ void scanner::transport_config_file(void) } void scanner::update_config(void) { + gb::sane_config_schm* schm = cfg_->get_scheme(); std::string notice(""); - cfg_->update(&scanner::is_option_float, handle_, &callback::option_title_2_name, ¬ice); - if (notice.length()) - { - std::wstring msg(dlg_base::language_from_hz936(L"\u4E0B\u5217\u914D\u7F6E\u6570\u636E\u9519\u8BEF\uFF0C\u5DF2\u7ECF\u6062\u590D\u5230\u9ED8\u8BA4\u503C\u3002\u5982\u679C\u9700\u8981\uFF0C\u8BF7\u91CD\u65B0\u8BBE\u7F6E") + L"\r\n\r\n"); - size_t pos = notice.find("\r\n"); - while (pos != std::string::npos) - { - msg += local_trans::a2u(callback::option_name_2_title(notice.substr(0, pos).c_str()), CP_UTF8) + L"\r\n"; - notice.erase(0, pos + 2); - pos = notice.find("\r\n"); - } - if (!IsWindow(app_wnd_)) - callback::bring_message_box_topmost(dlg_base::language_from_hz936(L"\u52A0\u8F7D\u914D\u7F6E").c_str()); - MessageBoxW(app_wnd_, msg.c_str(), dlg_base::language_from_hz936(L"\u52A0\u8F7D\u914D\u7F6E").c_str(), MB_OK | MB_ICONINFORMATION); + if (schm) + { + //schm->update(&scanner::is_option_float, handle_, &callback::option_title_2_name, ¬ice); + //if (notice.length()) + //{ + // std::wstring msg(local_trans::lang_trans_between_hz936(L"\u4E0B\u5217\u914D\u7F6E\u6570\u636E\u9519\u8BEF\uFF0C\u5DF2\u7ECF\u6062\u590D\u5230\u9ED8\u8BA4\u503C\u3002\u5982\u679C\u9700\u8981\uFF0C\u8BF7\u91CD\u65B0\u8BBE\u7F6E") + L"\r\n\r\n"); + // size_t pos = notice.find("\r\n"); + // + // while (pos != std::string::npos) + // { + // msg += local_trans::a2u(callback::option_name_2_title(notice.substr(0, pos).c_str()), CP_UTF8) + L"\r\n"; + // notice.erase(0, pos + 2); + // pos = notice.find("\r\n"); + // } + // if (!IsWindow(app_wnd_)) + // callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(L"\u52A0\u8F7D\u914D\u7F6E").c_str()); + // MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(L"\u52A0\u8F7D\u914D\u7F6E").c_str(), MB_OK | MB_ICONINFORMATION); + //} + schm->release(); } } void scanner::load_config(const wchar_t* file) { - cfg_->load_from_file(local_trans::u2a(file).c_str()); + cfg_->load_file(local_trans::u2a(file).c_str()); update_config(); } void scanner::save_config(const wchar_t* file) { - cfg_->save_to(local_trans::u2a(file).c_str()); + cfg_->save(local_trans::u2a(file).c_str()); } void scanner::apply_config(void) { - std::string n(""), v(""), ver(cfg_->get_version()); + gb::sane_config_schm* schm = cfg_->get_scheme(); - if (cfg_->first_config(n, v)) - { - do - { - int id = cfg_->id_from_name(n.c_str()); - if (id == -1) - { - if (gb::sane_config_schm::is_option_data(n)) - { - id = cfg_->id_from_name(n.c_str()); - if (id == is_custom_gamma_id_) - { - if (v.length() == sizeof(SANE_Gamma)) - { - unsigned int l = v.length(); - hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &v[0], &l); - } - else - { - wchar_t info[128] = { 0 }; - swprintf_s(info, _countof(info) - 1, L"ERROR: custom gamma data length is %u, but we expect %u.\r\n", v.length(), sizeof(SANE_Gamma)); - log_info(info, 0); - } - } - } - } - else - { - v = from_default_language(v.c_str(), nullptr); - void* data = &v[0]; - SANE_Fixed fixed = 0; - const SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, (const void*)id); - if (desc) - { - char* buf = NULL; - SANE_Int after = 0; + if (!schm) + return; - if (desc->type == SANE_TYPE_STRING) - { - buf = new char[desc->size + 4]; - memset(buf, 0, desc->size + 4); - strcpy(buf, v.c_str()); - data = buf; - } - hg_sane_middleware::instance()->set_option(handle_, (const void*)id, SANE_ACTION_SET_VALUE, data, &after); - - if (buf) - delete[] buf; - } - } - } while (cfg_->next_config(n, v)); - } + apply_scheme(schm); + schm->release(); } void scanner::on_ui_event(int uev, void* sender) { @@ -772,8 +745,8 @@ int scanner::open(void) HWND parent = callback::find_main_wnd(); if (!IsWindow(parent)) - callback::bring_message_box_topmost(dlg_base::language_from_hz936(L"\u6253\u5F00\u5931\u8D25").c_str()); - MessageBoxW(parent, msg.c_str(), dlg_base::language_from_hz936(L"\u6253\u5F00\u5931\u8D25").c_str(), MB_OK | MB_ICONERROR); + callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_OPEN_FAILED).c_str()); + MessageBoxW(parent, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_OPEN_FAILED).c_str(), MB_OK | MB_ICONERROR); } return ret; @@ -829,10 +802,10 @@ int scanner::init_options_id(void) if (desc->type == SANE_TYPE_STRING) { std::string deflan(to_default_language((char*)val, nullptr)); - cfg_->set_default_value(op_id, desc->name, &deflan[0], deflan.length()); + cfg_->set_default_value(op_id, desc->name, desc->title, &deflan[0], deflan.length(), desc->type); } else - cfg_->set_default_value(op_id, desc->name, (char*)val, len); + cfg_->set_default_value(op_id, desc->name, desc->title, (char*)val, len, desc->type); } local_utility::free_memory(val); } @@ -1103,14 +1076,14 @@ bool scanner::get_option_value_with_parent(int sn, set_opt_value setv, void* par memset(buf, 0, parent->size); hg_sane_middleware::instance()->get_cur_value(handle_, (void*)scan_mode_id_, buf); - handled = compare_sane_opt(OPTION_VALUE_SMZS_LXSM, buf); + handled = compare_sane_opt(local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_LXSM, true, nullptr), buf); delete[] buf; if (handled) { int count = -1; value_role role = VAL_ROLE_CURRENT; buf = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)scan_mode_id_); - if (compare_sane_opt(OPTION_VALUE_SMZS_LXSM, buf)) + if (compare_sane_opt(local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_LXSM, true, nullptr), buf)) role = value_role(role | VAL_ROLE_DEFAULT); local_utility::free_memory(buf); @@ -1134,17 +1107,17 @@ bool scanner::set_option_value_with_parent(int sn, void* data, int* err) // retu memset(val, 0, parent->size + 4); hg_sane_middleware::instance()->get_cur_value(handle_, (void*)scan_mode_id_, val); - if (compare_sane_opt(OPTION_VALUE_SMZS_LXSM, val)) + if (compare_sane_opt(local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_LXSM, true, nullptr), val)) { if (*(int*)data != -1) { - strcpy(val, OPTION_VALUE_SMZS_SMZDZS); + strcpy(val, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_SMZDZS, true, nullptr)); *err = hg_sane_middleware::instance()->set_option(handle_, (void*)scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after); } } else if (*(int*)data == -1) { - strcpy(val, OPTION_VALUE_SMZS_LXSM); + strcpy(val, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMZS_LXSM, true, nullptr)); *err = hg_sane_middleware::instance()->set_option(handle_, (void*)scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after); } delete[] val; @@ -1231,6 +1204,69 @@ scanner::EXAPIPOS scanner::find_ex_api(int op_id) { return std::find(ex_opts_.begin(), ex_opts_.end(), op_id); } +void scanner::apply_scheme(gb::sane_config_schm* schm) +{ + // restore ... + hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_RESTORE_SETTINGS, nullptr, nullptr); + + if (!schm) + return; + + std::string n(""), v(""), ver(schm->get_version()); + + if (schm->first_config(n, v)) + { + do + { + int id = schm->id_from_name(n.c_str()); + if (id == -1) + { + if (gb::sane_config_schm::is_option_data(n)) + { + id = schm->id_from_name(n.c_str()); + if (id == is_custom_gamma_id_) + { + if (v.length() == sizeof(SANE_Gamma)) + { + unsigned int l = v.length(); + hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &v[0], &l); + } + else + { + wchar_t info[128] = { 0 }; + swprintf_s(info, _countof(info) - 1, L"ERROR: custom gamma data length is %u, but we expect %u.\r\n", v.length(), sizeof(SANE_Gamma)); + log_info(info, 0); + } + } + } + } + else + { + v = from_default_language(v.c_str(), nullptr); + void* data = &v[0]; + SANE_Fixed fixed = 0; + const SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, (const void*)id); + if (desc) + { + char* buf = NULL; + SANE_Int after = 0; + + if (desc->type == SANE_TYPE_STRING) + { + buf = new char[desc->size + 4]; + memset(buf, 0, desc->size + 4); + strcpy(buf, v.c_str()); + data = buf; + } + hg_sane_middleware::instance()->set_option(handle_, (const void*)id, SANE_ACTION_SET_VALUE, data, &after); + + if (buf) + delete[] buf; + } + } + } while (schm->next_config(n, v)); + } +} EX_OPTION_HANDLER_IMPL(multiout) { @@ -1533,7 +1569,7 @@ EX_OPTION_HANDLER_IMPL(paper_lateral) if (*(bool*)data) { // set to A4Lateral ... - strcpy(buf, OPTION_VALUE_ZZCC_A4HX); + strcpy(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_A4HX, true, nullptr)); ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after); ret = local_utility::sane_statu_2_scanner_err(ret); } @@ -1556,8 +1592,8 @@ EX_OPTION_HANDLER_IMPL(auto_paper_size) if (setv) { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); - bool yes = strcmp(buf, OPTION_VALUE_ZZCC_PPYSCC) == 0, - def = strcmp(init, OPTION_VALUE_ZZCC_PPYSCC) == 0; + bool yes = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_PPYSCC, true, nullptr)) == 0, + def = strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_PPYSCC, true, nullptr)) == 0; local_utility::free_memory(init); set_cur_and_def_value(yes, def, setv, data); @@ -1565,7 +1601,7 @@ EX_OPTION_HANDLER_IMPL(auto_paper_size) else { SANE_Int after = 0; - strcpy(buf, *(bool*)data ? OPTION_VALUE_ZZCC_PPYSCC : OPTION_VALUE_ZZCC_A4); + strcpy(buf, *(bool*)data ? local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_PPYSCC, true, nullptr) : local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_A4, true, nullptr)); ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after); ret = local_utility::sane_statu_2_scanner_err(ret); } @@ -1585,7 +1621,7 @@ EX_OPTION_HANDLER_IMPL(auto_paper_crop) if (setv) { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); - bool yes = strcmp(buf, OPTION_VALUE_ZZCC_ZDSMCCZDCQ) == 0, + bool yes = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_ZDSMCCZDCQ, true, nullptr)) == 0, def = strcmp(init, OPTION_VALUE_ZZCC_ZDSMCCZDCQ) == 0; local_utility::free_memory(init); @@ -1594,7 +1630,7 @@ EX_OPTION_HANDLER_IMPL(auto_paper_crop) else { SANE_Int after = 0; - strcpy(buf, *(bool*)data ? OPTION_VALUE_ZZCC_ZDSMCCZDCQ : OPTION_VALUE_ZZCC_ZDSMCC); + strcpy(buf, *(bool*)data ? local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_ZDSMCCZDCQ, true, nullptr) : local_trans::lang_trans_between_hz936(OPTION_VALUE_ZZCC_ZDSMCC, true, nullptr)); ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after); ret = local_utility::sane_statu_2_scanner_err(ret); } @@ -1664,12 +1700,12 @@ EX_OPTION_HANDLER_IMPL(duplex) char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf); - set_cur_and_def_value(strcmp(buf, OPTION_VALUE_SMYM_SM) == 0, strcmp(init, OPTION_VALUE_SMYM_SM) == 0, setv, data); + set_cur_and_def_value(strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_SM, true, nullptr)) == 0, strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_SM, true, nullptr)) == 0, setv, data); local_utility::free_memory(init); } else { - strcpy(buf, val ? OPTION_VALUE_SMYM_SM : OPTION_VALUE_SMYM_DM); + strcpy(buf, val ? local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_SM, true, nullptr) : local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_DM, true, nullptr)); SANE_Int after = 0; ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after); ret = local_utility::sane_statu_2_scanner_err(ret); @@ -1691,13 +1727,13 @@ EX_OPTION_HANDLER_IMPL(fill_background) { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf); - val = strcmp(buf, OPTION_VALUE_SMYM_SM) == 0; - set_cur_and_def_value(strcmp(buf, OPTION_VALUE_BJTCFS_TDBX) == 0, strcmp(init, OPTION_VALUE_BJTCFS_TDBX) == 0, setv, data); + val = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_SM, true, nullptr)) == 0; + set_cur_and_def_value(strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_BJTCFS_TDBX, true, nullptr)) == 0, strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_BJTCFS_TDBX, true, nullptr)) == 0, setv, data); local_utility::free_memory(init); } else { - strcpy(buf, val ? OPTION_VALUE_BJTCFS_TDBX : OPTION_VALUE_BJTCFS_ADBX); + strcpy(buf, val ? local_trans::lang_trans_between_hz936(OPTION_VALUE_BJTCFS_TDBX, true, nullptr) : local_trans::lang_trans_between_hz936(OPTION_VALUE_BJTCFS_ADBX, true, nullptr)); SANE_Int after = 0; ret = hg_sane_middleware::instance()->set_option(handle_, (void*)base_id, SANE_ACTION_SET_VALUE, buf, &after); ret = local_utility::sane_statu_2_scanner_err(ret); @@ -1718,17 +1754,17 @@ EX_OPTION_HANDLER_IMPL(discard_blank_page) if (setv) { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); - bool def = strcmp(init, OPTION_VALUE_SMYM_TGKBYTY) == 0; + bool def = strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYTY, true, nullptr)) == 0; local_utility::free_memory(init); hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf); - val = strcmp(buf, OPTION_VALUE_SMYM_TGKBYTY) == 0; + val = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYTY, true, nullptr)) == 0; set_cur_and_def_value(val, def, setv, data); } else { if (val) - strcpy(buf, OPTION_VALUE_SMYM_TGKBYTY); + strcpy(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYTY, true, nullptr)); else { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); @@ -1755,17 +1791,17 @@ EX_OPTION_HANDLER_IMPL(discard_blank_receipt) if (setv) { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); - bool def = strcmp(init, OPTION_VALUE_SMYM_TGKBYFPZ) == 0; + bool def = strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYFPZ, true, nullptr)) == 0; local_utility::free_memory(init); hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf); - val = strcmp(buf, OPTION_VALUE_SMYM_TGKBYFPZ) == 0; + val = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYFPZ, true, nullptr)) == 0; set_cur_and_def_value(val, def, setv, data); } else { if (val) - strcpy(buf, OPTION_VALUE_SMYM_TGKBYFPZ); + strcpy(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_TGKBYFPZ, true, nullptr)); else { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); @@ -1792,17 +1828,17 @@ EX_OPTION_HANDLER_IMPL(page_fold) if (setv) { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); - bool def = strcmp(init, OPTION_VALUE_SMYM_DZ) == 0; + bool def = strcmp(init, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_DZ, true, nullptr)) == 0; local_utility::free_memory(init); hg_sane_middleware::instance()->get_cur_value(handle_, (void*)base_id, buf); - val = strcmp(buf, OPTION_VALUE_SMYM_DZ) == 0; + val = strcmp(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_DZ, true, nullptr)) == 0; set_cur_and_def_value(val, def, setv, data); } else { if (val) - strcpy(buf, OPTION_VALUE_SMYM_DZ); + strcpy(buf, local_trans::lang_trans_between_hz936(OPTION_VALUE_SMYM_DZ, true, nullptr)); else { char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, (void*)base_id); @@ -2255,8 +2291,8 @@ COM_API_IMPLEMENT(scanner, int, start(void)) if (indicator_.get()) indicator_->show(false); if (!IsWindow(app_wnd_)) - callback::bring_message_box_topmost(dlg_base::language_from_hz936(L"\u542F\u52A8\u5931\u8D25").c_str()); - MessageBoxW(app_wnd_, msg.c_str(), dlg_base::language_from_hz936(L"\u542F\u52A8\u5931\u8D25").c_str(), MB_OK | MB_ICONERROR); + callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str()); + MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str(), MB_OK | MB_ICONERROR); } prev_start_result_ = ret; is_scanning_ = ret == SANE_STATUS_GOOD; @@ -2708,7 +2744,7 @@ COM_API_IMPLEMENT(scanner, int, twain_get_config(char* buf, size_t* len)) } COM_API_IMPLEMENT(scanner, int, twain_set_config(char* buf, size_t len)) { - if(cfg_->load_from_mem(buf)) + if(cfg_->load_mem(buf)) { update_config(); apply_config(); @@ -2756,8 +2792,7 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan, bo pid = scanner_name_.length(); setting_.reset(new dlg_setting(parent, &api, handle_, with_scan, scanner_name_.substr(0, pid).c_str())); setting_->set_ui_event_notify(&scanner::ui_callback, this); - setting_->set_config(cfg_, (cfg_path_ + scanner_name_.substr(0, pid)).c_str()); - cfg_->begin_setting(); + setting_->set_config(cfg_, (cfg_path_ + scanner_name_.substr(0, pid) + L".cfg").c_str(), &scanner::apply_scheme, this); indicator_.reset(); if (indicator) { @@ -2862,8 +2897,8 @@ int scanner::handle_device_event(int ev_code, void* data, unsigned int* len) { std::wstring msg(local_trans::a2u((char*)data, CP_UTF8)); if(!IsWindow(app_wnd_)) - callback::bring_message_box_topmost(dlg_base::language_from_hz936(L"\u9519\u8BEF").c_str()); - MessageBoxW(app_wnd_, msg.c_str(), dlg_base::language_from_hz936(L"\u9519\u8BEF").c_str(), MB_OK); + callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str()); + MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str(), MB_OK); } on_ui_event(ev_code, (void*)ev_code); } diff --git a/sane/scanner.h b/sane/scanner.h index 180dfde..515fc3e 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -26,7 +26,7 @@ class dlg_indicator; class dlg_setting; namespace gb { - class sane_config_schm; + class scanner_cfg; } class scanner : public ISaneInvoker, virtual public refer @@ -53,7 +53,7 @@ class scanner : public ISaneInvoker, virtual public refer SANE_FinalImgFormat img_fmt_; std::unique_ptr indicator_; std::unique_ptr setting_; - gb::sane_config_schm* cfg_; + gb::scanner_cfg* cfg_; int(__stdcall* scanner_ev_handler_)(int, void*); void* evh_param_; @@ -99,6 +99,7 @@ class scanner : public ISaneInvoker, virtual public refer std::vector ex_opts_; typedef std::vector::iterator EXAPIPOS; EXAPIPOS find_ex_api(int op_id); + void apply_scheme(gb::sane_config_schm* schm); ; EX_OPTION_HANDLER_DECL(multiout); EX_OPTION_HANDLER_DECL(auto_color_type); @@ -167,6 +168,7 @@ class scanner : public ISaneInvoker, virtual public refer static float __stdcall to_float(SANE_Fixed v); static void __stdcall ui_callback(int uev, void* sender, void* param); static bool is_option_float(int sn, void* param); + static void __stdcall apply_scheme(gb::sane_config_schm* schm, void* param); public: scanner(SCANNERID id);