21 #include <sys/param.h>
35 #include <tqasciidict.h>
36 #include <tqstrlist.h>
38 #include "kcmdlineargs.h"
39 #include <kaboutdata.h>
41 #include <kapplication.h>
43 #include <kstringhandler.h>
44 #include <kstaticdeleter.h>
47 #define DISPLAY "DISPLAY"
48 #elif defined(Q_WS_QWS)
49 #define DISPLAY "QWS_DISPLAY"
53 #include <win32_utils.h>
56 template class TQAsciiDict<TQCString>;
57 template class TQPtrList<KCmdLineArgs>;
59 class KCmdLineParsedOptions :
public TQAsciiDict<TQCString>
62 KCmdLineParsedOptions()
63 : TQAsciiDict<TQCString>( 7 ) { }
70 TQDataStream&
save( TQDataStream &s)
const
71 {
return TQGDict::write(s); }
73 TQDataStream& load( TQDataStream &s)
74 {
return TQGDict::read(s); }
77 virtual TQDataStream& write( TQDataStream &s, TQPtrCollection::Item data)
const
79 TQCString *str = (TQCString *) data;
84 virtual TQDataStream& read( TQDataStream &s, TQPtrCollection::Item &item)
86 TQCString *str =
new TQCString;
94 class KCmdLineParsedArgs :
public TQStrList
98 : TQStrList( true ) { }
99 TQDataStream&
save( TQDataStream &s)
const
100 {
return TQGList::write(s); }
102 TQDataStream& load( TQDataStream &s)
103 {
return TQGList::read(s); }
107 class KCmdLineArgsList:
public TQPtrList<KCmdLineArgs>
110 KCmdLineArgsList() { }
113 KCmdLineArgsList *KCmdLineArgs::argsList = 0;
114 int KCmdLineArgs::argc = 0;
115 char **KCmdLineArgs::argv = 0;
116 char *KCmdLineArgs::mCwd = 0;
119 bool KCmdLineArgs::parsed =
false;
120 bool KCmdLineArgs::ignoreUnknown =
false;
128 const char *_description,
const char *_version,
bool noKApp)
131 new KAboutData(_appname, programName, _version, _description),
137 const char *_description,
const char *_version,
bool noKApp)
140 new KAboutData(_appname, _appname, _version, _description),
145 KCmdLineArgs::initIgnore(
int _argc,
char **_argv,
const char *_appname )
148 new KAboutData(_appname, _appname,
"unknown",
"KDE Application",
false));
149 ignoreUnknown =
true;
155 char **_argv = (
char **) malloc(
sizeof(
char *));
156 _argv[0] = (
char *) ab->
appName();
157 init(1,_argv,ab,
true);
169 fprintf(stderr,
"\n\nFAILURE (KCmdLineArgs):\n");
170 fprintf(stderr,
"Passing null-pointer to 'argv' is not allowed.\n\n");
178 char *p = strrchr( argv[0],
'/');
185 mCwd = mCwdd.
setObject(mCwd,
new char [PATH_MAX+1],
true);
186 (void) getcwd(mCwd, PATH_MAX);
188 win32_slashify(mCwd, PATH_MAX);
196 return TQFile::decodeName(TQCString(mCwd));
207 const char *
id,
const char *afterId)
210 argsList =
new KCmdLineArgsList();
212 int pos = argsList->count();
214 if (pos &&
id && argsList->last() && !argsList->last()->name)
219 for(args = argsList->first(); args; args = argsList->next(), i++)
221 if (!
id && !args->id)
224 if (
id && args->id && (::qstrcmp(
id, args->id) == 0))
227 if (afterId && args->id && (::qstrcmp(afterId, args->id) == 0))
231 assert( parsed ==
false );
234 argsList->insert(pos, args);
238 KCmdLineArgs::saveAppArgs( TQDataStream &ds)
247 TQCString qCwd = mCwd;
250 uint
count = argsList ? argsList->count() : 0;
256 for(args = argsList->first(); args; args = argsList->next())
258 ds << TQCString(args->id);
274 for(args = argsList->first(); args; args = argsList->next())
287 mCwd = mCwdd.
setObject(mCwd,
new char[qCwd.length()+1],
true);
288 strncpy(mCwd, qCwd.data(), qCwd.length()+1);
298 for(args = argsList->first(); args; args = argsList->next())
315 if ((
id && ::qstrcmp(args->id,
id) == 0) || (!
id && !args->id))
321 args = argsList->next();
327 void KCmdLineArgs::removeArgs(
const char *
id)
332 if (args->id &&
id && ::qstrcmp(args->id,
id) == 0)
338 args = argsList->next();
356 const char *&opt_name,
const char *&def,
bool &enabled)
360 int len = opt.length();
361 while(options && options->
name)
365 opt_name = options->
name;
366 if ((opt_name[0] ==
':') || (opt_name[0] == 0))
372 if (opt_name[0] ==
'!')
377 if ((opt_name[0] ==
'n') && (opt_name[1] ==
'o'))
382 if (strncmp(opt.data(), opt_name, len) == 0)
395 TQCString nextOption = options->
name;
396 int p = nextOption.find(
' ');
398 nextOption = nextOption.left(p);
399 if (nextOption[0] ==
'!')
400 nextOption = nextOption.mid(1);
401 if (strncmp(nextOption.data(),
"no", 2) == 0)
403 nextOption = nextOption.mid(2);
406 result = findOption(options, nextOption, opt_name, def, enabled);
414 if (opt_name[0] ==
' ')
429 KCmdLineArgs::findOption(
const char *_opt, TQCString opt,
int &i,
bool _enabled,
bool &moreOptions)
432 const char *opt_name;
435 int j = opt.find(
'=');
438 argument = opt.mid(j+1);
447 result = ::findOption(args->options, opt, opt_name, def, enabled);
449 args = argsList->next();
451 if (!args && (_opt[0] ==
'-') && _opt[1] && (_opt[1] !=
'-'))
458 TQCString singleCharOption =
" ";
459 singleCharOption[0] = _opt[p];
460 args = argsList->first();
464 result = ::findOption(args->options, singleCharOption, opt_name, def, enabled);
466 args = argsList->next();
474 args->setOption(singleCharOption, enabled);
480 else if (result == 3)
482 if (argument.isEmpty())
486 args->setOption(singleCharOption, (
const char*)argument);
495 if (!args || !result)
500 usage( i18n(
"Unknown option '%1'.").
arg(TQString::fromLocal8Bit(_opt)));
503 if ((result & 4) != 0)
516 usage( i18n(
"Unknown option '%1'.").
arg(TQString::fromLocal8Bit(_opt)));
518 if (argument.isEmpty())
524 usage( i18n(
"'%1' missing.").
arg( opt_name));
528 args->setOption(opt, (
const char*)argument);
532 args->setOption(opt, enabled);
537 KCmdLineArgs::printQ(
const TQString &msg)
539 TQCString localMsg = msg.local8Bit();
540 fprintf(stdout,
"%s", localMsg.data());
544 KCmdLineArgs::parseAllArgs()
546 bool allowArgs =
false;
547 bool inOptions =
true;
548 bool everythingAfterArgIsArgs =
false;
553 while(option && option->
name)
555 if (option->
name[0] ==
'+')
557 if ( option->
name[0] ==
'!' && option->
name[1] ==
'+' )
560 everythingAfterArgIsArgs =
true;
565 for(
int i = 1; i < argc; i++)
570 if ((argv[i][0] ==
'-') && argv[i][1] && inOptions)
573 const char *option = &argv[i][1];
574 const char *orig = argv[i];
575 if (option[0] ==
'-')
585 if (::qstrcmp(option,
"help") == 0)
589 else if (strncmp(option,
"help-",5) == 0)
593 else if ( (::qstrcmp(option,
"version") == 0) ||
594 (::qstrcmp(option,
"v") == 0))
596 printQ( TQString(
"Qt: %1\n").
arg(qVersion()));
597 printQ( TQString(
"KDE: %1\n").
arg(KDE_VERSION_STRING));
598 printQ( TQString(
"%1: %2\n").
601 }
else if ( (::qstrcmp(option,
"license") == 0) )
607 }
else if ( ::qstrcmp( option,
"author") == 0 ) {
610 const TQValueList<KAboutPerson> authors = about->
authors();
611 if ( !authors.isEmpty() ) {
613 for (TQValueList<KAboutPerson>::ConstIterator it = authors.begin(); it != authors.end(); ++it ) {
615 if ( !(*it).emailAddress().isEmpty() )
616 email =
" <" + (*it).emailAddress() +
">";
617 authorlist += TQString(
" ") + (*it).name() + email +
"\n";
619 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 ) );
622 printQ( i18n(
"This application was written by somebody who wants to remain anonymous.") );
629 printQ( i18n(
"Please use http://bugs.kde.org to report bugs.\n" ) );
632 printQ( i18n(
"Please report bugs to %1.\n" ).arg( about->
authors().first().emailAddress() ) );
634 printQ( i18n(
"Please report bugs to %1.\n" ).
arg(about->
bugAddress()) );
644 if ((option[0] ==
'n') && (option[1] ==
'o'))
649 findOption(orig, option, i, enabled, inOptions);
660 usage( i18n(
"Unexpected argument '%1'.").
arg(TQString::fromLocal8Bit(argv[i])));
664 appOptions->addArgument(argv[i]);
665 if (everythingAfterArgIsArgs)
679 KCmdLineArgs::qt_argc()
684 static int qt_argc = -1;
692 fprintf(stderr,
"\n\nFAILURE (KCmdLineArgs):\n");
693 fprintf(stderr,
"Application has not called KCmdLineArgs::init(...).\n\n");
699 assert(argc >= (args->
count()+1));
700 qt_argc = args->
count() +1;
710 KCmdLineArgs::qt_argv()
715 static char** qt_argv;
716 if( qt_argv != NULL )
723 fprintf(stderr,
"\n\nFAILURE (KCmdLineArgs):\n");
724 fprintf(stderr,
"Application has not called KCmdLineArgs::init(...).\n\n");
730 qt_argv =
new char*[ args->
count() + 2 ];
731 qt_argv[ 0 ] = qstrdup(
appName());
733 for(; i < args->
count(); i++)
735 qt_argv[i+1] = qstrdup((
char *) args->
arg(i));
746 if (KGlobal::_locale)
749 if (!KGlobal::_instance) {
751 (void) instance->
config();
759 assert(KGlobal::_locale);
760 TQCString localError = error.local8Bit();
761 if (localError[error.length()-1] ==
'\n')
762 localError = localError.left(error.length()-1);
763 fprintf(stderr,
"%s: %s\n", argv[0], localError.data());
765 TQString tmp = i18n(
"Use --help to get a list of available command line options.");
766 localError = tmp.local8Bit();
767 fprintf(stderr,
"%s: %s\n", argv[0], localError.data());
775 assert(argsList != 0);
778 TQString optionFormatString =
" %1 %2\n";
779 TQString optionFormatStringDef =
" %1 %2 [%3]\n";
780 TQString optionHeaderString = i18n(
"\n%1:\n");
786 if (!(args->id) && (args->options) &&
787 (args->options->
name) && (args->options->
name[0] !=
'+'))
789 usage = i18n(
"[options] ")+
usage;
796 usage = i18n(
"[%1-options]").arg(args->name)+
" "+
usage;
798 args = argsList->prev();
805 while(option && option->
name)
807 if (option->
name[0] ==
'+')
808 usage = usage + (option->
name+1) +
" ";
809 else if ( option->
name[0] ==
'!' && option->
name[1] ==
'+' )
810 usage = usage + (option->
name+2) +
" ";
816 printQ(i18n(
"Usage: %1 %2\n").
arg(argv[0]).
arg(usage));
819 printQ(optionHeaderString.arg(i18n(
"Generic options")));
820 printQ(optionFormatString.arg(
"--help", -25).arg(i18n(
"Show help about options")));
822 args = argsList->first();
825 if (args->name && args->id)
827 TQString option = TQString(
"--help-%1").arg(args->id);
828 TQString desc = i18n(
"Show %1 specific options").arg(args->name);
830 printQ(optionFormatString.arg(option, -25).arg(desc));
832 args = argsList->next();
835 printQ(optionFormatString.arg(
"--help-all",-25).arg(i18n(
"Show all options")));
836 printQ(optionFormatString.arg(
"--author",-25).arg(i18n(
"Show author information")));
837 printQ(optionFormatString.arg(
"-v, --version",-25).arg(i18n(
"Show version information")));
838 printQ(optionFormatString.arg(
"--license",-25).arg(i18n(
"Show license information")));
839 printQ(optionFormatString.arg(
"--", -25).arg(i18n(
"End of options")));
841 args = argsList->first();
843 bool showAll =
id && (::qstrcmp(
id,
"all") == 0);
849 if (!
id && !args->id)
break;
850 if (
id && (::qstrcmp(args->id,
id) == 0))
break;
851 args = argsList->next();
857 bool hasArgs =
false;
858 bool hasOptions =
false;
859 TQString optionsHeader;
861 optionsHeader = optionHeaderString.arg(i18n(
"%1 options").
arg(TQString::fromLatin1(args->name)));
863 optionsHeader = i18n(
"\nOptions:\n");
870 while(option && option->
name)
872 TQString description;
873 TQString descriptionRest;
877 if (option->
name[0] ==
':')
882 if (!optionsHeader.endsWith(
"\n"))
883 optionsHeader.append(
"\n");
891 if (option->
name[0] == 0)
896 if (!tmp.endsWith(
"\n"))
908 dl = TQStringList::split(
"\n", description,
true);
909 description = dl.first();
910 dl.remove( dl.begin() );
912 TQCString name = option->
name;
920 printQ(i18n(
"\nArguments:\n"));
925 if ((name[0] ==
'[') && (name[name.length()-1] ==
']'))
926 name = name.mid(1, name.length()-2);
927 printQ(optionFormatString.arg(QString(name), -25)
934 printQ(optionsHeader);
938 if ((name.length() == 1) || (name[1] ==
' '))
951 printQ(optionFormatString.arg(QString(opt), -25)
956 printQ(optionFormatStringDef.arg(QString(opt), -25)
957 .arg(description).arg(option->
def));
962 for(TQStringList::Iterator it = dl.begin();
966 printQ(optionFormatString.arg(
"", -25).arg(*it));
971 args = argsList->next();
972 if (!args || args->name || !args->id)
break;
990 const char *_name,
const char *_id)
991 : options(_options), name(_name), id(_id)
993 parsedOptionList = 0;
995 isQt = (::qstrcmp(
id,
"qt") == 0);
1003 delete parsedOptionList;
1004 delete parsedArgList;
1006 argsList->removeRef(
this);
1012 delete parsedArgList;
1014 delete parsedOptionList;
1015 parsedOptionList = 0;
1022 argsList->setAutoDelete(
true );
1031 KCmdLineArgs::save( TQDataStream &ds)
const
1034 if (parsedOptionList)
1035 parsedOptionList->save( ds );
1040 parsedArgList->save( ds );
1046 KCmdLineArgs::load( TQDataStream &ds)
1048 if (!parsedOptionList) parsedOptionList =
new KCmdLineParsedOptions;
1049 if (!parsedArgList) parsedArgList =
new KCmdLineParsedArgs;
1051 parsedOptionList->load( ds );
1052 parsedArgList->load( ds );
1054 if (parsedOptionList->count() == 0)
1056 delete parsedOptionList;
1057 parsedOptionList = 0;
1059 if (parsedArgList->count() == 0)
1061 delete parsedArgList;
1067 KCmdLineArgs::setOption(
const TQCString &opt,
bool enabled)
1072 TQCString
arg =
"-";
1078 if (!parsedOptionList) {
1079 parsedOptionList =
new KCmdLineParsedOptions;
1080 parsedOptionList->setAutoDelete(
true);
1084 parsedOptionList->replace( opt,
new TQCString(
"t") );
1086 parsedOptionList->replace( opt,
new TQCString(
"f") );
1090 KCmdLineArgs::setOption(
const TQCString &opt,
const char *value)
1095 TQCString arg =
"-";
1102 if (arg ==
"-display")
1104 setenv(DISPLAY, value,
true);
1108 if (!parsedOptionList) {
1109 parsedOptionList =
new KCmdLineParsedOptions;
1110 parsedOptionList->setAutoDelete(
true);
1113 parsedOptionList->insert( opt,
new TQCString(value) );
1119 TQCString *value = 0;
1120 if (parsedOptionList)
1122 value = parsedOptionList->find(_opt);
1129 const char *opt_name;
1132 TQCString opt = _opt;
1133 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
1137 fprintf(stderr,
"\n\nFAILURE (KCmdLineArgs):\n");
1138 fprintf(stderr,
"Application requests for getOption(\"%s\") but the \"%s\" option\n",
1140 fprintf(stderr,
"has never been specified via addCmdLineOptions( ... )\n\n");
1145 return TQCString(def);
1151 QCStringList result;
1152 if (!parsedOptionList)
1157 TQCString *value = parsedOptionList->take(_opt);
1160 result.prepend(*value);
1169 for(QCStringList::ConstIterator it=result.begin();
1173 parsedOptionList->insert(_opt,
new TQCString(*it));
1182 const char *opt_name;
1185 TQCString opt = _opt;
1186 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
1190 fprintf(stderr,
"\n\nFAILURE (KCmdLineArgs):\n");
1191 fprintf(stderr,
"Application requests for isSet(\"%s\") but the \"%s\" option\n",
1193 fprintf(stderr,
"has never been specified via addCmdLineOptions( ... )\n\n");
1199 TQCString *value = 0;
1200 if (parsedOptionList)
1202 value = parsedOptionList->find(opt);
1210 return ((*value)[0] ==
't');
1218 return (result == 2);
1226 return parsedArgList->count();
1232 if (!parsedArgList || (n >= (
int) parsedArgList->count()))
1234 fprintf(stderr,
"\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n");
1235 fprintf(stderr,
"Application requests for arg(%d) without checking count() first.\n",
1242 return parsedArgList->at(n);
1253 const TQString urlArg = TQFile::decodeName(_urlArg);
1254 TQFileInfo fileInfo(urlArg);
1255 if (!fileInfo.isRelative()) {
1268 return KURL(urlArg);
1272 KCmdLineArgs::addArgument(
const char *argument)
1275 parsedArgList =
new KCmdLineParsedArgs;
1277 parsedArgList->append(argument);
1282 {
"tempfile",
I18N_NOOP(
"The files/URLs opened by the application will be deleted after use"), 0},
1296 return args->
isSet(
"tempfile" );