/*
Copyright ( C ) 1999 Waldo Bastian < bastian @ kde . org >
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation .
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 <config.h>
# include <sys/param.h>
# include <assert.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# ifdef HAVE_LIMITS_H
# include <limits.h>
# endif
# include <tqdir.h>
# include <tqfile.h>
# include <tqasciidict.h>
# include <tqstrlist.h>
# include "kcmdlineargs.h"
# include <kaboutdata.h>
# include <klocale.h>
# include <kapplication.h>
# include <kglobal.h>
# include <kstringhandler.h>
# include <kstaticdeleter.h>
# ifdef Q_WS_X11
# define DISPLAY "DISPLAY"
# elif defined(Q_WS_QWS)
# define DISPLAY "QWS_DISPLAY"
# endif
# ifdef Q_WS_WIN
# include <win32_utils.h>
# endif
template class TQAsciiDict < TQCString > ;
template class TQPtrList < KCmdLineArgs > ;
class KCmdLineParsedOptions : public TQAsciiDict < TQCString >
{
public :
KCmdLineParsedOptions ( )
: TQAsciiDict < TQCString > ( 7 ) { }
// WABA: Huh?
// The compiler doesn't find KCmdLineParsedOptions::write(s) by itself ???
// WABA: No, because there is another write function that hides the
// write function in the base class even though this function has a
// different signature. (obscure C++ feature)
TQDataStream & save ( TQDataStream & s ) const
{ return TQGDict : : write ( s ) ; }
TQDataStream & load ( TQDataStream & s )
{ return TQGDict : : read ( s ) ; }
protected :
virtual TQDataStream & write ( TQDataStream & s , TQPtrCollection : : Item data ) const
{
TQCString * str = ( TQCString * ) data ;
s < < ( * str ) ;
return s ;
}
virtual TQDataStream & read ( TQDataStream & s , TQPtrCollection : : Item & item )
{
TQCString * str = new TQCString ;
s > > ( * str ) ;
item = ( void * ) str ;
return s ;
}
} ;
class KCmdLineParsedArgs : public TQStrList
{
public :
KCmdLineParsedArgs ( )
: TQStrList ( true ) { }
TQDataStream & save ( TQDataStream & s ) const
{ return TQGList : : write ( s ) ; }
TQDataStream & load ( TQDataStream & s )
{ return TQGList : : read ( s ) ; }
} ;
class KCmdLineArgsList : public TQPtrList < KCmdLineArgs >
{
public :
KCmdLineArgsList ( ) { }
} ;
KCmdLineArgsList * KCmdLineArgs : : argsList = 0 ;
int KCmdLineArgs : : argc = 0 ;
char * * KCmdLineArgs : : argv = 0 ;
char * KCmdLineArgs : : mCwd = 0 ;
static KStaticDeleter < char > mCwdd ;
const KAboutData * KCmdLineArgs : : about = 0 ;
bool KCmdLineArgs : : parsed = false ;
bool KCmdLineArgs : : ignoreUnknown = false ;
//
// Static functions
//
void
KCmdLineArgs : : init ( int _argc , char * * _argv , const char * _appname , const char * programName ,
const char * _description , const char * _version , bool noKApp )
{
init ( _argc , _argv ,
new KAboutData ( _appname , programName , _version , _description ) ,
noKApp ) ;
}
void
KCmdLineArgs : : init ( int _argc , char * * _argv , const char * _appname ,
const char * _description , const char * _version , bool noKApp )
{
init ( _argc , _argv ,
new KAboutData ( _appname , _appname , _version , _description ) ,
noKApp ) ;
}
void
KCmdLineArgs : : initIgnore ( int _argc , char * * _argv , const char * _appname )
{
init ( _argc , _argv ,
new KAboutData ( _appname , _appname , " unknown " , " KDE Application " , false ) ) ;
ignoreUnknown = true ;
}
void
KCmdLineArgs : : init ( const KAboutData * ab )
{
char * * _argv = ( char * * ) malloc ( sizeof ( char * ) ) ;
_argv [ 0 ] = ( char * ) ab - > appName ( ) ;
init ( 1 , _argv , ab , true ) ;
}
void
KCmdLineArgs : : init ( int _argc , char * * _argv , const KAboutData * _about , bool noKApp )
{
argc = _argc ;
argv = _argv ;
if ( ! argv )
{
fprintf ( stderr , " \n \n FAILURE (KCmdLineArgs): \n " ) ;
fprintf ( stderr , " Passing null-pointer to 'argv' is not allowed. \n \n " ) ;
assert ( 0 ) ;
exit ( 255 ) ;
}
// Strip path from argv[0]
if ( argc ) {
char * p = strrchr ( argv [ 0 ] , ' / ' ) ;
if ( p )
argv [ 0 ] = p + 1 ;
}
about = _about ;
parsed = false ;
mCwd = mCwdd . setObject ( mCwd , new char [ PATH_MAX + 1 ] , true ) ;
( void ) getcwd ( mCwd , PATH_MAX ) ;
# ifdef Q_WS_WIN
win32_slashify ( mCwd , PATH_MAX ) ;
# endif
if ( ! noKApp )
KApplication : : addCmdLineOptions ( ) ;
}
TQString KCmdLineArgs : : cwd ( )
{
return TQFile : : decodeName ( TQCString ( mCwd ) ) ;
}
const char * KCmdLineArgs : : appName ( )
{
if ( ! argc ) return 0 ;
return argv [ 0 ] ;
}
void
KCmdLineArgs : : addCmdLineOptions ( const KCmdLineOptions * options , const char * name ,
const char * id , const char * afterId )
{
if ( ! argsList )
argsList = new KCmdLineArgsList ( ) ;
int pos = argsList - > count ( ) ;
if ( pos & & id & & argsList - > last ( ) & & ! argsList - > last ( ) - > name )
pos - - ;
KCmdLineArgs * args ;
int i = 0 ;
for ( args = argsList - > first ( ) ; args ; args = argsList - > next ( ) , i + + )
{
if ( ! id & & ! args - > id )
return ; // Options already present.
if ( id & & args - > id & & ( : : qstrcmp ( id , args - > id ) = = 0 ) )
return ; // Options already present.
if ( afterId & & args - > id & & ( : : qstrcmp ( afterId , args - > id ) = = 0 ) )
pos = i + 1 ;
}
assert ( parsed = = false ) ; // You must add _ALL_ cmd line options
// before accessing the arguments!
args = new KCmdLineArgs ( options , name , id ) ;
argsList - > insert ( pos , args ) ;
}
void
KCmdLineArgs : : saveAppArgs ( TQDataStream & ds )
{
if ( ! parsed )
parseAllArgs ( ) ;
// Remove Qt and KDE options.
removeArgs ( " qt " ) ;
removeArgs ( " kde " ) ;
TQCString qCwd = mCwd ;
ds < < qCwd ;
uint count = argsList ? argsList - > count ( ) : 0 ;
ds < < count ;
if ( ! count ) return ;
KCmdLineArgs * args ;
for ( args = argsList - > first ( ) ; args ; args = argsList - > next ( ) )
{
ds < < TQCString ( args - > id ) ;
args - > save ( ds ) ;
}
}
void
KCmdLineArgs : : loadAppArgs ( TQDataStream & ds )
{
parsed = true ; // don't reparse argc/argv!
// Remove Qt and KDE options.
removeArgs ( " qt " ) ;
removeArgs ( " kde " ) ;
KCmdLineArgs * args ;
if ( argsList ) {
for ( args = argsList - > first ( ) ; args ; args = argsList - > next ( ) )
{
args - > clear ( ) ;
}
}
if ( ds . atEnd ( ) )
return ;
TQCString qCwd ;
ds > > qCwd ;
delete [ ] mCwd ;
mCwd = mCwdd . setObject ( mCwd , new char [ qCwd . length ( ) + 1 ] , true ) ;
strncpy ( mCwd , qCwd . data ( ) , qCwd . length ( ) + 1 ) ;
uint count ;
ds > > count ;
while ( count - - )
{
TQCString id ;
ds > > id ;
assert ( argsList ) ;
for ( args = argsList - > first ( ) ; args ; args = argsList - > next ( ) )
{
if ( args - > id = = id )
{
args - > load ( ds ) ;
break ;
}
}
}
parsed = true ;
}
KCmdLineArgs * KCmdLineArgs : : parsedArgs ( const char * id )
{
KCmdLineArgs * args = argsList ? argsList - > first ( ) : 0 ;
while ( args )
{
if ( ( id & & : : qstrcmp ( args - > id , id ) = = 0 ) | | ( ! id & & ! args - > id ) )
{
if ( ! parsed )
parseAllArgs ( ) ;
return args ;
}
args = argsList - > next ( ) ;
}
return args ;
}
void KCmdLineArgs : : removeArgs ( const char * id )
{
KCmdLineArgs * args = argsList ? argsList - > first ( ) : 0 ;
while ( args )
{
if ( args - > id & & id & & : : qstrcmp ( args - > id , id ) = = 0 )
{
if ( ! parsed )
parseAllArgs ( ) ;
break ;
}
args = argsList - > next ( ) ;
}
if ( args )
delete args ;
}
/*
* @ return :
* 0 - option not found .
* 1 - option found // -fork
* 2 - inverse option found ( ' no ' ) // -nofork
* 3 - option + arg found // -fork now
*
* + 4 - no more options follow // !fork
*/
static int
findOption ( const KCmdLineOptions * options , TQCString & opt ,
const char * & opt_name , const char * & def , bool & enabled )
{
int result ;
bool inverse ;
int len = opt . length ( ) ;
while ( options & & options - > name )
{
result = 0 ;
inverse = false ;
opt_name = options - > name ;
if ( ( opt_name [ 0 ] = = ' : ' ) | | ( opt_name [ 0 ] = = 0 ) )
{
options + + ;
continue ;
}
if ( opt_name [ 0 ] = = ' ! ' )
{
opt_name + + ;
result = 4 ;
}
if ( ( opt_name [ 0 ] = = ' n ' ) & & ( opt_name [ 1 ] = = ' o ' ) )
{
opt_name + = 2 ;
inverse = true ;
}
if ( strncmp ( opt . data ( ) , opt_name , len ) = = 0 )
{
opt_name + = len ;
if ( ! opt_name [ 0 ] )
{
if ( inverse )
return result + 2 ;
if ( ! options - > description )
{
options + + ;
if ( ! options - > name )
return result + 0 ;
TQCString nextOption = options - > name ;
int p = nextOption . find ( ' ' ) ;
if ( p > 0 )
nextOption = nextOption . left ( p ) ;
if ( nextOption [ 0 ] = = ' ! ' )
nextOption = nextOption . mid ( 1 ) ;
if ( strncmp ( nextOption . data ( ) , " no " , 2 ) = = 0 )
{
nextOption = nextOption . mid ( 2 ) ;
enabled = ! enabled ;
}
result = findOption ( options , nextOption , opt_name , def , enabled ) ;
assert ( result ) ;
opt = nextOption ;
return result ;
}
return 1 ;
}
if ( opt_name [ 0 ] = = ' ' )
{
opt_name + + ;
def = options - > def ;
return result + 3 ;
}
}
options + + ;
}
return 0 ;
}
void
KCmdLineArgs : : findOption ( const char * _opt , TQCString opt , int & i , bool _enabled , bool & moreOptions )
{
KCmdLineArgs * args = argsList - > first ( ) ;
const char * opt_name ;
const char * def ;
TQCString argument ;
int j = opt . find ( ' = ' ) ;
if ( j ! = - 1 )
{
argument = opt . mid ( j + 1 ) ;
opt = opt . left ( j ) ;
}
bool enabled = true ;
int result = 0 ;
while ( args )
{
enabled = _enabled ;
result = : : findOption ( args - > options , opt , opt_name , def , enabled ) ;
if ( result ) break ;
args = argsList - > next ( ) ;
}
if ( ! args & & ( _opt [ 0 ] = = ' - ' ) & & _opt [ 1 ] & & ( _opt [ 1 ] ! = ' - ' ) )
{
// Option not found check if it is a valid option
// in the style of -Pprinter1 or ps -aux
int p = 1 ;
while ( true )
{
TQCString singleCharOption = " " ;
singleCharOption [ 0 ] = _opt [ p ] ;
args = argsList - > first ( ) ;
while ( args )
{
enabled = _enabled ;
result = : : findOption ( args - > options , singleCharOption , opt_name , def , enabled ) ;
if ( result ) break ;
args = argsList - > next ( ) ;
}
if ( ! args )
break ; // Unknown argument
p + + ;
if ( result = = 1 ) // Single option
{
args - > setOption ( singleCharOption , enabled ) ;
if ( _opt [ p ] )
continue ; // Next option
else
return ; // Finished
}
else if ( result = = 3 ) // This option takes an argument
{
if ( argument . isEmpty ( ) )
{
argument = _opt + p ;
}
args - > setOption ( singleCharOption , ( const char * ) argument ) ;
return ;
}
break ; // Unknown argument
}
args = 0 ;
result = 0 ;
}
if ( ! args | | ! result )
{
if ( ignoreUnknown )
return ;
enable_i18n ( ) ;
usage ( i18n ( " Unknown option '%1'. " ) . arg ( TQString : : fromLocal8Bit ( _opt ) ) ) ;
}
if ( ( result & 4 ) ! = 0 )
{
result & = ~ 4 ;
moreOptions = false ;
}
if ( result = = 3 ) // This option takes an argument
{
if ( ! enabled )
{
if ( ignoreUnknown )
return ;
enable_i18n ( ) ;
usage ( i18n ( " Unknown option '%1'. " ) . arg ( TQString : : fromLocal8Bit ( _opt ) ) ) ;
}
if ( argument . isEmpty ( ) )
{
i + + ;
if ( i > = argc )
{
enable_i18n ( ) ;
usage ( i18n ( " '%1' missing. " ) . arg ( opt_name ) ) ;
}
argument = argv [ i ] ;
}
args - > setOption ( opt , ( const char * ) argument ) ;
}
else
{
args - > setOption ( opt , enabled ) ;
}
}
void
KCmdLineArgs : : printQ ( const TQString & msg )
{
TQCString localMsg = msg . local8Bit ( ) ;
fprintf ( stdout , " %s " , localMsg . data ( ) ) ;
}
void
KCmdLineArgs : : parseAllArgs ( )
{
bool allowArgs = false ;
bool inOptions = true ;
bool everythingAfterArgIsArgs = false ;
KCmdLineArgs * appOptions = argsList - > last ( ) ;
if ( ! appOptions - > id )
{
const KCmdLineOptions * option = appOptions - > options ;
while ( option & & option - > name )
{
if ( option - > name [ 0 ] = = ' + ' )
allowArgs = true ;
if ( option - > name [ 0 ] = = ' ! ' & & option - > name [ 1 ] = = ' + ' )
{
allowArgs = true ;
everythingAfterArgIsArgs = true ;
}
option + + ;
}
}
for ( int i = 1 ; i < argc ; i + + )
{
if ( ! argv [ i ] )
continue ;
if ( ( argv [ i ] [ 0 ] = = ' - ' ) & & argv [ i ] [ 1 ] & & inOptions )
{
bool enabled = true ;
const char * option = & argv [ i ] [ 1 ] ;
const char * orig = argv [ i ] ;
if ( option [ 0 ] = = ' - ' )
{
option + + ;
argv [ i ] + + ;
if ( ! option [ 0 ] )
{
inOptions = false ;
continue ;
}
}
if ( : : qstrcmp ( option , " help " ) = = 0 )
{
usage ( 0 ) ;
}
else if ( strncmp ( option , " help- " , 5 ) = = 0 )
{
usage ( option + 5 ) ;
}
else if ( ( : : qstrcmp ( option , " version " ) = = 0 ) | |
( : : qstrcmp ( option , " v " ) = = 0 ) )
{
printQ ( TQString ( " Qt: %1 \n " ) . arg ( qVersion ( ) ) ) ;
printQ ( TQString ( " KDE: %1 \n " ) . arg ( KDE_VERSION_STRING ) ) ;
printQ ( TQString ( " %1: %2 \n " ) .
arg ( about - > programName ( ) ) . arg ( about - > version ( ) ) ) ;
exit ( 0 ) ;
} else if ( ( : : qstrcmp ( option , " license " ) = = 0 ) )
{
enable_i18n ( ) ;
printQ ( about - > license ( ) ) ;
printQ ( " \n " ) ;
exit ( 0 ) ;
} else if ( : : qstrcmp ( option , " author " ) = = 0 ) {
enable_i18n ( ) ;
if ( about ) {
const TQValueList < KAboutPerson > authors = about - > authors ( ) ;
if ( ! authors . isEmpty ( ) ) {
TQString authorlist ;
for ( TQValueList < KAboutPerson > : : ConstIterator it = authors . begin ( ) ; it ! = authors . end ( ) ; + + it ) {
TQString email ;
if ( ! ( * it ) . emailAddress ( ) . isEmpty ( ) )
email = " < " + ( * it ) . emailAddress ( ) + " > " ;
authorlist + = TQString ( " " ) + ( * it ) . name ( ) + email + " \n " ;
}
printQ ( i18n ( " the 2nd argument is a list of name+address, one on each line " , " %1 was written by \n %2 " ) . arg ( TQString ( about - > programName ( ) ) ) . arg ( authorlist ) ) ;
}
} else {
printQ ( i18n ( " This application was written by somebody who wants to remain anonymous. " ) ) ;
}
if ( about )
{
if ( ! about - > customAuthorTextEnabled ( ) )
{
if ( about - > bugAddress ( ) . isEmpty ( ) | | about - > bugAddress ( ) = = " submit@bugs.kde.org " )
printQ ( i18n ( " Please use http://bugs.kde.org to report bugs. \n " ) ) ;
else {
if ( about - > authors ( ) . count ( ) = = 1 & & about - > authors ( ) . first ( ) . emailAddress ( ) = = about - > bugAddress ( ) )
printQ ( i18n ( " Please report bugs to %1. \n " ) . arg ( about - > authors ( ) . first ( ) . emailAddress ( ) ) ) ;
else
printQ ( i18n ( " Please report bugs to %1. \n " ) . arg ( about - > bugAddress ( ) ) ) ;
}
}
else
{
printQ ( about - > customAuthorPlainText ( ) ) ;
}
}
exit ( 0 ) ;
} else {
if ( ( option [ 0 ] = = ' n ' ) & & ( option [ 1 ] = = ' o ' ) )
{
option + = 2 ;
enabled = false ;
}
findOption ( orig , option , i , enabled , inOptions ) ;
}
}
else
{
// Check whether appOptions allows these arguments
if ( ! allowArgs )
{
if ( ignoreUnknown )
continue ;
enable_i18n ( ) ;
usage ( i18n ( " Unexpected argument '%1'. " ) . arg ( TQString : : fromLocal8Bit ( argv [ i ] ) ) ) ;
}
else
{
appOptions - > addArgument ( argv [ i ] ) ;
if ( everythingAfterArgIsArgs )
inOptions = false ;
}
}
}
parsed = true ;
}
/**
* For KApplication only :
*
* Return argc
*/
int *
KCmdLineArgs : : qt_argc ( )
{
if ( ! argsList )
KApplication : : addCmdLineOptions ( ) ; // Lazy bastards!
static int qt_argc = - 1 ;
if ( qt_argc ! = - 1 )
return & qt_argc ;
KCmdLineArgs * args = parsedArgs ( " qt " ) ;
assert ( args ) ; // No qt options have been added!
if ( ! argv )
{
fprintf ( stderr , " \n \n FAILURE (KCmdLineArgs): \n " ) ;
fprintf ( stderr , " Application has not called KCmdLineArgs::init(...). \n \n " ) ;
assert ( 0 ) ;
exit ( 255 ) ;
}
assert ( argc > = ( args - > count ( ) + 1 ) ) ;
qt_argc = args - > count ( ) + 1 ;
return & qt_argc ;
}
/**
* For KApplication only :
*
* Return argv
*/
char * * *
KCmdLineArgs : : qt_argv ( )
{
if ( ! argsList )
KApplication : : addCmdLineOptions ( ) ; // Lazy bastards!
static char * * qt_argv ;
if ( qt_argv ! = NULL )
return & qt_argv ;
KCmdLineArgs * args = parsedArgs ( " qt " ) ;
assert ( args ) ; // No qt options have been added!
if ( ! argv )
{
fprintf ( stderr , " \n \n FAILURE (KCmdLineArgs): \n " ) ;
fprintf ( stderr , " Application has not called KCmdLineArgs::init(...). \n \n " ) ;
assert ( 0 ) ;
exit ( 255 ) ;
}
qt_argv = new char * [ args - > count ( ) + 2 ] ;
qt_argv [ 0 ] = qstrdup ( appName ( ) ) ;
int i = 0 ;
for ( ; i < args - > count ( ) ; i + + )
{
qt_argv [ i + 1 ] = qstrdup ( ( char * ) args - > arg ( i ) ) ;
}
qt_argv [ i + 1 ] = 0 ;
return & qt_argv ;
}
void
KCmdLineArgs : : enable_i18n ( )
{
// called twice or too late
if ( KGlobal : : _locale )
return ;
if ( ! KGlobal : : _instance ) {
KInstance * instance = new KInstance ( about ) ;
( void ) instance - > config ( ) ;
// Don't delete instance!
}
}
void
KCmdLineArgs : : usage ( const TQString & error )
{
assert ( KGlobal : : _locale ) ;
TQCString localError = error . local8Bit ( ) ;
if ( localError [ error . length ( ) - 1 ] = = ' \n ' )
localError = localError . left ( error . length ( ) - 1 ) ;
fprintf ( stderr , " %s: %s \n " , argv [ 0 ] , localError . data ( ) ) ;
TQString tmp = i18n ( " Use --help to get a list of available command line options. " ) ;
localError = tmp . local8Bit ( ) ;
fprintf ( stderr , " %s: %s \n " , argv [ 0 ] , localError . data ( ) ) ;
exit ( 254 ) ;
}
void
KCmdLineArgs : : usage ( const char * id )
{
enable_i18n ( ) ;
assert ( argsList ! = 0 ) ; // It's an error to call usage(...) without
// having done addCmdLineOptions first!
TQString optionFormatString = " %1 %2 \n " ;
TQString optionFormatStringDef = " %1 %2 [%3] \n " ;
TQString optionHeaderString = i18n ( " \n %1: \n " ) ;
TQString tmp ;
TQString usage ;
KCmdLineArgs * args = argsList - > last ( ) ;
if ( ! ( args - > id ) & & ( args - > options ) & &
( args - > options - > name ) & & ( args - > options - > name [ 0 ] ! = ' + ' ) )
{
usage = i18n ( " [options] " ) + usage ;
}
while ( args )
{
if ( args - > name )
{
usage = i18n ( " [%1-options] " ) . arg ( args - > name ) + " " + usage ;
}
args = argsList - > prev ( ) ;
}
KCmdLineArgs * appOptions = argsList - > last ( ) ;
if ( ! appOptions - > id )
{
const KCmdLineOptions * option = appOptions - > options ;
while ( option & & option - > name )
{
if ( option - > name [ 0 ] = = ' + ' )
usage = usage + ( option - > name + 1 ) + " " ;
else if ( option - > name [ 0 ] = = ' ! ' & & option - > name [ 1 ] = = ' + ' )
usage = usage + ( option - > name + 2 ) + " " ;
option + + ;
}
}
printQ ( i18n ( " Usage: %1 %2 \n " ) . arg ( argv [ 0 ] ) . arg ( usage ) ) ;
printQ ( " \n " + about - > shortDescription ( ) + " \n " ) ;
printQ ( optionHeaderString . arg ( i18n ( " Generic options " ) ) ) ;
printQ ( optionFormatString . arg ( " --help " , - 25 ) . arg ( i18n ( " Show help about options " ) ) ) ;
args = argsList - > first ( ) ;
while ( args )
{
if ( args - > name & & args - > id )
{
TQString option = TQString ( " --help-%1 " ) . arg ( args - > id ) ;
TQString desc = i18n ( " Show %1 specific options " ) . arg ( args - > name ) ;
printQ ( optionFormatString . arg ( option , - 25 ) . arg ( desc ) ) ;
}
args = argsList - > next ( ) ;
}
printQ ( optionFormatString . arg ( " --help-all " , - 25 ) . arg ( i18n ( " Show all options " ) ) ) ;
printQ ( optionFormatString . arg ( " --author " , - 25 ) . arg ( i18n ( " Show author information " ) ) ) ;
printQ ( optionFormatString . arg ( " -v, --version " , - 25 ) . arg ( i18n ( " Show version information " ) ) ) ;
printQ ( optionFormatString . arg ( " --license " , - 25 ) . arg ( i18n ( " Show license information " ) ) ) ;
printQ ( optionFormatString . arg ( " -- " , - 25 ) . arg ( i18n ( " End of options " ) ) ) ;
args = argsList - > first ( ) ; // Sets current to 1st.
bool showAll = id & & ( : : qstrcmp ( id , " all " ) = = 0 ) ;
if ( ! showAll )
{
while ( args )
{
if ( ! id & & ! args - > id ) break ;
if ( id & & ( : : qstrcmp ( args - > id , id ) = = 0 ) ) break ;
args = argsList - > next ( ) ;
}
}
while ( args )
{
bool hasArgs = false ;
bool hasOptions = false ;
TQString optionsHeader ;
if ( args - > name )
optionsHeader = optionHeaderString . arg ( i18n ( " %1 options " ) . arg ( TQString : : fromLatin1 ( args - > name ) ) ) ;
else
optionsHeader = i18n ( " \n Options: \n " ) ;
while ( args )
{
const KCmdLineOptions * option = args - > options ;
TQCString opt = " " ;
//
while ( option & & option - > name )
{
TQString description ;
TQString descriptionRest ;
TQStringList dl ;
// Option header
if ( option - > name [ 0 ] = = ' : ' )
{
if ( option - > description )
{
optionsHeader = " \n " + i18n ( option - > description ) ;
if ( ! optionsHeader . endsWith ( " \n " ) )
optionsHeader . append ( " \n " ) ;
hasOptions = false ;
}
option + + ;
continue ;
}
// Free-form comment
if ( option - > name [ 0 ] = = 0 )
{
if ( option - > description )
{
TQString tmp = " \n " + i18n ( option - > description ) ;
if ( ! tmp . endsWith ( " \n " ) )
tmp . append ( " \n " ) ;
printQ ( tmp ) ;
}
option + + ;
continue ;
}
// Options
if ( option - > description )
{
description = i18n ( option - > description ) ;
dl = TQStringList : : split ( " \n " , description , true ) ;
description = dl . first ( ) ;
dl . remove ( dl . begin ( ) ) ;
}
TQCString name = option - > name ;
if ( name [ 0 ] = = ' ! ' )
name = name . mid ( 1 ) ;
if ( name [ 0 ] = = ' + ' )
{
if ( ! hasArgs )
{
printQ ( i18n ( " \n Arguments: \n " ) ) ;
hasArgs = true ;
}
name = name . mid ( 1 ) ;
if ( ( name [ 0 ] = = ' [ ' ) & & ( name [ name . length ( ) - 1 ] = = ' ] ' ) )
name = name . mid ( 1 , name . length ( ) - 2 ) ;
printQ ( optionFormatString . arg ( QString ( name ) , - 25 )
. arg ( description ) ) ;
}
else
{
if ( ! hasOptions )
{
printQ ( optionsHeader ) ;
hasOptions = true ;
}
if ( ( name . length ( ) = = 1 ) | | ( name [ 1 ] = = ' ' ) )
name = " - " + name ;
else
name = " -- " + name ;
if ( ! option - > description )
{
opt = name + " , " ;
}
else
{
opt = opt + name ;
if ( ! option - > def )
{
printQ ( optionFormatString . arg ( QString ( opt ) , - 25 )
. arg ( description ) ) ;
}
else
{
printQ ( optionFormatStringDef . arg ( QString ( opt ) , - 25 )
. arg ( description ) . arg ( option - > def ) ) ;
}
opt = " " ;
}
}
for ( TQStringList : : Iterator it = dl . begin ( ) ;
it ! = dl . end ( ) ;
+ + it )
{
printQ ( optionFormatString . arg ( " " , - 25 ) . arg ( * it ) ) ;
}
option + + ;
}
args = argsList - > next ( ) ;
if ( ! args | | args - > name | | ! args - > id ) break ;
}
if ( ! showAll ) break ;
}
exit ( 254 ) ;
}
//
// Member functions
//
/**
* Constructor .
*
* The given arguments are assumed to be constants .
*/
KCmdLineArgs : : KCmdLineArgs ( const KCmdLineOptions * _options ,
const char * _name , const char * _id )
: options ( _options ) , name ( _name ) , id ( _id )
{
parsedOptionList = 0 ;
parsedArgList = 0 ;
isQt = ( : : qstrcmp ( id , " qt " ) = = 0 ) ;
}
/**
* Destructor .
*/
KCmdLineArgs : : ~ KCmdLineArgs ( )
{
delete parsedOptionList ;
delete parsedArgList ;
if ( argsList )
argsList - > removeRef ( this ) ;
}
void
KCmdLineArgs : : clear ( )
{
delete parsedArgList ;
parsedArgList = 0 ;
delete parsedOptionList ;
parsedOptionList = 0 ;
}
void
KCmdLineArgs : : reset ( )
{
if ( argsList ) {
argsList - > setAutoDelete ( true ) ;
argsList - > clear ( ) ;
delete argsList ;
argsList = 0 ;
}
parsed = false ;
}
void
KCmdLineArgs : : save ( TQDataStream & ds ) const
{
uint count = 0 ;
if ( parsedOptionList )
parsedOptionList - > save ( ds ) ;
else
ds < < count ;
if ( parsedArgList )
parsedArgList - > save ( ds ) ;
else
ds < < count ;
}
void
KCmdLineArgs : : load ( TQDataStream & ds )
{
if ( ! parsedOptionList ) parsedOptionList = new KCmdLineParsedOptions ;
if ( ! parsedArgList ) parsedArgList = new KCmdLineParsedArgs ;
parsedOptionList - > load ( ds ) ;
parsedArgList - > load ( ds ) ;
if ( parsedOptionList - > count ( ) = = 0 )
{
delete parsedOptionList ;
parsedOptionList = 0 ;
}
if ( parsedArgList - > count ( ) = = 0 )
{
delete parsedArgList ;
parsedArgList = 0 ;
}
}
void
KCmdLineArgs : : setOption ( const TQCString & opt , bool enabled )
{
if ( isQt )
{
// Qt does it own parsing.
TQCString arg = " - " ;
if ( ! enabled )
arg + = " no " ;
arg + = opt ;
addArgument ( arg ) ;
}
if ( ! parsedOptionList ) {
parsedOptionList = new KCmdLineParsedOptions ;
parsedOptionList - > setAutoDelete ( true ) ;
}
if ( enabled )
parsedOptionList - > replace ( opt , new TQCString ( " t " ) ) ;
else
parsedOptionList - > replace ( opt , new TQCString ( " f " ) ) ;
}
void
KCmdLineArgs : : setOption ( const TQCString & opt , const char * value )
{
if ( isQt )
{
// Qt does it's own parsing.
TQCString arg = " - " ;
arg + = opt ;
addArgument ( arg ) ;
addArgument ( value ) ;
# ifdef Q_WS_X11
// Hack coming up!
if ( arg = = " -display " )
{
setenv ( DISPLAY , value , true ) ;
}
# endif
}
if ( ! parsedOptionList ) {
parsedOptionList = new KCmdLineParsedOptions ;
parsedOptionList - > setAutoDelete ( true ) ;
}
parsedOptionList - > insert ( opt , new TQCString ( value ) ) ;
}
TQCString
KCmdLineArgs : : getOption ( const char * _opt ) const
{
TQCString * value = 0 ;
if ( parsedOptionList )
{
value = parsedOptionList - > find ( _opt ) ;
}
if ( value )
return ( * value ) ;
// Look up the default.
const char * opt_name ;
const char * def ;
bool dummy = true ;
TQCString opt = _opt ;
int result = : : findOption ( options , opt , opt_name , def , dummy ) & ~ 4 ;
if ( result ! = 3 )
{
fprintf ( stderr , " \n \n FAILURE (KCmdLineArgs): \n " ) ;
fprintf ( stderr , " Application requests for getOption( \" %s \" ) but the \" %s \" option \n " ,
_opt , _opt ) ;
fprintf ( stderr , " has never been specified via addCmdLineOptions( ... ) \n \n " ) ;
assert ( 0 ) ;
exit ( 255 ) ;
}
return TQCString ( def ) ;
}
QCStringList
KCmdLineArgs : : getOptionList ( const char * _opt ) const
{
QCStringList result ;
if ( ! parsedOptionList )
return result ;
while ( true )
{
TQCString * value = parsedOptionList - > take ( _opt ) ;
if ( ! value )
break ;
result . prepend ( * value ) ;
delete value ;
}
// Reinsert items in dictionary
// WABA: This is rather silly, but I don't want to add restrictions
// to the API like "you can only call this function once".
// I can't access all items without taking them out of the list.
// So taking them out and then putting them back is the only way.
for ( QCStringList : : ConstIterator it = result . begin ( ) ;
it ! = result . end ( ) ;
+ + it )
{
parsedOptionList - > insert ( _opt , new TQCString ( * it ) ) ;
}
return result ;
}
bool
KCmdLineArgs : : isSet ( const char * _opt ) const
{
// Look up the default.
const char * opt_name ;
const char * def ;
bool dummy = true ;
TQCString opt = _opt ;
int result = : : findOption ( options , opt , opt_name , def , dummy ) & ~ 4 ;
if ( result = = 0 )
{
fprintf ( stderr , " \n \n FAILURE (KCmdLineArgs): \n " ) ;
fprintf ( stderr , " Application requests for isSet( \" %s \" ) but the \" %s \" option \n " ,
_opt , _opt ) ;
fprintf ( stderr , " has never been specified via addCmdLineOptions( ... ) \n \n " ) ;
assert ( 0 ) ;
exit ( 255 ) ;
}
TQCString * value = 0 ;
if ( parsedOptionList )
{
value = parsedOptionList - > find ( opt ) ;
}
if ( value )
{
if ( result = = 3 )
return true ;
else
return ( ( * value ) [ 0 ] = = ' t ' ) ;
}
if ( result = = 3 )
return false ; // String option has 'false' as default.
// We return 'true' as default if the option was listed as '-nofork'
// We return 'false' as default if the option was listed as '-fork'
return ( result = = 2 ) ;
}
int
KCmdLineArgs : : count ( ) const
{
if ( ! parsedArgList )
return 0 ;
return parsedArgList - > count ( ) ;
}
const char *
KCmdLineArgs : : arg ( int n ) const
{
if ( ! parsedArgList | | ( n > = ( int ) parsedArgList - > count ( ) ) )
{
fprintf ( stderr , " \n \n FAILURE (KCmdLineArgs): Argument out of bounds \n " ) ;
fprintf ( stderr , " Application requests for arg(%d) without checking count() first. \n " ,
n ) ;
assert ( 0 ) ;
exit ( 255 ) ;
}
return parsedArgList - > at ( n ) ;
}
KURL
KCmdLineArgs : : url ( int n ) const
{
return makeURL ( arg ( n ) ) ;
}
KURL KCmdLineArgs : : makeURL ( const char * _urlArg )
{
const TQString urlArg = TQFile : : decodeName ( _urlArg ) ;
TQFileInfo fileInfo ( urlArg ) ;
if ( ! fileInfo . isRelative ( ) ) { // i.e. starts with '/', on unix
KURL result ;
result . setPath ( urlArg ) ;
return result ; // Absolute path.
}
if ( KURL : : isRelativeURL ( urlArg ) | | fileInfo . exists ( ) ) {
KURL result ;
result . setPath ( cwd ( ) + ' / ' + urlArg ) ;
result . cleanPath ( ) ;
return result ; // Relative path
}
return KURL ( urlArg ) ; // Argument is a URL
}
void
KCmdLineArgs : : addArgument ( const char * argument )
{
if ( ! parsedArgList )
parsedArgList = new KCmdLineParsedArgs ;
parsedArgList - > append ( argument ) ;
}
static const KCmdLineOptions kde_tempfile_option [ ] =
{
{ " tempfile " , I18N_NOOP ( " The files/URLs opened by the application will be deleted after use " ) , 0 } ,
KCmdLineLastOption
} ;
void
KCmdLineArgs : : addTempFileOption ( )
{
KCmdLineArgs : : addCmdLineOptions ( kde_tempfile_option , " KDE-tempfile " , " kde-tempfile " ) ;
}
bool KCmdLineArgs : : isTempFileSet ( )
{
KCmdLineArgs * args = KCmdLineArgs : : parsedArgs ( " kde-tempfile " ) ;
if ( args )
return args - > isSet ( " tempfile " ) ;
return false ;
}