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