summaryrefslogtreecommitdiff
path: root/helpcompiler/source/BasCodeTagger.cxx
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/BasCodeTagger.cxx
parent089a9afc95acf7eeff242369fcddee0f5337df62 (diff)
Basic code syntaxhighlighting added to LibreOffice help
Change-Id: Id47172d0386e7aa28d82178f04b5f626f0c441fe
Diffstat (limited to 'helpcompiler/source/BasCodeTagger.cxx')
-rw-r--r--helpcompiler/source/BasCodeTagger.cxx251
1 files changed, 251 insertions, 0 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;
+}