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