mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-29 04:21:26 +01:00
New libforms.
Bumped major number. Ncurses backend still needs improving. Other back-ends need to be written.
This commit is contained in:
parent
8c0e89af78
commit
65e32573aa
@ -1,8 +1,10 @@
|
||||
LIB = forms
|
||||
SHLIB_MAJOR= 3
|
||||
SHLIB_MINOR= 0
|
||||
|
||||
SRCS = forms.c parser.y lex.l menu.c fields.c
|
||||
SRCS = debug.c bindings.c parser.y lex.l forms.c objects.c ncurses.c
|
||||
|
||||
CFLAGS += -I. -I${.CURDIR} -Wall -g -DHASH_STATS
|
||||
CFLAGS += -I. -I${.CURDIR} -DHASH_STATS #-g -DDEBUG -Wall -ansi -pedantic -Dlint
|
||||
LDFLAGS += -ll
|
||||
|
||||
CLEANFILES+= lex.c parser.c y.tab.h
|
||||
|
@ -3,7 +3,7 @@ NOMAN = yet
|
||||
|
||||
SRCS = example.c
|
||||
|
||||
CFLAGS = -g -static
|
||||
CFLAGS = -static #-g
|
||||
|
||||
.if exists(${.CURDIR}/../obj)
|
||||
FORMDIR=${.CURDIR}/../obj
|
||||
@ -11,7 +11,7 @@ FORMDIR=${.CURDIR}/../obj
|
||||
FORMDIR=${.CURDIR}/..
|
||||
.endif
|
||||
|
||||
LDADD = -L${FORMDIR} -lforms -lncurses -lmytinfo -ll
|
||||
DPADD = /usr/lib/libforms.a
|
||||
LDADD = -L${FORMDIR} -lforms -ldialog -lncurses -lmytinfo -ll
|
||||
DPADD = ${LIBFORMS} ${LIBNCURSES}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -33,66 +33,28 @@
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <strhash.h>
|
||||
#include <ncurses.h>
|
||||
#include "../forms.h"
|
||||
|
||||
extern hash_table *global_bindings;
|
||||
void UserRoutine(OBJECT *);
|
||||
|
||||
main()
|
||||
{
|
||||
struct Tuple *tuple;
|
||||
struct Form *form;
|
||||
struct Form *form1, *form2;
|
||||
int res;
|
||||
|
||||
initscr();
|
||||
|
||||
|
||||
if (form_load("example.frm") == FS_ERROR)
|
||||
exit(0);;
|
||||
|
||||
form = form_start("example");
|
||||
|
||||
if (!form) {
|
||||
err(-1, "No form `example' in example.frm returned");
|
||||
if (load_objects("example.frm") == ST_ERROR)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
keypad(form->window, TRUE);
|
||||
cbreak();
|
||||
noecho();
|
||||
bind_tuple(root_table, "User_Routine", TT_FUNC, &UserRoutine);
|
||||
|
||||
tuple = form_get_tuple(global_bindings, "example", FT_FORM);
|
||||
if (!tuple)
|
||||
err(0, "No such form: example");
|
||||
else
|
||||
form = (struct Form *)tuple->addr;
|
||||
|
||||
print_status("This is the status line");
|
||||
|
||||
form_bind_tuple(form->bindings, "exit_form", FT_FUNC, &exit_form);
|
||||
form_bind_tuple(form->bindings, "cancel_form", FT_FUNC, &cancel_form);
|
||||
|
||||
res = form_show("example");
|
||||
|
||||
while (form->status == FS_RUNNING) {
|
||||
do_field(form);
|
||||
wrefresh(form->window);
|
||||
}
|
||||
|
||||
wclear(form->window);
|
||||
wrefresh(form->window);
|
||||
|
||||
if (form->status == FS_EXIT) {
|
||||
printf("Your entries were:\n\n");
|
||||
tuple = form_get_tuple(form->bindings, "input1", FT_FIELD_INST);
|
||||
printf("Input 1 = %s\n", ((struct Field *)tuple->addr)->field.input->input);
|
||||
tuple = form_get_tuple(form->bindings, "input2", FT_FIELD_INST);
|
||||
printf("Input 2 = %s\n", ((struct Field *)tuple->addr)->field.input->input);
|
||||
tuple = form_get_tuple(form->bindings, "menu1", FT_FIELD_INST);
|
||||
res = ((struct Field *)tuple->addr)->field.menu->selected;
|
||||
printf("Menu selected = %d, %s\n", res,
|
||||
((struct Field *)tuple->addr)->field.menu->options[res]);
|
||||
} else if (form->status == FS_CANCEL)
|
||||
printf("You cancelled the form\n");
|
||||
|
||||
endwin();
|
||||
start_object("adduser");
|
||||
}
|
||||
|
||||
void
|
||||
UserRoutine(OBJECT *obj)
|
||||
{
|
||||
/* Just draw a box and return */
|
||||
exit (1);
|
||||
}
|
||||
|
@ -1,54 +1,162 @@
|
||||
Colours example_colors {
|
||||
pair = red, yellow
|
||||
pair = blue, white
|
||||
# An example form file for an adduser command
|
||||
!Forms Version name
|
||||
|
||||
Display screen1 {
|
||||
Height 1000
|
||||
Width 1000
|
||||
Type Ncurses {
|
||||
# libdialog compatible color pairs
|
||||
ColorPairs {
|
||||
01 Cyan Blue
|
||||
02 Black Black
|
||||
03 Black White
|
||||
04 Yellow White
|
||||
05 White White
|
||||
06 White Blue
|
||||
07 Black White
|
||||
08 White Blue
|
||||
09 Red White
|
||||
10 Yellow Blue
|
||||
11 Black White
|
||||
12 Black White
|
||||
13 Black White
|
||||
14 Black White
|
||||
15 Yellow White
|
||||
16 White White
|
||||
17 Yellow White
|
||||
18 Black White
|
||||
19 White White
|
||||
20 Black White
|
||||
21 White Blue
|
||||
22 Yellow White
|
||||
23 Yellow Blue
|
||||
24 Red White
|
||||
25 Red Blue
|
||||
26 Black White
|
||||
27 White White
|
||||
28 Green White
|
||||
29 Green White
|
||||
}
|
||||
}
|
||||
#
|
||||
# The AttrTable assosciates attribute strings with numeric id's.
|
||||
# It's up to the device dependant code to decide how to interprate an
|
||||
# attribute id. For ncurses the id is treated as a color pair number.
|
||||
# For other devices they'd likely be an index to some device specific
|
||||
# structure declared above.
|
||||
#
|
||||
AttrTable {
|
||||
screen 01
|
||||
shadow 02
|
||||
dialog 03
|
||||
title 04
|
||||
border 05
|
||||
button_active 06
|
||||
button_inactive 07
|
||||
button_key_active 08
|
||||
button_key_inactive 09
|
||||
button_label_active 10
|
||||
button_label_inactive 11
|
||||
inputbox 12
|
||||
inputbox_border 13
|
||||
searchbox 14
|
||||
searchbox_title 15
|
||||
searchbox_border 16
|
||||
position_indicator 17
|
||||
menubox 18
|
||||
menubox_border 19
|
||||
item 20
|
||||
item_selected 21
|
||||
tag 22
|
||||
tag_selected 23
|
||||
tag_key 24
|
||||
tag_key_selected 25
|
||||
check 26
|
||||
check_selected 27
|
||||
uarrow 28
|
||||
darrow 29
|
||||
}
|
||||
}
|
||||
|
||||
field1 { attributes = 0 text = "\standout This text is \bold bold and \blink flashy" }
|
||||
|
||||
field2 {
|
||||
height = 2
|
||||
width = 22
|
||||
text = "This is an input fieldwith a default"
|
||||
template {
|
||||
Width 15
|
||||
Text "This is defined as a template and duplicated here"
|
||||
}
|
||||
|
||||
field3 {
|
||||
width = 10
|
||||
default = "This is a default entry"
|
||||
limit = 30
|
||||
}
|
||||
|
||||
field4 { text = "This is a labelled input field" }
|
||||
|
||||
field5 { label = "A temp. label" }
|
||||
|
||||
field6 { text = "Some options to choose from: " }
|
||||
|
||||
field7 { selected = 0 options = "Choose", "another", "of", "these" }
|
||||
|
||||
field8 { width = 6 action = "EXIT" function = exit_form }
|
||||
|
||||
field9 {
|
||||
action = "CANCEL"
|
||||
function = cancel_form
|
||||
}
|
||||
|
||||
Form example at 0,0 {
|
||||
height = 25
|
||||
width = 80
|
||||
start = input1
|
||||
colortable = example
|
||||
attributes = 0
|
||||
|
||||
Title {attributes = 0 text = "A Simple Demo"} at 0,30
|
||||
|
||||
field1 at 3,23
|
||||
field2 at 7, 2
|
||||
field4 at 11, 2
|
||||
field6 at 15, 2
|
||||
|
||||
input1 {field3} at 7,45, next=input2,down=input2,up=quit,right=input2
|
||||
input2 {field5} at 11,45, next=menu1,down=menu1,up=input1,right=menu1
|
||||
menu1 {field7} at 15,45, next=quit,down=quit,up=input2,right=quit
|
||||
quit {field8} at 20,20, next=cancel,down=input1,up=menu1,right=cancel
|
||||
cancel {field9} at 20,43, next=input1,down=input1,up=menu1,right=input1
|
||||
Window adduser on screen1 at 0,0 {
|
||||
Attributes "\screen"
|
||||
|
||||
window at 1,1 {
|
||||
Height 22
|
||||
Width 75
|
||||
Attributes "\dialog"
|
||||
Active username
|
||||
|
||||
box {
|
||||
Attributes "\dialog"
|
||||
Highlight "\border"
|
||||
CallFunc draw_box
|
||||
shadow {
|
||||
Attributes "\shadow"
|
||||
CallFunc draw_shadow
|
||||
}
|
||||
}
|
||||
|
||||
Title at 0,9 { Text " This is a title " }
|
||||
|
||||
username at 5,20 {
|
||||
Height 1
|
||||
Width 30
|
||||
Attributes "\screen"
|
||||
Highlight "\tag_selected"
|
||||
|
||||
Next shells
|
||||
|
||||
Input "nobody"
|
||||
|
||||
exp at 3,3 {
|
||||
Attributes "\dialog"
|
||||
Text "The is an input object:"
|
||||
}
|
||||
prompt at 5,3 {
|
||||
Text "Username: "
|
||||
}
|
||||
}
|
||||
|
||||
shells at 9,20 {
|
||||
Attributes "\dialog"
|
||||
Highlight "\tag_selected"
|
||||
Next button
|
||||
Options {
|
||||
"sh"
|
||||
"csh"
|
||||
"tcsh"
|
||||
"bash"
|
||||
}
|
||||
|
||||
exp at 7,3 {
|
||||
Attributes "\dialog"
|
||||
Text "This is a horizontal menu:"
|
||||
}
|
||||
prompt at 9,3 { Text "Select a shell: "}
|
||||
}
|
||||
|
||||
button at 14,9 {
|
||||
Height 3
|
||||
Width 7
|
||||
Attributes "\tag_key_selected"
|
||||
Highlight "\tag_selected"
|
||||
Active button
|
||||
|
||||
button_box at 14,9 {
|
||||
CallFunc draw_box
|
||||
}
|
||||
|
||||
button at 15, 10 {
|
||||
Up username Down username
|
||||
Action User_Routine
|
||||
Label "QUIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,309 +33,235 @@
|
||||
*/
|
||||
|
||||
#include <strhash.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ncurses.h>
|
||||
#include <forms.h>
|
||||
#include <err.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
extern FILE *yyin;
|
||||
hash_table *root_table, *cbind;
|
||||
OBJECT *cur_obj;
|
||||
int done;
|
||||
|
||||
hash_table *global_bindings;
|
||||
|
||||
unsigned int f_keymap[] = {
|
||||
KEY_UP, /* F_UP */
|
||||
KEY_DOWN, /* F_DOWN */
|
||||
9, /* F_RIGHT */
|
||||
8, /* F_LEFT */
|
||||
10, /* F_NEXT */
|
||||
KEY_LEFT, /* F_CLEFT */
|
||||
KEY_RIGHT, /* F_CRIGHT */
|
||||
KEY_HOME, /* F_CHOME */
|
||||
KEY_END, /* F_CEND */
|
||||
263, /* F_CBS */
|
||||
330, /* F_CDEL */
|
||||
10 /* F_ACCEPT */
|
||||
/* Default attribute commands */
|
||||
struct attr_cmnd attr_cmnds[] = {
|
||||
{"box", ATTR_BOX },
|
||||
{"center", ATTR_CENTER },
|
||||
{"right", ATTR_RIGHT }
|
||||
};
|
||||
|
||||
/* Internal bindings */
|
||||
|
||||
struct intbind {
|
||||
char *key;
|
||||
void *addr;
|
||||
};
|
||||
|
||||
struct intbind internal_bindings[] = {
|
||||
{"draw_box", &draw_box},
|
||||
{"draw_shadow", &draw_shadow}
|
||||
};
|
||||
|
||||
/* Bind the internal function addresses */
|
||||
|
||||
void
|
||||
bind_internals(hash_table *table)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < (sizeof internal_bindings)/(sizeof (struct intbind)); i++)
|
||||
if (bind_tuple(table, internal_bindings[i].key,
|
||||
TT_FUNC, internal_bindings[i].addr) == ST_ERROR)
|
||||
errx(-1, "Failed to bind internal tuples");
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the default device and open a display on it.
|
||||
*/
|
||||
|
||||
DISPLAY *
|
||||
default_open(DISPLAY *display)
|
||||
{
|
||||
/* XXX -- not implemented, just calls ncurses */
|
||||
return (ncurses_open(display));
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
form_load(const char *filename)
|
||||
load_objects(const char *filename)
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
global_bindings = hash_create(0);
|
||||
root_table = hash_create(0);
|
||||
if (!root_table)
|
||||
errx(-1, "Failed to allocate root bindings table");
|
||||
|
||||
if (!global_bindings)
|
||||
return (FS_ERROR);
|
||||
cbind = root_table;
|
||||
|
||||
bind_internals(root_table);
|
||||
|
||||
if (!(fd = fopen(filename, "r"))) {
|
||||
warn("Couldn't open forms file %s", filename);
|
||||
return (FS_ERROR);
|
||||
warn("Couldn't open file %s", filename);
|
||||
return (ST_ERROR);
|
||||
}
|
||||
|
||||
yyin = fd;
|
||||
yyparse();
|
||||
|
||||
if (fclose(fd)) {
|
||||
warn("Couldn't close forms file %s", filename);
|
||||
return (FS_ERROR);
|
||||
warn("Couldn't close file %s", filename);
|
||||
return (ST_ERROR);
|
||||
}
|
||||
|
||||
hash_stats(global_bindings, 1);
|
||||
|
||||
return (FS_OK);
|
||||
return (ST_OK);
|
||||
}
|
||||
|
||||
int
|
||||
find_editable(char *key, void *data, void *arg)
|
||||
start_object(char *objname)
|
||||
{
|
||||
struct Tuple *tuple = (struct Tuple *)data;
|
||||
struct Field *field;
|
||||
TUPLE *tuple;
|
||||
OBJECT *object;
|
||||
|
||||
if (tuple->type != FT_FIELD_INST)
|
||||
return (1);
|
||||
tuple = get_tuple(root_table, objname, TT_OBJ_INST);
|
||||
if (!tuple)
|
||||
return (ST_NOBIND);
|
||||
|
||||
field = (struct Field *)tuple->addr;
|
||||
object = (OBJECT *)tuple->addr;
|
||||
cur_obj = object;
|
||||
|
||||
if ((field->type == FF_INPUT) ||
|
||||
(field->type == FF_MENU) ||
|
||||
(field->type == FF_ACTION)) {
|
||||
arg = field;
|
||||
return (0);
|
||||
} else
|
||||
return (1);
|
||||
}
|
||||
set_display(object->display);
|
||||
|
||||
struct Form *
|
||||
form_start(char *formname)
|
||||
{
|
||||
struct Tuple *tuple;
|
||||
struct Form *form;
|
||||
struct Field *field = 0;
|
||||
struct Field *start = 0;
|
||||
cur_obj->status |= O_VISIBLE;
|
||||
|
||||
tuple = form_get_tuple(global_bindings, formname, FT_FORM);
|
||||
|
||||
if (!tuple) {
|
||||
warnx("No such form");
|
||||
return (0);
|
||||
while (!done) {
|
||||
hash_traverse(root_table, &display_tuples, root_table);
|
||||
hash_traverse(root_table, &refresh_displays, root_table);
|
||||
process_object(cur_obj);
|
||||
}
|
||||
|
||||
form = tuple->addr;
|
||||
|
||||
/* Initialise form */
|
||||
if (!form->height)
|
||||
form->height = LINES;
|
||||
if (!form->width)
|
||||
form->width = COLS;
|
||||
|
||||
form->window = newwin(form->height, form->width, form->y, form->x);
|
||||
if (!form->window) {
|
||||
warnx("Couldn't open window, closing form");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Initialise the field instances */
|
||||
|
||||
hash_traverse(form->bindings, init_field, field);
|
||||
|
||||
tuple = form_get_tuple(form->bindings, form->startfield, FT_FIELD_INST);
|
||||
|
||||
if (!tuple) {
|
||||
warnx("No start field specified");
|
||||
/* Search for an editable field */
|
||||
hash_traverse(form->bindings, &find_editable, start);
|
||||
form->current_field = start;
|
||||
} else
|
||||
form->current_field = (struct Field *)tuple->addr;
|
||||
|
||||
if (!form->current_field)
|
||||
errx(1, "No suitable start field found, aborting");
|
||||
|
||||
form->prev_field = form->current_field;
|
||||
|
||||
form->status = FS_RUNNING;
|
||||
|
||||
return (form);
|
||||
return (ST_DONE);
|
||||
}
|
||||
|
||||
int
|
||||
form_bind_tuple(hash_table *htable, char *name, TupleType type, void *addr)
|
||||
call_function(char *func, OBJECT *obj)
|
||||
{
|
||||
struct Tuple *tuple;
|
||||
TUPLE *tuple;
|
||||
|
||||
tuple = malloc(sizeof (struct Tuple));
|
||||
if (!tuple) {
|
||||
warn("Couldn't allocate memory for new tuple");
|
||||
return (FS_ERROR);
|
||||
}
|
||||
|
||||
tuple->name = name;
|
||||
tuple->type = type;
|
||||
tuple->addr = addr;
|
||||
tuple->next = 0;
|
||||
|
||||
if (!htable)
|
||||
return (FS_ERROR);
|
||||
else {
|
||||
/* Check there isn't already a tuple of this type with this name */
|
||||
if (form_get_tuple(htable, name, type)) {
|
||||
warn("Duplicate tuple name, %s, skipping", name);
|
||||
return (FS_ERROR);
|
||||
} else
|
||||
hash_search(htable, tuple->name, tuple, NULL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
tuple_match_any(char *key, struct Tuple *tuple, TupleType *type)
|
||||
{
|
||||
if (tuple->type != *type) {
|
||||
type = 0;
|
||||
return (1);
|
||||
} else {
|
||||
type = (TupleType *)tuple;
|
||||
tuple = tuple_search(obj, func, TT_FUNC);
|
||||
if (!tuple)
|
||||
return (0);
|
||||
|
||||
(*tuple->addr)(obj);
|
||||
return (1);
|
||||
}
|
||||
|
||||
set_display(DISPLAY *display)
|
||||
{
|
||||
switch (display->type) {
|
||||
case DT_NCURSES:
|
||||
ncurses_set_display(display);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct Tuple *
|
||||
form_get_tuple(hash_table *htable, char *key, TupleType type)
|
||||
void
|
||||
display_object(OBJECT *obj)
|
||||
{
|
||||
void *arg = &type;
|
||||
switch(obj->display->type) {
|
||||
case DT_NCURSES:
|
||||
ncurses_display_object(obj);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a key is specified then search for that key,
|
||||
* otherwise, search the whole table for the first
|
||||
* tuple of the required type.
|
||||
*/
|
||||
void
|
||||
process_object(OBJECT *obj)
|
||||
{
|
||||
TUPLE *tuple;
|
||||
|
||||
if (key)
|
||||
return(hash_search(htable, key, NULL, NULL));
|
||||
else {
|
||||
hash_traverse(htable, &tuple_match_any, arg);
|
||||
return (arg);
|
||||
/* Call user routine, if there is one. */
|
||||
if (obj->UserProcFunc)
|
||||
if (call_function(obj->UserProcFunc, obj))
|
||||
return;
|
||||
|
||||
/* Find the first non-compound object or a default override */
|
||||
while (obj->type == OT_COMPOUND) {
|
||||
tuple = tuple_search(obj, obj->object.compound->defobj, TT_OBJ_INST);
|
||||
obj = (OBJECT *)tuple->addr;
|
||||
}
|
||||
cur_obj = obj;
|
||||
|
||||
switch(obj->display->type) {
|
||||
case DT_NCURSES:
|
||||
ncurses_process_object(obj);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
show_field(char *key, void *data, void *arg)
|
||||
refresh_displays(char *key, void *data, void *arg)
|
||||
{
|
||||
struct Tuple *tuple = (struct Tuple *)data;
|
||||
struct Field *field = (struct Field *)tuple->addr;
|
||||
TUPLE *tuple = (TUPLE *)data;
|
||||
DISPLAY *display;
|
||||
|
||||
display_field(arg, field);
|
||||
if (tuple->type == TT_DISPLAY)
|
||||
display = (DISPLAY *)tuple->addr;
|
||||
switch (display->type) {
|
||||
case DT_NCURSES:
|
||||
ncurses_refresh_display(display);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (1);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
form_show(char *formname)
|
||||
display_tuples(char *key, void *data, void *arg)
|
||||
{
|
||||
struct Tuple *tuple;
|
||||
struct Form *form;
|
||||
int x, y;
|
||||
TUPLE *tuple = (TUPLE *)data;
|
||||
OBJECT *obj;
|
||||
void (* fn)();
|
||||
|
||||
tuple = form_get_tuple(global_bindings, formname, FT_FORM);
|
||||
if (!tuple)
|
||||
return (FS_NOBIND);
|
||||
switch(tuple->type) {
|
||||
case TT_OBJ_INST:
|
||||
obj = (OBJECT *)tuple->addr;
|
||||
|
||||
form = tuple->addr;
|
||||
/* Call user routine, if there is one. */
|
||||
if (obj->UserDrawFunc) {
|
||||
if (!call_function(obj->UserDrawFunc, obj))
|
||||
display_object(obj);
|
||||
} else
|
||||
display_object(obj);
|
||||
|
||||
/* Clear form */
|
||||
wattrset(form->window, form->attr);
|
||||
for (y=0; y < form->height; y++)
|
||||
for (x=0; x < form->width; x++)
|
||||
mvwaddch(form->window, y, x, ' ');
|
||||
|
||||
hash_traverse(form->bindings, show_field, form->window);
|
||||
|
||||
return (FS_OK);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
do_key_bind(struct Form *form, unsigned int ch)
|
||||
{
|
||||
struct Field *field = form->current_field;
|
||||
struct Tuple *tuple=0;
|
||||
|
||||
/* XXX -- check for keymappings here --- not yet done */
|
||||
|
||||
if (ch == FK_UP) {
|
||||
if (field->fup) {
|
||||
tuple = form_get_tuple(form->bindings, field->fup, FT_FIELD_INST);
|
||||
if (!tuple)
|
||||
print_status("Field to move up to does not exist");
|
||||
} else
|
||||
print_status("Can't move up from this field");
|
||||
} else if (ch == FK_DOWN) {
|
||||
if (field->fdown) {
|
||||
tuple = form_get_tuple(form->bindings, field->fdown, FT_FIELD_INST);
|
||||
if (!tuple)
|
||||
print_status("Field to move down to does not exist");
|
||||
} else
|
||||
print_status("Can't move down from this field");
|
||||
} else if (ch == FK_LEFT) {
|
||||
if (field->fleft) {
|
||||
tuple = form_get_tuple(form->bindings, field->fleft, FT_FIELD_INST);
|
||||
if (!tuple)
|
||||
print_status("Field to move left to does not exist");
|
||||
} else
|
||||
print_status("Can't move left from this field");
|
||||
} else if (ch == FK_RIGHT) {
|
||||
if (field->fright) {
|
||||
tuple = form_get_tuple(form->bindings, field->fright, FT_FIELD_INST);
|
||||
if (!tuple)
|
||||
print_status("Field to move right to does not exist");
|
||||
} else
|
||||
print_status("Can't move right from this field");
|
||||
} else if (ch == FK_NEXT) {
|
||||
if (field->fnext) {
|
||||
tuple = form_get_tuple(form->bindings, field->fnext, FT_FIELD_INST);
|
||||
if (!tuple)
|
||||
print_status("Field to move to next does not exist");
|
||||
} else
|
||||
print_status("Can't move next from this field");
|
||||
} else
|
||||
/* No motion keys pressed */
|
||||
return (ch);
|
||||
|
||||
if (tuple) {
|
||||
form->prev_field = form->current_field;
|
||||
form->current_field = tuple->addr;
|
||||
return (FS_OK);
|
||||
} else {
|
||||
beep();
|
||||
return (FS_ERROR);
|
||||
/* Display sub-objects */
|
||||
if (obj->bind)
|
||||
hash_traverse(obj->bind, &display_tuples, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NOT_YET
|
||||
void
|
||||
debug_dump_bindings(hash_table *htable)
|
||||
AttrType
|
||||
parse_default_attributes(char *string)
|
||||
{
|
||||
struct Tuple *binds;
|
||||
int i;
|
||||
|
||||
binds = form_get_tuple(htable, 0, FT_ANY);
|
||||
while (binds) {
|
||||
printf("%s, %d, %x\n", binds->name, binds->type, (int)binds->addr);
|
||||
binds = form_next_tuple(0, FT_ANY, binds->next);
|
||||
}
|
||||
for (i=0; i < (sizeof attr_cmnds) / (sizeof (struct attr_cmnd)); i++)
|
||||
if (!strcmp(string, attr_cmnds[i].attr_name))
|
||||
return (attr_cmnds[i].attr_type);
|
||||
return (ATTR_UNKNOWN);
|
||||
}
|
||||
|
||||
void debug_dump_form(struct Form *form)
|
||||
{
|
||||
struct Field *field;
|
||||
|
||||
field = form->fieldlist;
|
||||
|
||||
for ( ; field; field = field->next) {
|
||||
printf("%s, %x, next = %x\n", field->defname, (int)field, (int)field->next);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -32,126 +32,158 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ncurses.h>
|
||||
#ifndef _FORMS_H_
|
||||
#define _FORMS_H_
|
||||
|
||||
#define FF_UNKNOWN 0
|
||||
#define FF_TEXT 1
|
||||
#define FF_ACTION 2
|
||||
#define FF_INPUT 3
|
||||
#define FF_MENU 4
|
||||
#include <ncurses.h>
|
||||
#include <strhash.h>
|
||||
|
||||
#define F_DEFATTR 0
|
||||
#define F_SELATTR A_REVERSE
|
||||
|
||||
/* Status values */
|
||||
|
||||
#define FS_ERROR -1
|
||||
#define FS_OK 0
|
||||
#define FS_EXIT 1
|
||||
#define FS_CANCEL 2
|
||||
#define FS_NOBIND 3
|
||||
#define FS_RUNNING 4
|
||||
|
||||
#define ST_ERROR -1
|
||||
#define ST_OK 0
|
||||
#define ST_DONE 1
|
||||
#define ST_CANCEL 2
|
||||
#define ST_NOBIND 3
|
||||
#define ST_RUNNING 4
|
||||
|
||||
typedef enum {
|
||||
FT_ANY,
|
||||
FT_FORM,
|
||||
FT_COLTAB,
|
||||
FT_FIELD_INST,
|
||||
FT_FIELD_DEF,
|
||||
FT_FUNC
|
||||
TT_ANY,
|
||||
TT_OBJ_INST,
|
||||
TT_OBJ_DEF,
|
||||
TT_FUNC,
|
||||
TT_DISPLAY,
|
||||
TT_ATTR
|
||||
} TupleType;
|
||||
|
||||
struct Tuple {
|
||||
typedef enum {
|
||||
DT_ANY,
|
||||
DT_NCURSES,
|
||||
DT_X,
|
||||
DT_VGA
|
||||
} DisplayType;
|
||||
|
||||
typedef enum {
|
||||
OT_ACTION,
|
||||
OT_COMPOUND,
|
||||
OT_FUNCTION,
|
||||
OT_INPUT,
|
||||
OT_MENU,
|
||||
OT_SHADOW,
|
||||
OT_TEXT
|
||||
} ObjectType;
|
||||
|
||||
#define FUNCP void(*)(void *)
|
||||
|
||||
typedef struct Tuple {
|
||||
char *name;
|
||||
int type;
|
||||
void *addr;
|
||||
struct Tuple *next;
|
||||
};
|
||||
void (*addr)(void *);
|
||||
} TUPLE;
|
||||
|
||||
struct col_pair {
|
||||
int f;
|
||||
int b;
|
||||
};
|
||||
typedef struct NcursesDevice {
|
||||
char *ttyname;
|
||||
char *input;
|
||||
char *output;
|
||||
SCREEN *screen;
|
||||
} NCURSDEV;
|
||||
|
||||
struct Form {
|
||||
int status;
|
||||
int no_fields;
|
||||
char *startfield;
|
||||
struct Field *current_field;
|
||||
struct Field *prev_field;
|
||||
typedef struct NcursesWindow {
|
||||
WINDOW *win;
|
||||
} NCURSES_WINDOW;
|
||||
|
||||
typedef struct Display {
|
||||
DisplayType type;
|
||||
int height;
|
||||
int width;
|
||||
int y;
|
||||
int x;
|
||||
int attr;
|
||||
char *colortable;
|
||||
WINDOW *window;
|
||||
hash_table *bindings;
|
||||
};
|
||||
int virt_height;
|
||||
int virt_width;
|
||||
union {
|
||||
NCURSDEV *ncurses;
|
||||
} device;
|
||||
hash_table *bind;
|
||||
} DISPLAY;
|
||||
|
||||
struct TextField {
|
||||
typedef struct ActionObject {
|
||||
char *text;
|
||||
};
|
||||
char *action;
|
||||
} ACTION_OBJECT;
|
||||
|
||||
struct ActionField {
|
||||
char *text;
|
||||
typedef struct CompoundObject {
|
||||
char *defobj;
|
||||
} COMPOUND_OBJECT;
|
||||
|
||||
typedef struct FunctionObject {
|
||||
char *fn;
|
||||
};
|
||||
} FUNCTION_OBJECT;
|
||||
|
||||
struct InputField {
|
||||
typedef struct InputObject {
|
||||
int lbl_flag;
|
||||
char *label;
|
||||
char *input;
|
||||
int limit;
|
||||
};
|
||||
} INPUT_OBJECT;
|
||||
|
||||
struct MenuField {
|
||||
typedef struct MenuObject {
|
||||
int selected;
|
||||
int no_options;
|
||||
char **options;
|
||||
};
|
||||
} MENU_OBJECT;
|
||||
|
||||
struct help_link {
|
||||
};
|
||||
typedef struct TextObject {
|
||||
char *text;
|
||||
} TEXT_OBJECT;
|
||||
|
||||
struct Field {
|
||||
char *defname;
|
||||
char *enter;
|
||||
char *leave;
|
||||
int type;
|
||||
typedef union {
|
||||
NCURSES_WINDOW *ncurses;
|
||||
} WIN;
|
||||
|
||||
typedef union {
|
||||
ACTION_OBJECT *action;
|
||||
COMPOUND_OBJECT *compound;
|
||||
FUNCTION_OBJECT *function;
|
||||
INPUT_OBJECT *input;
|
||||
MENU_OBJECT *menu;
|
||||
TEXT_OBJECT *text;
|
||||
} OBJ_TYPE;
|
||||
|
||||
typedef struct Object {
|
||||
ObjectType type;
|
||||
int status;
|
||||
struct Object *parent;
|
||||
int y;
|
||||
int x;
|
||||
int height;
|
||||
int width;
|
||||
int attr;
|
||||
int selattr;
|
||||
char *fnext;
|
||||
char *fup;
|
||||
char *fdown;
|
||||
char *fleft;
|
||||
char *fright;
|
||||
char *f_keymap;
|
||||
union {
|
||||
struct TextField *text;
|
||||
struct ActionField *action;
|
||||
struct InputField *input;
|
||||
struct MenuField *menu;
|
||||
}field;
|
||||
/*
|
||||
struct help_link help;
|
||||
*/
|
||||
};
|
||||
char *attributes;
|
||||
char *highlight;
|
||||
char *lnext;
|
||||
char *lup;
|
||||
char *ldown;
|
||||
char *lleft;
|
||||
char *lright;
|
||||
char *UserDrawFunc;
|
||||
char *UserProcFunc;
|
||||
char *OnEntry;
|
||||
char *OnExit;
|
||||
OBJ_TYPE object;
|
||||
hash_table *bind;
|
||||
struct Display *display;
|
||||
WIN window;
|
||||
} OBJECT;
|
||||
|
||||
/* Externally visible keymap table for user-definable keymaps */
|
||||
extern unsigned int keymap[];
|
||||
/* Externally visible variables */
|
||||
extern hash_table *root_table;
|
||||
|
||||
/* Externally visible function declarations */
|
||||
struct Form *form_start(char *);
|
||||
struct Tuple *form_get_tuple(hash_table *, char *, TupleType);
|
||||
int form_bind_tuple(hash_table *, char *, TupleType, void *);
|
||||
void print_status(char *);
|
||||
void exit_form(struct Form *form);
|
||||
void cancel_form(struct Form *form);
|
||||
void print_status(char *);
|
||||
int add_menu_option(struct MenuField *, char *);
|
||||
/* Function declarations */
|
||||
__inline struct Tuple *get_tuple(hash_table *, char *, TupleType);
|
||||
TUPLE *tuple_search(OBJECT *, char *, TupleType);
|
||||
int bind_tuple(hash_table *, char *, TupleType, void(*fn)());
|
||||
int add_menu_option(MENU_OBJECT *, char *);
|
||||
void draw_box(OBJECT *);
|
||||
void draw_shadow(OBJECT *);
|
||||
|
||||
#endif /* _FORMS_H_ */
|
||||
|
@ -32,45 +32,60 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define FK_UP f_keymap[0]
|
||||
#define FK_DOWN f_keymap[1]
|
||||
#define FK_RIGHT f_keymap[2]
|
||||
#define FK_LEFT f_keymap[3]
|
||||
#define FK_NEXT f_keymap[4]
|
||||
#define FK_CLEFT f_keymap[5]
|
||||
#define FK_CRIGHT f_keymap[6]
|
||||
#define FK_CHOME f_keymap[7]
|
||||
#define FK_CEND f_keymap[8]
|
||||
#define FK_CBS f_keymap[9]
|
||||
#define FK_CDEL f_keymap[10]
|
||||
#define FK_ACCEPT f_keymap[11]
|
||||
/* Object status values */
|
||||
#define O_VISIBLE 0x0001
|
||||
#define O_ACTIVE 0x0002
|
||||
|
||||
extern unsigned int f_keymap[];
|
||||
/* Standard attribute commands */
|
||||
typedef enum {
|
||||
ATTR_BOX,
|
||||
ATTR_CENTER,
|
||||
ATTR_RIGHT,
|
||||
ATTR_SHADOW,
|
||||
ATTR_UNKNOWN
|
||||
} AttrType;
|
||||
|
||||
struct attr_cmnd {
|
||||
char *attr_name;
|
||||
AttrType attr_type;
|
||||
};
|
||||
|
||||
/* Ncurses color pairs */
|
||||
typedef struct color_pair {
|
||||
int no;
|
||||
int fg;
|
||||
int bg;
|
||||
} COLPAIR;
|
||||
|
||||
extern struct attr_cmnd attr_cmnds[];
|
||||
|
||||
extern hash_table *root_table, *cbind;
|
||||
extern DISPLAY *cdisp;
|
||||
extern int lineno;
|
||||
|
||||
/* Private function declarations */
|
||||
void display_field(WINDOW *, struct Field *);
|
||||
void display_text(WINDOW *, struct Field *);
|
||||
void display_input(WINDOW *, struct Field *);
|
||||
void display_menu(WINDOW *, struct Field *);
|
||||
void display_action(WINDOW *, struct Field *);
|
||||
int print_string(WINDOW *, int, int, int, int, char *);
|
||||
unsigned int do_key_bind(struct Form *, unsigned int);
|
||||
int do_action(struct Form *);
|
||||
int do_menu(struct Form *);
|
||||
int do_input(struct Form *);
|
||||
int init_field(char *, void *, void *);
|
||||
int calc_string_width(char *);
|
||||
void calc_field_height(struct Field *, char *);
|
||||
int display_tuples(char *, void *, void *);
|
||||
int refresh_displays(char *, void *, void *);
|
||||
int copy_object_tree(char *, void *, void *);
|
||||
void process_tuple(OBJECT *);
|
||||
void process_object(OBJECT *);
|
||||
void process_input_object(OBJECT *);
|
||||
void process_menu_object(OBJECT *);
|
||||
void process_text_object(OBJECT *);
|
||||
|
||||
#ifdef not
|
||||
static void show_form(struct form *);
|
||||
static void disp_text(struct form *);
|
||||
static void disp_menu(struct form *);
|
||||
static void disp_action(struct form *);
|
||||
static void disp_input(struct form *);
|
||||
static void field_menu(struct form *);
|
||||
static void field_input(struct form *);
|
||||
static void field_action(struct form *);
|
||||
static int print_string(WINDOW *, int, int, int, int, char *);
|
||||
static int next_field(struct form *form, int);
|
||||
#endif
|
||||
DISPLAY *default_open(DISPLAY *);
|
||||
DISPLAY *ncurses_open(DISPLAY *);
|
||||
|
||||
int ncurses_print_string(OBJECT *, char *);
|
||||
void ncurses_print_status(char *);
|
||||
int ncurses_bind_key(OBJECT *, unsigned int);
|
||||
void ncurses_display_action(OBJECT *);
|
||||
void ncurses_display_compound(OBJECT *);
|
||||
void ncurses_display_function(OBJECT *);
|
||||
void ncurses_display_input(OBJECT *);
|
||||
void ncurses_display_menu(OBJECT *);
|
||||
void ncurses_display_text(OBJECT *);
|
||||
void ncurses_process_action(OBJECT *);
|
||||
void ncurses_process_input(OBJECT *);
|
||||
void ncurses_process_menu(OBJECT *);
|
||||
void ncurses_process_text(OBJECT *);
|
||||
|
@ -32,6 +32,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "y.tab.h"
|
||||
@ -40,56 +42,81 @@ extern int charno;
|
||||
extern int off;
|
||||
%}
|
||||
|
||||
NUM [0-9]+
|
||||
|
||||
%%
|
||||
colortable { return COLORTABLE; }
|
||||
colourtable { return COLORTABLE; }
|
||||
Colors { return COLOR; }
|
||||
Colours { return COLOR; }
|
||||
black { return BLACK; }
|
||||
red { return RED; }
|
||||
green { return GREEN; }
|
||||
yellow { return YELLOW; }
|
||||
blue { return BLUE; }
|
||||
magenta { return MAGENTA; }
|
||||
cyan { return CYAN; }
|
||||
white { return WHITE; }
|
||||
pair { return PAIR; }
|
||||
Form { return FORM; }
|
||||
at { return AT; }
|
||||
!Forms { return FORMS; }
|
||||
Action { return ACTION; }
|
||||
Active { return ACTIVE; }
|
||||
as { return AS; }
|
||||
height { return HEIGHT; }
|
||||
= { return EQUALS; }
|
||||
width { return WIDTH; }
|
||||
start { return STARTFIELD; }
|
||||
text { return TEXT; }
|
||||
attributes { return ATTR; }
|
||||
highlight { return SELATTR; }
|
||||
label { return LABEL; }
|
||||
default { return DEFAULT; }
|
||||
limit { return LIMIT; }
|
||||
selected { return SELECTED; }
|
||||
options { return OPTIONS; }
|
||||
action { return ACTION; }
|
||||
function { return FUNC; }
|
||||
up { return UP; }
|
||||
down { return DOWN; }
|
||||
left { return LEFT; }
|
||||
right { return RIGHT; }
|
||||
next { return NEXT; }
|
||||
at { return AT; }
|
||||
Attributes { return ATTR; }
|
||||
AttrTable { return ATTRTABLE; }
|
||||
CallFunc { return CALLFUNC; }
|
||||
ColorPairs { return COLORPAIRS; }
|
||||
Default { return DEFAULT; }
|
||||
Display { return A_DISPLAY; }
|
||||
Down { return DOWN; }
|
||||
Forms { return FORMS; }
|
||||
Function { return FUNCTION; }
|
||||
Height { return HEIGHT; }
|
||||
Highlight { return HIGHLIGHT; }
|
||||
Input { return INPUT; }
|
||||
InputFile { return INPUTFILE; }
|
||||
Label { return LABEL; }
|
||||
Left { return LEFT; }
|
||||
Limit { return LIMIT; }
|
||||
Menu { return MENU; }
|
||||
Ncurses { return NCURSES; }
|
||||
Next { return NEXT; }
|
||||
Object { return AN_OBJECT; }
|
||||
on { return ON; }
|
||||
OnEntry { return ONENTRY; }
|
||||
OnExit { return ONEXIT; }
|
||||
Options { return OPTIONS; }
|
||||
OutputFile { return OUTPUTFILE; }
|
||||
Right { return RIGHT; }
|
||||
Selected { return SELECTED; }
|
||||
Text { return TEXT; }
|
||||
Ttyname { return TTYNAME; }
|
||||
Type { return TYPE; }
|
||||
Up { return UP; }
|
||||
Use { return USE; }
|
||||
UserDrawFunc { return USERDRAWFUNC; }
|
||||
UserProcFunc { return USERPROCFUNC; }
|
||||
Version { return VERSION; }
|
||||
Width { return WIDTH; }
|
||||
Window { return WINDOW; }
|
||||
|
||||
Black { return BLACK; }
|
||||
Red { return RED; }
|
||||
Green { return GREEN; }
|
||||
Yellow { return YELLOW; }
|
||||
Blue { return BLUE; }
|
||||
Magenta { return MAGENTA; }
|
||||
Cyan { return CYAN; }
|
||||
White { return WHITE; }
|
||||
|
||||
, { return COMMA; }
|
||||
\{ { return LBRACE; }
|
||||
\} { return RBRACE; }
|
||||
[0-9]+ { yylval.ival = atoi(yytext); return NUMBER; }
|
||||
[A-Za-z_][A-Za-z0-9_()|&]* { yylval.sval = yytext; return NAME; }
|
||||
\"[^"]* {
|
||||
if (yytext[yyleng-1] == '\\') {
|
||||
yymore();
|
||||
} else {
|
||||
input();
|
||||
yylval.sval = yytext+1;
|
||||
; { return SEMICOLON; }
|
||||
|
||||
{NUM}+ { yylval.ival = atoi(yytext); return NUMBER; }
|
||||
|
||||
[A-Za-z_][A-Za-z0-9_.]* { yylval.sval = strdup(yytext);
|
||||
free(yytext);
|
||||
return NAME;
|
||||
}
|
||||
|
||||
\"[^"]+\" {
|
||||
yytext[strlen(yytext)-1] = '\0';
|
||||
yylval.sval = strdup(yytext + 1);
|
||||
free(yytext);
|
||||
return STRING;
|
||||
}
|
||||
}
|
||||
|
||||
\n { lineno++; }
|
||||
#.* { /* Ignored (comment) */; }
|
||||
[ \t\f]* { /* Ignored (white space) */; }
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user