diff options
Diffstat (limited to 'lib/messagebox.c')
-rw-r--r-- | lib/messagebox.c | 237 |
1 files changed, 98 insertions, 139 deletions
diff --git a/lib/messagebox.c b/lib/messagebox.c index 6fe775cfcbc9..edea7c41c18d 100644 --- a/lib/messagebox.c +++ b/lib/messagebox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,60 +27,34 @@ #include <sys/param.h> -#include <ctype.h> -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> #include <string.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" - -#define AUTO_WIDTH (COLS / 3U) -/* at least 1 line text for its pad building in widget_withtextpad_init() */ -#define MIN_HEIGHT (HBORDERS + 2 /*buttons*/ + 1 /*text*/) +#include "lib_util.h" extern struct bsddialog_theme t; static int message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, - int *w, char *text, struct buttons bs) + int *w, const char *text, struct buttons bs) { - int maxword, maxline, nlines, line; - - if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0) - return BSDDIALOG_ERROR; - - if (cols == BSDDIALOG_AUTOSIZE) { - *w = VBORDERS; - /* buttons size */ - *w += bs.nbuttons * bs.sizebutton; - *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; - /* text size */ - line = MIN(maxline + VBORDERS + t.text.hmargin * 2, AUTO_WIDTH); - line = MAX(line, (int) (maxword + VBORDERS + t.text.hmargin * 2)); - *w = MAX(*w, line); - /* conf.auto_minwidth */ - *w = MAX(*w, (int)conf->auto_minwidth); - /* avoid terminal overflow */ - *w = MIN(*w, widget_max_width(conf)); - } + int htext, wtext; - if (rows == BSDDIALOG_AUTOSIZE) { - *h = MIN_HEIGHT - 1; - if (maxword > 0) - *h += MAX(nlines, (int)(*w / GET_ASPECT_RATIO(conf))); - *h = MAX(*h, MIN_HEIGHT); - /* conf.auto_minheight */ - *h = MAX(*h, (int)conf->auto_minheight); - /* avoid terminal overflow */ - *h = MIN(*h, widget_max_height(conf)); + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, &bs, 0, SCREENCOLS/2, + &htext, &wtext) != 0) + return (BSDDIALOG_ERROR); } - return 0; + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, wtext, 0, &bs); + + if (rows == BSDDIALOG_AUTOSIZE) + *h = widget_min_height(conf, htext, 0, true); + + return (0); } static int message_checksize(int rows, int cols, struct buttons bs) @@ -92,182 +66,167 @@ static int message_checksize(int rows, int cols, struct buttons bs) mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; if (cols < mincols) - RETURN_ERROR("Few cols, Msgbox and Yesno need at least width "\ + RETURN_ERROR("Few cols, Msgbox and Yesno need at least width " "for borders, buttons and spaces between buttons"); - if (rows < MIN_HEIGHT) - RETURN_ERROR("Msgbox and Yesno need at least height 5"); + if (rows < HBORDERS + 2 /*buttons*/) + RETURN_ERROR("Msgbox and Yesno need at least height 4"); - return 0; + return (0); } static void -buttonsupdate(WINDOW *widget, int h, int w, struct buttons bs) +textupdate(WINDOW *widget, WINDOW *textpad, int htextpad, int ytextpad) { - draw_buttons(widget, h-2, w, bs, true); - wnoutrefresh(widget); -} + int y, x, h, w; + + getbegyx(widget, y, x); + getmaxyx(widget, h, w); -static void -textupdate(WINDOW *widget, int y, int x, int h, int w, WINDOW *textpad, - int htextpad, int textrow) -{ if (htextpad > h - 4) { mvwprintw(widget, h-3, w-6, "%3d%%", - 100 * (textrow+h-4)/ htextpad); + 100 * (ytextpad+h-4)/ htextpad); wnoutrefresh(widget); } - pnoutrefresh(textpad, textrow, 0, y+1, x+2, y+h-4, x+w-2); + pnoutrefresh(textpad, ytextpad, 0, y+1, x+2, y+h-4, x+w-2); } static int -do_dialog(struct bsddialog_conf *conf, char *text, int rows, int cols, +do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, struct buttons bs) { - WINDOW *widget, *textpad, *shadow; bool loop; - int i, y, x, h, w, input, output, htextpad, textrow; + int y, x, h, w, input, output, ytextpad, htextpad, unused; + WINDOW *widget, *textpad, *shadow; if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (message_checksize(h, w, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + true) != 0) + return (BSDDIALOG_ERROR); - textrow = 0; + ytextpad = 0; + getmaxyx(textpad, htextpad, unused); + unused++; /* fix unused error */ + textupdate(widget, textpad, htextpad, ytextpad); loop = true; - buttonsupdate(widget, h, w, bs); - textupdate(widget, y, x, h, w, textpad, htextpad, textrow); - while(loop) { + while (loop) { doupdate(); input = getch(); switch (input) { + case KEY_ENTER: case 10: /* Enter */ output = bs.value[bs.curr]; loop = false; break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = BSDDIALOG_ESC; + loop = false; + } break; case '\t': /* TAB */ bs.curr = (bs.curr + 1) % bs.nbuttons; - buttonsupdate(widget, h, w, bs); + draw_buttons(widget, bs, true); + wnoutrefresh(widget); + break; + case KEY_LEFT: + if (bs.curr > 0) { + bs.curr--; + draw_buttons(widget, bs, true); + wnoutrefresh(widget); + } + break; + case KEY_RIGHT: + if (bs.curr < (int)bs.nbuttons - 1) { + bs.curr++; + draw_buttons(widget, bs, true); + wnoutrefresh(widget); + } break; case KEY_F(1): if (conf->f1_file == NULL && conf->f1_message == NULL) break; if (f1help(conf) != 0) - return BSDDIALOG_ERROR; - /* No break! the terminal size can change */ + return (BSDDIALOG_ERROR); + /* No break, screen size can change */ case KEY_RESIZE: - hide_widget(y, x, h, w,conf->shadow); - - /* - * Unnecessary, but, when the columns decrease the - * following "refresh" seem not work - */ + /* Important for decreasing screen */ + hide_widget(y, x, h, w, conf->shadow); refresh(); if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; - if (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (message_autosize(conf, rows, cols, &h, &w, text, + bs) != 0) + return (BSDDIALOG_ERROR); if (message_checksize(h, w, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - wclear(shadow); - mvwin(shadow, y + t.shadow.h, x + t.shadow.w); - wresize(shadow, h, w); + if (update_dialog(conf, shadow, widget, y, x, h, w, + textpad, text, &bs, true) != 0) + return (BSDDIALOG_ERROR); - wclear(widget); - mvwin(widget, y, x); - wresize(widget, h, w); - - htextpad = 1; - wclear(textpad); - wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); - - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - buttonsupdate(widget, h, w, bs); - textupdate(widget, y, x, h, w, textpad, htextpad, textrow); + getmaxyx(textpad, htextpad, unused); + textupdate(widget, textpad, htextpad, ytextpad); /* Important to fix grey lines expanding screen */ refresh(); break; case KEY_UP: - if (textrow == 0) + if (ytextpad == 0) break; - textrow--; - textupdate(widget, y, x, h, w, textpad, htextpad, textrow); + ytextpad--; + textupdate(widget, textpad, htextpad, ytextpad); break; case KEY_DOWN: - if (textrow + h - 4 >= htextpad) + if (ytextpad + h - 4 >= htextpad) break; - textrow++; - textupdate(widget, y, x, h, w, textpad, htextpad, textrow); - break; - case KEY_LEFT: - if (bs.curr > 0) { - bs.curr--; - buttonsupdate(widget, h, w, bs); - } - break; - case KEY_RIGHT: - if (bs.curr < (int) bs.nbuttons - 1) { - bs.curr++; - buttonsupdate(widget, h, w, bs); - } + ytextpad++; + textupdate(widget, textpad, htextpad, ytextpad); break; default: - for (i = 0; i < (int) bs.nbuttons; i++) - if (tolower(input) == tolower(bs.label[i][0])) { - output = bs.value[i]; - loop = false; + if (shortcut_buttons(input, &bs)) { + output = bs.value[bs.curr]; + loop = false; } } } - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return output; + return (output); } /* API */ int -bsddialog_msgbox(struct bsddialog_conf *conf, char* text, int rows, int cols) +bsddialog_msgbox(struct bsddialog_conf *conf, const char *text, int rows, + int cols) { struct buttons bs; - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - NULL, BUTTONLABEL(help_label)); + get_buttons(conf, &bs, BUTTON_OK_LABEL, NULL); - return (do_dialog(conf, text, rows, cols, bs)); + return (do_message(conf, text, rows, cols, bs)); } int -bsddialog_yesno(struct bsddialog_conf *conf, char* text, int rows, int cols) +bsddialog_yesno(struct bsddialog_conf *conf, const char *text, int rows, + int cols) { struct buttons bs; - get_buttons(conf, &bs, - conf->button.ok_label == NULL ? "Yes" : conf->button.ok_label, - BUTTONLABEL(extra_label), - conf->button.cancel_label == NULL ? "No" : conf->button.cancel_label, - BUTTONLABEL(help_label)); + get_buttons(conf, &bs, "Yes", "No"); - return (do_dialog(conf, text, rows, cols, bs)); -} + return (do_message(conf, text, rows, cols, bs)); +}
\ No newline at end of file |