Blame view

readline/src/pad/prac1/EditableBufferedReader.java 5.98 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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
		switch(line.getMode())
		{
			case INSERT:
				if(line.getCursorPosition() != line.length()+1)
				{
					insertSpace();
				}			
				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
164
165
				System.out.print((char)ESC);
				System.out.print((char)ESC_SEQ);
				System.out.print((char)(NUM_0+pos-line.getCursorPosition()));
				System.out.print((char)FORWARD);
166
167
			}
168
			else if(pos < line.getCursorPosition())
169
			{
170
171
172
173
				System.out.print((char)ESC);
				System.out.print((char)ESC_SEQ);
				System.out.print((char)(NUM_0-pos+line.getCursorPosition()));
				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
				switch(parseKey(character))
Imanol-Mikel Barba Sabariego authored
201
				{
202
					case ESCAPE_SEQUENCE:
203
						switch(read())
204
						{
205
206
207
208
209
210
211
212
213
							case ESC_SEQ:
								switch(read())
								{
									case FORWARD:
										moveCursorTo(line.getCursorPosition()+1);
									break;

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

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

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

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

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

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

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

					case NON_PRINTABLE:
						//ignore
267
					break;
Imanol-Mikel Barba Sabariego authored
268
				}
269
Imanol-Mikel Barba Sabariego authored
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
	}
}