/*
 *   kdiff3 - Text Diff And Merge Tool
 *   Copyright (C) 2002-2007  Joachim Eibl, joachim.eibl at gmx.de
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include <tqcheckbox.h>
#include <tqcombobox.h>
#include <tqfont.h>
#include <tqframe.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqlineedit.h> 
#include <tqvbox.h>
#include <tqvalidator.h>
#include <tqtooltip.h>
#include <tqtextcodec.h>
#include <tqradiobutton.h>
#include <tqvbuttongroup.h>
#include <tqsettings.h>

#include <tdeapplication.h>
#include <kcolorbtn.h>
#include <tdefontdialog.h> // For TDEFontChooser
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdeconfig.h>
#include <tdemessagebox.h>
#include <tdemainwindow.h> //For tdetoolbar.h

//#include <kkeydialog.h>
#include <map>

#include "optiondialog.h"
#include "diff.h"
#include "smalldialogs.h"

#include <iostream>

#ifndef KREPLACEMENTS_H
#include <tdeglobalsettings.h>
#endif

static TQString s_historyEntryStartRegExpToolTip;
static TQString s_historyEntryStartSortKeyOrderToolTip;
static TQString s_autoMergeRegExpToolTip;
static TQString s_historyStartRegExpToolTip;

void OptionDialog::addOptionItem(OptionItem* p)
{
   m_optionItemList.push_back(p);
}

class OptionItem
{
public:
   OptionItem( OptionDialog* pOptionDialog, const TQString& saveName )
   {
      assert(pOptionDialog!=0);
      pOptionDialog->addOptionItem( this );
      m_saveName = saveName;
   }
   virtual ~OptionItem(){}
   virtual void setToDefault()=0;
   virtual void setToCurrent()=0;
   virtual void apply()=0;
   virtual void write(ValueMap*)=0;
   virtual void read(ValueMap*)=0;
   TQString getSaveName(){return m_saveName;}
protected:
   TQString m_saveName;
};

class OptionCheckBox : public TQCheckBox, public OptionItem
{
public:
   OptionCheckBox( TQString text, bool bDefaultVal, const TQString& saveName, bool* pbVar,
                   TQWidget* pParent, OptionDialog* pOD )
   : TQCheckBox( text, pParent ), OptionItem( pOD, saveName )
   {
      m_pbVar = pbVar;
      m_bDefaultVal = bDefaultVal;
   }
   void setToDefault(){ setChecked( m_bDefaultVal );      }
   void setToCurrent(){ setChecked( *m_pbVar );           }
   void apply()       { *m_pbVar = isChecked();                              }
   void write(ValueMap* config){ config->writeEntry(m_saveName, *m_pbVar );   }
   void read (ValueMap* config){ *m_pbVar = config->readBoolEntry( m_saveName, *m_pbVar ); }
private:
   OptionCheckBox( const OptionCheckBox& ); // private copy constructor without implementation
   bool* m_pbVar;
   bool m_bDefaultVal;
};

class OptionRadioButton : public TQRadioButton, public OptionItem
{
public:
   OptionRadioButton( TQString text, bool bDefaultVal, const TQString& saveName, bool* pbVar,
                   TQWidget* pParent, OptionDialog* pOD )
   : TQRadioButton( text, pParent ), OptionItem( pOD, saveName )
   {
      m_pbVar = pbVar;
      m_bDefaultVal = bDefaultVal;
   }
   void setToDefault(){ setChecked( m_bDefaultVal );      }
   void setToCurrent(){ setChecked( *m_pbVar );           }
   void apply()       { *m_pbVar = isChecked();                              }
   void write(ValueMap* config){ config->writeEntry(m_saveName, *m_pbVar );   }
   void read (ValueMap* config){ *m_pbVar = config->readBoolEntry( m_saveName, *m_pbVar ); }
private:
   OptionRadioButton( const OptionRadioButton& ); // private copy constructor without implementation
   bool* m_pbVar;
   bool m_bDefaultVal;
};


template<class T>
class OptionT : public OptionItem
{
public:
   OptionT( const T& defaultVal, const TQString& saveName, T* pVar, OptionDialog* pOD )
   : OptionItem( pOD, saveName )
   {
      m_pVar = pVar;
      *m_pVar = defaultVal;
   }
   OptionT( const TQString& saveName, T* pVar, OptionDialog* pOD )
   : OptionItem( pOD, saveName )
   {
      m_pVar = pVar;
   }
   void setToDefault(){}
   void setToCurrent(){}
   void apply()       {}
   void write(ValueMap* vm){ writeEntry( vm, m_saveName, *m_pVar ); }
   void read (ValueMap* vm){ readEntry ( vm, m_saveName, *m_pVar ); }
private:
   OptionT( const OptionT& ); // private copy constructor without implementation
   T* m_pVar;
};

template <class T> void writeEntry(ValueMap* vm, const TQString& saveName, const T& v ) {   vm->writeEntry( saveName, v ); }
static void writeEntry(ValueMap* vm, const TQString& saveName, const TQStringList& v )   {   vm->writeEntry( saveName, v, '|' ); }

static void readEntry(ValueMap* vm, const TQString& saveName, bool& v )       {   v = vm->readBoolEntry( saveName, v ); }
static void readEntry(ValueMap* vm, const TQString& saveName, int&  v )       {   v = vm->readNumEntry( saveName, v ); }
static void readEntry(ValueMap* vm, const TQString& saveName, TQSize& v )      {   v = vm->readSizeEntry( saveName, &v ); }
static void readEntry(ValueMap* vm, const TQString& saveName, TQPoint& v )     {   v = vm->readPointEntry( saveName, &v ); }
static void readEntry(ValueMap* vm, const TQString& saveName, TQStringList& v ){   v = vm->readListEntry( saveName, TQStringList(), '|' ); }

typedef OptionT<bool> OptionToggleAction;
typedef OptionT<int>  OptionNum;
typedef OptionT<TQPoint> OptionPoint;
typedef OptionT<TQSize> OptionSize;
typedef OptionT<TQStringList> OptionStringList;

class OptionFontChooser : public TDEFontChooser, public OptionItem
{
public:
   OptionFontChooser( const TQFont& defaultVal, const TQString& saveName, TQFont* pbVar, TQWidget* pParent, OptionDialog* pOD )
   :TDEFontChooser( pParent,"font",true/*onlyFixed*/,TQStringList(),false,6 ),
    OptionItem( pOD, saveName )
   {
      m_pbVar = pbVar;
      *m_pbVar = defaultVal;
      m_default = defaultVal;
   }
   void setToDefault(){ setFont( m_default, true /*only fixed*/ ); }
   void setToCurrent(){ setFont( *m_pbVar, true /*only fixed*/ ); }
   void apply()       { *m_pbVar = font();}
   void write(ValueMap* config){ config->writeEntry(m_saveName, *m_pbVar );   }
   void read (ValueMap* config){ *m_pbVar = config->readFontEntry( m_saveName, m_pbVar ); }
private:
   OptionFontChooser( const OptionToggleAction& ); // private copy constructor without implementation
   TQFont* m_pbVar;
   TQFont m_default;
};

class OptionColorButton : public KColorButton, public OptionItem
{
public:
   OptionColorButton( TQColor defaultVal, const TQString& saveName, TQColor* pVar, TQWidget* pParent, OptionDialog* pOD )
   : KColorButton( pParent ), OptionItem( pOD, saveName )
   {
      m_pVar = pVar;
      m_defaultVal = defaultVal;
   }
   void setToDefault(){ setColor( m_defaultVal );      }
   void setToCurrent(){ setColor( *m_pVar );           }
   void apply()       { *m_pVar = color();                              }
   void write(ValueMap* config){ config->writeEntry(m_saveName, *m_pVar );   }
   void read (ValueMap* config){ *m_pVar = config->readColorEntry( m_saveName, m_pVar ); }
private:
   OptionColorButton( const OptionColorButton& ); // private copy constructor without implementation
   TQColor* m_pVar;
   TQColor m_defaultVal;
};

class OptionLineEdit : public TQComboBox, public OptionItem
{
public:
   OptionLineEdit( const TQString& defaultVal, const TQString& saveName, TQString* pVar,
                   TQWidget* pParent, OptionDialog* pOD )
   : TQComboBox( pParent ), OptionItem( pOD, saveName )
   {
      setMinimumWidth(50);
      setEditable(true);
      m_pVar = pVar;
      m_defaultVal = defaultVal;
      m_list.push_back(defaultVal);
      insertText();
   }
   void setToDefault(){ setCurrentText( m_defaultVal );   }
   void setToCurrent(){ setCurrentText( *m_pVar );        }
   void apply()       { *m_pVar = currentText(); insertText();            }
   void write(ValueMap* config){ config->writeEntry( m_saveName, m_list, '|' );      }
   void read (ValueMap* config){ 
      m_list = config->readListEntry( m_saveName, m_defaultVal, '|' ); 
      if ( !m_list.empty() ) *m_pVar = m_list.front();
      clear();
      insertStringList(m_list);
   }
private:
   void insertText()
   {  // Check if the text exists. If yes remove it and push it in as first element
      TQString current = currentText();
      m_list.remove( current );
      m_list.push_front( current );
      clear();
      if ( m_list.size()>10 ) 
         m_list.erase( m_list.at(10),m_list.end() );
      insertStringList(m_list);
   }
   OptionLineEdit( const OptionLineEdit& ); // private copy constructor without implementation
   TQString* m_pVar;
   TQString m_defaultVal;
   TQStringList m_list;
};

#if defined TQT_NO_VALIDATOR
#error No validator
#endif
class OptionIntEdit : public TQLineEdit, public OptionItem
{
public:
   OptionIntEdit( int defaultVal, const TQString& saveName, int* pVar, int rangeMin, int rangeMax,
                   TQWidget* pParent, OptionDialog* pOD )
   : TQLineEdit( pParent ), OptionItem( pOD, saveName )
   {
      m_pVar = pVar;
      m_defaultVal = defaultVal;
      TQIntValidator* v = new TQIntValidator(this);
      v->setRange( rangeMin, rangeMax );
      setValidator( v );
   }
   void setToDefault(){ TQString s;  s.setNum(m_defaultVal); setText( s );  }
   void setToCurrent(){ TQString s;  s.setNum(*m_pVar);      setText( s );  }
   void apply()       { const TQIntValidator* v=static_cast<const TQIntValidator*>(validator());
                        *m_pVar = minMaxLimiter( text().toInt(), v->bottom(), v->top());
                        setText( TQString::number(*m_pVar) );  }
   void write(ValueMap* config){ config->writeEntry(m_saveName, *m_pVar );   }
   void read (ValueMap* config){ *m_pVar = config->readNumEntry( m_saveName, *m_pVar ); }
private:
   OptionIntEdit( const OptionIntEdit& ); // private copy constructor without implementation
   int* m_pVar;
   int m_defaultVal;
};

class OptionComboBox : public TQComboBox, public OptionItem
{
public:
   OptionComboBox( int defaultVal, const TQString& saveName, int* pVarNum,
                   TQWidget* pParent, OptionDialog* pOD )
   : TQComboBox( pParent ), OptionItem( pOD, saveName )
   {
      setMinimumWidth(50);
      m_pVarNum = pVarNum;
      m_pVarStr = 0;
      m_defaultVal = defaultVal;
      setEditable(false);
   }
   OptionComboBox( int defaultVal, const TQString& saveName, TQString* pVarStr,
                   TQWidget* pParent, OptionDialog* pOD )
   : TQComboBox( 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(ValueMap* config)
   { 
      if (m_pVarStr!=0) config->writeEntry(m_saveName, *m_pVarStr );
      else              config->writeEntry(m_saveName, *m_pVarNum );   
   }
   void read (ValueMap* 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_pVarNum;
   TQString* m_pVarStr;
   int m_defaultVal;
   
   void setText(const TQString& s)
   {
      // Find the string in the combobox-list, don't change the value if nothing fits.
      for( int i=0; i<count(); ++i )
      {
         if ( text(i)==s )
         {
            if (m_pVarNum!=0) *m_pVarNum = i;
            if (m_pVarStr!=0) *m_pVarStr = s;
            setCurrentItem(i);
            return;
         }
      }
   }
};

class OptionEncodingComboBox : public TQComboBox, public OptionItem
{
   std::vector<TQTextCodec*> m_codecVec;
   TQTextCodec** m_ppVarCodec;
public:
   OptionEncodingComboBox( const TQString& saveName, TQTextCodec** ppVarCodec,
                   TQWidget* pParent, OptionDialog* pOD )
   : TQComboBox( pParent ), OptionItem( pOD, saveName )
   {
      m_ppVarCodec = ppVarCodec;
      insertCodec( i18n("Unicode, 8 bit"),  TQTextCodec::codecForName("UTF-8") );
      insertCodec( i18n("Unicode"), TQTextCodec::codecForName("iso-10646-UCS-2") );
      insertCodec( i18n("Latin1"), TQTextCodec::codecForName("iso 8859-1") );

      // First sort codec names:
      std::map<TQString, TQTextCodec*> names;
      int i;
      for(i=0;;++i)
      {
         TQTextCodec* c = TQTextCodec::codecForIndex(i);
         if ( c==0 ) break;
         else  names[TQString(c->name()).upper()]=c;
      }

      std::map<TQString, TQTextCodec*>::iterator it;
      for(it=names.begin();it!=names.end();++it)
      {
         insertCodec( "", it->second );
      }

      TQToolTip::add( this, i18n(
         "Change this if non-ASCII characters are not displayed correctly."
         ));
   }
   void insertCodec( const TQString& visibleCodecName, TQTextCodec* c )
   {
      if (c!=0)
      {
         for( unsigned int i=0; i<m_codecVec.size(); ++i )
         {
            if ( c==m_codecVec[i] )
               return;  // don't insert any codec twice
         }
         insertItem( visibleCodecName.isEmpty() ? TQString(c->name()) : visibleCodecName+" ("+c->name()+")", m_codecVec.size() );
         m_codecVec.push_back( c );
      }
   }
   void setToDefault()
   {
      TQString defaultName = TQTextCodec::codecForLocale()->name();
      for(int i=0;i<count();++i)
      {
         if (defaultName==text(i) &&
             m_codecVec[i]==TQTextCodec::codecForLocale())
         {
            setCurrentItem(i);
            if (m_ppVarCodec!=0){ *m_ppVarCodec=m_codecVec[i]; }
            return;
         }
      }

      setCurrentItem( 0 );
      if (m_ppVarCodec!=0){ *m_ppVarCodec=m_codecVec[0]; }
   }
   void setToCurrent()
   {
      if (m_ppVarCodec!=0)
      {
         for(unsigned int i=0; i<m_codecVec.size(); ++i)
         {
            if ( *m_ppVarCodec==m_codecVec[i] )
            {
               setCurrentItem( i );
               break;
            }
         }
      }
   }
   void apply()
   {
      if (m_ppVarCodec!=0){ *m_ppVarCodec = m_codecVec[ currentItem() ]; }
   }
   void write(ValueMap* config)
   {
      if (m_ppVarCodec!=0) config->writeEntry(m_saveName, (*m_ppVarCodec)->name() );
   }
   void read (ValueMap* config)
   {
      TQString codecName = config->readEntry( m_saveName, m_codecVec[ currentItem() ]->name() );
      for(unsigned int i=0; i<m_codecVec.size(); ++i)
      {
         if ( codecName == m_codecVec[i]->name() )
         {
            setCurrentItem( i );
            if (m_ppVarCodec!=0) *m_ppVarCodec = m_codecVec[i];
            break;
         }
      }
   }
};


OptionDialog::OptionDialog( bool bShowDirMergeSettings, TQWidget *parent, char *name )
  :KDialogBase( IconList, i18n("Configure"), Help|Default|Apply|Ok|Cancel,
                Ok, parent, name, true /*modal*/, true )
{
   setHelp( "kdiff3/index.html", TQString() );

   setupFontPage();
   setupColorPage();
   setupEditPage();
   setupDiffPage();
   setupMergePage();
   setupOtherOptions();
   if (bShowDirMergeSettings)
      setupDirectoryMergePage();

   setupRegionalPage();
   setupIntegrationPage();

   //setupKeysPage();

   // Initialize all values in the dialog
   resetToDefaults();
   slotApply();
}

OptionDialog::~OptionDialog( void )
{
}

void OptionDialog::setupOtherOptions()
{
   new OptionToggleAction( false, "AutoAdvance", &m_bAutoAdvance, this );
   new OptionToggleAction( true,  "ShowWhiteSpaceCharacters", &m_bShowWhiteSpaceCharacters, this );
   new OptionToggleAction( true,  "ShowWhiteSpace", &m_bShowWhiteSpace, this );
   new OptionToggleAction( false, "ShowLineNumbers", &m_bShowLineNumbers, this );
   new OptionToggleAction( true,  "HorizDiffWindowSplitting", &m_bHorizDiffWindowSplitting, this );
   new OptionToggleAction( false, "WordWrap", &m_bWordWrap, this );

   new OptionToggleAction( true,  "ShowIdenticalFiles", &m_bDmShowIdenticalFiles, this );

   new OptionToggleAction( true,  "Show Toolbar", &m_bShowToolBar, this );
   new OptionToggleAction( true,  "Show Statusbar", &m_bShowStatusBar, this );

   new OptionNum( (int)TDEToolBar::Top, "ToolBarPos", &m_toolBarPos, this );
   new OptionSize( TQSize(600,400),"Geometry", &m_geometry, this );
   new OptionPoint( TQPoint(0,22), "Position", &m_position, this );
   new OptionToggleAction( false, "WindowStateMaximised", &m_bMaximised, this );

   new OptionStringList( "RecentAFiles", &m_recentAFiles, this );
   new OptionStringList( "RecentBFiles", &m_recentBFiles, this );
   new OptionStringList( "RecentCFiles", &m_recentCFiles, this );
   new OptionStringList( "RecentOutputFiles", &m_recentOutputFiles, this );
}

void OptionDialog::setupFontPage( void )
{
   TQFrame *page = addPage( i18n("Font"), i18n("Editor & Diff Output Font" ),
                             BarIcon("fonts", TDEIcon::SizeMedium ) );

   TQVBoxLayout *topLayout = new TQVBoxLayout( page, 5, spacingHint() );

   TQFont defaultFont =
#ifdef _WIN32
      TQFont("Courier New", 10 );
#elif defined( KREPLACEMENTS_H )
      TQFont("Courier", 10 );
#else
      TDEGlobalSettings::fixedFont();
#endif

   OptionFontChooser* pFontChooser = new OptionFontChooser( defaultFont, "Font", &m_font, page, this );
   topLayout->addWidget( pFontChooser );

   TQGridLayout *gbox = new TQGridLayout( 1, 2 );
   topLayout->addLayout( gbox );
   int line=0;

   OptionCheckBox* pItalicDeltas = new OptionCheckBox( i18n("Italic font for deltas"), false, "ItalicForDeltas", &m_bItalicForDeltas, page, this );
   gbox->addMultiCellWidget( pItalicDeltas, line, line, 0, 1 );
   TQToolTip::add( pItalicDeltas, i18n(
      "Selects the italic version of the font for differences.\n"
      "If the font doesn't support italic characters, then this does nothing.")
      );
}


void OptionDialog::setupColorPage( void )
{
  TQFrame *page = addPage( i18n("Color"), i18n("Colors Settings"),
     BarIcon("colorize", TDEIcon::SizeMedium ) );
  TQVBoxLayout *topLayout = new TQVBoxLayout( page, 5, spacingHint() );

  TQGridLayout *gbox = new TQGridLayout( 7, 2 );
  gbox->setColStretch(1,5);
  topLayout->addLayout(gbox);

  TQLabel* label;
  int line = 0;

  int depth = TQColor::numBitPlanes();
  bool bLowColor = depth<=8;

  label = new TQLabel( i18n("Editor and Diff Views:"), page );
  gbox->addWidget( label, line, 0 );
  TQFont f( label->font() );
  f.setBold(true);
  label->setFont(f);
  ++line;

  OptionColorButton* pFgColor = new OptionColorButton( TQt::black,"FgColor", &m_fgColor, page, this );
  label = new TQLabel( pFgColor, i18n("Foreground color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pFgColor, line, 1 );
  ++line;

  OptionColorButton* pBgColor = new OptionColorButton( TQt::white, "BgColor", &m_bgColor, page, this );
  label = new TQLabel( pBgColor, i18n("Background color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pBgColor, line, 1 );

  ++line;

  OptionColorButton* pDiffBgColor = new OptionColorButton( 
     bLowColor ? TQt::lightGray : tqRgb(224,224,224), "DiffBgColor", &m_diffBgColor, page, this );
  label = new TQLabel( pDiffBgColor, i18n("Diff background color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pDiffBgColor, line, 1 );
  ++line;

  OptionColorButton* pColorA = new OptionColorButton(
     bLowColor ? tqRgb(0,0,255) : tqRgb(0,0,200)/*blue*/, "ColorA", &m_colorA, page, this );
  label = new TQLabel( pColorA, i18n("Color A:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColorA, line, 1 );
  ++line;

  OptionColorButton* pColorB = new OptionColorButton(
     bLowColor ? tqRgb(0,128,0) : tqRgb(0,150,0)/*green*/, "ColorB", &m_colorB, page, this );
  label = new TQLabel( pColorB, i18n("Color B:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColorB, line, 1 );
  ++line;

  OptionColorButton* pColorC = new OptionColorButton(
     bLowColor ? tqRgb(128,0,128) : tqRgb(150,0,150)/*magenta*/, "ColorC", &m_colorC, page, this );
  label = new TQLabel( pColorC, i18n("Color C:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColorC, line, 1 );
  ++line;

  OptionColorButton* pColorForConflict = new OptionColorButton( TQt::red, "ColorForConflict", &m_colorForConflict, page, this );
  label = new TQLabel( pColorForConflict, i18n("Conflict color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColorForConflict, line, 1 );
  ++line;

  OptionColorButton* pColor = new OptionColorButton( 
     bLowColor ? tqRgb(192,192,192) : tqRgb(220,220,100), "CurrentRangeBgColor", &m_currentRangeBgColor, page, this );
  label = new TQLabel( pColor, i18n("Current range background color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColor, line, 1 );
  ++line;

  pColor = new OptionColorButton( 
     bLowColor ? tqRgb(255,255,0) : tqRgb(255,255,150), "CurrentRangeDiffBgColor", &m_currentRangeDiffBgColor, page, this );
  label = new TQLabel( pColor, i18n("Current range diff background color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColor, line, 1 );
  ++line;

  pColor = new OptionColorButton( tqRgb(0xff,0xd0,0x80), "ManualAlignmentRangeColor", &m_manualHelpRangeColor, page, this );
  label = new TQLabel( pColor, i18n("Color for manually aligned difference ranges:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColor, line, 1 );
  ++line;

  label = new TQLabel( i18n("Directory Comparison View:"), page );
  gbox->addWidget( label, line, 0 );
  label->setFont(f);
  ++line;

  pColor = new OptionColorButton( tqRgb(0,0xd0,0), "NewestFileColor", &m_newestFileColor, page, this );
  label = new TQLabel( pColor, i18n("Newest file color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColor, line, 1 );
  TQString dirColorTip = i18n( "Changing this color will only be effective when starting the next directory comparison.");
  TQToolTip::add( label, dirColorTip );
  ++line;

  pColor = new OptionColorButton( tqRgb(0xf0,0,0), "OldestFileColor", &m_oldestFileColor, page, this );
  label = new TQLabel( pColor, i18n("Oldest file color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColor, line, 1 );
  TQToolTip::add( label, dirColorTip );
  ++line;

  pColor = new OptionColorButton( tqRgb(0xc0,0xc0,0), "MidAgeFileColor", &m_midAgeFileColor, page, this );
  label = new TQLabel( pColor, i18n("Middle age file color:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColor, line, 1 );
  TQToolTip::add( label, dirColorTip );
  ++line;

  pColor = new OptionColorButton( tqRgb(0,0,0), "MissingFileColor", &m_missingFileColor, page, this );
  label = new TQLabel( pColor, i18n("Color for missing files:"), page );
  gbox->addWidget( label, line, 0 );
  gbox->addWidget( pColor, line, 1 );
  TQToolTip::add( label, dirColorTip );
  ++line;

  topLayout->addStretch(10);
}


void OptionDialog::setupEditPage( void )
{
   TQFrame *page = addPage( i18n("Editor"), i18n("Editor Behavior"),
                           BarIcon("edit", TDEIcon::SizeMedium ) );
   TQVBoxLayout *topLayout = new TQVBoxLayout( page, 5, spacingHint() );

   TQGridLayout *gbox = new TQGridLayout( 4, 2 );
   gbox->setColStretch(1,5);
   topLayout->addLayout( gbox );
   TQLabel* label;
   int line=0;

   OptionCheckBox* pReplaceTabs = new OptionCheckBox( i18n("Tab inserts spaces"), false, "ReplaceTabs", &m_bReplaceTabs, page, this );
   gbox->addMultiCellWidget( pReplaceTabs, line, line, 0, 1 );
   TQToolTip::add( pReplaceTabs, i18n(
      "On: Pressing tab generates the appropriate number of spaces.\n"
      "Off: A Tab-character will be inserted.")
      );
   ++line;

   OptionIntEdit* pTabSize = new OptionIntEdit( 8, "TabSize", &m_tabSize, 1, 100, page, this );
   label = new TQLabel( pTabSize, i18n("Tab size:"), page );
   gbox->addWidget( label, line, 0 );
   gbox->addWidget( pTabSize, line, 1 );
   ++line;

   OptionCheckBox* pAutoIndentation = new OptionCheckBox( i18n("Auto indentation"), true, "AutoIndentation", &m_bAutoIndentation, page, this  );
   gbox->addMultiCellWidget( pAutoIndentation, line, line, 0, 1 );
   TQToolTip::add( pAutoIndentation, i18n(
      "On: The indentation of the previous line is used for a new line.\n"
      ));
   ++line;

   OptionCheckBox* pAutoCopySelection = new OptionCheckBox( i18n("Auto copy selection"), false, "AutoCopySelection", &m_bAutoCopySelection, page, this );
   gbox->addMultiCellWidget( pAutoCopySelection, line, line, 0, 1 );
   TQToolTip::add( pAutoCopySelection, i18n(
      "On: Any selection is immediately written to the clipboard.\n"
      "Off: You must explicitely copy e.g. via Ctrl-C."
      ));
   ++line;
   
   label = new TQLabel( i18n("Line end style:"), page );
   gbox->addWidget( 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 );
   TQToolTip::add( label, i18n(
      "Sets the line endings for when an edited file is saved.\n"
      "DOS/Windows: CR+LF; UNIX: LF; with CR=0D, LF=0A")
      );
   ++line;
      
   topLayout->addStretch(10);
}


void OptionDialog::setupDiffPage( void )
{
   TQFrame *page = addPage( i18n("Diff"), i18n("Diff Settings"),
                           BarIcon("misc", TDEIcon::SizeMedium ) );
   TQVBoxLayout *topLayout = new TQVBoxLayout( page, 5, spacingHint() );

   TQGridLayout *gbox = new TQGridLayout( 3, 2 );
   gbox->setColStretch(1,5);
   topLayout->addLayout( gbox );
   int line=0;

   TQLabel* label=0;

//   OptionCheckBox* pPreserveCarriageReturn = new OptionCheckBox( i18n("Preserve carriage return"), false, "PreserveCarriageReturn", &m_bPreserveCarriageReturn, page, this );
//   gbox->addMultiCellWidget( pPreserveCarriageReturn, line, line, 0, 1 );
//   TQToolTip::add( pPreserveCarriageReturn, i18n(
//      "Show carriage return characters '\\r' if they exist.\n"
//      "Helps to compare files that were modified under different operating systems.")
//      );
//   ++line;
   TQString treatAsWhiteSpace = " ("+i18n("Treat as white space.")+")";

   OptionCheckBox* pIgnoreNumbers = new OptionCheckBox( i18n("Ignore numbers")+treatAsWhiteSpace, false, "IgnoreNumbers", &m_bIgnoreNumbers, page, this );
   gbox->addMultiCellWidget( pIgnoreNumbers, line, line, 0, 1 );
   TQToolTip::add( pIgnoreNumbers, i18n(
      "Ignore number characters during line matching phase. (Similar to Ignore white space.)\n"
      "Might help to compare files with numeric data.")
      );
   ++line;

   OptionCheckBox* pIgnoreComments = new OptionCheckBox( i18n("Ignore C/C++ comments")+treatAsWhiteSpace, false, "IgnoreComments", &m_bIgnoreComments, page, this );
   gbox->addMultiCellWidget( pIgnoreComments, line, line, 0, 1 );
   TQToolTip::add( pIgnoreComments, i18n( "Treat C/C++ comments like white space.")
      );
   ++line;

   OptionCheckBox* pIgnoreCase = new OptionCheckBox( i18n("Ignore case")+treatAsWhiteSpace, false, "IgnoreCase", &m_bIgnoreCase, page, this );
   gbox->addMultiCellWidget( pIgnoreCase, line, line, 0, 1 );
   TQToolTip::add( pIgnoreCase, i18n(
      "Treat case differences like white space changes. ('a'<=>'A')")
      );
   ++line;

   label = new TQLabel( i18n("Preprocessor command:"), page );
   gbox->addWidget( label, line, 0 );
   OptionLineEdit* pLE = new OptionLineEdit( "", "PreProcessorCmd", &m_PreProcessorCmd, page, this );
   gbox->addWidget( pLE, line, 1 );
   TQToolTip::add( label, i18n("User defined pre-processing. (See the docs for details.)") );
   ++line;

   label = new TQLabel( i18n("Line-matching preprocessor command:"), page );
   gbox->addWidget( label, line, 0 );
   pLE = new OptionLineEdit( "", "LineMatchingPreProcessorCmd", &m_LineMatchingPreProcessorCmd, page, this );
   gbox->addWidget( pLE, line, 1 );
   TQToolTip::add( label, i18n("This pre-processor is only used during line matching.\n(See the docs for details.)") );
   ++line;

   OptionCheckBox* pTryHard = new OptionCheckBox( i18n("Try hard (slower)"), true, "TryHard", &m_bTryHard, page, this );
   gbox->addMultiCellWidget( pTryHard, line, line, 0, 1 );
   TQToolTip::add( pTryHard, i18n(
      "Enables the --minimal option for the external diff.\n"
      "The analysis of big files will be much slower.")
      );
   ++line;

   topLayout->addStretch(10);
}

void OptionDialog::setupMergePage( void )
{
   TQFrame *page = addPage( i18n("Merge"), i18n("Merge Settings"),
                           BarIcon("misc", TDEIcon::SizeMedium ) );
   TQVBoxLayout *topLayout = new TQVBoxLayout( page );
   topLayout->setMargin( 5 );
   topLayout->setSpacing( spacingHint() );

   TQGridLayout *gbox = new TQGridLayout();
   gbox->setColStretch(1,5);
   topLayout->addLayout( gbox );
   int line=0;

   TQLabel* label=0;

   label = new TQLabel( i18n("Auto advance delay (ms):"), page );
   gbox->addWidget( label, line, 0 );
   OptionIntEdit* pAutoAdvanceDelay = new OptionIntEdit( 500, "AutoAdvanceDelay", &m_autoAdvanceDelay, 0, 2000, page, this );
   gbox->addWidget( pAutoAdvanceDelay, line, 1 );
   TQToolTip::add( label,i18n(
      "When in Auto-Advance mode the result of the current selection is shown \n"
      "for the specified time, before jumping to the next conflict. Range: 0-2000 ms")
      );
   ++line;

   label = new TQLabel( i18n("White space 2-file merge default:"), page );
   gbox->addWidget( label, line, 0 );
   OptionComboBox* pWhiteSpace2FileMergeDefault = new OptionComboBox( 0, "WhiteSpace2FileMergeDefault", &m_whiteSpace2FileMergeDefault, page, this );
   gbox->addWidget( pWhiteSpace2FileMergeDefault, line, 1 );
   pWhiteSpace2FileMergeDefault->insertItem( i18n("Manual Choice"), 0 );
   pWhiteSpace2FileMergeDefault->insertItem( "A", 1 );
   pWhiteSpace2FileMergeDefault->insertItem( "B", 2 );
   TQToolTip::add( label, i18n(
      "Allow the merge algorithm to automatically select an input for "
      "white-space-only changes." )
      );
   ++line;

   label = new TQLabel( i18n("White space 3-file merge default:"), page );
   gbox->addWidget( label, line, 0 );
   OptionComboBox* pWhiteSpace3FileMergeDefault = new OptionComboBox( 0, "WhiteSpace3FileMergeDefault", &m_whiteSpace3FileMergeDefault, page, this );
   gbox->addWidget( pWhiteSpace3FileMergeDefault, line, 1 );
   pWhiteSpace3FileMergeDefault->insertItem( i18n("Manual Choice"), 0 );
   pWhiteSpace3FileMergeDefault->insertItem( "A", 1 );
   pWhiteSpace3FileMergeDefault->insertItem( "B", 2 );
   pWhiteSpace3FileMergeDefault->insertItem( "C", 3 );
   TQToolTip::add( label, i18n(
      "Allow the merge algorithm to automatically select an input for "
      "white-space-only changes." )
      );
   ++line;

   TQGroupBox* pGroupBox = new TQGroupBox( 2, TQt::Horizontal, i18n("Automatic Merge Regular Expression"), page);
   gbox->addMultiCellWidget( pGroupBox, line,line,0,1);
   ++line;
   {
      TQWidget* page = new TQWidget( pGroupBox );
      TQGridLayout* gbox = new TQGridLayout( page, 2, 2, spacingHint() );
      gbox->setColStretch(1,10);
      int line = 0;

      label = new TQLabel( i18n("Auto merge regular expression:"), page );
      gbox->addWidget( label, line, 0 );
      m_pAutoMergeRegExpLineEdit = new OptionLineEdit( ".*\\$(Version|Header|Date|Author).*\\$.*", "AutoMergeRegExp", &m_autoMergeRegExp, page, this );
      gbox->addWidget( m_pAutoMergeRegExpLineEdit, line, 1 );
      s_autoMergeRegExpToolTip = i18n("Regular expression for lines where KDiff3 should automatically choose one source.\n"
                                      "When a line with a conflict matches the regular expression then\n"
                                      "- if available - C, otherwise B will be chosen.");
      TQToolTip::add( label, s_autoMergeRegExpToolTip );
      ++line;

      OptionCheckBox* pAutoMergeRegExp = new OptionCheckBox( i18n("Run regular expression auto merge on merge start"), false, "RunRegExpAutoMergeOnMergeStart", &m_bRunRegExpAutoMergeOnMergeStart, page, this );
      gbox->addMultiCellWidget( pAutoMergeRegExp, line, line, 0, 1 );
      TQToolTip::add( pAutoMergeRegExp, i18n( "Run the merge for auto merge regular expressions\n"
                                             "immediately when a merge starts.\n"));
      ++line;
   }

   pGroupBox = new TQGroupBox( 2, TQt::Horizontal, i18n("Version Control History Merging"), page);
   gbox->addMultiCellWidget( pGroupBox, line,line,0,1);
   ++line;
   {
      TQWidget* page = new TQWidget( pGroupBox );
      TQGridLayout* gbox = new TQGridLayout( page, 2, 2, spacingHint() );
      gbox->setColStretch(1,10);
      int line = 0;

      label = new TQLabel( i18n("History start regular expression:"), page );
      gbox->addWidget( label, line, 0 );
      m_pHistoryStartRegExpLineEdit = new OptionLineEdit( ".*\\$Log.*\\$.*", "HistoryStartRegExp", &m_historyStartRegExp, page, this );
      gbox->addWidget( m_pHistoryStartRegExpLineEdit, line, 1 );
      s_historyStartRegExpToolTip = i18n("Regular expression for the start of the version control history entry.\n"
                                 "Usually this line contains the \"$Log$\"-keyword.\n"
                                 "Default value: \".*\\$Log.*\\$.*\"");
      TQToolTip::add( label, s_historyStartRegExpToolTip );
      ++line;
   
      label = new TQLabel( i18n("History entry start regular expression:"), page );
      gbox->addWidget( label, line, 0 );
      // Example line:  "** \main\rolle_fsp_dev_008\1   17 Aug 2001 10:45:44   rolle"
      TQString historyEntryStartDefault =
         "\\s*\\\\main\\\\(\\S+)\\s+"  // Start with  "\main\"
         "([0-9]+) "          // day
         "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) " //month
         "([0-9][0-9][0-9][0-9]) " // year
         "([0-9][0-9]:[0-9][0-9]:[0-9][0-9])\\s+(.*)";  // time, name
   
      m_pHistoryEntryStartRegExpLineEdit = new OptionLineEdit( historyEntryStartDefault, "HistoryEntryStartRegExp", &m_historyEntryStartRegExp, page, this );
      gbox->addWidget( m_pHistoryEntryStartRegExpLineEdit, line, 1 );
      s_historyEntryStartRegExpToolTip = i18n("A version control history entry consists of several lines.\n"
                                 "Specify the regular expression to detect the first line (without the leading comment).\n"
                                 "Use parentheses to group the keys you want to use for sorting.\n"
                                 "If left empty, then KDiff3 assumes that empty lines separate history entries.\n"
                                 "See the documentation for details.");
      TQToolTip::add( label, s_historyEntryStartRegExpToolTip );
      ++line;
   
      m_pHistoryMergeSorting = new OptionCheckBox( i18n("History merge sorting"), false, "HistoryMergeSorting", &m_bHistoryMergeSorting, page, this );
      gbox->addMultiCellWidget( m_pHistoryMergeSorting, line, line, 0, 1 );
      TQToolTip::add( m_pHistoryMergeSorting, i18n("Sort version control history by a key.") );
      ++line;
            //TQString branch = newHistoryEntry.cap(1);
            //int day    = newHistoryEntry.cap(2).toInt();
            //int month  = TQString("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec").find(newHistoryEntry.cap(3))/4 + 1;
            //int year   = newHistoryEntry.cap(4).toInt();
            //TQString time = newHistoryEntry.cap(5);
            //TQString name = newHistoryEntry.cap(6);
      TQString defaultSortKeyOrder = "4,3,2,5,1,6"; //TQDate(year,month,day).toString(TQt::ISODate) +" "+ time + " " + branch + " " + name;

      label = new TQLabel( i18n("History entry start sort key order:"), page );
      gbox->addWidget( label, line, 0 );
      m_pHistorySortKeyOrderLineEdit = new OptionLineEdit( defaultSortKeyOrder, "HistoryEntryStartSortKeyOrder", &m_historyEntryStartSortKeyOrder, page, this );
      gbox->addWidget( m_pHistorySortKeyOrderLineEdit, line, 1 );
      s_historyEntryStartSortKeyOrderToolTip = i18n("Each parentheses used in the regular expression for the history start entry\n"
                                 "groups a key that can be used for sorting.\n"
                                 "Specify the list of keys (that are numbered in order of occurrence\n"
                                 "starting with 1) using ',' as separator (e.g. \"4,5,6,1,2,3,7\").\n"
                                 "If left empty, then no sorting will be done.\n"
                                 "See the documentation for details.");
      TQToolTip::add( label, s_historyEntryStartSortKeyOrderToolTip );
      m_pHistorySortKeyOrderLineEdit->setEnabled(false);
      connect( m_pHistoryMergeSorting, TQ_SIGNAL(toggled(bool)), m_pHistorySortKeyOrderLineEdit, TQ_SLOT(setEnabled(bool)));
      ++line;

      m_pHistoryAutoMerge = new OptionCheckBox( i18n("Merge version control history on merge start"), false, "RunHistoryAutoMergeOnMergeStart", &m_bRunHistoryAutoMergeOnMergeStart, page, this );
      gbox->addMultiCellWidget( m_pHistoryAutoMerge, line, line, 0, 1 );
      TQToolTip::add( m_pHistoryAutoMerge, i18n("Run version control history automerge on merge start.") );
      ++line;

      OptionIntEdit* pMaxNofHistoryEntries = new OptionIntEdit( -1, "MaxNofHistoryEntries", &m_maxNofHistoryEntries, -1, 1000, page, this );
      label = new TQLabel( pMaxNofHistoryEntries, i18n("Max number of history entries:"), page );
      gbox->addWidget( label, line, 0 );
      gbox->addWidget( pMaxNofHistoryEntries, line, 1 );
      TQToolTip::add( pMaxNofHistoryEntries, i18n("Cut off after specified number. Use -1 for infinite number of entries.") );
      ++line;
   }

   TQPushButton* pButton = new TQPushButton( i18n("Test your regular expressions"), page );
   gbox->addWidget( pButton, line, 0 );
   connect( pButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotHistoryMergeRegExpTester()));
   ++line;

   label = new TQLabel( i18n("Irrelevant merge command:"), page );
   gbox->addWidget( label, line, 0 );
   OptionLineEdit* pLE = new OptionLineEdit( "", "IrrelevantMergeCmd", &m_IrrelevantMergeCmd, page, this );
   gbox->addWidget( pLE, line, 1 );
   TQToolTip::add( label, i18n("If specified this script is run after automerge\n"
                              "when no other relevant changes were detected.\n"
                              "Called with the parameters: filename1 filename2 filename3") );
   ++line;


   OptionCheckBox* pAutoSaveAndQuit = new OptionCheckBox( i18n("Auto save and quit on merge without conflicts"), false,
      "AutoSaveAndQuitOnMergeWithoutConflicts", &m_bAutoSaveAndQuitOnMergeWithoutConflicts, page, this );
   gbox->addMultiCellWidget( pAutoSaveAndQuit, line, line, 0, 1 );
   TQToolTip::add( pAutoSaveAndQuit, i18n("When KDiff3 was started for a file-merge from the commandline and all\n" 
                                         "conflicts are solvable without user interaction then automatically save and quit.\n"
                                         "(Similar to command line option \"--auto\".") );
   ++line;

   topLayout->addStretch(10);
}

void OptionDialog::setupDirectoryMergePage( void )
{
   TQFrame *page = addPage( i18n("Directory Merge"), i18n("Directory Merge"),
                           BarIcon("folder", TDEIcon::SizeMedium ) );
   TQVBoxLayout *topLayout = new TQVBoxLayout( page, 5, spacingHint() );

   TQGridLayout *gbox = new TQGridLayout( 11, 2 );
   gbox->setColStretch(1,5);
   topLayout->addLayout( gbox );
   int line=0;

   OptionCheckBox* pRecursiveDirs = new OptionCheckBox( i18n("Recursive directories"), true, "RecursiveDirs", &m_bDmRecursiveDirs, page, this );
   gbox->addMultiCellWidget( pRecursiveDirs, line, line, 0, 1 );
   TQToolTip::add( pRecursiveDirs, i18n("Whether to analyze subdirectories or not.") );
   ++line;
   TQLabel* label = new TQLabel( i18n("File pattern(s):"), page );
   gbox->addWidget( label, line, 0 );
   OptionLineEdit* pFilePattern = new OptionLineEdit( "*", "FilePattern", &m_DmFilePattern, page, this );
   gbox->addWidget( pFilePattern, line, 1 );
   TQToolTip::add( label, i18n(
      "Pattern(s) of files to be analyzed. \n"
      "Wildcards: '*' and '?'\n"
      "Several Patterns can be specified by using the separator: ';'"
      ));
   ++line;

   label = new TQLabel( i18n("File-anti-pattern(s):"), page );
   gbox->addWidget( label, line, 0 );
   OptionLineEdit* pFileAntiPattern = new OptionLineEdit( "*.orig;*.o;*.obj", "FileAntiPattern", &m_DmFileAntiPattern, page, this );
   gbox->addWidget( pFileAntiPattern, line, 1 );
   TQToolTip::add( label, i18n(
      "Pattern(s) of files to be excluded from analysis. \n"
      "Wildcards: '*' and '?'\n"
      "Several Patterns can be specified by using the separator: ';'"
      ));
   ++line;

   label = new TQLabel( i18n("Dir-anti-pattern(s):"), page );
   gbox->addWidget( label, line, 0 );
   OptionLineEdit* pDirAntiPattern = new OptionLineEdit( "CVS;.deps;.svn", "DirAntiPattern", &m_DmDirAntiPattern, page, this );
   gbox->addWidget( pDirAntiPattern, line, 1 );
   TQToolTip::add( label, i18n(
      "Pattern(s) of directories to be excluded from analysis. \n"
      "Wildcards: '*' and '?'\n"
      "Several Patterns can be specified by using the separator: ';'"
      ));
   ++line;

   OptionCheckBox* pUseCvsIgnore = new OptionCheckBox( i18n("Use .cvsignore"), false, "UseCvsIgnore", &m_bDmUseCvsIgnore, page, this );
   gbox->addMultiCellWidget( pUseCvsIgnore, line, line, 0, 1 );
   TQToolTip::add( pUseCvsIgnore, i18n(
      "Extends the antipattern to anything that would be ignored by CVS.\n"
      "Via local \".cvsignore\"-files this can be directory specific."
      ));
   ++line;

   OptionCheckBox* pFindHidden = new OptionCheckBox( i18n("Find hidden files and directories"), true, "FindHidden", &m_bDmFindHidden, page, this );
   gbox->addMultiCellWidget( pFindHidden, line, line, 0, 1 );
#ifdef _WIN32
   TQToolTip::add( pFindHidden, i18n("Finds files and directories with the hidden attribute.") );
#else
   TQToolTip::add( pFindHidden, i18n("Finds files and directories starting with '.'.") );
#endif
   ++line;

   OptionCheckBox* pFollowFileLinks = new OptionCheckBox( i18n("Follow file links"), false, "FollowFileLinks", &m_bDmFollowFileLinks, page, this );
   gbox->addMultiCellWidget( pFollowFileLinks, line, line, 0, 1 );
   TQToolTip::add( pFollowFileLinks, i18n(
      "On: Compare the file the link points to.\n"
      "Off: Compare the links."
      ));
   ++line;

   OptionCheckBox* pFollowDirLinks = new OptionCheckBox( i18n("Follow directory links"), false, "FollowDirLinks", &m_bDmFollowDirLinks, page, this );
   gbox->addMultiCellWidget( pFollowDirLinks, line, line, 0, 1 );
   TQToolTip::add( pFollowDirLinks,    i18n(
      "On: Compare the directory the link points to.\n"
      "Off: Compare the links."
      ));
   ++line;

   //OptionCheckBox* pShowOnlyDeltas = new OptionCheckBox( i18n("List only deltas"),false,"ListOnlyDeltas", &m_bDmShowOnlyDeltas, page, this );
   //gbox->addMultiCellWidget( pShowOnlyDeltas, line, line, 0, 1 );
   //TQToolTip::add( pShowOnlyDeltas, i18n(
   //              "Files and directories without change will not appear in the list."));
   //++line;

#ifdef _WIN32
   bool bCaseSensitiveFilenameComparison = false;
#else
   bool bCaseSensitiveFilenameComparison = true;
#endif
   OptionCheckBox* pCaseSensitiveFileNames = new OptionCheckBox( i18n("Case sensitive filename comparison"),bCaseSensitiveFilenameComparison,"CaseSensitiveFilenameComparison", &m_bDmCaseSensitiveFilenameComparison, page, this );
   gbox->addMultiCellWidget( pCaseSensitiveFileNames, line, line, 0, 1 );
   TQToolTip::add( pCaseSensitiveFileNames, i18n(
                 "The directory comparison will compare files or directories when their names match.\n"
                 "Set this option if the case of the names must match. (Default for Windows is off, otherwise on.)"));
   ++line;

   TQVButtonGroup* pBG = new TQVButtonGroup(i18n("File Comparison Mode"),page);
   gbox->addMultiCellWidget( pBG, line, line, 0, 1 );
   ++line;
   
   OptionRadioButton* pBinaryComparison = new OptionRadioButton( i18n("Binary comparison"), true, "BinaryComparison", &m_bDmBinaryComparison, pBG, this );
   TQToolTip::add( pBinaryComparison, i18n("Binary comparison of each file. (Default)") );
   
   OptionRadioButton* pFullAnalysis = new OptionRadioButton( i18n("Full analysis"), false, "FullAnalysis", &m_bDmFullAnalysis, pBG, this );
   TQToolTip::add( pFullAnalysis, i18n("Do a full analysis and show statistics information in extra columns.\n"
                                      "(Slower than a binary comparison, much slower for binary files.)") );
   
   OptionRadioButton* pTrustDate = new OptionRadioButton( i18n("Trust the size and modification date (unsafe)"), false, "TrustDate", &m_bDmTrustDate, pBG, this );
   TQToolTip::add( pTrustDate, i18n("Assume that files are equal if the modification date and file length are equal.\n"
                                   "Files with equal contents but different modification dates will appear as different.\n"
                                     "Useful for big directories or slow networks.") );
   
   OptionRadioButton* pTrustDateFallbackToBinary = new OptionRadioButton( i18n("Trust the size and date, but use binary comparison if date doesn't match (unsafe)"), false, "TrustDateFallbackToBinary", &m_bDmTrustDateFallbackToBinary, pBG, this );
   TQToolTip::add( pTrustDateFallbackToBinary, i18n("Assume that files are equal if the modification date and file length are equal.\n"
                                     "If the date isn't equal but the sizes are, use binary comparison.\n"
                                     "Useful for big directories or slow networks.") );

   OptionRadioButton* pTrustSize = new OptionRadioButton( i18n("Trust the size (unsafe)"), false, "TrustSize", &m_bDmTrustSize, pBG, this );
   TQToolTip::add( pTrustSize, i18n("Assume that files are equal if their file lengths are equal.\n"
                                   "Useful for big directories or slow networks when the date is modified during download.") );

   // Some two Dir-options: Affects only the default actions.
   OptionCheckBox* pSyncMode = new OptionCheckBox( i18n("Synchronize directories"), false,"SyncMode", &m_bDmSyncMode, page, this );
   gbox->addMultiCellWidget( pSyncMode, line, line, 0, 1 );
   TQToolTip::add( pSyncMode, i18n(
                  "Offers to store files in both directories so that\n"
                  "both directories are the same afterwards.\n"
                  "Works only when comparing two directories without specifying a destination."  ) );
   ++line;

   // Allow white-space only differences to be considered equal
   OptionCheckBox* pWhiteSpaceDiffsEqual = new OptionCheckBox( i18n("White space differences considered equal"), true,"WhiteSpaceEqual", &m_bDmWhiteSpaceEqual, page, this );
   gbox->addMultiCellWidget( pWhiteSpaceDiffsEqual, line, line, 0, 1 );
   TQToolTip::add( pWhiteSpaceDiffsEqual, i18n(
                  "If files differ only by white space consider them equal.\n"
                  "This is only active when full analysis is chosen."  ) );
   connect(pFullAnalysis, TQ_SIGNAL(toggled(bool)), pWhiteSpaceDiffsEqual, TQ_SLOT(setEnabled(bool)));
   pWhiteSpaceDiffsEqual->setEnabled(false);
   ++line;

   OptionCheckBox* pCopyNewer = new OptionCheckBox( i18n("Copy newer instead of merging (unsafe)"), false, "CopyNewer", &m_bDmCopyNewer, page, this );
   gbox->addMultiCellWidget( pCopyNewer, line, line, 0, 1 );
   TQToolTip::add( pCopyNewer, i18n(
                  "Don't look inside, just take the newer file.\n"
                  "(Use this only if you know what you are doing!)\n"
                  "Only effective when comparing two directories."  ) );
   ++line;

   OptionCheckBox* pCreateBakFiles = new OptionCheckBox( i18n("Backup files (.orig)"), true, "CreateBakFiles", &m_bDmCreateBakFiles, page, this );
   gbox->addMultiCellWidget( pCreateBakFiles, line, line, 0, 1 );
   TQToolTip::add( pCreateBakFiles, i18n(
                 "When a file would be saved over an old file, then the old file\n"
                 "will be renamed with a '.orig'-extension instead of being deleted."));
   ++line;

   topLayout->addStretch(10);
}
/*
static void insertCodecs(OptionComboBox* p)
{
   std::multimap<TQString,TQString> m;  // Using the multimap for case-insensitive sorting.
   int i;
   for(i=0;;++i)
   {
      TQTextCodec* pCodec = TQTextCodec::codecForIndex ( i );
      if ( pCodec != 0 )  m.insert( std::make_pair( TQString(pCodec->mimeName()).upper(), pCodec->mimeName()) );
      else                break;
   }
   
   p->insertItem( i18n("Auto"), 0 );
   std::multimap<TQString,TQString>::iterator mi;
   for(mi=m.begin(), i=0; mi!=m.end(); ++mi, ++i)
      p->insertItem(mi->second, i+1);
}
*/

// UTF8-Codec that saves a BOM
class Utf8BOMCodec : public TQTextCodec
{
   public:
   const char * name () const { return "UTF-8-BOM"; }
   int mibEnum () const { return 2123; }
   int heuristicContentMatch(const char*, int) const { return 0; }
   class UTF8BOMEncoder : public TQTextEncoder
   {
      bool bBOMAdded;
   public:
      UTF8BOMEncoder()  {  bBOMAdded=false;  }
      TQCString fromUnicode(const TQString& uc, int& lenInOut )
      {
         TQCString r;
         if (!bBOMAdded)
         {
            r += "\xEF\xBB\xBF";
            bBOMAdded=true;
         }
         r += uc.utf8();
         lenInOut = r.length();
         return r;
      }
   };
   TQTextEncoder* makeEncoder() const
   {
      return new UTF8BOMEncoder;
   }

   class UTF8BOMDecoder : public TQTextDecoder
   {
      TQTextDecoder *m_pDecoder;
   public:
      UTF8BOMDecoder() {   m_pDecoder = TQTextCodec::codecForName("UTF-8")->makeDecoder();  }
      ~UTF8BOMDecoder() {
         delete m_pDecoder;
      }
      TQString toUnicode( const char* p, int len)
      {
         return m_pDecoder->toUnicode( p, len );
      }
   };
   TQTextDecoder* makeDecoder() const
   {
      return new UTF8BOMDecoder;
   }
};

void OptionDialog::setupRegionalPage( void )
{
   new Utf8BOMCodec();

   TQFrame *page = addPage( i18n("Regional Settings"), i18n("Regional Settings"),
                           BarIcon("locale"/*"charset"*/, TDEIcon::SizeMedium ) );
   TQVBoxLayout *topLayout = new TQVBoxLayout( page, 5, spacingHint() );

   TQGridLayout *gbox = new TQGridLayout( 3, 2 );
   gbox->setColStretch(1,5);
   topLayout->addLayout( gbox );
   int line=0;

   TQLabel* label;

#ifdef KREPLACEMENTS_H

static char* countryMap[]={
"af Afrikaans",
"ar Arabic",
"az Azerbaijani",
"be Belarusian",
"bg Bulgarian",
"bn Bengali",
"bo Tibetan",
"br Breton",
"bs Bosnian",
"ca Catalan",
"cs Czech",
"cy Welsh",
"da Danish",
"de German",
"el Greek",
"en_GB British English",
"eo Esperanto",
"es Spanish",
"et Estonian",
"eu Basque",
"fa Farsi (Persian)",
"fi Finnish",
"fo Faroese",
"fr French",
"ga Irish Gaelic",
"gl Galician",
"gu Gujarati",
"he Hebrew",
"hi Hindi",
"hr Croatian",
"hsb Upper Sorbian",
"hu Hungarian",
"id Indonesian",
"is Icelandic",
"it Italian",
"ja Japanese",
"ka Georgian",
"ko Korean",
"ku Kurdish",
"lo Lao",
"lt Lithuanian",
"lv Latvian",
"mi Maori",
"mk Macedonian",
"mn Mongolian",
"ms Malay",
"mt Maltese",
"nb Norwegian Bookmal",
"nds Low Saxon",
"nl Dutch",
"nn Norwegian Nynorsk",
"nso Northern Sotho",
"oc Occitan",
"pl Polish",
"pt Portuguese",
"pt_BR Brazilian Portuguese",
"ro Romanian",
"ru Russian",
"rw Kinyarwanda",
"se Northern Sami",
"sk Slovak",
"sl Slovenian",
"sq Albanian",
"sr Serbian",
"sr@Latn Serbian",
"ss Swati",
"sv Swedish",
"ta Tamil",
"tg Tajik",
"th Thai",
"tr Turkish",
"uk Ukrainian",
"uz Uzbek",
"ven Venda",
"vi Vietnamese",
"wa Walloon",
"xh Xhosa",
"zh_CN Chinese Simplified",
"zh_TW Chinese Traditional",
"zu Zulu"
};

   label = new TQLabel( 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( "Auto", 0 );  // Must not translate, won't work otherwise!
   pLanguage->insertItem( "en_orig" );
      
   // Read directory: Find all kdiff3_*.qm-files and insert the found files here selection   
   FileAccess fa( getTranslationDir() );
   t_DirectoryList dirList;
   fa.listDir( &dirList, false, false, "kdiff3_*.qm", "", "*", false, false );
   t_DirectoryList::iterator i;
   for( i=dirList.begin(); i!=dirList.end(); ++i)
   {      
      TQString fileName = i->fileName();
      // Skip the "kdiff3_" and omit the .qm
      TQString languageId = fileName.mid(7, fileName.length()-10 );
      
      unsigned int countryIdx=0;
      for(countryIdx=0; countryIdx< sizeof(countryMap)/sizeof(countryMap[0]); ++countryIdx )
      {
         TQString fullName = countryMap[countryIdx];
         if ( languageId+" " == fullName.left(languageId.length()+1) )
         {
            languageId += " (" + fullName.mid(languageId.length()+1) + ")";
         }
      }
      
      pLanguage->insertItem( languageId );
   }
   
   TQToolTip::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;
/*
   label = new TQLabel( 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 );
   TQToolTip::add( label, i18n(
      "Choose the codec that should be used for your input files\n"
      "or \"Auto\" if unsure." ) 
      );
   ++line;
*/      
#endif

   m_pSameEncoding = new OptionCheckBox( i18n("Use the same encoding for everything:"), true, "SameEncoding", &m_bSameEncoding, page, this );
   gbox->addMultiCellWidget( m_pSameEncoding, line, line, 0, 1 );
   TQToolTip::add( m_pSameEncoding, i18n(
                  "Enable this allows to change all encodings by changing the first only.\n"
                  "Disable this if different individual settings are needed."
                  ) );
   ++line;

   label = new TQLabel( i18n("Note: Local Encoding is ") + "\"" + TQTextCodec::codecForLocale()->name() + "\"", page );
   gbox->addWidget( label, line, 0 );
   ++line;

   label = new TQLabel( i18n("File Encoding for A:"), page );
   gbox->addWidget( label, line, 0 );
   m_pEncodingAComboBox = new OptionEncodingComboBox( "EncodingForA", &m_pEncodingA, page, this );
   gbox->addWidget( m_pEncodingAComboBox, line, 1 );

   TQString autoDetectToolTip = i18n(
      "If enabled then Unicode (UTF-16 or UTF-8) encoding will be detected.\n"
      "If the file encoding is not detected then the selected encoding will be used as fallback.\n"
      "(Unicode detection depends on the first bytes of a file - the byte order mark \"BOM\".)"
      );
   m_pAutoDetectUnicodeA = new OptionCheckBox( i18n("Auto Detect Unicode"), true, "AutoDetectUnicodeA", &m_bAutoDetectUnicodeA, page, this );
   gbox->addWidget( m_pAutoDetectUnicodeA, line, 2 );
   TQToolTip::add( m_pAutoDetectUnicodeA, autoDetectToolTip );
   ++line;

   label = new TQLabel( i18n("File Encoding for B:"), page );
   gbox->addWidget( label, line, 0 );
   m_pEncodingBComboBox = new OptionEncodingComboBox( "EncodingForB", &m_pEncodingB, page, this );
   gbox->addWidget( m_pEncodingBComboBox, line, 1 );
   m_pAutoDetectUnicodeB = new OptionCheckBox( i18n("Auto Detect Unicode"), true, "AutoDetectUnicodeB", &m_bAutoDetectUnicodeB, page, this );
   gbox->addWidget( m_pAutoDetectUnicodeB, line, 2 );
   TQToolTip::add( m_pAutoDetectUnicodeB, autoDetectToolTip );
   ++line;

   label = new TQLabel( i18n("File Encoding for C:"), page );
   gbox->addWidget( label, line, 0 );
   m_pEncodingCComboBox = new OptionEncodingComboBox( "EncodingForC", &m_pEncodingC, page, this );
   gbox->addWidget( m_pEncodingCComboBox, line, 1 );
   m_pAutoDetectUnicodeC = new OptionCheckBox( i18n("Auto Detect Unicode"), true, "AutoDetectUnicodeC", &m_bAutoDetectUnicodeC, page, this );
   gbox->addWidget( m_pAutoDetectUnicodeC, line, 2 );
   TQToolTip::add( m_pAutoDetectUnicodeC, autoDetectToolTip );
   ++line;

   label = new TQLabel( i18n("File Encoding for Merge Output and Saving:"), page );
   gbox->addWidget( label, line, 0 );
   m_pEncodingOutComboBox = new OptionEncodingComboBox( "EncodingForOutput", &m_pEncodingOut, page, this );
   gbox->addWidget( m_pEncodingOutComboBox, line, 1 );
   m_pAutoSelectOutEncoding = new OptionCheckBox( i18n("Auto Select"), true, "AutoSelectOutEncoding", &m_bAutoSelectOutEncoding, page, this );
   gbox->addWidget( m_pAutoSelectOutEncoding, line, 2 );
   TQToolTip::add( m_pAutoSelectOutEncoding, i18n(
      "If enabled then the encoding from the input files is used.\n"
      "In ambiguous cases a dialog will ask the user to choose the encoding for saving."
      ) );
   ++line;
   label = new TQLabel( i18n("File Encoding for Preprocessor Files:"), page );
   gbox->addWidget( label, line, 0 );
   m_pEncodingPPComboBox = new OptionEncodingComboBox( "EncodingForPP", &m_pEncodingPP, page, this );
   gbox->addWidget( m_pEncodingPPComboBox, line, 1 );   
   ++line;

   connect(m_pSameEncoding, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotEncodingChanged()));
   connect(m_pEncodingAComboBox, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotEncodingChanged()));
   connect(m_pAutoDetectUnicodeA, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotEncodingChanged()));
   connect(m_pAutoSelectOutEncoding, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotEncodingChanged()));

   OptionCheckBox* pRightToLeftLanguage = new OptionCheckBox( i18n("Right To Left Language"), false, "RightToLeftLanguage", &m_bRightToLeftLanguage, page, this );
   gbox->addMultiCellWidget( pRightToLeftLanguage, line, line, 0, 1 );
   TQToolTip::add( pRightToLeftLanguage, i18n(
                 "Some languages are read from right to left.\n"
                 "This setting will change the viewer and editor accordingly."));
   ++line;   


   topLayout->addStretch(10);
}

#ifdef _WIN32
#include "ccInstHelper.cpp"
#endif

void OptionDialog::setupIntegrationPage( void )
{
   TQFrame *page = addPage( i18n("Integration"), i18n("Integration Settings"),
                           BarIcon("launch"/*"charset"*/, TDEIcon::SizeMedium ) );
   TQVBoxLayout *topLayout = new TQVBoxLayout( page, 5, spacingHint() );

   TQGridLayout *gbox = new TQGridLayout( 3, 3 );
   gbox->setColStretch(2,5);
   topLayout->addLayout( gbox );
   int line=0;

   TQLabel* label;
   label = new TQLabel( i18n("Command line options to ignore:"), page );
   gbox->addWidget( label, line, 0 );
   OptionLineEdit* pIgnorableCmdLineOptions = new OptionLineEdit( "-u;-query;-html;-abort", "IgnorableCmdLineOptions", &m_ignorableCmdLineOptions, page, this );
   gbox->addMultiCellWidget( pIgnorableCmdLineOptions, line, line, 1,2 );
   TQToolTip::add( label, i18n(
      "List of command line options that should be ignored when KDiff3 is used by other tools.\n"
      "Several values can be specified if separated via ';'\n"
      "This will suppress the \"Unknown option\"-error."
      ));
   ++line;

#ifdef _WIN32
   TQPushButton* pIntegrateWithClearCase = new TQPushButton( i18n("Integrate with ClearCase"), page);
   gbox->addWidget( pIntegrateWithClearCase, line, 0 );
   TQToolTip::add( pIntegrateWithClearCase, i18n(
                 "Integrate with Rational ClearCase from IBM.\n"
                 "Modifies the \"map\" file in ClearCase-subdir \"lib/mgrs\"\n"
                 "(Only enabled when ClearCase \"bin\" directory is in the path.)"));
   connect(pIntegrateWithClearCase, TQ_SIGNAL(clicked()),this, TQ_SLOT(slotIntegrateWithClearCase()) );
   pIntegrateWithClearCase->setEnabled( integrateWithClearCase( "existsClearCase", "" )!=0 );

   TQPushButton* pRemoveClearCaseIntegration = new TQPushButton( i18n("Remove ClearCase Integration"), page);
   gbox->addWidget( pRemoveClearCaseIntegration, line, 1 );
   TQToolTip::add( pRemoveClearCaseIntegration, i18n(
                 "Restore the old \"map\" file from before doing the Clearcase integration."));
   connect(pRemoveClearCaseIntegration, TQ_SIGNAL(clicked()),this, TQ_SLOT(slotRemoveClearCaseIntegration()) );
   pRemoveClearCaseIntegration->setEnabled( integrateWithClearCase( "existsClearCase", "" )!=0 );

   ++line;
#endif

   topLayout->addStretch(10);
}

void OptionDialog::slotIntegrateWithClearCase()
{
#ifdef _WIN32
   char kdiff3CommandPath[1000];
   GetModuleFileNameA( 0, kdiff3CommandPath, sizeof(kdiff3CommandPath)-1 );
   integrateWithClearCase( "install", kdiff3CommandPath );
#endif
}

void OptionDialog::slotRemoveClearCaseIntegration()
{
#ifdef _WIN32
   char kdiff3CommandPath[1000];
   GetModuleFileNameA( 0, kdiff3CommandPath, sizeof(kdiff3CommandPath)-1 );
   integrateWithClearCase( "uninstall", kdiff3CommandPath );
#endif
}

void OptionDialog::slotEncodingChanged()
{
   if ( m_pSameEncoding->isChecked() )
   {
      m_pEncodingBComboBox->setEnabled( false );
      m_pEncodingBComboBox->setCurrentItem( m_pEncodingAComboBox->currentItem() );
      m_pEncodingCComboBox->setEnabled( false );
      m_pEncodingCComboBox->setCurrentItem( m_pEncodingAComboBox->currentItem() );
      m_pEncodingOutComboBox->setEnabled( false );
      m_pEncodingOutComboBox->setCurrentItem( m_pEncodingAComboBox->currentItem() );
      m_pEncodingPPComboBox->setEnabled( false );
      m_pEncodingPPComboBox->setCurrentItem( m_pEncodingAComboBox->currentItem() );
      m_pAutoDetectUnicodeB->setEnabled( false );
      m_pAutoDetectUnicodeB->setChecked( m_pAutoDetectUnicodeA->isChecked() );
      m_pAutoDetectUnicodeC->setEnabled( false );
      m_pAutoDetectUnicodeC->setChecked( m_pAutoDetectUnicodeA->isChecked() );
      m_pAutoSelectOutEncoding->setEnabled( false );
      m_pAutoSelectOutEncoding->setChecked( m_pAutoDetectUnicodeA->isChecked() );
   }
   else
   {
      m_pEncodingBComboBox->setEnabled( true );
      m_pEncodingCComboBox->setEnabled( true );
      m_pEncodingOutComboBox->setEnabled( true );
      m_pEncodingPPComboBox->setEnabled( true );
      m_pAutoDetectUnicodeB->setEnabled( true );
      m_pAutoDetectUnicodeC->setEnabled( true );
      m_pAutoSelectOutEncoding->setEnabled( true );
      m_pEncodingOutComboBox->setEnabled( !m_pAutoSelectOutEncoding->isChecked() );
   }
}

void OptionDialog::setupKeysPage( void )
{
   //TQVBox *page = addVBoxPage( i18n("Keys"), i18n("KeyDialog" ),
   //                          BarIcon("fonts", TDEIcon::SizeMedium ) );

   //TQVBoxLayout *topLayout = new TQVBoxLayout( page, 0, spacingHint() );
    //           new TDEFontChooser( page,"font",false/*onlyFixed*/,TQStringList(),false,6 );
   //m_pKeyDialog=new KKeyDialog( false, 0 );
   //topLayout->addWidget( m_pKeyDialog );
}

void OptionDialog::slotOk( void )
{
   slotApply();

   // My system returns variable width fonts even though I
   // disabled this. Even TQFont::fixedPitch() doesn't work.
   TQFontMetrics fm(m_font);
   if ( fm.width('W')!=fm.width('i') )
   {
      int result = KMessageBox::warningYesNo(this, i18n(
         "You selected a variable width font.\n\n"
         "Because this program doesn't handle variable width fonts\n"
         "correctly, you might experience problems while editing.\n\n"
         "Do you want to continue or do you want to select another font."),
         i18n("Incompatible Font"),
         i18n("Continue at Own Risk"), i18n("Select Another Font"));
      if (result==KMessageBox::No)
         return;
   }

   accept();
}


/** Copy the values from the widgets to the public variables.*/
void OptionDialog::slotApply( void )
{
   std::list<OptionItem*>::iterator i;
   for(i=m_optionItemList.begin(); i!=m_optionItemList.end(); ++i)
   {
      (*i)->apply();
   }

   emit applyClicked();   

#ifdef _WIN32
   TQString locale = m_language;
   if ( locale == "Auto" || locale.isEmpty() )
      locale = locale = TQTextCodec::locale();
   int spacePos = locale.find(' ');
   if (spacePos>0) locale = locale.left(spacePos);
   TQSettings settings;
   settings.setPath("KDiff3", "diff-ext", TQSettings::User );
   settings.writeEntry( "Language", locale );
#endif
}

/** Set the default values in the widgets only, while the
    public variables remain unchanged. */
void OptionDialog::slotDefault()
{
   int result = KMessageBox::warningContinueCancel(this, i18n("This resets all options. Not only those of the current topic.") );
   if ( result==KMessageBox::Cancel ) return;
   else resetToDefaults();
}

void OptionDialog::resetToDefaults()
{
   std::list<OptionItem*>::iterator i;
   for(i=m_optionItemList.begin(); i!=m_optionItemList.end(); ++i)
   {
      (*i)->setToDefault();
   }

   slotEncodingChanged();
}

/** Initialise the widgets using the values in the public varibles. */
void OptionDialog::setState()
{
   std::list<OptionItem*>::iterator i;
   for(i=m_optionItemList.begin(); i!=m_optionItemList.end(); ++i)
   {
      (*i)->setToCurrent();
   }

   slotEncodingChanged();
}

class ConfigValueMap : public ValueMap
{
private:
   TDEConfig* m_pConfig;
public:
   ConfigValueMap( TDEConfig* pConfig ) { m_pConfig = pConfig; }

   void writeEntry(const TQString& s, const TQFont&  v ){ m_pConfig->writeEntry(s,v); }
   void writeEntry(const TQString& s, const TQColor& v ){ m_pConfig->writeEntry(s,v); }
   void writeEntry(const TQString& s, const TQSize&  v ){ m_pConfig->writeEntry(s,v); }
   void writeEntry(const TQString& s, const TQPoint& v ){ m_pConfig->writeEntry(s,v); }
   void writeEntry(const TQString& s, int v )          { m_pConfig->writeEntry(s,v); }
   void writeEntry(const TQString& s, bool v )         { m_pConfig->writeEntry(s,v); }
   void writeEntry(const TQString& s, const TQStringList& v, char separator ){ m_pConfig->writeEntry(s,v,separator); }
   void writeEntry(const TQString& s, const TQString& v ){ m_pConfig->writeEntry(s,v); }
   void writeEntry(const TQString& s, const char* v )   { m_pConfig->writeEntry(s,v); }

   TQFont       readFontEntry (const TQString& s, TQFont* defaultVal ) { return m_pConfig->readFontEntry(s,defaultVal); }
   TQColor      readColorEntry(const TQString& s, TQColor* defaultVal ){ return m_pConfig->readColorEntry(s,defaultVal); }
   TQSize       readSizeEntry (const TQString& s, TQSize* defaultVal ) { return m_pConfig->readSizeEntry(s,defaultVal); }
   TQPoint      readPointEntry(const TQString& s, TQPoint* defaultVal) { return m_pConfig->readPointEntry(s,defaultVal); }
   bool        readBoolEntry (const TQString& s, bool defaultVal )   { return m_pConfig->readBoolEntry(s,defaultVal); }
   int         readNumEntry  (const TQString& s, int defaultVal )    { return m_pConfig->readNumEntry(s,defaultVal); }
   TQStringList readListEntry (const TQString& s, const TQStringList& def, char separator )    { return m_pConfig->readListEntry(s.latin1(),def,separator); }
   TQString     readEntry     (const TQString& s, const TQString& defaultVal){ return m_pConfig->readEntry(s,defaultVal); }
};

void OptionDialog::saveOptions( TDEConfig* config )
{
   // No i18n()-Translations here!

   config->setGroup("KDiff3 Options");

   ConfigValueMap cvm(config);
   std::list<OptionItem*>::iterator i;
   for(i=m_optionItemList.begin(); i!=m_optionItemList.end(); ++i)
   {
      (*i)->write(&cvm);
   }
}

void OptionDialog::readOptions( TDEConfig* config )
{
   // No i18n()-Translations here!

   config->setGroup("KDiff3 Options");

   ConfigValueMap cvm(config);
   std::list<OptionItem*>::iterator i;
   for(i=m_optionItemList.begin(); i!=m_optionItemList.end(); ++i)
   {
      (*i)->read(&cvm);
   }

   setState();
}

void OptionDialog::slotHelp( void )
{
   KDialogBase::slotHelp();
}

TQString OptionDialog::parseOptions( const QCStringList& optionList )
{
   TQString result;
   QCStringList::const_iterator i;
   for ( i=optionList.begin(); i!=optionList.end(); ++i )
   {
      TQString s = *i;

      int pos = s.find('=');
      if( pos > 0 )                     // seems not to have a tag
      {
         TQString key = s.left(pos);
         TQString val = s.mid(pos+1);
         std::list<OptionItem*>::iterator j;
         bool bFound = false;
         for(j=m_optionItemList.begin(); j!=m_optionItemList.end(); ++j)
         {
            if ( (*j)->getSaveName()==key )
            {
               ValueMap config;
               config.writeEntry( key, val );  // Write the value as a string and
               (*j)->read(&config);       // use the internal conversion from string to the needed value.
               bFound = true;
               break;
            }
         }
         if ( ! bFound )
         {
            result += "No config item named \"" + key + "\"\n";
         }
      }
      else
      {
         result += "No '=' found in \"" + s + "\"\n";
      }
   }
   return result;
}

TQString OptionDialog::calcOptionHelp()
{
   ValueMap config;
   std::list<OptionItem*>::iterator j;
   for(j=m_optionItemList.begin(); j!=m_optionItemList.end(); ++j)
   {
      (*j)->write( &config );
   }
   return config.getAsString();
}

void OptionDialog::slotHistoryMergeRegExpTester()
{
   RegExpTester dlg(this, s_autoMergeRegExpToolTip, s_historyStartRegExpToolTip, 
                          s_historyEntryStartRegExpToolTip, s_historyEntryStartSortKeyOrderToolTip );
   dlg.init(m_pAutoMergeRegExpLineEdit->currentText(), m_pHistoryStartRegExpLineEdit->currentText(), 
            m_pHistoryEntryStartRegExpLineEdit->currentText(), m_pHistorySortKeyOrderLineEdit->currentText());
   if ( dlg.exec() )
   {
      m_pAutoMergeRegExpLineEdit->setCurrentText( dlg.autoMergeRegExp() );
      m_pHistoryStartRegExpLineEdit->setCurrentText( dlg.historyStartRegExp() );
      m_pHistoryEntryStartRegExpLineEdit->setCurrentText( dlg.historyEntryStartRegExp() );
      m_pHistorySortKeyOrderLineEdit->setCurrentText( dlg.historySortKeyOrder() );
   }
}


#include "optiondialog.moc"
