summaryrefslogtreecommitdiff
path: root/helpcompiler/source
diff options
context:
space:
mode:
authorDávid Vastag <davewwpublic@gmail.com>2013-02-11 16:49:40 +0100
committerAndras Timar <atimar@suse.com>2013-02-13 10:19:14 +0100
commitd06c698b799e0e4ceaf3a3760c9589fe29dc29a9 (patch)
tree3bfb9ee128aa58f2dd0d436dba1ffe04df933bc4 /helpcompiler/source
parent089a9afc95acf7eeff242369fcddee0f5337df62 (diff)
Basic code syntaxhighlighting added to LibreOffice help
Change-Id: Id47172d0386e7aa28d82178f04b5f626f0c441fe
Diffstat (limited to 'helpcompiler/source')
-rw-r--r--helpcompiler/source/BasCodeTagger.cxx251
-rw-r--r--helpcompiler/source/HelpCompiler.cxx42
-rw-r--r--helpcompiler/source/HelpLinker.cxx2
3 files changed, 289 insertions, 6 deletions
diff --git a/helpcompiler/source/BasCodeTagger.cxx b/helpcompiler/source/BasCodeTagger.cxx
new file mode 100644
index 000000000000..858db824bbb1
--- /dev/null
+++ b/helpcompiler/source/BasCodeTagger.cxx
@@ -0,0 +1,251 @@
+#include <helpcompiler/BasCodeTagger.hxx>
+
+LibXmlTreeWalker::LibXmlTreeWalker( xmlDocPtr doc )
+{
+ if ( doc == NULL )
+ throw BasicCodeTagger::NULL_DOCUMENT;
+ m_pCurrentNode = xmlDocGetRootElement( doc );
+ if ( m_pCurrentNode == NULL )
+ throw BasicCodeTagger::EMPTY_DOCUMENT;
+ else if ( m_pCurrentNode->xmlChildrenNode != NULL )
+ m_Queue.push_back( m_pCurrentNode->xmlChildrenNode );
+ nextNode();
+}
+
+void LibXmlTreeWalker::nextNode()
+{
+
+ //next node
+ if ( m_pCurrentNode->next == NULL )
+ {
+ m_pCurrentNode = m_Queue.front();
+ m_Queue.pop_front();
+ }
+ else
+ m_pCurrentNode = m_pCurrentNode->next;
+ //queue chiledren if they exist
+ if ( m_pCurrentNode->xmlChildrenNode != NULL )
+ m_Queue.push_back( m_pCurrentNode->xmlChildrenNode );
+}
+
+void LibXmlTreeWalker::ignoreCurrNodesChildren()
+{
+ if ( m_pCurrentNode->xmlChildrenNode != NULL )
+ m_Queue.pop_back();
+}
+
+bool LibXmlTreeWalker::end()
+{
+ return m_pCurrentNode->next == NULL && m_Queue.empty();
+}
+
+xmlNodePtr LibXmlTreeWalker::currentNode()
+{
+ return m_pCurrentNode;
+}
+
+//======================================================
+
+BasicCodeTagger::BasicCodeTagger( xmlDocPtr rootDoc )
+{
+ if ( rootDoc == NULL )
+ throw NULL_DOCUMENT;
+ m_pDocument = rootDoc;
+ m_pXmlTreeWalker = NULL;
+ m_Highlighter.initialize( HIGHLIGHT_BASIC );
+ m_bTaggingCompleted = false;
+
+}
+
+BasicCodeTagger::~BasicCodeTagger()
+{
+ if ( m_pXmlTreeWalker != NULL )
+ delete m_pXmlTreeWalker;
+}
+//!Gathers all the <bascode> tag nodes from xml tree.
+/*!
+ * Assumes m_pDocument is valid. Handles m_pXmlTreeWalker and m_BasicCodeContainerTags members.
+ */
+void BasicCodeTagger::getBasicCodeContainerNodes()
+{
+ xmlNodePtr currentNode;
+
+ m_BasicCodeContainerTags.clear();
+
+ if ( m_pXmlTreeWalker != NULL )
+ delete m_pXmlTreeWalker;
+ m_pXmlTreeWalker = new LibXmlTreeWalker( m_pDocument );
+
+ currentNode = m_pXmlTreeWalker->currentNode();
+ if ( !( xmlStrcmp( currentNode->name, (const xmlChar*) "bascode" ) ) )
+ { //Found <bascode>
+ m_BasicCodeContainerTags.push_back( currentNode ); //it goes to the end of the list
+ }
+ while ( !m_pXmlTreeWalker->end() )
+ {
+ m_pXmlTreeWalker->nextNode();
+ if ( !( xmlStrcmp( m_pXmlTreeWalker->currentNode()->name, (const xmlChar*) "bascode" ) ) )
+ { //Found <bascode>
+ m_BasicCodeContainerTags.push_back( m_pXmlTreeWalker->currentNode() ); //it goes to the end of the list
+ m_pXmlTreeWalker->ignoreCurrNodesChildren();
+ }
+ }
+}
+
+//! Extracts Basic Codes containted in <bascode> tags.
+/*!
+ * For each <bascode> this method iterates trough it's <paragraph> tags and "inserts" <item> tags according
+ * to the Basic code syntax found in that paragraph.
+ */
+void BasicCodeTagger::tagBasCodeParagraphs()
+{
+ //helper variables
+ xmlNodePtr currBascodeNode;
+ xmlNodePtr currParagraph;
+ while ( !m_BasicCodeContainerTags.empty() )
+ {
+ currBascodeNode = m_BasicCodeContainerTags.front();
+ currParagraph = currBascodeNode->xmlChildrenNode; //first <paragraph>
+ while ( currParagraph != NULL )
+ {
+ tagParagraph( currParagraph );
+ currParagraph=currParagraph->next;
+ }
+ m_BasicCodeContainerTags.pop_front(); //next element
+ }
+}
+
+//! Used by tagBasCodeParagraphs(). It does the work on the current paragraph containing Basic code.
+void BasicCodeTagger::tagParagraph( xmlNodePtr paragraph )
+{
+ //1. get paragraph text
+ xmlChar* codeSnippet;
+ codeSnippet = xmlNodeListGetString( m_pDocument, paragraph->xmlChildrenNode, 1 );
+ if ( codeSnippet == NULL )
+ {
+ return; //no text, nothing more to do here
+ }
+ //2. delete every child from paragraph (except attributes)
+ xmlNodePtr curNode = paragraph->xmlChildrenNode;
+ xmlNodePtr sibling;
+ while ( curNode != NULL )
+ {
+ sibling = curNode->next;
+ xmlUnlinkNode( curNode );
+ xmlFreeNode( curNode );
+ curNode = sibling;
+ }
+
+ //3. create new paragraph content
+ String strLine(
+ OUString(
+ reinterpret_cast<const sal_Char*>(codeSnippet),
+ strlen(
+ reinterpret_cast<const char*>(codeSnippet)
+ ),
+ RTL_TEXTENCODING_UTF8
+ )
+ ) ;
+ m_Highlighter.notifyChange ( 0, 0, &strLine, 1 );
+ HighlightPortions portions;
+ m_Highlighter.getHighlightPortions( 0, strLine, portions );
+ xmlChar* subStr;
+ xmlChar* typeStr;
+ xmlNodePtr text;
+ for ( size_t i=0; i<portions.size(); i++ )
+ {
+ HighlightPortion& r = portions[i];
+ subStr = xmlStrsub( codeSnippet, r.nBegin, r.nEnd-r.nBegin );
+ text = xmlNewText( subStr );
+ if ( r.tokenType != TT_WHITESPACE )
+ {
+ typeStr = getTypeString( r.tokenType );
+ curNode = xmlNewTextChild( paragraph, 0, (xmlChar*)"item", 0 );
+ xmlNewProp( curNode, (xmlChar*)"type", typeStr );
+ xmlAddChild( curNode, text );
+ xmlFree( typeStr );
+ }
+ else
+ xmlAddChild( paragraph, text );
+ xmlFree( subStr );
+ }
+ xmlFree( codeSnippet );
+}
+
+//! Manages tagging process.
+/*!
+ * This is the "main" function of BasicCodeTagger.
+ */
+void BasicCodeTagger::tagBasicCodes()
+{
+ if ( m_bTaggingCompleted )
+ return;
+ //gather <bascode> nodes
+ try
+ {
+ getBasicCodeContainerNodes();
+ }
+ catch (TaggerException ex)
+ {
+ std::cout << "Some kind of error occured." << std::endl;
+ }
+
+ //tag basic code paragraphs in <bascode> tag
+ tagBasCodeParagraphs();
+ m_bTaggingCompleted = true;
+}
+
+//! Converts SyntaxHighlighter's TokenTypes enum to a type string for <item type=... >
+xmlChar* BasicCodeTagger::getTypeString( TokenTypes tokenType )
+{
+ const char* str;
+ switch ( tokenType )
+ {
+ case TT_UNKNOWN :
+ str = "unknown";
+ break;
+ case TT_IDENTIFIER :
+ str = "identifier";
+ break;
+ case TT_WHITESPACE :
+ str = "whitespace";
+ break;
+ case TT_NUMBER :
+ str = "number";
+ break;
+ case TT_STRING :
+ str = "string";
+ break;
+ case TT_EOL :
+ str = "eol";
+ break;
+ case TT_COMMENT :
+ str = "comment";
+ break;
+ case TT_ERROR :
+ str = "error";
+ break;
+ case TT_OPERATOR :
+ str = "operator";
+ break;
+ case TT_KEYWORDS :
+ str = "keywords";
+ break;
+ case TT_PARAMETER :
+ str = "parameter";
+ break;
+ default :
+ str = "unknown";
+ break;
+ }
+ return xmlCharStrdup( str );
+}
+
+//! Saves the current xml DOM to file with the provided libxml2 encoding string in an unformatted way.
+void BasicCodeTagger::saveTreeToFile( const std::string& filePath, const std::string& encoding )
+{
+ //saveDocument
+ int ret = xmlSaveFormatFileEnc( filePath.c_str(), m_pDocument, encoding.c_str(), 0 );
+ if ( ret == -1 )
+ throw FILE_WRITING;
+}
diff --git a/helpcompiler/source/HelpCompiler.cxx b/helpcompiler/source/HelpCompiler.cxx
index 74b29f59ba52..8c6f66b49977 100644
--- a/helpcompiler/source/HelpCompiler.cxx
+++ b/helpcompiler/source/HelpCompiler.cxx
@@ -19,6 +19,7 @@
#include <helpcompiler/HelpCompiler.hxx>
+#include <helpcompiler/BasCodeTagger.hxx>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -36,25 +37,55 @@ static void impl_sleep( sal_uInt32 nSec )
osl::Thread::wait( aTime );
}
-
HelpCompiler::HelpCompiler(StreamTable &in_streamTable, const fs::path &in_inputFile,
- const fs::path &in_src, const fs::path &in_resEmbStylesheet,
+ const fs::path &in_src, const fs::path &in_zipdir, const fs::path &in_resEmbStylesheet,
const std::string &in_module, const std::string &in_lang, bool in_bExtensionMode)
: streamTable(in_streamTable), inputFile(in_inputFile),
- src(in_src), module(in_module), lang(in_lang), resEmbStylesheet(in_resEmbStylesheet),
+ src(in_src), zipdir(in_zipdir), module(in_module), lang(in_lang), resEmbStylesheet(in_resEmbStylesheet),
bExtensionMode( in_bExtensionMode )
{
xmlKeepBlanksDefaultValue = 0;
char* guitmp = getenv("GUI");
if (guitmp)
{
- // WTF?
gui = (strcmp(guitmp, "UNX") ? gui : "UNIX");
gui = (strcmp(guitmp, "MAC") ? gui : "MAC");
gui = (strcmp(guitmp, "WNT") ? gui : "WIN");
}
}
+void HelpCompiler::sourceDocumentPreWorks( xmlDocPtr doc, const fs::path &filePath )
+{
+ if ( doc )
+ {
+ if ( module == "sbasic" )
+ {
+ try
+ {
+ BasicCodeTagger bct( doc );
+ bct.tagBasicCodes();
+ }
+ catch ( BasicCodeTagger::TaggerException ex )
+ {
+ if ( ex != BasicCodeTagger::EMPTY_DOCUMENT )
+ throw;
+ }
+ //save document in ziptmp<modul>_<lang>/text directory
+ //1. construct new path
+ const std::string& pth = filePath.native_file_string();
+ std::string sourceNativeXhpPath = pth.substr( pth.rfind( lang+"/text/" ) ).substr( lang.length() );
+ std::string xhpFileName = sourceNativeXhpPath.substr( sourceNativeXhpPath.rfind( '/' ) + 1 );
+ sourceNativeXhpPath = sourceNativeXhpPath.substr( 0, sourceNativeXhpPath.rfind( '/' ) );
+ //2. save xml doc with the new path
+ // -create directory hierachy
+ fs::create_directory( fs::path( zipdir.native_file_string() + sourceNativeXhpPath, fs::native ) );
+ // -save document
+ if ( -1 == xmlSaveFormatFileEnc( (zipdir.native_file_string() + sourceNativeXhpPath + '/' + xhpFileName).c_str(), doc, "utf-8", 0 ) )
+ throw BasicCodeTagger::FILE_WRITING;
+ }
+ }
+}
+
xmlDocPtr HelpCompiler::getSourceDocument(const fs::path &filePath)
{
static const char *params[4 + 1];
@@ -68,6 +99,7 @@ xmlDocPtr HelpCompiler::getSourceDocument(const fs::path &filePath)
impl_sleep( 3 );
res = xmlParseFile(filePath.native_file_string().c_str());
}
+ sourceDocumentPreWorks( res, filePath );
}
else
{
@@ -93,7 +125,7 @@ xmlDocPtr HelpCompiler::getSourceDocument(const fs::path &filePath)
impl_sleep( 3 );
doc = xmlParseFile(filePath.native_file_string().c_str());
}
-
+ sourceDocumentPreWorks( doc, filePath );
//???res = xmlParseFile(filePath.native_file_string().c_str());
res = xsltApplyStylesheet(cur, doc, params);
diff --git a/helpcompiler/source/HelpLinker.cxx b/helpcompiler/source/HelpLinker.cxx
index 62d364583f2a..4bbe2b6bd23e 100644
--- a/helpcompiler/source/HelpLinker.cxx
+++ b/helpcompiler/source/HelpLinker.cxx
@@ -377,7 +377,7 @@ void HelpLinker::link() throw( HelpProcessingException )
xhpFile = fs::path(xhpFileName, fs::native);
}
- HelpCompiler hc( streamTable, xhpFile, langsourceRoot,
+ HelpCompiler hc( streamTable, xhpFile, langsourceRoot, zipdir,
embeddStylesheet, module, lang, bExtensionMode );
HCDBG(std::cerr << "before compile of " << xhpFileName << std::endl);