1 /*
2  *  Notepad (settings.c)
3  *
4  *  Copyright 1998,99 Marcel Baur <mbaur@g26.ethz.ch>
5  *  Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr>
6  *  Copyright 2002 Andriy Palamarchuk
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 #include "notepad.h"
24 
25 #include <winreg.h>
26 
27 static LPCTSTR s_szRegistryKey = _T("Software\\Microsoft\\Notepad");
28 
29 
30 static LONG HeightFromPointSize(DWORD dwPointSize)
31 {
32     LONG lHeight;
33     HDC hDC;
34 
35     hDC = GetDC(NULL);
36     lHeight = -MulDiv(dwPointSize, GetDeviceCaps(hDC, LOGPIXELSY), 720);
37     ReleaseDC(NULL, hDC);
38 
39     return lHeight;
40 }
41 
42 static DWORD PointSizeFromHeight(LONG lHeight)
43 {
44     DWORD dwPointSize;
45     HDC hDC;
46 
47     hDC = GetDC(NULL);
48     dwPointSize = -MulDiv(lHeight, 720, GetDeviceCaps(hDC, LOGPIXELSY));
49     ReleaseDC(NULL, hDC);
50 
51     /* round to nearest multiple of 10 */
52     dwPointSize += 5;
53     dwPointSize -= dwPointSize % 10;
54 
55     return dwPointSize;
56 }
57 
58 static BOOL
59 QueryGeneric(HKEY hKey, LPCTSTR pszValueNameT, DWORD dwExpectedType,
60              LPVOID pvResult, DWORD dwResultSize)
61 {
62     DWORD dwType, cbData;
63     LPVOID *pTemp = _alloca(dwResultSize);
64 
65     ZeroMemory(pTemp, dwResultSize);
66 
67     cbData = dwResultSize;
68     if (RegQueryValueEx(hKey, pszValueNameT, NULL, &dwType, (LPBYTE) pTemp, &cbData) != ERROR_SUCCESS)
69         return FALSE;
70 
71     if (dwType != dwExpectedType)
72         return FALSE;
73 
74     memcpy(pvResult, pTemp, cbData);
75     return TRUE;
76 }
77 
78 static BOOL QueryDword(HKEY hKey, LPCTSTR pszValueName, DWORD *pdwResult)
79 {
80     return QueryGeneric(hKey, pszValueName, REG_DWORD, pdwResult, sizeof(*pdwResult));
81 }
82 
83 static BOOL QueryByte(HKEY hKey, LPCTSTR pszValueName, BYTE *pbResult)
84 {
85     DWORD dwResult;
86     if (!QueryGeneric(hKey, pszValueName, REG_DWORD, &dwResult, sizeof(dwResult)))
87         return FALSE;
88     if (dwResult >= 0x100)
89         return FALSE;
90     *pbResult = (BYTE) dwResult;
91     return TRUE;
92 }
93 
94 static BOOL QueryBool(HKEY hKey, LPCTSTR pszValueName, BOOL *pbResult)
95 {
96     DWORD dwResult;
97     if (!QueryDword(hKey, pszValueName, &dwResult))
98         return FALSE;
99     *pbResult = dwResult ? TRUE : FALSE;
100     return TRUE;
101 }
102 
103 static BOOL QueryString(HKEY hKey, LPCTSTR pszValueName, LPTSTR pszResult, DWORD dwResultSize)
104 {
105     return QueryGeneric(hKey, pszValueName, REG_SZ, pszResult, dwResultSize * sizeof(TCHAR));
106 }
107 
108 /***********************************************************************
109  *
110  *           NOTEPAD_LoadSettingsFromRegistry
111  *
112  *  Load settings from registry HKCU\Software\Microsoft\Notepad.
113  */
114 void NOTEPAD_LoadSettingsFromRegistry(void)
115 {
116     HKEY hKey = NULL;
117     HFONT hFont;
118     DWORD dwPointSize = 0;
119     INT base_length, dx, dy;
120 
121     base_length = (GetSystemMetrics(SM_CXSCREEN) > GetSystemMetrics(SM_CYSCREEN)) ?
122                   GetSystemMetrics(SM_CYSCREEN) : GetSystemMetrics(SM_CXSCREEN);
123 
124     dx = (INT)(base_length * .95);
125     dy = dx * 3 / 4;
126     SetRect(&Globals.main_rect, 0, 0, dx, dy);
127 
128     if (RegOpenKey(HKEY_CURRENT_USER, s_szRegistryKey, &hKey) == ERROR_SUCCESS)
129     {
130         QueryByte(hKey, _T("lfCharSet"), &Globals.lfFont.lfCharSet);
131         QueryByte(hKey, _T("lfClipPrecision"), &Globals.lfFont.lfClipPrecision);
132         QueryDword(hKey, _T("lfEscapement"), (DWORD*)&Globals.lfFont.lfEscapement);
133         QueryString(hKey, _T("lfFaceName"), Globals.lfFont.lfFaceName, ARRAY_SIZE(Globals.lfFont.lfFaceName));
134         QueryByte(hKey, _T("lfItalic"), &Globals.lfFont.lfItalic);
135         QueryDword(hKey, _T("lfOrientation"), (DWORD*)&Globals.lfFont.lfOrientation);
136         QueryByte(hKey, _T("lfOutPrecision"), &Globals.lfFont.lfOutPrecision);
137         QueryByte(hKey, _T("lfPitchAndFamily"), &Globals.lfFont.lfPitchAndFamily);
138         QueryByte(hKey, _T("lfQuality"), &Globals.lfFont.lfQuality);
139         QueryByte(hKey, _T("lfStrikeOut"), &Globals.lfFont.lfStrikeOut);
140         QueryByte(hKey, _T("lfUnderline"), &Globals.lfFont.lfUnderline);
141         QueryDword(hKey, _T("lfWeight"), (DWORD*)&Globals.lfFont.lfWeight);
142         QueryDword(hKey, _T("iPointSize"), &dwPointSize);
143         QueryBool(hKey, _T("fWrap"), &Globals.bWrapLongLines);
144         QueryBool(hKey, _T("fStatusBar"), &Globals.bShowStatusBar);
145         QueryString(hKey, _T("szHeader"), Globals.szHeader, ARRAY_SIZE(Globals.szHeader));
146         QueryString(hKey, _T("szTrailer"), Globals.szFooter, ARRAY_SIZE(Globals.szFooter));
147         QueryDword(hKey, _T("iMarginLeft"), (DWORD*)&Globals.lMargins.left);
148         QueryDword(hKey, _T("iMarginTop"), (DWORD*)&Globals.lMargins.top);
149         QueryDword(hKey, _T("iMarginRight"), (DWORD*)&Globals.lMargins.right);
150         QueryDword(hKey, _T("iMarginBottom"), (DWORD*)&Globals.lMargins.bottom);
151 
152         QueryDword(hKey, _T("iWindowPosX"), (DWORD*)&Globals.main_rect.left);
153         QueryDword(hKey, _T("iWindowPosY"), (DWORD*)&Globals.main_rect.top);
154         QueryDword(hKey, _T("iWindowPosDX"), (DWORD*)&dx);
155         QueryDword(hKey, _T("iWindowPosDY"), (DWORD*)&dy);
156 
157         Globals.main_rect.right = Globals.main_rect.left + dx;
158         Globals.main_rect.bottom = Globals.main_rect.top + dy;
159 
160         /* invert value because DIALOG_ViewStatusBar will be called to show it */
161         Globals.bShowStatusBar = !Globals.bShowStatusBar;
162 
163         if (dwPointSize != 0)
164             Globals.lfFont.lfHeight = HeightFromPointSize(dwPointSize);
165         else
166             Globals.lfFont.lfHeight = HeightFromPointSize(100);
167 
168         RegCloseKey(hKey);
169     }
170     else
171     {
172         /* If no settings are found in the registry, then use default values */
173         Globals.bShowStatusBar = FALSE;
174         Globals.bWrapLongLines = FALSE;
175         SetRect(&Globals.lMargins, 750, 1000, 750, 1000);
176 
177         /* FIXME: Globals.fSaveWindowPositions = FALSE; */
178         /* FIXME: Globals.fMLE_is_broken = FALSE; */
179 
180         LoadString(Globals.hInstance, STRING_PAGESETUP_HEADERVALUE, Globals.szHeader,
181                    ARRAY_SIZE(Globals.szHeader));
182         LoadString(Globals.hInstance, STRING_PAGESETUP_FOOTERVALUE, Globals.szFooter,
183                    ARRAY_SIZE(Globals.szFooter));
184 
185         ZeroMemory(&Globals.lfFont, sizeof(Globals.lfFont));
186         Globals.lfFont.lfCharSet = DEFAULT_CHARSET;
187         Globals.lfFont.lfClipPrecision = CLIP_STROKE_PRECIS;
188         Globals.lfFont.lfEscapement = 0;
189         LoadString(Globals.hInstance, STRING_DEFAULTFONT, Globals.lfFont.lfFaceName,
190                    ARRAY_SIZE(Globals.lfFont.lfFaceName));
191         Globals.lfFont.lfItalic = FALSE;
192         Globals.lfFont.lfOrientation = 0;
193         Globals.lfFont.lfOutPrecision = OUT_STRING_PRECIS;
194 
195         /* WORKAROUND: Far East Asian users may not have suitable fixed-pitch fonts. */
196         switch (PRIMARYLANGID(GetUserDefaultLangID()))
197         {
198             case LANG_CHINESE:
199             case LANG_JAPANESE:
200             case LANG_KOREAN:
201                 Globals.lfFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
202                 break;
203             default:
204                 Globals.lfFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
205                 break;
206         }
207 
208         Globals.lfFont.lfQuality = PROOF_QUALITY;
209         Globals.lfFont.lfStrikeOut = FALSE;
210         Globals.lfFont.lfUnderline = FALSE;
211         Globals.lfFont.lfWeight = FW_NORMAL;
212         Globals.lfFont.lfHeight = HeightFromPointSize(100);
213     }
214 
215     hFont = CreateFontIndirect(&Globals.lfFont);
216     SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
217     if (hFont)
218     {
219         if (Globals.hFont)
220             DeleteObject(Globals.hFont);
221         Globals.hFont = hFont;
222     }
223 }
224 
225 static BOOL SaveDword(HKEY hKey, LPCTSTR pszValueNameT, DWORD dwValue)
226 {
227     return RegSetValueEx(hKey, pszValueNameT, 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(dwValue)) == ERROR_SUCCESS;
228 }
229 
230 static BOOL SaveString(HKEY hKey, LPCTSTR pszValueNameT, LPCTSTR pszValue)
231 {
232     return RegSetValueEx(hKey, pszValueNameT, 0, REG_SZ, (LPBYTE) pszValue, (DWORD) _tcslen(pszValue) * sizeof(*pszValue)) == ERROR_SUCCESS;
233 }
234 
235 /***********************************************************************
236  *
237  *           NOTEPAD_SaveSettingsToRegistry
238  *
239  *  Save settings to registry HKCU\Software\Microsoft\Notepad.
240  */
241 void NOTEPAD_SaveSettingsToRegistry(void)
242 {
243     HKEY hKey;
244     DWORD dwDisposition;
245 
246     GetWindowRect(Globals.hMainWnd, &Globals.main_rect);
247 
248     if (RegCreateKeyEx(HKEY_CURRENT_USER, s_szRegistryKey,
249                        0, NULL, 0, KEY_SET_VALUE, NULL,
250                        &hKey, &dwDisposition) == ERROR_SUCCESS)
251     {
252         SaveDword(hKey, _T("lfCharSet"), Globals.lfFont.lfCharSet);
253         SaveDword(hKey, _T("lfClipPrecision"), Globals.lfFont.lfClipPrecision);
254         SaveDword(hKey, _T("lfEscapement"), Globals.lfFont.lfEscapement);
255         SaveString(hKey, _T("lfFaceName"), Globals.lfFont.lfFaceName);
256         SaveDword(hKey, _T("lfItalic"), Globals.lfFont.lfItalic);
257         SaveDword(hKey, _T("lfOrientation"), Globals.lfFont.lfOrientation);
258         SaveDword(hKey, _T("lfOutPrecision"), Globals.lfFont.lfOutPrecision);
259         SaveDword(hKey, _T("lfPitchAndFamily"), Globals.lfFont.lfPitchAndFamily);
260         SaveDword(hKey, _T("lfQuality"), Globals.lfFont.lfQuality);
261         SaveDword(hKey, _T("lfStrikeOut"), Globals.lfFont.lfStrikeOut);
262         SaveDword(hKey, _T("lfUnderline"), Globals.lfFont.lfUnderline);
263         SaveDword(hKey, _T("lfWeight"), Globals.lfFont.lfWeight);
264         SaveDword(hKey, _T("iPointSize"), PointSizeFromHeight(Globals.lfFont.lfHeight));
265         SaveDword(hKey, _T("fWrap"), Globals.bWrapLongLines ? 1 : 0);
266         SaveDword(hKey, _T("fStatusBar"), Globals.bShowStatusBar ? 1 : 0);
267         SaveString(hKey, _T("szHeader"), Globals.szHeader);
268         SaveString(hKey, _T("szTrailer"), Globals.szFooter);
269         SaveDword(hKey, _T("iMarginLeft"), Globals.lMargins.left);
270         SaveDword(hKey, _T("iMarginTop"), Globals.lMargins.top);
271         SaveDword(hKey, _T("iMarginRight"), Globals.lMargins.right);
272         SaveDword(hKey, _T("iMarginBottom"), Globals.lMargins.bottom);
273         SaveDword(hKey, _T("iWindowPosX"), Globals.main_rect.left);
274         SaveDword(hKey, _T("iWindowPosY"), Globals.main_rect.top);
275         SaveDword(hKey, _T("iWindowPosDX"), Globals.main_rect.right - Globals.main_rect.left);
276         SaveDword(hKey, _T("iWindowPosDY"), Globals.main_rect.bottom - Globals.main_rect.top);
277 
278         RegCloseKey(hKey);
279     }
280 }
281