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