23 #include "linklocator.h"
24 #include "pimemoticons.h"
25 #include <tdeglobal.h>
26 #include <kstandarddirs.h>
27 #include <kstaticdeleter.h>
31 #include <tqstylesheet.h>
37 TQMap<TQString, TQString> *LinkLocator::s_smileyEmoticonNameMap = 0;
38 TQMap<TQString, TQString> *LinkLocator::s_smileyEmoticonHTMLCache = 0;
40 static KStaticDeleter< TQMap<TQString, TQString> > smileyMapDeleter;
41 static KStaticDeleter< TQMap<TQString, TQString> > smileyCacheDeleter;
44 : mText(text), mPos(pos), mMaxUrlLen(4096), mMaxAddressLen(255)
52 if ( !s_smileyEmoticonNameMap ) {
53 smileyMapDeleter.setObject( s_smileyEmoticonNameMap,
54 new TQMap<TQString, TQString>() );
55 for (
int i = 0; i < EmotIcons::EnumSindex::COUNT; ++i ) {
56 TQString imageName( EmotIcons::EnumSindex::enumToString[i] );
57 imageName.truncate( imageName.length() - 2 );
58 s_smileyEmoticonNameMap->insert( EmotIcons::smiley(i), imageName );
62 if ( !s_smileyEmoticonHTMLCache )
63 smileyCacheDeleter.setObject( s_smileyEmoticonHTMLCache,
64 new TQMap<TQString, TQString>() );
79 mMaxAddressLen = length;
84 return mMaxAddressLen;
95 TQString(
"<>()[]").find(
mText[
mPos]) == -1)
100 const TQString allowedSpecialChars = TQString(
"#/&-_");
101 while(mPos > start &&
mText[mPos-1].isPunct() &&
102 allowedSpecialChars.find(
mText[mPos-1]) == -1 )
107 url =
mText.mid(start, mPos - start);
108 if(isEmptyUrl(url) || mPos - start >
maxUrlLen())
122 bool LinkLocator::atUrl()
const
126 const TQString allowedSpecialChars = TQString(
".!#$%&'*+-/=?^_`{|}~");
131 ( allowedSpecialChars.find(
mText[
mPos-1] ) != -1 ) ) )
135 return (ch==
'h' && (
mText.mid(
mPos, 7) ==
"http://" ||
137 (ch==
'v' &&
mText.mid(
mPos, 6) ==
"vnc://") ||
138 (ch==
'f' && (
mText.mid(
mPos, 7) ==
"fish://" ||
141 (ch==
's' && (
mText.mid(
mPos, 7) ==
"sftp://" ||
143 (ch==
'm' &&
mText.mid(
mPos, 7) ==
"mailto:") ||
144 (ch==
'w' &&
mText.mid(
mPos, 4) ==
"www.") ||
145 (ch==
'f' &&
mText.mid(
mPos, 4) ==
"ftp.") ||
146 (ch==
'n' &&
mText.mid(
mPos, 5) ==
"news:");
150 bool LinkLocator::isEmptyUrl(
const TQString& url)
152 return url.isEmpty() ||
175 const TQString allowedSpecialChars = TQString(
".!#$%&'*+-/=?^_`{|}~");
178 int start =
mPos - 1;
179 while ( start >= 0 &&
mText[start].unicode() < 128 &&
180 (
mText[start].isLetterOrNumber() ||
181 mText[start] ==
'@' ||
182 allowedSpecialChars.find(
mText[start] ) != -1 ) ) {
183 if (
mText[start] ==
'@' )
189 while ( ( start <
mPos ) && !
mText[start].isLetterOrNumber() )
195 int dotPos = INT_MAX;
197 while ( end < (
int)
mText.length() &&
198 (
mText[end].isLetterOrNumber() ||
201 mText[end] ==
'-' ) ) {
202 if (
mText[end] ==
'@' )
204 if (
mText[end] ==
'.' )
205 dotPos = TQMIN( dotPos, end );
209 while ( ( end >
mPos ) && !
mText[end - 1].isLetterOrNumber() )
218 address =
mText.mid( start, end - start );
226 int maxUrlLen,
int maxAddressLen)
233 TQString result((TQChar*)0, (
int)locator.
mText.length() * 2);
236 bool startOfLine =
true;
239 for (locator.
mPos = 0, x = 0; locator.
mPos < (
int)locator.
mText.length(); locator.
mPos++, x++)
242 if ( flags & PreserveSpaces )
251 while (locator.
mText[locator.
mPos] ==
' ')
255 if (locator.
mText[locator.
mPos] ==
' ') {
295 const int start = locator.
mPos;
296 if ( !(flags & IgnoreUrls) ) {
301 if(str.left(4) ==
"www.")
302 hyperlink =
"http://" + str;
303 else if(str.left(4) ==
"ftp.")
304 hyperlink =
"ftp://" + str;
308 str = str.replace(
'&',
"&");
309 result +=
"<a href=\"" + hyperlink +
"\">" + str +
"</a>";
310 x += locator.
mPos - start;
317 int len = str.find(
'@');
318 TQString localPart = str.left(len);
322 result.truncate(result.length() - len - (localPart.contains(
'&')*4));
325 result +=
"<a href=\"mailto:" + str +
"\">" + str +
"</a>";
326 x += str.length() - 1;
330 if ( flags & ReplaceSmileys ) {
331 str = locator.getEmoticon();
332 if ( ! str.isEmpty() ) {
334 x += locator.
mPos - start;
338 if ( flags & HighlightText ) {
339 str = locator.highlightedText();
340 if ( !str.isEmpty() ) {
342 x += locator.
mPos - start;
355 if ( iconPath.isEmpty() )
358 TQFile pngFile( iconPath );
359 if ( !pngFile.open( IO_ReadOnly | IO_Raw ) )
362 TQByteArray ba = pngFile.readAll();
364 return TQString::fromLatin1(
"data:image/png;base64,%1")
365 .arg( KCodecs::base64Encode( ba ).data() );
369 TQString LinkLocator::getEmoticon()
377 if ( ch !=
':' && ch !=
';' && ch !=
'(' && ch !=
'8' )
382 const int MinSmileyLen = 2;
383 const int MaxSmileyLen = 4;
385 while ( ( smileyLen <= MaxSmileyLen ) &&
386 (
mPos+smileyLen < (
int)
mText.length() ) &&
389 if ( smileyLen < MinSmileyLen || smileyLen > MaxSmileyLen )
392 const TQString smiley =
mText.mid(
mPos, smileyLen );
393 if ( !s_smileyEmoticonNameMap->contains( smiley ) )
397 if ( s_smileyEmoticonHTMLCache->contains( smiley ) ) {
398 htmlRep = (*s_smileyEmoticonHTMLCache)[smiley];
401 const TQString imageName = (*s_smileyEmoticonNameMap)[smiley];
403 #if KDE_IS_VERSION( 3, 3, 91 )
404 const TQString iconPath = locate(
"emoticons",
406 TQString::fromLatin1(
"/" ) +
407 imageName + TQString::fromLatin1(
".png") );
409 const TQString iconPath = locate(
"data",
410 TQString::fromLatin1(
"kopete/pics/emoticons/" )+
412 TQString::fromLatin1(
"/" ) +
413 imageName + TQString::fromLatin1(
".png") );
417 if ( dataUrl.isEmpty() ) {
418 htmlRep = TQString();
423 htmlRep = TQString(
"<img class=\"pimsmileyimg\" src=\"%1\" "
424 "alt=\"%2\" title=\"%3\" width=\"16\" height=\"16\"/>")
426 TQStyleSheet::escape( smiley ),
427 TQStyleSheet::escape( smiley ) );
429 s_smileyEmoticonHTMLCache->insert( smiley, htmlRep );
432 if ( !htmlRep.isEmpty() )
433 mPos += smileyLen - 1;
438 TQString LinkLocator::highlightedText()
445 if ( ch !=
'/' && ch !=
'*' && ch !=
'_' )
448 TQRegExp re = TQRegExp( TQString(
"\\%1([0-9A-Za-z]+)\\%2").arg( ch ).arg( ch ) );
450 uint length = re.matchedLength();
455 switch ( ch.latin1() ) {
457 return "<b>" + re.cap( 1 ) +
"</b>";
459 return "<u>" + re.cap( 1 ) +
"</u>";
461 return "<i>" + re.cap( 1 ) +
"</i>";