Source Code Cross Referenced for UnixTerminal.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:        import java.util.*;
011:
012:        /**
013:         *  <p>
014:         *  Terminal that is used for unix platforms. Terminal initialization
015:         *  is handled by issuing the <em>stty</em> command against the
016:         *  <em>/dev/tty</em> file to disable character echoing and enable
017:         *  character input. All known unix systems (including
018:         *  Linux and Macintosh OS X) support the <em>stty</em>), so this
019:         *  implementation should work for an reasonable POSIX system.
020:         *        </p>
021:         *
022:         *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
023:         *  @author  Updates <a href="mailto:dwkemp@gmail.com">Dale Kemp</a> 2005-12-03
024:         */
025:        public class UnixTerminal extends Terminal {
026:            public static final short ARROW_START = 27;
027:            public static final short ARROW_PREFIX = 91;
028:            public static final short ARROW_LEFT = 68;
029:            public static final short ARROW_RIGHT = 67;
030:            public static final short ARROW_UP = 65;
031:            public static final short ARROW_DOWN = 66;
032:            public static final short O_PREFIX = 79;
033:            public static final short HOME_CODE = 72;
034:            public static final short END_CODE = 70;
035:
036:            public static final short DEL_THIRD = 51;
037:            public static final short DEL_SECOND = 126;
038:
039:            private Map terminfo;
040:            private boolean echoEnabled;
041:            private String ttyConfig;
042:            private boolean backspaceDeleteSwitched = false;
043:            private static String sttyCommand = System.getProperty(
044:                    "jline.sttyCommand", "stty");
045:
046:            String encoding = System.getProperty("input.encoding", "UTF-8");
047:            ReplayPrefixOneCharInputStream replayStream = new ReplayPrefixOneCharInputStream(
048:                    encoding);
049:            InputStreamReader replayReader;
050:
051:            public UnixTerminal() {
052:                try {
053:                    replayReader = new InputStreamReader(replayStream, encoding);
054:                } catch (Exception e) {
055:                    throw new RuntimeException(e);
056:                }
057:            }
058:
059:            protected void checkBackspace() {
060:                String[] ttyConfigSplit = ttyConfig.split(":|=");
061:
062:                if (ttyConfigSplit.length < 7)
063:                    return;
064:
065:                if (ttyConfigSplit[6] == null)
066:                    return;
067:
068:                backspaceDeleteSwitched = ttyConfigSplit[6].equals("7f");
069:            }
070:
071:            /**
072:             *  Remove line-buffered input by invoking "stty -icanon min 1"
073:             *  against the current terminal.
074:             */
075:            public void initializeTerminal() throws IOException,
076:                    InterruptedException {
077:                // save the initial tty configuration
078:                ttyConfig = stty("-g");
079:
080:                // sanity check
081:                if ((ttyConfig.length() == 0)
082:                        || ((ttyConfig.indexOf("=") == -1) && (ttyConfig
083:                                .indexOf(":") == -1))) {
084:                    throw new IOException("Unrecognized stty code: "
085:                            + ttyConfig);
086:                }
087:
088:                checkBackspace();
089:
090:                // set the console to be character-buffered instead of line-buffered
091:                stty("-icanon min 1");
092:
093:                // disable character echoing
094:                stty("-echo");
095:                echoEnabled = false;
096:
097:                // at exit, restore the original tty configuration (for JDK 1.3+)
098:                try {
099:                    Runtime.getRuntime().addShutdownHook(new Thread() {
100:                        public void start() {
101:                            try {
102:                                restoreTerminal();
103:                            } catch (Exception e) {
104:                                consumeException(e);
105:                            }
106:                        }
107:                    });
108:                } catch (AbstractMethodError ame) {
109:                    // JDK 1.3+ only method. Bummer.
110:                    consumeException(ame);
111:                }
112:            }
113:
114:            /** 
115:             * Restore the original terminal configuration, which can be used when
116:             * shutting down the console reader. The ConsoleReader cannot be
117:             * used after calling this method.
118:             */
119:            public void restoreTerminal() throws Exception {
120:                if (ttyConfig != null) {
121:                    stty(ttyConfig);
122:                    ttyConfig = null;
123:                }
124:                resetTerminal();
125:            }
126:
127:            public int readVirtualKey(InputStream in) throws IOException {
128:                int c = readCharacter(in);
129:
130:                if (backspaceDeleteSwitched)
131:                    if (c == DELETE)
132:                        c = '\b';
133:                    else if (c == '\b')
134:                        c = DELETE;
135:
136:                // in Unix terminals, arrow keys are represented by
137:                // a sequence of 3 characters. E.g., the up arrow
138:                // key yields 27, 91, 68
139:                if (c == ARROW_START) {
140:                    //also the escape key is 27
141:                    //thats why we read until we
142:                    //have something different than 27
143:                    //this is a bugfix, because otherwise
144:                    //pressing escape and than an arrow key
145:                    //was an undefined state
146:                    while (c == ARROW_START)
147:                        c = readCharacter(in);
148:                    if (c == ARROW_PREFIX || c == O_PREFIX) {
149:                        c = readCharacter(in);
150:                        if (c == ARROW_UP) {
151:                            return CTRL_P;
152:                        } else if (c == ARROW_DOWN) {
153:                            return CTRL_N;
154:                        } else if (c == ARROW_LEFT) {
155:                            return CTRL_B;
156:                        } else if (c == ARROW_RIGHT) {
157:                            return CTRL_F;
158:                        } else if (c == HOME_CODE) {
159:                            return CTRL_A;
160:                        } else if (c == END_CODE) {
161:                            return CTRL_E;
162:                        } else if (c == DEL_THIRD) {
163:                            c = readCharacter(in); // read 4th
164:                            return DELETE;
165:                        }
166:                    }
167:                }
168:                // handle unicode characters, thanks for a patch from amyi@inf.ed.ac.uk
169:                if (c > 128) {
170:                    // handle unicode characters longer than 2 bytes,
171:                    // thanks to Marc.Herbert@continuent.com
172:                    replayStream.setInput(c, in);
173:                    //            replayReader = new InputStreamReader(replayStream, encoding);
174:                    c = replayReader.read();
175:
176:                }
177:
178:                return c;
179:            }
180:
181:            /**
182:             *  No-op for exceptions we want to silently consume.
183:             */
184:            private void consumeException(Throwable e) {
185:            }
186:
187:            public boolean isSupported() {
188:                return true;
189:            }
190:
191:            public boolean getEcho() {
192:                return false;
193:            }
194:
195:            /**
196:             *  Returns the value of "stty size" width param.
197:             *
198:             *  <strong>Note</strong>: this method caches the value from the
199:             *  first time it is called in order to increase speed, which means
200:             *  that changing to size of the terminal will not be reflected
201:             *  in the console.
202:             */
203:            public int getTerminalWidth() {
204:                int val = -1;
205:
206:                try {
207:                    val = getTerminalProperty("columns");
208:                } catch (Exception e) {
209:                }
210:
211:                if (val == -1) {
212:                    val = 80;
213:                }
214:
215:                return val;
216:            }
217:
218:            /**
219:             *  Returns the value of "stty size" height param.
220:             *
221:             *  <strong>Note</strong>: this method caches the value from the
222:             *  first time it is called in order to increase speed, which means
223:             *  that changing to size of the terminal will not be reflected
224:             *  in the console.
225:             */
226:            public int getTerminalHeight() {
227:                int val = -1;
228:
229:                try {
230:                    val = getTerminalProperty("rows");
231:                } catch (Exception e) {
232:                }
233:
234:                if (val == -1) {
235:                    val = 24;
236:                }
237:
238:                return val;
239:            }
240:
241:            private static int getTerminalProperty(String prop)
242:                    throws IOException, InterruptedException {
243:                // need to be able handle both output formats:
244:                // speed 9600 baud; 24 rows; 140 columns;
245:                // and:
246:                // speed 38400 baud; rows = 49; columns = 111; ypixels = 0; xpixels = 0;
247:                String props = stty("-a");
248:
249:                for (StringTokenizer tok = new StringTokenizer(props, ";\n"); tok
250:                        .hasMoreTokens();) {
251:                    String str = tok.nextToken().trim();
252:
253:                    if (str.startsWith(prop)) {
254:                        int index = str.lastIndexOf(" ");
255:
256:                        return Integer.parseInt(str.substring(index).trim());
257:                    } else if (str.endsWith(prop)) {
258:                        int index = str.indexOf(" ");
259:
260:                        return Integer.parseInt(str.substring(0, index).trim());
261:                    }
262:                }
263:
264:                return -1;
265:            }
266:
267:            /**
268:             *  Execute the stty command with the specified arguments
269:             *  against the current active terminal.
270:             */
271:            private static String stty(final String args) throws IOException,
272:                    InterruptedException {
273:                return exec("stty " + args + " < /dev/tty").trim();
274:            }
275:
276:            /**
277:             *  Execute the specified command and return the output
278:             *  (both stdout and stderr).
279:             */
280:            private static String exec(final String cmd) throws IOException,
281:                    InterruptedException {
282:                return exec(new String[] { "sh", "-c", cmd });
283:            }
284:
285:            /**
286:             *  Execute the specified command and return the output
287:             *  (both stdout and stderr).
288:             */
289:            private static String exec(final String[] cmd) throws IOException,
290:                    InterruptedException {
291:                ByteArrayOutputStream bout = new ByteArrayOutputStream();
292:
293:                Process p = Runtime.getRuntime().exec(cmd);
294:                int c;
295:                InputStream in;
296:
297:                in = p.getInputStream();
298:
299:                while ((c = in.read()) != -1) {
300:                    bout.write(c);
301:                }
302:
303:                in = p.getErrorStream();
304:
305:                while ((c = in.read()) != -1) {
306:                    bout.write(c);
307:                }
308:
309:                p.waitFor();
310:
311:                String result = new String(bout.toByteArray());
312:
313:                return result;
314:            }
315:
316:            /**
317:             *  The command to use to set the terminal options. Defaults
318:             *  to "stty", or the value of the system property "jline.sttyCommand".
319:             */
320:            public static void setSttyCommand(String cmd) {
321:                sttyCommand = cmd;
322:            }
323:
324:            /**
325:             *  The command to use to set the terminal options. Defaults
326:             *  to "stty", or the value of the system property "jline.sttyCommand".
327:             */
328:            public static String getSttyCommand() {
329:                return sttyCommand;
330:            }
331:
332:            public synchronized boolean isEchoEnabled() {
333:                return echoEnabled;
334:            }
335:
336:            public synchronized void enableEcho() {
337:                try {
338:                    stty("echo");
339:                    echoEnabled = true;
340:                } catch (Exception e) {
341:                    consumeException(e);
342:                }
343:            }
344:
345:            public synchronized void disableEcho() {
346:                try {
347:                    stty("-echo");
348:                    echoEnabled = false;
349:                } catch (Exception e) {
350:                    consumeException(e);
351:                }
352:            }
353:
354:            /**
355:             * This is awkward and inefficient, but probably the minimal way to add
356:             * UTF-8 support to JLine
357:             *
358:             * @author <a href="mailto:Marc.Herbert@continuent.com">Marc Herbert</a>
359:             */
360:            static class ReplayPrefixOneCharInputStream extends InputStream {
361:                byte firstByte;
362:                int byteLength;
363:                InputStream wrappedStream;
364:                int byteRead;
365:
366:                final String encoding;
367:
368:                public ReplayPrefixOneCharInputStream(String encoding) {
369:                    this .encoding = encoding;
370:                }
371:
372:                public void setInput(int recorded, InputStream wrapped)
373:                        throws IOException {
374:                    this .byteRead = 0;
375:                    this .firstByte = (byte) recorded;
376:                    this .wrappedStream = wrapped;
377:
378:                    byteLength = 1;
379:                    if (encoding.equalsIgnoreCase("UTF-8"))
380:                        setInputUTF8(recorded, wrapped);
381:                    else if (encoding.equalsIgnoreCase("UTF-16"))
382:                        byteLength = 2;
383:                    else if (encoding.equalsIgnoreCase("UTF-32"))
384:                        byteLength = 4;
385:                }
386:
387:                public void setInputUTF8(int recorded, InputStream wrapped)
388:                        throws IOException {
389:                    // 110yyyyy 10zzzzzz
390:                    if ((firstByte & (byte) 0xE0) == (byte) 0xC0)
391:                        this .byteLength = 2;
392:                    // 1110xxxx 10yyyyyy 10zzzzzz
393:                    else if ((firstByte & (byte) 0xF0) == (byte) 0xE0)
394:                        this .byteLength = 3;
395:                    // 11110www 10xxxxxx 10yyyyyy 10zzzzzz
396:                    else if ((firstByte & (byte) 0xF8) == (byte) 0xF0)
397:                        this .byteLength = 4;
398:                    else
399:                        throw new IOException("invalid UTF-8 first byte: "
400:                                + firstByte);
401:                }
402:
403:                public int read() throws IOException {
404:                    if (available() == 0)
405:                        return -1;
406:
407:                    byteRead++;
408:
409:                    if (byteRead == 1)
410:                        return firstByte;
411:
412:                    return wrappedStream.read();
413:                }
414:
415:                /**
416:                 * InputStreamReader is greedy and will try to read bytes in advance. We
417:                 * do NOT want this to happen since we use a temporary/"losing bytes"
418:                 * InputStreamReader above, that's why we hide the real
419:                 * wrappedStream.available() here.
420:                 */
421:                public int available() {
422:                    return byteLength - byteRead;
423:                }
424:            }
425:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.