void KviThemedComboBox::applyOptions()
{
#ifdef COMPILE_PSEUDO_TRANSPARENCY
	bool bIsTrasparent = (KVI_OPTION_BOOL(KviOption_boolUseCompositingForTransparency) && g_pApp->supportsCompositing()) || g_pShadedChildGlobalDesktopBackground;
#else
	bool bIsTrasparent = false;
#endif

	if(style()->objectName() == "oxygen" || style()->objectName().startsWith("ia-ora-"))
	{
		// workaround for broken oxygen in kde4.4: use palette() instead that stylesheet
		// ia-ora- are the mandriva default styles
		setFont(KVI_OPTION_FONT(KviOption_fontLabel));
		QPalette pal = palette();
		pal.setBrush(QPalette::Base, bIsTrasparent ? Qt::transparent : KVI_OPTION_COLOR(KviOption_colorLabelBackground));
		//qcombobox forces QPalette::Text as its forecolor
		pal.setBrush(QPalette::Text, bIsTrasparent ? KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_NONE).fore()) : KVI_OPTION_COLOR(KviOption_colorLabelForeground));
		setPalette(pal);
	} else {
		QString szStyle = QString("QComboBox { background: %1; color: %2; font-family: %3; font-size: %4pt; font-weight: %5; font-style: %6;}")
			.arg(bIsTrasparent ? "transparent" : KVI_OPTION_COLOR(KviOption_colorLabelBackground).name())
			.arg(bIsTrasparent ? KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_NONE).fore()).name() :
				KVI_OPTION_COLOR(KviOption_colorLabelForeground).name())
		.arg(KVI_OPTION_FONT(KviOption_fontLabel).family())
		.arg(KVI_OPTION_FONT(KviOption_fontLabel).pointSize())
		.arg(KVI_OPTION_FONT(KviOption_fontLabel).weight() == QFont::Bold ? "bold" : "normal")
		.arg(KVI_OPTION_FONT(KviOption_fontLabel).style() == QFont::StyleItalic ? "italic" : "normal");
		setStyleSheet(szStyle);
	}
	update();
}
예제 #2
0
파일: KviWindow.cpp 프로젝트: wodim/kronos
void KviWindow::internalOutput(KviIrcView * pView, int iMsgType, const kvi_wchar_t * pwText, int iFlags)
{
    // all roads lead to Rome :)

    if(pView)
    {
        if(!hasAttention())
        {
            iFlags |= KviIrcView::TriggersNotification;
            if(!pView->hasLineMark())
            {
                iFlags |= KviIrcView::SetLineMark;
            }
        }
        pView->appendText(iMsgType,pwText,iFlags);
    } else {
        // Redirect to the output proxy
        KviWindow * pWnd = outputProxy();
        if(pWnd)
            pWnd->outputNoFmt(iMsgType,pwText,iFlags);
    }

    if(!m_pWindowListItem)
        return;

    // if this option is checked we don't highlight other than channel msg
    if(KVI_OPTION_BOOL(KviOption_boolHighlightOnlyNormalMsg))
    {
        if((iMsgType != KVI_OUT_CHANPRIVMSG) && (iMsgType != KVI_OUT_CHANPRIVMSGCRYPTED))
        {
            if(!(
                        (
                            KVI_OPTION_BOOL(KviOption_boolHighlightOnlyNormalMsgQueryToo) &&
                            (
                                (iMsgType == KVI_OUT_QUERYPRIVMSG) || (iMsgType == KVI_OUT_QUERYTRACE) ||
                                (iMsgType == KVI_OUT_QUERYPRIVMSGCRYPTED) || (iMsgType == KVI_OUT_QUERYNOTICE) || (iMsgType == KVI_OUT_QUERYNOTICECRYPTED)
                            )
                        )
                        ||
                        (
                            KVI_OPTION_BOOL(KviOption_boolHighlightOnlyNormalMsgHighlightInChanToo) && (iMsgType == KVI_OUT_HIGHLIGHT)
                        )
                    )
              )
                return;
        }
    }

    if(KVI_OPTION_BOOL(KviOption_boolHighlightOnlyAtCostumHighlightLevel) &&
            (KVI_OPTION_MSGTYPE(iMsgType).level() < ((int)(KVI_OPTION_UINT(KviOption_uintMinHighlightLevel)))))
    {
        return;
    }

    m_pWindowListItem->highlight(KVI_OPTION_MSGTYPE(iMsgType).level());
}
예제 #3
0
KviIrcMessageCheckListItem::KviIrcMessageCheckListItem(QTreeWidget * par,KviIrcViewToolWidget * w,int id)
: QTreeWidgetItem(par)
{
	m_iId = id;
	setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
	setCheckState(0,Qt::Checked);
	setIcon(0,*(g_pIconManager->getSmallIcon(KVI_OPTION_MSGTYPE(id).pixId())));
	setText(0,__tr2qs_no_xgettext(KVI_OPTION_MSGTYPE(id).type()));
	m_pToolWidget = w;
}
예제 #4
0
void UrlDialog::addUrl(QString url, QString window, QString count, QString timestamp)
{
    QTreeWidgetItem * UrlItem = new QTreeWidgetItem(m_pUrlList);

    UrlItem->setText(0, url);
    UrlItem->setText(1, window);
    UrlItem->setText(2, count);
    UrlItem->setText(3, timestamp);

    UrlItem->setForeground(0, KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_URL).fore()));
    UrlItem->setForeground(1, KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_NONE).fore()));
    UrlItem->setForeground(2, KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_NONE).fore()));
    UrlItem->setForeground(3, KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_NONE).fore()));

    m_pUrlList->resizeColumnToContents(0);
    m_pUrlList->resizeColumnToContents(3);
    m_pUrlList->resizeColumnToContents(2);
    m_pUrlList->resizeColumnToContents(1);
}
예제 #5
0
void KviThemedComboBox::applyOptions()
{
#ifdef COMPILE_PSEUDO_TRANSPARENCY
	bool bIsTrasparent = (KVI_OPTION_BOOL(KviOption_boolUseCompositingForTransparency) && g_pApp->supportsCompositing()) || g_pShadedChildGlobalDesktopBackground;
#else
	bool bIsTrasparent = false;
#endif

	// As of 10.09.2017 setting a style sheet with 'background' or 'color' on the QComboBox makes
	// Qt go nuts. The console window does not redraw properly and several BadMatch errors appear:
	//   QXcbConnection: XCB error: 8 (BadMatch), sequence: 1335, resource id: 81789032, major code: 130 (Unknown), minor code: 3

#if 0
	if(style()->objectName() == "oxygen" || style()->objectName().startsWith("ia-ora-") || style()->objectName() == "breeze")
	{
		// workaround for broken oxygen in kde4.4: use palette() instead that stylesheet
		// ia-ora- are the mandriva default styles
#endif
		setFont(KVI_OPTION_FONT(KviOption_fontLabel));
		QPalette pal = palette();
		pal.setBrush(QPalette::Base, bIsTrasparent ? Qt::transparent : KVI_OPTION_COLOR(KviOption_colorLabelBackground));
		//qcombobox forces QPalette::Text as its forecolor
		pal.setBrush(QPalette::Text, bIsTrasparent ? KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_NONE).fore()) : KVI_OPTION_COLOR(KviOption_colorLabelForeground));
		setPalette(pal);
#if 0
	} else {
		//QString szStyle = QString("QComboBox { background: %1; color: %2; font-family: %3; font-size: %4pt; font-weight: %5; font-style: %6;}")
		QString szStyle = QString("QComboBox { background: %1; color: %2; font-family: %3; font-size: %4pt; font-weight: %5; font-style: %6;}")
		                      .arg(bIsTrasparent ? "transparent" : KVI_OPTION_COLOR(KviOption_colorLabelBackground).name())
		                      .arg(bIsTrasparent ? KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_NONE).fore()).name() : KVI_OPTION_COLOR(KviOption_colorLabelForeground).name())
		                      .arg(KVI_OPTION_FONT(KviOption_fontLabel).family())
		                      .arg(KVI_OPTION_FONT(KviOption_fontLabel).pointSize())
		                      .arg(KVI_OPTION_FONT(KviOption_fontLabel).weight() == QFont::Bold ? "bold" : "normal")
		                      .arg(KVI_OPTION_FONT(KviOption_fontLabel).style() == QFont::StyleItalic ? "italic" : "normal");
		setStyleSheet(szStyle);
	}
#endif
	update();
}
void OptionsWidget_messageColors::commit()
{
	saveLastItem();

	mergeResetFlag(KviOption_resetUpdateGui);

	int count = m_pListView->count();
	for(int i=0; i<count;i++)
	{
		MessageListWidgetItem* it = (MessageListWidgetItem *)m_pListView->item(i);
		KVI_OPTION_MSGTYPE(it->optionId()) = *(it->msgType());
	}

	KviOptionsWidget::commit();
}
MessageListWidgetItem::MessageListWidgetItem(MessageListWidget* l,int optId)
: KviTalListWidgetItem(l)
{
	m_iOptId = optId;
	m_pMsgType = new KviMessageTypeSettings(KVI_OPTION_MSGTYPE(optId));

	QString txt = g_msgtypeOptionsTable[m_iOptId].name;
	// skip the msgtype prefix
	txt.remove(0,KVI_MSGTYPE_OPTIONS_PREFIX_LEN);
	txt += " (";
	txt += __tr2qs_no_xgettext(m_pMsgType->type());
	txt += ")";

	setText(txt);
	setIcon(*(g_pIconManager->getSmallIcon(m_pMsgType->pixId())));
}
예제 #8
0
void KviThemedLineEdit::applyOptions()
{
#ifdef COMPILE_PSEUDO_TRANSPARENCY
	bool bIsTrasparent = (KVI_OPTION_BOOL(KviOption_boolUseCompositingForTransparency) && g_pApp->supportsCompositing()) || g_pShadedChildGlobalDesktopBackground;
#else
	bool bIsTrasparent = false;
#endif
	QString szStyle = QString("QLineEdit { background: %1; color: %2; font-family: %3; font-size: %4pt; font-weight: %5; font-style: %6; margin: 1px; }")
	                      .arg(bIsTrasparent ? "transparent" : KVI_OPTION_COLOR(KviOption_colorLabelBackground).name())
	                      .arg(bIsTrasparent ? KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_NONE).fore()).name() : KVI_OPTION_COLOR(KviOption_colorLabelForeground).name())
	                      .arg(KVI_OPTION_FONT(KviOption_fontLabel).family())
	                      .arg(KVI_OPTION_FONT(KviOption_fontLabel).pointSize())
	                      .arg(KVI_OPTION_FONT(KviOption_fontLabel).weight() == QFont::Bold ? "bold" : "normal")
	                      .arg(KVI_OPTION_FONT(KviOption_fontLabel).style() == QFont::StyleItalic ? "italic" : "normal");
	setStyleSheet(szStyle);
	update();
}
예제 #9
0
void KviNotifyListManager::notifyOnLine(const QString & szNick, const QString & szUser, const QString & szHost, const QString & szReason, bool bJoin)
{
	if(bJoin)
		m_pConsole->notifyListView()->join(szNick, szUser, szHost);

	KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolNotifyListChangesToActiveWindow) ? m_pConsole->activeWindow() : m_pConsole;
	if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnNotifyOnLine, pOut, szNick))
		return;

	QString szWho;
	QString szMsg;

	if(!(szUser.isEmpty() || szHost.isEmpty()))
		szWho = QString("\r!n\r%1\r [%2@\r!h\r%3\r]").arg(szNick, szUser, szHost);
	else
		szWho = QString("\r!n\r%1\r").arg(szNick);

	KviPointerHashTable<QString, KviRegisteredUser> * d = g_pRegisteredUserDataBase->userDict();
	KviPointerHashTableIterator<QString, KviRegisteredUser> it(*d);

	while(KviRegisteredUser * pUser = it.current())
	{
		QString szProp = pUser->getProperty("notify");
		if(!szProp.isEmpty())
		{
			if(szProp.split(",", QString::SkipEmptyParts).indexOf(szNick) != -1)
			{
				QString szComment = pUser->getProperty("comment");
				if(!szComment.isEmpty())
					szMsg = QString("%1 (%2), Group \"%3\" is on IRC as (%4)").arg(pUser->name(), szComment, pUser->group(), szWho);
				else
					szMsg = QString("%1, Group \"%2\" is on IRC as (%3)").arg(pUser->name(), pUser->group(), szWho);
				break;
			}
		}
		++it;
	}

	QString szFmt = __tr2qs("%1 is on IRC");

	if(szMsg.isEmpty())
		szMsg = QString(szFmt).arg(szWho);

	if((!szReason.isEmpty()) && (_OUTPUT_VERBOSE))
	{
		szMsg += "(";
		szMsg += szReason;
		szMsg += ")";
	}

	pOut->outputNoFmt(KVI_OUT_NOTIFYONLINE, szMsg);

	if(!(pOut->hasAttention(KviWindow::MainWindowIsVisible)))
	{
		if(KVI_OPTION_BOOL(KviOption_boolFlashWindowOnNotifyOnLine))
			pOut->demandAttention();
		if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNotifyOnLine))
		{
			szWho = "<b>";
			szWho += szNick;
			szWho += "</b>";
			szMsg = QString(szFmt).arg(szWho);
			g_pApp->notifierMessage(pOut, KVI_OPTION_MSGTYPE(KVI_OUT_NOTIFYONLINE).pixId(), szMsg, KVI_OPTION_UINT(KviOption_uintNotifierAutoHideTime));
		}
	}
}
예제 #10
0
const kvi_wchar_t * KviIrcView::getTextLine(
    int iMsgType,
    const kvi_wchar_t * data_ptr,
    KviIrcViewLine * line_ptr,
    bool bEnableTimeStamp,
    const QDateTime & datetime_param)
{
	const kvi_wchar_t * pUnEscapeAt = nullptr;

	// Splits the text data in lines (separated by '\n')

	// NOTE: This function may be NOT reentrant
	//   ... no function in this file is supposed to be thread safe anyway

	int iTextIdx = 0; //we're at the beginning in the buffer
	int iCurChunk = 0;
	int blockLen;

	const kvi_wchar_t * p = data_ptr;

	//Alloc the first attribute
	line_ptr->uChunkCount = 1;
	line_ptr->pChunks = (KviIrcViewLineChunk *)KviMemory::allocate(sizeof(KviIrcViewLineChunk));
	//And fill it up
	line_ptr->pChunks[0].type = KviControlCodes::Color;
	line_ptr->pChunks[0].iTextStart = 0;
	line_ptr->pChunks[0].colors.back = KVI_OPTION_MSGTYPE(iMsgType).back();
	line_ptr->pChunks[0].colors.fore = KVI_OPTION_MSGTYPE(iMsgType).fore();
	line_ptr->pChunks[0].customFore = QColor();

	// print a nice timestamp at the begin of the first line
	if(bEnableTimeStamp && KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp))
	{
		QString szTimestamp;
		QDateTime datetime = datetime_param;
		if(!datetime.isValid())
			datetime = QDateTime::currentDateTime();
		datetime = datetime.toTimeSpec(KVI_OPTION_BOOL(KviOption_boolIrcViewTimestampUTC) ? Qt::UTC : Qt::LocalTime);
		szTimestamp = datetime.toString(KVI_OPTION_STRING(KviOption_stringIrcViewTimestampFormat));
		szTimestamp.append(' ');
		int iTimeStampLength = szTimestamp.length();

		if(KVI_OPTION_BOOL(KviOption_boolUseSpecialColorForTimestamp))
		{
			// we need three chunks: the first one uses the default colors
			// for the message type, the second one the special colors
			// of the timestamp and the third one goes back to the defaults
			line_ptr->pChunks[0].iTextLen = 0;

			line_ptr->uChunkCount = 3;
			line_ptr->pChunks = (KviIrcViewLineChunk *)KviMemory::reallocate((void *)line_ptr->pChunks, 3 * sizeof(KviIrcViewLineChunk));

			line_ptr->pChunks[1].type = KviControlCodes::Color;
			line_ptr->pChunks[1].iTextStart = 0;
			line_ptr->pChunks[1].iTextLen = iTimeStampLength - 1;
			line_ptr->pChunks[1].colors.back = KVI_OPTION_UINT(KviOption_uintTimeStampBackground);
			line_ptr->pChunks[1].colors.fore = KVI_OPTION_UINT(KviOption_uintTimeStampForeground);

			line_ptr->pChunks[2].type = KviControlCodes::Color;
			line_ptr->pChunks[2].iTextStart = iTimeStampLength - 1;
			line_ptr->pChunks[2].iTextLen = 1;
			line_ptr->pChunks[2].colors.back = KVI_OPTION_MSGTYPE(iMsgType).back();
			line_ptr->pChunks[2].colors.fore = KVI_OPTION_MSGTYPE(iMsgType).fore();
			line_ptr->pChunks[2].customFore = QColor();
			iCurChunk += 2;
		}
		else
		{
			// only one chunk
			line_ptr->pChunks[0].iTextLen = iTimeStampLength;
		}

		// We need the timestamp string to be added
		// alloc the necessary space
		line_ptr->szText.resize(iTimeStampLength);

		iTextIdx = iTimeStampLength; // the rest of the string will begin 11 chars later

		// throw away const: we WANT to set the chars :D
		QChar * data_ptr_aux = (QChar *)line_ptr->szText.unicode();
		QChar * stamp_ptr_aux = (QChar *)szTimestamp.unicode();

		//copy the timestamp into line_ptr->szText.unicode()
		for(int i = 0; i < iTimeStampLength; i++)
			*data_ptr_aux++ = *stamp_ptr_aux++;
	}
	else
	{
		// Timestamp not needed... but we don't want null strings floating around
		line_ptr->szText = "";
		line_ptr->pChunks[0].iTextLen = 0;
	}

//
// Ok... a couple of macros that occur really frequently
// in the following code...
// these could work well as functions too...but the macros are a lot faster :)
//

/*
 * Profane description: this adds a block of text of known length to a already created chunk inside this line.
 */
#define APPEND_LAST_TEXT_BLOCK(__data_ptr, __data_len)                               \
	blockLen = (__data_len);                                                         \
	line_ptr->pChunks[iCurChunk].iTextLen += blockLen;                               \
	kvi_appendWCharToQStringWithLength(&(line_ptr->szText), __data_ptr, __data_len); \
	iTextIdx += blockLen;

/*
 * Profane description: this adds a block of text of known length to a already created chunk inside this line.
 * text is hidden (e.g. we want to display an emoticon instead of the ":)" text, so we insert it hidden)
 */

#define APPEND_LAST_TEXT_BLOCK_HIDDEN_FROM_NOW(__data_ptr, __data_len)               \
	blockLen = (__data_len);                                                         \
	kvi_appendWCharToQStringWithLength(&(line_ptr->szText), __data_ptr, __data_len); \
	iTextIdx += blockLen;

/*
 * Profane description: this is dummy
 */

#define APPEND_ZERO_LENGTH_BLOCK(__data_ptr) /* does nothing */

/*
 * Profane description: this adds a new chunk to the current line of the specified type. A chunk is a block of text
 * with similar style properties (mainly with the same color)
 */

#define NEW_LINE_CHUNK(_chunk_type)                                                             \
	line_ptr->uChunkCount++;                                                                    \
	line_ptr->pChunks = (KviIrcViewLineChunk *)KviMemory::reallocate((void *)line_ptr->pChunks, \
	    line_ptr->uChunkCount * sizeof(KviIrcViewLineChunk));                                   \
	iCurChunk++;                                                                                \
	line_ptr->pChunks[iCurChunk].type = _chunk_type;                                            \
	line_ptr->pChunks[iCurChunk].iTextStart = iTextIdx;                                         \
	line_ptr->pChunks[iCurChunk].iTextLen = 0;                                                  \
	line_ptr->pChunks[iCurChunk].customFore = iCurChunk ? line_ptr->pChunks[iCurChunk - 1].customFore : QColor();

	// EOF Macros

	int partLen;

/*
 * Some additional description for the profanes: we want a fast way to check the presence of "active objects we have to process" in lines of text;
 * such objects can be: EOF, URLs, mIRC control characters, emoticons, and so on. We implemented a jump table to accomplish this task very fast.
 * This jump table is an array[256] containing label addresses (imagine them as functions). So something like "goto array[4];" is valid construct
 * in C, that is equivalent to a function call to a function that starts on that label's line of code.
 * Imagine to parse the input line one character at once and match it (as a switch can do) against this big array. Every 1-byte character corresponds
 * to an ASCII integer between 0 and 255. If the array value for that integer key is defined and !=0, we jump to the corresponding label address.
 * Example, if we find a "H" (72) we'll "goto char_to_check_jump_table[72]", aka "goto check_http_url".
 * There exists two different versions of this tricky code, we switch them depending on the compiler abilities to accept our bad code :)
 */

#ifdef COMPILE_USE_DYNAMIC_LABELS

	// Heresy :)

	// This is not only usage of the *Evil Goto(tm)*
	// This is also a *rather unclear* use of the *Really Evil Goto(tm)*
	// char_to_check_jump_table is a table of dynamic label addresses...
	// we use it to jump to the proper check
	// loop_begin is a dynamic label, and we use it to
	// return to the appropriate loop
	// This is again BAD PROGRAMMING(TM) :).... but it is faster than
	// the version with no dynamic gotos, and really faster
	// that any version without gotos that came into my mind...
	//
	// This code will prolly work only with GCC...(and even needs a "smart" one)

	// Again did two versions... the first was:
	//
	//  if(void * jmp_address = char_to_check_jump_table[*((unsigned char *)p)])goto *jmp_address;
	//    18a3:	8b 55 f0             	movl   0xfffffff0(%ebp),%edx
	//    18a6:	31 c0                	xorl   %eax,%eax
	//    18a8:	8a 02                	movb   (%edx),%al
	//    18aa:	8b 04 85 20 00 00 00 	movl   0x20(,%eax,4),%eax
	//    18b1:	85 c0                	testl  %eax,%eax
	//    18b3:	74 02                	je     18b7 <KviIrcView::getTextLine(int, char const *, KviIrcViewLine *)+0x1f3>
	//    18b5:	ff e0                	jmp    *%eax
	//
	// I even had a nicer version:
	//
	//  goto *(char_to_check_jump_table[*((unsigned char *)p)]);
	//    18a3:	8b 55 f0             	movl   0xfffffff0(%ebp),%edx
	//    18a6:	31 c0                	xorl   %eax,%eax
	//    18a8:	8a 02                	movb   (%edx),%al
	//    18aa:	ff 24 85 20 00 00 00 	jmp    *0x20(,%eax,4)
	//
	// but sth tells me that "jmp *0x20(,%eax,4)" takes a loooooot of clock ticks...
	// ...we have less instructions, but the code takes longer to execute (7-8% longer)
	// it might be also due to pipeline tricks, jump "next instruction precalculation" stuff...

	// So we end up using the first version here

	void * loop_begin;

	static void * char_to_check_jump_table[256] = {
		// clang-format off
		&&found_end_of_buffer        ,nullptr                      ,&&found_mirc_escape          ,&&found_color_escape         ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,&&found_end_of_line          ,nullptr                      ,
		nullptr                      ,&&found_command_escape       ,nullptr                      ,&&found_mirc_escape          ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,&&found_mirc_escape          ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		&&found_icon_escape          ,&&found_mirc_escape          ,nullptr                      ,&&found_mirc_escape          , // 000-031
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 032-047
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,&&check_emoticon_char        ,&&check_emoticon_char        ,
		nullptr                      ,&&check_emoticon_char        ,nullptr                      ,nullptr                      , // 048-063 // 61='=' , 59=';' , 58=':'
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,&&check_e2k_url              ,&&check_file_or_ftp_url      ,nullptr                      ,
		&&check_http_url             ,&&check_irc_url              ,nullptr                      ,nullptr                      ,
		nullptr                      ,&&check_mailto_or_magnet_url ,nullptr                      ,nullptr                      , // 064-079  // 070==F 072==H 073==I  077==M
		nullptr                      ,nullptr                      ,nullptr                      ,&&check_spotify_url          ,
		nullptr                      ,nullptr                      ,nullptr                      ,&&check_www_url              ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 080-095  // 083==S 087==W
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,&&check_e2k_url              ,&&check_file_or_ftp_url      ,nullptr                      ,
		&&check_http_url             ,&&check_irc_url              ,nullptr                      ,nullptr                      ,
		nullptr                      ,&&check_mailto_or_magnet_url ,nullptr                      ,nullptr                      , // 096-111  // 101=e 102=f 104=h 105=i 109==m
		nullptr                      ,nullptr                      ,nullptr                      ,&&check_spotify_url          ,
		nullptr                      ,nullptr                      ,nullptr                      ,&&check_www_url              ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 112-127  // 115==s 119==w
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 128-133
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 134-159
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 160-175
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 176-191
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 192-207
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 208-223
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      , // 224-239
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                      ,
		nullptr                      ,nullptr                      ,nullptr                      ,nullptr                        // 240-255
		// clang-format on
	};

	if(KVI_OPTION_BOOL(KviOption_boolIrcViewUrlHighlighting) || KVI_OPTION_BOOL(KviOption_boolDrawEmoticons))
	{
		loop_begin = &&highlighting_check_loop; // get the address of the return label
	                                            // forever loop
	highlighting_check_loop:
		// yet more optimized
		if(*((unsigned short *)p) < 0xff)
			if(void * jmp_address = char_to_check_jump_table[*((unsigned short *)p)])
				goto * jmp_address;
		// goto *(char_to_check_jump_table[*((unsigned char *)p)]); <--- replace 0 with &nothing_found
		//nothing_found:
		p++;
		goto highlighting_check_loop;
		// never here
	}
	else
	{
예제 #11
0
void LogViewWindow::createLog(LogFile * pLog, int iId, QString * pszFile)
{
	if(!pLog)
		return;

	QRegExp rx;
	QString szLog, szLogDir, szInputBuffer, szOutputBuffer, szLine, szTmp;
	QString szDate = pLog->date().toString("yyyy.MM.dd");

	/* Fetching previous export path and concatenating with generated filename
	 * adjustFilePath is for file paths not directory paths */
	szLog = KVI_OPTION_STRING(KviOption_stringLogsExportPath).trimmed();
	if (!szLog.isEmpty())
		szLog += KVI_PATH_SEPARATOR_CHAR;
	szLog += QString("%1_%2.%3_%4").arg(pLog->typeString(),pLog->name(),pLog->network(),szDate);
	KviFileUtils::adjustFilePath(szLog);

	// Getting output file path from the user, with overwrite confirmation
	if(!KviFileDialog::askForSaveFileName(
			szLog,
			__tr2qs_ctx("Export Log - KVIrc","log"),
			szLog,
			QString(),
			false,
			true,
			true,
			this))
		return;

	/* Save export directory - this directory path is also used in the HTML export
	 * and info is used when working with pszFile */
	QFileInfo info(szLog);
	szLogDir = info.absoluteDir().absolutePath();
	KVI_OPTION_STRING(KviOption_stringLogsExportPath) = szLogDir;

	/* Reading in log file - LogFiles are read in as bytes, so '\r' isn't
	 * sanitised by default */
	pLog->getText(szInputBuffer);
	QStringList lines = szInputBuffer.replace('\r', "").split('\n');

	switch(iId)
	{
		case LogFile::PlainText:
		{
			/* Only append extension if it isn't there already (e.g. a specific
			 * file is to be overwritten) */
			if(!szLog.endsWith(".txt"))
				szLog += ".txt";

			// Scan the file
			for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it)
			{
				szTmp = (*it);
				szLine = KviControlCodes::stripControlBytes(szTmp);

				// Remove icons' code
				rx.setPattern("^\\d{1,3}\\s");
				szLine.replace(rx,"");

				// Remove link from a user speaking, deal with (and keep) various ranks
				// e.g.: <!ncHelLViS69>  -->  <HelLViS69>
				rx.setPattern("\\s<([+%@&~!]?)!nc");
				szLine.replace(rx," <\\1");

				// Remove link from a nick in a mask
				// e.g.: !nFoo [~bar@!hfoo.bar]  -->  Foo [~bar@!hfoo.bar]
				rx.setPattern("\\s!n");
				szLine.replace(rx," ");

				// Remove link from a host in a mask
				// e.g.: Foo [~bar@!hfoo.bar]  -->  Foo [[email protected]]
				rx.setPattern("@!h");
				szLine.replace(rx,"@");

				// Remove link from a channel
				// e.g.: !c#KVIrc  -->  #KVIrc
				rx.setPattern("!c#");
				szLine.replace(rx,"#");

				szOutputBuffer += szLine;
				szOutputBuffer += "\n";
			}

			break;
		}
		case LogFile::HTML:
		{
			/* Only append extension if it isn't there already (e.g. a specific
			 * file is to be overwritten) */
			if(!szLog.endsWith(".html"))
				szLog += ".html";

			szTmp = QString("KVIrc %1 %2").arg(KVI_VERSION).arg(KVI_RELEASE_NAME);
			QString szNick = "";
			bool bFirstLine = true;

			QString szTitle;
			switch(pLog->type())
			{
				case LogFile::Channel:
					szTitle = __tr2qs_ctx("Channel %1 on %2","log").arg(pLog->name(),pLog->network());
				break;
				case LogFile::Console:
					szTitle = __tr2qs_ctx("Console on %1","log").arg(pLog->network());
				break;
				case LogFile::Query:
					szTitle = __tr2qs_ctx("Query with %1 on %2","log").arg(pLog->name(),pLog->network());
				break;
				case LogFile::DccChat:
					szTitle = __tr2qs_ctx("DCC Chat with %1","log").arg(pLog->name());
				break;
				case LogFile::Other:
					szTitle = __tr2qs_ctx("Something on %1","log").arg(pLog->network());
				break;
			}

			// Prepare HTML document
			szOutputBuffer += "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n";
			szOutputBuffer += "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n";
			szOutputBuffer += "<head>\n";
			szOutputBuffer += "\t<meta http-equiv=\"content-type\" content=\"application/xhtml+xml; charset=utf-8\" />\n";
			szOutputBuffer += "\t<meta name=\"author\" content=\"" + szTmp + "\" />\n";
			szOutputBuffer += "\t<title>" + szTitle + "</title>\n";
			szOutputBuffer += "</head>\n<body>\n";
			szOutputBuffer += "<h2>" + szTitle + "</h2>\n<h3>Date: " + szDate + "</h3>\n";

			// Scan the file
			for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it)
			{
				szTmp = (*it);

				// Find who has talked
				QString szTmpNick = szTmp.section(" ",2,2);
				if((szTmpNick.left(1) != "<") && (szTmpNick.right(1) != ">"))
					szTmpNick = "";

				// locate msgtype
				QString szNum = szTmp.section(' ',0,0);
				bool bOk;
				int iMsgType = szNum.toInt(&bOk);

				// only human text for now...
				if(iMsgType != 24 && iMsgType != 25  && iMsgType != 26)
					continue;

				// remove msgtype tag
				szTmp = szTmp.remove(0,szNum.length()+1);

				szTmp = KviHtmlGenerator::convertToHtml(szTmp,true);

				// insert msgtype icon at start of the current text line
				KviMessageTypeSettings msg(KVI_OPTION_MSGTYPE(iMsgType));
				QString szIcon = g_pIconManager->getSmallIconResourceName((KviIconManager::SmallIcon)msg.pixId());
				szTmp.prepend("<img src=\"" + szIcon + "\" alt=\"\" /> ");

				/*
				 * Check if the nick who has talked is the same of the above line.
				 * If so, we have to put the line as it is, otherwise we have to
				 * open a new paragraph
				 */
				if(szTmpNick != szNick)
				{
					/*
					 * People is not the same, close the paragraph opened
					 * before and open a new one
					 */
					if(!bFirstLine)
						szOutputBuffer += "</p>\n";
					szTmp.prepend("<p>");

					szNick = szTmpNick;
				} else {
					// Break the line
					szTmp.prepend("<br />\n");
				}

				szOutputBuffer += szTmp;
				bFirstLine = false;
			}

			// Close the last paragraph
			szOutputBuffer += "</p>\n";

			// regexp to search all embedded icons
			rx.setPattern("<img src=\"smallicons:([^\"]+)");
			int iIndex = szOutputBuffer.indexOf(rx);
			QStringList szImagesList;

			// search for icons
			while (iIndex >= 0)
			{
				int iLength = rx.matchedLength();
				QString szCap = rx.cap(1);

				// if the icon isn't in the images list then add
				if(szImagesList.indexOf(szCap) == -1)
					szImagesList.append(szCap);
				iIndex = szOutputBuffer.indexOf(rx, iIndex + iLength);
			}

			// get current theme path
			QString szCurrentThemePath;
			g_pApp->getLocalKvircDirectory(szCurrentThemePath,KviApplication::Themes,KVI_OPTION_STRING(KviOption_stringIconThemeSubdir));
			szCurrentThemePath += KVI_PATH_SEPARATOR_CHAR;

			// current coresmall path
			szCurrentThemePath += "coresmall";
			szCurrentThemePath += KVI_PATH_SEPARATOR_CHAR;

			// check if coresmall exists in current theme
			if(!KviFileUtils::directoryExists(szCurrentThemePath))
			{
				// get global coresmall path
				g_pApp->getGlobalKvircDirectory(szCurrentThemePath,KviApplication::Pics,"coresmall");
				KviQString::ensureLastCharIs(szCurrentThemePath,QChar(KVI_PATH_SEPARATOR_CHAR));
			}

			// copy all icons to the log destination folder
			for(int i=0; i < szImagesList.count(); i++)
			{
				QString szSourceFile = szCurrentThemePath + szImagesList.at(i);
				QString szDestFile = szLogDir + szImagesList.at(i);
				KviFileUtils::copyFile(szSourceFile,szDestFile);
			}

			// remove internal tags
			rx.setPattern("<qt>|</qt>|smallicons:");
			szOutputBuffer.replace(rx,"");
			szOutputBuffer.replace(">!nc",">");
			szOutputBuffer.replace("@!nc","@");
			szOutputBuffer.replace("%!nc","%");

			// Close the document
			szOutputBuffer += "</body>\n</html>\n";

			break;
		}
	}

	// File overwriting already dealt with when file path was obtained
	QFile log(szLog);
	if(!log.open(QIODevice::WriteOnly | QIODevice::Text))
		return;

	if(pszFile)
	{
		*pszFile = "";
		*pszFile = info.filePath();
	}

	// Ensure we're writing in UTF-8
	QTextStream output(&log);
	output.setCodec("UTF-8");
	output << szOutputBuffer;

	// Close file descriptors
	log.close();
}
예제 #12
0
bool DccChatWindow::event(QEvent * e)
{
	if(e->type() == KVI_THREAD_EVENT)
	{
		switch(((KviThreadEvent *)e)->id())
		{
			case KVI_DCC_THREAD_EVENT_ERROR:
			{
				KviError::Code * pError = ((KviThreadDataEvent<KviError::Code> *)e)->getData();
				QString szErr = KviError::getDescription(*pError);
				if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatError, this, szErr, m_pDescriptor->idString()))
					output(KVI_OUT_DCCERROR, __tr2qs_ctx("ERROR: %Q", "dcc"), &szErr);
				KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatDisconnected, this, m_pDescriptor->idString());
				delete pError;
				return true;
			}
			break;
			case KVI_DCC_THREAD_EVENT_DATA:
			{
				KviCString * encoded = ((KviThreadDataEvent<KviCString> *)e)->getData();
				KviCString d = KviCString(decodeText(encoded->ptr()));
				if(d.firstCharIs(0x01))
				{
					d.cutLeft(1);
					if(d.lastCharIs(0x01))
						d.cutRight(1);
					if(kvi_strEqualCIN("ACTION", d.ptr(), 6))
						d.cutLeft(6);
					d.stripLeftWhiteSpace();
					output(KVI_OUT_ACTION, "%Q %s", &(m_pDescriptor->szNick), d.ptr());
					if(!hasAttention(KviWindow::MainWindowIsVisible))
					{
						if(KVI_OPTION_BOOL(KviOption_boolFlashDccChatWindowOnNewMessages))
						{
							demandAttention();
						}
						if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNewDccChatMessages))
						{
							QString szMsg = "<b>";
							szMsg += m_pDescriptor->szNick;
							szMsg += "</b> ";
							szMsg += KviQString::toHtmlEscaped(QString(d.ptr()));
							//qDebug("KviIrcServerParser_ctcp.cpp:975 debug: %s",szMsg.data());
							g_pApp->notifierMessage(this, KVI_OPTION_MSGTYPE(KVI_OUT_ACTION).pixId(), szMsg, KVI_OPTION_UINT(KviOption_uintNotifierAutoHideTime));
						}
					}
				}
				else
				{

#ifdef COMPILE_CRYPT_SUPPORT
					if(KviCryptSessionInfo * cinf = cryptSessionInfo())
					{
						if(cinf->m_bDoDecrypt)
						{
							KviCString decryptedStuff;
							switch(cinf->m_pEngine->decrypt(d.ptr(), decryptedStuff))
							{
								case KviCryptEngine::DecryptOkWasEncrypted:
								case KviCryptEngine::DecryptOkWasEncoded:
								case KviCryptEngine::DecryptOkWasPlainText:
									if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatMessage, this, QString(decryptedStuff.ptr()), m_pDescriptor->idString()))
									{
										g_pMainWindow->firstConsole()->outputPrivmsg(this, KVI_OUT_DCCCHATMSG,
										    m_pDescriptor->szNick.toUtf8().data(), m_pDescriptor->szUser.toUtf8().data(),
										    m_pDescriptor->szHost.toUtf8().data(), decryptedStuff.ptr());
									}
									delete encoded;
									return true;
									break;

								default: // also case KviCryptEngine::DecryptError
								{
									QString szErr = cinf->m_pEngine->lastError();
									output(KVI_OUT_SYSTEMERROR,
									    __tr2qs_ctx("The following message appears to be encrypted, but the encryption engine failed to decode it: %Q", "dcc"),
									    &szErr);
								}
								break;
							}
						}
					}
					else
					{
#endif
						// FIXME!
						if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatMessage, this, QString(d.ptr()), m_pDescriptor->idString()))
						{
							g_pMainWindow->firstConsole()->outputPrivmsg(this, KVI_OUT_DCCCHATMSG,
							    m_pDescriptor->szNick.toUtf8().data(), m_pDescriptor->szUser.toUtf8().data(),
							    m_pDescriptor->szHost.toUtf8().data(), d.ptr());
							if(!hasAttention(KviWindow::MainWindowIsVisible))
							{
								if(KVI_OPTION_BOOL(KviOption_boolFlashDccChatWindowOnNewMessages))
								{
									demandAttention();
								}
								if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNewDccChatMessages))
								{
									QString szMsg = KviQString::toHtmlEscaped(QString(d.ptr()));
									g_pApp->notifierMessage(this, KviIconManager::DccChatMsg, szMsg, KVI_OPTION_UINT(KviOption_uintNotifierAutoHideTime));
								}
							}
						}
#ifdef COMPILE_CRYPT_SUPPORT
					}
#endif
				}
				delete encoded;
				return true;
			}
			break;
		}
	}
	return KviWindow::event(e);
}
예제 #13
0
void LogViewWindow::createLog(LogFile * pLog, int iId, QString * pszFile)
{
	if(!pLog)
		return;

	QRegExp rx;
	QString szLog, szLogDir, szBuffer, szLine, szTmp;
	QString szDate = pLog->date().toString("yyyy.MM.dd");

	// The fresh new log
	g_pApp->getLocalKvircDirectory(szLogDir,KviApplication::Tmp);
	KviFileUtils::adjustFilePath(szLogDir);
	szLogDir += KVI_PATH_SEPARATOR_CHAR;
	szLog += szLogDir;
	szLog += QString("%1_%2.%3_%4").arg(pLog->typeString(),pLog->name(),pLog->network(),szDate);

	// Open file for reading
	QFile file(pLog->fileName());
	if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
		return;

	// Set up a 16bit Unicode string
	QTextStream input(&file);
	input.setCodec("UTF-8");

	switch(iId)
	{
		case LogFile::PlainText:
		{
			szLog += ".txt";

			// Scan the file
			while(!input.atEnd())
			{
				szTmp = input.readLine();
				szLine = KviControlCodes::stripControlBytes(szTmp);

				// Remove icons' code
				rx.setPattern("^\\d{1,3}\\s");
				szLine.replace(rx,"");

				// Remove link from a user speaking
				// e.g.: <!ncHelLViS69>  -->  <HelLViS69>
				rx.setPattern("\\s<!nc");
				szLine.replace(rx," <");

				// Remove link from a nick in a mask
				// e.g.: !nFoo [~bar@!hfoo.bar]  -->  Foo [~bar@!hfoo.bar]
				rx.setPattern("\\s!n");
				szLine.replace(rx," ");

				// Remove link from a host in a mask
				// e.g.: Foo [~bar@!hfoo.bar]  -->  Foo [[email protected]]
				rx.setPattern("@!h");
				szLine.replace(rx,"@");

				// Remove link from a channel
				// e.g.: !c#KVIrc  -->  #KVIrc
				rx.setPattern("!c#");
				szLine.replace(rx,"#");

				szBuffer += szLine;
				szBuffer += "\n";
			}

			break;
		}
		case LogFile::HTML:
		{
			szLog += ".html";
			szTmp = QString("KVIrc %1 %2").arg(KVI_VERSION).arg(KVI_RELEASE_NAME);
			QString szNick = "";
			bool bFirstLine = true;

			QString szTitle;
			switch(pLog->type())
			{
				case LogFile::Channel:
					szTitle = __tr2qs_ctx("Channel %1 on %2","log").arg(pLog->name(),pLog->network());
				break;
				case LogFile::Console:
					szTitle = __tr2qs_ctx("Console on %1","log").arg(pLog->network());
				break;
				case LogFile::Query:
					szTitle = __tr2qs_ctx("Query with %1 on %2","log").arg(pLog->name(),pLog->network());
				break;
				case LogFile::DccChat:
					szTitle = __tr2qs_ctx("DCC Chat with %1","log").arg(pLog->name());
				break;
				case LogFile::Other:
					szTitle = __tr2qs_ctx("Something on %1","log").arg(pLog->network());
				break;
			}

			// Prepare HTML document
			szBuffer += "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n";
			szBuffer += "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n";
			szBuffer += "<head>\n";
			szBuffer += "\t<meta http-equiv=\"content-type\" content=\"application/xhtml+xml; charset=utf-8\" />\n";
			szBuffer += "\t<meta name=\"author\" content=\"" + szTmp + "\" />\n";
			szBuffer += "\t<title>" + szTitle + "</title>\n";
			szBuffer += "</head>\n<body>\n";
			szBuffer += "<h2>" + szTitle + "</h2>\n<h3>Date: " + szDate + "</h3>\n";

			// Scan the file
			while(!input.atEnd())
			{
				szTmp = input.readLine();

				// Find who has talked
				QString szTmpNick = szTmp.section(" ",2,2);
				if((szTmpNick.left(1) != "<") && (szTmpNick.right(1) != ">"))
					szTmpNick = "";

				// locate msgtype
				QString szNum = szTmp.section(' ',0,0);
				bool bOk;
				int iMsgType = szNum.toInt(&bOk);

				// only human text for now...
				if(iMsgType != 24 && iMsgType != 25  && iMsgType != 26)
					continue;

				// remove msgtype tag
				szTmp = szTmp.remove(0,szNum.length()+1);

				szTmp = KviHtmlGenerator::convertToHtml(szTmp,true);

				// insert msgtype icon at start of the current text line
				KviMessageTypeSettings msg(KVI_OPTION_MSGTYPE(iMsgType));
				QString szIcon = g_pIconManager->getSmallIconResourceName((KviIconManager::SmallIcon)msg.pixId());
				szTmp.prepend("<img src=\"" + szIcon + "\" alt=\"\" /> ");

				/*
				 * Check if the nick who has talked is the same of the above line.
				 * If so, we have to put the line as it is, otherwise we have to
				 * open a new paragraph
				 */
				if(szTmpNick != szNick)
				{
					/*
					 * People is not the same, close the paragraph opened
					 * before and open a new one
					 */
					if(!bFirstLine)
						szBuffer += "</p>\n";
					szTmp.prepend("<p>");

					szNick = szTmpNick;
				} else {
					// Break the line
					szTmp.prepend("<br />\n");
				}

				szBuffer += szTmp;
				bFirstLine = false;
			}

			// Close the last paragraph
			szBuffer += "</p>\n";

			// regexp to search all embedded icons
			rx.setPattern("<img src=\"smallicons:([^\"]+)");
			int iIndex = szBuffer.indexOf(rx);
			QStringList szImagesList;

			// search for icons
			while (iIndex >= 0)
			{
				int iLength = rx.matchedLength();
				QString szCap = rx.cap(1);

				// if the icon isn't in the images list then add
				if(szImagesList.indexOf(szCap) == -1)
					szImagesList.append(szCap);
				iIndex = szBuffer.indexOf(rx, iIndex + iLength);
			}

			// get current theme path
			QString szCurrentThemePath;
			g_pApp->getLocalKvircDirectory(szCurrentThemePath,KviApplication::Themes,KVI_OPTION_STRING(KviOption_stringIconThemeSubdir));
			szCurrentThemePath += KVI_PATH_SEPARATOR_CHAR;

			// current coresmall path
			szCurrentThemePath += "coresmall";
			szCurrentThemePath += KVI_PATH_SEPARATOR_CHAR;

			// check if coresmall exists in current theme
			if(!KviFileUtils::directoryExists(szCurrentThemePath))
			{
				// get global coresmall path
				g_pApp->getGlobalKvircDirectory(szCurrentThemePath,KviApplication::Pics,"coresmall");
				KviQString::ensureLastCharIs(szCurrentThemePath,QChar(KVI_PATH_SEPARATOR_CHAR));
			}

			// copy all icons to the log destination folder
			for(int i=0; i < szImagesList.count(); i++)
			{
				QString szSourceFile = szCurrentThemePath + szImagesList.at(i);
				QString szDestFile = szLogDir + szImagesList.at(i);
				KviFileUtils::copyFile(szSourceFile,szDestFile);
			}

			// remove internal tags
			rx.setPattern("<qt>|</qt>|smallicons:");
			szBuffer.replace(rx,"");
			szBuffer.replace(">!nc",">");
			szBuffer.replace("@!nc","@");
			szBuffer.replace("%!nc","%");

			// Close the document
			szBuffer += "</body>\n</html>\n";

			break;
		}
	}

	if(QFile::exists(szLog))
	{
		if(QMessageBox::question(this,__tr2qs_ctx("Export Log - KVIrc","log"),__tr2qs_ctx("File '%1' already exists. Do you want to overwrite it?","log").arg(szLog),QMessageBox::Yes,QMessageBox::No) == QMessageBox::No)
			return;
	}

	QFile log(szLog);
	if(!log.open(QIODevice::WriteOnly | QIODevice::Text))
		return;

	if(pszFile)
	{
		*pszFile = "";
		QFileInfo info(log);
		*pszFile = info.filePath();
	}

	// Ensure we're writing in UTF-8
	QTextStream output(&log);
	output.setCodec("UTF-8");
	output << szBuffer;

	// Close file descriptors
	file.close();
	log.close();
}