kio Library API Documentation

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
KDE Logo
This file is part of the documentation for kio Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 20 09:49:15 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003