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(); }
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()); }
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; }
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); }
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()))); }
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(); }
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)); } } }
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 ¬hing_found //nothing_found: p++; goto highlighting_check_loop; // never here } else {
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(); }
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); }
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(); }