1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <BasCodeTagger.hxx>
12 LibXmlTreeWalker::LibXmlTreeWalker( xmlDocPtr doc
)
15 throw BasicCodeTagger::NULL_DOCUMENT
;
16 m_pCurrentNode
= xmlDocGetRootElement( doc
);
17 if ( m_pCurrentNode
== NULL
)
18 throw BasicCodeTagger::EMPTY_DOCUMENT
;
19 else if ( m_pCurrentNode
->xmlChildrenNode
!= NULL
)
20 m_Queue
.push_back( m_pCurrentNode
->xmlChildrenNode
);
24 void LibXmlTreeWalker::nextNode()
28 if ( m_pCurrentNode
->next
== NULL
)
30 m_pCurrentNode
= m_Queue
.front();
34 m_pCurrentNode
= m_pCurrentNode
->next
;
35 //queue chiledren if they exist
36 if ( m_pCurrentNode
->xmlChildrenNode
!= NULL
)
37 m_Queue
.push_back( m_pCurrentNode
->xmlChildrenNode
);
40 void LibXmlTreeWalker::ignoreCurrNodesChildren()
42 if ( m_pCurrentNode
->xmlChildrenNode
!= NULL
)
46 bool LibXmlTreeWalker::end()
48 return m_pCurrentNode
->next
== NULL
&& m_Queue
.empty();
54 BasicCodeTagger::BasicCodeTagger( xmlDocPtr rootDoc
):
55 m_Highlighter(HIGHLIGHT_BASIC
)
57 if ( rootDoc
== NULL
)
59 m_pDocument
= rootDoc
;
60 m_pXmlTreeWalker
= NULL
;
61 m_bTaggingCompleted
= false;
65 BasicCodeTagger::~BasicCodeTagger()
67 if ( m_pXmlTreeWalker
!= NULL
)
68 delete m_pXmlTreeWalker
;
70 //!Gathers all the <bascode> tag nodes from xml tree.
72 * Assumes m_pDocument is valid. Handles m_pXmlTreeWalker and m_BasicCodeContainerTags members.
74 void BasicCodeTagger::getBasicCodeContainerNodes()
76 xmlNodePtr currentNode
;
78 m_BasicCodeContainerTags
.clear();
80 if ( m_pXmlTreeWalker
!= NULL
)
81 delete m_pXmlTreeWalker
;
82 m_pXmlTreeWalker
= new LibXmlTreeWalker( m_pDocument
);
84 currentNode
= m_pXmlTreeWalker
->currentNode();
85 if ( !( xmlStrcmp( currentNode
->name
, reinterpret_cast<const xmlChar
*>("bascode") ) ) )
87 m_BasicCodeContainerTags
.push_back( currentNode
); //it goes to the end of the list
89 while ( !m_pXmlTreeWalker
->end() )
91 m_pXmlTreeWalker
->nextNode();
92 if ( !( xmlStrcmp( m_pXmlTreeWalker
->currentNode()->name
, reinterpret_cast<const xmlChar
*>("bascode") ) ) )
94 m_BasicCodeContainerTags
.push_back( m_pXmlTreeWalker
->currentNode() ); //it goes to the end of the list
95 m_pXmlTreeWalker
->ignoreCurrNodesChildren();
100 //! Extracts Basic Codes contained in <bascode> tags.
102 * For each <bascode> this method iterates through it's <paragraph> tags and "inserts" <item> tags according
103 * to the Basic code syntax found in that paragraph.
105 void BasicCodeTagger::tagBasCodeParagraphs()
108 xmlNodePtr currBascodeNode
;
109 xmlNodePtr currParagraph
;
110 while ( !m_BasicCodeContainerTags
.empty() )
112 currBascodeNode
= m_BasicCodeContainerTags
.front();
113 currParagraph
= currBascodeNode
->xmlChildrenNode
; //first <paragraph>
114 while ( currParagraph
!= NULL
)
116 tagParagraph( currParagraph
);
117 currParagraph
=currParagraph
->next
;
119 m_BasicCodeContainerTags
.pop_front(); //next element
123 //! Used by tagBasCodeParagraphs(). It does the work on the current paragraph containing Basic code.
124 void BasicCodeTagger::tagParagraph( xmlNodePtr paragraph
)
126 //1. get paragraph text
127 xmlChar
* codeSnippet
;
128 codeSnippet
= xmlNodeListGetString( m_pDocument
, paragraph
->xmlChildrenNode
, 1 );
129 if ( codeSnippet
== NULL
)
131 return; //no text, nothing more to do here
133 //2. delete every child from paragraph (except attributes)
134 xmlNodePtr curNode
= paragraph
->xmlChildrenNode
;
136 while ( curNode
!= NULL
)
138 sibling
= curNode
->next
;
139 xmlUnlinkNode( curNode
);
140 xmlFreeNode( curNode
);
144 //3. create new paragraph content
145 OUString
strLine( reinterpret_cast<const sal_Char
*>(codeSnippet
),
146 strlen(reinterpret_cast<const char*>(codeSnippet
)),
147 RTL_TEXTENCODING_UTF8
);
148 std::vector
<HighlightPortion
> portions
;
149 m_Highlighter
.getHighlightPortions( strLine
, portions
);
150 for (std::vector
<HighlightPortion
>::iterator
i(portions
.begin());
151 i
!= portions
.end(); ++i
)
153 OString
sToken(OUStringToOString(strLine
.copy(i
->nBegin
, i
->nEnd
-i
->nBegin
), RTL_TEXTENCODING_UTF8
));
154 xmlNodePtr text
= xmlNewText(reinterpret_cast<const xmlChar
*>(sToken
.getStr()));
155 if ( i
->tokenType
!= TT_WHITESPACE
)
157 xmlChar
* typeStr
= getTypeString( i
->tokenType
);
158 curNode
= xmlNewTextChild( paragraph
, 0, reinterpret_cast<xmlChar
const *>("item"), 0 );
159 xmlNewProp( curNode
, reinterpret_cast<xmlChar
const *>("type"), typeStr
);
160 xmlAddChild( curNode
, text
);
164 xmlAddChild( paragraph
, text
);
166 xmlFree( codeSnippet
);
169 //! Manages tagging process.
171 * This is the "main" function of BasicCodeTagger.
173 void BasicCodeTagger::tagBasicCodes()
175 if ( m_bTaggingCompleted
)
177 //gather <bascode> nodes
180 getBasicCodeContainerNodes();
182 catch (TaggerException
&ex
)
184 std::cout
<< "BasCodeTagger error occurred. Error code:" << ex
<< std::endl
;
187 //tag basic code paragraphs in <bascode> tag
188 tagBasCodeParagraphs();
189 m_bTaggingCompleted
= true;
192 //! Converts SyntaxHighlighter's TokenTypes enum to a type string for <item type=... >
193 xmlChar
* BasicCodeTagger::getTypeString( TokenTypes tokenType
)
235 return xmlCharStrdup( str
);
238 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */