15382d832SPeter Avalos /*
2*a8e38dc0SAntonio Huete Jimenez * $Id: formbox.c,v 1.106 2022/04/06 08:04:48 tom Exp $
35382d832SPeter Avalos *
45940c9abSDaniel Fojt * formbox.c -- implements the form (i.e., some pairs label/editbox)
55382d832SPeter Avalos *
6*a8e38dc0SAntonio Huete Jimenez * Copyright 2003-2021,2022 Thomas E. Dickey
75382d832SPeter Avalos *
85382d832SPeter Avalos * This program is free software; you can redistribute it and/or modify
95382d832SPeter Avalos * it under the terms of the GNU Lesser General Public License, version 2.1
105382d832SPeter Avalos * as published by the Free Software Foundation.
115382d832SPeter Avalos *
125382d832SPeter Avalos * This program is distributed in the hope that it will be useful, but
135382d832SPeter Avalos * WITHOUT ANY WARRANTY; without even the implied warranty of
145382d832SPeter Avalos * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
155382d832SPeter Avalos * Lesser General Public License for more details.
165382d832SPeter Avalos *
175382d832SPeter Avalos * You should have received a copy of the GNU Lesser General Public
185382d832SPeter Avalos * License along with this program; if not, write to
195382d832SPeter Avalos * Free Software Foundation, Inc.
205382d832SPeter Avalos * 51 Franklin St., Fifth Floor
215382d832SPeter Avalos * Boston, MA 02110, USA.
225382d832SPeter Avalos *
235382d832SPeter Avalos * This is adapted from source contributed by
245382d832SPeter Avalos * Valery Reznic (valery_reznic@users.sourceforge.net)
255382d832SPeter Avalos */
265382d832SPeter Avalos
27*a8e38dc0SAntonio Huete Jimenez #include <dlg_internals.h>
285382d832SPeter Avalos #include <dlg_keys.h>
295382d832SPeter Avalos
305382d832SPeter Avalos #define LLEN(n) ((n) * FORMBOX_TAGS)
315382d832SPeter Avalos
325382d832SPeter Avalos #define ItemName(i) items[LLEN(i) + 0]
335382d832SPeter Avalos #define ItemNameY(i) items[LLEN(i) + 1]
345382d832SPeter Avalos #define ItemNameX(i) items[LLEN(i) + 2]
355382d832SPeter Avalos #define ItemText(i) items[LLEN(i) + 3]
365382d832SPeter Avalos #define ItemTextY(i) items[LLEN(i) + 4]
375382d832SPeter Avalos #define ItemTextX(i) items[LLEN(i) + 5]
385382d832SPeter Avalos #define ItemTextFLen(i) items[LLEN(i) + 6]
395382d832SPeter Avalos #define ItemTextILen(i) items[LLEN(i) + 7]
405382d832SPeter Avalos #define ItemHelp(i) (dialog_vars.item_help ? items[LLEN(i) + 8] : dlg_strempty())
415382d832SPeter Avalos
425382d832SPeter Avalos static bool
is_readonly(DIALOG_FORMITEM * item)435382d832SPeter Avalos is_readonly(DIALOG_FORMITEM * item)
445382d832SPeter Avalos {
455382d832SPeter Avalos return ((item->type & 2) != 0) || (item->text_flen <= 0);
465382d832SPeter Avalos }
475382d832SPeter Avalos
485382d832SPeter Avalos static bool
is_hidden(DIALOG_FORMITEM * item)495382d832SPeter Avalos is_hidden(DIALOG_FORMITEM * item)
505382d832SPeter Avalos {
515382d832SPeter Avalos return ((item->type & 1) != 0);
525382d832SPeter Avalos }
535382d832SPeter Avalos
545382d832SPeter Avalos static bool
in_window(WINDOW * win,int scrollamt,int y)555382d832SPeter Avalos in_window(WINDOW *win, int scrollamt, int y)
565382d832SPeter Avalos {
575382d832SPeter Avalos return (y >= scrollamt && y - scrollamt < getmaxy(win));
585382d832SPeter Avalos }
595382d832SPeter Avalos
605382d832SPeter Avalos static bool
ok_move(WINDOW * win,int scrollamt,int y,int x)615382d832SPeter Avalos ok_move(WINDOW *win, int scrollamt, int y, int x)
625382d832SPeter Avalos {
635382d832SPeter Avalos return in_window(win, scrollamt, y)
645382d832SPeter Avalos && (wmove(win, y - scrollamt, x) != ERR);
655382d832SPeter Avalos }
665382d832SPeter Avalos
675382d832SPeter Avalos static void
move_past(WINDOW * win,int y,int x)685382d832SPeter Avalos move_past(WINDOW *win, int y, int x)
695382d832SPeter Avalos {
705382d832SPeter Avalos if (wmove(win, y, x) == ERR)
715382d832SPeter Avalos wmove(win, y, getmaxx(win) - 1);
725382d832SPeter Avalos }
735382d832SPeter Avalos
745382d832SPeter Avalos /*
755382d832SPeter Avalos * Print form item
765382d832SPeter Avalos */
775382d832SPeter Avalos static int
print_item(WINDOW * win,DIALOG_FORMITEM * item,int scrollamt,bool choice)785382d832SPeter Avalos print_item(WINDOW *win, DIALOG_FORMITEM * item, int scrollamt, bool choice)
795382d832SPeter Avalos {
805382d832SPeter Avalos int count = 0;
815382d832SPeter Avalos int len;
825382d832SPeter Avalos
835382d832SPeter Avalos if (ok_move(win, scrollamt, item->name_y, item->name_x)) {
845382d832SPeter Avalos len = item->name_len;
855382d832SPeter Avalos len = MIN(len, getmaxx(win) - item->name_x);
865382d832SPeter Avalos if (len > 0) {
875382d832SPeter Avalos dlg_show_string(win,
885382d832SPeter Avalos item->name,
895382d832SPeter Avalos 0,
905382d832SPeter Avalos menubox_attr,
915382d832SPeter Avalos item->name_y - scrollamt,
925382d832SPeter Avalos item->name_x,
935382d832SPeter Avalos len,
945382d832SPeter Avalos FALSE,
955382d832SPeter Avalos FALSE);
965382d832SPeter Avalos move_past(win, item->name_y - scrollamt, item->name_x + len);
975382d832SPeter Avalos count = 1;
985382d832SPeter Avalos }
995382d832SPeter Avalos }
1005382d832SPeter Avalos if (item->text_len && ok_move(win, scrollamt, item->text_y, item->text_x)) {
1015382d832SPeter Avalos chtype this_item_attribute;
1025382d832SPeter Avalos
1035382d832SPeter Avalos len = item->text_len;
1045382d832SPeter Avalos len = MIN(len, getmaxx(win) - item->text_x);
1055382d832SPeter Avalos
1065382d832SPeter Avalos if (!is_readonly(item)) {
1075382d832SPeter Avalos this_item_attribute = choice
1085382d832SPeter Avalos ? form_active_text_attr
1095382d832SPeter Avalos : form_text_attr;
1105382d832SPeter Avalos } else {
1115382d832SPeter Avalos this_item_attribute = form_item_readonly_attr;
1125382d832SPeter Avalos }
1135382d832SPeter Avalos
1145382d832SPeter Avalos if (len > 0) {
1155382d832SPeter Avalos dlg_show_string(win,
1165382d832SPeter Avalos item->text,
1175382d832SPeter Avalos 0,
1185382d832SPeter Avalos this_item_attribute,
1195382d832SPeter Avalos item->text_y - scrollamt,
1205382d832SPeter Avalos item->text_x,
1215382d832SPeter Avalos len,
1225382d832SPeter Avalos is_hidden(item),
1235382d832SPeter Avalos FALSE);
1245382d832SPeter Avalos move_past(win, item->text_y - scrollamt, item->text_x + len);
1255382d832SPeter Avalos count = 1;
1265382d832SPeter Avalos }
1275382d832SPeter Avalos }
1285382d832SPeter Avalos return count;
1295382d832SPeter Avalos }
1305382d832SPeter Avalos
1315382d832SPeter Avalos /*
1325382d832SPeter Avalos * Print the entire form.
1335382d832SPeter Avalos */
1345382d832SPeter Avalos static void
print_form(WINDOW * win,DIALOG_FORMITEM * item,int total,int scrollamt,int choice)1355382d832SPeter Avalos print_form(WINDOW *win, DIALOG_FORMITEM * item, int total, int scrollamt, int choice)
1365382d832SPeter Avalos {
1375382d832SPeter Avalos int n;
1385382d832SPeter Avalos int count = 0;
1395382d832SPeter Avalos
1405382d832SPeter Avalos for (n = 0; n < total; ++n) {
1415382d832SPeter Avalos count += print_item(win, item + n, scrollamt, n == choice);
1425382d832SPeter Avalos }
1435382d832SPeter Avalos if (count) {
1445382d832SPeter Avalos wbkgdset(win, menubox_attr | ' ');
1455382d832SPeter Avalos wclrtobot(win);
1465382d832SPeter Avalos (void) wnoutrefresh(win);
1475382d832SPeter Avalos }
1485382d832SPeter Avalos }
1495382d832SPeter Avalos
1505382d832SPeter Avalos static int
set_choice(DIALOG_FORMITEM item[],int choice,int item_no,bool * noneditable)1515382d832SPeter Avalos set_choice(DIALOG_FORMITEM item[], int choice, int item_no, bool * noneditable)
1525382d832SPeter Avalos {
1535382d832SPeter Avalos int result = -1;
1545382d832SPeter Avalos
1555382d832SPeter Avalos *noneditable = FALSE;
1565382d832SPeter Avalos if (!is_readonly(&item[choice])) {
1575382d832SPeter Avalos result = choice;
1585382d832SPeter Avalos } else {
1595940c9abSDaniel Fojt int i;
1605940c9abSDaniel Fojt
1615382d832SPeter Avalos for (i = 0; i < item_no; i++) {
1625382d832SPeter Avalos if (!is_readonly(&(item[i]))) {
1635382d832SPeter Avalos result = i;
1645382d832SPeter Avalos break;
1655382d832SPeter Avalos }
1665382d832SPeter Avalos }
1675382d832SPeter Avalos if (result < 0) {
1685382d832SPeter Avalos *noneditable = TRUE;
1695382d832SPeter Avalos result = 0;
1705382d832SPeter Avalos }
1715382d832SPeter Avalos }
1725382d832SPeter Avalos return result;
1735382d832SPeter Avalos }
1745382d832SPeter Avalos
1755382d832SPeter Avalos /*
1765382d832SPeter Avalos * Find the last y-value in the form.
1775382d832SPeter Avalos */
1785382d832SPeter Avalos static int
form_limit(DIALOG_FORMITEM item[])1795382d832SPeter Avalos form_limit(DIALOG_FORMITEM item[])
1805382d832SPeter Avalos {
1815382d832SPeter Avalos int n;
1825382d832SPeter Avalos int limit = 0;
1835382d832SPeter Avalos for (n = 0; item[n].name != 0; ++n) {
1845382d832SPeter Avalos if (limit < item[n].name_y)
1855382d832SPeter Avalos limit = item[n].name_y;
1865382d832SPeter Avalos if (limit < item[n].text_y)
1875382d832SPeter Avalos limit = item[n].text_y;
1885382d832SPeter Avalos }
1895382d832SPeter Avalos return limit;
1905382d832SPeter Avalos }
1915382d832SPeter Avalos
1925382d832SPeter Avalos static int
is_first_field(DIALOG_FORMITEM item[],int choice)1935382d832SPeter Avalos is_first_field(DIALOG_FORMITEM item[], int choice)
1945382d832SPeter Avalos {
1955382d832SPeter Avalos int count = 0;
1965382d832SPeter Avalos while (choice >= 0) {
1975382d832SPeter Avalos if (item[choice].text_flen > 0) {
1985382d832SPeter Avalos ++count;
1995382d832SPeter Avalos }
2005382d832SPeter Avalos --choice;
2015382d832SPeter Avalos }
2025382d832SPeter Avalos
2035382d832SPeter Avalos return (count == 1);
2045382d832SPeter Avalos }
2055382d832SPeter Avalos
2065382d832SPeter Avalos static int
is_last_field(DIALOG_FORMITEM item[],int choice,int item_no)2075382d832SPeter Avalos is_last_field(DIALOG_FORMITEM item[], int choice, int item_no)
2085382d832SPeter Avalos {
2095382d832SPeter Avalos int count = 0;
2105382d832SPeter Avalos while (choice < item_no) {
2115382d832SPeter Avalos if (item[choice].text_flen > 0) {
2125382d832SPeter Avalos ++count;
2135382d832SPeter Avalos }
2145382d832SPeter Avalos ++choice;
2155382d832SPeter Avalos }
2165382d832SPeter Avalos
2175382d832SPeter Avalos return (count == 1);
2185382d832SPeter Avalos }
2195382d832SPeter Avalos
2205382d832SPeter Avalos /*
2215382d832SPeter Avalos * Tab to the next field.
2225382d832SPeter Avalos */
2235382d832SPeter Avalos static bool
tab_next(WINDOW * win,DIALOG_FORMITEM item[],int item_no,int stepsize,int * choice,int * scrollamt)2245382d832SPeter Avalos tab_next(WINDOW *win,
2255382d832SPeter Avalos DIALOG_FORMITEM item[],
2265382d832SPeter Avalos int item_no,
2275382d832SPeter Avalos int stepsize,
2285382d832SPeter Avalos int *choice,
2295382d832SPeter Avalos int *scrollamt)
2305382d832SPeter Avalos {
2315382d832SPeter Avalos int old_choice = *choice;
2325382d832SPeter Avalos int old_scroll = *scrollamt;
2335382d832SPeter Avalos bool wrapped = FALSE;
2345382d832SPeter Avalos
2355382d832SPeter Avalos do {
2365382d832SPeter Avalos do {
2375382d832SPeter Avalos *choice += stepsize;
2385382d832SPeter Avalos if (*choice < 0) {
2395382d832SPeter Avalos *choice = item_no - 1;
2405382d832SPeter Avalos wrapped = TRUE;
2415382d832SPeter Avalos } else if (*choice >= item_no) {
2425382d832SPeter Avalos *choice = 0;
2435382d832SPeter Avalos wrapped = TRUE;
2445382d832SPeter Avalos }
2455382d832SPeter Avalos } while ((*choice != old_choice) && is_readonly(&(item[*choice])));
2465382d832SPeter Avalos
2475382d832SPeter Avalos if (item[*choice].text_flen > 0) {
2485382d832SPeter Avalos int lo = MIN(item[*choice].name_y, item[*choice].text_y);
2495382d832SPeter Avalos int hi = MAX(item[*choice].name_y, item[*choice].text_y);
2505382d832SPeter Avalos
2515382d832SPeter Avalos if (old_choice == *choice)
2525382d832SPeter Avalos break;
2535382d832SPeter Avalos print_item(win, item + old_choice, *scrollamt, FALSE);
2545382d832SPeter Avalos
2555382d832SPeter Avalos if (*scrollamt < lo + 1 - getmaxy(win))
2565382d832SPeter Avalos *scrollamt = lo + 1 - getmaxy(win);
2575382d832SPeter Avalos if (*scrollamt > hi)
2585382d832SPeter Avalos *scrollamt = hi;
2595382d832SPeter Avalos /*
2605382d832SPeter Avalos * If we have to scroll to show a wrap-around, it does get
2615382d832SPeter Avalos * confusing. Just give up rather than scroll. Tab'ing to the
2625382d832SPeter Avalos * next field in a multi-column form is a different matter. Scroll
2635382d832SPeter Avalos * for that.
2645382d832SPeter Avalos */
2655382d832SPeter Avalos if (*scrollamt != old_scroll) {
2665382d832SPeter Avalos if (wrapped) {
2675382d832SPeter Avalos beep();
2685382d832SPeter Avalos *scrollamt = old_scroll;
2695382d832SPeter Avalos *choice = old_choice;
2705382d832SPeter Avalos } else {
2715382d832SPeter Avalos scrollok(win, TRUE);
2725382d832SPeter Avalos wscrl(win, *scrollamt - old_scroll);
2735382d832SPeter Avalos scrollok(win, FALSE);
2745382d832SPeter Avalos }
2755382d832SPeter Avalos }
2765382d832SPeter Avalos break;
2775382d832SPeter Avalos }
2785382d832SPeter Avalos } while (*choice != old_choice);
2795382d832SPeter Avalos
2805382d832SPeter Avalos return (old_choice != *choice) || (old_scroll != *scrollamt);
2815382d832SPeter Avalos }
2825382d832SPeter Avalos
2835382d832SPeter Avalos /*
2845382d832SPeter Avalos * Scroll to the next page, putting the choice at the first editable field
2855382d832SPeter Avalos * in that page. Note that fields are not necessarily in top-to-bottom order,
2865382d832SPeter Avalos * nor is there necessarily a field on each row of the window.
2875382d832SPeter Avalos */
2885382d832SPeter Avalos static bool
scroll_next(WINDOW * win,DIALOG_FORMITEM item[],int stepsize,int * choice,int * scrollamt)2895382d832SPeter Avalos scroll_next(WINDOW *win, DIALOG_FORMITEM item[], int stepsize, int *choice, int *scrollamt)
2905382d832SPeter Avalos {
2915382d832SPeter Avalos bool result = TRUE;
2925382d832SPeter Avalos int old_choice = *choice;
2935382d832SPeter Avalos int old_scroll = *scrollamt;
2945382d832SPeter Avalos int old_row = MIN(item[old_choice].text_y, item[old_choice].name_y);
2955382d832SPeter Avalos int target = old_scroll + stepsize;
2965382d832SPeter Avalos
2975382d832SPeter Avalos if (stepsize < 0) {
2985382d832SPeter Avalos if (old_row != old_scroll)
2995382d832SPeter Avalos target = old_scroll;
3005382d832SPeter Avalos else
3015382d832SPeter Avalos target = old_scroll + stepsize;
3025382d832SPeter Avalos if (target < 0) {
3035382d832SPeter Avalos result = FALSE;
3045382d832SPeter Avalos }
3055382d832SPeter Avalos } else {
3065382d832SPeter Avalos if (target > form_limit(item)) {
3075382d832SPeter Avalos result = FALSE;
3085382d832SPeter Avalos }
3095382d832SPeter Avalos }
3105382d832SPeter Avalos
3115382d832SPeter Avalos if (result) {
3125940c9abSDaniel Fojt int n;
3135940c9abSDaniel Fojt
3145382d832SPeter Avalos for (n = 0; item[n].name != 0; ++n) {
3155382d832SPeter Avalos if (item[n].text_flen > 0) {
3165382d832SPeter Avalos int new_row = MIN(item[n].text_y, item[n].name_y);
3175382d832SPeter Avalos if (abs(new_row - target) < abs(old_row - target)) {
3185382d832SPeter Avalos old_row = new_row;
3195382d832SPeter Avalos *choice = n;
3205382d832SPeter Avalos }
3215382d832SPeter Avalos }
3225382d832SPeter Avalos }
3235382d832SPeter Avalos
3245382d832SPeter Avalos if (old_choice != *choice)
3255382d832SPeter Avalos print_item(win, item + old_choice, *scrollamt, FALSE);
3265382d832SPeter Avalos
3275382d832SPeter Avalos *scrollamt = *choice;
3285382d832SPeter Avalos if (*scrollamt != old_scroll) {
3295382d832SPeter Avalos scrollok(win, TRUE);
3305382d832SPeter Avalos wscrl(win, *scrollamt - old_scroll);
3315382d832SPeter Avalos scrollok(win, FALSE);
3325382d832SPeter Avalos }
3335382d832SPeter Avalos result = (old_choice != *choice) || (old_scroll != *scrollamt);
3345382d832SPeter Avalos }
3355382d832SPeter Avalos if (!result)
3365382d832SPeter Avalos beep();
3375382d832SPeter Avalos return result;
3385382d832SPeter Avalos }
3395382d832SPeter Avalos
3405382d832SPeter Avalos /*
3415382d832SPeter Avalos * Do a sanity check on the field length, and return the "right" value.
3425382d832SPeter Avalos */
3435382d832SPeter Avalos static int
real_length(DIALOG_FORMITEM * item)3445382d832SPeter Avalos real_length(DIALOG_FORMITEM * item)
3455382d832SPeter Avalos {
3465382d832SPeter Avalos return (item->text_flen > 0
3475382d832SPeter Avalos ? item->text_flen
3485382d832SPeter Avalos : (item->text_flen < 0
3495382d832SPeter Avalos ? -item->text_flen
3505382d832SPeter Avalos : item->text_len));
3515382d832SPeter Avalos }
3525382d832SPeter Avalos
3535382d832SPeter Avalos /*
3545382d832SPeter Avalos * Compute the form size, setup field buffers.
3555382d832SPeter Avalos */
3565382d832SPeter Avalos static void
make_FORM_ELTs(DIALOG_FORMITEM * item,int item_no,int * min_height,int * min_width)3575382d832SPeter Avalos make_FORM_ELTs(DIALOG_FORMITEM * item,
3585382d832SPeter Avalos int item_no,
3595382d832SPeter Avalos int *min_height,
3605382d832SPeter Avalos int *min_width)
3615382d832SPeter Avalos {
3625382d832SPeter Avalos int i;
3635382d832SPeter Avalos int min_w = 0;
3645382d832SPeter Avalos int min_h = 0;
3655382d832SPeter Avalos
3665382d832SPeter Avalos for (i = 0; i < item_no; ++i) {
3675382d832SPeter Avalos int real_len = real_length(item + i);
3685382d832SPeter Avalos
3695382d832SPeter Avalos /*
3705382d832SPeter Avalos * Special value '0' for text_flen: no input allowed
3715382d832SPeter Avalos * Special value '0' for text_ilen: 'be the same as text_flen'
3725382d832SPeter Avalos */
3735382d832SPeter Avalos if (item[i].text_ilen == 0)
3745382d832SPeter Avalos item[i].text_ilen = real_len;
3755382d832SPeter Avalos
3765382d832SPeter Avalos min_h = MAX(min_h, item[i].name_y + 1);
3775382d832SPeter Avalos min_h = MAX(min_h, item[i].text_y + 1);
3785382d832SPeter Avalos min_w = MAX(min_w, item[i].name_x + 1 + item[i].name_len);
3795382d832SPeter Avalos min_w = MAX(min_w, item[i].text_x + 1 + real_len);
3805382d832SPeter Avalos
3815382d832SPeter Avalos item[i].text_len = real_length(item + i);
3825382d832SPeter Avalos
3835382d832SPeter Avalos /*
3845382d832SPeter Avalos * We do not know the actual length of .text, so we allocate it here
3855382d832SPeter Avalos * to ensure it is big enough.
3865382d832SPeter Avalos */
3875382d832SPeter Avalos if (item[i].text_flen > 0) {
3885382d832SPeter Avalos int max_len = dlg_max_input(MAX(item[i].text_ilen + 1, MAX_LEN));
3895382d832SPeter Avalos char *old_text = item[i].text;
3905382d832SPeter Avalos
3915382d832SPeter Avalos item[i].text = dlg_malloc(char, (size_t) max_len + 1);
3925382d832SPeter Avalos assert_ptr(item[i].text, "make_FORM_ELTs");
3935382d832SPeter Avalos
3945382d832SPeter Avalos sprintf(item[i].text, "%.*s", item[i].text_ilen, old_text);
3955382d832SPeter Avalos
3965382d832SPeter Avalos if (item[i].text_free) {
3975382d832SPeter Avalos free(old_text);
3985382d832SPeter Avalos }
3995382d832SPeter Avalos item[i].text_free = TRUE;
4005382d832SPeter Avalos }
4015382d832SPeter Avalos }
4025382d832SPeter Avalos
4035382d832SPeter Avalos *min_height = min_h;
4045382d832SPeter Avalos *min_width = min_w;
4055382d832SPeter Avalos }
4065382d832SPeter Avalos
4075382d832SPeter Avalos int
dlg_default_formitem(DIALOG_FORMITEM * items)4085382d832SPeter Avalos dlg_default_formitem(DIALOG_FORMITEM * items)
4095382d832SPeter Avalos {
4105382d832SPeter Avalos int result = 0;
4115382d832SPeter Avalos
4125382d832SPeter Avalos if (dialog_vars.default_item != 0) {
4135382d832SPeter Avalos int count = 0;
4145382d832SPeter Avalos while (items->name != 0) {
4155382d832SPeter Avalos if (!strcmp(dialog_vars.default_item, items->name)) {
4165382d832SPeter Avalos result = count;
4175382d832SPeter Avalos break;
4185382d832SPeter Avalos }
4195382d832SPeter Avalos ++items;
4205382d832SPeter Avalos count++;
4215382d832SPeter Avalos }
4225382d832SPeter Avalos }
4235382d832SPeter Avalos return result;
4245382d832SPeter Avalos }
4255382d832SPeter Avalos
4265382d832SPeter Avalos #define sTEXT -1
4275382d832SPeter Avalos
4285382d832SPeter Avalos static int
next_valid_buttonindex(int state,int extra,bool non_editable)4295382d832SPeter Avalos next_valid_buttonindex(int state, int extra, bool non_editable)
4305382d832SPeter Avalos {
4315382d832SPeter Avalos state = dlg_next_ok_buttonindex(state, extra);
4325382d832SPeter Avalos while (non_editable && state == sTEXT)
4335382d832SPeter Avalos state = dlg_next_ok_buttonindex(state, sTEXT);
4345382d832SPeter Avalos return state;
4355382d832SPeter Avalos }
4365382d832SPeter Avalos
4375382d832SPeter Avalos static int
prev_valid_buttonindex(int state,int extra,bool non_editable)4385382d832SPeter Avalos prev_valid_buttonindex(int state, int extra, bool non_editable)
4395382d832SPeter Avalos {
4405382d832SPeter Avalos state = dlg_prev_ok_buttonindex(state, extra);
4415382d832SPeter Avalos while (non_editable && state == sTEXT)
4425382d832SPeter Avalos state = dlg_prev_ok_buttonindex(state, sTEXT);
4435382d832SPeter Avalos return state;
4445382d832SPeter Avalos }
4455382d832SPeter Avalos
4465382d832SPeter Avalos #define NAVIGATE_BINDINGS \
4475382d832SPeter Avalos DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), \
4485382d832SPeter Avalos DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), \
4495382d832SPeter Avalos DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ), \
4505382d832SPeter Avalos DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ), \
4515940c9abSDaniel Fojt DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_RIGHT ), \
4525382d832SPeter Avalos DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_NEXT ), \
4535382d832SPeter Avalos DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ), \
4545382d832SPeter Avalos DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_PREVIOUS ), \
4555940c9abSDaniel Fojt DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_LEFT ), \
4565382d832SPeter Avalos DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ), \
4575382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), \
4585382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE )
4595382d832SPeter Avalos /*
4605382d832SPeter Avalos * Display a form for entering a number of fields
4615382d832SPeter Avalos */
4625382d832SPeter Avalos int
dlg_form(const char * title,const char * cprompt,int height,int width,int form_height,int item_no,DIALOG_FORMITEM * items,int * current_item)4635382d832SPeter Avalos dlg_form(const char *title,
4645382d832SPeter Avalos const char *cprompt,
4655382d832SPeter Avalos int height,
4665382d832SPeter Avalos int width,
4675382d832SPeter Avalos int form_height,
4685382d832SPeter Avalos int item_no,
4695382d832SPeter Avalos DIALOG_FORMITEM * items,
4705382d832SPeter Avalos int *current_item)
4715382d832SPeter Avalos {
4725382d832SPeter Avalos /* *INDENT-OFF* */
4735382d832SPeter Avalos static DLG_KEYS_BINDING binding[] = {
4745382d832SPeter Avalos HELPKEY_BINDINGS,
4755382d832SPeter Avalos ENTERKEY_BINDINGS,
4765382d832SPeter Avalos NAVIGATE_BINDINGS,
4775940c9abSDaniel Fojt TOGGLEKEY_BINDINGS,
4785382d832SPeter Avalos END_KEYS_BINDING
4795382d832SPeter Avalos };
4805382d832SPeter Avalos static DLG_KEYS_BINDING binding2[] = {
4815382d832SPeter Avalos INPUTSTR_BINDINGS,
4825382d832SPeter Avalos HELPKEY_BINDINGS,
4835382d832SPeter Avalos ENTERKEY_BINDINGS,
4845382d832SPeter Avalos NAVIGATE_BINDINGS,
4855940c9abSDaniel Fojt /* no TOGGLEKEY_BINDINGS, since that includes space... */
4865382d832SPeter Avalos END_KEYS_BINDING
4875382d832SPeter Avalos };
4885382d832SPeter Avalos /* *INDENT-ON* */
4895382d832SPeter Avalos
4905382d832SPeter Avalos #ifdef KEY_RESIZE
4915382d832SPeter Avalos int old_height = height;
4925382d832SPeter Avalos int old_width = width;
493*a8e38dc0SAntonio Huete Jimenez int old_fhigh = form_height;
4945382d832SPeter Avalos #endif
4955382d832SPeter Avalos
4965382d832SPeter Avalos int form_width;
4975940c9abSDaniel Fojt bool first = TRUE;
4985940c9abSDaniel Fojt bool first_trace = TRUE;
4995382d832SPeter Avalos int chr_offset = 0;
5005940c9abSDaniel Fojt int state = (dialog_vars.default_button >= 0
5015940c9abSDaniel Fojt ? dlg_default_button()
5025940c9abSDaniel Fojt : sTEXT);
5035382d832SPeter Avalos int x, y, cur_x, cur_y, box_x, box_y;
5045382d832SPeter Avalos int code;
5055382d832SPeter Avalos int fkey;
5065382d832SPeter Avalos int choice = dlg_default_formitem(items);
5075382d832SPeter Avalos int new_choice, new_scroll;
5085382d832SPeter Avalos int scrollamt = 0;
5095382d832SPeter Avalos int result = DLG_EXIT_UNKNOWN;
5105382d832SPeter Avalos int min_width = 0, min_height = 0;
5115382d832SPeter Avalos bool was_autosize = (height == 0 || width == 0);
5125382d832SPeter Avalos bool show_buttons = FALSE;
5135382d832SPeter Avalos bool scroll_changed = FALSE;
5145382d832SPeter Avalos bool field_changed = FALSE;
5155382d832SPeter Avalos bool non_editable = FALSE;
5165382d832SPeter Avalos WINDOW *dialog, *form;
5175940c9abSDaniel Fojt char *prompt;
5185382d832SPeter Avalos const char **buttons = dlg_ok_labels();
5195382d832SPeter Avalos DIALOG_FORMITEM *current;
5205382d832SPeter Avalos
5215940c9abSDaniel Fojt DLG_TRACE(("# %sform args:\n", (dialog_vars.formitem_type
5225940c9abSDaniel Fojt ? "password"
5235940c9abSDaniel Fojt : "")));
5245940c9abSDaniel Fojt DLG_TRACE2S("title", title);
5255940c9abSDaniel Fojt DLG_TRACE2S("message", cprompt);
5265940c9abSDaniel Fojt DLG_TRACE2N("height", height);
5275940c9abSDaniel Fojt DLG_TRACE2N("width", width);
5285940c9abSDaniel Fojt DLG_TRACE2N("lheight", form_height);
5295940c9abSDaniel Fojt DLG_TRACE2N("llength", item_no);
5305940c9abSDaniel Fojt /* FIXME dump the items[][] too */
5315940c9abSDaniel Fojt DLG_TRACE2N("current", *current_item);
5325940c9abSDaniel Fojt
5335382d832SPeter Avalos make_FORM_ELTs(items, item_no, &min_height, &min_width);
5345382d832SPeter Avalos dlg_button_layout(buttons, &min_width);
5355382d832SPeter Avalos dlg_does_output();
5365382d832SPeter Avalos
5375382d832SPeter Avalos #ifdef KEY_RESIZE
5385382d832SPeter Avalos retry:
5395382d832SPeter Avalos #endif
5405382d832SPeter Avalos
5415940c9abSDaniel Fojt prompt = dlg_strclone(cprompt);
5425940c9abSDaniel Fojt dlg_tab_correct_str(prompt);
5435382d832SPeter Avalos dlg_auto_size(title, prompt, &height, &width,
5445382d832SPeter Avalos 1 + 3 * MARGIN,
5455382d832SPeter Avalos MAX(26, 2 + min_width));
5465382d832SPeter Avalos
5475382d832SPeter Avalos if (form_height == 0)
5485382d832SPeter Avalos form_height = min_height;
5495382d832SPeter Avalos
5505382d832SPeter Avalos if (was_autosize) {
5515382d832SPeter Avalos form_height = MIN(SLINES - height, form_height);
5525382d832SPeter Avalos height += form_height;
5535382d832SPeter Avalos } else {
5545382d832SPeter Avalos int thigh = 0;
5555382d832SPeter Avalos int twide = 0;
5565382d832SPeter Avalos dlg_auto_size(title, prompt, &thigh, &twide, 0, width);
5575382d832SPeter Avalos thigh = SLINES - (height - (thigh + 1 + 3 * MARGIN));
5585382d832SPeter Avalos form_height = MIN(thigh, form_height);
5595382d832SPeter Avalos }
5605382d832SPeter Avalos
5615382d832SPeter Avalos dlg_print_size(height, width);
5625382d832SPeter Avalos dlg_ctl_size(height, width);
5635382d832SPeter Avalos
5645382d832SPeter Avalos x = dlg_box_x_ordinate(width);
5655382d832SPeter Avalos y = dlg_box_y_ordinate(height);
5665382d832SPeter Avalos
5675382d832SPeter Avalos dialog = dlg_new_window(height, width, y, x);
5685382d832SPeter Avalos dlg_register_window(dialog, "formbox", binding);
5695382d832SPeter Avalos dlg_register_buttons(dialog, "formbox", buttons);
5705382d832SPeter Avalos
5715382d832SPeter Avalos dlg_mouse_setbase(x, y);
5725382d832SPeter Avalos
5735382d832SPeter Avalos dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
5745382d832SPeter Avalos dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
5755382d832SPeter Avalos dlg_draw_title(dialog, title);
5765382d832SPeter Avalos
5775940c9abSDaniel Fojt dlg_attrset(dialog, dialog_attr);
5785382d832SPeter Avalos dlg_print_autowrap(dialog, prompt, height, width);
5795382d832SPeter Avalos
5805382d832SPeter Avalos form_width = width - 6;
5815382d832SPeter Avalos getyx(dialog, cur_y, cur_x);
5825382d832SPeter Avalos (void) cur_x;
5835382d832SPeter Avalos box_y = cur_y + 1;
5845382d832SPeter Avalos box_x = (width - form_width) / 2 - 1;
5855382d832SPeter Avalos
5865382d832SPeter Avalos /* create new window for the form */
5875382d832SPeter Avalos form = dlg_sub_window(dialog, form_height, form_width, y + box_y + 1,
5885382d832SPeter Avalos x + box_x + 1);
5895382d832SPeter Avalos dlg_register_window(form, "formfield", binding2);
5905382d832SPeter Avalos
5915382d832SPeter Avalos /* draw a box around the form items */
5925382d832SPeter Avalos dlg_draw_box(dialog, box_y, box_x, form_height + 2, form_width + 2,
5935382d832SPeter Avalos menubox_border_attr, menubox_border2_attr);
5945382d832SPeter Avalos
5955382d832SPeter Avalos /* register the new window, along with its borders */
5965382d832SPeter Avalos dlg_mouse_mkbigregion(getbegy(form) - getbegy(dialog),
5975382d832SPeter Avalos getbegx(form) - getbegx(dialog),
5985382d832SPeter Avalos getmaxy(form),
5995382d832SPeter Avalos getmaxx(form),
6005382d832SPeter Avalos KEY_MAX, 1, 1, 3 /* by cells */ );
6015382d832SPeter Avalos
6025382d832SPeter Avalos show_buttons = TRUE;
6035382d832SPeter Avalos scroll_changed = TRUE;
6045382d832SPeter Avalos
6055382d832SPeter Avalos choice = set_choice(items, choice, item_no, &non_editable);
6065382d832SPeter Avalos current = &items[choice];
6075382d832SPeter Avalos if (non_editable)
6085382d832SPeter Avalos state = next_valid_buttonindex(state, sTEXT, non_editable);
6095382d832SPeter Avalos
6105382d832SPeter Avalos while (result == DLG_EXIT_UNKNOWN) {
6115382d832SPeter Avalos int edit = FALSE;
6125940c9abSDaniel Fojt int key;
6135382d832SPeter Avalos
6145382d832SPeter Avalos if (scroll_changed) {
6155382d832SPeter Avalos print_form(form, items, item_no, scrollamt, choice);
6165382d832SPeter Avalos dlg_draw_scrollbar(dialog,
6175382d832SPeter Avalos scrollamt,
6185382d832SPeter Avalos scrollamt,
6195382d832SPeter Avalos scrollamt + form_height + 1,
6205382d832SPeter Avalos min_height,
6215382d832SPeter Avalos box_x + 1,
6225382d832SPeter Avalos box_x + form_width,
6235382d832SPeter Avalos box_y,
6245382d832SPeter Avalos box_y + form_height + 1,
6255382d832SPeter Avalos menubox_border2_attr,
6265382d832SPeter Avalos menubox_border_attr);
6275382d832SPeter Avalos scroll_changed = FALSE;
6285382d832SPeter Avalos }
6295382d832SPeter Avalos
6305382d832SPeter Avalos if (show_buttons) {
6315382d832SPeter Avalos dlg_item_help("");
6325382d832SPeter Avalos dlg_draw_buttons(dialog, height - 2, 0, buttons,
6335382d832SPeter Avalos ((state < 0)
6345382d832SPeter Avalos ? 1000 /* no such button, not highlighted */
6355382d832SPeter Avalos : state),
6365382d832SPeter Avalos FALSE, width);
6375382d832SPeter Avalos show_buttons = FALSE;
6385382d832SPeter Avalos }
6395382d832SPeter Avalos
6405382d832SPeter Avalos if (first_trace) {
6415382d832SPeter Avalos first_trace = FALSE;
6425382d832SPeter Avalos dlg_trace_win(dialog);
6435382d832SPeter Avalos }
6445382d832SPeter Avalos
6455382d832SPeter Avalos if (field_changed || state == sTEXT) {
6465382d832SPeter Avalos if (field_changed)
6475382d832SPeter Avalos chr_offset = 0;
6485382d832SPeter Avalos current = &items[choice];
6495382d832SPeter Avalos dlg_item_help(current->help);
6505382d832SPeter Avalos dlg_show_string(form, current->text, chr_offset,
6515382d832SPeter Avalos form_active_text_attr,
6525382d832SPeter Avalos current->text_y - scrollamt,
6535382d832SPeter Avalos current->text_x,
6545382d832SPeter Avalos current->text_len,
6555382d832SPeter Avalos is_hidden(current), first);
6565382d832SPeter Avalos wsyncup(form);
6575382d832SPeter Avalos wcursyncup(form);
6585382d832SPeter Avalos field_changed = FALSE;
6595382d832SPeter Avalos }
6605382d832SPeter Avalos
6615382d832SPeter Avalos key = dlg_mouse_wgetch((state == sTEXT) ? form : dialog, &fkey);
6625940c9abSDaniel Fojt if (dlg_result_key(key, fkey, &result)) {
6635382d832SPeter Avalos break;
6645940c9abSDaniel Fojt }
6655382d832SPeter Avalos
6665382d832SPeter Avalos /* handle non-functionkeys */
6675382d832SPeter Avalos if (!fkey) {
6685382d832SPeter Avalos if (state != sTEXT) {
6695382d832SPeter Avalos code = dlg_char_to_button(key, buttons);
6705382d832SPeter Avalos if (code >= 0) {
6715382d832SPeter Avalos dlg_del_window(dialog);
6725382d832SPeter Avalos result = dlg_ok_buttoncode(code);
6735382d832SPeter Avalos continue;
6745382d832SPeter Avalos }
6755382d832SPeter Avalos }
6765382d832SPeter Avalos }
6775382d832SPeter Avalos
6785382d832SPeter Avalos /* handle functionkeys */
6795382d832SPeter Avalos if (fkey) {
6805382d832SPeter Avalos bool do_scroll = FALSE;
6815382d832SPeter Avalos bool do_tab = FALSE;
6825382d832SPeter Avalos int move_by = 0;
6835382d832SPeter Avalos
6845382d832SPeter Avalos switch (key) {
6855382d832SPeter Avalos case DLGK_MOUSE(KEY_PPAGE):
6865382d832SPeter Avalos case DLGK_PAGE_PREV:
6875382d832SPeter Avalos do_scroll = TRUE;
6885382d832SPeter Avalos move_by = -form_height;
6895382d832SPeter Avalos break;
6905382d832SPeter Avalos
6915382d832SPeter Avalos case DLGK_MOUSE(KEY_NPAGE):
6925382d832SPeter Avalos case DLGK_PAGE_NEXT:
6935382d832SPeter Avalos do_scroll = TRUE;
6945382d832SPeter Avalos move_by = form_height;
6955382d832SPeter Avalos break;
6965382d832SPeter Avalos
6975940c9abSDaniel Fojt case DLGK_TOGGLE:
6985382d832SPeter Avalos case DLGK_ENTER:
6995382d832SPeter Avalos dlg_del_window(dialog);
7005382d832SPeter Avalos result = (state >= 0) ? dlg_enter_buttoncode(state) : DLG_EXIT_OK;
7015382d832SPeter Avalos continue;
702*a8e38dc0SAntonio Huete Jimenez case DLGK_LEAVE:
703*a8e38dc0SAntonio Huete Jimenez if (state >= 0)
704*a8e38dc0SAntonio Huete Jimenez result = dlg_ok_buttoncode(state);
705*a8e38dc0SAntonio Huete Jimenez break;
7065382d832SPeter Avalos
7075382d832SPeter Avalos case DLGK_GRID_LEFT:
7085382d832SPeter Avalos if (state == sTEXT)
7095382d832SPeter Avalos break;
7105382d832SPeter Avalos /* FALLTHRU */
7115382d832SPeter Avalos case DLGK_ITEM_PREV:
7125382d832SPeter Avalos if (state == sTEXT) {
7135382d832SPeter Avalos do_tab = TRUE;
7145382d832SPeter Avalos move_by = -1;
7155382d832SPeter Avalos break;
7165382d832SPeter Avalos } else {
7175382d832SPeter Avalos state = prev_valid_buttonindex(state, 0, non_editable);
7185382d832SPeter Avalos show_buttons = TRUE;
7195382d832SPeter Avalos continue;
7205382d832SPeter Avalos }
7215382d832SPeter Avalos
7225382d832SPeter Avalos case DLGK_FORM_PREV:
7235382d832SPeter Avalos if (state == sTEXT && !is_first_field(items, choice)) {
7245382d832SPeter Avalos do_tab = TRUE;
7255382d832SPeter Avalos move_by = -1;
7265382d832SPeter Avalos break;
7275382d832SPeter Avalos } else {
7285382d832SPeter Avalos int old_state = state;
7295382d832SPeter Avalos state = prev_valid_buttonindex(state, sTEXT, non_editable);
7305382d832SPeter Avalos show_buttons = TRUE;
7315382d832SPeter Avalos if (old_state >= 0 && state == sTEXT) {
7325382d832SPeter Avalos new_choice = item_no - 1;
7335382d832SPeter Avalos if (choice != new_choice) {
7345382d832SPeter Avalos print_item(form, items + choice, scrollamt, FALSE);
7355382d832SPeter Avalos choice = new_choice;
7365382d832SPeter Avalos }
7375382d832SPeter Avalos }
7385382d832SPeter Avalos continue;
7395382d832SPeter Avalos }
7405382d832SPeter Avalos
7415382d832SPeter Avalos case DLGK_FIELD_PREV:
7425382d832SPeter Avalos state = prev_valid_buttonindex(state, sTEXT, non_editable);
7435382d832SPeter Avalos show_buttons = TRUE;
7445382d832SPeter Avalos continue;
7455382d832SPeter Avalos
7465382d832SPeter Avalos case DLGK_FIELD_NEXT:
7475382d832SPeter Avalos state = next_valid_buttonindex(state, sTEXT, non_editable);
7485382d832SPeter Avalos show_buttons = TRUE;
7495382d832SPeter Avalos continue;
7505382d832SPeter Avalos
7515382d832SPeter Avalos case DLGK_GRID_RIGHT:
7525382d832SPeter Avalos if (state == sTEXT)
7535382d832SPeter Avalos break;
7545382d832SPeter Avalos /* FALLTHRU */
7555382d832SPeter Avalos
7565382d832SPeter Avalos case DLGK_ITEM_NEXT:
7575382d832SPeter Avalos if (state == sTEXT) {
7585382d832SPeter Avalos do_tab = TRUE;
7595382d832SPeter Avalos move_by = 1;
7605382d832SPeter Avalos break;
7615382d832SPeter Avalos } else {
7625382d832SPeter Avalos state = next_valid_buttonindex(state, 0, non_editable);
7635382d832SPeter Avalos show_buttons = TRUE;
7645382d832SPeter Avalos continue;
7655382d832SPeter Avalos }
7665382d832SPeter Avalos
7675382d832SPeter Avalos case DLGK_FORM_NEXT:
7685382d832SPeter Avalos if (state == sTEXT && !is_last_field(items, choice, item_no)) {
7695382d832SPeter Avalos do_tab = TRUE;
7705382d832SPeter Avalos move_by = 1;
7715382d832SPeter Avalos break;
7725382d832SPeter Avalos } else {
7735382d832SPeter Avalos state = next_valid_buttonindex(state, sTEXT, non_editable);
7745382d832SPeter Avalos show_buttons = TRUE;
7755382d832SPeter Avalos if (state == sTEXT && choice) {
7765382d832SPeter Avalos print_item(form, items + choice, scrollamt, FALSE);
7775382d832SPeter Avalos choice = 0;
7785382d832SPeter Avalos }
7795382d832SPeter Avalos continue;
7805382d832SPeter Avalos }
7815382d832SPeter Avalos
7825382d832SPeter Avalos #ifdef KEY_RESIZE
7835382d832SPeter Avalos case KEY_RESIZE:
7845940c9abSDaniel Fojt dlg_will_resize(dialog);
7855382d832SPeter Avalos /* reset data */
7865382d832SPeter Avalos height = old_height;
7875382d832SPeter Avalos width = old_width;
788*a8e38dc0SAntonio Huete Jimenez form_height = old_fhigh;
7895940c9abSDaniel Fojt free(prompt);
7905940c9abSDaniel Fojt _dlg_resize_cleanup(dialog);
7915940c9abSDaniel Fojt dlg_unregister_window(form);
7925382d832SPeter Avalos /* repaint */
7935382d832SPeter Avalos goto retry;
7945382d832SPeter Avalos #endif
7955382d832SPeter Avalos default:
7965382d832SPeter Avalos #if USE_MOUSE
7975382d832SPeter Avalos if (is_DLGK_MOUSE(key)) {
7985382d832SPeter Avalos if (key >= DLGK_MOUSE(KEY_MAX)) {
7995382d832SPeter Avalos int cell = key - DLGK_MOUSE(KEY_MAX);
8005382d832SPeter Avalos int row = (cell / getmaxx(form)) + scrollamt;
8015382d832SPeter Avalos int col = (cell % getmaxx(form));
8025382d832SPeter Avalos int n;
8035382d832SPeter Avalos
8045382d832SPeter Avalos for (n = 0; n < item_no; ++n) {
8055382d832SPeter Avalos if (items[n].name_y == row
8065382d832SPeter Avalos && items[n].name_x <= col
8075382d832SPeter Avalos && (items[n].name_x + items[n].name_len > col
8085382d832SPeter Avalos || (items[n].name_y == items[n].text_y
8095382d832SPeter Avalos && items[n].text_x > col))) {
8105382d832SPeter Avalos if (!is_readonly(&(items[n]))) {
8115382d832SPeter Avalos field_changed = TRUE;
8125382d832SPeter Avalos break;
8135382d832SPeter Avalos }
8145382d832SPeter Avalos }
8155382d832SPeter Avalos if (items[n].text_y == row
8165382d832SPeter Avalos && items[n].text_x <= col
8175382d832SPeter Avalos && items[n].text_x + items[n].text_ilen > col) {
8185382d832SPeter Avalos if (!is_readonly(&(items[n]))) {
8195382d832SPeter Avalos field_changed = TRUE;
8205382d832SPeter Avalos break;
8215382d832SPeter Avalos }
8225382d832SPeter Avalos }
8235382d832SPeter Avalos }
8245382d832SPeter Avalos if (field_changed) {
8255382d832SPeter Avalos print_item(form, items + choice, scrollamt, FALSE);
8265382d832SPeter Avalos choice = n;
8275382d832SPeter Avalos continue;
8285382d832SPeter Avalos }
8295382d832SPeter Avalos beep();
8305382d832SPeter Avalos } else if ((code = dlg_ok_buttoncode(key - M_EVENT)) >= 0) {
8315382d832SPeter Avalos result = code;
8325382d832SPeter Avalos }
8335382d832SPeter Avalos continue;
8345382d832SPeter Avalos }
8355382d832SPeter Avalos #endif
8365382d832SPeter Avalos break;
8375382d832SPeter Avalos }
8385382d832SPeter Avalos
8395382d832SPeter Avalos new_scroll = scrollamt;
8405382d832SPeter Avalos new_choice = choice;
8415382d832SPeter Avalos if (do_scroll) {
8425382d832SPeter Avalos if (scroll_next(form, items, move_by, &new_choice, &new_scroll)) {
8435382d832SPeter Avalos if (choice != new_choice) {
8445382d832SPeter Avalos choice = new_choice;
8455382d832SPeter Avalos field_changed = TRUE;
8465382d832SPeter Avalos }
8475382d832SPeter Avalos if (scrollamt != new_scroll) {
8485382d832SPeter Avalos scrollamt = new_scroll;
8495382d832SPeter Avalos scroll_changed = TRUE;
8505382d832SPeter Avalos }
8515382d832SPeter Avalos }
8525382d832SPeter Avalos continue;
8535382d832SPeter Avalos }
8545382d832SPeter Avalos if (do_tab) {
8555382d832SPeter Avalos if (tab_next(form, items, item_no, move_by, &new_choice, &new_scroll)) {
8565382d832SPeter Avalos if (choice != new_choice) {
8575382d832SPeter Avalos choice = new_choice;
8585382d832SPeter Avalos field_changed = TRUE;
8595382d832SPeter Avalos }
8605382d832SPeter Avalos if (scrollamt != new_scroll) {
8615382d832SPeter Avalos scrollamt = new_scroll;
8625382d832SPeter Avalos scroll_changed = TRUE;
8635382d832SPeter Avalos }
8645382d832SPeter Avalos }
8655382d832SPeter Avalos continue;
8665382d832SPeter Avalos }
8675382d832SPeter Avalos }
8685382d832SPeter Avalos
8695382d832SPeter Avalos if (state == sTEXT) { /* Input box selected */
8705382d832SPeter Avalos if (!is_readonly(current))
8715382d832SPeter Avalos edit = dlg_edit_string(current->text, &chr_offset, key,
8725382d832SPeter Avalos fkey, first);
8735382d832SPeter Avalos if (edit) {
8745382d832SPeter Avalos dlg_show_string(form, current->text, chr_offset,
8755382d832SPeter Avalos form_active_text_attr,
8765382d832SPeter Avalos current->text_y - scrollamt,
8775382d832SPeter Avalos current->text_x,
8785382d832SPeter Avalos current->text_len,
8795382d832SPeter Avalos is_hidden(current), first);
8805382d832SPeter Avalos continue;
8815382d832SPeter Avalos }
8825382d832SPeter Avalos }
8835382d832SPeter Avalos
8845382d832SPeter Avalos }
8855382d832SPeter Avalos
8865382d832SPeter Avalos dlg_mouse_free_regions();
8875940c9abSDaniel Fojt dlg_unregister_window(form);
8885382d832SPeter Avalos dlg_del_window(dialog);
8895382d832SPeter Avalos free(prompt);
8905382d832SPeter Avalos
8915382d832SPeter Avalos *current_item = choice;
8925382d832SPeter Avalos return result;
8935382d832SPeter Avalos }
8945382d832SPeter Avalos
8955382d832SPeter Avalos /*
8965382d832SPeter Avalos * Free memory owned by a list of DIALOG_FORMITEM's.
8975382d832SPeter Avalos */
8985382d832SPeter Avalos void
dlg_free_formitems(DIALOG_FORMITEM * items)8995382d832SPeter Avalos dlg_free_formitems(DIALOG_FORMITEM * items)
9005382d832SPeter Avalos {
9015382d832SPeter Avalos int n;
9025382d832SPeter Avalos for (n = 0; items[n].name != 0; ++n) {
9035382d832SPeter Avalos if (items[n].name_free)
9045382d832SPeter Avalos free(items[n].name);
9055382d832SPeter Avalos if (items[n].text_free)
9065382d832SPeter Avalos free(items[n].text);
9075382d832SPeter Avalos if (items[n].help_free && items[n].help != dlg_strempty())
9085382d832SPeter Avalos free(items[n].help);
9095382d832SPeter Avalos }
9105382d832SPeter Avalos free(items);
9115382d832SPeter Avalos }
9125382d832SPeter Avalos
9135382d832SPeter Avalos /*
9145382d832SPeter Avalos * The script accepts values beginning at 1, while curses starts at 0.
9155382d832SPeter Avalos */
9165382d832SPeter Avalos int
dlg_ordinate(const char * s)9175382d832SPeter Avalos dlg_ordinate(const char *s)
9185382d832SPeter Avalos {
9195382d832SPeter Avalos int result = atoi(s);
9205382d832SPeter Avalos if (result > 0)
9215382d832SPeter Avalos --result;
9225382d832SPeter Avalos else
9235382d832SPeter Avalos result = 0;
9245382d832SPeter Avalos return result;
9255382d832SPeter Avalos }
9265382d832SPeter Avalos
9275382d832SPeter Avalos int
dialog_form(const char * title,const char * cprompt,int height,int width,int form_height,int item_no,char ** items)9285382d832SPeter Avalos dialog_form(const char *title,
9295382d832SPeter Avalos const char *cprompt,
9305382d832SPeter Avalos int height,
9315382d832SPeter Avalos int width,
9325382d832SPeter Avalos int form_height,
9335382d832SPeter Avalos int item_no,
9345382d832SPeter Avalos char **items)
9355382d832SPeter Avalos {
9365382d832SPeter Avalos int result;
9375940c9abSDaniel Fojt int choice = 0;
9385382d832SPeter Avalos int i;
9395382d832SPeter Avalos DIALOG_FORMITEM *listitems;
9405382d832SPeter Avalos DIALOG_VARS save_vars;
9415382d832SPeter Avalos bool show_status = FALSE;
9421ef6786aSJohn Marino char *help_result;
9435382d832SPeter Avalos
9445382d832SPeter Avalos dlg_save_vars(&save_vars);
9455382d832SPeter Avalos dialog_vars.separate_output = TRUE;
9465382d832SPeter Avalos
9475382d832SPeter Avalos listitems = dlg_calloc(DIALOG_FORMITEM, (size_t) item_no + 1);
9485382d832SPeter Avalos assert_ptr(listitems, "dialog_form");
9495382d832SPeter Avalos
9505382d832SPeter Avalos for (i = 0; i < item_no; ++i) {
9515382d832SPeter Avalos listitems[i].type = dialog_vars.formitem_type;
9525382d832SPeter Avalos listitems[i].name = ItemName(i);
9535382d832SPeter Avalos listitems[i].name_len = (int) strlen(ItemName(i));
9545382d832SPeter Avalos listitems[i].name_y = dlg_ordinate(ItemNameY(i));
9555382d832SPeter Avalos listitems[i].name_x = dlg_ordinate(ItemNameX(i));
9565382d832SPeter Avalos listitems[i].text = ItemText(i);
9575382d832SPeter Avalos listitems[i].text_len = (int) strlen(ItemText(i));
9585382d832SPeter Avalos listitems[i].text_y = dlg_ordinate(ItemTextY(i));
9595382d832SPeter Avalos listitems[i].text_x = dlg_ordinate(ItemTextX(i));
9605382d832SPeter Avalos listitems[i].text_flen = atoi(ItemTextFLen(i));
9615382d832SPeter Avalos listitems[i].text_ilen = atoi(ItemTextILen(i));
9625382d832SPeter Avalos listitems[i].help = ((dialog_vars.item_help)
9635382d832SPeter Avalos ? ItemHelp(i)
9645382d832SPeter Avalos : dlg_strempty());
9655382d832SPeter Avalos }
9665382d832SPeter Avalos
9675382d832SPeter Avalos result = dlg_form(title,
9685382d832SPeter Avalos cprompt,
9695382d832SPeter Avalos height,
9705382d832SPeter Avalos width,
9715382d832SPeter Avalos form_height,
9725382d832SPeter Avalos item_no,
9735382d832SPeter Avalos listitems,
9745382d832SPeter Avalos &choice);
9755382d832SPeter Avalos
9765382d832SPeter Avalos switch (result) {
9775382d832SPeter Avalos case DLG_EXIT_OK: /* FALLTHRU */
9785382d832SPeter Avalos case DLG_EXIT_EXTRA:
9795382d832SPeter Avalos show_status = TRUE;
9805382d832SPeter Avalos break;
9815382d832SPeter Avalos case DLG_EXIT_HELP:
9821ef6786aSJohn Marino dlg_add_help_formitem(&result, &help_result, &listitems[choice]);
9835382d832SPeter Avalos show_status = dialog_vars.help_status;
9841ef6786aSJohn Marino dlg_add_string(help_result);
9855382d832SPeter Avalos if (show_status)
9865382d832SPeter Avalos dlg_add_separator();
9875382d832SPeter Avalos break;
9885382d832SPeter Avalos }
9895382d832SPeter Avalos if (show_status) {
9905382d832SPeter Avalos for (i = 0; i < item_no; i++) {
9915382d832SPeter Avalos if (listitems[i].text_flen > 0) {
9925382d832SPeter Avalos dlg_add_string(listitems[i].text);
9935382d832SPeter Avalos dlg_add_separator();
9945382d832SPeter Avalos }
9955382d832SPeter Avalos }
9961ef6786aSJohn Marino dlg_add_last_key(-1);
9975382d832SPeter Avalos }
9985382d832SPeter Avalos
9995382d832SPeter Avalos dlg_free_formitems(listitems);
10005382d832SPeter Avalos dlg_restore_vars(&save_vars);
10015382d832SPeter Avalos
10025382d832SPeter Avalos return result;
10035382d832SPeter Avalos }
1004