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