1 /*
2  * PROJECT:    ReactOS Notepad
3  * LICENSE:    LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:    Providing a Windows-compatible simple text editor for ReactOS
5  * COPYRIGHT:  Copyright 1998,99 Marcel Baur <mbaur@g26.ethz.ch>
6  *             Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr>
7  *             Copyright 2002 Andriy Palamarchuk
8  */
9 
10 #include "notepad.h"
11 
12 #include <winreg.h>
13 
14 static LPCTSTR s_szRegistryKey = _T("Software\\Microsoft\\Notepad");
15 
16 
17 static LONG HeightFromPointSize(DWORD dwPointSize)
18 {
19     LONG lHeight;
20     HDC hDC;
21 
22     hDC = GetDC(NULL);
23     lHeight = -MulDiv(dwPointSize, GetDeviceCaps(hDC, LOGPIXELSY), 720);
24     ReleaseDC(NULL, hDC);
25 
26     return lHeight;
27 }
28 
29 static DWORD PointSizeFromHeight(LONG lHeight)
30 {
31     DWORD dwPointSize;
32     HDC hDC;
33 
34     hDC = GetDC(NULL);
35     dwPointSize = -MulDiv(lHeight, 720, GetDeviceCaps(hDC, LOGPIXELSY));
36     ReleaseDC(NULL, hDC);
37 
38     /* round to nearest multiple of 10 */
39     dwPointSize += 5;
40     dwPointSize -= dwPointSize % 10;
41 
42     return dwPointSize;
43 }
44 
45 static BOOL
46 QueryGeneric(HKEY hKey, LPCTSTR pszValueNameT, DWORD dwExpectedType,
47              LPVOID pvResult, DWORD dwResultSize)
48 {
49     DWORD dwType, cbData;
50     LPVOID *pTemp = _alloca(dwResultSize);
51 
52     ZeroMemory(pTemp, dwResultSize);
53 
54     cbData = dwResultSize;
55     if (RegQueryValueEx(hKey, pszValueNameT, NULL, &dwType, (LPBYTE) pTemp, &cbData) != ERROR_SUCCESS)
56         return FALSE;
57 
58     if (dwType != dwExpectedType)
59         return FALSE;
60 
61     memcpy(pvResult, pTemp, cbData);
62     return TRUE;
63 }
64 
65 static BOOL QueryDword(HKEY hKey, LPCTSTR pszValueName, DWORD *pdwResult)
66 {
67     return QueryGeneric(hKey, pszValueName, REG_DWORD, pdwResult, sizeof(*pdwResult));
68 }
69 
70 static BOOL QueryByte(HKEY hKey, LPCTSTR pszValueName, BYTE *pbResult)
71 {
72     DWORD dwResult;
73     if (!QueryGeneric(hKey, pszValueName, REG_DWORD, &dwResult, sizeof(dwResult)))
74         return FALSE;
75     if (dwResult >= 0x100)
76         return FALSE;
77     *pbResult = (BYTE) dwResult;
78     return TRUE;
79 }
80 
81 static BOOL QueryBool(HKEY hKey, LPCTSTR pszValueName, BOOL *pbResult)
82 {
83     DWORD dwResult;
84     if (!QueryDword(hKey, pszValueName, &dwResult))
85         return FALSE;
86     *pbResult = dwResult ? TRUE : FALSE;
87     return TRUE;
88 }
89 
90 static BOOL QueryString(HKEY hKey, LPCTSTR pszValueName, LPTSTR pszResult, DWORD dwResultLength)
91 {
92     if (dwResultLength == 0)
93         return FALSE;
94     if (!QueryGeneric(hKey, pszValueName, REG_SZ, pszResult, dwResultLength * sizeof(TCHAR)))
95         return FALSE;
96     pszResult[dwResultLength - 1] = 0; /* Avoid buffer overrun */
97     return TRUE;
98 }
99 
100 /***********************************************************************
101  *           NOTEPAD_LoadSettingsFromRegistry
102  *
103  *  Load settings from registry HKCU\Software\Microsoft\Notepad.
104  */
105 void NOTEPAD_LoadSettingsFromRegistry(void)
106 {
107     HKEY hKey;
108     HFONT hFont;
109     DWORD dwPointSize, cx, cy;
110     DWORD cxScreen = GetSystemMetrics(SM_CXSCREEN), cyScreen = GetSystemMetrics(SM_CYSCREEN);
111 
112     /* Set the default values */
113     Globals.bShowStatusBar = TRUE;
114     Globals.bWrapLongLines = FALSE;
115     SetRect(&Globals.lMargins, 750, 1000, 750, 1000);
116     ZeroMemory(&Globals.lfFont, sizeof(Globals.lfFont));
117     Globals.lfFont.lfCharSet = DEFAULT_CHARSET;
118     dwPointSize = 100;
119     Globals.lfFont.lfWeight = FW_NORMAL;
120     Globals.lfFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
121     Globals.main_rect.left = CW_USEDEFAULT;
122     Globals.main_rect.top = CW_USEDEFAULT;
123     cx = min((cxScreen * 3) / 4, 640);
124     cy = min((cyScreen * 3) / 4, 480);
125 
126     /* FIXME: Globals.fSaveWindowPositions = FALSE; */
127     /* FIXME: Globals.fMLE_is_broken = FALSE; */
128 
129     /* Open the target registry key */
130     if (RegOpenKey(HKEY_CURRENT_USER, s_szRegistryKey, &hKey) != ERROR_SUCCESS)
131         hKey = NULL;
132 
133     /* Load the values from registry */
134     if (hKey)
135     {
136         QueryByte(hKey, _T("lfCharSet"), &Globals.lfFont.lfCharSet);
137         QueryByte(hKey, _T("lfClipPrecision"), &Globals.lfFont.lfClipPrecision);
138         QueryDword(hKey, _T("lfEscapement"), (DWORD*)&Globals.lfFont.lfEscapement);
139         QueryByte(hKey, _T("lfItalic"), &Globals.lfFont.lfItalic);
140         QueryDword(hKey, _T("lfOrientation"), (DWORD*)&Globals.lfFont.lfOrientation);
141         QueryByte(hKey, _T("lfOutPrecision"), &Globals.lfFont.lfOutPrecision);
142         QueryByte(hKey, _T("lfPitchAndFamily"), &Globals.lfFont.lfPitchAndFamily);
143         QueryByte(hKey, _T("lfQuality"), &Globals.lfFont.lfQuality);
144         QueryByte(hKey, _T("lfStrikeOut"), &Globals.lfFont.lfStrikeOut);
145         QueryByte(hKey, _T("lfUnderline"), &Globals.lfFont.lfUnderline);
146         QueryDword(hKey, _T("lfWeight"), (DWORD*)&Globals.lfFont.lfWeight);
147         QueryDword(hKey, _T("iPointSize"), &dwPointSize);
148 
149         QueryBool(hKey, _T("fWrap"), &Globals.bWrapLongLines);
150         QueryBool(hKey, _T("fStatusBar"), &Globals.bShowStatusBar);
151 
152         QueryDword(hKey, _T("iMarginLeft"), (DWORD*)&Globals.lMargins.left);
153         QueryDword(hKey, _T("iMarginTop"), (DWORD*)&Globals.lMargins.top);
154         QueryDword(hKey, _T("iMarginRight"), (DWORD*)&Globals.lMargins.right);
155         QueryDword(hKey, _T("iMarginBottom"), (DWORD*)&Globals.lMargins.bottom);
156 
157         QueryDword(hKey, _T("iWindowPosX"), (DWORD*)&Globals.main_rect.left);
158         QueryDword(hKey, _T("iWindowPosY"), (DWORD*)&Globals.main_rect.top);
159         QueryDword(hKey, _T("iWindowPosDX"), &cx);
160         QueryDword(hKey, _T("iWindowPosDY"), &cy);
161 
162         QueryString(hKey, _T("searchString"), Globals.szFindText, _countof(Globals.szFindText));
163         QueryString(hKey, _T("replaceString"), Globals.szReplaceText, _countof(Globals.szReplaceText));
164     }
165 
166     Globals.lfFont.lfHeight = HeightFromPointSize(dwPointSize);
167     Globals.main_rect.right = Globals.main_rect.left + cx;
168     Globals.main_rect.bottom = Globals.main_rect.top + cy;
169 
170     if (!hKey || !QueryString(hKey, _T("lfFaceName"),
171                               Globals.lfFont.lfFaceName, _countof(Globals.lfFont.lfFaceName)))
172     {
173         LoadString(Globals.hInstance, STRING_DEFAULTFONT, Globals.lfFont.lfFaceName,
174                    _countof(Globals.lfFont.lfFaceName));
175     }
176 
177     if (!hKey || !QueryString(hKey, _T("szHeader"), Globals.szHeader, _countof(Globals.szHeader)))
178     {
179         LoadString(Globals.hInstance, STRING_PAGESETUP_HEADERVALUE, Globals.szHeader,
180                    _countof(Globals.szHeader));
181     }
182 
183     if (!hKey || !QueryString(hKey, _T("szTrailer"), Globals.szFooter, _countof(Globals.szFooter)))
184     {
185         LoadString(Globals.hInstance, STRING_PAGESETUP_FOOTERVALUE, Globals.szFooter,
186                    _countof(Globals.szFooter));
187     }
188 
189     if (hKey)
190         RegCloseKey(hKey);
191 
192     /* WORKAROUND: Far East Asian users may not have suitable fixed-pitch fonts. */
193     switch (PRIMARYLANGID(GetUserDefaultLangID()))
194     {
195         case LANG_CHINESE:
196         case LANG_JAPANESE:
197         case LANG_KOREAN:
198             Globals.lfFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
199             break;
200     }
201 
202     hFont = CreateFontIndirect(&Globals.lfFont);
203     SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)hFont, TRUE);
204     if (hFont)
205     {
206         if (Globals.hFont)
207             DeleteObject(Globals.hFont);
208         Globals.hFont = hFont;
209     }
210 }
211 
212 static BOOL SaveDword(HKEY hKey, LPCTSTR pszValueNameT, DWORD dwValue)
213 {
214     return RegSetValueEx(hKey, pszValueNameT, 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(dwValue)) == ERROR_SUCCESS;
215 }
216 
217 static BOOL SaveString(HKEY hKey, LPCTSTR pszValueNameT, LPCTSTR pszValue)
218 {
219     return RegSetValueEx(hKey, pszValueNameT, 0, REG_SZ, (LPBYTE) pszValue, (DWORD) _tcslen(pszValue) * sizeof(*pszValue)) == ERROR_SUCCESS;
220 }
221 
222 /***********************************************************************
223  *           NOTEPAD_SaveSettingsToRegistry
224  *
225  *  Save settings to registry HKCU\Software\Microsoft\Notepad.
226  */
227 void NOTEPAD_SaveSettingsToRegistry(void)
228 {
229     HKEY hKey;
230     DWORD dwDisposition;
231 
232     GetWindowRect(Globals.hMainWnd, &Globals.main_rect);
233 
234     if (RegCreateKeyEx(HKEY_CURRENT_USER, s_szRegistryKey,
235                        0, NULL, 0, KEY_SET_VALUE, NULL,
236                        &hKey, &dwDisposition) == ERROR_SUCCESS)
237     {
238         SaveDword(hKey, _T("lfCharSet"), Globals.lfFont.lfCharSet);
239         SaveDword(hKey, _T("lfClipPrecision"), Globals.lfFont.lfClipPrecision);
240         SaveDword(hKey, _T("lfEscapement"), Globals.lfFont.lfEscapement);
241         SaveString(hKey, _T("lfFaceName"), Globals.lfFont.lfFaceName);
242         SaveDword(hKey, _T("lfItalic"), Globals.lfFont.lfItalic);
243         SaveDword(hKey, _T("lfOrientation"), Globals.lfFont.lfOrientation);
244         SaveDword(hKey, _T("lfOutPrecision"), Globals.lfFont.lfOutPrecision);
245         SaveDword(hKey, _T("lfPitchAndFamily"), Globals.lfFont.lfPitchAndFamily);
246         SaveDword(hKey, _T("lfQuality"), Globals.lfFont.lfQuality);
247         SaveDword(hKey, _T("lfStrikeOut"), Globals.lfFont.lfStrikeOut);
248         SaveDword(hKey, _T("lfUnderline"), Globals.lfFont.lfUnderline);
249         SaveDword(hKey, _T("lfWeight"), Globals.lfFont.lfWeight);
250         SaveDword(hKey, _T("iPointSize"), PointSizeFromHeight(Globals.lfFont.lfHeight));
251         SaveDword(hKey, _T("fWrap"), Globals.bWrapLongLines ? 1 : 0);
252         SaveDword(hKey, _T("fStatusBar"), Globals.bShowStatusBar ? 1 : 0);
253         SaveString(hKey, _T("szHeader"), Globals.szHeader);
254         SaveString(hKey, _T("szTrailer"), Globals.szFooter);
255         SaveDword(hKey, _T("iMarginLeft"), Globals.lMargins.left);
256         SaveDword(hKey, _T("iMarginTop"), Globals.lMargins.top);
257         SaveDword(hKey, _T("iMarginRight"), Globals.lMargins.right);
258         SaveDword(hKey, _T("iMarginBottom"), Globals.lMargins.bottom);
259         SaveDword(hKey, _T("iWindowPosX"), Globals.main_rect.left);
260         SaveDword(hKey, _T("iWindowPosY"), Globals.main_rect.top);
261         SaveDword(hKey, _T("iWindowPosDX"), Globals.main_rect.right - Globals.main_rect.left);
262         SaveDword(hKey, _T("iWindowPosDY"), Globals.main_rect.bottom - Globals.main_rect.top);
263         SaveString(hKey, _T("searchString"), Globals.szFindText);
264         SaveString(hKey, _T("replaceString"), Globals.szReplaceText);
265 
266         RegCloseKey(hKey);
267     }
268 }
269