xref: /freebsd/contrib/bsddialog/lib/messagebox.c (revision 61ba55bcf70f2340f9c943c9571113b3fd8eda69)
1c76f0793SBaptiste Daroussin /*-
2c76f0793SBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
3c76f0793SBaptiste Daroussin  *
4*61ba55bcSBaptiste Daroussin  * Copyright (c) 2021-2023 Alfonso Sabato Siciliano
5c76f0793SBaptiste Daroussin  *
6c76f0793SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
7c76f0793SBaptiste Daroussin  * modification, are permitted provided that the following conditions
8c76f0793SBaptiste Daroussin  * are met:
9c76f0793SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
10c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
11c76f0793SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
12c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
13c76f0793SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
14c76f0793SBaptiste Daroussin  *
15c76f0793SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16c76f0793SBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17c76f0793SBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18c76f0793SBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c76f0793SBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c76f0793SBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21c76f0793SBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c76f0793SBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c76f0793SBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c76f0793SBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c76f0793SBaptiste Daroussin  * SUCH DAMAGE.
26c76f0793SBaptiste Daroussin  */
27c76f0793SBaptiste Daroussin 
28263660c0SAlfonso Siciliano #include <curses.h>
29c76f0793SBaptiste Daroussin 
30c76f0793SBaptiste Daroussin #include "bsddialog.h"
31b319d934SAlfonso S. Siciliano #include "bsddialog_theme.h"
32263660c0SAlfonso Siciliano #include "lib_util.h"
33c76f0793SBaptiste Daroussin 
34*61ba55bcSBaptiste Daroussin struct scroll {
35*61ba55bcSBaptiste Daroussin 	int ypad;      /* y scrollable pad */
36*61ba55bcSBaptiste Daroussin 	int htext;     /* real h text to draw, to use with htextpad */
37*61ba55bcSBaptiste Daroussin 	int htextpad;  /* h textpad, draw_dialog() set at least 1 */
38*61ba55bcSBaptiste Daroussin 	int printrows; /* h - BORDER - HBUTTONS - BORDER */
39*61ba55bcSBaptiste Daroussin };
40c76f0793SBaptiste Daroussin 
41*61ba55bcSBaptiste Daroussin static void textupdate(struct dialog *d, struct scroll *s)
42*61ba55bcSBaptiste Daroussin {
43*61ba55bcSBaptiste Daroussin 	if (s->htext > 0 && s->htextpad > s->printrows) {
44*61ba55bcSBaptiste Daroussin 		wattron(d->widget, t.dialog.arrowcolor);
45*61ba55bcSBaptiste Daroussin 		mvwprintw(d->widget, d->h - HBUTTONS - BORDER,
46*61ba55bcSBaptiste Daroussin 		    d->w - 4 - TEXTHMARGIN - BORDER,
47*61ba55bcSBaptiste Daroussin 		    "%3d%%", 100 * (s->ypad + s->printrows) / s->htextpad);
48*61ba55bcSBaptiste Daroussin 		wattroff(d->widget, t.dialog.arrowcolor);
49*61ba55bcSBaptiste Daroussin 		wnoutrefresh(d->widget);
50*61ba55bcSBaptiste Daroussin 	}
51*61ba55bcSBaptiste Daroussin 	rtextpad(d, s->ypad, 0, 0, HBUTTONS);
52*61ba55bcSBaptiste Daroussin }
53*61ba55bcSBaptiste Daroussin 
54*61ba55bcSBaptiste Daroussin static int message_size_position(struct dialog *d, int *htext)
55*61ba55bcSBaptiste Daroussin {
56*61ba55bcSBaptiste Daroussin 	int minw;
57*61ba55bcSBaptiste Daroussin 
58*61ba55bcSBaptiste Daroussin 	if (set_widget_size(d->conf, d->rows, d->cols, &d->h, &d->w) != 0)
59263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
60*61ba55bcSBaptiste Daroussin 	if (set_widget_autosize(d->conf, d->rows, d->cols, &d->h, &d->w,
61*61ba55bcSBaptiste Daroussin 	    d->text, (*htext < 0) ? htext : NULL, &d->bs, 0, 0) != 0)
62*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
63*61ba55bcSBaptiste Daroussin 	minw = (*htext > 0) ? 1 + TEXTHMARGINS : 0 ;
64*61ba55bcSBaptiste Daroussin 	if (widget_checksize(d->h, d->w, &d->bs, MIN(*htext, 1), minw) != 0)
65*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
66*61ba55bcSBaptiste Daroussin 	if (set_widget_position(d->conf, &d->y, &d->x, d->h, d->w) != 0)
67*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
68263660c0SAlfonso Siciliano 
69263660c0SAlfonso Siciliano 	return (0);
70c76f0793SBaptiste Daroussin }
71c76f0793SBaptiste Daroussin 
72*61ba55bcSBaptiste Daroussin static int message_draw(struct dialog *d, struct scroll *s)
73c76f0793SBaptiste Daroussin {
74*61ba55bcSBaptiste Daroussin 	int unused;
75c76f0793SBaptiste Daroussin 
76*61ba55bcSBaptiste Daroussin 	if (d->built) {
77*61ba55bcSBaptiste Daroussin 		hide_dialog(d);
78*61ba55bcSBaptiste Daroussin 		refresh(); /* Important for decreasing screen */
79*61ba55bcSBaptiste Daroussin 	}
80*61ba55bcSBaptiste Daroussin 	if (message_size_position(d, &s->htext) != 0)
81*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
82*61ba55bcSBaptiste Daroussin 	if (draw_dialog(d) != 0)
83*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
84*61ba55bcSBaptiste Daroussin 	if (d->built)
85*61ba55bcSBaptiste Daroussin 		refresh(); /* Important to fix grey lines expanding screen */
86c76f0793SBaptiste Daroussin 
87*61ba55bcSBaptiste Daroussin 	s->printrows = d->h - BORDER - HBUTTONS - BORDER;
88*61ba55bcSBaptiste Daroussin 	s->ypad = 0;
89*61ba55bcSBaptiste Daroussin 	getmaxyx(d->textpad, s->htextpad, unused);
90*61ba55bcSBaptiste Daroussin 	unused++; /* fix unused error */
91c76f0793SBaptiste Daroussin 
92263660c0SAlfonso Siciliano 	return (0);
93c76f0793SBaptiste Daroussin }
94c76f0793SBaptiste Daroussin 
95c76f0793SBaptiste Daroussin static int
96263660c0SAlfonso Siciliano do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
97*61ba55bcSBaptiste Daroussin     const char *oklabel, const char *cancellabel)
98c76f0793SBaptiste Daroussin {
99*61ba55bcSBaptiste Daroussin 	bool loop;
100*61ba55bcSBaptiste Daroussin 	int retval;
101b319d934SAlfonso S. Siciliano 	wint_t input;
102*61ba55bcSBaptiste Daroussin 	struct scroll s;
103*61ba55bcSBaptiste Daroussin 	struct dialog d;
104c76f0793SBaptiste Daroussin 
105*61ba55bcSBaptiste Daroussin 	if (prepare_dialog(conf, text, rows, cols, &d) != 0)
106263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
107*61ba55bcSBaptiste Daroussin 	set_buttons(&d, true, oklabel, cancellabel);
108*61ba55bcSBaptiste Daroussin 	s.htext = -1;
109*61ba55bcSBaptiste Daroussin 	if(message_draw(&d, &s) != 0)
110263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
111c76f0793SBaptiste Daroussin 
112c76f0793SBaptiste Daroussin 	loop = true;
113c76f0793SBaptiste Daroussin 	while (loop) {
114*61ba55bcSBaptiste Daroussin 		textupdate(&d, &s);
115c76f0793SBaptiste Daroussin 		doupdate();
116b319d934SAlfonso S. Siciliano 		if (get_wch(&input) == ERR)
117b319d934SAlfonso S. Siciliano 			continue;
118c76f0793SBaptiste Daroussin 		switch (input) {
119263660c0SAlfonso Siciliano 		case KEY_ENTER:
120c76f0793SBaptiste Daroussin 		case 10: /* Enter */
121*61ba55bcSBaptiste Daroussin 			retval = BUTTONVALUE(d.bs);
122c76f0793SBaptiste Daroussin 			loop = false;
123c76f0793SBaptiste Daroussin 			break;
124c76f0793SBaptiste Daroussin 		case 27: /* Esc */
125*61ba55bcSBaptiste Daroussin 			if (d.conf->key.enable_esc) {
126b319d934SAlfonso S. Siciliano 				retval = BSDDIALOG_ESC;
127c76f0793SBaptiste Daroussin 				loop = false;
128263660c0SAlfonso Siciliano 			}
129c76f0793SBaptiste Daroussin 			break;
130c76f0793SBaptiste Daroussin 		case '\t': /* TAB */
131*61ba55bcSBaptiste Daroussin 		case KEY_RIGHT:
132*61ba55bcSBaptiste Daroussin 			d.bs.curr = (d.bs.curr + 1) % d.bs.nbuttons;
133*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
134c76f0793SBaptiste Daroussin 			break;
135c76f0793SBaptiste Daroussin 		case KEY_LEFT:
136*61ba55bcSBaptiste Daroussin 			d.bs.curr--;
137*61ba55bcSBaptiste Daroussin 			if (d.bs.curr < 0)
138*61ba55bcSBaptiste Daroussin 				 d.bs.curr = d.bs.nbuttons - 1;
139*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
140c76f0793SBaptiste Daroussin 			break;
14184823cc7SAlfonso S. Siciliano 		case KEY_UP:
142*61ba55bcSBaptiste Daroussin 			if (s.ypad > 0)
143*61ba55bcSBaptiste Daroussin 				s.ypad--;
14484823cc7SAlfonso S. Siciliano 			break;
14584823cc7SAlfonso S. Siciliano 		case KEY_DOWN:
146*61ba55bcSBaptiste Daroussin 			if (s.ypad + s.printrows < s.htextpad)
147*61ba55bcSBaptiste Daroussin 				s.ypad++;
14884823cc7SAlfonso S. Siciliano 			break;
14984823cc7SAlfonso S. Siciliano 		case KEY_HOME:
150*61ba55bcSBaptiste Daroussin 			s.ypad = 0;
15184823cc7SAlfonso S. Siciliano 			break;
15284823cc7SAlfonso S. Siciliano 		case KEY_END:
153*61ba55bcSBaptiste Daroussin 			s.ypad = MAX(s.htextpad - s.printrows, 0);
15484823cc7SAlfonso S. Siciliano 			break;
15584823cc7SAlfonso S. Siciliano 		case KEY_PPAGE:
156*61ba55bcSBaptiste Daroussin 			s.ypad = MAX(s.ypad - s.printrows, 0);
15784823cc7SAlfonso S. Siciliano 			break;
15884823cc7SAlfonso S. Siciliano 		case KEY_NPAGE:
159*61ba55bcSBaptiste Daroussin 			s.ypad += s.printrows;
160*61ba55bcSBaptiste Daroussin 			if (s.ypad + s.printrows > s.htextpad)
161*61ba55bcSBaptiste Daroussin 				s.ypad = s.htextpad - s.printrows;
16284823cc7SAlfonso S. Siciliano 			break;
163263660c0SAlfonso Siciliano 		case KEY_F(1):
164*61ba55bcSBaptiste Daroussin 			if (d.conf->key.f1_file == NULL &&
165*61ba55bcSBaptiste Daroussin 			    d.conf->key.f1_message == NULL)
166263660c0SAlfonso Siciliano 				break;
167*61ba55bcSBaptiste Daroussin 			if (f1help_dialog(d.conf) != 0)
168263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
169*61ba55bcSBaptiste Daroussin 			if(message_draw(&d, &s) != 0)
170*61ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
171*61ba55bcSBaptiste Daroussin 			break;
172263660c0SAlfonso Siciliano 		case KEY_RESIZE:
173*61ba55bcSBaptiste Daroussin 			if(message_draw(&d, &s) != 0)
174263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
175263660c0SAlfonso Siciliano 			break;
176c76f0793SBaptiste Daroussin 		default:
177*61ba55bcSBaptiste Daroussin 			if (shortcut_buttons(input, &d.bs)) {
178*61ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
179*61ba55bcSBaptiste Daroussin 				doupdate();
180*61ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
181c76f0793SBaptiste Daroussin 				loop = false;
182c76f0793SBaptiste Daroussin 			}
183c76f0793SBaptiste Daroussin 		}
184c76f0793SBaptiste Daroussin 	}
185c76f0793SBaptiste Daroussin 
186*61ba55bcSBaptiste Daroussin 	end_dialog(&d);
187c76f0793SBaptiste Daroussin 
188b319d934SAlfonso S. Siciliano 	return (retval);
189c76f0793SBaptiste Daroussin }
190c76f0793SBaptiste Daroussin 
191c76f0793SBaptiste Daroussin /* API */
192c76f0793SBaptiste Daroussin int
193263660c0SAlfonso Siciliano bsddialog_msgbox(struct bsddialog_conf *conf, const char *text, int rows,
194263660c0SAlfonso Siciliano     int cols)
195c76f0793SBaptiste Daroussin {
196*61ba55bcSBaptiste Daroussin 	return (do_message(conf, text, rows, cols, OK_LABEL, NULL));
197c76f0793SBaptiste Daroussin }
198c76f0793SBaptiste Daroussin 
199c76f0793SBaptiste Daroussin int
200263660c0SAlfonso Siciliano bsddialog_yesno(struct bsddialog_conf *conf, const char *text, int rows,
201263660c0SAlfonso Siciliano     int cols)
202c76f0793SBaptiste Daroussin {
203*61ba55bcSBaptiste Daroussin 	return (do_message(conf, text, rows, cols, "Yes", "No"));
204*61ba55bcSBaptiste Daroussin }
205c76f0793SBaptiste Daroussin 
206*61ba55bcSBaptiste Daroussin int
207*61ba55bcSBaptiste Daroussin bsddialog_infobox(struct bsddialog_conf *conf, const char *text, int rows,
208*61ba55bcSBaptiste Daroussin     int cols)
209*61ba55bcSBaptiste Daroussin {
210*61ba55bcSBaptiste Daroussin 	int htext;
211*61ba55bcSBaptiste Daroussin 	struct dialog d;
212c76f0793SBaptiste Daroussin 
213*61ba55bcSBaptiste Daroussin 	if (prepare_dialog(conf, text, rows, cols, &d) != 0)
214*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
215*61ba55bcSBaptiste Daroussin 	htext = -1;
216*61ba55bcSBaptiste Daroussin 	if (message_size_position(&d, &htext) != 0)
217*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
218*61ba55bcSBaptiste Daroussin 	if (draw_dialog(&d) != 0)
219*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
220*61ba55bcSBaptiste Daroussin 	TEXTPAD(&d, 0);
221*61ba55bcSBaptiste Daroussin 	doupdate();
222*61ba55bcSBaptiste Daroussin 
223*61ba55bcSBaptiste Daroussin 	end_dialog(&d);
224*61ba55bcSBaptiste Daroussin 
225*61ba55bcSBaptiste Daroussin 	return (BSDDIALOG_OK);
226c76f0793SBaptiste Daroussin }
227