make designMode property available from js
[kdelibs.git] / kdoctools / meinproc.cpp
blob349f3a0457dbd483509d5b54f8f89cf32e0a7af8
1 #ifndef _WIN32
2 extern "C" int xmlLoadExtDtdDefaultValue;
3 #endif
5 #include <config-kdoctools.h>
6 #include <config.h>
7 #include <string.h>
8 #include <sys/time.h>
9 #include <unistd.h>
10 #include <libxml/xmlversion.h>
11 #include <libxml/xmlmemory.h>
12 #include <libxml/debugXML.h>
13 #include <libxml/HTMLtree.h>
14 #include <libxml/xmlIO.h>
15 #include <libxml/parserInternals.h>
16 #include <libxslt/xsltconfig.h>
17 #include <libxslt/xsltInternals.h>
18 #include <libxslt/transform.h>
19 #include <libxslt/xsltutils.h>
20 #include <QtCore/QString>
21 #include <kstandarddirs.h>
22 #include <kcomponentdata.h>
23 #include "xslt.h"
24 #include <QtCore/QFile>
25 #include <QtCore/QDir>
26 #include <kcmdlineargs.h>
27 #include <klocale.h>
28 #include <kaboutdata.h>
29 #include <stdlib.h>
30 #include <kdebug.h>
31 #include <QtCore/QTextCodec>
32 #include <QtCore/QFileInfo>
33 #include <kshell.h>
34 #include <kurl.h>
35 #include <QtCore/QList>
37 class MyPair {
38 public:
39 QString word;
40 int base;};
42 typedef QList<MyPair> PairList;
44 void parseEntry(PairList &list, xmlNodePtr cur, int base)
46 if ( !cur )
47 return;
49 base += atoi( ( const char* )xmlGetProp(cur, ( const xmlChar* )"header") );
50 if ( base > 10 ) // 10 is the maximum
51 base = 10;
53 /* We don't care what the top level element name is */
54 cur = cur->xmlChildrenNode;
55 while (cur != NULL) {
57 if ( cur->type == XML_TEXT_NODE ) {
58 QString words = QString::fromUtf8( ( char* )cur->content );
59 QStringList wlist = words.simplified().split( ' ',QString::SkipEmptyParts );
60 for ( QStringList::ConstIterator it = wlist.begin();
61 it != wlist.end(); ++it )
63 MyPair m;
64 m.word = *it;
65 m.base = base;
66 list.append( m );
68 } else if ( !xmlStrcmp( cur->name, (const xmlChar *) "entry") )
69 parseEntry( list, cur, base );
71 cur = cur->next;
76 int main(int argc, char **argv) {
78 // xsltSetGenericDebugFunc(stderr, NULL);
80 KCmdLineOptions options;
81 options.add("stylesheet <xsl>", ki18n("Stylesheet to use"));
82 options.add("stdout", ki18n("Output whole document to stdout"));
83 options.add("o");
84 options.add("output <file>", ki18n("Output whole document to file"));
85 options.add("htdig", ki18n("Create a ht://dig compatible index"));
86 options.add("check", ki18n("Check the document for validity"));
87 options.add("cache <file>", ki18n("Create a cache file for the document"));
88 options.add("srcdir <dir>", ki18n("Set the srcdir, for kdelibs"));
89 options.add("param <key>=<value>", ki18n("Parameters to pass to the stylesheet"));
90 options.add("+xml", ki18n("The file to transform"));
92 KAboutData aboutData( "meinproc4", "kio_help4", ki18n("XML-Translator" ),
93 "$Revision$",
94 ki18n("KDE Translator for XML"));
96 KCmdLineArgs::init(argc, argv, &aboutData, KCmdLineArgs::CmdLineArgKDE);
97 KCmdLineArgs::addCmdLineOptions( options );
99 KComponentData ins("kio_help4");
100 KGlobal::locale();
103 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
104 if ( args->count() != 1 ) {
105 args->usage();
106 return ( 1 );
109 // Need to set SRCDIR before calling fillInstance
110 QString srcdir;
111 if ( args->isSet( "srcdir" ) )
112 srcdir = QDir( args->getOption( "srcdir" ) ).absolutePath();
113 fillInstance(ins,srcdir);
115 LIBXML_TEST_VERSION
117 QString checkFilename = args->arg( 0 );
118 QFileInfo checkFile(checkFilename);
119 if (!checkFile.exists())
121 kError() << "File '" << checkFilename << "' does not exist." << endl;
122 return ( 2 );
124 if (!checkFile.isFile())
126 kError() << "'" << checkFilename << "' is not a file." << endl;
127 return ( 2 );
129 if (!checkFile.isReadable())
131 kError() << "File '" << checkFilename << "' is not readable." << endl;
132 return ( 2 );
135 if ( args->isSet( "check" ) ) {
136 QString pwd_buffer = QDir::currentPath();
137 QFileInfo file( args->arg( 0 ) );
139 QByteArray catalogs;
140 catalogs += KUrl::fromLocalFile( KStandardDirs::locate( "dtd", "customization/catalog.xml" ) ).toEncoded();
141 catalogs += ' ';
142 catalogs += KUrl::fromLocalFile( KStandardDirs::locate( "dtd", "docbook/xml-dtd-4.1.2/catalog.xml" ) ).toEncoded();
144 setenv( "XML_CATALOG_FILES", catalogs.constData(), 1 );
145 QString exe;
146 #if defined( XMLLINT )
147 exe = XMLLINT;
148 #endif
149 if ( !QFileInfo( exe ).isExecutable() ) {
150 exe = KStandardDirs::findExe( "xmllint" );
151 if (exe.isEmpty())
152 exe = KStandardDirs::locate( "exe", "xmllint" );
154 if ( QFileInfo( exe ).isExecutable() ) {
155 QDir::setCurrent( file.absolutePath() );
156 QString cmd = exe;
157 cmd += " --valid --noout ";
158 #ifdef Q_OS_WIN
159 cmd += file.fileName();
160 #else
161 cmd += KShell::quoteArg(file.fileName());
162 #endif
163 cmd += " 2>&1";
164 FILE *xmllint = popen( QFile::encodeName( cmd ).constData(), "r" );
165 char buf[ 512 ];
166 bool noout = true;
167 unsigned int n;
168 while ( ( n = fread(buf, 1, sizeof( buf ) - 1, xmllint ) ) ) {
169 noout = false;
170 buf[ n ] = '\0';
171 fputs( buf, stderr );
173 pclose( xmllint );
174 QDir::setCurrent( pwd_buffer );
175 if ( !noout )
176 return 1;
177 } else {
178 kWarning() << "couldn't find xmllint";
182 xmlSubstituteEntitiesDefault(1);
183 xmlLoadExtDtdDefaultValue = 1;
185 QVector<const char *> params;
186 #ifndef Q_WS_WIN
187 // libxslt parses the path given to outputFile as XPath expression which fails
188 // see libxslt/xsltEvalUserParams
189 // this parameter is used only by share/apps/ksgmltools2/docbook/xsl/html/math.xsl
190 // and is not supported on windows yet
191 if (args->isSet( "output" ) ) {
192 params.append( qstrdup( "outputFile" ) );
193 params.append( qstrdup( args->getOption( "output" ).toLocal8Bit() ) );
195 #endif
197 const QStringList paramList = args->getOptionList( "param" );
198 QStringList::ConstIterator it = paramList.begin();
199 QStringList::ConstIterator end = paramList.end();
200 for ( ; it != end; ++it ) {
201 const QString tuple = *it;
202 const int ch = tuple.indexOf( '=' );
203 if ( ch == -1 ) {
204 kError() << "Key-Value tuple '" << tuple << "' lacks a '='!" << endl;
205 return( 2 );
207 params.append( qstrdup( tuple.left( ch ).toUtf8() ) );
208 params.append( qstrdup( tuple.mid( ch + 1 ).toUtf8() ) );
211 params.append( NULL );
213 bool index = args->isSet( "htdig" );
214 QString tss = args->getOption( "stylesheet" );
215 if ( tss.isEmpty() )
216 tss = "customization/kde-chunk.xsl";
217 if ( index )
218 tss = "customization/htdig_index.xsl" ;
220 tss = KStandardDirs::locate( "dtd", tss );
222 if ( index ) {
223 xsltStylesheetPtr style_sheet =
224 xsltParseStylesheetFile((const xmlChar *)tss.toLatin1().data());
226 if (style_sheet != NULL) {
228 xmlDocPtr doc = xmlParseFile( QFile::encodeName( args->arg( 0 ) ).constData() );
230 xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, &params[0]);
232 xmlFreeDoc(doc);
233 xsltFreeStylesheet(style_sheet);
234 if (res != NULL) {
235 xmlNodePtr cur = xmlDocGetRootElement(res);
236 if (!cur || xmlStrcmp(cur->name, (const xmlChar *) "entry")) {
237 fprintf(stderr,"document of the wrong type, root node != entry");
238 xmlFreeDoc(res);
239 return(1);
241 PairList list;
242 parseEntry( list, cur, 0 );
243 int wi = 0;
244 for ( PairList::ConstIterator it = list.begin(); it != list.end();
245 ++it, ++wi )
246 fprintf( stdout, "w\t%s\t%d\t%d\n", ( *it ).word.toUtf8().data(),
247 1000*wi/list.count(), ( *it ).base );
249 xmlFreeDoc(res);
250 } else {
251 kDebug() << "couldn't parse document " << args->arg( 0 );
253 } else {
254 kDebug() << "couldn't parse style sheet " << tss;
257 } else {
258 QString output = transform(args->arg( 0 ) , tss, params);
259 if (output.isEmpty()) {
260 fprintf(stderr, "unable to parse %s\n", args->arg( 0 ).toLocal8Bit().data());
261 return(1);
264 QString cache = args->getOption( "cache" );
265 if ( !cache.isEmpty() ) {
266 if ( !saveToCache( output, cache ) ) {
267 kError() << i18n( "Could not write to cache file %1." , cache ) << endl;
269 goto end;
272 if (output.indexOf( "<FILENAME " ) == -1 || args->isSet( "stdout" ) || args->isSet("output") )
274 QFile file;
275 if (args->isSet( "stdout" ) ) {
276 file.open( stdout, QIODevice::WriteOnly );
277 } else {
278 if (args->isSet( "output" ) )
279 file.setFileName( args->getOption( "output" ));
280 else
281 file.setFileName( "index.html" );
282 file.open(QIODevice::WriteOnly);
284 replaceCharsetHeader( output );
286 QByteArray data = output.toLocal8Bit();
287 file.write(data.data(), data.length());
288 file.close();
289 } else {
290 int index = 0;
291 while (true) {
292 index = output.indexOf("<FILENAME ", index);
293 if (index == -1)
294 break;
295 int filename_index = index + strlen("<FILENAME filename=\"");
297 QString filename = output.mid(filename_index,
298 output.indexOf("\"", filename_index) -
299 filename_index);
301 QString filedata = splitOut(output, index);
302 QFile file(filename);
303 file.open(QIODevice::WriteOnly);
304 replaceCharsetHeader( filedata );
305 QByteArray data = fromUnicode( filedata );
306 file.write(data.data(), data.length());
307 file.close();
309 index += 8;
313 end:
314 xmlCleanupParser();
315 xmlMemoryDump();
316 return(0);