Logo Search packages:      
Sourcecode: hanterm-classic version File versions  Download package

charproc.c

/*
 * $XConsortium: charproc.c,v 1.173 91/07/22 11:32:49 gildea Exp $
 */

/*
 * Copyright 1988 Massachusetts Institute of Technology
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 *
 *                         All Rights Reserved
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of Digital Equipment
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior permission.
 *
 *
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
/* charproc.c */

/* XXX fuzzy baseline stuff */
int englift;
int eng_ascent;
int eng_descent;

#include "ptyx.h"
#include "VTparse.h"
#include "data.h"
#include "error.h"
#include "menu.h"
#include "main.h"
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/Atoms.h>
#include <X11/Xmu/CharSet.h>
#include <X11/Xmu/Converters.h>
#include <stdio.h>
#include <errno.h>
#include <setjmp.h>
#include <ctype.h>
#include <X11/keysym.h>
#include "hangul.h"
#include "hstrdefs.h"

#ifndef XtRGravity
#include "newConverters.h"
#endif /* XtRGravity */

/*
 * Check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
 * systems are broken and return EWOULDBLOCK when they should return EAGAIN.
 * Note that this macro may evaluate its argument more than once.
 */
#if defined(EAGAIN) && defined(EWOULDBLOCK)
#define E_TEST(err) ((err) == EAGAIN || (err) == EWOULDBLOCK)
#else
#ifdef EAGAIN
#define E_TEST(err) ((err) == EAGAIN)
#else
#define E_TEST(err) ((err) == EWOULDBLOCK)
#endif
#endif

#if !defined(NO_PATCH_FONT_JOHABNZ) /* by hanmaum 1998.2.2 */
extern int font_no_zero_width_char;
extern int font_minus_width_char_byte1;
extern int font_minus_width_char_byte2;
#endif

extern Widget toplevel;
extern void exit();
extern char *malloc();
extern char *realloc();

extern void FlushScroll();
extern void InsertLine();
extern void DeleteLine();
extern void InsertChar();
extern void DeleteChar();
extern void ClearAbove();
extern void ClearBelow();
extern void ClearRight();
extern void ClearLeft();
extern void ClearLine();
extern void ClearScreen();
extern void ReverseVideo();
extern void recolor_cursor();
extern void ResizeScrollBar();
extern void WindowScroll();
extern void ScrollBarOn();
extern void ScrollBarOff();
extern void ScreenWrite();
extern void TrackText();
extern void xevents();
extern void Bell();
extern void VisualBell();
extern void Redraw();

#ifdef ALLOWLOGFILEONOFF
extern void StartLog();
extern void CloseLog();
#endif

extern int (*converter)();
extern int convert_3_to_ks();
extern int convert_3_to_johab();
extern int convert_3_to_jo844();

#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
extern int convert_3_to_utf8();
#endif

#if !defined(NO_PATCH_LINE_DRAW)
void set_vt_graphics (/*TScreen *screen*/);
#endif

static void VTallocbuf();
static int finput();
static void dotext();
static void WriteText();
static void ToAlternate();
static void FromAlternate();
static void update_font_info();

static void bitset(), bitclr();
    
#define     DEFAULT           -1
#define TRACKTIMESEC    4L
#define TRACKTIMEUSEC   0L
#define BELLSUPPRESSMSEC 200

#define     XtNkeepBaseLine "keepBaseLine"
#define XtNalwaysHighlight "alwaysHighlight"
#define XtNappcursorDefault "appcursorDefault"
#define XtNappkeypadDefault "appkeypadDefault"
#define XtNbellSuppressTime "bellSuppressTime"
#define XtNboldFont "boldFont"
#define XtNc132 "c132"
#define XtNcharClass "charClass"
#define XtNcurses "curses"
#define XtNhpLowerleftBugCompat "hpLowerleftBugCompat"
#define XtNcursorColor "cursorColor"
#define XtNcolor0 "color0"
#define XtNcolor1 "color1"
#define XtNcolor2 "color2"
#define XtNcolor3 "color3"
#define XtNcolor4 "color4"
#define XtNcolor5 "color5"
#define XtNcolor6 "color6"
#define XtNcolor7 "color7"
/* inserted by ysyun@bulsai, 1999/03/19 */
#define XtNcolor8 "color8"
#define XtNcolor9 "color9"
#define XtNcolor10 "color10"
#define XtNcolor11 "color11"
#define XtNcolor12 "color12"
#define XtNcolor13 "color13"
#define XtNcolor14 "color14"
#define XtNcolor15 "color15"
/* end of insertion */

#define XtNcutNewline "cutNewline"
#define XtNcutToBeginningOfLine "cutToBeginningOfLine"
#define XtNeightBitInput "eightBitInput"
#define XtNeightBitOutput "eightBitOutput"
#define XtNgeometry "geometry"
#define XtNinternalBorder "internalBorder"
#define XtNjumpScroll "jumpScroll"
#ifdef ALLOWLOGFILEONOFF
#define XtNlogFile "logFile"
#define XtNlogging "logging"
#define XtNlogInhibit "logInhibit"
#endif
#define XtNloginShell "loginShell"
#define XtNmarginBell "marginBell"
#define XtNpointerColor "pointerColor"
#define XtNpointerColorBackground "pointerColorBackground"
#define XtNpointerShape "pointerShape"
#define XtNmultiClickTime "multiClickTime"
#define XtNmultiScroll "multiScroll"
#define XtNnMarginBell "nMarginBell"
#define XtNresizeGravity "resizeGravity"
#define XtNreverseWrap "reverseWrap"
#define XtNautoWrap "autoWrap"
#define XtNsaveLines "saveLines"
#define XtNscrollBar "scrollBar"
#define XtNscrollTtyOutput "scrollTtyOutput"
#define XtNscrollKey "scrollKey"
#define XtNscrollLines "scrollLines"
#define XtNscrollPos "scrollPos"
#define XtNsignalInhibit "signalInhibit"
#define XtNtiteInhibit "titeInhibit"
#define XtNunderLine "underLine"
#define XtNvisualBell "visualBell"
#define XtNallowSendEvents "allowSendEvents"

/* inserted by ysyun@bulsai, at 1999/03/18 */
#define     XtNksFont   "ksFont"
#define     XtNkstFont  "kstFont"
/* modified by cdpark@jupiter, at 1999/06/15 */
#define XtNcolorBD            "colorBD"
#define XtNcolorBDMode        "colorBDMode"
#define XtNcolorMode          "colorMode"
#define XtNcolorUL            "colorUL"
#define XtNcolorULMode        "colorULMode"
#define XtNunderLine          "underLine"
/* end of insertion */

#define XtCKeepBaseLine    "KeepBaseLine"
#define XtCAlwaysHighlight "AlwaysHighlight"
#define XtCAppcursorDefault "AppcursorDefault"
#define XtCAppkeypadDefault "AppkeypadDefault"
#define XtCBellSuppressTime "BellSuppressTime"
#define XtCBoldFont "BoldFont"
#define XtCC132 "C132"
#define XtCCharClass "CharClass"
#define XtCCurses "Curses"
#define XtCHpLowerleftBugCompat "HpLowerleftBugCompat"
#define XtCCutNewline "CutNewline"
#define XtCCutToBeginningOfLine "CutToBeginningOfLine"
#define XtCEightBitInput "EightBitInput"
#define XtCEightBitOutput "EightBitOutput"
#define XtCGeometry "Geometry"
#define XtCJumpScroll "JumpScroll"

#ifdef ALLOWLOGFILEONOFF
#define XtCLogfile "Logfile"
#define XtCLogging "Logging"
#define XtCLogInhibit "LogInhibit"
#endif

#define XtCLoginShell "LoginShell"
#define XtCMarginBell "MarginBell"
#define XtCMultiClickTime "MultiClickTime"
#define XtCMultiScroll "MultiScroll"
#define XtCColumn "Column"
#define XtCResizeGravity "ResizeGravity"
#define XtCReverseWrap "ReverseWrap"
#define XtCAutoWrap "AutoWrap"
#define XtCSaveLines "SaveLines"
#define XtCScrollBar "ScrollBar"
#define XtCScrollLines "ScrollLines"
#define XtCScrollPos "ScrollPos"
#define XtCScrollCond "ScrollCond"
#define XtCSignalInhibit "SignalInhibit"
#define XtCTiteInhibit "TiteInhibit"
#define XtCUnderLine "UnderLine"
#define XtCVisualBell "VisualBell"
#define XtCAllowSendEvents "AllowSendEvents"

/* inserted by ysyun@bulsai, at 1999/03/18 */
#define     XtCKsFont   "KsFont"
#define     XtCKstFont  "KstFont"
/* modified by cdpark@jupiter, at 1999/06/15 */
#define XtCUnderLine    "UnderLine"
#define XtCColorMode    "ColorMode"
/* end of insertion */

/* variable status line */
#define XtNhideCode       "noStatusCode"
#define XtNhideHanKbd     "noStatusKbd"
#define XtCHideCode       "NoStatusCode"
#define XtCHideHanKbd     "NoStatusKbd"

#define     doinput()         (bcnt-- > 0 ? *bptr++ : in_put())

static int nparam;
static ANSI reply;
static int param[NPARAM];

static unsigned long ctotal;
static unsigned long ntotal;
static jmp_buf vtjmpbuf;

extern int groundtable[];
extern int csitable[];
extern int dectable[];
extern int eigtable[];
extern int esctable[];
extern int iestable[];
extern int igntable[];
extern int scrtable[];
extern int scstable[];


/* event handlers */
extern void HandleKeyPressed(), HandleEightBitKeyPressed();
extern void HandleStringEvent();
extern void HandleEnterWindow();
extern void HandleLeaveWindow();
extern void HandleBellPropertyChange();
extern void HandleFocusChange();
static void HandleKeymapChange();
extern void HandleInsertSelection();
extern void HandleSelectStart(), HandleKeyboardSelectStart();
extern void HandleSelectExtend(), HandleSelectSet();
extern void HandleSelectEnd(), HandleKeyboardSelectEnd();
extern void HandleStartExtend(), HandleKeyboardStartExtend();
static void HandleBell();
static void HandleVisualBell();
static void HandleIgnore();
extern void HandleSecure();
extern void HandleScrollForward();
extern void HandleScrollBack();
extern void HandleCreateMenu(), HandlePopupMenu();
extern void HandleSetFont();
extern void HandleToggleHangul();
extern void HandleToggleChat();
extern void HandleChangeCode();
extern void HandleCodeInput();
extern void HandleHanjaInput();
extern void SetVTFont();

extern Boolean SendMousePosition();
extern void ScrnSetAttributes();

/*
 * NOTE: VTInitialize zeros out the entire ".screen" component of the 
 * XtermWidget, so make sure to add an assignment statement in VTInitialize() 
 * for each new ".screen" field added to this resource list.
 */

/* Defaults */
static  Boolean   defaultFALSE         = FALSE;
static  Boolean   defaultTRUE    = TRUE;
static  int defaultBorderWidth = DEFBORDERWIDTH;
static  int defaultIntBorder   = DEFBORDER;
static  int defaultSaveLines   = SAVELINES;
static      int   defaultScrollLines = SCROLLLINES;
static  int defaultNMarginBell = N_MARGINBELL;
static  int defaultMultiClickTime = MULTICLICKTIME;
static  int defaultBellSuppressTime = BELLSUPPRESSMSEC;
static      char *      _Font_Selected_ = "yes";  /* string is arbitrary */
static  int     defaultCode = C_WANSUNG;
/*
static  int     defaultKeyboard = 2;
*/
static  char    defaultKeyboardStr[] = HKB_2_STR;

/*
 * Warning, the following must be kept under 1024 bytes or else some 
 * compilers (particularly AT&T 6386 SVR3.2) will barf).  Workaround is to
 * declare a static buffer and copy in at run time (the the Athena text widget
 * does).  Yuck.
 */
#define TRANSTBL_SIZE 2048

static char defaultTranslations[TRANSTBL_SIZE] =
"\
 Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\
  Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\
Shift <KeyPress> Select:select-cursor-start() select-cursor-end(PRIMARY, CUT_BUFFER0) \n\
Shift <KeyPress> Insert:insert-selection(PRIMARY, CUT_BUFFER0) \n\
       !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
  !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
       ~Meta <Btn1Down>:select-start() \n\
     ~Meta <Btn1Motion>:select-extend() \n\
       !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
  !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
 ~Ctrl ~Meta <Btn2Down>:ignore() \n\
   ~Ctrl ~Meta <Btn2Up>:insert-selection(PRIMARY, CUT_BUFFER0) \n\
       !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
  !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
 ~Ctrl ~Meta <Btn3Down>:start-extend() \n\
     ~Meta <Btn3Motion>:select-extend()   \n\
                <BtnUp>:select-end(PRIMARY, CUT_BUFFER0) \n\
            <BtnDown>:bell(0) \n\
";
static char translations2[] =
"\
 Shift <KeyPress> space:toggle-hangul()\n\
 <KeyPress> F2:change-code()\n\
 <KeyPress> F3:toggle-chat()\n\
 <KeyPress> F9:hanja-input()\n\
 <KeyPress> F7:code-input()\n\
 ~Meta <KeyPress>:insert-seven-bit() \n\
 Meta <KeyPress>:insert-eight-bit() \n\
";

static XtActionsRec actionsList[] = { 
    { "bell",             HandleBell },
    { "create-menu",      HandleCreateMenu },
    { "ignore",           HandleIgnore },
    { "insert",           HandleKeyPressed },  /* alias for insert-seven-bit */
    { "insert-seven-bit", HandleKeyPressed },
    { "insert-eight-bit", HandleEightBitKeyPressed },
    { "insert-selection", HandleInsertSelection },
    { "keymap",     HandleKeymapChange },
    { "popup-menu",       HandlePopupMenu },
    { "secure",           HandleSecure },
    { "select-start",     HandleSelectStart },
    { "select-extend",    HandleSelectExtend },
    { "select-end",       HandleSelectEnd },
    { "select-set",       HandleSelectSet },
    { "select-cursor-start",    HandleKeyboardSelectStart },
    { "select-cursor-end",      HandleKeyboardSelectEnd },
    { "set-vt-font",      HandleSetFont },
    { "start-extend",     HandleStartExtend },
    { "start-cursor-extend",    HandleKeyboardStartExtend },
    { "string",           HandleStringEvent },
    { "scroll-forw",      HandleScrollForward },
    { "scroll-back",      HandleScrollBack },
    { "toggle-hangul",    HandleToggleHangul },
    { "toggle-chat",      HandleToggleChat },
    { "change-code",      HandleChangeCode },
    { "code-input",       HandleCodeInput },
    { "hanja-input",       HandleHanjaInput },
/* menu actions */
    { "allow-send-events",    HandleAllowSends },
    { "set-visual-bell",      HandleSetVisualBell },
#ifdef ALLOWLOGFILEONOFF
    { "set-logging",          HandleLogging },
#endif
    { "redraw",               HandleRedraw },
    { "send-signal",          HandleSendSignal },
    { "quit",                 HandleQuit },
    { "set-scrollbar",        HandleScrollbar },
    { "set-jumpscroll",       HandleJumpscroll },
    { "set-reverse-video",    HandleReverseVideo },
    { "set-autowrap",         HandleAutoWrap },
    { "set-reversewrap",      HandleReverseWrap },
    { "set-autolinefeed",     HandleAutoLineFeed },
    { "set-appcursor",        HandleAppCursor },
    { "set-appkeypad",        HandleAppKeypad },
    { "set-scroll-on-key",    HandleScrollKey },
    { "set-scroll-on-tty-output",   HandleScrollTtyOutput },
    { "set-allow132",         HandleAllow132 },
    { "set-cursesemul",       HandleCursesEmul },
    { "set-marginbell",       HandleMarginBell },
    { "soft-reset",           HandleSoftReset },
    { "hard-reset",           HandleHardReset },
    { "clear-saved-lines",    HandleClearSavedLines },
    { "visual-bell",          HandleVisualBell },
};


static XtResource resources[] = {
{XtNhangulCode, XtCHangulCode, XtRInt, sizeof(int),
      XtOffsetOf(XtermWidgetRec, screen.code), XtRInt,
      (XtPointer) &defaultCode},
{XtNhangulKeyboard, XtCHangulKeyboard, XtRString, sizeof(char *),
      XtOffsetOf(XtermWidgetRec, screen.keyboardStrPtr), XtRString,
      defaultKeyboardStr},
{XtNhideCode, XtCHideCode, XtRBoolean, sizeof(Boolean),
        XtOffsetOf(XtermWidgetRec, screen.showStatus.hideCode),
        XtRBoolean, (XtPointer) &defaultFALSE},
{XtNhideHanKbd, XtCHideHanKbd, XtRBoolean, sizeof(Boolean),
        XtOffsetOf(XtermWidgetRec, screen.showStatus.hideHanLayout),
        XtRBoolean, (XtPointer) &defaultFALSE},
{XtNuseDvorakLayout, XtCUseDvorakLayout, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.use_dvorak_layout), 
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNfont, XtCFont, XtRString, sizeof(char *),
      XtOffsetOf(XtermWidgetRec, misc.f_n), XtRString,
      DEFFONT},
{XtNhangulFont, XtCHangulFont, XtRString, sizeof(char *),
      XtOffsetOf(XtermWidgetRec, misc.f_h), XtRString,
      DEFHFONT},
{XtNboldFont, XtCBoldFont, XtRString, sizeof(char *),
      XtOffsetOf(XtermWidgetRec, misc.f_b), XtRString,
      DEFBOLDFONT},
{XtNc132, XtCC132, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.c132),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNcharClass, XtCCharClass, XtRString, sizeof(char *),
      XtOffsetOf(XtermWidgetRec, screen.charClass),
      XtRString, (XtPointer) NULL},
{XtNcurses, XtCCurses, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.curses),
      XtRBoolean, (XtPointer) &defaultFALSE},

/* inserted by ysyun@bulsa.kaist.ac.kr, at 1999/03/18 */
{XtNksFont, XtCKsFont, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.f_ks),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNkstFont, XtCKstFont, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.f_kst),
      XtRBoolean, (XtPointer) &defaultFALSE},
/* end of insertion */

{XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, XtRBoolean, sizeof(Boolean),
        XtOffsetOf(XtermWidgetRec, screen.hp_ll_bc),
        XtRBoolean, (XtPointer) &defaultFALSE},
{XtNcutNewline, XtCCutNewline, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.cutNewline),
      XtRBoolean, (XtPointer) &defaultTRUE},
{XtNcutToBeginningOfLine, XtCCutToBeginningOfLine, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.cutToBeginningOfLine),
      XtRBoolean, (XtPointer) &defaultTRUE},
{XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, core.background_pixel),
      XtRString, "XtDefaultBackground"},
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.foreground),
      XtRString, "XtDefaultForeground"},
{XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.cursorcolor),
      XtRString, "XtDefaultForeground"},

{XtNcolor0, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_0]),
      XtRString, "XtDefaultForeground"},
{XtNcolor1, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_1]),
      XtRString, "XtDefaultForeground"},
{XtNcolor2, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_2]),
      XtRString, "XtDefaultForeground"},
{XtNcolor3, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_3]),
      XtRString, "XtDefaultForeground"},
{XtNcolor4, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_4]),
      XtRString, "XtDefaultForeground"},
{XtNcolor5, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_5]),
      XtRString, "XtDefaultForeground"},
{XtNcolor6, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_6]),
      XtRString, "XtDefaultForeground"},
{XtNcolor7, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_7]),
      XtRString, "XtDefaultForeground"},

/* inserted by ysyun@bulsai, 1999/03/19 */
{XtNcolor8, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_8]),
      XtRString, "XtDefaultForeground"},
{XtNcolor9, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_9]),
      XtRString, "XtDefaultForeground"},
{XtNcolor10, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_10]),
      XtRString, "XtDefaultForeground"},
{XtNcolor11, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_11]),
      XtRString, "XtDefaultForeground"},
{XtNcolor12, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_12]),
      XtRString, "XtDefaultForeground"},
{XtNcolor13, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_13]),
      XtRString, "XtDefaultForeground"},
{XtNcolor14, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_14]),
      XtRString, "XtDefaultForeground"},
{XtNcolor15, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_15]),
      XtRString, "XtDefaultForeground"},
/* modefied by cdpark@jupiter, 1999/06/15 */
{XtNcolorBD, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_BD]),
      XtRString, "XtDefaultForeground"},
{XtNcolorUL, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.colors[COLOR_UL]),
      XtRString, "XtDefaultForeground"},
/* end of insertion */

/* insert by ysyun@bulsai, 1999/03/20 */
/* modefied by cdpark@jupiter, 1999/06/15 */
{XtNcolorBDMode, XtCColorMode, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.colorBDMode),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNcolorULMode, XtCColorMode, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.colorULMode),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNunderLine, XtCUnderLine, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.underline),
      XtRBoolean, (XtPointer) &defaultTRUE},
/* end of patch */

{XtNeightBitInput, XtCEightBitInput, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.input_eight_bits), 
      XtRBoolean, (XtPointer) &defaultTRUE},
{XtNeightBitOutput, XtCEightBitOutput, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.output_eight_bits), 
      XtRBoolean, (XtPointer) &defaultTRUE},
{XtNgeometry,XtCGeometry, XtRString, sizeof(char *),
      XtOffsetOf(XtermWidgetRec, misc.geo_metry),
      XtRString, (XtPointer) NULL},
{XtNalwaysHighlight,XtCAlwaysHighlight,XtRBoolean,
        sizeof(Boolean),XtOffsetOf(XtermWidgetRec, screen.always_highlight),
        XtRBoolean, (XtPointer) &defaultFALSE},
{XtNappcursorDefault,XtCAppcursorDefault,XtRBoolean,
        sizeof(Boolean),XtOffsetOf(XtermWidgetRec, misc.appcursorDefault),
        XtRBoolean, (XtPointer) &defaultFALSE},
{XtNappkeypadDefault,XtCAppkeypadDefault,XtRBoolean,
        sizeof(Boolean),XtOffsetOf(XtermWidgetRec, misc.appkeypadDefault),
        XtRBoolean, (XtPointer) &defaultFALSE},
{XtNbellSuppressTime, XtCBellSuppressTime, XtRInt, sizeof(int),
        XtOffsetOf(XtermWidgetRec, screen.bellSuppressTime),
        XtRInt, (XtPointer) &defaultBellSuppressTime},
{XtNinternalBorder,XtCBorderWidth,XtRInt, sizeof(int),
      XtOffsetOf(XtermWidgetRec, screen.border),
      XtRInt, (XtPointer) &defaultIntBorder},
{XtNjumpScroll, XtCJumpScroll, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.jumpscroll),
      XtRBoolean, (XtPointer) &defaultTRUE},
#ifdef ALLOWLOGFILEONOFF
{XtNlogFile, XtCLogfile, XtRString, sizeof(char *),
      XtOffsetOf(XtermWidgetRec, screen.logfile),
      XtRString, (XtPointer) NULL},
{XtNlogging, XtCLogging, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.log_on),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNlogInhibit, XtCLogInhibit, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.logInhibit),
      XtRBoolean, (XtPointer) &defaultFALSE},
#endif
{XtNloginShell, XtCLoginShell, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.login_shell),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNmarginBell, XtCMarginBell, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.marginbell),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNpointerColor, XtCForeground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.mousecolor),
      XtRString, "XtDefaultForeground"},
{XtNpointerColorBackground, XtCBackground, XtRPixel, sizeof(Pixel),
      XtOffsetOf(XtermWidgetRec, screen.mousecolorback),
      XtRString, "XtDefaultBackground"},
{XtNpointerShape,XtCCursor, XtRCursor, sizeof(Cursor),
      XtOffsetOf(XtermWidgetRec, screen.pointer_cursor),
      XtRString, (XtPointer) "xterm"},
{XtNmultiClickTime,XtCMultiClickTime, XtRInt, sizeof(int),
      XtOffsetOf(XtermWidgetRec, screen.multiClickTime),
      XtRInt, (XtPointer) &defaultMultiClickTime},
{XtNmultiScroll,XtCMultiScroll, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.multiscroll),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNnMarginBell,XtCColumn, XtRInt, sizeof(int),
      XtOffsetOf(XtermWidgetRec, screen.nmarginbell),
      XtRInt, (XtPointer) &defaultNMarginBell},
{XtNreverseVideo,XtCReverseVideo,XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.re_verse),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity),
      XtOffsetOf(XtermWidgetRec, misc.resizeGravity),
      XtRImmediate, (XtPointer) SouthWestGravity},
{XtNreverseWrap,XtCReverseWrap, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.reverseWrap),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNautoWrap,XtCAutoWrap, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.autoWrap),
      XtRBoolean, (XtPointer) &defaultTRUE},
{XtNsaveLines, XtCSaveLines, XtRInt, sizeof(int),
      XtOffsetOf(XtermWidgetRec, screen.savelines),
      XtRInt, (XtPointer) &defaultSaveLines},
{XtNscrollBar, XtCScrollBar, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.scrollbar),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNscrollTtyOutput,XtCScrollCond, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.scrollttyoutput),
      XtRBoolean, (XtPointer) &defaultTRUE},
{XtNscrollKey, XtCScrollCond, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.scrollkey),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNscrollLines, XtCScrollLines, XtRInt, sizeof(int),
      XtOffsetOf(XtermWidgetRec, screen.scrolllines),
      XtRInt, (XtPointer) &defaultScrollLines},
{XtNsignalInhibit,XtCSignalInhibit,XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.signalInhibit),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNtiteInhibit, XtCTiteInhibit, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, misc.titeInhibit),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNunderLine, XtCUnderLine, XtRBoolean, sizeof(Boolean),
        XtOffsetOf(XtermWidgetRec, screen.underline),
        XtRBoolean, (XtPointer) &defaultFALSE},

{XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.visualbell),
      XtRBoolean, (XtPointer) &defaultFALSE},
{XtNallowSendEvents, XtCAllowSendEvents, XtRBoolean, sizeof(Boolean),
      XtOffsetOf(XtermWidgetRec, screen.allowSendEvents),
      XtRBoolean, (XtPointer) &defaultFALSE},
{"font1", "Font1", XtRString, sizeof(String),
      XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font1]),
      XtRString, (XtPointer) NULL},
{"font2", "Font2", XtRString, sizeof(String),
      XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font2]),
      XtRString, (XtPointer) NULL},
{"font3", "Font3", XtRString, sizeof(String),
      XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font3]),
      XtRString, (XtPointer) NULL},
{"font4", "Font4", XtRString, sizeof(String),
      XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font4]),
      XtRString, (XtPointer) NULL},
{"font5", "Font5", XtRString, sizeof(String),
      XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font5]),
      XtRString, (XtPointer) NULL},
{"font6", "Font6", XtRString, sizeof(String),
      XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font6]),
      XtRString, (XtPointer) NULL},
{XtNkeepBaseLine, XtCKeepBaseLine, XtRBoolean, sizeof(Boolean),
        XtOffsetOf(XtermWidgetRec, misc.keepBaseline),
        XtRBoolean, (XtPointer) &defaultTRUE},
};

static void VTClassInit();
static void VTInitialize();
static void VTRealize();
static void VTExpose();
static void VTResize();
static void VTDestroy();
static Boolean VTSetValues();

static WidgetClassRec xtermClassRec = {
  {
/* core_class fields */ 
    /* superclass   */  (WidgetClass) &widgetClassRec,
    /* class_name   */  "VT100",
    /* widget_size        */  sizeof(XtermWidgetRec),
    /* class_initialize   */    VTClassInit,
    /* class_part_initialize */ NULL,
    /* class_inited       */  FALSE,
    /* initialize   */  VTInitialize,
    /* initialize_hook    */    NULL,                       
    /* realize            */  VTRealize,
    /* actions            */  actionsList,
    /* num_actions        */  XtNumber(actionsList),
    /* resources    */  resources,
    /* num_resources      */  XtNumber(resources),
    /* xrm_class    */  NULLQUARK,
    /* compress_motion    */  TRUE,
    /* compress_exposure  */  FALSE,
    /* compress_enterleave */   TRUE,
    /* visible_interest   */  FALSE,
    /* destroy            */  VTDestroy,
    /* resize             */  VTResize,
    /* expose             */  VTExpose,
    /* set_values   */  VTSetValues,
    /* set_values_hook    */    NULL,
    /* set_values_almost  */    NULL,
    /* get_values_hook    */    NULL,
    /* accept_focus       */  NULL,
    /* version            */    XtVersion,
    /* callback_offsets   */    NULL,
    /* tm_table           */    defaultTranslations,
    /* query_geometry     */    XtInheritQueryGeometry,
    /* display_accelerator*/    XtInheritDisplayAccelerator,
    /* extension          */    NULL
  }
};

WidgetClass xtermWidgetClass = (WidgetClass)&xtermClassRec;

static unsigned char last_hangul;
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
static int last_col = -1;
#endif

void ShowCursor();
void HideCursor();
void VTReset();
extern void Index();
extern void RevIndex();
extern void TrackMouse();

static int NumBit(color)
  Pixel color;
{
  int bc = 0;
  for( ; color != 0 ; color>>=1 ) {
    if( color&1 )
      bc ++;
  }
  return bc;
}

static void BoldColor()
{
  register TScreen *screen = &term->screen;

  if( !(term->flags & INVERSE) ) {
    term->flags |= FG_COLOR;
    term->cur_foreground = COLOR_BD;
  }
  else {
    term->flags |= BG_COLOR;
    term->cur_background = COLOR_BD;
  }
}

static void UnderlineColor()
{
  register TScreen *screen = &term->screen;

  if( !(term->flags & INVERSE) ) {
    term->flags |= FG_COLOR;
    term->cur_foreground = COLOR_UL;
  }
  else {
    term->flags |= BG_COLOR;
    term->cur_background = COLOR_UL;
  }
}

static void VTparse()
{
      register TScreen *screen = &term->screen;
      register int *parsestate = groundtable;
      register unsigned int c;
      register unsigned char *cp;
      register int row, col, top, bot, scstype;
      int print;
      int charset_sg = 0;
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      unsigned char push_ch1;
      unsigned char push_ch2;
      unsigned char push_ch3;
      int push_col1 = -1;
      int push_col2 = -1;
      int push_col3 = -1;
      int start_col;
#endif
        extern Bool BrightColor;        /* by ysyun@bulsai */

      if(setjmp(vtjmpbuf))
            parsestate = groundtable;
      for( ; ; ) {
          print = 0;
              switch (parsestate[c = doinput()]) {
             case CASE_PRINT:
                  /* printable characters */
                  top = bcnt > TEXT_BUF_SIZE ? TEXT_BUF_SIZE : bcnt;
                  cp = bptr;
                  *--bptr = c;

#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
    start_col = (unsigned)screen->cur_row<<8 | (unsigned)screen->cur_col;

    charset_sg = screen->curss ? (screen->gsets[screen->curss] == '0')
                         : (screen->gsets[screen->curgl] == '0');

    /* 예전에 입력되어 보존된 글자와 연결 */
    if (!charset_sg && (screen->code == C_WANSUNG || screen->code == C_JOHAB)) {
      Char *col = screen->buf[4*screen->cur_row] + screen->cur_col;
      Char *attrs = screen->buf[4*screen->cur_row+1] + screen->cur_col;

      if (push_col3 != -1) {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
          printf("pushed col3 = <%04x>, ch = %02x : term flags = %x\n", 
            push_col3, (unsigned char )push_ch3, term->flags&INSERT);
#endif
          if ((isprint(*bptr)||(*bptr & 0x80)) && (start_col == push_col3+1)
/*
            && (!(*attrs & FIRST_HAN) || (*(attrs-1) & FIRST_HAN))
            && (*(col-1) & 0x80)) 
*/
          )
          {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
            printf("push3 is applyed!\n");
#endif
            CursorBack(screen, 1);
            *--bptr = push_ch3;
            push_col3 = -1;
          }
      }
      if (push_col2 != -1) {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
          printf("pushed col2 = <%04x>, ch = %02x : term flags = %x\n", 
            push_col2, (unsigned char )push_ch2, term->flags&INSERT);
#endif
          if ((isprint(*bptr)||(*bptr & 0x80)) && (start_col == push_col2+1)
            )
          {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
            printf("push2 is applyed!\n");
#endif
            CursorBack(screen, 1);
            *--bptr = push_ch2;
            push_col2 = push_col3;
            push_ch2 = push_ch3;
            push_col3 = -1;
          }
      }
      if (push_col1 != -1) {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
          printf("pushed col1 = <%04x>, ch = %02x : term flags = %x\n", 
            push_col1, (unsigned char )push_ch1, term->flags&INSERT);
#endif
          if ((isprint(*bptr)||(*bptr & 0x80)) && (start_col == push_col1+1)
            )
          {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
            printf("push1 is applyed!\n");
#endif
            CursorBack(screen, 1);
            *--bptr = push_ch1;
            push_col1 = push_col2;
            push_ch1 = push_ch2;
            push_col2 = push_col3;
            push_ch2 = push_ch3;
            push_col3 = -1;
          }
      }
    }
#endif

    /* 처리하지 않고 남겨둔 글자를 회복 */
    if (!charset_sg)
    { 
      if (last_hangul && (
#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
          (screen->code == C_UTF8 &&
           c >= 0x80 && c < 0xc0) ||
#endif
          (screen->code == C_WANSUNG &&
           c > 0xa0 && c < 0xff) ||
          (screen->code == C_JOHAB &&
           c > 0x40 && c < 0xff))) 
      {
#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.4 */
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
          if ((screen->code == C_UTF8) || (last_col == start_col))
#endif
            bptr -= last_hangul;
#else
          --bptr;
#endif
      }
      while(top > 0 && (isprint(*cp) || (*cp & 0x80))) {
            top--;
            bcnt--;
            cp++;
      }
    }

#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
    {
      int i;
      printf("(%02d,%02d) [ ", screen->cursor_row, screen->cur_col);
      for (i = 0; i< (cp-bptr-last_hangul); i++) {
            printf("%02x ", bptr[i]);
      }
      printf("]\n");
    }
#endif

#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
    /* 글자의 뒷쪽 일부분만이 입력된 경우 다음 글자로 건너 뜀 */
    if (!charset_sg && (screen->code == C_WANSUNG || screen->code == C_JOHAB)) {
      int y = 4 * screen->cursor_row;
      Char *col = screen->buf[y] + screen->cur_col;
      Char *attrs = screen->buf[y+1] + screen->cur_col;

      if ((screen->cur_col > 0) && (col[-1] & 0x80) && (attrs[-1]&FIRST_HAN)) 
      {
          Boolean skip = False;

          if (screen->code == C_WANSUNG) {
            unsigned char temp_buf[BUFSIZ];
            int ret = convert_johab_to_ks(col - 1, temp_buf, 2);

            skip = (ret == 2 && temp_buf[1] == (unsigned char)*bptr);
          } else if (screen->code == C_JOHAB) {
            skip = (*col == (unsigned char)*bptr);
          }

          if (skip) {
            bptr++;
            CursorForward(screen, 1);
          }
      }
    }
#endif

#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
    start_col = (unsigned)screen->cur_row<<8 | (unsigned)screen->cur_col;

    /* 첫글자가 다음 기회에 연결될 가능성이 있는 경우 기억 */
    if (!charset_sg && (screen->code == C_WANSUNG || screen->code == C_JOHAB)) {
      if ((*bptr & 0x80) && ((cp-bptr) > 1)) {
          c = bptr[1];
            
          if (push_col2 == start_col) {
            push_col3 = -1;
          } else {
            push_ch3 = push_ch2;
            push_col3 = push_col2;
          }
          if (push_col1 == start_col) {
            push_col2 = -1;
          } else {
            push_ch2 = push_ch1;
            push_col2 = push_col1;
          }
          push_ch1 = *bptr;
          push_col1 = start_col;
          start_col++;

          /* 다음에 연결될 것이 확실한 경우 현재 글자는 빈 칸으로 처리 */
          if (!( (screen->code == C_WANSUNG 
            && c > (unsigned char)0xa0 && c < (unsigned char)0xff) 
            || (screen->code == C_JOHAB 
            && c > (unsigned char)0x40 && c < (unsigned char)0xff) )
          ) {
            *bptr = ' ';
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
            printf("push_ch = %02x, col = <%04x>\n", push_ch1, push_col1);
#endif
          }
      }
    }
#endif
    /* 글자가 완성되지 않아 처리못하고 남길 부분 조치 */
    if (!charset_sg) 
    {
#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.4 */
      /* 남는 바이트 수 계산 */
      last_hangul = adjust_hangul_string(bptr, cp - bptr, screen->code);
#else
      last_hangul = adjust_hangul_string(bptr, cp - bptr);
#endif
    }
    else
        last_hangul = 0;

    /* 최종적으로 얻어진 text 처리 */
    {
      if(screen->curss) {
            dotext(screen, term->flags,
                   term->cur_foreground,
                   term->cur_background,
                   screen->gsets[screen->curss], bptr,
                   bptr + 1);
            screen->curss = 0;
            bptr++;
      }
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      {
          int i;
          printf("(%02d,%02d) == [ ", screen->cursor_row, screen->cur_col);
          for (i = 0; i< (cp-bptr-last_hangul); i++) {
                printf("%02x ", bptr[i]);
          }
          printf("]\n");
      }
#endif
      if(bptr < (cp - last_hangul))
          dotext(screen, term->flags,
               term->cur_foreground,
               term->cur_background,
               screen->gsets[screen->curgl], bptr,
               cp - last_hangul);
    }
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
    /* 마무리 */
    if (!charset_sg) 
    {
      /* 남은 미완성 글자가 있을 경우 커서를 다시 그림(모양은 자동) */
      if (last_hangul && screen->cursor_state) {
          HideCursor();
          ShowCursor();
      }
    }

    if (!charset_sg && (screen->code == C_WANSUNG || screen->code == C_JOHAB)) {
      last_col = ((unsigned)screen->cur_row<<8) | (unsigned)screen->cur_col;

#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      printf("last_hangul=%d, start_col=<%04x>, last_col=<%04x>, ch=%02x\n", 
          last_hangul, start_col, last_col, (unsigned char)*(cp-last_hangul));
#endif

      /* 기억한 글자중 덮어쓰여져 더이상 쓸모없는 경우 삭제 */
      if (start_col <= push_col3 && push_col3 <= last_col) {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
          printf("removed col3 = <%04x>, ch = %02x : term flags = %x\n", 
            push_col3, (unsigned char )push_ch3, term->flags&INSERT);
#endif
          push_col3 = -1;
      }
      if (start_col <= push_col2 && push_col2 <= last_col) {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
          printf("removed col2 = <%04x>, ch = %02x : term flags = %x\n", 
            push_col2, (unsigned char )push_ch2, term->flags&INSERT);
#endif
          push_col2 = push_col3;
          push_ch2 = push_ch3;
          push_col3 = -1;
      }
      if (start_col <= push_col1 && push_col1 <= last_col) {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
          printf("removed col1 = <%04x>, ch = %02x : term flags = %x\n", 
            push_col1, (unsigned char )push_ch1, term->flags&INSERT);
#endif
          push_col1 = push_col2;
          push_ch1 = push_ch2;
          push_col2 = -1;
      }

      /* 남은 미완성 글자를 기억함 */
      if (last_hangul) 
      {
          if (push_col2 == last_col) {
            push_col3 = -1;
          } else {
            push_ch3 = push_ch2;
            push_col3 = push_col2;
          }
          if (push_col1 == last_col) {
            push_col2 = -1;
          } else {
            push_ch2 = push_ch1;
            push_col2 = push_col1;
          }
          push_ch1 = *(cp - last_hangul);
          push_col1 = last_col;

          /* 출력되었다고 가정하고 커서를 옮김 */
          CursorForward(screen, 1);

          /* 남은 글자 없는 것으로 결론 */
          last_hangul = 0;
      }
    }
#endif
                  /* 마지막 정리 */
                  bptr = cp;
                  print = 1;
                  break;

             case CASE_GROUND_STATE:
                  /* exit ignore mode */
                  parsestate = groundtable;
                  break;

             case CASE_IGNORE_STATE:
                  /* Ies: ignore anything else */
                  parsestate = igntable;
                  break;

             case CASE_IGNORE_ESC:
                  /* Ign: escape */
                  parsestate = iestable;
                  break;

             case CASE_IGNORE:
                  /* Ignore character */
                  break;

             case CASE_BELL:
                  /* bell */
                  Bell();
                  break;

             case CASE_BS:
                  /* backspace */
#if !defined(NO_PATCH_BACKSPACE_BUG) /* by hanmaum 1998.2.6 */
               if (last_hangul > 0) {
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
                    printf("backspace last_hangul = %d, ", last_hangul);
#endif
                  last_hangul--;
                  if (screen->code==C_WANSUNG || screen->code==C_JOHAB)
                      CursorBack(screen, 1);
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
                    printf("last_hangul2 = %d\n", last_hangul);
#endif
                  if (screen->cursor_state) {
                      HideCursor();
                      ShowCursor();
                  }
               }
               else
#endif
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
              {
                    printf("backspace cur_col = %d, ", screen->cur_col);
#endif
                  CursorBack(screen, 1);
#if defined(DEBUG_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
                    printf("cur_col = %d\n", screen->cur_col);
              }
#endif
                  break;

             case CASE_CR:
                  /* carriage return */
                  CarriageReturn(screen);
                  parsestate = groundtable;
                  break;

             case CASE_ESC:
                  /* escape */
                  parsestate = esctable;
                  break;

             case CASE_VMOT:
                  /*
                   * form feed, line feed, vertical tab
                   */
                  Index(screen, 1);
                  if (term->flags & LINEFEED)
                        CarriageReturn(screen);
                  if (QLength(screen->display) > 0 ||
                      GetBytesAvailable (ConnectionNumber(screen->display)) > 0)
                    xevents();
                  parsestate = groundtable;
                  break;

             case CASE_TAB:
                  /* tab */
                  screen->cur_col = TabNext(term->tabs, screen->cur_col);
                  if (screen->cur_col > screen->max_col)
                        screen->cur_col = screen->max_col;
                  break;

             case CASE_SI:
                  screen->curgl = 0;
                  break;

             case CASE_SO:
                  screen->curgl = 1;
                  break;

             case CASE_SCR_STATE:
                  /* enter scr state */
                  parsestate = scrtable;
                  break;

             case CASE_SCS0_STATE:
                  /* enter scs state 0 */
                  scstype = 0;
                  parsestate = scstable;
                  break;

             case CASE_SCS1_STATE:
                  /* enter scs state 1 */
                  scstype = 1;
                  parsestate = scstable;
                  break;

             case CASE_SCS2_STATE:
                  /* enter scs state 2 */
                  scstype = 2;
                  parsestate = scstable;
                  break;

             case CASE_SCS3_STATE:
                  /* enter scs state 3 */
                  scstype = 3;
                  parsestate = scstable;
                  break;

             case CASE_ESC_IGNORE:
                  /* unknown escape sequence */
                  parsestate = eigtable;
                  break;

             case CASE_ESC_DIGIT:
                  /* digit in csi or dec mode */
                  if((row = param[nparam - 1]) == DEFAULT)
                        row = 0;
                  param[nparam - 1] = 10 * row + (c - '0');
                  break;

             case CASE_ESC_SEMI:
                  /* semicolon in csi or dec mode */
                  param[nparam++] = DEFAULT;
                  break;

             case CASE_DEC_STATE:
                  /* enter dec mode */
                  parsestate = dectable;
                  break;

             case CASE_ICH:
                  /* ICH */
                  if((row = param[0]) < 1)
                        row = 1;
                  InsertChar(screen, row);
                  parsestate = groundtable;
                  break;

             case CASE_CUU:
                  /* CUU */
                  if((row = param[0]) < 1)
                        row = 1;
                  CursorUp(screen, row);
                  parsestate = groundtable;
                  break;

             case CASE_CUD:
                  /* CUD */
                  if((row = param[0]) < 1)
                        row = 1;
                  CursorDown(screen, row);
                  parsestate = groundtable;
                  break;

             case CASE_CUF:
                  /* CUF */
                  if((row = param[0]) < 1)
                        row = 1;
                  CursorForward(screen, row);
                  parsestate = groundtable;
                  break;

             case CASE_CUB:
                  /* CUB */
                  if((row = param[0]) < 1)
                        row = 1;
                  CursorBack(screen, row);
                  parsestate = groundtable;
                  break;

             case CASE_CUP:
                  /* CUP | HVP */
                  if((row = param[0]) < 1)
                        row = 1;
                  if(nparam < 2 || (col = param[1]) < 1)
                        col = 1;
                  CursorSet(screen, row-1, col-1, term->flags);
                  parsestate = groundtable;
                  break;

#ifdef CASE_HP_BUGGY_LL
             case CASE_HP_BUGGY_LL:
                  /* Some HP-UX applications have the bug that they
                     assume ESC F goes to the lower left corner of
                     the screen, regardless of what terminfo says. */
                  if (screen->hp_ll_bc)
                      CursorSet(screen, screen->max_row, 0, term->flags);
                  parsestate = groundtable;
                  break;
#endif

             case CASE_ED:
                  /* ED */
                  switch (param[0]) {
                   case DEFAULT:
                   case 0:
                        ClearBelow(screen);
                        break;

                   case 1:
                        ClearAbove(screen);
                        break;

                   case 2:
                        ClearScreen(screen);
                        break;
                  }
                  parsestate = groundtable;
                  break;

             case CASE_EL:
                  /* EL */
                  switch (param[0]) {
                   case DEFAULT:
                   case 0:
                        ClearRight(screen);
                        break;
                   case 1:
                        ClearLeft(screen);
                        break;
                   case 2:
                        ClearLine(screen);
                        break;
                  }
                  parsestate = groundtable;
                  break;

             case CASE_IL:
                  /* IL */
                  if((row = param[0]) < 1)
                        row = 1;
                  InsertLine(screen, row);
                  parsestate = groundtable;
                  break;

             case CASE_DL:
                  /* DL */
                  if((row = param[0]) < 1)
                        row = 1;
                  DeleteLine(screen, row);
                  parsestate = groundtable;
                  break;

             case CASE_DCH:
                  /* DCH */
                  if((row = param[0]) < 1)
                        row = 1;
                  DeleteChar(screen, row);
                  parsestate = groundtable;
                  break;

             case CASE_TRACK_MOUSE:
                  /* Track mouse as long as in window and between
                     specified rows */
                  TrackMouse(param[0], param[2]-1, param[1]-1,
                   param[3]-1, param[4]-2);
                  break;

             case CASE_DECID:
                  param[0] = -1;          /* Default ID parameter */
                  /* Fall through into ... */
             case CASE_DA1:
                  /* DA1 */
                  if (param[0] <= 0) {    /* less than means DEFAULT */
                        reply.a_type   = CSI;
                        reply.a_pintro = '?';
                        reply.a_nparam = 2;
                        reply.a_param[0] = 1;         /* VT102 */
                        reply.a_param[1] = 2;         /* VT102 */
                        reply.a_inters = 0;
                        reply.a_final  = 'c';
                        unparseseq(&reply, screen->respond);
                  }
                  parsestate = groundtable;
                  break;

             case CASE_TBC:
                  /* TBC */
                  if ((row = param[0]) <= 0) /* less than means default */
                        TabClear(term->tabs, screen->cur_col);
                  else if (row == 3)
                        TabZonk(term->tabs);
                  parsestate = groundtable;
                  break;

             case CASE_SET:
                  /* SET */
                  ansi_modes(term, bitset);
                  parsestate = groundtable;
                  break;

             case CASE_RST:
                  /* RST */
                  ansi_modes(term, bitclr);
                  parsestate = groundtable;
                  break;

             case CASE_SGR:
                  /* SGR */
                  for (row=0; row<nparam; ++row) {
                        switch (param[row]) {
                         case DEFAULT:
                         case 0:
                              term->flags &=
                                  ~(INVERSE|BOLD|UNDERLINE|FG_COLOR|
                                    BG_COLOR);
                              break;
                         case 1:
                         case 5:    /* Blink, really. */
                              term->flags |= BOLD;
                              if (screen->colorBDMode )
                                BoldColor();
                              break;
                         case 4:    /* Underscore           */
                              term->flags |= UNDERLINE;
                              if (screen->colorULMode)
                                UnderlineColor();
                              break;
                         case 7:    /* inverse */
                              term->flags |= INVERSE;
                              break;
                         case 27:   /* inverse-off */
                              term->flags &= ~INVERSE;
                              break;
                         case 30:
                         case 31:
                         case 32:
                         case 33:
                         case 34:
                         case 35:
                         case 36:
                         case 37:
                              if( term->flags & INVERSE ) {
                                term->flags |= BG_COLOR;
                                term->cur_background = param[row] - 30;
                                if( (term->flags & BOLD) || BrightColor )
                                    term->cur_background += BRIGHTCLR;
                              }
                              else {
                                term->flags |= FG_COLOR;
                                term->cur_foreground = param[row] - 30;
                                if( (term->flags & BOLD) || BrightColor )
                                    term->cur_foreground += BRIGHTCLR;
                              }
                              break;
                         case 40:
                         case 41:
                         case 42:
                         case 43:
                         case 44:
                         case 45:
                         case 46:
                         case 47:
                              if( term->flags & INVERSE ) {
                                term->flags |= FG_COLOR;
                                term->cur_foreground = param[row] - 40;
                                if( BrightColor && term->cur_foreground )
                                    term->cur_foreground += BRIGHTCLR;
                              }
                              else {
                                term->flags |= BG_COLOR;
                                term->cur_background = param[row] - 40;
                                if( BrightColor && term->cur_background )
                                    term->cur_background += BRIGHTCLR;
                              }
                              break;
                        }
                  }
                  parsestate = groundtable;
                  break;

             case CASE_CPR:
                  /* CPR */
                  if ((row = param[0]) == 5) {
                        reply.a_type = CSI;
                        reply.a_pintro = 0;
                        reply.a_nparam = 1;
                        reply.a_param[0] = 0;
                        reply.a_inters = 0;
                        reply.a_final  = 'n';
                        unparseseq(&reply, screen->respond);
                  } else if (row == 6) {
                        reply.a_type = CSI;
                        reply.a_pintro = 0;
                        reply.a_nparam = 2;
                        reply.a_param[0] = screen->cur_row+1;
                        reply.a_param[1] = screen->cur_col+1;
                        reply.a_inters = 0;
                        reply.a_final  = 'R';
                        unparseseq(&reply, screen->respond);
                  }
                  parsestate = groundtable;
                  break;

#ifdef CASE_HP_MEM_LOCK
             case CASE_HP_MEM_LOCK:
             case CASE_HP_MEM_UNLOCK:
                  if(screen->scroll_amt)
                      FlushScroll(screen);
                  if (parsestate[c] == CASE_HP_MEM_LOCK)
                      screen->top_marg = screen->cur_row;
                  else
                      screen->top_marg = 0;
                  parsestate = groundtable;
                  break;
#endif

             case CASE_DECSTBM:
                  /* DECSTBM - set scrolling region */
                  if((top = param[0]) < 1)
                        top = 1;
                  if(nparam < 2 || (bot = param[1]) == DEFAULT
                     || bot > screen->max_row + 1
                     || bot == 0)
                        bot = screen->max_row+1;
                  if (bot > top) {
                        if(screen->scroll_amt)
                              FlushScroll(screen);
                        screen->top_marg = top-1;
                        screen->bot_marg = bot-1;
                        CursorSet(screen, 0, 0, term->flags);
                  }
                  parsestate = groundtable;
                  break;

             case CASE_DECREQTPARM:
                  /* DECREQTPARM */
                  if ((row = param[0]) == DEFAULT)
                        row = 0;
                  if (row == 0 || row == 1) {
                        reply.a_type = CSI;
                        reply.a_pintro = 0;
                        reply.a_nparam = 7;
                        reply.a_param[0] = row + 2;
                        reply.a_param[1] = 1;   /* no parity */
                        reply.a_param[2] = 1;   /* eight bits */
                        reply.a_param[3] = 112; /* transmit 9600 baud */
                        reply.a_param[4] = 112; /* receive 9600 baud */
                        reply.a_param[5] = 1;   /* clock multiplier ? */
                        reply.a_param[6] = 0;   /* STP flags ? */
                        reply.a_inters = 0;
                        reply.a_final  = 'x';
                        unparseseq(&reply, screen->respond);
                  }
                  parsestate = groundtable;
                  break;

             case CASE_DECSET:
                  /* DECSET */
                  dpmodes(term, bitset);
                  parsestate = groundtable;
                  break;

             case CASE_DECRST:
                  /* DECRST */
                  dpmodes(term, bitclr);
                  parsestate = groundtable;
                  break;

             case CASE_DECALN:
                  /* DECALN */
                  if(screen->cursor_state)
                        HideCursor();
                  for(row = screen->max_row ; row >= 0 ; row--) {
                        memset(screen->buf[4 * row + 1], '\0',
                         col = screen->max_col + 1);
                        for(cp = (unsigned char *)screen->buf[4 * row] ; col > 0 ; col--)
                              *cp++ = (unsigned char) 'E';
                  }
                  ScrnRefresh(screen, 0, 0, screen->max_row + 1,
                   screen->max_col + 1, False);
                  parsestate = groundtable;
                  break;

             case CASE_GSETS:
                  screen->gsets[scstype] = c;
                  parsestate = groundtable;
                  break;

             case CASE_DECSC:
                  /* DECSC */
                  CursorSave(term, &screen->sc);
                  parsestate = groundtable;
                  break;

             case CASE_DECRC:
                  /* DECRC */
                  CursorRestore(term, &screen->sc);
                  parsestate = groundtable;
                  break;

             case CASE_DECKPAM:
                  /* DECKPAM */
                  term->keyboard.flags |= KYPD_APL;
                  update_appkeypad();
                  parsestate = groundtable;
                  break;

             case CASE_DECKPNM:
                  /* DECKPNM */
                  term->keyboard.flags &= ~KYPD_APL;
                  update_appkeypad();
                  parsestate = groundtable;
                  break;

             case CASE_IND:
                  /* IND */
                  Index(screen, 1);
                  if (QLength(screen->display) > 0 ||
                      GetBytesAvailable (ConnectionNumber(screen->display)) > 0)
                    xevents();
                  parsestate = groundtable;
                  break;

             case CASE_NEL:
                  /* NEL */
                  Index(screen, 1);
                  CarriageReturn(screen);
                  
                  if (QLength(screen->display) > 0 ||
                      GetBytesAvailable (ConnectionNumber(screen->display)) > 0)
                    xevents();
                  parsestate = groundtable;
                  break;

             case CASE_HTS:
                  /* HTS */
                  TabSet(term->tabs, screen->cur_col);
                  parsestate = groundtable;
                  break;

             case CASE_RI:
                  /* RI */
                  RevIndex(screen, 1);
                  parsestate = groundtable;
                  break;

             case CASE_SS2:
                  /* SS2 */
                  screen->curss = 2;
                  parsestate = groundtable;
                  break;

             case CASE_SS3:
                  /* SS3 */
                  screen->curss = 3;
                  parsestate = groundtable;
                  break;

             case CASE_CSI_STATE:
                  /* enter csi state */
                  nparam = 1;
                  param[0] = DEFAULT;
                  parsestate = csitable;
                  break;

             case CASE_OSC:
                  /* Operating System Command: ESC ] */
                  do_osc(finput);
                  parsestate = groundtable;
                  break;

             case CASE_RIS:
                  /* RIS */
                  VTReset(TRUE);
                  parsestate = groundtable;
                  break;

             case CASE_LS2:
                  /* LS2 */
                  screen->curgl = 2;
                  parsestate = groundtable;
                  break;

             case CASE_LS3:
                  /* LS3 */
                  screen->curgl = 3;
                  parsestate = groundtable;
                  break;

             case CASE_LS3R:
                  /* LS3R */
                  screen->curgr = 3;
                  parsestate = groundtable;
                  break;

             case CASE_LS2R:
                  /* LS2R */
                  screen->curgr = 2;
                  parsestate = groundtable;
                  break;

             case CASE_LS1R:
                  /* LS1R */
                  screen->curgr = 1;
                  parsestate = groundtable;
                  break;

             case CASE_XTERM_SAVE:
                  savemodes(term);
                  parsestate = groundtable;
                  break;

             case CASE_XTERM_RESTORE:
                  restoremodes(term);
                  parsestate = groundtable;
                  break;
            }
          if (!print) {
            last_hangul = 0;
          }
      }
}

static finput()
{
      return(doinput());
}


static char *v_buffer;        /* pointer to physical buffer */
static char *v_bufstr = NULL; /* beginning of area to write */
static char *v_bufptr;        /* end of area to write */
static char *v_bufend;        /* end of physical buffer */
#if !defined(linux) && !defined(SVR4)     /* dkim@surecom.com */
#define     ptymask()   (v_bufptr > v_bufstr ? pty_mask : 0)
#endif

/* Write data to the pty as typed by the user, pasted with the mouse,
   or generated by us in response to a query ESC sequence. */

v_write(f, d, len)
    int f;
    char *d;
    int len;
{
      int riten;
      int c = len;

      if (v_bufstr == NULL  &&  len > 0) {
              v_buffer = XtMalloc(len);
            v_bufstr = v_buffer;
            v_bufptr = v_buffer;
            v_bufend = v_buffer + len;
      }
#ifdef DEBUG
      fprintf(stderr, "v_write called with %d bytes (%d left over)",
            len, v_bufptr - v_bufstr);
      if (len > 1  &&  len < 10) fprintf(stderr, " \"%.*s\"", len, d);
      fprintf(stderr, "\n");
#endif

#if defined(linux) || defined(SVR4)
      if (f != pty_mask)
#else
      if ((1 << f) != pty_mask)
#endif
            return(write(f, d, len));

      /*
       * Append to the block we already have.
       * Always doing this simplifies the code, and
       * isn't too bad, either.  If this is a short
       * block, it isn't too expensive, and if this is
       * a long block, we won't be able to write it all
       * anyway.
       */

      if (len > 0) {
          if (v_bufend < v_bufptr + len) { /* we've run out of room */
            if (v_bufstr != v_buffer) {
                /* there is unused space, move everything down */
                /* possibly overlapping bcopy here */
#ifdef DEBUG
                fprintf(stderr, "moving data down %d\n",
                      v_bufstr - v_buffer);
#endif
#ifdef SVR4 /* dkim@surecom.com */
                memmove(v_buffer, v_bufstr, v_bufptr - v_bufstr);
#else
                bcopy(v_bufstr, v_buffer, v_bufptr - v_bufstr);
#endif
                v_bufptr -= v_bufstr - v_buffer;
                v_bufstr = v_buffer;
            }
            if (v_bufend < v_bufptr + len) {
                /* still won't fit: get more space */
                /* Don't use XtRealloc because an error is not fatal. */
                int size = v_bufptr - v_buffer; /* save across realloc */
                v_buffer = realloc(v_buffer, size + len);
                if (v_buffer) {
#ifdef DEBUG
                  fprintf(stderr, "expanded buffer to %d\n",
                        size + len);
#endif
                  v_bufstr = v_buffer;
                  v_bufptr = v_buffer + size;
                  v_bufend = v_bufptr + len;
                } else {
                  /* no memory: ignore entire write request */
                  fprintf(stderr, "%s: cannot allocate buffer space\n",
                        xterm_name);
                  v_buffer = v_bufstr; /* restore clobbered pointer */
                  c = 0;
                }
            }
          }
          if (v_bufend >= v_bufptr + len) {
            /* new stuff will fit */
            /* no overlap?? - dkim@surecom.com */
            memcpy(v_bufptr, d, len);
            v_bufptr += len;
          }
      }

      /*
       * Write out as much of the buffer as we can.
       * Be careful not to overflow the pty's input silo.
       * We are conservative here and only write
       * a small amount at a time.
       *
       * If we can't push all the data into the pty yet, we expect write
       * to return a non-negative number less than the length requested
       * (if some data written) or -1 and set errno to EAGAIN,
       * EWOULDBLOCK, or EINTR (if no data written).
       *
       * (Not all systems do this, sigh, so the code is actually
       * a little more forgiving.)
       */

#define MAX_PTY_WRITE 128     /* 1/2 POSIX minimum MAX_INPUT */

      if (v_bufptr > v_bufstr) {
          riten = write(f, v_bufstr, v_bufptr - v_bufstr <= MAX_PTY_WRITE ?
                               v_bufptr - v_bufstr : MAX_PTY_WRITE);
          if (riten < 0) {
#ifdef DEBUG
            perror("write");
#endif
            riten = 0;
          }
#ifdef DEBUG
          fprintf(stderr, "write called with %d, wrote %d\n",
                v_bufptr - v_bufstr <= MAX_PTY_WRITE ?
                v_bufptr - v_bufstr : MAX_PTY_WRITE,
                riten);
#endif
          v_bufstr += riten;
          if (v_bufstr >= v_bufptr) /* we wrote it all */
            v_bufstr = v_bufptr = v_buffer;
      }

      /*
       * If we have lots of unused memory allocated, return it
       */
      if (v_bufend - v_bufptr > 1024) { /* arbitrary hysteresis */
          /* save pointers across realloc */
          int start = v_bufstr - v_buffer;
          int size = v_bufptr - v_buffer;
          int allocsize = size ? size : 1;
          
          v_buffer = realloc(v_buffer, allocsize);
          if (v_buffer) {
            v_bufstr = v_buffer + start;
            v_bufptr = v_buffer + size;
            v_bufend = v_buffer + allocsize;
#ifdef DEBUG
            fprintf(stderr, "shrunk buffer to %d\n", allocsize);
#endif
          } else {
            /* should we print a warning if couldn't return memory? */
            v_buffer = v_bufstr - start; /* restore clobbered pointer */
          }
      }
      return(c);
}

#if (defined(linux)||defined(SVR4))||(defined(hpux) && OSMAJORVERSION >= 10)
static fd_set select_mask;
static fd_set write_mask;
#else
static int select_mask;
static int write_mask;
#endif
static int pty_read_bytes;

in_put()
{
    register TScreen *screen = &term->screen;
    register int i;
    static struct timeval select_timeout;

    for( ; ; ) {
#if defined(linux)||defined(SVR4)||(defined(hpux) && OSMAJORVERSION >= 10)
      if (FD_ISSET(pty_mask, &select_mask) && eventMode == NORMAL) {
#else
      if (select_mask & pty_mask && eventMode == NORMAL) {
#endif
#ifdef ALLOWLOGFILEONOFF
          if (screen->logging)
            FlushLog(screen);
#endif
          if (last_hangul) {
#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.4 */
               int i;
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
            /* reserve 10 bytes for safety */
            for (i = 10; i < last_hangul; i++)
                  buffer[i+10] = *(bptr - last_hangul + i);
            bptr = &buffer[last_hangul+10];
#else
               for (i = 0; i < last_hangul; i++)
                       buffer[i] = *(bptr - last_hangul + i);
               bptr = &buffer[last_hangul];
#endif /* !defined(NO_PATCH_CURSOR_MOVE) */
#else
               buffer[0] = *(bptr - 1);
               bptr = &buffer[1];
#endif /* !defined(NO_PATCH_ADJUSTHANGULSTRING) */
          } else {
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
            bptr = buffer + 10; /* reserve 10 bytes for safety */
#else
            bptr = buffer;
#endif
          }
          bcnt = read(screen->respond, bptr, BUF_SIZE);
          if (bcnt < 0) {
            if (errno == EIO)
                Cleanup (0);
            else if (!E_TEST(errno))
                Panic(
                    "input: read returned unexpected error (%d)\n",
                    errno);
          } else if (bcnt == 0)
            Panic("input: read returned zero\n", 0);
          else {
            /* read from pty was successful */
            if (!screen->output_eight_bits) {
                register int bc = bcnt;
                register Char *b = bptr;

                for (; bc > 0; bc--, b++) {
                  *b &= (Char) 0x7f;
                }
            }
            if ( screen->scrollWidget && screen->scrollttyoutput &&
                 screen->topline < 0)
                WindowScroll(screen, 0);  /* Scroll to bottom */
            pty_read_bytes += bcnt;
            /* stop speed reading at some point to look for X stuff */
            /* (4096 is just a random large number.) */
            if (pty_read_bytes > 4096) {
#if defined(linux)||defined(SVR4)||(defined(hpux) && OSMAJORVERSION >= 10)
                FD_CLR(pty_mask, &select_mask);
#else
                select_mask &= ~pty_mask;
#endif
            }
            break;
          }
      }
      pty_read_bytes = 0;
      /* update the screen */
      if (screen->scroll_amt)
          FlushScroll(screen);
      if (screen->cursor_set && (screen->cursor_col != screen->cur_col
                           || screen->cursor_row != screen->cur_row)) {
          if (screen->cursor_state)
            HideCursor();
          ShowCursor();
      } else if (screen->cursor_set != screen->cursor_state) {
          if (screen->cursor_set)
            ShowCursor();
          else
            HideCursor();
      }

      XFlush(screen->display); /* always flush writes before waiting */

      /* Update the masks and, unless X events are already in the queue,
         wait for I/O to be possible. */
      select_mask = Select_mask;
#if defined(linux) || defined(SVR4) ||(defined(hpux) && OSMAJORVERSION >= 10)
      if (v_bufptr > v_bufstr)
        FD_SET(pty_mask, &write_mask);
       else
         FD_ZERO(&write_mask);  /* by dkim 99/04/29 */
#else
      write_mask = ptymask();
#endif
      select_timeout.tv_sec = 0;
      select_timeout.tv_usec = 0;

/* by sangil's report */
/* #if defined(linux)||defined(SVR4)
    ||(defined(hpux) && OSMAJORVERSION >= 10) */
#if defined(linux)||defined(SVR4)
      if (QLength (screen->display))
      {
          i = select(max_plus1, (fd_set*) &select_mask, (fd_set*) &write_mask, (fd_set *)NULL, (struct timeval *) &select_timeout);
      }
      else
      {
          i = select(max_plus1, (fd_set*) &select_mask, (fd_set*) &write_mask, (fd_set *)NULL, (struct timeval *) NULL);
      }
#else
      if (QLength (screen->display))
      {
          i = select(max_plus1, &select_mask, &write_mask, (int *)NULL, (struct timeval *) &select_timeout);
      }
      else
      {
          i = select(max_plus1, &select_mask, &write_mask, (int *)NULL, (struct timeval *) NULL);
      }
#endif
      if (i < 0) {
          if (errno != EINTR)
            SysError(ERROR_SELECT);
          continue;
      } 

      /* if there is room to write more data to the pty, go write more */
#if defined(linux)||defined(SVR4)||(defined(hpux) && OSMAJORVERSION >= 10)
      if ((v_bufptr > v_bufstr) && FD_ISSET(pty_mask, &write_mask)) {
#else
      if (write_mask & ptymask()) {
#endif
          v_write(screen->respond, 0, 0); /* flush buffer */
      }

      /* if there are X events already in our queue, it
         counts as being readable */
#if defined(linux)||defined(SVR4)||(defined(hpux) && OSMAJORVERSION >= 10)
      if (QLength(screen->display) || (FD_ISSET(X_mask, &select_mask))) {
#else
      if (QLength(screen->display) || (select_mask & X_mask)) {
#endif
          xevents();
      }

    }
    bcnt--;
    return(*bptr++);
}

/*
 * process a string of characters according to the character set indicated
 * by charset.  worry about end of line conditions (wraparound if selected).
 */
static void
dotext(screen, flags, fg, bg, charset, buf, ptr)
    register TScreen    *screen;
    unsigned      flags;
    unsigned    fg, bg;
    char    charset;
    char    *buf;       /* start of characters to process */
    char    *ptr;       /* end */
{
#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.4 */
      extern int get_hangul_coding_length();
      extern int get_hangul_screen_length();

      int len_code; 
      int incomplete;
#endif

      register char     *s;
      register int      len;
      register int      n;
      register int      next_col;

      switch (charset) {
      case 'A':   /* United Kingdom set               */
            for (s=buf; s<ptr; ++s)
                  if (*s == '#')
                        *s = '\036';      /* UK pound sign*/
            break;

      case 'B':   /* ASCII set                        */
            break;

      case 'C':   /* KSC 5601 */
            for (s=buf; s<ptr; ++s)
                  if (*s>=0x21 && *s<=0x7e)
                        *s |= 0x80;
            break;

      case '0':   /* special graphics (line drawing)  */
#if !defined(NO_PATCH_LINE_DRAW)
                {
                    extern int *gr_mapping;
                    for (s=buf; s<ptr; ++s) {
                        *s = gr_mapping[(unsigned char )*s];
                    }
                }
#else
            for (s=buf; s<ptr; ++s)
                  if (*s>=0x5f && *s<=0x7e)
                        *s = *s == 0x5f ? 0x7f : *s - 0x5f;
#endif
            break;

      default:    /* any character sets we don't recognize*/
            return;
      }

      len = ptr - buf; 
      ptr = buf;
      while (len > 0) {
            n = screen->max_col - screen->cur_col +1;
            if (n <= 1) {
                  if (screen->do_wrap && (flags&WRAPAROUND)) {
                      /* mark that we had to wrap this line */
                      ScrnSetAttributes(screen, screen->cur_row, 0,
                                    LINEWRAPPED, LINEWRAPPED, 1);
                      Index(screen, 1);
                      screen->cur_col = 0;
                      screen->do_wrap = 0;
                      n = screen->max_col+1;
                  } else
                      n = 1;
            }

#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.4 */
            len_code = get_hangul_coding_length(ptr, len, n, screen->code);
            incomplete = adjust_hangul_string(ptr, len_code, screen->code);
            len_code -= incomplete;
            n = get_hangul_screen_length(ptr, len_code, screen->code);
            next_col = screen->cur_col + n + (incomplete?1:0);
            WriteText(screen, ptr, len_code, flags, fg, bg);
#else
            if (len < n)
                  n = len;
            next_col = screen->cur_col + n;
            if (n == screen->max_col + 1)
            {
#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.4 */
                  n -= adjust_hangul_string(ptr, n, screen->code);
#else
                  if (adjust_hangul_string(ptr, n))
                        n--;
#endif
            }
            WriteText(screen, ptr, n, flags, fg, bg);
#endif
            /*
             * the call to WriteText updates screen->cur_col.
             * If screen->cur_col != next_col, we must have
             * hit the right margin, so set the do_wrap flag.
             */
            screen->do_wrap = (screen->cur_col < next_col);
#if !defined(NO_PATCH_ADJUSTHANGULSTRING) /* by hanmaum 1998.2.4 */
            len -= len_code;
            ptr += len_code;
#else
            len -= n;
            ptr += n;
#endif
      }
}
 
 
/*
 * write a string str of length len onto the screen at
 * the current cursor position.  update cursor position.
 */
static void
WriteText(screen, str, len, flags, fg, bg)
    register TScreen    *screen;
    register char *str;
    register int  len;
    unsigned            flags;
    unsigned            fg, bg;
{
    register int cx, cy;
    register unsigned fgs = flags;
    register Pixel fg_pix, bg_pix;
    GC      currentGC, currentHGC;
    char johab_buf[BUF_SIZE];
    
    fg_pix = (fgs&FG_COLOR) ? screen->colors[fg] : screen->foreground;
    bg_pix = (fgs&BG_COLOR) ? screen->colors[bg] : term->core.background_pixel;

    if (screen->code == C_WANSUNG) {
      len = convert_ks_to_johab(str, johab_buf, len);
#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
    } else if (screen->code == C_UTF8) {
      len = convert_utf8_to_johab(str, johab_buf, len);
#endif
    } else {
      memcpy(johab_buf,str,len);
      johab_buf[len] = '\0';
    }
    if(screen->cur_row - screen->topline <= screen->max_row) {
      /*
        if(screen->cur_row == screen->cursor_row && screen->cur_col <=
        screen->cursor_col && screen->cursor_col <= screen->cur_col + len - 1)
        screen->cursor_state = OFF;
        */
      if(screen->cursor_state)
          HideCursor();
      
      /*
       *    make sure that the correct GC is current
       */
      
      if (fgs & INVERSE) {
          if (fgs & BOLD) {
            currentGC = screen->reverseboldGC;
            currentHGC = screen->reverseHGC;
          }
          else {
            currentGC = screen->reverseGC;
            currentHGC = screen->reverseHGC;
          }
          XSetForeground(screen->display, currentGC, bg_pix);
          XSetBackground(screen->display, currentGC, fg_pix);
          XSetForeground(screen->display, currentHGC, bg_pix);
          XSetBackground(screen->display, currentHGC, fg_pix);
      } else { /* not inverse */
          if (fgs & BOLD) {
            currentGC = screen->normalboldGC;
            currentHGC = screen->normalHGC;
          }
          else {
            currentGC = screen->normalGC;
            currentHGC = screen->normalHGC;
          }
          XSetForeground(screen->display, currentGC, fg_pix);
          XSetBackground(screen->display, currentGC, bg_pix);
          XSetForeground(screen->display, currentHGC, fg_pix);
          XSetBackground(screen->display, currentHGC, bg_pix);
      }
      if (fgs & INSERT)
          InsertChar(screen, len);
      if (!(AddToRefresh(screen))) {
          if(screen->scroll_amt)
            FlushScroll(screen);
          cx = CursorX(screen, screen->cur_col);
          cy = CursorY(screen, screen->cur_row)+screen->ascent;
          HDrawImageString(screen->display, TextWindow(screen), currentGC,
                       currentHGC, cx, cy, johab_buf, len);
          
          if((fgs & BOLD) && screen->enbolden) 
            if (currentGC == screen->normalGC ||
                currentGC == screen->reverseGC)
                HDrawString(screen->display, TextWindow(screen),
                        currentGC, currentHGC, cx + 1, cy, johab_buf,
                        len);
          
          if((fgs & UNDERLINE) && screen->underline)
            XDrawLine(screen->display, TextWindow(screen), currentGC,
                    cx, cy+1,
                    cx + len * FontWidth(screen), cy+1);
          /*
           * the following statements compile data to compute the average 
           * number of characters written on each call to XText.  The data
           * may be examined via the use of a "hidden" escape sequence.
           */
          ctotal += len;
          ++ntotal;
      }
    }
    ScreenWrite(screen, johab_buf, flags, fg, bg, len);
    CursorForward(screen, len);
}


/*
 * process ANSI modes set, reset
 */
ansi_modes(termw, func)
    XtermWidget   termw;
    int           (*func)();
{
      register int      i;

      for (i=0; i<nparam; ++i) {
            switch (param[i]) {
            case 4:                 /* IRM                        */
                  (*func)(&termw->flags, INSERT);
                  break;

            case 20:          /* LNM                        */
                  (*func)(&termw->flags, LINEFEED);
                  update_autolinefeed();
                  break;
            }
      }
}

/*
 * process DEC private modes set, reset
 */
dpmodes(termw, func)
    XtermWidget   termw;
    void (*func)();
{
      register TScreen  *screen     = &termw->screen;
      register int      i, j;

      for (i=0; i<nparam; ++i) {
            switch (param[i]) {
            case 1:                 /* DECCKM               */
                  (*func)(&termw->keyboard.flags, CURSOR_APL);
                  update_appcursor();
                  break;
            case 2:                 /* ANSI/VT52 mode       */
                  if (func == bitset) {
                        screen->gsets[0] =
                              screen->gsets[1] =
                              screen->gsets[2] =
                              screen->gsets[3] = 'B';
                        screen->curgl = 0;
                        screen->curgr = 2;
                  }
                  break;
            case 3:                 /* DECCOLM              */
                  if(screen->c132) {
                        ClearScreen(screen);
                        CursorSet(screen, 0, 0, termw->flags);
                        if((j = func == bitset ? 132 : 80) !=
                         ((termw->flags & IN132COLUMNS) ? 132 : 80) ||
                         j != screen->max_col + 1) {
                                Dimension replyWidth, replyHeight;
                              XtGeometryResult status;

                              status = XtMakeResizeRequest (
                                  (Widget) termw, 
                                  (Dimension) FontWidth(screen) * j
                                      + 2*screen->border
                                    + screen->scrollbar,
                                  (Dimension) FontHeight(screen)
                                    * (screen->max_row + 1)
                                    + 3 * screen->border
                                    + FontHeight(screen),
                                  &replyWidth, &replyHeight);

                              if (status == XtGeometryYes ||
                                  status == XtGeometryDone) {
                                  ScreenResize (&termw->screen,
                                            replyWidth,
                                            replyHeight,
                                            &termw->flags);
                              }
                        }
                        (*func)(&termw->flags, IN132COLUMNS);
                  }
                  break;
            case 4:                 /* DECSCLM (slow scroll)      */
                  if (func == bitset) {
                        screen->jumpscroll = 0;
                        if (screen->scroll_amt)
                              FlushScroll(screen);
                  } else
                        screen->jumpscroll = 1;
                  (*func)(&termw->flags, SMOOTHSCROLL);
                  update_jumpscroll();
                  break;
            case 5:                 /* DECSCNM              */
                  j = termw->flags;
                  (*func)(&termw->flags, REVERSE_VIDEO);
                  if ((termw->flags ^ j) & REVERSE_VIDEO)
                        ReverseVideo(termw);
                  /* update_reversevideo done in RevVid */
                  break;

            case 6:                 /* DECOM                */
                  (*func)(&termw->flags, ORIGIN);
                  CursorSet(screen, 0, 0, termw->flags);
                  break;

            case 7:                 /* DECAWM               */
                  (*func)(&termw->flags, WRAPAROUND);
                  update_autowrap();
                  break;
            case 8:                 /* DECARM               */
                  /* ignore autorepeat */
                  break;
            case 9:                 /* MIT bogus sequence         */
                  if(func == bitset)
                        screen->send_mouse_pos = 1;
                  else
                        screen->send_mouse_pos = 0;
                  break;
            case 38:          /* DECTEK               */
                  break;
            case 40:          /* 132 column mode            */
                  screen->c132 = (func == bitset);
                  update_allow132();
                  break;
            case 41:          /* curses hack                */
                  screen->curses = (func == bitset);
                  update_cursesemul();
                  break;
            case 44:          /* margin bell                */
                  screen->marginbell = (func == bitset);
                  if(!screen->marginbell)
                        screen->bellarmed = -1;
                  update_marginbell();
                  break;
            case 45:          /* reverse wraparound   */
                  (*func)(&termw->flags, REVERSEWRAP);
                  update_reversewrap();
                  break;
            case 46:          /* logging        */
#ifdef ALLOWLOGFILEONOFF
                  /*
                   * if this feature is enabled, logging may be 
                   * enabled and disabled via escape sequences.
                   */
                  if(func == bitset)
                        StartLog(screen);
                  else
                        CloseLog(screen);
#else
                  Bell();
                  Bell();
#endif /* ALLOWLOGFILEONOFF */
                  break;
            case 47:          /* alternate buffer */
                  if (!termw->misc.titeInhibit) {
                      if(func == bitset)
                        ToAlternate(screen);
                      else
                        FromAlternate(screen);
                  }
                  break;
            case 1000:        /* xterm bogus sequence       */
                  if(func == bitset)
                        screen->send_mouse_pos = 2;
                  else
                        screen->send_mouse_pos = 0;
                  break;
            case 1001:        /* xterm sequence w/hilite tracking */
                  if(func == bitset)
                        screen->send_mouse_pos = 3;
                  else
                        screen->send_mouse_pos = 0;
                  break;
            }
      }
}

/*
 * process xterm private modes save
 */
savemodes(termw)
    XtermWidget termw;
{
      register TScreen  *screen     = &termw->screen;
      register int i;

      for (i = 0; i < nparam; i++) {
            switch (param[i]) {
            case 1:                 /* DECCKM               */
                  screen->save_modes[0] = termw->keyboard.flags &
                   CURSOR_APL;
                  break;
            case 3:                 /* DECCOLM              */
                  if(screen->c132)
                      screen->save_modes[1] = termw->flags & IN132COLUMNS;
                  break;
            case 4:                 /* DECSCLM (slow scroll)      */
                  screen->save_modes[2] = termw->flags & SMOOTHSCROLL;
                  break;
            case 5:                 /* DECSCNM              */
                  screen->save_modes[3] = termw->flags & REVERSE_VIDEO;
                  break;
            case 6:                 /* DECOM                */
                  screen->save_modes[4] = termw->flags & ORIGIN;
                  break;

            case 7:                 /* DECAWM               */
                  screen->save_modes[5] = termw->flags & WRAPAROUND;
                  break;
            case 8:                 /* DECARM               */
                  /* ignore autorepeat */
                  break;
            case 9:                 /* mouse bogus sequence */
                  screen->save_modes[7] = screen->send_mouse_pos;
                  break;
            case 40:          /* 132 column mode            */
                  screen->save_modes[8] = screen->c132;
                  break;
            case 41:          /* curses hack                */
                  screen->save_modes[9] = screen->curses;
                  break;
            case 44:          /* margin bell                */
                  screen->save_modes[12] = screen->marginbell;
                  break;
            case 45:          /* reverse wraparound   */
                  screen->save_modes[13] = termw->flags & REVERSEWRAP;
                  break;
#ifdef ALLOWLOGFILEONOFF
            case 46:          /* logging        */
                  screen->save_modes[14] = screen->logging;
                  break;
#endif
            case 47:          /* alternate buffer           */
                  screen->save_modes[15] = screen->alternate;
                  break;
            case 1000:        /* mouse bogus sequence       */
            case 1001:
                  screen->save_modes[7] = screen->send_mouse_pos;
                  break;
            }
      }
}

/*
 * process xterm private modes restore
 */
restoremodes(termw)
    XtermWidget termw;
{
      register TScreen  *screen     = &termw->screen;
      register int i, j;

      for (i = 0; i < nparam; i++) {
            switch (param[i]) {
            case 1:                 /* DECCKM               */
                  termw->keyboard.flags &= ~CURSOR_APL;
                  termw->keyboard.flags |= screen->save_modes[0] &
                   CURSOR_APL;
                  update_appcursor();
                  break;
            case 3:                 /* DECCOLM              */
                  if(screen->c132) {
                        ClearScreen(screen);
                        CursorSet(screen, 0, 0, termw->flags);
                        if((j = (screen->save_modes[1] & IN132COLUMNS)
                         ? 132 : 80) != ((termw->flags & IN132COLUMNS)
                         ? 132 : 80) || j != screen->max_col + 1) {
                                Dimension replyWidth, replyHeight;
                              XtGeometryResult status;
                              status = XtMakeResizeRequest (
                                  (Widget) termw,
                                  (Dimension) FontWidth(screen) * j 
                                    + 2*screen->border
                                    + screen->scrollbar,
                                  (Dimension) FontHeight(screen)
                                    * (screen->max_row + 1)
                                    + 3*screen->border
                                    + FontHeight(screen),
                                  &replyWidth, &replyHeight);

                              if (status == XtGeometryYes ||
                                  status == XtGeometryDone) {
                                  ScreenResize (&termw->screen,
                                            replyWidth,
                                            replyHeight,
                                            &termw->flags);
                              }
                        }
                        termw->flags &= ~IN132COLUMNS;
                        termw->flags |= screen->save_modes[1] &
                         IN132COLUMNS;
                  }
                  break;
            case 4:                 /* DECSCLM (slow scroll)      */
                  if (screen->save_modes[2] & SMOOTHSCROLL) {
                        screen->jumpscroll = 0;
                        if (screen->scroll_amt)
                              FlushScroll(screen);
                  } else
                        screen->jumpscroll = 1;
                  termw->flags &= ~SMOOTHSCROLL;
                  termw->flags |= screen->save_modes[2] & SMOOTHSCROLL;
                  update_jumpscroll();
                  break;
            case 5:                 /* DECSCNM              */
                  if((screen->save_modes[3] ^ termw->flags) & REVERSE_VIDEO) {
                        termw->flags &= ~REVERSE_VIDEO;
                        termw->flags |= screen->save_modes[3] & REVERSE_VIDEO;
                        ReverseVideo(termw);
                        /* update_reversevideo done in RevVid */
                  }
                  break;
            case 6:                 /* DECOM                */
                  termw->flags &= ~ORIGIN;
                  termw->flags |= screen->save_modes[4] & ORIGIN;
                  CursorSet(screen, 0, 0, termw->flags);
                  break;

            case 7:                 /* DECAWM               */
                  termw->flags &= ~WRAPAROUND;
                  termw->flags |= screen->save_modes[5] & WRAPAROUND;
                  update_autowrap();
                  break;
            case 8:                 /* DECARM               */
                  /* ignore autorepeat */
                  break;
            case 9:                 /* MIT bogus sequence         */
                  screen->send_mouse_pos = screen->save_modes[7];
                  break;
            case 40:          /* 132 column mode            */
                  screen->c132 = screen->save_modes[8];
                  update_allow132();
                  break;
            case 41:          /* curses hack                */
                  screen->curses = screen->save_modes[9];
                  update_cursesemul();
                  break;
            case 44:          /* margin bell                */
                  if(!(screen->marginbell = screen->save_modes[12]))
                        screen->bellarmed = -1;
                  update_marginbell();
                  break;
            case 45:          /* reverse wraparound   */
                  termw->flags &= ~REVERSEWRAP;
                  termw->flags |= screen->save_modes[13] & REVERSEWRAP;
                  update_reversewrap();
                  break;
#ifdef ALLOWLOGFILEONOFF
            case 46:          /* logging        */
                  if(screen->save_modes[14])
                        StartLog(screen);
                  else
                        CloseLog(screen);
                  /* update_logging done by StartLog and CloseLog */
                  break;
#endif /* ALLOWLOGFILEONOFF */
            case 47:          /* alternate buffer */
                  if (!termw->misc.titeInhibit) {
                      if(screen->save_modes[15])
                        ToAlternate(screen);
                      else
                        FromAlternate(screen);
                      /* update_altscreen done by ToAlt and FromAlt */
                  }
                  break;
            case 1000:        /* mouse bogus sequence       */
            case 1001:
                  screen->send_mouse_pos = screen->save_modes[7];
                  break;
            }
      }
}

/*
 * set a bit in a word given a pointer to the word and a mask.
 */
static void bitset(p, mask)
    unsigned *p;
    int mask;
{
      *p |= mask;
}

/*
 * clear a bit in a word given a pointer to the word and a mask.
 */
static void bitclr(p, mask)
    unsigned *p;
    int mask;
{
      *p &= ~mask;
}

unparseseq(ap, fd)
    register ANSI *ap;
    int fd;
{
      register int      c;
      register int      i;
      register int      inters;

      c = ap->a_type;
      if (c>=0x80 && c<=0x9F) {
            unparseputc(ESC, fd);
            c -= 0x40;
      }
      unparseputc(c, fd);
      c = ap->a_type;
      if (c==ESC || c==DCS || c==CSI || c==OSC || c==PM || c==APC) {
            if (ap->a_pintro != 0)
                  unparseputc((char) ap->a_pintro, fd);
            for (i=0; i<ap->a_nparam; ++i) {
                  if (i != 0)
                        unparseputc(';', fd);
                  unparseputn((unsigned int) ap->a_param[i], fd);
            }
            inters = ap->a_inters;
            for (i=3; i>=0; --i) {
                  c = (inters >> (8*i)) & 0xff;
                  if (c != 0)
                        unparseputc(c, fd);
            }
            unparseputc((char) ap->a_final, fd);
      }
}

unparseputn(n, fd)
unsigned int      n;
int fd;
{
      unsigned int      q;

      q = n/10;
      if (q != 0)
            unparseputn(q, fd);
      unparseputc((char) ('0' + (n%10)), fd);
}

unparseputc(c, fd)
int c;
int fd;
{
      char  buf[20];
      register i = 1;
      extern XtermWidget term;

      i = hangul_automata(c, buf);
      if (i > 0) {
          if(buf[i-1] == '\r' && (term->flags & LINEFEED)) {
            buf[i] = '\n';
            i++;
          }
          v_write(fd, buf, i);
      }
}

unparsefputs (s, fd)
    register char *s;
    int fd;
{
    if (s) {
      while (*s) unparseputc (*s++, fd);
    }
}

static void SwitchBufs();

static void
ToAlternate(screen)
register TScreen *screen;
{
      extern ScrnBuf Allocate();

      if(screen->alternate)
            return;
      if(!screen->altbuf)
            screen->altbuf = Allocate(screen->max_row + 1, screen->max_col
             + 1, &screen->abuf_address);
      SwitchBufs(screen);
      screen->alternate = TRUE;
      update_altscreen();
}

static void
FromAlternate(screen)
register TScreen *screen;
{
      if(!screen->alternate)
            return;
      screen->alternate = FALSE;
      SwitchBufs(screen);
      update_altscreen();
}

static void
SwitchBufs(screen)
    register TScreen *screen;
{
      register int rows, top;

      if(screen->cursor_state)
            HideCursor();
      rows = screen->max_row + 1;
      SwitchBufPtrs(screen);
      TrackText(0, 0, 0, 0);  /* remove any highlighting */
      if((top = -screen->topline) <= screen->max_row) {
            if(screen->scroll_amt)
                  FlushScroll(screen);
            XClearArea(
                      screen->display,
                      TextWindow(screen),
                      (int) screen->border + screen->scrollbar,
                      (int) top * FontHeight(screen) + screen->border,
                      (unsigned) Width(screen),
                      (unsigned) (screen->max_row - top + 1)
                        * FontHeight(screen),
                      FALSE);
      }
      ScrnRefresh(screen, 0, 0, rows, screen->max_col + 1, False);
}

/* swap buffer line pointers between alt and regular screens */

SwitchBufPtrs(screen)
    register TScreen *screen;
{
    register int rows = screen->max_row + 1;
    char *save [4 * MAX_ROWS];

    /* no overlap - dkim@surecom.com */
    memcpy((char *)save, (char *)screen->buf, 4 * sizeof(char *) * rows);
    memcpy((char *)screen->buf, (char *)screen->altbuf, 4 * sizeof(char *) * rows);
    memcpy((char *)screen->altbuf, (char *)save, 4 * sizeof(char *) * rows);
}

VTRun()
{
      register TScreen *screen = &term->screen;
      register int i;
      
      set_vt_visibility (TRUE);

      if (screen->allbuf == NULL) VTallocbuf ();

      screen->cursor_state = OFF;
      screen->cursor_set = ON;

      bcnt = 0;
      bptr = buffer;
      VTparse();
      HideCursor();
      screen->cursor_set = OFF;
}

/*ARGSUSED*/
static void VTExpose(w, event, region)
    Widget w;
    XEvent *event;
    Region region;
{
      register TScreen *screen = &term->screen;

#ifdef DEBUG
      if(debug)
            fputs("Expose\n", stderr);
#endif      /* DEBUG */
      if (event->type == Expose)
            HandleExposure (screen, event);
}

static void VTGraphicsOrNoExpose (event)
    XEvent *event;
{
      register TScreen *screen = &term->screen;
      if (screen->incopy <= 0) {
            screen->incopy = 1;
            if (screen->scrolls > 0)
                  screen->scrolls--;
      }
      if (event->type == GraphicsExpose)
        if (HandleExposure (screen, event))
            screen->cursor_state = OFF;
      if ((event->type == NoExpose) || ((XGraphicsExposeEvent *)event)->count == 0) {
            if (screen->incopy <= 0 && screen->scrolls > 0)
                  screen->scrolls--;
            if (screen->scrolls)
                  screen->incopy = -1;
            else
                  screen->incopy = 0;
      }
}

/*ARGSUSED*/
static void VTNonMaskableEvent (w, closure, event, cont)
Widget w;               /* unused */
XtPointer closure;            /* unused */
XEvent *event;
Boolean *cont;                /* unused */
{
    switch (event->type) {
       case GraphicsExpose:
       case NoExpose:
        VTGraphicsOrNoExpose (event);
        break;
      }
}




static void VTResize(w)
    Widget w;
{
    if (XtIsRealized(w))
      ScreenResize (&term->screen, term->core.width, term->core.height,
                &term->flags);
}

                        
extern Atom wm_delete_window; /* for ICCCM delete window */

static String xterm_trans =
    "<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\
     <MappingNotify>: KeyboardMapping()\n";

int VTInit ()
{
    register TScreen *screen = &term->screen;
    Widget vtparent = term->core.parent;

    XtRealizeWidget (vtparent);
    XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans));
    (void) XSetWMProtocols (XtDisplay(vtparent), XtWindow(vtparent),
                      &wm_delete_window, 1);

    if (screen->allbuf == NULL) VTallocbuf ();
    return (1);
}

static void VTallocbuf ()
{
    register TScreen *screen = &term->screen;
    int nrows = screen->max_row + 1;
    extern ScrnBuf Allocate();

    /* allocate screen buffer now, if necessary. */
    if (screen->scrollWidget)
      nrows += screen->savelines;
    screen->allbuf = Allocate (nrows, screen->max_col + 1,
     &screen->sbuf_address);
    if (screen->scrollWidget)
      screen->buf = &screen->allbuf[4 * screen->savelines];
    else
      screen->buf = screen->allbuf;
    return;
}

static void VTClassInit ()
{
    static int arg = 0;

    XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity,
               (XtConvertArgList) NULL, (Cardinal) 0);
/* 99/03/03 gaemon */
    if(!arg) {
      if(strlen(defaultTranslations)+strlen(translations2) > TRANSTBL_SIZE)
        fprintf(stderr, "Translation table size too small\n");
      strncat(defaultTranslations, translations2, TRANSTBL_SIZE - strlen(defaultTranslations)); 
      arg = 1;
    }
}


static void VTInitialize (wrequest, wnew, args, num_args)
   Widget wrequest, wnew;
   ArgList args;
   Cardinal *num_args;
{
   XtermWidget request = (XtermWidget) wrequest;
   XtermWidget new     = (XtermWidget) wnew;
   int i;

   /* Zero out the entire "screen" component of "new" widget,
      then do field-by-field assigment of "screen" fields
      that are named in the resource list. */

   memset ((char *) &new->screen, '\0', sizeof(new->screen));
   new->screen.c132 = request->screen.c132;
   new->screen.curses = request->screen.curses;
   new->screen.hp_ll_bc = request->screen.hp_ll_bc;
   new->screen.foreground = request->screen.foreground;
   new->screen.cursorcolor = request->screen.cursorcolor;
   new->screen.border = request->screen.border;
   new->screen.jumpscroll = request->screen.jumpscroll;
#ifdef ALLOWLOGFILEONOFF
   new->screen.logfile = request->screen.logfile;
#endif
   new->screen.marginbell = request->screen.marginbell;
   new->screen.mousecolor = request->screen.mousecolor;
   new->screen.mousecolorback = request->screen.mousecolorback;
   new->screen.multiscroll = request->screen.multiscroll;
   new->screen.nmarginbell = request->screen.nmarginbell;
   new->screen.savelines = request->screen.savelines;
   new->screen.scrolllines = request->screen.scrolllines;
   new->screen.scrollttyoutput = request->screen.scrollttyoutput;
   new->screen.scrollkey = request->screen.scrollkey;

/* inserted by ysyun, 1999/03/20 */
   new->screen.colorBDMode = request->screen.colorBDMode;
   new->screen.colorULMode = request->screen.colorULMode;
   new->screen.underline = request->screen.underline;
/* end of patch */

   new->screen.visualbell = request->screen.visualbell;
   new->misc.re_verse = request->misc.re_verse;
   new->screen.multiClickTime = request->screen.multiClickTime;
   new->screen.bellSuppressTime = request->screen.bellSuppressTime;
   new->screen.charClass = request->screen.charClass;
   new->screen.cutNewline = request->screen.cutNewline;
   new->screen.cutToBeginningOfLine = request->screen.cutToBeginningOfLine;
   new->screen.always_highlight = request->screen.always_highlight;
   new->screen.pointer_cursor = request->screen.pointer_cursor;
   new->screen.input_eight_bits = request->screen.input_eight_bits;
   new->screen.output_eight_bits = request->screen.output_eight_bits;
   new->screen.allowSendEvents = request->screen.allowSendEvents;
   new->misc.titeInhibit = request->misc.titeInhibit;
   for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) {
       new->screen.menu_font_names[i] = request->screen.menu_font_names[i];
   }
   for (i = 0; i < MAXCOLORS; i++) {
       new->screen.colors[i] = request->screen.colors[i];
   }
   /* set default in realize proc */
   new->screen.menu_font_names[fontMenu_fontdefault] = NULL;
   new->screen.menu_font_names[fontMenu_fontescape] = NULL;
   new->screen.menu_font_names[fontMenu_fontsel] = NULL;
   new->screen.menu_font_number = fontMenu_fontdefault;

    /*
     * The definition of -rv now is that it changes the definition of 
     * XtDefaultForeground and XtDefaultBackground.  So, we no longer
     * need to do anything special.
     */
   new->keyboard.flags = 0;
   new->screen.display = new->core.screen->display;
   new->core.height = new->core.width = 1;
      /* dummy values so that we don't try to Realize the parent shell 
       with height or width of 0, which is illegal in X.  The real
       size is computed in the xtermWidget's Realize proc,
       but the shell's Realize proc is called first, and must see
       a valid size. */

   new->screen.code = 
      (request->screen.code >= 0 && request->screen.code <= C_LASTNUM)
        ? request->screen.code : C_WANSUNG;
   if (new->screen.code == C_WANSUNG) {
       converter = convert_3_to_ks;
#if !defined(NO_PATCH_UTF8) /* by hanmaum 1998.2.5 */
   } else if (new->screen.code == C_UTF8) {
       converter = convert_3_to_utf8;
#endif
   } else {
       converter = convert_3_to_johab;
   }

   /* set default hangul keyboard type from string */
   if (!strcmp(request->screen.keyboardStrPtr, HKB_2_STR)) {
      new->screen.keyboard = 2;
   }
   else if (!strcmp(request->screen.keyboardStrPtr, HKB_3_STR)) {
      new->screen.keyboard = 390;
   }
   else if (!strcmp(request->screen.keyboardStrPtr, HKB_390_STR)) {
      new->screen.keyboard = 390;
   }
   else if (!strcmp(request->screen.keyboardStrPtr, HKB_391_STR)) {
      new->screen.keyboard = 391;
   }
   else if (!strcasecmp(request->screen.keyboardStrPtr, HKB_3FINAL_STR)) {
      new->screen.keyboard = 391;
   }
   else {
      new->screen.keyboard = 2;
   }
   /* set default english keyboard type */
   new->screen.use_dvorak_layout = request->screen.use_dvorak_layout;

   /* set show status */
   new->screen.showStatus.hideCode = request->screen.showStatus.hideCode;
   new->screen.showStatus.hideHanLayout = request->screen.showStatus.hideHanLayout;

   /* look for focus related events on the shell, because we need
    * to care about the shell's border being part of our focus.
    */
   XtAddEventHandler(XtParent(new), EnterWindowMask, FALSE,
            HandleEnterWindow, (Opaque)NULL);
   XtAddEventHandler(XtParent(new), LeaveWindowMask, FALSE,
            HandleLeaveWindow, (Opaque)NULL);
   XtAddEventHandler(XtParent(new), FocusChangeMask, FALSE,
            HandleFocusChange, (Opaque)NULL);
   XtAddEventHandler((Widget)new, 0L, TRUE,
            VTNonMaskableEvent, (Opaque)NULL);
   XtAddEventHandler((Widget)new, PropertyChangeMask, FALSE,
                 HandleBellPropertyChange, (Opaque)NULL);
   new->screen.bellInProgress = FALSE;

   set_character_class (new->screen.charClass);

   /* create it, but don't realize it */
   ScrollBarOn (new, TRUE, FALSE);

   /* make sure that the resize gravity acceptable */
   if ( new->misc.resizeGravity != NorthWestGravity &&
        new->misc.resizeGravity != SouthWestGravity) {
       extern XtAppContext app_con;
       Cardinal nparams = 1;

       XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError",
                   "unsupported resizeGravity resource value (%d)",
                   (String *) &(new->misc.resizeGravity), &nparams);
       new->misc.resizeGravity = SouthWestGravity;
   }

   return;
}


static void VTDestroy (w)
Widget w;
{
    XtFree(((XtermWidget)w)->screen.selection);
}

/*ARGSUSED*/
static void VTRealize (w, valuemask, values)
    Widget w;
    XtValueMask *valuemask;
    XSetWindowAttributes *values;
{
      unsigned int width, height;
      register TScreen *screen = &term->screen;
      int xpos, ypos, pr;
      XSizeHints        sizehints;
      int scrollbar_width;

      TabReset (term->tabs);

      screen->menu_font_names[fontMenu_fontdefault] = term->misc.f_n;

      /*
       * mem. leak?
       * Daeshik Kim (dkim@surecom.com) - DKIM
       */
      if (screen->fnt_norm)
        XFreeFont (screen->display, screen->fnt_norm);
      if (screen->fnt_bold)
        XFreeFont (screen->display, screen->fnt_bold);
      if (screen->fnt_hangul)
        XFreeFont (screen->display, screen->fnt_hangul);

      screen->fnt_norm = screen->fnt_bold = screen->fnt_hangul = NULL;
      if (!LoadNewFont(screen, term->misc.f_n, term->misc.f_b,
                   term->misc.f_h, False, 0)) {
          fprintf (stderr, "%s:  can't open font\n\t\"%s\"\n\t\"%s\"\n",
                 xterm_name, term->misc.f_n, term->misc.f_h);
          Exit (1);
      }

      /* making cursor */
      if (!screen->pointer_cursor) 
        screen->pointer_cursor = make_colored_cursor(XC_xterm, 
                                           screen->mousecolor,
                                           screen->mousecolorback);
      else 
        recolor_cursor (screen->pointer_cursor, 
                    screen->mousecolor, screen->mousecolorback);

      scrollbar_width = (term->misc.scrollbar ?
                     screen->scrollWidget->core.width /* +
                     screen->scrollWidget->core.border_width */ : 0);

      /* set defaults */
      xpos = 1; ypos = 1; width = 80; height = 24;
      pr = XParseGeometry (term->misc.geo_metry, &xpos, &ypos,
                       &width, &height);
      screen->max_col = (width - 1);      /* units in character cells */
      screen->max_row = (height - 1);     /* units in character cells */
      update_font_info (&term->screen, False);

      width = screen->fullVwin.fullwidth;
      height = screen->fullVwin.fullheight;

      if ((pr & XValue) && (XNegative&pr)) 
        xpos += DisplayWidth(screen->display, DefaultScreen(screen->display))
                  - width - (term->core.parent->core.border_width * 2);
      if ((pr & YValue) && (YNegative&pr))
        ypos += DisplayHeight(screen->display,DefaultScreen(screen->display))
                  - height - (term->core.parent->core.border_width * 2);

      /* set up size hints for window manager; min 1 char by 1 char */
      sizehints.base_width = 2 * screen->border + scrollbar_width;
      sizehints.base_height = 3 * screen->border + FontHeight(screen);
      sizehints.width_inc = FontWidth(screen);
      sizehints.height_inc = FontHeight(screen);
      sizehints.min_width = sizehints.base_width + sizehints.width_inc;
      sizehints.min_height = sizehints.base_height + sizehints.height_inc;
      sizehints.flags = (PBaseSize|PMinSize|PResizeInc);
      sizehints.x = xpos;
      sizehints.y = ypos;
      if ((XValue&pr) || (YValue&pr)) {
          sizehints.flags |= USSize|USPosition;
          sizehints.flags |= PWinGravity;
          switch (pr & (XNegative | YNegative)) {
            case 0:
            sizehints.win_gravity = NorthWestGravity;
            break;
            case XNegative:
            sizehints.win_gravity = NorthEastGravity;
            break;
            case YNegative:
            sizehints.win_gravity = SouthWestGravity;
            break;
            default:
            sizehints.win_gravity = SouthEastGravity;
            break;
          }
      } else {
          /* set a default size, but do *not* set position */
          sizehints.flags |= PSize;
      }
      sizehints.width = width;
      sizehints.height = height;
      if ((WidthValue&pr) || (HeightValue&pr)) 
        sizehints.flags |= USSize;
      else sizehints.flags |= PSize;

      (void) XtMakeResizeRequest((Widget) term,
                           (Dimension)width, (Dimension)height,
                           &term->core.width, &term->core.height);

      /* XXX This is bogus.  We are parsing geometries too late.  This
       * is information that the shell widget ought to have before we get
       * realized, so that it can do the right thing.
       */
        if (sizehints.flags & USPosition)
          XMoveWindow (XtDisplay(term), term->core.parent->core.window,
                   sizehints.x, sizehints.y);

      XSetWMNormalHints (XtDisplay(term), term->core.parent->core.window,
                     &sizehints);
      XFlush (XtDisplay(term));     /* get it out to window manager */

      /* use ForgetGravity instead of SouthWestGravity because translating
         the Expose events for ConfigureNotifys is too hard */
      values->bit_gravity = term->misc.resizeGravity == NorthWestGravity ?
          NorthWestGravity : ForgetGravity;
      term->screen.fullVwin.window = term->core.window =
        XCreateWindow(XtDisplay(term), XtWindow(term->core.parent),
            term->core.x, term->core.y,
            term->core.width, term->core.height, term->core.border_width,
            (int) term->core.depth,
            InputOutput, CopyFromParent,  
            *valuemask|CWBitGravity, values);

      set_cursor_gcs (screen);

      /* Reset variables used by ANSI emulation. */

      screen->gsets[0] = 'B';             /* ASCII_G        */
      screen->gsets[1] = 'B';
      screen->gsets[2] = 'B';             /* DEC supplemental.    */
      screen->gsets[3] = 'B';
      screen->curgl = 0;                  /* G0 => GL.            */
      screen->curgr = 2;                  /* G2 => GR.            */
      screen->curss = 0;                  /* No single shift.     */

      XDefineCursor(screen->display, VShellWindow, screen->pointer_cursor);

        screen->cur_col = screen->cur_row = 0;
      screen->max_col = Width(screen)/screen->fullVwin.f_width - 1;
      screen->top_marg = 0;
      screen->bot_marg = screen->max_row = Height(screen) /
                        screen->fullVwin.f_height - 1;

      screen->sc.row = screen->sc.col = screen->sc.flags = 0;

      /* Mark screen buffer as unallocated.  We wait until the run loop so
         that the child process does not fork and exec with all the dynamic
         memory it will never use.  If we were to do it here, the
         swap space for new process would be huge for huge savelines. */
        screen->buf = screen->allbuf = NULL;

      screen->do_wrap = 0;
      screen->scrolls = screen->incopy = 0;
      set_vt_box (screen);

      screen->savedlines = 0;

      if (term->misc.scrollbar) {
            screen->scrollbar = 0;
            ScrollBarOn (term, FALSE, TRUE);
      }
      CursorSave (term, &screen->sc);
      return;
}

static Boolean VTSetValues (cur, request, new, args, num_args)
    Widget cur, request, new;
    ArgList args;
    Cardinal *num_args;
{
    XtermWidget curvt = (XtermWidget) cur;
    XtermWidget newvt = (XtermWidget) new; 
    Boolean refresh_needed = FALSE;
    Boolean fonts_redone = FALSE;

    if(curvt->core.background_pixel != newvt->core.background_pixel
       || curvt->screen.foreground != newvt->screen.foreground
       || curvt->screen.menu_font_names[curvt->screen.menu_font_number]
          != newvt->screen.menu_font_names[newvt->screen.menu_font_number]
       || curvt->misc.f_n != newvt->misc.f_n) {
      if(curvt->misc.f_n != newvt->misc.f_n)
          newvt->screen.menu_font_names[fontMenu_fontdefault] = newvt->misc.f_n;
      if (LoadNewFont(&newvt->screen,
                  newvt->screen.menu_font_names[curvt->screen.menu_font_number],
                  newvt->screen.menu_font_names[curvt->screen.menu_font_number],
                  newvt->misc.f_h,
                  TRUE, newvt->screen.menu_font_number)) {
          /* resizing does the redisplay, so don't ask for it here */
          refresh_needed = TRUE;
          fonts_redone = TRUE;
      } else
          if(curvt->misc.f_n != newvt->misc.f_n)
            newvt->screen.menu_font_names[fontMenu_fontdefault] = curvt->misc.f_n;
    }
    if(!fonts_redone
       && curvt->screen.cursorcolor != newvt->screen.cursorcolor) {
      set_cursor_gcs(&newvt->screen);
      refresh_needed = TRUE;
    }
    if(curvt->misc.re_verse != newvt->misc.re_verse) {
      newvt->flags ^= REVERSE_VIDEO;
      ReverseVideo(newvt);
      newvt->misc.re_verse = !newvt->misc.re_verse; /* ReverseVideo toggles */
      refresh_needed = TRUE;
    }
    if(curvt->screen.mousecolor != newvt->screen.mousecolor
       || curvt->screen.mousecolorback != newvt->screen.mousecolorback) {
      recolor_cursor (newvt->screen.pointer_cursor, 
                  newvt->screen.mousecolor,
                  newvt->screen.mousecolorback);
      refresh_needed = TRUE;
    }
    if (curvt->misc.scrollbar != newvt->misc.scrollbar) {
      if (newvt->misc.scrollbar) {
          ScrollBarOn (newvt, FALSE, FALSE);
      } else {
          ScrollBarOff (&newvt->screen);
      }
      update_scrollbar();
    }

    return refresh_needed;
}

/*
 * Shows cursor at new cursor position in screen.
 */
void ShowCursor()
{
      register TScreen *screen = &term->screen;
      register int x, y, flags, n;
      Char c[2];
      GC    currentGC, currentHGC;
      Boolean     in_selection;
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      Boolean half_cursor = False;
#endif

      if (eventMode != NORMAL) return;

    if (chat_mode)
      chat_show_cursor();

      if (screen->cur_row - screen->topline > screen->max_row)
            return;
      y = 4 * (screen->cursor_row = screen->cur_row);
      x = screen->cursor_col = screen->cur_col;
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      if (x > 0 && (screen->buf[y][x-1] & 0x80) 
            && (screen->buf[y+1][x-1] & FIRST_HAN)
            && (!(screen->buf[y+1][x] & FIRST_HAN) 
             || adjust_hangul_string(screen->buf[y+1], x, 0 /*C_JOHAB*/))) {
          --x;
          half_cursor = True;
      }
      else if (last_hangul) {
          half_cursor = True;
      }
#endif
      flags = screen->buf[y + 1][x];
      if (temp_hangul[0] && !chat_mode) {
          c[0] = temp_hangul[0];
          c[1] = temp_hangul[1];
          n = 2;
      }
      else {
          c[0] = screen->buf[y][x];
          n = 1;
          if (flags & FIRST_HAN) {
            c[1] = screen->buf[y][x+1];
            n = 2;
          }
      }
      if (c[0] == 0)
            c[0] = ' ';

                        /* boundary? */
        if (n == 2 && x == screen->max_col) {
          if (screen->cursor_state)
            HideCursor();
          ScrnSetAttributes(screen, screen->cur_row, 0,
                        LINEWRAPPED, LINEWRAPPED, 1);
          Index(screen, 1);
          FlushScroll(screen);
          screen->cursor_col = screen->cur_col = 0;
      }

      if (screen->cur_row > screen->endHRow ||
          (screen->cur_row == screen->endHRow &&
           screen->cur_col >= screen->endHCol) ||
          screen->cur_row < screen->startHRow ||
          (screen->cur_row == screen->startHRow &&
           screen->cur_col < screen->startHCol))
          in_selection = False;
      else
          in_selection = True;

      if ((screen->select || screen->always_highlight) && !chat_mode) {
            if (( (flags & INVERSE) && !in_selection) ||
                (!(flags & INVERSE) &&  in_selection)){
                /* text is reverse video */
                if (screen->cursorGC) {
                  currentGC = screen->cursorGC;
                  currentHGC = screen->cursorHGC;
                } else {
                  if (flags & BOLD) {
                        currentGC = screen->normalboldGC;
                        currentHGC = screen->normalHGC;
                  } else {
                        currentGC = screen->normalGC;
                        currentHGC = screen->normalHGC;
                  }
                }
            } else { /* normal video */
                if (screen->reversecursorGC) {
                  currentGC = screen->reversecursorGC;
                  currentHGC = screen->reversecursorHGC;
                } else {
                  if (flags & BOLD) {
                        currentGC = screen->reverseboldGC;
                        currentHGC = screen->reverseHGC;
                  } else {
                        currentGC = screen->reverseGC;
                        currentHGC = screen->reverseHGC;
                  }
                }
            }
      } else { /* not selected */
            if (( (flags & INVERSE) && !in_selection) ||
                (!(flags & INVERSE) &&  in_selection)) {
                /* text is reverse video */
                  currentGC = screen->reverseGC;
                  currentHGC = screen->reverseHGC;
            } else { /* normal video */
                  currentGC = screen->normalGC;
                  currentHGC = screen->normalHGC;
            }
      }

#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      x = CursorX (screen, x);
#else
      x = CursorX (screen, screen->cur_col);
#endif
      y = CursorY(screen, screen->cur_row) + screen->ascent;
      HDrawImageString(screen->display, TextWindow(screen), currentGC,
                     currentHGC, x, y, (char *) c, n);

      if((flags & BOLD) && screen->enbolden) /* no bold font */
            HDrawString(screen->display, TextWindow(screen), currentGC,
                      currentHGC, x + 1, y, (char *) c, n);
      if((flags & UNDERLINE) && screen->underline)
            XDrawLine(screen->display, TextWindow(screen), currentGC,
                  x, y+1, x + n*FontWidth(screen), y+1);
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      if ((half_cursor == True) || (flags & INVERSE)) {
               XDrawLine(screen->display, TextWindow(screen), currentGC,
                       x+(n-1)*FontWidth(screen),y-1,
                        x+n*FontWidth(screen),y-1);
               XDrawLine(screen->display, TextWindow(screen), currentGC,
                       x+(n-1)*FontWidth(screen),y,
                        x+n*FontWidth(screen),y);
      }
#endif
      if ((!screen->select && !screen->always_highlight) || chat_mode) {
          if (n == 1) {
            screen->box->x = x;
            screen->box->y = y - screen->ascent;
            XDrawLines (screen->display, TextWindow(screen), 
                      screen->cursoroutlineGC ? screen->cursoroutlineGC 
                                        : currentGC,
                      screen->box, NBOX, CoordModePrevious);
          }
          else {
            screen->hbox->x = x;
            screen->hbox->y = y - screen->ascent;
            XDrawLines (screen->display, TextWindow(screen), 
                      screen->cursoroutlineGC ? screen->cursoroutlineGC 
                                        : currentGC,
                      screen->hbox, NBOX, CoordModePrevious);
          }
      }
      screen->cursor_state = ON;
}

/*
 * hide cursor at previous cursor position in screen.
 */
void HideCursor()
{
      register TScreen *screen = &term->screen;
      GC    currentGC, currentHGC;
      register int x, y, flags, n;
      char c[3];
      Boolean     in_selection;
#if !defined(NO_PATCH_CURSOR_COLOR) /* by hanmaum 1998.2.6 */
      unsigned fg, bg;
      Pixel fg_pix, bg_pix;
#endif


      if (chat_mode)
          chat_hide_cursor();

      y = 4 * screen->cursor_row;
      x = screen->cursor_col;
      if(screen->cursor_row - screen->topline > screen->max_row)
            return;
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      if (x > 0 && (screen->buf[y][x-1] & 0x80) 
            && (screen->buf[y+1][x-1] & FIRST_HAN)
            && (!(screen->buf[y+1][x] & FIRST_HAN) 
             || adjust_hangul_string(screen->buf[y+1], x, 0 /*C_JOHAB*/))) 
          --x;
#endif
      c[0] = screen->buf[y][x];
      flags = screen->buf[y + 1][x];
      n = 1;
      if (temp_hangul[0] || flags & FIRST_HAN) {
          c[1] = screen->buf[y][x+1];
          n = 2;
      }
      if (screen->buf[y + 1][x + 1] & FIRST_HAN) {
          c[1] = screen->buf[y][x+1];
          c[2] = screen->buf[y][x+2];
          n = 3;
      }

#if !defined(NO_PATCH_CURSOR_COLOR) /* by hanmaum 1998.2.6 */
      fg = screen->buf[y+2][x];
      bg = screen->buf[y+3][x];
      fg_pix = (flags & FG_COLOR) ? screen->colors[fg]
                            : screen->foreground;
      bg_pix = (flags & BG_COLOR) ? screen->colors[bg]
                            : term->core.background_pixel;
#endif

      if (screen->cursor_row > screen->endHRow ||
          (screen->cursor_row == screen->endHRow &&
           screen->cursor_col >= screen->endHCol) ||
          screen->cursor_row < screen->startHRow ||
          (screen->cursor_row == screen->startHRow &&
           screen->cursor_col < screen->startHCol))
          in_selection = False;
      else
          in_selection = True;

      if (( (flags & INVERSE) && !in_selection) ||
          (!(flags & INVERSE) &&  in_selection)) {
            if(flags & BOLD) {
                  currentGC = screen->reverseboldGC;
                  currentHGC = screen->reverseHGC;
            } else {
                  currentGC = screen->reverseGC;
                  currentHGC = screen->reverseHGC;
            }
#if !defined(NO_PATCH_CURSOR_COLOR) /* by hanmaum 1998.2.6 */
            XSetForeground(screen->display, currentGC, bg_pix);
            XSetBackground(screen->display, currentGC, fg_pix);
            XSetForeground(screen->display, currentHGC, bg_pix);
            XSetBackground(screen->display, currentHGC, fg_pix);
#endif
      } else {
            if(flags & BOLD) {
                  currentGC = screen->normalboldGC;
                  currentHGC = screen->normalHGC;
            } else {
                  currentGC = screen->normalGC;
                  currentHGC = screen->normalHGC;
            }
#if !defined(NO_PATCH_CURSOR_COLOR) /* by hanmaum 1998.2.6 */
            XSetForeground(screen->display, currentGC, fg_pix);
            XSetBackground(screen->display, currentGC, bg_pix);
            XSetForeground(screen->display, currentHGC, fg_pix);
            XSetBackground(screen->display, currentHGC, bg_pix);
#endif
      }

      if (c[0] == 0)
            c[0] = ' ';
#if !defined(NO_PATCH_CURSOR_MOVE) /* by hanmaum 1998.2.6 */
      x = CursorX (screen, x);
#else
      x = CursorX (screen, screen->cursor_col);
#endif
      y = (((screen->cursor_row - screen->topline) * FontHeight(screen))) +
       screen->border;
      y = y+screen->ascent;
      HDrawImageString(screen->display, TextWindow(screen), currentGC,
            currentHGC, x, y, c, n);
      if((flags & BOLD) && screen->enbolden)
            HDrawString(screen->display, TextWindow(screen), currentGC,
                      currentHGC, x + 1, y, c, n);
      if((flags & UNDERLINE) && screen->underline)
            XDrawLine(screen->display, TextWindow(screen), currentGC,
                  x, y+1, x + n*FontWidth(screen), y+1);
      screen->cursor_state = OFF;
}

void VTReset(full)
    Boolean full;
{
      register TScreen *screen = &term->screen;

      /* reset scrolling region */
      screen->top_marg = 0;
      screen->bot_marg = screen->max_row;
      term->flags &= ~ORIGIN;
      if(full) {
            TabReset (term->tabs);
            term->keyboard.flags = 0;
            update_appcursor();
            update_appkeypad();
            screen->gsets[0] = 'B';
            screen->gsets[1] = 'B';
            screen->gsets[2] = 'B';
            screen->gsets[3] = 'B';
            screen->curgl = 0;
            screen->curgr = 2;
            screen->curss = 0;
            FromAlternate(screen);
            ClearScreen(screen);
            screen->cursor_state = OFF;
            if (term->flags & REVERSE_VIDEO)
                  ReverseVideo(term);

            term->flags = term->initflags;
            update_reversevideo();
            update_autowrap();
            update_reversewrap();
            update_autolinefeed();
            screen->jumpscroll = !(term->flags & SMOOTHSCROLL);
            update_jumpscroll();
            if(screen->c132 && (term->flags & IN132COLUMNS)) {
                    Dimension junk;
                  XtMakeResizeRequest(
                      (Widget) term,
                      (Dimension) 80*FontWidth(screen)
                        + 2 * screen->border + screen->scrollbar,
                      (Dimension) FontHeight(screen)
                          * (screen->max_row + 1) + 3 * screen->border
                                  + FontHeight(screen),
                      &junk, &junk);
                  XSync(screen->display, FALSE);      /* synchronize */
                  if(QLength(screen->display) > 0)
                        xevents();
            }
            CursorSet(screen, 0, 0, term->flags);
      }
      longjmp(vtjmpbuf, 1);   /* force ground state in parser */
}



/*
 * set_character_class - takes a string of the form
 * 
 *                 low[-high]:val[,low[-high]:val[...]]
 * 
 * and sets the indicated ranges to the indicated values.
 */

int set_character_class (s)
    register char *s;
{
    register int i;                 /* iterator, index into s */
    int len;                        /* length of s */
    int acc;                        /* accumulator */
    int low, high;                  /* bounds of range [0..127] */
    int base;                       /* 8, 10, 16 (octal, decimal, hex) */
    int numbers;              /* count of numbers per range */
    int digits;                     /* count of digits in a number */
    static char *errfmt = "%s:  %s in range string \"%s\" (position %d)\n";
    extern char *ProgramName;

    if (!s || !s[0]) return -1;

    base = 10;                      /* in case we ever add octal, hex */
    low = high = -1;                /* out of range */

    for (i = 0, len = strlen (s), acc = 0, numbers = digits = 0;
       i < len; i++) {
      char c = s[i];

      if (isspace(c)) {
          continue;
      } else if (isdigit(c)) {
          acc = acc * base + (c - '0');
          digits++;
          continue;
      } else if (c == '-') {
          low = acc;
          acc = 0;
          if (digits == 0) {
            fprintf (stderr, errfmt, ProgramName, "missing number", s, i);
            return (-1);
          }
          digits = 0;
          numbers++;
          continue;
      } else if (c == ':') {
          if (numbers == 0)
            low = acc;
          else if (numbers == 1)
            high = acc;
          else {
            fprintf (stderr, errfmt, ProgramName, "too many numbers",
                   s, i);
            return (-1);
          }
          digits = 0;
          numbers++;
          acc = 0;
          continue;
      } else if (c == ',') {
          /*
           * now, process it
           */

          if (high < 0) {
            high = low;
            numbers++;
          }
          if (numbers != 2) {
            fprintf (stderr, errfmt, ProgramName, "bad value number", 
                   s, i);
          } else if (SetCharacterClassRange (low, high, acc) != 0) {
            fprintf (stderr, errfmt, ProgramName, "bad range", s, i);
          }

          low = high = -1;
          acc = 0;
          digits = 0;
          numbers = 0;
          continue;
      } else {
          fprintf (stderr, errfmt, ProgramName, "bad character", s, i);
          return (-1);
      }                       /* end if else if ... else */

    }

    if (low < 0 && high < 0) return (0);

    /*
     * now, process it
     */

    if (high < 0) high = low;
    if (numbers < 1 || numbers > 2) {
      fprintf (stderr, errfmt, ProgramName, "bad value number", s, i);
    } else if (SetCharacterClassRange (low, high, acc) != 0) {
      fprintf (stderr, errfmt, ProgramName, "bad range", s, i);
    }

    return (0);
}

/* ARGSUSED */
static void HandleKeymapChange(w, event, params, param_count)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *param_count;
{
    static XtTranslations keymap, original;
    static XtResource key_resources[] = {
      { XtNtranslations, XtCTranslations, XtRTranslationTable,
            sizeof(XtTranslations), 0, XtRTranslationTable, (XtPointer)NULL}
    };
    char mapName[1000];
    char mapClass[1000];

    if (*param_count != 1) return;

    if (original == NULL) original = w->core.tm.translations;

    if (strcmp(params[0], "None") == 0) {
      XtOverrideTranslations(w, original);
      return;
    }
    (void) sprintf( mapName, "%sKeymap", params[0] );
    (void) strcpy( mapClass, mapName );
    if (islower(mapClass[0])) mapClass[0] = toupper(mapClass[0]);
    XtGetSubresources( w, (XtPointer)&keymap, mapName, mapClass,
                   key_resources, (Cardinal)1, NULL, (Cardinal)0 );
    if (keymap != NULL)
      XtOverrideTranslations(w, keymap);
}


/* ARGSUSED */
static void HandleBell(w, event, params, param_count)
    Widget w;
    XEvent *event;            /* unused */
    String *params;           /* [0] = volume */
    Cardinal *param_count;    /* 0 or 1 */
{
    int percent = (*param_count) ? atoi(params[0]) : 0;

    XBell( XtDisplay(w), percent );
}


/* ARGSUSED */
static void HandleVisualBell(w, event, params, param_count)
    Widget w;
    XEvent *event;            /* unused */
    String *params;           /* unused */
    Cardinal *param_count;    /* unused */
{
    VisualBell();
}


/* ARGSUSED */
static void HandleIgnore(w, event, params, param_count)
    Widget w;
    XEvent *event;            /* unused */
    String *params;           /* unused */
    Cardinal *param_count;    /* unused */
{
    /* do nothing, but check for funny escape sequences */
    (void) SendMousePosition(w, event);
}


/* ARGSUSED */
static void
DoSetSelectedFont(w, client_data, selection, type, value, length, format)
    Widget w;
    XtPointer client_data;
    Atom *selection, *type;
    XtPointer value;
    unsigned long *length;
    int *format;
{
    char *val = (char *)value;
    int len;
    if (*type != XA_STRING  ||  *format != 8) {
      Bell();
      return;
    }
    len = strlen(val);
    if (len > 0) {
      if (val[len-1] == '\n') val[len-1] = '\0';
      /* Do some sanity checking to avoid sending a long selection
         back to the server in an OpenFont that is unlikely to succeed.
         XLFD allows up to 255 characters and no control characters;
         we are a little more liberal here. */
      if (len > 1000  ||  strchr(val, '\n'))
          return;
      if (!LoadNewFont (&term->screen, val, NULL, term->misc.f_h, True,
                    fontMenu_fontsel))
          Bell();
    }
}

void FindFontSelection (atom_name, justprobe)
    char *atom_name;
    Bool justprobe;
{
    static AtomPtr *atoms;
    static int atomCount = 0;
    AtomPtr *pAtom;
    int a;
    Atom target;

    if (!atom_name) atom_name = "PRIMARY";

    for (pAtom = atoms, a = atomCount; a; a--, pAtom++) {
      if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) break;
    }
    if (!a) {
      atoms = (AtomPtr*) XtRealloc ((char *)atoms,
                              sizeof(AtomPtr)*(atomCount+1));
      *(pAtom = &atoms[atomCount++]) = XmuMakeAtom(atom_name);
    }

    target = XmuInternAtom(XtDisplay(term), *pAtom);
    if (justprobe) {
      term->screen.menu_font_names[fontMenu_fontsel] = 
        XGetSelectionOwner(XtDisplay(term), target) ? _Font_Selected_ : NULL;
    } else {
      XtGetSelectionValue((Widget)term, target, XA_STRING,
                      DoSetSelectedFont, NULL,
                      XtLastTimestampProcessed(XtDisplay(term)));
    }
    return;
}


/* ARGSUSED */
void HandleSetFont(w, event, params, param_count)
    Widget w;
    XEvent *event;            /* unused */
    String *params;           /* unused */
    Cardinal *param_count;    /* unused */
{
    int fontnum;
    char *name1 = NULL, *name2 = NULL;

    if (*param_count == 0) {
      fontnum = fontMenu_fontdefault;
    } else {
      int maxparams = 1;            /* total number of params allowed */

      switch (params[0][0]) {
        case 'd': case 'D': case '0':
          fontnum = fontMenu_fontdefault; break;
        case '1':
          fontnum = fontMenu_font1; break;
        case '2':
          fontnum = fontMenu_font2; break;
        case '3':
          fontnum = fontMenu_font3; break;
        case '4':
          fontnum = fontMenu_font4; break;
        case '5':
          fontnum = fontMenu_font5; break;
        case '6':
          fontnum = fontMenu_font6; break;
        case 'e': case 'E':
          fontnum = fontMenu_fontescape; maxparams = 3; break;
        case 's': case 'S':
          fontnum = fontMenu_fontsel; maxparams = 2; break;
        default:
          Bell();
          return;
      }
      if (*param_count > maxparams) {      /* see if extra args given */
          Bell();
          return;
      }
      switch (*param_count) {       /* assign 'em */
        case 3:
          name2 = params[2];
          /* fall through */
        case 2:
          name1 = params[1];
          break;
      }
    }

    SetVTFont (fontnum, True, name1, name2);
}


void SetVTFont (i, doresize, name1, name2)
    int i;
    Bool doresize;
    char *name1, *name2;
{
    TScreen *screen = &term->screen;

    if (i < 0 || i >= NMENUFONTS) {
      Bell();
      return;
    }
    if (i == fontMenu_fontsel) {    /* go get the selection */
      FindFontSelection (name1, False);  /* name1 = atom, name2 is ignored */
      return;
    }
    if (!name1) name1 = screen->menu_font_names[i];
    if (!LoadNewFont(screen, name1, name2, term->misc.f_h, doresize, i)) {
      Bell();
    }
    return;
}


int LoadNewFont (screen, nfontname, bfontname, hfontname, doresize, fontnum)
    TScreen *screen;
    char *nfontname, *bfontname, *hfontname;
    Bool doresize;
    int fontnum;
{
    XFontStruct *nfs = NULL, *hfs = NULL, *bfs = NULL;
    XGCValues xgcv;
    unsigned long mask;
    GC new_normalGC = NULL, new_normalHGC = NULL, new_normalboldGC = NULL;
    GC new_reverseGC = NULL, new_reverseHGC = NULL, new_reverseboldGC = NULL;
    char *tmpname = NULL;
    extern GC fillgc;         /* HDraw... 에 쓰임 */
    /* by ysyun@bulsai.kaist.ac.kr */
    extern int font_ks_mode;
    extern int font_jo_mode;
    extern Bool can_use_hanja;
    /* end of insertion */
    char* hfont_fullname;

    /* gaemon 99/03/05 */
    char* hFontEncoding;
    int i, numMinus;
    extern int xstrcasecmp(); /* in util.c */
    extern int xstrncasecmp();


    if (!nfontname) return 0;
    if (!hfontname) return 0;

    if (fontnum == fontMenu_fontescape &&
      nfontname != screen->menu_font_names[fontnum]) {
      tmpname = (char *) malloc (strlen(nfontname) + 1);
      if (!tmpname) return 0;
      strcpy (tmpname, nfontname);
    }

    if (!(nfs = XLoadQueryFont (screen->display, nfontname))) goto bad;
    if (nfs->ascent + nfs->descent == 0  ||  nfs->max_bounds.width == 0)
      goto bad;   /* can't use a 0-sized font */

    if (!(hfs = XLoadQueryFont (screen->display, hfontname))) goto bad;

/* Begin guessFont */
    /* first, check if -ks or -kst is specified */
    if(font_ks_mode != -1) goto guessFontDone;

    /* should check resources too */
    if( term->misc.f_ks || term->misc.f_kst ) {
      font_ks_mode = term->misc.f_ks ? 0 : 
      (term->misc.f_kst ? 't' : -1 );
      if( font_ks_mode != -1 )
      can_use_hanja = True;
      goto guessFontDone;
    }

    /* or, we could judge by font encoding space... bleeech */
    if(hfs->min_char_or_byte2 == 33 && hfs->max_char_or_byte2 == 126
       && hfs->min_byte1 == 33 && hfs->max_byte1 == 125) {
      font_ks_mode = 0;
      can_use_hanja = 1;
      goto guessFontDone;
    }
    if(hfs->min_char_or_byte2 == 161 && hfs->max_char_or_byte2 == 254
       && hfs->min_byte1 == 161 && hfs->max_byte1 == 253) {
      font_ks_mode = 't';
      can_use_hanja = 1;
      goto guessFontDone;
    }

    /* and, we can do by encoding name */
    {
      XFontProp *pp;
      int i;
      Atom atom_FONT = XInternAtom(screen->display,"FONT",False);
      for (i=0, pp = hfs->properties; i < hfs->n_properties; i++, pp++)
          if (pp->name == atom_FONT) {
            hfont_fullname = XGetAtomName(screen->display, pp->card32);  
            break;
          }
    }
    if(hfont_fullname == NULL) {
      fprintf(stderr,"can't find the full name of hangul font %s\n",
          hfontname);
      Exit(1);
    }

    for(i=strlen(hfont_fullname)-1, numMinus=0;
        i > 0 && numMinus < 2; i--)
          if(hfont_fullname[i]=='-') numMinus++;

    hFontEncoding = hfont_fullname+i+2;

    if(!xstrcasecmp(hFontEncoding, "ksc5601.1987-0")) font_ks_mode = 0;
    else if(!xstrcasecmp(hFontEncoding, "ksx1001.1997-0")) font_ks_mode = 0;
    else if(!xstrcasecmp(hFontEncoding, "ksc5601.1987-1")) font_ks_mode = 't';
    else if(!xstrcasecmp(hFontEncoding, "johab844-1")) font_jo_mode = TRUE;
    else if(xstrncasecmp(hFontEncoding, "johab", 5)) {
      fprintf(stderr,"Can't identify hangul font type %s\n",hfont_fullname);
      fprintf(stderr,"Try specifing the font style by -ks/kst option\n");
      fprintf(stderr,"or *ksFont, *kstFont resource.\n");
    }

    free(hfont_fullname);

/* End guessFont */
guessFontDone:

    if (hfs->ascent + hfs->descent == 0  ||  hfs->max_bounds.width == 0)
      goto bad;   /* can't use a 0-sized font */
#if !defined(NO_PATCH_FONT_JOHABNZ) /* by hanmaum 1998.2.2 */
    if (font_ks_mode == -1 && font_jo_mode != True
            && hfs != NULL && hfs->per_char != NULL
            && hfs->per_char[1].width != 0) {
      register int i;
      int char_num;
      int minus_width = - hfs->per_char[1].width;

      char_num = (hfs->max_byte1 - hfs->min_byte1 + 1)
            * (hfs->max_char_or_byte2 - hfs->min_char_or_byte2 + 1);

      for (i = char_num-1; i >= 0; i--) { 
          if (hfs->per_char[i].width == minus_width) {
            font_no_zero_width_char = 1;
            font_minus_width_char_byte1 = i 
                  / (hfs->max_char_or_byte2 - hfs->min_char_or_byte2 + 1)
                  + hfs->min_byte1;
            font_minus_width_char_byte2 = i 
                  % (hfs->max_char_or_byte2 - hfs->min_char_or_byte2 + 1)
                  + hfs->min_char_or_byte2;
            break;
          }
      }
    }
#endif

    if (!(bfontname && 
        (bfs = XLoadQueryFont (screen->display, bfontname))))
      bfs = nfs;
    else
      if (bfs->ascent + bfs->descent == 0  ||  bfs->max_bounds.width == 0)
          goto bad;

    mask = (GCFont | GCForeground | GCBackground | GCGraphicsExposures |
          GCFunction);

    xgcv.font = nfs->fid;
    xgcv.foreground = screen->foreground;
    xgcv.background = term->core.background_pixel;
    xgcv.graphics_exposures = TRUE; /* default */
    xgcv.function = GXcopy;

    new_normalGC = XtGetGC((Widget)term, mask, &xgcv);
    if (!new_normalGC) goto bad;

    xgcv.font = hfs->fid;
    new_normalHGC = XtGetGC((Widget)term, mask, &xgcv);
    if (!new_normalHGC) goto bad;

    if (nfs == bfs) {               /* there is no bold font */
      new_normalboldGC = new_normalGC;
    } else {
      xgcv.font = bfs->fid;
      new_normalboldGC = XtGetGC((Widget)term, mask, &xgcv);
      if (!new_normalboldGC) goto bad;
    }

    xgcv.font = nfs->fid;
    xgcv.foreground = term->core.background_pixel;
    xgcv.background = screen->foreground;
    new_reverseGC = XtGetGC((Widget)term, mask, &xgcv);
    if (!new_reverseGC) goto bad;

    xgcv.font = hfs->fid;
    new_reverseHGC = XtGetGC((Widget)term, mask, &xgcv);
    if (!new_reverseHGC) goto bad;

    if (nfs == bfs) {               /* there is no bold font */
      new_reverseboldGC = new_reverseGC;
    } else {
      xgcv.font = bfs->fid;
      new_reverseboldGC = XtGetGC((Widget)term, mask, &xgcv);
      if (!new_reverseboldGC) goto bad;
    }
    if (fillgc == 0) {
      fillgc = XtGetGC((Widget)term, GCForeground, &xgcv);
    }

    if (screen->normalGC != screen->normalboldGC)
      XtReleaseGC ((Widget) term, screen->normalboldGC);
    XtReleaseGC ((Widget) term, screen->normalGC);
    XtReleaseGC ((Widget) term, screen->normalHGC);
    if (screen->reverseGC != screen->reverseboldGC)
      XtReleaseGC ((Widget) term, screen->reverseboldGC);
    XtReleaseGC ((Widget) term, screen->reverseGC);
    XtReleaseGC ((Widget) term, screen->reverseHGC);
    screen->normalGC = new_normalGC;
    screen->normalHGC = new_normalHGC;
    screen->normalboldGC = new_normalboldGC;
    screen->reverseGC = new_reverseGC;
    screen->reverseHGC = new_reverseHGC;
    screen->reverseboldGC = new_reverseboldGC;
    screen->fnt_norm = nfs;
    screen->fnt_hangul = hfs;
    screen->fnt_bold = bfs;

#if   1
    /* XXX keepBaseline or shift english characters. */
    if (term->misc.keepBaseline) {
        englift = 0;
    } else if( nfs->ascent > hfs->ascent && nfs->descent < hfs->descent ) {
        englift = nfs->descent - hfs->descent;
    } else if( nfs->ascent < hfs->ascent && nfs->descent > hfs->descent ) {
        englift = nfs->descent - hfs->descent;
    } else {
        englift = 0;
    }
    eng_ascent = nfs->ascent + englift;
    eng_descent = nfs->descent - englift;
    screen->ascent = (eng_ascent > hfs->ascent ? eng_ascent : hfs->ascent);
    screen->descent = (eng_descent > hfs->descent ? eng_descent
                                                   : hfs->descent);
#else /* 1 */
    screen->ascent = (nfs->ascent > hfs->ascent ? nfs->ascent : hfs->ascent);
    screen->descent = (nfs->descent > hfs->descent ? nfs->descent
                                       : hfs->descent);
#endif      /* 1 */

    screen->enbolden = (nfs == bfs);
    set_menu_font (False);
    screen->menu_font_number = fontnum;
    set_menu_font (True);
    if (tmpname) {                  /* if setting escape or sel */
      if (screen->menu_font_names[fontnum])
        free (screen->menu_font_names[fontnum]);
      screen->menu_font_names[fontnum] = tmpname;
      if (fontnum == fontMenu_fontescape) {
          set_sensitivity (term->screen.fontMenu,
                       fontMenuEntries[fontMenu_fontescape].widget,
                       TRUE);
      }
    }
    set_cursor_gcs (screen);
    update_font_info (screen, doresize);
    return 1;

  bad:
    if (tmpname) free (tmpname);
    if (new_normalGC)
      XtReleaseGC ((Widget) term, screen->normalGC);
    if (new_normalHGC)
      XtReleaseGC ((Widget) term, screen->normalHGC);
    if (new_normalGC && new_normalGC != new_normalboldGC)
      XtReleaseGC ((Widget) term, new_normalboldGC);
    if (new_reverseGC)
      XtReleaseGC ((Widget) term, new_reverseGC);
    if (new_reverseHGC)
      XtReleaseGC ((Widget) term, new_reverseHGC);
    if (new_reverseGC && new_reverseGC != new_reverseboldGC)
      XtReleaseGC ((Widget) term, new_reverseboldGC);
    if (nfs) XFreeFont (screen->display, nfs);
    if (hfs) XFreeFont (screen->display, hfs);
    if (nfs && bfs && nfs != bfs) XFreeFont (screen->display, bfs);
    return 0;
}


static void
update_font_info (screen, doresize)
    TScreen *screen;
    Bool doresize;
{
    int i, j, width, height, scrollbar_width;

    screen->fullVwin.f_width = (screen->fnt_norm->max_bounds.width
                        > screen->fnt_hangul->max_bounds.width/2
                        ? screen->fnt_norm->max_bounds.width
                        : screen->fnt_hangul->max_bounds.width/2);
    screen->fullVwin.f_height = (screen->ascent + screen->descent);
    scrollbar_width = (term->misc.scrollbar ? 
                   screen->scrollWidget->core.width +
                   screen->scrollWidget->core.border_width : 0);
    i = 2 * screen->border + scrollbar_width;
    j = 3 * screen->border + FontHeight(screen);
    width = (screen->max_col + 1) * screen->fullVwin.f_width + i;
    height = (screen->max_row + 1) * screen->fullVwin.f_height + j;
    screen->fullVwin.fullwidth = width;
    screen->fullVwin.fullheight = height;
    screen->fullVwin.width = width - i;
    screen->fullVwin.height = height - j;

    if (doresize) {
      if (VWindow(screen)) {
          XClearWindow (screen->display, VWindow(screen));
      }
      DoResizeScreen (term);        /* set to the new natural size */
      if (screen->scrollWidget)
        ResizeScrollBar (screen->scrollWidget, -1, -1,
                     Height(screen) + screen->border * 2);
      Redraw ();
    }
    set_vt_box (screen);
#if !defined(NO_PATCH_LINE_DRAW)
    set_vt_graphics(screen);
#endif
}

set_vt_box (screen)
      TScreen *screen;
{
      XPoint      *vp;

      vp = &VTbox[1];
      (vp++)->x = FontWidth(screen) - 1;
      (vp++)->y = FontHeight(screen) - 1;
      (vp++)->x = -(FontWidth(screen) - 1);
      vp->y = -(FontHeight(screen) - 1);
      screen->box = VTbox;

                        /* box for unseleted hangul cursor */
      vp = &hVTbox[1];
      (vp++)->x = FontWidth(screen) * 2 - 1;
      (vp++)->y = FontHeight(screen) - 1;
      (vp++)->x = -(FontWidth(screen) * 2 - 1);
      vp->y = -(FontHeight(screen) - 1);
      screen->hbox = hVTbox;
}

#if !defined(NO_PATCH_LINE_DRAW)
Pixmap vtgraphics[20]={0}; /* Bitmaps */
int *gr_mapping = NULL;
void
set_vt_graphics (screen)
      TScreen *screen;
{
      static GC bmgc=0;
      static Pixmap gray=0;
      XPoint pts[4];
      Display *dpy = screen->display;
      Window win = RootWindowOfScreen(XtScreen(term));
      int W = FontWidth(screen), H = FontHeight(screen);
      int w = W - 1, h = H - 1;
      int w2 = w/2, h2 = h/2;
      int i;
      static char gr_valid_code[] = " `ajklmnopqrstuvwx~";

      if (!gr_mapping) {
            gr_mapping = (int *)malloc(sizeof(int)*256);
            for(i = 0; i < 256; i++) {
                gr_mapping[i] = 1;
            }
            for(i=0;gr_valid_code[i];i++) {
                  gr_mapping[gr_valid_code[i]] = i + 1;
            }
      }

      if (!gray) {
            /*
            static char gray_bits[] = { 0x08, 0x02, 0x04, 0x01 };
            gray = XCreateBitmapFromData(dpy, win, gray_bits, 4, 4);
            */
            static char gray_bits[] = { 0x11, 0x44 };
            gray = XCreateBitmapFromData(dpy, win, gray_bits, 8, 2);
      }
      if (!bmgc) {
            bmgc = XCreateGC(dpy, gray, 0, NULL);
      }

      for (i = 1; i < 20; i ++) {
            if (vtgraphics[i]) {
                  XFreePixmap(dpy, vtgraphics[i]);
                  vtgraphics[i] = 0;
            }
      }

      vtgraphics[gr_mapping[' ']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['`']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['a']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['j']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['k']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['l']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['m']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['n']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['o']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['p']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['q']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['r']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['s']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['t']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['u']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['v']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['w']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['x']] = XCreatePixmap(dpy, win, W, H, 1);
      vtgraphics[gr_mapping['~']] = XCreatePixmap(dpy, win, W, H, 1);

      XSetForeground(dpy, bmgc, 0);
      XSetFillStyle(dpy, bmgc, FillSolid);
      for (i = 1; i < 20; i ++) {
            if (vtgraphics[i]) {
                  XFillRectangle(dpy, vtgraphics[i], bmgc, 0, 0, W, H);
            }
      }

      XSetForeground(dpy, bmgc, 1);

      pts[0].x = w2;   pts[0].y = 0;
      pts[1].x = 0;    pts[1].y = h2;
      pts[2].x = w2;   pts[2].y = h2*2;
      pts[3].x = w2*2; pts[3].y = h2;
      XFillPolygon(dpy, vtgraphics[gr_mapping['`']], bmgc, pts, 4, Nonconvex, CoordModeOrigin);

      XSetFillStyle(dpy, bmgc, FillStippled);
      XSetStipple(dpy, bmgc, gray);
      XFillRectangle(dpy, vtgraphics[gr_mapping['a']], bmgc, 0, 0, W, H);

      XSetFillStyle(dpy, bmgc, FillSolid);
      XDrawLine(dpy, vtgraphics[gr_mapping['j']], bmgc, 0, h2, w2, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['j']], bmgc, w2, 0, w2, h2);

      XDrawLine(dpy, vtgraphics[gr_mapping['k']], bmgc, 0, h2, w2, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['k']], bmgc, w2, h2, w2, h);

      XDrawLine(dpy, vtgraphics[gr_mapping['l']], bmgc, w2, h2, w, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['l']], bmgc, w2, h2, w2, h);

      XDrawLine(dpy, vtgraphics[gr_mapping['m']], bmgc, w2, h2, w, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['m']], bmgc, w2, 0, w2, h2);

      XDrawLine(dpy, vtgraphics[gr_mapping['n']], bmgc, 0, h2, w, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['n']], bmgc, w2, 0, w2, h);

      XDrawLine(dpy, vtgraphics[gr_mapping['o']], bmgc, 0, 0, w, 0);

      XDrawLine(dpy, vtgraphics[gr_mapping['p']], bmgc, 0, h/4, w, h/4);

      XDrawLine(dpy, vtgraphics[gr_mapping['q']], bmgc, 0, h2, w, h2);

      XDrawLine(dpy, vtgraphics[gr_mapping['r']], bmgc, 0, h*3/4, w, h*3/4);

      XDrawLine(dpy, vtgraphics[gr_mapping['s']], bmgc, 0, h, w, h);

      XDrawLine(dpy, vtgraphics[gr_mapping['t']], bmgc, w2, h2, w, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['t']], bmgc, w2, 0, w2, h);

      XDrawLine(dpy, vtgraphics[gr_mapping['u']], bmgc, 0, h2, w2, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['u']], bmgc, w2, 0, w2, h);

      XDrawLine(dpy, vtgraphics[gr_mapping['v']], bmgc, 0, h2, w, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['v']], bmgc, w2, 0, w2, h2);

      XDrawLine(dpy, vtgraphics[gr_mapping['w']], bmgc, 0, h2, w, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['w']], bmgc, w2, h2, w2, h);

      XDrawLine(dpy, vtgraphics[gr_mapping['x']], bmgc, w2, 0, w2, h);

      XDrawLine(dpy, vtgraphics[gr_mapping['~']], bmgc, w2-1, h2, w2+1, h2);
      XDrawLine(dpy, vtgraphics[gr_mapping['~']], bmgc, w2, h2-1, w2, h2+1);

}
#endif

set_cursor_gcs (screen)
    TScreen *screen;
{
    XGCValues xgcv;
    XGCValues xgcv_h;
    unsigned long mask;
    unsigned long cc = screen->cursorcolor;
    unsigned long fg = screen->foreground;
    unsigned long bg = term->core.background_pixel;
    GC new_cursorGC = NULL, new_reversecursorGC = NULL;
    GC new_cursorHGC = NULL, new_reversecursorHGC = NULL;
    GC new_cursoroutlineGC = NULL;

    /*
     * Let's see, there are three things that have "color":
     *
     *     background
     *     text
     *     cursorblock
     *
     * And, there are four situation when drawing a cursor, if we decide
     * that we like have a solid block of cursor color with the letter
     * that it is highlighting shown in the background color to make it
     * stand out:
     *
     *     selected window, normal video - background on cursor
     *     selected window, reverse video - foreground on cursor
     *     unselected window, normal video - foreground on background
     *     unselected window, reverse video - background on foreground
     *
     * Since the last two are really just normalGC and reverseGC, we only
     * need two new GC's.  Under monochrome, we get the same effect as
     * above by setting cursor color to foreground.
     */

    xgcv.font = screen->fnt_norm->fid;
    xgcv_h.font = screen->fnt_hangul->fid;
    mask = (GCForeground | GCBackground | GCFont);
    if (cc != fg && cc != bg) {
      /* we have a colored cursor */
      xgcv.foreground = fg;
      xgcv.background = cc;
      new_cursorGC = XtGetGC ((Widget) term, mask, &xgcv);
      xgcv_h.foreground = fg;
      xgcv_h.background = cc;
      new_cursorHGC = XtGetGC ((Widget) term, mask, &xgcv_h);

      if (screen->always_highlight) {
          new_reversecursorGC = (GC) 0;
          new_reversecursorHGC = (GC) 0;
          new_cursoroutlineGC = (GC) 0;
      } else {
          xgcv.foreground = bg;
          xgcv.background = cc;
          new_reversecursorGC = XtGetGC ((Widget) term, mask, &xgcv);
          xgcv_h.foreground = bg;
          xgcv_h.background = cc;
          new_reversecursorHGC = XtGetGC ((Widget) term, mask, &xgcv_h);
          xgcv.foreground = cc;
          xgcv.background = bg;
          new_cursoroutlineGC = XtGetGC ((Widget) term, mask, &xgcv);
            }
    } else {
      new_cursorGC = (GC) 0;
      new_reversecursorGC = (GC) 0;
      new_cursorHGC = (GC) 0;
      new_reversecursorHGC = (GC) 0;
      new_cursoroutlineGC = (GC) 0;
    }
    if (screen->cursorGC) XtReleaseGC ((Widget)term, screen->cursorGC);
    if (screen->reversecursorGC)
      XtReleaseGC ((Widget)term, screen->reversecursorGC);
    if (screen->cursoroutlineGC)
      XtReleaseGC ((Widget)term, screen->cursoroutlineGC);
    if (screen->cursorHGC) XtReleaseGC ((Widget)term, screen->cursorHGC);
    if (screen->reversecursorHGC)
      XtReleaseGC ((Widget)term, screen->reversecursorHGC);
    screen->cursorGC = new_cursorGC;
    screen->reversecursorGC = new_reversecursorGC;
    screen->cursoroutlineGC = new_cursoroutlineGC;
    screen->cursorHGC = new_cursorHGC;
    screen->reversecursorHGC = new_reversecursorHGC;
}

Generated by  Doxygen 1.6.0   Back to index