diff app/src/main/java/org/tn5250j/framework/tn5250/Screen5250.java @ 438:d29cce60f393

migrate from Eclipse to Android Studio
author Carl Byington <carl@five-ten-sg.com>
date Thu, 03 Dec 2015 11:23:55 -0800
parents src/org/tn5250j/framework/tn5250/Screen5250.java@b525a8141923
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/src/main/java/org/tn5250j/framework/tn5250/Screen5250.java	Thu Dec 03 11:23:55 2015 -0800
@@ -0,0 +1,3738 @@
+/*
+ * Title: Screen5250.java
+ * Copyright:   Copyright (c) 2001 - 2004
+ * Company:
+ * @author  Kenneth J. Pouncey
+ * @version 0.5
+ *
+ * Description:
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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 static org.tn5250j.TN5250jConstants.*;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Vector;
+
+import org.tn5250j.TN5250jConstants;
+
+import android.util.Log;
+import de.mud.terminal.VDUBuffer;
+import de.mud.terminal.vt320;
+import com.five_ten_sg.connectbot.service.FontSizeChangedListener;
+
+
+public class Screen5250 implements FontSizeChangedListener {
+    private static final String TAG = "Screen5250";
+    private ScreenFields screenFields;
+    private int lastAttr;
+    private int lastPos;
+    private int lenScreen;
+    private KeyStrokenizer strokenizer;
+    private tnvt sessionVT;
+    private vt320 buffer;       // used to draw the screen
+    private int numRows = 0;
+    private int numCols = 0;
+    protected static final int initAttr = 32;
+    protected static final char initChar = 0;
+    public boolean cursorActive = false;
+    public boolean cursorShown = false;
+    protected boolean insertMode = false;
+    private boolean keyProcessed = false;
+    private Rect dirtyScreen = new Rect();
+
+    public int homePos = 0;
+    public int saveHomePos = 0;
+    private String bufferedKeys;
+    public boolean pendingInsert = false;
+
+    public final static byte STATUS_SYSTEM = 1;
+    public final static byte STATUS_ERROR_CODE = 2;
+    public final static byte STATUS_VALUE_ON = 1;
+    public final static byte STATUS_VALUE_OFF = 2;
+
+    private StringBuffer hsMore = new StringBuffer("More...");
+    private StringBuffer hsBottom = new StringBuffer("Bottom");
+
+    // error codes to be sent to the host on an error
+    private final static int ERR_CURSOR_PROTECTED = 0x05;
+    private final static int ERR_INVALID_SIGN = 0x11;
+    private final static int ERR_NO_ROOM_INSERT = 0x12;
+    private final static int ERR_NUMERIC_ONLY = 0x09;
+    private final static int ERR_DUP_KEY_NOT_ALLOWED = 0x19;
+    private final static int ERR_NUMERIC_09 = 0x10;
+    private final static int ERR_FIELD_MINUS = 0x16;
+    private final static int ERR_FIELD_EXIT_INVALID = 0x18;
+    private final static int ERR_ENTER_NO_ALLOWED = 0x20;
+    private final static int ERR_MANDATORY_ENTER = 0x21;
+
+    private boolean guiInterface = false;
+    private boolean resetRequired = false;
+    private boolean backspaceError = true;
+    private boolean feError;
+
+    // Operator Information Area
+    private ScreenOIA oia;
+
+    // screen planes
+    protected ScreenPlanes planes;
+
+
+
+    public Screen5250() {
+        try {
+            jbInit();
+        }
+        catch (Exception ex) {
+            Log.w(TAG, "In constructor: ", ex);
+        }
+    }
+
+    void jbInit() throws Exception {
+        lastAttr = 32;
+        // default number of rows and columns
+        numRows = 24;
+        numCols = 80;
+        setCursor(1, 1); // set initial cursor position
+        oia = new ScreenOIA(this);
+        oia.setKeyBoardLocked(true);
+        lenScreen = numRows * numCols;
+        planes = new ScreenPlanes(this, numRows);
+        screenFields = new ScreenFields(this);
+        strokenizer = new KeyStrokenizer();
+    }
+
+    protected ScreenPlanes getPlanes() {
+        return planes;
+    }
+
+    public final ScreenOIA getOIA() {
+        return oia;
+    }
+
+    protected final void setRowsCols(int rows, int cols) {
+        int oldRows = numRows;
+        int oldCols = numCols;
+        // default number of rows and columns
+        numRows = rows;
+        numCols = cols;
+        lenScreen = numRows * numCols;
+        planes.setSize(rows);
+
+        //  If they are not the same then we need to inform the listeners that
+        //  the size changed.
+        if (oldRows != numRows || oldCols != numCols)
+            fireScreenSizeChanged();
+    }
+
+
+    public boolean isCursorActive() {
+        return cursorActive;
+    }
+
+    public boolean isCursorShown() {
+        return cursorShown;
+    }
+
+    public void setUseGUIInterface(boolean gui) {
+        guiInterface = gui;
+    }
+
+    public void toggleGUIInterface() {
+        guiInterface = !guiInterface;
+    }
+
+    public void setResetRequired(boolean reset) {
+        resetRequired = reset;
+    }
+
+    public void setBackspaceError(boolean onError) {
+        backspaceError = onError;
+    }
+
+    /**
+     * Copy & Paste support
+     *
+     * @see {@link #pasteText(String, boolean)}
+     * @see {@link #copyTextField(int)}
+     */
+    public final String copyText(Rect area) {
+        StringBuilder sb = new StringBuilder();
+        Rect workR = new Rect();
+        workR.setBounds(area);
+        Log.d(TAG, "Copying " + workR);
+        // loop through all the screen characters to send them to the clip board
+        int m = workR.x;
+        int i = 0;
+        int t = 0;
+
+        while (workR.height-- > 0) {
+            t = workR.width;
+            i = workR.y;
+
+            while (t-- > 0) {
+                // only copy printable characters (in this case >= ' ')
+                char c = planes.getChar(getPos(m - 1, i - 1));
+
+                if (c >= ' ' && (planes.screenExtended[getPos(m - 1, i - 1)] & EXTENDED_5250_NON_DSP)
+                        == 0)
+                    sb.append(c);
+                else
+                    sb.append(' ');
+
+                i++;
+            }
+
+            sb.append('\n');
+            m++;
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Copy & Paste support
+     *
+     * @param content
+     * @see {@link #copyText(Rectangle)}
+     */
+    public final void pasteText(String content, boolean special) {
+        Log.d(TAG, "Pasting, special:" + special);
+        setCursorActive(false);
+        StringBuilder sb = new StringBuilder(content);
+        StringBuilder pd = new StringBuilder();
+        // character counters within the string to be pasted.
+        int nextChar = 0;
+        int nChars = sb.length();
+        int lr = getRow(lastPos);
+        int lc = getCol(lastPos);
+        resetDirty(lastPos);
+        int cpos = lastPos;
+        int length = getScreenLength();
+        char c = 0;
+        boolean setIt;
+        // save our current place within the FFT.
+        screenFields.saveCurrentField();
+
+        for (int x = nextChar; x < nChars; x++) {
+            c = sb.charAt(x);
+
+            if ((c == '\n') || (c == '\r')) {
+                Log.i(TAG, "pasted cr-lf>" + pd + "<");
+                pd.setLength(0);
+                // if we read in a cr lf in the data stream we need to go
+                // to the starting column of the next row and start from there
+                cpos = getPos(getRow(cpos) + 1, lc);
+
+                // If we go paste the end of the screen then let's start over from
+                //   the beginning of the screen space.
+                if (cpos > length)
+                    cpos = 0;
+            }
+            else {
+                // we will default to set the character always.
+                setIt = true;
+
+                // If we are in a special paste scenario then we check for valid
+                //   characters to paste.
+                if (special && (!Character.isLetter(c) && !Character.isDigit(c)))
+                    setIt = false;
+
+                // we will only push a character to the screen space if we are in
+                //  a field
+                if (isInField(cpos) && setIt) {
+                    planes.setChar(cpos, c);
+                    setDirty(cpos);
+                    screenFields.setCurrentFieldMDT();
+                }
+
+                //  If we placed a character then we go to the next position.
+                if (setIt)
+                    cpos++;
+
+                // we will append the information to our debug buffer.
+                pd.append(c);
+            }
+        }
+
+        // if we have anything else not logged then log it out.
+        if (pd.length() > 0)
+            Log.i(TAG, "pasted >" + pd + "<");
+
+        // restore out position within the FFT.
+        screenFields.restoreCurrentField();
+        updateDirty();
+        // restore our cursor position.
+        setCursor(lr + 1, lc + 1);
+        setCursorActive(true);
+    }
+
+    /**
+     * Copy & Paste support
+     *
+     * @param position
+     * @return
+     * @see {@link #copyText(int)}
+     */
+    public final String copyTextField(int position) {
+        screenFields.saveCurrentField();
+        isInField(position);
+        String result = screenFields.getCurrentFieldText();
+        screenFields.restoreCurrentField();
+        return result;
+    }
+
+    /**
+     *
+     * Copy & Paste end code
+     *
+     */
+
+    /**
+     * Sum them
+     *
+     * @param which
+     *            formatting option to use
+     * @return vector string of numberic values
+     */
+    public final Vector<Double> sumThem(boolean which, Rect area) {
+        StringBuilder sb = new StringBuilder();
+        Rect workR = new Rect();
+        workR.setBounds(area);
+        //      gui.rubberband.reset();
+        //      gui.repaint();
+        Log.d(TAG, "Summing");
+        // obtain the decimal format for parsing
+        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
+        DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
+
+        if (which) {
+            dfs.setDecimalSeparator('.');
+            dfs.setGroupingSeparator(',');
+        }
+        else {
+            dfs.setDecimalSeparator(',');
+            dfs.setGroupingSeparator('.');
+        }
+
+        df.setDecimalFormatSymbols(dfs);
+        Vector<Double> sumVector = new Vector<Double>();
+        // loop through all the screen characters to send them to the clip board
+        int m = workR.x;
+        int i = 0;
+        int t = 0;
+        double sum = 0.0;
+
+        while (workR.height-- > 0) {
+            t = workR.width;
+            i = workR.y;
+
+            while (t-- > 0) {
+                // only copy printable numeric characters (in this case >= ' ')
+                //              char c = screen[getPos(m - 1, i - 1)].getChar();
+                char c = planes.getChar(getPos(m - 1, i - 1));
+                //              if (((c >= '0' && c <= '9') || c == '.' || c == ',' || c == '-')
+                //                      && !screen[getPos(m - 1, i - 1)].nonDisplay) {
+
+                // TODO: update me here to implement the nonDisplay check as well
+                if (((c >= '0' && c <= '9') || c == '.' || c == ',' || c == '-')) {
+                    sb.append(c);
+                }
+
+                i++;
+            }
+
+            if (sb.length() > 0) {
+                if (sb.charAt(sb.length() - 1) == '-') {
+                    sb.insert(0, '-');
+                    sb.deleteCharAt(sb.length() - 1);
+                }
+
+                try {
+                    Number n = df.parse(sb.toString());
+                    //               System.out.println(s + " " + n.doubleValue());
+                    sumVector.add(new Double(n.doubleValue()));
+                    sum += n.doubleValue();
+                }
+                catch (ParseException pe) {
+                    Log.w(TAG, pe.getMessage() + " at "
+                          + pe.getErrorOffset());
+                }
+            }
+
+            sb.setLength(0);
+            m++;
+        }
+
+        Log.d(TAG, "" + sum);
+        return sumVector;
+    }
+
+    public void setVT(tnvt v) {
+        sessionVT = v;
+    }
+
+    public void setBuffer(vt320 buffer) {
+        this.buffer = buffer;
+    }
+
+    /**
+     * converts mnemonic string values into aid integers
+     *
+     * @see #sendKeys
+     * @param mnem string mnemonic value
+     * @return key value of Mnemonic
+     */
+    private int getMnemonicValue(String mnem) {
+        if (mnemonicMap.containsKey(mnem)) return mnemonicMap.get(mnem);
+
+        return 0;
+    }
+
+    protected void setPrehelpState(boolean setErrorCode, boolean lockKeyboard,
+                                   boolean unlockIfLocked) {
+        if (oia.isKeyBoardLocked() && unlockIfLocked)
+            oia.setKeyBoardLocked(false);
+        else
+            oia.setKeyBoardLocked(lockKeyboard);
+
+        bufferedKeys = null;
+        oia.setKeysBuffered(false);
+    }
+
+    /**
+     * Activate the cursor on screen
+     *
+     * @param activate
+     */
+    public void setCursorActive(boolean activate) {
+        //      System.out.println("cursor active " + updateCursorLoc + " " +
+        // cursorActive + " " + activate);
+        if (cursorActive && !activate) {
+            setCursorOff();
+            cursorActive = activate;
+        }
+        else {
+            if (!cursorActive && activate) {
+                cursorActive = activate;
+                setCursorOn();
+            }
+        }
+    }
+
+    /**
+     * Set the cursor on
+     */
+    public void setCursorOn() {
+        cursorShown = true;
+        updateCursorLoc();
+    }
+
+    /**
+     * Set the cursor off
+     */
+    public void setCursorOff() {
+        cursorShown = false;
+        updateCursorLoc();
+        //      System.out.println("cursor off " + updateCursorLoc + " " +
+        // cursorActive);
+    }
+
+    /**
+     *
+     */
+    private void updateCursorLoc() {
+        if (cursorActive) {
+            fireCursorChanged();
+        }
+    }
+
+    /**
+     * The sendKeys method sends a string of keys to the virtual screen. This
+     * method acts as if keystrokes were being typed from the keyboard. The
+     * keystrokes will be sent to the location given. The string being passed
+     * can also contain mnemonic values such as [enter] enter key,[tab] tab key,
+     * [pf1] pf1 etc...
+     *
+     * These will be processed as if you had pressed these keys from the
+     * keyboard. All the valid special key values are contained in the MNEMONIC
+     * enumeration:
+     *
+     * <table BORDER COLS=2 WIDTH="50%" >
+     *
+     * <tr>
+     * <td>MNEMONIC_CLEAR</td>
+     * <td>[clear]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_ENTER</td>
+     * <td>[enter]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_HELP</td>
+     * <td>[help]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PAGE_DOWN</td>
+     * <td>[pgdown]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PAGE_UP</td>
+     * <td>[pgup]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PRINT</td>
+     * <td>[print]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF1</td>
+     * <td>[pf1]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF2</td>
+     * <td>[pf2]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF3</td>
+     * <td>[pf3]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF4</td>
+     * <td>[pf4]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF5</td>
+     * <td>[pf5]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF6</td>
+     * <td>[pf6]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF7</td>
+     * <td>[pf7]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF8</td>
+     * <td>[pf8]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF9</td>
+     * <td>[pf9]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF10</td>
+     * <td>[pf10]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF11</td>
+     * <td>[pf11]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF12</td>
+     * <td>[pf12]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF13</td>
+     * <td>[pf13]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF14</td>
+     * <td>[pf14]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF15</td>
+     * <td>[pf15]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF16</td>
+     * <td>[pf16]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF17</td>
+     * <td>[pf17]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF18</td>
+     * <td>[pf18]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF19</td>
+     * <td>[pf19]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF20</td>
+     * <td>[pf20]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF21</td>
+     * <td>[pf21]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF22</td>
+     * <td>[pf22]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF23</td>
+     * <td>[pf23]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PF24</td>
+     * <td>[pf24]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_BACK_SPACE</td>
+     * <td>[backspace]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_BACK_TAB</td>
+     * <td>[backtab]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_UP</td>
+     * <td>[up]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_DOWN</td>
+     * <td>[down]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_LEFT</td>
+     * <td>[left]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_RIGHT</td>
+     * <td>[right]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_DELETE</td>
+     * <td>[delete]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_TAB</td>
+     * <td>"[tab]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_END_OF_FIELD</td>
+     * <td>[eof]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_ERASE_EOF</td>
+     * <td>[eraseeof]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_ERASE_FIELD</td>
+     * <td>[erasefld]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_INSERT</td>
+     * <td>[insert]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_HOME</td>
+     * <td>[home]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD0</td>
+     * <td>[keypad0]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD1</td>
+     * <td>[keypad1]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD2</td>
+     * <td>[keypad2]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD3</td>
+     * <td>[keypad3]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD4</td>
+     * <td>[keypad4]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD5</td>
+     * <td>[keypad5]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD6</td>
+     * <td>[keypad6]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD7</td>
+     * <td>[keypad7]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD8</td>
+     * <td>[keypad8]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD9</td>
+     * <td>[keypad9]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD_PERIOD</td>
+     * <td>[keypad.]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD_COMMA</td>
+     * <td>[keypad,]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_KEYPAD_MINUS</td>
+     * <td>[keypad-]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_FIELD_EXIT</td>
+     * <td>[fldext]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_FIELD_PLUS</td>
+     * <td>[field+]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_FIELD_MINUS</td>
+     * <td>[field-]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_BEGIN_OF_FIELD</td>
+     * <td>[bof]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PA1</td>
+     * <td>[pa1]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PA2</td>
+     * <td>[pa2]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_PA3</td>
+     * <td>[pa3]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_SYSREQ</td>
+     * <td>[sysreq]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_RESET</td>
+     * <td>[reset]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_ATTN</td>
+     * <td>[attn]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_MARK_LEFT</td>
+     * <td>[markleft]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_MARK_RIGHT</td>
+     * <td>[markright]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_MARK_UP</td>
+     * <td>[markup]</td>
+     * </tr>
+     * <tr>
+     * <td>MNEMONIC_MARK_DOWN</td>
+     * <td>[markdown]</td>
+     * </tr>
+     *
+     * </table>
+     *
+     * @param text
+     *            The string of characters to be sent
+     *
+     * @see #sendAid
+     *
+     */
+
+    public synchronized void sendKeys(String text) {
+        if (isStatusErrorCode() && !resetRequired) {
+            setCursorActive(false);
+            simulateMnemonic(getMnemonicValue("[reset]"));
+            setCursorActive(true);
+        }
+
+        if (oia.isKeyBoardLocked()) {
+            if (text.equals("[reset]") || text.equals("[sysreq]")
+                    || text.equals("[attn]")) {
+                setCursorActive(false);
+                simulateMnemonic(getMnemonicValue(text));
+                setCursorActive(true);
+            }
+            else {
+                if (isStatusErrorCode()) {
+                    sessionVT.signalBell();
+                    return;
+                }
+
+                oia.setKeysBuffered(true);
+
+                if (bufferedKeys == null) bufferedKeys = text;
+                else                      bufferedKeys += text;
+
+                return;
+            }
+        }
+        else {
+            if (oia.isKeysBuffered()) {
+                if (bufferedKeys != null) {
+                    text = bufferedKeys + text;
+                }
+
+                oia.setKeysBuffered(false);
+                bufferedKeys = null;
+            }
+
+            isInField();
+
+            if (text.length() == 1 && !text.equals("[") && !text.equals("]")) {
+                setCursorActive(false);
+                simulateKeyStroke(text.charAt(0));
+                setCursorActive(true);
+            }
+            else {
+                strokenizer.setKeyStrokes(text);
+                String s;
+                boolean done = false;
+                //            setCursorOff2();
+                setCursorActive(false);
+
+                while (!done) {
+                    if (strokenizer.hasMoreKeyStrokes()) {
+                        isInField();
+                        s = strokenizer.nextKeyStroke();
+
+                        if (s.length() == 1) {
+                            simulateKeyStroke(s.charAt(0));
+                        }
+                        else {
+                            simulateMnemonic(getMnemonicValue(s));
+                        }
+
+                        if (oia.isKeyBoardLocked()) {
+                            bufferedKeys = strokenizer
+                                           .getUnprocessedKeyStroked();
+
+                            if (bufferedKeys != null) {
+                                oia.setKeysBuffered(true);
+                            }
+
+                            done = true;
+                        }
+                    }
+                    else {
+                        done = true;
+                    }
+                }
+
+                setCursorActive(true);
+            }
+        }
+    }
+
+    /**
+     * The sendAid method sends an "aid" keystroke to the virtual screen. These
+     * aid keys can be thought of as special keystrokes, like the Enter key,
+     * PF1-24 keys or the Page Up key. All the valid special key values are
+     * contained in the AID_ enumeration:
+     *
+     * @param aidKey
+     *            The aid key to be sent to the host
+     *
+     * @see #sendKeys
+     * @see TN5250jConstants#AID_CLEAR
+     * @see #AID_ENTER
+     * @see #AID_HELP
+     * @see #AID_ROLL_UP
+     * @see #AID_ROLL_DOWN
+     * @see #AID_ROLL_LEFT
+     * @see #AID_ROLL_RIGHT
+     * @see #AID_PRINT
+     * @see #AID_PF1
+     * @see #AID_PF2
+     * @see #AID_PF3
+     * @see #AID_PF4
+     * @see #AID_PF5
+     * @see #AID_PF6
+     * @see #AID_PF7
+     * @see #AID_PF8
+     * @see #AID_PF9
+     * @see #AID_PF10
+     * @see #AID_PF11
+     * @see #AID_PF12
+     * @see #AID_PF13
+     * @see #AID_PF14
+     * @see #AID_PF15
+     * @see #AID_PF16
+     * @see #AID_PF17
+     * @see #AID_PF18
+     * @see #AID_PF19
+     * @see #AID_PF20
+     * @see #AID_PF21
+     * @see #AID_PF22
+     * @see #AID_PF23
+     * @see #AID_PF24
+     */
+    public void sendAid(int aidKey) {
+        sessionVT.sendAidKey(aidKey);
+    }
+
+    /**
+     * Restores the error line and sets the error mode off.
+     *
+     */
+    protected void resetError() {
+        restoreErrorLine();
+        setStatus(STATUS_ERROR_CODE, STATUS_VALUE_OFF, "");
+    }
+
+    protected boolean simulateMnemonic(int mnem) {
+        boolean simulated = false;
+
+        switch (mnem) {
+            case AID_CLEAR:
+            case AID_ENTER:
+            case AID_PF1:
+            case AID_PF2:
+            case AID_PF3:
+            case AID_PF4:
+            case AID_PF5:
+            case AID_PF6:
+            case AID_PF7:
+            case AID_PF8:
+            case AID_PF9:
+            case AID_PF10:
+            case AID_PF11:
+            case AID_PF12:
+            case AID_PF13:
+            case AID_PF14:
+            case AID_PF15:
+            case AID_PF16:
+            case AID_PF17:
+            case AID_PF18:
+            case AID_PF19:
+            case AID_PF20:
+            case AID_PF21:
+            case AID_PF22:
+            case AID_PF23:
+            case AID_PF24:
+            case AID_ROLL_DOWN:
+            case AID_ROLL_UP:
+            case AID_ROLL_LEFT:
+            case AID_ROLL_RIGHT:
+                if (!screenFields.isCanSendAid()) {
+                    displayError(ERR_ENTER_NO_ALLOWED);
+                }
+                else
+                    sendAid(mnem);
+
+                simulated = true;
+                break;
+
+            case AID_HELP:
+                sessionVT.sendHelpRequest();
+                simulated = true;
+                break;
+
+            case AID_PRINT:
+                sessionVT.hostPrint(1);
+                simulated = true;
+                break;
+
+            case BACK_SPACE:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    if (screenFields.getCurrentField().startPos() == lastPos) {
+                        if (backspaceError)
+                            displayError(ERR_CURSOR_PROTECTED);
+                        else {
+                            gotoFieldPrev();
+                            goto_XY(screenFields.getCurrentField().endPos());
+                            updateDirty();
+                        }
+                    }
+                    else {
+                        screenFields.getCurrentField().getKeyPos(lastPos);
+                        screenFields.getCurrentField().changePos(-1);
+                        resetDirty(screenFields.getCurrentField().getCurrentPos());
+                        shiftLeft(screenFields.getCurrentField().getCurrentPos());
+                        updateDirty();
+                        screenFields.setCurrentFieldMDT();
+                        simulated = true;
+                    }
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case BACK_TAB:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.isCurrentFieldHighlightedEntry()) {
+                    resetDirty(screenFields.getCurrentField().startPos);
+                    gotoFieldPrev();
+                    updateDirty();
+                }
+                else
+                    gotoFieldPrev();
+
+                if (screenFields.isCurrentFieldContinued()) {
+                    do {
+                        gotoFieldPrev();
+                    }
+                    while (screenFields.isCurrentFieldContinuedMiddle()
+                            || screenFields.isCurrentFieldContinuedLast());
+                }
+
+                isInField();
+                simulated = true;
+                break;
+
+            case UP:
+            case MARK_UP:
+                process_XY(lastPos - numCols);
+                simulated = true;
+                break;
+
+            case DOWN:
+            case MARK_DOWN:
+                process_XY(lastPos + numCols);
+                simulated = true;
+                break;
+
+            case LEFT:
+            case MARK_LEFT:
+                process_XY(lastPos - 1);
+                simulated = true;
+                break;
+
+            case RIGHT:
+            case MARK_RIGHT:
+                process_XY(lastPos + 1);
+                simulated = true;
+                break;
+
+            case NEXTWORD:
+                gotoNextWord();
+                simulated = true;
+                break;
+
+            case PREVWORD:
+                gotoPrevWord();
+                simulated = true;
+                break;
+
+            case DELETE:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    resetDirty(lastPos);
+                    screenFields.getCurrentField().getKeyPos(lastPos);
+                    shiftLeft(screenFields.getCurrentFieldPos());
+                    screenFields.setCurrentFieldMDT();
+                    updateDirty();
+                    simulated = true;
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case TAB:
+                if (screenFields.getCurrentField() != null
+                        && !screenFields.isCurrentFieldContinued()) {
+                    if (screenFields.isCurrentFieldHighlightedEntry()) {
+                        resetDirty(screenFields.getCurrentField().startPos);
+                        gotoFieldNext();
+                        updateDirty();
+                    }
+                    else
+                        gotoFieldNext();
+                }
+                else {
+                    do {
+                        gotoFieldNext();
+                    }
+                    while (screenFields.getCurrentField() != null
+                            && (screenFields.isCurrentFieldContinuedMiddle() || screenFields
+                                .isCurrentFieldContinuedLast()));
+                }
+
+                isInField();
+                simulated = true;
+                break;
+
+            case EOF:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    int where = endOfField(screenFields.getCurrentField()
+                                           .startPos(), true);
+
+                    if (where > 0) {
+                        setCursor((where / numCols) + 1, (where % numCols) + 1);
+                    }
+
+                    simulated = true;
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                resetDirty(lastPos);
+                break;
+
+            case ERASE_EOF:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    int where = lastPos;
+                    resetDirty(lastPos);
+
+                    if (fieldExit()) {
+                        screenFields.setCurrentFieldMDT();
+
+                        if (!screenFields.isCurrentFieldContinued()) {
+                            gotoFieldNext();
+                        }
+                        else {
+                            do {
+                                gotoFieldNext();
+
+                                if (screenFields.isCurrentFieldContinued())
+                                    fieldExit();
+                            }
+                            while (screenFields.isCurrentFieldContinuedMiddle()
+                                    || screenFields.isCurrentFieldContinuedLast());
+                        }
+                    }
+
+                    updateDirty();
+                    goto_XY(where);
+                    simulated = true;
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case ERASE_FIELD:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    int where = lastPos;
+                    lastPos = screenFields.getCurrentField().startPos();
+                    resetDirty(lastPos);
+
+                    if (fieldExit()) {
+                        screenFields.setCurrentFieldMDT();
+
+                        if (!screenFields.isCurrentFieldContinued()) {
+                            gotoFieldNext();
+                        }
+                        else {
+                            do {
+                                gotoFieldNext();
+
+                                if (screenFields.isCurrentFieldContinued())
+                                    fieldExit();
+                            }
+                            while (screenFields.isCurrentFieldContinuedMiddle()
+                                    || screenFields.isCurrentFieldContinuedLast());
+                        }
+                    }
+
+                    updateDirty();
+                    goto_XY(where);
+                    simulated = true;
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case INSERT:
+                // we toggle it
+                oia.setInsertMode(oia.isInsertMode() ? false : true);
+                break;
+
+            case HOME:
+
+                // position to the home position set
+                if (lastPos + numCols + 1 != homePos) {
+                    goto_XY(homePos - numCols - 1);
+                    isInField();
+                }
+                else
+                    gotoField(1);
+
+                break;
+
+            case KEYPAD_0:
+                simulated = simulateKeyStroke('0');
+                break;
+
+            case KEYPAD_1:
+                simulated = simulateKeyStroke('1');
+                break;
+
+            case KEYPAD_2:
+                simulated = simulateKeyStroke('2');
+                break;
+
+            case KEYPAD_3:
+                simulated = simulateKeyStroke('3');
+                break;
+
+            case KEYPAD_4:
+                simulated = simulateKeyStroke('4');
+                break;
+
+            case KEYPAD_5:
+                simulated = simulateKeyStroke('5');
+                break;
+
+            case KEYPAD_6:
+                simulated = simulateKeyStroke('6');
+                break;
+
+            case KEYPAD_7:
+                simulated = simulateKeyStroke('7');
+                break;
+
+            case KEYPAD_8:
+                simulated = simulateKeyStroke('8');
+                break;
+
+            case KEYPAD_9:
+                simulated = simulateKeyStroke('9');
+                break;
+
+            case KEYPAD_PERIOD:
+                simulated = simulateKeyStroke('.');
+                break;
+
+            case KEYPAD_COMMA:
+                simulated = simulateKeyStroke(',');
+                break;
+
+            case KEYPAD_MINUS:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    int s = screenFields.getCurrentField().getFieldShift();
+
+                    if (s == 3 || s == 5 || s == 7) {
+                        planes.setChar(lastPos, '-');
+                        resetDirty(lastPos);
+                        advancePos();
+
+                        if (fieldExit()) {
+                            screenFields.setCurrentFieldMDT();
+
+                            if (!screenFields.isCurrentFieldContinued()) {
+                                gotoFieldNext();
+                            }
+                            else {
+                                do {
+                                    gotoFieldNext();
+                                }
+                                while (screenFields
+                                        .isCurrentFieldContinuedMiddle()
+                                        || screenFields
+                                        .isCurrentFieldContinuedLast());
+                            }
+
+                            simulated = true;
+                            updateDirty();
+
+                            if (screenFields.isCurrentFieldAutoEnter())
+                                sendAid(AID_ENTER);
+                        }
+                    }
+                    else {
+                        displayError(ERR_FIELD_MINUS);
+                    }
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case FIELD_EXIT:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    resetDirty(lastPos);
+                    boolean autoFE = screenFields.isCurrentFieldAutoEnter();
+
+                    if (fieldExit()) {
+                        screenFields.setCurrentFieldMDT();
+
+                        if (!screenFields.isCurrentFieldContinued() &&
+                                !screenFields.isCurrentFieldAutoEnter()) {
+                            gotoFieldNext();
+                        }
+                        else {
+                            do {
+                                gotoFieldNext();
+
+                                if (screenFields.isCurrentFieldContinued())
+                                    fieldExit();
+                            }
+                            while (screenFields.isCurrentFieldContinuedMiddle()
+                                    || screenFields.isCurrentFieldContinuedLast());
+                        }
+                    }
+
+                    updateDirty();
+                    simulated = true;
+
+                    if (autoFE)
+                        sendAid(AID_ENTER);
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case FIELD_PLUS:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    resetDirty(lastPos);
+                    boolean autoFE = screenFields.isCurrentFieldAutoEnter();
+
+                    if (fieldExit()) {
+                        screenFields.setCurrentFieldMDT();
+
+                        if (!screenFields.isCurrentFieldContinued() &&
+                                !screenFields.isCurrentFieldAutoEnter()) {
+                            gotoFieldNext();
+                        }
+                        else {
+                            do {
+                                gotoFieldNext();
+                            }
+                            while (screenFields.isCurrentFieldContinuedMiddle()
+                                    || screenFields.isCurrentFieldContinuedLast());
+                        }
+                    }
+
+                    updateDirty();
+                    simulated = true;
+
+                    if (autoFE)
+                        sendAid(AID_ENTER);
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case FIELD_MINUS:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    int s = screenFields.getCurrentField().getFieldShift();
+
+                    if (s == 3 || s == 5 || s == 7) {
+                        planes.setChar(lastPos, '-');
+                        resetDirty(lastPos);
+                        advancePos();
+                        boolean autoFE = screenFields.isCurrentFieldAutoEnter();
+
+                        if (fieldExit()) {
+                            screenFields.setCurrentFieldMDT();
+
+                            if (!screenFields.isCurrentFieldContinued()
+                                    && !screenFields.isCurrentFieldAutoEnter()) {
+                                gotoFieldNext();
+                            }
+                            else {
+                                do {
+                                    gotoFieldNext();
+                                }
+                                while (screenFields.isCurrentFieldContinuedMiddle()
+                                        || screenFields.isCurrentFieldContinuedLast());
+                            }
+                        }
+
+                        updateDirty();
+                        simulated = true;
+
+                        if (autoFE)
+                            sendAid(AID_ENTER);
+                    }
+                    else {
+                        displayError(ERR_FIELD_MINUS);
+                    }
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case BOF:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    int where = screenFields.getCurrentField().startPos();
+
+                    if (where > 0) {
+                        goto_XY(where);
+                    }
+
+                    simulated = true;
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                resetDirty(lastPos);
+                break;
+
+            case SYSREQ:
+                sessionVT.systemRequest();
+                simulated = true;
+                break;
+
+            case RESET:
+                if (isStatusErrorCode()) {
+                    resetError();
+                    isInField();
+                    updateDirty();
+                }
+                else {
+                    setPrehelpState(false, oia.isKeyBoardLocked(), false);
+                }
+
+                simulated = true;
+                break;
+
+            case ATTN:
+                sessionVT.sendAttentionKey();
+                simulated = true;
+                break;
+
+            case DUP_FIELD:
+                if (screenFields.getCurrentField() != null
+                        && screenFields.withinCurrentField(lastPos)
+                        && !screenFields.isCurrentFieldBypassField()) {
+                    if (screenFields.isCurrentFieldDupEnabled()) {
+                        resetDirty(lastPos);
+                        screenFields.getCurrentField().setFieldChar(lastPos,
+                                (char) 0x1C);
+                        screenFields.setCurrentFieldMDT();
+                        gotoFieldNext();
+                        updateDirty();
+                        simulated = true;
+                    }
+                    else {
+                        displayError(ERR_DUP_KEY_NOT_ALLOWED);
+                    }
+                }
+                else {
+                    displayError(ERR_CURSOR_PROTECTED);
+                }
+
+                break;
+
+            case NEW_LINE:
+                if (screenFields.getSize() > 0) {
+                    int startRow = getRow(lastPos) + 1;
+                    int startPos = lastPos;
+
+                    if (startRow == getRows())
+                        startRow = 0;
+
+                    setCursor(++startRow, 1);
+
+                    if (!isInField() && screenFields.getCurrentField() != null
+                            && !screenFields.isCurrentFieldBypassField()) {
+                        while (!isInField()
+                                && screenFields.getCurrentField() != null
+                                && !screenFields.isCurrentFieldBypassField()) {
+                            // lets keep going
+                            advancePos();
+
+                            // Have we looped the screen?
+                            if (lastPos == startPos) {
+                                // if so then go back to starting point
+                                goto_XY(startPos);
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                simulated = true;
+                break;
+
+            case FAST_CURSOR_DOWN:
+                int rowNow = (getCurrentRow() - 1) + 3;
+
+                if (rowNow > getRows() - 1)
+                    rowNow = rowNow - getRows();
+
+                this.goto_XY(getPos(rowNow, getCurrentCol() - 1));
+                simulated = true;
+                break;
+
+            case FAST_CURSOR_UP:
+                rowNow = (getCurrentRow() - 1) - 3;
+
+                if (rowNow < 0)
+                    rowNow = (getRows()) + rowNow;
+
+                this.goto_XY(getPos(rowNow, getCurrentCol() - 1));
+                simulated = true;
+                break;
+
+            case FAST_CURSOR_LEFT:
+                int colNow = (getCurrentCol() - 1) - 3;
+                rowNow = getCurrentRow() - 1;
+
+                if (colNow <= 0) {
+                    colNow = getColumns() + colNow;
+                    rowNow--;
+                }
+
+                if (rowNow < 0)
+                    rowNow = getRows() - 1;
+
+                process_XY(getPos(rowNow, colNow));
+                simulated = true;
+                break;
+
+            case FAST_CURSOR_RIGHT:
+                colNow = (getCurrentCol() - 1) + 3;
+                rowNow = getCurrentRow() - 1;
+
+                if (colNow >= getColumns()) {
+                    colNow = colNow - getColumns();
+                    rowNow++;
+                }
+
+                if (rowNow > getRows() - 1)
+                    rowNow = getRows() - rowNow;
+
+                process_XY(getPos(rowNow, colNow));
+                simulated = true;
+                break;
+
+            default:
+                Log.i(TAG, " Mnemonic not supported " + mnem);
+                break;
+        }
+
+        return simulated;
+    }
+
+    protected boolean simulateKeyStroke(char c) {
+        if (isStatusErrorCode() && !Character.isISOControl(c) && !keyProcessed) {
+            if (resetRequired) return false;
+
+            resetError();
+        }
+
+        boolean updateField = false;
+        boolean numericError = false;
+        boolean updatePos = false;
+        boolean autoEnter = false;
+
+        if (!Character.isISOControl(c)) {
+            if (screenFields.getCurrentField() != null
+                    && screenFields.withinCurrentField(lastPos)
+                    && !screenFields.isCurrentFieldBypassField()) {
+                if (screenFields.isCurrentFieldFER()
+                        && !screenFields.withinCurrentField(screenFields
+                                .getCurrentFieldPos())
+                        && lastPos == screenFields.getCurrentField().endPos()
+                        && screenFields.getCurrentFieldPos() > screenFields
+                        .getCurrentField().endPos()) {
+                    displayError(ERR_FIELD_EXIT_INVALID);
+                    feError = true;
+                    return false;
+                }
+
+                switch (screenFields.getCurrentFieldShift()) {
+                    case 0: // Alpha shift
+                    case 2: // Numeric Shift
+                    case 4: // Kakana Shift
+                        updateField = true;
+                        break;
+
+                    case 1: // Alpha Only
+                        if (Character.isLetter(c) || c == ',' || c == '-'
+                                || c == '.' || c == ' ')
+                            updateField = true;
+
+                        break;
+
+                    case 3: // Numeric only
+                        if (Character.isDigit(c) || c == '+' || c == ','
+                                || c == '-' || c == '.' || c == ' ')
+                            updateField = true;
+                        else
+                            numericError = true;
+
+                        break;
+
+                    case 5: // Digits only
+                        if (Character.isDigit(c))
+                            updateField = true;
+                        else
+                            displayError(ERR_NUMERIC_09);
+
+                        break;
+
+                    case 7: // Signed numeric
+                        if (Character.isDigit(c) || c == '+' || c == '-')
+                            if (lastPos == screenFields.getCurrentField().endPos()
+                                    && (c != '+' && c != '-'))
+                                displayError(ERR_INVALID_SIGN);
+                            else
+                                updateField = true;
+                        else
+                            displayError(ERR_NUMERIC_09);
+
+                        break;
+                }
+
+                if (updateField) {
+                    if (screenFields.isCurrentFieldToUpper())
+                        c = Character.toUpperCase(c);
+
+                    updatePos = true;
+                    resetDirty(lastPos);
+
+                    if (oia.isInsertMode()) {
+                        if (endOfField(false) != screenFields.getCurrentField()
+                                .endPos())
+                            shiftRight(lastPos);
+                        else {
+                            displayError(ERR_NO_ROOM_INSERT);
+                            updatePos = false;
+                        }
+                    }
+
+                    if (updatePos) {
+                        screenFields.getCurrentField().getKeyPos(
+                            getRow(lastPos), getCol(lastPos));
+                        screenFields.getCurrentField().changePos(1);
+                        planes.setChar(lastPos, c);
+                        screenFields.setCurrentFieldMDT();
+
+                        // if we have gone passed the end of the field then goto
+                        // the next field
+                        if (!screenFields.withinCurrentField(screenFields
+                                                             .getCurrentFieldPos())) {
+                            if (screenFields.isCurrentFieldAutoEnter()) {
+                                autoEnter = true;
+                            }
+                            else if (!screenFields.isCurrentFieldFER())
+                                gotoFieldNext();
+                            else {
+                                //                        screenFields.getCurrentField().changePos(1);
+                                //
+                                //                        if (screenFields.
+                                //                        cursorPos == endPos)
+                                //                           System.out.println("end of field");
+                                //
+                                //                        feError != feError;
+                                //                        if (feError)
+                                //                           displayError(ERR_FIELD_EXIT_INVALID);
+                            }
+                        }
+                        else
+                            setCursor(screenFields.getCurrentField()
+                                      .getCursorRow() + 1, screenFields
+                                      .getCurrentField().getCursorCol() + 1);
+                    }
+
+                    fireScreenChanged();
+
+                    if (autoEnter)
+                        sendAid(AID_ENTER);
+                }
+                else {
+                    if (numericError) {
+                        displayError(ERR_NUMERIC_ONLY);
+                    }
+                }
+            }
+            else {
+                displayError(ERR_CURSOR_PROTECTED);
+            }
+        }
+
+        return updatePos;
+    }
+
+    /**
+     * Method: endOfField
+     * <p>
+     *
+     * convenience method that call endOfField with lastRow lastCol and passes
+     * the posSpace to that method
+     *
+     * @param posSpace
+     *            value of type boolean - specifying to return the position of
+     *            the the last space or not
+     * @return a value of type int - the screen postion (row * columns) + col
+     *
+     */
+    private int endOfField(boolean posSpace) {
+        return endOfField(lastPos, posSpace);
+    }
+
+    /**
+     * Method: endOfField
+     * <p>
+     *
+     * gets the position of the last character of the current field posSpace
+     * parameter tells the routine whether to return the position of the last
+     * space ( <= ' ') or the last non space posSpace == true last occurrence of
+     * char <= ' ' posSpace == false last occurrence of char > ' '
+     *
+     * @param pos
+     *            value of type int - position to start from
+     * @param posSpace
+     *            value of type boolean - specifying to return the position of
+     *            the the last space or not
+     * @return a value of type int - the screen postion (row * columns) + col
+     *
+     */
+    private int endOfField(int pos, boolean posSpace) {
+        int endPos = screenFields.getCurrentField().endPos();
+        int fePos = endPos;
+        // get the number of characters to the right
+        int count = endPos - pos;
+
+        // first lets get the real ending point without spaces and the such
+        while (planes.getChar(endPos) <= ' ' && count-- > 0) {
+            endPos--;
+        }
+
+        if (endPos == fePos) {
+            return endPos;
+        }
+
+        screenFields.getCurrentField().getKeyPos(endPos);
+
+        if (posSpace) screenFields.getCurrentField().changePos(+1);
+
+        return screenFields.getCurrentFieldPos();
+    }
+
+    private boolean fieldExit() {
+        int pos = lastPos;
+        boolean mdt = false;
+        int end = endOfField(false); // get the ending position of the first
+        // non blank character in field
+        ScreenField sf = screenFields.getCurrentField();
+
+        if (sf.isMandatoryEnter() && end == sf.startPos()) {
+            displayError(ERR_MANDATORY_ENTER);
+            return false;
+        }
+
+        // save off the current pos of the field for checking field exit required
+        //   positioning.  the getKeyPos resets this information so it is useless
+        //   for comparing if we are positioned passed the end of field.
+        //   Maybe this should be changed to not update the current cursor position
+        //   of the field.
+        int currentPos = sf.getCurrentPos();
+        // get the number of characters to the right
+        int count = (end - sf.startPos()) - sf.getKeyPos(pos);
+
+        if (count == 0 && sf.isFER()) {
+            if (currentPos > sf.endPos()) {
+                mdt = true;
+                return mdt;
+            }
+        }
+
+        for (; count >= 0; count--) {
+            planes.setChar(pos, initChar);
+            setDirty(pos);
+            pos++;
+            mdt = true;
+        }
+
+        // This checks for a field minus because a field minus places
+        // a negative sign and then advances a position. If it is the
+        // end of the field where the minus is placed then this offset will
+        //  place the count as -1.
+        if (count == -1) {
+            int s = sf.getFieldShift();
+
+            if (s == 3 || s == 5 || s == 7) {
+                mdt = true;
+            }
+        }
+
+        int adj = sf.getAdjustment();
+
+        if (adj != 0) {
+            switch (adj) {
+                case 5:
+                    rightAdjustField('0');
+                    sf.setRightAdjusted();
+                    break;
+
+                case 6:
+                    rightAdjustField(' ');
+                    sf.setRightAdjusted();
+                    break;
+
+                case 7:
+                    sf.setMandatoryEntered();
+                    break;
+            }
+        }
+        else {
+            // we need to right adjust signed numeric fields as well.
+            if (sf.isSignedNumeric()) {
+                rightAdjustField(' ');
+            }
+        }
+
+        return mdt;
+    }
+
+    private void rightAdjustField(char fill) {
+        int end = endOfField(false); // get the ending position of the first
+        // non blank character in field
+        // get the number of characters to the right
+        int count = screenFields.getCurrentField().endPos() - end;
+
+        // subtract 1 from count for signed numeric - note for later
+        if (screenFields.getCurrentField().isSignedNumeric()) {
+            if (planes.getChar(end - 1) != '-')
+                count--;
+        }
+
+        int pos = screenFields.getCurrentField().startPos();
+
+        while (count-- >= 0) {
+            shiftRight(pos);
+            planes.setChar(pos, fill);
+            setDirty(pos);
+        }
+    }
+
+    private void shiftLeft(int sPos) {
+        int endPos = 0;
+        int pos = sPos;
+        int pPos = sPos;
+        ScreenField sf = screenFields.getCurrentField();
+        int end;
+        int count;
+
+        do {
+            end = endOfField(pPos, false); // get the ending position of the
+            // first
+            // non blank character in field
+            count = (end - screenFields.getCurrentField().startPos())
+                    - screenFields.getCurrentField().getKeyPos(pPos);
+
+            // now we loop through and shift the remaining characters to the
+            // left
+            while (count-- > 0) {
+                pos++;
+                planes.setChar(pPos, planes.getChar(pos));
+                setDirty(pPos);
+                pPos = pos;
+            }
+
+            if (screenFields.isCurrentFieldContinued()) {
+                gotoFieldNext();
+
+                if (screenFields.getCurrentField().isContinuedFirst())
+                    break;
+
+                pos = screenFields.getCurrentField().startPos();
+                planes.setChar(pPos, planes.getChar(pos));
+                setDirty(pPos);
+                pPos = pos;
+            }
+        }
+        while (screenFields.isCurrentFieldContinued()
+                && !screenFields.getCurrentField().isContinuedFirst());
+
+        if (end >= 0 && count >= -1) {
+            endPos = end;
+        }
+        else {
+            endPos = sPos;
+        }
+
+        screenFields.setCurrentField(sf);
+        planes.setChar(endPos, initChar);
+        setDirty(endPos);
+        goto_XY(screenFields.getCurrentFieldPos());
+        sf = null;
+    }
+
+    private void shiftRight(int sPos) {
+        int end = endOfField(true); // get the ending position of the first
+        // non blank character in field
+        int pos = end;
+        int pPos = end;
+        int count = end - sPos;
+
+        // now we loop through and shift the remaining characters to the right
+        while (count-- > 0) {
+            pos--;
+            planes.setChar(pPos, planes.getChar(pos));
+            setDirty(pPos);
+            pPos = pos;
+        }
+    }
+
+    public int getRow(int pos) {
+        //      if (pos == 0)
+        //         return 1;
+        int row = pos / numCols;
+
+        if (row < 0) {
+            row = lastPos / numCols;
+        }
+
+        if (row > (lenScreen / numCols) - 1)
+            row = (lenScreen / numCols) - 1;
+
+        return row;
+    }
+
+    public int getCol(int pos) {
+        int col = pos % (getColumns());
+
+        if (col > 0) return col;
+
+        return 0;
+    }
+
+    /**
+     * This routine is 0 based offset. So to get row 20,1 then pass row 19,0
+     *
+     * @param row
+     * @param col
+     * @return
+     */
+    public int getPos(int row, int col) {
+        return (row * numCols) + col;
+    }
+
+    /**
+     * Current position is based on offsets of 1,1 not 0,0 of the current
+     * position of the screen
+     *
+     * @return int
+     */
+    public int getCurrentPos() {
+        //      return lastPos + numCols + 1;
+        return lastPos + 1;
+    }
+
+    /**
+     * I got this information from a tcp trace of each error. I could not find
+     * any documenation for this. Maybe there is but I could not find it. If
+     * anybody finds this documention could you please send me a copy. Please
+     * note that I did not look that hard either.
+     * <p>
+     * 0000: 00 50 73 1D 89 81 00 50 DA 44 C8 45 08 00 45 00 .Ps....P.D.E..E.
+     * </p>
+     * <p>
+     * 0010: 00 36 E9 1C 40 00 80 06 9B F9 C1 A8 33 58 C0 A8 .6..@...k....3X..
+     * </p>
+     * <p>
+     * 0020: C0 02 06 0E 00 17 00 52 6E 88 73 40 DE CB 50 18 .......Rn.s@..P.
+     * </p>
+     * <p>
+     * 0030: 20 12 3C 53 00 00 00 0C 12 A0 00 00 04 01 00 00 . <S............
+     * </p>
+     * <p>
+     * 0040: 00 05 FF EF .... ----------|| The 00 XX is the code to be sent. I
+     * found the following <table BORDER COLS=2 WIDTH="50%" >
+     * <tr>
+     * <td>ERR_CURSOR_PROTECTED</td>
+     * <td>0x05</td>
+     * </tr>
+     * <tr>
+     * <td>ERR_INVALID_SIGN</td>
+     * <td>0x11</td>
+     * </tr>
+     * <tr>
+     * <td>ERR_NO_ROOM_INSERT</td>
+     * <td>0x12</td>
+     * </tr>
+     * <tr>
+     * <td>ERR_NUMERIC_ONLY</td>
+     * <td>0x09</td>
+     * </tr>
+     * <tr>
+     * <td>ERR_NUMERIC_09</td>
+     * <td>0x10</td>
+     * </tr>
+     * <tr>
+     * <td>ERR_FIELD_MINUS</td>
+     * <td>0x16</td>
+     * </tr>
+     * <tr>
+     * <td>ERR_ENTER_NOT_ALLOWED</td>
+     * <td>0x20</td>
+     * </tr>
+     * <tr>
+     * <td>ERR_MANDATORY_ENTER</td>
+     * <td>0x21</td>
+     * </tr>
+     * <tr>
+     * <td>ERR_ENTER_NOT_ALLOWED</td>
+     * <td>0x20</td>
+     * </tr>
+     * </table> I am tired of typing and they should be self explanitory. Finding
+     * them in the first place was the pain.
+     * </p>
+     *
+     * @param ec error code
+     */
+    private void displayError(int ec) {
+        saveHomePos = homePos;
+        homePos = lastPos + numCols + 1;
+        pendingInsert = true;
+        sessionVT.sendNegResponse2(ec);
+    }
+
+    private void process_XY(int pos) {
+        if (pos < 0)
+            pos = lenScreen + pos;
+
+        if (pos > lenScreen - 1)
+            pos = pos - lenScreen;
+
+        // if there was a field exit error then we need to treat the movement
+        //  of the cursor in a special way that equals that of Client Access.
+        //    If the cursor is moved from the field then we need to reset the
+        //       position within the field so that the last character can be typed
+        //       over again instead of sending the field exit error again.
+        //       We also need to reset the field exit error flag.
+        //
+        //    How we know we have a field exit error is when the field position is
+        //    set beyond the end of the field and a character is then typed we can
+        //    not position that character. To reset this we need to set the next
+        //    position of the field to not be beyond the end of field but to the
+        //    last character.
+        //
+        //    Now to make it work like Client Access if the cursor is a back space
+        //    then do not move the cursor but place it on the last field. All
+        //    other keys will reset the field position so that entering over the
+        //    last character will not cause an error but replace that character or
+        //    just plain move the cursor if the key was to do that.
+        ScreenField sf = screenFields.getCurrentField();
+
+        if (feError) {
+            feError = false;
+            sf.changePos(-1);
+        }
+        else {
+            if (sf != null && sf.isFER()) {
+                if ((sf.getCurrentPos()
+                        > sf.endPos())) {
+                    if (sf.withinField(pos)) {
+                        sf.getKeyPos(pos);
+                        return;
+                    }
+
+                    sf.getKeyPos(sf.endPos());
+                }
+            }
+
+            goto_XY(pos);
+        }
+    }
+
+    public boolean isUsingGuiInterface() {
+        return guiInterface;
+    }
+
+    /**
+     * Convinience class to return if the cursor is in a field or not.
+     *
+     * @return true or false
+     */
+
+    protected boolean isInField() {
+        return isInField(lastPos, true);
+    }
+
+    /**
+     *
+     * Convinience class to return if the position that is passed is in a field
+     * or not. If it is then the chgToField parameter will change the current
+     * field to this field where the position indicates
+     *
+     * @param pos
+     * @param chgToField
+     * @return true or false
+     */
+    public boolean isInField(int pos, boolean chgToField) {
+        return screenFields.isInField(pos, chgToField);
+    }
+
+    /**
+     *
+     * Convinience class to return if the position that is passed is in a field
+     * or not. If it is then the field at this position becomes the current
+     * working field
+     *
+     * @param pos
+     * @return true or false
+     */
+    public boolean isInField(int pos) {
+        return screenFields.isInField(pos, true);
+    }
+
+    /**
+     * Convinience class to return if the position at row and column that is
+     * passed is in a field or not. If it is then the field at this position
+     * becomes the current working field.
+     *
+     * @param row
+     * @param col
+     * @return true or false
+     */
+    public boolean isInField(int row, int col) {
+        return isInField(row, col, true);
+    }
+
+    /**
+     *
+     * Convinience class to return if the position at row and column that is
+     * passed is in a field or not. If it is then the chgToField parameter will
+     * change the current field to this field where the row and column
+     * indicates.
+     *
+     * @param row
+     * @param col
+     * @param chgToField
+     * @return true or false
+     */
+    public boolean isInField(int row, int col, boolean chgToField) {
+        return screenFields.isInField((row * numCols) + col, chgToField);
+    }
+
+    /**
+     * Gets the length of the screen - number of rows times number of columns
+     *
+     * @return int value of screen length
+     */
+    public int getScreenLength() {
+        return lenScreen;
+    }
+
+    /**
+     * Get the number or rows available.
+     *
+     * @return number of rows
+     */
+    public int getRows() {
+        return numRows;
+    }
+
+    /**
+     * Get the number of columns available.
+     *
+     * @return number of columns
+     */
+    public int getColumns() {
+        return numCols;
+    }
+
+    /**
+     * Get the current row where the cursor is
+     *
+     * @return the cursor current row position 1,1 based
+     */
+    public int getCurrentRow() {
+        return (lastPos / numCols) + 1;
+    }
+
+    /**
+     * Get the current column where the cursor is
+     *
+     * @return the cursor current column position 1,1 based
+     */
+    public int getCurrentCol() {
+        return (lastPos % numCols) + 1;
+    }
+
+    /**
+     * The last position of the cursor on the screen - Note - position is based
+     * 0,0
+     *
+     * @return last position
+     */
+    protected int getLastPos() {
+        return lastPos;
+    }
+
+    /**
+     * Hotspot More... string
+     *
+     * @return string literal of More...
+     */
+    public StringBuffer getHSMore() {
+        return hsMore;
+    }
+
+    /**
+     * Hotspot Bottom string
+     *
+     * @return string literal of Bottom
+     */
+    public StringBuffer getHSBottom() {
+        return hsBottom;
+    }
+
+    /**
+     *
+     * Return the screen represented as a character array
+     *
+     * @return character array containing the text
+     */
+    public char[] getScreenAsChars() {
+        char[] sac = new char[lenScreen];
+        char c;
+
+        for (int x = 0; x < lenScreen; x++) {
+            c = planes.getChar(x);
+
+            // only draw printable characters (in this case >= ' ')
+            if ((c >= ' ') && (!planes.isAttributePlace(x))) {
+                sac[x] = c;
+                // TODO: implement the underline check here
+                //              if (screen[x].underLine && c <= ' ')
+                //                  sac[x] = '_';
+            }
+            else
+                sac[x] = ' ';
+        }
+
+        return sac;
+    }
+
+    public char[] getData(int startRow, int startCol, int endRow, int endCol, int plane) {
+        try {
+            int from = getPos(startRow, startCol);
+            int to = getPos(endRow, endCol);
+
+            if (from > to) {
+                int f = from;
+                to = f;
+                from = f;
+            }
+
+            return planes.getPlaneData(from, to, plane);
+        }
+        catch (Exception oe) {
+            return null;
+        }
+    }
+
+    /**
+     * <p>
+     *  GetScreen retrieves the various planes associated with the presentation
+     *  space. The data is returned as a linear array of character values in the
+     *  array provided. The array is not terminated by a null character except
+     *  when data is retrieved from the text plane, in which case a single null
+     *  character is appended.
+     *  </p>
+     *  <p>
+     *  The application must supply a buffer for the returned data and the length
+     *  of the buffer. Data is returned starting from the beginning of the
+     *  presentation space and continuing until the buffer is full or the entire
+     *  plane has been copied. For text plane data, the buffer must include one
+     *  extra position for the terminating null character.
+     *  <p>
+     *
+     * @param buffer
+     * @param bufferLength
+     * @param plane
+     * @return The number of characters copied to the buffer
+     * @throws OhioException
+     */
+
+    public synchronized int GetScreen(char buffer[], int bufferLength, int plane)
+    //                                       throws OhioException {
+    {
+        return GetScreen(buffer, bufferLength, 0, lenScreen, plane);
+    }
+
+    /**
+     * <p>
+     *  GetScreen retrieves the various planes associated with the presentation
+     *  space. The data is returned as a linear array of character values in the
+     *  array provided. The array is not terminated by a null character except
+     *  when data is retrieved from the text plane, in which case a single null
+     *  character is appended.
+     * </p>
+     * <p>
+     * The application must supply a buffer for the returned data and the length
+     * of the buffer. Data is returned starting from the given position and
+     * continuing until the specified number of characters have been copied, the
+     * buffer is full or the entire plane has been copied. For text plane data,
+     * the buffer must include one extra position for the terminating null character.
+     * </p>
+     *
+     * @param buffer
+     * @param bufferLength
+     * @param from
+     * @param length
+     * @param plane
+     * @return The number of characters copied to the buffer
+     * @throws OhioException
+     */
+
+    public synchronized int GetScreen(char buffer[], int bufferLength, int from,
+                                      int length, int plane)
+    //                                    throws OhioException {
+    {
+        return planes.GetScreen(buffer, bufferLength, from, length, plane);
+    }
+
+    /**
+     * <p>
+     *  GetScreen retrieves the various planes associated with the presentation
+     *  space. The data is returned as a linear array of character values in the
+     *  array provided. The array is not terminated by a null character except
+     *  when data is retrieved from the text plane, in which case a single null
+     *  character is appended.
+     *  </p>
+     *  <p>
+     *  The application must supply a buffer for the returned data and the length
+     *  of the buffer. Data is returned starting from the given coordinates and
+     *  continuing until the specified number of characters have been copied,
+     *  the buffer is full, or the entire plane has been copied. For text plane
+     *  data, the buffer must include one extra position for the terminating null
+     *  character.
+     *  </p>
+     *
+     * @param buffer
+     * @param bufferLength
+     * @param row
+     * @param col
+     * @param length
+     * @param plane
+     * @return The number of characters copied to the buffer.
+     * @throws OhioException
+     */
+
+    public synchronized int GetScreen(char buffer[], int bufferLength, int row,
+                                      int col, int length, int plane)
+    //                                       throws OhioException {
+    {
+        // Call GetScreen function after converting row and column to
+        // a position.
+        return planes.GetScreen(buffer, bufferLength, row, col, length, plane);
+    }
+
+    /**
+     * <p>
+     *  GetScreenRect retrieves data from the various planes associated with the
+     *  presentation space. The data is returned as a linear array of character
+     *  values in the buffer provided.
+     *  </p>
+     *
+     * <p>
+     * The application supplies two positions that represent opposing corners of
+     * a rectangle within the presentation space. The starting and ending
+     * positions can have any spatial relationship to each other. The data
+     * returned starts from the row containing the upper-most point to the row
+     * containing the lower-most point, and from the left-most column to the
+     * right-most column.
+     * </p>
+     * <p>
+     * The specified buffer must be at least large enough to contain the number
+     * of characters in the rectangle. If the buffer is too small, no data is
+     * copied and zero is returned by the method. Otherwise, the method returns
+     * the number of characters copied.
+     * </p>
+     *
+     * @param buffer
+     * @param bufferLength
+     * @param startPos
+     * @param endPos
+     * @param plane
+     * @return The number of characters copied to the buffer
+     * @throws OhioException
+     */
+
+    public synchronized int GetScreenRect(char buffer[], int bufferLength,
+                                          int startPos, int endPos, int plane)
+    //                                             throws OhioException {
+    {
+        return planes.GetScreenRect(buffer, bufferLength, startPos, endPos, plane);
+    }
+
+    /**
+     * <p>
+     *  GetScreenRect retrieves data from the various planes associated with the
+     *  presentation space. The data is returned as a linear array of character
+     *  values in the buffer provided. The buffer is not terminated by a null
+     *  character.
+     * </p>
+     * <p>
+     * The application supplies two coordinates that represent opposing corners
+     * of a rectangle within the presentation space. The starting and ending
+     * coordinates can have any spatial relationship to each other. The data
+     * returned starts from the row containing the upper-most point to the row
+     * containing the lower-most point, and from the left-most column to the
+     * right-most column.
+     * </p>
+     * <p>
+     * The specified buffer must be at least large enough to contain the number
+     * of characters in the rectangle. If the buffer is too small, no data is
+     * copied and zero is returned by the method. Otherwise, the method returns
+     * the number of characters copied.
+     * </p>
+     *
+     * @param buffer
+     * @param bufferLength
+     * @param startRow
+     * @param startCol
+     * @param endRow
+     * @param endCol
+     * @param plane
+     * @return The number characters copied to the buffer
+     * @throws OhioException
+     */
+
+    public synchronized int GetScreenRect(char buffer[], int bufferLength,
+                                          int startRow, int startCol,
+                                          int endRow, int endCol, int plane)
+    //                                             throws OhioException {
+    {
+        return planes.GetScreenRect(buffer, bufferLength, startRow, startCol, endRow,
+                                    endCol, plane);
+    }
+
+    public synchronized boolean[] getActiveAidKeys() {
+        return sessionVT.getActiveAidKeys();
+    }
+
+    protected synchronized void setScreenData(String text, int location) {
+        //                                             throws OhioException {
+        if (location < 0 || location > lenScreen) {
+            return;
+            //         throw new OhioException(sessionVT.getSessionConfiguration(),
+            //                      OhioScreen5250.class.getName(), "osohio.screen.ohio00300", 1);
+        }
+
+        int pos = location;
+        int l = text.length();
+        boolean updated = false;
+        boolean flag = false;
+        int x = 0;
+
+        for (; x < l; x++) {
+            if (isInField(pos + x, true)) {
+                if (!screenFields.getCurrentField().isBypassField()) {
+                    if (!flag) {
+                        screenFields.getCurrentField().setMDT();
+                        updated = true;
+                        resetDirty(pos + x);
+                        screenFields.setMasterMDT();
+                        flag = true;
+                    }
+
+                    planes.screen[pos + x] = text.charAt(x);
+                    setDirty(pos + x);
+                }
+            }
+        }
+
+        lastPos = pos + x;
+
+        if (updated) {
+            fireScreenChanged();
+        }
+    }
+
+    /**
+     * This routine is based on offset 1,1 not 0,0 it will translate to offset
+     * 0,0 and call the goto_XY(int pos) it is mostly used from external classes
+     * that use the 1,1 offset
+     *
+     * @param row
+     * @param col
+     */
+    public void setCursor(int row, int col) {
+        goto_XY(((row - 1) * numCols) + (col - 1));
+    }
+
+    // this routine is based on offset 0,0 not 1,1
+    protected void goto_XY(int pos) {
+        lastPos = pos;
+        updateCursorLoc();
+    }
+
+    /*
+     * set the content of the field at (l,c) to data
+     * if l == -1, set the current field contents to data
+     */
+    public void setField(int l, int c, char [] data) {
+        ScreenField cf;
+
+        if (l >= 0) {
+            lastPos = l * numCols + c;
+
+            while (!isInField()) advancePos();
+
+            setDirty(lastPos);
+            fireCursorChanged();
+        }
+
+        if ((data != null) && (data.length > 0)) {
+            cf = screenFields.getCurrentField();
+            cf.setString(new String(data));
+            lastPos = cf.getStartPos();
+            setDirty(lastPos);
+            setDirty(lastPos + cf.getLength());
+            lastPos += data.length;
+
+            if (!isInField()) {
+                gotoFieldNext();
+                isInField();
+                cf = screenFields.getCurrentField();
+                lastPos = cf.getStartPos();
+            }
+
+            setDirty(lastPos);
+            fireCursorChanged();
+        }
+
+        updateDirty();
+    }
+
+    /**
+     * Set the current working field to the field number specified.
+     *
+     * @param f -
+     *            numeric field number on the screen
+     * @return true or false whether it was sucessful
+     */
+    public boolean gotoField(int f) {
+        int sizeFields = screenFields.getSize();
+
+        if (f > sizeFields || f <= 0)
+            return false;
+
+        screenFields.setCurrentField(screenFields.getField(f - 1));
+
+        while (screenFields.isCurrentFieldBypassField() && f < sizeFields) {
+            screenFields.setCurrentField(screenFields.getField(f++));
+        }
+
+        return gotoField(screenFields.getCurrentField());
+    }
+
+    /**
+     * Convenience method to set the field object passed as the currect working
+     * screen field
+     *
+     * @param f
+     * @return true or false whether it was sucessful
+     * @see org.tn5250j.ScreenField
+     */
+    protected boolean gotoField(ScreenField f) {
+        if (f != null) {
+            goto_XY(f.startPos());
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Convenience class to position the cursor to the next word on the screen
+     *
+     */
+    private void gotoNextWord() {
+        int pos = lastPos;
+
+        if (planes.getChar(lastPos) > ' ') {
+            advancePos();
+
+            // get the next space character
+            while (planes.getChar(lastPos) > ' ' && pos != lastPos) {
+                advancePos();
+            }
+        }
+        else
+            advancePos();
+
+        // now that we are positioned on the next space character get the
+        // next none space character
+        while (planes.getChar(lastPos) <= ' ' && pos != lastPos) {
+            advancePos();
+        }
+    }
+
+    /**
+     * Convenience class to position the cursor to the previous word on the
+     * screen
+     *
+     */
+    private void gotoPrevWord() {
+        int pos = lastPos;
+        changePos(-1);
+
+        // position previous white space character
+        while (planes.getChar(lastPos) <= ' ') {
+            changePos(-1);
+
+            if (pos == lastPos)
+                break;
+        }
+
+        changePos(-1);
+
+        // get the previous space character
+        while (planes.getChar(lastPos) > ' ' && pos != lastPos) {
+            changePos(-1);
+        }
+
+        // and position one position more should give us the beginning of word
+        advancePos();
+    }
+
+    /**
+     * Convinience class to position to the next field on the screen.
+     *
+     * @see org.tn5250j.ScreenFields
+     */
+    private void gotoFieldNext() {
+        if (screenFields.isCurrentFieldHighlightedEntry())
+            unsetFieldHighlighted(screenFields.getCurrentField());
+
+        screenFields.gotoFieldNext();
+
+        if (screenFields.isCurrentFieldHighlightedEntry())
+            setFieldHighlighted(screenFields.getCurrentField());
+    }
+
+    /**
+     * Convinience class to position to the previous field on the screen.
+     *
+     * @see org.tn5250j.ScreenFields
+     */
+    private void gotoFieldPrev() {
+        if (screenFields.isCurrentFieldHighlightedEntry())
+            unsetFieldHighlighted(screenFields.getCurrentField());
+
+        screenFields.gotoFieldPrev();
+
+        if (screenFields.isCurrentFieldHighlightedEntry())
+            setFieldHighlighted(screenFields.getCurrentField());
+    }
+
+    /* *** NEVER USED LOCALLY ************************************************** */
+    //  /**
+    //   * Used to restrict the cursor to a particular position on the screen. Used
+    //   * in combination with windows to restrict the cursor to the active window
+    //   * show on the screen.
+    //   *
+    //   * Not supported yet. Please implement me :-(
+    //   *
+    //   * @param depth
+    //   * @param width
+    //   */
+    //  protected void setRestrictCursor(int depth, int width) {
+    //
+    //      restrictCursor = true;
+    //      //      restriction
+    //
+    //  }
+
+    /**
+     * Creates a window on the screen
+     *
+     * @param depth
+     * @param width
+     * @param type
+     * @param gui
+     * @param monoAttr
+     * @param colorAttr
+     * @param ul
+     * @param upper
+     * @param ur
+     * @param left
+     * @param right
+     * @param ll
+     * @param bottom
+     * @param lr
+     */
+    protected void createWindow(int depth, int width, int type, boolean gui,
+                                int monoAttr, int colorAttr, int ul, int upper, int ur, int left,
+                                int right, int ll, int bottom, int lr) {
+        int c = getCol(lastPos);
+        int w = 0;
+        width++;
+        w = width;
+        // set leading attribute byte
+        //      screen[lastPos].setCharAndAttr(initChar, initAttr, true);
+        planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true);
+        setDirty(lastPos);
+        advancePos();
+        // set upper left
+        //      screen[lastPos].setCharAndAttr((char) ul, colorAttr, false);
+        planes.setScreenCharAndAttr(lastPos, (char) ul, colorAttr, false);
+
+        if (gui) {
+            //          screen[lastPos].setUseGUI(UPPER_LEFT);
+            planes.setUseGUI(lastPos, UPPER_LEFT);
+        }
+
+        setDirty(lastPos);
+        advancePos();
+
+        // draw top row
+
+        while (w-- >= 0) {
+            //          screen[lastPos].setCharAndAttr((char) upper, colorAttr, false);
+            planes.setScreenCharAndAttr(lastPos, (char) upper, colorAttr, false);
+
+            if (gui) {
+                //              screen[lastPos].setUseGUI(UPPER);
+                planes.setUseGUI(lastPos, UPPER);
+            }
+
+            setDirty(lastPos);
+            advancePos();
+        }
+
+        // set upper right
+        //      screen[lastPos].setCharAndAttr((char) ur, colorAttr, false);
+        planes.setScreenCharAndAttr(lastPos, (char) ur, colorAttr, false);
+
+        if (gui) {
+            //          screen[lastPos].setUseGUI(UPPER_RIGHT);
+            planes.setUseGUI(lastPos, UPPER_RIGHT);
+        }
+
+        setDirty(lastPos);
+        advancePos();
+        // set ending attribute byte
+        planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true);
+        setDirty(lastPos);
+        lastPos = ((getRow(lastPos) + 1) * numCols) + c;
+
+        // now handle body of window
+        while (depth-- > 0) {
+            // set leading attribute byte
+            planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true);
+            setDirty(lastPos);
+            advancePos();
+            // set left
+            planes.setScreenCharAndAttr(lastPos, (char) left, colorAttr, false);
+
+            if (gui) {
+                planes.setUseGUI(lastPos, GUI_LEFT);
+            }
+
+            setDirty(lastPos);
+            advancePos();
+            w = width;
+
+            // fill it in
+            while (w-- >= 0) {
+                //              screen[lastPos].setCharAndAttr(initChar, initAttr, true);
+                planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true);
+                //              screen[lastPos].setUseGUI(NO_GUI);
+                planes.setUseGUI(lastPos, NO_GUI);
+                setDirty(lastPos);
+                advancePos();
+            }
+
+            // set right
+            //          screen[lastPos].setCharAndAttr((char) right, colorAttr, false);
+            planes.setScreenCharAndAttr(lastPos, (char) right, colorAttr, false);
+
+            if (gui) {
+                //              screen[lastPos].setUseGUI(RIGHT);
+                planes.setUseGUI(lastPos, GUI_RIGHT);
+            }
+
+            setDirty(lastPos);
+            advancePos();
+            // set ending attribute byte
+            //          screen[lastPos].setCharAndAttr(initChar, initAttr, true);
+            planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true);
+            setDirty(lastPos);
+            lastPos = ((getRow(lastPos) + 1) * numCols) + c;
+        }
+
+        // set leading attribute byte
+        //      screen[lastPos].setCharAndAttr(initChar, initAttr, true);
+        planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true);
+        setDirty(lastPos);
+        advancePos();
+        // set lower left
+        //      screen[lastPos].setCharAndAttr((char) ll, colorAttr, false);
+        planes.setScreenCharAndAttr(lastPos, (char) ll, colorAttr, false);
+
+        if (gui) {
+            //          screen[lastPos].setUseGUI(LOWER_LEFT);
+            planes.setUseGUI(lastPos, LOWER_LEFT);
+        }
+
+        setDirty(lastPos);
+        advancePos();
+        w = width;
+
+        // draw bottom row
+        while (w-- >= 0) {
+            planes.setScreenCharAndAttr(lastPos, (char) bottom, colorAttr, false);
+
+            if (gui) {
+                planes.setUseGUI(lastPos, BOTTOM);
+            }
+
+            setDirty(lastPos);
+            advancePos();
+        }
+
+        // set lower right
+        planes.setScreenCharAndAttr(lastPos, (char) lr, colorAttr, false);
+
+        if (gui) {
+            planes.setUseGUI(lastPos, LOWER_RIGHT);
+        }
+
+        setDirty(lastPos);
+        advancePos();
+        // set ending attribute byte
+        planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true);
+        setDirty(lastPos);
+    }
+
+    /**
+     * Creates a scroll bar on the screen using the parameters provided.
+     *  ** we only support vertical scroll bars at the time.
+     *
+     * @param flag -
+     *            type to draw - vertical or horizontal
+     * @param totalRowScrollable
+     * @param totalColScrollable
+     * @param sliderRowPos
+     * @param sliderColPos
+     * @param sbSize
+     */
+    protected void createScrollBar(int flag, int totalRowScrollable,
+                                   int totalColScrollable, int sliderRowPos, int sliderColPos,
+                                   int sbSize) {
+        //      System.out.println("Scrollbar flag: " + flag +
+        //                           " scrollable Rows: " + totalRowScrollable +
+        //                           " scrollable Cols: " + totalColScrollable +
+        //                           " thumb Row: " + sliderRowPos +
+        //                           " thumb Col: " + sliderColPos +
+        //                           " size: " + sbSize +
+        //                           " row: " + getRow(lastPos) +
+        //                           " col: " + getCol(lastPos));
+        int sp = lastPos;
+        int size = sbSize - 2;
+        int thumbPos = (int)(size * ((float) sliderColPos / (float) totalColScrollable));
+        //      System.out.println(thumbPos);
+        planes.setScreenCharAndAttr(sp, ' ', 32, false);
+        planes.setUseGUI(sp, BUTTON_SB_UP);
+        int ctr = 0;
+
+        while (ctr < size) {
+            sp += numCols;
+            planes.setScreenCharAndAttr(sp, ' ', 32, false);
+
+            if (ctr == thumbPos)
+                planes.setUseGUI(sp, BUTTON_SB_THUMB);
+            else
+                planes.setUseGUI(sp, BUTTON_SB_GUIDE);
+
+            ctr++;
+        }
+
+        sp += numCols;
+        planes.setScreenCharAndAttr(sp, ' ', 32, false);
+        planes.setUseGUI(sp, BUTTON_SB_DN);
+    }
+
+    /**
+     * Write the title of the window that is on the screen
+     *
+     * @param pos
+     * @param depth
+     * @param width
+     * @param orientation
+     * @param monoAttr
+     * @param colorAttr
+     * @param title
+     */
+    protected void writeWindowTitle(int pos, int depth, int width,
+                                    byte orientation, int monoAttr, int colorAttr, StringBuffer title) {
+        int len = title.length();
+
+        // get bit 0 and 1 for interrogation
+        switch (orientation & 0xc0) {
+            case 0x40: // right
+                pos += (4 + width - len);
+                break;
+
+            case 0x80: // left
+                pos += 2;
+                break;
+
+            default: // center
+                // this is to place the position to the first text position of the
+                // window
+                //    the position passed in is the first attribute position, the next
+                //    is the border character and then there is another attribute after
+                //    that.
+                pos += (3 + ((width / 2) - (len / 2)));
+                break;
+        }
+
+        //  if bit 2 is on then this is a footer
+        if ((orientation & 0x20) == 0x20)
+            pos += ((depth + 1) * numCols);
+
+        //      System.out.println(pos + "," + width + "," + len+ "," + getRow(pos)
+        //                              + "," + getCol(pos) + "," + ((orientation >> 6) & 0xf0));
+
+        for (int x = 0; x < len; x++) {
+            planes.setChar(pos, title.charAt(x));
+            planes.setUseGUI(pos++, NO_GUI);
+        }
+    }
+
+    /**
+     * Roll the screen up or down.
+     *
+     * Byte 1: Bit 0 0 = Roll up 1 = Roll down Bits 1-2 Reserved Bits 3-7 Number
+     * of lines that the designated area is to be rolled Byte 2: Bits 0-7 Line
+     * number defining the top line of the area that will participate in the
+     * roll. Byte 3: Bits 0-7 Line number defining the bottom line of the area
+     * that will participate in the roll.
+     *
+     * @param direction
+     * @param topLine
+     * @param bottomLine
+     */
+    protected void rollScreen(int direction, int topLine, int bottomLine) {
+        // get the number of lines which are the last 5 bits
+        /* int lines = direction & 0x7F; */
+        // get the direction of the roll which is the first bit
+        //    0 - up
+        //    1 - down
+        int updown = direction & 0x80;
+        final int lines = direction & 0x7F;
+        // calculate the reference points for the move.
+        int start = this.getPos(topLine - 1, 0);
+        int end = this.getPos(bottomLine - 1, numCols - 1);
+        int len = end - start;
+
+        //      System.out.println(" starting roll");
+        //      dumpScreen();
+        switch (updown) {
+            case 0:
+
+                //  Now round em up and head em UP.
+                for (int x = start; x < end + numCols; x++) {
+                    if (x + lines * numCols >= lenScreen) {
+                        //Clear at the end
+                        planes.setChar(x, ' ');
+                    }
+                    else {
+                        planes.setChar(x, planes.getChar(x + lines * numCols));
+                    }
+                }
+
+                break;
+
+            case 1:
+
+                //  Now round em up and head em DOWN.
+                for (int x = end + numCols; x > 0; x--) {
+                    if ((x - lines * numCols) < 0) {
+                        //Do nothing ... tooo small!!!
+                    }
+                    else {
+                        planes.setChar(x - lines  * numCols, planes.getChar(x));
+                        //and clear
+                        planes.setChar(x, ' ');
+                    }
+                }
+
+                break;
+
+            default:
+                Log.w(TAG, " Invalid roll parameter - please report this");
+        }
+
+        //      System.out.println(" end roll");
+        //      dumpScreen();
+    }
+
+    public void dumpScreen() {
+        StringBuffer sb = new StringBuffer();
+        char[] s = getScreenAsChars();
+        int c = getColumns();
+        int l = getRows() * c;
+        int col = 0;
+
+        for (int x = 0; x < l; x++, col++) {
+            sb.append(s[x]);
+
+            if (col == c) {
+                sb.append('\n');
+                col = 0;
+            }
+        }
+
+        Log.i(TAG, sb.toString());
+    }
+
+    /**
+     * Add a field to the field format table.
+     *
+     * @param attr - Field attribute
+     * @param len - length of field
+     * @param ffw1 - Field format word 1
+     * @param ffw2 - Field format word 2
+     * @param fcw1 - Field control word 1
+     * @param fcw2 - Field control word 2
+     */
+    protected void addField(int attr, int len, int ffw1, int ffw2, int fcw1,
+                            int fcw2) {
+        lastAttr = attr;
+        planes.setScreenCharAndAttr(lastPos, initChar, lastAttr, true);
+        setDirty(lastPos);
+        advancePos();
+        ScreenField sf = null;
+
+        // from 14.6.12 for Start of Field Order 5940 function manual
+        //  examine the format table for an entry that begins at the current
+        //  starting address plus 1.
+        if (screenFields.existsAtPos(lastPos)) {
+            screenFields.setCurrentFieldFFWs(ffw1, ffw2);
+        }
+        else {
+            sf = screenFields.setField(attr, getRow(lastPos), getCol(lastPos),
+                                       len, ffw1, ffw2, fcw1, fcw2);
+            lastPos = sf.startPos();
+            int x = len;
+            boolean gui = guiInterface;
+
+            if (sf.isBypassField())
+                gui = false;
+
+            while (x-- > 0) {
+                if (planes.getChar(lastPos) == 0)
+                    planes.setScreenCharAndAttr(lastPos, ' ', lastAttr, false);
+                else
+                    planes.setScreenAttr(lastPos, lastAttr);
+
+                if (gui) {
+                    planes.setUseGUI(lastPos, FIELD_MIDDLE);
+                }
+
+                // now we set the field plane attributes
+                planes.setScreenFieldAttr(lastPos, ffw1);
+                advancePos();
+            }
+
+            if (gui)
+                if (len > 1) {
+                    planes.setUseGUI(sf.startPos(), FIELD_LEFT);
+
+                    if (lastPos > 0)
+                        planes.setUseGUI(lastPos - 1, FIELD_RIGHT);
+                    else
+                        planes.setUseGUI(lastPos, FIELD_RIGHT);
+                }
+                else {
+                    planes.setUseGUI(lastPos - 1, FIELD_ONE);
+                }
+
+            //         screen[lastPos].setCharAndAttr(initChar,initAttr,true);
+            setEndingAttr(initAttr);
+            lastPos = sf.startPos();
+        }
+
+        //      if (fcw1 != 0 || fcw2 != 0) {
+        //         System.out.println("lr = " + lastRow + " lc = " + lastCol + " " +
+        // sf.toString());
+        //      }
+        sf = null;
+    }
+
+
+    //      public void addChoiceField(int attr, int len, int ffw1, int ffw2, int
+    // fcw1, int fcw2) {
+    //
+    //         lastAttr = attr;
+    //
+    //         screen[lastPos].setCharAndAttr(initChar,lastAttr,true);
+    //         setDirty(lastPos);
+    //
+    //         advancePos();
+    //
+    //         boolean found = false;
+    //         ScreenField sf = null;
+    //
+    //         // from 14.6.12 for Start of Field Order 5940 function manual
+    //         // examine the format table for an entry that begins at the current
+    //         // starting address plus 1.
+    //         for (int x = 0;x < sizeFields; x++) {
+    //            sf = screenFields[x];
+    //
+    //            if (lastPos == sf.startPos()) {
+    //               screenFields.getCurrentField() = sf;
+    //               screenFields.getCurrentField().setFFWs(ffw1,ffw2);
+    //               found = true;
+    //            }
+    //
+    //         }
+    //
+    //         if (!found) {
+    //            sf =
+    // setField(attr,getRow(lastPos),getCol(lastPos),len,ffw1,ffw2,fcw1,fcw2);
+    //
+    //            lastPos = sf.startPos();
+    //            int x = len;
+    //
+    //            boolean gui = guiInterface;
+    //            if (sf.isBypassField())
+    //               gui = false;
+    //
+    //            while (x-- > 0) {
+    //
+    //               if (screen[lastPos].getChar() == 0)
+    //                  screen[lastPos].setCharAndAttr(' ',lastAttr,false);
+    //               else
+    //                  screen[lastPos].setAttribute(lastAttr);
+    //
+    //               if (gui)
+    //                  screen[lastPos].setUseGUI(FIELD_MIDDLE);
+    //
+    //               advancePos();
+    //
+    //            }
+    //
+    //            if (gui)
+    //               if (len > 1) {
+    //                  screen[sf.startPos()].setUseGUI(FIELD_LEFT);
+    //                  if (lastPos > 0)
+    //                     screen[lastPos-1].setUseGUI(FIELD_RIGHT);
+    //                  else
+    //                     screen[lastPos].setUseGUI(FIELD_RIGHT);
+    //
+    //               }
+    //               else
+    //                  screen[lastPos-1].setUseGUI(FIELD_ONE);
+    //
+    //            setEndingAttr(initAttr);
+    //
+    //            lastPos = sf.startPos();
+    //         }
+    //
+    //   // if (fcw1 != 0 || fcw2 != 0) {
+    //   //
+    //   // System.out.println("lr = " + lastRow + " lc = " + lastCol + " " +
+    // sf.toString());
+    //   // }
+    //         sf = null;
+    //
+    //      }
+
+    /**
+     * Return the fields that are contained in the Field Format Table
+     *
+     * @return ScreenFields object
+     * @see org.tn5250j.ScreenFields
+     */
+    public ScreenFields getScreenFields() {
+        return screenFields;
+    }
+
+    /**
+     * Redraw the fields on the screen. Used for gui enhancement to redraw the
+     * fields when toggling
+     *
+     */
+    protected void drawFields() {
+        ScreenField sf;
+        int sizeFields = screenFields.getSize();
+
+        for (int x = 0; x < sizeFields; x++) {
+            sf = screenFields.getField(x);
+
+            if (!sf.isBypassField()) {
+                int pos = sf.startPos();
+                int l = sf.length;
+                boolean f = true;
+
+                if (l >= lenScreen)
+                    l = lenScreen - 1;
+
+                if (l > 1) {
+                    while (l-- > 0) {
+                        if (guiInterface && f) {
+                            planes.setUseGUI(pos, FIELD_LEFT);
+                            f = false;
+                        }
+                        else {
+                            planes.setUseGUI(pos, FIELD_MIDDLE);
+                        }
+
+                        if (guiInterface && l == 0) {
+                            planes.setUseGUI(pos, FIELD_RIGHT);
+                        }
+
+                        setDirty(pos++);
+                    }
+                }
+                else {
+                    planes.setUseGUI(pos, FIELD_ONE);
+                }
+            }
+        }
+
+        //updateDirty();
+    }
+
+    /**
+     * Draws the field on the screen. Used to redraw or change the attributes of
+     * the field.
+     *
+     * @param sf -
+     *            Field to be redrawn
+     * @see org.tn5250j.ScreenField.java
+     */
+    protected void drawField(ScreenField sf) {
+        int pos = sf.startPos();
+        int x = sf.length;
+
+        while (x-- > 0) {
+            setDirty(pos++);
+        }
+
+        updateDirty();
+    }
+
+    /**
+     * Set the field to be displayed as highlighted.
+     *
+     * @param sf -
+     *            Field to be highlighted
+     */
+    protected void setFieldHighlighted(ScreenField sf) {
+        int pos = sf.startPos();
+        int x = sf.length;
+        int na = sf.getHighlightedAttr();
+
+        while (x-- > 0) {
+            planes.setScreenAttr(pos, na);
+            setDirty(pos++);
+        }
+
+        fireScreenChanged();
+    }
+
+    /**
+     * Draw the field as un higlighted. This is used to reset the field
+     * presentation on the screen after the field is exited.
+     *
+     * @param sf -
+     *            Field to be unhighlighted
+     */
+    protected void unsetFieldHighlighted(ScreenField sf) {
+        int pos = sf.startPos();
+        int x = sf.length;
+        int na = sf.getAttr();
+
+        while (x-- > 0) {
+            planes.setScreenAttr(pos, na);
+            setDirty(pos++);
+        }
+
+        fireScreenChanged();
+    }
+
+    protected void setChar(int cByte) {
+        if (lastPos > 0) {
+            lastAttr = planes.getCharAttr(lastPos - 1);
+        }
+
+        if (cByte > 0 && (char)cByte < ' ') {
+            planes.setScreenCharAndAttr(lastPos, (char) 0x00, 33, false);
+            setDirty(lastPos);
+            advancePos();
+        }
+        else {
+            planes.setScreenCharAndAttr(lastPos, (char) cByte, lastAttr, false);
+            setDirty(lastPos);
+
+            if (guiInterface && !isInField(lastPos, false)) {
+                planes.setUseGUI(lastPos, NO_GUI);
+            }
+
+            advancePos();
+        }
+    }
+
+    protected void setEndingAttr(int cByte) {
+        int attr = lastAttr;
+        setAttr(cByte);
+        lastAttr = attr;
+    }
+
+    protected void setAttr(int cByte) {
+        lastAttr = cByte;
+        //      int sattr = screen[lastPos].getCharAttr();
+        //         System.out.println("changing from " + sattr + " to attr " + lastAttr
+        // +
+        //                     " at " + (this.getRow(lastPos) + 1) + "," + (this.getCol(lastPos) +
+        // 1));
+        planes.setScreenCharAndAttr(lastPos, initChar, lastAttr, true);
+        setDirty(lastPos);
+        advancePos();
+        int pos = lastPos;
+        int times = 0;
+        //      sattr = screen[lastPos].getCharAttr();
+        //         System.out.println(" next position after change " + sattr + " last
+        // attr " + lastAttr +
+        //                     " at " + (this.getRow(lastPos) + 1) + "," + (this.getCol(lastPos) +
+        // 1) +
+        //                     " attr place " + screen[lastPos].isAttributePlace());
+
+        while (planes.getCharAttr(lastPos) != lastAttr
+                && !planes.isAttributePlace(lastPos)) {
+            planes.setScreenAttr(lastPos, lastAttr);
+
+            if (guiInterface && !isInField(lastPos, false)) {
+                int g = planes.getWhichGUI(lastPos);
+
+                if (g >= FIELD_LEFT && g <= FIELD_ONE)
+                    planes.setUseGUI(lastPos, NO_GUI);
+            }
+
+            setDirty(lastPos);
+            times++;
+            advancePos();
+        }
+
+        // sanity check for right now
+        //      if (times > 200)
+        //         System.out.println(" setAttr = " + times + " start = " + (sr + 1) +
+        // "," + (sc + 1));
+        lastPos = pos;
+    }
+
+    protected void setScreenCharAndAttr(char right, int colorAttr, boolean isAttr) {
+        planes.setScreenCharAndAttr(lastPos, right, colorAttr, isAttr);
+        setDirty(lastPos);
+        advancePos();
+    }
+
+    protected void setScreenCharAndAttr(char right, int colorAttr,
+                                        int whichGui, boolean isAttr) {
+        planes.setScreenCharAndAttr(lastPos, right, colorAttr, isAttr);
+        planes.setUseGUI(lastPos, whichGui);
+        setDirty(lastPos);
+        advancePos();
+    }
+
+    /**
+     * Draw or redraw the dirty parts of the screen and display them.
+     *
+     * Rectangle dirty holds the dirty area of the screen to be updated.
+     *
+     * If you want to change the screen in anyway you need to set the screen
+     * attributes before calling this routine.
+     */
+    protected void updateDirty() {
+        fireScreenChanged();
+    }
+
+    protected void setDirty(int pos) {
+        int minr = Math.min(getRow(pos), getRow(dirtyScreen.x));
+        int minc = Math.min(getCol(pos), getCol(dirtyScreen.x));
+        int maxr = Math.max(getRow(pos), getRow(dirtyScreen.y));
+        int maxc = Math.max(getCol(pos), getCol(dirtyScreen.y));
+        int x1 = getPos(minr, minc);
+        int x2 = getPos(maxr, maxc);
+        dirtyScreen.setBounds(x1, x2, 0, 0);
+    }
+
+    private void resetDirty(int pos) {
+        dirtyScreen.setBounds(pos, pos, 0, 0);
+    }
+
+    /**
+     * Change the screen position by one column
+     */
+    protected void advancePos() {
+        changePos(1);
+    }
+
+    /**
+     * Change position of the screen by the increment of parameter passed.
+     *
+     * If the position change is under the minimum of the first screen position
+     * then the position is moved to the last row and column of the screen.
+     *
+     * If the position change is over the last row and column of the screen then
+     * cursor is moved to first position of the screen.
+     *
+     * @param i
+     */
+    protected void changePos(int i) {
+        lastPos += i;
+
+        while (lastPos < 0)          lastPos += lenScreen;
+
+        while (lastPos >= lenScreen) lastPos -= lenScreen;
+    }
+
+
+    protected void goHome() {
+        //  now we try to move to first input field according to
+        //  14.6 WRITE TO DISPLAY Command
+        //    ? If the WTD command is valid, after the command is processed,
+        //          the cursor moves to one of three locations:
+        //    - The location set by an insert cursor order (unless control
+        //          character byte 1, bit 1 is equal to B'1'.)
+        //    - The start of the first non-bypass input field defined in the
+        //          format table
+        //    - A default starting address of row 1 column 1.
+        if (pendingInsert && homePos > 0) {
+            setCursor(getRow(homePos), getCol(homePos));
+            isInField();
+        }
+        else {
+            if (!gotoField(1)) {
+                homePos = getPos(1, 1);
+                setCursor(1, 1);
+                isInField(0, 0);
+            }
+            else {
+                homePos = getPos(getCurrentRow(), getCurrentCol());
+            }
+        }
+    }
+
+    protected void setPendingInsert(boolean flag, int icX, int icY) {
+        pendingInsert = flag;
+
+        if (pendingInsert) {
+            homePos = getPos(icX, icY);
+        }
+
+        if (!isStatusErrorCode()) {
+            setCursor(icX, icY);
+        }
+    }
+
+    protected void setPendingInsert(boolean flag) {
+        if (homePos != -1)
+            pendingInsert = flag;
+    }
+
+    /**
+     * Set the error line number to that of number passed.
+     *
+     * @param line
+     */
+    protected void setErrorLine(int line) {
+        planes.setErrorLine(line);
+    }
+
+    /**
+     * Returns the current error line number
+     *
+     * @return current error line number
+     */
+    protected int getErrorLine() {
+        return planes.getErrorLine();
+    }
+
+    /**
+     * Saves off the current error line characters to be used later.
+     *
+     */
+    protected void saveErrorLine() {
+        planes.saveErrorLine();
+    }
+
+    /**
+     * Restores the error line characters from the save buffer.
+     *
+     * @see #saveErrorLine()
+     */
+    protected void restoreErrorLine() {
+        if (planes.isErrorLineSaved()) {
+            planes.restoreErrorLine();
+            fireScreenChanged(planes.getErrorLine() - 1, 0, planes.getErrorLine() - 1, numCols - 1);
+        }
+    }
+
+    protected void setStatus(byte attr, byte value, String s) {
+        // set the status area
+        switch (attr) {
+            case STATUS_SYSTEM:
+                if (value == STATUS_VALUE_ON) {
+                    oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, s);
+                }
+                else {
+                    oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, ScreenOIA.OIA_LEVEL_NOT_INHIBITED, s);
+                }
+
+                break;
+
+            case STATUS_ERROR_CODE:
+                if (value == STATUS_VALUE_ON) {
+                    setPrehelpState(true, true, false);
+                    oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+                                          ScreenOIA.OIA_LEVEL_INPUT_ERROR, s);
+                    sessionVT.signalBell();
+                }
+                else {
+                    oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED,
+                                          ScreenOIA.OIA_LEVEL_NOT_INHIBITED);
+                    setPrehelpState(false, true, true);
+                    homePos = saveHomePos;
+                    saveHomePos = 0;
+                    pendingInsert = false;
+                }
+
+                break;
+        }
+    }
+
+    protected boolean isStatusErrorCode() {
+        return oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_ERROR;
+    }
+
+    /**
+     * This routine clears the screen, resets row and column to 0, resets the
+     * last attribute to 32, clears the fields, turns insert mode off,
+     * clears/initializes the screen character array.
+     */
+    protected void clearAll() {
+        lastAttr = 32;
+        lastPos = 0;
+        clearTable();
+        clearScreen();
+        planes.setScreenAttr(0, initAttr);
+        oia.setInsertMode(false);
+    }
+
+    /**
+     * Clear the fields table
+     */
+    protected void clearTable() {
+        oia.setKeyBoardLocked(true);
+        screenFields.clearFFT();
+        planes.initalizeFieldPlanes();
+        pendingInsert = false;
+        homePos = -1;
+    }
+
+    /**
+     * Clear the gui constructs
+     *
+     */
+    protected void clearGuiStuff() {
+        for (int x = 0; x < lenScreen; x++) {
+            planes.setUseGUI(x, NO_GUI);
+        }
+
+        dirtyScreen.setBounds(0, lenScreen - 1, 0, 0);
+    }
+
+    /**
+     * Clear the screen by setting the initial character and initial attribute
+     * to all the positions on the screen
+     */
+    protected void clearScreen() {
+        planes.initalizePlanes();
+        dirtyScreen.setBounds(0, lenScreen - 1, 0, 0);
+        oia.clearScreen();
+    }
+
+    protected void restoreScreen() {
+        lastAttr = 32;
+        dirtyScreen.setBounds(0, lenScreen - 1, 0, 0);
+        updateDirty();
+    }
+
+    public void onFontSizeChanged(float size) {
+        fireScreenChanged(0, 0, numRows - 1, numCols - 1);
+    }
+
+    /**
+     * repaint part of the screen
+     *
+     */
+    private void fireScreenChanged(int startRow, int startCol, int endRow, int endCol) {
+        int [] vt320color = {0x0, // black
+                             0x4, // blue
+                             0x2, // green
+                             0x6, // cyan
+                             0x1, // red
+                             0x5, // magenta/purple
+                             0xb, // yellow
+                             0x7, // light gray/white
+                             0x8, // dark gray
+                             0xc, // light blue
+                             0xa, // light green
+                             0xe, // light cyan
+                             0x9, // light red
+                             0xd, // light magenta/purple
+                             0x3, // brown
+                             0xf  // bright white
+                            };
+
+        for (int r = startRow; r <= endRow; r++) {
+            for (int c = startCol; c <= endCol; c++) {
+                int p = getPos(r, c);
+                char ch = planes.getChar(p);
+                char co = planes.getCharColor(p);
+                char at = planes.getCharExtended(p);
+                boolean ia = planes.isAttributePlace(p);
+
+                if (ch < ' ') ch = ' ';
+
+                int bg = vt320color[(co >> 8) & 0x0f] + 1;
+                int fg = vt320color[co        & 0x0f] + 1;
+                int ul = at & EXTENDED_5250_UNDERLINE;
+                int nd = at & EXTENDED_5250_NON_DSP;
+                int vt_attr = (fg << VDUBuffer.COLOR_FG_SHIFT) + (bg << VDUBuffer.COLOR_BG_SHIFT);
+
+                if (ul > 0) vt_attr |= VDUBuffer.UNDERLINE;
+
+                if (ia || (nd > 0)) vt_attr |= VDUBuffer.INVISIBLE;
+
+                buffer.putChar(c, r, ch, vt_attr);
+            }
+        }
+
+        buffer.redrawPassthru();
+        dirtyScreen.setBounds(lenScreen, 0, 0, 0);
+    }
+
+    /**
+     * repaint the dirty part of the screen
+     *
+     */
+
+    private synchronized void fireScreenChanged() {
+        if (dirtyScreen.x > dirtyScreen.y) return;
+        fireScreenChanged(getRow(dirtyScreen.x), getCol(dirtyScreen.x),
+                          getRow(dirtyScreen.y), getCol(dirtyScreen.y));
+    }
+
+    /**
+     * update the cursor position
+     *
+     */
+
+    private synchronized void fireCursorChanged() {
+        int l = getRow(lastPos);
+        int c = getCol(lastPos);
+        buffer.setCursorPosition(c, l);
+    }
+
+    /**
+     * update the screen size.
+     */
+    private void fireScreenSizeChanged() {
+        buffer.setScreenSize(numCols, numRows, true);
+    }
+
+    /**
+     * This method does a complete refresh of the screen.
+     */
+    public final void updateScreen() {
+        repaintScreen();
+        setCursorActive(false);
+        setCursorActive(true);
+    }
+
+    /**
+     * Utility method to share the repaint behaviour between setBounds() and
+     * updateScreen.
+     */
+    public void repaintScreen() {
+        setCursorOff();
+        dirtyScreen.setBounds(0, lenScreen - 1, 0, 0);
+        updateDirty();
+
+        // restore statuses that were on the screen before resize
+        if (oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_ERROR) {
+            oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+                                  ScreenOIA.OIA_LEVEL_INPUT_ERROR);
+        }
+
+        if (oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_INHIBITED) {
+            oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+                                  ScreenOIA.OIA_LEVEL_INPUT_INHIBITED);
+        }
+
+        if (oia.isMessageWait())
+            oia.setMessageLightOn();
+
+        setCursorOn();
+    }
+
+    // ADDED BY BARRY - changed by Kenneth to use the character plane
+    //  This should be replaced with the getPlane methods when they are implemented
+    public char[] getCharacters() {
+        return planes.screen;
+    }
+
+}