summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorpaul <paul@FreeBSD.org>1995-05-12 17:20:06 +0000
committerpaul <paul@FreeBSD.org>1995-05-12 17:20:06 +0000
commit65e32573aa7d24409456153f596c431cc62fd970 (patch)
tree6558dacc67a647a255afdab138d04182dc651b44 /lib
parent8c0e89af78b6c3f0d502b8ea4e44085b6c336102 (diff)
downloadFreeBSD-src-65e32573aa7d24409456153f596c431cc62fd970.zip
FreeBSD-src-65e32573aa7d24409456153f596c431cc62fd970.tar.gz
New libforms.
Bumped major number. Ncurses backend still needs improving. Other back-ends need to be written.
Diffstat (limited to 'lib')
-rw-r--r--lib/libforms/Makefile6
-rw-r--r--lib/libforms/examples/Makefile6
-rw-r--r--lib/libforms/examples/example.c62
-rw-r--r--lib/libforms/examples/example.frm192
-rw-r--r--lib/libforms/forms.c400
-rw-r--r--lib/libforms/forms.h208
-rw-r--r--lib/libforms/internal.h91
-rw-r--r--lib/libforms/lex.l113
-rw-r--r--lib/libforms/parser.y935
9 files changed, 1141 insertions, 872 deletions
diff --git a/lib/libforms/Makefile b/lib/libforms/Makefile
index 3703960..55e06c1 100644
--- a/lib/libforms/Makefile
+++ b/lib/libforms/Makefile
@@ -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
diff --git a/lib/libforms/examples/Makefile b/lib/libforms/examples/Makefile
index 4f0a23f..4389b70 100644
--- a/lib/libforms/examples/Makefile
+++ b/lib/libforms/examples/Makefile
@@ -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>
diff --git a/lib/libforms/examples/example.c b/lib/libforms/examples/example.c
index 39c4432..b08a4ea 100644
--- a/lib/libforms/examples/example.c
+++ b/lib/libforms/examples/example.c
@@ -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();
-
- 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");
+ bind_tuple(root_table, "User_Routine", TT_FUNC, &UserRoutine);
- 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");
+ start_object("adduser");
+}
- endwin();
+void
+UserRoutine(OBJECT *obj)
+{
+ /* Just draw a box and return */
+ exit (1);
}
diff --git a/lib/libforms/examples/example.frm b/lib/libforms/examples/example.frm
index 513ced2..eca43ab 100644
--- a/lib/libforms/examples/example.frm
+++ b/lib/libforms/examples/example.frm
@@ -1,54 +1,162 @@
-Colours example_colors {
- pair = red, yellow
- pair = blue, white
-}
-
-field1 { attributes = 0 text = "\standout This text is \bold bold and \blink flashy" }
+# An example form file for an adduser command
+!Forms Version name
-field2 {
- height = 2
- width = 22
- text = "This is an input fieldwith a default"
+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
+ }
}
-field3 {
- width = 10
- default = "This is a default entry"
- limit = 30
+template {
+ Width 15
+ Text "This is defined as a template and duplicated here"
}
-field4 { text = "This is a labelled input field" }
+Window adduser on screen1 at 0,0 {
+ Attributes "\screen"
-field5 { label = "A temp. label" }
+ window at 1,1 {
+ Height 22
+ Width 75
+ Attributes "\dialog"
+ Active username
-field6 { text = "Some options to choose from: " }
+ box {
+ Attributes "\dialog"
+ Highlight "\border"
+ CallFunc draw_box
+ shadow {
+ Attributes "\shadow"
+ CallFunc draw_shadow
+ }
+ }
-field7 { selected = 0 options = "Choose", "another", "of", "these" }
+ Title at 0,9 { Text " This is a title " }
-field8 { width = 6 action = "EXIT" function = exit_form }
+ username at 5,20 {
+ Height 1
+ Width 30
+ Attributes "\screen"
+ Highlight "\tag_selected"
-field9 {
-action = "CANCEL"
-function = cancel_form
-}
+ 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
+ }
-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
+ button at 15, 10 {
+ Up username Down username
+ Action User_Routine
+ Label "QUIT"
+ }
+ }
+ }
}
diff --git a/lib/libforms/forms.c b/lib/libforms/forms.c
index f5a81a8..575608f 100644
--- a/lib/libforms/forms.c
+++ b/lib/libforms/forms.c
@@ -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 *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 */
+hash_table *root_table, *cbind;
+OBJECT *cur_obj;
+int done;
+
+/* Default attribute commands */
+struct attr_cmnd attr_cmnds[] = {
+ {"box", ATTR_BOX },
+ {"center", ATTR_CENTER },
+ {"right", ATTR_RIGHT }
};
-int
-form_load(const char *filename)
-{
- FILE *fd;
+/* Internal bindings */
- global_bindings = hash_create(0);
+struct intbind {
+ char *key;
+ void *addr;
+};
- if (!global_bindings)
- return (FS_ERROR);
+struct intbind internal_bindings[] = {
+ {"draw_box", &draw_box},
+ {"draw_shadow", &draw_shadow}
+};
- if (!(fd = fopen(filename, "r"))) {
- warn("Couldn't open forms file %s", filename);
- return (FS_ERROR);
- }
+/* Bind the internal function addresses */
- yyin = fd;
- yyparse();
+void
+bind_internals(hash_table *table)
+{
+ int i;
- if (fclose(fd)) {
- warn("Couldn't close forms file %s", filename);
- return (FS_ERROR);
- }
+ 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");
+}
- hash_stats(global_bindings, 1);
+/*
+ * 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));
- return (FS_OK);
}
int
-find_editable(char *key, void *data, void *arg)
+load_objects(const char *filename)
{
- struct Tuple *tuple = (struct Tuple *)data;
- struct Field *field;
+ FILE *fd;
- if (tuple->type != FT_FIELD_INST)
- return (1);
+ root_table = hash_create(0);
+ if (!root_table)
+ errx(-1, "Failed to allocate root bindings table");
- field = (struct Field *)tuple->addr;
+ cbind = root_table;
- if ((field->type == FF_INPUT) ||
- (field->type == FF_MENU) ||
- (field->type == FF_ACTION)) {
- arg = field;
- return (0);
- } else
- return (1);
-}
+ bind_internals(root_table);
-struct Form *
-form_start(char *formname)
-{
- struct Tuple *tuple;
- struct Form *form;
- struct Field *field = 0;
- struct Field *start = 0;
-
- tuple = form_get_tuple(global_bindings, formname, FT_FORM);
-
- if (!tuple) {
- warnx("No such form");
- return (0);
+ if (!(fd = fopen(filename, "r"))) {
+ warn("Couldn't open file %s", filename);
+ return (ST_ERROR);
}
- form = tuple->addr;
-
- /* Initialise form */
- if (!form->height)
- form->height = LINES;
- if (!form->width)
- form->width = COLS;
+ yyin = fd;
+ yyparse();
- form->window = newwin(form->height, form->width, form->y, form->x);
- if (!form->window) {
- warnx("Couldn't open window, closing form");
- return (0);
+ if (fclose(fd)) {
+ warn("Couldn't close file %s", filename);
+ return (ST_ERROR);
}
- /* Initialise the field instances */
-
- hash_traverse(form->bindings, init_field, field);
+ return (ST_OK);
+}
- tuple = form_get_tuple(form->bindings, form->startfield, FT_FIELD_INST);
+int
+start_object(char *objname)
+{
+ TUPLE *tuple;
+ OBJECT *object;
- 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;
+ tuple = get_tuple(root_table, objname, TT_OBJ_INST);
+ if (!tuple)
+ return (ST_NOBIND);
- if (!form->current_field)
- errx(1, "No suitable start field found, aborting");
+ object = (OBJECT *)tuple->addr;
+ cur_obj = object;
- form->prev_field = form->current_field;
+ set_display(object->display);
- form->status = FS_RUNNING;
+ cur_obj->status |= O_VISIBLE;
- return (form);
+ while (!done) {
+ hash_traverse(root_table, &display_tuples, root_table);
+ hash_traverse(root_table, &refresh_displays, root_table);
+ process_object(cur_obj);
+ }
+ 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);
- }
+ tuple = tuple_search(obj, func, TT_FUNC);
+ if (!tuple)
+ return (0);
- return (0);
+ (*tuple->addr)(obj);
+ return (1);
}
-int
-tuple_match_any(char *key, struct Tuple *tuple, TupleType *type)
+set_display(DISPLAY *display)
{
- if (tuple->type != *type) {
- type = 0;
- return (1);
- } else {
- type = (TupleType *)tuple;
- return (0);
+ 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;
-
- /*
- * If a key is specified then search for that key,
- * otherwise, search the whole table for the first
- * tuple of the required type.
- */
-
- if (key)
- return(hash_search(htable, key, NULL, NULL));
- else {
- hash_traverse(htable, &tuple_match_any, arg);
- return (arg);
+ switch(obj->display->type) {
+ case DT_NCURSES:
+ ncurses_display_object(obj);
+ break;
+ default:
+ break;
}
}
-int
-show_field(char *key, void *data, void *arg)
+void
+process_object(OBJECT *obj)
{
- struct Tuple *tuple = (struct Tuple *)data;
- struct Field *field = (struct Field *)tuple->addr;
-
- display_field(arg, field);
+ TUPLE *tuple;
- return (1);
+ /* 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
-form_show(char *formname)
+refresh_displays(char *key, void *data, void *arg)
{
- struct Tuple *tuple;
- struct Form *form;
- int x, y;
-
- tuple = form_get_tuple(global_bindings, formname, FT_FORM);
- if (!tuple)
- return (FS_NOBIND);
-
- form = tuple->addr;
-
- /* 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, ' ');
+ TUPLE *tuple = (TUPLE *)data;
+ DISPLAY *display;
+
+ if (tuple->type == TT_DISPLAY)
+ display = (DISPLAY *)tuple->addr;
+ switch (display->type) {
+ case DT_NCURSES:
+ ncurses_refresh_display(display);
+ break;
+ default:
+ break;
+ }
- 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);
- }
+ return (1);
}
-#ifdef DEBUG_NOT_YET
-void
-debug_dump_bindings(hash_table *htable)
+int
+display_tuples(char *key, void *data, void *arg)
{
- struct Tuple *binds;
-
- 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);
+ TUPLE *tuple = (TUPLE *)data;
+ OBJECT *obj;
+ void (* fn)();
+
+ switch(tuple->type) {
+ case TT_OBJ_INST:
+ obj = (OBJECT *)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);
+
+ /* Display sub-objects */
+ if (obj->bind)
+ hash_traverse(obj->bind, &display_tuples, 0);
+ break;
+ default:
+ break;
}
+ return (1);
}
-void debug_dump_form(struct Form *form)
+AttrType
+parse_default_attributes(char *string)
{
- struct Field *field;
+ int i;
- field = form->fieldlist;
-
- for ( ; field; field = field->next) {
- printf("%s, %x, next = %x\n", field->defname, (int)field, (int)field->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);
}
-#endif
diff --git a/lib/libforms/forms.h b/lib/libforms/forms.h
index ae1c06d..ceac287 100644
--- a/lib/libforms/forms.h
+++ b/lib/libforms/forms.h
@@ -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;
-};
-
-struct help_link {
-};
+} MENU_OBJECT;
-struct Field {
- char *defname;
- char *enter;
- char *leave;
- int type;
+typedef struct TextObject {
+ char *text;
+} TEXT_OBJECT;
+
+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;
- */
-};
-
-/* Externally visible keymap table for user-definable keymaps */
-extern unsigned int keymap[];
-
-/* 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 *);
+ 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 variables */
+extern hash_table *root_table;
+
+/* 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_ */
diff --git a/lib/libforms/internal.h b/lib/libforms/internal.h
index f91b8395..ba38601 100644
--- a/lib/libforms/internal.h
+++ b/lib/libforms/internal.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 *);
+
+DISPLAY *default_open(DISPLAY *);
+DISPLAY *ncurses_open(DISPLAY *);
-#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
+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 *);
diff --git a/lib/libforms/lex.l b/lib/libforms/lex.l
index 24e2e38..7aa0351 100644
--- a/lib/libforms/lex.l
+++ b/lib/libforms/lex.l
@@ -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) */; }
+
diff --git a/lib/libforms/parser.y b/lib/libforms/parser.y
index 401e991..31093e9 100644
--- a/lib/libforms/parser.y
+++ b/lib/libforms/parser.y
@@ -37,73 +37,29 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <ncurses.h>
#include <forms.h>
#include <err.h>
#include "internal.h"
-char *cpstr(char *);
-
extern int yyleng;
int lineno = 1;
-int charno = 1;
-int off;
-
-char *fieldname;
-char *defname;
-char *formname;
-char *startname;
-char *colortable;
-int formattr;
-char *text;
-char *label;
-char *function;
-char *up, *down, *left, *right, *next;
-int height, width;
-int y, x;
-int width;
-int limit;
-int attr;
-int selattr;
-int type;
-int lbl_flag;
-int selected, no_options=0;
-
-extern FILE *outf;
-extern hash_table *global_bindings;
-
-struct MenuList {
- char *option;
- struct MenuList *next;
-};
-
-struct MenuList *cur_menu;
-struct MenuList *menu_list;
-struct MenuList *menu;
-
-struct pair_node {
- char *foreground;
- char *background;
- struct pair_node *next;
-};
-struct pair_node *pair_list;
-struct pair_node *cur_pair;
-struct pair_node *pair;
-
-struct color_table {
- char *tablename;
- struct pair_node *pairs;
- struct color_table *next;
-};
-
-struct color_table *color_table;
-struct color_table *cur_table;
-struct color_table *color_tables;
-
-struct Form *form;
-struct Field *field_inst_list;
-struct Field *field;
-struct Field *cur_field;
+
+OBJECT *parent;
+extern hash_table *cbind;
+
+
+/* Some variables for holding temporary values as we parse objects */
+
+OBJECT *object, *tmpobj;
+DISPLAY *display;
+
+int tmp, len;
+char *tmpstr, *objname, *dispname, *useobj;
+TUPLE *tmptuple;
+TupleType t_type;
+
%}
%union {
@@ -111,9 +67,49 @@ struct Field *cur_field;
char *sval;
}
-%token <ival> FORM
-%token <ival> COLORTABLE
-%token <ival> COLOR
+%token <ival> ACTION
+%token <ival> ACTIVE
+%token <ival> AS
+%token <ival> AT
+%token <ival> ATTR
+%token <ival> ATTRTABLE
+%token <ival> CALLFUNC
+%token <ival> COLORPAIRS
+%token <ival> DEFAULT
+%token <ival> A_DISPLAY
+%token <ival> DOWN
+%token <ival> FORMS
+%token <ival> FUNCTION
+%token <ival> HANDLER
+%token <ival> HEIGHT
+%token <ival> INPUT
+%token <ival> INPUTFILE
+%token <ival> LABEL
+%token <ival> LEFT
+%token <ival> LIMIT
+%token <ival> MENU
+%token <ival> NCURSES
+%token <ival> NEXT
+%token <ival> AN_OBJECT
+%token <ival> ON
+%token <ival> ONENTRY
+%token <ival> ONEXIT
+%token <ival> OPTIONS
+%token <ival> OUTPUTFILE
+%token <ival> RIGHT
+%token <ival> HIGHLIGHT
+%token <ival> SELECTED
+%token <ival> TEXT
+%token <ival> TTYNAME
+%token <ival> TYPE
+%token <ival> UP
+%token <ival> USE
+%token <ival> USERDRAWFUNC
+%token <ival> USERPROCFUNC
+%token <ival> VERSION
+%token <ival> WIDTH
+%token <ival> WINDOW
+
%token <ival> BLACK
%token <ival> RED
%token <ival> GREEN
@@ -122,308 +118,605 @@ struct Field *cur_field;
%token <ival> MAGENTA
%token <ival> CYAN
%token <ival> WHITE
-%token <ival> PAIR
-%token <sval> NAME
-%token <sval> STRING
-%token <ival> AT
-%token <ival> AS
-%token <ival> HEIGHT
-%token <ival> EQUALS
-%token <ival> NUMBER
-%token <ival> WIDTH
-%token <ival> STARTFIELD
+
%token <ival> COMMA
+%token <ival> SEMICOLON
%token <ival> LBRACE
%token <ival> RBRACE
-%token <ival> TEXT
-%token <ival> ATTR
-%token <ival> SELATTR
-%token <ival> DEFAULT
-%token <ival> LABEL
-%token <ival> LIMIT
-%token <ival> SELECTED
-%token <ival> OPTIONS
-%token <ival> ACTION
-%token <ival> FUNC
-%token <ival> LINK
-%token <ival> UP
-%token <ival> DOWN
-%token <ival> LEFT
-%token <ival> RIGHT
-%token <ival> NEXT
-%token <ival> DEF
-%type <sval> a_color
+%token <sval> NAME
+%token <ival> NUMBER
+%token <sval> STRING
+
+%type <ival> color
-%start spec
+%start forms
%%
+forms: FORMS VERSION NAME spec
+ {
+#ifdef DEBUG
+ printf("Forms language version %s\n", $3);
+#endif
+ }
+ ;
+
spec: /* empty */
- | spec fields
- | spec forms
- | spec colours
+ | spec display
+ | spec window
+ | spec object
;
-colours: COLOR NAME
+display: A_DISPLAY NAME
{
- color_table = malloc(sizeof (struct color_table));
- if (!color_table) {
- fprintf(stderr, "Couldn't allocate memory for a color table\n");
- exit (1);
- }
- color_table->tablename = cpstr($2);
+ dispname = $2;
+ display = malloc(sizeof (DISPLAY));
+ if (!display)
+ errx(-1,
+ "Failed to allocate memory for display (%d)", lineno);
+ }
+ LBRACE HEIGHT NUMBER
+ {
+ display->virt_height = $6;
}
- LBRACE color_pairs RBRACE
+ WIDTH NUMBER
{
- color_table->pairs = pair_list;
- cur_pair = 0;
- form_bind_tuple(global_bindings, color_table->tablename, FT_COLTAB, color_table);
+ display->virt_width = $9;
+ }
+ disp_type disp_attr_table RBRACE
+ {
+ if (!display)
+ errx(-1, "Failed to open display (%d)", lineno);
+ bind_tuple(root_table, dispname, TT_DISPLAY, (FUNCP)display);
+ dispname = 0;
}
;
-color_pairs: /* empty */
- | color_pairs pair
+disp_type: /* empty */
+ {
+ display->type = DT_ANY;
+ display->device = 0;
+ display = default_open(display);
+ }
+ | TYPE NCURSES device_ncurses
+ { display->type = DT_NCURSES; }
;
-pair: PAIR EQUALS a_color
+device_ncurses: /* empty */
{
- pair = malloc(sizeof (struct pair_node));
- if (!pair) {
- fprintf(stderr, "Couldn't allocate memory for a color pair\n");
- exit(1);
- }
- pair->foreground = cpstr($3);
+ /* Use ncurses drivers but on a default tty */
+ display->device.ncurses = 0;
+ display = ncurses_open(display);
}
- COMMA a_color
+ | LBRACE device_ncurses_tty
{
- pair->background = cpstr($6);
- if (!cur_pair) {
- pair_list = pair;
- cur_pair = pair;
- } else {
- cur_pair->next = pair;
- cur_pair = pair;
- }
+ display = ncurses_open(display);
+ }
+ device_ncurses_colors RBRACE
+ ;
+
+device_ncurses_tty: /* empty */
+ {
+ /* Use ncurses drivers but on a default tty */
+ display->device.ncurses = 0;
+ }
+ | TTYNAME STRING INPUTFILE STRING OUTPUTFILE STRING
+ {
+ display->device.ncurses = (NCURSDEV *)malloc(sizeof (NCURSDEV));
+ if (!display->device.ncurses)
+ errx(-1, "Failed to allocate memory for ncurses device (%d)", lineno);
+ display->device.ncurses->ttyname = $2;
+ display->device.ncurses->input = $4;
+ display->device.ncurses->output = $6;
}
;
-a_color: BLACK
- { $$ = "COLOR_BLACK"; }
+device_ncurses_colors: /* empty */
+ | COLORPAIRS LBRACE color_pairs RBRACE
+ ;
+
+color_pairs: /* empty */
+ | color_pairs color_pair
+ ;
+
+color_pair: NUMBER color color
+ {
+ if (display)
+ init_pair($1, $2, $3);
+ }
+ ;
+
+color: BLACK
+ { $$ = COLOR_BLACK; }
| RED
- { $$ = "COLOR_RED"; }
- | GREEN
- { $$ = "COLOR_GREEN"; }
+ { $$ = COLOR_RED; }
+ | GREEN
+ { $$ = COLOR_GREEN; }
| YELLOW
- { $$ = "COLOR_YELLOW"; }
+ { $$ = COLOR_YELLOW; }
| BLUE
- { $$ = "COLOR_BLUE"; }
+ { $$ = COLOR_BLUE; }
| MAGENTA
- { $$ = "COLOR_MAGENTA"; }
+ { $$ = COLOR_MAGENTA; }
| CYAN
- { $$ = "COLOR_CYAN"; }
+ { $$ = COLOR_CYAN; }
| WHITE
- { $$ = "COLOR_WHITE"; }
+ { $$ = COLOR_WHITE; }
+ ;
+
+disp_attr_table: /* empty */
+ { display->bind = 0; }
+ | ATTRTABLE
+ {
+ display->bind = hash_create(0);
+ if (!display->bind)
+ errx(-1, "Failed to allocate memory for display bindings (%d)", lineno);
+ }
+ LBRACE disp_attrs RBRACE
;
-forms: FORM NAME
- { formname = cpstr($2); }
- AT coord
+disp_attrs: /* empty */
+ | disp_attrs disp_attr
+ ;
+
+disp_attr: NAME NUMBER
+ { bind_tuple(display->bind, $1, TT_ATTR, (FUNCP)$2); }
+ ;
+
+window: WINDOW NAME ON NAME AT NUMBER COMMA NUMBER LBRACE
+ {
+ objname = $2;
+ dispname = $4;
+ object = malloc(sizeof (OBJECT));
+ if (!object)
+ errx(-1, "Failed to allocate memory for window (%d)", lineno);
+
+ object->y = $6;
+ object->x = $8;
+ object->status = O_VISIBLE;
+ object->bind = hash_create(0);
+ if (!object->bind)
+ errx(-1, "Failed to allocate memory for window's bindings (%d)", lineno);
+ }
+ object_params
{
- form = malloc(sizeof (struct Form));
- if (!form) {
- fprintf(stderr,"Failed to allocate memory for form\n");
- exit(1);
+ tmptuple = tuple_search(object, dispname, TT_DISPLAY);
+ if (!tmptuple)
+ errx(-1, "Couldn't find binding for display (%d)", lineno);
+ free(dispname);
+ object->display = (struct Display *)tmptuple->addr;
+
+ switch (object->display->type) {
+ case DT_NCURSES:
+ default:
+ object->window.ncurses = malloc(sizeof (NCURSES_WINDOW));
+ if (!object->window.ncurses)
+ errx(-1, "Failed to allocate memory for ncurses window, (%d)", lineno);
+ ncurses_open_window(object);
+ break;
}
- form->bindings = hash_create(0);
- if (!form->bindings)
- errx(1, "Failed to allocate hash table for form");
- form->y = y;
- form->x = x;
+ object->parent = 0;
+ if (!object->height)
+ object->height = display->height;
+ if (!object->width)
+ object->width = display->width;
+ bind_tuple(root_table, objname, TT_OBJ_INST, (FUNCP)object);
+ parent = object;
+ cbind = parent->bind;
}
- LBRACE formspec RBRACE
+ object RBRACE
{
- form->startfield = startname;
- form->colortable = colortable;
- form->height = height;
- form->width = width;
- form->attr = formattr;
- form_bind_tuple(global_bindings, formname, FT_FORM, form);
+ parent = 0;
+ cbind = root_table;
}
;
-formspec: height width startfield colortable formattr fieldlocs
+objects: /* empty */
+ | objects object
;
-startfield: /* empty */
- { startname = 0;
- printf("Warning: No start field specified for form %s\n", formname);
+object: NAME
+ {
+ objname = $1;
+ object = malloc(sizeof (OBJECT));
+ if (!object)
+ errx(-1, "Failed to allocate memory for object (%d)", lineno);
+
+ object->bind = hash_create(0);
+ if (!object->bind)
+ errx(-1, "Failed to allocate memory for ",
+ "object's bindings (%d)", lineno);
+ }
+ at LBRACE use_copy
+ {
+ if (useobj) {
+ /* Need to declare parent to see previous scope levels */
+ object->parent = parent;
+ if (use_defined_object(object, useobj) == ST_NOBIND)
+ errx(-1, "Object, %s, not found in scope (%d)",
+ useobj, lineno);
+ }
+ }
+ object_params
+ {
+ /*
+ * If this is a function object convert it from
+ * a definition to an instance (see 'at' below).
+ */
+ if (object->type == OT_FUNCTION)
+ t_type = TT_OBJ_INST;
+
+ /*
+ * If this is an instance object and it doesn't
+ * have a parent then there's a syntax error since
+ * instances can only be specified inside windows.
+ */
+ if (parent)
+ inherit_properties(object, parent);
+ else if (t_type != TT_OBJ_DEF)
+ errx(-1, "Object, %s, has no parent (%d)", objname, lineno);
+
+ /* Propagate defobj up through nested compounds */
+ if (t_type == TT_OBJ_INST &&
+ parent && parent->type == OT_COMPOUND &&
+ !parent->object.compound->defobj)
+ parent->object.compound->defobj =
+ strdup(objname);
+
+ /* Add object and go down to next object */
+ bind_tuple(cbind, objname, t_type, (FUNCP)object);
+ parent = object;
+ cbind = object->bind;
+ }
+ objects RBRACE
+ {
+ parent = object->parent;
+ if (parent)
+ cbind = parent->bind;
+ else
+ cbind = root_table;
+ object = parent;
}
- | STARTFIELD EQUALS NAME
- { startname = cpstr($3); }
;
-colortable: /*empty */
- { colortable = 0; }
- | COLORTABLE EQUALS NAME
- { colortable = cpstr($3); }
+at: /* empty */
+ {
+ /*
+ * If there's no 'at' part specified then this is
+ * either a definition rather than an instance of
+ * an object or it's a function. Set it to a definition,
+ * we deal with the function case above.
+ */
+ t_type = TT_OBJ_DEF;
+ object->y = 0;
+ object->x = 0;
+ }
+ | AT NUMBER COMMA NUMBER
+ {
+ t_type = TT_OBJ_INST;
+ object->y = $2;
+ object->x = $4;
+ }
;
-formattr: /* empty */
- { formattr = 0; }
- | ATTR EQUALS NUMBER
- { formattr = $3; }
+use_copy: /* empty */
+ { useobj = 0; }
+ | USE NAME
+ { useobj = $2; }
;
-fieldlocs: /* empty */
- | fieldlocs field_at
+object_params: user_draw_func user_proc_func height width attributes highlight on_entry on_exit links object_type
;
-field_at: NAME
- { fieldname = cpstr($1); }
- field_def AT coord
- {
- field = malloc(sizeof (struct Field));
- if (!field) {
- fprintf(stderr,"Failed to allocate memory for form field\n");
- exit(1);
- }
- if (!defname)
- field->defname = fieldname;
- else
- field->defname = defname;
- field->y = y;
- field->x = x;
- }
- links
+object_type: /* empty */
{
- field->fup = up;
- field->fdown = down;
- field->fleft = left;
- field->fright = right;
- field->fnext = next;
- up = 0;
- down = 0;
- left = 0;
- right = 0;
- next = 0;
- form_bind_tuple(form->bindings, fieldname, FT_FIELD_INST, field);
+ /* If we haven't inherited a type assume it's a compound */
+ if (!object->type) {
+ object->type = OT_COMPOUND;
+ object->object.compound = malloc(sizeof (COMPOUND_OBJECT));
+ if (!object->object.compound)
+ errx(-1, "Failed to allocate memory for object, (%d)\n",
+ lineno);
+ object->object.compound->defobj = 0;
+ }
}
+ | object_action
+ | object_compound
+ | object_function
+ | object_input
+ | object_menu
+ | object_text
;
-fields: NAME
- { defname = cpstr($1); }
- field_spec
- { define_field(defname); }
+links: /* empty */
+ | links conns
;
-field_def: /* empty */
- { defname = 0; }
- | LBRACE NAME
- { defname = cpstr($2); }
- RBRACE
- | field_spec
- { defname = fieldname; define_field(defname); }
+conns: UP NAME
+ {
+ if (object->lup)
+ free(object->lup);
+ object->lup = $2;
+ }
+ | DOWN NAME
+ {
+ if (object->ldown)
+ free(object->ldown);
+ object->ldown = $2;
+ }
+ | LEFT NAME
+ {
+ if (object->lleft)
+ free(object->lleft);
+ object->lleft = $2;
+ }
+ | RIGHT NAME
+ {
+ if (object->lright)
+ free(object->lright);
+ object->lright = $2;
+ }
+ | NEXT NAME
+ {
+ if (object->lnext)
+ free(object->lnext);
+ object->lnext = $2;
+ }
;
-field_spec: LBRACE height width attr selattr type RBRACE
- ;
+/*
+ * Parse the action object type.
+ */
-links: /* empty */
- | links COMMA conns
+object_action: ACTION NAME LABEL STRING
+ {
+ object->type = OT_ACTION;
+ object->object.action = malloc(sizeof (ACTION_OBJECT));
+ if (!object->object.action)
+ errx(-1, "Failed to allocate memory for object, (%d)\n", lineno);
+ object->object.action->action = $2;
+ object->object.action->text = $4;
+ if (!object->width)
+ object->width = calc_string_width(object->object.text->text);
+ if (!object->height)
+ calc_object_height(object, object->object.text->text);
+ }
;
-conns: UP EQUALS NAME
- { up = cpstr($3); }
- | DOWN EQUALS NAME
- { down = cpstr($3); }
- | LEFT EQUALS NAME
- { left = cpstr($3); }
- | RIGHT EQUALS NAME
- { right = cpstr($3); }
- | NEXT EQUALS NAME
- { next = cpstr($3); }
- ;
+/*
+ * Parse the compound object type.
+ */
-type: textfield
- | inputfield
- | menufield
- | actionfield
+object_compound: ACTIVE NAME
+ {
+ object->type = OT_COMPOUND;
+ object->object.compound = malloc(sizeof (COMPOUND_OBJECT));
+ if (!object->object.compound)
+ errx(-1, "Failed to allocate memory for object, (%d)\n", lineno);
+ object->object.compound->defobj = $2;
+ }
;
-textfield: TEXT EQUALS STRING
- { type = FF_TEXT; text = cpstr($3); }
+/*
+ * Parse the function object type
+ */
+
+object_function: CALLFUNC NAME
+ {
+ object->type = OT_FUNCTION;
+ object->object.function = malloc(sizeof (FUNCTION_OBJECT));
+ if (!object->object.function)
+ errx(-1, "Failed to allocate memory for object (%d)", lineno);
+ object->object.function->fn = $2;
+ }
;
-inputfield: inputspec
- { type = FF_INPUT; }
+/*
+ * Parse the input object type
+ */
+
+object_input: INPUT
+ {
+ object->type = OT_INPUT;
+ object->object.input = malloc(sizeof (INPUT_OBJECT));
+ if (!object->object.input)
+ errx(-1, "Failed to allocate memory for object (%d)", lineno);
+ }
+ input_params limit
+ {
+ /* Force height to 1 regardless */
+ object->height = 1;
+ if (!object->width && !object->object.input->limit) {
+ if (!object->object.input->label)
+ errx(-1, "Unable to determine size of input object (%d)",
+ lineno);
+ object->width = calc_string_width(object->object.input->label);
+ object->object.input->limit = object->width;
+ } else if (!object->width)
+ object->width = object->object.input->limit;
+ else if (!object->object.input->limit)
+ object->object.input->limit = object->width;
+ if (object->object.input->limit < object->width)
+ object->width = object->object.input->limit;
+
+ object->object.input->input =
+ malloc(object->object.input->limit + 1);
+ if (!object->object.input->input)
+ errx(-1, "Failed to allocate memory for object (%d)", lineno);
+
+ /*
+ * If it's a label then clear the input string
+ * otherwise copy the default there.
+ */
+
+ if (object->object.input->lbl_flag)
+ object->object.input->input[0] = '\0';
+ else if (object->object.input->label) {
+ tmp = strlen(object->object.input->label);
+ strncpy(object->object.input->input,
+ object->object.input->label,
+ tmp);
+ object->object.input->input[tmp] = 0;
+ }
+ }
;
-inputspec: LABEL EQUALS STRING limit
- { lbl_flag = 1; label = cpstr($3); }
- | DEFAULT EQUALS STRING limit
- { lbl_flag = 0; label = cpstr($3); }
+input_params: /* empty */
+ {
+ object->object.input->lbl_flag = 0;
+ object->object.input->label = 0;
+ }
+ | STRING
+ {
+ object->object.input->lbl_flag = 0;
+ object->object.input->label = $1;
+ }
+ | DEFAULT STRING
+ {
+ object->object.input->lbl_flag = 0;
+ object->object.input->label = $2;
+ }
+ | LABEL STRING
+ {
+ object->object.input->lbl_flag = 1;
+ object->object.input->label = $2;
+ }
;
limit: /* empty */
- | LIMIT EQUALS NUMBER
- { limit = $3; }
+ { object->object.input->limit = 0; }
+ | LIMIT NUMBER
+ { object->object.input->limit = $2; }
+ ;
-menufield: SELECTED EQUALS NUMBER OPTIONS EQUALS menuoptions
- { type = FF_MENU; selected = $3; }
+/*
+ * Parse the menu object type
+ */
+
+object_menu: OPTIONS LBRACE
+ {
+ object->type = OT_MENU;
+ object->object.menu = malloc(sizeof (MENU_OBJECT));
+ if (!object->object.menu)
+ errx(-1, "Failed to allocate memory for object (%d)", lineno);
+ object->object.menu->no_options = 0;
+ object->object.menu->options = 0;
+ len = 0;
+ }
+ menuoptions
+ {
+ object->height = 1;
+ if (!object->width)
+ object->width = len;
+ }
+ RBRACE option_selected
;
menuoptions: menuoption
- | menuoptions COMMA menuoption
+ | menuoptions menuoption
;
menuoption: STRING
- {
- menu = malloc(sizeof(struct MenuList));
- if (!menu) {
- err(1, "Couldn't allocate memory for menu option\n");
- }
- menu->option = cpstr($1);
- if (!cur_menu) {
- menu_list = menu;
- cur_menu = menu;
- } else {
- cur_menu->next = menu;
- cur_menu = menu;
- }
+ {
+ tmpstr = $1;
+ object->object.menu->no_options =
+ add_menu_option(object->object.menu, tmpstr);
+ if (!object->object.menu->no_options)
+ errx(-1, "Failed to allocate memory for option (%d)", lineno);
+ tmp = calc_string_width(tmpstr);
+ if (tmp > len)
+ len = tmp;
+ free(tmpstr);
}
-;
+ ;
+
+option_selected: /* empty */
+ { object->object.menu->selected = 0; }
+ | SELECTED NUMBER
+ { object->object.menu->selected = $2; }
+ ;
+
+/*
+ * Parse the text object type
+ */
+
+object_text: TEXT STRING
+ {
+ object->type = OT_TEXT;
+ object->object.text = malloc(sizeof (TEXT_OBJECT));
+ if (!object->object.text)
+ errx(-1, "Failed to allocate memory for object (%d)", lineno);
+ object->object.text->text = $2;
+ if (!object->width)
+ object->width = calc_string_width(object->object.text->text);
+ if (!object->height)
+ calc_object_height(object, object->object.text->text);
+ }
+ ;
+
+user_draw_func: /* empty */
+ | USERDRAWFUNC NAME
+ {
+ if (object->UserDrawFunc)
+ free(object->UserDrawFunc);
+ object->UserDrawFunc = $2;
+ }
+ ;
-actionfield: ACTION EQUALS STRING FUNC EQUALS NAME
- { type = FF_ACTION; text = cpstr($3); function = cpstr($6); }
+user_proc_func: /* empty */
+ | USERPROCFUNC NAME
+ {
+ if (object->UserProcFunc)
+ free(object->UserProcFunc);
+ object->UserProcFunc = $2;
+ }
;
height: /* empty */
- { height = 0; }
- | HEIGHT EQUALS NUMBER
- { height = $3; }
+ | HEIGHT NUMBER
+ { object->height = $2; }
;
width: /* empty */
- { width = 0; }
- | WIDTH EQUALS NUMBER
- { width = $3; }
+ | WIDTH NUMBER
+ { object->width = $2; }
;
-attr: /* empty */
- { attr = 0; }
- | ATTR EQUALS NUMBER
- { attr = $3; }
+attributes: /* empty */
+ | ATTR STRING
+ {
+ if (object->attributes)
+ free(object->attributes);
+ object->attributes = $2;
+ }
;
-selattr: /* empty */
- { selattr = 0; }
- | SELATTR EQUALS NUMBER
- { selattr = $3; }
+highlight: /* empty */
+ | HIGHLIGHT STRING
+ {
+ if (object->highlight)
+ free(object->highlight);
+ object->highlight = $2;
+ }
+ ;
+
+on_entry: /* empty */
+ | ONENTRY NAME
+ {
+ if (object->OnEntry)
+ free(object->OnEntry);
+ object->OnEntry = $2;
+ }
;
-coord: NUMBER COMMA NUMBER
- { y = $1; x = $3; }
+on_exit: /* empty */
+ | ONEXIT NAME
+ {
+ if (object->OnExit)
+ free(object->OnExit);
+ object->OnExit = $2;
+ }
;
%%
@@ -431,101 +724,5 @@ coord: NUMBER COMMA NUMBER
void
yyerror (char *error)
{
- fprintf(stderr, "%s at line %d\n",error, lineno);
- exit(1);
-}
-
-char *
-cpstr(char *ostr)
-{
- char *nstr;
-
- nstr = malloc(strlen(ostr)+1);
- if (!nstr) {
- fprintf(stderr, "Couldn't allocate memory for string\n");
- exit(1);
- }
- strcpy(nstr, ostr);
- return (nstr);
-}
-
-void
-define_field(char *defname)
-{
- struct Field *field;
- struct MenuList *menu_options;
- int no_options;
-
- field = malloc(sizeof (struct Field));
- if (!field) {
- fprintf(stderr,"Failed to allocate memory for form field\n");
- exit(1);
- }
- field->defname = defname;
- field->type = type;
- field->height = height;
- field->width = width;
- field->attr = attr;
- field->selattr = selattr;
- switch (type) {
- case FF_TEXT:
- field->field.text = malloc(sizeof (struct TextField));
- if (!field->field.text) {
- fprintf(stderr,
- "Failed to allocate memory for text field\n");
- exit (1);
- }
- field->field.text->text = text;
- break;
- case FF_INPUT:
- field->field.input = malloc(sizeof (struct InputField));
- if (!field->field.input) {
- fprintf(stderr,
- "Failed to allocate memory for input field\n");
- exit (1);
- }
- field->field.input->lbl_flag = lbl_flag;
- field->field.input->label = label;
- field->field.input->limit = limit;
- break;
- case FF_MENU:
- printf("field type %s = %d\n", defname,field->type);
- field->field.menu = malloc(sizeof (struct MenuField));
- if (!field->field.menu) {
- fprintf(stderr,
- "Failed to allocate memory for menu field\n");
- exit (1);
- }
- field->field.menu->selected = selected;
- menu_options = menu_list;
- field->field.menu->no_options = 0;
- field->field.menu->options = 0;
- for (; menu_options; menu_options = menu_options->next) {
- no_options = add_menu_option(field->field.menu,
- menu_options->option);
- if (!no_options)
- err(1, "Couldn't add menu option");
- }
- field->field.menu->no_options = no_options;
- cur_menu = 0;
- break;
- case FF_ACTION:
- field->field.action = malloc(sizeof (struct ActionField));
- if (!field->field.action) {
- fprintf(stderr,
- "Failed to allocate memory for action field\n");
- exit (1);
- }
- field->field.action->text = text;
- field->field.action->fn = (void *) function;
- break;
- default:
- break;
- }
- form_bind_tuple(global_bindings, defname, FT_FIELD_DEF, field);
- width=0;
- height = 0;
- attr=0;
- selattr=0;
- limit=0;
+ errx(-1, "%s at line %d\n", error, lineno);
}
OpenPOWER on IntegriCloud