diff --git a/client/src/core/abstract.cc b/client/src/core/abstract.cc index ab252bd..9e0d712 100644 --- a/client/src/core/abstract.cc +++ b/client/src/core/abstract.cc @@ -101,12 +101,17 @@ } /// @brief Converte charset. - std::string Abstract::Session::convertCharset(iconv_t &converter, const char *str) { + std::string Abstract::Session::convertCharset(iconv_t &converter, const char *str, int length) { std::string rc; #ifdef HAVE_ICONV - size_t in = strlen(str); + size_t in; + + if(length < 0) + in = (size_t) strlen(str); + else + in = (size_t) length; if(in && converter != (iconv_t)(-1)) { @@ -136,13 +141,13 @@ } /// @brief Converte string recebida do host para o charset atual. - std::string Abstract::Session::convertFromHost(const char *str) const { - return convertCharset(const_cast(this)->converter.local,str); + std::string Abstract::Session::convertFromHost(const char *str, int length) const { + return convertCharset(const_cast(this)->converter.local,str,length); } /// @brief Converte string do charset atual para o charset do host. - std::string Abstract::Session::convertToHost(const char *str) const { - return convertCharset(const_cast(this)->converter.host,str); + std::string Abstract::Session::convertToHost(const char *str, int length) const { + return convertCharset(const_cast(this)->converter.host,str,length); } diff --git a/client/src/core/host.cc b/client/src/core/host.cc index aa86e91..bc6f3ec 100644 --- a/client/src/core/host.cc +++ b/client/src/core/host.cc @@ -37,6 +37,13 @@ */ #include + #include + #include + #include + + using std::string; + using std::clog; + using std::endl; /*---[ Implement ]----------------------------------------------------------------------------------*/ @@ -199,6 +206,276 @@ return *this; } + /// @brief Request print + Host & Host::print(LIB3270_CONTENT_OPTION option) { + throw std::system_error(ENOTSUP, std::system_category()); + } + + void Host::input(const char *text, size_t sz) { + +#ifdef DEBUG + { + string str = string(text,sz); + clog << __FUNCTION__ << "(\"" << str << "\")" << endl; + } +#endif // DEBUG + + this->session->input(text, sz); + + } + + + Host & Host::input(const char *text, const char control_char) { + + for(const char * ptr = strchr(text,control_char); ptr; ptr = strchr(text,control_char)) { + + input(text,(size_t) (ptr-text) ); + + switch(*(++ptr)) { + case 'P': // Print + print(); + break; + + case 'E': // Enter + push(ENTER); + break; + + case 'F': // Erase EOF + push(ERASE_EOF); + break; + + case '1': // PF1 + push(PF_1); + break; + + case '2': // PF2 + push(PF_2); + break; + + case '3': // PF3 + push(PF_3); + break; + + case '4': // PF4 + push(PF_4); + break; + + case '5': // PF5 + push(PF_5); + break; + + case '6': // PF6 + push(PF_6); + break; + + case '7': // PF7 + push(PF_7); + break; + + case '8': // PF8 + push(PF_8); + break; + + case '9': // PF9 + push(PF_9); + break; + + case 'a': // PF10 + push(PF_10); + break; + + case 'b': // PF11 + push(PF_11); + break; + + case 'c': // PF12 + push(PF_12); + break; + + case 'd': // PF13 + push(PF_13); + break; + + case 'e': // PF14 + push(PF_14); + break; + + case 'f': // PF15 + push(PF_15); + break; + + case 'g': // PF16 + push(PF_16); + break; + + case 'h': // PF17 + push(PF_17); + break; + + case 'i': // PF18 + push(PF_18); + break; + + case 'j': // PF19 + push(PF_19); + break; + + case 'k': // PF20 + push(PF_20); + break; + + case 'l': // PF21 + push(PF_21); + break; + + case 'm': // PF22 + push(PF_22); + break; + + case 'n': // PF23 + push(PF_23); + break; + + case 'o': // PF24 + push(PF_24); + break; + + case '@': // Send '@' character + input("@",(size_t) 1); + break; + + case 'x': // PA1 + push(PA_1); + break; + + case 'y': // PA2 + push(PA_2); + break; + + case 'z': // PA3 + push(PA_3); + break; + + case 'B': // PC_LEFTTAB = "@B" + break; + + case 'T': // PC_RIGHTTAB = "@T" + break; + + case 'N': // PC_NEWLINE = "@N" + push(NEWLINE); + break; + + case 'C': // PC_CLEAR = "@C" + push(CLEAR); + break; + + case 'D': // PC_DELETE = "@D" + push(CHAR_DELETE); + break; + + case 'H': // PC_HELP = "@H" + break; + + case 'I': // PC_INSERT = "@I" + break; + + case 'L': // PC_CURSORLEFT = "@L" + break; + + case 'R': // PC_RESET = "@R" + push(KYBD_RESET); + break; + + case 'U': // PC_CURSORUP = "@U" + break; + + case 'V': // PC_CURSORDOWN = "@V" + break; + + case 'Z': // PC_CURSORRIGHT = "@Z" + break; + + case '0': // PC_HOME = "@0" + break; + + case 'p': // PC_PLUSKEY = "@p" + break; + + case 'q': // PC_END = "@q" + break; + + case 's': // PC_SCRLK = "@s" + break; + + case 't': // PC_NUMLOCK = "@t" + break; + + case 'u': // PC_PAGEUP = "@u" + break; + + case 'v': // PC_PAGEDOWN = "@v" + break; + + case '/': // PC_OVERRUNOFQUEUE = "@/" ' Queue overflow, used in Get Key only + break; + + case '$': // PC_ALTCURSOR = "@$" ' Presentation Manager only, unused in VB environment + break; + + case '<': // PC_BACKSPACE = "@<" + push(BACKSPACE); + break; + + + // Global Const PC_TEST = "@A@C" + // Global Const PC_WORDDELETE = "@A@D" + // Global Const PC_FIELDEXIT = "@A@E" + // Global Const PC_ERASEINPUT = "@A@F" + // Global Const PC_SYSTEMREQUEST = "@A@H" + // Global Const PC_INSERTTOGGLE = "@A@I" + // Global Const PC_CURSORSELECT = "@A@J" + // Global Const PC_CURSLEFTFAST = "@A@L" + // Global Const PC_GETCURSOR = "@A@N" + // Global Const PC_LOCATECURSOR = "@A@O" + // Global Const PC_ATTENTION = "@A@Q" + // Global Const PC_DEVICECANCEL = "@A@R" + // Global Const PC_PRINTPS = "@A@T" + // Global Const PC_CURSUPFAST = "@A@U" + // Global Const PC_CURSDOWNFAST = "@A@V" + // Global Const PC_HEX = "@A@X" + // Global Const PC_FUNCTIONKEY = "@A@Y" + // Global Const PC_CURSRIGHTFAST = "@A@Z" + + // Global Const PC_REVERSEVIDEO = "@A@9" + // Global Const PC_UNDERSCORE = "@A@b" + // Global Const PC_BLINK = "@A@c" + // Global Const PC_RED = "@A@d"BACKSPACE + // Global Const PC_PINK = "@A@e" + // Global Const PC_GREEN = "@A@f" + // Global Const PC_YELLOW = "@A@g" + // Global Const PC_BLUE = "@A@h" + // Global Const PC_TURQOISE = "@A@i" + // Global Const PC_WHITE = "@A@j" + // Global Const PC_RSTHOSTCOLORS = "@A@l" + // Global Const PC_PRINTPC = "@A@t" + + // Global Const PC_FIELDMINUS = "@A@-" + // Global Const PC_FIELDPLUS = "@A@+" + } + + text = (ptr+1); + } + + if(*text) { + input(text,strlen(text)); + } + + return *this; + + } + + } diff --git a/client/src/include/ipc-client-internals.h b/client/src/include/ipc-client-internals.h index f9e3917..fbc6444 100644 --- a/client/src/include/ipc-client-internals.h +++ b/client/src/include/ipc-client-internals.h @@ -121,7 +121,7 @@ #endif /// @brief Converte charset. - static std::string convertCharset(iconv_t &converter, const char *str); + static std::string convertCharset(iconv_t &converter, const char *str, int length); protected: @@ -135,10 +135,10 @@ void setCharSet(const char *remote, const char *local = SYSTEM_CHARSET); /// @brief Converte string recebida do host para o charset atual. - std::string convertFromHost(const char *str) const; + std::string convertFromHost(const char *str, int length = -1) const; /// @brief Converte string do charset atual para o charset do host. - std::string convertToHost(const char *str) const; + std::string convertToHost(const char *str, int length = -1) const; }; @@ -199,6 +199,8 @@ TN3270::Session & pfkey(unsigned short value); TN3270::Session & pakey(unsigned short value); + TN3270::Session & input(const char *text, size_t length) override; + /// @brief Set field at current posicion, jumps to next writable field. TN3270::Session & push(const char *text) override; @@ -367,6 +369,8 @@ TN3270::Session & pfkey(unsigned short value); TN3270::Session & pakey(unsigned short value); + TN3270::Session & input(const char *text, size_t length) override; + /// @brief Set field at current posicion, jumps to next writable field. TN3270::Session & push(const char *text) override; diff --git a/client/src/session/local/session.cc b/client/src/session/local/session.cc index 5b7e3b9..fc143bb 100644 --- a/client/src/session/local/session.cc +++ b/client/src/session/local/session.cc @@ -228,16 +228,51 @@ /// @brief Set field at current position, jumps to next writable field. TN3270::Session & Local::Session::push(const char *text) { std::lock_guard lock(sync); + + string converted = convertToHost(text); + + int rc = lib3270_input_string(this->hSession, (unsigned char *) converted.c_str(), converted.size()); + if(rc) { + throw std::system_error(errno, std::system_category()); + } + + return *this; + } + + TN3270::Session & Local::Session::input(const char *text, size_t length) { + std::lock_guard lock(sync); + + string converted = convertToHost(text,length); + + int rc = lib3270_input_string(this->hSession, (unsigned char *) converted.c_str(), converted.size()); + if(rc) { + throw std::system_error(errno, std::system_category()); + } + return *this; } TN3270::Session & Local::Session::push(int baddr, const std::string &text) { std::lock_guard lock(sync); + + string converted = convertToHost(text.c_str(),text.size()); + + if(lib3270_set_string_at_address(this->hSession,baddr,(unsigned char *) converted.c_str(),converted.length()) < 0) { + throw std::system_error(errno, std::system_category()); + } + return *this; } TN3270::Session & Local::Session::push(int row, int col, const std::string &text) { std::lock_guard lock(sync); + + string converted = convertToHost(text.c_str(),text.size()); + + if(lib3270_set_string_at(this->hSession,row,col,(unsigned char *) converted.c_str())) { + throw std::system_error(errno, std::system_category()); + } + return *this; } diff --git a/client/src/session/remote/session.cc b/client/src/session/remote/session.cc index 344eeb6..d58a48d 100644 --- a/client/src/session/remote/session.cc +++ b/client/src/session/remote/session.cc @@ -125,6 +125,11 @@ } + TN3270::Session & IPC::Session::input(const char *text, size_t length) { + + return *this; + } + /// @brief Set field at current position, jumps to next writable field. TN3270::Session & IPC::Session::push(const char *text) { diff --git a/client/src/testprogram/testprogram.cc b/client/src/testprogram/testprogram.cc index 42119f1..2ecf36a 100644 --- a/client/src/testprogram/testprogram.cc +++ b/client/src/testprogram/testprogram.cc @@ -39,7 +39,6 @@ #include #include #include - #include using namespace std; @@ -87,11 +86,16 @@ << "\tProgram message is " << host.getProgramMessage() << std::endl; - // host.connect(getenv("LIB3270_DEFAULT_HOST")); + + // host.input("test@0another line"); + + /* + host.connect(); if(host) { cout << host << endl; } + */ } catch(const std::exception &e) { diff --git a/common/src/include/lib3270/ipc.h b/common/src/include/lib3270/ipc.h index e08fd10..85808c6 100644 --- a/common/src/include/lib3270/ipc.h +++ b/common/src/include/lib3270/ipc.h @@ -154,7 +154,19 @@ PF_9, PF_10, PF_11, - PF_12 + PF_12, + PF_13, + PF_14, + PF_15, + PF_16, + PF_17, + PF_18, + PF_19, + PF_20, + PF_21, + PF_22, + PF_23, + PF_24 }; /// @brief PF Keys @@ -264,6 +276,9 @@ return push(text.c_str()); } + /// @brief Input string. + virtual Session & input(const char *text, size_t length) = 0; + /// @brief Set cursor address. virtual TN3270::Session & setCursorPosition(unsigned short addr) = 0; @@ -276,7 +291,7 @@ /// @brief Send PF. virtual Session & pfkey(unsigned short value) = 0; - /// @brief Send PF. + /// @brief Send PA. virtual Session & pakey(unsigned short value) = 0; virtual Session & push(int baddr, const std::string &text) = 0; @@ -327,6 +342,8 @@ /// @brief Write error to log file. void error(const char *fmt, ...) const; + void input(const char *text, size_t sz); + public: Host(const char *id = nullptr, const char *url = nullptr, time_t timeout = DEFAULT_TIMEOUT); ~Host(); @@ -404,8 +421,20 @@ /// @brief Send PA. Host & pakey(unsigned short value); + /// @brief Request print + Host & print(LIB3270_CONTENT_OPTION option = LIB3270_CONTENT_ALL); + // Set contents. + /// @brief Input string. + /// + /// Input the supplied string processing commands delimited by the control char in + /// the same way of the old HLLAPI. + /// + /// @param text String with the text to input. + /// @param control_char Control character used to identify commands. + Host & input(const char *text, const char control_char = '@'); + /// @brief Set field at current posicion, jumps to next writable field. inline Host & push(const char *text) { session->push(text); diff --git a/server/src/core/methods.c b/server/src/core/methods.c index c00aec3..2513173 100644 --- a/server/src/core/methods.c +++ b/server/src/core/methods.c @@ -62,7 +62,7 @@ GVariant * ipc3270_method_call(GObject *object, const gchar *method_name, GVaria g_variant_get(parameters, "(&s)", &text); g_autofree gchar * converted = ipc3270_convert_output_string(object, text, error); - if(lib3270_input_string(hSession,(const unsigned char *) converted) < 0) + if(lib3270_input_string(hSession,(const unsigned char *) converted, -1)) { // Failed! debug("%s failed: %s",method_name,strerror(errno)); -- libgit2 0.21.2