changeset 445:8fa8e73e2f5c

update to tn5250j version 0.7.7, svn r1270
author Carl Byington <carl@five-ten-sg.com>
date Mon, 04 Jan 2016 15:52:25 -0800
parents 5a74f1b7c1db
children 5ce5235adde6
files TODO app/src/main/AndroidManifest.xml app/src/main/java/org/tn5250j/TN5250jConstants.java app/src/main/java/org/tn5250j/framework/tn5250/DataStreamDumper.java app/src/main/java/org/tn5250j/framework/tn5250/DataStreamProducer.java app/src/main/java/org/tn5250j/framework/tn5250/ScreenField.java app/src/main/java/org/tn5250j/framework/tn5250/Stream5250.java app/src/main/java/org/tn5250j/framework/tn5250/tnvt.java
diffstat 8 files changed, 269 insertions(+), 263 deletions(-) [+]
line wrap: on
line diff
--- a/TODO	Thu Dec 03 12:33:34 2015 -0800
+++ b/TODO	Mon Jan 04 15:52:25 2016 -0800
@@ -74,6 +74,17 @@
 
 ==================================
 
+merge more tn5250j updates
+svn checkout svn://svn.code.sf.net/p/tn5250j/code/trunk tn5250j-code
+r1270
+
+==================================
+
 TODO:
-change all System.*.println -> android log.d() calls
+change all System.*.println -> android Log.d(TAG, "") calls
 
+possible move to https://github.com/dkocher/sshj
+or https://github.com/hierynomus/sshj
+
+possible merge changes from https://github.com/connectbot/connectbot
+
--- a/app/src/main/AndroidManifest.xml	Thu Dec 03 12:33:34 2015 -0800
+++ b/app/src/main/AndroidManifest.xml	Mon Jan 04 15:52:25 2016 -0800
@@ -17,8 +17,8 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 	package="com.five_ten_sg.connectbot"
-	android:versionName="1.9.2-1"
-	android:versionCode="1921"
+	android:versionName="1.9.3-1"
+	android:versionCode="1931"
 	android:installLocation="auto">
 
 	<uses-sdk android:targetSdkVersion="15" android:minSdkVersion="8" />
--- a/app/src/main/java/org/tn5250j/TN5250jConstants.java	Thu Dec 03 12:33:34 2015 -0800
+++ b/app/src/main/java/org/tn5250j/TN5250jConstants.java	Mon Jan 04 15:52:25 2016 -0800
@@ -27,7 +27,7 @@
     // Version information
     public static final String tn5250jRelease = "0";
     public static final String tn5250jVersion = ".7";
-    public static final String tn5250jSubVer = ".4";
+    public static final String tn5250jSubVer = ".7";
 
     public static final String VERSION_INFO = tn5250jRelease + tn5250jVersion + tn5250jSubVer;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/src/main/java/org/tn5250j/framework/tn5250/DataStreamDumper.java	Mon Jan 04 15:52:25 2016 -0800
@@ -0,0 +1,144 @@
+/**
+ * Title: DataStreamDumper.java
+ * Copyright:   Copyright (c) 2015
+ * Company:
+ *
+ * @author Martin W. Kirst
+ * <p/>
+ * Description:
+ * <p/>
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * <p/>
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * <p/>
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+package org.tn5250j.framework.tn5250;
+
+import org.tn5250j.encoding.ICodePage;
+
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import android.util.Log;
+
+public class DataStreamDumper {
+    private static final String TAG = "DataStreamDumper";
+
+    private AtomicInteger counter = new AtomicInteger(0);
+
+    private FileOutputStream fw;
+    private BufferedOutputStream dw;
+    private boolean dumpActive = false;
+    private ICodePage codePage;
+
+    public void toggleDebug(ICodePage cp) {
+        if (codePage == null) codePage = cp;
+
+        dumpActive = !dumpActive;
+        if (dumpActive) {
+            try {
+                if (fw == null) {
+                    fw = new FileOutputStream("log.txt");
+                    dw = new BufferedOutputStream(fw);
+                }
+            } catch (FileNotFoundException fnfe) {
+                Log.w(TAG, fnfe.getMessage());
+            }
+
+        } else {
+            try {
+                if (dw != null) dw.close();
+                if (fw != null) fw.close();
+                dw = null;
+                fw = null;
+                codePage = null;
+            } catch (IOException ioe) {
+                Log.w(TAG, ioe.getMessage());
+            }
+        }
+
+        Log.i(TAG, "Data Stream output is now " + dumpActive);
+    }
+
+    public void dump(byte[] abyte0) {
+        if (!dumpActive) return;
+
+        try {
+            Log.i(TAG, "\n Buffer Dump of data from AS400: ");
+            dw.write("\r\n Buffer Dump of data from AS400: ".getBytes());
+            StringBuilder h = new StringBuilder();
+
+            for (int x = 0; x < abyte0.length; x++) {
+                if (x % 16 == 0) {
+                    System.out.println("  " + h.toString());
+                    dw.write(("  " + h.toString() + "\r\n").getBytes());
+                    h.setLength(0);
+                    h.append("+0000");
+                    h.setLength(5 - Integer.toHexString(x).length());
+                    h.append(Integer.toHexString(x).toUpperCase());
+                    System.out.print(h.toString());
+                    dw.write(h.toString().getBytes());
+                    h.setLength(0);
+                }
+
+                char ac = codePage.ebcdic2uni(abyte0[x]);
+
+                if (ac < ' ')
+                    h.append('.');
+                else
+                    h.append(ac);
+
+                if (x % 4 == 0) {
+                    System.out.print(" ");
+                    dw.write((" ").getBytes());
+                }
+
+                if (Integer.toHexString(abyte0[x] & 0xff).length() == 1) {
+                    System.out.print("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase());
+                    dw.write(("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes());
+                }
+                else {
+                    System.out.print(Integer.toHexString(abyte0[x] & 0xff).toUpperCase());
+                    dw.write((Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes());
+                }
+            }
+
+            System.out.println();
+            dw.write("\r\n".getBytes());
+            dw.flush();
+        }
+        catch (EOFException _ex) { }
+        catch (Exception _ex) {
+            Log.w(TAG, "Cannot dump from host\n\r");
+        }
+    }
+
+    void dumpRaw(byte[] buffer) {
+        try {
+            String fname = "dump_" + counter.get() + ".data";
+            Log.d(TAG, "Dumping file: " + fname);
+            FileOutputStream fos = new FileOutputStream(fname);
+            fos.write(buffer);
+            fos.close();
+        }
+        catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
--- a/app/src/main/java/org/tn5250j/framework/tn5250/DataStreamProducer.java	Thu Dec 03 12:33:34 2015 -0800
+++ b/app/src/main/java/org/tn5250j/framework/tn5250/DataStreamProducer.java	Mon Jan 04 15:52:25 2016 -0800
@@ -1,35 +1,29 @@
 package org.tn5250j.framework.tn5250;
 
 import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.net.SocketException;
 import java.util.concurrent.BlockingQueue;
+
+import static org.tn5250j.framework.tn5250.Stream5250.OPCODE_OFFSET;
+
 import java.util.Timer;
 import java.util.TimerTask;
 
-import org.tn5250j.encoding.ICodePage;
-
 import android.util.Log;
 
 
 public class DataStreamProducer implements Runnable {
+    private static final int MINIMAL_PARTIAL_STREAM_LEN = 2;
     private static final String TAG = "DataStreamProducer";
     private tnvt                vt;
     private BufferedInputStream bin;
     private ByteArrayOutputStream baosin;
-    private Thread me;
     private byte[] saveStream;
     private final BlockingQueue<Object> dsq;
-    private byte[] abyte2;
-    private FileOutputStream fw;
-    private BufferedOutputStream dw;
-    private boolean dumpBytes = false;
-    private ICodePage codePage;
+    private byte[] dataStream;
+    private DataStreamDumper dataStreamDumper = new DataStreamDumper();
 
 
 
@@ -38,18 +32,14 @@
         this.vt     = vt;
         baosin = new ByteArrayOutputStream();
         dsq = queue;
-        abyte2 = init;
-    }
-
-    public void setInputStream(ByteArrayOutputStream is) {
-        baosin = is;
+        dataStream = init;
     }
 
     public final void run() {
         boolean done = false;
-        me = Thread.currentThread();
+        Thread me = Thread.currentThread();
         // load the first response screen
-        loadStream(abyte2, 0);
+        loadStream(dataStream, 0);
 
         while (!done) {
             try {
@@ -81,71 +71,71 @@
             }
             catch (IOException ioe) {
                 Log.w(TAG, ioe.getMessage());
-
-                if (me.isInterrupted())
-                    done = true;
+                if (me.isInterrupted()) done = true;
             }
             catch (Exception ex) {
                 Log.w(TAG, ex.getMessage());
-
-                if (me.isInterrupted())
-                    done = true;
+                if (me.isInterrupted()) done = true;
             }
         }
     }
 
-    private final void loadStream(byte abyte0[], int i) {
-        int j = 0;
-        int size = 0;
+    private void loadStream(byte streamBuffer[], int offset) {
+
+        int partialLen = (streamBuffer[offset] & 0xff) << 8 | streamBuffer[offset + 1] & 0xff;
+        int bufferLen = streamBuffer.length;
+
+        Log.d(TAG, "loadStream() offset=" + offset + " partialLen=" + partialLen + " bufferLen=" + bufferLen);
 
-        if (saveStream == null) {
-            j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff;
-            size = abyte0.length;
-        }
-        else {
-            size = saveStream.length + abyte0.length;
-            byte[] inter = new byte[size];
+        if (saveStream != null) {
+            log.debug("partial stream found");
+            bufferLen = saveStream.length + streamBuffer.length;
+            byte[] inter = new byte[bufferLen];
             System.arraycopy(saveStream, 0, inter, 0, saveStream.length);
-            System.arraycopy(abyte0, 0, inter, saveStream.length, abyte0.length);
-            abyte0 = new byte[size];
-            System.arraycopy(inter, 0, abyte0, 0, size);
+            System.arraycopy(streamBuffer, 0, inter, saveStream.length, streamBuffer.length);
+            streamBuffer = new byte[bufferLen];
+            System.arraycopy(inter, 0, streamBuffer, 0, bufferLen);
             saveStream = null;
-            inter = null;
-            j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff;
-            Log.d(TAG, "partial stream found");
         }
 
-        if (j > size) {
-            saveStream = new byte[abyte0.length];
-            System.arraycopy(abyte0, 0, saveStream, 0, abyte0.length);
-            Log.d(TAG, "partial stream saved");
-        }
-        else {
-            byte abyte1[];
-
+        if (partialLen > bufferLen) {
+          saveStream = new byte[streamBuffer.length];
+          Log.d(TAG, "partial stream saved");
+          System.arraycopy(streamBuffer, 0, saveStream, 0, streamBuffer.length);
+        } else {
+            int buf_len = partialLen + 2;
+            byte[] buf = new byte[buf_len];
+            if (isBufferShifted(partialLen, bufferLen) && isOpcodeShifted(streamBuffer, offset)) {
+                log.debug("Invalid stream buffer detected. Ignoring the inserted byte.");
+                System.arraycopy(streamBuffer, offset, buf, 0, MINIMAL_PARTIAL_STREAM_LEN);
+                System.arraycopy(streamBuffer, offset + MINIMAL_PARTIAL_STREAM_LEN + 1, buf, MINIMAL_PARTIAL_STREAM_LEN, partialLen);
+            } else {
+                System.arraycopy(streamBuffer, offset, buf, 0, buf_len);
+            }
             try {
-                abyte1 = new byte[j + 2];
-                System.arraycopy(abyte0, i, abyte1, 0, j + 2);
-                dsq.put(abyte1);
-
-                if (abyte0.length > abyte1.length + i)
-                    loadStream(abyte0, i + j + 2);
-            }
-            catch (Exception ex) {
-                Log.w(TAG, "load stream error " + ex.getMessage());
-                //        ex.printStackTrace();
-                //        dump(abyte0);
+                dsq.put(buf);
+                if (streamBuffer.length > buf.length + offset + MINIMAL_PARTIAL_STREAM_LEN)
+                    loadStream(streamBuffer, offset + buf_len);
+            } catch (InterruptedException ex) {
+                Log.w(TAG, "load stream error.", ex);
             }
         }
     }
 
-    public final byte[] readIncoming()
-    throws IOException {
+    private boolean isOpcodeShifted(byte[] streamBuffer, int offset) {
+        byte code = streamBuffer[offset + 1 + OPCODE_OFFSET];
+        return (0 <= code && code <= 12);
+    }
+
+    private boolean isBufferShifted(int partialLen, int bufferLen) {
+        return partialLen + MINIMAL_PARTIAL_STREAM_LEN + 1 == bufferLen;
+    }
+
+    public final byte[] readIncoming() throws IOException {
         boolean done = false;
         boolean negotiate = false;
         baosin.reset();
         int j = -1;
-        int i = 0;
         Timer timer = new Timer("data.stream", true);
         TimerTask task = null;
 
@@ -164,7 +154,7 @@
                 timer.schedule(task, 10);   // 10 ms delay
             }
 
-            i = bin.read();
+            int i = bin.read();
 
             if (task != null) {
                 task.cancel();
@@ -235,9 +225,7 @@
         //     Impacts the run method! Added the null check.
         byte[] rBytes = baosin.toByteArray();
 
-        if (dumpBytes) {
-            dump(rBytes);
-        }
+        dataStreamDumper.dump(rBytes);
 
         if (negotiate) {
             if (bin.available() == 0) {
@@ -269,104 +257,7 @@
         return rBytes;
     }
 
-    protected final void toggleDebug(ICodePage cp) {
-        if (codePage == null)
-            codePage = cp;
-
-        dumpBytes = !dumpBytes;
-
-        if (dumpBytes) {
-            try {
-                if (fw == null) {
-                    fw = new FileOutputStream("log.txt");
-                    dw = new BufferedOutputStream(fw);
-                }
-            }
-            catch (FileNotFoundException fnfe) {
-                Log.w(TAG, fnfe.getMessage());
-            }
-        }
-        else {
-            try {
-                if (dw != null)
-                    dw.close();
-
-                if (fw != null)
-                    fw.close();
-
-                dw = null;
-                fw = null;
-                codePage = null;
-            }
-            catch (IOException ioe) {
-                Log.w(TAG, ioe.getMessage());
-            }
-        }
-
-        Log.i(TAG, "Data Stream output is now " + dumpBytes);
+    protected void toggleDebug(ICodePage codePage) {
+        dataStreamDumper.toggleDebug(codePage);
     }
 
-    public void dump(byte[] abyte0) {
-        try {
-            Log.i(TAG, "\n Buffer Dump of data from AS400: ");
-            dw.write("\r\n Buffer Dump of data from AS400: ".getBytes());
-            StringBuffer h = new StringBuffer();
-
-            for (int x = 0; x < abyte0.length; x++) {
-                if (x % 16 == 0) {
-                    System.out.println("  " + h.toString());
-                    dw.write(("  " + h.toString() + "\r\n").getBytes());
-                    h.setLength(0);
-                    h.append("+0000");
-                    h.setLength(5 - Integer.toHexString(x).length());
-                    h.append(Integer.toHexString(x).toUpperCase());
-                    System.out.print(h.toString());
-                    dw.write(h.toString().getBytes());
-                    h.setLength(0);
-                }
-
-                char ac = codePage.ebcdic2uni(abyte0[x]);
-
-                if (ac < ' ')
-                    h.append('.');
-                else
-                    h.append(ac);
-
-                if (x % 4 == 0) {
-                    System.out.print(" ");
-                    dw.write((" ").getBytes());
-                }
-
-                if (Integer.toHexString(abyte0[x] & 0xff).length() == 1) {
-                    System.out.print("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase());
-                    dw.write(("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes());
-                }
-                else {
-                    System.out.print(Integer.toHexString(abyte0[x] & 0xff).toUpperCase());
-                    dw.write((Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes());
-                }
-            }
-
-            System.out.println();
-            dw.write("\r\n".getBytes());
-            dw.flush();
-        }
-        catch (EOFException _ex) { }
-        catch (Exception _ex) {
-            Log.w(TAG, "Cannot dump from host\n\r");
-        }
-    }
-
-//      public void dumpBytes() {
-//         byte shit[] = bk.buffer;
-//         for (int i = 0;i < shit.length;i++)
-//            System.out.println(i + ">" + shit[i] + "< - ascii - >" + getASCIIChar(shit[i]) + "<");
-//      }
-//
-//      public void dumpHexBytes(byte[] abyte) {
-//         byte shit[] = abyte;
-//         for (int i = 0;i < shit.length;i++)
-//            System.out.println(i + ">" + shit[i] + "< hex >" + Integer.toHexString((shit[i] & 0xff)));
-//      }
-
-}
--- a/app/src/main/java/org/tn5250j/framework/tn5250/ScreenField.java	Thu Dec 03 12:33:34 2015 -0800
+++ b/app/src/main/java/org/tn5250j/framework/tn5250/ScreenField.java	Mon Jan 04 15:52:25 2016 -0800
@@ -457,24 +457,24 @@
     /**
      * Sets the field's text plane to the specified string. If the string is
      * shorter than the length of the field, the rest of the field is cleared.
-     * If the string is longer than the field, the text is truncated. A subsequent
-     * call to getText on this field will not show the changed text. To see the
-     * changed text, do a refresh on the iOhioFields collection and retrieve the
-     * refreshed field object.
+	 * If the string is longer than the field, the text is truncated. A
+	 * subsequent call to getText on this field will not show the changed text.
+	 * To see the changed text, do a refresh on the iOhioFields collection and
+	 * retrieve the refreshed field object.
      *
-     * @param text - The text to be placed in the field's text plane.
+	 * @param text
+	 *            - The text to be placed in the field's text plane.
      */
     public void setString(String text) {
-		cursorPos = startPos;
+		cursorPos = isRightToLeft() ? endPos - text.length() + 1 : startPos;
 
 		if (isRightToLeft()) {
 			text = new StringBuilder(text).reverse().toString();
 		}
 
-		final ScreenPlanes planes = s.getPlanes();
-		for (int x = 0,len = text.length(); x < length; x++) {
-			char tc = (x < len) ? text.charAt(x) : ' ';
-			planes.setChar(cursorPos, tc);
+		for (int x = 0, textLen = text.length(); x < length; x++) {
+			char tc = x < textLen ? text.charAt(x) : ' ';
+			s.getPlanes().setChar(cursorPos, tc);
 			changePos(1);
 		}
 		setMDT();
--- a/app/src/main/java/org/tn5250j/framework/tn5250/Stream5250.java	Thu Dec 03 12:33:34 2015 -0800
+++ b/app/src/main/java/org/tn5250j/framework/tn5250/Stream5250.java	Mon Jan 04 15:52:25 2016 -0800
@@ -26,6 +26,7 @@
 package org.tn5250j.framework.tn5250;
 
 public class Stream5250 {
+    public static final int OPCODE_OFFSET = 9;
 
     public int streamSize;
     public int opCode;
@@ -60,7 +61,7 @@
         buffer = abyte0;
         // size without end of record 0xFF 0xEF
         streamSize = (abyte0[0] & 0xff) << 8 | abyte0[1] & 0xff;
-        opCode = abyte0[9];
+     opCode = abyte0[OPCODE_OFFSET];
         dataStart = 6 + abyte0[6];
         pos = dataStart;
     }
--- a/app/src/main/java/org/tn5250j/framework/tn5250/tnvt.java	Thu Dec 03 12:33:34 2015 -0800
+++ b/app/src/main/java/org/tn5250j/framework/tn5250/tnvt.java	Mon Jan 04 15:52:25 2016 -0800
@@ -300,9 +300,7 @@
 
             producer = new DataStreamProducer(this, bin, dsq, abyte0);
             pthread = new Thread(producer);
-            //         pthread.setPriority(pthread.MIN_PRIORITY);
             pthread.setPriority(Thread.NORM_PRIORITY);
-            //          pthread.setPriority(Thread.NORM_PRIORITY / 2);
             pthread.start();
 
             try {
@@ -576,7 +574,6 @@
         //       row - first ##
         //       column - second ##
         //       F3 - Help Aid Key
-        //      System.out.println("Help request sent");
         baosp.write(screen52.getCurrentRow());
         baosp.write(screen52.getCurrentCol());
         baosp.write(AID_HELP);
@@ -609,8 +606,6 @@
         // bit 5 - SRQ system request
         // bit 6 - TRQ Test request key
         // bit 7 - HLP
-
-        //      System.out.println("Attention key sent");
         try {
             Log.i(TAG, "sendAttentionKey() writeGDS()");
             writeGDS(0x40, 0, null);
@@ -831,7 +826,7 @@
             ScreenPlanes planes = screen52.getPlanes();
             c = planes.getChar(str);
             boolean waitFor = !(c == 'a');
-            StringBuffer command = new StringBuffer();
+            StringBuilder command = new StringBuilder();
 
             for (int i = str + 1; i < 132; i++) {
                 c = planes.getChar(i);
@@ -877,7 +872,7 @@
      * @param scan
      *            if true, scanning is enabled; disabled otherwise.
      *
-     * @see scan4Cmd()
+     * @see #scan()
      */
     public void setScanningEnabled(boolean scan) {
         this.scan = scan;
@@ -899,10 +894,9 @@
      * second character in the datastream (the zero position allows to
      * devisualize the scan stream). If the sequence <code>#!</code> is
      * encountered and if this sequence is <strong>not </strong> followed by a
-     * blank character, the {@link parseCommand(ScreenChar[])}is called.
+     * blank character, the {@link parseCommand()}is called.
      */
     private void scan() {
-        //     System.out.println("Checking command : " +
         // screen52.screen[1].getChar() + screen52.screen[2].getChar());
         //      ScreenChar[] screen = screen52.screen;
         ScreenPlanes planes = screen52.getPlanes();
@@ -1080,8 +1074,8 @@
                     strpccmd();
                 }
             }
-            catch (Exception exd) {
-                Log.w(TAG, " tnvt.run: " + exd.getMessage());
+            catch (RuntimeException e) {
+                Log.w(TAG, " tnvt.run: " + e.getMessage());
                 exd.printStackTrace();
             }
 
@@ -1109,32 +1103,27 @@
     private final void readScreen() throws IOException {
         int rows = screen52.getRows();
         int cols = screen52.getColumns();
-        byte abyte0[] = new byte[rows * cols];
-        fillScreenArray(abyte0, rows, cols);
+        byte screenArray[] = new byte[rows * cols];
+        fillScreenArray(screenArray, rows, cols);
         Log.i(TAG, "readScreen() writeGDS()");
-        writeGDS(0, 0, abyte0);
-        abyte0 = null;
+        writeGDS(0, 0, screenArray);
     }
 
-    private final void fillScreenArray(byte[] sa, int rows, int cols) {
-        int la = 32;
-        int sac = 0;
-        int len = rows * cols;
+    private final void fillScreenArray(byte[] sa) {
         ScreenPlanes planes = screen52.planes;
 
         try {
-            for (int y = 0; y < len; y++) { // save the screen data
-                if (planes.isAttributePlace(y)) {
-                    la = planes.getCharAttr(y);
-                    sa[sac++] = (byte) la;
+            for (int i = 0; i < sa.length; i++) { // save the screen data
+                if (planes.isAttributePlace(i)) {
+                    sa[i] = (byte) planes.getCharAttr(i);
                 }
                 else {
                     //  The characters on screen are in unicode
-                    char ch = planes.getChar(y);
+                    char ch = planes.getChar(i);
                     byte byteCh;
                     if (isDataUnicode(ch)) byteCh = codePage.uni2ebcdic(ch);
                     else                   byteCh = (byte) ch;
-                    sa[sac++] = byteCh;
+                    sa[i] = byteCh;
                 }
             }
         }
@@ -1144,20 +1133,18 @@
         }
     }
 
-    private final void fillRegenerationBuffer(ByteArrayOutputStream sc, int rows, int cols)
-    throws IOException {
+	private byte[] createRegenerationBuffer(int len) throws IOException {
         int la = 32;
         int sac = 0;
-        int len = rows * cols;
         ScreenPlanes planes = screen52.planes;
         byte[] sa = new byte[len];
 
         try {
             boolean guiExists = sfParser != null && sfParser.isGuisExists();
 
-            for (int y = 0; y < len; y++) { // save the screen data
+            for (int i = 0; i < len; i++) { // save the screen data
                 if (guiExists) {
-                    byte[] guiSeg = sfParser.getSegmentAtPos(y);
+                    byte[] guiSeg = sfParser.getSegmentAtPos(i);
 
                     if (guiSeg != null) {
                         //Log.i(TAG," gui saved at " + y + " - " + screen52.getRow(y) + "," +
@@ -1170,18 +1157,16 @@
                         sa[sac++] = (byte)0x04;
                         sa[sac++] = (byte)0x11;
                         sac += guiSeg.length;
-                        //y--;
-                        //               continue;
                     }
                 }
 
-                if (planes.isAttributePlace(y)) {
-                    la = planes.getCharAttr(y);
+                if (planes.isAttributePlace(i)) {
+                    la = planes.getCharAttr(i);
                     sa[sac++] = (byte) la;
                 }
                 else {
                     //  The characters on screen are in unicode
-                    char ch = planes.getChar(y);
+                    char ch = planes.getChar(i);
                     byte byteCh;
                     if (isDataUnicode(ch)) byteCh = codePage.uni2ebcdic(ch);
                     else                   byteCh = (byte) ch;
@@ -1193,57 +1178,42 @@
             Log.i(TAG, exc.getMessage());
             exc.printStackTrace();
         }
-
-        sc.write(sa);
+        return sa;
     }
 
     public final void saveScreen() throws IOException {
         ByteArrayOutputStream sc = new ByteArrayOutputStream();
-        sc.write(4);
-        sc.write(0x12); // 18
-        sc.write(0); // 18
-        sc.write(0); // 18
-        sc.write((byte) screen52.getRows()); // store the current size
-        sc.write((byte) screen52.getColumns()); //    ""
+		sc.write(new byte[] {4, 0x12, 0, 0});
+        sc.write((byte) screen52.getRows());    // store the current size
+        sc.write((byte) screen52.getColumns()); // ""
         int cp = screen52.getCurrentPos(); // save off current position
-        // fix below submitted by Mitch Blevins
-        //int cp = screen52.getScreenFields().getCurrentFieldPos();
-        // save off current position
-        sc.write((byte)(cp >> 8 & 0xff));  //    ""
-        sc.write((byte)(cp & 0xff));  //    ""
+        sc.write((byte)(cp >> 8 & 0xff));  // ""
+        sc.write((byte)(cp & 0xff));       // ""
         sc.write((byte)(screen52.homePos >> 8 & 0xff));  // save home pos
-        sc.write((byte)(screen52.homePos & 0xff));  //    ""
-        int rows = screen52.getRows(); // store the current size
-        int cols = screen52.getColumns(); //    ""
-        //      byte[] sa = new byte[rows * cols];
-        fillRegenerationBuffer(sc, rows, cols);
-        //      fillScreenArray(sa, rows, cols);
-        //
-        //      sc.write(sa);
-        //      sa = null;
+        sc.write((byte)(screen52.homePos & 0xff));       // ""
+		sc.write(createRegenerationBuffer(screen52.getRows() * screen52.getColumns()));
         int sizeFields = screen52.getScreenFields().getSize();
-        sc.write((byte)(sizeFields >> 8 & 0xff));  //    ""
-        sc.write((byte)(sizeFields & 0xff));  //    ""
+        sc.write((byte)(sizeFields >> 8 & 0xff));  // save number of fields
+        sc.write((byte)(sizeFields & 0xff));       // ""
 
         if (sizeFields > 0) {
             int x = 0;
             int s = screen52.getScreenFields().getSize();
-            ScreenField sf = null;
 
             while (x < s) {
-                sf = screen52.getScreenFields().getField(x);
-                sc.write((byte) sf.getAttr()); // attribute
+                ScreenField sf = screen52.getScreenFields().getField(x);
+                sc.write((byte) sf.getAttr());      // attribute
                 int sp = sf.startPos();
-                sc.write((byte)(sp >> 8 & 0xff));  //    ""
-                sc.write((byte)(sp & 0xff));  //    ""
+                sc.write((byte)(sp >> 8 & 0xff));   // position
+                sc.write((byte)(sp & 0xff));        // ""
 
                 if (sf.mdt)
                     sc.write((byte) 1);
                 else
                     sc.write((byte) 0);
 
-                sc.write((byte)(sf.getLength() >> 8 & 0xff));  //    ""
-                sc.write((byte)(sf.getLength() & 0xff));  //    ""
+                sc.write((byte)(sf.getLength() >> 8 & 0xff));
+                sc.write((byte)(sf.getLength() & 0xff));
                 sc.write((byte) sf.getFFW1() & 0xff);
                 sc.write((byte) sf.getFFW2() & 0xff);
                 sc.write((byte) sf.getFCW1() & 0xff);
@@ -1252,8 +1222,6 @@
                 Log.d(TAG, sf.toString());
                 x++;
             }
-
-            sf = null;
         }
 
         // The following two lines of code looks to have caused all sorts of
@@ -1269,8 +1237,6 @@
         catch (IOException ioe) {
             Log.w(TAG, ioe.getMessage());
         }
-
-        sc = null;
         Log.d(TAG, "Save Screen end ");
     }
 
@@ -1886,7 +1852,6 @@
                     //break;
 
                     default: // all others must be output to screen
-                        //Log.d(TAG,"all others must be output to screen");
                         byte byte0 = bk.getByteOffset(-1);
 
                         if (isAttribute(byte0)) {
@@ -1926,7 +1891,6 @@
         }
         catch (Exception e) {
             Log.w(TAG, "write to display " + e.getMessage());
-            e.printStackTrace();
         }
 
         ;
@@ -2057,12 +2021,10 @@
             pendingUnlock = false;
 
         if (resetMDT || resetMDTAll || nullMDT || nullAll) {
-            ScreenField sf;
             int f = screen52.getScreenFields().getSize();
 
             for (int x = 0; x < f; x++) {
-                sf = screen52.getScreenFields().getField(x);
-
+                ScreenField sf = screen52.getScreenFields().getField(x);
                 if (!sf.isBypassField()) {
                     if ((nullMDT && sf.mdt) || nullAll) {
                         sf.setFieldChar((char) 0x0);
@@ -2073,8 +2035,6 @@
                 if (resetMDTAll || (resetMDT && !sf.isBypassField()))
                     sf.resetMDT();
             }
-
-            sf = null;
         }
     }
 
@@ -2154,8 +2114,8 @@
     //  The first 32 characters are non displayable characters
     //  This is normally the inverse of isDataEBCDIC (That's why there is a
     //  check on 255 -> 0xFFFF
-    private boolean isDataUnicode(int byte0) {
-        return (((byte0 < 0) || (byte0 >= 32)) && (byte0 != 0xFFFF));
+    private boolean isDataUnicode(int data) {
+        return (((data < 0) || (data >= 32)) && (data != 0xFFFF));
     }
 
     private void writeStructuredField() {
@@ -2379,8 +2339,7 @@
                                     break;
 
                                 case TIMING_MARK: // 6   rfc860
-                                    //                        System.out.println("Timing Mark Received and notifying " +
-                                    //                        "the server that we will not do it");
+                                    Log.d(TAG, "Timing Mark Received and notifying the server that we will not do it.");
                                     baosp.write(IAC);
                                     baosp.write(WONT);
                                     baosp.write(TIMING_MARK);
@@ -2570,7 +2529,7 @@
             return devName;
         }
         else {
-            StringBuffer sb = new StringBuffer(devName + devSeq);
+            StringBuilder sb = new StringBuilder(devName + devSeq);
             int ei = 1;
 
             while (sb.length() > 10) {