001: /*
002: * SSHTools - Java SSH2 API
003: *
004: * Copyright (C) 2002-2003 Lee David Painter and Contributors.
005: *
006: * Contributions made by:
007: *
008: * Brett Smith
009: * Richard Pernavas
010: * Erwin Bolwidt
011: *
012: * This program is free software; you can redistribute it and/or
013: * modify it under the terms of the GNU General Public License
014: * as published by the Free Software Foundation; either version 2
015: * of the License, or (at your option) any later version.
016: *
017: * This program is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with this program; if not, write to the Free Software
024: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
025: */
026: /**
027: * SSHTools - Java SSH API The contents of this package has been derived from
028: * the TelnetD library available from http://sourceforge.net/projects/telnetd
029: * The original license of the source code is as follows: TelnetD library
030: * (embeddable telnet daemon) Copyright (C) 2000 Dieter Wimberger This library
031: * is free software; you can either redistribute it and/or modify it under the
032: * terms of the GNU Lesser General Public License version 2.1,1999 as
033: * published by the Free Software Foundation (see copy received along with the
034: * library), or under the terms of the BSD-style license received along with
035: * this library.
036: */package com.sshtools.daemon.terminal;
037:
038: import java.io.*;
039:
040: /**
041: *
042: *
043: * @author $author$
044: * @version $Revision: 1.12 $
045: */
046: public class Editline {
047: //Aggregations (inner class!)
048: private Buffer buf;
049:
050: //Members
051: private TerminalIO myIO;
052: private int Cursor = 0;
053: private boolean InsertMode = true;
054: private int lastSize = 0;
055: private boolean hardwrapped = false;
056: private char lastread;
057: private int lastcurspos = 0;
058: private boolean maskInput = false;
059: private char mask = '*';
060:
061: /**
062: * Creates a new Editline object.
063: *
064: * @param io
065: */
066: public Editline(TerminalIO io) {
067: myIO = io;
068:
069: //allways full length
070: buf = new Buffer(myIO.getColumns() - 1);
071: Cursor = 0;
072: InsertMode = true;
073: }
074:
075: //constructor
076: public int size() {
077: return buf.size();
078: }
079:
080: //getSize
081: public String getValue() {
082: return buf.toString();
083: }
084:
085: //getValue
086: public void setValue(String str) throws BufferOverflowException,
087: IOException {
088: storeSize();
089:
090: //buffer
091: buf.clear();
092:
093: //cursor
094: Cursor = 0;
095:
096: //screen
097: myIO.moveLeft(lastSize);
098: myIO.eraseToEndOfLine();
099: append(str);
100: }
101:
102: //setValue
103: public void maskInput(boolean maskInput) {
104: this .maskInput = maskInput;
105: }
106:
107: /**
108: *
109: *
110: * @param mask
111: */
112: public void setMask(char mask) {
113: this .mask = mask;
114: }
115:
116: /**
117: *
118: *
119: * @throws IOException
120: */
121: public void clear() throws IOException {
122: storeSize();
123:
124: //Buffer
125: buf.clear();
126:
127: //Cursor
128: Cursor = 0;
129:
130: //Screen
131: draw();
132: }
133:
134: //clear
135: public String getSoftwrap() throws IndexOutOfBoundsException,
136: IOException {
137: //Wrap from Buffer
138: String content = buf.toString();
139: int idx = content.lastIndexOf(" ");
140:
141: if (idx == -1) {
142: content = "";
143: } else {
144: //System.out.println("Line:softwrap:lastspace:"+idx);
145: content = content.substring(idx + 1, content.length());
146:
147: //System.out.println("Line:softwrap:wraplength:"+content.length());
148: //Cursor
149: //remeber relative cursor pos
150: Cursor = size();
151: Cursor = Cursor - content.length();
152:
153: //buffer
154: for (int i = 0; i < content.length(); i++) {
155: buf.removeCharAt(Cursor);
156: }
157:
158: //screen
159: myIO.moveLeft(content.length());
160: myIO.eraseToEndOfLine();
161:
162: //System.out.println("Line:softwrap:buffercontent:"+buf.toString());
163: }
164:
165: return content + getLastRead();
166: }
167:
168: //getSoftWrap
169: public String getHardwrap() throws IndexOutOfBoundsException,
170: IOException {
171: //Buffer
172: String content = buf.toString();
173: content = content.substring(Cursor, content.length());
174:
175: //System.out.println("buffer:tostring:"+buf.toString()+":");
176: //System.out.println("buffer:size:"+buf.size());
177: int lastsize = buf.size();
178:
179: for (int i = Cursor; i < lastsize; i++) {
180: buf.removeCharAt(Cursor);
181:
182: //System.out.println("buffer:removing char #"+i);
183: }
184:
185: //System.out.println("buffer:tostring:"+buf.toString()+":");
186: //cursor stays
187: //screen
188: myIO.eraseToEndOfLine();
189:
190: return content;
191: }
192:
193: //getHardWrap
194: private void setCharAt(int pos, char ch)
195: throws IndexOutOfBoundsException, IOException {
196: //buffer
197: buf.setCharAt(pos, ch);
198:
199: //cursor
200: //implements overwrite mode no change
201: //screen
202: draw();
203: }
204:
205: //setCharAt
206: private void insertCharAt(int pos, char ch)
207: throws BufferOverflowException, IndexOutOfBoundsException,
208: IOException {
209: storeSize();
210:
211: //buffer
212: buf.ensureSpace(1);
213: buf.insertCharAt(pos, ch);
214:
215: //cursor adjustment (so that it stays in "same" pos)
216: if (Cursor >= pos) {
217: Cursor++;
218: }
219:
220: //screen
221: draw();
222: }
223:
224: //insertCharAt
225: private void removeCharAt(int pos)
226: throws IndexOutOfBoundsException, IOException {
227: storeSize();
228:
229: //buffer
230: buf.removeCharAt(pos);
231:
232: //cursor
233: if (Cursor > pos) {
234: Cursor--;
235: }
236:
237: //screen
238: draw();
239: }
240:
241: //removeChatAt
242: private void insertStringAt(int pos, String str)
243: throws BufferOverflowException, IndexOutOfBoundsException,
244: IOException {
245: storeSize();
246:
247: //buffer
248: buf.ensureSpace(str.length());
249:
250: for (int i = 0; i < str.length(); i++) {
251: buf.insertCharAt(pos, str.charAt(i));
252:
253: //Cursor
254: Cursor++;
255: }
256:
257: //screen
258: draw();
259: }
260:
261: //insertStringAt
262: public void append(char ch) throws BufferOverflowException,
263: IOException {
264: storeSize();
265:
266: //buffer
267: buf.ensureSpace(1);
268: buf.append(ch);
269:
270: //cursor
271: Cursor++;
272:
273: //screen
274: if (!maskInput) {
275: myIO.write(ch);
276: } else {
277: myIO.write(mask);
278: }
279: }
280:
281: //append(char)
282: public void append(String str) throws BufferOverflowException,
283: IOException {
284: storeSize();
285:
286: //buffer
287: buf.ensureSpace(str.length());
288:
289: for (int i = 0; i < str.length(); i++) {
290: buf.append(str.charAt(i));
291:
292: //Cursor
293: Cursor++;
294: }
295:
296: //screen
297: if (!maskInput) {
298: myIO.write(str);
299: } else {
300: for (int i = 0; i < str.length(); i++) {
301: myIO.write(mask);
302: }
303: }
304: }
305:
306: //append(String)
307: public int getCursorPosition() {
308: return Cursor;
309: }
310:
311: //getCursorPosition
312: public void setCursorPosition(int pos) {
313: if (buf.size() < pos) {
314: Cursor = buf.size();
315: } else {
316: Cursor = pos;
317: }
318:
319: //System.out.println("Editline:cursor:"+Cursor);
320: }
321:
322: //setCursorPosition
323: private char getLastRead() {
324: return lastread;
325: }
326:
327: //getLastRead
328: private void setLastRead(char ch) {
329: lastread = ch;
330: }
331:
332: //setLastRead
333: public boolean isInInsertMode() {
334: return InsertMode;
335: }
336:
337: //isInInsertMode
338: public void setInsertMode(boolean b) {
339: InsertMode = b;
340: }
341:
342: //setInsertMode
343: public boolean isHardwrapped() {
344: return hardwrapped;
345: }
346:
347: //isHardwrapped
348: public void setHardwrapped(boolean b) {
349: hardwrapped = b;
350: }
351:
352: //setHardwrapped
353: public int run() {
354: try {
355: int in = 0;
356:
357: do {
358: //get next key
359: in = myIO.read();
360:
361: //store cursorpos
362: lastcurspos = Cursor;
363:
364: switch (in) {
365: case TerminalIO.LEFT:
366:
367: if (!moveLeft()) {
368: return in;
369: }
370:
371: break;
372:
373: case TerminalIO.RIGHT:
374:
375: if (!moveRight()) {
376: return in;
377: }
378:
379: break;
380:
381: case TerminalIO.BACKSPACE:
382:
383: try {
384: if (Cursor == 0) {
385: return in;
386: } else {
387: removeCharAt(Cursor - 1);
388: }
389: } catch (IndexOutOfBoundsException ioobex) {
390: myIO.bell();
391: }
392:
393: break;
394:
395: case TerminalIO.DELETE:
396:
397: try {
398: removeCharAt(Cursor);
399: } catch (IndexOutOfBoundsException ioobex) {
400: myIO.bell();
401: }
402:
403: break;
404:
405: case TerminalIO.ENTER:
406: case TerminalIO.UP:
407: case TerminalIO.DOWN:
408: case TerminalIO.TABULATOR:
409: return in;
410:
411: default:
412:
413: try {
414: handleCharInput(in);
415: } catch (BufferOverflowException boex) {
416: setLastRead((char) in);
417:
418: return in;
419: }
420: }
421:
422: myIO.flush();
423: } while (true);
424: } catch (IOException ioe) {
425: return TerminalIO.IOERROR;
426: }
427: }
428:
429: //run
430: public void draw() throws IOException {
431: myIO.moveLeft(lastcurspos);
432: myIO.eraseToEndOfLine();
433:
434: if (!maskInput) {
435: myIO.write(buf.toString());
436: } else {
437: for (int i = 0; i < buf.size(); i++) {
438: myIO.write(mask);
439: }
440: }
441:
442: //adjust screen cursor hmm
443: if (Cursor < buf.size()) {
444: myIO.moveLeft(buf.size() - Cursor);
445: }
446: }
447:
448: private boolean moveRight() throws IOException {
449: //cursor
450: if (Cursor < buf.size()) {
451: Cursor++;
452:
453: //screen
454: myIO.moveRight(1);
455:
456: return true;
457: } else {
458: return false;
459: }
460: }
461:
462: private boolean moveLeft() throws IOException {
463: //cursor
464: if (Cursor > 0) {
465: Cursor--;
466:
467: //screen
468: myIO.moveLeft(1);
469:
470: return true;
471: } else {
472: return false;
473: }
474: }
475:
476: private boolean isCursorAtEnd() {
477: return (Cursor == buf.size());
478: }
479:
480: private void handleCharInput(int ch)
481: throws BufferOverflowException, IOException {
482: if (isCursorAtEnd()) {
483: append((char) ch);
484: } else {
485: if (isInInsertMode()) {
486: try {
487: insertCharAt(Cursor, (char) ch);
488: } catch (BufferOverflowException ex) {
489: //ignore buffer overflow on insert
490: myIO.bell();
491: }
492: } else {
493: setCharAt(Cursor, (char) ch);
494: }
495: }
496: }
497:
498: private void storeSize() {
499: lastSize = buf.size();
500: }
501:
502: class Buffer extends CharBuffer {
503: public Buffer(int size) {
504: super(size);
505: }
506: }
507: }
|