• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.9.5 API Reference
  • KDE Home
  • Contact Us
 

KDECore

kcmdlineargs.cpp
Go to the documentation of this file.
00001 /*
00002    Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include "kcmdlineargs.h"
00020 #include <kdebug.h>
00021 
00022 #include <config.h>
00023 
00024 #include <sys/param.h>
00025 
00026 #include <assert.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031 #include <locale.h>
00032 
00033 #ifdef HAVE_LIMITS_H
00034 #include <limits.h>
00035 #endif
00036 
00037 #include <QtCore/QDir>
00038 #include <QtCore/QFile>
00039 #include <QtCore/QHash>
00040 #include <QtCore/QTextCodec>
00041 
00042 #include "kaboutdata.h"
00043 #include "klocale.h"
00044 #include "kdeversion.h"
00045 #include "kcomponentdata.h"
00046 #include "kglobal.h"
00047 #include "kurl.h"
00048 
00049 #include "kuitsemantics_p.h" // for escaping arguments in i18n
00050 
00051 // -----------------------------------------------------------------------------
00052 // Design notes:
00053 //
00054 // These classes deal with a lot of text, some of which needs to be
00055 // marked for translation. Since at the time when these object and calls are
00056 // made the translation catalogs are usually still not initialized, the
00057 // translation has to be delayed. This is achieved by using KLocalizedString
00058 // for translatable strings. KLocalizedStrings are produced by ki18n* calls,
00059 // instead of the more usuall i18n* calls which produce QString by trying to
00060 // translate immediately.
00061 //
00062 // All the non-translatable string arguments to methods are taken QByteArray,
00063 // all the translatable are KLocalizedString. The getter methods always return
00064 // proper QString: the non-translatable strings supplied by the code are
00065 // treated with QString::fromUtf8(), those coming from the outside with
00066 // QTextCodec::toUnicode(), and translatable strings are finalized to QStrings
00067 // at the point of getter calls (i.e. delayed translation).
00068 //
00069 // The code below uses locally defined s->decodeInput(QByteArray) and
00070 // s->encodeOutput(QString) calls to centralize the conversion of raw external
00071 // bytes (instead of QString::to/fromLocal8Bit(), QFile::decodeName, etc.)
00072 // -----------------------------------------------------------------------------
00073 
00074 #ifdef Q_WS_X11
00075 #define DISPLAY "DISPLAY"
00076 #elif defined(Q_WS_QWS)
00077 #define DISPLAY "QWS_DISPLAY"
00078 #else
00079 #define DISPLAY "NODISPLAY"
00080 #endif
00081 
00082 //
00083 // Helper classes
00084 //
00085 
00086 class KCmdLineParsedOptions : public QHash<QByteArray,QByteArray>
00087 {
00088 public:
00089    KCmdLineParsedOptions() { }
00090 };
00091 
00092 class KCmdLineParsedArgs : public QList<QByteArray>
00093 {
00094 public:
00095    KCmdLineParsedArgs() { }
00096 };
00097 
00098 
00099 class KCmdLineArgsList: public QList<KCmdLineArgs*>
00100 {
00101 public:
00102    KCmdLineArgsList() { }
00103    ~KCmdLineArgsList() {
00104        while (count())
00105         delete takeFirst();
00106    }
00107 };
00108 
00109 //
00110 // KCmdLineOptions
00111 //
00112 
00113 class KCmdLineOptionsPrivate {
00114     public:
00115     QList<QByteArray> names;
00116     QList<KLocalizedString> descriptions;
00117     QStringList defaults;
00118 };
00119 
00120 KCmdLineOptions::KCmdLineOptions ()
00121 : d(new KCmdLineOptionsPrivate)
00122 {}
00123 
00124 KCmdLineOptions::~KCmdLineOptions ()
00125 {
00126     delete d;
00127 }
00128 
00129 KCmdLineOptions::KCmdLineOptions (const KCmdLineOptions &options)
00130 : d(new KCmdLineOptionsPrivate(*(options.d)))
00131 {
00132 }
00133 
00134 KCmdLineOptions& KCmdLineOptions::operator= (const KCmdLineOptions &options)
00135 {
00136     if (this != &options) {
00137         *d = *(options.d);
00138     }
00139     return *this;
00140 }
00141 
00142 KCmdLineOptions &KCmdLineOptions::add (const QByteArray &name,
00143                                        const KLocalizedString &description,
00144                                        const QByteArray &defaultValue)
00145 {
00146     d->names.append(name);
00147     d->descriptions.append(description);
00148     d->defaults.append(QString::fromUtf8(defaultValue));
00149     return *this;
00150 }
00151 
00152 KCmdLineOptions &KCmdLineOptions::add (const KCmdLineOptions &other)
00153 {
00154     d->names += other.d->names;
00155     d->descriptions += other.d->descriptions;
00156     d->defaults += other.d->defaults;
00157     return *this;
00158 }
00159 
00160 //
00161 // KCmdLineArgs static data and methods
00162 //
00163 
00164 class KCmdLineArgsStatic {
00165     public:
00166 
00167     KCmdLineArgsList *argsList; // All options.
00168     const KAboutData *about;
00169 
00170     int all_argc; // The original argc
00171     char **all_argv; // The original argv
00172     char *appName;
00173     bool parsed : 1; // Whether we have parsed the arguments since calling init
00174     bool ignoreUnknown : 1; // Ignore unknown options and arguments
00175     QByteArray mCwd; // Current working directory. Important for KUnqiueApp!
00176     KCmdLineArgs::StdCmdLineArgs mStdargs;
00177 
00178     KCmdLineOptions qt_options;
00179     KCmdLineOptions kde_options;
00180 
00181     KCmdLineArgsStatic ();
00182 
00183     ~KCmdLineArgsStatic ();
00184 
00185     QTextCodec *codec; // codec for converting raw input to QString
00186 
00194     static QString decodeInput(const QByteArray &rawstr);
00195 
00203     static QByteArray encodeOutput(const QString &str);
00204 
00209     void printQ(const QString &msg);
00210 
00224     static int findOption(const KCmdLineOptions &options, QByteArray &opt,
00225                           QByteArray &opt_name, QString &def, bool &enabled);
00226 
00232     static void findOption(const QByteArray &optv, const QByteArray &_opt,
00233                            int &i, bool _enabled, bool &moreOptions);
00234 
00241     static void parseAllArgs();
00242 
00250     static void removeArgs(const QByteArray &id);
00251 };
00252 
00253 K_GLOBAL_STATIC(KCmdLineArgsStatic, s)
00254 
00255 KCmdLineArgsStatic::KCmdLineArgsStatic () {
00256     // Global data
00257     argsList = 0;
00258     all_argc = 0;
00259     all_argv = 0;
00260     appName = 0;
00261     mCwd.clear();
00262     about = 0;
00263     parsed = false;
00264     ignoreUnknown = false;
00265     mStdargs = 0;
00266 
00267     // Text codec.
00268     codec = QTextCodec::codecForLocale();
00269 
00270     // Qt options
00271     //FIXME: Check if other options are specific to Qt/X11
00272 #ifdef Q_WS_X11
00273     qt_options.add("display <displayname>", ki18n("Use the X-server display 'displayname'"));
00274 #elif defined(Q_WS_QWS)
00275     qt_options.add("display <displayname>", ki18n("Use the QWS display 'displayname'"));
00276 #else
00277 #endif
00278     qt_options.add("session <sessionId>", ki18n("Restore the application for the given 'sessionId'"));
00279     qt_options.add("cmap", ki18n("Causes the application to install a private color\nmap on an 8-bit display"));
00280     qt_options.add("ncols <count>", ki18n("Limits the number of colors allocated in the color\ncube on an 8-bit display, if the application is\nusing the QApplication::ManyColor color\nspecification"));
00281     qt_options.add("nograb", ki18n("tells Qt to never grab the mouse or the keyboard"));
00282     qt_options.add("dograb", ki18n("running under a debugger can cause an implicit\n-nograb, use -dograb to override"));
00283     qt_options.add("sync", ki18n("switches to synchronous mode for debugging"));
00284     qt_options.add("fn");
00285     qt_options.add("font <fontname>", ki18n("defines the application font"));
00286     qt_options.add("bg");
00287     qt_options.add("background <color>", ki18n("sets the default background color and an\napplication palette (light and dark shades are\ncalculated)"));
00288     qt_options.add("fg");
00289     qt_options.add("foreground <color>", ki18n("sets the default foreground color"));
00290     qt_options.add("btn");
00291     qt_options.add("button <color>", ki18n("sets the default button color"));
00292     qt_options.add("name <name>", ki18n("sets the application name"));
00293     qt_options.add("title <title>", ki18n("sets the application title (caption)"));
00294     qt_options.add("testability", ki18n("load the testability framework"));
00295 #ifdef Q_WS_X11
00296     qt_options.add("visual TrueColor", ki18n("forces the application to use a TrueColor visual on\nan 8-bit display"));
00297     qt_options.add("inputstyle <inputstyle>", ki18n("sets XIM (X Input Method) input style. Possible\nvalues are onthespot, overthespot, offthespot and\nroot"));
00298     qt_options.add("im <XIM server>", ki18n("set XIM server"));
00299     qt_options.add("noxim", ki18n("disable XIM"));
00300 #endif
00301 #ifdef Q_WS_QWS
00302     qt_options.add("qws", ki18n("forces the application to run as QWS Server"));
00303 #endif
00304     qt_options.add("reverse", ki18n("mirrors the whole layout of widgets"));
00305     qt_options.add("stylesheet <file.qss>", ki18n("applies the Qt stylesheet to the application widgets"));
00306     qt_options.add("graphicssystem <system>", ki18n("use a different graphics system instead of the default one, options are raster and opengl (experimental)"));
00307     qt_options.add("qmljsdebugger <port>", ki18n("QML JS debugger information. Application must be\nbuilt with -DQT_DECLARATIVE_DEBUG for the debugger to be\nenabled"));
00308     // KDE options
00309     kde_options.add("caption <caption>",   ki18n("Use 'caption' as name in the titlebar"));
00310     kde_options.add("icon <icon>",         ki18n("Use 'icon' as the application icon"));
00311     kde_options.add("config <filename>",   ki18n("Use alternative configuration file"));
00312     kde_options.add("nocrashhandler",      ki18n("Disable crash handler, to get core dumps"));
00313 #ifdef Q_WS_X11
00314     kde_options.add("waitforwm",           ki18n("Waits for a WM_NET compatible windowmanager"));
00315 #endif
00316     kde_options.add("style <style>",       ki18n("sets the application GUI style"));
00317     kde_options.add("geometry <geometry>", ki18n("sets the client geometry of the main widget - see man X for the argument format (usually WidthxHeight+XPos+YPos)"));
00318 #ifndef Q_WS_WIN
00319     kde_options.add("smkey <sessionKey>"); // this option is obsolete and exists only to allow smooth upgrades from sessions
00320 #endif
00321 }
00322 
00323 KCmdLineArgsStatic::~KCmdLineArgsStatic ()
00324 {
00325     delete argsList;
00326     // KAboutData object is deleted by ~KCleanUpGlobalStatic.
00327     //delete about;
00328 }
00329 
00330 //
00331 // KCmdLineArgs private data and methods
00332 //
00333 
00334 class KCmdLineArgsPrivate
00335 {
00336     friend class KCmdLineArgsStatic;
00337 public:
00338     KCmdLineArgsPrivate(const KCmdLineOptions &_options, const KLocalizedString &_name, const QByteArray &_id)
00339         : options(_options)
00340         , name(_name)
00341         , id(_id)
00342         , parsedOptionList(0)
00343         , parsedArgList(0)
00344         , isQt(id == "qt")
00345     {
00346     }
00347     ~KCmdLineArgsPrivate()
00348     {
00349         delete parsedOptionList;
00350         delete parsedArgList;
00351     }
00352     const KCmdLineOptions options;
00353     const KLocalizedString name;
00354     const QByteArray id;
00355     KCmdLineParsedOptions *parsedOptionList;
00356     KCmdLineParsedArgs *parsedArgList;
00357     bool isQt;
00358 
00364     void setOption(const QByteArray &option, bool enabled);
00365 
00371     void setOption(const QByteArray &option, const QByteArray &value);
00372 
00378     void addArgument(const QByteArray &argument);
00379 
00385     void save( QDataStream &) const;
00386 
00392     void load( QDataStream &);
00393 };
00394 
00395 //
00396 // Static functions
00397 //
00398 
00399 QString
00400 KCmdLineArgsStatic::decodeInput(const QByteArray &rawstr)
00401 {
00402     return s->codec->toUnicode(rawstr);
00403 }
00404 
00405 QByteArray
00406 KCmdLineArgsStatic::encodeOutput(const QString &str)
00407 {
00408     return s->codec->fromUnicode(str);
00409 }
00410 
00411 void
00412 KCmdLineArgsStatic::printQ(const QString &msg)
00413 {
00414    fprintf(stdout, "%s", encodeOutput(msg).data());
00415 }
00416 
00417 void
00418 KCmdLineArgs::init(int _argc, char **_argv,
00419                    const QByteArray &_appname,
00420                    const QByteArray &_catalog,
00421                    const KLocalizedString &_programName,
00422                    const QByteArray &_version,
00423                    const KLocalizedString &_description,
00424                    StdCmdLineArgs stdargs)
00425 {
00426    init(_argc, _argv,
00427         new KAboutData(_appname, _catalog, _programName, _version, _description),
00428         stdargs);
00429 }
00430 
00431 void
00432 KCmdLineArgs::initIgnore(int _argc, char **_argv, const QByteArray &_appname )
00433 {
00434    init(_argc, _argv,
00435         new KAboutData(_appname, 0, ki18n(_appname), "unknown", ki18n("KDE Application")));
00436    s->ignoreUnknown = true;
00437 }
00438 
00439 void
00440 KCmdLineArgs::init(const KAboutData* ab)
00441 {
00442    char **_argv = (char **) malloc(sizeof(char *));
00443    _argv[0] = (char *) s->encodeOutput(ab->appName()).data();
00444    init(1,_argv,ab, CmdLineArgNone);
00445 }
00446 
00447 
00448 void
00449 KCmdLineArgs::init(int _argc, char **_argv, const KAboutData *_about, StdCmdLineArgs stdargs)
00450 {
00451    s->all_argc = _argc;
00452    s->all_argv = _argv;
00453 
00454    if (!s->all_argv)
00455    {
00456       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00457       fprintf(stderr, "Passing null-pointer to 'argv' is not allowed.\n\n");
00458 
00459       assert( 0 );
00460       exit(255);
00461    }
00462 
00463    // Strip path from argv[0]
00464    if (s->all_argc) {
00465      char *p = strrchr(s->all_argv[0], QDir::separator().toAscii());
00466      if (p)
00467        s->appName = p+1;
00468      else
00469        s->appName = s->all_argv[0];
00470    }
00471 
00472    s->about = _about;
00473    s->parsed = false;
00474    s->mCwd = QDir::currentPath().toLocal8Bit(); //currentPath() uses fromLocal8Bit internally apparently
00475    addStdCmdLineOptions(stdargs);
00476 }
00477 
00478 QString KCmdLineArgs::cwd()
00479 {
00480    return QString::fromLocal8Bit(s->mCwd);
00481 }
00482 
00483 QString KCmdLineArgs::appName()
00484 {
00485    if (!s->appName) return QString();
00486    return s->decodeInput(s->appName);
00487 }
00488 
00492 void KCmdLineArgs::addStdCmdLineOptions(StdCmdLineArgs stdargs) {
00493    if (stdargs & KCmdLineArgs::CmdLineArgQt) {
00494        KCmdLineArgs::addCmdLineOptions(s->qt_options, ki18n("Qt"), "qt");
00495    }
00496    if (stdargs & KCmdLineArgs::CmdLineArgKDE) {
00497        KCmdLineArgs::addCmdLineOptions(s->kde_options, ki18n("KDE"), "kde");
00498    }
00499    s->mStdargs = stdargs;
00500 }
00501 
00502 void
00503 KCmdLineArgs::addCmdLineOptions( const KCmdLineOptions &options, const KLocalizedString &name,
00504          const QByteArray &id, const QByteArray &afterId)
00505 {
00506    if (!s->argsList)
00507       s->argsList = new KCmdLineArgsList;
00508 
00509    int pos = s->argsList->count();
00510    // To make sure that the named options come before unnamed.
00511    if (pos > 0 && !id.isEmpty() && s->argsList->last()->d->name.isEmpty())
00512       pos--;
00513 
00514    KCmdLineArgsList::Iterator args;
00515    int i = 0;
00516    for(args = s->argsList->begin(); args != s->argsList->end(); ++args, i++)
00517    {
00518        if (id == (*args)->d->id) {
00519          return; // Options already present.
00520       }
00521 
00522       // Only check for afterId if it has been given non-empty, as the
00523       // unnamed option group should come after all named groups.
00524       if (!afterId.isEmpty() && afterId == (*args)->d->id)
00525          pos = i+1;
00526    }
00527 
00528    Q_ASSERT( s->parsed == false ); // You must add _ALL_ cmd line options
00529                                    // before accessing the arguments!
00530    s->argsList->insert(pos, new KCmdLineArgs(options, name, id));
00531 }
00532 
00533 void
00534 KCmdLineArgs::saveAppArgs( QDataStream &ds)
00535 {
00536    if (!s->parsed)
00537       s->parseAllArgs();
00538 
00539    // Remove Qt and KDE options.
00540    s->removeArgs("qt");
00541    s->removeArgs("kde");
00542    s->removeArgs("kuniqueapp");
00543 
00544    ds << s->mCwd;
00545 
00546    uint count = s->argsList ? s->argsList->count() : 0;
00547    ds << count;
00548 
00549    if (!count) return;
00550 
00551    KCmdLineArgsList::Iterator args;
00552    for(args = s->argsList->begin(); args != s->argsList->end(); ++args)
00553    {
00554       ds << (*args)->d->id;
00555       (*args)->d->save(ds);
00556    }
00557 }
00558 
00559 void
00560 KCmdLineArgs::loadAppArgs( QDataStream &ds)
00561 {
00562    s->parsed = true; // don't reparse argc/argv!
00563 
00564    // Remove Qt and KDE options.
00565    s->removeArgs("qt");
00566    s->removeArgs("kde");
00567    s->removeArgs("kuniqueapp");
00568 
00569    KCmdLineArgsList::Iterator args;
00570    if ( s->argsList ) {
00571       for(args = s->argsList->begin(); args != s->argsList->end(); ++args)
00572       {
00573          (*args)->clear();
00574       }
00575    }
00576 
00577    if (ds.atEnd())
00578       return;
00579 
00580    QByteArray qCwd;
00581    ds >> qCwd;
00582 
00583    s->mCwd = qCwd;
00584 
00585    uint count;
00586    ds >> count;
00587 
00588    while(count--)
00589    {
00590      QByteArray id;
00591      ds >> id;
00592      Q_ASSERT( s->argsList );
00593      bool found = false;
00594      for(args = s->argsList->begin(); args != s->argsList->end(); ++args)
00595      {
00596        if ((*args)->d->id  == id)
00597        {
00598           (*args)->d->load(ds);
00599           found = true;
00600           break;
00601        }
00602      }
00603      if (!found) {
00604          kWarning() << "Argument definitions for" << id << "not found!";
00605          // The next ds >> id will do nonsensical things...
00606      }
00607    }
00608    s->parsed = true;
00609 }
00610 
00611 KCmdLineArgs *KCmdLineArgs::parsedArgs(const QByteArray &id)
00612 {
00613    if (!s->argsList)
00614       return 0;
00615    KCmdLineArgsList::Iterator args = s->argsList->begin();
00616    while(args != s->argsList->end())
00617    {
00618       if ((*args)->d->id == id)
00619       {
00620           if (!s->parsed)
00621              s->parseAllArgs();
00622           return *args;
00623       }
00624       ++args;
00625    }
00626 
00627    return 0;
00628 }
00629 
00630 void KCmdLineArgsStatic::removeArgs(const QByteArray &id)
00631 {
00632    if (!s->argsList)
00633       return;
00634    KCmdLineArgsList::Iterator args = s->argsList->begin();
00635    while(args != s->argsList->end())
00636    {
00637       if ((*args)->d->id == id)
00638       {
00639           if (!s->parsed)
00640              s->parseAllArgs();
00641           break;
00642       }
00643       ++args;
00644    }
00645 
00646    if (args != s->argsList->end()) {
00647       KCmdLineArgs *a = *args;
00648       s->argsList->erase(args);
00649       delete a;
00650    }
00651 }
00652 
00653 int
00654 KCmdLineArgsStatic::findOption(const KCmdLineOptions &options, QByteArray &opt,
00655                                QByteArray &opt_name, QString &def, bool &enabled)
00656 {
00657    int result;
00658    bool inverse;
00659 
00660    for (int i = 0; i < options.d->names.size(); i++)
00661    {
00662       result = 0;
00663       inverse = false;
00664       opt_name = options.d->names[i];
00665       if (opt_name.startsWith(':') || opt_name.isEmpty())
00666       {
00667          continue;
00668       }
00669       if (opt_name.startsWith('!'))
00670       {
00671          opt_name = opt_name.mid(1);
00672          result = 4;
00673       }
00674       if (opt_name.startsWith("no") && !opt_name.contains('<')) // krazy:exclude=strings
00675       {
00676          opt_name = opt_name.mid(2);
00677          inverse = true;
00678       }
00679 
00680       int len = opt.length();
00681       if (opt == opt_name.left(len))
00682       {
00683          opt_name = opt_name.mid(len);
00684          if (opt_name.isEmpty())
00685          {
00686             if (inverse)
00687                return result+2;
00688 
00689             if (options.d->descriptions[i].isEmpty())
00690             {
00691                i++;
00692                if (i >= options.d->names.size())
00693                   return result+0;
00694                QByteArray nextOption = options.d->names[i];
00695                int p = nextOption.indexOf(' ');
00696                if (p > 0)
00697                   nextOption = nextOption.left(p);
00698                if (nextOption.startsWith('!'))
00699                   nextOption = nextOption.mid(1);
00700                if (nextOption.startsWith("no") && !nextOption.contains('<')) // krazy:exclude=strings
00701                {
00702                   nextOption = nextOption.mid(2);
00703                   enabled = !enabled;
00704                }
00705                result = findOption(options, nextOption, opt_name, def, enabled);
00706                Q_ASSERT(result);
00707                opt = nextOption;
00708                return result;
00709             }
00710 
00711             return 1;
00712          }
00713          if (opt_name.startsWith(' '))
00714          {
00715             opt_name = opt_name.mid(1);
00716             def = options.d->defaults[i];
00717             return result+3;
00718          }
00719       }
00720    }
00721    return 0;
00722 }
00723 
00724 void
00725 KCmdLineArgsStatic::findOption(const QByteArray &optv, const QByteArray &_opt,
00726                                int &i, bool _enabled, bool &moreOptions)
00727 {
00728    KCmdLineArgsList::Iterator args = s->argsList->begin();
00729    QByteArray opt = _opt;
00730    QByteArray opt_name;
00731    QString def;
00732    QByteArray argument;
00733    int j = opt.indexOf('=');
00734    if (j != -1)
00735    {
00736       argument = opt.mid(j+1);
00737       opt = opt.left(j);
00738    }
00739 
00740    bool enabled = true;
00741    int result = 0;
00742    while (args != s->argsList->end())
00743    {
00744       enabled = _enabled;
00745       result = findOption((*args)->d->options, opt, opt_name, def, enabled);
00746       if (result) break;
00747       ++args;
00748    }
00749    if ((args == s->argsList->end()) &&
00750        (optv.startsWith('-') && !optv.startsWith("--"))) // krazy:exclude=strings
00751    {
00752       // Option not found check if it is a valid option
00753       // in the style of -Pprinter1 or ps -aux
00754       int p = 1;
00755       while (true)
00756       {
00757          QByteArray singleCharOption = " "; // krazy:exclude=doublequote_chars
00758          singleCharOption[0] = optv[p];
00759          args = s->argsList->begin();
00760          while (args != s->argsList->end())
00761          {
00762             enabled = _enabled;
00763             result = findOption((*args)->d->options, singleCharOption,
00764                       opt_name, def, enabled);
00765             if (result) break;
00766             ++args;
00767          }
00768          if (args == s->argsList->end())
00769             break; // Unknown argument
00770 
00771          p++;
00772          if (result == 1) // Single option
00773          {
00774             (*args)->d->setOption(singleCharOption, enabled);
00775             if (p < optv.length())
00776                continue; // Next option
00777             else
00778                return; // Finished
00779          }
00780          else if (result == 3) // This option takes an argument
00781          {
00782             if (argument.isEmpty())
00783             {
00784                argument = optv.mid(p);
00785             }
00786             (*args)->d->setOption(singleCharOption, argument);
00787             return;
00788          }
00789          break; // Unknown argument
00790       }
00791       args = s->argsList->end();
00792       result = 0;
00793    }
00794 
00795    if (args == s->argsList->end() || !result)
00796    {
00797       if (s->ignoreUnknown)
00798          return;
00799       KCmdLineArgs::enable_i18n();
00800       KCmdLineArgs::usageError( i18n("Unknown option '%1'.", QString::fromLocal8Bit(_opt)));
00801    }
00802 
00803    if ((result & 4) != 0)
00804    {
00805       result &= ~4;
00806       moreOptions = false;
00807    }
00808 
00809    if (result == 3) // This option takes an argument
00810    {
00811       if (!enabled)
00812       {
00813          if (s->ignoreUnknown)
00814             return;
00815          KCmdLineArgs::enable_i18n();
00816          KCmdLineArgs::usageError( i18n("Unknown option '%1'.", QString::fromLocal8Bit(_opt)));
00817       }
00818       if (argument.isEmpty())
00819       {
00820          i++;
00821          if (i >= s->all_argc)
00822          {
00823             KCmdLineArgs::enable_i18n();
00824             KCmdLineArgs::usageError( i18nc("@info:shell %1 is cmdoption name","'%1' missing.",  QString::fromLocal8Bit(opt_name)));
00825          }
00826          argument = s->all_argv[i];
00827       }
00828       (*args)->d->setOption(opt, argument);
00829    }
00830    else
00831    {
00832       (*args)->d->setOption(opt, enabled);
00833    }
00834 }
00835 
00836 void
00837 KCmdLineArgsStatic::parseAllArgs()
00838 {
00839    bool allowArgs = false;
00840    bool inOptions = true;
00841    bool everythingAfterArgIsArgs = false;
00842    KCmdLineArgs *appOptions = s->argsList->last();
00843    if (appOptions->d->id.isEmpty())
00844    {
00845      foreach(const QByteArray& name, appOptions->d->options.d->names)
00846      {
00847        everythingAfterArgIsArgs = everythingAfterArgIsArgs || name.startsWith("!+");
00848        allowArgs = allowArgs || name.startsWith('+') || everythingAfterArgIsArgs;
00849      }
00850    }
00851    for(int i = 1; i < s->all_argc; i++)
00852    {
00853       if (!s->all_argv[i])
00854          continue;
00855 
00856       if ((s->all_argv[i][0] == '-') && s->all_argv[i][1] && inOptions)
00857       {
00858          bool enabled = true;
00859          QByteArray orig = s->all_argv[i];
00860          QByteArray option = orig.mid(1);
00861          if (option.startsWith('-'))
00862          {
00863             option = option.mid(1);
00864             if (option.isEmpty())
00865             {
00866                inOptions = false;
00867                continue;
00868             }
00869          }
00870          if (option == "help")
00871          {
00872             KCmdLineArgs::usage();
00873          }
00874          else if (option.startsWith("help-")) // krazy:exclude=strings
00875          {
00876             KCmdLineArgs::usage(option.mid(5));
00877          }
00878 #ifdef Q_WS_MAC
00879          // skip the finder -psn_* hint
00880          else if (option.startsWith("psn_")) // krazy:exclude=strings
00881          {
00882             continue;
00883          }
00884 #endif
00885          else if ((option == "version") || (option == "v"))
00886          {
00887             KCmdLineArgs::enable_i18n();
00888             s->printQ(i18nc("@info:shell message on appcmd --version; do not translate 'Development Platform'"
00889                             "%3 application name, other %n version strings",
00890                             "Qt: %1\n"
00891                             "KDE Development Platform: %2\n"
00892                             "%3: %4\n",
00893                             QString::fromLatin1(qVersion()),
00894                             QString::fromLatin1(KDE_VERSION_STRING),
00895                             s->about->programName(), s->about->version()));
00896             exit(0);
00897          } else if (option == "license")
00898          {
00899             KCmdLineArgs::enable_i18n();
00900             s->printQ(s->about->license());
00901             s->printQ(QString::fromLatin1("\n"));
00902             exit(0);
00903          } else if (option == "author") {
00904              KCmdLineArgs::enable_i18n();
00905        if ( s->about ) {
00906          const QList<KAboutPerson> authors = s->about->authors();
00907          if ( !authors.isEmpty() ) {
00908            QString authorlist;
00909            for (QList<KAboutPerson>::ConstIterator it = authors.begin(); it != authors.end(); ++it ) {
00910              QString email;
00911              if ( !(*it).emailAddress().isEmpty() )
00912                email = QString::fromLatin1(" &lt;") + (*it).emailAddress() + QLatin1String("&gt;");
00913              authorlist += QString::fromLatin1("    ") + (*it).name() + email + QLatin1Char('\n');
00914            }
00915            s->printQ( i18nc("the 2nd argument is a list of name+address, one on each line","%1 was written by\n%2",   QString(s->about->programName()) ,  authorlist ) );
00916          }
00917        } else {
00918          s->printQ( i18n("This application was written by somebody who wants to remain anonymous.") );
00919        }
00920        if (s->about)
00921        {
00922          if (!s->about->customAuthorTextEnabled ())
00923          {
00924            if (s->about->bugAddress().isEmpty() || s->about->bugAddress() == QLatin1String("submit@bugs.kde.org") )
00925              s->printQ( i18n( "Please use http://bugs.kde.org to report bugs.\n" ) );
00926            else
00927              s->printQ( i18n( "Please report bugs to %1.\n" , s->about->bugAddress()) );
00928          }
00929          else
00930          {
00931            s->printQ(s->about->customAuthorPlainText()+QLatin1Char('\n'));
00932          }
00933        }
00934        exit(0);
00935          } else {
00936            if (option.startsWith("no")) // krazy:exclude=strings
00937            {
00938               bool noHasParameter=false;
00939               foreach(const QByteArray& name, appOptions->d->options.d->names)
00940               {
00941                  if (name.contains(option + QByteArray(" ")) && name.contains('<'))
00942                  {
00943                     noHasParameter=true;
00944                     break;
00945                   }
00946               }
00947               if (!noHasParameter)
00948               {
00949                  option = option.mid(2);
00950                  enabled = false;
00951               }
00952            }
00953            s->findOption(orig, option, i, enabled, inOptions);
00954          }
00955       }
00956       else
00957       {
00958          // Check whether appOptions allows these arguments
00959          if (!allowArgs)
00960          {
00961             if (s->ignoreUnknown)
00962                continue;
00963             KCmdLineArgs::enable_i18n();
00964             KCmdLineArgs::usageError(i18n("Unexpected argument '%1'.", KuitSemantics::escape(s->decodeInput(s->all_argv[i]))));
00965          }
00966          else
00967          {
00968             appOptions->d->addArgument(s->all_argv[i]);
00969             if (everythingAfterArgIsArgs)
00970                 inOptions = false;
00971          }
00972       }
00973    }
00974    s->parsed = true;
00975 }
00976 
00977 int & KCmdLineArgs::qtArgc()
00978 {
00979    if (!s->argsList)
00980       addStdCmdLineOptions(CmdLineArgKDE|CmdLineArgQt); // Lazy bastards!
00981 
00982    static int qt_argc = -1;
00983    if( qt_argc != -1 )
00984       return qt_argc;
00985 
00986    if (!(s->mStdargs & KCmdLineArgs::CmdLineArgQt))
00987    {
00988      qt_argc = 2;
00989      return qt_argc;
00990    }
00991 
00992    KCmdLineArgs *args = parsedArgs("qt");
00993    Q_ASSERT(args); // No qt options have been added!
00994    if (!s->all_argv)
00995    {
00996       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00997       fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
00998 
00999       assert( 0 );
01000       exit(255);
01001    }
01002 
01003    Q_ASSERT(s->all_argc >= (args->count()+1));
01004    qt_argc = args->count() +1;
01005    return qt_argc;
01006 }
01007 
01008 static char** s_qt_argv;
01009 
01010 char **
01011 KCmdLineArgs::qtArgv()
01012 {
01013    if (!s->argsList)
01014       addStdCmdLineOptions(CmdLineArgKDE|CmdLineArgQt); // Lazy bastards!
01015 
01016    if( s_qt_argv != NULL )
01017       return s_qt_argv;
01018 
01019    if (!(s->mStdargs & KCmdLineArgs::CmdLineArgQt))
01020    {
01021      s_qt_argv = new char*[2];
01022      s_qt_argv[0] = qstrdup(s->all_argc?s->all_argv[0]:"");
01023      s_qt_argv[1] = 0;
01024 
01025      return s_qt_argv;
01026    }
01027 
01028    KCmdLineArgs *args = parsedArgs("qt");
01029    if (!args)
01030    {
01031       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01032       fprintf(stderr, "The \"qt\" options have not be added to KCmdLineArgs!\n\n");
01033 
01034       assert( 0 );
01035       exit(255);
01036    }
01037    if (!s->all_argv)
01038    {
01039       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01040       fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
01041 
01042       assert( 0 );
01043       exit(255);
01044    }
01045 
01046    int count=args->count();
01047    s_qt_argv = new char*[ count + 2 ];
01048    s_qt_argv[0] = qstrdup(s->all_argc?s->all_argv[0]:"");
01049    int i = 0;
01050    for(; i < count; i++)
01051    {
01052       s_qt_argv[i+1] = qstrdup(args->d->parsedArgList->at(i));
01053    }
01054    s_qt_argv[i+1] = 0;
01055 
01056    return s_qt_argv;
01057 }
01058 
01059 const KAboutData *
01060 KCmdLineArgs::aboutData()
01061 {
01062     return s->about;
01063 }
01064 
01065 void
01066 KCmdLineArgs::enable_i18n()
01067 {
01068     // called twice or too late
01069     if (KGlobal::hasLocale())
01070       return;
01071 
01072     if (!KGlobal::hasMainComponent()) {
01073         KComponentData mainComponentData(s->about);
01074         mainComponentData.config();
01075         // mainComponentData is now the main component and won't disappear until KGlobal deletes it
01076     }
01077 }
01078 
01079 void
01080 KCmdLineArgs::usageError(const QString &error)
01081 {
01082     Q_ASSERT(KGlobal::hasLocale());
01083     QByteArray localError = s->encodeOutput(error);
01084     if (localError.endsWith('\n'))
01085         localError.chop(1);
01086     fprintf(stderr, "%s: %s\n", s->appName, localError.data());
01087 
01088     QString tmp = i18n("Use --help to get a list of available command line options.");
01089     localError = s->encodeOutput(tmp);
01090     fprintf(stderr, "%s: %s\n", s->appName, localError.data());
01091     exit(254);
01092 }
01093 
01094 void
01095 KCmdLineArgs::usage(const QByteArray &id)
01096 {
01097    enable_i18n();
01098    Q_ASSERT(s->argsList != 0); // It's an error to call usage(...) without
01099                                // having done addCmdLineOptions first!
01100 
01101    QString optionFormatString = QString::fromLatin1("  %1 %2\n");
01102    QString optionFormatStringDef = QString::fromLatin1("  %1 %2 [%3]\n");
01103    QString tmp;
01104    QString usage;
01105 
01106    KCmdLineArgsList::Iterator args = --(s->argsList->end());
01107 
01108    if ((*args)->d->id.isEmpty() && ((*args)->d->options.d->names.size() > 0) &&
01109        !(*args)->d->options.d->names[0].startsWith('+'))
01110    {
01111       usage = i18n("[options] ")+usage;
01112    }
01113 
01114    while(true)
01115    {
01116       if (!(*args)->d->name.isEmpty())
01117       {
01118          usage = i18n("[%1-options]", (*args)->d->name.toString())+QLatin1Char(' ')+usage;
01119       }
01120       if (args == s->argsList->begin())
01121          break;
01122       --args;
01123    }
01124 
01125    KCmdLineArgs *appOptions = s->argsList->last();
01126    if (appOptions->d->id.isEmpty())
01127    {
01128      const KCmdLineOptions &option = appOptions->d->options;
01129      for (int i = 0; i < option.d->names.size(); i++)
01130      {
01131        QByteArray opt_name = option.d->names[i];
01132        if (opt_name.startsWith('+'))
01133            usage += QString::fromLatin1(opt_name.mid(1)) + QLatin1Char(' ');
01134        else if ( opt_name.startsWith("!+") )
01135           usage += QString::fromLatin1(opt_name.mid(2)) + QLatin1Char(' ');
01136      }
01137    }
01138 
01139    s->printQ(i18n("Usage: %1 %2\n", QString::fromLocal8Bit(s->appName), KuitSemantics::escape(usage)));
01140    s->printQ(QLatin1Char('\n')+s->about->shortDescription()+QLatin1Char('\n'));
01141 
01142    s->printQ(i18n("\nGeneric options:\n"));
01143    s->printQ(optionFormatString.arg(QString::fromLatin1("--help"), -25)
01144              .arg(i18n("Show help about options")));
01145 
01146    args = s->argsList->begin();
01147    while(args != s->argsList->end())
01148    {
01149       if (!(*args)->d->name.isEmpty() && !(*args)->d->id.isEmpty())
01150       {
01151           QString option = QString::fromLatin1("--help-%1").arg(QString::fromLatin1((*args)->d->id));
01152          QString desc = i18n("Show %1 specific options", (*args)->d->name.toString());
01153 
01154          s->printQ(optionFormatString.arg(option, -25).arg(desc));
01155       }
01156       ++args;
01157    }
01158 
01159    s->printQ(optionFormatString.arg(QString::fromLatin1("--help-all"),-25).arg(i18n("Show all options")));
01160    s->printQ(optionFormatString.arg(QString::fromLatin1("--author"),-25).arg(i18n("Show author information")));
01161    s->printQ(optionFormatString.arg(QString::fromLatin1("-v, --version"),-25).arg(i18n("Show version information")));
01162    s->printQ(optionFormatString.arg(QString::fromLatin1("--license"),-25).arg(i18n("Show license information")));
01163    s->printQ(optionFormatString.arg(QString::fromLatin1("--"), -25).arg(i18n("End of options")));
01164 
01165    args = s->argsList->begin(); // Sets current to 1st.
01166 
01167    bool showAll = (id == "all");
01168 
01169    if (!showAll)
01170    {
01171      while(args != s->argsList->end())
01172      {
01173        if (id == (*args)->d->id) break;
01174        ++args;
01175      }
01176    }
01177 
01178    while(args != s->argsList->end())
01179    {
01180      bool hasArgs = false;
01181      bool hasOptions = false;
01182      QString optionsHeader;
01183      if (!(*args)->d->name.isEmpty())
01184         optionsHeader = i18n("\n%1 options:\n", (*args)->d->name.toString());
01185      else
01186         optionsHeader = i18n("\nOptions:\n");
01187 
01188      while (args != s->argsList->end())
01189      {
01190        const KCmdLineOptions &option = (*args)->d->options;
01191        QByteArray opt;
01192 
01193        for (int i = 0; i < option.d->names.size(); i++)
01194        {
01195          QString description;
01196          QStringList dl;
01197 
01198          QString descriptionFull;
01199          if (!option.d->descriptions[i].isEmpty()) {
01200             descriptionFull = option.d->descriptions[i].toString();
01201          }
01202 
01203          // Option header
01204          if (option.d->names[i].startsWith(':'))
01205          {
01206             if (!descriptionFull.isEmpty())
01207             {
01208                optionsHeader = QLatin1Char('\n')+descriptionFull;
01209                if (!optionsHeader.endsWith(QLatin1Char('\n')))
01210                   optionsHeader.append(QLatin1Char('\n'));
01211                hasOptions = false;
01212             }
01213             continue;
01214          }
01215 
01216          // Free-form comment
01217          if (option.d->names[i].isEmpty())
01218          {
01219             if (!descriptionFull.isEmpty())
01220             {
01221                tmp = QLatin1Char('\n')+descriptionFull;
01222                if (!tmp.endsWith(QLatin1Char('\n')))
01223                   tmp.append(QLatin1Char('\n'));
01224                s->printQ(tmp);
01225             }
01226             continue;
01227          }
01228 
01229          // Options
01230          if (!descriptionFull.isEmpty())
01231          {
01232             dl = descriptionFull.split(QLatin1Char('\n'), QString::KeepEmptyParts);
01233             description = dl.first();
01234             dl.erase( dl.begin() );
01235          }
01236          QByteArray name = option.d->names[i];
01237          if (name.startsWith('!'))
01238              name = name.mid(1);
01239 
01240          if (name.startsWith('+'))
01241          {
01242             if (!hasArgs)
01243             {
01244                s->printQ(i18n("\nArguments:\n"));
01245                hasArgs = true;
01246             }
01247 
01248             name = name.mid(1);
01249             if (name.startsWith('[') && name.endsWith(']'))
01250                 name = name.mid(1, name.length()-2);
01251             s->printQ(optionFormatString.arg(QString::fromLocal8Bit(name), -25).arg(description));
01252          }
01253          else
01254          {
01255             if (!hasOptions)
01256             {
01257                s->printQ(optionsHeader);
01258                hasOptions = true;
01259             }
01260 
01261             if ((name.length() == 1) || (name[1] == ' '))
01262                name = '-'+name;
01263             else
01264                name = "--"+name;
01265             if (descriptionFull.isEmpty())
01266             {
01267                opt = name + ", ";
01268             }
01269             else
01270             {
01271                opt = opt + name;
01272                if (option.d->defaults[i].isEmpty())
01273                {
01274                    s->printQ(optionFormatString.arg(QString::fromLatin1(opt), -25).arg(description));
01275                }
01276                else
01277                {
01278                    s->printQ(optionFormatStringDef.arg(QString::fromLatin1(opt), -25)
01279                             .arg(description, option.d->defaults[i]));
01280                }
01281                opt.clear();
01282             }
01283          }
01284          for(QStringList::Iterator it = dl.begin();
01285              it != dl.end();
01286              ++it)
01287          {
01288             s->printQ(optionFormatString.arg(QString(), -25).arg(*it));
01289          }
01290        }
01291 
01292        ++args;
01293        if (args == s->argsList->end() || !(*args)->d->name.isEmpty() || (*args)->d->id.isEmpty())
01294         break;
01295      }
01296      if (!showAll) break;
01297    }
01298 
01299    exit(0);
01300 }
01301 
01302 //
01303 // Member functions
01304 //
01305 
01311 KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions &_options,
01312                             const KLocalizedString &_name,
01313                             const QByteArray &_id)
01314   : d(new KCmdLineArgsPrivate(_options, _name, _id))
01315 {
01316 }
01317 
01321 KCmdLineArgs::~KCmdLineArgs()
01322 {
01323   if (!s.isDestroyed() && s->argsList)
01324      s->argsList->removeAll(this);
01325   delete d;
01326 }
01327 
01328 void
01329 KCmdLineArgs::setCwd( const QByteArray &cwd )
01330 {
01331     s->mCwd = cwd;
01332 }
01333 
01334 void
01335 KCmdLineArgs::clear()
01336 {
01337    delete d->parsedArgList;     d->parsedArgList = 0;
01338    delete d->parsedOptionList;  d->parsedOptionList = 0;
01339 }
01340 
01341 void
01342 KCmdLineArgs::reset()
01343 {
01344    delete s->argsList; s->argsList = 0;
01345    s->parsed = false;
01346 }
01347 
01348 void
01349 KCmdLineArgsPrivate::save( QDataStream &ds) const
01350 {
01351    if (parsedOptionList)
01352       ds << (*(parsedOptionList));
01353    else
01354       ds << quint32(0);
01355 
01356    if (parsedArgList)
01357       ds << (*(parsedArgList));
01358    else
01359       ds << quint32(0);
01360 }
01361 
01362 void
01363 KCmdLineArgsPrivate::load( QDataStream &ds)
01364 {
01365    if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions;
01366    if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs;
01367 
01368    ds >> (*(parsedOptionList));
01369    ds >> (*(parsedArgList));
01370 
01371    if (parsedOptionList->count() == 0)
01372    {
01373       delete parsedOptionList;  parsedOptionList = 0;
01374    }
01375    if (parsedArgList->count() == 0)
01376    {
01377       delete parsedArgList;     parsedArgList = 0;
01378    }
01379 }
01380 
01381 void
01382 KCmdLineArgsPrivate::setOption(const QByteArray &opt, bool enabled)
01383 {
01384    if (isQt)
01385    {
01386       // Qt does it own parsing.
01387       QByteArray argString = "-"; // krazy:exclude=doublequote_chars
01388       if( !enabled )
01389           argString += "no";
01390       argString += opt;
01391       addArgument(argString);
01392    }
01393    if (!parsedOptionList) {
01394       parsedOptionList = new KCmdLineParsedOptions;
01395    }
01396 
01397    if (enabled)
01398       parsedOptionList->insert( opt, "t" ); // krazy:exclude=doublequote_chars
01399    else
01400       parsedOptionList->insert( opt, "f" ); // krazy:exclude=doublequote_chars
01401 }
01402 
01403 void
01404 KCmdLineArgsPrivate::setOption(const QByteArray &opt, const QByteArray &value)
01405 {
01406    if (isQt)
01407    {
01408       // Qt does it's own parsing.
01409       QByteArray argString = "-"; // krazy:exclude=doublequote_chars
01410       argString += opt;
01411       if (opt == "qmljsdebugger") {
01412           // hack: Qt expects the value of the "qmljsdebugger" option to be 
01413           // passed using a '=' separator rather than a space, so we recreate it
01414           // correctly.
01415           // See code of QCoreApplicationPrivate::processCommandLineArguments()
01416           addArgument(argString + "=" + value);
01417       } else {
01418           addArgument(argString);
01419           addArgument(value);
01420       }
01421 
01422 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
01423       // Hack coming up!
01424       if (argString == "-display")
01425       {
01426          setenv(DISPLAY, value.data(), true);
01427       }
01428 #endif
01429    }
01430    if (!parsedOptionList) {
01431       parsedOptionList = new KCmdLineParsedOptions;
01432    }
01433 
01434    parsedOptionList->insertMulti( opt, value );
01435 }
01436 
01437 QString
01438 KCmdLineArgs::getOption(const QByteArray &_opt) const
01439 {
01440    QByteArray opt = _opt;
01441    QByteArray value;
01442    if (d->parsedOptionList)
01443    {
01444       value = d->parsedOptionList->value(opt);
01445    }
01446    if (!value.isEmpty())
01447        return QString::fromLocal8Bit(value);
01448 
01449    // Look up the default.
01450    QByteArray opt_name;
01451    QString def;
01452    bool dummy = true;
01453    int result = s->findOption( d->options, opt, opt_name, def, dummy) & ~4;
01454 
01455    if (result != 3)
01456    {
01457       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01458       fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n",
01459                       opt.data(), opt.data());
01460       fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
01461 
01462       Q_ASSERT( 0 );
01463       exit(255);
01464    }
01465    return def;
01466 }
01467 
01468 QStringList
01469 KCmdLineArgs::getOptionList(const QByteArray &opt) const
01470 {
01471    QStringList result;
01472    if (!d->parsedOptionList)
01473       return result;
01474 
01475    while(true)
01476    {
01477       QByteArray value = d->parsedOptionList->take(opt);
01478       if (value.isEmpty())
01479          break;
01480       result.prepend(QString::fromLocal8Bit(value));
01481    }
01482 
01483    // Reinsert items in dictionary
01484    // WABA: This is rather silly, but I don't want to add restrictions
01485    // to the API like "you can only call this function once".
01486    // I can't access all items without taking them out of the list.
01487    // So taking them out and then putting them back is the only way.
01488    Q_FOREACH(const QString &str, result)
01489    {
01490       d->parsedOptionList->insertMulti(opt, str.toLocal8Bit());
01491    }
01492    return result;
01493 }
01494 
01495 bool
01496 KCmdLineArgs::isSet(const QByteArray &_opt) const
01497 {
01498    // Look up the default.
01499    QByteArray opt = _opt;
01500    QByteArray opt_name;
01501    QString def;
01502    int result = 0;
01503    KCmdLineArgsList::Iterator args = s->argsList->begin();
01504    while (args != s->argsList->end())
01505    {
01506       bool dummy = true;
01507       result = s->findOption((*args)->d->options, opt, opt_name, def, dummy) & ~4;
01508       if (result) break;
01509       ++args;
01510    }
01511 
01512    if (result == 0)
01513    {
01514       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01515       fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n",
01516                       opt.data(), opt.data());
01517       fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
01518 
01519       Q_ASSERT( 0 );
01520       exit(255);
01521    }
01522 
01523    QByteArray value;
01524    if (d->parsedOptionList)
01525    {
01526       value = d->parsedOptionList->value(opt);
01527    }
01528 
01529    if (!value.isEmpty())
01530    {
01531       if (result == 3)
01532          return true;
01533       else
01534          return (value.at(0) == 't');
01535    }
01536 
01537    if (result == 3)
01538       return false; // String option has 'false' as default.
01539 
01540    // We return 'true' as default if the option was listed as '-nofork'
01541    // We return 'false' as default if the option was listed as '-fork'
01542    return (result == 2);
01543 }
01544 
01545 int
01546 KCmdLineArgs::count() const
01547 {
01548    return d->parsedArgList?d->parsedArgList->count():0;
01549 }
01550 
01551 QString
01552 KCmdLineArgs::arg(int n) const
01553 {
01554    if (!d->parsedArgList || (n >= (int) d->parsedArgList->count()))
01555    {
01556       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n");
01557       fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n",
01558                       n);
01559 
01560       Q_ASSERT( 0 );
01561       exit(255);
01562    }
01563 
01564    return QString::fromLocal8Bit(d->parsedArgList->at(n));
01565 }
01566 
01567 KUrl
01568 KCmdLineArgs::url(int n) const
01569 {
01570    return makeURL( arg(n).toUtf8() );
01571 }
01572 
01573 KUrl KCmdLineArgs::makeURL(const QByteArray &_urlArg)
01574 {
01575     const QString urlArg = QString::fromUtf8(_urlArg);
01576     QFileInfo fileInfo(urlArg);
01577     if (!fileInfo.isRelative()) { // i.e. starts with '/', on unix
01578         KUrl result;
01579         result.setPath(QDir::fromNativeSeparators(urlArg));
01580         return result; // Absolute path.
01581     }
01582 
01583     if ( KUrl::isRelativeUrl(urlArg) || fileInfo.exists() ) {
01584         KUrl result;
01585         result.setPath(cwd()+QLatin1Char('/')+urlArg);
01586         result.cleanPath();
01587         return result;  // Relative path
01588     }
01589 
01590     return KUrl(urlArg); // Argument is a URL
01591 }
01592 
01593 void
01594 KCmdLineArgsPrivate::addArgument(const QByteArray &argument)
01595 {
01596    if (!parsedArgList)
01597       parsedArgList = new KCmdLineParsedArgs;
01598 
01599    parsedArgList->append(argument);
01600 }
01601 
01602 void
01603 KCmdLineArgs::addTempFileOption()
01604 {
01605     KCmdLineOptions tmpopt;
01606     tmpopt.add( "tempfile", ki18n("The files/URLs opened by the application will be deleted after use") );
01607     KCmdLineArgs::addCmdLineOptions( tmpopt, ki18n("KDE-tempfile"), "kde-tempfile" );
01608 }
01609 
01610 bool KCmdLineArgs::isTempFileSet()
01611 {
01612     KCmdLineArgs* args = KCmdLineArgs::parsedArgs( "kde-tempfile" );
01613     return args && args->isSet( "tempfile" );
01614 }
01615 
01616 QStringList KCmdLineArgs::allArguments()
01617 {
01618     QStringList lst;
01619 
01620     for(int i = 0; i < s->all_argc; i++) {
01621         char* arg = s->all_argv[i];
01622         if (!arg)
01623             continue;
01624         lst.append(QString::fromLocal8Bit(arg));
01625     }
01626     return lst;
01627 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:28:09 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs-4.9.5 API Reference

Skip menu "kdelibs-4.9.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal