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