Logo Search packages:      
Sourcecode: valknut version File versions  Download package

dcchat.cpp

/***************************************************************************
                          dcchat.cpp  -  description
                             -------------------
    begin                : Don Mär 28 2002
    copyright            : (C) 2002 by Mathias Küster
    email                : mathen@users.berlios.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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <qdatetime.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qclipboard.h>
#include <qapplication.h>
#include <qmessagebox.h>
#include <qimage.h>
#include <qregexp.h>
#include <qpopupmenu.h>
#include <qcursor.h>
#include <qcombobox.h>
#include <qlayout.h>
#include <qprocess.h>
#include <qglobal.h>
#include <qstatusbar.h>
#include <qtooltip.h>
#include <qfile.h>
#include <qfiledialog.h>
#include <qsplitter.h>
#include <qinputdialog.h>
#include <qtabwidget.h>

#include <dcgui.h>
#include <dcevent.h>
#include <dcclient.h>
#include <dcmenuhandler.h>
#include <dcconfig.h>
#include <dctranslator.h>
#include <cdialogpicturemap.h>
#include <dcfiletool.h>
#include <dchublistmanager.h>
#include <dcconnectionmanager.h>
#include <dcuserslist.h>
#include <dcqtextedit.h>
#include <dciconloader.h>

#include "dcchat.h"
#include "dchubsearch.h"

#include <dclib/cfilemanager.h>
#include <dclib/dcos.h>
#include <dclib/cutils.h>
#include <dclib/core/cbase64.h>
#include <dclib/core/cdir.h>
#include <dclib/core/cfile.h>
#include <dclib/dclib.h>
#include <dclib/clistenmanager.h>

/** the link list*/
const char * p_LinkList[] = {
      "HTTP://",
      "HTTPS://",
      "NEWS://",
      "FILE://",
      "WWW.",
      "FTP://",
      "FTP.",
      "HKP://",
      "LDAP://",
      "DCFILE://",
      "DCHUB://",
      "DCHUBS://",      
      "DCCMD://",
      "MAGNET:",
      NULL
};

#define MAX_HISTORY_COUNT 25

/** */
DCChat::DCChat( QWidget * parent, const char *name, int wflags, DCClient * client, bool bprivate ) : DCDialogChat(parent, name, wflags)
{
      ASSERT(client);

      // set default icon
      setIcon( g_pIconLoader->GetPixmap(eiGLOBE) );

      m_pParent      = parent;
      m_bPrivateChat = bprivate;
      m_pClient      = client;
      m_bSendAway    = TRUE;
      m_eSecureState = esecsNONE;
      m_pCurrentHistory = 0;

      m_sTimeStamp  = QDate::currentDate().toString("yyyyMMdd").ascii();
      m_sTimeStamp += "-";
      m_sTimeStamp += QTime::currentTime().toString("hhmmss").ascii();

      m_nTabStart   = -1;
      m_nTabEnd     = -1;
      m_nTabPressed = 0;
      m_sTabSaved   = "";
      m_sTabNick    = "";
      m_bFirstInit  = TRUE;
      
      InitDocument();
}

/** */
DCChat::~DCChat()
{
}

/** */
void DCChat::InitDocument()
{
      int i;

      m_pStatusBar = new QStatusBar(this);
      m_pStatusBar->setSizeGripEnabled(FALSE);
      DCDialogChatLayout->addWidget( m_pStatusBar, 1, 0 );
      m_pStatusCrypt = new QLabel(m_pStatusBar);
      m_pStatusBar->addWidget(m_pStatusCrypt);

      SetCrypt(esecsNONE);

      if ( !m_bPrivateChat )
      {
            m_pStatusBar->hide();
      }
      else
      {
            m_pStatusBar->show();
      }

/*    if ( g_pConfig->ShowChatStatusBar() == FALSE )
      {
            m_pStatusBar->hide();
      }
*/
      if ( g_pConfig->GetShowChatSendButton() )
      {
            connect( PushButton_SEND, SIGNAL(clicked()), this, SLOT(slotSendMessage()) );
            slotTextChangedChatInput();
      }
      else
      {
            // remove send button and recreate layout
            delete PushButton_SEND;
            PushButton_SEND = NULL;
            delete Frame_SEND->layout();
            QGridLayout * gl = new QGridLayout( Frame_SEND, 1, 1, 1, 1, "");
            gl->addWidget( TextEdit_CHATINPUT, 0, 0 );
      }

      m_pTextEdit_CHATOUTPUT = new DCQTextEdit( Frame_OUTPUT, "TextEdit_CHATOUTPUT" );
      m_pTextEdit_CHATOUTPUT->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 0, 0, m_pTextEdit_CHATOUTPUT->sizePolicy().hasHeightForWidth() ) );
      m_pTextEdit_CHATOUTPUT->setMinimumSize( QSize( 0, 60 ) );
      m_pTextEdit_CHATOUTPUT->setTextFormat( QTextEdit::RichText );
      m_pTextEdit_CHATOUTPUT->setWordWrap( QTextEdit::WidgetWidth );
      m_pTextEdit_CHATOUTPUT->setWrapPolicy( QTextEdit::AtWhiteSpace );
      m_pTextEdit_CHATOUTPUT->setReadOnly( TRUE );
      Frame_OUTPUTLayout->addWidget(m_pTextEdit_CHATOUTPUT,0,0);

      connect( m_pTextEdit_CHATOUTPUT, SIGNAL(rightButtonClicked( const QPoint& )), this, SLOT(slotRightButtonClickedChatOutput( const QPoint& )) );
#if QT_VERSION >= 0x030100
      connect( m_pTextEdit_CHATOUTPUT, SIGNAL(clicked( int, int )), this, SLOT(slotClickedChatOutput( int, int )) );
#endif
      if ( PushButton_SEND )
      {
            connect( TextEdit_CHATINPUT, SIGNAL(textChanged()), this, SLOT(slotTextChangedChatInput()) );
      }

      installEventFilter(this);

      m_pTextEdit_CHATOUTPUT->installEventFilter(this);
      TextEdit_CHATINPUT->installEventFilter(this);
      TextEdit_CHATINPUT->setFocus();
}

/** event filter */
bool DCChat::eventFilter( QObject * object, QEvent * event )
{
      if ((event->type() == QEvent::KeyPress)&&((QTextEdit*)object==TextEdit_CHATINPUT))
      {
            QKeyEvent * e = (QKeyEvent*)event;

            bool send = FALSE;
            if ( e->state() == AltButton )
            {
                  if ( (e->key() == Key_S) && (g_pConfig->GetSendChat() == tr("Alt + S").ascii()) )
                  {
                        send = TRUE;
                  }
                  else if( ((e->key() == Key_Enter) || (e->key() == Key_Return )) &&
                           (g_pConfig->GetSendChat() == tr("Alt + Enter").ascii()))
                  {
                        send = TRUE;
                  }
            }
            else if( (g_pConfig->GetSendChat() == tr("Ctrl + Enter").ascii()) &&
                   (e->state() == ControlButton) && ( e->key() == Key_Enter || e->key() == Key_Return) )
            {
                  send = TRUE;
            }
            else if( (g_pConfig->GetSendChat() == tr("Enter").ascii() && (e->state() != ControlButton) &&
                   ( e->key() == Key_Enter || e->key() == Key_Return)) )
            {
                  send = TRUE;
            }

            if( send == TRUE )
            {
                  SendMessage();
                  e->accept();
                  return true;
            }
            else if ( e->state() == ControlButton )
            {
                  CString * ps = 0;

                  // check for history
                  if ( (e->key() == Key_Down) && (m_pCurrentHistory != 0) )
                  {
                        ps = m_History.Next(m_pCurrentHistory);

                  }
                  else if ( e->key() == Key_Up )
                  {
                        ps = m_History.Forw(m_pCurrentHistory);

                        if ( m_pCurrentHistory == 0 )
                        {
                              // save current text
                              m_sHistoryTempString = TextEdit_CHATINPUT->text().ascii();
                              // save current cursor position
                              TextEdit_CHATINPUT->getCursorPosition( &m_nHistoryTempPara, &m_nHistoryTempIndex );
                        }
                  }

                  if ( ps != 0 )
                  {
                        m_pCurrentHistory = ps;
                        TextEdit_CHATINPUT->setText(m_pCurrentHistory->Data());
                  }
                  else if (e->key() == Key_Down)
                  {
                        m_pCurrentHistory = ps;
                        TextEdit_CHATINPUT->setText(m_sHistoryTempString.Data());
                        TextEdit_CHATINPUT->setCursorPosition( m_nHistoryTempPara, m_nHistoryTempIndex );
                  }
            }

            if ( e->key() == Key_Tab )
            {
                  NickCompletion();
                  e->accept();
                  return true;
            }
            else if ( m_nTabPressed != 0 )
            {
                  // reset tab settings
                  m_nTabStart   = -1;
                  m_nTabEnd     = -1;
                  m_nTabPressed = 0;
                  m_sTabSaved   = "";
                  //m_sTabNick    = "";
            }
      }
      else if ( event->type() == EVENT_TRANSLATION )
      {
            DC_TranslationEvent *e = (DC_TranslationEvent*)event;

            if ( e->m_bTranslate == TRUE )
            {
                  AddStatus( (tr("Translation: ") + "'" + e->m_sOriginal + "' -> '" + e->m_sTranslation + "'").ascii() );
            }
            else
            {
                  AddStatus( (tr("Translation failed: ") + "'" + e->m_sOriginal + "'").ascii() );
            }
      }
      else if ( (event->type() == QEvent::Resize) && (object == m_pTextEdit_CHATOUTPUT) )
      {
            bool bscroll, b;

            if ( m_pTextEdit_CHATOUTPUT->verticalScrollBar()->maxValue() == m_pTextEdit_CHATOUTPUT->verticalScrollBar()->value() )
            {
                  bscroll = TRUE;
            }
            else
            {
                  bscroll = FALSE;
            }

            b = QWidget::eventFilter( object, event );

            if ( bscroll )
            {
                  m_pTextEdit_CHATOUTPUT->scrollToBottom();
                  m_pTextEdit_CHATOUTPUT->moveCursor( QTextEdit::MoveEnd, FALSE );
            }
            
            return b;
      }

      return QWidget::eventFilter( object, event );    // standard event processing
}

/** */
void DCChat::AddHistory( CString message )
{
      CString *ps;

      if ( m_History.Count() == MAX_HISTORY_COUNT )
      {
            ps = m_History.Next(0);
            m_History.Del(ps);
      }

      m_pCurrentHistory = 0;
      m_History.Add(new CString(message));
}

/** */
void DCChat::SetCrypt( eSecureState e )
{
      if ( e == esecsENCRYPTED )
      {
            QToolTip::remove(m_pStatusCrypt);
            QToolTip::add(m_pStatusCrypt, tr("Line is encrypted."));
            m_pStatusCrypt->setPixmap( g_pIconLoader->GetPixmap(eiSSL_YES) );
      }
      else
      {
            QToolTip::remove(m_pStatusCrypt);
            QToolTip::add(m_pStatusCrypt, tr("Line is not encrypted."));
            m_pStatusCrypt->setPixmap( g_pIconLoader->GetPixmap(eiSSL_NO) );
      }

      m_eSecureState = e;
}

/** */
void DCChat::slotTextChangedChatInput()
{
      if ( PushButton_SEND )
      {
            if ( TextEdit_CHATINPUT->text() != "" )
            {
                  PushButton_SEND->setEnabled(TRUE);
            }
            else
            {
                  PushButton_SEND->setEnabled(FALSE);
            }
      }
}

/** */
void DCChat::slotClickedChatOutput( int, int )
{
      int i;
      CString pressedLink;
      QPoint p;
      int x,y;
      DCFileTool filetool;

      p = m_pTextEdit_CHATOUTPUT->mapFromGlobal(QCursor::pos());
      m_pTextEdit_CHATOUTPUT->viewportToContents(p.x(),p.y(),x,y);
      p.setX(x);
      p.setY(y);
      pressedLink = m_pTextEdit_CHATOUTPUT->anchorAt(p).ascii();

//    printf("%s\n",pressedLink.ascii());

      for(i=0;p_LinkList[i]!=0;i++)
      {
            if ( pressedLink.Left(CString(p_LinkList[i]).Length()).ToUpper() == p_LinkList[i] )
            {
                  if ( p_LinkList[i] == CString("DCFILE://") )
                  {
                        // DC-File-Link
                        QPopupMenu *m;
                        int id;
                        CString hubhost,hubname,nick,file;
                        ulonglong size;

                        if ( CUtils::ConvertDCLink( pressedLink, hubhost, hubname, nick, size, file ) == FALSE )
                        {
                              return;
                        }

                        m = new QPopupMenu(this);

                        DCMenuHandler::InsertMenu( m, emiDOWNLOAD );
                        DCMenuHandler::InsertMenu( m, emiDOWNLOAD_TO );
                        DCMenuHandler::InsertMenu( m, emiDOWNLOAD_AS );
                        DCMenuHandler::InsertMenu( m, emiDOWNLOAD_IN );

                        id = m->exec(QCursor::pos());

                        delete m;

                        if ( (id == emiDOWNLOAD) || (id == emiDOWNLOAD_AS) || (id == emiDOWNLOAD_TO) )
                        {
                              QString localrootpath = "";
                              QString localname = "";

                              // select downloadfolder for all selected files
                              if ( id == emiDOWNLOAD_TO )
                              {
                                    localrootpath = QFileDialog::getExistingDirectory( "", this, "bdf", tr("Select download folder"), TRUE );

                                    if ( localrootpath == "" )
                                          return;
                              }

                              CDir d;
                              d.SetPath(file);
                              QFileInfo fi(d.DirName().Data());
                              localname = fi.fileName();

                              if ( id == emiDOWNLOAD_AS )
                              {
                                    localrootpath = QFileDialog::getSaveFileName( "", "", this, "bdf", tr("Select file for")+" "+localname );

                                    if ( localrootpath == "" )
                                          return;

                                    QFileInfo fi(localrootpath);
                                    localrootpath = fi.dirPath();
                                    localname     = fi.fileName();

                                    if ( (localrootpath=="") || (localname=="") )
                                          return;
                              }

                              // add transfer to the waitlist
                              filetool.CheckFile( nick, hubname, hubhost,
                                          file, localname.ascii(), "", localrootpath.ascii(), eltFILE,
                                          size, "" );
                        }
                        else if ( id == emiDOWNLOAD_IN )
                        {
                              QString localrootpath;
                              QString localname;
                              QString localpath;

                              if ( filetool.SelectFileSource( size, localname, localrootpath, localpath ) == FALSE )
                              {
                                    return;
                              }

                              // add transfer to the waitlist
                              filetool.CheckFile( nick, hubname, hubhost,
                                            file, localname.ascii(), localpath.ascii(), localrootpath.ascii(), eltFILE,
                                          size, "", TRUE);
                        }
                  }
                  else if ( p_LinkList[i] == CString("DCHUB://") )
                  {
                        pressedLink = pressedLink.Right( pressedLink.Length()-8 );
                        // remove all '/' chars
                        pressedLink = pressedLink.Replace('/',"");

                        g_pConnectionManager->Connect( pressedLink, pressedLink );
                  }
                  else if ( p_LinkList[i] == CString("DCHUBS://") )
                  {
                        pressedLink = pressedLink.Right( pressedLink.Length()-8 );
                        // remove all '/' chars
                        pressedLink = pressedLink.Replace('/',"");

                        g_pConnectionManager->Connect( pressedLink, pressedLink, TRUE );
                  }
                  else if ( p_LinkList[i] == CString("DCCMD://") )
                  {
                        pressedLink = pressedLink.Right( pressedLink.Length()-8 );
                  }
                  else if ( p_LinkList[i] == CString("MAGNET:") )
                  {
                        //magnet:?xt=urn:tree:tiger:EOSA5AGTL5SD3VWCF3R2OH2WMGXV3S3R7SYN4YA&xl=708780032&dn=FC-6-i386-disc1.iso
                        // TTHs are always 39 characters long
                        QPopupMenu *m = new QPopupMenu(this);
                        int id, searchID, copyID, lookupID, i;
                        QString tth;
                        
                        i = pressedLink.Find("xt=urn:tree:tiger:");
                        if (i == -1)
                        {
                              i = pressedLink.Find("xt.1=urn:tree:tiger:");
                              tth = pressedLink.Mid(i + 20, 39).Data();
                        }
                        else
                        {
                              tth = pressedLink.Mid(i + 18, 39).Data();
                        }
                        
                        searchID = m->insertItem( QIconSet(g_pIconLoader->GetPixmap(eiFILEFIND)), QObject::tr("Search by TTH") );
                        m->setItemEnabled(searchID, TRUE);
                        copyID = m->insertItem( QIconSet(g_pIconLoader->GetPixmap(eiEDITCOPY)), QObject::tr("Copy TTH to clipboard") );
                        m->setItemEnabled(copyID, TRUE);
                        lookupID = m->insertItem( QIconSet(g_pIconLoader->GetPixmap(eiFILEFIND)), QObject::tr("Look up TTH at Bitzi.com") );
                        m->setItemEnabled(lookupID, TRUE);
                        
                        id = m->exec(QCursor::pos());
                        
                        delete m;
                        
                        if (id == searchID)
                        {
                              g_pHubSearch->Combobox_SEARCH->setEditText(tth);
                              g_pHubSearch->LineEdit_SEARCHSIZE->setText("0");
                              g_pHubSearch->ComboBox_SEARCHTYPE->setCurrentItem(9);
                              g_pHubSearch->ComboBox_SEARCHUNIT->setCurrentItem(0);
                              g_pHubSearch->ComboBox_SEARCHLIMIT->setCurrentItem(0);
            
                              if ( g_pHubSearch->isMinimized() )
                              {
                                    g_pHubSearch->showNormal();
                              }
                              else if ( g_pHubSearch->isVisible()==FALSE )
                              {
                                    g_pHubSearch->setEnabled(TRUE);
                                    g_pHubSearch->show();
                              }

                              if ( g_pHubSearch->TabWidget_HUBSEARCH->isVisible()==FALSE )
                              {
                                    g_pHubSearch->TabWidget_HUBSEARCH->show();
                              }
                              
                              // put search dialog above chat
                              g_pHubSearch->raise();
                              g_pHubSearch->setActiveWindow();
                        }
                        else if (id == copyID)
                        {
                              QApplication::clipboard()->setText(tth);
                        }
                        else if (id == lookupID)
                        {
                              // http://bitzi.com/lookup/tree:tiger:PKQRUF7BKROIPCX2XWTJ7XUKRXRPUMW5V6REAMY
                              if ( g_pConfig->GetBrowser() != "" )
                              {
                                    QProcess * pr = new QProcess();
                                    QByteArray buf;
                                    pr->addArgument(g_pConfig->GetBrowser().Data());
                                    pr->addArgument("http://bitzi.com/lookup/tree:tiger:" + tth);
                                    pr->launch(buf);
                                    delete pr;
                              }
                        }
                        
                  }
                  else if ( g_pConfig->GetBrowser() != "" )
                  {
                        QProcess * pr = new QProcess();
                        QByteArray buf;
                        pr->addArgument(g_pConfig->GetBrowser().Data());
                        pr->addArgument(pressedLink.Data());
                        pr->launch(buf);
                        delete pr;
                  }
            }
      }
}

/** */
void DCChat::slotRightButtonClickedChatOutput( const QPoint& )
{
      int para;
      QString pressedPara, pressedNick, userCommand;
      CString cPressedNick;
      QPoint p;
      int x,y, nickStart, nickLen;
      int id;
      bool isNickOnline;
      QPopupMenu *m,*muser,*mslot;
      QString s;  
      CList<DC_UserMenuCommand> usercommands;
      DC_UserMenuCommand * umc = 0;
      
      // get the paragraph of text where the right click was
      p = m_pTextEdit_CHATOUTPUT->mapFromGlobal(QCursor::pos());
      m_pTextEdit_CHATOUTPUT->viewportToContents(p.x(),p.y(),x,y);
      p.setX(x);
      p.setY(y);
      para = m_pTextEdit_CHATOUTPUT->paragraphAt(p);
      pressedPara = m_pTextEdit_CHATOUTPUT->text(para);
      
      // cut out the nick
      nickStart = 4 + pressedPara.find("&lt;");
      nickLen = pressedPara.find("&gt;") - nickStart;
      
      // sanity check
      if ( (nickStart == 3) || (nickLen < 0) )
      {
            if (m_bPrivateChat)
            {
                  pressedNick = QString(m_sNick.Data());
            }
            else
            {
                  pressedNick = "Unknown";
            }
      }
      else
      {
            pressedNick = pressedPara.mid(nickStart, nickLen);
      }
      
      // check for joins / parts message
      if ( pressedNick == "VALKNUT" )
      {
            int lenJoin = QString(tr("Joins: ")).length();
            int lenPart = QString(tr("Parts: ")).length();
            int joinPos = pressedPara.find(tr("Joins: "));
            int partPos = pressedPara.find(tr("Parts: "));
            
            if ( joinPos == -1 )
            {
                  nickStart = lenPart + partPos;
            }
            else
            {
                  nickStart = lenJoin + joinPos;      
            }
            
            if ( (joinPos != -1) || (partPos != -1) )
            {
                  nickLen = pressedPara.findRev("</span>") - nickStart;
                  pressedNick = pressedPara.mid(nickStart, nickLen);
            }
      }
      
      // check for private chat
      if ( (pressedNick == "VALKNUT") && m_bPrivateChat )
      {
            pressedNick = QString(m_sNick.Data());
      }
      
      //printf("Debug pressedNick: %s\n",pressedNick.ascii());
      
      cPressedNick = CString(pressedNick.ascii());
      isNickOnline = m_pClient->UserList()->IsUserOnline(cPressedNick);
      
      // select the user in the userlist
      if (isNickOnline)
      {
            QListViewItem * item = m_pClient->ListView_USERLIST->findItem(pressedNick, 0);
            m_pClient->ListView_USERLIST->clearSelection();
            m_pClient->ListView_USERLIST->setSelected(item, TRUE);
            m_pClient->ListView_USERLIST->setCurrentItem(item);
            m_pClient->ListView_USERLIST->ensureItemVisible(item);
      }
      
      m = new QPopupMenu(this);
      
      muser = DCMenuHandler::InsertMenu( m , emisCHAT_RIGHTCLICK_USER, TRUE, pressedNick );
      DCMenuHandler::InsertMenu( muser, emiPRIVATE_CHAT, isNickOnline );
      DCMenuHandler::InsertMenu( muser, emiADD_FRIEND,  isNickOnline );
      DCMenuHandler::InsertMenu( muser, emiBROWSE_USER_FILES, isNickOnline );
      DCMenuHandler::InsertMenu( muser, emiSEPARATOR );
      
      mslot = DCMenuHandler::InsertMenu( muser, emiUPLOAD_SLOT, TRUE);
      DCMenuHandler::InsertMenu( mslot, emiADD, TRUE);
      DCMenuHandler::InsertMenu( mslot, emiADD_PERMANENT, TRUE);
      DCMenuHandler::InsertMenu( mslot, emiREMOVE, TRUE);
      
      DCMenuHandler::InsertMenu( muser, emiSEPARATOR );
      DCMenuHandler::InsertMenu( muser, emiKICK, (isNickOnline && m_pClient->UserList()->IsAdmin(m_pClient->GetNick())) );
      DCMenuHandler::InsertMenu( muser, emiFORCE_MOVE, (isNickOnline && m_pClient->UserList()->IsAdmin(m_pClient->GetNick())) );
      
      DCMenuHandler::InsertMenu( muser, emiSEPARATOR );
      
      g_pConfig->GetUserMenuCommands(&usercommands);
      
      umc = 0;
      while ( (umc=usercommands.Next(umc)) != 0 )
      {
            if ( (umc->m_nContext) == 2)
            {
                  umc->m_nID = muser->insertItem(umc->m_sName.Data(), -1);
                  muser->setItemEnabled( umc->m_nID, isNickOnline );
            }
      }
      
      DCMenuHandler::InsertMenu( m, emiSEPARATOR );
      
      DCMenuHandler::InsertMenu( m, emiINSERTSMILEY, g_pConfig->GetEnableEmoticons() );
      DCMenuHandler::InsertMenu( m, emiSEPARATOR );
      DCMenuHandler::InsertMenu( m, emiCOPY, m_pTextEdit_CHATOUTPUT->hasSelectedText() );
      DCMenuHandler::InsertMenu( m, emiCLEAR, TRUE );
      DCMenuHandler::InsertMenu( m, emiSELECT_ALL, TRUE );
      DCMenuHandler::InsertMenu( m, emiSEPARATOR );
      DCMenuHandler::InsertMenu( m, emiTRANSLATE, m_pTextEdit_CHATOUTPUT->hasSelectedText() );
      DCMenuHandler::InsertMenu( m, emiTRANSLATOR );

      DCMenuHandler::InsertMenu( m, emiSEPARATOR );
      DCMenuHandler::InsertMenu( m, emiREFRESH );
      DCMenuHandler::InsertMenu( m, emiSEPARATOR );

      if ( m_bPrivateChat )
      {
            // insert request/close secure chat
            if ( m_eSecureState == esecsNONE )
                  DCMenuHandler::InsertMenu( m, emiREQUEST_SECURE_CHAT );
            else
                  DCMenuHandler::InsertMenu( m, emiCLOSE_SECURE_CHAT );
      }

      DCMenuHandler::InsertMenu( m, emiSAVE );

      if ( parentWidget() == 0 )
            DCMenuHandler::InsertMenu( m, emiDOCK );
      else
            DCMenuHandler::InsertMenu( m, emiUNDOCK );

      if ( m_bPrivateChat )
      {
            DCMenuHandler::InsertMenu( m, emiHIDE, m_bPrivateChat && !g_pConfig->GetShowChatInTab() );
            DCMenuHandler::InsertMenu( m, emiCLOSE, m_bPrivateChat );
      }
      
      if ( !m_bPrivateChat )
      {
            DCMenuHandler::InsertMenu( m, emiSEPARATOR );
            
            umc = 0;
            while ( (umc=usercommands.Next(umc)) != 0 )
            {
                  if ( (umc->m_nContext & 1) == 1)
                  {
                        umc->m_nID = m->insertItem(umc->m_sName.Data(), -1);
                  }
            }
      }
      
      id = m->exec(QCursor::pos());

      delete m;

      if ( id == emiINSERTSMILEY )
      {
            int x,y;
            CList<DC_EmoticonObject> * elist;

            elist = g_pConfig->EmoticonList();

            if ( elist )
            {
                  CDialogPictureMap * dialog = new CDialogPictureMap(this);
                  QPixmap p(g_pConfig->GetEmoticonImage());
                  dialog->SetPixmap(p);

                  if ( dialog->exec() == QDialog::Accepted )
                  {
                        dialog->GetXY(x,y);

                        DC_EmoticonObject * EmoticonObject = 0;

                        while ( (EmoticonObject=elist->Next(EmoticonObject)) != 0 )
                        {
                              if ( ((EmoticonObject->left<x) && (EmoticonObject->right>x)) &&
                                   ((EmoticonObject->top<y)  && (EmoticonObject->bottom>y)) )
                              {
                                    TextEdit_CHATINPUT->insert(EmoticonObject->m_Text.Data());
                                    break;
                              }
                        }
                  }

                  delete dialog;
            }
      }
      else if ( id == emiTRANSLATE )
      {
            QString sc;
            QClipboard * cb = QApplication::clipboard();
            
            // save old text
            sc = cb->text();
            // copy to cb
            m_pTextEdit_CHATOUTPUT->copy();
            // get new text
            s = cb->text();
            // save old text
            cb->setText(sc);
            
            s = s.replace(QRegExp("<!--StartFragment-->"),"");
            g_pTranslator->Translate( this, m_sLanguage.Data(), s );
      }
      else if ( id == emiTRANSLATOR )
      {
            m_sLanguage = g_pTranslator->SelectLanguage(m_sLanguage);
      }
      else if ( id == emiCOPY )
      {
            m_pTextEdit_CHATOUTPUT->copy();
      }
      else if ( id == emiCLEAR )
      {
            m_pTextEdit_CHATOUTPUT->clear();
            AddStatus( tr("Chat Cleared.").ascii() );
      }
      else if ( id == emiSELECT_ALL )
      {
            m_pTextEdit_CHATOUTPUT->selectAll();
      }
      else if ( id == emiREQUEST_SECURE_CHAT )
      {
            m_pClient->SendPrivateMessage( m_pClient->GetNick(), m_sNick, "<request secchannel>" );
      }
      else if ( id == emiCLOSE_SECURE_CHAT )
      {
            m_pClient->SendPrivateMessage( m_pClient->GetNick(), m_sNick, "<close secchannel>" );
      }
      else if ( (id == emiDOCK) || (id == emiUNDOCK) )
      {
            if ( parentWidget() == 0 )
            {
                  DCChat::reparent(m_pParent,QPoint(),TRUE);

                  if ( !m_bPrivateChat || g_pConfig->GetShowChatInTab() )
                  {
                        QTabWidget * p = (QTabWidget*)m_pParent;

                        p->insertTab(this,m_sLabel);
                        p->showPage(this);
                  }

                  show();
            }
            else
            {
                  if ( !m_bPrivateChat || g_pConfig->GetShowChatInTab() )
                  {
                        QTabWidget * p = (QTabWidget*)m_pParent;

                        m_sLabel = p->tabLabel(this);
                        p->removePage(this);
                  }

                  DCChat::reparent(0,QPoint(),TRUE);

                  move(0,0);

                  // set default icon
                  setIcon( g_pIconLoader->GetPixmap(eiGLOBE) );
            }
      }
      else if ( id == emiSAVE )
      {
            QString s = QFileDialog::getSaveFileName(
                  "",
                  "HTML (*.html *.htm)",
                  this,
                  "save file dialog",
                  tr("Choose a filename to save under") );

            if ( s != "" )
            {
                  QFile f(s);

                  if ( f.open(IO_WriteOnly) == TRUE )
                  {
                        f.writeBlock(m_pTextEdit_CHATOUTPUT->text(),m_pTextEdit_CHATOUTPUT->text().length());
                        f.close();
                  }
            }
      }
      else if ( id == emiREFRESH )
      {
            if ( CFileManager::Instance()->CreateShareList() )
                  s = tr("Refresh share in progress.");
            else
                  s = tr("Refresh share already in progress.");
            AddStatus(s.ascii());
      }
      else if ( id == emiCLOSE )
      {
            close();
      }
      else if ( id == emiHIDE )
      {
            setEnabled(FALSE);
            hide();
      }
      else if ( id == emiPRIVATE_CHAT )
      {
            m_pClient->DC_PrivateChat( pressedNick, "", "", TRUE );
      }
      else if ( id == emiADD_FRIEND )
      {
            g_pUsersList->AddFriend( cPressedNick,
                        m_pClient->GetHubName(), m_pClient->GetIP(), "" );
      }
      else if ( id == emiBROWSE_USER_FILES )
      {
            g_pTransferView->DLM_QueueAdd( cPressedNick, m_pClient->GetHubName(),
                        m_pClient->GetIP()+":"+QString().setNum(m_pClient->GetPort()).ascii(),
                        DC_USER_FILELIST_HE3, DC_USER_FILELIST_HE3, "", "", eltBUFFER,
                        0, 0, 0, ""  );
      }
      else if ( id == emiKICK )
      {
            QString kickMessage;
            
            if ( !m_pClient->GetOPKickMessage(kickMessage) )
            {
                  return;
            }
            m_pClient->OPKick( pressedNick, kickMessage );
            
      }
      else if ( id == emiFORCE_MOVE )
      {
            QString host, message;
            if ( !m_pClient->GetOPForceMoveMessage(message,host) )
            {
                  return;
            }
            m_pClient->OPForceMove(pressedNick, message, host);
      }
      else if ( id == emiADD )
      {
            g_pTransferView->DLM_AddUserSlot(cPressedNick, m_pClient->GetHubName(), 1);
      }
      else if ( id == emiADD_PERMANENT )
      {
            g_pTransferView->DLM_AddUserSlot(cPressedNick, m_pClient->GetHubName(), 0);
            g_pTransferView->DLM_AddUserSlot(cPressedNick, m_pClient->GetHubName(), 0, TRUE);
      }
      else if ( id == emiREMOVE )
      {
            g_pTransferView->DLM_AddUserSlot(cPressedNick, m_pClient->GetHubName(), 0);
      }
      else
      {
            umc = 0;
            while ( (umc=usercommands.Next(umc)) != 0 )
            {
                  if ( id == umc->m_nID )
                  {
                        userCommand = m_pClient->replaceCommandTags( umc->m_sCommand.Data(), pressedNick );
                        
                        AddStatus(userCommand.ascii());
                        m_pClient->SendString(userCommand.ascii());
                  }
            }
      }
}

/** */
bool DCChat::close( bool alsoDelete )
{
      // re-set the wflags ...
      setWFlags(WDestructiveClose);
      return QWidget::close(alsoDelete);
}

/** */
void DCChat::InitView()
{
      int i;

      if ( !m_bFirstInit )
            return;
            
      m_bFirstInit = FALSE;

/*    QValueList<int> list = Splitter3->sizes();
      QValueList<int>::Iterator it = list.begin();
      printf("SP: %d\n",*it);
      ++it;
      printf("SP: %d\n",*it);*/
      
      // resize splitter
      QValueList<int> list = Splitter3->sizes();
      QValueList<int>::Iterator it = list.begin();
      i = *it;
      ++it;
      i += *it;
      i -= TextEdit_CHATINPUT->minimumHeight()*2;
      it = list.begin();
      *it = i;
      ++it;
      *it = TextEdit_CHATINPUT->minimumHeight()*2;
      Splitter3->setSizes(list);
      
      // update view
      update();
}

/** */
void DCChat::slotSendMessage()
{
      SendMessage();
}

/** */
void DCChat::SetNick( CString nick, CString hubname )
{
      m_sNick = nick;

      if ( nick != "" )
      {
            setCaption(tr("Private Chat:")+" "+QString::fromUtf8(nick.Data())+" ["+QString::fromUtf8(hubname.Data())+"]");
      }
      else
      {
            setCaption(tr("Chat:")+" ["+QString::fromUtf8(hubname.Data())+"]");
      }
}

/** */
CString DCChat::GetTimeStamp()
{
      CString s = "";

      if ( ((g_pConfig->GetTimeStamp(etsPRIVATECHAT) == TRUE) && (m_bPrivateChat)) ||
           ((g_pConfig->GetTimeStamp(etsHUBCHAT) == TRUE) && (!m_bPrivateChat)) )
      {
            s = QTime::currentTime().toString("[hh:mm:ss]").ascii();
      }

      if ( m_bPrivateChat )
            s = "<font color=\"" + g_pConfig->GetChatColor(eccCHATTIMESTAMP) + "\">" + s + "</font> ";
      else
            s = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATTIMESTAMP) + "\">" + s + "</font> ";

      return s;
}

/** */
void DCChat::AddOutput( CString message )
{
      bool bscroll;
      CString s;

      if ( m_pTextEdit_CHATOUTPUT->verticalScrollBar()->maxValue() == m_pTextEdit_CHATOUTPUT->verticalScrollBar()->value() )
      {
            bscroll = TRUE;
      }
      else
      {
            bscroll = FALSE;
      }

      // convert newline
      message = message.Replace( "\xa\\r", "\xa" );
      message = message.Replace( "\xa", "<br />" );
      
      // convert tabs to spaces
      message = message.Replace( "  ", "&nbsp;&nbsp;&nbsp;&nbsp;" );

      if ( (g_pConfig->GetChatMaxParagraph()!= 0) && (m_pTextEdit_CHATOUTPUT->paragraphs() > (g_pConfig->GetChatMaxParagraph()+5)) )
      {
            m_pTextEdit_CHATOUTPUT->removeParagraph(0);
            m_pTextEdit_CHATOUTPUT->removeParagraph(0);
            m_pTextEdit_CHATOUTPUT->removeParagraph(0);
            m_pTextEdit_CHATOUTPUT->removeParagraph(0);
            m_pTextEdit_CHATOUTPUT->removeParagraph(0);
      }
      
      m_pTextEdit_CHATOUTPUT->append( QString::fromUtf8(message.Data()) );

      if ( bscroll )
      {
            m_pTextEdit_CHATOUTPUT->scrollToBottom();
            m_pTextEdit_CHATOUTPUT->moveCursor( QTextEdit::MoveEnd, FALSE );
      }

#if QT_VERSION >= 304
      message += "<br />";
#endif

      // save to logfile
      if ( g_pConfig->GetLogChatOption(elcoENABLELOGGING) )
      {
            if ( !(g_pConfig->GetLogChatOption(elcoDISABLEPUBLICCHAT) && !m_bPrivateChat) )
            {
                  if ( g_pConfig->CheckLogChatNickNameFilter(m_sNick) )
                  {
                        s = m_sNick;

                        if ( g_pConfig->GetLogChatOption(elcoAPPENDHUBNAME) )
                              s += "_" + m_pClient->GetHubName();

                        if ( g_pConfig->GetLogChatOption(elcoAPPENDHUBHOST) )
                              s += "_" + m_pClient->GetIP();

                        if ( g_pConfig->GetLogChatOption(elcoAPPENDDATE) )
                              s += "_" + m_sTimeStamp;

                        // damn hacking ;-)
                        s = s.Replace('/',"");
                        s = s.Replace('\\',"");
                        s = s.Replace(':',"");

                        s = g_pConfig->GetChatLogPath() + s + ".html";

                        QFile f(s.Data());

                        if ( f.open(IO_WriteOnly | IO_Append) == TRUE )
                        {
                              // add newline
                              message += "\n";

                              f.writeBlock(message.Data(),message.Length());
                              f.close();
                        }
                  }
            }
      }
}

/** */
void DCChat::AddStatus( CString message, bool show )
{
      CString timestamp;

      // convert special chars ... damn hacking ;-)
      message = message.Replace( "<", "&lt;" );
      message = message.Replace( ">", "&gt;" );

      if ( (g_pConfig->GetShowStatusMessage() == TRUE) || (show) )
      {
            timestamp = GetTimeStamp();

            // convert newline
            message = message.Replace( "\\r\xa", "\xa" );

#if QT_VERSION < 304
            if ( message.Find('\xa',0) == -1 )
                  message += "<br />";
#endif
            message = message.Replace( "\xa", "<br />" );

            if ( m_bPrivateChat )
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccCHATSTATUSTEXT) + "\">" + message + "</font>";
            else
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATSTATUSTEXT) + "\">" + message + "</font>";

            if ( m_bPrivateChat )
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccCHATSTATUSNICK) + "\">" + "<b>&lt;VALKNUT&gt;</b> " + "</font>" + message;
            else
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATSTATUSNICK) + "\">" + "<b>&lt;VALKNUT&gt;</b> " + "</font>" + message;

            AddOutput( timestamp + message );
      }
}

/** */
void DCChat::AddMessage( CMessagePrivateChat * msg, bool bremote, bool forward )
{
      if ( msg->m_eSecureState != m_eSecureState )
      {
            SetCrypt(msg->m_eSecureState);
      }

      if ( msg->m_sSrcNick == "" )
            AddMessage( msg->m_sSrcNick.Data(), msg->m_sMessage.Data(), bremote, forward );
      else
            AddMessage( msg->m_sMultiSrcNick.Data(), msg->m_sMessage.Data(), bremote, forward );
}

/** */
void DCChat::AddMessage( CString nick, CString message, bool bremote, bool forward )
{
      unsigned int len;
      bool b;
      CString msg,s,s1,timestamp;
      int index;
      int i1,i2;
      bool b1,b2;
      bool bSay = FALSE;
      bool bMe = FALSE;
      bool isOP = m_pClient->UserList()->IsAdmin( nick );

      //printf("ADD MESSAGE '%s'\n",message.Data());

      if ( message == "" )
      {
            return;
      }

      if ( CheckForData(message) == TRUE )
      {
            return;
      }

      // convert newline
      message = message.Replace( "\\r\xa", "\xa" );
      message = message.Replace( "\\r", "\xa" );

      // convert special chars ... damn hacking ;-)
      message = message.Replace( "<", "&lt;" );
      message = message.Replace( ">", "&gt;" );

      // convert special chars in nick ... damn hacking ;-)
      nick = nick.Replace( "<", "&lt;" );
      nick = nick.Replace( ">", "&gt;" );

      s1 = m_pClient->GetNick() + ": ";

      if ( ( message.Left(4).ToUpper() == "/ME " ) || ( message.Left(4).ToUpper() == "+ME " ) )
      {
            bMe    = TRUE;
            message = message.Right( message.Length() - 4 );
      }

      if ( message.Left(s1.Length()) == s1 )
      {
            bSay    = TRUE;
            // message = message.Right( message.Length() - s1.Length() );
      }

      msg = message;
      s1 = "";

      b1 = b2 = TRUE;

      while ( msg != "" )
      {
            if (b1)
            {
                  if ( (i1 = FindFirstLink(msg)) == -1 )
                  {
                        b1 = FALSE;
                  }
            }
            else
            {
                  i1 = -1;
            }

            if (b2)
            {
                  if ( (i2 = FindFirstEmoticon(msg)) == -1 )
                  {
                        b2 = FALSE;
                  }
            }
            else
            {
                  i2 = -1;
            }

            if ( ((i1 < i2) || (i2 == -1)) && (i1 != -1) )
            {
                  // convert link
                  s1 += msg.Left(i1);
                  msg = msg.Right(msg.Length()-i1);

                  index = ConvertLinks( msg, s );
            }
            else if ( ((i2 < i1) || (i1 == -1)) && (i2 != -1) )
            {
                  // convert emot
                  s1 += msg.Left(i2);
                  msg = msg.Right(msg.Length()-i2);

                  index = ConvertEmoticons( msg, s );
            }
            else
            {
                  // no link & no emot found
                  s1 += msg;
                  msg = "";
                  break;
            }

            if ( index > 1 )
            {
                  s1 += s;
                  msg = msg.Right(msg.Length()-index);
                  continue;
            }

            if ( index == 1 )
            {
                  s1 += msg.Left(1);
            }

            msg = msg.Right(msg.Length()-index);
      }

      message = s1;

      // convert spaces
      s = "";
      b = TRUE;

      for(len=0;len<message.Length();len++)
      {
            if ( message.Data()[len] == '\xa' )
                  b = TRUE;
            else if ( message.Data()[len] != ' ' )
                  b = FALSE;

            if ( message.Data()[len] == ' ' )
            {
                  if (b)
                        s += "&nbsp;";
                  else
                        s += " ";
                  b = !b;
            }
            else
            {
                  s += message.Data()[len];
            }
      }

      message = s;

      // convert newline
#if QT_VERSION < 304
      if ( message.Find('\xa',0) == -1 )
            message += "<br />";
#endif

      message = message.Replace( "\xa", "<br />" );

      // set color
      if ( m_bPrivateChat )
            if ( bremote && (nick != m_pClient->GetNick().Data()) )
                  if ( bSay )
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccCHATSAY) + "\">" + message + "</font>";
                  else
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccCHATREMOTETEXT) + "\">" + message + "</font>";
            else
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccCHATLOCALTEXT) + "\">" + message + "</font>";
      else
            if ( forward )
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICPRIVATECHATTEXT) + "\">" + message + "</font>";
            else if ( bremote && (nick != m_pClient->GetNick().Data()) )
                  if ( bSay )
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccCHATSAY) + "\">" + message + "</font>";
                  else
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATREMOTETEXT) + "\">" + message + "</font>";
            else
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATLOCALTEXT) + "\">" + message + "</font>";

      // add nick
      if ( m_bPrivateChat )
      {
            if ( nick != m_pClient->GetNick().Data() )
            {
                  if ( isOP )
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccOPNICK) + "\">" + "<b>" + nick + "</b>: " + message + "</font>";
                  else
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccCHATREMOTENICK) + "\">" + "<b>" + nick + "</b>: " + message + "</font>";
            }
            else
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccCHATLOCALNICK) + "\">" + "<b>" + nick + "</b>: " + message + "</font>";
      }
      else
      {
            if ( forward )
                  message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICPRIVATECHATNICK) + "\">" + "<b>&lt;" + nick + "&gt;</b> " + "</font>" + message;
            else if ( nick != m_pClient->GetNick().Data() )
                  if ( bMe )
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATMENICK) + "\">" + "<b>" + nick + "</b> " + "</font>" + message;
                  else
                  {
                        if ( isOP )
                              message = "<font color=\"" + g_pConfig->GetChatColor(eccOPNICK) + "\">" + "<b>&lt;" + nick + "&gt;</b> " + "</font>" + message;
                        else
                              message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATREMOTENICK) + "\">" + "<b>&lt;" + nick + "&gt;</b> " + "</font>" + message;
                  }
            else
                  if ( bMe )
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATMENICK) + "\">" + "<b>" + nick + "</b> " + "</font>" + message;               
                  else
                        message = "<font color=\"" + g_pConfig->GetChatColor(eccPUBLICCHATLOCALNICK) + "\">" + "<b>&lt;" + nick + "&gt;</b> " + "</font>" + message;
      }

      timestamp = GetTimeStamp();

      AddOutput( timestamp + message );

      if ( bremote && m_bPrivateChat )
      {
            g_pConfig->PlaySound(eusRECEIVE);

            // send away message
            if ( g_pConfig->GetAwayMode() == euamAWAY )
            {
                  s = g_pConfig->GetAwayMessage().Data();

                  if ( (s != "") && (m_bSendAway) )
                  {
                        m_pClient->SendPrivateMessage( m_pClient->GetNick(), m_sNick, s );
                        m_bSendAway = FALSE;
                        AddStatus("Sent away message: " + s);
                  }
            }
            else
            {
                  m_bSendAway = TRUE;
            }
      }
}

/** */
void DCChat::SendMessage( CString message )
{
      int err;
      CString s;
      bool local = FALSE;
      bool cmd = FALSE;

      if ( !m_pClient )
      {
            return;
      }

      if ( message == "" )
      {
            message = TextEdit_CHATINPUT->text().ascii();
      }
      else
      {
            local = TRUE;
      }

      if ( message != "" )
      {
            if ( local == FALSE )
            {
                  // add history
                  AddHistory(message);
                  m_sHistoryTempString = "";
                  cmd = CheckForCommand();
            }

            if ( cmd == FALSE )
            {
                  // convert the newlines
                  message = message.Replace( "\\r\xa", "\xa" );
                  message = message.Replace( "\xa", "\xd\xa" );

                  if ( m_bPrivateChat )
                        err = m_pClient->SendPrivateMessage( m_pClient->GetNick(), m_sNick, message );
                  else
                        err = m_pClient->SendChat( m_pClient->GetNick(), message );

                  if ( err == 0 )
                  {
                        if ( m_bPrivateChat )
                              AddMessage( m_pClient->GetNick(), message, FALSE );
                        g_pConfig->PlaySound(eusSEND);
                  }
                  else
                  {
                        AddStatus( tr("Message not sent!").ascii() );
                  }
            }

            if ( local == FALSE )
            {
                  TextEdit_CHATINPUT->setText("");
            }
      }
}

/** */
int DCChat::FindFirstLink( CString msg )
{
      int i,i1,i2;

      for(i=0,i1=-1,i2=-1;p_LinkList[i]!=0;i++)
      {
            if ( (i1 = msg.Find(p_LinkList[i],0,FALSE)) != -1 )
            {
                  if ( (i2 == -1) || (i2 > i1) )
                  {
                        i2 = i1;
                  }
            }
      }

      return i2;
}

/** */
int DCChat::ConvertLinks( CString msg, CString & s )
{
      int ret = 1;
      int i,i1,i2,i3;

      // convert links
      for(i=0;p_LinkList[i]!=0;i++)
      {
            if ( msg.Left(strlen(p_LinkList[i])).ToUpper() == p_LinkList[i] )
            {
                  // link end at space or newline
                  i1 = msg.Find(' ',0,FALSE);
                  i2 = msg.Find('\xa',0,FALSE);
                  i3 = msg.Find('\xd',0,FALSE);

                  if ( i1 == -1 )
                        i1 = msg.Length();
                  if ( (i1 > i2) && (i2 != -1) )
                        i1 = i2;
                  if ( (i1 > i3) && (i3 != -1) )
                        i1 = i3;

                  s = msg.Left(i1);
                  s = "<a title=\""+s+"\" name=\""+s+"\" href=\""+s+"\">"+s+"</a>";

                  ret = i1;

                  break;
            }
      }

      return ret;
}

/** */
int DCChat::FindFirstEmoticon( CString msg )
{
      int i1,i2;
      CList<DC_EmoticonObject> * elist;

      elist = g_pConfig->EmoticonList();

      i1 = i2 = -1;

      if ( (g_pConfig->GetEnableEmoticons() == TRUE) && (elist != 0) )
      {
            DC_EmoticonObject * EmoticonObject = 0;

            while ( (EmoticonObject=elist->Next(EmoticonObject)) != 0 )
            {
                  if ( (i1 = msg.Find( EmoticonObject->m_Text, 0 )) != -1 )
                  {
                        if ( (i2 == -1) || (i2 > i1) )
                        {
                              i2 = i1;
                        }
                  }
            }
      }

      return i2;
}

/** */
int DCChat::ConvertEmoticons( CString msg, CString & s )
{
      int ret = 1;
      CList<DC_EmoticonObject> * elist;

      elist = g_pConfig->EmoticonList();

      // convert emoticons
      if ( (g_pConfig->GetEnableEmoticons() == TRUE) && (elist != 0) )
      {
            DC_EmoticonObject * EmoticonObject = 0;

            while ( (EmoticonObject=elist->Next(EmoticonObject)) != 0 )
            {
                  if ( msg.Left(EmoticonObject->m_Text.Length()) == EmoticonObject->m_Text )
                  {
                        s   = "<img alt=\"\" align=\"center\" source=\"emoticon"+CString().setNum(EmoticonObject->m_nID)+"\" />";
                        ret = EmoticonObject->m_Text.Length();
                        break;
                  }
            }
      }

      return ret;
}

/** */
bool DCChat::CheckForCommand()
{
      bool res = FALSE;
      bool addedSpace = FALSE;
      QString timestamp;
      CString cmd,s;
      CList<DC_UserChatCommand> usercommands;
      DC_UserChatCommand * ucc = 0;
      
      cmd = TextEdit_CHATINPUT->text().ascii();
      
      // replace custom commands with their actions
      if ( cmd.Right(1) != " " )
      {
            cmd = cmd + " ";
            addedSpace = TRUE;
      }
      
      g_pConfig->GetUserChatCommands(&usercommands);
      
      while( (ucc=usercommands.Next(ucc)) != 0 )
      {
            if ( cmd.Left(ucc->m_sName.Length() + 1) == (ucc->m_sName + " ") )
            {
                  cmd = cmd.Replace( ucc->m_sName, ucc->m_sCommand );
            }
      }
            
      if (addedSpace)
      {
            cmd = cmd.Left(cmd.Length() - 1);
      }
      
      if ( (cmd != "") && (cmd.Left(1) == '/') )
      {
            // help
            if ( cmd == "/dchelp" )
            {
                  s  = tr("Help:").ascii();
                  s += "\n";
                  s += tr("/clear - clears the chat window").ascii();
                  s += "\n";
                  s += tr("/mode - shows the current mode").ascii();
                  s += "\n";
                  s += tr("/refresh - refresh share").ascii();
                  s += "\n";
                  s += tr("/rebuild - remove no longer present files from hash database").ascii();
                  s += "\n";
                  s += tr("/slots &lt;N&gt; - set number of upload slots to N");
                  s += "\n";
                  s += tr("/ts - switch time display in chat on/off").ascii();
                  s += "\n";
                  s += tr("/adv - send an advertisment to the hub").ascii();
                  s += "\n";
                  s += tr("/join &lt;address&gt; - disconnect from currently connected hub and connect to another hub").ascii();
                  s += "\n";
                  s += tr("/msg &lt;nick&gt; &lt;message&gt; - send private message").ascii();
                  s += "\n";
                  s += tr("/away &lt;message&gt; - set automatic response for private messages; if the message is empty, disable it").ascii();
                  s += "\n";
                  s += tr("/bye &lt;message&gt; - disconnect from channel with an optional message").ascii();
                  s += "\n";
                  s += tr("/uptime [show] - show valknut uptime [to other users]").ascii();
                  s += "\n";
                  s += tr("/ls &lt;nick&gt; - get share list from user").ascii();
                  s += "\n";
                  s += tr("/grant &lt;nick&gt; - grant user a slot").ascii();
                  s += "\n";
                  s += tr("/grantp &lt;nick&gt; - grant user a permanent slot").ascii();
                  s += "\n";
                  s += tr("/friend &lt;nick&gt; - add user to friend list").ascii();
                  s += "\n";
                  s += tr("/fav - add hub to bookmark list").ascii();
                  s += "\n";
                  s += tr("/info &lt;nick&gt; - show user info").ascii();
                  s += "\n";
                  s += tr("/now - send current time to the chat").ascii();
                  s += "\n";
                  s += tr("/sh &lt;command&gt; &lt;args...&gt; - send output of shell command to chat").ascii();
                  s += "\n";
                  s += tr("/raw - send raw message").ascii();
                  s += "\n";
                  s += tr("/disablesorting - disable sorting of the user list").ascii();
                  s += "\n";
                  s += tr("/enablesorting - enable sorting of the user list").ascii();
                  s += "\n";
                  s += tr("/ignore &lt;nick&gt; - do not show main chat lines from the user").ascii();
                  s += "\n";
                  s += tr("/unignore &lt;nick&gt - show main chat lines from the user again").ascii();
                  s += "\n";
                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /clear - clear the chat window
            else if ( cmd == "/clear" )
            {
                  m_pTextEdit_CHATOUTPUT->clear();

                  AddStatus( tr("Chat Cleared.").ascii(), TRUE );
                  res = TRUE;
            }
            // /info - show user info
            else if ( cmd.Left(5) == "/info" )
            {
                  CString nick;
                  CMessageMyInfo myinfo;
                  
                  if ( m_bPrivateChat && (cmd.Length() == 5) )
                  {
                        nick = m_sNick;
                  }
                  else
                  {
                        nick = cmd.Mid(6,cmd.Length()-6);   
                  }
                                    
                  if (m_pClient->UserList()->GetUserMyInfo( nick, &myinfo ) == FALSE)
                  {
                        s = tr("Get info failed.");
                  }
                  else
                  {
                        s  = tr("Info:") + "\n";
                        s += tr("Nick:") + " " + myinfo.m_sNick + "\n";
                        s += tr("Operator:") + " ";

                        if ( myinfo.m_bOperator )
                        {
                              s += tr("yes");
                        }
                        else
                        {
                              s += tr("no");
                        }

                        s += tr("\n");

                        s += tr("Comment:") + " " + myinfo.m_sComment + "\n";
                        s += tr("Speed:") + " " + myinfo.m_sUserSpeed + "\n";
                        s += tr("EMail:") + " " + myinfo.m_sEMail + "\n";
                        s += tr("Shared:") + " " + CString().setNum(myinfo.m_nShared) + " Bytes\n";

                        s += tr("Away:") + " ";

                        switch(myinfo.m_eAwayMode)
                        {
                              case euamAWAY:
                                    s += tr("on");
                                    break;
                              default:
                                    s += tr("off");
                                    break;
                        }

                        s += "\n";

                        s += tr("Version:") + " ";

                        switch(myinfo.m_eClientVersion)
                        {
                              case eucvDCPP:
                                    s += "DC++";
                                    break;
                              case eucvDCGUI:
                                    s += "DCGUI";
                                    break;
                              case eucvMICRODC:
                                    s += "microdc";
                                    break;
                              case eucvSHAKESPEER:
                                    s += "ShakesPeer";
                                    break;
                              default:
                                    s += tr("Unknown");
                                    break;
                        }

                        s += "\n";

                        s += tr("Tag:") + " " + myinfo.m_sVerComment + "\n";
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /uptime - show valknut uptime
            else if ( cmd.Left(7) == "/uptime" )
            {
                  int d,h,m;
                  int i = time(0)-dclibUptime();

                  d = i/(60*60*24);
                  i = i%(60*60*24);
                  h = i/(60*60);
                  i = i%(60*60);
                  m = i/60;

                  s  = tr("Valknut uptime") + ": ";

                  if ( d > 0 )
                  {
                        s += CString().setNum(d);
                        s += " ";
                        if ( d == 1 )
                              s += tr("day");
                        else
                              s += tr("days");
                        s += ",";
                  }
                  if ( h > 0 )
                  {
                        s += CString().setNum(h) + " ";
                        if ( h == 1 )
                              s += tr("hour");
                        else
                              s += tr("hours");
                        s += ",";
                  }
                  s += CString().setNum(m) + " ";
                  if ( m == 1 )
                        s += tr("minute");
                  else
                        s += tr("minutes");
                  
                  if ( cmd.Mid(8, 4).ToLower() == "show" )
                        SendMessage(s);
                  else
                        AddStatus( s, TRUE );

                  res = TRUE;
            }
            // /mode - show current mode
            else if ( cmd == "/mode" )
            {
                  CString lms;
                  
                  s  = tr("Current mode: ");

                  if ( g_pConfig->GetMode() == ecmACTIVE )
                        s += tr("active");
                  else
                        s += tr("passive");

                  // get listen manager status
                  if ( CListenManager::Instance() )
                  {
                        lms = CListenManager::Instance()->GetSocketErrorMsg();
                  
                        if ( lms != "" )
                        {
                              s += " (" + lms + ")";
                        }     
                  }
                  
                  s += ".";
                  
                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /refresh - refresh share 
            else if ( cmd == "/refresh" )
            {
                  if ( CFileManager::Instance()->CreateShareList() == TRUE )
                  {
                        s = tr("Refresh share in progress.").ascii();
                  }
                  else
                  {
                        s = tr("Refresh share already in progress.").ascii();
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /rebuild - clean up share databases
            else if ( cmd == "/rebuild" )
            {
                  if ( CFileManager::Instance()->RebuildLists() == TRUE )
                  {
                        s = tr("Rebuild share in progress.").ascii();
                  }
                  else
                  {
                        s = tr("Refresh/rebuild already in progress.").ascii();
                  }
                  
                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /slots - set number of slots
            else if ( cmd.Left(7) == "/slots " )
            {
                  int i = (cmd.Mid(7, cmd.Length() - 7)).asINT();
                  
                  if ( (i >= 0) && (i <= 99) )
                  {
                        g_pConfig->SetMaxUpload(i);
                        AddStatus( tr("Setting upload slots to: " + QString::number(i)).ascii(), TRUE );
                  }
                  else
                  {
                        AddStatus( tr("Invalid number of upload slots specified.").ascii(), TRUE );
                  }
                  
                  res = TRUE;
            }
            // /ts - switch time display in chat on/off 
            else if ( cmd == "/ts" )
            {
                  bool b;

                  if ( m_bPrivateChat )
                  {
                        b = !g_pConfig->GetTimeStamp(etsPRIVATECHAT);
                        g_pConfig->SetTimeStamp(etsPRIVATECHAT,b);
                  }
                  else
                  {
                        b = !g_pConfig->GetTimeStamp(etsHUBCHAT);
                        g_pConfig->SetTimeStamp(etsHUBCHAT,b);
                  }

                  s = tr("Switch timestamp ").ascii();

                  if ( b )
                        s += "on.";
                  else
                        s += "off.";

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /adv - send an advertisment to the hub
            else if ( cmd == "/adv" )
            {
                  AddStatus( tr("Send advertisment.").ascii(), TRUE );

                  s = tr("\nDownload Valknut from http://wxdcgui.sourceforge.net\nIt does everything !\nWorks on almost any platform you can think of and makes you coffee.\n");

                  SendMessage(s);

                  res = TRUE;
            }
            // /now - send current time to the chat
            else if ( ((cmd.Left(4) == "/now") && cmd.Length() == 4) ||
                      (cmd.Left(5) == "/now ") )
            {
                  if ( cmd.Length() > 4 )
                  {
                        s = " " + cmd.Mid(5,cmd.Length()-5);
                  }
                  
                  s = QTime::currentTime().toString("hh:mm:ss").ascii() + s;

                  SendMessage(s);

                  res = TRUE;
            }
            // /raw - send raw message
            else if ( cmd.Left(5) == "/raw " )
            {
                  CString msg;

                  if ( !m_bPrivateChat )
                  {
                        msg = cmd.Mid(5,cmd.Length()-5);
                  
                        if ( msg != "" )
                        {
                              AddStatus( msg, TRUE );
                              m_pClient->SendString(msg);
                        }
                  }

                  res = TRUE;
            }
            // /join <address> - disconnect from currently connected hub and connect to another hub 
            else if ( cmd.Left(6) == "/join " )
            {
                  CString address;

                  address = cmd.Mid(6,cmd.Length()-6);

                  if ( address == "" )
                        s = tr("Wrong parameter for '/join'").ascii();
                  else
                  {
                        s = tr("Join to: ").ascii() + address;

                        m_pClient->SetHubName(address);
                        m_pClient->setCaption(address.Data());
                        m_pClient->Connect(address);
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /ls - get share list from user
            else if ( cmd.Left(3) == "/ls" )
            {
                  CString nick;

                  if ( m_bPrivateChat && (cmd.Length() == 3) )
                  {
                        nick = m_sNick;
                  }
                  else
                  {
                        nick = cmd.Mid(4,cmd.Length()-4);
                  }

                  if ( nick != "" )
                  {
                        /** add transfer to the waitlist */
                        g_pTransferView->DLM_QueueAdd( nick, m_pClient->GetHubName(), m_pClient->GetIP()+":"+QString().setNum(m_pClient->GetPort()).ascii(),
                                          DC_USER_FILELIST_HE3, DC_USER_FILELIST_HE3, "", "", eltBUFFER,
                                          0, 0, 0, "" );

                        s = tr("Download sharelist from") + " '" + nick + "'";
                  }
                  else
                  {
                        s = tr("No nick, try /dchelp");
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /grantp - grant perm. slot to user
            else if ( cmd.Left(7) == "/grantp" )
            {
                  CString nick;

                  if ( m_bPrivateChat && (cmd.Length() == 7) )
                  {
                        nick = m_sNick;
                  }
                  else
                  {
                        nick = cmd.Mid(8,cmd.Length()-8);
                  }

                  if ( nick != "" )
                  {
                        g_pTransferView->DLM_AddUserSlot( nick, m_pClient->GetHubName(), 0 );
                        g_pTransferView->DLM_AddUserSlot( nick, m_pClient->GetHubName(), 0, TRUE );

                        s = tr("Permanent slot added for") + " '" + nick + "'";
                  }
                  else
                  {
                        s = tr("No nick, try /dchelp");
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /grant - grant slot to user
            else if ( cmd.Left(6) == "/grant" )
            {
                  CString nick;

                  if ( m_bPrivateChat && (cmd.Length() == 6) )
                  {
                        nick = m_sNick;
                  }
                  else
                  {
                        nick = cmd.Mid(7,cmd.Length()-7);
                  }

                  if ( nick != "" )
                  {
                        g_pTransferView->DLM_AddUserSlot( nick, m_pClient->GetHubName(), 1 );

                        s = tr("Slot added for") + " '" + nick + "'";
                  }
                  else
                  {
                        s = tr("No nick, try /dchelp");
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /friend - add user to friend list
            else if ( cmd.Left(7) == "/friend" )
            {
                  CString nick;

                  if ( m_bPrivateChat && (cmd.Length() == 7) )
                  {
                        nick = m_sNick;
                  }
                  else
                  {
                        nick = cmd.Mid(8,cmd.Length()-8);
                  }

                  if ( nick != "" )
                  {
                        g_pUsersList->AddFriend( nick, m_pClient->GetHubName(), m_pClient->GetHost(), "" );

                        s = tr("Added to friend list ") + " '" + nick + "'";
                  }
                  else
                  {
                        s = tr("No nick, try /dchelp");
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /fav - add hub to bookmarks
            else if ( cmd == "/fav" )
            {
                  g_pHubListManager->AddBookmark( m_pClient->GetHubName().Data(), m_pClient->GetHost().Data(), "" );

                  s = tr("Add bookmark hub") + " '" + m_pClient->GetHubName() + "'";

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            // /bye <msg> - disconnect from channel
            else if ( cmd.Left(4) == "/bye" )
            {
                  CString message;

                  message = cmd.Mid(5,cmd.Length()-5);

                  if ( message != "" )
                  {
                        SendMessage(message);
                  }

                  m_pClient->Disconnect(TRUE);

                  res = TRUE;
            }
            // /msg <nick> <message> - send private message 
            else if ( cmd.Left(5) == "/msg " )
            {
                  int i;
                  CString nick,message="";
                  
                  AddStatus( cmd, TRUE );

                  cmd = cmd.Mid(5,cmd.Length()-5);

                  if ( (i = cmd.Find(' ')) != -1 )
                  {
                        nick    = cmd.Left(i);
                        message = cmd.Mid(i+1,cmd.Length()-i-1);
                  }

                  if ( (nick == "") || (message == "") )
                  {
                        s = tr("Wrong parameter for '/msg'").ascii();
                  }
                  else
                  {
                        if ( m_pClient->SendPrivateMessage( m_pClient->GetNick(), nick, message ) == 0 )
                        {
                              s = tr("Private message sent.").ascii();
                              g_pConfig->PlaySound(eusSEND);
                        }
                        else
                        {
                              s = tr("Private message not sent!").ascii();
                        }
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;

            }
            // /away <message> - set automatic response for private messages; if the message is empty, disable it 
            else if ( cmd.Left(5) == "/away" )
            {
                  int i;

                  s = "";

                  i = cmd.Find(' ',5);

                  if ( i > 0 )
                        s = cmd.Mid(i+1,cmd.Length()-i-1);

                  g_pConfig->SetAwayMessage(s);

                  if ( s == "" )
                        s = tr("Away message disabled.").ascii();
                  else
                        s = tr("Away message set.").ascii();

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            else if ( cmd.Left(4) == "/sh " )
            {
                  // display the command the user entered
                  AddStatus( cmd, TRUE );
                  
                  // actually this is better - more portable, doesn't depend on /bin/sh
                  QStringList shellargs = QStringList::split( QString(" "), QString((cmd.Mid(4, cmd.Length() - 4)).Data()) );
                  
                  // QStringList shellargs;
                  // shellargs.append( QString("/bin/sh") );
                  // shellargs.append( QString("-c") );
                  // shellargs.append( QString((cmd.Mid(4, cmd.Length() - 4)).Data()) );
                  
                  // debug code - show the args we are going to run
                  //AddStatus( (shellargs.join( QString(",") )).ascii(), TRUE );
                  
                  QProcess shellproc( shellargs, this );
                  shellproc.setCommunication( QProcess::Stdout );
                  
                  if ( shellproc.start() )
                  {
                        // wait up to 5 seconds for the process to finish
                        int i = 0;
                        while ( (shellproc.isRunning()) && (i < 5) )
                        {
                              sleep(1);
                              i++;
                        }
                        
                        shellproc.closeStdin();
                        
                        // kill the process if it's still running
                        if ( shellproc.isRunning() )
                        {
                              AddStatus( tr("Process still running after 5 seconds, killing process...").ascii(), TRUE );
                              shellproc.tryTerminate();
                              sleep(1);
                              if ( shellproc.isRunning() )
                              {
                                    shellproc.kill();
                              }
                        }
      
                        if ( shellproc.normalExit() )
                        {
                              int exitcode = shellproc.exitStatus();
                              if ( exitcode == 0 )
                              {
                                    s = QString( shellproc.readStdout() ).stripWhiteSpace();
                                    if ( s == "" )
                                    {
                                          AddStatus( tr("Command produced no visible output.").ascii(), TRUE );
                                    }
                                    else
                                    {
                                          SendMessage(s);
                                    }
                              }
                              else
                              {
                                    AddStatus( tr("Process exited with status " + QString::number(exitcode)).ascii(), TRUE);
                              }
                        }
                        else
                        {
                              AddStatus( tr("Process was killed or crashed.").ascii(), TRUE);
                        }
                  }
                  else
                  {
                        AddStatus( tr("Failed to start shell command.").ascii(), TRUE );
                  }
                  
                  res = TRUE;
            }
            else if ( cmd == "/sendphoto" )
            {
                  if ( !m_bPrivateChat )
                  {
                        s = tr("Only allowed in private chat.").ascii();
                  }
                  else if ( m_pClient->UserList()->GetUserClientVersion(m_sNick) != eucvDCGUI )
                  {
                        s = tr("The user is using an old version or not using Valknut").ascii();
                  }
                  else
                  {
                        CString fn = g_pConfig->GetUserPhotoFileName();
                        CDir dir;
                        CFile f;
                        CByteArray bas,bad;
                        ulonglong size;
                        CBase64 base64;

                        size = dir.getFileSize( fn, FALSE );

                        if ( (size == 0) || (f.Open(fn,IO_READONLY|IO_RAW) == FALSE) )
                        {
                              s = tr("Photo not found.").ascii();
                        }
                        else
                        {
                              bas.SetSize(size);

                              if ( f.Read((char*)bas.Data(),size) != size )
                              {
                                    s = tr("Can't read your photo.").ascii();
                              }
                              else
                              {
                                    base64.Encode( &bad, &bas );

                                    if ( bad.Size() == 0 )
                                    {
                                          s = tr("Photo encode error.").ascii();
                                    }
                                    else
                                    {
                                          CString se;

                                          se.Set((char*)bad.Data(),bad.Size());
                                          se  = "<photo data=\"" + se + "\">";

                                          if ( m_pClient->SendPrivateMessage( m_pClient->GetNick(), m_sNick, se ) != 0 )
                                          {
                                                s = tr("Photo not sent.").ascii();
                                          }
                                          else
                                          {
                                                s = tr("Photo sent.").ascii();
                                          }
                                    }
                              }
                        }

                        f.Close();
                  }

                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            else if ( cmd == "/disablesorting" )
            {
                  m_pClient->ListView_USERLIST->setSortColumn(-1);
                  s = tr("Disabled user list sorting.").ascii();
                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            else if ( cmd == "/enablesorting" )
            {
                  m_pClient->ListView_USERLIST->setSortColumn(0);
                  s = tr("Enabled user list sorting.").ascii();
                  AddStatus( s, TRUE );
                  res = TRUE;
            }
            else if (cmd.Left(7) == "/ignore")
            {
                  CString nick = cmd.Mid(8, cmd.Length()-8);
                  if (nick != "")
                  {
                        if (g_pUsersList->isNickInList(nick) == FALSE)
                        {
                              g_pUsersList->AddFriend( nick, m_pClient->GetHubName(), m_pClient->GetHost(), "" );
                        }
                        
                        g_pUsersList->setIgnore( nick, TRUE );
                        s = tr(QString("Ignoring main chat lines from ") + QString(nick.Data()));
                  }
                  else
                  {
                        s = tr("No nick, try /dchelp");
                  }
                  
                  AddStatus( s, TRUE );
                  res = TRUE;
                  
            }
            else if (cmd.Left(9) == "/unignore")
            {
                  CString nick = cmd.Mid(10, cmd.Length()-10);
                  if (nick != "")
                  {
                        if (g_pUsersList->ignoreNick( nick ) == TRUE)
                        {
                              g_pUsersList->setIgnore( nick, FALSE);
                              s = tr(QString("Showing main chat for ") + QString(nick.Data()));
                        }
                        else
                        {
                              s = tr(QString(nick.Data()) + QString(" is not in ignore list"));
                        }
                        
                  }
                  else
                  {
                        s = tr("No nick, try /dchelp");
                  }
                  
                  AddStatus( s, TRUE );
                  res = TRUE;
            }
      }
      return res;
}

/** */
bool DCChat::CheckForData( CString message )
{
      bool res = FALSE;

      // now we check for special private messages
      if ( m_bPrivateChat )
      {
            // remote send a photo
            if ( (message.Find("<photo ") == 0) && (message.Find(">",7) > 0) )
            {
                  int i1,i2;
                  CString s;
                  CByteArray ba;
                  CBase64 base64;

                  if ( (i1 = message.Find("data=\"")) != -1 )
                  {
                        if ( (i2 = message.Find("\"",i1+6)) != -1 )
                        {
                              //printf("'%s'\n",message.Data());
                              //printf("'%s'\n",message.Mid(i1+6,i2-i1-6).Data());

                              s = message.Mid(i1+6,i2-i1-6);

                              if ( base64.Decode( &ba, &s ) > 0 )
                              {
                                    g_pUsersList->AddFriendPhoto(m_sNick,&ba);
                                    AddStatus(tr("Photo received.").ascii(), TRUE );

                                    res = TRUE;
                              }
                        }
                  }
            }
      }

      return res;
}

/** */
void DCChat::NickCompletion()
{
      // shameles stolen from ksirc
      int start, end;
      int p,i;
      QString s;

      if ( m_nTabPressed > 0 )
      {
            s     = m_sTabSaved;
            start = m_nTabStart;
            end   = m_nTabEnd;
      }
      else
      {
            TextEdit_CHATINPUT->getCursorPosition(&p,&i);
            s = TextEdit_CHATINPUT->text();
            m_sTabSaved = s;
            if ( i == 0 )
                  end = 0;
            else
                  end = i - 1;
            start = s.findRev(" ", end, FALSE);
            m_nTabStart = start;
            m_nTabEnd = end;
      }

      if ( (s.isEmpty() == TRUE) && (m_sTabNick.isEmpty() == FALSE) )
      {
            // use the saved nick
            QString line = m_sTabNick + ": ";
            TextEdit_CHATINPUT->setText(line);
            TextEdit_CHATINPUT->setCursorPosition( 0,line.length() );
      }
      else
      {
            int cpos = 1;

            if ( start == -1 )
            {
                  m_sTabNick = m_pClient->findNick( s.mid(0, end+1), m_nTabPressed );

                  if( m_sTabNick.isNull() == TRUE )
                  {
                        m_nTabPressed = 0;
                        m_sTabNick = m_pClient->findNick( s.mid(0, end+1), m_nTabPressed );
                  }

                  s.replace(0, end + 1, m_sTabNick + ": " );
                  cpos += 2;
            }
            else
            {
                  m_sTabNick = m_pClient->findNick( s.mid(start + 1, end - start), m_nTabPressed );

                  if( m_sTabNick.isNull() == TRUE )
                  {
                        m_nTabPressed = 0;
                        m_sTabNick = m_pClient->findNick( s.mid(start + 1, end - start), m_nTabPressed );
                  }

                  s.replace(start + 1, end - start, m_sTabNick);
            }

            if ( m_sTabNick.isEmpty() == FALSE )
            {
                  TextEdit_CHATINPUT->setText(s);

                  TextEdit_CHATINPUT->setCursorPosition(0,start + m_sTabNick.length() + cpos);

                  m_nTabPressed++;
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index