shorten options.c a little by moving some color stuff out of it
creates new coloratt.c file Also, this attempts to fulfill a wish-list item by paxed, to allow naming colors in symbols file by name as an alternative to using r-g-b values. The basic color names as well as html color names are supported.
This commit is contained in:
@@ -54,4 +54,21 @@
|
|||||||
#define DRAGON_SILVER CLR_BRIGHT_CYAN
|
#define DRAGON_SILVER CLR_BRIGHT_CYAN
|
||||||
#define HI_ZAP CLR_BRIGHT_BLUE
|
#define HI_ZAP CLR_BRIGHT_BLUE
|
||||||
|
|
||||||
|
enum nhcolortype { no_color, nh_color, rgb_color };
|
||||||
|
|
||||||
|
struct nethack_color {
|
||||||
|
enum nhcolortype colortyp;
|
||||||
|
int tableindex;
|
||||||
|
int rgbindex;
|
||||||
|
const char *name;
|
||||||
|
const char *hexval;
|
||||||
|
long r, g, b;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct color_and_attr {
|
||||||
|
int color, attr;
|
||||||
|
} color_attr;
|
||||||
|
|
||||||
#endif /* COLOR_H */
|
#endif /* COLOR_H */
|
||||||
|
|
||||||
|
/*color.h*/
|
||||||
|
|||||||
@@ -281,6 +281,26 @@ extern void all_options_statushilites(strbuf_t *);
|
|||||||
extern boolean status_hilite_menu(void);
|
extern boolean status_hilite_menu(void);
|
||||||
#endif /* STATUS_HILITES */
|
#endif /* STATUS_HILITES */
|
||||||
|
|
||||||
|
/* ### coloratt.c ### */
|
||||||
|
|
||||||
|
extern char *color_attr_to_str(color_attr *);
|
||||||
|
extern boolean color_attr_parse_str(color_attr *, char *);
|
||||||
|
extern int32 colortable_to_int32(struct nethack_color *);
|
||||||
|
extern int query_color(const char *, int) NO_NNARGS;
|
||||||
|
extern int query_attr(const char *, int) NO_NNARGS;
|
||||||
|
extern boolean query_color_attr(color_attr *, const char *) NONNULLARG1;
|
||||||
|
extern const char *attr2attrname(int);
|
||||||
|
extern void basic_menu_colors(boolean);
|
||||||
|
extern boolean add_menu_coloring_parsed(const char *, int, int);
|
||||||
|
extern const char *clr2colorname(int);
|
||||||
|
extern int match_str2clr(char *) NONNULLARG1;
|
||||||
|
extern int match_str2attr(const char *, boolean) NONNULLARG1;
|
||||||
|
extern boolean add_menu_coloring(char *) NONNULLARG1;
|
||||||
|
extern void free_one_menu_coloring(int);
|
||||||
|
extern void free_menu_coloring(void);
|
||||||
|
extern int count_menucolors(void);
|
||||||
|
extern int32 check_enhanced_colors(const char *) NONNULLARG1;
|
||||||
|
|
||||||
/* ### cmd.c ### */
|
/* ### cmd.c ### */
|
||||||
|
|
||||||
extern void set_move_cmd(int, int);
|
extern void set_move_cmd(int, int);
|
||||||
@@ -2238,14 +2258,6 @@ extern int add_autopickup_exception(const char *) NONNULLARG1;
|
|||||||
extern void free_autopickup_exceptions(void);
|
extern void free_autopickup_exceptions(void);
|
||||||
extern void set_playmode(void);
|
extern void set_playmode(void);
|
||||||
extern int sym_val(const char *) NONNULLARG1;
|
extern int sym_val(const char *) NONNULLARG1;
|
||||||
extern int query_color(const char *, int) NO_NNARGS;
|
|
||||||
extern int query_attr(const char *, int) NO_NNARGS;
|
|
||||||
extern boolean query_color_attr(color_attr *, const char *) NONNULLARG1;
|
|
||||||
extern const char *clr2colorname(int);
|
|
||||||
extern int match_str2clr(char *) NONNULLARG1;
|
|
||||||
extern int match_str2attr(const char *, boolean) NONNULLARG1;
|
|
||||||
extern boolean add_menu_coloring(char *) NONNULLARG1;
|
|
||||||
extern void free_menu_coloring(void);
|
|
||||||
extern boolean msgtype_parse_add(char *) NONNULLARG1;
|
extern boolean msgtype_parse_add(char *) NONNULLARG1;
|
||||||
extern int msgtype_type(const char *, boolean) NONNULLARG1;
|
extern int msgtype_type(const char *, boolean) NONNULLARG1;
|
||||||
extern void hide_unhide_msgtypes(boolean, int);
|
extern void hide_unhide_msgtypes(boolean, int);
|
||||||
|
|||||||
@@ -445,9 +445,7 @@ extern struct nomakedefs_s nomakedefs;
|
|||||||
#define MAX_MSG_HISTORY 128 /* max # of lines in msg_history */
|
#define MAX_MSG_HISTORY 128 /* max # of lines in msg_history */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct color_and_attr {
|
#include "color.h"
|
||||||
int color, attr;
|
|
||||||
} color_attr;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Version 3.7.x has aspirations of portable file formats. We
|
* Version 3.7.x has aspirations of portable file formats. We
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "lint.h"
|
#include "lint.h"
|
||||||
|
|
||||||
#include "color.h"
|
|
||||||
#include "align.h"
|
#include "align.h"
|
||||||
#include "dungeon.h"
|
#include "dungeon.h"
|
||||||
#include "objclass.h"
|
#include "objclass.h"
|
||||||
|
|||||||
709
src/coloratt.c
Normal file
709
src/coloratt.c
Normal file
@@ -0,0 +1,709 @@
|
|||||||
|
/* NetHack 3.7 color.c $NHDT-Date: 1682205020 2023/04/22 23:10:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.18 $ */
|
||||||
|
/* Copyright (c) Pasi Kallinen, 2024 */
|
||||||
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
|
#include "hack.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
struct color_names {
|
||||||
|
const char *name;
|
||||||
|
int color;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct color_names colornames[] = {
|
||||||
|
{ "black", CLR_BLACK },
|
||||||
|
{ "red", CLR_RED },
|
||||||
|
{ "green", CLR_GREEN },
|
||||||
|
{ "brown", CLR_BROWN },
|
||||||
|
{ "blue", CLR_BLUE },
|
||||||
|
{ "magenta", CLR_MAGENTA },
|
||||||
|
{ "cyan", CLR_CYAN },
|
||||||
|
{ "gray", CLR_GRAY },
|
||||||
|
{ "orange", CLR_ORANGE },
|
||||||
|
{ "light green", CLR_BRIGHT_GREEN },
|
||||||
|
{ "yellow", CLR_YELLOW },
|
||||||
|
{ "light blue", CLR_BRIGHT_BLUE },
|
||||||
|
{ "light magenta", CLR_BRIGHT_MAGENTA },
|
||||||
|
{ "light cyan", CLR_BRIGHT_CYAN },
|
||||||
|
{ "white", CLR_WHITE },
|
||||||
|
{ "no color", NO_COLOR },
|
||||||
|
{ (const char *) 0, CLR_BLACK }, /* everything after this is an alias */
|
||||||
|
{ "transparent", NO_COLOR },
|
||||||
|
{ "purple", CLR_MAGENTA },
|
||||||
|
{ "light purple", CLR_BRIGHT_MAGENTA },
|
||||||
|
{ "bright purple", CLR_BRIGHT_MAGENTA },
|
||||||
|
{ "grey", CLR_GRAY },
|
||||||
|
{ "bright red", CLR_ORANGE },
|
||||||
|
{ "bright green", CLR_BRIGHT_GREEN },
|
||||||
|
{ "bright blue", CLR_BRIGHT_BLUE },
|
||||||
|
{ "bright magenta", CLR_BRIGHT_MAGENTA },
|
||||||
|
{ "bright cyan", CLR_BRIGHT_CYAN }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct attr_names {
|
||||||
|
const char *name;
|
||||||
|
int attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attr_names attrnames[] = {
|
||||||
|
{ "none", ATR_NONE },
|
||||||
|
{ "bold", ATR_BOLD },
|
||||||
|
{ "dim", ATR_DIM },
|
||||||
|
{ "italic", ATR_ITALIC },
|
||||||
|
{ "underline", ATR_ULINE },
|
||||||
|
{ "blink", ATR_BLINK },
|
||||||
|
{ "inverse", ATR_INVERSE },
|
||||||
|
{ (const char *) 0, ATR_NONE }, /* everything after this is an alias */
|
||||||
|
{ "normal", ATR_NONE },
|
||||||
|
{ "uline", ATR_ULINE },
|
||||||
|
{ "reverse", ATR_INVERSE },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* { colortyp, tableindex, rgbindx, name, hexval, r, g, b }, */
|
||||||
|
|
||||||
|
static struct nethack_color colortable[] = {
|
||||||
|
{ nh_color, 0, 0, "black", "#000000", 0, 0, 0 },
|
||||||
|
{ nh_color, 1, 0, "red", "#FF0000", 255, 0, 0 },
|
||||||
|
{ nh_color, 2, 0, "green", "#228B22", 34, 139, 34 },
|
||||||
|
{ nh_color, 3, 0, "brown", "#A52A2A", 165, 42, 42 },
|
||||||
|
{ nh_color, 4, 0, "blue", "#0000FF", 0, 0, 255 },
|
||||||
|
{ nh_color, 5, 0, "magenta", "#FF00FF", 255, 0, 255 },
|
||||||
|
{ nh_color, 6, 0, "cyan", "#00FFFF", 0, 255, 255 },
|
||||||
|
{ nh_color, 7, 0, "gray", "#808080", 128, 128, 128 },
|
||||||
|
{ no_color, 8, 0, "nocolor", "#000000", 0, 0, 0 },
|
||||||
|
{ nh_color, 9, 0, "orange", "#FFA500", 255, 165, 0 },
|
||||||
|
{ nh_color, 10, 0, "bright-green", "#008000", 0, 128, 0 },
|
||||||
|
{ nh_color, 11, 0, "yellow", "#FFFF00", 255, 255, 0 },
|
||||||
|
{ nh_color, 12, 0, "bright-blue", "#ADD8E6", 173, 216, 230 },
|
||||||
|
{ nh_color, 13, 0, "bright-magenta", "#9370DB", 147, 112, 219 },
|
||||||
|
{ nh_color, 14, 0, "light-cyan", "#E0FFFF", 224, 255, 255 },
|
||||||
|
{ nh_color, 15, 0, "white", "#FFFFFF", 255, 255, 255 },
|
||||||
|
{ rgb_color, 16, 0, "maroon", "#800000", 128, 0, 0 },
|
||||||
|
{ rgb_color, 17, 1, "dark-red", "#8B0000", 139, 0, 0 },
|
||||||
|
{ rgb_color, 18, 2, "brown", "#A52A2A", 165, 42, 42 },
|
||||||
|
{ rgb_color, 19, 3, "firebrick", "#B22222", 178, 34, 34 },
|
||||||
|
{ rgb_color, 20, 4, "crimson", "#DC143C", 220, 20, 60 },
|
||||||
|
{ rgb_color, 21, 5, "red", "#FF0000", 255, 0, 0 },
|
||||||
|
{ rgb_color, 22, 6, "tomato", "#FF6347", 255, 99, 71 },
|
||||||
|
{ rgb_color, 23, 7, "coral", "#FF7F50", 255, 127, 80 },
|
||||||
|
{ rgb_color, 24, 8, "indian-red", "#CD5C5C", 205, 92, 92 },
|
||||||
|
{ rgb_color, 25, 9, "light-coral", "#F08080", 240, 128, 128 },
|
||||||
|
{ rgb_color, 26, 10, "dark-salmon", "#E9967A", 233, 150, 122 },
|
||||||
|
{ rgb_color, 27, 11, "salmon", "#FA8072", 250, 128, 114 },
|
||||||
|
{ rgb_color, 28, 12, "light-salmon", "#FFA07A", 255, 160, 122 },
|
||||||
|
{ rgb_color, 29, 13, "orange-red", "#FF4500", 255, 69, 0 },
|
||||||
|
{ rgb_color, 30, 14, "dark-orange", "#FF8C00", 255, 140, 0 },
|
||||||
|
{ rgb_color, 31, 15, "orange", "#FFA500", 255, 165, 0 },
|
||||||
|
{ rgb_color, 32, 16, "gold", "#FFD700", 255, 215, 0 },
|
||||||
|
{ rgb_color, 33, 17, "dark-golden-rod", "#B8860B", 184, 134, 11 },
|
||||||
|
{ rgb_color, 34, 18, "golden-rod", "#DAA520", 218, 165, 32 },
|
||||||
|
{ rgb_color, 35, 19, "pale-golden-rod", "#EEE8AA", 238, 232, 170 },
|
||||||
|
{ rgb_color, 36, 20, "dark-khaki", "#BDB76B", 189, 183, 107 },
|
||||||
|
{ rgb_color, 37, 21, "khaki", "#F0E68C", 240, 230, 140 },
|
||||||
|
{ rgb_color, 38, 22, "olive", "#808000", 128, 128, 0 },
|
||||||
|
{ rgb_color, 39, 23, "yellow", "#FFFF00", 255, 255, 0 },
|
||||||
|
{ rgb_color, 40, 24, "yellow-green", "#9ACD32", 154, 205, 50 },
|
||||||
|
{ rgb_color, 41, 25, "dark-olive-green", "#556B2F", 85, 107, 47 },
|
||||||
|
{ rgb_color, 42, 26, "olive-drab", "#6B8E23", 107, 142, 35 },
|
||||||
|
{ rgb_color, 43, 27, "lawn-green", "#7CFC00", 124, 252, 0 },
|
||||||
|
{ rgb_color, 44, 28, "chart-reuse", "#7FFF00", 127, 255, 0 },
|
||||||
|
{ rgb_color, 45, 29, "green-yellow", "#ADFF2F", 173, 255, 47 },
|
||||||
|
{ rgb_color, 46, 30, "dark-green", "#006400", 0, 100, 0 },
|
||||||
|
{ rgb_color, 47, 31, "green", "#008000", 0, 128, 0 },
|
||||||
|
{ rgb_color, 48, 32, "forest-green", "#228B22", 34, 139, 34 },
|
||||||
|
{ rgb_color, 49, 33, "lime", "#00FF00", 0, 255, 0 },
|
||||||
|
{ rgb_color, 50, 34, "lime-green", "#32CD32", 50, 205, 50 },
|
||||||
|
{ rgb_color, 51, 35, "light-green", "#90EE90", 144, 238, 144 },
|
||||||
|
{ rgb_color, 52, 36, "pale-green", "#98FB98", 152, 251, 152 },
|
||||||
|
{ rgb_color, 53, 37, "dark-sea-green", "#8FBC8F", 143, 188, 143 },
|
||||||
|
{ rgb_color, 54, 38, "medium-spring-green", "#00FA9A", 0, 250, 154 },
|
||||||
|
{ rgb_color, 55, 39, "spring-green", "#00FF7F", 0, 255, 127 },
|
||||||
|
{ rgb_color, 56, 40, "sea-green", "#2E8B57", 46, 139, 87 },
|
||||||
|
{ rgb_color, 57, 41, "medium-aqua-marine", "#66CDAA", 102, 205, 170 },
|
||||||
|
{ rgb_color, 58, 42, "medium-sea-green", "#3CB371", 60, 179, 113 },
|
||||||
|
{ rgb_color, 59, 43, "light-sea-green", "#20B2AA", 32, 178, 170 },
|
||||||
|
{ rgb_color, 60, 44, "dark-slate-gray", "#2F4F4F", 47, 79, 79 },
|
||||||
|
{ rgb_color, 61, 45, "teal", "#008080", 0, 128, 128 },
|
||||||
|
{ rgb_color, 62, 46, "dark-cyan", "#008B8B", 0, 139, 139 },
|
||||||
|
{ rgb_color, 63, 47, "aqua", "#00FFFF", 0, 255, 255 },
|
||||||
|
{ rgb_color, 64, 48, "cyan", "#00FFFF", 0, 255, 255 },
|
||||||
|
{ rgb_color, 65, 49, "light-cyan", "#E0FFFF", 224, 255, 255 },
|
||||||
|
{ rgb_color, 66, 50, "dark-turquoise", "#00CED1", 0, 206, 209 },
|
||||||
|
{ rgb_color, 67, 51, "turquoise", "#40E0D0", 64, 224, 208 },
|
||||||
|
{ rgb_color, 68, 52, "medium-turquoise", "#48D1CC", 72, 209, 204 },
|
||||||
|
{ rgb_color, 69, 53, "pale-turquoise", "#AFEEEE", 175, 238, 238 },
|
||||||
|
{ rgb_color, 70, 54, "aqua-marine", "#7FFFD4", 127, 255, 212 },
|
||||||
|
{ rgb_color, 71, 55, "powder-blue", "#B0E0E6", 176, 224, 230 },
|
||||||
|
{ rgb_color, 72, 56, "cadet-blue", "#5F9EA0", 95, 158, 160 },
|
||||||
|
{ rgb_color, 73, 57, "steel-blue", "#4682B4", 70, 130, 180 },
|
||||||
|
{ rgb_color, 74, 58, "corn-flower-blue", "#6495ED", 100, 149, 237 },
|
||||||
|
{ rgb_color, 75, 59, "deep-sky-blue", "#00BFFF", 0, 191, 255 },
|
||||||
|
{ rgb_color, 76, 60, "dodger-blue", "#1E90FF", 30, 144, 255 },
|
||||||
|
{ rgb_color, 77, 61, "light-blue", "#ADD8E6", 173, 216, 230 },
|
||||||
|
{ rgb_color, 78, 62, "sky-blue", "#87CEEB", 135, 206, 235 },
|
||||||
|
{ rgb_color, 79, 63, "light-sky-blue", "#87CEFA", 135, 206, 250 },
|
||||||
|
{ rgb_color, 80, 64, "midnight-blue", "#191970", 25, 25, 112 },
|
||||||
|
{ rgb_color, 81, 65, "navy", "#000080", 0, 0, 128 },
|
||||||
|
{ rgb_color, 82, 66, "dark-blue", "#00008B", 0, 0, 139 },
|
||||||
|
{ rgb_color, 83, 67, "medium-blue", "#0000CD", 0, 0, 205 },
|
||||||
|
{ rgb_color, 84, 68, "blue", "#0000FF", 0, 0, 255 },
|
||||||
|
{ rgb_color, 85, 69, "royal-blue", "#4169E1", 65, 105, 225 },
|
||||||
|
{ rgb_color, 86, 70, "blue-violet", "#8A2BE2", 138, 43, 226 },
|
||||||
|
{ rgb_color, 87, 71, "indigo", "#4B0082", 75, 0, 130 },
|
||||||
|
{ rgb_color, 88, 72, "dark-slate-blue", "#483D8B", 72, 61, 139 },
|
||||||
|
{ rgb_color, 89, 73, "slate-blue", "#6A5ACD", 106, 90, 205 },
|
||||||
|
{ rgb_color, 90, 74, "medium-slate-blue", "#7B68EE", 123, 104, 238 },
|
||||||
|
{ rgb_color, 91, 75, "medium-purple", "#9370DB", 147, 112, 219 },
|
||||||
|
{ rgb_color, 92, 76, "dark-magenta", "#8B008B", 139, 0, 139 },
|
||||||
|
{ rgb_color, 93, 77, "dark-violet", "#9400D3", 148, 0, 211 },
|
||||||
|
{ rgb_color, 94, 78, "dark-orchid", "#9932CC", 153, 50, 204 },
|
||||||
|
{ rgb_color, 95, 79, "medium-orchid", "#BA55D3", 186, 85, 211 },
|
||||||
|
{ rgb_color, 96, 80, "purple", "#800080", 128, 0, 128 },
|
||||||
|
{ rgb_color, 97, 81, "thistle", "#D8BFD8", 216, 191, 216 },
|
||||||
|
{ rgb_color, 98, 82, "plum", "#DDA0DD", 221, 160, 221 },
|
||||||
|
{ rgb_color, 99, 83, "violet", "#EE82EE", 238, 130, 238 },
|
||||||
|
{ rgb_color, 100, 84, "magenta", "#FF00FF", 255, 0, 255 },
|
||||||
|
{ rgb_color, 101, 85, "orchid", "#DA70D6", 218, 112, 214 },
|
||||||
|
{ rgb_color, 102, 86, "medium-violet-red", "#C71585", 199, 21, 133 },
|
||||||
|
{ rgb_color, 103, 87, "pale-violet-red", "#DB7093", 219, 112, 147 },
|
||||||
|
{ rgb_color, 104, 88, "deep-pink", "#FF1493", 255, 20, 147 },
|
||||||
|
{ rgb_color, 105, 89, "hot-pink", "#FF69B4", 255, 105, 180 },
|
||||||
|
{ rgb_color, 106, 90, "light-pink", "#FFB6C1", 255, 182, 193 },
|
||||||
|
{ rgb_color, 107, 91, "pink", "#FFC0CB", 255, 192, 203 },
|
||||||
|
{ rgb_color, 108, 92, "antique-white", "#FAEBD7", 250, 235, 215 },
|
||||||
|
{ rgb_color, 109, 93, "beige", "#F5F5DC", 245, 245, 220 },
|
||||||
|
{ rgb_color, 110, 94, "bisque", "#FFE4C4", 255, 228, 196 },
|
||||||
|
{ rgb_color, 111, 95, "blanched-almond", "#FFEBCD", 255, 235, 205 },
|
||||||
|
{ rgb_color, 112, 96, "wheat", "#F5DEB3", 245, 222, 179 },
|
||||||
|
{ rgb_color, 113, 97, "corn-silk", "#FFF8DC", 255, 248, 220 },
|
||||||
|
{ rgb_color, 114, 98, "lemon-chiffon", "#FFFACD", 255, 250, 205 },
|
||||||
|
{ rgb_color, 115, 99, "light-golden-rod-yellow", "#FAFAD2", 250, 250, 210 },
|
||||||
|
{ rgb_color, 116, 100, "light-yellow", "#FFFFE0", 255, 255, 224 },
|
||||||
|
{ rgb_color, 117, 101, "saddle-brown", "#8B4513", 139, 69, 19 },
|
||||||
|
{ rgb_color, 118, 102, "sienna", "#A0522D", 160, 82, 45 },
|
||||||
|
{ rgb_color, 119, 103, "chocolate", "#D2691E", 210, 105, 30 },
|
||||||
|
{ rgb_color, 120, 104, "peru", "#CD853F", 205, 133, 63 },
|
||||||
|
{ rgb_color, 121, 105, "sandy-brown", "#F4A460", 244, 164, 96 },
|
||||||
|
{ rgb_color, 122, 106, "burly-wood", "#DEB887", 222, 184, 135 },
|
||||||
|
{ rgb_color, 123, 107, "tan", "#D2B48C", 210, 180, 140 },
|
||||||
|
{ rgb_color, 124, 108, "rosy-brown", "#BC8F8F", 188, 143, 143 },
|
||||||
|
{ rgb_color, 125, 109, "moccasin", "#FFE4B5", 255, 228, 181 },
|
||||||
|
{ rgb_color, 126, 110, "navajo-white", "#FFDEAD", 255, 222, 173 },
|
||||||
|
{ rgb_color, 127, 111, "peach-puff", "#FFDAB9", 255, 218, 185 },
|
||||||
|
{ rgb_color, 128, 112, "misty-rose", "#FFE4E1", 255, 228, 225 },
|
||||||
|
{ rgb_color, 129, 113, "lavender-blush", "#FFF0F5", 255, 240, 245 },
|
||||||
|
{ rgb_color, 130, 114, "linen", "#FAF0E6", 250, 240, 230 },
|
||||||
|
{ rgb_color, 131, 115, "old-lace", "#FDF5E6", 253, 245, 230 },
|
||||||
|
{ rgb_color, 132, 116, "papaya-whip", "#FFEFD5", 255, 239, 213 },
|
||||||
|
{ rgb_color, 133, 117, "sea-shell", "#FFF5EE", 255, 245, 238 },
|
||||||
|
{ rgb_color, 134, 118, "mint-cream", "#F5FFFA", 245, 255, 250 },
|
||||||
|
{ rgb_color, 135, 119, "slate-gray", "#708090", 112, 128, 144 },
|
||||||
|
{ rgb_color, 136, 120, "light-slate-gray", "#778899", 119, 136, 153 },
|
||||||
|
{ rgb_color, 137, 121, "light-steel-blue", "#B0C4DE", 176, 196, 222 },
|
||||||
|
{ rgb_color, 138, 122, "lavender", "#E6E6FA", 230, 230, 250 },
|
||||||
|
{ rgb_color, 139, 123, "floral-white", "#FFFAF0", 255, 250, 240 },
|
||||||
|
{ rgb_color, 140, 124, "alice-blue", "#F0F8FF", 240, 248, 255 },
|
||||||
|
{ rgb_color, 141, 125, "ghost-white", "#F8F8FF", 248, 248, 255 },
|
||||||
|
{ rgb_color, 142, 126, "honeydew", "#F0FFF0", 240, 255, 240 },
|
||||||
|
{ rgb_color, 143, 127, "ivory", "#FFFFF0", 255, 255, 240 },
|
||||||
|
{ rgb_color, 144, 128, "azure", "#F0FFFF", 240, 255, 255 },
|
||||||
|
{ rgb_color, 145, 129, "snow", "#FFFAFA", 255, 250, 250 },
|
||||||
|
{ rgb_color, 146, 130, "black", "#000000", 0, 0, 0 },
|
||||||
|
{ rgb_color, 147, 131, "dim-gray", "#696969", 105, 105, 105 },
|
||||||
|
{ rgb_color, 148, 132, "gray", "#808080", 128, 128, 128 },
|
||||||
|
{ rgb_color, 149, 133, "dark-gray", "#A9A9A9", 169, 169, 169 },
|
||||||
|
{ rgb_color, 150, 134, "silver", "#C0C0C0", 192, 192, 192 },
|
||||||
|
{ rgb_color, 151, 135, "light-gray", "#D3D3D3", 211, 211, 211 },
|
||||||
|
{ rgb_color, 152, 136, "gainsboro", "#DCDCDC", 220, 220, 220 },
|
||||||
|
{ rgb_color, 153, 137, "white-smoke", "#F5F5F5", 245, 245, 245 },
|
||||||
|
{ rgb_color, 154, 138, "white", "#FFFFFF", 255, 255, 255 },
|
||||||
|
};
|
||||||
|
|
||||||
|
int32
|
||||||
|
colortable_to_int32(struct nethack_color *cte)
|
||||||
|
{
|
||||||
|
int32 clr = (cte->r << 16) | (cte->g << 8) | cte->b;
|
||||||
|
return clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
color_attr_to_str(color_attr *ca)
|
||||||
|
{
|
||||||
|
static char buf[BUFSZ];
|
||||||
|
|
||||||
|
Sprintf(buf, "%s&%s",
|
||||||
|
clr2colorname(ca->color),
|
||||||
|
attr2attrname(ca->attr));
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse string like "color&attr" into color_attr */
|
||||||
|
boolean
|
||||||
|
color_attr_parse_str(color_attr *ca, char *str)
|
||||||
|
{
|
||||||
|
char buf[BUFSZ];
|
||||||
|
char *amp = NULL;
|
||||||
|
int tmp, c = NO_COLOR, a = ATR_NONE;
|
||||||
|
|
||||||
|
(void) strncpy(buf, str, sizeof buf - 1);
|
||||||
|
buf[sizeof buf - 1] = '\0';
|
||||||
|
|
||||||
|
if ((amp = strchr(buf, '&')) != 0)
|
||||||
|
*amp = '\0';
|
||||||
|
|
||||||
|
if (amp) {
|
||||||
|
amp++;
|
||||||
|
c = match_str2clr(buf);
|
||||||
|
a = match_str2attr(amp, TRUE);
|
||||||
|
/* FIXME: match_str2clr & match_str2attr give config_error_add(),
|
||||||
|
so this is useless */
|
||||||
|
if (c >= CLR_MAX && a == -1) {
|
||||||
|
/* try other way around */
|
||||||
|
c = match_str2clr(amp);
|
||||||
|
a = match_str2attr(buf, TRUE);
|
||||||
|
}
|
||||||
|
if (c >= CLR_MAX || a == -1)
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
/* one param only */
|
||||||
|
tmp = match_str2attr(buf, FALSE);
|
||||||
|
if (tmp == -1) {
|
||||||
|
tmp = match_str2clr(buf);
|
||||||
|
if (tmp >= CLR_MAX)
|
||||||
|
return FALSE;
|
||||||
|
c = tmp;
|
||||||
|
} else {
|
||||||
|
a = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ca->attr = a;
|
||||||
|
ca->color = c;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean
|
||||||
|
query_color_attr(color_attr *ca, const char *prompt)
|
||||||
|
{
|
||||||
|
int c, a;
|
||||||
|
|
||||||
|
c = query_color(prompt, ca->color);
|
||||||
|
if (c == -1)
|
||||||
|
return FALSE;
|
||||||
|
a = query_attr(prompt, ca->attr);
|
||||||
|
if (a == -1)
|
||||||
|
return FALSE;
|
||||||
|
ca->color = c;
|
||||||
|
ca->attr = a;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
attr2attrname(int attr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SIZE(attrnames); i++)
|
||||||
|
if (attrnames[i].attr == attr)
|
||||||
|
return attrnames[i].name;
|
||||||
|
return (char *) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Color support functions and data for "color"
|
||||||
|
*
|
||||||
|
* Used by: optfn_()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char *
|
||||||
|
clr2colorname(int clr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SIZE(colornames); i++)
|
||||||
|
if (colornames[i].name && colornames[i].color == clr)
|
||||||
|
return colornames[i].name;
|
||||||
|
return (char *) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
match_str2clr(char *str)
|
||||||
|
{
|
||||||
|
int i, c = CLR_MAX;
|
||||||
|
|
||||||
|
/* allow "lightblue", "light blue", and "light-blue" to match "light blue"
|
||||||
|
(also junk like "_l i-gh_t---b l u e" but we won't worry about that);
|
||||||
|
also copes with trailing space; caller has removed any leading space */
|
||||||
|
for (i = 0; i < SIZE(colornames); i++)
|
||||||
|
if (colornames[i].name
|
||||||
|
&& fuzzymatch(str, colornames[i].name, " -_", TRUE)) {
|
||||||
|
c = colornames[i].color;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == SIZE(colornames) && digit(*str))
|
||||||
|
c = atoi(str);
|
||||||
|
|
||||||
|
if (c < 0 || c >= CLR_MAX) {
|
||||||
|
config_error_add("Unknown color '%.60s'", str);
|
||||||
|
c = CLR_MAX; /* "none of the above" */
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
match_str2attr(const char *str, boolean complain)
|
||||||
|
{
|
||||||
|
int i, a = -1;
|
||||||
|
|
||||||
|
for (i = 0; i < SIZE(attrnames); i++)
|
||||||
|
if (attrnames[i].name
|
||||||
|
&& fuzzymatch(str, attrnames[i].name, " -_", TRUE)) {
|
||||||
|
a = attrnames[i].attr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == -1 && complain)
|
||||||
|
config_error_add("Unknown text attribute '%.50s'", str);
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ask about highlighting attribute; for menu headers and menu
|
||||||
|
coloring patterns, only one attribute at a time is allowed;
|
||||||
|
for status highlighting, multiple attributes are allowed [overkill;
|
||||||
|
life would be much simpler if that were restricted to one also...] */
|
||||||
|
int
|
||||||
|
query_attr(const char *prompt, int dflt_attr)
|
||||||
|
{
|
||||||
|
winid tmpwin;
|
||||||
|
anything any;
|
||||||
|
int i, pick_cnt;
|
||||||
|
menu_item *picks = (menu_item *) 0;
|
||||||
|
boolean allow_many = (prompt && !strncmpi(prompt, "Choose", 6));
|
||||||
|
int clr = NO_COLOR;
|
||||||
|
|
||||||
|
tmpwin = create_nhwindow(NHW_MENU);
|
||||||
|
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
|
||||||
|
any = cg.zeroany;
|
||||||
|
for (i = 0; i < SIZE(attrnames); i++) {
|
||||||
|
if (!attrnames[i].name)
|
||||||
|
break;
|
||||||
|
any.a_int = i + 1;
|
||||||
|
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
|
||||||
|
attrnames[i].attr, clr, attrnames[i].name,
|
||||||
|
(attrnames[i].attr == dflt_attr) ? MENU_ITEMFLAGS_SELECTED
|
||||||
|
: MENU_ITEMFLAGS_NONE);
|
||||||
|
}
|
||||||
|
end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick an attribute");
|
||||||
|
pick_cnt = select_menu(tmpwin, allow_many ? PICK_ANY : PICK_ONE, &picks);
|
||||||
|
destroy_nhwindow(tmpwin);
|
||||||
|
if (pick_cnt > 0) {
|
||||||
|
int j, k = 0;
|
||||||
|
|
||||||
|
if (allow_many) {
|
||||||
|
/* PICK_ANY, with one preselected entry (ATR_NONE) which
|
||||||
|
should be excluded if any other choices were picked */
|
||||||
|
for (i = 0; i < pick_cnt; ++i) {
|
||||||
|
j = picks[i].item.a_int - 1;
|
||||||
|
if (attrnames[j].attr != ATR_NONE || pick_cnt == 1) {
|
||||||
|
switch (attrnames[j].attr) {
|
||||||
|
case ATR_NONE:
|
||||||
|
k = HL_NONE;
|
||||||
|
break;
|
||||||
|
case ATR_BOLD:
|
||||||
|
k |= HL_BOLD;
|
||||||
|
break;
|
||||||
|
case ATR_DIM:
|
||||||
|
k |= HL_DIM;
|
||||||
|
break;
|
||||||
|
case ATR_ITALIC:
|
||||||
|
k |= HL_ITALIC;
|
||||||
|
break;
|
||||||
|
case ATR_ULINE:
|
||||||
|
k |= HL_ULINE;
|
||||||
|
break;
|
||||||
|
case ATR_BLINK:
|
||||||
|
k |= HL_BLINK;
|
||||||
|
break;
|
||||||
|
case ATR_INVERSE:
|
||||||
|
k |= HL_INVERSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* PICK_ONE, but might get 0 or 2 due to preselected entry */
|
||||||
|
j = picks[0].item.a_int - 1;
|
||||||
|
/* pick_cnt==2: explicitly picked something other than the
|
||||||
|
preselected entry */
|
||||||
|
if (pick_cnt == 2 && attrnames[j].attr == dflt_attr)
|
||||||
|
j = picks[1].item.a_int - 1;
|
||||||
|
k = attrnames[j].attr;
|
||||||
|
}
|
||||||
|
free((genericptr_t) picks);
|
||||||
|
return k;
|
||||||
|
} else if (pick_cnt == 0 && !allow_many) {
|
||||||
|
/* PICK_ONE, preselected entry explicitly chosen */
|
||||||
|
return dflt_attr;
|
||||||
|
}
|
||||||
|
/* either ESC to explicitly cancel (pick_cnt==-1) or
|
||||||
|
PICK_ANY with preselected entry toggled off and nothing chosen */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
query_color(const char *prompt, int dflt_color)
|
||||||
|
{
|
||||||
|
winid tmpwin;
|
||||||
|
anything any;
|
||||||
|
int i, pick_cnt;
|
||||||
|
menu_item *picks = (menu_item *) 0;
|
||||||
|
|
||||||
|
/* replace user patterns with color name ones and force 'menucolors' On */
|
||||||
|
basic_menu_colors(TRUE);
|
||||||
|
|
||||||
|
tmpwin = create_nhwindow(NHW_MENU);
|
||||||
|
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
|
||||||
|
any = cg.zeroany;
|
||||||
|
for (i = 0; i < SIZE(colornames); i++) {
|
||||||
|
if (!colornames[i].name)
|
||||||
|
break;
|
||||||
|
any.a_int = i + 1;
|
||||||
|
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
|
||||||
|
ATR_NONE, NO_COLOR, colornames[i].name,
|
||||||
|
(colornames[i].color == dflt_color) ? MENU_ITEMFLAGS_SELECTED
|
||||||
|
: MENU_ITEMFLAGS_NONE);
|
||||||
|
}
|
||||||
|
end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick a color");
|
||||||
|
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
|
||||||
|
destroy_nhwindow(tmpwin);
|
||||||
|
|
||||||
|
/* remove temporary color name patterns and restore user-specified ones;
|
||||||
|
reset 'menucolors' option to its previous value */
|
||||||
|
basic_menu_colors(FALSE);
|
||||||
|
|
||||||
|
if (pick_cnt > 0) {
|
||||||
|
i = colornames[picks[0].item.a_int - 1].color;
|
||||||
|
/* pick_cnt==2: explicitly picked something other than the
|
||||||
|
preselected entry */
|
||||||
|
if (pick_cnt == 2 && i == NO_COLOR)
|
||||||
|
i = colornames[picks[1].item.a_int - 1].color;
|
||||||
|
free((genericptr_t) picks);
|
||||||
|
return i;
|
||||||
|
} else if (pick_cnt == 0) {
|
||||||
|
/* pick_cnt==0: explicitly picking preselected entry toggled it off */
|
||||||
|
return dflt_color;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DISABLE_WARNING_FORMAT_NONLITERAL
|
||||||
|
|
||||||
|
extern const char regex_id[]; /* from sys/share/<various>regex.{c,cpp} */
|
||||||
|
|
||||||
|
/* True: temporarily replace menu color entries with a fake set of menu
|
||||||
|
colors, { "light blue"=light_blue, "blue"=blue, "red"=red, &c }, that
|
||||||
|
illustrates most colors for use when the pick-a-color menu is rendered;
|
||||||
|
suppresses black and white because one of those will likely be invisible
|
||||||
|
due to matching the background; False: restore user-specified colorings */
|
||||||
|
void
|
||||||
|
basic_menu_colors(boolean load_colors)
|
||||||
|
{
|
||||||
|
if (load_colors) {
|
||||||
|
/* replace normal menu colors with a set specifically for colors */
|
||||||
|
gs.save_menucolors = iflags.use_menu_color;
|
||||||
|
gs.save_colorings = gm.menu_colorings;
|
||||||
|
|
||||||
|
iflags.use_menu_color = TRUE;
|
||||||
|
if (gc.color_colorings) {
|
||||||
|
/* use the alternate colorings which were set up previously */
|
||||||
|
gm.menu_colorings = gc.color_colorings;
|
||||||
|
} else {
|
||||||
|
/* create the alternate colorings once */
|
||||||
|
char cnm[QBUFSZ];
|
||||||
|
int i, c;
|
||||||
|
boolean pmatchregex = !strcmpi(regex_id, "pmatchregex");
|
||||||
|
const char *patternfmt = pmatchregex ? "*%s" : "%s";
|
||||||
|
|
||||||
|
/* menu_colorings pointer has been saved; clear it in order
|
||||||
|
to add the alternate entries as if from scratch */
|
||||||
|
gm.menu_colorings = (struct menucoloring *) 0;
|
||||||
|
|
||||||
|
/* this orders the patterns last-in/first-out; that means
|
||||||
|
that the "light <foo>" variations come before the basic
|
||||||
|
"<foo>" ones, which is exactly what we want */
|
||||||
|
for (i = 0; i < SIZE(colornames); ++i) {
|
||||||
|
if (!colornames[i].name) /* first alias entry has no name */
|
||||||
|
break;
|
||||||
|
c = colornames[i].color;
|
||||||
|
if (c == CLR_BLACK || c == CLR_WHITE || c == NO_COLOR)
|
||||||
|
continue; /* skip these */
|
||||||
|
Sprintf(cnm, patternfmt, colornames[i].name);
|
||||||
|
add_menu_coloring_parsed(cnm, c, ATR_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* right now, menu_colorings contains the alternate color list;
|
||||||
|
remember that list for future pick-a-color instances and
|
||||||
|
also keep it as is for this instance */
|
||||||
|
gc.color_colorings = gm.menu_colorings;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* restore normal user-specified menu colors */
|
||||||
|
iflags.use_menu_color = gs.save_menucolors;
|
||||||
|
gm.menu_colorings = gs.save_colorings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RESTORE_WARNING_FORMAT_NONLITERAL
|
||||||
|
|
||||||
|
boolean
|
||||||
|
add_menu_coloring_parsed(const char *str, int c, int a)
|
||||||
|
{
|
||||||
|
static const char re_error[] = "Menucolor regex error";
|
||||||
|
struct menucoloring *tmp;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return FALSE;
|
||||||
|
tmp = (struct menucoloring *) alloc(sizeof *tmp);
|
||||||
|
tmp->match = regex_init();
|
||||||
|
/* test_regex_pattern() has already validated this regexp but parsing
|
||||||
|
it again could conceivably run out of memory */
|
||||||
|
if (!regex_compile(str, tmp->match)) {
|
||||||
|
char errbuf[BUFSZ];
|
||||||
|
char *re_error_desc = regex_error_desc(tmp->match, errbuf);
|
||||||
|
|
||||||
|
/* free first in case reason for regcomp failure was out-of-memory */
|
||||||
|
regex_free(tmp->match);
|
||||||
|
free((genericptr_t) tmp);
|
||||||
|
config_error_add("%s: %s", re_error, re_error_desc);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
tmp->next = gm.menu_colorings;
|
||||||
|
tmp->origstr = dupstr(str);
|
||||||
|
tmp->color = c;
|
||||||
|
tmp->attr = a;
|
||||||
|
gm.menu_colorings = tmp;
|
||||||
|
iflags.use_menu_color = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse '"regex_string"=color&attr' and add it to menucoloring */
|
||||||
|
boolean
|
||||||
|
add_menu_coloring(char *tmpstr) /* never Null but could be empty */
|
||||||
|
{
|
||||||
|
int c = NO_COLOR, a = ATR_NONE;
|
||||||
|
char *tmps, *cs, *amp;
|
||||||
|
char str[BUFSZ];
|
||||||
|
|
||||||
|
(void) strncpy(str, tmpstr, sizeof str - 1);
|
||||||
|
str[sizeof str - 1] = '\0';
|
||||||
|
|
||||||
|
if ((cs = strchr(str, '=')) == 0) {
|
||||||
|
config_error_add("Malformed MENUCOLOR");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmps = cs + 1; /* advance past '=' */
|
||||||
|
mungspaces(tmps);
|
||||||
|
if ((amp = strchr(tmps, '&')) != 0)
|
||||||
|
*amp = '\0';
|
||||||
|
|
||||||
|
c = match_str2clr(tmps);
|
||||||
|
if (c >= CLR_MAX)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (amp) {
|
||||||
|
tmps = amp + 1; /* advance past '&' */
|
||||||
|
a = match_str2attr(tmps, TRUE);
|
||||||
|
if (a == -1)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the regexp portion here has not been condensed by mungspaces() */
|
||||||
|
*cs = '\0';
|
||||||
|
tmps = str;
|
||||||
|
if (*tmps == '"' || *tmps == '\'') {
|
||||||
|
cs--;
|
||||||
|
while (isspace((uchar) *cs))
|
||||||
|
cs--;
|
||||||
|
if (*cs == *tmps) {
|
||||||
|
*cs = '\0';
|
||||||
|
tmps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return add_menu_coloring_parsed(tmps, c, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release all menu color patterns */
|
||||||
|
void
|
||||||
|
free_menu_coloring(void)
|
||||||
|
{
|
||||||
|
/* either menu_colorings or color_colorings or both might need to
|
||||||
|
be freed or already be Null; do-loop will iterate at most twice */
|
||||||
|
do {
|
||||||
|
struct menucoloring *tmp, *tmp2;
|
||||||
|
|
||||||
|
for (tmp = gm.menu_colorings; tmp; tmp = tmp2) {
|
||||||
|
tmp2 = tmp->next;
|
||||||
|
regex_free(tmp->match);
|
||||||
|
free((genericptr_t) tmp->origstr);
|
||||||
|
free((genericptr_t) tmp);
|
||||||
|
}
|
||||||
|
gm.menu_colorings = gc.color_colorings;
|
||||||
|
gc.color_colorings = (struct menucoloring *) 0;
|
||||||
|
} while (gm.menu_colorings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release a specific menu color pattern; not used for color_colorings */
|
||||||
|
void
|
||||||
|
free_one_menu_coloring(int idx) /* 0 .. */
|
||||||
|
{
|
||||||
|
struct menucoloring *tmp = gm.menu_colorings;
|
||||||
|
struct menucoloring *prev = NULL;
|
||||||
|
|
||||||
|
while (tmp) {
|
||||||
|
if (idx == 0) {
|
||||||
|
struct menucoloring *next = tmp->next;
|
||||||
|
|
||||||
|
regex_free(tmp->match);
|
||||||
|
free((genericptr_t) tmp->origstr);
|
||||||
|
free((genericptr_t) tmp);
|
||||||
|
if (prev)
|
||||||
|
prev->next = next;
|
||||||
|
else
|
||||||
|
gm.menu_colorings = next;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
idx--;
|
||||||
|
prev = tmp;
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
count_menucolors(void)
|
||||||
|
{
|
||||||
|
struct menucoloring *tmp;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (tmp = gm.menu_colorings; tmp; tmp = tmp->next)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns -1 on no-match.
|
||||||
|
* buf is NONNULLARG1
|
||||||
|
*/
|
||||||
|
int32
|
||||||
|
check_enhanced_colors(const char *buf)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c = 0; c < SIZE(colortable); ++c) {
|
||||||
|
if (!strcmpi(buf, colortable[c].name))
|
||||||
|
return colortable_to_int32(&colortable[c]);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
527
src/options.c
527
src/options.c
@@ -26,9 +26,6 @@ NEARDATA struct instance_flags iflags; /* provide linkage */
|
|||||||
#define PREV_MSGS 0
|
#define PREV_MSGS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *color_attr_to_str(color_attr *);
|
|
||||||
static boolean color_attr_parse_str(color_attr *, char *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: If you add (or delete) an option, please review the following:
|
* NOTE: If you add (or delete) an option, please review the following:
|
||||||
* doc/options.txt
|
* doc/options.txt
|
||||||
@@ -340,17 +337,12 @@ static int petname_optfn(int, int, boolean, char *, char *);
|
|||||||
static int shared_menu_optfn(int, int, boolean, char *, char *);
|
static int shared_menu_optfn(int, int, boolean, char *, char *);
|
||||||
static int spcfn_misc_menu_cmd(int, int, boolean, char *, char *);
|
static int spcfn_misc_menu_cmd(int, int, boolean, char *, char *);
|
||||||
|
|
||||||
static const char *attr2attrname(int);
|
|
||||||
static void basic_menu_colors(boolean);
|
|
||||||
static const char * msgtype2name(int);
|
static const char * msgtype2name(int);
|
||||||
static int query_msgtype(void);
|
static int query_msgtype(void);
|
||||||
static boolean msgtype_add(int, char *);
|
static boolean msgtype_add(int, char *);
|
||||||
static void free_one_msgtype(int);
|
static void free_one_msgtype(int);
|
||||||
static int msgtype_count(void);
|
static int msgtype_count(void);
|
||||||
static boolean test_regex_pattern(const char *, const char *);
|
static boolean test_regex_pattern(const char *, const char *);
|
||||||
static boolean add_menu_coloring_parsed(const char *, int, int);
|
|
||||||
static void free_one_menu_coloring(int);
|
|
||||||
static int count_menucolors(void);
|
|
||||||
static boolean parse_role_opt(int, boolean, const char *, char *, char **);
|
static boolean parse_role_opt(int, boolean, const char *, char *, char **);
|
||||||
static char *get_cnf_role_opt(int);
|
static char *get_cnf_role_opt(int);
|
||||||
static unsigned int longest_option_name(int, int);
|
static unsigned int longest_option_name(int, int);
|
||||||
@@ -2095,61 +2087,6 @@ optfn_menu_shift_right(int optidx, int req, boolean negated,
|
|||||||
|
|
||||||
/* end of shared key assignments for menu commands */
|
/* end of shared key assignments for menu commands */
|
||||||
|
|
||||||
static char *
|
|
||||||
color_attr_to_str(color_attr *ca)
|
|
||||||
{
|
|
||||||
static char buf[BUFSZ];
|
|
||||||
|
|
||||||
Sprintf(buf, "%s&%s",
|
|
||||||
clr2colorname(ca->color),
|
|
||||||
attr2attrname(ca->attr));
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse string like "color&attr" into color_attr */
|
|
||||||
static boolean
|
|
||||||
color_attr_parse_str(color_attr *ca, char *str)
|
|
||||||
{
|
|
||||||
char buf[BUFSZ];
|
|
||||||
char *amp = NULL;
|
|
||||||
int tmp, c = NO_COLOR, a = ATR_NONE;
|
|
||||||
|
|
||||||
(void) strncpy(buf, str, sizeof buf - 1);
|
|
||||||
buf[sizeof buf - 1] = '\0';
|
|
||||||
|
|
||||||
if ((amp = strchr(buf, '&')) != 0)
|
|
||||||
*amp = '\0';
|
|
||||||
|
|
||||||
if (amp) {
|
|
||||||
amp++;
|
|
||||||
c = match_str2clr(buf);
|
|
||||||
a = match_str2attr(amp, TRUE);
|
|
||||||
/* FIXME: match_str2clr & match_str2attr give config_error_add(),
|
|
||||||
so this is useless */
|
|
||||||
if (c >= CLR_MAX && a == -1) {
|
|
||||||
/* try other way around */
|
|
||||||
c = match_str2clr(amp);
|
|
||||||
a = match_str2attr(buf, TRUE);
|
|
||||||
}
|
|
||||||
if (c >= CLR_MAX || a == -1)
|
|
||||||
return FALSE;
|
|
||||||
} else {
|
|
||||||
/* one param only */
|
|
||||||
tmp = match_str2attr(buf, FALSE);
|
|
||||||
if (tmp == -1) {
|
|
||||||
tmp = match_str2clr(buf);
|
|
||||||
if (tmp >= CLR_MAX)
|
|
||||||
return FALSE;
|
|
||||||
c = tmp;
|
|
||||||
} else {
|
|
||||||
a = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ca->attr = a;
|
|
||||||
ca->color = c;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
optfn_menu_headings(
|
optfn_menu_headings(
|
||||||
int optidx,
|
int optidx,
|
||||||
@@ -7419,335 +7356,6 @@ parsebindings(char *bindings)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Color support functions and data for "color"
|
|
||||||
*
|
|
||||||
* Used by: optfn_()
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct color_names {
|
|
||||||
const char *name;
|
|
||||||
int color;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct color_names colornames[] = {
|
|
||||||
{ "black", CLR_BLACK },
|
|
||||||
{ "red", CLR_RED },
|
|
||||||
{ "green", CLR_GREEN },
|
|
||||||
{ "brown", CLR_BROWN },
|
|
||||||
{ "blue", CLR_BLUE },
|
|
||||||
{ "magenta", CLR_MAGENTA },
|
|
||||||
{ "cyan", CLR_CYAN },
|
|
||||||
{ "gray", CLR_GRAY },
|
|
||||||
{ "orange", CLR_ORANGE },
|
|
||||||
{ "light green", CLR_BRIGHT_GREEN },
|
|
||||||
{ "yellow", CLR_YELLOW },
|
|
||||||
{ "light blue", CLR_BRIGHT_BLUE },
|
|
||||||
{ "light magenta", CLR_BRIGHT_MAGENTA },
|
|
||||||
{ "light cyan", CLR_BRIGHT_CYAN },
|
|
||||||
{ "white", CLR_WHITE },
|
|
||||||
{ "no color", NO_COLOR },
|
|
||||||
{ (const char *) 0, CLR_BLACK }, /* everything after this is an alias */
|
|
||||||
{ "transparent", NO_COLOR },
|
|
||||||
{ "purple", CLR_MAGENTA },
|
|
||||||
{ "light purple", CLR_BRIGHT_MAGENTA },
|
|
||||||
{ "bright purple", CLR_BRIGHT_MAGENTA },
|
|
||||||
{ "grey", CLR_GRAY },
|
|
||||||
{ "bright red", CLR_ORANGE },
|
|
||||||
{ "bright green", CLR_BRIGHT_GREEN },
|
|
||||||
{ "bright blue", CLR_BRIGHT_BLUE },
|
|
||||||
{ "bright magenta", CLR_BRIGHT_MAGENTA },
|
|
||||||
{ "bright cyan", CLR_BRIGHT_CYAN }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct attr_names {
|
|
||||||
const char *name;
|
|
||||||
int attr;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attr_names attrnames[] = {
|
|
||||||
{ "none", ATR_NONE },
|
|
||||||
{ "bold", ATR_BOLD },
|
|
||||||
{ "dim", ATR_DIM },
|
|
||||||
{ "italic", ATR_ITALIC },
|
|
||||||
{ "underline", ATR_ULINE },
|
|
||||||
{ "blink", ATR_BLINK },
|
|
||||||
{ "inverse", ATR_INVERSE },
|
|
||||||
{ (const char *) 0, ATR_NONE }, /* everything after this is an alias */
|
|
||||||
{ "normal", ATR_NONE },
|
|
||||||
{ "uline", ATR_ULINE },
|
|
||||||
{ "reverse", ATR_INVERSE },
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *
|
|
||||||
clr2colorname(int clr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < SIZE(colornames); i++)
|
|
||||||
if (colornames[i].name && colornames[i].color == clr)
|
|
||||||
return colornames[i].name;
|
|
||||||
return (char *) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
match_str2clr(char *str)
|
|
||||||
{
|
|
||||||
int i, c = CLR_MAX;
|
|
||||||
|
|
||||||
/* allow "lightblue", "light blue", and "light-blue" to match "light blue"
|
|
||||||
(also junk like "_l i-gh_t---b l u e" but we won't worry about that);
|
|
||||||
also copes with trailing space; caller has removed any leading space */
|
|
||||||
for (i = 0; i < SIZE(colornames); i++)
|
|
||||||
if (colornames[i].name
|
|
||||||
&& fuzzymatch(str, colornames[i].name, " -_", TRUE)) {
|
|
||||||
c = colornames[i].color;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == SIZE(colornames) && digit(*str))
|
|
||||||
c = atoi(str);
|
|
||||||
|
|
||||||
if (c < 0 || c >= CLR_MAX) {
|
|
||||||
config_error_add("Unknown color '%.60s'", str);
|
|
||||||
c = CLR_MAX; /* "none of the above" */
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
attr2attrname(int attr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < SIZE(attrnames); i++)
|
|
||||||
if (attrnames[i].attr == attr)
|
|
||||||
return attrnames[i].name;
|
|
||||||
return (char *) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
match_str2attr(const char *str, boolean complain)
|
|
||||||
{
|
|
||||||
int i, a = -1;
|
|
||||||
|
|
||||||
for (i = 0; i < SIZE(attrnames); i++)
|
|
||||||
if (attrnames[i].name
|
|
||||||
&& fuzzymatch(str, attrnames[i].name, " -_", TRUE)) {
|
|
||||||
a = attrnames[i].attr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a == -1 && complain)
|
|
||||||
config_error_add("Unknown text attribute '%.50s'", str);
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const char regex_id[]; /* from sys/share/<various>regex.{c,cpp} */
|
|
||||||
|
|
||||||
DISABLE_WARNING_FORMAT_NONLITERAL
|
|
||||||
|
|
||||||
/* True: temporarily replace menu color entries with a fake set of menu
|
|
||||||
colors, { "light blue"=light_blue, "blue"=blue, "red"=red, &c }, that
|
|
||||||
illustrates most colors for use when the pick-a-color menu is rendered;
|
|
||||||
suppresses black and white because one of those will likely be invisible
|
|
||||||
due to matching the background; False: restore user-specified colorings */
|
|
||||||
static void
|
|
||||||
basic_menu_colors(boolean load_colors)
|
|
||||||
{
|
|
||||||
if (load_colors) {
|
|
||||||
/* replace normal menu colors with a set specifically for colors */
|
|
||||||
gs.save_menucolors = iflags.use_menu_color;
|
|
||||||
gs.save_colorings = gm.menu_colorings;
|
|
||||||
|
|
||||||
iflags.use_menu_color = TRUE;
|
|
||||||
if (gc.color_colorings) {
|
|
||||||
/* use the alternate colorings which were set up previously */
|
|
||||||
gm.menu_colorings = gc.color_colorings;
|
|
||||||
} else {
|
|
||||||
/* create the alternate colorings once */
|
|
||||||
char cnm[QBUFSZ];
|
|
||||||
int i, c;
|
|
||||||
boolean pmatchregex = !strcmpi(regex_id, "pmatchregex");
|
|
||||||
const char *patternfmt = pmatchregex ? "*%s" : "%s";
|
|
||||||
|
|
||||||
/* menu_colorings pointer has been saved; clear it in order
|
|
||||||
to add the alternate entries as if from scratch */
|
|
||||||
gm.menu_colorings = (struct menucoloring *) 0;
|
|
||||||
|
|
||||||
/* this orders the patterns last-in/first-out; that means
|
|
||||||
that the "light <foo>" variations come before the basic
|
|
||||||
"<foo>" ones, which is exactly what we want */
|
|
||||||
for (i = 0; i < SIZE(colornames); ++i) {
|
|
||||||
if (!colornames[i].name) /* first alias entry has no name */
|
|
||||||
break;
|
|
||||||
c = colornames[i].color;
|
|
||||||
if (c == CLR_BLACK || c == CLR_WHITE || c == NO_COLOR)
|
|
||||||
continue; /* skip these */
|
|
||||||
Sprintf(cnm, patternfmt, colornames[i].name);
|
|
||||||
add_menu_coloring_parsed(cnm, c, ATR_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* right now, menu_colorings contains the alternate color list;
|
|
||||||
remember that list for future pick-a-color instances and
|
|
||||||
also keep it as is for this instance */
|
|
||||||
gc.color_colorings = gm.menu_colorings;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* restore normal user-specified menu colors */
|
|
||||||
iflags.use_menu_color = gs.save_menucolors;
|
|
||||||
gm.menu_colorings = gs.save_colorings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RESTORE_WARNING_FORMAT_NONLITERAL
|
|
||||||
|
|
||||||
int
|
|
||||||
query_color(const char *prompt, int dflt_color)
|
|
||||||
{
|
|
||||||
winid tmpwin;
|
|
||||||
anything any;
|
|
||||||
int i, pick_cnt;
|
|
||||||
menu_item *picks = (menu_item *) 0;
|
|
||||||
|
|
||||||
/* replace user patterns with color name ones and force 'menucolors' On */
|
|
||||||
basic_menu_colors(TRUE);
|
|
||||||
|
|
||||||
tmpwin = create_nhwindow(NHW_MENU);
|
|
||||||
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
|
|
||||||
any = cg.zeroany;
|
|
||||||
for (i = 0; i < SIZE(colornames); i++) {
|
|
||||||
if (!colornames[i].name)
|
|
||||||
break;
|
|
||||||
any.a_int = i + 1;
|
|
||||||
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
|
|
||||||
ATR_NONE, NO_COLOR, colornames[i].name,
|
|
||||||
(colornames[i].color == dflt_color) ? MENU_ITEMFLAGS_SELECTED
|
|
||||||
: MENU_ITEMFLAGS_NONE);
|
|
||||||
}
|
|
||||||
end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick a color");
|
|
||||||
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
|
|
||||||
destroy_nhwindow(tmpwin);
|
|
||||||
|
|
||||||
/* remove temporary color name patterns and restore user-specified ones;
|
|
||||||
reset 'menucolors' option to its previous value */
|
|
||||||
basic_menu_colors(FALSE);
|
|
||||||
|
|
||||||
if (pick_cnt > 0) {
|
|
||||||
i = colornames[picks[0].item.a_int - 1].color;
|
|
||||||
/* pick_cnt==2: explicitly picked something other than the
|
|
||||||
preselected entry */
|
|
||||||
if (pick_cnt == 2 && i == NO_COLOR)
|
|
||||||
i = colornames[picks[1].item.a_int - 1].color;
|
|
||||||
free((genericptr_t) picks);
|
|
||||||
return i;
|
|
||||||
} else if (pick_cnt == 0) {
|
|
||||||
/* pick_cnt==0: explicitly picking preselected entry toggled it off */
|
|
||||||
return dflt_color;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ask about highlighting attribute; for menu headers and menu
|
|
||||||
coloring patterns, only one attribute at a time is allowed;
|
|
||||||
for status highlighting, multiple attributes are allowed [overkill;
|
|
||||||
life would be much simpler if that were restricted to one also...] */
|
|
||||||
int
|
|
||||||
query_attr(const char *prompt, int dflt_attr)
|
|
||||||
{
|
|
||||||
winid tmpwin;
|
|
||||||
anything any;
|
|
||||||
int i, pick_cnt;
|
|
||||||
menu_item *picks = (menu_item *) 0;
|
|
||||||
boolean allow_many = (prompt && !strncmpi(prompt, "Choose", 6));
|
|
||||||
int clr = NO_COLOR;
|
|
||||||
|
|
||||||
tmpwin = create_nhwindow(NHW_MENU);
|
|
||||||
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
|
|
||||||
any = cg.zeroany;
|
|
||||||
for (i = 0; i < SIZE(attrnames); i++) {
|
|
||||||
if (!attrnames[i].name)
|
|
||||||
break;
|
|
||||||
any.a_int = i + 1;
|
|
||||||
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
|
|
||||||
attrnames[i].attr, clr, attrnames[i].name,
|
|
||||||
(attrnames[i].attr == dflt_attr) ? MENU_ITEMFLAGS_SELECTED
|
|
||||||
: MENU_ITEMFLAGS_NONE);
|
|
||||||
}
|
|
||||||
end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick an attribute");
|
|
||||||
pick_cnt = select_menu(tmpwin, allow_many ? PICK_ANY : PICK_ONE, &picks);
|
|
||||||
destroy_nhwindow(tmpwin);
|
|
||||||
if (pick_cnt > 0) {
|
|
||||||
int j, k = 0;
|
|
||||||
|
|
||||||
if (allow_many) {
|
|
||||||
/* PICK_ANY, with one preselected entry (ATR_NONE) which
|
|
||||||
should be excluded if any other choices were picked */
|
|
||||||
for (i = 0; i < pick_cnt; ++i) {
|
|
||||||
j = picks[i].item.a_int - 1;
|
|
||||||
if (attrnames[j].attr != ATR_NONE || pick_cnt == 1) {
|
|
||||||
switch (attrnames[j].attr) {
|
|
||||||
case ATR_NONE:
|
|
||||||
k = HL_NONE;
|
|
||||||
break;
|
|
||||||
case ATR_BOLD:
|
|
||||||
k |= HL_BOLD;
|
|
||||||
break;
|
|
||||||
case ATR_DIM:
|
|
||||||
k |= HL_DIM;
|
|
||||||
break;
|
|
||||||
case ATR_ITALIC:
|
|
||||||
k |= HL_ITALIC;
|
|
||||||
break;
|
|
||||||
case ATR_ULINE:
|
|
||||||
k |= HL_ULINE;
|
|
||||||
break;
|
|
||||||
case ATR_BLINK:
|
|
||||||
k |= HL_BLINK;
|
|
||||||
break;
|
|
||||||
case ATR_INVERSE:
|
|
||||||
k |= HL_INVERSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* PICK_ONE, but might get 0 or 2 due to preselected entry */
|
|
||||||
j = picks[0].item.a_int - 1;
|
|
||||||
/* pick_cnt==2: explicitly picked something other than the
|
|
||||||
preselected entry */
|
|
||||||
if (pick_cnt == 2 && attrnames[j].attr == dflt_attr)
|
|
||||||
j = picks[1].item.a_int - 1;
|
|
||||||
k = attrnames[j].attr;
|
|
||||||
}
|
|
||||||
free((genericptr_t) picks);
|
|
||||||
return k;
|
|
||||||
} else if (pick_cnt == 0 && !allow_many) {
|
|
||||||
/* PICK_ONE, preselected entry explicitly chosen */
|
|
||||||
return dflt_attr;
|
|
||||||
}
|
|
||||||
/* either ESC to explicitly cancel (pick_cnt==-1) or
|
|
||||||
PICK_ANY with preselected entry toggled off and nothing chosen */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean
|
|
||||||
query_color_attr(color_attr *ca, const char *prompt)
|
|
||||||
{
|
|
||||||
int c, a;
|
|
||||||
|
|
||||||
c = query_color(prompt, ca->color);
|
|
||||||
if (c == -1)
|
|
||||||
return FALSE;
|
|
||||||
a = query_attr(prompt, ca->attr);
|
|
||||||
if (a == -1)
|
|
||||||
return FALSE;
|
|
||||||
ca->color = c;
|
|
||||||
ca->attr = a;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
xint8 msgtyp;
|
xint8 msgtyp;
|
||||||
@@ -7974,141 +7582,6 @@ test_regex_pattern(const char *str, const char *errmsg)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
|
||||||
add_menu_coloring_parsed(const char *str, int c, int a)
|
|
||||||
{
|
|
||||||
static const char re_error[] = "Menucolor regex error";
|
|
||||||
struct menucoloring *tmp;
|
|
||||||
|
|
||||||
if (!str)
|
|
||||||
return FALSE;
|
|
||||||
tmp = (struct menucoloring *) alloc(sizeof *tmp);
|
|
||||||
tmp->match = regex_init();
|
|
||||||
/* test_regex_pattern() has already validated this regexp but parsing
|
|
||||||
it again could conceivably run out of memory */
|
|
||||||
if (!regex_compile(str, tmp->match)) {
|
|
||||||
char errbuf[BUFSZ];
|
|
||||||
char *re_error_desc = regex_error_desc(tmp->match, errbuf);
|
|
||||||
|
|
||||||
/* free first in case reason for regcomp failure was out-of-memory */
|
|
||||||
regex_free(tmp->match);
|
|
||||||
free((genericptr_t) tmp);
|
|
||||||
config_error_add("%s: %s", re_error, re_error_desc);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
tmp->next = gm.menu_colorings;
|
|
||||||
tmp->origstr = dupstr(str);
|
|
||||||
tmp->color = c;
|
|
||||||
tmp->attr = a;
|
|
||||||
gm.menu_colorings = tmp;
|
|
||||||
iflags.use_menu_color = TRUE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse '"regex_string"=color&attr' and add it to menucoloring */
|
|
||||||
boolean
|
|
||||||
add_menu_coloring(char *tmpstr) /* never Null but could be empty */
|
|
||||||
{
|
|
||||||
int c = NO_COLOR, a = ATR_NONE;
|
|
||||||
char *tmps, *cs, *amp;
|
|
||||||
char str[BUFSZ];
|
|
||||||
|
|
||||||
(void) strncpy(str, tmpstr, sizeof str - 1);
|
|
||||||
str[sizeof str - 1] = '\0';
|
|
||||||
|
|
||||||
if ((cs = strchr(str, '=')) == 0) {
|
|
||||||
config_error_add("Malformed MENUCOLOR");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmps = cs + 1; /* advance past '=' */
|
|
||||||
mungspaces(tmps);
|
|
||||||
if ((amp = strchr(tmps, '&')) != 0)
|
|
||||||
*amp = '\0';
|
|
||||||
|
|
||||||
c = match_str2clr(tmps);
|
|
||||||
if (c >= CLR_MAX)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (amp) {
|
|
||||||
tmps = amp + 1; /* advance past '&' */
|
|
||||||
a = match_str2attr(tmps, TRUE);
|
|
||||||
if (a == -1)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the regexp portion here has not been condensed by mungspaces() */
|
|
||||||
*cs = '\0';
|
|
||||||
tmps = str;
|
|
||||||
if (*tmps == '"' || *tmps == '\'') {
|
|
||||||
cs--;
|
|
||||||
while (isspace((uchar) *cs))
|
|
||||||
cs--;
|
|
||||||
if (*cs == *tmps) {
|
|
||||||
*cs = '\0';
|
|
||||||
tmps++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return add_menu_coloring_parsed(tmps, c, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* release all menu color patterns */
|
|
||||||
void
|
|
||||||
free_menu_coloring(void)
|
|
||||||
{
|
|
||||||
/* either menu_colorings or color_colorings or both might need to
|
|
||||||
be freed or already be Null; do-loop will iterate at most twice */
|
|
||||||
do {
|
|
||||||
struct menucoloring *tmp, *tmp2;
|
|
||||||
|
|
||||||
for (tmp = gm.menu_colorings; tmp; tmp = tmp2) {
|
|
||||||
tmp2 = tmp->next;
|
|
||||||
regex_free(tmp->match);
|
|
||||||
free((genericptr_t) tmp->origstr);
|
|
||||||
free((genericptr_t) tmp);
|
|
||||||
}
|
|
||||||
gm.menu_colorings = gc.color_colorings;
|
|
||||||
gc.color_colorings = (struct menucoloring *) 0;
|
|
||||||
} while (gm.menu_colorings);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* release a specific menu color pattern; not used for color_colorings */
|
|
||||||
static void
|
|
||||||
free_one_menu_coloring(int idx) /* 0 .. */
|
|
||||||
{
|
|
||||||
struct menucoloring *tmp = gm.menu_colorings;
|
|
||||||
struct menucoloring *prev = NULL;
|
|
||||||
|
|
||||||
while (tmp) {
|
|
||||||
if (idx == 0) {
|
|
||||||
struct menucoloring *next = tmp->next;
|
|
||||||
|
|
||||||
regex_free(tmp->match);
|
|
||||||
free((genericptr_t) tmp->origstr);
|
|
||||||
free((genericptr_t) tmp);
|
|
||||||
if (prev)
|
|
||||||
prev->next = next;
|
|
||||||
else
|
|
||||||
gm.menu_colorings = next;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
idx--;
|
|
||||||
prev = tmp;
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
count_menucolors(void)
|
|
||||||
{
|
|
||||||
struct menucoloring *tmp;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
for (tmp = gm.menu_colorings; tmp; tmp = tmp->next)
|
|
||||||
count++;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse 'role' or 'race' or 'gender' or 'alignment' */
|
/* parse 'role' or 'race' or 'gender' or 'alignment' */
|
||||||
static boolean
|
static boolean
|
||||||
parse_role_opt(
|
parse_role_opt(
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ static int32_t rgbstr_to_int32(const char *rgbstr);
|
|||||||
boolean closest_color(uint32_t lcolor, uint32_t *closecolor, int *clridx);
|
boolean closest_color(uint32_t lcolor, uint32_t *closecolor, int *clridx);
|
||||||
static const long nonzero_black = 0x1000000;
|
static const long nonzero_black = 0x1000000;
|
||||||
static int color_distance(uint32_t, uint32_t);
|
static int color_distance(uint32_t, uint32_t);
|
||||||
|
static boolean onlyhexdigits(const char *buf);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat)
|
to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat)
|
||||||
@@ -142,6 +143,20 @@ glyphrep_to_custom_map_entries(const char *op, int *glyphptr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
onlyhexdigits(const char *buf)
|
||||||
|
{
|
||||||
|
const char *dp = buf;
|
||||||
|
|
||||||
|
for (dp = buf; *dp; ++dp) {
|
||||||
|
if (!(strchr(hex, *dp) || *dp == '-'))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t
|
static int32_t
|
||||||
rgbstr_to_int32(const char *rgbstr)
|
rgbstr_to_int32(const char *rgbstr)
|
||||||
{
|
{
|
||||||
@@ -151,41 +166,51 @@ rgbstr_to_int32(const char *rgbstr)
|
|||||||
char buf[BUFSZ];
|
char buf[BUFSZ];
|
||||||
boolean dash = FALSE;
|
boolean dash = FALSE;
|
||||||
|
|
||||||
r = g = b = 0;
|
|
||||||
c_g = c_b = (char *) 0;
|
Snprintf(buf, sizeof buf, "%s",
|
||||||
Snprintf(buf, sizeof buf, "%s", rgbstr);
|
rgbstr ? rgbstr : "");
|
||||||
c_r = cp = buf;
|
|
||||||
while (*cp) {
|
if (*buf && onlyhexdigits(buf)) {
|
||||||
if (digit(*cp) || *cp == '-') {
|
r = g = b = 0;
|
||||||
if (*cp == '-') {
|
c_g = c_b = (char *) 0;
|
||||||
*cp = '\0';
|
c_r = cp = buf;
|
||||||
milestone++;
|
while (*cp) {
|
||||||
dash = TRUE;
|
if (digit(*cp) || *cp == '-') {
|
||||||
|
if (*cp == '-') {
|
||||||
|
*cp = '\0';
|
||||||
|
milestone++;
|
||||||
|
dash = TRUE;
|
||||||
|
}
|
||||||
|
cp++;
|
||||||
|
if (dash) {
|
||||||
|
if (milestone < 2)
|
||||||
|
c_g = cp;
|
||||||
|
else
|
||||||
|
c_b = cp;
|
||||||
|
dash = FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return -1L;
|
||||||
}
|
}
|
||||||
cp++;
|
}
|
||||||
if (dash) {
|
/* sanity checks */
|
||||||
if (milestone < 2)
|
if (c_r && c_g && c_b
|
||||||
c_g = cp;
|
&& (strlen(c_r) > 0 && strlen(c_r) < 4)
|
||||||
else
|
&& (strlen(c_g) > 0 && strlen(c_g) < 4)
|
||||||
c_b = cp;
|
&& (strlen(c_b) > 0 && strlen(c_b) < 4)) {
|
||||||
dash = FALSE;
|
r = atoi(c_r);
|
||||||
}
|
g = atoi(c_g);
|
||||||
} else {
|
b = atoi(c_b);
|
||||||
return -1L;
|
rgb = (r << 16) | (g << 8) | (b << 0);
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
} else if (*buf) {
|
||||||
|
/* perhaps an enhanced color name was used instead of rgb value? */
|
||||||
|
if ((rgb = check_enhanced_colors(buf)) != -1) {
|
||||||
|
return rgb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* sanity checks */
|
return -1;
|
||||||
if (c_r && c_g && c_b
|
|
||||||
&& (strlen(c_r) > 0 && strlen(c_r) < 4)
|
|
||||||
&& (strlen(c_g) > 0 && strlen(c_g) < 4)
|
|
||||||
&& (strlen(c_b) > 0 && strlen(c_b) < 4)) {
|
|
||||||
r = atoi(c_r);
|
|
||||||
g = atoi(c_g);
|
|
||||||
b = atoi(c_b);
|
|
||||||
rgb = (r << 16) | (g << 8) | (b << 0);
|
|
||||||
return rgb;
|
|
||||||
}
|
|
||||||
return -1L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@@ -209,7 +234,6 @@ unicode_val(const char *cp)
|
|||||||
{
|
{
|
||||||
const char *dp;
|
const char *dp;
|
||||||
int cval = 0, dcount;
|
int cval = 0, dcount;
|
||||||
static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
|
|
||||||
|
|
||||||
if (cp && *cp) {
|
if (cp && *cp) {
|
||||||
cval = dcount = 0;
|
cval = dcount = 0;
|
||||||
|
|||||||
@@ -493,7 +493,8 @@ HACK_H = ../src/hack.h-t
|
|||||||
# all .c that are part of the main NetHack program and are not operating- or
|
# all .c that are part of the main NetHack program and are not operating- or
|
||||||
# windowing-system specific. Do not include date.c in this list.
|
# windowing-system specific. Do not include date.c in this list.
|
||||||
HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
|
HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
|
||||||
botl.c cmd.c dbridge.c decl.c detect.c dig.c display.c dlb.c do.c \
|
botl.c coloratt.c cmd.c dbridge.c decl.c detect.c dig.c display.c \
|
||||||
|
dlb.c do.c \
|
||||||
do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c drawing.c \
|
do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c drawing.c \
|
||||||
dungeon.c eat.c end.c engrave.c exper.c explode.c extralev.c \
|
dungeon.c eat.c end.c engrave.c exper.c explode.c extralev.c \
|
||||||
files.c fountain.c hack.c hacklib.c \
|
files.c fountain.c hack.c hacklib.c \
|
||||||
@@ -568,6 +569,7 @@ HOSTOBJ = $(FIRSTOBJ) alloc.o drawing.o
|
|||||||
HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \
|
HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \
|
||||||
$(TARGETPFX)apply.o $(TARGETPFX)artifact.o $(TARGETPFX)attrib.o \
|
$(TARGETPFX)apply.o $(TARGETPFX)artifact.o $(TARGETPFX)attrib.o \
|
||||||
$(TARGETPFX)ball.o $(TARGETPFX)bones.o $(TARGETPFX)botl.o \
|
$(TARGETPFX)ball.o $(TARGETPFX)bones.o $(TARGETPFX)botl.o \
|
||||||
|
$(TARGETPFX)coloratt.o \
|
||||||
$(TARGETPFX)cmd.o $(TARGETPFX)dbridge.o $(TARGETPFX)decl.o \
|
$(TARGETPFX)cmd.o $(TARGETPFX)dbridge.o $(TARGETPFX)decl.o \
|
||||||
$(TARGETPFX)detect.o $(TARGETPFX)dig.o $(TARGETPFX)display.o \
|
$(TARGETPFX)detect.o $(TARGETPFX)dig.o $(TARGETPFX)display.o \
|
||||||
$(TARGETPFX)dlb.o $(TARGETPFX)do.o $(TARGETPFX)do_name.o \
|
$(TARGETPFX)dlb.o $(TARGETPFX)do.o $(TARGETPFX)do_name.o \
|
||||||
|
|||||||
Reference in New Issue
Block a user