14c8945a0SNathan Whitehorn /* 2*f4f33ea0SBaptiste Daroussin * $Id: formbox.c,v 1.95 2018/06/21 08:23:31 tom Exp $ 34c8945a0SNathan Whitehorn * 4*f4f33ea0SBaptiste Daroussin * formbox.c -- implements the form (i.e., some pairs label/editbox) 54c8945a0SNathan Whitehorn * 6*f4f33ea0SBaptiste Daroussin * Copyright 2003-2016,2018 Thomas E. Dickey 74c8945a0SNathan Whitehorn * 84c8945a0SNathan Whitehorn * This program is free software; you can redistribute it and/or modify 94c8945a0SNathan Whitehorn * it under the terms of the GNU Lesser General Public License, version 2.1 104c8945a0SNathan Whitehorn * as published by the Free Software Foundation. 114c8945a0SNathan Whitehorn * 124c8945a0SNathan Whitehorn * This program is distributed in the hope that it will be useful, but 134c8945a0SNathan Whitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of 144c8945a0SNathan Whitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 154c8945a0SNathan Whitehorn * Lesser General Public License for more details. 164c8945a0SNathan Whitehorn * 174c8945a0SNathan Whitehorn * You should have received a copy of the GNU Lesser General Public 184c8945a0SNathan Whitehorn * License along with this program; if not, write to 194c8945a0SNathan Whitehorn * Free Software Foundation, Inc. 204c8945a0SNathan Whitehorn * 51 Franklin St., Fifth Floor 214c8945a0SNathan Whitehorn * Boston, MA 02110, USA. 224c8945a0SNathan Whitehorn * 234c8945a0SNathan Whitehorn * This is adapted from source contributed by 244c8945a0SNathan Whitehorn * Valery Reznic (valery_reznic@users.sourceforge.net) 254c8945a0SNathan Whitehorn */ 264c8945a0SNathan Whitehorn 274c8945a0SNathan Whitehorn #include <dialog.h> 284c8945a0SNathan Whitehorn #include <dlg_keys.h> 294c8945a0SNathan Whitehorn 304c8945a0SNathan Whitehorn #define LLEN(n) ((n) * FORMBOX_TAGS) 314c8945a0SNathan Whitehorn 324c8945a0SNathan Whitehorn #define ItemName(i) items[LLEN(i) + 0] 334c8945a0SNathan Whitehorn #define ItemNameY(i) items[LLEN(i) + 1] 344c8945a0SNathan Whitehorn #define ItemNameX(i) items[LLEN(i) + 2] 354c8945a0SNathan Whitehorn #define ItemText(i) items[LLEN(i) + 3] 364c8945a0SNathan Whitehorn #define ItemTextY(i) items[LLEN(i) + 4] 374c8945a0SNathan Whitehorn #define ItemTextX(i) items[LLEN(i) + 5] 384c8945a0SNathan Whitehorn #define ItemTextFLen(i) items[LLEN(i) + 6] 394c8945a0SNathan Whitehorn #define ItemTextILen(i) items[LLEN(i) + 7] 404c8945a0SNathan Whitehorn #define ItemHelp(i) (dialog_vars.item_help ? items[LLEN(i) + 8] : dlg_strempty()) 414c8945a0SNathan Whitehorn 424c8945a0SNathan Whitehorn static bool 434c8945a0SNathan Whitehorn is_readonly(DIALOG_FORMITEM * item) 444c8945a0SNathan Whitehorn { 454c8945a0SNathan Whitehorn return ((item->type & 2) != 0) || (item->text_flen <= 0); 464c8945a0SNathan Whitehorn } 474c8945a0SNathan Whitehorn 484c8945a0SNathan Whitehorn static bool 494c8945a0SNathan Whitehorn is_hidden(DIALOG_FORMITEM * item) 504c8945a0SNathan Whitehorn { 514c8945a0SNathan Whitehorn return ((item->type & 1) != 0); 524c8945a0SNathan Whitehorn } 534c8945a0SNathan Whitehorn 544c8945a0SNathan Whitehorn static bool 554c8945a0SNathan Whitehorn in_window(WINDOW *win, int scrollamt, int y) 564c8945a0SNathan Whitehorn { 574c8945a0SNathan Whitehorn return (y >= scrollamt && y - scrollamt < getmaxy(win)); 584c8945a0SNathan Whitehorn } 594c8945a0SNathan Whitehorn 604c8945a0SNathan Whitehorn static bool 614c8945a0SNathan Whitehorn ok_move(WINDOW *win, int scrollamt, int y, int x) 624c8945a0SNathan Whitehorn { 634c8945a0SNathan Whitehorn return in_window(win, scrollamt, y) 644c8945a0SNathan Whitehorn && (wmove(win, y - scrollamt, x) != ERR); 654c8945a0SNathan Whitehorn } 664c8945a0SNathan Whitehorn 674c8945a0SNathan Whitehorn static void 684c8945a0SNathan Whitehorn move_past(WINDOW *win, int y, int x) 694c8945a0SNathan Whitehorn { 704c8945a0SNathan Whitehorn if (wmove(win, y, x) == ERR) 714c8945a0SNathan Whitehorn wmove(win, y, getmaxx(win) - 1); 724c8945a0SNathan Whitehorn } 734c8945a0SNathan Whitehorn 744c8945a0SNathan Whitehorn /* 754c8945a0SNathan Whitehorn * Print form item 764c8945a0SNathan Whitehorn */ 774c8945a0SNathan Whitehorn static int 784c8945a0SNathan Whitehorn print_item(WINDOW *win, DIALOG_FORMITEM * item, int scrollamt, bool choice) 794c8945a0SNathan Whitehorn { 804c8945a0SNathan Whitehorn int count = 0; 814c8945a0SNathan Whitehorn int len; 824c8945a0SNathan Whitehorn 834c8945a0SNathan Whitehorn if (ok_move(win, scrollamt, item->name_y, item->name_x)) { 844c8945a0SNathan Whitehorn len = item->name_len; 854c8945a0SNathan Whitehorn len = MIN(len, getmaxx(win) - item->name_x); 864c8945a0SNathan Whitehorn if (len > 0) { 874c8945a0SNathan Whitehorn dlg_show_string(win, 884c8945a0SNathan Whitehorn item->name, 894c8945a0SNathan Whitehorn 0, 904c8945a0SNathan Whitehorn menubox_attr, 914c8945a0SNathan Whitehorn item->name_y - scrollamt, 924c8945a0SNathan Whitehorn item->name_x, 934c8945a0SNathan Whitehorn len, 944c8945a0SNathan Whitehorn FALSE, 954c8945a0SNathan Whitehorn FALSE); 964c8945a0SNathan Whitehorn move_past(win, item->name_y - scrollamt, item->name_x + len); 974c8945a0SNathan Whitehorn count = 1; 984c8945a0SNathan Whitehorn } 994c8945a0SNathan Whitehorn } 1004c8945a0SNathan Whitehorn if (item->text_len && ok_move(win, scrollamt, item->text_y, item->text_x)) { 1014c8945a0SNathan Whitehorn chtype this_item_attribute; 1024c8945a0SNathan Whitehorn 1034c8945a0SNathan Whitehorn len = item->text_len; 1044c8945a0SNathan Whitehorn len = MIN(len, getmaxx(win) - item->text_x); 1054c8945a0SNathan Whitehorn 1064c8945a0SNathan Whitehorn if (!is_readonly(item)) { 1074c8945a0SNathan Whitehorn this_item_attribute = choice 1084c8945a0SNathan Whitehorn ? form_active_text_attr 1094c8945a0SNathan Whitehorn : form_text_attr; 1104c8945a0SNathan Whitehorn } else { 1114c8945a0SNathan Whitehorn this_item_attribute = form_item_readonly_attr; 1124c8945a0SNathan Whitehorn } 1134c8945a0SNathan Whitehorn 1144c8945a0SNathan Whitehorn if (len > 0) { 1154c8945a0SNathan Whitehorn dlg_show_string(win, 1164c8945a0SNathan Whitehorn item->text, 1174c8945a0SNathan Whitehorn 0, 1184c8945a0SNathan Whitehorn this_item_attribute, 1194c8945a0SNathan Whitehorn item->text_y - scrollamt, 1204c8945a0SNathan Whitehorn item->text_x, 1214c8945a0SNathan Whitehorn len, 1224c8945a0SNathan Whitehorn is_hidden(item), 1234c8945a0SNathan Whitehorn FALSE); 1244c8945a0SNathan Whitehorn move_past(win, item->text_y - scrollamt, item->text_x + len); 1254c8945a0SNathan Whitehorn count = 1; 1264c8945a0SNathan Whitehorn } 1274c8945a0SNathan Whitehorn } 1284c8945a0SNathan Whitehorn return count; 1294c8945a0SNathan Whitehorn } 1304c8945a0SNathan Whitehorn 1314c8945a0SNathan Whitehorn /* 1324c8945a0SNathan Whitehorn * Print the entire form. 1334c8945a0SNathan Whitehorn */ 1344c8945a0SNathan Whitehorn static void 1354c8945a0SNathan Whitehorn print_form(WINDOW *win, DIALOG_FORMITEM * item, int total, int scrollamt, int choice) 1364c8945a0SNathan Whitehorn { 1374c8945a0SNathan Whitehorn int n; 1384c8945a0SNathan Whitehorn int count = 0; 1394c8945a0SNathan Whitehorn 1404c8945a0SNathan Whitehorn for (n = 0; n < total; ++n) { 1414c8945a0SNathan Whitehorn count += print_item(win, item + n, scrollamt, n == choice); 1424c8945a0SNathan Whitehorn } 1434c8945a0SNathan Whitehorn if (count) { 1444c8945a0SNathan Whitehorn wbkgdset(win, menubox_attr | ' '); 1454c8945a0SNathan Whitehorn wclrtobot(win); 1464c8945a0SNathan Whitehorn (void) wnoutrefresh(win); 1474c8945a0SNathan Whitehorn } 1484c8945a0SNathan Whitehorn } 1494c8945a0SNathan Whitehorn 1504c8945a0SNathan Whitehorn static int 1514c8945a0SNathan Whitehorn set_choice(DIALOG_FORMITEM item[], int choice, int item_no, bool * noneditable) 1524c8945a0SNathan Whitehorn { 1534c8945a0SNathan Whitehorn int result = -1; 1544c8945a0SNathan Whitehorn int i; 1554c8945a0SNathan Whitehorn 1564c8945a0SNathan Whitehorn *noneditable = FALSE; 1574c8945a0SNathan Whitehorn if (!is_readonly(&item[choice])) { 1584c8945a0SNathan Whitehorn result = choice; 1594c8945a0SNathan Whitehorn } else { 1604c8945a0SNathan Whitehorn for (i = 0; i < item_no; i++) { 1614c8945a0SNathan Whitehorn if (!is_readonly(&(item[i]))) { 1624c8945a0SNathan Whitehorn result = i; 1634c8945a0SNathan Whitehorn break; 1644c8945a0SNathan Whitehorn } 1654c8945a0SNathan Whitehorn } 1664c8945a0SNathan Whitehorn if (result < 0) { 1674c8945a0SNathan Whitehorn *noneditable = TRUE; 1684c8945a0SNathan Whitehorn result = 0; 1694c8945a0SNathan Whitehorn } 1704c8945a0SNathan Whitehorn } 1714c8945a0SNathan Whitehorn return result; 1724c8945a0SNathan Whitehorn } 1734c8945a0SNathan Whitehorn 1744c8945a0SNathan Whitehorn /* 1754c8945a0SNathan Whitehorn * Find the last y-value in the form. 1764c8945a0SNathan Whitehorn */ 1774c8945a0SNathan Whitehorn static int 1784c8945a0SNathan Whitehorn form_limit(DIALOG_FORMITEM item[]) 1794c8945a0SNathan Whitehorn { 1804c8945a0SNathan Whitehorn int n; 1814c8945a0SNathan Whitehorn int limit = 0; 1824c8945a0SNathan Whitehorn for (n = 0; item[n].name != 0; ++n) { 1834c8945a0SNathan Whitehorn if (limit < item[n].name_y) 1844c8945a0SNathan Whitehorn limit = item[n].name_y; 1854c8945a0SNathan Whitehorn if (limit < item[n].text_y) 1864c8945a0SNathan Whitehorn limit = item[n].text_y; 1874c8945a0SNathan Whitehorn } 1884c8945a0SNathan Whitehorn return limit; 1894c8945a0SNathan Whitehorn } 1904c8945a0SNathan Whitehorn 1912a3e3873SBaptiste Daroussin static int 1922a3e3873SBaptiste Daroussin is_first_field(DIALOG_FORMITEM item[], int choice) 1932a3e3873SBaptiste Daroussin { 1942a3e3873SBaptiste Daroussin int count = 0; 1952a3e3873SBaptiste Daroussin while (choice >= 0) { 1962a3e3873SBaptiste Daroussin if (item[choice].text_flen > 0) { 1972a3e3873SBaptiste Daroussin ++count; 1982a3e3873SBaptiste Daroussin } 1992a3e3873SBaptiste Daroussin --choice; 2002a3e3873SBaptiste Daroussin } 2012a3e3873SBaptiste Daroussin 2022a3e3873SBaptiste Daroussin return (count == 1); 2032a3e3873SBaptiste Daroussin } 2042a3e3873SBaptiste Daroussin 2052a3e3873SBaptiste Daroussin static int 2062a3e3873SBaptiste Daroussin is_last_field(DIALOG_FORMITEM item[], int choice, int item_no) 2072a3e3873SBaptiste Daroussin { 2082a3e3873SBaptiste Daroussin int count = 0; 2092a3e3873SBaptiste Daroussin while (choice < item_no) { 2102a3e3873SBaptiste Daroussin if (item[choice].text_flen > 0) { 2112a3e3873SBaptiste Daroussin ++count; 2122a3e3873SBaptiste Daroussin } 2132a3e3873SBaptiste Daroussin ++choice; 2142a3e3873SBaptiste Daroussin } 2152a3e3873SBaptiste Daroussin 2162a3e3873SBaptiste Daroussin return (count == 1); 2172a3e3873SBaptiste Daroussin } 2182a3e3873SBaptiste Daroussin 2194c8945a0SNathan Whitehorn /* 2204c8945a0SNathan Whitehorn * Tab to the next field. 2214c8945a0SNathan Whitehorn */ 2224c8945a0SNathan Whitehorn static bool 2234c8945a0SNathan Whitehorn tab_next(WINDOW *win, 2244c8945a0SNathan Whitehorn DIALOG_FORMITEM item[], 2254c8945a0SNathan Whitehorn int item_no, 2264c8945a0SNathan Whitehorn int stepsize, 2274c8945a0SNathan Whitehorn int *choice, 2284c8945a0SNathan Whitehorn int *scrollamt) 2294c8945a0SNathan Whitehorn { 2304c8945a0SNathan Whitehorn int old_choice = *choice; 2314c8945a0SNathan Whitehorn int old_scroll = *scrollamt; 2324c8945a0SNathan Whitehorn bool wrapped = FALSE; 2334c8945a0SNathan Whitehorn 2344c8945a0SNathan Whitehorn do { 2354c8945a0SNathan Whitehorn do { 2364c8945a0SNathan Whitehorn *choice += stepsize; 2374c8945a0SNathan Whitehorn if (*choice < 0) { 2384c8945a0SNathan Whitehorn *choice = item_no - 1; 2394c8945a0SNathan Whitehorn wrapped = TRUE; 2404c8945a0SNathan Whitehorn } else if (*choice >= item_no) { 2414c8945a0SNathan Whitehorn *choice = 0; 2424c8945a0SNathan Whitehorn wrapped = TRUE; 2434c8945a0SNathan Whitehorn } 2444c8945a0SNathan Whitehorn } while ((*choice != old_choice) && is_readonly(&(item[*choice]))); 2454c8945a0SNathan Whitehorn 2464c8945a0SNathan Whitehorn if (item[*choice].text_flen > 0) { 2474c8945a0SNathan Whitehorn int lo = MIN(item[*choice].name_y, item[*choice].text_y); 2484c8945a0SNathan Whitehorn int hi = MAX(item[*choice].name_y, item[*choice].text_y); 2494c8945a0SNathan Whitehorn 2504c8945a0SNathan Whitehorn if (old_choice == *choice) 2514c8945a0SNathan Whitehorn break; 2524c8945a0SNathan Whitehorn print_item(win, item + old_choice, *scrollamt, FALSE); 2534c8945a0SNathan Whitehorn 2544c8945a0SNathan Whitehorn if (*scrollamt < lo + 1 - getmaxy(win)) 2554c8945a0SNathan Whitehorn *scrollamt = lo + 1 - getmaxy(win); 2564c8945a0SNathan Whitehorn if (*scrollamt > hi) 2574c8945a0SNathan Whitehorn *scrollamt = hi; 2584c8945a0SNathan Whitehorn /* 2594c8945a0SNathan Whitehorn * If we have to scroll to show a wrap-around, it does get 2604c8945a0SNathan Whitehorn * confusing. Just give up rather than scroll. Tab'ing to the 2614c8945a0SNathan Whitehorn * next field in a multi-column form is a different matter. Scroll 2624c8945a0SNathan Whitehorn * for that. 2634c8945a0SNathan Whitehorn */ 2644c8945a0SNathan Whitehorn if (*scrollamt != old_scroll) { 2654c8945a0SNathan Whitehorn if (wrapped) { 2664c8945a0SNathan Whitehorn beep(); 2674c8945a0SNathan Whitehorn *scrollamt = old_scroll; 2684c8945a0SNathan Whitehorn *choice = old_choice; 2694c8945a0SNathan Whitehorn } else { 2704c8945a0SNathan Whitehorn scrollok(win, TRUE); 2714c8945a0SNathan Whitehorn wscrl(win, *scrollamt - old_scroll); 2724c8945a0SNathan Whitehorn scrollok(win, FALSE); 2734c8945a0SNathan Whitehorn } 2744c8945a0SNathan Whitehorn } 2754c8945a0SNathan Whitehorn break; 2764c8945a0SNathan Whitehorn } 2774c8945a0SNathan Whitehorn } while (*choice != old_choice); 2784c8945a0SNathan Whitehorn 2794c8945a0SNathan Whitehorn return (old_choice != *choice) || (old_scroll != *scrollamt); 2804c8945a0SNathan Whitehorn } 2814c8945a0SNathan Whitehorn 2824c8945a0SNathan Whitehorn /* 2834c8945a0SNathan Whitehorn * Scroll to the next page, putting the choice at the first editable field 2844c8945a0SNathan Whitehorn * in that page. Note that fields are not necessarily in top-to-bottom order, 2854c8945a0SNathan Whitehorn * nor is there necessarily a field on each row of the window. 2864c8945a0SNathan Whitehorn */ 2874c8945a0SNathan Whitehorn static bool 2884c8945a0SNathan Whitehorn scroll_next(WINDOW *win, DIALOG_FORMITEM item[], int stepsize, int *choice, int *scrollamt) 2894c8945a0SNathan Whitehorn { 2902a3e3873SBaptiste Daroussin bool result = TRUE; 2914c8945a0SNathan Whitehorn int old_choice = *choice; 2924c8945a0SNathan Whitehorn int old_scroll = *scrollamt; 2934c8945a0SNathan Whitehorn int old_row = MIN(item[old_choice].text_y, item[old_choice].name_y); 2944c8945a0SNathan Whitehorn int target = old_scroll + stepsize; 2954c8945a0SNathan Whitehorn int n; 2964c8945a0SNathan Whitehorn 2974c8945a0SNathan Whitehorn if (stepsize < 0) { 2984c8945a0SNathan Whitehorn if (old_row != old_scroll) 2994c8945a0SNathan Whitehorn target = old_scroll; 3004c8945a0SNathan Whitehorn else 3014c8945a0SNathan Whitehorn target = old_scroll + stepsize; 3022a3e3873SBaptiste Daroussin if (target < 0) { 3032a3e3873SBaptiste Daroussin result = FALSE; 3042a3e3873SBaptiste Daroussin } 3054c8945a0SNathan Whitehorn } else { 3062a3e3873SBaptiste Daroussin if (target > form_limit(item)) { 3072a3e3873SBaptiste Daroussin result = FALSE; 3082a3e3873SBaptiste Daroussin } 3094c8945a0SNathan Whitehorn } 3104c8945a0SNathan Whitehorn 3112a3e3873SBaptiste Daroussin if (result) { 3124c8945a0SNathan Whitehorn for (n = 0; item[n].name != 0; ++n) { 3134c8945a0SNathan Whitehorn if (item[n].text_flen > 0) { 3144c8945a0SNathan Whitehorn int new_row = MIN(item[n].text_y, item[n].name_y); 3154c8945a0SNathan Whitehorn if (abs(new_row - target) < abs(old_row - target)) { 3164c8945a0SNathan Whitehorn old_row = new_row; 3174c8945a0SNathan Whitehorn *choice = n; 3184c8945a0SNathan Whitehorn } 3194c8945a0SNathan Whitehorn } 3204c8945a0SNathan Whitehorn } 3214c8945a0SNathan Whitehorn 3224c8945a0SNathan Whitehorn if (old_choice != *choice) 3234c8945a0SNathan Whitehorn print_item(win, item + old_choice, *scrollamt, FALSE); 3244c8945a0SNathan Whitehorn 3254c8945a0SNathan Whitehorn *scrollamt = *choice; 3264c8945a0SNathan Whitehorn if (*scrollamt != old_scroll) { 3274c8945a0SNathan Whitehorn scrollok(win, TRUE); 3284c8945a0SNathan Whitehorn wscrl(win, *scrollamt - old_scroll); 3294c8945a0SNathan Whitehorn scrollok(win, FALSE); 3304c8945a0SNathan Whitehorn } 3312a3e3873SBaptiste Daroussin result = (old_choice != *choice) || (old_scroll != *scrollamt); 3322a3e3873SBaptiste Daroussin } 3332a3e3873SBaptiste Daroussin if (!result) 3342a3e3873SBaptiste Daroussin beep(); 3352a3e3873SBaptiste Daroussin return result; 3364c8945a0SNathan Whitehorn } 3374c8945a0SNathan Whitehorn 3384c8945a0SNathan Whitehorn /* 3394c8945a0SNathan Whitehorn * Do a sanity check on the field length, and return the "right" value. 3404c8945a0SNathan Whitehorn */ 3414c8945a0SNathan Whitehorn static int 3424c8945a0SNathan Whitehorn real_length(DIALOG_FORMITEM * item) 3434c8945a0SNathan Whitehorn { 3444c8945a0SNathan Whitehorn return (item->text_flen > 0 3454c8945a0SNathan Whitehorn ? item->text_flen 3464c8945a0SNathan Whitehorn : (item->text_flen < 0 3474c8945a0SNathan Whitehorn ? -item->text_flen 3484c8945a0SNathan Whitehorn : item->text_len)); 3494c8945a0SNathan Whitehorn } 3504c8945a0SNathan Whitehorn 3514c8945a0SNathan Whitehorn /* 3524c8945a0SNathan Whitehorn * Compute the form size, setup field buffers. 3534c8945a0SNathan Whitehorn */ 3544c8945a0SNathan Whitehorn static void 3554c8945a0SNathan Whitehorn make_FORM_ELTs(DIALOG_FORMITEM * item, 3564c8945a0SNathan Whitehorn int item_no, 3574c8945a0SNathan Whitehorn int *min_height, 3584c8945a0SNathan Whitehorn int *min_width) 3594c8945a0SNathan Whitehorn { 3604c8945a0SNathan Whitehorn int i; 3614c8945a0SNathan Whitehorn int min_w = 0; 3624c8945a0SNathan Whitehorn int min_h = 0; 3634c8945a0SNathan Whitehorn 3644c8945a0SNathan Whitehorn for (i = 0; i < item_no; ++i) { 3654c8945a0SNathan Whitehorn int real_len = real_length(item + i); 3664c8945a0SNathan Whitehorn 3674c8945a0SNathan Whitehorn /* 3684c8945a0SNathan Whitehorn * Special value '0' for text_flen: no input allowed 3694c8945a0SNathan Whitehorn * Special value '0' for text_ilen: 'be the same as text_flen' 3704c8945a0SNathan Whitehorn */ 3714c8945a0SNathan Whitehorn if (item[i].text_ilen == 0) 3724c8945a0SNathan Whitehorn item[i].text_ilen = real_len; 3734c8945a0SNathan Whitehorn 3744c8945a0SNathan Whitehorn min_h = MAX(min_h, item[i].name_y + 1); 3754c8945a0SNathan Whitehorn min_h = MAX(min_h, item[i].text_y + 1); 3764c8945a0SNathan Whitehorn min_w = MAX(min_w, item[i].name_x + 1 + item[i].name_len); 3774c8945a0SNathan Whitehorn min_w = MAX(min_w, item[i].text_x + 1 + real_len); 3784c8945a0SNathan Whitehorn 3794c8945a0SNathan Whitehorn item[i].text_len = real_length(item + i); 3804c8945a0SNathan Whitehorn 3814c8945a0SNathan Whitehorn /* 3824c8945a0SNathan Whitehorn * We do not know the actual length of .text, so we allocate it here 3834c8945a0SNathan Whitehorn * to ensure it is big enough. 3844c8945a0SNathan Whitehorn */ 3854c8945a0SNathan Whitehorn if (item[i].text_flen > 0) { 3864c8945a0SNathan Whitehorn int max_len = dlg_max_input(MAX(item[i].text_ilen + 1, MAX_LEN)); 3874c8945a0SNathan Whitehorn char *old_text = item[i].text; 3884c8945a0SNathan Whitehorn 3894c8945a0SNathan Whitehorn item[i].text = dlg_malloc(char, (size_t) max_len + 1); 3904c8945a0SNathan Whitehorn assert_ptr(item[i].text, "make_FORM_ELTs"); 3914c8945a0SNathan Whitehorn 3924c8945a0SNathan Whitehorn sprintf(item[i].text, "%.*s", item[i].text_ilen, old_text); 3934c8945a0SNathan Whitehorn 3944c8945a0SNathan Whitehorn if (item[i].text_free) { 3954c8945a0SNathan Whitehorn item[i].text_free = FALSE; 3964c8945a0SNathan Whitehorn free(old_text); 3974c8945a0SNathan Whitehorn } 3984c8945a0SNathan Whitehorn item[i].text_free = TRUE; 3994c8945a0SNathan Whitehorn } 4004c8945a0SNathan Whitehorn } 4014c8945a0SNathan Whitehorn 4024c8945a0SNathan Whitehorn *min_height = min_h; 4034c8945a0SNathan Whitehorn *min_width = min_w; 4044c8945a0SNathan Whitehorn } 4054c8945a0SNathan Whitehorn 4064c8945a0SNathan Whitehorn int 4074c8945a0SNathan Whitehorn dlg_default_formitem(DIALOG_FORMITEM * items) 4084c8945a0SNathan Whitehorn { 4094c8945a0SNathan Whitehorn int result = 0; 4104c8945a0SNathan Whitehorn 4114c8945a0SNathan Whitehorn if (dialog_vars.default_item != 0) { 4124c8945a0SNathan Whitehorn int count = 0; 4134c8945a0SNathan Whitehorn while (items->name != 0) { 4144c8945a0SNathan Whitehorn if (!strcmp(dialog_vars.default_item, items->name)) { 4154c8945a0SNathan Whitehorn result = count; 4164c8945a0SNathan Whitehorn break; 4174c8945a0SNathan Whitehorn } 4184c8945a0SNathan Whitehorn ++items; 4194c8945a0SNathan Whitehorn count++; 4204c8945a0SNathan Whitehorn } 4214c8945a0SNathan Whitehorn } 4224c8945a0SNathan Whitehorn return result; 4234c8945a0SNathan Whitehorn } 4244c8945a0SNathan Whitehorn 4254c8945a0SNathan Whitehorn #define sTEXT -1 4264c8945a0SNathan Whitehorn 4274c8945a0SNathan Whitehorn static int 4284c8945a0SNathan Whitehorn next_valid_buttonindex(int state, int extra, bool non_editable) 4294c8945a0SNathan Whitehorn { 4304c8945a0SNathan Whitehorn state = dlg_next_ok_buttonindex(state, extra); 4314c8945a0SNathan Whitehorn while (non_editable && state == sTEXT) 4324c8945a0SNathan Whitehorn state = dlg_next_ok_buttonindex(state, sTEXT); 4334c8945a0SNathan Whitehorn return state; 4344c8945a0SNathan Whitehorn } 4354c8945a0SNathan Whitehorn 4364c8945a0SNathan Whitehorn static int 4374c8945a0SNathan Whitehorn prev_valid_buttonindex(int state, int extra, bool non_editable) 4384c8945a0SNathan Whitehorn { 4394c8945a0SNathan Whitehorn state = dlg_prev_ok_buttonindex(state, extra); 4404c8945a0SNathan Whitehorn while (non_editable && state == sTEXT) 4414c8945a0SNathan Whitehorn state = dlg_prev_ok_buttonindex(state, sTEXT); 4424c8945a0SNathan Whitehorn return state; 4434c8945a0SNathan Whitehorn } 4444c8945a0SNathan Whitehorn 4454c8945a0SNathan Whitehorn #define NAVIGATE_BINDINGS \ 4464c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), \ 4474c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), \ 4484c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ), \ 4494c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ), \ 450*f4f33ea0SBaptiste Daroussin DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_RIGHT ), \ 4514c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_NEXT ), \ 4524c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ), \ 4534c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_PREVIOUS ), \ 454*f4f33ea0SBaptiste Daroussin DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_LEFT ), \ 4554c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ), \ 4564c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), \ 4574c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ) 4584c8945a0SNathan Whitehorn /* 4592a3e3873SBaptiste Daroussin * Display a form for entering a number of fields 4604c8945a0SNathan Whitehorn */ 4614c8945a0SNathan Whitehorn int 4624c8945a0SNathan Whitehorn dlg_form(const char *title, 4634c8945a0SNathan Whitehorn const char *cprompt, 4644c8945a0SNathan Whitehorn int height, 4654c8945a0SNathan Whitehorn int width, 4664c8945a0SNathan Whitehorn int form_height, 4674c8945a0SNathan Whitehorn int item_no, 4684c8945a0SNathan Whitehorn DIALOG_FORMITEM * items, 4694c8945a0SNathan Whitehorn int *current_item) 4704c8945a0SNathan Whitehorn { 4714c8945a0SNathan Whitehorn /* *INDENT-OFF* */ 4724c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding[] = { 473682c9e0fSNathan Whitehorn HELPKEY_BINDINGS, 4744c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 4754c8945a0SNathan Whitehorn NAVIGATE_BINDINGS, 476*f4f33ea0SBaptiste Daroussin TOGGLEKEY_BINDINGS, 4774c8945a0SNathan Whitehorn END_KEYS_BINDING 4784c8945a0SNathan Whitehorn }; 4794c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding2[] = { 4804c8945a0SNathan Whitehorn INPUTSTR_BINDINGS, 481682c9e0fSNathan Whitehorn HELPKEY_BINDINGS, 4824c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 4834c8945a0SNathan Whitehorn NAVIGATE_BINDINGS, 484*f4f33ea0SBaptiste Daroussin /* no TOGGLEKEY_BINDINGS, since that includes space... */ 4854c8945a0SNathan Whitehorn END_KEYS_BINDING 4864c8945a0SNathan Whitehorn }; 4874c8945a0SNathan Whitehorn /* *INDENT-ON* */ 4884c8945a0SNathan Whitehorn 4894c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 4904c8945a0SNathan Whitehorn int old_height = height; 4914c8945a0SNathan Whitehorn int old_width = width; 4924c8945a0SNathan Whitehorn #endif 4934c8945a0SNathan Whitehorn 4944c8945a0SNathan Whitehorn int form_width; 495*f4f33ea0SBaptiste Daroussin bool first = TRUE; 496*f4f33ea0SBaptiste Daroussin bool first_trace = TRUE; 4974c8945a0SNathan Whitehorn int chr_offset = 0; 498*f4f33ea0SBaptiste Daroussin int state = (dialog_vars.default_button >= 0 499*f4f33ea0SBaptiste Daroussin ? dlg_default_button() 500*f4f33ea0SBaptiste Daroussin : sTEXT); 5014c8945a0SNathan Whitehorn int x, y, cur_x, cur_y, box_x, box_y; 5024c8945a0SNathan Whitehorn int code; 5034c8945a0SNathan Whitehorn int key = 0; 5044c8945a0SNathan Whitehorn int fkey; 5054c8945a0SNathan Whitehorn int choice = dlg_default_formitem(items); 5064c8945a0SNathan Whitehorn int new_choice, new_scroll; 5074c8945a0SNathan Whitehorn int scrollamt = 0; 5084c8945a0SNathan Whitehorn int result = DLG_EXIT_UNKNOWN; 5094c8945a0SNathan Whitehorn int min_width = 0, min_height = 0; 5104c8945a0SNathan Whitehorn bool was_autosize = (height == 0 || width == 0); 5114c8945a0SNathan Whitehorn bool show_buttons = FALSE; 5124c8945a0SNathan Whitehorn bool scroll_changed = FALSE; 5134c8945a0SNathan Whitehorn bool field_changed = FALSE; 5144c8945a0SNathan Whitehorn bool non_editable = FALSE; 5154c8945a0SNathan Whitehorn WINDOW *dialog, *form; 516*f4f33ea0SBaptiste Daroussin char *prompt; 5174c8945a0SNathan Whitehorn const char **buttons = dlg_ok_labels(); 5184c8945a0SNathan Whitehorn DIALOG_FORMITEM *current; 5194c8945a0SNathan Whitehorn 520*f4f33ea0SBaptiste Daroussin DLG_TRACE(("# %sform args:\n", (dialog_vars.formitem_type 521*f4f33ea0SBaptiste Daroussin ? "password" 522*f4f33ea0SBaptiste Daroussin : ""))); 523*f4f33ea0SBaptiste Daroussin DLG_TRACE2S("title", title); 524*f4f33ea0SBaptiste Daroussin DLG_TRACE2S("message", cprompt); 525*f4f33ea0SBaptiste Daroussin DLG_TRACE2N("height", height); 526*f4f33ea0SBaptiste Daroussin DLG_TRACE2N("width", width); 527*f4f33ea0SBaptiste Daroussin DLG_TRACE2N("lheight", form_height); 528*f4f33ea0SBaptiste Daroussin DLG_TRACE2N("llength", item_no); 529*f4f33ea0SBaptiste Daroussin /* FIXME dump the items[][] too */ 530*f4f33ea0SBaptiste Daroussin DLG_TRACE2N("current", *current_item); 531*f4f33ea0SBaptiste Daroussin 5324c8945a0SNathan Whitehorn make_FORM_ELTs(items, item_no, &min_height, &min_width); 5334c8945a0SNathan Whitehorn dlg_button_layout(buttons, &min_width); 5344c8945a0SNathan Whitehorn dlg_does_output(); 5354c8945a0SNathan Whitehorn 5364c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 5374c8945a0SNathan Whitehorn retry: 5384c8945a0SNathan Whitehorn #endif 5394c8945a0SNathan Whitehorn 540*f4f33ea0SBaptiste Daroussin prompt = dlg_strclone(cprompt); 541*f4f33ea0SBaptiste Daroussin dlg_tab_correct_str(prompt); 5424c8945a0SNathan Whitehorn dlg_auto_size(title, prompt, &height, &width, 5434c8945a0SNathan Whitehorn 1 + 3 * MARGIN, 5444c8945a0SNathan Whitehorn MAX(26, 2 + min_width)); 5454c8945a0SNathan Whitehorn 5464c8945a0SNathan Whitehorn if (form_height == 0) 5474c8945a0SNathan Whitehorn form_height = min_height; 5484c8945a0SNathan Whitehorn 5494c8945a0SNathan Whitehorn if (was_autosize) { 5504c8945a0SNathan Whitehorn form_height = MIN(SLINES - height, form_height); 5514c8945a0SNathan Whitehorn height += form_height; 5524c8945a0SNathan Whitehorn } else { 5534c8945a0SNathan Whitehorn int thigh = 0; 5544c8945a0SNathan Whitehorn int twide = 0; 5554c8945a0SNathan Whitehorn dlg_auto_size(title, prompt, &thigh, &twide, 0, width); 5564c8945a0SNathan Whitehorn thigh = SLINES - (height - (thigh + 1 + 3 * MARGIN)); 5574c8945a0SNathan Whitehorn form_height = MIN(thigh, form_height); 5584c8945a0SNathan Whitehorn } 5594c8945a0SNathan Whitehorn 5604c8945a0SNathan Whitehorn dlg_print_size(height, width); 5614c8945a0SNathan Whitehorn dlg_ctl_size(height, width); 5624c8945a0SNathan Whitehorn 5634c8945a0SNathan Whitehorn x = dlg_box_x_ordinate(width); 5644c8945a0SNathan Whitehorn y = dlg_box_y_ordinate(height); 5654c8945a0SNathan Whitehorn 5664c8945a0SNathan Whitehorn dialog = dlg_new_window(height, width, y, x); 5674c8945a0SNathan Whitehorn dlg_register_window(dialog, "formbox", binding); 5684c8945a0SNathan Whitehorn dlg_register_buttons(dialog, "formbox", buttons); 5694c8945a0SNathan Whitehorn 5704c8945a0SNathan Whitehorn dlg_mouse_setbase(x, y); 5714c8945a0SNathan Whitehorn 5722a3e3873SBaptiste Daroussin dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr); 5732a3e3873SBaptiste Daroussin dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr); 5744c8945a0SNathan Whitehorn dlg_draw_title(dialog, title); 5754c8945a0SNathan Whitehorn 576*f4f33ea0SBaptiste Daroussin dlg_attrset(dialog, dialog_attr); 5774c8945a0SNathan Whitehorn dlg_print_autowrap(dialog, prompt, height, width); 5784c8945a0SNathan Whitehorn 5794c8945a0SNathan Whitehorn form_width = width - 6; 5804c8945a0SNathan Whitehorn getyx(dialog, cur_y, cur_x); 5812a3e3873SBaptiste Daroussin (void) cur_x; 5824c8945a0SNathan Whitehorn box_y = cur_y + 1; 5834c8945a0SNathan Whitehorn box_x = (width - form_width) / 2 - 1; 5844c8945a0SNathan Whitehorn 5854c8945a0SNathan Whitehorn /* create new window for the form */ 5864c8945a0SNathan Whitehorn form = dlg_sub_window(dialog, form_height, form_width, y + box_y + 1, 5874c8945a0SNathan Whitehorn x + box_x + 1); 5882a3e3873SBaptiste Daroussin dlg_register_window(form, "formfield", binding2); 5894c8945a0SNathan Whitehorn 5904c8945a0SNathan Whitehorn /* draw a box around the form items */ 5914c8945a0SNathan Whitehorn dlg_draw_box(dialog, box_y, box_x, form_height + 2, form_width + 2, 5922a3e3873SBaptiste Daroussin menubox_border_attr, menubox_border2_attr); 5934c8945a0SNathan Whitehorn 5944c8945a0SNathan Whitehorn /* register the new window, along with its borders */ 5954c8945a0SNathan Whitehorn dlg_mouse_mkbigregion(getbegy(form) - getbegy(dialog), 5964c8945a0SNathan Whitehorn getbegx(form) - getbegx(dialog), 5974c8945a0SNathan Whitehorn getmaxy(form), 5984c8945a0SNathan Whitehorn getmaxx(form), 5994c8945a0SNathan Whitehorn KEY_MAX, 1, 1, 3 /* by cells */ ); 6004c8945a0SNathan Whitehorn 6014c8945a0SNathan Whitehorn show_buttons = TRUE; 6024c8945a0SNathan Whitehorn scroll_changed = TRUE; 6034c8945a0SNathan Whitehorn 6044c8945a0SNathan Whitehorn choice = set_choice(items, choice, item_no, &non_editable); 6054c8945a0SNathan Whitehorn current = &items[choice]; 6064c8945a0SNathan Whitehorn if (non_editable) 6074c8945a0SNathan Whitehorn state = next_valid_buttonindex(state, sTEXT, non_editable); 6084c8945a0SNathan Whitehorn 6094c8945a0SNathan Whitehorn while (result == DLG_EXIT_UNKNOWN) { 6104c8945a0SNathan Whitehorn int edit = FALSE; 6114c8945a0SNathan Whitehorn 6124c8945a0SNathan Whitehorn if (scroll_changed) { 6134c8945a0SNathan Whitehorn print_form(form, items, item_no, scrollamt, choice); 6144c8945a0SNathan Whitehorn dlg_draw_scrollbar(dialog, 6154c8945a0SNathan Whitehorn scrollamt, 6164c8945a0SNathan Whitehorn scrollamt, 6174c8945a0SNathan Whitehorn scrollamt + form_height + 1, 6184c8945a0SNathan Whitehorn min_height, 6194c8945a0SNathan Whitehorn box_x + 1, 6204c8945a0SNathan Whitehorn box_x + form_width, 6214c8945a0SNathan Whitehorn box_y, 6224c8945a0SNathan Whitehorn box_y + form_height + 1, 6232a3e3873SBaptiste Daroussin menubox_border2_attr, 6244c8945a0SNathan Whitehorn menubox_border_attr); 6254c8945a0SNathan Whitehorn scroll_changed = FALSE; 6264c8945a0SNathan Whitehorn } 6274c8945a0SNathan Whitehorn 6284c8945a0SNathan Whitehorn if (show_buttons) { 6294c8945a0SNathan Whitehorn dlg_item_help(""); 6304c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, height - 2, 0, buttons, 6314c8945a0SNathan Whitehorn ((state < 0) 6324c8945a0SNathan Whitehorn ? 1000 /* no such button, not highlighted */ 6334c8945a0SNathan Whitehorn : state), 6344c8945a0SNathan Whitehorn FALSE, width); 6354c8945a0SNathan Whitehorn show_buttons = FALSE; 6364c8945a0SNathan Whitehorn } 6374c8945a0SNathan Whitehorn 6382a3e3873SBaptiste Daroussin if (first_trace) { 6392a3e3873SBaptiste Daroussin first_trace = FALSE; 6402a3e3873SBaptiste Daroussin dlg_trace_win(dialog); 6412a3e3873SBaptiste Daroussin } 6422a3e3873SBaptiste Daroussin 6434c8945a0SNathan Whitehorn if (field_changed || state == sTEXT) { 6444c8945a0SNathan Whitehorn if (field_changed) 6454c8945a0SNathan Whitehorn chr_offset = 0; 6464c8945a0SNathan Whitehorn current = &items[choice]; 6474c8945a0SNathan Whitehorn dialog_vars.max_input = current->text_ilen; 6484c8945a0SNathan Whitehorn dlg_item_help(current->help); 6494c8945a0SNathan Whitehorn dlg_show_string(form, current->text, chr_offset, 6504c8945a0SNathan Whitehorn form_active_text_attr, 6514c8945a0SNathan Whitehorn current->text_y - scrollamt, 6524c8945a0SNathan Whitehorn current->text_x, 6534c8945a0SNathan Whitehorn current->text_len, 6544c8945a0SNathan Whitehorn is_hidden(current), first); 6552a3e3873SBaptiste Daroussin wsyncup(form); 6562a3e3873SBaptiste Daroussin wcursyncup(form); 6574c8945a0SNathan Whitehorn field_changed = FALSE; 6584c8945a0SNathan Whitehorn } 6594c8945a0SNathan Whitehorn 6602a3e3873SBaptiste Daroussin key = dlg_mouse_wgetch((state == sTEXT) ? form : dialog, &fkey); 6614c8945a0SNathan Whitehorn if (dlg_result_key(key, fkey, &result)) 6624c8945a0SNathan Whitehorn break; 6634c8945a0SNathan Whitehorn 6644c8945a0SNathan Whitehorn /* handle non-functionkeys */ 6654c8945a0SNathan Whitehorn if (!fkey) { 6664c8945a0SNathan Whitehorn if (state != sTEXT) { 6674c8945a0SNathan Whitehorn code = dlg_char_to_button(key, buttons); 6684c8945a0SNathan Whitehorn if (code >= 0) { 6694c8945a0SNathan Whitehorn dlg_del_window(dialog); 6704c8945a0SNathan Whitehorn result = dlg_ok_buttoncode(code); 6714c8945a0SNathan Whitehorn continue; 6724c8945a0SNathan Whitehorn } 6734c8945a0SNathan Whitehorn } 6744c8945a0SNathan Whitehorn } 6754c8945a0SNathan Whitehorn 6764c8945a0SNathan Whitehorn /* handle functionkeys */ 6774c8945a0SNathan Whitehorn if (fkey) { 6784c8945a0SNathan Whitehorn bool do_scroll = FALSE; 6794c8945a0SNathan Whitehorn bool do_tab = FALSE; 6804c8945a0SNathan Whitehorn int move_by = 0; 6814c8945a0SNathan Whitehorn 6824c8945a0SNathan Whitehorn switch (key) { 6834c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_PPAGE): 6844c8945a0SNathan Whitehorn case DLGK_PAGE_PREV: 6854c8945a0SNathan Whitehorn do_scroll = TRUE; 6864c8945a0SNathan Whitehorn move_by = -form_height; 6874c8945a0SNathan Whitehorn break; 6884c8945a0SNathan Whitehorn 6894c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_NPAGE): 6904c8945a0SNathan Whitehorn case DLGK_PAGE_NEXT: 6914c8945a0SNathan Whitehorn do_scroll = TRUE; 6924c8945a0SNathan Whitehorn move_by = form_height; 6934c8945a0SNathan Whitehorn break; 6944c8945a0SNathan Whitehorn 695*f4f33ea0SBaptiste Daroussin case DLGK_TOGGLE: 6964c8945a0SNathan Whitehorn case DLGK_ENTER: 6974c8945a0SNathan Whitehorn dlg_del_window(dialog); 698682c9e0fSNathan Whitehorn result = (state >= 0) ? dlg_enter_buttoncode(state) : DLG_EXIT_OK; 6994c8945a0SNathan Whitehorn continue; 7004c8945a0SNathan Whitehorn 7014c8945a0SNathan Whitehorn case DLGK_GRID_LEFT: 7024c8945a0SNathan Whitehorn if (state == sTEXT) 7034c8945a0SNathan Whitehorn break; 7044c8945a0SNathan Whitehorn /* FALLTHRU */ 7054c8945a0SNathan Whitehorn case DLGK_ITEM_PREV: 7064c8945a0SNathan Whitehorn if (state == sTEXT) { 7074c8945a0SNathan Whitehorn do_tab = TRUE; 7084c8945a0SNathan Whitehorn move_by = -1; 7094c8945a0SNathan Whitehorn break; 7104c8945a0SNathan Whitehorn } else { 7114c8945a0SNathan Whitehorn state = prev_valid_buttonindex(state, 0, non_editable); 7124c8945a0SNathan Whitehorn show_buttons = TRUE; 7134c8945a0SNathan Whitehorn continue; 7144c8945a0SNathan Whitehorn } 7154c8945a0SNathan Whitehorn 7162a3e3873SBaptiste Daroussin case DLGK_FORM_PREV: 7172a3e3873SBaptiste Daroussin if (state == sTEXT && !is_first_field(items, choice)) { 7182a3e3873SBaptiste Daroussin do_tab = TRUE; 7192a3e3873SBaptiste Daroussin move_by = -1; 7202a3e3873SBaptiste Daroussin break; 7212a3e3873SBaptiste Daroussin } else { 7222a3e3873SBaptiste Daroussin int old_state = state; 7232a3e3873SBaptiste Daroussin state = prev_valid_buttonindex(state, sTEXT, non_editable); 7242a3e3873SBaptiste Daroussin show_buttons = TRUE; 7252a3e3873SBaptiste Daroussin if (old_state >= 0 && state == sTEXT) { 7262a3e3873SBaptiste Daroussin new_choice = item_no - 1; 7272a3e3873SBaptiste Daroussin if (choice != new_choice) { 7282a3e3873SBaptiste Daroussin print_item(form, items + choice, scrollamt, FALSE); 7292a3e3873SBaptiste Daroussin choice = new_choice; 7302a3e3873SBaptiste Daroussin } 7312a3e3873SBaptiste Daroussin } 7322a3e3873SBaptiste Daroussin continue; 7332a3e3873SBaptiste Daroussin } 7342a3e3873SBaptiste Daroussin 7354c8945a0SNathan Whitehorn case DLGK_FIELD_PREV: 7364c8945a0SNathan Whitehorn state = prev_valid_buttonindex(state, sTEXT, non_editable); 7374c8945a0SNathan Whitehorn show_buttons = TRUE; 7384c8945a0SNathan Whitehorn continue; 7394c8945a0SNathan Whitehorn 7404c8945a0SNathan Whitehorn case DLGK_FIELD_NEXT: 7414c8945a0SNathan Whitehorn state = next_valid_buttonindex(state, sTEXT, non_editable); 7424c8945a0SNathan Whitehorn show_buttons = TRUE; 7434c8945a0SNathan Whitehorn continue; 7444c8945a0SNathan Whitehorn 7454c8945a0SNathan Whitehorn case DLGK_GRID_RIGHT: 7464c8945a0SNathan Whitehorn if (state == sTEXT) 7474c8945a0SNathan Whitehorn break; 7484c8945a0SNathan Whitehorn /* FALLTHRU */ 7494c8945a0SNathan Whitehorn 7504c8945a0SNathan Whitehorn case DLGK_ITEM_NEXT: 7514c8945a0SNathan Whitehorn if (state == sTEXT) { 7524c8945a0SNathan Whitehorn do_tab = TRUE; 7534c8945a0SNathan Whitehorn move_by = 1; 7544c8945a0SNathan Whitehorn break; 7554c8945a0SNathan Whitehorn } else { 7564c8945a0SNathan Whitehorn state = next_valid_buttonindex(state, 0, non_editable); 7574c8945a0SNathan Whitehorn show_buttons = TRUE; 7584c8945a0SNathan Whitehorn continue; 7594c8945a0SNathan Whitehorn } 7604c8945a0SNathan Whitehorn 7612a3e3873SBaptiste Daroussin case DLGK_FORM_NEXT: 7622a3e3873SBaptiste Daroussin if (state == sTEXT && !is_last_field(items, choice, item_no)) { 7632a3e3873SBaptiste Daroussin do_tab = TRUE; 7642a3e3873SBaptiste Daroussin move_by = 1; 7652a3e3873SBaptiste Daroussin break; 7662a3e3873SBaptiste Daroussin } else { 7672a3e3873SBaptiste Daroussin state = next_valid_buttonindex(state, sTEXT, non_editable); 7682a3e3873SBaptiste Daroussin show_buttons = TRUE; 7692a3e3873SBaptiste Daroussin if (state == sTEXT && choice) { 7702a3e3873SBaptiste Daroussin print_item(form, items + choice, scrollamt, FALSE); 7712a3e3873SBaptiste Daroussin choice = 0; 7722a3e3873SBaptiste Daroussin } 7732a3e3873SBaptiste Daroussin continue; 7742a3e3873SBaptiste Daroussin } 7752a3e3873SBaptiste Daroussin 7764c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 7774c8945a0SNathan Whitehorn case KEY_RESIZE: 778*f4f33ea0SBaptiste Daroussin dlg_will_resize(dialog); 7794c8945a0SNathan Whitehorn /* reset data */ 7804c8945a0SNathan Whitehorn height = old_height; 7814c8945a0SNathan Whitehorn width = old_width; 782*f4f33ea0SBaptiste Daroussin free(prompt); 7834c8945a0SNathan Whitehorn dlg_clear(); 784*f4f33ea0SBaptiste Daroussin dlg_unregister_window(form); 7854c8945a0SNathan Whitehorn dlg_del_window(dialog); 7864c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 787*f4f33ea0SBaptiste Daroussin /* repaint */ 7884c8945a0SNathan Whitehorn goto retry; 7894c8945a0SNathan Whitehorn #endif 7904c8945a0SNathan Whitehorn default: 7914c8945a0SNathan Whitehorn #if USE_MOUSE 7924c8945a0SNathan Whitehorn if (is_DLGK_MOUSE(key)) { 7934c8945a0SNathan Whitehorn if (key >= DLGK_MOUSE(KEY_MAX)) { 7944c8945a0SNathan Whitehorn int cell = key - DLGK_MOUSE(KEY_MAX); 7954c8945a0SNathan Whitehorn int row = (cell / getmaxx(form)) + scrollamt; 7964c8945a0SNathan Whitehorn int col = (cell % getmaxx(form)); 7974c8945a0SNathan Whitehorn int n; 7984c8945a0SNathan Whitehorn 7994c8945a0SNathan Whitehorn for (n = 0; n < item_no; ++n) { 8004c8945a0SNathan Whitehorn if (items[n].name_y == row 8014c8945a0SNathan Whitehorn && items[n].name_x <= col 8024c8945a0SNathan Whitehorn && (items[n].name_x + items[n].name_len > col 8034c8945a0SNathan Whitehorn || (items[n].name_y == items[n].text_y 8044c8945a0SNathan Whitehorn && items[n].text_x > col))) { 8054c8945a0SNathan Whitehorn if (!is_readonly(&(items[n]))) { 8064c8945a0SNathan Whitehorn field_changed = TRUE; 8074c8945a0SNathan Whitehorn break; 8084c8945a0SNathan Whitehorn } 8094c8945a0SNathan Whitehorn } 8104c8945a0SNathan Whitehorn if (items[n].text_y == row 8114c8945a0SNathan Whitehorn && items[n].text_x <= col 8124c8945a0SNathan Whitehorn && items[n].text_x + items[n].text_ilen > col) { 8134c8945a0SNathan Whitehorn if (!is_readonly(&(items[n]))) { 8144c8945a0SNathan Whitehorn field_changed = TRUE; 8154c8945a0SNathan Whitehorn break; 8164c8945a0SNathan Whitehorn } 8174c8945a0SNathan Whitehorn } 8184c8945a0SNathan Whitehorn } 8194c8945a0SNathan Whitehorn if (field_changed) { 8204c8945a0SNathan Whitehorn print_item(form, items + choice, scrollamt, FALSE); 8214c8945a0SNathan Whitehorn choice = n; 8224c8945a0SNathan Whitehorn continue; 8234c8945a0SNathan Whitehorn } 8244c8945a0SNathan Whitehorn beep(); 8254c8945a0SNathan Whitehorn } else if ((code = dlg_ok_buttoncode(key - M_EVENT)) >= 0) { 8264c8945a0SNathan Whitehorn result = code; 8274c8945a0SNathan Whitehorn } 8284c8945a0SNathan Whitehorn continue; 8294c8945a0SNathan Whitehorn } 8304c8945a0SNathan Whitehorn #endif 8314c8945a0SNathan Whitehorn break; 8324c8945a0SNathan Whitehorn } 8334c8945a0SNathan Whitehorn 8344c8945a0SNathan Whitehorn new_scroll = scrollamt; 8354c8945a0SNathan Whitehorn new_choice = choice; 8364c8945a0SNathan Whitehorn if (do_scroll) { 8374c8945a0SNathan Whitehorn if (scroll_next(form, items, move_by, &new_choice, &new_scroll)) { 8384c8945a0SNathan Whitehorn if (choice != new_choice) { 8394c8945a0SNathan Whitehorn choice = new_choice; 8404c8945a0SNathan Whitehorn field_changed = TRUE; 8414c8945a0SNathan Whitehorn } 8424c8945a0SNathan Whitehorn if (scrollamt != new_scroll) { 8434c8945a0SNathan Whitehorn scrollamt = new_scroll; 8444c8945a0SNathan Whitehorn scroll_changed = TRUE; 8454c8945a0SNathan Whitehorn } 8464c8945a0SNathan Whitehorn } 8474c8945a0SNathan Whitehorn continue; 8484c8945a0SNathan Whitehorn } 8494c8945a0SNathan Whitehorn if (do_tab) { 8504c8945a0SNathan Whitehorn if (tab_next(form, items, item_no, move_by, &new_choice, &new_scroll)) { 8514c8945a0SNathan Whitehorn if (choice != new_choice) { 8524c8945a0SNathan Whitehorn choice = new_choice; 8534c8945a0SNathan Whitehorn field_changed = TRUE; 8544c8945a0SNathan Whitehorn } 8554c8945a0SNathan Whitehorn if (scrollamt != new_scroll) { 8564c8945a0SNathan Whitehorn scrollamt = new_scroll; 8574c8945a0SNathan Whitehorn scroll_changed = TRUE; 8584c8945a0SNathan Whitehorn } 8594c8945a0SNathan Whitehorn } 8604c8945a0SNathan Whitehorn continue; 8614c8945a0SNathan Whitehorn } 8624c8945a0SNathan Whitehorn } 8634c8945a0SNathan Whitehorn 8644c8945a0SNathan Whitehorn if (state == sTEXT) { /* Input box selected */ 8654c8945a0SNathan Whitehorn if (!is_readonly(current)) 8664c8945a0SNathan Whitehorn edit = dlg_edit_string(current->text, &chr_offset, key, 8674c8945a0SNathan Whitehorn fkey, first); 8684c8945a0SNathan Whitehorn if (edit) { 8694c8945a0SNathan Whitehorn dlg_show_string(form, current->text, chr_offset, 8704c8945a0SNathan Whitehorn form_active_text_attr, 8714c8945a0SNathan Whitehorn current->text_y - scrollamt, 8724c8945a0SNathan Whitehorn current->text_x, 8734c8945a0SNathan Whitehorn current->text_len, 8744c8945a0SNathan Whitehorn is_hidden(current), first); 8754c8945a0SNathan Whitehorn continue; 8764c8945a0SNathan Whitehorn } 8774c8945a0SNathan Whitehorn } 8784c8945a0SNathan Whitehorn 8794c8945a0SNathan Whitehorn } 8804c8945a0SNathan Whitehorn 8814c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 882*f4f33ea0SBaptiste Daroussin dlg_unregister_window(form); 8834c8945a0SNathan Whitehorn dlg_del_window(dialog); 8844c8945a0SNathan Whitehorn free(prompt); 8854c8945a0SNathan Whitehorn 8864c8945a0SNathan Whitehorn *current_item = choice; 8874c8945a0SNathan Whitehorn return result; 8884c8945a0SNathan Whitehorn } 8894c8945a0SNathan Whitehorn 8904c8945a0SNathan Whitehorn /* 8914c8945a0SNathan Whitehorn * Free memory owned by a list of DIALOG_FORMITEM's. 8924c8945a0SNathan Whitehorn */ 8934c8945a0SNathan Whitehorn void 8944c8945a0SNathan Whitehorn dlg_free_formitems(DIALOG_FORMITEM * items) 8954c8945a0SNathan Whitehorn { 8964c8945a0SNathan Whitehorn int n; 8974c8945a0SNathan Whitehorn for (n = 0; items[n].name != 0; ++n) { 8984c8945a0SNathan Whitehorn if (items[n].name_free) 8994c8945a0SNathan Whitehorn free(items[n].name); 9004c8945a0SNathan Whitehorn if (items[n].text_free) 9014c8945a0SNathan Whitehorn free(items[n].text); 9024c8945a0SNathan Whitehorn if (items[n].help_free && items[n].help != dlg_strempty()) 9034c8945a0SNathan Whitehorn free(items[n].help); 9044c8945a0SNathan Whitehorn } 9054c8945a0SNathan Whitehorn free(items); 9064c8945a0SNathan Whitehorn } 9074c8945a0SNathan Whitehorn 9084c8945a0SNathan Whitehorn /* 9094c8945a0SNathan Whitehorn * The script accepts values beginning at 1, while curses starts at 0. 9104c8945a0SNathan Whitehorn */ 9114c8945a0SNathan Whitehorn int 9124c8945a0SNathan Whitehorn dlg_ordinate(const char *s) 9134c8945a0SNathan Whitehorn { 9144c8945a0SNathan Whitehorn int result = atoi(s); 9154c8945a0SNathan Whitehorn if (result > 0) 9164c8945a0SNathan Whitehorn --result; 9174c8945a0SNathan Whitehorn else 9184c8945a0SNathan Whitehorn result = 0; 9194c8945a0SNathan Whitehorn return result; 9204c8945a0SNathan Whitehorn } 9214c8945a0SNathan Whitehorn 9224c8945a0SNathan Whitehorn int 9234c8945a0SNathan Whitehorn dialog_form(const char *title, 9244c8945a0SNathan Whitehorn const char *cprompt, 9254c8945a0SNathan Whitehorn int height, 9264c8945a0SNathan Whitehorn int width, 9274c8945a0SNathan Whitehorn int form_height, 9284c8945a0SNathan Whitehorn int item_no, 9294c8945a0SNathan Whitehorn char **items) 9304c8945a0SNathan Whitehorn { 9314c8945a0SNathan Whitehorn int result; 932*f4f33ea0SBaptiste Daroussin int choice = 0; 9334c8945a0SNathan Whitehorn int i; 9344c8945a0SNathan Whitehorn DIALOG_FORMITEM *listitems; 9354c8945a0SNathan Whitehorn DIALOG_VARS save_vars; 9364c8945a0SNathan Whitehorn bool show_status = FALSE; 937febdb468SDevin Teske char *help_result; 9384c8945a0SNathan Whitehorn 9394c8945a0SNathan Whitehorn dlg_save_vars(&save_vars); 9404c8945a0SNathan Whitehorn dialog_vars.separate_output = TRUE; 9414c8945a0SNathan Whitehorn 9424c8945a0SNathan Whitehorn listitems = dlg_calloc(DIALOG_FORMITEM, (size_t) item_no + 1); 9434c8945a0SNathan Whitehorn assert_ptr(listitems, "dialog_form"); 9444c8945a0SNathan Whitehorn 9454c8945a0SNathan Whitehorn for (i = 0; i < item_no; ++i) { 9464c8945a0SNathan Whitehorn listitems[i].type = dialog_vars.formitem_type; 9474c8945a0SNathan Whitehorn listitems[i].name = ItemName(i); 9484c8945a0SNathan Whitehorn listitems[i].name_len = (int) strlen(ItemName(i)); 9494c8945a0SNathan Whitehorn listitems[i].name_y = dlg_ordinate(ItemNameY(i)); 9504c8945a0SNathan Whitehorn listitems[i].name_x = dlg_ordinate(ItemNameX(i)); 9514c8945a0SNathan Whitehorn listitems[i].text = ItemText(i); 9524c8945a0SNathan Whitehorn listitems[i].text_len = (int) strlen(ItemText(i)); 9534c8945a0SNathan Whitehorn listitems[i].text_y = dlg_ordinate(ItemTextY(i)); 9544c8945a0SNathan Whitehorn listitems[i].text_x = dlg_ordinate(ItemTextX(i)); 9554c8945a0SNathan Whitehorn listitems[i].text_flen = atoi(ItemTextFLen(i)); 9564c8945a0SNathan Whitehorn listitems[i].text_ilen = atoi(ItemTextILen(i)); 9574c8945a0SNathan Whitehorn listitems[i].help = ((dialog_vars.item_help) 9584c8945a0SNathan Whitehorn ? ItemHelp(i) 9594c8945a0SNathan Whitehorn : dlg_strempty()); 9604c8945a0SNathan Whitehorn } 9614c8945a0SNathan Whitehorn 9624c8945a0SNathan Whitehorn result = dlg_form(title, 9634c8945a0SNathan Whitehorn cprompt, 9644c8945a0SNathan Whitehorn height, 9654c8945a0SNathan Whitehorn width, 9664c8945a0SNathan Whitehorn form_height, 9674c8945a0SNathan Whitehorn item_no, 9684c8945a0SNathan Whitehorn listitems, 9694c8945a0SNathan Whitehorn &choice); 9704c8945a0SNathan Whitehorn 9714c8945a0SNathan Whitehorn switch (result) { 9724c8945a0SNathan Whitehorn case DLG_EXIT_OK: /* FALLTHRU */ 9734c8945a0SNathan Whitehorn case DLG_EXIT_EXTRA: 9744c8945a0SNathan Whitehorn show_status = TRUE; 9754c8945a0SNathan Whitehorn break; 9764c8945a0SNathan Whitehorn case DLG_EXIT_HELP: 977febdb468SDevin Teske dlg_add_help_formitem(&result, &help_result, &listitems[choice]); 9784c8945a0SNathan Whitehorn show_status = dialog_vars.help_status; 979febdb468SDevin Teske dlg_add_string(help_result); 9804c8945a0SNathan Whitehorn if (show_status) 9814c8945a0SNathan Whitehorn dlg_add_separator(); 9824c8945a0SNathan Whitehorn break; 9834c8945a0SNathan Whitehorn } 9844c8945a0SNathan Whitehorn if (show_status) { 9854c8945a0SNathan Whitehorn for (i = 0; i < item_no; i++) { 9864c8945a0SNathan Whitehorn if (listitems[i].text_flen > 0) { 9874c8945a0SNathan Whitehorn dlg_add_string(listitems[i].text); 9884c8945a0SNathan Whitehorn dlg_add_separator(); 9894c8945a0SNathan Whitehorn } 9904c8945a0SNathan Whitehorn } 9912a3e3873SBaptiste Daroussin dlg_add_last_key(-1); 9924c8945a0SNathan Whitehorn } 9934c8945a0SNathan Whitehorn 9944c8945a0SNathan Whitehorn dlg_free_formitems(listitems); 9954c8945a0SNathan Whitehorn dlg_restore_vars(&save_vars); 9964c8945a0SNathan Whitehorn 9974c8945a0SNathan Whitehorn return result; 9984c8945a0SNathan Whitehorn } 999