summaryrefslogtreecommitdiffstats
path: root/src/kvirc/ui/kvi_ircview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/kvirc/ui/kvi_ircview.cpp')
-rw-r--r--src/kvirc/ui/kvi_ircview.cpp5161
1 files changed, 5161 insertions, 0 deletions
diff --git a/src/kvirc/ui/kvi_ircview.cpp b/src/kvirc/ui/kvi_ircview.cpp
new file mode 100644
index 0000000..e09edee
--- /dev/null
+++ b/src/kvirc/ui/kvi_ircview.cpp
@@ -0,0 +1,5161 @@
+//=============================================================================
+//
+// 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 <brain.h>
+//
+// #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 Qt 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 <qbitmap.h>
+#include <qpainter.h>
+#include <qregexp.h>
+#include <qfile.h>
+#include <qtoolbutton.h>
+#include <qfontmetrics.h> // needed
+#include <qapplication.h>
+#include "kvi_tal_popupmenu.h"
+#include <qmessagebox.h>
+#include <qtextcodec.h>
+#include <qdatetime.h>
+#include <qevent.h>
+
+//#include <qcolor.h> // 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"
+
+#if QT_VERSION >= 300
+ #ifndef QT_CLEAN_NAMESPACE
+ #define QT_CLEAN_NAMESPACE
+ #include <qcursor.h>
+ #undef QT_CLEAN_NAMESPACE
+ #else
+ #include <qcursor.h>
+ #endif
+#else
+ #include <qcursor.h>
+#endif
+
+#include <qclipboard.h>
+#include <qdatetime.h>
+#include <qmessagebox.h>
+#include <qscrollbar.h>
+#include <qfontdialog.h>
+
+#include <time.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <q3mimefactory.h>
+ #define QMimeSourceFactory 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 <zlib.h>
+#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 QPixmap * 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...
+// Qt+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_QCHAR
+
+#define _WSTRING_WMEMCPY(_dst,_src,_len) kvi_fastmoveodd((void *)(_dst),(const void *)(_src),sizeof(kvi_wchar_t) * (_len))
+
+void kvi_appendWCharToQStringWithLength(QString * 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_QCHAR
+ _WSTRING_WMEMCPY(qstrptr->unicode() + oldLen,ptr,len);
+ #else // !WSTRINGCONFIG_SAFE_TO_MEMCPY_QCHAR
+ QChar * c = (qstrptr->unicode() + oldLen);
+ while(*ptr)
+ {
+ c->unicode() = *ptr;
+ ptr++;
+ c++;
+ }
+ #endif // !WSTRINGCONFIG_SAFE_TO_MEMCPY_QCHAR
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Info about escape syntax
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// escape commands:
+//
+// <cr>!<escape_command><cr><visible parameters<cr>
+//
+// <escape_command> ::= u <--- url link
+// <escape_command> ::= n <--- nick link
+// <escape_command> ::= s <--- server link
+// <escape_command> ::= h <--- host link
+// <escape_command> ::= [... <--- generic escape "rbt" | "mbt" | "dbl" | "txt"
+//
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : construct and destroy
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviIrcView::KviIrcView(QWidget *parent,KviFrame *pFrm,KviWindow *pWnd)
+: QWidget(parent,"irc_view")
+{
+ // Ok...here we go
+ // initialize the initializable
+
+#ifdef COMPILE_USE_QT4
+ setAttribute(Qt::WA_NoSystemBackground); // This disables automatic qt double buffering
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ //setAttribute(Qt::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<KviIrcViewLine>;
+ 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 QScrollBar(0,0,1,10,0,Qt::Vertical,this,"irc_view_scrollbar");
+#else
+ m_pScrollBar = new QScrollBar(0,0,1,10,0,QScrollBar::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
+ QIcon is1(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUPMENU)));
+ m_pToolsButton->setAutoRaise(true);
+#else
+ QIconSet is1(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUPMENU)),QIconSet::Small);
+#endif
+ m_pToolsButton->setIconSet(is1);
+
+ KviTalToolTip::add(m_pToolsButton,__tr2qs("Search tools"));
+ m_pToolsButton->setFocusProxy(this);
+
+ connect(m_pToolsButton,SIGNAL(clicked()),this,SLOT(showToolsPopup()));
+ m_pToolsButton->show();
+
+ connect(m_pScrollBar,SIGNAL(valueChanged(int)),this,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;i<l->uChunkCount;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 QFont &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;
+ }
+ QWidget::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(QDragEnterEvent *e)
+{
+ if(!m_bAcceptDrops)return;
+ e->accept(KviUriDrag::canDecode(e));
+ emit dndEntered();
+}
+
+void KviIrcView::dropEvent(QDropEvent *e)
+{
+ if(!m_bAcceptDrops)return;
+ QStringList list;
+ if(KviUriDrag::decodeLocalFiles(e,list))
+ {
+ if(!list.isEmpty())
+ {
+ QStringList::ConstIterator it = list.begin(); //kewl ! :)
+ for( ; it != list.end(); ++it )
+ {
+ QString tmp = *it; //wow :)
+ #ifndef COMPILE_ON_WINDOWS
+ if(tmp[0] != '/')tmp.prepend("/"); //HACK HACK HACK for Qt bug (?!?)
+ #endif
+ emit fileDropped(tmp);
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : Logging
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void KviIrcView::stopLogging()
+{
+ if(m_pLogFile)
+ {
+ QString szLogEnd;
+ szLogEnd.sprintf(__tr2qs("### Log session terminated at %s ###"),QDateTime::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))
+ {
+ QByteArray bytes;
+ bytes=m_pLogFile->readAll();
+ m_pLogFile->close();
+ QFileInfo fi(*m_pLogFile);
+ QString szFname=fi.dirPath(true)+QString("/")+fi.baseName(true);
+ gzFile file=gzopen(QTextCodec::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(QString &buffer)
+{
+ if(m_pLogFile) buffer=m_pLogFile->name();
+}
+
+void KviIrcView::getTextBuffer(QString &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))
+ {
+ QByteArray bytes;
+ bytes=m_pLogFile->readAll();
+ m_pLogFile->close();
+ QFileInfo fi(*m_pLogFile);
+ QString szFname=fi.dirPath(true)+QString("/")+fi.baseName(true);
+ gzFile file=gzopen(QTextCodec::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 QString & 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 KviQString::empty;
+}
+
+const QString & KviIrcView::lastLineOfText()
+{
+ if(!m_pLastLine)return KviQString::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,SLOT(masterDead()));
+ m_pMasterView = v;
+ if(m_pMasterView)connect(m_pMasterView,SIGNAL(destroyed()),this,SLOT(masterDead()));
+}
+
+void KviIrcView::masterDead()
+{
+ m_pMasterView = 0;
+}
+
+bool KviIrcView::startLogging(const QString& fname,bool bPrependCurBuffer)
+{
+ stopLogging();
+ QString 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 QFile(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;
+ }
+ }
+
+ QString szLogStart;
+ szLogStart.sprintf(__tr2qs("### Log session started at %s ###"),QDateTime::currentDateTime().toString().utf8().data());
+ add2Log(szLogStart);
+ if(bPrependCurBuffer)
+ {
+ add2Log(__tr2qs("### Existing data buffer:"));
+ QString buffer;
+ getTextBuffer(buffer);
+ add2Log(buffer);
+ add2Log(__tr2qs("### End of existing data buffer."));
+ m_pLogFile->flush();
+ }
+
+ return true;
+}
+
+void KviIrcView::add2Log(const QString &szBuffer,int iMsgType)
+{
+ QString szToWrite=QString("%1 %2\n").arg(iMsgType).arg(szBuffer);
+ KviQCString szTmp = KviQString::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)
+{
+ QFile f(QString::fromUtf8(filename));
+ if(!f.open(IO_WriteOnly|IO_Truncate))return false;
+ QString tmp;
+ getTextBuffer(tmp);
+ KviQCString tmpx = KviQString::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 QPixmap &pixmap,bool bRepaint)
+{
+ if(m_pPrivateBackgroundPixmap)
+ {
+ delete m_pPrivateBackgroundPixmap;
+ m_pPrivateBackgroundPixmap=0;
+ }
+ if(!pixmap.isNull())m_pPrivateBackgroundPixmap = new QPixmap(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()
+{
+ QDate::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(QEvent *e)
+{
+ if(e->type() == QEvent::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 QWidget::event(e);
+}
+
+void KviIrcView::wheelEvent(QWheelEvent *e)
+{
+#ifdef COMPILE_USE_QT4
+ static bool bHere = false;
+ if(bHere)return;
+ bHere = true; // Qt4 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 QEvent with a full repaint request
+ if(!m_bPostedPaintEventPending)
+ {
+ m_bPostedPaintEventPending = true;
+ QEvent *e = new QEvent(QEvent::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))
+ {
+ QString szBuffer;
+ kvi_appendWCharToQStringWithLength(&szBuffer,data_ptr,kvi_wstrlen(data_ptr));
+ szBuffer.prepend(QDateTime::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(QString &buffer,const QString &szPayload,const QString &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=QColor();
+
+ if(bEnableTimeStamp && KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp))
+ {
+ QString szTimestamp;
+ szTimestamp=QDateTime::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=QColor();
+ iCurChunk+=2;
+ } else {
+ // only one chunk
+ line_ptr->pChunks[0].iTextLen = iTimeStampLength;
+ }
+
+ // We need the timestamp string to be added
+ // alloc the necessary space
+ line_ptr->szText.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 QChar * data_ptr_aux = (QChar *)line_ptr->szText.unicode();
+ register QChar * stamp_ptr_aux = (QChar *)szTimestamp.unicode();
+
+ for(int i=0;i<iTimeStampLength;i++)
+ *data_ptr_aux++ = *stamp_ptr_aux++;
+ } else {
+ // Timestamp not needed... but we don't want null strings floating around
+ line_ptr->szText = "";
+ line_ptr->pChunks[0].iTextLen = 0;
+ }
+
+ //
+ // Ok... a couple of macros that occur really frequently
+ // in the following code...
+ // these could work well as functions too...but the macros are a lot faster :)
+ //
+
+#define APPEND_LAST_TEXT_BLOCK(__data_ptr,__data_len) \
+ blockLen = (__data_len); \
+ line_ptr->pChunks[iCurChunk].iTextLen += blockLen; \
+ kvi_appendWCharToQStringWithLength(&(line_ptr->szText),__data_ptr,__data_len); \
+ iTextIdx+=blockLen;
+
+#define APPEND_LAST_TEXT_BLOCK_HIDDEN_FROM_NOW(__data_ptr,__data_len) \
+ blockLen = (__data_len); \
+ kvi_appendWCharToQStringWithLength(&(line_ptr->szText),__data_ptr,__data_len); \
+ iTextIdx+=blockLen;
+
+
+#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 : QColor();
+
+ // 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 <KviIrcView::getTextLine(int, char const *, KviIrcViewLine *)+0x1f3>
+ // 18b5: ff e0 jmp *%eax
+ //
+ // I even had a nicer version:
+ //
+ // goto *(char_to_check_jump_table[*((unsigned char *)p)]);
+ // 18a3: 8b 55 f0 movl 0xfffffff0(%ebp),%edx
+ // 18a6: 31 c0 xorl %eax,%eax
+ // 18a8: 8a 02 movb (%edx),%al
+ // 18aa: ff 24 85 20 00 00 00 jmp *0x20(,%eax,4)
+ //
+ // but sth tells me that "jmp *0x20(,%eax,4)" takes a loooooot of clock ticks...
+ // ...we have less instructions , but the code takes longer to execute (7-8% longer)
+ // it might be also due to pipeline tricks, jump "next instruction precalculation" stuff...
+
+ // So we end up using the 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 &nothing_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!<escape_cmd>\r<visible parameters string>\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(QString((QChar*)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')
+ {
+ QString m_szNick = QString((QChar*)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!
+ QString 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)
+ {
+ QString 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!!!
+ QString 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),QRect(1,1,widgetWidth-2,widgetHeight-2));
+#else
+ bitBlt(this,1,1,this,1,heightToPaint,widgetWidth -2,widgetHeight - (heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER));
+
+ QRect r(0,widgetHeight - (heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER),
+ widgetWidth,heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER);
+
+ QPaintEvent * e = new QPaintEvent(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(QPaintEvent *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 QRect 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
+ QPainter pa(this); // we use qt4 double buffering
+#else
+ KviDoubleBuffer doublebuffer(width(),height());
+ QPixmap * pDoubleBufferPixmap = doublebuffer.pixmap();
+
+ QPainter pa(pDoubleBufferPixmap);
+#endif
+ SET_ANTI_ALIASING(pa);
+
+ pa.setFont(font());
+ if(!m_pFm)
+ {
+ // note that QFontMetrics(pa.font()) may be not the same as QFontMetrics(font())
+ // because the painter might effectively use an approximation of the QFont specified
+ // by font().
+ recalcFontVariables(QFontMetrics(pa.font()),pa.fontInfo());
+ }
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = mapToGlobal(QPoint(rectLeft,rectTop));
+ pa.drawTiledPixmap(rectLeft,rectTop,rectWidth,rectHeight,*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ QPixmap * 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 : QColor()); \
+ { \
+ 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 : QColor()); \
+ 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(QChar(block->pChunk->type));
+ break;
+ case KVI_TEXT_COLOR:
+ m_szLastSelectionLine.append(QChar(block->pChunk->type));
+ if((block->pChunk->colors.fore != KVI_NOCHANGE) && (block->pChunk->colors.fore != KVI_TRANSPARENT))
+ {
+ if(curFore > 9)m_szLastSelectionLine.append(QChar('1'));
+ m_szLastSelectionLine.append(QChar((curFore%10)+'0'));
+ }
+ if((block->pChunk->colors.back != KVI_NOCHANGE) && (block->pChunk->colors.back != KVI_TRANSPARENT) )
+ {
+ m_szLastSelectionLine.append(QChar(','));
+ if(curBack > 9)m_szLastSelectionLine.append(QChar('1'));
+ m_szLastSelectionLine.append(QChar((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(QChar(block->pChunk->type));
+ QString 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));
+ }
+ QString tmpQ;
+ tmpQ.setUnicodeCodes(block->pChunk->szSmileId,kvi_wstrlen(block->pChunk->szSmileId));
+ QPixmap * 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 : QColor());
+
+ 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 : QColor());
+ 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(QPainter::CompositionMode_SourceOut);
+#else
+ pa.setRasterOp(NotROP);
+#endif
+ pa.fillRect(0,curBottomCoord - iH,widgetWidth,iH + (m_iFontDescent << 1),Qt::black);
+#ifdef COMPILE_USE_QT4
+ pa.setCompositionMode(QPainter::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(QPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,Qt::DotLine));
+#else
+ pa.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,QPen::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(Qt::black);
+#ifdef COMPILE_USE_QT4
+ pa.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,Qt::DotLine));
+#else
+ pa.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,QPen::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,Qt::CopyROP);
+#endif
+// else we use the Qt4 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 QChar * unicode = ptr->szText.unicode();
+
+ for(;;)
+ {
+ //Calculate the block_width
+ register const QChar * 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 QChar * unicode = line->szText.unicode();
+ register const QChar * 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 QFontMetrics &fm,const QFontInfo &fi)
+{
+ // FIXME: #warning "OPTIMIZE THIS: GLOBAL VARIABLES"
+ if(m_pFm)delete m_pFm;
+ m_pFm = new QFontMetrics(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(QChar(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(QResizeEvent *)
+{
+ 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);
+ }
+ }
+}
+
+QSize KviIrcView::sizeHint() const
+{
+ QSize 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,SLOT(toggleToolWidget()));
+ else
+ m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SEARCH)),__tr2qs("Show Find Window"),this,SLOT(toggleToolWidget()));
+ m_pToolsPopup->insertSeparator();
+ m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PLUS)),__tr2qs("Zoom In"),this,SLOT(increaseFontSize()));
+ m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINUS)),__tr2qs("Zoom Out"),this,SLOT(decreaseFontSize()));
+ m_pToolsPopup->insertItem(__tr2qs("Choose Temporary Font..."),this,SLOT(chooseFont()));
+ m_pToolsPopup->insertItem(__tr2qs("Choose Temporary Background..."),this,SLOT(chooseBackground()));
+ int id = m_pToolsPopup->insertItem(__tr2qs("Reset Temporary Background"),this,SLOT(resetBackground()));
+ m_pToolsPopup->setItemEnabled(id,m_pPrivateBackgroundPixmap != 0);
+ m_pToolsPopup->insertSeparator();
+ m_pToolsPopup->insertItem(__tr2qs("Clear Buffer"),this,SLOT(clearBuffer()));
+
+ QSize s = m_pToolsPopup->sizeHint();
+
+ m_pToolsPopup->popup(m_pToolsButton->mapToGlobal(QPoint(m_pToolsButton->width() - s.width(),m_pToolsButton->height())));
+}
+
+void KviIrcView::increaseFontSize()
+{
+ QFont f = font();
+ f.setPointSize(f.pointSize() + 1);
+ setFont(f);
+}
+
+void KviIrcView::decreaseFontSize()
+{
+ QFont f = font();
+ int p = f.pointSize();
+ if(p > 2)p--;
+ f.setPointSize(p);
+ setFont(f);
+}
+
+void KviIrcView::chooseFont()
+{
+ bool bOk;
+ QFont f = QFontDialog::getFont(&bOk,font(),this);
+ if(!bOk)return;
+ setFont(f);
+}
+
+void KviIrcView::chooseBackground()
+{
+ QString f;
+ if(!KviFileDialog::askForOpenFileName(f,__tr2qs("Choose the background image...")))return;
+ if(f.isEmpty())return;
+ QPixmap p(f);
+ if(p.isNull())
+ {
+ QMessageBox::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 QString& 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)
+ {
+ QRegExp re(szText,bCaseS,!bExtended);
+#if QT_VERSION >= 300
+ idx = re.search(l->szText,0);
+#else
+ idx = re.find(l->szText,0);
+#endif
+ } else {
+ QString tmp = l->szText;
+ idx = tmp.find(szText,0,bCaseS);
+ }
+
+ if(idx != -1)
+ {
+ setCursorLine(l);
+ if(m_pToolWidget)
+ {
+ QString tmp;
+ KviQString::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 QString& 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)
+ {
+ QRegExp re(szText,bCaseS,!bExtended);
+#if QT_VERSION >= 300
+ idx = re.search(l->szText,0);
+#else
+ idx = re.find(l->szText,0);
+#endif
+ } else {
+ QString tmp = l->szText;
+ idx = tmp.find(szText,0,bCaseS);;
+ }
+
+ if(idx != -1)
+ {
+ setCursorLine(l);
+ if(m_pToolWidget)
+ {
+ QString tmp;
+ KviQString::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,QRect * pRect,QString * linkCmd,QString * 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 = QRect(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)
+ {
+ QString 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(QChar(l->pBlocks[iEndOfLInk].pChunk->type));
+ break;
+ case KVI_TEXT_COLOR:
+ szLink.append(QChar(KVI_TEXT_COLOR));
+ if(l->pBlocks[iEndOfLInk].pChunk->colors.fore != KVI_NOCHANGE)
+ {
+ szLink.append(QString("%1").arg((int)(l->pBlocks[iEndOfLInk].pChunk->colors.fore)));
+ }
+ if(l->pBlocks[iEndOfLInk].pChunk->colors.back != KVI_NOCHANGE)
+ {
+ szLink.append(QChar(','));
+ szLink.append(QString("%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 = QRect(iLastLeft,
+ bHadWordWraps ? firstRowTop : iTop,
+ iBlockWidth,
+ ((l->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent);
+ }
+ if(linkCmd)
+ {
+ *linkCmd = "[!txt]";
+ QString 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]
+
+ <cr>!<link_type><cr><visible text><cr>
+ <cr>!<escape_command><cr><visible text><cr>
+
+ [big]Escape format[/big]
+ The whole escape sequence format is the following:[br]
+ [b]<cr>!<escape_command><cr><visible text><cr>[/b][br]
+ <cr> is the carriage return character. You can obtain it by using the [fnc]]$cr[/fnc] function.[br]
+ <visible text> is the text that will appear as "link" when you move the mouse over it.[br]
+ <escape_command> is the description of the actions to be taken when the user interacts with the link.[br]
+ <escape_command> has the two following syntactic forms:[br]
+ [b]<escape_command> ::= <user_defined_commands>[/b][br]
+ [b]<escape_command> ::= <builtin_link_description>[/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 <escape_command> part by using the following syntax:[br]
+ <escape_command> ::= <user_defined_commands>[br]
+ <user_defined_commands> ::= <command_rule> [<user_defined_commands>][br]
+ <command_rule> ::= <action_tag><command>[br]
+ <action_tag> ::= "[!" <action> "]"[br]
+ <action> ::= "rbt" | "mbt" | "dbl" | "txt"[br]
+ <command> ::= 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 <escape_command> 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 <cr>),
+ 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 <visible text> (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(QMouseEvent *e)
+{
+ QString cmd;
+ QString linkCmd;
+ QString 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;
+ }
+
+ QString 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(KviQString::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())
+ {
+ QChar plmn = linkCmd[1];
+ if((plmn.unicode() == '+') || (plmn.unicode() == '-'))
+ {
+ QString target(m_pKviWindow->windowName());
+ target.replace("\\","\\\\");
+ target.replace("\"","\\\"");
+ target.replace(";","\\;");
+ target.replace("$","\\$");
+ target.replace("%","\\%");
+ QChar flag = linkCmd[2];
+ switch(flag.unicode())
+ {
+ case 'o':
+ case 'v':
+ // We can do nothing here...
+ break;
+
+ case 'b':
+ case 'I':
+ case 'e':
+ case 'k':
+ KviQString::sprintf(cmd,"mode %Q %c%c $0",&target,plmn.latin1(),flag.latin1());
+ break;
+ default:
+ KviQString::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':
+ {
+ QString urlText;
+ if(!szCmd.isEmpty()) urlText=szCmd;
+ else urlText=linkText;
+ if(
+ !KviQString::cmpCIN(urlText,"irc://",6) ||
+ !KviQString::cmpCIN(urlText,"irc6://",7) ||
+ !KviQString::cmpCIN(urlText,"ircs://",7) ||
+ !KviQString::cmpCIN(urlText,"ircs6://",8)
+ )
+ {
+ KviIrcUrl::run(urlText,KviIrcUrl::TryCurrentContext | KviIrcUrl::DoNotPartChans, console());
+ } else {
+ cmd = "openurl $0";
+ }
+ }
+ break;
+ case 'c':
+ {
+ if(console() && console()->connection())
+ {
+ QString 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 = QString("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(QMouseEvent *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() & Qt::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(QApplication::doubleClickInterval());
+ m_pLastEvent = new QMouseEvent(*e);
+ }
+ } else {
+ mouseRealPressEvent(e);
+ }
+}
+
+void KviIrcView::mouseRealPressEvent(QMouseEvent *e)
+{
+ QString linkCmd;
+ QString linkText;
+ getLinkUnderMouse(e->pos().x(),e->pos().y(),0,&linkCmd,&linkText);
+
+ QString 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() & Qt::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;
+ QString nick;
+ if(pParams->firstAsString(nick))
+ c->userListView()->select(nick);
+ }
+ }
+ }
+ } else bTrigger = true;
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(KviQString::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)
+ {
+ QString 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() & Qt::ControlButton)))
+ {
+ QString tmp;
+ getLinkEscapeCommand(tmp,linkCmd,QString("[!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(QMouseEvent *)
+{
+ if(m_iSelectTimer)
+ {
+ killTimer(m_iSelectTimer);
+ m_iSelectTimer = 0;
+ QClipboard * c = QApplication::clipboard();
+ if(c)
+ {
+ // copy to both!
+ c->setText(m_szLastSelection,QClipboard::Clipboard);
+ if(c->supportsSelection())
+ c->setText(m_szLastSelection,QClipboard::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(QMouseEvent *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;
+ QRect 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(Qt::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;
+ QRect r(0,top,width(),((lastBottom > thisBottom) ? lastBottom : thisBottom) - top);
+ repaint(r);
+ } else {
+ // no prev link
+ QRect r(0,rectTop,width(),rectHeight);
+ repaint(r);
+ }
+ m_iLastLinkRectTop = rectTop;
+ m_iLastLinkRectHeight = rectHeight;
+ } else {
+ setCursor(Qt::ArrowCursor);
+ if(m_iLastLinkRectHeight > -1)
+ {
+ // There was a previous bottom rect
+ QRect 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 QRect &rct,QString &linkCmd,QString &linkText)
+{
+ if(linkCmd.isEmpty())return;
+
+ QString szCmd(linkCmd);
+ szCmd.remove(0,1);
+
+ QString tip;
+
+ switch(linkCmd[0].unicode())
+ {
+ case 'u': // url link
+ {
+ tip = "<table width=\"100%\">" \
+ "<tr><td valign=\"center\"><img src=\"url_icon\"> <u><font color=\"blue\"><nowrap>";
+ if(linkText.length() > 50)
+ {
+ tip += linkText.left(47);
+ tip += "...";
+ } else {
+ tip += linkText;
+ }
+ tip+="</nowrap></font></u></td></tr><tr><td>";
+ QMimeSourceFactory::defaultFactory()->setPixmap("url_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_URL)));
+ tip += __tr2qs("Double-click to open this link");
+ tip += "</td></tr></table>";
+ }
+ break;
+ case 'h': // host link
+ {
+ tip = "<table width=\"100%\">" \
+ "<tr><td valign=\"center\"><img src=\"host_icon\"> <u><font color=\"blue\"><nowrap>";
+ if(linkText.length() > 50)
+ {
+ tip += linkText.left(47);
+ tip += "...";
+ } else {
+ tip += linkText;
+ }
+ tip+="</nowrap></font></u></td></tr><tr><td>";
+ QMimeSourceFactory::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<br>Right-click to view other options");
+ }
+ tip += "</td></tr></table>";
+ }
+ break;
+ case 's': // server link
+ {
+ // FIXME: #warning "Spit out some server info...hub ?...registered ?"
+
+ tip = "<table width=\"100%\">" \
+ "<tr><td valign=\"center\"><img src=\"server_icon\"> <u><font color=\"blue\"><nowrap>";
+ QMimeSourceFactory::defaultFactory()->setPixmap("server_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_IRC)));
+ if(linkText.length() > 50)
+ {
+ tip += linkText.left(47);
+ tip += "...";
+ } else {
+ tip += linkText;
+ }
+ tip+="</nowrap></font></u></td></tr><tr><td>";
+
+ if(linkText.find('*') != -1)
+ {
+ if(linkText.length() > 1)tip += __tr2qs("Server appears to be a network hub<br>");
+ else tip += __tr2qs("Unknown server<br>"); // might happen...
+ }
+
+ tip.append(__tr2qs("Double-click to read the MOTD<br>Right-click to view other options"));
+ tip += "</td></tr></table>";
+ }
+ break;
+ case 'm': // mode link
+ {
+ if((linkCmd.length() > 2) && (m_pKviWindow->type() == KVI_WINDOW_TYPE_CHANNEL))
+ {
+ if(((KviChannel *)m_pKviWindow)->isMeOp())
+ {
+ QChar plmn = linkCmd[1];
+ if((plmn.unicode() == '+') || (plmn.unicode() == '-'))
+ {
+ tip = __tr2qs("Double-click to set<br>");
+ QChar 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':
+ KviQString::appendFormatted(tip,QString("<b>mode %Q %c%c %Q</b>"),&(m_pKviWindow->windowName()),plmn.latin1(),flag.latin1(),&linkText);
+ break;
+ default:
+ KviQString::appendFormatted(tip,QString("<b>mode %Q %c%c</b>"),&(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)
+ {
+ QString buffer;
+ console()->getUserTipText(linkText,e,buffer);
+ tip = buffer;
+ } else KviQString::sprintf(tip,__tr2qs("Nothing known about %Q"),&linkText);
+ } else KviQString::sprintf(tip,__tr2qs("Nothing known about %Q (no connection)"),&linkText);
+ }
+ }
+ break;
+ case 'c': // channel link
+ {
+ if(console() && console()->connection())
+ {
+ QString szChan = linkText;
+ QString buf;
+ tip = "<img src=\"chan_icon\"> ";
+ QMimeSourceFactory::defaultFactory()->setPixmap("chan_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)));
+
+ if(szCmd.length()>0) szChan=szCmd;
+ KviChannel * c = console()->connection()->findChannel(szChan);
+ QString szUrl;
+ if(c)
+ {
+ QString chanMode;
+ c->getChannelModeString(chanMode);
+ QString topic = KviMircCntrl::stripControlBytes(c->topicWidget()->topic());
+ topic.replace("<","&lt;");
+ topic.replace(">","&gt;");
+ KviIrcUrl::join(szUrl,console()->connection()->target()->server());
+ szUrl.append(szChan);
+ KviQString::sprintf(buf,__tr2qs("<b>%Q</b> (<u><font color=\"blue\"><nowrap>"
+ "%Q</nowrap></font></u>): <br><nowrap>+%Q (%u users)<hr>%Q</nowrap>"),&szChan,&szUrl,&chanMode,
+ c->count(),&topic);
+ } else {
+ KviIrcUrl::join(szUrl,console()->connection()->target()->server());
+ szUrl.append(szChan);
+ KviQString::sprintf(buf,__tr2qs("<b>%Q</b> (<u><font color=\"blue\"><nowrap>"
+ "%Q</nowrap></font></u>)<hr>Double-click to join %Q<br>Right click to view other options"),&szChan,&szUrl,&szChan);
+ }
+
+ tip += buf;
+ }
+ }
+ break;
+ default:
+ {
+ QString 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("<hr>");
+ KviQString::appendFormatted(tip,__tr2qs("<b>Double-click:</b><br>%Q"),&dbl);
+ }
+ if(tip.isEmpty() && (!mbt.isEmpty()))
+ {
+ if(!tip.isEmpty())tip.append("<hr>");
+ KviQString::appendFormatted(tip,__tr2qs("<b>Middle-click:</b><br>%Q"),&mbt);
+ }
+ if(tip.isEmpty() && (!rbt.isEmpty()))
+ {
+ if(!tip.isEmpty())tip.append("<hr>");
+ KviQString::appendFormatted(tip,__tr2qs("<b>Right-click:</b><br>%Q"),&rbt);
+ }
+ }
+ break;
+ }
+
+ if(tip.isEmpty())return;
+
+ m_pToolTip->doTip(rct,tip);
+}
+void KviIrcView::leaveEvent ( QEvent * )
+{
+ if(m_pLastLinkUnderMouse)
+ {
+ m_pLastLinkUnderMouse=0;
+ update();
+ }
+}
+void KviIrcView::timerEvent(QTimerEvent *e)
+{
+ m_mouseCurrentPos = mapFromGlobal(QCursor::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(QKeyEvent *e)
+{
+ switch(e->key())
+ {
+ case Qt::Key_PageUp:
+ prevPage();
+ e->accept();
+ break;
+ case Qt::Key_PageDown:
+ nextPage();
+ e->accept();
+ break;
+ default:
+ e->ignore();
+ }
+}
+
+void KviIrcView::maybeTip(const QPoint &pnt)
+{
+ QString linkCmd;
+ QString linkText;
+
+ QRect 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"