pmattes / x3270

Family of IBM 3270 emulators
46 stars 18 forks source link

s3270 MoveCursor() action changes the cursor position but input field is not activated #79

Closed jhachandan1994 closed 2 months ago

jhachandan1994 commented 2 months ago

when using s3270 with MoveCursor() command i am able to move my cursor to a given position but in case of input fields when i send a string or key and then press enter text is written to previously activated field, somehow cursor position is changed but emulator remains still on the last active input field. This is working properly with c3270 only with s3270 i am facing this issue. is there any action that i need to use after MoveCursor() action ?

pmattes commented 2 months ago

Would it be possible to send me a trace of this misbehavior? Ideally you could turn tracing on just before you call MoveCursor(), so it can capture the contents of the screen.

jhachandan1994 commented 2 months ago

screen-capture.webm

jhachandan1994 commented 2 months ago

I have captured a video of this behaviour first when using MoveCursor you can see that the string that i enter in password field is showing in capital alphabets even though we can see that the string is getting typed on password field the property of string remains same used in user name field and when i send Enter key string sent to password field gets concatenated to user name field. in second example when i use tab instead of movecursor password string goes properly to password field.

i have used "s3270 -httpd 0.0.0.0:9100 pub400.com" this command to start s3270 session. also i tried this on multiple other servers s3270 behaves same in all cases but if i use c3270 this works perfectly fine.

pmattes commented 2 months ago

There is clearly a bug with the interactive form on the s3270 web server. It always appears to be one step behind in its display. But if you ignore the form's display window and simply type exactly the actions you need into the text box one at a time, what s3270 sends to the host is correct.

For example, type String(ABCD) into the box and press Submit. Then (ignoring what is displayed below, it is incorrect), type Tab() into the box and press Submit. Then (still ignoring the display) type String(EFGH) into the box and press Submit. Finally (continuing to ignore the display) type Enter() into the box and press Submit.

Now type Ignore() into the box and press Submit. This does nothing, but now the display window will catch up. You will see that s3270 sent ABCD as the username and EFGH as the password, as you intended.

I will certainly look into the interactive web form's display behavior. Definitely a bug there.

But are you somehow trying to use the interactive web form as a programming interface? It was never intended to be used that way (though that's no excuse for it being broken). It's much easier to use one of the rest APIs than the form. E.g., to send a string, do a GET on http://127.0.0.1:/3270/rest/json/String(ABCD). If you want to see what's on the display, go a GET on http://127.0.0.1:/3270/rest/json/Ascii().

jhachandan1994 commented 2 months ago

@pmattes no not a problem with interactive web form i just sent you the web form because it was better recorded. you see the web server one step behind because i am refreshing the page then new window comes. okay i will send you the terminal window for better understanding.

" For example, type String(ABCD) into the box and press Submit. Then (ignoring what is displayed below, it is incorrect), type Tab() into the box and press Submit. Then (still ignoring the display) type String(EFGH) into the box and press Submit. Finally (continuing to ignore the display) type Enter() into the box and press Submit."

This step will work perfectly i am raising about the MoveCursor command when using MoveCursor command cursor moves to a input field but it seems like input field is not getting in focus and string goes to previous activated input box.

give me some time i will send you terminal window screen.

jhachandan1994 commented 2 months ago

screen-capture (1).webm

If you look at this video after move cursor when i send a string we can see that string is at password field but its actually a part of user name only because for pasword field text gets hidden when i press enter efgh from password field also gets concatenated to username field only. if i do this same process and replace MoveCursor command with Tab it will work but there is certainly some problem with MoveCursor command its not activating the input field where cursor is.

screen-capture (2).webm

In this video you can see i replaced movecursor with tab and when i send password you dont see anything because password field is hidden and after pressing enter both user name and password goes in correct fields.

pmattes commented 2 months ago

I appreciate the videos, but my primary way of debugging s3270 issues is with traces. If you could run s3270 with the '-trace' command-line option, the resulting trace file would show me exactly the actions you are executing and how the host is responding. From that, I (and you) can see if s3270 is doing something wrong.

Without seeing the trace yet, my guess is that you are probably running into an origin issue when you are using MoveCursor(). MoveCursor() uses 0-origin screen coordinates (upper-left is row 0, column 0). There is a newer action called MoveCursor1(), which uses 1-origin screen coordinates (upper-left is row 1, column 1). The cursor position display on the 3270 screen is 1-origin, so this is much less confusing. There are companion methods like Ascii1(), and Show() keywords like Show(Cursor1).

So the issue you are seeing may simply be that you are moving the cursor to the wrong location.

jhachandan1994 commented 2 months ago

Okay. i will generate the trace file and will share. i dont think cursor is moving to wrong location because if you look at the status line after tab and movecursor commands both are matching and i have tried moving cursor forward backward as troubleshooting part and then sending strings but this happens with all fields and on all applications. anyways i will get the trace file lets see if we can get any info from there. thanks for the responses.

jhachandan1994 commented 2 months ago

tracefile_with_move_cursor.txt tracefile_with_tab.txt

These are the two trace files one with movecursor and one with tab. with tab working as expected issue is with movecursor. let me know if any further info is required.

pmattes commented 2 months ago

Okay, I see the problem. You are correct, there is not an issue with the coordinates passed to MoveCursor().

The problem is more subtle than that. pub400.com does not understand how to use a 3270 terminal natively other than a model 2 (24 rows, 80 columns). The default model for s3270 is a model 4 (43 rows, 80 columns). The default model for c3270 depends on the size of the terminal you run it in; it picks the biggest 3270 model that will fit.

When pub400 encounters a 3270 terminal model that it does understand, like a model 2, it negotiates native 3270 mode with the emulator. In native 3270 mode, pub400 sends real 3270 data stream protocol commands to s3270 or c3270. Here is what pub400 looks like with a model 2: image Note that the text is in color, and that in the lower left-hand corner of the display is the text 4A and a reverse-video blank.

When pub400 encounters a 3270 terminal that it does not understand, like a model 4, it does not do 3270 mode negotiation. Instead, it leaves the emulator in NVT mode, where the emulator acts like a xterm (DEC VT100) rather than an IBM 3270. There is software on the host that (imperfectly) translates between the native 5250 protocol and VT100 escape sequences.

Here is what pub400 looks like with a model 4: image Note that the text is all green (pub400 does not know that the terminal supports color) and that in the lower left-hand corner the reverse-video blank has been replaced by a reverse-video 'N', which means NVT Mode.

When you use c3270 interactively with pub400 in this mode, it all pretty much seems to work. And if you use s3270 in this mode, it also seems to work, except when it doesn't. An example of where it doesn't work is with actions like MoveCursor(). When s3270 is emulating a 3270, MoveCursor() moves the 3270 cursor to the requested location. If you type after that, the input goes into the new location. However, when s3270 is in NVT mode, emulating a VT100, MoveCursor() moves the VT100 cursor to the requested location. If you type after that, the host has no idea that you moved the cursor, because the VT100 protocol has no way of telling the host that you moved it. So the host assumes that the 3270 cursor is still where it last told it to be, and your input ends up in the wrong location on the 3270 display (which in this case is being emulated by pub400, not by s3270).

This is probably too much detail, but the easy fix is this: Pass the '-model 2' command line option to s3270. This will allow pub400 to treat s3270 like a real 3270 and not like a VT100, and actions like MoveCursor() will do what you expect.

This is explained here: https://x3270.miraheze.org/wiki/5250_support

jhachandan1994 commented 2 months ago

@pmattes Thanks for the detailed response. Understood, this explains weird behaviour on most of the applications. so after connecting to a host i should check if the connection is in nvt mode if its connected in nvt mode then might need to change model. by default i can keep model 2 as default model for connecting to a host. Thanks again for such a detailed response. i just trie4d by changing model and this worked perfectly fine.

pmattes commented 2 months ago

Oh, and there is no issue with the interactive web form (that was not already known). The interactive web form does not update asynchronously. To see updates generated by the host, you need to refresh the screen manually.

When x3270 is connected in 3270 mode, you will see the result of the String() action reflected in the web form's screen display immediately, because it is purely a local action. When it is connected in NVT mode, String() sends text to the host, and the hosts updates the screen asynchronously (or perhaps not at all). So you need to update the screen manually to see what the host has echoed back.

pmattes commented 2 months ago

@pmattes Thanks for the detailed response. Understood, this explains weird behaviour on most of the applications. so after connecting to a host i should check if the connection is in nvt mode if its connected in nvt mode then might need to change model. by default i can keep model 2 as default model for connecting to a host. Thanks again for such a detailed response. i just trie4d by changing model and this worked perfectly fine.

As far as I know, AS/400's only understand model 2's. So there is no need to try one model and then fall back to a model 2 if it doesn't work. Though I guess there is hope that this will change in the future.

jhachandan1994 commented 2 months ago

@pmattes Understood keeping default model as 2 will work. Thanks.

pmattes commented 2 months ago

I have decided that any possible utility of having MoveCursor() appear to work NVT mode is far outweighed by the confusion it causes. So as of 4.3ga9, MoveCursor() will fail if you try to use it in NVT mode.

jhachandan1994 commented 2 months ago

@pmattes yes that will help users in understanding the issue.