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