/****************************************************************************1* Copyright (c) 1998 Free Software Foundation, Inc. *2* *3* Permission is hereby granted, free of charge, to any person obtaining a *4* copy of this software and associated documentation files (the *5* "Software"), to deal in the Software without restriction, including *6* without limitation the rights to use, copy, modify, merge, publish, *7* distribute, distribute with modifications, sublicense, and/or sell *8* copies of the Software, and to permit persons to whom the Software is *9* furnished to do so, subject to the following conditions: *10* *11* The above copyright notice and this permission notice shall be included *12* in all copies or substantial portions of the Software. *13* *14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *15* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *17* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *20* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *21* *22* Except as contained in this notice, the name(s) of the above copyright *23* holders shall not be used in advertising or otherwise to promote the *24* sale, use or other dealings in this Software without prior written *25* authorization. *26****************************************************************************/2728/****************************************************************************29* Author: Juergen Pfeifer <[email protected]> 1995,1997 *30****************************************************************************/3132#include "form.priv.h"3334MODULE_ID("$Id$")3536/* this can't be readonly */37static FORM default_form = {380, /* status */390, /* rows */400, /* cols */410, /* currow */420, /* curcol */430, /* toprow */440, /* begincol */45-1, /* maxfield */46-1, /* maxpage */47-1, /* curpage */48ALL_FORM_OPTS, /* opts */49(WINDOW *)0, /* win */50(WINDOW *)0, /* sub */51(WINDOW *)0, /* w */52(FIELD **)0, /* field */53(FIELD *)0, /* current */54(_PAGE *)0, /* page */55(char *)0, /* usrptr */56NULL, /* forminit */57NULL, /* formterm */58NULL, /* fieldinit */59NULL /* fieldterm */60};6162FORM *_nc_Default_Form = &default_form;6364/*---------------------------------------------------------------------------65| Facility : libnform66| Function : static FIELD *Insert_Field_By_Position(67| FIELD *new_field,68| FIELD *head )69|70| Description : Insert new_field into sorted fieldlist with head "head"71| and return new head of sorted fieldlist. Sorting72| criteria is (row,column). This is a circular list.73|74| Return Values : New head of sorted fieldlist75+--------------------------------------------------------------------------*/76static FIELD *Insert_Field_By_Position(FIELD *newfield, FIELD *head)77{78FIELD *current, *newhead;7980assert(newfield != 0);8182if (!head)83{ /* empty list is trivial */84newhead = newfield->snext = newfield->sprev = newfield;85}86else87{88newhead = current = head;89while((current->frow < newfield->frow) ||90((current->frow==newfield->frow) &&91(current->fcol < newfield->fcol)) )92{93current = current->snext;94if (current==head)95{ /* We cycled through. Reset head to indicate that */96head = (FIELD *)0;97break;98}99}100/* we leave the loop with current pointing to the field after newfield*/101newfield->snext = current;102newfield->sprev = current->sprev;103newfield->snext->sprev = newfield;104newfield->sprev->snext = newfield;105if (current==head)106newhead = newfield;107}108return(newhead);109}110111/*---------------------------------------------------------------------------112| Facility : libnform113| Function : static void Disconnect_Fields(FORM *form)114|115| Description : Break association between form and array of fields.116|117| Return Values : -118+--------------------------------------------------------------------------*/119static void Disconnect_Fields( FORM * form )120{121if (form->field)122{123FIELD **fields;124125for(fields=form->field;*fields;fields++)126{127if (form == (*fields)->form)128(*fields)->form = (FORM *)0;129}130131form->rows = form->cols = 0;132form->maxfield = form->maxpage = -1;133form->field = (FIELD **)0;134if (form->page)135free(form->page);136form->page = (_PAGE *)0;137}138}139140/*---------------------------------------------------------------------------141| Facility : libnform142| Function : static int Connect_Fields(FORM *form, FIELD **fields)143|144| Description : Set association between form and array of fields.145|146| Return Values : E_OK - no error147| E_CONNECTED - a field is already connected148| E_BAD_ARGUMENT - Invalid form pointer or field array149| E_SYSTEM_ERROR - not enough memory150+--------------------------------------------------------------------------*/151static int Connect_Fields(FORM * form, FIELD ** fields)152{153int field_cnt, j;154int page_nr;155int maximum_row_in_field, maximum_col_in_field;156_PAGE *pg;157158assert(form != 0);159160form->field = fields;161form->maxfield = 0;162form->maxpage = 0;163164if (!fields)165RETURN(E_OK);166167page_nr = 0;168/* store formpointer in fields and count pages */169for(field_cnt=0;fields[field_cnt];field_cnt++)170{171if (fields[field_cnt]->form)172RETURN(E_CONNECTED);173if ( field_cnt==0 ||174(fields[field_cnt]->status & _NEWPAGE))175page_nr++;176fields[field_cnt]->form = form;177}178if (field_cnt==0)179RETURN(E_BAD_ARGUMENT);180181/* allocate page structures */182if ( (pg = (_PAGE *)malloc(page_nr * sizeof(_PAGE))) != (_PAGE *)0 )183{184form->page = pg;185}186else187RETURN(E_SYSTEM_ERROR);188189/* Cycle through fields and calculate page boundaries as well as190size of the form */191for(j=0;j<field_cnt;j++)192{193if (j==0)194pg->pmin = j;195else196{197if (fields[j]->status & _NEWPAGE)198{199pg->pmax = j-1;200pg++;201pg->pmin = j;202}203}204205maximum_row_in_field = fields[j]->frow + fields[j]->rows;206maximum_col_in_field = fields[j]->fcol + fields[j]->cols;207208if (form->rows < maximum_row_in_field)209form->rows = maximum_row_in_field;210if (form->cols < maximum_col_in_field)211form->cols = maximum_col_in_field;212}213214pg->pmax = field_cnt-1;215form->maxfield = field_cnt;216form->maxpage = page_nr;217218/* Sort fields on form pages */219for(page_nr = 0;page_nr < form->maxpage; page_nr++)220{221FIELD *fld = (FIELD *)0;222#ifdef __clang_analyzer__223/* Tell clang-analyzer the loop body runs at least once. */224assert(form->page[page_nr].pmin <= form->page[page_nr].pmax);225#endif226for(j = form->page[page_nr].pmin;j <= form->page[page_nr].pmax;j++)227{228fields[j]->index = j;229fields[j]->page = page_nr;230fld = Insert_Field_By_Position(fields[j],fld);231}232form->page[page_nr].smin = fld->index;233form->page[page_nr].smax = fld->sprev->index;234}235RETURN(E_OK);236}237238/*---------------------------------------------------------------------------239| Facility : libnform240| Function : static int Associate_Fields(FORM *form, FIELD **fields)241|242| Description : Set association between form and array of fields.243| If there are fields, position to first active field.244|245| Return Values : E_OK - success246| any other - error occurred247+--------------------------------------------------------------------------*/248INLINE static int Associate_Fields(FORM *form, FIELD **fields)249{250int res = Connect_Fields(form,fields);251if (res == E_OK)252{253if (form->maxpage>0)254{255form->curpage = 0;256form_driver(form,FIRST_ACTIVE_MAGIC);257}258else259{260form->curpage = -1;261form->current = (FIELD *)0;262}263}264return(res);265}266267/*---------------------------------------------------------------------------268| Facility : libnform269| Function : FORM *new_form( FIELD **fields )270|271| Description : Create new form with given array of fields.272|273| Return Values : Pointer to form. NULL if error occurred.274+--------------------------------------------------------------------------*/275FORM *new_form(FIELD ** fields)276{277int err = E_SYSTEM_ERROR;278279FORM *form = (FORM *)malloc(sizeof(FORM));280281if (form)282{283*form = *_nc_Default_Form;284if ((err=Associate_Fields(form,fields))!=E_OK)285{286free_form(form);287form = (FORM *)0;288}289}290291if (!form)292SET_ERROR(err);293294return(form);295}296297/*---------------------------------------------------------------------------298| Facility : libnform299| Function : int free_form( FORM *form )300|301| Description : Release internal memory associated with form.302|303| Return Values : E_OK - no error304| E_BAD_ARGUMENT - invalid form pointer305| E_POSTED - form is posted306+--------------------------------------------------------------------------*/307int free_form(FORM * form)308{309if ( !form )310RETURN(E_BAD_ARGUMENT);311312if ( form->status & _POSTED)313RETURN(E_POSTED);314315Disconnect_Fields( form );316if (form->page)317free(form->page);318free(form);319320RETURN(E_OK);321}322323/*---------------------------------------------------------------------------324| Facility : libnform325| Function : int set_form_fields( FORM *form, FIELD **fields )326|327| Description : Set a new association of an array of fields to a form328|329| Return Values : E_OK - no error330| E_BAD_ARGUMENT - invalid form pointer331| E_POSTED - form is posted332+--------------------------------------------------------------------------*/333int set_form_fields(FORM * form, FIELD ** fields)334{335FIELD **old;336int res;337338if ( !form )339RETURN(E_BAD_ARGUMENT);340341if ( form->status & _POSTED )342RETURN(E_POSTED);343344old = form->field;345Disconnect_Fields( form );346347if( (res = Associate_Fields( form, fields )) != E_OK )348Connect_Fields( form, old );349350RETURN(res);351}352353/*---------------------------------------------------------------------------354| Facility : libnform355| Function : FIELD **form_fields( const FORM *form )356|357| Description : Retrieve array of fields358|359| Return Values : Pointer to field array360+--------------------------------------------------------------------------*/361FIELD **form_fields(const FORM * form)362{363return (Normalize_Form( form )->field);364}365366/*---------------------------------------------------------------------------367| Facility : libnform368| Function : int field_count( const FORM *form )369|370| Description : Retrieve number of fields371|372| Return Values : Number of fields, -1 if none are defined373+--------------------------------------------------------------------------*/374int field_count(const FORM * form)375{376return (Normalize_Form( form )->maxfield);377}378379/* frm_def.c ends here */380381382