home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol132 / checks.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1984-04-29  |  24.4 KB  |  893 lines

  1. PROGRAM checks;
  2. { Pascal/z version--This is an update from Disk #15 of CheckBk(alias
  3.   NOW). The author sez the interesting improvements are the availability
  4.   of on-line changes in code assignments, and ability to edit and
  5.   reconform the data stored in the file. He has had a little bug in
  6.   the 'Dump' portion of the program. If it is selected from the menu
  7.   it may or may not lose some data . So if anyone traps that bug be
  8.   sure and let us know.}
  9.  
  10.  
  11. CONST max_items = 300;
  12.       max_codes = 50;
  13.       max_add_code = 10;
  14.       disk_file = 'A:CHECK82';
  15.       left = 7;     { Number of digits to the left of the dp }
  16.       right =  2;    {   "    "    "     "  "  right "  "  "  }
  17.  
  18.   { Number of bytes it takes to represent a fixed-point number  }
  19.     bytes = (left + right + 1) div 2;
  20.  
  21.    {  Length of a fixed-point converted string  }
  22.     maxchars = ((left * 4) div 3) + right + 3;
  23.  
  24. TYPE
  25.     signtyp = (plus, minus);
  26.     carrytyp = 0..1;
  27.  
  28. { The basic unit of a fixed-point number, takes 1 byte of storage. }
  29.     byte = 0..255;
  30.  
  31.     modetyp = (none, suplzer, supltzer, wdollar, wcomma, wboth);
  32.  
  33.   { This is the type around which this whole package is based.     }
  34.     fixed = record
  35.           sign: signtyp;
  36.           digits: array[1..bytes] of byte
  37.         end;
  38.  
  39. { This is a string type which holds a fixed-point number converted }
  40.   { to ASCII. }
  41.     fixstr = string maxchars;
  42.  
  43.     $STRING0 = STRING 0;
  44.     $STRING255 = STRING 255;
  45.          item_data = RECORD
  46.             item_number : INTEGER;
  47.             month : INTEGER;
  48.             day : INTEGER;
  49.             year : INTEGER;
  50.             amount : FIXED;
  51.             description : STRING 30;
  52.             code : INTEGER;
  53.             END;
  54. VAR command : CHAR;
  55.     code_description : ARRAY [1..max_codes] OF STRING 15;
  56.     items : ARRAY [1..max_items] OF item_data;
  57.         item_last : 1..max_items;
  58.     data_file : FILE of item_data;
  59.     lines_printed : 0..80;
  60.     code_amount : ARRAY [1..max_codes] OF FIXED;
  61.     entry_year : INTEGER;
  62.     swaped : BOOLEAN;
  63.     answer : CHAR;
  64.     result : INTEGER;
  65.  
  66. { This is set by the fixed point functions. It is set true if there }
  67. { was an overflow. }
  68.     fixederror: boolean;
  69.  
  70. { This is the carry flag. It is used by the fixed point functions. }
  71. { The user's code doesn't play with it. }
  72.     carry: carrytyp;
  73.  
  74. (****************************************************************)
  75. (*                                *)
  76. (* Ithaca InterSystems' Pascal/Z Fixed-Point Package            *)
  77. (*                                *)
  78. (* Written by Robert Bedichek      August 1980            *)
  79. (*                                *)
  80. (****************************************************************)
  81.  
  82. procedure setlength( var y:$string0; x: integer ); external;
  83. function length( x:$string255 ): integer; external;
  84.  
  85. (* The next two external functions are in LIB.REL and are automatically *)
  86. (* linked in when the library is being linked in.  They add and     *)
  87. (* subtract two decimal digits packed into a byte using Z-80 decimal    *)
  88. (* arithmetic.                                *)
  89. function addbyte( var carry: carrytyp; a, b: byte ):byte; external;
  90. function subbyte( var carry: carrytyp; a, b: byte ):byte; external;
  91.  
  92. function add( a, b: fixed ): fixed;
  93. (************************************************************************)
  94. (* The value of this function is the signed sum of the two value    *)
  95. (* parameters.    The global variable 'fixederror' is set if there was    *)
  96. (* an overflow.                             *)
  97. (*                                    *)
  98. (*                                    *)
  99. (*                                    *)
  100. (************************************************************************)
  101. var
  102.     carry: 0..1;
  103.     i: integer;
  104.     res: fixed;
  105.  
  106. begin
  107.   carry := 0;
  108.   if a.sign = b.sign then   (* Like signs, just add    *)
  109.     begin
  110.       add.sign := a.sign;
  111.       for i := 1 to bytes do
  112.     add.digits[ i ] := addbyte( carry, a.digits[ i ], b.digits[ i ] );
  113.       fixederror := (carry = 1)
  114.     end
  115.              else   (* Unlike signs, subract negative op from pos.  *)
  116.     begin
  117.       fixederror := false;
  118.       if a.sign = plus then
  119.     for i := 1 to bytes do
  120.       res.digits[ i ] := subbyte(carry, a.digits[ i ], b.digits[ i ])
  121.                else
  122.     for i := 1 to bytes do
  123.       res.digits[ i ] := subbyte(carry, b.digits[ i ], a.digits[ i ]);
  124.       if carry = 0 then res.sign := plus
  125.            else
  126.              begin
  127.                res.sign := minus;
  128.                carry := 0;
  129.  
  130. (* Take nines complement of the result by subtracting it from zero.    *)
  131.                for i := 1 to bytes do
  132.         res.digits[ i ] := subbyte( carry, 0, res.digits[ i ])
  133.              end;
  134.       add := res
  135.     end
  136. end;
  137.  
  138. function sub( minuend, subtrahend: fixed ): fixed;
  139. (************************************************************************)
  140. (* The value of this function is the signed difference of the two    *)
  141. (* value parameters.  The global variable 'fixederror' is set if the    *)
  142. (* is an overflow.                            *)
  143. (*                                    *)
  144. (*                                    *)
  145. (*                                    *)
  146. (************************************************************************)
  147.  
  148. begin
  149.  
  150. (* Just reverse the sign of the subtrahend and add.            *)
  151.   if subtrahend.sign = plus then subtrahend.sign := minus
  152.                 else subtrahend.sign := plus;
  153.   sub := add( minuend, subtrahend )
  154. end;
  155.  
  156.  
  157.  
  158. procedure shiftleft( var a: fixed );
  159. (************************************************************************)
  160. (* This procedure shifts all of the packed decimal digits in the    *)
  161. (* passed parameter left one position.    A zero is shifted into the    *)
  162. (* least significant position.    The digit shifted out is lost.        *)
  163. (*                                    *)
  164. (*                                    *)
  165. (*                                    *)
  166. (************************************************************************)
  167. var
  168.     i: integer;
  169.     next: byte;
  170.  
  171. begin
  172.   for i := bytes downto 1 do
  173.     begin
  174.       if i > 1 then next := (a.digits[ i - 1 ] div 16)
  175.            else next := 0;
  176.       a.digits[ i ] := ((a.digits[ i ] * 16) + next) mod 256
  177.     end
  178. end;        (*    shiftleft    *)
  179.  
  180. procedure shiftright( var a: fixed );
  181. (************************************************************************)
  182. (* This procedure shifts all of the packed decimal digits in the passed *)
  183. (* parameter right one position.  A zero is shifted into the most    *)
  184. (* significant position.  The digits shifted out is lost.        *)
  185. (*                                    *)
  186. (*                                    *)
  187. (*                                    *)
  188. (************************************************************************)
  189. var
  190.     i: integer;
  191.     next: byte;
  192.  
  193. begin
  194.   for i := 1 to bytes do
  195.     begin
  196.       if i < bytes then next := (a.digits[ i + 1 ] mod 16) * 16
  197.            else next := 0;
  198.       a.digits[ i ] := (a.digits[ i ] div 16) + next
  199.     end
  200. end;        (*    shiftright    *)
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208. function fixtostr( a: fixed; mode: modetyp; trailing: byte ): fixstr;
  209. (************************************************************************)
  210. (* This function returns a formatted string.  The 'mode' parameter    *)
  211. (* specifies which formatting operation is to take place.  The        *)
  212. (* 'trailing' parameter specifies the maximum number of digits to the    *)
  213. (* right of the decimal point that are to appear.            *)
  214. (*                                    *)
  215. (*                                    *)
  216. (************************************************************************)
  217. var
  218.     i, j: byte;
  219.     result: fixstr;
  220.  
  221. begin
  222.   if trailing > right then trailing := right;
  223.  
  224. (* Make the 'result' string have 'maxchars' spaces        *)
  225.   setlength( result, 0 );
  226.   for i := 1 to maxchars do append( result, ' ' );
  227.  
  228.   result[ maxchars - right ] := '.';
  229.  
  230. (* Put the digits to the right of the dp into the string     *)
  231.   for i := maxchars downto maxchars - (right - 1) do
  232.     begin
  233.       result[ i ] := chr((a.digits[ 1 ] mod 16) + ord('0'));
  234.       shiftright( a )
  235.     end;
  236.  
  237. (* Leave 'trailing' digits to the right of the decimal point    *)
  238.   for i := maxchars downto (maxchars - (right - trailing)) + 1 do
  239.     result[ i ] := ' ';
  240.  
  241. (* Put the digits to the left of the dp into the string     *)
  242.   j := maxchars - right - 1;
  243.   for i := maxchars - right - 1 downto maxchars - left - right do
  244.     begin
  245.  
  246. (* Put a comma between every third digit if 'mode' tells us to    *)
  247.       if ((((maxchars - right - 1) - i) mod 3) = 0) and
  248.      (i < (maxchars - right - 1)) and
  249.      (mode >= wcomma) then
  250.                 begin
  251.                   result[ j ] := ',';
  252.                   j := j - 1
  253.                 end;
  254.       result[ j ] := chr((a.digits[ 1 ] mod 16) + ord('0'));
  255.       j := j - 1;
  256.       shiftright( a )
  257.     end;
  258.  
  259.  
  260. (* Suppress leading zeros if mode is anything other than 'none' *)
  261.   j := j + 1;
  262.   if mode > none then
  263.     while ((result[ j ] = '0') or (result[ j ] = ','))
  264.       and (j < maxchars - right - 1) do
  265.       begin
  266.     result[ j ] := ' ';
  267.     j := j + 1
  268.       end;
  269.  
  270. (* Put a dollar sign in front of the most significant digit if    *)
  271. (* 'mode' is 'wdollar' or 'wboth'                *)
  272.   j := j - 1;
  273.   if (mode = wdollar) or (mode = wboth) then
  274.     begin
  275.       result[ j ] := '$';
  276.       j := j - 1
  277.     end;
  278.  
  279. (* If the number being converted is negative put a minus sign in    *)
  280. (* front of the dollar sign or (if there is no dollar sign) the most    *)
  281. (* most significant digit.                        *)
  282.   if a.sign = minus then result[ j ] := '-';
  283.  
  284. (* If we are supposed to suppress leading and trailing zeros    *)
  285. (* (mode = supltzer), suppress the trailing ones here.        *)
  286.   if mode = supltzer then
  287.     begin
  288.       j := maxchars - ( right - trailing );
  289.       while result[ j ] = '0' do
  290.     begin
  291.       result[ j ] := ' ';
  292.       j := j - 1
  293.     end
  294.     end;
  295.   fixtostr := result
  296. end;        (*    fixtostr    *)
  297.  
  298. function strtofix( a: fixstr ): fixed;
  299. (************************************************************************)
  300. (* This converts the passed string to fixed point.  All characters    *)
  301. (* other than the minus sign (-), decimal point(.), and the decimal    *)
  302. (* digits (0123456789) are skipped over and ignored.            *)
  303. (*                                    *)
  304. (*                                    *)
  305. (*                                    *)
  306. (************************************************************************)
  307. var
  308.     rightcount, i: byte;
  309.     righthalf: boolean;    (* True when scanning digits to right of dp  *)
  310.     result: fixed;
  311.  
  312. begin
  313.   righthalf := false;
  314.   rightcount := 0;
  315.   for i := 1 to bytes do result.digits[ i ] := 0;
  316.   result.sign := plus;
  317.   for i := 1 to length( a ) do
  318.     if a[ i ] = '.' then righthalf := true
  319.             else
  320.       if a[ i ] = '-' then result.sign := minus
  321.               else
  322.        if (rightcount < right) and (a[ i ] <= '9') and (a[ i ] >= '0')
  323.      then
  324.        begin
  325.          shiftleft( result );
  326.          result.digits[1] := result.digits[1] + ord(a[i]) - ord('0');
  327.          if righthalf then rightcount := rightcount + 1
  328.        end;
  329.     for i := rightcount to right - 1 do shiftleft( result );
  330.   strtofix := result
  331. end;        (*    strtofix    *)
  332.  
  333.  
  334.  
  335.  
  336. PROCEDURE initialize;
  337. { set inital values }
  338. VAR count : 0..max_items;
  339. BEGIN
  340.     item_last := 1;
  341.     FOR count := 1 TO max_codes DO
  342.       code_description[count] := '               ';
  343.     code_description[1]  := 'Balance forward';
  344.     code_description[2]  := 'Deposit        ';
  345.     code_description[3]  := 'NOW interest   ';
  346.         code_description[4]  := 'Misc. add      ';
  347.     code_description[11] := 'House payment  ';
  348.     code_description[12] := 'Car payment    ';
  349.     code_description[13] := 'Gas & Electric ';
  350.     code_description[14] := 'Gasoline       ';
  351.     code_description[15] := 'Credit cards   ';
  352.     code_description[16] := 'Auto insurance ';
  353.     code_description[17] := 'Entertainment  ';
  354.     code_description[18] := 'Telephone      ';
  355.     code_description[19] := 'Auto maint.    ';
  356.     code_description[20] := 'Subscriptions  ';
  357.     code_description[21] := 'Clothing       ';
  358.     code_description[22] := 'Computer parts ';
  359.     code_description[23] := 'Travel/hotels  ';
  360.     code_description[24] := 'Contributions  ';
  361.     code_description[25] := 'Misc auto      ';
  362.     code_description[26] := 'Investments    ';
  363.         code_description[27] := 'Education      ';                         
  364.         code_description[28] := 'Water & sewer  ';
  365.         code_description[29] := 'Taxes          ';
  366.         code_description[30] := 'Books          ';
  367.         code_description[31] := 'Food           ';
  368.         code_description[32] := 'Drugs          ';
  369.         code_description[33] := 'Medical service';
  370.         code_description[34] := 'Tyme withdrawl ';
  371.         code_description[35] := 'Misc insurance ';
  372.         code_description[36] := 'Dental         ';
  373.         code_description[37] := 'Pro tools/equip';
  374.         code_description[38] := 'Pro subscript. ';
  375.         code_description[39] := 'Pro books      ';
  376.         code_description[40] := 'Auto Registrat.';
  377.         code_description[41] := 'Slip rent      ';
  378.         code_description[42] := 'Boat expenses  ';
  379.         code_description[43] := 'Sewing/knitting';
  380.         code_description[49] := 'Misc. subtract ';
  381.         code_description[50] := 'Misc. expenses ';
  382. END;
  383.  
  384. PROCEDURE newpage;
  385. { print form-feed and 2 blank lines }
  386. BEGIN
  387.         WRITELN(CHR(12));
  388.         WRITELN;
  389.         WRITELN;
  390.         lines_printed := 0;
  391. END;
  392.  
  393. PROCEDURE instructions;
  394. { print description of program operation }
  395. VAR answer : CHAR;
  396.     count  : INTEGER;
  397. BEGIN
  398.         newpage;
  399.         WRITELN(' Checkbook program - For Wesley & Shirley Jenkins ');
  400.         WRITELN(' Version 1.23 ');
  401.         WRITELN;
  402.         WRITE(' Want instructions ? ');
  403.         READ(answer);
  404.         WRITELN;
  405.         IF (answer = 'Y') OR (answer = 'y') THEN
  406.           BEGIN          
  407.              newpage;    
  408.              WRITELN(' -- Commands --');
  409.              WRITELN;
  410.              WRITELN(' A - Add an item');
  411.              WRITELN(' R - Remove an item');
  412.              WRITELN(' P - Print all items');
  413.              WRITELN(' B - Print by balance');
  414.              WRITELN(' S - Sort by date');
  415.              WRITELN(' D - Dump to disk');
  416.              WRITELN(' L - Load from disk');
  417.          WRITELN(' M - Modify an item');
  418.              WRITELN(' Q - Quit');
  419.          WRITELN(' H - Hardcopy all items');
  420.          WRITELN(' I - Hardcopy instructions and codes');
  421.          WRITELN(' J - Hardcopy balance');
  422.              WRITELN;
  423.              WRITELN;
  424.              WRITELN('Code        Description');
  425.              FOR count := 1 TO 27 DO
  426.                 WRITE('-');
  427.              WRITELN;
  428.              FOR count := 1 TO 50 DO
  429.                 IF code_description[count] <> '              ' THEN
  430.                    WRITELN(count:3,'        ',code_description[count]);
  431.              END;
  432. END;
  433.  
  434. PROCEDURE heading;
  435. { print heading for new page of item printout }
  436. VAR  count : 0..79;
  437. BEGIN
  438.         WRITE(' Item     Date         Amount           Description');
  439.         WRITE('              Code');
  440.         WRITELN;
  441.         FOR COUNT := 1 TO 79 DO WRITE('-');
  442.         WRITELN;
  443. END;
  444.  
  445. PROCEDURE item_print(count : INTEGER);
  446. { print data on one item }
  447. BEGIN
  448.         WITH items[count] DO
  449.         BEGIN
  450.         WRITE(item_number:5);
  451.         WRITE(month:5,'/');
  452.         IF day < 10 THEN
  453.              WRITE('0',day:1) 
  454.         ELSE
  455.              WRITE(day:2);
  456.         WRITE('/',year:2);
  457.         WRITE(FIXTOSTR(amount,WBOTH,2));
  458.         WRITE(' ',description);
  459.         WRITE('  ',code_description[code]);
  460.         END;
  461. END;
  462.  
  463.  
  464. PROCEDURE print_instructions;
  465. { Output to printer, commands & codes }
  466. VAR file_out : TEXT;
  467.     count : INTEGER;
  468. BEGIN
  469.   REWRITE('Lst:',file_out);
  470.   WRITELN(file_out,CHR(12));
  471.   WRITELN(file_out,' ------Commands---------------------- ');
  472.   WRITELN(file_out,' A - Add an item');
  473.   WRITELN(file_out,' R - Remove an item');
  474.   WRITELN(file_out,' P - Print all items');
  475.   WRITELN(file_out,' B - Print by balance');
  476.   WRITELN(file_out,' S - Sort by date');
  477.   WRITELN(file_out,' D - Dump to disk');
  478.   WRITELN(file_out,' L - Load from disk');
  479.   WRITELN(file_out,' M - Modify an item');
  480.   WRITELN(file_out,' Q - Quit');
  481.   WRITELN(file_out,' H - Hardcopy all items');
  482.   WRITELN(file_out,' I - Hardcopy instructions and codes');
  483.   WRITELN(file_out,' J - Hardcopy balance');
  484.   WRITELN(file_out);
  485.   WRITELN(file_out,'Code    Description');
  486.   WRITELN(file_out,CHR(9),'---------------------------');
  487.   FOR count := 1 TO max_codes DO
  488.       WRITELN(file_out,count:3,'     ',code_description[count]);
  489.   WRITELN(file_out);
  490.   WRITELN;
  491. END;
  492.  
  493. PROCEDURE print_all;
  494. { print data for all items in file }
  495. VAR count : INTEGER;
  496. BEGIN
  497.         newpage;
  498.         heading;
  499.              FOR count := 1 TO item_last-1 DO
  500.              BEGIN
  501.              IF lines_printed = 20 THEN
  502.                     BEGIN
  503.                       newpage;
  504.                       heading;
  505.                     END;
  506.              item_print(count);
  507.              lines_printed := lines_printed +1;
  508.          WRITELN;
  509.              END;    
  510.         WRITELN;
  511. END;
  512.  
  513. PROCEDURE hardcopy_heading;
  514. { prints hardcopy heading for printout }
  515. VAR file_out : TEXT;
  516.     count : INTEGER;
  517. BEGIN
  518.     REWRITE('Lst:',file_out);
  519.         WRITELN(file_out,CHR(12));
  520.     WRITE(file_out,' Item     Date        Amount           Description');
  521.     WRITE(file_out,'              Code');
  522.     WRITELN(file_out);
  523.     FOR count := 1 TO 79 DO WRITE(file_out,'-');
  524.     WRITELN(file_out);
  525.     lines_printed := 3;
  526. END;
  527.  
  528. PROCEDURE copy_all;
  529. { Hardcopys all items in file }
  530. VAR count : 0..79;
  531.     file_out : TEXT;
  532. BEGIN
  533.     hardcopy_heading;
  534.          FOR count := 1 TO item_last-1 DO
  535.          BEGIN
  536.              IF lines_printed = 75 THEN
  537.             hardcopy_heading;
  538.              WITH items[count] DO  
  539.          BEGIN
  540.         REWRITE('Lst:',file_out);
  541.              WRITE(file_out,item_number:5);
  542.         WRITE(file_out,month:5,'/');
  543.         IF day < 10 THEN 
  544.             WRITE(file_out,'0',day:1)
  545.         ELSE
  546.             WRITE(file_out,day:2);
  547.         WRITE(file_out,'/',year:2);
  548.         WRITE(file_out,FIXTOSTR(amount,WBOTH,2));
  549.         WRITE(file_out,' ',description);
  550.         WRITE(file_out,'  ',code_description[code]);
  551.         WRITELN(file_out);
  552.              END;    
  553.         lines_printed := lines_printed +1;
  554.         END;
  555. END;
  556.  
  557. PROCEDURE print_balance;
  558. { Print totals by categories and net balance }
  559. VAR item : 1..max_items;
  560.     balance : FIXED;
  561. BEGIN
  562.         FOR item := 1 TO max_codes DO
  563.           code_amount[item] := STRTOFIX('0');
  564.         balance := STRTOFIX('0');
  565.     FOR item := 1 TO item_last-1 DO
  566.       WITH items[item] DO
  567.         code_amount[code] := ADD(code_amount[code], amount);
  568.     FOR item := 1 TO max_add_code DO
  569.       balance := ADD(balance, code_amount[item]);
  570.     FOR item := max_add_code+1 TO max_codes DO
  571.       balance := SUB(balance, code_amount[item]);
  572.     newpage;
  573.     WRITELN('   Category             Amount');
  574.     FOR item := 1 TO 32 DO
  575.       WRITE('-');
  576.     WRITELN;
  577.     FOR item := 1 TO max_codes DO
  578.       IF code_amount[item] <> STRTOFIX('0') THEN     
  579.    WRITELN(code_description[item],'  -',FIXTOSTR(code_amount[item],WBOTH, 2 ));
  580.     FOR item := 1 TO 32 DO
  581.       WRITE('-');
  582.     WRITELN;
  583.     WRITELN('Balance          -',FIXTOSTR(balance, WBOTH, 2));
  584.     WRITELN;
  585. END;
  586.  
  587. PROCEDURE kopy_balance;
  588. { hardcopy balance sheet to printer }
  589. VAR item : 1..max_items;
  590.     balance : FIXED;
  591.     file_out : TEXT;
  592. BEGIN
  593.         FOR item := 1 TO max_codes DO
  594.           code_amount[item] := STRTOFIX('0');
  595.         balance := STRTOFIX('0');
  596.     FOR item := 1 TO item_last-1 DO
  597.       WITH items[item] DO
  598.           code_amount[code] := ADD(code_amount[code], amount);
  599.     FOR item := 1 TO max_add_code DO
  600.       balance := ADD(balance, code_amount[item]);
  601.     FOR item := max_add_code+1 TO max_codes DO
  602.       balance := SUB(balance, code_amount[item]);
  603.     REWRITE('Lst:',file_out);
  604.     WRITELN(file_out,CHR(12));
  605.     WRITELN(file_out,'   Category               Amount');
  606.     FOR item := 1 TO 32 DO
  607.       WRITE(file_out,'-');
  608.     WRITELN(file_out);
  609.     FOR item := 1 TO max_codes DO
  610.       IF code_amount[item] <>STRTOFIX('0') THEN     
  611.        BEGIN
  612.                 WRITE(file_out,code_description[item],'  -');
  613.          WRITELN(file_out,FIXTOSTR(code_amount[item],WBOTH, 2 ));
  614.        END;
  615.     FOR item := 1 TO 32 DO
  616.       WRITE(file_out,'-');
  617.     WRITELN(file_out);
  618.     WRITELN(file_out,'Balance          -',FIXTOSTR(balance, WBOTH, 2));
  619.     WRITELN(file_out);
  620. END;
  621.  
  622. PROCEDURE remove;
  623. { remove item from file }
  624. VAR remove : CHAR;
  625.     found,item : INTEGER;
  626.     item_remove : INTEGER;
  627. BEGIN
  628.     found :=0;
  629.     WRITELN;
  630.     WRITE(' Remove item number - ');
  631.     READ(item_remove);
  632.     FOR item := 1 TO item_last-1 DO
  633.       IF items[item].item_number = item_remove THEN
  634.         found := item;
  635.     WRITELN;
  636.     IF found <> 0 THEN
  637.       BEGIN
  638.         heading;
  639.         item_print(found);
  640.         WRITELN;
  641.         WRITELN;
  642.         WRITE(' Remove ? ');
  643.         READ(remove);
  644.         IF (remove = 'Y') OR (remove = 'y') THEN
  645.         BEGIN
  646.           FOR item := found TO item_last-1 DO
  647.             items[item] := items[item+1];
  648.           item_last := item_last-1;
  649.         END;
  650.       END;
  651.   IF found = 0 THEN
  652.     WRITELN(' Item not in list.....');
  653. END;
  654.  
  655. PROCEDURE entry;
  656. { console entry of check/deposit data }
  657. VAR ch : CHAR;
  658.     number : STRING 20;
  659. BEGIN          
  660.   REPEAT
  661.     WITH items[item_last] DO
  662.     BEGIN
  663.       description := '                          ';
  664.       WRITELN;
  665.       WRITE(' Item number ? ');
  666.       READLN(item_number);
  667.       WRITE(' Month ? ');
  668.       READ(month);
  669.       WRITE(' Date ? ');
  670.       READ(day);
  671.       WRITE(' Amount ? ');
  672.       READ(number);
  673.       amount := STRTOFIX(number);
  674.       WRITELN('               _____________________________');
  675.       WRITE(' Description ? ');
  676.       READLN(description);
  677.       WHILE LENGTH(description) <> 30 DO
  678.         APPEND(description,' ');
  679.       WRITE(' Code ? ');
  680.       READ(code);
  681.       year := entry_year;
  682.       WRITELN;
  683.        END;
  684.   heading;
  685.   item_print(item_last);
  686.   WRITELN;
  687.   WRITELN;
  688.   WRITE(' Correct ? ');
  689.   READ(ch);
  690.   UNTIL (ch ='Y') OR (ch = 'y');
  691.   items[item_last+1] := items[item_last];
  692.   items[item_last+1].item_number := 0;
  693.   item_last := item_last+1;
  694.   WRITELN;
  695. END;
  696.  
  697. PROCEDURE modify;
  698. { modify a field in an item }
  699. VAR found,item : INTEGER;
  700.     number : STRING 20;
  701.     name : STRING 30;
  702.     item_modify : INTEGER;
  703.     answer : CHAR;
  704.     A,B,C,D,N,R : STRING 3;
  705. BEGIN
  706.   A:=CHR(27);
  707.   B:=CHR(48);
  708.   C:=CHR(64);
  709.   APPEND(A,B);
  710.   APPEND(A,C);
  711.   N:=A;
  712.   A:=CHR(27);
  713.   B:=CHR(48);
  714.   D:=CHR(80);
  715.   APPEND(A,B);
  716.   APPEND(A,D);
  717.   R:=A;
  718.   found := 0;
  719.   WRITELN;
  720.   WRITE(' Modify Item number - ');
  721.   READ(item_modify);
  722.   WRITELN;
  723.   FOR item := 1 TO item_last-1 DO
  724.    IF items[item].item_number=item_modify THEN
  725.      found := item;
  726.   WRITELN;
  727.   IF found<>0 THEN
  728.     BEGIN
  729.       heading;
  730.       item_print(found);
  731.       WRITELN;
  732.       WRITE(R,'I',N,'tem # ');
  733.       WRITE(R,'M',N,'onth ');
  734.       WRITE(R,'D',N,'ate     ');
  735.       WRITE(R,'A',N,'mount   ');
  736.       WRITE(R,'N',N,'ame or description      ');
  737.       WRITELN(R,'C',N,'ode');
  738.       WRITELN;
  739.       WRITELN(' Modify one of the above fields ');
  740.       WRITE(' Enter letter of the field to be changed?- ');
  741.       READ(answer);
  742.       WRITELN;
  743.       CASE answer OF
  744.     'I','i':BEGIN
  745.           WRITE(' New item number- ');
  746.                   READLN(items[found].item_number);
  747.           WRITELN;
  748.         END;
  749.     'M','m':BEGIN
  750.           WRITE(' New month- ');
  751.                   READ(items[found].month);
  752.           WRITELN;
  753.         END;
  754.         'D','d':BEGIN
  755.           WRITE(' New day- ');
  756.                 READ(items[found].day);
  757.           WRITELN;
  758.         END;
  759.     'A','a':BEGIN
  760.           WRITE(' New amount- ');
  761.            READ(number);
  762.           WRITELN;
  763.           items[found].amount:=STRTOFIX(number);
  764.         END;
  765.     'N','n':BEGIN
  766.           WRITE(' New name or description- ');
  767.           READLN(name);
  768.           WRITELN;
  769.           WHILE LENGTH(name)<>30 DO
  770.             APPEND(name,' ');
  771.           items[found].description:=name;
  772.         END;
  773.     'C','c':BEGIN
  774.           WRITE(' New code #- ');
  775.           READ(items[found].code);
  776.           WRITELN;
  777.         END;
  778.     END;
  779.   END;
  780. END;
  781.  
  782. PROCEDURE swap_items(item : INTEGER ; VAR swaped : BOOLEAN);
  783. { exchange file data at location with location+1 }
  784. BEGIN
  785.   items[max_items] := items[item];
  786.   items[item] := items[item+1];
  787.   items[item+1] := items[max_items];
  788.   swaped := TRUE
  789. END;
  790.  
  791. PROCEDURE date_sort;
  792. { sort data file by date }
  793. VAR finish , item : 0..max_items;
  794.     date_first , date_second : REAL;
  795.     item_first , item_second : INTEGER;
  796. BEGIN
  797.   finish := item_last-2;
  798.   REPEAT
  799.     swaped := FALSE;
  800.     FOR item := 1 TO finish DO
  801.     BEGIN
  802.       WITH items[item] DO
  803.        BEGIN
  804.          date_first := year * 10000.0 + month * 100.0 + day;
  805.          item_first := item_number;
  806.        END;
  807.       WITH items[item+1] DO
  808.         BEGIN
  809.           date_second := year * 10000.0 + month * 100.0 + day;
  810.           item_second := item_number;
  811.         END;
  812.       IF date_first > date_second THEN
  813.         swap_items(item,swaped);
  814.       IF (date_first = date_second) AND (item_first > item_second) THEN
  815.         swap_items(item,swaped);
  816.     END;
  817.       IF finish > 2 THEN
  818.         finish := finish -1;
  819.   UNTIL NOT swaped
  820. END;
  821.  
  822. PROCEDURE dump;
  823. { write file of item information to disk }
  824. VAR count : INTEGER;
  825. BEGIN
  826.   RESET(disk_file, data_file);
  827.   REWRITE(disk_file,data_file);
  828.   FOR count := 1 TO item_last DO
  829.     WRITE(data_file,items[count]);
  830. END;
  831.  
  832. PROCEDURE read_disk;
  833. { load data from disk to file }
  834. BEGIN
  835.   WRITELN;
  836.   RESET(disk_file,data_file);
  837.   item_last := 1;
  838.   REPEAT
  839.     READ(data_file,items[item_last]);
  840.     WRITE('.');
  841.     IF item_last MOD 10 = 0 THEN
  842.       WRITELN;
  843.     item_last := item_last + 1;
  844.   UNTIL items[item_last-1].item_number = 0;
  845.     item_last := item_last -1;
  846.     WRITELN;
  847. END;
  848.  
  849. PROCEDURE prog_commands;
  850. { console entry of program command }
  851. BEGIN
  852.     WRITELN;
  853.     WRITE(' Command ? ');
  854.     READ(command);
  855.     CASE command OF
  856.     'A','a' : entry;
  857.     'B','b' : print_balance;
  858.     'P','p' : print_all;
  859.     'R','r' : remove;
  860.     'S','s' : date_sort;
  861.     'D','d' : dump;
  862.     'L','l' : read_disk;
  863.     'M','m' : modify;
  864.     'H','h' : copy_all;
  865.     'I','i' : print_instructions;
  866.     'J','j' : kopy_balance;
  867.     ELSE :
  868.     IF (command = 'Q') OR (command ='q') THEN
  869.       WRITELN(' Leaving Program')
  870.     ELSE
  871.       WRITELN(' Invalid command .....')
  872.    END;
  873. END;
  874.  
  875. { Mainline Program }
  876. BEGIN
  877.     initialize;
  878.     instructions;
  879.     WRITELN;
  880.     WRITE(' Enter year " 2-digit " for new entries - ');
  881.     READ(entry_year);
  882.     WRITELN;
  883.     WRITELN;
  884.     REPEAT
  885.       prog_commands;
  886.     UNTIL (command = 'q') OR (command = 'Q');
  887.     WRITELN;
  888.     WRITE(' Save file ? ');
  889.     READ(answer);
  890.     IF (answer ='Y') OR (answer = 'y') THEN
  891.       dump;
  892. END.
  893.