001: /*
002: * CharacterOutputStream.java
003: *
004: * Copyright (C) 2002-2003 Peter Graves
005: * $Id: CharacterOutputStream.java,v 1.7 2003/11/15 11:03:33 beedlem Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.lisp;
023:
024: import java.io.IOException;
025: import java.io.OutputStream;
026: import java.io.OutputStreamWriter;
027: import java.io.PrintWriter;
028: import java.io.StringWriter;
029: import java.io.Writer;
030:
031: public class CharacterOutputStream extends LispOutputStream {
032: private static final String lineSeparator = System
033: .getProperty("line.separator");
034:
035: private Writer writer;
036:
037: // The number of characters on the current line of output (-1 if unknown).
038: private int charPos;
039:
040: protected CharacterOutputStream() {
041: }
042:
043: public CharacterOutputStream(OutputStream out) {
044: writer = new OutputStreamWriter(out);
045: }
046:
047: protected void setWriter(Writer writer) {
048: this .writer = writer;
049: }
050:
051: public int getCharPos() {
052: return charPos;
053: }
054:
055: public void setCharPos(int n) {
056: charPos = n;
057: }
058:
059: public LispObject terpri() throws ConditionThrowable {
060: try {
061: writer.write(lineSeparator);
062: writer.flush();
063: charPos = 0;
064: } catch (IOException e) {
065: throw new ConditionThrowable(new StreamError(e));
066: }
067: return NIL;
068: }
069:
070: public LispObject freshLine() throws ConditionThrowable {
071: if (charPos == 0)
072: return NIL;
073: try {
074: writer.write(lineSeparator);
075: writer.flush();
076: charPos = 0;
077: } catch (IOException e) {
078: throw new ConditionThrowable(new StreamError(e));
079: }
080: return T;
081: }
082:
083: public void print(LispObject obj) throws ConditionThrowable {
084: try {
085: writer.write(String.valueOf(obj));
086: } catch (IOException e) {
087: throw new ConditionThrowable(new StreamError(e));
088: }
089: }
090:
091: public void print(char c) throws ConditionThrowable {
092: try {
093: writer.write(c);
094: if (c == '\n') {
095: writer.flush();
096: charPos = 0;
097: } else
098: ++charPos;
099: } catch (IOException e) {
100: throw new ConditionThrowable(new StreamError(e));
101: }
102: }
103:
104: // PRINC is just like PRIN1 except that the output has no escape
105: // characters. It binds *PRINT-ESCAPE* to false and *PRINT-READABLY* to
106: // false. The general rule is that output from PRINC is intended to look
107: // good to people, while output from PRIN1 is intended to be acceptable to
108: // READ.
109: public void princ(LispObject obj) throws ConditionThrowable {
110: LispThread thread = LispThread.currentThread();
111: Environment oldDynEnv = thread.getDynamicEnvironment();
112: thread.bindSpecial(_PRINT_ESCAPE_, NIL);
113: String s = String.valueOf(obj);
114: thread.setDynamicEnvironment(oldDynEnv);
115: try {
116: writer.write(s);
117: int index = s.lastIndexOf('\n');
118: if (index < 0)
119: charPos += s.length();
120: else
121: charPos = s.length() - (index + 1);
122: } catch (IOException e) {
123: throw new ConditionThrowable(new StreamError(e));
124: }
125: }
126:
127: // PRIN1 produces output suitable for input to READ.
128: // Binds *PRINT-ESCAPE* to true.
129: public void prin1(LispObject obj) throws ConditionThrowable {
130: String s = String.valueOf(obj);
131: try {
132: writer.write(s);
133: int index = s.lastIndexOf('\n');
134: if (index < 0)
135: charPos += s.length();
136: else
137: charPos = s.length() - (index + 1);
138: } catch (IOException e) {
139: throw new ConditionThrowable(new StreamError(e));
140: }
141: }
142:
143: public void writeChar(char c) throws ConditionThrowable {
144: try {
145: writer.write(c);
146: if (c == '\n') {
147: writer.flush();
148: charPos = 0;
149: } else
150: ++charPos;
151: } catch (IOException e) {
152: throw new ConditionThrowable(new StreamError(e));
153: }
154: }
155:
156: public void writeString(LispString string)
157: throws ConditionThrowable {
158: writeString(string.getValue());
159: }
160:
161: public void writeString(String s) throws ConditionThrowable {
162: try {
163: writer.write(s);
164: int index = s.lastIndexOf('\n');
165: if (index < 0)
166: charPos += s.length();
167: else {
168: charPos = s.length() - (index + 1);
169: writer.flush();
170: }
171: } catch (IOException e) {
172: throw new ConditionThrowable(new StreamError(e));
173: }
174: }
175:
176: public void writeLine(String s) throws ConditionThrowable {
177: try {
178: writer.write(s);
179: writer.write(lineSeparator);
180: writer.flush();
181: charPos = 0;
182: } catch (IOException e) {
183: throw new ConditionThrowable(new StreamError(e));
184: }
185: }
186:
187: public void printStackTrace(Throwable t) throws ConditionThrowable {
188: StringWriter sw = new StringWriter();
189: PrintWriter pw = new PrintWriter(sw);
190: t.printStackTrace(pw);
191: try {
192: writer.write(sw.toString());
193: writer.write(lineSeparator);
194: writer.flush();
195: charPos = 0;
196: } catch (IOException e) {
197: throw new ConditionThrowable(new StreamError(e));
198: }
199: }
200:
201: public void flushOutput() throws ConditionThrowable {
202: try {
203: writer.flush();
204: } catch (IOException e) {
205: throw new ConditionThrowable(new StreamError(e));
206: }
207: }
208:
209: // Returns true if stream was open, otherwise implementation-dependent.
210: public LispObject close(LispObject abort) throws ConditionThrowable {
211: try {
212: writer.close();
213: return T;
214: } catch (IOException e) {
215: throw new ConditionThrowable(new StreamError(e));
216: }
217: }
218:
219: public String toString() {
220: return unreadableString("STREAM [character output]");
221: }
222: }
|