1. /*
  2. * @(#)RTFAttributes.java 1.12 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.text.rtf;
  8. import javax.swing.text.StyleConstants;
  9. import javax.swing.text.AttributeSet;
  10. import javax.swing.text.MutableAttributeSet;
  11. import javax.swing.text.TabStop;
  12. import java.util.*;
  13. import java.io.IOException;
  14. class RTFAttributes
  15. {
  16. static RTFAttribute attributes[];
  17. static {
  18. Vector a = new Vector();
  19. int CHR = RTFAttribute.D_CHARACTER;
  20. int PGF = RTFAttribute.D_PARAGRAPH;
  21. int SEC = RTFAttribute.D_SECTION;
  22. int DOC = RTFAttribute.D_DOCUMENT;
  23. int PST = RTFAttribute.D_META;
  24. Boolean True = Boolean.valueOf(true);
  25. Boolean False = Boolean.valueOf(false);
  26. a.addElement(new BooleanAttribute(CHR, StyleConstants.Italic, "i"));
  27. a.addElement(new BooleanAttribute(CHR, StyleConstants.Bold, "b"));
  28. a.addElement(new BooleanAttribute(CHR, StyleConstants.Underline, "ul"));
  29. a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.LeftIndent, "li",
  30. 0f, 0));
  31. a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.RightIndent, "ri",
  32. 0f, 0));
  33. a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.FirstLineIndent, "fi",
  34. 0f, 0));
  35. a.addElement(new AssertiveAttribute(PGF, StyleConstants.Alignment,
  36. "ql", StyleConstants.ALIGN_LEFT));
  37. a.addElement(new AssertiveAttribute(PGF, StyleConstants.Alignment,
  38. "qr", StyleConstants.ALIGN_RIGHT));
  39. a.addElement(new AssertiveAttribute(PGF, StyleConstants.Alignment,
  40. "qc", StyleConstants.ALIGN_CENTER));
  41. a.addElement(new AssertiveAttribute(PGF, StyleConstants.Alignment,
  42. "qj", StyleConstants.ALIGN_JUSTIFIED));
  43. a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.SpaceAbove,
  44. "sa", 0));
  45. a.addElement(NumericAttribute.NewTwips(PGF, StyleConstants.SpaceBelow,
  46. "sb", 0));
  47. a.addElement(new AssertiveAttribute(PST, RTFReader.TabAlignmentKey,
  48. "tqr", TabStop.ALIGN_RIGHT));
  49. a.addElement(new AssertiveAttribute(PST, RTFReader.TabAlignmentKey,
  50. "tqc", TabStop.ALIGN_CENTER));
  51. a.addElement(new AssertiveAttribute(PST, RTFReader.TabAlignmentKey,
  52. "tqdec", TabStop.ALIGN_DECIMAL));
  53. a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
  54. "tldot", TabStop.LEAD_DOTS));
  55. a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
  56. "tlhyph", TabStop.LEAD_HYPHENS));
  57. a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
  58. "tlul", TabStop.LEAD_UNDERLINE));
  59. a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
  60. "tlth", TabStop.LEAD_THICKLINE));
  61. a.addElement(new AssertiveAttribute(PST, RTFReader.TabLeaderKey,
  62. "tleq", TabStop.LEAD_EQUALS));
  63. /* The following aren't actually recognized by Swing */
  64. a.addElement(new BooleanAttribute(CHR, Constants.Caps, "caps"));
  65. a.addElement(new BooleanAttribute(CHR, Constants.Outline, "outl"));
  66. a.addElement(new BooleanAttribute(CHR, Constants.SmallCaps, "scaps"));
  67. a.addElement(new BooleanAttribute(CHR, Constants.Shadow, "shad"));
  68. a.addElement(new BooleanAttribute(CHR, Constants.Hidden, "v"));
  69. a.addElement(new BooleanAttribute(CHR, Constants.Strikethrough,
  70. "strike"));
  71. a.addElement(new BooleanAttribute(CHR, Constants.Deleted,
  72. "deleted"));
  73. a.addElement(new AssertiveAttribute(DOC, "saveformat", "defformat", "RTF"));
  74. a.addElement(new AssertiveAttribute(DOC, "landscape", "landscape"));
  75. a.addElement(NumericAttribute.NewTwips(DOC, Constants.PaperWidth,
  76. "paperw", 12240));
  77. a.addElement(NumericAttribute.NewTwips(DOC, Constants.PaperHeight,
  78. "paperh", 15840));
  79. a.addElement(NumericAttribute.NewTwips(DOC, Constants.MarginLeft,
  80. "margl", 1800));
  81. a.addElement(NumericAttribute.NewTwips(DOC, Constants.MarginRight,
  82. "margr", 1800));
  83. a.addElement(NumericAttribute.NewTwips(DOC, Constants.MarginTop,
  84. "margt", 1440));
  85. a.addElement(NumericAttribute.NewTwips(DOC, Constants.MarginBottom,
  86. "margb", 1440));
  87. a.addElement(NumericAttribute.NewTwips(DOC, Constants.GutterWidth,
  88. "gutter", 0));
  89. a.addElement(new AssertiveAttribute(PGF, Constants.WidowControl,
  90. "nowidctlpar", False));
  91. a.addElement(new AssertiveAttribute(PGF, Constants.WidowControl,
  92. "widctlpar", True));
  93. a.addElement(new AssertiveAttribute(DOC, Constants.WidowControl,
  94. "widowctrl", True));
  95. RTFAttribute[] attrs = new RTFAttribute[a.size()];
  96. a.copyInto(attrs);
  97. attributes = attrs;
  98. }
  99. static Dictionary attributesByKeyword()
  100. {
  101. Dictionary d = new Hashtable(attributes.length);
  102. int i, m;
  103. m = attributes.length;
  104. for(i = 0; i < m; i++)
  105. d.put(attributes[i].rtfName(), attributes[i]);
  106. return d;
  107. }
  108. /************************************************************************/
  109. /************************************************************************/
  110. static abstract class GenericAttribute
  111. {
  112. int domain;
  113. Object swingName;
  114. String rtfName;
  115. protected GenericAttribute(int d,Object s, String r)
  116. {
  117. domain = d;
  118. swingName = s;
  119. rtfName = r;
  120. }
  121. public int domain() { return domain; }
  122. public Object swingName() { return swingName; }
  123. public String rtfName() { return rtfName; }
  124. abstract boolean set(MutableAttributeSet target);
  125. abstract boolean set(MutableAttributeSet target, int parameter);
  126. abstract boolean setDefault(MutableAttributeSet target);
  127. public boolean write(AttributeSet source,
  128. RTFGenerator target,
  129. boolean force)
  130. throws IOException
  131. {
  132. return writeValue(source.getAttribute(swingName), target, force);
  133. }
  134. public boolean writeValue(Object value, RTFGenerator target,
  135. boolean force)
  136. throws IOException
  137. {
  138. return false;
  139. }
  140. }
  141. static class BooleanAttribute
  142. extends GenericAttribute
  143. implements RTFAttribute
  144. {
  145. boolean rtfDefault;
  146. boolean swingDefault;
  147. protected static final Boolean True = Boolean.valueOf(true);
  148. protected static final Boolean False = Boolean.valueOf(false);
  149. public BooleanAttribute(int d, Object s,
  150. String r, boolean ds, boolean dr)
  151. {
  152. super(d, s, r);
  153. swingDefault = ds;
  154. rtfDefault = dr;
  155. }
  156. public BooleanAttribute(int d, Object s, String r)
  157. {
  158. super(d, s, r);
  159. swingDefault = false;
  160. rtfDefault = false;
  161. }
  162. public boolean set(MutableAttributeSet target)
  163. {
  164. /* TODO: There's some ambiguity about whether this should
  165. *set* or *toggle* the attribute. */
  166. target.addAttribute(swingName, True);
  167. return true; /* true indicates we were successful */
  168. }
  169. public boolean set(MutableAttributeSet target, int parameter)
  170. {
  171. /* See above note in the case that parameter==1 */
  172. Boolean value = ( parameter != 0 ? True : False );
  173. target.addAttribute(swingName, value);
  174. return true; /* true indicates we were successful */
  175. }
  176. public boolean setDefault(MutableAttributeSet target)
  177. {
  178. if (swingDefault != rtfDefault ||
  179. ( target.getAttribute(swingName) != null ) )
  180. target.addAttribute(swingName, Boolean.valueOf(rtfDefault));
  181. return true;
  182. }
  183. public boolean writeValue(Object o_value,
  184. RTFGenerator target,
  185. boolean force)
  186. throws IOException
  187. {
  188. Boolean val;
  189. if (o_value == null)
  190. val = Boolean.valueOf(swingDefault);
  191. else
  192. val = (Boolean)o_value;
  193. if (force || (val.booleanValue() != rtfDefault)) {
  194. if (val.booleanValue()) {
  195. target.writeControlWord(rtfName);
  196. } else {
  197. target.writeControlWord(rtfName, 0);
  198. }
  199. }
  200. return true;
  201. }
  202. }
  203. static class AssertiveAttribute
  204. extends GenericAttribute
  205. implements RTFAttribute
  206. {
  207. Object swingValue;
  208. public AssertiveAttribute(int d, Object s, String r)
  209. {
  210. super(d, s, r);
  211. swingValue = Boolean.valueOf(true);
  212. }
  213. public AssertiveAttribute(int d, Object s, String r, Object v)
  214. {
  215. super(d, s, r);
  216. swingValue = v;
  217. }
  218. public AssertiveAttribute(int d, Object s, String r, int v)
  219. {
  220. super(d, s, r);
  221. swingValue = new Integer(v);
  222. }
  223. public boolean set(MutableAttributeSet target)
  224. {
  225. if (swingValue == null)
  226. target.removeAttribute(swingName);
  227. else
  228. target.addAttribute(swingName, swingValue);
  229. return true;
  230. }
  231. public boolean set(MutableAttributeSet target, int parameter)
  232. {
  233. return false;
  234. }
  235. public boolean setDefault(MutableAttributeSet target)
  236. {
  237. target.removeAttribute(swingName);
  238. return true;
  239. }
  240. public boolean writeValue(Object value,
  241. RTFGenerator target,
  242. boolean force)
  243. throws IOException
  244. {
  245. if (value == null) {
  246. return ! force;
  247. }
  248. if (value.equals(swingValue)) {
  249. target.writeControlWord(rtfName);
  250. return true;
  251. }
  252. return ! force;
  253. }
  254. }
  255. static class NumericAttribute
  256. extends GenericAttribute
  257. implements RTFAttribute
  258. {
  259. int rtfDefault;
  260. Number swingDefault;
  261. float scale;
  262. protected NumericAttribute(int d, Object s, String r)
  263. {
  264. super(d, s, r);
  265. rtfDefault = 0;
  266. swingDefault = null;
  267. scale = 1f;
  268. }
  269. public NumericAttribute(int d, Object s,
  270. String r, int ds, int dr)
  271. {
  272. this(d, s, r, new Integer(ds), dr, 1f);
  273. }
  274. public NumericAttribute(int d, Object s,
  275. String r, Number ds, int dr, float sc)
  276. {
  277. super(d, s, r);
  278. swingDefault = ds;
  279. rtfDefault = dr;
  280. scale = sc;
  281. }
  282. public static NumericAttribute NewTwips(int d, Object s, String r,
  283. float ds, int dr)
  284. {
  285. return new NumericAttribute(d, s, r, new Float(ds), dr, 20f);
  286. }
  287. public static NumericAttribute NewTwips(int d, Object s, String r,
  288. int dr)
  289. {
  290. return new NumericAttribute(d, s, r, null, dr, 20f);
  291. }
  292. public boolean set(MutableAttributeSet target)
  293. {
  294. return false;
  295. }
  296. public boolean set(MutableAttributeSet target, int parameter)
  297. {
  298. Number swingValue;
  299. if (scale == 1f)
  300. swingValue = new Integer(parameter);
  301. else
  302. swingValue = new Float(parameter / scale);
  303. target.addAttribute(swingName, swingValue);
  304. return true;
  305. }
  306. public boolean setDefault(MutableAttributeSet target)
  307. {
  308. Number old = (Number)target.getAttribute(swingName);
  309. if (old == null)
  310. old = swingDefault;
  311. if (old != null && (
  312. (scale == 1f && old.intValue() == rtfDefault) ||
  313. (Math.round(old.floatValue() * scale) == rtfDefault)
  314. ))
  315. return true;
  316. set(target, rtfDefault);
  317. return true;
  318. }
  319. public boolean writeValue(Object o_value,
  320. RTFGenerator target,
  321. boolean force)
  322. throws IOException
  323. {
  324. Number value = (Number)o_value;
  325. if (value == null)
  326. value = swingDefault;
  327. if (value == null) {
  328. /* TODO: What is the proper behavior if the Swing object does
  329. not specify a value, and we don't know its default value?
  330. Currently we pretend that the RTF default value is
  331. equivalent (probably a workable assumption) */
  332. return true;
  333. }
  334. int int_value = Math.round(value.floatValue() * scale);
  335. if (force || (int_value != rtfDefault))
  336. target.writeControlWord(rtfName, int_value);
  337. return true;
  338. }
  339. }
  340. }