home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
beehive
/
utilitys
/
chx8012b.arc
/
CHECKC.C
< prev
next >
Wrap
Text File
|
1990-07-21
|
27KB
|
909 lines
/* checkc.c -- 4th source file for check register program */
/* copyright (c) 1986 by Jim Woolley and WoolleyWare, San Jose, CA */
/* vers. 1.0, 12/85 thru 5/86
*
* vers. 1.2, 7/86
* saveclr() for CHECKS: add "Saving ... " display, avoid discarding SUMMARY
* entries, and add getw, getc, and fclose error tests
* savedat(): add fclose error test and argument TRUE if CR before display
* savedat() for CLEARS: add count of SUMMARY entries to CLR file
* help(): avoid writing '\n' after column 80 resulting in scrolling, add call
* to putquery(), and display entry number
* moved createrr(), writerr(), and baddisk() from checks.c
* added renamerr() and puterrmsg()
* integrated CLEARS using #ifdef
*/
/* this file contains:
* putcursor( i, f)
* cursorput( i, c)
* cursorto( r, c)
* putpos( i)
* puttitle()
* disheading()
* recheading( s1, s2)
* putquery()
* prompt( s)
* char putcommand( c)
* char putcntrl( c)
* char putnext()
* addmoney( m3, m1, m2, add)
* movmoney( m2, m1, credit)
* putmoney( m)
* putdate( d)
* formatd( s, n, d)
* printd( d)
* sign( i)
* char witch( c)
* iscntrl( c)
* waitesc()
* waitkey()
* done()
* saveclr()
* savedat( addcr)
* calcbbf()
* char help()
* createrr( f)
* writerr( f)
* renamerr( f1, f2)
* puterrmsg( s1, s2)
* baddisk()
* abort( s1, s2)
* aexit()
*/
#include "a:checks.h"
putcursor( i, f) /* put cursor in entry i, field f */
int i, f;
{
#ifndef CLEARS
if ( f == PAYFIELD)
Character = min( Character, strlen( Entry[ i].payee));
else Character = 0;
cursorto(( i - First + HEAD), ( Ftoc[ f] + Character));
#else
cursorto(( i - First + HEAD), Ftoc[ f]);
#endif
}
cursorput( i, c) /* put cursor in entry i, column c */
int i, c;
{
cursorto(( i - First + HEAD), c);
}
cursorto( r, c) /* put cursor at row r, column c */
int r, c; /* 0, 0 is upper-left corner */
{
int i;
if ( Printing)
putchar( '\n');
else
{
r += Linoff; /* add offset */
c += Coloff;
if ( Cb4flg)
{
i = r; /* swap */
r = c;
c = i;
}
putscr( Clead1);
putpos( r);
putscr( Clead2);
putpos( c);
putscr( Ctrail);
}
}
putpos( i) /* send cursor position i */
int i; /* ( 0 + offset) is home */
{
char *p, s[ 4];
if ( Ascur) /* if ASCII wanted */
{
strcpy(( p = s), "000"); /* template */
if ( Ascur < 3)
++p;
formatd( p, Ascur, i);
puts( p);
}
else putchar( i);
}
puttitle()
{
char f[ FNAMSIZE];
int i, length;
strcpy( f, Filename);
*( index( f, '.')) = '\0'; /* truncate at dot */
/* display 5 spaces on left, right justify f on column (COLS - 1), precede
* f with 2 spaces, then center Title in the remaining area; i.e.,
* _____<<<<<<<<<<<<<<<<<<<<<<< center Title >>>>>>>>>>>>>>>>>>>>>__A:FILENAME
*/
length = strlen( Title);
i = 5 + (( COLS - FNAMSIZE - 3) - length)/2;
length += i;
while ( i--) /* center title */
putchar( ' ');
puts( Title);
i = ( COLS - 1) - length - strlen( f);
while ( i--) /* fill title line (with Ivon) */
putchar( ' ');
puts( f);
i = HEAD - 2;
while ( i--)
putchar( '\n');
}
disheading() /* display heading for display() */
{
if ( !Printing)
{
cursorto( 0, 0);
putscr( Ivon);
}
puttitle();
#ifdef CLEARS
puts(
" Date Payee C Amount DEP <M> Balance"
);
#else
puts(
" Date Payee C Amount DEP CLR Balance"
);
#endif
putchar( '\n');
puts(
"-------- ------------------------------------------ - -------- --- --- --------"
);
if ( !Printing)
putscr( Ivoff);
}
recheading( s1, s2) /* display heading for reconcile() */
char *s1, *s2;
{
if ( !Printing)
{
clrscr();
putscr( Ivon);
}
puttitle();
#ifdef CLEARS
puts(
" Last Summary _____ <M>arked Entries _____ _______ All Entries ________"
);
putchar( '\n');
puts(
" Date C Forward Checks Deposits Summary Checks Deposits Summary"
);
#else
puts(
" Last Balance _____ Cleared Entries ______ _______ All Entries ________"
);
putchar( '\n');
puts(
" Date C Forward Checks Deposits Balance Checks Deposits Balance"
);
#endif
putchar( '\n');
puts( s1);
puts( s2);
if ( !Printing)
putscr( Ivoff);
}
putquery() /* select and display query */
{
char test, cwitch, dep;
if ( Recno > Maxentry)
{
#ifdef CLEARS
prompt( "Press ^J for help");
#else
prompt( "Press RETURN to start a new entry, or ^J for help");
#endif
return;
}
if ( isibbf( Recno)) /* if a BBF entry */
{
prompt( "Do you wish to void this entry's status as ");
puts( BBF);
puts( " (Y/N)? N");
return;
}
test = ( Field == Oldfield);
cwitch = Field;
#ifdef CLEARS
if ( test && cwitch != CLRFIELD)
return;
switch ( cwitch)
{
case CATFIELD:
prompt( "Enter category");
break;
case CLRFIELD:
prompt( "<M>ark this entry for summary/delete (Y/N)? ");
dep = Entry[ Recno].clear;
yesno: putchar( dep ? 'N' : 'Y');
break;
}
#else
if ( test && cwitch != DEPFIELD && cwitch != CLRFIELD)
return;
switch ( cwitch)
{
case MMFIELD:
prompt( "Enter month");
break;
case DDFIELD:
prompt( "Enter date");
break;
case YYFIELD:
prompt( "Enter year");
break;
case PAYFIELD:
prompt( "Enter/edit payee ( INSERT ");
puts( Inserton ? "ON )" : "OFF )");
break;
case CATFIELD:
prompt( "Enter category");
break;
case AMTFIELD:
prompt( "Enter/calculate amount");
cursorto(( HEAD - 4), ( AMTCOL - 9));
puts( "MEMORY = ");
putmoney( &Memory);
break;
case DEPFIELD:
prompt( "Is entry a deposit (Y/N)? ");
dep = Entry[ Recno].deposit;
goto yesno;
case CLRFIELD:
prompt( "Has entry cleared the bank (Y/N)? ");
dep = Entry[ Recno].clear;
yesno: putchar( dep ? 'Y' : 'N');
break;
}
#endif
return;
}
prompt( s) /* prompt for entry */
char *s;
{
int c;
cursorto(( HEAD - 4), 0);
puts( s);
clreol( c = strlen( s));
if ( !( *Eraeol)) /* if no Eraeol string */
cursorto(( HEAD - 4), c); /* return cursor */
Oldfield = -1;
}
char putcommand( c) /* display command */
char c; /* return TRUE if cursor moved */
{
switch ( c)
{
case CTRLK: case CTRLQ: case CTRLC: case CTRLR:
case CTRLB: case CTRLO: case CTRLP:
cursorto( 0, 0);
putscr( Ivon);
puts( CLRCOM);
putchar( '\r');
putcntrl( c);
putscr( Ivoff);
return ( TRUE);
default:
return ( FALSE);
}
}
char putcntrl( c) /* display control char */
char c; /* return ( c + CTRLTOA) or DEL */
{
if ( c != DEL)
{
putchar( '^');
putchar( c += CTRLTOA);
}
else puts( "DEL");
return ( c);
}
char putnext() /* display next command character */
{ /* return upper case character */
char c;
putscr( Ivon);
if ( isprint( c = getchar()))
{
putchar( c);
c = toupper( c);
}
else c = putcntrl( c);
putscr( Ivoff);
return ( c);
}
addmoney( m3, m1, m2, add) /* get m3 = m1 + m2 if add = TRUE */
struct money *m3, *m1, *m2; /* get m3 = m1 - m2 if add = FALSE */
char add;
{
int d, c, sd;
if ( add)
{
d = m1->dollar + m2->dollar;
c = m1->cent + m2->cent;
}
else
{
d = m1->dollar - m2->dollar;
c = m1->cent - m2->cent;
}
if ( d && ( sd = sign( d)) != sign( c))
{
d -= sd;
if ( sd < 0)
c -= 10000;
else c += 10000;
}
m3->dollar = d + c/10000;
m3->cent = c%10000;
}
movmoney( m2, m1, credit) /* set m2 = m1 if credit = TRUE */
struct money *m2, *m1; /* else, set m2 = abs( m1) */
char credit;
{
if ( credit)
{
m2->dollar = m1->dollar;
m2->cent = m1->cent;
}
else
{
m2->dollar = abs( m1->dollar);
m2->cent = abs( m1->cent);
}
}
putmoney( m) /* format and display money */
struct money *m;
{
char s[ 10];
int is, id, ic; /* int is assumed to be 16 bits */
struct money w;
if (( id = m->dollar) < -99 || 999 < id)
{
w.dollar = 0;
w.cent = 50; /* round-off to nearest dollar */
addmoney( &w, m, &w, ( id > 0));
id = w.dollar;
ic = w.cent;
is = 6;
strcpy( s, " 0 "); /* template */
}
else
{
ic = m->cent;
is = 3;
strcpy( s, " 0.00 "); /* template */
}
if ( id < 0 || ic < 0)
{
id = abs( id);
ic = abs( ic);
s[ 0] = '(';
s[ 8] = ')';
}
if ( id)
{
formatd( s, is, id);
s[ is] = '0'; /* fill */
}
formatd(( s + is), 2, ic/100);
if ( is == 3)
formatd(( s + 6), 2, ic%100);
puts( s);
}
putdate( d) /* format and display date */
struct calendar *d;
{
char s[ 10];
strcpy( s, " 0/00/00 "); /* template */
formatd( s, 2, d->mm);
formatd(( s + 3), 2, d->dd);
formatd(( s + 6), 2, d->yy);
puts( s);
}
formatd( s, n, d) /* format n digits of d into s */
char s[]; /* like sprintf( s, "%nd", d) */
int n, d; /* d is assumed to be positive */
{ /* and n decimal digits or less */
while ( d && n--) /* s is assumed to be initialized */
{ /* with an appropriate template */
s[ n] = '0' + d%10;
d /= 10;
}
}
printd( d) /* print d in decimal */
int d; /* like printf( "%d", d) */
{ /* d is assumed to be positive */
int n; /* see K & R, p. 85 */
if ( n = d/10)
printd( n); /* recursion for leading digits */
putchar( '0' + d%10); /* trailing digit */
}
sign( i) /* return 1 with sign of i */
{
return ( i < 0 ? -1 : 1);
}
char witch( c) /* return control character */
char c; /* else return CR */
{
if ( iscntrl( c))
return ( c);
return ( '\r');
}
iscntrl( c) /* is c a control char? */
char c;
{
return ( c < ' ' || c == DEL);
}
waitesc() /* wait for ESCAPE key */
{
puts( " -- Press ESCAPE to continue");
putchar( BEL);
while ( getchar() != ESC)
continue;
}
waitkey() /* wait for CTRL-C or other key */
{
puts( " -- ^C to quit, or any other key to continue");
putchar( BEL);
if ( getchar() == CTRLC)
aexit(); /* never return */
}
done() /* save and archive check register */
{
#ifdef CLEARS
saveclr();
#else
if ( saveclr())
return;
#endif
calcbbf();
if ( savedat( FALSE))
{
Recno = Maxentry + 1 - PAGE; /* initialize gobottom() */
First = Recno - PAGE;
Last = First - 1;
Field = 0;
gobottom(); /* redisplay */
return;
}
aexit(); /* no return */
}
#ifdef CLEARS
saveclr() /* audit marked entries */
{
int i, count, compdate();
reorder( 0, compdate);
count = 0; /* count number of marked entries */
for ( i = 0; i <= Maxentry; ++i)
if ( !Entry[ i].clear)
++count;
if ( !count)
return;
prompt( "Print an audit trail of <M>arked entries before deletion (Y/N)? ");
if ( getyesno( NO) && setlst())
{
disheading();
for ( i = 0; i <= Maxentry; ++i)
{
if ( !Entry[ i].clear)
{
Balance[ i].dollar = Balance[ i].cent = 0;
putrecord( i); /* print cleared entry */
}
}
resetlst();
}
}
#else /* not CLEARS */
saveclr() /* save cleared entries */
{ /* return TRUE if bad disk */
char *p, *msg;
char tempname[ FNAMSIZE], bufin[ BUFSIZ], bufout[ BUFSIZ];
int i, j, k, count, oldcount, sumcount, imax, total, compdate();
typcat( Filename, CLRTYP);
count = 0; /* count number of cleared entries */
for ( i = 0; i <= Maxentry; ++i)
if ( Entry[ i].clear)
++count;
if ( !count)
{
prompt( "No change necessary to ");
puts( Filename);
puts( " - ");
return ( FALSE);
}
reorder( 0, compdate);
prompt( msg = "Saving ... ");
strcpy( tempname, Filename);
typcat( tempname, TMPTYP);
resetdsk();
if ( fcreat( tempname, bufout) == ERROR)
{
createrr( tempname);
return ( TRUE);
}
if ( fopen( Filename, bufin) == ERROR)
sumcount = oldcount = 0;
else
{
oldcount = getw( bufin); /* total records in CLR file */
sumcount = getw( bufin); /* SUMMARY records */
if ( oldcount < 0 || sumcount < 0)
goto errin1;
getw( bufin); /* filler */
}
if ( imax = max( 0, ( oldcount + count - CLRSIZE)))
{
prompt( Filename);
puts( " is full. OK to discard ");
printd( imax);
puts( " oldest cleared entries (Y/N)? ");
if ( !getyesno( YES))
{
fclose( bufin);
fclose( bufout);
return ( FALSE);
}
else prompt( msg);
}
imax += sumcount;
total = min( CLRSIZE, ( oldcount + count));
putw( total, bufout); /* record new total record count */
putw( sumcount, bufout);
putw( 0, bufout); /* filler */
for ( i = 0; i < oldcount; ++i) /* transfer old records */
{
for ( j = RECSIZ; j; --j)
{
if (( k = getc( bufin)) == ERROR)
goto errin1;
if (( i < sumcount || /* discard oldest records */
imax <= i) && ( putc( k, bufout) == ERROR))
goto errin2;
}
}
if ( oldcount && ( fclose( bufin) == ERROR))
goto errin1;
for ( i = 0; i <= Maxentry; ++i)
{
if ( Entry[ i].clear)
{
p = &Entry[ i];
for ( j = RECSIZ; j; --j)
if ( putc( *p++, bufout) == ERROR)
goto errout;
}
}
if ( fflush( bufout) == ERROR || /* make sure it is all saved */
fclose( bufout) == ERROR)
goto errout;
prompt( "Do you wish to print an audit trail of cleared entries (Y/N)? ");
if ( getyesno( NO) && setlst())
{
disheading();
for ( i = 0; i <= Maxentry; ++i)
{
if ( Entry[ i].clear)
{
Balance[ i].dollar = Balance[ i].cent = 0;
putrecord( i); /* print cleared entry */
}
}
resetlst();
}
unlink( Filename);
if ( rename( tempname, Filename) == ERROR)
renamerr( tempname, Filename);
prompt( Filename);
puts( " has ");
printd( count);
puts( " new entries (");
printd( total);
puts( " total) - ");
return ( FALSE); /* normal return */
errin1:
puterrmsg( "reading ", Filename);
errin2:
fclose( bufin);
errout:
fclose( bufout);
writerr( tempname);
return( TRUE);
}
#endif
savedat( addcr) /* save all entries */
int addcr; /* TRUE if CR before display */
{ /* return TRUE if bad disk */
char *p, tempname[ FNAMSIZE], bufout[ BUFSIZ];
int i, j;
#ifndef CLEARS
char backname[ FNAMSIZE];
typcat( Filename, DATTYP);
strcpy( tempname, Filename);
typcat( tempname, TMPTYP);
strcpy( backname, Filename);
typcat( backname, BAKTYP);
#else
typcat( Filename, CLRTYP);
strcpy( tempname, Filename);
typcat( tempname, TMPTYP);
i = Memory.dollar = 0; /* use Memory to count SUMMARY */
while (( i <= Maxentry) && ( Entry[ i++].category & 0x80))
++( Memory.dollar);
prompt( "Saving ... ");
#endif
resetdsk();
if ( fcreat( tempname, bufout) == ERROR)
{
createrr( tempname);
return ( TRUE);
}
putw(( Maxentry + 1), bufout); /* record number of entries */
putw( Memory.dollar, bufout); /* record Memory */
putw( Memory.cent, bufout); /* if putw error, also putc later */
for ( i = 0; i <= Maxentry; ++i)
{
p = &Entry[ i];
for ( j = RECSIZ; j; --j)
if ( putc( *p++, bufout) == ERROR)
goto errout;
}
if ( fflush( bufout) == ERROR || /* make sure it is all saved */
fclose( bufout) == ERROR)
goto errout;
#ifdef CLEARS
unlink( Filename);
if ( rename( tempname, Filename) == ERROR)
renamerr( tempname, Filename);
prompt( Filename);
#else
unlink( backname);
rename( Filename, backname);
if ( rename( tempname, Filename) == ERROR)
{
renamerr( tempname, Filename);
prompt( "");
}
if ( addcr)
putchar( '\r');
puts( Filename);
#endif
puts( " has ");
printd( Maxentry + 1);
puts( " entries");
return ( FALSE); /* normal return */
errout:
fclose( bufout);
writerr( tempname);
return( TRUE);
}
calcbbf() /* calculate BBF for each category */
{ /* BBF = BALANCE BROUGHT FORWARD */
char c, nbr[ DEL];
int i, j, count, new;
struct record *e;
struct money sum;
struct calendar maxdate;
setmem( nbr, DEL, 0); /* initialize */
for ( j = 0; j <= Maxentry; ++j) /* identify categories */
{
e = &Entry[ j];
c = e->category;
#ifdef CLEARS
if ( c & 0x80) /* if BBF category */
e->clear = FALSE; /* mark for summation */
if ( !e->clear) /* count marked entries */
++nbr[ c & 0x7f]; /* for each category */
#else
if ( c & 0x80) /* if BBF category */
e->clear = TRUE; /* mark for summation */
if ( e->clear) /* count cleared entries */
++nbr[ c & 0x7f]; /* for each category */
#endif
}
new = 0;
for ( i = ' '; i < DEL; ++i) /* sum cleared categories */
{ /* in ASCII order */
if ( !nbr[ i]) /* if category does not exist */
continue; /* next category */
count = 0;
maxdate.mm = maxdate.dd = maxdate.yy = sum.dollar = sum.cent = 0;
for ( j = 0; j <= Maxentry; ++j)
{
e = &Entry[ j];
#ifdef CLEARS
if ( e->clear || ( e->category & 0x7f) != i)
continue; /* next entry */
#else
if ( !( e->clear) || ( e->category & 0x7f) != i)
continue; /* next entry */
#endif
addmoney( &sum, &sum, &( e->amount), e->deposit);
datemax( &maxdate, &( e->date));
if ( j < Maxentry) /* delete cleared category */
movmem( &Entry[ j + 1], e, ( Maxentry - j)*RECSIZ);
--Maxentry;
--j; /* Entry[ j + 1] moved up */
if ( ++count == nbr[ i]) /* if all entries for this category */
break; /* break j loop over entries */
} /* end j loop over entries */
e = &Entry[ new]; /* insert new BBF category */
if ( new <= Maxentry)
movmem( e, &Entry[ new + 1], ( Maxentry - new + 1)*RECSIZ);
++Maxentry;
++new;
if ( sum.dollar < 0 || sum.cent < 0)
e->deposit = FALSE;
else e->deposit = TRUE;
movmoney( &( e->amount), &sum, e->deposit);
e->date.mm = maxdate.mm;
e->date.dd = maxdate.dd;
e->date.yy = maxdate.yy;
#ifdef CLEARS
e->clear = TRUE;
#else
e->clear = FALSE;
#endif
e->category = i | 0x80;
strcpy( e->payee, BBF);
} /* end i loop over categories */
}
char help() /* display help screen */
{
char c, s[ MAXLINE], f[ FNAMSIZE], buf[ BUFSIZ], *fgets();
int i;
strcpy( f, DEFNAM);
typcat( f, SCRTYP);
if ( fopen( f, buf) == ERROR)
{
openerr( f);
return( 0);
}
cursorto( 0, 0);
putscr( Ivon);
for ( i = 0; i < HEAD && fgets( s, buf); )
{
s[ strlen( s) - 1] = '\0'; /* truncate Abc\n\0 at \n */
puts( s);
cursorto( ++i, 0);
}
putscr( Ivoff);
fclose( buf);
putcursor( Recno, Field);
c = getchar(); /* wait for another command */
for ( i = 0; i < HEAD; ++i) /* clear top of screen */
{
cursorto( i, 0);
clreol( 0);
}
disheading();
strcpy( s, CLRCOM);
formatd( s, 3, ( Recno + 1));
cursorto( 0, 0);
putscr( Ivon);
puts( s); /* display entry number */
putscr( Ivoff);
Oldfield = -1;
putquery();
putcursor( Recno, Field);
return ( c);
}
createrr( f) /* display error creating file f */
char *f;
{
puterrmsg( "creating ", f);
baddisk();
}
writerr( f) /* display error writing file f */
char *f;
{
puterrmsg( "writing ", f);
baddisk();
}
renamerr( f1, f2) /* display error renaming f1 to f2 */
char *f1, *f2;
{
prompt( "Could not rename ");
puts( f1);
puts( " to ");
puts( f2);
waitesc();
strcpy( f2, f1);
}
puterrmsg( s1, s2) /* display two part error message */
char *s1, *s2;
{
prompt( "Error ");
puts( s1);
puts( s2);
waitesc();
}
baddisk() /* prompt for another disk */
{
prompt( "Try another disk in ");
putchar( Filename[ 0]);
putchar( Filename[ 1]);
waitesc();
}
abort( s1, s2) /* abort with two part message */
char *s1, *s2;
{
cursorto(( ROWS - 2), 0);
clreol( 0);
putchar( '\r');
puts( s1);
puts( s2);
putchar( BEL);
aexit(); /* no return */
}
aexit() /* clear last line and exit */
{
cursorto(( ROWS - 1), 0);
clreol( 0);
cursorto(( ROWS - 2), 0);
exit();
}