KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > terminalemulator > LineDiscipline


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is Terminal Emulator.
16  * The Initial Developer of the Original Software is Sun Microsystems, Inc..
17  * Portions created by Sun Microsystems, Inc. are Copyright (C) 2001.
18  * All Rights Reserved.
19  *
20  * Contributor(s): Ivan Soleimanipour.
21  */

22
23 /*
24  * "LineDiscipline.java"
25  * LineDiscipline.java 1.8 01/07/10
26  */

27
28 package org.netbeans.lib.terminalemulator;
29
30 /**
31  * Do the sort of stuff pty's normally do:
32  * <ul>
33  * <li> echoing
34  * <li> CR/NL mappings
35  * <li> BS processing
36  * <li> Line buffering.
37  * </ul>
38  * <p>
39  * Currently the settings are hardcoded to simulate a pty setup for running
40  * shells.
41  * <p>
42  * This class is not complete by any means and is merely an example of
43  * a TermStream. Things that it might do:
44  * <ul>
45  * <li> TAB processing
46  * <li> conversion of control characters to "signals".
47  * </ul>
48  */

49
50 public class LineDiscipline extends TermStream {
51
52     private static final char bs_sequence[] = {(char)8, (char)32, (char)8};
53
54     // input line main buffer
55
private StringBuffer JavaDoc line = new StringBuffer JavaDoc();
56
57     // auto-growing buffer for sending lines accumulated in 'line'.
58
private int send_buf_sz = 2;
59     private char send_buf[] = new char[send_buf_sz];
60     char [] send_buf(int n) {
61     if (n >= send_buf_sz) {
62         send_buf_sz = n+1;
63         send_buf = new char[send_buf_sz];
64     }
65     return send_buf;
66     }
67
68     // buffer for processing incoming characters
69
private int put_capacity = 16;
70     private int put_length = 0;
71     private char put_buf[] = new char[put_capacity];
72
73     public void flush() {
74     toDTE.flush();
75     }
76
77     public void putChar(char c) {
78     // Even though we dealing with one character, as the processing on it
79
// may get more complicated we will want to use the code factored in
80
// processChar()
81

82     // reset buffer
83
put_length = 0;
84
85     // fill it
86
processChar(c);
87
88     // flush it
89
toDTE.putChars(put_buf, 0, put_length);
90     }
91
92     public void putChars(char buf[], int offset, int count) {
93
94     // reset buffer
95
put_length = 0;
96
97     // fill it
98
for (int bx = 0; bx < count; bx++)
99         processChar(buf[offset+bx]);
100
101     // flush it
102
toDTE.putChars(put_buf, 0, put_length);
103     }
104
105     private void processChar(char c) {
106     // Any actual mapping and processing gets done here
107
appendChar(c);
108
109     // Map NL to NLCR *stty onlcr)
110
if (c == 10)
111         appendChar((char) 13);
112     }
113
114     private void appendChar(char c) {
115
116     // Play StringBuffer
117

118     if (put_length >= put_capacity) {
119         int new_capacity = put_capacity * 2;
120         if (new_capacity < 0)
121         new_capacity = Integer.MAX_VALUE;
122         char new_buf[] = new char[new_capacity];
123         System.arraycopy(put_buf, 0, new_buf, 0, put_length);
124         put_buf = new_buf;
125         put_capacity = new_capacity;
126     }
127
128     put_buf[put_length++] = c;
129     }
130
131
132
133
134     public void sendChar(char c) {
135     // keystroke -> world (DCE)
136

137     // map CR to NL (stty icrnl)
138
if (c == 13) {
139         toDTE.putChar(c); // echo
140
toDTE.flush();
141
142         c = (char) 10;
143         toDTE.putChar(c); // echo the newline too
144
toDTE.flush();
145
146         line.append(c);
147
148         int nchars = line.length();
149         char [] tmp = send_buf(nchars);
150         line.getChars(0, nchars, tmp, 0);
151         toDCE.sendChars(tmp, 0, nchars);
152         line.delete(0, 99999); // clear the line
153

154     } else if (c == 10) {
155             toDTE.putChar((char) 13); // echo carriage return too
156
toDTE.flush();
157
158         toDTE.putChar(c); // echo
159
toDTE.flush();
160
161         line.append(c);
162
163         int nchars = line.length();
164         char [] tmp = send_buf(nchars);
165         line.getChars(0, nchars, tmp, 0);
166         toDCE.sendChars(tmp, 0, nchars);
167         line.delete(0, 99999); // clear the line
168

169         } else if (c == 8) {
170         // BS
171
int nchars = line.length();
172
173         if (nchars == 0)
174         return; // nothing left to BS over
175

176         char erased_char = ' '; // The char we're going to erase
177
try {
178         erased_char = line.charAt(nchars-1);
179         } catch (Exception JavaDoc x) {
180         return; // apparently the 'nchars == 0' test failed above ;-)
181
}
182         int cwidth = getTerm().charWidth(erased_char);
183
184         // remove from line buffer
185
line.delete(nchars-1, nchars);
186
187         // HACK
188
// If you play a bit with DtTerm on Solaris in a non-latin locale
189
// you'll see that when you BS over a multi-cell character it
190
// doesn't erase the whole character. The character is erased but the
191
// cursor moves back only one column. So you usually need to BS twice
192
// to get rid of it. If you "fix" Term to do something more reasonable
193
// you'll find out that as you backspace you'll run over the cursor.
194
// that's because the kernel linebuffer accounting assumes the above setup.
195
// I"m not sure how all of this came about but we have to mimic similar
196
// acounting and we do it by padding the buffer (only) with a bunch of spaces.
197
//
198
// NOTE: There are two strong invariants you have to keep in mind:
199
// - Solaris, and I assume other unixes, stick to the BS-SP-BS echo
200
// even though they seem to know about character widths.
201
// - BS from Term's point of view is _strictly_ a cursor motion operation!
202
// The fact that it erases things has to do with the line discipline
203
// (kernels or this class 'ere)
204
//
205
// Now I know non-unix people will want BS to behave sanely in non-unix
206
// environments, so perhapws we SHOULD have a property to control whether
207
// things get erased the unix way or some other way.
208

209         while(--cwidth > 0 )
210         line.append(' ');
211
212         // erase character on screen
213
toDTE.putChars(bs_sequence, 0, 3);
214         toDTE.flush();
215
216     } else {
217         toDTE.putChar(c); // echo
218
toDTE.flush();
219         line.append(c);
220     }
221     }
222
223     public void sendChars(char c[], int offset, int count) {
224     for (int cx = 0; cx < count; cx++)
225         sendChar(c[offset+cx]);
226     }
227 }
228
Popular Tags