20#include "amiproparser.h"
24#include <tqstringlist.h>
25#include <tqtextstream.h>
27const float AmiPro::LS_Single = -1;
28const float AmiPro::LS_OneAndHalf = -1.5;
29const float AmiPro::LS_Double = -2;
32static TQString AmiProUnescape(
const TQString& str )
36 for(
unsigned i=0; i< str.length(); i++ )
53 result.truncate( result.length() - 1 );
61 result.truncate( result.length() - 1 );
69 result.truncate( result.length() - 1 );
79 result.truncate( result.length() - 1 );
80 result.append(
'\'' );
85 result.truncate( result.length() - 1 );
86 result.append( TQChar(str[i+2].unicode() + 0x40 ) );
92 if( str[i+1] ==
'\\' )
94 result.truncate( result.length() - 1 );
95 result.append( TQChar(str[i+2].unicode() | 0x80 ) );
106AmiProParser::AmiProParser()
112AmiProParser::~AmiProParser()
116bool AmiProParser::setResult(
int result )
119 return m_result == OK;
122void AmiProParser::setListener( AmiProListener *listener )
124 m_listener = listener;
127bool AmiProParser::process(
const TQString& filename )
132 TQFile in( filename );
133 if( !in.open( IO_ReadOnly))
134 return setResult( FileError );
137 stream.setDevice( &in );
140 line = stream.readLine();
141 if( line !=
"[ver]" )
142 return setResult( InvalidFormat );
145 line = stream.readLine();
146 int format_version = line.toInt();
150 if( format_version != 4 )
151 return setResult( InvalidFormat );
154 m_currentFormat = AmiProFormat();
155 m_formatList.clear();
157 m_currentSection =
"";
164 line = stream.readLine();
165 if( line.isNull() )
break;
167 TQString old_section = m_currentSection;
168 bool enter_new_section =
false;
171 if( !line.isEmpty() )
if( line[0] ==
'[' )
173 enter_new_section =
true;
174 m_currentSection =
"";
175 for(
unsigned i=1; i<line.length(); i++ )
176 if( line[i] ==
']' )
break;
177 else m_currentSection += line[i];
181 if( enter_new_section && ( old_section ==
"tag" ) )
188 if( enter_new_section && ( old_section ==
"edoc" ) )
190 parseParagraph( lines.join(
" ") );
195 if( !enter_new_section && ( old_section ==
"tag" ) )
197 lines.append( line );
201 if( !enter_new_section && ( old_section ==
"edoc" ) )
205 parseParagraph( lines );
208 lines.append( line );
212 if( enter_new_section && ( m_currentSection ==
"tag" ) )
218 if( enter_new_section && ( m_currentSection ==
"edoc" ) )
220 processOpenDocument();
227 if( lines.count() > 0 ) parseParagraph( lines.join(
" " ) );
229 processCloseDocument();
234bool AmiProParser::processOpenDocument()
236 if( m_listener )
return m_listener->doOpenDocument();
240bool AmiProParser::processCloseDocument()
243 return m_listener->doCloseDocument();
247bool AmiProParser::parseParagraph(
const TQStringList& lines )
250 m_formatList.clear();
251 m_layout = AmiProLayout();
254 TQString partext =
"";
255 for(
unsigned i=0; i<lines.count(); i++ )
256 if( lines[i][0] ==
'>' )
break;
257 else partext.append( lines[i] +
"\n" );
259 TQChar ch = partext[partext.length()-1];
260 while( ( ch ==
'\n' ) || ( ch ==
'\r' ) )
262 partext.remove( partext.length()-1, 1 );
263 ch = partext[partext.length()-1];
267 TQString text = AmiProUnescape( partext );
270 m_layout.applyStyle( findStyle(
"Body Text" ) );
272 for(
unsigned i=0; i<text.length(); i++ )
280 for( i++; (i < text.length()) &&
281 (text[i] !=
'>'); i++) tag.append( text[i] );
291 for( i++; (i < partext.length()) && (partext[i] !=
'@'); i++)
292 styleName += partext[i];
293 m_layout.name = styleName;
294 AmiProStyle style = findStyle( styleName );
295 m_currentFormat.applyStyle( style );
296 m_formatList.append( m_currentFormat );
297 m_layout.applyStyle( style );
306 for(
unsigned j=0; j<m_formatList.count(); j++ )
309 AmiProFormat& format = m_formatList[j];
310 if( j < m_formatList.count()-1 )
312 AmiProFormat& nextformat = m_formatList[j+1];
313 nextpos = nextformat.pos;
315 else nextpos = m_text.length();
316 format.len = nextpos - format.pos;
320 return m_listener->doParagraph( m_text, m_formatList, m_layout );
325bool AmiProParser::parseStyle(
const TQStringList& lines )
329 style.name = AmiProUnescape( lines[0].stripWhiteSpace() );
330 if( style.name.isEmpty() )
return true;
333 if( lines[2].stripWhiteSpace() !=
"[fnt]" )
return true;
334 style.fontFamily = lines[3].stripWhiteSpace();
335 style.fontSize = lines[4].stripWhiteSpace().toFloat() / 20.0;
337 unsigned color = lines[5].stripWhiteSpace().toUInt();
338 style.fontColor.setRgb( color&255, (color>>8)&255, (color>>16)&255);
340 unsigned flag = lines[6].stripWhiteSpace().toUInt();
341 style.bold = flag & 1;
342 style.italic = flag & 2;
343 style.underline = flag & 4;
344 style.word_underline = flag & 8;
345 style.double_underline = flag & 64;
348 if( lines[7].stripWhiteSpace() !=
"[algn]" )
return true;
349 unsigned align_flag = lines[8].stripWhiteSpace().toUInt();
350 if( align_flag & 1 ) style.align = TQt::AlignLeft;
351 if( align_flag & 2 ) style.align = TQt::AlignRight;
352 if( align_flag & 4 ) style.align = TQt::AlignCenter;
353 if( align_flag & 8 ) style.align = TQt::AlignJustify;
356 if( lines[13].stripWhiteSpace() !=
"[spc]" )
return true;
357 unsigned ls_flag = lines[14].stripWhiteSpace().toUInt();
358 if( ls_flag & 1 ) style.linespace = AmiPro::LS_Single;
359 if( ls_flag & 2 ) style.linespace = AmiPro::LS_OneAndHalf;
360 if( ls_flag & 4 ) style.linespace = AmiPro::LS_Double;
362 style.linespace = lines[15].stripWhiteSpace().toFloat() / 20.0;
363 style.spaceBefore = lines[17].stripWhiteSpace().toFloat() / 20.0;
364 style.spaceAfter = lines[18].stripWhiteSpace().toFloat() / 20.0;
366 m_styleList.append( style );
370 if( style.name.left( 7 ) !=
"Style #" )
372 return m_listener->doDefineStyle( style );
376AmiProStyle AmiProParser::findStyle(
const TQString& name )
378 AmiProStyleList::iterator it;
379 for( it=m_styleList.begin(); it!=m_styleList.end(); ++it )
381 AmiProStyle& style = *it;
382 if( style.name == name )
385 return AmiProStyle();
388bool AmiProParser::handleTag(
const TQString& tag )
392 m_text.append(
">" );
396 m_text.append(
"[" );
401 m_currentFormat.bold =
true;
402 m_currentFormat.pos = m_text.length();
403 m_formatList.append( m_currentFormat );
409 m_currentFormat.bold =
false;
410 m_currentFormat.pos = m_text.length();
411 m_formatList.append( m_currentFormat );
417 m_currentFormat.italic =
true;
418 m_currentFormat.pos = m_text.length();
419 m_formatList.append( m_currentFormat );
425 m_currentFormat.italic =
false;
426 m_currentFormat.pos = m_text.length();
427 m_formatList.append( m_currentFormat );
433 m_currentFormat.underline =
true;
434 m_currentFormat.pos = m_text.length();
435 m_formatList.append( m_currentFormat );
441 m_currentFormat.underline =
false;
442 m_currentFormat.pos = m_text.length();
443 m_formatList.append( m_currentFormat );
449 m_currentFormat.double_underline =
true;
450 m_currentFormat.pos = m_text.length();
451 m_formatList.append( m_currentFormat );
457 m_currentFormat.double_underline =
false;
458 m_currentFormat.pos = m_text.length();
459 m_formatList.append( m_currentFormat );
465 m_currentFormat.word_underline =
true;
466 m_currentFormat.pos = m_text.length();
467 m_formatList.append( m_currentFormat );
473 m_currentFormat.word_underline =
false;
474 m_currentFormat.pos = m_text.length();
475 m_formatList.append( m_currentFormat );
481 m_currentFormat.superscript =
true;
482 m_currentFormat.pos = m_text.length();
483 m_formatList.append( m_currentFormat );
489 m_currentFormat.superscript =
false;
490 m_currentFormat.pos = m_text.length();
491 m_formatList.append( m_currentFormat );
497 m_currentFormat.subscript =
true;
498 m_currentFormat.pos = m_text.length();
499 m_formatList.append( m_currentFormat );
505 m_currentFormat.subscript =
false;
506 m_currentFormat.pos = m_text.length();
507 m_formatList.append( m_currentFormat );
513 m_currentFormat.strikethrough =
true;
514 m_currentFormat.pos = m_text.length();
515 m_formatList.append( m_currentFormat );
521 m_currentFormat.strikethrough =
false;
522 m_currentFormat.pos = m_text.length();
523 m_formatList.append( m_currentFormat );
528 m_layout.align = TQt::AlignLeft;
532 m_layout.align = TQt::AlignRight;
536 m_layout.align = TQt::AlignCenter;
540 m_layout.align = TQt::AlignJustify;
543 if( tag.left( 3 ) ==
":S+" )
545 float ls = tag.right( tag.length() - 3 ).toFloat();
546 m_layout.linespace = (ls == -1) ? AmiPro::LS_Single :
547 (ls == -2) ? AmiPro::LS_OneAndHalf :
548 (ls == -3) ? AmiPro::LS_Double : ls / 20.0;
552 if( tag.left( 2 ) ==
":f" )
554 TQString fontdesc = tag.right( tag.length()-2 );
555 TQStringList desc = TQStringList::split(
",", fontdesc );
556 if( desc.count() > 0 ) m_currentFormat.fontSize = desc[0].toFloat() / 20.0;
557 if( desc.count() > 1 )
559 TQString fontFamily = desc[1];
560 if( fontFamily[0].isDigit() ) fontFamily.remove( 0, 1 );
561 m_currentFormat.fontFamily = fontFamily;
563 if( desc.count() > 4 )
565 unsigned red = desc[2].toUInt();
566 unsigned green = desc[3].toUInt();
567 unsigned blue = desc[4].toUInt();
568 m_currentFormat.fontColor.setRgb( red, green, blue );
570 m_formatList.append( m_currentFormat );
577AmiProFormat::AmiProFormat()
580 bold = italic = underline =
581 word_underline = double_underline =
582 subscript = superscript = strikethrough =
false;
585 fontColor = TQt::black;
588void AmiProFormat::assign(
const AmiProFormat& f )
594 underline = f.underline;
595 word_underline = f.word_underline;
596 double_underline = f.double_underline;
597 subscript = f.subscript;
598 superscript = f.superscript;
599 strikethrough = f.strikethrough;
600 fontFamily = f.fontFamily;
601 fontSize = f.fontSize;
602 fontColor = f.fontColor;
605AmiProFormat::AmiProFormat(
const AmiProFormat& f )
610AmiProFormat& AmiProFormat::operator=(
const AmiProFormat& f )
616void AmiProFormat::applyStyle(
const AmiProStyle& style )
618 fontFamily = style.fontFamily;
619 fontSize = style.fontSize;
620 fontColor = style.fontColor;
622 italic = style.italic;
623 underline = style.underline;
624 word_underline = style.word_underline;
625 double_underline = style.double_underline;
626 subscript = style.subscript;
627 superscript = style.superscript;
628 strikethrough = style.strikethrough;
632AmiProLayout::AmiProLayout()
637 fontColor = TQt::black;
638 bold = italic = underline =
639 word_underline = double_underline =
640 subscript = superscript = strikethrough =
false;
641 align = TQt::AlignLeft;
642 linespace = AmiPro::LS_Single;
643 spaceBefore = spaceAfter = 0;
646void AmiProLayout::assign(
const AmiProLayout &l )
649 fontFamily = l.fontFamily;
650 fontSize = l.fontSize;
651 fontColor = l.fontColor;
654 underline = l.underline;
655 word_underline = l.word_underline;
656 double_underline = l.double_underline;
657 subscript = l.subscript;
658 superscript = l.superscript;
659 strikethrough = l.strikethrough;
661 linespace = l.linespace;
662 spaceBefore = l.spaceBefore;
663 spaceAfter = l.spaceAfter;
666AmiProLayout::AmiProLayout(
const AmiProLayout& l )
671AmiProLayout& AmiProLayout::operator=(
const AmiProLayout& l )
677void AmiProLayout::applyStyle(
const AmiProStyle& style )
679 fontFamily = style.fontFamily;
680 fontSize = style.fontSize;
681 fontColor = style.fontColor;
683 italic = style.italic;
684 underline = style.underline;
685 word_underline = style.word_underline;
686 double_underline = style.double_underline;
687 subscript = style.subscript;
688 superscript = style.superscript;
689 strikethrough = style.strikethrough;
691 linespace = style.linespace;
692 spaceBefore = style.spaceBefore;
693 spaceAfter = style.spaceAfter;
697AmiProStyle::AmiProStyle()
702 fontColor = TQt::black;
703 bold = italic = underline =
704 word_underline = double_underline =
705 subscript = superscript = strikethrough =
false;
706 linespace = AmiPro::LS_Single;
707 spaceBefore = spaceAfter = 0;
710void AmiProStyle::assign(
const AmiProStyle& s )
713 fontFamily = s.fontFamily;
714 fontSize = s.fontSize;
715 fontColor = s.fontColor;
718 underline = s.underline;
719 word_underline = s.word_underline;
720 double_underline = s.double_underline;
721 subscript = s.subscript;
722 superscript = s.superscript;
723 strikethrough = s.strikethrough;
725 linespace = s.linespace;
726 spaceBefore = s.spaceBefore;
727 spaceAfter = s.spaceAfter;
730AmiProStyle::AmiProStyle(
const AmiProStyle& s )
735AmiProStyle& AmiProStyle::operator=(
const AmiProStyle& s )
742AmiProListener::AmiProListener()
746AmiProListener::~AmiProListener()
750#define DO_TRUE_DEFINITION(string) \
751 bool AmiProListener::string \
756DO_TRUE_DEFINITION(doOpenDocument())
757DO_TRUE_DEFINITION(doCloseDocument())
758DO_TRUE_DEFINITION(doDefineStyle(const AmiProStyle& style))
759DO_TRUE_DEFINITION(doParagraph(const TQString& text, AmiProFormatList formatList,