Completely rewrite libforms so everything is done at runtime rather

than at compile time.

Should have same functionality as old libforms but with new mechanism.

Lots of new features that use the new mechanism are still to be added.
This commit is contained in:
Paul Richards 1995-03-01 08:19:06 +00:00
parent 1214e6da66
commit be7d950dc8
17 changed files with 4882 additions and 502 deletions

View file

@ -1,8 +1,9 @@
LIB = forms
SRCS = forms.c
SRCS = forms.c parser.y lex.l menu.c fields.c
CFLAGS += -I. -I${.CURDIR} -Wall -g
LDFLAGS += -ll
beforeinstall:
@(cd ${.CURDIR}; cmp -s forms.h ${DESTDIR}/usr/include/forms.h || \

View file

@ -0,0 +1,12 @@
LIB = forms
SRCS = forms.c
CFLAGS += -I. -I${.CURDIR} -Wall -g
beforeinstall:
@(cd ${.CURDIR}; cmp -s forms.h ${DESTDIR}/usr/include/forms.h || \
install -c -o ${BINOWN} -g ${BINGRP} -m 444 forms.h \
${DESTDIR}/usr/include/forms.h;)
.include <bsd.lib.mk>

View file

@ -1,7 +1,7 @@
PROG = example
NOMAN = yet
SRCS = example.c frm.tab.h
SRCS = example.c
CFLAGS = -g -static
@ -11,11 +11,7 @@ FORMDIR=${.CURDIR}/../obj
FORMDIR=${.CURDIR}/..
.endif
LDADD = -L${FORMDIR} -lforms -lncurses -lmytinfo
CLEANFILES += frm.tab.h
frm.tab.h:
fib example.frm
LDADD = -L${FORMDIR} -lforms -lncurses -lmytinfo -ll
DPADD = /usr/lib/libforms.a
.include <bsd.prog.mk>

View file

@ -1,4 +1,4 @@
/*-
/*
* Copyright (c) 1995
* Paul Richards. All rights reserved.
*
@ -33,36 +33,62 @@
*/
#include <stdio.h>
#include "../forms.h"
#include "frm.tab.h"
main()
{
struct Tuple *tuple;
struct Form *form;
int res;
initscr();
initfrm(&example);
if (!example.window) {
fprintf(stderr, "\nUnable to initialize forms library.\n");
endwin();
exit(1);
form_bind_tuple("exit_form", FT_FUNC, &exit_form);
form_bind_tuple("cancel_form", FT_FUNC, &cancel_form);
if (form_load("example.frm") == FS_ERROR)
exit(0);;
form = form_start("example");
if (!form) {
err(-1, "No form returned");
exit(0);
}
keypad(example.window, TRUE);
keypad(form->window, TRUE);
cbreak();
noecho();
tuple = form_get_tuple("example", FT_FORM);
if (!tuple)
err(0, "No such form");
else
form = (struct Form *)tuple->addr;
print_status("This is the status line");
while (!(res = update_form(&example)));
wclear(example.window);
wrefresh(example.window);
res = form_show("example");
if (res == F_DONE) {
while (form->status == FS_RUNNING) {
do_field(form);
wrefresh(form->window);
}
wclear(form->window);
wrefresh(form->window);
if (form->status == FS_EXIT) {
printf("You're entries were:\n\n");
printf("%s\n",input1.input);
printf("%s\n",input2.input);
printf("%s\n",menu1.options[example_fields[7].field.menu->selected]);
} else if (res == F_CANCEL)
tuple = form_get_tuple("input1", FT_FIELD_INST);
printf("Input 1 = %s\n", ((struct Field *)tuple->addr)->field.input->input);
tuple = form_get_tuple("input2", FT_FIELD_INST);
printf("Input 2 = %s\n", ((struct Field *)tuple->addr)->field.input->input);
tuple = form_get_tuple("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");
endfrm(&example);
endwin();
}

View file

@ -1,9 +1,4 @@
Colours example {
pair = red, yellow
pair = blue, white
}
field1 { attributes = A_BLINK|A_BOLD text = "This text is bold and flashy" }
field1 { attributes = 0 text = "This text is bold and flashy" }
field2 {
height = 2
@ -28,28 +23,27 @@ field7 { selected = 0 options = "Choose", "another", "of", "these" }
field8 { width = 6 action = "EXIT" function = exit_form }
field9 {
attributes = COLOR_PAIR(1)
highlight = COLOR_PAIR(1)|A_BOLD
action = "CANCEL"
function = cancel_form
action = "CANCEL"
function = cancel_form
}
Form example at 0,0 {
height = 25
width = 80
start = input1
colortable = example
attributes = COLOR_PAIR(1)
attributes = 0
Title {attributes = COLOR_PAIR(2) text = "A Simple Demo"} at 0,30
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, up=input2, down=input2
input2 {field5} at 11,45, next=menu1, up=input1, down=menu1
menu1 {field7} at 15,45, next=quit, up=input2, down=quit
quit {field8} at 20,20, up=menu1, right=cancel
cancel {field9} at 20,43, up=input1, down=input1, left=quit, right=input1
input1 {field3} at 7,45, next=input2
input2 {field5} at 11,45, next=menu1
menu1 {field7} at 15,45, next=quit
quit {field8} at 20,20, up = menu1, right = cancel
cancel {field9} at 20,43, next=input1
}

520
lib/libforms/fields.c Normal file
View file

@ -0,0 +1,520 @@
/*-
* Copyright (c) 1995
* Paul Richards. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* verbatim and that no modifications are made prior to this
* point in the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Paul Richards.
* 4. The name Paul Richards may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <ctype.h>
#include <err.h>
#include <ncurses.h>
#include <forms.h>
#include <string.h>
#include <stdlib.h>
#include "internal.h"
int done=0;
int
init_field(struct Field *field)
{
struct Tuple *tuple;
struct Field *def;
int i;
int len, lim;
tuple = form_get_tuple(field->defname, FT_FIELD_DEF);
if (!tuple) {
warnx("Field definition not found -- skipping field");
return (-1);
}
def = (struct Field *)tuple->addr;
field->height = def->height;
field->width = def->width;
field->attr = def->attr;
field->selattr = def->selattr;
field->type = def->type;
switch (field->type) {
case FF_INPUT:
field->field.input = malloc(sizeof (struct InputField));
if (!field->field.input) {
warnx("Couldn't allocate memory for input field");
return (-1);
}
field->field.input->limit = def->field.input->limit;
/* Force height to one regardless, at least for now :-) */
field->height = 1;
if (!field->width && !field->field.input->limit) {
field->width = strlen(def->field.input->label);
field->field.input->limit = field->width;
} else if (!field->width)
field->width = field->field.input->limit;
else if (!field->field.input->limit)
field->field.input->limit = field->width;
if (field->field.input->limit < field->width)
field->width = field->field.input->limit;
field->field.input->input = malloc(field->field.input->limit + 1);
if (!field->field.input->input) {
warnx("Couldn't allocate memory for input field text");
return (-1);
}
field->field.input->label = malloc(strlen(def->field.input->label)+1);
if (!field->field.input->label) {
warnx("Couldn't allocate memory for input field label");
return (-1);
}
strncpy(field->field.input->label,
def->field.input->label,
strlen(def->field.input->label) + 1);
field->field.input->lbl_flag = def->field.input->lbl_flag;
/*
* If it's a label then clear the input string
* otherwise copy the default there.
*/
if (field->field.input->lbl_flag)
field->field.input->input[0] = '\0';
else if (field->field.input->label) {
strncpy(field->field.input->input,
field->field.input->label,
field->field.input->limit);
field->field.input->input[field->field.input->limit] = 0;
}
break;
case FF_TEXT:
field->field.text = malloc(sizeof (struct TextField));
if (!field->field.text) {
warnx("Couldn't allocate memory for text field");
return (FS_ERROR);
}
if (!field->width)
field->width = strlen(def->field.text->text);
field->field.text->text = malloc(field->width + 1);
if (!field->field.text->text) {
warnx("Couldn't allocate memory for text field text");
return (FS_ERROR);
} else
strncpy(field->field.text->text,
def->field.text->text,
field->width + 1);
if (!field->height)
calc_field_height(field, field->field.text->text);
break;
case FF_MENU:
field->field.menu = malloc(sizeof (struct MenuField));
if (!field->field.menu) {
warnx("Couldn't allocate memory for menu field");
return (FS_ERROR);
}
field->field.menu->no_options = 0;
field->height = 1;
lim = 0;
for (i=0; i < def->field.menu->no_options; i++) {
field->field.menu->no_options =
add_menu_option(field->field.menu,
def->field.menu->options[i]);
if (!field->field.menu->no_options) {
warnx("Couldn't add menu option");
return (FS_ERROR);
}
len = strlen(def->field.menu->options[i]);
if (len > lim)
lim = len;
}
if (!field->width)
field->width = lim;
break;
case FF_ACTION:
field->field.action = malloc(sizeof (struct ActionField));
if (!field->field.action) {
warnx("Couldn't allocate memory for action field");
return (FS_ERROR);
}
if (!field->width)
field->width = strlen(def->field.action->text);
field->field.action->text = malloc(field->width + 1);
if (!field->field.action->text) {
warnx("Couldn't allocate memory for text field text");
return (FS_ERROR);
} else
strncpy(field->field.action->text,
def->field.action->text,
field->width + 1);
if (!field->height)
calc_field_height(field, field->field.action->text);
field->field.action->fn = def->field.action->fn;
break;
default:
break;
}
return (0);
}
void
display_field(WINDOW *window, struct Field *field)
{
wattrset(window, field->attr);
wmove(window, field->y, field->x);
switch (field->type) {
case FF_TEXT:
display_text(window, field);
break;
case FF_MENU:
display_menu(window, field);
break;
case FF_INPUT:
display_input(window, field);
break;
case FF_ACTION:
display_action(window, field);
break;
case FF_UNKNOWN:
default:
break;
}
wattrset(window, 0);
wrefresh(window);
}
void
display_text(WINDOW *window, struct Field *field)
{
if (print_string(window, field->y, field->x, field->height,
field->width, field->field.text->text) == ERR)
print_status("Illegal scroll in print_string");
}
void
display_input(WINDOW *window, struct Field *field)
{
if (field->field.input->lbl_flag) {
if (print_string(window, field->y, field->x, field->height,
field->width, field->field.input->label) == ERR)
print_status("Illegal scroll in print_string");
} else
if (print_string(window, field->y, field->x, field->height,
field->width, field->field.input->input) == ERR)
print_status("Illegal scroll in print_string");
}
void
display_menu(WINDOW *window, struct Field *field)
{
if (print_string(window, field->y, field->x,
field->height, field->width,
field->field.menu->options[field->field.menu->selected]) == ERR)
print_status("Illegal scroll in print_string");
}
void
display_action(WINDOW *window, struct Field *field)
{
if (print_string(window, field->y, field->x, field->height,
field->width,
field->field.action->text) == ERR)
print_status("Illegal scroll in print_string");
}
int
do_action(struct Form *form)
{
struct Field *field = form->current_field;
struct Tuple *tuple;
int ch;
void (* fn)();
display_action(form->window, field);
wmove(form->window, field->y, field->x);
for (;;) {
ch = wgetch(form->window);
if (ch == FK_ACCEPT) {
tuple = form_get_tuple(field->field.action->fn, FT_FUNC);
if (!tuple) {
print_status("No function bound to action");
beep();
continue;
} else {
fn = tuple->addr;
(*fn)(form);
return (FS_OK);
}
} else
ch = do_key_bind(form, ch);
if (ch == FS_OK)
return (FS_OK);
else if (ch == FS_ERROR)
continue;
}
}
int
do_menu(struct Form *form)
{
struct Field *field = form->current_field;
int ch;
for (;;) {
display_menu(form->window, field);
wmove(form->window, field->y, field->x);
ch = wgetch(form->window);
switch (ch) {
case ' ':
print_status("");
field->field.menu->selected++;
if (field->field.menu->selected >= field->field.menu->no_options)
field->field.menu->selected = 0;
break;
default:
ch = do_key_bind(form, ch);
break;
}
if (ch == FS_OK)
return (FS_OK);
else if (ch == FS_ERROR) {
beep();
continue;
} else {
print_status("Hit the space bar to toggle through options");
beep();
continue;
}
}
}
int
do_field(struct Form *form)
{
struct Field *field = form->current_field;
int status;
switch (field->type) {
case FF_TEXT:
status = FS_OK;
display_text(form->window, field);
break;
case FF_INPUT:
status = do_input(form);
break;
case FF_MENU:
status = do_menu(form);
break;
case FF_ACTION:
status = do_action(form);
break;
default:
status = FF_UNKNOWN;
beep();
print_status("Unknown field type");
form->current_field = form->prev_field;
break;
}
return (status);
}
int
print_string(WINDOW *window, int y, int x,
int height, int fwidth, char *string)
{
int len;
int width;
if (!string)
len = -1;
len = strlen(string);
if (wmove(window, y, x) == ERR)
return (ERR);
while (height--) {
width = fwidth;
while (width--) {
if (len-- > 0) {
if (waddch(window, *string++) == ERR)
return (ERR);
} else
if (waddch(window, ' ') == ERR)
return (ERR);
}
if (wmove(window, ++y, x) == ERR)
return (ERR);
}
return (OK);
}
void
print_status(char *msg)
{
if (wmove(stdscr, LINES-1, 0) == ERR) {
endwin();
exit(1);
}
wclrtoeol(stdscr);
wstandout(stdscr);
if (wprintw(stdscr, "%s",
msg) == ERR) {
endwin();
exit(1);
}
wstandend(stdscr);
wrefresh(stdscr);
}
int
do_input(struct Form *form)
{
struct Field *field = form->current_field;
int len;
int disp_off=0, abspos=0, cursor = 0;
unsigned int ch;
#define DISPOFF ((len < field->width) ? 0 : len - field->width)
#define CURSPOS ((len < field->width) ? len : field->width)
len = strlen(field->field.input->input);
display_input(form->window, field);
cursor = CURSPOS;
abspos = cursor;
for (;;) {
wmove(form->window, field->y, field->x+cursor);
wrefresh(form->window);
ch = wgetch(form->window);
ch = do_key_bind(form, ch);
/*
* If there was a valid motion command then we've
* moved to a new field so just return. If the motion
* command was invalid then just go around and get another
* keystroke. Otherwise, it was not a motion command.
*/
if (ch == FS_OK)
return (FS_OK);
else if (ch == FS_ERROR)
continue;
print_status("");
if (field->field.input->lbl_flag) {
field->field.input->lbl_flag = 0;
}
if ((ch == FK_CHOME) || (ch == '')) {
disp_off = 0;
cursor = 0;
abspos = 0;
} else if ((ch == FK_CEND) || (ch == '')) {
disp_off = DISPOFF;
abspos = len;
cursor = CURSPOS;
} else if (ch == FK_CDEL) {
if (!(len-abspos))
beep();
else {
bcopy(field->field.input->input+abspos+1,
field->field.input->input+abspos,
len - abspos);
--len;
}
} else if ((ch == FK_CLEFT) || (ch == FK_CBS) || (ch == '')) {
if (!abspos)
beep();
else {
if (ch == FK_CBS) {
bcopy(field->field.input->input+abspos,
field->field.input->input+abspos-1,
len-abspos+1);
--len;
}
--abspos;
--cursor;
if ((disp_off) && (cursor < 0)) {
--disp_off;
++cursor;
}
}
} else if ((ch == FK_CRIGHT) || (ch == '')) {
if (abspos == len)
beep();
else {
++abspos;
if (++cursor >= field->width) {
++disp_off;
--cursor;
}
}
} else if ((isprint(ch)) && (len < field->field.input->limit)){
bcopy(field->field.input->input+abspos,
field->field.input->input+abspos+1, len-abspos+1);
field->field.input->input[abspos++] = ch;
len++;
if (++cursor > field->width) {
++disp_off;
--cursor;
}
} else
beep();
print_string(form->window, field->y, field->x, field->height,
field->width, field->field.input->input+disp_off);
}
}
void
exit_form(struct Form *form)
{
form->status = FS_EXIT;
}
void
cancel_form(struct Form *form)
{
form->status = FS_CANCEL;
}

View file

@ -1,4 +1,4 @@
/*-
/*
* Copyright (c) 1995
* Paul Richards. All rights reserved.
*
@ -32,48 +32,72 @@
*
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <forms.h>
#include <err.h>
#include <ncurses.h>
#include "internal.h"
extern FILE *yyin;
struct Tuple *fbind_first;
struct Tuple *fbind_last;
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 */
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 */
};
int done=0;
int
initfrm(struct form *form)
form_load(const char *filename)
{
FILE *fd;
struct field *field = &form->field[0];
int i;
if (has_colors()) {
start_color();
if (form->color_table)
for (i=0; form->color_table[i].f != -1; i++) {
init_pair(i+1, form->color_table[i].f, form->color_table[i].b);
}
if (!(fd = fopen(filename, "r"))) {
warn("Couldn't open forms file %s", filename);
return (FS_ERROR);
}
cbreak();
noecho();
yyin = fd;
yyparse();
if (fclose(fd)) {
warn("Couldn't close forms file %s", filename);
return (FS_ERROR);
}
return (FS_OK);
}
struct Form *
form_start(const char *formname)
{
struct Tuple *tuple;
struct Form *form;
struct Field *field;
tuple = form_get_tuple(formname, FT_FORM);
if (!tuple) {
warnx("No such form");
return (0);
}
form = tuple->addr;
/* Initialise form */
if (!form->height)
form->height = LINES;
if (!form->width)
@ -81,422 +105,190 @@ initfrm(struct form *form)
form->window = newwin(form->height, form->width, form->y, form->x);
if (!form->window) {
print_status("Couldn't open window, closing form");
return (ERR);
warnx("Couldn't open window, closing form");
return (0);
}
form->no_fields = 0;
keypad(form->window, TRUE);
tuple = form_get_tuple(form->startfield, FT_FIELD_INST);
if (!tuple) {
warnx("No start field specified");
/* XXX should search for better default start */
form->current_field = form->fieldlist;
} else
form->current_field = (struct Field *)tuple->addr;
while (field->type != F_END) {
if (field->type == F_INPUT) {
field->field.input->input = malloc(field->field.input->limit);
if (!field->field.input->input){
print_status("Couldn't allocate memory, closing form");
endfrm(form);
return (ERR);
}
/*
* If it's a label then clear the input string
* otherwise copy the default string to the input string.
*/
if (field->field.input->lbl_flag)
field->field.input->input[0] = '\0';
else if (field->field.input->label) {
strncpy(field->field.input->input,
field->field.input->label,
field->field.input->limit);
field->field.input->input[field->field.input->limit] = 0;
}
} else if ((field->type != F_TEXT) && (field->type != F_MENU) &&
(field->type != F_ACTION)) {
print_status("Unknown field type, closing form");
endfrm(form);
return (ERR);
}
form->no_fields++;
field = &form->field[form->no_fields];
form->prev_field = form->current_field;
/* Initialise the field instances */
for (field = form->fieldlist; field; field = field->next) {
init_field(field);
}
form->current_field = form->start_field;
show_form(form);
return (OK);
}
void
endfrm(struct form *form)
{
form->status = FS_RUNNING;
struct field *field = &form->field[0];
int i;
delwin(form->window);
for (i=0; i < form->no_fields; i++) {
if (field->type == F_INPUT)
free(field->field.input->input);
field = &form->field[i];
}
return (form);
}
int
update_form(struct form *form)
form_bind_tuple(char *name, TupleType type, void *addr)
{
show_form(form);
struct Tuple *tuple;
if (form->current_field == -1)
return (F_CANCEL);
wattrset(form->window, form->field[form->current_field].selattr);
switch (form->field[form->current_field].type) {
case F_MENU:
field_menu(form);
break;
case F_INPUT:
field_input(form);
break;
case F_ACTION:
field_action(form);
break;
case F_TEXT:
default:
print_status("Error, current field is invalid");
return (F_CANCEL);
tuple = malloc(sizeof (struct Tuple));
if (!tuple) {
warn("Couldn't allocate memory for new tuple");
return (FS_ERROR);
}
wattrset(form->window, 0);
return (done);
tuple->name = name;
tuple->type = type;
tuple->addr = addr;
tuple->next = 0;
if (!fbind_first) {
fbind_first = tuple;
fbind_last = tuple;
} else {
/* Check there isn't already a tuple of this type with this name */
if (form_get_tuple(name, type)) {
warn("Duplicate tuple name, %s, skipping", name);
return (FS_ERROR);
}
fbind_last->next = tuple;
fbind_last = tuple;
}
return (0);
}
static void
show_form(struct form *form)
struct Tuple *
form_get_tuple(const char *name, TupleType type)
{
int i;
int y, x;
return (form_next_tuple(name, type, fbind_first));
}
struct Tuple *
form_next_tuple(const char *name, TupleType type, struct Tuple *tuple)
{
for (; tuple; tuple = tuple->next) {
if (type != FT_ANY)
if (tuple->type != type)
continue;
if (name)
if (strcmp(name, tuple->name))
continue;
return (tuple);
}
return (0);
}
int
form_show(const char *formname)
{
struct Tuple *tuple;
struct Form *form;
struct Field *field;
int x, y;
tuple = form_get_tuple(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++)
for (y=0; y < form->height; y++)
for (x=0; x < form->width; x++)
mvwaddch(form->window, y, x, ' ');
for (i=0; i < form->no_fields; i++) {
wattrset(form->window, form->field[i].attr);
wmove(form->window, form->field[i].y, form->field[i].x);
switch (form->field[i].type) {
case F_TEXT:
disp_text(form, i);
break;
case F_MENU:
disp_menu(form, i);
break;
case F_INPUT:
disp_input(form,i);
break;
case F_ACTION:
disp_action(form,i);
break;
case F_END:
default:
break;
}
for (field = form->fieldlist; field; field = field->next) {
display_field(form->window, field);
}
wattrset(form->window, 0);
wrefresh(form->window);
return (FS_OK);
}
static void
disp_text(struct form *form, int index)
unsigned int
do_key_bind(struct Form *form, unsigned int ch)
{
struct Field *field = form->current_field;
struct Tuple *tuple=0;
struct field *field = &form->field[index];
/* XXX -- check for keymappings here --- not yet done */
if (print_string(form->window, field->y, field->x, field->height,
field->width, field->field.text->text) == ERR)
print_status("Illegal scroll in print_string");
}
static void
disp_input(struct form *form, int index)
{
struct field *field = &form->field[index];
if (field->field.input->lbl_flag) {
if (print_string(form->window, field->y, field->x, field->height,
field->width, field->field.input->label) == ERR)
print_status("Illegal scroll in print_string");
} else
if (print_string(form->window, field->y, field->x, field->height,
field->width, field->field.input->input) == ERR)
print_status("Illegal scroll in print_string");
}
static void
disp_menu(struct form *form, int index)
{
struct field *field = &form->field[index];
if (print_string(form->window, field->y, field->x, field->height,
field->width,
field->field.menu->options[field->field.menu->selected]) == ERR)
print_status("Illegal scroll in print_string");
}
static void
disp_action(struct form *form, int index)
{
struct field *field = &form->field[index];
if (print_string(form->window, field->y, field->x, field->height,
field->width,
field->field.action->text) == ERR)
print_status("Illegal scroll in print_string");
}
static void
field_action(struct form *form)
{
struct field *field = &form->field[form->current_field];
int ch;
for (;;) {
disp_action(form, form->current_field);
wmove(form->window, field->y, field->x);
ch = wgetch(form->window);
if (ch == F_ACCEPT) {
(*field->field.action->fn)();
return;
} else if (!next_field(form, ch))
beep();
else
return;
}
}
static void
field_menu(struct form *form)
{
struct field *field = &form->field[form->current_field];
int ch;
for (;;) {
disp_menu(form, form->current_field);
wmove(form->window, field->y, field->x);
switch (ch = wgetch(form->window)) {
case ' ':
print_status("");
field->field.menu->selected++;
if (field->field.menu->selected >= field->field.menu->no_options)
field->field.menu->selected = 0;
break;
default:
if (!next_field(form, ch)) {
print_status("Hit the space bar to toggle through options");
beep();
} else
return;
}
}
}
static int
next_field(struct form *form, int ch)
{
struct field *field = &form->field[form->current_field];
if (ch == F_UP) {
if (field->up == -1) {
print_status("Can't go up from here");
return (0);
if (ch == FK_UP) {
if (field->fup) {
tuple = form_get_tuple(field->fup, FT_FIELD_INST);
if (!tuple)
print_status("Field to move up to does not exist");
} else
form->current_field = field->up;
} else if (ch == F_DOWN) {
if (field->down == -1) {
print_status("Can't go down from here");
return (0);
print_status("Can't move up from this field");
} else if (ch == FK_DOWN) {
if (field->fdown) {
tuple = form_get_tuple(field->fdown, FT_FIELD_INST);
if (!tuple)
print_status("Field to move down to does not exist");
} else
form->current_field = field->down;
} else if (ch == F_NEXT) {
if (field->next == -1) {
print_status("Can't go to next from here");
return (0);
print_status("Can't move down from this field");
} else if (ch == FK_LEFT) {
if (field->fleft) {
tuple = form_get_tuple(field->fleft, FT_FIELD_INST);
if (!tuple)
print_status("Field to move left to does not exist");
} else
form->current_field = field->next;
} else if (ch == F_RIGHT) {
if (field->right == -1) {
print_status("Can't go right from here");
return (0);
print_status("Can't move left from this field");
} else if (ch == FK_RIGHT) {
if (field->fright) {
tuple = form_get_tuple(field->fright, FT_FIELD_INST);
if (!tuple)
print_status("Field to move right to does not exist");
} else
form->current_field = field->right;
} else if (ch == F_LEFT) {
if (field->left == -1) {
print_status("Can't go left from here");
return (0);
print_status("Can't move right from this field");
} else if (ch == FK_NEXT) {
if (field->fnext) {
tuple = form_get_tuple(field->fnext, FT_FIELD_INST);
if (!tuple)
print_status("Field to move to next does not exist");
} else
form->current_field = field->left;
print_status("Can't move next from this field");
} else
return (0);
print_status("");
return (1);
}
static int
print_string(WINDOW *window, int y, int x,
int height, int fwidth, char *string)
{
int len;
int width;
if (!string)
len = -1;
len = strlen(string);
if (wmove(window, y, x) == ERR)
return (ERR);
while (height--) {
width = fwidth;
while (width--) {
if (len-- > 0) {
if (waddch(window, *string++) == ERR)
return (ERR);
} else
if (waddch(window, ' ') == ERR)
return (ERR);
}
if (wmove(window, ++y, x) == ERR)
return (ERR);
/* 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 (OK);
}
void
print_status(char *msg)
{
if (wmove(stdscr, LINES-1, 0) == ERR) {
endwin();
exit(1);
}
wclrtoeol(stdscr);
wstandout(stdscr);
if (wprintw(stdscr, "%s",
msg) == ERR) {
endwin();
exit(1);
}
wstandend(stdscr);
wrefresh(stdscr);
}
void
field_input(struct form *form)
{
struct field *field = &form->field[form->current_field];
int len;
int ch;
int disp_off=0, abspos=0, cursor = 0;
#define DISPOFF ((len < field->width) ? 0 : len - field->width)
#define CURSPOS ((len < field->width) ? len : field->width)
len = strlen(field->field.input->input);
disp_input(form, form->current_field);
cursor = CURSPOS;
abspos = cursor;
for(;;) {
wmove(form->window, field->y, field->x+cursor);
wrefresh(form->window);
ch = wgetch(form->window);
if (next_field(form, ch)) {
print_string(form->window, field->y, field->x,
field->height, field->width,
field->field.input->input+DISPOFF);
return;
}
if (field->field.input->lbl_flag) {
field->field.input->lbl_flag = 0;
}
if ((ch == F_CHOME) || (ch == '')) {
disp_off = 0;
cursor = 0;
abspos = 0;
} else if ((ch == F_CEND) || (ch == '')) {
disp_off = DISPOFF;
abspos = len;
cursor = CURSPOS;
} else if (ch == F_CDEL) {
if (!(len-abspos))
beep();
else {
bcopy(field->field.input->input+abspos+1,
field->field.input->input+abspos,
len - abspos);
--len;
}
} else if ((ch == F_CLEFT) || (ch == F_CBS) || (ch == '')) {
if (!abspos)
beep();
else {
if (ch == F_CBS) {
bcopy(field->field.input->input+abspos,
field->field.input->input+abspos-1,
len-abspos+1);
--len;
}
--abspos;
--cursor;
if ((disp_off) && (cursor < 0)) {
--disp_off;
++cursor;
}
}
} else if ((ch == F_CRIGHT) || (ch == '')) {
if (abspos == len)
beep();
else {
++abspos;
if (++cursor == field->width) {
++disp_off;
--cursor;
}
}
} else if ((isprint(ch)) && (len < field->field.input->limit)){
bcopy(field->field.input->input+abspos,
field->field.input->input+abspos+1, len-abspos+1);
field->field.input->input[abspos++] = ch;
len++;
if (++cursor > field->width) {
++disp_off;
--cursor;
}
} else {
beep();
}
print_string(form->window, field->y, field->x, field->height,
field->width, field->field.input->input+disp_off);
}
/* Not Reached */
}
void
exit_form(void)
debug_dump_bindings()
{
done = F_DONE;
struct Tuple *binds;
binds = form_get_tuple(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);
}
}
void
cancel_form(void)
void debug_dump_form(struct Form *form)
{
done = F_CANCEL;
struct Field *field;
field = form->fieldlist;
for ( ; field; field = field->next) {
printf("%s, %x, next = %x\n", field->defname, (int)field, (int)field->next);
}
}

502
lib/libforms/forms.c.orig Normal file
View file

@ -0,0 +1,502 @@
/*-
* Copyright (c) 1995
* Paul Richards. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* verbatim and that no modifications are made prior to this
* point in the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Paul Richards.
* 4. The name Paul Richards may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <forms.h>
#include <ncurses.h>
#include "internal.h"
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 */
};
int done=0;
int
initfrm(struct form *form)
{
struct field *field = &form->field[0];
int i;
if (has_colors()) {
start_color();
if (form->color_table)
for (i=0; form->color_table[i].f != -1; i++) {
init_pair(i+1, form->color_table[i].f, form->color_table[i].b);
}
}
cbreak();
noecho();
if (!form->height)
form->height = LINES;
if (!form->width)
form->width = COLS;
form->window = newwin(form->height, form->width, form->y, form->x);
if (!form->window) {
print_status("Couldn't open window, closing form");
return (ERR);
}
form->no_fields = 0;
keypad(form->window, TRUE);
while (field->type != F_END) {
if (field->type == F_INPUT) {
field->field.input->input = malloc(field->field.input->limit);
if (!field->field.input->input){
print_status("Couldn't allocate memory, closing form");
endfrm(form);
return (ERR);
}
/*
* If it's a label then clear the input string
* otherwise copy the default string to the input string.
*/
if (field->field.input->lbl_flag)
field->field.input->input[0] = '\0';
else if (field->field.input->label) {
strncpy(field->field.input->input,
field->field.input->label,
field->field.input->limit);
field->field.input->input[field->field.input->limit] = 0;
}
} else if ((field->type != F_TEXT) && (field->type != F_MENU) &&
(field->type != F_ACTION)) {
print_status("Unknown field type, closing form");
endfrm(form);
return (ERR);
}
form->no_fields++;
field = &form->field[form->no_fields];
}
form->current_field = form->start_field;
show_form(form);
return (OK);
}
void
endfrm(struct form *form)
{
struct field *field = &form->field[0];
int i;
delwin(form->window);
for (i=0; i < form->no_fields; i++) {
if (field->type == F_INPUT)
free(field->field.input->input);
field = &form->field[i];
}
}
int
update_form(struct form *form)
{
show_form(form);
if (form->current_field == -1)
return (F_CANCEL);
wattrset(form->window, form->field[form->current_field].selattr);
switch (form->field[form->current_field].type) {
case F_MENU:
field_menu(form);
break;
case F_INPUT:
field_input(form);
break;
case F_ACTION:
field_action(form);
break;
case F_TEXT:
default:
print_status("Error, current field is invalid");
return (F_CANCEL);
}
wattrset(form->window, 0);
return (done);
}
static void
show_form(struct form *form)
{
int i;
int y, x;
wattrset(form->window, form->attr);
for (y = 0; y < form->height; y++)
for (x = 0; x < form->width; x++)
mvwaddch(form->window, y, x, ' ');
for (i=0; i < form->no_fields; i++) {
wattrset(form->window, form->field[i].attr);
wmove(form->window, form->field[i].y, form->field[i].x);
switch (form->field[i].type) {
case F_TEXT:
disp_text(form, i);
break;
case F_MENU:
disp_menu(form, i);
break;
case F_INPUT:
disp_input(form,i);
break;
case F_ACTION:
disp_action(form,i);
break;
case F_END:
default:
break;
}
}
wattrset(form->window, 0);
wrefresh(form->window);
}
static void
disp_text(struct form *form, int index)
{
struct field *field = &form->field[index];
if (print_string(form->window, field->y, field->x, field->height,
field->width, field->field.text->text) == ERR)
print_status("Illegal scroll in print_string");
}
static void
disp_input(struct form *form, int index)
{
struct field *field = &form->field[index];
if (field->field.input->lbl_flag) {
if (print_string(form->window, field->y, field->x, field->height,
field->width, field->field.input->label) == ERR)
print_status("Illegal scroll in print_string");
} else
if (print_string(form->window, field->y, field->x, field->height,
field->width, field->field.input->input) == ERR)
print_status("Illegal scroll in print_string");
}
static void
disp_menu(struct form *form, int index)
{
struct field *field = &form->field[index];
if (print_string(form->window, field->y, field->x, field->height,
field->width,
field->field.menu->options[field->field.menu->selected]) == ERR)
print_status("Illegal scroll in print_string");
}
static void
disp_action(struct form *form, int index)
{
struct field *field = &form->field[index];
if (print_string(form->window, field->y, field->x, field->height,
field->width,
field->field.action->text) == ERR)
print_status("Illegal scroll in print_string");
}
static void
field_action(struct form *form)
{
struct field *field = &form->field[form->current_field];
int ch;
for (;;) {
disp_action(form, form->current_field);
wmove(form->window, field->y, field->x);
ch = wgetch(form->window);
if (ch == F_ACCEPT) {
(*field->field.action->fn)();
return;
} else if (!next_field(form, ch))
beep();
else
return;
}
}
static void
field_menu(struct form *form)
{
struct field *field = &form->field[form->current_field];
int ch;
for (;;) {
disp_menu(form, form->current_field);
wmove(form->window, field->y, field->x);
switch (ch = wgetch(form->window)) {
case ' ':
print_status("");
field->field.menu->selected++;
if (field->field.menu->selected >= field->field.menu->no_options)
field->field.menu->selected = 0;
break;
default:
if (!next_field(form, ch)) {
print_status("Hit the space bar to toggle through options");
beep();
} else
return;
}
}
}
static int
next_field(struct form *form, int ch)
{
struct field *field = &form->field[form->current_field];
if (ch == F_UP) {
if (field->up == -1) {
print_status("Can't go up from here");
return (0);
} else
form->current_field = field->up;
} else if (ch == F_DOWN) {
if (field->down == -1) {
print_status("Can't go down from here");
return (0);
} else
form->current_field = field->down;
} else if (ch == F_NEXT) {
if (field->next == -1) {
print_status("Can't go to next from here");
return (0);
} else
form->current_field = field->next;
} else if (ch == F_RIGHT) {
if (field->right == -1) {
print_status("Can't go right from here");
return (0);
} else
form->current_field = field->right;
} else if (ch == F_LEFT) {
if (field->left == -1) {
print_status("Can't go left from here");
return (0);
} else
form->current_field = field->left;
} else
return (0);
print_status("");
return (1);
}
static int
print_string(WINDOW *window, int y, int x,
int height, int fwidth, char *string)
{
int len;
int width;
if (!string)
len = -1;
len = strlen(string);
if (wmove(window, y, x) == ERR)
return (ERR);
while (height--) {
width = fwidth;
while (width--) {
if (len-- > 0) {
if (waddch(window, *string++) == ERR)
return (ERR);
} else
if (waddch(window, ' ') == ERR)
return (ERR);
}
if (wmove(window, ++y, x) == ERR)
return (ERR);
}
return (OK);
}
void
print_status(char *msg)
{
if (wmove(stdscr, LINES-1, 0) == ERR) {
endwin();
exit(1);
}
wclrtoeol(stdscr);
wstandout(stdscr);
if (wprintw(stdscr, "%s",
msg) == ERR) {
endwin();
exit(1);
}
wstandend(stdscr);
wrefresh(stdscr);
}
void
field_input(struct form *form)
{
struct field *field = &form->field[form->current_field];
int len;
int ch;
int disp_off=0, abspos=0, cursor = 0;
#define DISPOFF ((len < field->width) ? 0 : len - field->width)
#define CURSPOS ((len < field->width) ? len : field->width)
len = strlen(field->field.input->input);
disp_input(form, form->current_field);
cursor = CURSPOS;
abspos = cursor;
for(;;) {
wmove(form->window, field->y, field->x+cursor);
wrefresh(form->window);
ch = wgetch(form->window);
if (next_field(form, ch)) {
print_string(form->window, field->y, field->x,
field->height, field->width,
field->field.input->input+DISPOFF);
return;
}
if (field->field.input->lbl_flag) {
field->field.input->lbl_flag = 0;
}
if ((ch == F_CHOME) || (ch == '')) {
disp_off = 0;
cursor = 0;
abspos = 0;
} else if ((ch == F_CEND) || (ch == '')) {
disp_off = DISPOFF;
abspos = len;
cursor = CURSPOS;
} else if (ch == F_CDEL) {
if (!(len-abspos))
beep();
else {
bcopy(field->field.input->input+abspos+1,
field->field.input->input+abspos,
len - abspos);
--len;
}
} else if ((ch == F_CLEFT) || (ch == F_CBS) || (ch == '')) {
if (!abspos)
beep();
else {
if (ch == F_CBS) {
bcopy(field->field.input->input+abspos,
field->field.input->input+abspos-1,
len-abspos+1);
--len;
}
--abspos;
--cursor;
if ((disp_off) && (cursor < 0)) {
--disp_off;
++cursor;
}
}
} else if ((ch == F_CRIGHT) || (ch == '')) {
if (abspos == len)
beep();
else {
++abspos;
if (++cursor == field->width) {
++disp_off;
--cursor;
}
}
} else if ((isprint(ch)) && (len < field->field.input->limit)){
bcopy(field->field.input->input+abspos,
field->field.input->input+abspos+1, len-abspos+1);
field->field.input->input[abspos++] = ch;
len++;
if (++cursor > field->width) {
++disp_off;
--cursor;
}
} else {
beep();
}
print_string(form->window, field->y, field->x, field->height,
field->width, field->field.input->input+disp_off);
}
/* Not Reached */
}
void
exit_form(void)
{
done = F_DONE;
}
void
cancel_form(void)
{
done = F_CANCEL;
}

View file

@ -34,63 +34,89 @@
#include <ncurses.h>
#define F_END 0
#define F_TEXT 1
#define F_ACTION 2
#define F_INPUT 3
#define F_MENU 4
#define FF_UNKNOWN 0
#define FF_TEXT 1
#define FF_ACTION 2
#define FF_INPUT 3
#define FF_MENU 4
#define F_DEFATTR 0
#define F_SELATTR A_REVERSE
#define F_DONE 1
#define F_CANCEL -1
/* 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
typedef enum {
FT_ANY,
FT_FORM,
FT_COLTAB,
FT_FIELD_INST,
FT_FIELD_DEF,
FT_FUNC
} TupleType;
struct Tuple {
char *name;
int type;
void *addr;
struct Tuple *next;
};
struct col_pair {
int f;
int b;
};
struct form {
struct Form {
int status;
int no_fields;
int start_field;
int current_field;
struct field *field;
char *startfield;
struct Field *current_field;
struct Field *prev_field;
struct Field *fieldlist;
int height;
int width;
int y;
int x;
int attr;
struct col_pair *color_table;
char *colortable;
WINDOW *window;
};
struct text_field {
struct TextField {
char *text;
};
struct action_field {
struct ActionField {
char *text;
void (* fn)();
char *fn;
};
struct input_field {
struct InputField {
int lbl_flag;
char *label;
char *input;
int limit;
};
struct menu_field {
int no_options;
struct MenuField {
int selected;
int no_options;
char **options;
};
struct help_link {
};
struct field {
struct Field {
char *defname;
int type;
int y;
int x;
@ -98,17 +124,19 @@ struct field {
int width;
int attr;
int selattr;
int next;
int up;
int down;
int left;
int right;
char *fnext;
char *fup;
char *fdown;
char *fleft;
char *fright;
char *f_keymap;
union {
struct text_field *text;
struct action_field *action;
struct input_field *input;
struct menu_field *menu;
struct TextField *text;
struct ActionField *action;
struct InputField *input;
struct MenuField *menu;
}field;
struct Field *next;
/*
struct help_link help;
*/
@ -118,9 +146,18 @@ struct field {
extern unsigned int keymap[];
/* Externally visible function declarations */
struct Form *form_start(const char *);
struct Tuple *form_get_tuple(const char *, TupleType);
struct Tuple *form_next_tuple(const char *, TupleType, struct Tuple *);
int form_bind_tuple(char *, TupleType, void *);
void print_status(char *);
void exit_form(struct Form *form);
void cancel_form(struct Form *form);
#ifdef not
int update_form(struct form *);
int initfrm(struct form *);
void endfrm(struct form *);
void exit_form(void);
void cancel_form(void);
void print_status(char *);
#endif

126
lib/libforms/forms.h.orig Normal file
View file

@ -0,0 +1,126 @@
/*-
* Copyright (c) 1995
* Paul Richards. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* verbatim and that no modifications are made prior to this
* point in the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Paul Richards.
* 4. The name Paul Richards may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <ncurses.h>
#define F_END 0
#define F_TEXT 1
#define F_ACTION 2
#define F_INPUT 3
#define F_MENU 4
#define F_DEFATTR 0
#define F_SELATTR A_REVERSE
#define F_DONE 1
#define F_CANCEL -1
struct col_pair {
int f;
int b;
};
struct form {
int no_fields;
int start_field;
int current_field;
struct field *field;
int height;
int width;
int y;
int x;
int attr;
struct col_pair *color_table;
WINDOW *window;
};
struct text_field {
char *text;
};
struct action_field {
char *text;
void (* fn)();
};
struct input_field {
int lbl_flag;
char *label;
char *input;
int limit;
};
struct menu_field {
int no_options;
int selected;
char **options;
};
struct help_link {
};
struct field {
int type;
int y;
int x;
int height;
int width;
int attr;
int selattr;
int next;
int up;
int down;
int left;
int right;
union {
struct text_field *text;
struct action_field *action;
struct input_field *input;
struct menu_field *menu;
}field;
/*
struct help_link help;
*/
};
/* Externally visible keymap table for user-definable keymaps */
extern unsigned int keymap[];
/* Externally visible function declarations */
int update_form(struct form *);
int initfrm(struct form *);
void endfrm(struct form *);
void exit_form(void);
void cancel_form(void);
void print_status(char *);

View file

@ -1,38 +1,75 @@
/*
* Copyright (c) 1995 Paul Richards.
* Copyright (c) 1995
* Paul Richards. All rights reserved.
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* verbatim and that no modifications are made prior to this
* point in the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Paul Richards.
* 4. The name Paul Richards may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*/
#define F_UP f_keymap[0]
#define F_DOWN f_keymap[1]
#define F_RIGHT f_keymap[2]
#define F_LEFT f_keymap[3]
#define F_NEXT f_keymap[4]
#define F_CLEFT f_keymap[5]
#define F_CRIGHT f_keymap[6]
#define F_CHOME f_keymap[7]
#define F_CEND f_keymap[8]
#define F_CBS f_keymap[9]
#define F_CDEL f_keymap[10]
#define F_ACCEPT f_keymap[11]
#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]
extern unsigned int f_keymap[];
/* 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(struct Field *);
#ifdef not
static void show_form(struct form *);
static void disp_text(struct form *, int);
static void disp_menu(struct form *, int);
static void disp_action(struct form *, int);
static void disp_input(struct form *, int);
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

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 1995 Paul Richards.
*
* All rights reserved.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*/
#define F_UP f_keymap[0]
#define F_DOWN f_keymap[1]
#define F_RIGHT f_keymap[2]
#define F_LEFT f_keymap[3]
#define F_NEXT f_keymap[4]
#define F_CLEFT f_keymap[5]
#define F_CRIGHT f_keymap[6]
#define F_CHOME f_keymap[7]
#define F_CEND f_keymap[8]
#define F_CBS f_keymap[9]
#define F_CDEL f_keymap[10]
#define F_ACCEPT f_keymap[11]
/* Private function declarations */
static void show_form(struct form *);
static void disp_text(struct form *, int);
static void disp_menu(struct form *, int);
static void disp_action(struct form *, int);
static void disp_input(struct form *, int);
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);

1606
lib/libforms/lex.c Normal file

File diff suppressed because it is too large Load diff

58
lib/libforms/menu.c Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 1995
* Paul Richards. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* verbatim and that no modifications are made prior to this
* point in the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Paul Richards.
* 4. The name Paul Richards may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <forms.h>
#include <stdlib.h>
#include <string.h>
int
add_menu_option(struct MenuField *menu, char *option)
{
char **tmp;
int len;
tmp = (char **)realloc(menu->options, (menu->no_options + 1) * sizeof(char**));
if (!tmp)
return (0);
else
menu->options = tmp;
len = strlen(option) + 1;
menu->options[menu->no_options] = (char *)malloc(len);
if (!menu->options[menu->no_options])
return (0);
strncpy(menu->options[menu->no_options], option, len);
return (++menu->no_options);
}

1022
lib/libforms/parser.c Normal file

File diff suppressed because it is too large Load diff

567
lib/libforms/parser.y Normal file
View file

@ -0,0 +1,567 @@
%{
/*-
* Copyright (c) 1995
* Paul Richards. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* verbatim and that no modifications are made prior to this
* point in the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Paul Richards.
* 4. The name Paul Richards may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.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;
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;
%}
%union {
int ival;
char *sval;
}
%token <ival> FORM
%token <ival> COLORTABLE
%token <ival> COLOR
%token <ival> BLACK
%token <ival> RED
%token <ival> GREEN
%token <ival> YELLOW
%token <ival> BLUE
%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> 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
%start spec
%%
spec: /* empty */
| spec fields
| spec forms
| spec colours
;
colours: COLOR 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);
}
LBRACE color_pairs RBRACE
{
color_table->pairs = pair_list;
cur_pair = 0;
form_bind_tuple(color_table->tablename, FT_COLTAB, color_table);
}
;
color_pairs: /* empty */
| color_pairs pair
;
pair: PAIR EQUALS a_color
{
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);
}
COMMA a_color
{
pair->background = cpstr($6);
if (!cur_pair) {
pair_list = pair;
cur_pair = pair;
} else {
cur_pair->next = pair;
cur_pair = pair;
}
}
;
a_color: BLACK
{ $$ = "COLOR_BLACK"; }
| RED
{ $$ = "COLOR_RED"; }
| GREEN
{ $$ = "COLOR_GREEN"; }
| YELLOW
{ $$ = "COLOR_YELLOW"; }
| BLUE
{ $$ = "COLOR_BLUE"; }
| MAGENTA
{ $$ = "COLOR_MAGENTA"; }
| CYAN
{ $$ = "COLOR_CYAN"; }
| WHITE
{ $$ = "COLOR_WHITE"; }
;
forms: FORM NAME
{ formname = cpstr($2); }
AT coord
{
form = malloc(sizeof (struct Form));
if (!form) {
fprintf(stderr,"Failed to allocate memory for form\n");
exit(1);
}
form->y = y;
form->x = x;
}
LBRACE formspec RBRACE
{
form->startfield = startname;
form->colortable = colortable;
form->height = height;
form->width = width;
form->attr = formattr;
form->fieldlist = field_inst_list;
field_inst_list = 0;
form_bind_tuple(formname, FT_FORM, form);
}
;
formspec: height width startfield colortable formattr fieldlocs
;
startfield: /* empty */
{ startname = 0;
printf("Warning: No start field specified for form %s\n", formname);
}
| STARTFIELD EQUALS NAME
{ startname = cpstr($3); }
;
colortable: /*empty */
{ colortable = 0; }
| COLORTABLE EQUALS NAME
{ colortable = cpstr($3); }
;
formattr: /* empty */
{ formattr = 0; }
| ATTR EQUALS NUMBER
{ formattr = $3; }
;
fieldlocs: /* empty */
| fieldlocs field_at
;
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
{
field->fup = up;
field->fdown = down;
field->fleft = left;
field->fright = right;
field->fnext = next;
if (!field_inst_list)
field_inst_list = field;
up = 0;
down = 0;
left = 0;
right = 0;
next = 0;
if (!cur_field)
cur_field = field;
else {
cur_field->next = field;
cur_field = field;
}
form_bind_tuple(fieldname, FT_FIELD_INST, field);
}
;
fields: NAME
{ defname = cpstr($1); }
field_spec
{ define_field(defname); }
;
field_def: /* empty */
{ defname = 0; }
| LBRACE NAME
{ defname = cpstr($2); }
RBRACE
| field_spec
{ defname = fieldname; define_field(defname); }
;
field_spec: LBRACE height width attr selattr type RBRACE
;
links: /* empty */
| links COMMA conns
;
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); }
;
type: textfield
| inputfield
| menufield
| actionfield
;
textfield: TEXT EQUALS STRING
{ type = FF_TEXT; text = cpstr($3); }
;
inputfield: inputspec
{ type = FF_INPUT; }
;
inputspec: LABEL EQUALS STRING limit
{ lbl_flag = 1; label = cpstr($3); }
| DEFAULT EQUALS STRING limit
{ lbl_flag = 0; label = cpstr($3); }
;
limit: /* empty */
| LIMIT EQUALS NUMBER
{ limit = $3; }
menufield: SELECTED EQUALS NUMBER OPTIONS EQUALS menuoptions
{ type = FF_MENU; selected = $3; }
;
menuoptions: menuoption
| menuoptions COMMA 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;
}
}
;
actionfield: ACTION EQUALS STRING FUNC EQUALS NAME
{ type = FF_ACTION; text = cpstr($3); function = cpstr($6); }
;
height: /* empty */
{ height = 0; }
| HEIGHT EQUALS NUMBER
{ height = $3; }
;
width: /* empty */
{ width = 0; }
| WIDTH EQUALS NUMBER
{ width = $3; }
;
attr: /* empty */
{ attr = 0; }
| ATTR EQUALS NUMBER
{ attr = $3; }
;
selattr: /* empty */
{ selattr = 0; }
| SELATTR EQUALS NUMBER
{ selattr = $3; }
;
coord: NUMBER COMMA NUMBER
{ y = $1; x = $3; }
;
%%
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);
}
/* Calculate a default height for a field */
void
calc_field_height(struct Field *field, char *string)
{
int len;
len = strlen(string);
if (!field->width) {
/*
* This is a failsafe, this routine shouldn't be called
* with a width of 0, the width should be determined
* first.
*/
field->height = 1;
return;
}
if (len < field->width) {
field->height = 1;
return;
} else
field->height = len / field->width;
if ((field->height*field->width) < len)
field->height++;
return;
}
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(defname, FT_FIELD_DEF, field);
width=0;
height = 0;
attr=0;
selattr=0;
limit=0;
}

46
lib/libforms/y.tab.h Normal file
View file

@ -0,0 +1,46 @@
#define FORM 257
#define COLORTABLE 258
#define COLOR 259
#define BLACK 260
#define RED 261
#define GREEN 262
#define YELLOW 263
#define BLUE 264
#define MAGENTA 265
#define CYAN 266
#define WHITE 267
#define PAIR 268
#define NAME 269
#define STRING 270
#define AT 271
#define AS 272
#define HEIGHT 273
#define EQUALS 274
#define NUMBER 275
#define WIDTH 276
#define STARTFIELD 277
#define COMMA 278
#define LBRACE 279
#define RBRACE 280
#define TEXT 281
#define ATTR 282
#define SELATTR 283
#define DEFAULT 284
#define LABEL 285
#define LIMIT 286
#define SELECTED 287
#define OPTIONS 288
#define ACTION 289
#define FUNC 290
#define LINK 291
#define UP 292
#define DOWN 293
#define LEFT 294
#define RIGHT 295
#define NEXT 296
#define DEF 297
typedef union {
int ival;
char *sval;
} YYSTYPE;
extern YYSTYPE yylval;