// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf 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 General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "pdfcommandlineparser.hh" #include "progressfeedback.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_OS_UNIX) #include #endif using namespace wkhtmltopdf::settings; using namespace wkhtmltopdf; /*! * State mashine driven, shell like parser. This is used for * reading commandline options from stdin * \param buff the line to parse * \param nargc on return will hold the number of arguments read * \param nargv on return will hold the arguments read and be NULL terminated */ enum State {skip, tok, q1, q2, q1_esc, q2_esc, tok_esc}; void parseString(char * buff, int &nargc, char **nargv) { State state = skip; int write_start=0; int write=0; for (int read=0; buff[read]!='\0'; ++read) { State next_state=state; switch (state) { case skip: //Whitespace skipping state if (buff[read]!=' ' && buff[read]!='\t' && buff[read]!='\r' && buff[read]!='\n') { --read; next_state=tok; } break; case tok: //Normal toking reading state if (buff[read]=='\'') next_state=q1; else if (buff[read]=='"') next_state=q2; else if (buff[read]=='\\') next_state=tok_esc; else if (buff[read]==' ' || buff[read]=='\t' || buff[read]=='\n' || buff[read]=='\r') { next_state=skip; if (write_start != write) { buff[write++]='\0'; nargv[nargc++] = buff+write_start; if (nargc > 998) exit(1); } write_start = write; } else buff[write++] = buff[read]; break; case q1: //State parsing a single qoute argument if (buff[read]=='\'') next_state=tok; else if (buff[read]=='\\') next_state=q1_esc; else buff[write++] = buff[read]; break; case q2: //State parsing a double qoute argument if (buff[read]=='"') next_state=tok; else if (buff[read]=='\\') next_state=q2_esc; else buff[write++] = buff[read]; break; case tok_esc: //Escape one char and return to the token parsing state next_state=tok; buff[write++] = buff[read]; break; case q1_esc: //Espace one char and return to the single quote parsing state next_state=q1; buff[write++] = buff[read]; break; case q2_esc: //Escape one char and return to the double qoute parsing state next_state=q2; buff[write++] = buff[read]; break; } state=next_state; } //Remember the last parameter if (write_start != write) { buff[write++]='\0'; nargv[nargc++] = buff+write_start; } nargv[nargc]=NULL; } int main(int argc, char * argv[]) { #if defined(Q_OS_UNIX) setlocale(LC_ALL, ""); #endif //This will store all our settings PdfGlobal globalSettings; QList objectSettings; //Create a command line parser to parse commandline arguments PdfCommandLineParser parser(globalSettings, objectSettings); //Setup default values in settings //parser.loadDefaults(); //Parse the arguments parser.parseArguments(argc, (const char**)argv); //Construct QApplication required for printing bool use_graphics=true; #if defined(Q_OS_UNIX) || defined(Q_OS_MAC) #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ use_graphics=globalSettings.useGraphics; if (!use_graphics) QApplication::setGraphicsSystem("raster"); #endif #endif QApplication a(argc, argv, use_graphics); MyLooksStyle * style = new MyLooksStyle(); a.setStyle(style); if (parser.readArgsFromStdin) { char buff[20400]; char *nargv[1000]; nargv[0] = argv[0]; for (int i=0; i < argc; ++i) nargv[i] = argv[i]; while (fgets(buff,20398,stdin)) { int nargc=argc; parseString(buff,nargc,nargv); PdfGlobal globalSettings; QList objectSettings; //Create a command line parser to parse commandline arguments PdfCommandLineParser parser(globalSettings, objectSettings); //Setup default values in settings //parser.loadDefaults(); //Parse the arguments parser.parseArguments(nargc, (const char**)nargv, true); PdfConverter converter(globalSettings); ProgressFeedback feedback(globalSettings.quiet, converter); foreach (const PdfObject & object, objectSettings) converter.addResource(object); if (!converter.convert()) exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } //Create the actual page converter to convert the pages PdfConverter converter(globalSettings); QObject::connect(&converter, SIGNAL(producingForms(bool)), style, SLOT(producingForms(bool))); QObject::connect(&converter, SIGNAL(checkboxSvgChanged(const QString &)), style, SLOT(setCheckboxSvg(const QString &))); QObject::connect(&converter, SIGNAL(checkboxCheckedSvgChanged(const QString &)), style, SLOT(setCheckboxCheckedSvg(const QString &))); QObject::connect(&converter, SIGNAL(radiobuttonSvgChanged(const QString &)), style, SLOT(setRadioButtonSvg(const QString &))); QObject::connect(&converter, SIGNAL(radiobuttonCheckedSvgChanged(const QString &)), style, SLOT(setRadioButtonCheckedSvg(const QString &))); ProgressFeedback feedback(globalSettings.quiet, converter); foreach (const PdfObject & object, objectSettings) converter.addResource(object); bool success = converter.convert(); return handleError(success, converter.httpErrorCode()); }