//============================================================================= // // File : kvi_ircview.cpp // Creation date : Tue Jul 6 1999 14:45:20 by Szymon Stefanek // // This file is part of the KVirc irc client distribution // Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot net) // // This program is FREE software. You can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your opinion) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= #define __KVIRC__ // Damn complex class ...but it works :) // #include // // #define HOPE_THAT_IT_WILL_NEVER_NEED_TO_BE_MODIFIED :) // 07 May 1999 , // Already forgot how this damn thing works , // and spent 1 hour over a stupid bug. // I had to recreate the whole thing in my mind......ooooouh... // How did I wrote it ? // Just take a look to paintEvent() or to calculateLineWraps()... // Anyway...I've solved the bug. // 23 Nov 1999 , // Well , not so bad...I seem to still remember how it works // So just for fun , complicated the things a little bit more. // Added precaclucaltion of the text blocks and word wrapping // and a fast scrolling mode (3 lines at once) for consecutive // appendText() calls. // Now the code becomes really not understandable...:) // 29 Jun 2000 21:02 , // Here we go again... I have to adjust this stuff for 3.0.0 // Will I make this thingie work ? // 01 Jul 2000 04:20 (AM!) , // Yes....I got it to work just now // and YES , complicated the things yet more. // This time made some paint event code completely unreadable // by placing two monster macros... // I hope that you have a smart compiler (such as gcc is). // 09 Dec 2000 // This is my C-asm-optimisation-hack playground // Expect Bad Programming(tm) , Ugly Code(tm) , Unreadable Macros (tm) // and massive usage of the Evil(tm) goto. // 25 Sep 2001 // This stuff is going to be ported to Windoze // A conditionally compiled code will use only TQt calls...let's see :) // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Here we go... a huge set of includes // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "kvi_ircview.h" #include "kvi_ircviewtools.h" #include "kvi_ircviewprivate.h" #include "kvi_styled_controls.h" #include "kvi_debug.h" #include "kvi_app.h" #include "kvi_settings.h" #include "kvi_options.h" #include "kvi_mirccntrl.h" #include "kvi_defaults.h" #include "kvi_window.h" #include "kvi_locale.h" #include "kvi_frame.h" #include "kvi_malloc.h" #include "kvi_memmove.h" #include "kvi_iconmanager.h" #include "kvi_out.h" #include "kvi_parameterlist.h" #include "kvi_console.h" #include "kvi_ircuserdb.h" #include "kvi_channel.h" #include "kvi_topicw.h" #include "kvi_query.h" #include "kvi_filedialog.h" #include "kvi_msgbox.h" #include "kvi_texticonmanager.h" #include "kvi_ircconnection.h" #include "kvi_ircconnectiontarget.h" #include "kvi_mdimanager.h" #include "kvi_userinput.h" #include "kvi_kvs_eventtriggers.h" #include "kvi_doublebuffer.h" #include "kvi_ircurl.h" #include "kvi_draganddrop.h" #include "kvi_qcstring.h" // FIXME: #warning "There should be an option to preserve control codes in copied text (clipboard) (mIrc = CTRL+Copy->with colors)" #include #include #include #include #include #include // needed #include #include "kvi_tal_popupmenu.h" #include #include #include #include //#include // needed // FIXME: #warning "There are problems with the selection and wrapped lines: you can select something on the first line and get the second highlighted" // FIXME: #warning "This hack is temporary...later remove it" #include #include #include #include #include #include #include #ifdef COMPILE_USE_QT4 #include #define TQMimeSourceFactory Q3MimeSourceFactory #endif #ifdef COMPILE_ON_WINDOWS #pragma warning(disable: 4102) #endif #ifdef __STRICT_ANSI__ #ifdef COMPILE_USE_DYNAMIC_LABELS // incompatible with -ansi #undef COMPILE_USE_DYNAMIC_LABELS #endif #endif #ifdef COMPILE_ZLIB_SUPPORT #include #endif #define KVI_DEF_BACK 200 // FIXME: #warning "The scrollbar should NOT have a fixed size : the KDE styles can configure the size (sizeHint() ?)" // // FIXME: PgUp and PgDn scrolls a fixed number of lines! // Make it view height dependant // // FIXME: This widget is quite slow on a 300 MHz processor // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Globals // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Stuff declared in kvi_app.cpp and managed by KviApp class #ifdef COMPILE_PSEUDO_TRANSPARENCY extern TQPixmap * g_pShadedChildGlobalDesktopBackground; #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Internal constants // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Maximum size of the internal buffer for each window // This is the default value //#define KVI_IRCVIEW_MAX_LINES 1024 // Borders...just do not set it to 0 #define KVI_IRCVIEW_HORIZONTAL_BORDER 4 #define KVI_IRCVIEW_VERTICAL_BORDER 4 // A little bit more than the scroll-bar... // TQt+X have strange interactions that I can not understand when I try to move the splitter // to the maximum on the left , Maybe the cache pixmap size becomes negative ? (I don't think so) // Anyway , when the scroll bar position becomes negative (or the IrcView has smaller width than // the scroll bar) X aborts with a funny // X Error: BadDrawable (invalid Pixmap or Window parameter) 9 // Major opcode: 55 // Program received signal SIGABRT, Aborted. // Do not change unless you're sure that it will not happen :) #define KVI_IRCVIEW_MINIMUM_WIDTH 22 //16+4+(2*4) * Do not change #define KVI_IRCVIEW_PIXMAP_AND_SEPARATOR 20 #define KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH 28 #define KVI_IRCVIEW_SELECT_REPAINT_INTERVAL 100 #define KVI_IRCVIEW_SIZEHINT_WIDTH 150 #define KVI_IRCVIEW_SIZEHINT_HEIGHT 150 #define KVI_IRCVIEW_BLOCK_SELECTION_TOTAL 0 #define KVI_IRCVIEW_BLOCK_SELECTION_LEFT 1 #define KVI_IRCVIEW_BLOCK_SELECTION_RIGHT 2 #define KVI_IRCVIEW_BLOCK_SELECTION_CENTRAL 3 #define KVI_IRCVIEW_BLOCK_SELECTION_ICON 4 #define KVI_IRCVIEW_PIXMAP_SIZE 16 #define KVI_IRCVIEW_ESCAPE_TAG_URLLINK 'u' #define KVI_IRCVIEW_ESCAPE_TAG_NICKLINK 'n' #define KVI_IRCVIEW_ESCAPE_TAG_SERVERLINK 's' #define KVI_IRCVIEW_ESCAPE_TAG_HOSTLINK 'h' #define KVI_IRCVIEW_ESCAPE_TAG_GENERICESCAPE '[' // FIXME: Get rid of this!!!!!!!!! #define WSTRINGCONFIG_SAFE_TO_MEMCPY_TQCHAR #define _WSTRING_WMEMCPY(_dst,_src,_len) kvi_fastmoveodd((void *)(_dst),(const void *)(_src),sizeof(kvi_wchar_t) * (_len)) void kvi_appendWCharToTQStringWithLength(TQString * qstrptr,const kvi_wchar_t * ptr,kvi_wslen_t len) { kvi_wslen_t oldLen = qstrptr->length(); qstrptr->setLength(oldLen + len); #ifdef WSTRINGCONFIG_SAFE_TO_MEMCPY_TQCHAR _WSTRING_WMEMCPY(qstrptr->unicode() + oldLen,ptr,len); #else // !WSTRINGCONFIG_SAFE_TO_MEMCPY_TQCHAR TQChar * c = (qstrptr->unicode() + oldLen); while(*ptr) { c->unicode() = *ptr; ptr++; c++; } #endif // !WSTRINGCONFIG_SAFE_TO_MEMCPY_TQCHAR } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Info about escape syntax // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // escape commands: // // ! // // ::= u <--- url link // ::= n <--- nick link // ::= s <--- server link // ::= h <--- host link // ::= [... <--- generic escape "rbt" | "mbt" | "dbl" | "txt" // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // The IrcView : construct and destroy // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// KviIrcView::KviIrcView(TQWidget *parent,KviFrame *pFrm,KviWindow *pWnd) : TQWidget(parent,"irc_view") { // Ok...here we go // initialize the initializable #ifdef COMPILE_USE_QT4 setAttribute(TQt::WA_NoSystemBackground); // This disables automatic qt double buffering setAttribute(TQt::WA_OpaquePaintEvent); //setAttribute(TQt::WA_PaintOnScreen); // disable qt backing store (that would force us to trigger repaint() instead of the 10 times faster paintEvent(0)) #endif m_iFlushTimer = 0; m_pToolsPopup = 0; m_pFirstLine = 0; m_pCurLine = 0; m_pLastLine = 0; m_pCursorLine = 0; m_uLineMarkLineIndex = KVI_IRCVIEW_INVALID_LINE_MARK_INDEX; m_bHaveUnreadedHighlightedMessages = false; m_bHaveUnreadedMessages = false; m_iNumLines = 0; m_iMaxLines = KVI_OPTION_UINT(KviOption_uintIrcViewMaxBufferSize); m_uNextLineIndex = 0; if(m_iMaxLines < 32) { m_iMaxLines = 32; KVI_OPTION_UINT(KviOption_uintIrcViewMaxBufferSize) = 32; } m_bMouseIsDown = false; //m_bShowImages = KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages); m_iSelectTimer = 0; m_iMouseTimer = 0; //m_iTipTimer = 0; //m_bTimestamp = KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp); m_bAcceptDrops = false; m_pPrivateBackgroundPixmap = 0; m_bSkipScrollBarRepaint = false; m_pLogFile = 0; m_pKviWindow = pWnd; m_pFrm = pFrm; m_iUnprocessedPaintEventRequests = 0; m_bPostedPaintEventPending = false; m_pLastLinkUnderMouse = 0; m_iLastLinkRectTop = -1; m_iLastLinkRectHeight = -1; m_pMasterView = 0; m_pToolWidget = 0; m_pWrappedBlockSelectionInfo = new KviIrcViewWrappedBlockSelectionInfo; m_pMessagesStoppedWhileSelecting = new KviPointerList; m_pMessagesStoppedWhileSelecting->setAutoDelete(false); // say qt to avoid erasing on repaint #ifdef COMPILE_USE_QT4 setAutoFillBackground(false); #else setBackgroundMode(NoBackground); #endif m_pFm = 0; // will be updated in the first paint event m_pToolTip = new KviIrcViewToolTip(this); // Create the scroll bar #ifdef COMPILE_USE_QT4 m_pScrollBar = new TQScrollBar(0,0,1,10,0,Qt::Vertical,this,"irc_view_scrollbar"); #else m_pScrollBar = new TQScrollBar(0,0,1,10,0,Qt::Vertical,this,"irc_view_scrollbar"); #endif m_pScrollBar->setTracking(true); m_pScrollBar->show(); m_pScrollBar->setFocusProxy(this); m_pToolsButton = new KviStyledToolButton(this,"btntools"); #ifdef COMPILE_USE_QT4 TQIcon is1(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUPMENU))); m_pToolsButton->setAutoRaise(true); #else TQIconSet is1(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUPMENU)),TQIconSet::Small); #endif m_pToolsButton->setIconSet(is1); KviTalToolTip::add(m_pToolsButton,__tr2qs("Search tools")); m_pToolsButton->setFocusProxy(this); connect(m_pToolsButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(showToolsPopup())); m_pToolsButton->show(); connect(m_pScrollBar,TQT_SIGNAL(valueChanged(int)),this,TQT_SLOT(scrollBarPositionChanged(int))); m_iLastScrollBarValue = 0; // set the minimum width setMinimumWidth(KVI_IRCVIEW_MINIMUM_WIDTH); // and catch all mouse events setMouseTracking(true); // let's go! applyOptions(); if(KVI_OPTION_UINT(KviOption_uintAutoFlushLogs)) //m_iFlushTimer { m_iFlushTimer = startTimer(KVI_OPTION_UINT(KviOption_uintAutoFlushLogs)*60*1000); } // if(pWnd->input()) setFocusProxy(pWnd->input()); } static inline void delete_text_line(KviIrcViewLine * l) { for(unsigned int i=0;iuChunkCount;i++) { if((l->pChunks[i].type == KVI_TEXT_ESCAPE) || (l->pChunks[i].type == KVI_TEXT_ICON)) { if( (l->pChunks[i].type == KVI_TEXT_ICON) && (l->pChunks[i].szPayload!=l->pChunks[i].szSmileId) ) kvi_free(l->pChunks[i].szSmileId); kvi_free(l->pChunks[i].szPayload); } } kvi_free(l->pChunks); //free attributes data if(l->iBlockCount)kvi_free(l->pBlocks); delete l; } KviIrcView::~KviIrcView() { // kill any pending timer if(m_iFlushTimer) killTimer(m_iFlushTimer); if(m_iSelectTimer)killTimer(m_iSelectTimer); if(m_iMouseTimer)killTimer(m_iMouseTimer); // and close the log file (flush!) stopLogging(); if(m_pToolWidget)delete m_pToolWidget; // don't forget the bacgkround pixmap! if(m_pPrivateBackgroundPixmap)delete m_pPrivateBackgroundPixmap; // and to remove all the text lines emptyBuffer(false); // the pending ones too! while(KviIrcViewLine * l = m_pMessagesStoppedWhileSelecting->first()) { m_pMessagesStoppedWhileSelecting->removeFirst(); delete_text_line(l); } delete m_pMessagesStoppedWhileSelecting; if(m_pFm)delete m_pFm; delete m_pToolTip; delete m_pWrappedBlockSelectionInfo; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // The IrcView : options // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void KviIrcView::setFont(const TQFont &f) { if(m_pFm) { // force an update to the font variables delete m_pFm; m_pFm = 0; } KviIrcViewLine * l = m_pFirstLine; while(l) { l->iMaxLineWidth = -1; l = l->pNext; } TQWidget::setFont(f); update(); } void KviIrcView::applyOptions() { flushLog(); setFont(KVI_OPTION_FONT(KviOption_fontIrcView)); if(m_iFlushTimer) killTimer(m_iFlushTimer); if(KVI_OPTION_UINT(KviOption_uintAutoFlushLogs)) { m_iFlushTimer = startTimer(KVI_OPTION_UINT(KviOption_uintAutoFlushLogs)*60*1000); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // The IrcView : DnD //2005.Resurection by Grifisx & Noldor // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void KviIrcView::enableDnd(bool bEnable) { setAcceptDrops(bEnable); m_bAcceptDrops = bEnable; } void KviIrcView::dragEnterEvent(TQDragEnterEvent *e) { if(!m_bAcceptDrops)return; e->accept(KviUriDrag::canDecode(e)); emit dndEntered(); } void KviIrcView::dropEvent(TQDropEvent *e) { if(!m_bAcceptDrops)return; TQStringList list; if(KviUriDrag::decodeLocalFiles(e,list)) { if(!list.isEmpty()) { TQStringList::ConstIterator it = list.begin(); //kewl ! :) for( ; it != list.end(); ++it ) { TQString tmp = *it; //wow :) #ifndef COMPILE_ON_WINDOWS if(tmp[0] != '/')tmp.prepend("/"); //HACK HACK HACK for TQt bug (?!?) #endif emit fileDropped(tmp); } } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // The IrcView : Logging // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void KviIrcView::stopLogging() { if(m_pLogFile) { TQString szLogEnd; szLogEnd.sprintf(__tr2qs("### Log session terminated at %s ###"),TQDateTime::currentDateTime().toString().utf8().data()); add2Log(szLogEnd); m_pLogFile->close(); #ifdef COMPILE_ZLIB_SUPPORT if(KVI_OPTION_BOOL(KviOption_boolGzipLogs)) { if(m_pLogFile->open(IO_ReadOnly)) { TQByteArray bytes; bytes=m_pLogFile->readAll(); m_pLogFile->close(); TQFileInfo fi(*m_pLogFile); TQString szFname=fi.dirPath(true)+TQString("/")+fi.baseName(true); gzFile file=gzopen(TQTextCodec::codecForLocale()->fromUnicode(szFname).data(),"ab9"); if(file) { gzwrite(file,bytes.data(),bytes.size()); gzclose(file); m_pLogFile->remove(); } else { debug("Cannot open compressed stream"); } } } #endif delete m_pLogFile; m_pLogFile = 0; } } void KviIrcView::getLogFileName(KviStr &buffer) { if(m_pLogFile)buffer.append(m_pLogFile->name()); } void KviIrcView::getLogFileName(TQString &buffer) { if(m_pLogFile) buffer=m_pLogFile->name(); } void KviIrcView::getTextBuffer(TQString &buffer) { // FIXME: #warning "This does not merge the KviChannel::m_pMessageView buffer!" buffer = ""; if(!m_pLastLine)return; for(KviIrcViewLine *l=m_pFirstLine;l;l=l->pNext) { buffer.append(l->szText); buffer.append("\n"); } } void KviIrcView::flushLog() { if(m_pLogFile) { #ifdef COMPILE_ZLIB_SUPPORT if(KVI_OPTION_BOOL(KviOption_boolGzipLogs)) { m_pLogFile->close(); if(m_pLogFile->open(IO_ReadOnly)) { TQByteArray bytes; bytes=m_pLogFile->readAll(); m_pLogFile->close(); TQFileInfo fi(*m_pLogFile); TQString szFname=fi.dirPath(true)+TQString("/")+fi.baseName(true); gzFile file=gzopen(TQTextCodec::codecForLocale()->fromUnicode(szFname).data(),"ab9"); if(file) { gzwrite(file,bytes.data(),bytes.size()); gzclose(file); m_pLogFile->remove(); } else { debug("Cannot open compressed stream"); } } m_pLogFile->open(IO_Append|IO_WriteOnly); } else #endif m_pLogFile->flush(); } else if(m_pMasterView)m_pMasterView->flushLog(); } const TQString & KviIrcView::lastMessageText() { KviIrcViewLine * pCur=m_pLastLine; while(pCur) { switch(pCur->iMsgType) { case KVI_OUT_CHANPRIVMSG: case KVI_OUT_CHANPRIVMSGCRYPTED: case KVI_OUT_CHANNELNOTICE: case KVI_OUT_CHANNELNOTICECRYPTED: case KVI_OUT_ACTION: case KVI_OUT_OWNPRIVMSG: case KVI_OUT_OWNPRIVMSGCRYPTED: case KVI_OUT_HIGHLIGHT: return pCur->szText; } pCur=pCur->pPrev; } return KviTQString::empty; } const TQString & KviIrcView::lastLineOfText() { if(!m_pLastLine)return KviTQString::empty; return m_pLastLine->szText; } //void KviIrcView::toggleLogging() //{ // if(isLogging())stopLogging(); // else { //#warning "FIX THIS COMMENTED STUFF" // // KviStr tmp; // m_pKviWindow->getDefaultLogName(tmp); // startLogging(tmp.ptr()); // // } //} void KviIrcView::setMasterView(KviIrcView * v) { if(m_pMasterView)disconnect(this,TQT_SLOT(masterDead())); m_pMasterView = v; if(m_pMasterView)connect(m_pMasterView,TQT_SIGNAL(destroyed()),this,TQT_SLOT(masterDead())); } void KviIrcView::masterDead() { m_pMasterView = 0; } bool KviIrcView::startLogging(const TQString& fname,bool bPrependCurBuffer) { stopLogging(); TQString szFname(fname); if(fname.isEmpty()) { if(!m_pKviWindow)return false; m_pKviWindow->getDefaultLogFileName(szFname); } #ifdef COMPILE_ZLIB_SUPPORT if(KVI_OPTION_BOOL(KviOption_boolGzipLogs)) szFname+=".tmp"; #endif m_pLogFile = new TQFile(szFname); if(m_pLogFile->exists()) { if(!m_pLogFile->open(IO_Append|IO_WriteOnly)) { delete m_pLogFile; m_pLogFile = 0; return false; } } else { if(!m_pLogFile->open(IO_WriteOnly)) { delete m_pLogFile; m_pLogFile = 0; return false; } } TQString szLogStart; szLogStart.sprintf(__tr2qs("### Log session started at %s ###"),TQDateTime::currentDateTime().toString().utf8().data()); add2Log(szLogStart); if(bPrependCurBuffer) { add2Log(__tr2qs("### Existing data buffer:")); TQString buffer; getTextBuffer(buffer); add2Log(buffer); add2Log(__tr2qs("### End of existing data buffer.")); m_pLogFile->flush(); } return true; } void KviIrcView::add2Log(const TQString &szBuffer,int iMsgType) { TQString szToWrite=TQString("%1 %2\n").arg(iMsgType).arg(szBuffer); KviTQCString szTmp = KviTQString::toUtf8(szToWrite); if(m_pLogFile->writeBlock(szTmp.data(),szTmp.length())==-1) debug("WARNING : Can not write to the log file."); } //============================================================================= // // Some slots // //void KviIrcView::saveBufferToFile() //{ // // Yeah....this is powerful! :) //// KviStr cmd = "/DIALOG (savefile,Choose a file name,$deflogfile($window).savebuf,$window) " //// "if(\"$dialogresult\" != \"\")window $dialogmagic savebuffer $dialogresult"; //// m_pFrm->m_pUserParser->parseUserCommand(cmd,m_pKviWindow); //} /* void KviIrcView::toggleTimestamp() { setTimestamp(!timestamp()); } void KviIrcView::toggleImages() { setShowImages(!imagesVisible()); }*/ void KviIrcView::clearBuffer() { emptyBuffer(true); } bool KviIrcView::saveBuffer(const char *filename) { TQFile f(TQString::fromUtf8(filename)); if(!f.open(IO_WriteOnly|IO_Truncate))return false; TQString tmp; getTextBuffer(tmp); KviTQCString tmpx = KviTQString::toUtf8(tmp); f.writeBlock(tmpx.data(),tmpx.length()); f.close(); return true; } void KviIrcView::prevLine(){ m_pScrollBar->subtractLine(); } void KviIrcView::nextLine(){ m_pScrollBar->addLine(); } void KviIrcView::prevPage(){ m_pScrollBar->subtractPage(); } void KviIrcView::nextPage(){ m_pScrollBar->addPage(); } void KviIrcView::setPrivateBackgroundPixmap(const TQPixmap &pixmap,bool bRepaint) { if(m_pPrivateBackgroundPixmap) { delete m_pPrivateBackgroundPixmap; m_pPrivateBackgroundPixmap=0; } if(!pixmap.isNull())m_pPrivateBackgroundPixmap = new TQPixmap(pixmap); if(bRepaint) update(); } void KviIrcView::emptyBuffer(bool bRepaint) { while(m_pLastLine != 0)removeHeadLine(); if(bRepaint) update(); } void KviIrcView::clearLineMark(bool bRepaint) { m_uLineMarkLineIndex = KVI_IRCVIEW_INVALID_LINE_MARK_INDEX; clearUnreaded(); if(bRepaint) update(); } void KviIrcView::checkLogDate() { TQDate::currentDate(); } void KviIrcView::clearUnreaded() { m_bHaveUnreadedHighlightedMessages = false; m_bHaveUnreadedMessages = false; if(m_pFrm) if(m_pFrm->dockExtension()) m_pFrm->dockExtension()->refresh(); } void KviIrcView::setMaxBufferSize(int maxBufSize,bool bRepaint) { if(maxBufSize < 32)maxBufSize = 32; m_iMaxLines = maxBufSize; while(m_iNumLines > m_iMaxLines)removeHeadLine(); m_pScrollBar->setRange(0,m_iNumLines); if(bRepaint) update(); } /* void KviIrcView::setShowImages(bool bShow,bool bRepaint) { if(m_bShowImages!=bShow) { m_bShowImages=bShow; if(bRepaint)paintEvent(0); } } */ /* void KviIrcView::setTimestamp(bool bTimestamp) { m_bTimestamp = bTimestamp; // STATS FOR A BUFFER FULL OF HIGHLY COLORED STRINGS , HIGHLY WRAPPED // // Lines = 1024 (322425 bytes - 314 KB) (avg 314 bytes per line) , well :) // string bytes = 87745 (85 KB) // attributes = 3576 (42912 bytes - 41 KB) // blocks = 12226 (146712 bytes - 143 KB) // // unsigned long int nAlloc = 0; // unsigned long int nLines = 0; // unsigned long int nStringBytes = 0; // unsigned long int nAttrBytes = 0; // unsigned long int nBlockBytes = 0; // unsigned long int nBlocks = 0; // unsigned long int nAttributes = 0; // KviIrcViewLine * l=m_pFirstLine; // while(l){ // nLines++; // nAlloc += sizeof(KviIrcViewLine); // nStringBytes += l->data_len + 1; // nAlloc += l->data_len + 1; // nAlloc += (l->uChunkCount * sizeof(KviIrcViewLineChunk)); // nAttrBytes +=(l->uChunkCount * sizeof(KviIrcViewLineChunk)); // nAlloc += (l->iBlockCount * sizeof(KviIrcViewLineChunk)); // nBlockBytes += (l->iBlockCount * sizeof(KviIrcViewLineChunk)); // nBlocks += (l->iBlockCount); // nAttributes += (l->uChunkCount); // l = l->pNext; // } // debug("\n\nLines = %u (%u bytes - %u KB) (avg %u bytes per line)",nLines,nAlloc,nAlloc / 1024,nLines ? (nAlloc / nLines) : 0); // debug("string bytes = %u (%u KB)",nStringBytes,nStringBytes / 1024); // debug("attributes = %u (%u bytes - %u KB)",nAttributes,nAttrBytes,nAttrBytes / 1024); // debug("blocks = %u (%u bytes - %u KB)\n",nBlocks,nBlockBytes,nBlockBytes / 1024); } */ void KviIrcView::scrollBarPositionChanged(int newValue) { if(!m_pCurLine)return; int diff = 0; if(newValue > m_iLastScrollBarValue) { while(newValue > m_iLastScrollBarValue) { if(m_pCurLine->pNext) { m_pCurLine=m_pCurLine->pNext; diff++; } m_iLastScrollBarValue++; } } else { while(newValue < m_iLastScrollBarValue) { if(m_pCurLine->pPrev)m_pCurLine=m_pCurLine->pPrev; m_iLastScrollBarValue--; } } if(!m_bSkipScrollBarRepaint) repaint(); //update(); // if(!m_bSkipScrollBarRepaint)postUpdateEvent(); } bool KviIrcView::event(TQEvent *e) { if(e->type() == TQEvent::User) { __range_valid(m_bPostedPaintEventPending); if(m_iUnprocessedPaintEventRequests) repaint(); // else we just had a pointEvent that did the job m_bPostedPaintEventPending = false; return true; } return TQWidget::event(e); } void KviIrcView::wheelEvent(TQWheelEvent *e) { #ifdef COMPILE_USE_QT4 static bool bHere = false; if(bHere)return; bHere = true; // TQt4 tends to jump into infinite recursion here #endif g_pApp->sendEvent(m_pScrollBar,e); #ifdef COMPILE_USE_QT4 bHere = false; #endif } void KviIrcView::postUpdateEvent() { // This will post a TQEvent with a full repaint request if(!m_bPostedPaintEventPending) { m_bPostedPaintEventPending = true; TQEvent *e = new TQEvent(TQEvent::User); g_pApp->postEvent(this,e); // queue a repaint } m_iUnprocessedPaintEventRequests++; // paintEvent() will set it to 0 if(m_iUnprocessedPaintEventRequests == 3) { // Three unprocessed paint events...do it now #ifdef COMPILE_PSEUDO_TRANSPARENCY if(! ((KVI_OPTION_PIXMAP(KviOption_pixmapIrcViewBackground).pixmap()) || m_pPrivateBackgroundPixmap || g_pShadedChildGlobalDesktopBackground)) fastScroll(3); #else if(! ((KVI_OPTION_PIXMAP(KviOption_pixmapIrcViewBackground).pixmap()) || m_pPrivateBackgroundPixmap)) fastScroll(3); #endif else repaint(); } } void KviIrcView::appendLine(KviIrcViewLine *ptr,bool bRepaint) { //This one appends a KviIrcViewLine to //the buffer list (at the end) if(m_bMouseIsDown) { // Do not move the view! // So we append the text line to a temp queue // and then we'll add it when the mouse button is released m_pMessagesStoppedWhileSelecting->append(ptr); return; } // First log the line and assign the index // Don't use add2log here!...we must go as fast as possible, so we avoid some push and pop calls, and also a couple of branches if(m_pLogFile && KVI_OPTION_BOOL(KviOption_boolStripControlCodesInLogs)) { // a slave view has no log files! if(KVI_OPTION_MSGTYPE(ptr->iMsgType).logEnabled()) { add2Log(ptr->szText,ptr->iMsgType); // If we fail...this has been already reported! } // mmh.. when this overflows... we have problems (find doesn't work anymore :() // but it overflows at 2^32 lines... 2^32 = 4.294.967.296 lines // to spit it out in a year you'd need to print 1360 lines per second... that's insane :D // a really fast but reasonable rate of printed lines might be 10 per second // thus 429.496.730 seconds would be needed to make this var overflow // that means more or less 13 years of text spitting at full rate :D // I think that we can safely assume that this will NOT overflow ... your cpu (or you) // will get mad before. Well.. it is not that dangerous after all... ptr->uIndex = m_uNextLineIndex; m_uNextLineIndex++; } else { // no log: we could have master view! if(m_pMasterView) { if(m_pMasterView->m_pLogFile && KVI_OPTION_BOOL(KviOption_boolStripControlCodesInLogs)) { if(KVI_OPTION_MSGTYPE(ptr->iMsgType).logEnabled()) { m_pMasterView->add2Log(ptr->szText,ptr->iMsgType); } } ptr->uIndex = m_pMasterView->m_uNextLineIndex; m_pMasterView->m_uNextLineIndex++; } else { ptr->uIndex = m_uNextLineIndex; m_uNextLineIndex++; } } if(m_pLastLine) { // There is at least one line in the view m_pLastLine->pNext=ptr; ptr->pPrev =m_pLastLine; ptr->pNext =0; m_iNumLines++; if(m_iNumLines > m_iMaxLines) { // Too many lines in the view...remove one removeHeadLine(); if(m_pCurLine==m_pLastLine) { m_pCurLine=ptr; if(bRepaint) postUpdateEvent(); } else { // the cur line remains the same // the scroll bar must move up one place to be in sync m_bSkipScrollBarRepaint = true; if(m_pScrollBar->value() > 0) { m_iLastScrollBarValue--; __range_valid(m_iLastScrollBarValue >= 0); m_pScrollBar->subtractLine(); } // else will stay in sync m_bSkipScrollBarRepaint = false; } } else { // Just append m_pScrollBar->setRange(0,m_iNumLines); if(m_pCurLine==m_pLastLine) { m_bSkipScrollBarRepaint = true; m_pScrollBar->addLine(); m_bSkipScrollBarRepaint = false; if(bRepaint) postUpdateEvent(); } } m_pLastLine=ptr; } else { //First line m_pLastLine = ptr; m_pFirstLine = ptr; m_pCurLine = ptr; ptr->pPrev = 0; ptr->pNext = 0; m_iNumLines = 1; m_pScrollBar->setRange(0,1); m_pScrollBar->addLine(); if(bRepaint) postUpdateEvent(); } } //============== removeHeadLine ===============// void KviIrcView::removeHeadLine(bool bRepaint) { //Removes the first line of the text buffer if(!m_pLastLine)return; if(m_pFirstLine == m_pCursorLine)m_pCursorLine = 0; if(m_pFirstLine->pNext) { KviIrcViewLine *aux_ptr=m_pFirstLine->pNext; //get the next line aux_ptr->pPrev=0; //becomes the first if(m_pFirstLine==m_pCurLine)m_pCurLine=aux_ptr; //move the cur line if necessary delete_text_line(m_pFirstLine); //delete the struct m_pFirstLine=aux_ptr; //set the last m_iNumLines--; //and decrement the count } else { //unique line m_pCurLine = 0; delete_text_line(m_pFirstLine); m_pFirstLine = 0; m_iNumLines = 0; m_pLastLine = 0; } if(bRepaint) repaint(); } void KviIrcView::splitMessagesTo(KviIrcView *v) { v->emptyBuffer(false); KviIrcViewLine * l = m_pFirstLine; KviIrcViewLine * tmp; while(l) switch(l->iMsgType) { case KVI_OUT_CHANPRIVMSG: case KVI_OUT_CHANPRIVMSGCRYPTED: case KVI_OUT_CHANNELNOTICE: case KVI_OUT_CHANNELNOTICECRYPTED: case KVI_OUT_ACTION: case KVI_OUT_OWNPRIVMSG: case KVI_OUT_OWNPRIVMSGCRYPTED: case KVI_OUT_HIGHLIGHT: { m_iNumLines--; v->m_iNumLines++; if(l->pNext)l->pNext->pPrev = l->pPrev; if(l->pPrev)l->pPrev->pNext = l->pNext; if(l == m_pFirstLine)m_pFirstLine = l->pNext; if(l == m_pLastLine)m_pLastLine = l->pPrev; if(v->m_pLastLine) { v->m_pLastLine->pNext = l; l->pPrev = v->m_pLastLine; v->m_pLastLine = l; } else { v->m_pFirstLine = l; l->pPrev = 0; v->m_pLastLine = l; } tmp = l->pNext; l->pNext = 0; l = tmp; } break; default: l = l->pNext; break; } v->m_pCurLine = v->m_pLastLine; m_pCurLine = m_pLastLine; v->m_pCursorLine = 0; m_pCursorLine = 0; m_iLastScrollBarValue = m_iNumLines; m_pScrollBar->setRange(0,m_iNumLines); m_pScrollBar->setValue(m_iNumLines); repaint(); v->m_iLastScrollBarValue = v->m_iNumLines; v->m_pScrollBar->setRange(0,v->m_iNumLines); v->m_pScrollBar->setValue(v->m_iNumLines); v->repaint(); } void KviIrcView::appendMessagesFrom(KviIrcView *v) { if(!m_pLastLine) { m_pFirstLine = v->m_pFirstLine; } else { m_pLastLine->pNext = v->m_pFirstLine; v->m_pFirstLine->pPrev = m_pLastLine; } m_pLastLine = v->m_pLastLine; m_pCurLine = m_pLastLine; m_pCursorLine = 0; v->m_pFirstLine = 0; v->m_pLastLine = 0; v->m_pCurLine = 0; v->m_pCursorLine = 0; m_iNumLines += v->m_iNumLines; v->m_iNumLines = 0; // v->m_pScrollBar->setRange(0,0); // v->m_pScrollBar->setValue(0); m_iLastScrollBarValue = m_iNumLines; m_pScrollBar->setRange(0,m_iNumLines); m_pScrollBar->setValue(m_iNumLines); repaint(); } void KviIrcView::joinMessagesFrom(KviIrcView *v) { KviIrcViewLine * l1 = m_pFirstLine; KviIrcViewLine * l2 = v->m_pFirstLine; KviIrcViewLine * tmp; while(l2) { if(l1) { if(l2->uIndex < l1->uIndex) { // the external message is older than the current internal one l2->pPrev = l1->pPrev; if(l1->pPrev)l1->pPrev->pNext = l2; else m_pFirstLine = l2; l1->pPrev = l2; tmp = l2->pNext; l2->pNext = l1; l2 = tmp; } else { // the external message is younger than the current internal one l1 = l1->pNext; } } else { // There is no current internal message (ran over the end) // merge at the end then if(m_pFirstLine) { m_pLastLine->pNext = l2; l2->pPrev = m_pLastLine; } else { m_pFirstLine = l2; l2->pPrev = 0; } tmp = l2->pNext; l2->pNext = 0; m_pLastLine = l2; l2 = tmp; } } m_pCurLine = m_pLastLine; m_pCursorLine = 0; v->m_pFirstLine = 0; v->m_pLastLine = 0; v->m_pCurLine = 0; v->m_pCursorLine = 0; m_iNumLines += v->m_iNumLines; v->m_iNumLines = 0; // v->m_pScrollBar->setRange(0,0); // v->m_pScrollBar->setValue(0); m_iLastScrollBarValue = m_iNumLines; m_pScrollBar->setRange(0,m_iNumLines); m_pScrollBar->setValue(m_iNumLines); repaint(); } void KviIrcView::appendText(int iMsgType,const kvi_wchar_t *data_ptr,int iFlags) { //appends a text string to the buffer list //splits the lines __range_valid(data_ptr); m_pLastLinkUnderMouse = 0; while(*data_ptr) { //Have more data KviIrcViewLine *line_ptr=new KviIrcViewLine; //create a line struct line_ptr->iMsgType=iMsgType; line_ptr->iMaxLineWidth=-1; line_ptr->iBlockCount=0; if(!KVI_OPTION_BOOL(KviOption_boolStripControlCodesInLogs)) { TQString szBuffer; kvi_appendWCharToTQStringWithLength(&szBuffer,data_ptr,kvi_wstrlen(data_ptr)); szBuffer.prepend(TQDateTime::currentDateTime().toString("[h:mm:ss] ")); if(m_pLogFile && KVI_OPTION_MSGTYPE(iMsgType).logEnabled()) { add2Log(szBuffer,iMsgType); } else if(m_pMasterView) { if(m_pMasterView->m_pLogFile && KVI_OPTION_MSGTYPE(iMsgType).logEnabled()) { m_pMasterView->add2Log(szBuffer,iMsgType); } } } data_ptr=getTextLine(iMsgType,data_ptr,line_ptr,!(iFlags & NoTimestamp)); appendLine(line_ptr,!(iFlags & NoRepaint)); if(iFlags & SetLineMark) { if(KVI_OPTION_BOOL(KviOption_boolTrackLastReadTextViewLine)) { m_uLineMarkLineIndex = line_ptr->uIndex; iFlags &= ~SetLineMark; } m_bHaveUnreadedHighlightedMessages = m_bHaveUnreadedHighlightedMessages || iMsgType == KVI_OUT_HIGHLIGHT; m_bHaveUnreadedMessages = m_bHaveUnreadedMessages || iMsgType == KVI_OUT_CHANPRIVMSG || iMsgType == KVI_OUT_CHANPRIVMSGCRYPTED || iMsgType == KVI_OUT_CHANNELNOTICE || iMsgType == KVI_OUT_CHANNELNOTICECRYPTED || iMsgType == KVI_OUT_ACTION || iMsgType == KVI_OUT_OWNPRIVMSGCRYPTED || iMsgType == KVI_OUT_HIGHLIGHT; } } } void KviIrcView::getLinkEscapeCommand(TQString &buffer,const TQString &szPayload,const TQString &escape_label) { if(szPayload.isEmpty())return; int idx = szPayload.find(escape_label); if(idx == -1)return; idx += escape_label.length(); int idx2 = szPayload.find("[!",idx); int len = idx2 == -1 ? szPayload.length() - idx : idx2 - idx; buffer = szPayload.mid(idx,len); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // The IrcView : Get text line // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static kvi_wchar_t case_xtx_XX[256] = { 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; static kvi_wchar_t case_ltu_00[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0130, 0x004A, 0x212A, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x017F, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x212B, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0000, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178 }; static kvi_wchar_t case_ltu_01[256] = { 0x0000, 0x0100, 0x0000, 0x0102, 0x0000, 0x0104, 0x0000, 0x0106, 0x0000, 0x0108, 0x0000, 0x010A, 0x0000, 0x010C, 0x0000, 0x010E, 0x0000, 0x0110, 0x0000, 0x0112, 0x0000, 0x0114, 0x0000, 0x0116, 0x0000, 0x0118, 0x0000, 0x011A, 0x0000, 0x011C, 0x0000, 0x011E, 0x0000, 0x0120, 0x0000, 0x0122, 0x0000, 0x0124, 0x0000, 0x0126, 0x0000, 0x0128, 0x0000, 0x012A, 0x0000, 0x012C, 0x0000, 0x012E, 0x0000, 0x0049, 0x0000, 0x0132, 0x0000, 0x0134, 0x0000, 0x0136, 0x0000, 0x0000, 0x0139, 0x0000, 0x013B, 0x0000, 0x013D, 0x0000, 0x013F, 0x0000, 0x0141, 0x0000, 0x0143, 0x0000, 0x0145, 0x0000, 0x0147, 0x0000, 0x0000, 0x014A, 0x0000, 0x014C, 0x0000, 0x014E, 0x0000, 0x0150, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156, 0x0000, 0x0158, 0x0000, 0x015A, 0x0000, 0x015C, 0x0000, 0x015E, 0x0000, 0x0160, 0x0000, 0x0162, 0x0000, 0x0164, 0x0000, 0x0166, 0x0000, 0x0168, 0x0000, 0x016A, 0x0000, 0x016C, 0x0000, 0x016E, 0x0000, 0x0170, 0x0000, 0x0172, 0x0000, 0x0174, 0x0000, 0x0176, 0x0000, 0x0000, 0x0179, 0x0000, 0x017B, 0x0000, 0x017D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0182, 0x0000, 0x0184, 0x0000, 0x0000, 0x0187, 0x0000, 0x0000, 0x0000, 0x018B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0191, 0x0000, 0x0000, 0x01F6, 0x0000, 0x0000, 0x0000, 0x0198, 0x0000, 0x0000, 0x0000, 0x0000, 0x0220, 0x0000, 0x0000, 0x01A0, 0x0000, 0x01A2, 0x0000, 0x01A4, 0x0000, 0x0000, 0x01A7, 0x0000, 0x0000, 0x0000, 0x0000, 0x01AC, 0x0000, 0x0000, 0x01AF, 0x0000, 0x0000, 0x0000, 0x01B3, 0x0000, 0x01B5, 0x0000, 0x0000, 0x01B8, 0x0000, 0x0000, 0x0000, 0x01BC, 0x0000, 0x01F7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01C5, 0x0000, 0x0000, 0x01C8, 0x0000, 0x0000, 0x01CB, 0x0000, 0x01CD, 0x0000, 0x01CF, 0x0000, 0x01D1, 0x0000, 0x01D3, 0x0000, 0x01D5, 0x0000, 0x01D7, 0x0000, 0x01D9, 0x0000, 0x01DB, 0x018E, 0x0000, 0x01DE, 0x0000, 0x01E0, 0x0000, 0x01E2, 0x0000, 0x01E4, 0x0000, 0x01E6, 0x0000, 0x01E8, 0x0000, 0x01EA, 0x0000, 0x01EC, 0x0000, 0x01EE, 0x0000, 0x0000, 0x0000, 0x01F2, 0x0000, 0x01F4, 0x0000, 0x0000, 0x0000, 0x01F8, 0x0000, 0x01FA, 0x0000, 0x01FC, 0x0000, 0x01FE }; static kvi_wchar_t case_ltu_02[256] = { 0x0000, 0x0200, 0x0000, 0x0202, 0x0000, 0x0204, 0x0000, 0x0206, 0x0000, 0x0208, 0x0000, 0x020A, 0x0000, 0x020C, 0x0000, 0x020E, 0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0214, 0x0000, 0x0216, 0x0000, 0x0218, 0x0000, 0x021A, 0x0000, 0x021C, 0x0000, 0x021E, 0x0000, 0x0000, 0x0000, 0x0222, 0x0000, 0x0224, 0x0000, 0x0226, 0x0000, 0x0228, 0x0000, 0x022A, 0x0000, 0x022C, 0x0000, 0x022E, 0x0000, 0x0230, 0x0000, 0x0232, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0181, 0x0186, 0x0000, 0x0189, 0x018A, 0x0000, 0x018F, 0x0000, 0x0190, 0x0000, 0x0000, 0x0000, 0x0000, 0x0193, 0x0000, 0x0000, 0x0194, 0x0000, 0x0000, 0x0000, 0x0000, 0x0197, 0x0196, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x019C, 0x0000, 0x0000, 0x019D, 0x0000, 0x0000, 0x019F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01A6, 0x0000, 0x0000, 0x01A9, 0x0000, 0x0000, 0x0000, 0x0000, 0x01AE, 0x0000, 0x01B1, 0x01B2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01B7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_ltu_03[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0386, 0x0388, 0x0389, 0x038A, 0x0000, 0x0391, 0x03D0, 0x0393, 0x0394, 0x03F5, 0x0396, 0x0397, 0x03F4, 0x1FBE, 0x03F0, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03D6, 0x03F1, 0x0000, 0x03F2, 0x03A4, 0x03A5, 0x03D5, 0x03A7, 0x03A8, 0x2126, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03D8, 0x0000, 0x03DA, 0x0000, 0x03DC, 0x0000, 0x03DE, 0x0000, 0x03E0, 0x0000, 0x03E2, 0x0000, 0x03E4, 0x0000, 0x03E6, 0x0000, 0x03E8, 0x0000, 0x03EA, 0x0000, 0x03EC, 0x0000, 0x03EE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_ltu_04[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F, 0x0000, 0x0460, 0x0000, 0x0462, 0x0000, 0x0464, 0x0000, 0x0466, 0x0000, 0x0468, 0x0000, 0x046A, 0x0000, 0x046C, 0x0000, 0x046E, 0x0000, 0x0470, 0x0000, 0x0472, 0x0000, 0x0474, 0x0000, 0x0476, 0x0000, 0x0478, 0x0000, 0x047A, 0x0000, 0x047C, 0x0000, 0x047E, 0x0000, 0x0480, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x048A, 0x0000, 0x048C, 0x0000, 0x048E, 0x0000, 0x0490, 0x0000, 0x0492, 0x0000, 0x0494, 0x0000, 0x0496, 0x0000, 0x0498, 0x0000, 0x049A, 0x0000, 0x049C, 0x0000, 0x049E, 0x0000, 0x04A0, 0x0000, 0x04A2, 0x0000, 0x04A4, 0x0000, 0x04A6, 0x0000, 0x04A8, 0x0000, 0x04AA, 0x0000, 0x04AC, 0x0000, 0x04AE, 0x0000, 0x04B0, 0x0000, 0x04B2, 0x0000, 0x04B4, 0x0000, 0x04B6, 0x0000, 0x04B8, 0x0000, 0x04BA, 0x0000, 0x04BC, 0x0000, 0x04BE, 0x0000, 0x0000, 0x04C1, 0x0000, 0x04C3, 0x0000, 0x04C5, 0x0000, 0x04C7, 0x0000, 0x04C9, 0x0000, 0x04CB, 0x0000, 0x04CD, 0x0000, 0x0000, 0x04D0, 0x0000, 0x04D2, 0x0000, 0x04D4, 0x0000, 0x04D6, 0x0000, 0x04D8, 0x0000, 0x04DA, 0x0000, 0x04DC, 0x0000, 0x04DE, 0x0000, 0x04E0, 0x0000, 0x04E2, 0x0000, 0x04E4, 0x0000, 0x04E6, 0x0000, 0x04E8, 0x0000, 0x04EA, 0x0000, 0x04EC, 0x0000, 0x04EE, 0x0000, 0x04F0, 0x0000, 0x04F2, 0x0000, 0x04F4, 0x0000, 0x0000, 0x0000, 0x04F8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_ltu_05[256] = { 0x0000, 0x0500, 0x0000, 0x0502, 0x0000, 0x0504, 0x0000, 0x0506, 0x0000, 0x0508, 0x0000, 0x050A, 0x0000, 0x050C, 0x0000, 0x050E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, 0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F, 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_ltu_1E[256] = { 0x0000, 0x1E00, 0x0000, 0x1E02, 0x0000, 0x1E04, 0x0000, 0x1E06, 0x0000, 0x1E08, 0x0000, 0x1E0A, 0x0000, 0x1E0C, 0x0000, 0x1E0E, 0x0000, 0x1E10, 0x0000, 0x1E12, 0x0000, 0x1E14, 0x0000, 0x1E16, 0x0000, 0x1E18, 0x0000, 0x1E1A, 0x0000, 0x1E1C, 0x0000, 0x1E1E, 0x0000, 0x1E20, 0x0000, 0x1E22, 0x0000, 0x1E24, 0x0000, 0x1E26, 0x0000, 0x1E28, 0x0000, 0x1E2A, 0x0000, 0x1E2C, 0x0000, 0x1E2E, 0x0000, 0x1E30, 0x0000, 0x1E32, 0x0000, 0x1E34, 0x0000, 0x1E36, 0x0000, 0x1E38, 0x0000, 0x1E3A, 0x0000, 0x1E3C, 0x0000, 0x1E3E, 0x0000, 0x1E40, 0x0000, 0x1E42, 0x0000, 0x1E44, 0x0000, 0x1E46, 0x0000, 0x1E48, 0x0000, 0x1E4A, 0x0000, 0x1E4C, 0x0000, 0x1E4E, 0x0000, 0x1E50, 0x0000, 0x1E52, 0x0000, 0x1E54, 0x0000, 0x1E56, 0x0000, 0x1E58, 0x0000, 0x1E5A, 0x0000, 0x1E5C, 0x0000, 0x1E5E, 0x0000, 0x1E9B, 0x0000, 0x1E62, 0x0000, 0x1E64, 0x0000, 0x1E66, 0x0000, 0x1E68, 0x0000, 0x1E6A, 0x0000, 0x1E6C, 0x0000, 0x1E6E, 0x0000, 0x1E70, 0x0000, 0x1E72, 0x0000, 0x1E74, 0x0000, 0x1E76, 0x0000, 0x1E78, 0x0000, 0x1E7A, 0x0000, 0x1E7C, 0x0000, 0x1E7E, 0x0000, 0x1E80, 0x0000, 0x1E82, 0x0000, 0x1E84, 0x0000, 0x1E86, 0x0000, 0x1E88, 0x0000, 0x1E8A, 0x0000, 0x1E8C, 0x0000, 0x1E8E, 0x0000, 0x1E90, 0x0000, 0x1E92, 0x0000, 0x1E94, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1EA0, 0x0000, 0x1EA2, 0x0000, 0x1EA4, 0x0000, 0x1EA6, 0x0000, 0x1EA8, 0x0000, 0x1EAA, 0x0000, 0x1EAC, 0x0000, 0x1EAE, 0x0000, 0x1EB0, 0x0000, 0x1EB2, 0x0000, 0x1EB4, 0x0000, 0x1EB6, 0x0000, 0x1EB8, 0x0000, 0x1EBA, 0x0000, 0x1EBC, 0x0000, 0x1EBE, 0x0000, 0x1EC0, 0x0000, 0x1EC2, 0x0000, 0x1EC4, 0x0000, 0x1EC6, 0x0000, 0x1EC8, 0x0000, 0x1ECA, 0x0000, 0x1ECC, 0x0000, 0x1ECE, 0x0000, 0x1ED0, 0x0000, 0x1ED2, 0x0000, 0x1ED4, 0x0000, 0x1ED6, 0x0000, 0x1ED8, 0x0000, 0x1EDA, 0x0000, 0x1EDC, 0x0000, 0x1EDE, 0x0000, 0x1EE0, 0x0000, 0x1EE2, 0x0000, 0x1EE4, 0x0000, 0x1EE6, 0x0000, 0x1EE8, 0x0000, 0x1EEA, 0x0000, 0x1EEC, 0x0000, 0x1EEE, 0x0000, 0x1EF0, 0x0000, 0x1EF2, 0x0000, 0x1EF4, 0x0000, 0x1EF6, 0x0000, 0x1EF8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_ltu_1F[256] = { 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000, 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FB8, 0x1FB9, 0x0000, 0x1FBC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FCC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FD8, 0x1FD9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FE8, 0x1FE9, 0x0000, 0x0000, 0x0000, 0x1FEC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FFC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_ltu_21[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_ltu_24[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA, 0x24BB, 0x24BC, 0x24BD, 0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5, 0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_ltu_FF[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; kvi_wchar_t * kvirc_case_map_ltu[256] = { case_ltu_00, case_ltu_01, case_ltu_02, case_ltu_03, case_ltu_04, case_ltu_05, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_ltu_1E, case_ltu_1F, case_xtx_XX, case_ltu_21, case_xtx_XX, case_xtx_XX, case_ltu_24, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_ltu_FF }; static kvi_wchar_t case_utl_00[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0131, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03BC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0000, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_01[256] = { 0x0101, 0x0000, 0x0103, 0x0000, 0x0105, 0x0000, 0x0107, 0x0000, 0x0109, 0x0000, 0x010B, 0x0000, 0x010D, 0x0000, 0x010F, 0x0000, 0x0111, 0x0000, 0x0113, 0x0000, 0x0115, 0x0000, 0x0117, 0x0000, 0x0119, 0x0000, 0x011B, 0x0000, 0x011D, 0x0000, 0x011F, 0x0000, 0x0121, 0x0000, 0x0123, 0x0000, 0x0125, 0x0000, 0x0127, 0x0000, 0x0129, 0x0000, 0x012B, 0x0000, 0x012D, 0x0000, 0x012F, 0x0000, 0x0069, 0x0000, 0x0133, 0x0000, 0x0135, 0x0000, 0x0137, 0x0000, 0x0000, 0x013A, 0x0000, 0x013C, 0x0000, 0x013E, 0x0000, 0x0140, 0x0000, 0x0142, 0x0000, 0x0144, 0x0000, 0x0146, 0x0000, 0x0148, 0x0000, 0x0000, 0x014B, 0x0000, 0x014D, 0x0000, 0x014F, 0x0000, 0x0151, 0x0000, 0x0153, 0x0000, 0x0155, 0x0000, 0x0157, 0x0000, 0x0159, 0x0000, 0x015B, 0x0000, 0x015D, 0x0000, 0x015F, 0x0000, 0x0161, 0x0000, 0x0163, 0x0000, 0x0165, 0x0000, 0x0167, 0x0000, 0x0169, 0x0000, 0x016B, 0x0000, 0x016D, 0x0000, 0x016F, 0x0000, 0x0171, 0x0000, 0x0173, 0x0000, 0x0175, 0x0000, 0x0177, 0x0000, 0x00FF, 0x017A, 0x0000, 0x017C, 0x0000, 0x017E, 0x0000, 0x0073, 0x0000, 0x0253, 0x0183, 0x0000, 0x0185, 0x0000, 0x0254, 0x0188, 0x0000, 0x0256, 0x0257, 0x018C, 0x0000, 0x0000, 0x01DD, 0x0259, 0x025B, 0x0192, 0x0000, 0x0260, 0x0263, 0x0000, 0x0269, 0x0268, 0x0199, 0x0000, 0x0000, 0x0000, 0x026F, 0x0272, 0x0000, 0x0275, 0x01A1, 0x0000, 0x01A3, 0x0000, 0x01A5, 0x0000, 0x0280, 0x01A8, 0x0000, 0x0283, 0x0000, 0x0000, 0x01AD, 0x0000, 0x0288, 0x01B0, 0x0000, 0x028A, 0x028B, 0x01B4, 0x0000, 0x01B6, 0x0000, 0x0292, 0x01B9, 0x0000, 0x0000, 0x0000, 0x01BD, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01C6, 0x01C6, 0x0000, 0x01C9, 0x01C9, 0x0000, 0x01CC, 0x01CC, 0x0000, 0x01CE, 0x0000, 0x01D0, 0x0000, 0x01D2, 0x0000, 0x01D4, 0x0000, 0x01D6, 0x0000, 0x01D8, 0x0000, 0x01DA, 0x0000, 0x01DC, 0x0000, 0x0000, 0x01DF, 0x0000, 0x01E1, 0x0000, 0x01E3, 0x0000, 0x01E5, 0x0000, 0x01E7, 0x0000, 0x01E9, 0x0000, 0x01EB, 0x0000, 0x01ED, 0x0000, 0x01EF, 0x0000, 0x0000, 0x01F3, 0x01F3, 0x0000, 0x01F5, 0x0000, 0x0195, 0x01BF, 0x01F9, 0x0000, 0x01FB, 0x0000, 0x01FD, 0x0000, 0x01FF, 0x0000 }; static kvi_wchar_t case_utl_02[256] = { 0x0201, 0x0000, 0x0203, 0x0000, 0x0205, 0x0000, 0x0207, 0x0000, 0x0209, 0x0000, 0x020B, 0x0000, 0x020D, 0x0000, 0x020F, 0x0000, 0x0211, 0x0000, 0x0213, 0x0000, 0x0215, 0x0000, 0x0217, 0x0000, 0x0219, 0x0000, 0x021B, 0x0000, 0x021D, 0x0000, 0x021F, 0x0000, 0x019E, 0x0000, 0x0223, 0x0000, 0x0225, 0x0000, 0x0227, 0x0000, 0x0229, 0x0000, 0x022B, 0x0000, 0x022D, 0x0000, 0x022F, 0x0000, 0x0231, 0x0000, 0x0233, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_03[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03B9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03AC, 0x0000, 0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE, 0x0000, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03B2, 0x03B8, 0x0000, 0x0000, 0x0000, 0x03C6, 0x03C0, 0x0000, 0x03D9, 0x0000, 0x03DB, 0x0000, 0x03DD, 0x0000, 0x03DF, 0x0000, 0x03E1, 0x0000, 0x03E3, 0x0000, 0x03E5, 0x0000, 0x03E7, 0x0000, 0x03E9, 0x0000, 0x03EB, 0x0000, 0x03ED, 0x0000, 0x03EF, 0x0000, 0x03BA, 0x03C1, 0x03C3, 0x0000, 0x03B8, 0x03B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_04[256] = { 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0461, 0x0000, 0x0463, 0x0000, 0x0465, 0x0000, 0x0467, 0x0000, 0x0469, 0x0000, 0x046B, 0x0000, 0x046D, 0x0000, 0x046F, 0x0000, 0x0471, 0x0000, 0x0473, 0x0000, 0x0475, 0x0000, 0x0477, 0x0000, 0x0479, 0x0000, 0x047B, 0x0000, 0x047D, 0x0000, 0x047F, 0x0000, 0x0481, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x048B, 0x0000, 0x048D, 0x0000, 0x048F, 0x0000, 0x0491, 0x0000, 0x0493, 0x0000, 0x0495, 0x0000, 0x0497, 0x0000, 0x0499, 0x0000, 0x049B, 0x0000, 0x049D, 0x0000, 0x049F, 0x0000, 0x04A1, 0x0000, 0x04A3, 0x0000, 0x04A5, 0x0000, 0x04A7, 0x0000, 0x04A9, 0x0000, 0x04AB, 0x0000, 0x04AD, 0x0000, 0x04AF, 0x0000, 0x04B1, 0x0000, 0x04B3, 0x0000, 0x04B5, 0x0000, 0x04B7, 0x0000, 0x04B9, 0x0000, 0x04BB, 0x0000, 0x04BD, 0x0000, 0x04BF, 0x0000, 0x0000, 0x04C2, 0x0000, 0x04C4, 0x0000, 0x04C6, 0x0000, 0x04C8, 0x0000, 0x04CA, 0x0000, 0x04CC, 0x0000, 0x04CE, 0x0000, 0x0000, 0x04D1, 0x0000, 0x04D3, 0x0000, 0x04D5, 0x0000, 0x04D7, 0x0000, 0x04D9, 0x0000, 0x04DB, 0x0000, 0x04DD, 0x0000, 0x04DF, 0x0000, 0x04E1, 0x0000, 0x04E3, 0x0000, 0x04E5, 0x0000, 0x04E7, 0x0000, 0x04E9, 0x0000, 0x04EB, 0x0000, 0x04ED, 0x0000, 0x04EF, 0x0000, 0x04F1, 0x0000, 0x04F3, 0x0000, 0x04F5, 0x0000, 0x0000, 0x0000, 0x04F9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_05[256] = { 0x0501, 0x0000, 0x0503, 0x0000, 0x0505, 0x0000, 0x0507, 0x0000, 0x0509, 0x0000, 0x050B, 0x0000, 0x050D, 0x0000, 0x050F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_1E[256] = { 0x1E01, 0x0000, 0x1E03, 0x0000, 0x1E05, 0x0000, 0x1E07, 0x0000, 0x1E09, 0x0000, 0x1E0B, 0x0000, 0x1E0D, 0x0000, 0x1E0F, 0x0000, 0x1E11, 0x0000, 0x1E13, 0x0000, 0x1E15, 0x0000, 0x1E17, 0x0000, 0x1E19, 0x0000, 0x1E1B, 0x0000, 0x1E1D, 0x0000, 0x1E1F, 0x0000, 0x1E21, 0x0000, 0x1E23, 0x0000, 0x1E25, 0x0000, 0x1E27, 0x0000, 0x1E29, 0x0000, 0x1E2B, 0x0000, 0x1E2D, 0x0000, 0x1E2F, 0x0000, 0x1E31, 0x0000, 0x1E33, 0x0000, 0x1E35, 0x0000, 0x1E37, 0x0000, 0x1E39, 0x0000, 0x1E3B, 0x0000, 0x1E3D, 0x0000, 0x1E3F, 0x0000, 0x1E41, 0x0000, 0x1E43, 0x0000, 0x1E45, 0x0000, 0x1E47, 0x0000, 0x1E49, 0x0000, 0x1E4B, 0x0000, 0x1E4D, 0x0000, 0x1E4F, 0x0000, 0x1E51, 0x0000, 0x1E53, 0x0000, 0x1E55, 0x0000, 0x1E57, 0x0000, 0x1E59, 0x0000, 0x1E5B, 0x0000, 0x1E5D, 0x0000, 0x1E5F, 0x0000, 0x1E61, 0x0000, 0x1E63, 0x0000, 0x1E65, 0x0000, 0x1E67, 0x0000, 0x1E69, 0x0000, 0x1E6B, 0x0000, 0x1E6D, 0x0000, 0x1E6F, 0x0000, 0x1E71, 0x0000, 0x1E73, 0x0000, 0x1E75, 0x0000, 0x1E77, 0x0000, 0x1E79, 0x0000, 0x1E7B, 0x0000, 0x1E7D, 0x0000, 0x1E7F, 0x0000, 0x1E81, 0x0000, 0x1E83, 0x0000, 0x1E85, 0x0000, 0x1E87, 0x0000, 0x1E89, 0x0000, 0x1E8B, 0x0000, 0x1E8D, 0x0000, 0x1E8F, 0x0000, 0x1E91, 0x0000, 0x1E93, 0x0000, 0x1E95, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E61, 0x0000, 0x0000, 0x0000, 0x0000, 0x1EA1, 0x0000, 0x1EA3, 0x0000, 0x1EA5, 0x0000, 0x1EA7, 0x0000, 0x1EA9, 0x0000, 0x1EAB, 0x0000, 0x1EAD, 0x0000, 0x1EAF, 0x0000, 0x1EB1, 0x0000, 0x1EB3, 0x0000, 0x1EB5, 0x0000, 0x1EB7, 0x0000, 0x1EB9, 0x0000, 0x1EBB, 0x0000, 0x1EBD, 0x0000, 0x1EBF, 0x0000, 0x1EC1, 0x0000, 0x1EC3, 0x0000, 0x1EC5, 0x0000, 0x1EC7, 0x0000, 0x1EC9, 0x0000, 0x1ECB, 0x0000, 0x1ECD, 0x0000, 0x1ECF, 0x0000, 0x1ED1, 0x0000, 0x1ED3, 0x0000, 0x1ED5, 0x0000, 0x1ED7, 0x0000, 0x1ED9, 0x0000, 0x1EDB, 0x0000, 0x1EDD, 0x0000, 0x1EDF, 0x0000, 0x1EE1, 0x0000, 0x1EE3, 0x0000, 0x1EE5, 0x0000, 0x1EE7, 0x0000, 0x1EE9, 0x0000, 0x1EEB, 0x0000, 0x1EED, 0x0000, 0x1EEF, 0x0000, 0x1EF1, 0x0000, 0x1EF3, 0x0000, 0x1EF5, 0x0000, 0x1EF7, 0x0000, 0x1EF9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_1F[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x0000, 0x03B9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_21[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03C9, 0x0000, 0x0000, 0x0000, 0x006B, 0x00E5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_24[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, 0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7, 0x24E8, 0x24E9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static kvi_wchar_t case_utl_FF[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; kvi_wchar_t * kvirc_case_map_utl[256] = { case_utl_00, case_utl_01, case_utl_02, case_utl_03, case_utl_04, case_utl_05, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_utl_1E, case_utl_1F, case_xtx_XX, case_utl_21, case_xtx_XX, case_xtx_XX, case_utl_24, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_utl_FF }; // Case mapping tables are 13824 bytes long kvi_wchar_t kvi_wtolower(kvi_wchar_t c) { kvi_wchar_t l = kvirc_case_map_utl[c >> 8][c & 0xff]; return l ? l : c; } bool kvi_hstrEqualCIN(const kvi_wchar_t *str1,const char *str2,int len) { while(len-- && *str1)if(kvi_wtolower(*str1++) != (kvi_wchar_t)tolower(*str2++))return false; return (len < 0); } const kvi_wchar_t * KviIrcView::getTextLine(int iMsgType, const kvi_wchar_t * data_ptr, KviIrcViewLine *line_ptr, bool bEnableTimeStamp) { const kvi_wchar_t* pUnEscapeAt = 0; // 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; register const kvi_wchar_t *p= data_ptr; //Alloc the first attribute line_ptr->uChunkCount = 1; line_ptr->pChunks = (KviIrcViewLineChunk *)kvi_malloc(sizeof(KviIrcViewLineChunk)); //And fill it up line_ptr->pChunks[0].type = KVI_TEXT_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=TQColor(); if(bEnableTimeStamp && KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp)) { TQString szTimestamp; szTimestamp=TQDateTime::currentDateTime ( KVI_OPTION_BOOL(KviOption_boolIrcViewTimestampUTC) ? Qt::UTC : Qt::LocalTime ).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 *)kvi_realloc((void *)line_ptr->pChunks,3 * sizeof(KviIrcViewLineChunk)); line_ptr->pChunks[1].type = KVI_TEXT_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 = KVI_TEXT_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=TQColor(); 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.setLength(iTimeStampLength); iTextIdx = iTimeStampLength; // the rest of the string will begin 11 chars later // throw away const: we WANT to set the chars :D register TQChar * data_ptr_aux = (TQChar *)line_ptr->szText.unicode(); register TQChar * stamp_ptr_aux = (TQChar *)szTimestamp.unicode(); for(int i=0;iszText = ""; 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 :) // #define APPEND_LAST_TEXT_BLOCK(__data_ptr,__data_len) \ blockLen = (__data_len); \ line_ptr->pChunks[iCurChunk].iTextLen += blockLen; \ kvi_appendWCharToTQStringWithLength(&(line_ptr->szText),__data_ptr,__data_len); \ iTextIdx+=blockLen; #define APPEND_LAST_TEXT_BLOCK_HIDDEN_FROM_NOW(__data_ptr,__data_len) \ blockLen = (__data_len); \ kvi_appendWCharToTQStringWithLength(&(line_ptr->szText),__data_ptr,__data_len); \ iTextIdx+=blockLen; #define APPEND_ZERO_LENGTH_BLOCK(__data_ptr) /* does nothing */ #define NEW_LINE_CHUNK(_chunk_type) \ line_ptr->uChunkCount++; \ line_ptr->pChunks=(KviIrcViewLineChunk *)kvi_realloc((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 : TQColor(); // EOF Macros int partLen; #ifdef COMPILE_USE_DYNAMIC_LABELS // Herezy :) // 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 comed 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 // 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 fist version here void * loop_begin; static void * char_to_check_jump_table[256]= { &&found_end_of_buffer ,0 ,&&found_mirc_escape ,&&found_color_escape , 0 ,0 ,0 ,0 , 0 ,0 ,&&found_end_of_line ,0 , 0 ,&&found_command_escape ,0 ,&&found_mirc_escape , 0 ,0 ,0 ,0 , 0 ,0 ,&&found_mirc_escape ,0 , 0 ,0 ,0 ,0 , 0 ,&&found_icon_escape ,0 ,&&found_mirc_escape , // 000-031 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 032-047 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,&&check_emoticon_char ,&&check_emoticon_char , 0 ,&&check_emoticon_char ,0 ,0 , // 048-063 // 61='=' , 59=';' , 58=':' 0 ,0 ,0 ,0 , 0 ,&&check_e2k_url ,&&check_file_or_ftp_url,0 , &&check_http_url ,&&check_irc_url ,0 ,0 , 0 ,&&check_mailto_url ,0 ,0 , // 064-079 // 070==F 072==H 073==I 077==M 0 ,0 ,0 ,0 , 0 ,0 ,0 ,&&check_www_url , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 080-095 // 087==W 0 ,0 ,0 ,0 , 0 ,&&check_e2k_url ,&&check_file_or_ftp_url,0 , &&check_http_url ,&&check_irc_url ,0 ,0 , 0 ,&&check_mailto_url ,0 ,0 , // 096-111 // 101=e 102=f 104=h 105=i 109==m 0 ,0 ,0 ,0 , 0 ,0 ,0 ,&&check_www_url , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 112-127 // 119==w 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 128-133 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 134-159 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 160-175 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 176-191 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 192-207 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 208-223 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , // 224-239 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 , 0 ,0 ,0 ,0 // 240-255 }; if(KVI_OPTION_BOOL(KviOption_boolIrcViewUrlHighlighting)) { loop_begin = &&highlighting_check_loop; // get the address of the return label // forewer 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; // newer here } else { loop_begin = &&escape_check_loop; // get the address of the return label // forever loop escape_check_loop: while(*((unsigned short *)p) > 31)p++; goto check_escape_switch; // returns to escape_check_loop or returns from the function at all // newer here } // newer here #else // !COMPILE_USE_DYNAMIC_LABELS // No way to have a jump table, nor a dynamic return jump // Anyway...we can have sth similar to a jump table... // Note: this could be substituted by a compiler generated jump table // for a switch command... but this is STILL faster static char char_to_check_table[256]= { 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, // 000-015 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, // 016-031 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 032-047 0,0,0,0,0,0,0,0, 0,0,7,7,0,7,0,0, // 048-063 0,0,0,0,0,8,3,0, 2,5,0,0,0,6,0,0, // 064-079 // 070==F 072==H 073==I 077==M 0,0,0,0,0,0,0,4, 0,0,0,0,0,0,0,0, // 080-095 // 087==W 0,0,0,0,0,8,3,0, 2,5,0,0,0,6,0,0, // 096-111 // 102==f 104==h 105==i 109==m 0,0,0,0,0,0,0,4, 0,0,0,0,0,0,0,0, // 112-127 // 119==w 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 128-133 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 134-159 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 160-175 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 176-191 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 192-207 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 208-223 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 224-239 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 // 240-255 }; check_char_loop: if(KVI_OPTION_BOOL(KviOption_boolIrcViewUrlHighlighting)) { for(;;) { if(*((unsigned short *)p) < 0xff) if(unsigned int chk = char_to_check_table[*((unsigned short *)p)]) { switch(chk) { case 1: goto check_escape_switch; break; // returns to check_char_loop or returns from the function at all case 2: goto check_http_url; break; // returns to check_char_loop case 3: goto check_file_or_ftp_url; break; // returns to check_char_loop case 4: goto check_www_url; break; // returns to check_char_loop case 5: goto check_irc_url; break; // returns to check_char_loop case 6: goto check_mailto_url; break; // returns to check_char_loop case 7: goto check_emoticon_char; break; // returns to check_char_loop case 8: goto check_e2k_url; break; } } p++; } } else { while(((unsigned short)*p) > 31)p++; goto check_escape_switch; // returns to check_char_loop } #endif // !COMPILE_USE_DYNAMIC_LABELS check_escape_switch: switch(*p) { case '\0': #ifdef COMPILE_USE_DYNAMIC_LABELS found_end_of_buffer: #endif //COMPILE_USE_DYNAMIC_LABELS APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr) return p; break; case '\n': #ifdef COMPILE_USE_DYNAMIC_LABELS found_end_of_line: #endif //COMPILE_USE_DYNAMIC_LABELS // Found the end of a line APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr) // terminate the string // move the current pointer to the next character... // if it is '\0' we will simply stop p++; return p; break; case '\r': #ifdef COMPILE_USE_DYNAMIC_LABELS found_command_escape: #endif //COMPILE_USE_DYNAMIC_LABELS if (p==pUnEscapeAt) { APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr); NEW_LINE_CHUNK(KVI_TEXT_UNESCAPE); pUnEscapeAt = 0; p++; data_ptr=p; break; } // Command escape sequence // \r!\r\r p++; if(*p == '!') { const kvi_wchar_t * next_cr = p; // lookup the next carriage return while(*next_cr && (*next_cr != '\r'))next_cr++; if(*next_cr) { const kvi_wchar_t * term_cr = next_cr; term_cr++; while(*term_cr && (*term_cr != '\r'))term_cr++; if(*term_cr) { // ok....the format is right: // \r! ... \r ... \r // ^p ^next_cr ^term_cr p--; // \r! ... \r ... \r // ^p ^next_cr ^term_cr APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr) NEW_LINE_CHUNK(KVI_TEXT_ESCAPE) p+=2; //point after \r! blockLen = (next_cr - p); line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc(((next_cr - p) + 1) * sizeof(kvi_wchar_t)); kvi_fastmoveodd((void *)(line_ptr->pChunks[iCurChunk].szPayload),p,blockLen * sizeof(kvi_wchar_t)); line_ptr->pChunks[iCurChunk].szPayload[blockLen] = 0; ++next_cr; //point after the middle \r pUnEscapeAt = term_cr; bool bColorSetted=false; if((line_ptr->pChunks[iCurChunk].szPayload[0]=='n') && KVI_OPTION_BOOL(KviOption_boolUseUserListColorsAsNickColors) && (!KVI_OPTION_BOOL(KviOption_boolColorNicks))) { if(m_pKviWindow->type()==KVI_WINDOW_TYPE_CHANNEL && m_pKviWindow) { if(line_ptr->pChunks[iCurChunk].szPayload[1]=='c' && ((KviChannel*)m_pKviWindow)->userListView()) { KviUserListEntry *e = ((KviChannel*)m_pKviWindow)->userListView()->findEntry(TQString((TQChar*)next_cr,term_cr-next_cr)); if(e) { line_ptr->pChunks[iCurChunk].colors.fore = KVI_COLOR_CUSTOM; e->color(line_ptr->pChunks[iCurChunk].customFore); bColorSetted=true; } } } else if(m_pKviWindow->type()==KVI_WINDOW_TYPE_QUERY && m_pKviWindow && line_ptr->pChunks[iCurChunk].szPayload[1]=='c') { TQString m_szNick = TQString((TQChar*)next_cr,term_cr-next_cr); if(m_szNick==m_pKviWindow->connection()->currentNickName()) { line_ptr->pChunks[iCurChunk].colors.fore = KVI_COLOR_OWN; bColorSetted=true; } } } if(!bColorSetted) { line_ptr->pChunks[iCurChunk].colors.fore=KVI_NOCHANGE; } /*APPEND_LAST_TEXT_BLOCK(next_cr,term_cr - next_cr) NEW_LINE_CHUNK(KVI_TEXT_UNESCAPE)*/ p=next_cr; data_ptr=p; } } } break; case KVI_TEXT_COLOR: #ifdef COMPILE_USE_DYNAMIC_LABELS found_color_escape: #endif //COMPILE_USE_DYNAMIC_LABELS //Color control code...need a new attribute struct APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr) NEW_LINE_CHUNK(*p) p++; p=getColorBytesW(p,&(line_ptr->pChunks[iCurChunk].colors.fore), &(line_ptr->pChunks[iCurChunk].colors.back)); data_ptr=p; break; case KVI_TEXT_ICON: #ifdef COMPILE_USE_DYNAMIC_LABELS found_icon_escape: #endif //COMPILE_USE_DYNAMIC_LABELS p++; if(*p > 32) { // Icon control word... need a new attribute struct const kvi_wchar_t * beginPtr = p - 1; const kvi_wchar_t * icon_name = p; while(*p > 32)p++; int datalen = p - icon_name; kvi_wchar_t save = *p; // throw away constness! *((kvi_wchar_t *)p) = 0; // FIXME: this has to be changed! : lookupTextIcon must use wide characters! TQString tmpQ; tmpQ.setUnicodeCodes(icon_name,datalen); KviTextIcon * icon = g_pTextIconManager->lookupTextIcon(tmpQ); // throw away constness! *((kvi_wchar_t *)p) = save; //if(*p == KVI_TEXT_ICON)p++; // ending delimiter if(icon) { APPEND_LAST_TEXT_BLOCK(data_ptr,beginPtr - data_ptr) NEW_LINE_CHUNK(KVI_TEXT_ICON) line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc((datalen + 1) * sizeof(kvi_wchar_t)); kvi_fastmoveodd((void *)(line_ptr->pChunks[iCurChunk].szPayload),icon_name,datalen * sizeof(kvi_wchar_t)); line_ptr->pChunks[iCurChunk].szPayload[datalen] = 0; line_ptr->pChunks[iCurChunk].szSmileId=line_ptr->pChunks[iCurChunk].szPayload; APPEND_LAST_TEXT_BLOCK_HIDDEN_FROM_NOW(icon_name,datalen) data_ptr = p; NEW_LINE_CHUNK(KVI_TEXT_UNICON) } } break; case KVI_TEXT_BOLD: case KVI_TEXT_UNDERLINE: case KVI_TEXT_REVERSE: case KVI_TEXT_RESET: #ifdef COMPILE_USE_DYNAMIC_LABELS found_mirc_escape: #endif //COMPILE_USE_DYNAMIC_LABELS APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr) NEW_LINE_CHUNK(*p) data_ptr=++p; break; default: p++; break; } #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS check_http_url: p++; if((*p == 't') || (*p == 'T')) { p--; if(kvi_hstrEqualCIN(p,"http://",7)) { partLen = 7; goto got_url; } if(kvi_hstrEqualCIN(p,"https://",8)) { partLen = 8; goto got_url; } p++; } #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS check_file_or_ftp_url: p++; if((*p == 'i') || (*p == 'I')) { p--; if(kvi_hstrEqualCIN(p,"file://",7)) { partLen = 7; goto got_url; } p++; } else if((*p == 't') || (*p == 'T')) { p--; if(kvi_hstrEqualCIN(p,"ftp://",6)) { partLen = 6; goto got_url; } if(kvi_hstrEqualCIN(p,"ftp.",4)) { partLen = 4; goto got_url; } p++; } #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS check_e2k_url: p++; if((*p == 'd') || (*p == 'D')) { p--; if(kvi_hstrEqualCIN(p,"ed2k://",7)) { partLen = 7; goto got_url; } p++; } #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS check_www_url: p++; if((*p == 'w') || (*p == 'W')) { p--; if(kvi_hstrEqualCIN(p,"www.",4)) { partLen = 4; goto got_url; } p++; } #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS check_irc_url: p++; if((*p == 'r') || (*p == 'R')) { p--; if(kvi_hstrEqualCIN(p,"irc://",6)) { partLen = 6; goto got_url; } if(kvi_hstrEqualCIN(p,"irc6://",7)) { partLen = 7; goto got_url; } if(kvi_hstrEqualCIN(p,"ircs://",7)) { partLen = 7; goto got_url; } if(kvi_hstrEqualCIN(p,"ircs6://",8)) { partLen = 8; goto got_url; } p++; } #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS check_mailto_url: p++; if((*p == 'a') || (*p == 'A')) { p--; if(kvi_hstrEqualCIN(p,"mailto:",7)) { partLen = 7; goto got_url; } p++; } #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS got_url: //Url highlighting block if(*(p + partLen) < 47) { p+=partLen; APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr) } else { APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr) NEW_LINE_CHUNK(KVI_TEXT_ESCAPE) // FIXME: #warning "Option for the URL escape...double click and right button!!!" // int urlLen = KVI_OPTION_STRING(KviOption_stringUrlLinkCommand).len() + 1; line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc(2 * sizeof(kvi_wchar_t)); line_ptr->pChunks[iCurChunk].szPayload[0] = 'u'; line_ptr->pChunks[iCurChunk].szPayload[1] = 0x0; line_ptr->pChunks[iCurChunk].colors.fore = KVI_OPTION_MSGTYPE(KVI_OUT_URL).fore(); //and run until the presumed end of the url data_ptr=p; p+=partLen; // Question : What characters are NOT allowed in an URL ? // I assume [] () {} 'and chars below 33 (space too , and negative chars too! (for signed char systems)) // [] and () are used in ed2k links often // These characters are "{", "}", "|", "\", "^", "~", "[", "]", and "`". (RFC1738) while((*p > 32) && (*p != '[') && (*p != '|') && (*p != '{') && (*p != '>') && (*p != ']') && (*p != '}') && (*p != '<') && (*p != '"'))p++; if(m_pKviWindow) { TQString tmp; tmp.setUnicodeCodes(data_ptr,p-data_ptr); KVS_TRIGGER_EVENT_1(KviEvent_OnUrl,m_pKviWindow,tmp); } APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr) NEW_LINE_CHUNK(KVI_TEXT_UNESCAPE) } data_ptr=p; #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS //FIXME #warning: Add more emoticons, and more intelligent code to detect when they're not really emoticons check_emoticon_char: // What about this ? const kvi_wchar_t * begin = p; p++; if(KVI_OPTION_BOOL(KviOption_boolDrawEmoticons)) switch(iMsgType) { case KVI_OUT_CHANPRIVMSG: case KVI_OUT_ACTION: case KVI_OUT_OWNPRIVMSG: case KVI_OUT_QUERYPRIVMSG: case KVI_OUT_QUERYPRIVMSGCRYPTED: case KVI_OUT_QUERYNOTICE: case KVI_OUT_QUERYNOTICECRYPTED: case KVI_OUT_CHANPRIVMSGCRYPTED: case KVI_OUT_CHANNELNOTICE: case KVI_OUT_CHANNELNOTICECRYPTED: case KVI_OUT_OWNPRIVMSGCRYPTED: case KVI_OUT_HIGHLIGHT: case KVI_OUT_DCCCHATMSG: { // Pragma: 31.05.2002 : I had to kill the 8 prefix // It happens really too often to have an 8 followed by a parenthesis // that is not an emoticon // *begin can be one of ':' , ';' , '=' if(*p == '-')p++; // FIXME: we could handle also 'o' as a nose ??? (extreme: also '+' ?) // FIXME: use a "jump-like-check-table" here ? .... it would be surely faster // FIXME: handle also '[',']','\\','p','@','#','<','>','|' ??? switch(*p) { case ')': case '(': case '/': case 'D': case 'P': case 'S': case 'O': case '*': case '|': case 176: // '°' -> alt 176 : teardrop { const kvi_wchar_t * item = p; const kvi_wchar_t * item2 = 0; p++; while(*p == *item)p++; int count = (p - item) - 1; if(*item == 176) { if(*p == ')') { item2 = p; p++; } } if(!*p || (*p == ' ')) { // ok! this is an emoticon (sequence) ! // We lookup simplified versions of the emoticons... // FIXME: this sould become UNICODE!!! TQString lookupstring; kvi_wchar_t ng[3]; ng[0] = *begin; ng[1] = *item; if(item2)ng[2] = *item2; lookupstring.setUnicodeCodes(ng,item2 ? 3 : 2); KviTextIcon * icon = g_pTextIconManager->lookupTextIcon(lookupstring); // do we have that emoticon-icon association ? if(icon) { // we got an icon for this emoticon // the tooltip will carry the original emoticon source text APPEND_LAST_TEXT_BLOCK(data_ptr,begin - data_ptr) NEW_LINE_CHUNK(KVI_TEXT_ICON) int emolen = p - begin; int reallen=item2 ? 3 : 2; line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc((emolen + 1) * sizeof(kvi_wchar_t)); kvi_fastmoveodd(line_ptr->pChunks[iCurChunk].szPayload,begin,emolen * sizeof(kvi_wchar_t)); line_ptr->pChunks[iCurChunk].szPayload[emolen] = 0; line_ptr->pChunks[iCurChunk].szSmileId = (kvi_wchar_t *)kvi_malloc((reallen + 1) * sizeof(kvi_wchar_t)); kvi_fastmoveodd(line_ptr->pChunks[iCurChunk].szSmileId,ng,reallen * sizeof(kvi_wchar_t)); line_ptr->pChunks[iCurChunk].szSmileId[reallen] = 0; APPEND_LAST_TEXT_BLOCK_HIDDEN_FROM_NOW(begin,emolen) data_ptr = p; // let's also handle thingies like :DDDD item++; while(count > 0) { NEW_LINE_CHUNK(KVI_TEXT_ICON) line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc((emolen + 1) * sizeof(kvi_wchar_t)); kvi_fastmoveodd(line_ptr->pChunks[iCurChunk].szPayload,begin,emolen * sizeof(kvi_wchar_t)); line_ptr->pChunks[iCurChunk].szPayload[emolen] = 0; line_ptr->pChunks[iCurChunk].szSmileId = (kvi_wchar_t *)kvi_malloc((reallen + 1) * sizeof(kvi_wchar_t)); kvi_fastmoveodd(line_ptr->pChunks[iCurChunk].szSmileId,ng,reallen * sizeof(kvi_wchar_t)); line_ptr->pChunks[iCurChunk].szSmileId[reallen] = 0; APPEND_ZERO_LENGTH_BLOCK(data_ptr) count--; } NEW_LINE_CHUNK(KVI_TEXT_UNICON) } // we don't even need to skip back... the text eventually parsed is ok to be in a single block for sure } // we don't even need to skip back... the text eventually parsed is ok to be in a single block for sure } // we don't even need to skip back... the text eventually parsed is ok to be in a single block for sure break; } // switch(*p) } break; } #ifdef COMPILE_USE_DYNAMIC_LABELS goto *loop_begin; #else // !COMPILE_USE_DYNAMIC_LABELS goto check_char_loop; #endif // !COMPILE_USE_DYNAMIC_LABELS // never here return p; } void KviIrcView::fastScroll(int lines) { m_iUnprocessedPaintEventRequests = 0; if(!isVisible())return; if(!m_pFm) { // We must get the metrics from a real paint event :/ // must do a full repaint to get them... repaint(); return; } // Ok...the current line is the last one here // It is the only one that needs to be repainted int widgetWidth = width()-m_pScrollBar->width(); if(widgetWidth < KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH+10)return; //can't show stuff here int widgetHeight = height(); int maxLineWidth = widgetWidth; int defLeftCoord=KVI_IRCVIEW_HORIZONTAL_BORDER; if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages)) { maxLineWidth -= KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH; defLeftCoord+=KVI_IRCVIEW_PIXMAP_AND_SEPARATOR; } int heightToPaint = 1; KviIrcViewLine * l = m_pCurLine; while(lines > 0) { if(l) { if(maxLineWidth != l->iMaxLineWidth)calculateLineWraps(l,maxLineWidth); heightToPaint += l->uLineWraps * m_iFontLineSpacing; heightToPaint += (m_iFontLineSpacing + m_iFontDescent); lines--; l = l->pPrev; } else lines = 0; } #ifdef COMPILE_USE_QT4 scroll(0,-(heightToPaint-1),TQRect(1,1,widgetWidth-2,widgetHeight-2)); #else bitBlt(this,1,1,this,1,heightToPaint,widgetWidth -2,widgetHeight - (heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER)); TQRect r(0,widgetHeight - (heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER), widgetWidth,heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER); TQPaintEvent * e = new TQPaintEvent(r); paintEvent(e); delete e; #endif if(m_iLastLinkRectHeight > -1) { // need to kill the last highlighted link m_iLastLinkRectTop -= heightToPaint; if(m_iLastLinkRectTop < 0) { m_iLastLinkRectHeight += m_iLastLinkRectTop; m_iLastLinkRectTop = 0; } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // The IrcView : THE paint event // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void KviIrcView::paintEvent(TQPaintEvent *p) { // // THIS FUNCTION IS A MONSTER // int scrollbarWidth = m_pScrollBar->width(); int widgetWidth = width() - scrollbarWidth; if(!isVisible() || (widgetWidth < 20)) { m_iUnprocessedPaintEventRequests = 0; // assume a full repaint when this widget is shown... return; //can't show stuff here } // if the mdiManager is in SDI mode // and this window is attacched but is not the toplevel one // then it is hidden completely behind the other windows // and we can avoid to paint it :) if(g_pFrame->mdiManager()->isInSDIMode() && (m_pKviWindow->mdiParent() != g_pFrame->mdiManager()->topChild()) && (m_pKviWindow->mdiParent())) { m_iUnprocessedPaintEventRequests = 0; // assume a full repaint when this widget is shown... return; // totally hidden behind other windows } int widgetHeight = height(); static TQRect r; // static: avoid calling constructor and destructor every time... if(p) { r=p->rect(); // app triggered , or self triggered from fastScroll (in that case m_iUnprocessedPaintEventRequests is set to 0 there) if(r == rect()) m_iUnprocessedPaintEventRequests = 0; // only full repaints reset } else { // A self triggered event m_iUnprocessedPaintEventRequests = 0; // only full repaints reset r = rect(); } int rectLeft = r.x(); int rectTop = r.y(); int rectHeight = r.height(); int rectBottom = rectTop + rectHeight; int rectWidth = r.width(); if(rectWidth > widgetWidth)rectWidth = widgetWidth; #ifdef COMPILE_USE_QT4 TQPainter pa(this); // we use qt4 double buffering #else KviDoubleBuffer doublebuffer(width(),height()); TQPixmap * pDoubleBufferPixmap = doublebuffer.pixmap(); TQPainter pa(pDoubleBufferPixmap); #endif SET_ANTI_ALIASING(pa); pa.setFont(font()); if(!m_pFm) { // note that TQFontMetrics(pa.font()) may be not the same as TQFontMetrics(font()) // because the painter might effectively use an approximation of the TQFont specified // by font(). recalcFontVariables(TQFontMetrics(pa.font()),pa.fontInfo()); } #ifdef COMPILE_PSEUDO_TRANSPARENCY if(g_pShadedChildGlobalDesktopBackground) { TQPoint pnt = mapToGlobal(TQPoint(rectLeft,rectTop)); pa.drawTiledPixmap(rectLeft,rectTop,rectWidth,rectHeight,*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y()); } else { #endif TQPixmap * pix = m_pPrivateBackgroundPixmap; if(!pix) pix = KVI_OPTION_PIXMAP(KviOption_pixmapIrcViewBackground).pixmap(); pa.fillRect(rectLeft,rectTop,rectWidth,rectHeight,KVI_OPTION_COLOR(KviOption_colorIrcViewBackground)); if(pix) KviPixmapUtils::drawPixmapWithPainter(&pa,pix,KVI_OPTION_UINT(KviOption_uintIrcViewPixmapAlign),r,widgetWidth,widgetHeight); #ifdef COMPILE_PSEUDO_TRANSPARENCY } #endif //Have lines visible int curBottomCoord = widgetHeight - KVI_IRCVIEW_VERTICAL_BORDER; int maxLineWidth = widgetWidth; int defLeftCoord = KVI_IRCVIEW_HORIZONTAL_BORDER; int lineWrapsHeight; if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages)) { maxLineWidth -= KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH; defLeftCoord += KVI_IRCVIEW_PIXMAP_AND_SEPARATOR; } KviIrcViewLine *pCurTextLine = m_pCurLine; if(m_bMouseIsDown) { m_szLastSelectionLine = ""; m_szLastSelection = ""; } //Make sure that we have enough space to paint something... if(maxLineWidth < m_iMinimumPaintWidth)pCurTextLine=0; bool bLineMarkPainted = !KVI_OPTION_BOOL(KviOption_boolTrackLastReadTextViewLine); //And loop thru lines until we not run over the upper bound of the view while((curBottomCoord >= KVI_IRCVIEW_VERTICAL_BORDER) && pCurTextLine) { //Paint pCurTextLine if(maxLineWidth != pCurTextLine->iMaxLineWidth) { // Width of the widget or the font has been changed // from the last time that this line was painted calculateLineWraps(pCurTextLine,maxLineWidth); } // the evil multiplication // in an i486 it can get up to 42 clock cycles lineWrapsHeight = (pCurTextLine->uLineWraps) * m_iFontLineSpacing; curBottomCoord -= lineWrapsHeight; if((curBottomCoord - m_iFontLineSpacing) > rectBottom) { // not in update rect... skip curBottomCoord -= (m_iFontLineSpacing + m_iFontDescent); pCurTextLine = pCurTextLine->pPrev; continue; } if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages)) { //Paint the pixmap first //Calculate the position of the image //imageYPos = curBottomCoord - (pixmapHeight(16) + ((m_iFontLineSpacing - 16)/2) ); int imageYPos = curBottomCoord - m_iRelativePixmapY; //Set the mask if needed int iPixId = KVI_OPTION_MSGTYPE(pCurTextLine->iMsgType).pixId(); if(iPixId > 0) pa.drawPixmap(KVI_IRCVIEW_HORIZONTAL_BORDER,imageYPos,*(g_pIconManager->getSmallIcon(iPixId))); } if(m_pToolWidget) { if(!m_pToolWidget->messageEnabled(pCurTextLine->iMsgType)) { // not in update rect... skip curBottomCoord -= (m_iFontLineSpacing + m_iFontDescent); pCurTextLine = pCurTextLine->pPrev; continue; } } // Initialize for drawing this line of text // The first block is always an attribute block char defaultBack = pCurTextLine->pBlocks->pChunk->colors.back; char defaultFore = pCurTextLine->pBlocks->pChunk->colors.fore; bool curBold = false; bool curUnderline = false; char foreBeforeEscape= KVI_BLACK; bool curLink = false; bool bacWasTransp = false; char curFore = defaultFore; char curBack = defaultBack; int curLeftCoord = defLeftCoord; curBottomCoord -= m_iFontDescent; //rise up the text... // // Single text line loop (paint all text blocks) // (May correspond to more physical lines on the display if the text is wrapped) // for(int i=0;i < pCurTextLine->iBlockCount;i++) { register KviIrcViewWrappedBlock * block = &(pCurTextLine->pBlocks[i]); // Play with the attributes if(block->pChunk) { //normal block switch(block->pChunk->type) { case KVI_TEXT_COLOR: if(block->pChunk->colors.fore != KVI_NOCHANGE) { curFore = block->pChunk->colors.fore; if(block->pChunk->colors.back != KVI_NOCHANGE) curBack = block->pChunk->colors.back; } else { // only a CTRL+K... reset curFore = defaultFore; curBack = defaultBack; } // Begin Edit by GMC-jimmy: Added // When KVIrc encounters a CTRL+K code without any trailing numbers, we then use KVIrc's default color value // defined by the user in the Options dialog. // This is to allow KVIrc to handle mIRC color codes in a similar fashion to most other modern irc clients. // See also kvi_input.cpp // Pragma: optimized: moved the code above (avoided duplicate if()) // Pragma(05.03.2003): fixed again: reset ONLY if CTRL+K without numbers // otherwise leave the background unchanged //if(block->pChunk->colors.fore == KVI_NOCHANGE) // curFore = defaultFore; //if(block->pChunk->colors.back == KVI_NOCHANGE) // curBack = defaultBack; // End Edit break; case KVI_TEXT_ESCAPE: foreBeforeEscape = curFore; if(block->pChunk->colors.fore != KVI_NOCHANGE) curFore = block->pChunk->colors.fore; if(m_pLastLinkUnderMouse == block)curLink = true; break; case KVI_TEXT_UNESCAPE: curLink = false; curFore = foreBeforeEscape; break; case KVI_TEXT_BOLD: curBold = !curBold; break; case KVI_TEXT_UNDERLINE: curUnderline = !curUnderline; break; case KVI_TEXT_RESET: curBold = false; curUnderline = false; curFore = defaultFore; curBack = defaultBack; break; case KVI_TEXT_REVERSE: //Huh ? char aux = curBack; if(bacWasTransp == true) { curBack = KVI_TRANSPARENT; } else { curBack = curFore; } if(aux == KVI_TRANSPARENT) { curFore = (char)KVI_DEF_BACK; } else { curFore = aux; } bacWasTransp = (aux == KVI_TRANSPARENT); /* if(curBack != KVI_TRANSPARENT) { char aux =curFore; curFore = curBack; curBack = aux; } else { curBack = curFore; switch(curBack) { case KVI_WHITE: case KVI_ORANGE: case KVI_YELLOW: case KVI_LIGHTGREEN: case KVI_BLUEMARINE: case KVI_LIGHTBLUE: case KVI_LIGHTVIOLET: case KVI_LIGHTGRAY: curFore=KVI_BLACK; break; default: //transparent too curFore=KVI_LIGHTGREEN; break; } } */ break; //case KVI_TEXT_ICON: //case KVI_TEXT_UNICON: // does nothing //debug("Have a block with ICON/UNICON attr"); //break; } } else { // no attributes , it is a line wrap curLeftCoord = defLeftCoord; if(KVI_OPTION_BOOL(KviOption_boolIrcViewWrapMargin))curLeftCoord+=m_iWrapMargin; curBottomCoord += m_iFontLineSpacing; } // // Here we run really out of bounds :))))) // A couple of macros that could work well as functions... // but since there are really many params to be passed // and push & pop calls take clock cycles // my paranoic mind decided to go for the macro way. // This is NOT good programming // #define SET_PEN(_color,_custom)\ if( ((unsigned char)_color) < 16 )\ {\ pa.setPen(KVI_OPTION_MIRCCOLOR((unsigned char)_color));\ } else {\ switch((unsigned char)_color)\ {\ case KVI_COLOR_EXT_USER_OP:\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewOpForeground));\ break;\ case KVI_COLOR_EXT_USER_HALFOP:\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewHalfOpForeground));\ break;\ case KVI_COLOR_EXT_USER_ADMIN:\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewChanAdminForeground));\ break;\ case KVI_COLOR_EXT_USER_OWNER:\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewChanOwnerForeground));\ break;\ case KVI_COLOR_EXT_USER_VOICE:\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewVoiceForeground));\ break;\ case KVI_COLOR_EXT_USER_USEROP:\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewUserOpForeground));\ break;\ case KVI_COLOR_EXT_USER_NORMAL:\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewNormalForeground));\ break;\ case KVI_DEF_BACK :\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));\ break;\ case KVI_COLOR_CUSTOM :\ pa.setPen(_custom);\ break;\ case KVI_COLOR_OWN :\ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewOwnForeground));\ break;\ }\ } #define DRAW_SELECTED_TEXT(_text_str,_text_idx,_text_len,_text_width) \ SET_PEN(KVI_OPTION_MSGTYPE(KVI_OUT_SELECT).fore(),block->pChunk ? block->pChunk->customFore : TQColor()); \ { \ int theWdth = _text_width; \ if(theWdth < 0) \ theWdth=width()-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER+scrollbarWidth); \ pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,theWdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_SELECT).back())); \ } \ pa.drawText(curLeftCoord,curBottomCoord,_text_str,_text_idx,_text_len); \ m_szLastSelectionLine.append(_text_str.mid(_text_idx,_text_len)); \ curLeftCoord += _text_width; #define DRAW_NORMAL_TEXT(_text_str,_text_idx,_text_len,_text_width) \ SET_PEN(curFore,block->pChunk ? block->pChunk->customFore : TQColor()); \ if(curBack != KVI_TRANSPARENT){ \ int theWdth = _text_width; \ if(theWdth < 0) \ theWdth=width()-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER+scrollbarWidth); \ pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,theWdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR((unsigned char)curBack)); \ } \ pa.drawText(curLeftCoord,curBottomCoord,_text_str,_text_idx,_text_len); \ if(curBold)pa.drawText(curLeftCoord+1,curBottomCoord,_text_str,_text_idx,_text_len); \ if(curUnderline){ \ int theWdth = _text_width; \ if(theWdth < 0) \ theWdth=width()-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER+scrollbarWidth); \ pa.drawLine(curLeftCoord,curBottomCoord+2,curLeftCoord+theWdth,curBottomCoord+2); \ } \ curLeftCoord += _text_width; // EOF macro declarations if(m_bMouseIsDown) { //Check if the block or a part of it is selected if(checkSelectionBlock(pCurTextLine,curLeftCoord,curBottomCoord,i)) { //Selected in some way //__range_valid(g_pOptions->m_cViewOutSeleFore != KVI_TRANSPARENT); //__range_valid(g_pOptions->m_cViewOutSeleBack != KVI_TRANSPARENT); if(m_bShiftPressed && i && block->pChunk && ((m_pWrappedBlockSelectionInfo->selection_type == KVI_IRCVIEW_BLOCK_SELECTION_TOTAL) || (m_pWrappedBlockSelectionInfo->selection_type == KVI_IRCVIEW_BLOCK_SELECTION_LEFT)) ) { switch(block->pChunk->type) { case KVI_TEXT_BOLD: case KVI_TEXT_UNDERLINE: case KVI_TEXT_REVERSE: case KVI_TEXT_RESET: m_szLastSelectionLine.append(TQChar(block->pChunk->type)); break; case KVI_TEXT_COLOR: m_szLastSelectionLine.append(TQChar(block->pChunk->type)); if((block->pChunk->colors.fore != KVI_NOCHANGE) && (block->pChunk->colors.fore != KVI_TRANSPARENT)) { if(curFore > 9)m_szLastSelectionLine.append(TQChar('1')); m_szLastSelectionLine.append(TQChar((curFore%10)+'0')); } if((block->pChunk->colors.back != KVI_NOCHANGE) && (block->pChunk->colors.back != KVI_TRANSPARENT) ) { m_szLastSelectionLine.append(TQChar(',')); if(curBack > 9)m_szLastSelectionLine.append(TQChar('1')); m_szLastSelectionLine.append(TQChar((curBack%10)+'0')); } break; } } switch(m_pWrappedBlockSelectionInfo->selection_type) { case KVI_IRCVIEW_BLOCK_SELECTION_TOTAL: DRAW_SELECTED_TEXT(pCurTextLine->szText,block->block_start, block->block_len,block->block_width) break; case KVI_IRCVIEW_BLOCK_SELECTION_LEFT: DRAW_SELECTED_TEXT(pCurTextLine->szText,block->block_start, m_pWrappedBlockSelectionInfo->part_1_length, m_pWrappedBlockSelectionInfo->part_1_width) DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start+m_pWrappedBlockSelectionInfo->part_1_length, m_pWrappedBlockSelectionInfo->part_2_length, m_pWrappedBlockSelectionInfo->part_2_width) break; case KVI_IRCVIEW_BLOCK_SELECTION_RIGHT: DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start, m_pWrappedBlockSelectionInfo->part_1_length, m_pWrappedBlockSelectionInfo->part_1_width) DRAW_SELECTED_TEXT(pCurTextLine->szText,block->block_start+m_pWrappedBlockSelectionInfo->part_1_length, m_pWrappedBlockSelectionInfo->part_2_length, m_pWrappedBlockSelectionInfo->part_2_width) break; case KVI_IRCVIEW_BLOCK_SELECTION_CENTRAL: DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start, m_pWrappedBlockSelectionInfo->part_1_length, m_pWrappedBlockSelectionInfo->part_1_width) DRAW_SELECTED_TEXT(pCurTextLine->szText,block->block_start+m_pWrappedBlockSelectionInfo->part_1_length, m_pWrappedBlockSelectionInfo->part_2_length, m_pWrappedBlockSelectionInfo->part_2_width) DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start+m_pWrappedBlockSelectionInfo->part_1_length+m_pWrappedBlockSelectionInfo->part_2_length, m_pWrappedBlockSelectionInfo->part_3_length, m_pWrappedBlockSelectionInfo->part_3_width) break; case KVI_IRCVIEW_BLOCK_SELECTION_ICON: { int theWdth = block->block_width; if(theWdth < 0)theWdth=width()-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER+scrollbarWidth); pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,theWdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_SELECT).back())); kvi_wslen_t the_len = kvi_wstrlen(block->pChunk->szPayload); m_szLastSelectionLine.append(TQChar(block->pChunk->type)); TQString tmp; tmp.setUnicodeCodes(block->pChunk->szPayload,the_len); m_szLastSelectionLine.append(tmp); goto no_selection_paint; } break; } } else { if(block->pChunk && block->pChunk->type == KVI_TEXT_ICON)goto no_selection_paint; int wdth = block->block_width; if(wdth == 0) { // Last block before a word wrap , or a zero characters attribute block ? if(i < (pCurTextLine->iBlockCount - 1)) { // There is another block... // Check if it is a wrap... if(pCurTextLine->pBlocks[i+1].pChunk == 0)wdth = widgetWidth-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER); // else simply a zero characters block } // else simply a zero characters block } DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start,block->block_len,wdth) } } else { //No selection ...go fast! no_selection_paint: if(block->pChunk && block->pChunk->type == KVI_TEXT_ICON) { int wdth = block->block_width; if(wdth < 0)wdth = widgetWidth - (curLeftCoord + KVI_IRCVIEW_HORIZONTAL_BORDER); int imageYPos = curBottomCoord - m_iRelativePixmapY; //Set the mask if needed if(curBack != KVI_TRANSPARENT && curBack < 16) { pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,wdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR((unsigned char)curBack)); } TQString tmpQ; tmpQ.setUnicodeCodes(block->pChunk->szSmileId,kvi_wstrlen(block->pChunk->szSmileId)); TQPixmap * daIcon =0; KviTextIcon* pIcon = g_pTextIconManager->lookupTextIcon(tmpQ); if(pIcon) { daIcon = pIcon->pixmap(); } if(!daIcon) { // this should never happen since we do a check // when building the text icon block , but.. better safe than sorry: // so... we lost some icons ? wrong associations ? // recover it by displaying the "question mark" icon daIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_HELP); // must be there, eventually null pixmap :D } int moredown = 1; //used to center imager vertically (pixels which the image is moved more down) moredown += ((m_iFontLineSpacing - daIcon->height()) / 2); pa.drawPixmap(curLeftCoord + m_iIconSideSpacing,imageYPos + moredown,*(daIcon)); //debug("SHifting by %d",block->block_width); curLeftCoord += block->block_width; } else { int wdth = block->block_width; if(wdth < 0)wdth = widgetWidth - (curLeftCoord + KVI_IRCVIEW_HORIZONTAL_BORDER); // FIXME: We could avoid this XSetForeground if the curFore was not changed.... SET_PEN(curFore,block->pChunk ? block->pChunk->customFore : TQColor()); if(curBack != KVI_TRANSPARENT && curBack < 16 ) { pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,wdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR((unsigned char)curBack)); } if(curLink) { SET_PEN(KVI_OPTION_MSGTYPE(KVI_OUT_LINK).fore(),block->pChunk ? block->pChunk->customFore : TQColor()); pa.drawText(curLeftCoord,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len); pa.drawText(curLeftCoord+1,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len); pa.drawLine(curLeftCoord,curBottomCoord+2,curLeftCoord+wdth,curBottomCoord+2); } else if(curBold) { //Draw doubled font (simulate bold) pa.drawText(curLeftCoord,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len); pa.drawText(curLeftCoord + 1,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len); } else { pa.drawText(curLeftCoord,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len); } if(curUnderline) { //Draw a line under the text block.... pa.drawLine(curLeftCoord,curBottomCoord+2,curLeftCoord+wdth,curBottomCoord+2); } curLeftCoord += block->block_width; } } } if(pCurTextLine == m_pCursorLine) { // paint the cursor line int iH = lineWrapsHeight + m_iFontLineSpacing; #ifdef COMPILE_USE_QT4 pa.setCompositionMode(TQPainter::CompositionMode_SourceOut); #else pa.setRasterOp(NotROP); #endif pa.fillRect(0,curBottomCoord - iH,widgetWidth,iH + (m_iFontDescent << 1),TQt::black); #ifdef COMPILE_USE_QT4 pa.setCompositionMode(TQPainter::CompositionMode_SourceOver); #else pa.setRasterOp(CopyROP); #endif } if(m_bMouseIsDown) { if(!m_szLastSelectionLine.isEmpty()) { if(!m_szLastSelection.isEmpty())m_szLastSelection.prepend("\n"); m_szLastSelection.prepend(m_szLastSelectionLine); m_szLastSelectionLine = ""; } } curBottomCoord -= (lineWrapsHeight + m_iFontLineSpacing); if(pCurTextLine->uIndex == m_uLineMarkLineIndex) { if((curBottomCoord >= KVI_IRCVIEW_VERTICAL_BORDER) && !bLineMarkPainted) { // visible! bLineMarkPainted = true; //pa.setRasterOp(NotROP); #ifdef COMPILE_USE_QT4 pa.setPen(TQPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,TQt::DotLine)); #else pa.setPen(TQPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,TQPen::DotLine)); #endif pa.drawLine(0,curBottomCoord,widgetWidth,curBottomCoord); //pa.setRasterOp(CopyROP); } // else was partially visible only } pCurTextLine = pCurTextLine->pPrev; } if(!bLineMarkPainted && pCurTextLine && (rectTop <= (KVI_IRCVIEW_VERTICAL_BORDER + 5))) { // the line mark hasn't been painted yet // need to find out if the mark is above the display // the mark might be somewhere before the current text line // find the first line that can't be painted in the view at all while((curBottomCoord >= KVI_IRCVIEW_VERTICAL_BORDER) && pCurTextLine) { // the line wraps for the visible lines MUST have been already calculated // for this view width lineWrapsHeight = (pCurTextLine->uLineWraps) * m_iFontLineSpacing; curBottomCoord -= lineWrapsHeight + m_iFontLineSpacing + m_iFontDescent; pCurTextLine = pCurTextLine->pPrev; } if(pCurTextLine) { // this is the first NOT visible // so pCurTextLine->pNext is the last visible one if(pCurTextLine->pNext) { if(pCurTextLine->pNext->uIndex >= m_uLineMarkLineIndex) bLineMarkPainted = true; // yes, its somewhere before or on this line } else { // no next line ? hm... compare to the not visible one.. but this should never happen if(pCurTextLine->uIndex >= m_uLineMarkLineIndex) bLineMarkPainted = true; // yes, its somewhere before or on this line } if(bLineMarkPainted) { // need to mark it! //pa.setRasterOp(NotROP); //pa.setPen(TQt::black); #ifdef COMPILE_USE_QT4 pa.setPen(TQPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,TQt::DotLine)); #else pa.setPen(TQPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,TQPen::DotLine)); #endif int x = widgetWidth - 8; int y = KVI_IRCVIEW_VERTICAL_BORDER; pa.drawLine(x,y,x,y); y++; pa.drawLine(x-1,y,x+1,y); y++; pa.drawLine(x-2,y,x+2,y); y++; pa.drawLine(x-3,y,x+3,y); y++; pa.drawLine(x-4,y,x+4,y); //pa.setRasterOp(CopyROP); } } } //Need to draw the sunken rect around the view now... pa.setPen(colorGroup().dark()); pa.drawLine(0,0,widgetWidth,0); pa.drawLine(0,0,0,widgetHeight); pa.setPen(colorGroup().light()); widgetWidth--; pa.drawLine(1,widgetHeight-1,widgetWidth,widgetHeight-1); pa.drawLine(widgetWidth,1,widgetWidth,widgetHeight); // COPY TO THE DISPLAY #ifndef COMPILE_USE_QT4 bitBlt(this,rectLeft,rectTop,pDoubleBufferPixmap,rectLeft,rectTop,rectWidth,rectHeight,TQt::CopyROP); #endif // else we use the TQt4 native double buffering } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // The IrcView : calculate line wraps // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define IRCVIEW_WCHARWIDTH(__c) (((__c).unicode() < 0xff) ? m_iFontCharacterWidth[(__c).unicode()] : m_pFm->width(__c)) void KviIrcView::calculateLineWraps(KviIrcViewLine *ptr,int maxWidth) { // // Another monster // if(maxWidth<=0) return; if(ptr->iBlockCount != 0)kvi_free(ptr->pBlocks); // free any previous wrap blocks ptr->pBlocks = (KviIrcViewWrappedBlock *)kvi_malloc(sizeof(KviIrcViewWrappedBlock)); // alloc one block ptr->iMaxLineWidth = maxWidth; // calculus for this width ptr->iBlockCount = 0; // it will be ++ ptr->uLineWraps = 0; // no line wraps yet unsigned int curAttrBlock = 0; // Current attribute block int curLineWidth = 0; // init the first block ptr->pBlocks->block_start = 0; ptr->pBlocks->block_len = 0; ptr->pBlocks->block_width = 0; ptr->pBlocks->pChunk = &(ptr->pChunks[0]); // always an attribute block int maxBlockLen = ptr->pChunks->iTextLen; // ptr->pChunks[0].iTextLen const TQChar * unicode = ptr->szText.unicode(); for(;;) { //Calculate the block_width register const TQChar * p = unicode + ptr->pBlocks[ptr->iBlockCount].block_start; int curBlockLen = 0; int curBlockWidth = 0; if(ptr->pChunks[curAttrBlock].type == KVI_TEXT_ICON) { curBlockWidth = m_iIconWidth; } else { while(curBlockLen < maxBlockLen) { // FIXME: this is ugly :/ curBlockWidth += IRCVIEW_WCHARWIDTH(*p); curBlockLen++; p++; } } //Check the length curLineWidth += curBlockWidth; if(curLineWidth < maxWidth) { //debug("Block of %d pix and len %d with type %d",ptr->pBlocks[ptr->iBlockCount].block_width,ptr->pBlocks[ptr->iBlockCount].block_len,ptr->pChunks[curAttrBlock].type); //Ok....proceed to next block ptr->pBlocks[ptr->iBlockCount].block_len = curBlockLen; ptr->pBlocks[ptr->iBlockCount].block_width = curBlockWidth; curAttrBlock++; ptr->iBlockCount++; //Process the next block of data in the next loop or return if have no more blocks if(curAttrBlock < ptr->uChunkCount) { ptr->pBlocks = (KviIrcViewWrappedBlock *)kvi_realloc(ptr->pBlocks,(ptr->iBlockCount + 1) * sizeof(KviIrcViewWrappedBlock)); ptr->pBlocks[ptr->iBlockCount].block_start = ptr->pChunks[curAttrBlock].iTextStart; ptr->pBlocks[ptr->iBlockCount].block_len = 0; ptr->pBlocks[ptr->iBlockCount].block_width = 0; ptr->pBlocks[ptr->iBlockCount].pChunk = &(ptr->pChunks[curAttrBlock]); maxBlockLen = ptr->pBlocks[ptr->iBlockCount].pChunk->iTextLen; } else return; } else { //Need word wrap //First go back to an admissible width while((curLineWidth >= maxWidth) && curBlockLen) { p--; curBlockLen--; curLineWidth-=IRCVIEW_WCHARWIDTH(*p); } //Now look for a space while((*p != ' ') && curBlockLen) { p--; curBlockLen--; curLineWidth-=IRCVIEW_WCHARWIDTH(*p); } //If we ran up to the beginning of the block.... if(curBlockLen == 0) { if(ptr->pChunks[curAttrBlock].type == KVI_TEXT_ICON) { // This is an icon block: needs to be wrapped differently: // The wrap block goes BEFORE the icon itself ptr->pBlocks[ptr->iBlockCount].pChunk = 0; ptr->pBlocks[ptr->iBlockCount].block_width = 0; ptr->iBlockCount++; ptr->pBlocks = (KviIrcViewWrappedBlock *)kvi_realloc(ptr->pBlocks,(ptr->iBlockCount + 1) * sizeof(KviIrcViewWrappedBlock)); ptr->pBlocks[ptr->iBlockCount].block_start = p - unicode; ptr->pBlocks[ptr->iBlockCount].block_len = 0; ptr->pBlocks[ptr->iBlockCount].block_width = 0; ptr->pBlocks[ptr->iBlockCount].pChunk = &(ptr->pChunks[curAttrBlock]); goto wrap_line; } //Don't like it....forced wrap here... //Go ahead up to the biggest possible string if(maxBlockLen > 0) { do { curBlockLen++; p++; curLineWidth+=IRCVIEW_WCHARWIDTH(*p); } while((curLineWidth < maxWidth) && (curBlockLen < maxBlockLen)); //Now overrunned , go back 1 char p--; curBlockLen--; } //K...wrap } else { //found a space... //include it in the first block p++; curBlockLen++; } ptr->pBlocks[ptr->iBlockCount].block_len = curBlockLen; ptr->pBlocks[ptr->iBlockCount].block_width = -1; // word wrap --> negative block_width maxBlockLen-=curBlockLen; ptr->iBlockCount++; ptr->pBlocks = (KviIrcViewWrappedBlock *)kvi_realloc(ptr->pBlocks,(ptr->iBlockCount + 1) * sizeof(KviIrcViewWrappedBlock)); ptr->pBlocks[ptr->iBlockCount].block_start = p - unicode; ptr->pBlocks[ptr->iBlockCount].block_len = 0; ptr->pBlocks[ptr->iBlockCount].block_width = 0; ptr->pBlocks[ptr->iBlockCount].pChunk = 0; wrap_line: curLineWidth = 0; ptr->uLineWraps++; if(ptr->uLineWraps == 1) { if(KVI_OPTION_BOOL(KviOption_boolIrcViewWrapMargin))maxWidth-=m_iWrapMargin; if(maxWidth<=0) return; } } } ptr->iBlockCount++; } //================= calculateSelectionBounds ==================// void KviIrcView::calculateSelectionBounds() { if(m_mousePressPos.y() < m_mouseCurrentPos.y()) { m_iSelectionTop = m_mousePressPos.y(); m_iSelectionBottom = m_mouseCurrentPos.y(); m_iSelectionBegin = m_mousePressPos.x(); m_iSelectionEnd = m_mouseCurrentPos.x(); } else { m_iSelectionTop = m_mouseCurrentPos.y(); m_iSelectionBottom = m_mousePressPos.y(); m_iSelectionBegin = m_mouseCurrentPos.x(); m_iSelectionEnd = m_mousePressPos.x(); } if(m_iSelectionBegin < m_iSelectionEnd) { m_iSelectionLeft = m_iSelectionBegin; m_iSelectionRight = m_iSelectionEnd; } else { m_iSelectionLeft = m_iSelectionEnd; m_iSelectionRight = m_iSelectionBegin; } } //=============== checkSelectionBlock ===============// bool KviIrcView::checkSelectionBlock(KviIrcViewLine * line,int left,int bottom,int bufIndex) { // // Yahoo!!!! // const TQChar * unicode = line->szText.unicode(); register const TQChar * p = unicode + line->pBlocks[bufIndex].block_start; int top = bottom-m_iFontLineSpacing; int right = ((line->pBlocks[bufIndex].block_width >= 0) ? \ left+line->pBlocks[bufIndex].block_width : width()-(KVI_IRCVIEW_HORIZONTAL_BORDER + m_pScrollBar->width())); if(bottom < m_iSelectionTop)return false; //The selection starts under this line if(top > m_iSelectionBottom)return false; //The selection ends over this line if((top >= m_iSelectionTop)&&(bottom < m_iSelectionBottom)) { //Whole line selected if(line->pBlocks[bufIndex].pChunk && line->pBlocks[bufIndex].pChunk->type == KVI_TEXT_ICON) m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_ICON; else m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_TOTAL; return true; } if((top < m_iSelectionTop) && (bottom >= m_iSelectionBottom)) { //Selection begins and ends in this line if(right < m_iSelectionLeft)return false; if(left > m_iSelectionRight)return false; if(line->pBlocks[bufIndex].pChunk && line->pBlocks[bufIndex].pChunk->type == KVI_TEXT_ICON) { m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_ICON; return true; } if((right <= m_iSelectionRight) && (left > m_iSelectionLeft)) { //Whole line selected m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_TOTAL; return true; } if((right > m_iSelectionRight) && (left <= m_iSelectionLeft)) { //Selection ends and begins in THIS BLOCK! m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_CENTRAL; m_pWrappedBlockSelectionInfo->part_1_length = 0; m_pWrappedBlockSelectionInfo->part_1_width = 0; while((left <= m_iSelectionLeft) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len)){ int www = IRCVIEW_WCHARWIDTH(*p); left += www; m_pWrappedBlockSelectionInfo->part_1_width += www; p++; m_pWrappedBlockSelectionInfo->part_1_length++; } //Need to include the first character if(m_pWrappedBlockSelectionInfo->part_1_length > 0) { m_pWrappedBlockSelectionInfo->part_1_length--; p--; int www = IRCVIEW_WCHARWIDTH(*p); left -= www; m_pWrappedBlockSelectionInfo->part_1_width -= www; } int maxLenNow = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length; int maxWidthNow = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width; m_pWrappedBlockSelectionInfo->part_2_length = 0; m_pWrappedBlockSelectionInfo->part_2_width = 0; while((left < m_iSelectionRight) && (m_pWrappedBlockSelectionInfo->part_2_length < maxLenNow)) { int www = IRCVIEW_WCHARWIDTH(*p); left += www; m_pWrappedBlockSelectionInfo->part_2_width += www; p++; m_pWrappedBlockSelectionInfo->part_2_length++; } m_pWrappedBlockSelectionInfo->part_3_length = maxLenNow-m_pWrappedBlockSelectionInfo->part_2_length; m_pWrappedBlockSelectionInfo->part_3_width = maxWidthNow-m_pWrappedBlockSelectionInfo->part_2_width; return true; } if(right > m_iSelectionRight) { //Selection ends in THIS BLOCK! m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_LEFT; m_pWrappedBlockSelectionInfo->part_1_length = 0; m_pWrappedBlockSelectionInfo->part_1_width = 0; while((left < m_iSelectionRight) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len)) { int www = IRCVIEW_WCHARWIDTH(*p); left += www; m_pWrappedBlockSelectionInfo->part_1_width += www; p++; m_pWrappedBlockSelectionInfo->part_1_length++; } m_pWrappedBlockSelectionInfo->part_2_length = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length; m_pWrappedBlockSelectionInfo->part_2_width = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width; //debug("%d",m_pWrappedBlockSelectionInfo->part_2_width); return true; } //Selection begins in THIS BLOCK! m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_RIGHT; m_pWrappedBlockSelectionInfo->part_1_length = 0; m_pWrappedBlockSelectionInfo->part_1_width = 0; while((left <= m_iSelectionLeft) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len)) { int www = IRCVIEW_WCHARWIDTH(*p); left += www; m_pWrappedBlockSelectionInfo->part_1_width += www; p++; m_pWrappedBlockSelectionInfo->part_1_length++; } //Need to include the first character if(m_pWrappedBlockSelectionInfo->part_1_length > 0) { m_pWrappedBlockSelectionInfo->part_1_length--; p--; int www = IRCVIEW_WCHARWIDTH(*p); left -= www; m_pWrappedBlockSelectionInfo->part_1_width -= www; } m_pWrappedBlockSelectionInfo->part_2_length = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length; m_pWrappedBlockSelectionInfo->part_2_width = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width; return true; } if(top < m_iSelectionTop) { //Selection starts in this line if(right < m_iSelectionBegin)return false; if(line->pBlocks[bufIndex].pChunk && line->pBlocks[bufIndex].pChunk->type == KVI_TEXT_ICON) { m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_ICON; return true; } if(left > m_iSelectionBegin) { //Whole block selected m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_TOTAL; return true; } //Selection begins in THIS BLOCK! m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_RIGHT; m_pWrappedBlockSelectionInfo->part_1_length = 0; m_pWrappedBlockSelectionInfo->part_1_width = 0; while((left <= m_iSelectionBegin) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len)) { int www = IRCVIEW_WCHARWIDTH(*p); left += www; m_pWrappedBlockSelectionInfo->part_1_width += www; p++; m_pWrappedBlockSelectionInfo->part_1_length++; } //Need to include the first character if(m_pWrappedBlockSelectionInfo->part_1_length > 0) { m_pWrappedBlockSelectionInfo->part_1_length--; p--; int www = IRCVIEW_WCHARWIDTH(*p); left -= www; m_pWrappedBlockSelectionInfo->part_1_width -= www; } m_pWrappedBlockSelectionInfo->part_2_length = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length; m_pWrappedBlockSelectionInfo->part_2_width = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width; return true; } //Selection ends in this line if(left > m_iSelectionEnd)return false; if(line->pBlocks[bufIndex].pChunk && line->pBlocks[bufIndex].pChunk->type == KVI_TEXT_ICON) { m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_ICON; return true; } if(right < m_iSelectionEnd) { //Whole block selected m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_TOTAL; return true; } //Selection ends in THIS BLOCK! m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_LEFT; m_pWrappedBlockSelectionInfo->part_1_length = 0; m_pWrappedBlockSelectionInfo->part_1_width = 0; while((left < m_iSelectionEnd) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len)) { int www = IRCVIEW_WCHARWIDTH(*p); left += www; m_pWrappedBlockSelectionInfo->part_1_width += www; p++; m_pWrappedBlockSelectionInfo->part_1_length++; } m_pWrappedBlockSelectionInfo->part_2_length = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length; m_pWrappedBlockSelectionInfo->part_2_width = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width; return true; } //============ recalcFontVariables ==============// void KviIrcView::recalcFontVariables(const TQFontMetrics &fm,const TQFontInfo &fi) { // FIXME: #warning "OPTIMIZE THIS: GLOBAL VARIABLES" if(m_pFm)delete m_pFm; m_pFm = new TQFontMetrics(fm); m_iFontLineSpacing = m_pFm->lineSpacing(); if(m_iFontLineSpacing < KVI_IRCVIEW_PIXMAP_SIZE && KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages)) { m_iFontLineSpacing = KVI_IRCVIEW_PIXMAP_SIZE; } m_iFontDescent =m_pFm->descent(); m_iFontLineWidth =m_pFm->lineWidth(); // cache the first 256 characters for(unsigned short i=0;i<256;i++) { m_iFontCharacterWidth[i]=m_pFm->width(TQChar(i)); } if(m_iFontLineWidth==0)m_iFontLineWidth=1; m_iWrapMargin = m_pFm->width("wwww"); //for(int i=0;i<256;i++)m_iFontCharacterWidth[i]=fm.width((char)i); m_iMinimumPaintWidth = (m_pFm->width('w') << 1)+m_iWrapMargin; m_iRelativePixmapY = (m_iFontLineSpacing + KVI_IRCVIEW_PIXMAP_SIZE) >> 1; m_iIconWidth = m_pFm->width("w"); if(fi.fixedPitch() && (m_iIconWidth > 0)) { while(m_iIconWidth < 18)m_iIconWidth += m_iIconWidth; m_iIconSideSpacing = (m_iIconWidth - 16) >> 1; } else { m_iIconWidth = 18; m_iIconSideSpacing = 1; } } //================ resizeEvent ===============// void KviIrcView::resizeEvent(TQResizeEvent *) { int iScr = m_pScrollBar->sizeHint().width(); int iLeft = width()-iScr; m_pToolsButton->setGeometry(iLeft,0,iScr,iScr); m_pScrollBar->setGeometry(iLeft,iScr,iScr,height() - iScr); if(m_pToolWidget) { if( ((m_pToolWidget->x() + m_pToolWidget->width()) > (iLeft - 1)) || ((m_pToolWidget->y() + m_pToolWidget->height()) > (height() - 1))) { m_pToolWidget->move(10,10); } } } TQSize KviIrcView::sizeHint() const { TQSize ret(KVI_IRCVIEW_SIZEHINT_WIDTH,KVI_IRCVIEW_SIZEHINT_HEIGHT); return ret; } void KviIrcView::showToolsPopup() { if(!m_pToolsPopup) m_pToolsPopup = new KviTalPopupMenu(this); m_pToolsPopup->clear(); if(m_pToolWidget) m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SEARCH)),__tr2qs("Hide Find Window"),this,TQT_SLOT(toggleToolWidget())); else m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SEARCH)),__tr2qs("Show Find Window"),this,TQT_SLOT(toggleToolWidget())); m_pToolsPopup->insertSeparator(); m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PLUS)),__tr2qs("Zoom In"),this,TQT_SLOT(increaseFontSize())); m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINUS)),__tr2qs("Zoom Out"),this,TQT_SLOT(decreaseFontSize())); m_pToolsPopup->insertItem(__tr2qs("Choose Temporary Font..."),this,TQT_SLOT(chooseFont())); m_pToolsPopup->insertItem(__tr2qs("Choose Temporary Background..."),this,TQT_SLOT(chooseBackground())); int id = m_pToolsPopup->insertItem(__tr2qs("Reset Temporary Background"),this,TQT_SLOT(resetBackground())); m_pToolsPopup->setItemEnabled(id,m_pPrivateBackgroundPixmap != 0); m_pToolsPopup->insertSeparator(); m_pToolsPopup->insertItem(__tr2qs("Clear Buffer"),this,TQT_SLOT(clearBuffer())); TQSize s = m_pToolsPopup->sizeHint(); m_pToolsPopup->popup(m_pToolsButton->mapToGlobal(TQPoint(m_pToolsButton->width() - s.width(),m_pToolsButton->height()))); } void KviIrcView::increaseFontSize() { TQFont f = font(); f.setPointSize(f.pointSize() + 1); setFont(f); } void KviIrcView::decreaseFontSize() { TQFont f = font(); int p = f.pointSize(); if(p > 2)p--; f.setPointSize(p); setFont(f); } void KviIrcView::chooseFont() { bool bOk; TQFont f = TQFontDialog::getFont(&bOk,font(),this); if(!bOk)return; setFont(f); } void KviIrcView::chooseBackground() { TQString f; if(!KviFileDialog::askForOpenFileName(f,__tr2qs("Choose the background image...")))return; if(f.isEmpty())return; TQPixmap p(f); if(p.isNull()) { TQMessageBox::information(this,__tr2qs("Invalid image"),__tr2qs("Failed to load the selected image"),__tr2qs("Ok")); return; } setPrivateBackgroundPixmap(p); } void KviIrcView::resetBackground() { setPrivateBackgroundPixmap(0); } void KviIrcView::toggleToolWidget() { if(m_pToolWidget) { delete m_pToolWidget; m_pToolWidget = 0; m_pCursorLine = 0; repaint(); } else { m_pToolWidget = new KviIrcViewToolWidget(this); int w = m_pToolWidget->sizeHint().width(); m_pToolWidget->move(width() - (w + 40),10); m_pToolWidget->show(); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // The IrcView : find // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void KviIrcView::setCursorLine(KviIrcViewLine * l) { m_pCursorLine = l; if(m_pCursorLine == m_pCurLine) { repaint(); return; } int sc = m_pScrollBar->value(); l = m_pCurLine; if(m_pCursorLine->uIndex > m_pCurLine->uIndex) { // The cursor line is below the current line while(l && (l != m_pCursorLine)) { l = l->pNext; sc++; } if(!l)return; if(sc != m_pScrollBar->value()) { m_pCurLine = m_pCursorLine; m_iLastScrollBarValue = sc; m_pScrollBar->setValue(sc); } else { repaint(); } } else { // The cursor line is over the current line // Here we're in trouble :D int curBottomCoord = height() - KVI_IRCVIEW_VERTICAL_BORDER; int maxLineWidth = width(); if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages))maxLineWidth -= KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH; //Make sure that we have enough space to paint something... if(maxLineWidth < m_iMinimumPaintWidth)return; // ugh //And loop thru lines until we not run over the upper bound of the view KviIrcViewLine * curLine = m_pCurLine; while(l) { if(maxLineWidth != l->iMaxLineWidth)calculateLineWraps(l,maxLineWidth); curBottomCoord -= (l->uLineWraps + 1) * m_iFontLineSpacing; while(curLine && (curBottomCoord < KVI_IRCVIEW_VERTICAL_BORDER)) { if(curLine->iMaxLineWidth != maxLineWidth)calculateLineWraps(curLine,maxLineWidth); curBottomCoord += ((curLine->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent; curLine = curLine->pPrev; sc--; } if(l == m_pCursorLine)break; curBottomCoord -= m_iFontDescent; l = l->pPrev; } if(!curLine)return; if(sc != m_pScrollBar->value()) { m_pCurLine = curLine; m_iLastScrollBarValue = sc; m_pScrollBar->setValue(sc); } else { repaint(); } } } void KviIrcView::findNext(const TQString& szText,bool bCaseS,bool bRegExp,bool bExtended) { KviIrcViewLine * l = m_pCursorLine; if(!l)l = m_pCurLine; if(l) { l = l->pNext; if(!l)l = m_pFirstLine; KviIrcViewLine * start = l; int idx = -1; do{ if(m_pToolWidget) { if(!(m_pToolWidget->messageEnabled(l->iMsgType)))goto do_pNext; } if(bRegExp) { TQRegExp re(szText,bCaseS,!bExtended); idx = re.search(l->szText,0); } else { TQString tmp = l->szText; idx = tmp.find(szText,0,bCaseS); } if(idx != -1) { setCursorLine(l); if(m_pToolWidget) { TQString tmp; KviTQString::sprintf(tmp,__tr2qs("Pos %d"),idx); m_pToolWidget->setFindResult(tmp); } return; } do_pNext: l = l->pNext; if(!l)l = m_pFirstLine; } while(l != start); } m_pCursorLine = 0; repaint(); if(m_pToolWidget)m_pToolWidget->setFindResult(__tr2qs("Not found")); } void KviIrcView::findPrev(const TQString& szText,bool bCaseS,bool bRegExp,bool bExtended) { KviIrcViewLine * l = m_pCursorLine; if(!l)l = m_pCurLine; if(l) { l = l->pPrev; if(!l)l = m_pLastLine; KviIrcViewLine * start = l; int idx = -1; do{ if(m_pToolWidget) { if(!(m_pToolWidget->messageEnabled(l->iMsgType)))goto do_pPrev; } if(bRegExp) { TQRegExp re(szText,bCaseS,!bExtended); idx = re.search(l->szText,0); } else { TQString tmp = l->szText; idx = tmp.find(szText,0,bCaseS);; } if(idx != -1) { setCursorLine(l); if(m_pToolWidget) { TQString tmp; KviTQString::sprintf(tmp,__tr2qs("Pos %d"),idx); m_pToolWidget->setFindResult(tmp); } return; } do_pPrev: l = l->pPrev; if(!l)l = m_pLastLine; } while(l != start); } m_pCursorLine = 0; repaint(); if(m_pToolWidget)m_pToolWidget->setFindResult(__tr2qs("Not found")); } /* void KviIrcView::findClosestPositionInText(int xCursorPos,int yCursorPos,KviIrcViewPositionInText &pos) { pos.pLine = getVisibleLineAt(xCursorPos,uCursorPos); } */ KviIrcViewLine * KviIrcView::getVisibleLineAt(int xPos,int yPos) { KviIrcViewLine * l = m_pCurLine; int iTop = height() + m_iFontDescent - KVI_IRCVIEW_VERTICAL_BORDER; while(iTop > yPos) { if(l) { iTop -= ((l->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent; if(iTop <= yPos)return l; l = l->pPrev; } else return 0; } return 0; } KviIrcViewWrappedBlock * KviIrcView::getLinkUnderMouse(int xPos,int yPos,TQRect * pRect,TQString * linkCmd,TQString * linkText) { KviIrcViewLine * l = m_pCurLine; int iTop = height() + m_iFontDescent - KVI_IRCVIEW_VERTICAL_BORDER; while(iTop > yPos) { if(!l)return 0; iTop -= ((l->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent; if(iTop > yPos) { // still below the mouse l = l->pPrev; continue; } // got the right KviIrcViewLine int iLeft = KVI_IRCVIEW_HORIZONTAL_BORDER; if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages))iLeft += KVI_IRCVIEW_PIXMAP_AND_SEPARATOR; int firstRowTop = iTop; int i = 0; for(;;) { if(yPos <= iTop + m_iFontLineSpacing) { // exactly this row of this line if(iTop != firstRowTop) if(KVI_OPTION_BOOL(KviOption_boolIrcViewWrapMargin))iLeft+=m_iWrapMargin; if(xPos < iLeft)return 0; int iBlockWidth = 0; int iLastEscapeBlock = -1; int iLastEscapeBlockTop = -1; for(;;) { int iLastLeft = iLeft; if(i >= l->iBlockCount)return 0; if(l->pBlocks[i].pChunk) if(l->pBlocks[i].pChunk->type == KVI_TEXT_ESCAPE) { iLastEscapeBlock=i; iLastEscapeBlockTop=iTop; } if(l->pBlocks[i].pChunk) if(l->pBlocks[i].pChunk->type == KVI_TEXT_UNESCAPE) iLastEscapeBlock=-1; if(l->pBlocks[i].block_width > 0) { iBlockWidth = l->pBlocks[i].block_width; iLeft += iBlockWidth; } else { if(i < (l->iBlockCount - 1)) { // There is another block... // Check if it is a wrap... if(l->pBlocks[i+1].pChunk == 0) { iBlockWidth = width() - iLastLeft; iLeft = width(); } // else simply a zero characters block } } if(xPos < iLeft) { // Got it! // link ? bool bHadWordWraps = false; while(l->pBlocks[i].pChunk == 0) { // word wrap ? if(i >= 0) { i--; bHadWordWraps = true; } else return 0; // all word wraps ?!!! } if(iLastEscapeBlock != -1) { int iLeftBorder=iLeft; int k; for(k = i ; k>=iLastEscapeBlock ; k--) iLeftBorder-=l->pBlocks[k].block_width; int iRightBorder=0; unsigned int uLineWraps = 0; for(k = iLastEscapeBlock;; k++) { if(l->pBlocks[k].pChunk) if(l->pBlocks[k].pChunk->type != KVI_TEXT_UNESCAPE) iRightBorder+=l->pBlocks[k].block_width; else break; else { uLineWraps++; bHadWordWraps=1; } } if(pRect) { *pRect = TQRect(iLeftBorder, bHadWordWraps ? iLastEscapeBlockTop : iTop, iRightBorder, ((uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent); } if(linkCmd) { linkCmd->setUnicodeCodes(l->pBlocks[iLastEscapeBlock].pChunk->szPayload,kvi_wstrlen(l->pBlocks[iLastEscapeBlock].pChunk->szPayload)); linkCmd->stripWhiteSpace(); if((*linkCmd)=="nc") (*linkCmd)="n"; } if(linkText) { TQString szLink; int iEndOfLInk = iLastEscapeBlock; while(1) { if(l->pBlocks[iEndOfLInk].pChunk) if(l->pBlocks[iEndOfLInk].pChunk->type != KVI_TEXT_UNESCAPE) { switch(l->pBlocks[iEndOfLInk].pChunk->type) { case KVI_TEXT_BOLD: case KVI_TEXT_UNDERLINE: case KVI_TEXT_REVERSE: case KVI_TEXT_RESET: szLink.append(TQChar(l->pBlocks[iEndOfLInk].pChunk->type)); break; case KVI_TEXT_COLOR: szLink.append(TQChar(KVI_TEXT_COLOR)); if(l->pBlocks[iEndOfLInk].pChunk->colors.fore != KVI_NOCHANGE) { szLink.append(TQString("%1").arg((int)(l->pBlocks[iEndOfLInk].pChunk->colors.fore))); } if(l->pBlocks[iEndOfLInk].pChunk->colors.back != KVI_NOCHANGE) { szLink.append(TQChar(',')); szLink.append(TQString("%1").arg((int)(l->pBlocks[iEndOfLInk].pChunk->colors.back))); } break; } szLink.append(l->szText.mid(l->pBlocks[iEndOfLInk].block_start,l->pBlocks[iEndOfLInk].block_len)); } else break; iEndOfLInk++; } *linkText=szLink; // grab the rest of the link visible string // Continue while we do not find a non word wrap block block for(int bufIndex = (i + 1);bufIndex < l->iBlockCount;bufIndex++) { if(l->pBlocks[bufIndex].pChunk ) break; //finished : not a word wrap else { linkText->append(l->szText.mid(l->pBlocks[bufIndex].block_start,l->pBlocks[bufIndex].block_len)); } } } return &(l->pBlocks[iLastEscapeBlock]); } if(l->pBlocks[i].pChunk->type == KVI_TEXT_ICON) { if(pRect) { *pRect = TQRect(iLastLeft, bHadWordWraps ? firstRowTop : iTop, iBlockWidth, ((l->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent); } if(linkCmd) { *linkCmd = "[!txt]"; TQString tmp; tmp.setUnicodeCodes(l->pBlocks[i].pChunk->szPayload,kvi_wstrlen(l->pBlocks[i].pChunk->szPayload)); linkCmd->append(tmp); linkCmd->stripWhiteSpace(); } if(linkText) { *linkText = ""; } return &(l->pBlocks[i]); } return 0; } i++; } } else { // run until a word wrap block i++; //at least one block! while(i < l->iBlockCount) { // still ok to run right if(l->pBlocks[i].pChunk == 0) { // i++; break; } else i++; } if(i >= l->iBlockCount)return 0; iTop += m_iFontLineSpacing; } } } return 0; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Mouse handling routines /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* @doc: escape_sequences @title: Escape sequences and clickable links @type: generic @body: The KVIrc view widgets support clickable links.[br] The links can be created using special escape sequences in the text passed to the [cmd]echo[/cmd] command.[br] KVIrc uses some escape sequences in the text "echoed" internally.[br] The simplest way to explain it is to use an example:[br] [example] [cmd]echo[/cmd] This is a [fnc]$cr[/fnc]![!dbl][cmd]echo[/cmd] You have clicked it![fnc]$cr[/fnc]\clickable link$cr ! [/example] The example above will show the following text line: "This is a clickable link". If you move the mouse over the words "clickable link", you will see the text highlighted.[br] Once you double-click one of that words, the command "[cmd]echo[/cmd] You have clicked it!" will be executed.[br] The format looks complex ?... it is not...just read on.[br] ! ! [big]Escape format[/big] The whole escape sequence format is the following:[br] [b]![/b][br] is the carriage return character. You can obtain it by using the [fnc]]$cr[/fnc] function.[br] is the text that will appear as "link" when you move the mouse over it.[br] is the description of the actions to be taken when the user interacts with the link.[br] has the two following syntactic forms:[br] [b] ::= [/b][br] [b] ::= [/b] [big]User defined links[/big][br] The user defined links allow you to perform arbitrary commands when the user interacts with the link.[br] The commands are specified in the part by using the following syntax:[br] ::= [br] ::= [][br] ::= [br] ::= "[!" "]"[br] ::= "rbt" | "mbt" | "dbl" | "txt"[br] ::= any kvirc command (see notes below)[br] [big]Builtin links[/big][br] The builtin links have builtin actions performed when the user interact with the link.[br] These links are used internally in KVIrc , but you can use them too.[br] The is a single letter this time: it defines the type of the link.[br] Currently KVIrc uses six types of builtin links : 'n' for nickname links, 'u' for url links, 'c' for channel links, 'h' for hostname links, 'm' for mask links and 's' for server links.[br] Theoretically you can also use your own link types: just use any other letter or digit (you can't use ']' and ), but probably you will prefer a completely user defined link in that case anyway.[br] Once the user interacts with the link , kvirc executes the predefined events:[br] On right-click the event OnBuiltinLinkRightClicked is triggered: the first parameter is the link type, the second parameter is the (as a single parameter!!!)[br] On middle-click the event OnBuiltinLinkMiddleClicked is triggered: the parameters are similar to the previous one.[br] In the same way you have OnBuiltinLinkDoubleClicked.[br] [big]A shortcut[/big] You may have a look at the [fnc]$fmtlink[/fnc] function: it does automatically some of the job explained in this document.[br] */ // FIXME: #warning "Finish the doc above!! Maybe some examples ?!" void KviIrcView::mouseDoubleClickEvent(TQMouseEvent *e) { TQString cmd; TQString linkCmd; TQString linkText; if(m_iMouseTimer) { killTimer(m_iMouseTimer); m_iMouseTimer=0; delete m_pLastEvent; m_pLastEvent = 0; } getLinkUnderMouse(e->pos().x(),e->pos().y(),0,&linkCmd,&linkText); if(linkCmd.isEmpty()) { KVS_TRIGGER_EVENT_0(KviEvent_OnTextViewDoubleClicked,m_pKviWindow); return; } TQString szCmd(linkCmd); szCmd.remove(0,1); KviKvsVariantList * pParams = new KviKvsVariantList(); if(!szCmd.isEmpty()) pParams->append(szCmd); else pParams->append(linkText); pParams->append(linkText); pParams->append(szCmd); switch(linkCmd[0].unicode()) { case 'n': { bool bTrigger = false; switch(m_pKviWindow->type()) { case KVI_WINDOW_TYPE_CHANNEL: if(((KviChannel *)m_pKviWindow)->isOn(linkText)) { KVS_TRIGGER_EVENT(KviEvent_OnChannelNickDefaultActionRequest,m_pKviWindow,pParams); } else bTrigger = true; break; case KVI_WINDOW_TYPE_QUERY: if(KviTQString::equalCI(((KviQuery *)m_pKviWindow)->windowName(),linkText)) { KVS_TRIGGER_EVENT(KviEvent_OnQueryNickDefaultActionRequest,m_pKviWindow,pParams); } else bTrigger = true; break; default: bTrigger = true; break; } if(bTrigger) { if(console()) { KVS_TRIGGER_EVENT(KviEvent_OnNickLinkDefaultActionRequest,m_pKviWindow,pParams); } } } break; case 'm': if((linkCmd.length() > 2) && (m_pKviWindow->type() == KVI_WINDOW_TYPE_CHANNEL)) { if(((KviChannel *)m_pKviWindow)->isMeOp()) { TQChar plmn = linkCmd[1]; if((plmn.unicode() == '+') || (plmn.unicode() == '-')) { TQString target(m_pKviWindow->windowName()); target.replace("\\","\\\\"); target.replace("\"","\\\""); target.replace(";","\\;"); target.replace("$","\\$"); target.replace("%","\\%"); TQChar flag = linkCmd[2]; switch(flag.unicode()) { case 'o': case 'v': // We can do nothing here... break; case 'b': case 'I': case 'e': case 'k': KviTQString::sprintf(cmd,"mode %Q %c%c $0",&target,plmn.latin1(),flag.latin1()); break; default: KviTQString::sprintf(cmd,"mode %Q %c%c",&target,plmn.latin1(),flag.latin1()); break; } } } } break; case 'h': m_pKviWindow->output(KVI_OUT_HOSTLOOKUP,__tr2qs("Looking up host %Q..."),&linkText); cmd = "host -a $0"; break; case 'u': { TQString urlText; if(!szCmd.isEmpty()) urlText=szCmd; else urlText=linkText; if( !KviTQString::cmpCIN(urlText,"irc://",6) || !KviTQString::cmpCIN(urlText,"irc6://",7) || !KviTQString::cmpCIN(urlText,"ircs://",7) || !KviTQString::cmpCIN(urlText,"ircs6://",8) ) { KviIrcUrl::run(urlText,KviIrcUrl::TryCurrentContext | KviIrcUrl::DoNotPartChans, console()); } else { cmd = "openurl $0"; } } break; case 'c': { if(console() && console()->connection()) { TQString szChan=linkText; if(szCmd.length()>0) szChan=szCmd; if(KviChannel * c = console()->connection()->findChannel(szChan)) { // FIXME: #warning "Is this ok ?" c->raise(); c->setFocus(); } else { cmd = TQString("join %1").arg(szChan); } } } break; case 's': cmd = "motd $0"; break; default: { getLinkEscapeCommand(cmd,linkCmd,"[!dbl]"); if(cmd.isEmpty()) { KVS_TRIGGER_EVENT_0(KviEvent_OnTextViewDoubleClicked,m_pKviWindow); } } break; } if(!cmd.isEmpty()) { KviKvsScript::run(cmd,m_pKviWindow,pParams); } delete pParams; } void KviIrcView::mousePressEvent(TQMouseEvent *e) { if(m_pKviWindow->input()) m_pKviWindow->input()->setFocus(); if(e->button() & Qt::LeftButton) { // This is the beginning of a selection... // We just set the mouse to be "down" and // await mouseMove events... if(m_pToolWidget) { m_pCursorLine = getVisibleLineAt(e->pos().x(),e->pos().y()); repaint(); } m_mousePressPos = e->pos(); m_mouseCurrentPos = e->pos(); m_bMouseIsDown = true; m_bShiftPressed = (e->state() & TQt::ShiftButton); calculateSelectionBounds(); } if(e->button() & Qt::LeftButton) { if(m_iMouseTimer) { killTimer(m_iMouseTimer); m_iMouseTimer=0; delete m_pLastEvent; m_pLastEvent = 0; } else { m_iMouseTimer = startTimer(TQApplication::doubleClickInterval()); m_pLastEvent = new TQMouseEvent(*e); } } else { mouseRealPressEvent(e); } } void KviIrcView::mouseRealPressEvent(TQMouseEvent *e) { TQString linkCmd; TQString linkText; getLinkUnderMouse(e->pos().x(),e->pos().y(),0,&linkCmd,&linkText); TQString szCmd(linkCmd); szCmd.remove(0,1); KviKvsVariantList * pParams = new KviKvsVariantList(); if(!szCmd.isEmpty()) pParams->append(szCmd); else pParams->append(linkText); pParams->append(linkText); pParams->append(szCmd); if(!(e->state() & TQt::ControlButton))//(e->button() & Qt::RightButton) && ( { if(!linkCmd.isEmpty()) { switch(linkCmd[0].unicode()) { case 'n': { bool bTrigger = false; switch(m_pKviWindow->type()) { case KVI_WINDOW_TYPE_CHANNEL: if(((KviChannel *)m_pKviWindow)->isOn(linkText)) { if(e->button() & Qt::RightButton) KVS_TRIGGER_EVENT(KviEvent_OnChannelNickPopupRequest,m_pKviWindow,pParams); if(e->button() & Qt::LeftButton) { KVS_TRIGGER_EVENT(KviEvent_OnChannelNickLinkClick,m_pKviWindow,pParams); if(m_pKviWindow) { if(m_pKviWindow->inherits("KviChannel")) { KviChannel *c = (KviChannel*)m_pKviWindow; TQString nick; if(pParams->firstAsString(nick)) c->userListView()->select(nick); } } } } else bTrigger = true; break; case KVI_WINDOW_TYPE_QUERY: if(KviTQString::equalCI(((KviQuery *)m_pKviWindow)->windowName(),linkText)) { if(e->button() & Qt::RightButton) KVS_TRIGGER_EVENT(KviEvent_OnQueryNickPopupRequest,m_pKviWindow,pParams); if(e->button() & Qt::LeftButton) KVS_TRIGGER_EVENT(KviEvent_OnQueryNickLinkClick,m_pKviWindow,pParams); } else bTrigger = true; break; default: bTrigger = true; break; } if(bTrigger) { if(console()) { if(e->button() & Qt::RightButton) KVS_TRIGGER_EVENT(KviEvent_OnNickLinkPopupRequest,m_pKviWindow,pParams); if(e->button() & Qt::LeftButton) KVS_TRIGGER_EVENT(KviEvent_OnConsoleNickLinkClick,m_pKviWindow,pParams); } else emit rightClicked(); } } break; case 'h': if(e->button() & Qt::RightButton) KVS_TRIGGER_EVENT(KviEvent_OnHostLinkPopupRequest,m_pKviWindow,pParams); if(e->button() & Qt::LeftButton) KVS_TRIGGER_EVENT(KviEvent_OnHostLinkClick,m_pKviWindow,pParams); break; case 'u': if(e->button() & Qt::RightButton) KVS_TRIGGER_EVENT(KviEvent_OnUrlLinkPopupRequest,m_pKviWindow,pParams); if(e->button() & Qt::LeftButton) KVS_TRIGGER_EVENT(KviEvent_OnUrlLinkClick,m_pKviWindow,pParams); break; case 'c': if(e->button() & Qt::RightButton) KVS_TRIGGER_EVENT(KviEvent_OnChannelLinkPopupRequest,m_pKviWindow,pParams); if(e->button() & Qt::LeftButton) KVS_TRIGGER_EVENT(KviEvent_OnChannelLinkClick,m_pKviWindow,pParams); break; case 's': if(e->button() & Qt::RightButton) KVS_TRIGGER_EVENT(KviEvent_OnServerLinkPopupRequest,m_pKviWindow,pParams); if(e->button() & Qt::LeftButton) KVS_TRIGGER_EVENT(KviEvent_OnServerLinkClick,m_pKviWindow,pParams); break; default: { if(e->button() & Qt::RightButton) { TQString tmp; getLinkEscapeCommand(tmp,linkCmd,"[!rbt]"); if(!tmp.isEmpty()) { KviKvsScript::run(tmp,m_pKviWindow,pParams); } else emit rightClicked(); } } break; } } else if(e->button() & Qt::RightButton) emit rightClicked(); } else if((e->button() & Qt::MidButton) || ((e->button() & Qt::RightButton) && (e->state() & TQt::ControlButton))) { TQString tmp; getLinkEscapeCommand(tmp,linkCmd,TQString("[!mbt]")); if(!tmp.isEmpty()) { KviKvsScript::run(tmp,m_pKviWindow,pParams); } else { KVS_TRIGGER_EVENT_0(KviEvent_OnWindowPopupRequest,m_pKviWindow); } } delete pParams; } //================ mouseReleaseEvent ===============// void KviIrcView::mouseReleaseEvent(TQMouseEvent *) { if(m_iSelectTimer) { killTimer(m_iSelectTimer); m_iSelectTimer = 0; TQClipboard * c = TQApplication::clipboard(); if(c) { // copy to both! c->setText(m_szLastSelection,TQClipboard::Clipboard); if(c->supportsSelection()) c->setText(m_szLastSelection,TQClipboard::Selection); } } if(m_bMouseIsDown) { m_bMouseIsDown = false; m_bShiftPressed = false; // Insert the lines blocked while selecting while(KviIrcViewLine * l = m_pMessagesStoppedWhileSelecting->first()) { m_pMessagesStoppedWhileSelecting->removeFirst(); appendLine(l,false); } repaint(); } } // FIXME: #warning "The tooltip timeout should be small, because the view scrolls!" void KviIrcView::mouseMoveEvent(TQMouseEvent *e) { // debug("Pos : %d,%d",e->pos().x(),e->pos().y()); if(m_bMouseIsDown && (e->state() & Qt::LeftButton)) // m_bMouseIsDown MUST BE true...(otherwise the mouse entered the window with the button pressed ?) { if(m_iSelectTimer == 0)m_iSelectTimer = startTimer(KVI_IRCVIEW_SELECT_REPAINT_INTERVAL); /*if(m_iMouseTimer) { killTimer(m_iMouseTimer); m_iMouseTimer=0; mouseRealPressEvent(m_pLastEvent); delete m_pLastEvent; m_pLastEvent=0; }*/ } else { if(m_iSelectTimer) { killTimer(m_iSelectTimer); m_iSelectTimer = 0; } int yPos = e->pos().y(); int rectTop; int rectHeight; TQRect rctLink; KviIrcViewWrappedBlock * newLinkUnderMouse = getLinkUnderMouse(e->pos().x(),yPos,&rctLink); rectTop = rctLink.y(); rectHeight = rctLink.height(); if(newLinkUnderMouse != m_pLastLinkUnderMouse) { //abortTip(); //m_iTipTimer = startTimer(KVI_OPTION_UINT(KviOption_uintIrcViewToolTipTimeoutInMsec)); m_pLastLinkUnderMouse = newLinkUnderMouse; if(m_pLastLinkUnderMouse) { setCursor(TQt::PointingHandCursor); if(rectTop < 0)rectTop = 0; if((rectTop + rectHeight) > height())rectHeight = height() - rectTop; if(m_iLastLinkRectHeight > -1) { // prev link int top = (rectTop < m_iLastLinkRectTop) ? rectTop : m_iLastLinkRectTop; int lastBottom = m_iLastLinkRectTop + m_iLastLinkRectHeight; int thisBottom = rectTop + rectHeight; TQRect r(0,top,width(),((lastBottom > thisBottom) ? lastBottom : thisBottom) - top); repaint(r); } else { // no prev link TQRect r(0,rectTop,width(),rectHeight); repaint(r); } m_iLastLinkRectTop = rectTop; m_iLastLinkRectHeight = rectHeight; } else { setCursor(TQt::ArrowCursor); if(m_iLastLinkRectHeight > -1) { // There was a previous bottom rect TQRect r(0,m_iLastLinkRectTop,width(),m_iLastLinkRectHeight); repaint(r); m_iLastLinkRectTop = -1; m_iLastLinkRectHeight = -1; } } } } } KviConsole * KviIrcView::console() { return m_pKviWindow->console(); } void KviIrcView::doLinkToolTip(const TQRect &rct,TQString &linkCmd,TQString &linkText) { if(linkCmd.isEmpty())return; TQString szCmd(linkCmd); szCmd.remove(0,1); TQString tip; switch(linkCmd[0].unicode()) { case 'u': // url link { tip = "" \ "
"; if(linkText.length() > 50) { tip += linkText.left(47); tip += "..."; } else { tip += linkText; } tip+="
"; TQMimeSourceFactory::defaultFactory()->setPixmap("url_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_URL))); tip += __tr2qs("Double-click to open this link"); tip += "
"; } break; case 'h': // host link { tip = "" \ "
"; if(linkText.length() > 50) { tip += linkText.left(47); tip += "..."; } else { tip += linkText; } tip+="
"; TQMimeSourceFactory::defaultFactory()->setPixmap("host_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER))); if(linkText.find('*') != -1) { if(linkText.length() > 1)tip += __tr2qs("Unable to look it up hostname: Hostname appears to be masked"); else tip += __tr2qs("Unable to look it up hostname: Unknown host"); } else { tip += __tr2qs("Double-click to look up this hostname
Right-click to view other options"); } tip += "
"; } break; case 's': // server link { // FIXME: #warning "Spit out some server info...hub ?...registered ?" tip = "" \ "
"; TQMimeSourceFactory::defaultFactory()->setPixmap("server_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_IRC))); if(linkText.length() > 50) { tip += linkText.left(47); tip += "..."; } else { tip += linkText; } tip+="
"; if(linkText.find('*') != -1) { if(linkText.length() > 1)tip += __tr2qs("Server appears to be a network hub
"); else tip += __tr2qs("Unknown server
"); // might happen... } tip.append(__tr2qs("Double-click to read the MOTD
Right-click to view other options")); tip += "
"; } break; case 'm': // mode link { if((linkCmd.length() > 2) && (m_pKviWindow->type() == KVI_WINDOW_TYPE_CHANNEL)) { if(((KviChannel *)m_pKviWindow)->isMeOp()) { TQChar plmn = linkCmd[1]; if((plmn.unicode() == '+') || (plmn.unicode() == '-')) { tip = __tr2qs("Double-click to set
"); TQChar flag = linkCmd[2]; switch(flag.unicode()) { case 'o': case 'v': // We can do nothing here... tip = ""; break; case 'b': case 'I': case 'e': case 'k': KviTQString::appendFormatted(tip,TQString("mode %Q %c%c %Q"),&(m_pKviWindow->windowName()),plmn.latin1(),flag.latin1(),&linkText); break; default: KviTQString::appendFormatted(tip,TQString("mode %Q %c%c"),&(m_pKviWindow->windowName()),plmn.latin1(),flag.latin1()); break; } } } else { // I'm not op...no way tip = __tr2qs("You're not an operator: You may not change channel modes"); } } } break; case 'n': // nick link { if(console()) { if(console()->connection()) { KviIrcUserEntry * e = console()->connection()->userDataBase()->find(linkText); if(e) { TQString buffer; console()->getUserTipText(linkText,e,buffer); tip = buffer; } else KviTQString::sprintf(tip,__tr2qs("Nothing known about %Q"),&linkText); } else KviTQString::sprintf(tip,__tr2qs("Nothing known about %Q (no connection)"),&linkText); } } break; case 'c': // channel link { if(console() && console()->connection()) { TQString szChan = linkText; TQString buf; tip = " "; TQMimeSourceFactory::defaultFactory()->setPixmap("chan_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL))); if(szCmd.length()>0) szChan=szCmd; KviChannel * c = console()->connection()->findChannel(szChan); TQString szUrl; if(c) { TQString chanMode; c->getChannelModeString(chanMode); TQString topic = KviMircCntrl::stripControlBytes(c->topicWidget()->topic()); topic.replace("<","<"); topic.replace(">",">"); KviIrcUrl::join(szUrl,console()->connection()->target()->server()); szUrl.append(szChan); KviTQString::sprintf(buf,__tr2qs("%Q (" "%Q):
+%Q (%u users)
%Q
"),&szChan,&szUrl,&chanMode, c->count(),&topic); } else { KviIrcUrl::join(szUrl,console()->connection()->target()->server()); szUrl.append(szChan); KviTQString::sprintf(buf,__tr2qs("%Q (" "%Q)
Double-click to join %Q
Right click to view other options"),&szChan,&szUrl,&szChan); } tip += buf; } } break; default: { TQString dbl,rbt,txt,mbt; getLinkEscapeCommand(dbl,linkCmd,"[!dbl]"); getLinkEscapeCommand(rbt,linkCmd,"[!rbt]"); getLinkEscapeCommand(txt,linkCmd,"[!txt]"); getLinkEscapeCommand(mbt,linkCmd,"[!mbt]"); if(!txt.isEmpty())tip = txt; if(tip.isEmpty() && (!dbl.isEmpty())) { if(!tip.isEmpty())tip.append("
"); KviTQString::appendFormatted(tip,__tr2qs("Double-click:
%Q"),&dbl); } if(tip.isEmpty() && (!mbt.isEmpty())) { if(!tip.isEmpty())tip.append("
"); KviTQString::appendFormatted(tip,__tr2qs("Middle-click:
%Q"),&mbt); } if(tip.isEmpty() && (!rbt.isEmpty())) { if(!tip.isEmpty())tip.append("
"); KviTQString::appendFormatted(tip,__tr2qs("Right-click:
%Q"),&rbt); } } break; } if(tip.isEmpty())return; m_pToolTip->doTip(rct,tip); } void KviIrcView::leaveEvent ( TQEvent * ) { if(m_pLastLinkUnderMouse) { m_pLastLinkUnderMouse=0; update(); } } void KviIrcView::timerEvent(TQTimerEvent *e) { m_mouseCurrentPos = mapFromGlobal(TQCursor::pos()); if(e->timerId() == m_iSelectTimer) { calculateSelectionBounds(); repaint(); } if(e->timerId() == m_iMouseTimer) { killTimer(m_iMouseTimer); m_iMouseTimer=0; mouseRealPressEvent(m_pLastEvent); delete m_pLastEvent; m_pLastEvent=0; } if(e->timerId() == m_iFlushTimer) { flushLog(); } } void KviIrcView::keyPressEvent(TQKeyEvent *e) { switch(e->key()) { case TQt::Key_PageUp: prevPage(); e->accept(); break; case TQt::Key_PageDown: nextPage(); e->accept(); break; default: e->ignore(); } } void KviIrcView::maybeTip(const TQPoint &pnt) { TQString linkCmd; TQString linkText; TQRect rctLink; KviIrcViewWrappedBlock * linkUnderMouse = getLinkUnderMouse(pnt.x(),pnt.y(),&rctLink,&linkCmd,&linkText); if((linkUnderMouse == m_pLastLinkUnderMouse) && linkUnderMouse)doLinkToolTip(rctLink,linkCmd,linkText); else m_pLastLinkUnderMouse = 0; // } #include "kvi_ircview.moc"