1995-01-10 05:00:37 +01:00
|
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
1994-11-13 07:45:44 +01:00
|
|
|
|
#include <string.h>
|
1995-01-10 05:00:37 +01:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <ctype.h>
|
1994-11-13 07:45:44 +01:00
|
|
|
|
#include <forms.h>
|
1995-01-10 05:00:37 +01:00
|
|
|
|
#include "internal.h"
|
1994-11-13 07:45:44 +01:00
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
unsigned int 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 */
|
1994-11-13 07:45:44 +01:00
|
|
|
|
};
|
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
int done=0;
|
|
|
|
|
|
1994-11-13 07:45:44 +01:00
|
|
|
|
int
|
1995-01-10 05:00:37 +01:00
|
|
|
|
initfrm(struct form *form)
|
1994-11-13 07:45:44 +01:00
|
|
|
|
{
|
1995-01-10 05:00:37 +01:00
|
|
|
|
|
|
|
|
|
struct field *field = &form->field[0];
|
|
|
|
|
|
|
|
|
|
cbreak();
|
|
|
|
|
noecho();
|
|
|
|
|
|
|
|
|
|
form->window = newwin(form->nlines, form->ncols, 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->width);
|
|
|
|
|
if (!field->field.input->input){
|
|
|
|
|
print_status("Couldn't allocate memory, closing form");
|
|
|
|
|
endfrm(form);
|
|
|
|
|
return (ERR);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
1995-01-10 05:00:37 +01:00
|
|
|
|
/*
|
|
|
|
|
* 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)
|
|
|
|
|
strcpy(field->field.input->input, field->field.input->label);
|
|
|
|
|
} 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);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
1995-01-10 05:00:37 +01:00
|
|
|
|
form->no_fields++;
|
|
|
|
|
field = &form->field[form->no_fields];
|
|
|
|
|
}
|
|
|
|
|
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];
|
|
|
|
|
}
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
1995-01-10 05:00:37 +01:00
|
|
|
|
update_form(struct form *form)
|
1994-11-13 07:45:44 +01:00
|
|
|
|
{
|
|
|
|
|
|
1995-01-11 07:08:45 +01:00
|
|
|
|
show_form(form);
|
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
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:
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
return (done);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
show_form(struct form *form)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i=0; i < form->no_fields; i++) {
|
|
|
|
|
wattrset(form->window, 0);
|
|
|
|
|
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;
|
|
|
|
|
}
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
1995-01-10 05:00:37 +01:00
|
|
|
|
wrefresh(form->window);
|
|
|
|
|
}
|
1994-11-13 07:45:44 +01:00
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
static void
|
|
|
|
|
disp_text(struct form *form, int index)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct field *field = &form->field[index];
|
|
|
|
|
|
|
|
|
|
wattron(form->window, field->attr);
|
|
|
|
|
|
|
|
|
|
if (print_string(form->window, field->y, field->x,
|
|
|
|
|
field->disp_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];
|
|
|
|
|
|
|
|
|
|
wattron(form->window, field->attr);
|
|
|
|
|
|
|
|
|
|
if (field->field.input->lbl_flag) {
|
|
|
|
|
if (print_string(form->window, field->y, field->x,
|
|
|
|
|
field->disp_width, field->field.input->label) == ERR)
|
|
|
|
|
print_status("Illegal scroll in print_string");
|
|
|
|
|
} else
|
|
|
|
|
if (print_string(form->window, field->y, field->x,
|
|
|
|
|
field->disp_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];
|
|
|
|
|
|
|
|
|
|
wattron(form->window, field->attr);
|
|
|
|
|
|
|
|
|
|
if (print_string(form->window, field->y, field->x,
|
|
|
|
|
field->disp_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];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wattron(form->window, field->attr);
|
|
|
|
|
|
|
|
|
|
if (print_string(form->window, field->y, field->x,
|
|
|
|
|
field->disp_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 (;;) {
|
|
|
|
|
wattron(form->window, F_SELATTR);
|
|
|
|
|
disp_action(form, form->current_field);
|
1995-01-10 05:10:55 +01:00
|
|
|
|
wmove(form->window, field->y, field->x);
|
1995-01-10 05:00:37 +01:00
|
|
|
|
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 (;;) {
|
|
|
|
|
wattron(form->window, F_SELATTR);
|
|
|
|
|
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);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
} else
|
1995-01-10 05:00:37 +01:00
|
|
|
|
form->current_field = field->up;
|
|
|
|
|
} else if (ch == F_DOWN) {
|
|
|
|
|
if (field->down == -1) {
|
|
|
|
|
print_status("Can't go down from here");
|
|
|
|
|
return (0);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
} else
|
1995-01-10 05:00:37 +01:00
|
|
|
|
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);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
} else
|
1995-01-10 05:00:37 +01:00
|
|
|
|
form->current_field = field->next;
|
|
|
|
|
} else if (ch == F_RIGHT) {
|
|
|
|
|
if (field->right == -1) {
|
|
|
|
|
print_status("Can't go right from here");
|
|
|
|
|
return (0);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
} else
|
1995-01-10 05:00:37 +01:00
|
|
|
|
form->current_field = field->right;
|
|
|
|
|
} else if (ch == F_LEFT) {
|
|
|
|
|
if (field->left == -1) {
|
|
|
|
|
print_status("Can't go left from here");
|
|
|
|
|
return (0);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
} else
|
1995-01-10 05:00:37 +01:00
|
|
|
|
form->current_field = field->left;
|
|
|
|
|
} else
|
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
|
|
print_status("");
|
|
|
|
|
return (1);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
static int
|
|
|
|
|
print_string(WINDOW *window, int y, int x,
|
|
|
|
|
int disp_width, char *string)
|
1994-11-13 07:45:44 +01:00
|
|
|
|
{
|
1995-01-10 05:00:37 +01:00
|
|
|
|
int len;
|
1994-11-13 07:45:44 +01:00
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
if (!string)
|
|
|
|
|
len = -1;
|
1994-11-13 07:45:44 +01:00
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
len = strlen(string);
|
|
|
|
|
|
|
|
|
|
if (wmove(window, y, x) == ERR)
|
|
|
|
|
return (ERR);
|
|
|
|
|
while (disp_width--) {
|
|
|
|
|
if (len-- > 0) {
|
|
|
|
|
if (waddch(window, *string++) == ERR)
|
|
|
|
|
return (ERR);
|
|
|
|
|
} else
|
|
|
|
|
if (waddch(window, ' ') == ERR)
|
|
|
|
|
return (ERR);
|
|
|
|
|
}
|
|
|
|
|
return (OK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_status(char *msg)
|
1994-11-13 07:45:44 +01:00
|
|
|
|
{
|
1995-01-10 05:00:37 +01:00
|
|
|
|
if (wmove(stdscr, LINES-1, 0) == ERR) {
|
|
|
|
|
endwin();
|
|
|
|
|
exit(1);
|
1994-11-13 08:43:43 +01:00
|
|
|
|
}
|
1994-11-13 07:45:44 +01:00
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
wclrtoeol(stdscr);
|
1994-11-13 07:45:44 +01:00
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
wstandout(stdscr);
|
|
|
|
|
if (wprintw(stdscr, "%s",
|
|
|
|
|
msg) == ERR) {
|
|
|
|
|
endwin();
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
wstandend(stdscr);
|
|
|
|
|
wrefresh(stdscr);
|
|
|
|
|
}
|
1994-11-13 07:45:44 +01:00
|
|
|
|
|
1995-01-10 05:00:37 +01:00
|
|
|
|
|
|
|
|
|
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->disp_width) ? 0 : len - field->disp_width)
|
|
|
|
|
#define CURSPOS ((len < field->disp_width) ? len : field->disp_width)
|
|
|
|
|
|
|
|
|
|
len = strlen(field->field.input->input);
|
|
|
|
|
wattron(form->window, F_SELATTR);
|
|
|
|
|
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->disp_width,
|
|
|
|
|
field->field.input->input+DISPOFF);
|
|
|
|
|
return;
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
1995-01-10 05:00:37 +01:00
|
|
|
|
if (field->field.input->lbl_flag) {
|
|
|
|
|
field->field.input->lbl_flag = 0;
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
1995-01-11 07:08:45 +01:00
|
|
|
|
if ((ch == F_CHOME) || (ch == '')) {
|
1995-01-10 05:00:37 +01:00
|
|
|
|
disp_off = 0;
|
|
|
|
|
cursor = 0;
|
|
|
|
|
abspos = 0;
|
1995-01-11 07:08:45 +01:00
|
|
|
|
} else if ((ch == F_CEND) || (ch == '')) {
|
1995-01-10 05:00:37 +01:00
|
|
|
|
disp_off = DISPOFF;
|
|
|
|
|
abspos = len;
|
|
|
|
|
cursor = CURSPOS;
|
|
|
|
|
} else if (ch == F_CDEL) {
|
|
|
|
|
if (!(len-abspos))
|
1994-11-13 07:45:44 +01:00
|
|
|
|
beep();
|
1995-01-10 05:00:37 +01:00
|
|
|
|
else {
|
|
|
|
|
bcopy(field->field.input->input+abspos+1,
|
|
|
|
|
field->field.input->input+abspos,
|
|
|
|
|
len - abspos);
|
|
|
|
|
--len;
|
|
|
|
|
}
|
1995-01-11 07:08:45 +01:00
|
|
|
|
} else if ((ch == F_CLEFT) || (ch == F_CBS) || (ch == '')) {
|
1995-01-10 05:00:37 +01:00
|
|
|
|
if (!abspos)
|
1994-11-13 07:45:44 +01:00
|
|
|
|
beep();
|
1995-01-10 05:00:37 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
1995-01-11 07:08:45 +01:00
|
|
|
|
} else if ((ch == F_CRIGHT) || (ch == '')) {
|
1995-01-10 05:00:37 +01:00
|
|
|
|
if (abspos == len)
|
1994-11-13 07:45:44 +01:00
|
|
|
|
beep();
|
1995-01-10 05:00:37 +01:00
|
|
|
|
else {
|
|
|
|
|
++abspos;
|
|
|
|
|
if (cursor++ == field->disp_width) {
|
|
|
|
|
++disp_off;
|
|
|
|
|
--cursor;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if ((isprint(ch)) && (len < field->width)){
|
|
|
|
|
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->disp_width) {
|
|
|
|
|
++disp_off;
|
|
|
|
|
--cursor;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
1994-11-13 07:45:44 +01:00
|
|
|
|
beep();
|
1995-01-10 05:00:37 +01:00
|
|
|
|
}
|
|
|
|
|
print_string(form->window, field->y, field->x,
|
|
|
|
|
field->disp_width, field->field.input->input+disp_off);
|
|
|
|
|
}
|
|
|
|
|
/* Not Reached */
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
1995-01-10 05:00:37 +01:00
|
|
|
|
exit_form(void)
|
1994-11-13 07:45:44 +01:00
|
|
|
|
{
|
1995-01-10 05:00:37 +01:00
|
|
|
|
done = F_DONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cancel_form(void)
|
|
|
|
|
{
|
|
|
|
|
done = F_CANCEL;
|
1994-11-13 07:45:44 +01:00
|
|
|
|
}
|