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