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