1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2021-2022 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 36 struct bsddialog_theme t; 37 38 static struct bsddialog_theme bsddialogtheme = { 39 #define bgwidget COLOR_WHITE 40 #define bgcurr COLOR_YELLOW 41 .screen.color = GET_COLOR(COLOR_BLACK, COLOR_CYAN), 42 43 .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK), 44 .shadow.h = 1, 45 .shadow.w = 2, 46 47 .dialog.delimtitle = true, 48 .dialog.titlecolor = GET_COLOR(COLOR_YELLOW, bgwidget), 49 .dialog.lineraisecolor = GET_COLOR(COLOR_BLACK, bgwidget), 50 .dialog.linelowercolor = GET_COLOR(COLOR_BLACK, bgwidget), 51 .dialog.color = GET_COLOR(COLOR_BLACK, bgwidget), 52 .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, bgwidget), 53 .dialog.arrowcolor = GET_COLOR(COLOR_YELLOW, bgwidget), 54 55 .menu.f_selectorcolor = GET_COLOR(COLOR_BLACK, bgcurr), 56 .menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget), 57 .menu.f_desccolor = GET_COLOR(COLOR_WHITE, bgcurr), 58 .menu.desccolor = GET_COLOR(COLOR_BLACK, bgwidget), 59 .menu.f_namecolor = GET_COLOR(COLOR_BLACK, bgcurr), 60 .menu.namecolor = GET_COLOR(COLOR_BLACK, bgwidget), 61 .menu.namesepcolor = GET_COLOR(COLOR_YELLOW, bgwidget), 62 .menu.descsepcolor = GET_COLOR(COLOR_YELLOW, bgwidget), 63 .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, bgcurr), 64 .menu.shortcutcolor = GET_COLOR(COLOR_RED, bgwidget), 65 66 .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), 67 .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN), 68 .form.readonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE), 69 70 .bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE), 71 .bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE), 72 73 .button.hmargin = 3, 74 .button.leftdelim = '[', 75 .button.rightdelim = ']', 76 .button.f_delimcolor = GET_COLOR(COLOR_BLACK, bgwidget), 77 .button.delimcolor = GET_COLOR(COLOR_BLACK, bgwidget), 78 .button.f_color = GET_COLOR(COLOR_BLACK, bgcurr) | A_UNDERLINE, 79 .button.color = GET_COLOR(COLOR_BLACK, bgwidget) | A_UNDERLINE, 80 .button.f_shortcutcolor = GET_COLOR(COLOR_RED, bgcurr) | A_UNDERLINE, 81 .button.shortcutcolor = GET_COLOR(COLOR_RED, bgwidget) | A_UNDERLINE 82 }; 83 84 static struct bsddialog_theme blackwhite = { 85 #define fg COLOR_WHITE 86 #define bk COLOR_BLACK 87 .screen.color = GET_COLOR(fg, bk), 88 89 .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK), 90 .shadow.h = 1, 91 .shadow.w = 2, 92 93 .dialog.delimtitle = true, 94 .dialog.titlecolor = GET_COLOR(fg, bk), 95 .dialog.lineraisecolor = GET_COLOR(fg, bk), 96 .dialog.linelowercolor = GET_COLOR(fg, bk), 97 .dialog.color = GET_COLOR(fg, bk), 98 .dialog.bottomtitlecolor = GET_COLOR(fg, bk), 99 .dialog.arrowcolor = GET_COLOR(fg, bk), 100 101 .menu.f_selectorcolor = GET_COLOR(fg, bk) | A_REVERSE, 102 .menu.selectorcolor = GET_COLOR(fg, bk), 103 .menu.f_desccolor = GET_COLOR(fg, bk) | A_REVERSE, 104 .menu.desccolor = GET_COLOR(fg, bk), 105 .menu.f_namecolor = GET_COLOR(fg, bk) | A_REVERSE, 106 .menu.namecolor = GET_COLOR(fg, bk), 107 .menu.namesepcolor = GET_COLOR(fg, bk), 108 .menu.descsepcolor = GET_COLOR(fg, bk), 109 .menu.f_shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE, 110 .menu.shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE, 111 112 .form.f_fieldcolor = GET_COLOR(fg, bk) | A_REVERSE, 113 .form.fieldcolor = GET_COLOR(fg, bk), 114 .form.readonlycolor = GET_COLOR(fg, bk), 115 116 .bar.f_color = GET_COLOR(fg, bk) | A_REVERSE, 117 .bar.color = GET_COLOR(fg, bk), 118 119 .button.hmargin = 3, 120 .button.leftdelim = '[', 121 .button.rightdelim = ']', 122 .button.f_delimcolor = GET_COLOR(fg, bk), 123 .button.delimcolor = GET_COLOR(fg, bk), 124 .button.f_color = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE, 125 .button.color = GET_COLOR(fg, bk) | A_UNDERLINE, 126 .button.f_shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE, 127 .button.shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE 128 }; 129 130 static struct bsddialog_theme dialogtheme = { 131 .screen.color = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD, 132 133 .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK), 134 .shadow.h = 1, 135 .shadow.w = 2, 136 137 .dialog.delimtitle = false, 138 .dialog.titlecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD, 139 .dialog.lineraisecolor = GET_COLOR(COLOR_WHITE, COLOR_WHITE) | A_BOLD, 140 .dialog.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD, 141 .dialog.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE), 142 .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD, 143 .dialog.arrowcolor = GET_COLOR(COLOR_GREEN, COLOR_WHITE), 144 145 .menu.f_selectorcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), 146 .menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget), 147 .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), 148 .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE), 149 .menu.f_namecolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), 150 .menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE), 151 .menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), 152 .menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), 153 .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE), 154 .menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), 155 156 .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, 157 .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD, 158 .form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE)| A_BOLD, 159 160 .bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, 161 .bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD, 162 163 .button.hmargin = 3, 164 .button.leftdelim = '<', 165 .button.rightdelim = '>', 166 .button.f_delimcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, 167 .button.delimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE), 168 .button.f_color = GET_COLOR(COLOR_YELLOW, COLOR_BLUE) | A_BOLD, 169 .button.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE), 170 .button.f_shortcutcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, 171 .button.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE) | A_BOLD 172 }; 173 174 static void 175 set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src) 176 { 177 dst->screen.color = src->screen.color; 178 179 dst->shadow.color = src->shadow.color; 180 dst->shadow.h = src->shadow.h; 181 dst->shadow.w = src->shadow.w; 182 183 dst->dialog.delimtitle = src->dialog.delimtitle; 184 dst->dialog.titlecolor = src->dialog.titlecolor; 185 dst->dialog.lineraisecolor = src->dialog.lineraisecolor; 186 dst->dialog.linelowercolor = src->dialog.linelowercolor; 187 dst->dialog.color = src->dialog.color; 188 dst->dialog.bottomtitlecolor = src->dialog.bottomtitlecolor; 189 dst->dialog.arrowcolor = src->dialog.arrowcolor; 190 191 dst->menu.f_selectorcolor = src->menu.f_selectorcolor; 192 dst->menu.selectorcolor = src->menu.selectorcolor; 193 dst->menu.f_desccolor = src->menu.f_desccolor; 194 dst->menu.desccolor = src->menu.desccolor; 195 dst->menu.f_namecolor = src->menu.f_namecolor; 196 dst->menu.namecolor = src->menu.namecolor; 197 dst->menu.namesepcolor = src->menu.namesepcolor; 198 dst->menu.descsepcolor = src->menu.descsepcolor; 199 dst->menu.f_shortcutcolor = src->menu.f_shortcutcolor; 200 dst->menu.shortcutcolor = src->menu.shortcutcolor; 201 202 dst->form.f_fieldcolor = src->form.f_fieldcolor; 203 dst->form.fieldcolor = src->form.fieldcolor; 204 dst->form.readonlycolor = src->form.readonlycolor; 205 206 dst->bar.f_color = src->bar.f_color; 207 dst->bar.color = src->bar.color; 208 209 dst->button.hmargin = src->button.hmargin; 210 dst->button.leftdelim = src->button.leftdelim; 211 dst->button.rightdelim = src->button.rightdelim; 212 dst->button.f_delimcolor = src->button.f_delimcolor; 213 dst->button.delimcolor = src->button.delimcolor; 214 dst->button.f_color = src->button.f_color; 215 dst->button.color = src->button.color; 216 dst->button.f_shortcutcolor = src->button.f_shortcutcolor; 217 dst->button.shortcutcolor = src->button.shortcutcolor; 218 219 bkgd(dst->screen.color); 220 refresh(); 221 } 222 223 /* API */ 224 int bsddialog_get_theme(struct bsddialog_theme *theme) 225 { 226 if (theme == NULL) 227 RETURN_ERROR("theme is NULL"); 228 if (sizeof(*theme) != sizeof(struct bsddialog_theme)) 229 RETURN_ERROR("Bad suze struct bsddialog_theme"); 230 231 set_theme(theme, &t); 232 233 return (0); 234 } 235 236 int bsddialog_set_theme(struct bsddialog_theme *theme) 237 { 238 if (theme == NULL) 239 RETURN_ERROR("theme is NULL"); 240 if (sizeof(*theme) != sizeof(struct bsddialog_theme)) 241 RETURN_ERROR("Bad size struct bsddialog_theme"); 242 243 set_theme(&t, theme); 244 245 return (0); 246 } 247 248 int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme) 249 { 250 251 if (newtheme == BSDDIALOG_THEME_FLAT) { 252 bsddialog_set_theme(&dialogtheme); 253 t.dialog.lineraisecolor = t.dialog.linelowercolor; 254 t.dialog.delimtitle = true; 255 t.button.leftdelim = '['; 256 t.button.rightdelim = ']'; 257 } 258 else if (newtheme == BSDDIALOG_THEME_BSDDIALOG) 259 bsddialog_set_theme(&bsddialogtheme); 260 else if (newtheme == BSDDIALOG_THEME_BLACKWHITE) 261 bsddialog_set_theme(&blackwhite); 262 else if (newtheme == BSDDIALOG_THEME_DIALOG) 263 bsddialog_set_theme(&dialogtheme); 264 else 265 RETURN_ERROR("Unknow default theme"); 266 267 return (0); 268 } 269 270 int 271 bsddialog_color(enum bsddialog_color foreground, 272 enum bsddialog_color background, unsigned int flags) 273 { 274 unsigned int cursesflags = 0; 275 276 if (flags & BSDDIALOG_BOLD) 277 cursesflags |= A_BOLD; 278 if (flags & BSDDIALOG_REVERSE) 279 cursesflags |= A_REVERSE; 280 if (flags & BSDDIALOG_UNDERLINE) 281 cursesflags |= A_UNDERLINE; 282 283 return (GET_COLOR(foreground, background) | cursesflags); 284 } 285