Blame view

readline/src/pad/prac1/EditableBufferedReader.java 6.04 KB
Imanol-Mikel Barba Sabariego authored
1
2
3
4
5
6
package pad.prac1;
import java.io.*;


public class EditableBufferedReader extends BufferedReader 
{
7
8
9
10
	/*
	 * MODE DEFINITIONS
	 */
11
12
13
14
	public static final int DEL_BACKWARD 	= 0;
	public static final int DEL_FORWARD 	= 1;
	public static final int INSERT 			= 0;
	public static final int OVERWRITE 		= 1;
15
16
17
18
19
20

	/*
	 * TYPE DEFINITIONS
	 */

	public static final int ESCAPE_SEQUENCE = 0;
21
22
	public static final int PRINTABLE 		= 1;
	public static final int NON_PRINTABLE 	= 2;
23
24
25
26
27
28
29
30
31
32
33
34
35

	/* KEY DEFINITIONS
	 * ESC (0x1B) starts an escape sequence
	 * ESC+[+C (0x1B 0x5B 0x43) Cursor Forward
	 * ESC+[+D (0x1B 0x5B 0x44) Cursor Backward
	 * ESC+[+2+~ (0x1B 0x5B 0x32 0x7E) Insert
	 * ESC+[+3+~ (0x1B 0x5B 0x33 0x7E) Delete forward
	 * ESC+O+H (0x1B 0x4F 0x48) Home
	 * ESC+O+F (0x1B 0x4F 0x46) End
	 */

	public static final int RETURN_KEY 		= 0x0D;
	public static final int BACKSPACE 		= 0x08;
36
	public static final int BACKSPACE_DEL 	= 0x7F;
37
38
	public static final int ESC 			= 0x1B;
	public static final int ESC_SEQ 		= 0x5B;
39
40
41
	public static final int FORWARD 		= 0x43;
	public static final int BACKWARD		= 0x44;
	public static final int DEL 			= 0x33;
42
43
44
45
	public static final int TILDE 			= 0x7E;
	public static final int HOME_END 		= 0x4F;
	public static final int HOME 			= 0x48;
	public static final int END 			= 0x46;
46
47
48
49
	public static final int INSERT_KEY		= 0x32;
	public static final int INS_SPACE		= 0x40;
	public static final int DEL_CHAR		= 0x50;
	public static final int NUM_0			= 0x30;
Imanol-Mikel Barba Sabariego authored
50
51
52
53
	private Line line = new Line();
	private boolean returnKey 	= false;
Imanol-Mikel Barba Sabariego authored
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
	public EditableBufferedReader(Reader in)
	{
		super(in);
	}

	public EditableBufferedReader(Reader in, int sz)
	{
		super(in,sz);
	}

	private void setRaw() throws IOException, InterruptedException
	{
		String[] cmd = {"/bin/sh", "-c", "stty raw -echo </dev/tty"};
		Runtime.getRuntime().exec(cmd).waitFor();
	}

	private void unsetRaw() throws IOException, InterruptedException
	{
		String[] cmd = {"/bin/sh", "-c", "stty -raw echo </dev/tty"};
		Runtime.getRuntime().exec(cmd).waitFor();
	}
76
77
	private int parseKey(int key)
	{
78
79
80
81
82
83
84
85
86
87
88
89
		if(key < 0x20)
		{
			if(key == ESC)
			{
				return ESCAPE_SEQUENCE;
			}
			else if((key == BACKSPACE) || (key == RETURN_KEY))
			{
				return PRINTABLE;
			}
			return NON_PRINTABLE;
		}
90
91
92
		return PRINTABLE;
	}
93
	public void addChar(char c)
94
	{
95
96
97
98
99
100
		switch(line.getMode())
		{
			case INSERT:
				if(line.getCursorPosition() != line.length()+1)
				{
					insertSpace();
Imanol-Mikel Barba Sabariego authored
101
				}
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
				System.out.print(c);
				line.insertCharAt(c, line.getCursorPosition()-1);
				line.setCursorPosition(line.getCursorPosition()+1);
				break;

			case OVERWRITE:
				if(line.getCursorPosition() != line.length()+1)
				{
					line.removeCharAt(line.getCursorPosition()-1);
				}
				System.out.print(c);
				line.insertCharAt(c, line.getCursorPosition()-1);
				line.setCursorPosition(line.getCursorPosition()+1);
			break;
		}
117
118
119
120
	}

	public void delChar(int mode)
	{
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
		switch(mode)
		{
			case DEL_BACKWARD:
				if(line.getCursorPosition() != 1)
				{
					System.out.print((char)BACKSPACE);
					deleteCharacter();
					line.removeCharAt(line.getCursorPosition()-2);
					line.setCursorPosition(line.getCursorPosition()-1);
				}
			break;
			case DEL_FORWARD:
				if(line.getCursorPosition() != (line.length()+1))
				{
					line.removeCharAt(line.getCursorPosition()-1);
					deleteCharacter();
				}
			break;
		}
140
141
	}
142
	private void insertSpace()
143
144
145
	{
		System.out.print((char)ESC);
		System.out.print((char)ESC_SEQ);
146
		System.out.print((char)INS_SPACE);
147
148
	}
149
	private void deleteCharacter()
150
151
152
	{
		System.out.print((char)ESC);
		System.out.print((char)ESC_SEQ);
153
		System.out.print((char)DEL_CHAR);
154
155
156
157
	}

	public void moveCursorTo(int pos)
	{
158
		if((pos <= line.length()+1) && (pos >= 1))
159
		{
160
			if(pos > line.getCursorPosition())
161
			{
162
163
				System.out.print((char)ESC);
				System.out.print((char)ESC_SEQ);
164
				System.out.print(Integer.toString(pos-line.getCursorPosition()));
165
				System.out.print((char)FORWARD);
166
167
			}
168
			else if(pos < line.getCursorPosition())
169
			{
170
171
				System.out.print((char)ESC);
				System.out.print((char)ESC_SEQ);
172
				System.out.print(Integer.toString(line.getCursorPosition()-pos));
173
				System.out.print((char)BACKWARD);
174
			}
175
			line.setCursorPosition(pos);
176
177
178
		}
	}
Imanol-Mikel Barba Sabariego authored
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
	public int read() throws IOException
	{
		return super.read();
	}

	public String readLine()
	{
		try 
		{
			setRaw();
		} 
		catch (Exception e) 
		{
			System.out.println("Couldn't set terminal in raw mode");
			return "";
		}
		while(!returnKey)
		{
			try 
			{
				int character = read();
200
				//System.err.print(Integer.toHexString(character) + " \n");
201
				switch(parseKey(character))
Imanol-Mikel Barba Sabariego authored
202
				{
203
					case ESCAPE_SEQUENCE:
204
						switch(read())
205
						{
206
207
208
209
210
211
212
213
214
							case ESC_SEQ:
								switch(read())
								{
									case FORWARD:
										moveCursorTo(line.getCursorPosition()+1);
									break;

									case BACKWARD:
										moveCursorTo(line.getCursorPosition()-1);
215
216
									break;
217
218
219
220
221
									case DEL:
										if(read() == TILDE)
										{
											delChar(DEL_FORWARD);
										}
222
									break;
223
224
225
226
227
228

									case INSERT_KEY:
										if(read() == TILDE)
										{
											line.toggleMode();
										}
229
									break;
230
231
232
233
234
235
236
237
								}
							break;

							case HOME_END:
								switch(read())
								{
									case HOME:
										moveCursorTo(1);
238
									break;
239
240
241

									case END:
										moveCursorTo(line.length()+1);
242
									break;
243
244
								}
							break;
245
						}
246
					break;
247
248
249
250
251
252

					case PRINTABLE:
						switch(character)
						{
							case RETURN_KEY:
								returnKey = true;
253
							break;
254
255
256
257

							case BACKSPACE:
							case BACKSPACE_DEL:
								delChar(DEL_BACKWARD);
258
							break;
259
260
261

							default:
								addChar((char)character);
262
							break;
263
						}
264
					break;
265
266
267

					case NON_PRINTABLE:
						//ignore
268
					break;
Imanol-Mikel Barba Sabariego authored
269
270
271
272
				}
			} 
			catch (IOException e)
			{
273
				System.out.println("Error reading line");
Imanol-Mikel Barba Sabariego authored
274
275
276
277
278
279
280
281
282
283
284
285
				break;
			}
		}
		try 
		{
			unsetRaw();
		} 
		catch (Exception e) 
		{
			System.out.println("Couldn't unset raw mode");
			return "";
		}
286
		System.out.println("");
287
		return line.toString();
Imanol-Mikel Barba Sabariego authored
288
289
	}
}