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

kio

Skip menu "kio"
  • 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