From: Mark Jansen Date: Sat, 18 Mar 2017 13:01:18 +0000 (+0000) Subject: [APPLICATIONS/SYSUTILS] Add a font substitutes editor. Patch by Katayama Hirofumi... X-Git-Tag: ReactOS-0.4.5~246 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=fd3b70fc42ae4caa068d1270df3c250e4eb58d1b [APPLICATIONS/SYSUTILS] Add a font substitutes editor. Patch by Katayama Hirofumi MZ. CORE-12749 #resolve #comment Thanks! svn path=/trunk/; revision=74187 --- diff --git a/rosapps/applications/sysutils/CMakeLists.txt b/rosapps/applications/sysutils/CMakeLists.txt index 30bd384de85..ec5888deb7c 100644 --- a/rosapps/applications/sysutils/CMakeLists.txt +++ b/rosapps/applications/sysutils/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(chklib) add_subdirectory(ctm) +add_subdirectory(fontsub) add_subdirectory(gettype) add_subdirectory(kill) add_subdirectory(logevent) diff --git a/rosapps/applications/sysutils/fontsub/CMakeLists.txt b/rosapps/applications/sysutils/fontsub/CMakeLists.txt new file mode 100644 index 00000000000..09e1c733ca9 --- /dev/null +++ b/rosapps/applications/sysutils/fontsub/CMakeLists.txt @@ -0,0 +1,16 @@ +# FontSub by Katayama Hirofumi MZ +# +# To the extent possible under law, the person who associated CC0 with +# FontSub has waived all copyright and related or neighboring rights +# to FontSub. +# +# You should have received a copy of the CC0 legalcode along with this +# work. If not, see . + +set_cpp(WITH_RUNTIME WITH_STL WITH_EXCEPTIONS) + +add_executable(fontsubedit fontsub.cpp fontsub_res.rc) +set_module_type(fontsubedit win32gui UNICODE) +add_importlibs(fontsubedit advapi32 comctl32 comdlg32 shell32 gdi32 user32 msvcrt kernel32) +set_target_properties(fontsubedit PROPERTIES OUTPUT_NAME "fontsub") +add_cd_file(TARGET fontsubedit DESTINATION reactos/system32 FOR all) diff --git a/rosapps/applications/sysutils/fontsub/License.txt b/rosapps/applications/sysutils/fontsub/License.txt new file mode 100644 index 00000000000..6ca207ef004 --- /dev/null +++ b/rosapps/applications/sysutils/fontsub/License.txt @@ -0,0 +1,122 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + diff --git a/rosapps/applications/sysutils/fontsub/down.bmp b/rosapps/applications/sysutils/fontsub/down.bmp new file mode 100644 index 00000000000..13ba2d3d9de Binary files /dev/null and b/rosapps/applications/sysutils/fontsub/down.bmp differ diff --git a/rosapps/applications/sysutils/fontsub/fontsub.cpp b/rosapps/applications/sysutils/fontsub/fontsub.cpp new file mode 100644 index 00000000000..5345bea0dcc --- /dev/null +++ b/rosapps/applications/sysutils/fontsub/fontsub.cpp @@ -0,0 +1,1603 @@ +// FontSub by Katayama Hirofumi MZ +// +// To the extent possible under law, the person who associated CC0 with +// FontSub has waived all copyright and related or neighboring rights +// to FontSub. +// +// You should have received a copy of the CC0 legalcode along with this +// work. If not, see . + + +#include +#include +#include +#include +#include // for std::vector +#include // for std::set +#include // for std::basic_string +#include // for std::sort +#include +#include +#include +#include "resource.h" + + +#define NAME_COLUMN_WIDTH 250 +#define SUB_COLUMN_WIDTH 250 +#define MAX_STRING 120 + +#ifndef _countof + #define _countof(array) (sizeof(array) / sizeof(array[0])) +#endif + +typedef std::wstring STRING; + +struct ITEM +{ + STRING m_Name, m_Substitute; + BYTE m_CharSet1, m_CharSet2; + ITEM(const STRING& Name, const STRING& Substitute, + BYTE CharSet1, BYTE CharSet2) + : m_Name(Name), m_Substitute(Substitute), + m_CharSet1(CharSet1), m_CharSet2(CharSet2) { } +}; + +/* global variables */ +HINSTANCE g_hInstance = NULL; +HWND g_hMainWnd = NULL; +HICON g_hIcon = NULL; +HWND g_hListView = NULL; +BOOL g_bModified = FALSE; +BOOL g_bNeedsReboot = FALSE; +INT g_iItem = 0; + +LPCWSTR g_pszClassName = L"ReactOS Font Substitutes Editor"; +LPCWSTR g_pszFileHeader = L"Windows Registry Editor Version 5.00"; + +WCHAR g_szTitle[MAX_STRING]; +WCHAR g_szNameHead[MAX_STRING]; +WCHAR g_szSubstituteHead[MAX_STRING]; + +INT g_iSortColumn = 0; +BOOL g_bSortAscendant = TRUE; + +LPCWSTR g_pszKey = + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes"; + +typedef std::set FONTNAMESET; +typedef std::vector ITEMVECTOR; + +FONTNAMESET g_Names; +ITEMVECTOR g_Items; +STRING g_strFontName; +STRING g_strSubstitute; +BYTE g_CharSet1 = DEFAULT_CHARSET; +BYTE g_CharSet2 = DEFAULT_CHARSET; + +typedef struct CHARSET_ENTRY +{ + BYTE CharSet; + LPCWSTR DisplayName; +} CHARSET_ENTRY; + +CHARSET_ENTRY g_CharSetList[] = +{ + { DEFAULT_CHARSET, L"DEFAULT_CHARSET (1)" }, + { ANSI_CHARSET, L"ANSI_CHARSET (0)" }, + { SYMBOL_CHARSET, L"SYMBOL_CHARSET (2)" }, + { SHIFTJIS_CHARSET, L"SHIFTJIS_CHARSET (128)" }, + { HANGUL_CHARSET, L"HANGUL_CHARSET (129)" }, + { GB2312_CHARSET, L"GB2312_CHARSET (134)" }, + { CHINESEBIG5_CHARSET, L"CHINESEBIG5_CHARSET (136)" }, + { OEM_CHARSET, L"OEM_CHARSET (255)" }, + { JOHAB_CHARSET, L"JOHAB_CHARSET (130)" }, + { HEBREW_CHARSET, L"HEBREW_CHARSET (177)" }, + { ARABIC_CHARSET, L"ARABIC_CHARSET (178)" }, + { GREEK_CHARSET, L"GREEK_CHARSET (161)" }, + { TURKISH_CHARSET, L"TURKISH_CHARSET (162)" }, + { VIETNAMESE_CHARSET, L"VIETNAMESE_CHARSET (163)" }, + { THAI_CHARSET, L"THAI_CHARSET (222)" }, + { EASTEUROPE_CHARSET, L"EASTEUROPE_CHARSET (238)" }, + { RUSSIAN_CHARSET, L"RUSSIAN_CHARSET (204)" }, + { MAC_CHARSET, L"MAC_CHARSET (77)" }, + { BALTIC_CHARSET, L"BALTIC_CHARSET (186)" } +}; +const WCHAR g_LongestName[] = L"CHINESEBIG5_CHARSET (136)"; + +static void trim(STRING& str) +{ + static const WCHAR Spaces[] = L" \t\r\n"; + size_t i = str.find_first_not_of(Spaces); + size_t j = str.find_last_not_of(Spaces); + if (i == STRING::npos || j == STRING::npos) + { + str.clear(); + } + else + { + str = str.substr(i, j - i + 1); + } +} + +static int CALLBACK +EnumFontFamExProc(const ENUMLOGFONTW *pelf, + const NEWTEXTMETRICW *pntm, + int FontType, + LPARAM lParam) +{ + switch (pelf->elfFullName[0]) + { + case UNICODE_NULL: case L'@': + break; + default: + g_Names.insert((const WCHAR *)pelf->elfFullName); + } + switch (pelf->elfLogFont.lfFaceName[0]) + { + case UNICODE_NULL: case L'@': + break; + default: + g_Names.insert(pelf->elfLogFont.lfFaceName); + } + return 1; +} + +BOOL DoLoadNames(void) +{ + g_Names.clear(); + + LOGFONTW lf; + ZeroMemory(&lf, sizeof(lf)); + lf.lfCharSet = DEFAULT_CHARSET; + + HDC hDC = CreateCompatibleDC(NULL); + EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontFamExProc, 0, 0); + DeleteDC(hDC); + + return !g_Names.empty(); +} + +inline bool ItemCompareByNameAscend(const ITEM& Item1, const ITEM& Item2) +{ + return Item1.m_Name < Item2.m_Name; +} + +inline bool ItemCompareByNameDescend(const ITEM& Item1, const ITEM& Item2) +{ + return Item1.m_Name > Item2.m_Name; +} + +inline bool ItemCompareBySubAscend(const ITEM& Item1, const ITEM& Item2) +{ + return Item1.m_Substitute < Item2.m_Substitute; +} + +inline bool ItemCompareBySubDescend(const ITEM& Item1, const ITEM& Item2) +{ + return Item1.m_Substitute > Item2.m_Substitute; +} + +void DoSort(INT iColumn, BOOL bAscendant = TRUE) +{ + LV_COLUMN Column; + ZeroMemory(&Column, sizeof(Column)); + Column.mask = LVCF_IMAGE | LVCF_SUBITEM; + Column.iImage = 2; + Column.iSubItem = 0; + ListView_SetColumn(g_hListView, 0, &Column); + Column.iSubItem = 1; + ListView_SetColumn(g_hListView, 1, &Column); + + switch (iColumn) + { + case 0: + Column.iSubItem = 0; + if (bAscendant) + { + std::sort(g_Items.begin(), g_Items.end(), + ItemCompareByNameAscend); + Column.iImage = 0; + ListView_SetColumn(g_hListView, 0, &Column); + } + else + { + std::sort(g_Items.begin(), g_Items.end(), + ItemCompareByNameDescend); + Column.iImage = 1; + ListView_SetColumn(g_hListView, 0, &Column); + } + break; + case 1: + Column.iSubItem = 1; + if (bAscendant) + { + std::sort(g_Items.begin(), g_Items.end(), + ItemCompareBySubAscend); + Column.iImage = 0; + ListView_SetColumn(g_hListView, 1, &Column); + } + else + { + std::sort(g_Items.begin(), g_Items.end(), + ItemCompareBySubDescend); + Column.iImage = 1; + ListView_SetColumn(g_hListView, 1, &Column); + } + break; + } + g_iSortColumn = iColumn; + g_bSortAscendant = bAscendant; + InvalidateRect(g_hListView, NULL, TRUE); +} + +void LV_AddItems(HWND hwnd) +{ + ListView_DeleteAllItems(hwnd); + + LV_ITEM Item; + ZeroMemory(&Item, sizeof(Item)); + Item.mask = LVIF_PARAM; + + const INT Count = INT(g_Items.size()); + for (INT i = 0; i < Count; ++i) + { + Item.iItem = i; + Item.iSubItem = 0; + Item.lParam = i; + ListView_InsertItem(hwnd, &Item); + + Item.iItem = i; + Item.iSubItem = 1; + Item.lParam = i; + ListView_InsertItem(hwnd, &Item); + } +} + +BOOL DoLoadItems(void) +{ + ITEMVECTOR Items; + + HKEY hKey = NULL; + RegOpenKeyExW(HKEY_LOCAL_MACHINE, g_pszKey, 0, KEY_READ, &hKey); + if (hKey == NULL) + return FALSE; + + WCHAR szName[MAX_STRING], szValue[MAX_STRING]; + DWORD cbName, cbValue; + for (DWORD dwIndex = 0; ; ++dwIndex) + { + cbName = sizeof(szName); + cbValue = sizeof(szValue); + LONG Error = RegEnumValueW(hKey, dwIndex, szName, &cbName, + NULL, NULL, (LPBYTE)szValue, &cbValue); + if (Error != ERROR_SUCCESS) + break; + + BYTE CharSet1 = DEFAULT_CHARSET, CharSet2 = DEFAULT_CHARSET; + LPWSTR pch; + + pch = wcsrchr(szName, L','); + if (pch) + { + *pch = 0; + CharSet1 = (BYTE)_wtoi(pch + 1); + } + + pch = wcsrchr(szValue, L','); + if (pch) + { + *pch = 0; + CharSet2 = (BYTE)_wtoi(pch + 1); + } + + ITEM Item(szName, szValue, CharSet1, CharSet2); + trim(Item.m_Name); + trim(Item.m_Substitute); + Items.push_back(Item); + } + + RegCloseKey(hKey); + + g_Items = Items; + LV_AddItems(g_hListView); + DoSort(0, TRUE); + g_bModified = FALSE; + g_bNeedsReboot = FALSE; + + return !g_Items.empty(); +} + +BOOL DoLoad(void) +{ + return DoLoadNames() && DoLoadItems(); +} + +void LV_InvalidateRow(HWND hwnd, INT iRow = -1) +{ + if (iRow == -1) + iRow = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED); + if (iRow == -1) + return; + + RECT Rect; + LPRECT GccIsWhining = &Rect; + ListView_GetItemRect(hwnd, iRow, GccIsWhining, LVIR_BOUNDS); + InvalidateRect(hwnd, &Rect, FALSE); +} + +BOOL LV_Init(HWND hwnd) +{ + ListView_SetExtendedListViewStyle(hwnd, + LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); + + HIMAGELIST hImageList; + hImageList = ImageList_Create(12, 12, ILC_COLOR8 | ILC_MASK, 2, 2); + + HBITMAP hbm; + hbm = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(2), IMAGE_BITMAP, + 12, 12, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS); + assert(hbm); + ImageList_AddMasked(hImageList, hbm, RGB(192, 192, 192)); + DeleteObject(hbm); + + hbm = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(3), IMAGE_BITMAP, + 12, 12, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS); + assert(hbm); + ImageList_AddMasked(hImageList, hbm, RGB(192, 192, 192)); + DeleteObject(hbm); + + hbm = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(4), IMAGE_BITMAP, + 12, 12, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS); + assert(hbm); + ImageList_AddMasked(hImageList, hbm, RGB(192, 192, 192)); + DeleteObject(hbm); + + ListView_SetImageList(hwnd, hImageList, LVSIL_SMALL); + + LV_COLUMNW Column; + ZeroMemory(&Column, sizeof(Column)); + Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH | LVCF_IMAGE; + Column.fmt = LVCFMT_LEFT; + + Column.cx = NAME_COLUMN_WIDTH; + Column.pszText = g_szNameHead; + Column.iSubItem = 0; + Column.iImage = 0; + ListView_InsertColumn(hwnd, 0, &Column); + + Column.cx = SUB_COLUMN_WIDTH; + Column.pszText = g_szSubstituteHead; + Column.iSubItem = 1; + Column.iImage = 2; + ListView_InsertColumn(hwnd, 1, &Column); + + UINT State = LVIS_SELECTED | LVIS_FOCUSED; + ListView_SetItemState(hwnd, 0, State, State); + + return TRUE; +} + +BOOL EditDlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) +{ + COMBOBOXEXITEMW Item; + ZeroMemory(&Item, sizeof(Item)); + Item.mask = CBEIF_TEXT; + + FONTNAMESET::iterator it, end = g_Names.end(); + for (it = g_Names.begin(); it != end; ++it) + { + Item.pszText = const_cast(it->c_str()); + Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb2)); + SendDlgItemMessageW(hwnd, cmb2, CBEM_INSERTITEM, 0, (LPARAM)&Item); + } + SetDlgItemTextW(hwnd, edt1, g_strFontName.c_str()); + SetDlgItemTextW(hwnd, cmb2, g_strSubstitute.c_str()); + + const INT Count = _countof(g_CharSetList); + for (INT i = 0; i < Count; ++i) + { + Item.pszText = const_cast(g_CharSetList[i].DisplayName); + Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb3)); + SendDlgItemMessageW(hwnd, cmb3, CBEM_INSERTITEM, 0, (LPARAM)&Item); + Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb4)); + SendDlgItemMessageW(hwnd, cmb4, CBEM_INSERTITEM, 0, (LPARAM)&Item); + } + + SendDlgItemMessageW(hwnd, cmb3, CB_SETCURSEL, 0, 0); + SendDlgItemMessageW(hwnd, cmb4, CB_SETCURSEL, 0, 0); + for (INT i = 0; i < Count; ++i) + { + if (g_CharSet1 == g_CharSetList[i].CharSet) + { + SendDlgItemMessageW(hwnd, cmb3, CB_SETCURSEL, i, 0); + } + if (g_CharSet2 == g_CharSetList[i].CharSet) + { + SendDlgItemMessageW(hwnd, cmb4, CB_SETCURSEL, i, 0); + } + } + + SIZE siz; + HDC hDC = CreateCompatibleDC(NULL); + SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); + GetTextExtentPoint32W(hDC, g_LongestName, lstrlenW(g_LongestName), &siz); + DeleteDC(hDC); + + SendDlgItemMessageW(hwnd, cmb3, CB_SETHORIZONTALEXTENT, siz.cx + 16, 0); + SendDlgItemMessageW(hwnd, cmb4, CB_SETHORIZONTALEXTENT, siz.cx + 16, 0); + + EnableWindow(GetDlgItem(hwnd, cmb3), FALSE); + + return TRUE; +} + +void LV_OnDelete(HWND hwnd, INT iRow = -1) +{ + if (iRow == -1) + iRow = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED); + if (iRow == -1) + return; + + UINT State = LVIS_SELECTED | LVIS_FOCUSED; + ListView_SetItemState(g_hListView, iRow, State, State); + + WCHAR sz[MAX_STRING]; + LoadStringW(g_hInstance, IDS_QUERYDELETE, sz, _countof(sz)); + if (IDYES != MessageBoxW(g_hMainWnd, sz, g_szTitle, + MB_ICONINFORMATION | MB_YESNO)) + { + return; + } + + ListView_DeleteItem(hwnd, iRow); + g_Items.erase(g_Items.begin() + iRow); + g_bModified = TRUE; + + ListView_SetItemState(g_hListView, iRow, State, State); + + InvalidateRect(hwnd, NULL, TRUE); +} + +void EditDlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) +{ + WCHAR szValue[MAX_STRING]; + STRING str; + INT i; + + switch (id) + { + case IDOK: + GetDlgItemTextW(hwnd, cmb2, szValue, _countof(szValue)); + str = szValue; + trim(str); + if (str.empty()) + { + WCHAR sz[MAX_STRING]; + SendDlgItemMessageW(hwnd, cmb2, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); + SetFocus(GetDlgItem(hwnd, cmb2)); + LoadStringW(g_hInstance, IDS_ENTERNAME2, sz, _countof(sz)); + MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); + return; + } + + g_Items[g_iItem].m_CharSet2 = DEFAULT_CHARSET; + i = SendDlgItemMessageW(hwnd, cmb4, CB_GETCURSEL, 0, 0); + if (i != CB_ERR) + { + g_Items[g_iItem].m_CharSet2 = g_CharSetList[i].CharSet; + } + g_Items[g_iItem].m_Substitute = str; + + g_bModified = TRUE; + EndDialog(hwnd, IDOK); + break; + case IDCANCEL: + EndDialog(hwnd, IDCANCEL); + break; + case psh1: + LV_OnDelete(g_hListView, g_iItem); + EndDialog(hwnd, psh1); + break; + } +} + +INT_PTR CALLBACK +EditDlg_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + HANDLE_MSG(hwnd, WM_INITDIALOG, EditDlg_OnInitDialog); + HANDLE_MSG(hwnd, WM_COMMAND, EditDlg_OnCommand); + } + return 0; +} + +void LV_OnDblClk(HWND hwnd) +{ + g_iItem = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED); + if (g_iItem == -1) + return; + + g_strFontName = g_Items[g_iItem].m_Name; + g_strSubstitute = g_Items[g_iItem].m_Substitute; + g_CharSet1 = g_Items[g_iItem].m_CharSet1; + g_CharSet2 = g_Items[g_iItem].m_CharSet2; + + DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_EDIT), g_hMainWnd, + EditDlg_DlgProc); + InvalidateRect(g_hListView, NULL, TRUE); +} + +BOOL MainWnd_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) +{ + DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | + LVS_SINGLESEL | LVS_REPORT | LVS_OWNERDRAWFIXED; + DWORD dwExStyle = WS_EX_CLIENTEDGE; + g_hListView = CreateWindowEx(dwExStyle, WC_LISTVIEW, NULL, dwStyle, + 0, 0, 0, 0, + hwnd, (HMENU)1, g_hInstance, NULL); + if (g_hListView == NULL) + return FALSE; + + if (!LV_Init(g_hListView)) + return FALSE; + + if (!DoLoad()) + return FALSE; + + UINT State = LVIS_SELECTED | LVIS_FOCUSED; + ListView_SetItemState(g_hListView, 0, State, State); + SetFocus(g_hListView); + return TRUE; +} + +BOOL AddDlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) +{ + COMBOBOXEXITEMW Item; + ZeroMemory(&Item, sizeof(Item)); + Item.iItem = -1; + Item.mask = CBEIF_TEXT; + + FONTNAMESET::iterator it, end = g_Names.end(); + for (it = g_Names.begin(); it != end; ++it) + { + Item.pszText = const_cast(it->c_str()); + Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb1)); + SendDlgItemMessageW(hwnd, cmb1, CBEM_INSERTITEM, 0, (LPARAM)&Item); + Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb2)); + SendDlgItemMessageW(hwnd, cmb2, CBEM_INSERTITEM, 0, (LPARAM)&Item); + } + WCHAR szEnterName[MAX_STRING]; + LoadStringW(g_hInstance, IDS_ENTERNAME, szEnterName, _countof(szEnterName)); + SetDlgItemTextW(hwnd, cmb1, szEnterName); + SendDlgItemMessageW(hwnd, cmb1, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); + + const INT Count = _countof(g_CharSetList); + for (INT i = 0; i < Count; ++i) + { + Item.pszText = const_cast(g_CharSetList[i].DisplayName); + Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb3)); + SendDlgItemMessageW(hwnd, cmb3, CBEM_INSERTITEM, 0, (LPARAM)&Item); + Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb4)); + SendDlgItemMessageW(hwnd, cmb4, CBEM_INSERTITEM, 0, (LPARAM)&Item); + } + + SendDlgItemMessageW(hwnd, cmb3, CB_SETCURSEL, 0, 0); + SendDlgItemMessageW(hwnd, cmb4, CB_SETCURSEL, 0, 0); + for (INT i = 0; i < Count; ++i) + { + if (g_CharSet1 == g_CharSetList[i].CharSet) + { + SendDlgItemMessageW(hwnd, cmb3, CB_SETCURSEL, i, 0); + } + if (g_CharSet2 == g_CharSetList[i].CharSet) + { + SendDlgItemMessageW(hwnd, cmb4, CB_SETCURSEL, i, 0); + } + } + + SIZE siz; + HDC hDC = CreateCompatibleDC(NULL); + SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); + GetTextExtentPoint32W(hDC, g_LongestName, lstrlenW(g_LongestName), &siz); + DeleteDC(hDC); + + SendDlgItemMessageW(hwnd, cmb3, CB_SETHORIZONTALEXTENT, siz.cx + 16, 0); + SendDlgItemMessageW(hwnd, cmb4, CB_SETHORIZONTALEXTENT, siz.cx + 16, 0); + + return TRUE; +} + +void AddDlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) +{ + WCHAR szKey[MAX_STRING], szValue[MAX_STRING], sz[MAX_STRING]; + INT i, iCharSet1, iCharSet2; + BYTE CharSet1, CharSet2; + STRING key, value; + switch (id) + { + case IDOK: + GetDlgItemTextW(hwnd, cmb1, szKey, _countof(szKey)); + key = szKey; + trim(key); + LoadStringW(g_hInstance, IDS_ENTERNAME, sz, _countof(sz)); + if (key.empty() || key == sz) + { + SendDlgItemMessageW(hwnd, cmb1, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); + SetFocus(GetDlgItem(hwnd, cmb1)); + LoadStringW(g_hInstance, IDS_ENTERNAME2, sz, _countof(sz)); + MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); + return; + } + + GetDlgItemTextW(hwnd, cmb2, szValue, _countof(szValue)); + value = szValue; + trim(value); + if (value.empty()) + { + SendDlgItemMessageW(hwnd, cmb2, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); + SetFocus(GetDlgItem(hwnd, cmb2)); + LoadStringW(g_hInstance, IDS_ENTERNAME2, sz, _countof(sz)); + MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); + return; + } + + iCharSet1 = SendDlgItemMessageW(hwnd, cmb3, CB_GETCURSEL, 0, 0); + if (iCharSet1 == CB_ERR) + iCharSet1 = 0; + iCharSet2 = SendDlgItemMessageW(hwnd, cmb4, CB_GETCURSEL, 0, 0); + if (iCharSet2 == CB_ERR) + iCharSet2 = 0; + + CharSet1 = g_CharSetList[iCharSet1].CharSet; + CharSet2 = g_CharSetList[iCharSet2].CharSet; + + for (i = 0; i < (INT)g_Items.size(); ++i) + { + if (g_Items[i].m_Name == key && + g_Items[i].m_CharSet1 == CharSet1) + { + WCHAR sz[MAX_STRING]; + SendDlgItemMessageW(hwnd, cmb1, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); + SetFocus(GetDlgItem(hwnd, cmb1)); + LoadStringW(g_hInstance, IDS_ALREADYEXISTS, sz, _countof(sz)); + MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); + return; + } + } + { + ITEM Item(key, value, CharSet1, CharSet2); + g_Items.push_back(Item); + g_bModified = TRUE; + + i = (INT)g_Items.size(); + LV_ITEM LvItem; + ZeroMemory(&LvItem, sizeof(LvItem)); + LvItem.mask = LVIF_PARAM; + LvItem.iItem = i; + LvItem.lParam = i; + + LvItem.iSubItem = 0; + ListView_InsertItem(g_hListView, &LvItem); + + LvItem.iSubItem = 1; + ListView_InsertItem(g_hListView, &LvItem); + } + g_bModified = TRUE; + EndDialog(hwnd, IDOK); + break; + case IDCANCEL: + EndDialog(hwnd, IDCANCEL); + break; + } +} + +INT_PTR CALLBACK +AddDlg_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + HANDLE_MSG(hwnd, WM_INITDIALOG, AddDlg_OnInitDialog); + HANDLE_MSG(hwnd, WM_COMMAND, AddDlg_OnCommand); + } + return 0; +} + +void MainWnd_OnNew(HWND hwnd) +{ + g_iItem = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED); + if (g_iItem == -1) + return; + + g_strFontName = g_Items[g_iItem].m_Name; + g_strSubstitute = g_Items[g_iItem].m_Substitute; + g_CharSet1 = g_Items[g_iItem].m_CharSet1; + g_CharSet2 = g_Items[g_iItem].m_CharSet2; + + if (IDOK == DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_ADD), g_hMainWnd, + AddDlg_DlgProc)) + { + INT i = ListView_GetItemCount(g_hListView) - 1; + UINT State = LVIS_SELECTED | LVIS_FOCUSED; + ListView_SetItemState(g_hListView, i, State, State); + ListView_EnsureVisible(g_hListView, i, FALSE); + } +} + +BOOL MainWnd_OnUpdateRegistry(HWND hwnd) +{ + // open the key + HKEY hKey = NULL; + RegOpenKeyExW(HKEY_LOCAL_MACHINE, g_pszKey, 0, KEY_ALL_ACCESS, &hKey); + if (hKey == NULL) + return FALSE; + + // clear all values + WCHAR szName[MAX_STRING], szValue[MAX_STRING]; + DWORD cbName, cbValue; + for (;;) + { + cbName = sizeof(szName); + cbValue = sizeof(szValue); + LONG Error = RegEnumValueW(hKey, 0, szName, &cbName, + NULL, NULL, (LPBYTE)szValue, &cbValue); + if (Error != ERROR_SUCCESS) + break; + + RegDeleteValueW(hKey, szName); + } + + // set values + size_t Count = g_Items.size(); + for (size_t i = 0; i < Count; ++i) + { + DWORD cbData = (g_Items[i].m_Substitute.size() + 1) * sizeof(WCHAR); + RegSetValueExW(hKey, g_Items[i].m_Name.c_str(), 0, + REG_SZ, (LPBYTE)g_Items[i].m_Substitute.c_str(), cbData); + } + + // close now + RegCloseKey(hKey); + + g_bModified = FALSE; + g_bNeedsReboot = TRUE; + return TRUE; +} + +LPWSTR SkipSpace(LPCWSTR pch) +{ + while (*pch && wcschr(L" \t\r\n", *pch) != NULL) + { + ++pch; + } + return const_cast(pch); +} + +LPWSTR SkipQuoted(LPWSTR pch) +{ + ++pch; // L'"' + while (*pch) + { + if (*pch == L'"') + { + ++pch; + break; + } + if (*pch == L'\\') + { + ++pch; + } + ++pch; + } + return pch; +} + +void UnescapeHex(const STRING& str, size_t& i, STRING& Ret, BOOL Unicode) +{ + STRING Num; + + // hexadecimal + if (iswxdigit(str[i])) + { + Num += str[i]; + ++i; + if (iswxdigit(str[i])) + { + Num += str[i]; + ++i; + if (Unicode) + { + if (iswxdigit(str[i])) + { + Num += str[i]; + ++i; + if (iswxdigit(str[i])) + { + Num += str[i]; + ++i; + } + } + } + } + } + if (!Num.empty()) + { + Ret += (WCHAR)wcstoul(&Num[0], NULL, 16); + } +} + +void UnescapeOther(const STRING& str, size_t& i, STRING& Ret) +{ + STRING Num; + + // check octal + if (L'0' <= str[i] && str[i] < L'8') + { + Num += str[i]; + ++i; + if (L'0' <= str[i] && str[i] < L'8') + { + Num += str[i]; + ++i; + if (L'0' <= str[i] && str[i] < L'8') + { + Num += str[i]; + ++i; + } + } + } + if (Num.empty()) + { + Ret += str[i]; + ++i; + } + else + { + // octal + Ret += (WCHAR)wcstoul(&Num[0], NULL, 8); + } +} + +// process escape sequence +void UnescapeChar(const STRING& str, size_t& i, STRING& Ret) +{ + if (str[i] != L'\\') + { + Ret += str[i]; + ++i; + return; + } + + ++i; + switch (str[i]) + { + case L'a': Ret += L'\a'; ++i; break; + case L'b': Ret += L'\b'; ++i; break; + case L'f': Ret += L'\f'; ++i; break; + case L'n': Ret += L'\n'; ++i; break; + case L'r': Ret += L'\r'; ++i; break; + case L't': Ret += L'\t'; ++i; break; + case L'v': Ret += L'\v'; ++i; break; + case L'x': + // hexidemical + ++i; + UnescapeHex(str, i, Ret, FALSE); + break; + case L'u': + // Unicode hexidemical + ++i; + UnescapeHex(str, i, Ret, TRUE); + break; + default: + // other case + UnescapeOther(str, i, Ret); + break; + } +} + +STRING Unquote(const STRING& str) +{ + if (str[0] != L'"') + return str; + + STRING Ret; + size_t i = 1; + while (i < str.size()) + { + if (str[i] == L'"' || str[i] == UNICODE_NULL) + break; + + UnescapeChar(str, i, Ret); + } + return Ret; +} + +BOOL DoParseFile(LPVOID pvContents, DWORD dwSize) +{ + ITEMVECTOR Items; + + LPWSTR pch, pchSep, pchStart = (LPWSTR)pvContents; + + pchStart[dwSize / sizeof(WCHAR)] = UNICODE_NULL; + + // check header + const DWORD cbHeader = lstrlenW(g_pszFileHeader) * sizeof(WCHAR); + if (memcmp(pchStart, g_pszFileHeader, cbHeader) != 0) + return FALSE; + + pchStart += cbHeader / sizeof(WCHAR); + + // find the key + WCHAR szKey[MAX_STRING]; + wsprintfW(szKey, L"[HKEY_LOCAL_MACHINE\\%s]", g_pszKey); + pch = wcsstr(pchStart, szKey); + if (pch == NULL) + return FALSE; + + pchStart = pch + lstrlenW(szKey); + + for (;;) + { + pchStart = SkipSpace(pchStart); + if (*pchStart == UNICODE_NULL || *pchStart == L'[') + break; + + pch = wcschr(pchStart, L'\n'); + if (pch) + *pch = UNICODE_NULL; + + pchSep = SkipQuoted(pchStart); + if (*pchSep == L'=') + { + *pchSep = UNICODE_NULL; + + STRING key = pchStart; + trim(key); + key = Unquote(key); + + STRING value = pchSep + 1; + trim(value); + value = Unquote(value); + + BYTE CharSet1 = DEFAULT_CHARSET, CharSet2 = DEFAULT_CHARSET; + + size_t pos; + pos = key.find(L','); + if (pos != STRING::npos) + { + CharSet1 = (BYTE)_wtoi(&key[pos + 1]); + key.resize(pos); + trim(key); + } + pos = value.find(L','); + if (pos != STRING::npos) + { + CharSet2 = (BYTE)_wtoi(&value[pos + 1]); + value.resize(pos); + trim(value); + } + + ITEM Item(key, value, CharSet1, CharSet2); + Items.push_back(Item); + } + + if (pch == NULL) + break; + + pchStart = pch + 1; + } + + g_Items = Items; + g_bModified = TRUE; + + LV_AddItems(g_hListView); + return TRUE; +} + +BOOL DoImport(HWND hwnd, LPCWSTR pszFile) +{ + HANDLE hFile = CreateFileW(pszFile, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + BOOL bSuccess = FALSE; + DWORD dwSize = GetFileSize(hFile, NULL); + if (dwSize != 0xFFFFFFFF) + { + std::vector Contents(dwSize + 2); + DWORD cbRead; + if (ReadFile(hFile, &Contents[0], dwSize, &cbRead, NULL) && + cbRead == dwSize) + { + /* check BOM */ + if (memcmp(&Contents[0], "\xFF\xFE", 2) == 0) + { + bSuccess = DoParseFile(&Contents[2], dwSize - 2); + } + else + { + bSuccess = DoParseFile(&Contents[0], dwSize); + } + } + } + CloseHandle(hFile); + + return bSuccess; +} + +STRING Escape(const STRING& str) +{ + STRING Ret; + for (size_t i = 0; i < str.size(); ++i) + { + switch (str[i]) + { + case L'"': case L'\\': + Ret += L'\\'; + Ret += str[i]; + break; + default: + Ret += str[i]; + } + } + return Ret; +} + +BOOL DoExport(HWND hwnd, LPCWSTR pszFile) +{ + HANDLE hFile = CreateFileW(pszFile, GENERIC_WRITE, FILE_SHARE_READ, + NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + BOOL bSuccess; + DWORD dwSize, cbWritten; + WCHAR szCharSet1[MAX_STRING], szCharSet2[MAX_STRING]; + WCHAR szLine[MAX_STRING * 2 + 4]; + + /* write header */ + dwSize = lstrlenW(g_pszFileHeader) * sizeof(WCHAR); + bSuccess = + WriteFile(hFile, "\xFF\xFE", 2, &cbWritten, NULL) && + WriteFile(hFile, g_pszFileHeader, dwSize, &cbWritten, NULL); + if (bSuccess) + { + wsprintfW(szLine, L"\r\n\r\n[HKEY_LOCAL_MACHINE\\%s]\r\n", g_pszKey); + dwSize = lstrlenW(szLine) * sizeof(WCHAR); + bSuccess = WriteFile(hFile, szLine, dwSize, &cbWritten, NULL); + } + if (bSuccess) + { + size_t i, Count = g_Items.size(); + for (i = 0; i < Count; ++i) + { + if (g_Items[i].m_CharSet1 != DEFAULT_CHARSET) + wsprintfW(szCharSet1, L",%u", g_Items[i].m_CharSet1); + else + szCharSet1[0] = UNICODE_NULL; + + if (g_Items[i].m_CharSet2 != DEFAULT_CHARSET) + wsprintfW(szCharSet2, L",%u", g_Items[i].m_CharSet2); + else + szCharSet2[0] = UNICODE_NULL; + + STRING Name = Escape(g_Items[i].m_Name); + STRING Substitute = Escape(g_Items[i].m_Substitute); + wsprintfW(szLine, L"\"%s%s\"=\"%s%s\"\r\n", + Name.c_str(), szCharSet1, + Substitute.c_str(), szCharSet2); + + dwSize = lstrlenW(szLine) * sizeof(WCHAR); + if (!WriteFile(hFile, szLine, dwSize, &cbWritten, NULL)) + { + bSuccess = FALSE; + break; + } + } + WriteFile(hFile, L"\r\n", 2 * sizeof(WCHAR), &cbWritten, NULL); + } + CloseHandle(hFile); + + if (!bSuccess) + { + DeleteFileW(pszFile); + } + + return bSuccess; +} + +void MakeFilter(LPWSTR pszFilter) +{ + while (*pszFilter) + { + if (*pszFilter == L'|') + *pszFilter = 0; + + ++pszFilter; + } +} + +void MainWnd_OnImport(HWND hwnd) +{ + OPENFILENAMEW ofn = {0}; + WCHAR szFile[MAX_PATH] = L""; + WCHAR szImportTitle[MAX_STRING]; + WCHAR szCannotImport[MAX_STRING]; + WCHAR szImportFilter[MAX_STRING]; + LoadStringW(g_hInstance, IDS_IMPORT, szImportTitle, _countof(szImportTitle)); + LoadStringW(g_hInstance, IDS_CANTIMPORT, szCannotImport, _countof(szCannotImport)); + LoadStringW(g_hInstance, IDS_INPFILTER, szImportFilter, _countof(szImportFilter)); + MakeFilter(szImportFilter); + + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = szImportFilter; + ofn.lpstrFile = szFile; + ofn.nMaxFile = _countof(szFile); + ofn.lpstrTitle = szImportTitle; + ofn.Flags = OFN_DONTADDTORECENT | OFN_ENABLESIZING | + OFN_EXPLORER | OFN_FILEMUSTEXIST | + OFN_HIDEREADONLY | OFN_LONGNAMES | + OFN_PATHMUSTEXIST; + ofn.lpstrDefExt = L"reg"; + if (GetOpenFileNameW(&ofn)) + { + if (!DoImport(hwnd, szFile)) + { + MessageBoxW(hwnd, szCannotImport, g_szTitle, MB_ICONERROR); + } + } +} + +void MainWnd_OnExport(HWND hwnd) +{ + OPENFILENAMEW ofn = {0}; + WCHAR szFile[MAX_PATH] = L""; + WCHAR szExportTitle[MAX_STRING]; + WCHAR szCannotExport[MAX_STRING]; + WCHAR szExportFilter[MAX_STRING]; + LoadStringW(g_hInstance, IDS_EXPORT, szExportTitle, _countof(szExportTitle)); + LoadStringW(g_hInstance, IDS_CANTEXPORT, szCannotExport, _countof(szCannotExport)); + LoadStringW(g_hInstance, IDS_OUTFILTER, szExportFilter, _countof(szExportFilter)); + MakeFilter(szExportFilter); + + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = szExportFilter; + ofn.lpstrFile = szFile; + ofn.nMaxFile = _countof(szFile); + ofn.lpstrTitle = szExportTitle; + ofn.Flags = OFN_DONTADDTORECENT | OFN_ENABLESIZING | + OFN_EXPLORER | OFN_HIDEREADONLY | OFN_LONGNAMES | + OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; + ofn.lpstrDefExt = L"reg"; + if (GetSaveFileNameW(&ofn)) + { + if (!DoExport(hwnd, szFile)) + { + MessageBoxW(hwnd, szCannotExport, g_szTitle, MB_ICONERROR); + } + } +} + +void MainWnd_OnReload(HWND hwnd) +{ + DoLoad(); +} + +void MainWnd_OnEdit(HWND hwnd) +{ + LV_OnDblClk(g_hListView); +} + +void MainWnd_OnDelete(HWND hwnd) +{ + LV_OnDelete(g_hListView); +} + +void MainWnd_OnOpenRegKey(HWND hwnd) +{ + static const WCHAR s_szRegeditKey[] = + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit"; + WCHAR sz[MAX_STRING]; + + // open regedit key + HKEY hKey = NULL; + LSTATUS Result = RegCreateKeyExW(HKEY_CURRENT_USER, s_szRegeditKey, 0, + NULL, 0, KEY_WRITE, NULL, &hKey, NULL); + if (Result != ERROR_SUCCESS) + { + LoadStringW(g_hInstance, IDS_CANTOPENKEY, sz, _countof(sz)); + MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); + return; + } + + // set LastKey value + wsprintfW(sz, L"HKEY_LOCAL_MACHINE\\%s", g_pszKey); + DWORD dwSize = sizeof(sz); + Result = RegSetValueExW(hKey, L"LastKey", 0, REG_SZ, + (LPBYTE)sz, dwSize); + + // close now + RegCloseKey(hKey); + + if (Result != ERROR_SUCCESS) + { + LoadStringW(g_hInstance, IDS_CANTOPENKEY, sz, _countof(sz)); + MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); + return; + } + + // open by regedit + ShellExecuteW(hwnd, NULL, L"regedit.exe", NULL, NULL, SW_SHOWNORMAL); +} + +void MainWnd_OnAbout(HWND hwnd) +{ + WCHAR szAbout[MAX_PATH]; + LoadStringW(g_hInstance, IDS_ABOUT, szAbout, _countof(szAbout)); + + MSGBOXPARAMS Params; + ZeroMemory(&Params, sizeof(Params)); + Params.cbSize = sizeof(Params); + Params.hwndOwner = hwnd; + Params.hInstance = g_hInstance; + Params.lpszText = szAbout; + Params.lpszCaption = g_szTitle; + Params.dwStyle = MB_OK | MB_USERICON; + Params.lpszIcon = MAKEINTRESOURCEW(1); + Params.dwLanguageId = LANG_USER_DEFAULT; + MessageBoxIndirectW(&Params); +} + +void MainWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) +{ + switch (id) + { + case ID_NEW: + MainWnd_OnNew(hwnd); + break; + case ID_EDIT: + MainWnd_OnEdit(hwnd); + break; + case ID_EXIT: + PostMessage(hwnd, WM_CLOSE, 0, 0); + break; + case ID_RELOAD: + MainWnd_OnReload(hwnd); + break; + case ID_UPDATE_REGISTRY: + MainWnd_OnUpdateRegistry(hwnd); + break; + case ID_DELETE: + MainWnd_OnDelete(hwnd); + break; + case ID_IMPORT: + MainWnd_OnImport(hwnd); + break; + case ID_EXPORT: + MainWnd_OnExport(hwnd); + break; + case ID_OPEN_REGKEY: + MainWnd_OnOpenRegKey(hwnd); + break; + case ID_ABOUT: + MainWnd_OnAbout(hwnd); + break; + } +} + +void MainWnd_OnDestroy(HWND hwnd) +{ + PostQuitMessage(0); +} + +void MainWnd_OnSize(HWND hwnd, UINT state, int cx, int cy) +{ + MoveWindow(g_hListView, 0, 0, cx, cy, TRUE); +} + +void MainWnd_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT *lpDrawItem) +{ + if (lpDrawItem->CtlType != ODT_LISTVIEW) + return; + + HDC hDC = lpDrawItem->hDC; + SetBkMode(hDC, TRANSPARENT); + + INT iColumn = 0, x, cx; + RECT rcItem, rcSubItem, rcText; + STRING Str; + + x = -GetScrollPos(g_hListView, SB_HORZ); + + rcItem = lpDrawItem->rcItem; + if (lpDrawItem->itemState & ODS_SELECTED) + { + FillRect(hDC, &rcItem, (HBRUSH)(COLOR_HIGHLIGHT + 1)); + SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + else + { + FillRect(hDC, &rcItem, (HBRUSH)(COLOR_WINDOW + 1)); + SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); + } + + cx = ListView_GetColumnWidth(g_hListView, iColumn); + rcSubItem = rcItem; + rcSubItem.left = x; + rcSubItem.right = x + cx; + + WCHAR sz[MAX_STRING]; + + rcText = rcSubItem; + InflateRect(&rcText, -1, -1); + Str = g_Items[lpDrawItem->itemID].m_Name; + BYTE CharSet1 = g_Items[lpDrawItem->itemID].m_CharSet1; + if (CharSet1 != DEFAULT_CHARSET) + wsprintfW(sz, L"%s,%u", Str.c_str(), CharSet1); + else + wsprintfW(sz, L"%s", Str.c_str()); + + DrawTextW(hDC, sz, lstrlenW(sz), &rcText, + DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | + DT_NOPREFIX); + + x += cx; + ++iColumn; + + cx = ListView_GetColumnWidth(g_hListView, iColumn); + rcSubItem = rcItem; + rcSubItem.left = x; + rcSubItem.right = x + cx; + + rcText = rcSubItem; + InflateRect(&rcText, -1, -1); + Str = g_Items[lpDrawItem->itemID].m_Substitute; + BYTE CharSet2 = g_Items[lpDrawItem->itemID].m_CharSet2; + if (CharSet2 != DEFAULT_CHARSET) + wsprintfW(sz, L"%s,%u", Str.c_str(), CharSet2); + else + wsprintfW(sz, L"%s", Str.c_str()); + + DrawTextW(hDC, sz, lstrlenW(sz), &rcText, + DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | + DT_NOPREFIX); +} + +void MainWnd_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT *lpMeasureItem) +{ + if (lpMeasureItem->CtlType != ODT_LISTVIEW) + return; + + TEXTMETRIC tm; + HDC hDC = GetDC(hwnd); + GetTextMetrics(hDC, &tm); + ReleaseDC(hwnd, hDC); + + lpMeasureItem->itemHeight = tm.tmHeight * 4 / 3; +} + +LRESULT MainWnd_OnNotify(HWND hwnd, int idFrom, NMHDR *pnmhdr) +{ + NM_LISTVIEW *pNMLV = (NM_LISTVIEW *)pnmhdr; + LV_KEYDOWN *pLVKD = (LV_KEYDOWN *)pnmhdr; + + switch (pnmhdr->code) + { + case LVN_COLUMNCLICK: + if (pNMLV->iSubItem == g_iSortColumn) + DoSort(pNMLV->iSubItem, !g_bSortAscendant); + else + DoSort(pNMLV->iSubItem, TRUE); + break; + case NM_DBLCLK: + LV_OnDblClk(g_hListView); + break; + case LVN_KEYDOWN: + if (pLVKD->wVKey == VK_RETURN) // [Enter] key + { + LV_OnDblClk(g_hListView); + } + if (pLVKD->wVKey == VK_DELETE) // [Del] key + { + LV_OnDelete(g_hListView); + } + break; + } + return 0; +} + +LRESULT MainWnd_OnContextMenu(HWND hwnd, HWND hwndContext, UINT xPos, UINT yPos) +{ + POINT pt = {(INT)xPos, (INT)yPos}; + ScreenToClient(g_hListView, &pt); + SendMessageW(g_hListView, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y)); + + HMENU hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(2)); + if (hMenu == NULL) + return 0; + + HMENU hSubMenu = GetSubMenu(hMenu, 0); + if (hSubMenu == NULL) + return 0; + + SetForegroundWindow(hwnd); + TrackPopupMenu(hSubMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, + xPos, yPos, 0, g_hMainWnd, NULL); + PostMessage(g_hMainWnd, WM_NULL, 0, 0); + return 0; +} + +void MainWnd_OnActivate(HWND hwnd, UINT state, HWND hwndActDeact, BOOL fMinimized) +{ + if (state != WA_INACTIVE) + { + SetFocus(g_hListView); + } +} + +BOOL EnableProcessPrivileges(LPCWSTR lpPrivilegeName, BOOL bEnable = TRUE) +{ + HANDLE hToken; + LUID luid; + TOKEN_PRIVILEGES tokenPrivileges; + BOOL Ret; + + Ret = ::OpenProcessToken(::GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken); + if (!Ret) + return Ret; // failure + + Ret = ::LookupPrivilegeValueW(NULL, lpPrivilegeName, &luid); + if (Ret) + { + tokenPrivileges.PrivilegeCount = 1; + tokenPrivileges.Privileges[0].Luid = luid; + tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; + + Ret = ::AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, 0, 0); + } + + ::CloseHandle(hToken); + return Ret; +} + +void MainWnd_OnClose(HWND hwnd) +{ + if (!g_bNeedsReboot && !g_bModified) + { + DestroyWindow(hwnd); + return; + } + + if (g_bModified) + { + WCHAR szUpdateNow[MAX_STRING]; + LoadStringW(g_hInstance, IDS_QUERYUPDATE, szUpdateNow, _countof(szUpdateNow)); + INT id = MessageBoxW(hwnd, szUpdateNow, g_szTitle, + MB_ICONINFORMATION | MB_YESNOCANCEL); + switch (id) + { + case IDYES: + MainWnd_OnUpdateRegistry(hwnd); + break; + case IDNO: + break; + case IDCANCEL: + return; + } + } + + if (g_bNeedsReboot) + { + WCHAR szRebootNow[MAX_STRING]; + LoadStringW(g_hInstance, IDS_REBOOTNOW, szRebootNow, _countof(szRebootNow)); + INT id = MessageBoxW(hwnd, szRebootNow, g_szTitle, + MB_ICONINFORMATION | MB_YESNOCANCEL); + switch (id) + { + case IDYES: + EnableProcessPrivileges(SE_SHUTDOWN_NAME, TRUE); + ::ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0); + break; + case IDNO: + break; + case IDCANCEL: + return; + } + } + + ::DestroyWindow(hwnd); +} + +LRESULT CALLBACK +WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + HANDLE_MSG(hwnd, WM_CREATE, MainWnd_OnCreate); + HANDLE_MSG(hwnd, WM_COMMAND, MainWnd_OnCommand); + HANDLE_MSG(hwnd, WM_DESTROY, MainWnd_OnDestroy); + HANDLE_MSG(hwnd, WM_SIZE, MainWnd_OnSize); + HANDLE_MSG(hwnd, WM_DRAWITEM, MainWnd_OnDrawItem); + HANDLE_MSG(hwnd, WM_MEASUREITEM, MainWnd_OnMeasureItem); + HANDLE_MSG(hwnd, WM_NOTIFY, MainWnd_OnNotify); + HANDLE_MSG(hwnd, WM_CONTEXTMENU, MainWnd_OnContextMenu); + HANDLE_MSG(hwnd, WM_ACTIVATE, MainWnd_OnActivate); + HANDLE_MSG(hwnd, WM_CLOSE, MainWnd_OnClose); + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } +} + +INT WINAPI wWinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, + INT nCmdShow) +{ + g_hInstance = hInstance; + InitCommonControls(); + + HACCEL hAccel = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(1)); + + LoadStringW(hInstance, IDS_TITLE, g_szTitle, _countof(g_szTitle)); + LoadStringW(hInstance, IDS_FONTNAME, g_szNameHead, _countof(g_szNameHead)); + LoadStringW(hInstance, IDS_SUBSTITUTE, g_szSubstituteHead, _countof(g_szSubstituteHead)); + + WNDCLASSW wc = {0}; + wc.style = 0; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + g_hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1)); + wc.hIcon = g_hIcon; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); + wc.lpszMenuName = MAKEINTRESOURCEW(1); + wc.lpszClassName = g_pszClassName; + if (!RegisterClassW(&wc)) + { + MessageBoxA(NULL, "ERROR: RegisterClass failed.", NULL, MB_ICONERROR); + return 1; + } + + const DWORD dwStyle = WS_OVERLAPPEDWINDOW; + INT Width = NAME_COLUMN_WIDTH + SUB_COLUMN_WIDTH + + GetSystemMetrics(SM_CXVSCROLL) + + GetSystemMetrics(SM_CXSIZEFRAME); + INT Height = 320; + + RECT Rect = { 0, 0, Width, Height }; + AdjustWindowRect(&Rect, dwStyle, TRUE); + Width = Rect.right - Rect.left; + Height = Rect.bottom - Rect.top; + + g_hMainWnd = CreateWindowW(g_pszClassName, g_szTitle, dwStyle, + CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, + NULL, NULL, hInstance, NULL); + if (g_hMainWnd == NULL) + { + MessageBoxA(NULL, "ERROR: CreateWindow failed.", NULL, MB_ICONERROR); + return 2; + } + + ShowWindow(g_hMainWnd, nCmdShow); + UpdateWindow(g_hMainWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + if (TranslateAccelerator(g_hMainWnd, hAccel, &msg)) + continue; + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return (INT)msg.wParam; +} diff --git a/rosapps/applications/sysutils/fontsub/fontsub.ico b/rosapps/applications/sysutils/fontsub/fontsub.ico new file mode 100644 index 00000000000..f0e89946fc9 Binary files /dev/null and b/rosapps/applications/sysutils/fontsub/fontsub.ico differ diff --git a/rosapps/applications/sysutils/fontsub/fontsub.svg b/rosapps/applications/sysutils/fontsub/fontsub.svg new file mode 100644 index 00000000000..32d2cf57b1b --- /dev/null +++ b/rosapps/applications/sysutils/fontsub/fontsub.svg @@ -0,0 +1,368 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rosapps/applications/sysutils/fontsub/fontsub_res.rc b/rosapps/applications/sysutils/fontsub/fontsub_res.rc new file mode 100644 index 00000000000..46ffa501a16 --- /dev/null +++ b/rosapps/applications/sysutils/fontsub/fontsub_res.rc @@ -0,0 +1,46 @@ +/* FontSub by Katayama Hirofumi MZ + * + * To the extent possible under law, the person who associated CC0 with + * FontSub has waived all copyright and related or neighboring rights + * to FontSub. + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +#include +#include +#include + +#include "resource.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Font Substitute Editor" +#define REACTOS_STR_INTERNAL_NAME "fontsub" +#define REACTOS_STR_ORIGINAL_FILENAME "fontsub.exe" +#include + +/* UTF-8 */ +#pragma code_page(65001) + +1 ICON "fontsub.ico" + +2 BITMAP "up.bmp" +3 BITMAP "down.bmp" +4 BITMAP "nil.bmp" + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif +#ifdef LANGUAGE_JA_JP + #include "lang/ja-JP.rc" +#endif + +1 ACCELERATORS +BEGIN + "O", ID_IMPORT, CONTROL, VIRTKEY + "S", ID_EXPORT, CONTROL, VIRTKEY + "N", ID_NEW, CONTROL, VIRTKEY + "L", ID_RELOAD, CONTROL, VIRTKEY + "U", ID_UPDATE_REGISTRY, CONTROL, VIRTKEY +END diff --git a/rosapps/applications/sysutils/fontsub/lang/en-US.rc b/rosapps/applications/sysutils/fontsub/lang/en-US.rc new file mode 100644 index 00000000000..4685d438049 --- /dev/null +++ b/rosapps/applications/sysutils/fontsub/lang/en-US.rc @@ -0,0 +1,106 @@ +/* FontSub by Katayama Hirofumi MZ + * + * To the extent possible under law, the person who associated CC0 with + * FontSub has waived all copyright and related or neighboring rights + * to FontSub. + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +1 MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Import From...\tCtrl+O", ID_IMPORT + MENUITEM "&Export To...\tCtrl+S", ID_EXPORT + MENUITEM SEPARATOR + MENUITEM "Re&load from Registry\tCtrl+L", ID_RELOAD + MENUITEM "Update &Registry\tCtrl+U", ID_UPDATE_REGISTRY + MENUITEM SEPARATOR + MENUITEM "Open in Reg&edit", ID_OPEN_REGKEY + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", ID_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&New Item\tCtrl+N", ID_NEW + MENUITEM SEPARATOR + MENUITEM "&Edit Item\tEnter", ID_EDIT + MENUITEM SEPARATOR + MENUITEM "&Delete Item\tDel", ID_DELETE + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", ID_ABOUT + END +END + +2 MENU +BEGIN + POPUP "Popup" + BEGIN + MENUITEM "&New Item\tCtrl+N", ID_NEW + MENUITEM SEPARATOR + MENUITEM "&Edit Item\tEnter", ID_EDIT + MENUITEM SEPARATOR + MENUITEM "&Delete Item\tDel", ID_DELETE + END +END + +STRINGTABLE +BEGIN + IDS_TITLE, "Font Substitutes Editor" + IDS_FONTNAME, "Font Name" + IDS_SUBSTITUTE, "Substitute" + IDS_ENTERNAME, "(Please enter a font name...)" + IDS_IMPORT, "Import" + IDS_EXPORT, "Export" + IDS_CANTIMPORT, "Could not import." + IDS_CANTEXPORT, "Could not export." + IDS_INPFILTER, "Registry Files (*.reg)|*.reg|All Files (*.*)|*.*|" + IDS_OUTFILTER, "Registry Files (*.reg)|*.reg|" + IDS_QUERYUPDATE, "Substitutes info has been modified. Update registry now?" + IDS_ALREADYEXISTS, "The same name already exists." + IDS_ENTERNAME2, "Enter the font name." + IDS_QUERYDELETE, "Do you really want to delete this item?" + IDS_CANTOPENKEY, "Could not open the registry key." + IDS_REBOOTNOW, "Registry was updated. Reboot Windows now?" + IDS_ABOUT, "FontSub (Font Substitute Editor) Version 0.5\r\nby Katayama Hirofumi MZ and The ReactOS Team\r\n\r\nThis software was released under CC0 1.0 license." +END + +IDD_ADD DIALOG 0, 0, 315, 65 +STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU +CAPTION "Add Substitute Item" +FONT 10, "MS Shell Dlg" +BEGIN + CONTROL "Font &Name:", -1, "STATIC", SS_RIGHT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 5, 55, 15 + CONTROL "", cmb1, "ComboBoxEx32", CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 70, 6, 120, 120 + CONTROL "", cmb3, "ComboBoxEx32", CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 195, 6, 115, 120 + CONTROL "&Substitute:", -1, "STATIC", SS_RIGHT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 25, 55, 15 + CONTROL "", cmb2, "ComboBoxEx32", CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 70, 26, 120, 120 + CONTROL "", cmb4, "ComboBoxEx32", CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 195, 26, 115, 120 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 175, 45, 60, 14 + CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 240, 45, 60, 14 +END + +IDD_EDIT DIALOG 0, 0, 315, 65 +STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Substitute Item" +FONT 10, "MS Shell Dlg" +BEGIN + CONTROL "Font &Name:", -1, "STATIC", SS_RIGHT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 5, 55, 15 + CONTROL "", edt1, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_BORDER | WS_TABSTOP, 70, 6, 120, 14 + CONTROL "", cmb3, "ComboBoxEx32", CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 195, 6, 115, 120 + CONTROL "&Substitute:", -1, "STATIC", SS_RIGHT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 25, 55, 15 + CONTROL "", cmb2, "ComboBoxEx32", CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 70, 26, 120, 120 + CONTROL "", cmb4, "ComboBoxEx32", CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 195, 26, 115, 120 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 175, 45, 60, 14 + CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 240, 45, 60, 14 + CONTROL "&Delete", psh1, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 45, 60, 14 +END diff --git a/rosapps/applications/sysutils/fontsub/lang/ja-JP.rc b/rosapps/applications/sysutils/fontsub/lang/ja-JP.rc new file mode 100644 index 00000000000..71d7cd66d62 --- /dev/null +++ b/rosapps/applications/sysutils/fontsub/lang/ja-JP.rc @@ -0,0 +1,106 @@ +/* FontSub by Katayama Hirofumi MZ + * + * To the extent possible under law, the person who associated CC0 with + * FontSub has waived all copyright and related or neighboring rights + * to FontSub. + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT + +1 MENU +BEGIN + POPUP "ファイル(&F)" + BEGIN + MENUITEM "インポート(&I)...\tCtrl+O", ID_IMPORT + MENUITEM "エクスポート(&E)...\tCtrl+S", ID_EXPORT + MENUITEM SEPARATOR + MENUITEM "レジストリから再読み込み(&L)\tCtrl+L", ID_RELOAD + MENUITEM "レジストリの更新(&R)\tCtrl+U", ID_UPDATE_REGISTRY + MENUITEM SEPARATOR + MENUITEM "Regeditで開く(&E)", ID_OPEN_REGKEY + MENUITEM SEPARATOR + MENUITEM "終了(&X)\tAlt+F4", ID_EXIT + END + POPUP "編集(&E)" + BEGIN + MENUITEM "新しい項目(&N)\tCtrl+N", ID_NEW + MENUITEM SEPARATOR + MENUITEM "項目の編集(&E)\tEnter", ID_EDIT + MENUITEM SEPARATOR + MENUITEM "項目の削除(&D)\tDel", ID_DELETE + END + POPUP "ヘルプ(&H)" + BEGIN + MENUITEM "バージョン情報(&A)...", ID_ABOUT + END +END + +2 MENU +BEGIN + POPUP "ポップアップ" + BEGIN + MENUITEM "新しい項目(&N)\tCtrl+N", ID_NEW + MENUITEM SEPARATOR + MENUITEM "項目の編集(&E)\tEnter", ID_EDIT + MENUITEM SEPARATOR + MENUITEM "項目の削除(&D)\tDel", ID_DELETE + END +END + +STRINGTABLE +BEGIN + IDS_TITLE, "フォント代替エディタ" + IDS_FONTNAME, "フォント名" + IDS_SUBSTITUTE, "代替名" + IDS_ENTERNAME, "(フォント名を入力して下さい...)" + IDS_IMPORT, "インポート" + IDS_EXPORT, "エクスポート" + IDS_CANTIMPORT, "インポートできません。" + IDS_CANTEXPORT, "エクスポートできません。" + IDS_INPFILTER, "レジストリ ファイル (*.reg)|*.reg|すべてのファイル (*.*)|*.*|" + IDS_OUTFILTER, "レジストリ ファイル (*.reg)|*.reg|" + IDS_QUERYUPDATE, "代替情報は変更されています。レジストリを更新しますか?" + IDS_ALREADYEXISTS, "すでに同じ名前が存在します。" + IDS_ENTERNAME2, "フォント名を入力して下さい。" + IDS_QUERYDELETE, "本当にこの項目を削除したいですか?" + IDS_CANTOPENKEY, "レジストリキーが開けませんでした。" + IDS_REBOOTNOW, "レジストリが更新されました。Windowsを再起動しますか?" + IDS_ABOUT, "FontSub (Font Substitute Editor) Version 0.5\r\nby Katayama Hirofumi MZ and The ReactOS Team\r\n\r\nThis software was released under CC0 1.0 license." +END + +IDD_ADD DIALOG 0, 0, 315, 65 +STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU +CAPTION "代替項目を追加する" +FONT 10, "MS UI Gothic" +BEGIN + CONTROL "フォント名(&N):", -1, "STATIC", SS_RIGHT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 5, 55, 15 + CONTROL "", cmb1, "ComboBoxEx32", CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 70, 6, 120, 120 + CONTROL "", cmb3, "ComboBoxEx32", CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 195, 6, 115, 120 + CONTROL "代替名(&S):", -1, "STATIC", SS_RIGHT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 25, 55, 15 + CONTROL "", cmb2, "ComboBoxEx32", CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 70, 26, 120, 120 + CONTROL "", cmb4, "ComboBoxEx32", CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 195, 26, 115, 120 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 175, 45, 60, 14 + CONTROL "キャンセル", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 240, 45, 60, 14 +END + +IDD_EDIT DIALOG 0, 0, 315, 65 +STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU +CAPTION "代替項目を編集する" +FONT 10, "MS UI Gothic" +BEGIN + CONTROL "フォント名(&N):", -1, "STATIC", SS_RIGHT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 5, 55, 15 + CONTROL "", edt1, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_BORDER | WS_TABSTOP, 70, 6, 120, 14 + CONTROL "", cmb3, "ComboBoxEx32", CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 195, 6, 115, 120 + CONTROL "代替名(&S):", -1, "STATIC", SS_RIGHT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 25, 55, 15 + CONTROL "", cmb2, "ComboBoxEx32", CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 70, 26, 120, 120 + CONTROL "", cmb4, "ComboBoxEx32", CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 195, 26, 115, 120 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 175, 45, 60, 14 + CONTROL "キャンセル", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 240, 45, 60, 14 + CONTROL "削除(&D)", psh1, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 45, 60, 14 +END diff --git a/rosapps/applications/sysutils/fontsub/nil.bmp b/rosapps/applications/sysutils/fontsub/nil.bmp new file mode 100644 index 00000000000..c0efce3742b Binary files /dev/null and b/rosapps/applications/sysutils/fontsub/nil.bmp differ diff --git a/rosapps/applications/sysutils/fontsub/resource.h b/rosapps/applications/sysutils/fontsub/resource.h new file mode 100644 index 00000000000..9b71f337f83 --- /dev/null +++ b/rosapps/applications/sysutils/fontsub/resource.h @@ -0,0 +1,40 @@ +/* FontSub by Katayama Hirofumi MZ + * + * To the extent possible under law, the person who associated CC0 with + * FontSub has waived all copyright and related or neighboring rights + * to FontSub. + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +#define ID_NEW 100 +#define ID_EDIT 101 +#define ID_EXIT 102 +#define ID_UPDATE_REGISTRY 103 +#define ID_DELETE 104 +#define ID_IMPORT 105 +#define ID_EXPORT 106 +#define ID_RELOAD 107 +#define ID_ABOUT 108 +#define ID_OPEN_REGKEY 109 + +#define IDD_ADD 1 +#define IDD_EDIT 2 + +#define IDS_TITLE 1 +#define IDS_FONTNAME 2 +#define IDS_SUBSTITUTE 3 +#define IDS_ENTERNAME 4 +#define IDS_IMPORT 5 +#define IDS_EXPORT 6 +#define IDS_CANTIMPORT 7 +#define IDS_CANTEXPORT 8 +#define IDS_INPFILTER 9 +#define IDS_OUTFILTER 10 +#define IDS_QUERYUPDATE 11 +#define IDS_ALREADYEXISTS 12 +#define IDS_ENTERNAME2 13 +#define IDS_QUERYDELETE 14 +#define IDS_CANTOPENKEY 15 +#define IDS_REBOOTNOW 16 +#define IDS_ABOUT 17 diff --git a/rosapps/applications/sysutils/fontsub/up.bmp b/rosapps/applications/sysutils/fontsub/up.bmp new file mode 100644 index 00000000000..fbb8bf8a29a Binary files /dev/null and b/rosapps/applications/sysutils/fontsub/up.bmp differ