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();
51 xmlNodePtr
LibXmlTreeWalker::currentNode()
53 return m_pCurrentNode
;
56 //======================================================
58 BasicCodeTagger::BasicCodeTagger( xmlDocPtr rootDoc
)
60 if ( rootDoc
== NULL
)
62 m_pDocument
= rootDoc
;
63 m_pXmlTreeWalker
= NULL
;
64 m_Highlighter
.initialize( HIGHLIGHT_BASIC
);
65 m_bTaggingCompleted
= false;
69 BasicCodeTagger::~BasicCodeTagger()
71 if ( m_pXmlTreeWalker
!= NULL
)
72 delete m_pXmlTreeWalker
;
74 //!Gathers all the <bascode> tag nodes from xml tree.
76 * Assumes m_pDocument is valid. Handles m_pXmlTreeWalker and m_BasicCodeContainerTags members.
78 void BasicCodeTagger::getBasicCodeContainerNodes()
80 xmlNodePtr currentNode
;
82 m_BasicCodeContainerTags
.clear();
84 if ( m_pXmlTreeWalker
!= NULL
)
85 delete m_pXmlTreeWalker
;
86 m_pXmlTreeWalker
= new LibXmlTreeWalker( m_pDocument
);
88 currentNode
= m_pXmlTreeWalker
->currentNode();
89 if ( !( xmlStrcmp( currentNode
->name
, (const xmlChar
*) "bascode" ) ) )
91 m_BasicCodeContainerTags
.push_back( currentNode
); //it goes to the end of the list
93 while ( !m_pXmlTreeWalker
->end() )
95 m_pXmlTreeWalker
->nextNode();
96 if ( !( xmlStrcmp( m_pXmlTreeWalker
->currentNode()->name
, (const xmlChar
*) "bascode" ) ) )
98 m_BasicCodeContainerTags
.push_back( m_pXmlTreeWalker
->currentNode() ); //it goes to the end of the list
99 m_pXmlTreeWalker
->ignoreCurrNodesChildren();
104 //! Extracts Basic Codes containted in <bascode> tags.
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.
109 void BasicCodeTagger::tagBasCodeParagraphs()
112 xmlNodePtr currBascodeNode
;
113 xmlNodePtr currParagraph
;
114 while ( !m_BasicCodeContainerTags
.empty() )
116 currBascodeNode
= m_BasicCodeContainerTags
.front();
117 currParagraph
= currBascodeNode
->xmlChildrenNode
; //first <paragraph>
118 while ( currParagraph
!= NULL
)
120 tagParagraph( currParagraph
);
121 currParagraph
=currParagraph
->next
;
123 m_BasicCodeContainerTags
.pop_front(); //next element
127 //! Used by tagBasCodeParagraphs(). It does the work on the current paragraph containing Basic code.
128 void BasicCodeTagger::tagParagraph( xmlNodePtr paragraph
)
130 //1. get paragraph text
131 xmlChar
* codeSnippet
;
132 codeSnippet
= xmlNodeListGetString( m_pDocument
, paragraph
->xmlChildrenNode
, 1 );
133 if ( codeSnippet
== NULL
)
135 return; //no text, nothing more to do here
137 //2. delete every child from paragraph (except attributes)
138 xmlNodePtr curNode
= paragraph
->xmlChildrenNode
;
140 while ( curNode
!= NULL
)
142 sibling
= curNode
->next
;
143 xmlUnlinkNode( curNode
);
144 xmlFreeNode( curNode
);
148 //3. create new paragraph content
149 OUString
strLine( reinterpret_cast<const sal_Char
*>(codeSnippet
),
150 strlen(reinterpret_cast<const char*>(codeSnippet
)),
151 RTL_TEXTENCODING_UTF8
);
152 m_Highlighter
.notifyChange ( 0, 0, &strLine
, 1 );
153 HighlightPortions portions
;
154 m_Highlighter
.getHighlightPortions( 0, strLine
, portions
);
155 for ( size_t i
=0; i
<portions
.size(); i
++ )
157 HighlightPortion
& r
= portions
[i
];
158 OString
sToken(OUStringToOString(strLine
.copy(r
.nBegin
, r
.nEnd
-r
.nBegin
), RTL_TEXTENCODING_UTF8
));
159 xmlNodePtr text
= xmlNewText((const xmlChar
*)sToken
.getStr());
160 if ( r
.tokenType
!= TT_WHITESPACE
)
162 xmlChar
* typeStr
= getTypeString( r
.tokenType
);
163 curNode
= xmlNewTextChild( paragraph
, 0, (xmlChar
*)"item", 0 );
164 xmlNewProp( curNode
, (xmlChar
*)"type", typeStr
);
165 xmlAddChild( curNode
, text
);
169 xmlAddChild( paragraph
, text
);
171 xmlFree( codeSnippet
);
174 //! Manages tagging process.
176 * This is the "main" function of BasicCodeTagger.
178 void BasicCodeTagger::tagBasicCodes()
180 if ( m_bTaggingCompleted
)
182 //gather <bascode> nodes
185 getBasicCodeContainerNodes();
187 catch (TaggerException
&ex
)
189 std::cout
<< "BasCodeTagger error occured. Error code:" << ex
<< std::endl
;
192 //tag basic code paragraphs in <bascode> tag
193 tagBasCodeParagraphs();
194 m_bTaggingCompleted
= true;
197 //! Converts SyntaxHighlighter's TokenTypes enum to a type string for <item type=... >
198 xmlChar
* BasicCodeTagger::getTypeString( TokenTypes tokenType
)
240 return xmlCharStrdup( str
);
243 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */