diff --git a/diff_ext_for_kdiff3/class_factory.h b/diff_ext_for_kdiff3/class_factory.h index da91979..1930bd2 100644 --- a/diff_ext_for_kdiff3/class_factory.h +++ b/diff_ext_for_kdiff3/class_factory.h @@ -1,33 +1,51 @@ /* * Copyright (c) 2003, Sergey Zorin. All rights reserved. * - * This software is distributable under the BSD license. See the terms - * of the BSD license in the LICENSE file provided with this software. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __class_factory_h__ #define __class_factory_h__ #include #include class CLASS_FACTORY : public IClassFactory { public: CLASS_FACTORY(); virtual ~CLASS_FACTORY(); //IUnknown members STDMETHODIMP QueryInterface(REFIID, void**); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); //ICLASS_FACTORY members STDMETHODIMP CreateInstance(IUnknown*, REFIID, void**); STDMETHODIMP LockServer(BOOL); private: ULONG _ref_count; }; #endif //__class_factory_h__ diff --git a/diff_ext_for_kdiff3/diff_ext.cpp b/diff_ext_for_kdiff3/diff_ext.cpp index 315686e..a64cd97 100644 --- a/diff_ext_for_kdiff3/diff_ext.cpp +++ b/diff_ext_for_kdiff3/diff_ext.cpp @@ -1,640 +1,659 @@ /* * Copyright (c) 2003-2006, Sergey Zorin. All rights reserved. * - * This software is distributable under the BSD license. See the terms - * of the BSD license in the LICENSE file provided with this software. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ + #define _CRT_SECURE_NO_DEPRECATE #include #include #include #include "diff_ext.h" #include #include #ifdef UNICODE static void parseString( const std::wstring& s, size_t& i /*pos*/, std::wstring& r /*result*/ ) { size_t size = s.size(); ++i; // Skip initial '"' for( ; i s_translationMap; static tstring s_translationFileName; void readTranslationFile() { s_translationMap.clear(); FILE* pFile = _tfopen( s_translationFileName.c_str(), TEXT("rb") ); if ( pFile ) { MESSAGELOG( TEXT( "Reading translations: " ) + s_translationFileName ); std::vector buffer; try { if ( fseek(pFile, 0, SEEK_END)==0 ) { size_t length = ftell(pFile); // Get the file length buffer.resize(length); fseek(pFile, 0, SEEK_SET ); fread(&buffer[0], 1, length, pFile ); } } catch(...) { } fclose(pFile); if (buffer.size()>0) { size_t bufferSize = buffer.size(); int offset = 0; if ( buffer[0]=='\xEF' && buffer[1]=='\xBB' && buffer[2]=='\xBF' ) { offset += 3; bufferSize -= 3; } size_t sLength = MultiByteToWideChar(CP_UTF8,0,&buffer[offset], (int)bufferSize, 0, 0 ); std::wstring s( sLength, L' ' ); MultiByteToWideChar(CP_UTF8,0,&buffer[offset], (int)bufferSize, &s[0], (int)s.size() ); // Now analyse the file and extract translation strings std::wstring msgid; std::wstring msgstr; msgid.reserve( 1000 ); msgstr.reserve( 1000 ); bool bExpectingId = true; for( size_t i=0; i5 && wcsncmp( &s[i], L"msgid", 5 )==0 ) { if ( !msgid.empty() && !msgstr.empty() ) { s_translationMap[msgid] = msgstr; } bExpectingId = true; msgid.clear(); i+=4; } else if ( sLength-i>6 && wcsncmp( &s[i], L"msgstr", 6 )==0 ) { bExpectingId = false; msgstr.clear(); i+=5; } else { // Unexpected ? } } } } else { ERRORLOG( TEXT( "Reading translations failed: " ) + s_translationFileName ); } } static tstring getTranslation( const tstring& fallback ) { std::map< std::wstring, std::wstring >::iterator i = s_translationMap.find( fallback ); if (i!=s_translationMap.end()) return i->second; return fallback; } #else static tstring getTranslation( const tstring& fallback ) { return fallback; } #endif static void replaceArgs( tstring& s, const tstring& r1, const tstring& r2=TEXT(""), const tstring& r3=TEXT("") ) { tstring arg1 = TEXT("%1"); size_t pos1 = s.find( arg1 ); tstring arg2 = TEXT("%2"); size_t pos2 = s.find( arg2 ); tstring arg3 = TEXT("%3"); size_t pos3 = s.find( arg3 ); if ( pos1 != size_t(-1) ) { s.replace( pos1, arg1.length(), r1 ); if ( pos2 != size_t(-1) && pos1recent_files() ) { LOG(); _resource = SERVER::instance()->handle(); SERVER::instance()->lock(); } DIFF_EXT::~DIFF_EXT() { LOG(); if(_resource != SERVER::instance()->handle()) { FreeLibrary(_resource); } SERVER::instance()->release(); } STDMETHODIMP DIFF_EXT::QueryInterface(REFIID refiid, void** ppv) { HRESULT ret = E_NOINTERFACE; *ppv = 0; if(IsEqualIID(refiid, IID_IShellExtInit) || IsEqualIID(refiid, IID_IUnknown)) { *ppv = static_cast(this); } else if (IsEqualIID(refiid, IID_IContextMenu)) { *ppv = static_cast(this); } if(*ppv != 0) { AddRef(); ret = NOERROR; } return ret; } STDMETHODIMP_(ULONG) DIFF_EXT::AddRef() { return InterlockedIncrement((LPLONG)&_ref_count); } STDMETHODIMP_(ULONG) DIFF_EXT::Release() { ULONG ret = 0L; if(InterlockedDecrement((LPLONG)&_ref_count) != 0) { ret = _ref_count; } else { delete this; } return ret; } STDMETHODIMP DIFF_EXT::Initialize(LPCITEMIDLIST /*folder not used*/, IDataObject* data, HKEY /*key not used*/) { LOG(); #ifdef UNICODE tstring installDir = SERVER::instance()->getRegistryKeyString( TEXT(""), TEXT("InstallDir") ); tstring language = SERVER::instance()->getRegistryKeyString( TEXT(""), TEXT("Language") ); tstring translationFileName = installDir + TEXT("\\translations\\diff_ext_") + language + TEXT(".po"); if ( s_translationFileName != translationFileName ) { s_translationFileName = translationFileName; readTranslationFile(); } #endif FORMATETC format = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM medium; medium.tymed = TYMED_HGLOBAL; HRESULT ret = E_INVALIDARG; if(data->GetData(&format, &medium) == S_OK) { HDROP drop = (HDROP)medium.hGlobal; m_nrOfSelectedFiles = DragQueryFile(drop, 0xFFFFFFFF, 0, 0); TCHAR tmp[MAX_PATH]; //initialize_language(); if (m_nrOfSelectedFiles >= 1 && m_nrOfSelectedFiles <= 3) { DragQueryFile(drop, 0, tmp, MAX_PATH); _file_name1 = tmp; if(m_nrOfSelectedFiles >= 2) { DragQueryFile(drop, 1, tmp, MAX_PATH); _file_name2 = tmp; } if( m_nrOfSelectedFiles == 3) { DragQueryFile(drop, 2, tmp, MAX_PATH); _file_name3 = tmp; } ret = S_OK; } } else { SYSERRORLOG(TEXT("GetData")); } return ret; } static int insertMenuItemHelper( HMENU menu, UINT id, UINT position, const tstring& text, UINT fState = MFS_ENABLED, HMENU hSubMenu=0 ) { MENUITEMINFO item_info; ZeroMemory(&item_info, sizeof(item_info)); item_info.cbSize = sizeof(MENUITEMINFO); item_info.wID = id; if (text.empty()) { // Separator item_info.fMask = MIIM_TYPE; item_info.fType = MFT_SEPARATOR; item_info.dwTypeData = 0; } else { item_info.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | (hSubMenu!=0 ? MIIM_SUBMENU : 0); item_info.fType = MFT_STRING; item_info.fState = fState; item_info.dwTypeData = (LPTSTR)text.c_str(); item_info.hSubMenu = hSubMenu; } if ( 0 == InsertMenuItem(menu, position, TRUE, &item_info) ) SYSERRORLOG(TEXT("InsertMenuItem")); return id; } STDMETHODIMP DIFF_EXT::QueryContextMenu(HMENU menu, UINT position, UINT first_cmd, UINT /*last_cmd not used*/, UINT flags) { LOG(); SERVER::instance()->recent_files(); // updates recent files list (reads from registry) m_id_Diff = UINT(-1); m_id_DiffWith = UINT(-1); m_id_DiffLater = UINT(-1); m_id_MergeWith = UINT(-1); m_id_Merge3 = UINT(-1); m_id_Diff3 = UINT(-1); m_id_DiffWith_Base = UINT(-1); m_id_ClearList = UINT(-1); m_id_About = UINT(-1); HRESULT ret = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); if(!(flags & CMF_DEFAULTONLY)) { /* Menu structure: KDiff3 -> (1 File selected): Save 'selection' for later comparison (push onto history stack) Compare 'selection' with first file on history stack. Compare 'selection' with -> choice from history stack Merge 'selection' with first file on history stack. Merge 'selection' with last two files on history stack. (2 Files selected): Compare 's1' with 's2' Merge 's1' with 's2' (3 Files selected): Compare 's1', 's2' and 's3' */ HMENU subMenu = CreateMenu(); UINT id = first_cmd; m_id_FirstCmd = first_cmd; insertMenuItemHelper( menu, id++, position++, TEXT("") ); // begin separator tstring menuString; UINT pos2=0; if(m_nrOfSelectedFiles == 1) { size_t nrOfRecentFiles = m_recentFiles.size(); tstring menuStringCompare = i18n("Compare with %1"); tstring menuStringMerge = i18n("Merge with %1"); tstring firstFileName; if( nrOfRecentFiles>=1 ) { firstFileName = TEXT("'") + cut_to_length( m_recentFiles.front() ) + TEXT("'"); } replaceArgs( menuStringCompare, firstFileName ); replaceArgs( menuStringMerge, firstFileName ); m_id_DiffWith = insertMenuItemHelper( subMenu, id++, pos2++, menuStringCompare, nrOfRecentFiles >=1 ? MFS_ENABLED : MFS_DISABLED ); m_id_MergeWith = insertMenuItemHelper( subMenu, id++, pos2++, menuStringMerge, nrOfRecentFiles >=1 ? MFS_ENABLED : MFS_DISABLED ); //if( nrOfRecentFiles>=2 ) //{ // tstring firstFileName = cut_to_length( m_recentFiles.front() ); // tstring secondFileName = cut_to_length( *(++m_recentFiles.begin()) ); //} m_id_Merge3 = insertMenuItemHelper( subMenu, id++, pos2++, i18n("3-way merge with base"), nrOfRecentFiles >=2 ? MFS_ENABLED : MFS_DISABLED ); menuString = i18n("Save '%1' for later"); replaceArgs( menuString, _file_name1 ); m_id_DiffLater = insertMenuItemHelper( subMenu, id++, pos2++, menuString ); HMENU file_list = CreateMenu(); std::list::iterator i; m_id_DiffWith_Base = id; int n = 0; for( i = m_recentFiles.begin(); i!=m_recentFiles.end(); ++i ) { tstring s = cut_to_length( *i ); insertMenuItemHelper( file_list, id++, n, s ); ++n; } insertMenuItemHelper( subMenu, id++, pos2++, i18n("Compare with ..."), nrOfRecentFiles > 0 ? MFS_ENABLED : MFS_DISABLED, file_list ); m_id_ClearList = insertMenuItemHelper( subMenu, id++, pos2++, i18n("Clear list"), nrOfRecentFiles >=1 ? MFS_ENABLED : MFS_DISABLED ); } else if(m_nrOfSelectedFiles == 2) { //= "Diff " + cut_to_length(_file_name1, 20)+" and "+cut_to_length(_file_name2, 20); m_id_Diff = insertMenuItemHelper( subMenu, id++, pos2++, i18n("Compare") ); } else if ( m_nrOfSelectedFiles == 3 ) { m_id_Diff3 = insertMenuItemHelper( subMenu, id++, pos2++, i18n("3 way comparison") ); } else { // More than 3 files selected? } m_id_About = insertMenuItemHelper( subMenu, id++, pos2++, i18n("About Diff-Ext ...") ); insertMenuItemHelper( menu, id++, position++, TEXT("KDiff3"), MFS_ENABLED, subMenu ); insertMenuItemHelper( menu, id++, position++, TEXT("") ); // final separator ret = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, id-first_cmd); } return ret; } STDMETHODIMP DIFF_EXT::InvokeCommand(LPCMINVOKECOMMANDINFO ici) { HRESULT ret = NOERROR; _hwnd = ici->hwnd; if(HIWORD(ici->lpVerb) == 0) { UINT id = m_id_FirstCmd + LOWORD(ici->lpVerb); if(id == m_id_Diff) { LOG(); diff( TEXT("\"") + _file_name1 + TEXT("\" \"") + _file_name2 + TEXT("\"") ); } else if(id == m_id_Diff3) { LOG(); diff( TEXT("\"") + _file_name1 + TEXT("\" \"") + _file_name2 + TEXT("\" \"") + _file_name3 + TEXT("\"") ); } else if(id == m_id_Merge3) { LOG(); std::list< tstring >::iterator iFrom = m_recentFiles.begin(); std::list< tstring >::iterator iBase = iFrom; ++iBase; diff( TEXT("-m \"") + *iBase + TEXT("\" \"") + *iFrom + TEXT("\" \"") + _file_name1 + TEXT("\"") ); } else if(id == m_id_DiffWith) { LOG(); diff_with(0, false); } else if(id == m_id_MergeWith) { LOG(); diff_with(0, true); } else if(id == m_id_ClearList) { LOG(); m_recentFiles.clear(); SERVER::instance()->save_history(); } else if(id == m_id_DiffLater) { MESSAGELOG(TEXT("Diff Later: ")+_file_name1); m_recentFiles.remove( _file_name1 ); m_recentFiles.push_front( _file_name1 ); SERVER::instance()->save_history(); } else if(id >= m_id_DiffWith_Base && id < m_id_DiffWith_Base+m_recentFiles.size()) { LOG(); diff_with(id-m_id_DiffWith_Base, false); } else if(id == m_id_About) { LOG(); std::wstring sBits = i18n("(32 Bit)"); if (sizeof(void*)==8) sBits = i18n("(64 Bit)"); MessageBox( _hwnd, (i18n("Diff-Ext Copyright (c) 2003-2006, Sergey Zorin. All rights reserved.\n") - + i18n("This software is distributable under the BSD license.\n") + + i18n("This software is distributable under the BSD-2-Clause license.\n") + i18n("Some extensions for KDiff3 (c) 2006-2013 by Joachim Eibl.\n") + i18n("Homepage for Diff-Ext: http://diff-ext.sourceforge.net\n") + i18n("Homepage for KDiff3: http://kdiff3.sourceforge.net")).c_str() , (i18n("About Diff-Ext for KDiff3 ")+sBits).c_str(), MB_OK ); } else { ret = E_INVALIDARG; TCHAR verb[80]; _sntprintf(verb, 79, TEXT("Command id: %d"), LOWORD(ici->lpVerb)); verb[79]=0; ERRORLOG(verb); } } else { ret = E_INVALIDARG; } return ret; } STDMETHODIMP DIFF_EXT::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT*, LPSTR pszName, UINT cchMax) { // LOG(); // Gets called very often HRESULT ret = NOERROR; if(uFlags == GCS_HELPTEXT) { tstring helpString; if( idCmd == m_id_Diff ) { helpString = i18n("Compare selected files"); } else if( idCmd == m_id_DiffWith ) { if(!m_recentFiles.empty()) { helpString = i18n("Compare '%1' with '%2'"); replaceArgs( helpString, _file_name1, m_recentFiles.front() ); } } else if(idCmd == m_id_DiffLater) { helpString = i18n("Save '%1' for later operation"); replaceArgs( helpString, _file_name1 ); } else if((idCmd >= m_id_DiffWith_Base) && (idCmd < m_id_DiffWith_Base+m_recentFiles.size())) { if( !m_recentFiles.empty() ) { unsigned int num = idCmd - m_id_DiffWith_Base; std::list::iterator i = m_recentFiles.begin(); for(unsigned int j = 0; j < num && i != m_recentFiles.end(); j++) i++; if ( i!=m_recentFiles.end() ) { helpString = i18n("Compare '%1' with '%2'"); replaceArgs( helpString, _file_name1, *i ); } } } lstrcpyn( (LPTSTR)pszName, helpString.c_str(), cchMax ); } else { ret = E_INVALIDARG; } return ret; } void DIFF_EXT::diff( const tstring& arguments ) { LOG(); STARTUPINFO si; PROCESS_INFORMATION pi; bool bError = true; tstring command = SERVER::instance()->getRegistryKeyString( TEXT(""), TEXT("diffcommand") ); tstring commandLine = TEXT("\"") + command + TEXT("\" ") + arguments; if ( ! command.empty() ) { ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); if (CreateProcess(command.c_str(), (LPTSTR)commandLine.c_str(), 0, 0, FALSE, 0, 0, 0, &si, &pi) == 0) { SYSERRORLOG(TEXT("CreateProcess") + command); } else { bError = false; CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); } } if (bError) { tstring message = i18n("Could not start KDiff3. Please rerun KDiff3 installation."); message += TEXT("\n") + i18n("Command") + TEXT(": ") + command; message += TEXT("\n") + i18n("CommandLine") + TEXT(": ") + commandLine; MessageBox(_hwnd, message.c_str(), i18n("Diff-Ext For KDiff3").c_str(), MB_OK); } } void DIFF_EXT::diff_with(unsigned int num, bool bMerge) { LOG(); std::list::iterator i = m_recentFiles.begin(); for(unsigned int j = 0; j < num && i!=m_recentFiles.end(); j++) { i++; } if ( i!=m_recentFiles.end() ) _file_name2 = *i; diff( (bMerge ? TEXT("-m \"") : TEXT("\"") ) + _file_name2 + TEXT("\" \"") + _file_name1 + TEXT("\"") ); } tstring DIFF_EXT::cut_to_length(const tstring& in, size_t max_len) { tstring ret; if( in.length() > max_len) { ret = in.substr(0, (max_len-3)/2); ret += TEXT("..."); ret += in.substr( in.length()-(max_len-3)/2 ); } else { ret = in; } return ret; } diff --git a/diff_ext_for_kdiff3/diff_ext.h b/diff_ext_for_kdiff3/diff_ext.h index 76a9104..b126f73 100644 --- a/diff_ext_for_kdiff3/diff_ext.h +++ b/diff_ext_for_kdiff3/diff_ext.h @@ -1,67 +1,86 @@ /* * Copyright (c) 2003-2004, Sergey Zorin. All rights reserved. * - * This software is distributable under the BSD license. See the terms - * of the BSD license in the LICENSE file provided with this software. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ + #ifndef __diff_ext_h__ #define __diff_ext_h__ #include #include #include #include "server.h" // this is the actual OLE Shell context menu handler class DIFF_EXT : public IContextMenu, IShellExtInit { public: DIFF_EXT(); virtual ~DIFF_EXT(); //IUnknown members STDMETHODIMP QueryInterface(REFIID interface_id, void** result); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); //IShell members STDMETHODIMP QueryContextMenu(HMENU menu, UINT index, UINT cmd_first, UINT cmd_last, UINT flags); STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO info); STDMETHODIMP GetCommandString(UINT_PTR cmd, UINT flags, UINT* reserved, LPSTR name, UINT name_length); //IShellExtInit methods STDMETHODIMP Initialize(LPCITEMIDLIST folder, IDataObject* subj, HKEY key); private: void diff( const tstring& arguments ); void diff_with(unsigned int num, bool bMerge); tstring cut_to_length(const tstring&, size_t length = 64); void initialize_language(); private: UINT m_nrOfSelectedFiles; tstring _file_name1; tstring _file_name2; tstring _file_name3; HINSTANCE _resource; HWND _hwnd; ULONG _ref_count; std::list< tstring >& m_recentFiles; UINT m_id_FirstCmd; UINT m_id_Diff; UINT m_id_DiffWith; UINT m_id_DiffLater; UINT m_id_MergeWith; UINT m_id_Merge3; UINT m_id_Diff3; UINT m_id_DiffWith_Base; UINT m_id_About; UINT m_id_ClearList; }; #endif // __diff_ext_h__ diff --git a/diff_ext_for_kdiff3/diff_ext.pot b/diff_ext_for_kdiff3/diff_ext.pot index 6cc829c..56d3e4a 100644 --- a/diff_ext_for_kdiff3/diff_ext.pot +++ b/diff_ext_for_kdiff3/diff_ext.pot @@ -1,96 +1,96 @@ # Diff-ext-for-KDiff3 # Copyright (C) 2006 Joachim Eibl # This file is distributed under the same license as the diff-ext-for-KDiff3 package. # PO-Template created by Joachim Eibl , 2006. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-10-03 06:05+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: diff_ext.cpp:368 diff_ext.cpp:402 msgid "Compare with" msgstr "" #: diff_ext.cpp:369 msgid "Merge with" msgstr "" #: diff_ext.cpp:384 msgid "3-way merge with base" msgstr "" #: diff_ext.cpp:387 msgid "Save '%1' for later comparison or merge" msgstr "" #: diff_ext.cpp:408 msgid "Compare" msgstr "" #: diff_ext.cpp:412 msgid "3 way comparison" msgstr "" #: diff_ext.cpp:418 msgid "About Diff-Ext ..." msgstr "" #: diff_ext.cpp:482 msgid "Diff-Ext Copyright (c) 2003-2006, Sergey Zorin. All rights reserved.\n" msgstr "" #: diff_ext.cpp:483 -msgid "This software is distributable under the BSD license.\n" +msgid "This software is distributable under the BSD-2-Clause license.\n" msgstr "" #: diff_ext.cpp:484 msgid "Some extensions for KDiff3 by Joachim Eibl.\n" msgstr "" #: diff_ext.cpp:485 msgid "Homepage for Diff-Ext: http://diff-ext.sourceforge.net\n" msgstr "" #: diff_ext.cpp:486 msgid "Homepage for KDiff3: http://kdiff3.sourceforge.net" msgstr "" #: diff_ext.cpp:487 msgid "About Diff-Ext for KDiff3" msgstr "" #: diff_ext.cpp:512 msgid "Compare selected files" msgstr "" #: diff_ext.cpp:518 diff_ext.cpp:538 msgid "Compare '%1' with '%2'" msgstr "" #: diff_ext.cpp:524 msgid "Save '%1' for later operation" msgstr "" #: diff_ext.cpp:576 msgid "Could not start KDiff3. Please rerun KDiff3 installation." msgstr "" #: diff_ext.cpp:577 msgid "Command" msgstr "" #: diff_ext.cpp:578 msgid "CommandLine" msgstr "" #: diff_ext.cpp:579 msgid "Diff-Ext For KDiff3" msgstr "" diff --git a/diff_ext_for_kdiff3/diff_ext_de.po b/diff_ext_for_kdiff3/diff_ext_de.po deleted file mode 100644 index 9cfa297..0000000 --- a/diff_ext_for_kdiff3/diff_ext_de.po +++ /dev/null @@ -1,102 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2006-09-04 15:35+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#: diff_ext.cpp:363 -msgid "Compare with %1" -msgstr "Vergleichen mit %1" - -#: diff_ext.cpp:364 -msgid "Merge with %1" -msgstr "Zusammenführen mit %1" - -#: diff_ext.cpp:379 -msgid "3-way merge with base" -msgstr "3-Wege Zusammenführung mit Basis" - -#: diff_ext.cpp:382 -msgid "Save '%1' for later" -msgstr "Speichere '%1' für später" - -#: diff_ext.cpp:404 -msgid "Compare with ..." -msgstr "Vergleichen mit ..." - -#: diff_ext.cpp:403 -msgid "Compare" -msgstr "Vergleichen" - -#: diff_ext.cpp:403 -msgid "Clear list" -msgstr "Liste löschen" - - -#: diff_ext.cpp:407 -msgid "3 way comparison" -msgstr "Vergleiche 3 Dateien" - -#: diff_ext.cpp:413 -msgid "About Diff-Ext ..." -msgstr "Über Diff-Ext ..." - -#: diff_ext.cpp:474 -msgid "Diff-Ext Copyright (c) 2003-2006, Sergey Zorin. All rights reserved.\n" -msgstr "Diff-Ext Copyright (c) 2003-2006, Sergey Zorin. Alle Rechte vorbehalten.\n" - -#: diff_ext.cpp:475 -msgid "This software is distributable under the BSD license.\n" -msgstr "Weitergabe dieses Programms unter den Bedingungen der BSD Lizenz.\n" - -#: diff_ext.cpp:476 -msgid "Some extensions for KDiff3 by Joachim Eibl.\n" -msgstr "Einige Erweiterungen für KDiff3 von Joachim Eibl.\n" - -#: diff_ext.cpp:477 -msgid "See the homepage http://diff-ext.sourceforge.net" -msgstr "Siehe die Homepage http://diff-ext.sourceforge.net" - -#: diff_ext.cpp:478 -msgid "About Diff-Ext for KDiff3" -msgstr "Über Diff-Ext für KDiff3" - -#: diff_ext.cpp:503 -msgid "Compare selected files" -msgstr "Vergleiche markierte Dateien" - -#: diff_ext.cpp:509 diff_ext.cpp:529 -msgid "Compare '%1' with '%2'" -msgstr "Vergleiche '%1' mit '%2'" - -#: diff_ext.cpp:515 -msgid "Merke '%1' für spätere Aktion" -msgstr "" - -#: diff_ext.cpp:567 -msgid "Could not start KDiff3. Please rerun KDiff3 installation." -msgstr "Konnte KDiff3 nicht starten. Bitte wiederholen Sie die KDiff3 Installation." - -#: diff_ext.cpp:568 -msgid "Command" -msgstr "Kommando" - -#: diff_ext.cpp:569 -msgid "CommandLine" -msgstr "Kommandozeile" - -#: diff_ext.cpp:570 -msgid "Diff-Ext For KDiff3" -msgstr "Diff-Ext für KDiff3" diff --git a/diff_ext_for_kdiff3/diffextstring.h b/diff_ext_for_kdiff3/diffextstring.h index 132512e..d488499 100644 --- a/diff_ext_for_kdiff3/diffextstring.h +++ b/diff_ext_for_kdiff3/diffextstring.h @@ -1,157 +1,176 @@ /* * Copyright (c) 2003, Sergey Zorin. All rights reserved. * - * This software is distributable under the BSD license. See the terms of the - * BSD license in the LICENSE file provided with this software. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ + #ifndef __string_h__ #define __string_h__ #include #include #include #include class STRING; inline STRING operator+( const STRING& s1, const STRING& s2); class STRING { public: static const int begin = 0; static const int end = -1; public: STRING(const STRING& s) { _str = new TCHAR[s.length()+1]; lstrcpy(_str, s); } STRING(const TCHAR* str = TEXT("")) { _str = new TCHAR[lstrlen(str)+1]; lstrcpy(_str, str); } ~STRING() { delete[] _str; } void resize( size_t newLength ) { size_t oldLength = length(); if ( newLength < oldLength ) { _str[newLength] = 0; // Just truncate the string } else if( newLength>oldLength) { TCHAR* p = new TCHAR[ newLength + 1 ]; lstrcpy(p, _str); for( size_t i=oldLength; i #include #include #include #include #include #include #include //#include //#include //#include //#include #include "server.h" #include "class_factory.h" #define DllExport __declspec( dllexport ) // registry key util struct struct REGSTRUCT { LPCTSTR subkey; LPCTSTR name; LPCTSTR value; }; SERVER* SERVER::_instance = 0; static HINSTANCE server_instance; // Handle to this DLL itself. //DEFINE_GUID(CLSID_DIFF_EXT, 0xA0482097, 0xC69D, 0x4DEC, 0x8A, 0xB6, 0xD3, 0xA2, 0x59, 0xAC, 0xC1, 0x51); // New class id for DIFF_EXT for KDiff3 #ifdef _WIN64 // {34471FFB-4002-438b-8952-E4588D0C0FE9} DEFINE_GUID( CLSID_DIFF_EXT, 0x34471FFB, 0x4002, 0x438b, 0x89, 0x52, 0xE4, 0x58, 0x8D, 0x0C, 0x0F, 0xE9 ); #else DEFINE_GUID( CLSID_DIFF_EXT, 0x9f8528e4, 0xab20, 0x456e, 0x84, 0xe5, 0x3c, 0xe6, 0x9d, 0x87, 0x20, 0xf3 ); #endif tstring SERVER::getRegistryKeyString( const tstring& subKey, const tstring& value ) { tstring keyName = m_registryBaseName; if (!subKey.empty()) keyName += TEXT("\\")+subKey; HKEY key; HKEY baseKey = HKEY_CURRENT_USER; tstring result; for(;;) { if( RegOpenKeyEx( baseKey, keyName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &key ) == ERROR_SUCCESS ) { DWORD neededSizeInBytes = 0; if (RegQueryValueEx(key, value.c_str(), 0, 0, 0, &neededSizeInBytes) == ERROR_SUCCESS) { DWORD length = neededSizeInBytes / sizeof( TCHAR ); result.resize( length ); if ( RegQueryValueEx( key, value.c_str(), 0, 0, (LPBYTE)&result[0], &neededSizeInBytes ) == ERROR_SUCCESS) { //Everything is ok, but we want to cut off the terminating 0-character result.resize( length - 1 ); RegCloseKey(key); return result; } else { result.resize(0); } } RegCloseKey(key); } if (baseKey==HKEY_LOCAL_MACHINE) break; baseKey = HKEY_LOCAL_MACHINE; } // Error { LPTSTR message; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &message, 0, 0); ERRORLOG( (tstring(TEXT("RegOpenKeyEx: ")+keyName+TEXT("->")+value) + TEXT(": ")) + message ); \ LocalFree(message); } return result; } STDAPI DllCanUnloadNow(void) { HRESULT ret = S_FALSE; if(SERVER::instance()->reference_count() == 0) { ret = S_OK; } return ret; } extern "C" int APIENTRY DllMain(HINSTANCE instance, DWORD reason, LPVOID /* reserved */) { // char str[1024]; // char* reason_string[] = {"DLL_PROCESS_DETACH", "DLL_PROCESS_ATTACH", "DLL_THREAD_ATTACH", "DLL_THREAD_DETACH"}; // sprintf(str, "instance: %x; reason: '%s'", instance, reason_string[reason]); // MessageBox(0, str, TEXT("Info"), MB_OK); switch (reason) { case DLL_PROCESS_ATTACH: server_instance = instance; SERVER::instance()->save_history(); MESSAGELOG(TEXT("DLL_PROCESS_ATTACH")); break; case DLL_PROCESS_DETACH: MESSAGELOG(TEXT("DLL_PROCESS_DETACH")); SERVER::instance()->save_history(); break; } return 1; } STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** class_object) { HRESULT ret = CLASS_E_CLASSNOTAVAILABLE; *class_object = 0; if (IsEqualIID(rclsid, CLSID_DIFF_EXT)) { CLASS_FACTORY* pcf = new CLASS_FACTORY(); ret = pcf->QueryInterface(riid, class_object); } return ret; } /*extern "C" HRESULT STDAPICALLTYPE*/ STDAPI DllRegisterServer() { return SERVER::instance()->do_register(); } STDAPI DllUnregisterServer() { return SERVER::instance()->do_unregister(); } SERVER* SERVER::instance() { if(_instance == 0) { _instance = new SERVER(); _instance->initLogging(); MESSAGELOG(TEXT("New Server instance")); } return _instance; } SERVER::SERVER() : _reference_count(0) { m_registryBaseName = TEXT("Software\\KDiff3\\diff-ext"); m_pRecentFiles = 0; m_pLogFile = 0; } void SERVER::initLogging() { tstring logFileName = getRegistryKeyString( TEXT(""), TEXT("LogFile") ); if ( !logFileName.empty() ) { m_pLogFile = _tfopen( logFileName.c_str(), TEXT("a+, ccs=UTF-8") ); if (m_pLogFile) { _ftprintf( m_pLogFile, TEXT("\nSERVER::SERVER()\n") ); } } } SERVER::~SERVER() { if ( m_pLogFile ) { _ftprintf( m_pLogFile, TEXT("SERVER::~SERVER()\n\n") ); fclose( m_pLogFile ); } delete m_pRecentFiles; } HINSTANCE SERVER::handle() const { return server_instance; } void SERVER::lock() { InterlockedIncrement(&_reference_count); } void SERVER::release() { InterlockedDecrement(&_reference_count); //if(InterlockedDecrement((LPLONG)&_reference_count) == 0) // delete this; } void SERVER::logMessage( const char* function, const char* file, int line, const tstring& msg ) { SERVER* pServer = SERVER::instance(); if ( pServer && pServer->m_pLogFile ) { SYSTEMTIME st; GetSystemTime( &st ); _ftprintf( pServer->m_pLogFile, TEXT("%04d/%02d/%02d %02d:%02d:%02d ") #ifdef UNICODE TEXT("%S (%S:%d) %s\n"), // integrate char-string into wchar_t string #else TEXT("%s (%s:%d) %s\n"), #endif st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, function, file, line, msg.c_str() ); fflush(pServer->m_pLogFile); } } std::list& SERVER::recent_files() { LOG(); if ( m_pRecentFiles==0 ) { m_pRecentFiles = new std::list; } else { m_pRecentFiles->clear(); } MESSAGELOG(TEXT("Reading history from registry...")); for( int i=0; i<32; ++i ) // Max history size { TCHAR numAsString[10]; _sntprintf( numAsString, 10, TEXT("%d"), i ); tstring historyItem = getRegistryKeyString( TEXT("history"), numAsString ); if ( ! historyItem.empty() ) m_pRecentFiles->push_back( historyItem ); } return *m_pRecentFiles; } void SERVER::save_history() const { if( m_pRecentFiles ) { HKEY key; if( RegCreateKeyEx(HKEY_CURRENT_USER, (m_registryBaseName + TEXT("\\history")).c_str(), 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_WOW64_64KEY, 0, &key, 0) == ERROR_SUCCESS ) { LOG(); //DWORD len = MAX_PATH; int n = 0; std::list::const_iterator i; for(i = m_pRecentFiles->begin(); i!=m_pRecentFiles->end(); ++i, ++n ) { tstring str = *i; TCHAR numAsString[10]; _sntprintf( numAsString, 10, TEXT("%d"), n ); if(RegSetValueEx(key, numAsString, 0, REG_SZ, (const BYTE*)str.c_str(), (DWORD)(str.size()+1)*sizeof(TCHAR) ) != ERROR_SUCCESS) { LPTSTR message; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &message, 0, 0); MessageBox(0, message, TEXT("KDiff3-diff-ext: Save history failed"), MB_OK | MB_ICONINFORMATION); LocalFree(message); } } for(; n<32; ++n ) { TCHAR numAsString[10]; _sntprintf( numAsString, 10, TEXT("%d"), n ); RegDeleteValue(key, numAsString ); } RegCloseKey(key); } else { SYSERRORLOG(TEXT("RegOpenKeyEx")); } } } HRESULT SERVER::do_register() { LOG(); TCHAR class_id[MAX_PATH]; LPWSTR tmp_guid; HRESULT ret = SELFREG_E_CLASS; if (StringFromIID(CLSID_DIFF_EXT, &tmp_guid) == S_OK) { #ifdef UNICODE _tcsncpy(class_id, tmp_guid, MAX_PATH); #else wcstombs(class_id, tmp_guid, MAX_PATH); #endif CoTaskMemFree((void*)tmp_guid); TCHAR subkey[MAX_PATH]; TCHAR server_path[MAX_PATH]; HKEY key; LRESULT result = NOERROR; DWORD dwDisp; GetModuleFileName(SERVER::instance()->handle(), server_path, MAX_PATH); REGSTRUCT entry[] = { {TEXT("Software\\Classes\\CLSID\\%s"), 0, TEXT("diff-ext-for-kdiff3")}, {TEXT("Software\\Classes\\CLSID\\%s\\InProcServer32"), 0, TEXT("%s")}, {TEXT("Software\\Classes\\CLSID\\%s\\InProcServer32"), TEXT("ThreadingModel"), TEXT("Apartment")} }; for(unsigned int i = 0; (i < sizeof(entry)/sizeof(entry[0])) && (result == NOERROR); i++) { _sntprintf(subkey, MAX_PATH, entry[i].subkey, class_id); result = RegCreateKeyEx(HKEY_CURRENT_USER, subkey, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &dwDisp); if(result == NOERROR) { TCHAR szData[MAX_PATH]; _sntprintf(szData, MAX_PATH, entry[i].value, server_path); szData[MAX_PATH-1]=0; result = RegSetValueEx(key, entry[i].name, 0, REG_SZ, (LPBYTE)szData, DWORD(_tcslen(szData)*sizeof(TCHAR))); } RegCloseKey(key); } if(result == NOERROR) { result = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Classes\\*\\shellex\\ContextMenuHandlers\\diff-ext-for-kdiff3"), 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &dwDisp); if(result == NOERROR) { result = RegSetValueEx(key, 0, 0, REG_SZ, (LPBYTE)class_id, DWORD(_tcslen(class_id)*sizeof(TCHAR))); RegCloseKey(key); //If running on NT, register the extension as approved. OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); // NT needs to have shell extensions "approved". if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { result = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &dwDisp); if(result == NOERROR) { TCHAR szData[MAX_PATH]; lstrcpy(szData, TEXT("diff-ext")); result = RegSetValueEx(key, class_id, 0, REG_SZ, (LPBYTE)szData, DWORD(_tcslen(szData)*sizeof(TCHAR))); RegCloseKey(key); ret = S_OK; } else if (result == ERROR_ACCESS_DENIED) { TCHAR msg[] = TEXT("Warning! You have unsufficient rights to write to a specific registry key.\n") TEXT("The application may work anyway, but it is advised to register this module ") TEXT("again while having administrator rights."); MessageBox(0, msg, TEXT("Warning"), MB_ICONEXCLAMATION); ret = S_OK; } } else { ret = S_OK; } } } } return ret; } HRESULT SERVER::do_unregister() { LOG(); TCHAR class_id[MAX_PATH]; LPWSTR tmp_guid; HRESULT ret = SELFREG_E_CLASS; if (StringFromIID(CLSID_DIFF_EXT, &tmp_guid) == S_OK) { #ifdef UNICODE _tcsncpy(class_id, tmp_guid, MAX_PATH); #else wcstombs(class_id, tmp_guid, MAX_PATH); #endif CoTaskMemFree((void*)tmp_guid); LRESULT result = NOERROR; TCHAR subkey[MAX_PATH]; REGSTRUCT entry[] = { {TEXT("Software\\Classes\\CLSID\\%s\\InProcServer32"), 0, 0}, {TEXT("Software\\Classes\\CLSID\\%s"), 0, 0} }; for(unsigned int i = 0; (i < sizeof(entry)/sizeof(entry[0])) && (result == NOERROR); i++) { _stprintf(subkey, entry[i].subkey, class_id); result = RegDeleteKey(HKEY_CURRENT_USER, subkey); } if(result == NOERROR) { result = RegDeleteKey(HKEY_CURRENT_USER, TEXT("Software\\Classes\\*\\shellex\\ContextMenuHandlers\\diff-ext-for-kdiff3")); if(result == NOERROR) { //If running on NT, register the extension as approved. OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); // NT needs to have shell extensions "approved". if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { HKEY key; RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), 0, KEY_ALL_ACCESS, &key); result = RegDeleteValue(key, class_id); RegCloseKey(key); if(result == ERROR_SUCCESS) { ret = S_OK; } } else { ret = S_OK; } } } } return ret; } diff --git a/diff_ext_for_kdiff3/server.h b/diff_ext_for_kdiff3/server.h index ffaf90b..591728c 100644 --- a/diff_ext_for_kdiff3/server.h +++ b/diff_ext_for_kdiff3/server.h @@ -1,81 +1,99 @@ /* * Copyright (c) 2003-2005, Sergey Zorin. All rights reserved. * - * This software is distributable under the BSD license. See the terms - * of the BSD license in the LICENSE file provided with this software. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __server_h__ #define __server_h__ #include // std::list //#include #include #if 1 #include // std::wstring #ifdef UNICODE typedef std::wstring tstring; #else typedef std::string tstring; #endif #define i18n(x) getTranslation( TEXT(x) ) #else #include "diffextstring.h" typedef STRING tstring; #define i18n(x) TEXT(x) #endif #define MESSAGELOG( msg ) SERVER::logMessage( __FUNCTION__, __FILE__, __LINE__, msg ) #define LOG() MESSAGELOG( TEXT("") ) #define ERRORLOG( msg ) MESSAGELOG( TEXT("Error: ")+tstring(msg) ) #define SYSERRORLOG( msg ) \ { \ LPTSTR message; \ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, \ GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &message, 0, 0); \ ERRORLOG( (tstring(msg) + TEXT(": ")) + message ); \ LocalFree(message); \ } class SERVER { public: static SERVER* instance(); void initLogging(); public: virtual ~SERVER(); tstring getRegistryKeyString( const tstring& subKey, const tstring& value ); HINSTANCE handle() const; HRESULT do_register(); HRESULT do_unregister(); void lock(); void release(); ULONG reference_count() const { return _reference_count; } std::list< tstring >& recent_files(); void save_history() const; static void logMessage( const char* function, const char* file, int line, const tstring& msg ); private: SERVER(); SERVER(const SERVER&) {} private: LONG _reference_count; std::list* m_pRecentFiles; static SERVER* _instance; tstring m_registryBaseName; FILE* m_pLogFile; }; #endif // __server_h__