545 lines
16 KiB
C
545 lines
16 KiB
C
//
|
|
// Copyright (C) 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 -- Pictures |
|
|
| See each function's comments for more detail. |
|
|
| Independent of compressed PIC implementation: |
|
|
| tcob_picExpand() - Returns an expanded version of the PIC string |
|
|
| tcob_picCompLength() - Numeric character count |
|
|
| tcob_picEditedCompLength() - Numeric-edited character count |
|
|
| tcob_picEditedCompDecimals() - Decimal numeric-edited characters count |
|
|
| Dependent on compressed PIC implementation: |
|
|
| tcob_picElemVal() - Retrieve character value from a specified element |
|
|
| tcob_picElemLen() - Retrieve character count from a specified element |
|
|
| tcob_picReqLen() - Determine size to allocate for a new compressed PIC |
|
|
| tcob_picCreate() - Start a new compressed PIC string |
|
|
| tcob_picAppend() - Continue a compressed PIC string |
|
|
| |
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
#include "htcoblib.h"
|
|
#include "screenio.h"
|
|
|
|
extern int bDecimalComma;
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picExpand |
|
|
| expand a picture returning a malloc'ed string |
|
|
| from: "XAYBZC" (where X, Y, Z are picture characters and |
|
|
| A, B, C are binary counts for each character) |
|
|
| to: "XXXXYYYZZZZZ" |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
char * tcob_picExpand( struct fld_desc *f ) {
|
|
char *result, c;
|
|
unsigned int i, t, tot;
|
|
|
|
for (i=0, tot=0; tcob_picElemVal(f->pic,i); i++)
|
|
tot += tcob_picElemLen(f->pic,i);
|
|
result = malloc(tot+1);
|
|
for (i=0, tot=0; (c=tcob_picElemVal(f->pic,i)); i++) {
|
|
t = tcob_picElemLen(f->pic,i);
|
|
memset (&result[tot], c, t);
|
|
tot += t;
|
|
}
|
|
result[tot] = '\0';
|
|
/*
|
|
#ifdef PICTURE_TESTING
|
|
printf("tcob_picexpand: %s\n", result);
|
|
free(result);
|
|
return NULL;
|
|
#else
|
|
return result;
|
|
#endif
|
|
*/
|
|
return result;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picCompLength |
|
|
| For numeric types, determine the total number of stored digits. |
|
|
| Includes 9's. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
unsigned int tcob_picCompLength( struct fld_desc *f ) {
|
|
unsigned int len=0, i;
|
|
char c;
|
|
|
|
for (i=0; (c=tcob_picElemVal(f->pic,i)); i++) {
|
|
if (c == '9')
|
|
len += tcob_picElemLen(f->pic,i);
|
|
}
|
|
return len;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picEditedCompLength |
|
|
| For the numeric-edited type, determine the total number of digits |
|
|
| available. Includes 9's, Z's,*'s, and multiples of +, -, and the |
|
|
| currency sign. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
unsigned int tcob_picEditedCompLength( struct fld_desc *f ) {
|
|
unsigned int len=0, i;
|
|
unsigned int bSeenPlus=0, bSeenMinus=0, bSeenCurrency=0;
|
|
char c;
|
|
extern char cCurrencySymbol;
|
|
|
|
for (i=0; (c=tcob_picElemVal(f->pic,i)); i++) {
|
|
unsigned int ilen = tcob_picElemLen(f->pic,i);
|
|
if (c == '9' || c == 'Z' || c == '*' ||
|
|
(bSeenPlus && (c == '+')) ||
|
|
(bSeenMinus && (c == '-')) ||
|
|
(bSeenCurrency && (c == cCurrencySymbol)) )
|
|
len += ilen;
|
|
|
|
if (!bSeenPlus && (c == '+')) {
|
|
bSeenPlus = 1;
|
|
len += ilen - 1;
|
|
} else if (!bSeenMinus && (c == '-')) {
|
|
bSeenMinus = 1;
|
|
len += ilen - 1;
|
|
} else if (!bSeenCurrency && (c == cCurrencySymbol)) {
|
|
bSeenCurrency = 1;
|
|
len += ilen - 1;
|
|
}
|
|
}
|
|
return len;
|
|
}
|
|
|
|
unsigned int tcob_picTotalLen( char *pic ) {
|
|
int len=0;
|
|
while (*pic) {
|
|
len += *(pic+1);
|
|
pic+=2;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picSignPosition |
|
|
| For the numeric- type, determine the position of the sign |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
unsigned int tcob_picSignPosition( struct fld_desc *f ) {
|
|
unsigned int len=0, i;
|
|
char c;
|
|
int d = DISPLAYFIELD(f->type);
|
|
|
|
for (i=0; (c=tcob_picElemVal(f->pic,i)); i++) {
|
|
unsigned int ilen = tcob_picElemLen(f->pic,i);
|
|
len += ilen;
|
|
if ((c == '+' || c == '-') || (c == 'S' && d && i == 0)) {
|
|
len -= ilen;
|
|
return len;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picDecimalPointPosition |
|
|
| For the numeric- type, determine the position of the decimal point |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
unsigned int tcob_picDecimalPointPosition( struct fld_desc *f ) {
|
|
unsigned int len=0, i;
|
|
extern int bDecimalComma;
|
|
|
|
char c, cDecimal = (bDecimalComma) ? ',' : '.';
|
|
|
|
for (i=0; (c=tcob_picElemVal(f->pic,i)); i++) {
|
|
unsigned int ilen = tcob_picElemLen(f->pic,i);
|
|
len += ilen;
|
|
if (c == cDecimal) {
|
|
len -= ilen;
|
|
return len;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picEditedCompDecimals |
|
|
| For the numeric-edited type, determine the total number of digits |
|
|
| available after the decimal point. Includes 9's, Z's,*'s, and |
|
|
| multiples of +, -, and the currency sign. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
unsigned int tcob_picEditedCompDecimals( struct fld_desc *f ) {
|
|
unsigned int len=0, i;
|
|
int bSeenDecimal=0, bSeenPlus=0, bSeenMinus=0, bSeenCurrency=0;
|
|
extern int bDecimalComma;
|
|
extern char cCurrencySymbol;
|
|
char c, cDecimal = (bDecimalComma) ? ',' : '.';
|
|
|
|
for (i=0; (c=tcob_picElemVal(f->pic,i)); i++) {
|
|
unsigned int ilen = tcob_picElemLen(f->pic,i);
|
|
if (bSeenDecimal && // Must find the decimal point first
|
|
(c == '9' || c == 'Z' || c == '*' ||
|
|
(bSeenPlus && (c == '+')) ||
|
|
(bSeenMinus && (c == '-')) ||
|
|
(bSeenCurrency && (c == cCurrencySymbol)) ) )
|
|
len += ilen;
|
|
if (!bSeenDecimal && (c == cDecimal)) {
|
|
bSeenDecimal = 1;
|
|
} else if (!bSeenPlus && (c == '+')) {
|
|
bSeenPlus = 1;
|
|
if (bSeenDecimal)
|
|
len += ilen - 1;
|
|
} else if (!bSeenMinus && (c == '-')) {
|
|
bSeenMinus = 1;
|
|
if (bSeenDecimal)
|
|
len += ilen - 1;
|
|
} else if (!bSeenCurrency && (c == cCurrencySymbol)) {
|
|
bSeenCurrency = 1;
|
|
if (bSeenDecimal)
|
|
len += ilen - 1;
|
|
}
|
|
}
|
|
return len;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picElemLen & tcob_picElemVal |
|
|
| Determine the length or value of element i in array p. |
|
|
| Each element is composed of an 8-bit character and an 8-bit length. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
unsigned int tcob_picElemLen(char *p, unsigned int i) {
|
|
return ( (unsigned int)(((unsigned short *)p)[i] >> 8) );
|
|
}
|
|
|
|
char tcob_picElemVal(char *p, unsigned int i) {
|
|
return ( ((unsigned short *)p)[i] & 0x0ff );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picReqLen |
|
|
| Determine number of bytes to request for holding a compressed PIC |
|
|
| string of i elements. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
unsigned int tcob_picReqLen(unsigned int i) {
|
|
/* Currently using a 1-byte value and a 1-byte length for each
|
|
* element, plus a 1-byte NULL to indicate the end */
|
|
return ((i*2)+1);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picCreate |
|
|
| Create a new PIC string and place in p. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
char *tcob_picCreate(char *p, unsigned int len, ...) {
|
|
char pc;
|
|
unsigned int i=0, ilen;
|
|
va_list args;
|
|
|
|
va_start(args, len);
|
|
while ((pc=va_arg(args,int))) {
|
|
for (ilen=va_arg(args, int); ilen>255; ilen-=255) {
|
|
if (i+1>=len)
|
|
break;
|
|
p[i] = pc;
|
|
p[i+1] = 255;
|
|
ilen -= 255;
|
|
i += 2;
|
|
}
|
|
if (i+1>=len)
|
|
break;
|
|
p[i] = pc;
|
|
p[i+1] = ilen;
|
|
i += 2;
|
|
}
|
|
if (i<len)
|
|
p[i] = '\0';
|
|
else if (i>1)
|
|
p[i-2] = '\0';
|
|
else if (len==1)
|
|
p[0] = '\0';
|
|
va_end(args);
|
|
return p;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picAppend |
|
|
| Continue the PIC string found in p. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
char *tcob_picAppend(char *p, unsigned int len, ...) {
|
|
char pc;
|
|
unsigned int i, ilen;
|
|
va_list args;
|
|
|
|
for (i=0; p[i]; i+=2) ;
|
|
|
|
va_start(args, len);
|
|
while ((pc=va_arg(args,int))) {
|
|
for (ilen=va_arg(args, int); ilen>255; ilen-=255) {
|
|
if (i+1>=len)
|
|
break;
|
|
p[i] = pc;
|
|
p[i+1] = 255;
|
|
ilen -= 255;
|
|
i += 2;
|
|
}
|
|
if (i+1>=len)
|
|
break;
|
|
p[i] = pc;
|
|
p[i+1] = ilen;
|
|
i += 2;
|
|
}
|
|
if (i<len)
|
|
p[i] = '\0';
|
|
else if (i>1)
|
|
p[i-2] = '\0';
|
|
else if (len==1)
|
|
p[0] = '\0';
|
|
va_end(args);
|
|
return p;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*\
|
|
| |
|
|
| tcob_picChangeChar |
|
|
| change the PIC string char in p. |
|
|
| |
|
|
\*------------------------------------------------------------------------*/
|
|
|
|
void tcob_picChangeChar(char *p, int i, char c) {
|
|
p[i*2]= c;
|
|
}
|
|
|
|
/*-----------------------------------------------------------
|
|
* Classify picture type
|
|
* receives a compressed pic pointer
|
|
* returns picture type
|
|
*/
|
|
char tcob_classifyPic( char *p ) {
|
|
int i;
|
|
char type=0;
|
|
|
|
for (i=0; p[i]; i+=2) {
|
|
switch (p[i]) {
|
|
case 'A':
|
|
if ((type != DTYPE_ALPHANUMERIC && type != DTYPE_EDITED)
|
|
|| !type)
|
|
type = DTYPE_ALPHA;
|
|
break;
|
|
case 'X':
|
|
if (type == DTYPE_DISPLAY || !type)
|
|
type = DTYPE_ALPHANUMERIC;
|
|
break;
|
|
case 'Z':
|
|
type=DTYPE_EDITED;
|
|
break;
|
|
case '9':
|
|
if (!type)
|
|
type=DTYPE_DISPLAY;
|
|
break;
|
|
case 'V':
|
|
case 'P':
|
|
case 'S':
|
|
break;
|
|
case '.':
|
|
case ',':
|
|
case '0':
|
|
case 'B':
|
|
case '/':
|
|
case '+':
|
|
case '-':
|
|
case '*':
|
|
case 'C':
|
|
case 'R':
|
|
case 'D':
|
|
type=DTYPE_EDITED;
|
|
break;
|
|
}
|
|
}
|
|
return type;
|
|
}
|
|
/*********************************************
|
|
tcob_isNumEdit
|
|
|
|
check if a picture stands for a numeric-edited item (true) or
|
|
alphanumeric-edited (false).
|
|
|
|
Standard: ISO/IEC 1989:2001 (pp.323-324)
|
|
---------------------------
|
|
13.16.38.3 General Rules
|
|
...
|
|
FORMAT 1
|
|
...
|
|
7) To define an item as alphanumeric-edited, character-string-1 shall
|
|
include:
|
|
- at least one symbol 'A' or 'X', and
|
|
- at least one of the symbols from the set 'B', '0', '/'.
|
|
|
|
**********************************************/
|
|
|
|
int tcob_isNumEdit(char *p) {
|
|
char cDecimalChar = '.';
|
|
int i,dsep=0;
|
|
int axfound=0;
|
|
int bzslfound=0;
|
|
|
|
if (bDecimalComma)
|
|
cDecimalChar = ',';
|
|
|
|
for (i=0; p[i]; i+=2) {
|
|
switch (p[i]) {
|
|
/* the standard says we must find one of those below, at least,
|
|
but for dates (pic 99/99/999) which is visibly not
|
|
numeric-edited, there is none 'A' or 'X'. So let's not
|
|
require this until someone explains me what to do here. */
|
|
case 'A':
|
|
case 'X':
|
|
axfound=1;
|
|
break;
|
|
/* don't count a 'B' after 'D' (DB) */
|
|
case 'D':
|
|
if (p[i+1]==1 && p[i+2]=='B' && p[i+3]==1) {
|
|
i+=2;
|
|
continue;
|
|
}
|
|
case '.':
|
|
case ',':
|
|
if (p[i] == cDecimalChar) {
|
|
if (dsep++) {
|
|
return 0;
|
|
}
|
|
/* make sure there are no repetitions here */
|
|
if (p[i+1] > 1) {
|
|
return 0;
|
|
}
|
|
}
|
|
continue;
|
|
case 'B':
|
|
case '0':
|
|
case '/':
|
|
bzslfound=1;
|
|
break;
|
|
}
|
|
}
|
|
if (bzslfound && axfound)
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
int tcob_isNumeric(char *p) {
|
|
int i;
|
|
|
|
for (i=0; p[i]; i+=2) {
|
|
switch (p[i]) {
|
|
case 'S': // walter 13-12-05
|
|
continue;
|
|
case '9':
|
|
continue;
|
|
case 'V':
|
|
continue;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int tcob_isZNum(char *p) {
|
|
int i;
|
|
|
|
for (i=0; p[i]; i+=2) {
|
|
switch (p[i]) {
|
|
case '-':
|
|
case ',':
|
|
case '.':
|
|
case '9':
|
|
case 'Z':
|
|
continue;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int tcob_isAlpha(char *p) {
|
|
int i;
|
|
|
|
for (i=0; p[i]; i+=2) {
|
|
switch (p[i]) {
|
|
case 'A':
|
|
case 'X':
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* check if the picture has any pic Z string */
|
|
int tcob_hasZ(char *p) {
|
|
int i;
|
|
for (i=0; p[i]; i+=2) {
|
|
switch (p[i]) {
|
|
case 'Z':
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*********************
|
|
how many significative characters (Z,X,A,9,*) there
|
|
are in the picture
|
|
**********************/
|
|
int tcob_picCharLen( unsigned char *pic ) {
|
|
int n=0;
|
|
while (*pic) {
|
|
if (strchr("9ZXA*",*pic)) {
|
|
n+=*(pic+1);
|
|
}
|
|
pic += 2;
|
|
}
|
|
return n;
|
|
}
|