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