001 /**
002 * jline - Java console input library
003 * Copyright (c) 2002,2003 Marc Prud'hommeaux mwp1@cornell.edu
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either
008 * version 2.1 of the License, or (at your option) any later version.
009 *
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 * Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public
016 * License along with this library; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018 */
019 package jline;
020
021 import java.io.*;
022 import java.util.*;
023
024
025 /**
026 * A buffer that can contain ANSI text.
027 *
028 * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
029 */
030 public class ANSIBuffer
031 {
032 private boolean ansiEnabled = true;
033 private final StringBuffer ansiBuffer = new StringBuffer ();
034 private final StringBuffer plainBuffer = new StringBuffer ();
035
036
037 public ANSIBuffer ()
038 {
039 }
040
041
042 public ANSIBuffer (final String str)
043 {
044 append (str);
045 }
046
047
048 public void setAnsiEnabled (final boolean ansi)
049 {
050 this.ansiEnabled = ansiEnabled;
051 }
052
053
054 public boolean getAnsiEnabled ()
055 {
056 return this.ansiEnabled;
057 }
058
059
060 public String getAnsiBuffer ()
061 {
062 return ansiBuffer.toString ();
063 }
064
065
066 public String getPlainBuffer ()
067 {
068 return plainBuffer.toString ();
069 }
070
071
072 public String toString (final boolean ansi)
073 {
074 return ansi ? getAnsiBuffer () : getPlainBuffer ();
075 }
076
077
078 public String toString ()
079 {
080 return toString (ansiEnabled);
081 }
082
083
084 public ANSIBuffer append (final String str)
085 {
086 ansiBuffer.append (str);
087 plainBuffer.append (str);
088 return this;
089 }
090
091
092 public ANSIBuffer attrib (final String str, final int code)
093 {
094 ansiBuffer.append (ANSICodes.attrib (code))
095 .append (str)
096 .append (ANSICodes.attrib (ANSICodes.OFF));
097 plainBuffer.append (str);
098
099 return this;
100 }
101
102
103 public ANSIBuffer red (final String str)
104 {
105 return attrib (str, ANSICodes.FG_RED);
106 }
107
108
109 public ANSIBuffer blue (final String str)
110 {
111 return attrib (str, ANSICodes.FG_BLUE);
112 }
113
114
115 public ANSIBuffer green (final String str)
116 {
117 return attrib (str, ANSICodes.FG_GREEN);
118 }
119
120
121 public ANSIBuffer black (final String str)
122 {
123 return attrib (str, ANSICodes.FG_BLACK);
124 }
125
126
127 public ANSIBuffer yellow (final String str)
128 {
129 return attrib (str, ANSICodes.FG_YELLOW);
130 }
131
132
133 public ANSIBuffer magenta (final String str)
134 {
135 return attrib (str, ANSICodes.FG_MAGENTA);
136 }
137
138
139 public ANSIBuffer cyan (final String str)
140 {
141 return attrib (str, ANSICodes.FG_CYAN);
142 }
143
144
145 public ANSIBuffer bold (final String str)
146 {
147 return attrib (str, ANSICodes.BOLD);
148 }
149
150
151 public ANSIBuffer underscore (final String str)
152 {
153 return attrib (str, ANSICodes.UNDERSCORE);
154 }
155
156
157 public ANSIBuffer blink (final String str)
158 {
159 return attrib (str, ANSICodes.BLINK);
160 }
161
162
163 public ANSIBuffer reverse (final String str)
164 {
165 return attrib (str, ANSICodes.REVERSE);
166 }
167
168
169
170 public static class ANSICodes
171 {
172 static final int OFF = 0;
173 static final int BOLD = 1;
174 static final int UNDERSCORE = 4;
175 static final int BLINK = 5;
176 static final int REVERSE = 7;
177 static final int CONCEALED = 8;
178
179 static final int FG_BLACK = 30;
180 static final int FG_RED = 31;
181 static final int FG_GREEN = 32;
182 static final int FG_YELLOW = 33;
183 static final int FG_BLUE = 34;
184 static final int FG_MAGENTA = 35;
185 static final int FG_CYAN = 36;
186 static final int FG_WHITE = 37;
187 static final char ESC = 27;
188
189
190
191 /**
192 * Constructor is private since this is a utility class.
193 */
194 private ANSICodes ()
195 {
196 }
197
198
199 /**
200 * Sets the screen mode. The mode will be one of the following values:
201 * <pre>
202 * mode description
203 * ----------------------------------------
204 * 0 40 x 148 x 25 monochrome (text)
205 * 1 40 x 148 x 25 color (text)
206 * 2 80 x 148 x 25 monochrome (text)
207 * 3 80 x 148 x 25 color (text)
208 * 4 320 x 148 x 200 4-color (graphics)
209 * 5 320 x 148 x 200 monochrome (graphics)
210 * 6 640 x 148 x 200 monochrome (graphics)
211 * 7 Enables line wrapping
212 * 13 320 x 148 x 200 color (graphics)
213 * 14 640 x 148 x 200 color (16-color graphics)
214 * 15 640 x 148 x 350 monochrome (2-color graphics)
215 * 16 640 x 148 x 350 color (16-color graphics)
216 * 17 640 x 148 x 480 monochrome (2-color graphics)
217 * 18 640 x 148 x 480 color (16-color graphics)
218 * 19 320 x 148 x 200 color (256-color graphics)
219 * </pre>
220 */
221 public static String setmode (final int mode)
222 {
223 return ESC + "[=" + mode + "h";
224 }
225
226 /**
227 * Same as setmode () except for mode = 7, which disables line
228 * wrapping (useful for writing the right-most column without
229 * scrolling to the next line).
230 */
231 public static String resetmode (final int mode)
232 {
233 return ESC + "[=" + mode + "l";
234 }
235
236 /**
237 * Clears the screen and moves the cursor to the home postition.
238 */
239 public static String clrscr ()
240 {
241 return ESC + "[2J";
242 }
243
244 /**
245 * Removes all characters from the current cursor position until
246 * the end of the line.
247 */
248 public static String clreol ()
249 {
250 return ESC + "[K";
251 }
252
253 /**
254 * Moves the cursor n positions to the left. If n is greater or
255 * equal to the current cursor column, the cursor is moved to the
256 * first column.
257 */
258 public static String left (final int n)
259 {
260 return ESC + "[" + n + "D";
261 }
262
263 /**
264 * Moves the cursor n positions to the right. If n plus the current
265 * cursor column is greater than the rightmost column, the cursor
266 * is moved to the rightmost column.
267 */
268 public static String right (final int n)
269 {
270 return ESC + "[" + n + "C";
271 }
272
273 /**
274 * Moves the cursor n rows up without changing the current column.
275 * If n is greater than or equal to the current row, the cursor is
276 * placed in the first row.
277 */
278 public static String up (final int n)
279 {
280 return ESC + "[" + n + "A";
281 }
282
283 /**
284 * Moves the cursor n rows down. If n plus the current row is greater
285 * than the bottom row, the cursor is moved to the bottom row.
286 */
287 public static String down (final int n)
288 {
289 return ESC + "[" + n + "B";
290 }
291
292 /*
293 * Moves the cursor to the given row and column. (1,1) represents
294 * the upper left corner. The lower right corner of a usual DOS
295 * screen is (25, 80).
296 */
297 public static String gotoxy (final int row, final int column)
298 {
299 return ESC + "[" + row + ";" + column + "H";
300 }
301
302 /**
303 * Saves the current cursor position.
304 */
305 public static String save ()
306 {
307 return ESC + "[s";
308 }
309
310 /**
311 * Restores the saved cursor position.
312 */
313 public static String restore ()
314 {
315 return ESC + "[u";
316 }
317
318 /**
319 * Sets the character attribute. It will be
320 * one of the following character attributes:
321 *
322 * <pre>
323 * Text attributes
324 * 0 All attributes off
325 * 1 Bold on
326 * 4 Underscore (on monochrome display adapter only)
327 * 5 Blink on
328 * 7 Reverse video on
329 * 8 Concealed on
330 *
331 * Foreground colors
332 * 30 Black
333 * 31 Red
334 * 32 Green
335 * 33 Yellow
336 * 34 Blue
337 * 35 Magenta
338 * 36 Cyan
339 * 37 White
340 *
341 * Background colors
342 * 40 Black
343 * 41 Red
344 * 42 Green
345 * 43 Yellow
346 * 44 Blue
347 * 45 Magenta
348 * 46 Cyan
349 * 47 White
350 * </pre>
351 *
352 * The attributes remain in effect until the next attribute command
353 * is sent.
354 */
355 public static String attrib (final int attr)
356 {
357 return ESC + "[" + attr + "m";
358 }
359
360 /**
361 * Sets the key with the given code to the given value. code must be
362 * derived from the following table, value must
363 * be any semicolon-separated
364 * combination of String (enclosed in double quotes) and numeric values.
365 * For example, to set F1 to the String "Hello F1", followed by a CRLF
366 * sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10").
367 * Heres's the table of key values:
368 * <pre>
369 * Key Code SHIFT+code CTRL+code ALT+code
370 * ---------------------------------------------------------------
371 * F1 0;59 0;84 0;94 0;104
372 * F2 0;60 0;85 0;95 0;105
373 * F3 0;61 0;86 0;96 0;106
374 * F4 0;62 0;87 0;97 0;107
375 * F5 0;63 0;88 0;98 0;108
376 * F6 0;64 0;89 0;99 0;109
377 * F7 0;65 0;90 0;100 0;110
378 * F8 0;66 0;91 0;101 0;111
379 * F9 0;67 0;92 0;102 0;112
380 * F10 0;68 0;93 0;103 0;113
381 * F11 0;133 0;135 0;137 0;139
382 * F12 0;134 0;136 0;138 0;140
383 * HOME (num keypad) 0;71 55 0;119 --
384 * UP ARROW (num keypad) 0;72 56 (0;141) --
385 * PAGE UP (num keypad) 0;73 57 0;132 --
386 * LEFT ARROW (num keypad) 0;75 52 0;115 --
387 * RIGHT ARROW (num keypad) 0;77 54 0;116 --
388 * END (num keypad) 0;79 49 0;117 --
389 * DOWN ARROW (num keypad) 0;80 50 (0;145) --
390 * PAGE DOWN (num keypad) 0;81 51 0;118 --
391 * INSERT (num keypad) 0;82 48 (0;146) --
392 * DELETE (num keypad) 0;83 46 (0;147) --
393 * HOME (224;71) (224;71) (224;119) (224;151)
394 * UP ARROW (224;72) (224;72) (224;141) (224;152)
395 * PAGE UP (224;73) (224;73) (224;132) (224;153)
396 * LEFT ARROW (224;75) (224;75) (224;115) (224;155)
397 * RIGHT ARROW (224;77) (224;77) (224;116) (224;157)
398 * END (224;79) (224;79) (224;117) (224;159)
399 * DOWN ARROW (224;80) (224;80) (224;145) (224;154)
400 * PAGE DOWN (224;81) (224;81) (224;118) (224;161)
401 * INSERT (224;82) (224;82) (224;146) (224;162)
402 * DELETE (224;83) (224;83) (224;147) (224;163)
403 * PRINT SCREEN -- -- 0;114 --
404 * PAUSE/BREAK -- -- 0;0 --
405 * BACKSPACE 8 8 127 (0)
406 * ENTER 13 -- 10 (0
407 * TAB 9 0;15 (0;148) (0;165)
408 * NULL 0;3 -- -- --
409 * A 97 65 1 0;30
410 * B 98 66 2 0;48
411 * C 99 66 3 0;46
412 * D 100 68 4 0;32
413 * E 101 69 5 0;18
414 * F 102 70 6 0;33
415 * G 103 71 7 0;34
416 * H 104 72 8 0;35
417 * I 105 73 9 0;23
418 * J 106 74 10 0;36
419 * K 107 75 11 0;37
420 * L 108 76 12 0;38
421 * M 109 77 13 0;50
422 * N 110 78 14 0;49
423 * O 111 79 15 0;24
424 * P 112 80 16 0;25
425 * Q 113 81 17 0;16
426 * R 114 82 18 0;19
427 * S 115 83 19 0;31
428 * T 116 84 20 0;20
429 * U 117 85 21 0;22
430 * V 118 86 22 0;47
431 * W 119 87 23 0;17
432 * X 120 88 24 0;45
433 * Y 121 89 25 0;21
434 * Z 122 90 26 0;44
435 * 1 49 33 -- 0;120
436 * 2 50 64 0 0;121
437 * 3 51 35 -- 0;122
438 * 4 52 36 -- 0;123
439 * 5 53 37 -- 0;124
440 * 6 54 94 30 0;125
441 * 7 55 38 -- 0;126
442 * 8 56 42 -- 0;126
443 * 9 57 40 -- 0;127
444 * 0 48 41 -- 0;129
445 * - 45 95 31 0;130
446 * = 61 43 --- 0;131
447 * [ 91 123 27 0;26
448 * ] 93 125 29 0;27
449 * 92 124 28 0;43
450 * ; 59 58 -- 0;39
451 * ' 39 34 -- 0;40
452 * , 44 60 -- 0;51
453 * . 46 62 -- 0;52
454 * / 47 63 -- 0;53
455 * ` 96 126 -- (0;41)
456 * ENTER (keypad) 13 -- 10 (0;166)
457 * / (keypad) 47 47 (0;142) (0;74)
458 * * (keypad) 42 (0;144) (0;78) --
459 * - (keypad) 45 45 (0;149) (0;164)
460 * + (keypad) 43 43 (0;150) (0;55)
461 * 5 (keypad) (0;76) 53 (0;143) --
462 */
463 public static String setkey (final String code, final String value)
464 {
465 return ESC + "[" + code + ";" + value + "p";
466 }
467 }
468
469
470 public static void main (final String [] args)
471 throws Exception
472 {
473 // sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10").
474 BufferedReader reader = new BufferedReader (
475 new InputStreamReader (System.in));
476 System.out.print (ANSICodes.setkey ("97", "97;98;99;13")
477 + ANSICodes.attrib (ANSICodes.OFF));
478 System.out.flush ();
479 String line;
480 while ((line = reader.readLine ()) != null)
481 {
482 System.out.println ("GOT: " + line);
483 }
484 }
485 }
486