# kio Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kshellcompletion.cpp

    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., 59 Temple Place - Suite 330,
    00017     Boston, MA 02111-1307, 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

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:24:04 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003