1*c4f23a93Sblymn /* $NetBSD: field.c,v 1.21 2002/08/09 14:15:12 blymn Exp $ */ 241859428Sblymn /*- 341859428Sblymn * Copyright (c) 1998-1999 Brett Lymn 441859428Sblymn * (blymn@baea.com.au, brett_lymn@yahoo.com.au) 541859428Sblymn * All rights reserved. 641859428Sblymn * 741859428Sblymn * This code has been donated to The NetBSD Foundation by the Author. 841859428Sblymn * 941859428Sblymn * Redistribution and use in source and binary forms, with or without 1041859428Sblymn * modification, are permitted provided that the following conditions 1141859428Sblymn * are met: 1241859428Sblymn * 1. Redistributions of source code must retain the above copyright 1341859428Sblymn * notice, this list of conditions and the following disclaimer. 1441859428Sblymn * 2. The name of the author may not be used to endorse or promote products 15c03a48d6Swiz * derived from this software without specific prior written permission 1641859428Sblymn * 1741859428Sblymn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1841859428Sblymn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1941859428Sblymn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2041859428Sblymn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2141859428Sblymn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2241859428Sblymn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2341859428Sblymn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2441859428Sblymn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2541859428Sblymn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2641859428Sblymn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2741859428Sblymn * 2841859428Sblymn * 2941859428Sblymn */ 3041859428Sblymn 3141859428Sblymn #include <stdlib.h> 3241859428Sblymn #include <strings.h> 33*c4f23a93Sblymn #include <stdarg.h> 3441859428Sblymn #include <form.h> 3541859428Sblymn #include "internals.h" 3641859428Sblymn 3741859428Sblymn extern FORM _formi_default_form; 3841859428Sblymn 3941859428Sblymn FIELD _formi_default_field = { 4041859428Sblymn 0, /* rows in the field */ 4141859428Sblymn 0, /* columns in the field */ 4241859428Sblymn 0, /* dynamic rows */ 4341859428Sblymn 0, /* dynamic columns */ 4441859428Sblymn 0, /* maximum growth */ 4541859428Sblymn 0, /* starting row in the form subwindow */ 4641859428Sblymn 0, /* starting column in the form subwindow */ 4741859428Sblymn 0, /* number of off screen rows */ 4841859428Sblymn 0, /* index of this field in form fields array. */ 4941859428Sblymn 0, /* number of buffers associated with this field */ 5041859428Sblymn FALSE, /* set to true if buffer 0 has changed. */ 5141859428Sblymn NO_JUSTIFICATION, /* justification style of the field */ 5241859428Sblymn FALSE, /* set to true if field is in overlay mode */ 5341859428Sblymn 0, /* starting char in string (horiz scroll) */ 5441859428Sblymn 0, /* starting line in field (vert scroll) */ 5541859428Sblymn 0, /* number of rows actually used in field */ 56759e545dSblymn 0, /* actual pos of cursor in row, not same as x pos due to tabs */ 5741859428Sblymn 0, /* x pos of cursor in field */ 5841859428Sblymn 0, /* y pos of cursor in field */ 5941859428Sblymn 0, /* start of a new page on the form if 1 */ 6041859428Sblymn 0, /* number of the page this field is on */ 6141859428Sblymn A_NORMAL, /* character attributes for the foreground */ 62c0219226Sblymn A_NORMAL, /* character attributes for the background */ 6341859428Sblymn ' ', /* padding character */ 6441859428Sblymn DEFAULT_FORM_OPTS, /* options for the field */ 6541859428Sblymn NULL, /* the form this field is bound to, if any */ 6641859428Sblymn NULL, /* field above this one */ 6741859428Sblymn NULL, /* field below this one */ 6841859428Sblymn NULL, /* field to the left of this one */ 6941859428Sblymn NULL, /* field to the right of this one */ 7041859428Sblymn NULL, /* user defined pointer. */ 7141859428Sblymn NULL, /* used if fields are linked */ 7241859428Sblymn NULL, /* type struct for the field */ 7341859428Sblymn {NULL, NULL}, /* circle queue glue for sorting fields */ 7441859428Sblymn NULL, /* args for field type. */ 757ffbe072Sblymn 0, /* number of allocated slots in lines array */ 767ffbe072Sblymn NULL, /* pointer to the array of lines structures. */ 7741859428Sblymn NULL, /* array of buffers for the field */ 7841859428Sblymn }; 7941859428Sblymn 8041859428Sblymn /* internal function prototypes */ 81*c4f23a93Sblymn static int 82*c4f23a93Sblymn field_buffer_init(FIELD *field, int buffer, size_t len); 8341859428Sblymn static FIELD * 8441859428Sblymn _formi_create_field(FIELD *, int, int, int, int, int, int); 8541859428Sblymn 8641859428Sblymn 8741859428Sblymn /* 8841859428Sblymn * Set the userptr for the field 8941859428Sblymn */ 9041859428Sblymn int 91af28ef95Sblymn set_field_userptr(FIELD *field, void *ptr) 9241859428Sblymn { 9341859428Sblymn FIELD *fp = (field == NULL) ? &_formi_default_field : field; 9441859428Sblymn 9541859428Sblymn fp->userptr = ptr; 9641859428Sblymn 9741859428Sblymn return E_OK; 9841859428Sblymn } 9941859428Sblymn 10041859428Sblymn /* 10141859428Sblymn * Return the userptr for the field. 10241859428Sblymn */ 10341859428Sblymn 104af28ef95Sblymn void * 10541859428Sblymn field_userptr(FIELD *field) 10641859428Sblymn { 10741859428Sblymn if (field == NULL) 10841859428Sblymn return _formi_default_field.userptr; 10941859428Sblymn else 11041859428Sblymn return field->userptr; 11141859428Sblymn } 11241859428Sblymn 11341859428Sblymn /* 11441859428Sblymn * Set the options for the designated field. 11541859428Sblymn */ 11641859428Sblymn int 11741859428Sblymn set_field_opts(FIELD *field, Form_Options options) 11841859428Sblymn { 1196c29066dSblymn int i; 1206c29066dSblymn 12141859428Sblymn FIELD *fp = (field == NULL) ? &_formi_default_field : field; 12241859428Sblymn 1236c29066dSblymn /* not allowed to set opts if the field is the current one */ 1246c29066dSblymn if ((field != NULL) && (field->parent != NULL) && 1256c29066dSblymn (field->parent->cur_field == field->index)) 1266c29066dSblymn return E_CURRENT; 1276c29066dSblymn 1286c29066dSblymn if ((options & O_STATIC) == O_STATIC) { 129ad3d4120Sblymn for (i = 0; i < fp->nbuf; i++) { 130ad3d4120Sblymn if (fp->buffers[i].length > fp->cols) 131ad3d4120Sblymn fp->buffers[i].string[fp->cols] = '\0'; 1326c29066dSblymn } 1336c29066dSblymn } 1346c29066dSblymn 13541859428Sblymn fp->opts = options; 13641859428Sblymn 1378d09f0f7Sblymn /* if appropriate, redraw the field */ 1388d09f0f7Sblymn if ((field != NULL) && (field->parent != NULL) 1398d09f0f7Sblymn && (field->parent->posted == 1)) { 1408d09f0f7Sblymn _formi_redraw_field(field->parent, field->index); 1418d09f0f7Sblymn pos_form_cursor(field->parent); 1428d09f0f7Sblymn wrefresh(field->parent->scrwin); 1438d09f0f7Sblymn } 1448d09f0f7Sblymn 14541859428Sblymn return E_OK; 14641859428Sblymn } 14741859428Sblymn 14841859428Sblymn /* 14941859428Sblymn * Turn on the passed field options. 15041859428Sblymn */ 15141859428Sblymn int 15241859428Sblymn field_opts_on(FIELD *field, Form_Options options) 15341859428Sblymn { 1546c29066dSblymn int i; 1556c29066dSblymn 15641859428Sblymn FIELD *fp = (field == NULL) ? &_formi_default_field : field; 15741859428Sblymn 1586c29066dSblymn /* not allowed to set opts if the field is the current one */ 1596c29066dSblymn if ((field != NULL) && (field->parent != NULL) && 1606c29066dSblymn (field->parent->cur_field == field->index)) 1616c29066dSblymn return E_CURRENT; 1626c29066dSblymn 1636c29066dSblymn if ((options & O_STATIC) == O_STATIC) { 164ad3d4120Sblymn for (i = 0; i < fp->nbuf; i++) { 165ad3d4120Sblymn if (fp->buffers[i].length > fp->cols) 166ad3d4120Sblymn fp->buffers[i].string[fp->cols] = '\0'; 1676c29066dSblymn } 1686c29066dSblymn } 1696c29066dSblymn 17041859428Sblymn fp->opts |= options; 17141859428Sblymn 1728d09f0f7Sblymn /* if appropriate, redraw the field */ 1738d09f0f7Sblymn if ((field != NULL) && (field->parent != NULL) 1748d09f0f7Sblymn && (field->parent->posted == 1)) { 1758d09f0f7Sblymn _formi_redraw_field(field->parent, field->index); 1768d09f0f7Sblymn pos_form_cursor(field->parent); 1778d09f0f7Sblymn wrefresh(field->parent->scrwin); 1788d09f0f7Sblymn } 1798d09f0f7Sblymn 18041859428Sblymn return E_OK; 18141859428Sblymn } 18241859428Sblymn 18341859428Sblymn /* 18441859428Sblymn * Turn off the passed field options. 18541859428Sblymn */ 18641859428Sblymn int 18741859428Sblymn field_opts_off(FIELD *field, Form_Options options) 18841859428Sblymn { 18941859428Sblymn FIELD *fp = (field == NULL) ? &_formi_default_field : field; 19041859428Sblymn 1916c29066dSblymn /* not allowed to set opts if the field is the current one */ 1926c29066dSblymn if ((field != NULL) && (field->parent != NULL) && 1936c29066dSblymn (field->parent->cur_field == field->index)) 1946c29066dSblymn return E_CURRENT; 1956c29066dSblymn 19641859428Sblymn fp->opts &= ~options; 1978d09f0f7Sblymn 1988d09f0f7Sblymn /* if appropriate, redraw the field */ 1998d09f0f7Sblymn if ((field != NULL) && (field->parent != NULL) 2008d09f0f7Sblymn && (field->parent->posted == 1)) { 2018d09f0f7Sblymn _formi_redraw_field(field->parent, field->index); 2028d09f0f7Sblymn pos_form_cursor(field->parent); 2038d09f0f7Sblymn wrefresh(field->parent->scrwin); 2048d09f0f7Sblymn } 2058d09f0f7Sblymn 20641859428Sblymn return E_OK; 20741859428Sblymn } 20841859428Sblymn 20941859428Sblymn /* 21041859428Sblymn * Return the field options associated with the passed field. 21141859428Sblymn */ 21241859428Sblymn Form_Options 21341859428Sblymn field_opts(FIELD *field) 21441859428Sblymn { 21541859428Sblymn if (field == NULL) 21641859428Sblymn return _formi_default_field.opts; 21741859428Sblymn else 21841859428Sblymn return field->opts; 21941859428Sblymn } 22041859428Sblymn 22141859428Sblymn /* 22241859428Sblymn * Set the justification for the passed field. 22341859428Sblymn */ 22441859428Sblymn int 22541859428Sblymn set_field_just(FIELD *field, int justification) 22641859428Sblymn { 22741859428Sblymn FIELD *fp = (field == NULL) ? &_formi_default_field : field; 22841859428Sblymn 2296c29066dSblymn /* 2306c29066dSblymn * not allowed to set justification if the field is 2316c29066dSblymn * the current one 2326c29066dSblymn */ 2336c29066dSblymn if ((field != NULL) && (field->parent != NULL) && 2346c29066dSblymn (field->parent->cur_field == field->index)) 2356c29066dSblymn return E_CURRENT; 2366c29066dSblymn 23741859428Sblymn if ((justification < MIN_JUST_STYLE) /* check justification valid */ 23841859428Sblymn || (justification > MAX_JUST_STYLE)) 23941859428Sblymn return E_BAD_ARGUMENT; 24041859428Sblymn 241d0d41d9fSblymn /* only allow justification on static, single row fields */ 242d0d41d9fSblymn if (((fp->opts & O_STATIC) != O_STATIC) || 243d0d41d9fSblymn ((fp->rows + fp->nrows) > 1)) 244d0d41d9fSblymn return E_BAD_ARGUMENT; 245d0d41d9fSblymn 24641859428Sblymn fp->justification = justification; 247d0d41d9fSblymn 248d0d41d9fSblymn _formi_init_field_xpos(fp); 249d0d41d9fSblymn 25041859428Sblymn return E_OK; 25141859428Sblymn } 25241859428Sblymn 25341859428Sblymn /* 25441859428Sblymn * Return the justification style of the field passed. 25541859428Sblymn */ 25641859428Sblymn int 25741859428Sblymn field_just(FIELD *field) 25841859428Sblymn { 25941859428Sblymn if (field == NULL) 26041859428Sblymn return _formi_default_field.justification; 26141859428Sblymn else 26241859428Sblymn return field->justification; 26341859428Sblymn } 26441859428Sblymn 26541859428Sblymn /* 26641859428Sblymn * Return information about the field passed. 26741859428Sblymn */ 26841859428Sblymn int 26941859428Sblymn field_info(FIELD *field, int *rows, int *cols, int *frow, int *fcol, 27041859428Sblymn int *nrow, int *nbuf) 27141859428Sblymn { 27241859428Sblymn if (field == NULL) 27341859428Sblymn return E_BAD_ARGUMENT; 27441859428Sblymn 27541859428Sblymn *rows = field->rows; 27641859428Sblymn *cols = field->cols; 27741859428Sblymn *frow = field->form_row; 27841859428Sblymn *fcol = field->form_col; 27941859428Sblymn *nrow = field->nrows; 28041859428Sblymn *nbuf = field->nbuf; 28141859428Sblymn 28241859428Sblymn return E_OK; 28341859428Sblymn } 28441859428Sblymn 28541859428Sblymn /* 28641859428Sblymn * Report the dynamic field information. 28741859428Sblymn */ 28841859428Sblymn int 28941859428Sblymn dynamic_field_info(FIELD *field, int *drows, int *dcols, int *max) 29041859428Sblymn { 29141859428Sblymn if (field == NULL) 29241859428Sblymn return E_BAD_ARGUMENT; 29341859428Sblymn 2946c29066dSblymn if ((field->opts & O_STATIC) == O_STATIC) { 2956c29066dSblymn *drows = field->rows; 2966c29066dSblymn *dcols = field->cols; 2976c29066dSblymn } else { 29841859428Sblymn *drows = field->drows; 29941859428Sblymn *dcols = field->dcols; 3006c29066dSblymn } 3016c29066dSblymn 30241859428Sblymn *max = field->max; 30341859428Sblymn 30441859428Sblymn return E_OK; 30541859428Sblymn } 30641859428Sblymn 30741859428Sblymn /* 308*c4f23a93Sblymn * Init all the field variables, perform wrapping and other tasks 309*c4f23a93Sblymn * after the field buffer is set. 310*c4f23a93Sblymn */ 311*c4f23a93Sblymn static int 312*c4f23a93Sblymn field_buffer_init(FIELD *field, int buffer, size_t len) 313*c4f23a93Sblymn { 314*c4f23a93Sblymn int status; 315*c4f23a93Sblymn 316*c4f23a93Sblymn if (buffer == 0) { 317*c4f23a93Sblymn field->start_char = 0; 318*c4f23a93Sblymn field->start_line = 0; 319*c4f23a93Sblymn field->row_xpos = 0; 320*c4f23a93Sblymn field->cursor_xpos = 0; 321*c4f23a93Sblymn field->cursor_ypos = 0; 322*c4f23a93Sblymn field->row_count = 1; /* must be at least one row */ 323*c4f23a93Sblymn field->lines[0].start = 0; 324*c4f23a93Sblymn field->lines[0].end = (len > 0)? (len - 1) : 0; 325*c4f23a93Sblymn field->lines[0].length = 326*c4f23a93Sblymn _formi_tab_expanded_length(field->buffers[0].string, 327*c4f23a93Sblymn 0, field->lines[0].end); 328*c4f23a93Sblymn 329*c4f23a93Sblymn /* we have to hope the wrap works - if it does not then the 330*c4f23a93Sblymn buffer is pretty much borked */ 331*c4f23a93Sblymn status = _formi_wrap_field(field, 0); 332*c4f23a93Sblymn if (status != E_OK) 333*c4f23a93Sblymn return status; 334*c4f23a93Sblymn 335*c4f23a93Sblymn /* 336*c4f23a93Sblymn * calculate the tabs for a single row field, the 337*c4f23a93Sblymn * multiline case is handled when the wrap is done. 338*c4f23a93Sblymn */ 339*c4f23a93Sblymn if (field->row_count == 1) 340*c4f23a93Sblymn _formi_calculate_tabs(field, 0); 341*c4f23a93Sblymn 342*c4f23a93Sblymn /* redraw the field to reflect the new contents. If the field 343*c4f23a93Sblymn * is attached.... 344*c4f23a93Sblymn */ 345*c4f23a93Sblymn if ((field->parent != NULL) && (field->parent->posted == 1)) { 346*c4f23a93Sblymn _formi_redraw_field(field->parent, field->index); 347*c4f23a93Sblymn /* make sure cursor goes back to current field */ 348*c4f23a93Sblymn pos_form_cursor(field->parent); 349*c4f23a93Sblymn } 350*c4f23a93Sblymn } 351*c4f23a93Sblymn 352*c4f23a93Sblymn return E_OK; 353*c4f23a93Sblymn } 354*c4f23a93Sblymn 355*c4f23a93Sblymn 356*c4f23a93Sblymn /* 357*c4f23a93Sblymn * Set the field buffer to the string that results from processing 358*c4f23a93Sblymn * the given format (fmt) using sprintf. 359*c4f23a93Sblymn */ 360*c4f23a93Sblymn int 361*c4f23a93Sblymn set_field_printf(FIELD *field, int buffer, char *fmt, ...) 362*c4f23a93Sblymn { 363*c4f23a93Sblymn int len; 364*c4f23a93Sblymn va_list args; 365*c4f23a93Sblymn 366*c4f23a93Sblymn if (field == NULL) 367*c4f23a93Sblymn return E_BAD_ARGUMENT; 368*c4f23a93Sblymn 369*c4f23a93Sblymn if (buffer >= field->nbuf) 370*c4f23a93Sblymn return E_BAD_ARGUMENT; 371*c4f23a93Sblymn 372*c4f23a93Sblymn va_start(args, fmt); 373*c4f23a93Sblymn /* check for buffer already existing, free the storage */ 374*c4f23a93Sblymn if (field->buffers[buffer].allocated != 0) 375*c4f23a93Sblymn free(field->buffers[buffer].string); 376*c4f23a93Sblymn 377*c4f23a93Sblymn len = vasprintf(&field->buffers[buffer].string, fmt, args); 378*c4f23a93Sblymn va_end(args); 379*c4f23a93Sblymn if (len < 0) 380*c4f23a93Sblymn return E_SYSTEM_ERROR; 381*c4f23a93Sblymn 382*c4f23a93Sblymn field->buffers[buffer].length = len; 383*c4f23a93Sblymn field->buffers[buffer].allocated = len + 1; 384*c4f23a93Sblymn if (((field->opts & O_STATIC) == O_STATIC) && (len > field->cols) 385*c4f23a93Sblymn && ((field->rows + field->nrows) == 1)) 386*c4f23a93Sblymn len = field->cols; 387*c4f23a93Sblymn 388*c4f23a93Sblymn field->buffers[buffer].string[len] = '\0'; 389*c4f23a93Sblymn return field_buffer_init(field, buffer, (unsigned int) len); 390*c4f23a93Sblymn } 391*c4f23a93Sblymn 392*c4f23a93Sblymn /* 39341859428Sblymn * Set the value of the field buffer to the value given. 39441859428Sblymn */ 39541859428Sblymn 39641859428Sblymn int 39741859428Sblymn set_field_buffer(FIELD *field, int buffer, char *value) 39841859428Sblymn { 399*c4f23a93Sblymn size_t len; 4007ce7b462Sblymn int status; 40141859428Sblymn 40241859428Sblymn if (field == NULL) 40341859428Sblymn return E_BAD_ARGUMENT; 40441859428Sblymn 40541859428Sblymn if (buffer >= field->nbuf) /* make sure buffer is valid */ 40641859428Sblymn return E_BAD_ARGUMENT; 40741859428Sblymn 40841859428Sblymn len = strlen(value); 4097ffbe072Sblymn if (((field->opts & O_STATIC) == O_STATIC) && (len > field->cols) 4107ffbe072Sblymn && ((field->rows + field->nrows) == 1)) 4116cda6dc5Sblymn len = field->cols; 4126cda6dc5Sblymn 413cf202272Sblymn #ifdef DEBUG 414cf202272Sblymn if (_formi_create_dbg_file() != E_OK) 415cf202272Sblymn return E_SYSTEM_ERROR; 416cf202272Sblymn 417cf202272Sblymn fprintf(dbg, 418cf202272Sblymn "set_field_buffer: entry: len = %d, value = %s, buffer=%d\n", 419cf202272Sblymn len, value, buffer); 420cf202272Sblymn fprintf(dbg, "set_field_buffer: entry: string = "); 421cf202272Sblymn if (field->buffers[buffer].string != NULL) 422cf202272Sblymn fprintf(dbg, "%s, len = %d\n", field->buffers[buffer].string, 423cf202272Sblymn field->buffers[buffer].length); 424cf202272Sblymn else 425cf202272Sblymn fprintf(dbg, "(null), len = 0\n"); 426cf202272Sblymn fprintf(dbg, "set_field_buffer: entry: lines.len = %d\n", 427cf202272Sblymn field->lines[0].length); 428cf202272Sblymn #endif 429cf202272Sblymn 4306cda6dc5Sblymn if ((field->buffers[buffer].string = 4316cda6dc5Sblymn (char *) realloc(field->buffers[buffer].string, len + 1)) == NULL) 43241859428Sblymn return E_SYSTEM_ERROR; 43341859428Sblymn 4349bb8631dSblymn strlcpy(field->buffers[buffer].string, value, len + 1); 43541859428Sblymn field->buffers[buffer].length = len; 43641859428Sblymn field->buffers[buffer].allocated = len + 1; 437*c4f23a93Sblymn status = field_buffer_init(field, buffer, len); 438cf202272Sblymn 439cf202272Sblymn #ifdef DEBUG 440cf202272Sblymn fprintf(dbg, "set_field_buffer: exit: len = %d, value = %s\n", 441cf202272Sblymn len, value); 442cf202272Sblymn fprintf(dbg, "set_field_buffer: exit: string = %s, len = %d\n", 443cf202272Sblymn field->buffers[buffer].string, field->buffers[buffer].length); 444cf202272Sblymn fprintf(dbg, "set_field_buffer: exit: lines.len = %d\n", 445cf202272Sblymn field->lines[0].length); 446cf202272Sblymn #endif 44741859428Sblymn 448*c4f23a93Sblymn return status; 44941859428Sblymn } 45041859428Sblymn 45141859428Sblymn /* 45241859428Sblymn * Return the requested field buffer to the caller. 45341859428Sblymn */ 45441859428Sblymn char * 45541859428Sblymn field_buffer(FIELD *field, int buffer) 45641859428Sblymn { 45741859428Sblymn 45841859428Sblymn if (field == NULL) 45941859428Sblymn return NULL; 46041859428Sblymn 46141859428Sblymn if (buffer >= field->nbuf) 46241859428Sblymn return NULL; 46341859428Sblymn 46441859428Sblymn return field->buffers[buffer].string; 46541859428Sblymn } 46641859428Sblymn 46741859428Sblymn /* 46841859428Sblymn * Set the buffer 0 field status. 46941859428Sblymn */ 47041859428Sblymn int 47141859428Sblymn set_field_status(FIELD *field, int status) 47241859428Sblymn { 47341859428Sblymn 47441859428Sblymn if (field == NULL) 47541859428Sblymn return E_BAD_ARGUMENT; 47641859428Sblymn 47741859428Sblymn if (status != FALSE) 47841859428Sblymn field->buf0_status = TRUE; 47941859428Sblymn else 48041859428Sblymn field->buf0_status = FALSE; 48141859428Sblymn 48241859428Sblymn return E_OK; 48341859428Sblymn } 48441859428Sblymn 48541859428Sblymn /* 48641859428Sblymn * Return the buffer 0 status flag for the given field. 48741859428Sblymn */ 48841859428Sblymn int 48941859428Sblymn field_status(FIELD *field) 49041859428Sblymn { 49141859428Sblymn 49241859428Sblymn if (field == NULL) /* the default buffer 0 never changes :-) */ 49341859428Sblymn return FALSE; 49441859428Sblymn 49541859428Sblymn return field->buf0_status; 49641859428Sblymn } 49741859428Sblymn 49841859428Sblymn /* 49941859428Sblymn * Set the maximum growth for a dynamic field. 50041859428Sblymn */ 50141859428Sblymn int 50241859428Sblymn set_max_field(FIELD *fptr, int max) 50341859428Sblymn { 5042a68310bSblymn FIELD *field = (fptr == NULL)? &_formi_default_field : fptr; 50541859428Sblymn 50641859428Sblymn if ((field->opts & O_STATIC) == O_STATIC) /* check if field dynamic */ 50741859428Sblymn return E_BAD_ARGUMENT; 50841859428Sblymn 50941859428Sblymn if (max < 0) /* negative numbers are bad.... */ 51041859428Sblymn return E_BAD_ARGUMENT; 51141859428Sblymn 51241859428Sblymn field->max = max; 51341859428Sblymn return E_OK; 51441859428Sblymn } 51541859428Sblymn 51641859428Sblymn /* 51741859428Sblymn * Set the field foreground character attributes. 51841859428Sblymn */ 51941859428Sblymn int 52041859428Sblymn set_field_fore(FIELD *fptr, chtype attribute) 52141859428Sblymn { 52241859428Sblymn FIELD *field = (fptr == NULL)? &_formi_default_field : fptr; 52341859428Sblymn 52441859428Sblymn field->fore = attribute; 52541859428Sblymn return E_OK; 52641859428Sblymn } 52741859428Sblymn 52841859428Sblymn /* 52941859428Sblymn * Return the foreground character attribute for the given field. 53041859428Sblymn */ 53141859428Sblymn chtype 53241859428Sblymn field_fore(FIELD *field) 53341859428Sblymn { 53441859428Sblymn if (field == NULL) 53541859428Sblymn return _formi_default_field.fore; 53641859428Sblymn else 53741859428Sblymn return field->fore; 53841859428Sblymn } 53941859428Sblymn 54041859428Sblymn /* 54141859428Sblymn * Set the background character attribute for the given field. 54241859428Sblymn */ 54341859428Sblymn int 54441859428Sblymn set_field_back(FIELD *field, chtype attribute) 54541859428Sblymn { 54641859428Sblymn if (field == NULL) 54741859428Sblymn _formi_default_field.back = attribute; 54841859428Sblymn else 54941859428Sblymn field->back = attribute; 55041859428Sblymn 55141859428Sblymn return E_OK; 55241859428Sblymn } 55341859428Sblymn 55441859428Sblymn /* 555cc66fb4aSblymn * Get the background character attribute for the given field. 556cc66fb4aSblymn */ 557cc66fb4aSblymn chtype 558cc66fb4aSblymn field_back(FIELD *field) 559cc66fb4aSblymn { 560cc66fb4aSblymn if (field == NULL) 561cc66fb4aSblymn return _formi_default_field.back; 562cc66fb4aSblymn else 563cc66fb4aSblymn return field->back; 564cc66fb4aSblymn } 565cc66fb4aSblymn 566cc66fb4aSblymn /* 56741859428Sblymn * Set the pad character for the given field. 56841859428Sblymn */ 56941859428Sblymn int 57041859428Sblymn set_field_pad(FIELD *field, int pad) 57141859428Sblymn { 57241859428Sblymn if (field == NULL) 57341859428Sblymn _formi_default_field.pad = pad; 57441859428Sblymn else 57541859428Sblymn field->pad = pad; 57641859428Sblymn 57741859428Sblymn return E_OK; 57841859428Sblymn } 57941859428Sblymn 58041859428Sblymn /* 58141859428Sblymn * Return the padding character for the given field. 58241859428Sblymn */ 58341859428Sblymn int 58441859428Sblymn field_pad(FIELD *field) 58541859428Sblymn { 58641859428Sblymn if (field == NULL) 58741859428Sblymn return _formi_default_field.pad; 58841859428Sblymn else 58941859428Sblymn return field->pad; 59041859428Sblymn } 59141859428Sblymn 59241859428Sblymn /* 59341859428Sblymn * Set the field initialisation function hook. 59441859428Sblymn */ 59541859428Sblymn int 59641859428Sblymn set_field_init(FORM *form, Form_Hook function) 59741859428Sblymn { 59841859428Sblymn if (form == NULL) 59941859428Sblymn _formi_default_form.field_init = function; 60041859428Sblymn else 60141859428Sblymn form->field_init = function; 60241859428Sblymn 60341859428Sblymn return E_OK; 60441859428Sblymn } 60541859428Sblymn 60641859428Sblymn /* 60741859428Sblymn * Return the function hook for the field initialisation. 60841859428Sblymn */ 60941859428Sblymn Form_Hook 61041859428Sblymn field_init(FORM *form) 61141859428Sblymn { 61241859428Sblymn if (form == NULL) 61341859428Sblymn return _formi_default_form.field_init; 61441859428Sblymn else 61541859428Sblymn return form->field_init; 61641859428Sblymn } 61741859428Sblymn 61841859428Sblymn /* 61941859428Sblymn * Set the field termination function hook. 62041859428Sblymn */ 62141859428Sblymn int 62241859428Sblymn set_field_term(FORM *form, Form_Hook function) 62341859428Sblymn { 62441859428Sblymn if (form == NULL) 62541859428Sblymn _formi_default_form.field_term = function; 62641859428Sblymn else 62741859428Sblymn form->field_term = function; 62841859428Sblymn 62941859428Sblymn return E_OK; 63041859428Sblymn } 63141859428Sblymn 63241859428Sblymn /* 63341859428Sblymn * Return the function hook defined for the field termination. 63441859428Sblymn */ 63541859428Sblymn Form_Hook 63641859428Sblymn field_term(FORM *form) 63741859428Sblymn { 63841859428Sblymn if (form == NULL) 63941859428Sblymn return _formi_default_form.field_term; 64041859428Sblymn else 64141859428Sblymn return form->field_term; 64241859428Sblymn } 64341859428Sblymn 64441859428Sblymn /* 64541859428Sblymn * Set the page flag on the given field to indicate it is the start of a 64641859428Sblymn * new page. 64741859428Sblymn */ 64841859428Sblymn int 64941859428Sblymn set_new_page(FIELD *fptr, int page) 65041859428Sblymn { 65141859428Sblymn FIELD *field = (fptr == NULL)? &_formi_default_field : fptr; 65241859428Sblymn 65341859428Sblymn if (field->parent != NULL) /* check if field is connected to a form */ 65441859428Sblymn return E_CONNECTED; 65541859428Sblymn 65641859428Sblymn field->page_break = (page != FALSE); 65741859428Sblymn return E_OK; 65841859428Sblymn } 65941859428Sblymn 66041859428Sblymn /* 66141859428Sblymn * Return the page status for the given field. TRUE is returned if the 66241859428Sblymn * field is the start of a new page. 66341859428Sblymn */ 66441859428Sblymn int 66541859428Sblymn new_page(FIELD *field) 66641859428Sblymn { 66741859428Sblymn if (field == NULL) 66841859428Sblymn return _formi_default_field.page_break; 66941859428Sblymn else 67041859428Sblymn return field->page_break; 67141859428Sblymn } 67241859428Sblymn 67341859428Sblymn /* 67441859428Sblymn * Return the index of the field in the form fields array. 67541859428Sblymn */ 67641859428Sblymn int 67741859428Sblymn field_index(FIELD *field) 67841859428Sblymn { 67941859428Sblymn if (field == NULL) 680cc66fb4aSblymn return E_BAD_ARGUMENT; 68141859428Sblymn 68241859428Sblymn if (field->parent == NULL) 683cc66fb4aSblymn return E_NOT_CONNECTED; 68441859428Sblymn 68541859428Sblymn return field->index; 68641859428Sblymn } 68741859428Sblymn 68841859428Sblymn /* 68941859428Sblymn * Internal function that does most of the work to create a new field. 69041859428Sblymn * The new field is initialised from the information in the prototype 69141859428Sblymn * field passed. 69241859428Sblymn * Returns NULL on error. 69341859428Sblymn */ 69441859428Sblymn static FIELD * 69541859428Sblymn _formi_create_field(FIELD *prototype, int rows, int cols, int frow, 69641859428Sblymn int fcol, int nrows, int nbuf) 69741859428Sblymn { 69841859428Sblymn FIELD *new; 69941859428Sblymn 70041859428Sblymn if ((rows <= 0) || (cols <= 0) || (frow < 0) || (fcol < 0) || 70141859428Sblymn (nrows < 0) || (nbuf < 0)) 70241859428Sblymn return NULL; 70341859428Sblymn 70441859428Sblymn if ((new = (FIELD *)malloc(sizeof(FIELD))) == NULL) { 70541859428Sblymn return NULL; 70641859428Sblymn } 70741859428Sblymn 70841859428Sblymn /* copy in the default field info */ 70941859428Sblymn bcopy(prototype, new, sizeof(FIELD)); 71041859428Sblymn 71141859428Sblymn new->nbuf = nbuf + 1; 71241859428Sblymn new->rows = rows; 71341859428Sblymn new->cols = cols; 71441859428Sblymn new->form_row = frow; 71541859428Sblymn new->form_col = fcol; 71641859428Sblymn new->nrows = nrows; 71741859428Sblymn new->link = new; 71841859428Sblymn return new; 71941859428Sblymn } 72041859428Sblymn 72141859428Sblymn /* 72241859428Sblymn * Create a new field structure. 72341859428Sblymn */ 72441859428Sblymn FIELD * 72541859428Sblymn new_field(int rows, int cols, int frow, int fcol, int nrows, int nbuf) 72641859428Sblymn { 72741859428Sblymn FIELD *new; 72841859428Sblymn size_t buf_len; 72941859428Sblymn int i; 73041859428Sblymn 73141859428Sblymn 73241859428Sblymn if ((new = _formi_create_field(&_formi_default_field, rows, cols, 73341859428Sblymn frow, fcol, nrows, nbuf)) == NULL) 73441859428Sblymn return NULL; 73541859428Sblymn 73641859428Sblymn buf_len = (nbuf + 1) * sizeof(FORM_STR); 73741859428Sblymn 73841859428Sblymn if ((new->buffers = (FORM_STR *)malloc(buf_len)) == NULL) { 73941859428Sblymn free(new); 74041859428Sblymn return NULL; 74141859428Sblymn } 74241859428Sblymn 743790e1a7fSblymn /* Initialise the strings to a zero length string */ 74441859428Sblymn for (i = 0; i < nbuf + 1; i++) { 745790e1a7fSblymn if ((new->buffers[i].string = 7467ffbe072Sblymn (char *) malloc(sizeof(char))) == NULL) { 7477ffbe072Sblymn free(new->buffers); 7487ffbe072Sblymn free(new); 749790e1a7fSblymn return NULL; 7507ffbe072Sblymn } 751790e1a7fSblymn new->buffers[i].string[0] = '\0'; 75241859428Sblymn new->buffers[i].length = 0; 753790e1a7fSblymn new->buffers[i].allocated = 1; 75441859428Sblymn } 75541859428Sblymn 7567ffbe072Sblymn if ((new->lines = (_FORMI_FIELD_LINES *) 7577ffbe072Sblymn malloc(sizeof(struct _formi_field_lines))) == NULL) { 7587ffbe072Sblymn free(new->buffers); 7597ffbe072Sblymn free(new); 7607ffbe072Sblymn return NULL; 7617ffbe072Sblymn } 7627ffbe072Sblymn 7637ffbe072Sblymn new->lines_alloced = 1; 7647ffbe072Sblymn new->lines[0].length = 0; 7657ffbe072Sblymn new->lines[0].start = 0; 7667ffbe072Sblymn new->lines[0].end = 0; 767759e545dSblymn new->lines[0].tabs = NULL; 7687ffbe072Sblymn 76941859428Sblymn return new; 77041859428Sblymn } 77141859428Sblymn 77241859428Sblymn /* 77341859428Sblymn * Duplicate the given field, including it's buffers. 77441859428Sblymn */ 77541859428Sblymn FIELD * 77641859428Sblymn dup_field(FIELD *field, int frow, int fcol) 77741859428Sblymn { 77841859428Sblymn FIELD *new; 77941859428Sblymn size_t row_len, buf_len; 78041859428Sblymn 78141859428Sblymn if (field == NULL) 78241859428Sblymn return NULL; 78341859428Sblymn 784cc66fb4aSblymn /* XXXX this right???? */ 78541859428Sblymn if ((new = _formi_create_field(field, (int) field->rows, 78641859428Sblymn (int ) field->cols, 78741859428Sblymn frow, fcol, (int) field->nrows, 78841859428Sblymn field->nbuf - 1)) == NULL) 78941859428Sblymn return NULL; 79041859428Sblymn 79141859428Sblymn row_len = (field->rows + field->nrows + 1) * field->cols; 79241859428Sblymn buf_len = (field->nbuf + 1) * row_len * sizeof(FORM_STR); 79341859428Sblymn 79441859428Sblymn if ((new->buffers = (FORM_STR *)malloc(buf_len)) == NULL) { 79541859428Sblymn free(new); 79641859428Sblymn return NULL; 79741859428Sblymn } 79841859428Sblymn 79941859428Sblymn /* copy the buffers from the source field into the new copy */ 80041859428Sblymn bcopy(field->buffers, new->buffers, buf_len); 80141859428Sblymn 80241859428Sblymn return new; 80341859428Sblymn } 80441859428Sblymn 80541859428Sblymn /* 80641859428Sblymn * Create a new field at the specified location by duplicating the given 80741859428Sblymn * field. The buffers are shared with the parent field. 80841859428Sblymn */ 80941859428Sblymn FIELD * 81041859428Sblymn link_field(FIELD *field, int frow, int fcol) 81141859428Sblymn { 81241859428Sblymn FIELD *new; 81341859428Sblymn 81441859428Sblymn if (field == NULL) 81541859428Sblymn return NULL; 81641859428Sblymn 81741859428Sblymn if ((new = _formi_create_field(field, (int) field->rows, 81841859428Sblymn (int) field->cols, 81941859428Sblymn frow, fcol, (int) field->nrows, 82041859428Sblymn field->nbuf - 1)) == NULL) 82141859428Sblymn return NULL; 82241859428Sblymn 82341859428Sblymn new->link = field->link; 82441859428Sblymn field->link = new; 82541859428Sblymn 82641859428Sblymn /* we are done. The buffer pointer was copied during the field 82741859428Sblymn creation. */ 82841859428Sblymn return new; 82941859428Sblymn } 83041859428Sblymn 83141859428Sblymn /* 83241859428Sblymn * Release all storage allocated to the field 83341859428Sblymn */ 83441859428Sblymn int 83541859428Sblymn free_field(FIELD *field) 83641859428Sblymn { 83741859428Sblymn FIELD *flink; 838759e545dSblymn int i; 839759e545dSblymn _formi_tab_t *ts, *nts; 84041859428Sblymn 84141859428Sblymn if (field == NULL) 84241859428Sblymn return E_BAD_ARGUMENT; 84341859428Sblymn 84441859428Sblymn if (field->parent != NULL) 84541859428Sblymn return E_CONNECTED; 84641859428Sblymn 84741859428Sblymn if (field->link == field) { /* check if field linked */ 84841859428Sblymn /* no it is not - release the buffers */ 84941859428Sblymn free(field->buffers); 850759e545dSblymn /* free the tab structures */ 851759e545dSblymn for (i = 0; i < field->row_count - 1; i++) { 852759e545dSblymn if (field->lines[i].tabs != NULL) { 853759e545dSblymn ts = field->lines[i].tabs; 854759e545dSblymn while (ts != NULL) { 855759e545dSblymn nts = ts->fwd; 856759e545dSblymn free(ts); 857759e545dSblymn ts = nts; 858759e545dSblymn } 859759e545dSblymn } 860759e545dSblymn } 86141859428Sblymn } else { 86241859428Sblymn /* is linked, traverse the links to find the field referring 86341859428Sblymn * to the one to be freed. 86441859428Sblymn */ 86541859428Sblymn for (flink = field->link; flink != field; flink = flink->link); 86641859428Sblymn flink->link = field->link; 86741859428Sblymn } 86841859428Sblymn 86941859428Sblymn free(field); 87041859428Sblymn return E_OK; 87141859428Sblymn } 87241859428Sblymn 87341859428Sblymn 874