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