diff --git a/tools/apps/hgjson/CDlgLang.cpp b/tools/apps/hgjson/CDlgLang.cpp new file mode 100644 index 0000000..ad851b5 --- /dev/null +++ b/tools/apps/hgjson/CDlgLang.cpp @@ -0,0 +1,937 @@ +// CDlgLang.cpp: 实现文件 +// + +#include "stdafx.h" +#include "hgjson.h" +#include "afxdialogex.h" +#include "CDlgLang.h" +#include "DlgInput.h" + +#include +#include +#include +#include + +#define RESERVED_STR 600 + +namespace sdk_util +{ + INTER_MODULE_CALLBACK(got_str) + { + *((std::string*)param) += std::string(data, len); + + return inter_module_data::SET_RESULT_CONTINUE; + } + INTER_MODULE_CALLBACK(got_wstr) + { + *((std::wstring*)param) += std::wstring((const wchar_t*)data, len / 2); + + return inter_module_data::SET_RESULT_CONTINUE; + } + + uint32_t make_string_id(const wchar_t* str, bool(*is_repeat)(uint32_t, void*), void* param) + { + uint32_t crc = coding_util::crc_32(str, lstrlenW(str) * 2); + + crc &= 0x0ffff; + if (crc <= RESERVED_STR) + crc = RESERVED_STR + 1; + while (is_repeat(crc, param)) + crc++; + + return crc; + } + + void trim_left(std::wstring& str) + { + int i = 0; + + while (str[i] == L' ' || str[i] == L'\t') + i++; + + str.erase(0, i); + } + void trim_right(std::wstring& str) + { + int i = str.length() - 1; + while (i >= 0) + { + if (str[i] == L' ' || str[i] == L'\t') + i--; + else + break; + } + + str.erase(i + 1); + } + unsigned pick_number(const wchar_t* str, const wchar_t** end, int type) + { + int off = 0; + unsigned val = 0; + + if (type == coding_util::NUM_FMT_HEX) + { + for (; off < 4; ++off) + { + val <<= 4; + if (str[off] >= L'0' && str[off] <= L'9') + { + val += str[off] - L'0'; + } + else if (str[off] >= L'a' && str[off] <= L'f') + { + val += str[off] - L'a' + 10; + } + else if (str[off] >= L'A' && str[off] <= L'A') + { + val += str[off] - L'A' + 10; + } + else + { + val >>= 4; + break; + } + } + } + else if (type == coding_util::NUM_FMT_OCT) + { + for (; off < 3; ++off) + { + val <<= 3; + if (str[off] >= L'0' && str[off] <= L'7') + { + val += str[off] - L'0'; + } + else + { + val >>= 3; + break; + } + } + } + + if (end) + *end = str + off; + + return val; + } + void convert_unicode(std::wstring& str) + { + std::wstring conv(L""); + + for (int i = 0; i < str.length(); ++i) + { + if (str[i] == L'\\') + { + const wchar_t* end = NULL; + if (str[i + 1] == L'u') + { + unsigned val = (unsigned)sdk_util::pick_number(str.c_str() + i + 2, &end, coding_util::NUM_FMT_HEX); + if (end - str.c_str() == i + 6) + { + conv.append(1, val); + i += 5; + continue; + } + } + else if (iswdigit(str[i + 1])) + { + char val[4] = { 0 }; + val[0] = (char)sdk_util::pick_number(str.c_str() + i + 1, &end, coding_util::NUM_FMT_OCT); + if (end - str.c_str() == i + 4 && *end == L'\\' && iswdigit(end[1])) + { + val[1] = (char)sdk_util::pick_number(str.c_str() + i + 5, &end, coding_util::NUM_FMT_OCT); + if (end - str.c_str() == i + 8) + { + int off = 8; + if ((val[0] & 0x20) && *end == L'\\' && iswdigit(end[1])) + { + val[2] = (char)sdk_util::pick_number(str.c_str() + i + 9, &end, coding_util::NUM_FMT_OCT); + off += 4; + } + if (end - str.c_str() == i + off) + { + std::wstring oct(L""); + coding_util::utf8_2_unicode(val, got_wstr, &oct); + conv += oct; + i += off - 1; + continue; + } + } + } + } + } + + conv.append(1, str[i]); + } + + str = std::move(conv); + } + + typedef struct _lang_id + { + int id; + int cp; + std::string utf8; + + bool operator==(int i) + { + return id == i; + } + bool operator<(struct _lang_id& r) + { + return id < r.id; + } + }LANGID; + typedef struct _lang_id_w + { + int id; + std::wstring unic; + + bool operator==(int i) + { + return id == i; + } + bool operator<(struct _lang_id& r) + { + return id < r.id; + } + }LANGIDW; + static LANGID g_reserve[] = { {1, 936, "\344\270\255\346\226\207\357\274\210\347\256\200\344\275\223\357\274\211"} // 中文(简体) + , {2, 950, "\344\270\255\346\226\207\357\274\210\347\271\201\344\275\223\357\274\211"} // 中文(繁体) + , {10, 20127, "\350\213\261\350\257\255"} // 英语 + , {20, 855, "\344\277\204\350\257\255"} // 俄语 + , {30, 863, "\346\263\225\350\257\255"} // 法语 + , {40, 1141, "\345\276\267\350\257\255"} // 德语 + , {50, 1144, "\346\204\217\345\244\247\345\210\251\350\257\255"} // 意大利语 + , {60, 932, "\346\227\245\350\257\255"} // 日语 + , {70, 949, "\351\237\251\346\226\207"} // 韩文 + }; + LANGID* lang_info_from_cp(int cp) + { + for (auto& v : g_reserve) + { + if (v.cp == cp) + return &v; + } + + return NULL; + } + LANGID* lang_info_from_ID(int id) + { + for (auto& v : g_reserve) + { + if (v.id == id) + return &v; + } + + return NULL; + } + LANGID* lang_info_from_name(const char* utf8) + { + for (auto& v : g_reserve) + { + if (v.utf8 == utf8) + return &v; + } + + return NULL; + } + int save_2_lang_pak(HWND owner, std::vector& items, int cp = 936) + { + uint32_t len = 0, + crc = 0, + ver = MAKELPARAM(0, 1), + cps[] = { cp, -1}, + self_id = g_reserve[0].id, + off = sizeof(len) + sizeof(crc) + sizeof(ver) + sizeof(cps) + sizeof(self_id), + *ptr = NULL, + repeat = 0, + tmp = 0; + LANGID *info = lang_info_from_cp(cp); + std::string cont(""), str(""); + std::vector known; + + if (!info) + return ERROR_NOT_SUPPORTED; + + self_id = info->id; + +#define APPEND_INT(str, n) \ + str += std::string((char*)&n, sizeof(n)) +#define APPEND_ARRAY(str, n) \ + str += std::string((char*)n, sizeof(n)) + + APPEND_INT(cont, len); + APPEND_INT(cont, crc); + APPEND_INT(cont, ver); + APPEND_ARRAY(cont, cps); + APPEND_INT(cont, self_id); + cont += std::string(info->utf8.c_str(), info->utf8.length() + 1); + if (cont.length() % 16) + cont.append(16 - (cont.length() % 16), '\0'); // ENDING address align 16 before + + len = cont.length(); + off = (items.size() + _countof(g_reserve) + 1) * sizeof(len) * 2; + for (const auto& v : g_reserve) + { + APPEND_INT(cont, v.id); + APPEND_INT(cont, off); + + std::vector::iterator it = std::find(items.begin(), items.end(), v.id); + if (it == items.end()) + { + str += std::string(v.utf8.c_str(), v.utf8.length() + 1); + off += v.utf8.length() + 1; + } + else + { + str += std::string(it->utf8.c_str(), it->utf8.length() + 1); + off += it->utf8.length() + 1; + } + known.push_back(v.id); + } + for (const auto& v : items) + { + if (std::find(known.begin(), known.end(), v.id) == known.end()) + { + APPEND_INT(cont, v.id); + APPEND_INT(cont, off); + str += std::string(v.utf8.c_str(), v.utf8.length() + 1); + off += v.utf8.length() + 1; + } + else + repeat++; + } + + len = -1; + APPEND_INT(cont, len); + APPEND_INT(cont, len); + for (int i = 0; i < repeat; ++i) + { + APPEND_INT(cont, len); + APPEND_INT(cont, len); + } + + cont += std::string(str.c_str(), str.length()); + ptr = (uint32_t*)&cont[0]; + *ptr++ = cont.length(); + *ptr = coding_util::crc_32((const void*)(ptr + 1), cont.length() - 8); + + file_util::PATHFILE file = { 0 }; + if (file_util::browser_file(owner, &file, L"Language pack(*.pak)\0\0", false)) + { + file_util::save_2_file(cont.c_str(), cont.length(), file.path); + } + + return 0; + } + + bool parse_pak_digest(uint8_t* data, int* id) + { + uint32_t ver = *(uint32_t*)data, + val = 0, + name_id = 0, + * cps = (uint32_t*)(data + sizeof(uint32_t) * 3); + std::vector code_pages; + std::wstring name(L""); + + if (id) + *id = *cps; + while (*cps != -1) + { + code_pages.push_back(*cps++); + } + if (code_pages.empty()) + return false; + + cps++; + name_id = *cps++; + val = (uint8_t*)cps - data; + coding_util::utf8_2_unicode((char*)data + val, got_wstr, &name); + + return name.length() ? true : false; + } + bool parse_pak(uint8_t* data, std::vector& items) + { + uint32_t ver = *(uint32_t*)data, + val = 0, + * cps = (uint32_t*)(data + sizeof(uint32_t) * 3); + + while (*cps++ != -1); + cps++; + val = (uint8_t*)cps - data; + val += strlen((char*)data + val) + 1; + val += 15; + val /= 16; + val *= 16; + + struct + { + uint32_t id; + uint32_t off; + }*go = nullptr; + *((void**)&go) = (void*)(data + val); + while (go->id != -1) + { + LANGIDW l; + l.id = go->id; + coding_util::utf8_2_unicode((char*)data + go->off + val, got_wstr, &l.unic); + items.push_back(l); + go++; + } + + return true; + } + bool load_lang_pak(const wchar_t* file, std::vector& items, int* id = NULL) + { + std::string cont(""), name(""); + bool ret = false; + FILE* src = _wfopen(file, L"rb"); + + if (src) + { + int len = 0; + uint8_t* buf = nullptr; + + fseek(src, 0, SEEK_END); + len = ftell(src); + fseek(src, 0, SEEK_SET); + if (len) + { + buf = new uint8_t[len + 4]; + if (buf) + { + memset(buf, 0, len + 4); + len = fread(buf, 1, len, src); + if (len == *(uint32_t*)buf && coding_util::crc_32(buf + sizeof(uint32_t) * 2, len - sizeof(uint32_t) * 2) == ((uint32_t*)buf)[1]) + { + cont = std::string((char*)buf, len); + } + delete[] buf; + } + } + fclose(src); + } + if (cont.length()) + { + parse_pak_digest((uint8_t*)&cont[0], id); + ret = parse_pak((uint8_t*)&cont[0], items); + } + + return ret; + } + + +} + +// CDlgLang 对话框 + +IMPLEMENT_DYNAMIC(CDlgLang, CDialogEx) + +CDlgLang::CDlgLang(CWnd* pParent /*=nullptr*/) + : CDialogEx(IDD_LANGUAGE, pParent) + , cur_cp_(936) +{ + std::vector langs; + + //sdk_util::load_lang_pak(L"D:\\boxroom\\Dingding\\chinese.pak", langs); + langs.clear(); +} + +CDlgLang::~CDlgLang() +{ +} + +void CDlgLang::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_COMBO1, lang_); + DDX_Control(pDX, IDC_LIST1, list_); +} +BOOL CDlgLang::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + int ind = 0; + list_.InsertColumn(ind++, TEXT("No."), 0, 48); + list_.InsertColumn(ind++, TEXT("ID"), 0, 60); + list_.InsertColumn(ind++, TEXT("Text"), 0, 350); + list_.SetExtendedStyle(list_.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_INFOTIP); + list_.ModifyStyle(0, LVS_SINGLESEL); + + for (const auto& v : sdk_util::g_reserve) + { + std::wstring unic(L""); + coding_util::utf8_2_unicode(v.utf8.c_str(), sdk_util::got_wstr, &unic); + ind = lang_.AddString(unic.c_str()); + lang_.SetItemData(ind, (DWORD_PTR)v.cp); + } + select_code_page(936); + + return TRUE; // return TRUE unless you set the focus to a control +} +bool CDlgLang::select_code_page(int cp) +{ + bool found = false; + + for (int i = 0; i < lang_.GetCount(); ++i) + { + if ((int)lang_.GetItemData(i) == cp) + { + lang_.SetCurSel(i); + found = true; + break; + } + } + + return found; +} +void CDlgLang::add_2_list(void* lang_list, int id, bool unic) +{ + if (unic) + { + std::vector* data = (std::vector*)lang_list; + + for (const auto& v : *data) + { + std::wstring text(L""); + int ind = list_.InsertItem(list_.GetItemCount(), std::to_wstring(list_.GetItemCount() + 1).c_str()); + + list_.SetItemText(ind, 1, std::to_wstring(v.id).c_str()); + list_.SetItemText(ind, 2, v.unic.c_str()); + } + } + else + { + std::vector* data = (std::vector*)lang_list; + + for (const auto& v : *data) + { + std::wstring text(L""); + int ind = list_.InsertItem(list_.GetItemCount(), std::to_wstring(list_.GetItemCount() + 1).c_str()); + + list_.SetItemText(ind, 1, std::to_wstring(v.id).c_str()); + coding_util::utf8_2_unicode(v.utf8.c_str(), sdk_util::got_wstr, &text); + list_.SetItemText(ind, 2, std::to_wstring(v.id).c_str()); + } + } +} +int CDlgLang::insert_item_2_list(const wchar_t* str, uint32_t id) +{ + int item = 0; + bool ok = false; + wchar_t buf[40] = { 0 }; + + for (; item < list_.GetItemCount(); ++item) + { + list_.GetItemText(item, 1, buf, _countof(buf) - 1); + if (_wtoi(buf) > id) + { + item = list_.InsertItem(item, std::to_wstring(item + 1).c_str()); + ok = true; + break; + } + } + if (ok) + { + for (int i = item + 1; i < list_.GetItemCount(); ++i) + list_.SetItemText(i, 0, std::to_wstring(i + 1).c_str()); + } + else + item = list_.InsertItem(list_.GetItemCount(), std::to_wstring(list_.GetItemCount() + 1).c_str()); + + list_.SetItemText(item, 1, std::to_wstring(id).c_str()); + list_.SetItemText(item, 2, str); + list_.EnsureVisible(item, FALSE); + list_.SetItemState(item, LVNI_FOCUSED | LVIS_SELECTED, LVNI_FOCUSED | LVIS_SELECTED); + GotoDlgCtrl(&list_); + + return item; +} +int CDlgLang::find_hz_ID(const wchar_t* hz) +{ + for (const auto& v : hz_) + { + if (v.hz == hz) + return v.id; + } + + return -1; +} +int CDlgLang::find_list_item_by_ID(int id) +{ + for (int i = 0; i < list_.GetItemCount(); ++i) + { + TCHAR val[40] = { 0 }; + list_.GetItemText(i, 1, val, _countof(val) - 1); + if (_ttoi(val) == id) + return i; + } + + return -1; +} +void CDlgLang::on_hz_pak_initialized(bool success) +{ + lang_.EnableWindow(success); + list_.EnableWindow(success); + GetDlgItem(IDC_BUTTON_SAVE)->EnableWindow(success); + GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(cur_cp_ == 936); +} +bool CDlgLang::find_repeat_in_vector(uint32_t val, void* param) +{ + std::vector* vec = (std::vector*)param; + + return std::find(vec->begin(), vec->end(), val) != vec->end(); +} +bool CDlgLang::find_repeat_in_list(uint32_t val, void* param) +{ + CListCtrl* lst = (CListCtrl*)param; + wchar_t buf[40] = { 0 }; + + for (int i = 0; i < lst->GetItemCount(); ++i) + { + lst->GetItemText(i, 1, buf, _countof(buf) - 1); + if (_wtoi(buf) == val) + return true; + } + + return false; +} + +BEGIN_MESSAGE_MAP(CDlgLang, CDialogEx) + ON_BN_CLICKED(IDC_BUTTON_INIT_ID, &CDlgLang::OnBnClickedButtonInitId) + ON_CBN_SELCHANGE(IDC_COMBO1, &CDlgLang::OnCbnSelchangeLanguage) + ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CDlgLang::OnNMDblclkList1) + ON_BN_CLICKED(IDC_BUTTON_SAVE, &CDlgLang::OnBnClickedButtonSave) + ON_BN_CLICKED(IDC_BUTTON_ADD, &CDlgLang::OnBnClickedButtonAdd) +END_MESSAGE_MAP() + + +// CDlgLang 消息处理程序 + + +void CDlgLang::OnBnClickedButtonInitId() +{ + // TODO: 在此添加控件通知处理程序代码 + file_util::PATHFILE file = { 0 }; + std::vector items; + + if (file_util::browser_file(m_hWnd, &file, L"Language Pack (*.pak)\0All Files (*.*)\0\0")) + { + hz_.clear(); + { + file_util::PATHFILE ext = { 0 }; + file_util::file_extension(file.path, &ext); + if (wcsicmp(ext.path, L"pak") == 0) + { + std::vector lans; + int id = 0; + + sdk_util::load_lang_pak(file.path, lans, &id); + if (id != 936) + { + ::MessageBoxW(m_hWnd, L"\u8BF7\u9009\u62E9\u201C\u4E2D\u6587\uFF08\u7B80\u4F53\uFF09\u201D\u7684\u8BED\u8A00\u5305\u4F5C\u4E3A\u521D\u59CB\u5316\u8BED\u8A00\u5305\uFF01", L"\u91CD\u65B0\u9009\u62E9", MB_OK | MB_ICONINFORMATION); + return; + } + cur_cp_ = id; + for (auto& v : lans) + { + HZMAP hm; + hm.id = v.id; + hm.hz = v.unic; + hz_.push_back(hm); + } + list_.DeleteAllItems(); + add_2_list(&lans, cur_cp_, true); + select_code_page(cur_cp_); + on_hz_pak_initialized(true); + return; + } + } + + std::string bom(""), utf8(""); + std::wstring cont(L""), line(L""), save(L""); + size_t pos = -1; + int cur = 0, next = 0; + std::vector ids; + + file_util::load_file(file.path, sdk_util::got_str, &bom); + coding_util::bom::to_unicode(bom.c_str(), bom.length(), sdk_util::got_wstr, &cont); + bom.clear(); + coding_util::pick_line(cont.c_str(), sdk_util::got_wstr, &line, &next); + while (next || !line.empty()) + { + std::wstring cpy(line + L"\r\n"); + + if (!line.empty()) + { + sdk_util::trim_left(line); + pos = line.find(L"//"); + if (pos) + { + pos = line.find(L"#define"); + if (pos == 0) + { + line.erase(0, 7); + sdk_util::trim_left(line); + pos = line.find(L" "); + if(pos == std::wstring::npos) + pos = line.find(L"\t"); + if (pos != std::wstring::npos) + { + std::wstring name = line.substr(0, pos); + line.erase(0, pos + 1); + sdk_util::trim_left(line); + if (line[0] == L'\"') + { + int bgn = 0, end = 0; + if (coding_util::pick_value(line.c_str(), L"\"", L"\"", &bgn, &end)) + { + line.erase(end + 1); + line.erase(0, bgn); + cpy.insert(0, L"// "); + sdk_util::convert_unicode(line); + bgn = sdk_util::make_string_id(line.c_str(), &CDlgLang::find_repeat_in_vector, &ids); + ids.push_back(bgn); + cpy += L"#define ID_" + name + L" " + std::to_wstring(bgn) + L"\r\n\r\n"; + + sdk_util::LANGID li; + li.id = bgn; + coding_util::unicode_2_utf8(line.c_str(), sdk_util::got_str, &li.utf8); + items.push_back(li); + + HZMAP hm; + hm.id = li.id; + hm.hz = line; + hz_.push_back(hm); + } + } + } + } + } + } + save += cpy; + cur += next; + line.clear(); + coding_util::pick_line(cont.c_str() + cur, sdk_util::got_wstr, &line, &next); + } + + coding_util::unicode_2_utf8(save.c_str(), sdk_util::got_str, &utf8); + save.clear(); + coding_util::bom::from_utf8(utf8.c_str(), utf8.length(), sdk_util::got_str, &bom); + utf8.clear(); + file_util::save_2_file(bom.c_str(), bom.length(), file.path); + + std::sort(items.begin(), items.end()); + list_.DeleteAllItems(); + cur_cp_ = 936; + add_2_list(&items, cur_cp_, false); + select_code_page(cur_cp_); + on_hz_pak_initialized(true); + //sdk_util::save_2_lang_pak(m_hWnd, items); + } +} +void CDlgLang::OnCbnSelchangeLanguage() +{ + file_util::PATHFILE file = { 0 }; + int lang_cp = (int)lang_.GetItemData(lang_.GetCurSel()); + + if (file_util::browser_file(m_hWnd, &file)) + { + { + file_util::PATHFILE ext = { 0 }; + file_util::file_extension(file.path, &ext); + if (wcsicmp(ext.path, L"pak") == 0) + { + std::vector lans; + int cp = 0; + + sdk_util::load_lang_pak(file.path, lans, &cp); + if (cp != lang_cp) + { + sdk_util::LANGID* inf = sdk_util::lang_info_from_cp(lang_cp); + std::wstring unic(L""); + + coding_util::utf8_2_unicode(inf->utf8.c_str(), sdk_util::got_wstr, &unic); + unic.insert(0, L"\u8BF7\u9009\u62E9\u201C"); + unic += L"\u201D\u8BED\u8A00\u5305\uFF01"; + ::MessageBoxW(m_hWnd, unic.c_str(), L"Error", MB_OK | MB_ICONSTOP); + select_code_page(cur_cp_); + GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(cur_cp_ == 936); + return; + } + list_.DeleteAllItems(); + cur_cp_ = cp; + add_2_list(&lans, cur_cp_, true); + select_code_page(cur_cp_); + GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(cur_cp_ == 936); + return; + } + } + + ::MessageBoxW(m_hWnd, L"纯文本翻译对照,请以中文(简体)语言在第一列(如有空格请加英文双引号),其它语言为空格以后的第二列。", L"提示", MB_OK | MB_ICONINFORMATION); + + std::string bom(""); + std::wstring cont(L""), line(L""), hz(L""), lan(L""); + size_t pos = -1; + int cur = 1, next = -1; + std::vector ids; + std::map lost; + + cur_cp_ = lang_cp; + file_util::load_file(file.path, sdk_util::got_str, &bom); + coding_util::bom::to_unicode(bom.c_str(), bom.length(), sdk_util::got_wstr, &cont); + bom.clear(); + while (next || !line.empty()) + { + cur += next; + line.clear(); + coding_util::pick_line(cont.c_str() + cur, sdk_util::got_wstr, &line, &next); + if (line.empty()) + continue; + + sdk_util::trim_left(line); + if (line.empty()) + continue; + + if (line[0] == L'\"') + { + int bgn = 0, end = 0; + coding_util::pick_value(line.c_str(), L"\"", L"\"", &bgn, &end); + if (end <= bgn) + continue; + + hz = line.substr(bgn, end - bgn + 1); + line.erase(0, end + 2); + } + else + { + pos = line.find(L" "); + if (pos > line.find(L"\t")) + pos = line.find(L"\t"); + if (pos == std::wstring::npos) + continue; + hz = line.substr(0, pos); + line.erase(0, pos + 1); + } + sdk_util::trim_left(line); + if (line.empty()) + continue; + + lan = line; + + int id = find_hz_ID(hz.c_str()), + item = id == -1 ? -1 : find_list_item_by_ID(id); + if (item == -1) + lost[hz] = lan; + else + list_.SetItemText(item, 2, lan.c_str()); + } + + cont.clear(); + if (lost.size()) + { + for (auto& v : lost) + cont += L" " + v.first + L" <---> " + v.second + L"\r\n"; + file_util::set_clipboard(cont.c_str(), cont.length() * 2, CF_UNICODETEXT); + cont.insert(0, L"下列语言条目,没有找到中文原版,请在中文(简体)语言包中补充完整(内容已经拷贝到剪贴板):\r\n"); + ::MessageBoxW(m_hWnd, cont.c_str(), L"Lost", MB_OK | MB_ICONERROR); + } + } + else if (lang_cp == 936) + { + cur_cp_ = lang_cp; + list_.DeleteAllItems(); + lang_cp = 1; + for (const auto& v : hz_) + { + int item = list_.InsertItem(list_.GetItemCount(), std::to_wstring(lang_cp++).c_str()); + list_.SetItemText(item, 1, std::to_wstring(v.id).c_str()); + list_.SetItemText(item, 2, v.hz.c_str()); + } + } + GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(cur_cp_ == 936); +} +void CDlgLang::OnNMDblclkList1(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast(pNMHDR); + *pResult = 0; + + // TODO: 在此添加控件通知处理程序代码 + POINT pos = { 0 }; + int item = -1; + + GetCursorPos(&pos); + list_.ScreenToClient(&pos); + item = list_.HitTest(pos); + if (item != -1) + { + int size = 4 * 1024; + wchar_t* buf = new wchar_t[size]; + CDlgInput dlg; + + memset(buf, 0, size * sizeof(buf[0])); + list_.GetItemText(item, 2, buf, size - 1); + dlg.value_ = buf; + dlg.type_ = CDlgInput::INPUT_FOR_STRING; + delete[] buf; + if (dlg.DoModal() == IDOK) + { + list_.SetItemText(item, 2, dlg.value_); + } + } +} + + +void CDlgLang::OnBnClickedButtonSave() +{ + // TODO: 在此添加控件通知处理程序代码 + std::vector items; + int cp = (int)lang_.GetItemData(lang_.GetCurSel()), size = 1024; + wchar_t* buf = new wchar_t[size]; + + memset(buf, 0, size * sizeof(buf[0])); + for (int i = 0; i < list_.GetItemCount(); ++i) + { + sdk_util::LANGID lan; + + list_.GetItemText(i, 1, buf, size - 1); + lan.id = _wtoi(buf); + list_.GetItemText(i, 2, buf, size - 1); + coding_util::unicode_2_utf8(buf, sdk_util::got_str, &lan.utf8); + lan.cp = cp; + items.push_back(std::move(lan)); + } + delete[] buf; + + if (items.empty()) + { + MessageBox(TEXT("No items need save")); + return; + } + + sdk_util::save_2_lang_pak(m_hWnd, items, cp); +} + + +void CDlgLang::OnBnClickedButtonAdd() +{ + // TODO: 在此添加控件通知处理程序代码 + CDlgInput dlg; + + dlg.type_ = CDlgInput::INPUT_FOR_STRING; + if (dlg.DoModal() == IDOK) + { + HZMAP h; + + h.hz = dlg.value_.GetBuffer(); + h.id = sdk_util::make_string_id(h.hz.c_str(), &CDlgLang::find_repeat_in_list, &list_); + dlg.value_.ReleaseBuffer(); + + insert_item_2_list(h.hz.c_str(), h.id); + hz_.push_back(h); + } +} diff --git a/tools/apps/hgjson/CDlgLang.h b/tools/apps/hgjson/CDlgLang.h new file mode 100644 index 0000000..7cedffb --- /dev/null +++ b/tools/apps/hgjson/CDlgLang.h @@ -0,0 +1,59 @@ +#pragma once +#include "afxdialogex.h" +#include +#include + +// CDlgLang 对话框 + +class CDlgLang : public CDialogEx +{ + DECLARE_DYNAMIC(CDlgLang) + +public: + CDlgLang(CWnd* pParent = nullptr); // 标准构造函数 + virtual ~CDlgLang(); + +// 对话框数据 + enum { IDD = IDD_LANGUAGE }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 + virtual BOOL OnInitDialog(); + + bool select_code_page(int cp); + void add_2_list(void* lang_list, int id, bool unic); + int insert_item_2_list(const wchar_t* str, uint32_t id); + int find_hz_ID(const wchar_t* hz); + int find_list_item_by_ID(int id); + void on_hz_pak_initialized(bool success); + + static bool find_repeat_in_vector(uint32_t val, void* param); + static bool find_repeat_in_list(uint32_t val, void* param); + + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnBnClickedButtonInitId(); + afx_msg void OnCbnSelchangeLanguage(); + afx_msg void OnNMDblclkList1(NMHDR* pNMHDR, LRESULT* pResult); + CComboBox lang_; + CListCtrl list_; + int cur_cp_; + + typedef struct _base_map + { + int id; + std::wstring hz; + + bool operator==(int i) + { + return id == i; + } + bool operator==(const wchar_t* t) + { + return hz == t; + } + }HZMAP; + std::vector hz_; + afx_msg void OnBnClickedButtonSave(); + afx_msg void OnBnClickedButtonAdd(); +}; diff --git a/tools/apps/hgjson/CDlgMain.cpp b/tools/apps/hgjson/CDlgMain.cpp new file mode 100644 index 0000000..a147d48 --- /dev/null +++ b/tools/apps/hgjson/CDlgMain.cpp @@ -0,0 +1,104 @@ +// CDlgMain.cpp: 实现文件 +// + +#include "stdafx.h" +#include "hgjson.h" +#include "afxdialogex.h" +#include "CDlgMain.h" +#include "resource.h" + +#include "hgjsonDlg.h" +#include "CDlgLang.h" + +// CDlgMain 对话框 + +IMPLEMENT_DYNAMIC(CDlgMain, CDialogEx) + +CDlgMain::CDlgMain(CWnd* pParent /*=nullptr*/) + : CDialogEx(IDD_MAIN, pParent) +{ +#ifndef _WIN32_WCE + EnableActiveAccessibility(); +#endif + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); + +} + +CDlgMain::~CDlgMain() +{ +} + +void CDlgMain::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_TAB1, tab_); +} +BOOL CDlgMain::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + LRESULT lret = 0; + CDialogEx* page = new ChgjsonDlg(this); + page->Create(ChgjsonDlg::IDD, this); + insert_page(page, L"\u626B\u63CF\u4EEA\u914D\u7F6E"); + + page = new CDlgLang(this); + page->Create(CDlgLang::IDD, this); + insert_page(page, L"\u8BED\u8A00\u5305\u5236\u4F5C"); + + tab_.SetCurSel(0); + OnTcnSelchangeTab1(NULL, &lret); + + return TRUE; // return TRUE unless you set the focus to a control +} +void CDlgMain::insert_page(CDialogEx* page, const wchar_t* title) +{ + RECT r = { 0 }; + int ind = 0; + TCITEM item = { 0 }; + + GetDlgItem(IDC_STATIC_CHILD)->GetWindowRect(&r); + ScreenToClient(&r); + page->MoveWindow(&r); + page->ShowWindow(SW_HIDE); + + ind = tab_.InsertItem(tab_.GetItemCount(), title); + item.lParam = (LPARAM)page; + item.mask = TCIF_PARAM; + tab_.SetItem(ind, &item); +} + +BEGIN_MESSAGE_MAP(CDlgMain, CDialogEx) + ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, &CDlgMain::OnTcnSelchangeTab1) + ON_NOTIFY(TCN_SELCHANGING, IDC_TAB1, &CDlgMain::OnTcnSelchangingTab1) +END_MESSAGE_MAP() + + +// CDlgMain 消息处理程序 +void CDlgMain::OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult) +{ + // TODO: 在此添加控件通知处理程序代码 + *pResult = 0; + TCITEM item = { 0 }; + + item.mask = TCIF_PARAM; + tab_.GetItem(tab_.GetCurSel(), &item); + ((CWnd*)item.lParam)->ShowWindow(SW_SHOW); +} + +void CDlgMain::OnTcnSelchangingTab1(NMHDR* pNMHDR, LRESULT* pResult) +{ + // TODO: 在此添加控件通知处理程序代码 + *pResult = 0; + + TCITEM item = { 0 }; + + item.mask = TCIF_PARAM; + tab_.GetItem(tab_.GetCurSel(), &item); + ((CWnd*)item.lParam)->ShowWindow(SW_HIDE); +} diff --git a/tools/apps/hgjson/CDlgMain.h b/tools/apps/hgjson/CDlgMain.h new file mode 100644 index 0000000..861290e --- /dev/null +++ b/tools/apps/hgjson/CDlgMain.h @@ -0,0 +1,30 @@ +#pragma once +#include "afxdialogex.h" + + +// CDlgMain 对话框 + +class CDlgMain : public CDialogEx +{ + DECLARE_DYNAMIC(CDlgMain) + +public: + CDlgMain(CWnd* pParent = nullptr); // 标准构造函数 + virtual ~CDlgMain(); + +// 对话框数据 + enum { IDD = IDD_MAIN }; + +protected: + HICON m_hIcon; + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 + virtual BOOL OnInitDialog(); + + void insert_page(CDialogEx* page, const wchar_t* title); + + DECLARE_MESSAGE_MAP() +public: + CTabCtrl tab_; + afx_msg void OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnTcnSelchangingTab1(NMHDR* pNMHDR, LRESULT* pResult); +}; diff --git a/tools/apps/hgjson/DlgInput.cpp b/tools/apps/hgjson/DlgInput.cpp index 587f5ac..0a9c387 100644 --- a/tools/apps/hgjson/DlgInput.cpp +++ b/tools/apps/hgjson/DlgInput.cpp @@ -13,7 +13,7 @@ IMPLEMENT_DYNAMIC(CDlgInput, CDialogEx) CDlgInput::CDlgInput(CWnd* pParent /*=NULL*/) : CDialogEx(CDlgInput::IDD, pParent) - , value_(_T("")) + , value_(_T("")), type_(INPUT_FOR_NAME) { } @@ -27,6 +27,15 @@ void CDlgInput::DoDataExchange(CDataExchange* pDX) CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT1, value_); } +BOOL CDlgInput::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + + return TRUE; // return TRUE unless you set the focus to a control +} BEGIN_MESSAGE_MAP(CDlgInput, CDialogEx) @@ -41,16 +50,27 @@ END_MESSAGE_MAP() void CDlgInput::OnBnClickedOk() { // TODO: Add your control notification handler code here - wchar_t text[128] = { 0 }; - - ::GetDlgItemTextW(m_hWnd, IDC_EDIT1, text, _countof(text) - 1); - for (size_t i = 0; i < used_names_.size(); ++i) + UpdateData(); + if (value_.IsEmpty()) { - if (used_names_[i] == text) + ::MessageBoxW(m_hWnd, L"", L"Error", MB_OK | MB_ICONSTOP); + GotoDlgCtrl(GetDlgItem(IDC_EDIT1)); + return; + } + + if (type_ == INPUT_FOR_NAME) + { + wchar_t text[128] = { 0 }; + + ::GetDlgItemTextW(m_hWnd, IDC_EDIT1, text, _countof(text) - 1); + for (size_t i = 0; i < used_names_.size(); ++i) { - std::wstring t(used_names_[i] + L" is already used, choose another name, plz."); - ::MessageBoxW(m_hWnd, t.c_str(), L"Sorry", MB_OK); - return; + if (used_names_[i] == text) + { + std::wstring t(used_names_[i] + L" is already used, choose another name, plz."); + ::MessageBoxW(m_hWnd, t.c_str(), L"Sorry", MB_OK); + return; + } } } diff --git a/tools/apps/hgjson/DlgInput.h b/tools/apps/hgjson/DlgInput.h index c3d4f1b..7277479 100644 --- a/tools/apps/hgjson/DlgInput.h +++ b/tools/apps/hgjson/DlgInput.h @@ -20,9 +20,12 @@ public: protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); DECLARE_MESSAGE_MAP() public: CString value_; + enum { INPUT_FOR_NAME, INPUT_FOR_STRING, }; + int type_; afx_msg void OnBnClickedOk(); }; diff --git a/tools/apps/hgjson/hgjson.cpp b/tools/apps/hgjson/hgjson.cpp index b4c313c..3c60e09 100644 --- a/tools/apps/hgjson/hgjson.cpp +++ b/tools/apps/hgjson/hgjson.cpp @@ -4,7 +4,7 @@ #include "stdafx.h" #include "hgjson.h" -#include "hgjsonDlg.h" +#include "CDlgMain.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -39,6 +39,7 @@ ChgjsonApp theApp; BOOL ChgjsonApp::InitInstance() { + AfxOleInit(); // InitCommonControlsEx() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. @@ -70,7 +71,7 @@ BOOL ChgjsonApp::InitInstance() // such as the name of your company or organization SetRegistryKey(_T("Local AppWizard-Generated Applications")); - ChgjsonDlg dlg; + CDlgMain dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) diff --git a/tools/apps/hgjson/hgjson.rc b/tools/apps/hgjson/hgjson.rc index 880020c..3b2e91e 100644 Binary files a/tools/apps/hgjson/hgjson.rc and b/tools/apps/hgjson/hgjson.rc differ diff --git a/tools/apps/hgjson/hgjson.vcxproj b/tools/apps/hgjson/hgjson.vcxproj index ecc4c3f..bc1aa69 100644 --- a/tools/apps/hgjson/hgjson.vcxproj +++ b/tools/apps/hgjson/hgjson.vcxproj @@ -44,15 +44,17 @@ true - $(SolutionDir)..\sdk\Include\;$(SolutionDir)..\..\..\sdk\Include\;$(IncludePath) - $(SolutionDir)..\sdk\lib\;$(LibraryPath) + $(ProjectDir)..\..\sdk\Include\;$(ProjectDir)..\..\..\..\sdk\Include\;$(IncludePath) + $(ProjectDir)..\..\sdk\lib\;$(LibraryPath) $(OutDir)$(ProjectName)\ + $(ProjectDir)..\..\solution\$(Configuration)\ false - $(SolutionDir)..\sdk\Include\;$(SolutionDir)..\..\..\sdk\Include\;$(IncludePath) - $(SolutionDir)..\sdk\lib\;$(LibraryPath) + $(ProjectDir)..\..\sdk\Include\;$(ProjectDir)..\..\..\..\sdk\Include\;$(IncludePath) + $(ProjectDir)..\..\sdk\lib\;$(LibraryPath) $(OutDir)$(ProjectName)\ + $(ProjectDir)..\..\solution\$(Configuration)\ @@ -111,6 +113,8 @@ + + @@ -123,6 +127,8 @@ NotUsing NotUsing + + diff --git a/tools/apps/hgjson/hgjson.vcxproj.filters b/tools/apps/hgjson/hgjson.vcxproj.filters index 6df8dc7..68c66f1 100644 --- a/tools/apps/hgjson/hgjson.vcxproj.filters +++ b/tools/apps/hgjson/hgjson.vcxproj.filters @@ -39,6 +39,12 @@ Header Files + + Header Files + + + Header Files + @@ -56,6 +62,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/tools/apps/hgjson/hgjsonDlg.cpp b/tools/apps/hgjson/hgjsonDlg.cpp index b1dc9f7..44d3c88 100644 --- a/tools/apps/hgjson/hgjsonDlg.cpp +++ b/tools/apps/hgjson/hgjsonDlg.cpp @@ -5899,7 +5899,6 @@ ChgjsonDlg::ChgjsonDlg(CWnd* pParent /*=NULL*/) , show_list_tooltips_(true) { std::string py(hz_2_py::getLetter("ɫģʽ", true)); - m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void ChgjsonDlg::DoDataExchange(CDataExchange* pDX) @@ -6018,8 +6017,6 @@ BOOL ChgjsonDlg::OnInitDialog() // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog - SetIcon(m_hIcon, TRUE); // Set big icon - SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD); @@ -7091,24 +7088,24 @@ void ChgjsonDlg::filter_tree_item(HTREEITEM item, const std::vector& fil void ChgjsonDlg::OnPaint() { - if (IsIconic()) - { - CPaintDC dc(this); // device context for painting + //if (IsIconic()) + //{ + // CPaintDC dc(this); // device context for painting - SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); + // SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); - // Center icon in client rectangle - int cxIcon = GetSystemMetrics(SM_CXICON); - int cyIcon = GetSystemMetrics(SM_CYICON); - CRect rect; - GetClientRect(&rect); - int x = (rect.Width() - cxIcon + 1) / 2; - int y = (rect.Height() - cyIcon + 1) / 2; + // // Center icon in client rectangle + // int cxIcon = GetSystemMetrics(SM_CXICON); + // int cyIcon = GetSystemMetrics(SM_CYICON); + // CRect rect; + // GetClientRect(&rect); + // int x = (rect.Width() - cxIcon + 1) / 2; + // int y = (rect.Height() - cyIcon + 1) / 2; - // Draw the icon - dc.DrawIcon(x, y, m_hIcon); - } - else + // // Draw the icon + // dc.DrawIcon(x, y, m_hIcon); + //} + //else { CDialogEx::OnPaint(); } @@ -7118,7 +7115,7 @@ void ChgjsonDlg::OnPaint() // the minimized window. HCURSOR ChgjsonDlg::OnQueryDragIcon() { - return static_cast(m_hIcon); + return NULL;// static_cast(m_hIcon); } void ChgjsonDlg::OnPaste() diff --git a/tools/apps/hgjson/hgjsonDlg.h b/tools/apps/hgjson/hgjsonDlg.h index 4c4b99f..ba83e40 100644 --- a/tools/apps/hgjson/hgjsonDlg.h +++ b/tools/apps/hgjson/hgjsonDlg.h @@ -98,7 +98,6 @@ public: // Implementation protected: - HICON m_hIcon; CMenu tree_menu_; CMenu func_menu_; CImageList tree_img_; diff --git a/tools/apps/hgjson/resource.h b/tools/apps/hgjson/resource.h index 460bd7b..a6f521e 100644 Binary files a/tools/apps/hgjson/resource.h and b/tools/apps/hgjson/resource.h differ diff --git a/tools/sdk/include/coding/coding.h b/tools/sdk/include/coding/coding.h index 1019c61..1e05ca8 100644 --- a/tools/sdk/include/coding/coding.h +++ b/tools/sdk/include/coding/coding.h @@ -199,6 +199,9 @@ namespace coding_util PORT_API(int) aes_encoding(const char* plain, size_t len, const char *iv, const char* pwd, inter_module_data::set_data result, void* param, int iv_len = 16, int pwd_len = 16, _aes_type_ type = AES_CBC); PORT_API(int) aes_decoding(const char* cipher, size_t len, const char *iv, const char* pwd, inter_module_data::set_data result, void* param, int iv_len = 16, int pwd_len = 16, _aes_type_ type = AES_CBC); + // CRC ... + PORT_API(UINT) crc_32(const void* data, size_t bytes, UINT prev_crc = 0); + // return 0 if success PORT_API(int) lzw_encoding(const char* plain, size_t len, inter_module_data::set_data result, void* param); PORT_API(int) lzw_decoding(const char* cipher, size_t len, inter_module_data::set_data result, void* param); diff --git a/tools/sdk/include/utility/known_file.h b/tools/sdk/include/utility/known_file.h index 1ebc300..bc711fc 100644 Binary files a/tools/sdk/include/utility/known_file.h and b/tools/sdk/include/utility/known_file.h differ diff --git a/tools/sdk/lib/Debug/base_util.lib b/tools/sdk/lib/Debug/base_util.lib index e23d99d..850d7a4 100644 Binary files a/tools/sdk/lib/Debug/base_util.lib and b/tools/sdk/lib/Debug/base_util.lib differ diff --git a/tools/sdk/lib/Release/base_util.lib b/tools/sdk/lib/Release/base_util.lib index 485e366..5bbcb59 100644 Binary files a/tools/sdk/lib/Release/base_util.lib and b/tools/sdk/lib/Release/base_util.lib differ