# HG changeset patch # User joachim99 # Date 1078653549 0 # Node ID 8af4bb9d9a5a8ccb7fdecfbc63ad38067dc229bd # Parent 023fbd76c1e34262ec37f3d49c279612b85aa6a2 Version 0.9.83 diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/ChangeLog --- a/kdiff3/ChangeLog Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/ChangeLog Sun Mar 07 09:59:09 2004 +0000 @@ -1,3 +1,35 @@ +Version 0.9.83 - 2004/03/06 +=========================== +- Reading directorys fixed for Win95/98 +- Caseinsensitive filename matching for windows. +- Autocopy to selection for systems that support this. (Patch by Stefan Partheymueller) +- Drawing during recalc suppressed in merge result editor. +- Cursor could go beyond last line in merge result editor. (Corrected NrOfLine-counting.) +- Windows: Start with invalid cmd-line-options brings up a messagebox with the list of options. +- Corrected encoding when copying to or pasting from clipboard. +- Corrected char-by-char-diff at beginning of line. ("012345 12345 xyz" <-> "012345 xyz") +- Warning when merging with preprocessor or upcase-conversion enabled. +- Rewrite of preprocessing code should fix several problems. E.g.: + - Ignore C/C++-comments only worked with a preprocessor active. + - Preprocessor output now is input of line-matching preprocessor. + - Paste to diff-window, didn't work if LMPP or Ignore C/C++-Comments was set. + +Version 0.9.82 - 2004/02/02 +=========================== +- DirectoryMerge: Running merge op for last item in a folder, performed the + merge op for all following items in following folders. (Possible data loss!) +- Fix: Preprocessors and "Ignore Comments" didn't work at the same time. +- Fix: Preprocessors crashed with remote files. +- Open-Dialog: When either input is changed, then reset the output to be empty. + (To avoid accidental overwrites.) +- Icon for "Highlight white space differences." +- Editor-Option: Line End Style for saving: Dos/Windows "\r\n" vs. Unix "\n" +- Merge output editor: Corrected wrong encoding for output-filename and + user-typed characters. +- Speedup for reading directories under Windows. +- Enhanced progress dialog responsiveness during local file copy. +- Fix for non-KDE-version: No URL-encoding when dropping files in open dialog. + Version 0.9.81 - 2004/01/08 =========================== - Allow to compile with --enable-final @@ -40,7 +72,7 @@ - Default diff-view now again side by side instead of one above the other. -Version 0.9.71 - 2003/10/14 +Version 0.9.71 - 2003/10/17 =========================== - Windows-Installer by Sebastien Fricker. - Bugfixes for Windows. (Problems with setFont() in paintEvent().) diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/README --- a/kdiff3/README Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/README Sun Mar 07 09:59:09 2004 +0000 @@ -3,7 +3,7 @@ Author: Joachim Eibl (joachim.eibl@gmx.de) Copyright: (C) 2002-2003 by Joachim Eibl -KDiff3-Version: 0.9.81 +KDiff3-Version: 0.9.83 KDiff3 is a program that @@ -45,12 +45,12 @@ Requirements & Installation: - Version 0.9.81 provides special support for KDE3, but it can also be + Version 0.9.83 provides special support for KDE3, but it can also be built without KDE3 if the Qt-libraries are available. (I also tested the program under Windows.) You always need - - kdiff3-0.9.81.tar.gz + - kdiff3-0.9.83.tar.gz For building the KDE3-version - KDE>=3.1 and QT>=3.1-libraries. @@ -67,7 +67,7 @@ - Make sure your shell-variable QTDIR is correct. (echo $QTDIR). If it doesn't contain the correct path, type export QTDIR=your_path_to_qt (e.g. /usr/lib/qt3) - - cd into the directory kdiff3-0.9.81 and type + - cd into the directory kdiff3-0.9.83 and type - ./configure --prefix=/opt/kde3 (your KDE3 directory here) - (make clean) (Required if you already compiled once.) - make (Run compilation) @@ -78,6 +78,9 @@ If some icons are not visible or don't seem right, probably the prefix was wrong. Check where your KDE3 installation is located and use that directory with the prefix-option of configure. + + This command should tell you: kde-config --prefix + For SuSE and most distributions the prefix usually is /opt/kde3. For Redhat and Mandrake the prefix usually is /usr. For a local installation, that doesn't need root rights try @@ -105,7 +108,7 @@ - Make sure your shell-variable QTDIR is correct. (echo $QTDIR). If it doesn't contain the correct path, type export QTDIR=your_path_to_qt (e.g. /usr/lib/qt) - - cd into the directory kdiff3-0.9.81/src and type + - cd into the directory kdiff3-0.9.83/src and type - make -f Makefile.qt - make -f Makefile.qt install (You must have root-rights for this step.) (copies the files into /usr/local/bin and /usr/local/share/doc/kdiff3) @@ -124,7 +127,7 @@ - I couldn't test this, so you might have to experiment a bit. - Start by generating a Makefile with - qmake kdiff3.pro -o Makefile - - If you succeed, I'd like to know how so I can document it here. + - If you succeed, I'd like to know how, so I can document it here. Start from commandline: diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/TODO --- a/kdiff3/TODO Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/TODO Sun Mar 07 09:59:09 2004 +0000 @@ -3,7 +3,78 @@ TODO ==== -- Automatic line wrap in the difference windows +- Automatic line wrap for too long lines in the difference windows - Printing of the diff-windows (requires automatic line wrap) - Undo function in the merge-editor. - More viewing options for directory widget. + +- And one observation. When select Cyrillic charset - it looks like it was + not saved. When open this dialog again - Latin charset is selected anyway. +- Add options to specify a language and charset. +- Ask before saving to a file that already exists (optionally). +- Don't overwrite existing .orig-file, when saving the second time. + +- File Menu: Close (Ctrl-F4): Close current file (check if saved and forget the data) +- Dirview: + - Multiselections: Changing Operations or applying ops for all selected items. + - Optionally show size/date for A/B/C + - Choose what to see (all or only different items) + - If only different items are visible: copy the others nevertheless to destdir. + - Improve Ctrl-1/2/3 shortcuts in Dirview. + - Warnung wenn Datum in B oder C lter als A ist. + - Zielverzeichnis nachtrglich nderbar + - Bei Kopie von Remote nach lokal: Auf jeden Fall das modification Datum setzen. + - Ctrl-Space doesn't work when a file comparison takes place. + - Option to allow case-insensitive filename-matching. +- Options to show/suppress annoying messages + +- Unicode-support + +- What's this-Help. +- Tip of the day. + +More Statistics before the merge begins: +- How many files are there? +- How many files are equal/different? +- How many files would be copies/merged/ignored? + +- Allow to view and merge CVS-conflict files (and diff3-output) and allow to save output + with conflicts in diff3 output-format. + +- Provide configure-rules for systems without KDE. (I need help here.) + +- Allow different comment-styles (e.g. via a regexp for comments) + +- Possibility to jump to next difference in the same line (for very long lines). + +- Allow analysis of unified directory-diff/patch-file. + +- Add example for line-matching preprocessor to the documentation. + Simple testcase: Consider file a.txt (6 lines): + aa + ba + ca + da + ea + fa + And file b.txt (3 lines): + cg + dg + eg + And the following line matching preprocessor command, that replaces 'g' with 'a': + /usr/bin/perl -p -e 's/g/a/;' + Without that command the following lines would be placed next to each other: + aa - cg + ba - dg + ca - eg + da + ea + fa + But with this command the result of the comparison would be: + aa + ba + ca - cg + da - dg + ea - eg + fa + diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/configure.in.in --- a/kdiff3/configure.in.in Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/configure.in.in Sun Mar 07 09:59:09 2004 +0000 @@ -1,6 +1,6 @@ -#MIN_CONFIG(3.0.0) +#MIN_CONFIG(3.1) -AM_INIT_AUTOMAKE(kdiff3, 0.9.70) +AM_INIT_AUTOMAKE(kdiff3, 0.9.82) AC_C_BIGENDIAN AC_CHECK_KDEMAXPATHLEN diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/common.h --- a/kdiff3/src/common.h Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/common.h Sun Mar 07 09:59:09 2004 +0000 @@ -2,7 +2,7 @@ common.h - Things that are needed often ------------------- begin : Mon Mar 18 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/diff.cpp --- a/kdiff3/src/diff.cpp Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/diff.cpp Sun Mar 07 09:59:09 2004 +0000 @@ -2,7 +2,7 @@ diff.cpp - description ------------------- begin : Mon Mar 18 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ @@ -20,6 +20,7 @@ #include "diff.h" #include "fileaccess.h" +#include "optiondialog.h" #include #include @@ -32,7 +33,7 @@ //using namespace std; -int LineData::width() +int LineData::width() const { int w=0; int j=0; @@ -110,64 +111,424 @@ } -// class needed during preprocess phase -class LineDataRef + + +static bool isLineOrBufEnd( const char* p, int i, int size ) { - const LineData* m_pLd; -public: - LineDataRef(const LineData* pLd){ m_pLd = pLd; } + return + i>=size // End of file + || p[i]=='\n' // Normal end of line - bool operator<(const LineDataRef& ldr2) const - { - const LineData* pLd1 = m_pLd; - const LineData* pLd2 = ldr2.m_pLd; - const char* p1 = pLd1->pFirstNonWhiteChar; - const char* p2 = pLd2->pFirstNonWhiteChar; + // No support for Mac-end of line yet, because incompatible with GNU-diff-routines. + // || ( p[i]=='\r' && (i>=size-1 || p[i+1]!='\n') + // && (i==0 || p[i-1]!='\n') ) // Special case: '\r' without '\n' + ; +} - int size1=pLd1->size; - int size2=pLd2->size; - int i1=min2(pLd1->pFirstNonWhiteChar - pLd1->pLine,size1); - int i2=min2(pLd2->pFirstNonWhiteChar - pLd2->pLine,size2); - for(;;) - { - while( i1 0 ) + { + +#ifdef _WIN32 + QString catCmd = "type"; + fileNameIn1.replace( '/', "\\" ); +#else + QString catCmd = "cat"; +#endif + + // Run the first preprocessor + if ( m_pOptionDialog->m_PreProcessorCmd.isEmpty() ) + { + // No preprocessing: Read the file directly: + m_normalData.readFile( fileNameIn1 ); + } + else + { + QString ppCmd = m_pOptionDialog->m_PreProcessorCmd; + fileNameOut1 = FileAccess::tempFileName(); + QString cmd = catCmd + " \"" + fileNameIn1 + "\" | " + ppCmd + " >\"" + fileNameOut1+"\""; + ::system( encodeString(cmd, m_pOptionDialog) ); + bool bSuccess = m_normalData.readFile( fileNameOut1 ); + if ( fileInSize >0 && ( !bSuccess || m_normalData.m_size==0 ) ) + { + KMessageBox::error(m_pOptionDialog, + i18n("Preprocessing possibly failed. Check this command:\n\n %1" + "\n\nThe preprocessing command will be disabled now." + ).arg(cmd) ); + m_pOptionDialog->m_PreProcessorCmd = ""; + m_normalData.readFile( fileNameIn1 ); + } + } + + // Internal Preprocessing: Uppercase-conversion + bool bInternalPreprocessing = false; + if ( m_pOptionDialog->m_bUpCase ) + { + int i; + char* pBuf = const_cast(m_normalData.m_pBuf); + for(i=0; im_LineMatchingPreProcessorCmd.isEmpty() ) + { + if ( bInternalPreprocessing ) + { + // write data to file after internal preprocessing before running the external LMPP-cmd. + if ( !fileNameOut1.isEmpty() ) + { + FileAccess::removeFile( fileNameOut1 ); + fileNameOut1=""; + } + + fileNameIn2 = FileAccess::tempFileName(); + bool bSuccess = m_normalData.writeFile( fileNameIn2 ); + if ( !bSuccess ) + { + KMessageBox::error(m_pOptionDialog, i18n("Error writing temporary file: %1").arg(fileNameIn2) ); + } + } + else + { + fileNameIn2 = fileNameOut1.isEmpty() ? fileNameIn1 : fileNameOut1; + } + + QString ppCmd = m_pOptionDialog->m_LineMatchingPreProcessorCmd; + fileNameOut2 = FileAccess::tempFileName(); + QString cmd = catCmd + " \"" + fileNameIn2 + "\" | " + ppCmd + " >\"" + fileNameOut2 + "\""; + ::system( encodeString(cmd, m_pOptionDialog) ); + bool bSuccess = m_lmppData.readFile( fileNameOut2 ); + if ( FileAccess(fileNameIn2).size()>0 && ( !bSuccess || m_lmppData.m_size==0 ) ) + { + KMessageBox::error(m_pOptionDialog, + i18n("The line-matching-preprocessing possibly failed. Check this command:\n\n %1" + "\n\nThe line-matching-preprocessing command will be disabled now." + ).arg(cmd) ); + m_pOptionDialog->m_LineMatchingPreProcessorCmd = ""; + m_lmppData.readFile( fileNameIn2 ); + } + FileAccess::removeFile( fileNameOut2 ); + + if ( bInternalPreprocessing && !fileNameIn2.isEmpty() ) + { + FileAccess::removeFile( fileNameIn2 ); + fileNameIn2=""; + } + } + else if ( m_pOptionDialog->m_bIgnoreComments ) + { + // We need a copy of the normal data. + m_lmppData.copyBufFrom( m_normalData ); + } + else + { // We don't need any lmpp data at all. + m_lmppData.reset(); + } + } + + m_normalData.preprocess( m_pOptionDialog->m_bPreserveCarriageReturn ); + m_lmppData.preprocess( false ); + + if ( m_lmppData.m_vSize < m_normalData.m_vSize ) + { + // This probably is the fault of the LMPP-Command, but not worth reporting. + m_lmppData.m_v.resize( m_normalData.m_vSize ); + for(int i=m_lmppData.m_vSize; im_bIgnoreComments ) + { + m_lmppData.removeComments(); + int vSize = min2(m_normalData.m_vSize, m_lmppData.m_vSize); + for(int i=0; i0 && m_v[lineIdx].pLine[lineLength-1]=='\r' ) @@ -237,7 +598,7 @@ { bWhite = false; ++i; - for( ; i=size ) + if ( isLineOrBufEnd(p,i,size) ) { return; } @@ -307,7 +668,7 @@ // Modifies the input data, and replaces C/C++ comments with whitespace // when the line contains other data too. If the line contains only // a comment or white data, remember this in the flag bContainsPureComment. -void SourceData::removeComments( LineData* pLD ) +void SourceData::FileData::removeComments() { int line=0; char* p = (char*)m_pBuf; @@ -324,7 +685,7 @@ int commentStart = i; bCommentInLine = true; - for( ; i=size || p[i]=='\n'); - pLD[line].bContainsPureComment = bCommentInLine && bWhite; + assert( isLineOrBufEnd(p,i,size)); + m_v[line].bContainsPureComment = bCommentInLine && bWhite; /* std::cout << line << " : " << ( bCommentInLine ? "c" : " " ) << ( bWhite ? "w " : " ") << @@ -357,171 +718,8 @@ } } -// read and preprocess file for line matching input data -void SourceData::readLMPPFile( SourceData* pOrigSource, const QString& ppCmd, bool bUpCase, bool bRemoveComments ) -{ - if ( ( ppCmd.isEmpty() && !bRemoveComments ) || pOrigSource->m_bPreserve ) - { - reset(); - } - else - { - setFilename( pOrigSource->m_fileAccess.absFilePath() ); - readPPFile( false, ppCmd, bUpCase ); - if ( m_vSize < pOrigSource->m_vSize ) - { - m_v.resize( pOrigSource->m_vSize ); - m_vSize = pOrigSource->m_vSize; - } - } - if ( bRemoveComments && m_vSize==pOrigSource->m_vSize ) - removeComments( &pOrigSource->m_v[0] ); -} -void SourceData::readPPFile( bool bPreserveCR, const QString& ppCmd, bool bUpCase ) -{ - if ( !m_bPreserve ) - { - if ( ! ppCmd.isEmpty() && !m_fileName.isEmpty() && FileAccess::exists( m_fileName ) ) - { - QString fileNameOut = FileAccess::tempFileName(); -#ifdef _WIN32 - QString cmd = QString("type ") + m_fileName + " | " + ppCmd + " >" + fileNameOut; -#else - QString cmd = QString("cat ") + m_fileName + " | " + ppCmd + " >" + fileNameOut; -#endif - ::system( cmd.ascii() ); - readFile( fileNameOut, true, bUpCase ); - FileAccess::removeFile( fileNameOut ); - } - else - { - readFile( m_fileAccess.absFilePath(), true, bUpCase ); - } - } - preprocess( bPreserveCR ); -} - -void SourceData::readFile( const QString& filename, bool bFollowLinks, bool bUpCase ) -{ - delete (char*)m_pBuf; - m_size = 0; - m_pBuf = 0; - char* pBuf = 0; - if ( filename.isEmpty() ) { return; } - - if ( !bFollowLinks ) - { - FileAccess fi( filename ); - if ( fi.isSymLink() ) - { - QString s = fi.readLink(); - m_size = s.length(); - m_pBuf = pBuf = new char[m_size+100]; - memcpy( pBuf, s.ascii(), m_size ); - return; - } - } - - - FileAccess fa( filename ); - m_size = fa.sizeForReading(); - m_pBuf = pBuf = new char[m_size+100]; - bool bSuccess = fa.readFile( pBuf, m_size ); - if ( !bSuccess ) - { - delete pBuf; - m_pBuf = 0; - m_size = 0; - return; - } - - - if ( bUpCase ) - { - int i; - for(i=0; i occurancesMap; - int i; - for( i=0; i0 ) { // Find the corresponding lineA - while( (*i3).lineA!=lineA ) + while( (*i3).lineA!=lineA ) ++i3; (*i3).lineC = lineC; (*i3).bAEqC = true; (*i3).bBEqC = (*i3).bAEqB; - + --d.nofEquals; ++lineA; ++lineC; @@ -655,7 +853,7 @@ } // Third step -void calcDiff3LineListUsingBC( +void calcDiff3LineListUsingBC( const DiffList* pDiffListBC, Diff3LineList& d3ll ) @@ -728,7 +926,7 @@ while( i3 != i3b && i3!=d3ll.end() ) { - if ( (*i3).lineB != -1 ) + if ( (*i3).lineB != -1 ) ++nofDisturbingLines; ++i3; } @@ -740,7 +938,7 @@ while( i3 != i3b ) { - if ( (*i3).lineB != -1 ) + if ( (*i3).lineB != -1 ) { Diff3Line d3l; d3l.lineB = (*i3).lineB; @@ -778,7 +976,7 @@ int nofDisturbingLines = 0; while( i3 != i3c && i3!=d3ll.end() ) { - if ( (*i3).lineC != -1 ) + if ( (*i3).lineC != -1 ) ++nofDisturbingLines; ++i3; } @@ -789,7 +987,7 @@ i3 = i3b; while( i3 != i3c ) { - if ( (*i3).lineC != -1 ) + if ( (*i3).lineC != -1 ) { Diff3Line d3l; d3l.lineC = (*i3).lineC; @@ -816,7 +1014,7 @@ } } } - + --d.nofEquals; ++lineB; ++lineC; @@ -861,8 +1059,8 @@ int li=0; for( ; it!=d3ll.end(); ++it, ++li ) { - printf( "%4d %4d %4d %4d A%c=B A%c=C B%c=C\n", - li, (*it).lineA, (*it).lineB, (*it).lineC, + printf( "%4d %4d %4d %4d A%c=B A%c=C B%c=C\n", + li, (*it).lineA, (*it).lineB, (*it).lineC, (*it).bAEqB ? '=' : '!', (*it).bAEqC ? '=' : '!', (*it).bBEqC ? '=' : '!' ); } printf("\n");*/ @@ -873,8 +1071,8 @@ #endif // Fourth step -void calcDiff3LineListTrim( - Diff3LineList& d3ll, LineData* pldA, LineData* pldB, LineData* pldC +void calcDiff3LineListTrim( + Diff3LineList& d3ll, const LineData* pldA, const LineData* pldB, const LineData* pldC ) { const Diff3Line d3l_empty; @@ -974,7 +1172,7 @@ (*i).lineA = (*i3).lineA; (*i).lineB = (*i3).lineB; (*i).bAEqB = true; - + (*i3).lineA = -1; (*i3).lineB = -1; (*i3).bAEqB = false; @@ -993,7 +1191,7 @@ (*i).lineA = (*i3).lineA; (*i).lineC = (*i3).lineC; (*i).bAEqC = true; - + (*i3).lineA = -1; (*i3).lineC = -1; (*i3).bAEqC = false; @@ -1012,7 +1210,7 @@ (*i).lineB = (*i3).lineB; (*i).lineC = (*i3).lineC; (*i).bBEqC = true; - + (*i3).lineB = -1; (*i3).lineC = -1; (*i3).bBEqC = false; @@ -1052,8 +1250,8 @@ int li=0; for( ; it!=d3ll.end(); ++it, ++li ) { - printf( "%4d %4d %4d %4d A%c=B A%c=C B%c=C\n", - li, (*it).lineA, (*it).lineB, (*it).lineC, + printf( "%4d %4d %4d %4d A%c=B A%c=C B%c=C\n", + li, (*it).lineA, (*it).lineB, (*it).lineC, (*it).bAEqB ? '=' : '!', (*it).bAEqC ? '=' : '!', (*it).bBEqC ? '=' : '!' ); } @@ -1061,7 +1259,7 @@ } void calcWhiteDiff3Lines( - Diff3LineList& d3ll, LineData* pldA, LineData* pldB, LineData* pldC + Diff3LineList& d3ll, const LineData* pldA, const LineData* pldB, const LineData* pldC ) { Diff3LineList::iterator i3 = d3ll.begin(); @@ -1294,8 +1492,8 @@ void fineDiff( Diff3LineList& diff3LineList, int selector, - LineData* v1, - LineData* v2, + const LineData* v1, + const LineData* v2, bool& bTextsTotalEqual ) { @@ -1325,9 +1523,21 @@ // Optimize the diff list. DiffList::iterator dli; + bool bUsefulFineDiff = false; for( dli = pDiffList->begin(); dli!=pDiffList->end(); ++dli) { - if( dli->nofEquals < 4 && (dli->diff1>0 || dli->diff2>0) ) + if( dli->nofEquals >= 4 ) + { + bUsefulFineDiff = true; + break; + } + } + + for( dli = pDiffList->begin(); dli!=pDiffList->end(); ++dli) + { + if( dli->nofEquals < 4 && (dli->diff1>0 || dli->diff2>0) + && !( bUsefulFineDiff && dli==pDiffList->begin() ) + ) { dli->diff1 += dli->nofEquals; dli->diff2 += dli->nofEquals; @@ -1365,7 +1575,7 @@ { d3lv[j] = &(*i); } - assert( j==(int)d3lv.size() ); + assert( j==(int)d3lv.size() ); } diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/diff.h --- a/kdiff3/src/diff.h Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/diff.h Sun Mar 07 09:59:09 2004 +0000 @@ -2,7 +2,7 @@ diff.h - description ------------------- begin : Mon Mar 18 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ @@ -28,7 +28,7 @@ #include "common.h" #include "fileaccess.h" - +class OptionDialog; // Each range with matching elements is followed by a range with differences on either side. // Then again range of matching elements should follow. @@ -123,47 +123,74 @@ int size; LineData(){ pLine=0; size=0; occurances=0; bContainsPureComment=false; } - int width(); // Calcs width considering tabs. + int width() const; // Calcs width considering tabs. int occurances; - bool whiteLine(){ return pFirstNonWhiteChar-pLine == size; } + bool whiteLine() const { return pFirstNonWhiteChar-pLine == size; } bool bContainsPureComment; }; -void prepareOccurances( LineData* p, int size ); - class SourceData { public: - SourceData(){ m_pBuf=0;m_size=0;m_vSize=0;m_bIsText=false;m_bPreserve=false; } - const char* m_pBuf; - int m_size; - int m_vSize; // Nr of lines in m_pBuf1 and size of m_v1, m_dv12 and m_dv13 - std::vector m_v; - bool m_bIsText; - bool m_bPreserve; - void reset(); - void readPPFile( bool bPreserveCR, const QString& ppCmd, bool bUpCase ); - void readLMPPFile( SourceData* pOrigSource, const QString& ppCmd, bool bUpCase, bool bRemoveComments ); - void readFile(const QString& filename, bool bFollowLinks, bool bUpCase ); - void preprocess(bool bPreserveCR ); - void removeComments( LineData* pLD ); - void setData( const QString& data, bool bUpCase ); + SourceData(); + ~SourceData(); + + void setOptionDialog( OptionDialog* pOptionDialog ); + + int getSizeLines() const; + int getSizeBytes() const; + const char* getBuf() const; + const LineData* getLineDataForDisplay() const; + const LineData* getLineDataForDiff() const; + void setFilename(const QString& filename); void setFileAccess( const FileAccess& fa ); FileAccess& getFileAccess(); QString getFilename(); void setAliasName(const QString& a); QString getAliasName(); - bool isEmpty() { return getFilename().isEmpty(); } -private: - QString m_fileName; + bool isEmpty(); // File was set + bool hasData(); // Data was readable + bool isText(); // is it pure text (vs. binary data) + bool isFromBuffer(); // was it set via setData() (vs. setFileAccess() or setFilename()) + void setData( const QString& data ); + + void readAndPreprocess(); + bool saveNormalDataAs( const QString& fileName ); + + bool isBinaryEqualWith( const SourceData& other ) const; + + void reset(); + +private: QString m_aliasName; FileAccess m_fileAccess; + OptionDialog* m_pOptionDialog; + QString m_tempInputFileName; + + struct FileData + { + FileData(){ m_pBuf=0; m_size=0; } + ~FileData(){ reset(); } + const char* m_pBuf; + int m_size; + int m_vSize; // Nr of lines in m_pBuf1 and size of m_v1, m_dv12 and m_dv13 + std::vector m_v; + bool m_bIsText; + bool readFile( const QString& filename ); + bool writeFile( const QString& filename ); + void preprocess(bool bPreserveCR ); + void reset(); + void removeComments(); + void copyBufFrom( const FileData& src ); + }; + FileData m_normalData; + FileData m_lmppData; }; -void calcDiff3LineListTrim( Diff3LineList& d3ll, LineData* pldA, LineData* pldB, LineData* pldC ); -void calcWhiteDiff3Lines( Diff3LineList& d3ll, LineData* pldA, LineData* pldB, LineData* pldC ); +void calcDiff3LineListTrim( Diff3LineList& d3ll, const LineData* pldA, const LineData* pldB, const LineData* pldC ); +void calcWhiteDiff3Lines( Diff3LineList& d3ll, const LineData* pldA, const LineData* pldB, const LineData* pldC ); void calcDiff3LineVector( const Diff3LineList& d3ll, Diff3LineVector& d3lv ); @@ -214,6 +241,7 @@ class OptionDialog; QString decodeString( const char*s , OptionDialog* ); +QCString encodeString( const QString& s , OptionDialog* ); class DiffTextWindow : public QWidget { @@ -226,7 +254,7 @@ ); void init( const QString& fileName, - LineData* pLineData, + const LineData* pLineData, int size, const Diff3LineVector* pDiff3LineVector, int winIdx, @@ -271,7 +299,7 @@ private: bool m_bPaintingAllowed; - LineData* m_pLineData; + const LineData* m_pLineData; int m_size; QString m_filename; @@ -438,6 +466,7 @@ void slotAutoSolve(); void slotUnsolve(); void slotSetFastSelectorLine(int); + void setPaintingAllowed(bool); signals: void scroll( int deltaX, int deltaY ); @@ -463,6 +492,8 @@ const Diff3LineList* m_pDiff3LineList; const TotalDiffStatus* m_pTotalDiffStatus; + bool m_bPaintingAllowed; + private: class MergeEditLine { @@ -496,19 +527,33 @@ private: typedef std::list BASE; int m_size; + int* m_pTotalSize; public: typedef std::list::iterator iterator; typedef std::list::const_iterator const_iterator; - MergeEditLineList(){m_size=0;} - void clear() { m_size=0; BASE::clear(); } - void push_back( const MergeEditLine& m) { ++m_size; BASE::push_back(m); } - void push_front( const MergeEditLine& m) { ++m_size; BASE::push_front(m); } - iterator erase( iterator i ) { --m_size; return BASE::erase(i); } - iterator insert( iterator i, const MergeEditLine& m ) { ++m_size; return BASE::insert(i,m); } + MergeEditLineList(){m_size=0; m_pTotalSize=0; } + void clear() { ds(-m_size); BASE::clear(); } + void push_back( const MergeEditLine& m) { ds(+1); BASE::push_back(m); } + void push_front( const MergeEditLine& m) { ds(+1); BASE::push_front(m); } + iterator erase( iterator i ) { ds(-1); return BASE::erase(i); } + iterator insert( iterator i, const MergeEditLine& m ) { ds(+1); return BASE::insert(i,m); } int size(){ /*assert(int(BASE::size())==m_size);*/ return m_size;} iterator begin(){return BASE::begin();} iterator end(){return BASE::end();} bool empty() { return m_size==0; } + + void setTotalSizePtr(int* pTotalSize) + { + m_pTotalSize = pTotalSize; + *m_pTotalSize += m_size; + } + + private: + void ds(int deltaSize) + { + m_size+=deltaSize; + if (m_pTotalSize!=0) *m_pTotalSize+=deltaSize; + } }; friend class MergeEditLine; @@ -569,6 +614,7 @@ int m_firstColumn; int m_nofColumns; int m_nofLines; + int m_totalSize; //Same as m_nofLines, but calculated differently bool m_bMyUpdate; bool m_bInsertMode; QString m_fileName; @@ -597,8 +643,8 @@ void fineDiff( Diff3LineList& diff3LineList, int selector, - LineData* v1, - LineData* v2, + const LineData* v1, + const LineData* v2, bool& bTextsTotalEqual ); diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/difftextwindow.cpp --- a/kdiff3/src/difftextwindow.cpp Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/difftextwindow.cpp Sun Mar 07 09:59:09 2004 +0000 @@ -2,7 +2,7 @@ difftextwindow.cpp - description ------------------- begin : Mon Apr 8 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ @@ -59,7 +59,7 @@ void DiffTextWindow::init( const QString& filename, - LineData* pLineData, + const LineData* pLineData, int size, const Diff3LineVector* pDiff3LineVector, int winIdx, @@ -862,7 +862,7 @@ if (lineIdx==-1) return QCString(); else { - LineData* ld = &m_pLineData[lineIdx]; + const LineData* ld = &m_pLineData[lineIdx]; return QCString( ld->pLine, ld->size + 1 ); } return QCString(); @@ -962,13 +962,15 @@ int spaces = 1; if ( pLine[i]=='\t' ) { - spaces = tabber( outPos, g_tabSize ); } if( selection.within( line, outPos ) ) { - selectionString += pLine[i]; + char buf[2]; + buf[0] = pLine[i]; + buf[1] = '\0'; + selectionString += decodeString( buf, m_pOptionDialog ); } outPos += spaces; @@ -983,8 +985,6 @@ } } - - ++line; } @@ -1041,3 +1041,17 @@ else return QString(s); } + +QCString encodeString( const QString& s , OptionDialog* pOptions ) +{ + if ( pOptions->m_bStringEncoding ) + { + QTextCodec* c = QTextCodec::codecForLocale(); + if (c!=0) + return c->fromUnicode( s ); + else + return QCString( s.ascii() ); + } + else + return QCString( s.ascii() ); +} diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/directorymergewindow.cpp --- a/kdiff3/src/directorymergewindow.cpp Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/directorymergewindow.cpp Sun Mar 07 09:59:09 2004 +0000 @@ -1,8 +1,8 @@ /*************************************************************************** directorymergewindow.cpp - ------------------- + ----------------- begin : Sat Oct 19 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ @@ -347,6 +347,15 @@ calcDirStatus( bThreeDirs, static_cast(p), nofFiles, nofDirs, nofEqualFiles, nofManualMerges ); } +static QString sortString(const QString& s) +{ +#ifdef _WIN32 + return s.upper(); +#else + return s; +#endif +} + bool DirectoryMergeWindow::init ( FileAccess& dirA, @@ -439,7 +448,7 @@ for (i=dirListA.begin(); i!=dirListA.end();++i ) { - MergeFileInfos& mfi = m_fileMergeMap[i->filePath()]; + MergeFileInfos& mfi = m_fileMergeMap[sortString(i->filePath())]; //std::cout <filePath()<filePath()]; + MergeFileInfos& mfi = m_fileMergeMap[sortString(i->filePath())]; mfi.m_bExistsInB = true; mfi.m_fileInfoB = *i; } @@ -483,7 +492,7 @@ for (i=dirListC.begin(); i!=dirListC.end();++i ) { - MergeFileInfos& mfi = m_fileMergeMap[i->filePath()]; + MergeFileInfos& mfi = m_fileMergeMap[sortString(i->filePath())]; mfi.m_bExistsInC = true; mfi.m_fileInfoC = *i; } @@ -949,7 +958,6 @@ t.start(); for( j=m_fileMergeMap.begin(); j!=m_fileMergeMap.end(); ++j ) { - const QString& fileName = j->first; MergeFileInfos& mfi = j->second; mfi.m_subPath = mfi.m_fileInfoA.exists() ? mfi.m_fileInfoA.filePath() : @@ -957,6 +965,9 @@ mfi.m_fileInfoC.exists() ? mfi.m_fileInfoC.filePath() : QString(""); + // const QString& fileName = j->first; + const QString& fileName = mfi.m_subPath; + g_pProgressDialog->setInformation( i18n("Processing ") + QString::number(currentIdx) +" / "+ QString::number(nrOfFiles) +"\n" + fileName, double(currentIdx) / nrOfFiles, false ); @@ -994,7 +1005,7 @@ } else { - MergeFileInfos& dirMfi = m_fileMergeMap[dirPart]; // parent + MergeFileInfos& dirMfi = m_fileMergeMap[sortString(dirPart)]; // parent assert(dirMfi.m_pDMI!=0); new DirMergeItem( dirMfi.m_pDMI, filePart, &mfi ); mfi.m_pParent = &dirMfi; diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/directorymergewindow.h --- a/kdiff3/src/directorymergewindow.h Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/directorymergewindow.h Sun Mar 07 09:59:09 2004 +0000 @@ -2,7 +2,7 @@ directorymergewindow.h ------------------- begin : Sat Oct 19 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/fileaccess.cpp --- a/kdiff3/src/fileaccess.cpp Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/fileaccess.cpp Sun Mar 07 09:59:09 2004 +0000 @@ -35,6 +35,7 @@ #ifdef _WIN32 #include #include +#include #else #include // Needed for creating symbolic links via symlink(). #include @@ -204,9 +205,11 @@ S_IXOTH 00001 others have execute permission */ +#ifdef KREPLACEMENTS_H +void FileAccess::setUdsEntry( const KIO::UDSEntry& ){} // not needed if KDE is not available +#else void FileAccess::setUdsEntry( const KIO::UDSEntry& e ) { -#ifndef KREPLACEMENTS_H KIO::UDSEntry::const_iterator ei; long acc = 0; long fileType = 0; @@ -262,8 +265,8 @@ m_name = m_path.mid( pos ); } m_bHidden = m_name[0]=='.'; +} #endif -} bool FileAccess::isValid() const { return m_bValidData; } @@ -342,7 +345,7 @@ return false; } -bool FileAccess::writeFile( void* pSrcBuffer, unsigned long length ) +bool FileAccess::writeFile( const void* pSrcBuffer, unsigned long length ) { if (m_bLocal) { @@ -424,7 +427,7 @@ for(int i=0; ;++i) { // short filenames for WIN98 because for system() the command must not exceed 120 characters. - fileName = tmpDir + "/" + QString::number(i); + fileName = tmpDir + "\\" + QString::number(i); if ( ! FileAccess::exists(fileName) ) break; } @@ -624,7 +627,7 @@ } } -bool FileAccessJobHandler::put(void* pSrcBuffer, long maxLength, bool bOverwrite, bool bResume, int permissions ) +bool FileAccessJobHandler::put(const void* pSrcBuffer, long maxLength, bool bOverwrite, bool bResume, int permissions ) { if ( maxLength>0 ) { @@ -1167,6 +1170,7 @@ m_bSuccess = QDir::setCurrent( m_pFileAccess->absFilePath() ); if ( m_bSuccess ) { +#ifndef _WIN32 m_bSuccess = true; QDir dir( "." ); @@ -1192,6 +1196,75 @@ pDirList->push_back( FileAccess( nicePath(*fi) ) ); } } +#else + QString pattern ="*.*"; + WIN32_FIND_DATA findData; + WIN32_FIND_DATAA& findDataA=*(WIN32_FIND_DATAA*)&findData; // Needed for Win95 + + HANDLE searchHandle = QT_WA_INLINE( + FindFirstFile( (TCHAR*)pattern.ucs2(), &findData ), + FindFirstFileA( pattern.local8Bit(), &findDataA ) + ); + + if ( searchHandle != INVALID_HANDLE_VALUE ) + { + QString absPath = m_pFileAccess->absFilePath(); + QString relPath = m_pFileAccess->filePath(); + bool bFirst=true; + while( ! g_pProgressDialog->wasCancelled() ) + { + if (!bFirst) + { + if ( ! QT_WA_INLINE( + FindNextFile(searchHandle,&findData), + FindNextFileA(searchHandle,&findDataA)) ) + break; + } + bFirst = false; + FileAccess fa; + fa.m_size = findData.nFileSizeLow ;//+ findData.nFileSizeHigh; + + FILETIME ft; + SYSTEMTIME t; + FileTimeToLocalFileTime( &findData.ftLastWriteTime, &ft ); FileTimeToSystemTime(&ft,&t); + fa.m_modificationTime = QDateTime( QDate(t.wYear, t.wMonth, t.wDay), QTime(t.wHour, t.wMinute, t.wSecond) ); + FileTimeToLocalFileTime( &findData.ftLastAccessTime, &ft ); FileTimeToSystemTime(&ft,&t); + fa.m_accessTime = QDateTime( QDate(t.wYear, t.wMonth, t.wDay), QTime(t.wHour, t.wMinute, t.wSecond) ); + FileTimeToLocalFileTime( &findData.ftCreationTime, &ft ); FileTimeToSystemTime(&ft,&t); + fa.m_creationTime = QDateTime( QDate(t.wYear, t.wMonth, t.wDay), QTime(t.wHour, t.wMinute, t.wSecond) ); + + int a = findData.dwFileAttributes; + fa.m_bWritable = ( a & FILE_ATTRIBUTE_READONLY) == 0; + fa.m_bDir = ( a & FILE_ATTRIBUTE_DIRECTORY ) != 0; + fa.m_bFile = !fa.m_bDir; + fa.m_bHidden = ( a & FILE_ATTRIBUTE_HIDDEN) != 0; + + fa.m_bExecutable = false; // Useless on windows + fa.m_bExists = true; + fa.m_bReadable = true; + fa.m_bLocal = true; + fa.m_bValidData = true; + fa.m_bSymLink = false; + fa.m_fileType = 0; + + fa.m_name = QT_WA_INLINE( + QString::fromUcs2(findData.cFileName), + QString::fromLocal8Bit(findDataA.cFileName) + ); + + fa.m_path = fa.m_name; + fa.m_absFilePath = absPath + "/" + fa.m_name; + fa.m_url.setPath( fa.m_absFilePath ); + if ( fa.m_name!="." && fa.m_name!=".." ) + pDirList->push_back( fa ); + } + FindClose( searchHandle ); + } + else + { + return false; + } +#endif } } else diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/fileaccess.h --- a/kdiff3/src/fileaccess.h Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/fileaccess.h Sun Mar 07 09:59:09 2004 +0000 @@ -57,7 +57,7 @@ bool isLocal() const; bool readFile(void* pDestBuffer, unsigned long maxLength ); - bool writeFile(void* pSrcBuffer, unsigned long length ); + bool writeFile(const void* pSrcBuffer, unsigned long length ); bool listDir( t_DirectoryList* pDirList, bool bRecursive, bool bFindHidden, const QString& filePattern, const QString& fileAntiPattern, const QString& dirAntiPattern, bool bFollowDirLinks, bool bUseCvsIgnore ); @@ -121,7 +121,7 @@ FileAccessJobHandler( FileAccess* pFileAccess ); bool get( void* pDestBuffer, long maxLength ); - bool put( void* pSrcBuffer, long maxLength, bool bOverwrite, bool bResume=false, int permissions=-1 ); + bool put( const void* pSrcBuffer, long maxLength, bool bOverwrite, bool bResume=false, int permissions=-1 ); bool stat(int detailLevel=2, bool bWantToWrite=false ); bool copyFile( const QString& dest ); bool rename( const QString& dest ); diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/kdiff3.cpp --- a/kdiff3/src/kdiff3.cpp Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/kdiff3.cpp Sun Mar 07 09:59:09 2004 +0000 @@ -2,7 +2,7 @@ kdiff3.cpp - description ------------------- begin : Don Jul 11 12:31:29 CEST 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ @@ -108,6 +108,16 @@ // Needed before any file operations via FileAccess happen. g_pProgressDialog = new ProgressDialog(this); + // All default values must be set before calling readOptions(). + m_pOptionDialog = new OptionDialog( m_pKDiff3Shell!=0, this ); + connect( m_pOptionDialog, SIGNAL(applyClicked()), this, SLOT(slotRefresh()) ); + + m_pOptionDialog->readOptions( isPart() ? m_pKDiff3Part->instance()->config() : kapp->config() ); + + m_sd1.setOptionDialog(m_pOptionDialog); + m_sd2.setOptionDialog(m_pOptionDialog); + m_sd3.setOptionDialog(m_pOptionDialog); + // Option handling: Only when pParent==0 (no parent) KCmdLineArgs *args = isPart() ? 0 : KCmdLineArgs::parsedArgs(); @@ -165,12 +175,8 @@ m_pFindDialog = new FindDialog( this ); connect( m_pFindDialog, SIGNAL(findNext()), this, SLOT(slotEditFindNext())); - // All default values must be set before calling readOptions(). - m_pOptionDialog = new OptionDialog( m_pKDiff3Shell!=0, this ); - connect( m_pOptionDialog, SIGNAL(applyClicked()), this, SLOT(slotRefresh()) ); - readOptions( isPart() ? m_pKDiff3Part->instance()->config() : kapp->config() ); - + autoAdvance->setChecked( m_pOptionDialog->m_bAutoAdvance ); showWhiteSpaceCharacters->setChecked( m_pOptionDialog->m_bShowWhiteSpaceCharacters ); showWhiteSpace->setChecked( m_pOptionDialog->m_bShowWhiteSpace ); @@ -230,35 +236,31 @@ init( m_bAuto ); if ( m_bAuto ) { - const char* pBuf = 0; - unsigned int size = 0; + SourceData* pSD=0; if ( m_sd3.isEmpty() ) { - if ( m_totalDiffStatus.bBinaryAEqB ){ pBuf=m_sd1.m_pBuf; size=m_sd1.m_size; } + if ( m_totalDiffStatus.bBinaryAEqB ){ pSD = &m_sd1; } } else { - if ( m_totalDiffStatus.bBinaryBEqC ){ pBuf=m_sd3.m_pBuf; size=m_sd3.m_size; } - else if ( m_totalDiffStatus.bBinaryAEqB ){ pBuf=m_sd3.m_pBuf; size=m_sd3.m_size; } - else if ( m_totalDiffStatus.bBinaryAEqC ){ pBuf=m_sd2.m_pBuf; size=m_sd2.m_size; } + if ( m_totalDiffStatus.bBinaryBEqC ){ pSD = &m_sd3; } // B==C (assume A is old) + else if ( m_totalDiffStatus.bBinaryAEqB ){ pSD = &m_sd3; } // assuming C has changed + else if ( m_totalDiffStatus.bBinaryAEqC ){ pSD = &m_sd2; } // assuming B has changed } - if ( pBuf!=0 ) + if ( pSD!=0 ) { // Save this file directly, not via the merge result window. bool bSuccess = false; - if ( m_pOptionDialog->m_bDmCreateBakFiles && QDir().exists( m_outputFilename ) ) + FileAccess fa( m_outputFilename ); + if ( m_pOptionDialog->m_bDmCreateBakFiles && fa.exists() ) { QString newName = m_outputFilename + ".orig"; - if ( QDir().exists( newName ) ) QFile::remove(newName); - if ( !QDir().exists( newName ) ) QDir().rename( m_outputFilename, newName ); + if ( FileAccess::exists( newName ) ) FileAccess::removeFile( newName ); + if ( !FileAccess::exists( newName ) ) fa.rename( newName ); } - QFile file( m_outputFilename ); - if ( file.open( IO_WriteOnly ) ) - { - bSuccess = (long)size == file.writeBlock ( pBuf, size ); - file.close(); - } + + bSuccess = pSD->saveNormalDataAs( m_outputFilename ); if ( bSuccess ) ::exit(0); else KMessageBox::error( this, i18n("Saving failed.") ); } @@ -280,17 +282,17 @@ if ( ! m_bDirCompare && m_pKDiff3Shell!=0 ) { bool bFileOpenError = false; - if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 || - ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 || - ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 ) + if ( ! m_sd1.isEmpty() && !m_sd1.hasData() || + ! m_sd2.isEmpty() && !m_sd2.hasData() || + ! m_sd3.isEmpty() && !m_sd3.hasData() ) { QString text( i18n("Opening of these files failed:") ); text += "\n\n"; - if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 ) + if ( ! m_sd1.isEmpty() && !m_sd1.hasData() ) text += " - " + m_sd1.getAliasName() + "\n"; - if ( ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 ) + if ( ! m_sd2.isEmpty() && !m_sd2.hasData() ) text += " - " + m_sd2.getAliasName() + "\n"; - if ( ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 ) + if ( ! m_sd3.isEmpty() && !m_sd3.hasData() ) text += " - " + m_sd3.getAliasName() + "\n"; KMessageBox::sorry( this, text, i18n("File Open Error") ); @@ -353,6 +355,7 @@ #include "xpm/iconC.xpm" #include "xpm/autoadvance.xpm" #include "xpm/showwhitespace.xpm" +#include "xpm/showwhitespacechars.xpm" #include "xpm/showlinenumbers.xpm" //#include "reload.xpm" @@ -370,8 +373,8 @@ chooseC = new KToggleAction(i18n("Select Line(s) From C"), QIconSet(QPixmap(iconC)), CTRL+Key_3, this, SLOT(slotChooseC()), ac, "merge_choose_c"); autoAdvance = new KToggleAction(i18n("Automatically Go to Next Unsolved Conflict After Source Selection"), QIconSet(QPixmap(autoadvance)), 0, this, SLOT(slotAutoAdvanceToggled()), ac, "merge_autoadvance"); - showWhiteSpaceCharacters = new KToggleAction(i18n("Show Space && Tabulator Characters for Differences"), QIconSet(QPixmap(showwhitespace)), 0, this, SLOT(slotShowWhiteSpaceToggled()), ac, "merge_show_whitespace_characters"); - showWhiteSpace = new KToggleAction(i18n("Show White Space"), 0, this, SLOT(slotShowWhiteSpaceToggled()), ac, "merge_show_whitespace"); + showWhiteSpaceCharacters = new KToggleAction(i18n("Show Space && Tabulator Characters for Differences"), QIconSet(QPixmap(showwhitespacechars)), 0, this, SLOT(slotShowWhiteSpaceToggled()), ac, "merge_show_whitespace_characters"); + showWhiteSpace = new KToggleAction(i18n("Show White Space"), QIconSet(QPixmap(showwhitespace)), 0, this, SLOT(slotShowWhiteSpaceToggled()), ac, "merge_show_whitespace"); showLineNumbers = new KToggleAction(i18n("Show Line Numbers"), QIconSet(QPixmap(showlinenumbers)), 0, this, SLOT(slotShowLineNumbersToggled()), ac, "merge_showlinenumbers"); chooseAEverywhere = new KAction(i18n("Choose A Everywhere"), CTRL+SHIFT+Key_1, this, SLOT(slotChooseAEverywhere()), ac, "merge_choose_a_everywhere"); @@ -467,7 +470,6 @@ m_pKDiff3Shell->move( pos ); } } - m_pOptionDialog->readOptions( config ); slotRefresh(); } diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/kdiff3.desktop --- a/kdiff3/src/kdiff3.desktop Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/kdiff3.desktop Sun Mar 07 09:59:09 2004 +0000 @@ -2,17 +2,25 @@ [Desktop Entry] Encoding=UTF-8 Name=KDiff3 +Name[hi]=के-डिफ3 Name[sv]=Kdiff3 +Name[ta]=கேடிஃப்3 Name[xx]=xxKDiff3xx GenericName=Diff/Patch Frontend GenericName[da]=Forende for diff/patch GenericName[es]=Interfaz Diff/Patch -GenericName[hu]=grafikus diff/patch-felület +GenericName[et]=Võrdlemise ja liitmise rakendus +GenericName[fr]=Interface graphique à diff / patch +GenericName[hu]=Grafikus diff/patch GenericName[it]=Interfaccia per diff/patch -GenericName[pt]=Interface para o Diff/Patch -GenericName[pt_BR]=Interface para o Diff/Patch +GenericName[nl]=Een schil voor Diff/Patch +GenericName[pt]=Interface do Diff/Patch +GenericName[pt_BR]=Um front-end para Diff/Patch +GenericName[ru]=Графический интерфейс к Diff и Patch GenericName[sr]=Интерфејс за Diff и Patch GenericName[sv]=Jämförelse- och programfixgränssnitt +GenericName[ta]= ஒரு கேடியி முன்முனையில் இருந்து எஸ்எம்எஸ்அனுப்பு +GenericName[zh_CN]=Diff/Patch 前端 GenericName[zu]=Diff/PatchIsiqalo sokugcina Exec=kdiff3 %i %m -caption "%c" Icon=kdiff3 @@ -22,14 +30,19 @@ Comment[ca]=Una eina per a comparar i fusionar fitxers o directoris Comment[da]=Et indfletningsværktøj for filer og mapper Comment[de]=Programm zum Vergleichen und Zusammenfhren von Dateien und Verzeichnissen +Comment[el]=Ένα εργαλείο σύγκρισης και συγχώνευσης αρχείων και καταλόγων Comment[es]=Una herramienta para mezclar y comparar archivos y directorios Comment[et]=Failide ja kataloogide võrdlemise ja liitmise vahend +Comment[fr]=Un outil de comparaison et de fusion de fichiers et dossiers +Comment[hi]=एक फाइल तथा डिरेक्ट्री तुलना तथा विलीन उपकरण Comment[hu]=Segédprogram fájlok, könyvtárak összehasonlításához Comment[it]=Uno strumento di confronto e unione di file e directory Comment[nl]=Hulpmiddel voor het vergelijken en samenvoegen van bestanden en mappen Comment[pt]=Uma Ferramenta de Comparação e Junção de Ficheiros e Pastas Comment[pt_BR]=Uma Comparação de Arquivos e Pastas e uma Ferramenta para Mesclar Diferenças +Comment[ru]=Утилита сравнения и объединения файлов и каталогов Comment[sr]=Алат за поређење и стапање фајлова и директоријума Comment[sv]=Ett jämförelseverktyg för fil- och katalogjämförelser Comment[xx]=xxA File And Directory Comparison And Merge Toolxx +Comment[zh_CN]=一个文件和目录的比较及合并工具 Terminal=0 diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/kdiff3.h --- a/kdiff3/src/kdiff3.h Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/kdiff3.h Sun Mar 07 09:59:09 2004 +0000 @@ -2,7 +2,7 @@ kdiff3.h - description ------------------- begin : Don Jul 11 12:31:29 CEST 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ @@ -220,10 +220,6 @@ SourceData m_sd2; SourceData m_sd3; - SourceData m_sdlm1; // SourceData for Line Matching only. - SourceData m_sdlm2; - SourceData m_sdlm3; - QString m_outputFilename; bool m_bDefaultFilename; @@ -250,7 +246,7 @@ bool improveFilenames(); - bool runDiff( LineData* p1, int size1, LineData* p2, int size2, DiffList& diffList ); + bool runDiff( const LineData* p1, int size1, const LineData* p2, int size2, DiffList& diffList ); bool canContinue(); void choose(int choice); @@ -340,9 +336,11 @@ QCheckBox* m_pMerge; virtual void accept(); + virtual bool eventFilter(QObject* o, QEvent* e); private: OptionDialog* m_pOptions; void selectURL( QComboBox* pLine, bool bDir, int i, bool bSave ); + bool m_bInputFileNameChanged; private slots: void selectFileA(); void selectFileB(); @@ -353,6 +351,7 @@ void selectOutputName(); void selectOutputDir(); void internalSlot(int); + void inputFilenameChanged(); signals: void internalSignal(bool); }; diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/kdiff3.pro --- a/kdiff3/src/kdiff3.pro Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/kdiff3.pro Sun Mar 07 09:59:09 2004 +0000 @@ -11,7 +11,7 @@ win32 { QMAKE_CXXFLAGS_DEBUG -= -Zi - QMAKE_CXXFLAGS_DEBUG += -GX -GR -Z7 + QMAKE_CXXFLAGS_DEBUG += -GX -GR -Z7 /FR QMAKE_LFLAGS_DEBUG += /PDB:NONE QMAKE_CXXFLAGS_RELEASE += -GX -GR -DNDEBUG RC_FILE = kdiff3.rc diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/kdiff3_shell.rc --- a/kdiff3/src/kdiff3_shell.rc Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/kdiff3_shell.rc Sun Mar 07 09:59:09 2004 +0000 @@ -94,6 +94,7 @@ + diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/kdiff3part.desktop --- a/kdiff3/src/kdiff3part.desktop Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/kdiff3part.desktop Sun Mar 07 09:59:09 2004 +0000 @@ -1,9 +1,12 @@ [Desktop Entry] Encoding=UTF-8 Name=KDiff3Part +Name[hi]=के-डिफ3पार्ट Name[pt_BR]=Componente KDiff3 Name[sv]=Kdiff3-del +Name[ta]=கேடிஃப்3 பகுதி Name[xx]=xxKDiff3Partxx +Name[zh_CN]=KDiff3 组件 MimeType=text/x-diff ServiceTypes=KParts/ReadOnlyPart,KParts/ReadWritePart X-KDE-Library=libkdiff3part diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/kreplacements/kreplacements.cpp --- a/kdiff3/src/kreplacements/kreplacements.cpp Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/kreplacements/kreplacements.cpp Sun Mar 07 09:59:09 2004 +0000 @@ -141,7 +141,7 @@ int KMessageBox::warningYesNo( QWidget* parent, const QString& text, const QString& caption, const QString& button1, const QString& button2 ) { - return 0 == QMessageBox::warning( parent, caption, text, button1, button2 ) ? Yes : No; + return 0 == QMessageBox::warning( parent, caption, text, button1, button2, QString::null, 1, 1 ) ? Yes : No; } int KMessageBox::warningYesNoCancel( QWidget* parent, const QString& text, const QString& caption, @@ -419,6 +419,65 @@ { } +// safeStringJoin and safeStringSplit allow to convert a stringlist into a string and back +// safely, even if the individual strings in the list contain the separator character. +static QString safeStringJoin(const QStringList& sl, char sepChar=',', char metaChar='\\' ) +{ + // Join the strings in the list, using the separator ',' + // If a string contains the separator character, it will be replaced with "\,". + // Any occurances of "\" (one backslash) will be replaced with "\\" (2 backslashes) + + assert(sepChar!=metaChar); + + QString sep; + sep += sepChar; + QString meta; + meta += metaChar; + + QString safeString; + + QStringList::const_iterator i; + for (i=sl.begin(); i!=sl.end(); ++i) + { + QString s = *i; + s.replace(meta, meta+meta); // "\" -> "\\" + s.replace(sep, meta+sep); // "," -> "\," + if ( i==sl.begin() ) + safeString = s; + else + safeString += sep + s; + } + return safeString; +} + +// Split a string that was joined with safeStringJoin +static QStringList safeStringSplit(const QString& s, char sepChar=',', char metaChar='\\' ) +{ + assert(sepChar!=metaChar); + QStringList sl; + // Miniparser + int i=0; + int len=s.length(); + QString b; + for(i=0;i::iterator i = m_map.find( k ); if ( i!=m_map.end() ) { - QString s = i->second; - int idx=0; - for(;;) - { - QString sec = subSection( s, idx, '|' ); //s.section('|',idx,idx); - if ( sec.isEmpty() ) - break; - else - strList.append(sec); - ++idx; - } + strList = safeStringSplit( i->second, separator ); } return strList; } @@ -1042,7 +1080,7 @@ QString KCmdLineArgs::arg(int idx) { - return QString(s_vArg[idx]); + return QString::fromLocal8Bit( s_vArg[idx] ); } void KCmdLineArgs::clear() @@ -1155,21 +1193,27 @@ } if (j==nofOptions) { - using std::cerr; - using std::endl; - cerr << "Unknown option: " << s_argv[i] << endl< #include #include +#include int g_bAutoSolve = true; @@ -45,6 +46,7 @@ m_firstColumn = 0; m_nofColumns = 0; m_nofLines = 0; + m_totalSize = 0; m_bMyUpdate = false; m_bInsertMode = true; m_scrollDeltaX = 0; @@ -58,8 +60,9 @@ m_pDiff3LineList = 0; m_pTotalDiffStatus = 0; - + m_pOptionDialog = pOptionDialog; + m_bPaintingAllowed = false; m_cursorXPos=0; m_cursorOldXPos=0; @@ -255,6 +258,7 @@ } m_mergeLineList.clear(); + m_totalSize = 0; int lineIdx = 0; Diff3LineList::const_iterator it; for( it=m_pDiff3LineList->begin(); it!=m_pDiff3LineList->end(); ++it, ++lineIdx ) @@ -302,6 +306,7 @@ back->bConflict = false; } } + ml.mergeEditLineList.setTotalSizePtr(&m_totalSize); m_mergeLineList.push_back( ml ); } @@ -393,7 +398,6 @@ melsrc==3 ? mel.id3l()->lineC : -1; if ( srcLine == -1 && oldSrcLine==-1 && oldSrc == melsrc ) - melIt = ml.mergeEditLineList.erase( melIt ); else ++melIt; @@ -434,7 +438,7 @@ int MergeResultWindow::getNofLines() { - return m_nofLines; + return m_totalSize; } int MergeResultWindow::getNofVisibleColumns() @@ -791,6 +795,12 @@ ml.mergeEditLineList.push_back(mel); } + + if ( m_cursorYPos >= m_totalSize ) + { + m_cursorYPos = m_totalSize-1; + m_cursorXPos = 0; + } update(); emit updateAvailabilities(); @@ -1056,9 +1066,14 @@ } } +void MergeResultWindow::setPaintingAllowed(bool bPaintingAllowed) +{ + m_bPaintingAllowed = bPaintingAllowed; +} + void MergeResultWindow::paintEvent( QPaintEvent* e ) { - if (m_pDiff3LineList==0) return; + if (m_pDiff3LineList==0 || !m_bPaintingAllowed) return; bool bOldSelectionContainsData = m_selection.bSelectionContainsData; const QFontMetrics& fm = fontMetrics(); @@ -1079,9 +1094,7 @@ //int visibleLines = height() / fontHeight; { // Draw the topline - QString s; - s.sprintf(" Output : %s ", m_fileName.ascii() ); - // s.sprintf(" Output : %s : Line %d",(const char*) m_fileName, m_firstLine+1 ); + QString s = " " +i18n("Output") + " : " + m_fileName + " "; if (m_bModified) s += i18n("[Modified]"); @@ -1145,6 +1158,7 @@ if ( line != m_nofLines || nofColumns != m_nofColumns ) { m_nofLines = line; + assert( m_nofLines == m_totalSize ); m_nofColumns = nofColumns; emit resizeSignal(); @@ -1223,7 +1237,7 @@ int yOffset = topLineYOffset - m_firstLine * fontHeight; - line = min2( ( y - yOffset ) / fontHeight, m_nofLines-1 ); + line = min2( ( y - yOffset ) / fontHeight, m_totalSize-1 ); pos = ( x - xOffset ) / fontWidth; } @@ -1438,7 +1452,7 @@ if( !melIt->isEditableText() ) break; if (x>=stringLength) { - if ( ystringLength && ystringLength && ysetString( s ); x += t.length(); @@ -1632,7 +1646,7 @@ } } - y = minMaxLimiter( y, 0, m_nofLines-1 ); + y = minMaxLimiter( y, 0, m_totalSize-1 ); calcIteratorFromLineNr( y, mlIt, melIt ); ps = melIt->getString( this, stringLength ); @@ -1744,7 +1758,10 @@ if( m_selection.within( line, outPos ) ) { - selectionString += pLine[i]; + char buf[2]; + buf[0] = pLine[i]; + buf[1] = '\0'; + selectionString += decodeString( buf, m_pOptionDialog ); } outPos += spaces; @@ -1752,7 +1769,7 @@ } else if ( mel.isConflict() ) { - selectionString += ""; + selectionString += i18n(""); } if( m_selection.within( line, outPos ) ) @@ -1866,9 +1883,9 @@ { // Remove the line if ( mlIt->mergeEditLineList.size()>1 ) - { mlIt->mergeEditLineList.erase( melIt ); --m_nofLines; } + mlIt->mergeEditLineList.erase( melIt ); else - { melIt->setRemoved(); } + melIt->setRemoved(); } } @@ -1901,15 +1918,14 @@ const char* ps = melIt->getString( this, stringLength ); int x = convertToPosInText( ps, stringLength, m_cursorXPos ); - QString clipBoard = QApplication::clipboard()->text(); + QCString clipBoard = encodeString( QApplication::clipboard()->text(), m_pOptionDialog ); QCString currentLine = QCString( ps, x+1 ); QCString endOfLine = QCString( ps+x, stringLength-x+1 ); int i; for( i=0; i<(int)clipBoard.length(); ++i ) { - QChar uc = clipBoard[i]; - char c = uc; + char c = clipBoard[i]; if ( c == '\r' ) continue; if ( c == '\n' ) { @@ -2015,11 +2031,10 @@ if (line>0) // Prepend line feed, but not for first line { - #ifdef _WIN32 - s.prepend("\r\n"); size+=2; - #else - s.prepend("\n"); size+=1; - #endif + if ( m_pOptionDialog->m_lineEndStyle == eLineEndDos ) + { s.prepend("\r\n"); size+=2; } + else + { s.prepend("\n"); size+=1; } } if (i==0) neededBufferSize += size; @@ -2093,7 +2108,6 @@ update(); } - Overview::Overview( QWidget* pParent, OptionDialog* pOptions ) : QWidget( pParent, 0, WRepaintNoErase ) { diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/optiondialog.cpp --- a/kdiff3/src/optiondialog.cpp Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/optiondialog.cpp Sun Mar 07 09:59:09 2004 +0000 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,7 @@ #include #include //#include +#include #include "optiondialog.h" #include "diff.h" @@ -126,25 +128,42 @@ QColor m_defaultVal; }; -class OptionLineEdit : public QLineEdit, public OptionItem +class OptionLineEdit : public QComboBox, public OptionItem { public: OptionLineEdit( const QString& defaultVal, const QString& saveName, QString* pVar, QWidget* pParent, OptionDialog* pOD ) - : QLineEdit( pParent ), OptionItem( pOD, saveName ) + : QComboBox( pParent ), OptionItem( pOD, saveName ) { m_pVar = pVar; m_defaultVal = defaultVal; + m_list.push_back(defaultVal); + setEditable(true); } - void setToDefault(){ setText( m_defaultVal ); } - void setToCurrent(){ setText( *m_pVar ); } - void apply() { *m_pVar = text(); } - void write(KConfig* config){ config->writeEntry(m_saveName, *m_pVar ); } - void read (KConfig* config){ *m_pVar = config->readEntry( m_saveName, *m_pVar ); } + void setToDefault(){ setCurrentText( m_defaultVal ); } + void setToCurrent(){ setCurrentText( *m_pVar ); } + void apply() { *m_pVar = currentText(); insertText(); } + void write(KConfig* config){ config->writeEntry( m_saveName, m_list, '|' ); } + void read (KConfig* config){ + m_list = config->readListEntry( m_saveName, '|' ); + if ( !m_list.isEmpty() ) *m_pVar = m_list.front(); + clear(); + insertStringList(m_list); + } private: + void insertText() + { // Check if the text exists. If yes remove it and + QString current = currentText(); + m_list.remove( current ); + m_list.push_front( current ); + clear(); + if ( m_list.count()>10 ) m_list.erase( m_list.at(10), m_list.end() ); + insertStringList(m_list); + } OptionLineEdit( const OptionLineEdit& ); // private copy constructor without implementation QString* m_pVar; QString m_defaultVal; + QStringList m_list; }; #if defined QT_NO_VALIDATOR @@ -179,23 +198,69 @@ class OptionComboBox : public QComboBox, public OptionItem { public: - OptionComboBox( int defaultVal, const QString& saveName, int* pVar, + OptionComboBox( int defaultVal, const QString& saveName, int* pVarNum, QWidget* pParent, OptionDialog* pOD ) : QComboBox( pParent ), OptionItem( pOD, saveName ) { - m_pVar = pVar; + m_pVarNum = pVarNum; + m_pVarStr = 0; m_defaultVal = defaultVal; setEditable(false); } - void setToDefault(){ setCurrentItem( m_defaultVal ); } - void setToCurrent(){ setCurrentItem( *m_pVar ); } - void apply() { *m_pVar = currentItem(); } - void write(KConfig* config){ config->writeEntry(m_saveName, *m_pVar ); } - void read (KConfig* config){ *m_pVar = config->readNumEntry( m_saveName, *m_pVar ); } + OptionComboBox( int defaultVal, const QString& saveName, QString* pVarStr, + QWidget* pParent, OptionDialog* pOD ) + : QComboBox( pParent ), OptionItem( pOD, saveName ) + { + m_pVarNum = 0; + m_pVarStr = pVarStr; + m_defaultVal = defaultVal; + setEditable(false); + } + void setToDefault() + { + setCurrentItem( m_defaultVal ); + if (m_pVarStr!=0){ *m_pVarStr=currentText(); } + } + void setToCurrent() + { + if (m_pVarNum!=0) setCurrentItem( *m_pVarNum ); + else setText( *m_pVarStr ); + } + void apply() + { + if (m_pVarNum!=0){ *m_pVarNum = currentItem(); } + else { *m_pVarStr = currentText(); } + } + void write(KConfig* config) + { + if (m_pVarStr!=0) config->writeEntry(m_saveName, *m_pVarStr ); + else config->writeEntry(m_saveName, *m_pVarNum ); + } + void read (KConfig* config) + { + if (m_pVarStr!=0) setText( config->readEntry( m_saveName, currentText() ) ); + else *m_pVarNum = config->readNumEntry( m_saveName, *m_pVarNum ); + } private: OptionComboBox( const OptionIntEdit& ); // private copy constructor without implementation - int* m_pVar; + int* m_pVarNum; + QString* m_pVarStr; int m_defaultVal; + + void setText(const QString& s) + { + // Find the string in the combobox-list, don't change the value if nothing fits. + for( int i=0; iaddWidget( label, line, 0 ); + #ifdef _WIN32 + int defaultLineEndStyle = eLineEndDos; + #else + int defaultLineEndStyle = eLineEndUnix; + #endif + OptionComboBox* pLineEndStyle = new OptionComboBox( defaultLineEndStyle, "LineEndStyle", &m_lineEndStyle, page, this ); + gbox->addWidget( pLineEndStyle, line, 1 ); + pLineEndStyle->insertItem( "Unix", eLineEndUnix ); + pLineEndStyle->insertItem( "Dos/Windows", eLineEndDos ); + QToolTip::add( label, i18n( + "Sets the line endings for when a edited file is saved.\n" + "DOS/Windows: CR+LF; Unix: LF; with CR=0D, LF=0A") + ); + ++line; + OptionCheckBox* pStringEncoding = new OptionCheckBox( i18n("Use locale encoding"), true, "LocaleEncoding", &m_bStringEncoding, page, this ); gbox->addMultiCellWidget( pStringEncoding, line, line, 0, 1 ); QToolTip::add( pStringEncoding, i18n( @@ -464,7 +549,7 @@ pWhiteSpace2FileMergeDefault->insertItem( i18n("Manual choice"), 0 ); pWhiteSpace2FileMergeDefault->insertItem( "A", 1 ); pWhiteSpace2FileMergeDefault->insertItem( "B", 2 ); - QToolTip::add( pWhiteSpace2FileMergeDefault, i18n( + QToolTip::add( label, i18n( "Allow the merge algorithm to automatically select an input for " "white-space-only changes." ) ); @@ -478,7 +563,7 @@ pWhiteSpace3FileMergeDefault->insertItem( "A", 1 ); pWhiteSpace3FileMergeDefault->insertItem( "B", 2 ); pWhiteSpace3FileMergeDefault->insertItem( "C", 3 ); - QToolTip::add( pWhiteSpace3FileMergeDefault, i18n( + QToolTip::add( label, i18n( "Allow the merge algorithm to automatically select an input for " "white-space-only changes." ) ); @@ -612,6 +697,63 @@ topLayout->addStretch(10); } +static void insertCodecs(OptionComboBox* p) +{ + std::multimap m; // Using the multimap for case-insensitive sorting. + int i; + for(i=0;;++i) + { + QTextCodec* pCodec = QTextCodec::codecForIndex ( i ); + if ( pCodec != 0 ) m.insert( std::make_pair( QString(pCodec->mimeName()).upper(), pCodec->mimeName()) ); + else break; + } + + p->insertItem( i18n("Auto"), 0 ); + std::multimap::iterator mi; + for(mi=m.begin(), i=0; mi!=m.end(); ++mi, ++i) + p->insertItem(mi->second, i+1); +} + +void OptionDialog::setupRegionalPage( void ) +{ + QFrame *page = addPage( i18n("Regional Settings"), i18n("Regional Settings"), + BarIcon("locale"/*"charset"*/, KIcon::SizeMedium ) ); + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + + QGridLayout *gbox = new QGridLayout( 3, 2 ); + topLayout->addLayout( gbox ); + int line=0; + + QLabel* label; +#ifdef KREPLACEMENTS_H + label = new QLabel( i18n("Language (restart required)"), page ); + gbox->addWidget( label, line, 0 ); + OptionComboBox* pLanguage = new OptionComboBox( 0, "Language", &m_language, page, this ); + gbox->addWidget( pLanguage, line, 1 ); + pLanguage->insertItem( i18n("Auto"), 0 ); + // Read directory: Find all kdiff3_*.qm-files and insert the found files here selection + QToolTip::add( label, i18n( + "Choose the language of the GUI-strings or \"Auto\".\n" + "For a change of language to take place, quit and restart KDiff3.") + ); + ++line; +#endif + + label = new QLabel( i18n("Codec for file contents"), page ); + gbox->addWidget( label, line, 0 ); + OptionComboBox* pFileCodec = new OptionComboBox( 0, "FileCodec", &m_fileCodec, page, this ); + gbox->addWidget( pFileCodec, line, 1 ); + insertCodecs( pFileCodec ); + QToolTip::add( label, i18n( + "Choose the codec that should be used for your input files\n" + "or \"Auto\" if unsure." ) + ); + ++line; + + topLayout->addStretch(10); +} + + void OptionDialog::setupKeysPage( void ) { //QVBox *page = addVBoxPage( i18n("Keys"), i18n("KeyDialog" ), @@ -753,4 +895,5 @@ } + #include "optiondialog.moc" diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/optiondialog.h --- a/kdiff3/src/optiondialog.h Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/optiondialog.h Sun Mar 07 09:59:09 2004 +0000 @@ -35,6 +35,11 @@ class OptionItem; class KKeyDialog; +enum eLineEndStyle +{ + eLineEndUnix=0, + eLineEndDos +}; class OptionDialog : public KDialogBase { @@ -64,6 +69,7 @@ int m_tabSize; bool m_bAutoCopySelection; bool m_bStringEncoding; + int m_lineEndStyle; bool m_bPreserveCarriageReturn; bool m_bTryHard; @@ -105,6 +111,9 @@ QString m_DmFileAntiPattern; QString m_DmDirAntiPattern; + QString m_language; + QString m_fileCodec; + void saveOptions(KConfig* config); void readOptions(KConfig* config); @@ -133,11 +142,13 @@ void setupDiffPage(); void setupDirectoryMergePage(); void setupKeysPage(); + void setupRegionalPage(); void setupOtherOptions(); }; + #endif diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/pdiff.cpp --- a/kdiff3/src/pdiff.cpp Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/pdiff.cpp Sun Mar 07 09:59:09 2004 +0000 @@ -1,8 +1,8 @@ /*************************************************************************** - kdiff.cpp - description - ------------------- + pdiff.cpp - Implementation for class KDiff3App + --------------- begin : Mon Mr 18 20:04:50 CET 2002 - copyright : (C) 2002 by Joachim Eibl + copyright : (C) 2002-2004 by Joachim Eibl email : joachim.eibl@gmx.de ***************************************************************************/ @@ -99,7 +99,7 @@ return fileName; } -bool KDiff3App::runDiff( LineData* p1, int size1, LineData* p2, int size2, DiffList& diffList ) +bool KDiff3App::runDiff( const LineData* p1, int size1, const LineData* p2, int size2, DiffList& diffList ) { static GnuDiff gnuDiff; @@ -164,8 +164,11 @@ if (size1-currentLine1==size2-currentLine2 ) { - Diff d( size1-currentLine1,0,0); - diffList.push_back(d); + if (size1-currentLine1>0) + { + Diff d( size1-currentLine1,0,0); + diffList.push_back(d); + } } else if ( !diffList.empty() ) { // Only necessary for a files that end with a newline @@ -204,209 +207,6 @@ g_pProgressDialog->setSubCurrent(1.0); return true; -#if 0 - - if ( m_pOptionDialog->m_bUseExternalDiff ) - { - bool bSuccess=false; - - bool bIgnoreWhiteSpace = m_pOptionDialog->m_bIgnoreWhiteSpace; - bool bIgnoreNumbers = m_pOptionDialog->m_bIgnoreNumbers; - - // Create two temp files (Remove all white spaces and carriage returns here) - // (Make sure that no existing files are overwritten.) - g_pProgressDialog->setSubCurrent(0); - QString fileName1 = createTempFile( p1, size1, bIgnoreWhiteSpace, bIgnoreNumbers ); - g_pProgressDialog->setSubCurrent(0.25); - QString fileName2 = createTempFile( p2, size2, bIgnoreWhiteSpace, bIgnoreNumbers ); - g_pProgressDialog->setSubCurrent(0.5); - QString fileNameOut = FileAccess::tempFileName(); - - if ( !fileName1.isEmpty() && !fileName2.isEmpty() ) - { - QString cmd; -#ifdef _WIN32 - // Under Windows it's better to search for diff.exe - char buf[200]; - int r= SearchPathA( 0, "diff.exe", 0, sizeof(buf), buf, 0 ); - - if (r!=0) { cmd = buf; } -#else - // under Un*x I assume that a diff command is in the PATH - cmd = "diff"; -#endif - if ( !cmd.isEmpty() ) - { - cmd += " -a "; // -a = treat all files as text - if ( m_pOptionDialog->m_bTryHard ) - cmd += "--minimal "; - //if ( m_pOptionDialog->m_bIgnoreWhiteSpace ) This I do myself, see below - // cmd += "--ignore-all-space "; - cmd += fileName1+" "+fileName2+" >"+fileNameOut; - // Run diff - //int status1 = ::system( 0 ); // ==0 if shell not found - int status = ::system( cmd.ascii() ); -#ifdef WEXITSTATUS - status = WEXITSTATUS(status); -#endif - //if (status<0) - //{ - // errorString = strerror( errno ); - //} - bSuccess = status>=0 && status!=127; - } - } - - g_pProgressDialog->setSubCurrent(0.75); - - int currentLine1 = 0; - int currentLine2 = 0; - if ( bSuccess ) - { - // Parse the output and create the difflist - QFile f( fileNameOut ); - bSuccess = f.open(IO_ReadOnly); - if (bSuccess) - { - const QByteArray buf = f.readAll(); - unsigned int bufSize=buf.size(); - unsigned int pos=0; - for(pos=0;pos' || c == '-' || c=='<' ) - continue; // Not interested in the data - else - { - QCString line( &buf.at(lineStart), pos-lineStart+1 ); - int pa = line.find('a'); // add - int pc = line.find('c'); // change - int pd = line.find('d'); // delete - int p = pa>0 ? pa : (pc > 0 ? pc : pd); - if (p<0) break; // Unexpected error - QCString left = line.left(p); - QCString right = line.mid(p+1); - int pcommaleft = left.find(','); - int pcommaright = right.find(','); - int l1top=-1, l1bottom=-1, l2top=-1, l2bottom=-1; - if (pcommaleft>0) - { - l1top = left.left(pcommaleft).toInt(); - l1bottom = left.mid(pcommaleft+1).toInt(); - } - else - { - l1top = left.toInt(); - l1bottom = l1top; - } - if (pcommaright>0) - { - l2top = right.left(pcommaright).toInt(); - l2bottom = right.mid(pcommaright+1).toInt(); - } - else - { - l2top = right.toInt(); - l2bottom = l2top; - } - - Diff d(0,0,0); - - if ( pa>0 ) - { - d.nofEquals = l1top - currentLine1; - d.diff1 = 0; - d.diff2 = l2bottom - l2top + 1; - assert( d.nofEquals == l2top - 1 - currentLine2 ); - } - else if ( pd>0 ) - { - d.nofEquals = l2top - currentLine2; - d.diff1 = l1bottom - l1top + 1; - d.diff2 = 0; - assert( d.nofEquals == l1top - 1 - currentLine1 ); - } - else if ( pc>0 ) - { - d.nofEquals = l1top - 1 - currentLine1; - d.diff1 = l1bottom - l1top + 1; - d.diff2 = l2bottom - l2top + 1; - assert( d.nofEquals == l2top - 1 - currentLine2 ); - } - else - assert(false); - - currentLine1 += d.nofEquals + d.diff1; - currentLine2 += d.nofEquals + d.diff2; - diffList.push_back(d); - } - } - if (size1-currentLine1==size2-currentLine2 ) - { - Diff d( size1-currentLine1,0,0); - diffList.push_back(d); - currentLine1=size1; - currentLine2=size2; - } - - if ( currentLine1 == size1 && currentLine2 == size2 ) - bSuccess = true; - } - else - { - bSuccess = size1==size2; - } - } - if ( currentLine1==0 && currentLine2==0 ) - { - Diff d( 0, size1, size2 ); - diffList.push_back(d); - } - - g_pProgressDialog->setSubCurrent(1.0); - - if ( !bSuccess ) - { - KMessageBox::sorry(this, - i18n("Running the external diff failed.\n" - "Check if the diff works, if the program can write in the temp folder or if the disk is full.\n" - "The external diff option will be disabled now and the internal diff will be used."), - i18n("Warning")); - m_pOptionDialog->m_bUseExternalDiff = false; - } - - FileAccess::removeFile( fileName1 ); - FileAccess::removeFile( fileName2 ); - FileAccess::removeFile( fileNameOut ); - } - - if ( ! m_pOptionDialog->m_bUseExternalDiff ) - { - g_pProgressDialog->setSubCurrent(0.0); - if ( size1>0 && p1!=0 && p1->occurances==0 ) - { - prepareOccurances( p1, size1 ); - } - g_pProgressDialog->setSubCurrent(0.25); - - if ( size2>0 && p2!=0 && p2->occurances==0 ) - { - prepareOccurances( p2, size2 ); - } - g_pProgressDialog->setSubCurrent(0.5); - - calcDiff( p1, size1, p2, size2, diffList, 2, m_pOptionDialog->m_maxSearchLength ); - - g_pProgressDialog->setSubCurrent(1.0); - } - return true; -#endif } @@ -418,18 +218,44 @@ if ( bVisibleMergeResultWindow ) { bPreserveCarriageReturn = false; + + QString msg; + + if ( !m_pOptionDialog->m_PreProcessorCmd.isEmpty() ) + { + msg += "- " + i18n("PreprocessorCmd: ") + m_pOptionDialog->m_PreProcessorCmd + "\n"; + } + if ( m_pOptionDialog->m_bUpCase ) + { + msg += "- " + i18n("Convert to upper case\n"); + } + if ( !msg.isEmpty() ) + { + int result = KMessageBox::warningYesNo( this, + i18n("The following option(s) you selected might change data:\n") + msg + + i18n("\nMost likely this is not wanted during a merge.\n" + "Do you want to disable these settings or continue with these settings active?"), + i18n("Option unsafe for merging"), + i18n("Use these options during the merge"), i18n("Disable unsafe options") + ); + + if (result == KMessageBox::No ) + { + m_pOptionDialog->m_PreProcessorCmd = ""; + m_pOptionDialog->m_bUpCase = false; + } + } } m_diff3LineList.clear(); - bool bUseLineMatchingPP = !m_pOptionDialog->m_LineMatchingPreProcessorCmd.isEmpty() || - m_pOptionDialog->m_bIgnoreComments; - bool bUpCase = m_pOptionDialog->m_bUpCase; - + // Because of the progressdialog paintevents can occur, but data is invalid, + // so painting must be suppressed. if (m_pDiffTextWindow1) m_pDiffTextWindow1->setPaintingAllowed( false ); if (m_pDiffTextWindow2) m_pDiffTextWindow2->setPaintingAllowed( false ); if (m_pDiffTextWindow3) m_pDiffTextWindow3->setPaintingAllowed( false ); if (m_pOverview) m_pOverview->setPaintingAllowed( false ); + if (m_pMergeResultWindow) m_pMergeResultWindow->setPaintingAllowed( false ); if( m_sd3.isEmpty() ) @@ -441,95 +267,74 @@ // First get all input data. g_pProgressDialog->setInformation(i18n("Loading A")); - m_sd1.readPPFile( bPreserveCarriageReturn, m_pOptionDialog->m_PreProcessorCmd, bUpCase ); - m_sdlm1.readLMPPFile( &m_sd1, m_pOptionDialog->m_LineMatchingPreProcessorCmd, bUpCase, m_pOptionDialog->m_bIgnoreComments ); + m_sd1.readAndPreprocess(); g_pProgressDialog->step(); g_pProgressDialog->setInformation(i18n("Loading B")); - m_sd2.readPPFile( bPreserveCarriageReturn, m_pOptionDialog->m_PreProcessorCmd, bUpCase ); - m_sdlm2.readLMPPFile( &m_sd2, m_pOptionDialog->m_LineMatchingPreProcessorCmd, bUpCase, m_pOptionDialog->m_bIgnoreComments ); + m_sd2.readAndPreprocess(); g_pProgressDialog->step(); - m_sd3.m_bIsText = true; m_totalDiffStatus.reset(); // Run the diff. if ( m_sd3.isEmpty() ) { - m_totalDiffStatus.bBinaryAEqB = (m_sd1.m_size!=0 && m_sd1.m_size==m_sd2.m_size && memcmp(m_sd1.m_pBuf,m_sd2.m_pBuf,m_sd1.m_size)==0); + m_totalDiffStatus.bBinaryAEqB = m_sd1.getSizeBytes()!=0 && m_sd1.isBinaryEqualWith( m_sd2 ); g_pProgressDialog->setInformation(i18n("Diff: A <-> B")); - if ( !bUseLineMatchingPP ) - runDiff( &m_sd1.m_v[0], m_sd1.m_vSize, &m_sd2.m_v[0], m_sd2.m_vSize, m_diffList12 ); - else - runDiff( &m_sdlm1.m_v[0], m_sdlm1.m_vSize, &m_sdlm2.m_v[0], m_sdlm2.m_vSize, m_diffList12 ); + + runDiff( m_sd1.getLineDataForDiff(), m_sd1.getSizeLines(), m_sd2.getLineDataForDiff(), m_sd2.getSizeLines(), m_diffList12 ); g_pProgressDialog->step(); g_pProgressDialog->setInformation(i18n("Linediff: A <-> B")); calcDiff3LineListUsingAB( &m_diffList12, m_diff3LineList ); - fineDiff( m_diff3LineList, 1, &m_sd1.m_v[0], &m_sd2.m_v[0], m_totalDiffStatus.bTextAEqB ); - if ( m_sd1.m_size==0 ) m_totalDiffStatus.bTextAEqB=false; + fineDiff( m_diff3LineList, 1, m_sd1.getLineDataForDisplay(), m_sd2.getLineDataForDisplay(), m_totalDiffStatus.bTextAEqB ); + if ( m_sd1.getSizeBytes()==0 ) m_totalDiffStatus.bTextAEqB=false; g_pProgressDialog->step(); } else { g_pProgressDialog->setInformation(i18n("Loading C")); - m_sd3.readPPFile( bPreserveCarriageReturn, m_pOptionDialog->m_PreProcessorCmd, bUpCase ); - m_sdlm3.readLMPPFile( &m_sd3, m_pOptionDialog->m_LineMatchingPreProcessorCmd, bUpCase, m_pOptionDialog->m_bIgnoreComments ); + m_sd3.readAndPreprocess(); g_pProgressDialog->step(); - m_totalDiffStatus.bBinaryAEqB = (m_sd1.m_size!=0 && m_sd1.m_size==m_sd2.m_size && memcmp(m_sd1.m_pBuf,m_sd2.m_pBuf,m_sd1.m_size)==0); - m_totalDiffStatus.bBinaryAEqC = (m_sd1.m_size!=0 && m_sd1.m_size==m_sd3.m_size && memcmp(m_sd1.m_pBuf,m_sd3.m_pBuf,m_sd1.m_size)==0); - m_totalDiffStatus.bBinaryBEqC = (m_sd3.m_size!=0 && m_sd3.m_size==m_sd2.m_size && memcmp(m_sd3.m_pBuf,m_sd2.m_pBuf,m_sd3.m_size)==0); + m_totalDiffStatus.bBinaryAEqB = m_sd1.getSizeBytes()!=0 && m_sd1.isBinaryEqualWith(m_sd2); + m_totalDiffStatus.bBinaryAEqC = m_sd1.getSizeBytes()!=0 && m_sd1.isBinaryEqualWith(m_sd3); + m_totalDiffStatus.bBinaryBEqC = m_sd3.getSizeBytes()!=0 && m_sd3.isBinaryEqualWith(m_sd2); - if ( !bUseLineMatchingPP ) - { - g_pProgressDialog->setInformation(i18n("Diff: A <-> B")); - runDiff( &m_sd1.m_v[0], m_sd1.m_vSize, &m_sd2.m_v[0], m_sd2.m_vSize, m_diffList12 ); - g_pProgressDialog->step(); - g_pProgressDialog->setInformation(i18n("Diff: B <-> C")); - runDiff( &m_sd2.m_v[0], m_sd2.m_vSize, &m_sd3.m_v[0], m_sd3.m_vSize, m_diffList23 ); - g_pProgressDialog->step(); - g_pProgressDialog->setInformation(i18n("Diff: A <-> C")); - runDiff( &m_sd1.m_v[0], m_sd1.m_vSize, &m_sd3.m_v[0], m_sd3.m_vSize, m_diffList13 ); - g_pProgressDialog->step(); - } - else - { - g_pProgressDialog->setInformation(i18n("Diff: A <-> B")); - runDiff( &m_sdlm1.m_v[0], m_sd1.m_vSize, &m_sdlm2.m_v[0], m_sd2.m_vSize, m_diffList12 ); - g_pProgressDialog->step(); - g_pProgressDialog->setInformation(i18n("Diff: B <-> C")); - runDiff( &m_sdlm2.m_v[0], m_sd2.m_vSize, &m_sdlm3.m_v[0], m_sd3.m_vSize, m_diffList23 ); - g_pProgressDialog->step(); - g_pProgressDialog->setInformation(i18n("Diff: A <-> C")); - runDiff( &m_sdlm1.m_v[0], m_sd1.m_vSize, &m_sdlm3.m_v[0], m_sd3.m_vSize, m_diffList13 ); - g_pProgressDialog->step(); - } + g_pProgressDialog->setInformation(i18n("Diff: A <-> B")); + runDiff( m_sd1.getLineDataForDiff(), m_sd1.getSizeLines(), m_sd2.getLineDataForDiff(), m_sd2.getSizeLines(), m_diffList12 ); + g_pProgressDialog->step(); + g_pProgressDialog->setInformation(i18n("Diff: B <-> C")); + runDiff( m_sd2.getLineDataForDiff(), m_sd2.getSizeLines(), m_sd3.getLineDataForDiff(), m_sd3.getSizeLines(), m_diffList23 ); + g_pProgressDialog->step(); + g_pProgressDialog->setInformation(i18n("Diff: A <-> C")); + runDiff( m_sd1.getLineDataForDiff(), m_sd1.getSizeLines(), m_sd3.getLineDataForDiff(), m_sd3.getSizeLines(), m_diffList13 ); + g_pProgressDialog->step(); calcDiff3LineListUsingAB( &m_diffList12, m_diff3LineList ); calcDiff3LineListUsingAC( &m_diffList13, m_diff3LineList ); - calcDiff3LineListTrim( m_diff3LineList, &m_sd1.m_v[0], &m_sd2.m_v[0], &m_sd3.m_v[0] ); + calcDiff3LineListTrim( m_diff3LineList, m_sd1.getLineDataForDiff(), m_sd2.getLineDataForDiff(), m_sd3.getLineDataForDiff() ); calcDiff3LineListUsingBC( &m_diffList23, m_diff3LineList ); - calcDiff3LineListTrim( m_diff3LineList, &m_sd1.m_v[0], &m_sd2.m_v[0], &m_sd3.m_v[0] ); - debugLineCheck( m_diff3LineList, m_sd1.m_vSize, 1 ); - debugLineCheck( m_diff3LineList, m_sd2.m_vSize, 2 ); - debugLineCheck( m_diff3LineList, m_sd3.m_vSize, 3 ); + calcDiff3LineListTrim( m_diff3LineList, m_sd1.getLineDataForDiff(), m_sd2.getLineDataForDiff(), m_sd3.getLineDataForDiff() ); + debugLineCheck( m_diff3LineList, m_sd1.getSizeLines(), 1 ); + debugLineCheck( m_diff3LineList, m_sd2.getSizeLines(), 2 ); + debugLineCheck( m_diff3LineList, m_sd3.getSizeLines(), 3 ); g_pProgressDialog->setInformation(i18n("Linediff: A <-> B")); - fineDiff( m_diff3LineList, 1, &m_sd1.m_v[0], &m_sd2.m_v[0], m_totalDiffStatus.bTextAEqB ); + fineDiff( m_diff3LineList, 1, m_sd1.getLineDataForDisplay(), m_sd2.getLineDataForDisplay(), m_totalDiffStatus.bTextAEqB ); g_pProgressDialog->step(); g_pProgressDialog->setInformation(i18n("Linediff: B <-> C")); - fineDiff( m_diff3LineList, 2, &m_sd2.m_v[0], &m_sd3.m_v[0], m_totalDiffStatus.bTextBEqC ); + fineDiff( m_diff3LineList, 2, m_sd2.getLineDataForDisplay(), m_sd3.getLineDataForDisplay(), m_totalDiffStatus.bTextBEqC ); g_pProgressDialog->step(); g_pProgressDialog->setInformation(i18n("Linediff: A <-> C")); - fineDiff( m_diff3LineList, 3, &m_sd3.m_v[0], &m_sd1.m_v[0], m_totalDiffStatus.bTextAEqC ); + fineDiff( m_diff3LineList, 3, m_sd3.getLineDataForDisplay(), m_sd1.getLineDataForDisplay(), m_totalDiffStatus.bTextAEqC ); g_pProgressDialog->step(); - if ( m_sd1.m_size==0 ) { m_totalDiffStatus.bTextAEqB=false; m_totalDiffStatus.bTextAEqC=false; } - if ( m_sd2.m_size==0 ) { m_totalDiffStatus.bTextAEqB=false; m_totalDiffStatus.bTextBEqC=false; } + if ( m_sd1.getSizeBytes()==0 ) { m_totalDiffStatus.bTextAEqB=false; m_totalDiffStatus.bTextAEqC=false; } + if ( m_sd2.getSizeBytes()==0 ) { m_totalDiffStatus.bTextAEqB=false; m_totalDiffStatus.bTextBEqC=false; } } - calcWhiteDiff3Lines( m_diff3LineList, &m_sd1.m_v[0], &m_sd2.m_v[0], &m_sd3.m_v[0] ); + calcWhiteDiff3Lines( m_diff3LineList, m_sd1.getLineDataForDiff(), m_sd2.getLineDataForDiff(), m_sd3.getLineDataForDiff() ); calcDiff3LineVector( m_diff3LineList, m_diff3LineVector ); // Calc needed lines for display @@ -542,11 +347,11 @@ m_bTripleDiff = ! m_sd3.isEmpty(); m_pDiffTextWindow1->init( m_sd1.getAliasName(), - &m_sd1.m_v[0], m_sd1.m_vSize, &m_diff3LineVector, 1, m_bTripleDiff ); + m_sd1.getLineDataForDisplay(), m_sd1.getSizeLines(), &m_diff3LineVector, 1, m_bTripleDiff ); m_pDiffTextWindow2->init( m_sd2.getAliasName(), - &m_sd2.m_v[0], m_sd2.m_vSize, &m_diff3LineVector, 2, m_bTripleDiff ); + m_sd2.getLineDataForDisplay(), m_sd2.getSizeLines(), &m_diff3LineVector, 2, m_bTripleDiff ); m_pDiffTextWindow3->init( m_sd3.getAliasName(), - &m_sd3.m_v[0], m_sd3.m_vSize, &m_diff3LineVector, 3, m_bTripleDiff ); + m_sd3.getLineDataForDisplay(), m_sd3.getSizeLines(), &m_diff3LineVector, 3, m_bTripleDiff ); if (m_bTripleDiff) m_pDiffTextWindow3->show(); else m_pDiffTextWindow3->hide(); @@ -554,9 +359,9 @@ m_bOutputModified = bVisibleMergeResultWindow; m_pMergeResultWindow->init( - &m_sd1.m_v[0], - &m_sd2.m_v[0], - m_bTripleDiff ? &m_sd3.m_v[0] : 0, + m_sd1.getLineDataForDisplay(), + m_sd2.getLineDataForDisplay(), + m_bTripleDiff ? m_sd3.getLineDataForDisplay() : 0, &m_diff3LineList, &m_totalDiffStatus, m_outputFilename.isEmpty() ? QString("unnamed.txt") : m_outputFilename @@ -571,6 +376,8 @@ m_pDiffTextWindow2->setPaintingAllowed( true ); m_pDiffTextWindow3->setPaintingAllowed( true ); m_pOverview->setPaintingAllowed( true ); + m_pMergeResultWindow->setPaintingAllowed( true ); + if ( !bVisibleMergeResultWindow ) m_pMergeWindowFrame->hide(); @@ -604,7 +411,7 @@ KMessageBox::information( this, totalInfo ); } - if ( bVisibleMergeResultWindow && (!m_sd1.m_bIsText || !m_sd2.m_bIsText || !m_sd3.m_bIsText) ) + if ( bVisibleMergeResultWindow && (!m_sd1.isText() || !m_sd2.isText() || !m_sd3.isText()) ) { KMessageBox::information( this, i18n( "Some inputfiles don't seem to be pure textfiles.\n" @@ -949,7 +756,8 @@ return true; // eat event } - else if (e->type() == QEvent::Wheel ) { // wheel event + else if (e->type() == QEvent::Wheel ) // wheel event + { QWheelEvent *w = (QWheelEvent*)e; w->accept(); @@ -1001,10 +809,9 @@ if ( bDecodeSuccess && canContinue() ) { raise(); - bool bUpCase = m_pOptionDialog->m_bUpCase; - if ( o == m_pDiffTextWindow1 ) m_sd1.setData(text, bUpCase); - else if ( o == m_pDiffTextWindow2 ) m_sd2.setData(text, bUpCase); - else if ( o == m_pDiffTextWindow3 ) m_sd3.setData(text, bUpCase); + if ( o == m_pDiffTextWindow1 ) m_sd1.setData(text); + else if ( o == m_pDiffTextWindow2 ) m_sd2.setData(text); + else if ( o == m_pDiffTextWindow3 ) m_sd3.setData(text); init(); } } @@ -1037,6 +844,7 @@ connect( button, SIGNAL(clicked()), this, SLOT( selectFileA() ) ); QPushButton * button2 = new QPushButton( i18n("Dir..."), this ); connect( button2, SIGNAL(clicked()), this, SLOT( selectDirA() ) ); + connect( m_lineA, SIGNAL(textChanged(const QString&)), this, SLOT(inputFilenameChanged() ) ); h->addWidget( label, 0, 0 ); h->addWidget( m_lineA, 0, 1 ); @@ -1052,6 +860,7 @@ connect( button, SIGNAL(clicked()), this, SLOT( selectFileB() ) ); button2 = new QPushButton( i18n("Dir..."), this ); connect( button2, SIGNAL(clicked()), this, SLOT( selectDirB() ) ); + connect( m_lineB, SIGNAL(textChanged(const QString&)), this, SLOT(inputFilenameChanged() ) ); h->addWidget( label, 1, 0 ); h->addWidget( m_lineB, 1, 1 ); @@ -1067,6 +876,7 @@ connect( button, SIGNAL(clicked()), this, SLOT( selectFileC() ) ); button2 = new QPushButton( i18n("Dir..."), this ); connect( button2, SIGNAL(clicked()), this, SLOT( selectDirC() ) ); + connect( m_lineC, SIGNAL(textChanged(const QString&)), this, SLOT(inputFilenameChanged() ) ); h->addWidget( label, 2, 0 ); h->addWidget( m_lineC, 2, 1 ); @@ -1122,8 +932,44 @@ QSize sh = sizeHint(); setFixedHeight( sh.height() ); + m_bInputFileNameChanged = false; + +#ifdef KREPLACEMENTS_H + m_lineA->lineEdit()->installEventFilter( this ); + m_lineB->lineEdit()->installEventFilter( this ); + m_lineC->lineEdit()->installEventFilter( this ); + m_lineOut->lineEdit()->installEventFilter( this ); +#endif } +// Eventfilter: Only needed under Windows. +// Without this, files dropped in the line edit have URL-encoding. +// This eventfilter decodes the filenames as needed by KDiff3. +bool OpenDialog::eventFilter(QObject* o, QEvent* e) +{ + if (e->type()==QEvent::Drop) + { + QDropEvent* d = static_cast(e); + + if ( !QUriDrag::canDecode( d ) ) { + return false; + } + + QStringList lst; + QUriDrag::decodeLocalFiles( d, lst ); + + if ( lst.count() > 0 ) + { + static_cast(o)->setText( lst[0] ); + static_cast(o)->setFocus(); + } + + return true; + } + return false; +} + + void OpenDialog::selectURL( QComboBox* pLine, bool bDir, int i, bool bSave ) { QString current = pLine->currentText(); @@ -1154,6 +1000,18 @@ emit internalSignal(i!=0); } +// Clear the output-filename when any input-filename changed, +// because users forgot to change the output and accidently overwrote it with +// wrong data during a merge. +void OpenDialog::inputFilenameChanged() +{ + if(!m_bInputFileNameChanged) + { + m_bInputFileNameChanged=true; + m_lineOut->clearEdit(); + } +} + void OpenDialog::accept() { unsigned int maxNofRecentFiles = 10; @@ -1209,9 +1067,9 @@ for(;;) { OpenDialog d(this, - m_sd1.m_bPreserve ? QString("") : m_sd1.getAliasName(), - m_sd2.m_bPreserve ? QString("") : m_sd2.getAliasName(), - m_sd3.m_bPreserve ? QString("") : m_sd3.getAliasName(), + m_sd1.isFromBuffer() ? QString("") : m_sd1.getAliasName(), + m_sd2.isFromBuffer() ? QString("") : m_sd2.getAliasName(), + m_sd3.isFromBuffer() ? QString("") : m_sd3.getAliasName(), !m_outputFilename.isEmpty(), m_bDefaultFilename ? QString("") : m_outputFilename, SLOT(slotConfigure()), m_pOptionDialog ); @@ -1253,17 +1111,17 @@ m_pDirectoryMergeSplitter->hide(); init(); - if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 || - ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 || - ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 ) + if ( ! m_sd1.isEmpty() && !m_sd1.hasData() || + ! m_sd2.isEmpty() && !m_sd2.hasData() || + ! m_sd3.isEmpty() && !m_sd3.hasData() ) { QString text( i18n("Opening of these files failed:") ); text += "\n\n"; - if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 ) + if ( ! m_sd1.isEmpty() && !m_sd1.hasData() ) text += " - " + m_sd1.getAliasName() + "\n"; - if ( ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 ) + if ( ! m_sd2.isEmpty() && !m_sd2.hasData() ) text += " - " + m_sd2.getAliasName() + "\n"; - if ( ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 ) + if ( ! m_sd3.isEmpty() && !m_sd3.hasData() ) text += " - " + m_sd3.getAliasName() + "\n"; KMessageBox::sorry( this, text, i18n("File open error") ); @@ -1314,17 +1172,17 @@ { init(); - if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 || - ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 || - ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 ) + if ( ! m_sd1.isEmpty() && ! m_sd1.hasData() || + ! m_sd2.isEmpty() && ! m_sd2.hasData() || + ! m_sd3.isEmpty() && ! m_sd3.hasData() ) { QString text( i18n("Opening of these files failed:") ); text += "\n\n"; - if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 ) + if ( ! m_sd1.isEmpty() && !m_sd1.hasData() ) text += " - " + m_sd1.getAliasName() + "\n"; - if ( ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 ) + if ( ! m_sd2.isEmpty() && !m_sd2.hasData() ) text += " - " + m_sd2.getAliasName() + "\n"; - if ( ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 ) + if ( ! m_sd3.isEmpty() && !m_sd3.hasData() ) text += " - " + m_sd3.getAliasName() + "\n"; KMessageBox::sorry( this, text, i18n("File open error") ); @@ -1355,7 +1213,7 @@ if ( !s.isNull() ) { - QApplication::clipboard()->setText( s ); + QApplication::clipboard()->setText( s, QClipboard::Clipboard ); } slotStatusMsg(i18n("Ready.")); @@ -1371,7 +1229,7 @@ if ( s.isNull() && m_pMergeResultWindow!=0 ) s = m_pMergeResultWindow->getSelection(); if ( !s.isNull() ) { - QApplication::clipboard()->setText( s ); + QApplication::clipboard()->setText( s, QClipboard::Clipboard ); } slotStatusMsg(i18n("Ready.")); @@ -1387,20 +1245,19 @@ } else if ( canContinue() ) { - bool bUpCase = m_pOptionDialog->m_bUpCase; if ( m_pDiffTextWindow1->hasFocus() ) { - m_sd1.setData( QApplication::clipboard()->text(), bUpCase ); + m_sd1.setData( QApplication::clipboard()->text() ); init(); } else if ( m_pDiffTextWindow2->hasFocus() ) { - m_sd2.setData( QApplication::clipboard()->text(), bUpCase ); + m_sd2.setData( QApplication::clipboard()->text() ); init(); } else if ( m_pDiffTextWindow3->hasFocus() ) { - m_sd3.setData( QApplication::clipboard()->text(), bUpCase ); + m_sd3.setData( QApplication::clipboard()->text() ); init(); } } @@ -1585,6 +1442,23 @@ { slotEditCopy(); } + else + { + QClipboard *clipBoard = QApplication::clipboard(); + + if (clipBoard->supportsSelection ()) + { + QString s; + if ( m_pDiffTextWindow1!=0 ) s = m_pDiffTextWindow1->getSelection(); + if ( s.isNull() && m_pDiffTextWindow2!=0 ) s = m_pDiffTextWindow2->getSelection(); + if ( s.isNull() && m_pDiffTextWindow3!=0 ) s = m_pDiffTextWindow3->getSelection(); + if ( s.isNull() && m_pMergeResultWindow!=0 ) s = m_pMergeResultWindow->getSelection(); + if ( !s.isNull() ) + { + clipBoard->setText( s, QClipboard::Selection ); + } + } + } } void KDiff3App::slotClipboardChanged() @@ -1922,15 +1796,15 @@ if ( !canContinue() ) return; if ( m_outputFilename.isEmpty() ) { - if ( !m_sd3.isEmpty() && !m_sd3.m_bPreserve ) + if ( !m_sd3.isEmpty() && !m_sd3.isFromBuffer() ) { m_outputFilename = m_sd3.getFilename(); } - else if ( !m_sd2.isEmpty() && !m_sd2.m_bPreserve ) + else if ( !m_sd2.isEmpty() && !m_sd2.isFromBuffer() ) { m_outputFilename = m_sd2.getFilename(); } - else if ( !m_sd1.isEmpty() && !m_sd1.m_bPreserve ) + else if ( !m_sd1.isEmpty() && !m_sd1.isFromBuffer() ) { m_outputFilename = m_sd1.getFilename(); } @@ -2016,7 +1890,7 @@ void KDiff3App::slotUpdateAvailabilities() { - bool bTextDataAvailable = (m_sd1.m_pBuf != 0 || m_sd2.m_pBuf != 0 || m_sd3.m_pBuf != 0 ); + bool bTextDataAvailable = ( m_sd1.hasData() || m_sd2.hasData() || m_sd3.hasData() ); if( dirShowBoth->isChecked() ) { if ( m_bDirCompare ) diff -r 023fbd76c1e3 -r 8af4bb9d9a5a kdiff3/src/version.h --- a/kdiff3/src/version.h Sat Jan 31 14:25:47 2004 +0000 +++ b/kdiff3/src/version.h Sun Mar 07 09:59:09 2004 +0000 @@ -1,2 +1,2 @@ #undef VERSION -#define VERSION "0.9.81" +#define VERSION "0.9.83"