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 */
007package jline;
008
009import 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 */
016public 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)
061                  .append(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, final String value) {
387            return ESC + "[" + code + ";" + value + "p";
388        }
389    }
390
391    public static void main(final String[] args) throws Exception {
392        // sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10").
393        BufferedReader reader =
394            new BufferedReader(new InputStreamReader(System.in));
395        System.out.print(ANSICodes.setkey("97", "97;98;99;13")
396                         + ANSICodes.attrib(ANSICodes.OFF));
397        System.out.flush();
398
399        String line;
400
401        while ((line = reader.readLine()) != null) {
402            System.out.println("GOT: " + line);
403        }
404    }
405}