1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*      Copyright (c) 1988 AT&T     */
  23 /*        All Rights Reserved   */
  24 
  25 
  26 /*
  27  *      Copyright (c) 1997, by Sun Microsystems, Inc.
  28  *      All rights reserved.
  29  */
  30 
  31 /*
  32  * Copyright (c) 2018, Joyent, Inc.
  33  */
  34 
  35 /*LINTLIBRARY*/
  36 
  37 #include <sys/types.h>
  38 #include <stdlib.h>
  39 #include "utility.h"
  40 
  41         /*
  42          *  default field
  43          */
  44 
  45 static FIELD default_field =
  46 {
  47                         0,                      /* status       */
  48                         0,                      /* rows         */
  49                         0,                      /* cols         */
  50                         0,                      /* frow         */
  51                         0,                      /* fcol         */
  52                         0,                      /* drows        */
  53                         0,                      /* dcols        */
  54                         0,                      /* maxgrow      */
  55                         0,                      /* nrow         */
  56                         0,                      /* nbuf         */
  57                         NO_JUSTIFICATION,       /* just         */
  58                         0,                      /* page         */
  59                         0,                      /* index        */
  60                         ' ',                    /* pad          */
  61                         A_NORMAL,               /* fore         */
  62                         A_NORMAL,               /* back         */
  63                         O_VISIBLE       |
  64                         O_ACTIVE        |
  65                         O_PUBLIC        |
  66                         O_EDIT          |
  67                         O_WRAP          |
  68                         O_BLANK         |
  69                         O_AUTOSKIP      |
  70                         O_NULLOK        |
  71                         O_PASSOK        |
  72                         O_STATIC,               /* opts         */
  73                         (FIELD *)0,             /* snext        */
  74                         (FIELD *)0,             /* sprev        */
  75                         (FIELD *)0,             /* link         */
  76                         (FORM *)0,              /* form         */
  77                         (FIELDTYPE *)0,         /* type         */
  78                         (char *)0,              /* arg          */
  79                         (char *)0,              /* buf          */
  80                         (char *)0,              /* usrptr       */
  81 };
  82 
  83 FIELD * _DEFAULT_FIELD  = &default_field;
  84 
  85         /*
  86          *  MakeType
  87          */
  88 
  89 static int
  90 MakeType(FIELD *f, va_list *ap)
  91 {
  92         int err = 0;
  93 
  94         f->arg = MakeArg(f, ap, &err);   /* pick off type specific args  */
  95 
  96         if (err) {
  97                 FreeArg(f);             /* release type specific args   */
  98                 f->type = (FIELDTYPE *)0;
  99                 f->arg = (char *)0;
 100                 return (FALSE);
 101         }
 102         IncrType(f->type);           /* increment reference count    */
 103         return (TRUE);
 104 }
 105 
 106         /*
 107          *  CopyType
 108          */
 109 
 110 static int
 111 CopyType(FIELD *f, FIELD *fsrc)
 112 {
 113         int err = 0;
 114 
 115         f->type = fsrc->type;             /* copy field type              */
 116         f->arg = CopyArg(fsrc, &err);    /* copy type specific info      */
 117 
 118         if (err) {
 119                 FreeArg(f);             /* release type specific args   */
 120                 f->type = (FIELDTYPE *)0;
 121                 f->arg = (char *)0;
 122                 return (FALSE);
 123         }
 124         IncrType(f->type);           /* increment reference count    */
 125         return (TRUE);
 126 }
 127 
 128         /*
 129          *  FreeType
 130          */
 131 
 132 static void
 133 FreeType(FIELD *f)
 134 {
 135         DecrType(f->type);           /* decrement reference count    */
 136         FreeArg(f);                     /* release type specific args   */
 137 }
 138 
 139         /*
 140          *  new_field
 141          */
 142 
 143 FIELD *
 144 new_field(int rows, int cols, int frow, int fcol, int nrow, int nbuf)
 145 
 146 /* int rows;     number of visible rows         */
 147 /* int cols;     number of visible cols         */
 148 /* int frow;     first row relative to form origin      */
 149 /* int fcol;     first col relative to form origin      */
 150 /* int nrow;     number of off screen rows              */
 151 /* int nbuf;     number of additional buffers           */
 152 {
 153         FIELD *f = (FIELD *) 0;
 154         int i, size;
 155 
 156         if (rows > 0 &&      cols > 0 && frow >= 0 && fcol >= 0 && nrow >= 0 &&
 157             nbuf >= 0 && Alloc(f, FIELD)) {
 158                 *f = *_DEFAULT_FIELD;
 159 
 160                 f->rows      = rows;
 161                 f->cols      = cols;
 162                 f->frow      = frow;
 163                 f->fcol      = fcol;
 164                 f->drows     = rows + nrow;
 165                 f->dcols     = cols;
 166                 f->nrow      = nrow;
 167                 f->nbuf      = nbuf;
 168                 f->link      = f;
 169 
 170                 if (CopyType(f, _DEFAULT_FIELD)) {
 171                         size = TotalBuf(f);
 172 
 173                         if (arrayAlloc(Buf(f), size, char)) {
 174                                 (void) memset(Buf(f), ' ', size);
 175 
 176                                 for (i = 0; i <= f->nbuf; ++i)
 177                                         *(Buffer(f, i + 1) - 1) = '\0';
 178                                 return (f);
 179                         }
 180                 }
 181         }
 182         (void) free_field(f);
 183         return ((FIELD *) 0);
 184 }
 185 
 186         /*
 187          *  dup_field
 188          */
 189 
 190 FIELD *
 191 dup_field(FIELD *field, int frow, int fcol)
 192 
 193 /* FIELD * field;        field to duplicate             */
 194 /* int frow;     first row relative to form origin      */
 195 /* int fcol;     first col relative to form origin      */
 196 {
 197         FIELD *f = (FIELD *) 0;
 198         int size;
 199 
 200         if (field && frow >= 0 && fcol >= 0 && Alloc(f, FIELD)) {
 201                 *f = *_DEFAULT_FIELD;
 202 
 203                 f->frow = frow;
 204                 f->fcol = fcol;
 205                 f->link = f;
 206 
 207                 f->rows      = field->rows;
 208                 f->cols      = field->cols;
 209                 f->drows = field->drows;
 210                 f->dcols = field->dcols;
 211                 f->maxgrow = field->maxgrow;
 212                 f->nrow = field->nrow;
 213                 f->nbuf      = field->nbuf;
 214                 f->just = field->just;
 215                 f->fore      = field->fore;
 216                 f->back      = field->back;
 217                 f->pad       = field->pad;
 218                 f->opts      = field->opts;
 219                 f->usrptr = field->usrptr;
 220                 f->status = Status(field, GROWABLE);
 221 
 222                 if (CopyType(f, field)) {
 223                         size = TotalBuf(f);
 224 
 225                         if (arrayAlloc(Buf(f), size, char)) {
 226                                 (void) memcpy(Buf(f), Buf(field), size);
 227                                 return (f);
 228                         }
 229                 }
 230         }
 231         (void) free_field(f);
 232         return ((FIELD *) 0);
 233 }
 234 
 235         /*
 236          *  link_field
 237          */
 238 
 239 FIELD *
 240 link_field(FIELD *field, int frow, int fcol)
 241 
 242 /* FIELD * field;        field to link to               */
 243 /* int frow;     first row relative to form origin      */
 244 /* int fcol;     first col relative to form origin      */
 245 {
 246         FIELD *f = (FIELD *) 0;
 247 
 248         if (field && frow >= 0 && fcol >= 0 && Alloc(f, FIELD)) {
 249                 *f = *_DEFAULT_FIELD;
 250 
 251                 f->frow = frow;
 252                 f->fcol = fcol;
 253 
 254                 f->link = field->link;
 255                 field->link = f;             /* add field to linked list */
 256 
 257                 f->buf       = field->buf;
 258                 f->rows      = field->rows;
 259                 f->cols      = field->cols;
 260                 f->drows = field->drows;
 261                 f->dcols = field->dcols;
 262                 f->maxgrow = field->maxgrow;
 263                 f->nrow      = field->nrow;
 264                 f->nbuf      = field->nbuf;
 265                 f->just      = field->just;
 266                 f->fore      = field->fore;
 267                 f->back      = field->back;
 268                 f->pad       = field->pad;
 269                 f->opts      = field->opts;
 270                 f->usrptr = field->usrptr;
 271                 f->status = Status(field, GROWABLE);
 272 
 273                 if (CopyType(f, field))
 274                         return (f);
 275         }
 276         (void) free_field(f);
 277         return ((FIELD *) 0);
 278 }
 279 
 280         /*
 281          *  free_field
 282          */
 283 
 284 int
 285 free_field(FIELD *f)
 286 {
 287         FIELD *p;
 288 
 289         if (!f)
 290                 return (E_BAD_ARGUMENT);
 291 
 292         if (f->form)
 293                 return (E_CONNECTED);
 294 
 295         if (f->link != f) {  /* check for linked field */
 296                 for (p = f->link; p->link != f; p = p->link)
 297                         ;
 298                 p->link = f->link;        /* delete from list     */
 299         } else
 300                 Free(Buf(f));           /* free buffer space    */
 301 
 302         FreeType(f);
 303         Free(f);
 304         return (E_OK);
 305 }
 306 
 307         /*
 308          *  field_info
 309          */
 310 
 311 int
 312 field_info(FIELD *f, int *rows, int *cols, int *frow, int *fcol,
 313         int *nrow, int *nbuf)
 314 
 315 /* FIELD *f;    field whose information is wanted */
 316 /* int *rows;   number of visible rows          */
 317 /* int *cols;   number of visible cols          */
 318 /* int *frow;   first row relative to form origin */
 319 /* int *fcol;   first col relative to form origin */
 320 /* int *nrow;   number of off screen rows       */
 321 /* int *nbuf;   number of additional buffers    */
 322 {
 323         if (!f)
 324                 return (E_BAD_ARGUMENT);
 325 
 326         *rows = f->rows;
 327         *cols = f->cols;
 328         *frow = f->frow;
 329         *fcol = f->fcol;
 330         *nrow = f->nrow;
 331         *nbuf = f->nbuf;
 332         return (E_OK);
 333 }
 334 
 335         /*
 336          *  set_max_field
 337          */
 338 
 339 int
 340 set_max_field(FIELD *f, int max)
 341 {
 342         BOOLEAN onerow;
 343 
 344         if (!f)
 345                 return (E_BAD_ARGUMENT);
 346 
 347         onerow = OneRow(f);
 348 
 349         if (max && ((onerow && f->dcols > max) ||
 350             (!onerow && f->drows > max)))
 351                 return (E_BAD_ARGUMENT);
 352 
 353         f->maxgrow = max;
 354         Clr(f, GROWABLE);
 355 
 356         if (!Opt(f, O_STATIC) && ((!max || onerow && f->dcols < max) ||
 357             (!onerow && f->drows < max))) {
 358                 Set(f, GROWABLE);
 359         }
 360 
 361         return (E_OK);
 362 }
 363 
 364         /*
 365          *  dynamic_field_info
 366          */
 367 
 368 int
 369 dynamic_field_info(FIELD *f, int *drows, int *dcols, int *max)
 370 
 371 /* FIELD *f;     field whose information is wanted */
 372 /* int *drows;   number of actual rows  */
 373 /* int *dcols;   number of actual cols  */
 374 /* int *max;     maximum growth allowable, else -1 */
 375 {
 376         if (!f)
 377                 return (E_BAD_ARGUMENT);
 378 
 379         *drows = f->drows;
 380         *dcols = f->dcols;
 381         *max   = f->maxgrow;
 382         return (E_OK);
 383 }
 384 
 385         /*
 386          *  move_field
 387          */
 388 
 389 int
 390 move_field(FIELD *f, int frow, int fcol)
 391 
 392 /* FIELD *f;    field to move   */
 393 /* int frow;    first row relative to form origin */
 394 /* int fcol;    first col relative to form origin */
 395 {
 396         if (! f || frow < 0 || fcol < 0)
 397                 return (E_BAD_ARGUMENT);
 398 
 399         if (f->form)
 400                 return (E_CONNECTED);
 401 
 402         f->frow = frow;
 403         f->fcol = fcol;
 404         return (E_OK);
 405 }
 406 
 407         /*
 408          *  set_field_type
 409          */
 410 
 411 int
 412 set_field_type(FIELD *f, FIELDTYPE *ft, ...)
 413 {
 414         va_list         ap;
 415         int             v = E_SYSTEM_ERROR;
 416 
 417         va_start(ap, ft);
 418         f = Field(f);
 419         FreeType(f);                            /* free old type        */
 420         f->type = ft;
 421 
 422         if (MakeType(f, &ap))                       /* set up new type      */
 423                 v = E_OK;
 424         va_end(ap);
 425         return (v);
 426 }
 427 
 428 FIELDTYPE *
 429 field_type(FIELD *f)
 430 {
 431         return (Field(f)->type);
 432 }
 433 
 434 char *
 435 field_arg(FIELD *f)
 436 {
 437         return (Field(f)->arg);
 438 }
 439 
 440         /*
 441          *  set_new_page
 442          */
 443 
 444 int
 445 set_new_page(FIELD *f, int flag)
 446 {
 447         f = Field(f);
 448 
 449         if (f->form)
 450                 return (E_CONNECTED);
 451 
 452         if (flag)
 453                 Set(f, NEW_PAGE);
 454         else
 455                 Clr(f, NEW_PAGE);
 456 
 457         return (E_OK);
 458 }
 459 
 460 int
 461 new_page(FIELD *f)
 462 {
 463         if (Status(Field(f), NEW_PAGE))
 464                 return (TRUE);
 465         else
 466                 return (FALSE);
 467 }