/* SPDX-License-Identifier: LGPL-3.0-or-later */
/*
* Copyright (C) 2008 Banco do Brasil S.A.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#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 < ((int) (hSession->view.rows * hSession->view.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);
lib3270_action_group_notify(hSession,LIB3270_ACTION_GROUP_SELECTION);
}
return 0;
}
LIB3270_EXPORT void lib3270_select_to(H3270 *session, int baddr) {
int start, end;
CHECK_SESSION_HANDLE(session);
if(!lib3270_is_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_is_connected(h))
return ENOTCONN;
maxlen = (h->view.rows * h->view.cols);
// Check bounds
if(start < 0 || start > maxlen || end < 0 || end > maxlen)
return EINVAL;
do_select(h,start,end,lib3270_get_toggle(h,LIB3270_TOGGLE_RECTANGLE_SELECT));
return 0;
}
LIB3270_EXPORT int lib3270_select_word(H3270 *session) {
return lib3270_select_word_at(session,-1);
}
LIB3270_EXPORT int lib3270_select_word_at(H3270 *session, int baddr) {
int start, end, rc;
rc = lib3270_get_word_bounds(session,baddr,&start,&end);
if(rc)
return rc;
trace("%s: baddr=%d start=%d end=%d",__FUNCTION__,baddr,start,end);
rc = do_select(session,start,end,0);
if(rc)
return rc;
// Notify word selected to allow testing for URL selection.
session->cbk.word_selected(session,start,end);
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->view.rows * hSession->view.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->view.cols) - (from / hSession->view.cols);
cols = (to % hSession->view.cols) - (from % hSession->view.cols);
for(f=0; f<2; f++) {
int row = (pos[f] / hSession->view.cols) + rows;
int col = (pos[f] % hSession->view.cols) + cols;
if(row < 0)
rows = - (pos[f] / hSession->view.cols);
if(col < 0)
cols = - (pos[f] % hSession->view.cols);
if(row >= ((int) hSession->view.rows))
rows = hSession->view.rows - ((pos[f] / hSession->view.cols)+1);
if(col >= ((int) hSession->view.cols))
cols = hSession->view.cols - ((pos[f] % hSession->view.cols)+1);
}
step = (rows * hSession->view.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->view.cols;
col = baddr%h->view.cols;
if(flag & SELECTION_LEFT) // Update left margin
origin = first = ((first/h->view.cols)*h->view.cols) + col;
if(flag & SELECTION_TOP) // Update top margin
origin = first = (row*h->view.cols) + (first%h->view.cols);
if(flag & SELECTION_RIGHT) // Update right margin
origin = last = ((last/h->view.cols)*h->view.cols) + col;
if(flag & SELECTION_BOTTOM) // Update bottom margin
origin = last = (row*h->view.cols) + (last%h->view.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 <= ((int) hSession->view.cols))
return EINVAL;
start -= hSession->view.cols;
end -= hSession->view.cols;
break;
case LIB3270_DIR_DOWN:
if(end >= ((int) (hSession->view.cols * (hSession->view.rows-1))))
return EINVAL;
start += hSession->view.cols;
end += hSession->view.cols;
break;
case LIB3270_DIR_LEFT:
if( (start % hSession->view.cols) < 1)
return EINVAL;
start--;
end--;
break;
case LIB3270_DIR_RIGHT:
if( (end % hSession->view.cols) >= (hSession->view.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;
}