1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "oox/vml/vmltextboxcontext.hxx"
29 
30 namespace oox {
31 namespace vml {
32 
33 // ============================================================================
34 
35 using ::oox::core::ContextHandler2;
36 using ::oox::core::ContextHandler2Helper;
37 using ::oox::core::ContextHandlerRef;
38 using ::rtl::OUString;
39 
40 // ============================================================================
41 
42 TextPortionContext::TextPortionContext( ContextHandler2Helper& rParent,
43         TextBox& rTextBox, const TextFontModel& rParentFont,
44         sal_Int32 nElement, const AttributeList& rAttribs ) :
45     ContextHandler2( rParent ),
46     mrTextBox( rTextBox ),
47     maFont( rParentFont ),
48     mnInitialPortions( rTextBox.getPortionCount() )
49 {
50     switch( nElement )
51     {
52         case XML_font:
53             maFont.moName = rAttribs.getXString( XML_face );
54             maFont.moColor = rAttribs.getXString( XML_color );
55             maFont.monSize = rAttribs.getInteger( XML_size );
56         break;
57         case XML_u:
58             OSL_ENSURE( !maFont.monUnderline, "TextPortionContext::TextPortionContext - nested <u> elements" );
59             maFont.monUnderline = (rAttribs.getToken( XML_class, XML_TOKEN_INVALID ) == XML_font4) ? XML_double : XML_single;
60         break;
61         case XML_sub:
62         case XML_sup:
63             OSL_ENSURE( !maFont.monEscapement, "TextPortionContext::TextPortionContext - nested <sub> or <sup> elements" );
64             maFont.monEscapement = nElement;
65         break;
66         case XML_b:
67             OSL_ENSURE( !maFont.mobBold, "TextPortionContext::TextPortionContext - nested <b> elements" );
68             maFont.mobBold = true;
69         break;
70         case XML_i:
71             OSL_ENSURE( !maFont.mobItalic, "TextPortionContext::TextPortionContext - nested <i> elements" );
72             maFont.mobItalic = true;
73         break;
74         case XML_s:
75             OSL_ENSURE( !maFont.mobStrikeout, "TextPortionContext::TextPortionContext - nested <s> elements" );
76             maFont.mobStrikeout = true;
77         break;
78         case XML_span:
79         break;
80         default:
81             OSL_ENSURE( false, "TextPortionContext::TextPortionContext - unknown element" );
82     }
83 }
84 
85 ContextHandlerRef TextPortionContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
86 {
87     OSL_ENSURE( nElement != XML_font, "TextPortionContext::onCreateContext - nested <font> elements" );
88     return new TextPortionContext( *this, mrTextBox, maFont, nElement, rAttribs );
89 }
90 
91 void TextPortionContext::onCharacters( const OUString& rChars )
92 {
93     switch( getCurrentElement() )
94     {
95         case XML_span:
96             // replace all NBSP characters with SP
97             mrTextBox.appendPortion( maFont, rChars.replace( 0xA0, ' ' ) );
98         break;
99         default:
100             mrTextBox.appendPortion( maFont, rChars );
101     }
102 }
103 
104 void TextPortionContext::onEndElement()
105 {
106     /*  A child element without own child elements may contain a single space
107         character, for example:
108 
109           <div>
110             <font><i>abc</i></font>
111             <font> </font>
112             <font><b>def</b></font>
113           </div>
114 
115         represents the italic text 'abc', an unformatted space character, and
116         the bold text 'def'. Unfortunately, the XML parser skips the space
117         character without issuing a 'characters' event. The class member
118         'mnInitialPortions' contains the number of text portions existing when
119         this context has been constructed. If no text has been added in the
120         meantime, the space character has to be added manually.
121      */
122     if( mrTextBox.getPortionCount() == mnInitialPortions )
123         mrTextBox.appendPortion( maFont, OUString( sal_Unicode( ' ' ) ) );
124 }
125 
126 // ============================================================================
127 
128 TextBoxContext::TextBoxContext( ContextHandler2Helper& rParent, TextBox& rTextBox, const AttributeList& /*rAttribs*/ ) :
129     ContextHandler2( rParent ),
130     mrTextBox( rTextBox )
131 {
132 }
133 
134 ContextHandlerRef TextBoxContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
135 {
136     switch( getCurrentElement() )
137     {
138         case VML_TOKEN( textbox ):
139             if( nElement == XML_div ) return this;
140         break;
141         case XML_div:
142             if( nElement == XML_font ) return new TextPortionContext( *this, mrTextBox, TextFontModel(), nElement, rAttribs );
143         break;
144     }
145     return 0;
146 }
147 
148 // ============================================================================
149 
150 } // namespace vml
151 } // namespace oox
152