diff --git a/lib3270.cbp b/lib3270.cbp
index f89975e..c3bacc7 100644
--- a/lib3270.cbp
+++ b/lib3270.cbp
@@ -217,7 +217,10 @@
-
+
+
+
+
diff --git a/src/lib3270/Makefile.in b/src/lib3270/Makefile.in
index 44f3c9a..0086f1c 100644
--- a/src/lib3270/Makefile.in
+++ b/src/lib3270/Makefile.in
@@ -30,6 +30,7 @@ LIBNAME=lib@LIB3270_NAME@
SOURCES= \
$(wildcard *.c) \
+ $(wildcard selection/*.c) \
$(wildcard @OSNAME@/*.c) \
$(wildcard ssl/*.c) \
$(wildcard ssl/@OSNAME@/*.c) \
diff --git a/src/lib3270/private.h b/src/lib3270/private.h
index 9265b24..064b988 100644
--- a/src/lib3270/private.h
+++ b/src/lib3270/private.h
@@ -648,6 +648,16 @@ struct _h3270
};
+#define SELECTION_LEFT 0x01
+#define SELECTION_TOP 0x02
+#define SELECTION_RIGHT 0x04
+#define SELECTION_BOTTOM 0x08
+
+#define SELECTION_SINGLE_COL 0x10
+#define SELECTION_SINGLE_ROW 0x20
+
+#define SELECTION_ACTIVE 0x80
+
/* Library internal calls */
LIB3270_INTERNAL void key_ACharacter(H3270 *hSession, unsigned char c, enum keytype keytype, enum iaction cause,Boolean *skipped);
LIB3270_INTERNAL int cursor_move(H3270 *session, int baddr);
@@ -660,6 +670,9 @@ LIB3270_INTERNAL void lib3270_sock_disconnect(H3270 *hSession);
LIB3270_INTERNAL int lib3270_default_event_dispatcher(H3270 *hSession, int block);
+LIB3270_INTERNAL void do_select(H3270 *h, int start, int end, int rect);
+
+
/**
* @brief Called from timer to attempt an automatic reconnection.
*/
diff --git a/src/lib3270/selection.c b/src/lib3270/selection.c
deleted file mode 100644
index 72fb83e..0000000
--- a/src/lib3270/selection.c
+++ /dev/null
@@ -1,912 +0,0 @@
-/*
- * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
- * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
- * aplicativos mainframe. Registro no INPI sob o nome G3270.
- *
- * Copyright (C) <2008>
- *
- * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
- * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
- * Free Software Foundation.
- *
- * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
- * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
- * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
- * obter mais detalhes.
- *
- * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
- * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
- * St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Este programa está nomeado como selection.c e possui - linhas de código.
- *
- * Contatos:
- *
- * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
- * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
- *
- */
-
- #include "private.h"
- #include
- #include
- #include
- #include
- #include "3270ds.h"
-
- #define SELECTION_LEFT 0x01
- #define SELECTION_TOP 0x02
- #define SELECTION_RIGHT 0x04
- #define SELECTION_BOTTOM 0x08
-
- #define SELECTION_SINGLE_COL 0x10
- #define SELECTION_SINGLE_ROW 0x20
-
- #define SELECTION_ACTIVE 0x80
-
- static void do_select(H3270 *h, int start, int end, int rect);
-
- /*--[ Implement ]------------------------------------------------------------------------------------*/
-
-static void get_selected_addr(H3270 *session, int *start, int *end)
-{
- if(session->select.start > session->select.end)
- {
- *end = session->select.start;
- *start = session->select.end;
- }
- else
- {
- *start = session->select.start;
- *end = session->select.end;
- }
-}
-
-static void update_selected_rectangle(H3270 *session)
-{
- struct
- {
- int row;
- int col;
- } p[2];
-
-
- int begin, end, row, col, baddr;
-
- get_selected_addr(session,&begin,&end);
-
- // Get start & end posision
- p[0].row = (begin/session->cols);
- p[0].col = (begin%session->cols);
- p[1].row = (end/session->cols);
- p[1].col = (end%session->cols);
-
- if(p[0].row > p[1].row)
- {
- int swp = p[0].row;
- p[0].row = p[1].row;
- p[1].row = swp;
- }
-
- if(p[0].col > p[1].col)
- {
- int swp = p[0].col;
- p[0].col = p[1].col;
- p[1].col = swp;
- }
-
- // First remove unselected areas
- baddr = 0;
- for(row=0;row < session->rows;row++)
- {
- for(col = 0; col < session->cols;col++)
- {
- if(!(row >= p[0].row && row <= p[1].row && col >= p[0].col && col <= p[1].col) && (session->text[baddr].attr & LIB3270_ATTR_SELECTED))
- {
- session->text[baddr].attr &= ~LIB3270_ATTR_SELECTED;
- session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
- }
- baddr++;
- }
- }
-
- // Then, draw selected ones
- baddr = 0;
- for(row=0;row < session->rows;row++)
- {
- for(col = 0; col < session->cols;col++)
- {
- if((row >= p[0].row && row <= p[1].row && col >= p[0].col && col <= p[1].col) && !(session->text[baddr].attr & LIB3270_ATTR_SELECTED))
- {
- session->text[baddr].attr |= LIB3270_ATTR_SELECTED;
- session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
- }
- baddr++;
- }
- }
-
-}
-
-static void update_selected_region(H3270 *session)
-{
- int baddr,begin,end;
- int len = session->rows*session->cols;
-
- get_selected_addr(session,&begin,&end);
-
- // First remove unselected areas
- for(baddr = 0; baddr < begin; baddr++)
- {
- if(session->text[baddr].attr & LIB3270_ATTR_SELECTED)
- {
- session->text[baddr].attr &= ~LIB3270_ATTR_SELECTED;
- session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
- }
- }
-
- for(baddr = end+1; baddr < len; baddr++)
- {
- if(session->text[baddr].attr & LIB3270_ATTR_SELECTED)
- {
- session->text[baddr].attr &= ~LIB3270_ATTR_SELECTED;
- session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
- }
- }
-
- // Then draw the selected ones
- for(baddr = begin; baddr <= end; baddr++)
- {
- if(!(session->text[baddr].attr & LIB3270_ATTR_SELECTED))
- {
- session->text[baddr].attr |= LIB3270_ATTR_SELECTED;
- session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
- }
- }
-
-}
-
-void toggle_rectselect(H3270 *session, struct lib3270_toggle GNUC_UNUSED(*t), LIB3270_TOGGLE_TYPE GNUC_UNUSED(tt))
-{
- if(!session->selected)
- return;
-
- if(t->value)
- update_selected_rectangle(session);
- else
- update_selected_region(session);
-}
-
-LIB3270_EXPORT int lib3270_unselect(H3270 *hSession)
-{
- int a;
-
- CHECK_SESSION_HANDLE(hSession);
-
- trace("%s",__FUNCTION__);
-
- if(hSession->selected)
- {
- hSession->selected = 0;
-
- for(a = 0; a < hSession->rows*hSession->cols; a++)
- {
- if(hSession->text[a].attr & LIB3270_ATTR_SELECTED)
- {
- hSession->text[a].attr &= ~LIB3270_ATTR_SELECTED;
- if(hSession->cbk.update)
- hSession->cbk.update(hSession,a,hSession->text[a].chr,hSession->text[a].attr,a == hSession->cursor_addr);
- }
- }
-
- hSession->cbk.set_selection(hSession,0);
- hSession->cbk.update_selection(hSession,-1,-1);
- }
-
- return 0;
-}
-
-LIB3270_EXPORT void lib3270_select_to(H3270 *session, int baddr)
-{
- int start, end;
-
- CHECK_SESSION_HANDLE(session);
-
- if(!lib3270_connected(session))
- return;
-
- start = session->selected ? session->select.start : session->cursor_addr;
-
- cursor_move(session,end = baddr);
-
- do_select(session,start,end,lib3270_get_toggle(session,LIB3270_TOGGLE_RECTANGLE_SELECT));
-
-}
-
-LIB3270_EXPORT int lib3270_select_region(H3270 *h, int start, int end)
-{
- int maxlen;
-
- CHECK_SESSION_HANDLE(h);
-
- if(!lib3270_connected(h))
- return ENOTCONN;
-
- maxlen = (h->rows * h->cols);
-
- // Check bounds
- if(start < 0 || start > maxlen || end < 0 || end > maxlen || start > end)
- return EINVAL;
-
- do_select(h,start,end,lib3270_get_toggle(h,LIB3270_TOGGLE_RECTANGLE_SELECT));
- cursor_move(h,h->select.end);
-
- return 0;
-}
-
-static void do_select(H3270 *h, int start, int end, int rect)
-{
- if(start < 0 || end > (h->rows * h->cols))
- return;
-
- // Do we really need to change selection?
- if(start == h->select.start && end == h->select.end && h->selected)
- return;
-
- // Start address is inside the screen?
- h->select.start = start;
- h->select.end = end;
-
- if(rect)
- {
- h->rectsel = 1;
- update_selected_rectangle(h);
- }
- else
- {
- h->rectsel = 0;
- update_selected_region(h);
- }
-
- if(!h->selected)
- {
- h->selected = 1;
- h->cbk.set_selection(h,1);
- }
-
- h->cbk.update_selection(h,start,end);
-
-}
-
-LIB3270_EXPORT unsigned char lib3270_get_selection_flags(H3270 *hSession, int baddr)
-{
- int row,col;
- unsigned char rc = 0;
-
- CHECK_SESSION_HANDLE(hSession);
-
- if(!(lib3270_connected(hSession) && (hSession->text[baddr].attr & LIB3270_ATTR_SELECTED)))
- return rc;
-
- row = baddr / hSession->cols;
- col = baddr % hSession->cols;
- rc |= SELECTION_ACTIVE;
-
- if( (hSession->select.start % hSession->cols) == (hSession->select.end % hSession->cols) )
- {
- rc |= SELECTION_SINGLE_COL;
- }
- else
- {
- if( (col == 0) || !(hSession->text[baddr-1].attr & LIB3270_ATTR_SELECTED) )
- rc |= SELECTION_LEFT;
-
- if( (col == hSession->cols) || !(hSession->text[baddr+1].attr & LIB3270_ATTR_SELECTED) )
- rc |= SELECTION_RIGHT;
- }
-
- if( (hSession->select.start / hSession->cols) == (hSession->select.end / hSession->cols) )
- {
- rc |= SELECTION_SINGLE_ROW;
- }
- else
- {
- if( (row == 0) || !(hSession->text[baddr-hSession->cols].attr & LIB3270_ATTR_SELECTED) )
- rc |= SELECTION_TOP;
-
- if( (row == hSession->rows) || !(hSession->text[baddr+hSession->cols].attr & LIB3270_ATTR_SELECTED) )
- rc |= SELECTION_BOTTOM;
- }
-
- return rc;
-}
-
-LIB3270_EXPORT int lib3270_select_word_at(H3270 *session, int baddr)
-{
- int start, end;
-
- if(lib3270_get_word_bounds(session,baddr,&start,&end))
- return -1;
-
- trace("%s: baddr=%d start=%d end=%d",__FUNCTION__,baddr,start,end);
-
- do_select(session,start,end,0);
-
- return 0;
-}
-
-LIB3270_EXPORT int lib3270_select_field_at(H3270 *session, int baddr)
-{
- int start, end;
-
- if(lib3270_get_field_bounds(session,baddr,&start,&end))
- return -1;
-
- do_select(session,start,end,0);
-
- return 0;
-}
-
-LIB3270_EXPORT int lib3270_select_field(H3270 *hSession)
-{
- CHECK_SESSION_HANDLE(hSession);
- lib3270_select_field_at(hSession,hSession->cursor_addr);
- return 0;
-}
-
-LIB3270_EXPORT int lib3270_select_all(H3270 * hSession)
-{
- FAIL_IF_NOT_ONLINE(hSession);
-
- do_select(hSession,0,(hSession->rows*hSession->cols)-1,0);
-
- return 0;
-}
-
-LIB3270_EXPORT int lib3270_reselect(H3270 *hSession)
-{
- FAIL_IF_NOT_ONLINE(hSession);
-
- if(hSession->select.start == hSession->select.end || hSession->selected)
- return 0;
-
- do_select(hSession, hSession->select.start,hSession->select.end,lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECTANGLE_SELECT));
-
- return 0;
-}
-
-static char * get_text(H3270 *hSession,unsigned char all, unsigned char tok)
-{
- int row, col, baddr;
- char * ret;
- size_t buflen = (hSession->rows * (hSession->cols+1))+1;
- size_t sz = 0;
- unsigned short attr = 0xFFFF;
-
- if(!(lib3270_connected(hSession) && hSession->text))
- {
- errno = ENOTCONN;
- return NULL;
- }
-
- ret = lib3270_malloc(buflen);
-
- baddr = 0;
-
- for(row=0;row < hSession->rows;row++)
- {
- int cr = 0;
-
- for(col = 0; col < hSession->cols;col++)
- {
- if(all || hSession->text[baddr].attr & LIB3270_ATTR_SELECTED)
- {
- if(tok && attr != hSession->text[baddr].attr)
- {
- attr = hSession->text[baddr].attr;
- ret[sz++] = tok;
- ret[sz++] = (attr & 0x0F);
- ret[sz++] = ((attr & 0xF0) >> 4);
- }
-
- cr++;
- ret[sz++] = hSession->text[baddr].chr;
- }
- baddr++;
- }
-
- if(cr)
- ret[sz++] = '\n';
-
- if((sz+10) > buflen)
- {
- buflen += 100;
- ret = lib3270_realloc(ret,buflen);
- }
- }
-
- if(!sz)
- {
- lib3270_free(ret);
- errno = ENOENT;
- return NULL;
- }
- else if(sz > 1 && ret[sz-1] == '\n') // Remove ending \n
- {
- ret[sz-1] = 0;
- }
-
- ret[sz++] = 0;
-
- if(sz != buflen)
- ret = lib3270_realloc(ret,sz);
-
- return ret;
-}
-
-LIB3270_EXPORT char * lib3270_get_region(H3270 *h, int start_pos, int end_pos, unsigned char all)
-{
- char * text;
- int maxlen;
- int sz = 0;
- int baddr;
-
- CHECK_SESSION_HANDLE(h);
-
- if(!lib3270_connected(h))
- return NULL;
-
- maxlen = h->rows * (h->cols+1);
-
- if(start_pos < 0 || start_pos > maxlen || end_pos < 0 || end_pos > maxlen || end_pos < start_pos)
- return NULL;
-
- text = lib3270_malloc(maxlen);
-
- for(baddr=start_pos;baddrtext[baddr].attr & LIB3270_ATTR_SELECTED)
- text[sz++] = (h->text[baddr].attr & LIB3270_ATTR_CG) ? ' ' : h->text[baddr].chr;
-
- if((baddr%h->cols) == 0 && sz > 0)
- text[sz++] = '\n';
- }
- text[sz++] = 0;
-
- return lib3270_realloc(text,sz);
-}
-
-LIB3270_EXPORT char * lib3270_get_string_at_address(H3270 *h, int offset, int len, char lf)
-{
- char * buffer;
- int maxlen;
- char * ptr;
-
- CHECK_SESSION_HANDLE(h);
-
- if(!lib3270_connected(h))
- {
- errno = ENOTCONN;
- return NULL;
- }
-
- maxlen = (h->rows * (h->cols+1)) - offset;
- if(maxlen <= 0 || offset < 0)
- {
- errno = EINVAL;
- return NULL;
- }
-
- if(len < 0 || len > maxlen)
- len = maxlen;
-
- buffer = lib3270_malloc(len+1);
- ptr = buffer;
-
-// trace("len=%d buffer=%p",len,buffer);
-
- while(len > 0)
- {
- if(h->text[offset].attr & LIB3270_ATTR_CG)
- *ptr = ' ';
- else if(h->text[offset].chr)
- *ptr = h->text[offset].chr;
- else
- *ptr = ' ';
-
- ptr++;
- offset++;
- len--;
-
- if(lf && (offset%h->cols) == 0 && len > 0)
- {
- *(ptr++) = lf;
- len--;
- }
- }
-// trace("len=%d buffer=%p pos=%d",len,buffer,ptr-buffer);
-
- *ptr = 0;
-
- return buffer;
-}
-
-LIB3270_EXPORT char * lib3270_get_string_at(H3270 *h, int row, int col, int len, char lf)
-{
- CHECK_SESSION_HANDLE(h);
- return lib3270_get_string_at_address(h, ((row-1) * h->cols) + (col-1), len, lf);
-}
-
-LIB3270_EXPORT int lib3270_cmp_text_at(H3270 *h, int row, int col, const char *text, char lf)
-{
- int rc;
- size_t sz = strlen(text);
- char * contents;
-
- contents = lib3270_get_string_at(h,row,col,sz,lf);
- if(!contents)
- return -1;
-
- rc = strncmp(contents,text,sz);
-
- lib3270_free(contents);
-
- return rc;
-}
-
-
-/**
- * Get field contents
- *
- * @param session Session handle
- * @param baddr Field addr
- *
- * @return String with the field contents (release it with lib3270_free()
- */
-LIB3270_EXPORT char * lib3270_get_field_text_at(H3270 *session, int baddr)
-{
- int first = lib3270_field_addr(session,baddr);
-
- if(first < 0)
- return NULL;
-
- return lib3270_get_string_at_address(session,first,lib3270_field_length(session,first)+1,0);
-}
-
-LIB3270_EXPORT int lib3270_has_selection(H3270 *hSession)
-{
- CHECK_SESSION_HANDLE(hSession);
- return hSession->selected != 0;
-}
-
-LIB3270_EXPORT char * lib3270_get_selected(H3270 *hSession)
-{
- CHECK_SESSION_HANDLE(hSession);
-
- if(!hSession->selected || hSession->select.start == hSession->select.end)
- return NULL;
-
- if(!lib3270_connected(hSession))
- return NULL;
-
-
- return get_text(hSession,0,0);
-}
-
-static void copy_chr(H3270 *hSession, int from, int to)
-{
- if(hSession->text[from].chr == hSession->text[to].chr)
- return;
-
- hSession->text[to].chr = hSession->text[from].chr;
-
- memcpy(&hSession->ea_buf[to], &hSession->ea_buf[from],sizeof(struct lib3270_ea));
- hSession->ea_buf[from].fa = 0;
-
- hSession->cbk.update( hSession,
- to,
- hSession->text[to].chr,
- hSession->text[to].attr,
- to == hSession->cursor_addr );
-}
-
-static void clear_chr(H3270 *hSession, int baddr)
-{
- hSession->text[baddr].chr = ' ';
-
- hSession->ea_buf[baddr].cc = EBC_null;
- hSession->ea_buf[baddr].cs = 0;
-
- hSession->cbk.update( hSession,
- baddr,
- hSession->text[baddr].chr,
- hSession->text[baddr].attr,
- baddr == hSession->cursor_addr );
-}
-
-int cut_addr(H3270 *hSession, int daddr, int saddr, int maxlen, int *sattr)
-{
- if(hSession->ea_buf[saddr].fa)
- *sattr = hSession->ea_buf[saddr++].fa;
-
- if(FA_IS_PROTECTED(*sattr) || saddr >= maxlen)
- clear_chr(hSession,daddr);
- else
- copy_chr(hSession,saddr++,daddr);
-
- return saddr;
-}
-
-char * cut_text(H3270 *hSession, char tok)
-{
- unsigned short attr = 0xFFFF;
-
- CHECK_SESSION_HANDLE(hSession);
-
- if(!hSession->selected || hSession->select.start == hSession->select.end)
- return NULL;
-
- if(!(lib3270_connected(hSession) && hSession->text))
- return NULL;
-
- trace("Rectangle select is %s",lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECTANGLE_SELECT) ? "Active" : "Inactive");
-
- if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECTANGLE_SELECT))
- {
- // Rectangle cut is not implemented
- lib3270_popup_dialog(hSession, LIB3270_NOTIFY_INFO, _( "Not available" ), _( "Invalid cut action" ), "%s", _( "Can't cut rectangular regions") );
- }
- else
- {
- int end;
- size_t szText;
- size_t buflen;
- size_t bufpos = 0;
- int daddr; /* Destination addr */
- int dattr; /* Destination addr attribute */
- int saddr; /* Source addr (First field after the selected area) */
- int sattr; /* Source addr attribute */
- char *text;
- size_t maxlen = hSession->rows * hSession->cols;
- size_t f;
-
- get_selected_addr(hSession,&daddr,&end);
-
- lib3270_set_cursor_address(hSession,daddr);
-
- if(daddr >= end)
- return NULL;
-
- dattr = lib3270_field_attribute(hSession,daddr); /* Get first attribute */
-
- szText = (end-daddr)+1;
- buflen = szText;
- bufpos = 0;
-
- text = lib3270_malloc(buflen+1);
-
- saddr = daddr+szText;
- sattr = lib3270_field_attribute(hSession,saddr);
-
- for(f=0;fea_buf[daddr].fa)
- dattr = hSession->ea_buf[daddr].fa;
-
- if((bufpos+10) > buflen)
- {
- buflen += 100;
- text = lib3270_realloc(text,buflen);
- }
-
- if(tok && attr != hSession->text[daddr].attr)
- {
- attr = hSession->text[daddr].attr;
- text[bufpos++] = tok;
- text[bufpos++] = (attr & 0x0F);
- text[bufpos++] = ((attr & 0xF0) >> 4);
- }
-
- text[bufpos++] = hSession->text[daddr].chr;
-
- if(!FA_IS_PROTECTED(dattr))
- saddr = cut_addr(hSession,daddr,saddr,maxlen,&sattr);
-
- daddr++;
- }
-
- text[bufpos++] = 0;
- text = lib3270_realloc(text,bufpos);
-
- // Move contents of the current field
- while(daddr < (int) (maxlen-1) && !hSession->ea_buf[daddr].fa)
- {
- saddr = cut_addr(hSession,daddr,saddr,maxlen,&sattr);
- daddr++;
- }
-
- if(!hSession->ea_buf[daddr].fa)
- clear_chr(hSession,daddr);
-
- hSession->cbk.changed(hSession,0,maxlen);
-
- lib3270_unselect(hSession);
- return text;
- }
-
- return NULL;
-}
-
-LIB3270_EXPORT char * lib3270_cut_selected(H3270 *hSession)
-{
- return cut_text(hSession,0);
-}
-
-LIB3270_EXPORT int lib3270_get_selection_bounds(H3270 *hSession, int *start, int *end)
-{
- int first, last;
-
- CHECK_SESSION_HANDLE(hSession);
-
- if(!hSession->selected || hSession->select.start == hSession->select.end)
- return 0;
-
- if(hSession->select.end > hSession->select.start)
- {
- first = hSession->select.start;
- last = hSession->select.end;
- }
- else
- {
- first = hSession->select.end;
- last = hSession->select.start;
- }
-
- if(start)
- *start = first;
-
- if(end)
- *end = last;
-
- return 1;
-}
-
-LIB3270_EXPORT int lib3270_move_selected_area(H3270 *hSession, int from, int to)
-{
- int pos[2];
- int rows, cols, f, step;
-
- if(from == to)
- return from;
-
- if(!lib3270_get_selection_bounds(hSession,&pos[0],&pos[1]))
- return from;
-
- rows = (to / hSession->cols) - (from / hSession->cols);
- cols = (to % hSession->cols) - (from % hSession->cols);
-
- for(f=0;f<2;f++)
- {
- int row = (pos[f] / hSession->cols) + rows;
- int col = (pos[f] % hSession->cols) + cols;
-
- if(row < 0)
- rows = - (pos[f] / hSession->cols);
-
- if(col < 0)
- cols = - (pos[f] % hSession->cols);
-
- if(row >= (hSession->rows))
- rows = hSession->rows - ((pos[f] / hSession->cols)+1);
-
- if(col >= hSession->cols)
- cols = hSession->cols - ((pos[f] % hSession->cols)+1);
- }
-
- step = (rows * hSession->cols) + cols;
-
- do_select(hSession,hSession->select.start + step,hSession->select.end + step,hSession->rectsel);
- cursor_move(hSession,hSession->select.end);
-
- return from+step;
-}
-
-LIB3270_EXPORT int lib3270_drag_selection(H3270 *h, unsigned char flag, int origin, int baddr)
-{
- int first, last, row, col;
-
- if(!lib3270_get_selection_bounds(h,&first,&last))
- return origin;
-
-/*
- trace("%s: flag=%04x %s %s %s %s",__FUNCTION__,
- flag,
- flag & SELECTION_LEFT ? "Left" : "-",
- flag & SELECTION_TOP ? "Top" : "-",
- flag & SELECTION_RIGHT ? "Right" : "-",
- flag & SELECTION_BOTTOM ? "Bottom" : "-"
- );
-*/
-
- if(!flag)
- return origin;
- else if((flag&0x8F) == SELECTION_ACTIVE)
- return lib3270_move_selected_area(h,origin,baddr);
-
- row = baddr/h->cols;
- col = baddr%h->cols;
-
- if(flag & SELECTION_LEFT) // Update left margin
- origin = first = ((first/h->cols)*h->cols) + col;
-
- if(flag & SELECTION_TOP) // Update top margin
- origin = first = (row*h->cols) + (first%h->cols);
-
- if(flag & SELECTION_RIGHT) // Update right margin
- origin = last = ((last/h->cols)*h->cols) + col;
-
- if(flag & SELECTION_BOTTOM) // Update bottom margin
- origin = last = (row*h->cols) + (last%h->cols);
-
- trace("origin=%d first=%d last=%d",origin,first,last);
-
- if(first < last)
- do_select(h,first,last,h->rectsel);
- else
- do_select(h,last,first,h->rectsel);
-
- cursor_move(h,h->select.end);
-
- return origin;
-}
-
-
-LIB3270_EXPORT int lib3270_move_selection(H3270 *hSession, LIB3270_DIRECTION dir)
-{
- int start, end;
-
- if(!hSession->selected || hSession->select.start == hSession->select.end)
- return ENOENT;
-
- start = hSession->select.start;
- end = hSession->select.end;
-
- switch(dir)
- {
- case LIB3270_DIR_UP:
- if(start <= hSession->cols)
- return EINVAL;
- start -= hSession->cols;
- end -= hSession->cols;
- break;
-
- case LIB3270_DIR_DOWN:
- if(end >= (hSession->cols * (hSession->rows-1)))
- return EINVAL;
- start += hSession->cols;
- end += hSession->cols;
- break;
-
- case LIB3270_DIR_LEFT:
- if( (start % hSession->cols) < 1)
- return EINVAL;
- start--;
- end--;
- break;
-
- case LIB3270_DIR_RIGHT:
- if( (end % hSession->cols) >= (hSession->cols-1))
- return EINVAL;
- start++;
- end++;
- break;
-
- default:
- return -1;
- }
-
- do_select(hSession,start,end,hSession->rectsel);
- cursor_move(hSession,hSession->select.end);
-
- return 0;
-}
-
diff --git a/src/lib3270/selection/actions.c b/src/lib3270/selection/actions.c
new file mode 100644
index 0000000..9d2d549
--- /dev/null
+++ b/src/lib3270/selection/actions.c
@@ -0,0 +1,328 @@
+/*
+ * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
+ * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
+ * aplicativos mainframe. Registro no INPI sob o nome G3270.
+ *
+ * Copyright (C) <2008>
+ *
+ * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
+ * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
+ * Free Software Foundation.
+ *
+ * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
+ * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
+ * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
+ * obter mais detalhes.
+ *
+ * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
+ * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
+ * St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Este programa está nomeado como selection.c e possui - linhas de código.
+ *
+ * Contatos:
+ *
+ * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
+ * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
+ *
+ */
+
+ #include "../private.h"
+ #include
+ #include
+ #include
+ #include
+ #include "3270ds.h"
+
+/*--[ Implement ]------------------------------------------------------------------------------------*/
+
+LIB3270_EXPORT int lib3270_unselect(H3270 *hSession)
+{
+ int a;
+
+ CHECK_SESSION_HANDLE(hSession);
+
+ trace("%s",__FUNCTION__);
+
+ if(hSession->selected)
+ {
+ hSession->selected = 0;
+
+ for(a = 0; a < hSession->rows*hSession->cols; a++)
+ {
+ if(hSession->text[a].attr & LIB3270_ATTR_SELECTED)
+ {
+ hSession->text[a].attr &= ~LIB3270_ATTR_SELECTED;
+ if(hSession->cbk.update)
+ hSession->cbk.update(hSession,a,hSession->text[a].chr,hSession->text[a].attr,a == hSession->cursor_addr);
+ }
+ }
+
+ hSession->cbk.set_selection(hSession,0);
+ hSession->cbk.update_selection(hSession,-1,-1);
+ }
+
+ return 0;
+}
+
+LIB3270_EXPORT void lib3270_select_to(H3270 *session, int baddr)
+{
+ int start, end;
+
+ CHECK_SESSION_HANDLE(session);
+
+ if(!lib3270_connected(session))
+ return;
+
+ start = session->selected ? session->select.start : session->cursor_addr;
+
+ cursor_move(session,end = baddr);
+
+ do_select(session,start,end,lib3270_get_toggle(session,LIB3270_TOGGLE_RECTANGLE_SELECT));
+
+}
+
+LIB3270_EXPORT int lib3270_select_region(H3270 *h, int start, int end)
+{
+ int maxlen;
+
+ CHECK_SESSION_HANDLE(h);
+
+ if(!lib3270_connected(h))
+ return ENOTCONN;
+
+ maxlen = (h->rows * h->cols);
+
+ // Check bounds
+ if(start < 0 || start > maxlen || end < 0 || end > maxlen || start > end)
+ return EINVAL;
+
+ do_select(h,start,end,lib3270_get_toggle(h,LIB3270_TOGGLE_RECTANGLE_SELECT));
+ cursor_move(h,h->select.end);
+
+ return 0;
+}
+
+LIB3270_EXPORT int lib3270_select_word_at(H3270 *session, int baddr)
+{
+ int start, end;
+
+ if(lib3270_get_word_bounds(session,baddr,&start,&end))
+ return -1;
+
+ trace("%s: baddr=%d start=%d end=%d",__FUNCTION__,baddr,start,end);
+
+ do_select(session,start,end,0);
+
+ return 0;
+}
+
+LIB3270_EXPORT int lib3270_select_field_at(H3270 *session, int baddr)
+{
+ int start, end;
+
+ if(lib3270_get_field_bounds(session,baddr,&start,&end))
+ return -1;
+
+ do_select(session,start,end,0);
+
+ return 0;
+}
+
+LIB3270_EXPORT int lib3270_select_field(H3270 *hSession)
+{
+ CHECK_SESSION_HANDLE(hSession);
+ lib3270_select_field_at(hSession,hSession->cursor_addr);
+ return 0;
+}
+
+LIB3270_EXPORT int lib3270_select_all(H3270 * hSession)
+{
+ FAIL_IF_NOT_ONLINE(hSession);
+
+ do_select(hSession,0,(hSession->rows*hSession->cols)-1,0);
+
+ return 0;
+}
+
+LIB3270_EXPORT int lib3270_reselect(H3270 *hSession)
+{
+ FAIL_IF_NOT_ONLINE(hSession);
+
+ if(hSession->select.start == hSession->select.end || hSession->selected)
+ return 0;
+
+ do_select(hSession, hSession->select.start,hSession->select.end,lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECTANGLE_SELECT));
+
+ return 0;
+}
+
+LIB3270_EXPORT int lib3270_get_selection_bounds(H3270 *hSession, int *start, int *end)
+{
+ int first, last;
+
+ CHECK_SESSION_HANDLE(hSession);
+
+ if(!hSession->selected || hSession->select.start == hSession->select.end)
+ return 0;
+
+ if(hSession->select.end > hSession->select.start)
+ {
+ first = hSession->select.start;
+ last = hSession->select.end;
+ }
+ else
+ {
+ first = hSession->select.end;
+ last = hSession->select.start;
+ }
+
+ if(start)
+ *start = first;
+
+ if(end)
+ *end = last;
+
+ return 1;
+}
+
+LIB3270_EXPORT int lib3270_move_selected_area(H3270 *hSession, int from, int to)
+{
+ int pos[2];
+ int rows, cols, f, step;
+
+ if(from == to)
+ return from;
+
+ if(!lib3270_get_selection_bounds(hSession,&pos[0],&pos[1]))
+ return from;
+
+ rows = (to / hSession->cols) - (from / hSession->cols);
+ cols = (to % hSession->cols) - (from % hSession->cols);
+
+ for(f=0;f<2;f++)
+ {
+ int row = (pos[f] / hSession->cols) + rows;
+ int col = (pos[f] % hSession->cols) + cols;
+
+ if(row < 0)
+ rows = - (pos[f] / hSession->cols);
+
+ if(col < 0)
+ cols = - (pos[f] % hSession->cols);
+
+ if(row >= (hSession->rows))
+ rows = hSession->rows - ((pos[f] / hSession->cols)+1);
+
+ if(col >= hSession->cols)
+ cols = hSession->cols - ((pos[f] % hSession->cols)+1);
+ }
+
+ step = (rows * hSession->cols) + cols;
+
+ do_select(hSession,hSession->select.start + step,hSession->select.end + step,hSession->rectsel);
+ cursor_move(hSession,hSession->select.end);
+
+ return from+step;
+}
+
+LIB3270_EXPORT int lib3270_drag_selection(H3270 *h, unsigned char flag, int origin, int baddr)
+{
+ int first, last, row, col;
+
+ if(!lib3270_get_selection_bounds(h,&first,&last))
+ return origin;
+
+/*
+ trace("%s: flag=%04x %s %s %s %s",__FUNCTION__,
+ flag,
+ flag & SELECTION_LEFT ? "Left" : "-",
+ flag & SELECTION_TOP ? "Top" : "-",
+ flag & SELECTION_RIGHT ? "Right" : "-",
+ flag & SELECTION_BOTTOM ? "Bottom" : "-"
+ );
+*/
+
+ if(!flag)
+ return origin;
+ else if((flag&0x8F) == SELECTION_ACTIVE)
+ return lib3270_move_selected_area(h,origin,baddr);
+
+ row = baddr/h->cols;
+ col = baddr%h->cols;
+
+ if(flag & SELECTION_LEFT) // Update left margin
+ origin = first = ((first/h->cols)*h->cols) + col;
+
+ if(flag & SELECTION_TOP) // Update top margin
+ origin = first = (row*h->cols) + (first%h->cols);
+
+ if(flag & SELECTION_RIGHT) // Update right margin
+ origin = last = ((last/h->cols)*h->cols) + col;
+
+ if(flag & SELECTION_BOTTOM) // Update bottom margin
+ origin = last = (row*h->cols) + (last%h->cols);
+
+ trace("origin=%d first=%d last=%d",origin,first,last);
+
+ if(first < last)
+ do_select(h,first,last,h->rectsel);
+ else
+ do_select(h,last,first,h->rectsel);
+
+ cursor_move(h,h->select.end);
+
+ return origin;
+}
+
+LIB3270_EXPORT int lib3270_move_selection(H3270 *hSession, LIB3270_DIRECTION dir)
+{
+ int start, end;
+
+ if(!hSession->selected || hSession->select.start == hSession->select.end)
+ return ENOENT;
+
+ start = hSession->select.start;
+ end = hSession->select.end;
+
+ switch(dir)
+ {
+ case LIB3270_DIR_UP:
+ if(start <= hSession->cols)
+ return EINVAL;
+ start -= hSession->cols;
+ end -= hSession->cols;
+ break;
+
+ case LIB3270_DIR_DOWN:
+ if(end >= (hSession->cols * (hSession->rows-1)))
+ return EINVAL;
+ start += hSession->cols;
+ end += hSession->cols;
+ break;
+
+ case LIB3270_DIR_LEFT:
+ if( (start % hSession->cols) < 1)
+ return EINVAL;
+ start--;
+ end--;
+ break;
+
+ case LIB3270_DIR_RIGHT:
+ if( (end % hSession->cols) >= (hSession->cols-1))
+ return EINVAL;
+ start++;
+ end++;
+ break;
+
+ default:
+ return -1;
+ }
+
+ do_select(hSession,start,end,hSession->rectsel);
+ cursor_move(hSession,hSession->select.end);
+
+ return 0;
+}
+
+
diff --git a/src/lib3270/selection/selection.c b/src/lib3270/selection/selection.c
new file mode 100644
index 0000000..9802058
--- /dev/null
+++ b/src/lib3270/selection/selection.c
@@ -0,0 +1,610 @@
+/*
+ * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
+ * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
+ * aplicativos mainframe. Registro no INPI sob o nome G3270.
+ *
+ * Copyright (C) <2008>
+ *
+ * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
+ * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
+ * Free Software Foundation.
+ *
+ * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
+ * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
+ * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
+ * obter mais detalhes.
+ *
+ * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
+ * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
+ * St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Este programa está nomeado como selection.c e possui - linhas de código.
+ *
+ * Contatos:
+ *
+ * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
+ * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
+ *
+ */
+
+ #include "../private.h"
+ #include
+ #include
+ #include
+ #include
+ #include "3270ds.h"
+
+ /*--[ Implement ]------------------------------------------------------------------------------------*/
+
+static void get_selected_addr(H3270 *session, int *start, int *end)
+{
+ if(session->select.start > session->select.end)
+ {
+ *end = session->select.start;
+ *start = session->select.end;
+ }
+ else
+ {
+ *start = session->select.start;
+ *end = session->select.end;
+ }
+}
+
+static void update_selected_rectangle(H3270 *session)
+{
+ struct
+ {
+ int row;
+ int col;
+ } p[2];
+
+
+ int begin, end, row, col, baddr;
+
+ get_selected_addr(session,&begin,&end);
+
+ // Get start & end posision
+ p[0].row = (begin/session->cols);
+ p[0].col = (begin%session->cols);
+ p[1].row = (end/session->cols);
+ p[1].col = (end%session->cols);
+
+ if(p[0].row > p[1].row)
+ {
+ int swp = p[0].row;
+ p[0].row = p[1].row;
+ p[1].row = swp;
+ }
+
+ if(p[0].col > p[1].col)
+ {
+ int swp = p[0].col;
+ p[0].col = p[1].col;
+ p[1].col = swp;
+ }
+
+ // First remove unselected areas
+ baddr = 0;
+ for(row=0;row < session->rows;row++)
+ {
+ for(col = 0; col < session->cols;col++)
+ {
+ if(!(row >= p[0].row && row <= p[1].row && col >= p[0].col && col <= p[1].col) && (session->text[baddr].attr & LIB3270_ATTR_SELECTED))
+ {
+ session->text[baddr].attr &= ~LIB3270_ATTR_SELECTED;
+ session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
+ }
+ baddr++;
+ }
+ }
+
+ // Then, draw selected ones
+ baddr = 0;
+ for(row=0;row < session->rows;row++)
+ {
+ for(col = 0; col < session->cols;col++)
+ {
+ if((row >= p[0].row && row <= p[1].row && col >= p[0].col && col <= p[1].col) && !(session->text[baddr].attr & LIB3270_ATTR_SELECTED))
+ {
+ session->text[baddr].attr |= LIB3270_ATTR_SELECTED;
+ session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
+ }
+ baddr++;
+ }
+ }
+
+}
+
+static void update_selected_region(H3270 *session)
+{
+ int baddr,begin,end;
+ int len = session->rows*session->cols;
+
+ get_selected_addr(session,&begin,&end);
+
+ // First remove unselected areas
+ for(baddr = 0; baddr < begin; baddr++)
+ {
+ if(session->text[baddr].attr & LIB3270_ATTR_SELECTED)
+ {
+ session->text[baddr].attr &= ~LIB3270_ATTR_SELECTED;
+ session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
+ }
+ }
+
+ for(baddr = end+1; baddr < len; baddr++)
+ {
+ if(session->text[baddr].attr & LIB3270_ATTR_SELECTED)
+ {
+ session->text[baddr].attr &= ~LIB3270_ATTR_SELECTED;
+ session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
+ }
+ }
+
+ // Then draw the selected ones
+ for(baddr = begin; baddr <= end; baddr++)
+ {
+ if(!(session->text[baddr].attr & LIB3270_ATTR_SELECTED))
+ {
+ session->text[baddr].attr |= LIB3270_ATTR_SELECTED;
+ session->cbk.update(session,baddr,session->text[baddr].chr,session->text[baddr].attr,baddr == session->cursor_addr);
+ }
+ }
+
+}
+
+void toggle_rectselect(H3270 *session, struct lib3270_toggle GNUC_UNUSED(*t), LIB3270_TOGGLE_TYPE GNUC_UNUSED(tt))
+{
+ if(!session->selected)
+ return;
+
+ if(t->value)
+ update_selected_rectangle(session);
+ else
+ update_selected_region(session);
+}
+
+void do_select(H3270 *h, int start, int end, int rect)
+{
+ if(start < 0 || end > (h->rows * h->cols))
+ return;
+
+ // Do we really need to change selection?
+ if(start == h->select.start && end == h->select.end && h->selected)
+ return;
+
+ // Start address is inside the screen?
+ h->select.start = start;
+ h->select.end = end;
+
+ if(rect)
+ {
+ h->rectsel = 1;
+ update_selected_rectangle(h);
+ }
+ else
+ {
+ h->rectsel = 0;
+ update_selected_region(h);
+ }
+
+ if(!h->selected)
+ {
+ h->selected = 1;
+ h->cbk.set_selection(h,1);
+ }
+
+ h->cbk.update_selection(h,start,end);
+
+}
+
+LIB3270_EXPORT unsigned char lib3270_get_selection_flags(H3270 *hSession, int baddr)
+{
+ int row,col;
+ unsigned char rc = 0;
+
+ CHECK_SESSION_HANDLE(hSession);
+
+ if(!(lib3270_connected(hSession) && (hSession->text[baddr].attr & LIB3270_ATTR_SELECTED)))
+ return rc;
+
+ row = baddr / hSession->cols;
+ col = baddr % hSession->cols;
+ rc |= SELECTION_ACTIVE;
+
+ if( (hSession->select.start % hSession->cols) == (hSession->select.end % hSession->cols) )
+ {
+ rc |= SELECTION_SINGLE_COL;
+ }
+ else
+ {
+ if( (col == 0) || !(hSession->text[baddr-1].attr & LIB3270_ATTR_SELECTED) )
+ rc |= SELECTION_LEFT;
+
+ if( (col == hSession->cols) || !(hSession->text[baddr+1].attr & LIB3270_ATTR_SELECTED) )
+ rc |= SELECTION_RIGHT;
+ }
+
+ if( (hSession->select.start / hSession->cols) == (hSession->select.end / hSession->cols) )
+ {
+ rc |= SELECTION_SINGLE_ROW;
+ }
+ else
+ {
+ if( (row == 0) || !(hSession->text[baddr-hSession->cols].attr & LIB3270_ATTR_SELECTED) )
+ rc |= SELECTION_TOP;
+
+ if( (row == hSession->rows) || !(hSession->text[baddr+hSession->cols].attr & LIB3270_ATTR_SELECTED) )
+ rc |= SELECTION_BOTTOM;
+ }
+
+ return rc;
+}
+
+static char * get_text(H3270 *hSession,unsigned char all, unsigned char tok)
+{
+ int row, col, baddr;
+ char * ret;
+ size_t buflen = (hSession->rows * (hSession->cols+1))+1;
+ size_t sz = 0;
+ unsigned short attr = 0xFFFF;
+
+ if(!(lib3270_connected(hSession) && hSession->text))
+ {
+ errno = ENOTCONN;
+ return NULL;
+ }
+
+ ret = lib3270_malloc(buflen);
+
+ baddr = 0;
+
+ for(row=0;row < hSession->rows;row++)
+ {
+ int cr = 0;
+
+ for(col = 0; col < hSession->cols;col++)
+ {
+ if(all || hSession->text[baddr].attr & LIB3270_ATTR_SELECTED)
+ {
+ if(tok && attr != hSession->text[baddr].attr)
+ {
+ attr = hSession->text[baddr].attr;
+ ret[sz++] = tok;
+ ret[sz++] = (attr & 0x0F);
+ ret[sz++] = ((attr & 0xF0) >> 4);
+ }
+
+ cr++;
+ ret[sz++] = hSession->text[baddr].chr;
+ }
+ baddr++;
+ }
+
+ if(cr)
+ ret[sz++] = '\n';
+
+ if((sz+10) > buflen)
+ {
+ buflen += 100;
+ ret = lib3270_realloc(ret,buflen);
+ }
+ }
+
+ if(!sz)
+ {
+ lib3270_free(ret);
+ errno = ENOENT;
+ return NULL;
+ }
+ else if(sz > 1 && ret[sz-1] == '\n') // Remove ending \n
+ {
+ ret[sz-1] = 0;
+ }
+
+ ret[sz++] = 0;
+
+ if(sz != buflen)
+ ret = lib3270_realloc(ret,sz);
+
+ return ret;
+}
+
+LIB3270_EXPORT char * lib3270_get_region(H3270 *h, int start_pos, int end_pos, unsigned char all)
+{
+ char * text;
+ int maxlen;
+ int sz = 0;
+ int baddr;
+
+ CHECK_SESSION_HANDLE(h);
+
+ if(!lib3270_connected(h))
+ return NULL;
+
+ maxlen = h->rows * (h->cols+1);
+
+ if(start_pos < 0 || start_pos > maxlen || end_pos < 0 || end_pos > maxlen || end_pos < start_pos)
+ return NULL;
+
+ text = lib3270_malloc(maxlen);
+
+ for(baddr=start_pos;baddrtext[baddr].attr & LIB3270_ATTR_SELECTED)
+ text[sz++] = (h->text[baddr].attr & LIB3270_ATTR_CG) ? ' ' : h->text[baddr].chr;
+
+ if((baddr%h->cols) == 0 && sz > 0)
+ text[sz++] = '\n';
+ }
+ text[sz++] = 0;
+
+ return lib3270_realloc(text,sz);
+}
+
+LIB3270_EXPORT char * lib3270_get_string_at_address(H3270 *h, int offset, int len, char lf)
+{
+ char * buffer;
+ int maxlen;
+ char * ptr;
+
+ CHECK_SESSION_HANDLE(h);
+
+ if(!lib3270_connected(h))
+ {
+ errno = ENOTCONN;
+ return NULL;
+ }
+
+ maxlen = (h->rows * (h->cols+1)) - offset;
+ if(maxlen <= 0 || offset < 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if(len < 0 || len > maxlen)
+ len = maxlen;
+
+ buffer = lib3270_malloc(len+1);
+ ptr = buffer;
+
+// trace("len=%d buffer=%p",len,buffer);
+
+ while(len > 0)
+ {
+ if(h->text[offset].attr & LIB3270_ATTR_CG)
+ *ptr = ' ';
+ else if(h->text[offset].chr)
+ *ptr = h->text[offset].chr;
+ else
+ *ptr = ' ';
+
+ ptr++;
+ offset++;
+ len--;
+
+ if(lf && (offset%h->cols) == 0 && len > 0)
+ {
+ *(ptr++) = lf;
+ len--;
+ }
+ }
+// trace("len=%d buffer=%p pos=%d",len,buffer,ptr-buffer);
+
+ *ptr = 0;
+
+ return buffer;
+}
+
+LIB3270_EXPORT char * lib3270_get_string_at(H3270 *h, int row, int col, int len, char lf)
+{
+ CHECK_SESSION_HANDLE(h);
+ return lib3270_get_string_at_address(h, ((row-1) * h->cols) + (col-1), len, lf);
+}
+
+LIB3270_EXPORT int lib3270_cmp_text_at(H3270 *h, int row, int col, const char *text, char lf)
+{
+ int rc;
+ size_t sz = strlen(text);
+ char * contents;
+
+ contents = lib3270_get_string_at(h,row,col,sz,lf);
+ if(!contents)
+ return -1;
+
+ rc = strncmp(contents,text,sz);
+
+ lib3270_free(contents);
+
+ return rc;
+}
+
+
+/**
+ * Get field contents
+ *
+ * @param session Session handle
+ * @param baddr Field addr
+ *
+ * @return String with the field contents (release it with lib3270_free()
+ */
+LIB3270_EXPORT char * lib3270_get_field_text_at(H3270 *session, int baddr)
+{
+ int first = lib3270_field_addr(session,baddr);
+
+ if(first < 0)
+ return NULL;
+
+ return lib3270_get_string_at_address(session,first,lib3270_field_length(session,first)+1,0);
+}
+
+LIB3270_EXPORT int lib3270_has_selection(H3270 *hSession)
+{
+ CHECK_SESSION_HANDLE(hSession);
+ return hSession->selected != 0;
+}
+
+LIB3270_EXPORT char * lib3270_get_selected(H3270 *hSession)
+{
+ CHECK_SESSION_HANDLE(hSession);
+
+ if(!hSession->selected || hSession->select.start == hSession->select.end)
+ return NULL;
+
+ if(!lib3270_connected(hSession))
+ return NULL;
+
+
+ return get_text(hSession,0,0);
+}
+
+static void copy_chr(H3270 *hSession, int from, int to)
+{
+ if(hSession->text[from].chr == hSession->text[to].chr)
+ return;
+
+ hSession->text[to].chr = hSession->text[from].chr;
+
+ memcpy(&hSession->ea_buf[to], &hSession->ea_buf[from],sizeof(struct lib3270_ea));
+ hSession->ea_buf[from].fa = 0;
+
+ hSession->cbk.update( hSession,
+ to,
+ hSession->text[to].chr,
+ hSession->text[to].attr,
+ to == hSession->cursor_addr );
+}
+
+static void clear_chr(H3270 *hSession, int baddr)
+{
+ hSession->text[baddr].chr = ' ';
+
+ hSession->ea_buf[baddr].cc = EBC_null;
+ hSession->ea_buf[baddr].cs = 0;
+
+ hSession->cbk.update( hSession,
+ baddr,
+ hSession->text[baddr].chr,
+ hSession->text[baddr].attr,
+ baddr == hSession->cursor_addr );
+}
+
+int cut_addr(H3270 *hSession, int daddr, int saddr, int maxlen, int *sattr)
+{
+ if(hSession->ea_buf[saddr].fa)
+ *sattr = hSession->ea_buf[saddr++].fa;
+
+ if(FA_IS_PROTECTED(*sattr) || saddr >= maxlen)
+ clear_chr(hSession,daddr);
+ else
+ copy_chr(hSession,saddr++,daddr);
+
+ return saddr;
+}
+
+char * cut_text(H3270 *hSession, char tok)
+{
+ unsigned short attr = 0xFFFF;
+
+ CHECK_SESSION_HANDLE(hSession);
+
+ if(!hSession->selected || hSession->select.start == hSession->select.end)
+ return NULL;
+
+ if(!(lib3270_connected(hSession) && hSession->text))
+ return NULL;
+
+ trace("Rectangle select is %s",lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECTANGLE_SELECT) ? "Active" : "Inactive");
+
+ if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECTANGLE_SELECT))
+ {
+ // Rectangle cut is not implemented
+ lib3270_popup_dialog(hSession, LIB3270_NOTIFY_INFO, _( "Not available" ), _( "Invalid cut action" ), "%s", _( "Can't cut rectangular regions") );
+ }
+ else
+ {
+ int end;
+ size_t szText;
+ size_t buflen;
+ size_t bufpos = 0;
+ int daddr; /* Destination addr */
+ int dattr; /* Destination addr attribute */
+ int saddr; /* Source addr (First field after the selected area) */
+ int sattr; /* Source addr attribute */
+ char *text;
+ size_t maxlen = hSession->rows * hSession->cols;
+ size_t f;
+
+ get_selected_addr(hSession,&daddr,&end);
+
+ lib3270_set_cursor_address(hSession,daddr);
+
+ if(daddr >= end)
+ return NULL;
+
+ dattr = lib3270_field_attribute(hSession,daddr); /* Get first attribute */
+
+ szText = (end-daddr)+1;
+ buflen = szText;
+ bufpos = 0;
+
+ text = lib3270_malloc(buflen+1);
+
+ saddr = daddr+szText;
+ sattr = lib3270_field_attribute(hSession,saddr);
+
+ for(f=0;fea_buf[daddr].fa)
+ dattr = hSession->ea_buf[daddr].fa;
+
+ if((bufpos+10) > buflen)
+ {
+ buflen += 100;
+ text = lib3270_realloc(text,buflen);
+ }
+
+ if(tok && attr != hSession->text[daddr].attr)
+ {
+ attr = hSession->text[daddr].attr;
+ text[bufpos++] = tok;
+ text[bufpos++] = (attr & 0x0F);
+ text[bufpos++] = ((attr & 0xF0) >> 4);
+ }
+
+ text[bufpos++] = hSession->text[daddr].chr;
+
+ if(!FA_IS_PROTECTED(dattr))
+ saddr = cut_addr(hSession,daddr,saddr,maxlen,&sattr);
+
+ daddr++;
+ }
+
+ text[bufpos++] = 0;
+ text = lib3270_realloc(text,bufpos);
+
+ // Move contents of the current field
+ while(daddr < (int) (maxlen-1) && !hSession->ea_buf[daddr].fa)
+ {
+ saddr = cut_addr(hSession,daddr,saddr,maxlen,&sattr);
+ daddr++;
+ }
+
+ if(!hSession->ea_buf[daddr].fa)
+ clear_chr(hSession,daddr);
+
+ hSession->cbk.changed(hSession,0,maxlen);
+
+ lib3270_unselect(hSession);
+ return text;
+ }
+
+ return NULL;
+}
+
+LIB3270_EXPORT char * lib3270_cut_selected(H3270 *hSession)
+{
+ return cut_text(hSession,0);
+}
+
diff --git a/src/lib3270/valgrind.suppression b/src/lib3270/valgrind.suppression
index e69de29..0f577b5 100644
--- a/src/lib3270/valgrind.suppression
+++ b/src/lib3270/valgrind.suppression
@@ -0,0 +1,14 @@
+{
+ libcrypt_FIPS_selftest
+ Memcheck:Cond
+ ...
+ fun:FIPS_selftest
+}
+
+{
+ libcrypt_FIPS_mode_set
+ Memcheck:Cond
+ ...
+ fun:FIPS_mode_set
+}
+
--
libgit2 0.21.2