1 /*
2 * Copyright 1997-2002 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 package javax.swing.text.rtf;
26
27 import javax.swing.text.StyleConstants;
28 import javax.swing.text.AttributeSet;
29 import javax.swing.text.MutableAttributeSet;
30 import javax.swing.text.TabStop;
31 import java.util;
32 import java.io.IOException;
33
34 class RTFAttributes
35 {
36 static RTFAttribute attributes[];
37
38 static {
39 Vector a = new Vector();
40 int CHR = RTFAttribute.D_CHARACTER;
41 int PGF = RTFAttribute.D_PARAGRAPH;
42 int SEC = RTFAttribute.D_SECTION;
43 int DOC = RTFAttribute.D_DOCUMENT;
44 int PST = RTFAttribute.D_META;
45 Boolean True = Boolean.valueOf(true);
46 Boolean False = Boolean.valueOf(false);
47
48 a.addElement(new BooleanAttribute(CHR, StyleConstants.Italic, "i"));
49 a.addElement(new BooleanAttribute(CHR, StyleConstants.Bold, "b"));
50 a.addElement(new BooleanAttribute(CHR, StyleConstants.Underline, "ul"));
51 a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.LeftIndent, "li",
52 0f, 0));
53 a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.RightIndent, "ri",
54 0f, 0));
55 a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.FirstLineIndent, "fi",
56 0f, 0));
57
58 a.addElement(new AssertiveAttribute(PGF, StyleConstants.Alignment,
59 "ql", StyleConstants.ALIGN_LEFT));
60 a.addElement(new AssertiveAttribute(PGF, StyleConstants.Alignment,
61 "qr", StyleConstants.ALIGN_RIGHT));
62 a.addElement(new AssertiveAttribute(PGF, StyleConstants.Alignment,
63 "qc", StyleConstants.ALIGN_CENTER));
64 a.addElement(new AssertiveAttribute(PGF, StyleConstants.Alignment,
65 "qj", StyleConstants.ALIGN_JUSTIFIED));
66 a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.SpaceAbove,
67 "sa", 0));
68 a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.SpaceBelow,
69 "sb", 0));
70
71 a.addElement(new AssertiveAttribute(PST, RTFReader.TabAlignmentKey,
72 "tqr", TabStop.ALIGN_RIGHT));
73 a.addElement(new AssertiveAttribute(PST, RTFReader.TabAlignmentKey,
74 "tqc", TabStop.ALIGN_CENTER));
75 a.addElement(new AssertiveAttribute(PST, RTFReader.TabAlignmentKey,
76 "tqdec", TabStop.ALIGN_DECIMAL));
77
78
79 a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
80 "tldot", TabStop.LEAD_DOTS));
81 a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
82 "tlhyph", TabStop.LEAD_HYPHENS));
83 a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
84 "tlul", TabStop.LEAD_UNDERLINE));
85 a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
86 "tlth", TabStop.LEAD_THICKLINE));
87 a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
88 "tleq", TabStop.LEAD_EQUALS));
89
90 /* The following aren't actually recognized by Swing */
91 a.addElement(new BooleanAttribute(CHR, Constants.Caps, "caps"));
92 a.addElement(new BooleanAttribute(CHR, Constants.Outline, "outl"));
93 a.addElement(new BooleanAttribute(CHR, Constants.SmallCaps, "scaps"));
94 a.addElement(new BooleanAttribute(CHR, Constants.Shadow, "shad"));
95 a.addElement(new BooleanAttribute(CHR, Constants.Hidden, "v"));
96 a.addElement(new BooleanAttribute(CHR, Constants.Strikethrough,
97 "strike"));
98 a.addElement(new BooleanAttribute(CHR, Constants.Deleted,
99 "deleted"));
100
101
102
103 a.addElement(new AssertiveAttribute(DOC, "saveformat", "defformat", "RTF"));
104 a.addElement(new AssertiveAttribute(DOC, "landscape", "landscape"));
105
106 a.addElement(NumericAttribute.NewTwips(DOC, Constants.PaperWidth,
107 "paperw", 12240));
108 a.addElement(NumericAttribute.NewTwips(DOC, Constants.PaperHeight,
109 "paperh", 15840));
110 a.addElement(NumericAttribute.NewTwips(DOC, Constants.MarginLeft,
111 "margl", 1800));
112 a.addElement(NumericAttribute.NewTwips(DOC, Constants.MarginRight,
113 "margr", 1800));
114 a.addElement(NumericAttribute.NewTwips(DOC, Constants.MarginTop,
115 "margt", 1440));
116 a.addElement(NumericAttribute.NewTwips(DOC, Constants.MarginBottom,
117 "margb", 1440));
118 a.addElement(NumericAttribute.NewTwips(DOC, Constants.GutterWidth,
119 "gutter", 0));
120
121 a.addElement(new AssertiveAttribute(PGF, Constants.WidowControl,
122 "nowidctlpar", False));
123 a.addElement(new AssertiveAttribute(PGF, Constants.WidowControl,
124 "widctlpar", True));
125 a.addElement(new AssertiveAttribute(DOC, Constants.WidowControl,
126 "widowctrl", True));
127
128
129 RTFAttribute[] attrs = new RTFAttribute[a.size()];
130 a.copyInto(attrs);
131 attributes = attrs;
132 }
133
134 static Dictionary attributesByKeyword()
135 {
136 Dictionary d = new Hashtable(attributes.length);
137 int i, m;
138
139 m = attributes.length;
140 for(i = 0; i < m; i++)
141 d.put(attributes[i].rtfName(), attributes[i]);
142
143 return d;
144 }
145
146 /************************************************************************/
147 /************************************************************************/
148
149 static abstract class GenericAttribute
150 {
151 int domain;
152 Object swingName;
153 String rtfName;
154
155 protected GenericAttribute(int d,Object s, String r)
156 {
157 domain = d;
158 swingName = s;
159 rtfName = r;
160 }
161
162 public int domain() { return domain; }
163 public Object swingName() { return swingName; }
164 public String rtfName() { return rtfName; }
165
166 abstract boolean set(MutableAttributeSet target);
167 abstract boolean set(MutableAttributeSet target, int parameter);
168 abstract boolean setDefault(MutableAttributeSet target);
169
170 public boolean write(AttributeSet source,
171 RTFGenerator target,
172 boolean force)
173 throws IOException
174 {
175 return writeValue(source.getAttribute(swingName), target, force);
176 }
177
178 public boolean writeValue(Object value, RTFGenerator target,
179 boolean force)
180 throws IOException
181 {
182 return false;
183 }
184 }
185
186 static class BooleanAttribute
187 extends GenericAttribute
188 implements RTFAttribute
189 {
190 boolean rtfDefault;
191 boolean swingDefault;
192
193 protected static final Boolean True = Boolean.valueOf(true);
194 protected static final Boolean False = Boolean.valueOf(false);
195
196 public BooleanAttribute(int d, Object s,
197 String r, boolean ds, boolean dr)
198 {
199 super(d, s, r);
200 swingDefault = ds;
201 rtfDefault = dr;
202 }
203
204 public BooleanAttribute(int d, Object s, String r)
205 {
206 super(d, s, r);
207
208 swingDefault = false;
209 rtfDefault = false;
210 }
211
212 public boolean set(MutableAttributeSet target)
213 {
214 /* TODO: There's some ambiguity about whether this should
215 *set* or *toggle* the attribute. */
216 target.addAttribute(swingName, True);
217
218 return true; /* true indicates we were successful */
219 }
220
221 public boolean set(MutableAttributeSet target, int parameter)
222 {
223 /* See above note in the case that parameter==1 */
224 Boolean value = ( parameter != 0 ? True : False );
225
226 target.addAttribute(swingName, value);
227
228 return true; /* true indicates we were successful */
229 }
230
231 public boolean setDefault(MutableAttributeSet target)
232 {
233 if (swingDefault != rtfDefault ||
234 ( target.getAttribute(swingName) != null ) )
235 target.addAttribute(swingName, Boolean.valueOf(rtfDefault));
236 return true;
237 }
238
239 public boolean writeValue(Object o_value,
240 RTFGenerator target,
241 boolean force)
242 throws IOException
243 {
244 Boolean val;
245
246 if (o_value == null)
247 val = Boolean.valueOf(swingDefault);
248 else
249 val = (Boolean)o_value;
250
251 if (force || (val.booleanValue() != rtfDefault)) {
252 if (val.booleanValue()) {
253 target.writeControlWord(rtfName);
254 } else {
255 target.writeControlWord(rtfName, 0);
256 }
257 }
258 return true;
259 }
260 }
261
262
263 static class AssertiveAttribute
264 extends GenericAttribute
265 implements RTFAttribute
266 {
267 Object swingValue;
268
269 public AssertiveAttribute(int d, Object s, String r)
270 {
271 super(d, s, r);
272 swingValue = Boolean.valueOf(true);
273 }
274
275 public AssertiveAttribute(int d, Object s, String r, Object v)
276 {
277 super(d, s, r);
278 swingValue = v;
279 }
280
281 public AssertiveAttribute(int d, Object s, String r, int v)
282 {
283 super(d, s, r);
284 swingValue = Integer.valueOf(v);
285 }
286
287 public boolean set(MutableAttributeSet target)
288 {
289 if (swingValue == null)
290 target.removeAttribute(swingName);
291 else
292 target.addAttribute(swingName, swingValue);
293
294 return true;
295 }
296
297 public boolean set(MutableAttributeSet target, int parameter)
298 {
299 return false;
300 }
301
302 public boolean setDefault(MutableAttributeSet target)
303 {
304 target.removeAttribute(swingName);
305 return true;
306 }
307
308 public boolean writeValue(Object value,
309 RTFGenerator target,
310 boolean force)
311 throws IOException
312 {
313 if (value == null) {
314 return ! force;
315 }
316
317 if (value.equals(swingValue)) {
318 target.writeControlWord(rtfName);
319 return true;
320 }
321
322 return ! force;
323 }
324 }
325
326
327 static class NumericAttribute
328 extends GenericAttribute
329 implements RTFAttribute
330 {
331 int rtfDefault;
332 Number swingDefault;
333 float scale;
334
335 protected NumericAttribute(int d, Object s, String r)
336 {
337 super(d, s, r);
338 rtfDefault = 0;
339 swingDefault = null;
340 scale = 1f;
341 }
342
343 public NumericAttribute(int d, Object s,
344 String r, int ds, int dr)
345 {
346 this(d, s, r, Integer.valueOf(ds), dr, 1f);
347 }
348
349 public NumericAttribute(int d, Object s,
350 String r, Number ds, int dr, float sc)
351 {
352 super(d, s, r);
353 swingDefault = ds;
354 rtfDefault = dr;
355 scale = sc;
356 }
357
358 public static NumericAttribute NewTwips(int d, Object s, String r,
359 float ds, int dr)
360 {
361 return new NumericAttribute(d, s, r, new Float(ds), dr, 20f);
362 }
363
364 public static NumericAttribute NewTwips(int d, Object s, String r,
365 int dr)
366 {
367 return new NumericAttribute(d, s, r, null, dr, 20f);
368 }
369
370 public boolean set(MutableAttributeSet target)
371 {
372 return false;
373 }
374
375 public boolean set(MutableAttributeSet target, int parameter)
376 {
377 Number swingValue;
378
379 if (scale == 1f)
380 swingValue = Integer.valueOf(parameter);
381 else
382 swingValue = new Float(parameter / scale);
383 target.addAttribute(swingName, swingValue);
384 return true;
385 }
386
387 public boolean setDefault(MutableAttributeSet target)
388 {
389 Number old = (Number)target.getAttribute(swingName);
390 if (old == null)
391 old = swingDefault;
392 if (old != null && (
393 (scale == 1f && old.intValue() == rtfDefault) ||
394 (Math.round(old.floatValue() * scale) == rtfDefault)
395 ))
396 return true;
397 set(target, rtfDefault);
398 return true;
399 }
400
401 public boolean writeValue(Object o_value,
402 RTFGenerator target,
403 boolean force)
404 throws IOException
405 {
406 Number value = (Number)o_value;
407 if (value == null)
408 value = swingDefault;
409 if (value == null) {
410 /* TODO: What is the proper behavior if the Swing object does
411 not specify a value, and we don't know its default value?
412 Currently we pretend that the RTF default value is
413 equivalent (probably a workable assumption) */
414 return true;
415 }
416 int int_value = Math.round(value.floatValue() * scale);
417 if (force || (int_value != rtfDefault))
418 target.writeControlWord(rtfName, int_value);
419 return true;
420 }
421 }
422 }