23#include "linklocator.h"
24#include "pimemoticons.h"
26#include <tdestandarddirs.h>
27#include <kstaticdeleter.h>
31#include <tqstylesheet.h>
37TQMap<TQString, TQString> *LinkLocator::s_smileyEmoticonNameMap = 0;
38TQMap<TQString, TQString> *LinkLocator::s_smileyEmoticonHTMLCache = 0;
40static KStaticDeleter< TQMap<TQString, TQString> > smileyMapDeleter;
41static 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(
"#/&-_");
102 allowedSpecialChars.find(
mText[
mPos-1]) == -1 )
122bool 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:");
150bool 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() );
369TQString 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];
402 const TQString iconPath = locate(
"emoticons",
404 TQString::fromLatin1(
"/" ) +
405 imageName + TQString::fromLatin1(
".png") );
407 if ( dataUrl.isEmpty() ) {
408 htmlRep = TQString();
413 htmlRep = TQString(
"<img class=\"pimsmileyimg\" src=\"%1\" "
414 "alt=\"%2\" title=\"%3\" width=\"16\" height=\"16\"/>")
416 TQStyleSheet::escape( smiley ),
417 TQStyleSheet::escape( smiley ) );
419 s_smileyEmoticonHTMLCache->insert( smiley, htmlRep );
422 if ( !htmlRep.isEmpty() )
423 mPos += smileyLen - 1;
428TQString LinkLocator::highlightedText()
435 if ( ch !=
'/' && ch !=
'*' && ch !=
'_' )
438 TQRegExp re = TQRegExp( TQString(
"\\%1([0-9A-Za-z]+)\\%2").arg( ch ).arg( ch ) );
440 uint length = re.matchedLength();
445 switch ( ch.latin1() ) {
447 return "<b>" + re.cap( 1 ) +
"</b>";
449 return "<u>" + re.cap( 1 ) +
"</u>";
451 return "<i>" + re.cap( 1 ) +
"</i>";
LinkLocator assists in identifying sections of text that can usefully be converted in hyperlinks in h...
int maxAddressLen() const
TQString getEmailAddress()
Attempts to grab an email address.
void setMaxUrlLen(int length)
Sets the maximum length of URLs that will be matched by getUrl().
static TQString pngToDataUrl(const TQString &iconPath)
Embed the given PNG image into a data URL.
void setMaxAddressLen(int length)
Sets the maximum length of email addresses that will be matched by getEmailAddress().
static TQString convertToHtml(const TQString &plainText, int flags=0, int maxUrlLen=4096, int maxAddressLen=255)
Converts plaintext into html.
int mPos
The current scan position.
LinkLocator(const TQString &text, int pos=0)
Constructs a LinkLocator that will search a plaintext string from a given starting point.
TQString mText
The plaintext string being scanned for URLs and email addresses.
TQString getUrl()
Attempts to grab a URL starting at the current scan position.