filters

wmlparser.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002 Ariya Hidayat <ariyahidayat@yahoo.de>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include <tqstring.h>
21#include <tqxml.h>
22#include <tqfile.h>
23#include <tqvaluestack.h>
24
25#include <wmlparser.h>
26
27class WMLParseState
28{
29 public:
30 unsigned tableRow, tableCol;
31 WMLFormat currentFormat;
32 WMLFormatList formatList;
33 WMLLayout currentLayout;
34 WMLParseState();
35 WMLParseState( const WMLParseState& );
36 WMLParseState& operator=( const WMLParseState& );
37 void assign( const WMLParseState& );
38};
39
40WMLParseState::WMLParseState()
41{
42 tableRow = tableCol = 0;
43}
44
45WMLParseState::WMLParseState( const WMLParseState& state )
46{
47 assign( state );
48}
49
50WMLParseState& WMLParseState::operator=( const WMLParseState& state )
51{
52 assign( state );
53 return *this ;
54}
55
56void WMLParseState::assign( const WMLParseState& state )
57{
58 tableRow = state.tableRow;
59 tableCol = state.tableCol;
60 currentFormat = state.currentFormat;
61 formatList = state.formatList;
62 currentLayout = state.currentLayout;
63}
64
65// ContentHandler for use with the reader
66class WMLHandler: public TQXmlDefaultHandler
67{
68 public:
69
70 WMLHandler( WMLParser *parser ){ m_parser = parser; }
71
72 bool startDocument();
73 bool startElement( const TQString&, const TQString&, const TQString& ,
74 const TQXmlAttributes& );
75 bool endElement( const TQString&, const TQString&, const TQString& );
76 bool characters( const TQString& ch );
77
78 private:
79
80 WMLParser *m_parser;
81
82 bool m_inBlock;
83 TQString m_text;
84
85 bool m_inLink;
86 TQString m_link;
87 TQString m_href;
88
89 WMLParseState m_state;
90 TQValueStack<WMLParseState> m_stateStack;
91
92 bool flushParagraph();
93 void pushState();
94 void popState();
95};
96
97bool WMLHandler::startDocument()
98{
99 m_text = "";
100 m_inBlock = false;
101
102 m_link = "";
103 m_href = "";
104
105 return true;
106}
107
108bool WMLHandler::startElement( const TQString&, const TQString&,
109 const TQString& qName,
110 const TQXmlAttributes& attr )
111{
112 TQString tag = qName.lower();
113
114 if( tag == "wml" )
115 return m_parser->doOpenDocument();
116
117 if( tag == "card" )
118 {
119 m_state = WMLParseState();
120 TQString card_id = attr.value("id");
121 TQString card_title = attr.value("title");
122 return m_parser->doOpenCard( card_id, card_title );
123 }
124
125 if( tag == "p" )
126 {
127 m_state.currentLayout = WMLLayout();
128 m_inBlock = true;
129 if( m_state.currentFormat.bold ||
130 m_state.currentFormat.italic ||
131 m_state.currentFormat.underline ||
132 (m_state.currentFormat.fontsize != WMLFormat::Normal) )
133 m_state.formatList.append( m_state.currentFormat );
134
135 TQString align = attr.value("align").lower();
136 if( align == "right" )
137 m_state.currentLayout.align = WMLLayout::Right;
138 if( align == "center" )
139 m_state.currentLayout.align = WMLLayout::Center;
140
141 return true;
142 }
143
144 if(( tag == "b" ) || (tag == "strong") )
145 {
146 m_state.currentFormat.bold = true;
147 m_state.currentFormat.pos = m_text.length();
148 m_state.formatList.append( m_state.currentFormat );
149 return true;
150 }
151
152 if(( tag == "i" ) || (tag == "em") )
153 {
154 m_state.currentFormat.italic = true;
155 m_state.currentFormat.pos = m_text.length();
156 m_state.formatList.append( m_state.currentFormat );
157 return true;
158 }
159
160 if( tag == "u" )
161 {
162 m_state.currentFormat.underline = true;
163 m_state.currentFormat.pos = m_text.length();
164 m_state.formatList.append( m_state.currentFormat );
165 return true;
166 }
167
168 if( tag == "big" )
169 {
170 m_state.currentFormat.fontsize = WMLFormat::Big;
171 m_state.currentFormat.pos = m_text.length();
172 m_state.formatList.append( m_state.currentFormat );
173 return true;
174 }
175
176 if( tag == "small" )
177 {
178 m_state.currentFormat.fontsize = WMLFormat::Small;
179 m_state.currentFormat.pos = m_text.length();
180 m_state.formatList.append( m_state.currentFormat );
181 return true;
182 }
183
184 if( tag == "a" )
185 {
186 TQString href = attr.value("href");
187 if( !href.isEmpty() )
188 {
189 m_inBlock = false;
190 m_inLink = true;
191 m_state.currentFormat.link = "";
192 m_state.currentFormat.href = href;
193 m_state.currentFormat.pos = m_text.length();
194 m_state.currentFormat.len = 1;
195 m_text.append( "#" ); // inline char
196 return true;
197 }
198 }
199
200 // open new table
201 if( tag == "table" )
202 {
203 pushState();
204 return m_parser->doBeginTable();
205 }
206
207 // open table row
208 if( tag == "tr" )
209 {
210 m_state.tableRow++;
211 return true;
212 }
213
214 // open table cell, keep in sync with <p> above
215 if( tag == "td" )
216 {
217 m_state.tableCol++;
218 m_state.currentLayout = WMLLayout();
219 m_inBlock = true;
220 m_state.formatList.append( m_state.currentFormat );
221 return m_parser->doTableCell( m_state.tableRow, m_state.tableCol );
222 }
223
224 // unhandled element
225 return true;
226}
227
228bool WMLHandler::endElement( const TQString&, const TQString&,
229 const TQString& qName )
230{
231 TQString tag = qName.lower();
232
233 if( tag == "wml" )
234 return m_parser->doCloseDocument();
235
236 if( tag == "card" )
237 {
238 // forget </p> before </card> ?
239 m_inBlock = false;
240 if( !m_text.isEmpty() )
241 flushParagraph();
242 return m_parser->doCloseCard();
243 }
244
245 if( tag == "p" )
246 {
247 m_inBlock = false;
248 return flushParagraph();
249 }
250
251 if(( tag == "b" ) || (tag == "strong") )
252 {
253 m_state.currentFormat.bold = false;
254 m_state.currentFormat.pos = m_text.length();
255 m_state.formatList.append( m_state.currentFormat );
256 return true;
257 }
258
259 if(( tag == "i" ) || (tag == "em") )
260 {
261 m_state.currentFormat.italic = false;
262 m_state.currentFormat.pos = m_text.length();
263 m_state.formatList.append( m_state.currentFormat );
264 return true;
265 }
266
267 if( tag == "u" )
268 {
269 m_state.currentFormat.underline = false;
270 m_state.currentFormat.pos = m_text.length();
271 m_state.formatList.append( m_state.currentFormat );
272 return true;
273 }
274
275 if( tag == "big" )
276 {
277 m_state.currentFormat.fontsize = WMLFormat::Normal;
278 m_state.currentFormat.pos = m_text.length();
279 m_state.formatList.append( m_state.currentFormat );
280 return true;
281 }
282
283 if( tag == "small" )
284 {
285 m_state.currentFormat.fontsize = WMLFormat::Normal;
286 m_state.currentFormat.pos = m_text.length();
287 m_state.formatList.append( m_state.currentFormat );
288 return true;
289 }
290
291 if( tag == "a" )
292 {
293 m_inBlock = true;
294 m_inLink = false;
295 m_state.formatList.append( m_state.currentFormat );
296 return true;
297 }
298
299 // close table
300 if( tag == "table" )
301 {
302 popState();
303 return m_parser->doEndTable();
304 }
305
306 // close table row
307 if( tag == "tr" )
308 return true; //skip
309
310 // close table cell, like </p>
311 if( tag == "td" )
312 {
313 m_inBlock = false;
314 return flushParagraph();
315 }
316
317 // unhandled
318 return true;
319}
320
321bool WMLHandler::characters( const TQString& ch )
322{
323 if( m_inBlock )
324 m_text.append( ch );
325
326 if( m_inLink )
327 m_state.currentFormat.link.append( ch );
328
329 return true;
330}
331
332bool WMLHandler::flushParagraph()
333{
334 // calc length of each format tag
335 for( unsigned i=0; i<m_state.formatList.count(); i++ )
336 {
337 int nextpos;
338 WMLFormat& format = m_state.formatList[i];
339 if( i < m_state.formatList.count()-1 )
340 {
341 WMLFormat& nextformat = m_state.formatList[i+1];
342 nextpos = nextformat.pos;
343 }
344 else nextpos = m_text.length();
345 if( format.len <= 0 )
346 format.len = nextpos - format.pos;
347 }
348
349 bool result = m_parser->doParagraph( m_text, m_state.formatList, m_state.currentLayout );
350
351 // ready for next paragraph
352 m_text = "";
353 m_state.formatList.clear();
354 m_state.currentLayout = WMLLayout();
355
356 // m_state.currentFormat = WMLFormat();
357 // FIXME should we reset formatting ?
358
359 return result;
360}
361
362void WMLHandler::pushState()
363{
364 m_stateStack.push( m_state );
365}
366
367void WMLHandler::popState()
368{
369 if( !m_stateStack.isEmpty() )
370 m_state = m_stateStack.pop();
371}
372
373// formatting for the text
374WMLFormat::WMLFormat()
375{
376 pos = len = 0;
377 fontsize = Normal;
378 bold = italic = underline = false;
379 link = "";
380 href = "";
381}
382
383void WMLFormat::assign( const WMLFormat& f )
384{
385 pos = f.pos;
386 len = f.len;
387 bold = f.bold;
388 italic = f.italic;
389 underline = f.underline;
390 fontsize = f.fontsize;
391 link = f.link;
392 href= f.href;
393}
394
395WMLFormat::WMLFormat( const WMLFormat& f )
396{
397 assign( f );
398}
399
400WMLFormat& WMLFormat::operator=( const WMLFormat& f )
401{
402 assign( f );
403 return *this;
404}
405
406// paragraph layout info
407WMLLayout::WMLLayout()
408{
409 align = Left;
410}
411
412void WMLLayout::assign( const WMLLayout& l )
413{
414 align = l.align;
415}
416
417WMLLayout::WMLLayout( const WMLLayout& l )
418{
419 assign( l );
420}
421
422WMLLayout& WMLLayout::operator=( const WMLLayout& l )
423{
424 assign( l );
425 return *this;
426}
427
428// The basic WML parser
429void WMLParser::parse( const char* filename )
430{
431 TQFile f( filename );
432 TQXmlInputSource source( &f );
433 TQXmlSimpleReader reader;
434 WMLHandler handler( this );
435 reader.setContentHandler( &handler );
436 reader.parse( source );
437}
438
439bool WMLParser::doOpenDocument()
440{
441 return true;
442}
443
444bool WMLParser::doCloseDocument()
445{
446 return true;
447}
448
449bool WMLParser::doOpenCard( TQString, TQString )
450{
451 return true;
452}
453
454bool WMLParser::doCloseCard()
455{
456 return true;
457}
458
459bool WMLParser::doParagraph( TQString, WMLFormatList, WMLLayout )
460{
461 return true;
462}
463
464bool WMLParser::doBeginTable()
465{
466 return true;
467}
468
469bool WMLParser::doEndTable()
470{
471 return true;
472}
473
474bool WMLParser::doTableCell( unsigned, unsigned )
475{
476 return true;
477}