10c874100SMasahiro Yamada // SPDX-License-Identifier: GPL-2.0+ 26f6046cfSSam Ravnborg /* 36f6046cfSSam Ravnborg * textbox.c -- implements the text box 46f6046cfSSam Ravnborg * 56f6046cfSSam Ravnborg * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 66f6046cfSSam Ravnborg * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 76f6046cfSSam Ravnborg */ 86f6046cfSSam Ravnborg 96f6046cfSSam Ravnborg #include "dialog.h" 106f6046cfSSam Ravnborg 116f6046cfSSam Ravnborg static void back_lines(int n); 1295ac9b3bSBenjamin Poirier static void print_page(WINDOW *win, int height, int width, update_text_fn 1395ac9b3bSBenjamin Poirier update_text, void *data); 146f6046cfSSam Ravnborg static void print_line(WINDOW *win, int row, int width); 156f6046cfSSam Ravnborg static char *get_line(void); 16c8dc68adSSam Ravnborg static void print_position(WINDOW * win); 176f6046cfSSam Ravnborg 182982de69SSam Ravnborg static int hscroll; 192982de69SSam Ravnborg static int begin_reached, end_reached, page_length; 2095ac9b3bSBenjamin Poirier static char *buf; 2195ac9b3bSBenjamin Poirier static char *page; 226f6046cfSSam Ravnborg 236f6046cfSSam Ravnborg /* 24c8dc68adSSam Ravnborg * refresh window content 25c8dc68adSSam Ravnborg */ 26c8dc68adSSam Ravnborg static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, 2795ac9b3bSBenjamin Poirier int cur_y, int cur_x, update_text_fn update_text, 2895ac9b3bSBenjamin Poirier void *data) 29c8dc68adSSam Ravnborg { 3095ac9b3bSBenjamin Poirier print_page(box, boxh, boxw, update_text, data); 31c8dc68adSSam Ravnborg print_position(dialog); 32c8dc68adSSam Ravnborg wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 33c8dc68adSSam Ravnborg wrefresh(dialog); 34c8dc68adSSam Ravnborg } 35c8dc68adSSam Ravnborg 36c8dc68adSSam Ravnborg 37c8dc68adSSam Ravnborg /* 386f6046cfSSam Ravnborg * Display text from a file in a dialog box. 39537ddae7SBenjamin Poirier * 40537ddae7SBenjamin Poirier * keys is a null-terminated array 4195ac9b3bSBenjamin Poirier * update_text() may not add or remove any '\n' or '\0' in tbuf 426f6046cfSSam Ravnborg */ 4395ac9b3bSBenjamin Poirier int dialog_textbox(const char *title, char *tbuf, int initial_height, 4495ac9b3bSBenjamin Poirier int initial_width, int *keys, int *_vscroll, int *_hscroll, 4595ac9b3bSBenjamin Poirier update_text_fn update_text, void *data) 466f6046cfSSam Ravnborg { 472982de69SSam Ravnborg int i, x, y, cur_x, cur_y, key = 0; 48c8dc68adSSam Ravnborg int height, width, boxh, boxw; 49c8dc68adSSam Ravnborg WINDOW *dialog, *box; 50537ddae7SBenjamin Poirier bool done = false; 516f6046cfSSam Ravnborg 522982de69SSam Ravnborg begin_reached = 1; 532982de69SSam Ravnborg end_reached = 0; 542982de69SSam Ravnborg page_length = 0; 552982de69SSam Ravnborg hscroll = 0; 562982de69SSam Ravnborg buf = tbuf; 576f6046cfSSam Ravnborg page = buf; /* page is pointer to start of page to be displayed */ 586f6046cfSSam Ravnborg 591d1e2caeSBenjamin Poirier if (_vscroll && *_vscroll) { 601d1e2caeSBenjamin Poirier begin_reached = 0; 611d1e2caeSBenjamin Poirier 621d1e2caeSBenjamin Poirier for (i = 0; i < *_vscroll; i++) 631d1e2caeSBenjamin Poirier get_line(); 641d1e2caeSBenjamin Poirier } 651d1e2caeSBenjamin Poirier if (_hscroll) 661d1e2caeSBenjamin Poirier hscroll = *_hscroll; 671d1e2caeSBenjamin Poirier 68c8dc68adSSam Ravnborg do_resize: 69c8dc68adSSam Ravnborg getmaxyx(stdscr, height, width); 70851f6657SSedat Dilek if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN) 71c8dc68adSSam Ravnborg return -ERRDISPLAYTOOSMALL; 72c8dc68adSSam Ravnborg if (initial_height != 0) 73c8dc68adSSam Ravnborg height = initial_height; 74c8dc68adSSam Ravnborg else 75c8dc68adSSam Ravnborg if (height > 4) 76c8dc68adSSam Ravnborg height -= 4; 77c8dc68adSSam Ravnborg else 78c8dc68adSSam Ravnborg height = 0; 79c8dc68adSSam Ravnborg if (initial_width != 0) 80c8dc68adSSam Ravnborg width = initial_width; 81c8dc68adSSam Ravnborg else 82c8dc68adSSam Ravnborg if (width > 5) 83c8dc68adSSam Ravnborg width -= 5; 84c8dc68adSSam Ravnborg else 85c8dc68adSSam Ravnborg width = 0; 86c8dc68adSSam Ravnborg 876f6046cfSSam Ravnborg /* center dialog box on screen */ 884f2de3e1SDirk Gouders x = (getmaxx(stdscr) - width) / 2; 894f2de3e1SDirk Gouders y = (getmaxy(stdscr) - height) / 2; 906f6046cfSSam Ravnborg 916f6046cfSSam Ravnborg draw_shadow(stdscr, y, x, height, width); 926f6046cfSSam Ravnborg 936f6046cfSSam Ravnborg dialog = newwin(height, width, y, x); 946f6046cfSSam Ravnborg keypad(dialog, TRUE); 956f6046cfSSam Ravnborg 96c8dc68adSSam Ravnborg /* Create window for box region, used for scrolling text */ 97c8dc68adSSam Ravnborg boxh = height - 4; 98c8dc68adSSam Ravnborg boxw = width - 2; 99c8dc68adSSam Ravnborg box = subwin(dialog, boxh, boxw, y + 1, x + 1); 100c8dc68adSSam Ravnborg wattrset(box, dlg.dialog.atr); 101c8dc68adSSam Ravnborg wbkgdset(box, dlg.dialog.atr & A_COLOR); 1026f6046cfSSam Ravnborg 103c8dc68adSSam Ravnborg keypad(box, TRUE); 1046f6046cfSSam Ravnborg 1056f6046cfSSam Ravnborg /* register the new window, along with its borders */ 10698e5a157SSam Ravnborg draw_box(dialog, 0, 0, height, width, 10798e5a157SSam Ravnborg dlg.dialog.atr, dlg.border.atr); 1086f6046cfSSam Ravnborg 10998e5a157SSam Ravnborg wattrset(dialog, dlg.border.atr); 1106f6046cfSSam Ravnborg mvwaddch(dialog, height - 3, 0, ACS_LTEE); 1116f6046cfSSam Ravnborg for (i = 0; i < width - 2; i++) 1126f6046cfSSam Ravnborg waddch(dialog, ACS_HLINE); 11398e5a157SSam Ravnborg wattrset(dialog, dlg.dialog.atr); 11498e5a157SSam Ravnborg wbkgdset(dialog, dlg.dialog.atr & A_COLOR); 1156f6046cfSSam Ravnborg waddch(dialog, ACS_RTEE); 1166f6046cfSSam Ravnborg 1176f6046cfSSam Ravnborg print_title(dialog, title, width); 1186f6046cfSSam Ravnborg 119694c49a7SSam Ravnborg print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE); 1206f6046cfSSam Ravnborg wnoutrefresh(dialog); 1216f6046cfSSam Ravnborg getyx(dialog, cur_y, cur_x); /* Save cursor position */ 1226f6046cfSSam Ravnborg 1236f6046cfSSam Ravnborg /* Print first page of text */ 124c8dc68adSSam Ravnborg attr_clear(box, boxh, boxw, dlg.dialog.atr); 12595ac9b3bSBenjamin Poirier refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text, 12695ac9b3bSBenjamin Poirier data); 1276f6046cfSSam Ravnborg 128537ddae7SBenjamin Poirier while (!done) { 1296f6046cfSSam Ravnborg key = wgetch(dialog); 1306f6046cfSSam Ravnborg switch (key) { 1316f6046cfSSam Ravnborg case 'E': /* Exit */ 1326f6046cfSSam Ravnborg case 'e': 1336f6046cfSSam Ravnborg case 'X': 1346f6046cfSSam Ravnborg case 'x': 1359d4792c9SBenjamin Poirier case 'q': 136537ddae7SBenjamin Poirier case '\n': 137537ddae7SBenjamin Poirier done = true; 138537ddae7SBenjamin Poirier break; 1396f6046cfSSam Ravnborg case 'g': /* First page */ 1406f6046cfSSam Ravnborg case KEY_HOME: 1416f6046cfSSam Ravnborg if (!begin_reached) { 1426f6046cfSSam Ravnborg begin_reached = 1; 1436f6046cfSSam Ravnborg page = buf; 144c8dc68adSSam Ravnborg refresh_text_box(dialog, box, boxh, boxw, 14595ac9b3bSBenjamin Poirier cur_y, cur_x, update_text, 14695ac9b3bSBenjamin Poirier data); 1476f6046cfSSam Ravnborg } 1486f6046cfSSam Ravnborg break; 1496f6046cfSSam Ravnborg case 'G': /* Last page */ 1506f6046cfSSam Ravnborg case KEY_END: 1516f6046cfSSam Ravnborg 1526f6046cfSSam Ravnborg end_reached = 1; 1532982de69SSam Ravnborg /* point to last char in buf */ 1542982de69SSam Ravnborg page = buf + strlen(buf); 155c8dc68adSSam Ravnborg back_lines(boxh); 15695ac9b3bSBenjamin Poirier refresh_text_box(dialog, box, boxh, boxw, cur_y, 15795ac9b3bSBenjamin Poirier cur_x, update_text, data); 1586f6046cfSSam Ravnborg break; 1596f6046cfSSam Ravnborg case 'K': /* Previous line */ 1606f6046cfSSam Ravnborg case 'k': 1616f6046cfSSam Ravnborg case KEY_UP: 1621a374ae6SBenjamin Poirier if (begin_reached) 1631a374ae6SBenjamin Poirier break; 164537ddae7SBenjamin Poirier 1656f6046cfSSam Ravnborg back_lines(page_length + 1); 1661a374ae6SBenjamin Poirier refresh_text_box(dialog, box, boxh, boxw, cur_y, 16795ac9b3bSBenjamin Poirier cur_x, update_text, data); 1686f6046cfSSam Ravnborg break; 1696f6046cfSSam Ravnborg case 'B': /* Previous page */ 1706f6046cfSSam Ravnborg case 'b': 1719d4792c9SBenjamin Poirier case 'u': 1726f6046cfSSam Ravnborg case KEY_PPAGE: 1736f6046cfSSam Ravnborg if (begin_reached) 1746f6046cfSSam Ravnborg break; 175c8dc68adSSam Ravnborg back_lines(page_length + boxh); 17695ac9b3bSBenjamin Poirier refresh_text_box(dialog, box, boxh, boxw, cur_y, 17795ac9b3bSBenjamin Poirier cur_x, update_text, data); 1786f6046cfSSam Ravnborg break; 1796f6046cfSSam Ravnborg case 'J': /* Next line */ 1806f6046cfSSam Ravnborg case 'j': 1816f6046cfSSam Ravnborg case KEY_DOWN: 1821a374ae6SBenjamin Poirier if (end_reached) 1831a374ae6SBenjamin Poirier break; 1841a374ae6SBenjamin Poirier 1851a374ae6SBenjamin Poirier back_lines(page_length - 1); 1861a374ae6SBenjamin Poirier refresh_text_box(dialog, box, boxh, boxw, cur_y, 18795ac9b3bSBenjamin Poirier cur_x, update_text, data); 1886f6046cfSSam Ravnborg break; 1896f6046cfSSam Ravnborg case KEY_NPAGE: /* Next page */ 1906f6046cfSSam Ravnborg case ' ': 1919d4792c9SBenjamin Poirier case 'd': 1926f6046cfSSam Ravnborg if (end_reached) 1936f6046cfSSam Ravnborg break; 1946f6046cfSSam Ravnborg 1956f6046cfSSam Ravnborg begin_reached = 0; 19695ac9b3bSBenjamin Poirier refresh_text_box(dialog, box, boxh, boxw, cur_y, 19795ac9b3bSBenjamin Poirier cur_x, update_text, data); 1986f6046cfSSam Ravnborg break; 1996f6046cfSSam Ravnborg case '0': /* Beginning of line */ 2006f6046cfSSam Ravnborg case 'H': /* Scroll left */ 2016f6046cfSSam Ravnborg case 'h': 2026f6046cfSSam Ravnborg case KEY_LEFT: 2036f6046cfSSam Ravnborg if (hscroll <= 0) 2046f6046cfSSam Ravnborg break; 2056f6046cfSSam Ravnborg 2066f6046cfSSam Ravnborg if (key == '0') 2076f6046cfSSam Ravnborg hscroll = 0; 2086f6046cfSSam Ravnborg else 2096f6046cfSSam Ravnborg hscroll--; 2106f6046cfSSam Ravnborg /* Reprint current page to scroll horizontally */ 2116f6046cfSSam Ravnborg back_lines(page_length); 21295ac9b3bSBenjamin Poirier refresh_text_box(dialog, box, boxh, boxw, cur_y, 21395ac9b3bSBenjamin Poirier cur_x, update_text, data); 2146f6046cfSSam Ravnborg break; 2156f6046cfSSam Ravnborg case 'L': /* Scroll right */ 2166f6046cfSSam Ravnborg case 'l': 2176f6046cfSSam Ravnborg case KEY_RIGHT: 2186f6046cfSSam Ravnborg if (hscroll >= MAX_LEN) 2196f6046cfSSam Ravnborg break; 2206f6046cfSSam Ravnborg hscroll++; 2216f6046cfSSam Ravnborg /* Reprint current page to scroll horizontally */ 2226f6046cfSSam Ravnborg back_lines(page_length); 22395ac9b3bSBenjamin Poirier refresh_text_box(dialog, box, boxh, boxw, cur_y, 22495ac9b3bSBenjamin Poirier cur_x, update_text, data); 2256f6046cfSSam Ravnborg break; 226f3cbcdc9SSam Ravnborg case KEY_ESC: 227537ddae7SBenjamin Poirier if (on_key_esc(dialog) == KEY_ESC) 228537ddae7SBenjamin Poirier done = true; 2296f6046cfSSam Ravnborg break; 230c8dc68adSSam Ravnborg case KEY_RESIZE: 231c8dc68adSSam Ravnborg back_lines(height); 232c8dc68adSSam Ravnborg delwin(box); 233c8dc68adSSam Ravnborg delwin(dialog); 234c8dc68adSSam Ravnborg on_key_resize(); 235c8dc68adSSam Ravnborg goto do_resize; 236537ddae7SBenjamin Poirier default: 237537ddae7SBenjamin Poirier for (i = 0; keys[i]; i++) { 238537ddae7SBenjamin Poirier if (key == keys[i]) { 239537ddae7SBenjamin Poirier done = true; 240537ddae7SBenjamin Poirier break; 241537ddae7SBenjamin Poirier } 242537ddae7SBenjamin Poirier } 2436f6046cfSSam Ravnborg } 2446f6046cfSSam Ravnborg } 245c8dc68adSSam Ravnborg delwin(box); 2466f6046cfSSam Ravnborg delwin(dialog); 2471d1e2caeSBenjamin Poirier if (_vscroll) { 2481d1e2caeSBenjamin Poirier const char *s; 2491d1e2caeSBenjamin Poirier 2501d1e2caeSBenjamin Poirier s = buf; 2511d1e2caeSBenjamin Poirier *_vscroll = 0; 2521d1e2caeSBenjamin Poirier back_lines(page_length); 2531d1e2caeSBenjamin Poirier while (s < page && (s = strchr(s, '\n'))) { 2541d1e2caeSBenjamin Poirier (*_vscroll)++; 2551d1e2caeSBenjamin Poirier s++; 2561d1e2caeSBenjamin Poirier } 2571d1e2caeSBenjamin Poirier } 2581d1e2caeSBenjamin Poirier if (_hscroll) 2591d1e2caeSBenjamin Poirier *_hscroll = hscroll; 260537ddae7SBenjamin Poirier return key; 2616f6046cfSSam Ravnborg } 2626f6046cfSSam Ravnborg 2636f6046cfSSam Ravnborg /* 2642982de69SSam Ravnborg * Go back 'n' lines in text. Called by dialog_textbox(). 2656f6046cfSSam Ravnborg * 'page' will be updated to point to the desired line in 'buf'. 2666f6046cfSSam Ravnborg */ 2676f6046cfSSam Ravnborg static void back_lines(int n) 2686f6046cfSSam Ravnborg { 2692982de69SSam Ravnborg int i; 2706f6046cfSSam Ravnborg 2716f6046cfSSam Ravnborg begin_reached = 0; 2722982de69SSam Ravnborg /* Go back 'n' lines */ 2732982de69SSam Ravnborg for (i = 0; i < n; i++) { 2742982de69SSam Ravnborg if (*page == '\0') { 2752982de69SSam Ravnborg if (end_reached) { 2762982de69SSam Ravnborg end_reached = 0; 2772982de69SSam Ravnborg continue; 2782982de69SSam Ravnborg } 2792982de69SSam Ravnborg } 2806f6046cfSSam Ravnborg if (page == buf) { 2816f6046cfSSam Ravnborg begin_reached = 1; 2826f6046cfSSam Ravnborg return; 2836f6046cfSSam Ravnborg } 2842982de69SSam Ravnborg page--; 2856f6046cfSSam Ravnborg do { 2866f6046cfSSam Ravnborg if (page == buf) { 2876f6046cfSSam Ravnborg begin_reached = 1; 2886f6046cfSSam Ravnborg return; 2896f6046cfSSam Ravnborg } 2902982de69SSam Ravnborg page--; 2912982de69SSam Ravnborg } while (*page != '\n'); 2926f6046cfSSam Ravnborg page++; 2936f6046cfSSam Ravnborg } 2942982de69SSam Ravnborg } 2956f6046cfSSam Ravnborg 2966f6046cfSSam Ravnborg /* 29795ac9b3bSBenjamin Poirier * Print a new page of text. 2986f6046cfSSam Ravnborg */ 29995ac9b3bSBenjamin Poirier static void print_page(WINDOW *win, int height, int width, update_text_fn 30095ac9b3bSBenjamin Poirier update_text, void *data) 3016f6046cfSSam Ravnborg { 3026f6046cfSSam Ravnborg int i, passed_end = 0; 3036f6046cfSSam Ravnborg 30495ac9b3bSBenjamin Poirier if (update_text) { 30595ac9b3bSBenjamin Poirier char *end; 30695ac9b3bSBenjamin Poirier 30795ac9b3bSBenjamin Poirier for (i = 0; i < height; i++) 30895ac9b3bSBenjamin Poirier get_line(); 30995ac9b3bSBenjamin Poirier end = page; 31095ac9b3bSBenjamin Poirier back_lines(height); 31195ac9b3bSBenjamin Poirier update_text(buf, page - buf, end - buf, data); 31295ac9b3bSBenjamin Poirier } 31395ac9b3bSBenjamin Poirier 3146f6046cfSSam Ravnborg page_length = 0; 3156f6046cfSSam Ravnborg for (i = 0; i < height; i++) { 3166f6046cfSSam Ravnborg print_line(win, i, width); 3176f6046cfSSam Ravnborg if (!passed_end) 3186f6046cfSSam Ravnborg page_length++; 3196f6046cfSSam Ravnborg if (end_reached && !passed_end) 3206f6046cfSSam Ravnborg passed_end = 1; 3216f6046cfSSam Ravnborg } 3226f6046cfSSam Ravnborg wnoutrefresh(win); 3236f6046cfSSam Ravnborg } 3246f6046cfSSam Ravnborg 3256f6046cfSSam Ravnborg /* 32695ac9b3bSBenjamin Poirier * Print a new line of text. 3276f6046cfSSam Ravnborg */ 3286f6046cfSSam Ravnborg static void print_line(WINDOW * win, int row, int width) 3296f6046cfSSam Ravnborg { 3306f6046cfSSam Ravnborg char *line; 3316f6046cfSSam Ravnborg 3326f6046cfSSam Ravnborg line = get_line(); 3336f6046cfSSam Ravnborg line += MIN(strlen(line), hscroll); /* Scroll horizontally */ 3346f6046cfSSam Ravnborg wmove(win, row, 0); /* move cursor to correct line */ 3356f6046cfSSam Ravnborg waddch(win, ' '); 3366f6046cfSSam Ravnborg waddnstr(win, line, MIN(strlen(line), width - 2)); 3376f6046cfSSam Ravnborg 3386f6046cfSSam Ravnborg /* Clear 'residue' of previous line */ 3396f6046cfSSam Ravnborg #if OLD_NCURSES 3406f6046cfSSam Ravnborg { 341702a9450SLucas De Marchi int x = getcurx(win); 3426f6046cfSSam Ravnborg int i; 3436f6046cfSSam Ravnborg for (i = 0; i < width - x; i++) 3446f6046cfSSam Ravnborg waddch(win, ' '); 3456f6046cfSSam Ravnborg } 3466f6046cfSSam Ravnborg #else 3476f6046cfSSam Ravnborg wclrtoeol(win); 3486f6046cfSSam Ravnborg #endif 3496f6046cfSSam Ravnborg } 3506f6046cfSSam Ravnborg 3516f6046cfSSam Ravnborg /* 3526f6046cfSSam Ravnborg * Return current line of text. Called by dialog_textbox() and print_line(). 3536f6046cfSSam Ravnborg * 'page' should point to start of current line before calling, and will be 3546f6046cfSSam Ravnborg * updated to point to start of next line. 3556f6046cfSSam Ravnborg */ 3566f6046cfSSam Ravnborg static char *get_line(void) 3576f6046cfSSam Ravnborg { 3582982de69SSam Ravnborg int i = 0; 3596f6046cfSSam Ravnborg static char line[MAX_LEN + 1]; 3606f6046cfSSam Ravnborg 3616f6046cfSSam Ravnborg end_reached = 0; 3626f6046cfSSam Ravnborg while (*page != '\n') { 3636f6046cfSSam Ravnborg if (*page == '\0') { 3646f6046cfSSam Ravnborg end_reached = 1; 3656f6046cfSSam Ravnborg break; 3666f6046cfSSam Ravnborg } else if (i < MAX_LEN) 3676f6046cfSSam Ravnborg line[i++] = *(page++); 3686f6046cfSSam Ravnborg else { 3696f6046cfSSam Ravnborg /* Truncate lines longer than MAX_LEN characters */ 3706f6046cfSSam Ravnborg if (i == MAX_LEN) 3716f6046cfSSam Ravnborg line[i++] = '\0'; 3726f6046cfSSam Ravnborg page++; 3736f6046cfSSam Ravnborg } 3746f6046cfSSam Ravnborg } 3756f6046cfSSam Ravnborg if (i <= MAX_LEN) 3766f6046cfSSam Ravnborg line[i] = '\0'; 3776f6046cfSSam Ravnborg if (!end_reached) 378b9d29abdSBenjamin Poirier page++; /* move past '\n' */ 3796f6046cfSSam Ravnborg 3806f6046cfSSam Ravnborg return line; 3816f6046cfSSam Ravnborg } 3826f6046cfSSam Ravnborg 3836f6046cfSSam Ravnborg /* 3846f6046cfSSam Ravnborg * Print current position 3856f6046cfSSam Ravnborg */ 386c8dc68adSSam Ravnborg static void print_position(WINDOW * win) 3876f6046cfSSam Ravnborg { 3882982de69SSam Ravnborg int percent; 3896f6046cfSSam Ravnborg 39098e5a157SSam Ravnborg wattrset(win, dlg.position_indicator.atr); 39198e5a157SSam Ravnborg wbkgdset(win, dlg.position_indicator.atr & A_COLOR); 3922982de69SSam Ravnborg percent = (page - buf) * 100 / strlen(buf); 393c8dc68adSSam Ravnborg wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); 3946f6046cfSSam Ravnborg wprintw(win, "(%3d%%)", percent); 3956f6046cfSSam Ravnborg } 396