home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 207_01 / checkd.c < prev    next >
Text File  |  1979-12-31  |  20KB  |  592 lines

  1. /*  checkd.c -- 5th source file for check register program                   */
  2.  
  3. /*  copyright (c) 1986 by Jim Woolley and WoolleyWare, San Jose, CA          */
  4.  
  5. /*  vers. 1.0, 12/85 thru 5/86
  6.  */
  7.  
  8. /*  this file contains:
  9.  *      delete()
  10.  *      undo()
  11.  *      insert()
  12.  *      ctrlqork()
  13.  *      erase( c)
  14.  *      abandon()
  15.  *      save()
  16.  *      reconcile()
  17.  *      abreviations()
  18.  *      print()
  19.  *      order()
  20.  *      reorder( f)
  21.  *      datemax( md, d)
  22.  */
  23.  
  24. #include    "a:checks.h"
  25.  
  26. delete()                                /*  delete Entry[ Recno]             */
  27. {
  28.     int r;
  29.  
  30.     if ( Recno > Maxentry)
  31.         return;
  32.     if ( isibbf( Recno))
  33.     {
  34.         prompt( "Cannot delete ");
  35.         puts( BBF);
  36.         waitesc();
  37.         return;
  38.     }
  39.     r = Recno - First + HEAD;
  40.     movmem( &Entry[ Recno], &Entryundo, RECSIZ);
  41.     Modified = Ctrlyundo = TRUE;
  42.     if ( Savrecno == Recno)
  43.         Savrecno = -1;
  44.     else if ( Savrecno > Recno)
  45.         --Savrecno;
  46.     if ( Recno < Maxentry)
  47.         movmem( &Entry[ Recno + 1], &Entry[ Recno], ( Maxentry - Recno)*RECSIZ);
  48.     --Maxentry;
  49.     if ( Maxentry < 0)
  50.     {
  51.         First = 0;
  52.         Last = Maxentry = -1;
  53.     }
  54.     else First = min( First, ( Last = min( Last, Maxentry)));
  55.     dellin( r);
  56.     update( Recno);
  57.     if ( Recno > Maxentry)
  58.         Field = 0;
  59.     putcursor( Recno, Field);
  60. }
  61.  
  62. undo()                                  /*  undo delete for Entry[ Recno]    */
  63. {
  64.     if ( Ctrlyundo && insert())
  65.     {
  66.         movmem( &Entryundo, &Entry[ Recno], RECSIZ);
  67.         putrecord( Recno);
  68.         update( Recno);
  69.         putcursor( Recno, Field);
  70.     }
  71. }
  72.  
  73. insert()                                /*  insert Entry[ Recno]             */
  74. {                                       /*  return TRUE if successful        */
  75.     int i;
  76.  
  77.     if ( Maxentry == ( ENTRYSIZE - 1))
  78.     {
  79.         prompt( "Number of entries is maximum allowed");
  80.         waitesc();
  81.         return ( FALSE);
  82.     }
  83.     if ( Recno <= Maxentry)
  84.     {
  85.         i = Maxentry - Recno + 1;
  86.         movmem( &Entry[ Recno], &Entry[ Recno + 1], i*RECSIZ);
  87.         movmem( &Balance[ Recno], &Balance[ Recno + 1], i*sizeof( Balance[ 0]));
  88.     }
  89.     if ( Savrecno >= Recno)
  90.         ++Savrecno;
  91.     ++Maxentry;
  92.     newentry( Recno);                   /*  Modified will be set TRUE        */
  93.     Last = min(( Last + 1), ( First + LAST));
  94.     inslin( Recno - First + HEAD);
  95.     putcursor( Recno, Field);
  96.     return ( TRUE);
  97. }
  98.  
  99. ctrlqork( c)                            /*  process CTRLQ or CTRLK command   */
  100. char c;
  101. {
  102.     char n;
  103.     int i;
  104.  
  105.     cursorto( 0, 2);
  106.     n = putnext();
  107.     if ( c == CTRLQ)                    /*  process CTRLQ command            */
  108.     {
  109.         switch ( n)
  110.         {
  111.         case 'R':
  112.             gotop();
  113.             break;
  114.         case 'C':
  115.             gobottom();
  116.             break;
  117.         case 'D':
  118.             if ( Recno > Maxentry)
  119.                 break;
  120.             Character = PAYEESIZE;      /*  putcursor() will readjust        */
  121.             putcursor( Recno, ( Field = MAXFIELD - 1));
  122.             break;
  123.         case 'S':  case 'H':
  124.             Character = 0;
  125.             putcursor( Recno, ( Field = 0));
  126.             break;
  127.         case 'E':
  128.             putcursor(( Recno = First), Field);
  129.             break;
  130.         case 'X':
  131.             Recno = min(( Maxentry + 1), ( First + ( LAST - 1)));
  132.             if ( Recno > Maxentry)
  133.                 Field = 0;
  134.             putcursor( Recno, Field);
  135.             break;
  136.         case 'Y':  case DEL:  case ( CTRL_ + CTRLTOA):
  137.             if ( Field == PAYFIELD)
  138.             {
  139.                 strcpy( Savpayee, Entry[ Recno].payee);
  140.                 Savrecno = Recno;
  141.                 putcursor( Recno, Field);
  142.                 erase( n);
  143.             }
  144.             break;
  145.         case 'W':  case 'Z':
  146.             goupdown( n);
  147.             break;
  148.         default:
  149.             putchar( BEL);
  150.             break;
  151.         }
  152.     }
  153.     else                                /*  process CTRLK command            */
  154.     {
  155.         switch ( n)
  156.         {
  157.         case 'O':
  158.             order( 0);
  159.             break;
  160.         case 'D':  case 'X':
  161.             done();                     /*  never returns                    */
  162.             break;
  163.         case 'S':
  164.             save();
  165.             break;
  166.         case 'Q':
  167.             abandon();                  /*  may not return                   */
  168.             break;
  169.         case 'R':
  170.             reconcile();
  171.             break;
  172.         case 'A':
  173.             abreviations();
  174.             break;
  175.         case 'P':
  176.             print();
  177.             break;
  178.         default:
  179.             putchar( BEL);
  180.             break;
  181.         }
  182.     }
  183. }
  184.  
  185. erase( c)                               /*  erase payee left or right        */
  186. char c;
  187. {
  188.     char *p, *q;
  189.     int count;
  190.  
  191.     q = Entry[ Recno].payee;
  192.     p = q + Character;
  193.     if ( c == 'Y')
  194.     {
  195.         count = strlen( p);
  196.         *p = '\0';
  197.     }
  198.     else if ( !Character)
  199.         return;
  200.     else
  201.     {
  202.         strcpy( q, p);
  203.         count = Character;
  204.         Character = 0;
  205.         putcursor( Recno, Field);
  206.         puts( q);
  207.     }
  208.     while ( count--)
  209.         putchar( PAYEEFILL);
  210.     Modified = TRUE;
  211. }
  212.  
  213. abandon()                               /*  abandon without resave           */
  214. {
  215.     if ( Modified)
  216.     {
  217.         prompt( "Abandon without saving changes (Y/N)? ");
  218.         if ( getyesno( NO))
  219.             aexit();
  220.     }
  221.     else
  222.     {
  223.         prompt( "Abandoning unchanged file");
  224.         aexit();
  225.     }
  226. }
  227.  
  228. save()                                  /*  save entries and continue        */
  229. {
  230.     prompt( "");                        /*  clear prompt line                */
  231.     if ( savedat())                     /*  if error                         */
  232.         return;
  233.     waitesc();                          /*  else, wait for recognition       */
  234.     Modified = FALSE;
  235. }
  236.  
  237. reconcile()                             /*  display summary by category      */
  238. {
  239.     char c, *spaces, *sh, *ss, scroll, nbr[ DEL];
  240.     int i, j, count, lines, firstline, lastline, maxline;
  241.     struct
  242.         {
  243.         struct calendar maxdate;
  244.         char sumcategory;
  245.         struct money beginbal, clrcheck, clrdeposit, allcheck, alldeposit;
  246.         } sum, *a, *start;
  247.     struct record *e;
  248.     struct money *m, clrendbal, allendbal;
  249.  
  250.     spaces = "           ";
  251.     sh =
  252. "--------  --------  --------  --------  --------  --------  --------";
  253.     ss = "-------- - ";
  254.     prompt( "");
  255.     setmem( nbr, DEL, 0);               /*  initialize                       */
  256.     for ( j = 0; j <= Maxentry; ++j)    /*  count number in each category    */
  257.         ++nbr[ Entry[ j].category & 0x7f];
  258.     lines = 0;
  259.     for ( i = ' '; i < DEL; ++i)        /*  count separate categories, then  */
  260.         if ( nbr[ i])                   /*      allocate space for each      */
  261.             ++lines;
  262.     if ( !lines)
  263.         return;
  264.     if ( !( a = start = alloc( lines*sizeof( *a))))
  265.     {
  266.         prompt( "Insufficient memory to reconcile all categories");
  267.         waitesc();
  268.         return;
  269.     }
  270.     recheading( ss, sh);
  271.     setmem( &sum, sizeof( sum), 0);      /*  initialize                       */
  272.     setmem( a, ( lines*sizeof( *a)), 0);
  273.     for ( i = ' '; i < DEL; ++i)        /*  summarize each category          */
  274.     {
  275.         if ( !nbr[ i])                  /*  if category does not exist       */
  276.             continue;                   /*      next category                */
  277.         a->sumcategory = i;
  278.         count = 0;
  279.         for ( j = 0; j <= Maxentry; ++j)
  280.         {                               /*  loop thru entries                */
  281.             e = &Entry[ j];
  282.             if ((( c = e->category) & 0x7f) != i)
  283.                 continue;               /*  next entry                       */
  284.             datemax( &( a->maxdate), &( e->date));
  285.             m = &( e->amount);
  286.             if ( c & 0x80)              /*  if a BBF entry                   */
  287.                 addmoney( &a->beginbal, &a->beginbal, m, e->deposit);
  288.             else                        /*  not a BBF entry                  */
  289.             {
  290.                 if ( e->deposit)        /*  if a deposit                     */
  291.                 {
  292.                     addmoney( &a->alldeposit, &a->alldeposit, m, TRUE);
  293.                     if ( e->clear)
  294.                         addmoney( &a->clrdeposit, &a->clrdeposit, m, TRUE);
  295.                 }
  296.                 else                    /*  not a deposit                    */
  297.                 {
  298.                     addmoney( &a->allcheck, &a->allcheck, m, TRUE);
  299.                     if ( e->clear)
  300.                         addmoney( &a->clrcheck, &a->clrcheck, m, TRUE);
  301.                 }
  302.             }
  303.             if ( ++count == nbr[ i])    /*  if all entries for this category */
  304.                 break;                  /*      break j loop over entries    */
  305.         }                               /*  end j loop over entries          */
  306.         datemax( &( sum.maxdate), &( a->maxdate));
  307.         addmoney( &sum.beginbal, &sum.beginbal, &a->beginbal, TRUE);
  308.         addmoney( &sum.alldeposit, &sum.alldeposit, &a->alldeposit, TRUE);
  309.         addmoney( &sum.clrdeposit, &sum.clrdeposit, &a->clrdeposit, TRUE);
  310.         addmoney( &sum.allcheck, &sum.allcheck, &a->allcheck, TRUE);
  311.         addmoney( &sum.clrcheck, &sum.clrcheck, &a->clrcheck, TRUE);
  312.         ++a;                            /*  next summary line                */
  313.     }                                   /*  end i loop over categories       */
  314.     firstline = i = 0;
  315.     maxline = lines + 1;
  316.     lastline = min( maxline, ( LAST - 1));
  317.     Printing = scroll = FALSE;
  318.     FOREVER                             /*  begin display loop               */
  319.     {
  320.         cursorto((( HEAD + 1) + i - firstline), 0);
  321.         if ( i == lines)
  322.         {
  323.             puts( spaces);
  324.             puts( sh);
  325.         }
  326.         else
  327.         {
  328.             if ( i < lines)
  329.             {
  330.                 a = start + i;
  331.                 c = a->sumcategory;
  332.             }
  333.             else
  334.             {
  335.                 a = ∑
  336.                 c = ' ';
  337.             }
  338.             putdate( &( a->maxdate));
  339.             putchar( c);
  340.             addmoney( &clrendbal, &a->beginbal, &a->clrcheck, FALSE);
  341.             addmoney( &clrendbal, &clrendbal, &a->clrdeposit, TRUE);
  342.             addmoney( &allendbal, &a->beginbal, &a->allcheck, FALSE);
  343.             addmoney( &allendbal, &allendbal, &a->alldeposit, TRUE);
  344.             putchar( ' ');
  345.             putmoney( &a->beginbal);
  346.             putchar( ' ');
  347.             putmoney( &a->clrcheck);
  348.             putchar( ' ');
  349.             putmoney( &a->clrdeposit);
  350.             putchar( ' ');
  351.             putmoney( &clrendbal);
  352.             putchar( ' ');
  353.             putmoney( &a->allcheck);
  354.             putchar( ' ');
  355.             putmoney( &a->alldeposit);
  356.             putchar( ' ');
  357.             putmoney( &allendbal);
  358.         }
  359.         if ( Printing)
  360.         {
  361.             if ( ++i > maxline)
  362.             {
  363.                 resetlst();
  364.                 i = count;              /*  reset line index                 */
  365.             }
  366.         }
  367.         else if ( !( scroll = ( scroll || i == lastline)))
  368.         {
  369.             ++i;                        /*  fill screen                      */
  370.             scroll |= ( kbhit() && firstline && lastline < maxline);
  371.         }
  372.         else
  373.         {
  374.             prompt( "");
  375.             if ( firstline)             /*  if line 0 is off screen          */
  376.                 puts( "^W to see prior, ");
  377.             if ( lastline < maxline)    /*  if final line is off screen      */
  378.                 puts( "^Z to see next, ");
  379.             puts( "^P to print, or ESCAPE to see full register");
  380.             FOREVER                     /*  loop until valid key             */
  381.             {
  382.                 if (( c = getchar()) == CTRLW && firstline)
  383.                 {
  384.                     i = --firstline;
  385.                     --lastline;
  386.                     if ( !linins( HEAD + 1))
  387.                         scroll = FALSE;
  388.                     break;              /*  break FOREVER loop               */
  389.                 }
  390.                 else if ( c == CTRLZ && lastline < maxline)
  391.                 {
  392.                     ++firstline;
  393.                     i = ++lastline;
  394.                     if ( !lindel( HEAD + 1))
  395.                     {
  396.                         i = firstline;
  397.                         scroll = FALSE;
  398.                     }
  399.                     break;              /*  break FOREVER loop               */
  400.                 }
  401.                 else if ( c == CTRLP)
  402.                 {
  403.                     if ( setlst())
  404.                     {
  405.                         recheading( ss, sh);
  406.                         count = i;      /*  save current line index          */
  407.                         i = 0;
  408.                     }
  409.                     break;              /*  break FOREVER loop               */
  410.                 }
  411.                 else if ( c == ESC)
  412.                 {
  413.                     free( start);
  414.                     clrscr();
  415.                     disheading();
  416.                     display( First);
  417.                     return;
  418.                 }
  419.             }                           /*  end FOREVER loop until valid key */
  420.         }                               /*  end if ... else scroll test      */
  421.     }                                   /*  end FOREVER display loop         */
  422. }                                       /*  end reconcile()                  */
  423.  
  424. abreviations()                          /*  display installed abreviations   */
  425. {
  426.     char c, scroll;
  427.     int i, lines, hashval, firstline, lastline, compabrev();
  428.     struct nlist *np, **start;
  429.  
  430.     prompt( "");
  431.     lines = 0;                          /*  allocate abrev pointer space     */
  432.     for ( hashval = 0; hashval < HASHSIZE; ++hashval)
  433.         for ( np = Hashtab[ hashval]; np; np = np->next)
  434.             ++lines;                    /*  count abreviations               */
  435.     if ( !lines)
  436.     {
  437.         prompt( "There are no abreviations installed");
  438.         goto quit;
  439.     }
  440.     if ( !( start = alloc( lines*sizeof( np))))
  441.     {
  442.         prompt( "Insufficient memory to display all abreviations");
  443. quit:   waitesc();
  444.         return;
  445.     }
  446.     clrscr();
  447.     putscr( Ivon);
  448.     puttitle();
  449.     puts(
  450. "            Abreviation  Payee                                                 "
  451.          );
  452.     putchar( '\n');
  453.     puts(
  454. "            -----------  ------------------------------------------            "
  455.          );
  456.     putscr( Ivoff);
  457.     i = 0;
  458.     for ( hashval = 0; hashval < HASHSIZE; ++hashval)
  459.         for ( np = Hashtab[ hashval]; np; np = np->next)
  460.             *( start + ( i++)) = np;    /*  save pointer to each abreviation */
  461.     qsort( start, lines, sizeof( np), compabrev);
  462.     firstline = i = 0;
  463.     lastline = min( --lines, LAST);
  464.     scroll = FALSE;
  465.     FOREVER                             /*  begin display loop               */
  466.     {
  467.         cursorto(( HEAD + i - firstline), 0);
  468.         np = *( start + i);
  469.         puts( "                ");
  470.         puts( np->abrev);
  471.         puts( "      ");
  472.         puts ( np->fullname);
  473.         if ( !( scroll = ( scroll || i == lastline)))
  474.         {
  475.             ++i;                        /*  fill screen                      */
  476.             scroll |= ( kbhit() && firstline && lastline < lines);
  477.         }
  478.         else
  479.         {
  480.             prompt( "");
  481.             if ( firstline)             /*  if line 0 is off screen          */
  482.                 puts( "^W to see prior, or ");
  483.             if ( lastline < lines)      /*  if final line is off screen  */
  484.                 puts( "^Z to see next, or ");
  485.             puts( "ESCAPE to see full register");
  486.             FOREVER                     /*  loop until valid key             */
  487.             {
  488.                 if (( c = getchar()) == CTRLW && firstline)
  489.                 {
  490.                     i = --firstline;
  491.                     --lastline;
  492.                     if ( !linins( HEAD))
  493.                         scroll = FALSE;
  494.                     break;              /*  break FOREVER loop               */
  495.                 }
  496.                 else if ( c == CTRLZ && lastline < lines)
  497.                 {
  498.                     ++firstline;
  499.                     i = ++lastline;
  500.                     if ( !lindel( HEAD))
  501.                     {
  502.                         i = firstline;
  503.                         scroll = FALSE;
  504.                     }
  505.                     break;              /*  break FOREVER loop               */
  506.                 }
  507.                 else if ( c == ESC)
  508.                 {
  509.                     free( start);
  510.                     clrscr();
  511.                     disheading();
  512.                     display( First);
  513.                     return;
  514.                 }
  515.             }                           /*  end FOREVER loop until valid key */
  516.         }                               /*  end if ... else scroll test      */
  517.     }                                   /*  end FOREVER display loop         */
  518. }                                       /*  end abreviations()               */
  519.  
  520. print()                                 /*  print entries                    */
  521. {
  522.     int i;
  523.  
  524.     if ( setlst())
  525.     {
  526.         disheading();
  527.         for ( i = 0; i <= Maxentry; ++i)
  528.             putrecord( i);              /*  cannot use display()             */
  529.         resetlst();
  530.     }
  531. }
  532.  
  533. order( i)                               /*  reorder entries i to Maxentry    */
  534. int i;
  535. {
  536.     char c;
  537.     int compdate(), comppayee(), compcateg(), compamount(), ( *f)();
  538.  
  539.     prompt(
  540. "Order entries by Date, Payee, Category, Amount, or Neither (D/P/C/A/N)? N"
  541.            );
  542.     putchar( '\b');
  543.     switch ( c = toupper( getchar()))
  544.     {
  545.     case 'D':
  546.         f = compdate;
  547.         break;
  548.     case 'P':
  549.         f = comppayee;
  550.         break;
  551.     case 'C':
  552.         f = compcateg;
  553.         break;
  554.     case 'A':
  555.         f = compamount;
  556.         break;
  557.     default:
  558.         c = 0;
  559.         break;
  560.     }
  561.     if ( c)
  562.     {
  563.         putchar( c);
  564.         reorder( i, f);
  565.     }
  566. }
  567.  
  568. reorder( i, f)                          /*  reorder from i using function f  */
  569. int i, ( *f)();
  570. {
  571.     qsort( &Entry[ i], ( Maxentry - i + 1), RECSIZ, f);
  572.     for ( ; i <= Maxentry; ++i)    /*  update balance and display            */
  573.     {
  574.         newbalance( i);
  575.         if ( First <= i && i <= Last)
  576.             putrecord( i);
  577.     }
  578.     Character = 0;                      /*  avoid dangling cursor            */
  579. }
  580.  
  581. datemax( md, d)                         /*  determine max date               */
  582. struct calendar *md;                    /*  max date                         */
  583. struct calendar *d;                     /*  trial date                       */
  584. {
  585.     if ( datecomp( md, d) < 0)
  586.     {
  587.         md->mm = d->mm;
  588.         md->dd = d->dd;
  589.         md->yy = d->yy;
  590.     }
  591. }
  592.