32 #include <tqstringlist.h>
33 #include <tqvaluelist.h>
38 #include <tqtextstream.h>
39 #include <tqdeepcopy.h>
42 #include <kapplication.h>
44 #include <kcompletion.h>
46 #include <kio/jobclasses.h>
48 #include <kprotocolinfo.h>
54 #include <sys/types.h>
60 #include <sys/param.h>
62 #include "kurlcompletion.h"
64 static bool expandTilde(TQString &);
65 static bool expandEnv(TQString &);
67 static TQString unescape(
const TQString &text);
71 #define MODE_EXE (S_IXUSR | S_IXGRP | S_IXOTH)
74 enum ComplType {CTNone=0, CTEnv, CTUser, CTMan, CTExe, CTFile, CTUrl, CTInfo};
76 class CompletionThread;
83 class CompletionMatchEvent :
public TQCustomEvent
86 CompletionMatchEvent( CompletionThread *thread ) :
87 TQCustomEvent( uniqueType() ),
88 m_completionThread( thread )
91 CompletionThread *completionThread()
const {
return m_completionThread; }
92 static int uniqueType() {
return User + 61080; }
95 CompletionThread *m_completionThread;
98 class CompletionThread :
public TQThread
103 m_receiver( receiver ),
104 m_terminationRequested( false )
108 void requestTermination() { m_terminationRequested =
true; }
109 TQDeepCopy<TQStringList> matches()
const {
return m_matches; }
112 void addMatch(
const TQString &match ) { m_matches.append( match ); }
113 bool terminationRequested()
const {
return m_terminationRequested; }
116 if ( !m_terminationRequested )
117 kapp->postEvent( m_receiver,
new CompletionMatchEvent(
this ) );
124 TQStringList m_matches;
125 bool m_terminationRequested;
133 class UserListThread :
public CompletionThread
137 CompletionThread( receiver )
143 static const TQChar tilde =
'~';
146 while ( ( pw = ::getpwent() ) && !terminationRequested() )
147 addMatch( tilde + TQString::fromLocal8Bit( pw->pw_name ) );
157 class DirectoryListThread :
public CompletionThread
161 const TQStringList &dirList,
162 const TQString &filter,
166 bool appendSlashToDir ) :
167 CompletionThread( receiver ),
168 m_dirList( TQDeepCopy<TQStringList>( dirList ) ),
169 m_filter( TQDeepCopy<TQString>( filter ) ),
170 m_onlyExe( onlyExe ),
171 m_onlyDir( onlyDir ),
172 m_noHidden( noHidden ),
173 m_appendSlashToDir( appendSlashToDir )
179 TQStringList m_dirList;
184 bool m_appendSlashToDir;
187 void DirectoryListThread::run()
203 for ( TQStringList::ConstIterator it = m_dirList.begin();
204 it != m_dirList.end() && !terminationRequested();
210 dir = ::opendir( TQFile::encodeName( *it ) );
212 kdDebug() <<
"Failed to open dir: " << *it << endl;
222 TQString path = TQDir::currentDirPath();
223 TQDir::setCurrent( *it );
229 #ifndef HAVE_READDIR_R
230 struct dirent *dirEntry = 0;
231 while ( !terminationRequested() &&
232 (dirEntry = ::readdir( dir)))
234 #if !defined(MAXPATHLEN) && defined(__GNU__)
235 #define MAXPATHLEN UCHAR_MAX
237 struct dirent *dirPosition = (
struct dirent *) malloc(
sizeof(
struct dirent ) + MAXPATHLEN + 1 );
238 struct dirent *dirEntry = 0;
239 while ( !terminationRequested() &&
240 ::readdir_r( dir, dirPosition, &dirEntry ) == 0 && dirEntry )
246 if ( dirEntry->d_name[0] ==
'.' && m_noHidden )
251 if ( dirEntry->d_name[0] ==
'.' && dirEntry->d_name[1] ==
'\0' )
256 if ( dirEntry->d_name[0] ==
'.' && dirEntry->d_name[1] ==
'.' && dirEntry->d_name[2] ==
'\0' )
259 TQString file = TQFile::decodeName( dirEntry->d_name );
261 if ( m_filter.isEmpty() || file.startsWith( m_filter ) ) {
263 if ( m_onlyExe || m_onlyDir || m_appendSlashToDir ) {
264 KDE_struct_stat sbuff;
266 if ( KDE_stat( dirEntry->d_name, &sbuff ) == 0 ) {
270 if ( m_onlyExe && ( sbuff.st_mode & MODE_EXE ) == 0 )
275 if ( m_onlyDir && !S_ISDIR( sbuff.st_mode ) )
280 if ( m_appendSlashToDir && S_ISDIR( sbuff.st_mode ) )
285 kdDebug() <<
"Could not stat file " << file << endl;
296 TQDir::setCurrent( path );
300 #ifdef HAVE_READDIR_R
313 class KURLCompletion::MyURL
316 MyURL(
const TQString &url,
const TQString &cwd);
317 MyURL(
const MyURL &url);
320 KURL *kurl()
const {
return m_kurl; }
322 TQString protocol()
const {
return m_kurl->protocol(); }
324 TQString
dir()
const {
return m_kurl->directory(
false,
false); }
325 TQString file()
const {
return m_kurl->fileName(
false); }
328 TQString url()
const {
return m_url; }
331 bool isURL()
const {
return m_isURL; }
333 void filter(
bool replace_user_dir,
bool replace_env );
336 void init(
const TQString &url,
const TQString &cwd);
343 KURLCompletion::MyURL::MyURL(
const TQString &url,
const TQString &cwd)
348 KURLCompletion::MyURL::MyURL(
const MyURL &url)
350 m_kurl =
new KURL( *(url.m_kurl) );
352 m_isURL = url.m_isURL;
355 void KURLCompletion::MyURL::init(
const TQString &url,
const TQString &cwd)
361 TQString url_copy = url;
364 if ( url_copy[0] ==
'#' ) {
365 if ( url_copy[1] ==
'#' )
366 url_copy.replace( 0, 2, TQString(
"info:") );
368 url_copy.replace( 0, 1, TQString(
"man:") );
372 TQRegExp protocol_regex = TQRegExp(
"^[^/\\s\\\\]*:" );
376 if ( protocol_regex.search( url_copy ) == 0 )
378 m_kurl =
new KURL( url_copy );
387 if ( !TQDir::isRelativePath(url_copy) || url_copy[0] ==
'$' || url_copy[0] ==
'~' )
388 m_kurl->setPath( url_copy );
394 KURL base = KURL::fromPathOrURL( cwd );
397 if ( !TQDir::isRelativePath(url_copy) || url_copy[0] ==
'~' || url_copy[0] ==
'$' )
400 m_kurl->setPath( url_copy );
405 m_kurl =
new KURL( base );
406 m_kurl->addPath( url_copy );
412 KURLCompletion::MyURL::~MyURL()
417 void KURLCompletion::MyURL::filter(
bool replace_user_dir,
bool replace_env )
419 TQString d = dir() + file();
420 if ( replace_user_dir ) expandTilde( d );
421 if ( replace_env ) expandEnv( d );
422 m_kurl->setPath( d );
429 class KURLCompletionPrivate
432 KURLCompletionPrivate() : url_auto_completion(true),
435 ~KURLCompletionPrivate();
437 TQValueList<KURL*> list_urls;
442 bool url_auto_completion;
446 bool popup_append_slash;
449 TQString last_path_listed;
450 TQString last_file_listed;
451 TQString last_prepend;
468 bool list_urls_only_exe;
469 bool list_urls_no_hidden;
470 TQString list_urls_filter;
472 CompletionThread *userListThread;
473 CompletionThread *dirListThread;
476 KURLCompletionPrivate::~KURLCompletionPrivate()
478 if ( userListThread )
479 userListThread->requestTermination();
481 dirListThread->requestTermination();
508 void KURLCompletion::init()
510 d =
new KURLCompletionPrivate;
512 d->cwd = TQDir::homeDirPath();
514 d->replace_home =
true;
515 d->replace_env =
true;
516 d->last_no_hidden =
false;
517 d->last_compl_type = 0;
519 d->mode = KURLCompletion::FileCompletion;
522 KConfig *c = KGlobal::config();
523 KConfigGroupSaver cgs( c,
"URLCompletion" );
525 d->url_auto_completion = c->readBoolEntry(
"alwaysAutoComplete",
true);
526 d->popup_append_slash = c->readBoolEntry(
"popupAppendSlash",
true);
527 d->onlyLocalProto = c->readBoolEntry(
"LocalProtocolsOnly",
false);
552 return d->replace_env;
557 d->replace_env = replace;
562 return d->replace_home;
567 d->replace_home = replace;
579 MyURL url(text, d->cwd);
581 d->compl_text = text;
585 int toRemove = url.file().length() - url.kurl()->query().length();
586 if ( url.kurl()->hasRef() )
587 toRemove += url.kurl()->ref().length() + 1;
588 d->prepend = text.left( text.length() - toRemove );
589 d->complete_url = url.isURL();
595 if ( d->replace_env && envCompletion( url, &match ) )
600 if ( d->replace_home && userCompletion( url, &match ) )
604 url.filter( d->replace_home, d->replace_env );
611 if ( d->mode == ExeCompletion ) {
614 if ( exeCompletion( url, &match ) )
620 if ( urlCompletion( url, &match ) )
623 else if ( d->mode == SystemExeCompletion ) {
626 if ( systemexeCompletion( url, &match ) )
632 if ( urlCompletion( url, &match ) )
638 if ( fileCompletion( url, &match ) )
643 if ( urlCompletion( url, &match ) )
647 setListedURL( CTNone );
650 return TQString::null;
659 TQString KURLCompletion::finished()
661 if ( d->last_compl_type == CTInfo )
662 return KCompletion::makeCompletion( d->compl_text.lower() );
664 return KCompletion::makeCompletion( d->compl_text );
675 return d->list_job || (d->dirListThread && !d->dirListThread->finished());
690 if ( !d->list_urls.isEmpty() ) {
691 TQValueList<KURL*>::Iterator it = d->list_urls.begin();
692 for ( ; it != d->list_urls.end(); it++ )
694 d->list_urls.clear();
697 if ( d->dirListThread ) {
698 d->dirListThread->requestTermination();
699 d->dirListThread = 0;
706 void KURLCompletion::setListedURL(
int complType,
708 const TQString& filter,
711 d->last_compl_type = complType;
712 d->last_path_listed =
dir;
713 d->last_file_listed = filter;
714 d->last_no_hidden = (int)no_hidden;
715 d->last_prepend = d->prepend;
718 bool KURLCompletion::isListedURL(
int complType,
720 const TQString& filter,
723 return d->last_compl_type == complType
724 && ( d->last_path_listed == dir
725 || (dir.isEmpty() && d->last_path_listed.isEmpty()) )
726 && ( filter.startsWith(d->last_file_listed)
727 || (filter.isEmpty() && d->last_file_listed.isEmpty()) )
728 && d->last_no_hidden == (int)no_hidden
729 && d->last_prepend == d->prepend;
737 bool KURLCompletion::isAutoCompletion()
739 return completionMode() == KGlobalSettings::CompletionAuto
740 || completionMode() == KGlobalSettings::CompletionPopup
741 || completionMode() == KGlobalSettings::CompletionMan
742 || completionMode() == KGlobalSettings::CompletionPopupAuto;
749 bool KURLCompletion::userCompletion(
const MyURL &url, TQString *match)
751 if ( url.protocol() !=
"file"
752 || !url.dir().isEmpty()
753 || url.file().at(0) !=
'~' )
756 if ( !isListedURL( CTUser ) ) {
760 if ( !d->userListThread ) {
761 d->userListThread =
new UserListThread(
this );
762 d->userListThread->start();
767 d->userListThread->wait( 200 );
768 TQStringList l = d->userListThread->matches();
781 extern char **environ;
783 bool KURLCompletion::envCompletion(
const MyURL &url, TQString *match)
785 if ( url.file().at(0) !=
'$' )
788 if ( !isListedURL( CTEnv ) ) {
792 char **env = environ;
794 TQString dollar = TQString(
"$");
799 TQString s = TQString::fromLocal8Bit( *env );
801 int pos = s.find(
'=');
807 l.append( dollar + s.left(pos) );
815 setListedURL( CTEnv );
826 bool KURLCompletion::exeCompletion(
const MyURL &url, TQString *match)
828 if ( url.protocol() !=
"file" )
831 TQString dir = url.dir();
833 dir = unescape( dir );
842 TQStringList dirList;
844 if ( !TQDir::isRelativePath(dir) ) {
846 dirList.append( dir );
848 else if ( !dir.isEmpty() && !d->cwd.isEmpty() ) {
850 dirList.append( d->cwd +
'/' + dir );
852 else if ( !url.file().isEmpty() ) {
854 dirList = TQStringList::split(KPATH_SEPARATOR,
855 TQString::fromLocal8Bit(::getenv(
"PATH")));
857 TQStringList::Iterator it = dirList.begin();
859 for ( ; it != dirList.end(); it++ )
864 bool no_hidden_files = url.file().at(0) !=
'.';
868 if ( !isListedURL( CTExe, dir, url.file(), no_hidden_files ) )
873 setListedURL( CTExe, dir, url.file(), no_hidden_files );
875 *match = listDirectories( dirList, url.file(),
true,
false, no_hidden_files );
881 if ( d->dirListThread )
882 setListedURL( CTExe, dir, url.file(), no_hidden_files );
883 *match = TQString::null;
894 bool KURLCompletion::systemexeCompletion(
const MyURL &url, TQString *match)
896 if ( url.protocol() !=
"file" )
899 TQString dir = url.dir();
901 dir = unescape( dir );
910 TQStringList dirList;
912 if ( !url.file().isEmpty() ) {
914 dirList = TQStringList::split(KPATH_SEPARATOR,
915 TQString::fromLocal8Bit(::getenv(
"PATH")));
917 TQStringList::Iterator it = dirList.begin();
919 for ( ; it != dirList.end(); it++ )
924 bool no_hidden_files = url.file().at(0) !=
'.';
928 if ( !isListedURL( CTExe, dir, url.file(), no_hidden_files ) )
933 setListedURL( CTExe, dir, url.file(), no_hidden_files );
935 *match = listDirectories( dirList, url.file(),
true,
false, no_hidden_files );
941 if ( d->dirListThread )
942 setListedURL( CTExe, dir, url.file(), no_hidden_files );
943 *match = TQString::null;
954 bool KURLCompletion::fileCompletion(
const MyURL &url, TQString *match)
956 if ( url.protocol() !=
"file" )
959 TQString dir = url.dir();
961 if (url.url()[0] ==
'.')
963 if (url.url().length() == 1)
966 ( completionMode() == KGlobalSettings::CompletionMan )?
"." :
"..";
969 if (url.url().length() == 2 && url.url()[1]==
'.')
978 dir = unescape( dir );
986 TQStringList dirList;
988 if ( !TQDir::isRelativePath(dir) ) {
990 dirList.append( dir );
992 else if ( !d->cwd.isEmpty() ) {
994 dirList.append( d->cwd +
'/' + dir );
998 bool no_hidden_files = ( url.file().at(0) !=
'.' );
1002 if ( !isListedURL( CTFile, dir,
"", no_hidden_files ) )
1007 setListedURL( CTFile, dir,
"", no_hidden_files );
1010 bool append_slash = ( d->popup_append_slash
1011 && (completionMode() == KGlobalSettings::CompletionPopup ||
1012 completionMode() == KGlobalSettings::CompletionPopupAuto ) );
1014 bool only_dir = ( d->mode == DirCompletion );
1016 *match = listDirectories( dirList,
"",
false, only_dir, no_hidden_files,
1020 *match = finished();
1023 *match = TQString::null;
1034 bool KURLCompletion::urlCompletion(
const MyURL &url, TQString *match)
1041 KURL url_cwd = KURL::fromPathOrURL( d->cwd );
1044 KURL url_dir( url_cwd, url.kurl()->url() );
1052 bool man_or_info = ( url_dir.protocol() == TQString(
"man")
1053 || url_dir.protocol() == TQString(
"info") );
1055 if ( !url_dir.isValid()
1058 && ( url_dir.directory(
false,
false).isEmpty()
1059 || ( isAutoCompletion()
1060 && !d->url_auto_completion ) ) ) ) {
1064 url_dir.setFileName(
"");
1067 TQString dir = url_dir.directory(
false,
false );
1069 dir = unescape( dir );
1071 url_dir.setPath( dir );
1075 if ( !isListedURL( CTUrl, url_dir.prettyURL(), url.file() ) )
1080 setListedURL( CTUrl, url_dir.prettyURL(),
"" );
1082 TQValueList<KURL*> url_list;
1083 url_list.append(
new KURL( url_dir ) );
1085 listURLs( url_list,
"",
false );
1087 *match = TQString::null;
1090 *match = finished();
1093 *match = TQString::null;
1109 void KURLCompletion::addMatches(
const TQStringList &matches )
1111 TQStringList::ConstIterator it = matches.begin();
1112 TQStringList::ConstIterator end = matches.end();
1114 if ( d->complete_url )
1115 for ( ; it != end; it++ )
1116 addItem( d->prepend + KURL::encode_string(*it));
1118 for ( ; it != end; it++ )
1119 addItem( d->prepend + (*it));
1134 TQString KURLCompletion::listDirectories(
1135 const TQStringList &dirList,
1136 const TQString &filter,
1140 bool append_slash_to_dir)
1144 if ( !::getenv(
"KURLCOMPLETION_LOCAL_KIO") ) {
1150 if ( d->dirListThread )
1151 d->dirListThread->requestTermination();
1155 for ( TQStringList::ConstIterator it = dirList.begin();
1156 it != dirList.end();
1161 if ( kapp->authorizeURLAction(
"list", KURL(), url ) )
1165 d->dirListThread =
new DirectoryListThread(
this, dirs, filter, only_exe, only_dir,
1166 no_hidden, append_slash_to_dir );
1167 d->dirListThread->start();
1168 d->dirListThread->wait( 200 );
1169 addMatches( d->dirListThread->matches() );
1178 TQValueList<KURL*> url_list;
1180 TQStringList::ConstIterator it = dirList.begin();
1182 for ( ; it != dirList.end(); it++ )
1183 url_list.append(
new KURL(*it) );
1185 listURLs( url_list, filter, only_exe, no_hidden );
1188 return TQString::null;
1200 void KURLCompletion::listURLs(
1201 const TQValueList<KURL *> &urls,
1202 const TQString &filter,
1206 assert( d->list_urls.isEmpty() );
1207 assert( d->list_job == 0L );
1209 d->list_urls = urls;
1210 d->list_urls_filter = filter;
1211 d->list_urls_only_exe = only_exe;
1212 d->list_urls_no_hidden = no_hidden;
1229 void KURLCompletion::slotEntries(
KIO::Job*,
const KIO::UDSEntryList& entries)
1231 TQStringList matches;
1233 KIO::UDSEntryListConstIterator it = entries.begin();
1234 KIO::UDSEntryListConstIterator end = entries.end();
1236 TQString filter = d->list_urls_filter;
1238 int filter_len = filter.length();
1242 for (; it != end; ++it) {
1245 bool is_exe =
false;
1246 bool is_dir =
false;
1249 KIO::UDSEntry::ConstIterator it_2 = e.begin();
1251 for( ; it_2 != e.end(); it_2++ ) {
1252 switch ( (*it_2).m_uds ) {
1254 name = (*it_2).m_str;
1257 is_exe = ((*it_2).m_long & MODE_EXE) != 0;
1260 is_dir = ((*it_2).m_long & S_IFDIR) != 0;
1263 url = (*it_2).m_str;
1268 if (!url.isEmpty()) {
1270 name = KURL(url).fileName();
1275 if ( name[0] ==
'.' &&
1276 ( d->list_urls_no_hidden ||
1277 name.length() == 1 ||
1278 ( name.length() == 2 && name[1] ==
'.' ) ) )
1281 if ( d->mode == DirCompletion && !is_dir )
1284 if ( filter_len == 0 || name.left(filter_len) == filter ) {
1288 if ( is_exe || !d->list_urls_only_exe )
1289 matches.append( name );
1293 addMatches( matches );
1304 void KURLCompletion::slotIOFinished(
KIO::Job * job )
1308 assert( job == d->list_job );
1310 if ( d->list_urls.isEmpty() ) {
1319 KURL *kurl = d->list_urls.first();
1321 d->list_urls.remove( kurl );
1326 d->list_job->addMetaData(
"no-auth-prompt",
"true");
1328 assert( d->list_job );
1330 connect( d->list_job,
1332 TQT_SLOT(slotIOFinished(
KIO::Job*)) );
1334 connect( d->list_job,
1335 TQT_SIGNAL( entries(
KIO::Job*,
const KIO::UDSEntryList&)),
1336 TQT_SLOT( slotEntries(
KIO::Job*,
const KIO::UDSEntryList&)) );
1353 void KURLCompletion::postProcessMatch( TQString *match )
const
1357 if ( !match->isEmpty() ) {
1361 if ( d->last_compl_type == CTFile )
1362 adjustMatch( *match );
1366 void KURLCompletion::adjustMatch( TQString& match )
const
1368 if ( match.at( match.length()-1 ) !=
'/' )
1372 if ( match.startsWith( TQString(
"file:") ) )
1373 copy = KURL(match).path();
1377 expandTilde( copy );
1379 if ( TQDir::isRelativePath(copy) )
1380 copy.prepend( d->cwd +
'/' );
1384 KDE_struct_stat sbuff;
1386 TQCString file = TQFile::encodeName( copy );
1388 if ( KDE_stat( (
const char*)file, &sbuff ) == 0 ) {
1389 if ( S_ISDIR ( sbuff.st_mode ) )
1390 match.append(
'/' );
1393 kdDebug() <<
"Could not stat file " << copy << endl;
1398 void KURLCompletion::postProcessMatches( TQStringList * matches )
const
1400 if ( !matches->isEmpty() && d->last_compl_type == CTFile ) {
1401 TQStringList::Iterator it = matches->begin();
1402 for (; it != matches->end(); ++it ) {
1403 adjustMatch( (*it) );
1408 void KURLCompletion::postProcessMatches( KCompletionMatches * matches )
const
1410 if ( !matches->isEmpty() && d->last_compl_type == CTFile ) {
1411 KCompletionMatches::Iterator it = matches->begin();
1412 for (; it != matches->end(); ++it ) {
1413 adjustMatch( (*it).value() );
1418 void KURLCompletion::customEvent(TQCustomEvent *e)
1420 if ( e->type() == CompletionMatchEvent::uniqueType() ) {
1422 CompletionMatchEvent *
event =
static_cast<CompletionMatchEvent *
>( e );
1424 event->completionThread()->wait();
1426 if ( !isListedURL( CTUser ) ) {
1429 addMatches( event->completionThread()->matches() );
1432 setListedURL( CTUser );
1434 if ( d->userListThread == event->completionThread() )
1435 d->userListThread = 0;
1437 if ( d->dirListThread == event->completionThread() )
1438 d->dirListThread = 0;
1440 delete event->completionThread();
1447 if ( text.isEmpty() )
1450 MyURL url( text, TQString::null );
1451 if ( !url.kurl()->isLocalFile() )
1454 url.filter( replaceHome, replaceEnv );
1455 return url.dir() + url.file();
1461 return replacedPath( text, d->replace_home, d->replace_env );
1474 static bool expandEnv( TQString &text )
1480 bool expanded =
false;
1482 while ( (pos = text.find(
'$', pos)) != -1 ) {
1486 if ( text[pos-1] ==
'\\' ) {
1494 int pos2 = text.find(
' ', pos+1 );
1495 int pos_tmp = text.find(
'/', pos+1 );
1497 if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) )
1501 pos2 = text.length();
1507 int len = pos2 - pos;
1508 TQString key = text.mid( pos+1, len-1);
1510 TQString::fromLocal8Bit( ::getenv(key.local8Bit()) );
1512 if ( !value.isEmpty() ) {
1514 text.replace( pos, len, value );
1515 pos = pos + value.length();
1533 static bool expandTilde(TQString &text)
1535 if ( text[0] !=
'~' )
1538 bool expanded =
false;
1542 int pos2 = text.find(
' ', 1 );
1543 int pos_tmp = text.find(
'/', 1 );
1545 if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) )
1549 pos2 = text.length();
1555 TQString user = text.mid( 1, pos2-1 );
1560 if ( user.isEmpty() ) {
1561 dir = TQDir::homeDirPath();
1566 struct passwd *pw = ::getpwnam( user.local8Bit() );
1569 dir = TQFile::decodeName( pw->pw_dir );
1574 if ( !dir.isEmpty() ) {
1576 text.replace(0, pos2, dir);
1589 static TQString unescape(
const TQString &text)
1593 for (uint pos = 0; pos < text.length(); pos++)
1594 if ( text[pos] !=
'\\' )
1595 result.insert( result.length(), text[pos] );
1600 void KURLCompletion::virtual_hook(
int id,
void* data )
1601 { KCompletion::virtual_hook(
id, data ); }
1603 #include "kurlcompletion.moc"