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