1 /**************************************************************************** 2 * Copyright (c) 1998-2010,2012 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, 1995,1997 * 31 ****************************************************************************/ 32 33 #include "form.priv.h" 34 35 MODULE_ID("$Id: frm_def.c,v 1.26 2012/03/11 00:37:16 tom Exp $") 36 37 /* this can't be readonly */ 38 static FORM default_form = 39 { 40 0, /* status */ 41 0, /* rows */ 42 0, /* cols */ 43 0, /* currow */ 44 0, /* curcol */ 45 0, /* toprow */ 46 0, /* begincol */ 47 -1, /* maxfield */ 48 -1, /* maxpage */ 49 -1, /* curpage */ 50 ALL_FORM_OPTS, /* opts */ 51 (WINDOW *)0, /* win */ 52 (WINDOW *)0, /* sub */ 53 (WINDOW *)0, /* w */ 54 (FIELD **)0, /* field */ 55 (FIELD *)0, /* current */ 56 (_PAGE *) 0, /* page */ 57 (char *)0, /* usrptr */ 58 NULL, /* forminit */ 59 NULL, /* formterm */ 60 NULL, /* fieldinit */ 61 NULL /* fieldterm */ 62 }; 63 64 NCURSES_EXPORT_VAR(FORM *) _nc_Default_Form = &default_form; 65 66 /*--------------------------------------------------------------------------- 67 | Facility : libnform 68 | Function : static FIELD *Insert_Field_By_Position( 69 | FIELD *new_field, 70 | FIELD *head ) 71 | 72 | Description : Insert new_field into sorted fieldlist with head "head" 73 | and return new head of sorted fieldlist. Sorting 74 | criteria is (row,column). This is a circular list. 75 | 76 | Return Values : New head of sorted fieldlist 77 +--------------------------------------------------------------------------*/ 78 static FIELD * 79 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 123 Disconnect_Fields(FORM *form) 124 { 125 if (form->field) 126 { 127 FIELD **fields; 128 129 for (fields = form->field; *fields; fields++) 130 { 131 if (form == (*fields)->form) 132 (*fields)->form = (FORM *)0; 133 } 134 135 form->rows = form->cols = 0; 136 form->maxfield = form->maxpage = -1; 137 form->field = (FIELD **)0; 138 if (form->page) 139 free(form->page); 140 form->page = (_PAGE *) 0; 141 } 142 } 143 144 /*--------------------------------------------------------------------------- 145 | Facility : libnform 146 | Function : static int Connect_Fields(FORM *form, FIELD **fields) 147 | 148 | Description : Set association between form and array of fields. 149 | 150 | Return Values : E_OK - no error 151 | E_CONNECTED - a field is already connected 152 | E_BAD_ARGUMENT - Invalid form pointer or field array 153 | E_SYSTEM_ERROR - not enough memory 154 +--------------------------------------------------------------------------*/ 155 static int 156 Connect_Fields(FORM *form, FIELD **fields) 157 { 158 int field_cnt, j; 159 int page_nr; 160 int maximum_row_in_field, maximum_col_in_field; 161 _PAGE *pg; 162 163 T((T_CALLED("Connect_Fields(%p,%p)"), (void *)form, (void *)fields)); 164 165 assert(form); 166 167 form->field = fields; 168 form->maxfield = 0; 169 form->maxpage = 0; 170 171 if (!fields) 172 RETURN(E_OK); 173 174 page_nr = 0; 175 /* store formpointer in fields and count pages */ 176 for (field_cnt = 0; fields[field_cnt]; field_cnt++) 177 { 178 if (fields[field_cnt]->form) 179 RETURN(E_CONNECTED); 180 if (field_cnt == 0 || 181 (fields[field_cnt]->status & _NEWPAGE)) 182 page_nr++; 183 fields[field_cnt]->form = form; 184 } 185 if (field_cnt == 0 || (short)field_cnt < 0) 186 RETURN(E_BAD_ARGUMENT); 187 188 /* allocate page structures */ 189 if ((pg = typeMalloc(_PAGE, page_nr)) != (_PAGE *) 0) 190 { 191 T((T_CREATE("_PAGE %p"), (void *)pg)); 192 form->page = pg; 193 } 194 else 195 RETURN(E_SYSTEM_ERROR); 196 197 /* Cycle through fields and calculate page boundaries as well as 198 size of the form */ 199 for (j = 0; j < field_cnt; j++) 200 { 201 if (j == 0) 202 pg->pmin = (short) j; 203 else 204 { 205 if (fields[j]->status & _NEWPAGE) 206 { 207 pg->pmax = (short) (j - 1); 208 pg++; 209 pg->pmin = (short) j; 210 } 211 } 212 213 maximum_row_in_field = fields[j]->frow + fields[j]->rows; 214 maximum_col_in_field = fields[j]->fcol + fields[j]->cols; 215 216 if (form->rows < maximum_row_in_field) 217 form->rows = (short) maximum_row_in_field; 218 if (form->cols < maximum_col_in_field) 219 form->cols = (short) maximum_col_in_field; 220 } 221 222 pg->pmax = (short) (field_cnt - 1); 223 form->maxfield = (short) field_cnt; 224 form->maxpage = (short) page_nr; 225 226 /* Sort fields on form pages */ 227 for (page_nr = 0; page_nr < form->maxpage; page_nr++) 228 { 229 FIELD *fld = (FIELD *)0; 230 231 for (j = form->page[page_nr].pmin; j <= form->page[page_nr].pmax; j++) 232 { 233 fields[j]->index = (short) j; 234 fields[j]->page = (short) page_nr; 235 fld = Insert_Field_By_Position(fields[j], fld); 236 } 237 if (fld) 238 { 239 form->page[page_nr].smin = fld->index; 240 form->page[page_nr].smax = fld->sprev->index; 241 } 242 else 243 { 244 form->page[page_nr].smin = 0; 245 form->page[page_nr].smax = 0; 246 } 247 } 248 RETURN(E_OK); 249 } 250 251 /*--------------------------------------------------------------------------- 252 | Facility : libnform 253 | Function : static int Associate_Fields(FORM *form, FIELD **fields) 254 | 255 | Description : Set association between form and array of fields. 256 | If there are fields, position to first active field. 257 | 258 | Return Values : E_OK - success 259 | E_BAD_ARGUMENT - Invalid form pointer or field array 260 | E_CONNECTED - a field is already connected 261 | E_SYSTEM_ERROR - not enough memory 262 +--------------------------------------------------------------------------*/ 263 NCURSES_INLINE static int 264 Associate_Fields(FORM *form, FIELD **fields) 265 { 266 int res = Connect_Fields(form, fields); 267 268 if (res == E_OK) 269 { 270 if (form->maxpage > 0) 271 { 272 form->curpage = 0; 273 form_driver(form, FIRST_ACTIVE_MAGIC); 274 } 275 else 276 { 277 form->curpage = -1; 278 form->current = (FIELD *)0; 279 } 280 } 281 return (res); 282 } 283 284 /*--------------------------------------------------------------------------- 285 | Facility : libnform 286 | Function : FORM *new_form_sp(SCREEN* sp, FIELD** fields ) 287 | 288 | Description : Create new form with given array of fields. 289 | 290 | Return Values : Pointer to form. NULL if error occurred. 291 ! Set errno: 292 | E_OK - success 293 | E_BAD_ARGUMENT - Invalid form pointer or field array 294 | E_CONNECTED - a field is already connected 295 | E_SYSTEM_ERROR - not enough memory 296 +--------------------------------------------------------------------------*/ 297 NCURSES_EXPORT(FORM *) 298 NCURSES_SP_NAME(new_form) (NCURSES_SP_DCLx FIELD **fields) 299 { 300 int err = E_SYSTEM_ERROR; 301 FORM *form = (FORM *)0; 302 303 T((T_CALLED("new_form(%p,%p)"), (void *)SP_PARM, (void *)fields)); 304 305 if (IsValidScreen(SP_PARM)) 306 { 307 form = typeMalloc(FORM, 1); 308 309 if (form) 310 { 311 T((T_CREATE("form %p"), (void *)form)); 312 *form = *_nc_Default_Form; 313 /* This ensures win and sub are always non-null, 314 so we can derive always the SCREEN that this form is 315 running on. */ 316 form->win = StdScreen(SP_PARM); 317 form->sub = StdScreen(SP_PARM); 318 if ((err = Associate_Fields(form, fields)) != E_OK) 319 { 320 free_form(form); 321 form = (FORM *)0; 322 } 323 } 324 } 325 326 if (!form) 327 SET_ERROR(err); 328 329 returnForm(form); 330 } 331 332 /*--------------------------------------------------------------------------- 333 | Facility : libnform 334 | Function : FORM* new_form(FIELD** fields ) 335 | 336 | Description : Create new form with given array of fields. 337 | 338 | Return Values : Pointer to form. NULL if error occurred. 339 ! Set errno: 340 | E_OK - success 341 | E_BAD_ARGUMENT - Invalid form pointer or field array 342 | E_CONNECTED - a field is already connected 343 | E_SYSTEM_ERROR - not enough memory 344 +--------------------------------------------------------------------------*/ 345 #if NCURSES_SP_FUNCS 346 NCURSES_EXPORT(FORM *) 347 new_form(FIELD **fields) 348 { 349 return NCURSES_SP_NAME(new_form) (CURRENT_SCREEN, fields); 350 } 351 #endif 352 353 /*--------------------------------------------------------------------------- 354 | Facility : libnform 355 | Function : int free_form( FORM *form ) 356 | 357 | Description : Release internal memory associated with form. 358 | 359 | Return Values : E_OK - no error 360 | E_BAD_ARGUMENT - invalid form pointer 361 | E_POSTED - form is posted 362 +--------------------------------------------------------------------------*/ 363 NCURSES_EXPORT(int) 364 free_form(FORM *form) 365 { 366 T((T_CALLED("free_form(%p)"), (void *)form)); 367 368 if (!form) 369 RETURN(E_BAD_ARGUMENT); 370 371 if (form->status & _POSTED) 372 RETURN(E_POSTED); 373 374 Disconnect_Fields(form); 375 if (form->page) 376 free(form->page); 377 free(form); 378 379 RETURN(E_OK); 380 } 381 382 /*--------------------------------------------------------------------------- 383 | Facility : libnform 384 | Function : int set_form_fields( FORM *form, FIELD **fields ) 385 | 386 | Description : Set a new association of an array of fields to a form 387 | 388 | Return Values : E_OK - no error 389 | E_BAD_ARGUMENT - Invalid form pointer or field array 390 | E_CONNECTED - a field is already connected 391 | E_POSTED - form is posted 392 | E_SYSTEM_ERROR - not enough memory 393 +--------------------------------------------------------------------------*/ 394 NCURSES_EXPORT(int) 395 set_form_fields(FORM *form, FIELD **fields) 396 { 397 FIELD **old; 398 int res; 399 400 T((T_CALLED("set_form_fields(%p,%p)"), (void *)form, (void *)fields)); 401 402 if (!form) 403 RETURN(E_BAD_ARGUMENT); 404 405 if (form->status & _POSTED) 406 RETURN(E_POSTED); 407 408 old = form->field; 409 Disconnect_Fields(form); 410 411 if ((res = Associate_Fields(form, fields)) != E_OK) 412 Connect_Fields(form, old); 413 414 RETURN(res); 415 } 416 417 /*--------------------------------------------------------------------------- 418 | Facility : libnform 419 | Function : FIELD **form_fields( const FORM *form ) 420 | 421 | Description : Retrieve array of fields 422 | 423 | Return Values : Pointer to field array 424 +--------------------------------------------------------------------------*/ 425 NCURSES_EXPORT(FIELD **) 426 form_fields(const FORM *form) 427 { 428 T((T_CALLED("form_field(%p)"), (const void *)form)); 429 returnFieldPtr(Normalize_Form(form)->field); 430 } 431 432 /*--------------------------------------------------------------------------- 433 | Facility : libnform 434 | Function : int field_count( const FORM *form ) 435 | 436 | Description : Retrieve number of fields 437 | 438 | Return Values : Number of fields, -1 if none are defined 439 +--------------------------------------------------------------------------*/ 440 NCURSES_EXPORT(int) 441 field_count(const FORM *form) 442 { 443 T((T_CALLED("field_count(%p)"), (const void *)form)); 444 445 returnCode(Normalize_Form(form)->maxfield); 446 } 447 448 /* frm_def.c ends here */ 449