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 
HeightFromPointSize(DWORD dwPointSize)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 
PointSizeFromHeight(LONG lHeight)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
QueryGeneric(HKEY hKey,LPCTSTR pszValueNameT,DWORD dwExpectedType,LPVOID pvResult,DWORD dwResultSize)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 
QueryDword(HKEY hKey,LPCTSTR pszValueName,DWORD * pdwResult)65 static BOOL QueryDword(HKEY hKey, LPCTSTR pszValueName, DWORD *pdwResult)
66 {
67     return QueryGeneric(hKey, pszValueName, REG_DWORD, pdwResult, sizeof(*pdwResult));
68 }
69 
QueryByte(HKEY hKey,LPCTSTR pszValueName,BYTE * pbResult)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 
QueryBool(HKEY hKey,LPCTSTR pszValueName,BOOL * pbResult)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 
QueryString(HKEY hKey,LPCTSTR pszValueName,LPTSTR pszResult,DWORD dwResultLength)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  */
NOTEPAD_LoadSettingsFromRegistry(PWINDOWPLACEMENT pWP)105 void NOTEPAD_LoadSettingsFromRegistry(PWINDOWPLACEMENT pWP)
106 {
107     HKEY hKey;
108     HFONT hFont;
109     DWORD dwPointSize;
110     DWORD x = CW_USEDEFAULT, y = CW_USEDEFAULT, cx = 0, cy = 0;
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 
122     /* FIXME: Globals.fSaveWindowPositions = FALSE; */
123     /* FIXME: Globals.fMLE_is_broken = FALSE; */
124 
125     /* Open the target registry key */
126     if (RegOpenKey(HKEY_CURRENT_USER, s_szRegistryKey, &hKey) != ERROR_SUCCESS)
127         hKey = NULL;
128 
129     /* Load the values from registry */
130     if (hKey)
131     {
132         QueryByte(hKey, _T("lfCharSet"), &Globals.lfFont.lfCharSet);
133         QueryByte(hKey, _T("lfClipPrecision"), &Globals.lfFont.lfClipPrecision);
134         QueryDword(hKey, _T("lfEscapement"), (DWORD*)&Globals.lfFont.lfEscapement);
135         QueryByte(hKey, _T("lfItalic"), &Globals.lfFont.lfItalic);
136         QueryDword(hKey, _T("lfOrientation"), (DWORD*)&Globals.lfFont.lfOrientation);
137         QueryByte(hKey, _T("lfOutPrecision"), &Globals.lfFont.lfOutPrecision);
138         QueryByte(hKey, _T("lfPitchAndFamily"), &Globals.lfFont.lfPitchAndFamily);
139         QueryByte(hKey, _T("lfQuality"), &Globals.lfFont.lfQuality);
140         QueryByte(hKey, _T("lfStrikeOut"), &Globals.lfFont.lfStrikeOut);
141         QueryByte(hKey, _T("lfUnderline"), &Globals.lfFont.lfUnderline);
142         QueryDword(hKey, _T("lfWeight"), (DWORD*)&Globals.lfFont.lfWeight);
143         QueryDword(hKey, _T("iPointSize"), &dwPointSize);
144 
145         QueryBool(hKey, _T("fWrap"), &Globals.bWrapLongLines);
146         QueryBool(hKey, _T("fStatusBar"), &Globals.bShowStatusBar);
147 
148         QueryDword(hKey, _T("iMarginLeft"), (DWORD*)&Globals.lMargins.left);
149         QueryDword(hKey, _T("iMarginTop"), (DWORD*)&Globals.lMargins.top);
150         QueryDword(hKey, _T("iMarginRight"), (DWORD*)&Globals.lMargins.right);
151         QueryDword(hKey, _T("iMarginBottom"), (DWORD*)&Globals.lMargins.bottom);
152 
153         QueryDword(hKey, _T("iWindowPosX"), &x);
154         QueryDword(hKey, _T("iWindowPosY"), &y);
155         QueryDword(hKey, _T("iWindowPosDX"), &cx);
156         QueryDword(hKey, _T("iWindowPosDY"), &cy);
157 
158         QueryString(hKey, _T("searchString"), Globals.szFindText, _countof(Globals.szFindText));
159         QueryString(hKey, _T("replaceString"), Globals.szReplaceText, _countof(Globals.szReplaceText));
160     }
161 
162     pWP->length = sizeof(*pWP);
163     pWP->flags = 0;
164     pWP->showCmd = SW_SHOWDEFAULT;
165     if (cy & 0x80000000)
166     {
167         cy &= ~0x80000000;
168         pWP->flags |= WPF_RESTORETOMAXIMIZED;
169         pWP->showCmd = SW_SHOWMAXIMIZED;
170     }
171     pWP->rcNormalPosition.left = x;
172     pWP->rcNormalPosition.right = x + cx;
173     pWP->rcNormalPosition.top = y;
174     pWP->rcNormalPosition.bottom = y + cy;
175     pWP->ptMaxPosition.x = x;
176     pWP->ptMaxPosition.y = y;
177 
178     Globals.lfFont.lfHeight = HeightFromPointSize(dwPointSize);
179     if (!hKey || !QueryString(hKey, _T("lfFaceName"),
180                               Globals.lfFont.lfFaceName, _countof(Globals.lfFont.lfFaceName)))
181     {
182         LoadString(Globals.hInstance, STRING_DEFAULTFONT, Globals.lfFont.lfFaceName,
183                    _countof(Globals.lfFont.lfFaceName));
184     }
185 
186     if (!hKey || !QueryString(hKey, _T("szHeader"), Globals.szHeader, _countof(Globals.szHeader)))
187     {
188         LoadString(Globals.hInstance, STRING_PAGESETUP_HEADERVALUE, Globals.szHeader,
189                    _countof(Globals.szHeader));
190     }
191 
192     if (!hKey || !QueryString(hKey, _T("szTrailer"), Globals.szFooter, _countof(Globals.szFooter)))
193     {
194         LoadString(Globals.hInstance, STRING_PAGESETUP_FOOTERVALUE, Globals.szFooter,
195                    _countof(Globals.szFooter));
196     }
197 
198     if (hKey)
199         RegCloseKey(hKey);
200 
201     /* WORKAROUND: Far East Asian users may not have suitable fixed-pitch fonts. */
202     switch (PRIMARYLANGID(GetUserDefaultLangID()))
203     {
204         case LANG_CHINESE:
205         case LANG_JAPANESE:
206         case LANG_KOREAN:
207             Globals.lfFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
208             break;
209     }
210 
211     hFont = CreateFontIndirect(&Globals.lfFont);
212     SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)hFont, TRUE);
213     if (hFont)
214     {
215         if (Globals.hFont)
216             DeleteObject(Globals.hFont);
217         Globals.hFont = hFont;
218     }
219 }
220 
SaveDword(HKEY hKey,LPCTSTR pszValueNameT,DWORD dwValue)221 static BOOL SaveDword(HKEY hKey, LPCTSTR pszValueNameT, DWORD dwValue)
222 {
223     return RegSetValueEx(hKey, pszValueNameT, 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(dwValue)) == ERROR_SUCCESS;
224 }
225 
SaveString(HKEY hKey,LPCTSTR pszValueNameT,LPCTSTR pszValue)226 static BOOL SaveString(HKEY hKey, LPCTSTR pszValueNameT, LPCTSTR pszValue)
227 {
228     return RegSetValueEx(hKey, pszValueNameT, 0, REG_SZ, (LPBYTE) pszValue, (DWORD) _tcslen(pszValue) * sizeof(*pszValue)) == ERROR_SUCCESS;
229 }
230 
231 /***********************************************************************
232  *           NOTEPAD_SaveSettingsToRegistry
233  *
234  *  Save settings to registry HKCU\Software\Microsoft\Notepad.
235  */
NOTEPAD_SaveSettingsToRegistry(void)236 void NOTEPAD_SaveSettingsToRegistry(void)
237 {
238     HKEY hKey;
239     DWORD dwDisposition;
240     WINDOWPLACEMENT wp;
241     UINT x, y, cx, cy;
242 
243     wp.length = sizeof(wp);
244     GetWindowPlacement(Globals.hMainWnd, &wp);
245     x = wp.rcNormalPosition.left;
246     y = wp.rcNormalPosition.top;
247     cx = wp.rcNormalPosition.right - x;
248     cy = wp.rcNormalPosition.bottom - y;
249     if (wp.flags & WPF_RESTORETOMAXIMIZED)
250         cy |= 0x80000000;
251 
252 
253     if (RegCreateKeyEx(HKEY_CURRENT_USER, s_szRegistryKey,
254                        0, NULL, 0, KEY_SET_VALUE, NULL,
255                        &hKey, &dwDisposition) == ERROR_SUCCESS)
256     {
257         SaveDword(hKey, _T("lfCharSet"), Globals.lfFont.lfCharSet);
258         SaveDword(hKey, _T("lfClipPrecision"), Globals.lfFont.lfClipPrecision);
259         SaveDword(hKey, _T("lfEscapement"), Globals.lfFont.lfEscapement);
260         SaveString(hKey, _T("lfFaceName"), Globals.lfFont.lfFaceName);
261         SaveDword(hKey, _T("lfItalic"), Globals.lfFont.lfItalic);
262         SaveDword(hKey, _T("lfOrientation"), Globals.lfFont.lfOrientation);
263         SaveDword(hKey, _T("lfOutPrecision"), Globals.lfFont.lfOutPrecision);
264         SaveDword(hKey, _T("lfPitchAndFamily"), Globals.lfFont.lfPitchAndFamily);
265         SaveDword(hKey, _T("lfQuality"), Globals.lfFont.lfQuality);
266         SaveDword(hKey, _T("lfStrikeOut"), Globals.lfFont.lfStrikeOut);
267         SaveDword(hKey, _T("lfUnderline"), Globals.lfFont.lfUnderline);
268         SaveDword(hKey, _T("lfWeight"), Globals.lfFont.lfWeight);
269         SaveDword(hKey, _T("iPointSize"), PointSizeFromHeight(Globals.lfFont.lfHeight));
270         SaveDword(hKey, _T("fWrap"), Globals.bWrapLongLines ? 1 : 0);
271         SaveDword(hKey, _T("fStatusBar"), Globals.bShowStatusBar ? 1 : 0);
272         SaveString(hKey, _T("szHeader"), Globals.szHeader);
273         SaveString(hKey, _T("szTrailer"), Globals.szFooter);
274         SaveDword(hKey, _T("iMarginLeft"), Globals.lMargins.left);
275         SaveDword(hKey, _T("iMarginTop"), Globals.lMargins.top);
276         SaveDword(hKey, _T("iMarginRight"), Globals.lMargins.right);
277         SaveDword(hKey, _T("iMarginBottom"), Globals.lMargins.bottom);
278         SaveDword(hKey, _T("iWindowPosX"), x);
279         SaveDword(hKey, _T("iWindowPosY"), y);
280         SaveDword(hKey, _T("iWindowPosDX"), cx);
281         SaveDword(hKey, _T("iWindowPosDY"), cy);
282         SaveString(hKey, _T("searchString"), Globals.szFindText);
283         SaveString(hKey, _T("replaceString"), Globals.szReplaceText);
284 
285         RegCloseKey(hKey);
286     }
287 }
288