From 7f0f43e6f98bccab20db7ab3cb509fdbe60a7b2b Mon Sep 17 00:00:00 2001 From: "nethack.allison" Date: Tue, 17 Oct 2006 23:55:42 +0000 Subject: [PATCH] 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. --- dat/symbols | 132 ++++++++++++++++++ include/config.h | 6 +- include/decl.h | 5 +- include/extern.h | 16 ++- include/flag.h | 2 + include/global.h | 37 ++++- include/ntconf.h | 5 + include/rm.h | 24 ++-- include/tradstdc.h | 2 + include/wintty.h | 17 ++- src/decl.c | 3 +- src/drawing.c | 10 +- src/files.c | 107 +++++++++++++- src/hacklib.c | 188 +++++++++++++++++++++++++ src/mapglyph.c | 19 +-- src/options.c | 99 ++++++++----- src/pager.c | 2 +- src/pline.c | 6 +- sys/winnt/nttty.c | 85 +++++++++--- win/tty/getline.c | 71 ++++++++-- win/tty/topl.c | 194 ++++++++++++++++++++++---- win/tty/wintty.c | 340 ++++++++++++++++++++++++++++++++++++++++----- 22 files changed, 1193 insertions(+), 177 deletions(-) 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*/