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