1251839Sbapt/* 2255852Sdteske * $Id: buildlist.c,v 1.59 2013/09/02 17:01:02 tom Exp $ 3251839Sbapt * 4251839Sbapt * buildlist.c -- implements the buildlist dialog 5251839Sbapt * 6251839Sbapt * Copyright 2012,2013 Thomas E. Dickey 7251839Sbapt * 8251839Sbapt * This program is free software; you can redistribute it and/or modify 9251839Sbapt * it under the terms of the GNU Lesser General Public License, version 2.1 10251839Sbapt * as published by the Free Software Foundation. 11251839Sbapt * 12251839Sbapt * This program is distributed in the hope that it will be useful, but 13251839Sbapt * WITHOUT ANY WARRANTY; without even the implied warranty of 14251839Sbapt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15251839Sbapt * Lesser General Public License for more details. 16251839Sbapt * 17251839Sbapt * You should have received a copy of the GNU Lesser General Public 18251839Sbapt * License along with this program; if not, write to 19251839Sbapt * Free Software Foundation, Inc. 20251839Sbapt * 51 Franklin St., Fifth Floor 21251839Sbapt * Boston, MA 02110, USA. 22251839Sbapt */ 23251839Sbapt 24251839Sbapt#include <dialog.h> 25251839Sbapt#include <dlg_keys.h> 26251839Sbapt 27251839Sbapt/* 28251839Sbapt * Visually like menubox, but two columns. 29251839Sbapt */ 30251839Sbapt 31251839Sbapt#define sLEFT (-2) 32251839Sbapt#define sRIGHT (-1) 33251839Sbapt 34251839Sbapt#define KEY_TOGGLE ' ' 35251839Sbapt#define KEY_LEFTCOL '^' 36251839Sbapt#define KEY_RIGHTCOL '$' 37251839Sbapt 38251839Sbapt#define MIN_HIGH (1 + (5 * MARGIN)) 39251839Sbapt 40251839Sbapttypedef struct { 41251839Sbapt WINDOW *win; 42251839Sbapt int box_y; 43251839Sbapt int box_x; 44251839Sbapt int top_index; 45251839Sbapt int cur_index; 46251839Sbapt} MY_DATA; 47251839Sbapt 48251839Sbapttypedef struct { 49251839Sbapt DIALOG_LISTITEM *items; 50251839Sbapt int base_y; /* base for mouse coordinates */ 51251839Sbapt int base_x; 52251839Sbapt int use_height; /* actual size of column box */ 53251839Sbapt int use_width; 54251839Sbapt int item_no; 55251839Sbapt int check_x; 56251839Sbapt int item_x; 57251839Sbapt MY_DATA list[2]; 58251839Sbapt} ALL_DATA; 59251839Sbapt 60251839Sbapt/* 61251839Sbapt * Print list item. The 'selected' parameter is true if 'choice' is the 62251839Sbapt * current item. That one is colored differently from the other items. 63251839Sbapt */ 64251839Sbaptstatic void 65251839Sbaptprint_item(ALL_DATA * data, 66251839Sbapt WINDOW *win, 67251839Sbapt DIALOG_LISTITEM * item, 68251839Sbapt int choice, 69251839Sbapt int selected) 70251839Sbapt{ 71251839Sbapt chtype save = dlg_get_attrs(win); 72251839Sbapt int i; 73251839Sbapt bool both = (!dialog_vars.no_tags && !dialog_vars.no_items); 74251839Sbapt bool first = TRUE; 75251839Sbapt int climit = (data->item_x - data->check_x - 1); 76251839Sbapt const char *show = (dialog_vars.no_items 77251839Sbapt ? item->name 78251839Sbapt : item->text); 79251839Sbapt 80251839Sbapt /* Clear 'residue' of last item */ 81251839Sbapt (void) wattrset(win, menubox_attr); 82251839Sbapt (void) wmove(win, choice, 0); 83251839Sbapt for (i = 0; i < getmaxx(win); i++) 84251839Sbapt (void) waddch(win, ' '); 85251839Sbapt 86251839Sbapt (void) wmove(win, choice, data->check_x); 87251839Sbapt (void) wattrset(win, menubox_attr); 88251839Sbapt 89251839Sbapt if (both) { 90251839Sbapt dlg_print_listitem(win, item->name, climit, first, selected); 91251839Sbapt (void) waddch(win, ' '); 92251839Sbapt first = FALSE; 93251839Sbapt } 94251839Sbapt 95251839Sbapt (void) wmove(win, choice, data->item_x); 96251839Sbapt climit = (getmaxx(win) - data->item_x + 1); 97251839Sbapt dlg_print_listitem(win, show, climit, first, selected); 98251839Sbapt 99251839Sbapt if (selected) { 100251839Sbapt dlg_item_help(item->help); 101251839Sbapt } 102251839Sbapt (void) wattrset(win, save); 103251839Sbapt} 104251839Sbapt 105251839Sbapt/* 106251839Sbapt * Prints either the left (unselected) or right (selected) list. 107251839Sbapt */ 108251839Sbaptstatic void 109251839Sbaptprint_1_list(ALL_DATA * data, 110251839Sbapt int choice, 111251839Sbapt int selected) 112251839Sbapt{ 113251839Sbapt MY_DATA *moi = data->list + selected; 114251839Sbapt WINDOW *win = moi->win; 115251839Sbapt int i, j; 116251839Sbapt int last = 0; 117251839Sbapt int max_rows = getmaxy(win); 118251839Sbapt 119251839Sbapt for (i = j = 0; j < max_rows; i++) { 120251839Sbapt int ii = i + moi->top_index; 121251839Sbapt if (ii >= data->item_no) { 122251839Sbapt break; 123251839Sbapt } else if (!(selected ^ (data->items[ii].state != 0))) { 124251839Sbapt print_item(data, 125251839Sbapt win, 126251839Sbapt &data->items[ii], 127251839Sbapt j, ii == choice); 128251839Sbapt last = ++j; 129251839Sbapt } 130251839Sbapt } 131251839Sbapt if (wmove(win, last, 0) != ERR) 132251839Sbapt wclrtobot(win); 133251839Sbapt (void) wnoutrefresh(win); 134251839Sbapt} 135251839Sbapt 136251839Sbapt/* 137251839Sbapt * Return the previous item from the list, staying in the same column. If no 138251839Sbapt * further movement is possible, return the same choice as given. 139251839Sbapt */ 140251839Sbaptstatic int 141251839Sbaptprev_item(ALL_DATA * data, int choice, int selected) 142251839Sbapt{ 143251839Sbapt int result = choice; 144251839Sbapt int n; 145251839Sbapt 146251839Sbapt for (n = choice - 1; n >= 0; --n) { 147251839Sbapt if ((data->items[n].state != 0) == selected) { 148251839Sbapt result = n; 149251839Sbapt break; 150251839Sbapt } 151251839Sbapt } 152251839Sbapt return result; 153251839Sbapt} 154251839Sbapt 155251839Sbapt/* 156251839Sbapt * Return true if the given choice is on the first page in the current column. 157251839Sbapt */ 158251839Sbaptstatic bool 159251839Sbaptstop_prev(ALL_DATA * data, int choice, int selected) 160251839Sbapt{ 161251839Sbapt return (prev_item(data, choice, selected) == choice); 162251839Sbapt} 163251839Sbapt 164251839Sbaptstatic bool 165251839Sbaptcheck_hotkey(DIALOG_LISTITEM * items, int choice, int selected) 166251839Sbapt{ 167251839Sbapt bool result = FALSE; 168251839Sbapt 169251839Sbapt if ((items[choice].state != 0) == selected) { 170251839Sbapt if (dlg_match_char(dlg_last_getc(), 171251839Sbapt (dialog_vars.no_tags 172251839Sbapt ? items[choice].text 173251839Sbapt : items[choice].name))) { 174251839Sbapt result = TRUE; 175251839Sbapt } 176251839Sbapt } 177251839Sbapt return result; 178251839Sbapt} 179251839Sbapt 180251839Sbapt/* 181251839Sbapt * Return the next item from the list, staying in the same column. If no 182251839Sbapt * further movement is possible, return the same choice as given. 183251839Sbapt */ 184251839Sbaptstatic int 185251839Sbaptnext_item(ALL_DATA * data, int choice, int selected) 186251839Sbapt{ 187251839Sbapt int result = choice; 188251839Sbapt int n; 189251839Sbapt 190251839Sbapt for (n = choice + 1; n < data->item_no; ++n) { 191251839Sbapt if ((data->items[n].state != 0) == selected) { 192251839Sbapt result = n; 193251839Sbapt break; 194251839Sbapt } 195251839Sbapt } 196251839Sbapt dlg_trace_msg("next_item(%d) ->%d\n", choice, result); 197251839Sbapt return result; 198251839Sbapt} 199251839Sbapt 200251839Sbapt/* 201251839Sbapt * Translate a choice from items[] to a row-number in an unbounded column, 202251839Sbapt * starting at zero. 203251839Sbapt */ 204251839Sbaptstatic int 205251839Sbaptindex2row(ALL_DATA * data, int choice, int selected) 206251839Sbapt{ 207251839Sbapt int result = -1; 208251839Sbapt int n; 209251839Sbapt for (n = 0; n < data->item_no; ++n) { 210251839Sbapt if ((data->items[n].state != 0) == selected) { 211251839Sbapt ++result; 212251839Sbapt } 213251839Sbapt if (n == choice) 214251839Sbapt break; 215251839Sbapt } 216251839Sbapt return result; 217251839Sbapt} 218251839Sbapt 219251839Sbapt/* 220251839Sbapt * Return the first choice from items[] for the given column. 221251839Sbapt */ 222251839Sbaptstatic int 223251839Sbaptfirst_item(ALL_DATA * data, int selected) 224251839Sbapt{ 225251839Sbapt int result = -1; 226251839Sbapt int n; 227251839Sbapt 228251839Sbapt for (n = 0; n < data->item_no; ++n) { 229251839Sbapt if ((data->items[n].state != 0) == selected) { 230251839Sbapt result = n; 231251839Sbapt break; 232251839Sbapt } 233251839Sbapt } 234251839Sbapt return result; 235251839Sbapt} 236251839Sbapt 237251839Sbapt/* 238251839Sbapt * Return the last choice from items[] for the given column. 239251839Sbapt */ 240251839Sbaptstatic int 241251839Sbaptlast_item(ALL_DATA * data, int selected) 242251839Sbapt{ 243251839Sbapt int result = -1; 244251839Sbapt int n; 245251839Sbapt 246251839Sbapt for (n = data->item_no - 1; n >= 0; --n) { 247251839Sbapt if ((data->items[n].state != 0) == selected) { 248251839Sbapt result = n; 249251839Sbapt break; 250251839Sbapt } 251251839Sbapt } 252251839Sbapt return result; 253251839Sbapt} 254251839Sbapt 255251839Sbapt/* 256251839Sbapt * Convert a row-number back to an item number, i.e., index into items[]. 257251839Sbapt */ 258251839Sbaptstatic int 259251839Sbaptrow2index(ALL_DATA * data, int row, int selected) 260251839Sbapt{ 261251839Sbapt int result = -1; 262251839Sbapt int n; 263251839Sbapt for (n = 0; n < data->item_no; ++n) { 264251839Sbapt if ((data->items[n].state != 0) == selected) { 265251839Sbapt if (row-- <= 0) { 266251839Sbapt result = n; 267251839Sbapt break; 268251839Sbapt } 269251839Sbapt } 270251839Sbapt } 271251839Sbapt return result; 272251839Sbapt} 273251839Sbapt 274251839Sbaptstatic int 275251839Sbaptskip_rows(ALL_DATA * data, int row, int skip, int selected) 276251839Sbapt{ 277251839Sbapt int choice = row2index(data, row, selected); 278251839Sbapt int result = row; 279251839Sbapt int n; 280251839Sbapt if (skip > 0) { 281251839Sbapt for (n = choice + 1; n < data->item_no; ++n) { 282251839Sbapt if ((data->items[n].state != 0) == selected) { 283251839Sbapt ++result; 284251839Sbapt if (--skip <= 0) 285251839Sbapt break; 286251839Sbapt } 287251839Sbapt } 288251839Sbapt } else if (skip < 0) { 289251839Sbapt for (n = choice - 1; n >= 0; --n) { 290251839Sbapt if ((data->items[n].state != 0) == selected) { 291251839Sbapt --result; 292251839Sbapt if (++skip >= 0) 293251839Sbapt break; 294251839Sbapt } 295251839Sbapt } 296251839Sbapt } 297251839Sbapt return result; 298251839Sbapt} 299251839Sbapt 300251839Sbapt/* 301251839Sbapt * Find the closest item in the given column starting with the given choice. 302251839Sbapt */ 303251839Sbaptstatic int 304251839Sbaptclosest_item(ALL_DATA * data, int choice, int selected) 305251839Sbapt{ 306251839Sbapt int prev = choice; 307251839Sbapt int next = choice; 308251839Sbapt int result = choice; 309251839Sbapt int n; 310251839Sbapt 311251839Sbapt for (n = choice; n >= 0; --n) { 312251839Sbapt if ((data->items[n].state != 0) == selected) { 313251839Sbapt prev = n; 314251839Sbapt break; 315251839Sbapt } 316251839Sbapt } 317251839Sbapt for (n = choice; n < data->item_no; ++n) { 318251839Sbapt if ((data->items[n].state != 0) == selected) { 319251839Sbapt next = n; 320251839Sbapt break; 321251839Sbapt } 322251839Sbapt } 323251839Sbapt if (prev != choice) { 324251839Sbapt result = prev; 325251839Sbapt if (next != choice) { 326251839Sbapt if ((choice - prev) > (next - choice)) { 327251839Sbapt result = next; 328251839Sbapt } 329251839Sbapt } 330251839Sbapt } else if (next != choice) { 331251839Sbapt result = next; 332251839Sbapt } 333251839Sbapt return result; 334251839Sbapt} 335251839Sbapt 336251839Sbaptstatic void 337251839Sbaptprint_both(ALL_DATA * data, 338251839Sbapt int choice) 339251839Sbapt{ 340251839Sbapt int selected; 341251839Sbapt int cur_y, cur_x; 342251839Sbapt WINDOW *dialog = wgetparent(data->list[0].win); 343251839Sbapt 344251839Sbapt getyx(dialog, cur_y, cur_x); 345251839Sbapt for (selected = 0; selected < 2; ++selected) { 346251839Sbapt MY_DATA *moi = data->list + selected; 347251839Sbapt WINDOW *win = moi->win; 348251839Sbapt int thumb_top = index2row(data, moi->top_index, selected); 349251839Sbapt int thumb_max = index2row(data, -1, selected); 350251839Sbapt int thumb_end = thumb_top + getmaxy(win); 351251839Sbapt 352251839Sbapt print_1_list(data, choice, selected); 353251839Sbapt 354251839Sbapt dlg_mouse_setcode(selected * KEY_MAX); 355251839Sbapt dlg_draw_scrollbar(dialog, 356251839Sbapt (long) (moi->top_index), 357251839Sbapt (long) (thumb_top), 358251839Sbapt (long) MIN(thumb_end, thumb_max), 359251839Sbapt (long) thumb_max, 360251839Sbapt moi->box_x + data->check_x, 361251839Sbapt moi->box_x + getmaxx(win), 362251839Sbapt moi->box_y, 363251839Sbapt moi->box_y + getmaxy(win) + 1, 364251839Sbapt menubox_border2_attr, 365251839Sbapt menubox_border_attr); 366251839Sbapt } 367251839Sbapt (void) wmove(dialog, cur_y, cur_x); 368251839Sbapt dlg_mouse_setcode(0); 369251839Sbapt} 370251839Sbapt 371251839Sbaptstatic void 372251839Sbaptset_top_item(ALL_DATA * data, int value, int selected) 373251839Sbapt{ 374251839Sbapt if (value != data->list[selected].top_index) { 375251839Sbapt dlg_trace_msg("set top of %s column to %d\n", 376251839Sbapt selected ? "right" : "left", 377251839Sbapt value); 378251839Sbapt data->list[selected].top_index = value; 379251839Sbapt } 380251839Sbapt} 381251839Sbapt 382251839Sbapt/* 383251839Sbapt * Adjust the top-index as needed to ensure that it and the given item are 384251839Sbapt * visible. 385251839Sbapt */ 386251839Sbaptstatic void 387251839Sbaptfix_top_item(ALL_DATA * data, int cur_item, int selected) 388251839Sbapt{ 389251839Sbapt int top_item = data->list[selected].top_index; 390251839Sbapt int cur_row = index2row(data, cur_item, selected); 391251839Sbapt int top_row = index2row(data, top_item, selected); 392251839Sbapt 393251839Sbapt if (cur_row < top_row) { 394251839Sbapt top_item = cur_item; 395251839Sbapt } else if ((cur_row - top_row) > data->use_height) { 396251839Sbapt top_item = row2index(data, cur_row + 1 - data->use_height, selected); 397251839Sbapt } 398251839Sbapt if (cur_row < data->use_height) { 399251839Sbapt top_item = row2index(data, 0, selected); 400251839Sbapt } 401251839Sbapt dlg_trace_msg("fix_top_item(cur_item %d, selected %d) ->top_item %d\n", 402251839Sbapt cur_item, selected, top_item); 403251839Sbapt set_top_item(data, top_item, selected); 404251839Sbapt} 405251839Sbapt 406251839Sbapt/* 407251839Sbapt * This is an alternate interface to 'buildlist' which allows the application 408251839Sbapt * to read the list item states back directly without putting them in the 409251839Sbapt * output buffer. 410251839Sbapt */ 411251839Sbaptint 412251839Sbaptdlg_buildlist(const char *title, 413251839Sbapt const char *cprompt, 414251839Sbapt int height, 415251839Sbapt int width, 416251839Sbapt int list_height, 417251839Sbapt int item_no, 418251839Sbapt DIALOG_LISTITEM * items, 419251839Sbapt const char *states, 420251839Sbapt int order_mode, 421251839Sbapt int *current_item) 422251839Sbapt{ 423251839Sbapt /* *INDENT-OFF* */ 424251839Sbapt static DLG_KEYS_BINDING binding[] = { 425251839Sbapt HELPKEY_BINDINGS, 426251839Sbapt ENTERKEY_BINDINGS, 427251839Sbapt DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ), 428251839Sbapt DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), 429251839Sbapt DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), 430251839Sbapt DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ), 431251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_FIRST, KEY_HOME ), 432251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_LAST, KEY_END ), 433251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_LAST, KEY_LL ), 434251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_NEXT, '+' ), 435251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ), 436251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ), 437251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_PREV, '-' ), 438251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ), 439251839Sbapt DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ), 440251839Sbapt DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), 441251839Sbapt DLG_KEYS_DATA( DLGK_PAGE_NEXT, DLGK_MOUSE(KEY_NPAGE) ), 442251839Sbapt DLG_KEYS_DATA( DLGK_PAGE_NEXT, DLGK_MOUSE(KEY_NPAGE+KEY_MAX) ), 443251839Sbapt DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ), 444251839Sbapt DLG_KEYS_DATA( DLGK_PAGE_PREV, DLGK_MOUSE(KEY_PPAGE) ), 445251839Sbapt DLG_KEYS_DATA( DLGK_PAGE_PREV, DLGK_MOUSE(KEY_PPAGE+KEY_MAX) ), 446251839Sbapt DLG_KEYS_DATA( DLGK_GRID_LEFT, KEY_LEFTCOL ), 447251839Sbapt DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_RIGHTCOL ), 448251839Sbapt END_KEYS_BINDING 449251839Sbapt }; 450251839Sbapt /* *INDENT-ON* */ 451251839Sbapt 452251839Sbapt#ifdef KEY_RESIZE 453251839Sbapt int old_height = height; 454251839Sbapt int old_width = width; 455251839Sbapt#endif 456251839Sbapt ALL_DATA all; 457251839Sbapt MY_DATA *data = all.list; 458251839Sbapt int i, j, k, key2, found, x, y, cur_x, cur_y; 459251839Sbapt int key = 0, fkey; 460251839Sbapt bool save_visit = dialog_state.visit_items; 461251839Sbapt int button; 462251839Sbapt int cur_item; 463251839Sbapt int was_mouse; 464251839Sbapt int name_width, text_width, full_width, list_width; 465251839Sbapt int result = DLG_EXIT_UNKNOWN; 466251839Sbapt int num_states; 467251839Sbapt bool first = TRUE; 468251839Sbapt WINDOW *dialog; 469251839Sbapt char *prompt = dlg_strclone(cprompt); 470251839Sbapt const char **buttons = dlg_ok_labels(); 471251839Sbapt const char *widget_name = "buildlist"; 472251839Sbapt 473251839Sbapt (void) order_mode; 474251839Sbapt 475251839Sbapt /* 476251839Sbapt * Unlike other uses of --visit-items, we have two windows to visit. 477251839Sbapt */ 478251839Sbapt if (dialog_state.visit_cols) 479251839Sbapt dialog_state.visit_cols = 2; 480251839Sbapt 481251839Sbapt memset(&all, 0, sizeof(all)); 482251839Sbapt all.items = items; 483251839Sbapt all.item_no = item_no; 484251839Sbapt 485251839Sbapt if (dialog_vars.default_item != 0) { 486251839Sbapt cur_item = dlg_default_listitem(items); 487251839Sbapt } else { 488251839Sbapt if ((cur_item = first_item(&all, 0)) < 0) 489251839Sbapt cur_item = first_item(&all, 1); 490251839Sbapt } 491251839Sbapt button = (dialog_state.visit_items 492251839Sbapt ? (items[cur_item].state ? sRIGHT : sLEFT) 493251839Sbapt : dlg_default_button()); 494251839Sbapt 495251839Sbapt dlg_does_output(); 496251839Sbapt dlg_tab_correct_str(prompt); 497251839Sbapt 498251839Sbapt#ifdef KEY_RESIZE 499251839Sbapt retry: 500251839Sbapt#endif 501251839Sbapt 502251839Sbapt all.use_height = list_height; 503251839Sbapt all.use_width = (2 * (dlg_calc_list_width(item_no, items) 504251839Sbapt + 4 505251839Sbapt + 2 * MARGIN) 506251839Sbapt + 1); 507251839Sbapt all.use_width = MAX(26, all.use_width); 508251839Sbapt if (all.use_height == 0) { 509251839Sbapt /* calculate height without items (4) */ 510251839Sbapt dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, all.use_width); 511251839Sbapt dlg_calc_listh(&height, &all.use_height, item_no); 512251839Sbapt } else { 513251839Sbapt dlg_auto_size(title, prompt, 514251839Sbapt &height, &width, 515251839Sbapt MIN_HIGH + all.use_height, all.use_width); 516251839Sbapt } 517251839Sbapt dlg_button_layout(buttons, &width); 518251839Sbapt dlg_print_size(height, width); 519251839Sbapt dlg_ctl_size(height, width); 520251839Sbapt 521251839Sbapt /* we need at least two states */ 522251839Sbapt if (states == 0 || strlen(states) < 2) 523251839Sbapt states = " *"; 524251839Sbapt num_states = (int) strlen(states); 525251839Sbapt 526251839Sbapt x = dlg_box_x_ordinate(width); 527251839Sbapt y = dlg_box_y_ordinate(height); 528251839Sbapt 529251839Sbapt dialog = dlg_new_window(height, width, y, x); 530251839Sbapt dlg_register_window(dialog, widget_name, binding); 531251839Sbapt dlg_register_buttons(dialog, widget_name, buttons); 532251839Sbapt 533251839Sbapt dlg_mouse_setbase(all.base_x = x, all.base_y = y); 534251839Sbapt 535251839Sbapt dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr); 536251839Sbapt dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr); 537251839Sbapt dlg_draw_title(dialog, title); 538251839Sbapt 539251839Sbapt (void) wattrset(dialog, dialog_attr); 540251839Sbapt dlg_print_autowrap(dialog, prompt, height, width); 541251839Sbapt 542251839Sbapt list_width = (width - 6 * MARGIN - 2) / 2; 543251839Sbapt getyx(dialog, cur_y, cur_x); 544251839Sbapt data[0].box_y = cur_y + 1; 545251839Sbapt data[0].box_x = MARGIN + 1; 546251839Sbapt data[1].box_y = cur_y + 1; 547251839Sbapt data[1].box_x = data[0].box_x + 1 + 2 * MARGIN + list_width; 548251839Sbapt 549251839Sbapt /* 550251839Sbapt * After displaying the prompt, we know how much space we really have. 551251839Sbapt * Limit the list to avoid overwriting the ok-button. 552251839Sbapt */ 553251839Sbapt if (all.use_height + MIN_HIGH > height - cur_y) 554251839Sbapt all.use_height = height - MIN_HIGH - cur_y; 555251839Sbapt if (all.use_height <= 0) 556251839Sbapt all.use_height = 1; 557251839Sbapt 558251839Sbapt for (k = 0; k < 2; ++k) { 559251839Sbapt /* create new window for the list */ 560251839Sbapt data[k].win = dlg_sub_window(dialog, all.use_height, list_width, 561251839Sbapt y + data[k].box_y + 1, 562251839Sbapt x + data[k].box_x + 1); 563251839Sbapt 564251839Sbapt /* draw a box around the list items */ 565251839Sbapt dlg_draw_box(dialog, data[k].box_y, data[k].box_x, 566251839Sbapt all.use_height + 2 * MARGIN, 567251839Sbapt list_width + 2 * MARGIN, 568251839Sbapt menubox_border_attr, menubox_border2_attr); 569251839Sbapt } 570251839Sbapt 571251839Sbapt text_width = 0; 572251839Sbapt name_width = 0; 573251839Sbapt /* Find length of longest item to center buildlist */ 574251839Sbapt for (i = 0; i < item_no; i++) { 575251839Sbapt text_width = MAX(text_width, dlg_count_columns(items[i].text)); 576251839Sbapt name_width = MAX(name_width, dlg_count_columns(items[i].name)); 577251839Sbapt } 578251839Sbapt 579251839Sbapt /* If the name+text is wider than the list is allowed, then truncate 580251839Sbapt * one or both of them. If the name is no wider than 1/4 of the list, 581251839Sbapt * leave it intact. 582251839Sbapt */ 583251839Sbapt all.use_width = (list_width - 6 * MARGIN); 584251839Sbapt if (dialog_vars.no_tags && !dialog_vars.no_items) { 585251839Sbapt full_width = MIN(all.use_width, text_width); 586251839Sbapt } else if (dialog_vars.no_items) { 587251839Sbapt full_width = MIN(all.use_width, name_width); 588251839Sbapt } else { 589251839Sbapt if (text_width >= 0 590251839Sbapt && name_width >= 0 591251839Sbapt && all.use_width > 0 592251839Sbapt && text_width + name_width > all.use_width) { 593251839Sbapt int need = (int) (0.25 * all.use_width); 594251839Sbapt if (name_width > need) { 595251839Sbapt int want = (int) (all.use_width * ((double) name_width) / 596251839Sbapt (text_width + name_width)); 597251839Sbapt name_width = (want > need) ? want : need; 598251839Sbapt } 599251839Sbapt text_width = all.use_width - name_width; 600251839Sbapt } 601251839Sbapt full_width = text_width + name_width; 602251839Sbapt } 603251839Sbapt 604251839Sbapt all.check_x = (all.use_width - full_width) / 2; 605251839Sbapt all.item_x = ((dialog_vars.no_tags 606251839Sbapt ? 0 607251839Sbapt : (dialog_vars.no_items 608251839Sbapt ? 0 609251839Sbapt : (name_width + 2))) 610251839Sbapt + all.check_x); 611251839Sbapt 612251839Sbapt /* ensure we are scrolled to show the current choice */ 613251839Sbapt j = MIN(all.use_height, item_no); 614251839Sbapt for (i = 0; i < 2; ++i) { 615251839Sbapt int top_item = 0; 616251839Sbapt if ((items[cur_item].state != 0) == i) { 617251839Sbapt top_item = cur_item - j + 1; 618251839Sbapt if (top_item < 0) 619251839Sbapt top_item = 0; 620251839Sbapt set_top_item(&all, top_item, i); 621251839Sbapt } else { 622251839Sbapt set_top_item(&all, 0, i); 623251839Sbapt } 624251839Sbapt } 625251839Sbapt 626251839Sbapt /* register the new window, along with its borders */ 627251839Sbapt for (i = 0; i < 2; ++i) { 628251839Sbapt dlg_mouse_mkbigregion(data[i].box_y + 1, 629251839Sbapt data[i].box_x, 630251839Sbapt all.use_height, 631251839Sbapt list_width + 2, 632251839Sbapt 2 * KEY_MAX + (i * (1 + all.use_height)), 633251839Sbapt 1, 1, 1 /* by lines */ ); 634251839Sbapt } 635251839Sbapt 636251839Sbapt dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); 637251839Sbapt 638251839Sbapt while (result == DLG_EXIT_UNKNOWN) { 639251839Sbapt int which = (items[cur_item].state != 0); 640251839Sbapt MY_DATA *moi = data + which; 641251839Sbapt int at_top = index2row(&all, moi->top_index, which); 642251839Sbapt int at_end = index2row(&all, -1, which); 643251839Sbapt int at_bot = skip_rows(&all, at_top, all.use_height, which); 644251839Sbapt 645251839Sbapt dlg_trace_msg("\t** state %d:%d top %d (%d:%d:%d) %d\n", 646251839Sbapt cur_item, item_no - 1, 647251839Sbapt moi->top_index, 648251839Sbapt at_top, at_bot, at_end, 649251839Sbapt which); 650251839Sbapt 651251839Sbapt if (first) { 652251839Sbapt print_both(&all, cur_item); 653251839Sbapt dlg_trace_win(dialog); 654251839Sbapt first = FALSE; 655251839Sbapt } 656251839Sbapt 657251839Sbapt if (button < 0) { /* --visit-items */ 658251839Sbapt int cur_row = index2row(&all, cur_item, which); 659251839Sbapt cur_y = (data[which].box_y 660251839Sbapt + cur_row 661251839Sbapt + 1); 662251839Sbapt if (at_top > 0) 663251839Sbapt cur_y -= at_top; 664251839Sbapt cur_x = (data[which].box_x 665251839Sbapt + all.check_x + 1); 666251839Sbapt dlg_trace_msg("\t...visit row %d (%d,%d)\n", cur_row, cur_y, cur_x); 667251839Sbapt wmove(dialog, cur_y, cur_x); 668251839Sbapt } 669251839Sbapt 670251839Sbapt key = dlg_mouse_wgetch(dialog, &fkey); 671251839Sbapt if (dlg_result_key(key, fkey, &result)) 672251839Sbapt break; 673251839Sbapt 674251839Sbapt was_mouse = (fkey && is_DLGK_MOUSE(key)); 675251839Sbapt if (was_mouse) 676251839Sbapt key -= M_EVENT; 677251839Sbapt 678251839Sbapt if (!was_mouse) { 679251839Sbapt ; 680251839Sbapt } else if (key >= 2 * KEY_MAX) { 681251839Sbapt i = (key - 2 * KEY_MAX) % (1 + all.use_height); 682251839Sbapt j = (key - 2 * KEY_MAX) / (1 + all.use_height); 683251839Sbapt k = row2index(&all, i + at_top, j); 684251839Sbapt dlg_trace_msg("MOUSE column %d, row %d ->item %d\n", j, i, k); 685251839Sbapt if (k >= 0 && j < 2) { 686251839Sbapt if (j != which) { 687251839Sbapt /* 688251839Sbapt * Mouse click was in the other column. 689251839Sbapt */ 690251839Sbapt moi = data + j; 691251839Sbapt fix_top_item(&all, k, j); 692251839Sbapt } 693251839Sbapt which = j; 694251839Sbapt at_top = index2row(&all, moi->top_index, which); 695251839Sbapt at_bot = skip_rows(&all, at_top, all.use_height, which); 696251839Sbapt cur_item = k; 697251839Sbapt print_both(&all, cur_item); 698251839Sbapt key = KEY_TOGGLE; /* force the selected item to toggle */ 699251839Sbapt } else { 700251839Sbapt beep(); 701251839Sbapt continue; 702251839Sbapt } 703251839Sbapt fkey = FALSE; 704251839Sbapt } else if (key >= KEY_MIN) { 705251839Sbapt if (key > KEY_MAX) { 706251839Sbapt if (which == 0) { 707251839Sbapt key = KEY_RIGHTCOL; /* switch to right-column */ 708251839Sbapt fkey = FALSE; 709251839Sbapt } else { 710251839Sbapt key -= KEY_MAX; 711251839Sbapt } 712251839Sbapt } else { 713251839Sbapt if (which == 1) { 714251839Sbapt key = KEY_LEFTCOL; /* switch to left-column */ 715251839Sbapt fkey = FALSE; 716251839Sbapt } 717251839Sbapt } 718251839Sbapt key = dlg_lookup_key(dialog, key, &fkey); 719251839Sbapt } 720251839Sbapt 721251839Sbapt /* 722251839Sbapt * A space toggles the item status. Normally we put the cursor on 723251839Sbapt * the next available item in the same column. But if there are no 724251839Sbapt * more items in the column, move the cursor to the other column. 725251839Sbapt */ 726251839Sbapt if (key == KEY_TOGGLE) { 727251839Sbapt int new_choice; 728251839Sbapt int new_state = items[cur_item].state + 1; 729251839Sbapt 730251839Sbapt if ((new_choice = next_item(&all, cur_item, which)) == cur_item) { 731251839Sbapt new_choice = prev_item(&all, cur_item, which); 732251839Sbapt } 733251839Sbapt dlg_trace_msg("cur_item %d, new_choice:%d\n", cur_item, new_choice); 734251839Sbapt if (new_state >= num_states) 735251839Sbapt new_state = 0; 736251839Sbapt 737251839Sbapt items[cur_item].state = new_state; 738251839Sbapt if (cur_item == moi->top_index) { 739251839Sbapt set_top_item(&all, new_choice, which); 740251839Sbapt } 741251839Sbapt 742251839Sbapt if (new_choice >= 0) { 743251839Sbapt fix_top_item(&all, cur_item, !which); 744251839Sbapt cur_item = new_choice; 745251839Sbapt } 746251839Sbapt print_both(&all, cur_item); 747251839Sbapt dlg_trace_win(dialog); 748251839Sbapt continue; /* wait for another key press */ 749251839Sbapt } 750251839Sbapt 751251839Sbapt /* 752251839Sbapt * Check if key pressed matches first character of any item tag in 753251839Sbapt * list. If there is more than one match, we will cycle through 754251839Sbapt * each one as the same key is pressed repeatedly. 755251839Sbapt */ 756251839Sbapt found = FALSE; 757251839Sbapt if (!fkey) { 758251839Sbapt if (button < 0 || !dialog_state.visit_items) { 759251839Sbapt for (j = cur_item + 1; j < item_no; j++) { 760251839Sbapt if (check_hotkey(items, j, which)) { 761251839Sbapt found = TRUE; 762251839Sbapt i = j; 763251839Sbapt break; 764251839Sbapt } 765251839Sbapt } 766251839Sbapt if (!found) { 767251839Sbapt for (j = 0; j <= cur_item; j++) { 768251839Sbapt if (check_hotkey(items, j, which)) { 769251839Sbapt found = TRUE; 770251839Sbapt i = j; 771251839Sbapt break; 772251839Sbapt } 773251839Sbapt } 774251839Sbapt } 775251839Sbapt if (found) 776251839Sbapt dlg_flush_getc(); 777251839Sbapt } else if ((j = dlg_char_to_button(key, buttons)) >= 0) { 778251839Sbapt button = j; 779251839Sbapt ungetch('\n'); 780251839Sbapt continue; 781251839Sbapt } 782251839Sbapt } 783251839Sbapt 784251839Sbapt /* 785251839Sbapt * A single digit (1-9) positions the selection to that line in the 786251839Sbapt * current screen. 787251839Sbapt */ 788251839Sbapt if (!found 789251839Sbapt && (key <= '9') 790251839Sbapt && (key > '0') 791251839Sbapt && (key - '1' < at_bot)) { 792251839Sbapt found = TRUE; 793251839Sbapt i = key - '1'; 794251839Sbapt } 795251839Sbapt 796251839Sbapt if (!found && fkey) { 797251839Sbapt switch (key) { 798251839Sbapt case DLGK_FIELD_PREV: 799251839Sbapt if ((button == sRIGHT) && dialog_state.visit_items) { 800251839Sbapt key = DLGK_GRID_LEFT; 801251839Sbapt button = sLEFT; 802251839Sbapt } else { 803251839Sbapt button = dlg_prev_button(buttons, button); 804251839Sbapt dlg_draw_buttons(dialog, height - 2, 0, buttons, button, 805251839Sbapt FALSE, width); 806251839Sbapt if (button == sRIGHT) { 807251839Sbapt key = DLGK_GRID_RIGHT; 808251839Sbapt } else { 809251839Sbapt continue; 810251839Sbapt } 811251839Sbapt } 812251839Sbapt break; 813251839Sbapt case DLGK_FIELD_NEXT: 814251839Sbapt if ((button == sLEFT) && dialog_state.visit_items) { 815251839Sbapt key = DLGK_GRID_RIGHT; 816251839Sbapt button = sRIGHT; 817251839Sbapt } else { 818251839Sbapt button = dlg_next_button(buttons, button); 819251839Sbapt dlg_draw_buttons(dialog, height - 2, 0, buttons, button, 820251839Sbapt FALSE, width); 821251839Sbapt if (button == sLEFT) { 822251839Sbapt key = DLGK_GRID_LEFT; 823251839Sbapt } else { 824251839Sbapt continue; 825251839Sbapt } 826251839Sbapt } 827251839Sbapt break; 828251839Sbapt } 829251839Sbapt } 830251839Sbapt 831251839Sbapt if (!found && fkey) { 832251839Sbapt i = cur_item; 833251839Sbapt found = TRUE; 834251839Sbapt switch (key) { 835251839Sbapt case DLGK_GRID_LEFT: 836251839Sbapt i = closest_item(&all, cur_item, 0); 837251839Sbapt fix_top_item(&all, i, 0); 838251839Sbapt break; 839251839Sbapt case DLGK_GRID_RIGHT: 840251839Sbapt i = closest_item(&all, cur_item, 1); 841251839Sbapt fix_top_item(&all, i, 1); 842251839Sbapt break; 843251839Sbapt case DLGK_PAGE_PREV: 844251839Sbapt if (cur_item > moi->top_index) { 845251839Sbapt i = moi->top_index; 846251839Sbapt } else if (moi->top_index != 0) { 847251839Sbapt int temp = at_top; 848251839Sbapt if ((temp -= all.use_height) < 0) 849251839Sbapt temp = 0; 850251839Sbapt i = row2index(&all, temp, which); 851251839Sbapt } 852251839Sbapt break; 853251839Sbapt case DLGK_PAGE_NEXT: 854251839Sbapt if ((at_end - at_bot) < all.use_height) { 855251839Sbapt i = next_item(&all, 856251839Sbapt row2index(&all, at_end, which), 857251839Sbapt which); 858251839Sbapt } else { 859251839Sbapt i = next_item(&all, 860251839Sbapt row2index(&all, at_bot, which), 861251839Sbapt which); 862251839Sbapt at_top = at_bot; 863251839Sbapt set_top_item(&all, 864251839Sbapt next_item(&all, 865251839Sbapt row2index(&all, at_top, which), 866251839Sbapt which), 867251839Sbapt which); 868251839Sbapt at_bot = skip_rows(&all, at_top, all.use_height, which); 869251839Sbapt at_bot = MIN(at_bot, at_end); 870251839Sbapt } 871251839Sbapt break; 872251839Sbapt case DLGK_ITEM_FIRST: 873251839Sbapt i = first_item(&all, which); 874251839Sbapt break; 875251839Sbapt case DLGK_ITEM_LAST: 876251839Sbapt i = last_item(&all, which); 877251839Sbapt break; 878251839Sbapt case DLGK_ITEM_PREV: 879251839Sbapt i = prev_item(&all, cur_item, which); 880251839Sbapt if (stop_prev(&all, cur_item, which)) 881251839Sbapt continue; 882251839Sbapt break; 883251839Sbapt case DLGK_ITEM_NEXT: 884251839Sbapt i = next_item(&all, cur_item, which); 885251839Sbapt break; 886251839Sbapt default: 887251839Sbapt found = FALSE; 888251839Sbapt break; 889251839Sbapt } 890251839Sbapt } 891251839Sbapt 892251839Sbapt if (found) { 893251839Sbapt if (i != cur_item) { 894251839Sbapt int now_at = index2row(&all, i, which); 895251839Sbapt int oops = item_no; 896251839Sbapt int old_item; 897251839Sbapt 898251839Sbapt dlg_trace_msg("<--CHOICE %d\n", i); 899251839Sbapt dlg_trace_msg("<--topITM %d\n", moi->top_index); 900251839Sbapt dlg_trace_msg("<--now_at %d\n", now_at); 901251839Sbapt dlg_trace_msg("<--at_top %d\n", at_top); 902251839Sbapt dlg_trace_msg("<--at_bot %d\n", at_bot); 903251839Sbapt 904251839Sbapt if (now_at >= at_bot) { 905251839Sbapt while (now_at >= at_bot) { 906251839Sbapt if ((at_bot - at_top) >= all.use_height) { 907251839Sbapt set_top_item(&all, 908251839Sbapt next_item(&all, moi->top_index, which), 909251839Sbapt which); 910251839Sbapt } 911251839Sbapt at_top = index2row(&all, moi->top_index, which); 912251839Sbapt at_bot = skip_rows(&all, at_top, all.use_height, which); 913251839Sbapt 914251839Sbapt dlg_trace_msg("...at_bot %d (now %d vs %d)\n", 915251839Sbapt at_bot, now_at, at_end); 916251839Sbapt dlg_trace_msg("...topITM %d\n", moi->top_index); 917251839Sbapt dlg_trace_msg("...at_top %d (diff %d)\n", at_top, 918251839Sbapt at_bot - at_top); 919251839Sbapt 920251839Sbapt if (at_bot >= at_end) { 921251839Sbapt /* 922251839Sbapt * If we bumped into the end, move the top-item 923251839Sbapt * down by one line so that we can display the 924251839Sbapt * last item in the list. 925251839Sbapt */ 926251839Sbapt if ((at_bot - at_top) > all.use_height) { 927251839Sbapt set_top_item(&all, 928251839Sbapt next_item(&all, moi->top_index, which), 929251839Sbapt which); 930251839Sbapt } else if (at_top > 0 && 931251839Sbapt (at_bot - at_top) >= all.use_height) { 932251839Sbapt set_top_item(&all, 933251839Sbapt next_item(&all, moi->top_index, which), 934251839Sbapt which); 935251839Sbapt } 936251839Sbapt break; 937251839Sbapt } 938251839Sbapt if (--oops < 0) { 939251839Sbapt dlg_trace_msg("OOPS-forward\n"); 940251839Sbapt break; 941251839Sbapt } 942251839Sbapt } 943251839Sbapt } else if (now_at < at_top) { 944251839Sbapt while (now_at < at_top) { 945251839Sbapt old_item = moi->top_index; 946251839Sbapt set_top_item(&all, 947251839Sbapt prev_item(&all, moi->top_index, which), 948251839Sbapt which); 949251839Sbapt at_top = index2row(&all, moi->top_index, which); 950251839Sbapt 951251839Sbapt dlg_trace_msg("...at_top %d (now %d)\n", at_top, now_at); 952251839Sbapt dlg_trace_msg("...topITM %d\n", moi->top_index); 953251839Sbapt 954251839Sbapt if (moi->top_index >= old_item) 955251839Sbapt break; 956251839Sbapt if (at_top <= now_at) 957251839Sbapt break; 958251839Sbapt if (--oops < 0) { 959251839Sbapt dlg_trace_msg("OOPS-backward\n"); 960251839Sbapt break; 961251839Sbapt } 962251839Sbapt } 963251839Sbapt } 964251839Sbapt dlg_trace_msg("-->now_at %d\n", now_at); 965251839Sbapt cur_item = i; 966251839Sbapt print_both(&all, cur_item); 967251839Sbapt } 968251839Sbapt dlg_trace_win(dialog); 969251839Sbapt continue; /* wait for another key press */ 970251839Sbapt } 971251839Sbapt 972251839Sbapt if (fkey) { 973251839Sbapt switch (key) { 974251839Sbapt case DLGK_ENTER: 975251839Sbapt result = dlg_enter_buttoncode(button); 976251839Sbapt break; 977251839Sbapt#ifdef KEY_RESIZE 978251839Sbapt case KEY_RESIZE: 979251839Sbapt /* reset data */ 980251839Sbapt height = old_height; 981251839Sbapt width = old_width; 982251839Sbapt /* repaint */ 983251839Sbapt dlg_clear(); 984251839Sbapt dlg_del_window(dialog); 985251839Sbapt refresh(); 986251839Sbapt dlg_mouse_free_regions(); 987251839Sbapt goto retry; 988251839Sbapt#endif 989251839Sbapt default: 990251839Sbapt if (was_mouse) { 991251839Sbapt if ((key2 = dlg_ok_buttoncode(key)) >= 0) { 992251839Sbapt result = key2; 993251839Sbapt break; 994251839Sbapt } 995251839Sbapt beep(); 996251839Sbapt } 997251839Sbapt } 998251839Sbapt } else { 999251839Sbapt beep(); 1000251839Sbapt } 1001251839Sbapt } 1002251839Sbapt 1003251839Sbapt dialog_state.visit_cols = save_visit; 1004251839Sbapt dlg_del_window(dialog); 1005251839Sbapt dlg_mouse_free_regions(); 1006251839Sbapt free(prompt); 1007251839Sbapt *current_item = cur_item; 1008251839Sbapt return result; 1009251839Sbapt} 1010251839Sbapt 1011251839Sbapt/* 1012251839Sbapt * Display a dialog box with a list of options that can be turned on or off 1013251839Sbapt */ 1014251839Sbaptint 1015251839Sbaptdialog_buildlist(const char *title, 1016251839Sbapt const char *cprompt, 1017251839Sbapt int height, 1018251839Sbapt int width, 1019251839Sbapt int list_height, 1020251839Sbapt int item_no, 1021251839Sbapt char **items, 1022251839Sbapt int order_mode) 1023251839Sbapt{ 1024251839Sbapt int result; 1025251839Sbapt int i, j; 1026251839Sbapt DIALOG_LISTITEM *listitems; 1027251839Sbapt bool separate_output = dialog_vars.separate_output; 1028251839Sbapt bool show_status = FALSE; 1029251839Sbapt int current = 0; 1030255852Sdteske char *help_result; 1031251839Sbapt 1032251839Sbapt listitems = dlg_calloc(DIALOG_LISTITEM, (size_t) item_no + 1); 1033251839Sbapt assert_ptr(listitems, "dialog_buildlist"); 1034251839Sbapt 1035251839Sbapt for (i = j = 0; i < item_no; ++i) { 1036251839Sbapt listitems[i].name = items[j++]; 1037251839Sbapt listitems[i].text = (dialog_vars.no_items 1038251839Sbapt ? dlg_strempty() 1039251839Sbapt : items[j++]); 1040251839Sbapt listitems[i].state = !dlg_strcmp(items[j++], "on"); 1041251839Sbapt listitems[i].help = ((dialog_vars.item_help) 1042251839Sbapt ? items[j++] 1043251839Sbapt : dlg_strempty()); 1044251839Sbapt } 1045251839Sbapt dlg_align_columns(&listitems[0].text, (int) sizeof(DIALOG_LISTITEM), item_no); 1046251839Sbapt 1047251839Sbapt result = dlg_buildlist(title, 1048251839Sbapt cprompt, 1049251839Sbapt height, 1050251839Sbapt width, 1051251839Sbapt list_height, 1052251839Sbapt item_no, 1053251839Sbapt listitems, 1054251839Sbapt NULL, 1055251839Sbapt order_mode, 1056251839Sbapt ¤t); 1057251839Sbapt 1058251839Sbapt switch (result) { 1059251839Sbapt case DLG_EXIT_OK: /* FALLTHRU */ 1060251839Sbapt case DLG_EXIT_EXTRA: 1061251839Sbapt show_status = TRUE; 1062251839Sbapt break; 1063251839Sbapt case DLG_EXIT_HELP: 1064255852Sdteske dlg_add_help_listitem(&result, &help_result, &listitems[current]); 1065255852Sdteske if ((show_status = dialog_vars.help_status)) { 1066255852Sdteske if (separate_output) { 1067255852Sdteske dlg_add_string(help_result); 1068255852Sdteske dlg_add_separator(); 1069251839Sbapt } else { 1070255852Sdteske dlg_add_quoted(help_result); 1071251839Sbapt } 1072251839Sbapt } else { 1073255852Sdteske dlg_add_string(help_result); 1074251839Sbapt } 1075251839Sbapt break; 1076251839Sbapt } 1077251839Sbapt 1078251839Sbapt if (show_status) { 1079251839Sbapt for (i = 0; i < item_no; i++) { 1080251839Sbapt if (listitems[i].state) { 1081251839Sbapt if (separate_output) { 1082251839Sbapt dlg_add_string(listitems[i].name); 1083251839Sbapt dlg_add_separator(); 1084251839Sbapt } else { 1085251839Sbapt if (dlg_need_separator()) 1086251839Sbapt dlg_add_separator(); 1087251839Sbapt dlg_add_quoted(listitems[i].name); 1088251839Sbapt } 1089251839Sbapt } 1090251839Sbapt } 1091251839Sbapt dlg_add_last_key(-1); 1092251839Sbapt } 1093251839Sbapt 1094251839Sbapt dlg_free_columns(&listitems[0].text, (int) sizeof(DIALOG_LISTITEM), item_no); 1095251839Sbapt free(listitems); 1096251839Sbapt return result; 1097251839Sbapt} 1098