OSDN Git Service

Shell Extension for Windows 11 or later (5)
[winmerge-jp/winmerge-jp.git] / Src / OptionsInit.cpp
1 /**
2  * @file  OptionsInit.cpp
3  *
4  * @brief Options initialisation.
5  */
6
7 #include "pch.h"
8 #include <vector>
9 #include <typeinfo>
10 #include "OptionsDef.h"
11 #include "OptionsMgr.h"
12 #include "RegOptionsMgr.h"
13 #include "OptionsCustomColors.h"
14 #include "OptionsDiffOptions.h"
15 #include "OptionsDiffColors.h"
16 #include "OptionsDirColors.h"
17 #include "OptionsEditorSyntax.h"
18 #include "OptionsFont.h"
19 #include "OptionsProject.h"
20 #include "DiffWrapper.h" // CMP_CONTENT
21 #include "paths.h"
22 #include "Environment.h"
23 #include "FileTransform.h"
24 #include "Constants.h"
25
26 // Functions to copy values set by installer from HKLM to HKCU.
27 static bool OpenHKLM(HKEY *key, LPCTSTR relpath = nullptr);
28 static bool OpenHKCU(HKEY *key, LPCTSTR relpath = nullptr);
29 static void CopyFromLMtoCU(HKEY lmKey, HKEY cuKey, LPCTSTR valname);
30
31 namespace Options
32 {
33
34 /**
35  * @brief Initialise options and set default values.
36  *
37  * @note Remember default values are what users see first time
38  * using WinMerge and many users never change them. So pick
39  * default values carefully!
40  */
41 void Init(COptionsMgr *pOptions)
42 {
43         if (typeid(*pOptions) == typeid(CRegOptionsMgr))
44         {
45                 static_cast<CRegOptionsMgr*>(pOptions)->SetRegRootKey(_T("Thingamahoochie\\WinMerge\\"));
46         }
47
48         LANGID LangId = GetUserDefaultLangID();
49         pOptions->InitOption(OPT_SELECTED_LANGUAGE, static_cast<int>(LangId));
50
51         // Initialise options (name, default value)
52         pOptions->InitOption(OPT_SHOW_UNIQUE_LEFT, true);
53         pOptions->InitOption(OPT_SHOW_UNIQUE_MIDDLE, true);
54         pOptions->InitOption(OPT_SHOW_UNIQUE_RIGHT, true);
55         pOptions->InitOption(OPT_SHOW_DIFFERENT, true);
56         pOptions->InitOption(OPT_SHOW_IDENTICAL, true);
57         pOptions->InitOption(OPT_SHOW_BINARIES, true);
58         pOptions->InitOption(OPT_SHOW_SKIPPED, false);
59         pOptions->InitOption(OPT_SHOW_DIFFERENT_LEFT_ONLY, true);
60         pOptions->InitOption(OPT_SHOW_DIFFERENT_MIDDLE_ONLY, true);
61         pOptions->InitOption(OPT_SHOW_DIFFERENT_RIGHT_ONLY, true);
62         pOptions->InitOption(OPT_SHOW_MISSING_LEFT_ONLY, true);
63         pOptions->InitOption(OPT_SHOW_MISSING_MIDDLE_ONLY, true);
64         pOptions->InitOption(OPT_SHOW_MISSING_RIGHT_ONLY, true);
65
66         pOptions->InitOption(OPT_SHOW_TOOLBAR, true);
67         pOptions->InitOption(OPT_SHOW_STATUSBAR, true);
68         pOptions->InitOption(OPT_SHOW_TABBAR, true);
69         pOptions->InitOption(OPT_TOOLBAR_SIZE, 0, 0, 2);
70         pOptions->InitOption(OPT_RESIZE_PANES, false);
71
72         pOptions->InitOption(OPT_SYNTAX_HIGHLIGHT, true);
73         pOptions->InitOption(OPT_WORDWRAP, false);
74         pOptions->InitOption(OPT_VIEW_LINENUMBERS, false);
75         pOptions->InitOption(OPT_VIEW_WHITESPACE, false);
76         pOptions->InitOption(OPT_VIEW_EOL, false);
77         pOptions->InitOption(OPT_SCROLL_TO_FIRST, false);
78         pOptions->InitOption(OPT_SCROLL_TO_FIRST_INLINE_DIFF, false);
79         pOptions->InitOption(OPT_VERIFY_OPEN_PATHS, true);
80         pOptions->InitOption(OPT_AUTO_COMPLETE_SOURCE, (int)1, 0, 2);
81         pOptions->InitOption(OPT_VIEW_FILEMARGIN, false);
82         pOptions->InitOption(OPT_DIFF_CONTEXT, (int)-1);
83         pOptions->InitOption(OPT_INVERT_DIFF_CONTEXT, false);
84         pOptions->InitOption(OPT_SPLIT_HORIZONTALLY, false);
85         pOptions->InitOption(OPT_RENDERING_MODE, -1, 0, 6);
86         pOptions->InitOption(OPT_FILE_SIZE_THRESHOLD, 64*1024*1024);
87
88         pOptions->InitOption(OPT_WORDDIFF_HIGHLIGHT, true);
89         pOptions->InitOption(OPT_BREAK_SEPARATORS, _T(".,:;?[](){}<=>`'!\"#$%&^~\\|@+-*/"));
90
91         pOptions->InitOption(OPT_BACKUP_FOLDERCMP, false);
92         pOptions->InitOption(OPT_BACKUP_FILECMP, true);
93         pOptions->InitOption(OPT_BACKUP_LOCATION, (int)0, 0, 1);
94         pOptions->InitOption(OPT_BACKUP_GLOBALFOLDER, _T(""));
95         pOptions->InitOption(OPT_BACKUP_ADD_BAK, true);
96         pOptions->InitOption(OPT_BACKUP_ADD_TIME, false);
97
98         pOptions->InitOption(OPT_DIRVIEW_SORT_COLUMN, (int)-1, -1, 128);
99         pOptions->InitOption(OPT_DIRVIEW_SORT_COLUMN3, (int)-1, -1, 128);
100         pOptions->InitOption(OPT_DIRVIEW_SORT_ASCENDING, true);
101         pOptions->InitOption(OPT_SHOW_SELECT_FILES_AT_STARTUP, false);
102         pOptions->InitOption(OPT_DIRVIEW_EXPAND_SUBDIRS, false);
103         pOptions->InitOption(OPT_DIRVIEW_COLUMN_ORDERS, _T(""));
104         pOptions->InitOption(OPT_DIRVIEW_COLUMN_WIDTHS, _T(""));
105         pOptions->InitOption(OPT_DIRVIEW3_COLUMN_ORDERS, _T(""));
106         pOptions->InitOption(OPT_DIRVIEW3_COLUMN_WIDTHS, _T(""));
107
108         pOptions->InitOption(OPT_REPORTFILES_REPORTTYPE, 0, 0, 3);
109         pOptions->InitOption(OPT_REPORTFILES_COPYTOCLIPBOARD, false);
110         pOptions->InitOption(OPT_REPORTFILES_INCLUDEFILECMPREPORT, false);
111
112         pOptions->InitOption(OPT_AUTOMATIC_RESCAN, false);
113         pOptions->InitOption(OPT_ALLOW_MIXED_EOL, false);
114         pOptions->InitOption(OPT_COPY_FULL_LINE, false);
115         pOptions->InitOption(OPT_TAB_SIZE, (int)4, 0, 64);
116         pOptions->InitOption(OPT_TAB_TYPE, (int)0, 0, 1);       // 0 means tabs inserted
117
118         pOptions->InitOption(OPT_EXT_EDITOR_CMD, _T("%windir%\\NOTEPAD.EXE"));
119         pOptions->InitOption(OPT_USE_RECYCLE_BIN, true);
120         pOptions->InitOption(OPT_SINGLE_INSTANCE, 0, 0, 2);
121         pOptions->InitOption(OPT_MERGE_MODE, false);
122         // OPT_WORDDIFF_HIGHLIGHT is initialized above
123         pOptions->InitOption(OPT_BREAK_ON_WORDS, false);
124         pOptions->InitOption(OPT_BREAK_TYPE, 1, 0, 1);
125
126         pOptions->InitOption(OPT_CLOSE_WITH_ESC, 1, 0, 2);
127         pOptions->InitOption(OPT_CLOSE_WITH_OK, false);
128         pOptions->InitOption(OPT_IGNORE_SMALL_FILETIME, false);
129         pOptions->InitOption(OPT_ASK_MULTIWINDOW_CLOSE, false);
130         pOptions->InitOption(OPT_PRESERVE_FILETIMES, false);
131         pOptions->InitOption(OPT_TREE_MODE, true);
132
133         pOptions->InitOption(OPT_CMP_METHOD, (int)CMP_CONTENT, 0, CMP_SIZE);
134         pOptions->InitOption(OPT_CMP_MOVED_BLOCKS, false);
135         pOptions->InitOption(OPT_CMP_MATCH_SIMILAR_LINES, false);
136         pOptions->InitOption(OPT_CMP_STOP_AFTER_FIRST, false);
137         pOptions->InitOption(OPT_CMP_QUICK_LIMIT, 4 * 1024 * 1024); // 4 Megs
138         pOptions->InitOption(OPT_CMP_BINARY_LIMIT, 64 * 1024 * 1024); // 64 Megs
139         pOptions->InitOption(OPT_CMP_COMPARE_THREADS, -1, -128, 128);
140         pOptions->InitOption(OPT_CMP_WALK_UNIQUE_DIRS, true);
141         pOptions->InitOption(OPT_CMP_IGNORE_REPARSE_POINTS, false);
142         pOptions->InitOption(OPT_CMP_IGNORE_CODEPAGE, false);
143         pOptions->InitOption(OPT_CMP_INCLUDE_SUBDIRS, true);
144         pOptions->InitOption(OPT_CMP_ENABLE_IMGCMP_IN_DIRCMP, false);
145
146         pOptions->InitOption(OPT_CMP_BIN_FILEPATTERNS, _T("*.bin;*.frx"));
147
148         pOptions->InitOption(OPT_CMP_CSV_FILEPATTERNS, _T("*.csv"));
149         pOptions->InitOption(OPT_CMP_TSV_FILEPATTERNS, _T("*.tsv"));
150         pOptions->InitOption(OPT_CMP_DSV_FILEPATTERNS, _T(""));
151         pOptions->InitOption(OPT_CMP_DSV_DELIM_CHAR, _T(";"));
152         pOptions->InitOption(OPT_CMP_TBL_ALLOW_NEWLINES_IN_QUOTES, true);
153         pOptions->InitOption(OPT_CMP_TBL_QUOTE_CHAR, _T("\""));
154
155         pOptions->InitOption(OPT_CMP_IMG_FILEPATTERNS, _T("*.bmp;*.cut;*.dds;*.exr;*.g3;*.gif;*.hdr;*.ico;*.iff;*.lbm;*.j2k;*.j2c;*.jng;*.jp2;*.jpg;*.jif;*.jpeg;*.jpe;*.jxr;*.wdp;*.hdp;*.koa;*.mng;*.pcd;*.pcx;*.pfm;*.pct;*.pict;*.pic;*.png;*.pbm;*.pgm;*.ppm;*.psd;*.ras;*.sgi;*.rgb;*.rgba;*.bw;*.tga;*.targa;*.tif;*.tiff;*.wap;*.wbmp;*.wbm;*.webp;*.xbm;*.xpm"));
156         pOptions->InitOption(OPT_CMP_IMG_SHOWDIFFERENCES, true);
157         pOptions->InitOption(OPT_CMP_IMG_OVERLAYMODE, 0, 0, 3);
158         pOptions->InitOption(OPT_CMP_IMG_OVERLAYALPHA, 30, 0, 100);
159         pOptions->InitOption(OPT_CMP_IMG_DRAGGING_MODE, 1, 0, 5);
160         pOptions->InitOption(OPT_CMP_IMG_ZOOM, 1000, 1, 8000);
161         pOptions->InitOption(OPT_CMP_IMG_USEBACKCOLOR, true);
162         pOptions->InitOption(OPT_CMP_IMG_BACKCOLOR, 0xFFFFFF);
163         pOptions->InitOption(OPT_CMP_IMG_DIFFBLOCKSIZE, 8, 0, 64);
164         pOptions->InitOption(OPT_CMP_IMG_DIFFCOLORALPHA, 70, 0, 100);
165         pOptions->InitOption(OPT_CMP_IMG_THRESHOLD, 0, 0, 442);
166         pOptions->InitOption(OPT_CMP_IMG_INSERTIONDELETIONDETECTION_MODE, 0, 0, 2);
167         pOptions->InitOption(OPT_CMP_IMG_VECTOR_IMAGE_ZOOM_RATIO, 1000, 1, 8000);
168         pOptions->InitOption(OPT_CMP_IMG_OCR_RESULT_TYPE, 0, 0, 2);
169
170         pOptions->InitOption(OPT_PROJECTS_PATH, _T(""));
171         pOptions->InitOption(OPT_USE_SYSTEM_TEMP_PATH, true);
172         pOptions->InitOption(OPT_CUSTOM_TEMP_PATH, _T(""));
173
174         pOptions->InitOption(OPT_LINEFILTER_ENABLED, false);
175         pOptions->InitOption(OPT_SUBSTITUTION_FILTERS_ENABLED, false);
176
177         pOptions->InitOption(OPT_FILEFILTER_CURRENT, _T("*.*"));
178         // CMainFrame initializes this when it is empty.
179         pOptions->InitOption(OPT_FILTER_USERPATH, _T(""));
180         if (pOptions->GetString(OPT_FILTER_USERPATH).empty())
181                 pOptions->SaveOption(OPT_FILTER_USERPATH, paths::ConcatPath(env::GetMyDocuments(), DefaultRelativeFilterPath));
182         pOptions->InitOption(OPT_FILEFILTER_SHARED, false);
183
184         pOptions->InitOption(OPT_CP_DEFAULT_MODE, (int)0);
185         pOptions->InitOption(OPT_CP_DEFAULT_CUSTOM, (int)GetACP());
186
187         if (PRIMARYLANGID(LangId) == LANG_JAPANESE)
188                 pOptions->InitOption(OPT_CP_DETECT, (int)(50932 << 16) | 3);
189         else if (LangId == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED))
190                 pOptions->InitOption(OPT_CP_DETECT, (int)(50936 << 16) | 3);
191         else if (PRIMARYLANGID(LangId) == LANG_KOREAN)
192                 pOptions->InitOption(OPT_CP_DETECT, (int)(50949 << 16) | 3);
193         else if (LangId == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL))
194                 pOptions->InitOption(OPT_CP_DETECT, (int)(50950 << 16) | 3);
195         else
196                 pOptions->InitOption(OPT_CP_DETECT, (int)(50001 << 16) | 1);
197
198         pOptions->InitOption(OPT_ARCHIVE_ENABLE, true); // Enable by default
199         pOptions->InitOption(OPT_ARCHIVE_PROBETYPE, false);
200         pOptions->InitOption(OPT_ARCHIVE_FILTER_INDEX, 1);
201
202         pOptions->InitOption(OPT_PLUGINS_ENABLED, true);
203         pOptions->InitOption(OPT_PLUGINS_CUSTOM_SETTINGS_LIST, _T(""));
204         pOptions->InitOption(OPT_PLUGINS_UNPACKER_MODE, false);
205         pOptions->InitOption(OPT_PLUGINS_PREDIFFER_MODE, false);
206         pOptions->InitOption(OPT_PLUGINS_UNPACK_DONT_CHECK_EXTENSION, true);
207         pOptions->InitOption(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE, false);
208
209         pOptions->InitOption(OPT_PATCHCREATOR_PATCH_STYLE, 0, 0, 3);
210         pOptions->InitOption(OPT_PATCHCREATOR_CONTEXT_LINES, 0);
211         pOptions->InitOption(OPT_PATCHCREATOR_CASE_SENSITIVE, true);
212         pOptions->InitOption(OPT_PATCHCREATOR_EOL_SENSITIVE, true);
213         pOptions->InitOption(OPT_PATCHCREATOR_IGNORE_BLANK_LINES, false);
214         pOptions->InitOption(OPT_PATCHCREATOR_WHITESPACE, WHITESPACE_COMPARE_ALL, WHITESPACE_COMPARE_ALL, WHITESPACE_IGNORE_ALL);
215         pOptions->InitOption(OPT_PATCHCREATOR_OPEN_TO_EDITOR, false);
216         pOptions->InitOption(OPT_PATCHCREATOR_INCLUDE_CMD_LINE, false);
217
218         pOptions->InitOption(OPT_TABBAR_AUTO_MAXWIDTH, true);
219         pOptions->InitOption(OPT_ACTIVE_FRAME_MAX, true);
220         pOptions->InitOption(OPT_ACTIVE_PANE, 0, 0, 2);
221
222         pOptions->InitOption(OPT_MRU_MAX, 9, 0, 128);
223
224         pOptions->InitOption(OPT_COLOR_SCHEME, _T("Default"));
225
226         Options::CustomColors::Init(pOptions);
227         Options::DiffOptions::Init(pOptions);
228         Options::DiffColors::Init(pOptions);
229         Options::DirColors::Init(pOptions);
230         Options::EditorSyntax::Init(pOptions);
231         Options::Font::Init(pOptions);
232         Options::Project::Init(pOptions);
233 }
234
235 /**
236  * @brief Copy some HKLM values to HKCU.
237  * The installer sets HKLM values for "all users". This function copies
238  * few of those values for "user" values. E.g. enabling ShellExtension
239  * initially for user is done by this function.
240  */
241 void CopyHKLMValues()
242 {
243         HKEY LMKey;
244         HKEY CUKey;
245         if (OpenHKLM(&LMKey))
246         {
247                 if (OpenHKCU(&CUKey))
248                 {
249                         CopyFromLMtoCU(LMKey, CUKey, _T("ContextMenuEnabled"));
250                         CopyFromLMtoCU(LMKey, CUKey, _T("Executable"));
251                         RegCloseKey(CUKey);
252                 }
253                 RegCloseKey(LMKey);
254         }
255         if (OpenHKLM(&LMKey, _T("Locale")))
256         {
257                 if (OpenHKCU(&CUKey, _T("Locale")))
258                 {
259                         CopyFromLMtoCU(LMKey, CUKey, _T("LanguageId"));
260                         RegCloseKey(CUKey);
261                 }
262                 RegCloseKey(LMKey);
263         }
264 }
265
266 }
267
268 /**
269  * @brief Open HKLM registry key.
270  * @param [out] key Pointer to open HKLM key.
271  * @param [in] relpath Relative registry path (to WinMerge reg path) to open, or nullptr.
272  * @return true if opening succeeded.
273  */
274 static bool OpenHKLM(HKEY *key, LPCTSTR relpath)
275 {
276         TCHAR valuename[256];
277         if (relpath)
278                 wsprintf(valuename, _T("%s\\%s"), RegDir, relpath);
279         else
280                 lstrcpy(valuename, RegDir);
281         LONG retval = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
282                         valuename, 0, KEY_READ, key);
283         if (retval == ERROR_SUCCESS)
284         {
285                 return true;
286         }
287         return false;
288 }
289
290 /**
291  * @brief Open HKCU registry key.
292  * Opens the HKCU key for WinMerge. If the key does not exist, creates one.
293  * @param [out] key Pointer to open HKCU key.
294  * @param [in] relpath Relative registry path (to WinMerge reg path) to open, or nullptr.
295  * @return true if opening succeeded.
296  */
297 static bool OpenHKCU(HKEY *key, LPCTSTR relpath)
298 {
299         TCHAR valuename[256];
300         if (relpath)
301                 wsprintf(valuename, _T("%s\\%s"), RegDir, relpath);
302         else
303                 lstrcpy(valuename, RegDir);
304         LONG retval = RegOpenKeyEx(HKEY_CURRENT_USER,
305                         valuename, 0, KEY_ALL_ACCESS, key);
306         if (retval == ERROR_SUCCESS)
307         {
308                 return true;
309         }
310         else if (retval == ERROR_FILE_NOT_FOUND)
311         {
312                 retval = RegCreateKeyEx(HKEY_CURRENT_USER,
313                         valuename, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, key, nullptr);
314                 if (retval == ERROR_SUCCESS)
315                         return true;
316         }
317         return false;
318 }
319
320 /**
321  * @brief Copy value from HKLM to HKCU.
322  * @param [in] lmKey HKLM key from where to copy.
323  * @param [in] cuKey HKCU key to where to copy.
324  * @param [in] valname Name of the value to copy.
325  */
326 static void CopyFromLMtoCU(HKEY lmKey, HKEY cuKey, LPCTSTR valname)
327 {
328         DWORD len = 0;
329         LONG retval = RegQueryValueEx(cuKey, valname, 0, nullptr, nullptr, &len);
330         if (retval == ERROR_FILE_NOT_FOUND)
331         {
332                 retval = RegQueryValueEx(lmKey, valname, 0, nullptr, nullptr, &len);
333                 if (retval == ERROR_SUCCESS)
334                 {
335                         DWORD type = 0;
336                         std::vector<BYTE> buf(len);
337                         retval = RegQueryValueEx(lmKey, valname, 0, &type, &buf[0], &len);
338                         if (retval == ERROR_SUCCESS)
339                         {
340                                 RegSetValueEx(cuKey, valname , 0, type,
341                                         &buf[0], len);
342                         }
343                 }
344         }
345 }