Source Code Cross Referenced for WindowsTerminal.java in  » Development » jLine » jline » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » jLine » jline 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:        import jline.UnixTerminal.ReplayPrefixOneCharInputStream;
012:
013:        /**
014:         * <p>
015:         * Terminal implementation for Microsoft Windows. Terminal initialization in
016:         * {@link #initializeTerminal} is accomplished by extracting the
017:         * <em>jline_<i>version</i>.dll</em>, saving it to the system temporary
018:         * directoy (determined by the setting of the <em>java.io.tmpdir</em> System
019:         * property), loading the library, and then calling the Win32 APIs <a
020:         * href="http://msdn.microsoft.com/library/default.asp?
021:         * url=/library/en-us/dllproc/base/setconsolemode.asp">SetConsoleMode</a> and
022:         * <a href="http://msdn.microsoft.com/library/default.asp?
023:         * url=/library/en-us/dllproc/base/getconsolemode.asp">GetConsoleMode</a> to
024:         * disable character echoing.
025:         * </p>
026:         *
027:         * <p>
028:         * By default, the {@link #readCharacter} method will attempt to test to see if
029:         * the specified {@link InputStream} is {@link System#in} or a wrapper around
030:         * {@link FileDescriptor#in}, and if so, will bypass the character reading to
031:         * directly invoke the readc() method in the JNI library. This is so the class
032:         * can read special keys (like arrow keys) which are otherwise inaccessible via
033:         * the {@link System#in} stream. Using JNI reading can be bypassed by setting
034:         * the <code>jline.WindowsTerminal.disableDirectConsole</code> system property
035:         * to <code>true</code>.
036:         * </p>
037:         *
038:         * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
039:         */
040:        public class WindowsTerminal extends Terminal {
041:            // constants copied from wincon.h
042:
043:            /**
044:             * The ReadFile or ReadConsole function returns only when a carriage return
045:             * character is read. If this mode is disable, the functions return when one
046:             * or more characters are available.
047:             */
048:            private static final int ENABLE_LINE_INPUT = 2;
049:
050:            /**
051:             * Characters read by the ReadFile or ReadConsole function are written to
052:             * the active screen buffer as they are read. This mode can be used only if
053:             * the ENABLE_LINE_INPUT mode is also enabled.
054:             */
055:            private static final int ENABLE_ECHO_INPUT = 4;
056:
057:            /**
058:             * CTRL+C is processed by the system and is not placed in the input buffer.
059:             * If the input buffer is being read by ReadFile or ReadConsole, other
060:             * control keys are processed by the system and are not returned in the
061:             * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also
062:             * enabled, backspace, carriage return, and linefeed characters are handled
063:             * by the system.
064:             */
065:            private static final int ENABLE_PROCESSED_INPUT = 1;
066:
067:            /**
068:             * User interactions that change the size of the console screen buffer are
069:             * reported in the console's input buffee. Information about these events
070:             * can be read from the input buffer by applications using
071:             * theReadConsoleInput function, but not by those using ReadFile
072:             * orReadConsole.
073:             */
074:            private static final int ENABLE_WINDOW_INPUT = 8;
075:
076:            /**
077:             * If the mouse pointer is within the borders of the console window and the
078:             * window has the keyboard focus, mouse events generated by mouse movement
079:             * and button presses are placed in the input buffer. These events are
080:             * discarded by ReadFile or ReadConsole, even when this mode is enabled.
081:             */
082:            private static final int ENABLE_MOUSE_INPUT = 16;
083:
084:            /**
085:             * When enabled, text entered in a console window will be inserted at the
086:             * current cursor location and all text following that location will not be
087:             * overwritten. When disabled, all following text will be overwritten. An OR
088:             * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS
089:             * flag to enable this functionality.
090:             */
091:            private static final int ENABLE_PROCESSED_OUTPUT = 1;
092:
093:            /**
094:             * This flag enables the user to use the mouse to select and edit text. To
095:             * enable this option, use the OR to combine this flag with
096:             * ENABLE_EXTENDED_FLAGS.
097:             */
098:            private static final int ENABLE_WRAP_AT_EOL_OUTPUT = 2;
099:
100:            /**
101:             * On windows terminals, this character indicates that a 'special' key has
102:             * been pressed. This means that a key such as an arrow key, or delete, or
103:             * home, etc. will be indicated by the next character.
104:             */
105:            public static final int SPECIAL_KEY_INDICATOR = 224;
106:
107:            /**
108:             * On windows terminals, this character indicates that a special key on the
109:             * number pad has been pressed.
110:             */
111:            public static final int NUMPAD_KEY_INDICATOR = 0;
112:
113:            /**
114:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR,
115:             * this character indicates an left arrow key press.
116:             */
117:            public static final int LEFT_ARROW_KEY = 75;
118:
119:            /**
120:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
121:             * this character indicates an
122:             * right arrow key press.
123:             */
124:            public static final int RIGHT_ARROW_KEY = 77;
125:
126:            /**
127:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
128:             * this character indicates an up
129:             * arrow key press.
130:             */
131:            public static final int UP_ARROW_KEY = 72;
132:
133:            /**
134:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
135:             * this character indicates an
136:             * down arrow key press.
137:             */
138:            public static final int DOWN_ARROW_KEY = 80;
139:
140:            /**
141:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
142:             * this character indicates that
143:             * the delete key was pressed.
144:             */
145:            public static final int DELETE_KEY = 83;
146:
147:            /**
148:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
149:             * this character indicates that
150:             * the home key was pressed.
151:             */
152:            public static final int HOME_KEY = 71;
153:
154:            /**
155:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
156:             * this character indicates that
157:             * the end key was pressed.
158:             */
159:            public static final char END_KEY = 79;
160:
161:            /**
162:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
163:             * this character indicates that
164:             * the page up key was pressed.
165:             */
166:            public static final char PAGE_UP_KEY = 73;
167:
168:            /**
169:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
170:             * this character indicates that
171:             * the page down key was pressed.
172:             */
173:            public static final char PAGE_DOWN_KEY = 81;
174:
175:            /**
176:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR
177:             * this character indicates that
178:             * the insert key was pressed.
179:             */
180:            public static final char INSERT_KEY = 82;
181:
182:            /**
183:             * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR,
184:             * this character indicates that the escape key was pressed.
185:             */
186:            public static final char ESCAPE_KEY = 0;
187:
188:            private Boolean directConsole;
189:
190:            private boolean echoEnabled;
191:
192:            String encoding = System.getProperty(
193:                    "jline.WindowsTerminal.input.encoding", System
194:                            .getProperty("file.encoding"));
195:            ReplayPrefixOneCharInputStream replayStream = new ReplayPrefixOneCharInputStream(
196:                    encoding);
197:            InputStreamReader replayReader;
198:
199:            public WindowsTerminal() {
200:                String dir = System
201:                        .getProperty("jline.WindowsTerminal.directConsole");
202:
203:                if ("true".equals(dir)) {
204:                    directConsole = Boolean.TRUE;
205:                } else if ("false".equals(dir)) {
206:                    directConsole = Boolean.FALSE;
207:                }
208:
209:                try {
210:                    replayReader = new InputStreamReader(replayStream, encoding);
211:                } catch (Exception e) {
212:                    throw new RuntimeException(e);
213:                }
214:
215:            }
216:
217:            private native int getConsoleMode();
218:
219:            private native void setConsoleMode(final int mode);
220:
221:            private native int readByte();
222:
223:            private native int getWindowsTerminalWidth();
224:
225:            private native int getWindowsTerminalHeight();
226:
227:            public int readCharacter(final InputStream in) throws IOException {
228:                // if we can detect that we are directly wrapping the system
229:                // input, then bypass the input stream and read directly (which
230:                // allows us to access otherwise unreadable strokes, such as
231:                // the arrow keys)
232:                if (directConsole == Boolean.FALSE) {
233:                    return super .readCharacter(in);
234:                } else if ((directConsole == Boolean.TRUE)
235:                        || ((in == System.in) || (in instanceof  FileInputStream && (((FileInputStream) in)
236:                                .getFD() == FileDescriptor.in)))) {
237:                    return readByte();
238:                } else {
239:                    return super .readCharacter(in);
240:                }
241:            }
242:
243:            public void initializeTerminal() throws Exception {
244:                loadLibrary("jline");
245:
246:                final int originalMode = getConsoleMode();
247:
248:                setConsoleMode(originalMode & ~ENABLE_ECHO_INPUT);
249:
250:                // set the console to raw mode
251:                int newMode = originalMode
252:                        & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT
253:                                | ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT);
254:                echoEnabled = false;
255:                setConsoleMode(newMode);
256:
257:                // at exit, restore the original tty configuration (for JDK 1.3+)
258:                try {
259:                    Runtime.getRuntime().addShutdownHook(new Thread() {
260:                        public void start() {
261:                            // restore the old console mode
262:                            setConsoleMode(originalMode);
263:                        }
264:                    });
265:                } catch (AbstractMethodError ame) {
266:                    // JDK 1.3+ only method. Bummer.
267:                    consumeException(ame);
268:                }
269:            }
270:
271:            private void loadLibrary(final String name) throws IOException {
272:                // store the DLL in the temporary directory for the System
273:                String version = getClass().getPackage()
274:                        .getImplementationVersion();
275:
276:                if (version == null) {
277:                    version = "";
278:                }
279:
280:                version = version.replace('.', '_');
281:
282:                File f = new File(System.getProperty("java.io.tmpdir"), name
283:                        + "_" + version + ".dll");
284:                boolean exists = f.isFile(); // check if it already exists
285:
286:                // extract the embedded jline.dll file from the jar and save
287:                // it to the current directory
288:                int bits = 32;
289:
290:                // check for 64-bit systems and use to appropriate DLL
291:                if (System.getProperty("os.arch").indexOf("64") != -1)
292:                    bits = 64;
293:
294:                InputStream in = new BufferedInputStream(getClass()
295:                        .getResourceAsStream(name + bits + ".dll"));
296:
297:                try {
298:                    OutputStream fout = new BufferedOutputStream(
299:                            new FileOutputStream(f));
300:                    byte[] bytes = new byte[1024 * 10];
301:
302:                    for (int n = 0; n != -1; n = in.read(bytes)) {
303:                        fout.write(bytes, 0, n);
304:                    }
305:
306:                    fout.close();
307:                } catch (IOException ioe) {
308:                    // We might get an IOException trying to overwrite an existing
309:                    // jline.dll file if there is another process using the DLL.
310:                    // If this happens, ignore errors.
311:                    if (!exists) {
312:                        throw ioe;
313:                    }
314:                }
315:
316:                // try to clean up the DLL after the JVM exits
317:                f.deleteOnExit();
318:
319:                // now actually load the DLL
320:                System.load(f.getAbsolutePath());
321:            }
322:
323:            public int readVirtualKey(InputStream in) throws IOException {
324:                int indicator = readCharacter(in);
325:
326:                // in Windows terminals, arrow keys are represented by
327:                // a sequence of 2 characters. E.g., the up arrow
328:                // key yields 224, 72
329:                if (indicator == SPECIAL_KEY_INDICATOR
330:                        || indicator == NUMPAD_KEY_INDICATOR) {
331:                    int key = readCharacter(in);
332:
333:                    switch (key) {
334:                    case UP_ARROW_KEY:
335:                        return CTRL_P; // translate UP -> CTRL-P
336:                    case LEFT_ARROW_KEY:
337:                        return CTRL_B; // translate LEFT -> CTRL-B
338:                    case RIGHT_ARROW_KEY:
339:                        return CTRL_F; // translate RIGHT -> CTRL-F
340:                    case DOWN_ARROW_KEY:
341:                        return CTRL_N; // translate DOWN -> CTRL-N
342:                    case DELETE_KEY:
343:                        return CTRL_QM; // translate DELETE -> CTRL-?
344:                    case HOME_KEY:
345:                        return CTRL_A;
346:                    case END_KEY:
347:                        return CTRL_E;
348:                    case PAGE_UP_KEY:
349:                        return CTRL_K;
350:                    case PAGE_DOWN_KEY:
351:                        return CTRL_L;
352:                    case ESCAPE_KEY:
353:                        return CTRL_OB; // translate ESCAPE -> CTRL-[
354:                    case INSERT_KEY:
355:                        return CTRL_C;
356:                    default:
357:                        return 0;
358:                    }
359:                } else if (indicator > 128) {
360:                    // handle unicode characters longer than 2 bytes,
361:                    // thanks to Marc.Herbert@continuent.com
362:                    replayStream.setInput(indicator, in);
363:                    // replayReader = new InputStreamReader(replayStream, encoding);
364:                    indicator = replayReader.read();
365:
366:                }
367:
368:                return indicator;
369:
370:            }
371:
372:            public boolean isSupported() {
373:                return true;
374:            }
375:
376:            /**
377:             * Windows doesn't support ANSI codes by default; disable them.
378:             */
379:            public boolean isANSISupported() {
380:                return false;
381:            }
382:
383:            public boolean getEcho() {
384:                return false;
385:            }
386:
387:            /**
388:             * Unsupported; return the default.
389:             *
390:             * @see Terminal#getTerminalWidth
391:             */
392:            public int getTerminalWidth() {
393:                return getWindowsTerminalWidth();
394:            }
395:
396:            /**
397:             * Unsupported; return the default.
398:             *
399:             * @see Terminal#getTerminalHeight
400:             */
401:            public int getTerminalHeight() {
402:                return getWindowsTerminalHeight();
403:            }
404:
405:            /**
406:             * No-op for exceptions we want to silently consume.
407:             */
408:            private void consumeException(final Throwable e) {
409:            }
410:
411:            /**
412:             * Whether or not to allow the use of the JNI console interaction.
413:             */
414:            public void setDirectConsole(Boolean directConsole) {
415:                this .directConsole = directConsole;
416:            }
417:
418:            /**
419:             * Whether or not to allow the use of the JNI console interaction.
420:             */
421:            public Boolean getDirectConsole() {
422:                return this .directConsole;
423:            }
424:
425:            public synchronized boolean isEchoEnabled() {
426:                return echoEnabled;
427:            }
428:
429:            public synchronized void enableEcho() {
430:                // Must set these four modes at the same time to make it work fine.
431:                setConsoleMode(getConsoleMode() | ENABLE_ECHO_INPUT
432:                        | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT
433:                        | ENABLE_WINDOW_INPUT);
434:                echoEnabled = true;
435:            }
436:
437:            public synchronized void disableEcho() {
438:                // Must set these four modes at the same time to make it work fine.
439:                setConsoleMode(getConsoleMode()
440:                        & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT
441:                                | ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT));
442:                echoEnabled = true;
443:            }
444:
445:            public InputStream getDefaultBindings() {
446:                return getClass().getResourceAsStream(
447:                        "windowsbindings.properties");
448:            }
449:
450:            /**
451:             * This is awkward and inefficient, but probably the minimal way to add
452:             * UTF-8 support to JLine
453:             *
454:             * @author <a href="mailto:Marc.Herbert@continuent.com">Marc Herbert</a>
455:             */
456:            static class ReplayPrefixOneCharInputStream extends InputStream {
457:                byte firstByte;
458:                int byteLength;
459:                InputStream wrappedStream;
460:                int byteRead;
461:
462:                final String encoding;
463:
464:                public ReplayPrefixOneCharInputStream(String encoding) {
465:                    this .encoding = encoding;
466:                }
467:
468:                public void setInput(int recorded, InputStream wrapped)
469:                        throws IOException {
470:                    this .byteRead = 0;
471:                    this .firstByte = (byte) recorded;
472:                    this .wrappedStream = wrapped;
473:
474:                    byteLength = 1;
475:                    if (encoding.equalsIgnoreCase("UTF-8"))
476:                        setInputUTF8(recorded, wrapped);
477:                    else if (encoding.equalsIgnoreCase("UTF-16"))
478:                        byteLength = 2;
479:                    else if (encoding.equalsIgnoreCase("UTF-32"))
480:                        byteLength = 4;
481:                }
482:
483:                public void setInputUTF8(int recorded, InputStream wrapped)
484:                        throws IOException {
485:                    // 110yyyyy 10zzzzzz
486:                    if ((firstByte & (byte) 0xE0) == (byte) 0xC0)
487:                        this .byteLength = 2;
488:                    // 1110xxxx 10yyyyyy 10zzzzzz
489:                    else if ((firstByte & (byte) 0xF0) == (byte) 0xE0)
490:                        this .byteLength = 3;
491:                    // 11110www 10xxxxxx 10yyyyyy 10zzzzzz
492:                    else if ((firstByte & (byte) 0xF8) == (byte) 0xF0)
493:                        this .byteLength = 4;
494:                    else
495:                        throw new IOException("invalid UTF-8 first byte: "
496:                                + firstByte);
497:                }
498:
499:                public int read() throws IOException {
500:                    if (available() == 0)
501:                        return -1;
502:
503:                    byteRead++;
504:
505:                    if (byteRead == 1)
506:                        return firstByte;
507:
508:                    return wrappedStream.read();
509:                }
510:
511:                /**
512:                 * InputStreamReader is greedy and will try to read bytes in advance. We
513:                 * do NOT want this to happen since we use a temporary/"losing bytes"
514:                 * InputStreamReader above, that's why we hide the real
515:                 * wrappedStream.available() here.
516:                 */
517:                public int available() {
518:                    return byteLength - byteRead;
519:                }
520:            }
521:
522:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.