/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ /* * Copyright (c) 1997, by Sun Microsystems, Inc. * All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.8 */ /*LINTLIBRARY*/ #include <sys/types.h> #include <stdlib.h> #include "utility.h" #define MAX_BUF 81 /* default form */ static FORM default_form = { 0, /* status */ 0, /* rows */ 0, /* cols */ 0, /* currow */ 0, /* curcol */ 0, /* toprow */ 0, /* begincol */ -1, /* maxfield */ -1, /* maxpage */ -1, /* curpage */ O_NL_OVERLOAD | O_BS_OVERLOAD, /* opts */ (WINDOW *) 0, /* win */ (WINDOW *) 0, /* sub */ (WINDOW *) 0, /* w */ (FIELD **) 0, /* field */ (FIELD *) 0, /* current */ (_PAGE *) 0, /* page */ (char *) 0, /* usrptr */ (PTF_void) 0, /* forminit */ (PTF_void) 0, /* formterm */ (PTF_void) 0, /* fieldinit */ (PTF_void) 0, /* fieldterm */ }; FORM * _DEFAULT_FORM = &default_form; /* * insert - insert field f into sorted list pointed * to by head. return (possibly new) head of list. */ static FIELD * insert(FIELD *f, FIELD *head) { FIELD *p; FIELD *newhead; int frow, fcol; if (head) { p = newhead = head; frow = f->frow; fcol = f->fcol; while ((p->frow < frow) || (p->frow == frow && p->fcol < fcol)) { p = p->snext; if (p == head) { head = (FIELD *) 0; break; } } f->snext = p; f->sprev = p->sprev; f->snext->sprev = f; f->sprev->snext = f; if (p == head) newhead = f; /* insert at head of list */ } else newhead = f->sprev = f->snext = f; /* initialize new list */ return (newhead); } /* sort_form - sort fields on form(per page) */ static void sort_form(FORM *f) { FIELD **field; FIELD *p; int i, page, pmin, pmax; field = f->field; for (page = 0; page < f->maxpage; ++page) { /* for each page */ p = (FIELD *) 0; pmin = Pmin(f, page); pmax = Pmax(f, page); for (i = pmin; i <= pmax; ++i) { /* for each field */ field[i]->index = i; field[i]->page = page; p = insert(field[i], p); } Smin(f, page) = p->index; /* set sorted min */ Smax(f, page) = p->sprev->index; /* set sorted max */ } } /* merge - xmax/ymax is the minimum window size to hold field f */ static void merge(FIELD *f, FORM *form) /* adjust form dimensions to include field f */ { int xmax = f->fcol + f->cols; int ymax = f->frow + f->rows; if (form->rows < ymax) form->rows = ymax; if (form->cols < xmax) form->cols = xmax; } /* disconnect_fields - disconnect fields from form */ static void disconnect_fields(FORM *form) { FIELD **f = form->field; if (f) while (*f) { if ((*f)->form == form) (*f)->form = (FORM *) 0; ++f; } form->rows = 0; form->cols = 0; form->maxfield = -1; form->maxpage = -1; form->field = (FIELD **) 0; } /* connect_fields - connect fields to form */ static int connect_fields(FORM *f, FIELD **x) { _PAGE * page; int nf, /* number of fields */ np; /* number of pages */ int i; f->field = x; f->maxfield = 0; f->maxpage = 0; if (!x) return (E_OK); /* null field array */ for (nf = 0, np = 0; x[nf]; ++nf) { if (nf == 0 || Status(x[nf], NEW_PAGE)) ++np; /* count pages */ if (x[nf]->form) return (E_CONNECTED); else x[nf]->form = f; /* connect field to form */ } if (nf == 0) return (E_BAD_ARGUMENT); /* no fields */ if (arrayAlloc(f->page, np, _PAGE)) { page = f->page; for (i = 0; i < nf; ++i) { if (i == 0) page->pmin = i; else if (Status(x[i], NEW_PAGE)) { page->pmax = i - 1; ++page; page->pmin = i; } merge(x[i], f); } page->pmax = nf - 1; f->maxfield = nf; f->maxpage = np; sort_form(f); return (E_OK); } return (E_SYSTEM_ERROR); } FORM * new_form(FIELD **field) { FORM *f; if (Alloc(f, FORM)) { *f = *_DEFAULT_FORM; if (connect_fields(f, field) == E_OK) { if (f->maxpage) { P(f) = 0; C(f) = _first_active(f); } else { P(f) = -1; C(f) = (FIELD *) 0; } return (f); } } (void) free_form(f); return ((FORM *) 0); } int free_form(FORM *f) { if (!f) return (E_BAD_ARGUMENT); if (Status(f, POSTED)) return (E_POSTED); disconnect_fields(f); Free(f->page); Free(f); return (E_OK); } int set_form_fields(FORM *f, FIELD **fields) { FIELD **p; int v; if (!f) return (E_BAD_ARGUMENT); if (Status(f, POSTED)) return (E_POSTED); p = f->field; disconnect_fields(f); if ((v = connect_fields(f, fields)) == E_OK) { if (f->maxpage) { P(f) = 0; C(f) = _first_active(f); } else { P(f) = -1; C(f) = (FIELD *) 0; } } else (void) connect_fields(f, p); /* reconnect original fields */ return (v); } FIELD ** form_fields(FORM *f) { return (Form(f)->field); } int field_count(FORM *f) { return (Form(f)->maxfield); } int scale_form(FORM *f, int *rows, int *cols) { if (!f) return (E_BAD_ARGUMENT); if (!f->field) return (E_NOT_CONNECTED); *rows = f->rows; *cols = f->cols; return (E_OK); } BOOLEAN data_behind(FORM *f) { return (OneRow(C(f)) ? B(f) != 0 : T(f) != 0); } /* _data_ahead - return ptr to last non-pad char in v[n] (v on failure) */ static char * _data_ahead(char *v, int pad, int n) { char *vend = v + n; while (vend > v && *(vend - 1) == pad) --vend; return (vend); } BOOLEAN data_ahead(FORM *f) { static char buf[ MAX_BUF ]; char *bptr = buf; WINDOW *w = W(f); FIELD *c = C(f); int ret = FALSE; int pad = Pad(c); int cols = c->cols; int dcols; int drows; int flag = cols > MAX_BUF - 1; int start; int chunk; if (flag) bptr = malloc(cols + 1); if (OneRow(c)) { dcols = c->dcols; start = B(f) + cols; while (start < dcols) { chunk = MIN(cols, dcols - start); (void) wmove(w, 0, start); (void) winnstr(w, bptr, chunk); if (bptr != _data_ahead(bptr, pad, chunk)) { ret = (TRUE); break; } start += cols; } } else { /* else multi-line field */ drows = c->drows; start = T(f) + c->rows; while (start < drows) { (void) wmove(w, start++, 0); (void) winnstr(w, bptr, cols); if (bptr != _data_ahead(bptr, pad, cols)) { ret = TRUE; break; } } } if (flag) (void) free(bptr); (void) wmove(w, Y(f), X(f)); return (ret); }