/***************************************************************************
 *   Copyright (C) 2008 by SK Communications.                              *
 *   http://kldp.net/projects/nateon/                                      *
 *                                                                         *
 *   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 3 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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <stdlib.h>
#include "chatview.h"
#include "knateoncommon.h"
#include <kfiledialog.h>
#include <kwin.h>
#include "../buddy/buddy.h"
#include "../util/emoticon.h"
#include "../network/sendfileinfo.h"
// #include "../ncrypto/ncrypto.h"
#include "../dialog/emoticonselector.h"
#include "../dialog/addbuddyselector.h"
#include "../dialog/confirmsavelog.h"
#include "../knateonmainview.h"
#include "../currentaccount.h"
#include "../util/sound.h"
#include "../util/common.h"
#include "utils.h"
#include "../network/nomhttpproxy.h"

extern nmconfig stConfig;

ChatView::ChatView(QWidget *parent, const char *name)
:ChatQW(parent, name),
m_sSS_Server( QString::null ),
m_nSS_Port( 0 ),
m_sAuthKey( QString::null ),
m_bWriteLocked(false),
m_nTrid(1),
m_pSSSocket(0),
pEmoticon(0),
bTyping(false),
trMessageQueueTimer(0),
trStatusLabelTimer(0),
pAddBuddy(0),
pEmoticonSelector(0),
pBuddyList(0),
pGroupList(0),
m_pCurrentAccount(0),
bGroupChat(false),
isNonBuddyChat(false),
_BuddyStatusText( QString::null ),
_MyStatusText( QString::null ),
_BuddyDiable(false),
pTypeTimer(0),
bTypeTimeOut( FALSE ),
bAlwaysTop( FALSE ),
m_pCommon(0),
_MyDiable(false),
bSave(false),
m_pHttpProxy(0)
{
	/*! 드롭 */
	setAcceptDrops(FALSE);
	config = kapp->config();
  
	m_BuddyList.clear();
	m_BuddyList.setAutoDelete(FALSE);

	m_SendFileInfoList.clear();
	m_SendFileInfoList.setAutoDelete(FALSE);

	textLabel1->clear();
	ChatEditQTE->clear();
	slMessageQueue.clear();
	slSendFileList.clear();

	/// 기본 암호화를 하지 않음.
	setCrypt(false);

	// Create the socket
	m_pSSSocket = new KExtendedSocket();

	// Connect it up and set some defaults
	// 0x00 = anySocket | 0x600000 = bufferedSocket
	m_pSSSocket->setSocketFlags( 0x00 | 0x600000 );
	m_pSSSocket->enableRead( true );
	m_pSSSocket->setTimeout( 0 );


#ifdef NETDEBUG
	// Check that we are disconnected (the socket is null)
	if ( !( ( m_pSSSocket->socketStatus() == KExtendedSocket::nothing )
			|| ( m_pSSSocket->socketStatus() == KExtendedSocket::done ) ) )
	{
		kdDebug() << "XXX>>> Connection: Socket is not disconnected.  Already connected?" << endl;
	}
#endif
	
	// This seams to solve some problems with re-connecting
	// to the switchboard if there is a timeout.
	m_pSSSocket->reset();

	connect( m_pSSSocket, SIGNAL( connectionFailed(int) ), this, SLOT( socketError(int) ) );
	connect( m_pSSSocket, SIGNAL( connectionSuccess() ), this, SLOT( connectionSuccess() ) );
	connect( m_pSSSocket, SIGNAL( closed(int ) ), this, SLOT( socketclosed(int) ) );
	connect( m_pSSSocket, SIGNAL( readyRead() ), this, SLOT( dataReceivedSS() ) );
	connect( SendQPB, SIGNAL( clicked() ), this, SLOT( sendMSG() ) );
	// connect( fileSendButton, SIGNAL( clicked() ), SLOT( slotSelectFile() ) );
	connect( fileSendButton, SIGNAL( clicked() ), SLOT( slotSendFile() ) );
	connect( ChatEditQTE, SIGNAL( textChanged() ), this, SLOT( slotSendTyping() ) );
	connect( ChatEditQTE, SIGNAL( onlyReturn() ), this, SLOT( sendMSG() ) );
	connect( inviteButton, SIGNAL( clicked() ), SLOT( slotInviteDialog() ) );
	connect( fontButton, SIGNAL( clicked() ), SLOT( slotFontDialog() ) );
	connect( fontColorButton, SIGNAL( clicked() ), SLOT( slotFontColorDialog() ) );
	connect( emoticonButton, SIGNAL( clicked() ), this, SLOT( slotEmoticonDialog() ) );
	connect( ChatEditQTE, SIGNAL( sendFiles( const QStringList & ) ), SLOT( slotSendFileList( const QStringList & ) ) );
 
	setEnabled();
	SendQPB->setDisabled();
  
	KStandardDirs   *dirs   = KGlobal::dirs();
	sPicsPath = dirs->findResource( "data", QString( KGlobal::instance()->aboutData()->appName() ) + "/pics/" );
	
	ChatViewQTE->clear();
	ChatViewQTE->setReadOnly ( true );
	( UTF8("대화 암호화 설정이 해제된 상태입니다.<br>--------------------------------------------") );

	config->setGroup( "Chat" );
	QFont myFont( UTF8("굴림"), 10 );
	QFont font = config->readFontEntry( "Font", &myFont );
	ChatEditQTE->setFont( font );
	QColor myColor( "black" );
	QColor color = config->readColorEntry("FontColor", &myColor );
	ChatEditQTE->setColor( color );
	ChatEditQTE->setFocus();

	pTypeTimer = new QTimer( this );
	connect( pTypeTimer, SIGNAL( timeout() ), SLOT( slotTypeTimeOut() ) );

	m_pCommon = new Common();
}


ChatView::~ChatView()
{
	if (m_pSSSocket) delete m_pSSSocket;
	// if (pEmoticon) delete pEmoticon;
}

#include "chatview.moc"


/*!
  \fn ChatView::addBuddy(Buddy &m_Buddy)
  bQuit가 true이면, INVT를 보내게 된다.
*/
void ChatView::addBuddy( Buddy *pBuddy, bool bQuit)
{
	pBuddy->setQuit(bQuit);
 
	m_BuddyList.append(pBuddy);
  
	updateNickNameLabel();
	updateStatus(/* pBuddy */);

	/*! BL(Block List) == 1 */
	if ( /* pBuddy->getBuddyFlag()[2] == '1' */ pBuddy->isBL() == true )
		buddy->changeItem ( lockID, UTF8("친구 차단 해제") );
	else
		buddy->changeItem ( lockID, UTF8("친구 차단") );
  
	emit BuddyAdded(pBuddy);
}


void ChatView::updateNickNameLabel()
{
	/*!
	 * 비버디 체팅이면 상태표시 업데이트를 하지 않는다.
	 */
	if ( isNonBuddyChat )  return;
  
	/// 채팅창 ID 갱신.
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	Buddy* Buddy;

	QStringList slIDs;
	QString sNameNick;
	int nCount = 0; /// <== 채팅인원
	QString sToolTip;

	while(iterator.current() != 0)
	{
		Buddy = iterator.current();
		sNameNick = Buddy->getName();
		sNameNick += " ("; 
		sNameNick += Buddy->getNick();
		sNameNick += ")";

		slIDs.append(sNameNick);
		if ( nCount == 0 )
		{
			caption_ = sNameNick;
			sToolTip = sNameNick;
		}
		else
		{
			caption_ += ",";
			caption_ += sNameNick;
      
			sToolTip += "\n";
			sToolTip += sNameNick;
		}
		nCount++;
		++iterator;
	}

	/*!
	 * 1명 이상의 그룹체팅 중인가?
	 */
	if ( nCount > 1 )
		bGroupChat = true;
	else
		bGroupChat = false;

	QString sNickNameLabel;

	if (nCount > 1)
	{
		sNickNameLabel = slIDs[0];
		sNickNameLabel += QString::fromUtf8(" 외");
		sNickNameLabel += QString::number(nCount - 1);
		sNickNameLabel += QString::fromUtf8("명");
	}
	else
	{
		sNickNameLabel = slIDs[0];
	}
  
	QString sTemp = Common::qEllipsisText( sNickNameLabel, QWidget::fontMetrics(), width() - 50 , Qt::AlignLeft  );
	nicknameLabel->setText( sTemp );
	setCaption( caption_ );
	QToolTip::add( nicknameLabel, sToolTip );
}


bool ChatView::connectToServerSS()
{
	if ( !( ( m_pSSSocket->socketStatus() == KExtendedSocket::nothing )
			|| ( m_pSSSocket->socketStatus() == KExtendedSocket::done ) ) )
	{
		disconnectFromServerSS( false );
	}
	
	QString sServer;
	int nPort = 0;
	if ( m_pCurrentAccount->getProxyType() == 2 ) {
		/*! HTTP Proxy */
		m_pHttpProxy = new NOMHTTPProxy( "pri.nate.com", 5004 );
		sServer = m_pCurrentAccount->getProxyServer();
		nPort = m_pCurrentAccount->getProxyPort();
	} else {
		if ( stConfig.dplconnectionfail == TRUE ) {
			sServer = stConfig.prsserver;
			nPort = stConfig.prsport;
		} else {
			sServer = m_sSS_Server;
			nPort = m_nSS_Port;
		}
	}
	m_pSSSocket->setAddress( sServer, nPort );
	
	// Apparently async lookups don't work correctly under Qt3
	m_pSSSocket->lookup();
	int nConnectionSuccess = m_pSSSocket->startAsyncConnect();
	return nConnectionSuccess == 0;
}

bool ChatView::putENTRSS()
{
	QString pBody;
	// KURL kurl;

	pBody = m_sID + " ";

	// kurl.setPath(m_sNickName);
	// pBody += KURL::encode_string( m_sNickName.local8Bit() ) + " ";
	QString sNickName( m_pCurrentAccount->getMyNickName() );
	pBody += sNickName.replace(" ", "%20") + " ";
	// pBody += m_sNickName.replace(" ", "%20") + " ";
	// kurl.setPath(m_sName);
	// pBody += KURL::encode_string( m_sName.local8Bit() ) + " ";
	QString sName( m_pCurrentAccount->getMyName() );
	pBody += sName.replace(" ", "%20") + " ";

	// pBody += m_sAuthKey + " UTF8 P 1.0 1\r\n";
	pBody += m_sAuthKey + " UTF8 P\r\n";

	sendCommandSS("ENTR", pBody );

	if ( stConfig.showawaymemo && ( m_pCurrentAccount->getStatus() == 'A' ) )
	{
		sendAwayMessage();
	}
	else if ( stConfig.showawaymemo_busy && ( m_pCurrentAccount->getStatus() == 'B' ) )
	{
		sendAwayMessage();
	}
	return true;
}

void ChatView::writeDataSS(const QString & sData)
{
	if ( !isConnectedSS() )
	{
		emit newConnectSS( this );
#ifdef NETDEBUG
		kdDebug() << "[SS] Connection: WARNING - Attempting to write data to a disconnected socket." << endl;
		kdDebug() << sData << endl;
#endif
		return;
	}
  
	int nBytesWritten;

	while ( m_bWriteLocked )
	{
#ifdef NETDEBUG
		kdDebug() << "Connection: WRITE DATA IS LOCKED TO AVOID WRITING OVERLAPPING DATA TO THE SOCKET." << endl;
#endif
	}

	// Lock the writing of data.
	m_bWriteLocked = true;

#if 0
	kdDebug() << m_sIdentifier << " >>> " << sData.utf8() << endl;
#endif
	QCString unicode;
	if ( m_pCurrentAccount->getProxyType() == 2 ) {
		/*! HTTP Proxy */
		QString sHttp( m_pHttpProxy->getPOST( sData ) );
		unicode = sHttp.utf8();
	} else {
		unicode = sData.utf8();
	}
	
	nBytesWritten = m_pSSSocket->writeBlock( unicode.data(), unicode.length() );

	// Note that the previous code used data.length instead of unicode.length(), but I
	// changed this since that is the string we send to the socket... (could be wrong here)
#ifdef NETDEBUG
	if ( nBytesWritten != unicode.length() )
	{
		kdDebug() << "Connection: WARNING - Wanted to write " << sData.length() << " bytes to the socket, wrote " << nBytesWritten << "." << endl;
	}
#endif
	// Unlock the writing of data.
	m_bWriteLocked = false;

	emit OutgoingMessage("[ Chat ] {" + sData +"}");
}

int ChatView::sendCommandSS(const QString & sPrefix, const QString & sText)
{
    int nTrid = getTridSS();
    QString sTridString;
    // Get an acknowledgement number and convert it to a string
    sTridString.sprintf("%d", nTrid);

#ifdef KNATEONTEST
    ASSERT( sTridString.toInt() == nTrid );
#endif
#ifdef NETDEBUG
    kdDebug() << "Connection: Sending " << sPrefix << " command (" << sTridString << ")." << endl;
#endif

    // Send the data to the server
    QString sCommand = sPrefix + " " + sTridString + " " + sText;
    writeDataSS( sCommand );

    // Return the ack used
    return nTrid;
}

int ChatView::sendCommandSS_0(const QString & sPrefix, const QString & sText)
{
    int nTrid = getTridSS();
    QString sTridString;
    // Get an acknowledgement number and convert it to a string
    sTridString.sprintf("%d", nTrid);

#ifdef KNATEONTEST
    ASSERT( sTridString.toInt() == nTrid );
#endif
#ifdef NETDEBUG
	kdDebug() << "Connection: Sending " << sPrefix << " command (" << sTridString << ")." << endl;
#endif

    // Send the data to the server
    QString sCommand = sPrefix + " 0 " + sText;
    writeDataSS( sCommand );

    // Return the ack used
    return nTrid;
}


// void ChatView::putTestMESGSS()
void ChatView::sendMSG()
{
	QString sMsg;
	sMsg = ChatEditQTE->text();

	/*!
	 * 버퍼링이 필요한건 언제인가?
	 * 모두 채팅창에 들어와 있을때?
	 * 접속이 끊겼을때.
	 */
#if 0
	if ( isConnectedSS() )
	{
		sendMessage( sMsg );
	}
	else
	{
		if (!trMessageQueueTimer)
		{
			trMessageQueueTimer = new QTimer( this );
			connect( trMessageQueueTimer, SIGNAL(timeout()), SLOT( slotMessageQueueFail() ) );
		}
		trMessageQueueTimer->start( 5000, TRUE );
		addMessageQueue( sMsg );
		emit newConnectSS( this );
	}
#endif
#if 1 /// 지우지 말고 생각할 부분...
	if ( isAllJoined() /* && isConnectedSS() */ )
	{
		sendMessage( sMsg );
	}
	else
	{
		if (!trMessageQueueTimer)
		{
			trMessageQueueTimer = new QTimer( this );
			connect( trMessageQueueTimer, SIGNAL(timeout()), SLOT( slotMessageQueueFail() ) );
		}
		emit newConnectSS( this );
		addMessageQueue( sMsg );
		trMessageQueueTimer->start( 5000, TRUE );
	}
#endif
  
	ChatEditQTE->clear();
	bTyping = false;
}


void ChatView::sendMessage(QString &sMsg)
{
	if ( !isConnectedSS() )
	{
		addMessageQueue( sMsg );
		emit newConnectSS( this );
#ifdef NETDEBUG
		kdDebug() << "XXX>> Socket is Not Connected!!! [" << m_sSS_Server << "] [" << QString::number(m_nSS_Port) << "]" << endl;
#endif
		return;
	}
	
	QString sLogMsg( sMsg );
	QString sViewMsg( sMsg );
	QString sSendMsg( sMsg );

	config->setGroup( "Chat" );
	QFont myFont( UTF8("굴림"), 10 );
	QFont font = config->readFontEntry( "Font", &myFont );
	QColor myColor( "black" );
	QColor color = config->readColorEntry("FontColor", &myColor );
	QString sName( m_pCurrentAccount->getMyName() );
	QString sNick( m_pCurrentAccount->getMyNickName() );
	Common::fixOutString( sNick );
	
	/*!
	 * 채팅창에 보여짐
	 */
	addChatView( font, color, sName, sNick, sViewMsg );
	

	/*!
	 * 채팅 메시지 보내기
	 */
	sendChatCommand( font, color, QString("MSG"), sSendMsg );
	
	
	/*! TODO: ? */
	if ( !bSave )
		bSave = true;

	/*!
	 * 채팅 로그 저장
	 */
	addChatLog( sName, sNick, sLogMsg );
}

void ChatView::appendLogSS(const QString & m_Log)
{
	// ChatViewQTE->append("(" + QDateTime::currentDateTime().toString(QString("yyyy-MM-dd hh:mm:ss")) + ") " + m_Log );
	addChatView( "(" + QDateTime::currentDateTime().toString(QString("yyyy-MM-dd hh:mm:ss")) + ") " + m_Log );
}


#include <qtextcodec.h>

void ChatView::dataReceivedSS()
{
#ifdef KNATEONTEST
	ASSERT( m_pSSSocket != 0 );
#endif

	char rawblock[1024];
	QCString sBlock, sCommandLine;
	int nIndex, nBytesRemaining, nBytesRead /*, nMessageLength*/;
	QStringList slCommand;

	do
	{
		// Read in a block from the socket
		nBytesRead = m_pSSSocket->readBlock( rawblock, 1024 );

		// Find out how much data remains in the socket
		nBytesRemaining = m_pSSSocket->bytesAvailable();

		// If the noBytesRead is less than zero, it's an error code, so exit
		if ( nBytesRead < 0 )
		{
			return;
		}

		// Add the block to the buffer
		m_Buffer.add( rawblock, nBytesRead );

		// If the buffer contains "\r\n" then there should be at least one full command in there.
		while ( true )
		{

			// Find the location of the end of the command
			nIndex = m_Buffer.findNewline();

			if (nIndex == -1) break;

			// Pull off a command line
			sCommandLine = m_Buffer.left( nIndex );

			// don't know why it need this, commandLine should already be this length
			sCommandLine = sCommandLine.left( nIndex );
#if 0
			QString sTemp;
			sTemp.sprintf("%s", (const char *) sCommandLine);
#endif
			emit IncomingMessage("[ Chat ] {" + QString::fromUtf8(sCommandLine) +"}");
			// sCommandLine = m_Buffer;

			// Convert the line to a QStringList command
			slCommand = QStringList::split( " ", QString::fromUtf8( sCommandLine ) );

			m_Buffer.remove( nIndex + 2 );
			parseCommand( slCommand );


			// QCString encoded_string = ...; // Some ISO 8859-5 encoded text.
			QTextCodec* codec = QTextCodec::codecForName("utf8");
			QString string = codec->toUnicode( sCommandLine );
		}
	}
	while(nBytesRemaining > 0);
}

void ChatView::socketError(int error)
{
	error = 0;
	disconnectFromServerSS();
}

void ChatView::disconnectFromServerSS(bool isTransfer)
{
#ifdef NETDEBUG
	kdDebug() << "Connection: Send 'OUT'." << endl;
#endif

    // stop any more pings
    // setSendPings( false );

    // If the socket is connected...
    if ( isConnectedSS() )
    {
        // Send "OUT"
        writeDataSS("LOUT\r\n");
    }
#ifdef NETDEBUG
    kdDebug() << "Connection: Flush the socket." << endl;
#endif

    // Flush the socket
    m_pSSSocket->flush();

#ifdef NETDEBUG
    kdDebug() << "Connection: Close the socket." << endl;
#endif

    // Close the socket
    m_pSSSocket->closeNow();
    // Reset the socket
    m_pSSSocket->reset();

#ifdef NETDEBUG
    kdDebug() << "Connection: emit 'disconnected'." << endl;
#endif

    if ( !isTransfer ) emit disconnectedSS();
}

void ChatView::connectionSuccess()
{
	if ( stConfig.dplconnectionfail == TRUE )
		putRCONSS();
	else
		putENTRSS();
}

void ChatView::socketclosed(int nFlag)
{
	nFlag = 0;
	m_pSSSocket->reset();
}

bool ChatView::parseCommand(const QStringList & slCommand)
{
	Buddy *pBuddy = 0;

	if ( slCommand[0] == "WHSP" ) {
		if ( slCommand[3] == "FILE" ) { /*! 파일전송 */
			QStringList slData = QStringList::split(QString("%09"), slCommand[4]);
			if ( slData[0] == "REQUEST" ) {
				/*! 파일 수신 요청 */
				gotFILE_REQUEST( slCommand );
			} else if ( slData[0] == "NACK" ) {
				/*! 파일 수신 취소 */
				gotFILE_NACK( slCommand );
				emit cancelReceive( slCommand );
			} else if ( slData[0] == "CANCEL" ) {
				/*! 파일 전송 중 취소 */
				gotFILE_CANCEL( slCommand );
				emit cancelReceiveAll( slCommand );
			}
		} else if ( ( slCommand[3] == "AVCHAT2" ) || 
		            ( slCommand[3] == "AVCHAT37" ) ) 
		{ /*! 화상/음성 대화 */
			QStringList slSubCommand = QStringList::split( "%09", slCommand[4] );
			// kdDebug() << slSubCommand.count() << endl;
			if ( slSubCommand.count() > 3) {
				if ( ( slSubCommand[0] == "REQAVCHAT" ) ) {
					QString sCommand;
					sCommand = slCommand[2];
					sCommand += " ";
					sCommand += slCommand[3];
					sCommand += " ";
					sCommand += "RESAVCHAT";
					sCommand += "%09";
					sCommand += "0";
					sCommand += "%09";
					sCommand += slSubCommand[2];
					sCommand += "%09";
					sCommand += slSubCommand[3];
					sCommand += "%09";
					/*! 0:이미 화상 대화중, 1:사용자 거절, 2: 미니대화중, 3: Unknown Error, 4: 버전이 맞지 않음 (네이트온 2.0사용자, 리눅스, 맥 사용자.) */
					sCommand += "4";
					sCommand += "\r\n";
					sendCommandSS( "WHSP", sCommand );
				}
			}
		} else if ( slCommand[3] == "SPION" ) { /*! 사진 함께 보기 */
			if ( slCommand[4].find("REQINV") != -1 ) {
				QString sRES( slCommand[4] );
				sRES.replace( "REQINV%091", "RESINV%090" );
				
				QString sCommand( slCommand[2] );
				sCommand += " ";
				sCommand += slCommand[3];
				sCommand += " ";
				sCommand += sRES;
				sCommand += "%09";
				/*! 0:이미 화상 대화중, 1:사용자 거절, 2: 미니대화중, 3: Unknown Error, 4: 버전이 맞지 않음 (네이트온 2.0사용자, 리눅스, 맥 사용자.) */
				sCommand += "4";
				sCommand += "\r\n";
				sendCommandSS( "WHSP", sCommand );
			}
		} else if ( slCommand[3] == "WBOARD" ) { /*! 화이트 보드 */
			if ( slCommand[4].find("REQWB") != -1 ) {
				QString sRES( slCommand[4] );
				sRES.replace( "REQWB%091", "RESWB%090" );
				
				QString sCommand( slCommand[2] );
				sCommand += " ";
				sCommand += slCommand[3];
				sCommand += " ";
				sCommand += sRES;
				sCommand += "%09";
				/*! 0:이미 화상 대화중, 1:사용자 거절, 2: 미니대화중, 3: Unknown Error, 4: 버전이 맞지 않음 (네이트온 2.0사용자, 리눅스, 맥 사용자.) */
				sCommand += "4";
				sCommand += "\r\n";
				sendCommandSS( "WHSP", sCommand );
			}
		} else if ( slCommand[3] == "WEBSHR" ) { /*! 웹 사이트 함께 보기 */
			if ( slCommand[4].find("REQWS") != -1 ) {
				QString sRES( slCommand[4] );
				sRES.replace( "REQWS%091", "RESWS%090" );
				
				QString sCommand( slCommand[2] );
				sCommand += " ";
				sCommand += slCommand[3];
				sCommand += " ";
				sCommand += sRES;
				sCommand += "%09";
				/*! 0:이미 화상 대화중, 1:사용자 거절, 2: 미니대화중, 3: Unknown Error, 4: 버전이 맞지 않음 (네이트온 2.0사용자, 리눅스, 맥 사용자.) */
				sCommand += "4";
				sCommand += "\r\n";
				sendCommandSS( "WHSP", sCommand );
			}
		} else if ( slCommand[3] == "PLUGIN" ) { /*! 플러그인 */
			if ( slCommand[4].find("REQUEST") != -1 ) {
				QString sRES( slCommand[4] );
				sRES.replace( "REQUEST", "NACK" );
				
				QString sCommand( slCommand[2] );
				sCommand += " ";
				sCommand += slCommand[3];
				sCommand += " ";
				sCommand += sRES;
				// sCommand += "%09";
				/*! 0:이미 화상 대화중, 1:사용자 거절, 2: 미니대화중, 3: Unknown Error, 4: 버전이 맞지 않음 (네이트온 2.0사용자, 리눅스, 맥 사용자.) */
				// sCommand += "4";
				sCommand += "\r\n";
				sendCommandSS( "WHSP", sCommand );
			}
		} else {
			if ( slCommand.count() > 3 )
				kdDebug() << "Unknown protocol : " << slCommand[3] << endl;
		}
	}
	else if ( slCommand[0] == "MESG" )
	{
		if ( slCommand[3] == "MSG")
		{
			/*! 창이 활성화 되지 않았으면, 반짝이기 */
			if ( !isActiveWindow() )
			{
				KWin::demandAttention(winId());
				
				/*!
				 * 버디로부터 대화가 왔을때 소리
				 */
        
				if ( stConfig.usesound && stConfig.usestartchatsound )
					Sound::play( stConfig.startchatsoundpath );
        
				/*!
				 * KNotifyClient를 활용하면 전역적인 이벤트 설정도 가능함.
				 */
				// KNotifyClient::event(UTF8("대화메시지"), UTF8("대화메시지가 왔습니다.") );
			}

			pBuddy = getBuddyByID( slCommand[2] );

			if ( pBuddy )
			{
				QStringList slInfo = QStringList::split( "%09", slCommand[4], true );
				QString sFontName;
				if (slInfo[0] == "")
					sFontName = "굴림";
				else
					sFontName = slInfo[0];
				
				QString sFontAttr( slInfo[2] );
				
				QString sHEXColor( "#" );
				QString sHex = QString::number(slInfo[1].toInt(), 16);
				int nFill = 6 - sHex.length();
				QString sFill;
				sFill.fill( '0', nFill );
				QString sColor; /*! RGB */
				sColor = sFill;
				sColor += sHex;
				QString sRColor; /*! BGR 변환 */
				sRColor = sColor.right(2);
				sRColor += sColor.mid(2, 2);
				sRColor += sColor.left(2);
				sHEXColor += sRColor;
				
				int nSeper = slCommand[4].findRev("%09");
				QString sMessage( slCommand[4].mid( nSeper + 3 , slCommand[4].length() ) );
				QString sLogMsg( slCommand[4].mid( nSeper + 3 , slCommand[4].length() ) );
				
				if ( pBuddy->getStatus() == "X" )
				{
					/*! 비 버디 */
					QString sID( pBuddy->getUID() );
					/*! 대화창에 대화 표시 */
					addChatView( sFontName, sFontAttr, sHEXColor, sID, sMessage);
					/*! 대화 저장 */
					addChatLog( sID, sLogMsg ); /*! X 는 비버디 대화 */
				}
				else
				{
					QString sName( pBuddy->getName() );
					QString sNick( pBuddy->getNick() );
					Common::fixOutString( sNick );
					/*! 대화창에 대화 표시 */
					addChatView( sFontName, sFontAttr, sHEXColor, sName, sNick, sMessage);
					/*! 대화 저장 */
					addChatLog( sName, sNick, sLogMsg );
				}
				
				if ( !bSave ) bSave = true;
				
				if ( ! isVisible() )
				{
					ChatEditQTE->setFocus();
					showMinimized();
					emit gotChatMessage( slCommand );
				}
			}
#ifdef NETDEBUG
			else
			{
				kdDebug() << "pBuddy is 0 [" << slCommand[2] << "]" << endl;
			}
#endif
			/*!
			 * 마지막 메시지 받은 시간 표시
			 */
			QDateTime dtDateTime = QDateTime::currentDateTime();
			QDate date = dtDateTime.date();
			QTime time = dtDateTime.time();

			QString sStatusLabel;
			QString sDate;
			QString sTime;
			if (time.hour() <= 12)
			{
				sStatusLabel = QString::fromUtf8("마지막 메시지 받은 시각 : ");
				sDate.sprintf("%d-%02d-%02d", date.year(), date.month(), date.day());
				sStatusLabel += sDate;
				sStatusLabel += QString::fromUtf8(" 오전 ");
				sTime.sprintf("%02d:%02d", time.hour(), time.minute() );
				sStatusLabel += sTime;
			}
			else
			{
				sStatusLabel = QString::fromUtf8("마지막 메시지 받은 시각 : ");
				sDate.sprintf("%d-%02d-%02d", date.year(), date.month(), date.day());
				sStatusLabel += sDate;
				sStatusLabel += QString::fromUtf8(" 오후 ");
				sTime.sprintf("%02d:%02d", time.hour() - 12, time.minute() );
				sStatusLabel += sTime;
			}
			textLabel1->setText( sStatusLabel );
			
			/*! 입력중 타임 아웃 없앰. */
			bTypeTimeOut = FALSE;
			if ( pTypeTimer->isActive () )
				pTypeTimer->stop();
		}
		/*! 부재중 메시지 받으면, */
		else if ( slCommand[3] == "AWAYMSG" )
		{
			QString sMessage;
			pBuddy = getBuddyByID( slCommand[2] );

			if ( pBuddy )
			{
				QStringList slInfo = QStringList::split( "%09", slCommand[4], true );
				
				QString sFontName;
				if (slInfo[0] == "")
					sFontName = "굴림";
				else
					sFontName = slInfo[0];
				
				QString sFontAttr( slInfo[2] );
				
				QString sHEXColor( "#" );
				QString sHex = QString::number(slInfo[1].toInt(), 16);
				int nFill = 6 - sHex.length();
				QString sFill;
				sFill.fill( '0', nFill );
				QString sColor; /*! RGB */
				sColor = sFill;
				sColor += sHex;
				QString sRColor; /*! BGR 변환 */
				sRColor = sColor.right(2);
				sRColor += sColor.mid(2, 2);
				sRColor += sColor.left(2);
				sHEXColor += sRColor;
				
				int nSeper = slCommand[4].findRev("%09");
				QString sMessage( slCommand[4].mid( nSeper + 3 , slCommand[4].length() ) );
				QString sLogMsg( slCommand[4].mid( nSeper + 3 , slCommand[4].length() ) );
				
				if ( pBuddy->getStatus() == "X" )
				{
					/*! 비 버디 */
					QString sID( pBuddy->getUID() );
					/*! 대화창에 대화 표시 */
					addChatView( sFontName, sFontAttr, sHEXColor, sID, sMessage, TRUE );
					/*! 대화 저장 */
					addChatLog( sID, sLogMsg ); /*! X 는 비버디 대화 */
				}
				else
				{
					QString sName( pBuddy->getName() );
					QString sNick( pBuddy->getNick() );
					Common::fixOutString( sNick );
					/*! 대화창에 대화 표시 */
					addChatView( sFontName, sFontAttr, sHEXColor, sName, sNick, sMessage, TRUE );
					/*! 대화 저장 */
					addChatLog( sName, sNick, sLogMsg );
				}
				
				if ( !bSave ) bSave = true;
				
				if ( ! isVisible() )
				{
					ChatEditQTE->setFocus();
					showMinimized();
					emit gotChatMessage( slCommand );
				}
			}
#ifdef NETDEBUG
			else
			{
				kdDebug() << "pBuddy is 0 [" << slCommand[2] << "]" << endl;
			}
#endif
			
			QDateTime dtDateTime = QDateTime::currentDateTime();
			QDate date = dtDateTime.date();
			QTime time = dtDateTime.time();
      
			QString sStatusLabel;
			QString sDate;
			QString sTime;
			if (time.hour() <= 12)
			{
				sStatusLabel = QString::fromUtf8("마지막 메시지 받은 시각 : ");
				sDate.sprintf("%d-%02d-%02d", date.year(), date.month(), date.day());
				sStatusLabel += sDate;
				sStatusLabel += QString::fromUtf8(" 오전 ");
				sTime.sprintf("%02d:%02d", time.hour(), time.minute() );
				sStatusLabel += sTime;
			}
			else
			{
				sStatusLabel = QString::fromUtf8("마지막 메시지 받은 시각 : ");
				sDate.sprintf("%d-%02d-%02d", date.year(), date.month(), date.day());
				sStatusLabel += sDate;
				sStatusLabel += QString::fromUtf8(" 오후 ");
				sTime.sprintf("%02d:%02d", time.hour() - 12, time.minute() );
				sStatusLabel += sTime;
			}

			/*! 입력중 타임 아웃 없앰. */
			bTypeTimeOut = FALSE;
			if ( pTypeTimer->isActive () )
				pTypeTimer->stop();
			
			textLabel1->setText( sStatusLabel );
		}
		else if ( slCommand[3] == "TYPING" )
		{
			if (slCommand[4] == "1")
			{
				pBuddy = getBuddyByID( slCommand[2] );
				if (pBuddy)
				{
					/*! 상태줄 내용을 변수에 저장한다. */
					sSaveStatus = textLabel1->text();
					
					QString sStatusLabel;
					if ( pBuddy->getStatus() == "X" )
					{
						sStatusLabel = pBuddy->getUID();
						sStatusLabel += QString::fromUtf8(" 님이 메세지를 입력하고 있습니다.");
					}
					else
					{
						sStatusLabel = pBuddy->getName();
						sStatusLabel += " (";
						QString sNick = pBuddy->getNick();
            
						QFontMetrics fm = QWidget::fontMetrics();
						int pixelsWide = fm.width( " () 님이 메세지를 입력하고 있습니다." );
						QString sTemp = Common::qEllipsisText( sNick, QWidget::fontMetrics(), width() - pixelsWide, Qt::AlignLeft  );
            
						sStatusLabel += sTemp;
						sStatusLabel += QString::fromUtf8(") 님이 메세지를 입력하고 있습니다.");
					}

					if ( pTypeTimer->isActive() )
					{
						bTypeTimeOut = TRUE;
						pTypeTimer->changeInterval( 5000 );
					}
					else
					{
						bTypeTimeOut = TRUE;
						pTypeTimer->start( 5000, TRUE );
					}
					textLabel1->setText( sStatusLabel );
				}
			}
		}
	}
	else if ( slCommand[0] == "ENTR" )
	{
		emit putINVT(this);
	}
	else if ( slCommand[0] == "RCON" )
	{
		emit putENTRSS();
	}
	else if ( slCommand[0] == "QUIT" )
	{
		/*!
		 * 1. 상대가 대화창을 닫았을 때,
		 *  >> QUIT 0 [ID]
		 * 2. SS서버가 QUIT를 보낼 때,
		 *  >> QUIT 0 [ID] 1
		 * 필드 개수로 구분
		 */
		if ( slCommand.count() == 3 )
		{
			pBuddy = getBuddyByID( QString( slCommand[2] ) );
			if ( pBuddy )
			{
				pBuddy->setQuit( true );
				/*!
				 * 여러명일때는 대화방을 나갔습니다 표시하고, 나간 버디를 삭제한다.
				 * 단일 대화일때는 Quit를 true로 해서 다시 INVT를 날릴 수 있도록 한다.
				 */
				if ( m_BuddyList.count() > 1 )
				{
					/*
					KStandardDirs   *dirs   = KGlobal::dirs();
					QString         sPicsPath( dirs->findResource( "data", "knateon/pics/" ) );
					*/
          
					QString sMsg;
					sMsg = "<p style=\"margin-left:15px\"><font color=\"#FF0000\"><img src='";
					sMsg += sPicsPath;
					sMsg += "main_list_state_online.png'/>";
					sMsg += pBuddy->getName();
					sMsg += "(";
					QString sNick( pBuddy->getNick() );
					// sNick.replace("%20", " ");
          
					// if (!pEmoticon)
					// 	pEmoticon = Emoticon::instance(); // pEmoticon = new Emoticon();
					Common::fixOutString( sNick );
          
					sMsg += sNick;
					sMsg += ")";
					sMsg += QString::fromUtf8(" 님이 대화방을 나갔습니다.</p>");
					addChatView( sMsg ); // ChatViewQTE->append( sMsg );
          
					m_BuddyList.remove(pBuddy);
					updateNickNameLabel();
				}
			}
		}
		else /*! 서버가 QUIT를 보낼 때 */
		{
			pBuddy = getBuddyByID( QString( slCommand[2] ) );
			if ( pBuddy )
			{
				/*!
				 * INVT를 날릴 수 있도록
				 * Quit에 true를 세팅해 둔다.
				 */
				pBuddy->setQuit( true );
			}
		}
	}
	else if ( slCommand[0] == "JOIN" )
	{
		/*
		KStandardDirs   *dirs   = KGlobal::dirs();
		QString         sPicsPath( dirs->findResource( "data", "knateon/pics/" ) );
		*/
		if ( m_BuddyList.count() > 1 )
		{
			QString sMsg;
			sMsg = "<p style=\"margin-left:15px\"><font color=\"#008000\"><img src='";
			sMsg += sPicsPath;
			sMsg += "main_list_state_online.png'/>";
			sMsg += slCommand[4];
			sMsg += "(";
			QString sNick( slCommand[3] );
			// sNick.replace("%20", " ");

			// if (!pEmoticon)
			// 	pEmoticon = Emoticon::instance(); // pEmoticon = new Emoticon();
			Common::fixOutString( sNick );
      
			sMsg += sNick;
			sMsg += ")";
			sMsg += QString::fromUtf8(" 님이 대화에 참여했습니다.</p>");
			addChatView( sMsg ); // ChatViewQTE->append( sMsg );
		} 
		Buddy *pBuddy = getBuddyByID( slCommand[2] );
		if ( pBuddy )
			pBuddy->setQuit( false );
		else
			addBuddy( slCommand[2], false );
#if 1
		/*!
		  Queue 했던 메세지를 모두 join이 되었는지 확인 하고 보낸다.
		*/
		if ( isAllJoined() )
		{
			// QStringList slMsg;
			// slMsg = getMessageQueue();
			if ( !slMessageQueue.empty() )
			{
				for ( QStringList::Iterator it = slMessageQueue.begin(); it != slMessageQueue.end(); ++it ) {
					sendMessage( *it );
				}
				slMessageQueue.clear();
			}
			if ( !slSendFileList.empty() )
			{
				slotSendFileList( slSendFileList );
				slSendFileList.clear();
			}
			if ( trMessageQueueTimer )
				trMessageQueueTimer->stop();
		}
#endif
	}
	else if ( slCommand[0] == "USER" )
	{
		Buddy *pBuddy = getBuddyByID( slCommand[2] );
		if ( pBuddy )
			pBuddy->setQuit( false );
		else
			addBuddy( slCommand[4], false );
#if 1
		/*!
		  Queue 했던 메세지를 모두 join이 되었는지 확인 하고 보낸다.
		*/
		if ( isAllJoined() )
		{
#if 0
			QStringList slMsg;
			slMsg = getMessageQueue();
			for ( QStringList::Iterator it = slMsg.begin(); it != slMsg.end(); ++it ) {
				sendMessage( *it );
			}
			clearMessageQueue();
#endif
			if ( !slMessageQueue.empty() )
			{
				for ( QStringList::Iterator it = slMessageQueue.begin(); it != slMessageQueue.end(); ++it ) {
					sendMessage( *it );
				}
				slMessageQueue.clear();
			}
			if ( !slSendFileList.empty() )
			{
				slotSendFileList( slSendFileList );
				slSendFileList.clear();
			}
			
			if ( trMessageQueueTimer )
				trMessageQueueTimer->stop();
		}
#endif
	}
	return true;
}

void ChatView::gotFILE_REQUEST(const QStringList & slCommand)
{
	QStringList slData = QStringList::split(QString("%09"), slCommand[4]);

	/// 창이 있고, 보이지 않을때.
	if ( !isVisible() ) show();

	Buddy *pBuddy = getBuddyByID( slCommand[2] );
	if ( pBuddy ) {
		/*
		KStandardDirs   *dirs   = KGlobal::dirs();
		QString         sPicsPath( dirs->findResource( "data", "knateon/pics/" ) );
		*/
		
		QString sMsg;
		sMsg = "<img src='";
		sMsg += sPicsPath;
		sMsg += "chat_fileroom_private_btn.png'/>";
		sMsg += pBuddy->getName();
		sMsg += "(";
		
		QString sNick( pBuddy->getNick() );
		// if (!pEmoticon)
		// 	pEmoticon = Emoticon::instance(); // pEmoticon = new Emoticon();
		Common::fixOutString( sNick );
		
		sMsg += sNick;
		sMsg += ")";
		sMsg += QString::fromUtf8(" 님이 파일을 전송합니다.");
		
		addChatView( sMsg ); // ChatViewQTE->append( sMsg );
	}

	int nAllOk = KMessageBox::No;
	
	if ( slData[1] != "1" ) { /*! 파일 받을 개수 */
		/*! Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 */
		nAllOk = KMessageBox::messageBox(this, KMessageBox::QuestionYesNo, slData[1] + QString::fromUtf8("개의 파일을 전송하려고 합니다.\n모두 받으시겠습니까?"), QString::fromUtf8("파일전송") );
	}
	
	for(int i=0; i<slData[1].toInt(); i++) {
		QStringList slDatainfo = QStringList::split(QString("|"), slData[i+2]);
		
		/*! 파일명에서 %20을 공백으로 변환 */
		slDatainfo[0].replace("%20"," ");
		
		
		int nResult = KMessageBox::No;
		if ( nAllOk == KMessageBox::No ) {
			/*! Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 */
			nResult = KMessageBox::messageBox(this, KMessageBox::QuestionYesNo, QString::fromUtf8("상대방의 수락을 기다리는 중입니다.\n전송자: " + slCommand[2] + "\n파일명: ") + slDatainfo[0] + " (" + slDatainfo[1] + ")", QString::fromUtf8("파일전송") );
		}
		
		if ( nResult == KMessageBox::Yes ||  nAllOk == KMessageBox::Yes ) {
			// SendFileInfo(const QString MyID, const QString YourID, const QString File, unsigned long Size)
			SendFileInfo *pSendFileInfo = new SendFileInfo(m_sID, slCommand[2], slDatainfo[0], QString(slDatainfo[1]).toInt() );
			pSendFileInfo->setSSCookie( slDatainfo[2] );
			
			/*! 수신필드 셋팅 */
			pSendFileInfo->setReceive();
			m_SendFileInfoList.append(pSendFileInfo);
			
			/*! 대화창을 파일 전송정보에서 참조 */
			pSendFileInfo->setChatView( this );
			emit sendRECQNEW(this, pSendFileInfo);
		} else {
			QString sCmd;
			sCmd = slCommand[2];
			sCmd += " ";
			sCmd += slCommand[3];
			sCmd += " ";
			QString sTemp( slCommand[4] );
			sTemp.replace("REQUEST", "NACK");
			sCmd += sTemp;
			sCmd += "\r\n";
			sendCommandSS("WHSP", sCmd);
		}
	}
}


Buddy * ChatView::getBuddyByID(QString sID)
{
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	Buddy* pBuddy = 0;

	while(iterator.current() != 0)
	{
		pBuddy = iterator.current();
		if ( pBuddy->getUID() == sID )
		{
			return pBuddy;
		}
		++iterator;
	}
	return 0;
}

void ChatView::slotSendFileList(const QStringList & slFiles)
{
	if ( !isConnectedSS() ) {
		slSendFileList = slFiles;
		emit newConnectSS( this );
#ifdef NETDEBUG
		kdDebug() << "XXX>> Socket is Not Connected!!! [" << m_sSS_Server << "] [" << QString::number(m_nSS_Port) << "]" << endl;
#endif
		return;
	}
	
	/*! 파일 전송을 알림. */
	int j,l;
	srand ((unsigned int)time (NULL));
	j = 1 + (int) (1000.0 * (rand() / (RAND_MAX + 1.0)));
	l = 1 + (int) (1000.0 * (rand() / (RAND_MAX + 1.0)));
	/*! [INDEX]:[MYCMN]:[RANDOM_NUMBER(3)] */
	/*
	sRandom = QString::number(j);
	sRandom += ":";
	sRandom += m_pCurrentAccount->getMyCMN();
	sRandom += ":";
	sRandom += QString::number(l);
	*/
	
	// segfault TODO: 파일 전송에는 KIO의 network transparency를 이용한다
	
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	QString sBody;
	while(iterator.current() != 0) {
		Buddy* pBuddy = iterator.current();
		sBody = pBuddy->getUID();
		sBody += " FILE REQUEST%09";
		sBody += QString::number( slFiles.count() );
		for ( QStringList::ConstIterator it = slFiles.begin(); it != slFiles.end(); ++it ) {
			QString csFile( *it );
			unsigned long nFileSize = QFile(csFile).size() ;
			QString sFileName( csFile.right( csFile.length() - csFile.findRev("/") - 1 ) );
				/*! 파일명에서 공백을 %20으로 변환 */
			sFileName.replace(" ", "%20");
			sBody += "%09" + sFileName + "|" + QString::number( nFileSize ) + "|";
			QString sRandom;
			sRandom = QString::number(j++);
			sRandom += ":";
			sRandom += m_pCurrentAccount->getMyCMN();
			sRandom += ":";
			sRandom += QString::number(l);
			sBody += sRandom;
			SendFileInfo* pSendFileInfo = new SendFileInfo(m_sID, pBuddy->getUID(), csFile, nFileSize);
			pSendFileInfo->setSSCookie( sRandom );
			
		/*!
		  파일 전송 필드 셋팅
		  반대는 setReceive() 파일 수신 필드 셋팅.
		*/
			pSendFileInfo->setSend();
			/*
			KStandardDirs   *dirs   = KGlobal::dirs();
			QString         sPicsPath( dirs->findResource( "data", "knateon/pics/" ) );
			*/
			QString sMsg;
			sMsg = "<img src='";
			sMsg += sPicsPath;
			sMsg += "chat_fileroom_private_btn.png'/>";
			sMsg += pBuddy->getName();
			sMsg += "(";
			
			QString sNick( pBuddy->getNick() );
			Common::fixOutString( sNick );
			
			sMsg += sNick;
			sMsg += ")";
			sMsg += QString::fromUtf8(" 님에게 파일을 전송합니다.");
			addChatView( sMsg );
			
			/*! 파일 전송 정보에 대화창 포인터로 넘김 */
			pSendFileInfo->setChatView( this );
			
			/*! 전송 파일 목록으로 관리 */
			m_SendFileInfoList.append(pSendFileInfo);
			
			emit sendFile(pSendFileInfo);
		}
		sBody += "\r\n";
		
		/*!
		  ex>
		  WHSP 12 angelk76@nate.com FILE REQUEST%091%09file_transfer1.png|27636|71:2147483647:156
		*/
		sendCommandSS( "WHSP", sBody);
		++iterator;
	}
}

// void ChatView::slotSendFile(const QString& csFile)
void ChatView::slotSendFile()
{
	/*!
	QStringList getOpenFileNames ( const QString & filter = QString::null, const QString & dir = QString::null, QWidget * parent = 0, const char * name = 0, const QString & caption = QString::null, QString * selectedFilter = 0, bool resolveSymlinks = TRUE );
	*/
	QStringList slFileList = KFileDialog::getOpenFileNames(
		QDir::homeDirPath(),
		UTF8("*|모든 파일"),
		this,
		UTF8("파일 보내기")
		);
	if ( isAllJoined() )
	{
		slotSendFileList( slFileList );
	}
	else
	{
		emit newConnectSS( this );
		slSendFileList = slFileList;
	}
}

void ChatView::slotSendTyping()
{
	if (!bTyping && ChatEditQTE->text().length() > 0 )
	{
		sendCommandSS("MESG","TYPING 1\r\n");
		bTyping = true;
	}
	else
	{
		// 대화내용을 입력하다가 삭제하면, 상대방 대화창의 상태바에는 '대기중입니다' 메시지가 보여야한다.
		if( ChatEditQTE->text().length() == 0 )
		{
			sendCommandSS("MESG","TYPING 0\r\n");
			bTyping = false;
		}
	}
	if ( ChatEditQTE->length() > 0)
	{
		SendQPB->setEnabled();
	}
	else
	{
		SendQPB->setDisabled();
	}
}

bool ChatView::isAllJoined()
{
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	Buddy* pBuddy;

	while(iterator.current() != 0)
	{
		pBuddy = iterator.current();
		if ( pBuddy->isQuit())
		{
			return false;
		}
		++iterator;
	}
	return true;
}

void ChatView::slotMessageQueueFail()
{
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	Buddy* pBuddy;

	QString sMsg;

	int nTwo=0;
	while(iterator.current() != 0)
	{
		pBuddy = iterator.current();
		if ( pBuddy->isQuit())
		{
			if (!nTwo)
				sMsg = pBuddy->getName();
			else
			{
				sMsg += ", ";
				sMsg += pBuddy->getName();
			}
			// m_BuddyList.remove();
			nTwo = 1;
		}
		++iterator;
	}
  
	// QFont font( "굴림", 12 );
	// QFontMetrics fm( font );
	QFontMetrics fm = QWidget::fontMetrics();
	int pixelsWide = fm.width( "는 현재 메세지를 받을 수 없습니다." );
  
	QString sTemp = Common::qEllipsisText( sMsg, QWidget::fontMetrics(), width() - pixelsWide, Qt::AlignLeft );
	QString sTemp2;
	sTemp2 = sTemp;
	sTemp2 += QString::fromUtf8("는 현재 메세지를 받을 수 없습니다.");

	statusLabel->setText( sTemp2 );
	statusLabel->show();
	if (!trStatusLabelTimer)
	{
		trStatusLabelTimer = new QTimer( this );
		connect( trStatusLabelTimer, SIGNAL(timeout()), this, SLOT( slotHideStatusLabel() ) );
	}
	trStatusLabelTimer->start(5000, TRUE);
#if 0
	QStringList slMsg;
	slMsg = getMessageQueue();
	for ( QStringList::Iterator it = slMsg.begin(); it != slMsg.end(); ++it ) {
		sendMessage( *it );
	}
	clearMessageQueue();
#endif
	if ( !slMessageQueue.empty() )
	{
		for ( QStringList::Iterator it = slMessageQueue.begin(); it != slMessageQueue.end(); ++it ) {
			sendMessage( *it );
		}
		slMessageQueue.clear();
	}
	if ( !slSendFileList.empty() )
	{
		slotSendFileList( slSendFileList );
		slSendFileList.clear();
	}
	
	if ( trMessageQueueTimer )
		trMessageQueueTimer->stop();
}

void ChatView::slotHideStatusLabel()
{
	statusLabel->clear();
	statusLabel->hide();

	if ( trStatusLabelTimer )
		trStatusLabelTimer->stop();
}

void ChatView::addBuddy(Buddy * pBuddy)
{
	addBuddy(pBuddy, TRUE);
}

void ChatView::setDisabled()
{
	// ChatEditQTE->clear();
	ChatEditQTE->setDisabled( TRUE );
	ChatEditQTE->setPaletteBackgroundColor( QColor( 164, 167, 174 ) );
	frame3->setPaletteBackgroundColor( QColor( 164, 167, 174 ) );
	// ChatViewQTE->clear();
	ChatViewQTE->setDisabled( FALSE );
	SendQPB->setDisabled();
	emoticonButton->setDisabled();
	fileSendButton->setDisabled();
	fontButton->setDisabled();
	fontColorButton->setDisabled();
	inviteButton->setDisabled();

	action->setItemEnabled ( m_nInvite, FALSE );
	action->setItemEnabled ( m_nSendMemo, FALSE );
	action->setItemEnabled ( m_nSendFile, FALSE );
	buddy->setItemEnabled ( m_nAddBuddy, FALSE );
}

void ChatView::setEnabled()
{
	ChatEditQTE->setDisabled( FALSE );
	ChatEditQTE->setPaletteBackgroundColor( QColor( 249, 253, 255 ) );
	frame3->setPaletteBackgroundColor( QColor( 249, 253, 255 ) );
	ChatViewQTE->setDisabled( FALSE );
	if ( ChatEditQTE->length() > 0 )
		SendQPB->setEnabled();
	else
		SendQPB->setDisabled();
	emoticonButton->setEnabled();
	fileSendButton->setEnabled();
	fontButton->setEnabled();
	fontColorButton->setEnabled();
	inviteButton->setEnabled();
	
	action->setItemEnabled ( m_nInvite, TRUE );
	action->setItemEnabled ( m_nSendMemo, TRUE );
	action->setItemEnabled ( m_nSendFile, TRUE );
	buddy->setItemEnabled ( m_nAddBuddy, TRUE );
}

void ChatView::slotInviteDialog()
{
	emit updateInviteData(this);
}

void ChatView::showInviteDialog()
{
	if ( pAddBuddy )
		delete pAddBuddy;
	pAddBuddy = new AddBuddySelector(this, "XXX");
	connect(pAddBuddy, SIGNAL( selectedBuddies(const QString&) ), this, SLOT( slotAddBuddies(const QString& ) ) );

	QStringList slExcept;

	QPtrListIterator<Buddy> iterator(m_BuddyList);
	while(iterator.current() != 0)
	{
		Buddy* pBuddy = iterator.current();
		slExcept.append( pBuddy->getUID() );
		++iterator;
	}

	BuddyList *pBuddyList = m_pCurrentAccount->getBuddyList();
	GroupList *pGroupList = m_pCurrentAccount->getGroupList();
	// QPtrListIterator<Buddy> iterator(pBuddyList);
	iterator = *pBuddyList;
	while(iterator.current() != 0)
	{
		Buddy* pBuddy = iterator.current();
		if ( pBuddy->getStatus() == "F" ) /*! 쪽지 보내기에서는 F 도 보여야 함. */
		{
			slExcept.append( pBuddy->getHandle() );
		}
		/*! BL(Block List) == 1 */
		else if ( pBuddy->isBL() == TRUE || pBuddy->isFL() == FALSE )
		{
			slExcept.append( pBuddy->getHandle() );
		}
		++iterator;
	}
	
	pAddBuddy->setGroupList(pGroupList);
	pAddBuddy->setExceptList(slExcept);
	pAddBuddy->setBuddyList(pBuddyList);
	// pAddBuddy->setBuddyList( m_BuddyList );
  
	/// 석택되지 못한 QListView 목록 채움.
	pAddBuddy->setAllList();

	pAddBuddy->show();
}

void ChatView::slotAddBuddies(const QString & csList)
{
	// Buddy* pBuddy;
	QRegExp rx("<?([^@\\s<]+@[^>\\s]+)>?");

	QStringList slInviteList;
	slInviteList.clear();

	int pos = 0;
	while ( pos >= 0 )
	{
		pos = rx.search( csList, pos );
		if ( pos > -1 )
		{
			slInviteList.append( rx.cap(1) );
			pos  += rx.matchedLength();
		}
	}
	emit putINVT_Invite(this, slInviteList);
}

void ChatView::updateUserStatus(QString sID, QString sStatus)
{
	setEnabled();
	Buddy* pBuddy = getBuddyByID(sID);
  
	if ( pBuddy )
	{
		pBuddy->setStatus(sStatus);
		updateStatus(/* pBuddy */);
	}

	return;
}

void ChatView::updateUserFlag(QString sID, QString sFlag)
{
	setEnabled();
	Buddy* pBuddy = getBuddyByID(sID);
  
	if ( pBuddy )
	{
		pBuddy->setBuddyFlag( sFlag );
		updateStatus(/* pBuddy */);
	}
  
	return;
}

const QStringList ChatView::getBuddyIDList() const
{
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	Buddy* pBuddy;
	QStringList slIDs;

	while(iterator.current() != 0)
	{
		pBuddy = iterator.current();
		slIDs.append( pBuddy->getUID() );
		++iterator;
	}

	return slIDs;
}

void ChatView::show()
{
	// config->writeEntry("Size", size() );
	
	config->setGroup( "Chat" );
	QSize mySize( 380, 400 );
	resize( config->readSizeEntry("Size", &mySize ) );
		
#if 0
	config->setGroup( "Chat" );
	QFont font = config->readFontEntry( "Font", &( QFont( UTF8("굴림"), 10 ) ) );
	ChatEditQTE->setFont( font );
	ChatViewQTE->setFont( font );
#endif
	ChatEditQTE->setFocus();
	// QWidget::showMinimized();
	QWidget::show();
}


void ChatView::slotFontDialog()
{
	bool ok = false;
  
	config->setGroup( "Chat" );
	QFont myFont( UTF8("굴림"), 10 );
	QFont f = config->readFontEntry("Font", &myFont );
	QFont font = QFontDialog::getFont( &ok, f, this );

	if ( ok )
	{
#if 0
		ChatEditQTE->setFont( font );
		ChatViewQTE->setFont( font );
#endif
		config->writeEntry( "Font", font );
		config->sync();
  	ChatViewQTE->setPointSize( font.pointSize () );
  	ChatEditQTE->setFont( font );
	}
}

void ChatView::slotEmoticonDialog()
{
	if ( !pEmoticonSelector )
	{
		pEmoticonSelector = new EmoticonSelector( this, "EmoticonSelector" );
		connect(pEmoticonSelector->toolButton1, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton2, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton3, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton4, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton5, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton6, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton7, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton8, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton9, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton10, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton11, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton12, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton13, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton14, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton15, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton16, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton17, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton18, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton19, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton20, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton21, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton22, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton23, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton24, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton25, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton26, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton27, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton28, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton29, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton30, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton31, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton32, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton33, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton34, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton35, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton36, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton37, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton38, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton39, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton40, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton41, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton42, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton43, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton44, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton45, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton46, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton47, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton48, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton49, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton50, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton51, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton52, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton53, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton54, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton55, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton56, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton57, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton58, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton59, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton60, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton61, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton62, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton63, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton64, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton65, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton66, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton67, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton68, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton69, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton70, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton71, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton72, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton73, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton74, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton75, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton76, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton77, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton78, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton79, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton80, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton81, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton82, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton83, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton84, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton85, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton86, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton87, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton88, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton89, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton90, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton91, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton92, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton93, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton94, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton95, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton96, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton97, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton98, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton99, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton100, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton101, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton102, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton103, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton104, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton105, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton106, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton107, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton108, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton109, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton110, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton111, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton112, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton113, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton114, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton115, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton116, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton117, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton118, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton119, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton120, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton121, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton122, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton123, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton124, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton125, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton126, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton127, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton128, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton129, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton130, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton131, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton132, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton133, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton134, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton135, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton136, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton137, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton138, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton139, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton140, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton141, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton142, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton143, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
		connect(pEmoticonSelector->toolButton144, SIGNAL( clicked(const QString &) ), SLOT( slotPutEmoticon(const QString &) ) );
	}
  
	int screen = kapp->desktop()->screenNumber();
	QRect screenSize = kapp->desktop()->screenGeometry(screen);

	if ( ( x() + ( width() / 2) ) > ( screenSize.width() / 2 ) )
		pEmoticonSelector->move( x() - pEmoticonSelector->width(), y() + ( height() - pEmoticonSelector->height() ) );
	else
		pEmoticonSelector->move( x() + width(), y() + ( height() - pEmoticonSelector->height() ) );
	pEmoticonSelector->setModal( false );
	if ( pEmoticonSelector->isShown() )
		pEmoticonSelector->hide();
	else
		pEmoticonSelector->show();
  
}

void ChatView::slotPutEmoticon(const QString & sText)
{
	ChatEditQTE->insert( sText );
	ChatEditQTE->setActiveWindow ();
}

void ChatView::moveEvent ( QMoveEvent *e )
{
	ChatQW::moveEvent ( e );
	if ( pEmoticonSelector )
	{
		if ( pEmoticonSelector->isShown() )
		{
			int screen = kapp->desktop()->screenNumber();
			QRect screenSize = kapp->desktop()->screenGeometry(screen);

			if ( ( x() + ( width() / 2) ) > ( screenSize.width() / 2 ) )
				pEmoticonSelector->move( x() - pEmoticonSelector->width(), y() + ( height() - pEmoticonSelector->height() ) );
			else
				pEmoticonSelector->move( x() + width(), y() + ( height() - pEmoticonSelector->height() ) );
		}
	}
}

void ChatView::updateStatus( /* Buddy * pBuddy */ )
{
	bool bDialbe = FALSE;
	/*
	KStandardDirs   *dirs   = KGlobal::dirs();
	QString         sPicsPath( dirs->findResource( "data", "knateon/pics/" ) );
	*/
	QPtrListIterator<Buddy> iterator( getBuddyList() );
	QString sMsg;
	
	while(iterator.current() != 0)
	{
		Buddy *pBuddy = iterator.current();
		QString sNick = pBuddy->getNick();
		QFontMetrics fm = QWidget::fontMetrics();
		int pixelsWide = fm.width( pBuddy->getName() + " ()님이 [다른 용무 중]이므로 응답하지 않을 수도 있습니다." );
		
		QString sTemp = Common::qEllipsisText( sNick, QWidget::fontMetrics(), width() - pixelsWide, Qt::AlignLeft );

		if ( sMsg.length() > 1 )
			sMsg += "\n";

		/*! BL == 1 */
		if ( /* pBuddy->getBuddyFlag()[2] == '1'*/  pBuddy->isBL() == true  )
		{
			sMsg = pBuddy->getName();
			sMsg += " (";
			sMsg += sTemp;
			sMsg += ")";
			sMsg += QString::fromUtf8(" 님은 차단되었으므로 대화에 응답하지 않습니다.");
			bDialbe = TRUE;
			if ( pBuddy->getStatus() == "F" )
			{
				statusWidget->setShape( sPicsPath + "main_list_state_cut_offline.png" );
			}
			else
			{
				statusWidget->setShape( sPicsPath + "main_list_state_cut_online.png" );
			}
		}
		else
		{
			sMsg += QString::fromUtf8("님이 ");
			if (pBuddy->getStatus() == "A")
			{
				sMsg = pBuddy->getName();
				sMsg += " (";
				sMsg += sTemp;
				sMsg += ")";
				sMsg += QString::fromUtf8("[자리비움]");
				sMsg += QString::fromUtf8("이므로 응답하지 않을 수도 있습니다.");
				statusWidget->setShape( sPicsPath + "main_list_state_vacant.png" );
			}
			else if (pBuddy->getStatus() == "B")
			{
				sMsg = pBuddy->getName();
				sMsg += " (";
				sMsg += sTemp;
				sMsg += ")";
				sMsg += QString::fromUtf8("[다른 용무 중]");
				sMsg += QString::fromUtf8("이므로 응답하지 않을 수도 있습니다.");
				statusWidget->setShape( sPicsPath + "main_list_state_otherbusiness.png" );
			}
			else if (pBuddy->getStatus() == "P")
			{
				sMsg = pBuddy->getName();
				sMsg += " (";
				sMsg += sTemp;
				sMsg += ")";
				sMsg += QString::fromUtf8("[통화 중]");
				sMsg += QString::fromUtf8("이므로 응답하지 않을 수도 있습니다.");
				statusWidget->setShape( sPicsPath + "main_list_state_onphone.png" );
			}
			else if (pBuddy->getStatus() == "M")
			{
				sMsg = pBuddy->getName();
				sMsg += " (";
				sMsg += sTemp;
				sMsg += ")";
				sMsg += QString::fromUtf8("[회의 중]");
				sMsg += QString::fromUtf8("이므로 응답하지 않을 수도 있습니다.");
				statusWidget->setShape( sPicsPath + "main_list_state_meeting.png" );
			}
			else if (pBuddy->getStatus() == "F")
			{
				sMsg = pBuddy->getName();
				sMsg += " (";
				sMsg += sTemp;
				sMsg += ")";
				sMsg += QString::fromUtf8("[오프 라인]");
				sMsg += QString::fromUtf8("이므로 응답하지 않을 수도 있습니다.");
				statusWidget->setShape( sPicsPath + "main_list_state_offline.png" );
				bDialbe = TRUE;
			}
			else if (pBuddy->getStatus() == "O")
			{
				sMsg = "";
				statusWidget->setShape( sPicsPath + "main_list_state_online.bmp" );
				// return;
			}
		}
		++iterator;
	}
	
	_BuddyStatusText = sMsg;
	_BuddyDiable = bDialbe;
	updateStatusLabel();
	
	return;
}


/*!
  QString sCommand;
  sCommand = getID();
  sCommand += " TYPING 2\r\n";
  sendCommandSS( "MESG", sCommand );
  sendCommandSS( "QUIT", getID() + "\r\n" );
  if ( pEmoticonSelector )
  if ( pEmoticonSelector->isShown() )
  pEmoticonSelector->hide();
  emit hideChat(this);
*/
void ChatView::closeEvent(QCloseEvent * e)
{
    /*! 대화내용 저장 */
	int result;
	QString sChatLog;
	QString sCommand;

	if ( bGroupChat )
	{
		result = KMessageBox::  questionYesNo(this, QString::fromUtf8("대화창이 닫힙니다.\n대화창을 닫으시겠습니까?"), UTF8("대화 하기") );
		if ( result == KMessageBox::No )
			return;
	}


	bool bSaveChatLog = FALSE;
	if ( bSave )
	{
		switch( stConfig.savechatlog )
		{
		case 0: /*! 0: 저장 여부 확인하기 */
			result = KMessageBox::  questionYesNoCancel(this, QString::fromUtf8("대화 내용을 저장하시겠습니까?\n(환경 설정에서 저장 방법을 변경할 수 있습니다.)"), UTF8("대화 내용을 저장하시겠습니까?") );
			if ( result == KMessageBox::Yes )
				bSaveChatLog = TRUE;
			else if ( result == KMessageBox::Cancel )
				return;
			break;
		case 1: /*! 1: 자동저장 */
			bSaveChatLog = TRUE;
			break;
		case 2: /*! 2: 자동저장않기 */
			break;
		}
		sCommand = getID();
		sCommand += " TYPING 2\r\n";
		sendCommandSS( "MESG", sCommand );
		sendCommandSS( "QUIT", getID() + "\r\n" );
	}
	emit hideChat(this, bSaveChatLog);
	
	config->setGroup( "Chat" );
	config->writeEntry( "Font", ChatEditQTE->font() );

	if ( pEmoticonSelector )
		if ( pEmoticonSelector->isShown() )
			pEmoticonSelector->hide();
	
	// config->setGroup( "Chat" );
	config->writeEntry("Size", size() );
	config->sync();
	
	ChatQW::closeEvent(e);
}

void ChatView::dropEvent(QDropEvent * e)
{
	e = 0;
#ifdef NETDEBUG
	kdDebug() << "XXX : [" << e->format() << "]" << endl;
#endif
}

void ChatView::showNormal()
{
	/*! 창 숨겨서 보이기 */
#if 0
	config->setGroup( "Chat" );
	QFont font = config->readFontEntry( "Font", &( QFont( UTF8("굴림"), 10 ) ) );
	ChatEditQTE->setFont( font );
	ChatViewQTE->setFont( font );
#endif
	ChatEditQTE->setFocus();
	QWidget::showNormal();
}

void ChatView::slotFontColorDialog()
{
	// bool ok = false;
  
	config->setGroup( "Chat" );
	QColor myColor( "black" );
	QColor c = config->readColorEntry("FontColor", &myColor );
	QColor color = QColorDialog::getColor( c, this, "Font Color" );
  
	if ( color.isValid() )
	{
#ifdef NETDEBUG
		kdDebug() << "XXX Font Color XXX" << endl;
#endif
		config->writeEntry( "FontColor", color );
		config->sync();
		ChatEditQTE->setColor( color );
	}
}

/*!
 * Quit를 true로 해서 INVT를 보내도록 한다.
 */
void ChatView::addBuddy(const QString & sID, bool bQuit)
{
	Buddy *pBuddy;
	pBuddy = getBuddyByID( sID );
	if ( !pBuddy )
	{
		BuddyList* m_pBuddyList = m_pCurrentAccount->getBuddyList();
		pBuddy = m_pBuddyList->getBuddyByID( sID );
		if ( pBuddy )
		{
			pBuddy->setQuit(bQuit);
#if 0
			Buddy *mBuddy;
			mBuddy = (Buddy *)malloc( sizeof(Buddy) );
			memset( mBuddy, 0x00, sizeof(Buddy) );
			memcpy( mBuddy, pBuddy, sizeof(Buddy) );
#endif
			m_BuddyList.append(pBuddy);
      
			updateNickNameLabel();
			updateStatus( /* pBuddy */ );
			/*! BL(Block List) == 1 */
			if ( /* pBuddy->getBuddyFlag()[2] == '1' */  pBuddy->isBL() == true )
				buddy->changeItem ( lockID, UTF8("친구 차단 해제") );
			else
				buddy->changeItem ( lockID, UTF8("친구 차단") );

			// hompyWidget->show();
			statusWidget->show();
      
			emit BuddyAdded(pBuddy);
		}
		else
		{
			/*! 비버디 대화 */
			Buddy *pBuddy = new Buddy();
			pBuddy->setStatus("X");
			pBuddy->setGID( "9999" );
			pBuddy->setUID( sID );
			pBuddy->setName( QString::null );
			pBuddy->setNick( QString::null );
			pBuddy->setHandle( "9999999999" );
#ifdef NETDEBUG
			kdDebug() << "비버디 대화 ID : [" << sID << "]" << endl;
#endif

			m_BuddyList.append(pBuddy);

			setCaption( sID );
			QToolTip::add( nicknameLabel, sID );
			nicknameLabel->setText( sID );
			caption_ = sID;
			isNonBuddyChat = true;
      
			// hompyWidget->hide();
			statusWidget->hide();
			emit BuddyAdded(pBuddy);
		}
	}
	else
	{
		pBuddy->setQuit(bQuit);
		updateNickNameLabel();
		updateStatus( /* pBuddy */ );
		/*! BL == 1 */
		if ( /* pBuddy->getBuddyFlag()[2] == '1' */  pBuddy->isBL() == true )
			buddy->changeItem ( lockID, UTF8("친구 차단 해제") );
		else
			buddy->changeItem ( lockID, UTF8("친구 차단") );
	}
}

void ChatView::slotSave()
{
	emit saveChatLog(this, true);
	KMessageBox::information (this, UTF8("대화 내용을 저장하였습니다."), UTF8("대화 내용 저장"));
}

void ChatView::slotFileFolder()
{
	emit showDownDir();
}

void ChatView::slotShowChatLog()
{
	emit showChatLog( this );
}

void ChatView::slotClose()
{
	close();
}

void ChatView::slotInvite()
{
	emit updateInviteData(this);
}

void ChatView::slotSendMemo()
{
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	Buddy* pBuddy = iterator.current();
  
	if ( pBuddy )
	{
		emit sendMemo( pBuddy->getUID() );
	}
}

void ChatView::slotShowProfile()
{
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	Buddy* pBuddy = iterator.current();
  
	if ( pBuddy )
	{
		QString sURL("http://br.nate.com/index.php");
		sURL += "?code=F009";
		sURL += "&t=";
		sURL += m_pCurrentAccount->getMyTicket();
		sURL += "&param=";
		sURL += pBuddy->getHandle();;
#ifdef NETDEBUG
		kdDebug() << "Profile : [" << sURL << "]" <<endl;
#endif
		LNMUtils::openURL( sURL );
	}
}

void ChatView::slotAddBuddy()
{
	emit addBuddy();
}

void ChatView::slotLock()
{
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	Buddy* pBuddy = iterator.current();
  
	if ( pBuddy )
	{
		emit lockToggle( pBuddy->getUID() );
		/*! BL == 1 */
		if ( pBuddy->isBL() == true )
		{
			buddy->changeItem ( lockID, UTF8("친구 차단 해제") );
		}
		else
		{
			buddy->changeItem ( lockID, UTF8("친구 차단") );
		}
	}
}

void ChatView::slotOnline()
{
}

void ChatView::slotAway()
{
}

void ChatView::slotBusy()
{
}

void ChatView::slotPhone()
{
}

void ChatView::slotMeeting()
{
}

void ChatView::slotOffline()
{
}

void ChatView::slotChangeNick()
{
	emit changeNick();
}

void ChatView::slotEditMyProfile()
{
	QString sURL("http://br.nate.com/index.php");
	sURL += "?code=F010";
	sURL += "&t=";
	sURL += m_pCurrentAccount->getMyTicket();
	sURL += "&param=";
	sURL += m_pCurrentAccount->getMyCMN();
#ifdef NETDEBUG
	kdDebug() << "Profile : [" << sURL << "]" <<endl;
#endif
	LNMUtils::openURL( sURL );
}

void ChatView::slotAlwaysTop()
{
	/*
	int flags = getWFlags();
  
	flags |= Qt::WStyle_StaysOnTop;
	QPoint p(geometry().x(),geometry().y());
	reparent(0,flags,p,true);
	 */

	int flags = getWFlags();
	
#if 0
	stConfig.alwaystop = bTop;
	config->setGroup( "Config_General" );
	config->writeEntry( "Always_Top", stConfig.alwaystop );
#endif
	
	/*! 메뉴의 항상위 채크 */
	if ( bAlwaysTop )
	{
		if( testWFlags(Qt::WStyle_StaysOnTop) )
		{
			flags ^= Qt::WStyle_StaysOnTop;
			QPoint p(geometry().x(),geometry().y());
			reparent(0,flags,p,true);
		}
		bAlwaysTop = FALSE;
		setup->setItemChecked( nAlwaysTopID, FALSE );
	}
	else
	{
		if( !testWFlags(Qt::WStyle_StaysOnTop) )
		{
			flags |= Qt::WStyle_StaysOnTop;
			QPoint p(geometry().x(),geometry().y());
			reparent(0,flags,p,true);
		}
		bAlwaysTop = TRUE;
		setup->setItemChecked( nAlwaysTopID, TRUE );
	}
	
}

void ChatView::slotSetup()
{
	emit showSetup();
}

void ChatView::slotGoNateonHome()
{
	LNMUtils::openURL( "http://nateonweb.nate.com" );
}

void ChatView::slotGoCyworldHome()
{
	LNMUtils::openURL( "http://cyworld.nate.com" );
}

void ChatView::slotGoNateDotComHome()
{
	LNMUtils::openURL( "http://www.nate.com" );
}

void ChatView::slotGoHotTip()
{
	LNMUtils::openURL( "http://nateonweb.nate.com/help/guide_hottip_v3_main.html" );
}

void ChatView::slotGoNateonMiniHompy()
{
	LNMUtils::openURL( "http://cyworld.nate.com/nateoncyevent" );
}

void ChatView::slotGoHelp()
{
	QString sURL("http://br.nate.com/index.php");
	sURL += "?code=E069";
	LNMUtils::openURL( sURL );
}

void ChatView::slotGoFaq()
{
	LNMUtils::openURL( "http://nateonweb.nate.com/help/guide_faqsearch_list.html");
}

void ChatView::slotInfo()
{
#if 1
	if ( !helpMenu_ )
		helpMenu_= new KHelpMenu(this, KGlobal::instance()->aboutData());
	helpMenu_->aboutApplication();
#endif
}

void ChatView::resizeEvent(QResizeEvent * e)
{
	// updateNickNameLabel();
	// nicknameLabel->setText();
	// statusLabel->setText();
	// textLabel1->setText();
	QWidget::resizeEvent( e );
}

void ChatView::slotChangeStatus( int nStatus )
{
	QString sMsg;
	bool bDialbe = FALSE;
	
	switch( nStatus )
	{
	case 0 :
		sMsg = "";
		online->setOn ( true );
		break;
	case 1 :
		sMsg = UTF8("회원님은 현재 ");
		sMsg += UTF8("[자리비움]");
		sMsg += UTF8("으로 설정되어 있습니다.");
		away->setOn ( true );
		break;
	case 2 :
		sMsg = UTF8("회원님은 현재 ");
		sMsg += UTF8("[다른 용무 중]");
		sMsg += UTF8("으로 설정되어 있습니다.");
		busy->setOn ( true );
		break;
	case 3 :
		sMsg = UTF8("회원님은 현재 ");
		sMsg += UTF8("[통화 중]");
		sMsg += UTF8("으로 설정되어 있습니다.");
		phone->setOn ( true );
		break;
	case 4 :
		sMsg = UTF8("회원님은 현재 ");
		sMsg += UTF8("[회의 중]");
		sMsg += UTF8("으로 설정되어 있습니다.");
		meeting->setOn ( true );
		break;
	case 5 :
		offline->setOn ( true );
		sMsg = UTF8("회원님은 현재 ");
		sMsg += UTF8("[오프라인]");
		sMsg += UTF8("으로 설정되어 있습니다.");
		bDialbe = TRUE;
		break;
	}
	_MyDiable = bDialbe;
	_MyStatusText = sMsg;
	updateStatusLabel();
}

void ChatView::setCurrentAccount(CurrentAccount * pCurrentAccount)
{
	m_pCurrentAccount = pCurrentAccount;
	// slotChangeStatus( m_pCurrentAccount->getStatus() );
	switch( m_pCurrentAccount->getStatus() )
	{
	case 'O':
		slotChangeStatus( 0 );
		break;
	case 'A':
		slotChangeStatus( 1 );
		break;
	case 'B':
		slotChangeStatus( 2 );
		break;
	case 'P':
		slotChangeStatus( 3 );
		break;
	case 'M':
		slotChangeStatus( 4 );
		break;
	case 'F':
		slotChangeStatus( 5 );
		break;
	}
}

void ChatView::putSuccessFileTransfer(SendFileInfo * pSendFileInfo)
{
	/*
	KStandardDirs   *dirs   = KGlobal::dirs();
	QString         sPicsPath( dirs->findResource( "data", "knateon/pics/" ) );
  	*/
	
	QString sMsg;
	sMsg = "<img src='";
	sMsg += sPicsPath;
	sMsg += "chat_fileroom_private_btn.png'/>";
#if 1
	if ( pSendFileInfo->getFileName().findRev("/") == -1 )
		sMsg += pSendFileInfo->getFileName();
	else
		sMsg += pSendFileInfo->getFileName().right( pSendFileInfo->getFileName().length() -  pSendFileInfo->getFileName().findRev("/") - 1 );
#endif
	sMsg += "(";
	if ( pSendFileInfo->getFileSize() < 1000)
	{
		sMsg += QString::number( pSendFileInfo->getFileSize() );
		sMsg += "Byte";
	}
	else if ( ( 1000000 > pSendFileInfo->getFileSize() )
	          && ( pSendFileInfo->getFileSize() >= 1000 ) )
	{
		sMsg += QString::number( pSendFileInfo->getFileSize() / 1024 );
		sMsg += "KB";
	}
	else if ( pSendFileInfo->getFileSize() >= 1000000 )
	{
		sMsg += QString::number( ( pSendFileInfo->getFileSize() / 1024 ) / 1024 );
		sMsg += "MB";
	}
	sMsg += ")";
	sMsg += QString::fromUtf8("전송을 완료했습니다.");
    
	addChatView( sMsg ); // ChatViewQTE->append( sMsg );
}

void ChatView::sendAwayMessage()
{
	if ( !isConnectedSS() )
	{
		emit newConnectSS( this );
#ifdef NETDEBUG
		kdDebug() << "XXX>> Socket is Not Connected!!! [" << m_sSS_Server << "] [" << QString::number(m_nSS_Port) << "]" << endl;
#endif
		return;
	}
	config->setGroup( "Config_Message" );
	QFont myFont( UTF8("굴림"), 10 );
	QFont font = config->readFontEntry( "Away_Message_Font", &myFont );
	QColor myColor( "black" );
	QColor color = config->readColorEntry("Away_Message_FontColor", &myColor );
	QString sMsg = config->readEntry( "Away_Message" );
	QString sName( m_pCurrentAccount->getMyName() );
	QString sNick( m_pCurrentAccount->getMyNickName() );
	Common::fixOutString( sNick );
	
	QString sMessage( sMsg );
	QString sSendMsg( sMsg );
	QString sLogMsg( sMsg );

	/*!대화창에 대화 내용 보임. */ 
	addChatViewAway( font, color, sName, sNick, sMessage );
	
	/*! 상대에게 메시지 보내기 */
	sendChatCommand( font, color, QString("AWAYMSG"), sSendMsg );
	
	/*! 저장 로그 */
	addChatLog( sName, sNick, sLogMsg );
}

void ChatView::updateStatusLabel()
{
	QString sMsg;
	sMsg = _BuddyStatusText;
	if ( sMsg.length() > 0 )
	{
		sMsg += "\n";
		sMsg += _MyStatusText;
	}
	else
	{
		sMsg = _MyStatusText;
	}
	
	statusLabel->setText( sMsg );

	if ( ( _BuddyStatusText.length() > 0 ) || ( _MyStatusText.length() > 0 ) )
		statusLabel->show();
	else
		statusLabel->hide();

	if ( _BuddyDiable || _MyDiable )
		setDisabled();
	else
		setEnabled();
}

void ChatView::slotTypeTimeOut()
{
	if ( bTypeTimeOut )
	{
		textLabel1->setText( sSaveStatus );
	}
}

void ChatView::showEvent(QShowEvent * e)
{
	ChatEditQTE->setFocus();
	QWidget::showEvent( e );
}

void ChatView::gotFILE_NACK(const QStringList & slCommand)
{
	/*
	QString         sPicsPath( KGlobal::dirs()->findResource( "data", "knateon/pics/" ) );
	*/
	Buddy *pBuddy = getBuddyByID( slCommand[2] );
	if ( pBuddy )
	{
		QString sMsg;
		sMsg = "<img src='";
		sMsg += sPicsPath;
		sMsg += "chat_fileroom_private_btn.png'/>";
		sMsg += pBuddy->getName();
		sMsg += "(";
		
		QString sNick( pBuddy->getNick() );
		// if (!pEmoticon)
		// 	pEmoticon = Emoticon::instance(); // pEmoticon = new Emoticon();
		Common::fixOutString( sNick );
		
		sMsg += sNick;
		sMsg += ")";
		sMsg += QString::fromUtf8(" 님이 파일을 전송을 취소했습니다.");
		
		/*!
		* 대화창을 파일 전송정보에서 참조
		*/
		addChatView( sMsg ); // ChatViewQTE->append( sMsg );
	}
}

void ChatView::gotFILE_CANCEL(const QStringList & slCommand)
{
	/*
	QString         sPicsPath( KGlobal::dirs()->findResource( "data", "knateon/pics/" ) );
	*/
	Buddy *pBuddy = getBuddyByID( slCommand[2] );
	if ( pBuddy )
	{
		QString sMsg;
		sMsg = "<img src='";
		sMsg += sPicsPath;
		sMsg += "chat_fileroom_private_btn.png'/>";
		sMsg += pBuddy->getName();
		sMsg += "(";
		
		QString sNick( pBuddy->getNick() );
		// if (!pEmoticon)
		//	pEmoticon = Emoticon::instance(); // pEmoticon = new Emoticon();
		Common::fixOutString( sNick );
		
		sMsg += sNick;
		sMsg += ")";
		sMsg += QString::fromUtf8(" 님이 파일을 전송을 취소했습니다.");
		
		/*!
		* 대화창을 파일 전송정보에서 참조
		*/
		addChatView( sMsg ); // ChatViewQTE->append( sMsg );

		QStringList slInfo = QStringList::split( "%09", slCommand[4] );
		
		emit cancelFileTransfer( slInfo[2] ) ;
	}
}

void ChatView::sendFILE_CANCEL(const QString & sSSCookie)
{
	QPtrListIterator<Buddy> iterator(m_BuddyList);
	
	while(iterator.current() != 0)
	{
		Buddy* pBuddy = iterator.current();
		QString sCommand;
		sCommand = pBuddy->getUID();
		sCommand += " ";
		sCommand += "FILE";
		sCommand += " ";
		sCommand += "CANCEL%091%09";
		sCommand += sSSCookie;
		sCommand += "\r\n";
		sendCommandSS( "WHSP", sCommand );
		++iterator;
	}
}

void ChatView::myCancel()
{
	/*
	QString sPicsPath( KGlobal::dirs()->findResource( "data", "knateon/pics/" ) );
	*/
	QString sMsg;
	sMsg = "<img src='";
	sMsg += sPicsPath;
	sMsg += "chat_fileroom_private_btn.png'/>";
	sMsg += QString::fromUtf8("파일을 전송을 취소했습니다.");
	
		/*!
		* 대화창을 파일 전송정보에서 참조
		*/
	addChatView( sMsg ); // ChatViewQTE->append( sMsg );
}

void ChatView::slotBuddyChangeNick()
{
	updateNickNameLabel();
}

bool ChatView::putRCONSS()
{
	QString sCommand( m_sSS_Server );
	sCommand += " ";
	sCommand += QString::number( m_nSS_Port );
	sCommand += "\r\n";
	sendCommandSS("RCON", sCommand );
	return TRUE;
}

/*! 
 * 버디리스트가 같은지 확인하는 함수
 * 채팅창 띄울때 비교하기 위해서 사용.
 */
bool ChatView::isEqualBuddyList(QStringList slBuddys)
{
	if ( slBuddys.count() != m_BuddyList.count() )
		return FALSE;
	
	for ( QStringList::Iterator it = slBuddys.begin(); it != slBuddys.end(); ++it ) {
		if ( !getBuddyByID( *it ) ) {
			return FALSE;
		}
	}
	return TRUE;
}

void ChatView::addChatLog(const QString & sLog)
{
	// m_pCommon->removePercents( sLog );
	sChatSaveLog.append( sLog );
}

/*! 비 버디 대화 */
void ChatView::addChatLog(QString & sID, QString & sMessage)
{
	QString sLog(sID);
	sLog += QString::fromUtf8(" 님의 말 :\n");
	// m_pCommon->removePercents( sMessage );
	Common::fixOutString( sMessage );
	sLog += sMessage;
	sLog += "\n";
	sChatSaveLog.append( sLog );
}

void ChatView::addChatLog(QString &sName, QString &sNick, QString &sMessage)
{
	/*! 저장 로그 */
	QString sLog(sName);
	sLog += " ( ";
	sLog += sNick;
	sLog += QString::fromUtf8(" ) 님의 말 :\n");
	// m_pCommon->removePercents( sMessage );
	Common::fixOutString( sMessage );
	sLog += sMessage;
	sLog += "\n";
	sChatSaveLog.append( sLog );
}

/*! 부재중 메시지 */
void ChatView::addChatLog2(QString & sName, QString & sNick, QString & sMessage)
{
	QString sLog(sName);
	sLog += " ( ";
	sLog += sNick;
	sLog += QString::fromUtf8(" ) 님의 부재중 메시지 :\n");
	// m_pCommon->removePercents( sMessage );
	Common::fixOutString( sMessage );
	sLog += sMessage;
	sLog += "\n";
	sChatSaveLog.append( sLog );
}

void ChatView::addChatView(QString m_Msg)
{
	ChatViewQTE->append(m_Msg);
	ChatViewQTE->moveCursor ( QTextEdit::MoveEnd, FALSE );
}

void ChatView::addChatView(QFont & pFont, QColor & pColor, QString & sName, QString & sNick, QString & sMessage)
{
	QString sHeader = "<p style=\"margin-left:3px\">" + sName + "(" + sNick + QString::fromUtf8(")님의 말 :</p>");
	addChatViewBody( pFont, pColor, sHeader, sMessage );
}

void ChatView::addChatViewAway(QFont & pFont, QColor & pColor, QString & sName, QString & sNick, QString & sMessage)
{
	QString sHeader = "<p style=\"margin-left:3px\">" + sName + "(" + sNick + QString::fromUtf8(")님의 부재중 메시지 :</p>");
	addChatViewBody( pFont, pColor, sHeader, sMessage );
}

void ChatView::addChatViewBody(QFont & pFont, QColor & pColor, QString & sHeader, QString & sMessage)
{
	QString sHTMLBody;
	sHTMLBody = sHeader;
	sHTMLBody += "<p style=\"margin-left:15px\"><font face=\"";
	sHTMLBody += pFont.family();
	sHTMLBody += "\"";
	
	QStyleSheet* tempStyle;
	tempStyle = ChatEditQTE->styleSheet();
	int fontSize = 3;
	tempStyle->scaleFont(pFont, fontSize);
	sHTMLBody += " ";
	sHTMLBody += "size=\"";
	sHTMLBody += QString::number( fontSize );
	sHTMLBody += "\"";
	
	if ( pColor != "0" )
	{
		sHTMLBody += " color=\"#";
		QString sHex;
		sHex.sprintf("%02x%02x%02x", pColor.red(), pColor.green(), pColor.blue() );
		sHTMLBody += sHex;
		sHTMLBody += "\"";
	}
	sHTMLBody +=">";
	
	if ( pFont.bold() ) sHTMLBody += "<b>"; /*! Bold */
	if ( pFont.italic() ) sHTMLBody += "<i>"; /*! Italic */
	if ( pFont.underline() ) sHTMLBody += "<u>"; /*! Underline */
	if ( pFont.strikeOut() ) sHTMLBody += "<s>"; /*! Strikeout */
	
	kdDebug() << "Before : " << sMessage << endl;
	
	sMessage.replace("&", "&amp;" );
	sMessage.replace("<", "&lt;");
	sMessage.replace(">", "&gt;");
	sMessage.replace(' ', "&nbsp;");
	sMessage.replace('\n', "<br>");
	
	Emoticon *pEmoticon	= Emoticon::instance();
	pEmoticon->replaseEmoticons( sMessage );
	
	kdDebug() << "After : " << sMessage << endl;
	sHTMLBody += sMessage;
	
	if ( pFont.strikeOut () ) sHTMLBody += "</s>"; /*! Strikeout */
	if ( pFont.underline () ) sHTMLBody += "</u>"; /*! Underline */
	if ( pFont.bold() ) sHTMLBody += "</b>"; /*! Bold */
	if ( pFont.italic() ) sHTMLBody += "</i>"; /*! Italic */
	
	sHTMLBody += "</font>";
	sHTMLBody += "</p>";
	
#if 0
	kdDebug() << "CHAT MSG : [" << sHTMLBody << "]" << endl;
#endif
	addChatView( sHTMLBody );
}

void ChatView::sendChatCommand(QFont & pFont, QColor & pColor, QString sCode, QString & sMessage)
{
	QString sCommand( sCode );
	sCommand += " ";
	
	QString fontName( pFont.family() );
	fontName.replace(" ", "%20");
	sCommand += fontName;
	sCommand += "%09";
	
	QString sColor;
	if ( pColor == QColor("black") )
		sColor = "0"; /*!  Color 124124124 */
	else {
		QString sTempColor;
		sTempColor.sprintf( "%02x%02x%02x", pColor.blue(), pColor.green(), pColor.red() );
		kdDebug() << "HEX : [" << sTempColor << "]" << endl;
		int nTemp = 0;
		int base = 1;
		for ( int i=5; i>=0; i-- ) {
			nTemp += htoi( sTempColor[i].latin1() ) * base;
			base *= 16;
		}
		sColor = QString::number( nTemp );
		kdDebug() << "DEC : [" << sColor << "]" << endl;
	}
	
	sCommand += sColor;
	sCommand += "%09";
	
	if ( pFont.bold() ) sCommand += "B"; /*! Bold */
	if ( pFont.italic() ) sCommand += "I"; /*! Italic */
	if ( pFont.underline () ) sCommand += "U"; /*! Underline */
	if ( pFont.strikeOut () ) sCommand += "S"; /*! Strikeout */
	sCommand += "%09";

#if 1
	sMessage.replace("%", "%25");
	sMessage.replace(" ", "%20");
	sMessage.replace("\n", "%0A");
	sMessage.replace("\r", "%0D");
#endif
	sCommand += sMessage + "\r\n";
	/*!
	 * 채팅 명령 보냄
	 */
	sendCommandSS("MESG", sCommand);
}

/*!
 * Qt TextEdit 에서 예제. 대소문자 구분함. 소문자로
 * <b>ddddd</b><font color="#ff00ff" size="+1" face="바탕">dfdsfdsf</font>
 * <p style="margin-top:14px"><span style="font-size:10pt;font-weight:600">aaa</span></p>
 * <p style="margin-left:40px;margin-right:40px;margin-bottom:10px">
 * <span style="font-family:휴먼옛체;color:#808000">ㄴㅣㅏㅣㅏㅣㅏ</span></p>
 */
void ChatView::addChatView(QString & sFontName, QString &sFontAttr, QString & sHEXColor, QString & sName, QString & sNick, QString & sMessage, bool bAway)
{
	QString sHeader;	
	if ( bAway )
		sHeader = "<p style=\"margin-left:3px\">" + sName + "(" + sNick + QString::fromUtf8(")님의 부재중 메시지 :</p>");
	else
		sHeader = "<p style=\"margin-left:3px\">" + sName + "(" + sNick + QString::fromUtf8(")님의 말 :</p>");
	addChatViewBody( sFontName, sFontAttr, sHEXColor, sHeader, sMessage );
}

void ChatView::addChatView(QString & sFontName, QString &sFontAttr, QString & sHEXColor, QString & sID, QString & sMessage, bool bAway)
{
	QString sHeader;
	if ( bAway )
		sHeader = "<p style=\"margin-left:3px\">" + sID + QString::fromUtf8(" 님의 부재중 메시지 :</p>");
	else
		sHeader = "<p style=\"margin-left:3px\">" + sID + QString::fromUtf8(" 님의 말 :</p>");
	addChatViewBody( sFontName, sFontAttr, sHEXColor, sHeader, sMessage );
}

void ChatView::addChatViewBody(QString & sFontName, QString &sFontAttr, QString & sHEXColor, QString & sHeader, QString & sMessage)
{
	QString sHTMLString;
	sHTMLString += sHeader;
	sHTMLString += "<p style=\"margin-left:15px\"><font face=\"";
	sHTMLString += sFontName;
	sHTMLString += "\"";
	sHTMLString += " color=\"";
	sHTMLString += sHEXColor;
	sHTMLString += "\"";
	sHTMLString +=">";
	
	bool bBold = FALSE;
	bool bItaric = FALSE;
	bool bUnderline = FALSE;
	bool bStrong = FALSE;

	if ( sFontAttr.find('B') != -1 ) bBold = TRUE;
	if ( sFontAttr.find('I') != -1 ) bItaric= TRUE;
	if ( sFontAttr.find('U') != -1 ) bUnderline = TRUE;
	if ( sFontAttr.find('S') != -1 ) bStrong = TRUE;
	
	if ( bBold ) sHTMLString += "<b>";
	if ( bItaric ) sHTMLString += "<i>";
	if ( bUnderline ) sHTMLString += "<u>";
	if ( bStrong ) sHTMLString += "<s>";

	QString sSaveBody( sMessage );
#ifdef NETDEBUG
	kdDebug() << "X : [" << sSaveBody << "]" << endl;
#endif
				/*! 플래시콘 체크 */
	if ( sSaveBody.find( QRegExp("<FLCON.*FLCON>") ) != -1 )
		sSaveBody = UTF8("플래시콘을 보내셨습니다.%0D%0A현재 리눅스 버전은 플래시콘을 지원하지 않습니다.");
	
	kdDebug() << "Before : [" << sSaveBody << "]" << endl;
	sSaveBody.replace('&', "&amp;" );
	sSaveBody.replace('<', "&lt;");
	sSaveBody.replace('>', "&gt;");
	sSaveBody.replace( "%20", "&nbsp;" );
	sSaveBody.replace( "%0A", "<br>");
	Common::fixOutString( sSaveBody );
	kdDebug() << "After : [" << sSaveBody << "]" << endl;
	
	sHTMLString += sSaveBody;
	
	if ( bStrong ) sHTMLString += "</s>";
	if ( bUnderline ) sHTMLString += "</u>";
	if ( bItaric ) sHTMLString += "</i>";
	if ( bBold ) sHTMLString += "</b>";
	
	sHTMLString+= "</font></p>";
	sHTMLString.stripWhiteSpace ();
	
	kdDebug() << "HTML : [" << sHTMLString << "]" << endl;
	
	addChatView( sHTMLString );
}

int ChatView::htoi(const char hex)
{
	if (hex>='0' and hex<='9') return int(hex-'0');
	else if (hex>='a' and hex<='f') return int(hex-'a')+10;
	else if (hex>='A' and hex<='F') return int(hex-'A')+10;
	else return 0;
}



