diff options
Diffstat (limited to 'tdeio/tdeio/kshellcompletion.cpp')
-rw-r--r-- | tdeio/tdeio/kshellcompletion.cpp | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/tdeio/tdeio/kshellcompletion.cpp b/tdeio/tdeio/kshellcompletion.cpp new file mode 100644 index 000000000..2fb67a31f --- /dev/null +++ b/tdeio/tdeio/kshellcompletion.cpp @@ -0,0 +1,311 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Smith <dsmith@algonet.se> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <stdlib.h> +#include <kdebug.h> +#include <tqstring.h> +#include <tqstringlist.h> +#include <tqregexp.h> +#include <kcompletion.h> + +#include "kshellcompletion.h" + +class KShellCompletionPrivate +{ +}; + +KShellCompletion::KShellCompletion() : KURLCompletion() +{ + m_word_break_char = ' '; + m_quote_char1 = '\"'; + m_quote_char2 = '\''; + m_escape_char = '\\'; +} + +/* + * makeCompletion() + * + * Entry point for file name completion + */ +TQString KShellCompletion::makeCompletion(const TQString &text) +{ + // Split text at the last unquoted space + // + splitText(text, m_text_start, m_text_compl); + + // Remove quotes from the text to be completed + // + TQString tmp = unquote(m_text_compl); + m_text_compl = tmp; + + // Do exe-completion if there was no unquoted space + // + bool is_exe_completion = true; + + for ( uint i = 0; i < m_text_start.length(); i++ ) { + if ( m_text_start[i] != m_word_break_char ) { + is_exe_completion = false; + break; + } + } + + Mode mode = (is_exe_completion ? ExeCompletion : FileCompletion ); + + setMode(mode); + + // Make completion on the last part of text + // + return KURLCompletion::makeCompletion( m_text_compl ); +} + +/* + * postProcessMatch, postProcessMatches + * + * Called by KCompletion before emitting match() and matches() + * + * Add add the part of the text that was not completed + * Add quotes when needed + */ +void KShellCompletion::postProcessMatch( TQString *match ) const +{ + //kDebugInfo("KShellCompletion::postProcessMatch() in: '%s'", + // match->latin1()); + + KURLCompletion::postProcessMatch( match ); + + if ( match->isNull() ) + return; + + if ( match->right(1) == TQChar('/') ) + quoteText( match, false, true ); // don't quote the trailing '/' + else + quoteText( match, false, false ); // quote the whole text + + match->prepend( m_text_start ); + + //kDebugInfo("KShellCompletion::postProcessMatch() ut: '%s'", + // match->latin1()); +} + +void KShellCompletion::postProcessMatches( TQStringList *matches ) const +{ + KURLCompletion::postProcessMatches( matches ); + + for ( TQStringList::Iterator it = matches->begin(); + it != matches->end(); it++ ) + { + if ( !(*it).isNull() ) { + if ( (*it).right(1) == TQChar('/') ) + quoteText( &(*it), false, true ); // don't quote trailing '/' + else + quoteText( &(*it), false, false ); // quote the whole text + + (*it).prepend( m_text_start ); + } + } +} + +void KShellCompletion::postProcessMatches( KCompletionMatches *matches ) const +{ + KURLCompletion::postProcessMatches( matches ); + + for ( KCompletionMatches::Iterator it = matches->begin(); + it != matches->end(); it++ ) + { + if ( !(*it).value().isNull() ) { + if ( (*it).value().right(1) == TQChar('/') ) + quoteText( &(*it).value(), false, true ); // don't quote trailing '/' + else + quoteText( &(*it).value(), false, false ); // quote the whole text + + (*it).value().prepend( m_text_start ); + } + } +} + +/* + * splitText + * + * Split text at the last unquoted space + * + * text_start = [out] text at the left, including the space + * text_compl = [out] text at the right + */ +void KShellCompletion::splitText(const TQString &text, TQString &text_start, + TQString &text_compl) const +{ + bool in_quote = false; + bool escaped = false; + TQChar p_last_quote_char; + int last_unquoted_space = -1; + int end_space_len = 0; + + for (uint pos = 0; pos < text.length(); pos++) { + + end_space_len = 0; + + if ( escaped ) { + escaped = false; + } + else if ( in_quote && text[pos] == p_last_quote_char ) { + in_quote = false; + } + else if ( !in_quote && text[pos] == m_quote_char1 ) { + p_last_quote_char = m_quote_char1; + in_quote = true; + } + else if ( !in_quote && text[pos] == m_quote_char2 ) { + p_last_quote_char = m_quote_char2; + in_quote = true; + } + else if ( text[pos] == m_escape_char ) { + escaped = true; + } + else if ( !in_quote && text[pos] == m_word_break_char ) { + + end_space_len = 1; + + while ( pos+1 < text.length() && text[pos+1] == m_word_break_char ) { + end_space_len++; + pos++; + } + + if ( pos+1 == text.length() ) + break; + + last_unquoted_space = pos; + } + } + + text_start = text.left( last_unquoted_space + 1 ); + + // the last part without trailing blanks + text_compl = text.mid( last_unquoted_space + 1 ); + +// text_compl = text.mid( last_unquoted_space + 1, +// text.length() - end_space_len - (last_unquoted_space + 1) ); + + //kDebugInfo("split right = '%s'", text_compl.latin1()); +} + +/* + * quoteText() + * + * Add quotations to 'text' if needed or if 'force' = true + * Returns true if quotes were added + * + * skip_last => ignore the last charachter (we add a space or '/' to all filenames) + */ +bool KShellCompletion::quoteText(TQString *text, bool force, bool skip_last) const +{ + int pos = 0; + + if ( !force ) { + pos = text->find( m_word_break_char ); + if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1; + } + + if ( !force && pos == -1 ) { + pos = text->find( m_quote_char1 ); + if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1; + } + + if ( !force && pos == -1 ) { + pos = text->find( m_quote_char2 ); + if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1; + } + + if ( !force && pos == -1 ) { + pos = text->find( m_escape_char ); + if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1; + } + + if ( force || (pos >= 0) ) { + + // Escape \ in the string + text->replace( m_escape_char, + TQString( m_escape_char ) + m_escape_char ); + + // Escape " in the string + text->replace( m_quote_char1, + TQString( m_escape_char ) + m_quote_char1 ); + + // " at the beginning + text->insert( 0, m_quote_char1 ); + + // " at the end + if ( skip_last ) + text->insert( text->length()-1, m_quote_char1 ); + else + text->insert( text->length(), m_quote_char1 ); + + return true; + } + + return false; +} + +/* + * unquote + * + * Remove quotes and return the result in a new string + * + */ +TQString KShellCompletion::unquote(const TQString &text) const +{ + bool in_quote = false; + bool escaped = false; + TQChar p_last_quote_char; + TQString result; + + for (uint pos = 0; pos < text.length(); pos++) { + + if ( escaped ) { + escaped = false; + result.insert( result.length(), text[pos] ); + } + else if ( in_quote && text[pos] == p_last_quote_char ) { + in_quote = false; + } + else if ( !in_quote && text[pos] == m_quote_char1 ) { + p_last_quote_char = m_quote_char1; + in_quote = true; + } + else if ( !in_quote && text[pos] == m_quote_char2 ) { + p_last_quote_char = m_quote_char2; + in_quote = true; + } + else if ( text[pos] == m_escape_char ) { + escaped = true; + result.insert( result.length(), text[pos] ); + } + else { + result.insert( result.length(), text[pos] ); + } + + } + + return result; +} + +void KShellCompletion::virtual_hook( int id, void* data ) +{ KURLCompletion::virtual_hook( id, data ); } + +#include "kshellcompletion.moc" + |