BOOL CListCtrlEx::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN) { if (GetKeyState(VK_CONTROL) < 0) { switch (pMsg->wParam) { case 'A': if (GetStyle() & LVS_SINGLESEL) break; select_all(); return true; case VK_ADD: auto_size(); return true; } } } return CListCtrl::PreTranslateMessage(pMsg); }
/* * Display a dialog box with a list of options that can be turned on or off * The `flag' parameter is used to select between radiolist and checklist. */ int dialog_checklist(const char *title, const char *cprompt, int height, int width, int list_height, int item_no, char **items, int flag, int separate_output) { int i, j, key2, found, x, y, cur_x, cur_y, box_x, box_y; int key = 0, fkey; int button = 0; int choice = 0; int scrollamt = 0; int max_choice, *status; int use_width, name_width, text_width; int result = DLG_EXIT_UNKNOWN; WINDOW *dialog, *list; char *prompt = strclone(cprompt); const char **buttons = dlg_ok_labels(); tab_correct_str(prompt); if (list_height == 0) { use_width = calc_listw(item_no, items, CHECKBOX_TAGS) + 10; /* calculate height without items (4) */ auto_size(title, prompt, &height, &width, 4, MAX(26, use_width)); calc_listh(&height, &list_height, item_no); } else { auto_size(title, prompt, &height, &width, 4 + list_height, 26); } print_size(height, width); ctl_size(height, width); checkflag = flag; /* Allocate space for storing item on/off status */ status = malloc(sizeof(int) * item_no); assert_ptr(status, "dialog_checklist"); /* Initializes status */ for (i = 0; i < item_no; i++) status[i] = !dlg_strcmp(ItemStatus(i), "on"); max_choice = MIN(list_height, item_no); x = box_x_ordinate(width); y = box_y_ordinate(height); dialog = new_window(height, width, y, x); mouse_setbase(x, y); draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_bottom_box(dialog); draw_title(dialog, title); wattrset(dialog, dialog_attr); print_autowrap(dialog, prompt, height, width); list_width = width - 6; getyx(dialog, cur_y, cur_x); box_y = cur_y + 1; box_x = (width - list_width) / 2 - 1; /* create new window for the list */ list = sub_window(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1); /* draw a box around the list items */ draw_box(dialog, box_y, box_x, list_height + 2 * MARGIN, list_width + 2 * MARGIN, menubox_border_attr, menubox_attr); text_width = 0; name_width = 0; /* Find length of longest item to center checklist */ for (i = 0; i < item_no; i++) { text_width = MAX(text_width, (int) strlen(ItemText(i))); name_width = MAX(name_width, (int) strlen(ItemName(i))); } /* If the name+text is wider than the list is allowed, then truncate * one or both of them. If the name is no wider than 1/4 of the list, * leave it intact. */ use_width = (list_width - 6); if (text_width + name_width > use_width) { int need = 0.25 * use_width; if (name_width > need) { int want = use_width * ((double) name_width) / (text_width + name_width); name_width = (want > need) ? want : need; } text_width = use_width - name_width; } check_x = (use_width - (text_width + name_width)) / 2; item_x = name_width + check_x + 6; /* Print the list */ for (i = 0; i < max_choice; i++) print_item(list, ItemData(i), status[i], i, i == choice); (void) wnoutrefresh(list); /* register the new window, along with its borders */ mouse_mkbigregion(box_y + 1, box_x, list_height, list_width + 2, KEY_MAX, 1, 1, 1 /* by lines */ ); dlg_draw_arrows(dialog, scrollamt, scrollamt + max_choice < item_no - 1, box_x + check_x + 5, box_y, box_y + list_height + 1); dlg_draw_buttons(dialog, height - 2, 0, buttons, 0, FALSE, width); wtimeout(dialog, WTIMEOUT_VAL); while (result == DLG_EXIT_UNKNOWN) { key = mouse_wgetch(dialog, &fkey); if (fkey && (key >= (M_EVENT + KEY_MAX))) { getyx(dialog, cur_y, cur_x); /* De-highlight current item */ print_item(list, ItemData(scrollamt + choice), status[scrollamt + choice], choice, FALSE); /* Highlight new item */ choice = (key - (M_EVENT + KEY_MAX)); print_item(list, ItemData(scrollamt + choice), status[scrollamt + choice], choice, TRUE); (void) wnoutrefresh(list); (void) wmove(dialog, cur_y, cur_x); key = ' '; /* force the selected item to toggle */ fkey = FALSE; } /* * A space toggles the item status. We handle either a checklist * (any number of items can be selected) or radio list (zero or one * items can be selected). */ if (key == ' ') { getyx(dialog, cur_y, cur_x); if (flag == FLAG_CHECK) { /* checklist? */ status[scrollamt + choice] = !status[scrollamt + choice]; print_item(list, ItemData(scrollamt + choice), status[scrollamt + choice], choice, TRUE); } else { /* radiolist */ if (!status[scrollamt + choice]) { for (i = 0; i < item_no; i++) status[i] = FALSE; status[scrollamt + choice] = TRUE; for (i = 0; i < max_choice; i++) print_item(list, ItemData(scrollamt + i), status[scrollamt + i], i, i == choice); } } (void) wnoutrefresh(list); (void) wmove(dialog, cur_y, cur_x); wrefresh(dialog); continue; /* wait for another key press */ } else if (key == ESC) { result = DLG_EXIT_ESC; continue; } if (!fkey) { fkey = TRUE; switch (key) { case '\n': case '\r': key = KEY_ENTER; break; case '-': key = KEY_UP; break; case '+': key = KEY_DOWN; break; case TAB: key = KEY_RIGHT; break; default: fkey = FALSE; break; } } /* * Check if key pressed matches first character of any item tag in * list. If there is more than one match, we will cycle through * each one as the same key is pressed repeatedly. */ found = FALSE; if (!fkey) { for (j = scrollamt + choice + 1; j < item_no; j++) { if (dlg_match_char(dlg_last_getc(), ItemName(j))) { found = TRUE; i = j - scrollamt; break; } } if (!found) { for (j = 0; j <= scrollamt + choice; j++) { if (dlg_match_char(dlg_last_getc(), ItemName(j))) { found = TRUE; i = j - scrollamt; break; } } } if (found) dlg_flush_getc(); } /* * A single digit (1-9) positions the selection to that line in the * current screen. */ if (!found && (key <= '9') && (key > '0') && (key - '1' < max_choice)) { found = TRUE; i = key - '1'; } if (!found) { if (fkey) { found = TRUE; switch (key) { case KEY_HOME: i = -scrollamt; break; case KEY_LL: case KEY_END: i = item_no - 1 - scrollamt; break; case M_EVENT + KEY_PPAGE: case KEY_PPAGE: if (choice) i = 0; else if (scrollamt != 0) i = -MIN(scrollamt, max_choice); else continue; break; case M_EVENT + KEY_NPAGE: case KEY_NPAGE: i = MIN(choice + max_choice, item_no - scrollamt - 1); break; case KEY_UP: i = choice - 1; if (choice == 0 && scrollamt == 0) continue; break; case KEY_DOWN: i = choice + 1; if (scrollamt + choice >= item_no - 1) continue; break; default: found = FALSE; break; } } } if (found) { if (i != choice) { getyx(dialog, cur_y, cur_x); if (i < 0 || i >= max_choice) { #if defined(NCURSES_VERSION_MAJOR) && NCURSES_VERSION_MAJOR < 5 /* * Using wscrl to assist ncurses scrolling is not needed * in version 5.x */ if (i == -1) { if (list_height > 1) { /* De-highlight current first item */ print_item(list, ItemData(scrollamt), status[scrollamt], 0, FALSE); scrollok(list, TRUE); wscrl(list, -1); scrollok(list, FALSE); } scrollamt--; print_item(list, ItemData(scrollamt), status[scrollamt], 0, TRUE); } else if (i == max_choice) { if (list_height > 1) { /* De-highlight current last item before scrolling up */ print_item(list, ItemData(scrollamt + max_choice - 1), status[scrollamt + max_choice - 1], max_choice - 1, FALSE); scrollok(list, TRUE); wscrl(list, 1); scrollok(list, FALSE); } scrollamt++; print_item(list, ItemData(scrollamt + max_choice - 1), status[scrollamt + max_choice - 1], max_choice - 1, TRUE); } else #endif { if (i < 0) { scrollamt += i; choice = 0; } else { choice = max_choice - 1; scrollamt += (i - max_choice + 1); } for (i = 0; i < max_choice; i++) { print_item(list, ItemData(scrollamt + i), status[scrollamt + i], i, i == choice); } } (void) wnoutrefresh(list); dlg_draw_arrows(dialog, scrollamt, scrollamt + choice < item_no - 1, box_x + check_x + 5, box_y, box_y + list_height + 1); } else { /* De-highlight current item */ print_item(list, ItemData(scrollamt + choice), status[scrollamt + choice], choice, FALSE); /* Highlight new item */ choice = i; print_item(list, ItemData(scrollamt + choice), status[scrollamt + choice], choice, TRUE); (void) wnoutrefresh(list); (void) wmove(dialog, cur_y, cur_x); wrefresh(dialog); } } continue; /* wait for another key press */ } if (fkey) { switch (key) { case KEY_ENTER: result = dlg_ok_buttoncode(button); break; case KEY_BTAB: case KEY_LEFT: button = dlg_prev_button(buttons, button); dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); break; case KEY_RIGHT: button = dlg_next_button(buttons, button); dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); break; default: if (key >= M_EVENT) { if ((key2 = dlg_ok_buttoncode(key - M_EVENT)) >= 0) { result = key2; break; } beep(); } } } else { beep(); } } del_window(dialog); switch (result) { case DLG_EXIT_OK: /* FALLTHRU */ case DLG_EXIT_EXTRA: for (i = 0; i < item_no; i++) { if (status[i]) { if (flag == FLAG_CHECK) { if (separate_output) { dlg_add_result(ItemName(i)); dlg_add_result("\n"); } else { dlg_add_result("\""); dlg_add_result(ItemName(i)); dlg_add_result("\" "); } } else { dlg_add_result(ItemName(i)); } } } break; case DLG_EXIT_HELP: dlg_add_result("HELP "); if (USE_ITEM_HELP(ItemHelp(scrollamt + choice))) { dlg_add_result(ItemHelp(scrollamt + choice)); result = DLG_EXIT_OK; /* this is inconsistent */ } else { dlg_add_result(ItemName(scrollamt + choice)); } break; } mouse_free_regions(); free(status); free(prompt); return result; }
/* * Display a dialog box for entering a date */ int dialog_calendar(const char *title, const char *subtitle, int height, int width, int day, int month, int year) { BOX dy_box, mn_box, yr_box; int fkey; int key = 0; int key2; int step; int button = 0; int result = DLG_EXIT_UNKNOWN; WINDOW *dialog; time_t now_time = time((time_t *) 0); struct tm current; STATES state = 0; const char **buttons = dlg_ok_labels(); char *prompt = strclone(subtitle); dlg_does_output(); now_time = time((time_t *) 0); current = *localtime(&now_time); if (day < 0) day = current.tm_mday; if (month < 0) month = current.tm_mon + 1; if (year < 0) year = current.tm_year + 1900; /* compute a struct tm that matches the day/month/year parameters */ if (((year -= 1900) > 0) && (year < 200)) { /* ugly, but I'd like to run this on older machines w/o mktime -TD */ for (;;) { if (year > current.tm_year) { now_time += ONE_DAY * days_in_year(¤t, 0); } else if (year < current.tm_year) { now_time -= ONE_DAY * days_in_year(¤t, -1); } else if (month > current.tm_mon + 1) { now_time += ONE_DAY * days_in_month(¤t, 0); } else if (month < current.tm_mon + 1) { now_time -= ONE_DAY * days_in_month(¤t, -1); } else if (day > current.tm_mday) { now_time += ONE_DAY; } else if (day < current.tm_mday) { now_time -= ONE_DAY; } else { break; } current = *localtime(&now_time); } } auto_size(title, prompt, &height, &width, 0, 0); height += MIN_HIGH; if (width < MIN_WIDE) width = MIN_WIDE; print_size(height, width); ctl_size(height, width); /* FIXME: how to make this resizable? */ dialog = new_window(height, width, box_y_ordinate(height), box_x_ordinate(width)); draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_bottom_box(dialog); draw_title(dialog, title); wattrset(dialog, dialog_attr); print_autowrap(dialog, prompt, height, width); /* compute positions of day, month and year boxes */ memset(&dy_box, 0, sizeof(dy_box)); memset(&mn_box, 0, sizeof(mn_box)); memset(&yr_box, 0, sizeof(yr_box)); if (init_object(&dy_box, dialog, (width - DAY_WIDE) / 2, (height - (DAY_HIGH + BTN_HIGH + (4 * MARGIN))), DAY_WIDE, DAY_HIGH + (2 * MARGIN), draw_day, 'D') < 0 || DrawObject(&dy_box) < 0) return DLG_EXIT_ERROR; if (init_object(&mn_box, dialog, dy_box.x, dy_box.y - (HDR_HIGH + 2 * MARGIN), (DAY_WIDE / 2) - MARGIN, HDR_HIGH, draw_month, 'M') < 0 || DrawObject(&mn_box) < 0) return DLG_EXIT_ERROR; if (init_object(&yr_box, dialog, dy_box.x + mn_box.width + 2, mn_box.y, mn_box.width, mn_box.height, draw_year, 'Y') < 0 || DrawObject(&yr_box) < 0) return DLG_EXIT_ERROR; while (result == DLG_EXIT_UNKNOWN) { BOX *obj = (state == sDAY ? &dy_box : (state == sMONTH ? &mn_box : (state == sYEAR ? &yr_box : 0))); button = (state < 0) ? 0 : state; dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); if (obj != 0) dlg_set_focus(dialog, obj->window); key = mouse_wgetch(dialog, &fkey); if ((key2 = dlg_char_to_button(key, buttons)) >= 0) { result = key2; } else { /* handle non-functionkeys */ if (!fkey) { fkey = TRUE; switch (key) { case ' ': case '\n': case '\r': key = KEY_ENTER; break; case TAB: key = KEY_RIGHT; break; case CHR_PREVIOUS: case CHR_NEXT: case CHR_BACKSPACE: case 'h': case 'j': case 'k': case 'l': /* treat these as function-keys */ break; case ESC: result = DLG_EXIT_ESC; fkey = FALSE; break; default: fkey = FALSE; break; } } /* handle functionkeys */ if (fkey) { switch (key) { case M_EVENT + 'D': state = sDAY; break; case M_EVENT + 'M': state = sMONTH; break; case M_EVENT + 'Y': state = sYEAR; break; case KEY_ENTER: result = dlg_ok_buttoncode(button); break; case KEY_LEFT: case KEY_BTAB: state = dlg_prev_ok_buttonindex(state, sMONTH); break; case KEY_RIGHT: state = dlg_next_ok_buttonindex(state, sMONTH); break; default: step = 0; key2 = -1; if (key >= M_EVENT) { if ((key2 = dlg_ok_buttoncode(key - M_EVENT)) >= 0) { result = key2; break; } else if (key >= (M_EVENT + KEY_MAX)) { state = sDAY; obj = &dy_box; key2 = 1; step = (key - (M_EVENT + KEY_MAX) - day_cell_number(¤t)); } } if (obj != 0) { if (key2 < 0) step = next_or_previous(key, (obj == &dy_box)); if (step != 0) { struct tm old = current; /* see comment regarding mktime -TD */ if (obj == &dy_box) { now_time += ONE_DAY * step; } else if (obj == &mn_box) { if (step > 0) now_time += ONE_DAY * days_in_month(¤t, 0); else now_time -= ONE_DAY * days_in_month(¤t, -1); } else if (obj == &yr_box) { if (step > 0) now_time += (ONE_DAY * days_in_year(¤t, 0)); else now_time -= (ONE_DAY * days_in_year(¤t, -1)); } current = *localtime(&now_time); if (obj != &dy_box && (current.tm_mday != old.tm_mday || current.tm_mon != old.tm_mon || current.tm_year != old.tm_year)) DrawObject(&dy_box); if (obj != &mn_box && current.tm_mon != old.tm_mon) DrawObject(&mn_box); if (obj != &yr_box && current.tm_year != old.tm_year) DrawObject(&yr_box); (void) DrawObject(obj); } } break; } } } } del_window(dialog); sprintf(dialog_vars.input_result, "%02d/%02d/%0d\n", current.tm_mday, current.tm_mon + 1, current.tm_year + 1900); mouse_free_regions(); free(prompt); return result; }
/* * Display a menu for choosing among a number of options */ int dialog_menu(const char *title, const char *cprompt, int height, int width, int menu_height, int item_no, const char **items) { int i, j, x, y, cur_x, cur_y, box_x, box_y; int key = 0; int button = 0; int choice = dlg_default_item(items, MENUBOX_TAGS); int scrollamt = 0; int max_choice, min_width; int found; int use_width, name_width, text_width; WINDOW *dialog, *menu; char *prompt = strclone(cprompt); const char **buttons = dlg_ok_labels(); tab_correct_str(prompt); if (menu_height == 0) { min_width = calc_listw(item_no, items, MENUBOX_TAGS) + 10; /* calculate height without items (4) */ auto_size(title, prompt, &height, &width, 4, MAX(26, min_width)); calc_listh(&height, &menu_height, item_no); } else { auto_size(title, prompt, &height, &width, 4 + menu_height, 26); } print_size(height, width); ctl_size(height, width); max_choice = MIN(menu_height, item_no); x = box_x_ordinate(width); y = box_y_ordinate(height); dialog = new_window(height, width, y, x); mouse_setbase(x, y); draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_bottom_box(dialog); draw_title(dialog, title); wattrset(dialog, dialog_attr); print_autowrap(dialog, prompt, height, width); menu_width = width - 6; getyx(dialog, cur_y, cur_x); box_y = cur_y + 1; box_x = (width - menu_width) / 2 - 1; /* create new window for the menu */ menu = sub_window(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1); /* draw a box around the menu items */ draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, menubox_border_attr, menubox_attr); name_width = 0; text_width = 0; /* Find length of longest item to center menu */ for (i = 0; i < item_no; i++) { name_width = MAX(name_width, (int) strlen(ItemName(i))); text_width = MAX(text_width, (int) strlen(ItemText(i))); } /* If the name+text is wider than the list is allowed, then truncate * one or both of them. If the name is no wider than 1/4 of the list, * leave it intact. */ use_width = (menu_width - 2); if (text_width + name_width > use_width) { int need = 0.25 * use_width; if (name_width > need) { int want = use_width * ((double) name_width) / (text_width + name_width); name_width = (want > need) ? want : need; } text_width = use_width - name_width; } tag_x = (use_width - text_width - name_width) / 2; item_x = name_width + tag_x + 2; if (choice - scrollamt >= max_choice) { scrollamt = choice - (max_choice - 1); choice = max_choice - 1; } /* Print the menu */ for (i = 0; i < max_choice; i++) print_item(menu, ItemData(i + scrollamt), i, i == choice); (void) wnoutrefresh(menu); /* register the new window, along with its borders */ mouse_mkbigregion(box_y, box_x, menu_height + 2, menu_width + 2, item_no, item_x, /* the threshold */ 1 /* dirty mode */ ); dlg_draw_arrows(dialog, scrollamt, scrollamt + max_choice < item_no, box_x + tag_x + 1, box_y, box_y + menu_height + 1); dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); wtimeout(dialog, WTIMEOUT_VAL); while (key != ESC) { key = mouse_wgetch(dialog); /* Check if key pressed matches first character of any item tag in menu */ for (i = 0; i < max_choice; i++) if (toupper(key) == toupper(UCH(ItemName(scrollamt + i)[0]))) break; /* * Check if key pressed matches first character of any item tag in * list. If there is more than one match, we will cycle through * each one as the same key is pressed repeatedly. */ found = FALSE; for (j = scrollamt + choice + 1; j < item_no; j++) { if (toupper(key) == toupper(UCH(ItemName(j)[0]))) { found = TRUE; i = j - scrollamt; break; } } if (!found) { for (j = 0; j <= scrollamt + choice; j++) { if (toupper(key) == toupper(UCH(ItemName(j)[0]))) { found = TRUE; i = j - scrollamt; break; } } } /* * A single digit (1-9) positions the selection to that line in the * current screen. */ if (!found && (key <= '9') && (key > '0') && (key - '1' <= max_choice)) { found = TRUE; i = key - '1'; } if (!found) { found = TRUE; switch (key) { case KEY_HOME: i = -scrollamt; break; case KEY_LL: case KEY_END: i = item_no - 1 - scrollamt; break; case KEY_PPAGE: if (choice) i = 0; else if (scrollamt != 0) i = -MIN(scrollamt, max_choice); else continue; break; case KEY_NPAGE: i = MIN(choice + max_choice, item_no - scrollamt - 1); break; case KEY_UP: case '-': i = choice - 1; if (choice == 0 && scrollamt == 0) continue; break; case KEY_DOWN: case '+': i = choice + 1; if (scrollamt + choice >= item_no - 1) continue; break; default: found = FALSE; break; } } if (found) { if (i != choice) { getyx(dialog, cur_y, cur_x); if (i < 0 || i >= max_choice) { #if defined(NCURSES_VERSION_MAJOR) && NCURSES_VERSION_MAJOR < 5 /* * Using wscrl to assist ncurses scrolling is not needed * in version 5.x */ if (i == -1) { if (menu_height > 1) { /* De-highlight current first item */ print_item(menu, ItemData(scrollamt), 0, FALSE); scrollok(menu, TRUE); wscrl(menu, -1); scrollok(menu, FALSE); } scrollamt--; print_item(menu, ItemData(scrollamt), 0, TRUE); } else if (i == max_choice) { if (menu_height > 1) { /* De-highlight current last item before scrolling up */ print_item(menu, ItemData(scrollamt + max_choice - 1), max_choice - 1, FALSE); scrollok(menu, TRUE); wscrl(menu, 1); scrollok(menu, FALSE); } scrollamt++; print_item(menu, ItemData(scrollamt + max_choice - 1), max_choice - 1, TRUE); } else #endif { if (i < 0) { scrollamt += i; choice = 0; } else { choice = max_choice - 1; scrollamt += (i - max_choice + 1); } for (i = 0; i < max_choice; i++) { print_item(menu, ItemData(scrollamt + i), i, i == choice); } } (void) wnoutrefresh(menu); dlg_draw_arrows(dialog, scrollamt, scrollamt + choice < item_no - 1, box_x + tag_x + 1, box_y, box_y + menu_height + 1); } else { /* De-highlight current item */ print_item(menu, ItemData(scrollamt + choice), choice, FALSE); /* Highlight new item */ choice = i; print_item(menu, ItemData(scrollamt + choice), choice, TRUE); (void) wnoutrefresh(menu); (void) wmove(dialog, cur_y, cur_x); wrefresh(dialog); } } continue; /* wait for another key press */ } switch (key) { case M_EVENT + 'O': del_window(dialog); return scrollamt + choice; case M_EVENT + 'C': del_window(dialog); return -2; case M_EVENT + 'o': /* mouse enter... */ case M_EVENT + 'c': /* use the code for toggling */ button = (key == M_EVENT + 'o'); /* FALLTHRU */ case ' ': case KEY_BTAB: case TAB: case KEY_LEFT: case KEY_RIGHT: if (!dialog_vars.nocancel) button = !button; dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); break; case '\n': del_window(dialog); return (button ? -2 : (scrollamt + choice)); } } del_window(dialog); return -1; /* ESC pressed */ }
/* * Display a gauge, or progress meter. Starts at percent% and reads stdin. If * stdin is not XXX, then it is interpreted as a percentage, and the display is * updated accordingly. Otherwise the next line is the percentage, and * subsequent lines up to another XXX are used for the new prompt. Note that * the size of the window never changes, so the prompt can not get any larger * than the height and width specified. */ int dialog_gauge(const char *title, const char *prompt, int height, int width, int percent) { int i, x, y; char buf[MY_LEN]; char prompt_buf[MY_LEN]; WINDOW *dialog; auto_size(title, prompt, &height, &width, MIN_HIGH, MIN_WIDE); print_size(height, width); ctl_size(height, width); /* center dialog box on screen */ x = box_x_ordinate(width); y = box_y_ordinate(height); dialog = new_window(height, width, y, x); curs_set(0); do { (void) werase(dialog); draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_title(dialog, title); wattrset(dialog, dialog_attr); print_autowrap(dialog, prompt, height, width - (2 * MARGIN)); draw_box(dialog, height - 4, 2 + MARGIN, 2 + MARGIN, width - 2 * (2 + MARGIN), dialog_attr, border_attr); (void) wmove(dialog, height - 3, 4); wattrset(dialog, title_attr); for (i = 0; i < (width - 2 * (3 + MARGIN)); i++) (void) waddch(dialog, ' '); wattrset(dialog, title_attr); (void) wmove(dialog, height - 3, (width / 2) - 2); (void) wprintw(dialog, "%3d%%", percent); x = (percent * (width - 2 * (3 + MARGIN))) / 100; wattrset(dialog, A_REVERSE); (void) wmove(dialog, height - 3, 4); for (i = 0; i < x; i++) (void) waddch(dialog, winch(dialog)); (void) wrefresh(dialog); if (read_data(buf, pipe_fp) == 0) break; if (isMarker(buf)) { /* * Historically, next line should be percentage, but one of the * worse-written clones of 'dialog' assumes the number is missing. * (Gresham's Law applied to software). */ if (read_data(buf, pipe_fp) == 0) break; prompt_buf[0] = '\0'; if (decode_percent(buf)) percent = atoi(buf); else strcpy(prompt_buf, buf); /* Rest is message text */ while (read_data(buf, pipe_fp) != 0 && !isMarker(buf)) { if (strlen(prompt_buf) + strlen(buf) < sizeof(prompt_buf) - 1) { strcat(prompt_buf, buf); } } prompt = prompt_buf; } else if (decode_percent(buf)) { percent = atoi(buf); } } while (1); curs_set(1); del_window(dialog); return (DLG_EXIT_OK); }
void CListCtrlEx::OnSize(UINT nType, int cx, int cy) { CListCtrl::OnSize(nType, cx, cy); auto_size(); }
/* * Display a dialog box for entering a date */ int dialog_timebox(const char *title, const char *subtitle, int height, int width, int hour, int minute, int second) { BOX hr_box, mn_box, sc_box; int key = 0, key2, button = sOK; int result = -2; WINDOW *dialog; time_t now_time = time((time_t *) 0); struct tm current; STATES state = sOK; const char **buttons = dlg_ok_labels(); char *prompt = strclone(subtitle); now_time = time((time_t *) 0); current = *localtime(&now_time); auto_size(title, prompt, &height, &width, 0, 0); height += MIN_HIGH; if (width < MIN_WIDE) width = MIN_WIDE; dlg_button_layout(buttons, &width); print_size(height, width); ctl_size(height, width); /* FIXME: how to make this resizable? */ dialog = new_window(height, width, box_y_ordinate(height), box_x_ordinate(width)); draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_bottom_box(dialog); draw_title(dialog, title); wattrset(dialog, dialog_attr); print_autowrap(dialog, prompt, height, width); /* compute positions of hour, month and year boxes */ memset(&hr_box, 0, sizeof(hr_box)); memset(&mn_box, 0, sizeof(mn_box)); memset(&sc_box, 0, sizeof(sc_box)); if (init_object(&hr_box, dialog, (width - MIN_WIDE + 1) / 2 + MARGIN, (height - MIN_HIGH + MARGIN), ONE_WIDE, ONE_HIGH, 24, hour >= 0 ? hour : current.tm_hour, 'H') < 0 || DrawObject(&hr_box) < 0) return -1; mvwprintw(dialog, hr_box.y, hr_box.x + ONE_WIDE + MARGIN, ":"); if (init_object(&mn_box, dialog, hr_box.x + (ONE_WIDE + 2 * MARGIN + 1), hr_box.y, hr_box.width, hr_box.height, 60, minute >= 0 ? minute : current.tm_min, 'M') < 0 || DrawObject(&mn_box) < 0) return -1; mvwprintw(dialog, mn_box.y, mn_box.x + ONE_WIDE + MARGIN, ":"); if (init_object(&sc_box, dialog, mn_box.x + (ONE_WIDE + 2 * MARGIN + 1), mn_box.y, mn_box.width, mn_box.height, 60, second >= 0 ? second : current.tm_sec, 'S') < 0 || DrawObject(&sc_box) < 0) return -1; while (result == -2) { BOX *obj = (state == sHR ? &hr_box : (state == sMN ? &mn_box : (state == sSC ? &sc_box : 0))); button = (state == sCANCEL) ? 1 : 0; dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); if (obj != 0) dlg_set_focus(dialog, obj->window); key = mouse_wgetch(dialog); if ((key2 = dlg_char_to_button(key, buttons)) >= 0) { result = key2; } else { switch (key) { case M_EVENT + 0: result = DLG_EXIT_OK; break; case M_EVENT + 1: result = DLG_EXIT_CANCEL; break; case M_EVENT + 'H': state = sHR; break; case M_EVENT + 'M': state = sMN; break; case M_EVENT + 'S': state = sSC; break; case ESC: result = -1; break; case ' ': case '\n': result = button; break; case KEY_BTAB: state = prev_object(state); break; case TAB: state = next_object(state); break; default: if (obj != 0) { int step = next_or_previous(key); if (step != 0) { obj->value += step; while (obj->value < 0) obj->value += obj->period; obj->value %= obj->period; (void) DrawObject(obj); } } break; } } } del_window(dialog); sprintf(dialog_vars.input_result, "%02d:%02d:%02d\n", hr_box.value, mn_box.value, sc_box.value); mouse_free_regions(); return result; }
/* * Display a menu for choosing among a number of options */ int dialog_menu(const char *title, const char *cprompt, int height, int width, int menu_height, int item_no, char **items) { int i, j, x, y, cur_x, cur_y, box_x, box_y; int key = 0, fkey; int button = 0; int choice = dlg_default_item(items, MENUBOX_TAGS); int result = DLG_EXIT_UNKNOWN; int scrollamt = 0; int max_choice, min_width; int found; int use_width, name_width, text_width; WINDOW *dialog, *menu; char *prompt = strclone(cprompt); const char **buttons = dlg_ok_labels(); tab_correct_str(prompt); if (menu_height == 0) { min_width = calc_listw(item_no, items, MENUBOX_TAGS) + 10; /* calculate height without items (4) */ auto_size(title, prompt, &height, &width, 4, MAX(26, min_width)); calc_listh(&height, &menu_height, item_no); } else { auto_size(title, prompt, &height, &width, 4 + menu_height, 26); } print_size(height, width); ctl_size(height, width); /* Find out maximal number of displayable items at once. */ max_choice = MIN(menu_height, RowHeight(item_no)); if (dialog_vars.input_menu) max_choice /= INPUT_ROWS; x = box_x_ordinate(width); y = box_y_ordinate(height); dialog = new_window(height, width, y, x); mouse_setbase(x, y); draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_bottom_box(dialog); draw_title(dialog, title); wattrset(dialog, dialog_attr); print_autowrap(dialog, prompt, height, width); menu_width = width - 6; getyx(dialog, cur_y, cur_x); box_y = cur_y + 1; box_x = (width - menu_width) / 2 - 1; /* create new window for the menu */ menu = sub_window(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1); /* draw a box around the menu items */ draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, menubox_border_attr, menubox_attr); name_width = 0; text_width = 0; /* Find length of longest item to center menu * * only if --menu was given, using --inputmenu * * won't be centered. */ for (i = 0; i < item_no; i++) { name_width = MAX(name_width, dlg_count_columns(ItemName(i))); text_width = MAX(text_width, dlg_count_columns(ItemText(i))); } /* If the name+text is wider than the list is allowed, then truncate * one or both of them. If the name is no wider than 1/4 of the list, * leave it intact. */ use_width = (menu_width - GUTTER); if (text_width + name_width > use_width) { int need = 0.25 * use_width; if (name_width > need) { int want = use_width * ((double) name_width) / (text_width + name_width); name_width = (want > need) ? want : need; } text_width = use_width - name_width; } tag_x = (dialog_vars.input_menu ? 0 : (use_width - text_width - name_width) / 2); item_x = name_width + tag_x + GUTTER; if (choice - scrollamt >= max_choice) { scrollamt = choice - (max_choice - 1); choice = max_choice - 1; } /* Print the menu */ for (i = 0; i < max_choice; i++) print_item(menu, ItemData(i + scrollamt), i, i == choice); (void) wnoutrefresh(menu); /* register the new window, along with its borders */ mouse_mkbigregion(box_y + 1, box_x, menu_height + 2, menu_width + 2, KEY_MAX, 1, 1, 1 /* by lines */ ); dlg_draw_arrows(dialog, scrollamt, scrollamt + max_choice < item_no, box_x + tag_x + 1, box_y, box_y + menu_height + 1); dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); wtimeout(dialog, WTIMEOUT_VAL); while (result == DLG_EXIT_UNKNOWN) { key = mouse_wgetch(dialog, &fkey); if (!fkey) { fkey = TRUE; switch (key) { case '\n': case '\r': key = KEY_ENTER; break; case '-': key = KEY_UP; break; case '+': key = KEY_DOWN; break; case ' ': case TAB: key = KEY_RIGHT; break; case ESC: result = DLG_EXIT_ESC; continue; default: fkey = FALSE; break; } } found = FALSE; if (fkey) { /* * Allow a mouse-click on a box to switch selection to that box. * Handling a button click is a little more complicated, since we * push a KEY_ENTER back onto the input stream so we'll put the * cursor at the right place before handling the "keypress". */ if (key >= (M_EVENT + KEY_MAX)) { key -= (M_EVENT + KEY_MAX); i = RowToItem(key); found = TRUE; } else if (key >= M_EVENT && dlg_ok_buttoncode(key - M_EVENT) >= 0) { button = (key - M_EVENT); ungetch('\n'); continue; } } else { /* * Check if key pressed matches first character of any item tag in * list. If there is more than one match, we will cycle through * each one as the same key is pressed repeatedly. */ for (j = scrollamt + choice + 1; j < item_no; j++) { if (dlg_match_char(dlg_last_getc(), ItemName(j))) { found = TRUE; i = j - scrollamt; break; } } if (!found) { for (j = 0; j <= scrollamt + choice; j++) { if (dlg_match_char(dlg_last_getc(), ItemName(j))) { found = TRUE; i = j - scrollamt; break; } } } if (found) dlg_flush_getc(); /* * A single digit (1-9) positions the selection to that line in the * current screen. */ if (!found && (key <= '9') && (key > '0') && (key - '1' < max_choice)) { found = TRUE; i = key - '1'; } } if (!found && fkey) { found = TRUE; switch (key) { case KEY_HOME: i = -scrollamt; break; case KEY_LL: case KEY_END: i = item_no - 1 - scrollamt; break; case M_EVENT + KEY_PPAGE: case KEY_PPAGE: if (choice) i = 0; else if (scrollamt != 0) i = -MIN(scrollamt, max_choice); else continue; break; case M_EVENT + KEY_NPAGE: case KEY_NPAGE: i = MIN(choice + max_choice, item_no - scrollamt - 1); break; case KEY_UP: i = choice - 1; if (choice == 0 && scrollamt == 0) continue; break; case KEY_DOWN: i = choice + 1; if (scrollamt + choice >= item_no - 1) continue; break; default: found = FALSE; break; } } if (found) { if (i != choice) { getyx(dialog, cur_y, cur_x); if (i < 0 || i >= max_choice) { #if defined(NCURSES_VERSION_MAJOR) && NCURSES_VERSION_MAJOR < 5 /* * Using wscrl to assist ncurses scrolling is not needed * in version 5.x */ if (i == -1) { if (menu_height > 1) { /* De-highlight current first item */ print_item(menu, ItemData(scrollamt), 0, FALSE); scrollok(menu, TRUE); wscrl(menu, -RowHeight(1)); scrollok(menu, FALSE); } scrollamt--; print_item(menu, ItemData(scrollamt), 0, TRUE); } else if (i == max_choice) { if (menu_height > 1) { /* De-highlight current last item before scrolling up */ print_item(menu, ItemData(scrollamt + max_choice - 1), max_choice - 1, FALSE); scrollok(menu, TRUE); wscrl(menu, RowHeight(1)); scrollok(menu, FALSE); } scrollamt++; print_item(menu, ItemData(scrollamt + max_choice - 1), max_choice - 1, TRUE); } else #endif { if (i < 0) { scrollamt += i; choice = 0; } else { choice = max_choice - 1; scrollamt += (i - max_choice + 1); } for (i = 0; i < max_choice; i++) { print_item(menu, ItemData(scrollamt + i), i, i == choice); } } /* Clean bottom lines */ if (dialog_vars.input_menu) { int spare_lines, x_count; spare_lines = menu_height % INPUT_ROWS; wattrset(menu, menubox_attr); for (; spare_lines; spare_lines--) { wmove(menu, menu_height - spare_lines, 0); for (x_count = 0; x_count < menu_width; x_count++) { waddch(menu, ' '); } } } (void) wnoutrefresh(menu); dlg_draw_arrows(dialog, scrollamt, scrollamt + choice < item_no - 1, box_x + tag_x + 1, box_y, box_y + menu_height + 1); } else { /* De-highlight current item */ print_item(menu, ItemData(scrollamt + choice), choice, FALSE); /* Highlight new item */ choice = i; print_item(menu, ItemData(scrollamt + choice), choice, TRUE); (void) wnoutrefresh(menu); (void) wmove(dialog, cur_y, cur_x); wrefresh(dialog); } } continue; /* wait for another key press */ } if (fkey) { switch (key) { case KEY_BTAB: case KEY_LEFT: button = dlg_prev_button(buttons, button); dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); break; case KEY_RIGHT: button = dlg_next_button(buttons, button); dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); break; case KEY_ENTER: del_window(dialog); result = handle_button(dlg_ok_buttoncode(button), items, scrollamt + choice); if (dialog_vars.input_menu && result == DLG_EXIT_EXTRA) { char *tmp; tmp = input_menu_edit(menu, ItemData(scrollamt + choice), choice); dialog_vars.input_result[0] = '\0'; dlg_add_result("RENAMED "); dlg_add_result(ItemName(scrollamt + choice)); dlg_add_result(" "); dlg_add_result(tmp); free(tmp); dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); } break; default: flash(); break; } } } mouse_free_regions(); del_window(dialog); free(prompt); return result; }