mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-04 23:50:27 +00:00
a6d8be451f
Implicitly import also 1.0.1, both versions are for fixing and feature requests. Fixing: Change --mixedform behavior to fix a bsdinstall fault avoiding to change the command line in wlanconfig. Feature requests: * Add keys to navigate menus. * Add key to redraw dialogs. * Avoid to handle env NCURSES_NO_UTF8_ACS in PuTTY. See '2024-04-11 Version 1.0.2' and '2023-11-16 Version 1.0.1' in /usr/src/contrib/bsddialog/CHANGELOG for more detailed information. PR: 274472 Differential Revision: D42380 Merge commit 'be8846bd9e069f4a6bea3d769005bea96cf43990'
232 lines
6 KiB
C
232 lines
6 KiB
C
/*-
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 2021-2024 Alfonso Sabato Siciliano
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <curses.h>
|
|
|
|
#include "bsddialog.h"
|
|
#include "bsddialog_theme.h"
|
|
#include "lib_util.h"
|
|
|
|
struct scroll {
|
|
int ypad; /* y scrollable pad */
|
|
int htext; /* real h text to draw, to use with htextpad */
|
|
int htextpad; /* h textpad, draw_dialog() set at least 1 */
|
|
int printrows; /* h - BORDER - HBUTTONS - BORDER */
|
|
};
|
|
|
|
static void textupdate(struct dialog *d, struct scroll *s)
|
|
{
|
|
if (s->htext > 0 && s->htextpad > s->printrows) {
|
|
wattron(d->widget, t.dialog.arrowcolor);
|
|
mvwprintw(d->widget, d->h - HBUTTONS - BORDER,
|
|
d->w - 4 - TEXTHMARGIN - BORDER,
|
|
"%3d%%", 100 * (s->ypad + s->printrows) / s->htextpad);
|
|
wattroff(d->widget, t.dialog.arrowcolor);
|
|
wnoutrefresh(d->widget);
|
|
}
|
|
rtextpad(d, s->ypad, 0, 0, HBUTTONS);
|
|
}
|
|
|
|
static int message_size_position(struct dialog *d, int *htext)
|
|
{
|
|
int minw;
|
|
|
|
if (set_widget_size(d->conf, d->rows, d->cols, &d->h, &d->w) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
if (set_widget_autosize(d->conf, d->rows, d->cols, &d->h, &d->w,
|
|
d->text, (*htext < 0) ? htext : NULL, &d->bs, 0, 0) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
minw = (*htext > 0) ? 1 + TEXTHMARGINS : 0 ;
|
|
if (widget_checksize(d->h, d->w, &d->bs, MIN(*htext, 1), minw) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
if (set_widget_position(d->conf, &d->y, &d->x, d->h, d->w) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int message_draw(struct dialog *d, struct scroll *s)
|
|
{
|
|
int unused;
|
|
|
|
if (d->built) {
|
|
hide_dialog(d);
|
|
refresh(); /* Important for decreasing screen */
|
|
}
|
|
if (message_size_position(d, &s->htext) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
if (draw_dialog(d) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
if (d->built)
|
|
refresh(); /* Important to fix grey lines expanding screen */
|
|
|
|
s->printrows = d->h - BORDER - HBUTTONS - BORDER;
|
|
s->ypad = 0;
|
|
getmaxyx(d->textpad, s->htextpad, unused);
|
|
(void)unused; /* fix unused error */
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
|
|
const char *oklabel, const char *cancellabel)
|
|
{
|
|
bool loop;
|
|
int retval;
|
|
wint_t input;
|
|
struct scroll s;
|
|
struct dialog d;
|
|
|
|
if (prepare_dialog(conf, text, rows, cols, &d) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
set_buttons(&d, true, oklabel, cancellabel);
|
|
s.htext = -1;
|
|
if (message_draw(&d, &s) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
|
|
loop = true;
|
|
while (loop) {
|
|
textupdate(&d, &s);
|
|
doupdate();
|
|
if (get_wch(&input) == ERR)
|
|
continue;
|
|
switch (input) {
|
|
case KEY_ENTER:
|
|
case 10: /* Enter */
|
|
retval = BUTTONVALUE(d.bs);
|
|
loop = false;
|
|
break;
|
|
case 27: /* Esc */
|
|
if (d.conf->key.enable_esc) {
|
|
retval = BSDDIALOG_ESC;
|
|
loop = false;
|
|
}
|
|
break;
|
|
case '\t': /* TAB */
|
|
case KEY_RIGHT:
|
|
d.bs.curr = (d.bs.curr + 1) % d.bs.nbuttons;
|
|
DRAW_BUTTONS(d);
|
|
break;
|
|
case KEY_LEFT:
|
|
d.bs.curr--;
|
|
if (d.bs.curr < 0)
|
|
d.bs.curr = d.bs.nbuttons - 1;
|
|
DRAW_BUTTONS(d);
|
|
break;
|
|
case '-':
|
|
case KEY_CTRL('p'):
|
|
case KEY_UP:
|
|
if (s.ypad > 0)
|
|
s.ypad--;
|
|
break;
|
|
case '+':
|
|
case KEY_CTRL('n'):
|
|
case KEY_DOWN:
|
|
if (s.ypad + s.printrows < s.htextpad)
|
|
s.ypad++;
|
|
break;
|
|
case KEY_HOME:
|
|
s.ypad = 0;
|
|
break;
|
|
case KEY_END:
|
|
s.ypad = MAX(s.htextpad - s.printrows, 0);
|
|
break;
|
|
case KEY_PPAGE:
|
|
s.ypad = MAX(s.ypad - s.printrows, 0);
|
|
break;
|
|
case KEY_NPAGE:
|
|
s.ypad += s.printrows;
|
|
if (s.ypad + s.printrows > s.htextpad)
|
|
s.ypad = s.htextpad - s.printrows;
|
|
break;
|
|
case KEY_F(1):
|
|
if (d.conf->key.f1_file == NULL &&
|
|
d.conf->key.f1_message == NULL)
|
|
break;
|
|
if (f1help_dialog(d.conf) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
if (message_draw(&d, &s) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
break;
|
|
case KEY_CTRL('l'):
|
|
case KEY_RESIZE:
|
|
if (message_draw(&d, &s) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
break;
|
|
default:
|
|
if (shortcut_buttons(input, &d.bs)) {
|
|
DRAW_BUTTONS(d);
|
|
doupdate();
|
|
retval = BUTTONVALUE(d.bs);
|
|
loop = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
end_dialog(&d);
|
|
|
|
return (retval);
|
|
}
|
|
|
|
/* API */
|
|
int
|
|
bsddialog_msgbox(struct bsddialog_conf *conf, const char *text, int rows,
|
|
int cols)
|
|
{
|
|
return (do_message(conf, text, rows, cols, OK_LABEL, NULL));
|
|
}
|
|
|
|
int
|
|
bsddialog_yesno(struct bsddialog_conf *conf, const char *text, int rows,
|
|
int cols)
|
|
{
|
|
return (do_message(conf, text, rows, cols, "Yes", "No"));
|
|
}
|
|
|
|
int
|
|
bsddialog_infobox(struct bsddialog_conf *conf, const char *text, int rows,
|
|
int cols)
|
|
{
|
|
int htext;
|
|
struct dialog d;
|
|
|
|
if (prepare_dialog(conf, text, rows, cols, &d) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
htext = -1;
|
|
if (message_size_position(&d, &htext) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
if (draw_dialog(&d) != 0)
|
|
return (BSDDIALOG_ERROR);
|
|
TEXTPAD(&d, 0);
|
|
doupdate();
|
|
|
|
end_dialog(&d);
|
|
|
|
return (BSDDIALOG_OK);
|
|
}
|