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

KIO

kshellcompletion.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2000 David Smith <dsmith@algonet.se>
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 "kshellcompletion.h"
00021 
00022 #include <stdlib.h>
00023 #include <kdebug.h>
00024 #include <QtCore/QCharRef>
00025 #include <QtCore/QMutableStringListIterator>
00026 #include <QtCore/QRegExp>
00027 #include <kcompletion.h>
00028 
00029 class KShellCompletionPrivate
00030 {
00031 public:
00032     KShellCompletionPrivate()
00033         : m_word_break_char(' ')
00034         , m_quote_char1( '\"' )
00035         , m_quote_char2( '\'' )
00036         , m_escape_char( '\\' )
00037     {
00038     }
00039 
00040     void splitText(const QString &text, QString &text_start, QString &text_compl) const;
00041     bool quoteText(QString *text, bool force, bool skip_last) const;
00042     QString unquote(const QString &text) const;
00043 
00044     QString m_text_start; // part of the text that was not completed
00045     QString m_text_compl; // part of the text that was completed (unchanged)
00046 
00047     QChar m_word_break_char;
00048     QChar m_quote_char1;
00049     QChar m_quote_char2;
00050     QChar m_escape_char;
00051 };
00052 
00053 KShellCompletion::KShellCompletion()
00054     : KUrlCompletion(),
00055       d( new KShellCompletionPrivate )
00056 {
00057 }
00058 
00059 KShellCompletion::~KShellCompletion()
00060 {
00061     delete d;
00062 }
00063 
00064 
00065 /*
00066  * makeCompletion()
00067  *
00068  * Entry point for file name completion
00069  */
00070 QString KShellCompletion::makeCompletion(const QString &text)
00071 {
00072     // Split text at the last unquoted space
00073     //
00074     d->splitText(text, d->m_text_start, d->m_text_compl);
00075 
00076     // Remove quotes from the text to be completed
00077     //
00078     QString tmp = d->unquote(d->m_text_compl);
00079     d->m_text_compl = tmp;
00080 
00081     // Do exe-completion if there was no unquoted space
00082     //
00083     bool is_exe_completion = true;
00084 
00085     for ( int i = 0; i < d->m_text_start.length(); i++ ) {
00086         if ( d->m_text_start[i] != d->m_word_break_char ) {
00087             is_exe_completion = false;
00088             break;
00089         }
00090     }
00091 
00092     Mode mode = (is_exe_completion ? ExeCompletion : FileCompletion );
00093 
00094     setMode(mode);
00095 
00096     // Make completion on the last part of text
00097     //
00098     return KUrlCompletion::makeCompletion( d->m_text_compl );
00099 }
00100 
00101 /*
00102  * postProcessMatch, postProcessMatches
00103  *
00104  * Called by KCompletion before emitting match() and matches()
00105  *
00106  * Add add the part of the text that was not completed
00107  * Add quotes when needed
00108  */
00109 void KShellCompletion::postProcessMatch( QString *match ) const
00110 {
00111     KUrlCompletion::postProcessMatch( match );
00112 
00113     if ( match->isNull() )
00114         return;
00115 
00116     if ( match->endsWith( QLatin1Char( '/' ) ) )
00117         d->quoteText( match, false, true ); // don't quote the trailing '/'
00118     else
00119         d->quoteText( match, false, false ); // quote the whole text
00120 
00121     match->prepend( d->m_text_start );
00122 }
00123 
00124 void KShellCompletion::postProcessMatches( QStringList *matches ) const
00125 {
00126     KUrlCompletion::postProcessMatches( matches );
00127 
00128     for ( QStringList::Iterator it = matches->begin();
00129           it != matches->end(); it++ )
00130     {
00131         if ( !(*it).isNull() ) {
00132             if ( (*it).endsWith( QLatin1Char( '/' ) ) )
00133                 d->quoteText( &(*it), false, true ); // don't quote trailing '/'
00134             else
00135                 d->quoteText( &(*it), false, false ); // quote the whole text
00136 
00137             (*it).prepend( d->m_text_start );
00138         }
00139     }
00140 }
00141 
00142 void KShellCompletion::postProcessMatches( KCompletionMatches *matches ) const
00143 {
00144     KUrlCompletion::postProcessMatches( matches );
00145 
00146     for ( KCompletionMatches::Iterator it = matches->begin();
00147           it != matches->end(); it++ )
00148     {
00149         if ( !(*it).value().isNull() ) {
00150             if ( (*it).value().endsWith( QLatin1Char( '/' ) ) )
00151                 d->quoteText( &(*it).value(), false, true ); // don't quote trailing '/'
00152             else
00153                 d->quoteText( &(*it).value(), false, false ); // quote the whole text
00154 
00155             (*it).value().prepend( d->m_text_start );
00156         }
00157     }
00158 }
00159 
00160 /*
00161  * splitText
00162  *
00163  * Split text at the last unquoted space
00164  *
00165  * text_start = [out] text at the left, including the space
00166  * text_compl = [out] text at the right
00167  */
00168 void KShellCompletionPrivate::splitText(const QString &text, QString &text_start,
00169         QString &text_compl) const
00170 {
00171     bool in_quote = false;
00172     bool escaped = false;
00173     QChar p_last_quote_char;
00174     int last_unquoted_space = -1;
00175     int end_space_len = 0;
00176 
00177     for (int pos = 0; pos < text.length(); pos++) {
00178 
00179         end_space_len = 0;
00180 
00181         if ( escaped ) {
00182             escaped = false;
00183         }
00184         else if ( in_quote && text[pos] == p_last_quote_char ) {
00185             in_quote = false;
00186         }
00187         else if ( !in_quote && text[pos] == m_quote_char1 ) {
00188             p_last_quote_char = m_quote_char1;
00189             in_quote = true;
00190         }
00191         else if ( !in_quote && text[pos] == m_quote_char2 ) {
00192             p_last_quote_char = m_quote_char2;
00193             in_quote = true;
00194         }
00195         else if ( text[pos] == m_escape_char ) {
00196             escaped = true;
00197         }
00198         else if ( !in_quote && text[pos] == m_word_break_char ) {
00199 
00200             end_space_len = 1;
00201 
00202             while ( pos+1 < text.length() && text[pos+1] == m_word_break_char ) {
00203                 end_space_len++;
00204                 pos++;
00205             }
00206 
00207             if ( pos+1 == text.length() )
00208                 break;
00209 
00210             last_unquoted_space = pos;
00211         }
00212     }
00213 
00214     text_start = text.left( last_unquoted_space + 1 );
00215 
00216     // the last part without trailing blanks
00217     text_compl = text.mid( last_unquoted_space + 1 );
00218 }
00219 
00220 /*
00221  * quoteText()
00222  *
00223  * Add quotations to 'text' if needed or if 'force' = true
00224  * Returns true if quotes were added
00225  *
00226  * skip_last => ignore the last charachter (we add a space or '/' to all filenames)
00227  */
00228 bool KShellCompletionPrivate::quoteText(QString *text, bool force, bool skip_last) const
00229 {
00230     int pos = 0;
00231 
00232     if ( !force ) {
00233         pos = text->indexOf( m_word_break_char );
00234         if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1;
00235     }
00236 
00237     if ( !force && pos == -1 ) {
00238         pos = text->indexOf( m_quote_char1 );
00239         if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1;
00240     }
00241 
00242     if ( !force && pos == -1 ) {
00243         pos = text->indexOf( m_quote_char2 );
00244         if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1;
00245     }
00246 
00247     if ( !force && pos == -1 ) {
00248         pos = text->indexOf( m_escape_char );
00249         if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1;
00250     }
00251 
00252     if ( force || (pos >= 0) ) {
00253 
00254         // Escape \ in the string
00255         text->replace( m_escape_char,
00256                        QString( m_escape_char ) + m_escape_char );
00257 
00258         // Escape " in the string
00259         text->replace( m_quote_char1,
00260                        QString( m_escape_char ) + m_quote_char1 );
00261 
00262         // " at the beginning
00263         text->insert( 0, m_quote_char1 );
00264 
00265         // " at the end
00266         if ( skip_last )
00267             text->insert( text->length()-1, m_quote_char1 );
00268         else
00269             text->insert( text->length(), m_quote_char1 );
00270 
00271         return true;
00272     }
00273 
00274     return false;
00275 }
00276 
00277 /*
00278  * unquote
00279  *
00280  * Remove quotes and return the result in a new string
00281  *
00282  */
00283 QString KShellCompletionPrivate::unquote(const QString &text) const
00284 {
00285     bool in_quote = false;
00286     bool escaped = false;
00287     QChar p_last_quote_char;
00288     QString result;
00289 
00290     for (int pos = 0; pos < text.length(); pos++) {
00291 
00292         if ( escaped ) {
00293             escaped = false;
00294             result.insert( result.length(), text[pos] );
00295         }
00296         else if ( in_quote && text[pos] == p_last_quote_char ) {
00297             in_quote = false;
00298         }
00299         else if ( !in_quote && text[pos] == m_quote_char1 ) {
00300             p_last_quote_char = m_quote_char1;
00301             in_quote = true;
00302         }
00303         else if ( !in_quote && text[pos] == m_quote_char2 ) {
00304             p_last_quote_char = m_quote_char2;
00305             in_quote = true;
00306         }
00307         else if ( text[pos] == m_escape_char ) {
00308             escaped = true;
00309             result.insert( result.length(), text[pos] );
00310         }
00311         else {
00312             result.insert( result.length(), text[pos] );
00313         }
00314 
00315     }
00316 
00317     return result;
00318 }
00319 
00320 #include "kshellcompletion.moc"
00321 

KIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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