00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023
00024 #include "kstringhandler.h"
00025 #include "kglobal.h"
00026
00027 static void parsePythonRange( const QCString &range, uint &start, uint &end )
00028 {
00029 const int colon = range.find( ':' );
00030 if ( colon == -1 ) {
00031 start = range.toUInt();
00032 end = start;
00033 } else if ( colon == int( range.length() - 1 ) ) {
00034 start = range.left( colon ).toUInt();
00035 } else if ( colon == 0 ) {
00036 end = range.mid( 1 ).toUInt();
00037 } else {
00038 start = range.left( colon ).toInt();
00039 end = range.mid( colon + 1 ).toInt();
00040 }
00041 }
00042
00043 QString KStringHandler::word( const QString &text , uint pos )
00044 {
00045 return text.section( ' ', pos, pos );
00046 }
00047
00048 QString KStringHandler::word( const QString &text , const char *range )
00049 {
00050
00051
00052
00053
00054
00055 QStringList list = QStringList::split( " ", text , true );
00056 QString tmp = "";
00057 QString r = range;
00058
00059 if ( text.isEmpty() )
00060 return tmp;
00061
00062 uint pos = 0, cnt = list.count();
00063 parsePythonRange( range, pos, cnt );
00064
00065
00066
00067
00068 int wordsToExtract = cnt-pos+1;
00069 QStringList::Iterator it = list.at( pos);
00070
00071 while ( (it != list.end()) && (wordsToExtract-- > 0))
00072 {
00073 tmp += *it;
00074 tmp += " ";
00075 it++;
00076 }
00077
00078 return tmp.stripWhiteSpace();
00079 }
00080
00081
00082
00083
00084 QString KStringHandler::insword( const QString &text , const QString &word , uint pos )
00085 {
00086 if ( text.isEmpty() )
00087 return word;
00088
00089 if ( word.isEmpty() )
00090 return text;
00091
00092
00093 QStringList list = QStringList::split( " ", text, true );
00094
00095 if ( pos >= list.count() )
00096 list.append( word );
00097 else
00098 list.insert( list.at(pos) , word );
00099
00100
00101 return list.join( " " );
00102 }
00103
00104 QString KStringHandler::setword( const QString &text , const QString &word , uint pos )
00105 {
00106 if ( text.isEmpty() )
00107 return word;
00108
00109 if ( word.isEmpty() )
00110 return text;
00111
00112
00113 QStringList list = QStringList::split( " ", text, true );
00114
00115 if ( pos >= list.count() )
00116 list.append( word );
00117 else
00118 {
00119 list.insert( list.remove( list.at(pos) ) , word );
00120 }
00121
00122
00123 return list.join( " " );
00124 }
00125
00126 QString KStringHandler::remrange( const QString &text , const char *range )
00127 {
00128
00129
00130
00131
00132
00133 QStringList list = QStringList::split( " ", text , true );
00134 QString tmp = "";
00135 QString r = range;
00136
00137 if ( text.isEmpty() )
00138 return tmp;
00139
00140 uint pos = 0, cnt = list.count();
00141 parsePythonRange( range, pos, cnt );
00142
00143
00144
00145
00146 int wordsToDelete = cnt-pos+1;
00147 QStringList::Iterator it = list.at( pos);
00148
00149 while ( (it != list.end()) && (wordsToDelete-- > 0))
00150 it = list.remove( it );
00151
00152 return list.join( " " );
00153 }
00154
00155 QString KStringHandler::remword( const QString &text , uint pos )
00156 {
00157 QString tmp = "";
00158
00159 if ( text.isEmpty() )
00160 return tmp;
00161
00162
00163 QStringList list = QStringList::split( " ", text, true );
00164
00165 if ( pos < list.count() )
00166 list.remove( list.at( pos ) );
00167
00168
00169 return list.join( " " );
00170 }
00171
00172 QString KStringHandler::remword( const QString &text , const QString &word )
00173 {
00174 QString tmp = "";
00175
00176 if ( text.isEmpty() )
00177 return tmp;
00178
00179 if ( word.isEmpty() )
00180 return text;
00181
00182
00183 QStringList list = QStringList::split( " ", text, true );
00184
00185 QStringList::Iterator it = list.find(word);
00186
00187 if (it != list.end())
00188 list.remove( it );
00189
00190
00191 return list.join( " " );
00192 }
00193
00194
00195
00196
00197 QString KStringHandler::capwords( const QString &text )
00198 {
00199 if ( text.isEmpty() ) {
00200 return text;
00201 }
00202
00203 const QString strippedText = text.stripWhiteSpace();
00204 const QStringList words = capwords( QStringList::split( ' ', strippedText ) );
00205
00206 QString result = text;
00207 result.replace( strippedText, words.join( " " ) );
00208 return result;
00209 }
00210
00211 QStringList KStringHandler::capwords( const QStringList &list )
00212 {
00213 QStringList tmp = list;
00214 for ( QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it ) {
00215 *it = ( *it )[ 0 ].upper() + ( *it ).mid( 1 );
00216 }
00217 return tmp;
00218 }
00219
00220
00221
00222
00223 QString KStringHandler::reverse( const QString &text )
00224 {
00225 QString tmp;
00226
00227 if ( text.isEmpty() )
00228 return tmp;
00229
00230 QStringList list;
00231 list = QStringList::split( " ", text, true );
00232 list = reverse( list );
00233
00234 return list.join( " " );
00235 }
00236
00237 QStringList KStringHandler::reverse( const QStringList &list )
00238 {
00239 QStringList tmp;
00240
00241 if ( list.count() == 0 )
00242 return tmp;
00243
00244 for ( QStringList::ConstIterator it= list.begin();
00245 it != list.end();
00246 it++)
00247 tmp.prepend( *it );
00248
00249 return tmp;
00250 }
00251
00252
00253
00254
00255 QString KStringHandler::ljust( const QString &text , uint width )
00256 {
00257 return text.stripWhiteSpace().leftJustify( width );
00258 }
00259
00260 QString KStringHandler::rjust( const QString &text , uint width )
00261 {
00262 return text.stripWhiteSpace().rightJustify( width );
00263 }
00264
00265 QString KStringHandler::center( const QString &text , uint width )
00266 {
00267 const QString s = text.stripWhiteSpace();
00268 const unsigned int length = s.length();
00269 if ( width <= length ) {
00270 return s;
00271 }
00272
00273 QString result;
00274 result.fill( ' ', ( width - length ) / 2 );
00275 result += s;
00276
00277 return result.leftJustify( width );
00278 }
00279
00280 QString KStringHandler::lsqueeze( const QString & str, uint maxlen )
00281 {
00282 if (str.length() > maxlen) {
00283 int part = maxlen-3;
00284 return QString("..." + str.right(part));
00285 }
00286 else return str;
00287 }
00288
00289 QString KStringHandler::csqueeze( const QString & str, uint maxlen )
00290 {
00291 if (str.length() > maxlen && maxlen > 3) {
00292 int part = (maxlen-3)/2;
00293 return QString(str.left(part) + "..." + str.right(part));
00294 }
00295 else return str;
00296 }
00297
00298 QString KStringHandler::rsqueeze( const QString & str, uint maxlen )
00299 {
00300 if (str.length() > maxlen) {
00301 int part = maxlen-3;
00302 return QString(str.left(part) + "...");
00303 }
00304 else return str;
00305 }
00306
00307 QString KStringHandler::lEmSqueeze(const QString &name, const QFontMetrics& fontMetrics, uint maxlen)
00308 {
00309 return lPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
00310 }
00311
00312 QString KStringHandler::lPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
00313 {
00314 uint nameWidth = fontMetrics.width(name);
00315
00316 if (maxPixels < nameWidth)
00317 {
00318 QString tmp = name;
00319 const uint em = fontMetrics.maxWidth();
00320 maxPixels -= fontMetrics.width("...");
00321
00322 while (maxPixels < nameWidth && !tmp.isEmpty())
00323 {
00324 int delta = (nameWidth - maxPixels) / em;
00325 delta = kClamp(delta, 1, delta);
00326
00327 tmp.remove(0, delta);
00328 nameWidth = fontMetrics.width(tmp);
00329 }
00330
00331 return ("..." + tmp);
00332 }
00333
00334 return name;
00335 }
00336
00337 QString KStringHandler::cEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen)
00338 {
00339 return cPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
00340 }
00341
00342 QString KStringHandler::cPixelSqueeze(const QString& s, const QFontMetrics& fm, uint width)
00343 {
00344 if ( s.isEmpty() || uint( fm.width( s ) ) <= width ) {
00345 return s;
00346 }
00347
00348 const unsigned int length = s.length();
00349 if ( length == 2 ) {
00350 return s;
00351 }
00352
00353 const int maxWidth = width - fm.width( '.' ) * 3;
00354 if ( maxWidth <= 0 ) {
00355 return "...";
00356 }
00357
00358 unsigned int leftIdx = 0, rightIdx = length;
00359 unsigned int leftWidth = fm.charWidth( s, leftIdx++ );
00360 unsigned int rightWidth = fm.charWidth( s, --rightIdx );
00361 while ( leftWidth + rightWidth < uint( maxWidth ) ) {
00362 while ( leftWidth <= rightWidth && leftWidth + rightWidth < uint( maxWidth ) ) {
00363 leftWidth += fm.charWidth( s, leftIdx++ );
00364 }
00365 while ( rightWidth <= leftWidth && leftWidth + rightWidth < uint( maxWidth ) ) {
00366 rightWidth += fm.charWidth( s, --rightIdx );
00367 }
00368 }
00369
00370 if ( leftWidth > rightWidth ) {
00371 --leftIdx;
00372 } else {
00373 ++rightIdx;
00374 }
00375
00376 rightIdx = length - rightIdx;
00377 if ( leftIdx == 0 && rightIdx == 1 || leftIdx == 1 && rightIdx == 0 ) {
00378 return "...";
00379 }
00380
00381 return s.left( leftIdx ) + "..." + s.right( rightIdx );
00382 }
00383
00384 QString KStringHandler::rEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen)
00385 {
00386 return rPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
00387 }
00388
00389 QString KStringHandler::rPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
00390 {
00391 uint nameWidth = fontMetrics.width(name);
00392
00393 if (maxPixels < nameWidth)
00394 {
00395 QString tmp = name;
00396 const uint em = fontMetrics.maxWidth();
00397 maxPixels -= fontMetrics.width("...");
00398
00399 while (maxPixels < nameWidth && !tmp.isEmpty())
00400 {
00401 int length = tmp.length();
00402 int delta = (nameWidth - maxPixels) / em;
00403 delta = kClamp(delta, 1, length) ;
00404
00405 tmp.remove(length - delta, delta);
00406 nameWidth = fontMetrics.width(tmp);
00407 }
00408
00409 return (tmp + "...");
00410 }
00411
00412 return name;
00413 }
00414
00416
00417 bool KStringHandler::matchFileName( const QString& filename, const QString& pattern )
00418 {
00419 int len = filename.length();
00420 int pattern_len = pattern.length();
00421
00422 if (!pattern_len)
00423 return false;
00424
00425
00426 if ( pattern[ pattern_len - 1 ] == '*' && len + 1 >= pattern_len ) {
00427 if ( pattern[ 0 ] == '*' )
00428 {
00429 return filename.find(pattern.mid(1, pattern_len - 2)) != -1;
00430 }
00431
00432 const QChar *c1 = pattern.unicode();
00433 const QChar *c2 = filename.unicode();
00434 int cnt = 1;
00435 while ( cnt < pattern_len && *c1++ == *c2++ )
00436 ++cnt;
00437 return cnt == pattern_len;
00438 }
00439
00440
00441 if ( pattern[ 0 ] == '*' && len + 1 >= pattern_len )
00442 {
00443 const QChar *c1 = pattern.unicode() + pattern_len - 1;
00444 const QChar *c2 = filename.unicode() + len - 1;
00445 int cnt = 1;
00446 while ( cnt < pattern_len && *c1-- == *c2-- )
00447 ++cnt;
00448 return cnt == pattern_len;
00449 }
00450
00451
00452 return ( filename == pattern );
00453 }
00454
00455 QStringList
00456 KStringHandler::perlSplit(const QString & sep, const QString & s, uint max)
00457 {
00458 bool ignoreMax = 0 == max;
00459
00460 QStringList l;
00461
00462 int searchStart = 0;
00463
00464 int tokenStart = s.find(sep, searchStart);
00465
00466 while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
00467 {
00468 if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
00469 l << s.mid(searchStart, tokenStart - searchStart);
00470
00471 searchStart = tokenStart + sep.length();
00472 tokenStart = s.find(sep, searchStart);
00473 }
00474
00475 if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
00476 l << s.mid(searchStart, s.length() - searchStart);
00477
00478 return l;
00479 }
00480
00481 QStringList
00482 KStringHandler::perlSplit(const QChar & sep, const QString & s, uint max)
00483 {
00484 bool ignoreMax = 0 == max;
00485
00486 QStringList l;
00487
00488 int searchStart = 0;
00489
00490 int tokenStart = s.find(sep, searchStart);
00491
00492 while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
00493 {
00494 if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
00495 l << s.mid(searchStart, tokenStart - searchStart);
00496
00497 searchStart = tokenStart + 1;
00498 tokenStart = s.find(sep, searchStart);
00499 }
00500
00501 if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
00502 l << s.mid(searchStart, s.length() - searchStart);
00503
00504 return l;
00505 }
00506
00507 QStringList
00508 KStringHandler::perlSplit(const QRegExp & sep, const QString & s, uint max)
00509 {
00510 bool ignoreMax = 0 == max;
00511
00512 QStringList l;
00513
00514 int searchStart = 0;
00515 int tokenStart = sep.search(s, searchStart);
00516 int len = sep.matchedLength();
00517
00518 while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
00519 {
00520 if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
00521 l << s.mid(searchStart, tokenStart - searchStart);
00522
00523 searchStart = tokenStart + len;
00524 tokenStart = sep.search(s, searchStart);
00525 len = sep.matchedLength();
00526 }
00527
00528 if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
00529 l << s.mid(searchStart, s.length() - searchStart);
00530
00531 return l;
00532 }
00533
00534 QString
00535 KStringHandler::tagURLs( const QString& text )
00536 {
00537 QRegExp urlEx("(www\\.(?!\\.)|(fish|(f|ht)tp(|s))://)[\\d\\w\\./,:_~\\?=&;#@\\-\\+\\%]+[\\d\\w/]");
00538
00539 QString richText( text );
00540 int urlPos = 0, urlLen;
00541 while ((urlPos = urlEx.search(richText, urlPos)) >= 0)
00542 {
00543 urlLen = urlEx.matchedLength();
00544 QString href = richText.mid( urlPos, urlLen );
00545
00546 if((urlPos > 0) && richText[urlPos-1].isLetterOrNumber()){
00547 urlPos++;
00548 continue;
00549 }
00550
00551 QString anchor = "<a href=\"" + href + "\">" + href + "</a>";
00552 richText.replace( urlPos, urlLen, anchor );
00553
00554
00555 urlPos += anchor.length();
00556 }
00557 return richText;
00558 }
00559
00560 QString KStringHandler::obscure( const QString &str )
00561 {
00562 QString result;
00563 const QChar *unicode = str.unicode();
00564 for ( uint i = 0; i < str.length(); ++i )
00565 result += ( unicode[ i ].unicode() < 0x20 ) ? unicode[ i ] :
00566 QChar( 0x1001F - unicode[ i ].unicode() );
00567
00568 return result;
00569 }
00570
00571 bool KStringHandler::isUtf8(const char *buf)
00572 {
00573 int i, n;
00574 register unsigned char c;
00575 bool gotone = false;
00576
00577 if (!buf)
00578 return true;
00579
00580 #define F 0
00581 #define T 1
00582 #define I 2
00583 #define X 3
00584
00585 static const unsigned char text_chars[256] = {
00586
00587 F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F,
00588
00589 F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F,
00590 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
00591 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
00592 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
00593 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
00594 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
00595 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F,
00596
00597 X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X,
00598 X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
00599 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
00600 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
00601 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
00602 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
00603 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
00604 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I
00605 };
00606
00607
00608 for (i = 0; (c = buf[i]); i++) {
00609 if ((c & 0x80) == 0) {
00610
00611
00612
00613
00614
00615 if (text_chars[c] != T)
00616 return false;
00617
00618 } else if ((c & 0x40) == 0) {
00619 return false;
00620 } else {
00621 int following;
00622
00623 if ((c & 0x20) == 0) {
00624 following = 1;
00625 } else if ((c & 0x10) == 0) {
00626 following = 2;
00627 } else if ((c & 0x08) == 0) {
00628 following = 3;
00629 } else if ((c & 0x04) == 0) {
00630 following = 4;
00631 } else if ((c & 0x02) == 0) {
00632 following = 5;
00633 } else
00634 return false;
00635
00636 for (n = 0; n < following; n++) {
00637 i++;
00638 if (!(c = buf[i]))
00639 goto done;
00640
00641 if ((c & 0x80) == 0 || (c & 0x40))
00642 return false;
00643 }
00644 gotone = true;
00645 }
00646 }
00647 done:
00648 return gotone;
00649 }
00650
00651 #undef F
00652 #undef T
00653 #undef I
00654 #undef X
00655
00656 QString KStringHandler::from8Bit( const char *str )
00657 {
00658 if (!str)
00659 return QString::null;
00660 if (!*str) {
00661 static const QString &emptyString = KGlobal::staticQString("");
00662 return emptyString;
00663 }
00664 return KStringHandler::isUtf8( str ) ?
00665 QString::fromUtf8( str ) :
00666 QString::fromLocal8Bit( str );
00667 }