PrintConsumer.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. // Copyright (c) 2002 Per M.A. Bothner.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.lists;
  4. import gnu.kawa.io.OutPort;
  5. import java.io.*;
  6. import gnu.kawa.io.PrettyWriter;
  7. /** A Consumer that extends a PrintWriter. Useful for formatting. */
  8. public class PrintConsumer extends PrintWriter
  9. implements Appendable, XConsumer
  10. {
  11. protected boolean skipping;
  12. protected Consumer base;
  13. private static Writer dummyWriter = new ConsumerWriter(null);
  14. public PrintConsumer(Writer out) {
  15. this(out, false);
  16. }
  17. public PrintConsumer(Writer out, boolean autoFlush) {
  18. super(out==null ? dummyWriter : out, autoFlush);
  19. if (out == null) {
  20. this.lock = this;
  21. this.out = null;
  22. } else if (out instanceof Consumer)
  23. this.base = (Consumer) out;
  24. }
  25. public PrintConsumer(Consumer out, boolean autoFlush) {
  26. this(out instanceof Writer ? (Writer) out
  27. : new ConsumerWriter(out),
  28. autoFlush);
  29. this.base = out;
  30. }
  31. public PrintConsumer(OutputStream out, boolean autoFlush) {
  32. super(out, autoFlush);
  33. }
  34. public PrettyWriter getPrettyWriter() {
  35. PrintConsumer cur = this;
  36. for (;;) {
  37. if (cur instanceof PrettyWriter)
  38. return (PrettyWriter) cur;
  39. Writer next = cur.out;
  40. if (next instanceof PrintConsumer)
  41. cur = (PrintConsumer) next;
  42. else
  43. return null;
  44. }
  45. }
  46. protected void startNumber() {
  47. writeWordStart();
  48. }
  49. protected void endNumber() {
  50. writeWordEnd();
  51. }
  52. public PrintConsumer append (char c)
  53. {
  54. print(c);
  55. return this;
  56. }
  57. public PrintConsumer append (CharSequence csq)
  58. {
  59. if (csq == null)
  60. csq = "null";
  61. append(csq, 0, csq.length());
  62. return this;
  63. }
  64. public PrintConsumer append (CharSequence csq, int start, int end)
  65. {
  66. write(csq == null ? "null" : csq,
  67. start, end-start);
  68. return this;
  69. }
  70. public void write(CharSequence csq, int start, int length) {
  71. if (length == 0)
  72. csq = "";
  73. if (csq instanceof String)
  74. write((String) csq, start, length);
  75. else {
  76. synchronized (lock) {
  77. int end = start+length;
  78. for (int i = start; i < end; i++)
  79. write(csq.charAt(i));
  80. }
  81. }
  82. }
  83. public void freshLine() {
  84. if (base instanceof PrintConsumer)
  85. ((PrintConsumer) base).freshLine();
  86. }
  87. public void writeSpace(int kind) {
  88. write(' ');
  89. writeBreak(kind);
  90. }
  91. public void writeBreak(int kind) {
  92. if (base instanceof PrintConsumer)
  93. ((PrintConsumer) base).writeBreak(kind);
  94. }
  95. public static void writeBreakFill(Consumer out) {
  96. if (out instanceof PrintConsumer)
  97. ((PrintConsumer) out).writeBreakFill();
  98. }
  99. public void writeBreakFill() {
  100. writeBreak(PrettyWriter.NEWLINE_FILL);
  101. }
  102. public static void writeSpaceFill(Consumer out) {
  103. if (out instanceof PrintConsumer)
  104. ((PrintConsumer) out).writeSpaceFill();
  105. else
  106. out.write(' ');
  107. }
  108. public void writeSpaceFill() {
  109. writeSpace(PrettyWriter.NEWLINE_FILL);
  110. }
  111. public void writeSpaceLinear() {
  112. writeSpace(PrettyWriter.NEWLINE_LINEAR);
  113. }
  114. /** Write a new-line iff the containing section cannot be printed
  115. * on one line. Either all linear-style newlines in a logical
  116. * block becomes spaces (if it all fits in a line), or none
  117. * of them do. */
  118. public void writeBreakLinear() {
  119. writeBreak(PrettyWriter.NEWLINE_LINEAR);
  120. }
  121. public void setIndentation(int amount, boolean current) {
  122. if (base instanceof PrintConsumer)
  123. ((PrintConsumer) base).setIndentation(amount, current);
  124. }
  125. public boolean isDomTerm() { return false; }
  126. /** If supported (i.e. on DomTerm), "print" a show/hide button. */
  127. public void writeShowHideButton(boolean show) {
  128. if (base instanceof PrintConsumer
  129. && ((PrintConsumer) base).isDomTerm()) {
  130. String buttonChar = "\u25BC";
  131. writeRaw("\033[16u"+buttonChar+"\033[17u");
  132. }
  133. }
  134. /** Start section controled by a show/hide button.
  135. * Must be properly nested within/around logical blocks.
  136. * Current only supported on DomTerm. */
  137. public void startHiderSection(boolean show) {
  138. if (base instanceof PrintConsumer
  139. && ((PrintConsumer) base).isDomTerm()) {
  140. writeRaw(show ? "\033[83;1u" : "\033[83;2u");
  141. }
  142. }
  143. /** End section controled by a show/hide button */
  144. public void endHiderSection() {
  145. if (base instanceof PrintConsumer
  146. && ((PrintConsumer) base).isDomTerm()) {
  147. writeRaw("\033[83;0u");
  148. }
  149. }
  150. public static void startLogicalBlock(String prefix, boolean perLine,
  151. String suffix, Consumer out) {
  152. if (out instanceof PrintConsumer)
  153. ((PrintConsumer) out).startLogicalBlock(prefix, perLine, suffix);
  154. else
  155. out.write(prefix);
  156. }
  157. public void startLogicalBlock(String prefix, boolean perLine,
  158. String suffix) {
  159. if (base instanceof PrintConsumer)
  160. ((PrintConsumer) base).startLogicalBlock(prefix, perLine, suffix);
  161. else
  162. writeRaw(prefix);
  163. }
  164. public void startLogicalBlock(String prefix, String suffix,
  165. int indent) {
  166. if (base instanceof PrintConsumer)
  167. ((PrintConsumer) base).startLogicalBlock(prefix, suffix, indent);
  168. else
  169. writeRaw(prefix);
  170. }
  171. public static void endLogicalBlock(String suffix, Consumer out) {
  172. if (out instanceof PrintConsumer)
  173. ((PrintConsumer) out).endLogicalBlock(suffix);
  174. else
  175. out.write(suffix);
  176. }
  177. public void endLogicalBlock(String suffix) {
  178. if (base instanceof PrintConsumer)
  179. ((PrintConsumer) base).endLogicalBlock(suffix);
  180. else
  181. writeRaw(suffix);
  182. }
  183. protected void beforeContent() {
  184. }
  185. protected void beforeNode() {
  186. }
  187. public void writeWordStart() {
  188. if (out instanceof PrintConsumer)
  189. ((PrintConsumer) out).writeWordStart();
  190. }
  191. public void writeWordEnd() {
  192. if (out instanceof PrintConsumer)
  193. ((PrintConsumer) out).writeWordEnd();
  194. }
  195. protected void clearWordEnd() {
  196. if (out instanceof PrintConsumer)
  197. ((PrintConsumer) out).clearWordEnd();
  198. }
  199. public void writeBoolean(boolean v) {
  200. if (skipping)
  201. return;
  202. synchronized (lock) {
  203. writeWordStart();
  204. if (base != null)
  205. base.writeBoolean(v);
  206. else
  207. print(v);
  208. writeWordEnd();
  209. }
  210. }
  211. public void writeFloat(float v) {
  212. if (skipping)
  213. return;
  214. synchronized (lock) {
  215. startNumber();
  216. if (base != null)
  217. base.writeFloat(v);
  218. else
  219. print(v);
  220. endNumber();
  221. }
  222. }
  223. public void writeDouble(double v) {
  224. if (skipping)
  225. return;
  226. synchronized (lock) {
  227. startNumber();
  228. if (base != null)
  229. base.writeDouble(v);
  230. else
  231. print(v);
  232. endNumber();
  233. }
  234. }
  235. public void writeInt(int v) {
  236. if (skipping)
  237. return;
  238. synchronized (lock) {
  239. startNumber();
  240. if (base != null)
  241. base.writeInt(v);
  242. else
  243. print(v);
  244. endNumber();
  245. }
  246. }
  247. public void writeLong(long v) {
  248. if (skipping)
  249. return;
  250. synchronized (lock) {
  251. startNumber();
  252. if (base != null)
  253. base.writeLong(v);
  254. else
  255. print(v);
  256. endNumber();
  257. }
  258. }
  259. /*
  260. public void print(Object v) {
  261. if (out instanceof Consumer)
  262. ((Consumer) out).writeObject(v);
  263. else
  264. super.print(v);
  265. }
  266. */
  267. public void startDocument() {
  268. if (base != null && ! skipping)
  269. base.startDocument();
  270. }
  271. public void endDocument() {
  272. if (base != null && ! skipping)
  273. base.endDocument();
  274. }
  275. public void startElement(Object type) {
  276. if (base != null && ! skipping)
  277. base.startElement(type);
  278. }
  279. public void endElement() {
  280. if (base != null && ! skipping)
  281. base.endElement();
  282. }
  283. public void startAttribute (Object attrType) { }
  284. public void endAttribute() { }
  285. public void writeComment(char[] chars, int offset, int length) {
  286. if (skipping)
  287. return;
  288. beforeNode();
  289. if (base instanceof XConsumer)
  290. ((XConsumer) base).writeComment(chars, offset, length);
  291. }
  292. public void writeProcessingInstruction(String target, char[] content,
  293. int offset, int length) {
  294. if (skipping)
  295. return;
  296. beforeNode();
  297. if (base instanceof XConsumer)
  298. ((XConsumer) base)
  299. .writeProcessingInstruction(target, content, offset, length);
  300. }
  301. public void writeCDATA(char[] chars, int offset, int length) {
  302. beforeContent();
  303. if (skipping)
  304. return;
  305. if (base instanceof XConsumer)
  306. ((XConsumer) base).writeCDATA(chars, offset, length);
  307. else
  308. writeRaw(chars, offset, length);
  309. }
  310. public void beginEntity(Object baseUri) {
  311. if (skipping)
  312. return;
  313. beforeNode();
  314. if (base instanceof XConsumer)
  315. ((XConsumer) base).beginEntity(baseUri);
  316. }
  317. public void endEntity() {
  318. if (skipping)
  319. return;
  320. if (base instanceof XConsumer)
  321. ((XConsumer) base).endEntity();
  322. }
  323. protected void writeRaw(int v) {
  324. try {
  325. out.write(v);
  326. } catch (IOException ex) {
  327. setError();
  328. }
  329. }
  330. protected void writeRaw(String str) {
  331. try {
  332. out.write(str, 0, str.length());
  333. } catch (IOException ex) {
  334. setError();
  335. }
  336. }
  337. protected void writeRaw(String str, int start, int length) {
  338. try {
  339. out.write(str, start, length);
  340. } catch (IOException ex) {
  341. setError();
  342. }
  343. }
  344. protected void writeRaw(char[] chars, int start, int length) {
  345. try {
  346. out.write(chars, start, length);
  347. } catch (IOException ex) {
  348. setError();
  349. }
  350. }
  351. public void writeObject(Object v) {
  352. if (out instanceof Consumer)
  353. ((Consumer) out).writeObject(v);
  354. else
  355. print(v);
  356. }
  357. public boolean ignoring()
  358. {
  359. return false;
  360. }
  361. }