2 * @file OptionsInit.cpp
4 * @brief Options initialisation.
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 "DiffWrapper.h" // CMP_CONTENT
21 #include "Environment.h"
22 #include "FileTransform.h"
23 #include "Constants.h"
25 // Functions to copy values set by installer from HKLM to HKCU.
26 static bool OpenHKLM(HKEY *key, LPCTSTR relpath = nullptr);
27 static bool OpenHKCU(HKEY *key, LPCTSTR relpath = nullptr);
28 static void CopyFromLMtoCU(HKEY lmKey, HKEY cuKey, LPCTSTR valname);
34 * @brief Initialise options and set default values.
36 * @note Remember default values are what users see first time
37 * using WinMerge and many users never change them. So pick
38 * default values carefully!
40 void Init(COptionsMgr *pOptions)
42 if (typeid(*pOptions) == typeid(CRegOptionsMgr))
44 static_cast<CRegOptionsMgr*>(pOptions)->SetRegRootKey(_T("Thingamahoochie\\WinMerge\\"));
47 LANGID LangId = GetUserDefaultLangID();
48 pOptions->InitOption(OPT_SELECTED_LANGUAGE, static_cast<int>(LangId));
50 // Initialise options (name, default value)
51 pOptions->InitOption(OPT_SHOW_UNIQUE_LEFT, true);
52 pOptions->InitOption(OPT_SHOW_UNIQUE_MIDDLE, true);
53 pOptions->InitOption(OPT_SHOW_UNIQUE_RIGHT, true);
54 pOptions->InitOption(OPT_SHOW_DIFFERENT, true);
55 pOptions->InitOption(OPT_SHOW_IDENTICAL, true);
56 pOptions->InitOption(OPT_SHOW_BINARIES, true);
57 pOptions->InitOption(OPT_SHOW_SKIPPED, false);
58 pOptions->InitOption(OPT_SHOW_DIFFERENT_LEFT_ONLY, true);
59 pOptions->InitOption(OPT_SHOW_DIFFERENT_MIDDLE_ONLY, true);
60 pOptions->InitOption(OPT_SHOW_DIFFERENT_RIGHT_ONLY, true);
61 pOptions->InitOption(OPT_SHOW_MISSING_LEFT_ONLY, true);
62 pOptions->InitOption(OPT_SHOW_MISSING_MIDDLE_ONLY, true);
63 pOptions->InitOption(OPT_SHOW_MISSING_RIGHT_ONLY, true);
65 pOptions->InitOption(OPT_SHOW_TOOLBAR, true);
66 pOptions->InitOption(OPT_SHOW_STATUSBAR, true);
67 pOptions->InitOption(OPT_SHOW_TABBAR, true);
68 pOptions->InitOption(OPT_TOOLBAR_SIZE, 0);
69 pOptions->InitOption(OPT_RESIZE_PANES, false);
71 pOptions->InitOption(OPT_SYNTAX_HIGHLIGHT, true);
72 pOptions->InitOption(OPT_WORDWRAP, false);
73 pOptions->InitOption(OPT_VIEW_LINENUMBERS, false);
74 pOptions->InitOption(OPT_VIEW_WHITESPACE, false);
75 pOptions->InitOption(OPT_VIEW_EOL, false);
76 pOptions->InitOption(OPT_SCROLL_TO_FIRST, false);
77 pOptions->InitOption(OPT_SCROLL_TO_FIRST_INLINE_DIFF, false);
78 pOptions->InitOption(OPT_VERIFY_OPEN_PATHS, true);
79 pOptions->InitOption(OPT_AUTO_COMPLETE_SOURCE, (int)1);
80 pOptions->InitOption(OPT_VIEW_FILEMARGIN, false);
81 pOptions->InitOption(OPT_DIFF_CONTEXT, (int)-1);
82 pOptions->InitOption(OPT_INVERT_DIFF_CONTEXT, false);
83 pOptions->InitOption(OPT_SPLIT_HORIZONTALLY, false);
84 pOptions->InitOption(OPT_RENDERING_MODE, -1);
85 pOptions->InitOption(OPT_FILE_SIZE_THRESHOLD, 64*1024*1024);
87 pOptions->InitOption(OPT_WORDDIFF_HIGHLIGHT, true);
88 pOptions->InitOption(OPT_BREAK_SEPARATORS, _T(".,:;?[](){}<=>`'!\"#$%&^~\\|@+-*/"));
90 pOptions->InitOption(OPT_BACKUP_FOLDERCMP, false);
91 pOptions->InitOption(OPT_BACKUP_FILECMP, true);
92 pOptions->InitOption(OPT_BACKUP_LOCATION, (int)0);
93 pOptions->InitOption(OPT_BACKUP_GLOBALFOLDER, _T(""));
94 pOptions->InitOption(OPT_BACKUP_ADD_BAK, true);
95 pOptions->InitOption(OPT_BACKUP_ADD_TIME, false);
97 pOptions->InitOption(OPT_DIRVIEW_SORT_COLUMN, (int)-1);
98 pOptions->InitOption(OPT_DIRVIEW_SORT_COLUMN3, (int)-1);
99 pOptions->InitOption(OPT_DIRVIEW_SORT_ASCENDING, true);
100 pOptions->InitOption(OPT_SHOW_SELECT_FILES_AT_STARTUP, false);
101 pOptions->InitOption(OPT_DIRVIEW_EXPAND_SUBDIRS, false);
102 pOptions->InitOption(OPT_DIRVIEW_COLUMN_ORDERS, _T(""));
103 pOptions->InitOption(OPT_DIRVIEW_COLUMN_WIDTHS, _T(""));
104 pOptions->InitOption(OPT_DIRVIEW3_COLUMN_ORDERS, _T(""));
105 pOptions->InitOption(OPT_DIRVIEW3_COLUMN_WIDTHS, _T(""));
107 pOptions->InitOption(OPT_REPORTFILES_REPORTTYPE, 0);
108 pOptions->InitOption(OPT_REPORTFILES_COPYTOCLIPBOARD, false);
109 pOptions->InitOption(OPT_REPORTFILES_INCLUDEFILECMPREPORT, false);
111 pOptions->InitOption(OPT_AUTOMATIC_RESCAN, false);
112 pOptions->InitOption(OPT_ALLOW_MIXED_EOL, false);
113 pOptions->InitOption(OPT_COPY_FULL_LINE, false);
114 pOptions->InitOption(OPT_TAB_SIZE, (int)4);
115 pOptions->InitOption(OPT_TAB_TYPE, (int)0); // 0 means tabs inserted
117 pOptions->InitOption(OPT_EXT_EDITOR_CMD, _T("%windir%\\NOTEPAD.EXE"));
118 pOptions->InitOption(OPT_USE_RECYCLE_BIN, true);
119 pOptions->InitOption(OPT_SINGLE_INSTANCE, 0);
120 pOptions->InitOption(OPT_MERGE_MODE, false);
121 // OPT_WORDDIFF_HIGHLIGHT is initialized above
122 pOptions->InitOption(OPT_BREAK_ON_WORDS, false);
123 pOptions->InitOption(OPT_BREAK_TYPE, 1);
125 pOptions->InitOption(OPT_CLOSE_WITH_ESC, 1);
126 pOptions->InitOption(OPT_CLOSE_WITH_OK, false);
127 pOptions->InitOption(OPT_IGNORE_SMALL_FILETIME, false);
128 pOptions->InitOption(OPT_ASK_MULTIWINDOW_CLOSE, false);
129 pOptions->InitOption(OPT_PRESERVE_FILETIMES, false);
130 pOptions->InitOption(OPT_TREE_MODE, true);
132 pOptions->InitOption(OPT_CMP_METHOD, (int)CMP_CONTENT);
133 pOptions->InitOption(OPT_CMP_MOVED_BLOCKS, false);
134 pOptions->InitOption(OPT_CMP_MATCH_SIMILAR_LINES, false);
135 pOptions->InitOption(OPT_CMP_STOP_AFTER_FIRST, false);
136 pOptions->InitOption(OPT_CMP_QUICK_LIMIT, 4 * 1024 * 1024); // 4 Megs
137 pOptions->InitOption(OPT_CMP_BINARY_LIMIT, 64 * 1024 * 1024); // 64 Megs
138 pOptions->InitOption(OPT_CMP_COMPARE_THREADS, -1);
139 pOptions->InitOption(OPT_CMP_WALK_UNIQUE_DIRS, true);
140 pOptions->InitOption(OPT_CMP_IGNORE_REPARSE_POINTS, false);
141 pOptions->InitOption(OPT_CMP_IGNORE_CODEPAGE, false);
142 pOptions->InitOption(OPT_CMP_INCLUDE_SUBDIRS, true);
143 pOptions->InitOption(OPT_CMP_ENABLE_IMGCMP_IN_DIRCMP, false);
145 pOptions->InitOption(OPT_CMP_BIN_FILEPATTERNS, _T("*.bin;*.frx"));
147 pOptions->InitOption(OPT_CMP_CSV_FILEPATTERNS, _T("*.csv"));
148 pOptions->InitOption(OPT_CMP_TSV_FILEPATTERNS, _T("*.tsv"));
149 pOptions->InitOption(OPT_CMP_DSV_FILEPATTERNS, _T(""));
150 pOptions->InitOption(OPT_CMP_DSV_DELIM_CHAR, _T(";"));
151 pOptions->InitOption(OPT_CMP_TBL_ALLOW_NEWLINES_IN_QUOTES, true);
152 pOptions->InitOption(OPT_CMP_TBL_QUOTE_CHAR, _T("\""));
154 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"));
155 pOptions->InitOption(OPT_CMP_IMG_SHOWDIFFERENCES, true);
156 pOptions->InitOption(OPT_CMP_IMG_OVERLAYMOVE, 0);
157 pOptions->InitOption(OPT_CMP_IMG_OVERLAYALPHA, 30);
158 pOptions->InitOption(OPT_CMP_IMG_DRAGGING_MODE, 1);
159 pOptions->InitOption(OPT_CMP_IMG_ZOOM, 1000);
160 pOptions->InitOption(OPT_CMP_IMG_USEBACKCOLOR, true);
161 pOptions->InitOption(OPT_CMP_IMG_BACKCOLOR, 0xFFFFFF);
162 pOptions->InitOption(OPT_CMP_IMG_DIFFBLOCKSIZE, 8);
163 pOptions->InitOption(OPT_CMP_IMG_DIFFCOLORALPHA, 70);
164 pOptions->InitOption(OPT_CMP_IMG_THRESHOLD, 0);
165 pOptions->InitOption(OPT_CMP_IMG_INSERTIONDELETIONDETECTION_MODE, 0);
166 pOptions->InitOption(OPT_CMP_IMG_VECTOR_IMAGE_ZOOM_RATIO, 1000);
167 pOptions->InitOption(OPT_CMP_IMG_OCR_RESULT_TYPE, 0);
169 pOptions->InitOption(OPT_PROJECTS_PATH, _T(""));
170 pOptions->InitOption(OPT_USE_SYSTEM_TEMP_PATH, true);
171 pOptions->InitOption(OPT_CUSTOM_TEMP_PATH, _T(""));
173 pOptions->InitOption(OPT_LINEFILTER_ENABLED, false);
174 pOptions->InitOption(OPT_SUBSTITUTION_FILTERS_ENABLED, false);
176 pOptions->InitOption(OPT_FILEFILTER_CURRENT, _T("*.*"));
177 // CMainFrame initializes this when it is empty.
178 pOptions->InitOption(OPT_FILTER_USERPATH, _T(""));
179 if (pOptions->GetString(OPT_FILTER_USERPATH).empty())
180 pOptions->SaveOption(OPT_FILTER_USERPATH, paths::ConcatPath(env::GetMyDocuments(), DefaultRelativeFilterPath));
181 pOptions->InitOption(OPT_FILEFILTER_SHARED, false);
183 pOptions->InitOption(OPT_CP_DEFAULT_MODE, (int)0);
184 pOptions->InitOption(OPT_CP_DEFAULT_CUSTOM, (int)GetACP());
186 if (PRIMARYLANGID(LangId) == LANG_JAPANESE)
187 pOptions->InitOption(OPT_CP_DETECT, (int)(50932 << 16) | 3);
188 else if (LangId == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED))
189 pOptions->InitOption(OPT_CP_DETECT, (int)(50936 << 16) | 3);
190 else if (PRIMARYLANGID(LangId) == LANG_KOREAN)
191 pOptions->InitOption(OPT_CP_DETECT, (int)(50949 << 16) | 3);
192 else if (LangId == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL))
193 pOptions->InitOption(OPT_CP_DETECT, (int)(50950 << 16) | 3);
195 pOptions->InitOption(OPT_CP_DETECT, (int)(50001 << 16) | 1);
197 pOptions->InitOption(OPT_ARCHIVE_ENABLE, 1); // Enable by default
198 pOptions->InitOption(OPT_ARCHIVE_PROBETYPE, false);
199 pOptions->InitOption(OPT_ARCHIVE_FILTER_INDEX, 1);
201 pOptions->InitOption(OPT_PLUGINS_ENABLED, true);
202 pOptions->InitOption(OPT_PLUGINS_CUSTOM_SETTINGS_LIST, _T(""));
203 pOptions->InitOption(OPT_PLUGINS_UNPACKER_MODE, false);
204 pOptions->InitOption(OPT_PLUGINS_PREDIFFER_MODE, false);
205 pOptions->InitOption(OPT_PLUGINS_UNPACK_DONT_CHECK_EXTENSION, true);
206 pOptions->InitOption(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE, false);
208 pOptions->InitOption(OPT_PATCHCREATOR_PATCH_STYLE, 0);
209 pOptions->InitOption(OPT_PATCHCREATOR_CONTEXT_LINES, 0);
210 pOptions->InitOption(OPT_PATCHCREATOR_CASE_SENSITIVE, true);
211 pOptions->InitOption(OPT_PATCHCREATOR_EOL_SENSITIVE, true);
212 pOptions->InitOption(OPT_PATCHCREATOR_IGNORE_BLANK_LINES, false);
213 pOptions->InitOption(OPT_PATCHCREATOR_WHITESPACE, WHITESPACE_COMPARE_ALL);
214 pOptions->InitOption(OPT_PATCHCREATOR_OPEN_TO_EDITOR, false);
215 pOptions->InitOption(OPT_PATCHCREATOR_INCLUDE_CMD_LINE, false);
217 pOptions->InitOption(OPT_TABBAR_AUTO_MAXWIDTH, true);
218 pOptions->InitOption(OPT_ACTIVE_FRAME_MAX, true);
219 pOptions->InitOption(OPT_ACTIVE_PANE, 0);
221 pOptions->InitOption(OPT_MRU_MAX, 9);
223 pOptions->InitOption(OPT_COLOR_SCHEME, _T("Default"));
225 Options::CustomColors::SetDefaults(pOptions);
226 Options::DiffOptions::SetDefaults(pOptions);
227 Options::DiffColors::SetDefaults(pOptions);
228 Options::DirColors::SetDefaults(pOptions);
229 Options::EditorSyntax::SetDefaults(pOptions);
230 Options::Font::SetDefaults(pOptions);
234 * @brief Copy some HKLM values to HKCU.
235 * The installer sets HKLM values for "all users". This function copies
236 * few of those values for "user" values. E.g. enabling ShellExtension
237 * initially for user is done by this function.
239 void CopyHKLMValues()
243 if (OpenHKLM(&LMKey))
245 if (OpenHKCU(&CUKey))
247 CopyFromLMtoCU(LMKey, CUKey, _T("ContextMenuEnabled"));
248 CopyFromLMtoCU(LMKey, CUKey, _T("Executable"));
253 if (OpenHKLM(&LMKey, _T("Locale")))
255 if (OpenHKCU(&CUKey, _T("Locale")))
257 CopyFromLMtoCU(LMKey, CUKey, _T("LanguageId"));
267 * @brief Open HKLM registry key.
268 * @param [out] key Pointer to open HKLM key.
269 * @param [in] relpath Relative registry path (to WinMerge reg path) to open, or nullptr.
270 * @return true if opening succeeded.
272 static bool OpenHKLM(HKEY *key, LPCTSTR relpath)
274 TCHAR valuename[256];
276 wsprintf(valuename, _T("%s\\%s"), RegDir, relpath);
278 lstrcpy(valuename, RegDir);
279 LONG retval = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
280 valuename, 0, KEY_READ, key);
281 if (retval == ERROR_SUCCESS)
289 * @brief Open HKCU registry key.
290 * Opens the HKCU key for WinMerge. If the key does not exist, creates one.
291 * @param [out] key Pointer to open HKCU key.
292 * @param [in] relpath Relative registry path (to WinMerge reg path) to open, or nullptr.
293 * @return true if opening succeeded.
295 static bool OpenHKCU(HKEY *key, LPCTSTR relpath)
297 TCHAR valuename[256];
299 wsprintf(valuename, _T("%s\\%s"), RegDir, relpath);
301 lstrcpy(valuename, RegDir);
302 LONG retval = RegOpenKeyEx(HKEY_CURRENT_USER,
303 valuename, 0, KEY_ALL_ACCESS, key);
304 if (retval == ERROR_SUCCESS)
308 else if (retval == ERROR_FILE_NOT_FOUND)
310 retval = RegCreateKeyEx(HKEY_CURRENT_USER,
311 valuename, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, key, nullptr);
312 if (retval == ERROR_SUCCESS)
319 * @brief Copy value from HKLM to HKCU.
320 * @param [in] lmKey HKLM key from where to copy.
321 * @param [in] cuKey HKCU key to where to copy.
322 * @param [in] valname Name of the value to copy.
324 static void CopyFromLMtoCU(HKEY lmKey, HKEY cuKey, LPCTSTR valname)
327 LONG retval = RegQueryValueEx(cuKey, valname, 0, nullptr, nullptr, &len);
328 if (retval == ERROR_FILE_NOT_FOUND)
330 retval = RegQueryValueEx(lmKey, valname, 0, nullptr, nullptr, &len);
331 if (retval == ERROR_SUCCESS)
334 std::vector<BYTE> buf(len);
335 retval = RegQueryValueEx(lmKey, valname, 0, &type, &buf[0], &len);
336 if (retval == ERROR_SUCCESS)
338 RegSetValueEx(cuKey, valname , 0, type,