OSDN Git Service

Update Dutch.po (#842)
[winmerge-jp/winmerge-jp.git] / Src / SelectPluginDlg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 //    WinMerge:  an interactive diff/merge utility
3 //    Copyright (C) 1997-2000  Thingamahoochie Software
4 //    Author: Dean Grimm
5 //    SPDX-License-Identifier: GPL-2.0-or-later
6 /////////////////////////////////////////////////////////////////////////////
7 /**
8  * @file  SelectPluginDlg.cpp
9  *
10  * @brief Unpacker plugin selection dialog implementation.
11  */
12
13 #include "stdafx.h"
14 #include "SelectPluginDlg.h"
15 #include "Plugins.h"
16 #include "FileTransform.h"
17 #include "OptionsMgr.h"
18 #include "OptionsDef.h"
19 #include "unicoder.h"
20
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #endif
24
25 /////////////////////////////////////////////////////////////////////////////
26 // CSelectPluginDlg dialog
27
28 void CSelectPluginDlg::Initialize(bool unpacker)
29 {
30         //{{AFX_DATA_INIT(CSelectPluginDlg)
31         m_bNoExtensionCheck = false;
32         m_bOpenInSameFrameType = false;
33         m_strDescription = _T("");
34         m_strExtensions = _T("");
35         m_strArguments = _T("");
36         //}}AFX_DATA_INIT
37
38         // texts for the default unpackers
39         noPlugin.reset(new PluginInfo);
40         noPlugin->m_lpDispatch = nullptr;
41         noPlugin->m_name = _("<None>");
42         automaticPlugin.reset(new PluginInfo);
43         automaticPlugin->m_lpDispatch = nullptr;
44         automaticPlugin->m_name = _("<Automatic>");
45         automaticPlugin->m_description = _("The adapted unpacker is applied to both files (one file only needs the extension).");
46
47         std::vector<std::wstring> events = unpacker ?  FileTransform::UnpackerEventNames : FileTransform::PredifferEventNames;
48         m_Plugins = FileTransform::CreatePluginMenuInfos(m_filteredFilenames, events, 0).second;
49 }
50
51
52 CSelectPluginDlg::CSelectPluginDlg(const String& pluginPipeline, const String& filename,
53         bool unpacker /*= true */, bool argumentRequired/*= false  */, CWnd* pParent /*= nullptr*/)
54         : CTrDialog(CSelectPluginDlg::IDD, pParent)
55         , m_strPluginPipeline(pluginPipeline)
56         , m_filteredFilenames(filename)
57         , m_bUnpacker(unpacker)
58         , m_bArgumentRequired(argumentRequired)
59 {
60         Initialize(unpacker);
61 }
62
63 CSelectPluginDlg::~CSelectPluginDlg()
64 {
65 }
66
67 void CSelectPluginDlg::DoDataExchange(CDataExchange* pDX)
68 {
69         CTrDialog::DoDataExchange(pDX);
70         //{{AFX_DATA_MAP(CSelectPluginDlg)
71         DDX_Control(pDX, IDC_PLUGIN_NAME, m_cboPluginName);
72         DDX_Check(pDX, IDC_PLUGIN_ALLOW_ALL, m_bNoExtensionCheck);
73         DDX_Check(pDX, IDC_PLUGIN_OPEN_IN_SAME_FRAME_TYPE, m_bOpenInSameFrameType);
74         DDX_Text(pDX, IDC_PLUGIN_DESCRIPTION, m_strDescription);
75         DDX_Text(pDX, IDC_PLUGIN_SUPPORTED_EXTENSIONS, m_strExtensions);
76         DDX_Text(pDX, IDC_PLUGIN_ARGUMENTS, m_strArguments);
77         DDX_Control(pDX, IDC_PLUGIN_PIPELINE, m_ctlPluginPipeline);
78         DDX_CBStringExact(pDX, IDC_PLUGIN_PIPELINE, m_strPluginPipeline);
79         //}}AFX_DATA_MAP
80 }
81
82
83 BEGIN_MESSAGE_MAP(CSelectPluginDlg, CTrDialog)
84         //{{AFX_MSG_MAP(CSelectPluginDlg)
85         ON_BN_CLICKED(IDC_PLUGIN_ALLOW_ALL, OnUnpackerAllowAll)
86         ON_CBN_SELCHANGE(IDC_PLUGIN_NAME, OnSelchangeUnpackerName)
87         ON_CBN_SELENDOK(IDC_PLUGIN_NAME, OnSelchangeUnpackerName)
88         ON_BN_CLICKED(IDC_PLUGIN_ADDPIPE, OnClickedAddPipe)
89         ON_EN_CHANGE(IDC_PLUGIN_PIPELINE, OnChangePipeline)
90         //}}AFX_MSG_MAP
91 END_MESSAGE_MAP()
92
93 /////////////////////////////////////////////////////////////////////////////
94 // CSelectPluginDlg message handlers
95
96 void CSelectPluginDlg::OnOK() 
97 {
98         UpdateData(TRUE);
99
100         GetOptionsMgr()->SaveOption(OPT_PLUGINS_UNPACK_DONT_CHECK_EXTENSION, m_bNoExtensionCheck);
101         GetOptionsMgr()->SaveOption(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE, m_bOpenInSameFrameType);
102         m_ctlPluginPipeline.SaveState(m_bUnpacker ? _T("Files\\Unpacker") : _T("Files\\Prediffer"));
103
104         CTrDialog::OnOK();
105 }
106
107 BOOL CSelectPluginDlg::OnInitDialog() 
108 {
109         CTrDialog::OnInitDialog();
110
111         m_bNoExtensionCheck = GetOptionsMgr()->GetBool(OPT_PLUGINS_UNPACK_DONT_CHECK_EXTENSION);
112         m_bOpenInSameFrameType = GetOptionsMgr()->GetBool(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE);
113
114         prepareListbox();
115         m_ctlPluginPipeline.SetFileControlStates(true);
116         m_ctlPluginPipeline.LoadState(m_bUnpacker ? _T("Files\\Unpacker") : _T("Files\\Prediffer"));
117
118         EnableDlgItem(IDC_PLUGIN_OPEN_IN_SAME_FRAME_TYPE, m_bUnpacker);
119
120         UpdateData(FALSE);
121
122         if (m_bArgumentRequired)
123         {
124                 SetWindowText(_("Specify plugin arguments").c_str());
125                 String args;
126                 CString pipeline;
127                 GetDlgItemText(IDC_PLUGIN_ARGUMENTS, args);
128                 m_ctlPluginPipeline.GetWindowText(pipeline);
129                 m_strPluginPipeline = pipeline + _T(" ") + args.c_str();
130                 m_ctlPluginPipeline.SetWindowText(m_strPluginPipeline.c_str());
131                 m_ctlPluginPipeline.SetFocus();
132                 return FALSE;
133         }
134
135         return TRUE;  // return TRUE unless you set the focus to a control
136                       // EXCEPTION: OCX Property Pages should return FALSE
137 }
138
139 void CSelectPluginDlg::prepareListbox() 
140 {
141         int sel = -1;
142         int i = 0;
143         String errorMessage;
144         auto parseResult = PluginForFile::ParsePluginPipeline(m_strPluginPipeline, errorMessage);
145         String lastPluginName = parseResult.empty() ? _T("") : parseResult.back().name;
146         m_cboPluginName.AddString(noPlugin->m_name.c_str());
147         m_cboPluginName.AddString(automaticPlugin->m_name.c_str());
148
149         std::vector<String> processTypes;
150         for (const auto& [processType, pluginList] : m_Plugins)
151                 processTypes.push_back(processType);
152
153         auto itFound = std::find(processTypes.begin(), processTypes.end(), _("&Others"));
154         if (itFound != processTypes.end())
155         {
156                 processTypes.erase(itFound);
157                 processTypes.push_back(_("&Others"));
158         }
159
160         for (const auto& processType : processTypes)
161         {
162                 const auto& pluginList = m_Plugins[processType];
163                 String processType2 = processType;
164                 auto it = processType2.find(_("(&"));
165                 if (it != String::npos)
166                         processType2.erase(it, it + 2);
167                 strutils::replace(processType2, _T("&"), _T(""));
168                 if (!processType2.empty())
169                         m_cboPluginName.AddString((_T("[") + processType2 + _T("]")).c_str());
170                 for (const auto& [caption, name, id, plugin] : pluginList)
171                 {
172                         if (!name.empty() && name != _T("<Automatic>"))
173                         {
174                                 if (m_bNoExtensionCheck || plugin->TestAgainstRegList(m_filteredFilenames) || lastPluginName == name)
175                                 {
176                                         m_cboPluginName.AddString(name.c_str());
177                                         if (lastPluginName == name)
178                                                 sel = m_cboPluginName.GetCount() - 1;
179                                 }
180                         }
181                 }
182         }
183         if (lastPluginName == _T("<Automatic>"))
184                 sel = 1;
185         if (sel == -1)
186         {
187                 m_cboPluginName.SelectString(-1, noPlugin->m_name.c_str());
188         }
189         else
190         {
191                 m_cboPluginName.SetCurSel(sel);
192                 OnSelchangeUnpackerName();
193         }
194 }
195
196 void CSelectPluginDlg::OnUnpackerAllowAll() 
197 {
198         UpdateData ();
199
200         m_cboPluginName.ResetContent();
201
202         prepareListbox();
203
204         UpdateData (FALSE);
205 }
206
207 void CSelectPluginDlg::OnClickedAddPipe()
208 {
209         m_strPluginPipeline += _T("|");
210         UpdateData(FALSE);
211 }
212
213 void CSelectPluginDlg::OnChangePipeline()
214 {
215         UpdateData(TRUE);
216 }
217
218 void CSelectPluginDlg::OnSelchangeUnpackerName() 
219 {
220         PluginInfo* pPlugin = nullptr;
221         int i = m_cboPluginName.GetCurSel();
222         if (i == 0)
223         {
224                 pPlugin = noPlugin.get();
225                 m_strPluginPipeline.clear();
226         }
227         else if (i == 1)
228         {
229                 pPlugin = automaticPlugin.get();
230                 m_strPluginPipeline = _T("<Automatic>");
231         }
232         else
233         {
234                 // initialize with the default unpacker
235                 CString cstrPluginName;
236                 m_cboPluginName.GetWindowText(cstrPluginName);
237                 String pluginName = cstrPluginName.Trim();
238                 for (const auto& [processType, pluginList] : m_Plugins)
239                 {
240                         for (const auto& [caption, name, id, plugin] : pluginList)
241                         {
242                                 if (pluginName == name)
243                                 {
244                                         String pluginPipeline = strutils::trim_ws(m_strPluginPipeline);
245                                         if (!pluginPipeline.empty() && pluginPipeline.back() == '|')
246                                                 pluginPipeline += _T("dummy");
247                                         String errorMessage;
248                                         auto parseResult = PluginForFile::ParsePluginPipeline(pluginPipeline, errorMessage);
249                                         if (parseResult.empty())
250                                                 parseResult.push_back({ name, {}, '\0' });
251                                         parseResult.back().name = name;
252                                         m_strPluginPipeline = PluginForFile::MakePluginPipeline(parseResult);
253                                         pPlugin = plugin;
254                                         break;
255                                 }
256                         }
257                 }
258         }
259
260         if (pPlugin)
261         {
262                 m_strDescription = pPlugin->m_description;
263                 m_strExtensions = pPlugin->m_filtersText;
264                 m_strArguments = pPlugin->m_arguments;
265         }
266
267         m_bOpenInSameFrameType = IsDlgButtonChecked(IDC_PLUGIN_OPEN_IN_SAME_FRAME_TYPE);
268
269         UpdateData (FALSE);
270 }