tinycobol/lib/scr_curses.c

1656 lines
39 KiB
C

//
// Copyright (C) 2002,2001, 2000, 1999, Rildo Pragana, Jim Noeth,
// Andrew Cameron, David Essex.
// Copyright (C) 1993, 1991 Rildo Pragana.
//
// This library 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 2.1,
// or (at your option) any later version.
//
// This library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; see the file COPYING.LIB. If
// not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Cobol Compiler Run Time Library
// Curses Screen I/O Functions - Screen frontedn
//
#include "htcoblib.h"
#include "mwindows.h"
#if defined(SunOS)
#include <curses.h>
#else
# if defined(__CYGWIN__)
# include <ncurses/ncurses.h>
# else
# if defined(__MINGW32__)
# include <curses.h> //# include <pdcurses.h>
# else
# include <curses.h>
# endif
# endif
#endif
#include "screenio.h"
#include "rterrors.h"
#include "config.h"
/* PDcurses 2.4 does not have the following defenetion */
#ifndef KEY_CODE_YES
#define KEY_CODE_YES 0x100 /* A wchar_t contains a key code */
#endif
static short fore_color; // Actual fore and back colors
static short back_color;
static int cursor_x = 0; // Actual screen position for dinamically
static int cursor_y = 0; // calculate +/- line/col
extern int bDecimalComma;
static struct KeyBinding *keyBindings;
int tcob_isZNum(char *p); // walter
//
// Initialize curses
//
int tcob_scr_init(){
int i;
initscr();
noecho();
cbreak();
keypad(stdscr,TRUE);
scrollok(stdscr,FALSE); //walter: turn off scroll possibility
nonl();
//raw();
noecho();
//walter 03-01-06 if (has_colors())
//walter 03-01-06 start_color();
keyBindings = tcob_get_keybindings();
// pair_content(0,&fore_color,&back_color); walter: pair_content first argument must be between 1 and COLOR_PAIRS-1
attrset(A_NORMAL);
//
// This is needed for pdcurses, that has all the pairs to 0-7
//
//walter 03-01-06 for(i=0;i<COLOR_PAIRS;i++)
//walter 03-01-06 init_pair(i,0,0);
if(has_colors()) { // temos suporte a cores
start_color();
}
attrset(A_NORMAL);
for(i = 0; i < COLOR_PAIRS; i++)
init_pair(i, i%COLORS, i/COLORS);
return TRUE;
}
//
// Close curses
//
void tcob_scr_finish(){
if(!isendwin())
endwin();
}
//
// Set len positions to c
//
static void tcob_scr_setchar(char c, unsigned int len){
unsigned int i;
for (i=0; i<len; i++)
addch(c);
}
//
// Get actual cursos position on the screen
//
int tcob_scr_getx(){
return cursor_x;
}
int tcob_scr_gety(){
return cursor_y;
}
/* Scroll screen up by one line, if needed, and
return if actually scrolled or not */
int tcob_scr_scrl() {
if (cursor_y >= (LINES-1)) {
scrollok(stdscr,TRUE); //walter: turn on scroll possibility
scrl(1); // scroll 1 line
scrollok(stdscr,FALSE); //walter: turn off scroll possibility
move(cursor_y,0);
cursor_x=0;
return 1;
}
return 0;
}
//
// Set cursos position on the screen
//
void tcob_scr_setyx(int y, int x){
move(y,x);
getyx(stdscr,cursor_y,cursor_x);
}
void tcob_scr_setx(int x){
tcob_scr_setyx(tcob_scr_gety(),x);
}
void tcob_scr_sety(int y){
tcob_scr_setyx(y,tcob_scr_getx());
}
//
// Get the status of keyboard.
//
// return TRUE if there is a char in the buffer and FALSE if not
//
int tcob_scr_kbdstatus(){
int c;
nodelay(stdscr,TRUE);
c=getch();
nodelay(stdscr,FALSE);
if (c==ERR) {
return 0;
}
ungetch(c);
return 1;
}
/*-------------------------------------------------------------------------*\
| |
| tcob_scr_action_for_key |
| Looks in the table which is the action to return for the key passed. |
| If exists the SCREEN STATUS field moves the value in the table to it. |
| |
\*-------------------------------------------------------------------------*/
int tcob_scr_action_for_key(int key,int *status) {
struct KeyBinding *binding=NULL;
struct KeyBinding *pbindings;
for(pbindings=keyBindings; pbindings->keyCode!=0; pbindings++) {
if (pbindings->keyCode == key) {
binding=pbindings;
break;
}
}
if (binding==NULL) {
return EDIT_NOP;
}
*status = binding->screenStatus;
return binding->action;
}
/*
check the configuration for "auto clean all" setting
*/
int tcob_autocleanall() {
struct KeyBinding *binding=NULL;
struct KeyBinding *pbindings;
for(pbindings=keyBindings; pbindings->keyCode!=0; pbindings++) {
if (pbindings->keyCode == TCOBKEY_AUTOCLEANALL) {
binding=pbindings;
break;
}
}
if (binding==NULL) {
return 0;
}
return binding->screenStatus;
}
//
// Returns the curses color code from the cobol color number
//
static int get_curses_color(int cobol_color) {
unsigned int colour = COLOR_BLACK;
// switch(cobol_color % 8) {
switch(cobol_color % COLORS) {
case TC_BLUE:
colour = COLOR_BLUE;
break;
case TC_GREEN:
colour = COLOR_GREEN;
break;
case TC_CYAN:
colour = COLOR_CYAN;
break;
case TC_RED:
colour = COLOR_RED;
break;
case TC_MAGENTA:
colour = COLOR_MAGENTA;
break;
case TC_YELLOW:
colour = COLOR_YELLOW;
break;
case TC_WHITE:
colour = COLOR_WHITE;
break;
case TC_BLACK:
default:
break;
}
return colour;
}
/*static int get_curses_color(int cobol_color) {
// Color numbers from standard
//
// 0 - black
// 1 - blue
// 2 - green
// 3 - cyan
// 4 - red
// 5 - magenta
// 6 - brown/yellow
// 7 - white
//
// Curses colors
// #define COLOR_BLACK 0
// #define COLOR_RED 1
// #define COLOR_GREEN 2
// #define COLOR_YELLOW 3
// #define COLOR_BLUE 4
// #define COLOR_MAGENTA 5
// #define COLOR_CYAN 6
// #define COLOR_WHITE 7
//
//switch(cobol_color % 8) {
switch(cobol_color % COLORS) {
case TC_BLACK: return COLOR_BLACK;
case TC_BLUE: return COLOR_BLUE;
case TC_GREEN: return COLOR_GREEN;
case TC_CYAN: return COLOR_CYAN;
case TC_RED: return COLOR_RED;
case TC_MAGENTA:return COLOR_MAGENTA;
case TC_YELLOW: return COLOR_YELLOW;
case TC_WHITE: return COLOR_WHITE;
default:return 0;
}
}*/
//
// sets the color for the next display
//
static void set_colors(){
int i;
// short fore,back;
/*walter 03-01-06
for(i = 0; i < COLOR_PAIRS; ++i) {
pair_content(i,&fore,&back);
if ((fore == fore_color) && (back == back_color)) {
break;
}
if ((fore == 0) && (back == 0)) {
init_pair(i,fore_color,back_color);
break;
}
}
*/
i=(back_color*8)+fore_color;
if (i != COLOR_PAIRS)
{
#ifdef CURSES_HAS_COLOR_SET
color_set(i,NULL);
#else
attrset(COLOR_PAIR(i));
#endif
bkgdset(COLOR_PAIR(i));
} else {
attrset(A_NORMAL);
}
}
/*-------------------------------------------------------------------------*\
| |
| set_attributes |
| |
\*-------------------------------------------------------------------------*/
static void set_atributes(struct ScrFld *pFld) {
attr_t iAttr=0;
chtype pos; // walter
short color; // walter
attrset(A_NORMAL);
if (pFld->iAttributes != -1)
{
if ((pFld->iAttributes & SCR_HIGHLIGHT) == SCR_HIGHLIGHT)
iAttr |= A_BOLD;
if ((pFld->iAttributes & SCR_LOWLIGHT) == SCR_LOWLIGHT)
iAttr |= A_DIM;
if ((pFld->iAttributes & SCR_UNDERLINE) == SCR_UNDERLINE)
iAttr |= A_UNDERLINE;
if ((pFld->iAttributes & SCR_REVERSE_VIDEO) == SCR_REVERSE_VIDEO)
iAttr |= A_REVERSE;
if ((pFld->iAttributes & SCR_BLINK) == SCR_BLINK) {
iAttr |= A_BLINK;
}
if ((pFld->iAttributes & SCR_BELL) == SCR_BELL)
beep();
if ((pFld->iAttributes & SCR_BLANK_SCREEN) == SCR_BLANK_SCREEN) {
clear();
tcob_scr_setyx(tcob_scr_gety(),tcob_scr_getx());
}
attron(iAttr);
}
if (has_colors() == TRUE) {
fore_color=COLOR_WHITE;
back_color=COLOR_BLACK;
pos = mvinch(pFld->iLine, pFld->iCol);
color = ( pos & A_COLOR ) / 256;
if (pFld->iFgColor != -1){
fore_color=get_curses_color(pFld->iFgColor);
} else { // walter, get the foreground color in screen
if(color)
fore_color=color % 8;
} // fim walter
if (pFld->iBgColor != -1) {
back_color=get_curses_color(pFld->iBgColor);
} else { // walter, get the background color in screen
if(color)
back_color=color / 8;
}
set_colors();
}
/*
chtype pos; // walter
unsigned int color; // walter
if (pFld->iAttributes != -1)
{
if (pFld->iAttributes & SCR_HIGHLIGHT) attron(A_BOLD);
else attroff(A_BOLD);
if (pFld->iAttributes & SCR_LOWLIGHT) attron(A_DIM);
else attroff(A_DIM);
if(pFld->iAttributes & SCR_UNDERLINE) attron(A_UNDERLINE);
else attroff(A_UNDERLINE);
if(pFld->iAttributes & SCR_REVERSE_VIDEO) attron(A_REVERSE);
else attroff(A_REVERSE);
if(pFld->iAttributes & SCR_BLINK) attron(A_BLINK);
else attroff(A_BLINK);
if(pFld->iAttributes & SCR_BELL)
beep();
if(pFld->iAttributes & SCR_BLANK_SCREEN) {
clear();
tcob_scr_setyx(tcob_scr_gety(),tcob_scr_getx());
}
}
if (pFld->iFgColor != -1){
fore_color=get_curses_color(pFld->iFgColor);
} else { // walter, get the foreground color in screen
pos = mvinch(pFld->iLine, pFld->iCol);
color = ( pos & A_COLOR ) / 256;
fore_color=color % 8;
} // fim walter
if (pFld->iBgColor != -1){
back_color=get_curses_color(pFld->iBgColor);
} else { // walter, get the background color in screen
pos = mvinch(pFld->iLine, pFld->iCol);
color = ( pos & A_COLOR ) / 256;
back_color=color / 8;
if(fore_color == 0 && back_color == 0)
fore_color = 7;
}
set_colors();
*/
}
/*-------------------------------------------------------------------------*\
| |
| _DisplayField |
| |
\*-------------------------------------------------------------------------*/
static void _DisplayField(struct ScrFld *pFld) {
set_atributes(pFld);
tcob_scr_setyx(pFld->iLine, pFld->iCol);
if(pFld->iAttributes & SCR_BLANK_LINE){ // erase all the current line
move(tcob_scr_gety(),0);
clrtoeol();
tcob_scr_setyx(tcob_scr_gety(),tcob_scr_getx());
}
if(pFld->iAttributes & SCR_ERASE_EOL) // erase to end of line
clrtoeol();
if(pFld->iAttributes & SCR_ERASE_EOS) // erase to end of screen
clrtobot();
if(pFld->iAttributes & SCR_BELL)
beep();
if(pFld->iAttributes & SCR_BLANK_SCREEN){
clear();
tcob_scr_setyx(tcob_scr_gety(),tcob_scr_getx());
}
if(pFld->iAttributes & SCR_SECURE) {
tcob_scr_setchar('*', pFld->fldScr.len);
} else {
if((pFld->iAttributes & SCR_BLANK_WHEN_ZERO) != SCR_BLANK_WHEN_ZERO) {
addnstr(pFld->caScr, pFld->fldScr.len);
} else {
unsigned int i, sign;
tcob_scr_setyx(pFld->iLine, pFld->iCol);
sign = tcob_extract_sign(&pFld->fldWk, pFld->caWk);
for(i = 0; i < pFld->fldWk.len; ++i) {
if(pFld->caWk[i] != '0')
break;
}
tcob_put_sign(&pFld->fldWk, pFld->caWk, sign);
if(i == pFld->fldWk.len)
tcob_scr_setchar(' ', pFld->fldScr.len);
else
addnstr(pFld->caScr, pFld->fldScr.len);
}
}
}
/*-------------------------------------------------------------------------*\
| |
| _DisplayForAccept |
| |
\*-------------------------------------------------------------------------*/
static void _DisplayForAccept(struct ScrFld *pFld) {
set_atributes(pFld);
tcob_scr_setyx(pFld->iLine, pFld->iCol);
if(pFld->iAttributes & SCR_BLANK_LINE)
clrtoeol();
if(pFld->iAttributes & SCR_SECURE)
tcob_scr_setchar('*', pFld->fldScr.len);
else if(pFld->iAttributes & SCR_NOECHO)
tcob_scr_setchar(' ', pFld->fldScr.len);
else
addnstr(pFld->caScr, pFld->fldScr.len);
}
void tcob_scr_display_field(struct ScrFld *pFld){
_DisplayField(pFld);
}
void tcob_scr_display_for_input(struct ScrFld *pFld){
_DisplayForAccept(pFld);
}
void tcob_scr_display(struct ScrFld *fields){
struct ScrFld *pFld;
for(pFld=fields; pFld; pFld=pFld->pNext) {
// if(pFld->fldFrom) { /* if we have a from field */
// tcob_move(pFld->fldFrom, pFld->caFrom, &(pFld->fldScr), pFld->caScr);
// }
tcob_scr_display_field(pFld);
tcob_scr_setx(tcob_scr_getx() + pFld->fldScr.len);
}
}
static int full_field(struct ScrFld *pFld) {
return ((pFld->charCount - pFld->decimals) >= (pFld->len - pFld->decimals));
}
static int first_pos(struct ScrFld *pFld) {
int t = pFld->fldScr.len - 1;
int pos = 0;
if (NUMERICFIELD(pFld->fldScr.type)) {
while (pos < t && pFld->caScr[pos] == ' ')
pos++;
}
return pos;
}
static int last_pos(struct ScrFld *pFld) {
unsigned int b = (pFld->decimalPointPosition <= pFld->iScrPos);
int full = full_field(pFld);
int pos;
if (NUMERICFIELD(pFld->fldScr.type)) {
pos = pFld->fldScr.len - 1;
if (!b && !full) { /* cursor wasn't already over the decimal point */
if (pFld->decimalPointPosition >= 0)
pos = pFld->decimalPointPosition;
}
}
else {
pos = pFld->charCount;
if (pos == pFld->fldScr.len) pos--;
}
return pos;
}
/*-------------------------------------------------------------------------*\
| |
| move_cursor_first |
| move_cursor_last |
| move_cursor_left |
| move_cursor_right |
| |
| This are helper functions for cob_accept_screen to help moving inside a |
| field. |
\*-------------------------------------------------------------------------*/
static void move_cursor_first(struct ScrFld *pFld) {
pFld->iScrPos = first_pos(pFld);
pFld->iFldPos = 0;
}
static void move_cursor_last(struct ScrFld *pFld) {
pFld->iScrPos = last_pos(pFld);
}
static int move_cursor_left(struct ScrFld *pFld) {
char cWk;
int p = first_pos(pFld);
int full = full_field(pFld);
if(pFld->iScrPos > p) {
--pFld->iFldPos;
--pFld->iScrPos;
if(pFld->iScrPos > p && EDITEDFIELD(pFld->fldScr.type)) {
while(pFld->iScrPos > p) {
if (DECIMALPOINT && !full) break;
cWk = pFld->caScr[pFld->iScrPos];
if((cWk != '.')
&& (cWk != ',')
&& (cWk != '/')
&& (cWk != '-'))
break;
--pFld->iScrPos;
}
}
return 1;
}
return 0;
}
static int move_cursor_right(struct ScrFld *pFld) {
char cWk;
int full = full_field(pFld);
int l = last_pos(pFld);
int f = first_pos(pFld);
if (pFld->iScrPos < l) {
++pFld->iScrPos;
++pFld->iFldPos;
if (EDITEDFIELD(pFld->fldScr.type)) {
while(pFld->iScrPos < l) {
if (DECIMALPOINT && !full) break;
cWk = pFld->caScr[pFld->iScrPos];
if((cWk != '.')
&& (cWk != ',')
&& (cWk != '/')
&& (cWk != '-'))
break;
++pFld->iScrPos;
}
}
if (pFld->iScrPos < f)
pFld->iScrPos = f;
return 1;
}
return 0;
}
/*static void shift_right(char *source, int pos, int len) {
char *p = source + pos;
len--;
memmove(p+1, p, len);
*p = ' ';
}*/
static void shift_left(char *source, int pos, int len) {
char *p = source + pos;
len--;
memcpy(p, p+1, len);
*(p+len) = ' ';
}
static void calculate_charcount(struct ScrFld *pFld) {
int j, k, l;
char c;
if (!NUMERICFIELD(pFld->fldScr.type)) {
k = pFld->fldWk.len;
j = pFld->iScrPos;
while (--k > j && pFld->caWk[k] == ' ');
if (k >= pFld->charCount)
pFld->charCount = k + 1;
}
else if DISPLAYFIELD(pFld->fldScr.type){
j = -1;
k = pFld->fldWk.len;
while (++j < k && pFld->caWk[j] == '0');
pFld->charCount = k- j;
}
else { /* edited */
k = pFld->fldScr.len;
j = -1;
l = 0;
while (++j < k) {
c = pFld->caScr[j];
if (c >= '0' && c <= '9') l++;
pFld->charCount = l;
}
}
}
static int createdRoomToField; /* true if you need shift the field
to alocate space to a digit */
static void display_field(struct ScrFld *pFld) {
int j, k;
tcob_move(&pFld->fldScr, pFld->caScr, &pFld->fldWk, pFld->caWk);
tcob_move(&pFld->fldWk, pFld->caWk, &pFld->fldScr, pFld->caScr);
calculate_charcount(pFld);
createdRoomToField = 0;
/* RP -- we never get a DISPLAYFIELD here, as it is being faked as EDITED!! */
if (DISPLAYFIELD(pFld->fldScr.type)) {
j = -1;
k = pFld->fldWk.len;
while (++j < k && pFld->caScr[j] == '0')
pFld->caScr[j] = ' ';
if (pFld->charCount < pFld->fldWk.len) { /* we need room to the cursor */
shift_left(pFld->caScr, 0, pFld->fldScr.len);
createdRoomToField = 1;
}
}
else
if (EDITEDFIELD(pFld->fldScr.type)
&& !HASDECIMALPOINT
&& !HASSIGN
&& pFld->charCount < pFld->fldWk.len) { /* we need room to the cursor */
shift_left(pFld->caScr, 0, pFld->fldScr.len);
createdRoomToField = 1;
}
_DisplayForAccept(pFld);
}
static void remove_char(struct ScrFld *pFld) {
if (NUMERICFIELD(pFld->fldScr.type)) {
pFld->caScr[pFld->iScrPos] = ' ';
display_field(pFld);
if (!createdRoomToField || pFld->iScrPos < first_pos(pFld))
move_cursor_right(pFld);
}
else {
shift_left(pFld->caScr, pFld->iScrPos, (pFld->fldScr.len - pFld->iScrPos));
display_field(pFld);
}
}
static void process_special_char(struct ScrFld *pFld, int iKey) {
int j;
if (iKey == CDECIMALPOINT) {
if (pFld->decimalPointPosition < 0) {
beep();
return;
}
pFld->iScrPos = pFld->decimalPointPosition + 1;
return;
}
if (iKey == CTHOUSANDSEPARATOR) {
j = pFld->iScrPos;
while (j < pFld->fldScr.len && pFld->caScr[j] != CTHOUSANDSEPARATOR)
j++;
j++;
if (j >= pFld->fldScr.len) {
beep();
return;
}
pFld->iScrPos = j;
return;
}
if (iKey == '-' || iKey == '+') {
if (pFld->signPosition < 0) {
beep();
return;
}
pFld->caScr[pFld->signPosition] = (char)iKey;
return;
}
}
static int fill_field(struct ScrFld *pFld, int iKey) {
int ret = 0;
int l;
int digit;
if(pFld->fldWk.type != DTYPE_ALPHANUMERIC) { // numeric input
digit = ((iKey >= '0') && (iKey <= '9'));
if (!digit &&
(iKey != '-') &&
(iKey != '+') &&
(iKey != CTHOUSANDSEPARATOR) &&
(iKey != CDECIMALPOINT)) {
beep();
iKey = 0;
}
else
if (!digit) {
process_special_char(pFld, iKey);
display_field(pFld);
iKey = 0;
}
else
if (pFld->iScrPos == pFld->signPosition) {
if (full_field(pFld)) {
beep();
iKey = 0;
}
else {
shift_left(pFld->caScr, 0, pFld->iScrPos);
}
}
}
if ( iKey ) {
int k;
/* upper & lower */
if (pFld->iAttributes & SCR_UPPER)
iKey=toupper(iKey);
if (pFld->iAttributes & SCR_LOWER)
iKey=tolower(iKey);
k = pFld->iScrPos;
if (DECIMALPOINT) {
shift_left(pFld->caScr, 0, pFld->decimalPointPosition);
k--;
}
pFld->caScr[k] = (char)iKey;
l = pFld->charCount;
display_field(pFld);
k = full_field(pFld);
if (pFld->charCount < l)
move_cursor_first(pFld);
else
if (!DECIMALPOINT || k)
ret = move_cursor_right(pFld);
ret = (pFld->charCount == pFld->fldWk.len) &&
(pFld->iScrPos == pFld->fldScr.len - 1) && !ret;
}
return ret;
}
/* compute offset in screen field from digit position
pix -- the expanded picture for the screen field
pos -- position in the digits array
(something with pic like 9(n)V9(m))
*/
int scr_pos(char *pix, int pos) {
int n=0;
while (1) {
if (strchr("9ZXA",*(pix+n))) {
if (!pos) break;
pos--;
}
n++;
}
return n;
}
/* make sure no positions in the field are nonsense */
void fixField( int len, char *str, char *pix, char hasSign ) {
int found=0;
char *s=str;
if (hasSign) {
if (*s != '-' && *s != '+')
*s='+';
s++;
len--;
}
while (len) {
switch (*pix) {
case '9':
if (!isdigit(*s)) *s='0';
break;
case 'Z':
if (found) {
if (!isdigit(*s))
*s='0';
} else {
if (!isdigit(*s))
*s=' ';
else
found=1;
}
break;
case 'X':
case 'A':
if (((unsigned)*s) > 0x7f || ((unsigned)*s) < 0x20) {
*s = ' ';
}
break;
default:
pix++;
continue;
}
s++;
pix++;
len--;
}
}
/* check if a number has all digits filled */
int filledNum( char *s, char *pic ) {
while (*pic != '9' && *pic != 'Z') {
s++;
pic += 2;
}
return ((*s >= '1') && (*s <= '9'));
}
/* accept display (numeric) field */
int tcob_scr_accept_number(struct ScrFld *pFld,int *status){
int j, k, iKey,action,pos;
int maxpos,dpos,dp=0;
int blank=0,moved=0,hasz=0,is9edited=0,isZNum=0,atdp=0,hs=0;
char *pix;
char *s;
int tmppos,scr_corr,chk_ov=0;
int insmode=0;
/* if the accepted field is a refmod, don't auto-clean */
if (pFld->iAttributes & SCR_IS_REFMOD)
moved++;
//if (pFld->fldTo->type == DTYPE_EDITED) {
if (pFld->fldScr.type == DTYPE_EDITED) {
isZNum = tcob_isZNum(pFld->fldScr.pic);
if (!isZNum) {
if (tcob_hasZ(pFld->fldScr.pic))
hasz++;
else
is9edited++;
}
}
pix=tcob_picExpand( &(pFld->fldScr) );
s=pFld->caWk;
maxpos=pFld->fldWk.len-1;
dpos=pFld->fldWk.len-pFld->fldWk.decimals;
dp=pFld->fldWk.decimals;
if (*(pFld->fldWk.pic) == 'S') {
hs=1;
s++;
dpos--;
maxpos--;
}
/* Correct the discrepancy between the Wk field size
and the requested data field (why in the earth it is like this?!).
Anyway, we must align fields by the decimal point.*/
scr_corr = tcob_picEditedCompLength(&(pFld->fldScr))-pFld->fldWk.len+hs;
//scr_corr = 0;
tcob_move(&pFld->fldScr, pFld->caScr, &pFld->fldWk, pFld->caWk);
fixField(pFld->fldWk.len,pFld->caWk,pix,hs);
pos = 0;
if (hasz && !tcob_autocleanall()) {
moved++;
} else {
if (!is9edited) {
while (pos < maxpos && pos < (dpos-1)
&& (*(s+pos) == '0' || *(s+pos) == ' ')) pos++;
} else {
while (pos < maxpos && pos < (dpos-1)
&& (*(s+pos) == ' ')) pos++;
}
if (isZNum && pos==(dpos-1) && dp)
atdp=1;
}
while(1) {
tcob_move(&pFld->fldWk, pFld->caWk, &pFld->fldScr, pFld->caScr);
if (chk_ov) {
chk_ov=0;
if (*pFld->caScr != '0' && *pFld->caScr != ' ') {
pos++;
atdp=0;
}
}
tmppos=scr_pos(pix,pos+scr_corr);
if (blank && *(pFld->caScr+tmppos) == '0') {
*(pFld->caScr+tmppos)=' ';
}
_DisplayForAccept(pFld);
if (atdp) tmppos++;
tcob_scr_setyx(pFld->iLine, pFld->iCol + tmppos);
refresh();
iKey = getch();
if(iKey == 8) // walter
iKey = 0x107;
*status=0;
if ((iKey >= '0') && (iKey <= '9')) {
blank=0;
if (!moved) {
if (hs) *(pFld->caWk)='+';
memset(s,'0',pFld->fldWk.len);
if (!is9edited) {
if (!dp)
pos = maxpos;
else
pos = (dpos?dpos-1:dpos);
} else {
pos = 0;
}
moved=1;
}
if (!dp) {
/* integer numbers */
if (pos == maxpos &&
pos && (*s == '0' || *s == ' ')) {
*(s+pos) = iKey;
if (!is9edited) {
memmove(s,s+1,pos);
*(s+pos) = '0';
blank=1;
} else if (pFld->iAttributes & SCR_AUTO) {
return EDIT_DOWN_FIELD;
}
} else {
if (insmode) {
if (!hasz) {
memmove(s+pos+1,s+pos,maxpos-pos);
*(s+pos) = iKey;
} else {
if (pos) {
memmove(s,s+1,pos);
*(s+pos-1) = iKey;
}
}
if (pos == maxpos && (pFld->iAttributes & SCR_AUTO)) {
return EDIT_DOWN_FIELD;
}
} else {
*(s+pos) = iKey;
if (pos < maxpos) {
pos++;
} else if (pFld->iAttributes & SCR_AUTO) {
return EDIT_DOWN_FIELD;
}
}
}
} else {
/* numbers with fractional contents -- insert mode */
if (insmode || atdp) {
//if (pos && pos < dpos) {
if (pos < dpos) {
if (atdp) {
/*if (*s == '0') {*/
if (*pFld->caScr == '0' ||
*pFld->caScr == ' ') {
memmove(s,s+1,pos+1);
*(s+pos) = iKey;
chk_ov=1;
/*if (*s!='0') {
pos++;
atdp=0;
}*/
} else {
atdp=0;
if (pos < maxpos) {
pos++;
} else if (pFld->iAttributes & SCR_AUTO) {
return EDIT_DOWN_FIELD;
}
}
} else {
if (isZNum) {
if (pos) {
memmove(s,s+1,pos);
*(s+pos-1) = iKey;
}
} else {
memmove(s,s+1,pos);
*(s+pos-1) = iKey;
}
}
} else if (pos >= dpos) {
if (pos < maxpos) {
memmove(s+pos+1,s+pos,maxpos-dpos);
}
*(s+pos) = iKey;
if (pos < maxpos) {
pos++;
} else if (pFld->iAttributes & SCR_AUTO) {
return EDIT_DOWN_FIELD;
}
}
/* fractional numbers -- replace mode */
} else {
if (atdp && *s == '0') {
continue;
}
*(s+pos) = iKey;
if (isZNum) {
atdp=0;
if (pos < maxpos) {
if (pos == (dpos-1)) {
if (*s!='0') {
pos++;
atdp=0;
} else {
atdp = 1;
}
} else {
pos++;
}
}
} else {
if (pos < maxpos) {
pos++;
} else if (pFld->iAttributes & SCR_AUTO) {
return EDIT_DOWN_FIELD;
}
}
}
}
} else if (iKey == '+') {
if (hs) {
*(pFld->caWk)='+';
moved=1;
}
} else if (iKey == '-') {
if (hs) {
*(pFld->caWk)='-';
moved=1;
}
} else { // non data key pressed
action = tcob_scr_action_for_key(iKey,status);
switch(action) {
case EDIT_LEFT: /* move cursor to left */
if (isZNum) {
if (atdp) {
atdp=0;
} else if (pos+scr_corr) {
pos--;
if (pos==(dpos-1))
atdp=1;
}
} else {
if (!dp && blank && pos==maxpos && *(s+pos) == '0') {
memmove(s+1,s,pos);
*s='0';
} else if (pos+scr_corr) {
pos--;
}
}
blank=0;
moved=1;
break;
case EDIT_RIGHT: /* move cursor to right */
blank=0;
if (isZNum) {
if (atdp) {
atdp=0;
if (pos < maxpos)
pos++;
} else {
if (pos==(dpos-1)) {
atdp=1;
} else {
if (pos < maxpos)
pos++;
}
}
} else {
if (!is9edited && !dp && pos==maxpos &&
(*s == '0' || *s == ' ')) {
memmove(s,s+1,pos);
*(s+pos) = '0';
blank=1;
} else if (pos < maxpos) {
pos++;
}
}
moved=1;
break;
case EDIT_FIRST:
blank=0;
pos=0;
while (*(pFld->caScr+pos) == ' ') pos++;
break;
case EDIT_LAST:
blank=0;
pos = maxpos;
break;
case EDIT_BACKSPACE:
if (!insmode) {
if (pos && (pos < dpos || pos > dpos)) {
if (pos != (dpos-1)) {
pos--;
*(s+pos)='0';
} else {
if (blank) {
memmove(s+1,s,pos-1);
*s='0';
} else {
if (atdp) {
memmove(s+1,s,pos);
*s='0';
} else {
*(s+pos-1)='0';
pos--;
}
}
}
} else {
if (pos) {
pos--;
*(s+pos)='0';
}
}
} else {
if ((dp && pos < dpos) || !dp) {
if (pos+scr_corr) {
if (atdp) {
memmove(s+1,s,pos);
*s='0';
} else if (pos-1) {
memmove(s+1,s,pos-1);
*s='0';
}
}
} else {
if (pos > dpos && (pos+scr_corr)) {
if (insmode) {
memmove(s+pos-1,s+pos,maxpos-pos+1);
*(s+maxpos)='0';
} else {
*(s+pos-1)='0';
pos--;
}
}
}
}
break;
case EDIT_DELETE:
if (blank && pos == maxpos) {
continue;
}
blank=0;
if (pos < dpos) {
if (pos+scr_corr) {
memmove(s+1,s,pos);
*(s+scr_corr) = '0';
if (pos < maxpos)
pos++;
}
} else if (dp) {
memmove(s+pos,s+pos+1,maxpos-pos);
*(s+maxpos)='0';
}
break;
case EDIT_INSERT: /* toggle insert mode */
if (insmode)
insmode=0;
else
insmode=1;
moved=1;
break;
case EDIT_CLEAR: /* clear the current field */
blank=0;
memset(pFld->caScr,' ',pFld->fldScr.len);
break;
case EDIT_CLEAR_TOEND: /* Clear to the end of field */
blank=0;
j = pFld->fldScr.len - pFld->iFldPos - 1;
k = pFld->iFldPos;
memset(pFld->caScr + k,' ',j);
break;
case EDIT_DECIMALPT:
if (dp && pos < dpos && !atdp) {
memmove(s+dpos-pos,s,pos);
memset(s,'0',dpos-pos);
pos=dpos;
}
if (atdp)
pos=dpos;
atdp=0;
moved=1;
break;
default:
tcob_move(&pFld->fldScr, pFld->caScr,
&pFld->fldWk, pFld->caWk);
free(pix);
return action;
}
}
}
free(pix);
return EDIT_TERMINATE;
}
/* verify if character is valid against picture mask char */
static int valid_char(int c, int picc) {
switch (picc) {
case '9':
case 'Z':
if (isdigit(c))
return 1;
else
break;
case 'A':
if (isalpha(c))
return 1;
else
break;
case 'X':
if (c <= 0xff && c >= 0x20)
return 1;
else
break;
}
return 0;
}
/* clean a field following its picture mask */
static void clean_field(char *s, char *pix) {
while (*pix) {
if (*pix == '9') {
*s++ = '0';
} else if (*pix == 'A' || *pix == 'X' || *pix == 'Z') {
*s++ = ' ';
}
pix++;
}
}
int tcob_scr_accept_edited(struct ScrFld *pFld,int *status){
int j, k, iKey,action,pos;
int maxpos=0;
int moved=0;
char *pix;
char *s;
int tmppos;
int insmode=0;
insmode=0;
if (pFld->iAttributes & SCR_IS_REFMOD) {
pix=tcob_picExpand( &(pFld->fldWk) );
} else {
pix=tcob_picExpand( &(pFld->fldScr) );
}
s=pFld->caWk;
maxpos=pFld->fldWk.len-1;
/* if the accepted field is a refmod, don't auto-clean */
if (pFld->iAttributes & SCR_IS_REFMOD)
moved++;
pos = 0;
if (pFld->fldScr.type != 'X' && pFld->fldScr.type != 'D') {
while (pos < maxpos && *(s+pos) == ' ') pos++;
} else {
if (!tcob_autocleanall())
moved++;
}
while(1) {
tcob_move(&pFld->fldWk, pFld->caWk, &pFld->fldScr, pFld->caScr);
tmppos=scr_pos(pix,pos);
_DisplayForAccept(pFld);
tcob_scr_setyx(pFld->iLine, pFld->iCol + tmppos);
refresh();
iKey = getch();
if(iKey == 8) // walter
iKey = 0x107;
//walter garrote
/* upper & lower */
if (pFld->iAttributes & SCR_UPPER)
iKey=toupper(iKey);
if (pFld->iAttributes & SCR_LOWER)
iKey=tolower(iKey);
//fim
*status=0;
if (valid_char(iKey,*(pix+scr_pos(pix,pos)))) {
if (!moved) {
clean_field(s,pix);
//memset(s,' ',pFld->fldWk.len);
pos = 0;
moved=1;
if (pFld->fldWk.type != 'X') {
while (pos < maxpos && *(s+pos) == ' ') pos++;
}
}
if (insmode) {
if (pos < maxpos)
memmove(s+pos+1,s+pos,maxpos-pos);
*(s+pos) = iKey;
if (pos < maxpos) {
pos++;
} else if (pFld->iAttributes & SCR_AUTO) {
return EDIT_DOWN_FIELD;
}
} else {
*(s+pos) = iKey;
if (pos < maxpos) {
pos++;
} else if ((pFld->iAttributes & SCR_AUTO) &&
(*s != ' ')) {
return EDIT_DOWN_FIELD;
} else if (*s == ' ') {
memmove(s,s+1,maxpos);
if (pFld->fldWk.type == '9') // walter estava com =
*(s+maxpos) = '0';
else
*(s+maxpos) = ' ';
}
}
} else if (iKey > 0x7f || iKey < 0x20) { // non data key pressed
action = tcob_scr_action_for_key(iKey,status);
switch(action) {
case EDIT_LEFT: /* move cursor to left */
if (pos) {
pos--;
}
moved=1;
break;
case EDIT_RIGHT: /* move cursor to right */
if (pos < maxpos) {
pos++;
}
moved=1;
break;
case EDIT_FIRST:
pos=0;
while (*(pFld->caScr+pos) == ' ') pos++;
break;
case EDIT_LAST:
pos = maxpos;
break;
case EDIT_BACKSPACE:
if (!insmode) {
if (*(pix+scr_pos(pix,pos)) == '9')
*(s+pos)='0';
else
*(s+pos)=' ';
if (pos) { // walter inverti
pos--;
}
} else {
if (pos) {
memmove(s+pos-1,s+pos,maxpos-pos+1);
if (*(pix+scr_pos(pix,maxpos)) == '9')
*(s+maxpos)='0';
else
*(s+maxpos)=' ';
pos--;
}
}
break;
case EDIT_DELETE:
if (pos < maxpos) {
/*memmove(s+1,s,pos);
if (*(pix+scr_pos(pix,0)) == '9')
*(s) = '0';
else
*(s) = ' ';
pos++;*/
memmove(s+pos,s+pos+1,maxpos-pos);
*(s+maxpos) = ' ';
} else {
if (*(pix+scr_pos(pix,maxpos)) == '9')
*(s+maxpos) = '0';
else
*(s+maxpos) = ' ';
}
break;
case EDIT_INSERT: /* toggle insert mode */
if (insmode)
insmode=0;
else
insmode=1;
moved=1;
break;
case EDIT_CLEAR: /* clear the current field */
memset(pFld->caScr,' ',pFld->fldScr.len);
break;
case EDIT_CLEAR_TOEND: /* Clear to the end of field */
j = pFld->fldScr.len - pFld->iFldPos - 1;
k = pFld->iFldPos;
memset(pFld->caScr + k,' ',j);
break;
default:
free(pix);
return action;
}
}
}
free(pix);
return EDIT_TERMINATE;
}
//
// Accept one field
//
//
//
int tcob_scr_accept_field(struct ScrFld *pFld,int *status){
int j, k, iKey,bAtEnd,action;
//char type=pFld->fldScr.type;
if (pFld->fldTo->type == DTYPE_DISPLAY ||
(pFld->fldTo->type == DTYPE_EDITED &&
tcob_isNumEdit(pFld->fldScr.pic))) {
return (tcob_scr_accept_number(pFld,status));
}
//if (pFld->fldTo->type == DTYPE_EDITED) {
return (tcob_scr_accept_edited(pFld,status));
//}
pFld->charCount = -1;
display_field(pFld);
//_DisplayForAccept(pFld);
move_cursor_first(pFld);
set_atributes(pFld);
while(1) {
tcob_scr_setyx(pFld->iLine, pFld->iCol + pFld->iScrPos);
refresh();
iKey = getch();
*status=0;
if(!(iKey & KEY_CODE_YES) && !(iKey < ' ')) { // data key pressed
bAtEnd = fill_field(pFld, iKey);
if((bAtEnd) && (pFld->iAttributes & SCR_AUTO)) {
return EDIT_DOWN_FIELD;
}
} else { // non data key pressed
action = tcob_scr_action_for_key(iKey,status);
switch(action) {
case EDIT_LEFT: /* move cursor to left */
if (!(move_cursor_left(pFld))) {
beep();
}
break;
case EDIT_RIGHT: /* move cursor to right */
if (!(move_cursor_right(pFld))) {
beep();
}
break;
case EDIT_FIRST:
move_cursor_first(pFld);
break;
case EDIT_LAST:
move_cursor_last(pFld);
break;
case EDIT_BACKSPACE:
if(pFld->iScrPos > first_pos(pFld)) {
pFld->iScrPos--;
if (!EDITEDFIELD(pFld->fldScr.type))
remove_char(pFld);
else {
int k = pFld->iScrPos;
while (!isdigit(pFld->caScr[k]) && --k >= 0);
if (k >= 0) {
pFld->iScrPos = k;
remove_char(pFld);
}
else {
beep();
}
}
} else {
beep();
}
break;
case EDIT_DELETE: /* delete character under cursor */
if (pFld->iScrPos != pFld->signPosition)
remove_char(pFld);
else beep();
break;
case EDIT_INSERT: /* insert a character before cursor */
j = pFld->fldScr.len - pFld->iFldPos - 1;
k = pFld->iFldPos;
memmove(pFld->caWk+k+1, pFld->caWk+k, j);
pFld->caWk[k] = ' ';
_DisplayForAccept(pFld);
break;
case EDIT_CLEAR: /* clear the current field */
memset(pFld->caWk,' ',pFld->fldWk.len);
_DisplayForAccept(pFld);
break;
case EDIT_CLEAR_TOEND: /* Clear to the end of field */
j = pFld->fldWk.len - pFld->iFldPos - 1;
k = pFld->iFldPos;
memset(pFld->caWk + k,' ',j);
_DisplayForAccept(pFld);
break;
default: // replace character under cursor
return action;
}
}
}
return EDIT_TERMINATE;
}
//
// Accept all the fields until finish of function key pressed
// Return the value for the screen_status
//
int tcob_scr_accept(struct ScrFld *fields) {
int key_status,action;
struct ScrFld *pFld;
struct ScrFld *pFirst=NULL;
struct ScrFld *pLast=NULL;
struct ScrFld *pPrev=NULL;
char *pix,*s,*d;
int i;
for (pFld=fields; pFld; pFld=pFld->pNext) {
if(pFld->fldTo) { // cursor stop
if(!pFirst)
pFirst = pFld;
pLast = pFld;
}
}
if(!pFirst)
return 0;
for(pFld=pFirst;pFld;) { //main accept loop
if(pFld->fldTo) {
/* this don't work with all fields types:
prepare_input_field(pFld);*/
if (pFld->fldTo->type == '9') {
memmove(pFld->caWk,pFld->caScr,pFld->fldScr.len);
//pFld->fldWk.len = pFld->fldTo->len;
} else {
/* make our work copy have the significant characters */
if (pFld->iAttributes & SCR_IS_REFMOD) {
pix=tcob_picExpand( &(pFld->fldWk) );
} else {
pix=tcob_picExpand( &(pFld->fldScr) );
}
d = pFld->caWk;
s = pFld->caScr;
for (i=0;i<pFld->fldScr.len;i++) {
if (strchr("9ZXA",*(pix+i))) {
*d++ = *s++;
} else {
s++;
}
}
}
/*tcob_move(&pFld->fldWk, pFld->caWk, &pFld->fldScr,
pFld->caScr);*/
}
tcob_scr_display_for_input(pFld);
if (pFld != pPrev) { // if new field, put the cursor on position
// and display the last accepted
if (pPrev)
tcob_scr_display_field(pPrev);
}
pPrev = pFld;
action = tcob_scr_accept_field(pFld,&key_status);
tcob_move(&pFld->fldWk, pFld->caWk, &pFld->fldScr, pFld->caScr);
switch(action) {
case EDIT_FIRST_FIELD: /* move to first input field */
pFld = pFirst;
break;
case EDIT_LAST_FIELD: /* move to last input field */
pFld = pLast;
break;
case EDIT_DOWN_FIELD: /* move cursor to next input field */
/* find next input field in chain */
pFld = get_next_input_field(pFld);
break;
case EDIT_UP_FIELD: /* move cursor to prev input field */
/* find prev input field in chain */
pFld = get_prev_input_field(pFld);
break;
case EDIT_NEXT_FIELD: /* move cursor to next input field */
pFld = get_next_input_field(pFld);
if(!pFld) /* if last field rotate */
pFld = pFirst;
break;
case EDIT_PREV_FIELD: /* move cursor to prev input field */
/* find prev input field in chain */
pFld = get_prev_input_field(pFld);
if(!pFld) /* if last field rotate */
pFld = pLast;
break;
case EDIT_TERMINATE: /* we're done */
pFld = NULL;
break;
} // switch
} // main loop
if(pPrev)
tcob_scr_display_field(pPrev); // Display last accepted field
refresh();
return key_status;
}
/* scr_curses.c */