changeset 3:e8d2a24e85c6 tn5250

adding tn5250 files
author Carl Byington <carl@five-ten-sg.com>
date Thu, 22 May 2014 12:11:10 -0700
parents a01665cb683d
children 1f5d9b76a183
files TODO src/org/tn5250j/TN5250jConstants.java src/org/tn5250j/framework/Tn5250jEvent.java src/org/tn5250j/framework/Tn5250jKeyEvents.java src/org/tn5250j/framework/Tn5250jListener.java src/org/tn5250j/framework/tn5250/DataStreamProducer.java src/org/tn5250j/framework/tn5250/KbdTypesCodePages.java src/org/tn5250j/framework/tn5250/KeyStrokenizer.java src/org/tn5250j/framework/tn5250/Rect.java src/org/tn5250j/framework/tn5250/Screen5250.java src/org/tn5250j/framework/tn5250/ScreenField.java src/org/tn5250j/framework/tn5250/ScreenFields.java src/org/tn5250j/framework/tn5250/ScreenOIA.java src/org/tn5250j/framework/tn5250/ScreenPlanes.java src/org/tn5250j/framework/tn5250/Stream5250.java src/org/tn5250j/framework/tn5250/WTDSFParser.java src/org/tn5250j/framework/tn5250/tnvt.java src/org/tn5250j/framework/transport/SSL/SSLImplementation.java src/org/tn5250j/framework/transport/SSL/X509CertificateTrustManager.java src/org/tn5250j/framework/transport/SSLInterface.java src/org/tn5250j/framework/transport/SocketConnector.java
diffstat 21 files changed, 12607 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/TODO	Thu May 22 12:09:58 2014 -0700
+++ b/TODO	Thu May 22 12:11:10 2014 -0700
@@ -41,6 +41,6 @@
 
 
 merge tn5250j
-svn checkout svn://svn.code.sf.net/p/tn5250j/code/trunk tn5250j
+svn checkout svn://svn.code.sf.net/p/tn5250j/code/branches/new-tabs-jse1.6 tn5250j
 after 5250 merge, go up to version 1.8.0-1
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/TN5250jConstants.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,530 @@
+/*
+ * @(#)TN5250jConstants.java
+ * Copyright:    Copyright (c) 2001
+ *
+ * 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;
+
+public interface TN5250jConstants {
+
+   // Version information
+   public static final String tn5250jRelease = "0";
+   public static final String tn5250jVersion = ".7";
+   public static final String tn5250jSubVer= ".3";
+   
+   public static final String VERSION_INFO = tn5250jRelease + tn5250jVersion + tn5250jSubVer;
+
+   // STATE
+   static final int STATE_DISCONNECTED   =  0;
+   static final int STATE_CONNECTED   =  1;
+   static final int STATE_REMOVE   =  2;
+
+   // SESSION Level key value pairs
+   public static final String SESSION_HOST      = "SESSION_HOST";
+   public static final String SESSION_HOST_PORT ="SESSION_HOST_PORT";
+   public static final String SESSION_CONFIG_RESOURCE = "SESSION_CONFIG_RESOURCE";
+   public static final String SESSION_TYPE     = "SESSION_HOST_TYPE";
+   public static final String SESSION_TN_ENHANCED = "SESSION_TN_ENHANCED";
+   public static final String SESSION_SCREEN_SIZE = "SESSION_SCREEN_SIZE";
+   public static final String SESSION_CODE_PAGE = "SESSION_CODE_PAGE";
+   public static final String SESSION_PROXY_HOST = "SESSION_PROXY_HOST";
+   public static final String SESSION_PROXY_PORT = "SESSION_PROXY_PORT";
+   public static final String SESSION_USE_GUI = "SESSION_USE_GUI";
+   public static final String SESSION_DEVICE_NAME = "SESSION_DEVICE_NAME";
+   public static final String SESSION_NAMES_REFS = "SESSION_NAMES_REFS";
+   public static final String SESSION_LOCALE = "SESSION_LOCALE";
+   public static final String SESSION_CONFIG_FILE = "SESSION_CONFIG_FILE";
+   public static final String SESSION_TERM_NAME_SYSTEM = "SESSION_TERM_NAME_SYSTEM";
+   public static final String SESSION_TERM_NAME = "SESSION_TERM_NAME";
+   public static final String SESSION_IS_APPLET = "SESSION_IS_APPLET";
+   public static final String SESSION_HEART_BEAT = "SESSION_KEEP_ALIVE_ENABLED";
+
+//   public static final String GUI_MDI_TYPE = "GUI_MDI_TYPE";
+   public static final String GUI_FRAME_WIDTH = "GUI_FRAME_WIDTH";
+   public static final String GUI_FRAME_HEIGHT = "GUI_FRAME_HEIGHT";
+   public static final String GUI_NO_TAB = "GUI_NO_TAB";
+   public static final String NO_CHECK_RUNNING = "NO_CHECK_RUNNING";
+   public static final String START_MONITOR_THREAD = "START_MONITOR_THREAD";
+
+//   public static final String SSL_TYPE = "TN5250J_SSL_TYPE";
+   public static final String SSL_TYPE = "-sslType";
+   public static final String SSL_TYPE_NONE = "NONE";
+   public static final String SSL_TYPE_SSLv2 = "SSLv2";
+   public static final String SSL_TYPE_SSLv3 = "SSLv3";
+   public static final String SSL_TYPE_TLS = "TLS";
+
+   public static final String[] SSL_TYPES = {SSL_TYPE_NONE,
+                                             SSL_TYPE_SSLv2,
+                                             SSL_TYPE_SSLv3,
+                                             SSL_TYPE_TLS};
+
+   // Session JUMP Directions
+   static final int JUMP_PREVIOUS   =  0;
+   static final int JUMP_NEXT   =  1;
+
+//   // OS_OHIO_SESSION_TYPE type of sessions
+//   public static final String OS_OHIO_SESSION_TYPE_5250_STR   = "2";
+
+   // SCREEN_SIZE Size of screen string
+   public static final String SCREEN_SIZE_24X80_STR   = "0";
+   public static final String SCREEN_SIZE_27X132_STR   = "1";
+
+   // SCREEN_SIZE Size of screen int
+   public static final int SCREEN_SIZE_24X80   = 0;
+   public static final int SCREEN_SIZE_27X132   = 1;
+
+   public static final int NUM_PARMS = 20;
+
+   // mnemonic value constants
+   public static final int BACK_SPACE = 1001;
+   public static final int BACK_TAB  = 1002;
+   public static final int UP = 1003;
+   public static final int DOWN = 1004;
+   public static final int LEFT = 1005;
+   public static final int RIGHT = 1006;
+   public static final int DELETE = 1007;
+   public static final int TAB = 1008;
+   public static final int EOF = 1009;
+   public static final int ERASE_EOF = 1010;
+   public static final int ERASE_FIELD = 1011;
+   public static final int INSERT = 1012;
+   public static final int HOME = 1013;
+   public static final int KEYPAD_0 = 1014;
+   public static final int KEYPAD_1 = 1015;
+   public static final int KEYPAD_2 = 1016;
+   public static final int KEYPAD_3 = 1017;
+   public static final int KEYPAD_4 = 1018;
+   public static final int KEYPAD_5 = 1019;
+   public static final int KEYPAD_6 = 1020;
+   public static final int KEYPAD_7 = 1021;
+   public static final int KEYPAD_8 = 1022;
+   public static final int KEYPAD_9 = 1023;
+   public static final int KEYPAD_PERIOD = 1024;
+   public static final int KEYPAD_COMMA = 1025;
+   public static final int KEYPAD_MINUS = 1026;
+   public static final int FIELD_EXIT = 1027;
+   public static final int FIELD_PLUS = 1028;
+   public static final int FIELD_MINUS = 1029;
+   public static final int BOF = 1030;
+   public static final int SYSREQ = 1031;
+   public static final int RESET = 1032;
+   public static final int NEXTWORD = 1033;
+   public static final int PREVWORD = 1034;
+   public static final int COPY = 1035;
+   public static final int PASTE = 1036;
+   public static final int ATTN = 1037;
+   public static final int MARK_UP = 1038;
+   public static final int MARK_DOWN = 1039;
+   public static final int MARK_LEFT = 1040;
+   public static final int MARK_RIGHT = 1041;
+   public static final int DUP_FIELD = 1042;
+   public static final int NEW_LINE = 1043;
+   public static final int JUMP_NEXT_SESS = 5000;
+   public static final int JUMP_PREV_SESS = 5001;
+   public static final int OPEN_NEW = 5002;
+   public static final int TOGGLE_CONNECTION = 5003;
+   public static final int HOTSPOTS = 5004;
+   public static final int GUI = 5005;
+   public static final int DSP_MSGS = 5006;
+   public static final int DSP_ATTRIBUTES = 5007;
+   public static final int PRINT_SCREEN = 5008;
+   public static final int CURSOR = 5009;
+   public static final int DEBUG = 5010;
+   public static final int CLOSE = 5011;
+   public static final int TRANSFER = 5012;
+   public static final int E_MAIL = 5013;
+   public static final int RUN_SCRIPT = 5014;
+   public static final int SPOOL_FILE = 5015;
+   public static final int QUICK_MAIL = 5016;
+   public static final int OPEN_SAME = 5017;
+   public static final int FAST_CURSOR_DOWN = 5018;
+   public static final int FAST_CURSOR_UP = 5019;
+   public static final int FAST_CURSOR_RIGHT = 5020;
+   public static final int FAST_CURSOR_LEFT = 5021;
+
+   // PF Keys
+   public static final int PF1 = 0x31;
+   public static final int PF2 = 0x32;
+   public static final int PF3 = 0x33;
+   public static final int PF4 = 0x34;
+   public static final int PF5 = 0x35;
+   public static final int PF6 = 0x36;
+   public static final int PF7 = 0x37;
+   public static final int PF8 = 0x38;
+   public static final int PF9 = 0x39;
+   public static final int PF10 = 0x3A;
+   public static final int PF11 = 0x3B;
+   public static final int PF12 = 0x3C;
+   public static final int PF13 = 0xB1;
+   public static final int PF14 = 0xB2;
+   public static final int PF15 = 0xB3;
+   public static final int PF16 = 0xB4;
+   public static final int PF17 = 0xB5;
+   public static final int PF18 = 0xB6;
+   public static final int PF19 = 0xB7;
+   public static final int PF20 = 0xB8;
+   public static final int PF21 = 0xB9;
+   public static final int PF22 = 0xBA;
+   public static final int PF23 = 0xBB;
+   public static final int PF24 = 0xBC;
+
+   public static final String mnemonicData[] = {
+        "[backspace]", "[backtab]", "[up]", "[down]", "[left]",
+        "[right]", "[delete]", "[tab]", "[eof]", "[eraseeof]",
+        "[erasefld]", "[insert]", "[home]", "[keypad0]", "[keypad1]",
+        "[keypad2]", "[keypad3]", "[keypad4]", "[keypad5]", "[keypad6]",
+        "[keypad7]", "[keypad8]", "[keypad9]", "[keypad.]", "[keypad,]",
+        "[keypad-]", "[fldext]", "[field+]", "[field-]", "[bof]",
+        "[enter]","[pf1]","[pf2]","[pf3]","[pf4]",
+        "[pf5]","[pf6]","[pf7]","[pf8]","[pf9]",
+        "[pf10]","[pf11]","[pf12]","[pf13]","[pf14]",
+        "[pf15]","[pf16]","[pf17]","[pf18]","[pf19]",
+        "[pf20]","[pf21]","[pf22]","[pf23]","[pf24]",
+        "[clear]", "[help]", "[pgup]", "[pgdown]", "[rollleft]",
+        "[rollright]", "[hostprint]", "[pa1]", "[pa2]", "[pa3]",
+        "[sysreq]","[reset]","[nextword]", "[prevword]", "[copy]",
+        "[paste]","[attn]","[markup]", "[markdown]", "[markleft]",
+        "[markright]","[dupfield]","[newline]","[jumpnext]","[jumpprev]",
+        "[opennew]","[togcon]","[hotspots]","[gui]","[dspmsgs]",
+        "[dspattr]","[print]","[cursor]","[debug]","[close]",
+        "[transfer]","[e-mail]","[runscript]","[spoolfile]","[quick-mail]",
+        "[open-same]","[fastcursordown]","[fastcursorup]","[fastcursorright]","[fastcursorleft]"
+   };
+
+   public static final int mnemonicValue[] = {
+        1001, 1002, 1003, 1004, 1005,
+        1006, 1007, 1008, 1009, 1010,
+        1011, 1012, 1013, 1014, 1015,
+        1016, 1017, 1018, 1019, 1020,
+        1021, 1022, 1023, 1024, 1025,
+        1026, 1027, 1028, 1029, 1030,
+        0xF1, 0x31, 0x32, 0x33, 0x34,
+        0x35, 0x36, 0x37, 0x38, 0x39,
+        0x3A, 0x3B, 0x3C, 0xB1, 0xB2,
+        0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+        0xB8, 0xB9, 0xBA, 0xBB, 0xBC,
+        0xBD, 0xF3, 0xF4, 0xF5, 0xD9,
+        0xDA, 0xF6, 0x6C, 0x6E, 0x6B,
+        1031, 1032, 1033, 1034, 1035,
+        1036, 1037, 1038, 1039, 1040,
+        1041, 1042, 1043, 5000, 5001,
+        5002, 5003, 5004, 5005, 5006,
+        5007, 5008, 5009, 5010, 5011,
+        5012, 5013, 5014, 5015, 5016,
+        5017, 5018, 5019, 5020, 5021
+   };
+
+   public static final String MNEMONIC_CLEAR   =  "[clear]";
+   public static final String MNEMONIC_ENTER   =  "[enter]";
+   public static final String MNEMONIC_HELP   =  "[help]";
+   public static final String MNEMONIC_PAGE_DOWN   =  "[pgdown]";
+   public static final String MNEMONIC_PAGE_UP   =  "[pgup]";
+   public static final String MNEMONIC_PRINT   =  "[hostprint]";
+   public static final String MNEMONIC_PF1   =  "[pf1]";
+   public static final String MNEMONIC_PF2   =  "[pf2]";
+   public static final String MNEMONIC_PF3   =  "[pf3]";
+   public static final String MNEMONIC_PF4   =  "[pf4]";
+   public static final String MNEMONIC_PF5   =  "[pf5]";
+   public static final String MNEMONIC_PF6   =  "[pf6]";
+   public static final String MNEMONIC_PF7   =  "[pf7]";
+   public static final String MNEMONIC_PF8   =  "[pf8]";
+   public static final String MNEMONIC_PF9   =  "[pf9]";
+   public static final String MNEMONIC_PF10   =  "[pf10]";
+   public static final String MNEMONIC_PF11   =  "[pf11]";
+   public static final String MNEMONIC_PF12   =  "[pf12]";
+   public static final String MNEMONIC_PF13   =  "[pf13]";
+   public static final String MNEMONIC_PF14   =  "[pf14]";
+   public static final String MNEMONIC_PF15   =  "[pf15]";
+   public static final String MNEMONIC_PF16   =  "[pf16]";
+   public static final String MNEMONIC_PF17   =  "[pf17]";
+   public static final String MNEMONIC_PF18   =  "[pf18]";
+   public static final String MNEMONIC_PF19   =  "[pf19]";
+   public static final String MNEMONIC_PF20   =  "[pf20]";
+   public static final String MNEMONIC_PF21   =  "[pf21]";
+   public static final String MNEMONIC_PF22   =  "[pf22]";
+   public static final String MNEMONIC_PF23   =  "[pf23]";
+   public static final String MNEMONIC_PF24   =  "[pf24]";
+   public static final String MNEMONIC_BACK_SPACE   =  "[backspace]";
+   public static final String MNEMONIC_BACK_TAB   =  "[backtab]";
+   public static final String MNEMONIC_UP   =  "[up]";
+   public static final String MNEMONIC_DOWN   =  "[down]";
+   public static final String MNEMONIC_LEFT   =  "[left]";
+   public static final String MNEMONIC_RIGHT   =  "[right]";
+   public static final String MNEMONIC_DELETE   =  "[delete]";
+   public static final String MNEMONIC_TAB =  "[tab]";
+   public static final String MNEMONIC_END_OF_FIELD   =  "[eof]";
+   public static final String MNEMONIC_ERASE_EOF   =  "[eraseeof]";
+   public static final String MNEMONIC_ERASE_FIELD   =  "[erasefld]";
+   public static final String MNEMONIC_INSERT   =  "[insert]";
+   public static final String MNEMONIC_HOME   =  "[home]";
+   public static final String MNEMONIC_KEYPAD0   =  "[keypad0]";
+   public static final String MNEMONIC_KEYPAD1   =  "[keypad1]";
+   public static final String MNEMONIC_KEYPAD2   =  "[keypad2]";
+   public static final String MNEMONIC_KEYPAD3   =  "[keypad3]";
+   public static final String MNEMONIC_KEYPAD4   =  "[keypad4]";
+   public static final String MNEMONIC_KEYPAD5   =  "[keypad5]";
+   public static final String MNEMONIC_KEYPAD6   =  "[keypad6]";
+   public static final String MNEMONIC_KEYPAD7   =  "[keypad7]";
+   public static final String MNEMONIC_KEYPAD8   =  "[keypad8]";
+   public static final String MNEMONIC_KEYPAD9   =  "[keypad9]";
+   public static final String MNEMONIC_KEYPAD_PERIOD   =  "[keypad.]";
+   public static final String MNEMONIC_KEYPAD_COMMA   =  "[keypad,]";
+   public static final String MNEMONIC_KEYPAD_MINUS   =  "[keypad-]";
+   public static final String MNEMONIC_FIELD_EXIT   =  "[fldext]";
+   public static final String MNEMONIC_FIELD_PLUS   =  "[field+]";
+   public static final String MNEMONIC_FIELD_MINUS   =  "[field-]";
+   public static final String MNEMONIC_BEGIN_OF_FIELD   =  "[bof]";
+   public static final String MNEMONIC_PA1   =  "[pa1]";
+   public static final String MNEMONIC_PA2   =  "[pa2]";
+   public static final String MNEMONIC_PA3   =  "[pa3]";
+   public static final String MNEMONIC_SYSREQ   =  "[sysreq]";
+   public static final String MNEMONIC_RESET   =  "[reset]";
+   public static final String MNEMONIC_NEXTWORD   =  "[nextword]";
+   public static final String MNEMONIC_PREVWORD   =  "[prevword]";
+   public static final String MNEMONIC_ATTN   =  "[attn]";
+   public static final String MNEMONIC_MARK_LEFT   =  "[markleft]";
+   public static final String MNEMONIC_MARK_RIGHT   =  "[markright]";
+   public static final String MNEMONIC_MARK_UP   =  "[markup]";
+   public static final String MNEMONIC_MARK_DOWN   =  "[markdown]";
+   public static final String MNEMONIC_DUP_FIELD   =  "[dupfield]";
+   public static final String MNEMONIC_NEW_LINE   =  "[newline]";
+   public static final String MNEMONIC_JUMP_NEXT   =  "[jumpnext]";
+   public static final String MNEMONIC_JUMP_PREV   =  "[jumpprev]";
+   public static final String MNEMONIC_OPEN_NEW   =  "[opennew]";
+   public static final String MNEMONIC_TOGGLE_CONNECTION   =  "[togcon]";
+   public static final String MNEMONIC_HOTSPOTS   =  "[hotspots]";
+   public static final String MNEMONIC_GUI   =  "[gui]";
+   public static final String MNEMONIC_DISP_MESSAGES   =  "[dspmsgs]";
+   public static final String MNEMONIC_DISP_ATTRIBUTES   =  "[dspattr]";
+   public static final String MNEMONIC_PRINT_SCREEN   =  "[print]";
+   public static final String MNEMONIC_CURSOR   =  "[cursor]";
+   public static final String MNEMONIC_DEBUG   =  "[debug]";
+   public static final String MNEMONIC_CLOSE   =  "[close]";
+   public static final String MNEMONIC_E_MAIL   =  "[e-mail]";
+   public static final String MNEMONIC_COPY   =  "[copy]";
+   public static final String MNEMONIC_PASTE   =  "[paste]";
+   public static final String MNEMONIC_FILE_TRANSFER   =  "[transfer]";
+   public static final String MNEMONIC_RUN_SCRIPT   =  "[runscript]";
+   public static final String MNEMONIC_SPOOL_FILE   =  "[spoolfile]";
+   public static final String MNEMONIC_QUICK_MAIL   =  "[quick-mail]";
+   public static final String MNEMONIC_OPEN_SAME   =  "[open-same]";
+   public static final String MNEMONIC_FAST_CURSOR_DOWN   =  "[fastcursordown]";
+   public static final String MNEMONIC_FAST_CURSOR_UP   =  "[fastcursorup]";
+   public static final String MNEMONIC_FAST_CURSOR_RIGHT   =  "[fastcursorright]";
+   public static final String MNEMONIC_FAST_CURSOR_LEFT   =  "[fastcursorleft]";
+
+   // AID-Generating Keys
+   public static final int AID_CLEAR = 0xBD;
+   public static final int AID_ENTER = 0xF1;
+   public static final int AID_HELP = 0xF3;
+   public static final int AID_ROLL_UP = 0xF4;
+   public static final int AID_ROLL_DOWN = 0xF5;
+   public static final int AID_ROLL_LEFT = 0xD9;
+   public static final int AID_ROLL_RIGHT = 0xDA;
+   public static final int AID_PRINT = 0xF6;
+   public static final int AID_PF1 = 0x31;
+   public static final int AID_PF2 = 0x32;
+   public static final int AID_PF3 = 0x33;
+   public static final int AID_PF4 = 0x34;
+   public static final int AID_PF5 = 0x35;
+   public static final int AID_PF6 = 0x36;
+   public static final int AID_PF7 = 0x37;
+   public static final int AID_PF8 = 0x38;
+   public static final int AID_PF9 = 0x39;
+   public static final int AID_PF10 = 0x3A;
+   public static final int AID_PF11 = 0x3B;
+   public static final int AID_PF12 = 0x3C;
+   public static final int AID_PF13 = 0xB1;
+   public static final int AID_PF14 = 0xB2;
+   public static final int AID_PF15 = 0xB3;
+   public static final int AID_PF16 = 0xB4;
+   public static final int AID_PF17 = 0xB5;
+   public static final int AID_PF18 = 0xB6;
+   public static final int AID_PF19 = 0xB7;
+   public static final int AID_PF20 = 0xB8;
+   public static final int AID_PF21 = 0xB9;
+   public static final int AID_PF22 = 0xBA;
+   public static final int AID_PF23 = 0xBB;
+   public static final int AID_PF24 = 0xBC;
+
+   // negative response categories
+   public static final int NR_REQUEST_REJECT = 0x08;
+   public static final int NR_REQUEST_ERROR = 0x10;
+   public static final int NR_STATE_ERROR = 0x20;
+   public static final int NR_USAGE_ERROR = 0x40;
+   public static final int NR_PATH_ERROR = 0x80;
+
+   // commands
+   public static final byte CMD_WRITE_TO_DISPLAY = 0x11; // 17
+   public static final byte CMD_CLEAR_UNIT = 0x40; // 64
+   public static final byte CMD_CLEAR_UNIT_ALTERNATE = 0x20; // 32
+   public static final byte CMD_CLEAR_FORMAT_TABLE = 0x50; // 80
+   public static final byte CMD_READ_INPUT_FIELDS = 0x42; // 66
+   public static final byte CMD_READ_MDT_FIELDS = 0x52; // 82
+   public static final byte CMD_READ_MDT_IMMEDIATE_ALT = (byte)0x83; // 131
+//   public static final byte CMD_READ_MDT_FIELDS_ALT = (byte)0x82; // 130
+//   public static final byte CMD_READ_IMMEDIATE = 0x72; // 114
+   public static final byte CMD_READ_SCREEN_IMMEDIATE = 0x62; // 98
+   public static final byte CMD_WRITE_STRUCTURED_FIELD = (byte)243;  // (byte)0xF3 -13
+   public static final byte CMD_SAVE_SCREEN = 0x02; // 02
+   public static final byte CMD_RESTORE_SCREEN = 0x12; // 18
+   public static final byte CMD_WRITE_ERROR_CODE = 0x21; // 33
+   public static final byte CMD_WRITE_ERROR_CODE_TO_WINDOW = 0x22; // 34
+   public static final byte CMD_ROLL = 0x23; // 35
+   public static final byte CMD_READ_SCREEN_TO_PRINT = (byte)0x66; // 102
+
+   // PLANES
+   public static final int PLANE_TEXT   =  1;
+   public static final int PLANE_COLOR   =  2;
+   public static final int PLANE_FIELD   =  3;
+   public static final int PLANE_EXTENDED   =  4;
+   public static final int PLANE_EXTENDED_GRAPHIC   =  5;
+   public static final int PLANE_EXTENDED_FIELD   =  6;
+   public static final int PLANE_ATTR   =  7;
+   public static final int PLANE_IS_ATTR_PLACE   =  8;
+
+   // COLOR_BG
+   public static final char COLOR_BG_BLACK   =  0;
+   public static final char COLOR_BG_BLUE   =  1;
+   public static final char COLOR_BG_GREEN   =  2;
+   public static final char COLOR_BG_CYAN   =  3;
+   public static final char COLOR_BG_RED   =  4;
+   public static final char COLOR_BG_MAGENTA   =  5;
+   public static final char COLOR_BG_YELLOW   =  6;
+   public static final char COLOR_BG_WHITE   =  7;
+
+   // COLOR_FG
+   public static final char COLOR_FG_BLACK   =  0;
+   public static final char COLOR_FG_BLUE   =  1;
+   public static final char COLOR_FG_GREEN   =  2;
+   public static final char COLOR_FG_CYAN   =  3;
+   public static final char COLOR_FG_RED   =  4;
+   public static final char COLOR_FG_MAGENTA   =  5;
+   public static final char COLOR_FG_YELLOW   =  6;
+   public static final char COLOR_FG_WHITE   =  7;
+   public static final char COLOR_FG_BROWN   =  0xE;
+   public static final char COLOR_FG_GRAY   =  8;
+   public static final char COLOR_FG_LIGHT_BLUE   =  9;
+   public static final char COLOR_FG_LIGHT_GREEN   =  0xA;
+   public static final char COLOR_FG_LIGHT_CYAN   =  0xB;
+   public static final char COLOR_FG_LIGHT_RED   =  0xC;
+   public static final char COLOR_FG_LIGHT_MAGENTA   =  0xD;
+   public static final char COLOR_FG_WHITE_HIGH   =  0xF;
+
+   public static final int EXTENDED_5250_REVERSE   =  0x10;
+   public static final int EXTENDED_5250_UNDERLINE   =  0x08;
+   public static final int EXTENDED_5250_BLINK   =  0x04;
+   public static final int EXTENDED_5250_COL_SEP   =  0x02;
+   public static final int EXTENDED_5250_NON_DSP   =  0x01;
+
+   public static final char ATTR_32 = (COLOR_BG_BLACK << 8 & 0xff00) |
+   													(COLOR_FG_GREEN & 0xff);
+   public static final char ATTR_33 = (COLOR_BG_GREEN << 8 & 0xff00) |
+   													(COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_34 = (COLOR_BG_BLACK << 8 & 0xff00) |
+   													(COLOR_FG_WHITE & 0xff);
+   public static final char ATTR_35 = (COLOR_BG_WHITE << 8 & 0xff00) |
+   													(COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_36 = (COLOR_BG_BLACK << 8 & 0xff00) |
+   													(COLOR_FG_GREEN & 0xff);
+   public static final char ATTR_37 = (COLOR_BG_GREEN << 8 & 0xff00) |
+   													(COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_38 = (COLOR_BG_BLACK << 8 & 0xff00) |
+   													(COLOR_FG_WHITE & 0xff);
+   public static final char ATTR_40 = (COLOR_BG_BLACK << 8 & 0xff00) |
+   													(COLOR_FG_RED & 0xff);
+   public static final char ATTR_41 = (COLOR_BG_RED << 8 & 0xff00) |
+   													(COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_42 = (COLOR_BG_BLACK << 8 & 0xff00) |
+														(COLOR_FG_RED & 0xff);
+   public static final char ATTR_43 = (COLOR_BG_RED << 8 & 0xff00) |
+   													(COLOR_FG_BLACK & 0xff);
+
+   public static final char ATTR_44 = (COLOR_BG_BLACK << 8 & 0xff00) |
+   													(COLOR_FG_RED & 0xff);
+   public static final char ATTR_45 = ( COLOR_BG_RED << 8 & 0xff00) |
+   													( COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_46 = (COLOR_BG_BLACK << 8 & 0xff00) |
+														(COLOR_FG_RED & 0xff);
+
+   public static final char ATTR_48 = (COLOR_BG_BLACK << 8 & 0xff00) |
+      												(COLOR_FG_CYAN & 0xff);
+   public static final char ATTR_49 = (COLOR_BG_CYAN << 8 & 0xff00) |
+   													(COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_50 = (COLOR_BG_BLACK << 8 & 0xff00) |
+   													(COLOR_FG_YELLOW & 0xff);
+
+   public static final char ATTR_51 = (COLOR_BG_YELLOW << 8 & 0xff00) |
+   													(COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_52 = ( COLOR_BG_BLACK << 8 & 0xff00) |
+   													( COLOR_FG_CYAN & 0xff);
+   public static final char ATTR_53 = ( COLOR_BG_CYAN << 8 & 0xff00) |
+   													( COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_54 = ( COLOR_BG_BLACK << 8 & 0xff00) |
+   													( COLOR_FG_YELLOW & 0xff);
+   public static final char ATTR_56 = ( COLOR_BG_BLACK << 8 & 0xff00) |
+   													( COLOR_FG_MAGENTA & 0xff);
+   public static final char ATTR_57 = ( COLOR_BG_MAGENTA << 8 & 0xff00) |
+   													( COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_58 = ( COLOR_BG_BLACK << 8 & 0xff00) |
+   													( COLOR_FG_BLUE & 0xff);
+   public static final char ATTR_59 = ( COLOR_BG_BLUE << 8 & 0xff00) |
+   													( COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_60 = ( COLOR_BG_BLACK << 8 & 0xff00) |
+   													( COLOR_FG_MAGENTA & 0xff);
+   public static final char ATTR_61 = ( COLOR_BG_MAGENTA << 8 & 0xff00) |
+   													( COLOR_FG_BLACK & 0xff);
+   public static final char ATTR_62 = ( COLOR_BG_BLACK << 8 & 0xff00) |
+   													( COLOR_FG_BLUE & 0xff);
+
+   public static final int NO_GUI = 0;
+   public static final int UPPER_LEFT = 1;
+   public static final int UPPER = 2;
+   public static final int UPPER_RIGHT = 3;
+   public static final int GUI_LEFT = 4;
+   public static final int GUI_RIGHT = 5;
+   public static final int LOWER_LEFT = 6;
+   public static final int BOTTOM = 7;
+   public static final int LOWER_RIGHT = 8;
+   public static final int FIELD_LEFT = 9;
+   public static final int FIELD_RIGHT = 10;
+   public static final int FIELD_MIDDLE = 11;
+   public static final int FIELD_ONE = 12;
+   public static final int BUTTON_LEFT = 13;
+   public static final int BUTTON_RIGHT = 14;
+   public static final int BUTTON_MIDDLE = 15;
+   public static final int BUTTON_ONE = 16;
+   public static final int BUTTON_LEFT_UP = 17;
+   public static final int BUTTON_RIGHT_UP = 18;
+   public static final int BUTTON_MIDDLE_UP = 19;
+   public static final int BUTTON_ONE_UP = 20;
+   public static final int BUTTON_LEFT_DN = 21;
+   public static final int BUTTON_RIGHT_DN = 22;
+   public static final int BUTTON_MIDDLE_DN = 23;
+   public static final int BUTTON_ONE_DN = 24;
+   public static final int BUTTON_LEFT_EB = 25;
+   public static final int BUTTON_RIGHT_EB = 26;
+   public static final int BUTTON_MIDDLE_EB = 27;
+   public static final int BUTTON_SB_UP = 28;
+   public static final int BUTTON_SB_DN = 29;
+   public static final int BUTTON_SB_GUIDE = 30;
+   public static final int BUTTON_SB_THUMB = 31;
+   public static final int BUTTON_LAST = 31;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/Tn5250jEvent.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,62 @@
+/**Copyright (C) 2004 Seagull Software
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*
+*@author bvansomeren (bvansomeren@seagull.nl)
+*/
+package org.tn5250j.framework;
+
+//import org.tn5250j.Screen5250;
+import org.tn5250j.framework.tn5250.Screen5250;
+import org.tn5250j.framework.tn5250.ScreenFields;
+//import org.tn5250j.ScreenFields;
+
+public class Tn5250jEvent {
+
+	private Screen5250 screen;
+	private char[] data;
+	private ScreenFields fields;
+
+	public Tn5250jEvent() {
+		screen = null;
+	}
+
+	public Tn5250jEvent(Screen5250 newscreen) {
+		screen = newscreen;
+//		Object[] original = (Object[])screen.getCharacters();
+//		data = new ScreenChar[original.length];
+//		System.arraycopy(original, 0, data, 0, original.length);
+
+      // changed by Kenneth - This should be replaced with a call to
+      //   getPlane method of screen object when they are implemented.  These
+      //   new methods will also do the array copy.
+		char[] original = screen.getCharacters();
+		data = new char[original.length];
+		System.arraycopy(original, 0, data, 0, original.length);
+		this.fields = newscreen.getScreenFields();
+	}
+
+	public char[] getData() {
+		return data;
+	}
+
+	public Screen5250 getScreen() {
+		return screen;
+	}
+
+	public ScreenFields getFields() {
+		return this.fields;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/Tn5250jKeyEvents.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,36 @@
+/**Copyright (C) 2004 Seagull Software
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*
+*@author bvansomeren (bvansomeren@seagull.nl)
+*/
+package org.tn5250j.framework;
+
+//import org.tn5250j.Screen5250;
+import org.tn5250j.framework.tn5250.Screen5250;
+
+public class Tn5250jKeyEvents extends Tn5250jEvent {
+	private String keystrokes;
+
+	public Tn5250jKeyEvents(Screen5250 screen, String strokes) {
+		super(screen);
+		this.keystrokes = strokes;
+	}
+
+	public String getKeystrokes() {
+		return this.keystrokes;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/Tn5250jListener.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,38 @@
+/**Copyright (C) 2004 Seagull Software
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*
+*@author bvansomeren (bvansomeren@seagull.nl)
+*/
+package org.tn5250j.framework;
+
+import java.io.File;
+import java.util.Properties;
+
+public abstract class Tn5250jListener {
+	public abstract void actionPerformed(Tn5250jEvent event);
+	
+	public abstract void init(File fileDir, Properties config);
+	
+	public abstract void run();
+	
+	public abstract void destroy();
+	
+	public abstract String getName();
+	
+	public abstract void setController(Tn5250jController control);
+	
+	public abstract void sessionCreated(Tn5250jSession session);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/DataStreamProducer.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,353 @@
+package org.tn5250j.framework.tn5250;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.SocketException;
+import java.util.concurrent.BlockingQueue;
+
+import org.tn5250j.encoding.ICodePage;
+import org.tn5250j.tools.logging.TN5250jLogFactory;
+import org.tn5250j.tools.logging.TN5250jLogger;
+
+public class DataStreamProducer implements Runnable {
+
+   private BufferedInputStream bin;
+   private ByteArrayOutputStream baosin;
+   private Thread me;
+   private byte[] saveStream;
+   private final BlockingQueue<Object> dsq;
+   private tnvt vt;
+   private byte[] abyte2;
+   private FileOutputStream fw;
+   private BufferedOutputStream dw;
+   private boolean dumpBytes = false;
+   private ICodePage codePage;
+
+   private TN5250jLogger  log = TN5250jLogFactory.getLogger (this.getClass());
+
+   public DataStreamProducer(tnvt vt, BufferedInputStream in, BlockingQueue<Object> queue, byte[] init) {
+      bin = in;
+      this.vt = vt;
+      baosin = new ByteArrayOutputStream();
+      dsq = queue;
+      abyte2 = init;
+   }
+
+   public void setInputStream(ByteArrayOutputStream is) {
+
+      baosin = is;
+
+   }
+
+   public final void run() {
+
+      boolean done = false;
+
+      me = Thread.currentThread();
+
+      // load the first response screen
+      loadStream(abyte2, 0);
+      
+      while (!done) {
+		  try {
+
+			  byte[] abyte0 = readIncoming();
+
+			  // WVL - LDC : 17/05/2004 : Device name negotiations send TIMING MARK
+			  // Restructured to the readIncoming() method to return null
+			  // on TIMING MARK. Don't process in that case (abyte0 == null)!
+			  if (abyte0 != null)
+			  {
+				  // WVL - LDC : 16/07/2003 : TR.000345
+				  // When the socket has been closed, the reading returns
+				  // no bytes (an empty byte arrray).
+				  // But the loadStream fails on this, so we check it here!
+				  if (abyte0.length > 0)
+				  {
+					  loadStream(abyte0, 0);
+				  }
+				  // WVL - LDC : 16/07/2003 : TR.000345
+				  // Returning no bytes means the input buffer has
+				  // reached end-of-stream, so we do a disconnect!
+				  else
+				  {
+					  done = true;
+					  vt.disconnect();
+				  }
+			  }
+
+         }
+
+		 catch (SocketException se) {
+            log.warn("   DataStreamProducer thread interrupted and stopping " + se.getMessage());
+            done = true;
+         }
+
+         catch (IOException ioe) {
+
+		   log.warn(ioe.getMessage());
+           if (me.isInterrupted())
+              done = true;
+
+         }
+         catch (Exception ex) {
+
+           log.warn(ex.getMessage());
+           if (me.isInterrupted())
+              done = true;
+
+         }
+      }
+    }
+
+   private final void loadStream(byte abyte0[], int i) {
+
+      int j = 0;
+      int size = 0;
+      if (saveStream == null) {
+         j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff;
+         size = abyte0.length;
+      }
+      else {
+         size = saveStream.length + abyte0.length;
+         byte[] inter = new byte[size];
+         System.arraycopy(saveStream, 0, inter, 0, saveStream.length);
+         System.arraycopy(abyte0, 0, inter, saveStream.length, abyte0.length);
+         abyte0 = new byte[size];
+         System.arraycopy(inter, 0, abyte0, 0, size);
+         saveStream = null;
+         inter = null;
+         j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff;
+		 log.debug("partial stream found");
+      }
+
+      if (j > size) {
+         saveStream = new byte[abyte0.length];
+         System.arraycopy(abyte0, 0, saveStream, 0, abyte0.length);
+		 log.debug("partial stream saved");
+      }
+      else {
+         byte abyte1[];
+         try {
+            abyte1 = new byte[j + 2];
+
+            System.arraycopy(abyte0, i, abyte1, 0, j + 2);
+            dsq.put(abyte1);
+            if(abyte0.length > abyte1.length + i)
+                loadStream(abyte0, i + j + 2);
+         }
+         catch (Exception ex) {
+
+           log.warn("load stream error " + ex.getMessage());
+   //        ex.printStackTrace();
+   //        dump(abyte0);
+
+         }
+      }
+   }
+
+   public final byte[] readIncoming()
+        throws IOException {
+
+      boolean done = false;
+      boolean negotiate = false;
+
+      baosin.reset();
+      int j = -1;
+      int i = 0;
+      
+      while(!done) {
+         
+         i = bin.read();
+
+         // WVL - LDC : 16/07/2003 : TR.000345
+         // The inStream return -1 when end-of-stream is reached. This
+         // happens e.g. when the connection is closed from the AS/400.
+         // So we stop in this case!
+         // ==> an empty byte array is returned from this method.
+         if (i == -1) // nothing read!
+         {
+           done = true;
+            vt.disconnect();
+           continue;
+         }
+
+         // We use the values instead of the static values IAC and EOR
+         //    because they are defined as bytes.
+         //
+         // The > if(i != 255 || j != 255)  < is a hack for the double FF FF's
+         // that are being returned.  I do not know why this is like this and
+         // can not find any documentation for it.  It is also being returned
+         // on my Client Access tcp dump as well so they are handling it.
+         //
+         // my5250
+         // 0000:  00 50 DA 44 C8 45 42 00 00 00 00 24 08 00 45 00 .P.D.EB....$..E.
+         // 0010:  04 2A BC F9 00 00 40 06 D0 27 C1 A8 33 04 C1 A8 .*....@..'..3...
+         // 0020:  33 58 00 17 04 18 6F A2 83 CB 00 1E D1 BA 50 18 3X....o.......P.
+         // 0030:  20 00 8A 9A 00 00 03 FF FF 12 A0 00 00 04 00 00  ...............
+         // --------------------------- || || -------------------------------------
+         // 0040:  03 04 40 04 11 00 20 01 07 00 00 00 18 00 00 10 ..@... .........
+
+         if(j == 255 && i == 255) {
+            j = -1;
+            continue;
+         }
+        baosin.write(i);
+        // check for end of record EOR and IAC  - FFEF
+        if(j == 255 && i == 239)
+           done = true;
+
+        // This is to check for the TELNET TIMING MARK OPTION
+        // rfc860 explains this in more detail.  When we receive it
+        // we will negotiate with the server by sending a WONT'T TIMING-MARK
+        // This will let the server know that we processed the information
+        // and are just waiting for the user to enter some data so keep the
+        // socket alive.   This is more or less a AYT (ARE YOU THERE) or not.
+        if(i == 253 && j == 255) {
+           done = true;
+           negotiate = true;
+        }
+        j = i;
+     }
+
+     // after the initial negotiation we might get other options such as
+     //    timing marks ??????????????  do we ???????????? look at telnet spec
+     // yes we do. rfc860 explains about timing marks.
+
+     	 // WVL - LDC : 17/05/2004 : Device name negotiations send TIMING MARK
+     	 //                          to existing device!
+     	 // Handled incorrectly: we cannot continue processing the TIMING MARK DO
+     	 // after we have handled it in the vt.negotiate()
+     	 // We should not return the bytes;
+     	 // ==> restructured to return null after negotiation!
+     	 //     Impacts the run method! Added the null check.
+     	 byte[] rBytes = baosin.toByteArray();
+
+		 if (dumpBytes) {
+			dump(rBytes);
+		 }
+
+         if (negotiate) {
+            // get the negotiation option
+            baosin.write(bin.read());
+            vt.negotiate(rBytes);
+
+            return null;
+         }
+         return rBytes;
+	}
+
+   protected final void toggleDebug (ICodePage cp) {
+
+      if (codePage == null)
+         codePage = cp;
+
+      dumpBytes = !dumpBytes;
+      if (dumpBytes) {
+
+         try {
+            if (fw == null) {
+               fw = new FileOutputStream("log.txt");
+               dw = new BufferedOutputStream(fw);
+            }
+         }
+         catch (FileNotFoundException fnfe) {
+            log.warn(fnfe.getMessage());
+         }
+
+      }
+      else {
+
+         try {
+
+            if (dw != null)
+               dw.close();
+            if (fw != null)
+               fw.close();
+            dw = null;
+            fw = null;
+            codePage = null;
+         }
+         catch(IOException ioe) {
+
+            log.warn(ioe.getMessage());
+         }
+      }
+
+      log.info("Data Stream output is now " + dumpBytes);
+   }
+
+   public void dump (byte[] abyte0) {
+      try {
+
+         log.info("\n Buffer Dump of data from AS400: ");
+         dw.write("\r\n Buffer Dump of data from AS400: ".getBytes());
+
+         StringBuffer h = new StringBuffer();
+         for (int x = 0; x < abyte0.length; x++) {
+            if (x % 16 == 0) {
+               System.out.println("  " + h.toString());
+               dw.write(("  " + h.toString() + "\r\n").getBytes());
+
+               h.setLength(0);
+               h.append("+0000");
+               h.setLength(5 - Integer.toHexString(x).length());
+               h.append(Integer.toHexString(x).toUpperCase());
+
+               System.out.print(h.toString());
+               dw.write(h.toString().getBytes());
+
+               h.setLength(0);
+            }
+            char ac = codePage.ebcdic2uni(abyte0[x]);
+            if (ac < ' ')
+               h.append('.');
+            else
+               h.append(ac);
+            if (x % 4 == 0) {
+               System.out.print(" ");
+               dw.write((" ").getBytes());
+
+            }
+
+            if (Integer.toHexString(abyte0[x] & 0xff).length() == 1){
+               System.out.print("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase());
+               dw.write(("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes());
+
+            }
+            else {
+               System.out.print(Integer.toHexString(abyte0[x] & 0xff).toUpperCase());
+               dw.write((Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes());
+            }
+
+         }
+         System.out.println();
+         dw.write("\r\n".getBytes());
+
+         dw.flush();
+      }
+      catch(EOFException _ex) { }
+      catch(Exception _ex) {
+         log.warn("Cannot dump from host\n\r");
+      }
+
+   }
+
+//      public void dumpBytes() {
+//         byte shit[] = bk.buffer;
+//         for (int i = 0;i < shit.length;i++)
+//            System.out.println(i + ">" + shit[i] + "< - ascii - >" + getASCIIChar(shit[i]) + "<");
+//      }
+//
+//      public void dumpHexBytes(byte[] abyte) {
+//         byte shit[] = abyte;
+//         for (int i = 0;i < shit.length;i++)
+//            System.out.println(i + ">" + shit[i] + "< hex >" + Integer.toHexString((shit[i] & 0xff)));
+//      }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/KbdTypesCodePages.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,112 @@
+package org.tn5250j.framework.tn5250;
+
+/**
+ * IBM i 7.1 Information Center > Programmierung > i5/OS globalization > Globalization reference information > Keyboard reference information 
+ * 
+ * @see <a href="http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=/nls/rbagsnatlangkeybrdtype.htm">National language keyboard types and SBCS code pages</a>
+ */
+public enum KbdTypesCodePages {
+	
+	ALI("Albanian","ALI","697","500","500"),
+	CLB("Arabic","CLB","235","420","420"),
+	AGB("Austrian/ German","AGB","697","273","273"),
+	AGE("Austrian/ German","AGB","695","1141","1141"),
+	AGI("Austrian/German (MNCS)","AGI","697","500","500"),
+	BLI("Belgian MNCS","BLI","697","500","500"),
+	BRB("Brazilian Portuguese","BRB","697","37","37"),
+	BGB("Bulgarian","BGB","1150","1025","1025"),
+	CAB("Canadian French","CAB","341","260","65535"),
+	CAI("Canadian French MNCS","CAI","697","500","500"),
+//	YGI("Croatian","YGI","959","870","870"),
+	CYB("Cyrillic","CYB","960","880","880"),
+	CSB("Czech","CSB","959","870","870"),
+	DMB("Danish","DMB","697","277","277"),
+	DMI("Danish MNCS","DMI","697","500","500"),
+	FNB("Finnish/Swedish","FNB","697","278","278"),
+	FNI("Finnish/Swedish MNCS","FNI","697","500","500"),
+	FAB("French (Azerty)","FAB","697","297","297"),
+	FAI("French (Azerty) MNCS","FAI","697","500","500"),
+	FQB("French (Qwerty)","FQB","697","297","297"),
+	FQI("French (Qwerty) MNCS","FQI","697","500","500"),
+	GNB("Greek (See note 2.)","GNB","925","875","875"),
+	NCB("Hebrew","NCB","941","424","424"),
+	HNB("Hungarian","HNB","959","870","870"),
+	ICB("Icelandic","ICB","697","871","871"),
+	ICI("Icelandic MNCS","ICI","697","500","500"),
+	INB("International","INB","697","500","500"),
+	INBX("International-X","INB","697","500","500-ch"),
+//	INB("International MNCS","INB","697","500","500"),
+	IRB("Farsi (Iran)","IRB","1219","1097","1097"),
+	ITB("Italian","ITB","697","280","280"),
+	ITI("Italian MNCS","ITI","697","500","500"),
+	JEB("Japanese-English","JEB","697","281","65535"),
+	JEI("Japanese- English MNCS","JEI","697","500","500"),
+	JKB("Japanese Kanji and Katakana","JKB","1172","290","5026"),
+//	JUB("Japanese Kanji and US English","JUB","697","37","See note 3."),
+	KAB("Japanese Katakana","KAB","332","290","290"),
+	JPB("Japanese Latin Extended","JPB","1172","1027","1027"),
+	KOB("Korean","KOB","1173","833","833"),
+	ROB("Latin 2","ROB","959","870","870"),
+	MKB("Macedonian","MKB","1150","1025","1025"),
+	NEB("Dutch (Netherlands)","NEB","697","37","37"),
+	NEI("Dutch (Netherlands) MNCS","NEI","697","500","500"),
+	NWB("Norwegian","NWB","697","277","277"),
+	NWI("Norwegian MNCS","NWI","697","500","500"),
+	PLB("Polish","PLB","959","870","870"),
+	PLBX("Polish 870-pl","PLB","959","870","870-pl"), // Workaround, to catch up Java codepage '870-pl'
+	PRB("Portuguese","PRB","697","37","37"),
+	PRI("Portuguese MNCS","PRI","697","500","500"),
+	RMB("Romanian","RMB","959","870","870"),
+	RUB("Russian","RUB","1150","1025","1025"),
+	SQB("Serbian, Cyrillic","SQB","1150","1025","1025"),
+	YGI("Serbian, Latin","YGI","959","870","870"),
+	RCB("Simplified Chinese","RCB","1174","836","836"),
+	SKB("Slovakian","SKB","959","870","870"),
+	SKBX("Slovakian 870-sk","SKB","959","870","870-sk"), // Workaround, to catch up Java codepage '870-sk'
+//	YGI("Slovenian","YGI","959","870","870"),
+	SPB("Spanish","SPB","697","284","284"),
+	SPI("Spanish MNCS","SPI","697","500","500"),
+	SSB("Spanish Speaking","SSB","697","284","284"),
+	SSI("Spanish Speaking MNCS","SSI","697","500","500"),
+	SWB("Swedish","SWB","697","278","278"),
+	SWI("Swedish MNCS","SWI","697","500","500"),
+	SFI("French (Switzerland) MNCS","SFI","697","500","500"),
+	SGI("German (Switzerland) MNCS","SGI","697","500","500"),
+	THB("Thai","THB","1176","838","838"),
+	TAB("Traditional Chinese","TAB","1175","37","937"),
+	TKB("Turkish (Qwerty)","TKB","1152","1026","1026"),
+	TRB("Turkish (F)","TRB","1152","1026","1026"),
+	UKB("English (United Kingdom)","UKB","697","285","285"),
+	UKI("English (United Kingdom) MNCS","UKI","697","500","500"),
+	USB("English (United States and Canada)","USB","697","37","37"),
+	USI("English (United States and Canada) MNCS","USI","697","500","500");
+	
+	public final String description;
+	public final String kbdType;
+	public final String charset;
+	public final String codepage;
+	public final String ccsid;
+	
+	/**
+	 * @param description
+	 * @param kbdType
+	 * @param charset
+	 * @param codepage
+	 * @param ccsid
+	 */
+	private KbdTypesCodePages(String description, String kbdType, String charset, String codepage, String ccsid) {
+		this.description = description;
+		this.kbdType = kbdType;
+		this.charset = charset;
+		this.codepage = codepage;
+		this.ccsid = ccsid;
+	}
+
+	@Override
+	public String toString() {
+		return "[description=" + description + ", kbdType=" + kbdType
+		+ ", charset=" + charset + ", codepage=" + codepage
+		+ ", ccsid=" + ccsid + "]";
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/KeyStrokenizer.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,158 @@
+/*
+ * @(#)KeyStrokenizer.java
+ * Copyright:    Copyright (c) 2001
+ *
+ * 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 org.tn5250j.tools.logging.TN5250jLogFactory;
+import org.tn5250j.tools.logging.TN5250jLogger;
+
+
+public class KeyStrokenizer {
+
+   private StringBuffer keyStrokes;
+   private StringBuffer sb;
+   private int index;
+   private int length;
+	
+   private final TN5250jLogger log = TN5250jLogFactory.getLogger(this.getClass());
+   
+   public KeyStrokenizer() {
+
+      sb = new StringBuffer();
+      setKeyStrokes(null);
+   }
+
+   public void setKeyStrokes (String strokes) {
+
+      if (strokes != null) {
+         keyStrokes.setLength(0);
+		 log.debug("set "+ keyStrokes);
+         length = strokes.length();
+      }
+      else {
+
+         keyStrokes = new StringBuffer();
+         length = 0;
+
+      }
+      keyStrokes.append(strokes);
+      index = 0;
+
+   }
+
+   public boolean hasMoreKeyStrokes() {
+      return length > index;
+   }
+
+   public String nextKeyStroke() {
+
+      String s = "";
+      boolean gotOne = false;
+      if(length > index) {
+         sb.setLength(0);
+
+         char c = keyStrokes.charAt(index);
+         switch(c) {
+            case '[':
+               sb.append(c);
+               index++;
+
+               // we need to throw an error here
+               if(index >= length) {
+                  log.warn(" mnemonic key was incomplete :1 " +
+                                       "at position " + index + " len " + length );
+               }
+               else {
+                  c = keyStrokes.charAt(index);
+
+                  if(c == '[')
+                       index++;
+                  else {
+                     while(!gotOne) {
+
+                        if(c == ']') { // did we find an ending
+                           sb.append(c);
+                           index++;
+                           gotOne = true;
+                        }
+                        else {
+                           sb.append(c);
+                           index++;
+                           // we need to throw an error here because we did not
+                           //   find an ending for the potential mnemonic
+                           if(index >= length) {
+                              log.warn(
+                              " mnemonic key was incomplete ending not found :2 " +
+                                          "at position " + index);
+                           }
+                           c = keyStrokes.charAt(index);
+                        }
+                     }
+                  }
+               }
+               break;
+
+            case ']':
+               index++;
+               if(index >= length) {
+                  log.warn(
+                  " mnemonic key was incomplete ending not found :3 " +
+                              "at position " + index);
+                  sb.append(c);
+                  index++;
+
+               }
+               else {
+                  c = keyStrokes.charAt(index);
+                  if(c == ']') {
+                     sb.append(c);
+                     index++;
+                  }
+                  else {
+                     log.warn(
+                     " mnemonic key was incomplete beginning not found :4 " +
+                                 "at position " + index);
+                  }
+               }
+               break;
+            default:
+               sb.append(c);
+               index++;
+               break;
+         }
+         if(sb != null) {
+            s = new String(sb);
+         }
+
+      }
+	  log.debug("next "+ keyStrokes);
+
+      return s;
+   }
+
+   public String getUnprocessedKeyStroked() {
+      if(index >= length) {
+    	  return null;
+      }
+      return keyStrokes.substring(index);
+   }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/Rect.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,61 @@
+/**
+ * $Id: Rect.java 1092 2011-01-16 20:27:56Z master_jaf $
+ * 
+ * Title: tn5250J
+ * Copyright:   Copyright (c) 2001,2009
+ * Company:
+ * @author: master_jaf
+ *
+ * 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;
+
+
+/**
+ * Simplified rectangle class. Very much similar like java.awt.Rectangle,
+ * but we want to decouple the packages ...
+ */
+public class Rect {
+
+	/* default */ int x;
+	/* default */ int y;
+	/* default */ int height;
+	/* default */ int width;
+	
+	/**
+	 * @param rect
+	 */
+	public void setBounds(Rect rect) {
+		setBounds(rect.x, rect.y, rect.width, rect.height);
+	}
+	
+    /**
+     * @param x the new X coordinate for the upper-left corner of this rectangle
+     * @param y the new Y coordinate for the upper-left corner of this rectangle
+     * @param width the new width for this rectangle
+     * @param height the new height for this rectangle
+     */
+	public void setBounds(int x, int y, int width, int height) {
+		this.x = x;
+		this.y = y;
+		this.width = width;
+		this.height = height;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/Screen5250.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,3999 @@
+/**
+ * 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 org.tn5250j.event.ScreenListener;
+import org.tn5250j.tools.logging.TN5250jLogFactory;
+import org.tn5250j.tools.logging.TN5250jLogger;
+
+public class Screen5250 {
+
+	private ScreenFields screenFields;
+	private int lastAttr;
+	private int lastPos;
+	private int lenScreen;
+	private KeyStrokenizer strokenizer;
+	private tnvt sessionVT;
+	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_MANDITORY_ENTER = 0x21;
+
+	private boolean guiInterface = false;
+	private boolean resetRequired = true;
+	private boolean backspaceError = true;
+	private boolean feError;
+
+	// vector of listeners for changes to the screen.
+	Vector<ScreenListener> listeners = null;
+
+	// Operator Information Area
+	private ScreenOIA oia;
+
+	// screen planes
+	protected ScreenPlanes planes;
+
+	//Added by Barry
+	private StringBuffer keybuf;
+
+	private TN5250jLogger log = TN5250jLogFactory.getLogger(this.getClass());
+
+	public Screen5250() {
+
+		//Added by Barry
+		this.keybuf = new StringBuffer();
+
+		try {
+			jbInit();
+		} catch (Exception ex) {
+			log.warn("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.debug("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) {
+		if (log.isDebugEnabled()) {
+			log.debug("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.info("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.info("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.debug("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.warn(pe.getMessage() + " at "
+							+ pe.getErrorOffset());
+				}
+			}
+			sb.setLength(0);
+			m++;
+		}
+		log.debug("" + sum);
+		return sumVector;
+	}
+
+	/**
+	 * This will move the screen cursor based on the mouse event.
+	 *
+	 * I do not think the checks here for the gui characters should be here but
+	 * will leave them here for now until we work out the interaction.  This
+	 * should be up to the gui frontend in my opinion.
+	 *
+	 * @param pos
+	 */
+	public boolean moveCursor(int pos) {
+
+		if (!oia.isKeyBoardLocked()) {
+
+			if (pos < 0)
+				return false;
+			// because getRowColFromPoint returns offset of 1,1 we need to
+			//    translate to offset 0,0
+			//         pos -= (numCols + 1);
+
+			int g = planes.getWhichGUI(pos);
+
+			// lets check for hot spots
+			if (g >= BUTTON_LEFT && g <= BUTTON_LAST) {
+				StringBuffer aid = new StringBuffer();
+				boolean aidFlag = true;
+				switch (g) {
+				case BUTTON_RIGHT:
+				case BUTTON_MIDDLE:
+					while (planes.getWhichGUI(--pos) != BUTTON_LEFT) {
+					}
+				case BUTTON_LEFT:
+					if (planes.getChar(pos) == 'F') {
+						pos++;
+					} else
+						aidFlag = false;
+
+					if (planes.getChar(pos + 1) != '='
+						&& planes.getChar(pos + 1) != '.'
+							&& planes.getChar(pos + 1) != '/') {
+						//                     System.out.println(" Hotspot clicked!!! we will send
+						// characters " +
+						//                                    screen[pos].getChar() +
+						//                                    screen[pos+1].getChar());
+						aid.append(planes.getChar(pos));
+						aid.append(planes.getChar(pos + 1));
+					} else {
+						log.debug(" Hotspot clicked!!! we will send character "
+								+ planes.getChar(pos));
+						aid.append(planes.getChar(pos));
+					}
+					break;
+
+				}
+				if (aidFlag) {
+					switch (g) {
+
+					case BUTTON_LEFT_UP:
+					case BUTTON_MIDDLE_UP:
+					case BUTTON_RIGHT_UP:
+					case BUTTON_ONE_UP:
+					case BUTTON_SB_UP:
+					case BUTTON_SB_GUIDE:
+						sessionVT.sendAidKey(AID_ROLL_UP);
+						break;
+
+					case BUTTON_LEFT_DN:
+					case BUTTON_MIDDLE_DN:
+					case BUTTON_RIGHT_DN:
+					case BUTTON_ONE_DN:
+					case BUTTON_SB_DN:
+					case BUTTON_SB_THUMB:
+
+						sessionVT.sendAidKey(AID_ROLL_DOWN);
+						break;
+					case BUTTON_LEFT_EB:
+					case BUTTON_MIDDLE_EB:
+					case BUTTON_RIGHT_EB:
+						StringBuffer eb = new StringBuffer();
+						while (planes.getWhichGUI(pos--) != BUTTON_LEFT_EB)
+							;
+						while (planes.getWhichGUI(pos++) != BUTTON_RIGHT_EB) {
+							eb.append(planes.getChar(pos));
+						}
+						org.tn5250j.tools.system.OperatingSystem.displayURL(eb
+								.toString());
+						// take out the log statement when we are sure it is
+						// working
+						log.info("Send to external Browser: " + eb.toString());
+						break;
+
+					default:
+						int aidKey = Integer.parseInt(aid.toString());
+						if (aidKey >= 1 && aidKey <= 12)
+							sessionVT.sendAidKey(0x30 + aidKey);
+						if (aidKey >= 13 && aidKey <= 24)
+							sessionVT.sendAidKey(0xB0 + (aidKey - 12));
+					}
+				} else {
+					if (screenFields.getCurrentField() != null) {
+						int xPos = screenFields.getCurrentField().startPos();
+						for (int x = 0; x < aid.length(); x++) {
+							//                  System.out.println(sr + "," + (sc + x) + " " +
+							// aid.charAt(x));
+							planes.setChar(xPos + x , aid.charAt(x));
+						}
+						//                  System.out.println(aid);
+						screenFields.setCurrentFieldMDT();
+						sessionVT.sendAidKey(AID_ENTER);
+					}
+
+				}
+				// return back to the calling routine that the cursor was not moved
+				// but something else here was done like aid keys or the such
+				return false;
+			}
+			// this is a note to not execute this code here when we
+			// implement
+			//   the remain after edit function option.
+			//				if (gui.rubberband.isAreaSelected()) {
+			//					gui.rubberband.reset();
+			//					gui.repaint();
+			//				} else {
+			goto_XY(pos);
+			isInField(lastPos);
+
+			// return back to the calling object that the cursor was indeed
+			//  moved with in the screen object
+			return true;
+			//				}
+		}
+		return false;
+	}
+
+	public void setVT(tnvt v) {
+
+		sessionVT = v;
+	}
+
+	/**
+	 * Searches the mnemonicData array looking for the specified string. If it
+	 * is found it will return the value associated from the mnemonicValue
+	 *
+	 * @see #sendKeys
+	 * @param mnem
+	 *            string mnemonic value
+	 * @return key value of Mnemonic
+	 */
+	private int getMnemonicValue(String mnem) {
+
+		for (int x = 0; x < mnemonicData.length; x++) {
+
+			if (mnemonicData[x].equals(mnem))
+				return mnemonicValue[x];
+		}
+		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(3);
+
+		}
+	}
+
+	//Added by Barry
+	public String getKeys() {
+		String result = this.keybuf.toString();
+		this.keybuf = new StringBuffer();
+		return result;
+	}
+
+	/**
+	 * 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
+	 *
+	 * Added synchronized to fix a StringOutOfBounds error - Luc Gorren LDC
+	 */
+	public synchronized void sendKeys(String text) {
+
+		//      if (text == null) {
+		//         return;
+		//      }
+		this.keybuf.append(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;
+					return;
+				}
+				bufferedKeys += text;
+				return;
+			}
+
+		} else {
+
+			if (oia.isKeysBuffered()) {
+				if (bufferedKeys != null) {
+					text = bufferedKeys + text;
+				}
+				//            if (text.length() == 0) {
+				oia.setKeysBuffered(false);
+				//            }
+				bufferedKeys = null;
+
+			}
+			// check to see if position is in a field and if it is then change
+			//   current field to that field
+			isInField(lastPos, true);
+			if (text.length() == 1 && !text.equals("[") && !text.equals("]")) {
+				//               setCursorOff2();
+				setCursorActive(false);
+				simulateKeyStroke(text.charAt(0));
+				setCursorActive(true);
+				//               setCursorOn2();
+				//                     System.out.println(" text one");
+
+			} else {
+
+				strokenizer.setKeyStrokes(text);
+				String s;
+				boolean done = false;
+
+				//            setCursorOff2();
+				setCursorActive(false);
+				while (!done) {
+					//            while (strokenizer.hasMoreKeyStrokes() && !keyboardLocked
+					// &&
+					//                        !isStatusErrorCode() && !done) {
+					if (strokenizer.hasMoreKeyStrokes()) {
+
+						// check to see if position is in a field and if it is
+						// then change
+						//   current field to that field
+						isInField(lastPos, true);
+						s = strokenizer.nextKeyStroke();
+						if (s.length() == 1) {
+							//                  setCursorOn();
+							//                  if (!keysBuffered) {
+							//                     System.out.println(" s two" + s);
+							//                     setCursorOn();
+							//                  }
+
+							//                  try { new Thread().sleep(400);} catch
+							// (InterruptedException ie) {}
+							simulateKeyStroke(s.charAt(0));
+							//                     System.out.println(" s two " + s + " " +
+							// cursorActive);
+							//                  if (cursorActive && !keysBuffered) {
+							//                     System.out.println(" s two" + s);
+							//                     setCursorOn();
+							//                  }
+						} else {
+							simulateMnemonic(getMnemonicValue(s));
+							//                  if (!cursorActive && !keysBuffered) {
+							//                     System.out.println(" m one");
+							//                     setCursorOn();
+							//                  }
+						}
+
+						if (oia.isKeyBoardLocked()) {
+
+							bufferedKeys = strokenizer
+							.getUnprocessedKeyStroked();
+							if (bufferedKeys != null) {
+								oia.setKeysBuffered(true);
+
+							}
+							done = true;
+						}
+
+					}
+
+					else {
+						//                  setCursorActive(true);
+						//                  setCursorOn();
+						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(lastPos);
+			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(lastPos);
+			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);
+				// now check if we are in a field
+				isInField(lastPos);
+			} 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(lastPos);
+				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.info(" 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(1);
+
+					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_MANDITORY_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.setManditoryEntered();
+				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_MANDITORY_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 whole screen represented as a character array
+	 *
+	 * @return character array containing the text
+	 *
+	 * Added by Luc - LDC
+	 *
+	 * Note to KJP - Have to ask what the difference is between this method and
+	 * the other
+	 */
+	public char[] getScreenAsAllChars() {
+		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;
+	}
+
+	/**
+	 *
+	 * 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(1);
+		}
+
+	}
+
+	/**
+	 * 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) {
+		//      setCursorOff();
+		updateCursorLoc();
+		lastPos = pos;
+		//      setCursorOn();
+		updateCursorLoc();
+	}
+
+	/**
+	 * 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.warn(" 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.info(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(1);
+
+	}
+
+	/**
+	 * 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(1);
+
+	}
+
+	public boolean checkHotSpots() {
+
+		return planes.checkHotSpots();
+	}
+
+	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(1);
+
+	}
+
+	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);
+
+	}
+
+	/* *** NEVER USED LOCALLY ************************************************** */
+	//	private void setDirty(int row, int col) {
+	//
+	//		setDirty(getPos(row, col));
+	//
+	//	}
+
+	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;
+		if (lastPos < 0)
+			lastPos = lenScreen + lastPos;
+		if (lastPos > lenScreen - 1)
+			lastPos = lastPos - lenScreen;
+
+		//      System.out.println(lastRow + "," + ((lastPos) / numCols) + "," +
+		//                         lastCol + "," + ((lastPos) % numCols) + "," +
+		//                         ((lastRow * numCols) + lastCol) + "," +
+		//                         (lastPos));
+
+	}
+
+	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(); // we now check if we are in a field
+		} else {
+			if (!gotoField(1)) {
+				homePos = getPos(1, 1);
+				setCursor(1, 1);
+				isInField(0, 0); // we now check if we are in a field
+			} 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(1,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();
+	}
+
+	/**
+	 * Notify all registered listeners of the onScreenChanged event.
+	 *
+	 */
+	private void fireScreenChanged(int which, int startRow, int startCol,
+			int endRow, int endCol) {
+		if (listeners != null) {
+			// Patch below contributed by Mitch Blevins
+			//int size = listeners.size();
+			Vector<ScreenListener> lc = new Vector<ScreenListener>(listeners);
+			int size = lc.size();
+			for (int i = 0; i < size; i++) {
+				//ScreenListener target =
+				//      (ScreenListener)listeners.elementAt(i);
+				ScreenListener target = lc.elementAt(i);
+				target.onScreenChanged(1,startRow,startCol,endRow,endCol);
+			}
+		}
+		dirtyScreen.setBounds(lenScreen,0,0,0);
+	}
+
+	/**
+	 * Notify all registered listeners of the onScreenChanged event.
+	 *
+	 */
+	private synchronized void fireScreenChanged(int update) {
+		if (dirtyScreen.x > dirtyScreen.y) {
+			//         log.info(" x < y " + dirtyScreen);
+			return;
+		}
+
+		fireScreenChanged(update, getRow(dirtyScreen.x), getCol(dirtyScreen.x),
+				getRow(dirtyScreen.y), getCol(dirtyScreen.y));
+
+	}
+
+	/**
+	 * Notify all registered listeners of the onScreenChanged event.
+	 *
+	 */
+	private synchronized void fireCursorChanged(int update) {
+		int startRow = getRow(lastPos);
+		int startCol = getCol(lastPos);
+
+		if (listeners != null) {
+			Vector<ScreenListener> lc = new Vector<ScreenListener>(listeners);
+			//int size = listeners.size();
+			int size = lc.size();
+			for (int i = 0; i < size; i++) {
+				ScreenListener target =
+					lc.elementAt(i);
+				target.onScreenChanged(update,startRow,startCol,startRow,startCol);
+			}
+		}
+	}
+
+	/**
+	 * Notify all registered listeners of the onScreenSizeChanged event.
+	 *
+	 */
+	private void fireScreenSizeChanged() {
+
+		if (listeners != null) {
+			Vector<ScreenListener> lc = new Vector<ScreenListener>(listeners);
+			//int size = listeners.size();
+			int size = lc.size();
+			for (int i = 0; i < size; i++) {
+				ScreenListener target =
+					lc.elementAt(i);
+				target.onScreenSizeChanged(numRows,numCols);
+			}
+		}
+	}
+
+	/**
+	 * This method does a complete refresh of the screen.
+	 */
+	public final void updateScreen() {
+		repaintScreen();
+		setCursorActive(false);
+		setCursorActive(true);
+	}
+
+	/**
+	 * Add a ScreenListener to the listener list.
+	 *
+	 * @param listener  The ScreenListener to be added
+	 */
+	public void addScreenListener(ScreenListener listener) {
+
+		if (listeners == null) {
+			listeners = new java.util.Vector<ScreenListener>(3);
+		}
+		listeners.addElement(listener);
+
+	}
+
+	/**
+	 * Remove a ScreenListener from the listener list.
+	 *
+	 * @param listener  The ScreenListener to be removed
+	 */
+	public void removeScreenListener(ScreenListener listener) {
+
+		if (listeners == null) {
+			return;
+		}
+		listeners.removeElement(listener);
+	}
+
+	/**
+	 * 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;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/ScreenField.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,606 @@
+/**
+ * Title: tn5250J
+ * Copyright:   Copyright (c) 2001
+ * Company:
+ * @author  Kenneth J. Pouncey
+ * @version 0.4
+ *
+ * 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;
+
+public class ScreenField {
+
+   protected ScreenField(Screen5250 s) {
+
+      this.s = s;
+
+   }
+
+   protected ScreenField setField(int attr, int len, int ffw1, int ffw2,
+                     int fcw1, int fcw2) {
+
+      return setField(attr,
+               s.getCurrentRow() - 1,
+               s.getCurrentCol() - 1,
+               len,
+               ffw1,
+               ffw2,
+               fcw1,
+               fcw2);
+   }
+
+   protected ScreenField setField(int attr, int row, int col, int len, int ffw1, int ffw2,
+                     int fcw1, int fcw2) {
+
+//      startRow = row;
+//      startCol = col;
+      startPos = (row * s.getColumns()) + col;
+      endPos = startPos + length -1;
+      cursorProg = 0;
+      fieldId = 0;
+      length = len;
+      endPos = startPos + length -1;
+      this.attr = attr;
+      setFFWs(ffw1,ffw2);
+      setFCWs(fcw1,fcw2);
+
+      next = null;
+      prev = null;
+
+      return this;
+
+   }
+
+   public int getAttr(){
+      return attr;
+   }
+
+   public int getHighlightedAttr(){
+      return (fcw2 & 0x0f) | 0x20;
+   }
+
+   public int getLength(){
+      return length;
+   }
+
+   protected boolean setFFWs(int ffw1, int ffw2) {
+
+      this.ffw1 = ffw1;
+      this.ffw2 = ffw2;
+
+      int adj = getAdjustment();
+
+      if (adj  > 0) {
+         checkCanSend = true;
+
+         switch (adj) {
+
+            case 5:
+            case 6:
+               rightAdjd = false;
+               break;
+            case 7:
+               manditoried = false;
+               break;
+         }
+
+      }
+      mdt = (ffw1 & 0x8 ) == 0x8;
+//      if (mdt)
+//         s.masterMDT = true;
+      return mdt;
+   }
+
+
+   public int getFFW1(){
+      return ffw1;
+   }
+   public int getFFW2(){
+      return ffw2;
+   }
+
+   protected void setFCWs(int fcw1, int fcw2) {
+
+      this.fcw1 = fcw1;
+      this.fcw2 = fcw2;
+
+//      if ((fcw1 & 0x88) == 0x88) {
+      if (fcw1 == 0x88) {
+
+         cursorProg = fcw2;
+      }
+   }
+
+   public int getFCW1(){
+      return fcw1;
+   }
+
+   public int getFCW2(){
+      return fcw2;
+   }
+
+   public int getFieldLength(){
+      return length;
+   }
+
+   public int getCursorProgression() {
+      return cursorProg;
+   }
+
+   public int getFieldId() {
+      return fieldId;
+   }
+
+   protected void setFieldId(int fi) {
+      fieldId = fi;
+   }
+
+   public int getCursorRow() {
+
+      return cursorPos / s.getColumns();
+   }
+
+   public int getCursorCol() {
+
+      return cursorPos % s.getColumns();
+   }
+
+   protected void changePos(int i) {
+
+      cursorPos += i;
+
+   }
+
+   protected String getText() {
+
+
+      StringBuffer text = new StringBuffer();
+      getKeyPos(endPos);
+      int x = length;
+      text.setLength(x);
+      while (x-- > 0) {
+
+         // here we manipulate the unicode characters a little for attributes
+         //    that are imbedded in input fields.  We will offset them by unicode
+         //    \uff00.   All routines that process these fields will have to
+         //    return them to their proper offsets.
+         //    example:
+         //    if we read an attribute byte of 32 for normal display the unicode
+         //       character for this is \u0020 and the unicode character for
+         //       a space is also \u0020 thus the offset.
+         if (s.planes.isAttributePlace(cursorPos)) {
+            text.setCharAt(x,(char)('\uff00' + s.planes.getCharAttr(cursorPos)));
+         }
+         else {
+            text.setCharAt(x,s.planes.getChar(cursorPos));
+         }
+         changePos(-1);
+
+      }
+
+      // Since only the mdt of the first continued field is set we will get
+      //    the text of the next continued field if we are dealing with continued
+      //    fields.  See routine setMDT for the whys of this.  This is only
+      //    executed if this is the first field of a continued field.
+      if (isContinued() && isContinuedFirst()) {
+         ScreenField sf = this;
+         do {
+            sf = sf.next;
+            text.append(sf.getText());
+         }
+         while (!sf.isContinuedLast());
+
+         sf = null;
+      }
+
+      return text.toString();
+
+   }
+
+   public String getString() {
+
+
+      StringBuffer text = new StringBuffer();
+      getKeyPos(endPos);
+      int x = length;
+      text.setLength(x);
+      while (x-- > 0) {
+
+         // here we manipulate the unicode characters a little for attributes
+         //    that are imbedded in input fields.  We will offset them by unicode
+         //    \uff00.   All routines that process these fields will have to
+         //    return them to their proper offsets.
+         //    example:
+         //    if we read an attribute byte of 32 for normal display the unicode
+         //       character for this is \u0020 and the unicode character for
+         //       a space is also \u0020 thus the offset.
+         if (s.planes.isAttributePlace(cursorPos)) {
+            text.setCharAt(x,(char)('\uff00' + s.planes.getCharAttr(cursorPos)));
+         }
+         else {
+            if (s.planes.getChar(cursorPos) < ' ')
+               text.setCharAt(x,' ');
+            else
+               text.setCharAt(x,s.planes.getChar(cursorPos));
+         }
+         changePos(-1);
+
+      }
+
+      // Since only the mdt of the first continued field is set we will get
+      //    the text of the next continued field if we are dealing with continued
+      //    fields.  See routine setMDT for the whys of this.  This is only
+      //    executed if this is the first field of a continued field.
+      if (isContinued() && isContinuedFirst()) {
+         ScreenField sf = this;
+         do {
+            sf = sf.next;
+            text.append(sf.getString());
+         }
+         while (!sf.isContinuedLast());
+
+         sf = null;
+      }
+
+      return text.toString();
+
+   }
+
+   public void setFieldChar(char c) {
+
+      int x = length;
+      cursorPos = startPos;
+      while (x-- > 0) {
+         s.planes.setChar(cursorPos,c);
+         changePos(1);
+      }
+
+   }
+
+   public void setFieldChar(int lastPos, char c) {
+
+      int x = endPos - lastPos + 1;
+      cursorPos = lastPos;
+      while (x-- > 0) {
+         s.planes.setChar(cursorPos,c);
+         s.setDirty(cursorPos);
+         changePos(1);
+      }
+   }
+
+   protected void setRightAdjusted() {
+      rightAdjd = true;
+   }
+
+   protected void setManditoryEntered() {
+
+      manditoried = true;
+   }
+
+   protected void resetMDT() {
+      mdt = false;
+
+   }
+
+   protected void setMDT() {
+
+      //  get the first field of a continued edit field if it is continued
+      if (isContinued() && !isContinuedFirst()) {
+         ScreenField sf = prev;
+         while (sf.isContinued() && !sf.isContinuedFirst()) {
+
+            sf = sf.prev;
+
+         }
+         sf.setMDT();
+         sf = null;
+      }
+      else {
+         mdt = true;
+      }
+
+   }
+
+   public boolean isBypassField() {
+
+      return (ffw1 & 0x20) == 0x20;
+
+   }
+
+   public int getAdjustment () {
+
+      return (ffw2 & 0x7);
+   }
+
+   // is field exit required
+   public boolean isFER () {
+
+      return (ffw2 & 0x40) == 0x40;
+   }
+
+   // is field manditory enter
+   public boolean isMandatoryEnter() {
+
+      return (ffw2 & 0x8) == 0x8;
+
+   }
+
+   public boolean isToUpper() {
+
+      return (ffw2 & 0x20) == 0x20;
+
+   }
+
+   // bits 5 - 7
+   public int getFieldShift () {
+
+      return (ffw1 & 0x7);
+
+   }
+
+   public boolean isHiglightedEntry() {
+
+      return (fcw1 == 0x89);
+
+   }
+
+   public boolean isAutoEnter() {
+
+      return (ffw2 & 0x80) == 0x80;
+
+   }
+
+   public boolean isSignedNumeric () {
+
+      return (getFieldShift() == 7);
+
+   }
+   
+   public boolean isRightToLeft() {
+	   return (getFieldShift() == 0x04);
+   }
+
+   public boolean isNumeric () {
+
+      return (getFieldShift() == 3);
+
+   }
+
+   public boolean isDupEnabled() {
+
+      return (ffw1 & 0x10) == 0x10;
+
+   }
+
+   public boolean isContinued() {
+
+      return (fcw1 & 0x86) == 0x86 && (fcw2 >= 1 && fcw2 <= 3) ;
+
+   }
+
+   public boolean isContinuedFirst() {
+
+      return (fcw1 & 0x86) == 0x86 && (fcw2 == 1);
+
+   }
+
+   public boolean isContinuedMiddle() {
+
+      return (fcw1 & 0x86) == 0x86 && (fcw2 == 3);
+
+   }
+
+   public boolean isContinuedLast() {
+
+      return (fcw1 & 0x86) == 0x86 && (fcw2 == 2);
+
+   }
+
+   protected boolean isCanSend() {
+
+      int adj = getAdjustment();
+
+      // here we need to check the Field Exit Required value first before checking
+      //   the adjustments.  If the last character has been entered and we are
+      //   now setting past the last position then we are allowed to process the
+      //   the field without continuing.
+      if (isFER() && cursorPos > endPos) {
+         return true;
+      }
+
+      // signed numeric fields need to be checked as well.
+      if (isSignedNumeric() && cursorPos < endPos - 1) {
+         return false;
+      }
+
+      if (adj  > 0) {
+
+         switch (adj) {
+
+            case 5:
+            case 6:
+               return rightAdjd;
+            case 7:
+               return manditoried;
+            default:
+               return true;
+         }
+
+      }
+      return true;
+   }
+
+   public boolean isSelectionField() {
+
+      return isSelectionField;
+
+   }
+
+   public void setSelectionFieldInfo(int type, int index, int position) {
+
+      selectionFieldType = type;
+      selectionIndex = index;
+      selectionPos = position;
+      isSelectionField = true;
+
+   }
+
+   protected int getKeyPos(int row1, int col1) {
+
+      int x = ((row1 * s.getColumns()) + col1);
+      int y = x - startPos();
+      cursorPos = x;
+
+      return y;
+   }
+
+   protected int getKeyPos(int pos) {
+
+      int y = pos - startPos();
+      cursorPos = pos;
+
+      return y;
+   }
+
+   public int getCurrentPos() {
+
+      return cursorPos;
+   }
+
+   public boolean withinField (int pos) {
+
+      if (pos >= startPos && pos <= endPos)
+            return true;
+      return false;
+
+   }
+
+   public int startPos() {
+
+      return startPos;
+   }
+
+   /**
+    * Get the starting row of the field.  Offset is 0 so row 6 returned
+    *    is row 7 mapped to screen
+    * @return int starting row of the field offset 0
+    */
+   public int startRow() {
+
+      return startPos / s.getColumns();
+
+   }
+
+   /**
+    * Get the starting column of the field.  Offset is 0 so column 6 returned
+    *    is column 7 mapped to screen
+    * @return int starting column of the field offset 0
+    */
+   public int startCol() {
+
+      return startPos % s.getColumns();
+
+   }
+
+   public int endPos() {
+
+      return endPos;
+
+   }
+
+   /**
+    * Sets the field's text plane to the specified string. If the string is
+    * shorter than the length of the field, the rest of the field is cleared.
+    * If the string is longer than the field, the text is truncated. A subsequent
+    * call to getText on this field will not show the changed text. To see the
+    * changed text, do a refresh on the iOhioFields collection and retrieve the
+    * refreshed field object.
+    *
+    * @param text - The text to be placed in the field's text plane.
+    */
+   public void setString(String text) {
+
+      int y = length;
+      cursorPos = startPos;
+      int len = text.length();
+      char[] c = text.toCharArray();
+      char tc = ' ';
+
+      for (int x = 0; x < y; x++) {
+         tc = ' ';
+         if (x < len) {
+            tc = c[x];
+         }
+         s.getPlanes().setChar(cursorPos,tc);
+         changePos(1);
+      }
+      setMDT();
+      s.getScreenFields().setMasterMDT();
+   }
+
+   public String toString() {
+      int fcw = (fcw1 & 0xff) << 8 | fcw2 & 0xff;
+      return "startRow = " + startRow() + " startCol = " + startCol() +
+            " length = " + length + " ffw1 = (0x" + Integer.toHexString(ffw1) +
+            ") ffw2 = (0x" + Integer.toHexString(ffw2) +
+            ") fcw1 = (0x" + Integer.toHexString(fcw1) +
+            ") fcw2 = (0x" + Integer.toHexString(fcw2) +
+            ") fcw = (" + Integer.toBinaryString(fcw) +
+            ") fcw hex = (0x" + Integer.toHexString(fcw) +
+            ") is bypass field = " + isBypassField() +
+            ") is autoenter = " + isAutoEnter() +
+            ") is manditoryenter = " + isMandatoryEnter() +
+            ") is field exit required = " + isFER() +
+            ") is Numeric = " + isNumeric() +
+            ") is Signed Numeric = " + isSignedNumeric() +
+            ") is cursor progression = " + (fcw1 == 0x88) +
+            ") next progression field = " + fcw2 +
+            ") field id " + fieldId +
+            " continued edit field = " + isContinued() +
+            " first continued edit field = " + isContinuedFirst() +
+            " middle continued edit field = " + isContinuedMiddle() +
+            " last continued edit field = " + isContinuedLast() +
+            " mdt = " + mdt;
+   }
+
+   int startPos = 0;
+   int endPos = 0;
+   boolean mdt = false;
+   protected boolean checkCanSend;
+   protected boolean rightAdjd;
+   protected boolean manditoried;
+   boolean canSend = true;
+   int attr = 0;
+   int length = 0;
+   int ffw1 = 0;
+   int ffw2 = 0;
+   int fcw1 = 0;
+   int fcw2 = 0;
+   int cursorPos = 0;
+   Screen5250 s;
+   int cursorProg = 0;
+   int fieldId = 0;
+   ScreenField next = null;
+   ScreenField prev = null;
+   boolean isSelectionField;
+   int selectionFieldType;
+   int selectionIndex;
+   int selectionPos;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/ScreenFields.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,724 @@
+/**
+ * Title: tn5250J
+ * Copyright:   Copyright (c) 2001
+ * 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.CMD_READ_INPUT_FIELDS;
+import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_FIELDS;
+import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_IMMEDIATE_ALT;
+
+import java.io.ByteArrayOutputStream;
+
+import org.tn5250j.encoding.ICodePage;
+
+public class ScreenFields {
+
+   private ScreenField[] screenFields;
+   private ScreenField currentField;
+   private ScreenField saveCurrent;
+   private int sizeFields;
+   private boolean cpfExists;
+   private int nextField;
+   private int fieldIds;
+   private Screen5250 screen;
+   private boolean masterMDT;
+   protected boolean currentModified;
+
+   public ScreenFields(Screen5250 s) {
+
+      screen = s;
+      screenFields = new ScreenField[256];
+   }
+
+   protected void clearFFT() {
+
+      sizeFields = nextField = fieldIds = 0;
+      cpfExists = false;   // clear the cursor progression fields flag
+      currentField = null;
+      masterMDT = false;
+
+   }
+
+   protected boolean existsAtPos(int lastPos) {
+
+      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()) {
+            currentField = sf;
+            currentModified = false;
+            return true;
+         }
+
+      }
+
+      return false;
+   }
+
+   public boolean isMasterMDT() {
+      return masterMDT;
+   }
+
+   protected void setMasterMDT() {
+      masterMDT = true;
+   }
+
+   public boolean isCurrentField() {
+      return currentField == null;
+   }
+
+   public boolean isCurrentFieldFER() {
+      return currentField.isFER();
+   }
+
+   public boolean isCurrentFieldDupEnabled() {
+      return currentField.isDupEnabled();
+   }
+
+   public boolean isCurrentFieldToUpper() {
+      return currentField.isToUpper();
+   }
+
+   public boolean isCurrentFieldBypassField() {
+      return currentField.isBypassField();
+   }
+
+   public boolean isCurrentFieldHighlightedEntry() {
+      if (currentField != null)
+         return currentField.isHiglightedEntry();
+      else
+         return false;
+   }
+
+   public boolean isCurrentFieldAutoEnter() {
+      return currentField.isAutoEnter();
+   }
+
+   public boolean withinCurrentField(int pos) {
+      return currentField.withinField(pos);
+   }
+
+   public boolean isCurrentFieldContinued() {
+      return currentField.isContinued();
+   }
+
+   public boolean isCurrentFieldContinuedFirst() {
+      return currentField.isContinuedFirst();
+   }
+
+   public boolean isCurrentFieldContinuedMiddle() {
+      return currentField.isContinuedMiddle();
+   }
+
+   public boolean isCurrentFieldContinuedLast() {
+      return currentField.isContinuedLast();
+   }
+
+   public boolean isCurrentFieldModified() {
+      return currentModified;
+   }
+
+   /**
+    * This routine is used to check if we can send the Aid key to the host
+    *
+    * Taken from Section  16.2.1.2 Enter/Rec Adv Key
+    *
+    * In the normal unlocked state, when the workstation operator presses the
+    * Enter/Rec Adv key:
+    *
+    * 1. The 5494 checks for the completion of mandatory-fill, self-check, and
+    *    right-adjust fields when in an active field. (An active field is one in
+    *    which the workstation operator has begun entering data.) If the
+    *    requirements of the field have not been satisfied, an error occurs.
+    *
+    * @return
+    *
+    */
+   public boolean isCanSendAid() {
+
+      // We also have to check if we are still in the field.
+      if (currentField != null &&
+            (currentField.getAdjustment() > 0 || currentField.isSignedNumeric())
+             && currentModified && isInField()
+            && !currentField.isCanSend())
+
+         return false;
+      else
+         return true;
+
+   }
+
+   protected void saveCurrentField() {
+      saveCurrent = currentField;
+   }
+
+   protected void restoreCurrentField() {
+      currentField = saveCurrent;
+   }
+
+   protected void setCurrentField(ScreenField sf) {
+      currentField = sf;
+   }
+
+   protected void setCurrentFieldMDT() {
+      currentField.setMDT();
+      currentModified = true;
+      masterMDT = true;
+   }
+
+   protected void setCurrentFieldFFWs(int ffw1, int ffw2) {
+
+      masterMDT = currentField.setFFWs(ffw1,ffw2);
+
+   }
+
+
+   protected ScreenField setField(int attr, int row, int col, int len, int ffw1,
+                           int ffw2, int fcw1, int fcw2) {
+
+      ScreenField sf = null;
+      screenFields[nextField] = new ScreenField(screen);
+      screenFields[nextField].setField(attr,row,col,len,ffw1,ffw2,fcw1,fcw2);
+      sf = screenFields[nextField++];
+
+      sizeFields++;
+
+
+      // set the field id if it is not a bypass field
+      // this is used for cursor progression
+      //  changed this because of problems not allocating field id's for
+      //  all fields.  kjp 2002/10/21
+//      if (!sf.isBypassField())
+      sf.setFieldId(++fieldIds);
+
+      // check if the cursor progression field flag should be set.
+//      if ((fcw1 & 0x88) == 0x88)
+      if (fcw1 == 0x88)
+         cpfExists = true;
+
+      if (currentField != null) {
+         currentField.next = sf;
+         sf.prev = currentField;
+      }
+
+      currentField = sf;
+
+      // check if the Modified Data Tag was set while creating the field
+      if (!masterMDT)
+         masterMDT = currentField.mdt;
+
+      currentModified = false;
+
+      return currentField;
+
+   }
+
+   public ScreenField getField(int index) {
+
+      return screenFields[index];
+   }
+
+   public ScreenField getCurrentField() {
+      return currentField;
+   }
+
+   public int getCurrentFieldPos() {
+      return currentField.getCurrentPos();
+   }
+
+   protected int getCurrentFieldShift() {
+      return currentField.getFieldShift();
+   }
+
+   public String getCurrentFieldText() {
+
+      return currentField.getText();
+   }
+
+   public int getCurrentFieldHighlightedAttr(){
+      return currentField.getHighlightedAttr();
+   }
+
+   public int getSize() {
+
+      return sizeFields;
+   }
+
+   public int getFieldCount() {
+
+      return sizeFields;
+   }
+
+   protected boolean isInField(int pos) {
+      return isInField(pos,true);
+   }
+
+   protected boolean isInField() {
+      return isInField(screen.getLastPos(),true);
+   }
+
+   protected boolean isInField(int pos, boolean chgToField) {
+
+      ScreenField sf;
+
+      for (int x = 0;x < sizeFields; x++) {
+         sf = screenFields[x];
+
+         if (sf.withinField(pos)) {
+
+            if (chgToField) {
+               if (!currentField.equals(sf))
+                  currentModified = false;
+               currentField = sf;
+            }
+            return true;
+         }
+      }
+      return false;
+
+   }
+
+   /**
+    * Searches the collection for the target string and returns the iOhioField
+    * object containing that string.  The string must be totally contained
+    * within the field to be considered a match.
+    *
+    * @param targetString The target string.
+    * @param startPos The row and column where to start the search. The position
+    *                 is inclusive (for example, row 1, col 1 means that
+    *                 position 1,1 will be used as the starting location and
+    *                 1,1 will be included in the search).
+    * @param length The length from startPos to include in the search.
+    * @param dir An OHIO_DIRECTION value:
+    *
+    * <table BORDER COLS=3 WIDTH="50%" >
+    * <tr><th>Constant </th><th>Value</th>
+    *                            <th>Description</th></tr>
+    * <tr><td>OS_OHIO_DIRECTION_FORWARD </td><td>0</td>
+    *                            <td>Forward (beginning towards end)</td></tr>
+    * <tr><td>OS_OHIO_DIRECTION_BACKWARD </td><td>1</td>
+    *                            <td>Backward (end towards beginning)</td></tr>
+    * </table>
+    *       Constant Value Description
+    *       ignoreCase - Indicates whether the search is case sensitive.
+    *       True means that case will be ignored. False means the search will
+    *       be case sensitive.
+    * @return If found, an iOhioField object containing the target string. If
+    *         not found, returns a null.
+    */
+   public ScreenField findByString (String targetString,
+                                             int startPos,
+                                             int length,
+                                             int dir,
+                                             boolean ignoreCase) {
+
+      // first lets check if the string exists in the screen space
+//      iOhioPosition pos = screen.findString(targetString, startPos, length,
+//                                             dir, ignoreCase);
+
+      // if it does exist then lets search the fields by the position that
+      //  was found and return the results of that search.
+//      if (pos != null) {
+         return findByPosition(startPos);
+//      }
+
+      //return null;
+
+   }
+
+   /**
+    * Searches the collection for the target position and returns the ScreenField
+    * object containing that position.
+    *
+    * @param targetPosition The target row and column expressed as a linear
+    *          position within the presentation space.
+    *
+    * @return If found, a ScreenField object containing the target position.
+    *         If not found, returns a null.
+    */
+   public ScreenField findByPosition(int targetPosition) {
+
+      ScreenField sf = null;
+
+      for (int x = 0;x < sizeFields; x++) {
+
+         sf = screenFields[x];
+
+         if (sf.withinField(targetPosition)) {
+            return sf;
+         }
+
+      }
+
+      return null;
+   }
+
+   /**
+    * Searches the collection for the target position and returns the ScreenField
+    * object containing that position.
+    *
+    * @param row The beginning row to start search with in the presentation space.
+    * @param col The beginning column to start search with in the presentation space.
+    *
+    * @return If found, a ScreenField object containing the target position.
+    *         If not found, returns a null.
+    */
+   public ScreenField findByPosition(int row, int col) {
+
+      return findByPosition(screen.getPos(row,col));
+   }
+
+   public ScreenField[] getFields () {
+
+      ScreenField[] fields = new ScreenField[sizeFields];
+      for (int x = 0; x < sizeFields; x++) {
+
+         fields[x] = screenFields[x];
+      }
+
+      return fields;
+   }
+
+   public ScreenField getFirstInputField() {
+
+		if (sizeFields <= 0)
+			return null;
+
+      int f = 0;
+      ScreenField sf = screenFields[f];
+
+      while (sf.isBypassField() && f++ < sizeFields) {
+         sf = screenFields[f];
+      }
+
+      if (sf.isBypassField())
+         return null;
+      else
+         return sf;
+
+   }
+
+   public void gotoFieldNext() {
+
+      // sanity check - we where getting null pointers after a restore of screen
+      //   and cursor was not positioned on a field when returned
+      //   *** Note *** to myself
+      //   maybe this is fixed I will have to check this some time
+      int lastPos = screen.getLastPos();
+
+      if (currentField == null && (sizeFields != 0) && !isInField(lastPos,true)) {
+         int pos = lastPos;
+         screen.setCursorOff();
+         screen.advancePos();
+         lastPos = screen.getLastPos();
+         while (!isInField() && pos != lastPos) {
+            screen.advancePos();
+         }
+         screen.setCursorOn();
+      }
+
+      // if we are still null do nothing
+      if (currentField == null)
+         return;
+
+      ScreenField sf = currentField;
+
+      if (!sf.withinField(lastPos)) {
+         screen.setCursorOff();
+
+         if (sizeFields > 0) {
+
+            // lets get the current position so we can test if we have looped
+            //    the screen and not found a valid field.
+            int pos = lastPos;
+            int savPos = lastPos;
+            boolean done = false;
+            do {
+               screen.advancePos();
+               lastPos = screen.getLastPos();
+               if (isInField(lastPos)
+                   || pos==lastPos) {
+                  if (!currentField.isBypassField()) {
+                     screen.gotoField(currentField);
+                     done = true;
+                  }
+               }
+            }  while ( !done && lastPos != savPos);
+         }
+         currentModified = false;
+         screen.setCursorOn();
+
+      }
+      else {
+         if (!cpfExists) {
+            do {
+
+               sf = sf.next;
+            }
+            while ( sf != null && sf.isBypassField());
+
+         }
+         else {
+            int f = 0;
+            int cp = sf.getCursorProgression();
+
+            if (cp == 0) {
+               do {
+
+                  sf = sf.next;
+               }
+               while ( sf != null && sf.isBypassField());
+
+            }
+            else {
+               ScreenField sf1 = null;
+               boolean found = false;
+               while (!found && f < sizeFields) {
+
+                  sf1 = screenFields[f++];
+                  if (sf1.getFieldId() == cp)
+                     found = true;
+               }
+               if (found)
+                  sf = sf1;
+               else {
+                  do {
+                     sf = sf.next;
+                  }
+                  while ( sf != null && sf.isBypassField());
+
+               }
+               sf1 = null;
+            }
+         }
+         if (sf == null)
+            screen.gotoField(1);
+         else {
+            currentField = sf;
+            screen.gotoField(currentField);
+         }
+
+         currentModified = false;
+
+      }
+   }
+
+   public void gotoFieldPrev() {
+
+      ScreenField sf = currentField;
+      int lastPos = screen.getLastPos();
+
+      if (!sf.withinField(lastPos)) {
+         screen.setCursorOff();
+
+         if (sizeFields > 0) {
+            // lets get the current position so we can test if we have looped
+            //    the screen and not found a valid field.
+            int pos = lastPos;
+            int savPos = lastPos;
+            boolean done = false;
+
+            do {
+               screen.changePos(-1);
+               lastPos = screen.getLastPos();
+
+               if (isInField(lastPos)
+                  || (pos == lastPos)) {
+
+                  if (!currentField.isBypassField()) {
+                     screen.gotoField(currentField);
+                     done = true;
+                  }
+               }
+            } while ( !done && lastPos != savPos);
+         }
+         screen.setCursorOn();
+
+      }
+      else {
+
+         if (sf.startPos() == lastPos) {
+            if (!cpfExists) {
+
+               do {
+                  sf = sf.prev;
+               }
+               while ( sf != null && sf.isBypassField());
+            }
+            else {
+
+               int f = 0;
+               int cp = sf.getFieldId();
+               ScreenField sf1 = null;
+               boolean found = false;
+               while (!found && f < sizeFields) {
+
+                  sf1 = screenFields[f++];
+                  if (sf1.getCursorProgression() == cp)
+                     found = true;
+               }
+               if (found)
+                  sf = sf1;
+               else {
+                  do {
+                     sf = sf.prev;
+                  }
+                  while ( sf != null && sf.isBypassField());
+               }
+               sf1 = null;
+            }
+         }
+
+         if (sf == null) {
+            int size = sizeFields;
+            sf = screenFields[size - 1];
+
+            while (sf.isBypassField() && size-- > 0) {
+               sf = screenFields[size];
+
+            }
+         }
+         currentField = sf;
+         currentModified = false;
+         screen.gotoField(currentField);
+      }
+   }
+
+   protected void readFormatTable(ByteArrayOutputStream baosp,int readType, ICodePage codePage) {
+
+      ScreenField sf;
+      boolean isSigned = false;
+      char c;
+
+      if (masterMDT) {
+
+         StringBuffer sb = new StringBuffer();
+         for (int x = 0; x < sizeFields; x++) {
+            isSigned = false;
+
+            sf = screenFields[x];
+
+            if (sf.mdt || (readType == CMD_READ_INPUT_FIELDS)) {
+
+               sb.setLength(0);
+               sb.append(sf.getText());
+
+
+               if (readType == CMD_READ_MDT_FIELDS ||
+                     readType == CMD_READ_MDT_IMMEDIATE_ALT) {
+                  int len = sb.length() - 1;
+
+                  // we strip out all '\u0020' and less
+                  while (len >= 0 &&
+//                     (sb.charAt(len) <= ' ' || sb.charAt(len) >= '\uff20' )) {
+                     (sb.charAt(len) < ' ' || sb.charAt(len) >= '\uff20')) {
+
+                     // if we have the dup character and dup is enabled then we
+                     //    stop here
+                     if (sb.charAt(len) == 0x1C && sf.isDupEnabled())
+                        break;
+
+                     sb.deleteCharAt(len--);
+                  }
+
+               }
+
+//               System.out.println("field " + sf.toString());
+//               System.out.println(">" + sb.toString() + "<");
+//               System.out.println(" field is all nulls");
+               if (sf.isSignedNumeric() && sb.length() > 0 && sb.charAt(sb.length() - 1) == '-') {
+                  isSigned = true;
+                  sb.setLength(sb.length() - 1);
+               }
+
+               int len3 = sb.length();
+
+               if (len3 > 0 || (readType == CMD_READ_MDT_FIELDS ||
+                       readType == CMD_READ_MDT_IMMEDIATE_ALT)) {
+
+                  if ((readType == CMD_READ_MDT_FIELDS ||
+                       readType == CMD_READ_MDT_IMMEDIATE_ALT)) {
+
+                     baosp.write(17);   // start of field data
+                  if (sf.isSelectionField()) {
+                     baosp.write(screen.getRow(sf.selectionPos)+1);
+                     baosp.write(screen.getCol(sf.selectionPos)+1);
+                  }
+                  else {
+                     baosp.write(sf.startRow()+1);
+                     baosp.write(sf.startCol()+1);
+                  }
+
+                  }
+//                  int len = sb.length();
+                  if (sf.isSelectionField()) {
+                     baosp.write(0);
+                     baosp.write(sf.selectionIndex + 0x1F);
+
+                  }
+                  else {
+                  for (int k = 0; k < len3; k++) {
+                     c = sb.charAt(k);
+                     // here we have to check for special instances of the
+                     //    characters in the string field.  Attribute bytes
+                     //    are encoded with an offset of \uff00
+                     //    This is a hack !!!!!!!!!!!
+                     //    See ScreenField object for a description
+                     if (c < ' ' || c >= '\uff20') {
+
+                        // if it is an offset attribute byte we just pass
+                        //    it straight on to the output stream
+                        if (c >= '\uff20' && c <= '\uff3f') {
+                           baosp.write(c - '\uff00');
+                        }
+                        else
+                           // check for dup character
+                           if (c == 0x1C)
+                              baosp.write(c);
+                           else
+                              baosp.write(codePage.uni2ebcdic(' '));
+                     }
+                     else {
+                        if (isSigned && k == len3 - 1) {
+                           baosp.write(0xd0 | (0x0f & c));
+                        }
+                        else
+                           baosp.write(codePage.uni2ebcdic(c));
+
+                     }
+                  }
+                  }
+               }
+            }
+         }
+      }
+   }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/ScreenOIA.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,294 @@
+/**
+ * <p>Title: ScreenOIA.java</p>
+ * <p>Description: Main interface to control Operator information area screen</p>
+ * <p>Copyright: Copyright (c) 2000 - 2002</p>
+ * <p>
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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
+ * </p>
+ * @author Kenneth J. Pouncey
+ * @version 0.5
+ */
+package org.tn5250j.framework.tn5250;
+
+import java.util.Vector;
+
+import org.tn5250j.event.ScreenOIAListener;
+
+/**
+ * The operator information area of a host session. This area is used to provide
+ * status information regarding the state of the host session and location of
+ * the cursor.  A ScreenOIA object can be obtained using the GetOIA() method on
+ * an instance of Screen5250.
+ *
+ *
+ */
+public class ScreenOIA
+  {
+   // OIA_LEVEL
+   public static final int OIA_LEVEL_INPUT_INHIBITED   =  1;
+   public static final int OIA_LEVEL_NOT_INHIBITED   =  2;
+   public static final int OIA_LEVEL_MESSAGE_LIGHT_ON  =  3;
+   public static final int OIA_LEVEL_MESSAGE_LIGHT_OFF  =  4;
+   public static final int OIA_LEVEL_AUDIBLE_BELL  =  5;
+   public static final int OIA_LEVEL_INSERT_MODE  =  6;
+   public static final int OIA_LEVEL_KEYBOARD  =  7;
+   public static final int OIA_LEVEL_CLEAR_SCREEN  =  8;
+   public static final int OIA_LEVEL_SCREEN_SIZE  =  9;
+   public static final int OIA_LEVEL_INPUT_ERROR   =  10;
+   public static final int OIA_LEVEL_KEYS_BUFFERED   =  11;
+   public static final int OIA_LEVEL_SCRIPT   =  12;
+
+   // INPUTINHIBITED
+   public static final int INPUTINHIBITED_NOTINHIBITED   =  0;
+   public static final int INPUTINHIBITED_SYSTEM_WAIT   =  1;
+   public static final int INPUTINHIBITED_COMMCHECK   =  2;
+   public static final int INPUTINHIBITED_PROGCHECK   =  3;
+   public static final int INPUTINHIBITED_MACHINECHECK   =  4;
+   public static final int INPUTINHIBITED_OTHER   =  5;
+
+   public ScreenOIA (Screen5250 screen) {
+
+      source = screen;
+
+   }
+
+   public boolean isInsertMode() {
+
+      return insertMode;
+   }
+
+   protected void setInsertMode(boolean mode) {
+
+      level = OIA_LEVEL_INSERT_MODE;
+      insertMode = mode;
+      fireOIAChanged(ScreenOIAListener.OIA_CHANGED_INSERT_MODE);
+   }
+
+   public int getCommCheckCode() {
+
+      return commCheck;
+   }
+
+   public int getInputInhibited() {
+
+      return inputInhibited;
+   }
+
+   public int getMachineCheckCode() {
+
+      return machineCheck;
+   }
+
+   public int getOwner() {
+      return owner;
+   }
+
+   public int getProgCheckCode() {
+      return 0;
+   }
+
+	/**
+	 * Is the keyboard locked or not
+	 *
+	 * @return locked or not
+	 */
+   public boolean isKeyBoardLocked() {
+      return locked;
+   }
+
+   public boolean isKeysBuffered() {
+      return keysBuffered;
+   }
+
+   public void setKeysBuffered(boolean kb) {
+      level = OIA_LEVEL_KEYS_BUFFERED;
+      boolean oldKB = keysBuffered;
+      keysBuffered = kb;
+      if (keysBuffered != oldKB)
+         fireOIAChanged(ScreenOIAListener.OIA_CHANGED_KEYS_BUFFERED);
+   }
+
+   protected void setKeyBoardLocked(boolean lockIt) {
+      level = OIA_LEVEL_KEYBOARD;
+      boolean oldLocked = locked;
+      locked = lockIt;
+		if (!lockIt) {
+
+			if (isKeysBuffered()) {
+				source.sendKeys("");
+			}
+		}
+
+      if (locked != oldLocked)
+         fireOIAChanged(ScreenOIAListener.OIA_CHANGED_KEYBOARD_LOCKED);
+   }
+
+   public boolean isMessageWait() {
+      return messageWait;
+   }
+
+   protected void setMessageLightOn() {
+      level = OIA_LEVEL_MESSAGE_LIGHT_ON;
+      messageWait = true;
+      fireOIAChanged(ScreenOIAListener.OIA_CHANGED_MESSAGELIGHT);
+   }
+
+   protected void setMessageLightOff() {
+      level = OIA_LEVEL_MESSAGE_LIGHT_OFF;
+      messageWait = false;
+      fireOIAChanged(ScreenOIAListener.OIA_CHANGED_MESSAGELIGHT);
+   }
+
+   public void setScriptActive(boolean running) {
+      level = OIA_LEVEL_SCRIPT;
+      scriptRunning = running;
+      fireOIAChanged(ScreenOIAListener.OIA_CHANGED_SCRIPT);
+   }
+
+   public boolean isScriptActive() {
+      return scriptRunning;
+   }
+
+   public void setAudibleBell() {
+      level = OIA_LEVEL_AUDIBLE_BELL;
+      fireOIAChanged(ScreenOIAListener.OIA_CHANGED_BELL);
+   }
+
+   protected void clearScreen() {
+      level = OIA_LEVEL_CLEAR_SCREEN;
+      fireOIAChanged(ScreenOIAListener.OIA_CHANGED_CLEAR_SCREEN);
+   }
+
+   /**
+    * Add a ScreenOIAListener to the listener list.
+    *
+    * @param listener  The ScreenOIAListener to be added
+    */
+   public void addOIAListener(ScreenOIAListener listener) {
+
+      if (listeners == null) {
+          listeners = new java.util.Vector<ScreenOIAListener>(3);
+      }
+      listeners.addElement(listener);
+
+   }
+
+   /**
+    * Remove a iOhioSessionListener from the listener list.
+    *
+    * @param listener  The iOhioSessionListener to be removed
+    */
+   public void removeOIAListener(ScreenOIAListener listener) {
+
+      if (listeners == null) {
+          return;
+      }
+      listeners.removeElement(listener);
+   }
+
+   // object methods
+   public Screen5250 getSource() {
+
+      return source;
+   }
+
+
+   public void setSource(Screen5250 screen) {
+
+      source = screen;
+
+   }
+
+   public void setOwner(int newOwner) {
+
+      owner = newOwner;
+
+   }
+
+   public int getLevel() {
+
+      return level;
+   }
+
+   public String getInhibitedText() {
+      return inhibitedText;
+   }
+
+   public void setInputInhibited(int inhibit , int whatCode) {
+      setInputInhibited(inhibit, whatCode, null);
+   }
+
+   public void setInputInhibited(int inhibit , int whatCode, String message) {
+
+      inputInhibited = inhibit;
+      level = OIA_LEVEL_INPUT_INHIBITED;
+      inhibitedText = message;
+
+//      if (saveInhibit != inhibit || saveInhibitLevel != whatCode) {
+         switch(inhibit) {
+
+            case INPUTINHIBITED_COMMCHECK :
+               commCheck = whatCode;
+               break;
+            case INPUTINHIBITED_PROGCHECK :
+//               progCheck = whatCode; // never used
+               break;
+            case INPUTINHIBITED_MACHINECHECK :
+               machineCheck = whatCode;
+               break;
+            case INPUTINHIBITED_SYSTEM_WAIT :
+               level = whatCode;
+               break;
+            case INPUTINHIBITED_NOTINHIBITED :
+               level = whatCode;
+               break;
+         }
+
+         fireOIAChanged(ScreenOIAListener.OIA_CHANGED_INPUTINHIBITED);
+//      }
+   }
+
+   /**
+    * Notify all registered listeners of the onOIAChanged event.
+    *
+    */
+   private void fireOIAChanged(int change) {
+
+      if (listeners != null) {
+         int size = listeners.size();
+         for (int i = 0; i < size; i++) {
+            ScreenOIAListener target =
+                    listeners.elementAt(i);
+            target.onOIAChanged(this, change);
+         }
+      }
+   }
+
+   private Vector<ScreenOIAListener> listeners = null;
+   private boolean insertMode;
+   private boolean locked;
+   private boolean keysBuffered;
+   private int owner = 0;
+   private int level = 0;
+   private Screen5250 source = null;
+   private int commCheck = 0;
+   private int machineCheck = 0;
+   private boolean messageWait;
+   private boolean scriptRunning;
+   private int inputInhibited = INPUTINHIBITED_NOTINHIBITED;
+   private String inhibitedText;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/ScreenPlanes.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,1173 @@
+/**
+ * Title: ScreenPlanes.java
+ * Copyright:   Copyright (c) 2001
+ * 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.util.Properties;
+
+import org.tn5250j.ExternalProgramConfig;
+
+public class ScreenPlanes {
+
+	private final Screen5250 scr;
+	private int screenSize;
+	private int numRows;
+	private int numCols;
+	private int errorLineNum;
+
+	private static final int initAttr = 32;
+	private static final char initChar = 0;
+
+	protected char[] screen;   // text plane
+	private char[] screenAttr;   // attribute plane
+	private char[] screenGUI;   // gui plane
+	private char[] screenIsAttr;
+	private char[] fieldExtended;
+	private char[] screenField;
+	private char[] screenColor;   // color plane
+	protected char[] screenExtended;   // extended plane
+	private char[] screenIsChanged;
+
+	private char[] initArray;
+
+	private char[] errorLine;
+	private char[] errorLineAttr;
+	private char[] errorLineIsAttr;
+	private char[] errorLineGui;
+
+	public ScreenPlanes(Screen5250 s5250, int size) {
+
+		scr = s5250;
+		setSize(size);
+	}
+
+	protected void setSize(int newSize) {
+
+		screenSize = newSize;
+
+		numCols = 80;
+		switch (newSize) {
+		case 24:
+			numRows = 24;
+			break;
+		case 27:
+			numRows = 27;
+			numCols = 132;
+			break;
+
+		}
+
+		// this is used here when size changes
+		setErrorLine(numRows);
+
+		screenSize = numRows * numCols;
+		screen = new char[screenSize];
+		screenAttr = new char[screenSize];
+		screenIsAttr = new char[screenSize];
+		screenGUI = new char[screenSize];
+		screenColor = new char[screenSize];
+		screenExtended = new char[screenSize];
+		fieldExtended = new char[screenSize];
+		screenIsChanged = new char[screenSize];
+		screenField = new char[screenSize];
+
+		initArray = new char[screenSize];
+
+		initalizePlanes();
+	}
+
+	protected void setErrorLine (int line) {
+
+		// * NOTE * for developers I have changed the send qry to pass different
+		//    parameters to the host so check setsize for setting error line as well.
+		//
+		if (line == 0 || line > numRows)
+			errorLineNum = numRows;
+		else
+			errorLineNum = line;
+	}
+
+	/**
+	 * Returns the current error line number
+	 *
+	 * @return current error line number
+	 */
+	protected int getErrorLine() {
+		return errorLineNum;
+	}
+
+	protected void saveErrorLine() {
+
+		// if there is already an error line saved then do not save it again
+		//  This signifies that there was a previous error and the original error
+		//  line was not restored yet.
+		if (errorLine == null) {
+			errorLine = new char[numCols];
+			errorLineAttr = new char[numCols];
+			errorLineIsAttr = new char[numCols];
+			errorLineGui = new char[numCols];
+
+			int r = scr.getPos(errorLineNum-1,0);
+
+			for (int x = 0;x < numCols; x++) {
+				errorLine[x] = screen[r+x];
+				errorLineAttr[x] = screenAttr[r+x];
+				errorLineIsAttr[x] = screenIsAttr[r+x];
+				errorLineGui[x] = screenGUI[r+x];
+			}
+		}
+	}
+
+	/**
+	 * Restores the error line characters from the save buffer.
+	 *
+	 * @see #saveErrorLine()
+	 */
+	protected void restoreErrorLine() {
+
+		if (errorLine != null) {
+			int r = scr.getPos(errorLineNum - 1, 0);
+
+			for (int x = 0; x < numCols - 1; x++) {
+				setScreenCharAndAttr(r+x,errorLine[x],errorLineAttr[x],
+						(errorLineIsAttr[x] == '1' ? true : false));
+				screenGUI[x] = errorLineGui[x];
+			}
+
+			errorLine = null;
+			errorLineAttr = null;
+			errorLineIsAttr = null;
+			errorLineGui = null;
+		}
+	}
+
+	protected boolean isErrorLineSaved() {
+		return errorLine == null ? false : true;
+	}
+
+	protected void setScreenCharAndAttr(int pos, char c, int attr, boolean isAttr) {
+
+		screen[pos] = c;
+		screenAttr[pos] = (char)attr;
+		disperseAttribute(pos,attr);
+		screenIsAttr[pos] = (isAttr ? (char)1 : (char)0);
+		screenGUI[pos] = NO_GUI;
+
+	}
+
+	protected void setScreenAttr(int pos, int attr, boolean isAttr) {
+
+		screenAttr[pos] = (char)attr;
+		screenIsAttr[pos] = isAttr ? (char)1 : (char)0;
+		disperseAttribute(pos,attr);
+		screenGUI[pos] = initChar;
+
+	}
+
+	protected void setScreenAttr(int pos, int attr) {
+
+		screenAttr[pos] = (char)attr;
+		//screenGUI[pos] = initChar;
+		disperseAttribute(pos,attr);
+
+	}
+
+	protected void setScreenFieldAttr(int pos, int attr) {
+
+		screenField[pos] = (char)attr;
+
+	}
+
+	protected final void setChar(int pos, char c) {
+		screenIsChanged[pos] = screen[pos] == c ? '0' : '1';
+		screen[pos] = c;
+		if (screenIsAttr[pos] == 1)
+			setScreenCharAndAttr(pos,c,32,false);
+
+	}
+
+	protected final char getChar(int pos) {
+		return screen[pos];
+	}
+
+	protected final int getCharAttr(int pos) {
+		return screenAttr[pos];
+	}
+
+	protected final boolean isAttributePlace(int pos) {
+		return screenIsAttr[pos] == 1 ? true : false;
+	}
+
+	public final void setUseGUI(int pos, int which) {
+
+		screenIsChanged[pos] = screenGUI[pos] == which ? '0' : '1';
+		screenGUI[pos] = (char)which;
+	}
+
+	private void disperseAttribute(int pos, int attr) {
+
+		char c = 0;
+		char cs = 0;
+		char ul = 0;
+		char nd = 0;
+
+		if(attr == 0)
+			return;
+
+		switch(attr) {
+		case 32: // green normal
+			c = ATTR_32;
+			break;
+
+		case 33: // green/revers
+			c = ATTR_33;
+			break;
+
+		case 34: // white normal
+			c = ATTR_34;
+			break;
+
+		case 35: // white/reverse
+			c = ATTR_35;
+			break;
+
+		case 36: // green/underline
+			c = ATTR_36;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 37: // green/reverse/underline
+			c = ATTR_37;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 38: // white/underline
+			c = ATTR_38;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 39:
+			nd = EXTENDED_5250_NON_DSP;
+			break;
+
+		case 40:
+		case 42: // red/normal
+			c = ATTR_40;
+			break;
+
+		case 41:
+		case 43: // red/reverse
+			c = ATTR_41;
+			break;
+
+		case 44:
+		case 46: // red/underline
+			c = ATTR_44;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 45: // red/reverse/underline
+			c = ATTR_45;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 47:
+			nd = EXTENDED_5250_NON_DSP;
+			break;
+
+		case 48:
+			c = ATTR_48;
+			cs = EXTENDED_5250_COL_SEP;
+			break;
+
+		case 49:
+			c = ATTR_49;
+			cs = EXTENDED_5250_COL_SEP;
+			break;
+
+		case 50:
+			c = ATTR_50;
+			cs = EXTENDED_5250_COL_SEP;
+			break;
+
+		case 51:
+			c = ATTR_51;
+			cs = EXTENDED_5250_COL_SEP;
+			break;
+
+		case 52:
+			c = ATTR_52;
+			//            colSep = true;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 53:
+			c = ATTR_53;
+			//            colSep = true;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 54:
+			c = ATTR_54;
+			//            colSep = true;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 55:
+			nd = EXTENDED_5250_NON_DSP;
+			break;
+
+		case 56: // pink
+			c = ATTR_56;
+			break;
+
+		case 57: // pink/reverse
+			c = ATTR_57;
+			break;
+
+		case 58: // blue/reverse
+			c = ATTR_58;
+			break;
+
+		case 59: // blue
+			c = ATTR_59;
+			break;
+
+		case 60: // pink/underline
+			c = ATTR_60;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 61: // pink/reverse/underline
+			c = ATTR_61;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 62: // blue/underline
+			c = ATTR_62;
+			ul = EXTENDED_5250_UNDERLINE;
+			break;
+
+		case 63:  // nondisplay
+			nd = EXTENDED_5250_NON_DSP;
+			cs = EXTENDED_5250_COL_SEP;
+			break;
+		default:
+			c = ( COLOR_BG_BLACK << 8 & 0xff00) |
+			( COLOR_FG_YELLOW & 0xff);
+			break;
+
+		}
+
+		screenColor[pos] = c;
+		screenExtended[pos] = (char)(ul | cs | nd);
+	}
+
+	protected void initalizePlanes () {
+
+		char c = (COLOR_BG_BLACK << 8 & 0xff00) |
+		(COLOR_FG_GREEN & 0xff);
+
+		for (int y = 0;y < screenSize; y++) {
+
+			screenAttr[y] = initAttr;
+			screenColor[y] = c;
+
+		}
+
+		// here we will just copy the initialized plane onto the other planes
+		// using arraycopy which will be faster.  I hope.
+
+		System.arraycopy(initArray,0,screen,0,screenSize);
+		System.arraycopy(initArray,0,screenGUI,0,screenSize);
+		System.arraycopy(initArray,0,screenIsAttr,0,screenSize);
+		System.arraycopy(initArray,0,screenExtended,0,screenSize);
+		System.arraycopy(initArray,0,fieldExtended,0,screenSize);
+		System.arraycopy(initArray,0,screenField,0,screenSize);
+	}
+
+	protected void initalizeFieldPlanes () {
+		System.arraycopy(initArray,0,fieldExtended,0,screenSize);
+		System.arraycopy(initArray,0,screenField,0,screenSize);
+	}
+
+	protected final int getWhichGUI(int pos) {
+
+		return screenGUI[pos];
+	}
+
+	protected final boolean isChanged(int pos) {
+		return screenIsChanged[pos] == 0 ? false : true;
+	}
+
+	protected final boolean isUseGui(int pos) {
+		return screenGUI[pos] == NO_GUI ? false : true;
+	}
+
+	/**
+	 * Return the data associated with the plane that is passed.
+	 *
+	 * @param from Position from which to start
+	 * @param to Position to end
+	 * @param plane From which plane to obtain the data
+	 * @return Character array containing the data requested
+	 */
+	protected synchronized char[] getPlaneData(int from, int to, int plane) {
+
+		int len = (to - from);
+
+		char[] planeChars = new char[len + 1];
+
+		switch (plane) {
+		case PLANE_TEXT:
+			System.arraycopy(screen, from, planeChars, 0, len);
+			break;
+		case PLANE_ATTR:
+			System.arraycopy(screenAttr, from, planeChars, 0, len);
+			break;
+		case PLANE_COLOR:
+			System.arraycopy(screenColor, from, planeChars, 0, len);
+			break;
+		case PLANE_EXTENDED:
+			System.arraycopy(screenExtended, from, planeChars, 0, len);
+			break;
+		case PLANE_EXTENDED_GRAPHIC:
+			System.arraycopy(screenGUI, from, planeChars, 0, len);
+			break;
+		case PLANE_FIELD:
+			System.arraycopy(screenField, from, planeChars, 0, len);
+			break;
+		case PLANE_IS_ATTR_PLACE:
+			System.arraycopy(screenIsAttr, from, planeChars, 0, len);
+			break;
+		default:
+			System.arraycopy(screen, from, planeChars, 0, len);
+
+		}
+		return planeChars;
+
+	}
+
+	/**
+	 * Converts a linear presentation space position to its corresponding row.
+	 *
+	 * @param pos The position to be converted
+	 * @return The row which corresponds to the position given
+	 * @throws OhioException
+	 */
+	private int convertPosToRow(int pos) {
+
+		return (pos / numCols) + 1;
+
+	}
+
+	/**
+	 * Converts a linear presentation space position to its corresponding column.
+	 *
+	 * @param pos The position to be converted
+	 * @return The column which corresponds to the position given
+	 * @throws OhioException
+	 */
+	private int convertPosToColumn(int pos) {
+
+		return (pos % numCols) + 1;
+
+	}
+
+	/**
+	 *
+	 * Converts a row and column coordinate to its corresponding linear position.
+	 *
+	 * @param row - The row of the coordinate
+	 * @param col - The column of the coordinate
+	 * @return The linear position which corresponds to the coordinate given.
+	 * @throws OhioException
+	 */
+	private int convertRowColToPos(int row, int col) {
+
+
+		return (row - 1) * numCols + col -1;
+
+	}
+
+
+	/**
+	 * <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) {
+
+		return GetScreen(buffer,bufferLength,0,screenSize,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)
+	{
+		//      if(buffer == null)
+		//         throw new OhioException(sessionVT.getSessionConfiguration(),
+		//                     OhioScreen.class.getName(), "osohio.screen.ohio00300", 1);
+		if(buffer == null)
+			return 0;
+
+		int min = Math.min(Math.min(buffer.length, bufferLength), screenSize);
+		if ((from + min) > screenSize) {
+			min = screenSize - from;
+		}
+
+		char[] pd = getPlaneData(from,from + min,plane);
+		if(pd != null) {
+			System.arraycopy(pd, 0, buffer, 0, min);
+			return pd.length;
+		}
+
+		return 0;
+	}
+
+	/**
+	 * <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 GetScreen(buffer,bufferLength, convertRowColToPos(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
+	 */
+	protected int GetScreenRect(char buffer[], int bufferLength,
+			int startPos, int endPos, int plane)
+	//                                             throws OhioException {
+	{
+		// We will use the row,col routine here because it is easier to use
+		// row colum than it is for position since I wrote the other first and
+		// am to lazy to implement it here
+		// Maybe it would be faster to do it the other way?
+		int startRow = convertPosToRow(startPos);
+		int startCol = convertPosToColumn(startPos);
+		int endRow = convertPosToRow(endPos);
+		int endCol = convertPosToColumn(endPos);
+		return GetScreenRect(buffer, bufferLength, startRow, startCol,
+				endRow, endCol, 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
+	 */
+	protected int GetScreenRect(char buffer[], int bufferLength,
+			int startRow, int startCol,
+			int endRow, int endCol, int plane)
+	//                                             throws OhioException {
+	{
+		// number of bytes obtained
+		int numBytes = 0;
+
+		// lets check the row range.  If they are reversed then we need to
+		// place them in the correct order.
+		if(startRow > endRow) {
+			int r = startRow;
+			startRow = endRow;
+			endRow = r;
+		}
+		// lets check the column range.  If they are reversed then we need to
+		// place them in the correct order.
+		if(startCol > endCol) {
+			int c = startCol;
+			startCol = endCol;
+			endCol = c;
+		}
+		int numCols = (endCol - startCol) + 1;
+		int numRows = (endRow - startRow) + 1;
+
+		// lets make sure it is within the bounds of the character array passed
+		//  if not the return as zero bytes where read as per documentation.
+		if(numCols * numRows <= bufferLength) {
+
+			// make sure it is one larger.  I guess for other languanges to
+			// reference like in C which is terminated by a zero byte at the end
+			// of strings.
+			char cb[] = new char[numCols + 1];
+			int charOffset = 0;
+			int bytes = 0;
+
+			// now let's loop through and get the screen information for
+			//  each row;
+			for(int row = startRow; row <= endRow;) {
+				if((bytes = GetScreen(cb, cb.length, row, startCol, numCols, plane)) != 0) {
+					System.arraycopy(cb, 0, buffer, charOffset, numCols);
+				}
+				row++;
+				charOffset += numCols;
+				// make sure we count the number of bytes returned
+				numBytes += bytes;
+			}
+
+		}
+
+		return numBytes;
+	}
+
+	protected boolean checkHotSpots () {
+
+		Screen5250 s = scr;
+		int lenScreen = scr.getScreenLength();
+		boolean hs = false;
+		boolean retHS = false;
+		StringBuffer hsMore = s.getHSMore();
+		StringBuffer hsBottom = s.getHSBottom();
+
+		for (int x = 0; x < lenScreen; x++) {
+
+			hs =false;
+			if (s.isInField(x,false))
+				continue;
+
+			// First check for PF keys
+			if (x > 0 && screen[x] == 'F') {
+				if (screen[x + 1] >= '0' &&
+						screen[x + 1] <= '9' &&
+						screen[x - 1] <= ' ' &&
+						(screenExtended[x] & EXTENDED_5250_NON_DSP) == 0) {
+
+					if (screen[x + 2] >= '0' &&
+							screen[x + 2] <= '9' &&
+							(screen[x + 3] == '=' ||
+									screen[x + 3] == '-' ||
+									screen[x + 3] == '/') )
+						hs = true;
+					else
+						if (   screen[x + 2] == '=' ||
+								screen[x + 3] == '-' ||
+								screen[x + 3] == '/')
+							hs = true;
+
+					if (hs) {
+						screenGUI[x] = BUTTON_LEFT;
+
+						int ns = 0;
+						int row = x / numCols;
+						while (ns < 2 && ++x / numCols == row) {
+							if (screen[x] <= ' ')
+								ns++;
+							else
+								ns = 0;
+							if (ns <2)
+								screenGUI[x] = BUTTON_MIDDLE;
+
+						}
+
+						// now lets go back and take out gui's that do not belong
+						while (screen[--x] <= ' ') {
+							screenGUI[x] = NO_GUI;
+						}
+						screenGUI[x] = BUTTON_RIGHT;
+
+					}
+				}
+			}
+
+			// now lets check for menus
+			if (!hs && x > 0 && x < lenScreen - 2 &&
+					screen[x] == '.' &&
+					screenGUI[x] == NO_GUI &&
+					(screenExtended[x] & EXTENDED_5250_UNDERLINE) == 0 &&
+					(screenExtended[x] & EXTENDED_5250_NON_DSP) == 0
+			) {
+
+				int os = 0;
+				if ((os = isOption(screen,x,lenScreen,2,3,'.') )> 0) {
+					hs = true;
+
+					int stop = x;
+					int ns = 0;
+					int row = stop / numCols;
+
+					while (++stop / numCols == row &&
+							(screen[stop] >= ' ' ||
+									screen[stop] == 0x0) ) {
+
+						if (screen[stop] <= ' ') {
+							ns++;
+						}
+						else
+							ns = 0;
+
+						if (screen[stop] == '.') {
+							int io = 0;
+							if ((io = isOption(screen,stop,lenScreen,2,3,'.')) > 0) {
+
+								stop = io;
+								break;
+							}
+						}
+
+						if (ns > 3)
+							break;
+					}
+
+					screenGUI[++os] = BUTTON_LEFT;
+					s.setDirty(os);
+
+					while (++os < stop) {
+						screenGUI[os] = BUTTON_MIDDLE;
+						s.setDirty(os);
+					}
+
+					// now lets go back and take out gui's that do not belong
+					while (screen[--stop] <= ' ') {
+						screenGUI[stop] = NO_GUI;
+						s.setDirty(stop);
+					}
+					screenGUI[stop] = BUTTON_RIGHT;
+					s.setDirty(stop);
+
+				}
+			}
+
+			// now lets check for options.
+			if (!hs && x > 0 && x < lenScreen - 2 &&
+					screen[x] == '=' &&
+					screenGUI[x] == NO_GUI &&
+					(screenExtended[x] & EXTENDED_5250_UNDERLINE) == 0 &&
+					(screenExtended[x] & EXTENDED_5250_NON_DSP) == 0
+			) {
+
+				int os = 0;
+				if ((os = isOption(screen,x,lenScreen,2,2,'=') )> 0) {
+					hs = true;
+
+					int stop = x;
+					int ns = 0;
+					int row = stop / numCols;
+
+					while (++stop / numCols == row &&
+							screen[stop] >= ' ') {
+
+						if (screen[stop] == ' ') {
+							ns++;
+						}
+						else
+							ns = 0;
+
+						if (screen[stop] == '=') {
+							int io = 0;
+							if ((io = isOption(screen,stop,lenScreen,2,2,'=')) > 0) {
+
+								stop = io;
+								break;
+							}
+						}
+
+						if (ns > 2)
+							break;
+					}
+
+					screenGUI[++os] = BUTTON_LEFT;
+					s.setDirty(os);
+
+					while (++os < stop) {
+						screenGUI[os] = BUTTON_MIDDLE;
+						s.setDirty(os);
+
+					}
+
+					// now lets go back and take out gui's that do not belong
+					while (screen[--stop] <= ' ') {
+						screenGUI[stop] = NO_GUI;
+						s.setDirty(stop);
+
+					}
+					screenGUI[stop] = BUTTON_RIGHT;
+					s.setDirty(stop);
+				}
+			}
+
+			// now lets check for More... .
+
+			if (!hs && x > 2 && x < lenScreen - hsMore.length() &&
+					screen[x] == hsMore.charAt(0) &&
+					screen[x - 1] <= ' ' &&
+					screen[x - 2] <= ' ' &&
+					screenGUI[x] == NO_GUI &&
+					(screenExtended[x] & EXTENDED_5250_NON_DSP) == 0
+			) {
+
+				boolean mFlag = true;
+				int ms = hsMore.length();
+				int mc = 0;
+				while (++mc < ms) {
+					if (screen[x+mc] != hsMore.charAt(mc)) {
+						mFlag = false;
+						break;
+					}
+
+				}
+
+				if (mFlag) {
+					hs = true;
+
+					screenGUI[x] = BUTTON_LEFT_DN;
+
+					while (--ms > 0) {
+						screenGUI[++x] = BUTTON_MIDDLE_DN;
+
+					}
+					screenGUI[x] = BUTTON_RIGHT_DN;
+				}
+			}
+
+			// now lets check for Bottom .
+			if (!hs && x > 2 && x < lenScreen - hsBottom.length() &&
+					screen[x] == hsBottom.charAt(0) &&
+					screen[x - 1]  <= ' ' &&
+					screen[x - 2] <= ' ' &&
+					screenGUI[x] == NO_GUI &&
+					(screenExtended[x] & EXTENDED_5250_NON_DSP) == 0
+			) {
+
+				boolean mFlag = true;
+				int bs = hsBottom.length();
+				int bc = 0;
+				while (++bc < bs) {
+					if (screen[x+bc] != hsBottom.charAt(bc)) {
+						mFlag = false;
+						break;
+					}
+
+				}
+
+				if (mFlag) {
+					hs = true;
+
+					screenGUI[x] = BUTTON_LEFT_UP;
+
+					while (--bs > 0) {
+						screenGUI[++x] = BUTTON_MIDDLE_UP;
+
+					}
+					screenGUI[x] = BUTTON_RIGHT_UP;
+				}
+			}
+
+			// Submitted by Richard Houston of RLH Consulting rhouston@rlhc.net
+			// now lets check for HTTP:// or HTTPS://.
+			if (!hs && x > 0 && x < lenScreen - 7 &&
+					Character.toLowerCase(screen[x]) == 'h' &&
+					screen[x - 1] <= ' ' &&
+					screenGUI[x] == NO_GUI &&
+					(screenExtended[x] & EXTENDED_5250_NON_DSP) == 0
+			) {
+
+				if (Character.toLowerCase(screen[x+1]) == 't' &&
+						Character.toLowerCase(screen[x+2]) == 't' &&
+						Character.toLowerCase(screen[x+3]) == 'p' &&
+						screen[x+4] == ':' &&
+						screen[x+5] == '/' &&
+						screen[x+6] == '/' ) {
+
+					hs = true;
+
+					screenGUI[x] = BUTTON_LEFT_EB;
+
+					while (screen[++x] > ' ') {
+						screenGUI[x] = BUTTON_MIDDLE_EB;
+
+					}
+
+					screenGUI[--x] = BUTTON_RIGHT_EB;
+				}
+
+				else if (Character.toLowerCase(screen[x+1]) == 't' &&
+						Character.toLowerCase(screen[x+2]) == 't' &&
+						Character.toLowerCase(screen[x+3]) == 'p' &&
+						Character.toLowerCase(screen[x+4]) == 's' &&
+						screen[x+5] == ':' &&
+						screen[x+6] == '/' &&
+						screen[x+7] == '/' ) {
+
+					hs = true;
+
+					screenGUI[x] = BUTTON_LEFT_EB;
+
+					while (screen[++x] > ' ') {
+						screenGUI[x] = BUTTON_MIDDLE_EB;
+
+					}
+
+					screenGUI[--x] = BUTTON_RIGHT_EB;
+				}
+
+			}
+			// now lets check for MAILTO: .
+			else if (!hs && x > 0 && x < lenScreen - 7 &&
+					Character.toLowerCase(screen[x]) == 'm' &&
+					screen[x - 1] <= ' ' &&
+					screenGUI[x] == NO_GUI &&
+					(screenExtended[x] & EXTENDED_5250_NON_DSP) == 0
+			) {
+
+				if (Character.toLowerCase(screen[x+1]) == 'a' &&
+						Character.toLowerCase(screen[x+2]) == 'i' &&
+						Character.toLowerCase(screen[x+3]) == 'l' &&
+						Character.toLowerCase(screen[x+4]) == 't' &&
+						Character.toLowerCase(screen[x+5]) == 'o' &&
+						screen[x+6] == ':') {
+
+					hs = true;
+
+					screenGUI[x] = BUTTON_LEFT_EB;
+
+					while (screen[++x] > ' ') {
+						screenGUI[x] = BUTTON_MIDDLE_EB;
+
+					}
+					screenGUI[--x] = BUTTON_RIGHT_EB;
+				}
+			}
+			// now lets check for External Program: .
+			else if (!hs && x > 0 && x < lenScreen - 7 &&
+					screen[x - 1] <= ' ' &&
+					screenGUI[x] == NO_GUI &&
+					(screenExtended[x] & EXTENDED_5250_NON_DSP) == 0
+			) {
+				Properties etnProps = ExternalProgramConfig.getInstance().getEtnPgmProps();
+				String count = etnProps.getProperty("etn.pgm.support.total.num");
+				if(count != null && count.length() > 0){
+					int total = Integer.parseInt(count);
+					for(int i=1;i<=total;i++){
+						String program = etnProps.getProperty("etn.pgm."+i+".command.name");
+						String key="";
+						if(x + program.length() >= screen.length) break;
+						for(int j=0;j<=program.length();j++){
+							key+=screen[x+j];
+						}
+						if(key.toLowerCase().equals(program.toLowerCase()+":")) {
+							hs = true;
+							screenGUI[x] = BUTTON_LEFT_EB;
+							while (screen[++x] > ' ') {
+								screenGUI[x] = BUTTON_MIDDLE_EB;
+							}
+							screenGUI[--x] = BUTTON_RIGHT_EB;
+							break;
+						}
+					}
+				}
+			}
+
+			if (!retHS && hs)
+				retHS = true;
+
+		}
+
+		return retHS;
+	}
+
+	private int isOption(char[] screen,
+			int x,
+			int lenScreen,
+			int numPref,
+			int numSuff,
+			char suff) {
+		boolean hs =true;
+		int sp = x;
+		int os = 0;
+		// check to the left for option
+		while (--sp >=0 &&  screen[sp] <= ' ' ) {
+
+			if (x - sp > numPref || screen[sp] == suff||
+					screen[sp] == '.' ||
+					screen[sp] == '*') {
+				hs =false;
+				break;
+			}
+		}
+
+		// now lets check for how long the option is it has to be numPref or less
+		os = sp;
+		while (hs && --os > 0 && screen[os] > ' ' ) {
+
+			if (sp - os >= numPref || screen[os] == suff ||
+					screen[os] == '.' ||
+					screen[os] == '*') {
+				hs = false;
+				break;
+			}
+		}
+		if (sp - os > 1 && !Character.isDigit(screen[os+1])) {
+			hs = false;
+		}
+
+		sp = x;
+
+		if (Character.isDigit(screen[sp+1]))
+			hs = false;
+		// now lets make sure there are no more than numSuff spaces after option
+		while (hs && (++sp < lenScreen && screen[sp] <= ' '
+			|| screen[sp] == suff )) {
+			if (sp - x >= numSuff || screen[sp] == suff ||
+					screen[sp] == '.' ||
+					screen[sp] == '*') {
+				hs =false;
+				break;
+			}
+		}
+		if (hs && !Character.isLetterOrDigit(screen[sp]))
+			hs = false;
+		if (hs) {
+			return os;
+		}
+		return -1;
+	}
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/Stream5250.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,173 @@
+/**
+ * Title: tn5250J
+ * Copyright:   Copyright (c) 2001
+ * Company:
+ * @author  Kenneth J. Pouncey
+ * @version 0.4
+ *
+ * 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;
+
+public class Stream5250 {
+
+    public int streamSize;
+    public int opCode;
+    public int dataStart;
+    public int pos;
+    public byte buffer[];
+
+    public Stream5250(byte abyte0[]) {
+        buffer = abyte0;
+        // size without end of record 0xFF 0xEF
+        streamSize = (abyte0[0] & 0xff) << 8 | abyte0[1] & 0xff;
+        opCode = abyte0[9];
+        dataStart = 6 + abyte0[6];
+        pos = dataStart;
+    }
+
+    public Stream5250() {
+       buffer = null;
+       streamSize = 0;
+       opCode = 0;
+       dataStart = 0;
+       pos = dataStart;
+   }
+
+    /**
+     * This method takes a byte array and initializes the object information
+     *    to be used.
+     * 
+     * @param abyte0
+     */
+    public void initialize(byte abyte0[]) {
+       
+     buffer = abyte0;
+     // size without end of record 0xFF 0xEF
+     streamSize = (abyte0[0] & 0xff) << 8 | abyte0[1] & 0xff;
+     opCode = abyte0[9];
+     dataStart = 6 + abyte0[6];
+     pos = dataStart;
+       
+    }
+    
+    public final int getOpCode() {
+        return opCode;
+    }
+
+    public final byte getNextByte()
+        throws Exception  {
+        if(buffer == null || pos > buffer.length)
+            throw new Exception("Buffer length exceeded: " + pos);
+        else
+            return buffer[pos++];
+    }
+
+    public final void setPrevByte()
+        throws Exception {
+        if(pos == 0) {
+            throw new Exception("Index equals zero.");
+        }
+        else {
+            pos--;
+            return;
+      }
+   }
+
+   /**
+    * Returns where we are in the buffer
+    * @return position in the buffer
+    */
+   public final int getCurrentPos() {
+      return pos;
+   }
+
+   public final byte getByteOffset(int off)
+        throws Exception  {
+
+        if(buffer == null || (pos + off ) > buffer.length)
+            throw new Exception("Buffer length exceeded: " + pos);
+        else
+            return buffer[pos + off];
+
+   }
+
+   public final boolean size() {
+      return pos >= streamSize;
+   }
+
+
+   /**
+    * Determines if any more bytes are available in the buffer to be processed.
+    * @return yes or no
+    */
+   public final boolean hasNext() {
+
+//      return pos >= buffer.length;
+      return pos < streamSize;
+   }
+
+   /**
+    * This routine will retrieve a segment based on the first two bytes being
+    * the length of the segment.
+    *
+    * @return a new byte array containing the bytes of the segment.
+    * @throws Exception
+    */
+   public final byte[] getSegment() throws Exception {
+
+      // The first two bytes contain the length of the segment.
+      int length = ((buffer[pos] & 0xff )<< 8 | (buffer[pos+1] & 0xff));
+      // allocate space for it.
+      byte[] segment = new byte[length];
+
+      getSegment(segment,length,true);
+
+      return segment;
+   }
+
+
+   /**
+    * This routine will retrieve a byte array based on the first two bytes being
+    * the length of the segment.
+    *
+    * @param segment - byte array
+    * @param length - length of segment to return
+    * @param adjustPos - adjust the position of the buffer to the end of the seg
+    *                      ment
+    * @throws Exception
+    */
+   public final void getSegment(byte[] segment, int length, boolean adjustPos)
+               throws Exception {
+
+      // If the length is larger than what is available throw an exception
+      if((pos + length ) > buffer.length)
+            throw new Exception("Buffer length exceeded: start " + pos
+                                 + " length " + length);
+      // use the system array copy to move the bytes from the buffer
+      //    to the allocated byte array
+      System.arraycopy(buffer,pos,segment,0,length);
+
+      // update the offset to be after the segment so the next byte can be read
+      if (adjustPos)
+         pos +=length;
+
+   }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/WTDSFParser.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,976 @@
+/**
+ * Title: tn5250J
+ * Copyright:   Copyright (c) 2001
+ * 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.BOTTOM;
+import static org.tn5250j.TN5250jConstants.GUI_LEFT;
+import static org.tn5250j.TN5250jConstants.GUI_RIGHT;
+import static org.tn5250j.TN5250jConstants.LOWER_LEFT;
+import static org.tn5250j.TN5250jConstants.LOWER_RIGHT;
+import static org.tn5250j.TN5250jConstants.NO_GUI;
+import static org.tn5250j.TN5250jConstants.NR_REQUEST_ERROR;
+import static org.tn5250j.TN5250jConstants.UPPER;
+import static org.tn5250j.TN5250jConstants.UPPER_LEFT;
+import static org.tn5250j.TN5250jConstants.UPPER_RIGHT;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.tn5250j.encoding.ICodePage;
+import org.tn5250j.tools.logging.TN5250jLogFactory;
+import org.tn5250j.tools.logging.TN5250jLogger;
+
+/**
+ *
+ * Write To Display Structured Field:
+ *
+ * This module will parse the structured field information for enhanced
+ * emulation mode.
+ *
+ */
+public class WTDSFParser {
+
+   private Screen5250 screen52;
+   private tnvt vt;
+   private ICodePage codePage;
+   int pos;
+   byte[] segment;
+   int length;
+   boolean error;
+   boolean guiStructsExist;
+
+   private TN5250jLogger log = TN5250jLogFactory.getLogger(this.getClass());
+
+   private final List<Window> guiStructs = new ArrayList<Window>(3);
+   private final List<ChoiceField> choices = new ArrayList<ChoiceField>(3);
+
+
+   WTDSFParser (tnvt vt) {
+
+      this.vt = vt;
+      screen52 = vt.screen52;
+      codePage = vt.codePage;
+
+   }
+
+	protected class ChoiceField {
+
+		int x;
+		int y;
+      int row;
+      int col;
+		int width;
+		int height;
+		char mnemonic;
+		int fieldId;
+      int selectIndex;
+
+      ChoiceField(int row, int col, int fldRow, int fldCol) {
+         x = row;
+         y = col;
+         row = fldRow;
+         col = fldCol;
+      }
+	}
+
+   protected class Window {
+
+      byte[] window;
+      int pos;
+
+      Window(byte[] seg, int pos) {
+
+         //log.info("window created at " + pos);
+         window = seg;
+         this.pos = pos;
+         guiStructsExist = true;
+      }
+
+   }
+
+	protected void addChoiceField(int row,int col,int fldRow, int fldCol, String text) {
+
+		ChoiceField cf = new ChoiceField(row,col, fldRow, fldCol);
+		cf.fieldId = screen52.getScreenFields().getCurrentField().getFieldId();
+		choices.add(cf);
+
+	}
+
+   protected boolean isGuisExists () {
+
+      return guiStructsExist;
+
+   }
+
+   protected byte[] getSegmentAtPos(int pos) {
+      int len = guiStructs.size();
+      for (int x = 0; x < len; x++) {
+         Window w = guiStructs.get(x);
+         if (w.pos == pos)
+            return w.window;
+      }
+
+      return null;
+
+   }
+
+   protected void clearGuiStructs() {
+
+      guiStructs.clear();
+   }
+
+   protected boolean parseWriteToDisplayStructuredField(byte[] seg) {
+
+//      bk = vt.bk;
+
+      error = false;
+      boolean done = false;
+      boolean windowDefined = false;
+//      int nextone;
+      pos = 0;
+      segment = seg;
+
+//      try {
+         length = (( segment[pos++] & 0xff )<< 8 | (segment[pos++] & 0xff));
+
+         while (!done) {
+            int s =    segment[pos++] & 0xff;
+            switch (s) {
+
+               case 0xD9:     // Class Type 0xD9 - Create Window
+
+                  switch (segment[pos++]) {
+                     case 0x50:      // Define Selection Field
+
+                        defineSelectionField(length);
+                        done = true;
+                        break;
+                     case 0x51:      // Create Window
+
+                        guiStructs.add(new Window(segment, screen52.getLastPos()));
+
+                        boolean cr = false;
+                        int rows = 0;
+                        int cols = 0;
+                        // pull down not supported yet
+                        if ((segment[pos++] & 0x80) == 0x80)
+                           cr = true;  // restrict cursor
+                        pos++; // get reserved field pos 6
+                        pos++; // get reserved field pos 7
+                        rows = segment[pos++]; // get window depth rows pos 8
+                        cols = segment[pos++]; // get window width cols pos 9
+                        length -= 9;
+                        if (length == 0) {
+                           done = true;
+//                           System.out.println("Create Window");
+//                           System.out.println("   restrict cursor " + cr);
+//                           System.out.println(" Depth = " + rows + " Width = " + cols);
+//                           screen52.createWindow(rows,cols,1,true,32,58,
+                           createWindow(rows,cols,1,true,32,58,
+                                             '.',
+                                             '.',
+                                             '.',
+                                             ':',
+                                             ':',
+                                             ':',
+                                             '.',
+                                             ':');
+                           windowDefined = true;
+                           break;
+                        }
+
+                        // pos 10 is Minor Structure
+                        int ml = 0;
+                        int type = 0;
+                        int lastPos = screen52.getLastPos();
+//                        if (cr)
+//                           screen52.setPendingInsert(true,
+//                                          screen52.getCurrentRow(),
+//                                          screen52.getCurrentCol());
+                        int mAttr = 0;
+                        int cAttr = 0;
+
+                        while (length > 0) {
+
+                           // get minor length
+                           ml = ( segment[pos++] & 0xff );
+                           length -= ml;
+
+                           // only normal windows are supported at this time
+                           type = segment[pos++];
+
+                           switch (type) {
+
+                              case 0x01 : // Border presentation
+                                 boolean gui = false;
+                                 if ((segment[pos++] & 0x80) == 0x80)
+                                    gui = true;
+                                 mAttr = segment[pos++];
+                                 cAttr = segment[pos++];
+
+                                 char ul = '.';
+                                 char upper = '.';
+                                 char ur = '.';
+                                 char left = ':';
+                                 char right = ':';
+                                 char ll = ':';
+                                 char bottom = '.';
+                                 char lr = ':';
+
+                                 // if minor length is greater than 5 then
+                                 //    the border characters are specified
+                                 if (ml > 5) {
+                                    ul = codePage.ebcdic2uni(segment[pos++]);
+//                                    ul = getASCIIChar(segment[pos++]);
+                                    if (ul == 0)
+                                       ul = '.';
+
+                                    upper = codePage.ebcdic2uni(segment[pos++]);
+//                                    upper = getASCIIChar(segment[pos++]);
+                                    if (upper == 0)
+                                       upper = '.';
+
+                                    ur = codePage.ebcdic2uni(segment[pos++]);
+//                                    ur = getASCIIChar(segment[pos++]);
+                                    if (ur == 0)
+                                       ur = '.';
+
+                                    left = codePage.ebcdic2uni(segment[pos++]);
+//                                    left = getASCIIChar(segment[pos++]);
+                                    if (left == 0)
+                                       left = ':';
+
+                                    right = codePage.ebcdic2uni(segment[pos++]);
+//                                    right = getASCIIChar(segment[pos++]);
+                                    if (right == 0)
+                                       right = ':';
+
+                                    ll = codePage.ebcdic2uni(segment[pos++]);
+//                                    ll = getASCIIChar(segment[pos++]);
+                                    if (ll == 0)
+                                       ll = ':';
+
+                                    bottom = codePage.ebcdic2uni(segment[pos++]);
+//                                    bottom = getASCIIChar(segment[pos++]);
+                                    if (bottom == 0)
+                                       bottom = '.';
+
+                                    lr = codePage.ebcdic2uni(segment[pos++]);
+//                                    lr = getASCIIChar(segment[pos++]);
+                                    if (lr == 0)
+                                       lr = ':';
+                                 }
+
+//                                 System.out.println("Create Window");
+//                                 System.out.println("   restrict cursor " + cr);
+//                                 System.out.println("   Depth = " + rows + " Width = " + cols);
+//                                 System.out.println("   type = " + type + " gui = " + gui);
+//                                 System.out.println("   mono attr = " + mAttr + " color attr = " + cAttr);
+//                                 System.out.println("   ul = " + ul + " upper = " + upper +
+//                                                         " ur = " + ur +
+//                                                         " left = " + left +
+//                                                         " right = " + right +
+//                                                         " ll = " + ll +
+//                                                         " bottom = " + bottom +
+//                                                         " lr = " + lr
+//                                                         );
+//                                 screen52.createWindow(rows,cols,type,gui,mAttr,cAttr,
+                                       createWindow(rows,cols,type,gui,mAttr,cAttr,
+                                                      ul,
+                                                      upper,
+                                                      ur,
+                                                      left,
+                                                      right,
+                                                      ll,
+                                                      bottom,
+                                                      lr);
+                                 windowDefined = true;
+                              break;
+         //
+         //  The following shows the input for window with a title
+         //
+         //      +0000 019A12A0 00000400 00020411 00200107  .?.?..?...?..?.
+         //      +0010 00000018 00000011 06131500 37D95180  ........?.?..R??
+         //      +0020 00000A24 0D018023 23404040 40404040  ..??..???
+         //      +0030 40211000 000000D7 C2C1D9C4 C5D4D67A   \uFFFD.....PBARDEMO:
+         //      +0040 40D79996 879985A2 A2408281 99408485   Progress bar de
+         //      +0050 94961108 1520D5A4 94828599 40968640  mo.???Number of
+         //      +0060 8595A399 8985A24B 4B4B4B4B 4B7A2011  entries......:?.
+         //      +0070 082E2040 404040F5 F0F06BF0 F0F02011  ?.?    500,000?.
+         //      +0080 091520C3 A4999985 95A34085 95A399A8  \uFFFD??Current entry
+         //      +0090 4095A494 8285994B 4B4B7A20 11092E20   number...:?.\uFFFD.?
+         //      +00A0 40404040 4040F56B F0F0F020 110A1520        5,000?.???
+         //      +00B0 D9859481 89958995 87408595 A3998985  Remaining entrie
+         //      +00C0 A24B4B4B 4B4B4B7A 20110A2E 20404040  s......:?.?.?
+         //      +00D0 40F4F9F5 6BF0F0F0 20110C15 20E2A381   495,000?..??Sta
+         //      +00E0 99A340A3 8994854B 4B4B4B4B 4B4B4B4B  rt time.........
+         //      +00F0 4B4B4B4B 7A20110C 2F2040F7 7AF5F37A  ....:?...? 7:53:
+
+                              case 0x10 : // Window title/footer
+                                 if (!windowDefined) {
+//                                    screen52.createWindow(rows,cols,1,true,32,58,
+                                    guiStructs.add(new Window(segment, screen52.getLastPos()));
+                                          createWindow(rows,cols,1,true,32,58,
+                                                         '.',
+                                                         '.',
+                                                         '.',
+                                                         ':',
+                                                         ':',
+                                                         ':',
+                                                         '.',
+                                                         ':');
+                                    windowDefined = true;
+                                 }
+
+                                 byte orientation = segment[pos++];
+                                 mAttr = segment[pos++];
+                                 cAttr = segment[pos++];
+
+                                 //reserved
+                                 pos++;
+                                 ml -= 6;
+
+                                 StringBuffer hfBuffer = new StringBuffer(ml);
+                                 while (ml-- > 0) {
+                                    //LDC - 13/02/2003 - Convert it to unicode
+                                    hfBuffer.append(codePage.ebcdic2uni(segment[pos++]));
+//                                    hfBuffer.append(getASCIIChar(segment[pos++]));
+
+                                 }
+
+                                 log.debug(
+                                    " orientation " + Integer.toBinaryString(orientation) +
+                                    " mAttr " + mAttr +
+                                    " cAttr " + cAttr +
+                                    " Header/Footer " + hfBuffer);
+                                 screen52.writeWindowTitle(lastPos,
+                                                            rows,
+                                                            cols,
+                                                            orientation,
+                                                            mAttr,
+                                                            cAttr,
+                                                            hfBuffer);
+                                 break;
+                              default:
+                            	  log.warn("Invalid Window minor structure");
+                              length = 0;
+                              done = true;
+                           }
+
+                        }
+
+                        done = true;
+
+                        break;
+
+                     case 0x53:      // Scroll Bar
+                        int sblen = 15;
+                        byte sbflag = segment[pos++];  // flag position 5
+
+                        pos++;  // reserved position 6
+
+                        // position 7,8
+                        int totalRowScrollable =  (( segment[pos++] & 0xff )<< 8
+                                                | (segment[pos++] & 0xff));
+
+                        // position 9,10
+                        int totalColScrollable =  (( segment[pos++] & 0xff )<< 8
+                                                | (segment[pos++] & 0xff));
+
+                        // position 11,12
+                        int sliderRowPos =  (( segment[pos++] & 0xff )<< 8
+                                                | (segment[pos++] & 0xff));
+
+                        // position 13,14
+                        int sliderColPos =  (( segment[pos++] & 0xff )<< 8
+                                                | (segment[pos++] & 0xff));
+
+                        // position 15
+                        int sliderRC = segment[pos++];
+
+                        screen52.createScrollBar(sbflag,totalRowScrollable,
+                                                   totalColScrollable,
+                                                   sliderRowPos,
+                                                   sliderColPos,
+                                                   sliderRC);
+                        length -= 15;
+
+                        done = true;
+
+                        break;
+
+                     case 0x5B:      // Remove GUI ScrollBar field
+
+                        pos++; // reserved must be set to off pos 5
+                        pos++; // reserved must be set to zero pos 6
+
+                        done = true;
+                        break;
+
+                     case 0x5F:      // Remove All GUI Constructs
+                        log.info("remove all gui contructs");
+                        clearGuiStructs();
+                        guiStructsExist = false;
+                        int len = 4;
+                        int d = 0;
+                        length -= s;
+                        while (--len > 0)
+                           d = segment[pos++];
+//                        if (length > 0) {
+//                           len = (segment[pos++] & 0xff )<< 8;
+//
+//                           while (--len > 0)
+//                              d = segment[pos++];
+//                        }
+
+                        screen52.clearGuiStuff();
+                        // per 14.6.13.4 documentation we should clear the
+                        //    format table after this command
+                        screen52.clearTable();
+                        done = true;
+                        break;
+                     case 0x59:	// remove gui window
+                        log.info(" remove window at " + screen52.getCurrentPos());
+                        done = true;
+                        break;
+
+                     case 0x60:      // Erase/Draw Grid Lines - not supported
+                                    // do not know what they are
+                                    // as of 03/11/2002 we should not be getting
+                                    // this anymore but I will leave it here
+                                    //  just in case.
+//                        System.out.println("erase/draw grid lines " + length);
+                        len = 6;
+                        d = 0;
+                        length -= 9;
+                        while (--len > 0)
+                           d = segment[pos++];
+                           if (length > 0) {
+                              len = (segment[pos++] & 0xff )<< 8;
+
+                           while (--len > 0) {
+                              d = segment[pos++];
+                           }
+                        }
+                        done = true;
+                        break;
+                     default:
+                        vt.sendNegResponse(NR_REQUEST_ERROR,0x03,0x01,0x01,"invalid wtd structured field sub command "
+                                                   + ( pos - 1));
+//                                                   + bk.getByteOffset(-1));
+                        error = true;
+                        break;
+                  }
+                  break;
+
+               default:
+                  vt.sendNegResponse(NR_REQUEST_ERROR,0x03,0x01,0x01,
+                              "invalid wtd structured field command "
+                               + (pos - 1));
+//                               + bk.getByteOffset(-1));
+                  error = true;
+                  break;
+            }
+
+            if (error)
+               done = true;
+
+         }
+//      }
+//      catch (Exception e) {};
+
+      return error;
+
+   }
+
+	/**
+	 * 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 lastPos = screen52.getLastPos();
+	   int numCols = screen52.getColumns();
+
+		int c = screen52.getCol(lastPos);
+		int w = 0;
+		width++;
+
+		w = width;
+		char initChar = Screen5250.initChar;
+		int initAttr = Screen5250.initAttr;
+
+		// set leading attribute byte
+		screen52.setScreenCharAndAttr(initChar, initAttr, true);
+
+		// set upper left
+		if (gui) {
+			screen52.setScreenCharAndAttr((char) ul, colorAttr, UPPER_LEFT, false);
+		}
+		else {
+			screen52.setScreenCharAndAttr((char) ul, colorAttr, false);
+		}
+
+		// draw top row
+		while (w-- >= 0) {
+			if (gui) {
+				screen52.setScreenCharAndAttr((char) upper, colorAttr, UPPER,false);
+			}
+			else {
+				screen52.setScreenCharAndAttr((char) upper, colorAttr, false);
+			}
+		}
+
+		// set upper right
+		if (gui) {
+			screen52.setScreenCharAndAttr((char) ur, colorAttr, UPPER_RIGHT, false);
+		}
+		else {
+			screen52.setScreenCharAndAttr((char) ur, colorAttr, false);
+
+		}
+
+		// set ending attribute byte
+		screen52.setScreenCharAndAttr(initChar, initAttr, true);
+
+		lastPos = ((screen52.getRow(lastPos) + 1) * numCols) + c;
+		screen52.goto_XY(lastPos);
+
+		// now handle body of window
+		while (depth-- > 0) {
+
+			// set leading attribute byte
+			screen52.setScreenCharAndAttr(initChar, initAttr, true);
+			// set left
+			if (gui) {
+				screen52.setScreenCharAndAttr((char) left, colorAttr, GUI_LEFT, false);
+			}
+			else {
+				screen52.setScreenCharAndAttr((char) left, colorAttr, false);
+
+			}
+
+			w = width - 2;
+		   screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, true);
+			// fill it in
+			while (w-- >= 0) {
+//			   if (!planes.isUseGui(screen52.getLastPos()))
+			   screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, false);
+			}
+			screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, true);
+
+			// set right
+			if (gui) {
+				screen52.setScreenCharAndAttr((char) right, colorAttr, GUI_RIGHT, false);
+
+			}
+			else {
+				screen52.setScreenCharAndAttr((char) right, colorAttr, false);
+
+			}
+
+			screen52.setScreenCharAndAttr(initChar, initAttr, true);
+
+			lastPos = ((screen52.getRow(lastPos) + 1) * numCols) + c;
+			screen52.goto_XY(lastPos);
+		}
+
+		// set leading attribute byte
+		screen52.setScreenCharAndAttr(initChar, initAttr, true);
+		if (gui) {
+			screen52.setScreenCharAndAttr((char) ll, colorAttr, LOWER_LEFT, false);
+
+		}
+		else {
+			screen52.setScreenCharAndAttr((char) ll, colorAttr, false);
+
+		}
+		w = width;
+
+		// draw bottom row
+		while (w-- >= 0) {
+			if (gui) {
+				screen52.setScreenCharAndAttr((char) bottom, colorAttr, BOTTOM, false);
+			}
+			else {
+				screen52.setScreenCharAndAttr((char) bottom, colorAttr, false);
+
+			}
+		}
+
+		// set lower right
+		if (gui) {
+			screen52.setScreenCharAndAttr((char) lr, colorAttr, LOWER_RIGHT, false);
+		}
+		else {
+			screen52.setScreenCharAndAttr((char) lr, colorAttr, false);
+		}
+
+		// set ending attribute byte
+		screen52.setScreenCharAndAttr(initChar, initAttr, true);
+
+	}
+
+/* *** NEVER USED LOCALLY ************************************************** */
+//	private void clearWindowBody(ScreenPlanes planes, int startPos, int depth, int width) {
+//
+//	   int lastPos = startPos;
+//		char initChar = Screen5250.initChar;
+//		int initAttr = Screen5250.initAttr;
+//
+//		// 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();
+//
+//			int 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);
+//				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 = startPos;
+//		}
+//
+//	}
+
+/* *** NEVER USED LOCALLY ************************************************** */
+//	private void setDirty(int pos) {
+//
+//	   screen52.setDirty(pos);
+//
+//	}
+
+/* *** NEVER USED LOCALLY ************************************************** */
+//	private void advancePos() {
+//
+//	   screen52.advancePos();
+//	}
+
+   private void defineSelectionField(int majLen) {
+
+      //   0030:  20 00 2C 3E 00 00 00 69 12 A0 00 00 04 00 00 03  .,>...i........
+      //   0040:  04 40 04 11 00 28 01 07 00 00 00 19 00 00 04 11 .@...(..........
+      //   0050:  14 19 15 00 48 D9 50 00 60 00 11 01 84 84 00 00 ....H.P.`.......
+      //   0060:  05 03 01 01 00 00 00 13 01 E0 00 21 00 21 00 3B ...........!.!.;
+      //   0070:  22 20 20 20 20 3A 24 20 20 3A 0B 10 08 00 E0 00 "    :$  :......
+      //   0080:  D6 95 85 40 40 0B 10 08 00 E0 00 E3 A6 96 40 40 ...@@.........@@
+      //   0090:  0B 10 08 00 E0 00 E3 88 99 85 85 04 52 00 00 FF ............R...
+      //   00A0:  EF                                              .
+      try {
+         int flag1 = segment[pos++];    // Flag byte 1 - byte 5
+         int flag2 = segment[pos++];    // Flag byte 2 - byte 6
+         int flag3 = segment[pos++];    // Flag byte 3 - byte 7
+         int typeSelection = segment[pos++];    // Type of selection Field - byte 8
+
+         // GUI Device Characteristics:
+         //    This byte is used if the target device is a GUI PWS or a GUI-like
+         //    NWS.  If neigher of these WS are the targets, this byte is ignored
+         int guiDevice = segment[pos++];    // byte 9
+         int withMnemonic = segment[pos++];    //  byte 10
+         int noMnemonic = segment[pos++];    // byte 11
+
+         pos++;    // Reserved - byte 12
+         pos++;    // Reserved - byte 13
+
+         int cols = segment[pos++];    // Text Size - byte 14
+         int rows = segment[pos++];    // Rows - byte 15
+
+         int maxColChoice = segment[pos++];    // byte 16 num of column choices
+         int padding = segment[pos++];    // byte 17
+         int numSepChar = segment[pos++];    // byte 18
+         int ctySepChar = segment[pos++];    // byte 19
+         int cancelAID = segment[pos++];    // byte 20
+
+         int cnt = 0;
+         int minLen = 0;
+         majLen -= 21;
+         log.debug(" row: " + screen52.getCurrentRow()
+                              + " col: " + screen52.getCurrentCol()
+                              + " type " + typeSelection
+                              + " gui " + guiDevice
+                              + " withMnemonic " + Integer.toHexString(withMnemonic & 0xf0)
+                              + " noMnemonic " + Integer.toHexString(noMnemonic & 0xf0)
+                              + " noMnemonic " + Integer.toBinaryString(noMnemonic)
+                              + " noMnemonicType " + Integer.toBinaryString((noMnemonic & 0xf0))
+                              + " noMnemonicSel " + Integer.toBinaryString((noMnemonic & 0x0f))
+                              + " maxcols " + maxColChoice
+                              + " cols " + cols
+                              + " rows " + rows);
+         int rowCtr = 0;
+         int colCtr = 0;
+         int chcRowStart = screen52.getCurrentRow();
+         int chcColStart = screen52.getCurrentCol();
+         int chcRow = chcRowStart;
+         int chcCol = chcColStart;
+         int chcPos = screen52.getPos(chcRow-1,chcCol);
+
+// client access
+//0000   00 04 ac 9e b9 35 00 01 02 32 bb 4e 08 00 45 00  .....5...2.N..E.
+//0010   00 3c 4f 8e 40 00 80 06 00 00 c1 a8 33 58 c1 a8  .<O.@.......3X..
+//0020   33 01 09 e4 00 17 5b bf b7 a4 c3 41 43 d1 50 18  3.....[....AC.P.
+//0030   fc de e9 d8 00 00 00 12 12 a0 00 00 04 00 80 03  ................
+//0040   16 18 f1 11 14 1a 00 22 ff ef                    ......."..
+
+         int colAvail = 0x20;
+         int colSelAvail = 0x20;
+         int fld = 0;
+
+         do {
+            minLen = segment[pos++];    // Minor Length byte 21
+
+            int minType = segment[pos++];    // Minor Type
+
+            switch (minType) {
+
+               case 0x01:  // Choice Presentation Display
+
+                  // flag
+                  int flagCP1 = segment[pos++];
+
+                  pos++; // mon select cursor avail emphasis - byte4
+                  colSelAvail = segment[pos++];  // -byte 5
+
+                  pos++; // mon select cursor - byte 6
+                  int colSelCur = segment[pos++];  // -byte 7
+
+                  pos++; // mon select cursor not avail emphasis - byte 8
+                  int colSelNotAvail = segment[pos++];  // -byte 9
+
+                  pos++; // mon avail emphasis - byte 10
+                  colAvail = segment[pos++];  // -byte 11
+
+                  pos++; // mon select emphasis - byte 12
+                  int colSel = segment[pos++];  // -byte 13
+
+                  pos++; // mon not avail emphasis - byte 14
+                  int colNotAvail = segment[pos++];  // -byte 15
+
+                  pos++; // mon indicator emphasis - byte 16
+                  int colInd = segment[pos++];  // -byte 17
+
+                  pos++; // mon indicator not avail emphasis - byte 18
+                  int colNotAvailInd = segment[pos++];  // -byte 19
+
+                  break;
+
+               case 0x10:  // Choice Text minor structure
+
+                  cnt = 5;
+                  int flagCT1 = segment[pos++];
+                  int flagCT2 = segment[pos++];
+                  int flagCT3 = segment[pos++];
+                  int mnemOffset = 0;
+                  boolean aid = false;
+                  boolean selected = false;
+
+                  // is in selected state
+                  if ((flagCT1 & 0x40) == 0x40) {
+                	  log.debug(" selected ");
+                     selected = true;
+                  }
+
+                  //System.out.println(Integer.toBinaryString((flagCT1 & 0xf0)));
+                  // is mnemonic offset specified
+                  if ((flagCT1 & 0x08) == 8) {
+                	 log.debug(" mnemOffset " + mnemOffset);
+                     mnemOffset = segment[pos++];
+                     cnt++;
+                  }
+
+                  // is aid key specified
+                  if ((flagCT1 & 0x04) == 4) {
+
+                     aid = true;
+                     log.debug(" aidKey " + aid);
+//                     cnt++;
+                  }
+
+                  // is single digit number specified
+                  if ((flagCT1 & 0x01) == 0x01) {
+                	 log.debug(" single digit " );
+                     pos++;
+                     cnt++;
+                  }
+
+                  // is double digint number specified
+                  if ((flagCT1 & 0x02) == 0x02) {
+                	 log.debug(" double digit " );
+
+                     pos++;
+                     cnt++;
+                  }
+
+                  String s = "";
+                  byte byte0 = 0;
+                  fld++;
+
+                  screen52.setCursor(chcRowStart,chcColStart);
+
+                  // we do not add a selection if it is marked as unavailable
+                  if ((flagCT1 & 0x80) != 0x80) {
+                     screen52.addField(0x26,1,0,0,0,0);
+                     screen52.getScreenFields().getCurrentField().setFieldChar('.');
+                     screen52.getScreenFields().getCurrentField().setSelectionFieldInfo(17,
+                                 fld,
+                                 chcPos);
+                     screen52.setCursor(chcRowStart,chcColStart + 3);
+
+                     for (;cnt < minLen; cnt++) {
+
+                        byte0 = segment[pos++];
+                        s += vt.codePage.ebcdic2uni(byte0);
+                        screen52.setChar(vt.codePage.ebcdic2uni(byte0));
+
+                     }
+
+                     addChoiceField(chcRowStart,chcColStart,chcRow,chcCol,s);
+                  }
+
+//         screen52.getScreenFields().getCurrentField().setMDT();
+
+                  log.debug(s + " selected " + selected);
+//                  chcRowStart;
+                  //maxColChoice
+                  colCtr++;
+//                  rowCtr++;
+                  if (colCtr >= maxColChoice) {
+
+                     rowCtr++;
+                     colCtr=0;
+                     chcColStart = chcCol;
+                     chcRowStart = chcRow + rowCtr;
+                     if (rowCtr > rows) {
+                        chcRowStart = chcRow;
+                        rowCtr = 0;
+                        chcColStart = chcColStart + 3 + cols + padding;
+                     }
+                  }
+                  else {
+                     chcColStart = chcColStart + padding + cols + 3;
+//
+                  }
+
+                  break;
+               default:
+                  for (cnt = 2;cnt < minLen; cnt++) {
+
+                     pos++;
+                  }
+
+            }
+
+            majLen -= minLen;
+
+         }  while (majLen > 0);
+      }
+      catch (Exception exc) {
+    	 log.warn(" defineSelectionField :", exc);
+         exc.printStackTrace();
+      }
+   }
+
+   // negotiating commands
+//   private static final byte IAC = (byte)-1; // 255  FF
+//   private static final byte DONT = (byte)-2; //254  FE
+//   private static final byte DO = (byte)-3; //253    FD
+//   private static final byte WONT = (byte)-4; //252  FC
+//   private static final byte WILL = (byte)-5; //251  FB
+//   private static final byte SB = (byte)-6; //250 Sub Begin  FA
+//   private static final byte SE = (byte)-16; //240 Sub End   F0
+//   private static final byte EOR = (byte)-17; //239 End of Record  EF
+//   private static final byte TERMINAL_TYPE = (byte)24;     // 18
+//   private static final byte OPT_END_OF_RECORD = (byte)25;  // 19
+//   private static final byte TRANSMIT_BINARY = (byte)0;     // 0
+//   private static final byte QUAL_IS = (byte)0;             // 0
+//   private static final byte TIMING_MARK = (byte)6;         // 6
+//   private static final byte NEW_ENVIRONMENT = (byte)39;         // 27
+//   private static final byte IS = (byte)0;         // 0
+//   private static final byte SEND = (byte)1;         // 1
+//   private static final byte INFO = (byte)2;         // 2
+//   private static final byte VAR = (byte)0;         // 0
+//   private static final byte VALUE = (byte)1;         // 1
+//   private static final byte NEGOTIATE_ESC = (byte)2;         // 2
+//   private static final byte USERVAR = (byte)3;         // 3
+
+   // miscellaneous
+//   private static final byte ESC = 0x04; // 04
+//   private static final char char0 = 0;
+
+//   private static final byte CMD_READ_IMMEDIATE_ALT = (byte)0x83; // 131
+
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/tn5250/tnvt.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,2844 @@
+/**
+ * Title: tnvt.java
+ * Copyright: Copyright (c) 2001 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.AID_HELP;
+import static org.tn5250j.TN5250jConstants.AID_PRINT;
+import static org.tn5250j.TN5250jConstants.CMD_CLEAR_FORMAT_TABLE;
+import static org.tn5250j.TN5250jConstants.CMD_CLEAR_UNIT;
+import static org.tn5250j.TN5250jConstants.CMD_CLEAR_UNIT_ALTERNATE;
+import static org.tn5250j.TN5250jConstants.CMD_READ_INPUT_FIELDS;
+import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_FIELDS;
+import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_IMMEDIATE_ALT;
+import static org.tn5250j.TN5250jConstants.CMD_READ_SCREEN_IMMEDIATE;
+import static org.tn5250j.TN5250jConstants.CMD_READ_SCREEN_TO_PRINT;
+import static org.tn5250j.TN5250jConstants.CMD_RESTORE_SCREEN;
+import static org.tn5250j.TN5250jConstants.CMD_ROLL;
+import static org.tn5250j.TN5250jConstants.CMD_SAVE_SCREEN;
+import static org.tn5250j.TN5250jConstants.CMD_WRITE_ERROR_CODE;
+import static org.tn5250j.TN5250jConstants.CMD_WRITE_ERROR_CODE_TO_WINDOW;
+import static org.tn5250j.TN5250jConstants.CMD_WRITE_STRUCTURED_FIELD;
+import static org.tn5250j.TN5250jConstants.CMD_WRITE_TO_DISPLAY;
+import static org.tn5250j.TN5250jConstants.NR_REQUEST_ERROR;
+import static org.tn5250j.TN5250jConstants.PF1;
+import static org.tn5250j.TN5250jConstants.PF10;
+import static org.tn5250j.TN5250jConstants.PF11;
+import static org.tn5250j.TN5250jConstants.PF12;
+import static org.tn5250j.TN5250jConstants.PF13;
+import static org.tn5250j.TN5250jConstants.PF14;
+import static org.tn5250j.TN5250jConstants.PF15;
+import static org.tn5250j.TN5250jConstants.PF16;
+import static org.tn5250j.TN5250jConstants.PF17;
+import static org.tn5250j.TN5250jConstants.PF18;
+import static org.tn5250j.TN5250jConstants.PF19;
+import static org.tn5250j.TN5250jConstants.PF2;
+import static org.tn5250j.TN5250jConstants.PF20;
+import static org.tn5250j.TN5250jConstants.PF21;
+import static org.tn5250j.TN5250jConstants.PF22;
+import static org.tn5250j.TN5250jConstants.PF23;
+import static org.tn5250j.TN5250jConstants.PF24;
+import static org.tn5250j.TN5250jConstants.PF3;
+import static org.tn5250j.TN5250jConstants.PF4;
+import static org.tn5250j.TN5250jConstants.PF5;
+import static org.tn5250j.TN5250jConstants.PF6;
+import static org.tn5250j.TN5250jConstants.PF7;
+import static org.tn5250j.TN5250jConstants.PF8;
+import static org.tn5250j.TN5250jConstants.PF9;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.Properties;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import javax.net.ssl.SSLSocket;
+import javax.swing.SwingUtilities;
+
+import org.tn5250j.Session5250;
+import org.tn5250j.TN5250jConstants;
+import org.tn5250j.encoding.CharMappings;
+import org.tn5250j.encoding.ICodePage;
+import org.tn5250j.framework.transport.SocketConnector;
+import org.tn5250j.tools.logging.TN5250jLogFactory;
+import org.tn5250j.tools.logging.TN5250jLogger;
+
+public final class tnvt implements Runnable {
+
+
+	// negotiating commands
+	private static final byte IAC = (byte) -1; // 255 FF
+	private static final byte DONT = (byte) -2; //254 FE
+	private static final byte DO = (byte) -3; //253 FD
+	private static final byte WONT = (byte) -4; //252 FC
+	private static final byte WILL = (byte) -5; //251 FB
+	private static final byte SB = (byte) -6; //250 Sub Begin FA
+	private static final byte SE = (byte) -16; //240 Sub End F0
+	private static final byte EOR = (byte) -17; //239 End of Record EF
+	private static final byte TERMINAL_TYPE = (byte) 24; // 18
+	private static final byte OPT_END_OF_RECORD = (byte) 25; // 19
+	private static final byte TRANSMIT_BINARY = (byte) 0; // 0
+	private static final byte QUAL_IS = (byte) 0; // 0
+	private static final byte TIMING_MARK = (byte) 6; // 6
+	private static final byte NEW_ENVIRONMENT = (byte) 39; // 27
+	private static final byte IS = (byte) 0; // 0
+	private static final byte SEND = (byte) 1; // 1
+	private static final byte INFO = (byte) 2; // 2
+	private static final byte VAR = (byte) 0; // 0
+	private static final byte VALUE = (byte) 1; // 1
+	private static final byte NEGOTIATE_ESC = (byte) 2; // 2
+	private static final byte USERVAR = (byte) 3; // 3
+
+	// miscellaneous
+	private static final byte ESC = 0x04; // 04
+
+	private Socket sock;
+	private BufferedInputStream bin;
+	private BufferedOutputStream bout;
+	private final BlockingQueue<Object> dsq = new ArrayBlockingQueue<Object>(25);
+	private Stream5250 bk;
+	private DataStreamProducer producer;
+	protected Screen5250 screen52;
+	private boolean waitingForInput;
+	private boolean invited;
+	private boolean negotiated = false;
+	private Thread me;
+	private Thread pthread;
+	private int readType;
+	private boolean enhanced = true;
+	private Session5250 controller;
+	private boolean cursorOn = false;
+	private String session = "";
+	private int port = 23;
+	private boolean connected = false;
+	private boolean support132 = true;
+	private ByteArrayOutputStream baosp = null;
+	private ByteArrayOutputStream baosrsp = null;
+	private int devSeq = -1;
+	private String devName;
+	private String devNameUsed;
+	private KbdTypesCodePages kbdTypesCodePage;
+	// WVL - LDC : TR.000300 : Callback scenario from 5250
+	private boolean scan; // = false;
+	private static int STRSCAN = 1;
+	// WVL - LDC : 05/08/2005 : TFX.006253 - support STRPCCMD
+	private boolean strpccmd; // = false;
+	private String user;
+	private String password;
+	private String library;
+	private String initialMenu;
+	private String program;
+	private boolean keepTrucking = true;
+	private boolean pendingUnlock = false;
+	private boolean[] dataIncluded;
+	protected ICodePage codePage;
+	private boolean firstScreen;
+	private String sslType;
+	private WTDSFParser sfParser;
+
+	private final TN5250jLogger log = TN5250jLogFactory.getLogger(this.getClass());
+
+	/**
+	 * @param session
+	 * @param screen52
+	 * @param type
+	 * @param support132
+	 */
+	public tnvt(Session5250 session, Screen5250 screen52, boolean type, boolean support132) {
+
+		controller = session;
+		if (log.isInfoEnabled()) {
+			log.info(" new session -> " + controller.getSessionName());
+		}
+
+		enhanced = type;
+		this.support132 = support132;
+		setCodePage("37");
+		this.screen52 = screen52;
+		dataIncluded = new boolean[24];
+
+		if (System.getProperties().containsKey("SESSION_CONNECT_USER")) {
+			user = System.getProperties().getProperty("SESSION_CONNECT_USER");
+			if (System.getProperties().containsKey("SESSION_CONNECT_PASSWORD"))
+				password = System.getProperties().getProperty(
+				"SESSION_CONNECT_PASSWORD");
+			if (System.getProperties().containsKey("SESSION_CONNECT_LIBRARY"))
+				library = System.getProperties().getProperty(
+				"SESSION_CONNECT_LIBRARY");
+			if (System.getProperties().containsKey("SESSION_CONNECT_MENU"))
+				initialMenu = System.getProperties().getProperty(
+				"SESSION_CONNECT_MENU");
+			if (System.getProperties().containsKey("SESSION_CONNECT_PROGRAM"))
+				program = System.getProperties().getProperty(
+				"SESSION_CONNECT_PROGRAM");
+		}
+
+		baosp = new ByteArrayOutputStream();
+		baosrsp = new ByteArrayOutputStream();
+	}
+
+	public String getHostName() {
+
+		return session;
+	}
+
+
+	public void setSSLType(String type) {
+		sslType = type;
+	}
+
+	public void setDeviceName(String name) {
+
+		devName = name;
+
+	}
+
+	public String getDeviceName() {
+		return devName;
+	}
+
+	public String getAllocatedDeviceName() {
+		return devNameUsed;
+	}
+
+	public boolean isConnected() {
+
+		return connected;
+	}
+
+	/**
+	 * @return true when SSL is used and socket is connected.
+	 * @see {@link #isConnected()}
+	 */
+	public boolean isSslSocket() {
+		if (this.connected && this.sock != null && this.sock instanceof SSLSocket) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	public final void setProxy(String proxyHost, String proxyPort) {
+
+		Properties systemProperties = System.getProperties();
+		systemProperties.put("socksProxySet", "true");
+		systemProperties.put("socksProxyHost", proxyHost);
+		systemProperties.put("socksProxyPort", proxyPort);
+
+		System.setProperties(systemProperties);
+		log.info(" socks set ");
+	}
+
+	public final boolean connect() {
+
+		return connect(session, port);
+
+	}
+
+
+	public final boolean connect(String s, int port) {
+
+		// We will now see if there are any bypass signon parameters to be
+		//    processed. The system properties override these parameters so
+		//    have precidence if specified.
+		Properties props = controller.getConnectionProperties();
+		if (user == null && props.containsKey("SESSION_CONNECT_USER")) {
+			user = props.getProperty("SESSION_CONNECT_USER");
+			log.info(" user -> " + user + " " + controller.getSessionName());
+			if (props.containsKey("SESSION_CONNECT_PASSWORD"))
+				password = props.getProperty("SESSION_CONNECT_PASSWORD");
+			if (props.containsKey("SESSION_CONNECT_LIBRARY"))
+				library = props.getProperty("SESSION_CONNECT_LIBRARY");
+			if (props.containsKey("SESSION_CONNECT_MENU"))
+				initialMenu = props.getProperty("SESSION_CONNECT_MENU");
+			if (props.containsKey("SESSION_CONNECT_PROGRAM"))
+				program = props.getProperty("SESSION_CONNECT_PROGRAM");
+		}
+
+
+		try {
+			session = s;
+			this.port = port;
+
+			try {
+				SwingUtilities.invokeAndWait(new Runnable() {
+					public void run() {
+						screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+								ScreenOIA.OIA_LEVEL_INPUT_INHIBITED,"X - Connecting");
+					}
+				});
+
+			} catch (Exception exc) {
+				log.warn("setStatus(ON) " + exc.getMessage());
+
+			}
+
+			//         sock = new Socket(s, port);
+			//smk - For SSL compability
+			SocketConnector sc = new SocketConnector();
+			if (sslType != null)
+				sc.setSSLType(sslType);
+			sock = sc.createSocket(s, port);
+
+			if (sock == null) {
+				log.warn("I did not get a socket");
+				disconnect();
+				return false;
+			}
+
+			connected = true;
+			// used for JDK1.3
+			sock.setKeepAlive(true);
+			sock.setTcpNoDelay(true);
+			sock.setSoLinger(false, 0);
+			InputStream in = sock.getInputStream();
+			OutputStream out = sock.getOutputStream();
+
+			bin = new BufferedInputStream(in, 8192);
+			bout = new BufferedOutputStream(out);
+
+			byte abyte0[];
+			while (negotiate(abyte0 = readNegotiations()));
+			negotiated = true;
+			try {
+				screen52.setCursorActive(false);
+			} catch (Exception excc) {
+				log.warn("setCursorOff " + excc.getMessage());
+
+			}
+
+			producer = new DataStreamProducer(this, bin, dsq, abyte0);
+			pthread = new Thread(producer);
+			//         pthread.setPriority(pthread.MIN_PRIORITY);
+			pthread.setPriority(Thread.NORM_PRIORITY);
+			//			pthread.setPriority(Thread.NORM_PRIORITY / 2);
+			pthread.start();
+
+			try {
+				SwingUtilities.invokeAndWait(new Runnable() {
+					public void run() {
+						screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED,
+								ScreenOIA.OIA_LEVEL_INPUT_INHIBITED);
+					}
+				});
+
+			} catch (Exception exc) {
+				log.warn("setStatus(OFF) " + exc.getMessage());
+			}
+
+			keepTrucking = true;
+			me = new Thread(this);
+			me.start();
+
+		} catch (Exception exception) {
+			if (exception.getMessage() == null)
+				exception.printStackTrace();
+			log.warn("connect() " + exception.getMessage());
+
+			if (sock == null)
+				log.warn("I did not get a socket");
+
+			disconnect();
+			return false;
+		}
+		return true;
+
+	}
+
+	public final boolean disconnect() {
+
+		// Added by LUC - LDC to fix a null pointer exception.
+		if (!connected) {
+			screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+					ScreenOIA.OIA_LEVEL_INPUT_INHIBITED,"X - Disconnected");
+			return false;
+		}
+
+		if (me != null && me.isAlive()) {
+			me.interrupt();
+			keepTrucking = false;
+			pthread.interrupt();
+		}
+
+		screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+				ScreenOIA.OIA_LEVEL_INPUT_INHIBITED,"X - Disconnected");
+		screen52.getOIA().setKeyBoardLocked(false);
+		pendingUnlock = false;
+
+		try {
+			if (sock != null) {
+				log.info("Closing socket");
+				sock.close();
+			}
+			if (bin != null)
+				bin.close();
+			if (bout != null)
+				bout.close();
+			connected = false;
+			firstScreen = false;
+
+			// WVL - LDC : TR.000345 : properly disconnect and clear screen
+			// Is this the right place to set screen realestate on disconnect?
+			//controller.getScreen().clearAll();
+			screen52.goto_XY(0);
+			screen52.setCursorActive(false);
+			screen52.clearAll();
+			screen52.restoreScreen();
+
+			controller.fireSessionChanged(TN5250jConstants.STATE_DISCONNECTED);
+
+		} catch (Exception exception) {
+			log.warn(exception.getMessage());
+			connected = false;
+			devSeq = -1;
+			return false;
+
+		}
+		devSeq = -1;
+		return true;
+	}
+
+	private final ByteArrayOutputStream appendByteStream(byte abyte0[]) {
+		ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
+		for (int i = 0; i < abyte0.length; i++) {
+			bytearrayoutputstream.write(abyte0[i]);
+			if (abyte0[i] == -1)
+				bytearrayoutputstream.write(-1);
+		}
+
+		return bytearrayoutputstream;
+	}
+
+	private final byte[] readNegotiations() throws IOException {
+		int i = bin.read();
+		if (i < 0) {
+			throw new IOException("Connection closed.");
+		} else {
+			int j = bin.available();
+			byte abyte0[] = new byte[j + 1];
+			abyte0[0] = (byte) i;
+			bin.read(abyte0, 1, j);
+			return abyte0;
+		}
+	}
+
+	private final void writeByte(byte abyte0[]) throws IOException {
+
+		bout.write(abyte0);
+		bout.flush();
+	}
+
+	//	private final void writeByte(byte byte0) throws IOException {
+	//
+	//		bout.write(byte0);
+	//		bout.flush();
+	//	}
+
+	public final void sendHeartBeat() throws IOException {
+
+		byte[] b = { (byte) 0xff, (byte) 0xf1 };
+		bout.write(b);
+		bout.flush();
+	}
+
+	private final void readImmediate(int readType) {
+
+		if (screen52.isStatusErrorCode()) {
+			screen52.restoreErrorLine();
+			screen52.setStatus(Screen5250.STATUS_ERROR_CODE,
+					Screen5250.STATUS_VALUE_OFF, null);
+		}
+
+		if (!enhanced) {
+			screen52.setCursorActive(false);
+		}
+		//		screen52.setStatus(Screen5250.STATUS_SYSTEM,
+		//				Screen5250.STATUS_VALUE_ON, null);
+		screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+				ScreenOIA.OIA_LEVEL_INPUT_INHIBITED);
+
+		screen52.getOIA().setKeyBoardLocked(true);
+		pendingUnlock = false;
+		invited = false;
+
+		screen52.getScreenFields().readFormatTable(baosp, readType, codePage);
+
+		try {
+
+			writeGDS(0, 3, baosp.toByteArray());
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+			baosp.reset();
+		}
+		baosp.reset();
+
+	}
+
+	public final boolean sendAidKey(int aid) {
+
+		if (screen52.isStatusErrorCode()) {
+			screen52.restoreErrorLine();
+			screen52.setStatus(Screen5250.STATUS_ERROR_CODE,
+					Screen5250.STATUS_VALUE_OFF, null);
+		}
+
+		if (!enhanced) {
+			screen52.setCursorActive(false);
+		}
+		//		screen52.setStatus(Screen5250.STATUS_SYSTEM,
+		//				Screen5250.STATUS_VALUE_ON, null);
+		screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+				ScreenOIA.OIA_LEVEL_INPUT_INHIBITED);
+
+		screen52.getOIA().setKeyBoardLocked(true);
+		pendingUnlock = false;
+		invited = false;
+		baosp.write(screen52.getCurrentRow());
+		baosp.write(screen52.getCurrentCol());
+		baosp.write(aid);
+
+		if (dataIncluded(aid))
+
+			screen52.getScreenFields().readFormatTable(baosp, readType,
+					codePage);
+
+		try {
+
+			writeGDS(0, 3, baosp.toByteArray());
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+			baosp.reset();
+			return false;
+		}
+		baosp.reset();
+		return true;
+
+	}
+
+	private boolean dataIncluded(int aid) {
+
+		switch (aid) {
+
+		case PF1:
+			return !dataIncluded[0];
+		case PF2:
+			return !dataIncluded[1];
+		case PF3:
+			return !dataIncluded[2];
+		case PF4:
+			return !dataIncluded[3];
+		case PF5:
+			return !dataIncluded[4];
+		case PF6:
+			return !dataIncluded[5];
+		case PF7:
+			return !dataIncluded[6];
+		case PF8:
+			return !dataIncluded[7];
+		case PF9:
+			return !dataIncluded[8];
+		case PF10:
+			return !dataIncluded[9];
+		case PF11:
+			return !dataIncluded[10];
+		case PF12:
+			return !dataIncluded[11];
+		case PF13:
+			return !dataIncluded[12];
+		case PF14:
+			return !dataIncluded[13];
+		case PF15:
+			return !dataIncluded[14];
+		case PF16:
+			return !dataIncluded[15];
+		case PF17:
+			return !dataIncluded[16];
+		case PF18:
+			return !dataIncluded[17];
+		case PF19:
+			return !dataIncluded[18];
+		case PF20:
+			return !dataIncluded[19];
+		case PF21:
+			return !dataIncluded[20];
+		case PF22:
+			return !dataIncluded[21];
+		case PF23:
+			return !dataIncluded[22];
+		case PF24:
+			return !dataIncluded[23];
+
+		default:
+			return true;
+
+		}
+
+	}
+
+	/**
+	 * Help request -
+	 *
+	 *
+	 * See notes inside method
+	 */
+	public final void sendHelpRequest() {
+
+		// Client sends header 000D12A0000004000003####F3FFEF
+		//       operation code 3
+		//       row - first ##
+		//       column - second ##
+		//       F3 - Help Aid Key
+		//      System.out.println("Help request sent");
+		baosp.write(screen52.getCurrentRow());
+		baosp.write(screen52.getCurrentCol());
+		baosp.write(AID_HELP);
+
+		try {
+			writeGDS(0, 3, baosp.toByteArray());
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+		}
+		baosp.reset();
+	}
+
+	/**
+	 * Attention Key -
+	 *
+	 *
+	 * See notes inside method
+	 */
+	public final void sendAttentionKey() {
+
+		// Client sends header 000A12A000004400000FFEF
+		//    0x40 -> 01000000
+		//
+		// flags
+		// bit 0 - ERR
+		// bit 1 - ATN Attention
+		// bits 2-4 - reserved
+		// bit 5 - SRQ system request
+		// bit 6 - TRQ Test request key
+		// bit 7 - HLP
+
+		//      System.out.println("Attention key sent");
+
+		try {
+			writeGDS(0x40, 0, null);
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+		}
+	}
+
+	/**
+	 * Opens a dialog and asks the user before sending a request
+	 *
+	 * @see {@link #systemRequest(String)}
+	 */
+	public final void systemRequest() {
+		final String sysreq = this.controller.showSystemRequest();
+		systemRequest(sysreq);
+	}
+
+	/**
+	 * @param sr - system request option
+	 * @see {@link #systemRequest(String)}
+	 */
+	public final void systemRequest(char sr) {
+		systemRequest(Character.toString(sr));
+	}
+
+	/**
+	 * System request, taken from the rfc1205, 5250 Telnet interface section 4.3
+	 *
+	 * @param sr system request option (allowed to be null, but than nothing happens)
+	 */
+	public final void systemRequest(String sr) {
+		byte[] bytes = null;
+
+		if ( (sr != null) && (sr.length() > 0)) {
+			// XXX: Not sure, if this is a sufficient check for 'clear dataq'
+			if (sr.charAt(0) == '2') {
+				dsq.clear();
+			}
+			for (int i = 0, l = sr.length(); i < l; i++) {
+				baosp.write(codePage.uni2ebcdic(sr.charAt(i)));
+			}
+			bytes = baosp.toByteArray();
+		}
+
+		try	{
+			writeGDS(4, 0, bytes);
+		} catch (IOException ioe) {
+			log.info(ioe.getMessage());
+		}
+		baosp.reset();
+	}
+
+	/**
+	 * Cancel Invite - taken from the rfc1205 - 5250 Telnet interface section
+	 * 4.3
+	 *
+	 * See notes inside method
+	 */
+	public final void cancelInvite() {
+
+		//		screen52.setStatus(Screen5250.STATUS_SYSTEM,
+		//				Screen5250.STATUS_VALUE_ON, null);
+		screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+				ScreenOIA.OIA_LEVEL_INPUT_INHIBITED);
+
+		// from rfc1205 section 4.3
+		// Server: Sends header with the 000A12A0 00000400 000AFFEF
+		// Opcode = Cancel Invite.
+
+		// Client: sends header with the 000A12A0 00000400 000AFFEF
+		// Opcode = Cancel Invite to
+		// indicate that the work station is
+		// no longer invited.
+		try {
+			writeGDS(0, 10, null);
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+		}
+
+	}
+
+	public final void hostPrint(int aid) {
+
+		if (screen52.isStatusErrorCode()) {
+			screen52.restoreErrorLine();
+			screen52.setStatus(Screen5250.STATUS_ERROR_CODE,
+					Screen5250.STATUS_VALUE_OFF, null);
+		}
+
+		screen52.setCursorActive(false);
+		//		screen52.setStatus(Screen5250.STATUS_SYSTEM,
+		//				Screen5250.STATUS_VALUE_ON, null);
+		screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT,
+				ScreenOIA.OIA_LEVEL_INPUT_INHIBITED);
+
+		// From client access ip capture
+		// it seems to use an operation code of 3 and 4
+		// also note that the flag field that says reserved is being sent as
+		// well
+		// with a value of 0x80
+		//
+		// I have tried with not setting these flags and sending with 3 or 1
+		// there is no effect and I still get a host print screen. Go figure
+		//0000: 000D 12A0 0000 0400 8003 1407 F6FFEF
+		//0000: 000D 12A0 0000 0400 8001 110E F6FFEF
+		//
+		// Client sends header 000D12A0000004000003####F6FFEF
+		//       operation code 3
+		//       row - first ##
+		//       column - second ##
+		//       F6 - Print Aid Key
+
+		baosp.write(screen52.getCurrentRow());
+		baosp.write(screen52.getCurrentCol());
+		baosp.write(AID_PRINT); // aid key
+
+		try {
+			writeGDS(0, 3, baosp.toByteArray());
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+		}
+		baosp.reset();
+	}
+
+	public final void toggleDebug() {
+		producer.toggleDebug(codePage);
+	}
+
+	// write gerneral data stream
+	private final void writeGDS(int flags, int opcode, byte abyte0[])
+	throws IOException {
+
+		// Added to fix for JDK 1.4 this was null coming from another method.
+		//  There was a weird keyRelease event coming from another panel when
+		//  using a key instead of the mouse to select button.
+		//  The other method was fixed as well but this check should be here
+		// anyway.
+		if (bout == null)
+			return;
+
+		int length;
+		if (abyte0 != null)
+			length = abyte0.length + 10;
+		else
+			length = 10;
+
+		// refer to rfc1205 - 5250 Telnet interface
+		// Section 3. Data Stream Format
+
+		// Logical Record Length - 16 bits
+		baosrsp.write(length >> 8); // Length LL
+		baosrsp.write(length & 0xff); //        LL
+
+		// Record Type - 16 bits
+		// It should always be set to '12A0'X to indicate the
+		// General Data Stream (GDS) record type.
+		baosrsp.write(18); // 0x12
+		baosrsp.write(160); // 0xA0
+
+		// the next 16 bits are not used
+		baosrsp.write(0); // 0x00
+		baosrsp.write(0); // 0x00
+
+		//  The second part is meant to be variable in length
+		//  currently this portion is 4 octets long (1 byte or 8 bits for us ;-O)
+		baosrsp.write(4); // 0x04
+
+		baosrsp.write(flags); // flags
+		// bit 0 - ERR
+		// bit 1 - ATN Attention
+		// bits 2-4 - reserved
+		// bit 5 - SRQ system request
+		// bit 6 - TRQ Test request key
+		// bit 7 - HLP
+		baosrsp.write(0); // reserved - set to 0x00
+		baosrsp.write(opcode); // opcode
+
+		if (abyte0 != null)
+			baosrsp.write(abyte0, 0, abyte0.length);
+
+		baosrsp = appendByteStream(baosrsp.toByteArray());
+
+		// make sure we indicate no more to be sent
+		baosrsp.write(IAC);
+		baosrsp.write(EOR);
+
+		baosrsp.writeTo(bout);
+
+		//        byte[] b = new byte[baosrsp.size()];
+		//        b = baosrsp.toByteArray();
+		//      dump(b);
+		bout.flush();
+		//      baos = null;
+		baosrsp.reset();
+	}
+
+	protected final int getOpCode() {
+
+		return bk.getOpCode();
+	}
+
+	//	private final void sendNotify() throws IOException {
+	//
+	//		writeGDS(0, 0, null);
+	//	}
+
+	protected boolean[] getActiveAidKeys() {
+		boolean aids[] = new boolean[dataIncluded.length];
+		System.arraycopy(dataIncluded,0,aids,0,dataIncluded.length);
+		return aids;
+	}
+
+	private final void setInvited() {
+
+		log.debug("invited");
+		if (!screen52.isStatusErrorCode())
+			screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED,
+					ScreenOIA.OIA_LEVEL_INPUT_INHIBITED);
+
+		invited = true;
+	}
+
+	// WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD
+	private void strpccmd()
+	{
+		try
+		{
+			int str = 11;
+			char c;
+			ScreenPlanes planes = screen52.getPlanes();
+			c = planes.getChar(str);
+			boolean waitFor = !(c == 'a');
+
+			StringBuffer command = new StringBuffer();
+			for (int i = str+1; i < 132; i++)
+			{
+				c = planes.getChar(i);
+				if (Character.isISOControl(c))
+					c = ' ';
+				command.append(c);
+			}
+
+			String cmd = command.toString().trim();
+
+			run(cmd, waitFor);
+		}
+		finally
+		{
+			strpccmd = false;
+			screen52.sendKeys(TN5250jConstants.MNEMONIC_ENTER);
+		}
+	}
+
+	// WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD
+	private void run(String cmd, boolean waitFor)
+	{
+		try
+		{
+			log.debug("RUN cmd = " + cmd);
+			log.debug("RUN wait = " + waitFor);
+
+			Runtime r = Runtime.getRuntime();
+			Process p = r.exec(cmd);
+			if (waitFor)
+			{
+				int result = p.waitFor();
+				log.debug("RUN result = " + result);
+			}
+		}
+		catch (Throwable t)
+		{
+			log.error(t);
+		}
+	}
+
+
+	// WVL - LDC : TR.000300 : Callback scenario from 5250
+	/**
+	 * Activate or deactivate the command scanning behaviour.
+	 *
+	 * @param scan
+	 *            if true, scanning is enabled; disabled otherwise.
+	 *
+	 * @see scan4Cmd()
+	 */
+	public void setScanningEnabled(boolean scan) {
+		this.scan = scan;
+	}
+
+	// WVL - LDC : TR.000300 : Callback scenario from 5250
+	/**
+	 * Checks whether command scanning is enabled.
+	 *
+	 * @return true is command scanning is enabled; false otherwise.
+	 */
+	public boolean isScanningEnabled() {
+		return this.scan;
+	}
+
+	// WVL - LDC : TR.000300 : Callback scenario from 5250
+	/**
+	 * When command scanning is activated, the terminal reads the first and
+	 * second character in the datastream (the zero position allows to
+	 * devisualize the scan stream). If the sequence <code>#!</code> is
+	 * encountered and if this sequence is <strong>not </strong> followed by a
+	 * blank character, the {@link parseCommand(ScreenChar[])}is called.
+	 */
+	private void scan() {
+		//     System.out.println("Checking command : " +
+		// screen52.screen[1].getChar() + screen52.screen[2].getChar());
+
+		//		ScreenChar[] screen = screen52.screen;
+		ScreenPlanes planes = screen52.getPlanes();
+
+		if ((planes.getChar(STRSCAN) == '#')
+				&& (planes.getChar(STRSCAN + 1) == '!')
+				&& (planes.getChar(STRSCAN + 2) != ' ')) {
+			try {
+				parseCommand();
+			} catch (Throwable t) {
+				log.info("Exec cmd: " + t.getMessage());
+				t.printStackTrace();
+			}
+		}
+	}
+
+	// WVL - LDC : TR.000300 : Callback scenario from 5250
+	/**
+	 * The screen is parsed starting from second position until a white space is
+	 * encountered. When found the Session#execCommand(String, int) is
+	 * called with the parsed string. The position immediately following the
+	 * encountered white space, separating the command from the rest of the
+	 * screen, is passed as starting index.
+	 *
+	 * Note that the character at the starting position can potentially be a
+	 * white space itself. The starting position in <code>execCommand</code>
+	 * provided to make the scanning sequence more flexible. We'd like for
+	 * example to embed also a <code>+</code> or <code>-</code> sign to
+	 * indicate whether the tnvt should trigger a repaint or not. This would
+	 * allow the flashing of command sequences without them becoming visible.
+	 *
+	 * <ul>
+	 * <li><strong>PRE </strong> The screen character at position
+	 * <code>STRSCAN + 2</code> is not a white space.</li>
+	 * </ul>
+	 */
+	private void parseCommand() {
+		// Search for the command i.e. the first token in the stream
+		// after the #! sequence separated by a space from the rest
+		// of the screen.
+		char[] screen = screen52.getScreenAsAllChars();
+		for (int s = STRSCAN + 2, i = s; i < screen.length; i++) {
+			if (screen[i] == ' ') {
+				String command = new String(screen, s, i - s);
+
+				// Skip all white spaces between the command and the rest of
+				// the screen.
+				//for (; (i < screen.length) && (screen[i] == ' '); i++);
+
+				String remainder = new String(screen, i + 1, screen.length
+						- (i + 1));
+				//        System.out.println("Sensing action command in the input! = "
+				// + command);
+				controller.fireScanned(command, remainder);
+				break;
+			}
+		}
+	}
+
+	public void run() {
+
+		if (enhanced)
+			sfParser = new WTDSFParser(this);
+
+		bk = new Stream5250();
+
+		while (keepTrucking) {
+
+			try {
+				bk.initialize((byte[]) dsq.take());
+			} catch (InterruptedException ie) {
+				log.warn("   vt thread interrupted and stopping ");
+				keepTrucking = false;
+				continue;
+			}
+
+			// lets play nicely with the others on the playground
+			//         me.yield();
+
+			Thread.yield();
+
+			invited = false;
+
+			screen52.setCursorActive(false);
+
+			//      System.out.println("operation code: " + bk.getOpCode());
+			if (bk == null)
+				continue;
+
+			switch (bk.getOpCode()) {
+			case 00:
+				log.debug("No operation");
+				break;
+			case 1:
+				log.debug("Invite Operation");
+				parseIncoming();
+				//               screen52.setKeyboardLocked(false);
+				pendingUnlock = true;
+				cursorOn = true;
+				setInvited();
+				break;
+			case 2:
+				log.debug("Output Only");
+				parseIncoming();
+				//               System.out.println(screen52.dirty);
+				screen52.updateDirty();
+
+				//            invited = true;
+
+				break;
+			case 3:
+				log.debug("Put/Get Operation");
+				parseIncoming();
+				//               inviteIt =true;
+				setInvited();
+				if (!firstScreen) {
+					firstScreen = true;
+					controller.fireSessionChanged(TN5250jConstants.STATE_CONNECTED);
+				}
+				break;
+			case 4:
+				log.debug("Save Screen Operation");
+				parseIncoming();
+				break;
+
+			case 5:
+				log.debug("Restore Screen Operation");
+				parseIncoming();
+				break;
+			case 6:
+				log.debug("Read Immediate");
+				sendAidKey(0);
+				break;
+			case 7:
+				log.debug("Reserved");
+				break;
+			case 8:
+				log.debug("Read Screen Operation");
+				try {
+					readScreen();
+				} catch (IOException ex) {
+					log.warn(ex.getMessage());
+				}
+				break;
+
+			case 9:
+				log.debug("Reserved");
+				break;
+
+			case 10:
+				log.debug("Cancel Invite Operation");
+				cancelInvite();
+				break;
+
+			case 11:
+				log.debug("Turn on message light");
+				screen52.getOIA().setMessageLightOn();
+				screen52.setCursorActive(true);
+
+				break;
+			case 12:
+				log.debug("Turn off Message light");
+				screen52.getOIA().setMessageLightOff();
+				screen52.setCursorActive(true);
+
+				break;
+			default:
+				break;
+			}
+
+			if (screen52.isUsingGuiInterface())
+				screen52.drawFields();
+
+			//      if (screen52.screen[0][1].getChar() == '#' &&
+			//         screen52.screen[0][2].getChar() == '!')
+			//         execCmd();
+			//      else {
+
+			//			if (screen52.isHotSpots()) {
+			//				screen52.checkHotSpots();
+			//			}
+
+			try {
+				if (!strpccmd) {
+					//               SwingUtilities.invokeAndWait(
+					//                  new Runnable () {
+					//                     public void run() {
+					//                        screen52.updateDirty();
+					//                     }
+					//                  }
+					//               );
+					screen52.updateDirty();
+					//				controller.validate();
+					//				log.debug("update dirty");
+				} else {
+					strpccmd();
+				}
+			} catch (Exception exd) {
+				log.warn(" tnvt.run: " + exd.getMessage());
+				exd.printStackTrace();
+			}
+
+			if (pendingUnlock && !screen52.isStatusErrorCode()) {
+				screen52.getOIA().setKeyBoardLocked(false);
+				pendingUnlock = false;
+			}
+
+			if (cursorOn && !screen52.getOIA().isKeyBoardLocked()) {
+				screen52.setCursorActive(true);
+				cursorOn = false;
+			}
+
+			// lets play nicely with the others on the playground
+			//me.yield();
+			Thread.yield();
+
+		}
+	}
+
+	public void dumpStuff() {
+
+		if (log.isDebugEnabled()) {
+			log.debug(" Pending unlock " + pendingUnlock);
+			log.debug(" Status Error " + screen52.isStatusErrorCode());
+			log.debug(" Keyboard Locked " + screen52.getOIA().isKeyBoardLocked());
+			log.debug(" Cursor On " + cursorOn);
+			log.debug(" Cursor Active " + screen52.cursorActive);
+		}
+
+	}
+
+	//      private final void execCmd() {
+	//         String name = "";
+	//         String argString = "";
+	//
+	//         StringBuffer sb = new StringBuffer();
+	//         sb.append(screen52.screen[0][3].getChar());
+	//         sb.append(screen52.screen[0][4].getChar());
+	//         sb.append(screen52.screen[0][5].getChar());
+	//         sb.append(screen52.screen[0][6].getChar());
+	//
+	//         System.out.println("command = " + sb);
+	//         int x = 8;
+	//         sb.setLength(0);
+	//         while (screen52.screen[0][x].getChar() > ' ') {
+	//            sb.append(screen52.screen[0][x].getChar());
+	//            x++;
+	//         }
+	//         name = sb.toString();
+	//         System.out.println("name = " + name);
+	//
+	//         sb.setLength(0);
+	//         x++;
+	//         while (screen52.screen[0][x].getChar() >= ' ') {
+	//            sb.append(screen52.screen[0][x].getChar());
+	//            x++;
+	//         }
+	//         argString = sb.toString();
+	//         System.out.println("args = " + argString);
+	//
+	//         sendAidKey(AID_ENTER);
+	//
+	//         try {
+	//
+	//            Class c = Class.forName(name);
+	//            String args1[] = {argString};
+	//            String args2[] = {};
+	//
+	//            Method m = c.getMethod("main",
+	//            new Class[] { args1.getClass() });
+	//            m.setAccessible(true);
+	//            int mods = m.getModifiers();
+	//            if (m.getReturnType() !=
+	//                   void.class || !Modifier.isStatic(mods) ||
+	//                  !Modifier.isPublic(mods)) {
+	//
+	//                     throw new NoSuchMethodException("main");
+	//                  }
+	//            try {
+	//               if (argString.length() > 0)
+	//                  m.invoke(null, new Object[] { args1 });
+	//               else
+	//                  m.invoke(null, new Object[] { args2 });
+	//            }
+	//            catch (IllegalAccessException e) {
+	//                 // This should not happen, as we have
+	//                 // disabled access checks
+	//                  System.out.println("iae " + e.getMessage());
+	//
+	//            }
+	//         }
+	//         catch (ClassNotFoundException cnfe) {
+	//            System.out.println("cnfe " + cnfe.getMessage());
+	//         }
+	//         catch (NoSuchMethodException nsmf) {
+	//            System.out.println("nsmf " + nsmf.getMessage());
+	//         }
+	//         catch (InvocationTargetException ite) {
+	//            System.out.println("ite " + ite.getMessage());
+	//         }
+	//   // catch (IllegalAccessException iae) {
+	//   // System.out.println("iae " + iae.getMessage());
+	//   // }
+	//   // catch (InstantiationException ie) {
+	//   // System.out.println("ie " + ie.getMessage());
+	//   // }
+	//   // try {
+	//   //
+	//   // Runtime rt = Runtime.getRuntime();
+	//   // Process proc = rt.exec("notepad");
+	//   // int exitVal = proc.exitValue();
+	//   // }
+	//   // catch (Throwable t) {
+	//   //
+	//   // t.printStackTrace();
+	//   // }
+	//      }
+
+	private final void readScreen() throws IOException {
+
+		int rows = screen52.getRows();
+		int cols = screen52.getColumns();
+		byte abyte0[] = new byte[rows * cols];
+		fillScreenArray(abyte0, rows, cols);
+		writeGDS(0, 0, abyte0);
+		abyte0 = null;
+	}
+
+	private final void fillScreenArray(byte[] sa, int rows, int cols) {
+
+		int la = 32;
+		int sac = 0;
+		int len = rows * cols;
+
+		ScreenPlanes planes = screen52.planes;
+
+		for (int y = 0; y < len; y++) { // save the screen data
+
+			if (planes.isAttributePlace(y)) {
+				la = planes.getCharAttr(y);
+				sa[sac++] = (byte) la;
+			} else {
+				if (planes.getCharAttr(y) != la) {
+					la = planes.getCharAttr(y);
+					sac--;
+					sa[sac++] = (byte) la;
+				}
+				//LDC: Check to see if it is an displayable character. If not,
+				//  do not convert the character.
+				//  The characters on screen are in unicode
+				//sa[sac++] =
+				// (byte)codePage.uni2ebcdic(screen52.screen[y].getChar());
+				char ch = planes.getChar(y);
+				byte byteCh = (byte) ch;
+				if (isDataUnicode(ch))
+					byteCh = codePage.uni2ebcdic(ch);
+				sa[sac++] = byteCh;
+			}
+		}
+	}
+
+	private final void fillRegenerationBuffer(ByteArrayOutputStream sc, int rows, int cols)
+	throws IOException {
+
+		int la = 32;
+		int sac = 0;
+		int len = rows * cols;
+
+		ScreenPlanes planes = screen52.planes;
+		byte[] sa = new byte[len];
+
+		try {
+			boolean guiExists = sfParser != null && sfParser.isGuisExists();
+
+
+			for (int y = 0; y < len; y++) { // save the screen data
+
+				if (guiExists) {
+
+					byte[] guiSeg = sfParser.getSegmentAtPos(y);
+					if (guiSeg != null) {
+						//log.info(" gui saved at " + y + " - " + screen52.getRow(y) + "," +
+						//    screen52.getCol(y));
+
+						byte[] gsa = new byte[sa.length + guiSeg.length + 2];
+						System.arraycopy(sa,0,gsa,0,sa.length);
+						System.arraycopy(guiSeg,0,gsa,sac+2,guiSeg.length);
+						sa = new byte[gsa.length];
+						System.arraycopy(gsa,0,sa,0,gsa.length);
+						sa[sac++] = (byte)0x04;
+						sa[sac++] = (byte)0x11;
+						sac += guiSeg.length;
+						//y--;
+						//		         continue;
+					}
+				}
+				if (planes.isAttributePlace(y)) {
+					la = planes.getCharAttr(y);
+					sa[sac++] = (byte) la;
+				} else {
+					if (planes.getCharAttr(y) != la) {
+						la = planes.getCharAttr(y);
+						sac--;
+						sa[sac++] = (byte) la;
+					}
+					//LDC: Check to see if it is an displayable character. If not,
+					//  do not convert the character.
+					//  The characters on screen are in unicode
+					//sa[sac++] =
+					// (byte)codePage.uni2ebcdic(screen52.screen[y].getChar());
+					char ch = planes.getChar(y);
+					byte byteCh = (byte) ch;
+					if (isDataUnicode(ch))
+						byteCh = codePage.uni2ebcdic(ch);
+					sa[sac++] = byteCh;
+				}
+			}
+		}
+		catch(Exception exc) {
+
+			log.info(exc.getMessage());
+			exc.printStackTrace();
+		}
+		sc.write(sa);
+	}
+
+	public final void saveScreen() throws IOException {
+
+		ByteArrayOutputStream sc = new ByteArrayOutputStream();
+		sc.write(4);
+		sc.write(0x12); // 18
+		sc.write(0); // 18
+		sc.write(0); // 18
+
+		sc.write((byte) screen52.getRows()); // store the current size
+		sc.write((byte) screen52.getColumns()); //    ""
+
+		int cp = screen52.getCurrentPos(); // save off current position
+		// fix below submitted by Mitch Blevins
+		//int cp = screen52.getScreenFields().getCurrentFieldPos();
+		// save off current position
+		sc.write((byte) (cp >> 8 & 0xff)); //    ""
+		sc.write((byte) (cp & 0xff)); //    ""
+
+		sc.write((byte) (screen52.homePos >> 8 & 0xff)); // save home pos
+		sc.write((byte) (screen52.homePos & 0xff)); //    ""
+
+		int rows = screen52.getRows(); // store the current size
+		int cols = screen52.getColumns(); //    ""
+
+		//		byte[] sa = new byte[rows * cols];
+		fillRegenerationBuffer(sc,rows,cols);
+		//		fillScreenArray(sa, rows, cols);
+		//
+		//		sc.write(sa);
+		//		sa = null;
+		int sizeFields = screen52.getScreenFields().getSize();
+		sc.write((byte) (sizeFields >> 8 & 0xff)); //    ""
+		sc.write((byte) (sizeFields & 0xff)); //    ""
+
+		if (sizeFields > 0) {
+			int x = 0;
+			int s = screen52.getScreenFields().getSize();
+			ScreenField sf = null;
+			while (x < s) {
+				sf = screen52.getScreenFields().getField(x);
+				sc.write((byte) sf.getAttr()); // attribute
+				int sp = sf.startPos();
+				sc.write((byte) (sp >> 8 & 0xff)); //    ""
+				sc.write((byte) (sp & 0xff)); //    ""
+				if (sf.mdt)
+					sc.write((byte) 1);
+				else
+					sc.write((byte) 0);
+				sc.write((byte) (sf.getLength() >> 8 & 0xff)); //    ""
+				sc.write((byte) (sf.getLength() & 0xff)); //    ""
+				sc.write((byte) sf.getFFW1() & 0xff);
+				sc.write((byte) sf.getFFW2() & 0xff);
+				sc.write((byte) sf.getFCW1() & 0xff);
+				sc.write((byte) sf.getFCW2() & 0xff);
+				log.debug("Saved ");
+				log.debug(sf.toString());
+
+				x++;
+			}
+			sf = null;
+		}
+
+		// The following two lines of code looks to have caused all sorts of
+		//    problems so for now we have commented them out.
+		//      screen52.getScreenFields().setCurrentField(null); // set it to null
+		// for GC ?
+		//      screen52.clearTable();
+
+		try {
+			writeGDS(0, 3, sc.toByteArray());
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+		}
+
+		sc = null;
+		log.debug("Save Screen end ");
+	}
+
+	/**
+	 *
+	 * @throws IOException
+	 */
+	public final void restoreScreen() throws IOException {
+		int which = 0;
+
+		ScreenPlanes planes = screen52.planes;
+
+		try {
+			log.debug("Restore ");
+
+			bk.getNextByte();
+			bk.getNextByte();
+
+			int rows = bk.getNextByte() & 0xff;
+			int cols = bk.getNextByte() & 0xff;
+			int pos = bk.getNextByte() << 8 & 0xff00; // current position
+			pos |= bk.getNextByte() & 0xff;
+			int hPos = bk.getNextByte() << 8 & 0xff00; // home position
+			hPos |= bk.getNextByte() & 0xff;
+			if (rows != screen52.getRows())
+				screen52.setRowsCols(rows, cols);
+			screen52.clearAll(); // initialize what we currenty have
+			if (sfParser != null && sfParser.isGuisExists())
+				sfParser.clearGuiStructs();
+
+			int b = 32;
+			int la = 32;
+			int len = rows * cols;
+			for (int y = 0; y < len; y++) {
+
+				b = bk.getNextByte();
+				if (b == 0x04) {
+
+					log.info(" gui restored at " + y + " - " + screen52.getRow(y) + "," +
+							screen52.getCol(y));
+					int command = bk.getNextByte();
+					byte[] seg = bk.getSegment();
+
+					if (seg.length > 0) {
+						screen52.goto_XY(y);
+						sfParser.parseWriteToDisplayStructuredField(seg);
+					}
+					y--;
+					//				      screen52.goto_XY(y);
+				}
+				else {
+					//				b = bk.getNextByte();
+					if (planes.isUseGui(y))
+						continue;
+					if (isAttribute(b)) {
+						planes.setScreenCharAndAttr(y, planes.getChar(y), b, true);
+						la = b;
+
+					}
+					else {
+						//LDC - 12/02/2003 - Check to see if it is an displayable
+						// character. If not,
+						//  do not convert the character.
+						//  The characters on screen are in unicode
+						char ch = (char) b;
+						if (isDataEBCDIC(b))
+							ch = codePage.ebcdic2uni(b);
+
+						planes.setScreenCharAndAttr(y, ch, la, false);
+					}
+				}
+			}
+
+			int numFields = bk.getNextByte() << 8 & 0xff00;
+			numFields |= bk.getNextByte() & 0xff;
+			log.debug("number of fields " + numFields);
+
+			if (numFields > 0) {
+				int x = 0;
+				int attr = 0;
+				int fPos = 0;
+				int fLen = 0;
+				int ffw1 = 0;
+				int ffw2 = 0;
+				int fcw1 = 0;
+				int fcw2 = 0;
+				boolean mdt = false;
+
+				ScreenField sf = null;
+				while (x < numFields) {
+
+					attr = bk.getNextByte();
+					fPos = bk.getNextByte() << 8 & 0xff00;
+					fPos |= bk.getNextByte() & 0xff;
+					if (bk.getNextByte() == 1)
+						mdt = true;
+					else
+						mdt = false;
+					fLen = bk.getNextByte() << 8 & 0xff00;
+					fLen |= bk.getNextByte() & 0xff;
+					ffw1 = bk.getNextByte();
+					ffw2 = bk.getNextByte();
+					fcw1 = bk.getNextByte();
+					fcw2 = bk.getNextByte();
+
+					sf = screen52.getScreenFields().setField(attr,
+							screen52.getRow(fPos), screen52.getCol(fPos), fLen,
+							ffw1, ffw2, fcw1, fcw2);
+
+					while (fLen-- > 0) {
+
+						// now we set the field plane attributes
+						planes.setScreenFieldAttr(fPos++,ffw1);
+
+					}
+
+					if (mdt) {
+						sf.setMDT();
+						screen52.getScreenFields().setMasterMDT();
+					}
+					if (log.isDebugEnabled()) {
+						log.debug("/nRestored ");
+						log.debug(sf.toString());
+					}
+					x++;
+				}
+			}
+
+			//  Redraw the gui fields if we are in gui mode
+			if (screen52.isUsingGuiInterface())
+				screen52.drawFields();
+
+			screen52.restoreScreen(); // display the screen
+
+			//  The position was saved with currentPos which 1,1 offset of the
+			//     screen position.
+			//  The setPendingInsert is the where the cursor position will be
+			//  displayed after the restore.
+			screen52.setPendingInsert(true, screen52.getRow(pos + cols), screen52
+					.getCol(pos + cols));
+			//  We need to offset the pos by -1 since the position is 1,1 based
+			//    and the goto_XY is 0,0 based.
+			screen52.goto_XY(pos - 1);
+			screen52.isInField();
+			//			//  Redraw the gui fields if we are in gui mode
+			//			if (screen52.isUsingGuiInterface())
+			//				screen52.drawFields();
+		} catch (Exception e) {
+			log.warn("error restoring screen " + which + " with "
+					+ e.getMessage());
+		}
+	}
+
+	public final boolean waitingForInput() {
+
+		return waitingForInput;
+	}
+
+	private void parseIncoming() {
+
+		boolean done = false;
+		boolean error = false;
+
+		try {
+			while (bk.hasNext() && !done) {
+				byte b = bk.getNextByte();
+
+				switch (b) {
+				case 0:
+				case 1:
+					break;
+				case CMD_SAVE_SCREEN: // 0x02 2 Save Screen
+				case 3: // 0x03 3 Save Partial Screen
+					log.debug("save screen partial");
+					saveScreen();
+					break;
+
+				case ESC: // ESCAPE
+					break;
+				case 7: // audible bell
+					controller.signalBell();
+					bk.getNextByte();
+					bk.getNextByte();
+					break;
+				case CMD_WRITE_TO_DISPLAY: // 0x11 17 write to display
+					error = writeToDisplay(true);
+					// WVL - LDC : TR.000300 : Callback scenario from 5250
+					// Only scan when WRITE_TO_DISPLAY operation (i.e. refill
+					// screen buffer)
+					// has been issued!
+					if (scan)
+						scan();
+
+					break;
+				case CMD_RESTORE_SCREEN: // 0x12 18 Restore Screen
+				case 13: // 0x13 19 Restore Partial Screen
+					log.debug("restore screen partial");
+					restoreScreen();
+					break;
+
+				case CMD_CLEAR_UNIT_ALTERNATE: // 0x20 32 clear unit alternate
+					int param = bk.getNextByte();
+					if (param != 0) {
+						log.debug(" clear unit alternate error "
+								+ Integer.toHexString(param));
+						sendNegResponse(NR_REQUEST_ERROR, 03, 01, 05,
+						" clear unit alternate not supported");
+						done = true;
+					} else {
+						if (screen52.getRows() != 27)
+							screen52.setRowsCols(27, 132);
+
+						screen52.clearAll();
+						if (sfParser != null && sfParser.isGuisExists())
+							sfParser.clearGuiStructs();
+
+
+					}
+					break;
+
+				case CMD_WRITE_ERROR_CODE: // 0x21 33 Write Error Code
+					writeErrorCode();
+					error = writeToDisplay(false);
+					break;
+				case CMD_WRITE_ERROR_CODE_TO_WINDOW: // 0x22 34
+					// Write Error Code to window
+					writeErrorCodeToWindow();
+					error = writeToDisplay(false);
+					break;
+
+				case CMD_READ_SCREEN_IMMEDIATE: // 0x62 98
+				case CMD_READ_SCREEN_TO_PRINT: // 0x66 102 read screen to print
+					readScreen();
+					break;
+
+				case CMD_CLEAR_UNIT: // 64 0x40 clear unit
+					if (screen52.getRows() != 24)
+						screen52.setRowsCols(24, 80);
+					screen52.clearAll();
+					if (sfParser != null && sfParser.isGuisExists())
+						sfParser.clearGuiStructs();
+
+					break;
+
+				case CMD_CLEAR_FORMAT_TABLE: // 80 0x50 Clear format table
+					screen52.clearTable();
+					break;
+
+				case CMD_READ_INPUT_FIELDS: //0x42 66 read input fields
+				case CMD_READ_MDT_FIELDS: // 0x52 82 read MDT Fields
+					bk.getNextByte();
+					bk.getNextByte();
+					readType = b;
+					screen52.goHome();
+					// do nothing with the cursor here it is taken care of
+					//   in the main loop.
+					//////////////// screen52.setCursorOn();
+					waitingForInput = true;
+					pendingUnlock = true;
+					//                  screen52.setKeyboardLocked(false);
+					break;
+				case CMD_READ_MDT_IMMEDIATE_ALT: // 0x53 83
+					readType = b;
+					//                  screen52.goHome();
+					//                  waitingForInput = true;
+					//                  screen52.setKeyboardLocked(false);
+					readImmediate(readType);
+					break;
+				case CMD_WRITE_STRUCTURED_FIELD: // 243 0xF3 -13 Write
+					// structured field
+					writeStructuredField();
+					break;
+				case CMD_ROLL: // 0x23 35 Roll Not sure what it does right now
+					int updown = bk.getNextByte();
+					int topline = bk.getNextByte();
+					int bottomline = bk.getNextByte();
+					screen52.rollScreen(updown, topline, bottomline);
+					break;
+
+				default:
+					done = true;
+					sendNegResponse(NR_REQUEST_ERROR, 03, 01, 01,
+					"parseIncoming");
+					break;
+				}
+
+				if (error)
+					done = true;
+			}
+			//       BEGIN FRAMEWORK
+			//  I took this out for debugging a problem
+			//			ScreenField[] a = this.screen52.getScreenFields().getFields();
+			//			if (log.isDebugEnabled()) {
+			//				for (int x = 0; x < a.length; x++) {
+			//					log.debug(a[x].toString());
+			//				}
+			//			}
+			//
+			//			String strokes = this.screen52.getKeys();
+			//			if (!strokes.equals("")) {
+			//				Tn5250jKeyEvents e = new Tn5250jKeyEvents(this.screen52,
+			//						strokes);
+			//				//from the previous screen.
+			//				Tn5250jController.getCurrent().handleEvent(e);
+			//			}
+			//
+			//			Tn5250jEvent event = new Tn5250jEvent(screen52);
+			//			Tn5250jController.getCurrent().handleEvent(event);
+			//
+			//			//END FRAMEWORK
+		} catch (Exception exc) {
+			log.warn("incoming " + exc.getMessage());
+		}
+		;
+	}
+
+	/**
+	 * This routine handles sending negative responses back to the host.
+	 *
+	 * You can find a description of the types of responses to be sent back by
+	 * looking at section 12.4 of the 5250 Functions Reference manual
+	 *
+	 *
+	 * @param cat
+	 * @param modifier
+	 * @param uByte1
+	 * @param uByte2
+	 * @param from
+	 *
+	 */
+	protected void sendNegResponse(int cat, int modifier, int uByte1,
+			int uByte2, String from) {
+
+		try {
+
+			int os = bk.getByteOffset(-1) & 0xf0;
+			int cp = (bk.getCurrentPos() - 1);
+			log.info("invalid " + from + " command " + os
+					+ " at pos " + cp);
+		} catch (Exception e) {
+
+			log.warn("Send Negative Response error " + e.getMessage());
+		}
+
+		baosp.write(cat);
+		baosp.write(modifier);
+		baosp.write(uByte1);
+		baosp.write(uByte2);
+
+		try {
+			writeGDS(128, 0, baosp.toByteArray());
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+		}
+		baosp.reset();
+
+	}
+
+	public void sendNegResponse2(int ec) {
+
+		screen52.setPrehelpState(true, true, false);
+		baosp.write(0x00);
+		baosp.write(ec);
+
+		try {
+			writeGDS(1, 0, baosp.toByteArray());
+		} catch (IOException ioe) {
+
+			log.warn(ioe.getMessage());
+		}
+
+		baosp.reset();
+	}
+
+	private boolean writeToDisplay(boolean controlsExist) {
+
+		boolean error = false;
+		boolean done = false;
+		int attr;
+		byte control0 = 0;
+		byte control1 = 0;
+		int saRows = screen52.getRows();
+		int saCols = screen52.getColumns();
+
+		try {
+			if (controlsExist) {
+				control0 = bk.getNextByte();
+				control1 = bk.getNextByte();
+				processCC0(control0);
+			}
+			while (bk.hasNext() && !done) {
+				//            pos = bk.getCurrentPos();
+
+				//            int rowc = screen52.getCurrentRow();
+				//            int colc = screen52.getCurrentCol();
+
+				byte bytebk = bk.getNextByte();
+
+				switch (bytebk) {
+
+				case 1: // SOH - Start of Header Order
+					log.debug("SOH - Start of Header Order");
+					error = processSOH();
+
+					break;
+				case 02: // RA - Repeat to address
+					log.debug("RA - Repeat to address");
+					int row = screen52.getCurrentRow();
+					int col = screen52.getCurrentCol();
+
+					int toRow = bk.getNextByte();
+					int toCol = bk.getNextByte() & 0xff;
+					if (toRow >= row) {
+						int repeat = bk.getNextByte();
+
+						// a little intelligence here I hope
+						if (row == 1 && col == 2 && toRow == screen52.getRows()
+								&& toCol == screen52.getColumns())
+
+							screen52.clearScreen();
+						else {
+							if (repeat != 0) {
+								//LDC - 13/02/2003 - convert it to unicode
+								repeat = codePage.ebcdic2uni(repeat);
+								//repeat = getASCIIChar(repeat);
+							}
+
+							int times = ((toRow * screen52.getColumns()) + toCol)
+							- ((row * screen52.getColumns()) + col);
+							while (times-- >= 0) {
+								screen52.setChar(repeat);
+							}
+
+						}
+					} else {
+						sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x23,
+						" RA invalid");
+						error = true;
+					}
+					break;
+
+				case 03: // EA - Erase to address
+					log.debug("EA - Erase to address");
+					int EArow = screen52.getCurrentRow();
+					int EAcol = screen52.getCurrentCol();
+
+					int toEARow = bk.getNextByte();
+					int toEACol = bk.getNextByte() & 0xff;
+					int EALength = bk.getNextByte() & 0xff;
+					while (--EALength > 0) {
+
+						bk.getNextByte();
+
+					}
+					char EAAttr = (char) 0;
+
+					// a little intelligence here I hope
+					if (EArow == 1 && EAcol == 2
+							&& toEARow == screen52.getRows()
+							&& toEACol == screen52.getColumns())
+
+						screen52.clearScreen();
+					else {
+						int times = ((toEARow * screen52.getColumns()) + toEACol)
+						- ((EArow * screen52.getColumns()) + EAcol);
+						while (times-- >= 0) {
+							screen52.setChar(EAAttr);
+						}
+					}
+					break;
+				case 04: // Command - Escape
+					log.debug("Command - Escape");
+					done = true;
+					break;
+
+				case 16: // TD - Transparent Data
+					log.debug("TD - Transparent Data");
+					int j = (bk.getNextByte() & 0xff) << 8 | bk.getNextByte()
+					& 0xff; // length
+					break;
+
+				case 17: // SBA - set buffer address order (row column)
+					log.debug("SBA - set buffer address order (row column)");
+					int saRow = bk.getNextByte();
+					int saCol = bk.getNextByte() & 0xff;
+					// make sure it is in bounds
+					if (saRow >= 0 && saRow <= screen52.getRows() && saCol >= 0
+							&& saCol <= screen52.getColumns()) {
+						screen52.setCursor(saRow, saCol); // now set screen
+						// position for output
+
+					} else {
+
+						sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22,
+								"invalid row/col order" + " saRow = " + saRow
+								+ " saRows = " + screen52.getRows()
+								+ " saCol = " + saCol);
+
+						error = true;
+
+					}
+					break;
+
+				case 18: // WEA - Extended Attribute
+					log.debug("WEA - Extended Attribute");
+					bk.getNextByte();
+					bk.getNextByte();
+					break;
+
+				case 19: // IC - Insert Cursor
+					log.debug("IC - Insert Cursor");
+					int icX = bk.getNextByte();
+					int icY = bk.getNextByte() & 0xff;
+					if (icX >= 0 && icX <= saRows && icY >= 0 && icY <= saCols) {
+
+						log.debug(" IC " + icX + " " + icY);
+						screen52.setPendingInsert(true, icX, icY);
+					} else {
+						sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22,
+						" IC/IM position invalid ");
+						error = true;
+					}
+
+					break;
+
+				case 20: // MC - Move Cursor
+					log.debug("MC - Move Cursor");
+					int imcX = bk.getNextByte();
+					int imcY = bk.getNextByte() & 0xff;
+					if (imcX >= 0 && imcX <= saRows && imcY >= 0
+							&& imcY <= saCols) {
+
+						log.debug(" MC " + imcX + " " + imcY);
+						screen52.setPendingInsert(false, imcX, imcY);
+					} else {
+						sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22,
+						" IC/IM position invalid ");
+						error = true;
+					}
+
+					break;
+
+				case 21: // WTDSF - Write To Display Structured Field order
+					log
+					.debug("WTDSF - Write To Display Structured Field order");
+					byte[] seg = bk.getSegment();
+					error = sfParser.parseWriteToDisplayStructuredField(seg);
+
+					//                  error = writeToDisplayStructuredField();
+					break;
+
+				case 29: // SF - Start of Field
+					log.debug("SF - Start of Field");
+					int fcw1 = 0;
+					int fcw2 = 0;
+					int ffw1 = 0;
+					int ffw0 = bk.getNextByte() & 0xff; // FFW
+
+					if ((ffw0 & 0x40) == 0x40) {
+						ffw1 = bk.getNextByte() & 0xff; // FFW 1
+
+						fcw1 = bk.getNextByte() & 0xff; // check for field
+						// control word
+
+						// check if the first fcw1 is an 0x81 if it is then get
+						// the
+						// next pair for checking
+						if (fcw1 == 0x81) {
+							bk.getNextByte();
+							fcw1 = bk.getNextByte() & 0xff; // check for field
+							// control word
+						}
+
+						if (!isAttribute(fcw1)) {
+
+							fcw2 = bk.getNextByte() & 0xff; // FCW 2
+							attr = bk.getNextByte() & 0xff; // attribute field
+
+							while (!isAttribute(attr)) {
+								log.info(Integer.toHexString(fcw1) + " "
+										+ Integer.toHexString(fcw2)
+										+ " ");
+								log.info(Integer.toHexString(attr)
+										+ " "
+										+ Integer.toHexString(bk
+												.getNextByte() & 0xff));
+								//                           bk.getNextByte();
+								attr = bk.getNextByte() & 0xff; // attribute
+								// field
+							}
+						} else {
+							attr = fcw1; // attribute of field
+							fcw1 = 0;
+						}
+					} else {
+						attr = ffw0;
+					}
+
+					int fLength = (bk.getNextByte() & 0xff) << 8
+					| bk.getNextByte() & 0xff;
+					screen52.addField(attr, fLength, ffw0, ffw1, fcw1, fcw2);
+
+					break;
+					// WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD
+				case -128: //STRPCCMD
+					//          if (screen52.getCurrentPos() == 82) {
+					log.debug("STRPCCMD got a -128 command at " + screen52.getCurrentPos());
+					StringBuffer value = new StringBuffer();
+					int b;
+					char c;
+					int[] pco = new int[9];
+					int[] pcoOk = {0xfc, 0xd7, 0xc3, 0xd6, 0x40, 0x83, 0x80, 0xa1, 0x80};
+
+					for (int i = 0; i < 9; i++)
+					{
+						b = bk.getNextByte();
+						pco[i] = ((b & 0xff));
+						c = codePage.ebcdic2uni(b);
+						value.append(c);
+					}
+
+					// Check "PCO-String"
+					if (Arrays.equals(pco, pcoOk)) {
+						strpccmd = true;
+					}
+					// we return in the stream to have all chars
+					// arrive at the screen for later processing
+					for (int i = 0; i < 9; i++)
+						bk.setPrevByte();
+					//}
+					// no break: so every chars arrives
+					// on the screen for later parsing
+					//break;
+
+				default: // all others must be output to screen
+					log.debug("all others must be output to screen");
+					byte byte0 = bk.getByteOffset(-1);
+					if (isAttribute(byte0)) {
+						screen52.setAttr(byte0);
+					} else {
+						if (!screen52.isStatusErrorCode()) {
+							if (!isDataEBCDIC(byte0)) {
+								//                           if (byte0 == 255) {
+								//                              sendNegResponse(NR_REQUEST_ERROR,0x05,0x01,0x42,
+								//                              " Attempt to send FF to screen");
+								//                           }
+								//                           else
+
+								screen52.setChar(byte0);
+							} else
+								//LDC - 13/02/2003 - Convert it to unicode
+								//screen52.setChar(getASCIIChar(byte0));
+								screen52.setChar(codePage.ebcdic2uni(byte0));
+						} else {
+							if (byte0 == 0)
+								screen52.setChar(byte0);
+							else
+								//LDC - 13/02/2003 - Convert it to unicode
+								//screen52.setChar(getASCIIChar(byte0));
+								screen52.setChar(codePage.ebcdic2uni(byte0));
+						}
+					}
+
+					break;
+				}
+
+				if (error)
+					done = true;
+			}
+		}
+
+		catch (Exception e) {
+			log.warn("write to display " + e.getMessage());
+			e.printStackTrace();
+		}
+		;
+
+		processCC1(control1);
+
+		return error;
+
+	}
+
+	private boolean processSOH() throws Exception {
+
+		int l = bk.getNextByte(); // length
+		log.debug(" byte 0 " + l);
+
+		if (l > 0 && l <= 7) {
+			bk.getNextByte(); // flag byte 2
+			bk.getNextByte(); // reserved
+			bk.getNextByte(); // resequence fields
+
+			screen52.clearTable();
+
+			// well that is the first time I have seen this. This fixes a
+			// problem
+			// with S/36 command line. Finally got it.
+			if (l <= 3)
+				return false;
+
+			screen52.setErrorLine(bk.getNextByte()); // error row
+
+			int byte1 = 0;
+			if (l >= 5) {
+				byte1 = bk.getNextByte();
+				dataIncluded[23] = (byte1 & 0x80) == 0x80;
+				dataIncluded[22] = (byte1 & 0x40) == 0x40;
+				dataIncluded[21] = (byte1 & 0x20) == 0x20;
+				dataIncluded[20] = (byte1 & 0x10) == 0x10;
+				dataIncluded[19] = (byte1 & 0x8) == 0x8;
+				dataIncluded[18] = (byte1 & 0x4) == 0x4;
+				dataIncluded[17] = (byte1 & 0x2) == 0x2;
+				dataIncluded[16] = (byte1 & 0x1) == 0x1;
+			}
+
+			if (l >= 6) {
+				byte1 = bk.getNextByte();
+				dataIncluded[15] = (byte1 & 0x80) == 0x80;
+				dataIncluded[14] = (byte1 & 0x40) == 0x40;
+				dataIncluded[13] = (byte1 & 0x20) == 0x20;
+				dataIncluded[12] = (byte1 & 0x10) == 0x10;
+				dataIncluded[11] = (byte1 & 0x8) == 0x8;
+				dataIncluded[10] = (byte1 & 0x4) == 0x4;
+				dataIncluded[9] = (byte1 & 0x2) == 0x2;
+				dataIncluded[8] = (byte1 & 0x1) == 0x1;
+			}
+
+			if (l >= 7) {
+				byte1 = bk.getNextByte();
+				dataIncluded[7] = (byte1 & 0x80) == 0x80;
+				dataIncluded[6] = (byte1 & 0x40) == 0x40;
+				dataIncluded[5] = (byte1 & 0x20) == 0x20;
+				dataIncluded[4] = (byte1 & 0x10) == 0x10;
+				dataIncluded[3] = (byte1 & 0x8) == 0x8;
+				dataIncluded[2] = (byte1 & 0x4) == 0x4;
+				dataIncluded[1] = (byte1 & 0x2) == 0x2;
+				dataIncluded[0] = (byte1 & 0x1) == 0x1;
+			}
+			return false;
+		} else {
+			sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x2B,
+			"invalid SOH length");
+			return true;
+		}
+
+	}
+
+	private void processCC0(byte byte0) {
+		log.debug(" Control byte0 " + Integer.toBinaryString(byte0 & 0xff));
+		boolean lockKeyboard = true;
+		boolean resetMDT = false;
+		boolean resetMDTAll = false;
+		boolean nullMDT = false;
+		boolean nullAll = false;
+
+		// Bits 3 to 6 are reserved and should be set to '0000'
+		// 0xE0 = '11100000' - only the first 3 bits are tested
+		if ((byte0 & 0xE0) == 0x00) {
+			lockKeyboard = false;
+		}
+
+		// '00100000' = 0x20 /32 -- just lock keyboard
+		// '01000000' = 0x40 /64
+		// '01100000' = 0x60 /96
+		// '10000000' = 0x80 /128
+		// '10100000' = 0xA0 /160
+		// '11000000' = 0xC0 /192
+		// '11100000' = 0xE0 /224
+
+		switch (byte0 & 0xE0) {
+
+		case 0x40:
+			resetMDT = true;
+			break;
+		case 0x60:
+			resetMDTAll = true;
+			break;
+		case 0x80:
+			nullMDT = true;
+			break;
+		case 0xA0:
+			resetMDT = true;
+			nullAll = true;
+			break;
+		case 0xC0:
+			resetMDT = true;
+			nullMDT = true;
+			break;
+
+		case 0xE0:
+			resetMDTAll = true;
+			nullAll = true;
+			break;
+
+		}
+
+		if (lockKeyboard) {
+			screen52.getOIA().setKeyBoardLocked(true);
+			pendingUnlock = false;
+		} else
+			pendingUnlock = false;
+
+		if (resetMDT || resetMDTAll || nullMDT || nullAll) {
+			ScreenField sf;
+
+			int f = screen52.getScreenFields().getSize();
+			for (int x = 0; x < f; x++) {
+				sf = screen52.getScreenFields().getField(x);
+
+				if (!sf.isBypassField()) {
+					if ((nullMDT && sf.mdt) || nullAll) {
+						sf.setFieldChar((char) 0x0);
+						screen52.drawField(sf);
+					}
+				}
+				if (resetMDTAll || (resetMDT && !sf.isBypassField()))
+					sf.resetMDT();
+
+			}
+			sf = null;
+		}
+
+	}
+
+	private void processCC1(byte byte1) {
+		log.debug(" Control byte1 " + Integer.toBinaryString(byte1 & 0xff));
+
+		if ((byte1 & 0x04) == 0x04) {
+			controller.signalBell();
+		}
+		if ((byte1 & 0x02) == 0x02) {
+			screen52.getOIA().setMessageLightOff();
+		}
+		if ((byte1 & 0x01) == 0x01) {
+			screen52.getOIA().setMessageLightOn();
+		}
+
+		if ((byte1 & 0x01) == 0x01 && (byte1 & 0x02) == 0x02) {
+			screen52.getOIA().setMessageLightOn();
+		}
+
+		// reset blinking cursor seems to control whether to set or not set the
+		// the cursor position. No documentation for this just testing and
+		// looking at the bit settings of this field. This was a pain in the
+		// ass!
+		//
+		// if it is off '0' then keep existing cursor positioning information
+		// if it is on '1' then reset the cursor positioning information
+		// *** Note *** unless we receive bit 4 on at the same time
+		// this seems to work so far
+		if ((byte1 & 0x20) == 0x20 && (byte1 & 0x08) == 0x00) {
+			screen52.setPendingInsert(false);
+			log.debug(" WTD position no move");
+		} else {
+
+			screen52.setPendingInsert(true);
+			log.debug(" WTD position move to home" + screen52.homePos + " row "
+					+ screen52.getRow(screen52.homePos) + " col "
+					+ screen52.getCol(screen52.homePos));
+
+		}
+		// in enhanced mode we sometimes only receive bit 6 turned on which
+		// is reset blinking cursor
+		if ((byte1 & 0x20) == 0x20 && enhanced) {
+			cursorOn = true;
+		}
+
+		if (!screen52.isStatusErrorCode() && (byte1 & 0x08) == 0x08) {
+
+			//         screen52.setStatus(screen52.STATUS_SYSTEM,screen52.STATUS_VALUE_OFF,null);
+			cursorOn = true;
+		}
+
+		if ((byte1 & 0x20) == 0x20 && (byte1 & 0x08) == 0x00) {
+			screen52.setPendingInsert(false, 1, 1);
+		}
+
+	}
+
+	private boolean isAttribute(int byte0) {
+		int byte1 = byte0 & 0xff;
+		return (byte1 & 0xe0) == 0x20;
+	}
+
+	//LDC - 12/02/2003 - Function name changed from isData to isDataEBCDIC
+	private boolean isDataEBCDIC(int byte0) {
+		int byte1 = byte0 & 0xff;
+		// here it should always be less than 255
+		if (byte1 >= 64 && byte1 < 255)
+
+			return true;
+		else
+			return false;
+
+	}
+
+	//LDC - 12/02/2003 - Test if the unicode character is a displayable
+	// character.
+	//  The first 32 characters are non displayable characters
+	//  This is normally the inverse of isDataEBCDIC (That's why there is a
+	//  check on 255 -> 0xFFFF
+	private boolean isDataUnicode(int byte0) {
+		return (((byte0 < 0) || (byte0 >= 32)) && (byte0 != 0xFFFF));
+	}
+
+	private void writeStructuredField() {
+
+		boolean done = false;
+		try {
+			int length = ((bk.getNextByte() & 0xff) << 8 | (bk.getNextByte() & 0xff));
+			while (bk.hasNext() && !done) {
+				switch (bk.getNextByte()) {
+
+				case -39: // SOH - Start of Header Order
+
+					switch (bk.getNextByte()) {
+					case 112: // 5250 Query
+						bk.getNextByte(); // get null required field
+						sendQueryResponse();
+						break;
+					default:
+						log.debug("invalid structured field sub command "
+								+ bk.getByteOffset(-1));
+						break;
+					}
+					break;
+				default:
+					log.debug("invalid structured field command "
+							+ bk.getByteOffset(-1));
+					break;
+				}
+			}
+		} catch (Exception e) {
+		}
+		;
+
+	}
+
+	private final void writeErrorCode() throws Exception {
+		screen52.setCursor(screen52.getErrorLine(), 1); // Skip the control byte
+		screen52.setStatus(Screen5250.STATUS_ERROR_CODE,
+				Screen5250.STATUS_VALUE_ON, null);
+		screen52.saveErrorLine();
+		cursorOn = true;
+
+	}
+
+	private final void writeErrorCodeToWindow() throws Exception {
+		int fromCol = bk.getNextByte() & 0xff; // from column
+		int toCol = bk.getNextByte() & 0xff; // to column
+		screen52.setCursor(screen52.getErrorLine(), fromCol); // Skip the control
+		// byte
+		screen52.setStatus(Screen5250.STATUS_ERROR_CODE,
+				Screen5250.STATUS_VALUE_ON, null);
+		screen52.saveErrorLine();
+		cursorOn = true;
+
+	}
+
+	/**
+	 * Method sendQueryResponse
+	 *
+	 * The query command is used to obtain information about the capabilities of
+	 * the 5250 display.
+	 *
+	 * The Query command must follow an Escape (0x04) and Write Structured Field
+	 * command (0xF3).
+	 *
+	 * This section is modeled after the rfc1205 - 5250 Telnet Interface section
+	 * 5.3
+	 *
+	 * @throws IOException
+	 */
+	private final void sendQueryResponse() throws IOException {
+
+		log.info("sending query response");
+		byte abyte0[] = new byte[64];
+		abyte0[0] = 0; // Cursor Row/column (set to zero)
+		abyte0[1] = 0; //           ""
+		abyte0[2] = -120; // X'88' inbound write structure Field aid
+		if (enhanced == true) {
+			abyte0[3] = 0; // 0x003D (61) length of query response
+			abyte0[4] = 64; //       "" see note below ?????????
+		} else {
+			abyte0[3] = 0; // 0x003A (58) length of query response
+			abyte0[4] = 58; //       ""
+			//  the length between 58 and 64 seems to cause
+			//  different formatting codes to be sent from
+			//  the host ???????????????? why ???????
+			//    Well the why can be found in the manual if
+			//       read a little more ;-)
+		}
+		abyte0[5] = -39; // command class 0xD9
+		abyte0[6] = 112; // Command type query 0x70
+		abyte0[7] = -128; // 0x80 Flag byte
+		abyte0[8] = 6; // Controller Hardware Class
+		abyte0[9] = 0; // 0x0600 - Other WSF or another 5250 Emulator
+		abyte0[10] = 1; // Controller Code Level
+		abyte0[11] = 1; //    Version 1 Rel 1.0
+		abyte0[12] = 0; //       ""
+
+		abyte0[13] = 0; // 13 - 28 are reserved so set to 0x00
+		abyte0[14] = 0; //       ""
+		abyte0[15] = 0; //       ""
+		abyte0[16] = 0; //       ""
+		abyte0[17] = 0; //       ""
+		abyte0[18] = 0; //       ""
+		abyte0[19] = 0; //       ""
+		abyte0[20] = 0; //       ""
+		abyte0[21] = 0; //       ""
+		abyte0[22] = 0; //       ""
+		abyte0[23] = 0; //       ""
+		abyte0[24] = 0; //       ""
+		abyte0[25] = 0; //       ""
+		abyte0[26] = 0; //       ""
+		abyte0[27] = 0; //       ""
+		abyte0[28] = 0; //       ""
+		abyte0[29] = 1; // Device type - 0x01 5250 Emulator
+		abyte0[30] = codePage.uni2ebcdic('5'); // Device type character
+		abyte0[31] = codePage.uni2ebcdic('2'); //          ""
+		abyte0[32] = codePage.uni2ebcdic('5'); //          ""
+		abyte0[33] = codePage.uni2ebcdic('1'); //          ""
+		abyte0[34] = codePage.uni2ebcdic('0'); //          ""
+		abyte0[35] = codePage.uni2ebcdic('1'); //          ""
+		abyte0[36] = codePage.uni2ebcdic('1'); //          ""
+
+		abyte0[37] = 2; // Keyboard Id - 0x02 Standard Keyboard
+		abyte0[38] = 0; // extended keyboard id
+		abyte0[39] = 0; // reserved
+
+		abyte0[40] = 0; // 40 - 43 Display Serial Number
+		abyte0[41] = 36; //
+		abyte0[42] = 36; //
+		abyte0[43] = 0; //
+
+		abyte0[44] = 1; // Maximum number of display fields - 256
+		abyte0[45] = 0; // 0x0100
+		abyte0[46] = 0; // 46 -48 Reserved set to 0x00
+		abyte0[47] = 0;
+		abyte0[48] = 0;
+		abyte0[49] = 1; // 49 - 53 Controller Display Capability
+		abyte0[50] = 17; //      see rfc - tired of typing :-)
+		abyte0[51] = 0; //          ""
+		abyte0[52] = 0; //          ""
+
+		//  53
+		//    Bit 0-2: B'000' - no graphics capability
+		//             B'001' - 5292-2 style graphics
+		//    Bit 3-7: B '00000' = reserved (it seems for Client access)
+
+		if (enhanced == true) {
+			//         abyte0[53] = 0x5E; // 0x5E turns on ehnhanced mode
+			//         abyte0[53] = 0x27; // 0x5E turns on ehnhanced mode
+			abyte0[53] = 0x7; //  0x5E turns on ehnhanced mode
+			log.info("enhanced options");
+		} else
+			abyte0[53] = 0x0; //  0x0 is normal emulation
+
+		abyte0[54] = 24; // 54 - 60 Reserved set to 0x00
+		//  54 - I found out is used for enhanced user
+		//       interface level 3. Bit 4 allows headers
+		//       and footers for windows
+		abyte0[54] = 8; // 54 - 60 Reserved set to 0x00
+		//  54 - I found out is used for enhanced user
+		//       interface level 3. Bit 4 allows headers
+		//       and footers for windows
+		abyte0[55] = 0;
+		abyte0[56] = 0;
+		abyte0[57] = 0;
+		abyte0[58] = 0;
+		abyte0[59] = 0;
+		abyte0[60] = 0;
+		abyte0[61] = 0; // gridlines are not supported
+		abyte0[62] = 0; // gridlines are not supported
+		abyte0[63] = 0;
+		writeGDS(0, 0, abyte0); // now tell them about us
+		abyte0 = null;
+
+	}
+
+	protected final boolean negotiate(byte abyte0[]) throws IOException {
+		int i = 0;
+
+
+		// from server negotiations
+		if(abyte0[i] == IAC) { // -1
+
+			while(i < abyte0.length && abyte0[i++] == -1)
+				//         while(i < abyte0.length && (abyte0[i] == -1 || abyte0[i++] == 0x20))
+				switch(abyte0[i++]) {
+
+				// we will not worry about what it WONT do
+				case WONT:            // -4
+				default:
+					break;
+
+				case DO: //-3
+
+					// not sure why but since moving to V5R2 we are receiving a
+					//   DO with no option when connecting a second session with
+					//   device name.  Can not find the cause at all.  If anybody
+					//   is interested please debug this until then this works.
+					if (i < abyte0.length) {
+						switch(abyte0[i]) {
+						case TERMINAL_TYPE: // 24
+							baosp.write(IAC);
+							baosp.write(WILL);
+							baosp.write(TERMINAL_TYPE);
+							writeByte(baosp.toByteArray());
+							baosp.reset();
+
+							break;
+
+						case OPT_END_OF_RECORD: // 25
+
+							baosp.write(IAC);
+							baosp.write(WILL);
+							baosp.write(OPT_END_OF_RECORD);
+							writeByte(baosp.toByteArray());
+							baosp.reset();
+							break;
+
+						case TRANSMIT_BINARY: // 0
+
+							baosp.write(IAC);
+							baosp.write(WILL);
+							baosp.write(TRANSMIT_BINARY);
+							writeByte(baosp.toByteArray());
+							baosp.reset();
+
+							break;
+
+						case TIMING_MARK: // 6   rfc860
+							//                        System.out.println("Timing Mark Received and notifying " +
+							//                        "the server that we will not do it");
+							baosp.write(IAC);
+							baosp.write(WONT);
+							baosp.write(TIMING_MARK);
+							writeByte(baosp.toByteArray());
+							baosp.reset();
+
+							break;
+
+						case NEW_ENVIRONMENT: // 39 rfc1572, rfc4777
+							// allways send new environment vars ...
+							baosp.write(IAC);
+							baosp.write(WILL);
+							baosp.write(NEW_ENVIRONMENT);
+							writeByte(baosp.toByteArray());
+							baosp.reset();
+							break;
+
+						default:  // every thing else we will not do at this time
+							baosp.write(IAC);
+							baosp.write(WONT);
+							baosp.write(abyte0[i]); // either
+							writeByte(baosp.toByteArray());
+							baosp.reset();
+
+							break;
+						}
+					}
+
+					i++;
+					break;
+
+				case WILL:
+
+					switch(abyte0[i]) {
+					case OPT_END_OF_RECORD: // 25
+						baosp.write(IAC);
+						baosp.write(DO);
+						baosp.write(OPT_END_OF_RECORD);
+						writeByte(baosp.toByteArray());
+						baosp.reset();
+
+						break;
+
+					case TRANSMIT_BINARY: // '\0'
+						baosp.write(IAC);
+						baosp.write(DO);
+						baosp.write(TRANSMIT_BINARY);
+						writeByte(baosp.toByteArray());
+						baosp.reset();
+
+						break;
+					}
+					i++;
+					break;
+
+				case SB: // -6
+
+					if(abyte0[i] == NEW_ENVIRONMENT && abyte0[i + 1] == 1) {
+						negNewEnvironment();
+
+						while (++i < abyte0.length && abyte0[i + 1] != IAC);
+					}
+
+					if(abyte0[i] == TERMINAL_TYPE && abyte0[i + 1] == 1) {
+						baosp.write(IAC);
+						baosp.write(SB);
+						baosp.write(TERMINAL_TYPE);
+						baosp.write(QUAL_IS);
+						if(!support132)
+							baosp.write("IBM-3179-2".getBytes());
+						else
+							baosp.write("IBM-3477-FC".getBytes());
+						baosp.write(IAC);
+						baosp.write(SE);
+						writeByte(baosp.toByteArray());
+						baosp.reset();
+
+						i++;
+					}
+					i++;
+					break;
+				}
+			return true;
+		}
+		else {
+			return false;
+		}
+	}
+
+	/**
+	 * Negotiate new environment string for device name
+	 *
+	 * @throws IOException
+	 */
+	private void negNewEnvironment() throws IOException {
+
+		baosp.write(IAC);
+		baosp.write(SB);
+		baosp.write(NEW_ENVIRONMENT);
+		baosp.write(IS);
+
+		// http://tools.ietf.org/html/rfc4777
+
+		if (kbdTypesCodePage != null) {
+			baosp.write(USERVAR);
+			baosp.write("KBDTYPE".getBytes());
+			baosp.write(VALUE);
+			baosp.write(kbdTypesCodePage.kbdType.getBytes());
+
+			baosp.write(USERVAR);
+			baosp.write("CODEPAGE".getBytes());
+			baosp.write(VALUE);
+			baosp.write(kbdTypesCodePage.codepage.getBytes());
+
+			baosp.write(USERVAR);
+			baosp.write("CHARSET".getBytes());
+			baosp.write(VALUE);
+			baosp.write(kbdTypesCodePage.charset.getBytes());
+		}
+
+		if (devName != null) {
+			baosp.write(USERVAR);
+
+			baosp.write("DEVNAME".getBytes());
+
+			baosp.write(VALUE);
+
+			baosp.write(negDeviceName().getBytes());
+		}
+
+		if (user != null) {
+
+			baosp.write(VAR);
+			baosp.write("USER".getBytes());
+			baosp.write(VALUE);
+			baosp.write(user.getBytes());
+
+			if (password != null) {
+				baosp.write(USERVAR);
+				baosp.write("IBMRSEED".getBytes());
+				baosp.write(VALUE);
+				baosp.write(NEGOTIATE_ESC);
+				baosp.write(0x0);
+				baosp.write(0x0);
+				baosp.write(0x0);
+				baosp.write(0x0);
+				baosp.write(0x0);
+				baosp.write(0x0);
+				baosp.write(0x0);
+				baosp.write(0x0);
+				baosp.write(USERVAR);
+				baosp.write("IBMSUBSPW".getBytes());
+				baosp.write(VALUE);
+				baosp.write(password.getBytes());
+			}
+
+			if (library != null) {
+				baosp.write(USERVAR);
+				baosp.write("IBMCURLIB".getBytes());
+				baosp.write(VALUE);
+				baosp.write(library.getBytes());
+			}
+
+			if (initialMenu != null) {
+				baosp.write(USERVAR);
+				baosp.write("IBMIMENU".getBytes());
+				baosp.write(VALUE);
+				baosp.write(initialMenu.getBytes());
+			}
+
+			if (program != null) {
+				baosp.write(USERVAR);
+				baosp.write("IBMPROGRAM".getBytes());
+				baosp.write(VALUE);
+				baosp.write(program.getBytes());
+			}
+		}
+		baosp.write(IAC);
+		baosp.write(SE);
+
+		writeByte(baosp.toByteArray());
+		baosp.reset();
+
+	}
+
+	/**
+	 * This will negotiate a device name with controller. if the sequence is
+	 * less than zero then it will send the device name as specified. On each
+	 * unsuccessful attempt a sequential number is appended until we find one or
+	 * the controller says no way.
+	 *
+	 * @return String
+	 */
+	private String negDeviceName() {
+
+		if (devSeq++ == -1) {
+			devNameUsed = devName;
+			return devName;
+		} else {
+			StringBuffer sb = new StringBuffer(devName + devSeq);
+			int ei = 1;
+			while (sb.length() > 10) {
+
+				sb.setLength(0);
+				sb.append(devName.substring(0, devName.length() - ei++));
+				sb.append(devSeq);
+
+			}
+			devNameUsed = sb.toString();
+			return devNameUsed;
+		}
+	}
+
+	public final void setCodePage(String cp) {
+		codePage = CharMappings.getCodePage(cp);
+		cp = cp.toLowerCase();
+		for (KbdTypesCodePages kbdtyp : KbdTypesCodePages.values()) {
+			if (("cp"+kbdtyp.codepage).equals(cp) || kbdtyp.ccsid.equals(cp)) {
+				kbdTypesCodePage = kbdtyp;
+				break;
+			}
+		}
+		if (log.isInfoEnabled()) {
+			log.info("Choosed keyboard mapping " + kbdTypesCodePage.toString() + " for code page " + cp);
+		}
+	}
+
+	public final ICodePage getCodePage() {
+		return codePage;
+	}
+
+	/**
+	 * @see org.tn5250j.Session5250#signalBell()
+	 */
+	public void signalBell() {
+		controller.signalBell();
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/transport/SSL/SSLImplementation.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,211 @@
+package org.tn5250j.framework.transport.SSL;
+
+/*
+ * @(#)SSLImplementation.java
+ * @author Stephen M. Kennedy
+ *
+ * Copyright:    Copyright (c) 2001
+ *
+ * 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
+ *
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.net.Socket;
+import java.security.KeyStore;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import javax.swing.JOptionPane;
+
+import org.tn5250j.GlobalConfigure;
+import org.tn5250j.framework.transport.SSLInterface;
+import org.tn5250j.tools.logging.TN5250jLogFactory;
+import org.tn5250j.tools.logging.TN5250jLogger;
+
+/**
+ * <p>
+ * This class implements the SSLInterface and is used to create SSL socket
+ * instances.
+ * </p>
+ * 
+ * @author Stephen M. Kennedy <skennedy@tenthpowertech.com>
+ * 
+ */
+public class SSLImplementation implements SSLInterface, X509TrustManager {
+
+	SSLContext sslContext = null;
+
+	KeyStore userks = null;
+	private String userKsPath;
+	private char[] userksPassword = "changeit".toCharArray();
+
+	KeyManagerFactory userkmf = null;
+
+	TrustManagerFactory usertmf = null;
+
+	TrustManager[] userTrustManagers = null;
+
+	X509Certificate[] acceptedIssuers;
+
+	TN5250jLogger logger;
+
+	public SSLImplementation() {
+		logger = TN5250jLogFactory.getLogger(getClass());
+	}
+
+	public void init(String sslType) {
+		try {
+			logger.debug("Initializing User KeyStore");
+			userKsPath = System.getProperty("user.home") + File.separator
+					+ GlobalConfigure.TN5250J_FOLDER + File.separator + "keystore";
+			File userKsFile = new File(userKsPath);
+			userks = KeyStore.getInstance(KeyStore.getDefaultType());
+			userks.load(userKsFile.exists() ? new FileInputStream(userKsFile)
+					: null, userksPassword);
+			logger.debug("Initializing User Key Manager Factory");
+			userkmf = KeyManagerFactory.getInstance(KeyManagerFactory
+					.getDefaultAlgorithm());
+			userkmf.init(userks, userksPassword);
+			logger.debug("Initializing User Trust Manager Factory");
+			usertmf = TrustManagerFactory.getInstance(TrustManagerFactory
+					.getDefaultAlgorithm());
+			usertmf.init(userks);
+			userTrustManagers = usertmf.getTrustManagers();
+			logger.debug("Initializing SSL Context");
+			sslContext = SSLContext.getInstance(sslType);
+			sslContext.init(userkmf.getKeyManagers(), new TrustManager[] {this}, null);
+		} catch (Exception ex) {
+			logger.error("Error initializing SSL [" + ex.getMessage() + "]");
+		}
+
+	}
+
+	public Socket createSSLSocket(String destination, int port) {
+		if (sslContext == null)
+			throw new IllegalStateException("SSL Context Not Initialized");
+		SSLSocket socket = null;
+		try {
+			socket = (SSLSocket) sslContext.getSocketFactory().createSocket(
+					destination, port);
+		} catch (Exception e) {
+			logger.error("Error creating ssl socket [" + e.getMessage() + "]");
+		}
+		return socket;
+	}
+
+	// X509TrustManager Methods
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
+	 */
+	public X509Certificate[] getAcceptedIssuers() {
+		return acceptedIssuers;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.
+	 * X509Certificate[], java.lang.String)
+	 */
+	public void checkClientTrusted(X509Certificate[] arg0, String arg1)
+			throws CertificateException {
+		throw new SecurityException("checkClientTrusted unsupported");
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.
+	 * X509Certificate[], java.lang.String)
+	 */
+	public void checkServerTrusted(X509Certificate[] chain, String type)
+			throws CertificateException {
+		try {
+			for (int i = 0; i < userTrustManagers.length; i++) {
+				if (userTrustManagers[i] instanceof X509TrustManager) {
+					X509TrustManager trustManager = (X509TrustManager) userTrustManagers[i];
+					X509Certificate[] calist = trustManager
+							.getAcceptedIssuers();
+					if (calist.length > 0) {
+						trustManager.checkServerTrusted(chain, type);
+					} else {
+						throw new CertificateException(
+								"Empty list of accepted issuers (a.k.a. root CA list).");
+					}
+				}
+			}
+			return;
+		} catch (CertificateException ce) {
+			X509Certificate cert = chain[0];
+			String certInfo = "Version: " + cert.getVersion() + "\n";
+			certInfo = certInfo.concat("Serial Number: "
+					+ cert.getSerialNumber() + "\n");
+			certInfo = certInfo.concat("Signature Algorithm: "
+					+ cert.getSigAlgName() + "\n");
+			certInfo = certInfo.concat("Issuer: "
+					+ cert.getIssuerDN().getName() + "\n");
+			certInfo = certInfo.concat("Valid From: " + cert.getNotBefore()
+					+ "\n");
+			certInfo = certInfo
+					.concat("Valid To: " + cert.getNotAfter() + "\n");
+			certInfo = certInfo.concat("Subject DN: "
+					+ cert.getSubjectDN().getName() + "\n");
+			certInfo = certInfo.concat("Public Key: "
+					+ cert.getPublicKey().getFormat() + "\n");
+
+			int accept = JOptionPane
+					.showConfirmDialog(null, certInfo, "Unknown Certificate - Do you accept it?",
+							javax.swing.JOptionPane.YES_NO_OPTION);
+			if (accept != JOptionPane.YES_OPTION) {
+				throw new java.security.cert.CertificateException(
+						"Certificate Rejected");
+			}
+
+			int save = JOptionPane.showConfirmDialog(null,
+					"Remember this certificate?", "Save Certificate",
+					javax.swing.JOptionPane.YES_NO_OPTION);
+
+			if (save == JOptionPane.YES_OPTION) {
+				try {
+					userks.setCertificateEntry(cert.getSubjectDN().getName(),
+							cert);
+					userks.store(new FileOutputStream(userKsPath),
+							userksPassword);
+				} catch (Exception e) {
+					logger.error("Error saving certificate [" + e.getMessage()
+							+ "]");
+					e.printStackTrace();
+				}
+			}
+		}
+
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/transport/SSL/X509CertificateTrustManager.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,102 @@
+package org.tn5250j.framework.transport.SSL;
+
+/*
+ * @(#)X509CertificateTrustManager.java
+ *
+ * Copyright:    Copyright (c) 2001
+ *
+ * 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
+ *
+ */
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.X509Certificate;
+import java.security.KeyStore;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.swing.JOptionPane;
+
+/**
+ * This class is used to trust certificates exchanged during an SSL socket
+ * handshake.  It allows the user to accept the certificate so that connections
+ * can be made without requiring the server to have a certificate signed by a
+ * CA (Verisign, Thawte, etc.).
+ *  
+ * @author Stephen M. Kennedy <skennedy@tenthpowertech.com>
+ * @deprecated.  no longer used.
+ *
+ */
+public class X509CertificateTrustManager implements X509TrustManager {
+
+  KeyStore ks = null;
+  TrustManager[] trustManagers;
+  //X509TrustManager trustManager = null;
+
+  public X509CertificateTrustManager(TrustManager[] managers, KeyStore keyStore) {
+    trustManagers = managers;
+    ks = keyStore;
+  }
+
+  public void checkClientTrusted(X509Certificate[] chain, String type) throws CertificateException {
+  	throw new SecurityException("checkClientTrusted unsupported");
+  }
+  
+  
+  /**
+   * Checks the server certificate.  If it isn't trusted by the trust manager
+   * passed to the constructor, then the user will be prompted to accept the
+   * certificate.
+   */
+  public void checkServerTrusted(X509Certificate[] chain, String type) 
+  		throws CertificateException {
+    try {
+    	for (int i=0; i<trustManagers.length; i++) {
+    		if (trustManagers[i] instanceof X509TrustManager)
+    			((X509TrustManager)trustManagers[i]).checkServerTrusted(chain,type);
+    	}
+      return;
+    } catch (CertificateException ce) {
+	      X509Certificate cert = chain[0];
+	      String certInfo = "Version: " + cert.getVersion() + "\n";
+	      certInfo = certInfo.concat("Serial Number: " + cert.getSerialNumber()+"\n");
+	      certInfo = certInfo.concat("Signature Algorithm: " + cert.getSigAlgName()+"\n");
+	      certInfo = certInfo.concat("Issuer: " + cert.getIssuerDN().getName()+"\n");
+	      certInfo = certInfo.concat("Valid From: " + cert.getNotBefore()+"\n");
+	      certInfo = certInfo.concat("Valid To: " + cert.getNotAfter()+"\n");
+	      certInfo = certInfo.concat("Subject DN: " + cert.getSubjectDN().getName()+"\n");
+	      certInfo = certInfo.concat("Public Key: " + cert.getPublicKey().getFormat()+"\n");
+	
+	      int accept = JOptionPane.showConfirmDialog(null,certInfo,
+	                  "Accept Certificate",javax.swing.JOptionPane.YES_NO_OPTION);
+	      if (accept != JOptionPane.YES_OPTION) {
+	        throw new java.security.cert.CertificateException("Certificate Not Accepted");
+	      }
+    	}
+  }
+
+  public X509Certificate[] getAcceptedIssuers() {
+  	ArrayList<X509Certificate> list = new ArrayList<X509Certificate>(10);
+	for (int i=0; i<trustManagers.length; i++) {
+		if (trustManagers[i] instanceof X509TrustManager)
+			list.addAll(Arrays.asList(((X509TrustManager)trustManagers[i]).getAcceptedIssuers()));
+	}
+	X509Certificate[] acceptedIssuers = new X509Certificate[list.size()];
+	acceptedIssuers = list.toArray(acceptedIssuers);
+    return acceptedIssuers;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/transport/SSLInterface.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,44 @@
+package org.tn5250j.framework.transport;
+
+/*
+ * @(#)SSLInterface.java
+ *
+ * Copyright:    Copyright (c) 2001
+ *
+ * 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
+ *
+ */
+import java.net.Socket;
+
+public interface SSLInterface {
+
+	/**
+	 * Initialize the components required to create a new client socket
+	 * when createSSLSocket is called.
+	 * @param type The ssl socket type (SSLv2, SSLv3, TLS)
+	 * @see org.tn5250j.framework.transport.SSLConstants
+	 */
+   public abstract void init(String sslType);
+
+   /**
+    * Create a new socket
+    * @param destination
+    * @param port
+    * @return new socket, or null if none could be created.
+    */
+   public abstract Socket createSSLSocket(String destination, int port);
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tn5250j/framework/transport/SocketConnector.java	Thu May 22 12:11:10 2014 -0700
@@ -0,0 +1,110 @@
+
+/**
+ * @(#)SocketConnector.java
+ * @author Stephen M. Kennedy
+ *
+ * Copyright:    Copyright (c) 2001
+ *
+ * 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.transport;
+
+import java.net.Socket;
+
+import org.tn5250j.TN5250jConstants;
+import org.tn5250j.tools.logging.TN5250jLogFactory;
+import org.tn5250j.tools.logging.TN5250jLogger;
+
+public class SocketConnector {
+
+  String sslType = null;
+
+  TN5250jLogger logger;
+
+  /**
+   * Creates a new instance that creates a plain socket by default.
+   */
+  public SocketConnector() {
+  	logger = TN5250jLogFactory.getLogger(getClass());
+  }
+
+  /**
+   * Set the type of SSL connection to use.  Specify null or an empty string
+   * to use a plain socket. 
+   * @param type The SSL connection type
+   * @see org.tn5250j.framework.transport.SSLConstants
+   */
+  public void setSSLType(String type) {
+    sslType = type;
+  }
+
+  /**
+   * Create a new client Socket to the given destination and port.  If an SSL
+   * socket type has not been specified <i>(by setSSLType(String))</i>, then
+   * a plain socket will be created.  Otherwise, a new SSL socket of the 
+   * specified type will be created.
+   * @param destination
+   * @param port
+   * @return a new client socket, or null if  
+   */
+  public Socket createSocket(String destination, int port) {
+
+  	Socket socket = null;
+  	Exception ex = null;
+  	
+      if (sslType == null || sslType.trim().length() == 0 || 
+      		sslType.toUpperCase().equals(TN5250jConstants.SSL_TYPE_NONE)) {
+        	logger.info("Creating Plain Socket");
+        try {
+			// Use Socket Constructor!!! SocketFactory for jdk 1.4
+			socket = new Socket(destination,port);
+		} catch (Exception e) {
+			ex = e;
+		}
+      } else {  //SSL SOCKET
+
+   		logger.info("Creating SSL ["+sslType+"] Socket");      
+      
+      	SSLInterface sslIf = null;
+      	
+      	String sslImplClassName = 
+      		"org.tn5250j.framework.transport.SSL.SSLImplementation";  
+		try {
+			Class<?> c = Class.forName(sslImplClassName);
+			sslIf = (SSLInterface)c.newInstance();
+		} catch (Exception e) {
+			ex = new Exception("Failed to create SSLInterface Instance. " +
+					"Message is ["+e.getMessage()+"]");
+		}
+		
+      	if (sslIf != null) {
+      		sslIf.init(sslType);
+      		socket = sslIf.createSSLSocket(destination,port);
+      	}
+      }
+
+      if (ex != null) {
+      	logger.error(ex);
+      }
+      if (socket == null) {
+      	logger.warn("No socket was created");
+      }
+      return socket;
+  }
+      
+      
+}
\ No newline at end of file