001 /** 002 * jline - Java console input library 003 * Copyright (c) 2002,2003 Marc Prud'hommeaux marc@apocalypse.org 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:marc@apocalypse.org">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 (String str) 043 { 044 append (str); 045 } 046 047 048 public void setAnsiEnabled (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 (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 (String str) 085 { 086 ansiBuffer.append (str); 087 plainBuffer.append (str); 088 return this; 089 } 090 091 092 public ANSIBuffer attrib (String str, 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 (String str) 104 { 105 return attrib (str, ANSICodes.FG_RED); 106 } 107 108 109 public ANSIBuffer blue (String str) 110 { 111 return attrib (str, ANSICodes.FG_BLUE); 112 } 113 114 115 public ANSIBuffer green (String str) 116 { 117 return attrib (str, ANSICodes.FG_GREEN); 118 } 119 120 121 public ANSIBuffer black (String str) 122 { 123 return attrib (str, ANSICodes.FG_BLACK); 124 } 125 126 127 public ANSIBuffer yellow (String str) 128 { 129 return attrib (str, ANSICodes.FG_YELLOW); 130 } 131 132 133 public ANSIBuffer magenta (String str) 134 { 135 return attrib (str, ANSICodes.FG_MAGENTA); 136 } 137 138 139 public ANSIBuffer cyan (String str) 140 { 141 return attrib (str, ANSICodes.FG_CYAN); 142 } 143 144 145 public ANSIBuffer bold (String str) 146 { 147 return attrib (str, ANSICodes.BOLD); 148 } 149 150 151 public ANSIBuffer underscore (String str) 152 { 153 return attrib (str, ANSICodes.UNDERSCORE); 154 } 155 156 157 public ANSIBuffer blink (String str) 158 { 159 return attrib (str, ANSICodes.BLINK); 160 } 161 162 163 public ANSIBuffer reverse (String str) 164 { 165 return attrib (str, ANSICodes.REVERSE); 166 } 167 168 169 170 public static class ANSICodes 171 { 172 public static int OFF = 0; 173 public static int BOLD = 1; 174 public static int UNDERSCORE = 4; 175 public static int BLINK = 5; 176 public static int REVERSE = 7; 177 public static int CONCEALED = 8; 178 179 public static int FG_BLACK = 30; 180 public static int FG_RED = 31; 181 public static int FG_GREEN = 32; 182 public static int FG_YELLOW = 33; 183 public static int FG_BLUE = 34; 184 public static int FG_MAGENTA = 35; 185 public static int FG_CYAN = 36; 186 public static int FG_WHITE = 37; 187 //---Constants------------------------------------------------ 188 public static char ESC = 27; 189 190 //---Static methods------------------------------------------- 191 /** 192 * Sets the screen mode to one of the following values: 193 * <pre> 194 * mode description 195 * ---------------------------------------- 196 * 0 40 x 148 x 25 monochrome (text) 197 * 1 40 x 148 x 25 color (text) 198 * 2 80 x 148 x 25 monochrome (text) 199 * 3 80 x 148 x 25 color (text) 200 * 4 320 x 148 x 200 4-color (graphics) 201 * 5 320 x 148 x 200 monochrome (graphics) 202 * 6 640 x 148 x 200 monochrome (graphics) 203 * 7 Enables line wrapping 204 * 13 320 x 148 x 200 color (graphics) 205 * 14 640 x 148 x 200 color (16-color graphics) 206 * 15 640 x 148 x 350 monochrome (2-color graphics) 207 * 16 640 x 148 x 350 color (16-color graphics) 208 * 17 640 x 148 x 480 monochrome (2-color graphics) 209 * 18 640 x 148 x 480 color (16-color graphics) 210 * 19 320 x 148 x 200 color (256-color graphics) 211 * </pre> 212 */ 213 public static String setmode (int mode) 214 { 215 return ESC + "[=" + mode + "h"; 216 } 217 218 /** 219 * Same as setmode () except for mode = 7, which disables line 220 * wrapping (useful for writing the right-most column without 221 * scrolling to the next line). 222 */ 223 public static String resetmode (int mode) 224 { 225 return ESC + "[=" + mode + "l"; 226 } 227 228 /** 229 * Clears the screen and moves the cursor to the home postition. 230 */ 231 public static String clrscr () 232 { 233 return ESC + "[2J"; 234 } 235 236 /** 237 * Removes all characters from the current cursor position until 238 * the end of the line. 239 */ 240 public static String clreol () 241 { 242 return ESC + "[K"; 243 } 244 245 /** 246 * Moves the cursor n positions to the left. If n is greater or 247 * equal to the current cursor column, the cursor is moved to the 248 * first column. 249 */ 250 public static String left (int n) 251 { 252 return ESC + "[" + n + "D"; 253 } 254 255 /** 256 * Moves the cursor n positions to the right. If n plus the current 257 * cursor column is greater than the rightmost column, the cursor 258 * is moved to the rightmost column. 259 */ 260 public static String right (int n) 261 { 262 return ESC + "[" + n + "C"; 263 } 264 265 /** 266 * Moves the cursor n rows up without changing the current column. 267 * If n is greater than or equal to the current row, the cursor is 268 * placed in the first row. 269 */ 270 public static String up (int n) 271 { 272 return ESC + "[" + n + "A"; 273 } 274 275 /** 276 * Moves the cursor n rows down. If n plus the current row is greater 277 * than the bottom row, the cursor is moved to the bottom row. 278 */ 279 public static String down (int n) 280 { 281 return ESC + "[" + n + "B"; 282 } 283 284 /* 285 * Moves the cursor to the given row and column. (1,1) represents 286 * the upper left corner. The lower right corner of a usual DOS 287 * screen is (25, 80). 288 */ 289 public static String gotoxy (int row, int column) 290 { 291 return ESC + "[" + row + ";" + column + "H"; 292 } 293 294 /** 295 * Saves the current cursor position. 296 */ 297 public static String save () 298 { 299 return ESC + "[s"; 300 } 301 302 /** 303 * Restores the saved cursor position. 304 */ 305 public static String restore () 306 { 307 return ESC + "[u"; 308 } 309 310 /** 311 * Sets one of the following character attributes: 312 * 313 * <pre> 314 * Text attributes 315 * 0 All attributes off 316 * 1 Bold on 317 * 4 Underscore (on monochrome display adapter only) 318 * 5 Blink on 319 * 7 Reverse video on 320 * 8 Concealed on 321 * 322 * Foreground colors 323 * 30 Black 324 * 31 Red 325 * 32 Green 326 * 33 Yellow 327 * 34 Blue 328 * 35 Magenta 329 * 36 Cyan 330 * 37 White 331 * 332 * Background colors 333 * 40 Black 334 * 41 Red 335 * 42 Green 336 * 43 Yellow 337 * 44 Blue 338 * 45 Magenta 339 * 46 Cyan 340 * 47 White 341 * </pre> 342 * 343 * The attributes remain in effect until the next attribute command 344 * is sent. 345 */ 346 public static String attrib (int attr) 347 { 348 return ESC + "[" + attr + "m"; 349 } 350 351 /** 352 * Sets the key with the given code to the given value. code must be 353 * derived from the following table, value must 354 * be any semicolon-separated 355 * combination of String (enclosed in double quotes) and numeric values. 356 * For example, to set F1 to the String "Hello F1", followed by a CRLF 357 * sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10"). 358 * Heres's the table of key values: 359 * <pre> 360 * Key Code SHIFT+code CTRL+code ALT+code 361 * --------------------------------------------------------------- 362 * F1 0;59 0;84 0;94 0;104 363 * F2 0;60 0;85 0;95 0;105 364 * F3 0;61 0;86 0;96 0;106 365 * F4 0;62 0;87 0;97 0;107 366 * F5 0;63 0;88 0;98 0;108 367 * F6 0;64 0;89 0;99 0;109 368 * F7 0;65 0;90 0;100 0;110 369 * F8 0;66 0;91 0;101 0;111 370 * F9 0;67 0;92 0;102 0;112 371 * F10 0;68 0;93 0;103 0;113 372 * F11 0;133 0;135 0;137 0;139 373 * F12 0;134 0;136 0;138 0;140 374 * HOME (num keypad) 0;71 55 0;119 -- 375 * UP ARROW (num keypad) 0;72 56 (0;141) -- 376 * PAGE UP (num keypad) 0;73 57 0;132 -- 377 * LEFT ARROW (num keypad) 0;75 52 0;115 -- 378 * RIGHT ARROW (num keypad) 0;77 54 0;116 -- 379 * END (num keypad) 0;79 49 0;117 -- 380 * DOWN ARROW (num keypad) 0;80 50 (0;145) -- 381 * PAGE DOWN (num keypad) 0;81 51 0;118 -- 382 * INSERT (num keypad) 0;82 48 (0;146) -- 383 * DELETE (num keypad) 0;83 46 (0;147) -- 384 * HOME (224;71) (224;71) (224;119) (224;151) 385 * UP ARROW (224;72) (224;72) (224;141) (224;152) 386 * PAGE UP (224;73) (224;73) (224;132) (224;153) 387 * LEFT ARROW (224;75) (224;75) (224;115) (224;155) 388 * RIGHT ARROW (224;77) (224;77) (224;116) (224;157) 389 * END (224;79) (224;79) (224;117) (224;159) 390 * DOWN ARROW (224;80) (224;80) (224;145) (224;154) 391 * PAGE DOWN (224;81) (224;81) (224;118) (224;161) 392 * INSERT (224;82) (224;82) (224;146) (224;162) 393 * DELETE (224;83) (224;83) (224;147) (224;163) 394 * PRINT SCREEN -- -- 0;114 -- 395 * PAUSE/BREAK -- -- 0;0 -- 396 * BACKSPACE 8 8 127 (0) 397 * ENTER 13 -- 10 (0 398 * TAB 9 0;15 (0;148) (0;165) 399 * NULL 0;3 -- -- -- 400 * A 97 65 1 0;30 401 * B 98 66 2 0;48 402 * C 99 66 3 0;46 403 * D 100 68 4 0;32 404 * E 101 69 5 0;18 405 * F 102 70 6 0;33 406 * G 103 71 7 0;34 407 * H 104 72 8 0;35 408 * I 105 73 9 0;23 409 * J 106 74 10 0;36 410 * K 107 75 11 0;37 411 * L 108 76 12 0;38 412 * M 109 77 13 0;50 413 * N 110 78 14 0;49 414 * O 111 79 15 0;24 415 * P 112 80 16 0;25 416 * Q 113 81 17 0;16 417 * R 114 82 18 0;19 418 * S 115 83 19 0;31 419 * T 116 84 20 0;20 420 * U 117 85 21 0;22 421 * V 118 86 22 0;47 422 * W 119 87 23 0;17 423 * X 120 88 24 0;45 424 * Y 121 89 25 0;21 425 * Z 122 90 26 0;44 426 * 1 49 33 -- 0;120 427 * 2 50 64 0 0;121 428 * 3 51 35 -- 0;122 429 * 4 52 36 -- 0;123 430 * 5 53 37 -- 0;124 431 * 6 54 94 30 0;125 432 * 7 55 38 -- 0;126 433 * 8 56 42 -- 0;126 434 * 9 57 40 -- 0;127 435 * 0 48 41 -- 0;129 436 * - 45 95 31 0;130 437 * = 61 43 --- 0;131 438 * [ 91 123 27 0;26 439 * ] 93 125 29 0;27 440 * 92 124 28 0;43 441 * ; 59 58 -- 0;39 442 * ' 39 34 -- 0;40 443 * , 44 60 -- 0;51 444 * . 46 62 -- 0;52 445 * / 47 63 -- 0;53 446 * ` 96 126 -- (0;41) 447 * ENTER (keypad) 13 -- 10 (0;166) 448 * / (keypad) 47 47 (0;142) (0;74) 449 * * (keypad) 42 (0;144) (0;78) -- 450 * - (keypad) 45 45 (0;149) (0;164) 451 * + (keypad) 43 43 (0;150) (0;55) 452 * 5 (keypad) (0;76) 53 (0;143) -- 453 */ 454 public static String setkey (String code, String value) 455 { 456 return ESC + "[" + code + ";" + value + "p"; 457 } 458 } 459 460 461 public static void main (String [] args) 462 throws Exception 463 { 464 // sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10"). 465 BufferedReader reader = new BufferedReader ( 466 new InputStreamReader (System.in)); 467 System.out.print (ANSICodes.setkey ("97", "97;98;99;13") 468 + ANSICodes.attrib (ANSICodes.OFF)); 469 System.out.flush (); 470 String line; 471 while ((line = reader.readLine ()) != null) 472 { 473 System.out.println ("GOT: " + line); 474 } 475 } 476 } 477