1 /* $NetBSD: driver.c,v 1.18 2013/11/26 01:17:00 christos Exp $ */
4 * Copyright (c) 1998-1999 Brett Lymn
5 * (blymn@baea.com.au, brett_lymn@yahoo.com.au)
8 * This code has been donated to The NetBSD Foundation by the Author.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: driver.c,v 1.18 2013/11/26 01:17:00 christos Exp $");
37 #include "internals.h"
40 traverse_form_links(FORM
*form
, int direction
);
43 * Traverse the links of the current field in the given direction until
44 * either a active & visible field is found or we return to the current
45 * field. Direction is the REQ_{LEFT,RIGHT,UP,DOWN}_FIELD driver commands.
46 * The function returns E_OK if a valid field is found, E_REQUEST_DENIED
50 traverse_form_links(FORM
*form
, int direction
)
54 idx
= form
->cur_field
;
59 if (form
->fields
[idx
]->left
== NULL
)
60 return E_REQUEST_DENIED
;
61 idx
= form
->fields
[idx
]->left
->index
;
65 if (form
->fields
[idx
]->right
== NULL
)
66 return E_REQUEST_DENIED
;
67 idx
= form
->fields
[idx
]->right
->index
;
71 if (form
->fields
[idx
]->up
== NULL
)
72 return E_REQUEST_DENIED
;
73 idx
= form
->fields
[idx
]->up
->index
;
77 if (form
->fields
[idx
]->down
== NULL
)
78 return E_REQUEST_DENIED
;
79 idx
= form
->fields
[idx
]->down
->index
;
83 return E_REQUEST_DENIED
;
86 if ((form
->fields
[idx
]->opts
& (O_ACTIVE
| O_VISIBLE
))
87 == (O_ACTIVE
| O_VISIBLE
)) {
88 form
->cur_field
= idx
;
91 } while (idx
!= form
->cur_field
);
93 return E_REQUEST_DENIED
;
97 form_driver(FORM
*form
, int c
)
100 int update_page
, update_field
, old_field
, old_page
, status
;
105 return E_BAD_ARGUMENT
;
107 if ((form
->fields
== NULL
) || (*(form
->fields
) == NULL
))
108 return E_INVALID_FIELD
;
110 if (form
->posted
!= 1)
113 if (form
->in_init
== 1)
117 old_field
= start_field
= form
->cur_field
;
118 fieldp
= form
->fields
[form
->cur_field
];
119 update_page
= update_field
= 0;
122 if (c
< REQ_MIN_REQUEST
) {
123 if (isprint(c
) || isblank(c
)) {
125 pos
= fieldp
->start_char
+ fieldp
->row_xpos
;
127 /* check if we are allowed to edit this field */
128 if ((fieldp
->opts
& O_EDIT
) != O_EDIT
)
129 return E_REQUEST_DENIED
;
132 (_formi_add_char(fieldp
, pos
, c
)))
133 == E_REQUEST_DENIED
) {
136 * Need to check here if we
137 * want to autoskip. we
138 * call the form driver
139 * recursively to pos us on
140 * the next field and then
141 * we loop back to ensure
142 * the next field selected
143 * can have data added to it
145 if ((fieldp
->opts
& O_AUTOSKIP
)
147 return E_REQUEST_DENIED
;
148 status
= form_driver(form
,
154 * check if we have looped
155 * around all the fields.
156 * This can easily happen if
157 * all the fields are full.
159 if (start_field
== form
->cur_field
)
160 return E_REQUEST_DENIED
;
162 old_field
= form
->cur_field
;
163 fieldp
= form
->fields
[form
->cur_field
];
164 status
= _formi_add_char(fieldp
,
166 + fieldp
->cursor_xpos
,
168 } else if (status
== E_INVALID_FIELD
)
169 /* char failed validation, just
173 else if (status
== E_NO_ROOM
)
174 /* we will get this if the line
175 * wrapping fails. Deny the
178 return E_REQUEST_DENIED
;
180 while (status
!= E_OK
);
181 update_field
= (status
== E_OK
);
183 return E_REQUEST_DENIED
;
185 if (c
> REQ_MAX_COMMAND
)
186 return E_UNKNOWN_COMMAND
;
188 if ((c
>= REQ_NEXT_PAGE
) && (c
<= REQ_DOWN_FIELD
)) {
189 /* first check the field we are in is ok */
190 if (_formi_validate_field(form
) != E_OK
)
191 return E_INVALID_FIELD
;
193 if (form
->field_term
!= NULL
)
194 form
->field_term(form
);
197 * if we have a page movement then the form term
198 * needs to be called too
200 if ((c
<= REQ_LAST_PAGE
) && (form
->form_term
!= NULL
))
201 form
->form_term(form
);
207 if (form
->page
< form
->max_page
) {
208 old_page
= form
->page
;
211 if (_formi_pos_first_field(form
) != E_OK
) {
212 form
->page
= old_page
;
213 status
= E_REQUEST_DENIED
;
216 status
= E_REQUEST_DENIED
;
220 if (form
->page
> 0) {
221 old_page
= form
->page
;
224 if (_formi_pos_first_field(form
) != E_OK
) {
225 form
->page
= old_page
;
226 status
= E_REQUEST_DENIED
;
229 status
= E_REQUEST_DENIED
;
233 old_page
= form
->page
;
236 if (_formi_pos_first_field(form
) != E_OK
) {
237 form
->page
= old_page
;
238 status
= E_REQUEST_DENIED
;
243 old_page
= form
->page
;
244 form
->page
= form
->max_page
- 1;
246 if (_formi_pos_first_field(form
) != E_OK
) {
247 form
->page
= old_page
;
248 status
= E_REQUEST_DENIED
;
253 status
= _formi_pos_new_field(form
, _FORMI_FORWARD
,
259 status
= _formi_pos_new_field(form
, _FORMI_BACKWARD
,
264 case REQ_FIRST_FIELD
:
270 form
->cur_field
= form
->field_count
- 1;
274 case REQ_SNEXT_FIELD
:
275 status
= _formi_pos_new_field(form
, _FORMI_FORWARD
,
280 case REQ_SPREV_FIELD
:
281 status
= _formi_pos_new_field(form
, _FORMI_BACKWARD
,
286 case REQ_SFIRST_FIELD
:
287 fieldp
= TAILQ_FIRST(&form
->sorted_fields
);
288 form
->cur_field
= fieldp
->index
;
292 case REQ_SLAST_FIELD
:
293 fieldp
= TAILQ_LAST(&form
->sorted_fields
,
295 form
->cur_field
= fieldp
->index
;
300 * The up, down, left and right field traversals
301 * are rolled up into a single function, allow a
302 * fall through to that function.
305 case REQ_RIGHT_FIELD
:
308 status
= traverse_form_links(form
, c
);
312 /* the following commands modify the buffer, check if
313 this is allowed first before falling through. */
317 * need to check for the overloading of this
318 * request. If overload flag set and we are
319 * at the start of field this request turns
320 * into a previous field request. Otherwise
321 * fallthrough to the field handler.
323 if ((form
->opts
& O_BS_OVERLOAD
) == O_BS_OVERLOAD
) {
324 if ((fieldp
->start_char
== 0) &&
325 (fieldp
->start_line
== 0) &&
326 (fieldp
->row_xpos
== 0)) {
328 _formi_manipulate_field(form
,
337 * need to check for the overloading of this
338 * request. If overload flag set and we are
339 * at the start of field this request turns
340 * into a next field request. Otherwise
341 * fallthrough to the field handler.
343 if ((form
->opts
& O_NL_OVERLOAD
) == O_NL_OVERLOAD
) {
344 if ((fieldp
->start_char
== 0) &&
345 (fieldp
->start_line
== 0) &&
346 (fieldp
->row_xpos
== 0)) {
348 _formi_manipulate_field(form
,
365 /* check if we are allowed to edit the field and fall
368 if ((form
->fields
[form
->cur_field
]->opts
& O_EDIT
) != O_EDIT
)
369 return E_REQUEST_DENIED
;
371 /* the following manipulate the field contents, bundle
372 them into one function.... */
400 update_field
= _formi_manipulate_field(form
, c
);
404 return _formi_validate_field(form
);
408 case REQ_PREV_CHOICE
:
409 case REQ_NEXT_CHOICE
:
410 update_field
= _formi_field_choice(form
, c
);
411 /* reinit the cursor pos just in case */
412 if (update_field
== 1) {
413 _formi_init_field_xpos(fieldp
);
414 fieldp
->row_xpos
= 0;
418 default: /* should not need to do this, but.... */
419 return E_UNKNOWN_COMMAND
;
425 /* call the field and form init functions if required. */
426 if ((c
>= REQ_NEXT_PAGE
) && (c
<= REQ_DOWN_FIELD
)) {
427 if (form
->field_init
!= NULL
)
428 form
->field_init(form
);
431 * if we have a page movement then the form init
432 * needs to be called too
434 if ((c
<= REQ_LAST_PAGE
) && (form
->form_init
!= NULL
))
435 form
->form_init(form
);
438 * if there was an error just return now...
443 /* if we have no error, reset the various offsets */
444 fieldp
= form
->fields
[form
->cur_field
];
445 fieldp
->start_char
= 0;
446 fieldp
->start_line
= fieldp
->alines
;
447 fieldp
->cur_line
= fieldp
->alines
;
448 fieldp
->row_xpos
= 0;
449 fieldp
->cursor_ypos
= 0;
450 _formi_init_field_xpos(fieldp
);
453 if (update_field
< 0)
456 if (update_field
== 1)
457 update_page
|= _formi_update_field(form
, old_field
);
459 if (update_page
== 1)
460 _formi_draw_page(form
);
462 pos_form_cursor(form
);
464 if ((update_page
== 1) || (update_field
== 1))
465 wrefresh(form
->scrwin
);