tn5250j/src/org/tn5250j/framework/tn5250 Screen5250.java,NONE,1.1 Stream5250.java,NONE,1.1 DataStreamProducer.java,NONE,1.1 DataStreamQueue.java,NONE,1.1 ScreenFields.java,NONE,1.1 tnvt.java,NONE,1.1 WTDSFParser.java,NONE,1.1 ScreenOIA.java,NONE,1.1 ScreenPlanes.java,NONE,1.1 ScreenField.java,NONE,1.1
"Kenneth J. Pouncey" <[email protected]> Mon, 26 Jul 2004 19:23:02 +0000
| Newsgroups | gmane.comp.java.tn5250j.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/tn5250j/tn5250j/src/org/tn5250j/framework/tn5250
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11632/src/org/tn5250j/framework/tn5250
Added Files:
Screen5250.java Stream5250.java DataStreamProducer.java
DataStreamQueue.java ScreenFields.java tnvt.java
WTDSFParser.java ScreenOIA.java ScreenPlanes.java
ScreenField.java
Log Message:
Added tn5250 package to framwork to start work on the interfaces
--- NEW FILE: DataStreamProducer.java ---
package org.tn5250j.framework.tn5250;
import java.io.*;
import java.net.*;
import org.tn5250j.tools.logging.*;
import org.tn5250j.encoding.CodePage;
public class DataStreamProducer implements Runnable {
private BufferedInputStream bin;
private ByteArrayOutputStream baosin;
private Thread me;
private byte[] saveStream;
private DataStreamQueue dsq;
private tnvt vt;
private byte[] abyte2;
private FileOutputStream fw;
private BufferedOutputStream dw;
private boolean dumpBytes = false;
private CodePage codePage;
private TN5250jLogger log = TN5250jLogFactory.getLogger (this.getClass());
public DataStreamProducer(tnvt vt, BufferedInputStream in, DataStreamQueue queue, byte[] init) {
bin = in;
this.vt = vt;
baosin = new ByteArrayOutputStream();
dsq = queue;
abyte2 = init;
}
public void setInputStream(ByteArrayOutputStream is) {
baosin = is;
}
public void setQueue( DataStreamQueue queue) {
dsq = queue;
}
public final void run() {
boolean done = false;
me = Thread.currentThread();
// load the first response screen
try {
loadStream(abyte2, 0);
}
catch (IOException ioef) {
log.warn(" run() " + ioef.getMessage());
}
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)
throws IOException {
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(new Stream5250(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;
}
else {
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;
}
else
{
return rBytes;
}
}
protected final void toggleDebug (CodePage 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)));
// }
}
--- NEW FILE: tnvt.java ---
/**
* 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
[...3281 lines suppressed...]
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
}
--- NEW FILE: WTDSFParser.java ---
/**
* 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 org.tn5250j.encoding.CodePage;
import org.tn5250j.framework.tn5250.Screen5250;
import org.tn5250j.TN5250jConstants;
/**
*
* Write To Display Structured Field:
*
* This module will parse the Structrued Field information for enhanced
* emulation mode.
*
*/
public class WTDSFParser implements TN5250jConstants {
private Screen5250 screen52;
private Stream5250 bk;
private tnvt vt;
private CodePage codePage;
int pos;
byte[] segment;
int length;
boolean error;
WTDSFParser (tnvt vt) {
this.vt = vt;
screen52 = vt.screen52;
bk = vt.bk;
codePage = vt.codePage;
}
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
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,
'.',
'.',
'.',
':',
':',
':',
'.',
':');
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,
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,
'.',
'.',
'.',
':',
':',
':',
'.',
':');
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++]));
}
System.out.println(
" orientation " + Integer.toBinaryString(orientation) +
" mAttr " + mAttr +
" cAttr " + cAttr +
" Header/Footer " + hfBuffer);
screen52.writeWindowTitle(lastPos,
rows,
cols,
orientation,
mAttr,
cAttr,
hfBuffer);
break;
default:
System.out.println("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
// System.out.println("remove all gui contructs");
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 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;
}
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;
System.out.println(" row: " + screen52.getCurrentRow()
+ " col: " + screen52.getCurrentCol()
+ " type " + typeSelection
+ " gui " + guiDevice
+ " withMnemonic " + withMnemonic
+ " noMnemonic " + Integer.toHexString(noMnemonic)
+ " noMnemonic " + Integer.toBinaryString(noMnemonic)
+ " noMnemonicType " + Integer.toBinaryString((noMnemonic & 0xf0))
+ " noMnemonicSel " + Integer.toBinaryString((noMnemonic & 0x0f))
+ " cols " + cols
+ " rows " + rows);
int rowCtr = 0;
int chcRowStart = screen52.getCurrentRow();
int chcColStart = screen52.getCurrentCol();
screen52.addField(0x20,1,0,0,0,0);
screen52.getScreenFields().getCurrentField().setFieldChar((char)0x20);
screen52.getScreenFields().getCurrentField().setMDT();
//0000: 00 04 AC 9E B9 35 00 01 02 32 BB 4E 08 00 45 00 .....5...2.N..E.
//0010: 00 3C 82 C1 40 00 80 06 00 00 C1 A8 33 58 C1 A8 .<[email protected]..
//0020: 33 01 04 F6 00 17 92 68 71 34 00 02 31 F9 50 18 3......hq4..1.P.
//0030: FD F0 E9 D8 00 00 00 12 12 A0 00 00 04 00 80 03 ................
//0040: 10 05 F1 11 0C 05 00 24 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
screen52.goto_XY(chcRowStart++,chcColStart);
cnt = 5;
int flagCT1 = segment[pos++];
int flagCT2 = segment[pos++];
int flagCT3 = segment[pos++];
int mnemOffset = 0;
boolean aid = false;
boolean selected = false;
// is mnemonic offset specified
if ((flagCT1 & 0x40) == 0x40) {
System.out.println(" selected ");
selected = true;
}
// is mnemonic offset specified
if ((flagCT1 & 0x08) == 8) {
System.out.println(" mnemOffset " + mnemOffset);
mnemOffset = segment[pos++];
cnt++;
}
// is aid key specified
if ((flagCT1 & 0x04) == 4) {
aid = true;
System.out.println(" aidKey " + aid);
// cnt++;
}
// is single digit number specified
if ((flagCT1 & 0x01) == 0x01) {
System.out.println(" single digit " );
pos++;
cnt++;
}
// is double digint number specified
if ((flagCT1 & 0x02) == 0x02) {
System.out.println(" double digit " );
pos++;
cnt++;
}
String s = "";
byte byte0 = 0;
// if (fld++ == 2)
// screen52.addField(colAvail,cols,0x0,0,0,0);
// else
// screen52.addField(colAvail,cols,0x20,0,0,0);
for (;cnt < minLen; cnt++) {
byte0 = segment[pos++];
s += vt.ebcdic2uni(byte0);
screen52.setChar(vt.ebcdic2uni(byte0));
}
screen52.addChoiceField(s);
System.out.println(s + " selected " + selected);
break;
default:
for (cnt = 2;cnt < minLen; cnt++) {
pos++;
}
}
majLen -= minLen;
} while (majLen > 0);
}
catch (Exception exc) {
System.out.println(" defineSelectionField :" + exc.getMessage());
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
}
--- NEW FILE: ScreenField.java ---
/**
* 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.getCols()) + 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.getCols();
}
public int getCursorCol() {
return cursorPos % s.getCols();
}
protected void changePos(int i) {
cursorPos += i;
}
public String getText() {
StringBuffer text = new StringBuffer();
getKeyPos(endPos);
int x = length;
text.setLength(x);
int nc = s.getCols();
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.screen[cursorPos].attributePlace) {
if (s.planes.isAttributePlace(cursorPos)) {
// text.setCharAt(x,(char)('\uff00' + s.screen[cursorPos].attr));
text.setCharAt(x,(char)('\uff00' + s.planes.getCharAttr(cursorPos)));
}
else {
// text.setCharAt(x,s.screen[cursorPos].getChar());
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 void setFieldChar(char c) {
int x = length;
cursorPos = startPos;
while (x-- > 0) {
// s.screen[cursorPos].setChar(c);
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.screen[cursorPos].setChar(c);
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 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;
}
protected int getKeyPos(int row1, int col1) {
int x = ((row1 * s.getCols()) + 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.getCols();
}
/**
* 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.getCols();
}
public int endPos() {
return endPos;
}
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;
}
--- NEW FILE: Screen5250.java ---
/**
* 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.
*
[...4594 lines suppressed...]
// numRows, Color.black, defaultPrinter, (Session) gui);
//
// printerThread.start();
//
// }
// // ADDED BY BARRY
// public ScreenChar[] getCharacters() {
// return this.screen;
// }
// 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;
}
// public Gui5250 getGui() {
// return this.gui;
// }
}
--- NEW FILE: ScreenPlanes.java ---
/**
* 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.
*
[...1056 lines suppressed...]
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;
}
}
--- NEW FILE: ScreenOIA.java ---
/**
* <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.*;
import org.tn5250j.event.ScreenOIAListener;
import org.tn5250j.framework.tn5250.*;
/**
* 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(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;
break;
case INPUTINHIBITED_MACHINECHECK :
machineCheck = whatCode;
break;
case INPUTINHIBITED_SYSTEM_WAIT :
level = whatCode;
break;
case INPUTINHIBITED_NOTINHIBITED :
level = whatCode;
break;
}
saveInhibit = inhibit;
saveInhibitLevel = level;
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 =
(ScreenOIAListener)listeners.elementAt(i);
target.onOIAChanged((ScreenOIA)this, change);
}
}
}
Vector listeners = null;
private boolean insertMode;
private boolean locked;
private boolean keysBuffered;
private int size = 0;
private int owner = 0;
private int level = 0;
private Screen5250 source = null;
private int commCheck = 0;
private int progCheck = 0;
private int machineCheck = 0;
private boolean messageWait;
private boolean scriptRunning;
private int inputInhibited = INPUTINHIBITED_NOTINHIBITED;
private int saveInhibit = -1;
private int saveInhibitLevel = -1;
private String inhibitedText;
}
--- NEW FILE: Stream5250.java ---
/**
* 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 final int getOpCode() {
return opCode;
}
public final byte getNextByte()
throws Exception {
if(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((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;
}
}
--- NEW FILE: ScreenFields.java ---
/**
* 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 java.io.ByteArrayOutputStream;
import org.tn5250j.encoding.CodePage;
import org.tn5250j.TN5250jConstants;
public class ScreenFields implements TN5250jConstants {
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];
}
public 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 boolean isInField(int pos) {
return isInField(pos,true);
}
public boolean isInField() {
return isInField(screen.getLastPos(),true);
}
public 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;
}
public ScreenField[] getFields () {
ScreenField[] fields = new ScreenField[sizeFields];
for (int x = 0; x < sizeFields; x++) {
fields[x] = screenFields[x];
}
return fields;
}
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,
CodePage 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
baosp.write(sf.startRow()+1);
baosp.write(sf.startCol()+1);
}
// int len = sb.length();
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));
}
}
}
}
}
}
}
}
--- NEW FILE: DataStreamQueue.java ---
/**
* 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;
import java.util.Vector;
public class DataStreamQueue {
private final Object lock = new Object();
private final Vector vector;
public DataStreamQueue () {
vector = new Vector();
}
/**
* @todo redo the throttling of large queues that are backed up
* This is the cause of numerous painting bugs.
* @return a datastream object from queue
* @throws InterruptedException
*/
public Object get() throws InterruptedException {
synchronized (lock) {
// wait until there is something to read
while (isEmpty()) {
lock.wait();
}
/**
* @todo here is the throttling code to look at
*
* just something here to try. OK it works but we need to be a little
* more intelligent with the throttling.
*/
if (vector.size() >= 20) {
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
vector.remove(0);
// System.out.println(vector.size());
}
// we have the lock and state we're seeking
return vector.remove(0);
}
}
public boolean isEmpty() {
return vector.isEmpty();
}
public void clear() {
synchronized (lock) {
vector.clear();
lock.notifyAll();
}
}
public void put(Object o) {
synchronized (lock) {
vector.addElement(o);
// if (vector.size() > 5)
// System.out.println(vector.size());
// tell waiting threads to wake up
lock.notifyAll();
}
}
}
-------------------------------------------------------
This SF.Net email is sponsored by BEA Weblogic Workshop
FREE Java Enterprise J2EE developer tools!
Get your free copy of BEA WebLogic Workshop 8.1 today.
http://ads.osdn.com/?ad_id=4721&alloc_id=10040&op=click