• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kstringhandler.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 1999 Ian Zepp (icszepp@islc.net)
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
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     // Format in: START:END
00047     // Note index starts a 0 (zero)
00048     //
00049     // 0:        first word to end
00050     // 1:3        second to fourth words
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     // Extract words
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 // Insertion and removal routines
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     // Split words and add into list
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     // Rejoin
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     // Split words and add into list
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     // Rejoin
00119     return list.join( " " );
00120 }
00121 
00122 QString KStringHandler::remrange( const QString &text , const char *range )
00123 {
00124     // Format in: START:END
00125     // Note index starts a 0 (zero)
00126     //
00127     // 0:        first word to end
00128     // 1:3        second to fourth words
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     // Remove that range of words
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     // Split words and add into list
00159     QStringList list = QStringList::split( " ", text, true );
00160 
00161     if ( pos < list.count() )
00162         list.remove( list.at( pos ) );
00163 
00164     // Rejoin
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     // Split words and add into list
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     // Rejoin
00187     return list.join( " " );
00188 }
00189 
00190 //
00191 // Capitalization routines
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 // Reverse routines
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 // Left, Right, Center justification
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); // no max
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    // Patterns like "Makefile*"
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    // Patterns like "*~", "*.extension"
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    // Patterns like "Makefile"
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     /*static*/ 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         // Qt doesn't support (?<=pattern) so we do it here
00542         if((urlPos > 0) && richText[urlPos-1].isLetterOrNumber()){
00543             urlPos++;
00544             continue;
00545         }
00546         // Don't use QString::arg since %01, %20, etc could be in the string
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; // whatever, just don't crash
00575 
00576 #define F 0   /* character never appears in text */
00577 #define T 1   /* character appears in plain ASCII text */
00578 #define I 2   /* character appears in ISO-8859 text */
00579 #define X 3   /* character appears in non-ISO extended ASCII (Mac, IBM PC) */
00580 
00581   static const unsigned char text_chars[256] = {
00582         /*                  BEL BS HT LF    FF CR    */
00583         F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F,  /* 0x0X */
00584         /*                              ESC          */
00585         F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F,  /* 0x1X */
00586         T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,  /* 0x2X */
00587         T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,  /* 0x3X */
00588         T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,  /* 0x4X */
00589         T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,  /* 0x5X */
00590         T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,  /* 0x6X */
00591         T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F,  /* 0x7X */
00592         /*            NEL                            */
00593         X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X,  /* 0x8X */
00594         X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,  /* 0x9X */
00595         I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,  /* 0xaX */
00596         I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,  /* 0xbX */
00597         I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,  /* 0xcX */
00598         I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,  /* 0xdX */
00599         I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,  /* 0xeX */
00600         I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I   /* 0xfX */
00601   };
00602 
00603   /* *ulen = 0; */
00604   for (i = 0; (c = buf[i]); i++) {
00605     if ((c & 0x80) == 0) {        /* 0xxxxxxx is plain ASCII */
00606       /*
00607        * Even if the whole file is valid UTF-8 sequences,
00608        * still reject it if it uses weird control characters.
00609        */
00610 
00611       if (text_chars[c] != T)
00612         return false;
00613 
00614     } else if ((c & 0x40) == 0) { /* 10xxxxxx never 1st byte */
00615       return false;
00616     } else {                           /* 11xxxxxx begins UTF-8 */
00617       int following;
00618 
00619     if ((c & 0x20) == 0) {             /* 110xxxxx */
00620       following = 1;
00621     } else if ((c & 0x10) == 0) {      /* 1110xxxx */
00622       following = 2;
00623     } else if ((c & 0x08) == 0) {      /* 11110xxx */
00624       following = 3;
00625     } else if ((c & 0x04) == 0) {      /* 111110xx */
00626       following = 4;
00627     } else if ((c & 0x02) == 0) {      /* 1111110x */
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;   /* don't claim it's UTF-8 if it's all 7-bit */
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 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal