14c8945a0SNathan Whitehorn /* 2*febdb468SDevin Teske * $Id: formbox.c,v 1.87 2013/09/02 17:02:05 tom Exp $ 34c8945a0SNathan Whitehorn * 44c8945a0SNathan Whitehorn * formbox.c -- implements the form (i.e, some pairs label/editbox) 54c8945a0SNathan Whitehorn * 62a3e3873SBaptiste Daroussin * Copyright 2003-2012,2013 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 ), \ 4504c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_NEXT ), \ 4514c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ), \ 4524c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_PREVIOUS ), \ 4534c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ), \ 4544c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), \ 4554c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ) 4564c8945a0SNathan Whitehorn /* 4572a3e3873SBaptiste Daroussin * Display a form for entering a number of fields 4584c8945a0SNathan Whitehorn */ 4594c8945a0SNathan Whitehorn int 4604c8945a0SNathan Whitehorn dlg_form(const char *title, 4614c8945a0SNathan Whitehorn const char *cprompt, 4624c8945a0SNathan Whitehorn int height, 4634c8945a0SNathan Whitehorn int width, 4644c8945a0SNathan Whitehorn int form_height, 4654c8945a0SNathan Whitehorn int item_no, 4664c8945a0SNathan Whitehorn DIALOG_FORMITEM * items, 4674c8945a0SNathan Whitehorn int *current_item) 4684c8945a0SNathan Whitehorn { 4694c8945a0SNathan Whitehorn /* *INDENT-OFF* */ 4704c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding[] = { 471682c9e0fSNathan Whitehorn HELPKEY_BINDINGS, 4724c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 4734c8945a0SNathan Whitehorn NAVIGATE_BINDINGS, 4744c8945a0SNathan Whitehorn END_KEYS_BINDING 4754c8945a0SNathan Whitehorn }; 4764c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding2[] = { 4774c8945a0SNathan Whitehorn INPUTSTR_BINDINGS, 478682c9e0fSNathan Whitehorn HELPKEY_BINDINGS, 4794c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 4804c8945a0SNathan Whitehorn NAVIGATE_BINDINGS, 4814c8945a0SNathan Whitehorn END_KEYS_BINDING 4824c8945a0SNathan Whitehorn }; 4834c8945a0SNathan Whitehorn /* *INDENT-ON* */ 4844c8945a0SNathan Whitehorn 4854c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 4864c8945a0SNathan Whitehorn int old_height = height; 4874c8945a0SNathan Whitehorn int old_width = width; 4884c8945a0SNathan Whitehorn #endif 4894c8945a0SNathan Whitehorn 4904c8945a0SNathan Whitehorn int form_width; 4914c8945a0SNathan Whitehorn int first = TRUE; 4922a3e3873SBaptiste Daroussin int first_trace = TRUE; 4934c8945a0SNathan Whitehorn int chr_offset = 0; 4942a3e3873SBaptiste Daroussin int state = dialog_vars.default_button >= 0 ? dlg_default_button() : sTEXT; 4954c8945a0SNathan Whitehorn int x, y, cur_x, cur_y, box_x, box_y; 4964c8945a0SNathan Whitehorn int code; 4974c8945a0SNathan Whitehorn int key = 0; 4984c8945a0SNathan Whitehorn int fkey; 4994c8945a0SNathan Whitehorn int choice = dlg_default_formitem(items); 5004c8945a0SNathan Whitehorn int new_choice, new_scroll; 5014c8945a0SNathan Whitehorn int scrollamt = 0; 5024c8945a0SNathan Whitehorn int result = DLG_EXIT_UNKNOWN; 5034c8945a0SNathan Whitehorn int min_width = 0, min_height = 0; 5044c8945a0SNathan Whitehorn bool was_autosize = (height == 0 || width == 0); 5054c8945a0SNathan Whitehorn bool show_buttons = FALSE; 5064c8945a0SNathan Whitehorn bool scroll_changed = FALSE; 5074c8945a0SNathan Whitehorn bool field_changed = FALSE; 5084c8945a0SNathan Whitehorn bool non_editable = FALSE; 5094c8945a0SNathan Whitehorn WINDOW *dialog, *form; 5104c8945a0SNathan Whitehorn char *prompt = dlg_strclone(cprompt); 5114c8945a0SNathan Whitehorn const char **buttons = dlg_ok_labels(); 5124c8945a0SNathan Whitehorn DIALOG_FORMITEM *current; 5134c8945a0SNathan Whitehorn 5144c8945a0SNathan Whitehorn make_FORM_ELTs(items, item_no, &min_height, &min_width); 5154c8945a0SNathan Whitehorn dlg_button_layout(buttons, &min_width); 5164c8945a0SNathan Whitehorn dlg_does_output(); 5174c8945a0SNathan Whitehorn dlg_tab_correct_str(prompt); 5184c8945a0SNathan Whitehorn 5194c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 5204c8945a0SNathan Whitehorn retry: 5214c8945a0SNathan Whitehorn #endif 5224c8945a0SNathan Whitehorn 5234c8945a0SNathan Whitehorn dlg_auto_size(title, prompt, &height, &width, 5244c8945a0SNathan Whitehorn 1 + 3 * MARGIN, 5254c8945a0SNathan Whitehorn MAX(26, 2 + min_width)); 5264c8945a0SNathan Whitehorn 5274c8945a0SNathan Whitehorn if (form_height == 0) 5284c8945a0SNathan Whitehorn form_height = min_height; 5294c8945a0SNathan Whitehorn 5304c8945a0SNathan Whitehorn if (was_autosize) { 5314c8945a0SNathan Whitehorn form_height = MIN(SLINES - height, form_height); 5324c8945a0SNathan Whitehorn height += form_height; 5334c8945a0SNathan Whitehorn } else { 5344c8945a0SNathan Whitehorn int thigh = 0; 5354c8945a0SNathan Whitehorn int twide = 0; 5364c8945a0SNathan Whitehorn dlg_auto_size(title, prompt, &thigh, &twide, 0, width); 5374c8945a0SNathan Whitehorn thigh = SLINES - (height - (thigh + 1 + 3 * MARGIN)); 5384c8945a0SNathan Whitehorn form_height = MIN(thigh, form_height); 5394c8945a0SNathan Whitehorn } 5404c8945a0SNathan Whitehorn 5414c8945a0SNathan Whitehorn dlg_print_size(height, width); 5424c8945a0SNathan Whitehorn dlg_ctl_size(height, width); 5434c8945a0SNathan Whitehorn 5444c8945a0SNathan Whitehorn x = dlg_box_x_ordinate(width); 5454c8945a0SNathan Whitehorn y = dlg_box_y_ordinate(height); 5464c8945a0SNathan Whitehorn 5474c8945a0SNathan Whitehorn dialog = dlg_new_window(height, width, y, x); 5484c8945a0SNathan Whitehorn dlg_register_window(dialog, "formbox", binding); 5494c8945a0SNathan Whitehorn dlg_register_buttons(dialog, "formbox", buttons); 5504c8945a0SNathan Whitehorn 5514c8945a0SNathan Whitehorn dlg_mouse_setbase(x, y); 5524c8945a0SNathan Whitehorn 5532a3e3873SBaptiste Daroussin dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr); 5542a3e3873SBaptiste Daroussin dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr); 5554c8945a0SNathan Whitehorn dlg_draw_title(dialog, title); 5564c8945a0SNathan Whitehorn 5572a3e3873SBaptiste Daroussin (void) wattrset(dialog, dialog_attr); 5584c8945a0SNathan Whitehorn dlg_print_autowrap(dialog, prompt, height, width); 5594c8945a0SNathan Whitehorn 5604c8945a0SNathan Whitehorn form_width = width - 6; 5614c8945a0SNathan Whitehorn getyx(dialog, cur_y, cur_x); 5622a3e3873SBaptiste Daroussin (void) cur_x; 5634c8945a0SNathan Whitehorn box_y = cur_y + 1; 5644c8945a0SNathan Whitehorn box_x = (width - form_width) / 2 - 1; 5654c8945a0SNathan Whitehorn 5664c8945a0SNathan Whitehorn /* create new window for the form */ 5674c8945a0SNathan Whitehorn form = dlg_sub_window(dialog, form_height, form_width, y + box_y + 1, 5684c8945a0SNathan Whitehorn x + box_x + 1); 5692a3e3873SBaptiste Daroussin dlg_register_window(form, "formfield", binding2); 5704c8945a0SNathan Whitehorn 5714c8945a0SNathan Whitehorn /* draw a box around the form items */ 5724c8945a0SNathan Whitehorn dlg_draw_box(dialog, box_y, box_x, form_height + 2, form_width + 2, 5732a3e3873SBaptiste Daroussin menubox_border_attr, menubox_border2_attr); 5744c8945a0SNathan Whitehorn 5754c8945a0SNathan Whitehorn /* register the new window, along with its borders */ 5764c8945a0SNathan Whitehorn dlg_mouse_mkbigregion(getbegy(form) - getbegy(dialog), 5774c8945a0SNathan Whitehorn getbegx(form) - getbegx(dialog), 5784c8945a0SNathan Whitehorn getmaxy(form), 5794c8945a0SNathan Whitehorn getmaxx(form), 5804c8945a0SNathan Whitehorn KEY_MAX, 1, 1, 3 /* by cells */ ); 5814c8945a0SNathan Whitehorn 5824c8945a0SNathan Whitehorn show_buttons = TRUE; 5834c8945a0SNathan Whitehorn scroll_changed = TRUE; 5844c8945a0SNathan Whitehorn 5854c8945a0SNathan Whitehorn choice = set_choice(items, choice, item_no, &non_editable); 5864c8945a0SNathan Whitehorn current = &items[choice]; 5874c8945a0SNathan Whitehorn if (non_editable) 5884c8945a0SNathan Whitehorn state = next_valid_buttonindex(state, sTEXT, non_editable); 5894c8945a0SNathan Whitehorn 5904c8945a0SNathan Whitehorn while (result == DLG_EXIT_UNKNOWN) { 5914c8945a0SNathan Whitehorn int edit = FALSE; 5924c8945a0SNathan Whitehorn 5934c8945a0SNathan Whitehorn if (scroll_changed) { 5944c8945a0SNathan Whitehorn print_form(form, items, item_no, scrollamt, choice); 5954c8945a0SNathan Whitehorn dlg_draw_scrollbar(dialog, 5964c8945a0SNathan Whitehorn scrollamt, 5974c8945a0SNathan Whitehorn scrollamt, 5984c8945a0SNathan Whitehorn scrollamt + form_height + 1, 5994c8945a0SNathan Whitehorn min_height, 6004c8945a0SNathan Whitehorn box_x + 1, 6014c8945a0SNathan Whitehorn box_x + form_width, 6024c8945a0SNathan Whitehorn box_y, 6034c8945a0SNathan Whitehorn box_y + form_height + 1, 6042a3e3873SBaptiste Daroussin menubox_border2_attr, 6054c8945a0SNathan Whitehorn menubox_border_attr); 6064c8945a0SNathan Whitehorn scroll_changed = FALSE; 6074c8945a0SNathan Whitehorn } 6084c8945a0SNathan Whitehorn 6094c8945a0SNathan Whitehorn if (show_buttons) { 6104c8945a0SNathan Whitehorn dlg_item_help(""); 6114c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, height - 2, 0, buttons, 6124c8945a0SNathan Whitehorn ((state < 0) 6134c8945a0SNathan Whitehorn ? 1000 /* no such button, not highlighted */ 6144c8945a0SNathan Whitehorn : state), 6154c8945a0SNathan Whitehorn FALSE, width); 6164c8945a0SNathan Whitehorn show_buttons = FALSE; 6174c8945a0SNathan Whitehorn } 6184c8945a0SNathan Whitehorn 6192a3e3873SBaptiste Daroussin if (first_trace) { 6202a3e3873SBaptiste Daroussin first_trace = FALSE; 6212a3e3873SBaptiste Daroussin dlg_trace_win(dialog); 6222a3e3873SBaptiste Daroussin } 6232a3e3873SBaptiste Daroussin 6244c8945a0SNathan Whitehorn if (field_changed || state == sTEXT) { 6254c8945a0SNathan Whitehorn if (field_changed) 6264c8945a0SNathan Whitehorn chr_offset = 0; 6274c8945a0SNathan Whitehorn current = &items[choice]; 6284c8945a0SNathan Whitehorn dialog_vars.max_input = current->text_ilen; 6294c8945a0SNathan Whitehorn dlg_item_help(current->help); 6304c8945a0SNathan Whitehorn dlg_show_string(form, current->text, chr_offset, 6314c8945a0SNathan Whitehorn form_active_text_attr, 6324c8945a0SNathan Whitehorn current->text_y - scrollamt, 6334c8945a0SNathan Whitehorn current->text_x, 6344c8945a0SNathan Whitehorn current->text_len, 6354c8945a0SNathan Whitehorn is_hidden(current), first); 6362a3e3873SBaptiste Daroussin wsyncup(form); 6372a3e3873SBaptiste Daroussin wcursyncup(form); 6384c8945a0SNathan Whitehorn field_changed = FALSE; 6394c8945a0SNathan Whitehorn } 6404c8945a0SNathan Whitehorn 6412a3e3873SBaptiste Daroussin key = dlg_mouse_wgetch((state == sTEXT) ? form : dialog, &fkey); 6424c8945a0SNathan Whitehorn if (dlg_result_key(key, fkey, &result)) 6434c8945a0SNathan Whitehorn break; 6444c8945a0SNathan Whitehorn 6454c8945a0SNathan Whitehorn /* handle non-functionkeys */ 6464c8945a0SNathan Whitehorn if (!fkey) { 6474c8945a0SNathan Whitehorn if (state != sTEXT) { 6484c8945a0SNathan Whitehorn code = dlg_char_to_button(key, buttons); 6494c8945a0SNathan Whitehorn if (code >= 0) { 6504c8945a0SNathan Whitehorn dlg_del_window(dialog); 6514c8945a0SNathan Whitehorn result = dlg_ok_buttoncode(code); 6524c8945a0SNathan Whitehorn continue; 6534c8945a0SNathan Whitehorn } 6544c8945a0SNathan Whitehorn if (key == ' ') { 6554c8945a0SNathan Whitehorn fkey = TRUE; 6564c8945a0SNathan Whitehorn key = DLGK_ENTER; 6574c8945a0SNathan Whitehorn } 6584c8945a0SNathan Whitehorn } 6594c8945a0SNathan Whitehorn } 6604c8945a0SNathan Whitehorn 6614c8945a0SNathan Whitehorn /* handle functionkeys */ 6624c8945a0SNathan Whitehorn if (fkey) { 6634c8945a0SNathan Whitehorn bool do_scroll = FALSE; 6644c8945a0SNathan Whitehorn bool do_tab = FALSE; 6654c8945a0SNathan Whitehorn int move_by = 0; 6664c8945a0SNathan Whitehorn 6674c8945a0SNathan Whitehorn switch (key) { 6684c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_PPAGE): 6694c8945a0SNathan Whitehorn case DLGK_PAGE_PREV: 6704c8945a0SNathan Whitehorn do_scroll = TRUE; 6714c8945a0SNathan Whitehorn move_by = -form_height; 6724c8945a0SNathan Whitehorn break; 6734c8945a0SNathan Whitehorn 6744c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_NPAGE): 6754c8945a0SNathan Whitehorn case DLGK_PAGE_NEXT: 6764c8945a0SNathan Whitehorn do_scroll = TRUE; 6774c8945a0SNathan Whitehorn move_by = form_height; 6784c8945a0SNathan Whitehorn break; 6794c8945a0SNathan Whitehorn 6804c8945a0SNathan Whitehorn case DLGK_ENTER: 6814c8945a0SNathan Whitehorn dlg_del_window(dialog); 682682c9e0fSNathan Whitehorn result = (state >= 0) ? dlg_enter_buttoncode(state) : DLG_EXIT_OK; 6834c8945a0SNathan Whitehorn continue; 6844c8945a0SNathan Whitehorn 6854c8945a0SNathan Whitehorn case DLGK_GRID_LEFT: 6864c8945a0SNathan Whitehorn if (state == sTEXT) 6874c8945a0SNathan Whitehorn break; 6884c8945a0SNathan Whitehorn /* FALLTHRU */ 6894c8945a0SNathan Whitehorn case DLGK_ITEM_PREV: 6904c8945a0SNathan Whitehorn if (state == sTEXT) { 6914c8945a0SNathan Whitehorn do_tab = TRUE; 6924c8945a0SNathan Whitehorn move_by = -1; 6934c8945a0SNathan Whitehorn break; 6944c8945a0SNathan Whitehorn } else { 6954c8945a0SNathan Whitehorn state = prev_valid_buttonindex(state, 0, non_editable); 6964c8945a0SNathan Whitehorn show_buttons = TRUE; 6974c8945a0SNathan Whitehorn continue; 6984c8945a0SNathan Whitehorn } 6994c8945a0SNathan Whitehorn 7002a3e3873SBaptiste Daroussin case DLGK_FORM_PREV: 7012a3e3873SBaptiste Daroussin if (state == sTEXT && !is_first_field(items, choice)) { 7022a3e3873SBaptiste Daroussin do_tab = TRUE; 7032a3e3873SBaptiste Daroussin move_by = -1; 7042a3e3873SBaptiste Daroussin break; 7052a3e3873SBaptiste Daroussin } else { 7062a3e3873SBaptiste Daroussin int old_state = state; 7072a3e3873SBaptiste Daroussin state = prev_valid_buttonindex(state, sTEXT, non_editable); 7082a3e3873SBaptiste Daroussin show_buttons = TRUE; 7092a3e3873SBaptiste Daroussin if (old_state >= 0 && state == sTEXT) { 7102a3e3873SBaptiste Daroussin new_choice = item_no - 1; 7112a3e3873SBaptiste Daroussin if (choice != new_choice) { 7122a3e3873SBaptiste Daroussin print_item(form, items + choice, scrollamt, FALSE); 7132a3e3873SBaptiste Daroussin choice = new_choice; 7142a3e3873SBaptiste Daroussin } 7152a3e3873SBaptiste Daroussin } 7162a3e3873SBaptiste Daroussin continue; 7172a3e3873SBaptiste Daroussin } 7182a3e3873SBaptiste Daroussin 7194c8945a0SNathan Whitehorn case DLGK_FIELD_PREV: 7204c8945a0SNathan Whitehorn state = prev_valid_buttonindex(state, sTEXT, non_editable); 7214c8945a0SNathan Whitehorn show_buttons = TRUE; 7224c8945a0SNathan Whitehorn continue; 7234c8945a0SNathan Whitehorn 7244c8945a0SNathan Whitehorn case DLGK_FIELD_NEXT: 7254c8945a0SNathan Whitehorn state = next_valid_buttonindex(state, sTEXT, non_editable); 7264c8945a0SNathan Whitehorn show_buttons = TRUE; 7274c8945a0SNathan Whitehorn continue; 7284c8945a0SNathan Whitehorn 7294c8945a0SNathan Whitehorn case DLGK_GRID_RIGHT: 7304c8945a0SNathan Whitehorn if (state == sTEXT) 7314c8945a0SNathan Whitehorn break; 7324c8945a0SNathan Whitehorn /* FALLTHRU */ 7334c8945a0SNathan Whitehorn 7344c8945a0SNathan Whitehorn case DLGK_ITEM_NEXT: 7354c8945a0SNathan Whitehorn if (state == sTEXT) { 7364c8945a0SNathan Whitehorn do_tab = TRUE; 7374c8945a0SNathan Whitehorn move_by = 1; 7384c8945a0SNathan Whitehorn break; 7394c8945a0SNathan Whitehorn } else { 7404c8945a0SNathan Whitehorn state = next_valid_buttonindex(state, 0, non_editable); 7414c8945a0SNathan Whitehorn show_buttons = TRUE; 7424c8945a0SNathan Whitehorn continue; 7434c8945a0SNathan Whitehorn } 7444c8945a0SNathan Whitehorn 7452a3e3873SBaptiste Daroussin case DLGK_FORM_NEXT: 7462a3e3873SBaptiste Daroussin if (state == sTEXT && !is_last_field(items, choice, item_no)) { 7472a3e3873SBaptiste Daroussin do_tab = TRUE; 7482a3e3873SBaptiste Daroussin move_by = 1; 7492a3e3873SBaptiste Daroussin break; 7502a3e3873SBaptiste Daroussin } else { 7512a3e3873SBaptiste Daroussin state = next_valid_buttonindex(state, sTEXT, non_editable); 7522a3e3873SBaptiste Daroussin show_buttons = TRUE; 7532a3e3873SBaptiste Daroussin if (state == sTEXT && choice) { 7542a3e3873SBaptiste Daroussin print_item(form, items + choice, scrollamt, FALSE); 7552a3e3873SBaptiste Daroussin choice = 0; 7562a3e3873SBaptiste Daroussin } 7572a3e3873SBaptiste Daroussin continue; 7582a3e3873SBaptiste Daroussin } 7592a3e3873SBaptiste Daroussin 7604c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 7614c8945a0SNathan Whitehorn case KEY_RESIZE: 7624c8945a0SNathan Whitehorn /* reset data */ 7634c8945a0SNathan Whitehorn height = old_height; 7644c8945a0SNathan Whitehorn width = old_width; 7654c8945a0SNathan Whitehorn /* repaint */ 7664c8945a0SNathan Whitehorn dlg_clear(); 7674c8945a0SNathan Whitehorn dlg_del_window(dialog); 7684c8945a0SNathan Whitehorn refresh(); 7694c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 7704c8945a0SNathan Whitehorn goto retry; 7714c8945a0SNathan Whitehorn #endif 7724c8945a0SNathan Whitehorn default: 7734c8945a0SNathan Whitehorn #if USE_MOUSE 7744c8945a0SNathan Whitehorn if (is_DLGK_MOUSE(key)) { 7754c8945a0SNathan Whitehorn if (key >= DLGK_MOUSE(KEY_MAX)) { 7764c8945a0SNathan Whitehorn int cell = key - DLGK_MOUSE(KEY_MAX); 7774c8945a0SNathan Whitehorn int row = (cell / getmaxx(form)) + scrollamt; 7784c8945a0SNathan Whitehorn int col = (cell % getmaxx(form)); 7794c8945a0SNathan Whitehorn int n; 7804c8945a0SNathan Whitehorn 7814c8945a0SNathan Whitehorn for (n = 0; n < item_no; ++n) { 7824c8945a0SNathan Whitehorn if (items[n].name_y == row 7834c8945a0SNathan Whitehorn && items[n].name_x <= col 7844c8945a0SNathan Whitehorn && (items[n].name_x + items[n].name_len > col 7854c8945a0SNathan Whitehorn || (items[n].name_y == items[n].text_y 7864c8945a0SNathan Whitehorn && items[n].text_x > col))) { 7874c8945a0SNathan Whitehorn if (!is_readonly(&(items[n]))) { 7884c8945a0SNathan Whitehorn field_changed = TRUE; 7894c8945a0SNathan Whitehorn break; 7904c8945a0SNathan Whitehorn } 7914c8945a0SNathan Whitehorn } 7924c8945a0SNathan Whitehorn if (items[n].text_y == row 7934c8945a0SNathan Whitehorn && items[n].text_x <= col 7944c8945a0SNathan Whitehorn && items[n].text_x + items[n].text_ilen > col) { 7954c8945a0SNathan Whitehorn if (!is_readonly(&(items[n]))) { 7964c8945a0SNathan Whitehorn field_changed = TRUE; 7974c8945a0SNathan Whitehorn break; 7984c8945a0SNathan Whitehorn } 7994c8945a0SNathan Whitehorn } 8004c8945a0SNathan Whitehorn } 8014c8945a0SNathan Whitehorn if (field_changed) { 8024c8945a0SNathan Whitehorn print_item(form, items + choice, scrollamt, FALSE); 8034c8945a0SNathan Whitehorn choice = n; 8044c8945a0SNathan Whitehorn continue; 8054c8945a0SNathan Whitehorn } 8064c8945a0SNathan Whitehorn beep(); 8074c8945a0SNathan Whitehorn } else if ((code = dlg_ok_buttoncode(key - M_EVENT)) >= 0) { 8084c8945a0SNathan Whitehorn result = code; 8094c8945a0SNathan Whitehorn } 8104c8945a0SNathan Whitehorn continue; 8114c8945a0SNathan Whitehorn } 8124c8945a0SNathan Whitehorn #endif 8134c8945a0SNathan Whitehorn break; 8144c8945a0SNathan Whitehorn } 8154c8945a0SNathan Whitehorn 8164c8945a0SNathan Whitehorn new_scroll = scrollamt; 8174c8945a0SNathan Whitehorn new_choice = choice; 8184c8945a0SNathan Whitehorn if (do_scroll) { 8194c8945a0SNathan Whitehorn if (scroll_next(form, items, move_by, &new_choice, &new_scroll)) { 8204c8945a0SNathan Whitehorn if (choice != new_choice) { 8214c8945a0SNathan Whitehorn choice = new_choice; 8224c8945a0SNathan Whitehorn field_changed = TRUE; 8234c8945a0SNathan Whitehorn } 8244c8945a0SNathan Whitehorn if (scrollamt != new_scroll) { 8254c8945a0SNathan Whitehorn scrollamt = new_scroll; 8264c8945a0SNathan Whitehorn scroll_changed = TRUE; 8274c8945a0SNathan Whitehorn } 8284c8945a0SNathan Whitehorn } 8294c8945a0SNathan Whitehorn continue; 8304c8945a0SNathan Whitehorn } 8314c8945a0SNathan Whitehorn if (do_tab) { 8324c8945a0SNathan Whitehorn if (tab_next(form, items, item_no, move_by, &new_choice, &new_scroll)) { 8334c8945a0SNathan Whitehorn if (choice != new_choice) { 8344c8945a0SNathan Whitehorn choice = new_choice; 8354c8945a0SNathan Whitehorn field_changed = TRUE; 8364c8945a0SNathan Whitehorn } 8374c8945a0SNathan Whitehorn if (scrollamt != new_scroll) { 8384c8945a0SNathan Whitehorn scrollamt = new_scroll; 8394c8945a0SNathan Whitehorn scroll_changed = TRUE; 8404c8945a0SNathan Whitehorn } 8414c8945a0SNathan Whitehorn } 8424c8945a0SNathan Whitehorn continue; 8434c8945a0SNathan Whitehorn } 8444c8945a0SNathan Whitehorn } 8454c8945a0SNathan Whitehorn 8464c8945a0SNathan Whitehorn if (state == sTEXT) { /* Input box selected */ 8474c8945a0SNathan Whitehorn if (!is_readonly(current)) 8484c8945a0SNathan Whitehorn edit = dlg_edit_string(current->text, &chr_offset, key, 8494c8945a0SNathan Whitehorn fkey, first); 8504c8945a0SNathan Whitehorn if (edit) { 8514c8945a0SNathan Whitehorn dlg_show_string(form, current->text, chr_offset, 8524c8945a0SNathan Whitehorn form_active_text_attr, 8534c8945a0SNathan Whitehorn current->text_y - scrollamt, 8544c8945a0SNathan Whitehorn current->text_x, 8554c8945a0SNathan Whitehorn current->text_len, 8564c8945a0SNathan Whitehorn is_hidden(current), first); 8574c8945a0SNathan Whitehorn continue; 8584c8945a0SNathan Whitehorn } 8594c8945a0SNathan Whitehorn } 8604c8945a0SNathan Whitehorn 8614c8945a0SNathan Whitehorn } 8624c8945a0SNathan Whitehorn 8634c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 8644c8945a0SNathan Whitehorn dlg_del_window(dialog); 8654c8945a0SNathan Whitehorn free(prompt); 8664c8945a0SNathan Whitehorn 8674c8945a0SNathan Whitehorn *current_item = choice; 8684c8945a0SNathan Whitehorn return result; 8694c8945a0SNathan Whitehorn } 8704c8945a0SNathan Whitehorn 8714c8945a0SNathan Whitehorn /* 8724c8945a0SNathan Whitehorn * Free memory owned by a list of DIALOG_FORMITEM's. 8734c8945a0SNathan Whitehorn */ 8744c8945a0SNathan Whitehorn void 8754c8945a0SNathan Whitehorn dlg_free_formitems(DIALOG_FORMITEM * items) 8764c8945a0SNathan Whitehorn { 8774c8945a0SNathan Whitehorn int n; 8784c8945a0SNathan Whitehorn for (n = 0; items[n].name != 0; ++n) { 8794c8945a0SNathan Whitehorn if (items[n].name_free) 8804c8945a0SNathan Whitehorn free(items[n].name); 8814c8945a0SNathan Whitehorn if (items[n].text_free) 8824c8945a0SNathan Whitehorn free(items[n].text); 8834c8945a0SNathan Whitehorn if (items[n].help_free && items[n].help != dlg_strempty()) 8844c8945a0SNathan Whitehorn free(items[n].help); 8854c8945a0SNathan Whitehorn } 8864c8945a0SNathan Whitehorn free(items); 8874c8945a0SNathan Whitehorn } 8884c8945a0SNathan Whitehorn 8894c8945a0SNathan Whitehorn /* 8904c8945a0SNathan Whitehorn * The script accepts values beginning at 1, while curses starts at 0. 8914c8945a0SNathan Whitehorn */ 8924c8945a0SNathan Whitehorn int 8934c8945a0SNathan Whitehorn dlg_ordinate(const char *s) 8944c8945a0SNathan Whitehorn { 8954c8945a0SNathan Whitehorn int result = atoi(s); 8964c8945a0SNathan Whitehorn if (result > 0) 8974c8945a0SNathan Whitehorn --result; 8984c8945a0SNathan Whitehorn else 8994c8945a0SNathan Whitehorn result = 0; 9004c8945a0SNathan Whitehorn return result; 9014c8945a0SNathan Whitehorn } 9024c8945a0SNathan Whitehorn 9034c8945a0SNathan Whitehorn int 9044c8945a0SNathan Whitehorn dialog_form(const char *title, 9054c8945a0SNathan Whitehorn const char *cprompt, 9064c8945a0SNathan Whitehorn int height, 9074c8945a0SNathan Whitehorn int width, 9084c8945a0SNathan Whitehorn int form_height, 9094c8945a0SNathan Whitehorn int item_no, 9104c8945a0SNathan Whitehorn char **items) 9114c8945a0SNathan Whitehorn { 9124c8945a0SNathan Whitehorn int result; 9134c8945a0SNathan Whitehorn int choice; 9144c8945a0SNathan Whitehorn int i; 9154c8945a0SNathan Whitehorn DIALOG_FORMITEM *listitems; 9164c8945a0SNathan Whitehorn DIALOG_VARS save_vars; 9174c8945a0SNathan Whitehorn bool show_status = FALSE; 918*febdb468SDevin Teske char *help_result; 9194c8945a0SNathan Whitehorn 9204c8945a0SNathan Whitehorn dlg_save_vars(&save_vars); 9214c8945a0SNathan Whitehorn dialog_vars.separate_output = TRUE; 9224c8945a0SNathan Whitehorn 9234c8945a0SNathan Whitehorn listitems = dlg_calloc(DIALOG_FORMITEM, (size_t) item_no + 1); 9244c8945a0SNathan Whitehorn assert_ptr(listitems, "dialog_form"); 9254c8945a0SNathan Whitehorn 9264c8945a0SNathan Whitehorn for (i = 0; i < item_no; ++i) { 9274c8945a0SNathan Whitehorn listitems[i].type = dialog_vars.formitem_type; 9284c8945a0SNathan Whitehorn listitems[i].name = ItemName(i); 9294c8945a0SNathan Whitehorn listitems[i].name_len = (int) strlen(ItemName(i)); 9304c8945a0SNathan Whitehorn listitems[i].name_y = dlg_ordinate(ItemNameY(i)); 9314c8945a0SNathan Whitehorn listitems[i].name_x = dlg_ordinate(ItemNameX(i)); 9324c8945a0SNathan Whitehorn listitems[i].text = ItemText(i); 9334c8945a0SNathan Whitehorn listitems[i].text_len = (int) strlen(ItemText(i)); 9344c8945a0SNathan Whitehorn listitems[i].text_y = dlg_ordinate(ItemTextY(i)); 9354c8945a0SNathan Whitehorn listitems[i].text_x = dlg_ordinate(ItemTextX(i)); 9364c8945a0SNathan Whitehorn listitems[i].text_flen = atoi(ItemTextFLen(i)); 9374c8945a0SNathan Whitehorn listitems[i].text_ilen = atoi(ItemTextILen(i)); 9384c8945a0SNathan Whitehorn listitems[i].help = ((dialog_vars.item_help) 9394c8945a0SNathan Whitehorn ? ItemHelp(i) 9404c8945a0SNathan Whitehorn : dlg_strempty()); 9414c8945a0SNathan Whitehorn } 9424c8945a0SNathan Whitehorn 9434c8945a0SNathan Whitehorn result = dlg_form(title, 9444c8945a0SNathan Whitehorn cprompt, 9454c8945a0SNathan Whitehorn height, 9464c8945a0SNathan Whitehorn width, 9474c8945a0SNathan Whitehorn form_height, 9484c8945a0SNathan Whitehorn item_no, 9494c8945a0SNathan Whitehorn listitems, 9504c8945a0SNathan Whitehorn &choice); 9514c8945a0SNathan Whitehorn 9524c8945a0SNathan Whitehorn switch (result) { 9534c8945a0SNathan Whitehorn case DLG_EXIT_OK: /* FALLTHRU */ 9544c8945a0SNathan Whitehorn case DLG_EXIT_EXTRA: 9554c8945a0SNathan Whitehorn show_status = TRUE; 9564c8945a0SNathan Whitehorn break; 9574c8945a0SNathan Whitehorn case DLG_EXIT_HELP: 958*febdb468SDevin Teske dlg_add_help_formitem(&result, &help_result, &listitems[choice]); 9594c8945a0SNathan Whitehorn show_status = dialog_vars.help_status; 960*febdb468SDevin Teske dlg_add_string(help_result); 9614c8945a0SNathan Whitehorn if (show_status) 9624c8945a0SNathan Whitehorn dlg_add_separator(); 9634c8945a0SNathan Whitehorn break; 9644c8945a0SNathan Whitehorn } 9654c8945a0SNathan Whitehorn if (show_status) { 9664c8945a0SNathan Whitehorn for (i = 0; i < item_no; i++) { 9674c8945a0SNathan Whitehorn if (listitems[i].text_flen > 0) { 9684c8945a0SNathan Whitehorn dlg_add_string(listitems[i].text); 9694c8945a0SNathan Whitehorn dlg_add_separator(); 9704c8945a0SNathan Whitehorn } 9714c8945a0SNathan Whitehorn } 9722a3e3873SBaptiste Daroussin dlg_add_last_key(-1); 9734c8945a0SNathan Whitehorn } 9744c8945a0SNathan Whitehorn 9754c8945a0SNathan Whitehorn dlg_free_formitems(listitems); 9764c8945a0SNathan Whitehorn dlg_restore_vars(&save_vars); 9774c8945a0SNathan Whitehorn 9784c8945a0SNathan Whitehorn return result; 9794c8945a0SNathan Whitehorn } 980