1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package org.openoffice.xmerge.converter.xml.sxw.pocketword;
25 
26 import org.openoffice.xmerge.converter.xml.TextStyle;
27 
28 import org.openoffice.xmerge.util.EndianConverter;
29 
30 import org.openoffice.xmerge.util.ColourConverter;
31 
32 import java.io.ByteArrayOutputStream;
33 import java.io.IOException;
34 
35 /**
36  * This class represents a portion of text with a particular formatting style.
37  * The style may differ from the default style of the paragraph of which it
38  * is part.
39  *
40  * @author  Mark Murnane
41  * @version 1.1
42  */
43 class ParagraphTextSegment implements PocketWordConstants {
44 
45     private String    pText;
46     private TextStyle pStyle;
47 
48 
49     /**
50      * <p>Initialise a new <code>ParagraphTextSegment</p>.
51      * <p>Both parameters may be <code>null</code>.</p>
52      *
53      * @param   data    The text of this segment.
54      * @param   style   The style describing this segment.
55      */
ParagraphTextSegment(String data, TextStyle style)56     public ParagraphTextSegment (String data, TextStyle style) {
57         pText  = data;
58         pStyle = style;
59     }
60 
61     /**
62      * <p>Sets the text for this segment.</p>
63      *
64      * @param   data    The text of this segment.
65      */
setText(String data)66     public void setText (String data) {
67         pText = data;
68     }
69 
70     /**
71      * <p>Gets the text for this segment.</p>
72      *
73      * @return    The text of this segment.
74      */
getText()75     public String getText () {
76         return pText;
77     }
78 
79 
80     /**
81      * <p>Sets the style for this segment.</p>
82      *
83      * @param   style    The style describing this segment.
84      */
setStyle(TextStyle style)85     public void setStyle (TextStyle style) {
86         pStyle = style;
87     }
88 
89 
90     /**
91      * <p>Gets the style for this segment.</p>
92      *
93      * @return  The style describing this segment.
94      */
getStyle()95     public TextStyle getStyle () {
96         return pStyle;
97     }
98 
99 
100     /**
101      * <p>Returns the string data for this text segment wrapped with the
102      *    appropriate byte codes for the formatting settings used.</p>
103      *
104      * @return  <code>byte</code> array containing formatted text in Pocket Word
105      *          format.
106      */
getData()107     public byte[] getData () {
108         ByteArrayOutputStream data = new ByteArrayOutputStream();
109 
110         boolean colourSet    = false;
111         boolean boldSet      = false;
112         boolean italicSet    = false;
113         boolean underlineSet = false;
114         boolean strikeSet    = false;
115         boolean highlightSet = false;
116 
117         // TODO: Font changes need to be worked out here
118 
119         try {
120             if (pStyle != null) {
121                 if (pStyle.getFontColor() != null) {
122 					ColourConverter cc = new ColourConverter();
123                     short colourCode = cc.convertFromRGB(pStyle.getFontColor());
124                     if (colourCode != 0) {	// not black
125                         data.write(COLOUR_TAG);
126                         data.write(EndianConverter.writeShort(colourCode));
127                         colourSet = true;
128                     }
129                 }
130                 if (pStyle.isSet(TextStyle.BOLD) && pStyle.getAttribute(TextStyle.BOLD)) {
131                     data.write(new byte[] { FONT_WEIGHT_TAG, FONT_WEIGHT_BOLD, 0x00 } );
132                     boldSet = true;
133                 }
134                 if (pStyle.isSet(TextStyle.ITALIC) && pStyle.getAttribute(TextStyle.ITALIC)) {
135                     data.write(new byte[] { ITALIC_TAG, 0x01 } );
136                     italicSet = true;
137                 }
138                 if (pStyle.isSet(TextStyle.UNDERLINE) && pStyle.getAttribute(TextStyle.UNDERLINE)) {
139                     data.write(new byte[] { UNDERLINE_TAG, 0x01 } );
140                     underlineSet = true;
141                 }
142                 if (pStyle.isSet(TextStyle.STRIKETHRU) && pStyle.getAttribute(TextStyle.STRIKETHRU)) {
143                     data.write(new byte[] { STRIKETHROUGH_TAG, 0x01 } );
144                     strikeSet = true;
145                 }
146                 if (pStyle.getBackgroundColor() != null) {
147                     data.write(new byte[] { HIGHLIGHT_TAG, 0x01 } );
148                     highlightSet = true;
149                 }
150             }
151 
152 
153             // Now write out the data
154             if (!pText.equals("\t")) {
155                 data.write(pText.getBytes());
156             }
157             else {
158                 /*
159                  * Tabs are a special case.  They are represented by Pocket Word
160                 * as the LE sequence 0xC4 0x04.
161                 */
162                 data.write(new byte[] { (byte)0xC4, 0x04 } );
163             }
164 
165 
166             // Now close out any of the settings changes
167             if (colourSet) {
168                 /*
169                  * Colours may change without changing back to black, but
170                  * without knowing what the previous colour was, the only
171                  * way to ensure correct conversion is to restore to black and
172                  * let the next segment change the colour again.
173                  */
174                 data.write(new byte[] { COLOUR_TAG, 0x00, 0x00 } );
175             }
176             if (boldSet) {
177                 data.write(new byte[] { FONT_WEIGHT_TAG, FONT_WEIGHT_NORMAL, 0x00 } );
178             }
179             if (italicSet) {
180                 data.write(new byte[] { ITALIC_TAG, 0x00 } );
181             }
182             if (underlineSet) {
183                 data.write(new byte[] { UNDERLINE_TAG, 0x00 } );
184             }
185             if (strikeSet) {
186                 data.write(new byte[] { STRIKETHROUGH_TAG, 0x00 } );
187             }
188             if (highlightSet) {
189                 data.write(new byte[] { HIGHLIGHT_TAG, 0x00 } );
190             }
191         }
192         catch (IOException ioe) {
193             // Should never occur in a memory based stream
194         }
195 
196         return data.toByteArray();
197     }
198 }
199