1 // WinMergeScript.cpp : Implementation of CWinMergeScript
3 #include "IgnoreFieldsComma.h"
4 #include "WinMergeScript.h"
8 /////////////////////////////////////////////////////////////////////////////
12 * @brief Get the name of the current dll
14 LPTSTR GetDllFilename(LPTSTR name, int len)
16 // careful for the last char, the doc does not give this detail
18 GetModuleFileName(_Module.GetModuleInstance(), name, len-1);
19 // find last backslash
20 TCHAR * lastslash = _tcsrchr(name, '/');
25 TCHAR * lastslash2 = _tcsrchr(lastslash, '\\');
30 if (lastslash2 != name)
31 lstrcpy(name, lastslash2);
39 GetDllFilename(name, 256);
40 lstrcpy(szKeyName, _T("Software\\Thingamahoochie\\WinMerge\\Plugins\\"));
41 lstrcat(szKeyName, name);
45 CString RegReadString(const CString& key, const CString& valuename, const CString& defaultValue)
48 if (reg.Open(HKEY_CURRENT_USER, key, KEY_READ) == ERROR_SUCCESS)
50 TCHAR value[512] = {0};
51 DWORD dwSize = sizeof(value) / sizeof(value[0]);
52 reg.QueryStringValue(valuename, value, &dwSize);
58 int CreateArrayFromRangeString(const TCHAR *rangestr, int (* value)[2])
62 lstrcpy(name, rangestr);
67 // first pass : prepare the chunks
69 TCHAR * token = _tcstok(name, _T(",_"));
70 while( token != NULL )
74 token = _tcstok( NULL, _T(",_") );
78 // just return the number of values
83 for (i = 0 ; i < nValue ; i++)
85 value[i][0] = _tcstol(token, &token, 10);
86 while (*token != 0 && !_istdigit(*token))
90 value[i][1] = value[i][0];
94 value[i][1] = _tcstol(token, &token, 10);
96 token = token + _tcslen(token) + 1;
102 CString CreateRangeStringFromArray(int nExcludedRanges, const int aExcludedRanges[][2])
104 CString rangestr = _T("");
105 for (int i = 0; i < nExcludedRanges; ++i)
108 if (aExcludedRanges[i][0] > 0 && aExcludedRanges[i][1] > 0)
110 if (aExcludedRanges[i][0] == aExcludedRanges[i][1])
112 wsprintf(value, _T("%d"), aExcludedRanges[i][0]);
117 wsprintf(value, _T("%d-%d"), aExcludedRanges[i][0], aExcludedRanges[i][1]);
123 if (!rangestr.IsEmpty())
124 rangestr.Delete(rangestr.GetLength() - 1);
129 CString GetColumnRangeString()
132 GetDllFilename(name, 256);
134 TCHAR * token = _tcspbrk(name, _T(",_"));
136 rangestr = RegReadString(KeyName(), _T("ColumnRanges"), _T(""));
138 rangestr = token + 1;
140 int nExcludedRanges = CreateArrayFromRangeString(rangestr, NULL);
141 int (* aExcludedRanges)[2] = new int[nExcludedRanges][2];
142 if (aExcludedRanges == NULL)
145 nExcludedRanges = CreateArrayFromRangeString(rangestr, aExcludedRanges);
147 rangestr = CreateRangeStringFromArray(nExcludedRanges, aExcludedRanges);
149 delete[] aExcludedRanges;
155 STDMETHODIMP CWinMergeScript::get_PluginEvent(BSTR *pVal)
157 *pVal = SysAllocString(L"BUFFER_PREDIFF");
161 STDMETHODIMP CWinMergeScript::get_PluginDescription(BSTR *pVal)
163 *pVal = SysAllocString(L"Ignore some fields - ignored fields list from the plugin name");
168 STDMETHODIMP CWinMergeScript::get_PluginFileFilters(BSTR *pVal)
170 *pVal = SysAllocString(L"\\.csv$");
175 STDMETHODIMP CWinMergeScript::get_PluginIsAutomatic(VARIANT_BOOL *pVal)
177 *pVal = VARIANT_TRUE;
181 STDMETHODIMP CWinMergeScript::PrediffBufferW(BSTR *pText, INT *pSize, VARIANT_BOOL *pbChanged, VARIANT_BOOL *pbHandled)
183 WCHAR * pBeginText = *pText;
185 WCHAR * pEndText = pBeginText + nSize;
187 CString rangestr = GetColumnRangeString();
189 int nExcludedRanges = CreateArrayFromRangeString(rangestr, NULL);
190 int (* aExcludedRanges)[2] = new int[nExcludedRanges][2];
191 if (aExcludedRanges == NULL)
194 nExcludedRanges = CreateArrayFromRangeString(rangestr, aExcludedRanges);
196 if (nExcludedRanges == 0)
198 *pbChanged = VARIANT_FALSE;
199 *pbHandled = VARIANT_TRUE;
203 // first column is 1 for user, but is 0 here
205 for (i = 0 ; i < nExcludedRanges ; i++)
207 aExcludedRanges[i][0] --;
208 aExcludedRanges[i][1] --;
212 WCHAR * pDst = pBeginText;
215 // change this to change the delimiter between fields
216 const WCHAR delimiter = L',';
218 const WCHAR quote = RegReadString(_T("Software\\Thingamahoochie\\WinMerge\\Settings"), _T("TableQuoteCharacter"), _T("\""))[0];
219 const bool allowNewlinesInQuotes =
220 _ttoi(RegReadString(_T("Software\\Thingamahoochie\\WinMerge\\Settings"), _T("TableAllowNewlinesInQuotes"), _T("1"))) != 0;
222 // order of the column in the current line
224 // next excluded column range in the current line
225 int nextExcludedRange = 0;
227 for (columnBegin = pBeginText; columnBegin < pEndText ; )
229 bool inQuote = false;
230 // search for the end of the column (columnEnd = first excluded character)
231 WCHAR * columnEnd = columnBegin;
232 if (allowNewlinesInQuotes)
234 while (columnEnd < pEndText &&
235 !(!inQuote && (*columnEnd == L'\n' || *columnEnd == L'\r' || *columnEnd == delimiter)))
237 if (*columnEnd == quote)
244 while (columnEnd < pEndText &&
245 !(*columnEnd == L'\n' || *columnEnd == L'\r' || (!inQuote && *columnEnd == delimiter)))
247 if (*columnEnd == quote)
253 // determine the status of this column
254 if (nextExcludedRange < nExcludedRanges && iColumn > aExcludedRanges[nextExcludedRange][1])
255 nextExcludedRange ++;
256 BOOL bIsColumnIncluded = TRUE;
257 if (nextExcludedRange < nExcludedRanges && iColumn >= aExcludedRanges[nextExcludedRange][0])
258 bIsColumnIncluded = FALSE;
260 // copy the characters of included columns
261 if (bIsColumnIncluded)
263 wcsncpy(pDst, columnBegin, columnEnd - columnBegin);
264 pDst += columnEnd - columnBegin;
267 // advance the cursor
268 columnBegin = columnEnd;
270 // keep possible tabulation (only one)
271 if (columnBegin < pEndText)
272 if (*columnBegin == delimiter)
274 // copy the tabulation
277 // advance the cursor
283 // keep possible EOL characters
284 WCHAR * eolEnd = columnBegin;
285 while (eolEnd < pEndText && (*eolEnd == L'\n' || *eolEnd == L'\r'))
290 if (eolEnd > columnBegin)
292 // copy the EOL characters
293 wcsncpy(pDst, columnBegin, eolEnd - columnBegin);
294 pDst += eolEnd - columnBegin;
295 // advance the cursor
296 columnBegin = eolEnd;
297 // reset the column counter
299 nextExcludedRange = 0;
304 delete [] aExcludedRanges;
307 *pSize = pDst - pBeginText;
310 *pbChanged = VARIANT_FALSE;
312 *pbChanged = VARIANT_TRUE;
314 *pbHandled = VARIANT_TRUE;
318 INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
322 SetDlgItemText(hWnd, IDC_EDIT1, GetColumnRangeString());
326 if (LOWORD(wParam) == IDOK)
329 if (reg.Create(HKEY_CURRENT_USER, KeyName(), REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE) != ERROR_SUCCESS)
331 TCHAR value[512] = {0};
332 GetDlgItemText(hWnd, IDC_EDIT1, value, sizeof(value)/sizeof(TCHAR));
333 reg.SetStringValue(_T("ColumnRanges"), value);
334 EndDialog(hWnd, IDOK);
336 else if (LOWORD(wParam) == IDCANCEL)
338 EndDialog(hWnd, IDCANCEL);
349 STDMETHODIMP CWinMergeScript::ShowSettingsDialog(VARIANT_BOOL *pbHandled)
351 *pbHandled = (DialogBox(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) == IDOK);