home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / PROCWRKB.ZIP / BENCH1.ZIP / GENSUP / ADD.C next >
Encoding:
C/C++ Source or Header  |  1990-08-27  |  8.8 KB  |  433 lines

  1. /* ==( gensup/add.c )== */
  2. /* ----------------------------------------------- */
  3. /* Pro-C  Copyright (C) 1988 - 1990 Vestronix Inc. */
  4. /* Modification to this source is not supported    */
  5. /* by Vestronix Inc.                               */
  6. /*            All Rights Reserved                  */
  7. /* ----------------------------------------------- */
  8. /* Written   Nig   1-Jan-90                        */
  9. /* Modified  Nig   1-Jan-90                        */
  10. /* ----------------------------------------------- */
  11. /* %W%  (%H% %T%) */
  12.  
  13.  
  14. # include <stdio.h>
  15. # include <bench.h>
  16. # include <proc.io>
  17. # include "field.h"
  18. # include "iodef.h"
  19. # include "sup.h"
  20. # include "screen.h"
  21. # include "passwd.h"
  22.  
  23. extern int tot_size;
  24. extern int pending;
  25.  
  26. /*
  27.  * Driving ADD Mode Logic
  28.  *
  29.  * Start by hitting ADD KEY, and record is 
  30.  * actually added by hitting ADD KEY again
  31. */
  32. int add_mode(tab, head, lptr, table, mode)
  33. struct _table *tab;
  34. struct a_line **head, **lptr;
  35. int table, mode;
  36. {
  37.     int stat, try = 0, omsg;
  38.     struct a_line *tmp, *top = ANULL;
  39.     int curidx, deltmp;
  40.  
  41.     if (!(tab->perms & PERM_ADD))
  42.     {
  43.         errmsg(ErrNoAdd);
  44.         return (IOPERM);
  45.     }
  46.  
  47.     /*
  48.      * Switch on Transaction Processing for the duration
  49.     */
  50.     if (tab->tp)
  51.         tran_p(tab);
  52.  
  53.     /*
  54.      * In Add mode, we are adding new items on
  55.      * to the list.  With multiple records on the
  56.      * page, we add to max depth, then scroll the 
  57.      * list up.
  58.     */
  59.     do
  60.     {
  61.         /*
  62.          * Take copy of top record, in case
  63.          * the user aborts the add.
  64.         */
  65.         if (*head != ANULL)
  66.         {
  67.             top = *head;
  68.  
  69.             deltmp = (*head)->deleted;
  70.             curidx = *(tab->index);     /* save this for later */
  71.         }
  72.  
  73.         /*
  74.          * Work out the index to add to
  75.         */
  76.         for (*(tab->index) = 0, tmp = *head; tmp != ANULL; (*(tab->index))++, tmp = tmp->next)
  77.             ;
  78.  
  79.         /*
  80.          * Bottom of list, so scroll around
  81.         */
  82.         if (tab->maximum > 1)
  83.             while (*(tab->index) >= tab->maximum)
  84.             {
  85.                 if ((*head)->next != ANULL)
  86.                     (*head) = (*head)->next;
  87.                 (*(tab->index))--;
  88.             }
  89.         else
  90.             (*(tab->index)) = 0;
  91.  
  92.         /*
  93.          * Allocate space for the new record
  94.         */
  95.         *(tab->seq) = ASCENDING;
  96.         new_record(tab, head, lptr);
  97.  
  98.         (*lptr)->deleted = TRUE;
  99.  
  100.         shuffle_down(tab, head, lptr, mode);
  101.  
  102.         (*lptr)->deleted = FALSE;
  103.  
  104.         /*
  105.          * If required, to copy the previous record's 
  106.          * values into the current record as defaults,
  107.          * then swap these over.
  108.          *
  109.            * 1 : bytecpy((*lptr)->rec, tab->rec, tab->size);
  110.          *
  111.          * 2 : zerorec(tab->rec, tab->size);
  112.          *     if (tab->dsp_fn != (void (*)())0) 
  113.            *        (*tab->dsp_fn)(UNDERLINED, CLR);
  114.         */
  115.         zerorec(tab->rec, tab->size);
  116.         if (tab->dsp_fn != (void (*)())0) 
  117.               (*tab->dsp_fn)(UNDERLINED, CLR);
  118.     }
  119.     while ((*tab->inp_fn)(ADD, tab, head, lptr, table) != FALSE);
  120.  
  121.     /*
  122.      * If the user aborts the add having already performed
  123.      * the auto-increment, then we need to remove the pre-added
  124.      * record from the file.  Re-find it - NIG.
  125.     */
  126.     if ((*lptr)->curr != ANULL)
  127.     {
  128.         /*
  129.          * Lock it  ( it better be unique )
  130.         */
  131.         bytecpy(tab->rec, (*lptr)->curr->rec, tab->size);
  132.         stat = findkey(tab->fd, tab->rec);
  133.         /*
  134.          * Then delete it
  135.         */
  136.         if (stat == IOGOOD)
  137.             stat = removerec(tab->fd, tab->rec);
  138.  
  139.         free ((*lptr)->curr);
  140.         (*lptr)->curr = ANULL;
  141.     }
  142.  
  143.     /*
  144.      * erase the aborted record and its xrefs
  145.     */
  146.     if (tab->tabno > 1)
  147.     {
  148.         (*lptr)->deleted = TRUE;
  149.         if (tab->dsp_fn != (void (*)())0) 
  150.               (*tab->dsp_fn)(UNDERLINED, DSP);
  151.     }
  152.  
  153.     /*
  154.      * Commit any pending transactions
  155.     */
  156.     if (tab->tp)
  157.         comm_p(tab);
  158.  
  159.     /*
  160.      * We need to reset the key search order in case an
  161.      * auto increment was performed
  162.     */
  163.       selectinx(tab->fd, *(tab->keynum), *(tab->keymatch), tab->retry);
  164.  
  165.     /*
  166.      * If we have a depth of just 1, then we can copy
  167.      * the previous record's values into the current 
  168.      * record when they abort the add.
  169.      *
  170.      * If the depth is greater than 1, then the top of
  171.      * page is saved each time a record is added
  172.      * and is restored upon exit, thus restoring the
  173.      * full page of display.
  174.     */
  175.     shuffle_up(tab, head, lptr);
  176.  
  177.     if (top != ANULL)
  178.     {
  179.         *head = top;
  180.           bytecpy(tab->rec, (*head)->rec, tab->size);
  181.         
  182.         (*head)->deleted = deltmp;
  183.         top = ANULL;
  184.     }
  185.  
  186.     /*
  187.      * reset that which was previously saved
  188.      * *lptr is set in the process as well
  189.     */
  190.     for ( *(tab->index) = 0, *lptr = *head;
  191.             *(tab->index) != curidx && *lptr != ANULL;
  192.             (*(tab->index))++, *lptr = (*lptr)->next )
  193.         ;
  194.  
  195.     if (*lptr != ANULL)
  196.     {
  197.         /*
  198.           * Re-find the current record
  199.         */
  200.           bytecpy(tab->rec, (*lptr)->rec, tab->size);
  201.  
  202.         stat = findkey(tab->fd, tab->rec);
  203.  
  204.         ulock_rec(tab->fd, tab->rec);
  205.  
  206.         if (stat != IOGOOD)
  207.             return (do_error(stat));
  208.  
  209.         /*
  210.          * If we didn't find right one,
  211.          * we better make sure the one we found
  212.          * is the current one.
  213.          * Also, since it's not the right one,
  214.          * might as well make it the top one in the list
  215.          * - will often get lucky, and this will be the previous top record,
  216.          * - or it will be easier for the user to use next & prevs
  217.          *   to re-order the list properly.
  218.         */
  219.         if (cmp_rec(tab, *lptr) != 0)
  220.         {
  221.             if (tab->messages)
  222.                 errmsg(NoCurrEst);
  223.  
  224.             bytecpy(tab->rec, (*head)->rec, tab->size);
  225.             /* bytecpy((*head)->rec, tab->rec, tab->size); */
  226.  
  227.             /*
  228.              * This call to fill_list will perform the same
  229.              * lookups as the call from the generated proggy
  230.              * due to the Table Driven nature of these funcs.
  231.             */
  232.             fill_list_mode(tab, head, lptr);
  233.  
  234.             *lptr = *head;
  235.             *(tab->index) = 0;
  236.         }
  237.     }
  238.  
  239.     do_page_mode(tab, head, lptr, mode);
  240.  
  241.     return (IOGOOD);
  242. }
  243.  
  244. /*
  245.  * Add a new record to the file
  246. */
  247. int add_record(tab, head, lptr)
  248. struct _table *tab;
  249. struct a_line **head, **lptr;
  250. {
  251.     int stat;
  252.  
  253.     if (*lptr == ANULL)
  254.         return (FALSE);
  255.  
  256.    /* 
  257.      * Confirm the Addition
  258.     */
  259.     if (tab->query_box && !warning (99, AddConfirm))
  260.         return (FALSE);
  261.  
  262.     /*
  263.      * Copy record to be added into list
  264.     */
  265.     bytecpy((*lptr)->rec, tab->rec, tab->size);
  266.  
  267.     /*
  268.      * Free up curr pointer if necessary.
  269.      * Only set on Auto-Add in add mode.
  270.      * If Set, then update the record, as
  271.      * one has been pre-added, else simply
  272.      * add the record.  Re-find - NIG.
  273.     */
  274.     no_msg = !(tab->messages);
  275.  
  276.     if ((*lptr)->curr != ANULL)
  277.     {
  278.         /*
  279.          * Save it
  280.         */
  281.         bytecpy((*lptr)->rec, tab->rec, tab->size);
  282.         bytecpy(tab->rec, (*lptr)->curr->rec, tab->size);
  283.         /*
  284.          * Lock it  ( It better be unique )
  285.         */
  286.         selectinx(tab->fd, tab->uniquekey, *(tab->keymatch), -1);
  287.  
  288.         stat = findkey(tab->fd, tab->rec);
  289.         /*
  290.          * Then update it
  291.         */
  292.         if (stat == IOGOOD)
  293.         {
  294.             int k;
  295.  
  296.             k = cmp_rec(tab, (*lptr)->curr);
  297.  
  298.             if (k == 0 || (k != 0 && warning(-1, WrongRec)))
  299.             {
  300.                 bytecpy(tab->rec, (*lptr)->rec, tab->size);
  301.                 stat = updrec(tab->fd, tab->rec);
  302.             }
  303.  
  304.             free ((*lptr)->curr);
  305.             (*lptr)->curr = ANULL;
  306.         }
  307.     }
  308.     else
  309.         stat = appendrec(tab->fd, tab->rec);
  310.  
  311.     if (do_error(stat) != IOGOOD)
  312.         return (FALSE);
  313.  
  314.     /*
  315.      * Paranoid Unlocking
  316.     */
  317.     ulock_rec(tab->fd, tab->rec);
  318.  
  319.     /*
  320.      * Commit or Rollback the pending operations
  321.     */
  322.     pending = TRUE;
  323.  
  324.     if (tab->tp)
  325.     {
  326.         if (stat == IOGOOD)
  327.             comm_p(tab);
  328.         else
  329.             roll_p(tab);
  330.     }
  331.  
  332.     if (do_error(stat) == IOGOOD)
  333.         return (TRUE);
  334.  
  335.     return (FALSE);
  336. }
  337.  
  338.  
  339. /*
  340.  * Only called by add mode, to seek to the end 
  341.  * of the list before adding the next record.
  342. */
  343. void shuffle_down(tab, head, lptr, mode)
  344. struct _table *tab;
  345. struct a_line **head, **lptr;
  346. int mode;
  347. {
  348.     struct a_line *tmp, *tmp2;
  349.     int i, j;
  350.  
  351.     /*
  352.      * Find beginning of list
  353.     */
  354.     if (*head != ANULL)
  355.         for (tmp = *head; tmp->prev != ANULL; tmp = tmp->prev)
  356.             ;
  357.  
  358.     tmp2 = tmp;
  359.  
  360.     for ( ; tmp != ANULL; tmp = tmp->next)
  361.         j = i = tmp->index;
  362.  
  363.     /*
  364.      * Adjust current head if necessary
  365.     */
  366.     for (*head = tmp2 ; i >= tab->maximum; i--)
  367.         *head = (*head)->next;
  368.  
  369.     /*
  370.      * For Main Tables, eliminate excess records
  371.      * above the head !!
  372.     */
  373.     if (tab->tabno == 1 && j > tab->maximum)
  374.     {
  375.         struct a_line *nxt;
  376.  
  377.         while (tmp2 != (*head)->prev)
  378.         {
  379.             nxt = tmp2->next;
  380.             nxt->prev = ANULL;
  381.  
  382.             free (tmp2);
  383.             tmp2 = ANULL;
  384.             tmp2 = nxt;
  385.         }
  386.         for (i = 0; tmp2 != ANULL; tmp2 = tmp2->next)
  387.             tmp2->index = i++;
  388.     }
  389.  
  390.     if (tab->maximum > 1)
  391.         do_page_mode(tab, head, lptr, mode);
  392.     else
  393.         if (tab->dsp_fn != (void (*)())0) 
  394.               (*tab->dsp_fn)(UNDERLINED, CLR);
  395. }
  396.  
  397.  
  398. /*
  399.  * Delete un-added entry from the list
  400. */
  401. void shuffle_up(tab, head, lptr)
  402. struct _table *tab;
  403. struct a_line **head, **lptr;
  404. {
  405.     struct a_line *tmp;
  406.  
  407.     tmp = (*lptr)->prev;
  408.  
  409.     /*
  410.      * Reset pointers at end & top of list
  411.     */
  412.     if (tmp != ANULL)
  413.         tmp->next = ANULL;
  414.  
  415.     if (*head != ANULL)
  416.     {
  417.         while ((*head)->prev != ANULL)
  418.             *head = (*head)->prev;
  419.     }
  420.     
  421.     if (*head == *lptr)
  422.     {
  423.         free (*head);
  424.         *head = ANULL;
  425.     }
  426.     else
  427.     {
  428.         free (*lptr);
  429.         *lptr = ANULL;
  430.     }
  431. }
  432.  
  433.