23 #include "linklocator.h"
24 #include "pimemoticons.h"
25 #include <tdeversion.h>
26 #include <tdeglobal.h>
27 #include <kstandarddirs.h>
28 #include <kstaticdeleter.h>
32 #include <tqstylesheet.h>
38 TQMap<TQString, TQString> *LinkLocator::s_smileyEmoticonNameMap = 0;
39 TQMap<TQString, TQString> *LinkLocator::s_smileyEmoticonHTMLCache = 0;
41 static KStaticDeleter< TQMap<TQString, TQString> > smileyMapDeleter;
42 static KStaticDeleter< TQMap<TQString, TQString> > smileyCacheDeleter;
45 : mText(text), mPos(pos), mMaxUrlLen(4096), mMaxAddressLen(255)
53 if ( !s_smileyEmoticonNameMap ) {
54 smileyMapDeleter.setObject( s_smileyEmoticonNameMap,
55 new TQMap<TQString, TQString>() );
56 for (
int i = 0; i < EmotIcons::EnumSindex::COUNT; ++i ) {
57 TQString imageName( EmotIcons::EnumSindex::enumToString[i] );
58 imageName.truncate( imageName.length() - 2 );
59 s_smileyEmoticonNameMap->insert( EmotIcons::smiley(i), imageName );
63 if ( !s_smileyEmoticonHTMLCache )
64 smileyCacheDeleter.setObject( s_smileyEmoticonHTMLCache,
65 new TQMap<TQString, TQString>() );
80 mMaxAddressLen = length;
85 return mMaxAddressLen;
96 TQString(
"<>()[]").find(
mText[
mPos]) == -1)
101 const TQString allowedSpecialChars = TQString(
"#/&-_");
103 allowedSpecialChars.find(
mText[
mPos-1]) == -1 )
123 bool LinkLocator::atUrl()
const
127 const TQString allowedSpecialChars = TQString(
".!#$%&'*+-/=?^_`{|}~");
132 ( allowedSpecialChars.find(
mText[
mPos-1] ) != -1 ) ) )
136 return (ch==
'h' && (
mText.mid(
mPos, 7) ==
"http://" ||
138 (ch==
'v' &&
mText.mid(
mPos, 6) ==
"vnc://") ||
139 (ch==
'f' && (
mText.mid(
mPos, 7) ==
"fish://" ||
142 (ch==
's' && (
mText.mid(
mPos, 7) ==
"sftp://" ||
144 (ch==
'm' &&
mText.mid(
mPos, 7) ==
"mailto:") ||
145 (ch==
'w' &&
mText.mid(
mPos, 4) ==
"www.") ||
146 (ch==
'f' &&
mText.mid(
mPos, 4) ==
"ftp.") ||
147 (ch==
'n' &&
mText.mid(
mPos, 5) ==
"news:");
151 bool LinkLocator::isEmptyUrl(
const TQString& url)
153 return url.isEmpty() ||
176 const TQString allowedSpecialChars = TQString(
".!#$%&'*+-/=?^_`{|}~");
179 int start =
mPos - 1;
180 while ( start >= 0 &&
mText[start].unicode() < 128 &&
181 (
mText[start].isLetterOrNumber() ||
182 mText[start] ==
'@' ||
183 allowedSpecialChars.find(
mText[start] ) != -1 ) ) {
184 if (
mText[start] ==
'@' )
190 while ( ( start <
mPos ) && !
mText[start].isLetterOrNumber() )
196 int dotPos = INT_MAX;
198 while ( end < (
int)
mText.length() &&
199 (
mText[end].isLetterOrNumber() ||
202 mText[end] ==
'-' ) ) {
203 if (
mText[end] ==
'@' )
205 if (
mText[end] ==
'.' )
206 dotPos = TQMIN( dotPos, end );
210 while ( ( end >
mPos ) && !
mText[end - 1].isLetterOrNumber() )
219 address =
mText.mid( start, end - start );
227 int maxUrlLen,
int maxAddressLen)
234 TQString result((TQChar*)0, (
int)locator.
mText.length() * 2);
237 bool startOfLine =
true;
240 for (locator.
mPos = 0, x = 0; locator.
mPos < (
int)locator.
mText.length(); locator.
mPos++, x++)
243 if ( flags & PreserveSpaces )
252 while (locator.
mText[locator.
mPos] ==
' ')
256 if (locator.
mText[locator.
mPos] ==
' ') {
296 const int start = locator.
mPos;
297 if ( !(flags & IgnoreUrls) ) {
302 if(str.left(4) ==
"www.")
303 hyperlink =
"http://" + str;
304 else if(str.left(4) ==
"ftp.")
305 hyperlink =
"ftp://" + str;
309 str = str.replace(
'&',
"&");
310 result +=
"<a href=\"" + hyperlink +
"\">" + str +
"</a>";
311 x += locator.
mPos - start;
318 int len = str.find(
'@');
319 TQString localPart = str.left(len);
323 result.truncate(result.length() - len - (localPart.contains(
'&')*4));
326 result +=
"<a href=\"mailto:" + str +
"\">" + str +
"</a>";
327 x += str.length() - 1;
331 if ( flags & ReplaceSmileys ) {
332 str = locator.getEmoticon();
333 if ( ! str.isEmpty() ) {
335 x += locator.
mPos - start;
339 if ( flags & HighlightText ) {
340 str = locator.highlightedText();
341 if ( !str.isEmpty() ) {
343 x += locator.
mPos - start;
356 if ( iconPath.isEmpty() )
359 TQFile pngFile( iconPath );
360 if ( !pngFile.open( IO_ReadOnly | IO_Raw ) )
363 TQByteArray ba = pngFile.readAll();
365 return TQString::fromLatin1(
"data:image/png;base64,%1")
366 .arg( KCodecs::base64Encode( ba ).data() );
370 TQString LinkLocator::getEmoticon()
378 if ( ch !=
':' && ch !=
';' && ch !=
'(' && ch !=
'8' )
383 const int MinSmileyLen = 2;
384 const int MaxSmileyLen = 4;
386 while ( ( smileyLen <= MaxSmileyLen ) &&
387 (
mPos+smileyLen < (
int)
mText.length() ) &&
390 if ( smileyLen < MinSmileyLen || smileyLen > MaxSmileyLen )
393 const TQString smiley =
mText.mid(
mPos, smileyLen );
394 if ( !s_smileyEmoticonNameMap->contains( smiley ) )
398 if ( s_smileyEmoticonHTMLCache->contains( smiley ) ) {
399 htmlRep = (*s_smileyEmoticonHTMLCache)[smiley];
402 const TQString imageName = (*s_smileyEmoticonNameMap)[smiley];
404 #if KDE_IS_VERSION( 3, 3, 91 )
405 const TQString iconPath = locate(
"emoticons",
407 TQString::fromLatin1(
"/" ) +
408 imageName + TQString::fromLatin1(
".png") );
410 const TQString iconPath = locate(
"data",
411 TQString::fromLatin1(
"kopete/pics/emoticons/" )+
413 TQString::fromLatin1(
"/" ) +
414 imageName + TQString::fromLatin1(
".png") );
418 if ( dataUrl.isEmpty() ) {
419 htmlRep = TQString();
424 htmlRep = TQString(
"<img class=\"pimsmileyimg\" src=\"%1\" "
425 "alt=\"%2\" title=\"%3\" width=\"16\" height=\"16\"/>")
427 TQStyleSheet::escape( smiley ),
428 TQStyleSheet::escape( smiley ) );
430 s_smileyEmoticonHTMLCache->insert( smiley, htmlRep );
433 if ( !htmlRep.isEmpty() )
434 mPos += smileyLen - 1;
439 TQString LinkLocator::highlightedText()
446 if ( ch !=
'/' && ch !=
'*' && ch !=
'_' )
449 TQRegExp re = TQRegExp( TQString(
"\\%1([0-9A-Za-z]+)\\%2").arg( ch ).arg( ch ) );
451 uint length = re.matchedLength();
456 switch ( ch.latin1() ) {
458 return "<b>" + re.cap( 1 ) +
"</b>";
460 return "<u>" + re.cap( 1 ) +
"</u>";
462 return "<i>" + re.cap( 1 ) +
"</i>";