diff --git a/dat/symbols b/dat/symbols index 108d761d1..8f396582b 100644 --- a/dat/symbols +++ b/dat/symbols @@ -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 + diff --git a/include/config.h b/include/config.h index 8b54d1d67..8b63083e5 100644 --- a/include/config.h +++ b/include/config.h @@ -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 */ diff --git a/include/decl.h b/include/decl.h index 37a3489d6..c4b4db3ed 100644 --- a/include/decl.h +++ b/include/decl.h @@ -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) */ diff --git a/include/extern.h b/include/extern.h index 7ab7ffcdf..f828e7841 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 ### */ diff --git a/include/flag.h b/include/flag.h index a9fe3869c..5878c443f 100644 --- a/include/flag.h +++ b/include/flag.h @@ -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 */ diff --git a/include/global.h b/include/global.h index e761b5d60..cee74d9fb 100644 --- a/include/global.h +++ b/include/global.h @@ -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) diff --git a/include/ntconf.h b/include/ntconf.h index 8323af597..39c2d4c36 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -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 diff --git a/include/rm.h b/include/rm.h index 8c840693e..312ff1929 100644 --- a/include/rm.h +++ b/include/rm.h @@ -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 */ diff --git a/include/tradstdc.h b/include/tradstdc.h index ccd4e7d67..02a75bc39 100644 --- a/include/tradstdc.h +++ b/include/tradstdc.h @@ -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. */ diff --git a/include/wintty.h b/include/wintty.h index fc993aa3c..51b491086 100644 --- a/include/wintty.h +++ b/include/wintty.h @@ -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 **)); diff --git a/src/decl.c b/src/decl.c index cba20bfc7..27524c529 100644 --- a/src/decl.c +++ b/src/decl.c @@ -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 */ diff --git a/src/drawing.c b/src/drawing.c index 11d569ad9..161c858f0 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -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, }; diff --git a/src/files.c b/src/files.c index 6dedcfed7..1dffde979 100644 --- a/src/files.c +++ b/src/files.c @@ -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 ----------- */ diff --git a/src/hacklib.c b/src/hacklib.c index 6b599822f..9fd49d710 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -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*/ diff --git a/src/mapglyph.c b/src/mapglyph.c index a21c81926..3ceb1c404 100644 --- a/src/mapglyph.c +++ b/src/mapglyph.c @@ -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*/ diff --git a/src/options.c b/src/options.c index a09489339..59f38665e 100644 --- a/src/options.c +++ b/src/options.c @@ -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() */ diff --git a/src/pager.c b/src/pager.c index 138c254e8..430167a7f 100644 --- a/src/pager.c +++ b/src/pager.c @@ -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", diff --git a/src/pline.c b/src/pline.c index 313d07bd6..3fb5f4d39 100644 --- a/src/pline.c +++ b/src/pline.c @@ -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); diff --git a/sys/winnt/nttty.c b/sys/winnt/nttty.c index 1c641c1f8..412d37747 100644 --- a/sys/winnt/nttty.c +++ b/sys/winnt/nttty.c @@ -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); diff --git a/win/tty/getline.c b/win/tty/getline.c index fbe4d85dc..6987cd7c4 100644 --- a/win/tty/getline.c +++ b/win/tty/getline.c @@ -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 */ diff --git a/win/tty/topl.c b/win/tty/topl.c index c896c5ff3..4f8135b37 100644 --- a/win/tty/topl.c +++ b/win/tty/topl.c @@ -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 */ diff --git a/win/tty/wintty.c b/win/tty/wintty.c index dc44a507a..82e5eacd9 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -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; imaxrow; 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; imaxrow; 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*/