home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / CSSRC / FIELD.C < prev    next >
C/C++ Source or Header  |  1990-10-26  |  10KB  |  385 lines

  1. /*
  2.     field.c
  3.  
  4.     % field object routines
  5.  
  6.     C-scape 3.2
  7.     Copyright (c) 1986-1989, by Oakland Group, Inc.
  8.     ALL RIGHTS RESERVED.
  9.  
  10.     Revision History:
  11.     -----------------
  12.     03/07/86 sng    rewrote for speed so that the merge is now in the data
  13.                     structure instead of being constructed from the spec and
  14.                     record (field_GetMerge was a bottleneck while profiling).
  15.     03/24/86 sng    added #defines; added field_merge2record.
  16.     04/28/86 sng    added integer data item (to support marking).
  17.     05/05/86 sng    record variable is now passed in open.
  18.     05/06/86 sng    disabled merge cacheing, removed checks on record.
  19.     05/12/86 sng    reversed the last two changes (!) so that types can now
  20.                     be supported.
  21.      07/08/86 sng    put asserts on single line for easier grep'ing.
  22.     07/09/86 sng    #defined out xprint to save space.
  23.     10/30/86 jmd    removed ifdefs.
  24.     11/04/86 sng    made field_Ok static.
  25.     11/05/86 sng    made field_Open return NULL if out of memory.
  26.     11/16/86 sng    now handles variable length fields ("string too short").
  27.      2/21/87 jmd    replaced asserts
  28.      4/21/87 jmd    got rid of spec
  29.      4/27/87 jmd    added data array to field
  30.      5/04/87 jmd    Replaced the grid
  31.      9/11/87 jmd    Added '\0' check to SetString
  32.  
  33.      3/07/88 jmd    Fixed assert in NextChar and PrevChar (reclen vs mergelen)
  34.      3/07/88 jmd    Added mergeless fields.  This saves runtime space
  35.                     Set merge to NULL for fields that are all writeable
  36.      4/10/88 jmd    field_Open no longer takes row and col as args
  37.      4/11/88 jmd    added scrollable fields
  38.      5/09/88 jmd    added WIDE fields
  39.      6/23/88 jmd    converted generic pointers to VOID*
  40.      8/16/88 jmd    added calls to omalloc
  41.      8/20/88 jmd    changed args to field_Open
  42.                     chaned merglen calculation
  43.                     added bob objects
  44.      8/24/88 jmd    added field_GetBox
  45.      9/19/88 jmd    added field name support
  46.     10/17/88 jdc    added bob_Close to field_Close
  47.  
  48.      4/11/89 jmd    renamed protect to avoid Zortech conflict
  49.      9/06/89 jmd    added ubit initialization
  50.      9/11/89 jmd    removed asserts for fieldpos
  51.  
  52.     11/29/89 jmd    added casts for DG
  53.      3/28/90 jmd    ansi-fied
  54.     10/25/90 jmd    added test for NULL string in field_SetString
  55. */
  56.  
  57. #include "field.h"
  58.  
  59. /***** Creators *****/
  60.  
  61. field_type field_Open(char *spec, int width, int dcount)
  62. /*
  63.      effects:    Creates a new field with the data given.
  64.      returns:    The new field.  If there isn't enough memory to create the
  65.                  field, returns NULL.
  66.      notes:        The space for the new field is allocated in one chunk
  67.                  to save time.
  68.                 If there are no non-writeable positions the field is opened
  69.                 as a "merge-less" field.  (merge is set to NULL).
  70.                 If width is (-1) then set field->width equal to mergelen
  71. */
  72. {
  73.     field_type f;
  74.     register int i;
  75.     char   *s, *p;
  76.     int     recpos, specpos, reclen, mergelen;
  77.     boolean merge_less;
  78.  
  79.     /* Calculate record and merge length. */
  80.     reclen = 0;
  81.     mergelen = 0;
  82.     for (s = spec; *s != '\0'; s++) {
  83.         mergelen++;
  84.         if (*s == CS_INPUT) {
  85.             reclen++;
  86.         }
  87.     }
  88.  
  89.     if (mergelen == reclen) {
  90.         merge_less = TRUE;
  91.         /* (Mergeless field) Allocate space for: */
  92.         p = (char *) omalloc(
  93.           CSA_FIELD,
  94.           sizeof(struct field_struct) +           /* the structure, */
  95.           dcount * sizeof(VOID *) +                  /* the data pointer array, */
  96.           reclen + 1 );                              /* and the record. */
  97.     }
  98.     else {
  99.         merge_less = FALSE;
  100.         /* (Normal field) Allocate space for: */
  101.         p = (char *) omalloc(
  102.           CSA_FIELD,
  103.           sizeof(struct field_struct) +           /* the structure, */
  104.           reclen * sizeof(int) +                  /* record to merge map, */
  105.           dcount * sizeof(VOID *) +                  /* the data pointer array, */
  106.           reclen + 1 +                              /* the record, */
  107.           mergelen + 1 );                          /* and the merge. */
  108.     }
  109.  
  110.     if (p == NULL) {
  111.         return(NULL);
  112.     }
  113.  
  114.     /* Set the pointers for the structure _and_ the pointers in the
  115.        structure.
  116.     */
  117.     f = (field_type) p;
  118.     p += sizeof(struct field_struct);
  119.  
  120.     f->mergelen = mergelen;                /* non-ptrs are done first */
  121.     f->reclen = reclen;                    /* so they can lie on word bounds */
  122.  
  123.     if (merge_less) {
  124.         f->r2m = NULL;
  125.     }
  126.     else {
  127.         f->r2m = (int *) p;
  128.         p += sizeof(int) * reclen;
  129.     }
  130.  
  131.     f->dcount = dcount;
  132.     f->data    = (VOID **) p;
  133.     p += dcount * sizeof(VOID *);
  134.  
  135.     f->record = p;
  136.     p += reclen + 1;
  137.     memset((VOID *) f->record, '\0', reclen+1);
  138.  
  139.     if (merge_less) {
  140.         f->merge = NULL;
  141.     }
  142.     else {
  143.         f->merge = p;
  144.         memset((VOID *) f->merge, MRGPADCHAR, mergelen);
  145.         f->merge[mergelen] = '\0';
  146.  
  147.         /* Make the maps and the merge. */
  148.         for (recpos = specpos = 0; specpos < mergelen; specpos++) {
  149.             if (spec[specpos] == CS_INPUT) {
  150.                 f->r2m[recpos++] = specpos;
  151.             }
  152.             else {
  153.                 f->merge[specpos] = spec[specpos];
  154.             }
  155.         }
  156.     }
  157.  
  158.     /* Initialize data. */
  159.     for (i = 0; i < dcount; i++) {
  160.         f->data[i] = NULL;
  161.     }
  162.  
  163.     field_SetProtected(f, FALSE);
  164.  
  165.     f->var = NULL;
  166.     f->funcs = NULL;
  167.     f->bob = NULL;
  168.     f->row = 0;
  169.     f->col = 0;
  170.     f->nameno = -1;
  171.  
  172.     f->width = (width < 0) ? mergelen : width;
  173.     f->xoffset = 0;
  174.  
  175.     f->marked = FALSE;
  176.     f->reg = (char) 0;
  177.     f->sel = (char) 0;
  178.     f->ubit = FALSE;
  179.     f->hicharon = FALSE;
  180.     f->hicharno = 0;
  181.  
  182.     f->gcol = 0;
  183.     f->right = -1;
  184.     f->left = -1;
  185.  
  186.     return(f);
  187. }
  188.  
  189. /**** Mutators *****/
  190.  
  191. void field_SetString(field_type f, char *string)
  192. /*
  193.  *    modifies:   The field passed.
  194.  *
  195.  *    effects:    Sets the record of the field to the string given.  The string
  196.  *                can be less than or equal to the length of the record.
  197.  */
  198. {
  199.     int     recpos;
  200.     boolean inrec;
  201.  
  202.     cs_Assert(field_Ok(f), CS_FLD_SS_FLD, 0);
  203.  
  204.     /* test for NULL string */
  205.     if (string != NULL) {
  206.         if (string[0] == '\0' && f->record[0] == '\0') {
  207.             /* no sense in setting the record */
  208.             return;
  209.         }
  210.  
  211.         inrec = TRUE;
  212.     }
  213.     else {
  214.         /* NULL string, clear the record */
  215.         inrec = FALSE;
  216.     }
  217.  
  218.     for (recpos = 0; recpos < f->reclen; recpos++) {
  219.         if (inrec && string[recpos] == '\0') {
  220.             inrec = FALSE;
  221.         }
  222.         f->record[recpos] = inrec ? string[recpos] : '\0';
  223.         if (f->merge != NULL) {
  224.             f->merge[f->r2m[recpos]] = inrec ? string[recpos] : MRGPADCHAR;
  225.         }
  226.     }
  227. }
  228.  
  229. void field_SetChar(field_type f, int recpos, char c)
  230. /*
  231.  *    requires:   The column passed must be within the span of the
  232.  *                field.
  233.  *
  234.  *    modifies:   The field given.
  235.  *
  236.  *    effects:    Sets a character at the given record position of the field.
  237.  *
  238.  */
  239. {
  240.     register int len;
  241.  
  242.     cs_Assert(field_Ok(f), CS_FLD_SC_FLD, 0);
  243.  
  244.     if (recpos >= 0 && recpos < f->reclen) {
  245.         len = strlen(f->record);
  246.  
  247.         /* Need to pad with spaces? */
  248.         if (len < recpos) {
  249.             memset((VOID *) (f->record + len), RECPADCHAR, recpos - len);
  250.         }
  251.  
  252.         f->record[recpos] = c;
  253.         if (f->merge != NULL) {
  254.             f->merge[f->r2m[recpos]] = c;
  255.         }
  256.     }
  257. }
  258.  
  259. boolean field_SetData(field_type field, int datano, VOID *data)
  260. /*
  261.     Sets the appropriate field data to data.
  262.     If datano > field->dcount return FALSE.
  263. */
  264. {
  265.     cs_Assert(field_Ok(field), CS_FLD_FSD_FLD, 0);
  266.  
  267.     if (datano < 0 || datano >= field->dcount) {
  268.         return(FALSE);
  269.     }
  270.  
  271.     field->data[datano] = data;
  272.     return(TRUE);
  273. }
  274.  
  275. /**** Observers *****/
  276.  
  277. VOID *field_GetData(field_type field, int datano)
  278. /*
  279.     Returns the appropriate data pointer for the field.
  280.     If datano > field->dcount return NULL.
  281. */
  282. {
  283.     cs_Assert(field_Ok(field), CS_FLD_FGD_FLD, 0);
  284.  
  285.     if (datano < 0 || datano >= field->dcount) {
  286.         return(NULL);
  287.     }
  288.  
  289.     return(field->data[datano]);
  290. }
  291.  
  292. int field_FirstChar(field_type field)
  293. /*
  294.  *    effects:    Finds the first writeable record position from the one given.
  295.  *                If there are no writeable positions, return -1.
  296.  *
  297.  *    returns:    The first writeable position.
  298.  */
  299. {
  300.     cs_Assert(field_Ok(field), CS_FLD_FC_FLD, 0);
  301.  
  302.     return(field->reclen > 0 ? 0 : -1);
  303. }
  304.  
  305. int field_LastChar(field_type field)
  306. /*
  307.  *    effects:    Finds the last writeable record position from the one given.
  308.  *
  309.  *    returns:    The last position with a character in it.  If the field has
  310.  *                no record (i.e. writeable) positions, return -1.
  311.  *
  312.  */
  313. {
  314.     cs_Assert(field_Ok(field), CS_FLD_LC_FLD, 0);
  315.  
  316.     return(field->reclen > 0 ? (int) strlen(field->record) : -1);
  317. }
  318.  
  319. int field_NextChar(field_type field, int fieldpos)
  320. /*
  321.  *    requires:    The position passed must be within the span of the writeable
  322.  *                positions.
  323.  *
  324.  *    effects:    Finds the next record position after the one given.  If
  325.  *                there are no more positions, return -1.
  326.  *
  327.  *    returns:    The next record position.
  328.  *
  329.  */
  330. {
  331.     cs_Assert(field_Ok(field), CS_FLD_NC_FLD, 0);
  332.  
  333.     if (fieldpos >= 0 && fieldpos < field->reclen) {
  334.         return(fieldpos + 1 < field->reclen ? fieldpos + 1 : -1);
  335.     }
  336.     else {
  337.         return(-1);
  338.     }
  339. }
  340.  
  341. int field_PrevChar(field_type field, int fieldpos)
  342. /*
  343.  *    requires:    The position passed must be within the span of the field.
  344.  *
  345.  *    effects:    Finds the previous writeable position from the one given.  If
  346.  *                we're at the first position, return -1.
  347.  *
  348.  *    returns:    The previous writeable position.
  349.  */
  350. {
  351.     if (fieldpos >= 0 && fieldpos < field->reclen) {
  352.         return(fieldpos > 0 ? fieldpos - 1 : -1);
  353.     }
  354.     else {
  355.         return(-1);
  356.     }
  357. }
  358.  
  359. boolean field_Ok(field_type f)
  360. /*
  361.  *    effects:    Checks the validity of a field.
  362.  *
  363.  *    returns:    TRUE if a field is okay, FALSE if it ain't.
  364.  */
  365. {
  366.     return (f != NULL && f->record != NULL);
  367. }
  368.  
  369. void field_SetHiChar(field_type f, int mergepos)
  370. /*
  371.     Enables field character highlighting.
  372.     mergepos is the character to highlight.
  373.     use mergepos < 0 to turn off higlighting
  374.     Note: currently only values of 0-15 are supported.
  375. */
  376. {
  377.     if (mergepos < 0 || mergepos > 15 || mergepos >= f->mergelen) {
  378.         f->hicharon = FALSE;
  379.     }
  380.     else {
  381.         f->hicharon = TRUE;
  382.         f->hicharno = mergepos;
  383.     }
  384. }
  385.