[APPLICATIONS/SYSUTILS] Add a font substitutes editor. Patch by Katayama Hirofumi...
authorMark Jansen <mark.jansen@reactos.org>
Sat, 18 Mar 2017 13:01:18 +0000 (13:01 +0000)
committerMark Jansen <mark.jansen@reactos.org>
Sat, 18 Mar 2017 13:01:18 +0000 (13:01 +0000)
svn path=/trunk/; revision=74187

13 files changed:
rosapps/applications/sysutils/CMakeLists.txt
rosapps/applications/sysutils/fontsub/CMakeLists.txt [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/License.txt [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/down.bmp [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/fontsub.cpp [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/fontsub.ico [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/fontsub.svg [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/fontsub_res.rc [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/lang/en-US.rc [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/lang/ja-JP.rc [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/nil.bmp [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/resource.h [new file with mode: 0644]
rosapps/applications/sysutils/fontsub/up.bmp [new file with mode: 0644]

index 30bd384..ec5888d 100644 (file)
@@ -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 (file)
index 0000000..09e1c73
--- /dev/null
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+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 (file)
index 0000000..6ca207e
--- /dev/null
@@ -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 (file)
index 0000000..13ba2d3
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 (file)
index 0000000..5345bea
--- /dev/null
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+
+#include <windows.h>
+#include <windowsx.h>
+#include <commctrl.h>
+#include <tchar.h>
+#include <vector>       // for std::vector
+#include <set>          // for std::set
+#include <string>       // for std::basic_string
+#include <algorithm>    // for std::sort
+#include <cstdio>
+#include <cstring>
+#include <cassert>
+#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<STRING>    FONTNAMESET;
+typedef std::vector<ITEM>   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<LPWSTR>(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<LPWSTR>(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<LPWSTR>(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<LPWSTR>(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<LPWSTR>(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<BYTE> 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 (file)
index 0000000..f0e8994
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 (file)
index 0000000..32d2cf5
--- /dev/null
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="256"
+   height="256"
+   viewBox="0 0 256 256"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="fontsub.svg"
+   inkscape:export-filename="C:\Users\katahiromz\Desktop\fontsub2\fontsub.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.35"
+     inkscape:cx="-96.950454"
+     inkscape:cy="-3.229257"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:snap-bbox="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-intersection-paths="true"
+     inkscape:object-paths="true"
+     inkscape:object-nodes="true"
+     inkscape:snap-smooth-nodes="true"
+     inkscape:snap-midpoints="true"
+     inkscape:snap-object-midpoints="true"
+     inkscape:snap-center="true"
+     inkscape:snap-text-baseline="true"
+     inkscape:snap-page="true"
+     inkscape:snap-global="true"
+     inkscape:window-width="1366"
+     inkscape:window-height="705"
+     inkscape:window-x="-8"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1"
+     units="px" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="レイヤー 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-796.36219)">
+    <g
+       id="g4467"
+       transform="matrix(0.2822222,0,0,0.2822222,0,755.36218)">
+      <rect
+         y="362.76154"
+         x="2.6432549e-006"
+         height="689.60077"
+         width="907.08661"
+         id="rect4240-2"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         y="145.27559"
+         x="7.7024585e-015"
+         height="254.62881"
+         width="907.08661"
+         id="rect4240"
+         style="opacity:1;fill:#b1b1b1;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         y="145.27559"
+         x="2.6432549e-006"
+         height="37.142868"
+         width="907.08661"
+         id="rect3336"
+         style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         y="1015.2194"
+         x="2.6432549e-006"
+         height="37.142868"
+         width="907.08661"
+         id="rect3336-9"
+         style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         transform="matrix(0,-1,1,0,0,0)"
+         y="0"
+         x="-1052.3622"
+         height="37.142868"
+         width="907.08661"
+         id="rect3336-9-4"
+         style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         transform="matrix(0,-1,1,0,0,0)"
+         y="869.94373"
+         x="-1052.3623"
+         height="37.142868"
+         width="907.08661"
+         id="rect3336-9-4-9"
+         style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         transform="matrix(0,-1,1,0,0,0)"
+         y="434.97186"
+         x="-1052.3623"
+         height="37.142868"
+         width="907.08661"
+         id="rect3336-9-4-8"
+         style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         y="580.2475"
+         x="2.6432549e-006"
+         height="37.142868"
+         width="907.08661"
+         id="rect3336-9-4-8-9"
+         style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         y="362.76154"
+         x="2.6432549e-006"
+         height="37.142868"
+         width="907.08661"
+         id="rect3336-9-4-8-9-9"
+         style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <rect
+         y="797.73346"
+         x="2.6432549e-006"
+         height="37.142868"
+         width="907.08661"
+         id="rect3336-9-4-8-9-9-0"
+         style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901" />
+      <g
+         id="g4346">
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98"
+           width="147.08661"
+           height="37.142868"
+           x="-564.2475"
+           y="87.599564"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1"
+           width="118.51518"
+           height="37.142868"
+           x="-206.11475"
+           y="-454.30377"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-8"
+           width="94.285751"
+           height="37.142868"
+           x="-181.88531"
+           y="-516.64795"
+           transform="scale(-1,-1)" />
+      </g>
+      <g
+         transform="translate(0,-2)"
+         id="g4351">
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-4"
+           width="85.427803"
+           height="37.142868"
+           x="-502.58875"
+           y="506.45667"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-6"
+           width="118.51518"
+           height="37.142868"
+           x="-624.97186"
+           y="-454.3038"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-8-7"
+           width="117.19617"
+           height="37.142868"
+           x="-623.65283"
+           y="-510.8382"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-4-1"
+           width="72.800896"
+           height="37.142868"
+           x="-552.87671"
+           y="586.50995"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-6-6"
+           width="118.51518"
+           height="37.142868"
+           x="-623.65283"
+           y="-567.37256"
+           transform="scale(-1,-1)" />
+      </g>
+      <g
+         id="g4346-9"
+         transform="translate(0,217.11474)">
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-6"
+           width="147.08661"
+           height="37.142868"
+           x="-564.2475"
+           y="87.599564"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-5"
+           width="118.51518"
+           height="37.142868"
+           x="-206.11475"
+           y="-454.30377"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-8-8"
+           width="94.285751"
+           height="37.142868"
+           x="-181.88531"
+           y="-516.64795"
+           transform="scale(-1,-1)" />
+      </g>
+      <g
+         id="g4346-9-6"
+         transform="translate(0,434.22944)">
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-6-9"
+           width="147.08661"
+           height="37.142868"
+           x="-564.2475"
+           y="87.599564"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-5-2"
+           width="118.51518"
+           height="37.142868"
+           x="-206.11475"
+           y="-454.30377"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-8-8-5"
+           width="94.285751"
+           height="37.142868"
+           x="-181.88531"
+           y="-516.64795"
+           transform="scale(-1,-1)" />
+      </g>
+      <g
+         transform="translate(0,215.61916)"
+         id="g4351-9">
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-4-8"
+           width="85.427803"
+           height="37.142868"
+           x="-502.58875"
+           y="506.45667"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-6-7"
+           width="118.51518"
+           height="37.142868"
+           x="-624.97186"
+           y="-454.3038"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-8-7-3"
+           width="117.19617"
+           height="37.142868"
+           x="-623.65283"
+           y="-510.8382"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-4-1-2"
+           width="72.800896"
+           height="37.142868"
+           x="-552.87671"
+           y="586.50995"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-6-6-4"
+           width="118.51518"
+           height="37.142868"
+           x="-623.65283"
+           y="-567.37256"
+           transform="scale(-1,-1)" />
+      </g>
+      <g
+         transform="translate(0,433.23832)"
+         id="g4351-1">
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-4-15"
+           width="85.427803"
+           height="37.142868"
+           x="-502.58875"
+           y="506.45667"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-6-64"
+           width="118.51518"
+           height="37.142868"
+           x="-624.97186"
+           y="-454.3038"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-8-7-9"
+           width="117.19617"
+           height="37.142868"
+           x="-623.65283"
+           y="-510.8382"
+           transform="scale(-1,-1)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-4-1-5"
+           width="72.800896"
+           height="37.142868"
+           x="-552.87671"
+           y="586.50995"
+           transform="matrix(0,-1,1,0,0,0)" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.90200043;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.50243901"
+           id="rect3336-9-4-98-1-6-6-6"
+           width="118.51518"
+           height="37.142868"
+           x="-623.65283"
+           y="-567.37256"
+           transform="scale(-1,-1)" />
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/rosapps/applications/sysutils/fontsub/fontsub_res.rc b/rosapps/applications/sysutils/fontsub/fontsub_res.rc
new file mode 100644 (file)
index 0000000..46ffa50
--- /dev/null
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+#include <windef.h>
+#include <winuser.h>
+#include <dlgs.h>
+
+#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 <reactos/version.rc>
+
+/* 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 (file)
index 0000000..4685d43
--- /dev/null
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+/* 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 (file)
index 0000000..71d7cd6
--- /dev/null
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+/* 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 (file)
index 0000000..c0efce3
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 (file)
index 0000000..9b71f33
--- /dev/null
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+#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 (file)
index 0000000..fbb8bf8
Binary files /dev/null and b/rosapps/applications/sysutils/fontsub/up.bmp differ