Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : */
9 :
10 : #include <BasCodeTagger.hxx>
11 :
12 0 : LibXmlTreeWalker::LibXmlTreeWalker( xmlDocPtr doc )
13 : {
14 0 : if ( doc == NULL )
15 0 : throw BasicCodeTagger::NULL_DOCUMENT;
16 0 : m_pCurrentNode = xmlDocGetRootElement( doc );
17 0 : if ( m_pCurrentNode == NULL )
18 0 : throw BasicCodeTagger::EMPTY_DOCUMENT;
19 0 : else if ( m_pCurrentNode->xmlChildrenNode != NULL )
20 0 : m_Queue.push_back( m_pCurrentNode->xmlChildrenNode );
21 0 : nextNode();
22 0 : }
23 :
24 0 : void LibXmlTreeWalker::nextNode()
25 : {
26 :
27 : //next node
28 0 : if ( m_pCurrentNode->next == NULL )
29 : {
30 0 : m_pCurrentNode = m_Queue.front();
31 0 : m_Queue.pop_front();
32 : }
33 : else
34 0 : m_pCurrentNode = m_pCurrentNode->next;
35 : //queue chiledren if they exist
36 0 : if ( m_pCurrentNode->xmlChildrenNode != NULL )
37 0 : m_Queue.push_back( m_pCurrentNode->xmlChildrenNode );
38 0 : }
39 :
40 0 : void LibXmlTreeWalker::ignoreCurrNodesChildren()
41 : {
42 0 : if ( m_pCurrentNode->xmlChildrenNode != NULL )
43 0 : m_Queue.pop_back();
44 0 : }
45 :
46 0 : bool LibXmlTreeWalker::end()
47 : {
48 0 : return m_pCurrentNode->next == NULL && m_Queue.empty();
49 : }
50 :
51 0 : xmlNodePtr LibXmlTreeWalker::currentNode()
52 : {
53 0 : return m_pCurrentNode;
54 : }
55 :
56 :
57 :
58 0 : BasicCodeTagger::BasicCodeTagger( xmlDocPtr rootDoc ):
59 0 : m_Highlighter(HIGHLIGHT_BASIC)
60 : {
61 0 : if ( rootDoc == NULL )
62 0 : throw NULL_DOCUMENT;
63 0 : m_pDocument = rootDoc;
64 0 : m_pXmlTreeWalker = NULL;
65 0 : m_bTaggingCompleted = false;
66 :
67 0 : }
68 :
69 0 : BasicCodeTagger::~BasicCodeTagger()
70 : {
71 0 : if ( m_pXmlTreeWalker != NULL )
72 0 : delete m_pXmlTreeWalker;
73 0 : }
74 : //!Gathers all the <bascode> tag nodes from xml tree.
75 : /*!
76 : * Assumes m_pDocument is valid. Handles m_pXmlTreeWalker and m_BasicCodeContainerTags members.
77 : */
78 0 : void BasicCodeTagger::getBasicCodeContainerNodes()
79 : {
80 : xmlNodePtr currentNode;
81 :
82 0 : m_BasicCodeContainerTags.clear();
83 :
84 0 : if ( m_pXmlTreeWalker != NULL )
85 0 : delete m_pXmlTreeWalker;
86 0 : m_pXmlTreeWalker = new LibXmlTreeWalker( m_pDocument );
87 :
88 0 : currentNode = m_pXmlTreeWalker->currentNode();
89 0 : if ( !( xmlStrcmp( currentNode->name, (const xmlChar*) "bascode" ) ) )
90 : { //Found <bascode>
91 0 : m_BasicCodeContainerTags.push_back( currentNode ); //it goes to the end of the list
92 : }
93 0 : while ( !m_pXmlTreeWalker->end() )
94 : {
95 0 : m_pXmlTreeWalker->nextNode();
96 0 : if ( !( xmlStrcmp( m_pXmlTreeWalker->currentNode()->name, (const xmlChar*) "bascode" ) ) )
97 : { //Found <bascode>
98 0 : m_BasicCodeContainerTags.push_back( m_pXmlTreeWalker->currentNode() ); //it goes to the end of the list
99 0 : m_pXmlTreeWalker->ignoreCurrNodesChildren();
100 : }
101 : }
102 0 : }
103 :
104 : //! Extracts Basic Codes containted in <bascode> tags.
105 : /*!
106 : * For each <bascode> this method iterates trough it's <paragraph> tags and "inserts" <item> tags according
107 : * to the Basic code syntax found in that paragraph.
108 : */
109 0 : void BasicCodeTagger::tagBasCodeParagraphs()
110 : {
111 : //helper variables
112 : xmlNodePtr currBascodeNode;
113 : xmlNodePtr currParagraph;
114 0 : while ( !m_BasicCodeContainerTags.empty() )
115 : {
116 0 : currBascodeNode = m_BasicCodeContainerTags.front();
117 0 : currParagraph = currBascodeNode->xmlChildrenNode; //first <paragraph>
118 0 : while ( currParagraph != NULL )
119 : {
120 0 : tagParagraph( currParagraph );
121 0 : currParagraph=currParagraph->next;
122 : }
123 0 : m_BasicCodeContainerTags.pop_front(); //next element
124 : }
125 0 : }
126 :
127 : //! Used by tagBasCodeParagraphs(). It does the work on the current paragraph containing Basic code.
128 0 : void BasicCodeTagger::tagParagraph( xmlNodePtr paragraph )
129 : {
130 : //1. get paragraph text
131 : xmlChar* codeSnippet;
132 0 : codeSnippet = xmlNodeListGetString( m_pDocument, paragraph->xmlChildrenNode, 1 );
133 0 : if ( codeSnippet == NULL )
134 : {
135 0 : return; //no text, nothing more to do here
136 : }
137 : //2. delete every child from paragraph (except attributes)
138 0 : xmlNodePtr curNode = paragraph->xmlChildrenNode;
139 : xmlNodePtr sibling;
140 0 : while ( curNode != NULL )
141 : {
142 0 : sibling = curNode->next;
143 0 : xmlUnlinkNode( curNode );
144 0 : xmlFreeNode( curNode );
145 0 : curNode = sibling;
146 : }
147 :
148 : //3. create new paragraph content
149 : OUString strLine( reinterpret_cast<const sal_Char*>(codeSnippet),
150 0 : strlen(reinterpret_cast<const char*>(codeSnippet)),
151 0 : RTL_TEXTENCODING_UTF8 );
152 0 : std::vector<HighlightPortion> portions;
153 0 : m_Highlighter.getHighlightPortions( strLine, portions );
154 0 : for (std::vector<HighlightPortion>::iterator i(portions.begin());
155 0 : i != portions.end(); ++i)
156 : {
157 0 : OString sToken(OUStringToOString(strLine.copy(i->nBegin, i->nEnd-i->nBegin), RTL_TEXTENCODING_UTF8));
158 0 : xmlNodePtr text = xmlNewText((const xmlChar*)sToken.getStr());
159 0 : if ( i->tokenType != TT_WHITESPACE )
160 : {
161 0 : xmlChar* typeStr = getTypeString( i->tokenType );
162 0 : curNode = xmlNewTextChild( paragraph, 0, (xmlChar*)"item", 0 );
163 0 : xmlNewProp( curNode, (xmlChar*)"type", typeStr );
164 0 : xmlAddChild( curNode, text );
165 0 : xmlFree( typeStr );
166 : }
167 : else
168 0 : xmlAddChild( paragraph, text );
169 0 : }
170 0 : xmlFree( codeSnippet );
171 : }
172 :
173 : //! Manages tagging process.
174 : /*!
175 : * This is the "main" function of BasicCodeTagger.
176 : */
177 0 : void BasicCodeTagger::tagBasicCodes()
178 : {
179 0 : if ( m_bTaggingCompleted )
180 0 : return;
181 : //gather <bascode> nodes
182 : try
183 : {
184 0 : getBasicCodeContainerNodes();
185 : }
186 0 : catch (TaggerException &ex)
187 : {
188 0 : std::cout << "BasCodeTagger error occured. Error code:" << ex << std::endl;
189 : }
190 :
191 : //tag basic code paragraphs in <bascode> tag
192 0 : tagBasCodeParagraphs();
193 0 : m_bTaggingCompleted = true;
194 : }
195 :
196 : //! Converts SyntaxHighlighter's TokenTypes enum to a type string for <item type=... >
197 0 : xmlChar* BasicCodeTagger::getTypeString( TokenTypes tokenType )
198 : {
199 : const char* str;
200 0 : switch ( tokenType )
201 : {
202 : case TT_UNKNOWN :
203 0 : str = "unknown";
204 0 : break;
205 : case TT_IDENTIFIER :
206 0 : str = "identifier";
207 0 : break;
208 : case TT_WHITESPACE :
209 0 : str = "whitespace";
210 0 : break;
211 : case TT_NUMBER :
212 0 : str = "number";
213 0 : break;
214 : case TT_STRING :
215 0 : str = "string";
216 0 : break;
217 : case TT_EOL :
218 0 : str = "eol";
219 0 : break;
220 : case TT_COMMENT :
221 0 : str = "comment";
222 0 : break;
223 : case TT_ERROR :
224 0 : str = "error";
225 0 : break;
226 : case TT_OPERATOR :
227 0 : str = "operator";
228 0 : break;
229 : case TT_KEYWORDS :
230 0 : str = "keyword";
231 0 : break;
232 : case TT_PARAMETER :
233 0 : str = "parameter";
234 0 : break;
235 : default :
236 0 : str = "unknown";
237 0 : break;
238 : }
239 0 : return xmlCharStrdup( str );
240 0 : }
241 :
242 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|