diff --git a/src/include/lib3270.h b/src/include/lib3270.h index d67eb1a..868af9f 100644 --- a/src/include/lib3270.h +++ b/src/include/lib3270.h @@ -509,18 +509,17 @@ */ LIB3270_EXPORT int lib3270_set_cursor_address(H3270 *h, int baddr); - LIB3270_EXPORT int lib3270_set_cursor_position(H3270 *h, int row, int col); - /** - * Move cursor + * Set cursor position. * * @param h Session handle. - * @param dir Direction to move - * @param sel Non zero to move and selected to the current cursor position + * @param row New cursor row. + * @param col New cursor col. + * + * @return last cursor address. * - * @return 0 if the movement can be done, non zero if failed. */ - LIB3270_EXPORT int lib3270_move_cursor(H3270 *h, LIB3270_DIRECTION dir, unsigned char sel); + LIB3270_EXPORT int lib3270_set_cursor_position(H3270 *h, int row, int col); /** * get cursor address. @@ -532,6 +531,18 @@ */ LIB3270_EXPORT int lib3270_get_cursor_address(H3270 *h); + + /** + * Move cursor + * + * @param h Session handle. + * @param dir Direction to move + * @param sel Non zero to move and selected to the current cursor position + * + * @return 0 if the movement can be done, non zero if failed. + */ + LIB3270_EXPORT int lib3270_move_cursor(H3270 *h, LIB3270_DIRECTION dir, unsigned char sel); + /** * Print page * diff --git a/src/plugins/dbus3270/gobject.c b/src/plugins/dbus3270/gobject.c index 09114a3..1e6ea0c 100644 --- a/src/plugins/dbus3270/gobject.c +++ b/src/plugins/dbus3270/gobject.c @@ -222,6 +222,23 @@ void pw3270_dbus_set_text_at(PW3270Dbus *object, int row, int col, const gchar * g_free(text); } +void pw3270_dbus_input(PW3270Dbus *object, const gchar *utftext, DBusGMethodInvocation *context) +{ + gchar * text; + H3270 * hSession = pw3270_dbus_get_session_handle(object); + + trace("%s object=%p context=%p",__FUNCTION__,object,context); + if(pw3270_dbus_check_valid_state(object,context)) + return; + + text = g_convert_with_fallback(utftext,-1,lib3270_get_charset(hSession),"UTF-8","?",NULL,NULL,NULL); + + dbus_g_method_return(context,lib3270_emulate_input(hSession,(const char *) text,-1,1)); + + g_free(text); +} + + void pw3270_dbus_get_text_at(PW3270Dbus *object, int row, int col, int len, DBusGMethodInvocation *context) { gchar * text; @@ -282,6 +299,18 @@ void pw3270_dbus_get_text_at(PW3270Dbus *object, int row, int col, int len, DBus dbus_g_method_return(context,lib3270_set_cursor_position(pw3270_dbus_get_session_handle(object),row,col)); } + void pw3270_dbus_set_cursor_address(PW3270Dbus *object, int addr, DBusGMethodInvocation *context) + { + trace("%s object=%p context=%p",__FUNCTION__,object,context); + dbus_g_method_return(context,lib3270_set_cursor_address(pw3270_dbus_get_session_handle(object),addr)); + } + + void pw3270_dbus_get_cursor_address(PW3270Dbus *object, DBusGMethodInvocation *context) + { + trace("%s object=%p context=%p",__FUNCTION__,object,context); + dbus_g_method_return(context,lib3270_get_cursor_address(pw3270_dbus_get_session_handle(object))); + } + void pw3270_dbus_set_toggle(PW3270Dbus *object, int id, int value, DBusGMethodInvocation *context) { trace("%s object=%p context=%p",__FUNCTION__,object,context); diff --git a/src/plugins/dbus3270/pw3270dbus.xml b/src/plugins/dbus3270/pw3270dbus.xml index d706af0..4108b13 100644 --- a/src/plugins/dbus3270/pw3270dbus.xml +++ b/src/plugins/dbus3270/pw3270dbus.xml @@ -44,6 +44,10 @@ + + + + @@ -80,6 +84,15 @@ + + + + + + + + + diff --git a/src/plugins/dbus3270/service.h b/src/plugins/dbus3270/service.h index 35909a0..515f247 100644 --- a/src/plugins/dbus3270/service.h +++ b/src/plugins/dbus3270/service.h @@ -76,7 +76,11 @@ void pw3270_dbus_is_connected(PW3270Dbus *object, DBusGMethodInvocation *context); void pw3270_dbus_is_ready(PW3270Dbus *object, DBusGMethodInvocation *context); void pw3270_dbus_in_tn3270_e(PW3270Dbus *object, DBusGMethodInvocation *context); + void pw3270_dbus_set_cursor_at(PW3270Dbus *object, int row, int col, DBusGMethodInvocation *context); + void pw3270_dbus_set_cursor_address(PW3270Dbus *object, int addr, DBusGMethodInvocation *context); + void pw3270_dbus_get_cursor_address(PW3270Dbus *object, DBusGMethodInvocation *context); + void pw3270_dbus_set_toggle(PW3270Dbus *object, int id, int value, DBusGMethodInvocation *context); void pw3270_dbus_wait_for_ready(PW3270Dbus *object, int timeout, DBusGMethodInvocation *context); @@ -91,6 +95,7 @@ void pw3270_dbus_set_text_at(PW3270Dbus *object, int row, int col, const gchar *text, DBusGMethodInvocation *context); void pw3270_dbus_get_text_at(PW3270Dbus *object, int row, int col, int len, DBusGMethodInvocation *context); void pw3270_dbus_cmp_text_at(PW3270Dbus *object, int row, int col, const gchar *text, DBusGMethodInvocation *context); + void pw3270_dbus_input(PW3270Dbus *object, const gchar *utftext, DBusGMethodInvocation *context); G_END_DECLS diff --git a/src/plugins/rx3270/local.cc b/src/plugins/rx3270/local.cc index 17f8c0d..ce14a91 100644 --- a/src/plugins/rx3270/local.cc +++ b/src/plugins/rx3270/local.cc @@ -72,8 +72,11 @@ char * get_text_at(int row, int col, size_t sz); int cmp_text_at(int row, int col, const char *text); int set_text_at(int row, int col, const char *str); + int emulate_input(const char *str); int set_cursor_position(int row, int col); + int set_cursor_addr(int addr); + int get_cursor_addr(void); int set_toggle(LIB3270_TOGGLE ix, bool value); @@ -106,6 +109,9 @@ int (*_set_toggle)(H3270 *h, LIB3270_TOGGLE ix, int value); int (*_get_field_start)(H3270 *h, int baddr); int (*_get_field_len)(H3270 *h, int baddr); + int (*_set_cursor_addr)(H3270 *h, int addr); + int (*_get_cursor_addr)(H3270 *h); + int (*_emulate_input)(H3270 *session, const char *s, int len, int pasting); #ifdef WIN32 HMODULE hModule; @@ -235,6 +241,9 @@ dynamic::dynamic() { (void **) & _set_toggle, "lib3270_set_toggle" }, { (void **) & _get_field_start, "lib3270_get_field_start" }, { (void **) & _get_field_len, "lib3270_get_field_len" }, + { (void **) & _set_cursor_addr, "lib3270_set_cursor_address" }, + { (void **) & _get_cursor_addr, "lib3270_get_cursor_address" }, + { (void **) & _emulate_input, "lib3270_emulate_input" }, }; @@ -533,3 +542,23 @@ int dynamic::get_field_len(int baddr) return -1; } +int dynamic::set_cursor_addr(int addr) +{ + if(hModule) + return _set_cursor_addr(hSession,addr); + return -1; +} + +int dynamic::get_cursor_addr(void) +{ + if(hModule) + return _get_cursor_addr(hSession); + return -1; +} + +int dynamic::emulate_input(const char *str) +{ + if(hModule) + return _emulate_input(hSession,str,-1,1); + return -1; +} diff --git a/src/plugins/rx3270/pluginmain.cc b/src/plugins/rx3270/pluginmain.cc index e6179a8..a88255f 100644 --- a/src/plugins/rx3270/pluginmain.cc +++ b/src/plugins/rx3270/pluginmain.cc @@ -87,6 +87,9 @@ int set_text_at(int row, int col, const char *str); int set_cursor_position(int row, int col); + int set_cursor_addr(int addr); + int get_cursor_addr(void); + int emulate_input(const char *str); int set_toggle(LIB3270_TOGGLE ix, bool value); @@ -282,6 +285,21 @@ g_free(ptr); } + int plugin::set_cursor_addr(int addr) + { + return lib3270_set_cursor_address(hSession,addr); + } + + int plugin::get_cursor_addr(void) + { + return lib3270_get_cursor_address(hSession); + } + + int plugin::emulate_input(const char *str) + { + return lib3270_emulate_input(hSession, str, -1, 1); + } + static int REXXENTRY Rexx_IO_exit(RexxExitContext *context, int exitnumber, int subfunction, PEXIT parmBlock) { trace("%s call with ExitNumber: %d Subfunction: %d",__FUNCTION__,(int) exitnumber, (int) subfunction); @@ -336,10 +354,10 @@ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CANCEL, - "%s", _( "Can't start script" )); + _( "Can't start %s script" ), "rexx" ); gtk_window_set_title(GTK_WINDOW(dialog),_( "Rexx error" )); - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),"%s",_( "Can't create rexx interpreter instance" )); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),_( "Can't create %s interpreter instance" ), "rexx"); gtk_dialog_run(GTK_DIALOG (dialog)); gtk_widget_destroy(dialog); @@ -383,13 +401,14 @@ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CANCEL, - "%s", _( "Rexx script failed" )); + _( "%s script failed" ), "Rexx" ); gtk_window_set_title(GTK_WINDOW(dialog),_( "Rexx error" )); gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG(dialog), - _( "Rexx error %d: %s\n%s" ), + _( "%s error %d: %s\n%s" ), + "Rexx", (int) condition.code, threadContext->CString(condition.errortext), threadContext->CString(condition.message) @@ -471,7 +490,7 @@ extern "C" gtk_file_filter_add_pattern(filter[f],list[f].pattern); } - filename = pw3270_get_filename(widget,"rexx","script",filter,_( "Select Rexx script to run" )); + filename = pw3270_get_filename(widget,"rexx","script",filter,_( "Select script to run" )); if(filename) { diff --git a/src/plugins/rx3270/remote.cc b/src/plugins/rx3270/remote.cc index a02d60c..b504c09 100644 --- a/src/plugins/rx3270/remote.cc +++ b/src/plugins/rx3270/remote.cc @@ -65,10 +65,13 @@ char * get_text_at(int row, int col, size_t sz); int cmp_text_at(int row, int col, const char *text); int set_text_at(int row, int col, const char *str); + int emulate_input(const char *str); int wait_for_text_at(int row, int col, const char *key, int timeout); int set_cursor_position(int row, int col); + int set_cursor_addr(int addr); + int get_cursor_addr(void); int set_toggle(LIB3270_TOGGLE ix, bool value); @@ -799,6 +802,44 @@ int remote::set_text_at(int row, int col, const char *str) return -1; } +int remote::emulate_input(const char *str) +{ +#if defined(WIN32) + + if(hPipe != INVALID_HANDLE_VALUE) + { + size_t len = strlen(str); + struct hllapi_packet_emulate_input * query; + struct hllapi_packet_result response; + DWORD cbSize = sizeof(struct hllapi_packet_emulate_input)+len; + + query = (struct hllapi_packet_emulate_input *) malloc(cbSize); + query->packet_id = HLLAPI_PACKET_EMULATE_INPUT; + query->len = len; + query->pasting = 1; + strcpy(query->text,str); + + TransactNamedPipe(hPipe,(LPVOID) query, cbSize, &response, sizeof(response), &cbSize,NULL); + + free(query); + + return response.rc; + } + +#elif defined(HAVE_DBUS) + + DBusMessage * msg = create_message("input"); + if(msg) + { + dbus_message_append_args(msg, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID); + return get_intval(call(msg)); + } + +#endif + + return -1; +} + int remote::set_cursor_position(int row, int col) { #if defined(WIN32) @@ -1031,3 +1072,56 @@ char * remote::get_text(int baddr, size_t len) #warning IMPLEMENTAR return NULL; } + +int remote::set_cursor_addr(int addr) +{ +#if defined(WIN32) + + if(hPipe != INVALID_HANDLE_VALUE) + { + struct hllapi_packet_addr query = { HLLAPI_PACKET_FIELD_LEN, (unsigned short) addr }; + struct hllapi_packet_result response; + DWORD cbSize = sizeof(query); + TransactNamedPipe(hPipe,(LPVOID) &query, cbSize, &response, sizeof(response), &cbSize,NULL); + return response.rc; + } + +#elif defined(HAVE_DBUS) + + dbus_int32_t k = (dbus_int32_t) addr; + + DBusMessage * msg = create_message("setCursorAddress"); + if(msg) + { + dbus_message_append_args(msg, DBUS_TYPE_INT32, &k, DBUS_TYPE_INVALID); + return get_intval(call(msg)); + } + +#endif + + return -1; +} + +int remote::get_cursor_addr(void) +{ +#if defined(WIN32) + + if(hPipe != INVALID_HANDLE_VALUE) + { + struct hllapi_packet_query query = { HLLAPI_PACKET_GET_CURSOR }; + struct hllapi_packet_result response; + DWORD cbSize = sizeof(query); + TransactNamedPipe(hPipe,(LPVOID) &query, cbSize, &response, sizeof(response), &cbSize,NULL); + return response.rc; + } + +#elif defined(HAVE_DBUS) + + return query_intval("getCursorAddress"); + +#else + + return -1; + +#endif +} diff --git a/src/plugins/rx3270/rexx_methods.cc b/src/plugins/rx3270/rexx_methods.cc index 56603b3..bf3ef92 100644 --- a/src/plugins/rx3270/rexx_methods.cc +++ b/src/plugins/rx3270/rexx_methods.cc @@ -145,6 +145,22 @@ RexxMethod3(int, rx3270_method_set_cursor, CSELF, sessionPtr, int, row, int, col return hSession->set_cursor_position(row,col); } +RexxMethod1(int, rx3270_method_get_cursor_addr, CSELF, sessionPtr) +{ + rx3270 *hSession = (rx3270 *) sessionPtr; + if(!hSession) + return -1; + return hSession->get_cursor_addr(); +} + +RexxMethod2(int, rx3270_method_set_cursor_addr, CSELF, sessionPtr, int, addr) +{ + rx3270 *hSession = (rx3270 *) sessionPtr; + if(!hSession) + return -1; + return hSession->set_cursor_addr(addr); +} + RexxMethod1(int, rx3270_method_enter, CSELF, sessionPtr) { rx3270 *hSession = (rx3270 *) sessionPtr; @@ -206,6 +222,21 @@ RexxMethod4(int, rx3270_method_set_text_at, CSELF, sessionPtr, int, row, int, co return -1; } +RexxMethod2(int, rx3270_method_input_text, CSELF, sessionPtr, CSTRING, text) +{ + rx3270 * session = (rx3270 *) sessionPtr; + + if(session) + { + char * str = session->get_3270_string(text); + int rc = session->emulate_input(str); + free(str); + return rc; + } + + return -1; +} + RexxMethod4(int, rx3270_method_cmp_text_at, CSELF, sessionPtr, int, row, int, col, CSTRING, key) { int rc = 0; @@ -363,6 +394,7 @@ RexxMethod3(RexxStringObject, rx3270_method_get_text, CSELF, sessionPtr, OPTIONA return context->String(""); } + RexxMethod2(int, rx3270_method_get_field_len, CSELF, sessionPtr, OPTIONAL_int, baddr) { rx3270 *hSession = (rx3270 *) sessionPtr; @@ -376,7 +408,7 @@ RexxMethod2(int, rx3270_method_get_field_start, CSELF, sessionPtr, OPTIONAL_int, rx3270 *hSession = (rx3270 *) sessionPtr; if(!hSession) return -1; - return hSession->get_field_start(baddr); + return hSession->get_field_start(baddr)+1; } RexxMethod1(RexxStringObject, rx3270_method_get_selection, CSELF, sessionPtr) diff --git a/src/plugins/rx3270/rx3270.cls b/src/plugins/rx3270/rx3270.cls index 6f7a46b..6fdada6 100644 --- a/src/plugins/rx3270/rx3270.cls +++ b/src/plugins/rx3270/rx3270.cls @@ -50,6 +50,8 @@ ::METHOD WAITFORREADY EXTERNAL "LIBRARY rx3270 rx3270_method_wait_for_ready" ::METHOD SETCURSOR EXTERNAL "LIBRARY rx3270 rx3270_method_set_cursor" +::METHOD GETCURSORADDR EXTERNAL "LIBRARY rx3270 rx3270_method_get_cursor_addr" +::METHOD SETCURSORADDR EXTERNAL "LIBRARY rx3270 rx3270_method_set_cursor_addr" ::METHOD ENTER EXTERNAL "LIBRARY rx3270 rx3270_method_enter" ::METHOD PFKEY EXTERNAL "LIBRARY rx3270 rx3270_method_pfkey" @@ -63,7 +65,10 @@ ::METHOD GETTEXTAT EXTERNAL "LIBRARY rx3270 rx3270_method_get_text_at" ::METHOD SETTEXTAT EXTERNAL "LIBRARY rx3270 rx3270_method_set_text_at" ::METHOD CMPTEXTAT EXTERNAL "LIBRARY rx3270 rx3270_method_cmp_text_at" + ::METHOD GET EXTERNAL "LIBRARY rx3270 rx3270_method_get_text" +::METHOD INPUT EXTERNAL "LIBRARY rx3270 rx3270_method_input_text" + ::METHOD WAITFORTEXTAT EXTERNAL "LIBRARY rx3270 rx3270_method_wait_for_text_at" ::METHOD TEST EXTERNAL "LIBRARY rx3270 rx3270_method_test" diff --git a/src/plugins/rx3270/rx3270.h b/src/plugins/rx3270/rx3270.h index 64ad9bd..cf56bc7 100644 --- a/src/plugins/rx3270/rx3270.h +++ b/src/plugins/rx3270/rx3270.h @@ -93,6 +93,8 @@ REXX_METHOD_PROTOTYPE(rx3270_method_is_ready); REXX_METHOD_PROTOTYPE(rx3270_method_wait_for_ready); REXX_METHOD_PROTOTYPE(rx3270_method_set_cursor); + REXX_METHOD_PROTOTYPE(rx3270_method_get_cursor_addr); + REXX_METHOD_PROTOTYPE(rx3270_method_set_cursor_addr); REXX_METHOD_PROTOTYPE(rx3270_method_enter); REXX_METHOD_PROTOTYPE(rx3270_method_pfkey); REXX_METHOD_PROTOTYPE(rx3270_method_pakey); REXX_METHOD_PROTOTYPE(rx3270_method_get_text); @@ -110,7 +112,9 @@ REXX_METHOD_PROTOTYPE(rx3270_method_get_selection); REXX_METHOD_PROTOTYPE(rx3270_method_set_selection); REXX_METHOD_PROTOTYPE(rx3270_method_get_clipboard); - + REXX_METHOD_PROTOTYPE(rx3270_method_get_cursor_addr); + REXX_METHOD_PROTOTYPE(rx3270_method_set_cursor_addr); + REXX_METHOD_PROTOTYPE(rx3270_method_input_text); /*---[ Globals ]---------------------------------------------------------------------------------------------*/ @@ -166,7 +170,11 @@ virtual int wait(int seconds) = 0; virtual int wait_for_ready(int seconds) = 0; virtual int wait_for_text_at(int row, int col, const char *key, int timeout); + virtual int set_cursor_position(int row, int col) = 0; + virtual int set_cursor_addr(int addr) = 0; + virtual int get_cursor_addr(void) = 0; + virtual int set_toggle(LIB3270_TOGGLE ix, bool value) = 0; virtual int enter(void) = 0; @@ -176,6 +184,7 @@ virtual char * get_text_at(int row, int col, size_t sz) = 0; virtual char * get_text(int baddr, size_t len) = 0; virtual int cmp_text_at(int row, int col, const char *text) = 0; virtual int set_text_at(int row, int col, const char *str) = 0; + virtual int emulate_input(const char *str) = 0; virtual int get_field_start(int baddr = -1) = 0; virtual int get_field_len(int baddr = -1) = 0; diff --git a/src/plugins/rx3270/rxapimain.cc b/src/plugins/rx3270/rxapimain.cc index 1a95842..1ebeca2 100644 --- a/src/plugins/rx3270/rxapimain.cc +++ b/src/plugins/rx3270/rxapimain.cc @@ -129,6 +129,8 @@ RexxMethodEntry rx3270_methods[] = REXX_METHOD(rx3270_method_is_ready, rx3270_method_is_ready ), REXX_METHOD(rx3270_method_wait_for_ready, rx3270_method_wait_for_ready ), REXX_METHOD(rx3270_method_set_cursor, rx3270_method_set_cursor ), + REXX_METHOD(rx3270_method_set_cursor, rx3270_method_get_cursor_addr ), + REXX_METHOD(rx3270_method_set_cursor, rx3270_method_set_cursor_addr ), REXX_METHOD(rx3270_method_enter, rx3270_method_enter ), REXX_METHOD(rx3270_method_pfkey, rx3270_method_pfkey ), REXX_METHOD(rx3270_method_pakey, rx3270_method_pakey ), @@ -149,6 +151,10 @@ RexxMethodEntry rx3270_methods[] = REXX_METHOD(rx3270_method_set_selection, rx3270_method_set_selection ), REXX_METHOD(rx3270_method_get_clipboard, rx3270_method_get_clipboard ), + REXX_METHOD(rx3270_method_get_cursor_addr, rx3270_method_get_cursor_addr ), + REXX_METHOD(rx3270_method_set_cursor_addr, rx3270_method_set_cursor_addr ), + REXX_METHOD(rx3270_method_input_text, rx3270_method_input_text ), + REXX_LAST_METHOD() }; diff --git a/src/plugins/rx3270/sample/clipboard.rex b/src/plugins/rx3270/sample/clipboard.rex index 672c5d3..9ae8873 100644 --- a/src/plugins/rx3270/sample/clipboard.rex +++ b/src/plugins/rx3270/sample/clipboard.rex @@ -7,6 +7,12 @@ host = .rx3270~new("") + if host~connected() = 0 then + do + say "Disconnected from host" + return 0 + end + text = host~GetClipboard() if text = "" then do @@ -14,8 +20,52 @@ return 0 end - say "["||text||"]" + if host~WaitForReady(60) <> 0 then + do + say "Timeout waiting for host" + return 0 + end + + while text <> "" + do + host~SetCursorAddr(host~GetFieldStart()) + field_len = host~GetFieldLen() + + if length(text) < field_len then + do + /* Text is smaller than field, just insert it */ + host~input(text) + end + else + do + /* Text is bigger than field, split ... */ + s = strip(left(text,field_len)) + p = lastpos(" ",s) + if p = 0 then + do + s = strip(left(text,field_len)) + text = substr(text,field_len+1) + end + else + do + s = strip(left(text,p)) + text = strip(substr(text,p+1)) + end + + /* ... and justify */ + + /* TODO */ + + /* Insert new string */ + host~input(s) + + end + + say text + + text = "" + end return 0 -- libgit2 0.21.2