diff options
author | paul <paul@FreeBSD.org> | 1995-05-12 17:20:06 +0000 |
---|---|---|
committer | paul <paul@FreeBSD.org> | 1995-05-12 17:20:06 +0000 |
commit | 65e32573aa7d24409456153f596c431cc62fd970 (patch) | |
tree | 6558dacc67a647a255afdab138d04182dc651b44 /lib | |
parent | 8c0e89af78b6c3f0d502b8ea4e44085b6c336102 (diff) | |
download | FreeBSD-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/Makefile | 6 | ||||
-rw-r--r-- | lib/libforms/examples/Makefile | 6 | ||||
-rw-r--r-- | lib/libforms/examples/example.c | 62 | ||||
-rw-r--r-- | lib/libforms/examples/example.frm | 192 | ||||
-rw-r--r-- | lib/libforms/forms.c | 400 | ||||
-rw-r--r-- | lib/libforms/forms.h | 208 | ||||
-rw-r--r-- | lib/libforms/internal.h | 91 | ||||
-rw-r--r-- | lib/libforms/lex.l | 113 | ||||
-rw-r--r-- | lib/libforms/parser.y | 935 |
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); } |