diff --git a/src/include/lib3270++.h b/src/include/lib3270++.h index b49f2dd..a2d1b24 100644 --- a/src/include/lib3270++.h +++ b/src/include/lib3270++.h @@ -67,6 +67,8 @@ class Host; class Controller; + #define DEFAULT_TIMEOUT 5 + class TN3270_PUBLIC Event { public: enum Type : uint8_t { @@ -200,7 +202,7 @@ virtual void disconnect() = 0; // Wait for session state. - virtual void waitForReady(time_t timeout = 5) throw() = 0; + virtual void waitForReady(time_t timeout = DEFAULT_TIMEOUT) throw() = 0; // Gets virtual std::string toString(int baddr = 0, size_t len = -1, char lf = '\n') const = 0; @@ -255,6 +257,9 @@ /// @brief Connection with the host Session *session; + /// @brief How much seconds we wait for the terminal to be ready? + time_t timeout; + protected: /// @brief Writes characters to the associated file from the put area @@ -273,19 +278,23 @@ void error(const char *fmt, ...) const; public: - Host(const char *id = nullptr, const char *url = nullptr); + Host(const char *id = nullptr, const char *url = nullptr, time_t timeout = DEFAULT_TIMEOUT); ~Host(); inline bool operator==(ConnectionState state) const noexcept { return session->getConnectionState() == state; } - void connect(const char *url); + void connect(const char *url, bool sync = true); inline ProgramMessage getProgramMessage() const { return session->getProgramMessage(); } + inline bool isReady() const { + return getProgramMessage() == MESSAGE_NONE; + } + inline operator ProgramMessage() const { return getProgramMessage(); } @@ -294,6 +303,10 @@ return session->getConnectionState(); } + inline bool isConnected() const { + return getConnectionState() == CONNECTED_TN3270E; + } + inline operator ConnectionState() const { return getConnectionState(); } @@ -336,22 +349,13 @@ // Get contents. - inline Host & pop(int baddr, std::string &text) { - session->pop(baddr, text); - return *this; - } - - inline Host & pop(int row, int col, std::string &text) { - session->pop(row,col,text); - return *this; - } - - inline Host & pop(std::string &text) { - session->pop(text); - return *this; - } + Host & pop(int baddr, std::string &text); + Host & pop(int row, int col, std::string &text); + Host & pop(std::string &text); std::string toString() const; + std::string toString(int baddr, size_t len = -1, char lf = '\n') const; + std::string toString(int row, int col, size_t sz, char lf = '\n') const; // Event listeners inline Host & insert(Event::Type type, std::function listener) noexcept { diff --git a/src/include/lib3270.h b/src/include/lib3270.h index 79b5a6a..8326ca2 100644 --- a/src/include/lib3270.h +++ b/src/include/lib3270.h @@ -555,6 +555,18 @@ LIB3270_EXPORT int lib3270_emulate_input(H3270 *session, const char *s, int len, int pasting); /** + * @brief Converts row/col in a buffer address. + * + * @param hSession TN3270 Session. + * @param row Row inside the screen. + * @param col Col inside the screen. + * + * @return Current address or -1 if invalid (sets errno). + * + */ + LIB3270_EXPORT int lib3270_translate_to_address(H3270 *hSession, int row, int col); + + /** * Set string at current cursor position. * * Returns are ignored; newlines mean "move to beginning of next line"; @@ -578,7 +590,7 @@ * @param h Session handle. * @param baddr New cursor address. * - * @return last cursor address. + * @return or -1 if invalid (sets errno). * */ LIB3270_EXPORT int lib3270_set_cursor_address(H3270 *h, int baddr); @@ -590,7 +602,7 @@ * @param row New cursor row. * @param col New cursor col. * - * @return last cursor address. + * @return last cursor address or -1 if invalid (sets errno).. * */ LIB3270_EXPORT int lib3270_set_cursor_position(H3270 *h, int row, int col); diff --git a/src/lib3270++/host.cc b/src/lib3270++/host.cc index a6ecfc0..9d6d720 100644 --- a/src/lib3270++/host.cc +++ b/src/lib3270++/host.cc @@ -43,7 +43,8 @@ namespace TN3270 { - Host::Host(const char *id, const char *url) { + Host::Host(const char *id, const char *url, time_t timeout) { + this->timeout = timeout; this->session = Session::create(id); if(url) { this->connect(url); @@ -55,15 +56,17 @@ this->session = nullptr; } - void Host::connect(const char *url) { + void Host::connect(const char *url, bool sync) { this->session->connect(url); - sync(); + if(sync) { + this->sync(); + } } /// @brief Writes characters to the associated file from the put area int Host::sync() { - this->session->waitForReady(); + this->session->waitForReady(this->timeout); return 0; } @@ -89,6 +92,8 @@ std::string Host::toString() const { + this->session->waitForReady(this->timeout); + if(this->session->getConnectionState() == TN3270::DISCONNECTED) { throw std::system_error(ENOTCONN, std::system_category()); } @@ -96,5 +101,70 @@ return this->session->toString(); } + std::string Host::toString(int baddr, size_t len, char lf) const { + + this->session->waitForReady(this->timeout); + + if(this->session->getConnectionState() == TN3270::DISCONNECTED) { + throw std::system_error(ENOTCONN, std::system_category()); + } + + return this->session->toString(baddr,len,lf); + + } + + std::string Host::toString(int row, int col, size_t sz, char lf) const { + + this->session->waitForReady(this->timeout); + + if(this->session->getConnectionState() == TN3270::DISCONNECTED) { + throw std::system_error(ENOTCONN, std::system_category()); + } + + return this->session->toString(row,col,sz,lf); + + + } + + Host & Host::pop(int baddr, std::string &text) { + + this->session->waitForReady(this->timeout); + + if(this->session->getConnectionState() == TN3270::DISCONNECTED) { + throw std::system_error(ENOTCONN, std::system_category()); + } + + session->pop(baddr, text); + + return *this; + } + + Host & Host::pop(int row, int col, std::string &text) { + + this->session->waitForReady(this->timeout); + + if(this->session->getConnectionState() == TN3270::DISCONNECTED) { + throw std::system_error(ENOTCONN, std::system_category()); + } + + session->pop(row,col,text); + + return *this; + } + + Host & Host::pop(std::string &text) { + + this->session->waitForReady(this->timeout); + + if(this->session->getConnectionState() == TN3270::DISCONNECTED) { + throw std::system_error(ENOTCONN, std::system_category()); + } + + session->pop(text); + + return *this; + } + + } diff --git a/src/lib3270++/local/session.cc b/src/lib3270++/local/session.cc index 5318d5f..c2e84dc 100644 --- a/src/lib3270++/local/session.cc +++ b/src/lib3270++/local/session.cc @@ -216,7 +216,19 @@ } TN3270::Session & Local::Session::pop(int baddr, std::string &text) { + std::lock_guard lock(sync); + + char *contents = lib3270_get_field_at(hSession, baddr); + + if(!contents) { + throw std::runtime_error("Can't get field contents"); + } + + text.assign(convertFromHost(contents).c_str()); + + lib3270_free(contents); + return *this; } diff --git a/src/lib3270++/testprogram/testprogram.cc b/src/lib3270++/testprogram/testprogram.cc index 685d97e..8336762 100644 --- a/src/lib3270++/testprogram/testprogram.cc +++ b/src/lib3270++/testprogram/testprogram.cc @@ -47,7 +47,7 @@ TN3270::Host host; - host.connect(getenv("TN3270URL")); + host.connect(getenv("LIB3270_DEFAULT_HOST")); cout << host << endl; host << TN3270::ENTER; diff --git a/src/lib3270/screen.c b/src/lib3270/screen.c index 62ac4c7..48da3ca 100644 --- a/src/lib3270/screen.c +++ b/src/lib3270/screen.c @@ -382,20 +382,80 @@ LIB3270_EXPORT int lib3270_get_cursor_address(H3270 *h) return h->cursor_addr; } -LIB3270_EXPORT int lib3270_set_cursor_address(H3270 *h, int baddr) +/** + * @brief Converts row/col in a buffer address. + * + * @param hSession TN3270 Session. + * @param row Row inside the screen. + * @param col Col inside the screen. + * + * @return Current address or -1 if invalid (sets errno). + * + */ +LIB3270_EXPORT int lib3270_translate_to_address(H3270 *hSession, int row, int col) { - CHECK_SESSION_HANDLE(h); + CHECK_SESSION_HANDLE(hSession); + + row--; + col--; + + if(row < 0 || col < 0 || row > hSession->rows || col > hSession->cols) + { + // Invalid coordinates + errno = EINVAL; + return -1; + } + + return (row * hSession->cols) + col; +} + + +/** + * @brief Move cursor to a new position. + * + * @see lib3270_set_cursor_position + * + * @param hSession TN3270 session. + * @param baddr New cursor position. + * + * @return Old cursor address or -1 in case of error (sets errno). + * + */ +LIB3270_EXPORT int lib3270_set_cursor_address(H3270 *hSession, int baddr) +{ + CHECK_SESSION_HANDLE(hSession); trace("%s(%d)",__FUNCTION__,baddr); - if(h->selected && !lib3270_get_toggle(h,LIB3270_TOGGLE_KEEP_SELECTED)) - lib3270_unselect(h); + if(baddr < 0 || baddr > (hSession->rows * hSession->cols)) + { + errno = EINVAL; + return -1; + } + + if(hSession->selected && !lib3270_get_toggle(hSession,LIB3270_TOGGLE_KEEP_SELECTED)) + lib3270_unselect(hSession); - return cursor_move(h,baddr); + return cursor_move(hSession,baddr); } -LIB3270_EXPORT int lib3270_set_cursor_position(H3270 *h, int row, int col) +/** + * @brief Move cursor to a new position. + * + * @see lib3270_set_cursor_position + * + * @param hSession TN3270 session. + * @param row New cursor row. + * @parma col New cursor column. + * + * @return Old cursor address or -1 in case of error (sets errno). + * + */ +LIB3270_EXPORT int lib3270_set_cursor_position(H3270 *hSession, int row, int col) { + return lib3270_set_cursor_address(hSession,lib3270_translate_to_address(hSession, row, col)); + + /* int baddr = -1; CHECK_SESSION_HANDLE(h); @@ -418,20 +478,37 @@ LIB3270_EXPORT int lib3270_set_cursor_position(H3270 *h, int row, int col) } return baddr; + */ } - -int cursor_move(H3270 *h, int baddr) +/** + * @brief Move cursor to a new position. + * + * @see lib3270_set_cursor_address + * + * @param hSession TN3270 session. + * @param baddr New cursor position. + * + * @return Old cursor position. + * + */ +int cursor_move(H3270 *hSession, int baddr) { - int ret = h->cursor_addr; + int ret = hSession->cursor_addr; if(ret == baddr) return ret; if(baddr >= 0) { - h->cursor_addr = baddr; - h->cbk.update_cursor(h,(unsigned short) (baddr/h->cols),(unsigned short) (baddr%h->cols),h->text[baddr].chr,h->text[baddr].attr); + hSession->cursor_addr = baddr; + hSession->cbk.update_cursor( + hSession, + (unsigned short) (baddr/hSession->cols), + (unsigned short) (baddr%hSession->cols), + hSession->text[baddr].chr, + hSession->text[baddr].attr + ); } return ret; -- libgit2 0.21.2