You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by ja...@apache.org on 2013/01/24 13:21:39 UTC

svn commit: r1437973 [7/11] - in /openoffice/branches/l10n/main/l10ntools/source: ./ filter/ filter/merge/ filter/utils/ help/

Added: openoffice/branches/l10n/main/l10ntools/source/help/HelpFileDocument.java
URL: http://svn.apache.org/viewvc/openoffice/branches/l10n/main/l10ntools/source/help/HelpFileDocument.java?rev=1437973&view=auto
==============================================================================
--- openoffice/branches/l10n/main/l10ntools/source/help/HelpFileDocument.java (added)
+++ openoffice/branches/l10n/main/l10ntools/source/help/HelpFileDocument.java Thu Jan 24 12:21:38 2013
@@ -0,0 +1,82 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+
+
+package com.sun.star.help;
+
+import java.io.File;
+import java.io.Reader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+//import java.io.FileReader;
+import java.io.StringReader;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+
+/** Lucene Document for help files */
+public class HelpFileDocument
+{
+    /** Creates reader for UTF-8 files
+    */
+    private static Reader getReaderForFile( File aFile )
+        throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException {
+		Reader aReader;
+		if( aFile != null ) {
+			FileInputStream fis = new FileInputStream( aFile );
+			aReader = new InputStreamReader( fis, "UTF-8" );
+		}
+		else {
+			aReader = new StringReader( "" );
+		}
+		return aReader;
+    }
+    
+    /** Makes a document for a File.
+    */
+    public static Document Document( String aModule, File aCaptionFile, File aContentFile )
+        throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException {
+		Document doc = new Document();
+
+		// Add the path of the file as a field named "path".  Use a field that is 
+		// indexed (i.e. searchable), but don't tokenize the field into words.
+		File aFile = aCaptionFile != null ? aCaptionFile : aContentFile;
+		if( aFile != null )
+		{
+			String aPath = "#HLP#" + aModule + "/" + aFile.getName();
+			doc.add(new Field("path", aPath, Field.Store.YES, Field.Index.NOT_ANALYZED));
+		}
+		
+		// Add the caption of the file to a field named "caption".  Specify a Reader,
+		// so that the text of the file is tokenized and indexed, but not stored.
+		doc.add( new Field( "caption", getReaderForFile( aCaptionFile ) ) );
+
+		// Add the contents of the file to a field named "content".  Specify a Reader,
+		// so that the text of the file is tokenized and indexed, but not stored.
+		doc.add( new Field( "content", getReaderForFile( aContentFile ) ) );
+		
+		// return the document
+		return doc;
+	}
+
+    private HelpFileDocument() {}
+}

Propchange: openoffice/branches/l10n/main/l10ntools/source/help/HelpFileDocument.java
------------------------------------------------------------------------------
    svn:executable = *

Added: openoffice/branches/l10n/main/l10ntools/source/help/HelpIndexerTool.java
URL: http://svn.apache.org/viewvc/openoffice/branches/l10n/main/l10ntools/source/help/HelpIndexerTool.java?rev=1437973&view=auto
==============================================================================
--- openoffice/branches/l10n/main/l10ntools/source/help/HelpIndexerTool.java (added)
+++ openoffice/branches/l10n/main/l10ntools/source/help/HelpIndexerTool.java Thu Jan 24 12:21:38 2013
@@ -0,0 +1,408 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+
+
+package com.sun.star.help;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import java.util.zip.CRC32;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.analysis.cjk.CJKAnalyzer;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.util.Version;
+import org.apache.lucene.store.NIOFSDirectory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Date;
+
+/**
+   When this tool is used with long path names on Windows, that is paths which start
+   with \\?\, then the caller must make sure that the path is unique. This is achieved
+   by removing '.' and '..' from the path. Paths which are created by
+   osl_getSystemPathFromFileURL fulfill this requirement. This is necessary because
+   lucene is patched to not use File.getCanonicalPath. See long_path.patch in the lucene
+   module.
+ */
+
+public class HelpIndexerTool
+{
+    public HelpIndexerTool()
+	{
+    }
+
+    
+    /**
+     * @param args the command line arguments
+     */
+    public static void main( String[] args )
+	{
+		boolean bExtensionMode = false;
+		mainImpl( args, bExtensionMode ); 
+	}
+
+    public static void mainImpl( String[] args, boolean bExtensionMode )
+	{
+        String aDirToZipStr = "";
+        String aSrcDirStr = "";
+        String aLanguageStr = "";
+        String aModule = "";
+        String aTargetZipFileStr = "";
+        String aCfsName = "";
+        String aSegmentName = "";
+
+        // Scan arguments
+        //If this tool is invoked in the build process for extensions help,
+        //then -extension must be set.
+        boolean bExtension = false;
+        boolean bLang = false;
+        boolean bMod = false;
+        boolean bZipDir = false;
+        boolean bSrcDir = false;
+        boolean bOutput = false;
+        boolean bCfsName = false;
+        boolean bSegmentName = false;
+
+        int nArgCount = args.length;
+        for( int i = 0 ; i < nArgCount ; i++ )
+		{
+            if( "-extension".equals(args[i]) )
+			{
+                bExtension = true;
+            }            
+            else if( "-lang".equals(args[i]) )
+			{
+                if( i + 1 < nArgCount )
+				{
+                    aLanguageStr = args[i + 1];
+                    bLang = true;
+                }
+                i++;
+            }
+			else if( "-mod".equals(args[i]) )
+			{
+                if( i + 1 < nArgCount )
+				{
+                    aModule = args[i + 1];
+                    bMod = true;
+                }
+                i++;
+            }
+			else if( "-zipdir".equals(args[i]) )
+			{
+                if( i + 1 < nArgCount )
+				{
+                    aDirToZipStr = args[i + 1];
+                    bZipDir = true;
+                }
+                i++;
+            }
+			else if( "-srcdir".equals(args[i]) )
+			{
+                if( i + 1 < nArgCount )
+				{
+                    aSrcDirStr = args[i + 1];
+                    bSrcDir = true;
+                }
+                i++;
+            }
+			else if( "-o".equals(args[i]) )
+			{
+                if( i + 1 < nArgCount )
+				{
+                    aTargetZipFileStr = args[i + 1];
+                    bOutput = true;
+                }
+                i++;
+            }
+			else if( "-checkcfsandsegname".equals(args[i]) )
+			{
+                if( i + 1 < nArgCount )
+				{
+                    aCfsName = args[i + 1] + ".cfs";
+                    bCfsName = true;
+                }
+                i++;
+                if( i + 1 < nArgCount )
+				{
+                    aSegmentName = "segments" + args[i + 1];
+                    bSegmentName = true;
+                }
+                i++;
+                if (!(bCfsName && bSegmentName))
+                {
+                    System.out.println("Usage: HelpIndexer -checkcfsandsegname _0 _3 (2 arguments needed)");
+                    System.exit( -1 );
+                }
+            }
+        }
+
+        if( !bLang || !bMod || !bZipDir || (!bOutput && !bExtensionMode && !bExtension) )
+		{
+			if( bExtensionMode )
+				return;
+
+			System.out.println("Usage: HelpIndexer -lang ISOLangCode -mod HelpModule -zipdir TempZipDir -o OutputZipFile");
+            System.out.println("Usage: HelpIndexer -extension -lang ISOLangCode -mod HelpModule -zipdir PathToLangDir");
+			System.exit( -1 );
+        }
+
+        String aIndexDirName = aModule + ".idxl";
+        File aIndexDir = new File( aDirToZipStr + File.separator + aIndexDirName );
+		if( !bSrcDir )
+			aSrcDirStr = aDirToZipStr;
+        File aCaptionFilesDir = new File( aSrcDirStr + File.separator + "caption" );
+        File aContentFilesDir = new File( aSrcDirStr + File.separator + "content" );
+		
+        try
+		{
+            Date start = new Date();
+	    Analyzer analyzer = aLanguageStr.equals("ja") ? (Analyzer)new CJKAnalyzer(Version.LUCENE_29) : (Analyzer)new StandardAnalyzer(Version.LUCENE_29);
+	    IndexWriter writer = new IndexWriter( NIOFSDirectory.open(aIndexDir), analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED );
+			if( !bExtensionMode )
+	            System.out.println( "Lucene: Indexing to directory '" + aIndexDir + "'..." );
+            int nRet = indexDocs( writer, aModule, bExtensionMode, aCaptionFilesDir, aContentFilesDir );
+            if( nRet != -1 )
+			{
+				if( !bExtensionMode )
+				{
+					System.out.println();
+					System.out.println( "Optimizing ..." );
+				}
+                writer.optimize();
+            }
+            writer.close();
+
+			boolean bCfsFileOk = true;
+			boolean bSegmentFileOk = true;
+			if( bCfsName && bSegmentName && !bExtensionMode && nRet != -1 )
+			{
+				String aCompleteCfsFileName = aDirToZipStr + File.separator + aIndexDirName + File.separator + aCfsName;
+				String aCompleteSegmentFileName = aDirToZipStr + File.separator + aIndexDirName + File.separator + aSegmentName;
+				File aCfsFile = new File( aCompleteCfsFileName );
+				File aSegmentFile = new File( aCompleteSegmentFileName );
+				bCfsFileOk = aCfsFile.exists();
+				bSegmentFileOk = aSegmentFile.exists();
+				System.out.println( "Checking cfs file " + aCfsName+ ": " + (bCfsFileOk ? "Found" : "Not found") );
+				System.out.println( "Checking segment file " + aSegmentName+ ": " + (bSegmentFileOk ? "Found" : "Not found") );
+			}
+
+			if( bExtensionMode || bExtension)
+			{
+				if( !bSrcDir )
+				{
+					deleteRecursively( aCaptionFilesDir );
+					deleteRecursively( aContentFilesDir );
+				}
+			}
+			else
+			{
+				if( nRet == -1 )
+					deleteRecursively( aIndexDir );
+
+				if( bCfsFileOk && bSegmentFileOk )
+					System.out.println( "Zipping ..." );
+				File aDirToZipFile = new File( aDirToZipStr );
+				createZipFile( aDirToZipFile, aTargetZipFileStr );
+				deleteRecursively( aDirToZipFile );
+			}
+
+			if( !bCfsFileOk )
+			{
+				System.out.println( "cfs file check failed, terminating..." );
+				System.exit( -1 );
+			}
+
+			if( !bSegmentFileOk )
+			{
+				System.out.println( "segment file check failed, terminating..." );
+				System.exit( -1 );
+			}
+
+			Date end = new Date();
+			if( !bExtensionMode )
+				System.out.println(end.getTime() - start.getTime() + " total milliseconds");
+        }
+		catch (IOException e)
+		{
+			if( bExtensionMode )
+				return;
+
+			System.out.println(" caught a " + e.getClass() +
+				"\n with message: " + e.getMessage());
+			System.exit( -1 );
+        }
+    }
+
+	private static int indexDocs(IndexWriter writer, String aModule, boolean bExtensionMode,
+		File aCaptionFilesDir, File aContentFilesDir) throws IOException
+	{
+        if( !aCaptionFilesDir.canRead() || !aCaptionFilesDir.isDirectory() )
+		{
+			if( !bExtensionMode )
+	            System.out.println( "Not found: " + aCaptionFilesDir );
+            return -1;
+        }
+        if( !aContentFilesDir.canRead() || !aContentFilesDir.isDirectory() )
+		{
+			if( !bExtensionMode )
+	            System.out.println( "Not found: " + aContentFilesDir );
+            return -1;
+        }
+
+        String[] aCaptionFiles = aCaptionFilesDir.list();
+        List aCaptionFilesList = Arrays.asList( aCaptionFiles );
+        HashSet aCaptionFilesHashSet = new HashSet( aCaptionFilesList );
+
+        String[] aContentFiles = aContentFilesDir.list();
+        List aContentFilesList = Arrays.asList( aContentFiles );
+        HashSet aContentFilesHashSet = new HashSet( aContentFilesList );
+
+        // Loop over caption files and find corresponding content file
+		if( !bExtensionMode )
+	        System.out.println( "Indexing, adding files" );
+        int nCaptionFilesLen = aCaptionFiles.length;
+        for( int i = 0 ; i < nCaptionFilesLen ; i++ )
+		{
+            String aCaptionFileStr = aCaptionFiles[i];
+            File aCaptionFile = new File( aCaptionFilesDir, aCaptionFileStr );
+            File aContentFile = null;
+            if( aContentFilesHashSet.contains( aCaptionFileStr ) )
+                aContentFile = new File( aContentFilesDir, aCaptionFileStr );
+
+			if( !bExtensionMode )
+				System.out.print( "." );
+            writer.addDocument( HelpFileDocument.Document( aModule, aCaptionFile, aContentFile ) );
+        }
+
+        // Loop over content files to find remaining files not mapped to caption files
+        int nContentFilesLen = aContentFiles.length;
+        for( int i = 0 ; i < nContentFilesLen ; i++ )
+		{
+            String aContentFileStr = aContentFiles[i];
+            if( !aCaptionFilesHashSet.contains( aContentFileStr ) )
+			{
+                // Not already handled in caption files loop
+                File aCaptionFile = null;
+                File aContentFile = new File( aContentFilesDir, aContentFileStr );
+				if( !bExtensionMode )
+					System.out.print( "." );
+                writer.addDocument( HelpFileDocument.Document( aModule, aCaptionFile, aContentFile ) );
+            }
+        }
+        return 0;
+    }
+
+    public static void createZipFile( File aDirToZip, String aTargetZipFileStr )
+            throws FileNotFoundException, IOException
+	{
+        FileOutputStream fos = new FileOutputStream( aTargetZipFileStr );
+        ZipOutputStream zos = new ZipOutputStream( fos );
+
+        File[] aChildrenFiles = aDirToZip.listFiles();
+        int nFileCount = aChildrenFiles.length;
+        for( int i = 0 ; i < nFileCount ; i++ )
+            addToZipRecursively( zos, aChildrenFiles[i], null );
+
+        zos.close();
+    }
+
+    public static void addToZipRecursively( ZipOutputStream zos, File aFile, String aBasePath )
+            throws FileNotFoundException, IOException
+	{
+        if( aFile.isDirectory() )
+		{
+            String aDirName = aFile.getName();
+            if( aDirName.equalsIgnoreCase( "caption" ) || aDirName.equalsIgnoreCase( "content" ) )
+                return;
+
+            File[] aChildrenFiles = aFile.listFiles();
+            String aNewBasePath = "";
+            if( aBasePath != null )
+                aNewBasePath += aBasePath + File.separator;
+            aNewBasePath += aDirName;
+
+            int nFileCount = aChildrenFiles.length;
+            for( int i = 0 ; i < nFileCount ; i++ )
+                addToZipRecursively( zos, aChildrenFiles[i], aNewBasePath );
+
+            return;
+        }
+
+        // No directory
+        // read contents of file we are going to put in the zip
+        int fileLength = (int) aFile.length();
+        FileInputStream fis = new FileInputStream( aFile );
+        byte[] wholeFile = new byte[fileLength];
+        int bytesRead = fis.read( wholeFile, 0, fileLength );
+        fis.close();
+
+        String aFileName = aFile.getName();
+        String aEntryName = "";
+        if( aBasePath != null )
+            aEntryName += aBasePath + "/";
+        aEntryName += aFileName;
+        ZipEntry aZipEntry = new ZipEntry( aEntryName );
+        aZipEntry.setTime( aFile.lastModified() );
+        aZipEntry.setSize( fileLength );
+
+        int nMethod = ( aFileName.toLowerCase().endsWith( ".jar" ) )
+                ? ZipEntry.STORED : ZipEntry.DEFLATED;
+        aZipEntry.setMethod( nMethod );
+
+        CRC32 tempCRC = new CRC32();
+        tempCRC.update( wholeFile, 0, wholeFile.length );
+        aZipEntry.setCrc( tempCRC.getValue() );
+
+        // write the contents into the zip element
+        zos.putNextEntry( aZipEntry );
+        zos.write( wholeFile, 0, fileLength );
+        zos.closeEntry();
+    }
+
+    static public boolean deleteRecursively( File aFile )
+	{
+        if( aFile.isDirectory() )
+		{
+            File[] aChildrenFiles = aFile.listFiles();
+            int nFileCount = aChildrenFiles.length;
+            for( int i = 0 ; i < nFileCount ; i++ )
+			{
+                File aChildrenFile = aChildrenFiles[i];
+                boolean bSuccess = deleteRecursively( aChildrenFile );
+                if( !bSuccess )
+                    return false;
+            }
+        }
+
+        return aFile.delete();
+    }
+}
+

Propchange: openoffice/branches/l10n/main/l10ntools/source/help/HelpIndexerTool.java
------------------------------------------------------------------------------
    svn:executable = *

Added: openoffice/branches/l10n/main/l10ntools/source/help/HelpLinker.cxx
URL: http://svn.apache.org/viewvc/openoffice/branches/l10n/main/l10ntools/source/help/HelpLinker.cxx?rev=1437973&view=auto
==============================================================================
--- openoffice/branches/l10n/main/l10ntools/source/help/HelpLinker.cxx (added)
+++ openoffice/branches/l10n/main/l10ntools/source/help/HelpLinker.cxx Thu Jan 24 12:21:38 2013
@@ -0,0 +1,1095 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+
+
+#include "HelpCompiler.hxx"
+
+#include <map>
+
+#include <string.h>
+#include <limits.h>
+
+#include <libxslt/xslt.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/functions.h>
+#include <libxslt/extensions.h>
+
+#include <sal/types.h>
+#include <osl/time.h>
+#include <rtl/bootstrap.hxx>
+
+#include <expat.h>
+
+class IndexerPreProcessor
+{
+private:
+    std::string       m_aModuleName;
+    fs::path          m_fsIndexBaseDir;
+    fs::path          m_fsCaptionFilesDirName;
+    fs::path          m_fsContentFilesDirName;
+
+    xsltStylesheetPtr m_xsltStylesheetPtrCaption;
+    xsltStylesheetPtr m_xsltStylesheetPtrContent;
+
+public:
+    IndexerPreProcessor( const std::string& aModuleName, const fs::path& fsIndexBaseDir,
+         const fs::path& idxCaptionStylesheet, const fs::path& idxContentStylesheet );
+    ~IndexerPreProcessor();
+
+    void processDocument( xmlDocPtr doc, const std::string& EncodedDocPath );
+};
+
+IndexerPreProcessor::IndexerPreProcessor
+    ( const std::string& aModuleName, const fs::path& fsIndexBaseDir,
+      const fs::path& idxCaptionStylesheet, const fs::path& idxContentStylesheet )
+        : m_aModuleName( aModuleName )
+        , m_fsIndexBaseDir( fsIndexBaseDir )
+{
+    m_fsCaptionFilesDirName = fsIndexBaseDir / "caption";
+    fs::create_directory( m_fsCaptionFilesDirName );
+
+    m_fsContentFilesDirName = fsIndexBaseDir / "content";
+    fs::create_directory( m_fsContentFilesDirName );
+
+    m_xsltStylesheetPtrCaption = xsltParseStylesheetFile
+        ((const xmlChar *)idxCaptionStylesheet.native_file_string().c_str());
+    m_xsltStylesheetPtrContent = xsltParseStylesheetFile
+        ((const xmlChar *)idxContentStylesheet.native_file_string().c_str());
+}
+
+IndexerPreProcessor::~IndexerPreProcessor()
+{
+    if( m_xsltStylesheetPtrCaption )
+        xsltFreeStylesheet( m_xsltStylesheetPtrCaption );
+    if( m_xsltStylesheetPtrContent )
+        xsltFreeStylesheet( m_xsltStylesheetPtrContent );
+}
+
+
+std::string getEncodedPath( const std::string& Path )
+{
+    rtl::OString aOStr_Path( Path.c_str() );
+    rtl::OUString aOUStr_Path( rtl::OStringToOUString
+        ( aOStr_Path, fs::getThreadTextEncoding() ) );
+    rtl::OUString aPathURL;
+    osl::File::getFileURLFromSystemPath( aOUStr_Path, aPathURL );
+    rtl::OString aOStr_PathURL( rtl::OUStringToOString
+        ( aPathURL, fs::getThreadTextEncoding() ) );
+    std::string aStdStr_PathURL( aOStr_PathURL.getStr() );
+    return aStdStr_PathURL;
+}
+
+void IndexerPreProcessor::processDocument
+    ( xmlDocPtr doc, const std::string &EncodedDocPath )
+{
+    std::string aStdStr_EncodedDocPathURL = getEncodedPath( EncodedDocPath );
+
+    if( m_xsltStylesheetPtrCaption )
+    {
+        xmlDocPtr resCaption = xsltApplyStylesheet( m_xsltStylesheetPtrCaption, doc, NULL );
+        xmlNodePtr pResNodeCaption = resCaption->xmlChildrenNode;
+        if( pResNodeCaption )
+        {
+            fs::path fsCaptionPureTextFile_docURL = m_fsCaptionFilesDirName / aStdStr_EncodedDocPathURL;
+            std::string aCaptionPureTextFileStr_docURL = fsCaptionPureTextFile_docURL.native_file_string();
+#ifdef WNT     //We need _wfopen to support long file paths on Windows XP
+            FILE* pFile_docURL = _wfopen(
+                fsCaptionPureTextFile_docURL.native_file_string_w(), L"w" );
+#else            
+            FILE* pFile_docURL = fopen(
+                fsCaptionPureTextFile_docURL.native_file_string().c_str(), "w" );
+#endif            
+            if( pFile_docURL )
+            {
+                fprintf( pFile_docURL, "%s\n", pResNodeCaption->content );
+                fclose( pFile_docURL );
+            }
+        }
+        xmlFreeDoc(resCaption);
+    }
+
+    if( m_xsltStylesheetPtrContent )
+    {
+        xmlDocPtr resContent = xsltApplyStylesheet( m_xsltStylesheetPtrContent, doc, NULL );
+        xmlNodePtr pResNodeContent = resContent->xmlChildrenNode;
+        if( pResNodeContent )
+        {
+            fs::path fsContentPureTextFile_docURL = m_fsContentFilesDirName / aStdStr_EncodedDocPathURL;
+#ifdef WNT     //We need _wfopen to support long file paths on Windows XP
+            FILE* pFile_docURL = _wfopen(
+                fsContentPureTextFile_docURL.native_file_string_w(), L"w" );
+#else            
+            FILE* pFile_docURL = fopen(
+                fsContentPureTextFile_docURL.native_file_string().c_str(), "w" );
+#endif            
+            if( pFile_docURL )
+            {
+                fprintf( pFile_docURL, "%s\n", pResNodeContent->content );
+                fclose( pFile_docURL );
+            }
+        }
+        xmlFreeDoc(resContent);
+    }
+}
+
+struct Data
+{
+    std::vector<std::string> _idList;
+    typedef std::vector<std::string>::const_iterator cIter;
+
+    void append(const std::string &id)
+    {
+        _idList.push_back(id);
+    }
+
+    std::string getString() const
+    {
+        std::string ret;
+        cIter aEnd = _idList.end();
+        for (cIter aIter = _idList.begin(); aIter != aEnd; ++aIter)
+            ret += *aIter + ";";
+        return ret;
+    }
+};
+
+void writeKeyValue_DBHelp( FILE* pFile, const std::string& aKeyStr, const std::string& aValueStr )
+{
+    if( pFile == NULL )
+        return;
+    char cLF = 10;
+    unsigned int nKeyLen = aKeyStr.length();
+    unsigned int nValueLen = aValueStr.length();
+    fprintf( pFile, "%x ", nKeyLen );
+    if( nKeyLen > 0 )
+    {
+        if (fwrite( aKeyStr.c_str(), 1, nKeyLen, pFile ) != nKeyLen)
+            fprintf(stderr, "fwrite to db failed\n");
+    }
+    if (fprintf( pFile, " %x ", nValueLen ) < 0)
+        fprintf(stderr, "fwrite to db failed\n");
+    if( nValueLen > 0 )
+    {
+        if (fwrite( aValueStr.c_str(), 1, nValueLen, pFile ) != nValueLen)
+            fprintf(stderr, "fwrite to db failed\n");
+    }
+    if (fprintf( pFile, "%c", cLF ) < 0)
+        fprintf(stderr, "fwrite to db failed\n");
+}
+
+class HelpKeyword
+{
+private:
+    typedef std::hash_map<std::string, Data, pref_hash> DataHashtable;
+    DataHashtable _hash;
+
+public:
+    void insert(const std::string &key, const std::string &id)
+    {
+        Data &data = _hash[key];
+        data.append(id);
+    }
+
+    void dump_DBHelp( const fs::path& rFileName )
+    {
+#ifdef WNT     //We need _wfopen to support long file paths on Windows XP
+        FILE* pFile = _wfopen( rFileName.native_file_string_w(), L"wb" );
+#else        
+        FILE* pFile = fopen( rFileName.native_file_string().c_str(), "wb" );
+#endif        
+        if( pFile == NULL )
+            return;
+
+        DataHashtable::const_iterator aEnd = _hash.end();
+        for (DataHashtable::const_iterator aIter = _hash.begin(); aIter != aEnd; ++aIter)
+            writeKeyValue_DBHelp( pFile, aIter->first, aIter->second.getString() );
+
+        fclose( pFile );
+    }
+};
+
+class HelpLinker
+{
+public:
+    void main(std::vector<std::string> &args,
+              std::string* pExtensionPath = NULL,
+              std::string* pDestination = NULL,
+              const rtl::OUString* pOfficeHelpPath = NULL )
+
+            throw( HelpProcessingException );
+
+    HelpLinker()
+        : init(true)
+        , m_pIndexerPreProcessor(NULL)
+    {}
+    ~HelpLinker()
+        { delete m_pIndexerPreProcessor; }
+
+private:
+    int locCount, totCount;
+    Stringtable additionalFiles;
+    HashSet helpFiles;
+    fs::path sourceRoot;
+    fs::path embeddStylesheet;
+    fs::path idxCaptionStylesheet;
+    fs::path idxContentStylesheet;
+    fs::path zipdir;
+    fs::path outputFile;
+    std::string extsource;
+    std::string extdestination;
+    std::string module;
+    std::string lang;
+    std::string extensionPath;
+    std::string extensionDestination;
+    bool bExtensionMode;
+    fs::path indexDirName;
+    fs::path indexDirParentName;
+    bool init;
+    IndexerPreProcessor* m_pIndexerPreProcessor;
+    void initIndexerPreProcessor();
+    void link() throw( HelpProcessingException );
+    void addBookmark( FILE* pFile_DBHelp, std::string thishid,
+        const std::string& fileB, const std::string& anchorB,
+        const std::string& jarfileB, const std::string& titleB );
+};
+
+namespace URLEncoder
+{
+    static std::string encode(const std::string &rIn)
+    {
+        const char *good = "!$&'()*+,-.=@_";
+        static const char hex[17] = "0123456789ABCDEF";
+
+        std::string result;
+        for (size_t i=0; i < rIn.length(); ++i)
+        {
+            unsigned char c = rIn[i];
+            if (isalnum (c) || strchr (good, c))
+                result += c;
+            else {
+                result += '%';
+                result += hex[c >> 4];
+                result += hex[c & 0xf];
+            }
+        }
+        return result;
+    }
+}
+
+void HelpLinker::addBookmark( FILE* pFile_DBHelp, std::string thishid,
+        const std::string& fileB, const std::string& anchorB,
+        const std::string& jarfileB, const std::string& titleB)
+{
+    HCDBG(std::cerr << "HelpLinker::addBookmark " << thishid << " " <<
+        fileB << " " << anchorB << " " << jarfileB << " " << titleB << std::endl);
+
+    thishid = URLEncoder::encode(thishid);
+
+    int fileLen = fileB.length();
+    if (!anchorB.empty())
+        fileLen += (1 + anchorB.length());
+    int dataLen = 1 + fileLen + 1 + jarfileB.length() + 1 + titleB.length();
+
+    std::vector<unsigned char> dataB(dataLen);
+    size_t i = 0;
+    dataB[i++] = static_cast<unsigned char>(fileLen);
+    for (size_t j = 0; j < fileB.length(); ++j)
+        dataB[i++] = fileB[j];
+    if (!anchorB.empty())
+    {
+        dataB[i++] = '#';
+        for (size_t j = 0; j < anchorB.length(); ++j)
+            dataB[i++] = anchorB[j];
+    }
+    dataB[i++] = static_cast<unsigned char>(jarfileB.length());
+    for (size_t j = 0; j < jarfileB.length(); ++j)
+        dataB[i++] = jarfileB[j];
+
+    dataB[i++] = static_cast<unsigned char>(titleB.length());
+    for (size_t j = 0; j < titleB.length(); ++j)
+        dataB[i++] = titleB[j];
+
+    if( pFile_DBHelp != NULL )
+    {
+        std::string aValueStr( dataB.begin(), dataB.end() );
+        writeKeyValue_DBHelp( pFile_DBHelp, thishid, aValueStr );
+    }
+}
+
+void HelpLinker::initIndexerPreProcessor()
+{
+    if( m_pIndexerPreProcessor )
+        delete m_pIndexerPreProcessor;
+    std::string mod = module;
+    std::transform (mod.begin(), mod.end(), mod.begin(), tolower);
+    m_pIndexerPreProcessor = new IndexerPreProcessor( mod, indexDirParentName,
+         idxCaptionStylesheet, idxContentStylesheet );
+}
+
+/**
+*
+*/
+void HelpLinker::link() throw( HelpProcessingException )
+{
+    bool bIndexForExtension = true;
+
+    if( bExtensionMode )
+    {
+        //indexDirParentName = sourceRoot;
+        indexDirParentName = extensionDestination;
+    }
+    else
+    {
+        indexDirParentName = zipdir;
+        fs::create_directory(indexDirParentName);
+    }
+
+    std::string mod = module;
+    std::transform (mod.begin(), mod.end(), mod.begin(), tolower);
+
+    // do the work here
+    // continue with introduction of the overall process thing into the
+    // here all hzip files will be worked on
+    std::string appl = mod;
+    if (appl[0] == 's')
+        appl = appl.substr(1);
+
+    bool bUse_ = true;
+    if( !bExtensionMode )
+        bUse_ = false;
+
+    fs::path helpTextFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".ht_" : ".ht")));
+#ifdef WNT
+    //We need _wfopen to support long file paths on Windows XP
+    FILE* pFileHelpText_DBHelp = _wfopen
+        ( helpTextFileName_DBHelp.native_file_string_w(), L"wb" );
+#else
+    
+    FILE* pFileHelpText_DBHelp = fopen
+        ( helpTextFileName_DBHelp.native_file_string().c_str(), "wb" );
+#endif
+
+    fs::path dbBaseFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".db_" : ".db")));
+#ifdef WNT
+    //We need _wfopen to support long file paths on Windows XP
+    FILE* pFileDbBase_DBHelp = _wfopen
+        ( dbBaseFileName_DBHelp.native_file_string_w(), L"wb" );
+#else    
+    FILE* pFileDbBase_DBHelp = fopen
+        ( dbBaseFileName_DBHelp.native_file_string().c_str(), "wb" );
+#endif    
+
+    fs::path keyWordFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".key_" : ".key")));
+
+    HelpKeyword helpKeyword;
+
+    // catch HelpProcessingException to avoid locking data bases
+    try
+    {
+
+    // lastly, initialize the indexBuilder
+    if ( (!bExtensionMode || bIndexForExtension) && !helpFiles.empty())
+        initIndexerPreProcessor();
+
+    if( !bExtensionMode )
+    {
+#ifndef OS2 // YD @TODO@ crashes libc runtime :-(
+        std::cout << "Making " << outputFile.native_file_string() <<
+            " from " << helpFiles.size() << " input files" << std::endl;
+#endif
+    }
+
+    // here we start our loop over the hzip files.
+    HashSet::iterator end = helpFiles.end();
+    for (HashSet::iterator iter = helpFiles.begin(); iter != end; ++iter)
+    {
+        if( !bExtensionMode )
+        {
+            std::cout << ".";
+            std::cout.flush();
+        }
+
+        // process one file
+        // streamTable contains the streams in the hzip file
+        StreamTable streamTable;
+        const std::string &xhpFileName = *iter;
+
+        if (!bExtensionMode && xhpFileName.rfind(".xhp") != xhpFileName.length()-4)
+        {
+            // only work on .xhp - files
+            std::cerr <<
+                "ERROR: input list entry '"
+                    << xhpFileName
+                    << "' has the wrong extension (only files with extension .xhp "
+                    << "are accepted)";
+            continue;
+        }
+
+        fs::path langsourceRoot(sourceRoot);
+        fs::path xhpFile;
+
+        if( bExtensionMode )
+        {
+            // langsourceRoot == sourceRoot for extensions
+            std::string xhpFileNameComplete( extensionPath );
+            xhpFileNameComplete.append( '/' + xhpFileName );
+            xhpFile = fs::path( xhpFileNameComplete );
+        }
+        else
+        {
+            langsourceRoot.append('/' + lang + '/');
+            xhpFile = fs::path(xhpFileName, fs::native);
+        }
+
+        HelpCompiler hc( streamTable, xhpFile, langsourceRoot,
+            embeddStylesheet, module, lang, bExtensionMode );
+
+        HCDBG(std::cerr << "before compile of " << xhpFileName << std::endl);
+        bool success = hc.compile();
+        HCDBG(std::cerr << "after compile of " << xhpFileName << std::endl);
+
+        if (!success && !bExtensionMode)
+        {
+            std::stringstream aStrStream;
+            aStrStream <<
+                "\nERROR: compiling help particle '"
+                    << xhpFileName
+                    << "' for language '"
+                    << lang
+                    << "' failed!";
+            throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+        }
+
+        const std::string documentBaseId = streamTable.document_id;
+        std::string documentPath = streamTable.document_path;
+        if (documentPath.find("/") == 0)
+            documentPath = documentPath.substr(1);
+
+        std::string documentJarfile = streamTable.document_module + ".jar";
+
+        std::string documentTitle = streamTable.document_title;
+        if (documentTitle.empty())
+            documentTitle = "<notitle>";
+
+        const std::string& fileB = documentPath;
+        const std::string& jarfileB = documentJarfile;
+        std::string& titleB = documentTitle;
+
+        // add once this as its own id.
+        addBookmark(pFileDbBase_DBHelp, documentPath, fileB, std::string(), jarfileB, titleB);
+
+        const HashSet *hidlist = streamTable.appl_hidlist;
+        if (!hidlist)
+            hidlist = streamTable.default_hidlist;
+        if (hidlist && !hidlist->empty())
+        {
+            // now iterate over all elements of the hidlist
+            HashSet::const_iterator aEnd = hidlist->end();
+            for (HashSet::const_iterator hidListIter = hidlist->begin();
+                hidListIter != aEnd; ++hidListIter)
+            {
+                std::string thishid = *hidListIter;
+
+                std::string anchorB;
+                size_t index = thishid.rfind('#');
+                if (index != std::string::npos)
+                {
+                    anchorB = thishid.substr(1 + index);
+                    thishid = thishid.substr(0, index);
+                }
+                addBookmark(pFileDbBase_DBHelp, thishid, fileB, anchorB, jarfileB, titleB);
+            }
+        }
+
+        // now the keywords
+        const Hashtable *anchorToLL = streamTable.appl_keywords;
+        if (!anchorToLL)
+            anchorToLL = streamTable.default_keywords;
+        if (anchorToLL && !anchorToLL->empty())
+        {
+            std::string fakedHid = URLEncoder::encode(documentPath);
+            Hashtable::const_iterator aEnd = anchorToLL->end();
+            for (Hashtable::const_iterator enumer = anchorToLL->begin();
+                enumer != aEnd; ++enumer)
+            {
+                const std::string &anchor = enumer->first;
+                addBookmark(pFileDbBase_DBHelp, documentPath, fileB,
+                    anchor, jarfileB, titleB);
+                std::string totalId = fakedHid + "#" + anchor;
+                // std::cerr << hzipFileName << std::endl;
+                const LinkedList& ll = enumer->second;
+                LinkedList::const_iterator aOtherEnd = ll.end();
+                for (LinkedList::const_iterator llIter = ll.begin();
+                    llIter != aOtherEnd; ++llIter)
+                {
+                        helpKeyword.insert(*llIter, totalId);
+                }
+            }
+
+        }
+
+        // and last the helptexts
+        const Stringtable *helpTextHash = streamTable.appl_helptexts;
+        if (!helpTextHash)
+            helpTextHash = streamTable.default_helptexts;
+        if (helpTextHash && !helpTextHash->empty())
+        {
+            Stringtable::const_iterator aEnd = helpTextHash->end();
+            for (Stringtable::const_iterator helpTextIter = helpTextHash->begin();
+                helpTextIter != aEnd; ++helpTextIter)
+            {
+                std::string helpTextId = helpTextIter->first;
+                const std::string& helpTextText = helpTextIter->second;
+
+                helpTextId = URLEncoder::encode(helpTextId);
+
+                if( pFileHelpText_DBHelp != NULL )
+                    writeKeyValue_DBHelp( pFileHelpText_DBHelp, helpTextId, helpTextText );
+            }
+        }
+
+        //IndexerPreProcessor
+        if( !bExtensionMode || bIndexForExtension )
+        {
+            // now the indexing
+            xmlDocPtr document = streamTable.appl_doc;
+            if (!document)
+                document = streamTable.default_doc;
+            if (document)
+            {
+                std::string temp = module;
+                std::transform (temp.begin(), temp.end(), temp.begin(), tolower);
+                m_pIndexerPreProcessor->processDocument(document, URLEncoder::encode(documentPath) );
+            }
+        }
+
+    } // while loop over hzip files ending
+    if( !bExtensionMode )
+        std::cout << std::endl;
+
+    } // try
+    catch( const HelpProcessingException& )
+    {
+        // catch HelpProcessingException to avoid locking data bases
+        if( pFileHelpText_DBHelp != NULL )
+            fclose( pFileHelpText_DBHelp );
+        if( pFileDbBase_DBHelp != NULL )
+            fclose( pFileDbBase_DBHelp );
+        throw;
+    }
+
+    if( pFileHelpText_DBHelp != NULL )
+        fclose( pFileHelpText_DBHelp );
+    if( pFileDbBase_DBHelp != NULL )
+        fclose( pFileDbBase_DBHelp );
+
+    helpKeyword.dump_DBHelp( keyWordFileName_DBHelp);
+
+    if( !bExtensionMode )
+    {
+        // New index
+        Stringtable::iterator aEnd = additionalFiles.end();
+        for (Stringtable::iterator enumer = additionalFiles.begin(); enumer != aEnd;
+            ++enumer)
+        {
+            const std::string &additionalFileName = enumer->second;
+            const std::string &additionalFileKey = enumer->first;
+
+            fs::path fsAdditionalFileName( additionalFileName, fs::native );
+                std::string aNativeStr = fsAdditionalFileName.native_file_string();
+                const char* pStr = aNativeStr.c_str();
+                std::cerr << pStr;
+
+            fs::path fsTargetName( indexDirParentName / additionalFileKey );
+
+            fs::copy( fsAdditionalFileName, fsTargetName );
+        }
+    }
+
+}
+
+
+void HelpLinker::main( std::vector<std::string> &args,
+                       std::string* pExtensionPath, std::string* pDestination,
+                       const rtl::OUString* pOfficeHelpPath )
+    throw( HelpProcessingException )
+{
+    bExtensionMode = false;
+    helpFiles.clear();
+
+    if (args.size() > 0 && args[0][0] == '@')
+    {
+        std::vector<std::string> stringList;
+        std::string strBuf;
+        std::ifstream fileReader(args[0].substr(1).c_str());
+
+        while (fileReader)
+        {
+            std::string token;
+            fileReader >> token;
+            if (!token.empty())
+                stringList.push_back(token);
+        }
+        fileReader.close();
+
+        args = stringList;
+    }
+
+    size_t i = 0;
+    bool bSrcOption = false;
+    while (i < args.size())
+    {
+        if (args[i].compare("-extlangsrc") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "extension source missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+            extsource = args[i];
+        }
+        else if (args[i].compare("-extlangdest") == 0)
+        {
+            //If this argument is not provided then the location provided in -extsource will
+            //also be the destination
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "extension destination missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+            extdestination = args[i];
+        }
+        else if (args[i].compare("-src") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "sourceroot missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+            bSrcOption = true;
+            sourceRoot = fs::path(args[i], fs::native);
+        }
+        else if (args[i].compare("-sty") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "embeddingStylesheet missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+
+            embeddStylesheet = fs::path(args[i], fs::native);
+        }
+        else if (args[i].compare("-zipdir") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "idxtemp missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+
+            zipdir = fs::path(args[i], fs::native);
+        }
+        else if (args[i].compare("-idxcaption") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "idxcaption stylesheet missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+
+            idxCaptionStylesheet = fs::path(args[i], fs::native);
+        }
+        else if (args[i].compare("-idxcontent") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "idxcontent stylesheet missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+
+            idxContentStylesheet = fs::path(args[i], fs::native);
+        }
+        else if (args[i].compare("-o") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "outputfilename missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+
+            outputFile = fs::path(args[i], fs::native);
+        }
+        else if (args[i].compare("-mod") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "module name missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+
+            module = args[i];
+        }
+        else if (args[i].compare("-lang") == 0)
+        {
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "language name missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+
+            lang = args[i];
+        }
+        else if (args[i].compare("-hid") == 0)
+        {
+            ++i;
+            throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, "obsolete -hid argument used" );
+        }
+        else if (args[i].compare("-add") == 0)
+        {
+            std::string addFile, addFileUnderPath;
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "pathname missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+
+            addFileUnderPath = args[i];
+            ++i;
+            if (i >= args.size())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "pathname missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+            addFile = args[i];
+            if (!addFileUnderPath.empty() && !addFile.empty())
+                additionalFiles[addFileUnderPath] = addFile;
+        }
+        else
+            helpFiles.push_back(args[i]);
+        ++i;
+    }
+
+    //We can be called from the helplinker executable or the extension manager
+    //In the latter case extsource is not used.
+    if( (pExtensionPath && pExtensionPath->length() > 0 && pOfficeHelpPath)
+        || !extsource.empty())
+    {
+        bExtensionMode = true;
+        if (!extsource.empty())
+        {
+            //called from helplinker.exe, pExtensionPath and pOfficeHelpPath
+            //should be NULL
+            sourceRoot = fs::path(extsource, fs::native);
+            extensionPath = sourceRoot.toUTF8();
+
+            if (extdestination.empty())
+            {
+                std::stringstream aStrStream;
+                aStrStream << "-extlangdest is missing" << std::endl;
+                throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+            }
+            else
+            {
+                //Convert from system path to file URL!!!
+                fs::path p(extdestination, fs::native);
+                extensionDestination = p.toUTF8();
+            }
+        }
+        else
+        { //called from extension manager
+            extensionPath = *pExtensionPath;
+            sourceRoot = fs::path(extensionPath);
+            extensionDestination = *pDestination;
+        }
+        //check if -src option was used. This option must not be used
+        //when extension help is compiled.
+        if (bSrcOption)
+        {
+            std::stringstream aStrStream;
+            aStrStream << "-src must not be used together with -extsource missing" << std::endl;
+            throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+        }
+    }
+
+    if (!bExtensionMode && zipdir.empty())
+    {
+        std::stringstream aStrStream;
+        aStrStream << "no index dir given" << std::endl;
+        throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+    }
+
+    if (!bExtensionMode && idxCaptionStylesheet.empty()
+        || !extsource.empty() && idxCaptionStylesheet.empty())
+    {
+        //No extension mode and extension mode using commandline
+        //!extsource.empty indicates extension mode using commandline
+        // -idxcaption paramter is required
+        std::stringstream aStrStream;
+        aStrStream << "no index caption stylesheet given" << std::endl;
+        throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+    }
+    else if ( bExtensionMode &&  extsource.empty())
+    {
+        //This part is used when compileExtensionHelp is called from the extensions manager.
+        //If extension help is compiled using helplinker in the build process
+        rtl::OUString aIdxCaptionPathFileURL( *pOfficeHelpPath );
+        aIdxCaptionPathFileURL += rtl::OUString::createFromAscii( "/idxcaption.xsl" );
+
+        rtl::OString aOStr_IdxCaptionPathFileURL( rtl::OUStringToOString
+            ( aIdxCaptionPathFileURL, fs::getThreadTextEncoding() ) );
+        std::string aStdStr_IdxCaptionPathFileURL( aOStr_IdxCaptionPathFileURL.getStr() );
+
+        idxCaptionStylesheet = fs::path( aStdStr_IdxCaptionPathFileURL );
+    }
+
+    if (!bExtensionMode && idxContentStylesheet.empty()
+        || !extsource.empty() && idxContentStylesheet.empty())
+    {
+        //No extension mode and extension mode using commandline
+        //!extsource.empty indicates extension mode using commandline
+        // -idxcontent paramter is required
+        std::stringstream aStrStream;
+        aStrStream << "no index content stylesheet given" << std::endl;
+        throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+    }
+    else if ( bExtensionMode && extsource.empty())
+    {
+        //If extension help is compiled using helplinker in the build process
+        //then  -idxcontent must be supplied
+        //This part is used when compileExtensionHelp is called from the extensions manager.
+        rtl::OUString aIdxContentPathFileURL( *pOfficeHelpPath );
+        aIdxContentPathFileURL += rtl::OUString::createFromAscii( "/idxcontent.xsl" );
+
+        rtl::OString aOStr_IdxContentPathFileURL( rtl::OUStringToOString
+            ( aIdxContentPathFileURL, fs::getThreadTextEncoding() ) );
+        std::string aStdStr_IdxContentPathFileURL( aOStr_IdxContentPathFileURL.getStr() );
+
+        idxContentStylesheet = fs::path( aStdStr_IdxContentPathFileURL );
+    }
+    if (!bExtensionMode && embeddStylesheet.empty())
+    {
+        std::stringstream aStrStream;
+        aStrStream << "no embedding resolving file given" << std::endl;
+        throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+    }
+    if (sourceRoot.empty())
+    {
+        std::stringstream aStrStream;
+        aStrStream << "no sourceroot given" << std::endl;
+        throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+    }
+    if (!bExtensionMode && outputFile.empty())
+    {
+        std::stringstream aStrStream;
+        aStrStream << "no output file given" << std::endl;
+        throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+    }
+    if (module.empty())
+    {
+        std::stringstream aStrStream;
+        aStrStream << "module missing" << std::endl;
+        throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+    }
+    if (!bExtensionMode && lang.empty())
+    {
+        std::stringstream aStrStream;
+        aStrStream << "language missing" << std::endl;
+        throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+    }
+    link();
+}
+
+int main(int argc, char**argv)
+{
+    sal_uInt32 starttime = osl_getGlobalTimer();
+    std::vector<std::string> args;
+    for (int i = 1; i < argc; ++i)
+        args.push_back(std::string(argv[i]));
+    try
+    {
+        HelpLinker* pHelpLinker = new HelpLinker();
+        pHelpLinker->main( args );
+        delete pHelpLinker;
+    }
+    catch( const HelpProcessingException& e )
+    {
+        std::cerr << e.m_aErrorMsg;
+        exit(1);
+    }
+    sal_uInt32 endtime = osl_getGlobalTimer();
+#ifndef OS2 // YD @TODO@ crashes libc runtime :-(
+    std::cout << "time taken was " << (endtime-starttime)/1000.0 << " seconds" << std::endl;
+#endif
+    return 0;
+}
+
+// Variable to set an exception in "C" StructuredXMLErrorFunction
+static const HelpProcessingException* GpXMLParsingException = NULL;
+
+extern "C" void StructuredXMLErrorFunction(void *userData, xmlErrorPtr error)
+{
+    (void)userData;
+    (void)error;
+
+    std::string aErrorMsg = error->message;
+    std::string aXMLParsingFile;
+    if( error->file != NULL )
+        aXMLParsingFile = error->file;
+    int nXMLParsingLine = error->line;
+    HelpProcessingException* pException = new HelpProcessingException( aErrorMsg, aXMLParsingFile, nXMLParsingLine );
+    GpXMLParsingException = pException;
+
+    // Reset error handler
+    xmlSetStructuredErrorFunc( NULL, NULL );
+}
+
+HelpProcessingErrorInfo& HelpProcessingErrorInfo::operator=( const struct HelpProcessingException& e )
+{
+    m_eErrorClass = e.m_eErrorClass;
+    rtl::OString tmpErrorMsg( e.m_aErrorMsg.c_str() );
+    m_aErrorMsg = rtl::OStringToOUString( tmpErrorMsg, fs::getThreadTextEncoding() );
+    rtl::OString tmpXMLParsingFile( e.m_aXMLParsingFile.c_str() );
+    m_aXMLParsingFile = rtl::OStringToOUString( tmpXMLParsingFile, fs::getThreadTextEncoding() );
+    m_nXMLParsingLine = e.m_nXMLParsingLine;
+    return *this;
+}
+
+
+// Returns true in case of success, false in case of error
+HELPLINKER_DLLPUBLIC bool compileExtensionHelp
+(
+    const rtl::OUString& aOfficeHelpPath,
+    const rtl::OUString& aExtensionName,
+    const rtl::OUString& aExtensionLanguageRoot,
+    sal_Int32 nXhpFileCount, const rtl::OUString* pXhpFiles,
+    const rtl::OUString& aDestination,
+    HelpProcessingErrorInfo& o_rHelpProcessingErrorInfo
+)
+{
+    bool bSuccess = true;
+
+    std::vector<std::string> args;
+    args.reserve(nXhpFileCount + 2);
+    args.push_back(std::string("-mod"));
+    rtl::OString aOExtensionName = rtl::OUStringToOString( aExtensionName, fs::getThreadTextEncoding() );
+    args.push_back(std::string(aOExtensionName.getStr()));
+
+    for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp )
+    {
+        rtl::OUString aXhpFile = pXhpFiles[iXhp];
+
+        rtl::OString aOXhpFile = rtl::OUStringToOString( aXhpFile, fs::getThreadTextEncoding() );
+        args.push_back(std::string(aOXhpFile.getStr()));
+    }
+
+    rtl::OString aOExtensionLanguageRoot = rtl::OUStringToOString( aExtensionLanguageRoot, fs::getThreadTextEncoding() );
+    const char* pExtensionPath = aOExtensionLanguageRoot.getStr();
+    std::string aStdStrExtensionPath = pExtensionPath;
+    rtl::OString aODestination = rtl::OUStringToOString(aDestination, fs::getThreadTextEncoding());
+    const char* pDestination = aODestination.getStr();
+    std::string aStdStrDestination = pDestination;
+
+    // Set error handler
+    xmlSetStructuredErrorFunc( NULL, (xmlStructuredErrorFunc)StructuredXMLErrorFunction );
+    try
+    {
+        HelpLinker* pHelpLinker = new HelpLinker();
+        pHelpLinker->main( args, &aStdStrExtensionPath, &aStdStrDestination, &aOfficeHelpPath );
+        delete pHelpLinker;
+    }
+    catch( const HelpProcessingException& e )
+    {
+        if( GpXMLParsingException != NULL )
+        {
+            o_rHelpProcessingErrorInfo = *GpXMLParsingException;
+            delete GpXMLParsingException;
+            GpXMLParsingException = NULL;
+        }
+        else
+        {
+            o_rHelpProcessingErrorInfo = e;
+        }
+        bSuccess = false;
+    }
+    // Reset error handler
+    xmlSetStructuredErrorFunc( NULL, NULL );
+
+    // i83624: Tree files
+    ::rtl::OUString aTreeFileURL = aExtensionLanguageRoot;
+    aTreeFileURL += rtl::OUString::createFromAscii( "/help.tree" );
+    osl::DirectoryItem aTreeFileItem;
+    osl::FileBase::RC rcGet = osl::DirectoryItem::get( aTreeFileURL, aTreeFileItem );
+    osl::FileStatus aFileStatus( FileStatusMask_FileSize );
+    if( rcGet == osl::FileBase::E_None &&
+        aTreeFileItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None &&
+        aFileStatus.isValid( FileStatusMask_FileSize ) )
+    {
+        sal_uInt64 ret, len = aFileStatus.getFileSize();
+        char* s = new char[ int(len) ];  // the buffer to hold the installed files
+        osl::File aFile( aTreeFileURL );
+        aFile.open( OpenFlag_Read );
+        aFile.read( s, len, ret );
+        aFile.close();
+
+        XML_Parser parser = XML_ParserCreate( 0 );
+        int parsed = XML_Parse( parser, s, int( len ), true );
+
+        if( parsed == 0 )
+        {
+            XML_Error nError = XML_GetErrorCode( parser );
+            o_rHelpProcessingErrorInfo.m_eErrorClass = HELPPROCESSING_XMLPARSING_ERROR;
+            o_rHelpProcessingErrorInfo.m_aErrorMsg = rtl::OUString::createFromAscii( XML_ErrorString( nError ) );;
+            o_rHelpProcessingErrorInfo.m_aXMLParsingFile = aTreeFileURL;
+            // CRAHSES!!! o_rHelpProcessingErrorInfo.m_nXMLParsingLine = XML_GetCurrentLineNumber( parser );
+            bSuccess = false;
+        }
+
+        XML_ParserFree( parser );
+        delete[] s;
+    }
+
+    return bSuccess;
+}
+

Propchange: openoffice/branches/l10n/main/l10ntools/source/help/HelpLinker.cxx
------------------------------------------------------------------------------
    svn:executable = *

Added: openoffice/branches/l10n/main/l10ntools/source/help/compilehelp.hxx
URL: http://svn.apache.org/viewvc/openoffice/branches/l10n/main/l10ntools/source/help/compilehelp.hxx?rev=1437973&view=auto
==============================================================================
--- openoffice/branches/l10n/main/l10ntools/source/help/compilehelp.hxx (added)
+++ openoffice/branches/l10n/main/l10ntools/source/help/compilehelp.hxx Thu Jan 24 12:21:38 2013
@@ -0,0 +1,75 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+
+
+#ifndef COMPILE_HXX
+#define COMPILE_HXX
+
+#include "sal/types.h"
+
+#if defined(HELPLINKER_DLLIMPLEMENTATION)
+#define HELPLINKER_DLLPUBLIC  SAL_DLLPUBLIC_EXPORT
+#else
+#define HELPLINKER_DLLPUBLIC  SAL_DLLPUBLIC_IMPORT
+#endif
+#define HELPLINKER_DLLPRIVATE SAL_DLLPRIVATE
+
+
+//#include <helplinkerdllapi.h>
+#include <rtl/ustring.hxx>
+
+enum HelpProcessingErrorClass
+{
+	HELPPROCESSING_NO_ERROR,
+	HELPPROCESSING_GENERAL_ERROR,		// Missing files, options etc.
+	HELPPROCESSING_INTERNAL_ERROR,		// Unexpected problems
+	HELPPROCESSING_XMLPARSING_ERROR		// Errors thrown by libxml
+};
+
+struct HelpProcessingErrorInfo
+{
+	HelpProcessingErrorClass		m_eErrorClass;
+	rtl::OUString					m_aErrorMsg;
+	rtl::OUString					m_aXMLParsingFile;
+	sal_Int32						m_nXMLParsingLine;
+
+	HelpProcessingErrorInfo( void )
+		: m_eErrorClass( HELPPROCESSING_NO_ERROR )
+		, m_nXMLParsingLine( -1 )
+	{}
+
+	HelpProcessingErrorInfo& operator=( const struct HelpProcessingException& e );
+};
+
+
+// Returns true in case of success, false in case of error
+HELPLINKER_DLLPUBLIC bool compileExtensionHelp
+(
+ 	const rtl::OUString& aOfficeHelpPath,
+	const rtl::OUString& aExtensionName,
+	const rtl::OUString& aExtensionLanguageRoot,
+	sal_Int32 nXhpFileCount, const rtl::OUString* pXhpFiles,
+    const rtl::OUString& aDestination,
+	HelpProcessingErrorInfo& o_rHelpProcessingErrorInfo
+);
+
+#endif

Propchange: openoffice/branches/l10n/main/l10ntools/source/help/compilehelp.hxx
------------------------------------------------------------------------------
    svn:executable = *

Added: openoffice/branches/l10n/main/l10ntools/source/help/helplinker.pmk
URL: http://svn.apache.org/viewvc/openoffice/branches/l10n/main/l10ntools/source/help/helplinker.pmk?rev=1437973&view=auto
==============================================================================
--- openoffice/branches/l10n/main/l10ntools/source/help/helplinker.pmk (added)
+++ openoffice/branches/l10n/main/l10ntools/source/help/helplinker.pmk Thu Jan 24 12:21:38 2013
@@ -0,0 +1,27 @@
+#**************************************************************
+#  
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#  
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+#  
+#**************************************************************
+
+
+
+# define HELPLINKER_DLLIMPLEMENTATION (see @ inc/xmlhelp/helplinkerdllapi.h)
+CDEFS += -DHELPLINKER_DLLIMPLEMENTATION
+
+VISIBILITY_HIDDEN=TRUE

Propchange: openoffice/branches/l10n/main/l10ntools/source/help/helplinker.pmk
------------------------------------------------------------------------------
    svn:executable = *

Added: openoffice/branches/l10n/main/l10ntools/source/help/makefile.mk
URL: http://svn.apache.org/viewvc/openoffice/branches/l10n/main/l10ntools/source/help/makefile.mk?rev=1437973&view=auto
==============================================================================
--- openoffice/branches/l10n/main/l10ntools/source/help/makefile.mk (added)
+++ openoffice/branches/l10n/main/l10ntools/source/help/makefile.mk Thu Jan 24 12:21:38 2013
@@ -0,0 +1,108 @@
+#**************************************************************
+#  
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#  
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+#  
+#**************************************************************
+
+
+
+PRJ		= ..$/..
+PRJNAME = l10ntools
+TARGET  = HelpLinker
+LIBBASENAME = helplinker
+PACKAGE = com$/sun$/star$/help
+TARGETTYPE=CUI
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : helplinker.pmk
+ 
+.IF "$(SYSTEM_LIBXSLT)" == "YES"
+CFLAGS+= $(LIBXSLT_CFLAGS)
+.ELSE
+LIBXSLTINCDIR=external$/libxslt
+CFLAGS+= -I$(SOLARINCDIR)$/$(LIBXSLTINCDIR)
+.ENDIF
+
+.IF "$(SYSTEM_EXPAT)" == "YES"
+CFLAGS+=-DSYSTEM_EXPAT
+.ENDIF
+
+OBJFILES=\
+        $(OBJ)$/HelpLinker.obj \
+        $(OBJ)$/HelpCompiler.obj
+SLOFILES=\
+        $(SLO)$/HelpLinker.obj \
+        $(SLO)$/HelpCompiler.obj
+
+EXCEPTIONSFILES=\
+        $(OBJ)$/HelpLinker.obj \
+        $(OBJ)$/HelpCompiler.obj \
+        $(SLO)$/HelpLinker.obj \
+        $(SLO)$/HelpCompiler.obj
+.IF "$(OS)" == "MACOSX" && "$(CPU)" == "P" && "$(COM)" == "GCC"
+# There appears to be a GCC 4.0.1 optimization error causing _file:good() to
+# report true right before the call to writeOut at HelpLinker.cxx:1.12 l. 954
+# but out.good() to report false right at the start of writeOut at
+# HelpLinker.cxx:1.12 l. 537:
+NOOPTFILES=\
+        $(OBJ)$/HelpLinker.obj \
+        $(SLO)$/HelpLinker.obj
+.ENDIF
+
+APP1TARGET= $(TARGET)
+APP1OBJS=\
+      $(OBJ)$/HelpLinker.obj \
+      $(OBJ)$/HelpCompiler.obj
+
+APP1STDLIBS+=$(SALLIB) $(XSLTLIB) $(EXPATASCII3RDLIB)
+
+SHL1TARGET	=$(LIBBASENAME)$(DLLPOSTFIX)
+SHL1LIBS=	$(SLB)$/$(TARGET).lib
+SHL1IMPLIB	=i$(LIBBASENAME)
+SHL1DEF		=$(MISC)$/$(SHL1TARGET).def
+SHL1STDLIBS =$(SALLIB) $(XSLTLIB) $(EXPATASCII3RDLIB)
+SHL1USE_EXPORTS	=ordinal
+
+DEF1NAME	=$(SHL1TARGET) 
+DEFLIB1NAME	=$(TARGET)
+
+JAVAFILES = \
+	HelpIndexerTool.java			        \
+	HelpFileDocument.java
+
+
+JAVACLASSFILES = \
+	$(CLASSDIR)$/$(PACKAGE)$/HelpIndexerTool.class			        \
+	$(CLASSDIR)$/$(PACKAGE)$/HelpFileDocument.class
+
+.IF "$(SYSTEM_LUCENE)" == "YES"
+EXTRAJARFILES += $(LUCENE_CORE_JAR) $(LUCENE_ANALYZERS_JAR)
+.ELSE
+JARFILES += lucene-core-2.9.4-dev.jar lucene-analyzers-2.9.4-dev.jar
+.ENDIF
+JAVAFILES = $(subst,$(CLASSDIR)$/$(PACKAGE)$/, $(subst,.class,.java $(JAVACLASSFILES)))
+
+JARCLASSDIRS	   = $(PACKAGE)/*
+JARTARGET	       = HelpIndexerTool.jar
+JARCOMPRESS        = TRUE 
+ 
+# --- Targets ------------------------------------------------------
+
+.INCLUDE :  target.mk

Propchange: openoffice/branches/l10n/main/l10ntools/source/help/makefile.mk
------------------------------------------------------------------------------
    svn:executable = *

Added: openoffice/branches/l10n/main/l10ntools/source/helpex.cxx
URL: http://svn.apache.org/viewvc/openoffice/branches/l10n/main/l10ntools/source/helpex.cxx?rev=1437973&view=auto
==============================================================================
--- openoffice/branches/l10n/main/l10ntools/source/helpex.cxx (added)
+++ openoffice/branches/l10n/main/l10ntools/source/helpex.cxx Thu Jan 24 12:21:38 2013
@@ -0,0 +1,286 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+#include <stdlib.h>
+
+// local includes
+#include "helpmerge.hxx"
+
+// defines to parse command line
+#define STATE_NON  		        0x0001
+#define STATE_INPUT		        0x0002
+#define STATE_OUTPUT	        0x0003
+#define STATE_PRJ		        0x0004
+#define STATE_ROOT		        0x0005
+#define STATE_SDFFILE	        0x0006
+#define STATE_ERRORLOG	        0x0007
+#define STATE_BREAKHELP	        0x0008
+#define STATE_UNMERGE	        0x0009
+#define STATE_UTF8		        0x000A
+#define STATE_LANGUAGES	        0x000B
+#define STATE_FORCE_LANGUAGES   0x000C 
+#define STATE_OUTPUTX           0xfe
+#define STATE_OUTPUTY           0xff
+
+// set of global variables
+ByteString sInputFile;
+sal_Bool bEnableExport;
+sal_Bool bMergeMode;
+sal_Bool bErrorLog;
+sal_Bool bUTF8;
+ByteString sPrj;
+ByteString sPrjRoot;
+ByteString sOutputFile;
+ByteString sOutputFileX;
+ByteString sOutputFileY;
+ByteString sSDFFile;
+
+/*****************************************************************************/
+sal_Bool ParseCommandLine( int argc, char* argv[])
+/*****************************************************************************/
+{
+	bEnableExport = sal_False;
+	bMergeMode = sal_False;
+	bErrorLog = sal_True;
+	bUTF8 = sal_True;
+	sPrj = "";
+	sPrjRoot = "";
+    Export::sLanguages = "";
+    Export::sForcedLanguages = "";
+
+	sal_uInt16 nState = STATE_NON;
+	sal_Bool bInput = sal_False;
+
+	// parse command line
+	for( int i = 1; i < argc; i++ ) {
+		if ( ByteString( argv[ i ]).ToUpperAscii() == "-I" ) {
+			nState = STATE_INPUT; // next tokens specifies source files
+		}
+		else if ( ByteString( argv[ i ]).ToUpperAscii()  == "-O" ) {
+			nState = STATE_OUTPUT; // next token specifies the dest file
+		}
+		else if ( ByteString( argv[ i ]).ToUpperAscii()  == "-X" ) {
+			nState = STATE_OUTPUTX; // next token specifies the dest file
+		}
+		else if ( ByteString( argv[ i ]).ToUpperAscii()  == "-Y" ) {
+			nState = STATE_OUTPUTY; // next token specifies the dest file
+		}
+		else if ( ByteString( argv[ i ]).ToUpperAscii() == "-P" ) {
+			nState = STATE_PRJ; // next token specifies the cur. project
+		}
+ 		else if ( ByteString( argv[ i ]).ToUpperAscii() == "-LF" ) {
+			nState = STATE_FORCE_LANGUAGES; 
+		}
+       
+		else if ( ByteString( argv[ i ]).ToUpperAscii() == "-R" ) {
+			nState = STATE_ROOT; // next token specifies path to project root
+		}
+		else if ( ByteString( argv[ i ]).ToUpperAscii() == "-M" ) {
+			nState = STATE_SDFFILE; // next token specifies the merge database
+		}
+		else if ( ByteString( argv[ i ]).ToUpperAscii() == "-E" ) {
+			nState = STATE_ERRORLOG;
+			bErrorLog = sal_False;
+		}
+        else if ( ByteString( argv[ i ]).ToUpperAscii() == "-UTF8" ) {
+			nState = STATE_UTF8;
+			bUTF8 = sal_True;
+		}
+		else if ( ByteString( argv[ i ]).ToUpperAscii() == "-NOUTF8" ) {
+			nState = STATE_UTF8;
+			bUTF8 = sal_False;
+		}
+		else if ( ByteString( argv[ i ]).ToUpperAscii() == "-L" ) {
+			nState = STATE_LANGUAGES;
+		}
+		else {
+			switch ( nState ) {
+				case STATE_NON: {
+					return sal_False;	// no valid command line
+				}
+				//break;
+				case STATE_INPUT: {
+					sInputFile = argv[ i ];
+					bInput = sal_True; // source file found
+				}
+				break;
+				case STATE_OUTPUT: {
+					sOutputFile = argv[ i ]; // the dest. file
+				}
+                break;
+				case STATE_OUTPUTX: {
+					sOutputFileX = argv[ i ]; // the dest. file
+				}
+                break;
+				case STATE_OUTPUTY: {
+					sOutputFileY = argv[ i ]; // the dest. file
+				}
+				break;
+				case STATE_PRJ: {
+					sPrj = argv[ i ];
+//					sPrj.ToLowerAscii(); // the project
+				}
+				break;
+				case STATE_ROOT: {
+					sPrjRoot = argv[ i ]; // path to project root
+				}
+				break;
+				case STATE_SDFFILE: {
+					sSDFFile = argv[ i ];
+					bMergeMode = sal_True; // activate merge mode, cause merge database found
+				}
+				break;
+				case STATE_LANGUAGES: {
+					Export::sLanguages = argv[ i ];
+				}
+                case STATE_FORCE_LANGUAGES:{
+                    Export::sForcedLanguages = argv[ i ];
+                }
+				break;
+			}
+		}
+	}
+
+	if ( bInput ) {
+		// command line is valid
+		bEnableExport = sal_True;
+		return sal_True;
+	}
+
+	// command line is not valid
+	return sal_False;
+}
+
+
+/*****************************************************************************/
+void Help()
+/*****************************************************************************/
+{
+	fprintf( stdout, "Syntax: HELPEX[-p Prj][-r PrjRoot]-i FileIn ( -o FileOut | -x path -y relfile )[-m DataBase][-e][-b][-u][-L l1,l2,...] -LF l1,l2 \n" );
+	fprintf( stdout, " Prj:      Project\n" );
+	fprintf( stdout, " PrjRoot:  Path to project root (..\\.. etc.)\n" );
+	fprintf( stdout, " FileIn:   Source file (*.lng)\n" );
+	fprintf( stdout, " FileOut:  Destination file (*.*)\n" );
+	fprintf( stdout, " DataBase: Mergedata (*.sdf)\n" );
+	fprintf( stdout, " -L: Restrict the handled languages. l1,l2,... are elements of (en-US,fr,de...)\n" );
+	fprintf( stdout, "     A fallback language can be defined like this: l1=f1.\n" );
+	fprintf( stdout, "     f1, f2,... are also elements of (en-US,fr,de...)\n" );
+	fprintf( stdout, "     Example: -L fr=en-US\n" );
+	fprintf( stdout, "              Restriction to fr, en-US will be fallback for fr\n" );
+	fprintf( stdout, " -LF: Force the creation of that languages\n" );
+
+}
+
+/*****************************************************************************/
+#ifndef TESTDRIVER
+
+#if defined(UNX) || defined(OS2)
+int main( int argc, char *argv[] )
+#else
+int _cdecl main( int argc, char *argv[] )
+#endif
+/*****************************************************************************/
+{
+
+    if ( !ParseCommandLine( argc, argv )) {
+		Help();
+		return 1;
+	}
+	//sal_uInt32 startfull = Export::startMessure();
+
+    bool hasInputList = sInputFile.GetBuffer()[0]=='@';
+//    printf("x = %s , y = %s , o = %s\n", sOutputFileX.GetBuffer(),  sOutputFileY.GetBuffer() , sOutputFile.GetBuffer() ); 
+    bool hasNoError = true;
+	
+    if ( sOutputFile.Len() ){                                               // Merge single file ?
+		//printf("DBG: Inputfile = %s\n",sInputFile.GetBuffer());
+		HelpParser aParser( sInputFile, bUTF8 , false );
+		
+		if ( bMergeMode )
+		{
+			
+			//sal_uInt64 startreadloc = Export::startMessure();
+			MergeDataFile aMergeDataFile( sSDFFile, sInputFile , sal_False, RTL_TEXTENCODING_MS_1252 ); 
+		    //MergeDataFile aMergeDataFile( sSDFFile, sInputFile , sal_False, RTL_TEXTENCODING_MS_1252, false ); 
+            //Export::stopMessure( ByteString("read localize.sdf") , startreadloc );
+
+			hasNoError = aParser.Merge( sSDFFile, sOutputFile , Export::sLanguages , aMergeDataFile );
+		}
+		else
+			hasNoError = aParser.CreateSDF( sOutputFile, sPrj, sPrjRoot, sInputFile, new XMLFile( '0' ), "help" );
+	}else if ( sOutputFileX.Len() && sOutputFileY.Len() && hasInputList ) {  // Merge multiple files ?
+		if ( bMergeMode ){
+            
+            ifstream aFStream( sInputFile.Copy( 1 , sInputFile.Len() ).GetBuffer() , ios::in );
+                                                                                                                  
+            if( !aFStream ){
+                cerr << "ERROR: - helpex - Can't open the file " << sInputFile.Copy( 1 , sInputFile.Len() ).GetBuffer() << "\n";
+                exit(-1);
+            }
+        
+            vector<ByteString> filelist;
+            rtl::OStringBuffer filename;
+            sal_Char aChar;
+            while( aFStream.get( aChar ) )
+            {
+                if( aChar == ' ' || aChar == '\n')
+                    filelist.push_back( ByteString( filename.makeStringAndClear().getStr() ) );
+                else
+                    filename.append( aChar );
+            }
+            if( filename.getLength() > 0 ) 
+                filelist.push_back( ByteString ( filename.makeStringAndClear().getStr() ) );
+	        
+            aFStream.close();
+            ByteString sHelpFile(""); // dummy
+            //MergeDataFile aMergeDataFile( sSDFFile, sHelpFile , sal_False, RTL_TEXTENCODING_MS_1252, false );
+            MergeDataFile aMergeDataFile( sSDFFile, sHelpFile , sal_False, RTL_TEXTENCODING_MS_1252 ); 
+
+	        //aMergeDataFile.Dump();
+            std::vector<ByteString> aLanguages;
+	        HelpParser::parse_languages( aLanguages , aMergeDataFile );
+			
+			bool bCreateDir = true;
+	        for( vector<ByteString>::iterator pos = filelist.begin() ; pos != filelist.end() ; ++pos )
+            {
+                sHelpFile = *pos;   
+                cout << ".";cout.flush();
+		        
+                HelpParser aParser( sHelpFile , bUTF8 , true );
+                hasNoError = aParser.Merge( sSDFFile , sOutputFileX , sOutputFileY , true , aLanguages , aMergeDataFile , bCreateDir );
+				bCreateDir = false;
+            }
+        }
+    } else
+        cerr << "helpex ERROR: Wrong input parameters!\n";
+    
+	//Export::stopMessure( ByteString("full cycle") , startfull );
+	if( hasNoError )
+        return 0;
+    else 
+        return 1;
+}
+#endif

Propchange: openoffice/branches/l10n/main/l10ntools/source/helpex.cxx
------------------------------------------------------------------------------
    svn:executable = *