1 /**************************************************************************** 2 * Copyright (c) 1998,2000 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29 /**************************************************************************** 30 * Author: Juergen Pfeifer <juergen.pfeifer@gmx.net> 1995,1997 * 31 ****************************************************************************/ 32 33 #include "form.priv.h" 34 35 MODULE_ID("$Id: frm_def.c,v 1.10 2000/12/10 02:09:38 tom Exp $") 36 37 /* this can't be readonly */ 38 static FORM default_form = { 39 0, /* status */ 40 0, /* rows */ 41 0, /* cols */ 42 0, /* currow */ 43 0, /* curcol */ 44 0, /* toprow */ 45 0, /* begincol */ 46 -1, /* maxfield */ 47 -1, /* maxpage */ 48 -1, /* curpage */ 49 ALL_FORM_OPTS, /* opts */ 50 (WINDOW *)0, /* win */ 51 (WINDOW *)0, /* sub */ 52 (WINDOW *)0, /* w */ 53 (FIELD **)0, /* field */ 54 (FIELD *)0, /* current */ 55 (_PAGE *)0, /* page */ 56 (char *)0, /* usrptr */ 57 NULL, /* forminit */ 58 NULL, /* formterm */ 59 NULL, /* fieldinit */ 60 NULL /* fieldterm */ 61 }; 62 63 NCURSES_EXPORT_VAR(FORM *) _nc_Default_Form = &default_form; 64 65 /*--------------------------------------------------------------------------- 66 | Facility : libnform 67 | Function : static FIELD *Insert_Field_By_Position( 68 | FIELD *new_field, 69 | FIELD *head ) 70 | 71 | Description : Insert new_field into sorted fieldlist with head "head" 72 | and return new head of sorted fieldlist. Sorting 73 | criteria is (row,column). This is a circular list. 74 | 75 | Return Values : New head of sorted fieldlist 76 +--------------------------------------------------------------------------*/ 77 static FIELD *Insert_Field_By_Position(FIELD *newfield, FIELD *head) 78 { 79 FIELD *current, *newhead; 80 81 assert(newfield); 82 83 if (!head) 84 { /* empty list is trivial */ 85 newhead = newfield->snext = newfield->sprev = newfield; 86 } 87 else 88 { 89 newhead = current = head; 90 while((current->frow < newfield->frow) || 91 ((current->frow==newfield->frow) && 92 (current->fcol < newfield->fcol)) ) 93 { 94 current = current->snext; 95 if (current==head) 96 { /* We cycled through. Reset head to indicate that */ 97 head = (FIELD *)0; 98 break; 99 } 100 } 101 /* we leave the loop with current pointing to the field after newfield*/ 102 newfield->snext = current; 103 newfield->sprev = current->sprev; 104 newfield->snext->sprev = newfield; 105 newfield->sprev->snext = newfield; 106 if (current==head) 107 newhead = newfield; 108 } 109 return(newhead); 110 } 111 112 /*--------------------------------------------------------------------------- 113 | Facility : libnform 114 | Function : static void Disconnect_Fields(FORM *form) 115 | 116 | Description : Break association between form and array of fields. 117 | 118 | Return Values : - 119 +--------------------------------------------------------------------------*/ 120 static void Disconnect_Fields( FORM * form ) 121 { 122 if (form->field) 123 { 124 FIELD **fields; 125 126 for(fields=form->field;*fields;fields++) 127 { 128 if (form == (*fields)->form) 129 (*fields)->form = (FORM *)0; 130 } 131 132 form->rows = form->cols = 0; 133 form->maxfield = form->maxpage = -1; 134 form->field = (FIELD **)0; 135 if (form->page) 136 free(form->page); 137 form->page = (_PAGE *)0; 138 } 139 } 140 141 /*--------------------------------------------------------------------------- 142 | Facility : libnform 143 | Function : static int Connect_Fields(FORM *form, FIELD **fields) 144 | 145 | Description : Set association between form and array of fields. 146 | 147 | Return Values : E_OK - no error 148 | E_CONNECTED - a field is already connected 149 | E_BAD_ARGUMENT - Invalid form pointer or field array 150 | E_SYSTEM_ERROR - not enough memory 151 +--------------------------------------------------------------------------*/ 152 static int Connect_Fields(FORM * form, FIELD ** fields) 153 { 154 int field_cnt, j; 155 int page_nr; 156 int maximum_row_in_field, maximum_col_in_field; 157 _PAGE *pg; 158 159 assert(form); 160 161 form->field = fields; 162 form->maxfield = 0; 163 form->maxpage = 0; 164 165 if (!fields) 166 RETURN(E_OK); 167 168 page_nr = 0; 169 /* store formpointer in fields and count pages */ 170 for(field_cnt=0;fields[field_cnt];field_cnt++) 171 { 172 if (fields[field_cnt]->form) 173 RETURN(E_CONNECTED); 174 if ( field_cnt==0 || 175 (fields[field_cnt]->status & _NEWPAGE)) 176 page_nr++; 177 fields[field_cnt]->form = form; 178 } 179 if (field_cnt==0) 180 RETURN(E_BAD_ARGUMENT); 181 182 /* allocate page structures */ 183 if ( (pg = (_PAGE *)malloc(page_nr * sizeof(_PAGE))) != (_PAGE *)0 ) 184 { 185 form->page = pg; 186 } 187 else 188 RETURN(E_SYSTEM_ERROR); 189 190 /* Cycle through fields and calculate page boundaries as well as 191 size of the form */ 192 for(j=0;j<field_cnt;j++) 193 { 194 if (j==0) 195 pg->pmin = j; 196 else 197 { 198 if (fields[j]->status & _NEWPAGE) 199 { 200 pg->pmax = j-1; 201 pg++; 202 pg->pmin = j; 203 } 204 } 205 206 maximum_row_in_field = fields[j]->frow + fields[j]->rows; 207 maximum_col_in_field = fields[j]->fcol + fields[j]->cols; 208 209 if (form->rows < maximum_row_in_field) 210 form->rows = maximum_row_in_field; 211 if (form->cols < maximum_col_in_field) 212 form->cols = maximum_col_in_field; 213 } 214 215 pg->pmax = field_cnt-1; 216 form->maxfield = field_cnt; 217 form->maxpage = page_nr; 218 219 /* Sort fields on form pages */ 220 for(page_nr = 0;page_nr < form->maxpage; page_nr++) 221 { 222 FIELD *fld = (FIELD *)0; 223 for(j = form->page[page_nr].pmin;j <= form->page[page_nr].pmax;j++) 224 { 225 fields[j]->index = j; 226 fields[j]->page = page_nr; 227 fld = Insert_Field_By_Position(fields[j],fld); 228 } 229 form->page[page_nr].smin = fld->index; 230 form->page[page_nr].smax = fld->sprev->index; 231 } 232 RETURN(E_OK); 233 } 234 235 /*--------------------------------------------------------------------------- 236 | Facility : libnform 237 | Function : static int Associate_Fields(FORM *form, FIELD **fields) 238 | 239 | Description : Set association between form and array of fields. 240 | If there are fields, position to first active field. 241 | 242 | Return Values : E_OK - success 243 | any other - error occured 244 +--------------------------------------------------------------------------*/ 245 INLINE static int Associate_Fields(FORM *form, FIELD **fields) 246 { 247 int res = Connect_Fields(form,fields); 248 if (res == E_OK) 249 { 250 if (form->maxpage>0) 251 { 252 form->curpage = 0; 253 form_driver(form,FIRST_ACTIVE_MAGIC); 254 } 255 else 256 { 257 form->curpage = -1; 258 form->current = (FIELD *)0; 259 } 260 } 261 return(res); 262 } 263 264 /*--------------------------------------------------------------------------- 265 | Facility : libnform 266 | Function : FORM *new_form( FIELD **fields ) 267 | 268 | Description : Create new form with given array of fields. 269 | 270 | Return Values : Pointer to form. NULL if error occured. 271 +--------------------------------------------------------------------------*/ 272 NCURSES_EXPORT(FORM *) 273 new_form (FIELD ** fields) 274 { 275 int err = E_SYSTEM_ERROR; 276 277 FORM *form = (FORM *)malloc(sizeof(FORM)); 278 279 if (form) 280 { 281 *form = *_nc_Default_Form; 282 if ((err=Associate_Fields(form,fields))!=E_OK) 283 { 284 free_form(form); 285 form = (FORM *)0; 286 } 287 } 288 289 if (!form) 290 SET_ERROR(err); 291 292 return(form); 293 } 294 295 /*--------------------------------------------------------------------------- 296 | Facility : libnform 297 | Function : int free_form( FORM *form ) 298 | 299 | Description : Release internal memory associated with form. 300 | 301 | Return Values : E_OK - no error 302 | E_BAD_ARGUMENT - invalid form pointer 303 | E_POSTED - form is posted 304 +--------------------------------------------------------------------------*/ 305 NCURSES_EXPORT(int) 306 free_form (FORM * form) 307 { 308 if ( !form ) 309 RETURN(E_BAD_ARGUMENT); 310 311 if ( form->status & _POSTED) 312 RETURN(E_POSTED); 313 314 Disconnect_Fields( form ); 315 if (form->page) 316 free(form->page); 317 free(form); 318 319 RETURN(E_OK); 320 } 321 322 /*--------------------------------------------------------------------------- 323 | Facility : libnform 324 | Function : int set_form_fields( FORM *form, FIELD **fields ) 325 | 326 | Description : Set a new association of an array of fields to a form 327 | 328 | Return Values : E_OK - no error 329 | E_BAD_ARGUMENT - invalid form pointer 330 | E_POSTED - form is posted 331 +--------------------------------------------------------------------------*/ 332 NCURSES_EXPORT(int) 333 set_form_fields (FORM * form, FIELD ** fields) 334 { 335 FIELD **old; 336 int res; 337 338 if ( !form ) 339 RETURN(E_BAD_ARGUMENT); 340 341 if ( form->status & _POSTED ) 342 RETURN(E_POSTED); 343 344 old = form->field; 345 Disconnect_Fields( form ); 346 347 if( (res = Associate_Fields( form, fields )) != E_OK ) 348 Connect_Fields( form, old ); 349 350 RETURN(res); 351 } 352 353 /*--------------------------------------------------------------------------- 354 | Facility : libnform 355 | Function : FIELD **form_fields( const FORM *form ) 356 | 357 | Description : Retrieve array of fields 358 | 359 | Return Values : Pointer to field array 360 +--------------------------------------------------------------------------*/ 361 NCURSES_EXPORT(FIELD **) 362 form_fields (const FORM * form) 363 { 364 return (Normalize_Form( form )->field); 365 } 366 367 /*--------------------------------------------------------------------------- 368 | Facility : libnform 369 | Function : int field_count( const FORM *form ) 370 | 371 | Description : Retrieve number of fields 372 | 373 | Return Values : Number of fields, -1 if none are defined 374 +--------------------------------------------------------------------------*/ 375 NCURSES_EXPORT(int) 376 field_count (const FORM * form) 377 { 378 return (Normalize_Form( form )->maxfield); 379 } 380 381 /* frm_def.c ends here */ 382