add some unicode support (trunk only)

This patch attempts to add some levels of unicode support
to NetHack.

The master on/off switch for any Unicode support is
defining UNICODE_SUPPORT in config.h. Currently
there is code support for two subsets of unicode support:

UNICODE_DRAWING

If UNICODE_DRAWING is defined, then the data
structures used to house drawing symbols are expanded
to the size of wchar_t, big enough to hold unicode characters.
A typdef called `nhsym' is involved and if UNICODE_DRAWING
is defined, it is wchar_t, otherwise it is uchar.

UNICODE_WIDEWINPORT

If UNICODE_WIDEWINPORT is defined, then the data
structures inside the window port are expanded to the size of
wchar_t, big enough to hold unicode characters.  Both map
symbols and text within the window port are expanded, in order
for potential support for displaying multinational characters some
day, but this patch only provides viewing of map symbols.
A typdef called `nhwchar' is involved and if UNICODE_WIDEWINPORT
is defined, it is wchar_t, otherwise it is char.

The only window port with code support for UNICODE_WIDEWINPORT
currently is the TTY port.  Don't enable UNICODE_WIDEWINPORT
unless:
- it is a TTY port
- the underlying platform specific routines can
handle the larger data structures.

Don't enable UNICODE_SUPPORT unless:
- your compiler can handle wchar_t.
- your compiler can accept L'a' characters.
- your compiler can accept L"wide" strings.

Note that if your compiler can handle the above, you could
enable the larger data structures (currently if TTY) even if your
platform can't actually display unicode or UTF-8, by messing
with u_putch() in win/tty/wintty.c to only deal regular chars.
That should be the only function that actually pushes wide characters
out to the display.

If you enable UNICODE_SUPPORT, and your platform is capable
you will need to turn on the unicode run-time option to be able to
load unicode character sets from the symbol file, to be able to
push unicode characters to the display. You'll also want to load
a unicode symbol set once the unicode option is toggled on. In
a config file you would do that via these two lines:
OPTIONS=unicode
OPTIONS=symset:Unicode_non_US

The repository was stamped with NETHACK_PRE_UNICODE
prior to applying this patch, and stamped with
NETHACK_POST_UNICODE afterwards. The code differences
between those two tagged versions are this patch.
This commit is contained in:
nethack.allison
2006-10-17 23:55:42 +00:00
parent 3054c1c846
commit 7f0f43e6f9
22 changed files with 1193 additions and 177 deletions

View File

@@ -201,6 +201,10 @@ start: RogueEpyx
S_food: \x05 # club (as in cards)
S_potion: \xad # upside down '!'
S_scroll: \x0e # musical note
# S_armor: \x5b
# S_ring: \x3d
# S_amulet: \x0c
# S_tool: \x28
S_wand: \xe7 # greek tau
S_coin: \x0f # yes it's the same as gems
S_gem: \x0f # fancy '*'
@@ -393,3 +397,131 @@ start: NHAccess
S_explode9: \047
finish
start: Unicode_US
Description: Unicode symbols similar to code page 437
Restrictions: Unicode
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 up and left
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+2556 # box drawings down double and left single
S_vodoor: U+25A0 # black square
S_hodoor: U+25A0 # black square
S_bars: U+2261 # identical to
S_tree: U+00B1 # plus-minus sign
S_room: U+00B7 # middle dot
S_corr: U+2591 # light shade
S_litcorr: U+2592 # medium shade
S_fountain: U+2320 # top half integral
S_pool: U+2248 # almost equal to
S_ice: U+00B7 # middle dot
S_lava: U+2248 # almost equal to
S_vodbridge: U+00B7 # middle dot
S_hodbridge: U+00B7 # middle dot
S_water: U+2248 # almost equal to
S_vbeam: U+2502 # box drawings light vertical
S_hbeam: U+2500 # box drawings light horizontal
S_sw_ml: U+2502 # box drawings light vertical
S_sw_mr: U+2502 # box drawings light vertical
S_explode4: U+2502 # box drawings light vertical
S_explode6: U+2502 # box drawings light vertical
finish
start: Unicode_non_US
Description: If default OEM CP for non-Unicode programs is not 437 or 850
Restrictions: Unicode
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 up and left
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_vodoor: U+25A0 # black square
S_hodoor: U+25A0 # black square
S_corr: U+2591 # light shade
S_litcorr: U+2592 # medium shade
S_vbeam: U+2502 # box drawings light vertical
S_hbeam: U+2500 # box drawings light horizontal
S_sw_ml: U+2502 # box drawings light vertical
S_sw_mr: U+2502 # box drawings light vertical
S_explode4: U+2502 # box drawings light vertical
S_explode6: U+2502 # box drawings light vertical
S_coin: U+20AC # euro
finish
start: UnicodeRogueEpyx
Description: Unicode Rogue level symbols
Restrictions: Unicode
Restrictions: Rogue
Color: Yes
S_weapon: U+2191 # up arrow
S_armor: U+25d9 # Vert rect with o
S_ring: U+2642 # circle with arrow
S_amulet: U+2640 # "female" symbol
S_food: U+2663 # club (as in cards)
S_potion: U+00a1 # upside down '!'
S_scroll: U+266a # musical note
S_wand: U+03c4 # greek tau
S_coin: U+263c # yes it's the same as gems
S_gem: U+263c # fancy '*'
S_rock: U+0060 # grave accent
S_ball: U+0030 # digit 0
S_chain: U+005f # low line
S_venom: U+002e # full stop
S_book: U+002b # + sign
S_vwall: U+2551 # all walls now use
S_hwall: U+2550 # double line graphics
S_tlcorn: U+2554 # box drawing double down and right
S_trcorn: U+2557 # box drawing double down and left
S_blcorn: U+255a # box drawing double up and right
S_brcorn: U+255d # box drawing double up and left
S_crwall: U+256c # box drawing double vertical and horizontal
S_tuwall: U+2569 # box drawing double up and horizontal
S_tdwall: U+2566 # box drawing double down and horizontal
S_tlwall: U+2563 # box drawing double vertical and left
S_trwall: U+2560 # box drawing double vertical and right
S_ndoor: U+256c # box drawing double vertical and horizontal
S_vodoor: U+256c # box drawing double vertical and horizontal
S_hodoor: U+256c # box drawing double vertical and horizontal
S_room: U+00b7 # centered dot
S_corr: U+2592 # medium shade
S_litcorr: U+2593 # dark shade
S_upstair: U+001e # Greek Xi
S_dnstair: U+001f
S_arrow_trap: U+2666 # diamond (cards)
S_dart_trap: U+2666
S_falling_rock_trap: U+2666
S_squeaky_board: U+2666
S_bear_trap: U+2666
S_land_mine: U+2666
S_rolling_boulder_trap: U+2666
S_sleeping_gas_trap: U+2666
S_rust_trap: U+2666
S_fire_trap: U+2666
S_pit: U+2666
S_spiked_pit: U+2666
S_hole: U+2666
S_trap_door: U+2666
S_teleportation_trap: U+2666
S_level_teleporter: U+2666
S_magic_portal: U+2666
S_web: U+2666
S_statue_trap: U+2666
S_magic_trap: U+2666
S_anti_magic_trap: U+2666
S_polymorph_trap: U+2666
S_human: U+263a # face
finish

View File

@@ -263,6 +263,10 @@
*/
#endif /* CHDIR */
/*
* Enable some UNICODE support.
*/
/*#define UNICODE_SUPPORT */ /* master on/off for any unicode support */
/*
@@ -356,7 +360,7 @@ typedef unsigned char uchar;
*/
/* display features */
#define LOADSYMSETS /* loadable symbol sets; only default symbols w/o this */
#define LOADSYMSETS /* loadable symbol sets; only default symbols w/o this */
/* dungeon features */
#define SINKS /* Kitchen sinks - Janet Walz */
/* dungeon levels */

View File

@@ -35,7 +35,7 @@ E NEARDATA int nsubroom;
E NEARDATA int occtime;
#define WARNCOUNT 6 /* number of different warning levels */
E uchar warnsyms[WARNCOUNT];
E nhsym warnsyms[WARNCOUNT];
E NEARDATA int warn_obj_cnt; /* count of monsters meeting criteria */
E int x_maze_max, y_maze_max;
@@ -334,7 +334,8 @@ E NEARDATA winid WIN_MESSAGE;
E NEARDATA winid WIN_STATUS;
#endif
E NEARDATA winid WIN_MAP, WIN_INVEN;
E char toplines[];
E nhwchar toplines[];
#ifndef TCAP_H
E struct tc_gbl_data { /* also declared in tcap.h */
char *tc_AS, *tc_AE; /* graphics start and end (tty font swapping) */

View File

@@ -721,6 +721,7 @@ E void NDECL(read_wizkit);
#ifdef LOADSYMSETS
E int FDECL(read_sym_file, (int));
E int FDECL(parse_sym_line, (char *,int));
E int FDECL(sym_val, (const char *));
#endif
E void FDECL(paniclog, (const char *, const char *));
E int FDECL(validate_prefix_locations, (char *));
@@ -829,6 +830,20 @@ E int NDECL(phase_of_the_moon);
E boolean NDECL(friday_13th);
E int NDECL(night);
E int NDECL(midnight);
#ifdef UNICODE_WIDEWINPORT
E nhwchar *FDECL(nhwstrncpy, (nhwchar *,const char *,size_t));
E nhwchar *FDECL(nhwncpy, (nhwchar *,const nhwchar *,size_t));
E nhwchar *FDECL(nhwcpy, (nhwchar *,const nhwchar *));
E nhwchar *FDECL(nhwstrcpy, (nhwchar *,const char *));
E char *FDECL(strnhwcpy, (char *,const nhwchar *));
E nhwchar *FDECL(nhwstrcat, (nhwchar *,const char *));
E nhwchar *FDECL(nhwcat, (nhwchar *,const nhwchar *));
E nhwchar *FDECL(nhwindex, (const nhwchar *,int));
E size_t FDECL(nhwlen, (const nhwchar *));
E int FDECL(nhwcmp, (const nhwchar *,const nhwchar *));
E int FDECL(nhwncmp, (const nhwchar *,const nhwchar *,int));
E int FDECL(nhwstrcmp, (const nhwchar *,const char *));
#endif
/* ### invent.c ### */
@@ -1544,7 +1559,6 @@ E void NDECL(free_autopickup_exceptions);
E int FDECL(load_symset, (const char *,int));
E void FDECL(parsesymbols, (char *));
E struct symparse *FDECL(match_sym, (char *));
E int FDECL(sym_val, (char *));
#endif
/* ### pager.c ### */

View File

@@ -182,6 +182,8 @@ struct instance_flags {
boolean rlecomp; /* run-length comp of levels when writing savefile */
uchar num_pad_mode;
boolean echo; /* 1 to echo characters */
boolean unicodecapable; /* unicode support is possible on platform */
boolean unicodedisp; /* unicode support is turned on */
#if 0
boolean DECgraphics; /* use DEC VT-xxx extended character set */
boolean IBMgraphics; /* use IBM extended character set */

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)global.h 3.5 2006/06/28 */
/* SCCS Id: @(#)global.h 3.5 2006/10/17 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -61,6 +61,41 @@ typedef xchar boolean; /* 0 or 1 */
#define FALSE ((boolean)0)
#endif
/*
* UNICODE_SUPPORT
* Unicode/wide character related support.
*/
#ifdef UNICODE_SUPPORT
# define UNICODE_DRAWING /* store drawing symbols in wchar_t data type */
# define UNICODE_WIDEWINPORT /* store and render wide chars in window port */
/*# define UNICODE_PLAYERTEXT*/ /* not implemented - player input in wide chars */
#else
# undef UNICODE_DRAWING
# undef UNICODE_WIDEWINPORT
# undef UNICODE_PLAYERTEXT
#endif
#if defined(UNICODE_DRAWING)
typedef wchar_t nhsym; /* nhsym is wide char */
#else
typedef char nhsym;
#endif
#if defined(UNICODE_WIDEWINPORT)
typedef wchar_t nhwchar; /* nhwchar (window port char) is wide char */
#else
typedef char nhwchar;
#endif
#if 0
/* Not Implemented presently */
#if defined(UNICODE_PLAYERTEXT)
typedef wchar_t nhptext; /* player input is wide char */
#else
typedef char nhptext;
#endif
#endif
#ifndef STRNCMPI
# ifndef __SASC_60 /* SAS/C already shifts to stricmp */
# define strcmpi(a,b) strncmpi((a),(b),-1)

View File

@@ -187,6 +187,11 @@ extern void NDECL(toggle_mouse_support);
extern void FDECL(map_subkeyvalue, (char *));
extern void NDECL(load_keyboard_handler);
extern void NDECL(raw_clear_screen);
# ifdef UNICODE_WIDEWINPORT
extern void FDECL(xputc, (NHWCHAR_P));
# else
extern void FDECL(xputc, (int));
# endif
#endif
#include <fcntl.h>

View File

@@ -223,6 +223,13 @@ struct symdef {
#endif
};
/*
* Graphics sets for display symbols
*/
#define PRIMARY 0 /* primary graphics */
#define ROGUESET 1 /* rogue graphics */
#define NUM_GRAPHICS 2
struct symparse {
unsigned range;
#define SYM_CONTROL 1 /* start/finish markers */
@@ -249,30 +256,23 @@ struct symsetentry {
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 */
Bitfield(unicode,1); /* restricted for use as a unicode set */
/* 5 free bits */
};
/*
* Graphics sets for display symbols
*/
#define DEFAULT_GRAPHICS 0 /* regular characters: '-', '+', &c */
#define PRIMARY 0 /* primary graphics set */
#define ROGUESET 1 /* rogue graphics set */
#define NUM_GRAPHICS 2
/*
* special symbol set handling types ( for invoking callbacks, etc.)
* Must match the order of the known_handlers strings
* in drawing.c
*/
#define H_UNK 0
#define H_IBM 1
#define H_DEC 2
#define H_UNK 0
#define H_IBM 1
#define H_DEC 2
extern const struct symdef defsyms[MAXPCHARS]; /* defaults */
extern const struct symdef def_warnsyms[WARNCOUNT];
extern int currentgraphics; /* from drawing.c */
extern uchar showsyms[];
extern nhsym showsyms[];
#ifdef LOADSYMSETS
extern struct symsetentry symset[NUM_GRAPHICS]; /* from drawing.c */

View File

@@ -254,6 +254,7 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
# define BOOLEAN_P boolean
# endif
# define ALIGNTYP_P aligntyp
# define NHWCHAR_P nhwchar
#else
# ifdef WIDENED_PROTOTYPES
# define CHAR_P int
@@ -263,6 +264,7 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
# define SHORT_P int
# define BOOLEAN_P int
# define ALIGNTYP_P int
# define NHWCHAR_P int
# else
/* Neither widened nor unwidened prototypes. Argument list expansion
* by FDECL/VDECL always empty; all xxx_P vanish so defs aren't needed. */

View File

@@ -34,8 +34,8 @@ struct WinDesc {
/* maxcol is also used by WIN_MESSAGE for */
/* tracking the ^P command */
short *datlen; /* allocation size for *data */
char **data; /* window data [row][column] */
char *morestr; /* string to display instead of default */
nhwchar **data; /* window data [row][column] */
nhwchar *morestr; /* string to display instead of default */
tty_menu_item *mlist; /* menu information (MENU) */
tty_menu_item **plist; /* menu page pointers (MENU) */
short plist_size; /* size of allocated plist (MENU) */
@@ -86,7 +86,7 @@ extern struct WinDesc *wins[MAXWIN];
extern struct DisplayDesc *ttyDisplay; /* the tty display descriptor */
extern char morc; /* last character typed to xwaitforspace */
extern char defmorestr[]; /* default --more-- prompt */
extern nhwchar defmorestr[]; /* default --more-- prompt */
/* port specific external function references */
@@ -107,7 +107,9 @@ E void NDECL(tty_shutdown);
* actually would be expanded. So here, we have to make an exception. */
E void FDECL(xputc, (int));
#else
# ifndef WIN32CON
E void FDECL(xputc, (CHAR_P));
# endif
#endif
E void FDECL(xputs, (const char *));
#if defined(SCREEN_VGA) || defined(SCREEN_8514)
@@ -150,10 +152,10 @@ E int FDECL(has_color,(int color));
/* ### topl.c ### */
E void FDECL(addtopl, (const char *));
E void FDECL(addtopl, (const nhwchar *));
E void NDECL(more);
E void FDECL(update_topl, (const char *));
E void FDECL(putsyms, (const char*));
E void FDECL(update_topl, (const nhwchar *));
E void FDECL(putsyms, (const nhwchar *));
/* ### wintty.c ### */
#ifdef CLIPPING
@@ -163,6 +165,9 @@ E void FDECL(docorner, (int, int));
E void NDECL(end_glyphout);
E void FDECL(g_putch, (int));
E void NDECL(win_tty_init);
#ifdef UNICODE_WIDEWINPORT
E void FDECL(u_putch, (nhwchar));
#endif
/* external declarations */
E void FDECL(tty_init_nhwindows, (int *, char **));

View File

@@ -261,7 +261,8 @@ NEARDATA winid WIN_MESSAGE = WIN_ERR;
NEARDATA winid WIN_STATUS = WIN_ERR;
#endif
NEARDATA winid WIN_MAP = WIN_ERR, WIN_INVEN = WIN_ERR;
char toplines[TBUFSZ];
nhwchar toplines[TBUFSZ];
/* Windowing stuff that's really tty oriented, but present for all ports */
struct tc_gbl_data tc_gbl_data = { 0,0, 0,0 }; /* AS,AE, LI,CO */

View File

@@ -23,13 +23,13 @@ struct symsetentry symset[NUM_GRAPHICS];
int currentgraphics = 0;
uchar showsyms[SYM_MAX] = DUMMY; /* symbols to be displayed */
uchar l_syms[SYM_MAX] = DUMMY; /* loaded symbols */
nhsym showsyms[SYM_MAX] = DUMMY; /* symbols to be displayed */
nhsym l_syms[SYM_MAX] = DUMMY; /* loaded symbols */
#ifdef REINCARNATION
uchar r_syms[SYM_MAX] = DUMMY; /* rogue symbols */
nhsym r_syms[SYM_MAX] = DUMMY; /* rogue symbols */
#endif
uchar warnsyms[WARNCOUNT] = DUMMY; /* the current warning display symbols */
nhsym warnsyms[WARNCOUNT] = DUMMY; /* the current warning display symbols */
const char invisexplain[] = "remembered, unseen, creature";
/* Default object class symbols. See objclass.h.
@@ -546,6 +546,7 @@ boolean name_too;
/* initialize restriction bits */
symset[which_set].primary = 0;
symset[which_set].rogue = 0;
symset[which_set].unicode = 0;
if (name_too) {
if (symset[which_set].name)
@@ -583,6 +584,7 @@ const char *known_handling[] = {
const char *known_restrictions[] = {
"primary",
"rogue",
"unicode",
(const char *)0,
};

View File

@@ -2531,6 +2531,7 @@ int which_set;
return 0;
if (!symset[which_set].name) {
int i;
/* A null symset name indicates that we're just
building a pick-list of possible symset
values from the file, so only do that */
@@ -2556,6 +2557,20 @@ int which_set;
/* initialize restriction bits */
tmpsp->primary = 0;
tmpsp->rogue = 0;
tmpsp->unicode = 0;
break;
case 2:
/* handler type identified */
tmpsp = symset_list; /* most recent symset */
tmpsp->handling = H_UNK;
i = 0;
while (known_handling[i]) {
if (!strcmpi(known_handling[i], bufp)) {
tmpsp->handling = i;
break; /* while loop */
}
i++;
}
break;
case 3: /* description:something */
tmpsp = symset_list; /* most recent symset */
@@ -2573,6 +2588,7 @@ int which_set;
switch(i) {
case 0: tmpsp->primary = 1; break;
case 1: tmpsp->rogue = 1; break;
case 2: tmpsp->unicode = 1; break;
}
break; /* while loop */
}
@@ -2594,6 +2610,7 @@ int which_set;
/* these init_*() functions clear symset fields too */
# ifdef REINCARNATION
if (which_set == ROGUESET) init_r_symbols();
else
# endif
if (which_set == PRIMARY) init_l_symbols();
}
@@ -2639,18 +2656,32 @@ int which_set;
}
i++;
}
}
/* Don't allow unicode set if code can't handle it */
if (symset[which_set].unicode &&
!iflags.unicodedisp) {
if (chosen_symset_start)
chosen_symset_end = FALSE;
chosen_symset_start = FALSE;
# ifdef REINCARNATION
if (which_set == ROGUESET) init_r_symbols();
else
# endif
if (which_set == PRIMARY) init_l_symbols();
}
}
break;
}
} else { /* !SYM_CONTROL */
val = sym_val(bufp);
if (chosen_symset_start) {
if (which_set == PRIMARY) {
update_l_symset(symp, val);
}
# ifdef REINCARNATION
if (which_set == ROGUESET)
update_r_symset(symp, val);
else
else if (which_set == ROGUESET) {
update_r_symset(symp, val);
}
# endif
update_l_symset(symp, val);
}
}
}
@@ -2673,6 +2704,72 @@ int which_set;
i++;
}
}
/*
* Produces a single integer value.
*/
int
sym_val(cp)
const char *cp;
{
unsigned int cval = 0;
int meta = 0, dcount = 0;
const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
while (*cp)
{
if (*cp == '\\' && index("mM", cp[1])) {
meta = 1;
cp += 2;
}
if ((*cp == 'U' || *cp == 'u') && cp[1] == '+' && index(hex, cp[2]))
{
dcount = 0;
cp++;
for (++cp; *cp && (dp = index(hex, *cp)) && (dcount++ < 4); cp++)
cval = (unsigned int)((cval * 16) +
((unsigned int)(dp - hex) / 2));
}
else if (*cp == '\\' && index("0123456789xXoO", cp[1]))
{
dcount = 0;
cp++;
if (*cp == 'x' || *cp == 'X')
for (++cp; *cp && (dp = index(hex, *cp)) && (dcount++ < 4); cp++)
cval = (unsigned int)((cval * 16) +
((unsigned int)(dp - hex) / 2));
else if (*cp == 'o' || *cp == 'O')
for (++cp; *cp && (index("01234567",*cp)) && (dcount++ < 5); cp++)
cval = (cval * 8) + (unsigned int)(*cp - '0');
else
for (; *cp && (index("0123456789",*cp)) && (dcount++ < 5); cp++)
cval = (cval * 10) + (unsigned int)(*cp - '0');
}
else if (*cp == '\\') /* C-style character escapes */
{
switch (*++cp)
{
case '\\': cval = '\\'; break;
case 'n': cval = '\n'; break;
case 't': cval = '\t'; break;
case 'b': cval = '\b'; break;
case 'r': cval = '\r'; break;
default: cval = (unsigned int)*cp;
}
cp++;
}
else if (*cp == '^') /* expand control-character syntax */
{
cval = (unsigned int)(*++cp & 0x1f);
cp++;
}
else
cval = (unsigned int)*cp++;
if (meta)
cval |= 0x80;
}
return cval;
}
#endif /*LOADSYMSETS*/
/* ---------- END CONFIG FILE HANDLING ----------- */

View File

@@ -624,4 +624,192 @@ midnight()
return(getlt()->tm_hour == 0);
}
#ifdef UNICODE_WIDEWINPORT
nhwchar *
nhwstrncpy(dest, strSource, cnt)
nhwchar *dest;
const char *strSource;
size_t cnt;
{
nhwchar *d = dest;
const char *s = strSource;
size_t dcnt = 0;
while(*s && dcnt < cnt) {
*d++ = (nhwchar)*s++;
dcnt++;
}
if (dcnt < cnt) *d = 0;
return dest;
}
nhwchar *
nhwncpy(dest, src, cnt)
nhwchar *dest;
const nhwchar *src;
size_t cnt;
{
nhwchar *d = dest;
const nhwchar *s = src;
size_t dcnt = 0;
while(*s && dcnt < cnt) {
*d++ = *s++;
dcnt++;
}
if (dcnt < cnt) *d = 0;
return dest;
}
nhwchar *
nhwcpy(dest, src)
nhwchar *dest;
const nhwchar *src;
{
nhwchar *d = dest;
const nhwchar *s = src;
while(*s) {
*d++ = *s++;
}
*d = 0;
return dest;
}
nhwchar *
nhwstrcpy(dest, strSource)
nhwchar *dest;
const char *strSource;
{
nhwchar *d = dest;
const char *s = strSource;
while(*s) {
*d++ = *s++;
}
*d = 0;
return dest;
}
char *
strnhwcpy(strDest, src)
char *strDest;
const nhwchar *src;
{
char *d = strDest;
const nhwchar *s = src;
while(*s) {
*d++ = (char)*s++;
}
*d = 0;
return strDest;
}
nhwchar *
nhwstrcat(dest, strSource)
nhwchar *dest;
const char *strSource;
{
nhwchar *d = dest;
const char *s = strSource;
while(*d) d++;
while(*s) {
*d++ = *s++;
}
*d = 0;
return dest;
}
nhwchar *
nhwcat(dest, src)
nhwchar *dest;
const nhwchar *src;
{
nhwchar *d = dest;
const nhwchar *s = src;
while(*d) d++;
while(*s) {
*d++ = *s++;
}
*d = 0;
return dest;
}
nhwchar *
nhwindex(ss, c)
const nhwchar *ss;
int c;
{
const nhwchar *s = ss;
while (*s) {
if (*s == c) return (nhwchar *)s;
s++;
}
if (*s == c) return (nhwchar *)s;
return (nhwchar *)0;
}
size_t nhwlen(src)
const nhwchar *src;
{
register size_t dl = 0;
while(*src++) dl++;
return dl;
}
int
nhwcmp(s1, s2) /* case insensitive counted string comparison */
register const nhwchar *s1, *s2;
{ /*{ aka strncasecmp }*/
register nhwchar t1, t2;
for (;;) {
if (!*s2) return (*s1 != 0); /* s1 >= s2 */
else if (!*s1) return -1; /* s1 < s2 */
t1 = *s1++;
t2 = *s2++;
if (t1 != t2) return (t1 > t2) ? 1 : -1;
}
return 0; /* s1 == s2 */
}
int
nhwncmp(s1, s2, n) /* case sensitive counted nhwchar (wide string) comparison */
register const nhwchar *s1, *s2;
register int n; /*(should probably be size_t, which is usually unsigned)*/
{
register nhwchar t1, t2;
while (n--) {
if (!*s2) return (*s1 != 0); /* s1 >= s2 */
else if (!*s1) return -1; /* s1 < s2 */
t1 = *s1++;
t2 = *s2++;
if (t1 != t2) return (t1 > t2) ? 1 : -1;
}
return 0; /* s1 == s2 */
}
int
nhwstrcmp(s1, s2)
register const nhwchar *s1;
const char *s2;
{ /*{ aka strncasecmp }*/
register nhwchar t1, t2;
for (;;) {
if (!*s2) return (*s1 != 0); /* s1 >= s2 */
else if (!*s1) return -1; /* s1 < s2 */
t1 = *s1++;
t2 = (nhwchar)*s2++;
if (t1 != t2) return (t1 > t2) ? 1 : -1;
}
return 0; /* s1 == s2 */
}
#endif
/*hacklib.c*/

View File

@@ -67,7 +67,7 @@ unsigned *ospecial;
#if defined(TEXTCOLOR) || defined(ROGUE_COLOR)
int color = NO_COLOR;
#endif
uchar ch;
nhsym ch;
unsigned special = 0;
/* condense multiple tests in macro version down to single */
boolean has_rogue_ibm_graphics = HAS_ROGUE_IBM_GRAPHICS;
@@ -263,6 +263,7 @@ int glyph;
return encbuf;
}
#ifndef UNICODE_WIDEWINPORT
/*
* This differs from putstr() because the str parameter can
* contain a sequence of characters representing:
@@ -304,25 +305,12 @@ genl_putmixed(window, attr, str)
gv = (int)((gv * 16) + ((int)(dp - hex) / 2));
so = mapglyph(gv, &ch, &oc, &os, 0, 0);
*put++ = showsyms[so];
continue;
} else {
/* possible forgery - leave it the way it is */
cp = save_cp;
}
break;
# if 0
case 'S': /* symbol offset */
dcount = 0;
for (++cp; *cp && (dp = index(hex, *cp)) && (dcount++ < 4); cp++)
rndchk = (int)((rndchk * 16) + ((int)(dp - hex) / 2));
if (rndchk == context.rndencode) {
dcount = 0;
for (; *cp && (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
so = (int)((so * 16) + ((int)(dp - hex) / 2));
}
*put++ = showsyms[so];
break;
# endif
case '\\':
break;
}
@@ -333,4 +321,5 @@ genl_putmixed(window, attr, str)
/* now send it to the normal putstr */
putstr(window, attr, buf);
}
#endif /*!UNICODE_WIDEWINPORT*/
/*mapglyph.c*/

View File

@@ -195,6 +195,9 @@ static struct Bool_Opt
{"tombstone",&flags.tombstone, TRUE, SET_IN_GAME},
{"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME},
{"travel", &flags.travelcmd, TRUE, SET_IN_GAME},
#ifdef UNICODE_SUPPORT
{"unicode", &iflags.unicodedisp, FALSE, SET_IN_GAME},
#endif
#ifdef WIN32CON
{"use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME}, /*WC*/
#else
@@ -347,7 +350,7 @@ static struct Comp_Opt
DISP_IN_GAME},
# endif
#else
SET_IN_FILE },
SET_IN_FILE},
#endif
{ "suppress_alert", "suppress alerts about version-specific features",
8, SET_IN_GAME },
@@ -582,6 +585,9 @@ initoptions()
iflags.msg_history = 20;
#ifdef TTY_GRAPHICS
iflags.prevmsg_window = 's';
# if defined(UNIX) && defined(UNICODE_WIDEWINPORT)
iflags.unicodecapable = TRUE;
# endif
#endif
iflags.menu_headings = ATR_INVERSE;
@@ -2326,7 +2332,7 @@ goodfruit:
# ifdef LOADSYMSETS
if (duplicate) complain_about_duplicate(opts,1);
if (!negated) {
for (i = 0; i < NUM_GRAPHICS; ++i) {
for (i = PRIMARY; i <= ROGUESET; ++i) {
if (symset[i].name)
badflag = TRUE;
else {
@@ -3154,25 +3160,31 @@ boolean setinitial,setfromfile;
if (pick_cnt >= 0) goto ape_again;
}
#endif /* AUTOPICKUP_EXCEPTIONS */
} else if (!strcmp("symset", optname) ||
!strcmp("roguesymset", optname)) {
} else if (!strcmp("symset", optname)
|| !strcmp("roguesymset", optname)) {
menu_item *symset_pick = (menu_item *)0;
boolean primaryflag = (*optname == 's'),
rogueflag = (*optname == 'r');
rogueflag = (*optname == 'r'),
ready_to_switch = FALSE,
nothing_to_do = FALSE;
#ifdef LOADSYMSETS
int res;
char *symset_name, fmtstr[20];
struct symsetentry *sl;
int setcount = 0;
#endif
int chosen = -2, which_set =
int chosen = -2, which_set;
#ifdef REINCARNATION
rogueflag ? ROGUESET :
if (rogueflag) which_set = ROGUESET;
else
#endif
PRIMARY;
which_set = PRIMARY;
#ifndef REINCARNATION
if (rogueflag) return TRUE;
#endif
#ifdef LOADSYMSETS
/* clear symset[].name as a flag to read_sym_file() to build list */
symset_name = symset[which_set].name;
@@ -3186,7 +3198,8 @@ boolean setinitial,setfromfile;
sl = symset_list;
while (sl) {
/* check restrictions */
if ((!rogueflag && sl->rogue) ||
if ((!rogueflag && sl->rogue) ||
(!iflags.unicodedisp && sl->unicode) ||
(!primaryflag && sl->primary)) {
sl = sl->next;
continue;
@@ -3199,8 +3212,8 @@ boolean setinitial,setfromfile;
}
if (!setcount) {
pline("There are no appropriate %ssymbol sets available.",
(rogueflag) ? "rogue level " :
(primaryflag) ? "primary " :
(rogueflag) ? "rogue level " :
(primaryflag) ? "primary " :
"");
return TRUE;
}
@@ -3216,6 +3229,7 @@ boolean setinitial,setfromfile;
while (sl) {
/* check restrictions */
if ((!rogueflag && sl->rogue) ||
(!iflags.unicodedisp && sl->unicode) ||
(!primaryflag && sl->primary)) {
sl = sl->next;
continue;
@@ -3226,10 +3240,10 @@ boolean setinitial,setfromfile;
sl->desc ? sl->desc : "");
add_menu(tmpwin, NO_GLYPH, &any, let, 0,
ATR_NONE, symsetchoice, MENU_UNSELECTED);
sl = sl->next;
if (let == 'z') let = 'A';
else let++;
}
sl = sl->next;
}
end_menu(tmpwin, "Select symbol set:");
if (select_menu(tmpwin, PICK_ONE, &symset_pick) > 0) {
@@ -3254,7 +3268,7 @@ boolean setinitial,setfromfile;
symset[which_set].name =
(char *)alloc(strlen(sl->name)+1);
Strcpy(symset[which_set].name, sl->name);
ready_to_switch = TRUE;
break;
}
sl = sl->next;
@@ -3268,6 +3282,7 @@ boolean setinitial,setfromfile;
symset_name = (char *)0;
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);
@@ -3292,34 +3307,41 @@ boolean setinitial,setfromfile;
free((genericptr_t)sl);
}
/* Set default symbols and clear the handling value */
# ifdef REINCARNATION
if(rogueflag) init_r_symbols();
else
# endif
init_l_symbols();
if (nothing_to_do) return TRUE;
if (!symset[which_set].name && symset_name)
symset[which_set].name = symset_name;
symset[which_set].name = symset_name;
/* Set default symbols and clear the handling value */
# ifdef REINCARNATION
if(rogueflag)
init_r_symbols();
else
# endif
init_l_symbols();
if (symset[which_set].name) {
if (read_sym_file(which_set))
switch_symbols(TRUE);
ready_to_switch = TRUE;
else {
clear_symsetentry(which_set, TRUE);
return TRUE;
}
}
switch_symbols(TRUE);
if (ready_to_switch) switch_symbols(TRUE);
# ifdef REINCARNATION
if (Is_rogue_level(&u.uz))
assign_graphics(ROGUESET);
else
if (Is_rogue_level(&u.uz)) {
if (rogueflag)
assign_graphics(ROGUESET);
} else
# endif
assign_graphics(PRIMARY);
if (!rogueflag) assign_graphics(PRIMARY);
need_redraw = TRUE;
#endif /*LOADSYMSETS*/
return TRUE;
} else {
/* didn't match any of the special options */
return FALSE;
@@ -3366,7 +3388,11 @@ char *buf;
#endif
#ifdef BACKWARD_COMPAT
else if (!strcmp(optname, "boulder"))
# ifdef UNICODE_DRAWING
Sprintf(buf, "\\x%04X", iflags.bouldersym ?
# else
Sprintf(buf, "%c", iflags.bouldersym ?
# endif
iflags.bouldersym :
showsyms[(int)objects[BOULDER].oc_class + SYM_OFF_O]);
#endif
@@ -3519,14 +3545,17 @@ char *buf;
else if (!strcmp(optname, "race"))
Sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
#ifdef REINCARNATION
else if (!strcmp(optname, "roguesymset"))
else if (!strcmp(optname, "roguesymset")) {
Sprintf(buf, "%s",
# ifdef LOADSYMSETS
symset[ROGUESET].name ?
symset[ROGUESET].name :
# endif
"default");
if (currentgraphics == ROGUESET && symset[ROGUESET].name)
Strcat(buf, ", active");
#endif
}
else if (!strcmp(optname, "role"))
Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
else if (!strcmp(optname, "runmode"))
@@ -3558,13 +3587,16 @@ char *buf;
FEATURE_NOTICE_VER_MIN,
FEATURE_NOTICE_VER_PATCH);
}
else if (!strcmp(optname, "symset"))
else if (!strcmp(optname, "symset")) {
Sprintf(buf, "%s",
#ifdef LOADSYMSETS
symset[PRIMARY].name ?
symset[PRIMARY].name :
#endif
"default");
if (currentgraphics == PRIMARY && symset[PRIMARY].name)
Strcat(buf, ", active");
}
else if (!strcmp(optname, "tile_file"))
Sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
else if (!strcmp(optname, "tile_height")) {
@@ -3818,15 +3850,6 @@ char *buf;
}
return (struct symparse *)0;
}
int sym_val(strval)
char *strval;
{
char buf[QBUFSZ];
buf[0] = '\0';
escapes(strval, buf);
return (int)*buf;
}
#endif /*LOADSYMSETS*/
/* data for option_help() */

View File

@@ -581,7 +581,7 @@ do_look(mode, click_cc)
for (i = 0; i < MAXMCLASSES; i++) {
if (sym == ((from_screen || clicklook) ?
showsyms[i + SYM_OFF_M] : def_monsyms[i].sym) &&
def_monsyms[i].explain) {
def_monsyms[i].explain) {
need_to_look = TRUE;
if (!found) {
Sprintf(out_str, "%s %s",

View File

@@ -58,7 +58,11 @@ pline VA_DECL(const char *, line)
return;
}
#ifndef MAC
if (no_repeat && !strcmp(line, toplines))
# ifdef UNICODE_WIDEWINPORT
if (no_repeat && !nhwstrcmp(toplines, line))
# else
if (no_repeat && !strcmp(toplines, line))
# endif
return;
#endif /* MAC */
if (vision_full_recalc) vision_recalc(0);

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)nttty.c 3.5 $Date$ */
/* SCCS Id: @(#)nttty.c 3.5 $Date$ */
/* Copyright (c) NetHack PC Development Team 1993 */
/* NetHack may be freely redistributed. See license for details. */
@@ -61,9 +61,6 @@ int GUILaunched;
extern int redirect_stdout;
static BOOL FDECL(CtrlHandler, (DWORD));
/* Flag for whether unicode is supported */
static boolean has_unicode;
#ifdef PORT_DEBUG
static boolean display_cursor_info = FALSE;
#endif
@@ -146,6 +143,12 @@ static void NDECL(init_ttycolor);
# endif
static void NDECL(really_move_cursor);
#ifdef UNICODE_WIDEWINPORT
void FDECL(xputc_core,(NHWCHAR_P));
#else
void FDECL(xputc_core,(int));
#endif
#define MAX_OVERRIDES 256
unsigned char key_overrides[MAX_OVERRIDES];
@@ -193,11 +196,14 @@ const char *s;
void
setftty()
{
static int cp = 0;
if (!cp) cp = GetConsoleOutputCP();
/* SetConsoleOutputCP(1250); */
#ifdef CHANGE_COLOR
if (altered_palette) adjust_palette();
#endif
start_screen();
has_unicode = ((GetVersion() & 0x80000000) == 0);
iflags.unicodecapable = ((GetVersion() & 0x80000000) == 0);
}
void
@@ -448,24 +454,61 @@ int x,y;
ttyDisplay->cury = y;
}
#ifdef UNICODE_WIDEWINPORT
#define T(x) L##x
#else
#define T(x) x
#endif
void
xputc_core(ch)
char ch;
xputc_core(ich)
#ifdef UNICODE_WIDEWINPORT
nhwchar ich;
#else
int ich;
#endif
{
static uchar c[2] = {0,0};
char ch = (char)ich;
#if 0
/*EURO symbol*/
if (ich == 0x20AC) {
if (!c[0]) {
wchar_t t[2]={0x20ac, 0x0000};
int cp = GetConsoleOutputCP();
(void) WideCharToMultiByte(cp,
0,
t, 1,
c, 2,
(LPCSTR)0,
(LPBOOL)0);
}
ich = (nhwchar)c[0];
}
#endif
#ifdef UNICODE_WIDEWINPORT
switch(ich) {
#else
switch(ch) {
case '\n':
#endif
case T('\n'):
cursor.Y++;
/* fall through */
case '\r':
case T('\r'):
cursor.X = 1;
break;
case '\b':
case T('\b'):
cursor.X--;
break;
default:
WriteConsoleOutputAttribute(hConOut,&attr,1,
cursor,&acount);
if (has_unicode) {
if (iflags.unicodedisp) {
#ifdef UNICODE_WIDEWINPORT
WriteConsoleOutputCharacterW(hConOut,&ich,1,
cursor,&ccount);
#else
/* Avoid bug in ANSI API on WinNT */
WCHAR c2[2];
int rc;
@@ -476,6 +519,7 @@ char ch;
c2, 2);
WriteConsoleOutputCharacterW(hConOut,c2,rc,
cursor,&ccount);
#endif
}
else {
WriteConsoleOutputCharacterA(hConOut,&ch,1,
@@ -487,7 +531,11 @@ char ch;
void
xputc(ch)
char ch;
#ifdef UNICODE_WIDEWINPORT
nhwchar ch;
#else
int ch;
#endif
{
cursor.X = ttyDisplay->curx;
cursor.Y = ttyDisplay->cury;
@@ -518,8 +566,8 @@ const char *s;
* for win32. It is used for glyphs only, not text.
*/
void
g_putch(in_ch)
int in_ch;
g_putch(in_sym)
int in_sym;
{
/* CP437 to Unicode mapping according to the Unicode Consortium */
static const WCHAR cp437[] =
@@ -557,12 +605,17 @@ int in_ch;
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
};
unsigned char ch = (unsigned char)in_ch;
uchar ch = (uchar)in_sym;
cursor.X = ttyDisplay->curx;
cursor.Y = ttyDisplay->cury;
WriteConsoleOutputAttribute(hConOut,&attr,1,cursor,&acount);
if (has_unicode)
#ifdef UNICODE_DRAWING
if (symset[currentgraphics].name && iflags.unicodedisp)
WriteConsoleOutputCharacterW(hConOut,(LPCWSTR)&in_sym,1,cursor,&ccount);
else
#endif
if (SYMHANDLING(H_IBM))
WriteConsoleOutputCharacterW(hConOut,&cp437[ch],1,cursor,&ccount);
else
WriteConsoleOutputCharacterA(hConOut,&ch,1,cursor,&ccount);

View File

@@ -23,6 +23,12 @@ extern int NDECL(extcmd_via_menu); /* cmd.c */
extern char erase_char, kill_char; /* from appropriate tty.c file */
#ifdef UNICODE_WIDEWINPORT
#define T(x) L##x
#else
#define T(x) x
#endif
/*
* Read a line closed with '\n' into the array char bufp[BUFSZ].
* (The '\n' is not stored. The string is closed with a '\0'.)
@@ -47,6 +53,9 @@ getlin_hook_proc hook;
register int c;
struct WinDesc *cw = wins[WIN_MESSAGE];
boolean doprev = 0;
#ifdef UNICODE_WIDEWINPORT
nhwchar wbuf[BUFSZ];
#endif
if(ttyDisplay->toplin == 1 && !(cw->flags & WIN_STOP)) more();
cw->flags &= ~WIN_STOP;
@@ -55,9 +64,18 @@ getlin_hook_proc hook;
pline("%s ", query);
*obufp = 0;
for(;;) {
#ifdef UNICODE_WIDEWINPORT
char buf[BUFSZ];
(void) fflush(stdout);
Sprintf(buf, "%s ", query);
Strcat(buf, obufp);
nhwstrcpy(wbuf, buf);
(void)nhwcpy(toplines, wbuf);
#else
(void) fflush(stdout);
Sprintf(toplines, "%s ", query);
Strcat(toplines, obufp);
#endif
if((c = Getchar()) == EOF) c = '\033';
if(c == '\033') {
*obufp = c;
@@ -76,10 +94,19 @@ getlin_hook_proc hook;
ttyDisplay->inread = sav;
tty_clear_nhwindow(WIN_MESSAGE);
cw->maxcol = cw->maxrow;
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(wbuf, query);
addtopl(wbuf);
addtopl(L" ");
*bufp = 0;
nhwstrcpy(wbuf, obufp);
addtopl(wbuf);
#else
addtopl(query);
addtopl(" ");
*bufp = 0;
addtopl(obufp);
#endif
} else {
if (!doprev)
(void) tty_doprev_message();/* need two initially */
@@ -91,10 +118,22 @@ getlin_hook_proc hook;
tty_clear_nhwindow(WIN_MESSAGE);
cw->maxcol = cw->maxrow;
doprev = 0;
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(wbuf, query);
addtopl(wbuf);
addtopl(L" ");
#else
addtopl(query);
addtopl(" ");
#endif
*bufp = 0;
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(wbuf, obufp);
addtopl(wbuf);
#else
addtopl(obufp);
#endif
}
if(c == erase_char || c == '\b') {
if(bufp != obufp) {
@@ -104,11 +143,11 @@ getlin_hook_proc hook;
#endif /* NEWAUTOCOMP */
bufp--;
#ifndef NEWAUTOCOMP
putsyms("\b \b");/* putsym converts \b */
putsyms(T("\b \b"));/* putsym converts \b */
#else /* NEWAUTOCOMP */
putsyms("\b");
for (i = bufp; *i; ++i) putsyms(" ");
for (; i > bufp; --i) putsyms("\b");
putsyms(T("\b"));
for (i = bufp; *i; ++i) putsyms(T(" "));
for (; i > bufp; --i) putsyms(T("\b"));
*bufp = 0;
#endif /* NEWAUTOCOMP */
} else tty_nhbell();
@@ -131,21 +170,31 @@ getlin_hook_proc hook;
#endif /* NEWAUTOCOMP */
*bufp = c;
bufp[1] = 0;
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(wbuf, bufp);
putsyms(wbuf);
#else
putsyms(bufp);
#endif
bufp++;
if (hook && (*hook)(obufp)) {
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(wbuf, bufp);
putsyms(wbuf);
#else
putsyms(bufp);
#endif
#ifndef NEWAUTOCOMP
bufp = eos(bufp);
#else /* NEWAUTOCOMP */
/* pointer and cursor left where they were */
for (i = bufp; *i; ++i) putsyms("\b");
for (i = bufp; *i; ++i) putsyms(T("\b"));
} else if (i > bufp) {
char *s = i;
/* erase rest of prior guess */
for (; i > bufp; --i) putsyms(" ");
for (; s > bufp; --s) putsyms("\b");
for (; i > bufp; --i) putsyms(T(" "));
for (; s > bufp; --s) putsyms(T("\b"));
#endif /* NEWAUTOCOMP */
}
} else if(c == kill_char || c == '\177') { /* Robert Viduya */
@@ -153,11 +202,11 @@ getlin_hook_proc hook;
#ifndef NEWAUTOCOMP
while(bufp != obufp) {
bufp--;
putsyms("\b \b");
putsyms(T("\b \b"));
}
#else /* NEWAUTOCOMP */
for (; *bufp; ++bufp) putsyms(" ");
for (; bufp != obufp; --bufp) putsyms("\b \b");
for (; *bufp; ++bufp) putsyms(T(" "));
for (; bufp != obufp; --bufp) putsyms(T("\b \b"));
*bufp = 0;
#endif /* NEWAUTOCOMP */
} else
@@ -168,6 +217,8 @@ getlin_hook_proc hook;
clear_nhwindow(WIN_MESSAGE); /* clean up after ourselves */
}
#undef T
void
xwaitforspace(s)
register const char *s; /* chars allowed besides return */

View File

@@ -14,11 +14,13 @@
#define C(c) (0x1f & (c))
#endif
STATIC_DCL void FDECL(redotoplin, (const char*));
STATIC_DCL void FDECL(topl_putsym, (CHAR_P));
STATIC_DCL void FDECL(redotoplin, (const nhwchar*));
STATIC_DCL void FDECL(topl_putsym, (NHWCHAR_P));
STATIC_DCL void NDECL(remember_topl);
STATIC_DCL void FDECL(removetopl, (int));
extern nhwchar emptysym[];
int
tty_doprev_message()
{
@@ -26,6 +28,9 @@ tty_doprev_message()
winid prevmsg_win;
int i;
#ifdef UNICODE_WIDEWINPORT
char buf[BUFSZ];
#endif
if ((iflags.prevmsg_window != 's') && !ttyDisplay->inread) { /* not single */
if(iflags.prevmsg_window == 'f') { /* full */
prevmsg_win = create_nhwindow(NHW_MENU);
@@ -34,11 +39,23 @@ tty_doprev_message()
cw->maxcol = cw->maxrow;
i = cw->maxcol;
do {
if(cw->data[i] && strcmp(cw->data[i], "") )
#ifdef UNICODE_WIDEWINPORT
if(cw->data[i] && nhwstrcmp(cw->data[i], "") ) {
strnhwcpy(buf, cw->data[i]);
putstr(prevmsg_win, 0, buf);
#else
if(cw->data[i] && strcmp(cw->data[i], "") ) {
putstr(prevmsg_win, 0, cw->data[i]);
#endif
}
i = (i + 1) % cw->rows;
} while (i != cw->maxcol);
#ifdef UNICODE_WIDEWINPORT
strnhwcpy(buf, toplines);
putstr(prevmsg_win, 0, buf);
#else
putstr(prevmsg_win, 0, toplines);
#endif
display_nhwindow(prevmsg_win, TRUE);
destroy_nhwindow(prevmsg_win);
} else if (iflags.prevmsg_window == 'c') { /* combination */
@@ -65,11 +82,24 @@ tty_doprev_message()
cw->maxcol = cw->maxrow;
i = cw->maxcol;
do {
if(cw->data[i] && strcmp(cw->data[i], "") )
#ifdef UNICODE_WIDEWINPORT
if(cw->data[i] && nhwstrcmp(cw->data[i], "") ) {
strnhwcpy(buf, cw->data[i]);
putstr(prevmsg_win, 0, buf);
#else
if(cw->data[i] && strcmp(cw->data[i], "") ) {
putstr(prevmsg_win, 0, cw->data[i]);
#endif
}
i = (i + 1) % cw->rows;
} while (i != cw->maxcol);
#ifdef UNICODE_WIDEWINPORT
strnhwcpy(buf, toplines);
putstr(prevmsg_win, 0, buf);
#else
putstr(prevmsg_win, 0, toplines);
#endif
display_nhwindow(prevmsg_win, TRUE);
destroy_nhwindow(prevmsg_win);
}
@@ -81,11 +111,22 @@ tty_doprev_message()
prevmsg_win = create_nhwindow(NHW_MENU);
putstr(prevmsg_win, 0, "Message History");
putstr(prevmsg_win, 0, "");
#ifdef UNICODE_WIDEWINPORT
strnhwcpy(buf, toplines);
putstr(prevmsg_win, 0, buf);
#else
putstr(prevmsg_win, 0, toplines);
#endif
cw->maxcol=cw->maxrow-1;
if(cw->maxcol < 0) cw->maxcol = cw->rows-1;
do {
putstr(prevmsg_win, 0, cw->data[cw->maxcol]);
#ifdef UNICODE_WIDEWINPORT
strnhwcpy(buf, cw->data[cw->maxcol]);
putstr(prevmsg_win, 0, buf);
#else
putstr(prevmsg_win, 0, cw->data[cw->maxcol]);
#endif
cw->maxcol--;
if (cw->maxcol < 0) cw->maxcol = cw->rows-1;
if (!cw->data[cw->maxcol])
@@ -116,19 +157,23 @@ tty_doprev_message()
}
STATIC_OVL void
redotoplin(str)
const char *str;
redotoplin(symstr)
const nhwchar *symstr;
{
int otoplin = ttyDisplay->toplin;
home();
if(*str & 0x80) {
#ifdef UNICODE_WIDEWINPORT
if(*symstr >= 0x80) {
#else
if(*symstr & 0x80) {
#endif
/* kludge for the / command, the only time we ever want a */
/* graphics character on the top line */
g_putch((int)*str++);
g_putch((int)*symstr++);
ttyDisplay->curx++;
}
end_glyphout(); /* in case message printed during graphics output */
putsyms(str);
putsyms(symstr);
cl_end();
ttyDisplay->toplin = 1;
if(ttyDisplay->cury && otoplin != 3)
@@ -140,21 +185,29 @@ remember_topl()
{
register struct WinDesc *cw = wins[WIN_MESSAGE];
int idx = cw->maxrow;
#ifdef UNICODE_WIDEWINPORT
unsigned len = nhwlen(toplines) + 1;
#else
unsigned len = strlen(toplines) + 1;
#endif
if (len > (unsigned)cw->datlen[idx]) {
if (cw->data[idx]) free(cw->data[idx]);
len += (8 - (len & 7)); /* pad up to next multiple of 8 */
cw->data[idx] = (char *)alloc(len);
cw->data[idx] = (nhwchar *)alloc(sizeof(nhwchar) * len);
cw->datlen[idx] = (short)len;
}
#ifdef UNICODE_WIDEWINPORT
(void)nhwcpy(cw->data[idx], toplines);
#else
Strcpy(cw->data[idx], toplines);
#endif
cw->maxcol = cw->maxrow = (idx + 1) % cw->rows;
}
void
addtopl(s)
const char *s;
const nhwchar *s;
{
register struct WinDesc *cw = wins[WIN_MESSAGE];
@@ -175,7 +228,12 @@ more()
if(ttyDisplay->toplin) {
tty_curs(BASE_WINDOW, cw->curx+1, cw->cury);
if(cw->curx >= CO - 8) topl_putsym('\n');
if(cw->curx >= CO - 8)
#ifdef UNICODE_WIDEWINPORT
topl_putsym(L'\n');
#else
topl_putsym('\n');
#endif
}
if(flags.standout)
@@ -204,22 +262,33 @@ more()
void
update_topl(bp)
register const char *bp;
register const nhwchar *bp;
{
register char *tl, *otl;
register nhwchar *tl, *otl;
register int n0;
int notdied = 1;
struct WinDesc *cw = wins[WIN_MESSAGE];
/* If there is room on the line, print message on same line */
/* But messages like "You die..." deserve their own line */
#ifdef UNICODE_WIDEWINPORT
n0 = nhwlen(bp);
#else
n0 = strlen(bp);
#endif
if ((ttyDisplay->toplin == 1 || (cw->flags & WIN_STOP)) &&
cw->cury == 0 &&
#ifdef UNICODE_WIDEWINPORT
n0 + (int)nhwlen(toplines) + 3 < CO-8 && /* room for --More-- */
(notdied = nhwncmp(bp, L"You die", 7))) {
(void)nhwcat(toplines, L" ");
(void)nhwcat(toplines, bp);
#else
n0 + (int)strlen(toplines) + 3 < CO-8 && /* room for --More-- */
(notdied = strncmp(bp, "You die", 7))) {
Strcat(toplines, " ");
Strcat(toplines, bp);
#endif
cw->curx += 2;
if(!(cw->flags & WIN_STOP))
addtopl(bp);
@@ -232,7 +301,11 @@ update_topl(bp)
}
}
remember_topl();
#ifdef UNICODE_WIDEWINPORT
(void) nhwncpy(toplines, bp, TBUFSZ);
#else
(void) strncpy(toplines, bp, TBUFSZ);
#endif
toplines[TBUFSZ - 1] = 0;
for(tl = toplines; n0 >= CO; ){
@@ -240,34 +313,49 @@ update_topl(bp)
for(tl+=CO-1; tl != otl && !isspace(*tl); --tl) ;
if(tl == otl) {
/* Eek! A huge token. Try splitting after it. */
#ifdef UNICODE_WIDEWINPORT
tl = nhwindex(otl, ' ');
#else
tl = index(otl, ' ');
#endif
if (!tl) break; /* No choice but to spit it out whole. */
}
#ifdef UNICODE_WIDEWINPORT
*tl++ = (nhwchar)'\n';
n0 = nhwlen(tl);
#else
*tl++ = '\n';
n0 = strlen(tl);
#endif
}
if(!notdied) cw->flags &= ~WIN_STOP;
if(!(cw->flags & WIN_STOP)) redotoplin(toplines);
}
#ifdef UNICODE_WIDEWINPORT
#define T(x) L##x
#else
#define T(x) x
#endif
STATIC_OVL
void
topl_putsym(c)
char c;
nhwchar c;
{
register struct WinDesc *cw = wins[WIN_MESSAGE];
if(cw == (struct WinDesc *) 0) panic("Putsym window MESSAGE nonexistant");
switch(c) {
case '\b':
case T('\b'):
if(ttyDisplay->curx == 0 && ttyDisplay->cury > 0)
tty_curs(BASE_WINDOW, CO, (int)ttyDisplay->cury-1);
backsp();
ttyDisplay->curx--;
cw->curx = ttyDisplay->curx;
return;
case '\n':
case T('\n'):
cl_end();
ttyDisplay->curx = 0;
ttyDisplay->cury++;
@@ -278,7 +366,7 @@ topl_putsym(c)
break;
default:
if(ttyDisplay->curx == CO-1)
topl_putsym('\n'); /* 1 <= curx <= CO; avoid CO */
topl_putsym(T('\n')); /* 1 <= curx <= CO; avoid CO */
#ifdef WIN32CON
(void) putchar(c);
#endif
@@ -291,12 +379,14 @@ topl_putsym(c)
#endif
}
#undef T
void
putsyms(str)
const char *str;
putsyms(symstr)
const nhwchar *symstr;
{
while(*str)
topl_putsym(*str++);
while(*symstr)
topl_putsym(*symstr++);
}
STATIC_OVL void
@@ -304,7 +394,12 @@ removetopl(n)
register int n;
{
/* assume addtopl() has been done, so ttyDisplay->toplin is already set */
while (n-- > 0) putsyms("\b \b");
while (n-- > 0)
#ifdef UNICODE_WIDEWINPORT
putsyms(L"\b \b");
#else
putsyms("\b \b");
#endif
}
extern char erase_char; /* from xxxtty.c; don't need kill_char */
@@ -331,6 +426,9 @@ char def;
struct WinDesc *cw = wins[WIN_MESSAGE];
boolean doprev = 0;
char prompt[QBUFSZ];
#ifdef UNICODE_WIDEWINPORT
nhwchar wprompt[QBUFSZ];
#endif
if(ttyDisplay->toplin == 1 && !(cw->flags & WIN_STOP)) more();
cw->flags &= ~WIN_STOP;
@@ -362,7 +460,12 @@ char def;
ttyDisplay->inread = sav;
tty_clear_nhwindow(WIN_MESSAGE);
cw->maxcol = cw->maxrow;
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(wprompt, prompt);
addtopl(wprompt);
#else
addtopl(prompt);
#endif
} else {
if(!doprev)
(void) tty_doprev_message(); /* need two initially */
@@ -378,7 +481,12 @@ char def;
tty_clear_nhwindow(WIN_MESSAGE);
cw->maxcol = cw->maxrow;
doprev = 0;
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(wprompt, prompt);
addtopl(wprompt);
#else
addtopl(prompt);
#endif
q = '\0'; /* force another loop iteration */
continue;
}
@@ -399,13 +507,18 @@ char def;
tty_nhbell();
q = (char)0;
} else if (q == '#' || digit_ok) {
char z, digit_string[2];
char z;
nhwchar digit_string[2];
int n_len = 0;
long value = 0;
#ifdef UNICODE_WIDEWINPORT
addtopl(L"#"), n_len++;
#else
addtopl("#"), n_len++;
digit_string[1] = '\0';
#endif
digit_string[1] = (nhwchar)0;
if (q != '#') {
digit_string[0] = q;
digit_string[0] = (nhwchar)q;
addtopl(digit_string), n_len++;
value = q - '0';
q = '#';
@@ -415,7 +528,7 @@ char def;
if (digit(z)) {
value = (10 * value) + (z - '0');
if (value < 0) break; /* overflow: try again */
digit_string[0] = z;
digit_string[0] = (nhwchar)z;
addtopl(digit_string), n_len++;
} else if (z == 'y' || index(quitchars, z)) {
if (z == '\033') value = -1; /* abort */
@@ -440,7 +553,12 @@ char def;
if (q != '#') {
Sprintf(rtmp, "%c", q);
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(wprompt, rtmp); /* rtmp[40] -> wprompt[128] ok */
addtopl(wprompt);
#else
addtopl(rtmp);
#endif
}
clean_up:
ttyDisplay->inread--;
@@ -468,6 +586,7 @@ boolean init;
static boolean doneinit = FALSE;
register struct WinDesc *cw = wins[WIN_MESSAGE];
char *retstr = (char *)0;
static char buf[BUFSZ];
if (!cw) return (char *)0; /* bail */
/*
@@ -483,11 +602,24 @@ boolean init;
if (doneinit && state < 2) {
if (state == 1) {
++state;
#ifdef UNICODE_WIDEWINPORT
strnhwcpy(buf,toplines);
return buf;
#else
return toplines;
#endif
}
do {
#ifdef UNICODE_WIDEWINPORT
if(cw->data[idx] && nhwcmp(cw->data[idx], emptysym) ) {
strnhwcpy(buf, cw->data[idx]);
retstr = buf;
}
#else
if(cw->data[idx] && strcmp(cw->data[idx], "") )
retstr = cw->data[idx];
#endif
idx = (idx + 1) % cw->rows;
} while (idx != cw->maxrow && !retstr);
if (idx == cw->maxrow) ++state;
@@ -513,10 +645,14 @@ const char *msg;
if (len > (unsigned)cw->datlen[idx]) {
if (cw->data[idx]) free(cw->data[idx]);
len += (8 - (len & 7)); /* pad up to next multiple of 8 */
cw->data[idx] = (char *)alloc(len);
cw->data[idx] = (nhwchar *)alloc(sizeof(nhwchar) * len);
cw->datlen[idx] = (short)len;
}
#ifdef UNICODE_WIDEWINPORT
(void)nhwstrcpy(cw->data[idx], msg);
#else
Strcpy(cw->data[idx], msg);
#endif
cw->maxcol = cw->maxrow = (idx + 1) % cw->rows;
}
#endif /* TTY_GRAPHICS */

View File

@@ -43,6 +43,11 @@ extern char mapped_menu_cmds[]; /* from options.c */
/* this is only needed until tty_status_* routines are written */
extern NEARDATA winid WIN_STATUS;
#ifdef UNICODE_WIDEWINPORT
void FDECL(tty_putmixed,(winid,int,const char *));
void FDECL(tty_putstr_core,(winid,int,const nhwchar *));
#endif
/* Interface definition, for windows.c */
struct window_procs tty_procs = {
"tty",
@@ -70,7 +75,11 @@ struct window_procs tty_procs = {
tty_destroy_nhwindow,
tty_curs,
tty_putstr,
#ifdef UNICODE_WIDEWINPORT
tty_putmixed,
#else
genl_putmixed,
#endif
tty_display_file,
tty_start_menu,
tty_add_menu,
@@ -141,7 +150,12 @@ static char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
#endif
static char winpanicstr[] = "Bad window id %d";
char defmorestr[] = "--More--";
#ifdef UNICODE_WIDEWINPORT
nhwchar defmorestr[] = L"--More--";
#else
nhwchar defmorestr[] = "--More--";
#endif
nhwchar emptysym[1] = {0};
#ifdef CLIPPING
# if defined(USE_TILES) && defined(MSDOS)
@@ -181,8 +195,9 @@ STATIC_DCL void FDECL(process_menu_window, (winid,struct WinDesc *));
STATIC_DCL void FDECL(process_text_window, (winid,struct WinDesc *));
STATIC_DCL tty_menu_item *FDECL(reverse, (tty_menu_item *));
STATIC_DCL const char * FDECL(compress_str, (const char *));
STATIC_DCL void FDECL(tty_putsym, (winid, int, int, CHAR_P));
STATIC_DCL void FDECL(tty_putsym, (winid, int, int, NHWCHAR_P));
static char *FDECL(copy_of, (const char *));
static nhwchar *FDECL(nhwchar_copy_of, (const nhwchar *));
STATIC_DCL void FDECL(bail, (const char *)); /* __attribute__((noreturn)) */
/*
@@ -260,7 +275,11 @@ winch()
for(i=WIN_INVEN; i < MAXWIN; i++)
if(wins[i] && wins[i]->active) {
/* cop-out */
#ifdef UNICODE_WIDEWINPORT
addtopl(L"Press Return to continue: ");
#else
addtopl("Press Return to continue: ");
#endif
break;
}
(void) fflush(stdout);
@@ -953,24 +972,24 @@ tty_create_nhwindow(type)
if(newwin->maxrow) {
newwin->data =
(char **) alloc(sizeof(char *) * (unsigned)newwin->maxrow);
(nhwchar **) alloc(sizeof(nhwchar *) * (unsigned)newwin->maxrow);
newwin->datlen =
(short *) alloc(sizeof(short) * (unsigned)newwin->maxrow);
if(newwin->maxcol) {
for (i = 0; i < newwin->maxrow; i++) {
newwin->data[i] = (char *) alloc((unsigned)newwin->maxcol);
newwin->data[i] = (nhwchar *) alloc(sizeof(nhwchar) * (unsigned)newwin->maxcol);
newwin->datlen[i] = newwin->maxcol;
}
} else {
for (i = 0; i < newwin->maxrow; i++) {
newwin->data[i] = (char *) 0;
newwin->data[i] = (nhwchar *) 0;
newwin->datlen[i] = 0;
}
}
if(newwin->type == NHW_MESSAGE)
newwin->maxrow = 0;
} else {
newwin->data = (char **)0;
newwin->data = (nhwchar **)0;
newwin->datlen = (short *)0;
}
@@ -1008,12 +1027,12 @@ free_window_info(cw, free_data)
for(i=0; i<cw->maxrow; i++)
if(cw->data[i]) {
free((genericptr_t)cw->data[i]);
cw->data[i] = (char *)0;
cw->data[i] = (nhwchar *)0;
if (cw->datlen) cw->datlen[i] = 0;
}
if (free_data) {
free((genericptr_t)cw->data);
cw->data = (char **)0;
cw->data = (nhwchar **)0;
if (cw->datlen) free((genericptr_t)cw->datlen);
cw->datlen = (short *)0;
cw->rows = 0;
@@ -1087,15 +1106,25 @@ dmore(cw, s)
register struct WinDesc *cw;
const char *s; /* valid responses */
{
const char *prompt = cw->morestr ? cw->morestr : defmorestr;
#ifdef UNICODE_WIDEWINPORT
char buf[BUFSZ];
#endif
const nhwchar *prompt = cw->morestr ? cw->morestr : defmorestr;
int offset = (cw->type == NHW_TEXT) ? 1 : 2;
tty_curs(BASE_WINDOW,
(int)ttyDisplay->curx + offset, (int)ttyDisplay->cury);
if(flags.standout)
standoutbeg();
#ifdef UNICODE_WIDEWINPORT
strnhwcpy(buf, prompt);
xputs(buf);
ttyDisplay->curx += strlen(buf);
#else
xputs(prompt);
ttyDisplay->curx += strlen(prompt);
#endif
if(flags.standout)
standoutend();
@@ -1210,13 +1239,13 @@ struct WinDesc *cw;
long count;
int n, curr_page, page_lines;
boolean finished, counting, reset_count;
char *cp, *rp, resp[QBUFSZ], gacc[QBUFSZ],
*msave, *morestr;
char *cp, *rp, resp[QBUFSZ], gacc[QBUFSZ];
nhwchar *msave, *morestr;
curr_page = page_lines = 0;
page_start = page_end = 0;
msave = cw->morestr; /* save the morestr */
cw->morestr = morestr = (char*) alloc((unsigned) QBUFSZ);
cw->morestr = morestr = (nhwchar*) alloc(sizeof(nhwchar) * (unsigned) QBUFSZ);
counting = FALSE;
count = 0L;
reset_count = TRUE;
@@ -1332,20 +1361,41 @@ struct WinDesc *cw;
Strcat(resp, gacc); /* group accelerators */
Strcat(resp, mapped_menu_cmds);
if (cw->npages > 1)
if (cw->npages > 1) {
#ifdef UNICODE_WIDEWINPORT
char buf[BUFSZ];
Sprintf(buf, "(%d of %d)",
curr_page + 1, (int) cw->npages);
(void)nhwstrcpy(cw->morestr, buf);
#else
Sprintf(cw->morestr, "(%d of %d)",
curr_page + 1, (int) cw->npages);
else if (msave)
#endif
} else if (msave) {
#ifdef UNICODE_WIDEWINPORT
(void)nhwcpy(cw->morestr, msave);
#else
Strcpy(cw->morestr, msave);
else
#endif
} else {
#ifdef UNICODE_WIDEWINPORT
(void)nhwcpy(cw->morestr, defmorestr);
#else
Strcpy(cw->morestr, defmorestr);
#endif
}
tty_curs(window, 1, page_lines);
cl_end();
dmore(cw, resp);
} else {
/* just put the cursor back... */
tty_curs(window, (int) strlen(cw->morestr) + 2, page_lines);
tty_curs(window,
#ifdef UNICODE_WIDEWINPORT
(int) nhwlen(cw->morestr) + 2,
#else
(int) strlen(cw->morestr) + 2,
#endif
page_lines);
xwaitforspace(resp);
}
@@ -1509,7 +1559,7 @@ winid window;
struct WinDesc *cw;
{
int i, n, attr;
register char *cp;
register nhwchar *cp;
for (n = 0, i = 0; i < cw->maxrow; i++) {
if (!cw->offx && (n + cw->offy == ttyDisplay->rows - 1)) {
@@ -1543,7 +1593,11 @@ struct WinDesc *cw;
*cp && (int) ttyDisplay->curx < (int) ttyDisplay->cols;
cp++, ttyDisplay->curx++)
#endif
#ifdef UNICODE_WIDEWINPORT
u_putch(*cp);
#else
(void) putchar(*cp);
#endif
term_end_attr(attr);
}
}
@@ -1772,7 +1826,7 @@ STATIC_OVL void
tty_putsym(window, x, y, ch)
winid window;
int x, y;
char ch;
nhwchar ch;
{
register struct WinDesc *cw = 0;
@@ -1784,7 +1838,11 @@ tty_putsym(window, x, y, ch)
case NHW_MAP:
case NHW_BASE:
tty_curs(window, x, y);
#ifdef UNICODE_WIDEWINPORT
u_putch(ch);
#else
(void) putchar(ch);
#endif
ttyDisplay->curx++;
cw->curx++;
break;
@@ -1827,9 +1885,14 @@ tty_putstr(window, attr, str)
const char *str;
{
register struct WinDesc *cw = 0;
register char *ob;
register const char *nb;
#ifdef UNICODE_WIDEWINPORT
nhwchar symbuf[BUFSZ];
register const nhwchar *symstr = symbuf;
#else
register const nhwchar *nb;
register nhwchar *ob;
register int i, j, n0;
#endif
/* Assume there's a real problem if the window is missing --
* probably a panic message
@@ -1844,21 +1907,52 @@ tty_putstr(window, attr, str)
return;
if(cw->type != NHW_MESSAGE)
str = compress_str(str);
#if defined(USER_SOUNDS) && defined(WIN32CON)
else
play_sound_for_message(str);
#endif
#ifdef UNICODE_WIDEWINPORT
nhwstrcpy(symbuf, str);
tty_putstr_core(window, attr, symstr);
}
void
tty_putstr_core(window, attr, symstr)
winid window;
int attr;
const nhwchar *symstr;
{
register struct WinDesc *cw = wins[window];
register const nhwchar *nb;
register nhwchar *ob;
register int i, j, n0;
#endif
ttyDisplay->lastwin = window;
switch(cw->type) {
case NHW_MESSAGE:
/* really do this later */
#if defined(USER_SOUNDS) && defined(WIN32CON)
play_sound_for_message(str);
#endif
#ifdef UNICODE_WIDEWINPORT
update_topl(symstr);
#else
update_topl(str);
#endif
break;
case NHW_STATUS:
ob = &cw->data[cw->cury][j = cw->curx];
if(context.botlx) *ob = 0;
#ifdef UNICODE_WIDEWINPORT
if(!cw->cury && (int)nhwlen(symstr) >= CO) {
/* the characters before "St:" are unnecessary */
nb = nhwindex(symstr, L':');
if(nb && nb > symstr+2)
symstr = nb - 2;
}
nb = symstr;
#else
if(!cw->cury && (int)strlen(str) >= CO) {
/* the characters before "St:" are unnecessary */
nb = index(str, ':');
@@ -1866,6 +1960,8 @@ tty_putstr(window, attr, str)
str = nb - 2;
}
nb = str;
#endif
for(i = cw->curx+1, n0 = cw->cols; i < n0; i++, nb++) {
if(!*nb) {
if(*ob || context.botlx) {
@@ -1880,19 +1976,31 @@ tty_putstr(window, attr, str)
if(*ob) ob++;
}
#ifdef UNICODE_WIDEWINPORT
(void) nhwncpy(&cw->data[cw->cury][j], symstr, cw->cols - j - 1);
#else
(void) strncpy(&cw->data[cw->cury][j], str, cw->cols - j - 1);
cw->data[cw->cury][cw->cols-1] = '\0'; /* null terminate */
#endif
cw->data[cw->cury][cw->cols-1] = (nhwchar)0; /* null terminate */
cw->cury = (cw->cury+1) % 2;
cw->curx = 0;
break;
case NHW_MAP:
tty_curs(window, cw->curx+1, cw->cury);
term_start_attr(attr);
#ifdef UNICODE_WIDEWINPORT
while(*symstr && (int) ttyDisplay->curx < (int) ttyDisplay->cols-1) {
u_putch(*symstr);
symstr++;
ttyDisplay->curx++;
}
#else
while(*str && (int) ttyDisplay->curx < (int) ttyDisplay->cols-1) {
(void) putchar(*str);
str++;
ttyDisplay->curx++;
}
#endif
cw->curx = 0;
cw->cury++;
term_end_attr(attr);
@@ -1900,14 +2008,23 @@ tty_putstr(window, attr, str)
case NHW_BASE:
tty_curs(window, cw->curx+1, cw->cury);
term_start_attr(attr);
#ifdef UNICODE_WIDEWINPORT
while (*symstr) {
#else
while (*str) {
#endif
if ((int) ttyDisplay->curx >= (int) ttyDisplay->cols-1) {
cw->curx = 0;
cw->cury++;
tty_curs(window, cw->curx+1, cw->cury);
}
#ifdef UNICODE_WIDEWINPORT
u_putch(*symstr);
symstr++;
#else
(void) putchar(*str);
str++;
#endif
ttyDisplay->curx++;
}
cw->curx = 0;
@@ -1929,10 +2046,10 @@ tty_putstr(window, attr, str)
}
/* always grows one at a time, but alloc 12 at a time */
if(cw->cury >= cw->rows) {
char **tmp;
nhwchar **tmp;
cw->rows += 12;
tmp = (char **) alloc(sizeof(char *) * (unsigned)cw->rows);
tmp = (nhwchar **) alloc(sizeof(nhwchar *) * (unsigned)cw->rows);
for(i=0; i<cw->maxrow; i++)
tmp[i] = cw->data[i];
if(cw->data)
@@ -1944,10 +2061,19 @@ tty_putstr(window, attr, str)
}
if(cw->data[cw->cury])
free((genericptr_t)cw->data[cw->cury]);
#ifdef UNICODE_WIDEWINPORT
n0 = nhwlen(symstr) + 1;
#else
n0 = strlen(str) + 1;
ob = cw->data[cw->cury] = (char *)alloc((unsigned)n0 + 1);
*ob++ = (char)(attr + 1); /* avoid nuls, for convenience */
#endif
ob = cw->data[cw->cury] = (nhwchar *)alloc(sizeof(nhwchar) * (unsigned)n0 + 1);
*ob++ = (nhwchar)(attr + 1); /* avoid nuls, for convenience */
#ifdef UNICODE_WIDEWINPORT
(void)nhwcpy(ob, symstr);
#else
Strcpy(ob, str);
#endif
if(n0 > cw->maxcol)
cw->maxcol = n0;
@@ -1955,11 +2081,19 @@ tty_putstr(window, attr, str)
cw->maxrow = cw->cury;
if(n0 > CO) {
/* attempt to break the line */
#ifdef UNICODE_WIDEWINPORT
for(i = CO-1; i && symstr[i] != L' ' && symstr[i] != L'\n';)
#else
for(i = CO-1; i && str[i] != ' ' && str[i] != '\n';)
#endif
i--;
if(i) {
cw->data[cw->cury-1][++i] = '\0';
cw->data[cw->cury-1][++i] = (nhwchar)0;
#ifdef UNICODE_WIDEWINPORT
tty_putstr_core(window, attr, &symstr[i]);
#else
tty_putstr(window, attr, &str[i]);
#endif
}
}
@@ -1967,6 +2101,60 @@ tty_putstr(window, attr, str)
}
}
#ifdef UNICODE_WIDEWINPORT
/*
* This differs from putstr() because the str parameter can
* contain a sequence of characters representing:
* \GXXXXNNNN a glyph value, encoded by encglyph().
*
*/
void
tty_putmixed(window, attr, str)
winid window;
int attr;
const char *str;
{
nhwchar wbuf[BUFSZ];
const char *cp = str;
nhwchar *put = wbuf;
while (*cp) {
if (*cp == '\\') {
int rndchk = 0, so = 0, gv = 0, ch, oc, dcount;
unsigned os;
const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
const char *save_cp = cp;
cp++;
switch(*cp) {
case 'G': /* glyph value \GXXXXNNNN*/
dcount = 0;
for (++cp; *cp && (dp = index(hex, *cp)) && (dcount++ < 4); cp++)
rndchk = (int)((rndchk * 16) + ((int)(dp - hex) / 2));
if (rndchk == context.rndencode) {
dcount = 0;
for (; *cp && (dp = index(hex, *cp)) && (dcount++ < 4); cp++)
gv = (int)((gv * 16) + ((int)(dp - hex) / 2));
so = mapglyph(gv, &ch, &oc, &os, 0, 0);
*put++ = (nhwchar)showsyms[so];
continue;
} else {
/* possible forgery - leave it the way it is */
cp = save_cp;
}
break;
case '\\':
break;
}
}
*put++ = (nhwchar)*cp++;
}
*put = (nhwchar)0;
/* now send it to tty_putstr_core() */
tty_putstr_core(window, attr, wbuf);
}
#endif /*UNICODE_WIDEWINPORT*/
void
tty_display_file(fname, complain)
const char *fname;
@@ -2149,7 +2337,7 @@ tty_end_menu(window, prompt)
/* Reverse the list so that items are in correct order. */
cw->mlist = reverse(cw->mlist);
/* Put the promt at the beginning of the menu. */
/* Put the prompt at the beginning of the menu. */
if (prompt) {
anything any;
@@ -2200,10 +2388,19 @@ tty_end_menu(window, prompt)
/* produce the largest demo string */
Sprintf(buf, "(%d of %d) ", cw->npages, cw->npages);
len = strlen(buf);
#ifdef UNICODE_WIDEWINPORT
cw->morestr = nhwchar_copy_of(emptysym);
#else
cw->morestr = copy_of("");
#endif
} else {
#ifdef UNICODE_WIDEWINPORT
cw->morestr = nhwchar_copy_of(L"(end) ");
len = nhwlen(cw->morestr);
#else
cw->morestr = copy_of("(end) ");
len = strlen(cw->morestr);
#endif
}
if (len > (int)ttyDisplay->cols) {
@@ -2323,7 +2520,11 @@ tty_wait_synch()
} else {
tty_display_nhwindow(WIN_MAP, FALSE);
if(ttyDisplay->inmore) {
#ifdef UNICODE_WIDEWINPORT
addtopl(L"--More--");
#else
addtopl("--More--");
#endif
(void) fflush(stdout);
} else if(ttyDisplay->inread > program_state.gameover) {
/* this can only happen if we were reading and got interrupted */
@@ -2395,6 +2596,58 @@ end_glyphout()
#endif
}
#ifdef UNICODE_WIDEWINPORT
/*
* Parts of u_putch() were contributed by Adam Wozniak, 2005.
*/
void
u_putch(sym)
nhwchar sym;
{
unsigned long unicode = sym;
if (!iflags.unicodedisp)
putchar((char)sym);
else {
#if defined(UNIX) || defined(VMS)
/* send utf8 to display */
if (unicode < 0x80) {
(void) putchar(unicode);
} else if (unicode < 0x00000800) {
(void) putchar(0xC0 | (unicode >> 6));
(void) putchar(0x80 | (unicode & 0x3F));
} else if (unicode < 0x00010000) {
(void) putchar(0xE0 | (unicode >> 12));
(void) putchar(0x80 | ((unicode >> 6) & 0x3F));
(void) putchar(0x80 | (unicode & 0x3F));
} else if (unicode < 0x00200000) {
(void) putchar(0xF0 | (unicode >> 18));
(void) putchar(0x80 | ((unicode >> 12) & 0x3F));
(void) putchar(0x80 | ((unicode >> 6) & 0x3F));
(void) putchar(0x80 | (unicode & 0x3F));
} else if (unicode < 0x04000000) {
(void) putchar(0xF8 | (unicode >> 24));
(void) putchar(0x80 | ((unicode >> 18) & 0x3F));
(void) putchar(0x80 | ((unicode >> 12) & 0x3F));
(void) putchar(0x80 | ((unicode >> 6) & 0x3F));
(void) putchar(0x80 | (unicode & 0x3F));
} else {
(void) putchar(0xFC | (unicode >> 30));
(void) putchar(0x80 | ((unicode >> 24) & 0x3F));
(void) putchar(0x80 | ((unicode >> 18) & 0x3F));
(void) putchar(0x80 | ((unicode >> 12) & 0x3F));
(void) putchar(0x80 | ((unicode >> 6) & 0x3F));
(void) putchar(0x80 | (unicode & 0x3F));
}
#else
/* it is assumed that whatever is being substituted for
putchar() can handle unicode characters directly at
this point (nttty's xputc() for example) */
(void) putchar(sym);
#endif
}
}
#endif /*UNICODE_WIDEWINPORT*/
#ifndef WIN32
void
g_putch(in_ch)
@@ -2403,6 +2656,11 @@ int in_ch;
register char ch = (char)in_ch;
# if defined(ASCIIGRAPH) && !defined(NO_TERMS)
# if defined(UNICODE_WIDEWINPORT) && defined(UNICODE_DRAWING)
if (iflags.unicodedisp && symset[currentgraphics].name) {
u_putch(in_ch);
} else
# endif
if (SYMHANDLING(H_IBM) || iflags.eight_bit_tty) {
/* IBM-compatible displays don't need other stuff */
(void) putchar(ch);
@@ -2486,9 +2744,9 @@ tty_print_glyph(window, x, y, glyph)
xchar x, y;
int glyph;
{
int ch;
int ch, idx;
boolean reverse_on = FALSE;
int color;
int color;
unsigned special;
#ifdef CLIPPING
@@ -2498,7 +2756,7 @@ tty_print_glyph(window, x, y, glyph)
}
#endif
/* map glyph to character and color */
(void)mapglyph(glyph, &ch, &color, &special, x, y);
idx = mapglyph(glyph, &ch, &color, &special, x, y);
/* Move the cursor. */
tty_curs(window, x,y);
@@ -2531,6 +2789,11 @@ tty_print_glyph(window, x, y, glyph)
if (iflags.grmode && iflags.tile_view)
xputg(glyph,ch,special);
else
#endif
#if defined(UNICODE_WIDEWINPORT) && defined(UNICODE_DRAWING)
if (iflags.unicodedisp && symset[currentgraphics].name)
g_putch(showsyms[idx]); /* use the unicode symset */
else
#endif
g_putch(ch); /* print the character */
@@ -2683,6 +2946,15 @@ copy_of(s)
return strcpy((char *) alloc((unsigned) (strlen(s) + 1)), s);
}
# ifdef UNICODE_WIDEWINPORT
static nhwchar *
nhwchar_copy_of(s)
const nhwchar *s;
{
if (!s) s = emptysym;
return nhwcpy((nhwchar *) alloc(sizeof(nhwchar) * (unsigned) (nhwlen(s) + 1)), s);
}
# endif /*UNICODE_WIDEWINPORT*/
#endif /* TTY_GRAPHICS */
/*wintty.c*/