#include <sys/cdefs.h>
__RCSID("$NetBSD: driver.c,v 1.18 2013/11/26 01:17:00 christos Exp $");
#include <ctype.h>
#include "form.h"
#include "internals.h"
static int
traverse_form_links(FORM *form, int direction);
static int
traverse_form_links(FORM *form, int direction)
{
unsigned idx;
idx = form->cur_field;
do {
switch (direction) {
case REQ_LEFT_FIELD:
if (form->fields[idx]->left == NULL)
return E_REQUEST_DENIED;
idx = form->fields[idx]->left->index;
break;
case REQ_RIGHT_FIELD:
if (form->fields[idx]->right == NULL)
return E_REQUEST_DENIED;
idx = form->fields[idx]->right->index;
break;
case REQ_UP_FIELD:
if (form->fields[idx]->up == NULL)
return E_REQUEST_DENIED;
idx = form->fields[idx]->up->index;
break;
case REQ_DOWN_FIELD:
if (form->fields[idx]->down == NULL)
return E_REQUEST_DENIED;
idx = form->fields[idx]->down->index;
break;
default:
return E_REQUEST_DENIED;
}
if ((form->fields[idx]->opts & (O_ACTIVE | O_VISIBLE))
== (O_ACTIVE | O_VISIBLE)) {
form->cur_field = idx;
return E_OK;
}
} while (idx != form->cur_field);
return E_REQUEST_DENIED;
}
int
form_driver(FORM *form, int c)
{
FIELD *fieldp;
int update_page, update_field, old_field, old_page, status;
int start_field;
unsigned int pos;
if (form == NULL)
return E_BAD_ARGUMENT;
if ((form->fields == NULL) || (*(form->fields) == NULL))
return E_INVALID_FIELD;
if (form->posted != 1)
return E_NOT_POSTED;
if (form->in_init == 1)
return E_BAD_STATE;
old_field = start_field = form->cur_field;
fieldp = form->fields[form->cur_field];
update_page = update_field = 0;
status = E_OK;
if (c < REQ_MIN_REQUEST) {
if (isprint(c) || isblank(c)) {
do {
pos = fieldp->start_char + fieldp->row_xpos;
if ((fieldp->opts & O_EDIT) != O_EDIT)
return E_REQUEST_DENIED;
if ((status =
(_formi_add_char(fieldp, pos, c)))
== E_REQUEST_DENIED) {
if ((fieldp->opts & O_AUTOSKIP)
!= O_AUTOSKIP)
return E_REQUEST_DENIED;
status = form_driver(form,
REQ_NEXT_FIELD);
if (status != E_OK)
return status;
if (start_field == form->cur_field)
return E_REQUEST_DENIED;
old_field = form->cur_field;
fieldp = form->fields[form->cur_field];
status = _formi_add_char(fieldp,
fieldp->start_char
+ fieldp->cursor_xpos,
c);
} else if (status == E_INVALID_FIELD)
return status;
else if (status == E_NO_ROOM)
return E_REQUEST_DENIED;
}
while (status != E_OK);
update_field = (status == E_OK);
} else
return E_REQUEST_DENIED;
} else {
if (c > REQ_MAX_COMMAND)
return E_UNKNOWN_COMMAND;
if ((c >= REQ_NEXT_PAGE) && (c <= REQ_DOWN_FIELD)) {
if (_formi_validate_field(form) != E_OK)
return E_INVALID_FIELD;
if (form->field_term != NULL)
form->field_term(form);
if ((c <= REQ_LAST_PAGE) && (form->form_term != NULL))
form->form_term(form);
}
switch (c) {
case REQ_NEXT_PAGE:
if (form->page < form->max_page) {
old_page = form->page;
form->page++;
update_page = 1;
if (_formi_pos_first_field(form) != E_OK) {
form->page = old_page;
status = E_REQUEST_DENIED;
}
} else
status = E_REQUEST_DENIED;
break;
case REQ_PREV_PAGE:
if (form->page > 0) {
old_page = form->page;
form->page--;
update_page = 1;
if (_formi_pos_first_field(form) != E_OK) {
form->page = old_page;
status = E_REQUEST_DENIED;
}
} else
status = E_REQUEST_DENIED;
break;
case REQ_FIRST_PAGE:
old_page = form->page;
form->page = 0;
update_page = 1;
if (_formi_pos_first_field(form) != E_OK) {
form->page = old_page;
status = E_REQUEST_DENIED;
}
break;
case REQ_LAST_PAGE:
old_page = form->page;
form->page = form->max_page - 1;
update_page = 1;
if (_formi_pos_first_field(form) != E_OK) {
form->page = old_page;
status = E_REQUEST_DENIED;
}
break;
case REQ_NEXT_FIELD:
status = _formi_pos_new_field(form, _FORMI_FORWARD,
FALSE);
update_field = 1;
break;
case REQ_PREV_FIELD:
status = _formi_pos_new_field(form, _FORMI_BACKWARD,
FALSE);
update_field = 1;
break;
case REQ_FIRST_FIELD:
form->cur_field = 0;
update_field = 1;
break;
case REQ_LAST_FIELD:
form->cur_field = form->field_count - 1;
update_field = 1;
break;
case REQ_SNEXT_FIELD:
status = _formi_pos_new_field(form, _FORMI_FORWARD,
TRUE);
update_field = 1;
break;
case REQ_SPREV_FIELD:
status = _formi_pos_new_field(form, _FORMI_BACKWARD,
TRUE);
update_field = 1;
break;
case REQ_SFIRST_FIELD:
fieldp = TAILQ_FIRST(&form->sorted_fields);
form->cur_field = fieldp->index;
update_field = 1;
break;
case REQ_SLAST_FIELD:
fieldp = TAILQ_LAST(&form->sorted_fields,
_formi_sort_head);
form->cur_field = fieldp->index;
update_field = 1;
break;
case REQ_LEFT_FIELD:
case REQ_RIGHT_FIELD:
case REQ_UP_FIELD:
case REQ_DOWN_FIELD:
status = traverse_form_links(form, c);
update_field = 1;
break;
case REQ_DEL_PREV:
if ((form->opts & O_BS_OVERLOAD) == O_BS_OVERLOAD) {
if ((fieldp->start_char == 0) &&
(fieldp->start_line == 0) &&
(fieldp->row_xpos == 0)) {
update_field =
_formi_manipulate_field(form,
REQ_PREV_FIELD);
break;
}
}
case REQ_NEW_LINE:
if ((form->opts & O_NL_OVERLOAD) == O_NL_OVERLOAD) {
if ((fieldp->start_char == 0) &&
(fieldp->start_line == 0) &&
(fieldp->row_xpos == 0)) {
update_field =
_formi_manipulate_field(form,
REQ_NEXT_FIELD);
break;
}
}
case REQ_INS_CHAR:
case REQ_INS_LINE:
case REQ_DEL_CHAR:
case REQ_DEL_LINE:
case REQ_DEL_WORD:
case REQ_CLR_EOL:
case REQ_CLR_EOF:
case REQ_CLR_FIELD:
case REQ_OVL_MODE:
case REQ_INS_MODE:
if ((form->fields[form->cur_field]->opts & O_EDIT) != O_EDIT)
return E_REQUEST_DENIED;
case REQ_NEXT_CHAR:
case REQ_PREV_CHAR:
case REQ_NEXT_LINE:
case REQ_PREV_LINE:
case REQ_NEXT_WORD:
case REQ_PREV_WORD:
case REQ_BEG_FIELD:
case REQ_END_FIELD:
case REQ_BEG_LINE:
case REQ_END_LINE:
case REQ_LEFT_CHAR:
case REQ_RIGHT_CHAR:
case REQ_UP_CHAR:
case REQ_DOWN_CHAR:
case REQ_SCR_FLINE:
case REQ_SCR_BLINE:
case REQ_SCR_FPAGE:
case REQ_SCR_BPAGE:
case REQ_SCR_FHPAGE:
case REQ_SCR_BHPAGE:
case REQ_SCR_FCHAR:
case REQ_SCR_BCHAR:
case REQ_SCR_HFLINE:
case REQ_SCR_HBLINE:
case REQ_SCR_HFHALF:
case REQ_SCR_HBHALF:
update_field = _formi_manipulate_field(form, c);
break;
case REQ_VALIDATION:
return _formi_validate_field(form);
break;
case REQ_PREV_CHOICE:
case REQ_NEXT_CHOICE:
update_field = _formi_field_choice(form, c);
if (update_field == 1) {
_formi_init_field_xpos(fieldp);
fieldp->row_xpos = 0;
}
break;
default:
return E_UNKNOWN_COMMAND;
break;
}
}
if ((c >= REQ_NEXT_PAGE) && (c <= REQ_DOWN_FIELD)) {
if (form->field_init != NULL)
form->field_init(form);
if ((c <= REQ_LAST_PAGE) && (form->form_init != NULL))
form->form_init(form);
if (status != E_OK)
return status;
fieldp = form->fields[form->cur_field];
fieldp->start_char = 0;
fieldp->start_line = fieldp->alines;
fieldp->cur_line = fieldp->alines;
fieldp->row_xpos = 0;
fieldp->cursor_ypos = 0;
_formi_init_field_xpos(fieldp);
}
if (update_field < 0)
return update_field;
if (update_field == 1)
update_page |= _formi_update_field(form, old_field);
if (update_page == 1)
_formi_draw_page(form);
pos_form_cursor(form);
if ((update_page == 1) || (update_field == 1))
wrefresh(form->scrwin);
return E_OK;
}