home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
database
/
chx8010b.lbr
/
CHECKC.CZ
/
CHECKC.C
Wrap
Text File
|
1986-07-13
|
21KB
|
709 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
*/
/* 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()
* calcbbf()
* char help()
* abort( s1, s2)
* aexit()
*/
#include "a:checks.h"
putcursor( i, f) /* put cursor in entry i, field f */
int i, f;
{
if ( f == PAYFIELD)
Character = min( Character, strlen( Entry[ i].payee));
else Character = 0;
cursorto(( i - First + HEAD), ( Ftoc[ f] + Character));
}
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();
puts(
" Date Payee C Amount DEP CLR Balance"
);
putchar( '\n');
puts(
"-------- ------------------------------------------ - -------- --- --- --------"
);
if ( !Printing)
putscr( Ivoff);
}
recheading( s1, s2) /* display heading for reconcile() */
char *s1, *s2;
{
if ( !Printing)
{
clrscr();
putscr( Ivon);
}
puttitle();
puts(
" Last Balance _____ Cleared Entries ______ _______ All Entries ________"
);
putchar( '\n');
puts(
" Date C Forward Checks Deposits Balance Checks Deposits Balance"
);
putchar( '\n');
puts( s1);
puts( s2);
if ( !Printing)
putscr( Ivoff);
}
putquery() /* select and display query */
{
char test, cwitch, dep;
if ( Recno > Maxentry)
{
prompt( "Press RETURN to start a new entry, or ^J for help");
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;
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;
}
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⌐ /¬ forma⌠ ε digit≤ oµ Σ int∩ ≤ */
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 */
{
if ( saveclr())
return;
calcbbf();
if ( savedat())
{
Recno = Maxentry + 1 - PAGE; /* initialize gobottom() */
First = Recno - PAGE;
Last = First - 1;
Field = 0;
gobottom(); /* redisplay */
return;
}
aexit(); /* no return */
}
saveclr() /* save cleared entries */
{ /* return TRUE if bad disk */
char *p;
char tempname[ FNAMSIZE], bufin[ BUFSIZ], bufout[ BUFSIZ];
int i, j, count, oldcount, 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);
}
prompt( "");
reorder( 0, compdate);
strcpy( tempname, Filename);
typcat( tempname, TMPTYP);
resetdsk();
if ( fcreat( tempname, bufout) == ERROR)
{
createrr( tempname);
return ( TRUE);
}
if ( fopen( Filename, bufin) == ERROR)
oldcount = 0;
else
{
oldcount = getw( bufin); /* records in CLR file */
getw( bufin); /* filler */
getw( bufin); /* filler */
}
if ( imax = max( 0, ( RECSIZ*( oldcount + count - CLRSIZE))))
{
prompt( Filename);
puts( " is full. OK to discard oldest cleared entries (Y/N)? ");
if ( !getyesno( YES))
return ( FALSE);
for ( i = imax; i; --i)
getc( bufin); /* discard old records */
}
imax = RECSIZ*oldcount - imax;
total = min( CLRSIZE, ( oldcount + count));
putw( total, bufout); /* record new total record count */
putw( 0, bufout); /* filler */
putw( 0, bufout); /* filler */
for ( i = imax; i; --i) /* transfer old records */
if ( putc( getc( bufin), bufout) == ERROR)
goto error;
if ( oldcount)
fclose( bufin);
for ( i = 0; i <= Maxentry; ++i)
{
if ( Entry[ i].clear)
{
p = &Entry[ i];
for ( j = RECSIZ; j; --j)
if ( putc( *p++, bufout) == ERROR)
goto error;
}
}
if ( fflush( bufout) == ERROR) /* make sure it is all saved */
goto error;
fclose( bufout);
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)
{
prompt( "Could not rename ");
puts( tempname);
puts( " to ");
puts( Filename);
waitesc();
strcpy( Filename, tempname);
}
prompt( Filename);
puts( " has ");
printd( count);
puts( " new entries (");
printd( total);
puts( " total) - ");
return ( FALSE); /* normal return */
error:
fclose( bufout);
writerr( tempname);
return ( TRUE);
}
savedat() /* save all entries */
{ /* return TRUE if bad disk */
char *p, tempname[ FNAMSIZE], backname[ FNAMSIZE], bufout[ BUFSIZ];
int i, j;
typcat( Filename, DATTYP);
strcpy( tempname, Filename);
typcat( tempname, TMPTYP);
strcpy( backname, Filename);
typcat( backname, BAKTYP);
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);
for ( i = 0; i <= Maxentry; ++i)
{
p = &Entry[ i];
for ( j = RECSIZ; j; --j)
if ( putc( *p++, bufout) == ERROR)
goto error;
}
if ( fflush( bufout) == ERROR) /* make sure it is all saved */
goto error;
fclose( bufout);
unlink( backname);
rename( Filename, backname);
rename( tempname, Filename);
puts( Filename);
puts( " has ");
printd( Maxentry + 1);
puts( " entries");
return ( FALSE); /* normal return */
error:
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;
if ( c & 0x80) /* if BBF category */
e->clear = TRUE; /* mark for summation */
if ( e->clear) /* count cleared entries */
++nbr[ c & 0x7f]; /* for each category */
}
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];
if ( !( e->clear) || ( e->category & 0x7f) != i)
continue; /* next entry */
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;
e->clear = FALSE;
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 = 6; i-- && fgets( s, buf); )
puts( s);
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();
putcursor( Recno, Field);
return ( c);
}
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();
}