Subject: PATCH: Fix for NT keyboard and support for ISO-8859-1 character set: part 1, the patch [long]

From: Ray Chason <[email-masked]>
Date: Fri, 01 Feb 2002 03:10:17 -0000

This patch provides two improvements to the official sources:

* On Windows NT, add support for keyboards other than USA, and allow
  typing of diacritics.

* On NT, MSDOS, and Linux (may work on other Unixes), provide full support
  for characters in the ISO-8859-1 character set.

These are the changes I made to support diacritics on Spanish Nethack.
They do not change bones or save files.

--CUT HERE--CUT HERE--CUT HERE--CUT HERE--CUT HERE--CUT HERE--CUT HERE--
diff -C 3 -r nethack-3.3.1/include/flag.h nethack-3.3.1-latin1/include/flag.h
*** nethack-3.3.1/include/flag.h	Sun Oct  8 21:57:58 2000
--- nethack-3.3.1-latin1/include/flag.h	Wed Jan  9 06:11:58 2002
***************
*** 143,148 ****
--- 143,149 ----
   */
  
  struct instance_flags {
+ 	boolean  accents;	/* display supports accented characters */
  	boolean  cbreak;	/* in cbreak mode, rogue format */
  	boolean  DECgraphics;	/* use DEC VT-xxx extended character set */
  	boolean  echo;		/* 1 to echo characters */
***************
*** 151,156 ****
--- 152,158 ----
  	boolean  extmenu;	/* extended commands use menu interface */
  #endif
  	boolean  IBMgraphics;	/* use IBM extended character set */
+ 	boolean  IBMcharset;	/* display has IBM character set (else Latin-1) */
  	unsigned msg_history;	/* hint: # of top lines to save */
  	boolean  num_pad;	/* use numbers for movement commands */
  	boolean  news;		/* print news */
diff -C 3 -r nethack-3.3.1/src/drawing.c nethack-3.3.1-latin1/src/drawing.c
*** nethack-3.3.1/src/drawing.c	Sun Oct  8 21:58:00 2000
--- nethack-3.3.1-latin1/src/drawing.c	Thu Jan 31 20:02:40 2002
***************
*** 19,24 ****
--- 19,29 ----
  
  #define g_FILLER(symbol) 0
  
+ #ifdef __linux__
+ extern void NDECL(linux_mapon);
+ extern void NDECL(linux_mapoff);
+ #endif
+ 
  uchar oc_syms[MAXOCLASSES] = DUMMY; /* the current object  display symbols */
  uchar showsyms[MAXPCHARS]  = DUMMY; /* the current feature display symbols */
  uchar monsyms[MAXMCLASSES] = DUMMY; /* the current monster display symbols */
***************
*** 408,413 ****
--- 413,533 ----
  /*90*/	g_FILLER(S_explode8),
  	g_FILLER(S_explode9)
  };
+ /* LENGUA:  lat1_graphics replaces the 0xf0, 0xf4, and 0xfe characters with
+    0xe3, 0xe1, and 0xdb, symbols that are common to the IBM and Latin-1
+    character sets.  This map is for Linux, with modifications for MSDOS; other
+    systems may need a different map. */
+ static uchar lat1_graphics[MAXPCHARS] = {
+ /* 0*/	g_FILLER(S_stone),
+ 	0xb3,	/* S_vwall:	meta-3, vertical rule */
+ 	0xc4,	/* S_hwall:	meta-D, horizontal rule */
+ 	0xda,	/* S_tlcorn:	meta-Z, top left corner */
+ 	0xbf,	/* S_trcorn:	meta-?, top right corner */
+ 	0xc0,	/* S_blcorn:	meta-@, bottom left */
+ 	0xd9,	/* S_brcorn:	meta-Y, bottom right */
+ 	0xc5,	/* S_crwall:	meta-E, cross */
+ 	0xc1,	/* S_tuwall:	meta-A, T up */
+ 	0xc2,	/* S_tdwall:	meta-B, T down */
+ /*10*/	0xb4,	/* S_tlwall:	meta-4, T left */
+ 	0xc3,	/* S_trwall:	meta-C, T right */
+ 	0xfa,	/* S_ndoor:	meta-z, centered dot */
+ #ifdef __linux__
+ 	0xdb,	/* S_vodoor:	solid block */
+ 	0xdb,	/* S_hodoor:	solid block */
+ #else /* MSDOS etc */
+ 	0xfe,	/* S_vodoor:	meta-~, small centered square */
+ 	0xfe,	/* S_hodoor:	meta-~, small centered square */
+ #endif
+ 	g_FILLER(S_vcdoor),
+ 	g_FILLER(S_hcdoor),
+ 	227,	/* S_bars:	small pi */
+ 	241,	/* S_tree:	plus or minus symbol */
+ 	0xfa,	/* S_room:	meta-z, centered dot */
+ /*20*/	0xb0,	/* S_corr:	meta-0, light shading */
+ 	0xb1,	/* S_litcorr:	meta-1, medium shading */
+ 	g_FILLER(S_upstair),
+ 	g_FILLER(S_dnstair),
+ 	g_FILLER(S_upladder),
+ 	g_FILLER(S_dnladder),
+ 	g_FILLER(S_altar),
+ 	g_FILLER(S_grave),
+ 	g_FILLER(S_throne),
+ 	g_FILLER(S_sink),
+ /*30*/	0xe1,	/* S_fountain:	beta/German double S */
+ #ifdef __linux__
+ 	0xf7,	/* S_pool:	meta-w, approx. equals */
+ #else /* MSDOS etc */
+ 	0xf5,	/* S_pool:	meta-u, section mark */
+ #endif
+ 	0xfa,	/* S_ice:	meta-z, centered dot */
+ #ifdef __linux__
+ 	0xf7,	/* S_lava:	meta-w, approx. equals */
+ #else /* MSDOS etc */
+ 	0xf5,	/* S_lava:	meta-u, section mark */
+ #endif
+ 	0xfa,	/* S_vodbridge:	meta-z, centered dot */
+ 	0xfa,	/* S_hodbridge:	meta-z, centered dot */
+ 	g_FILLER(S_vcdbridge),
+ 	g_FILLER(S_hcdbridge),
+ 	g_FILLER(S_air),
+ 	g_FILLER(S_cloud),
+ #ifdef __linux__
+ /*40*/	0xf7,	/* S_water:	meta-w, approx. equals */
+ #else /* MSDOS etc */
+ /*40*/	0xf5,	/* S_water:	meta-u, section mark */
+ #endif
+ 	g_FILLER(S_arrow_trap),
+ 	g_FILLER(S_dart_trap),
+ 	g_FILLER(S_falling_rock_trap),
+ 	g_FILLER(S_squeaky_board),
+ 	g_FILLER(S_bear_trap),
+ 	g_FILLER(S_land_mine),
+ 	g_FILLER(S_rolling_boulder_trap),
+ 	g_FILLER(S_sleeping_gas_trap),
+ 	g_FILLER(S_rust_trap),
+ /*50*/	g_FILLER(S_fire_trap),
+ 	g_FILLER(S_pit),
+ 	g_FILLER(S_spiked_pit),
+ 	g_FILLER(S_hole),
+ 	g_FILLER(S_trap_door),
+ 	g_FILLER(S_teleportation_trap),
+ 	g_FILLER(S_level_teleporter),
+ 	g_FILLER(S_magic_portal),
+ 	g_FILLER(S_web),
+ 	g_FILLER(S_statue_trap),
+ /*60*/	g_FILLER(S_magic_trap),
+ 	g_FILLER(S_anti_magic_trap),
+ 	g_FILLER(S_polymorph_trap),
+ 	0xb3,	/* S_vbeam:	meta-3, vertical rule */
+ 	0xc4,	/* S_hbeam:	meta-D, horizontal rule */
+ 	g_FILLER(S_lslant),
+ 	g_FILLER(S_rslant),
+ 	g_FILLER(S_digbeam),
+ 	g_FILLER(S_flashbeam),
+ 	g_FILLER(S_boomleft),
+ /*70*/	g_FILLER(S_boomright),
+ 	g_FILLER(S_ss1),
+ 	g_FILLER(S_ss2),
+ 	g_FILLER(S_ss3),
+ 	g_FILLER(S_ss4),
+ 	g_FILLER(S_sw_tl),
+ 	g_FILLER(S_sw_tc),
+ 	g_FILLER(S_sw_tr),
+ 	0xb3,	/* S_sw_ml:	meta-3, vertical rule */
+ 	0xb3,	/* S_sw_mr:	meta-3, vertical rule */
+ /*80*/	g_FILLER(S_sw_bl),
+ 	g_FILLER(S_sw_bc),
+ 	g_FILLER(S_sw_br),
+ 	g_FILLER(S_explode1),
+ 	g_FILLER(S_explode2),
+ 	g_FILLER(S_explode3),
+ 	0xb3,	/* S_explode4:	meta-3, vertical rule */
+ 	g_FILLER(S_explode5),
+ 	0xb3,	/* S_explode6:	meta-3, vertical rule */
+ 	g_FILLER(S_explode7),
+ /*90*/	g_FILLER(S_explode8),
+ 	g_FILLER(S_explode9)
+ };
  #endif  /* ASCIIGRAPH */
  
  #ifdef TERMLIB
***************
*** 659,664 ****
--- 779,787 ----
  	default:
  	case ASCII_GRAPHICS:
  	    assign_graphics((uchar *)0, 0, MAXPCHARS, 0);
+ #ifdef __linux__
+ 	    linux_mapon();
+ #endif
  #ifdef PC9800
  	    if (ascgraphics_mode_callback) (*ascgraphics_mode_callback)();
  #endif
***************
*** 674,680 ****
   */
  	    iflags.IBMgraphics = TRUE;
  	    iflags.DECgraphics = FALSE;
! 	    assign_graphics(ibm_graphics, SIZE(ibm_graphics), MAXPCHARS, 0);
  #ifdef PC9800
  	    if (ibmgraphics_mode_callback) (*ibmgraphics_mode_callback)();
  #endif
--- 797,809 ----
   */
  	    iflags.IBMgraphics = TRUE;
  	    iflags.DECgraphics = FALSE;
! 	    if (iflags.IBMcharset)
! 		assign_graphics(ibm_graphics, SIZE(ibm_graphics), MAXPCHARS, 0);
! 	    else
! 		assign_graphics(lat1_graphics, SIZE(lat1_graphics), MAXPCHARS, 0);
! #ifdef __linux__
! 	    linux_mapoff();
! #endif
  #ifdef PC9800
  	    if (ibmgraphics_mode_callback) (*ibmgraphics_mode_callback)();
  #endif
***************
*** 689,694 ****
--- 818,826 ----
  	    iflags.IBMgraphics = FALSE;
  	    assign_graphics(dec_graphics, SIZE(dec_graphics), MAXPCHARS, 0);
  	    if (decgraphics_mode_callback) (*decgraphics_mode_callback)();
+ #ifdef __linux__
+ 	    linux_mapon();
+ #endif
  	    break;
  #endif /* TERMLIB */
  #ifdef MAC_GRAPHICS_ENV
***************
*** 796,801 ****
--- 928,936 ----
  	    monsyms[i] = def_monsyms[i];
  # ifdef ASCIIGRAPH
  	if (iflags.IBMgraphics
+ #  if defined(__linux__)
+ 		&& iflags.IBMcharset
+ #  endif
  #  if defined(USE_TILES) && defined(MSDOS)
  		&& !iflags.grmode
  #  endif
***************
*** 840,847 ****
  	    showsyms[S_room]    = 0xfa; /* centered dot */
  	    showsyms[S_corr]    = 0xb1;
  	    showsyms[S_litcorr] = 0xb2;
! 	    showsyms[S_upstair] = 0xf0; /* Greek Xi */
! 	    showsyms[S_dnstair] = 0xf0;
  	    showsyms[S_arrow_trap] = 0x04; /* diamond (cards) */
  	    showsyms[S_dart_trap] = 0x04;
  	    showsyms[S_falling_rock_trap] = 0x04;
--- 975,987 ----
  	    showsyms[S_room]    = 0xfa; /* centered dot */
  	    showsyms[S_corr]    = 0xb1;
  	    showsyms[S_litcorr] = 0xb2;
! 	    /* LENGUA: Latin-1 doesn't have the 0xF0 character */
! 	    if (iflags.IBMcharset) {
! 		showsyms[S_upstair] = 0xf0; /* Greek Xi */
! 		showsyms[S_dnstair] = 0xf0;
! 	    } else {
! 		showsyms[S_upstair] = showsyms[S_dnstair] = '%';
! 	    }
  	    showsyms[S_arrow_trap] = 0x04; /* diamond (cards) */
  	    showsyms[S_dart_trap] = 0x04;
  	    showsyms[S_falling_rock_trap] = 0x04;
***************
*** 873,881 ****
  # if defined(USE_TILES) && defined(MSDOS)
  		&& !iflags.grmode
  # endif
! 		)
  		oc_syms[i] = IBM_r_oc_syms[i];
! 	    else
  #endif /* ASCIIGRAPH */
  		oc_syms[i] = r_oc_syms[i];
  	}
--- 1013,1026 ----
  # if defined(USE_TILES) && defined(MSDOS)
  		&& !iflags.grmode
  # endif
! 		) {
  		oc_syms[i] = IBM_r_oc_syms[i];
! # if defined(__linux__) || defined(MSDOS)
! 		/* Fixup for missing IBM character */
! 		if (oc_syms[i]==0xE7 && !iflags.IBMcharset)
! 		    oc_syms[i] = '/';
! # endif
! 	    } else
  #endif /* ASCIIGRAPH */
  		oc_syms[i] = r_oc_syms[i];
  	}
diff -C 3 -r nethack-3.3.1/src/options.c nethack-3.3.1-latin1/src/options.c
*** nethack-3.3.1/src/options.c	Sun Oct  8 21:58:00 2000
--- nethack-3.3.1-latin1/src/options.c	Thu Jan 31 20:07:38 2002
***************
*** 29,34 ****
--- 29,35 ----
  	const char *name;
  	boolean	*addr, initvalue;
  } boolopt[] = {
+ 	{"accents", &iflags.accents, TRUE},
  #ifdef AMIGA
  	{"altmeta", &flags.altmeta, TRUE},
  #else
***************
*** 98,105 ****
--- 99,108 ----
  #endif
  #ifdef ASCIIGRAPH
  	{"IBMgraphics", &iflags.IBMgraphics, FALSE},
+ 	{"IBMcharset", &iflags.IBMcharset, FALSE},
  #else
  	{"IBMgraphics", (boolean *)0, FALSE},
+ 	{"IBMcharset", (boolean *)0, FALSE},
  #endif
  	{"ignintr", &flags.ignintr, FALSE},
  #ifdef MAC_GRAPHICS_ENV
***************
*** 1695,1700 ****
--- 1698,1704 ----
  # endif
  # ifdef ASCIIGRAPH
  				 || (boolopt[i].addr) == &iflags.IBMgraphics
+ 				 || (boolopt[i].addr) == &iflags.IBMcharset
  # endif
  # ifdef MAC_GRAPHICS_ENV
  				 || (boolopt[i].addr) == &iflags.MACgraphics
***************
*** 1713,1718 ****
--- 1717,1730 ----
  # ifdef ASCIIGRAPH
  			    if ((boolopt[i].addr) == &iflags.IBMgraphics)
  				switch_graphics(iflags.IBMgraphics ?
+ 						IBM_GRAPHICS : ASCII_GRAPHICS);
+ 			    if ((boolopt[i].addr) == &iflags.IBMcharset)
+ 				switch_graphics(
+ #ifdef TERMLIB
+ 						iflags.DECgraphics ?
+ 						DEC_GRAPHICS :
+ #endif
+ 						iflags.IBMgraphics ?
  						IBM_GRAPHICS : ASCII_GRAPHICS);
  # endif
  # ifdef MAC_GRAPHICS_ENV
diff -C 3 -r nethack-3.3.1/sys/msdos/video.c nethack-3.3.1-latin1/sys/msdos/video.c
*** nethack-3.3.1/sys/msdos/video.c	Sat Dec 11 05:21:02 1999
--- nethack-3.3.1-latin1/sys/msdos/video.c	Thu Jan 31 20:12:06 2002
***************
*** 71,76 ****
--- 71,78 ----
   *=========================================================================
   */
  
+ /* 8-bit character handling */
+ extern char ibmconvert[], ibm850convert[];
  
  #ifdef OVLB
  void
***************
*** 551,565 ****
  const char *s;
  {
  	int col,row;
  
  	col = (int)ttyDisplay->curx;
  	row = (int)ttyDisplay->cury;
  
  	if (!iflags.grmode) {
! 		txt_xputs(s,col,row);
  #  ifdef SCREEN_VGA
  	} else if (iflags.usevga) {
! 		vga_xputs(s,col,row);
  #  endif
  	}
  }
--- 553,576 ----
  const char *s;
  {
  	int col,row;
+ 	char buf[BUFSZ];
+ 	unsigned i;
  
  	col = (int)ttyDisplay->curx;
  	row = (int)ttyDisplay->cury;
  
+ 	if (iflags.IBMcharset)
+ 		for (i=0; s[i]!=0; i++)
+ 			buf[i] = (s[i] & 0x80)? ibmconvert[s[i]] : s[i];
+ 	else
+ 		for (i=0; s[i]!=0; i++)
+ 			buf[i] = (s[i] & 0x80)? ibm850convert[s[i]] : s[i];
+ 	buf[i] = 0;
  	if (!iflags.grmode) {
! 		txt_xputs(buf,col,row);
  #  ifdef SCREEN_VGA
  	} else if (iflags.usevga) {
! 		vga_xputs(buf,col,row);
  #  endif
  	}
  }
diff -C 3 -r nethack-3.3.1/sys/share/pcsys.c nethack-3.3.1-latin1/sys/share/pcsys.c
*** nethack-3.3.1/sys/share/pcsys.c	Sun Oct  8 21:58:02 2000
--- nethack-3.3.1-latin1/sys/share/pcsys.c	Sun Jan 13 20:44:26 2002
***************
*** 56,61 ****
--- 56,63 ----
  
  #ifdef MICRO
  
+ extern char ibmconvert[], ibm850convert[];
+  
  void
  flushout()
  {
***************
*** 399,405 ****
  	if (iflags.grmode)
  		gr_finish();
  # endif
! 	Vprintf(fmt, VA_ARGS);
  	flushout();
  	VA_END();
  	return;
--- 401,425 ----
  	if (iflags.grmode)
  		gr_finish();
  # endif
! 	{
! 		char buf[BUFSZ];
! # if defined(MSDOS) || defined(WIN32)
! 		unsigned i;
! # endif
! 
! 		Vsprintf(buf, fmt, VA_ARGS);
! # if defined(MSDOS) || defined(WIN32)
! 		if (iflags.IBMcharset)
! 			for (i=0; buf[i]!=0; i++) {
! 				if (buf[i] & 0x80) buf[i]=ibmconvert[buf[i]];
! 			}
! 		else
! 			for (i=0; buf[i]!=0; i++) {
! 				if (buf[i] & 0x80) buf[i]=ibm850convert[buf[i]];
! 			}
! # endif
! 		fputs(buf, stdout);
! 	}
  	flushout();
  	VA_END();
  	return;
diff -C 3 -r nethack-3.3.1/sys/share/unixtty.c nethack-3.3.1-latin1/sys/share/unixtty.c
*** nethack-3.3.1/sys/share/unixtty.c	Sun Oct  8 21:58:02 2000
--- nethack-3.3.1-latin1/sys/share/unixtty.c	Thu Jan 31 20:19:08 2002
***************
*** 386,392 ****
  {
  # ifdef TTY_GRAPHICS
  	if (!strcmp(windowprocs.name, "tty") && linux_flag_console) {
! 		write(1, "\033(B", 3);
  	}
  # endif
  }
--- 386,392 ----
  {
  # ifdef TTY_GRAPHICS
  	if (!strcmp(windowprocs.name, "tty") && linux_flag_console) {
! 		fputs("\033(B", stdout);
  	}
  # endif
  }
***************
*** 396,402 ****
  {
  # ifdef TTY_GRAPHICS
  	if (!strcmp(windowprocs.name, "tty") && linux_flag_console) {
! 		write(1, "\033(U", 3);
  	}
  # endif
  }
--- 396,402 ----
  {
  # ifdef TTY_GRAPHICS
  	if (!strcmp(windowprocs.name, "tty") && linux_flag_console) {
! 		fputs("\033(U", stdout);
  	}
  # endif
  }
diff -C 3 -r nethack-3.3.1/sys/winnt/Makefile.nt nethack-3.3.1-latin1/sys/winnt/Makefile.nt
*** nethack-3.3.1/sys/winnt/Makefile.nt	Sun Oct  8 21:58:02 2000
--- nethack-3.3.1-latin1/sys/winnt/Makefile.nt	Thu Jan 31 19:36:22 2002
***************
*** 183,189 ****
  CFLAGSG	= $(CFLAGSU)
  NHLFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /PDB:"$(GAME).PDB" /RELEASE /NOLOGO
  #LFLAGSG = $(guiflags) $(linkdebug) -IGNORE:505 $(guilibsmt) comctl32.lib
! LFLAGSG	= $(NHLFLAGS) /MACHINE:$(CPU) /MAP:"$(GAME).MAP" $(linkdebug) -IGNORE:505 $(conlibsmt) 
  
  GAMEFILE = $(GAMEDIR)\$(GAME).exe # whole thing
  
--- 183,189 ----
  CFLAGSG	= $(CFLAGSU)
  NHLFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /PDB:"$(GAME).PDB" /RELEASE /NOLOGO
  #LFLAGSG = $(guiflags) $(linkdebug) -IGNORE:505 $(guilibsmt) comctl32.lib
! LFLAGSG	= $(NHLFLAGS) /MACHINE:$(CPU) /MAP:"$(GAME).MAP" $(linkdebug) -IGNORE:505 $(conlibsmt) user32.lib
  
  GAMEFILE = $(GAMEDIR)\$(GAME).exe # whole thing
  
diff -C 3 -r nethack-3.3.1/sys/winnt/nttty.c nethack-3.3.1-latin1/sys/winnt/nttty.c
*** nethack-3.3.1/sys/winnt/nttty.c	Sun Oct  8 21:58:02 2000
--- nethack-3.3.1-latin1/sys/winnt/nttty.c	Sun Jan 13 21:00:22 2002
***************
*** 66,71 ****
--- 66,73 ----
  #define MIDBUTTON   FROM_LEFT_2ND_BUTTON_PRESSED
  #define MOUSEMASK (LEFTBUTTON | RIGHTBUTTON | MIDBUTTON)
  
+ extern unsigned char ibmconvert[], ibm850convert[];
+ 
  /*
   * Called after returning from ! or ^Z
   */
***************
*** 245,250 ****
--- 247,254 ----
  
  #define inmap(x)	(SCANLO <= (x) && (x) < SCANLO + SIZE(scanmap))
  
+ static int pushed_char;
+ 
  int process_keystroke(ir, valid)
  INPUT_RECORD *ir;
  boolean *valid;
***************
*** 253,259 ****
  	unsigned char ch;
  	unsigned short int scan;
  	unsigned long shiftstate;
! 	int altseq;
  	const struct pad *kpad;
  
  	shiftstate = 0L;
--- 257,263 ----
  	unsigned char ch;
  	unsigned short int scan;
  	unsigned long shiftstate;
! 	int altseq, shift, ctrl;
  	const struct pad *kpad;
  
  	shiftstate = 0L;
***************
*** 261,269 ****
--- 265,287 ----
  	scan  = ir->Event.KeyEvent.wVirtualScanCode;
  	shiftstate = ir->Event.KeyEvent.dwControlKeyState;
  	altseq=(shiftstate & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED) && (ch || inmap(scan)));
+ 	ctrl = shiftstate & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED);
+ 	shift = shiftstate & SHIFT_PRESSED;
  	if (ch || (iskeypad(scan)) || altseq)
  			*valid = 1;
  	/* if (!valid) return 0; */
+         /* Two special cases for typing the inverted question and exclamation
+            marks on a non-Spanish keyboard */
+         if (ctrl && shift) {
+             if (scan ==  2) {
+                 *valid = 1;
+                 return 0xA1;        /* Inverted exclamation */
+             }
+             if (scan == 53)  {
+                 *valid = 1;
+                 return 0xBF;        /* Inverted question */
+             }
+         }
      	/*
  	 * shiftstate can be checked to see if various special
           * keys were pressed at the same time as the key.
***************
*** 280,289 ****
           */
          if (iskeypad(scan)) {
              kpad = iflags.num_pad ? numpad : keypad;
!             if (shiftstate & SHIFT_PRESSED) {
                  ch = kpad[scan - KEYPADLO].shift;
              }
!             else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
                  ch = kpad[scan - KEYPADLO].cntrl;
              }
              else {
--- 298,307 ----
           */
          if (iskeypad(scan)) {
              kpad = iflags.num_pad ? numpad : keypad;
!             if (shift) {
                  ch = kpad[scan - KEYPADLO].shift;
              }
!             else if (ctrl) {
                  ch = kpad[scan - KEYPADLO].cntrl;
              }
              else {
***************
*** 296,301 ****
--- 314,340 ----
              if (index(extendedlist, tolower(ch)) != 0) ch = M(tolower(ch));
                  else if (scan == (SCANLO + SIZE(scanmap)) - 1) ch = M('?');
          }
+         else {
+             BYTE keystate[256];
+             WORD chars[2];
+             int count;
+ 
+             memset(keystate, 0, 256);
+             if (shift)
+                 keystate[VK_SHIFT  ] = 0x81;
+             if (ctrl)
+                 keystate[VK_CONTROL] = 0x81;
+             if (shiftstate & CAPSLOCK_ON)
+                 keystate[VK_CAPITAL] = 0x81;
+             count = ToAscii(
+                     ir->Event.KeyEvent.wVirtualKeyCode,
+                     scan,
+                     keystate,
+                     chars,
+                     FALSE);
+             ch = count>0? chars[0] : 0;
+             pushed_char = count>1? chars[1] : 0;
+         }
          return (ch == '\r') ? '\n' : ch;
  }
  
***************
*** 305,310 ****
--- 344,355 ----
  	int count;
  	int valid = 0;
  	int ch;
+ 	if (pushed_char)
+ 	{
+ 	    ch = pushed_char;
+ 	    pushed_char = 0;
+ 	    return ch;
+ 	}
  	valid = 0;
  	while (!valid)
  	{
***************
*** 326,331 ****
--- 371,382 ----
  	int altseq;
  	int done = 0;
  	int valid = 0;
+ 	if (pushed_char)
+ 	{
+ 	    ch = pushed_char;
+ 	    pushed_char = 0;
+ 	    return ch;
+ 	}
  	while (!done)
  	{
  	    count = 0;
***************
*** 502,508 ****
  char c;
  {
  	int count;
- 
  	WriteConsole(hConOut,&c,1,&count,0);
  }
  
--- 553,558 ----
***************
*** 511,518 ****
  const char *s;
  {
  	int count;
! 	
! 	WriteConsole(hConOut,s,strlen(s),&count,0);
  }
  
  void
--- 561,582 ----
  const char *s;
  {
  	int count;
! 	char buf[BUFSZ];
! 	int i;
! 
! 	for (i=0; s[i]!=0 && i<BUFSZ; i++)
! 	{
! 	    if (s[i] & 0x80) {
! 		if (iflags.IBMcharset)
! 		    buf[i] = ibmconvert[s[i] & 0x7F];
! 		else
! 		    buf[i] = ibm850convert[s[i] & 0x7F];
! 	    }
! 	    else {
! 		buf[i] = s[i];
! 	    }
! 	}
! 	WriteConsole(hConOut,buf,i,&count,0);
  }
  
  void
diff -C 3 -r nethack-3.3.1/util/lev_main.c nethack-3.3.1-latin1/util/lev_main.c
*** nethack-3.3.1/util/lev_main.c	Sun Oct  8 21:58:02 2000
--- nethack-3.3.1-latin1/util/lev_main.c	Thu Jan 31 20:22:02 2002
***************
*** 1512,1517 ****
--- 1512,1523 ----
  	lev->nrmonst = 0;
  }
  
+ #ifdef __linux__
+ /* for drawing.c */
+ void linux_mapon() {}
+ void linux_mapoff() {}
+ #endif
+ 
  #ifdef STRICT_REF_DEF
  /*
   * Any globals declared in hack.h and descendents which aren't defined
diff -C 3 -r nethack-3.3.1/win/tty/termcap.c nethack-3.3.1-latin1/win/tty/termcap.c
*** nethack-3.3.1/win/tty/termcap.c	Sun Oct  8 21:58:04 2000
--- nethack-3.3.1-latin1/win/tty/termcap.c	Thu Jan 31 20:34:00 2002
***************
*** 11,16 ****
--- 11,18 ----
  #include "tcap.h"

+ extern void FDECL(putchar2, (int));
+ extern void FDECL(fputs2, (const char *, FILE *));
  #ifdef MICROPORT_286_BUG
  #define Tgetstr(key) (tgetstr(key,tbuf))
  #else
***************
*** 563,569 ****
  char c;
  #endif
  {
! 	(void) putchar(c);
  }
  
  void
--- 565,571 ----
  char c;
  #endif
  {
! 	(void) putchar2(c);
  }
  
  void
***************
*** 571,577 ****
  const char *s;
  {
  # ifndef TERMLIB
! 	(void) fputs(s, stdout);
  # else
  #  if defined(NHSTDC) || defined(ULTRIX_PROTO)
  	tputs(s, 1, (int (*)())xputc);
--- 573,579 ----
  const char *s;
  {
  # ifndef TERMLIB
! 	(void) fputs2(s, stdout);
  # else
  #  if defined(NHSTDC) || defined(ULTRIX_PROTO)
  	tputs(s, 1, (int (*)())xputc);
diff -C 3 -r nethack-3.3.1/win/tty/topl.c nethack-3.3.1-latin1/win/tty/topl.c
*** nethack-3.3.1/win/tty/topl.c	Sun Oct  8 21:58:04 2000
--- nethack-3.3.1-latin1/win/tty/topl.c	Thu Jan 31 20:36:08 2002
***************
*** 18,23 ****
--- 18,24 ----
  STATIC_DCL void FDECL(topl_putsym, (CHAR_P));
  STATIC_DCL void NDECL(remember_topl);
  STATIC_DCL void FDECL(removetopl, (int));
+ extern void FDECL(putchar2, (int));
  
  #ifdef OVLB
  
***************
*** 51,57 ****
  {
  	int otoplin = ttyDisplay->toplin;
  	home();
! 	if(*str & 0x80) {
  		/* kludge for the / command, the only time we ever want a */
  		/* graphics character on the top line */
  		g_putch((int)*str++);
--- 52,64 ----
  {
  	int otoplin = ttyDisplay->toplin;
  	home();
! 	/* LENGUA:  The original version of this function assumed that only the
! 	   symbol displayed by the / command ever has the top bit set, an
! 	   assumption that does not hold in Spanish.  Accented characters and
! 	   the ¡ and ¿ symbols didn't display correctly in the left column.
! 	   Until I can get a better approach, also check the second column for
! 	   a space, and hope that this is enough.  FIXME */
! 	if((str[0] & 0x80)!=0 && str[1]==' ') {
  		/* kludge for the / command, the only time we ever want a */
  		/* graphics character on the top line */
  		g_putch((int)*str++);
***************
*** 212,218 ****
      }
      cw->curx = ttyDisplay->curx;
      if(cw->curx == 0) cl_end();
!     (void) putchar(c);
  }
  
  void
--- 219,225 ----
      }
      cw->curx = ttyDisplay->curx;
      if(cw->curx == 0) cl_end();
!     (void) putchar2(c);
  }
  
  void
diff -C 3 -r nethack-3.3.1/win/tty/wintty.c nethack-3.3.1-latin1/win/tty/wintty.c
*** nethack-3.3.1/win/tty/wintty.c	Sun Oct  8 21:58:04 2000
--- nethack-3.3.1-latin1/win/tty/wintty.c	Thu Jan 31 19:50:04 2002
***************
*** 155,160 ****
--- 155,168 ----
  STATIC_DCL void FDECL(tty_putsym, (winid, int, int, CHAR_P));
  static char *FDECL(copy_of, (const char *));
  STATIC_DCL void FDECL(bail, (const char *));	/* __attribute__((noreturn)) */
+ # if defined(ASCIIGRAPH) && !defined(NO_TERMS) && defined(__linux__) && defined(REINCARNATION)
+ static void FDECL(utf8_put, (int));
+ #endif
+ void FDECL(putchar2, (int));
+ #ifndef MICRO
+ STATIC_DCL void FDECL(puts2, (const char *));
+ #endif
+ void FDECL(fputs2, (const char *, FILE *));
  
  /*
   * A string containing all the default commands -- to add to a list
***************
*** 671,682 ****
  #if defined(MICRO)
  # if defined(MSDOS)
  			if (iflags.grmode) {
! 				(void) putchar(c);
  			} else
  # endif
  			msmsg("%c", c);
  #else
! 			(void) putchar(c);
  #endif
  			plname[ct++] = c;
  		}
--- 679,690 ----
  #if defined(MICRO)
  # if defined(MSDOS)
  			if (iflags.grmode) {
! 				(void) putchar2(c);
  			} else
  # endif
  			msmsg("%c", c);
  #else
! 			(void) putchar2(c);
  #endif
  			plname[ct++] = c;
  		}
***************
*** 993,999 ****
      char ch = item->selected ? (item->count == -1L ? '+' : '#') : '-';
      tty_curs(window, 4, lineno);
      term_start_attr(item->attr);
!     (void) putchar(ch);
      ttyDisplay->curx++;
      term_end_attr(item->attr);
  }
--- 1001,1007 ----
      char ch = item->selected ? (item->count == -1L ? '+' : '#') : '-';
      tty_curs(window, 4, lineno);
      term_start_attr(item->attr);
!     (void) putchar2(ch);
      ttyDisplay->curx++;
      term_end_attr(item->attr);
  }
***************
*** 1182,1188 ****
  			    else
  				(void) putchar('#'); /* count selected */
  			} else
! 			    (void) putchar(*cp);
  		    term_end_attr(curr->attr);
  		}
  	    } else {
--- 1190,1196 ----
  			    else
  				(void) putchar('#'); /* count selected */
  			} else
! 			    (void) putchar2(*cp);
  		    term_end_attr(curr->attr);
  		}
  	    } else {
***************
*** 1409,1415 ****
  	    for (cp = &cw->data[i][1];
  		    *cp && (int) ++ttyDisplay->curx < (int) ttyDisplay->cols;
  		    cp++)
! 		(void) putchar(*cp);
  	    term_end_attr(attr);
  	}
      }
--- 1417,1423 ----
  	    for (cp = &cw->data[i][1];
  		    *cp && (int) ++ttyDisplay->curx < (int) ttyDisplay->cols;
  		    cp++)
! 		(void) putchar2(*cp);
  	    term_end_attr(attr);
  	}
      }
***************
*** 1648,1654 ****
      case NHW_MAP:
      case NHW_BASE:
  	tty_curs(window, x, y);
! 	(void) putchar(ch);
  	ttyDisplay->curx++;
  	cw->curx++;
  	break;
--- 1656,1662 ----
      case NHW_MAP:
      case NHW_BASE:
  	tty_curs(window, x, y);
! 	(void) putchar2(ch);
  	ttyDisplay->curx++;
  	cw->curx++;
  	break;
***************
*** 1749,1755 ****
  	tty_curs(window, cw->curx+1, cw->cury);
  	term_start_attr(attr);
  	while(*str && (int) ttyDisplay->curx < (int) ttyDisplay->cols-1) {
! 	    (void) putchar(*str);
  	    str++;
  	    ttyDisplay->curx++;
  	}
--- 1757,1763 ----
  	tty_curs(window, cw->curx+1, cw->cury);
  	term_start_attr(attr);
  	while(*str && (int) ttyDisplay->curx < (int) ttyDisplay->cols-1) {
! 	    (void) putchar2(*str);
  	    str++;
  	    ttyDisplay->curx++;
  	}
***************
*** 1766,1772 ****
  		cw->cury++;
  		tty_curs(window, cw->curx+1, cw->cury);
  	    }
! 	    (void) putchar(*str);
  	    str++;
  	    ttyDisplay->curx++;
  	}
--- 1774,1780 ----
  		cw->cury++;
  		tty_curs(window, cw->curx+1, cw->cury);
  	    }
! 	    (void) putchar2(*str);
  	    str++;
  	    ttyDisplay->curx++;
  	}
***************
*** 2249,2254 ****
--- 2257,2273 ----
  #endif
  }
  
+ # if defined(ASCIIGRAPH) && !defined(NO_TERMS) && defined(__linux__) && defined(REINCARNATION)
+ /* Print a character using UTF-8 and the direct-to-font space */
+ static void
+ utf8_put(ch)
+ int ch;
+ {
+     printf("\033%%G\357%c%c\033%%@",
+ 	    (char)(0x80 | (ch>>6)), (char)(0x80 | (ch & 0x3F)));
+ }
+ # endif
+ 
  void
  g_putch(in_ch)
  int in_ch;
***************
*** 2258,2264 ****
  # if defined(ASCIIGRAPH) && !defined(NO_TERMS)
      if (iflags.IBMgraphics || iflags.eight_bit_tty) {
  	/* IBM-compatible displays don't need other stuff */
! 	(void) putchar(ch);
      } else if (ch & 0x80) {
  	if (!GFlag || HE_resets_AS) {
  	    graph_on();
--- 2277,2289 ----
  # if defined(ASCIIGRAPH) && !defined(NO_TERMS)
      if (iflags.IBMgraphics || iflags.eight_bit_tty) {
  	/* IBM-compatible displays don't need other stuff */
! 	/* LENGUA: ...except for the diamond character on Linux */
! #  if defined(__linux__) && defined(REINCARNATION)
! 	if (!iflags.IBMcharset && ch==0x04) /* Perhaps support others later */
! 	    utf8_put(ch);
! 	else
! #  endif
! 	    (void) putchar(ch);
      } else if (ch & 0x80) {
  	if (!GFlag || HE_resets_AS) {
  	    graph_on();
***************
*** 2558,2564 ****
  #ifdef MICRO
      msmsg("%s\n", str);
  #else
!     puts(str); (void) fflush(stdout);
  #endif
  }
  
--- 2583,2589 ----
  #ifdef MICRO
      msmsg("%s\n", str);
  #else
!     puts2(str); (void) fflush(stdout);
  #endif
  }
  
***************
*** 2571,2583 ****
  #ifdef MICRO
      msmsg("%s", str);
  #else
!     (void) fputs(str, stdout);
  #endif
      term_end_raw_bold();
  #ifdef MICRO
      msmsg("\n");
  #else
!     puts("");
      (void) fflush(stdout);
  #endif
  }
--- 2596,2608 ----
  #ifdef MICRO
      msmsg("%s", str);
  #else
!     (void) fputs2(str, stdout);
  #endif
      term_end_raw_bold();
  #ifdef MICRO
      msmsg("\n");
  #else
!     puts2("");
      (void) fflush(stdout);
  #endif
  }
***************
*** 2681,2686 ****
--- 2706,2920 ----
  {
      if (!s) s = "";
      return strcpy((char *) alloc((unsigned) (strlen(s) + 1)), s);
+ }
+ 
+ /* The translation tables are public for the benefit of sys/share/pcsys.c and
+    anything else that may need them */
+ /* Translation table from ISO 8859-1 to 7 bit ASCII */
+ const char asciiconvert[] =
+ {
+     /* The control codes are transformed in a manner paralleling ibm850convert */
+     ' ',  ' ',  ' ',  '-',  ' ',  '+',  '+',  '+',
+     ' ',  '+',  '+',  '+',  '|',  '+',  '+',  '+',
+     ' ',  ' ',  ' ',  '-',  ' ',  '+',  '+',  '+',
+     ' ',  '+',  '+',  '+',  '|',  '+',  '+',  '+',
+     /* Transform for the others; where ibmconvert uses an ASCII character, so
+        should asciiconvert */
+     ' ',  '!',  'L',  'c',  '$',  'Y',  '|',  'S',
+     '"',  'C',  'a',  '"',  '-',  '-',  'R',  '-',
+     'o',  '+',  '2',  '3',  '\'', 'u',  'P',  '.',
+     ',',  '1',  'o',  '"',  '4',  '2',  '3',  '?',
+     'A',  'A',  'A',  'A',  'A',  'A',  'A',  'C',
+     'E',  'E',  'E',  'E',  'I',  'I',  'I',  'I',
+     'D',  'N',  'O',  'O',  'O',  'O',  'O',  'x',
+     'O',  'U',  'U',  'U',  'U',  'Y',  'T',  'S',
+     'a',  'a',  'a',  'a',  'a',  'a',  'a',  'c',
+     'e',  'e',  'e',  'e',  'i',  'i',  'i',  'i',
+     'd',  'n',  'o',  'o',  'o',  'o',  'o',  '/',
+     'o',  'u',  'u',  'u',  'u',  'y',  't',  'y',
+ };
+ 
+ /* Translation table from ISO 8859-1 to IBM code page 437 */
+ const char ibmconvert[] =
+ {
+     /* This transform is not reversible:  missing accented letters are mapped
+        to the equivalent unaccented letter */
+ /*                    ..lr        .d.r  .dl.  .dlr        u..r  u.l.  u.lr  ud..  ud.r  udl.  udlr */
+     0xB0, 0xB1, 0xB2, 0xC4, 0xFE, 0xDA, 0xBF, 0xC2, 0x9F, 0xC0, 0xD9, 0xC1, 0xB3, 0xC3, 0xB4, 0xC5,
+     0xDC, 0xDF, 0xDB, 0xCD, 0xF2, 0xC9, 0xBB, 0xCB, 0xD5, 0xC8, 0xBC, 0xCA, 0xBA, 0xCC, 0xB9, 0xCE,
+     0xFF, 0xAD, 0x9B, 0x9C, '$' , 0x9D, '|' , 0x15,
+     '"' , 'C' , 0xA6, 0xAE, 0xAA, '-' , 'R' , '-' ,
+     0xF8, 0xF1, 0xFD, '3' , '\'', 0xE6, 0x14, 0xFA,
+     ',' , '1' , 0xA7, 0xAF, 0xAC, 0xAB, '3' , 0xA8,
+     'A' , 'A' , 'A' , 'A' , 0x8E, 0x8F, 0x92, 0x80,
+     'E' , 0x90, 'E' , 'E' , 'I' , 'I' , 'I' , 'I' ,
+     'D' , 0xA5, 'O' , 'O' , 'O' , 'O' , 0x99, 'x' ,
+     'O' , 'U' , 'U' , 'U' , 0x9A, 'Y' , 'T' , 0xE1,
+     0x85, 0xA0, 0x83, 'a' , 0x84, 0x86, 0x91, 0x87,
+     0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,
+     0xEB, 0xA4, 0x95, 0xA2, 0x93, 'o' , 0x94, 0xF6,
+     0xED, 0x97, 0xA3, 0x96, 0x81, 'y' , 't' , 0x98
+ };
+ 
+ #if defined(MSDOS) || defined(WIN32)
+ /* Translation table from ISO 8859-1 to IBM code page 850 */
+ /* TODO: perhaps this works with WinNT and OS/2 as well? */
+ const char ibm850convert[] =
+ {
+     /* The mappings for codes 80 through 9F are chosen to place the line
+        drawing characters in a logical order.  The other characters are
+        placed to make a reversible transform, and are otherwise arbitrary. */
+ /*                    ..lr        .d.r  .dl.  .dlr        u..r  u.l.  u.lr  ud..  ud.r  udl.  udlr */
+     0xB0, 0xB1, 0xB2, 0xC4, 0xFE, 0xDA, 0xBF, 0xC2, 0x9F, 0xC0, 0xD9, 0xC1, 0xB3, 0xC3, 0xB4, 0xC5,
+     0xDC, 0xDF, 0xDB, 0xCD, 0xF2, 0xC9, 0xBB, 0xCB, 0xD5, 0xC8, 0xBC, 0xCA, 0xBA, 0xCC, 0xB9, 0xCE,
+     /* The mappings for codes A0 through FF convert ISO 8859-1 characters to
+        the equivalent code page 850 characters */
+     0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5,
+     0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,
+     0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA,
+     0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,
+     0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80,
+     0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8,
+     0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E,
+     0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE7, 0xE1,
+     0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87,
+     0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,
+     0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6,
+     0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE8, 0x98
+ };
+ #endif
+ 
+ /*
+  * Put a character, translating to the IBM character set if called for
+  */
+ void
+ putchar2(ch)
+ int ch;
+ {
+     /* For displays with only ASCII */
+     if (!iflags.accents && (ch & 0x80))
+         ch = asciiconvert[ch & 0x7F];
+ #if defined(__linux__)
+     /* For Linux, we can choose a mapping that reflects the desired character
+        set */
+     if (!(ch & 0x80)) {
+ 	putchar(ch);
+     } else if (iflags.IBMcharset) {
+ 	if (!iflags.IBMgraphics) linux_mapoff();
+ 	putchar(ibmconvert[ch & 0x7F]);
+ 	if (!iflags.IBMgraphics) linux_mapon();
+     } else {
+ 	if (iflags.IBMgraphics) linux_mapon();
+ 	putchar(ch);
+ 	if (iflags.IBMgraphics) linux_mapoff();
+     }
+ #elif defined(MSDOS) || defined(WIN32)
+     /* For MSDOS, IBMcharset true means code page 437, and false means 850 */
+     if (!(ch & 0x80)) {
+ 	putchar(ch);
+     } else if (iflags.IBMcharset) {
+ 	putchar(ibmconvert[ch & 0x7F]);
+     } else {
+ 	putchar(ibm850convert[ch & 0x7F]);
+     }
+ #else
+     /* For others, assume for now the choice between code page 437 and
+        ISO-8859-1 */
+     if ((ch & 0x80) && iflags.IBMcharset) {
+ 	putchar(ibmconvert[ch & 0x7F]);
+     } else {
+ 	putchar(ch);
+     }
+ #endif
+ }
+ #ifndef MICRO
+ void
+ puts2(str)
+ const char *str;
+ {
+     char str2[BUFSZ];
+     int i;
+     int ch;
+ 
+ #ifdef __linux__
+     if (iflags.IBMgraphics && !iflags.IBMcharset && str[0]!=0)
+ 	linux_mapon();
+     else if (!iflags.IBMgraphics && iflags.IBMcharset && str[0]!=0)
+ 	linux_mapoff();
+ #endif
+     if (iflags.IBMcharset) {
+ 	for (i=0; str[i]!=0; i++) {
+ 	    ch = str[i];
+ 	    str2[i] = (ch & 0x80)? ibmconvert[ch & 0x7F] : ch;
+ 	}
+ 	str2[i] = 0;
+ 	str = str2;
+     }
+ #if defined(MSDOS) || defined(WIN32)
+     else {
+ 	for (i=0; str[i]!=0; i++) {
+ 	    ch = str[i];
+ 	    str2[i] = (ch & 0x80)? ibm850convert[ch & 0x7F] : ch;
+ 	}
+ 	str2[i] = 0;
+ 	str = str2;
+     }
+ #endif
+     puts(str);
+ #ifdef __linux__
+     if (iflags.IBMgraphics && !iflags.IBMcharset && str[0]!=0)
+ 	linux_mapoff();
+     else if (!iflags.IBMgraphics && iflags.IBMcharset && str[0]!=0)
+ 	linux_mapon();
+ #endif
+ }
+ #endif
+ 
+ void
+ fputs2(str, fp)
+ const char *str;
+ FILE *fp;
+ {
+     char str2[BUFSZ];
+     int i;
+     int ch;
+ 
+     if (fp != stdout) {
+ 	fputs(str, fp);
+ 	return;
+     }
+ 
+ #ifdef __linux__
+     if (iflags.IBMgraphics && !iflags.IBMcharset && str[0]!=0)
+ 	linux_mapon();
+     else if (!iflags.IBMgraphics && iflags.IBMcharset && str[0]!=0)
+ 	linux_mapoff();
+ #endif
+     if (iflags.IBMcharset) {
+ 	for (i=0; str[i]!=0; i++) {
+ 	    ch = str[i];
+ 	    str2[i] = (ch & 0x80)? ibmconvert[ch & 0x7F] : ch;
+ 	}
+ 	str2[i] = 0;
+ 	str = str2;
+     }
+ #if defined(MSDOS) || defined(WIN32)
+     else {
+ 	for (i=0; str[i]!=0; i++) {
+ 	    ch = str[i];
+ 	    str2[i] = (ch & 0x80)? ibm850convert[ch & 0x7F] : ch;
+ 	}
+ 	str2[i] = 0;
+ 	str = str2;
+     }
+ #endif
+     puts(str);
+ #ifdef __linux__
+     if (iflags.IBMgraphics && !iflags.IBMcharset && str[0]!=0)
+ 	linux_mapoff();
+     else if (!iflags.IBMgraphics && iflags.IBMcharset && str[0]!=0)
+ 	linux_mapon();
+ #endif
  }
  
  #endif /* TTY_GRAPHICS */
--CUT HERE--CUT HERE--CUT HERE--CUT HERE--CUT HERE--CUT HERE--CUT HERE--

-- 
 --------------===============<[ Ray Chason ]>===============--------------
         PGP public key at http://www.smart.net/~rchason/pubkey.asc
                            Delenda est Windoze