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