home *** CD-ROM | disk | FTP | other *** search
- /* ==( gensup/add.c )== */
- /* ----------------------------------------------- */
- /* Pro-C Copyright (C) 1988 - 1990 Vestronix Inc. */
- /* Modification to this source is not supported */
- /* by Vestronix Inc. */
- /* All Rights Reserved */
- /* ----------------------------------------------- */
- /* Written Nig 1-Jan-90 */
- /* Modified Nig 1-Jan-90 */
- /* ----------------------------------------------- */
- /* %W% (%H% %T%) */
-
-
- # include <stdio.h>
- # include <bench.h>
- # include <proc.io>
- # include "field.h"
- # include "iodef.h"
- # include "sup.h"
- # include "screen.h"
- # include "passwd.h"
-
- extern int tot_size;
- extern int pending;
-
- /*
- * Driving ADD Mode Logic
- *
- * Start by hitting ADD KEY, and record is
- * actually added by hitting ADD KEY again
- */
- int add_mode(tab, head, lptr, table, mode)
- struct _table *tab;
- struct a_line **head, **lptr;
- int table, mode;
- {
- int stat, try = 0, omsg;
- struct a_line *tmp, *top = ANULL;
- int curidx, deltmp;
-
- if (!(tab->perms & PERM_ADD))
- {
- errmsg(ErrNoAdd);
- return (IOPERM);
- }
-
- /*
- * Switch on Transaction Processing for the duration
- */
- if (tab->tp)
- tran_p(tab);
-
- /*
- * In Add mode, we are adding new items on
- * to the list. With multiple records on the
- * page, we add to max depth, then scroll the
- * list up.
- */
- do
- {
- /*
- * Take copy of top record, in case
- * the user aborts the add.
- */
- if (*head != ANULL)
- {
- top = *head;
-
- deltmp = (*head)->deleted;
- curidx = *(tab->index); /* save this for later */
- }
-
- /*
- * Work out the index to add to
- */
- for (*(tab->index) = 0, tmp = *head; tmp != ANULL; (*(tab->index))++, tmp = tmp->next)
- ;
-
- /*
- * Bottom of list, so scroll around
- */
- if (tab->maximum > 1)
- while (*(tab->index) >= tab->maximum)
- {
- if ((*head)->next != ANULL)
- (*head) = (*head)->next;
- (*(tab->index))--;
- }
- else
- (*(tab->index)) = 0;
-
- /*
- * Allocate space for the new record
- */
- *(tab->seq) = ASCENDING;
- new_record(tab, head, lptr);
-
- (*lptr)->deleted = TRUE;
-
- shuffle_down(tab, head, lptr, mode);
-
- (*lptr)->deleted = FALSE;
-
- /*
- * If required, to copy the previous record's
- * values into the current record as defaults,
- * then swap these over.
- *
- * 1 : bytecpy((*lptr)->rec, tab->rec, tab->size);
- *
- * 2 : zerorec(tab->rec, tab->size);
- * if (tab->dsp_fn != (void (*)())0)
- * (*tab->dsp_fn)(UNDERLINED, CLR);
- */
- zerorec(tab->rec, tab->size);
- if (tab->dsp_fn != (void (*)())0)
- (*tab->dsp_fn)(UNDERLINED, CLR);
- }
- while ((*tab->inp_fn)(ADD, tab, head, lptr, table) != FALSE);
-
- /*
- * If the user aborts the add having already performed
- * the auto-increment, then we need to remove the pre-added
- * record from the file. Re-find it - NIG.
- */
- if ((*lptr)->curr != ANULL)
- {
- /*
- * Lock it ( it better be unique )
- */
- bytecpy(tab->rec, (*lptr)->curr->rec, tab->size);
- stat = findkey(tab->fd, tab->rec);
- /*
- * Then delete it
- */
- if (stat == IOGOOD)
- stat = removerec(tab->fd, tab->rec);
-
- free ((*lptr)->curr);
- (*lptr)->curr = ANULL;
- }
-
- /*
- * erase the aborted record and its xrefs
- */
- if (tab->tabno > 1)
- {
- (*lptr)->deleted = TRUE;
- if (tab->dsp_fn != (void (*)())0)
- (*tab->dsp_fn)(UNDERLINED, DSP);
- }
-
- /*
- * Commit any pending transactions
- */
- if (tab->tp)
- comm_p(tab);
-
- /*
- * We need to reset the key search order in case an
- * auto increment was performed
- */
- selectinx(tab->fd, *(tab->keynum), *(tab->keymatch), tab->retry);
-
- /*
- * If we have a depth of just 1, then we can copy
- * the previous record's values into the current
- * record when they abort the add.
- *
- * If the depth is greater than 1, then the top of
- * page is saved each time a record is added
- * and is restored upon exit, thus restoring the
- * full page of display.
- */
- shuffle_up(tab, head, lptr);
-
- if (top != ANULL)
- {
- *head = top;
- bytecpy(tab->rec, (*head)->rec, tab->size);
-
- (*head)->deleted = deltmp;
- top = ANULL;
- }
-
- /*
- * reset that which was previously saved
- * *lptr is set in the process as well
- */
- for ( *(tab->index) = 0, *lptr = *head;
- *(tab->index) != curidx && *lptr != ANULL;
- (*(tab->index))++, *lptr = (*lptr)->next )
- ;
-
- if (*lptr != ANULL)
- {
- /*
- * Re-find the current record
- */
- bytecpy(tab->rec, (*lptr)->rec, tab->size);
-
- stat = findkey(tab->fd, tab->rec);
-
- ulock_rec(tab->fd, tab->rec);
-
- if (stat != IOGOOD)
- return (do_error(stat));
-
- /*
- * If we didn't find right one,
- * we better make sure the one we found
- * is the current one.
- * Also, since it's not the right one,
- * might as well make it the top one in the list
- * - will often get lucky, and this will be the previous top record,
- * - or it will be easier for the user to use next & prevs
- * to re-order the list properly.
- */
- if (cmp_rec(tab, *lptr) != 0)
- {
- if (tab->messages)
- errmsg(NoCurrEst);
-
- bytecpy(tab->rec, (*head)->rec, tab->size);
- /* bytecpy((*head)->rec, tab->rec, tab->size); */
-
- /*
- * This call to fill_list will perform the same
- * lookups as the call from the generated proggy
- * due to the Table Driven nature of these funcs.
- */
- fill_list_mode(tab, head, lptr);
-
- *lptr = *head;
- *(tab->index) = 0;
- }
- }
-
- do_page_mode(tab, head, lptr, mode);
-
- return (IOGOOD);
- }
-
- /*
- * Add a new record to the file
- */
- int add_record(tab, head, lptr)
- struct _table *tab;
- struct a_line **head, **lptr;
- {
- int stat;
-
- if (*lptr == ANULL)
- return (FALSE);
-
- /*
- * Confirm the Addition
- */
- if (tab->query_box && !warning (99, AddConfirm))
- return (FALSE);
-
- /*
- * Copy record to be added into list
- */
- bytecpy((*lptr)->rec, tab->rec, tab->size);
-
- /*
- * Free up curr pointer if necessary.
- * Only set on Auto-Add in add mode.
- * If Set, then update the record, as
- * one has been pre-added, else simply
- * add the record. Re-find - NIG.
- */
- no_msg = !(tab->messages);
-
- if ((*lptr)->curr != ANULL)
- {
- /*
- * Save it
- */
- bytecpy((*lptr)->rec, tab->rec, tab->size);
- bytecpy(tab->rec, (*lptr)->curr->rec, tab->size);
- /*
- * Lock it ( It better be unique )
- */
- selectinx(tab->fd, tab->uniquekey, *(tab->keymatch), -1);
-
- stat = findkey(tab->fd, tab->rec);
- /*
- * Then update it
- */
- if (stat == IOGOOD)
- {
- int k;
-
- k = cmp_rec(tab, (*lptr)->curr);
-
- if (k == 0 || (k != 0 && warning(-1, WrongRec)))
- {
- bytecpy(tab->rec, (*lptr)->rec, tab->size);
- stat = updrec(tab->fd, tab->rec);
- }
-
- free ((*lptr)->curr);
- (*lptr)->curr = ANULL;
- }
- }
- else
- stat = appendrec(tab->fd, tab->rec);
-
- if (do_error(stat) != IOGOOD)
- return (FALSE);
-
- /*
- * Paranoid Unlocking
- */
- ulock_rec(tab->fd, tab->rec);
-
- /*
- * Commit or Rollback the pending operations
- */
- pending = TRUE;
-
- if (tab->tp)
- {
- if (stat == IOGOOD)
- comm_p(tab);
- else
- roll_p(tab);
- }
-
- if (do_error(stat) == IOGOOD)
- return (TRUE);
-
- return (FALSE);
- }
-
-
- /*
- * Only called by add mode, to seek to the end
- * of the list before adding the next record.
- */
- void shuffle_down(tab, head, lptr, mode)
- struct _table *tab;
- struct a_line **head, **lptr;
- int mode;
- {
- struct a_line *tmp, *tmp2;
- int i, j;
-
- /*
- * Find beginning of list
- */
- if (*head != ANULL)
- for (tmp = *head; tmp->prev != ANULL; tmp = tmp->prev)
- ;
-
- tmp2 = tmp;
-
- for ( ; tmp != ANULL; tmp = tmp->next)
- j = i = tmp->index;
-
- /*
- * Adjust current head if necessary
- */
- for (*head = tmp2 ; i >= tab->maximum; i--)
- *head = (*head)->next;
-
- /*
- * For Main Tables, eliminate excess records
- * above the head !!
- */
- if (tab->tabno == 1 && j > tab->maximum)
- {
- struct a_line *nxt;
-
- while (tmp2 != (*head)->prev)
- {
- nxt = tmp2->next;
- nxt->prev = ANULL;
-
- free (tmp2);
- tmp2 = ANULL;
- tmp2 = nxt;
- }
- for (i = 0; tmp2 != ANULL; tmp2 = tmp2->next)
- tmp2->index = i++;
- }
-
- if (tab->maximum > 1)
- do_page_mode(tab, head, lptr, mode);
- else
- if (tab->dsp_fn != (void (*)())0)
- (*tab->dsp_fn)(UNDERLINED, CLR);
- }
-
-
- /*
- * Delete un-added entry from the list
- */
- void shuffle_up(tab, head, lptr)
- struct _table *tab;
- struct a_line **head, **lptr;
- {
- struct a_line *tmp;
-
- tmp = (*lptr)->prev;
-
- /*
- * Reset pointers at end & top of list
- */
- if (tmp != ANULL)
- tmp->next = ANULL;
-
- if (*head != ANULL)
- {
- while ((*head)->prev != ANULL)
- *head = (*head)->prev;
- }
-
- if (*head == *lptr)
- {
- free (*head);
- *head = ANULL;
- }
- else
- {
- free (*lptr);
- *lptr = ANULL;
- }
- }
-
-