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