You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CharacterRun.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hwpf.usermodel;
  16. import org.apache.poi.common.Duplicatable;
  17. import org.apache.poi.hwpf.HWPFDocument;
  18. import org.apache.poi.hwpf.HWPFOldDocument;
  19. import org.apache.poi.hwpf.model.CHPX;
  20. import org.apache.poi.hwpf.model.FFData;
  21. import org.apache.poi.hwpf.model.Ffn;
  22. import org.apache.poi.hwpf.model.NilPICFAndBinData;
  23. import org.apache.poi.hwpf.model.StyleSheet;
  24. import org.apache.poi.hwpf.sprm.SprmBuffer;
  25. import org.apache.poi.util.Removal;
  26. /**
  27. * This class represents a run of text that share common properties.
  28. */
  29. public final class CharacterRun extends Range implements Duplicatable, org.apache.poi.wp.usermodel.CharacterRun {
  30. public static final short SPRM_FRMARKDEL = (short)0x0800;
  31. public static final short SPRM_FRMARK = 0x0801;
  32. public static final short SPRM_FFLDVANISH = 0x0802;
  33. public static final short SPRM_PICLOCATION = 0x6A03;
  34. public static final short SPRM_IBSTRMARK = 0x4804;
  35. public static final short SPRM_DTTMRMARK = 0x6805;
  36. public static final short SPRM_FDATA = 0x0806;
  37. public static final short SPRM_SYMBOL = 0x6A09;
  38. public static final short SPRM_FOLE2 = 0x080A;
  39. public static final short SPRM_HIGHLIGHT = 0x2A0C;
  40. public static final short SPRM_OBJLOCATION = 0x680E;
  41. public static final short SPRM_ISTD = 0x4A30;
  42. public static final short SPRM_FBOLD = 0x0835;
  43. public static final short SPRM_FITALIC = 0x0836;
  44. public static final short SPRM_FSTRIKE = 0x0837;
  45. public static final short SPRM_FOUTLINE = 0x0838;
  46. public static final short SPRM_FSHADOW = 0x0839;
  47. public static final short SPRM_FSMALLCAPS = 0x083A;
  48. public static final short SPRM_FCAPS = 0x083B;
  49. public static final short SPRM_FVANISH = 0x083C;
  50. public static final short SPRM_KUL = 0x2A3E;
  51. public static final short SPRM_DXASPACE = (short)0x8840;
  52. public static final short SPRM_LID = 0x4A41;
  53. public static final short SPRM_ICO = 0x2A42;
  54. public static final short SPRM_HPS = 0x4A43;
  55. public static final short SPRM_HPSPOS = 0x4845;
  56. public static final short SPRM_ISS = 0x2A48;
  57. public static final short SPRM_HPSKERN = 0x484B;
  58. public static final short SPRM_YSRI = 0x484E;
  59. public static final short SPRM_RGFTCASCII = 0x4A4F;
  60. public static final short SPRM_RGFTCFAREAST = 0x4A50;
  61. public static final short SPRM_RGFTCNOTFAREAST = 0x4A51;
  62. public static final short SPRM_CHARSCALE = 0x4852;
  63. public static final short SPRM_FDSTRIKE = 0x2A53;
  64. public static final short SPRM_FIMPRINT = 0x0854;
  65. public static final short SPRM_FSPEC = 0x0855;
  66. public static final short SPRM_FOBJ = 0x0856;
  67. public static final short SPRM_PROPRMARK = (short)0xCA57;
  68. public static final short SPRM_FEMBOSS = 0x0858;
  69. public static final short SPRM_SFXTEXT = 0x2859;
  70. public static final short SPRM_DISPFLDRMARK = (short)0xCA62;
  71. public static final short SPRM_IBSTRMARKDEL = 0x4863;
  72. public static final short SPRM_DTTMRMARKDEL = 0x6864;
  73. public static final short SPRM_BRC = 0x6865;
  74. public static final short SPRM_SHD = 0x4866;
  75. public static final short SPRM_IDSIRMARKDEL = 0x4867;
  76. public static final short SPRM_CPG = 0x486B;
  77. public static final short SPRM_NONFELID = 0x486D;
  78. public static final short SPRM_FELID = 0x486E;
  79. public static final short SPRM_IDCTHINT = 0x286F;
  80. protected short _istd;
  81. protected SprmBuffer _chpx;
  82. protected CharacterProperties _props;
  83. /**
  84. *
  85. * @param chpx The chpx this object is based on.
  86. * @param ss The stylesheet for the document this run belongs to.
  87. * @param istd The style index if this run's base style.
  88. * @param parent The parent range of this character run (usually a paragraph).
  89. */
  90. CharacterRun(CHPX chpx, StyleSheet ss, short istd, Range parent)
  91. {
  92. super(Math.max(parent._start, chpx.getStart()), Math.min(parent._end, chpx.getEnd()), parent);
  93. _props = chpx.getCharacterProperties(ss, istd);
  94. _chpx = chpx.getSprmBuf();
  95. _istd = istd;
  96. }
  97. CharacterRun(CharacterRun other) {
  98. super(other);
  99. _istd = other._istd;
  100. _chpx = (other._chpx == null) ? null : other._chpx.copy();
  101. _props = (other._props == null) ? null : other._props.copy();
  102. }
  103. /**
  104. * Here for runtime type determination using a switch statement convenient.
  105. *
  106. * @return TYPE_CHARACTER
  107. */
  108. @SuppressWarnings("deprecation")
  109. public int type()
  110. {
  111. return TYPE_CHARACTER;
  112. }
  113. public boolean isMarkedDeleted()
  114. {
  115. return _props.isFRMarkDel();
  116. }
  117. public void markDeleted(boolean mark)
  118. {
  119. _props.setFRMarkDel(mark);
  120. byte newVal = (byte)(mark ? 1 : 0);
  121. _chpx.updateSprm(SPRM_FRMARKDEL, newVal);
  122. }
  123. public boolean isBold()
  124. {
  125. return _props.isFBold();
  126. }
  127. public void setBold(boolean bold)
  128. {
  129. _props.setFBold(bold);
  130. byte newVal = (byte)(bold ? 1 : 0);
  131. _chpx.updateSprm(SPRM_FBOLD, newVal);
  132. }
  133. public boolean isItalic()
  134. {
  135. return _props.isFItalic();
  136. }
  137. public void setItalic(boolean italic)
  138. {
  139. _props.setFItalic(italic);
  140. byte newVal = (byte)(italic ? 1 : 0);
  141. _chpx.updateSprm(SPRM_FITALIC, newVal);
  142. }
  143. public boolean isOutlined()
  144. {
  145. return _props.isFOutline();
  146. }
  147. public void setOutline(boolean outlined)
  148. {
  149. _props.setFOutline(outlined);
  150. byte newVal = (byte)(outlined ? 1 : 0);
  151. _chpx.updateSprm(SPRM_FOUTLINE, newVal);
  152. }
  153. public boolean isFldVanished()
  154. {
  155. return _props.isFFldVanish();
  156. }
  157. public void setFldVanish(boolean fldVanish)
  158. {
  159. _props.setFFldVanish(fldVanish);
  160. byte newVal = (byte)(fldVanish ? 1 : 0);
  161. _chpx.updateSprm(SPRM_FFLDVANISH, newVal);
  162. }
  163. public boolean isSmallCaps()
  164. {
  165. return _props.isFSmallCaps();
  166. }
  167. public void setSmallCaps(boolean smallCaps)
  168. {
  169. _props.setFSmallCaps(smallCaps);
  170. byte newVal = (byte)(smallCaps ? 1 : 0);
  171. _chpx.updateSprm(SPRM_FSMALLCAPS, newVal);
  172. }
  173. public boolean isCapitalized()
  174. {
  175. return _props.isFCaps();
  176. }
  177. public void setCapitalized(boolean caps)
  178. {
  179. _props.setFCaps(caps);
  180. byte newVal = (byte)(caps ? 1 : 0);
  181. _chpx.updateSprm(SPRM_FCAPS, newVal);
  182. }
  183. public boolean isVanished()
  184. {
  185. return _props.isFVanish();
  186. }
  187. public void setVanished(boolean vanish)
  188. {
  189. _props.setFVanish(vanish);
  190. byte newVal = (byte)(vanish ? 1 : 0);
  191. _chpx.updateSprm(SPRM_FVANISH, newVal);
  192. }
  193. public boolean isMarkedInserted()
  194. {
  195. return _props.isFRMark();
  196. }
  197. public void markInserted(boolean mark)
  198. {
  199. _props.setFRMark(mark);
  200. byte newVal = (byte)(mark ? 1 : 0);
  201. _chpx.updateSprm(SPRM_FRMARK, newVal);
  202. }
  203. public boolean isStrikeThrough()
  204. {
  205. return _props.isFStrike();
  206. }
  207. public void setStrikeThrough(boolean strike)
  208. {
  209. strikeThrough(strike);
  210. }
  211. public void strikeThrough(boolean strike)
  212. {
  213. _props.setFStrike(strike);
  214. byte newVal = (byte)(strike ? 1 : 0);
  215. _chpx.updateSprm(SPRM_FSTRIKE, newVal);
  216. }
  217. public boolean isShadowed()
  218. {
  219. return _props.isFShadow();
  220. }
  221. public void setShadow(boolean shadow)
  222. {
  223. _props.setFShadow(shadow);
  224. byte newVal = (byte)(shadow ? 1 : 0);
  225. _chpx.updateSprm(SPRM_FSHADOW, newVal);
  226. }
  227. public boolean isEmbossed()
  228. {
  229. return _props.isFEmboss();
  230. }
  231. public void setEmbossed(boolean emboss)
  232. {
  233. _props.setFEmboss(emboss);
  234. byte newVal = (byte)(emboss ? 1 : 0);
  235. _chpx.updateSprm(SPRM_FEMBOSS, newVal);
  236. }
  237. public boolean isImprinted()
  238. {
  239. return _props.isFImprint();
  240. }
  241. public void setImprinted(boolean imprint)
  242. {
  243. _props.setFImprint(imprint);
  244. byte newVal = (byte)(imprint ? 1 : 0);
  245. _chpx.updateSprm(SPRM_FIMPRINT, newVal);
  246. }
  247. public boolean isDoubleStrikeThrough()
  248. {
  249. return _props.isFDStrike();
  250. }
  251. public void setDoubleStrikethrough(boolean dstrike)
  252. {
  253. _props.setFDStrike(dstrike);
  254. byte newVal = (byte)(dstrike ? 1 : 0);
  255. _chpx.updateSprm(SPRM_FDSTRIKE, newVal);
  256. }
  257. public void setFtcAscii(int ftcAscii)
  258. {
  259. _props.setFtcAscii(ftcAscii);
  260. _chpx.updateSprm(SPRM_RGFTCASCII, (short)ftcAscii);
  261. }
  262. public void setFtcFE(int ftcFE)
  263. {
  264. _props.setFtcFE(ftcFE);
  265. _chpx.updateSprm(SPRM_RGFTCFAREAST, (short)ftcFE);
  266. }
  267. public void setFtcOther(int ftcOther)
  268. {
  269. _props.setFtcOther(ftcOther);
  270. _chpx.updateSprm(SPRM_RGFTCNOTFAREAST, (short)ftcOther);
  271. }
  272. public int getFontSize()
  273. {
  274. return _props.getHps();
  275. }
  276. public void setFontSize(int halfPoints)
  277. {
  278. _props.setHps(halfPoints);
  279. _chpx.updateSprm(SPRM_HPS, (short)halfPoints);
  280. }
  281. public int getCharacterSpacing()
  282. {
  283. return _props.getDxaSpace();
  284. }
  285. public void setCharacterSpacing(int twips)
  286. {
  287. _props.setDxaSpace(twips);
  288. _chpx.updateSprm(SPRM_DXASPACE, twips);
  289. }
  290. public short getSubSuperScriptIndex()
  291. {
  292. return _props.getIss();
  293. }
  294. public void setSubSuperScriptIndex(short iss)
  295. {
  296. _props.setDxaSpace(iss);
  297. _chpx.updateSprm(SPRM_DXASPACE, iss);
  298. }
  299. public int getUnderlineCode()
  300. {
  301. return _props.getKul();
  302. }
  303. public void setUnderlineCode(int kul)
  304. {
  305. _props.setKul((byte)kul);
  306. _chpx.updateSprm(SPRM_KUL, (byte)kul);
  307. }
  308. public int getColor()
  309. {
  310. return _props.getIco();
  311. }
  312. public void setColor(int color)
  313. {
  314. _props.setIco((byte)color);
  315. _chpx.updateSprm(SPRM_ICO, (byte)color);
  316. }
  317. public int getVerticalOffset()
  318. {
  319. return _props.getHpsPos();
  320. }
  321. public void setVerticalOffset(int hpsPos)
  322. {
  323. _props.setHpsPos((short) hpsPos);
  324. _chpx.updateSprm(SPRM_HPSPOS, (byte)hpsPos);
  325. }
  326. public int getKerning()
  327. {
  328. return _props.getHpsKern();
  329. }
  330. public void setKerning(int kern)
  331. {
  332. _props.setHpsKern(kern);
  333. _chpx.updateSprm(SPRM_HPSKERN, (short)kern);
  334. }
  335. public boolean isHighlighted()
  336. {
  337. return _props.isFHighlight();
  338. }
  339. public byte getHighlightedColor()
  340. {
  341. return _props.getIcoHighlight();
  342. }
  343. public void setHighlighted(byte color)
  344. {
  345. _props.setFHighlight(true);
  346. _props.setIcoHighlight(color);
  347. _chpx.updateSprm(SPRM_HIGHLIGHT, color);
  348. }
  349. public String getFontName()
  350. {
  351. if (_doc instanceof HWPFOldDocument) {
  352. return ((HWPFOldDocument) _doc).getOldFontTable().getMainFont(_props.getFtcAscii());
  353. }
  354. if (_doc.getFontTable() == null)
  355. // old word format
  356. return null;
  357. return _doc.getFontTable().getMainFont(_props.getFtcAscii());
  358. }
  359. public boolean isSpecialCharacter()
  360. {
  361. return _props.isFSpec();
  362. }
  363. public void setSpecialCharacter(boolean spec)
  364. {
  365. _props.setFSpec(spec);
  366. byte newVal = (byte)(spec ? 1 : 0);
  367. _chpx.updateSprm(SPRM_FSPEC, newVal);
  368. }
  369. public boolean isObj()
  370. {
  371. return _props.isFObj();
  372. }
  373. public void setObj(boolean obj)
  374. {
  375. _props.setFObj(obj);
  376. byte newVal = (byte)(obj ? 1 : 0);
  377. _chpx.updateSprm(SPRM_FOBJ, newVal);
  378. }
  379. public int getPicOffset()
  380. {
  381. return _props.getFcPic();
  382. }
  383. public void setPicOffset(int offset)
  384. {
  385. _props.setFcPic(offset);
  386. _chpx.updateSprm(SPRM_PICLOCATION, offset);
  387. }
  388. /**
  389. * Does the picture offset represent picture
  390. * or binary data?
  391. * If it's set, then the picture offset refers to
  392. * a NilPICFAndBinData structure, otherwise to a
  393. * PICFAndOfficeArtData
  394. */
  395. public boolean isData()
  396. {
  397. return _props.isFData();
  398. }
  399. public void setData(boolean data)
  400. {
  401. _props.setFData(data);
  402. byte newVal = (byte)(data ? 1 : 0);
  403. _chpx.updateSprm(SPRM_FOBJ, newVal);
  404. }
  405. public boolean isOle2()
  406. {
  407. return _props.isFOle2();
  408. }
  409. public void setOle2(boolean ole)
  410. {
  411. _props.setFOle2(ole);
  412. byte newVal = (byte)(ole ? 1 : 0);
  413. _chpx.updateSprm(SPRM_FOBJ, newVal);
  414. }
  415. public int getObjOffset()
  416. {
  417. return _props.getFcObj();
  418. }
  419. public void setObjOffset(int obj)
  420. {
  421. _props.setFcObj(obj);
  422. _chpx.updateSprm(SPRM_OBJLOCATION, obj);
  423. }
  424. /**
  425. * Get the ico24 field for the CHP record.
  426. */
  427. public int getIco24()
  428. {
  429. return _props.getIco24();
  430. }
  431. /**
  432. * Set the ico24 field for the CHP record.
  433. */
  434. public void setIco24(int colour24)
  435. {
  436. _props.setIco24(colour24);
  437. }
  438. /**
  439. * Used to create a deep copy of this object.
  440. *
  441. * @return A deep copy.
  442. */
  443. @Override
  444. @SuppressWarnings("squid:S2975")
  445. @Deprecated
  446. @Removal(version = "5.0.0")
  447. public CharacterRun clone() {
  448. return copy();
  449. }
  450. @Override
  451. public CharacterRun copy() {
  452. return new CharacterRun(this);
  453. }
  454. /**
  455. * Returns true, if the CharacterRun is a special character run containing a symbol, otherwise false.
  456. *
  457. * <p>In case of a symbol, the {@link #text()} method always returns a single character 0x0028, but word actually stores
  458. * the character in a different field. Use {@link #getSymbolCharacter()} to get that character and {@link #getSymbolFont()}
  459. * to determine its font.
  460. */
  461. public boolean isSymbol()
  462. {
  463. return isSpecialCharacter() && text().equals("\u0028");
  464. }
  465. /**
  466. * Returns the symbol character, if this is a symbol character run.
  467. *
  468. * @see #isSymbol()
  469. * @throws IllegalStateException If this is not a symbol character run: call {@link #isSymbol()} first.
  470. */
  471. public char getSymbolCharacter()
  472. {
  473. if (isSymbol()) {
  474. return (char)_props.getXchSym();
  475. } else
  476. throw new IllegalStateException("Not a symbol CharacterRun");
  477. }
  478. /**
  479. * Returns the symbol font, if this is a symbol character run. Might return null, if the font index is not found in the font table.
  480. *
  481. * @see #isSymbol()
  482. * @throws IllegalStateException If this is not a symbol character run: call {@link #isSymbol()} first.
  483. */
  484. public Ffn getSymbolFont()
  485. {
  486. if (isSymbol()) {
  487. if (_doc.getFontTable() == null)
  488. return null;
  489. // Fetch all font names
  490. Ffn[] fontNames = _doc.getFontTable().getFontNames();
  491. // Try to find the name of the font for our symbol
  492. if (fontNames.length <= _props.getFtcSym())
  493. return null;
  494. return fontNames[_props.getFtcSym()];
  495. } else
  496. throw new IllegalStateException("Not a symbol CharacterRun");
  497. }
  498. public BorderCode getBorder() {
  499. return _props.getBrc();
  500. }
  501. public int getLanguageCode() {
  502. return _props.getLidDefault();
  503. }
  504. /**
  505. * <p>Returns the index of the base style which applies to
  506. * this Run. Details of the style can be looked up
  507. * from the {@link StyleSheet}, via
  508. * {@link StyleSheet#getStyleDescription(int)}.</p>
  509. * <p>Note that runs typically override some of the style
  510. * properties from the base, so normally style information
  511. * should be fetched directly from the {@link CharacterRun}
  512. * itself.</p>
  513. */
  514. public short getStyleIndex() {
  515. return _istd;
  516. }
  517. public String toString() {
  518. String text = text();
  519. return "CharacterRun of " + text.length() + " characters - " + text;
  520. }
  521. public String[] getDropDownListValues()
  522. {
  523. if ( getDocument() instanceof HWPFDocument )
  524. {
  525. char c = _text.charAt( _start );
  526. if ( c == 0x01 )
  527. {
  528. NilPICFAndBinData data = new NilPICFAndBinData(
  529. ( (HWPFDocument) getDocument() ).getDataStream(),
  530. getPicOffset() );
  531. FFData ffData = new FFData( data.getBinData(), 0 );
  532. return ffData.getDropList();
  533. }
  534. }
  535. return null;
  536. }
  537. public Integer getDropDownListDefaultItemIndex()
  538. {
  539. if ( getDocument() instanceof HWPFDocument )
  540. {
  541. char c = _text.charAt( _start );
  542. if ( c == 0x01 )
  543. {
  544. NilPICFAndBinData data = new NilPICFAndBinData(
  545. ( (HWPFDocument) getDocument() ).getDataStream(),
  546. getPicOffset() );
  547. FFData ffData = new FFData( data.getBinData(), 0 );
  548. return Integer.valueOf( ffData.getDefaultDropDownItemIndex() );
  549. }
  550. }
  551. return null;
  552. }
  553. }