|
|
|
/* This file is part of ksirc
|
|
|
|
Copyright (c) 2001 Malte Starostik <malte@kde.org>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Color parser code courtesy of ksirc <http://www.kde.org>
|
|
|
|
Modified by Jason Keirstead <jason@keirstead.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <knotifyclient.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tqbuffer.h>
|
|
|
|
#include <tqdatastream.h>
|
|
|
|
#include <tqstylesheet.h>
|
|
|
|
#include "ksparser.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
KSParser KSParser::m_parser;
|
|
|
|
|
|
|
|
const TQColor KSParser::IRC_Colors[17]=
|
|
|
|
{
|
|
|
|
TQt::white,
|
|
|
|
TQt::black,
|
|
|
|
TQt::darkBlue,
|
|
|
|
TQt::darkGreen,
|
|
|
|
TQt::red,
|
|
|
|
TQt::darkRed,
|
|
|
|
TQt::darkMagenta,
|
|
|
|
TQt::darkYellow,
|
|
|
|
TQt::yellow,
|
|
|
|
TQt::green,
|
|
|
|
TQt::darkCyan,
|
|
|
|
TQt::cyan,
|
|
|
|
TQt::blue,
|
|
|
|
TQt::magenta,
|
|
|
|
TQt::darkGray,
|
|
|
|
TQt::gray,
|
|
|
|
TQColor() // default invalid color, must be the last
|
|
|
|
};
|
|
|
|
|
|
|
|
const TQRegExp KSParser::sm_colorsModeRegexp("(\\d{1,2})(?:,(\\d{1,2}))?");
|
|
|
|
|
|
|
|
template <typename _TYPE_>
|
|
|
|
inline void swap(_TYPE_ &o1, _TYPE_ &o2)
|
|
|
|
{
|
|
|
|
_TYPE_ tmp = o1;
|
|
|
|
o1 = o2;
|
|
|
|
o2 = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
KSParser::KSParser()
|
|
|
|
{
|
|
|
|
kdDebug(14120) << k_funcinfo << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
KSParser::~KSParser()
|
|
|
|
{
|
|
|
|
kdDebug(14120) << k_funcinfo << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NOTE: If thread corruption are seen simply ad a qlock here */
|
|
|
|
TQCString KSParser::parse(const TQCString &message)
|
|
|
|
{
|
|
|
|
return m_parser._parse(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQCString KSParser::_parse(const TQCString &message)
|
|
|
|
{
|
|
|
|
TQCString data( message.size() * 2 );
|
|
|
|
TQBuffer buff( data );
|
|
|
|
buff.open( IO_WriteOnly );
|
|
|
|
|
|
|
|
m_tags.clear();
|
|
|
|
m_attributes.clear();
|
|
|
|
|
|
|
|
TQRegExp colorsModeRegexp(sm_colorsModeRegexp);
|
|
|
|
|
|
|
|
// should be set to the current default colors ....
|
|
|
|
TQColor fgColor; /*KopeteMesage::fg().name()*/
|
|
|
|
TQColor bgColor; /*KopeteMesage::bg().name()*/
|
|
|
|
|
|
|
|
uint chars = 0;
|
|
|
|
for(uint i = 0; i < message.length(); ++i)
|
|
|
|
{
|
|
|
|
const TQChar &cur = message[i];
|
|
|
|
TQString toAppend;
|
|
|
|
|
|
|
|
switch (cur)
|
|
|
|
{
|
|
|
|
case 0x02: //Bold: ^B
|
|
|
|
toAppend= toggleTag("b");
|
|
|
|
break;
|
|
|
|
case 0x03: //Color code: ^C
|
|
|
|
if (colorsModeRegexp.search(message, i+1) == (int)i+1)
|
|
|
|
{
|
|
|
|
i += colorsModeRegexp.matchedLength(); // + 1 will be added by ++
|
|
|
|
TQString tagStyle;
|
|
|
|
|
|
|
|
fgColor = ircColor(colorsModeRegexp.cap(1));
|
|
|
|
bgColor = ircColor(colorsModeRegexp.cap(2));
|
|
|
|
|
|
|
|
toAppend = pushColorTag(fgColor, bgColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
toAppend = popTag(TQString::tqfromLatin1("span"));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x07: //System bell: ^G
|
|
|
|
KNotifyClient::beep( TQString::tqfromLatin1("IRC beep event received in a message") );
|
|
|
|
break;
|
|
|
|
case '\t': // 0x09
|
|
|
|
toAppend = TQString::tqfromLatin1(" ");
|
|
|
|
break;
|
|
|
|
case '\n': // 0x0D
|
|
|
|
toAppend= TQString::tqfromLatin1("<br/>");
|
|
|
|
break;
|
|
|
|
case 0x0D: // Italics: ^N
|
|
|
|
toAppend = toggleTag("i");
|
|
|
|
break;
|
|
|
|
case 0x0F: //Plain Text, close all tags: ^O
|
|
|
|
toAppend = popAll();
|
|
|
|
break;
|
|
|
|
// case 0x12: // Reverse original text colors: ^R
|
|
|
|
// break;
|
|
|
|
case 0x16: //Invert Colors: ^V
|
|
|
|
swap(fgColor, bgColor);
|
|
|
|
toAppend = pushColorTag(fgColor, bgColor);
|
|
|
|
break;
|
|
|
|
case 0x1F: //Underline
|
|
|
|
toAppend = toggleTag("u");
|
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
toAppend = TQString::tqfromLatin1("<");
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
toAppend = TQString::tqfromLatin1(">");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (cur < TQChar(' ')) // search for control characters
|
|
|
|
toAppend = TQString::tqfromLatin1("<%1>").tqarg(cur, 2, 16).upper();
|
|
|
|
else
|
|
|
|
toAppend = TQStyleSheet::escape(cur);
|
|
|
|
}
|
|
|
|
|
|
|
|
chars += toAppend.length();
|
|
|
|
buff.writeBlock( toAppend.latin1(), toAppend.length() );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString toAppend = popAll();
|
|
|
|
chars += toAppend.length();
|
|
|
|
buff.writeBlock( toAppend.latin1(), toAppend.length() );
|
|
|
|
|
|
|
|
// Make sure we have enough room for NULL character.
|
|
|
|
if (data.size() < chars+1)
|
|
|
|
data.resize(chars+1);
|
|
|
|
|
|
|
|
data[chars] = '\0';
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KSParser::pushTag(const TQString &tag, const TQString &attributes)
|
|
|
|
{
|
|
|
|
TQString res;
|
|
|
|
m_tags.push(tag);
|
|
|
|
if(!m_attributes.tqcontains(tag))
|
|
|
|
m_attributes.insert(tag, attributes);
|
|
|
|
else if(!attributes.isEmpty())
|
|
|
|
m_attributes.tqreplace(tag, attributes);
|
|
|
|
res.append("<" + tag);
|
|
|
|
if(!m_attributes[tag].isEmpty())
|
|
|
|
res.append(" " + m_attributes[tag]);
|
|
|
|
return res + ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KSParser::pushColorTag(const TQColor &fgColor, const TQColor &bgColor)
|
|
|
|
{
|
|
|
|
TQString tagStyle;
|
|
|
|
|
|
|
|
if (fgColor.isValid())
|
|
|
|
tagStyle += TQString::tqfromLatin1("color:%1;").tqarg(fgColor.name());
|
|
|
|
if (bgColor.isValid())
|
|
|
|
tagStyle += TQString::tqfromLatin1("background-color:%1;").tqarg(bgColor.name());
|
|
|
|
|
|
|
|
if(!tagStyle.isEmpty())
|
|
|
|
tagStyle = TQString::tqfromLatin1("style=\"%1\"").tqarg(tagStyle);
|
|
|
|
|
|
|
|
return pushTag(TQString::tqfromLatin1("span"), tagStyle);;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KSParser::popTag(const TQString &tag)
|
|
|
|
{
|
|
|
|
if (!m_tags.tqcontains(tag))
|
|
|
|
return TQString();
|
|
|
|
|
|
|
|
TQString res;
|
|
|
|
TQValueStack<TQString> savedTags;
|
|
|
|
while(m_tags.top() != tag)
|
|
|
|
{
|
|
|
|
savedTags.push(m_tags.pop());
|
|
|
|
res.append("</" + savedTags.top() + ">");
|
|
|
|
}
|
|
|
|
res.append("</" + m_tags.pop() + ">");
|
|
|
|
m_attributes.remove(tag);
|
|
|
|
while(!savedTags.isEmpty())
|
|
|
|
res.append(pushTag(savedTags.pop()));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KSParser::toggleTag(const TQString &tag)
|
|
|
|
{
|
|
|
|
return m_attributes.tqcontains(tag)?popTag(tag):pushTag(tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KSParser::popAll()
|
|
|
|
{
|
|
|
|
TQString res;
|
|
|
|
while(!m_tags.isEmpty())
|
|
|
|
res.append("</" + m_tags.pop() + ">");
|
|
|
|
m_attributes.clear();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQColor KSParser::ircColor(const TQString &color)
|
|
|
|
{
|
|
|
|
bool success;
|
|
|
|
unsigned int intColor = color.toUInt(&success);
|
|
|
|
|
|
|
|
if (success)
|
|
|
|
return ircColor(intColor);
|
|
|
|
else
|
|
|
|
return TQColor();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQColor KSParser::ircColor(unsigned int color)
|
|
|
|
{
|
|
|
|
unsigned int maxcolor = sizeof(IRC_Colors)/sizeof(TQColor);
|
|
|
|
return color<=maxcolor?IRC_Colors[color]:IRC_Colors[maxcolor];
|
|
|
|
}
|
|
|
|
|
|
|
|
int KSParser::colorForHTML(const TQString &html)
|
|
|
|
{
|
|
|
|
TQColor color(html);
|
|
|
|
for(uint i=0; i<sizeof(IRC_Colors)/sizeof(TQColor); i++)
|
|
|
|
{
|
|
|
|
if(IRC_Colors[i] == color)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|