KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > jemacs > buffer > BufferWriter


1 package gnu.jemacs.buffer;
2 import java.awt.Color JavaDoc;
3
4 /** A Writer that writes at a Buffer's point or a Marker. */
5
6 public class BufferWriter extends java.io.Writer JavaDoc implements Runnable JavaDoc
7 {
8   Marker marker;
9   Object JavaDoc style;
10   Object JavaDoc stylePlain;
11   boolean adjustPoint;
12
13   /** We are not handling escape sequences. */
14   static final int NO_ESCAPES_STATE = 1;
15   /** We are ready to handle escape sequences. */
16   static final int NORMAL_STATE = 0;
17   /** Last character was a graphic in the last column.
18    * If next char is graphic, first move one column right
19    * (and line warp) before displaying it. */

20   static final int LAST_COLUMN_STATE = 1;
21   /** Seen an Escape character. */
22   static final int SEEN_ESC_STATE = 2;
23   /** We're in the middle of an escape sequence.
24    * What we've seen so far is in the savedOutput buffer. */

25   static final int SEEN_ESC_LBRAC_STATE = 3;
26   static final int SEEN_ESC_RBRAC_STATE = 4;
27   int state = NORMAL_STATE;
28
29   static final int ESC = 033;
30
31   boolean insertMode = false;
32
33   char[] savedOutput;
34   int savedCount;
35
36   public BufferWriter (Marker marker, boolean adjustPoint)
37   {
38     this.marker = marker;
39     EToolkit toolkit = EToolkit.getInstance();
40     this.stylePlain = toolkit.getFace("output", true);
41     this.style = stylePlain;
42     this.adjustPoint = adjustPoint;
43     // StyleConstants.setItalic(this.style, true);
44
}
45
46   public BufferWriter (Buffer buffer)
47   {
48     this(buffer.pointMarker, false);
49   }
50
51   boolean bold = false;
52   boolean underline = false;
53   boolean blink = false; // not implemented
54
boolean inverse;
55   boolean invisible;
56   String JavaDoc foregroundName;
57   String JavaDoc backgroundName;
58   Color JavaDoc foreground;
59   Color JavaDoc background;
60   StringBuffer JavaDoc styleNameBuf;
61   String JavaDoc styleName;
62
63   void resetAttributes()
64   {
65     bold = false;
66     underline = false;
67     blink = false;
68     inverse = false;
69     invisible = false;
70     foregroundName = null;
71     backgroundName = null;
72     foreground = null;
73     background = null;
74   }
75
76   void updateStyle()
77   {
78     if (styleNameBuf == null)
79       styleNameBuf = new StringBuffer JavaDoc(60);
80     styleNameBuf.setLength(0);
81     if (underline) styleNameBuf.append("underlined,");
82     if (bold) styleNameBuf.append("bold,");
83     if (foreground != null)
84       {
85     styleNameBuf.append("fg=");
86     styleNameBuf.append(foregroundName != null ? foregroundName
87                 : foreground.toString());
88     styleNameBuf.append(',');
89       }
90     if (background != null)
91       {
92     styleNameBuf.append("bg=");
93     styleNameBuf.append(backgroundName != null ? backgroundName
94                 : background.toString());
95     styleNameBuf.append(',');
96       }
97     int slen = styleNameBuf.length();
98     if (slen == 0)
99       {
100     style = stylePlain;
101     styleName = "output";
102     return;
103       }
104     styleNameBuf.setLength(slen-1); // Remove final comma.
105
styleName = styleNameBuf.toString();
106     EToolkit toolkit = EToolkit.getInstance();
107     style = toolkit.getFace(styleName, false);
108     if (style != null)
109       return;
110     style = toolkit.getFace(styleName, true);
111     toolkit.setUnderline(style, underline);
112     toolkit.setBold(style, bold);
113     if (foreground != null)
114       toolkit.setForeground(style, foreground);
115     if (background != null)
116       toolkit.setBackground(style, background);
117   }
118
119   private String JavaDoc name;
120   private Color JavaDoc color;
121   private void getColor(int index, boolean bright /*ignored, for now*/)
122   {
123     switch (index)
124       {
125       case 0: color = Color.black; name = "black"; break;
126       case 1: color = Color.red; name = "red"; break;
127       case 2: color = Color.green; name = "green"; break;
128       case 3: color = Color.yellow; name = "yellow"; break;
129       case 4: color = Color.blue; name = "blue"; break;
130       case 5: color = Color.magenta; name = "magenta"; break;
131       case 6: color = Color.cyan; name = "cyan"; break;
132       case 7: color = Color.white; name = "white"; break;
133       default: color = null; name = null;
134       }
135   }
136
137   /**
138    * Process an SGR command with the given code.
139    * @param param parameter value from the escape sequence
140    * @param position following offset in savedOutput array
141    * @return updated value of position, if we gobble multiple parameters
142    */

143   public int handleSetCharacterRendition(int param, int position)
144   {
145     switch (param)
146       {
147       case -1: case 0:
148     resetAttributes();
149       case 1:
150     bold = true;
151     break;
152       case 4:
153     underline = true;
154     break;
155       case 22:
156     bold = false;
157     break;
158       case 24:
159     underline = false;
160     break;
161       default:
162     if (param >= 30 && param <= 39)
163       {
164         getColor(param - 30, false);
165         foreground = color;
166         foregroundName = name;
167       }
168     else if (param >= 40 && param <= 49)
169       {
170         getColor(param - 40, false);
171         background = color;
172         backgroundName = name;
173       }
174     else if (param >= 90 && param <= 97)
175       {
176         getColor(param - 90, true);
177         background = color;
178         backgroundName = name;
179       }
180     else if (param >= 100 && param <= 107)
181       {
182         getColor(param - 100, true);
183         background = color;
184         backgroundName = name;
185       }
186     // else ignore
187
}
188     return position;
189   }
190
191   public void handleOperatingSystemCommand(char ch)
192   {
193     if (ch == '\007') /* BEL */
194       {
195     // ignore, for now
196
state = NORMAL_STATE;
197       }
198     else if (savedCount >= savedOutput.length)
199       {
200     // Seems rather excessive ... Probably error.
201
int i;
202     for (i = 0; i < savedCount && savedOutput[i] != '\n';) i++;
203     if (i < savedCount || ch == '\n')
204       state = NORMAL_STATE; // Seen '\n' - OK time to bail.
205
else
206       savedCount = 0; // No '\n' yet - drop what we've seen so far.
207
}
208     else
209       savedOutput[savedCount++] = ch;
210   }
211
212   /**
213    * Process a single command following CSI.
214    * CSI is "Control Sequence Introducer" - i.e. ESC [.
215    * @param ch the control command
216    * @param param parameter value from the escape sequence
217    * @param position following offset in savedOutput array
218    * @return updated value of position, if we gobble multiple parameters
219    */

220   public int handleCSICommand(char ch, int param, int position)
221   {
222     switch (ch)
223       {
224       case 'C': // \E[C - cursor right
225
moveColumns(param > 0 ? param : 1);
226     break;
227       case 'D': // \E[D - cursor left
228
moveColumns(- (param > 0 ? param : 1));
229     break;
230       case 'h': // \E[?h - DEC Private Mode Set
231
if (param == 4)
232       insertMode = true;
233     break;
234       case 'l': // \E[?l - DEC Private Mode Reset
235
if (param == 4)
236       insertMode = false;
237     break;
238       case 'm':
239     return handleSetCharacterRendition(param, position);
240       }
241     return position;
242   }
243
244   public void handleEscapeBracket(char ch)
245   {
246     if (ch == ';' || (ch >= '0' && ch <= '9'))
247       {
248     if (savedCount >= savedOutput.length)
249       savedCount = 0; // Overflow - drop excess parameters.
250
savedOutput[savedCount++] = ch;
251       }
252     else
253       {
254     int value = -1;
255     for (int i = 0; i < savedCount; i++)
256       {
257         ch = savedOutput[i];
258         if (ch >= '0' && ch <= '9')
259           value = (value <= 0 ? 0 : 10 * value) + (ch - '0');
260         else
261           {
262         i = handleCSICommand('m', value, i);
263         value = -1;
264           }
265       }
266     handleCSICommand('m', value, savedCount);
267     updateStyle();
268     state = NORMAL_STATE;
269       }
270   }
271
272   public void unTabifyRestOfLine()
273   {
274     // FIXME
275
}
276
277   /** Delete characters - but only in current screen line. */
278   public void removeChars(int count)
279   {
280     int save = marker.getOffset();
281     moveColumns(count);
282     marker.removeChar(marker.getOffset() - save);
283   }
284
285   /** Move some number of columns right (or left if count < 0). */
286   public void moveColumns(int count)
287   {
288     marker.moveToColumn(marker.currentColumn() + count, true);
289   }
290
291   /*
292   public synchronized void put(int x)
293   {
294     if (insertMode)
295       unTabifyRestOfLine();
296     else if (marker.getOffset() < marker.buffer.maxDot())
297       removeChars(1);
298     AbstractDocument document = marker.buffer;
299     boolean mustAdjustPoint
300       = adjustPoint && marker.getOffset() == marker.buffer.getDot();
301     marker.insert((char) x, 1, x == '\n' ? stylePlain : style);
302     if (mustAdjustPoint)
303       marker.buffer.setDot(marker.getOffset());
304   }
305   */

306
307   public synchronized void put (char[] data, int off, int len)
308   {
309     if (len == 0)
310       return;
311     if (insertMode)
312       unTabifyRestOfLine();
313     else
314       removeChars(len);
315     boolean mustAdjustPoint
316       = adjustPoint && marker.getOffset() == marker.buffer.getDot();
317     marker.insert(new String JavaDoc(data, off, len), style);
318     if (mustAdjustPoint)
319       marker.buffer.setDot(marker.getOffset());
320   }
321
322   char[] buf1 = new char[1];
323
324   public synchronized void write(int ch)
325   {
326     boolean move = marker.getOffset() == marker.buffer.getDot();
327     write1(ch);
328     if (move) marker.buffer.setDot(marker.getOffset());
329   }
330
331   public synchronized void write1(int ch)
332   {
333     if (state <= NORMAL_STATE)
334       {
335     if (ch >= ' ' || ch == '\n' || state < NORMAL_STATE)
336       {
337         buf1[0] = (char) ch;
338         put(buf1, 0, 1);
339       }
340     else if (ch == ESC)
341       state = SEEN_ESC_STATE;
342     else if (ch == '\b')
343       moveColumns(-1);
344     else if (ch == '\t')
345       {
346         int col = marker.currentColumn();
347         marker.moveToColumn(col + 8 - (col & 7), true);
348       }
349     else if (ch == '\r')
350       {
351         // FIXME - until we handle '\n' more generally.
352
// marker.moveToColumn(0, false);
353
}
354     else
355       System.err.println("received ctrl-"+(char)(ch+64));
356       }
357     else if (state == SEEN_ESC_STATE)
358       {
359     switch (ch)
360       {
361       case '[':
362         state = SEEN_ESC_LBRAC_STATE;
363         if (savedOutput == null)
364           savedOutput = new char[100];
365         savedCount = 0;
366         break;
367       case ']':
368         state = SEEN_ESC_RBRAC_STATE;
369         if (savedOutput == null)
370           savedOutput = new char[100];
371         savedCount = 0;
372         break;
373       default:
374         state = NORMAL_STATE;
375         break;
376       }
377       }
378     else if (state == SEEN_ESC_LBRAC_STATE)
379       {
380     handleEscapeBracket((char) ch);
381       }
382     else /* if (state == SEEN_ESC_RBRAC_STATE) */
383       {
384     handleOperatingSystemCommand((char) ch);
385       }
386   }
387
388   public synchronized void write (char[] data, int off, int len)
389   {
390     boolean move = marker.getOffset() == marker.buffer.getDot();
391     while (len > 0)
392       {
393     if (state > NORMAL_STATE)
394       {
395         write1(data[off++]);
396         len--;
397       }
398     else
399       {
400         int i;
401         if (state == NO_ESCAPES_STATE)
402           i = len;
403         else
404           {
405         for (i = 0; i < len; i++)
406           {
407             char ch = data[off+i];
408             if (ch < ' ')
409               break;
410           }
411           }
412         if (i > 0)
413           {
414         put(data, off, i);
415         off += i;
416         len -= i;
417           }
418         if (i < len)
419           {
420         write1(data[off++]);
421         len--;
422           }
423       }
424       }
425     if (move) marker.buffer.setDot(marker.getOffset());
426   }
427
428   public synchronized void flush()
429   {
430   }
431
432   public synchronized void close()
433   {
434   }
435
436   char[] buffer;
437   int count;
438   public void run()
439   {
440     write(buffer, 0, count);
441   }
442 }
443
Popular Tags