]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bsddialog/lib/theme.c
zfs: merge openzfs/zfs@a0b2a93c4
[FreeBSD/FreeBSD.git] / contrib / bsddialog / lib / theme.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2021-2023 Alfonso Sabato Siciliano
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <curses.h>
29
30 #include "bsddialog.h"
31 #include "bsddialog_theme.h"
32 #include "lib_util.h"
33
34 #define GET_COLOR(bg, fg) (COLOR_PAIR(bg * 8 + fg +1))
35 #define WHITE GET_COLOR(COLOR_WHITE, COLOR_BLACK)
36 #define BLACK GET_COLOR(COLOR_WHITE, COLOR_BLACK) | A_REVERSE
37 #define NFLAGS 6
38
39 struct bsddialog_theme t;
40 bool hastermcolors;
41
42 struct flag_converter {
43         unsigned int public;
44         unsigned int private;
45 };
46
47 static struct flag_converter flagconv[NFLAGS] = {
48         {BSDDIALOG_BLINK,      A_BLINK},
49         {BSDDIALOG_BOLD,       A_BOLD},
50         {BSDDIALOG_HALFBRIGHT, A_DIM},
51         {BSDDIALOG_HIGHLIGHT,  A_STANDOUT},
52         {BSDDIALOG_REVERSE,    A_REVERSE},
53         {BSDDIALOG_UNDERLINE,  A_UNDERLINE}
54 };
55
56 static struct bsddialog_theme blackwhite = {
57         .screen.color = WHITE,
58
59         .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
60         .shadow.y     = 1,
61         .shadow.x     = 2,
62
63         .dialog.delimtitle       = true,
64         .dialog.titlecolor       = WHITE,
65         .dialog.lineraisecolor   = WHITE,
66         .dialog.linelowercolor   = WHITE,
67         .dialog.color            = WHITE,
68         .dialog.bottomtitlecolor = WHITE,
69         .dialog.arrowcolor       = WHITE,
70
71         .menu.f_prefixcolor   = WHITE,
72         .menu.prefixcolor     = WHITE,
73         .menu.f_selectorcolor = BLACK,
74         .menu.selectorcolor   = WHITE,
75         .menu.f_desccolor     = BLACK,
76         .menu.desccolor       = WHITE,
77         .menu.f_namecolor     = BLACK,
78         .menu.namecolor       = WHITE,
79         .menu.f_shortcutcolor = BLACK | A_UNDERLINE,
80         .menu.shortcutcolor   = WHITE | A_UNDERLINE,
81         .menu.bottomdesccolor = WHITE,
82         .menu.sepnamecolor    = WHITE,
83         .menu.sepdesccolor    = WHITE,
84
85         .form.f_fieldcolor    = BLACK,
86         .form.fieldcolor      = WHITE,
87         .form.readonlycolor   = WHITE,
88         .form.bottomdesccolor = WHITE,
89
90         .bar.f_color = BLACK,
91         .bar.color   = WHITE,
92
93         .button.minmargin       = 1,
94         .button.maxmargin       = 5,
95         .button.leftdelim       = '[',
96         .button.rightdelim      = ']',
97         .button.f_delimcolor    = WHITE,
98         .button.delimcolor      = WHITE,
99         .button.f_color         = BLACK,
100         .button.color           = WHITE,
101         .button.f_shortcutcolor = BLACK | A_UNDERLINE | A_BOLD,
102         .button.shortcutcolor   = WHITE | A_UNDERLINE | A_BOLD
103 };
104
105 static struct bsddialog_theme flat = {
106         .screen.color = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD,
107
108         .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
109         .shadow.y     = 1,
110         .shadow.x     = 2,
111
112         .dialog.delimtitle       = true,
113         .dialog.titlecolor       = GET_COLOR(COLOR_BLUE,  COLOR_WHITE) | A_BOLD,
114         .dialog.lineraisecolor   = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
115         .dialog.linelowercolor   = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
116         .dialog.color            = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
117         .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
118         .dialog.arrowcolor       = GET_COLOR(COLOR_BLUE,  COLOR_WHITE),
119
120         .menu.f_prefixcolor   = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
121         .menu.prefixcolor     = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
122         .menu.f_selectorcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
123         .menu.selectorcolor   = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
124         .menu.f_desccolor     = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
125         .menu.desccolor       = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
126         .menu.f_namecolor     = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
127         .menu.namecolor       = GET_COLOR(COLOR_BLUE,  COLOR_WHITE),
128         .menu.f_shortcutcolor = GET_COLOR(COLOR_RED,   COLOR_BLUE),
129         .menu.shortcutcolor   = GET_COLOR(COLOR_RED,   COLOR_WHITE),
130         .menu.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
131         .menu.sepnamecolor    = GET_COLOR(COLOR_RED,   COLOR_WHITE),
132         .menu.sepdesccolor    = GET_COLOR(COLOR_RED,   COLOR_WHITE),
133
134         .form.f_fieldcolor    = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
135         .form.fieldcolor      = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
136         .form.readonlycolor   = GET_COLOR(COLOR_CYAN,  COLOR_WHITE)| A_BOLD,
137         .form.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
138
139         .bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE)  | A_BOLD,
140         .bar.color   = GET_COLOR(COLOR_BLUE,  COLOR_WHITE) | A_BOLD,
141
142         .button.minmargin       = 1,
143         .button.maxmargin       = 5,
144         .button.leftdelim       = '[',
145         .button.rightdelim      = ']',
146         .button.f_delimcolor    = GET_COLOR(COLOR_WHITE,  COLOR_BLUE)  | A_BOLD,
147         .button.delimcolor      = GET_COLOR(COLOR_BLACK,  COLOR_WHITE),
148         .button.f_color         = GET_COLOR(COLOR_YELLOW, COLOR_BLUE)  | A_BOLD,
149         .button.color           = GET_COLOR(COLOR_BLACK,  COLOR_WHITE),
150         .button.f_shortcutcolor = GET_COLOR(COLOR_WHITE,  COLOR_BLUE)  | A_BOLD,
151         .button.shortcutcolor   = GET_COLOR(COLOR_RED,    COLOR_WHITE) | A_BOLD
152 };
153
154 static void
155 set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src)
156 {
157         dst->screen.color = src->screen.color;
158
159         dst->shadow.color = src->shadow.color;
160         dst->shadow.y     = src->shadow.y;
161         dst->shadow.x     = src->shadow.x;
162
163         dst->dialog.delimtitle       = src->dialog.delimtitle;
164         dst->dialog.titlecolor       = src->dialog.titlecolor;
165         dst->dialog.lineraisecolor   = src->dialog.lineraisecolor;
166         dst->dialog.linelowercolor   = src->dialog.linelowercolor;
167         dst->dialog.color            = src->dialog.color;
168         dst->dialog.bottomtitlecolor = src->dialog.bottomtitlecolor;
169         dst->dialog.arrowcolor       = src->dialog.arrowcolor;
170
171         dst->menu.f_prefixcolor   = src->menu.f_prefixcolor;
172         dst->menu.prefixcolor     = src->menu.prefixcolor;
173         dst->menu.f_selectorcolor = src->menu.f_selectorcolor;
174         dst->menu.selectorcolor   = src->menu.selectorcolor;
175         dst->menu.f_desccolor     = src->menu.f_desccolor;
176         dst->menu.desccolor       = src->menu.desccolor;
177         dst->menu.f_namecolor     = src->menu.f_namecolor;
178         dst->menu.namecolor       = src->menu.namecolor;
179         dst->menu.f_shortcutcolor = src->menu.f_shortcutcolor;
180         dst->menu.shortcutcolor   = src->menu.shortcutcolor;
181         dst->menu.bottomdesccolor = src->menu.bottomdesccolor;
182         dst->menu.sepnamecolor    = src->menu.sepnamecolor;
183         dst->menu.sepdesccolor    = src->menu.sepdesccolor;
184
185         dst->form.f_fieldcolor    = src->form.f_fieldcolor;
186         dst->form.fieldcolor      = src->form.fieldcolor;
187         dst->form.readonlycolor   = src->form.readonlycolor;
188         dst->form.bottomdesccolor = src->form.bottomdesccolor;
189
190         dst->bar.f_color = src->bar.f_color;
191         dst->bar.color   = src->bar.color;
192
193         dst->button.minmargin       = src->button.minmargin;
194         dst->button.maxmargin       = src->button.maxmargin;
195         dst->button.leftdelim       = src->button.leftdelim;
196         dst->button.rightdelim      = src->button.rightdelim;
197         dst->button.f_delimcolor    = src->button.f_delimcolor;
198         dst->button.delimcolor      = src->button.delimcolor;
199         dst->button.f_color         = src->button.f_color;
200         dst->button.color           = src->button.color;
201         dst->button.f_shortcutcolor = src->button.f_shortcutcolor;
202         dst->button.shortcutcolor   = src->button.shortcutcolor;
203
204         bkgd(dst->screen.color);
205 }
206
207 /* API */
208 int bsddialog_get_theme(struct bsddialog_theme *theme)
209 {
210         CHECK_PTR(theme);
211         set_theme(theme, &t);
212
213         return (BSDDIALOG_OK);
214 }
215
216 int bsddialog_set_theme(struct bsddialog_theme *theme)
217 {
218         CHECK_PTR(theme);
219         set_theme(&t, theme);
220         refresh();
221
222         return (BSDDIALOG_OK);
223 }
224
225 int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
226 {
227         if (newtheme == BSDDIALOG_THEME_3D) {
228                 set_theme(&t, &flat);
229                 t.dialog.lineraisecolor   =
230                     GET_COLOR(COLOR_WHITE, COLOR_WHITE) | A_BOLD;
231                 t.dialog.delimtitle       = false;
232                 t.dialog.bottomtitlecolor = t.dialog.bottomtitlecolor | A_BOLD;
233         } else if (newtheme == BSDDIALOG_THEME_BLACKWHITE) {
234                 set_theme(&t, &blackwhite);
235         } else if (newtheme == BSDDIALOG_THEME_FLAT) {
236                 set_theme(&t, &flat);
237         } else {
238                 RETURN_FMTERROR("Unknown default theme (%d), "
239                     "to use enum bsddialog_default_theme",
240                     newtheme);
241         }
242         refresh();
243
244         return (BSDDIALOG_OK);
245 }
246
247 int
248 bsddialog_color(enum bsddialog_color foreground,
249     enum bsddialog_color background, unsigned int flags)
250 {
251         unsigned int i, f;
252
253         f = 0;
254         for (i=0; i < NFLAGS; i++)
255                 if (flags & flagconv[i].public)
256                         f |= flagconv[i].private;
257
258         return (GET_COLOR(foreground, background) | f);
259 }
260
261 int
262 bsddialog_color_attrs(int color, enum bsddialog_color *foreground,
263     enum bsddialog_color *background, unsigned int *flags)
264 {
265         short fg, bg;
266         unsigned int i, f;
267
268         if (flags != NULL) {
269                 f = 0;
270                 for (i=0; i < NFLAGS; i++)
271                         if (color & flagconv[i].private)
272                                 f |= flagconv[i].public;
273                 *flags = f;
274         }
275         if (pair_content(PAIR_NUMBER(color), &fg, &bg) != OK)
276                 RETURN_ERROR("Cannot get color attributes");
277         if (foreground != NULL)
278                 *foreground = fg;
279         if (background != NULL)
280                 *background = bg;
281
282         return (BSDDIALOG_OK);
283 }
284
285 bool bsddialog_hascolors(void)
286 {
287         return (hastermcolors);
288 }