REM                        LEDGER1.BAS
REM
REM  This is a source program in CBASIC version 2 for use under CP/M
REM  with 32+ K memory and dual floppy discs.  Written by Patrick Cun-
REM  ningham, 235 Sharon Drive, San Antonio, TX  78216.  Commercial re-
REM  production is prohibited.  This program will read budget entries
REM  entered on disc with the BUDGET1.BAS program, sum like entries and
REM  output updated totals for a given data file.  It then stores the
REM  monthly totals in an annual total file, named TOTALS.Ynn
REM
     FOR I%=1 TO 15   REM a little fancy output
          PRINT
          NEXT I%
PRINT TAB(10);  "This program reads and totals monthly expense entries."
PRINT TAB(10);  ":::::::::::::::::::::::::::::::::::::::::::::::::::::"
     FOR I%=1 TO 15   REM  more of the same
          PRINT
          NEXT I%
   OPEN.OUT.FILE%=0   REM used in case of iteration
10 INPUT "Do you want an update [U] or disc total entry [D]?";QUES$
   IF QUES$="" THEN 10
   IF QUES$="U" THEN UPDATE%=-1 : GOTO 10.1
   IF QUES$="D" THEN UPDATE%=0 : GOTO 10.1
   PRINT "Your response is not recognizeable." : GOTO 10
10.1 INPUT "What expense file are you accessing?"; LINE RESP$
REM
REM  Now we see if the file name is valid
REM
   IF LEN(RESP$)=0 THEN GOTO 10.1
   IF LEN(RESP$)>12 THEN PRINT "** NAME TOO LONG **" : GOTO 10.1
   CH.CHAR$= RIGHT$(RESP$,4)
   CHAR.ONE$=LEFT$(CH.CHAR$,1)
   IF CHAR.ONE$<>"." THEN PRINT CHR$(07);TAB(20);"INVALID FILE NAME" :\
                          GOTO 10.1
   FILN$ = UCASE$(RESP$)
11 INPUT "Do you want data printed as it is read {Y/N}";LINE RR$
   IF RR$="" THEN 11
   IF RR$="Y" THEN PRINT.FLAG%=1 : GOTO 12
   IF RR$="N" THEN PRINT.FLAG%=0 : GOTO 12
   PRINT "Your response is not recognizeable" : GOTO 11
12 IF END # 1 THEN 10
   IF UPDATE% OR OPEN.OUT.FILE% THEN GOTO 13.1
REM
REM  This next routine sets up the annual output file
REM
   INPUT "Does the totals file already exist on the disc {Y/N}?";LINE RS$
   IF RS$="" THEN 12
   IF RS$="Y" THEN FILE.NEW%=0  : GOTO 13
   IF RS$="N" THEN FILE.NEW%=-1 : GOTO 13
   PRINT "Your response is not recognizeable" : GOTO 12
13 INPUT "What year is it?"; LINE YEAR$
   IF LEN(YEAR$)<>4 THEN 13
   OUT.FILE.NAME$ = "EXP"+ YEAR$ +".TOT"
   IF END # 2 THEN 10
   IF FILE.NEW% THEN CREATE OUT.FILE.NAME$ RECL 64 AS 2
   IF NOT FILE.NEW% THEN OPEN OUT.FILE.NAME$ RECL 64 AS 2
   PRINT "MONTH'S TOTALS TO BE OUTPUT TO FILE ";OUT.FILE.NAME$
   OPEN.TWO%=-1
REM
REM  we now calculate the number of records in either file
REM
13.1 OPEN FILN$ RECL 64 AS 1
   FALSE%=0
   TRUE%=-1
   DEF FN.CALCULATE.FILE.NO%(FILE.NAME$,REC.SIZE%,FILE.NUM%,POSITION%)
       FN.CALCULATE.FILE.NO% = FALSE%
       FILE.SIZE%=SIZE(FILE.NAME$)
       IF FILE.SIZE%=0 THEN \   FALSE IF NO FILE
            RETURN \
            ELSE FN.CALCULATE.FILE.NO% = TRUE%
       IF END # FILE.NUM% THEN 14
       POSITION%=INT%(FLOAT(FILE.SIZE%)* 128/REC.SIZE%)
       PRINT "locating file at end"
       READ # FILE.NUM%,POSITION%;
       WHILE TRUE%
           READ # FILE.NUM%; LINE DUMMY$
           POSITION% = POSITION% + 1
           WEND
14     PRINT "There are";POSITION%;"entries in this data file."
       FN.CALCULATE.FILE.NO%=POSITION%
       RETURN
   FEND         REM end of defined function
POSN%=0
FILE.RECORD.LENGTH%=FN.CALCULATE.FILE.NO%(FILN$,128,1,POSN%)
CLOSE 1
REM 
REM  We now read in the various expense entries from the disc
REM
OPEN FILN$ RECL 64 AS 1
DIM EXPENSE(FILE.RECORD.LENGTH%,4)
DIM EXPENSE.CAT$(FILE.RECORD.LENGTH%,4)
DIM PAYEE$(FILE.RECORD.LENGTH%)
DIM DATE%(FILE.RECORD.LENGTH%)
FOR I%=1 TO FILE.RECORD.LENGTH%
          IF END # 1 THEN 25
          READ # 1,I%; DATE%(I%), PAYEE$(I%), EXPENSE.CAT$(I%,1),EXPENSE(I%,1),EXPENSE.CAT$(I%,2),EXPENSE(I%,2),EXPENSE.CAT$(I%,3),EXPENSE(I%,3),EXPENSE.CAT$(I%,4),EXPENSE(I%,4)
          NEXT I%
25  IF PRINT.FLAG%=0 THEN GOTO 26
    FOR I%=1 TO FILE.RECORD.LENGTH%
          PRINT PAYEE$(I%);" ";
          FOR J%=1 TO 4
          PRINT EXPENSE.CAT$(I%,J%);"|";EXPENSE(I%,J%);
          NEXT J%
       PRINT
       NEXT I%
26  REM all data has been read in and printed, if that was desired.
    PRINT.FLAG%=0
    REM we will now sum up like data and output it in readable form
    DIM CATEGORY.NAME$(19)
    DIM CATEGORY.CODE$(19)
    FOR H%=1 TO 19
         READ CATEGORY.NAME$(H%),CATEGORY.CODE$(H%)
         NEXT H%
    DATA Charity,C,Drugs & Pharmacy,D,Clothing/Garments,G,Food,F,Household/hardware,H,Inventoried(mortgage),I,Insurance,J,Medical,Y,Miscellaneous taxable,M,Miscellaneous non-tax,N,Phone(pers.),P,Phone(business),B,Phone(Special.),R
    DATA Savings,S,Utility,U,Gas(personal),E,Auto parts(personal),X,Auto repair,W,SALES TAX,T
    RESTORE
    MONTH.TOTAL=0.0
    DIM CATEGORY.SUM(19)
    FOR H%=1 TO 19
         CATEGORY.TOTAL=0.0
         PRINT TAB(20);"............."
         PRINT TAB(20);CATEGORY.NAME$(H%)
         PRINT
         FOR I%=1 TO FILE.RECORD.LENGTH%
              FOR J%=1 TO 4
                   WHILE EXPENSE.CAT$(I%,J%)=CATEGORY.CODE$(H%)
                        CATEGORY.TOTAL=CATEGORY.TOTAL+ EXPENSE(I%,J%)  
                        IF LEN(PAYEE$(I%))<10 THEN \
                              PAYEE$(I%)=PAYEE$(I%)+"     "
                        PRINT TAB(09); DATE%(I%);TAB(13);":";PAYEE$(I%),
                        PRINT USING "$$####.## ";EXPENSE(I%,J%)  
                        GOTO 30  REM logically, we take next I%
                        WEND
                   IF EXPENSE.CAT$(I%,J%+1)="" THEN GOTO 30
                   NEXT J%
30            NEXT I%
        CATEGORY.SUM(H%)=CATEGORY.TOTAL
        IF LEN(CATEGORY.NAME$(H%))<13 THEN \
             CATEGORY.NAME$(H%)=CATEGORY.NAME$(H%)+"         "
        PRINT TAB(44);"--------"
        PRINT "TOTAL FOR ";CATEGORY.NAME$(H%),
        PRINT USING "$$#####.## ";CATEGORY.SUM(H%)
        MONTH.TOTAL=MONTH.TOTAL+CATEGORY.TOTAL  
        NEXT H%
PRINT
PRINT "TOTAL EXPENSES FOR THIS MONTH ARE: ";
PRINT USING "$$######.## "; MONTH.TOTAL
REM
REM   We now output the month's totals to the annual totals disc file.
REM
      IF UPDATE% THEN UPDATE%=0 : GOTO 45
40    IF END # 2 THEN 42
      OUT.FILE.LENGTH%=FN.CALCULATE.FILE.NO%(OUT.FILE.NAME$,64,2,0)
42    MONTH.CODE$=RIGHT$(FILN$,3)
      PRINT # 2; "*", MONTH.CODE$,YEAR$
      FOR H%=1 TO 19
           PRINT # 2; " ", CATEGORY.CODE$(H%),CATEGORY.SUM(H%)
           PRINT "disc entered:";CATEGORY.NAME$(H%);":";CATEGORY.SUM(H%)
           NEXT H%
      PRINT # 2; "=",MONTH.TOTAL
      PRINT "disc entered total for ";MONTH.CODE$;",";YEAR$
45    INPUT "Any other files to process{Y/N}?"; RSS$
      IF RSS$="" THEN 45
      IF RSS$="Y" THEN CLOSE 1 : OPEN.OUT.FILE%=-1 : GOTO 10
      IF RSS$="N" THEN 50
      PRINT "Your response is not recognizeable" : GOTO 45
50    PRINT TAB(20); "end of this routine."
      IF OPEN.TWO% THEN CLOSE 2
END   REM: Really, isn't Algol much neater?
