ENHANCED_SYMBOLS

A new feature, enabled by default to maximize testing, but one which can
be disabled by commenting it out in config.h

With this, some additional information is added to the glyphmap entries
in a new optional substructure called u with these fields:
    ucolor          RGB color for use with truecolor terminals/platforms.
                    A ucolor value of zero means "not set." The actual
                    rgb value of 0 has the 0x1000000 bit set.
    u256coloridx    256 color index value for use with 256 color
                    terminals, the closest color match to ucolor.
    utf8str         Custom representation via utf-8 string (can be null).

There is a new symset included in the symbols file, called enhanced1.

Some initial code has been added to parse individual
OPTIONS=glyph:glyphid/R-G-B entries in the config file.

The glyphid can, in theory, either be an individual glyph (G_* glyphid)
for a single glyph, or it can be an existing symbol S_ value
(monster, object, or cmap symbol) to store the custom representation for
all the glyphs that match that symbol.

Examples:
   OPTIONS=glyph:G_fountain/U+03A8/0-150-255

(Your platform/terminal font needs to be able to include/display the
character, of course.)

The NetHack core code does parsing and storing the customized
entries, and adding them to the glyphmap data structure.

Any window port can utilize the additional information in the glyphinfo
that is passed to them, once code is added to do so.

Also, consolidate some symbol-related code into symbols.c, and remove it from
files.c and options.c
This commit is contained in:
nhmall
2022-05-07 10:25:13 -04:00
parent 132e1d433a
commit cb0c21e91d
50 changed files with 3072 additions and 1242 deletions

View File

@@ -2,7 +2,7 @@
# Copyright (c) 2006 by Michael Allison
# NetHack may be freely redistributed. See license for details.
#
# Symbol sets for use in NetHack's text-based display.
# Symbol sets and handlers for use in NetHack's text-based display.
#
# IBMgraphics works by specifying special characters which reside
# outside the range of normal printable characters. It has subsets
@@ -22,7 +22,17 @@
# on an old graphics mode for the Curses interface and is the default
# on that windowport if no symset is specified. The Curses interface
# can also use DECgraphics as-is; IBMgraphics probably won't work.
#
# Symsets that use the UTF8 handler work a little differently than
# those that do not. When the UTF8 handler is in effect, any NetHack
# glyphs that have a utf8str entry present in the runtime glyphmap[]
# array will utilize that UTF-8 character sequence for the glyph display
# instead of the NetHack ttychar symbol that would otherwise be used.
# Any NetHack glyphs that don't actually have a utf8str sequence present
# in the internal glyphmap will simply fall back to utilizing the typical
# NetHack ttychar symbol as usual. That is true even when the UTF-8
# handler is in effect.
#
# plain looks decent for room+corridor levels where there aren't a lot
# of wall corners and ones present tend to be spread out, but it looks
# awful for wallified mazes
@@ -550,4 +560,94 @@ start: MACgraphics
S_pool: \xe0
finish
start: Enhanced1
Description: Enhanced with Unicode glyphs and 24-bit color
Restrictions: primary
Handling: UTF8
S_vwall: U+2502 # BOX DRAWINGS LIGHT VERTICAL
S_hwall: U+2500 # BOX DRAWINGS LIGHT HORIZONTAL
S_tlcorn: U+250c # BOX DRAWINGS LIGHT DOWN AND RIGHT
S_trcorn: U+2510 # BOX DRAWINGS LIGHT DOWN AND LEFT
S_blcorn: U+2514 # BOX DRAWINGS LIGHT UP AND RIGHT
S_brcorn: U+2518 # BOX DRAWINGS LIGHT UP AND LEFT
S_crwall: U+253c # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
S_tuwall: U+2534 # BOX DRAWINGS LIGHT UP AND HORIZONTAL
S_tdwall: U+252c # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
S_tlwall: U+2524 # BOX DRAWINGS LIGHT VERTICAL AND LEFT
S_trwall: U+251c # BOX DRAWINGS LIGHT VERTICAL AND RIGHT
S_ndoor: U+00b7 # MIDDLE DOT
S_vodoor: U+2592 # MEDIUM SHADE
S_hodoor: U+2592 # MEDIUM SHADE
S_bars: U+2261 # IDENTICAL TO
S_tree: U+03a8 # GREEK CAPITAL LETTER PSI
S_room: U+00b7 # MIDDLE DOT
S_darkroom: U+00b7 # MIDDLE DOT
S_upladder: U+2264 # LESS-THAN OR EQUAL TO
S_dnladder: U+2265 # GREATER-THAN OR EQUAL TO
S_altar: U+03A9 # GREEK CAPITAL LETTER OMEGA
S_grave: U+2020 # DAGGER
G_fountain: U+2320/0-150-255 # TOP HALF INTEGRAL
S_pool: U+224b # TRIPLE TILDE
S_ice: U+00b7 # MIDDLE DOT
S_lava: U+224b # TRIPLE TILDE
S_vodbridge: U+00b7 # MIDDLE DOT
S_hodbridge: U+00b7 # MIDDLE DOT
S_water: U+2248 # ALMOST EQUAL TO
S_web: U+00A4 # CURRENCY SIGN
S_vbeam: U+2502 # BOX DRAWINGS LIGHT VERTICAL
S_hbeam: U+2500 # BOX DRAWINGS LIGHT HORIZONTAL
S_sw_tc: U+2594 # UPPER ONE EIGHTH BLOCK
S_sw_ml: U+258f # LEFT ONE EIGHTH BLOCK
S_sw_mr: U+2595 # RIGHT ONE EIGHTH BLOCK
S_sw_bc: U+2581 # LOWER ONE EIGHTH BLOCK
S_expl_tc: U+2594 # UPPER ONE EIGHTH BLOCK
S_expl_ml: U+258f # LEFT ONE EIGHTH BLOCK
S_expl_mr: U+2595 # RIGHT ONE EIGHTH BLOCK
S_expl_bc: U+2581 # LOWER ONE EIGHTH BLOCK
G_vwall_sokoban: U+2502/0-0-190
G_hwall_sokoban: U+2500/0-0-190
G_tlcorn_sokoban: U+250c/0-0-190
G_trcorn_sokoban: U+2510/0-0-190
G_blcorn_sokoban: U+2514/0-0-190
G_brcorn_sokoban: U+2518/0-0-190
G_crwall_sokoban: U+253C/0-0-190
G_tuwall_sokoban: U+2500/0-0-190
G_tdwall_sokoban: U+252C/0-0-190
G_tlwall_sokoban: U+2524/0-0-190
G_trwall_sokoban: U+251C/0-0-190
G_vwall_gehennom: U+2502/190-0-0
G_hwall_gehennom: U+2500/190-0-0
G_tlcorn_gehennom: U+250c/190-0-0
G_trcorn_gehennom: U+2510/190-0-0
G_blcorn_gehennom: U+2514/190-0-0
G_brcorn_gehennom: U+2518/190-0-0
G_crwall_gehennom: U+253C/190-0-0
G_tuwall_gehennom: U+2500/190-0-0
G_tdwall_gehennom: U+252C/190-0-0
G_tlwall_gehennom: U+2524/190-0-0
G_trwall_gehennom: U+251C/190-0-0
G_vwall_knox: U+2502/150-75-0
G_hwall_knox: U+2500/150-75-0
G_tlcorn_knox: U+250c/150-75-0
G_trcorn_knox: U+2510/150-75-0
G_blcorn_knox: U+2514/150-75-0
G_brcorn_knox: U+2518/150-75-0
G_crwall_knox: U+253C/150-75-0
G_tuwall_knox: U+2500/150-75-0
G_tdwall_knox: U+252C/150-75-0
G_tlwall_knox: U+2524/150-75-0
G_trwall_knox: U+251C/150-75-0
G_vwall_mines: U+2502/113-126-142
G_hwall_mines: U+2500/113-126-142
G_tlcorn_mines: U+250c/113-126-142
G_trcorn_mines: U+2510/113-126-142
G_blcorn_mines: U+2514/113-126-142
G_brcorn_mines: U+2518/113-126-142
G_crwall_mines: U+253C/113-126-142
G_tuwall_mines: U+2500/113-126-142
G_tdwall_mines: U+252C/113-126-142
G_tlwall_mines: U+2524/113-126-142
G_trwall_mines: U+251C/113-126-142
finish
# symbols EOF

View File

@@ -36,7 +36,7 @@
.ds f0 "\*(vr
.ds f1
.\"DO NOT REMOVE NH_DATESUB .ds f2 "DATE(%B %-d, %Y)
.ds f2 "February 27, 2022
.ds f2 "May 7, 2022
.
.\" A note on some special characters:
.\" \(lq = left double quote
@@ -5519,6 +5519,41 @@ So S_rock is only used for boulders and not used at all if
overridden by the more specific S_boulder.
.pg
.hn 2
Customizing Map Glyph Representations Using Unicode
.pg
If your platform or terminal supports the display of UTF-8 character
sequences, you can customize your game display by assigning Unicode
codepoint values and \fIred-green-blue\fP colors to glyph
representations. The customizations can be specified for use with a symset that
has a UTF8 handler within the symbols file such as the enhanced1 set, or
individually within your nethack.rc file.
.pg
The format for defining a glyph representation is:
.SD n
\f(CROPTIONS=glyph:glyphid\fIU+nnnn\fP/\fIR-G-B\fP\fP
.ED
.pg
The window port that is active needs to provide support for displaying
UTF-8 character sequences and explicit red-green-blue colors in order
for the glyph representation to be visible.
For example, the following line in your configuration file will cause
the glyph representation for glyphid G_pool to use Unicode codepoint
U+224B and the color represented by R-G-B value 0-0-160
.SD n
\f(CROPTIONS=glyph:G_pool/U+224B/0-0-160\fP
.ED
The list of acceptable glyphid's can be produced by
\fBnethack \-\-dumpglyphids\fP.
Individual NetHack glyphs can be specified using the G_ prefix,
or you can use an S_ symbol for a glyphid and store the custom
representation for all NetHack glyphs that would map to that
particular symbol.
You will need to select a symset with a UTF8 handler to enable the
display of the customizations, such as the Enhanced symset.
.pg
.hn 2
Configuring NetHack for Play by the Blind
.pg
NetHack can be set up to use only standard ASCII characters for making

View File

@@ -46,7 +46,7 @@
\author{Original version - Eric S. Raymond\\
(Edited and expanded for 3.7 by Mike Stephenson and others)}
%DO NOT REMOVE NH_DATESUB \date{DATE(%B %-d, %Y)}
\date{February 27, 2022}
\date{May 7, 2022}
\maketitle
@@ -6071,6 +6071,46 @@ version 3.6.0, statues are displayed as the monster they depict.
So S\verb+_+rock is only used for boulders and not used at all if
overridden by the more specific S\verb+_+boulder.
%.lp
%.hn 2
\subsection*{Customizing Map Glyph Representations Using Unicode}
%.pg
If your platform or terminal supports the display of UTF-8 character
sequences, you can customize your game display by assigning Unicode
codepoint values and red-green-blue colors to glyph
representations. The customizations can be specified for use with a symset that
has a UTF8 handler within the symbols file such as the enhanced1 set, or
individually within your own nethack.rc file.
The format for defining a glyph representation is:\\
\begin{verbatim}
OPTIONS=glyph:glyphid/U+nnnn/R-G-B
\end{verbatim}
The window port that is active needs to provide support for displaying UTF-8
character sequences and explicit 24-bit red-green-blue colors in order for the glyph
representation to be visible as specified.
For example, the following line in your configuration file will cause
the glyph representation for glyphid G_pool to use Unicode codepoint U+224B
and the color represented by R-G-B value 0-0-160:\\
\begin{verbatim}
OPTIONS=glyph:G_pool/U+224B/0-0-160
\end{verbatim}
The list of acceptable glyphid's can be produced by
\begin{verbatim}
nethack --glyphids
\end{verbatim}
Individual NetHack glyphs can be specified using the G\verb+_+ prefix,
or you can use an S\verb+_+ symbol for a glyphid and store the custom
representation for all NetHack glyphs that would map to that
particular symbol.
You will need to select a symset with a UTF8 handler to enable the
display of the customizations, such as the Enhanced symset.
%.pg
%.hn 2
\subsection*{Configuring {\it NetHack\/} for Play by the Blind}

View File

@@ -280,6 +280,15 @@
*/
/* #define NODUMPENUMS */
/*
* ENHANCED_SYMBOLS
* Support the enhanced display of symbols by utilizing utf8 and 24-bit
* color sequences. Enabled by default, but it can be disabled by
* commenting it out.
*/
#define ENHANCED_SYMBOLS
/*
* If COMPRESS is defined, it should contain the full path name of your
* 'compress' program.

View File

@@ -434,7 +434,10 @@ E const char *ARGV0;
enum earlyarg {ARG_DEBUG, ARG_VERSION, ARG_SHOWPATHS
#ifndef NODUMPENUMS
, ARG_DUMPENUMS
#ifdef ENHANCED_SYMBOLS
, ARG_DUMPGLYPHIDS
#endif
#endif /* NODUMPENUMS */
#ifdef WIN32
,ARG_WINDOWS
#endif
@@ -679,6 +682,11 @@ struct _cmd_queue {
struct _cmd_queue *next;
};
struct enum_dump {
int val;
const char *nm;
};
typedef long cmdcount_nht; /* Command counts */
/*
@@ -888,8 +896,11 @@ struct instance_globals {
struct rm nowhere;
const char *gate_str;
/* drawing */
/* symbols.c */
struct symsetentry symset[NUM_GRAPHICS];
#ifdef ENHANCED_SYMBOLS
struct symset_customization sym_customizations[NUM_GRAPHICS + 1]; /* adds UNICODESET */
#endif
int currentgraphics;
nhsym showsyms[SYM_MAX]; /* symbols to be displayed */
nhsym primary_syms[SYM_MAX]; /* loaded primary symbols */

View File

@@ -1047,6 +1047,9 @@ extern void nh_snprintf(const char *func, int line, char *str, size_t size,
extern int FITSint_(long long, const char *, int);
#define FITSuint(x) FITSuint_(x, __func__, __LINE__)
extern unsigned FITSuint_(unsigned long long, const char *, int);
#ifdef ENHANCED_SYMBOLS
extern int unicodeval_to_utf8str(int, uint8 *, size_t);
#endif
/* ### insight.c ### */
@@ -1281,6 +1284,9 @@ extern int buzzmu(struct monst *, struct attack *);
extern void runtime_info_init(void);
extern const char *do_runtime_info(int *);
extern void release_runtime_info(void);
#ifdef ENHANCED_SYMBOLS
extern void dump_glyphids(void);
#endif
/* ### mhitm.c ### */
@@ -1828,6 +1834,10 @@ extern void synch_cursor(void);
extern void nethack_enter_consoletty(void);
extern void consoletty_exit(void);
extern int set_keyhandling_via_option(void);
#ifdef ENHANCED_SYMBOLS
extern void tty_utf8graphics_fixup(void);
extern void tty_ibmgraphics_fixup(void);
#endif /* ENHANCED_SYMBOLS */
#endif /* WIN32 */
/* ### o_init.c ### */
@@ -1947,10 +1957,6 @@ extern void set_wc2_option_mod_status(unsigned long, int);
extern void set_option_mod_status(const char *, int);
extern int add_autopickup_exception(const char *);
extern void free_autopickup_exceptions(void);
extern int load_symset(const char *, int);
extern void free_symsets(void);
extern boolean parsesymbols(char *, int);
extern struct symparse *match_sym(char *);
extern void set_playmode(void);
extern int sym_val(const char *);
extern int query_color(const char *);
@@ -2623,11 +2629,25 @@ extern void init_rogue_symbols(void);
extern void init_ov_primary_symbols(void);
extern void init_ov_rogue_symbols(void);
extern void clear_symsetentry(int, boolean);
extern void update_primary_symset(struct symparse *, int);
extern void update_rogue_symset(struct symparse *, int);
extern void update_ov_primary_symset(struct symparse *, int);
extern void update_ov_rogue_symset(struct symparse *, int);
extern void update_primary_symset(const struct symparse *, int);
extern void update_rogue_symset(const struct symparse *, int);
extern void update_ov_primary_symset(const struct symparse *, int);
extern void update_ov_rogue_symset(const struct symparse *, int);
extern nhsym get_othersym(int, int);
extern boolean symset_is_compatible(enum symset_handling_types, unsigned long);
extern void set_symhandling(char *handling, int which_set);
extern boolean proc_symset_line(char *);
extern int do_symset(boolean);
extern int load_symset(const char *, int);
extern void free_symsets(void);
extern const struct symparse *match_sym(char *);
extern boolean parsesymbols(char *, int);
#ifdef ENHANCED_SYMBOLS
extern struct customization_detail *find_matching_symset_customization(
const char *symset_name, int custtype,
enum graphics_sets which_set);
extern void apply_customizations_to_symset(enum graphics_sets which_set);
#endif
/* ### sys.c ### */
@@ -2910,6 +2930,9 @@ extern void setftty(void);
extern void intron(void);
extern void introff(void);
extern void error (const char *, ...) PRINTF_F(1, 2);
#ifdef ENHANCED_SYMBOLS
extern void tty_utf8graphics_fixup(void);
#endif
#endif /* UNIX || __BEOS__ */
/* ### unixunix.c ### */
@@ -2939,6 +2962,24 @@ extern int hide_privileges(boolean);
#endif
#endif /* UNIX */
/* ### utf8map.c ### */
#ifdef ENHANCED_SYMBOLS
extern int glyphrep(const char *);
extern char *mixed_to_utf8(char *buf, size_t bufsz, const char *str, int *);
extern int match_glyph(char *);
extern void dump_all_glyphids(FILE *fp);
extern void fill_glyphid_cache(void);
extern void free_glyphid_cache(void);
extern boolean glyphid_cache_status(void);
extern int glyphrep_to_custom_map_entries(const char *op, int *glyph);
void free_all_glyphmap_u(void);
int add_custom_urep_entry(const char *symset_name, int glyphidx,
const uint8 *utf8str, long ucolor,
enum graphics_sets which_set);
int set_map_u(glyph_map *gm, const uint8 *utf8str, long ucolor);
#endif /* ENHANCED_SYMBOLS */
/* ### vault.c ### */
extern void newegd(struct monst *);
@@ -3191,6 +3232,7 @@ extern int has_color(int);
extern int glyph2ttychar(int);
extern int glyph2symidx(int);
extern char *encglyph(int);
extern int decode_glyph(const char *str, int *glyph_ptr);
extern char *decode_mixed(char *, const char *);
extern void genl_putmixed(winid, int, const char *);
extern boolean menuitem_invert_test(int, unsigned, boolean);

View File

@@ -237,6 +237,8 @@ struct instance_flags {
int menuinvertmode; /* 0 = invert toggles every item;
1 = invert skips 'all items' item */
int menu_headings; /* ATR for menu headings */
uint32_t colorcount; /* store how many colors terminal is capable of */
boolean use_truecolor; /* force use of truecolor */
#ifdef ALTMETA
boolean altmeta; /* Alt-c sends ESC c rather than M-c */
#endif
@@ -389,7 +391,7 @@ struct instance_flags {
Bitfield(save_uinwater, 1);
Bitfield(save_uburied, 1);
struct debug_flags debug;
boolean windowtype_locked; /* windowtype can't change from configfile */
boolean windowtype_locked; /* windowtype can't change from configfile */
boolean windowtype_deferred; /* pick a windowport and store it in
chosen_windowport[], but do not switch to
it in the midst of options processing */

View File

@@ -183,6 +183,7 @@ typedef struct {
#include "align.h"
#include "dungeon.h"
#include "wintype.h"
#include "sym.h"
#include "mkroom.h"
@@ -199,7 +200,6 @@ enum misc_arti_nums {
#include "objclass.h"
#include "youprop.h"
#include "wintype.h"
#include "context.h"
#include "rm.h"
#include "botl.h"

View File

@@ -218,6 +218,8 @@ opt_##a,
&iflags.wc2_fullscreen)
NHOPTC(gender, 8, opt_in, set_gameview, No, Yes, No, No, NoAlias,
"your starting gender (male or female)")
NHOPTC(glyph, 40, opt_in, set_in_game, No, Yes, Yes, No, NoAlias,
"set representation of a glyph to a unicode value and color")
NHOPTB(goldX, 0, opt_in, set_in_game, Off, Yes, No, No, NoAlias,
&flags.goldX)
NHOPTB(guicolor, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
@@ -521,6 +523,8 @@ opt_##a,
&iflags.wc2_darkgray)
NHOPTB(use_inverse, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
&iflags.wc_inverse)
NHOPTB(use_truecolor, 0, opt_in, set_in_config, Off, Yes, No, No,
"use_truecolour", &iflags.use_truecolor)
NHOPTC(vary_msgcount, 20, opt_in, set_gameview, No, Yes, No, No, NoAlias,
"show more old messages at a time")
NHOPTB(verbose, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,

View File

@@ -25,7 +25,6 @@ enum mon_syms {
};
#ifndef MAKEDEFS_C
/* Default characters for dungeon surroundings and furniture */
enum cmap_symbols {
#define PCHAR_S_ENUM
@@ -34,6 +33,22 @@ enum cmap_symbols {
MAXPCHARS
};
/*
* special symbol set handling types ( for invoking callbacks, etc.)
* Must match the order of the known_handlers strings
* in drawing.c
*/
enum symset_handling_types {
H_UNK = 0,
H_IBM = 1,
H_DEC = 2,
H_CURS = 3,
H_MAC = 4, /* obsolete; needed so that the listing of available
* symsets by 'O' can skip it for !MAC_GRAPHICS_ENV */
H_UTF8 = 5
};
struct symdef {
uchar sym;
const char *explanation;
@@ -51,7 +66,7 @@ enum symparse_range {
};
struct symparse {
unsigned range;
enum symparse_range range;
int idx;
const char *name;
};
@@ -62,7 +77,7 @@ struct symsetentry {
char *name; /* ptr to symset name */
char *desc; /* ptr to description */
int idx; /* an index value */
int handling; /* known handlers value */
enum symset_handling_types handling; /* known handlers value */
Bitfield(nocolor, 1); /* don't use color if set */
Bitfield(primary, 1); /* restricted for use as primary set */
Bitfield(rogue, 1); /* restricted for use as rogue lev set */
@@ -109,25 +124,41 @@ enum misc_symbols {
*/
#define DEFAULT_GRAPHICS 0 /* regular characters: '-', '+', &c */
enum graphics_sets {
PRIMARY = 0, /* primary graphics set */
PRIMARYSET = 0, /* primary graphics set */
ROGUESET = 1, /* rogue graphics set */
NUM_GRAPHICS
NUM_GRAPHICS,
UNICODESET = NUM_GRAPHICS
};
/*
* special symbol set handling types ( for invoking callbacks, etc.)
* Must match the order of the known_handlers strings
* in drawing.c
*/
#ifdef ENHANCED_SYMBOLS
enum customization_types { custom_none, custom_symbols, custom_ureps };
enum symset_handling_types {
H_UNK = 0,
H_IBM = 1,
H_DEC = 2,
H_CURS = 3,
H_MAC = 4 /* obsolete; needed so that the listing of available
* symsets by 'O' can skip it for !MAC_GRAPHICS_ENV */
struct custom_symbol {
const struct symparse *symparse;
unsigned char val;
};
struct custom_urep {
int glyphidx;
struct unicode_representation u;
};
union customization_content {
struct custom_symbol sym;
struct custom_urep urep;
};
struct customization_detail {
union customization_content content;
struct customization_detail *next;
};
/* one set per symset_name */
struct symset_customization {
const char *customization_name;
int count;
int custtype;
struct customization_detail *details;
};
#endif /* ENHANCED_SYMBOLS */
extern const struct symdef defsyms[MAXPCHARS]; /* defaults */
#define WARNCOUNT 6 /* number of different warning levels */

View File

@@ -127,8 +127,14 @@ extern void curses_refresh_nethack_windows(void);
extern void curses_del_nhwin(winid wid);
extern void curses_del_wid(winid wid);
extern void curs_destroy_all_wins(void);
#ifdef ENHANCED_SYMBOLS
extern void curses_putch(winid wid, int x, int y, int ch,
int color, int attrs);
struct unicode_representation *u, int color,
int attrs);
#else
extern void curses_putch(winid wid, int x, int y, int ch, int color,
int attrs);
#endif
extern void curses_get_window_size(winid wid, int *height, int *width);
extern boolean curses_window_has_border(winid wid);
extern boolean curses_window_exists(winid wid);

View File

@@ -231,8 +231,10 @@ extern
* via non-display attribute flag */
#define WC2_SUPPRESS_HIST 0x8000L /* 16 putstr(WIN_MESSAGE) supports history
* suppression via non-disp attr */
#define WC2_MENU_SHIFT 0x010000L /* 17 horizontal menu scrolling */
/* 15 free bits */
#define WC2_MENU_SHIFT 0x010000L /* 17 horizontal menu scrolling */
#define WC2_U_UTF8STR 0x020000L /* 18 utf8str support */
#define WC2_U_24BITCOLOR 0x040000L /* 19 24-bit color support available */
/* 13 free bits */
#define ALIGN_LEFT 1
#define ALIGN_RIGHT 2

View File

@@ -78,6 +78,7 @@ struct DisplayDesc {
int intr; /* non-zero if inread was interrupted */
winid lastwin; /* last window used for I/O */
char dismiss_more; /* extra character accepted at --More-- */
int topl_utf8; /* non-zero if utf8 in str */
};
#endif /* WINDOW_STRUCTS */
@@ -165,6 +166,10 @@ E void term_end_raw_bold(void);
E void term_end_color(void);
E void term_start_color(int color);
#endif /* TEXTCOLOR */
#ifdef ENHANCED_SYMBOLS
extern void term_start_24bitcolor(struct unicode_representation *);
extern void term_end_24bitcolor(void); /* termcap.c, consoletty.c */
#endif
/* ### topl.c ### */
@@ -182,6 +187,11 @@ E void setclipped(void);
E void docorner(int, int);
E void end_glyphout(void);
E void g_putch(int);
#ifdef ENHANCED_SYMBOLS
#if defined(WIN32) || defined(UNIX)
E void g_pututf8(uint8 *);
#endif
#endif /* ENHANCED_SYMBOLS */
E void win_tty_init(int);
/* external declarations */
@@ -200,6 +210,7 @@ E void tty_dismiss_nhwindow(winid);
E void tty_destroy_nhwindow(winid);
E void tty_curs(winid, int, int);
E void tty_putstr(winid, int, const char *);
E void tty_putmixed(winid window, int attr, const char *str);
E void tty_display_file(const char *, boolean);
E void tty_start_menu(winid, unsigned long);
E void tty_add_menu(winid, const glyph_info *, const ANY_P *, char, char,

View File

@@ -5,6 +5,8 @@
#ifndef WINTYPE_H
#define WINTYPE_H
#include "integer.h"
typedef int winid; /* a window identifier */
/* generic parameter - must not be any larger than a pointer */
@@ -60,15 +62,28 @@ typedef struct mi {
} menu_item;
#define MENU_ITEM_P struct mi
/* These would be in display.h if they weren't needed to define
the windowproc interface for X11 which doesn't seem to include
the main NetHack header files */
/* These would be in sym.h and display.h if they weren't needed to
define the windowproc interface for X11 which doesn't include
most of the main NetHack header files */
typedef struct glyph_map_entry {
struct classic_representation {
int color;
int symidx;
};
struct unicode_representation {
uint32 ucolor;
uint16 u256coloridx;
uint8 *utf8str;
};
typedef struct glyph_map_entry {
unsigned glyphflags;
struct classic_representation sym;
short int tileidx;
#ifdef ENHANCED_SYMBOLS
struct unicode_representation *u;
#endif
} glyph_map;
/* glyph plus additional info

View File

@@ -829,7 +829,10 @@ static const struct early_opt earlyopts[] = {
{ARG_SHOWPATHS, "showpaths", 9, FALSE},
#ifndef NODUMPENUMS
{ARG_DUMPENUMS, "dumpenums", 9, FALSE},
#ifdef ENHANCED_SYMBOLS
{ARG_DUMPGLYPHIDS, "dumpglyphids", 12, FALSE},
#endif
#endif /* NODUMPENUMS */
#ifdef WIN32
{ARG_WINDOWS, "windows", 4, TRUE},
#endif
@@ -913,7 +916,13 @@ argcheck(int argc, char *argv[], enum earlyarg e_arg)
dump_enums();
return 2;
}
#ifdef ENHANCED_SYMBOLS
case ARG_DUMPGLYPHIDS: {
dump_glyphids();
return 2;
}
#endif
#endif /* NODUMPENUMS */
#ifdef WIN32
case ARG_WINDOWS: {
if (extended_opt) {
@@ -1006,6 +1015,17 @@ timet_delta(time_t etim, time_t stim) /* end and start times */
}
#ifndef NODUMPENUMS
#define DUMP_ENUMS
struct enum_dump monsdump[] = {
#include "monsters.h"
{ NUMMONS, "NUMMONS" },
};
struct enum_dump objdump[] = {
#include "objects.h"
{ NUM_OBJECTS, "NUM_OBJECTS" },
};
#undef DUMP_ENUMS
void
dump_enums(void)
{
@@ -1018,21 +1038,6 @@ dump_enums(void)
};
static const char *const titles[NUM_ENUM_DUMPS] =
{ "monnums", "objects_nums" , "misc_object_nums" };
struct enum_dump {
int val;
const char *nm;
};
#define DUMP_ENUMS
struct enum_dump monsdump[] = {
#include "monsters.h"
{ NUMMONS, "NUMMONS" },
};
struct enum_dump objdump[] = {
#include "objects.h"
{ NUM_OBJECTS, "NUM_OBJECTS" },
};
#undef DUMP_ENUMS
struct enum_dump omdump[] = {
{ LAST_GEM, "LAST_GEM" },
@@ -1058,6 +1063,14 @@ dump_enums(void)
}
raw_print("");
}
#ifdef ENHANCED_SYMBOLS
void
dump_glyphids(void)
{
dump_all_glyphids(stdout);
}
#endif /* ENHANCED_SYMBOLS */
#endif /* NODUMPENUMS */
/*allmain.c*/

View File

@@ -373,9 +373,12 @@ const struct instance_globals g_init = {
UNDEFINED_VALUES, /* nowhere */
UNDEFINED_PTR, /* gate_str */
/* drawing.c */
/* symbols.c */
DUMMY, /* symset */
0, /* currentgraphics */
#ifdef ENHANCED_SYMBOLS
DUMMY, /* symset_customizations */
#endif
0, /* currentgraphics */
DUMMY, /* showsyms */
DUMMY, /* primary_syms */
DUMMY, /* rogue_syms */

View File

@@ -1363,9 +1363,14 @@ see_traps(void)
}
}
/* glyph, ttychar, {color, symidx, glyphflags, tileidx } */
/* glyph, ttychar, { glyphflags, { sym.color, sym.symidx },
tileidx, u } */
static glyph_info no_ginfo = {
NO_GLYPH, ' ', { NO_COLOR, 0, MG_BADXY, 0 }
NO_GLYPH, ' ', { MG_BADXY, { NO_COLOR, 0 }, 0
#ifdef ENHANCED_SYMBOLS
, 0
#endif
}
};
#ifndef UNBUFFERED_GLYPHINFO
#define Glyphinfo_at(x, y, glyph) \
@@ -1379,12 +1384,17 @@ static glyph_info ginfo;
#ifdef USE_TILES
extern const glyph_info nul_glyphinfo; /* tile.c */
#else
/* glyph, ttychar, { color, symidx, glyphflags, tileidx} */
/* glyph, ttychar, { glyphflags, { sym.color, sym.symidx },
tileidx, 0} */
const glyph_info nul_glyphinfo = {
NO_GLYPH, ' ',
{ /* glyph_map */
NO_COLOR, SYM_UNEXPLORED + SYM_OFF_X,
MG_UNEXPL, 0
MG_UNEXPL,
{ NO_COLOR, SYM_UNEXPLORED + SYM_OFF_X },
0
#ifdef ENHANCED_SYMBOLS
, 0
#endif
}
};
#endif
@@ -1393,7 +1403,7 @@ const glyph_info nul_glyphinfo = {
extern glyph_map glyphmap[MAX_GLYPH]; /* from tile.c */
#else
glyph_map glyphmap[MAX_GLYPH] = {
{0, 0, 0U, 0 }
{ 0U, { 0, 0}, 0, 0 }
};
#endif
@@ -1686,7 +1696,7 @@ show_glyph(int x, int y, int glyph)
be thorough and check everything */
|| g.gbuf[y][x].glyphinfo.ttychar != glyphinfo.ttychar
|| g.gbuf[y][x].glyphinfo.gm.glyphflags != glyphinfo.gm.glyphflags
|| g.gbuf[y][x].glyphinfo.gm.color != glyphinfo.gm.color
|| g.gbuf[y][x].glyphinfo.gm.sym.color != glyphinfo.gm.sym.color
|| g.gbuf[y][x].glyphinfo.gm.tileidx != glyphinfo.gm.tileidx
#endif
|| iflags.use_background_glyph) {
@@ -1721,7 +1731,12 @@ show_glyph(int x, int y, int glyph)
static gbuf_entry nul_gbuf = {
0, /* gnew */
{ GLYPH_UNEXPLORED, (unsigned) ' ', /* glyphinfo.glyph */
{ (unsigned) NO_COLOR, 0, MG_UNEXPL, 0 } /* glyphinfo.gm */
/* glyphinfo.gm */
{ MG_UNEXPL, { (unsigned) NO_COLOR, 0 }, 0
#ifdef ENHANCED_SYMBOLS
, 0
#endif
}
}
};
@@ -1743,13 +1758,13 @@ clear_glyph_buffer(void)
#endif
#ifndef UNBUFFERED_GLYPHINFO
nul_gbuf.gnew = (giptr->ttychar != nul_gbuf.glyphinfo.ttychar
|| giptr->gm.color != nul_gbuf.glyphinfo.gm.color
|| giptr->gm.sym.color != nul_gbuf.glyphinfo.gm.sym.color
|| giptr->gm.glyphflags
!= nul_gbuf.glyphinfo.gm.glyphflags
|| giptr->gm.tileidx != nul_gbuf.glyphinfo.gm.tileidx)
#else
nul_gbuf.gnew = (giptr->glyphinfo.ttychar != ' '
|| giptr->gm.color != NO_COLOR
|| giptr->gm.sym.color != NO_COLOR
|| (giptr->gm.glyphflags & ~MG_UNEXPL) != 0)
#endif
? 1 : 0;
@@ -1782,12 +1797,12 @@ row_refresh(int start, int stop, int y)
#endif
#ifndef UNBUFFERED_GLYPHINFO
force = (giptr->ttychar != nul_gbuf.glyphinfo.ttychar
|| giptr->gm.color != nul_gbuf.glyphinfo.gm.color
|| giptr->gm.sym.color != nul_gbuf.glyphinfo.gm.sym.color
|| giptr->gm.glyphflags != nul_gbuf.glyphinfo.gm.glyphflags
|| giptr->gm.tileidx != nul_gbuf.glyphinfo.gm.tileidx)
#else
force = (giptr->ttychar != ' '
|| giptr->gm.color != NO_COLOR
|| giptr->gm.sym.color != NO_COLOR
|| (giptr->gm.glyphflags & ~MG_UNEXPL) != 0)
#endif
? 1 : 0;
@@ -2193,7 +2208,7 @@ map_glyphinfo(
&& glyph_is_monster(glyph));
const glyph_map *gmap = &glyphmap[glyph];
glyphinfo->gm = *gmap; /* glyphflags, symidx, color, tileidx */
glyphinfo->gm = *gmap; /* glyphflags, sym.symidx, sym.color, tileidx */
/*
* Only hero tinkering permitted on-the-fly (who).
* Unique glyphs in glyphmap[] determine everything else (what).
@@ -2210,12 +2225,12 @@ map_glyphinfo(
} else if (HAS_ROGUE_IBM_GRAPHICS
&& g.symset[g.currentgraphics].nocolor == 0) {
/* actually player should be yellow-on-gray if in corridor */
glyphinfo->gm.color = CLR_YELLOW;
glyphinfo->gm.sym.color = CLR_YELLOW;
} else if (flags.showrace) {
/* for showrace, non-human hero is displayed by the symbol of
corresponding type of monster rather than by '@' (handled
by newsym()); we change the color to same as human hero */
glyphinfo->gm.color = HI_DOMESTIC;
glyphinfo->gm.sym.color = HI_DOMESTIC;
}
#endif
/* accessibility
@@ -2227,7 +2242,7 @@ map_glyphinfo(
if ((g.glyphmap_perlevel_flags & GMAP_ROGUELEVEL)
? g.ov_rogue_syms[offset]
: g.ov_primary_syms[offset])
glyphinfo->gm.symidx = offset;
glyphinfo->gm.sym.symidx = offset;
}
glyphinfo->gm.glyphflags |= MG_HERO;
}
@@ -2235,9 +2250,9 @@ map_glyphinfo(
&& (mgflags & MG_FLAG_NOOVERRIDE) && glyph_is_pet(glyph)) {
/* one more accessiblity kludge;
turn off override symbol if caller has specfieid NOOVERRIDE */
glyphinfo->gm.symidx = mons[glyph_to_mon(glyph)].mlet + SYM_OFF_M;
glyphinfo->gm.sym.symidx = mons[glyph_to_mon(glyph)].mlet + SYM_OFF_M;
}
glyphinfo->ttychar = g.showsyms[glyphinfo->gm.symidx];
glyphinfo->ttychar = g.showsyms[glyphinfo->gm.sym.symidx];
glyphinfo->glyph = glyph;
}
@@ -2382,38 +2397,38 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
* offsets. The order is set in display.h.
*/
if ((offset = (glyph - GLYPH_NOTHING_OFF)) >= 0) {
gmap->symidx = SYM_NOTHING + SYM_OFF_X;
gmap->sym.symidx = SYM_NOTHING + SYM_OFF_X;
color = NO_COLOR;
gmap->glyphflags |= MG_NOTHING;
} else if ((offset = (glyph - GLYPH_UNEXPLORED_OFF)) >= 0) {
gmap->symidx = SYM_UNEXPLORED + SYM_OFF_X;
gmap->sym.symidx = SYM_UNEXPLORED + SYM_OFF_X;
color = NO_COLOR;
gmap->glyphflags |= MG_UNEXPL;
} else if ((offset = (glyph - GLYPH_STATUE_FEM_PILETOP_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = CLR_RED;
else
obj_color(STATUE);
gmap->glyphflags |= (MG_STATUE | MG_FEMALE | MG_OBJPILE);
} else if ((offset = (glyph - GLYPH_STATUE_MALE_PILETOP_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = CLR_RED;
else
obj_color(STATUE);
gmap->glyphflags |= (MG_STATUE | MG_MALE | MG_OBJPILE);
} else if ((offset = (glyph - GLYPH_BODY_PILETOP_OFF)) >= 0) {
gmap->symidx = objects[CORPSE].oc_class + SYM_OFF_O;
gmap->sym.symidx = objects[CORPSE].oc_class + SYM_OFF_O;
if (has_rogue_color)
color = CLR_RED;
else
mon_color(offset);
gmap->glyphflags |= (MG_CORPSE | MG_OBJPILE);
} else if ((offset = (glyph - GLYPH_OBJ_PILETOP_OFF)) >= 0) {
gmap->symidx = objects[offset].oc_class + SYM_OFF_O;
gmap->sym.symidx = objects[offset].oc_class + SYM_OFF_O;
if (offset == BOULDER)
gmap->symidx = SYM_BOULDER + SYM_OFF_X;
gmap->sym.symidx = SYM_BOULDER + SYM_OFF_X;
if (has_rogue_color) {
switch (objects[offset].oc_class) {
case COIN_CLASS:
@@ -2430,14 +2445,14 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
obj_color(offset);
gmap->glyphflags |= MG_OBJPILE;
} else if ((offset = (glyph - GLYPH_STATUE_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = CLR_RED;
else
obj_color(STATUE);
gmap->glyphflags |= (MG_STATUE | MG_FEMALE);
} else if ((offset = (glyph - GLYPH_STATUE_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = CLR_RED;
else
@@ -2445,70 +2460,70 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
gmap->glyphflags |= (MG_STATUE | MG_MALE);
} else if ((offset = (glyph - GLYPH_WARNING_OFF))
>= 0) { /* warn flash */
gmap->symidx = offset + SYM_OFF_W;
gmap->sym.symidx = offset + SYM_OFF_W;
if (has_rogue_color)
color = NO_COLOR;
else
warn_color(offset);
} else if ((offset = (glyph - GLYPH_EXPLODE_FROSTY_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_frosty);
} else if ((offset = (glyph - GLYPH_EXPLODE_FIERY_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_fiery);
} else if ((offset = (glyph - GLYPH_EXPLODE_MAGICAL_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_magical);
} else if ((offset = (glyph - GLYPH_EXPLODE_WET_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_wet);
} else if ((offset = (glyph - GLYPH_EXPLODE_MUDDY_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_muddy);
} else if ((offset = (glyph - GLYPH_EXPLODE_NOXIOUS_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_noxious);
} else if ((offset = (glyph - GLYPH_EXPLODE_DARK_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_dark);
} else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) {
/* see swallow_to_glyph() in display.c */
gmap->symidx = (S_sw_tl + (offset & 0x7)) + SYM_OFF_P;
gmap->sym.symidx = (S_sw_tl + (offset & 0x7)) + SYM_OFF_P;
if (has_rogue_color)
color = NO_COLOR;
else
mon_color(offset >> 3);
} else if ((offset = (glyph - GLYPH_CMAP_C_OFF)) >= 0) {
gmap->symidx = S_digbeam + offset + SYM_OFF_P;
gmap->sym.symidx = S_digbeam + offset + SYM_OFF_P;
if (has_rogue_color)
color = cmap_to_roguecolor(S_digbeam + offset);
else
cmap_color(S_digbeam + offset);
} else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) {
/* see zapdir_to_glyph() in display.c */
gmap->symidx = (S_vbeam + (offset & 0x3)) + SYM_OFF_P;
gmap->sym.symidx = (S_vbeam + (offset & 0x3)) + SYM_OFF_P;
if (has_rogue_color)
color = NO_COLOR;
else
zap_color((offset >> 2));
} else if ((offset = (glyph - GLYPH_CMAP_B_OFF)) >= 0) {
int cmap = S_grave + offset;
gmap->symidx = cmap + SYM_OFF_P;
gmap->sym.symidx = cmap + SYM_OFF_P;
cmap_color(cmap);
if (!iflags.use_color) {
/* try to provide a visible difference between water and lava
if they use the same symbol and color is disabled */
if (cmap == S_lava
&& (g.showsyms[gmap->symidx]
&& (g.showsyms[gmap->sym.symidx]
== g.showsyms[S_pool + SYM_OFF_P]
|| g.showsyms[gmap->symidx]
|| g.showsyms[gmap->sym.symidx]
== g.showsyms[S_water + SYM_OFF_P])) {
gmap->glyphflags |= MG_BW_LAVA;
/* similar for floor [what about empty doorway?] and ice */
} else if (offset == S_ice
&& (g.showsyms[gmap->symidx]
&& (g.showsyms[gmap->sym.symidx]
== g.showsyms[S_room + SYM_OFF_P]
|| g.showsyms[gmap->symidx]
|| g.showsyms[gmap->sym.symidx]
== g.showsyms[S_darkroom
+ SYM_OFF_P])) {
gmap->glyphflags |= MG_BW_ICE;
@@ -2518,14 +2533,14 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
}
} else if ((offset = (glyph - GLYPH_ALTAR_OFF)) >= 0) {
/* unaligned, chaotic, neutral, lawful, other altar */
gmap->symidx = S_altar + SYM_OFF_P;
gmap->sym.symidx = S_altar + SYM_OFF_P;
if (has_rogue_color)
color = cmap_to_roguecolor(S_altar);
else
altar_color(offset);
} else if ((offset = (glyph - GLYPH_CMAP_A_OFF)) >= 0) {
int cmap = S_ndoor + offset;
gmap->symidx = cmap + SYM_OFF_P;
gmap->sym.symidx = cmap + SYM_OFF_P;
cmap_color(cmap);
/*
* Some speciality color mappings not hardcoded in data init
@@ -2536,36 +2551,36 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
/* provide a visible difference if normal and lit corridor
use the same symbol */
} else if ((cmap == S_litcorr)
&& g.showsyms[gmap->symidx]
&& g.showsyms[gmap->sym.symidx]
== g.showsyms[S_corr + SYM_OFF_P]) {
color = CLR_WHITE;
#endif
}
} else if ((offset = (glyph - GLYPH_CMAP_SOKO_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
wall_color(sokoban_walls);
} else if ((offset = (glyph - GLYPH_CMAP_KNOX_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
wall_color(knox_walls);
} else if ((offset = (glyph - GLYPH_CMAP_GEH_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
wall_color(gehennom_walls);
} else if ((offset = (glyph - GLYPH_CMAP_MINES_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
wall_color(mines_walls);
} else if ((offset = (glyph - GLYPH_CMAP_MAIN_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
if (has_rogue_color)
color = cmap_to_roguecolor(S_vwall + offset);
else
wall_color(main_walls);
} else if ((offset = (glyph - GLYPH_CMAP_STONE_OFF)) >= 0) {
gmap->symidx = SYM_OFF_P;
gmap->sym.symidx = SYM_OFF_P;
cmap_color(S_stone);
} else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) {
gmap->symidx = objects[offset].oc_class + SYM_OFF_O;
gmap->sym.symidx = objects[offset].oc_class + SYM_OFF_O;
if (offset == BOULDER)
gmap->symidx = SYM_BOULDER + SYM_OFF_X;
gmap->sym.symidx = SYM_BOULDER + SYM_OFF_X;
if (has_rogue_color) {
switch (objects[offset].oc_class) {
case COIN_CLASS:
@@ -2581,7 +2596,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
} else
obj_color(offset);
} else if ((offset = (glyph - GLYPH_RIDDEN_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
/* This currently implies that the hero is here -- monsters */
/* don't ride (yet...). Should we set it to yellow like in */
@@ -2592,21 +2607,21 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
mon_color(offset);
gmap->glyphflags |= (MG_RIDDEN | MG_FEMALE);
} else if ((offset = (glyph - GLYPH_RIDDEN_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
mon_color(offset);
gmap->glyphflags |= (MG_RIDDEN | MG_MALE);
} else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) {
gmap->symidx = objects[CORPSE].oc_class + SYM_OFF_O;
gmap->sym.symidx = objects[CORPSE].oc_class + SYM_OFF_O;
if (has_rogue_color)
color = CLR_RED;
else
mon_color(offset);
gmap->glyphflags |= MG_CORPSE;
} else if ((offset = (glyph - GLYPH_DETECT_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
@@ -2615,7 +2630,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
/* is_reverse = TRUE; */
gmap->glyphflags |= (MG_DETECT | MG_FEMALE);
} else if ((offset = (glyph - GLYPH_DETECT_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
@@ -2624,28 +2639,28 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
/* is_reverse = TRUE; */
gmap->glyphflags |= (MG_DETECT | MG_MALE);
} else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) {
gmap->symidx = SYM_INVISIBLE + SYM_OFF_X;
gmap->sym.symidx = SYM_INVISIBLE + SYM_OFF_X;
if (has_rogue_color)
color = NO_COLOR;
else
invis_color(offset);
gmap->glyphflags |= MG_INVIS;
} else if ((offset = (glyph - GLYPH_PET_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
pet_color(offset);
gmap->glyphflags |= (MG_PET | MG_FEMALE);
} else if ((offset = (glyph - GLYPH_PET_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
pet_color(offset);
gmap->glyphflags |= (MG_PET | MG_MALE);
} else if ((offset = (glyph - GLYPH_MON_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color) {
color = NO_COLOR;
} else {
@@ -2653,7 +2668,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
}
gmap->glyphflags |= MG_FEMALE;
} else if ((offset = (glyph - GLYPH_MON_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color) {
color = CLR_YELLOW;
} else {
@@ -2669,7 +2684,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
: g.ov_primary_syms[SYM_PET_OVERRIDE + SYM_OFF_X]);
if (g.showsyms[pet_override] != ' ')
gmap->symidx = SYM_PET_OVERRIDE + SYM_OFF_X;
gmap->sym.symidx = SYM_PET_OVERRIDE + SYM_OFF_X;
}
#ifdef TEXTCOLOR
/* Turn off color if no color defined, or rogue level w/o PC graphics.
@@ -2679,7 +2694,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
&& !has_rogue_color)) || !iflags.use_color)
#endif
color = NO_COLOR;
gmap->color = color;
gmap->sym.color = color;
}
}

View File

@@ -1455,7 +1455,7 @@ goto_level(
}
if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARY);
assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARYSET);
check_gold_symbol();
/* record this level transition as a potential seen branch unless using
* some non-standard means of transportation (level teleport).

View File

@@ -6,6 +6,7 @@
#include "color.h"
#include "rm.h"
#include "objclass.h"
#include "wintype.h"
#include "sym.h"
/* Relevant header information in rm.h, objclass.h, sym.h, defsym.h. */

View File

@@ -165,8 +165,6 @@ static void wizkit_addinv(struct obj *);
boolean proc_wizkit_line(char *buf);
void read_wizkit(void);
static FILE *fopen_sym_file(void);
boolean proc_symset_line(char *);
static void set_symhandling(char *, int);
#ifdef SELF_RECOVER
static boolean copy_bytes(int, int);
@@ -2678,7 +2676,7 @@ parse_config_line(char *origbuf)
}
switch_symbols(TRUE);
} else if (match_varname(buf, "SYMBOLS", 4)) {
if (!parsesymbols(bufp, PRIMARY)) {
if (!parsesymbols(bufp, PRIMARYSET)) {
config_error_add("Error in SYMBOLS definition '%s'", bufp);
retval = FALSE;
}
@@ -3443,7 +3441,7 @@ fopen_sym_file(void)
}
/*
* Returns 1 if the chose symset was found and loaded.
* Returns 1 if the chosen symset was found and loaded.
* 0 if it wasn't found in the sym file or other problem.
*/
int
@@ -3492,214 +3490,6 @@ read_sym_file(int which_set)
return 1;
}
boolean
proc_symset_line(char *buf)
{
return !((boolean) parse_sym_line(buf, g.symset_which_set));
}
/* returns 0 on error */
int
parse_sym_line(char *buf, int which_set)
{
int val, i;
struct symparse *symp;
char *bufp, *commentp, *altp;
if (strlen(buf) >= BUFSZ)
buf[BUFSZ - 1] = '\0';
/* convert each instance of whitespace (tabs, consecutive spaces)
into a single space; leading and trailing spaces are stripped */
mungspaces(buf);
/* remove trailing comment, if any (this isn't strictly needed for
individual symbols, and it won't matter if "X#comment" without
separating space slips through; for handling or set description,
symbol set creator is responsible for preceding '#' with a space
and that comment itself doesn't contain " #") */
if ((commentp = rindex(buf, '#')) != 0 && commentp[-1] == ' ')
commentp[-1] = '\0';
/* find the '=' or ':' */
bufp = index(buf, '=');
altp = index(buf, ':');
if (!bufp || (altp && altp < bufp))
bufp = altp;
if (!bufp) {
if (strncmpi(buf, "finish", 6) == 0) {
/* end current graphics set */
if (g.chosen_symset_start)
g.chosen_symset_end = TRUE;
g.chosen_symset_start = FALSE;
return 1;
}
config_error_add("No \"finish\"");
return 0;
}
/* skip '=' and space which follows, if any */
++bufp;
if (*bufp == ' ')
++bufp;
symp = match_sym(buf);
if (!symp) {
config_error_add("Unknown sym keyword");
return 0;
}
if (!g.symset[which_set].name) {
/* A null symset name indicates that we're just
building a pick-list of possible symset
values from the file, so only do that */
if (symp->range == SYM_CONTROL) {
struct symsetentry *tmpsp, *lastsp;
for (lastsp = g.symset_list; lastsp; lastsp = lastsp->next)
if (!lastsp->next)
break;
switch (symp->idx) {
case 0:
tmpsp = (struct symsetentry *) alloc(sizeof *tmpsp);
tmpsp->next = (struct symsetentry *) 0;
if (!lastsp)
g.symset_list = tmpsp;
else
lastsp->next = tmpsp;
tmpsp->idx = g.symset_count++;
tmpsp->name = dupstr(bufp);
tmpsp->desc = (char *) 0;
tmpsp->handling = H_UNK;
/* initialize restriction bits */
tmpsp->nocolor = 0;
tmpsp->primary = 0;
tmpsp->rogue = 0;
break;
case 2:
/* handler type identified */
tmpsp = lastsp; /* most recent symset */
for (i = 0; known_handling[i]; ++i)
if (!strcmpi(known_handling[i], bufp)) {
tmpsp->handling = i;
break; /* for loop */
}
break;
case 3:
/* description:something */
tmpsp = lastsp; /* most recent symset */
if (tmpsp && !tmpsp->desc)
tmpsp->desc = dupstr(bufp);
break;
case 5:
/* restrictions: xxxx*/
tmpsp = lastsp; /* most recent symset */
for (i = 0; known_restrictions[i]; ++i) {
if (!strcmpi(known_restrictions[i], bufp)) {
switch (i) {
case 0:
tmpsp->primary = 1;
break;
case 1:
tmpsp->rogue = 1;
break;
}
break; /* while loop */
}
}
break;
}
}
return 1;
}
if (symp->range) {
if (symp->range == SYM_CONTROL) {
switch (symp->idx) {
case 0:
/* start of symset */
if (!strcmpi(bufp, g.symset[which_set].name)) {
/* matches desired one */
g.chosen_symset_start = TRUE;
/* these init_*() functions clear symset fields too */
if (which_set == ROGUESET)
init_rogue_symbols();
else if (which_set == PRIMARY)
init_primary_symbols();
}
break;
case 1:
/* finish symset */
if (g.chosen_symset_start)
g.chosen_symset_end = TRUE;
g.chosen_symset_start = FALSE;
break;
case 2:
/* handler type identified */
if (g.chosen_symset_start)
set_symhandling(bufp, which_set);
break;
/* case 3: (description) is ignored here */
case 4: /* color:off */
if (g.chosen_symset_start) {
if (bufp) {
if (!strcmpi(bufp, "true") || !strcmpi(bufp, "yes")
|| !strcmpi(bufp, "on"))
g.symset[which_set].nocolor = 0;
else if (!strcmpi(bufp, "false")
|| !strcmpi(bufp, "no")
|| !strcmpi(bufp, "off"))
g.symset[which_set].nocolor = 1;
}
}
break;
case 5: /* restrictions: xxxx*/
if (g.chosen_symset_start) {
int n = 0;
while (known_restrictions[n]) {
if (!strcmpi(known_restrictions[n], bufp)) {
switch (n) {
case 0:
g.symset[which_set].primary = 1;
break;
case 1:
g.symset[which_set].rogue = 1;
break;
}
break; /* while loop */
}
n++;
}
}
break;
}
} else { /* !SYM_CONTROL */
val = sym_val(bufp);
if (g.chosen_symset_start) {
if (which_set == PRIMARY) {
update_primary_symset(symp, val);
} else if (which_set == ROGUESET) {
update_rogue_symset(symp, val);
}
}
}
}
return 1;
}
static void
set_symhandling(char *handling, int which_set)
{
int i = 0;
g.symset[which_set].handling = H_UNK;
while (known_handling[i]) {
if (!strcmpi(known_handling[i], handling)) {
g.symset[which_set].handling = i;
return;
}
i++;
}
}
/* ---------- END SYMSET FILE HANDLING ----------- */
/* ---------- BEGIN SCOREBOARD CREATION ----------- */

View File

@@ -1378,4 +1378,49 @@ FITSuint_(unsigned long long i, const char *file, int line){
return (unsigned)i;
}
#ifdef ENHANCED_SYMBOLS
/* Unicode routines */
int
unicodeval_to_utf8str(int uval, uint8 *buffer, size_t bufsz)
{
// static uint8 buffer[7];
uint8 *b = buffer;
if (bufsz < 5)
return 0;
/*
* Binary Hex Comments
* 0xxxxxxx 0x00..0x7F Only byte of a 1-byte character encoding
* 10xxxxxx 0x80..0xBF Continuation byte : one of 1-3 bytes following
* first 110xxxxx 0xC0..0xDF First byte of a 2-byte character encoding
* 1110xxxx 0xE0..0xEF First byte of a 3-byte character encoding
* 11110xxx 0xF0..0xF7 First byte of a 4-byte character encoding
*/
*b = '\0';
if (uval < 0x80) {
*b++ = uval;
} else if (uval < 0x800) {
*b++ = 192 + uval / 64;
*b++ = 128 + uval % 64;
} else if (uval - 0xd800u < 0x800) {
return 0;
} else if (uval < 0x10000) {
*b++ = 224 + uval / 4096;
*b++ = 128 + uval / 64 % 64;
*b++ = 128 + uval % 64;
} else if (uval < 0x110000) {
*b++ = 240 + uval / 262144;
*b++ = 128 + uval / 4096 % 64;
*b++ = 128 + uval / 64 % 64;
*b++ = 128 + uval % 64;
} else {
return 0;
}
*b = '\0'; /* NUL terminate */
return 1;
}
#endif /* ENHANCED_SYMBOLS */
/*hacklib.c*/

View File

@@ -16,6 +16,7 @@
#include "config.h"
#include "permonst.h"
#include "objclass.h"
#include "wintype.h"
#include "sym.h"
#include "artilist.h"
#include "dungeon.h"

View File

@@ -5,6 +5,7 @@
#include "config.h"
#include "permonst.h"
#include "wintype.h"
#include "sym.h"
#ifdef C

View File

@@ -505,7 +505,7 @@ parseoptions(register char *opts, boolean tinitial, boolean tfrom_file)
if (!got_match) {
/* Is it a symbol? */
if (strstr(opts, "S_") == opts && parsesymbols(opts, PRIMARY)) {
if (strstr(opts, "S_") == opts && parsesymbols(opts, PRIMARYSET)) {
switch_symbols(TRUE);
check_gold_symbol();
optresult = optn_ok;
@@ -872,7 +872,7 @@ optfn_boulder(int optidx UNUSED, int req, boolean negated UNUSED,
if (!g.opt_initial) {
nhsym sym = get_othersym(SYM_BOULDER,
Is_rogue_level(&u.uz) ? ROGUESET
: PRIMARY);
: PRIMARYSET);
if (sym)
g.showsyms[SYM_BOULDER + SYM_OFF_X] = sym;
@@ -946,13 +946,13 @@ optfn_cursesgraphics(int optidx, int req, boolean negated,
#ifdef BACKWARD_COMPAT
if (!negated) {
/* There is no rogue level cursesgraphics-specific set */
if (g.symset[PRIMARY].name) {
if (g.symset[PRIMARYSET].name) {
badflag = TRUE;
} else {
g.symset[PRIMARY].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARY)) {
g.symset[PRIMARYSET].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARYSET)) {
badflag = TRUE;
clear_symsetentry(PRIMARY, TRUE);
clear_symsetentry(PRIMARYSET, TRUE);
} else
switch_symbols(TRUE);
}
@@ -996,13 +996,13 @@ optfn_DECgraphics(int optidx, int req, boolean negated,
#ifdef BACKWARD_COMPAT
if (!negated) {
/* There is no rogue level DECgraphics-specific set */
if (g.symset[PRIMARY].name) {
if (g.symset[PRIMARYSET].name) {
badflag = TRUE;
} else {
g.symset[PRIMARY].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARY)) {
g.symset[PRIMARYSET].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARYSET)) {
badflag = TRUE;
clear_symsetentry(PRIMARY, TRUE);
clear_symsetentry(PRIMARYSET, TRUE);
} else
switch_symbols(TRUE);
}
@@ -1390,6 +1390,43 @@ optfn_gender(int optidx, int req, boolean negated, char *opts, char *op)
return optn_ok;
}
static int
optfn_glyph(int optidx UNUSED, int req, boolean negated, char *opts, char *op)
{
#ifdef ENHANCED_SYMBOLS
int glyph;
#endif
if (req == do_init) {
return optn_ok;
}
if (req == do_set) {
/* OPTION=glyph:G_glyph/U+NNNN/r-g-b */
if (negated) {
if (op != empty_optstr) {
bad_negation("glyph", TRUE);
return optn_err;
}
}
if (op == empty_optstr)
return optn_err;
/* strip leading/trailing spaces, condense internal ones (3.6.2) */
mungspaces(op);
#ifdef ENHANCED_SYMBOLS
if (!glyphrep_to_custom_map_entries(op, &glyph))
return optn_err;
#endif
return optn_ok;
}
if (req == get_val) {
if (!opts)
return optn_err;
Sprintf(opts, "%s", to_be_done);
return optn_ok;
}
return optn_ok;
}
static int
optfn_hilite_status(
int optidx UNUSED,
@@ -1534,13 +1571,13 @@ optfn_MACgraphics(int optidx, int req, boolean negated, char *opts, char *op)
if (req == do_set) {
/* "MACgraphics" */
if (!negated) {
if (g.symset[PRIMARY].name) {
if (g.symset[PRIMARYSET].name) {
badflag = TRUE;
} else {
g.symset[PRIMARY].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARY)) {
g.symset[PRIMARYSET].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARYSET)) {
badflag = TRUE;
clear_symsetentry(PRIMARY, TRUE);
clear_symsetentry(PRIMARYSET, TRUE);
}
}
if (badflag) {
@@ -3303,25 +3340,37 @@ optfn_suppress_alert(int optidx, int req, boolean negated,
return optn_ok;
}
extern const char *known_handling[]; /* symbols.c */
extern const char *known_restrictions[]; /* symbols.c */
static int
optfn_symset(int optidx UNUSED, int req, boolean negated UNUSED,
char *opts, char *op)
optfn_symset(int optidx UNUSED, int req, boolean negated UNUSED, char *opts,
char *op)
{
if (req == do_init) {
return optn_ok;
}
if (req == do_set) {
if (op != empty_optstr) {
g.symset[PRIMARY].name = dupstr(op);
if (!read_sym_file(PRIMARY)) {
clear_symsetentry(PRIMARY, TRUE);
g.symset[PRIMARYSET].name = dupstr(op);
if (!read_sym_file(PRIMARYSET)) {
clear_symsetentry(PRIMARYSET, TRUE);
config_error_add(
"Unable to load symbol set \"%s\" from \"%s\"", op,
SYMBOLS);
return optn_err;
} else {
switch_symbols(g.symset[PRIMARY].name != (char *) 0);
g.opt_need_redraw = TRUE;
if (g.symset[PRIMARYSET].handling) {
#ifndef ENHANCED_SYMBOLS
if (g.symset[PRIMARYSET].handling == H_UTF8) {
config_error_add("Unavailable symset handler \"%s\" for %s",
known_handling[H_UTF8], op);
load_symset("default", PRIMARYSET);
}
#endif
switch_symbols(g.symset[PRIMARYSET].name != (char *) 0);
g.opt_need_redraw = g.opt_need_glyph_reset = TRUE;
}
}
} else
return optn_err;
@@ -3331,13 +3380,32 @@ optfn_symset(int optidx UNUSED, int req, boolean negated UNUSED,
if (!opts)
return optn_err;
Sprintf(opts, "%s",
g.symset[PRIMARY].name ? g.symset[PRIMARY].name : "default");
if (g.currentgraphics == PRIMARY && g.symset[PRIMARY].name)
g.symset[PRIMARYSET].name ? g.symset[PRIMARYSET].name : "default");
if (g.currentgraphics == PRIMARYSET && g.symset[PRIMARYSET].name)
Strcat(opts, ", active");
if (g.symset[PRIMARYSET].handling) {
Sprintf(eos(opts), ", handler=%s",
known_handling[g.symset[PRIMARYSET].handling]);
}
return optn_ok;
}
if (req == do_handler) {
return handler_symset(optidx);
int reslt;
if (g.symset[PRIMARYSET].handling == H_UTF8) {
#ifdef ENHANCED_SYMBOLS
if (!glyphid_cache_status())
fill_glyphid_cache();
#endif
}
reslt = handler_symset(optidx);
if (g.symset[PRIMARYSET].handling == H_UTF8) {
#ifdef ENHANCED_SYMBOLS
if (glyphid_cache_status())
free_glyphid_cache();
#endif
}
return reslt;
}
return optn_ok;
}
@@ -5082,187 +5150,16 @@ handler_whatis_filter(void)
return optn_ok;
}
DISABLE_WARNING_FORMAT_NONLITERAL
static int
handler_symset(int optidx)
{
winid tmpwin;
anything any;
int n;
char buf[BUFSZ];
menu_item *symset_pick = (menu_item *) 0;
boolean rogueflag = (optidx == opt_roguesymset),
ready_to_switch = FALSE,
nothing_to_do = FALSE;
char *symset_name, fmtstr[20];
struct symsetentry *sl;
int res, which_set, setcount = 0, chosen = -2, defindx = 0;
int reslt;
which_set = rogueflag ? ROGUESET : PRIMARY;
g.symset_list = (struct symsetentry *) 0;
/* clear symset[].name as a flag to read_sym_file() to build list */
symset_name = g.symset[which_set].name;
g.symset[which_set].name = (char *) 0;
res = read_sym_file(which_set);
/* put symset name back */
g.symset[which_set].name = symset_name;
if (res && g.symset_list) {
int thissize,
biggest = (int) (sizeof "Default Symbols" - sizeof ""),
big_desc = 0;
for (sl = g.symset_list; sl; sl = sl->next) {
/* check restrictions */
if (rogueflag ? sl->primary : sl->rogue)
continue;
#ifndef MAC_GRAPHICS_ENV
if (sl->handling == H_MAC)
continue;
#endif
setcount++;
/* find biggest name */
thissize = sl->name ? (int) strlen(sl->name) : 0;
if (thissize > biggest)
biggest = thissize;
thissize = sl->desc ? (int) strlen(sl->desc) : 0;
if (thissize > big_desc)
big_desc = thissize;
}
if (!setcount) {
pline("There are no appropriate %s symbol sets available.",
rogueflag ? "rogue level" : "primary");
return TRUE;
}
Sprintf(fmtstr, "%%-%ds %%s", biggest + 2);
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
any = cg.zeroany;
any.a_int = 1; /* -1 + 2 [see 'if (sl->name) {' below]*/
if (!symset_name)
defindx = any.a_int;
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
"Default Symbols",
(any.a_int == defindx) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
for (sl = g.symset_list; sl; sl = sl->next) {
/* check restrictions */
if (rogueflag ? sl->primary : sl->rogue)
continue;
#ifndef MAC_GRAPHICS_ENV
if (sl->handling == H_MAC)
continue;
#endif
if (sl->name) {
/* +2: sl->idx runs from 0 to N-1 for N symsets;
+1 because Defaults are implicitly in slot [0];
+1 again so that valid data is never 0 */
any.a_int = sl->idx + 2;
if (symset_name && !strcmpi(sl->name, symset_name))
defindx = any.a_int;
Sprintf(buf, fmtstr, sl->name, sl->desc ? sl->desc : "");
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
ATR_NONE, buf,
(any.a_int == defindx) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
}
}
Sprintf(buf, "Select %ssymbol set:",
rogueflag ? "rogue level " : "");
end_menu(tmpwin, buf);
n = select_menu(tmpwin, PICK_ONE, &symset_pick);
if (n > 0) {
chosen = symset_pick[0].item.a_int;
/* if picking non-preselected entry yields 2, make sure
that we're going with the non-preselected one */
if (n == 2 && chosen == defindx)
chosen = symset_pick[1].item.a_int;
chosen -= 2; /* convert menu index to symset index;
* "Default symbols" have index -1 */
free((genericptr_t) symset_pick);
} else if (n == 0 && defindx > 0) {
chosen = defindx - 2;
}
destroy_nhwindow(tmpwin);
if (chosen > -1) {
/* chose an actual symset name from file */
for (sl = g.symset_list; sl; sl = sl->next)
if (sl->idx == chosen)
break;
if (sl) {
/* free the now stale attributes */
clear_symsetentry(which_set, TRUE);
/* transfer only the name of the symbol set */
g.symset[which_set].name = dupstr(sl->name);
ready_to_switch = TRUE;
}
} else if (chosen == -1) {
/* explicit selection of defaults */
/* free the now stale symset attributes */
clear_symsetentry(which_set, TRUE);
} else
nothing_to_do = TRUE;
} else if (!res) {
/* The symbols file could not be accessed */
pline("Unable to access \"%s\" file.", SYMBOLS);
return TRUE;
} else if (!g.symset_list) {
/* The symbols file was empty */
pline("There were no symbol sets found in \"%s\".", SYMBOLS);
return TRUE;
}
/* clean up */
while ((sl = g.symset_list) != 0) {
g.symset_list = sl->next;
if (sl->name)
free((genericptr_t) sl->name), sl->name = (char *) 0;
if (sl->desc)
free((genericptr_t) sl->desc), sl->desc = (char *) 0;
free((genericptr_t) sl);
}
if (nothing_to_do)
return TRUE;
/* Set default symbols and clear the handling value */
if (rogueflag)
init_rogue_symbols();
else
init_primary_symbols();
if (g.symset[which_set].name) {
/* non-default symbols */
if (read_sym_file(which_set)) {
ready_to_switch = TRUE;
} else {
clear_symsetentry(which_set, TRUE);
return TRUE;
}
}
if (ready_to_switch)
switch_symbols(TRUE);
if (Is_rogue_level(&u.uz)) {
if (rogueflag)
assign_graphics(ROGUESET);
} else if (!rogueflag)
assign_graphics(PRIMARY);
preference_update("symset");
reslt = do_symset(optidx == opt_roguesymset); /* symbols.c */
g.opt_need_redraw = TRUE;
return optidx;
return reslt;
}
RESTORE_WARNING_FORMAT_NONLITERAL
static int
handler_autopickup_exception(void)
{
@@ -5985,6 +5882,12 @@ initoptions_init(void)
memcpy(allopt, allopt_init, sizeof(allopt));
determine_ambiguities();
#ifdef ENHANCED_SYMBOLS
/* make any symbol parsing quicker */
if (!glyphid_cache_status())
fill_glyphid_cache();
#endif
/* set up the command parsing */
reset_commands(TRUE); /* init */
@@ -6048,8 +5951,8 @@ initoptions_init(void)
*/
/* this detects the IBM-compatible console on most 386 boxes */
if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
if (!g.symset[PRIMARY].explicitly)
load_symset("IBMGraphics", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("IBMGraphics", PRIMARYSET);
if (!g.symset[ROGUESET].explicitly)
load_symset("RogueIBM", ROGUESET);
switch_symbols(TRUE);
@@ -6065,8 +5968,8 @@ initoptions_init(void)
/* [could also check "xterm" which emulates vtXXX by default] */
&& !strncmpi(opts, "vt", 2)
&& AS && AE && index(AS, '\016') && index(AE, '\017')) {
if (!g.symset[PRIMARY].explicitly)
load_symset("DECGraphics", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("DECGraphics", PRIMARYSET);
switch_symbols(TRUE);
}
#endif
@@ -6074,14 +5977,14 @@ initoptions_init(void)
#if defined(MSDOS) || defined(WIN32)
/* Use IBM defaults. Can be overridden via config file */
if (!g.symset[PRIMARY].explicitly)
load_symset("IBMGraphics_2", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("IBMGraphics_2", PRIMARYSET);
if (!g.symset[ROGUESET].explicitly)
load_symset("RogueEpyx", ROGUESET);
#endif
#ifdef MAC_GRAPHICS_ENV
if (!g.symset[PRIMARY].explicitly)
load_symset("MACGraphics", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("MACGraphics", PRIMARYSET);
switch_symbols(TRUE);
#endif /* MAC_GRAPHICS_ENV */
flags.menu_style = MENU_FULL;
@@ -6206,7 +6109,7 @@ initoptions_finish(void)
obj_descr[SLIME_MOLD].oc_name = "fruit";
sym = get_othersym(SYM_BOULDER,
Is_rogue_level(&u.uz) ? ROGUESET : PRIMARY);
Is_rogue_level(&u.uz) ? ROGUESET : PRIMARYSET);
if (sym)
g.showsyms[SYM_BOULDER + SYM_OFF_X] = sym;
reglyph_darkroom();
@@ -6229,6 +6132,11 @@ initoptions_finish(void)
}
#endif
update_rest_on_space();
#ifdef ENHANCED_SYMBOLS
if (glyphid_cache_status())
free_glyphid_cache();
apply_customizations_to_symset(g.currentgraphics);
#endif
g.opt_initial = FALSE;
return;
}
@@ -8195,128 +8103,6 @@ free_autopickup_exceptions(void)
}
}
/* bundle some common usage into one easy-to-use routine */
int
load_symset(const char *s, int which_set)
{
clear_symsetentry(which_set, TRUE);
if (g.symset[which_set].name)
free((genericptr_t) g.symset[which_set].name);
g.symset[which_set].name = dupstr(s);
if (read_sym_file(which_set)) {
switch_symbols(TRUE);
} else {
clear_symsetentry(which_set, TRUE);
return 0;
}
return 1;
}
void
free_symsets(void)
{
clear_symsetentry(PRIMARY, TRUE);
clear_symsetentry(ROGUESET, TRUE);
/* symset_list is cleaned up as soon as it's used, so we shouldn't
have to anything about it here */
/* assert( symset_list == NULL ); */
}
/* Parse the value of a SYMBOLS line from a config file */
boolean
parsesymbols(register char *opts, int which_set)
{
int val;
char *op, *symname, *strval;
struct symparse *symp;
if ((op = index(opts, ',')) != 0) {
*op++ = 0;
if (!parsesymbols(op, which_set))
return FALSE;
}
/* S_sample:string */
symname = opts;
strval = index(opts, ':');
if (!strval)
strval = index(opts, '=');
if (!strval)
return FALSE;
*strval++ = '\0';
/* strip leading and trailing white space from symname and strval */
mungspaces(symname);
mungspaces(strval);
symp = match_sym(symname);
if (!symp)
return FALSE;
if (symp->range && symp->range != SYM_CONTROL) {
val = sym_val(strval);
if (which_set == ROGUESET)
update_ov_rogue_symset(symp, val);
else
update_ov_primary_symset(symp, val);
}
return TRUE;
}
struct symparse *
match_sym(char *buf)
{
int i;
struct alternate_parse {
const char *altnm;
const char *nm;
} alternates[] = {
{ "S_armour" , "S_armor" },
{ "S_explode1" , "S_expl_tl" },
{ "S_explode2" , "S_expl_tc" },
{ "S_explode3" , "S_expl_tr" },
{ "S_explode4" , "S_expl_ml" },
{ "S_explode5" , "S_expl_mc" },
{ "S_explode6" , "S_expl_mr" },
{ "S_explode7" , "S_expl_bl" },
{ "S_explode8" , "S_expl_bc" },
{ "S_explode9" , "S_expl_br" },
};
unsigned len = Strlen(buf);
const char *p = index(buf, ':'), *q = index(buf, '=');
struct symparse *sp = loadsyms;
if (!p || (q && q < p))
p = q;
if (p) {
/* note: there will be at most one space before the '='
because caller has condensed buf[] with mungspaces() */
if (p > buf && p[-1] == ' ')
p--;
len = (int) (p - buf);
}
while (sp->range) {
if ((len >= Strlen(sp->name)) && !strncmpi(buf, sp->name, len))
return sp;
sp++;
}
for (i = 0; i < SIZE(alternates); ++i) {
if ((len >= strlen(alternates[i].altnm))
&& !strncmpi(buf, alternates[i].altnm, len)) {
sp = loadsyms;
while (sp->range) {
if (!strcmp(alternates[i].nm, sp->name))
return sp;
sp++;
}
}
}
return (struct symparse *) 0;
}
int
sym_val(const char *strval) /* up to 4*BUFSZ-1 long; only first few
chars matter */

View File

@@ -15,13 +15,18 @@ void (*decgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
void (*ibmgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
void (*ascgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
#endif
#ifdef WIN32
void (*ibmgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
#endif
#ifdef CURSES_GRAPHICS
void (*cursesgraphics_mode_callback)(void) = 0;
#endif
/*
#if defined(TTY_GRAPHICS) && defined(WIN32)
void (*ibmgraphics_mode_callback)(void) = 0;
#endif
#ifdef ENHANCED_SYMBOLS
void (*utf8graphics_mode_callback)(void) = 0; /* set in tty_start_screen and
found in unixtty, windtty, etc */
#endif
/*
* Explanations of the functions found below:
*
* init_symbols()
@@ -56,7 +61,7 @@ void (*cursesgraphics_mode_callback)(void) = 0;
* If arg is ROGUESET, this places the rogue level
* symbols from g.rogue_syms into g.showsyms.
*
* If arg is PRIMARY, this places the symbols
* If arg is PRIMARYSET, this places the symbols
* from g.primary_syms into g.showsyms.
*
* update_primary_symset()
@@ -97,7 +102,7 @@ init_showsyms(void)
for (i = 0; i < WARNCOUNT; i++)
g.showsyms[i + SYM_OFF_W] = def_warnsyms[i].sym;
for (i = 0; i < MAXOTHER; i++)
g.showsyms[i + SYM_OFF_X] = get_othersym(i, PRIMARY);
g.showsyms[i + SYM_OFF_X] = get_othersym(i, PRIMARYSET);
}
/* initialize defaults for the overrides to the rogue symset */
@@ -169,9 +174,9 @@ init_primary_symbols(void)
for (i = 0; i < WARNCOUNT; i++)
g.primary_syms[i + SYM_OFF_W] = def_warnsyms[i].sym;
for (i = 0; i < MAXOTHER; i++)
g.primary_syms[i + SYM_OFF_X] = get_othersym(i, PRIMARY);
g.primary_syms[i + SYM_OFF_X] = get_othersym(i, PRIMARYSET);
clear_symsetentry(PRIMARY, FALSE);
clear_symsetentry(PRIMARYSET, FALSE);
}
/* initialize defaults for the rogue symset */
@@ -224,7 +229,7 @@ assign_graphics(int whichset)
g.currentgraphics = ROGUESET;
break;
case PRIMARY:
case PRIMARYSET:
default:
for (i = 0; i < SYM_MAX; i++)
g.showsyms[i] = g.ov_primary_syms[i] ? g.ov_primary_syms[i]
@@ -234,7 +239,7 @@ assign_graphics(int whichset)
if (iflags.grmode)
tileview(TRUE);
#endif
g.currentgraphics = PRIMARY;
g.currentgraphics = PRIMARYSET;
break;
}
reset_glyphmap(gm_symchange);
@@ -267,6 +272,14 @@ switch_symbols(int nondefault)
if (SYMHANDLING(H_CURS) && cursesgraphics_mode_callback)
(*cursesgraphics_mode_callback)();
# endif
#endif
#ifdef WIN32
if (SYMHANDLING(H_IBM) && ibmgraphics_mode_callback)
(*ibmgraphics_mode_callback)();
#endif
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8) && utf8graphics_mode_callback)
(*utf8graphics_mode_callback)();
#endif
} else {
init_primary_symbols();
@@ -275,25 +288,25 @@ switch_symbols(int nondefault)
}
void
update_ov_primary_symset(struct symparse* symp, int val)
update_ov_primary_symset(const struct symparse* symp, int val)
{
g.ov_primary_syms[symp->idx] = val;
}
void
update_ov_rogue_symset(struct symparse* symp, int val)
update_ov_rogue_symset(const struct symparse* symp, int val)
{
g.ov_rogue_syms[symp->idx] = val;
}
void
update_primary_symset(struct symparse* symp, int val)
update_primary_symset(const struct symparse* symp, int val)
{
g.primary_syms[symp->idx] = val;
}
void
update_rogue_symset(struct symparse* symp, int val)
update_rogue_symset(const struct symparse* symp, int val)
{
g.rogue_syms[symp->idx] = val;
}
@@ -318,7 +331,20 @@ clear_symsetentry(int which_set, boolean name_too)
}
}
/*
boolean symset_is_compatible(enum symset_handling_types handling, unsigned long wincap2)
{
#ifdef ENHANCED_SYMBOLS
if ((handling == H_UTF8) &&
(((wincap2 & WC2_U_UTF8STR) == 0)
|| ((wincap2 & WC2_U_24BITCOLOR) == 0)))
return FALSE;
#else
nhUse(handling);
nhUse(wincap2);
#endif
return TRUE;
}
/*
* If you are adding code somewhere to be able to recognize
* particular types of symset "handling", define a
* H_XXX macro in include/sym.h and add the name
@@ -330,6 +356,7 @@ const char *known_handling[] = {
"DEC", /* H_DEC */
"CURS", /* H_CURS */
"MAC", /* H_MAC -- pre-OSX MACgraphics */
"UTF8", /* H_UTF8 */
(const char *) 0,
};
@@ -377,4 +404,677 @@ const struct symparse loadsyms[] = {
{ 0, 0, (const char *) 0 } /* fence post */
};
boolean
proc_symset_line(char *buf)
{
return !((boolean) parse_sym_line(buf, g.symset_which_set));
}
/* returns 0 on error */
int
parse_sym_line(char *buf, int which_set)
{
int val, i;
const struct symparse *symp = (struct symparse *) 0;
char *bufp, *commentp, *altp;
int glyph = NO_GLYPH;
boolean enhanced_unavailable = FALSE, is_glyph = FALSE;
if (strlen(buf) >= BUFSZ)
buf[BUFSZ - 1] = '\0';
/* convert each instance of whitespace (tabs, consecutive spaces)
into a single space; leading and trailing spaces are stripped */
mungspaces(buf);
/* remove trailing comment, if any (this isn't strictly needed for
individual symbols, and it won't matter if "X#comment" without
separating space slips through; for handling or set description,
symbol set creator is responsible for preceding '#' with a space
and that comment itself doesn't contain " #") */
if ((commentp = rindex(buf, '#')) != 0 && commentp[-1] == ' ')
commentp[-1] = '\0';
/* find the '=' or ':' */
bufp = index(buf, '=');
altp = index(buf, ':');
if (!bufp || (altp && altp < bufp))
bufp = altp;
if (!bufp) {
if (strncmpi(buf, "finish", 6) == 0) {
/* end current graphics set */
if (g.chosen_symset_start)
g.chosen_symset_end = TRUE;
g.chosen_symset_start = FALSE;
return 1;
}
config_error_add("No \"finish\"");
return 0;
}
/* skip '=' and space which follows, if any */
++bufp;
if (*bufp == ' ')
++bufp;
symp = match_sym(buf);
if (!symp && buf[0] == 'G' && buf[1] == '_') {
#ifdef ENHANCED_SYMBOLS
is_glyph = match_glyph(buf);
#else
enhanced_unavailable = TRUE;
#endif
}
if (!symp && !is_glyph && !enhanced_unavailable) {
config_error_add("Unknown sym keyword");
return 0;
}
if (symp) {
if (!g.symset[which_set].name) {
/* A null symset name indicates that we're just
building a pick-list of possible symset
values from the file, so only do that */
if (symp->range == SYM_CONTROL) {
struct symsetentry *tmpsp, *lastsp;
for (lastsp = g.symset_list; lastsp; lastsp = lastsp->next)
if (!lastsp->next)
break;
switch (symp->idx) {
case 0:
tmpsp = (struct symsetentry *) alloc(sizeof *tmpsp);
tmpsp->next = (struct symsetentry *) 0;
if (!lastsp)
g.symset_list = tmpsp;
else
lastsp->next = tmpsp;
tmpsp->idx = g.symset_count++;
tmpsp->name = dupstr(bufp);
tmpsp->desc = (char *) 0;
tmpsp->handling = H_UNK;
/* initialize restriction bits */
tmpsp->nocolor = 0;
tmpsp->primary = 0;
tmpsp->rogue = 0;
break;
case 2:
/* handler type identified */
tmpsp = lastsp; /* most recent symset */
for (i = 0; known_handling[i]; ++i)
if (!strcmpi(known_handling[i], bufp)) {
tmpsp->handling = i;
break; /* for loop */
}
break;
case 3:
/* description:something */
tmpsp = lastsp; /* most recent symset */
if (tmpsp && !tmpsp->desc)
tmpsp->desc = dupstr(bufp);
break;
case 5:
/* restrictions: xxxx*/
tmpsp = lastsp; /* most recent symset */
for (i = 0; known_restrictions[i]; ++i) {
if (!strcmpi(known_restrictions[i], bufp)) {
switch (i) {
case 0:
tmpsp->primary = 1;
break;
case 1:
tmpsp->rogue = 1;
break;
}
break; /* while loop */
}
}
break;
}
}
return 1;
}
if (symp->range && symp->range == SYM_CONTROL) {
switch (symp->idx) {
case 0:
/* start of symset */
if (!strcmpi(bufp, g.symset[which_set].name)) {
/* matches desired one */
g.chosen_symset_start = TRUE;
/* these init_*() functions clear symset fields too */
if (which_set == ROGUESET)
init_rogue_symbols();
else if (which_set == PRIMARYSET)
init_primary_symbols();
}
break;
case 1:
/* finish symset */
if (g.chosen_symset_start)
g.chosen_symset_end = TRUE;
g.chosen_symset_start = FALSE;
break;
case 2:
/* handler type identified */
if (g.chosen_symset_start)
set_symhandling(bufp, which_set);
break;
/* case 3: (description) is ignored here */
case 4: /* color:off */
if (g.chosen_symset_start) {
if (bufp) {
if (!strcmpi(bufp, "true") || !strcmpi(bufp, "yes")
|| !strcmpi(bufp, "on"))
g.symset[which_set].nocolor = 0;
else if (!strcmpi(bufp, "false")
|| !strcmpi(bufp, "no")
|| !strcmpi(bufp, "off"))
g.symset[which_set].nocolor = 1;
}
}
break;
case 5: /* restrictions: xxxx*/
if (g.chosen_symset_start) {
int n = 0;
while (known_restrictions[n]) {
if (!strcmpi(known_restrictions[n], bufp)) {
switch (n) {
case 0:
g.symset[which_set].primary = 1;
break;
case 1:
g.symset[which_set].rogue = 1;
break;
}
break; /* while loop */
}
n++;
}
}
break;
}
} else {
/* Not SYM_CONTROL */
if (g.symset[which_set].handling != H_UTF8) {
val = sym_val(bufp);
if (g.chosen_symset_start) {
if (which_set == PRIMARYSET) {
update_primary_symset(symp, val);
} else if (which_set == ROGUESET) {
update_rogue_symset(symp, val);
}
}
#ifdef ENHANCED_SYMBOLS
} else {
glyphrep_to_custom_map_entries(buf, &glyph);
#endif
}
}
}
#ifndef ENHANCED_SYMBOLS
nhUse(glyph);
#endif
return 1;
}
void
set_symhandling(char *handling, int which_set)
{
int i = 0;
g.symset[which_set].handling = H_UNK;
while (known_handling[i]) {
if (!strcmpi(known_handling[i], handling)) {
g.symset[which_set].handling = i;
return;
}
i++;
}
}
/* bundle some common usage into one easy-to-use routine */
int
load_symset(const char *s, int which_set)
{
clear_symsetentry(which_set, TRUE);
if (g.symset[which_set].name)
free((genericptr_t) g.symset[which_set].name);
g.symset[which_set].name = dupstr(s);
if (read_sym_file(which_set)) {
switch_symbols(TRUE);
} else {
clear_symsetentry(which_set, TRUE);
return 0;
}
return 1;
}
void
free_symsets(void)
{
clear_symsetentry(PRIMARYSET, TRUE);
clear_symsetentry(ROGUESET, TRUE);
/* symset_list is cleaned up as soon as it's used, so we shouldn't
have to anything about it here */
/* assert( symset_list == NULL ); */
}
/* Parse the value of a SYMBOLS line from a config file */
boolean
parsesymbols(register char *opts, int which_set)
{
int val;
char *op, *symname, *strval;
const struct symparse *symp;
boolean is_glyph = FALSE;
if ((op = index(opts, ',')) != 0) {
*op++ = 0;
if (!parsesymbols(op, which_set))
return FALSE;
}
/* S_sample:string */
symname = opts;
strval = index(opts, ':');
if (!strval)
strval = index(opts, '=');
if (!strval)
return FALSE;
*strval++ = '\0';
/* strip leading and trailing white space from symname and strval */
mungspaces(symname);
mungspaces(strval);
symp = match_sym(symname);
#ifdef ENHANCED_SYMBOLS
if (!symp && symname[0] == 'G' && symname[1] == '_') {
is_glyph = match_glyph(symname);
}
#endif
if (!symp && !is_glyph)
return FALSE;
if (symp) {
if (symp->range && symp->range != SYM_CONTROL) {
#ifdef ENHANCED_SYMBOLS
int glyph;
#endif
if ((g.symset[which_set].handling == H_UTF8)
|| (strval && (lowc(strval[0]) == 'u') && (strval[1] == '+'))) {
#ifdef ENHANCED_SYMBOLS
char buf[BUFSZ];
Snprintf(buf, sizeof buf, "%s:%s", opts, strval);
glyphrep_to_custom_map_entries(buf, &glyph);
#endif /* ENHANCED_SYMBOLS */
} else {
val = sym_val(strval);
if (which_set == ROGUESET)
update_ov_rogue_symset(symp, val);
else
update_ov_primary_symset(symp, val);
}
}
}
return TRUE;
}
const struct symparse *
match_sym(char *buf)
{
int i;
struct alternate_parse {
const char *altnm;
const char *nm;
} alternates[] = {
{ "S_armour", "S_armor" }, { "S_explode1", "S_expl_tl" },
{ "S_explode2", "S_expl_tc" }, { "S_explode3", "S_expl_tr" },
{ "S_explode4", "S_expl_ml" }, { "S_explode5", "S_expl_mc" },
{ "S_explode6", "S_expl_mr" }, { "S_explode7", "S_expl_bl" },
{ "S_explode8", "S_expl_bc" }, { "S_explode9", "S_expl_br" },
};
size_t len = strlen(buf);
const char *p = index(buf, ':'), *q = index(buf, '=');
const struct symparse *sp = loadsyms;
if (!p || (q && q < p))
p = q;
if (p) {
/* note: there will be at most one space before the '='
because caller has condensed buf[] with mungspaces() */
if (p > buf && p[-1] == ' ')
p--;
len = (int) (p - buf);
}
while (sp->range) {
if ((len >= strlen(sp->name)) && !strncmpi(buf, sp->name, len))
return sp;
sp++;
}
for (i = 0; i < SIZE(alternates); ++i) {
if ((len >= strlen(alternates[i].altnm))
&& !strncmpi(buf, alternates[i].altnm, len)) {
sp = loadsyms;
while (sp->range) {
if (!strcmp(alternates[i].nm, sp->name))
return sp;
sp++;
}
}
}
return (struct symparse *) 0;
}
DISABLE_WARNING_FORMAT_NONLITERAL
/*
* this is called from options.c to do the symset work.
*/
int
do_symset(boolean rogueflag)
{
winid tmpwin;
anything any;
int n;
char buf[BUFSZ];
menu_item *symset_pick = (menu_item *) 0;
boolean ready_to_switch = FALSE,
nothing_to_do = FALSE;
char *symset_name, fmtstr[20];
struct symsetentry *sl;
int res, which_set, setcount = 0, chosen = -2, defindx = 0;
which_set = rogueflag ? ROGUESET : PRIMARYSET;
g.symset_list = (struct symsetentry *) 0;
/* clear symset[].name as a flag to read_sym_file() to build list */
symset_name = g.symset[which_set].name;
g.symset[which_set].name = (char *) 0;
res = read_sym_file(which_set);
/* put symset name back */
g.symset[which_set].name = symset_name;
if (res && g.symset_list) {
int thissize,
biggest = (int) (sizeof "Default Symbols" - sizeof ""),
big_desc = 0;
for (sl = g.symset_list; sl; sl = sl->next) {
/* check restrictions */
if (rogueflag ? sl->primary : sl->rogue)
continue;
#ifndef MAC_GRAPHICS_ENV
if (sl->handling == H_MAC)
continue;
#endif
#ifndef ENHANCED_SYMBOLS
if (sl->handling == H_UTF8)
continue;
#endif
setcount++;
/* find biggest name */
thissize = sl->name ? (int) strlen(sl->name) : 0;
if (thissize > biggest)
biggest = thissize;
thissize = sl->desc ? (int) strlen(sl->desc) : 0;
if (thissize > big_desc)
big_desc = thissize;
}
if (!setcount) {
pline("There are no appropriate %s symbol sets available.",
rogueflag ? "rogue level" : "primary");
return TRUE;
}
Sprintf(fmtstr, "%%-%ds %%s", biggest + 2);
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
any = cg.zeroany;
any.a_int = 1; /* -1 + 2 [see 'if (sl->name) {' below]*/
if (!symset_name)
defindx = any.a_int;
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
"Default Symbols",
(any.a_int == defindx) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
for (sl = g.symset_list; sl; sl = sl->next) {
/* check restrictions */
if (rogueflag ? sl->primary : sl->rogue)
continue;
#ifndef MAC_GRAPHICS_ENV
if (sl->handling == H_MAC)
continue;
#endif
#ifndef ENHANCED_SYMBOLS
if (sl->handling == H_UTF8)
continue;
#endif
if (sl->name) {
/* +2: sl->idx runs from 0 to N-1 for N symsets;
+1 because Defaults are implicitly in slot [0];
+1 again so that valid data is never 0 */
any.a_int = sl->idx + 2;
if (symset_name && !strcmpi(sl->name, symset_name))
defindx = any.a_int;
Sprintf(buf, fmtstr, sl->name, sl->desc ? sl->desc : "");
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
ATR_NONE, buf,
(any.a_int == defindx) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
}
}
Sprintf(buf, "Select %ssymbol set:",
rogueflag ? "rogue level " : "");
end_menu(tmpwin, buf);
n = select_menu(tmpwin, PICK_ONE, &symset_pick);
if (n > 0) {
chosen = symset_pick[0].item.a_int;
/* if picking non-preselected entry yields 2, make sure
that we're going with the non-preselected one */
if (n == 2 && chosen == defindx)
chosen = symset_pick[1].item.a_int;
chosen -= 2; /* convert menu index to symset index;
* "Default symbols" have index -1 */
free((genericptr_t) symset_pick);
} else if (n == 0 && defindx > 0) {
chosen = defindx - 2;
}
destroy_nhwindow(tmpwin);
if (chosen > -1) {
/* chose an actual symset name from file */
for (sl = g.symset_list; sl; sl = sl->next)
if (sl->idx == chosen)
break;
if (sl) {
/* free the now stale attributes */
clear_symsetentry(which_set, TRUE);
/* transfer only the name of the symbol set */
g.symset[which_set].name = dupstr(sl->name);
ready_to_switch = TRUE;
}
} else if (chosen == -1) {
/* explicit selection of defaults */
/* free the now stale symset attributes */
clear_symsetentry(which_set, TRUE);
} else
nothing_to_do = TRUE;
} else if (!res) {
/* The symbols file could not be accessed */
pline("Unable to access \"%s\" file.", SYMBOLS);
return TRUE;
} else if (!g.symset_list) {
/* The symbols file was empty */
pline("There were no symbol sets found in \"%s\".", SYMBOLS);
return TRUE;
}
/* clean up */
while ((sl = g.symset_list) != 0) {
g.symset_list = sl->next;
if (sl->name)
free((genericptr_t) sl->name), sl->name = (char *) 0;
if (sl->desc)
free((genericptr_t) sl->desc), sl->desc = (char *) 0;
free((genericptr_t) sl);
}
if (nothing_to_do)
return TRUE;
/* Set default symbols and clear the handling value */
if (rogueflag)
init_rogue_symbols();
else
init_primary_symbols();
if (g.symset[which_set].name) {
/* non-default symbols */
if (read_sym_file(which_set)) {
ready_to_switch = TRUE;
} else {
clear_symsetentry(which_set, TRUE);
return TRUE;
}
}
if (ready_to_switch)
switch_symbols(TRUE);
if (Is_rogue_level(&u.uz)) {
if (rogueflag)
assign_graphics(ROGUESET);
} else if (!rogueflag)
assign_graphics(PRIMARYSET);
#ifdef ENHANCED_SYMBOLS
apply_customizations_to_symset(rogueflag ? ROGUESET : PRIMARYSET);
#endif
preference_update("symset");
return TRUE;
}
#ifdef ENHANCED_SYMBOLS
RESTORE_WARNING_FORMAT_NONLITERAL
struct customization_detail *find_display_sym_customization(
const char *customization_name, const struct symparse *symparse,
enum graphics_sets which_set);
struct customization_detail *find_matching_symset_customization(
const char *customization_name, int custtype,
enum graphics_sets which_set);
struct customization_detail *find_display_urep_customization(
const char *customization_name, int glyphidx, enum graphics_sets which_set);
void purge_custom_entries(enum graphics_sets which_set);
extern glyph_map glyphmap[MAX_GLYPH];
static void shuffle_customizations(void);
void
apply_customizations_to_symset(enum graphics_sets which_set)
{
glyph_map *gm;
struct customization_detail *details;
if (g.symset[which_set].handling == H_UTF8
&& g.sym_customizations[UNICODESET].count
&& g.sym_customizations[UNICODESET].details) {
/* These UTF-8 customizations get applied to the glyphmap array,
not to symset entries */
details = g.sym_customizations[UNICODESET].details;
while (details) {
gm = &glyphmap[details->content.urep.glyphidx];
(void) set_map_u(gm, details->content.urep.u.utf8str,
details->content.urep.u.ucolor);
details = details->next;
}
shuffle_customizations();
}
}
/* Shuffle the customizations to match shuffled object descriptions,
* so a red potion isn't displayed with a blue customization, and so on.
*/
static void
shuffle_customizations(void)
{
int i;
struct unicode_representation *tmp_u[2][NUM_OBJECTS];
for (i = 0; i < NUM_OBJECTS; i++) {
tmp_u[0][i] =
glyphmap[objects[i].oc_descr_idx + GLYPH_OBJ_OFF].u;
tmp_u[1][i] =
glyphmap[objects[i].oc_descr_idx + GLYPH_OBJ_PILETOP_OFF].u;
}
for (i = 0; i < NUM_OBJECTS; i++) {
glyphmap[i + GLYPH_OBJ_OFF].u = tmp_u[0][i];
glyphmap[i + GLYPH_OBJ_PILETOP_OFF].u = tmp_u[1][i];
}
}
struct customization_detail *
find_matching_symset_customization(const char *customization_name,
int custtype,
enum graphics_sets which_set)
{
struct symset_customization *gdc = &g.sym_customizations[which_set];
if ((gdc->custtype == custtype)
&& (strcmp(customization_name, gdc->customization_name) != 0))
return gdc->details;
return (struct customization_detail *) 0;
}
void
purge_custom_entries(enum graphics_sets which_set)
{
struct symset_customization *gdc = &g.sym_customizations[which_set];
struct customization_detail *details = gdc->details, *next;
if (details) {
next = details->next;
if (gdc->custtype == custom_ureps) {
if (details->content.urep.u.utf8str)
free(details->content.urep.u.utf8str);
details->content.urep.u.utf8str = (uint8 *) 0;
details->content.urep.u.ucolor = 0L;
details->content.urep.u.u256coloridx = 0L;
} else if (gdc->custtype == custom_symbols) {
details->content.sym.symparse = (struct symparse *) 0;
details->content.sym.val = 0;
}
free(details);
details = next;
}
gdc->details = 0;
if (gdc->customization_name) {
free((genericptr_t) gdc->customization_name);
gdc->customization_name = 0;
}
gdc->count = 0;
}
struct customization_detail *
find_display_sym_customization(const char *customization_name,
const struct symparse *symparse,
enum graphics_sets which_set)
{
struct symset_customization *gdc = &g.sym_customizations[which_set];
struct customization_detail *symdetails;
if ((gdc->custtype == custom_symbols)
&& (strcmp(customization_name, gdc->customization_name) == 0)) {
symdetails = gdc->details;
while (symdetails) {
if (symdetails->content.sym.symparse == symparse)
return symdetails;
symdetails = symdetails->next;
}
}
return (struct customization_detail *) 0;
}
#endif /* ENHANCED_SYMBOLS */
/*symbols.c*/

1123
src/utf8map.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1375,7 +1375,7 @@ glyph2symidx(int glyph)
glyph_info glyphinfo;
map_glyphinfo(0, 0, glyph, 0, &glyphinfo);
return glyphinfo.gm.symidx;
return glyphinfo.gm.sym.symidx;
}
char *
@@ -1387,10 +1387,37 @@ encglyph(int glyph)
return encbuf;
}
int
decode_glyph(const char *str, int *glyph_ptr)
{
static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
int rndchk = 0, dcount = 0, retval = 0;
const char *dp;
for (; *str && ++dcount <= 4; ++str) {
if ((dp = index(hex, *str)) != 0) {
retval++;
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
} else
break;
}
if (rndchk == g.context.rndencode) {
*glyph_ptr = dcount = 0;
for (; *str && ++dcount <= 4; ++str) {
if ((dp = index(hex, *str)) != 0) {
retval++;
*glyph_ptr = (*glyph_ptr * 16) + ((int) (dp - hex) / 2);
} else
break;
}
return retval;
}
return 0;
}
char *
decode_mixed(char *buf, const char *str)
{
static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
char *put = buf;
glyph_info glyphinfo = nul_glyphinfo;
@@ -1399,27 +1426,16 @@ decode_mixed(char *buf, const char *str)
while (*str) {
if (*str == '\\') {
int rndchk, dcount, so, gv;
const char *dp, *save_str;
int dcount, so, gv;
const char *save_str;
save_str = str++;
switch (*str) {
case 'G': /* glyph value \GXXXXNNNN*/
rndchk = dcount = 0;
for (++str; *str && ++dcount <= 4; ++str)
if ((dp = index(hex, *str)) != 0)
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
else
break;
if (rndchk == g.context.rndencode) {
gv = dcount = 0;
for (; *str && ++dcount <= 4; ++str)
if ((dp = index(hex, *str)) != 0)
gv = (gv * 16) + ((int) (dp - hex) / 2);
else
break;
if ((dcount = decode_glyph(str + 1, &gv))) {
str += (dcount + 1);
map_glyphinfo(0, 0, gv, 0, &glyphinfo);
so = glyphinfo.gm.symidx;
so = glyphinfo.gm.sym.symidx;
*put++ = g.showsyms[so];
/* 'str' is ready for the next loop iteration and '*str'
should not be copied at the end of this iteration */
@@ -1429,25 +1445,6 @@ decode_mixed(char *buf, const char *str)
str = save_str;
}
break;
#if 0
case 'S': /* symbol offset */
so = rndchk = dcount = 0;
for (++str; *str && ++dcount <= 4; ++str)
if ((dp = index(hex, *str)) != 0)
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
else
break;
if (rndchk == g.context.rndencode) {
dcount = 0;
for (; *str && ++dcount <= 2; ++str)
if ((dp = index(hex, *str)) != 0)
so = (so * 16) + ((int) (dp - hex) / 2);
else
break;
}
*put++ = g.showsyms[so];
break;
#endif
case '\\':
break;
case '\0':
@@ -1467,6 +1464,7 @@ decode_mixed(char *buf, const char *str)
return buf;
}
/*
* This differs from putstr() because the str parameter can
* contain a sequence of characters representing:

View File

@@ -361,7 +361,7 @@ process_options(int argc, char *argv[])
|| !strcmpi(*argv, "-debug")) {
wizard = TRUE, discover = FALSE;
} else if (!strncmpi(*argv, "-DECgraphics", l)) {
load_symset("DECGraphics", PRIMARY);
load_symset("DECGraphics", PRIMARYSET);
switch_symbols(TRUE);
} else {
raw_printf("Unknown option: %.60s", *argv);
@@ -391,7 +391,7 @@ process_options(int argc, char *argv[])
case 'I':
case 'i':
if (!strncmpi(*argv, "-IBMgraphics", l)) {
load_symset("IBMGraphics", PRIMARY);
load_symset("IBMGraphics", PRIMARYSET);
load_symset("RogueIBM", ROGUESET);
switch_symbols(TRUE);
} else {

View File

@@ -561,7 +561,7 @@ process_options(int argc, char *argv[])
case 'I':
case 'i':
if (!strncmpi(argv[0] + 1, "IBM", 3)) {
load_symset("IBMGraphics", PRIMARY);
load_symset("IBMGraphics", PRIMARYSET);
load_symset("RogueIBM", ROGUESET);
switch_symbols(TRUE);
}
@@ -569,7 +569,7 @@ process_options(int argc, char *argv[])
/* case 'D': */
case 'd':
if (!strncmpi(argv[0] + 1, "DEC", 3)) {
load_symset("DECGraphics", PRIMARY);
load_symset("DECGraphics", PRIMARYSET);
switch_symbols(TRUE);
}
break;

View File

@@ -393,7 +393,7 @@ init_sco_cons(void)
if (WINDOWPORT("tty") && sco_flag_console) {
atexit(sco_mapon);
sco_mapoff();
load_symset("IBMGraphics", PRIMARY);
load_symset("IBMGraphics", PRIMARYSET);
load_symset("RogueIBM", ROGUESET);
switch_symbols(TRUE);
#ifdef TEXTCOLOR
@@ -485,3 +485,15 @@ error(const char *s, ...)
RESTORE_WARNING_FORMAT_NONLITERAL
#ifdef ENHANCED_SYMBOLS
/*
* set in tty_start_screen() and allows
* OS-specific changes that may be
* required for support of utf8.
*/
void
tty_utf8graphics_fixup(void)
{
}
#endif

View File

@@ -488,7 +488,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
rip.c rnd.c role.c rumors.c save.c sfstruct.c \
shk.c shknam.c sit.c sounds.c \
sp_lev.c spell.c steal.c steed.c symbols.c sys.c teleport.c \
timeout.c topten.c track.c trap.c u_init.c \
timeout.c topten.c track.c trap.c u_init.c utf8map.c \
uhitm.c vault.c version.c vision.c weapon.c were.c wield.c \
windows.c wizard.c worm.c worn.c write.c zap.c
@@ -580,8 +580,8 @@ HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \
$(TARGETPFX)symbols.o $(TARGETPFX)sys.o $(TARGETPFX)steal.o \
$(TARGETPFX)steed.o $(TARGETPFX)teleport.o $(TARGETPFX)timeout.o \
$(TARGETPFX)topten.o $(TARGETPFX)track.o $(TARGETPFX)trap.o \
$(TARGETPFX)u_init.o $(TARGETPFX)uhitm.o $(TARGETPFX)vault.o \
$(TARGETPFX)vision.o $(TARGETPFX)weapon.o \
$(TARGETPFX)u_init.o $(TARGETPFX)uhitm.o $(TARGETPFX)utf8map.o \
$(TARGETPFX)vault.o $(TARGETPFX)vision.o $(TARGETPFX)weapon.o \
$(TARGETPFX)were.o $(TARGETPFX)wield.o $(TARGETPFX)windows.o \
$(TARGETPFX)wizard.o $(TARGETPFX)worm.o $(TARGETPFX)worn.o \
$(TARGETPFX)write.o $(TARGETPFX)zap.o \

View File

@@ -105,6 +105,9 @@ NHCFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
#NHCFLAGS+=-DTTY_SOUND_ESCCODES
#NHCFLAGS+=-DNO_CHRONICLE
#NHCFLAGS+=-DLIVELOG
ifdef WANT_WIN_CURSES
NHCFLAGS+=-DCURSES_UNICODE
endif
CFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
CFLAGS+= $(NHCFLAGS)

View File

@@ -105,6 +105,9 @@ NHCFLAGS+=-DNOMAIL
#NHCFLAGS+=-DTTY_SOUND_ESCCODES
#NHCFLAGS+=-DNO_CHRONICLE
#NHCFLAGS+=-DLIVELOG
ifdef WANT_WIN_CURSES
NHCFLAGS+=-DCURSES_UNICODE
endif
CFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
CFLAGS+= $(NHCFLAGS)

View File

@@ -115,7 +115,10 @@ main(int argc, char *argv[])
#endif /* CHDIR */
/* handle -dalthackdir, -s <score stuff>, --version, --showpaths */
early_options(&argc, &argv, &dir);
#ifdef ENHANCED_SYMBOLS
if (argcheck(argc, argv, ARG_DUMPGLYPHIDS) == 2)
exit(EXIT_SUCCESS);
#endif
#ifdef CHDIR
/*
* Change directories before we initialize the window system so
@@ -405,7 +408,7 @@ process_options(int argc, char *argv[])
if ((arg[1] == 'D' && !arg[2]) || !strcmpi(arg, "-debug")) {
wizard = TRUE, discover = FALSE;
} else if (!strncmpi(arg, "-DECgraphics", l)) {
load_symset("DECGraphics", PRIMARY);
load_symset("DECGraphics", PRIMARYSET);
switch_symbols(TRUE);
} else {
config_error_add("Unknown option: %.60s", origarg);
@@ -442,7 +445,7 @@ process_options(int argc, char *argv[])
case 'I':
case 'i':
if (!strncmpi(arg, "-IBMgraphics", l)) {
load_symset("IBMGraphics", PRIMARY);
load_symset("IBMGraphics", PRIMARYSET);
load_symset("RogueIBM", ROGUESET);
switch_symbols(TRUE);
} else {

View File

@@ -281,7 +281,7 @@ process_options(int argc, char *argv[])
case 'I':
case 'i':
if (!strncmpi(argv[0] + 1, "IBM", 3)) {
load_symset("IBMGraphics", PRIMARY);
load_symset("IBMGraphics", PRIMARYSET);
load_symset("RogueIBM", ROGUESET);
switch_symbols(TRUE);
}
@@ -289,7 +289,7 @@ process_options(int argc, char *argv[])
/* case 'D': */
case 'd':
if (!strncmpi(argv[0] + 1, "DEC", 3)) {
load_symset("DECGraphics", PRIMARY);
load_symset("DECGraphics", PRIMARYSET);
switch_symbols(TRUE);
}
break;

View File

@@ -724,7 +724,7 @@ COREOBJS = $(addsuffix .o, allmain alloc apply artifact attrib ball bones botl c
pager pickup pline polyself potion pray priest quest questpgr \
random read rect region restore rip rnd role rumors \
safeproc save sfstruct shk shknam sit sounds sp_lev spell steal steed stubs symbols sys \
teleport timeout topten track trap u_init uhitm vault version vision \
teleport timeout topten track trap u_init uhitm utf8map vault version vision \
weapon were wield windmain windows windsys wizard worm worn write zap)
CFLAGSW = $(CFLAGS) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRPHICS

View File

@@ -435,8 +435,8 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
rip.c rnd.c role.c rumors.c save.c sfstruct.c \
shk.c shknam.c sit.c sounds.c \
sp_lev.c spell.c steal.c steed.c symbols.c sys.c teleport.c \
timeout.c topten.c track.c trap.c u_init.c \
uhitm.c vault.c version.c vision.c weapon.c were.c wield.c \
timeout.c topten.c track.c trap.c u_init.c uhitm.c utf8map.c \
vault.c version.c vision.c weapon.c were.c wield.c \
windows.c wizard.c worm.c worn.c write.c zap.c
@@ -496,10 +496,10 @@ VOBJ21 = $(O)sfstruct.o $(O)shk.o $(O)shknam.o $(O)sit.o
VOBJ22 = $(O)sounds.o $(O)sp_lev.o $(O)spell.o $(O)steal.o
VOBJ23 = $(O)steed.o $(O)symbols.o $(O)sys.o $(O)teleport.o
VOBJ24 = $(O)timeout.o $(O)topten.o $(O)track.o $(O)trap.o
VOBJ25 = $(O)u_init.o $(O)uhitm.o $(O)vault.o $(O)vision.o
VOBJ26 = $(O)weapon.o $(O)were.o $(O)wield.o $(O)windows.o
VOBJ27 = $(O)wizard.o $(O)worm.o $(O)worn.o $(O)write.o
VOBJ28 = $(O)zap.o
VOBJ25 = $(O)u_init.o $(O)uhitm.o $(O)utf8map.o $(O)vault.o
VOBJ26 = $(O)vision.o $(O)weapon.o $(O)were.o $(O)wield.o
VOBJ27 = $(O)windows.o $(O)wizard.o $(O)worm.o $(O)worn.o
VOBJ28 = $(O)write.o $(O)zap.o
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o $(O)nhlobj.o
@@ -510,7 +510,7 @@ DLBOBJ = $(O)dlb.o
REGEX = $(O)cppregex.o
TTYOBJ = $(O)topl.o $(O)getline.o $(O)wintty.o
TTYOBJ = $(O)topl.o $(O)getline.o $(O)wintty.o
MDLIB = $(O)mdlib.o
@@ -723,7 +723,7 @@ ccommon= -c -nologo -D"_CONSOLE" -D"_CRT_NONSTDC_NO_DEPRECATE" -D"_CRT_SECURE_NO
-DHAS_STDINT_H -DHAS_INLINE $(CURSESDEF) $(RUNTIMEOPTDEF) \
-EHsc -fp:precise -Gd -GF -GS -Gy \
$(CL_RECENT) -WX- -Zc:forScope -Zc:wchar_t -Zi
cdebug= -analyze- -D"_DEBUG" -MTd -RTC1 -Od
cdebug= -analyze- -D"_DEBUG" -MTd -RTC1 -Od /fsanitize=address
crelease= -analyze- -D"_MBCS" -errorReport:prompt -MT -O2 -Ot -Ox -Oy
lcommon= /NOLOGO /INCREMENTAL:NO
@@ -2246,6 +2246,7 @@ $(TARGETPFX)track.o: track.c $(HACK_H)
$(TARGETPFX)trap.o: trap.c $(HACK_H)
$(TARGETPFX)u_init.o: u_init.c $(HACK_H)
$(TARGETPFX)uhitm.o: uhitm.c $(HACK_H)
$(TARGETPFX)utf8map.o: utf8map.c $(HACK_H)
$(TARGETPFX)vault.o: vault.c $(HACK_H)
$(TARGETPFX)version.o: version.c $(HACK_H) $(INCL)\dlb.h
$(TARGETPFX)vision.o: vision.c $(HACK_H)

View File

@@ -15,6 +15,7 @@
#ifndef NO_VT
#define VIRTUAL_TERMINAL_SEQUENCES
#define UTF8_FROM_CORE
#endif
#ifdef WIN32
@@ -84,6 +85,7 @@ typedef struct {
WCHAR wcharacter;
WORD attr;
long color24;
int color256idx;
const char *colorseq;
#endif /* VIRTUAL_TERMINAL_SEQUENCES */
} cell_t;
@@ -94,9 +96,9 @@ cell_t undefined_cell = { CONSOLE_UNDEFINED_CHARACTER,
CONSOLE_UNDEFINED_ATTRIBUTE };
#else /* VIRTUAL_TERMINAL_SEQUENCES */
cell_t clear_cell = { { CONSOLE_CLEAR_CHARACTER, 0, 0, 0, 0, 0, 0 },
CONSOLE_CLEAR_CHARACTER, 0, 0L, "\x1b[0m" };
CONSOLE_CLEAR_CHARACTER, 0, 0L, 0, "\x1b[0m" };
cell_t undefined_cell = { { CONSOLE_UNDEFINED_CHARACTER, 0, 0, 0, 0, 0, 0 },
CONSOLE_UNDEFINED_CHARACTER, 0, 0L, (const char *) 0 };
CONSOLE_UNDEFINED_CHARACTER, 0, 0L, 0, (const char *) 0 };
static const uint8 empty_utf8str[MAX_UTF8_SEQUENCE] = { 0 };
#endif /* VIRTUAL_TERMINAL_SEQUENCES */
@@ -137,7 +139,8 @@ static void restore_original_console_font(void);
extern void safe_routines(void);
void tty_ibmgraphics_fixup(void);
#ifdef VIRTUAL_TERMINAL_SEQUENCES
extern void (*ibmgraphics_mode_callback)(void); /* symbols.c */
extern void (*ibmgraphics_mode_callback)(void); /* symbols.c */
extern void (*utf8graphics_mode_callback)(void); /* symbols.c */
#endif /* VIRTUAL_TERMINAL_SEQUENCES */
/* Win32 Screen buffer,coordinate,console I/O information */
@@ -160,27 +163,9 @@ static boolean init_ttycolor_completed;
#ifdef PORT_DEBUG
static boolean display_cursor_info = FALSE;
#endif
#ifdef CHANGE_COLOR
static void adjust_palette(void);
static int match_color_name(const char *);
typedef HWND(WINAPI *GETCONSOLEWINDOW)();
static HWND GetConsoleHandle(void);
static HWND GetConsoleHwnd(void);
static boolean altered_palette;
static COLORREF UserDefinedColors[CLR_MAX];
static COLORREF NetHackColors[CLR_MAX] = {
0x00000000, 0x00c80000, 0x0000c850, 0x00b4b432, 0x000000d2, 0x00800080,
0x000064b4, 0x00c0c0c0, 0x00646464, 0x00f06464, 0x0000ff00, 0x00ffff00,
0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
};
static COLORREF DefaultColors[CLR_MAX] = {
0x00000000, 0x00800000, 0x00008000, 0x00808000, 0x00000080, 0x00800080,
0x00008080, 0x00c0c0c0, 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
};
#endif
struct console_t {
boolean is_ready;
HWND hWnd;
WORD background;
WORD foreground;
WORD attr;
@@ -217,8 +202,10 @@ struct console_t {
DWORD in_cmode;
DWORD out_cmode;
long color24;
int color256idx;
} console = {
FALSE,
0,
(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED), /* background */
(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED), /* foreground */
0, /* attr */
@@ -263,7 +250,8 @@ struct console_t {
NULL, /* localestr */
0, /* in_cmode */
0, /* out_cmode */
0L /* color24 */
0L, /* color24 */
0 /* color256idx */
#endif /* VIRTUAL_TERMINAL_SEQUENCES */
};
@@ -532,6 +520,7 @@ void emit_stop_underline(void);
void emit_start_inverse(void);
void emit_stop_inverse(void);
void emit_start_24bitcolor(long color24bit);
void emit_start_256color(int u256coloridx);
void emit_default_color(void);
void emit_return_to_default(void);
void emit_hide_cursor(void);
@@ -656,22 +645,42 @@ emit_stop_inverse(void)
&unused, &reserved);
}
#if 0
#define tcfmtstr "\x1b[38;2;%d;%d;%dm"
#if 0
#define tcfmtstr "\x1b[38:2:%d:%d:%dm"
#endif
#endif
#ifndef SEP2
#define tcfmtstr24bit "\x1b[38;2;%ld;%ld;%ldm"
#define tcfmtstr256 "\x1b[38;5;%ldm"
#else
#define tcfmtstr24bit "\x1b[38:2:%ld:%ld:%ldm"
#define tcfmtstr256 "\x1b[38:5:%dm"
#endif
void
emit_start_256color(int u256coloridx)
{
DWORD unused, reserved;
static char tcolorbuf[QBUFSZ];
Snprintf(tcolorbuf, sizeof tcolorbuf, tcfmtstr256, u256coloridx);
WriteConsoleA(console.hConOut, (LPCSTR) tcolorbuf,
(int) strlen(tcolorbuf), &unused, &reserved);
}
void
emit_start_24bitcolor(long color24bit)
{
DWORD unused, reserved;
static char tcolorbuf[QBUFSZ];
long mcolor24bit =
long mcolor =
(color24bit & 0xFFFFFF); /* color 0 has bit 0x1000000 set */
Snprintf(tcolorbuf, sizeof tcolorbuf, tcfmtstr,
((mcolor24bit >> 0) & 0xFF), /* red */
((mcolor24bit >> 8) & 0xFF), /* green */
((mcolor24bit >> 16) & 0xFF)); /* blue */
Snprintf(tcolorbuf, sizeof tcolorbuf, tcfmtstr24bit,
((mcolor >> 16) & 0xFF), /* red */
((mcolor >> 8) & 0xFF), /* green */
((mcolor >> 0) & 0xFF)); /* blue */
WriteConsoleA(console.hConOut, (LPCSTR) tcolorbuf,
(int) strlen(tcolorbuf), &unused, &reserved);
}
@@ -744,9 +753,19 @@ back_buffer_flip(void)
do_anything |= do_colorseq;
if (back->attr != front->attr)
do_anything |= do_newattr;
if (strcmp((const char *) back->utf8str,
(const char *) front->utf8str))
do_anything |= do_utf8_content;
#ifdef UTF8_FROM_CORE
if (!SYMHANDLING(H_UTF8)) {
if (console.has_unicode
&& (back->wcharacter != front->wcharacter))
do_anything |= do_wide_content;
} else {
#endif
if (strcmp((const char *) back->utf8str,
(const char *) front->utf8str))
do_anything |= do_utf8_content;
#ifdef UTF8_FROM_CORE
}
#endif
if (do_anything) {
SetConsoleCursorPosition(console.hConOut, pos);
pos_set = TRUE;
@@ -771,7 +790,10 @@ back_buffer_flip(void)
if (color24_on && back->color24) {
did_anything |= did_color24;
if (back->color24) {
emit_start_24bitcolor(back->color24);
if (!iflags.use_truecolor && iflags.colorcount == 256)
emit_start_256color(back->color256idx);
else
emit_start_24bitcolor(back->color24);
}
} else if (back->colorseq) {
did_anything |= did_colorseq;
@@ -784,9 +806,20 @@ back_buffer_flip(void)
}
if (did_anything
|| (do_anything & (do_wide_content | do_utf8_content))) {
#ifdef UTF8_FROM_CORE
if (SYMHANDLING(H_UTF8) || !console.has_unicode) {
WriteConsoleA(console.hConOut, (LPCSTR) back->utf8str,
(int) strlen((char *) back->utf8str),
&unused, &reserved);
did_anything |= did_utf8_content;
} else {
#endif
WriteConsoleW(console.hConOut, &back->wcharacter, 1,
&unused, &reserved);
did_anything |= did_wide_content;
#ifdef UTF8_FROM_CORE
}
#endif
}
}
if (did_anything) {
@@ -930,10 +963,6 @@ settty(const char* s)
void
setftty()
{
#ifdef CHANGE_COLOR
if (altered_palette)
adjust_palette();
#endif
start_screen();
}
@@ -943,6 +972,8 @@ tty_startup(int *wid, int *hgt)
*wid = console.width;
*hgt = console.height;
set_option_mod_status("mouse_support", set_in_game);
iflags.colorcount = 16777216;
// iflags.colorcount = 256;
}
void
@@ -958,6 +989,11 @@ tty_start_screen()
tty_number_pad(1); /* make keypad send digits */
#ifdef VIRTUAL_TERMINAL_SEQUENCES
ibmgraphics_mode_callback = tty_ibmgraphics_fixup;
#ifdef ENHANCED_SYMBOLS
#ifdef UTF8_FROM_CORE
utf8graphics_mode_callback = tty_utf8graphics_fixup;
#endif
#endif
#endif /* VIRTUAL_TERMINAL_SEQUENCES */
}
@@ -1234,13 +1270,25 @@ xputc_core(int ch)
// if (console.color24)
// __debugbreak();
cell.color24 = 0L;
cell.color256idx = 0;
wch[1] = 0;
if (console.has_unicode) {
wch[0] = (ch >= 0 && ch < SIZE(console.cpMap)) ? console.cpMap[ch]
: ch;
#ifdef UTF8_FROM_CORE
if (SYMHANDLING(H_UTF8)) {
/* we have to convert it to UTF-8 for cell.utf8str */
ccount = WideCharToMultiByte(
CP_UTF8, 0, wch, -1, (char *) cell.utf8str,
(int) sizeof cell.utf8str, NULL, NULL);
} else {
#endif
/* store the wide version here also, so we don't slow
down back_buffer_flip() with conversions */
cell.wcharacter = wch[0];
#ifdef UTF8_FROM_CORE
}
#endif
} else {
/* we can just use the UTF-8 utf8str field, since ascii is a
single-byte representation of a small subset of unicode */
@@ -1278,6 +1326,11 @@ xputc_core(int ch)
* Overrides wintty.c function of the same name
* for win32. It is used for glyphs only, not text.
*/
#ifdef UTF8_FROM_CORE
/* See g_pututf8() for a corresponding UTF-8 sequence
* version, rather than a single character.
*/
#endif
void
g_putch(int in_ch)
{
@@ -1308,12 +1361,24 @@ g_putch(int in_ch)
cell.attr = console.attr;
cell.colorseq = esc_seq_colors[console.current_nhcolor];
cell.color24 = console.color24 ? console.color24 : 0L;
cell.color256idx = 0;
wch[1] = 0;
if (console.has_unicode) {
wch[0] = (ch >= 0 && ch < SIZE(console.cpMap)) ? console.cpMap[ch] : ch;
#ifdef UTF8_FROM_CORE
if (SYMHANDLING(H_UTF8)) {
/* we have to convert it to UTF-8 for cell.utf8str */
ccount = WideCharToMultiByte(
CP_UTF8, 0, wch, -1, (char *) cell.utf8str,
(int) sizeof cell.utf8str, NULL, NULL);
} else {
#endif
/* store the wide version here also, so we don't slow
down back_buffer_flip() with conversions */
cell.wcharacter = wch[0];
#ifdef UTF8_FROM_CORE
}
#endif
} else {
/* we can just use the UTF-8 utf8str field, since ascii is a
single-byte representation of a small subset of unicode */
@@ -1326,16 +1391,41 @@ g_putch(int in_ch)
}
#ifdef VIRTUAL_TERMINAL_SEQUENCES
#ifdef UTF8_FROM_CORE
/*
* Overrides wintty.c function of the same name
* for win32. It is used for glyphs only, not text and
* only when a UTF-8 sequence is involved for the
* representation. Single character representations
* use g_putch() instead.
*/
void
term_start_24bitcolor(long color24bit)
g_pututf8(uint8 *sequence)
{
console.color24 = color24bit; /* color 0 has bit 0x1000000 set */
set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
cell_t cell;
cell.attr = console.attr;
cell.colorseq = esc_seq_colors[console.current_nhcolor];
cell.color24 = console.color24 ? console.color24 : 0L;
cell.color256idx =console.color256idx ? console.color256idx : 0;
Snprintf((char *) cell.utf8str, sizeof cell.utf8str, "%s",
(char *) sequence);
buffer_write(console.back_buffer, &cell, console.cursor);
}
#endif /* UTF8_FROM_CORE */
void
term_start_24bitcolor(struct unicode_representation *uval)
{
console.color24 = uval->ucolor; /* color 0 has bit 0x1000000 set */
console.color256idx = uval->u256coloridx;
}
void
term_end_24bitcolor(void)
{
console.color24 = 0L;
console.color256idx = 0;
}
#endif /* VIRTUAL_TERMINAL_SEQUENCES */
@@ -1712,7 +1802,15 @@ consoletty_preference_update(const char* pref)
#endif
}
if (stricmp(pref, "symset") == 0) {
#ifdef UTF8_FROM_CORE
if ((tty_procs.wincap2 & WC2_U_UTF8STR) && SYMHANDLING(H_UTF8)) {
#ifdef ENHANCED_SYMBOLS
tty_utf8graphics_fixup();
#endif
} else if ((tty_procs.wincap2 & WC2_U_UTF8STR) && SYMHANDLING(H_IBM)) {
#else
if (SYMHANDLING(H_IBM)) {
#endif
tty_ibmgraphics_fixup();
}
check_and_set_font();
@@ -1720,6 +1818,70 @@ consoletty_preference_update(const char* pref)
return;
}
#ifdef UTF8_FROM_CORE
#ifdef VIRTUAL_TERMINAL_SEQUENCES
/*
* This is called when making the switch to a symset
* with a UTF8 handler to allow any operating system
* specific changes to be carried out.
*/
void
tty_utf8graphics_fixup(void)
{
CONSOLE_FONT_INFOEX console_font_info;
if ((tty_procs.wincap2 & WC2_U_UTF8STR) && SYMHANDLING(H_UTF8)) {
if (!console.hConOut)
console.hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
/* the locale */
if (console.localestr)
free(console.localestr);
console.localestr = strdup(setlocale(LC_ALL, ".UTF8"));
/* the code page */
SetConsoleOutputCP(65001);
console.code_page = GetConsoleOutputCP();
/* the font */
console_font_info.cbSize = sizeof(console_font_info);
BOOL success = GetCurrentConsoleFontEx(console.hConOut, FALSE,
&console_font_info);
/* Try DejaVu Sans Mono for Powerline */
wcscpy_s(console_font_info.FaceName,
sizeof(console_font_info.FaceName)
/ sizeof(console_font_info.FaceName[0]),
L"DejaVu Sans Mono for Powerline");
console_font_info.cbSize = sizeof(console_font_info);
success = SetCurrentConsoleFontEx(console.hConOut, FALSE,
&console_font_info);
if (!success) {
/* Next, try Lucida Console */
wcscpy_s(console_font_info.FaceName,
sizeof(console_font_info.FaceName)
/ sizeof(console_font_info.FaceName[0]),
L"Lucida Console");
console_font_info.cbSize = sizeof(console_font_info);
success = SetCurrentConsoleFontEx(console.hConOut, FALSE,
&console_font_info);
}
nhassert(success);
if (success) {
console.font_info = console_font_info;
console.font_changed = TRUE;
}
/* the console mode */
GetConsoleMode(console.hConOut, &console.out_cmode);
#if 1
if ((console.out_cmode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0) {
/* recognize escape sequences */
console.out_cmode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(console.hConOut, console.out_cmode);
}
#else
console.out_cmode &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING;
#endif
}
}
#endif
#endif /* UTF8_FROM_CORE */
/*
* This is called when making the switch to a symset
* with an IBM handler to allow any operating system
@@ -1836,400 +1998,6 @@ synch_cursor(void)
really_move_cursor();
}
#ifdef CHANGE_COLOR
void
tty_change_color(color_number, rgb, reverse)
int color_number, reverse;
long rgb;
{
/* Map NetHack color index to NT Console palette index */
int idx, win32_color_number[] = {
0, /* CLR_BLACK 0 */
4, /* CLR_RED 1 */
2, /* CLR_GREEN 2 */
6, /* CLR_BROWN 3 */
1, /* CLR_BLUE 4 */
5, /* CLR_MAGENTA 5 */
3, /* CLR_CYAN 6 */
7, /* CLR_GRAY 7 */
8, /* NO_COLOR 8 */
12, /* CLR_ORANGE 9 */
10, /* CLR_BRIGHT_GREEN 10 */
14, /* CLR_YELLOW 11 */
9, /* CLR_BRIGHT_BLUE 12 */
13, /* CLR_BRIGHT_MAGENTA 13 */
11, /* CLR_BRIGHT_CYAN 14 */
15 /* CLR_WHITE 15 */
};
int k;
if (color_number < 0) { /* indicates OPTIONS=palette with no value */
/* copy the NetHack palette into UserDefinedColors */
for (k = 0; k < CLR_MAX; k++)
UserDefinedColors[k] = NetHackColors[k];
} else if (color_number >= 0 && color_number < CLR_MAX) {
if (!altered_palette) {
/* make sure a full suite is available */
for (k = 0; k < CLR_MAX; k++)
UserDefinedColors[k] = DefaultColors[k];
}
idx = win32_color_number[color_number];
UserDefinedColors[idx] = rgb;
}
altered_palette = TRUE;
}
char *
tty_get_color_string()
{
return "";
}
int
match_color_name(c)
const char *c;
{
const struct others {
int idx;
const char *colorname;
} othernames[] = {
{ CLR_MAGENTA, "purple" },
{ CLR_BRIGHT_MAGENTA, "bright purple" },
{ NO_COLOR, "dark gray" },
{ NO_COLOR, "dark grey" },
{ CLR_GRAY, "grey" },
};
int cnt;
for (cnt = 0; cnt < CLR_MAX; ++cnt) {
if (!strcmpi(c, c_obj_colors[cnt]))
return cnt;
}
for (cnt = 0; cnt < SIZE(othernames); ++cnt) {
if (!strcmpi(c, othernames[cnt].colorname))
return othernames[cnt].idx;
}
return -1;
}
/*
* Returns 0 if badoption syntax
*/
int
alternative_palette(op)
char *op;
{
/*
* palette:color-R-G-B
* OPTIONS=palette:green-4-3-1, palette:0-0-0-0
*/
int fieldcnt, color_number, rgb, red, green, blue;
char *fields[4], *cp;
if (!op) {
change_color(-1, 0, 0); /* indicates palette option with
no value meaning "load an entire
hard-coded NetHack palette." */
return 1;
}
cp = fields[0] = op;
for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
cp = index(cp, '-');
if (!cp)
return 0;
fields[fieldcnt] = cp;
cp++;
}
for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
*(fields[fieldcnt]) = '\0';
++fields[fieldcnt];
}
rgb = 0;
for (fieldcnt = 0; fieldcnt < 4; ++fieldcnt) {
if (fieldcnt == 0 && isalpha(*(fields[0]))) {
color_number = match_color_name(fields[0]);
if (color_number == -1)
return 0;
} else {
int dcount = 0, cval = 0;
cp = fields[fieldcnt];
if (*cp == '\\' && index("0123456789xXoO", cp[1])) {
const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
cp++;
if (*cp == 'x' || *cp == 'X')
for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
cval = (int) ((cval * 16) + (dp - hex) / 2);
else if (*cp == 'o' || *cp == 'O')
for (++cp; (index("01234567", *cp)) && (dcount++ < 3);
cp++)
cval = (cval * 8) + (*cp - '0');
else
return 0;
} else {
for (; *cp && (index("0123456789", *cp)) && (dcount++ < 3);
cp++)
cval = (cval * 10) + (*cp - '0');
}
switch (fieldcnt) {
case 0:
color_number = cval;
break;
case 1:
red = cval;
break;
case 2:
green = cval;
break;
case 3:
blue = cval;
break;
}
}
}
rgb = RGB(red, green, blue);
if (color_number >= 0 && color_number < CLR_MAX)
change_color(color_number, rgb, 0);
return 1;
}
/*
* This uses an undocumented method to set console attributes
* at runtime including console palette
*
* VOID WINAPI SetConsolePalette(COLORREF palette[16])
*
* Author: James Brown at www.catch22.net
*
* Set palette of current console.
* Palette should be of the form:
*
* COLORREF DefaultColors[CLR_MAX] =
* {
* 0x00000000, 0x00800000, 0x00008000, 0x00808000,
* 0x00000080, 0x00800080, 0x00008080, 0x00c0c0c0,
* 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
* 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
* };
*/
#pragma pack(push, 1)
/*
* Structure to send console via WM_SETCONSOLEINFO
*/
typedef struct _CONSOLE_INFO {
ULONG Length;
COORD ScreenBufferSize;
COORD WindowSize;
ULONG WindowPosX;
ULONG WindowPosY;
COORD FontSize;
ULONG FontFamily;
ULONG FontWeight;
WCHAR FaceName[32];
ULONG CursorSize;
ULONG FullScreen;
ULONG QuickEdit;
ULONG AutoPosition;
ULONG InsertMode;
USHORT ScreenColors;
USHORT PopupColors;
ULONG HistoryNoDup;
ULONG HistoryBufferSize;
ULONG NumberOfHistoryBuffers;
COLORREF ColorTable[16];
ULONG CodePage;
HWND Hwnd;
WCHAR ConsoleTitle[0x100];
} CONSOLE_INFO;
#pragma pack(pop)
BOOL SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci);
static void GetConsoleSizeInfo(CONSOLE_INFO *pci);
VOID WINAPI SetConsolePalette(COLORREF crPalette[16]);
void
adjust_palette(void)
{
SetConsolePalette(UserDefinedColors);
altered_palette = 0;
}
/*
/* only in Win2k+ (use FindWindow for NT4) */
/* HWND WINAPI GetConsoleWindow(); */
/* Undocumented console message */
#define WM_SETCONSOLEINFO (WM_USER + 201)
VOID WINAPI
SetConsolePalette(COLORREF palette[16])
{
CONSOLE_INFO ci = { sizeof(ci) };
int i;
HWND hwndConsole = GetConsoleHandle();
/* get current size/position settings rather than using defaults.. */
GetConsoleSizeInfo(&ci);
/* set these to zero to keep current settings */
ci.FontSize.X = 0; /* def = 8 */
ci.FontSize.Y = 0; /* def = 12 */
ci.FontFamily = 0; /* def = 0x30 = FF_MODERN|FIXED_PITCH */
ci.FontWeight = 0; /* 0x400; */
/* lstrcpyW(ci.FaceName, L"Terminal"); */
ci.FaceName[0] = L'\0';
ci.CursorSize = 25;
ci.FullScreen = FALSE;
ci.QuickEdit = TRUE;
ci.AutoPosition = 0x10000;
ci.InsertMode = TRUE;
ci.ScreenColors = MAKEWORD(0x7, 0x0);
ci.PopupColors = MAKEWORD(0x5, 0xf);
ci.HistoryNoDup = FALSE;
ci.HistoryBufferSize = 50;
ci.NumberOfHistoryBuffers = 4;
// colour table
for (i = 0; i < 16; i++)
ci.ColorTable[i] = palette[i];
ci.CodePage = GetConsoleOutputCP();
ci.Hwnd = hwndConsole;
lstrcpyW(ci.ConsoleTitle, L"");
SetConsoleInfo(hwndConsole, &ci);
}
/*
* Wrapper around WM_SETCONSOLEINFO. We need to create the
* necessary section (file-mapping) object in the context of the
* process which owns the console, before posting the message
*/
BOOL
SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci)
{
DWORD dwConsoleOwnerPid;
HANDLE hProcess;
HANDLE hSection, hDupSection;
PVOID ptrView = 0;
HANDLE hThread;
/*
* Open the process which "owns" the console
*/
GetWindowThreadProcessId(hwndConsole, &dwConsoleOwnerPid);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwConsoleOwnerPid);
/*
* Create a SECTION object backed by page-file, then map a view of
* this section into the owner process so we can write the contents
* of the CONSOLE_INFO buffer into it
*/
hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
pci->Length, 0);
/*
* Copy our console structure into the section-object
*/
ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0,
pci->Length);
memcpy(ptrView, pci, pci->Length);
UnmapViewOfFile(ptrView);
/*
* Map the memory into owner process
*/
DuplicateHandle(GetCurrentProcess(), hSection, hProcess, &hDupSection, 0,
FALSE, DUPLICATE_SAME_ACCESS);
/* Send console window the "update" message */
SendMessage(hwndConsole, WM_SETCONSOLEINFO, (WPARAM) hDupSection, 0);
/*
* clean up
*/
hThread = CreateRemoteThread(hProcess, 0, 0,
(LPTHREAD_START_ROUTINE) CloseHandle,
hDupSection, 0, 0);
CloseHandle(hThread);
CloseHandle(hSection);
CloseHandle(hProcess);
return TRUE;
}
/*
* Fill the CONSOLE_INFO structure with information
* about the current console window
*/
static void
GetConsoleSizeInfo(CONSOLE_INFO *pci)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
HANDLE hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleOut, &csbi);
pci->ScreenBufferSize = csbi.dwSize;
pci->WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
pci->WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
pci->WindowPosX = csbi.srWindow.Left;
pci->WindowPosY = csbi.srWindow.Top;
}
static HWND
GetConsoleHandle(void)
{
HMODULE hMod = GetModuleHandle("kernel32.dll");
GETCONSOLEWINDOW pfnGetConsoleWindow =
(GETCONSOLEWINDOW) GetProcAddress(hMod, "GetConsoleWindow");
if (pfnGetConsoleWindow)
return pfnGetConsoleWindow();
else
return GetConsoleHwnd();
}
static HWND
GetConsoleHwnd(void)
{
int iterations = 0;
HWND hwndFound = 0;
char OldTitle[1024], NewTitle[1024], TestTitle[1024];
/* Get current window title */
GetConsoleTitle(OldTitle, sizeof OldTitle);
(void) sprintf(NewTitle, "NETHACK%d/%d", GetTickCount(),
GetCurrentProcessId());
SetConsoleTitle(NewTitle);
GetConsoleTitle(TestTitle, sizeof TestTitle);
while (strcmp(TestTitle, NewTitle) != 0) {
iterations++;
/* sleep(0); */
GetConsoleTitle(TestTitle, sizeof TestTitle);
}
hwndFound = FindWindow(NULL, NewTitle);
SetConsoleTitle(OldTitle);
/* printf("%d iterations\n", iterations); */
return hwndFound;
}
#endif /*CHANGE_COLOR*/
static int CALLBACK EnumFontCallback(
const LOGFONTW * lf, const TEXTMETRICW * tm, DWORD fontType, LPARAM lParam)
{
@@ -2271,8 +2039,8 @@ check_font_widths(void)
* NOTE: the DC from the console window does not have the correct
* font selected at this point.
*/
HWND hWnd = GetConsoleWindow();
HDC hDC = GetDC(hWnd);
console.hWnd = GetConsoleWindow();
HDC hDC = GetDC(console.hWnd);
LOGFONTW logical_font;
logical_font.lfCharSet = DEFAULT_CHARSET;
@@ -2574,6 +2342,14 @@ void nethack_enter_consoletty(void)
#if 0
/* set up state needed by early_raw_print() */
windowprocs.win_raw_print = early_raw_print;
#endif
#if 0
/* prevent re-sizing of the console window */
if (!console.hWnd)
console.hWnd = GetConsoleWindow();
SetWindowLong(console.hWnd, GWL_STYLE,
GetWindowLong(console.hWnd, GWL_STYLE)
& ~WS_MAXIMIZEBOX & ~WS_SIZEBOX);
#endif
console.hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
nhassert(console.hConOut != NULL); // NOTE: this assert will not print

View File

@@ -35,6 +35,16 @@ extern void backsp(void);
#endif
extern void clear_screen(void);
#if defined(TERMLIB) || defined(CURSES_GRAPHICS)
extern void (*decgraphics_mode_callback)(void);
#endif
#ifdef CURSES_GRAPHICS
extern void (*cursesgraphics_mode_callback)(void);
#endif
#ifdef ENHANCED_SYMBOLS
extern void (*utf8graphics_mode_callback)(void);
#endif
#ifdef _MSC_VER
#ifdef kbhit
#undef kbhit
@@ -393,7 +403,8 @@ copy_hack_content()
update_file(g.fqn_prefix[HACKPREFIX], OPTIONFILE,
g.fqn_prefix[DATAPREFIX], OPTIONFILE, FALSE);
}
extern const char *known_handling[]; /* symbols.c */
extern const char *known_restrictions[]; /* symbols.c */
/*
* __MINGW32__ Note
* If the graphics version is built, we don't need a main; it is skipped
@@ -420,7 +431,7 @@ mingw_main(int argc, char *argv[])
safe_routines();
early_init();
#ifdef _MSC_VER
# ifdef DEBUG
#ifdef DEBUG
/* set these appropriately for VS debugging */
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR,
@@ -439,7 +450,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
| _CRTDBG_LEAK_CHECK_DF);
_CrtSetBreakAlloc(1423);
*/
# endif
#endif
#endif
g.hname = "NetHack"; /* used for syntax messages */
@@ -480,7 +491,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
}
/* Finished processing options, lock all directory paths */
for(int i = 0; i < PREFIX_COUNT; i++)
for (int i = 0; i < PREFIX_COUNT; i++)
fqn_prefix_locked[i] = TRUE;
if (!validate_prefix_locations(failbuf)) {
@@ -491,23 +502,23 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
copy_hack_content();
/*
* It seems you really want to play.
*/
if (argc >= 1
&& !strcmpi(default_window_sys, "mswin")
/*
* It seems you really want to play.
*/
if (argc >= 1 && !strcmpi(default_window_sys, "mswin")
&& (strstri(argv[0], "nethackw.exe") || GUILaunched))
iflags.windowtype_locked = TRUE;
windowtype = default_window_sys;
#ifdef DLB
if (!dlb_init()) {
pline("%s\n%s\n%s\n%s\n\n",
copyright_banner_line(1), copyright_banner_line(2),
copyright_banner_line(3), copyright_banner_line(4));
pline("NetHack was unable to open the required file \"%s\"",DLBFILE);
pline("%s\n%s\n%s\n%s\n\n", copyright_banner_line(1),
copyright_banner_line(2), copyright_banner_line(3),
copyright_banner_line(4));
pline("NetHack was unable to open the required file \"%s\"", DLBFILE);
if (file_exists(DLBFILE))
pline("\nAre you perhaps trying to run NetHack within a zip utility?");
pline("\nAre you perhaps trying to run NetHack within a zip "
"utility?");
error("dlb_init failure.");
}
#endif
@@ -540,6 +551,33 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
if (WINDOWPORT("tty"))
toggle_mouse_support();
if (g.symset[PRIMARYSET].handling
&& !symset_is_compatible(g.symset[PRIMARYSET].handling,
windowprocs.wincap2)) {
/* current symset handling and windowtype are
not compatible, feature-wise. Use IBM defaults */
load_symset("IBMGraphics_2", PRIMARYSET);
load_symset("RogueEpyx", ROGUESET);
}
/* Has the callback for the symset been invoked? Config file processing to
load a symset runs too early to accomplish that because
the various *graphics_mode_callback pointers don't get set until
term_start_screen, unfortunately */
#if defined(TERMLIB) || defined(CURSES_GRAPHICS)
if (SYMHANDLING(H_DEC) && decgraphics_mode_callback)
(*decgraphics_mode_callback)();
#endif /* TERMLIB || CURSES */
#if 0
#ifdef CURSES_GRAPHICS
if (WINDOWPORT("curses"))
(*cursesgraphics_mode_callback)();
#endif
#endif
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8) && utf8graphics_mode_callback)
(*utf8graphics_mode_callback)();
#endif
/* strip role,race,&c suffix; calls askname() if g.plname[] is empty
or holds a generic user name like "player" or "games" */
plnamesuffix();
@@ -656,7 +694,12 @@ process_options(int argc, char * argv[])
#ifndef NODUMPENUMS
if (argcheck(argc, argv, ARG_DUMPENUMS) == 2) {
nethack_exit(EXIT_SUCCESS);
}
}
#ifdef ENHANCED_SYMBOLS
if (argcheck(argc, argv, ARG_DUMPGLYPHIDS) == 2) {
nethack_exit(EXIT_SUCCESS);
}
#endif
#endif
if (argcheck(argc, argv, ARG_DEBUG) == 1) {
argc--;

View File

@@ -547,7 +547,7 @@ void NetHackQtMapViewport::PrintGlyph(int x, int y,
{
Glyph(x, y) = (unsigned short) glyphinfo->glyph;
Glyphttychar(x, y) = (unsigned short) glyphinfo->ttychar;
Glyphcolor(x, y) = (unsigned short) glyphinfo->gm.color;
Glyphcolor(x, y) = (unsigned short) glyphinfo->gm.sym.color;
Glyphflags(x, y) = glyphinfo->gm.glyphflags;
Glyphtileidx(x, y) = (unsigned short) glyphinfo->gm.tileidx;
Changed(x, y);

View File

@@ -113,7 +113,7 @@ X11_print_glyph(
register unsigned char *co_ptr;
#endif
color = glyphinfo->gm.color;
color = glyphinfo->gm.sym.color;
special = glyphinfo->gm.glyphflags;
och = glyphinfo->ttychar;
ch = (uchar) och;

View File

@@ -741,8 +741,8 @@ curses_init_options(void)
set_option_mod_status("eight_bit_tty", set_in_config);
/* If we don't have a symset defined, load the curses symset by default */
if (!g.symset[PRIMARY].explicitly)
load_symset("curses", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("curses", PRIMARYSET);
if (!g.symset[ROGUESET].explicitly)
load_symset("default", ROGUESET);

View File

@@ -7,6 +7,9 @@
#include "hack.h"
#include "color.h"
#include "wincurs.h"
#ifdef CURSES_UNICODE
#include "locale.h"
#endif
/* define this if not linking with <foo>tty.o|.obj for some reason */
#ifdef CURSES_DEFINE_ERASE_CHAR
@@ -41,6 +44,9 @@ struct window_procs curses_procs = {
#endif
| WC_PERM_INVENT | WC_POPUP_DIALOG | WC_SPLASH_SCREEN),
(WC2_DARKGRAY | WC2_HITPOINTBAR
#ifdef CURSES_UNICODE
| WC2_U_UTF8STR
#endif
#ifdef SELECTSAVED
| WC2_SELECTSAVED
#endif
@@ -150,6 +156,10 @@ curses_init_nhwindows(int *argcp UNUSED,
char window_title[BUFSZ];
#endif
#ifdef CURSES_UNICODE
setlocale(LC_CTYPE, "");
#endif
#ifdef XCURSES
base_term = Xinitscr(*argcp, argv);
#else
@@ -760,7 +770,7 @@ curses_print_glyph(winid wid, xchar x, xchar y,
glyph = glyphinfo->glyph;
special = glyphinfo->gm.glyphflags;
ch = glyphinfo->ttychar;
color = glyphinfo->gm.color;
color = glyphinfo->gm.sym.color;
if ((special & MG_PET) && iflags.hilite_pet) {
attr = iflags.wc2_petattr;
}
@@ -789,7 +799,17 @@ curses_print_glyph(winid wid, xchar x, xchar y,
}
}
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8)
&& glyphinfo->gm.u
&& glyphinfo->gm.u->utf8str) {
curses_putch(wid, x, y, ch, glyphinfo->gm.u, color, attr);
} else {
curses_putch(wid, x, y, ch, NULL, color, attr);
}
#else
curses_putch(wid, x, y, ch, color, attr);
#endif
}
/*

View File

@@ -33,6 +33,7 @@ typedef struct nhchar {
int ch; /* character */
int color; /* color info for character */
int attr; /* attributes of character */
struct unicode_representation *unicode_representation;
} nethack_char;
static boolean map_clipped; /* Map window smaller than 80x21 */
@@ -363,7 +364,13 @@ curs_destroy_all_wins(void)
/* Print a single character in the given window at the given coordinates */
void
#ifdef ENHANCED_SYMBOLS
curses_putch(winid wid, int x, int y, int ch,
struct unicode_representation *unicode_representation,
int color, int attr)
#else
curses_putch(winid wid, int x, int y, int ch, int color, int attr)
#endif
{
static boolean map_initted = FALSE;
int sx, sy, ex, ey;
@@ -387,6 +394,9 @@ curses_putch(winid wid, int x, int y, int ch, int color, int attr)
map[y][x].ch = ch;
map[y][x].color = color;
map[y][x].attr = attr;
#ifdef ENHANCED_SYMBOLS
map[y][x].unicode_representation = unicode_representation;
#endif
nch = map[y][x];
(void) curses_map_borders(&sx, &sy, &ex, &ey, -1, -1);
@@ -589,7 +599,10 @@ write_char(WINDOW * win, int x, int y, nethack_char nch)
#ifdef PDCURSES
mvwaddrawch(win, y, x, nch.ch);
#else
mvwaddch(win, y, x, nch.ch);
if (nch.unicode_representation && nch.unicode_representation->utf8str)
mvwprintw(win, y, x, "%s", nch.unicode_representation->utf8str);
else
mvwaddch(win, y, x, nch.ch);
#endif
curses_toggle_color_attr(win, nch.color, nch.attr, OFF);
}
@@ -694,6 +707,7 @@ clear_map(void)
map[y][x].ch = ' ';
map[y][x].color = NO_COLOR;
map[y][x].attr = A_NORMAL;
map[y][x].unicode_representation = NULL;
}
}
}

View File

@@ -21,7 +21,12 @@ void curses_refresh_nhwin(winid wid);
void curses_del_nhwin(winid wid);
void curses_del_wid(winid wid);
void curs_destroy_all_wins(void);
#ifdef ENHANCED_SYMBOLS
void curses_putch(winid wid, int x, int y, int ch,
struct unicode_representation *ur, int color, int attrs);
#else
void curses_putch(winid wid, int x, int y, int ch, int color, int attrs);
#endif
void curses_get_window_xy(winid wid, int *x, int *y);
boolean curses_window_has_border(winid wid);
boolean curses_window_exists(winid wid);

View File

@@ -1341,22 +1341,32 @@ main(int argc UNUSED, char *argv[] UNUSED)
Fprintf(ofp, "int maxmontile = %d,\n", lastmontile);
Fprintf(ofp, "%smaxobjtile = %d,\n", indent, lastobjtile);
Fprintf(ofp, "%smaxothtile = %d;\n\n", indent, lastothtile);
Fprintf(ofp,
"/* glyph, ttychar, { color, symidx, ovidx, glyphflags, tileidx} */\n");
Fprintf(ofp,
"/* glyph, ttychar, { glyphflags, {color, symidx}, ovidx, tileidx, 0 } */\n");
Fprintf(ofp, "const glyph_info nul_glyphinfo = { \n");
Fprintf(ofp, "%sNO_GLYPH, ' ',\n", indent);
Fprintf(ofp, "%s%s{ /* glyph_map */\n", indent, indent);
Fprintf(ofp, "%s%s%sNO_COLOR, SYM_UNEXPLORED + SYM_OFF_X,\n",
Fprintf(ofp, "%s%s%sMG_UNEXPL, { NO_COLOR, SYM_UNEXPLORED + SYM_OFF_X },\n",
indent, indent, indent);
Fprintf(ofp, "%s%s%sMG_UNEXPL, %d\n", indent, indent, indent,
#ifdef ENHANCED_SYMBOLS
Fprintf(ofp, "%s%s%s%d, 0\n", indent, indent, indent,
TILE_unexplored);
#else
Fprintf(ofp, "%s%s%s%d\n", indent, indent, indent,
TILE_unexplored);
#endif
Fprintf(ofp, "%s%s}\n", indent, indent);
Fprintf(ofp, "};\n");
Fprintf(ofp, "\nglyph_map glyphmap[MAX_GLYPH] = {\n");
for (i = 0; i < MAX_GLYPH; i++) {
tilenum = tilemap[i].tilenum;
Fprintf(ofp, " { 0, 0, 0U, %4d }, /* [%04d] %s=%03d %s */\n",
Fprintf(ofp,
#ifdef ENHANCED_SYMBOLS
" { 0U, { 0, 0 }, %4d, 0 }, /* [%04d] %s:%03d %s */\n",
#else
" { 0U, { 0, 0 }, %4d}, /* [%04d] %s:%03d %s */\n",
#endif
tilenum, i,
tilesrc_texts[tilelist[tilenum]->src],
tilelist[tilenum]->file_entry,

View File

@@ -17,6 +17,9 @@ static char *e_atr2str(int);
void cmov(int, int);
void nocmov(int, int);
void term_start_24bitcolor(struct unicode_representation *);
void term_end_24bitcolor(void);
#if defined(TEXTCOLOR) && defined(TERMLIB)
#if (!defined(UNIX) || !defined(TERMINFO)) && !defined(TOS)
static void analyze_seq(char *, int *, int *);
@@ -430,11 +433,12 @@ tty_decgraphics_termcap_fixup(void)
#endif /* TERMLIB */
#if defined(ASCIIGRAPH) && defined(PC9800)
extern void (*ibmgraphics_mode_callback)(void); /* defined in drawing.c */
extern void (*ibmgraphics_mode_callback)(void); /* defined in symbols.c */
#endif
extern void (*utf8graphics_mode_callback)(void); /* defined in symbols.c */
#ifdef PC9800
extern void (*ascgraphics_mode_callback)(void); /* defined in drawing.c */
extern void (*ascgraphics_mode_callback)(void); /* defined in symbols.c */
static void tty_ascgraphics_hilite_fixup(void);
static void
@@ -478,6 +482,10 @@ tty_start_screen(void)
/* set up callback in case option is not set yet but toggled later */
decgraphics_mode_callback = tty_decgraphics_termcap_fixup;
#endif
#ifdef ENHANCED_SYMBOLS
utf8graphics_mode_callback = tty_utf8graphics_fixup;
#endif
if (g.Cmd.num_pad)
tty_number_pad(1); /* make keypad send digits */
}
@@ -870,14 +878,21 @@ const struct {
{ COLOR_MAGENTA, CLR_MAGENTA, CLR_BRIGHT_MAGENTA },
{ COLOR_CYAN, CLR_CYAN, CLR_BRIGHT_CYAN } };
typedef struct {
unsigned char r, g, b;
} RGB;
static char nilstring[] = "";
static void
init_hilite(void)
{
int c, colors;
char *setf, *scratch;
int c, md_len = 0;
int colors = tgetnum("Co");
colors = tgetnum("Co");
iflags.colorcount = colors;
int md_len = 0;
if (colors < 8 || (MD == NULL) || (strlen(MD) == 0)
|| ((setf = tgetstr("AF", (char **) 0)) == (char *) 0
@@ -1410,9 +1425,66 @@ term_start_color(int color)
if (color < CLR_MAX && hilites[color] && *hilites[color])
xputs(hilites[color]);
}
#endif /* TEXTCOLOR */
#endif /* TTY_GRAPHICS && !NO_TERMS */
#ifdef ENHANCED_SYMBOLS
#ifndef SEP2
#define tcfmtstr "\033[38;2;%ld;%ld;%ldm"
#ifdef UNIX
#define tcfmtstr24bit "\033[38;2;%u;%u;%um"
#define tcfmtstr256 "\033[38;5;%dm"
#else
#define tcfmtstr "\033[38:2:%ld:%ld:%ldm"
#define tcfmtstr24bit "\033[38;2;%lu;%lu;%lum"
#define tcfmtstr256 "\033[38:5:%ldm"
#endif
#endif
static void emit24bit(long mcolor);
static void emit256(int u256coloridx);
static void emit24bit(long mcolor)
{
static char tcolorbuf[QBUFSZ];
Snprintf(tcolorbuf, sizeof tcolorbuf, tcfmtstr,
((mcolor >> 16) & 0xFF), /* red */
((mcolor >> 8) & 0xFF), /* green */
((mcolor >> 0) & 0xFF)); /* blue */
xputs(tcolorbuf);
}
static void emit256(int u256coloridx)
{
static char tcolorbuf[QBUFSZ];
Snprintf(tcolorbuf, sizeof tcolorbuf, tcfmtstr256,
u256coloridx);
xputs(tcolorbuf);
}
void
term_start_24bitcolor(struct unicode_representation *urep)
{
if (urep && SYMHANDLING(H_UTF8)) {
/* color 0 has bit 0x1000000 set */
long mcolor = (urep->ucolor & 0xFFFFFF);
if (iflags.colorcount == 256)
emit256(urep->u256coloridx);
else
emit24bit(mcolor);
}
}
void
term_end_24bitcolor(void)
{
if (SYMHANDLING(H_UTF8)) {
xputs("\033[0m");
}
}
#endif /* ENHANCED_SYMBOLS */
#endif /* TTY_GRAPHICS && !NO_TERMS */
/*termcap.c*/

View File

@@ -124,13 +124,15 @@ redotoplin(const char *str)
int otoplin = ttyDisplay->toplin;
home();
if (*str & 0x80) {
/* kludge for the / command, the only time we ever want a */
/* graphics character on the top line */
g_putch((int) *str++);
ttyDisplay->curx++;
if (!ttyDisplay->topl_utf8) {
if (*str & 0x80) {
/* kludge for the / command, the only time we ever want a */
/* graphics character on the top line */
g_putch((int) *str++);
ttyDisplay->curx++;
}
end_glyphout(); /* in case message printed during graphics output */
}
end_glyphout(); /* in case message printed during graphics output */
putsyms(str);
cl_end();
ttyDisplay->toplin = TOPLINE_NEED_MORE;

View File

@@ -97,7 +97,7 @@ struct window_procs tty_procs = {
#ifdef MSDOS
| WC_TILED_MAP | WC_ASCII_MAP
#endif
#if defined(WIN32CON)
#if defined(WIN32)
| WC_MOUSE_SUPPORT
#endif
| WC_COLOR | WC_HILITE_PET | WC_INVERSE | WC_EIGHT_BIT_IN),
@@ -109,7 +109,12 @@ struct window_procs tty_procs = {
| WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS
| WC2_RESET_STATUS
#endif
| WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_STATUSLINES),
| WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_STATUSLINES)
| WC2_U_UTF8STR
#if !defined(NO_TERMS) || defined(WIN32)
| WC2_U_24BITCOLOR
#endif
,
#ifdef TEXTCOLOR
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
#else
@@ -118,7 +123,8 @@ struct window_procs tty_procs = {
tty_init_nhwindows, tty_player_selection, tty_askname, tty_get_nh_event,
tty_exit_nhwindows, tty_suspend_nhwindows, tty_resume_nhwindows,
tty_create_nhwindow, tty_clear_nhwindow, tty_display_nhwindow,
tty_destroy_nhwindow, tty_curs, tty_putstr, genl_putmixed,
tty_destroy_nhwindow, tty_curs, tty_putstr,
tty_putmixed,
tty_display_file, tty_start_menu, tty_add_menu, tty_end_menu,
tty_select_menu, tty_message_menu, tty_update_inventory, tty_mark_synch,
tty_wait_synch,
@@ -159,6 +165,7 @@ struct DisplayDesc *ttyDisplay; /* the tty display descriptor */
extern void cmov(int, int); /* from termcap.c */
extern void nocmov(int, int); /* from termcap.c */
#if defined(UNIX) || defined(VMS)
static char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
#endif
@@ -231,6 +238,9 @@ static void shrink_dlvl(int);
static void status_sanity_check(void);
#endif /* NH_DEVEL_STATUS */
#endif
#if !defined(NO_TERMS) && !defined(WIN32)
void g_pututf8(uint8 *utf8str);
#endif
/*
* A string containing all the default commands -- to add to a list
@@ -442,6 +452,7 @@ tty_init_nhwindows(int *argcp UNUSED, char **argv UNUSED)
/* set up tty descriptor */
ttyDisplay = (struct DisplayDesc *) alloc(sizeof (struct DisplayDesc));
ttyDisplay->toplin = TOPLINE_EMPTY;
ttyDisplay->topl_utf8 = 0; /* putmixed may set this */
ttyDisplay->rows = hgt;
ttyDisplay->cols = wid;
ttyDisplay->curx = ttyDisplay->cury = 0;
@@ -2344,9 +2355,14 @@ process_text_window(winid window, struct WinDesc *cw)
) {
/* message recall for msg_window:full/combination/reverse
might have output from '/' in it (see redotoplin()) */
if (linestart && (*cp & 0x80) != 0) {
g_putch(*cp);
end_glyphout();
if (linestart) {
if (SYMHANDLING(H_UTF8)) {
/* FIXME: what is actually in that line? is it the \GNNNNNNNN or UTF-8? */
g_putch(*cp);
} else if ((*cp & 0x80) != 0) {
g_putch(*cp);
end_glyphout();
}
linestart = FALSE;
} else {
(void) putchar(*cp);
@@ -3367,8 +3383,11 @@ g_putch(int in_ch)
register char ch = (char) in_ch;
HUPSKIP();
#if defined(ASCIIGRAPH) && !defined(NO_TERMS)
if (SYMHANDLING(H_IBM)
if (SYMHANDLING(H_UTF8)) {
(void) putchar(ch);
} else if (SYMHANDLING(H_IBM)
/* for DECgraphics, lower-case letters with high bit set mean
switch character set and render with high bit clear;
user might want 8-bits for other characters */
@@ -3397,6 +3416,17 @@ g_putch(int in_ch)
return;
}
void
g_pututf8(uint8 *utf8str)
{
HUPSKIP();
while (*utf8str) {
(void) putchar(*utf8str);
utf8str++;
}
return;
}
#endif /* !WIN32 */
#ifdef CLIPPING
@@ -3458,6 +3488,11 @@ tty_print_glyph(winid window, xchar x, xchar y,
boolean inverse_on = FALSE;
int ch, color;
unsigned special;
#ifdef ENHANCED_SYMBOLS
#if !defined(NO_TERMS) || defined(WIN32)
boolean color24bit_on = FALSE;
#endif
#endif
HUPSKIP();
#ifdef CLIPPING
@@ -3468,7 +3503,7 @@ tty_print_glyph(winid window, xchar x, xchar y,
#endif
/* get glyph ttychar, color, and special flags */
ch = glyphinfo->ttychar;
color = glyphinfo->gm.color;
color = glyphinfo->gm.sym.color;
special = glyphinfo->gm.glyphflags;
print_vt_code2(AVTC_SELECT_WINDOW, window);
@@ -3484,24 +3519,33 @@ tty_print_glyph(winid window, xchar x, xchar y,
backsp();
}
#endif
if (iflags.use_color) {
#ifdef TEXTCOLOR
if (iflags.wizmgender && (special & MG_FEMALE) && iflags.use_inverse) {
if (ttyDisplay->color != NO_COLOR)
term_end_color();
term_start_attr(ATR_INVERSE);
inverse_on = TRUE;
ttyDisplay->color = CLR_RED;
term_start_color(ttyDisplay->color);
} else if (color != ttyDisplay->color) {
if (ttyDisplay->color != NO_COLOR)
term_end_color();
ttyDisplay->color = color;
if (color != NO_COLOR)
term_start_color(color);
}
if (color != ttyDisplay->color) {
if (ttyDisplay->color != NO_COLOR)
term_end_color();
}
#endif
#if !defined(NO_TERMS) || defined(WIN32)
#ifdef ENHANCED_SYMBOLS
/* we don't link with termcap.o if NO_TERMS is defined */
if ((tty_procs.wincap2 & WC2_U_24BITCOLOR) && SYMHANDLING(H_UTF8)
&& glyphinfo->gm.u && glyphinfo->gm.u->ucolor) {
term_start_24bitcolor(glyphinfo->gm.u);
color24bit_on = TRUE;
} else
#endif
#endif
{
#ifdef TEXTCOLOR
ttyDisplay->color = color;
if (color != NO_COLOR)
term_start_color(color);
#endif /* TEXTCOLOR */
#if !defined(NO_TERMS) || defined(WIN32)
}
#endif
} /* iflags.use_color aka iflags.wc_color */
/* must be after color check; term_end_color may turn off inverse too;
BW_LAVA and BW_ICE won't ever be set when color is on;
(tried bold for ice but it didn't look very good; inverse is easier
@@ -3519,21 +3563,34 @@ tty_print_glyph(winid window, xchar x, xchar y,
xputg(glyphinfo);
else
#endif
g_putch(ch); /* print the character */
if (inverse_on) {
#ifdef ENHANCED_SYMBOLS
if ((tty_procs.wincap2 & WC2_U_UTF8STR) && SYMHANDLING(H_UTF8)
&& glyphinfo->gm.u && glyphinfo->gm.u->utf8str) {
/* we have a sequence to do */
g_pututf8(glyphinfo->gm.u->utf8str);
} else
#endif
g_putch(ch); /* print the character */
if (inverse_on)
term_end_attr(ATR_INVERSE);
if (iflags.use_color) {
#ifdef TEXTCOLOR
/* turn off color as well, turning off ATR_INVERSE may have done
this already and if so, we won't know the current state unless
we do it explicitly */
this already and if so, we won't know the current state unless
we do it explicitly */
if (ttyDisplay->color != NO_COLOR) {
term_end_color();
ttyDisplay->color = NO_COLOR;
}
#endif
#ifdef ENHANCED_SYMBOLS
#if !defined(NO_TERMS) || defined(WIN32)
if (color24bit_on)
term_end_24bitcolor();
#endif
#endif
}
print_vt_code1(AVTC_GLYPH_END);
wins[window]->curx++; /* one character over */
@@ -3688,6 +3745,31 @@ tty_update_positionbar(char *posbar)
}
#endif /* POSITIONBAR */
void
tty_putmixed(winid window, int attr, const char *str)
{
struct WinDesc *cw;
char buf[BUFSZ];
#ifdef ENHANCED_SYMBOLS
int utf8flag = 0;
#endif
if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0) {
tty_raw_print(str);
return;
}
#ifdef ENHANCED_SYMBOLS
if ((windowprocs.wincap2 & WC2_U_UTF8STR) && SYMHANDLING(H_UTF8)) {
mixed_to_utf8(buf, sizeof buf, str, &utf8flag);
if (cw->type == NHW_MESSAGE)
ttyDisplay->topl_utf8 = utf8flag;
} else
#endif
decode_mixed(buf, str);
/* now send it to the normal tty_putstr */
tty_putstr(window, attr, buf);
ttyDisplay->topl_utf8 = 0;
}
/*
* +------------------+

View File

@@ -930,7 +930,7 @@ paintGlyph(PNHMapWindow data, int i, int j, RECT * rect)
OldFg = SetTextColor(hDC, nhcolor_to_RGB(color));
#else
ch = (char) data->map[i][j].ttychar;
color = (int) data->map[i][j].gm.color;
color = (int) data->map[i][j].gm.sym.color;
if (((data->map[i][j].gm.glyphflags & MG_PET) && iflags.hilite_pet)
|| ((data->map[i][j].gm.glyphflags & (MG_DETECT | MG_BW_LAVA))
&& iflags.use_inverse)) {
@@ -1000,7 +1000,7 @@ static void setGlyph(PNHMapWindow data, int i, int j,
if ((data->map[i][j].glyph != fg->glyph)
|| (data->bkmap[i][j].glyph != bg->glyph)
|| data->map[i][j].ttychar != fg->ttychar
|| data->map[i][j].gm.color != fg->gm.color
|| data->map[i][j].gm.sym.color != fg->gm.sym.color
|| data->map[i][j].gm.glyphflags != fg->gm.glyphflags
|| data->map[i][j].gm.tileidx != fg->gm.tileidx) {
data->map[i][j] = *fg;