Mercurial > illumos > onarm
view usr/src/cmd/fmli/oh/if_menu.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
line wrap: on
line source
/* * 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 2005 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 */ #pragma ident "%Z%%M% %I% %E% SMI" #include <stdio.h> #include <string.h> #include <ctype.h> #include <sys/types.h> /* EFT abs k16 */ #include "wish.h" #include "vtdefs.h" #include "ctl.h" #include "menudefs.h" #include "token.h" #include "slk.h" #include "actrec.h" #include "typetab.h" #include "fm_mn_par.h" #include "objmenu.h" #include "var_arrays.h" #include "terror.h" #include "moremacros.h" #include "interrupt.h" #include "sizes.h" #include "message.h" #define MN_INTR PAR_INTR #define MN_ONINTR PAR_ONINTR #define MN_DONE PAR_DONE #define MN_MENU 3 #define MN_HELP 4 #define MN_LIFE 5 #define MN_INIT 6 #define MN_BEGROW 7 #define MN_BEGCOL 8 #define MN_ROWS 9 #define MN_COLUMNS 10 #define MN_CLOSE 11 #define MN_REREAD 12 #define MN_MULTI 13 #define MN_MSELECT 14 #define MN_ALTSLKS 15 #define MN_FRMMSG 16 /* defined above #define MN_INTR PAR_INTR #define MN_ONINTR PAR_ONINTR abs */ #define MN_ACTI PAR_ACTION #define MN_NAME PAR_NAME #define MN_DESC 4 #define MN_BUTT 5 #define MN_LININFO 6 #define MN_SHOW 7 #define MN_ARG 8 #define MN_SELECTED 9 #define MN_ITEMMSG 10 #define MN_INACTIVE 11 #define MN_KEYS 17 static struct attribute Mn_tab[MN_KEYS] = { { "interrupt", RET_STR|EVAL_ALWAYS, NULL, NULL, 0 }, { "oninterrupt",RET_STR|EVAL_ALWAYS, NULL, NULL, 0 }, { "done", RET_ARGS|EVAL_ALWAYS, "", NULL, 0 }, { "menu", RET_STR|EVAL_ONCE, "Menu", NULL, 0 }, { "help", RET_ARGS|EVAL_ALWAYS, "", NULL, 0 }, { "lifetime", RET_STR|EVAL_ALWAYS, "longterm", NULL, 0 }, { "init", RET_BOOL|EVAL_ALWAYS, "", NULL, 0 }, { "begrow", RET_STR|EVAL_ONCE, "any", NULL, 0 }, { "begcol", RET_STR|EVAL_ONCE, "any", NULL, 0 }, { "rows", RET_INT|EVAL_ONCE, "0", NULL, 0 }, { "columns", RET_INT|EVAL_ONCE, "0", NULL, 0 }, { "close", RET_BOOL|EVAL_ONCE, NULL, NULL, 0 }, { "reread", RET_BOOL|EVAL_ALWAYS, NULL, NULL, 0 }, { "multicolumn",RET_BOOL|EVAL_ONCE, "", NULL, 0 }, { "multiselect",RET_BOOL|EVAL_ONCE, NULL, NULL, 0 }, { "altslks", RET_BOOL|EVAL_ONCE, NULL, NULL, 0 }, { "framemsg", RET_STR|EVAL_ONCE, "", NULL, 0 } }; #define MN_FLD_KEYS 12 static struct attribute Mn_fld_tab[MN_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 }, { "description",RET_STR|EVAL_ONCE, NULL, NULL, 0 }, { "button", RET_INT|EVAL_ONCE, "0", NULL, 0 }, { "lininfo", RET_STR|EVAL_ALWAYS, NULL, NULL, 0 }, { "show", RET_BOOL|EVAL_SOMETIMES,"", NULL, 0 }, { "arg", RET_STR|EVAL_SOMETIMES, NULL, NULL, 0 }, { "selected", MAKE_COPY|RET_BOOL|EVAL_SOMETIMES, NULL, NULL, 0 }, { "itemmsg", RET_STR|EVAL_ALWAYS, NULL, NULL, 0 }, { "inactive", RET_BOOL|EVAL_SOMETIMES, NULL, NULL, 0 } }; #define CURmenu() (&(((menuinfo *) Cur_rec->odptr)->fm_mn)) #define CURmenuinfo() ((menuinfo *) Cur_rec->odptr) #define NUMactive() (((menuinfo *) Cur_rec->odptr)->numactive) #define DEVirt(X) (((menuinfo *) Cur_rec->odptr)->visible[X]) #define ARGS() (((menuinfo *) Cur_rec->odptr)->args) static struct menu_line objmenu_disp(); static struct actrec *Cur_rec; static int objmenu_noncur(); static int objmenu_reread(); static struct fm_mn parse_menu(); static token if_omsh(); extern menu_id menu_make(); /* ** Calls setaction and returns the token. */ static token objmenu_help(rec) struct actrec *rec; { token make_action(); Cur_rec = rec; return(setaction(sing_eval(CURmenu(), MN_HELP))); } /* ** Calls close function and frees the structures. */ static int objmenu_close(a) struct actrec *a; { int lcv, i; char *p, *strchr(); Cur_rec = a; copyAltenv(ARGS()); /* in case MN_CLOSE references $ARGs */ sing_eval(CURmenu(), MN_CLOSE); /* execute the close function */ freeitup(CURmenu()); /* free information IN the menuinfo structure */ objmenu_noncur(a, FALSE); /* delete ARGs from the Altenv */ lcv = array_len(ARGS()); /* delete ARGs from the menu data */ for (i = 0; i < lcv; i++) { char namebuf[BUFSIZ]; if (p = strchr(ARGS()[i], '=')) *p = '\0'; strcpy(namebuf, ARGS()[i]); if (p) *p = '='; delaltenv(&ARGS(), namebuf); } array_destroy(ARGS()); /* variable table */ array_destroy(((menuinfo *)a->odptr)->slks); /* visible slks */ array_destroy(((menuinfo *)a->odptr)->visible); /* visible items */ /* * Free information in the activation record */ free(a->odptr); /* free the menuinfo structure */ free(a->slks); /* free the object specific SLKS */ free(a->path); /* free path of the definition file */ return(menu_close(a->id)); /* close the menu */ } /* * Rereads if reread is set */ static int objmenu_reinit(a) struct actrec *a; { Cur_rec = a; if (sing_eval(CURmenu(), MN_REREAD)) return(objmenu_reread(a)); return(SUCCESS); } /* ** Front-end to parser(), it sets up defaults. */ static struct fm_mn parse_menu(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, Mn_tab, MN_KEYS); parser(flags, info_or_file, Mn_tab, MN_KEYS, &fm_mn.single, Mn_fld_tab, MN_FLD_KEYS, &fm_mn.multi, fp); return(fm_mn); } /* ** If a->id >= 0 this is a reread. If so it frees the old info. ** Either way it calls the parser. */ static int objmenu_reread(a) register struct actrec *a; { struct fm_mn *fm_mn; extern struct slk Defslk[MAX_SLK + 1]; extern struct slk Menuslk[]; extern char * itoa(); register int i, but; char buf[10]; char *label, *intr, *onintr, *get_def(); menuinfo *mi; int lcv; FILE *fp = NULL; Cur_rec = a; fm_mn = CURmenu(); mi = CURmenuinfo(); /* 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 (!(mi->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(CURmenu()); mi->fm_mn = parse_menu(mi->flags, a->path, fp); /* abs k14.0 */ if (fm_mn->single.attrs == NULL) { if (a->id >= 0) ar_close(a, FALSE); return(FAIL); } fm_mn->seqno = 1; mi->visible = NULL; mn_vislist(mi); strcpy(buf, "NR="); strncat(buf, itoa((long)array_len(mi->visible), 10), 6); /* abs k16 */ putaltenv(&ARGS(), buf); putAltenv(buf); if (!sing_eval(CURmenu(), MN_INIT) || (int)array_len(mi->visible) <= 0 || (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(CURmenu(), MN_CLOSE); freeitup(CURmenu()); objmenu_noncur(a, FALSE); /* clean up Altenv. abs k14 */ return(FAIL); } } ar_ctl(a, CTSETINTR, get_sing_def(CURmenu(), MN_INTR), NULL, NULL, NULL, NULL, NULL); ar_ctl(a, CTSETONINTR, get_sing_def(CURmenu(), MN_ONINTR), NULL, NULL, NULL, NULL, NULL); set_top_slks(Menuslk); if (sing_eval(CURmenu(), MN_MSELECT)) set_slk_mark(TRUE); else set_slk_mark(FALSE); memcpy((char *)a->slks, (char *)Defslk, sizeof(Defslk)); lcv = array_len(mi->slks); for (i = 0; i < lcv; i++) { but = atoi(multi_eval(fm_mn, mi->slks[i], MN_BUTT)) - 1; if (but < 0 || but >= MAX_SLK) /* abs */ continue; label = multi_eval(fm_mn, mi->slks[i], MN_NAME); intr = get_def(CURmenu(),mi->slks[i], MN_INTR); onintr = get_def(CURmenu(),mi->slks[i], MN_ONINTR); set_obj_slk(&(a->slks[but]), label, TOK_SLK1 + but, intr, onintr); } if (a->id >= 0) { objmenu_ctl(0, CTSETSTRT, a->id); /* go to 1st item. abs */ a->id = menu_reinit(a->id, 0, atoi(sing_eval(CURmenu(), MN_ROWS)), atoi(sing_eval(CURmenu(), MN_COLUMNS)), objmenu_disp, a->odptr); } (void) ar_ctl(Cur_rec, CTSETMSG, FALSE, NULL, NULL, NULL, NULL, NULL); /* was AR_cur. abs k15 */ return(SUCCESS); } /* ** Takes this object's information out of the altenv. */ static int objmenu_noncur(a, all) struct actrec *a; bool all; { register int i; register char *p; int lcv; Cur_rec = a; lcv = array_len(ARGS()); for (i = 0; i < lcv; i++) { char namebuf[BUFSIZ]; if (p = strchr(ARGS()[i], '=')) *p = '\0'; strcpy(namebuf, ARGS()[i]); if (p) *p = '='; delAltenv(namebuf); } if (all) return(menu_noncurrent(a->id)); else return(SUCCESS); } /* ** Moves information in this object's altenv to the major altenv. */ static int objmenu_current(a) struct actrec *a; { int line; char *str; Cur_rec = a; copyAltenv(ARGS()); menu_ctl(Cur_rec->id, CTGETPOS, &line); if ((str = multi_eval(CURmenu(), DEVirt(line), MN_ITEMMSG)) && *str) mess_temp(str); return(menu_current(a->id)); } /* ** get the right ARGS. abs k18 */ static int objmenu_temp_cur(a) struct actrec *a; { Cur_rec = a; copyAltenv(ARGS()); return(menu_current(a->id)); } /* ** Calculates the show functions to decide which menu lines and SLKs ** should be shown. */ int mn_vislist(mi) menuinfo *mi; { int i; struct fm_mn *ptr; int lcv; ptr = &(mi->fm_mn); if (!mi->visible) { mi->slks = (int *) array_create(sizeof(int), array_len(ptr->multi)); mi->visible = (int *) array_create(sizeof(int), array_len(ptr->multi)); } else { array_trunc(mi->slks); array_trunc(mi->visible); } lcv = array_len(ptr->multi); NUMactive() = 0; for (i = 0; i < lcv; i++) if (multi_eval(ptr, i, MN_SHOW)) { if (atoi(multi_eval(ptr, i, MN_BUTT))) mi->slks = (int *) array_append(mi->slks, (char *) &i); else mi->visible = (int *) array_append(mi->visible, (char *) &i); /* * Keep track of number of active menu items */ if (!multi_eval(ptr, i, MN_INACTIVE)) NUMactive()++; } return (0); } /* * TOGGLE MARK will toggle the "mark" flag for a given menu * item indexed by i (Multiple Selection Menus). */ int toggle_mark(ptr, i) struct fm_mn *ptr; int i; { struct attribute *att; att = (ptr->multi + i)->attrs[MN_SELECTED]; att->flags ^= MENU_MARKED; /* toggle flag */ return (0); } /* * ISMARKED will check for the "mark" flag */ int ismarked(ptr, i) struct fm_mn *ptr; int i; { struct attribute *att; att = (ptr->multi + i)->attrs[MN_SELECTED]; if (!att) return(0); if (sing_eval(ptr, MN_MSELECT) && !(att->flags & MENU_CHECKED) && multi_eval(ptr, i, MN_SELECTED)) { toggle_mark(ptr, i); att->flags |= MENU_CHECKED; } return (att->flags & MENU_MARKED); } /* ** Calculates NAME, FLAGS, and DESCRIPTION */ static struct menu_line objmenu_disp(n, mi) int n; menuinfo *mi; { register int i; struct fm_mn *ptr; struct menu_line m; if (n >= (int)array_len(mi->visible)) m.highlight = m.description = NULL; else { i = mi->visible[n]; ptr = &(mi->fm_mn); m.highlight = multi_eval(ptr, i, MN_NAME); m.lininfo = multi_eval(ptr, i, MN_LININFO); m.flags = 0; if (multi_eval(ptr, i, MN_INACTIVE)) m.flags = MENU_INACT; if (ismarked(ptr, i)) { m.flags = MENU_MRK; if (multi_eval(ptr, i, MN_INACTIVE)) m.flags = MENU_INACT|MENU_MRK; } m.description = multi_eval(ptr, i, MN_DESC); } return(m); } /* ** Shrinks the string (if needed) to max_len characters. ** Terminate the string with TRUNCATE_STR to show that it was ** truncated. */ char * shrink_str(str, max_len) char *str; int max_len; { static char shrunk[MAX_WIDTH]; int len; len = strlen(str); if (len <= max_len) { strncpy(shrunk, str, len); shrunk[len] = '\0'; } else { strncpy(shrunk, str, max_len - LEN_TRUNC_STR); strcpy(shrunk + max_len - LEN_TRUNC_STR, TRUNCATE_STR); } return(shrunk); } int objmenu_ctl(rec, cmd, arg1, arg2, arg3, arg4, arg5, arg6) struct actrec *rec; int cmd; int arg1, arg2, arg3, arg4, arg5, arg6; { int pos; switch (cmd) { case CTGETARG: { char *str; Cur_rec = rec; if (menu_ctl(rec->id, CTGETPOS, &pos) == FAIL) return(FAIL); pos = DEVirt(pos); if ((str = multi_eval(CURmenu(), pos, MN_ARG)) && *str) /* abs k16 */ { **((char ***)(&arg1)) = strsave(str); return(SUCCESS); } 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(CURmenu(), MN_FRMMSG, newmsg); } else mess_frame(sing_eval(CURmenu(), MN_FRMMSG)); return(SUCCESS); } case CTSETLIFE: { char *life; /* used Cur_rec before. abs F15 */ life = sing_eval((&(((menuinfo *) rec->odptr)->fm_mn)), MN_LIFE); setlifetime(rec, life); return(SUCCESS); } case CTSETSTRT: { char *str; menu_ctl(arg1, CTSETSTRT); if ((str = multi_eval(CURmenu(), DEVirt(0), MN_ITEMMSG)) && *str) mess_temp(str); return(SUCCESS); } /* not needed (yet) afterall. to add must make this routine return char * case CTGETDESCRIPTION: { menuinfo *mi = (menuinfo *)arg2; struct fm_mn *ptr = &(mi->fm_mn); if (arg1 >= array_len(mi->visible)) return(NULL); else return(multi_eval(ptr, mi->visible[arg1], MN_DESC)); } */ default: return(menu_ctl(rec->id, cmd, arg1, arg2, arg3, arg4, arg5, arg6)); } } /* ** Uses path_to_ar() and nextpath_to_ar() to see if it is a reopen ** and if so, makes it current. Otherwise, it builds the actrec and ** calls ar_create(). */ int IF_omopen(args) register char **args; { register int i; int do_inline; struct actrec a, *first_rec, *ar_create(), *path_to_ar(), *nextpath_to_ar(); struct fm_mn *fm_mn; extern struct slk Defslk[MAX_SLK + 1]; menuinfo *mi; char *life; char envbuf[6]; char *begcol, *begrow; int startrow, startcol, type; 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, *getaltenv(); strcpy(envbuf, "ARG1"); for (i = do_inline ? 2 : 1; (env = getaltenv(ARGS(), 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) /* circular list */ break; } mi = (menuinfo *)new(menuinfo); mi->flags = do_inline ? INLINE : 0; mi->args = NULL; a.odptr = (char *) mi; fm_mn = &(mi->fm_mn); 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.id = -1; a.fcntbl[AR_CLOSE] = objmenu_close; a.fcntbl[AR_HELP] = (int (*)())objmenu_help; /* added cast abs 9/12/88 */ a.fcntbl[AR_REREAD] = objmenu_reread; a.fcntbl[AR_REINIT] = objmenu_reinit; a.fcntbl[AR_CURRENT] = objmenu_current; a.fcntbl[AR_TEMP_CUR] = objmenu_temp_cur; /* abs k18 */ a.fcntbl[AR_NONCUR] = objmenu_noncur; a.fcntbl[AR_ODSH] = (int (*)())if_omsh; /* added cast abs 9/12/88 */ a.fcntbl[AR_CTL] = objmenu_ctl; Cur_rec = &a; setupenv(mi->flags, args, &ARGS()); if (objmenu_reread(&a) == FAIL) return(FAIL); begrow = sing_eval(fm_mn, MN_BEGROW); begcol = sing_eval(fm_mn, MN_BEGCOL); life = sing_eval(CURmenu(), MN_LIFE); life_and_pos(&a, life, begrow, begcol, &startrow, &startcol, &type); /* * create the menu (menu frame) */ a.id = menu_make(-1, shrink_str(sing_eval(fm_mn, MN_MENU), MAX_TITLE), type, startrow, startcol, atoi(sing_eval(fm_mn, MN_ROWS)), atoi(sing_eval(fm_mn, MN_COLUMNS)), objmenu_disp, (char *)mi); if (a.id == FAIL) return(FAIL); if (sing_eval(fm_mn, MN_ALTSLKS)) a.flags = AR_ALTSLKS; else a.flags = 0; if (sing_eval(fm_mn, MN_MSELECT)) menu_ctl(a.id, CTSETATTR); /* multi-select menu */ return(ar_current(Cur_rec = ar_create(&a), FALSE)); /* abs k15 */ } /* ** Takes a line number and calls setaction on its ACTION. ** (re-evaluate the lifetime descriptor before actually performing ** the specifie action via "setaction") */ token linaction(n) int n; { return(setaction(multi_eval(CURmenu(), n, MN_ACTI))); } /* ** Catches SLKs and processes them. */ token objmenu_stream(tok) register token tok; { int line; char *tmp, *str; char *ott_to_path(); int *slks; extern int Arg_count; int lcv; if (tok == TOK_NEXT) { /* kludge for per-item message (menu_stream passes TOK_NEXT) */ menu_ctl(Cur_rec->id, CTGETPOS, &line); if ((str = multi_eval(CURmenu(), DEVirt(line), MN_ITEMMSG)) && *str) mess_temp(str); return(TOK_NOP); } menu_ctl(Cur_rec->id, CTGETPOS, &line); tmp = multi_eval(CURmenu(), DEVirt(line), MN_LININFO); if (strlen(tmp)) { char buf[BUFSIZ]; sprintf(buf, "LININFO=%s", tmp); putAltenv(buf); } else delAltenv("LININFO"); if (tok >= TOK_SLK1 && tok <= TOK_SLK16) { int num; int i; slks = CURmenuinfo()->slks; num = tok - TOK_SLK1 + 1; lcv = array_len(slks); for (i = 0; i < lcv; i++) { if (atoi(multi_eval(CURmenu(), slks[i],MN_BUTT)) == num) tok = linaction(slks[i]); } } if (tok == TOK_MARK && sing_eval(CURmenu(), MN_MSELECT)) { /* * If this is a multiple selection menu then * mark the item (and update the menu) */ toggle_mark(CURmenu(), DEVirt(line)); menu_ctl(Cur_rec->id, CTSETPOS, DEVirt(line)); /* * SELECTED is updated in the alternate * environment in case the "action" descriptor * contains a reference to $SELECTED */ if (ismarked(CURmenu(), DEVirt(line))) putAltenv("SELECTED=true"); else putAltenv("SELECTED=false"); multi_eval(CURmenu(), DEVirt(line), MN_ACTI); tok = TOK_NOP; } else if (tok == TOK_OPEN && Arg_count < 2) { if (sing_eval(CURmenu(), MN_MSELECT)) tok = setaction(sing_eval(CURmenu(), MN_DONE)); else { menu_ctl(Cur_rec->id, CTGETPOS, &line); tok = linaction(DEVirt(line)); } } return(tok); } /* ** Calls menu_stream and objmenu_stream() */ static token if_omsh(a, t) struct actrec *a; register token t; { token (*func[3])(); extern token menu_stream(); register int olifetime; Cur_rec = a; olifetime = Cur_rec->lifetime; Cur_rec->lifetime = AR_PERMANENT; func[0] = menu_stream; func[1] = objmenu_stream; func[2] = NULL; t = stream(t, func); Cur_rec->lifetime = olifetime; return(t); }