• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

kurlcompletion.cpp
00001 /* -*- indent-tabs-mode: t; tab-width: 4; c-basic-offset:4 -*-
00002 
00003    This file is part of the KDE libraries
00004    Copyright (C) 2000 David Smith <dsmith@algonet.se>
00005    Copyright (C) 2004 Scott Wheeler <wheeler@kde.org>
00006 
00007    This class was inspired by a previous KURLCompletion by
00008    Henner Zeller <zeller@think.de>
00009 
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Library General Public
00012    License as published by the Free Software Foundation; either
00013    version 2 of the License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018    Library General Public License for more details.
00019 
00020    You should have received a copy of the GNU Library General Public License
00021    along with this library; see the file COPYING.LIB.   If not, write to
00022    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00023    Boston, MA 02110-1301, USA.
00024 */
00025 
00026 #include <config.h>
00027 #include <stdlib.h>
00028 #include <assert.h>
00029 #include <limits.h>
00030 
00031 #include <tqstring.h>
00032 #include <tqstringlist.h>
00033 #include <tqvaluelist.h>
00034 #include <tqregexp.h>
00035 #include <tqtimer.h>
00036 #include <tqdir.h>
00037 #include <tqfile.h>
00038 #include <tqtextstream.h>
00039 #include <tqdeepcopy.h>
00040 #include <tqthread.h>
00041 
00042 #include <tdeapplication.h>
00043 #include <kdebug.h>
00044 #include <kcompletion.h>
00045 #include <kurl.h>
00046 #include <tdeio/jobclasses.h>
00047 #include <tdeio/job.h>
00048 #include <kprotocolinfo.h>
00049 #include <tdeconfig.h>
00050 #include <tdeglobal.h>
00051 #include <tdelocale.h>
00052 #include <kde_file.h>
00053 
00054 #include <sys/types.h>
00055 #include <dirent.h>
00056 #include <unistd.h>
00057 #include <sys/stat.h>
00058 #include <pwd.h>
00059 #include <time.h>
00060 #include <sys/param.h>
00061 
00062 #include "kurlcompletion.h"
00063 
00064 static bool expandTilde(TQString &);
00065 static bool expandEnv(TQString &);
00066 
00067 static TQString unescape(const TQString &text);
00068 
00069 // Permission mask for files that are executable by
00070 // user, group or other
00071 #define MODE_EXE (S_IXUSR | S_IXGRP | S_IXOTH)
00072 
00073 // Constants for types of completion
00074 enum ComplType {CTNone=0, CTEnv, CTUser, CTMan, CTExe, CTFile, CTUrl, CTInfo};
00075 
00076 class CompletionThread;
00077 
00083 class CompletionMatchEvent : public TQCustomEvent
00084 {
00085 public:
00086     CompletionMatchEvent( CompletionThread *thread ) :
00087         TQCustomEvent( uniqueType() ),
00088         m_completionThread( thread )
00089     {}
00090 
00091     CompletionThread *completionThread() const { return m_completionThread; }
00092     static int uniqueType() { return User + 61080; }
00093 
00094 private:
00095     CompletionThread *m_completionThread;
00096 };
00097 
00098 class CompletionThread : public TQThread
00099 {
00100 protected:
00101     CompletionThread( KURLCompletion *receiver ) :
00102         TQThread(),
00103         m_receiver( receiver ),
00104         m_terminationRequested( false )
00105     {}
00106 
00107 public:
00108     void requestTermination() { m_terminationRequested = true; }
00109     TQDeepCopy<TQStringList> matches() const { return m_matches; }
00110 
00111 protected:
00112     void addMatch( const TQString &match ) { m_matches.append( match ); }
00113     bool terminationRequested() const { return m_terminationRequested; }
00114     void done()
00115     {
00116         if ( !m_terminationRequested )
00117             kapp->postEvent( m_receiver, new CompletionMatchEvent( this ) );
00118         else
00119             delete this;
00120     }
00121 
00122 private:
00123     KURLCompletion *m_receiver;
00124     TQStringList m_matches;
00125     bool m_terminationRequested;
00126 };
00127 
00133 class UserListThread : public CompletionThread
00134 {
00135 public:
00136     UserListThread( KURLCompletion *receiver ) :
00137         CompletionThread( receiver )
00138     {}
00139 
00140 protected:
00141     virtual void run()
00142     {
00143         static const TQChar tilde = '~';
00144 
00145         struct passwd *pw;
00146         while ( ( pw = ::getpwent() ) && !terminationRequested() )
00147             addMatch( tilde + TQString::fromLocal8Bit( pw->pw_name ) );
00148 
00149         ::endpwent();
00150 
00151         addMatch( tilde );
00152 
00153         done();
00154     }
00155 };
00156 
00157 class DirectoryListThread : public CompletionThread
00158 {
00159 public:
00160     DirectoryListThread( KURLCompletion *receiver,
00161                          const TQStringList &dirList,
00162                          const TQString &filter,
00163                          bool onlyExe,
00164                          bool onlyDir,
00165                          bool noHidden,
00166                          bool appendSlashToDir ) :
00167         CompletionThread( receiver ),
00168         m_dirList( TQDeepCopy<TQStringList>( dirList ) ),
00169         m_filter( TQDeepCopy<TQString>( filter ) ),
00170         m_onlyExe( onlyExe ),
00171         m_onlyDir( onlyDir ),
00172         m_noHidden( noHidden ),
00173         m_appendSlashToDir( appendSlashToDir )
00174     {}
00175 
00176     virtual void run();
00177 
00178 private:
00179     TQStringList m_dirList;
00180     TQString m_filter;
00181     bool m_onlyExe;
00182     bool m_onlyDir;
00183     bool m_noHidden;
00184     bool m_appendSlashToDir;
00185 };
00186 
00187 void DirectoryListThread::run()
00188 {
00189     // Thread safety notes:
00190     //
00191     // There very possibly may be thread safety issues here, but I've done a check
00192     // of all of the things that would seem to be problematic.  Here are a few
00193     // things that I have checked to be safe here (some used indirectly):
00194     //
00195     // TQDir::currentDirPath(), TQDir::setCurrent(), TQFile::decodeName(), TQFile::encodeName()
00196     // TQString::fromLocal8Bit(), TQString::local8Bit(), TQTextCodec::codecForLocale()
00197     //
00198     // Also see (for POSIX functions):
00199     // http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html
00200 
00201     DIR *dir = 0;
00202 
00203     for ( TQStringList::ConstIterator it = m_dirList.begin();
00204           it != m_dirList.end() && !terminationRequested();
00205           ++it )
00206     {
00207         // Open the next directory
00208 
00209         if ( !dir ) {
00210             dir = ::opendir( TQFile::encodeName( *it ) );
00211             if ( ! dir ) {
00212                 kdDebug() << "Failed to open dir: " << *it << endl;
00213                 done();
00214                 return;
00215             }
00216         }
00217 
00218         // A trick from TDEIO that helps performance by a little bit:
00219         // chdir to the directroy so we won't have to deal with full paths
00220         // with stat()
00221 
00222         TQString path = TQDir::currentDirPath();
00223         TQDir::setCurrent( *it );
00224 
00225         // Loop through all directory entries
00226         // Solaris and IRIX dirent structures do not allocate space for d_name. On
00227         // systems that do (HP-UX, Linux, Tru64 UNIX), we overallocate space but
00228         // that's ok.
00229 #ifndef HAVE_READDIR_R
00230         struct dirent *dirEntry = 0;
00231         while ( !terminationRequested() &&
00232                 (dirEntry = ::readdir( dir)))
00233 #else
00234 #if !defined(MAXPATHLEN) && defined(__GNU__)
00235 #define MAXPATHLEN UCHAR_MAX
00236 #endif
00237         struct dirent *dirPosition = (struct dirent *) malloc( sizeof( struct dirent ) + MAXPATHLEN + 1 );
00238         struct dirent *dirEntry = 0;
00239         while ( !terminationRequested() &&
00240                 ::readdir_r( dir, dirPosition, &dirEntry ) == 0 && dirEntry )
00241 #endif 
00242 
00243         {
00244             // Skip hidden files if m_noHidden is true
00245 
00246             if ( dirEntry->d_name[0] == '.' && m_noHidden )
00247                 continue;
00248 
00249             // Skip "."
00250 
00251             if ( dirEntry->d_name[0] == '.' && dirEntry->d_name[1] == '\0' )
00252                 continue;
00253 
00254             // Skip ".."
00255 
00256             if ( dirEntry->d_name[0] == '.' && dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0' )
00257                 continue;
00258 
00259             TQString file = TQFile::decodeName( dirEntry->d_name );
00260 
00261             if ( m_filter.isEmpty() || file.startsWith( m_filter ) ) {
00262 
00263                 if ( m_onlyExe || m_onlyDir || m_appendSlashToDir ) {
00264                     KDE_struct_stat sbuff;
00265 
00266                     if ( KDE_stat( dirEntry->d_name, &sbuff ) == 0 ) {
00267 
00268                         // Verify executable
00269 
00270                         if ( m_onlyExe && ( sbuff.st_mode & MODE_EXE ) == 0 )
00271                             continue;
00272 
00273                         // Verify directory
00274 
00275                         if ( m_onlyDir && !S_ISDIR( sbuff.st_mode ) )
00276                             continue;
00277 
00278                         // Add '/' to directories
00279 
00280                         if ( m_appendSlashToDir && S_ISDIR( sbuff.st_mode ) )
00281                             file.append( '/' );
00282 
00283                     }
00284                     else {
00285                         kdDebug() << "Could not stat file " << file << endl;
00286                         continue;
00287                     }
00288                 }
00289 
00290                 addMatch( file );
00291             }
00292         }
00293 
00294         // chdir to the original directory
00295 
00296         TQDir::setCurrent( path );
00297 
00298         ::closedir( dir );
00299         dir = 0;
00300 #ifdef HAVE_READDIR_R
00301         free( dirPosition );
00302 #endif
00303     }
00304 
00305     done();
00306 }
00307 
00310 // MyURL - wrapper for KURL with some different functionality
00311 //
00312 
00313 class KURLCompletion::MyURL
00314 {
00315 public:
00316     MyURL(const TQString &url, const TQString &cwd);
00317     MyURL(const MyURL &url);
00318     ~MyURL();
00319 
00320     KURL *kurl() const { return m_kurl; }
00321 
00322     TQString protocol() const { return m_kurl->protocol(); }
00323     // The directory with a trailing '/'
00324     TQString dir() const { return m_kurl->directory(false, false); }
00325     TQString file() const { return m_kurl->fileName(false); }
00326 
00327     // The initial, unparsed, url, as a string.
00328     TQString url() const { return m_url; }
00329 
00330     // Is the initial string a URL, or just a path (whether absolute or relative)
00331     bool isURL() const { return m_isURL; }
00332 
00333     void filter( bool replace_user_dir, bool replace_env );
00334 
00335 private:
00336     void init(const TQString &url, const TQString &cwd);
00337 
00338     KURL *m_kurl;
00339     TQString m_url;
00340     bool m_isURL;
00341 };
00342 
00343 KURLCompletion::MyURL::MyURL(const TQString &url, const TQString &cwd)
00344 {
00345     init(url, cwd);
00346 }
00347 
00348 KURLCompletion::MyURL::MyURL(const MyURL &url)
00349 {
00350     m_kurl = new KURL( *(url.m_kurl) );
00351     m_url = url.m_url;
00352     m_isURL = url.m_isURL;
00353 }
00354 
00355 void KURLCompletion::MyURL::init(const TQString &url, const TQString &cwd)
00356 {
00357     // Save the original text
00358     m_url = url;
00359 
00360     // Non-const copy
00361     TQString url_copy = url;
00362 
00363     // Special shortcuts for "man:" and "info:"
00364     if ( url_copy[0] == '#' ) {
00365         if ( url_copy[1] == '#' )
00366             url_copy.replace( 0, 2, TQString("info:") );
00367         else
00368             url_copy.replace( 0, 1, TQString("man:") );
00369     }
00370 
00371     // Look for a protocol in 'url'
00372     TQRegExp protocol_regex = TQRegExp( "^[^/\\s\\\\]*:" );
00373 
00374     // Assume "file:" or whatever is given by 'cwd' if there is
00375     // no protocol.  (KURL does this only for absoute paths)
00376     if ( protocol_regex.search( url_copy ) == 0 )
00377     {
00378         m_kurl = new KURL( url_copy );
00379         m_isURL = true;
00380     }
00381     else // relative path or ~ or $something
00382     {
00383         m_isURL = false;
00384         if ( cwd.isEmpty() )
00385         {
00386             m_kurl = new KURL();
00387             if ( !TQDir::isRelativePath(url_copy) || url_copy[0] == '$' || url_copy[0] == '~' )
00388                 m_kurl->setPath( url_copy );
00389             else
00390                 *m_kurl = url_copy;
00391         }
00392         else
00393         {
00394             KURL base = KURL::fromPathOrURL( cwd );
00395             base.adjustPath(+1);
00396 
00397             if ( !TQDir::isRelativePath(url_copy) || url_copy[0] == '~' || url_copy[0] == '$' )
00398             {
00399                 m_kurl = new KURL();
00400                 m_kurl->setPath( url_copy );
00401             }
00402             else // relative path
00403             {
00404                 //m_kurl = new KURL( base, url_copy );
00405                 m_kurl = new KURL( base );
00406                 m_kurl->addPath( url_copy );
00407             }
00408         }
00409     }
00410 }
00411 
00412 KURLCompletion::MyURL::~MyURL()
00413 {
00414     delete m_kurl;
00415 }
00416 
00417 void KURLCompletion::MyURL::filter( bool replace_user_dir, bool replace_env )
00418 {
00419     TQString d = dir() + file();
00420     if ( replace_user_dir ) expandTilde( d );
00421     if ( replace_env ) expandEnv( d );
00422     m_kurl->setPath( d );
00423 }
00424 
00427 // KURLCompletionPrivate
00428 //
00429 class KURLCompletionPrivate
00430 {
00431 public:
00432     KURLCompletionPrivate() : url_auto_completion(true),
00433                               userListThread(0),
00434                               dirListThread(0) {}
00435     ~KURLCompletionPrivate();
00436 
00437     TQValueList<KURL*> list_urls;
00438 
00439     bool onlyLocalProto;
00440 
00441     // urlCompletion() in Auto/Popup mode?
00442     bool url_auto_completion;
00443 
00444     // Append '/' to directories in Popup mode?
00445     // Doing that stat's all files and is slower
00446     bool popup_append_slash;
00447 
00448     // Keep track of currently listed files to avoid reading them again
00449     TQString last_path_listed;
00450     TQString last_file_listed;
00451     TQString last_prepend;
00452     int last_compl_type;
00453     int last_no_hidden;
00454 
00455     TQString cwd; // "current directory" = base dir for completion
00456 
00457     KURLCompletion::Mode mode; // ExeCompletion, FileCompletion, DirCompletion
00458     bool replace_env;
00459     bool replace_home;
00460     bool complete_url; // if true completing a URL (i.e. 'prepend' is a URL), otherwise a path
00461 
00462     TDEIO::ListJob *list_job; // tdeio job to list directories
00463 
00464     TQString prepend; // text to prepend to listed items
00465     TQString compl_text; // text to pass on to TDECompletion
00466 
00467     // Filters for files read with  tdeio
00468     bool list_urls_only_exe; // true = only list executables
00469     bool list_urls_no_hidden;
00470     TQString list_urls_filter; // filter for listed files
00471 
00472     CompletionThread *userListThread;
00473     CompletionThread *dirListThread;
00474 };
00475 
00476 KURLCompletionPrivate::~KURLCompletionPrivate()
00477 {
00478     if ( userListThread )
00479         userListThread->requestTermination();
00480     if ( dirListThread )
00481         dirListThread->requestTermination();
00482 }
00483 
00486 // KURLCompletion
00487 //
00488 
00489 KURLCompletion::KURLCompletion() : TDECompletion()
00490 {
00491     init();
00492 }
00493 
00494 
00495 KURLCompletion::KURLCompletion( Mode mode ) : TDECompletion()
00496 {
00497     init();
00498     setMode ( mode );
00499 }
00500 
00501 KURLCompletion::~KURLCompletion()
00502 {
00503     stop();
00504     delete d;
00505 }
00506 
00507 
00508 void KURLCompletion::init()
00509 {
00510     d = new KURLCompletionPrivate;
00511 
00512     d->cwd = TQDir::homeDirPath();
00513 
00514     d->replace_home = true;
00515     d->replace_env = true;
00516     d->last_no_hidden = false;
00517     d->last_compl_type = 0;
00518     d->list_job = 0L;
00519     d->mode = KURLCompletion::FileCompletion;
00520 
00521     // Read settings
00522     TDEConfig *c = TDEGlobal::config();
00523     TDEConfigGroupSaver cgs( c, "URLCompletion" );
00524 
00525     d->url_auto_completion = c->readBoolEntry("alwaysAutoComplete", true);
00526     d->popup_append_slash = c->readBoolEntry("popupAppendSlash", true);
00527     d->onlyLocalProto = c->readBoolEntry("LocalProtocolsOnly", false);
00528 }
00529 
00530 void KURLCompletion::setDir(const TQString &dir)
00531 {
00532     d->cwd = dir;
00533 }
00534 
00535 TQString KURLCompletion::dir() const
00536 {
00537     return d->cwd;
00538 }
00539 
00540 KURLCompletion::Mode KURLCompletion::mode() const
00541 {
00542     return d->mode;
00543 }
00544 
00545 void KURLCompletion::setMode( Mode mode )
00546 {
00547     d->mode = mode;
00548 }
00549 
00550 bool KURLCompletion::replaceEnv() const
00551 {
00552     return d->replace_env;
00553 }
00554 
00555 void KURLCompletion::setReplaceEnv( bool replace )
00556 {
00557     d->replace_env = replace;
00558 }
00559 
00560 bool KURLCompletion::replaceHome() const
00561 {
00562     return d->replace_home;
00563 }
00564 
00565 void KURLCompletion::setReplaceHome( bool replace )
00566 {
00567     d->replace_home = replace;
00568 }
00569 
00570 /*
00571  * makeCompletion()
00572  *
00573  * Entry point for file name completion
00574  */
00575 TQString KURLCompletion::makeCompletion(const TQString &text)
00576 {
00577     //kdDebug() << "KURLCompletion::makeCompletion: " << text << " d->cwd=" << d->cwd << endl;
00578 
00579     MyURL url(text, d->cwd);
00580 
00581     d->compl_text = text;
00582 
00583     // Set d->prepend to the original URL, with the filename [and ref/query] stripped.
00584     // This is what gets prepended to the directory-listing matches.
00585     int toRemove = url.file().length() - url.kurl()->query().length();
00586     if ( url.kurl()->hasRef() )
00587         toRemove += url.kurl()->ref().length() + 1;
00588     d->prepend = text.left( text.length() - toRemove );
00589     d->complete_url = url.isURL();
00590 
00591     TQString match;
00592 
00593     // Environment variables
00594     //
00595     if ( d->replace_env && envCompletion( url, &match ) )
00596         return match;
00597 
00598     // User directories
00599     //
00600     if ( d->replace_home && userCompletion( url, &match ) )
00601         return match;
00602 
00603     // Replace user directories and variables
00604     url.filter( d->replace_home, d->replace_env );
00605 
00606     //kdDebug() << "Filtered: proto=" << url.protocol()
00607     //          << ", dir=" << url.dir()
00608     //          << ", file=" << url.file()
00609     //          << ", kurl url=" << *url.kurl() << endl;
00610 
00611     if ( d->mode == ExeCompletion ) {
00612         // Executables
00613         //
00614         if ( exeCompletion( url, &match ) )
00615             return match;
00616 
00617         // KRun can run "man:" and "info:" etc. so why not treat them
00618         // as executables...
00619 
00620         if ( urlCompletion( url, &match ) )
00621             return match;
00622     }
00623     else if ( d->mode == SystemExeCompletion ) {
00624         // Executables
00625         //
00626         if ( systemexeCompletion( url, &match ) )
00627             return match;
00628 
00629         // KRun can run "man:" and "info:" etc. so why not treat them
00630         // as executables...
00631 
00632         if ( urlCompletion( url, &match ) )
00633             return match;
00634     }
00635     else {
00636         // Local files, directories
00637         //
00638         if ( fileCompletion( url, &match ) )
00639             return match;
00640 
00641         // All other...
00642         //
00643         if ( urlCompletion( url, &match ) )
00644             return match;
00645     }
00646 
00647     setListedURL( CTNone );
00648     stop();
00649 
00650     return TQString::null;
00651 }
00652 
00653 /*
00654  * finished
00655  *
00656  * Go on and call TDECompletion.
00657  * Called when all matches have been added
00658  */
00659 TQString KURLCompletion::finished()
00660 {
00661     if ( d->last_compl_type == CTInfo )
00662         return TDECompletion::makeCompletion( d->compl_text.lower() );
00663     else
00664         return TDECompletion::makeCompletion( d->compl_text );
00665 }
00666 
00667 /*
00668  * isRunning
00669  *
00670  * Return true if either a TDEIO job or the DirLister
00671  * is running
00672  */
00673 bool KURLCompletion::isRunning() const
00674 {
00675     return d->list_job || (d->dirListThread && !d->dirListThread->finished());
00676 }
00677 
00678 /*
00679  * stop
00680  *
00681  * Stop and delete a running TDEIO job or the DirLister
00682  */
00683 void KURLCompletion::stop()
00684 {
00685     if ( d->list_job ) {
00686         d->list_job->kill();
00687         d->list_job = 0L;
00688     }
00689 
00690     if ( !d->list_urls.isEmpty() ) {
00691         TQValueList<KURL*>::Iterator it = d->list_urls.begin();
00692         for ( ; it != d->list_urls.end(); it++ )
00693             delete (*it);
00694         d->list_urls.clear();
00695     }
00696 
00697     if ( d->dirListThread ) {
00698         d->dirListThread->requestTermination();
00699         d->dirListThread = 0;
00700     }
00701 }
00702 
00703 /*
00704  * Keep track of the last listed directory
00705  */
00706 void KURLCompletion::setListedURL( int complType,
00707                                    const TQString& dir,
00708                                    const TQString& filter,
00709                                    bool no_hidden )
00710 {
00711     d->last_compl_type = complType;
00712     d->last_path_listed = dir;
00713     d->last_file_listed = filter;
00714     d->last_no_hidden = (int)no_hidden;
00715     d->last_prepend = d->prepend;
00716 }
00717 
00718 bool KURLCompletion::isListedURL( int complType,
00719                                   const TQString& dir,
00720                                   const TQString& filter,
00721                                   bool no_hidden )
00722 {
00723     return  d->last_compl_type == complType
00724             && ( d->last_path_listed == dir
00725                     || (dir.isEmpty() && d->last_path_listed.isEmpty()) )
00726             && ( filter.startsWith(d->last_file_listed)
00727                     || (filter.isEmpty() && d->last_file_listed.isEmpty()) )
00728             && d->last_no_hidden == (int)no_hidden
00729             && d->last_prepend == d->prepend; // e.g. relative path vs absolute
00730 }
00731 
00732 /*
00733  * isAutoCompletion
00734  *
00735  * Returns true if completion mode is Auto or Popup
00736  */
00737 bool KURLCompletion::isAutoCompletion()
00738 {
00739     return completionMode() == TDEGlobalSettings::CompletionAuto
00740            || completionMode() == TDEGlobalSettings::CompletionPopup
00741            || completionMode() == TDEGlobalSettings::CompletionMan
00742            || completionMode() == TDEGlobalSettings::CompletionPopupAuto;
00743 }
00746 // User directories
00747 //
00748 
00749 bool KURLCompletion::userCompletion(const MyURL &url, TQString *match)
00750 {
00751     if ( url.protocol() != "file"
00752           || !url.dir().isEmpty()
00753           || url.file().at(0) != '~' )
00754         return false;
00755 
00756     if ( !isListedURL( CTUser ) ) {
00757         stop();
00758         clear();
00759 
00760         if ( !d->userListThread ) {
00761             d->userListThread = new UserListThread( this );
00762             d->userListThread->start();
00763 
00764             // If the thread finishes quickly make sure that the results
00765             // are added to the first matching case.
00766 
00767             d->userListThread->wait( 200 );
00768             TQStringList l = d->userListThread->matches();
00769             addMatches( l );
00770         }
00771     }
00772     *match = finished();
00773     return true;
00774 }
00775 
00778 // Environment variables
00779 //
00780 
00781 #if !defined(__OpenBSD__) && !defined(__FreeBSD__)
00782 extern char **environ; // Array of environment variables
00783 #endif
00784 
00785 bool KURLCompletion::envCompletion(const MyURL &url, TQString *match)
00786 {
00787 #if defined(__OpenBSD__) || defined(__FreeBSD__)
00788     return false;
00789 #else
00790     if ( url.file().at(0) != '$' )
00791         return false;
00792 
00793     if ( !isListedURL( CTEnv ) ) {
00794         stop();
00795         clear();
00796 
00797         char **env = environ;
00798 
00799         TQString dollar = TQString("$");
00800 
00801         TQStringList l;
00802 
00803         while ( *env ) {
00804             TQString s = TQString::fromLocal8Bit( *env );
00805 
00806             int pos = s.find('=');
00807 
00808             if ( pos == -1 )
00809                 pos = s.length();
00810 
00811             if ( pos > 0 )
00812                 l.append( dollar + s.left(pos) );
00813 
00814             env++;
00815         }
00816 
00817         addMatches( l );
00818     }
00819 
00820     setListedURL( CTEnv );
00821 
00822     *match = finished();
00823     return true;
00824 #endif
00825 }
00826 
00829 // Executables
00830 //
00831 
00832 bool KURLCompletion::exeCompletion(const MyURL &url, TQString *match)
00833 {
00834     if ( url.protocol() != "file" )
00835         return false;
00836 
00837     TQString dir = url.dir();
00838 
00839     dir = unescape( dir ); // remove escapes
00840 
00841     // Find directories to search for completions, either
00842     //
00843     // 1. complete path given in url
00844     // 2. current directory (d->cwd)
00845     // 3. $PATH
00846     // 4. no directory at all
00847 
00848     TQStringList dirList;
00849 
00850     if ( !TQDir::isRelativePath(dir) ) {
00851         // complete path in url
00852         dirList.append( dir );
00853     }
00854     else if ( !dir.isEmpty() && !d->cwd.isEmpty() ) {
00855         // current directory
00856         dirList.append( d->cwd + '/' + dir );
00857     }
00858     else if ( !url.file().isEmpty() ) {
00859         // $PATH
00860         dirList = TQStringList::split(KPATH_SEPARATOR,
00861                     TQString::fromLocal8Bit(::getenv("PATH")));
00862 
00863         TQStringList::Iterator it = dirList.begin();
00864 
00865         for ( ; it != dirList.end(); it++ )
00866             (*it).append('/');
00867     }
00868 
00869     // No hidden files unless the user types "."
00870     bool no_hidden_files = url.file().at(0) != '.';
00871 
00872     // List files if needed
00873     //
00874     if ( !isListedURL( CTExe, dir, url.file(), no_hidden_files ) )
00875     {
00876         stop();
00877         clear();
00878 
00879         setListedURL( CTExe, dir, url.file(), no_hidden_files );
00880 
00881         *match = listDirectories( dirList, url.file(), true, false, no_hidden_files );
00882     }
00883     else if ( !isRunning() ) {
00884         *match = finished();
00885     }
00886     else {
00887         if ( d->dirListThread )
00888             setListedURL( CTExe, dir, url.file(), no_hidden_files );
00889         *match = TQString::null;
00890     }
00891 
00892     return true;
00893 }
00894 
00897 // System Executables
00898 //
00899 
00900 bool KURLCompletion::systemexeCompletion(const MyURL &url, TQString *match)
00901 {
00902     if ( url.protocol() != "file" )
00903         return false;
00904 
00905     TQString dir = url.dir();
00906 
00907     dir = unescape( dir ); // remove escapes
00908 
00909     // Find directories to search for completions, either
00910     //
00911     // 1. complete path given in url
00912     // 2. current directory (d->cwd)
00913     // 3. $PATH
00914     // 4. no directory at all
00915 
00916     TQStringList dirList;
00917 
00918     if ( !url.file().isEmpty() ) {
00919         // $PATH
00920         dirList = TQStringList::split(KPATH_SEPARATOR,
00921                     TQString::fromLocal8Bit(::getenv("PATH")));
00922 
00923         TQStringList::Iterator it = dirList.begin();
00924 
00925         for ( ; it != dirList.end(); it++ )
00926             (*it).append('/');
00927     }
00928 
00929     // No hidden files unless the user types "."
00930     bool no_hidden_files = url.file().at(0) != '.';
00931 
00932     // List files if needed
00933     //
00934     if ( !isListedURL( CTExe, dir, url.file(), no_hidden_files ) )
00935     {
00936         stop();
00937         clear();
00938 
00939         setListedURL( CTExe, dir, url.file(), no_hidden_files );
00940 
00941         *match = listDirectories( dirList, url.file(), true, false, no_hidden_files );
00942     }
00943     else if ( !isRunning() ) {
00944         *match = finished();
00945     }
00946     else {
00947         if ( d->dirListThread )
00948             setListedURL( CTExe, dir, url.file(), no_hidden_files );
00949         *match = TQString::null;
00950     }
00951 
00952     return true;
00953 }
00954 
00957 // Local files
00958 //
00959 
00960 bool KURLCompletion::fileCompletion(const MyURL &url, TQString *match)
00961 {
00962     if ( url.protocol() != "file" )
00963         return false;
00964 
00965     TQString dir = url.dir();
00966 
00967     if (url.url()[0] == '.')
00968     {
00969         if (url.url().length() == 1)
00970         {
00971             *match =
00972                 ( completionMode() == TDEGlobalSettings::CompletionMan )? "." : "..";
00973             return true;
00974         }
00975         if (url.url().length() == 2 && url.url()[1]=='.')
00976         {
00977             *match="..";
00978             return true;
00979         }
00980     }
00981 
00982     //kdDebug() << "fileCompletion " << url.url() << " dir=" << dir << endl;
00983 
00984     dir = unescape( dir ); // remove escapes
00985 
00986     // Find directories to search for completions, either
00987     //
00988     // 1. complete path given in url
00989     // 2. current directory (d->cwd)
00990     // 3. no directory at all
00991 
00992     TQStringList dirList;
00993 
00994     if ( !TQDir::isRelativePath(dir) ) {
00995         // complete path in url
00996         dirList.append( dir );
00997     }
00998     else if ( !d->cwd.isEmpty() ) {
00999         // current directory
01000         dirList.append( d->cwd + '/' + dir );
01001     }
01002 
01003     // No hidden files unless the user types "."
01004     bool no_hidden_files = ( url.file().at(0) != '.' );
01005 
01006     // List files if needed
01007     //
01008     if ( !isListedURL( CTFile, dir, "", no_hidden_files ) )
01009     {
01010         stop();
01011         clear();
01012 
01013         setListedURL( CTFile, dir, "", no_hidden_files );
01014 
01015         // Append '/' to directories in Popup mode?
01016         bool append_slash = ( d->popup_append_slash
01017             && (completionMode() == TDEGlobalSettings::CompletionPopup ||
01018             completionMode() == TDEGlobalSettings::CompletionPopupAuto ) );
01019 
01020         bool only_dir = ( d->mode == DirCompletion );
01021 
01022         *match = listDirectories( dirList, "", false, only_dir, no_hidden_files,
01023                                   append_slash );
01024     }
01025     else if ( !isRunning() ) {
01026         *match = finished();
01027     }
01028     else {
01029         *match = TQString::null;
01030     }
01031 
01032     return true;
01033 }
01034 
01037 // URLs not handled elsewhere...
01038 //
01039 
01040 bool KURLCompletion::urlCompletion(const MyURL &url, TQString *match)
01041 {
01042     //kdDebug() << "urlCompletion: url = " << *url.kurl() << endl;
01043     if (d->onlyLocalProto && KProtocolInfo::protocolClass(url.protocol()) != ":local")
01044         return false;
01045 
01046     // Use d->cwd as base url in case url is not absolute
01047     KURL url_cwd = KURL::fromPathOrURL( d->cwd );
01048 
01049     // Create an URL with the directory to be listed
01050     KURL url_dir( url_cwd, url.kurl()->url() );
01051 
01052     // Don't try url completion if
01053     // 1. malformed url
01054     // 2. protocol that doesn't have listDir()
01055     // 3. there is no directory (e.g. "ftp://ftp.kd" shouldn't do anything)
01056     // 4. auto or popup completion mode depending on settings
01057 
01058     bool man_or_info = ( url_dir.protocol() == TQString("man")
01059                          || url_dir.protocol() == TQString("info") );
01060 
01061     if ( !url_dir.isValid()
01062          || !KProtocolInfo::supportsListing( url_dir )
01063          || ( !man_or_info
01064               && ( url_dir.directory(false,false).isEmpty()
01065                    || ( isAutoCompletion()
01066                         && !d->url_auto_completion ) ) ) ) {
01067         return false;
01068         }
01069 
01070     url_dir.setFileName(""); // not really nesseccary, but clear the filename anyway...
01071 
01072     // Remove escapes
01073     TQString dir = url_dir.directory( false, false );
01074 
01075     dir = unescape( dir );
01076 
01077     url_dir.setPath( dir );
01078 
01079     // List files if needed
01080     //
01081     if ( !isListedURL( CTUrl, url_dir.prettyURL(), url.file() ) )
01082     {
01083         stop();
01084         clear();
01085 
01086         setListedURL( CTUrl, url_dir.prettyURL(), "" );
01087 
01088         TQValueList<KURL*> url_list;
01089         url_list.append( new KURL( url_dir ) );
01090 
01091         listURLs( url_list, "", false );
01092 
01093         *match = TQString::null;
01094     }
01095     else if ( !isRunning() ) {
01096         *match = finished();
01097     }
01098     else {
01099         *match = TQString::null;
01100     }
01101 
01102     return true;
01103 }
01104 
01107 // Directory and URL listing
01108 //
01109 
01110 /*
01111  * addMatches
01112  *
01113  * Called to add matches to TDECompletion
01114  */
01115 void KURLCompletion::addMatches( const TQStringList &matches )
01116 {
01117     TQStringList::ConstIterator it = matches.begin();
01118     TQStringList::ConstIterator end = matches.end();
01119 
01120     if ( d->complete_url )
01121         for ( ; it != end; it++ )
01122             addItem( d->prepend + KURL::encode_string(*it));
01123     else
01124         for ( ; it != end; it++ )
01125             addItem( d->prepend + (*it));
01126 }
01127 
01128 /*
01129  * listDirectories
01130  *
01131  * List files starting with 'filter' in the given directories,
01132  * either using DirLister or listURLs()
01133  *
01134  * In either case, addMatches() is called with the listed
01135  * files, and eventually finished() when the listing is done
01136  *
01137  * Returns the match if available, or TQString::null if
01138  * DirLister timed out or using tdeio
01139  */
01140 TQString KURLCompletion::listDirectories(
01141         const TQStringList &dirList,
01142         const TQString &filter,
01143         bool only_exe,
01144         bool only_dir,
01145         bool no_hidden,
01146         bool append_slash_to_dir)
01147 {
01148     assert( !isRunning() );
01149 
01150     if ( !::getenv("KURLCOMPLETION_LOCAL_TDEIO") ) {
01151 
01152         //kdDebug() << "Listing (listDirectories): " << dirList << " filter=" << filter << " without TDEIO" << endl;
01153 
01154         // Don't use TDEIO
01155 
01156         if ( d->dirListThread )
01157             d->dirListThread->requestTermination();
01158 
01159         TQStringList dirs;
01160 
01161         for ( TQStringList::ConstIterator it = dirList.begin();
01162               it != dirList.end();
01163               ++it )
01164         {
01165             KURL url;
01166             url.setPath(*it);
01167             if ( kapp->authorizeURLAction( "list", KURL(), url ) )
01168                 dirs.append( *it );
01169         }
01170 
01171         d->dirListThread = new DirectoryListThread( this, dirs, filter, only_exe, only_dir,
01172                                                     no_hidden, append_slash_to_dir );
01173         d->dirListThread->start();
01174         d->dirListThread->wait( 200 );
01175         addMatches( d->dirListThread->matches() );
01176 
01177         return finished();
01178     }
01179     else {
01180 
01181         // Use TDEIO
01182         //kdDebug() << "Listing (listDirectories): " << dirList << " with TDEIO" << endl;
01183 
01184         TQValueList<KURL*> url_list;
01185 
01186         TQStringList::ConstIterator it = dirList.begin();
01187 
01188         for ( ; it != dirList.end(); it++ )
01189             url_list.append( new KURL(*it) );
01190 
01191         listURLs( url_list, filter, only_exe, no_hidden );
01192         // Will call addMatches() and finished()
01193 
01194         return TQString::null;
01195     }
01196 }
01197 
01198 /*
01199  * listURLs
01200  *
01201  * Use TDEIO to list the given urls
01202  *
01203  * addMatches() is called with the listed files
01204  * finished() is called when the listing is done
01205  */
01206 void KURLCompletion::listURLs(
01207         const TQValueList<KURL *> &urls,
01208         const TQString &filter,
01209         bool only_exe,
01210         bool no_hidden )
01211 {
01212     assert( d->list_urls.isEmpty() );
01213     assert( d->list_job == 0L );
01214 
01215     d->list_urls = urls;
01216     d->list_urls_filter = filter;
01217     d->list_urls_only_exe = only_exe;
01218     d->list_urls_no_hidden = no_hidden;
01219 
01220 //  kdDebug() << "Listing URLs: " << urls[0]->prettyURL() << ",..." << endl;
01221 
01222     // Start it off by calling slotIOFinished
01223     //
01224     // This will start a new list job as long as there
01225     // are urls in d->list_urls
01226     //
01227     slotIOFinished(0L);
01228 }
01229 
01230 /*
01231  * slotEntries
01232  *
01233  * Receive files listed by TDEIO and call addMatches()
01234  */
01235 void KURLCompletion::slotEntries(TDEIO::Job*, const TDEIO::UDSEntryList& entries)
01236 {
01237     TQStringList matches;
01238 
01239     TDEIO::UDSEntryListConstIterator it = entries.begin();
01240     TDEIO::UDSEntryListConstIterator end = entries.end();
01241 
01242     TQString filter = d->list_urls_filter;
01243 
01244     int filter_len = filter.length();
01245 
01246     // Iterate over all files
01247     //
01248     for (; it != end; ++it) {
01249         TQString name;
01250         TQString url;
01251         bool is_exe = false;
01252         bool is_dir = false;
01253 
01254         TDEIO::UDSEntry e = *it;
01255         TDEIO::UDSEntry::ConstIterator it_2 = e.begin();
01256 
01257         for( ; it_2 != e.end(); it_2++ ) {
01258             switch ( (*it_2).m_uds ) {
01259                 case TDEIO::UDS_NAME:
01260                     name = (*it_2).m_str;
01261                     break;
01262                 case TDEIO::UDS_ACCESS:
01263                     is_exe = ((*it_2).m_long & MODE_EXE) != 0;
01264                     break;
01265                 case TDEIO::UDS_FILE_TYPE:
01266                     is_dir = ((*it_2).m_long & S_IFDIR) != 0;
01267                     break;
01268                 case TDEIO::UDS_URL:
01269                     url = (*it_2).m_str;
01270                     break;
01271             }
01272         }
01273 
01274         if (!url.isEmpty()) {
01275             // kdDebug() << "KURLCompletion::slotEntries url: " << url << endl;
01276             name = KURL(url).fileName();
01277         }
01278 
01279         // kdDebug() << "KURLCompletion::slotEntries name: " << name << endl;
01280 
01281         if ( name[0] == '.' &&
01282              ( d->list_urls_no_hidden ||
01283                 name.length() == 1 ||
01284                   ( name.length() == 2 && name[1] == '.' ) ) )
01285             continue;
01286 
01287         if ( d->mode == DirCompletion && !is_dir )
01288             continue;
01289 
01290         if ( filter_len == 0 || name.left(filter_len) == filter ) {
01291             if ( is_dir )
01292                 name.append( '/' );
01293 
01294             if ( is_exe || !d->list_urls_only_exe )
01295                 matches.append( name );
01296         }
01297     }
01298 
01299     addMatches( matches );
01300 }
01301 
01302 /*
01303  * slotIOFinished
01304  *
01305  * Called when a TDEIO job is finished.
01306  *
01307  * Start a new list job if there are still urls in
01308  * d->list_urls, otherwise call finished()
01309  */
01310 void KURLCompletion::slotIOFinished( TDEIO::Job * job )
01311 {
01312 //  kdDebug() << "slotIOFinished() " << endl;
01313 
01314     assert( job == d->list_job );
01315 
01316     if ( d->list_urls.isEmpty() ) {
01317 
01318         d->list_job = 0L;
01319 
01320         finished(); // will call TDECompletion::makeCompletion()
01321 
01322     }
01323     else {
01324 
01325         KURL *kurl = d->list_urls.first();
01326 
01327         d->list_urls.remove( kurl );
01328 
01329 //      kdDebug() << "Start TDEIO: " << kurl->prettyURL() << endl;
01330 
01331         d->list_job = TDEIO::listDir( *kurl, false );
01332         d->list_job->addMetaData("no-auth-prompt", "true");
01333 
01334         assert( d->list_job );
01335 
01336         connect( d->list_job,
01337                 TQT_SIGNAL(result(TDEIO::Job*)),
01338                 TQT_SLOT(slotIOFinished(TDEIO::Job*)) );
01339 
01340         connect( d->list_job,
01341                 TQT_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList&)),
01342                 TQT_SLOT( slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList&)) );
01343 
01344         delete kurl;
01345     }
01346 }
01347 
01350 
01351 /*
01352  * postProcessMatch, postProcessMatches
01353  *
01354  * Called by TDECompletion before emitting match() and matches()
01355  *
01356  * Append '/' to directories for file completion. This is
01357  * done here to avoid stat()'ing a lot of files
01358  */
01359 void KURLCompletion::postProcessMatch( TQString *match ) const
01360 {
01361 //  kdDebug() << "KURLCompletion::postProcess: " << *match << endl;
01362 
01363     if ( !match->isEmpty() ) {
01364 
01365         // Add '/' to directories in file completion mode
01366         // unless it has already been done
01367         if ( d->last_compl_type == CTFile )
01368             adjustMatch( *match );
01369     }
01370 }
01371 
01372 void KURLCompletion::adjustMatch( TQString& match ) const
01373 {
01374     if ( match.at( match.length()-1 ) != '/' )
01375     {
01376         TQString copy;
01377 
01378         if ( match.startsWith( TQString("file:") ) )
01379             copy = KURL(match).path();
01380         else
01381             copy = match;
01382 
01383         expandTilde( copy );
01384         expandEnv( copy );
01385         if ( TQDir::isRelativePath(copy) )
01386             copy.prepend( d->cwd + '/' );
01387 
01388 //      kdDebug() << "postProcess: stating " << copy << endl;
01389 
01390         KDE_struct_stat sbuff;
01391 
01392         TQCString file = TQFile::encodeName( copy );
01393 
01394         if ( KDE_stat( (const char*)file, &sbuff ) == 0 ) {
01395             if ( S_ISDIR ( sbuff.st_mode ) )
01396                 match.append( '/' );
01397         }
01398         else {
01399             kdDebug() << "Could not stat file " << copy << endl;
01400         }
01401     }
01402 }
01403 
01404 void KURLCompletion::postProcessMatches( TQStringList * matches ) const
01405 {
01406     if ( !matches->isEmpty() && d->last_compl_type == CTFile ) {
01407         TQStringList::Iterator it = matches->begin();
01408         for (; it != matches->end(); ++it ) {
01409             adjustMatch( (*it) );
01410         }
01411     }
01412 }
01413 
01414 void KURLCompletion::postProcessMatches( TDECompletionMatches * matches ) const
01415 {
01416     if ( !matches->isEmpty() && d->last_compl_type == CTFile ) {
01417         TDECompletionMatches::Iterator it = matches->begin();
01418         for (; it != matches->end(); ++it ) {
01419             adjustMatch( (*it).value() );
01420         }
01421     }
01422 }
01423 
01424 void KURLCompletion::customEvent(TQCustomEvent *e)
01425 {
01426     if ( e->type() == CompletionMatchEvent::uniqueType() ) {
01427 
01428         CompletionMatchEvent *event = static_cast<CompletionMatchEvent *>( e );
01429 
01430         event->completionThread()->wait();
01431 
01432         if ( !isListedURL( CTUser ) ) {
01433             stop();
01434             clear();
01435             addMatches( event->completionThread()->matches() );
01436         }
01437 
01438         setListedURL( CTUser );
01439 
01440         if ( d->userListThread == event->completionThread() )
01441             d->userListThread = 0;
01442 
01443         if ( d->dirListThread == event->completionThread() )
01444             d->dirListThread = 0;
01445 
01446         delete event->completionThread();
01447     }
01448 }
01449 
01450 // static
01451 TQString KURLCompletion::replacedPath( const TQString& text, bool replaceHome, bool replaceEnv )
01452 {
01453     if ( text.isEmpty() )
01454         return text;
01455 
01456     MyURL url( text, TQString::null ); // no need to replace something of our current cwd
01457     if ( !url.kurl()->isLocalFile() )
01458         return text;
01459 
01460     url.filter( replaceHome, replaceEnv );
01461     return url.dir() + url.file();
01462 }
01463 
01464 
01465 TQString KURLCompletion::replacedPath( const TQString& text )
01466 {
01467     return replacedPath( text, d->replace_home, d->replace_env );
01468 }
01469 
01472 // Static functions
01473 
01474 /*
01475  * expandEnv
01476  *
01477  * Expand environment variables in text. Escaped '$' are ignored.
01478  * Return true if expansion was made.
01479  */
01480 static bool expandEnv( TQString &text )
01481 {
01482     // Find all environment variables beginning with '$'
01483     //
01484     int pos = 0;
01485 
01486     bool expanded = false;
01487 
01488     while ( (pos = text.find('$', pos)) != -1 ) {
01489 
01490         // Skip escaped '$'
01491         //
01492         if ( text[pos-1] == '\\' ) {
01493             pos++;
01494         }
01495         // Variable found => expand
01496         //
01497         else {
01498             // Find the end of the variable = next '/' or ' '
01499             //
01500             int pos2 = text.find( ' ', pos+1 );
01501             int pos_tmp = text.find( '/', pos+1 );
01502 
01503             if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) )
01504                 pos2 = pos_tmp;
01505 
01506             if ( pos2 == -1 )
01507                 pos2 = text.length();
01508 
01509             // Replace if the variable is terminated by '/' or ' '
01510             // and defined
01511             //
01512             if ( pos2 >= 0 ) {
01513                 int len = pos2 - pos;
01514                 TQString key    = text.mid( pos+1, len-1);
01515                 TQString value =
01516                     TQString::fromLocal8Bit( ::getenv(key.local8Bit()) );
01517 
01518                 if ( !value.isEmpty() ) {
01519                     expanded = true;
01520                     text.replace( pos, len, value );
01521                     pos = pos + value.length();
01522                 }
01523                 else {
01524                     pos = pos2;
01525                 }
01526             }
01527         }
01528     }
01529 
01530     return expanded;
01531 }
01532 
01533 /*
01534  * expandTilde
01535  *
01536  * Replace "~user" with the users home directory
01537  * Return true if expansion was made.
01538  */
01539 static bool expandTilde(TQString &text)
01540 {
01541     if ( text[0] != '~' )
01542         return false;
01543 
01544     bool expanded = false;
01545 
01546     // Find the end of the user name = next '/' or ' '
01547     //
01548     int pos2 = text.find( ' ', 1 );
01549     int pos_tmp = text.find( '/', 1 );
01550 
01551     if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) )
01552         pos2 = pos_tmp;
01553 
01554     if ( pos2 == -1 )
01555         pos2 = text.length();
01556 
01557     // Replace ~user if the user name is terminated by '/' or ' '
01558     //
01559     if ( pos2 >= 0 ) {
01560 
01561         TQString user = text.mid( 1, pos2-1 );
01562         TQString dir;
01563 
01564         // A single ~ is replaced with $HOME
01565         //
01566         if ( user.isEmpty() ) {
01567             dir = TQDir::homeDirPath();
01568         }
01569         // ~user is replaced with the dir from passwd
01570         //
01571         else {
01572             struct passwd *pw = ::getpwnam( user.local8Bit() );
01573 
01574             if ( pw )
01575                 dir = TQFile::decodeName( pw->pw_dir );
01576 
01577             ::endpwent();
01578         }
01579 
01580         if ( !dir.isEmpty() ) {
01581             expanded = true;
01582             text.replace(0, pos2, dir);
01583         }
01584     }
01585 
01586     return expanded;
01587 }
01588 
01589 /*
01590  * unescape
01591  *
01592  * Remove escapes and return the result in a new string
01593  *
01594  */
01595 static TQString unescape(const TQString &text)
01596 {
01597     TQString result;
01598 
01599     for (uint pos = 0; pos < text.length(); pos++)
01600         if ( text[pos] != '\\' )
01601             result.insert( result.length(), text[pos] );
01602 
01603     return result;
01604 }
01605 
01606 void KURLCompletion::virtual_hook( int id, void* data )
01607 { TDECompletion::virtual_hook( id, data ); }
01608 
01609 #include "kurlcompletion.moc"
01610 

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.