Mercurial > 510Connectbot
annotate src/org/tn5250j/framework/tn5250/ScreenFields.java @ 105:1b5887a3bb1c
setField() needs to dirty the modified screen positions
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 18 Jun 2014 10:36:46 -0700 |
parents | 294435151b0c |
children | 77ac18bc1b2f |
rev | line source |
---|---|
3 | 1 /** |
2 * Title: tn5250J | |
3 * Copyright: Copyright (c) 2001 | |
4 * Company: | |
5 * @author Kenneth J. Pouncey | |
6 * @version 0.5 | |
7 * | |
8 * Description: | |
9 * | |
10 * This program is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2, or (at your option) | |
13 * any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this software; see the file COPYING. If not, write to | |
22 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |
23 * Boston, MA 02111-1307 USA | |
24 * | |
25 */ | |
26 package org.tn5250j.framework.tn5250; | |
27 | |
28 import static org.tn5250j.TN5250jConstants.CMD_READ_INPUT_FIELDS; | |
29 import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_FIELDS; | |
30 import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_IMMEDIATE_ALT; | |
31 | |
32 import java.io.ByteArrayOutputStream; | |
33 | |
34 import org.tn5250j.encoding.ICodePage; | |
35 | |
36 public class ScreenFields { | |
37 | |
38 private ScreenField[] screenFields; | |
39 private ScreenField currentField; | |
40 private ScreenField saveCurrent; | |
41 private int sizeFields; | |
42 private boolean cpfExists; | |
43 private int nextField; | |
44 private int fieldIds; | |
45 private Screen5250 screen; | |
46 private boolean masterMDT; | |
47 protected boolean currentModified; | |
48 | |
49 public ScreenFields(Screen5250 s) { | |
50 | |
51 screen = s; | |
52 screenFields = new ScreenField[256]; | |
53 } | |
54 | |
55 protected void clearFFT() { | |
56 | |
57 sizeFields = nextField = fieldIds = 0; | |
58 cpfExists = false; // clear the cursor progression fields flag | |
59 currentField = null; | |
60 masterMDT = false; | |
61 | |
62 } | |
63 | |
64 protected boolean existsAtPos(int lastPos) { | |
65 | |
66 ScreenField sf = null; | |
67 | |
68 // from 14.6.12 for Start of Field Order 5940 function manual | |
69 // examine the format table for an entry that begins at the current | |
70 // starting address plus 1. | |
71 for (int x = 0;x < sizeFields; x++) { | |
72 sf = screenFields[x]; | |
73 | |
74 if (lastPos == sf.startPos()) { | |
75 currentField = sf; | |
76 currentModified = false; | |
77 return true; | |
78 } | |
79 | |
80 } | |
81 | |
82 return false; | |
83 } | |
84 | |
85 public boolean isMasterMDT() { | |
86 return masterMDT; | |
87 } | |
88 | |
89 protected void setMasterMDT() { | |
90 masterMDT = true; | |
91 } | |
92 | |
93 public boolean isCurrentField() { | |
94 return currentField == null; | |
95 } | |
96 | |
97 public boolean isCurrentFieldFER() { | |
98 return currentField.isFER(); | |
99 } | |
100 | |
101 public boolean isCurrentFieldDupEnabled() { | |
102 return currentField.isDupEnabled(); | |
103 } | |
104 | |
105 public boolean isCurrentFieldToUpper() { | |
106 return currentField.isToUpper(); | |
107 } | |
108 | |
109 public boolean isCurrentFieldBypassField() { | |
110 return currentField.isBypassField(); | |
111 } | |
112 | |
113 public boolean isCurrentFieldHighlightedEntry() { | |
114 if (currentField != null) | |
115 return currentField.isHiglightedEntry(); | |
116 else | |
117 return false; | |
118 } | |
119 | |
120 public boolean isCurrentFieldAutoEnter() { | |
121 return currentField.isAutoEnter(); | |
122 } | |
123 | |
124 public boolean withinCurrentField(int pos) { | |
125 return currentField.withinField(pos); | |
126 } | |
127 | |
128 public boolean isCurrentFieldContinued() { | |
129 return currentField.isContinued(); | |
130 } | |
131 | |
132 public boolean isCurrentFieldContinuedFirst() { | |
133 return currentField.isContinuedFirst(); | |
134 } | |
135 | |
136 public boolean isCurrentFieldContinuedMiddle() { | |
137 return currentField.isContinuedMiddle(); | |
138 } | |
139 | |
140 public boolean isCurrentFieldContinuedLast() { | |
141 return currentField.isContinuedLast(); | |
142 } | |
143 | |
144 public boolean isCurrentFieldModified() { | |
145 return currentModified; | |
146 } | |
147 | |
148 /** | |
149 * This routine is used to check if we can send the Aid key to the host | |
150 * | |
151 * Taken from Section 16.2.1.2 Enter/Rec Adv Key | |
152 * | |
153 * In the normal unlocked state, when the workstation operator presses the | |
154 * Enter/Rec Adv key: | |
155 * | |
156 * 1. The 5494 checks for the completion of mandatory-fill, self-check, and | |
157 * right-adjust fields when in an active field. (An active field is one in | |
158 * which the workstation operator has begun entering data.) If the | |
159 * requirements of the field have not been satisfied, an error occurs. | |
160 * | |
161 * @return | |
162 * | |
163 */ | |
164 public boolean isCanSendAid() { | |
165 | |
166 // We also have to check if we are still in the field. | |
167 if (currentField != null && | |
168 (currentField.getAdjustment() > 0 || currentField.isSignedNumeric()) | |
169 && currentModified && isInField() | |
170 && !currentField.isCanSend()) | |
171 | |
172 return false; | |
173 else | |
174 return true; | |
175 | |
176 } | |
177 | |
178 protected void saveCurrentField() { | |
179 saveCurrent = currentField; | |
180 } | |
181 | |
182 protected void restoreCurrentField() { | |
183 currentField = saveCurrent; | |
184 } | |
185 | |
186 protected void setCurrentField(ScreenField sf) { | |
187 currentField = sf; | |
188 } | |
189 | |
190 protected void setCurrentFieldMDT() { | |
191 currentField.setMDT(); | |
192 currentModified = true; | |
193 masterMDT = true; | |
194 } | |
195 | |
196 protected void setCurrentFieldFFWs(int ffw1, int ffw2) { | |
197 | |
198 masterMDT = currentField.setFFWs(ffw1,ffw2); | |
199 | |
200 } | |
201 | |
202 | |
203 protected ScreenField setField(int attr, int row, int col, int len, int ffw1, | |
204 int ffw2, int fcw1, int fcw2) { | |
205 | |
206 ScreenField sf = null; | |
207 screenFields[nextField] = new ScreenField(screen); | |
208 screenFields[nextField].setField(attr,row,col,len,ffw1,ffw2,fcw1,fcw2); | |
209 sf = screenFields[nextField++]; | |
210 | |
211 sizeFields++; | |
212 | |
213 | |
214 // set the field id if it is not a bypass field | |
215 // this is used for cursor progression | |
216 // changed this because of problems not allocating field id's for | |
217 // all fields. kjp 2002/10/21 | |
218 // if (!sf.isBypassField()) | |
219 sf.setFieldId(++fieldIds); | |
220 | |
221 // check if the cursor progression field flag should be set. | |
222 // if ((fcw1 & 0x88) == 0x88) | |
223 if (fcw1 == 0x88) | |
224 cpfExists = true; | |
225 | |
226 if (currentField != null) { | |
227 currentField.next = sf; | |
228 sf.prev = currentField; | |
229 } | |
230 | |
231 currentField = sf; | |
232 | |
233 // check if the Modified Data Tag was set while creating the field | |
234 if (!masterMDT) | |
235 masterMDT = currentField.mdt; | |
236 | |
237 currentModified = false; | |
238 | |
239 return currentField; | |
240 | |
241 } | |
242 | |
243 public ScreenField getField(int index) { | |
244 | |
245 return screenFields[index]; | |
246 } | |
247 | |
248 public ScreenField getCurrentField() { | |
249 return currentField; | |
250 } | |
251 | |
252 public int getCurrentFieldPos() { | |
253 return currentField.getCurrentPos(); | |
254 } | |
255 | |
256 protected int getCurrentFieldShift() { | |
257 return currentField.getFieldShift(); | |
258 } | |
259 | |
260 public String getCurrentFieldText() { | |
261 | |
262 return currentField.getText(); | |
263 } | |
264 | |
265 public int getCurrentFieldHighlightedAttr(){ | |
266 return currentField.getHighlightedAttr(); | |
267 } | |
268 | |
269 public int getSize() { | |
270 | |
271 return sizeFields; | |
272 } | |
273 | |
274 public int getFieldCount() { | |
275 | |
276 return sizeFields; | |
277 } | |
278 | |
279 protected boolean isInField(int pos) { | |
280 return isInField(pos,true); | |
281 } | |
282 | |
283 protected boolean isInField() { | |
284 return isInField(screen.getLastPos(),true); | |
285 } | |
286 | |
287 protected boolean isInField(int pos, boolean chgToField) { | |
288 | |
289 ScreenField sf; | |
290 | |
291 for (int x = 0;x < sizeFields; x++) { | |
292 sf = screenFields[x]; | |
293 | |
294 if (sf.withinField(pos)) { | |
295 | |
296 if (chgToField) { | |
297 if (!currentField.equals(sf)) | |
298 currentModified = false; | |
299 currentField = sf; | |
300 } | |
301 return true; | |
302 } | |
303 } | |
304 return false; | |
305 | |
306 } | |
307 | |
308 /** | |
309 * Searches the collection for the target string and returns the iOhioField | |
310 * object containing that string. The string must be totally contained | |
311 * within the field to be considered a match. | |
312 * | |
313 * @param targetString The target string. | |
314 * @param startPos The row and column where to start the search. The position | |
315 * is inclusive (for example, row 1, col 1 means that | |
316 * position 1,1 will be used as the starting location and | |
317 * 1,1 will be included in the search). | |
318 * @param length The length from startPos to include in the search. | |
319 * @param dir An OHIO_DIRECTION value: | |
320 * | |
321 * <table BORDER COLS=3 WIDTH="50%" > | |
322 * <tr><th>Constant </th><th>Value</th> | |
323 * <th>Description</th></tr> | |
324 * <tr><td>OS_OHIO_DIRECTION_FORWARD </td><td>0</td> | |
325 * <td>Forward (beginning towards end)</td></tr> | |
326 * <tr><td>OS_OHIO_DIRECTION_BACKWARD </td><td>1</td> | |
327 * <td>Backward (end towards beginning)</td></tr> | |
328 * </table> | |
329 * Constant Value Description | |
330 * ignoreCase - Indicates whether the search is case sensitive. | |
331 * True means that case will be ignored. False means the search will | |
332 * be case sensitive. | |
333 * @return If found, an iOhioField object containing the target string. If | |
334 * not found, returns a null. | |
335 */ | |
336 public ScreenField findByString (String targetString, | |
337 int startPos, | |
338 int length, | |
339 int dir, | |
340 boolean ignoreCase) { | |
341 | |
342 // first lets check if the string exists in the screen space | |
343 // iOhioPosition pos = screen.findString(targetString, startPos, length, | |
344 // dir, ignoreCase); | |
345 | |
346 // if it does exist then lets search the fields by the position that | |
347 // was found and return the results of that search. | |
348 // if (pos != null) { | |
349 return findByPosition(startPos); | |
350 // } | |
351 | |
352 //return null; | |
353 | |
354 } | |
355 | |
356 /** | |
357 * Searches the collection for the target position and returns the ScreenField | |
358 * object containing that position. | |
359 * | |
360 * @param targetPosition The target row and column expressed as a linear | |
361 * position within the presentation space. | |
362 * | |
363 * @return If found, a ScreenField object containing the target position. | |
364 * If not found, returns a null. | |
365 */ | |
366 public ScreenField findByPosition(int targetPosition) { | |
367 | |
368 ScreenField sf = null; | |
369 | |
370 for (int x = 0;x < sizeFields; x++) { | |
371 | |
372 sf = screenFields[x]; | |
373 | |
374 if (sf.withinField(targetPosition)) { | |
375 return sf; | |
376 } | |
377 | |
378 } | |
379 | |
380 return null; | |
381 } | |
382 | |
383 /** | |
384 * Searches the collection for the target position and returns the ScreenField | |
385 * object containing that position. | |
386 * | |
387 * @param row The beginning row to start search with in the presentation space. | |
388 * @param col The beginning column to start search with in the presentation space. | |
389 * | |
390 * @return If found, a ScreenField object containing the target position. | |
391 * If not found, returns a null. | |
392 */ | |
393 public ScreenField findByPosition(int row, int col) { | |
394 | |
395 return findByPosition(screen.getPos(row,col)); | |
396 } | |
397 | |
398 public ScreenField[] getFields () { | |
399 | |
400 ScreenField[] fields = new ScreenField[sizeFields]; | |
401 for (int x = 0; x < sizeFields; x++) { | |
402 | |
403 fields[x] = screenFields[x]; | |
404 } | |
405 | |
406 return fields; | |
407 } | |
408 | |
409 public ScreenField getFirstInputField() { | |
410 | |
411 if (sizeFields <= 0) | |
412 return null; | |
413 | |
414 int f = 0; | |
415 ScreenField sf = screenFields[f]; | |
416 | |
417 while (sf.isBypassField() && f++ < sizeFields) { | |
418 sf = screenFields[f]; | |
419 } | |
420 | |
421 if (sf.isBypassField()) | |
422 return null; | |
423 else | |
424 return sf; | |
425 | |
426 } | |
427 | |
428 public void gotoFieldNext() { | |
429 | |
69
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
430 // sanity check - we were getting null pointers after a restore of screen |
3 | 431 // and cursor was not positioned on a field when returned |
432 // *** Note *** to myself | |
433 // maybe this is fixed I will have to check this some time | |
434 int lastPos = screen.getLastPos(); | |
435 | |
436 if (currentField == null && (sizeFields != 0) && !isInField(lastPos,true)) { | |
437 int pos = lastPos; | |
438 screen.setCursorOff(); | |
439 screen.advancePos(); | |
440 lastPos = screen.getLastPos(); | |
441 while (!isInField() && pos != lastPos) { | |
442 screen.advancePos(); | |
443 } | |
444 screen.setCursorOn(); | |
445 } | |
446 | |
447 // if we are still null do nothing | |
448 if (currentField == null) | |
449 return; | |
450 | |
451 ScreenField sf = currentField; | |
452 | |
453 if (!sf.withinField(lastPos)) { | |
454 screen.setCursorOff(); | |
455 | |
456 if (sizeFields > 0) { | |
457 | |
458 // lets get the current position so we can test if we have looped | |
459 // the screen and not found a valid field. | |
460 int pos = lastPos; | |
461 int savPos = lastPos; | |
462 boolean done = false; | |
463 do { | |
464 screen.advancePos(); | |
465 lastPos = screen.getLastPos(); | |
466 if (isInField(lastPos) | |
467 || pos==lastPos) { | |
468 if (!currentField.isBypassField()) { | |
469 screen.gotoField(currentField); | |
470 done = true; | |
471 } | |
472 } | |
473 } while ( !done && lastPos != savPos); | |
474 } | |
475 currentModified = false; | |
476 screen.setCursorOn(); | |
477 | |
478 } | |
479 else { | |
480 if (!cpfExists) { | |
481 do { | |
482 | |
483 sf = sf.next; | |
484 } | |
485 while ( sf != null && sf.isBypassField()); | |
486 | |
487 } | |
488 else { | |
489 int f = 0; | |
490 int cp = sf.getCursorProgression(); | |
491 | |
492 if (cp == 0) { | |
493 do { | |
494 | |
495 sf = sf.next; | |
496 } | |
497 while ( sf != null && sf.isBypassField()); | |
498 | |
499 } | |
500 else { | |
501 ScreenField sf1 = null; | |
502 boolean found = false; | |
503 while (!found && f < sizeFields) { | |
504 | |
505 sf1 = screenFields[f++]; | |
506 if (sf1.getFieldId() == cp) | |
507 found = true; | |
508 } | |
509 if (found) | |
510 sf = sf1; | |
511 else { | |
512 do { | |
513 sf = sf.next; | |
514 } | |
515 while ( sf != null && sf.isBypassField()); | |
516 | |
517 } | |
518 sf1 = null; | |
519 } | |
520 } | |
521 if (sf == null) | |
522 screen.gotoField(1); | |
523 else { | |
524 currentField = sf; | |
525 screen.gotoField(currentField); | |
526 } | |
527 | |
528 currentModified = false; | |
529 | |
530 } | |
531 } | |
532 | |
533 public void gotoFieldPrev() { | |
534 | |
535 ScreenField sf = currentField; | |
536 int lastPos = screen.getLastPos(); | |
537 | |
538 if (!sf.withinField(lastPos)) { | |
539 screen.setCursorOff(); | |
540 | |
541 if (sizeFields > 0) { | |
542 // lets get the current position so we can test if we have looped | |
543 // the screen and not found a valid field. | |
544 int pos = lastPos; | |
545 int savPos = lastPos; | |
546 boolean done = false; | |
547 | |
548 do { | |
549 screen.changePos(-1); | |
550 lastPos = screen.getLastPos(); | |
551 | |
552 if (isInField(lastPos) | |
553 || (pos == lastPos)) { | |
554 | |
555 if (!currentField.isBypassField()) { | |
556 screen.gotoField(currentField); | |
557 done = true; | |
558 } | |
559 } | |
560 } while ( !done && lastPos != savPos); | |
561 } | |
562 screen.setCursorOn(); | |
563 | |
564 } | |
565 else { | |
566 | |
567 if (sf.startPos() == lastPos) { | |
568 if (!cpfExists) { | |
569 | |
570 do { | |
571 sf = sf.prev; | |
572 } | |
573 while ( sf != null && sf.isBypassField()); | |
574 } | |
575 else { | |
576 | |
577 int f = 0; | |
578 int cp = sf.getFieldId(); | |
579 ScreenField sf1 = null; | |
580 boolean found = false; | |
581 while (!found && f < sizeFields) { | |
582 | |
583 sf1 = screenFields[f++]; | |
584 if (sf1.getCursorProgression() == cp) | |
585 found = true; | |
586 } | |
587 if (found) | |
588 sf = sf1; | |
589 else { | |
590 do { | |
591 sf = sf.prev; | |
592 } | |
593 while ( sf != null && sf.isBypassField()); | |
594 } | |
595 sf1 = null; | |
596 } | |
597 } | |
598 | |
599 if (sf == null) { | |
600 int size = sizeFields; | |
601 sf = screenFields[size - 1]; | |
602 | |
603 while (sf.isBypassField() && size-- > 0) { | |
604 sf = screenFields[size]; | |
605 | |
606 } | |
607 } | |
608 currentField = sf; | |
609 currentModified = false; | |
610 screen.gotoField(currentField); | |
611 } | |
612 } | |
613 | |
614 protected void readFormatTable(ByteArrayOutputStream baosp,int readType, ICodePage codePage) { | |
615 | |
616 ScreenField sf; | |
617 boolean isSigned = false; | |
618 char c; | |
619 | |
620 if (masterMDT) { | |
621 | |
622 StringBuffer sb = new StringBuffer(); | |
623 for (int x = 0; x < sizeFields; x++) { | |
624 isSigned = false; | |
625 | |
626 sf = screenFields[x]; | |
627 | |
628 if (sf.mdt || (readType == CMD_READ_INPUT_FIELDS)) { | |
629 | |
630 sb.setLength(0); | |
631 sb.append(sf.getText()); | |
632 | |
633 | |
634 if (readType == CMD_READ_MDT_FIELDS || | |
635 readType == CMD_READ_MDT_IMMEDIATE_ALT) { | |
636 int len = sb.length() - 1; | |
637 | |
638 // we strip out all '\u0020' and less | |
639 while (len >= 0 && | |
640 // (sb.charAt(len) <= ' ' || sb.charAt(len) >= '\uff20' )) { | |
641 (sb.charAt(len) < ' ' || sb.charAt(len) >= '\uff20')) { | |
642 | |
643 // if we have the dup character and dup is enabled then we | |
644 // stop here | |
645 if (sb.charAt(len) == 0x1C && sf.isDupEnabled()) | |
646 break; | |
647 | |
648 sb.deleteCharAt(len--); | |
649 } | |
650 | |
651 } | |
652 | |
653 // System.out.println("field " + sf.toString()); | |
654 // System.out.println(">" + sb.toString() + "<"); | |
655 // System.out.println(" field is all nulls"); | |
656 if (sf.isSignedNumeric() && sb.length() > 0 && sb.charAt(sb.length() - 1) == '-') { | |
657 isSigned = true; | |
658 sb.setLength(sb.length() - 1); | |
659 } | |
660 | |
661 int len3 = sb.length(); | |
662 | |
663 if (len3 > 0 || (readType == CMD_READ_MDT_FIELDS || | |
664 readType == CMD_READ_MDT_IMMEDIATE_ALT)) { | |
665 | |
666 if ((readType == CMD_READ_MDT_FIELDS || | |
667 readType == CMD_READ_MDT_IMMEDIATE_ALT)) { | |
668 | |
669 baosp.write(17); // start of field data | |
670 if (sf.isSelectionField()) { | |
671 baosp.write(screen.getRow(sf.selectionPos)+1); | |
672 baosp.write(screen.getCol(sf.selectionPos)+1); | |
673 } | |
674 else { | |
675 baosp.write(sf.startRow()+1); | |
676 baosp.write(sf.startCol()+1); | |
677 } | |
678 | |
679 } | |
680 // int len = sb.length(); | |
681 if (sf.isSelectionField()) { | |
682 baosp.write(0); | |
683 baosp.write(sf.selectionIndex + 0x1F); | |
684 | |
685 } | |
686 else { | |
687 for (int k = 0; k < len3; k++) { | |
688 c = sb.charAt(k); | |
689 // here we have to check for special instances of the | |
690 // characters in the string field. Attribute bytes | |
691 // are encoded with an offset of \uff00 | |
692 // This is a hack !!!!!!!!!!! | |
693 // See ScreenField object for a description | |
694 if (c < ' ' || c >= '\uff20') { | |
695 | |
696 // if it is an offset attribute byte we just pass | |
697 // it straight on to the output stream | |
698 if (c >= '\uff20' && c <= '\uff3f') { | |
699 baosp.write(c - '\uff00'); | |
700 } | |
701 else | |
702 // check for dup character | |
703 if (c == 0x1C) | |
704 baosp.write(c); | |
705 else | |
706 baosp.write(codePage.uni2ebcdic(' ')); | |
707 } | |
708 else { | |
709 if (isSigned && k == len3 - 1) { | |
710 baosp.write(0xd0 | (0x0f & c)); | |
711 } | |
712 else | |
713 baosp.write(codePage.uni2ebcdic(c)); | |
714 | |
715 } | |
716 } | |
717 } | |
718 } | |
719 } | |
720 } | |
721 } | |
722 } | |
723 | |
724 } |