if_form.c revision d67944fbe3fa0b31893a7116a09b0718eecf6078
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <curses.h>
#include <sys/types.h> /* EFT abs k16 */
#include "wish.h"
#include "menudefs.h"
#include "message.h"
#include "token.h"
#include "vtdefs.h"
#include "ctl.h"
#include "slk.h"
#include "actrec.h"
#include "typetab.h"
#include "winp.h"
#include "form.h"
#include "fm_mn_par.h"
#include "objform.h"
#include "eval.h"
#include "terror.h"
#include "var_arrays.h"
#include "moremacros.h"
#include "interrupt.h"
#include "sizes.h"
#define FM_KEYS 13
#define FM_INTR PAR_INTR
#define FM_ONINTR PAR_ONINTR
#define FM_DONE PAR_DONE
#define FM_TITLE 3
#define FM_LIFE 4
#define FM_INIT 5
#define FM_BEGROW 6
#define FM_BEGCOL 7
#define FM_HELP 8
#define FM_REREAD 9
#define FM_CLOSE 10
#define FM_ALTSLKS 11
#define FM_FRMMSG 12
#define FM_FLD_KEYS 27
/* defined above abs
#define FM_INTR PAR_INTR
#define FM_ONINTR PAR_ONINTR
*/
#define FM_ACTI PAR_ACTION
#define FM_NAME PAR_NAME
#define FM_FROW 4
#define FM_FCOL 5
#define FM_NROW 6
#define FM_NCOL 7
#define FM_ROWS 8
#define FM_COLS 9
#define FM_FLEN 10
#define FM_VALUE 11
#define FM_RMENU 12
#define FM_CHOICEMSG 13
#define FM_VALID 14
#define FM_NOECHO 15
#define FM_MENUO 16
#define FM_SHOW 17
#define FM_SCROLL 18
#define FM_WRAP 19
#define FM_PAGE 20
#define FM_BUTT 21
#define FM_VALMSG 22
#define FM_INACTIVE 23
#define FM_FIELDMSG 24
#define FM_LININFO 25
#define FM_AUTOADVANCE 26
static struct attribute Fm_tab[FM_KEYS] = {
{ "interrupt", RET_STR|EVAL_ALWAYS, NULL, NULL, 0 },
{ "oninterrupt",RET_STR|EVAL_ALWAYS, NULL, NULL, 0 },
{ "done", RET_ARGS|EVAL_ALWAYS, "", NULL, 0 },
{ "form", RET_STR|EVAL_ONCE, "Form", NULL, 0 },
{ "lifetime", RET_STR|EVAL_ALWAYS, "longterm", NULL, 0 },
{ "init", RET_BOOL|EVAL_ALWAYS, "", NULL, 0 },
{ "begrow", RET_INT|EVAL_ONCE, "any", NULL, 0 },
{ "begcol", RET_INT|EVAL_ONCE, "any", NULL, 0 },
{ "help", RET_ARGS|EVAL_ALWAYS, "", NULL, 0 },
{ "reread", RET_BOOL|EVAL_ALWAYS, NULL, NULL, 0 },
{ "close", RET_BOOL|EVAL_ONCE, NULL, NULL, 0 },
{ "altslks", RET_BOOL|EVAL_ONCE, NULL, NULL, 0 },
{ "framemsg", RET_STR|EVAL_ONCE, "", NULL, 0 }
};
static struct attribute Fm_fld_tab[FM_FLD_KEYS] = {
{ "interrupt", RET_STR|EVAL_ALWAYS, NULL, NULL, 0 },
{ "oninterrupt",RET_STR|EVAL_ALWAYS, NULL, NULL, 0 },
{ "action", RET_ARGS|EVAL_ALWAYS, "", NULL, 0 },
{ "name", RET_STR|EVAL_ONCE, NULL, NULL, 0 },
{ "frow", RET_INT|EVAL_ONCE, "-1", NULL, 0 },
{ "fcol", RET_INT|EVAL_ONCE, "-1", NULL, 0 },
{ "nrow", RET_INT|EVAL_ONCE, "-1", NULL, 0 },
{ "ncol", RET_INT|EVAL_ONCE, "-1", NULL, 0 },
{ "rows", RET_INT|EVAL_ONCE, "1", NULL, 0 }, /* abs f15 */
{ "columns", RET_INT|EVAL_ONCE, "-1", NULL, 0 },
{ "flen", RET_INT|EVAL_ONCE, NULL, NULL, 0 },
{ "value", MAKE_COPY|RET_STR|EVAL_SOMETIMES,"", NULL, 0 },
{ "rmenu", RET_LIST|EVAL_ONCE|EV_SQUIG,"", NULL, 0 },
{ "choicemsg", RET_STR|EVAL_ONCE, NULL, NULL, 0 },
{ "valid", RET_BOOL|EVAL_SOMETIMES,"", NULL, 0 },
{ "noecho", RET_BOOL|EVAL_ONCE, NULL, NULL, 0 },
{ "menuonly", RET_BOOL|EVAL_ONCE, NULL, NULL, 0 },
{ "show", RET_BOOL|EVAL_SOMETIMES,"", NULL, 0 },
{ "scroll", RET_BOOL|EVAL_ONCE, NULL, NULL, 0 },
{ "wrap", RET_BOOL|EVAL_ONCE, NULL, NULL, 0 },
{ "page", RET_STR|EVAL_ONCE, "1", NULL, 0 },
{ "button", RET_INT|EVAL_ONCE, "0", NULL, 0 },
{ "invalidmsg", RET_STR|EVAL_SOMETIMES, NULL, NULL, 0 },
{ "inactive", RET_BOOL|EVAL_SOMETIMES, NULL, NULL, 0 },
{ "fieldmsg", RET_STR|EVAL_ALWAYS, NULL, NULL, 0 },
{ "lininfo", RET_STR|EVAL_ALWAYS, NULL, NULL, 0 },
{ "autoadvance",RET_BOOL|EVAL_ONCE, NULL, NULL, 0 }
};
char *itoa();
#define DEVirt(X) (((forminfo *) Cur_rec->odptr)->visible[X])
#define CURforminfo() ((forminfo *) Cur_rec->odptr)
#define CURform() (&(((forminfo *) Cur_rec->odptr)->fm_mn))
#define CURattr(x, y) ((CURform()->multi + x)->attrs[y])
#define NUMvis() (array_len(((forminfo *) Cur_rec->odptr)->visible))
#define NUMactive() (((forminfo *) Cur_rec->odptr)->numactive)
#define VALS() (((forminfo *) Cur_rec->odptr)->mulvals)
#define PTRS() (((forminfo *) Cur_rec->odptr)->holdptrs)
#define NUMflds() (array_len(((forminfo *) Cur_rec->odptr)->fm_mn.multi))
#define CURfield() (((forminfo *) Cur_rec->odptr)->curfield)
#define CURffield() (objform_disp(DEVirt(((forminfo *) Cur_rec->odptr)->curfield), CURforminfo()))
#define SET_curfield(X) (((forminfo *) Cur_rec->odptr)->curfield) = X
#define CURpage() ((((forminfo *) Cur_rec->odptr)->curpage))
#define LASTpage() ((((forminfo *) Cur_rec->odptr)->lastpage))
#define NUMSTR(X) (strcpy(Field_str + 1, itoa((long)X, 10)), Field_str) /* abs k16 */
extern int Mouse_row; /* Row offset of the mouse */
extern int Mouse_col; /* Column offset of the mouse */
extern int Toggle; /* when to "toggle" field choices (if_init.c) */
#define NX_ANY 0 /* pseudo flag */
#define NX_NOCUR 1
#define NX_ADVANCE 2
extern char *shrink_str();
extern char *expand();
extern char *getaltenv();
extern struct actrec *ar_create(), *ar_current();
static void chg_curfield();
static int objform_close();
static int objform_reinit();
static int objform_reread();
static int objform_current();
static int objform_noncur();
static int objform_ctl();
static int objform_stream();
static int fld_ck();
static int is_valid();
static struct fm_mn parse_form();
static struct actrec *Cur_rec; /* current activation record */
static char *Equal = "=";
static char *Field_str = "F000";
#define QUERY -1
#define TOOBIG 1000
#define TOOSMALL -1000
/*
* Returns the virtual index of the given actual field number ........
*
* The ACTUAL number is the order that the field appears in the form's
* definition file.
*
* The VIRTUAL number is the index into the VISIBLE array of fields
* (i.e., the subset of ACTUAL fields that contains only those fields
* that appear on the "current page" or whose "show" descriptor = "true").
*/
int
virt(i)
register int i;
{
register int j;
int lcv;
lcv = NUMvis();
for (j = 0; j < lcv; j++)
if (DEVirt(j) == i)
return(j);
return(0); /* not exactly right but better than garbage.. */
/* ..since no one checks the return value */
}
/*
** Starting with start, recalculate the values until they are
** all set. This works by faking out each value into being
** a control sequence and then substituting the real value for
** the control sequence
*/
int
redo_vals(start)
int start;
{
int changed;
register char *envbuf;
register int i;
char *hold1, *hold2;
char buf[BUFSIZ];
int lcv;
upseqno(CURform());
envbuf = buf;
lcv = NUMflds();
for (i = start; i < lcv; i++) {
strcpy(envbuf, NUMSTR(i + 1));
strcat(envbuf, "=\001");
strcat(envbuf, NUMSTR(i + 1));
putAltenv(envbuf);
}
changed = FALSE;
lcv = NUMflds();
for (i = start; i < lcv; i++) {
int dofree, maxamt, amt;
dofree = 0;
hold1 = multi_eval(CURform(), i, FM_VALUE);
maxamt = BUFSIZ - strlen(NUMSTR(i + 1)) - 2;
if ((amt = strlen(hold1)) > maxamt) {
/*
* Value is greater than 1K so malloc
* enough space to hold it.
*/
maxamt = amt + strlen(NUMSTR(i + 1)) + 2;
if ((envbuf = (char *) malloc(maxamt)) == NULL)
fatal(NOMEM, nil);
dofree++;
}
else {
/*
* ... otherwise, use static 1K buffer
*/
envbuf = buf;
dofree = 0;
}
strcpy(envbuf, NUMSTR(i + 1));
changed |= strcmp(hold1, (hold2 = getaltenv(VALS(), envbuf)) ?
hold2 : nil) == 0;
strcat(envbuf, Equal);
strncat(envbuf, hold1, maxamt);
putAltenv(envbuf);
putaltenv(&VALS(), envbuf);
if (dofree) /* if buffer was malloc'd, free it */
free(envbuf);
}
while (changed) {
changed = FALSE;
lcv = NUMflds();
for (i = start; i < lcv; i++) {
register char *p;
int dofree, amt, maxamt;
dofree = 0;
envbuf = buf;
strcpy(envbuf, NUMSTR(i + 1));
hold1 = getaltenv(VALS(), envbuf);
for (p = NULL; p = strchr(hold1, '\001'); )
*p = '$';
if (!p)
continue;
hold2 = expand(hold1);
maxamt = BUFSIZ - strlen(NUMSTR(i + 1)) - 2;
if ((amt = strlen(hold2)) > maxamt) {
/*
* Value is greater than 1K so malloc
* enough space to hold it.
*/
maxamt = amt + strlen(NUMSTR(i + 1)) + 2;
if ((envbuf = (char *) malloc(maxamt)) == NULL)
fatal(NOMEM, nil);
strcpy(envbuf, NUMSTR(i + 1));
dofree++;
}
else {
/*
* ... otherwise, use static 1K buffer
*/
dofree = 0;
}
strcat(envbuf, Equal);
strncat(envbuf, hold2, maxamt);
changed = TRUE;
free(hold2);
putaltenv(&VALS(), envbuf);
putAltenv(envbuf);
if (dofree)
free(envbuf);
}
}
return (0);
}
/*
** Returns the current value of the field, fieldno.
*/
char *
curval(fieldno)
int fieldno;
{
return(getaltenv(VALS(), NUMSTR(fieldno + 1)));
}
/*
** Figure out which fields are on the screen as decided by the show
** function values.
*/
int
fm_vislist(ptr)
forminfo *ptr;
{
int i, num;
struct fm_mn *fm_mn;
char *page;
int lcv;
fm_mn = &(ptr->fm_mn);
if (!ptr->visible) {
ptr->slks = (int *) array_create(sizeof(int),array_len(fm_mn->multi));
ptr->visible = (int *) array_create(sizeof(int), NUMflds());
}
else {
array_trunc(ptr->visible);
array_trunc(ptr->slks);
}
lcv = NUMflds();
NUMactive() = 0;
for (i = 0; i < lcv; i++) {
if (atoi(multi_eval(fm_mn, i, FM_BUTT))) {
/*
* SLK definition
*/
if (multi_eval(fm_mn, i, FM_SHOW))
ptr->slks = (int *) array_append(ptr->slks, (char *) &i);
}
else {
/*
* FIELD definition
*/
page = multi_eval(fm_mn, i, FM_PAGE);
num = atoi(page);
if (num > LASTpage())
LASTpage() = num; /* record last page */
/*
* Only make visible fields on the CURRENT
* page ...
*/
if ((num <= 0) || !page)
continue;
else if ((num == CURpage()) ||
(strcmp(page, "all") == 0) || (*page == '*')) {
/*
* add field to visible list ...
* keep track of the number of active fields
* for this page ...
*/
ptr->visible = (int *) array_append(ptr->visible, &i);
if (multi_eval(fm_mn, i, FM_SHOW) &&
(!multi_eval(fm_mn, i, FM_INACTIVE)))
NUMactive()++;
}
}
}
return (0);
}
static int
objform_reinit(a)
struct actrec *a;
{
Cur_rec = a;
if (sing_eval(CURform(), FM_REREAD))
return(objform_reread(a));
return(SUCCESS);
}
/*
** A front end to parser() which will set up most of the defaults for
** a form.
*/
static struct fm_mn
parse_form(flags, info_or_file, fp)
int flags;
char *info_or_file;
FILE *fp;
{
struct fm_mn fm_mn;
fm_mn.single.attrs = NULL;
fm_mn.multi = NULL;
filldef(&fm_mn.single, Fm_tab, FM_KEYS);
parser(flags, info_or_file, Fm_tab, FM_KEYS, &fm_mn.single,
Fm_fld_tab, FM_FLD_KEYS, &fm_mn.multi, fp);
return(fm_mn);
}
/*
** Read the form object indicated by this actrec, if a->id > 0
** then the object is being reread.
*/
static int
objform_reread(a)
struct actrec *a;
{
extern struct slk Defslk[MAX_SLK + 1];
extern struct slk Formslk[];
forminfo *fi;
register int i, but;
char *label, *intr, *onintr, *get_def();
int lcv;
FILE *fp = NULL;
Cur_rec = a;
fi = CURforminfo();
/* make sure file exists and is readable (if there is a file)
* The "flags" say if a->path is the information
* itself or the file of where the information sits. abs k15
*/
if (!(fi->flags & INLINE))
if ((fp = fopen(a->path, "r")) == NULL)
{
if (a->id >= 0) /* if frame is already posted */
warn(NOT_UPDATED, a->path);
else
warn(FRAME_NOPEN, a->path);
return(FAIL);
}
if (a->id >= 0)
freeitup(CURform()); /* if posted then free it old one */
fi->fm_mn = parse_form(fi->flags, a->path, fp); /* abs k14.0 */
if ((CURform())->single.attrs == NULL) {
#ifdef _DEBUG4
_debug4(stderr, "Couldn't parse it\n");
#endif
return(FAIL);
}
(CURform())->seqno = 1;
if (PTRS())
free(PTRS());
if (NUMflds() && (PTRS() = (char **) calloc(NUMflds(), sizeof(char *))) == NULL)
fatal(NOMEM, nil);
lcv = NUMflds();
for (i = 0; i < lcv; i++)
PTRS()[i] = (char *) NULL;
fi->visible = NULL; /* initialize array of visible fields */
fi->slks = NULL; /* initialize array of object's SLKS */
redo_vals(0); /* initialize field values */
fm_vislist(CURforminfo()); /* set up visible field list */
if (a->id < 0)
SET_curfield(-1);
/*
* If "init=false" or Form is empty then cleanup
*/
if (!sing_eval(CURform(), FM_INIT) || (NUMactive() <= 0))
{
if (a->id >= 0) /* form is already posted */
{
if (a->lifetime == AR_INITIAL)
{
mess_temp("can't close this frame");
mess_lock();
}
else
{
ar_close(a, FALSE);
return(FAIL);
}
}
else
{
sing_eval(CURform(), FM_CLOSE);
objform_noncur(a, TRUE); /* takes ARGs out of Altenv */
freeitup(CURform());
return(FAIL);
}
}
/*
* update the interrupt descriptors in the activation rec
*/
ar_ctl(a, CTSETINTR, get_sing_def(CURform(), FM_INTR), NULL, NULL, NULL, NULL, NULL);
ar_ctl(a, CTSETONINTR, get_sing_def(CURform(), FM_ONINTR), NULL, NULL, NULL, NULL, NULL);
/*
* Set up object specific SLK array
*/
set_top_slks(Formslk);
memcpy((char *)a->slks, (char *)Defslk, sizeof(Defslk));
lcv = array_len(fi->slks);
for (i = 0; i < lcv; i++) {
but = atoi(multi_eval(CURform(), fi->slks[i], FM_BUTT)) - 1;
if (but < 0 || but >= MAX_SLK) /* abs */
continue;
label = multi_eval(CURform(), fi->slks[i], FM_NAME);
intr = get_def(CURform(),fi->slks[i], FM_INTR);
onintr = get_def(CURform(),fi->slks[i], FM_ONINTR);
set_obj_slk(&(a->slks[but]), label, TOK_SLK1 + but, intr, onintr);
}
if (a->id >= 0) /* go to first field, first page */
{
vt_current(form_ctl(a->id, CTGETVT));
CURpage() = 1;
fm_vislist(CURforminfo());
form_ctl(a->id, CTSETPAGE, TRUE, 1, fi->lastpage);
nextfield(0, 0, 1, NX_ANY);
form_ctl(a->id, CTSETDIRTY);
/* used to just go to first field of current page..
ar_ctl(a, CTCLEARWIN, 0, NULL, NULL, NULL, NULL, NULL);
nextfield(0, 0, 1, NX_ANY);
form_ctl(a->id, CTSETDIRTY);
*/
}
(void) ar_ctl(Cur_rec, CTSETMSG, FALSE, NULL, NULL, NULL, NULL, NULL); /* was AR_cur. abs k15 */
return(SUCCESS);
}
/*
** Frees up the structures and evaluates the "close" function.
*/
static int
objform_close(a)
struct actrec *a;
{
register int i, lcv;
char *p, *strchr();
Cur_rec = a;
form_close(a->id); /* remove the form FIRST */
copyAltenv(VALS());
sing_eval(CURform(), FM_CLOSE); /* evaluate close function */
objform_noncur(a, FALSE); /* remove ARGs from Altenv */
/*
* Free information IN the forminfo structure
*/
freeitup(CURform()); /* the form parse table */
if (PTRS()) /* holdptrs array */
free(PTRS());
lcv = array_len(VALS());
for (i = 0; i < lcv; i++) { /* form specific variables */
char namebuf[BUFSIZ]; /* (e.g., F1, F2, .... ) */
if (p = strchr(VALS()[0], '='))
*p = '\0';
strcpy(namebuf, VALS()[0]);
if (p)
*p = '=';
delaltenv(&VALS(), namebuf);
}
array_destroy(VALS()); /* variables array */
array_destroy(((forminfo *)a->odptr)->slks); /* visible SLKS */
array_destroy(((forminfo *)a->odptr)->visible); /* visible fields */
/*
* Free information in the activation record
*/
free(a->odptr); /* the forminfo structure */
free(a->slks); /* object specific SLKS */
free(a->path); /* form definition file */
return(SUCCESS);
}
/*
** Takes this objects's information out of the major altenv.
*/
static int
objform_noncur(a, all)
struct actrec *a;
bool all;
{
register int i;
register char *p;
int lcv;
Cur_rec = a;
lcv = array_len(VALS());
for (i = 0; i < lcv; i++) {
char namebuf[BUFSIZ];
if (p = strchr(VALS()[i], '='))
*p = '\0';
strcpy(namebuf, VALS()[i]);
if (p)
*p = '=';
delAltenv(namebuf);
}
if (all)
return(form_noncurrent());
else
return(SUCCESS);
}
/*
** Sets up the major alternate environment based on the values
** for the altenv that pertains to this object.
*/
static int
objform_current(a)
struct actrec *a;
{
char *choice;
static char *Form_Choice = "Form_Choice";
/*
* Make the form "current" and make the first field
* current if this is the first time.
*/
Cur_rec = a;
form_current(a->id);
if (CURfield() == -1)
nextfield(0, 0, 1, NX_ANY);
/*
* Initialize the field with the value of variable "Form_Choice"
* (variable holds the selected item(s) from a choices menu)
*/
if (choice = getAltenv(Form_Choice)) {
copyAltenv(VALS());
if (set_curval(strsave(choice)) == SUCCESS) {
fm_vislist(CURforminfo());
redo_vals(CURfield() + 1);
form_ctl(Cur_rec->id, CTSETDIRTY);
if (multi_eval(CURform(), CURfield(), FM_AUTOADVANCE))
nextfield(atoi(CURattr(CURfield(),FM_FROW)->cur),
atoi(CURattr(CURfield(),FM_FCOL)->cur),
1, NX_NOCUR);
}
delAltenv(Form_Choice);
}
else
copyAltenv(VALS());
set_form_field(a->id, CURfield());
return(SUCCESS);
}
/*
** Sets up the major alternate environment based on the values
** for the altenv that pertains to this object.
** Does min neccessary to make object "temporarily" current,
** invisible to the user.
*/
static int
objform_temp_cur(a)
struct actrec *a;
{
/*
* Make the form "current"
*/
Cur_rec = a;
form_current(a->id);
if (CURfield() == -1)
nextfield(0, 0, 1, NX_ANY);
copyAltenv(VALS());
return(SUCCESS);
}
/*
** Evaluates many of the fields to return a form structure that includes
** name, value, their positions, editing capabilities and a structure
** that is held here and is used by the low-level form code to pertain
** to each field.
*/
static formfield
objform_disp(n, fi)
int n;
forminfo *fi;
{
register int i;
struct fm_mn *ptr;
formfield m;
ptr = &(fi->fm_mn);
if (n >= (int)NUMvis() || n < 0) /* abs k17 */
m.name = NULL;
else
{
i = DEVirt(n);
m.name = multi_eval(ptr, i, FM_NAME);
m.value = (char *) curval(i);
m.frow = atoi(multi_eval(ptr, i, FM_FROW));
m.fcol = atoi(multi_eval(ptr, i, FM_FCOL));
m.nrow = atoi(multi_eval(ptr, i, FM_NROW));
m.ncol = atoi(multi_eval(ptr, i, FM_NCOL));
m.rows = atoi(multi_eval(ptr, i, FM_ROWS));
m.cols = atoi(multi_eval(ptr, i, FM_COLS));
if (multi_eval(ptr, i, FM_INACTIVE))
m.flags = I_FANCY;
else
m.flags = I_BLANK|I_FANCY|I_FILL;
if (!multi_eval(ptr, i, FM_SHOW))
m.flags |= I_NOSHOW;
m.ptr = PTRS() + i;
if (multi_eval(ptr, i, FM_WRAP))
m.flags |= I_WRAP;
if (multi_eval(ptr, i, FM_SCROLL))
m.flags |= I_SCROLL;
if (LASTpage() > 1)
m.flags |= I_NOPAGE;
if (multi_eval(ptr, i, FM_NOECHO)) {
m.flags |= I_INVISIBLE;
m.flags &= ~(I_BLANK | I_FILL);
}
if (multi_eval(ptr, i, FM_AUTOADVANCE))
m.flags |= I_AUTOADV;
if (m.cols <= 0 || m.rows <= 0 || m.frow < 0 || m.fcol < 0)
{ /* field not active */
m.cols = 1;
m.rows = 1;
m.frow = -1; /* title bar line */
m.fcol = 0;
m.flags = I_NOEDIT;
m.value = "";
}
}
return(m);
}
/*
** Evaluates the help field and returns a token for it.
*/
static token
objform_help(rec)
struct actrec *rec;
{
token make_action();
Cur_rec = rec;
return(make_action(sing_eval(CURform(), FM_HELP)));
}
/*
** Forms have no arguments to give, so that must fail. All else is
** passed on.
*/
static int
objform_ctl(rec, cmd, arg1, arg2, arg3, arg4, arg5, arg6)
struct actrec *rec;
int cmd;
int arg1, arg2, arg3, arg4, arg5, arg6;
{
Cur_rec = rec;
switch (cmd)
{
case CTGETARG:
return(FAIL);
case CTSETMSG:
if (arg1 == TRUE) {
/*
* if arg1 == TRUE then the frame message was
* generated "externally" (i.e., via the message
* built-it). Update the "framemsg" descriptor
* accordingly.
*/
char *newmsg, *get_mess_frame();
newmsg = get_mess_frame();
set_single_default(CURform(), FM_FRMMSG, newmsg);
}
else
mess_frame(sing_eval(CURform(), FM_FRMMSG));
return(SUCCESS);
case CTSETLIFE:
{
char *life;
/* used CURform, Cur_rec before F15. abs */
life = sing_eval((&(((forminfo *) rec->odptr)->fm_mn)), FM_LIFE);
setlifetime(rec, life);
return(SUCCESS);
}
default:
return(form_ctl(rec->id, cmd, arg1, arg2, arg3, arg4, arg5, arg6));
}
}
/*
** Calls path_to_ar() and nextpath_to_ar() to decide whether this is a
** reopen or a first open. If it is the latter, it sets up the actrec
** and calls ar_create().
*/
int
IF_ofopen(args)
register char **args;
{
register int i;
struct actrec a, *first_rec, *path_to_ar(), *nextpath_to_ar();
extern struct slk Defslk[MAX_SLK + 1];
int startrow, startcol;
int do_inline;
int type;
char *life;
char *begcol, *begrow;
register struct fm_mn *fm_mn;
forminfo *fi;
char envbuf[6];
a.serial = 0;
a.slks = (struct slk *)NULL;
a.prevrec = (struct actrec *)NULL;
a.nextrec = (struct actrec *)NULL;
a.backup = (struct actrec *)NULL;
if (strCcmp(args[0], "-i") == 0)
{
do_inline = TRUE;
Cur_rec = path_to_ar(args[1]);
}
else
{
do_inline = FALSE;
Cur_rec = path_to_ar(args[0]);
}
for (first_rec = Cur_rec; Cur_rec; ) {
char *env;
strcpy(envbuf, "ARG1");
for (i = do_inline ? 2 : 1;
(env = getaltenv(VALS(), envbuf)) && args[i];
envbuf[3]++, i++)
if (strcmp(args[i], env))
break;
if (!args[i] && !env) {
ar_current(Cur_rec, TRUE); /* abs k15 */
return(SUCCESS);
}
Cur_rec = nextpath_to_ar(Cur_rec);
if (Cur_rec == first_rec)
break;
}
fi = (forminfo *)new(forminfo);
fi->flags = do_inline ? INLINE : 0;
fi->mulvals = NULL;
fm_mn = &(fi->fm_mn);
a.odptr = (char *) fi;
a.id = -1;
fm_mn->single.attrs = NULL;
if (do_inline)
a.path = strsave(args[1]);
else
a.path = strsave(args[0]);
if ((a.slks = (struct slk *) malloc(sizeof(Defslk))) == NULL)
fatal(NOMEM, nil);
a.fcntbl[AR_CLOSE] = objform_close;
a.fcntbl[AR_HELP] = (int (*)())objform_help; /* added cast abs */
a.fcntbl[AR_REREAD] = objform_reread;
a.fcntbl[AR_REINIT] = objform_reinit;
a.fcntbl[AR_CURRENT] = objform_current;
a.fcntbl[AR_TEMP_CUR] = objform_temp_cur; /* abs k15 */
a.fcntbl[AR_NONCUR] = objform_noncur;
a.fcntbl[AR_CTL] = objform_ctl;
a.fcntbl[AR_ODSH] = objform_stream;
Cur_rec = &a;
CURpage() = 1;
setupenv(fi->flags, args, &VALS());
if (objform_reread(&a) == FAIL)
return(FAIL);
/* return(NULL); abs */
type = 0;
life = sing_eval(CURform(), FM_LIFE);
begrow = sing_eval(fm_mn, FM_BEGROW);
begcol = sing_eval(fm_mn, FM_BEGCOL);
life_and_pos(&a, life, begrow, begcol, &startrow, &startcol, &type);
a.id = form_default(shrink_str(sing_eval(fm_mn, FM_TITLE), MAX_TITLE),
type, startrow, startcol, objform_disp, (char *)fi);
if (sing_eval(fm_mn, FM_ALTSLKS))
a.flags = AR_ALTSLKS | AR_NORESHAPE;
else
a.flags = AR_NORESHAPE;
if (a.id == FAIL)
return(FAIL);
form_ctl(a.id, CTSETPAGE, FALSE, CURpage(), LASTpage());
return((int) ar_current(Cur_rec = (struct actrec *) ar_create(&a), FALSE));
}
/*
** Set the value of the current field.
*/
int
set_curval(str)
char *str;
{
char *s;
char *tmp=NULL;
char buf[BUFSIZ];
char *envbuf;
strcpy(buf, NUMSTR(CURfield() + 1));
form_ctl(Cur_rec->id, CTGETARG, &tmp);
if (strcmp(str, s = getaltenv(VALS(), buf)) || strcmp(str,tmp)) {
/*
* If the current value and the passed value are
* different then add the passed value (str) to
* the environment
*/
int dofree, maxamt, amt;
dofree = 0;
maxamt = BUFSIZ - strlen(NUMSTR(CURfield() + 1)) - 2;
if ((amt = strlen(str)) > maxamt) {
/*
* Value is greater than 1K so malloc
* enough space to hold it.
*/
maxamt = amt + strlen(NUMSTR(CURfield() + 1)) + 2;
if ((envbuf = (char *) malloc(maxamt)) == NULL)
fatal(NOMEM, nil);
dofree++;
}
else {
/*
* ... otherwise, use static 1K buffer
*/
envbuf = buf;
dofree = 0;
}
set_cur(CURform(), CURfield(), FM_VALUE, strsave(str));
strcpy(envbuf, NUMSTR(CURfield() + 1));
strcat(envbuf, Equal);
strncat(envbuf, str, maxamt);
putaltenv(&VALS(), envbuf);
putAltenv(envbuf);
if (dofree)
free(envbuf);
return(SUCCESS);
}
return(FAIL);
}
static int chk_page();
/*
* CHK_FORM returns the actual number of the FIRST field that
* is invalid ....
*/
static int
chk_form()
{
register int n, page, fldnum;
int savefield, savepage, retval;
/*
* Save current form page/field
*/
savepage = CURpage();
savefield = CURfield();
/*
* if the current page has an invalid field then return
* its field number
*/
if ((fldnum = chk_page(CURpage())) >= 0) {
SET_curfield(savefield);
return(fldnum);
}
/*
* For each page of the form, scan the list of
* fields and validate those that were not touched.
* (Start with the page AFTER the current page and wrap around)
*/
retval = -1;
page = CURpage();
for (n = 1; n < LASTpage(); n++) {
page = (page % LASTpage()) + 1;
if ((fldnum = chk_page(page)) >= 0) {
retval = fldnum;
break;
}
}
/*
* restore current form page/field
*/
if (CURpage() != savepage) {
CURpage() = savepage;
fm_vislist(CURforminfo()); /* create new visible list */
}
SET_curfield(savefield);
return(retval);
}
/*
* CHK_PAGE will make sure that all visible fields of "page" are valid.
*/
static int
chk_page(page)
int page;
{
register int i, j, lcv;
register struct attribute *attr;
if (page != CURpage()) { /* compute new visible list? */
CURpage() = page;
fm_vislist(CURforminfo());
}
for (i = 0, lcv = NUMvis(); i < lcv; i++) {
j = DEVirt(i);
/*
* check the flags of the appropriate "attribute"
* structure to see if the field has ever been "touched"
* (visited) ...
*/
if (multi_eval(CURform(), j, FM_MENUO))
attr = CURattr(j, FM_MENUO);
else
attr = CURattr(j, FM_VALID);
if (multi_eval(CURform(), j, FM_SHOW) && attr &&
!(attr->flags & ATTR_TOUCHED)) {
attr->flags |= ATTR_TOUCHED;
SET_curfield(j);
if (fld_ck(j) != SUCCESS)
return(j);
}
}
return(-1);
}
/*
** Given a form_field structure, it will get the value of the current
** field and see if it is A) different and B) valid. If the value is
** different all sorts of recalculation must go on (the show function,
** all the new values). If the value is valid, it returns SUCCESS,
** so that the function calling it can navigate or close.
*/
int
fld_get_ck(form_field)
formfield *form_field;
{
char *s;
char buf[BUFSIZ];
if ( form_field->flags & I_SCROLL )
s = NULL;
else
s = (form_field->rows * form_field->cols >= BUFSIZ) ? NULL : buf;
form_ctl(Cur_rec->id, CTGETARG, &s);
if (set_curval(s) == SUCCESS) {
redo_vals(CURfield() + 1);
fm_vislist(CURforminfo());
form_ctl(Cur_rec->id, CTSETDIRTY);
}
return(is_valid(s));
}
/*
* FLD_IS_VALID will check to see if a field is valid by retrieving, and
* not computing, the value of "$FN" ...
*/
static int
fld_ck(i)
int i;
{
char *s;
char buf[BUFSIZ];
strcpy(buf, NUMSTR(i + 1));
s = getaltenv(VALS(), buf);
return(is_valid(s));
}
static int
is_valid(s)
char *s;
{
int ret;
char *str;
ret = SUCCESS;
if (!multi_eval(CURform(), CURfield(), FM_VALID)) {
if ((str=multi_eval(CURform(), CURfield(), FM_VALMSG)) && *str)
mess_temp(str);
else
warn(VALID, s);
mess_lock();
ret = FAIL;
}
else if (multi_eval(CURform(), CURfield(), FM_MENUO)) {
char **list;
if ((list = (char **) multi_eval(CURform(), CURfield(), FM_RMENU)) &&
*list != '\0')
{
int i, lcv;
lcv = array_len(list) - 1;
for (i = 1; i < lcv; i++)
if (strcmp(s, list[i]) == 0)
break;
if (i == lcv) {
if ((str = multi_eval(CURform(), CURfield(), FM_VALMSG)) && *str)
mess_temp(str);
else
warn(VALID, s);
mess_lock();
ret = FAIL;
}
}
else {
if ((str = multi_eval(CURform(), CURfield(), FM_VALMSG)) && *str)
mess_temp(str);
else
warn(VALID, s);
mess_lock();
ret = FAIL;
}
}
return(ret);
}
/*
** Move to another field.
*/
static void
chg_curfield(virtnum)
int virtnum;
{
int num;
num = DEVirt(virtnum);
if (CURfield() == num)
return;
SET_curfield(num);
set_form_field(Cur_rec->id, num);
}
/*
** Calculates the next field to go to. Mode is either positive or
** negative 1 for forward and backward navigation. Canbecur
** decides whether the current field should be eliminated from the
** choices for nextfield().
*/
int
nextfield(currow, curcol, mode, flags)
int currow;
int curcol;
register int mode;
int flags;
{
register int i, j, frow, fcol;
int curi, rows, cols;
int newcurrow, newcurcol;
int leastcol, leastrow, leasti;
struct fm_mn *curf;
int no_current, page_advance;
int lcv;
int f_error, oldfield, oldpage; /* abs */
int try; /* abs k17 */
oldfield = CURfield(); /* abs */
oldpage = CURpage(); /* abs */
no_current = page_advance = 0;
if (flags & NX_NOCUR)
no_current++;
if (flags & NX_ADVANCE)
page_advance++;
curf = CURform();
leastrow = mode * TOOBIG;
leastcol = mode * TOOBIG;
newcurrow = mode * TOOBIG;
newcurcol = mode * TOOBIG;
curi = -1;
leasti = -1;
lcv = NUMvis();
for (i = 0; i < lcv; i++)
{
/*
* First eliminate fields that can be eliminated
*
* IF ...
* 1. field is inactive/non showable OR
* 2. field is current and isn't eligible OR
* 3. either rows or cols <= 0 OR
* 4. frow or fcol < 0
*
* THEN skip the field
*
* NOTE: The reason that fields that do not satisfy
* (3) and (4) are visible is that one can
* have a field name with no field associated
* with it .... (ETI does not have such a
* field/field-name association)
*
*/
j = DEVirt(i);
if (multi_eval(curf, j, FM_INACTIVE) ||
(!multi_eval(curf, j, FM_SHOW)) ||
((j == CURfield()) && no_current))
continue;
rows = atoi(multi_eval(curf, j, FM_ROWS));
cols = atoi(multi_eval(curf, j, FM_COLS));
frow = atoi(multi_eval(curf, j, FM_FROW));
fcol = atoi(multi_eval(curf, j, FM_FCOL));
if (rows <= 0 || cols <= 0 || frow < 0 || fcol < 0)
continue;
/*
* Determine whether the "ith" visible field is next
* A few comments here would help !!!
*/
if ((mode * frow >= mode * currow) && (mode * frow <= mode * newcurrow))
{
if (((mode * frow > mode * currow) ||
(mode * fcol >= mode * curcol)) &&
((mode * frow < mode * newcurrow) ||
(mode * fcol < mode * newcurcol)))
{
newcurcol = fcol;
newcurrow = frow;
curi = i;
continue;
}
}
if ((mode * frow <= mode * leastrow))
{
if ((mode * frow < mode * leastrow) ||
(mode * fcol <= mode * leastcol))
{
leastcol = fcol;
leastrow = frow;
leasti = i;
}
}
} /* end for i=0.. */
if ((newcurrow == mode * TOOBIG) && (newcurcol == mode * TOOBIG))
{
/*
* User has reached a page boundary (i.e., there is no
* next/previous field on the current page)
*/
if (LASTpage() != 1 && page_advance)
{
/*
* If this is a multi-page form AND the page should be
* automatically advanced on page boundaries then ...
*/
if (mode < 0) /* prev field */
{ /* find the prev page with visible fields abs k17 */
f_error = TRUE; /* abs k17 */
for (try = LASTpage(); try > 1; try--) /* abs k17 */
{ /* abs k17 */
if (CURpage() != 1)
CURpage()--;
else
CURpage() = LASTpage();
fm_vislist(CURforminfo());
if ((int)NUMvis() > 0) /* abs k17 */
{ /* abs k17 */
f_error = FALSE; /* abs k17 */
break; /* abs k17 */
} /* abs k17 */
} /* abs k17 */
if (!f_error) /* abs k17 */
f_error = form_ctl(Cur_rec->id, CTSETPAGE, TRUE, CURpage(),
LASTpage());
if (f_error)
{
CURpage() = oldpage;
CURfield() = oldfield;
fm_vislist(CURforminfo());
form_ctl(Cur_rec->id, CTSETPAGE, TRUE, oldpage, LASTpage());
mess_temp("Cannot display the previous page: page may be too large");
mess_lock();
return (0);
}
CURfield() = -1; /* abs */
nextfield(1000, 1000, -1, NX_ANY);
return (0);
}
else /* next field */
{ /* find the next page with visible fields abs k17 */
f_error = TRUE; /* abs k17 */
for (try = LASTpage(); try > 1; try--) /* abs k17 */
{ /* abs k17 */
if (CURpage() != LASTpage())
CURpage()++;
else
CURpage() = 1;
fm_vislist(CURforminfo());
if ((int)NUMvis() > 0) /* abs k17 */
{ /* abs k17 */
f_error = FALSE; /* abs k17 */
break; /* abs k17 */
} /* abs k17 */
} /* abs k17 */
if (!f_error) /* abs k17 */
f_error = form_ctl(Cur_rec->id, CTSETPAGE, TRUE, CURpage(),
LASTpage());
if (f_error)
{
CURpage() = oldpage;
CURfield() = oldfield;
fm_vislist(CURforminfo());
form_ctl(Cur_rec->id, CTSETPAGE, TRUE, oldpage, LASTpage());
mess_temp("Cannot display the next page: page may be too large");
mess_lock();
return (0);
}
CURfield() = -1; /* abs */
nextfield(0, 0, 1, NX_ANY);
return (0);
}
}
else
{
/*
* simply wrap around to the top/bottom of the page
*/
curi = leasti;
}
}
if (curi < 0)
curi = virt(CURfield()); /* zero or one active field */
chg_curfield(curi);
return (0);
}
token
seek_field(row, col)
int row, col;
{
register int i, j, lcv;
struct fm_mn *curf;
int frow, fcol, foundfield;
curf = CURform();
lcv = NUMvis();
foundfield = -1;
/*
* since row,col is 0,0 use 1,1 scale for offset
*/
for (i = 0; i < lcv; i++) {
/*
* First eliminate fields that can be eliminated
*/
j = DEVirt(i);
if ((multi_eval(curf, j, FM_SHOW)) &&
((frow = atoi(multi_eval(curf, j, FM_FROW))) <= row) &&
(atoi(multi_eval(curf, j, FM_ROWS)) + frow > row) &&
((fcol = atoi(multi_eval(curf, j, FM_FCOL))) <= col) &&
(atoi(multi_eval(curf, j, FM_COLS)) + fcol > col)) {
foundfield = i;
break;
}
}
if (foundfield < 0 || multi_eval(curf, foundfield, FM_INACTIVE))
return(TOK_BADCHAR);
else {
chg_curfield(foundfield);
return(TOK_NOP);
}
}
/* return values */
#define TOGGLE 1
#define LONGLIST 2
#define ACTION 3
/*
** Checks an "rmenu" to see if it is a small list (toggle choices
** if less than "threshold" members), a large list or a command.
*/
int
testlist(list)
char **list;
{
if (list[0][0] == '{') {
if (((int)array_len(list) - 2) <= Toggle) /* account for "{ }" */
return(TOGGLE);
return(LONGLIST);
}
return(ACTION);
}
char *Choice_list[3] =
{
"OPEN",
"MENU",
"-i"
};
/*
** Turns an rmenu field into a command.
*/
token
rmenuaction(list)
register char **list;
{
extern char *Args[];
extern int Arg_count;
int lcv;
if (testlist(list) == LONGLIST) {
register int i;
register IOSTRUCT *out;
/* char **help;
*/
out = io_open(EV_USE_STRING, NULL);
putastr("menu=Choices\n", out);
putastr("lifetime=shortterm\n", out);
/* Shouldn't evaluate help when choices is pressed!! abs.
* putastr("Help=", out);
* help = (char **) sing_eval(CURform(), FM_HELP);
* lcv = array_len(help);
* for (i = 0; i < lcv; i++) {
* putastr(help[i], out);
* putac(' ', out);
* }
* putac('\n', out);
*/
lcv = array_len(list) - 1;
for (i = 1; i < lcv; i++) {
putac('\n', out);
putastr("name=\"", out);
putastr(list[i], out);
putastr("\"\n", out);
putastr("lininfo=\"", out);
putastr(list[i], out);
putastr("\"\n", out);
putastr("action=`set -l Form_Choice=\"", out);
putastr(list[i], out);
putastr("\"`close", out);
putac('\n', out);
putac('\n', out);
}
putastr("name=\nbutton=1\naction=badchar\n", out);
putastr("name=\nbutton=2\naction=badchar\n", out);
putastr("name=\nbutton=4\naction=badchar\n", out);
putastr("name=\nbutton=5\naction=badchar\n", out);
putastr("name=\nbutton=7\naction=badchar\n", out);
putastr("name=\nbutton=8\naction=badchar\n", out);
for (Arg_count = 0; Arg_count < 3; Arg_count++) {
if (Args[Arg_count])
free(Args[Arg_count]); /* les */
Args[Arg_count] = strsave(Choice_list[Arg_count]);
}
if (Args[Arg_count])
free(Args[Arg_count]); /* les */
Args[Arg_count++] = io_string(out);
io_close(out);
if (Args[Arg_count])
free(Args[Arg_count]); /* les */
Args[Arg_count] = NULL;
return(TOK_OPEN);
}
return(setaction(list));
}
/*
** Processes characters after the editor.
*/
token
post_stream(t)
register token t;
{
formfield form_field;
char *str;
char **list;
int *slks;
int i, len;
int num, fnum;
int nextflags, flag;
char *s;
int lcv;
int f_error; /* abs */
token make_action();
nextflags = flag = 0;
form_field = CURffield();
s = NULL;
if (t >= TOK_SLK1 && t <= TOK_SLK16) {
slks = CURforminfo()->slks;
num = t - TOK_SLK1 + 1;
lcv = array_len(slks);
for(i = 0; i < lcv; i++)
if (atoi(multi_eval(CURform(), slks[i], FM_BUTT)) == num) {
form_ctl(Cur_rec->id, CTGETARG, &s);
t = setaction(multi_eval(CURform(), slks[i], FM_ACTI));
break;
}
}
switch(t) {
case TOK_BPRESSED:
return(TOK_NOP); /* do nothing on a button press */
case TOK_BRELEASED:
return((token) seek_field(Mouse_row, Mouse_col));
case TOK_OPTIONS:
t = TOK_NOP;
if (list = (char **) multi_eval(CURform(), CURfield(), FM_RMENU)) {
int i;
char *str;
if ((str = multi_eval(CURform(), CURfield(), FM_CHOICEMSG)) && *str) {
mess_temp(str);
mess_lock(); /* don't overwrite it !!! */
}
len = array_len(list);
if (len == 0 || (len <= 2 && list[0][0] == '{')) {
if (!(str && *str))
mess_temp("There are no choices available");
}
else if (testlist(list) == TOGGLE) {
char *s;
s = getaltenv(VALS(), NUMSTR(CURfield() + 1));
len -= 2;
list = list + 1;
for (i = 0; i < len - 1; i++)
if (strcmp(s, list[i]) == 0)
break;
if (set_curval(strsave(list[(i + 1) % len])) == SUCCESS) {
fm_vislist(CURforminfo());
redo_vals(CURfield() + 1);
form_ctl(Cur_rec->id, CTSETDIRTY);
}
}
else
t = rmenuaction(list);
}
break;
case TOK_RESET:
{
char *s = NULL;
form_ctl(Cur_rec->id, CTGETARG, &s);
de_const(CURform(), CURfield(), FM_VALUE);
redo_vals(CURfield());
fm_vislist(CURforminfo());
form_ctl(Cur_rec->id, CTSETDIRTY);
t = TOK_NOP;
break;
}
case TOK_DONE:
t = TOK_BADCHAR;
if (fld_get_ck(&form_field) != SUCCESS)
t = TOK_NOP;
else if ((fnum = chk_form()) >= 0) {
int page;
/*
* fnum is the actual (rather than the virtual)
* field num
*/
page = atoi(multi_eval(CURform(), fnum, FM_PAGE));
if (page != CURpage()) {
/*
* make the new page visible
*/
CURpage() = page;
fm_vislist(CURforminfo());
form_ctl(Cur_rec->id, CTSETPAGE, TRUE, CURpage(), LASTpage());
}
chg_curfield(virt(fnum));
t = TOK_NOP;
}
else if (str = sing_eval(CURform(), FM_DONE))
t = make_action(str);
else {
warn(VALID, "");
mess_lock();
}
break;
case TOK_UP:
nextflags |= NX_ADVANCE;
/* fall through */
case TOK_PREVIOUS:
case TOK_BTAB: /* added backtab mapping. abs k16 */
nextflags |= NX_NOCUR;
if (fld_get_ck(&form_field) == SUCCESS)
nextfield(atoi(multi_eval(CURform(), CURfield(), FM_FROW)),
atoi(multi_eval(CURform(), CURfield(), FM_FCOL)),
-1, nextflags);
else
set_form_field(Cur_rec->id, CURfield());
t = TOK_NOP;
break;
case TOK_DOWN:
nextflags |= NX_ADVANCE;
/* fall through */
case TOK_TIME:
case TOK_SAVE:
case TOK_NEXT:
nextflags |= NX_NOCUR;
if (fld_get_ck(&form_field) == SUCCESS)
nextfield(atoi(multi_eval(CURform(), CURfield(), FM_FROW)),
atoi(multi_eval(CURform(), CURfield(), FM_FCOL)),
1, nextflags);
else
set_form_field(Cur_rec->id, CURfield());
t = TOK_NOP;
break;
case TOK_PPAGE:
if (fld_get_ck(&form_field) == SUCCESS)
{ /* find the prev page with visible fields. abs k17 */
int oldpage = CURpage(); /* abs k17 */
if (CURpage() == 1) /* abs k17 */
{
set_form_field(Cur_rec->id, CURfield());
t = TOK_BADCHAR;
break;
}
else
{
while (CURpage() != 1) /* abs k17 */
{ /* abs k17 */
CURpage()--;
fm_vislist(CURforminfo());
if ((int)NUMvis() > 0) /* abs k17 */
{ /* abs k17 */
f_error = FALSE; /* abs k17 */
break; /* abs k17 */
} /* abs k17 */
else /* abs k17 */
f_error = TRUE; /* abs k17 */
} /* abs k17 */
if (!f_error) /* abs k17 */
f_error = form_ctl(Cur_rec->id, CTSETPAGE, TRUE,
CURpage(), LASTpage());
if (f_error) /* bad page .. go back to old one */
{
CURpage() = oldpage; /* abs k17 */
fm_vislist(CURforminfo());
f_error = form_ctl(Cur_rec->id, CTSETPAGE, TRUE,
CURpage(), LASTpage());
mess_temp("Cannot display the previous page: page may be too large");
mess_lock();
}
else
nextfield(0, 0, 1, NX_ANY);
}
}
else
set_form_field(Cur_rec->id, CURfield());
t = TOK_NOP;
break;
case TOK_NPAGE:
if (fld_get_ck(&form_field) == SUCCESS)
{ /* find the next page with visible fields. abs k17 */
int oldpage = CURpage(); /* abs k17 */
if (CURpage() == LASTpage()) /* abs k17 */
{
set_form_field(Cur_rec->id, CURfield());
t = TOK_BADCHAR;
break;
}
else
{
while (CURpage() != LASTpage() ) /* abs k17 */
{ /* abs k17 */
CURpage()++;
fm_vislist(CURforminfo());
if ((int)NUMvis() > 0) /* abs k17 */
{ /* abs k17 */
f_error = FALSE; /* abs k17 */
break; /* abs k17 */
} /* abs k17 */
else /* abs k17 */
f_error = TRUE; /* abs k17 */
} /* abs k17 */
if (!f_error) /* abs k17 */
f_error = form_ctl(Cur_rec->id, CTSETPAGE, TRUE,
CURpage(), LASTpage());
if (f_error) /* bad page .. go back to old one */
{
CURpage() = oldpage; /* abs k17 */
fm_vislist(CURforminfo());
f_error = form_ctl(Cur_rec->id, CTSETPAGE, TRUE,
CURpage(), LASTpage());
mess_temp("Cannot display the next page: page may be too large");
mess_lock();
}
else
nextfield(0, 0, 1, NX_ANY);
}
}
else
set_form_field(Cur_rec->id, CURfield());
t = TOK_NOP;
break;
}
return(t);
}
/*
** Processes characters before the editor.
*/
int
pre_stream(t)
register token t;
{
formfield form_field;
/* les */
/* if ( isprint(t)) ** only looks at 8 bits. abs k17 */
if ( t > 037 && t < 0177 )
return t;
/*******/
form_field = CURffield();
switch(t) {
case TOK_END:
nextfield(1000, 1000, -1, NX_ANY);
t = TOK_NOP;
break;
case TOK_BEG:
nextfield(0, 0, 1, NX_ANY);
t = TOK_NOP;
break;
case TOK_BTAB:
if (fld_get_ck(&form_field) == SUCCESS)
nextfield(atoi(multi_eval(CURform(), CURfield(), FM_FROW)),
atoi(multi_eval(CURform(), CURfield(), FM_FCOL)),
-1, NX_NOCUR | NX_ADVANCE);
else
set_form_field(Cur_rec->id, CURfield());
t = TOK_NOP;
break;
case TOK_TAB:
t = TOK_SAVE;
case TOK_WDWMGMT:
break;
}
return(t);
}
/*
** Sets up the stream for forms.
*/
static int
objform_stream(a, t)
struct actrec *a;
token t;
{
int (*func[5])();
register int olifetime;
extern int field_stream();
Cur_rec = a;
olifetime = Cur_rec->lifetime;
Cur_rec->lifetime = AR_PERMANENT;
func[0] = pre_stream;
func[1] = field_stream;
func[2] = (int (*)())post_stream; /* added cast abs */
func[3] = NULL;
t = stream(t, func);
Cur_rec->lifetime = olifetime;
return(t);
}
int
set_form_field(id, field_num)
int id, field_num;
{
char *str;
char *lininfo;
char buf[BUFSIZ];
struct attribute *attr;
/*
* mark the attribute as touched (visited) ...
*/
if (multi_eval(CURform(), field_num, FM_MENUO))
attr = CURattr(field_num, FM_MENUO);
else
attr = CURattr(field_num, FM_VALID);
if (attr)
attr->flags |= ATTR_TOUCHED;
/*
* set "LININFO" variable to the value of the "lininfo"
* descriptor for field_num
*/
lininfo = multi_eval(CURform(), field_num, FM_LININFO);
if (strlen(lininfo)) {
sprintf(buf, "LININFO=%s", lininfo);
putAltenv(buf);
}
else
delAltenv("LININFO");
/*
* display on the message line the "fieldmsg" for field_num
*/
if ((str = multi_eval(CURform(), field_num, FM_FIELDMSG)) && *str)
mess_temp(str);
form_ctl(id, CTSETPOS, virt(field_num), 0, 0);
return (0);
}