home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QBasic & Borland Pascal & C
/
Delphi5.iso
/
C
/
Samples
/
CSAPE32.ARJ
/
SOURCE
/
CSSRC
/
FIELD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-26
|
10KB
|
385 lines
/*
field.c
% field object routines
C-scape 3.2
Copyright (c) 1986-1989, by Oakland Group, Inc.
ALL RIGHTS RESERVED.
Revision History:
-----------------
03/07/86 sng rewrote for speed so that the merge is now in the data
structure instead of being constructed from the spec and
record (field_GetMerge was a bottleneck while profiling).
03/24/86 sng added #defines; added field_merge2record.
04/28/86 sng added integer data item (to support marking).
05/05/86 sng record variable is now passed in open.
05/06/86 sng disabled merge cacheing, removed checks on record.
05/12/86 sng reversed the last two changes (!) so that types can now
be supported.
07/08/86 sng put asserts on single line for easier grep'ing.
07/09/86 sng #defined out xprint to save space.
10/30/86 jmd removed ifdefs.
11/04/86 sng made field_Ok static.
11/05/86 sng made field_Open return NULL if out of memory.
11/16/86 sng now handles variable length fields ("string too short").
2/21/87 jmd replaced asserts
4/21/87 jmd got rid of spec
4/27/87 jmd added data array to field
5/04/87 jmd Replaced the grid
9/11/87 jmd Added '\0' check to SetString
3/07/88 jmd Fixed assert in NextChar and PrevChar (reclen vs mergelen)
3/07/88 jmd Added mergeless fields. This saves runtime space
Set merge to NULL for fields that are all writeable
4/10/88 jmd field_Open no longer takes row and col as args
4/11/88 jmd added scrollable fields
5/09/88 jmd added WIDE fields
6/23/88 jmd converted generic pointers to VOID*
8/16/88 jmd added calls to omalloc
8/20/88 jmd changed args to field_Open
chaned merglen calculation
added bob objects
8/24/88 jmd added field_GetBox
9/19/88 jmd added field name support
10/17/88 jdc added bob_Close to field_Close
4/11/89 jmd renamed protect to avoid Zortech conflict
9/06/89 jmd added ubit initialization
9/11/89 jmd removed asserts for fieldpos
11/29/89 jmd added casts for DG
3/28/90 jmd ansi-fied
10/25/90 jmd added test for NULL string in field_SetString
*/
#include "field.h"
/***** Creators *****/
field_type field_Open(char *spec, int width, int dcount)
/*
effects: Creates a new field with the data given.
returns: The new field. If there isn't enough memory to create the
field, returns NULL.
notes: The space for the new field is allocated in one chunk
to save time.
If there are no non-writeable positions the field is opened
as a "merge-less" field. (merge is set to NULL).
If width is (-1) then set field->width equal to mergelen
*/
{
field_type f;
register int i;
char *s, *p;
int recpos, specpos, reclen, mergelen;
boolean merge_less;
/* Calculate record and merge length. */
reclen = 0;
mergelen = 0;
for (s = spec; *s != '\0'; s++) {
mergelen++;
if (*s == CS_INPUT) {
reclen++;
}
}
if (mergelen == reclen) {
merge_less = TRUE;
/* (Mergeless field) Allocate space for: */
p = (char *) omalloc(
CSA_FIELD,
sizeof(struct field_struct) + /* the structure, */
dcount * sizeof(VOID *) + /* the data pointer array, */
reclen + 1 ); /* and the record. */
}
else {
merge_less = FALSE;
/* (Normal field) Allocate space for: */
p = (char *) omalloc(
CSA_FIELD,
sizeof(struct field_struct) + /* the structure, */
reclen * sizeof(int) + /* record to merge map, */
dcount * sizeof(VOID *) + /* the data pointer array, */
reclen + 1 + /* the record, */
mergelen + 1 ); /* and the merge. */
}
if (p == NULL) {
return(NULL);
}
/* Set the pointers for the structure _and_ the pointers in the
structure.
*/
f = (field_type) p;
p += sizeof(struct field_struct);
f->mergelen = mergelen; /* non-ptrs are done first */
f->reclen = reclen; /* so they can lie on word bounds */
if (merge_less) {
f->r2m = NULL;
}
else {
f->r2m = (int *) p;
p += sizeof(int) * reclen;
}
f->dcount = dcount;
f->data = (VOID **) p;
p += dcount * sizeof(VOID *);
f->record = p;
p += reclen + 1;
memset((VOID *) f->record, '\0', reclen+1);
if (merge_less) {
f->merge = NULL;
}
else {
f->merge = p;
memset((VOID *) f->merge, MRGPADCHAR, mergelen);
f->merge[mergelen] = '\0';
/* Make the maps and the merge. */
for (recpos = specpos = 0; specpos < mergelen; specpos++) {
if (spec[specpos] == CS_INPUT) {
f->r2m[recpos++] = specpos;
}
else {
f->merge[specpos] = spec[specpos];
}
}
}
/* Initialize data. */
for (i = 0; i < dcount; i++) {
f->data[i] = NULL;
}
field_SetProtected(f, FALSE);
f->var = NULL;
f->funcs = NULL;
f->bob = NULL;
f->row = 0;
f->col = 0;
f->nameno = -1;
f->width = (width < 0) ? mergelen : width;
f->xoffset = 0;
f->marked = FALSE;
f->reg = (char) 0;
f->sel = (char) 0;
f->ubit = FALSE;
f->hicharon = FALSE;
f->hicharno = 0;
f->gcol = 0;
f->right = -1;
f->left = -1;
return(f);
}
/**** Mutators *****/
void field_SetString(field_type f, char *string)
/*
* modifies: The field passed.
*
* effects: Sets the record of the field to the string given. The string
* can be less than or equal to the length of the record.
*/
{
int recpos;
boolean inrec;
cs_Assert(field_Ok(f), CS_FLD_SS_FLD, 0);
/* test for NULL string */
if (string != NULL) {
if (string[0] == '\0' && f->record[0] == '\0') {
/* no sense in setting the record */
return;
}
inrec = TRUE;
}
else {
/* NULL string, clear the record */
inrec = FALSE;
}
for (recpos = 0; recpos < f->reclen; recpos++) {
if (inrec && string[recpos] == '\0') {
inrec = FALSE;
}
f->record[recpos] = inrec ? string[recpos] : '\0';
if (f->merge != NULL) {
f->merge[f->r2m[recpos]] = inrec ? string[recpos] : MRGPADCHAR;
}
}
}
void field_SetChar(field_type f, int recpos, char c)
/*
* requires: The column passed must be within the span of the
* field.
*
* modifies: The field given.
*
* effects: Sets a character at the given record position of the field.
*
*/
{
register int len;
cs_Assert(field_Ok(f), CS_FLD_SC_FLD, 0);
if (recpos >= 0 && recpos < f->reclen) {
len = strlen(f->record);
/* Need to pad with spaces? */
if (len < recpos) {
memset((VOID *) (f->record + len), RECPADCHAR, recpos - len);
}
f->record[recpos] = c;
if (f->merge != NULL) {
f->merge[f->r2m[recpos]] = c;
}
}
}
boolean field_SetData(field_type field, int datano, VOID *data)
/*
Sets the appropriate field data to data.
If datano > field->dcount return FALSE.
*/
{
cs_Assert(field_Ok(field), CS_FLD_FSD_FLD, 0);
if (datano < 0 || datano >= field->dcount) {
return(FALSE);
}
field->data[datano] = data;
return(TRUE);
}
/**** Observers *****/
VOID *field_GetData(field_type field, int datano)
/*
Returns the appropriate data pointer for the field.
If datano > field->dcount return NULL.
*/
{
cs_Assert(field_Ok(field), CS_FLD_FGD_FLD, 0);
if (datano < 0 || datano >= field->dcount) {
return(NULL);
}
return(field->data[datano]);
}
int field_FirstChar(field_type field)
/*
* effects: Finds the first writeable record position from the one given.
* If there are no writeable positions, return -1.
*
* returns: The first writeable position.
*/
{
cs_Assert(field_Ok(field), CS_FLD_FC_FLD, 0);
return(field->reclen > 0 ? 0 : -1);
}
int field_LastChar(field_type field)
/*
* effects: Finds the last writeable record position from the one given.
*
* returns: The last position with a character in it. If the field has
* no record (i.e. writeable) positions, return -1.
*
*/
{
cs_Assert(field_Ok(field), CS_FLD_LC_FLD, 0);
return(field->reclen > 0 ? (int) strlen(field->record) : -1);
}
int field_NextChar(field_type field, int fieldpos)
/*
* requires: The position passed must be within the span of the writeable
* positions.
*
* effects: Finds the next record position after the one given. If
* there are no more positions, return -1.
*
* returns: The next record position.
*
*/
{
cs_Assert(field_Ok(field), CS_FLD_NC_FLD, 0);
if (fieldpos >= 0 && fieldpos < field->reclen) {
return(fieldpos + 1 < field->reclen ? fieldpos + 1 : -1);
}
else {
return(-1);
}
}
int field_PrevChar(field_type field, int fieldpos)
/*
* requires: The position passed must be within the span of the field.
*
* effects: Finds the previous writeable position from the one given. If
* we're at the first position, return -1.
*
* returns: The previous writeable position.
*/
{
if (fieldpos >= 0 && fieldpos < field->reclen) {
return(fieldpos > 0 ? fieldpos - 1 : -1);
}
else {
return(-1);
}
}
boolean field_Ok(field_type f)
/*
* effects: Checks the validity of a field.
*
* returns: TRUE if a field is okay, FALSE if it ain't.
*/
{
return (f != NULL && f->record != NULL);
}
void field_SetHiChar(field_type f, int mergepos)
/*
Enables field character highlighting.
mergepos is the character to highlight.
use mergepos < 0 to turn off higlighting
Note: currently only values of 0-15 are supported.
*/
{
if (mergepos < 0 || mergepos > 15 || mergepos >= f->mergelen) {
f->hicharon = FALSE;
}
else {
f->hicharon = TRUE;
f->hicharno = mergepos;
}
}