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
* 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 "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_ONINTR PAR_ONINTR
#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_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
};
};
char *itoa();
extern int Mouse_row; /* Row offset of the mouse */
extern int Mouse_col; /* Column offset of the mouse */
#define NX_ANY 0 /* pseudo flag */
#define NX_NOCUR 1
#define NX_ADVANCE 2
extern char *shrink_str();
extern char *expand();
extern char *getaltenv();
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 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;
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
int start;
{
int changed;
register char *envbuf;
register int i;
int lcv;
}
dofree = 0;
/*
* Value is greater than 1K so malloc
* enough space to hold it.
*/
dofree++;
}
else {
/*
* ... otherwise, use static 1K buffer
*/
dofree = 0;
}
if (dofree) /* if buffer was malloc'd, free it */
}
while (changed) {
register char *p;
dofree = 0;
*p = '$';
if (!p)
continue;
/*
* Value is greater than 1K so malloc
* enough space to hold it.
*/
dofree++;
}
else {
/*
* ... otherwise, use static 1K buffer
*/
dofree = 0;
}
if (dofree)
}
}
return (0);
}
/*
** Returns the current value of the field, fieldno.
*/
char *
int fieldno;
{
}
/*
** Figure out which fields are on the screen as decided by the show
** function values.
*/
int
{
int i, num;
char *page;
int lcv;
}
else {
}
NUMactive() = 0;
for (i = 0; i < lcv; i++) {
/*
* SLK definition
*/
}
else {
/*
* FIELD definition
*/
/*
* Only make visible fields on the CURRENT
* page ...
*/
continue;
/*
* add field to visible list ...
* keep track of the number of active fields
* for this page ...
*/
NUMactive()++;
}
}
}
return (0);
}
static int
struct actrec *a;
{
Cur_rec = a;
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
int flags;
char *info_or_file;
{
return(fm_mn);
}
/*
** Read the form object indicated by this actrec, if a->id > 0
** then the object is being reread.
*/
static int
struct actrec *a;
{
register int i, but;
int lcv;
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 (a->id >= 0) /* if frame is already posted */
else
return(FAIL);
}
if (a->id >= 0)
#ifdef _DEBUG4
#endif
return(FAIL);
}
if (PTRS())
for (i = 0; i < lcv; i++)
redo_vals(0); /* initialize field values */
if (a->id < 0)
SET_curfield(-1);
/*
* If "init=false" or Form is empty then cleanup
*/
{
if (a->id >= 0) /* form is already posted */
{
if (a->lifetime == AR_INITIAL)
{
mess_temp("can't close this frame");
mess_lock();
}
else
{
return(FAIL);
}
}
else
{
return(FAIL);
}
}
/*
* update the interrupt descriptors in the activation rec
*/
/*
* Set up object specific SLK array
*/
for (i = 0; i < lcv; i++) {
continue;
}
if (a->id >= 0) /* go to first field, first page */
{
CURpage() = 1;
/* 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);
*/
}
return(SUCCESS);
}
/*
** Frees up the structures and evaluates the "close" function.
*/
static int
struct actrec *a;
{
register int i, lcv;
char *p, *strchr();
Cur_rec = a;
copyAltenv(VALS());
/*
* Free information IN the forminfo structure
*/
if (PTRS()) /* holdptrs array */
for (i = 0; i < lcv; i++) { /* form specific variables */
*p = '\0';
if (p)
*p = '=';
}
/*
* Free information in the activation record
*/
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;
for (i = 0; i < lcv; i++) {
*p = '\0';
if (p)
*p = '=';
}
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
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)
/*
* Initialize the field with the value of variable "Form_Choice"
* (variable holds the selected item(s) from a choices menu)
*/
copyAltenv(VALS());
1, NX_NOCUR);
}
}
else
copyAltenv(VALS());
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
struct actrec *a;
{
/*
* Make the form "current"
*/
Cur_rec = a;
form_current(a->id);
if (CURfield() == -1)
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;
{
register int i;
formfield m;
if (n >= (int)NUMvis() || n < 0) /* abs k17 */
else
{
i = DEVirt(n);
else
if (LASTpage() > 1)
m.flags |= I_INVISIBLE;
}
{ /* field not active */
m.cols = 1;
m.rows = 1;
m.fcol = 0;
m.value = "";
}
}
return(m);
}
/*
** Evaluates the help field and returns a token for it.
*/
static token
{
token make_action();
}
/*
** Forms have no arguments to give, so that must fail. All else is
** passed on.
*/
static int
int cmd;
{
switch (cmd)
{
case CTGETARG:
return(FAIL);
case CTSETMSG:
/*
* 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();
}
else
return(SUCCESS);
case CTSETLIFE:
{
char *life;
/* used CURform, Cur_rec before F15. abs */
return(SUCCESS);
}
default:
}
}
/*
** 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
register char **args;
{
register int i;
int do_inline;
int type;
char *life;
char envbuf[6];
a.serial = 0;
{
}
else
{
}
char *env;
envbuf[3]++, i++)
break;
return(SUCCESS);
}
break;
}
a.id = -1;
if (do_inline)
else
Cur_rec = &a;
CURpage() = 1;
if (objform_reread(&a) == FAIL)
return(FAIL);
/* return(NULL); abs */
type = 0;
else
a.flags = AR_NORESHAPE;
return(FAIL);
}
/*
** Set the value of the current field.
*/
int
char *str;
{
char *s;
char *envbuf;
/*
* If the current value and the passed value are
* different then add the passed value (str) to
* the environment
*/
dofree = 0;
/*
* Value is greater than 1K so malloc
* enough space to hold it.
*/
dofree++;
}
else {
/*
* ... otherwise, use static 1K buffer
*/
dofree = 0;
}
if (dofree)
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()
{
/*
*/
/*
* if the current page has an invalid field then return
* its field number
*/
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;
for (n = 1; n < LASTpage(); n++) {
break;
}
}
/*
*/
}
return(retval);
}
/*
* CHK_PAGE will make sure that all visible fields of "page" are valid.
*/
static int
int page;
{
register int i, j, lcv;
}
j = DEVirt(i);
/*
* check the flags of the appropriate "attribute"
* structure to see if the field has ever been "touched"
* (visited) ...
*/
else
SET_curfield(j);
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
{
char *s;
s = NULL;
else
if (set_curval(s) == SUCCESS) {
}
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;
return(is_valid(s));
}
static int
is_valid(s)
char *s;
{
int ret;
char *str;
else
mess_lock();
}
char **list;
*list != '\0')
{
int i, lcv;
for (i = 1; i < lcv; i++)
break;
if (i == lcv) {
else
mess_lock();
}
}
else {
else
mess_lock();
}
}
return(ret);
}
/*
** Move to another field.
*/
static void
int virtnum;
{
int num;
return;
}
/*
** 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
int currow;
int curcol;
register int mode;
int flags;
{
int no_current, page_advance;
int lcv;
int try; /* abs k17 */
no_current = page_advance = 0;
no_current++;
if (flags & NX_ADVANCE)
page_advance++;
curi = -1;
leasti = -1;
for (i = 0; i < lcv; i++)
{
/*
* First eliminate fields that can be eliminated
*
* IF ...
* 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);
((j == CURfield()) && no_current))
continue;
continue;
/*
* Determine whether the "ith" visible field is next
* A few comments here would help !!!
*/
{
{
curi = i;
continue;
}
}
{
{
leasti = i;
}
}
} /* end for i=0.. */
{
/*
* User has reached a page boundary (i.e., there is no
*/
{
/*
* 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 */
{ /* abs k17 */
if (CURpage() != 1)
CURpage()--;
else
if ((int)NUMvis() > 0) /* abs k17 */
{ /* abs k17 */
break; /* abs k17 */
} /* abs k17 */
} /* abs k17 */
if (!f_error) /* abs k17 */
LASTpage());
if (f_error)
{
mess_temp("Cannot display the previous page: page may be too large");
mess_lock();
return (0);
}
return (0);
}
else /* next field */
{ /* find the next page with visible fields abs k17 */
{ /* abs k17 */
CURpage()++;
else
CURpage() = 1;
if ((int)NUMvis() > 0) /* abs k17 */
{ /* abs k17 */
break; /* abs k17 */
} /* abs k17 */
} /* abs k17 */
if (!f_error) /* abs k17 */
LASTpage());
if (f_error)
{
mess_temp("Cannot display the next page: page may be too large");
mess_lock();
return (0);
}
return (0);
}
}
else
{
/*
*/
}
}
if (curi < 0)
return (0);
}
{
register int i, j, lcv;
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);
foundfield = i;
break;
}
}
return(TOK_BADCHAR);
else {
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
char **list;
{
if (list[0][0] == '{') {
return(TOGGLE);
return(LONGLIST);
}
return(ACTION);
}
char *Choice_list[3] =
{
"OPEN",
"MENU",
"-i"
};
/*
** Turns an rmenu field into a command.
*/
register char **list;
{
extern char *Args[];
extern int Arg_count;
int lcv;
register int i;
/* char **help;
*/
/* 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);
*/
for (i = 1; i < lcv; i++) {
}
}
return(TOK_OPEN);
}
}
/*
** Processes characters after the editor.
*/
post_stream(t)
register token t;
{
char *str;
char **list;
int *slks;
int i, len;
char *s;
int lcv;
int f_error; /* abs */
token make_action();
form_field = CURffield();
s = NULL;
for(i = 0; i < lcv; i++)
break;
}
}
switch(t) {
case TOK_BPRESSED:
return(TOK_NOP); /* do nothing on a button press */
case TOK_BRELEASED:
case TOK_OPTIONS:
t = TOK_NOP;
int i;
char *str;
mess_lock(); /* don't overwrite it !!! */
}
mess_temp("There are no choices available");
}
char *s;
len -= 2;
for (i = 0; i < len - 1; i++)
break;
}
}
else
t = rmenuaction(list);
}
break;
case TOK_RESET:
{
char *s = NULL;
t = TOK_NOP;
break;
}
case TOK_DONE:
t = TOK_BADCHAR;
t = TOK_NOP;
int page;
/*
* fnum is the actual (rather than the virtual)
* field num
*/
/*
* make the new page visible
*/
}
t = TOK_NOP;
}
t = make_action(str);
else {
mess_lock();
}
break;
case TOK_UP:
nextflags |= NX_ADVANCE;
/* fall through */
case TOK_PREVIOUS:
case TOK_BTAB: /* added backtab mapping. abs k16 */
-1, nextflags);
else
t = TOK_NOP;
break;
case TOK_DOWN:
nextflags |= NX_ADVANCE;
/* fall through */
case TOK_TIME:
case TOK_SAVE:
case TOK_NEXT:
1, nextflags);
else
t = TOK_NOP;
break;
case TOK_PPAGE:
{ /* find the prev page with visible fields. abs k17 */
{
t = TOK_BADCHAR;
break;
}
else
{
{ /* abs k17 */
CURpage()--;
if ((int)NUMvis() > 0) /* abs k17 */
{ /* abs k17 */
break; /* abs k17 */
} /* abs k17 */
else /* abs k17 */
} /* abs k17 */
if (!f_error) /* abs k17 */
if (f_error) /* bad page .. go back to old one */
{
mess_temp("Cannot display the previous page: page may be too large");
mess_lock();
}
else
}
}
else
t = TOK_NOP;
break;
case TOK_NPAGE:
{ /* find the next page with visible fields. abs k17 */
{
t = TOK_BADCHAR;
break;
}
else
{
{ /* abs k17 */
CURpage()++;
if ((int)NUMvis() > 0) /* abs k17 */
{ /* abs k17 */
break; /* abs k17 */
} /* abs k17 */
else /* abs k17 */
} /* abs k17 */
if (!f_error) /* abs k17 */
if (f_error) /* bad page .. go back to old one */
{
mess_temp("Cannot display the next page: page may be too large");
mess_lock();
}
else
}
}
else
t = TOK_NOP;
break;
}
return(t);
}
/*
** Processes characters before the editor.
*/
int
pre_stream(t)
register token t;
{
/* 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:
t = TOK_NOP;
break;
case TOK_BEG:
t = TOK_NOP;
break;
case TOK_BTAB:
else
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;
func[0] = pre_stream;
return(t);
}
int
{
char *str;
char *lininfo;
/*
* mark the attribute as touched (visited) ...
*/
else
if (attr)
/*
* set "LININFO" variable to the value of the "lininfo"
* descriptor for field_num
*/
}
else
delAltenv("LININFO");
/*
* display on the message line the "fieldmsg" for field_num
*/
return (0);
}