OSDN Git Service

can_use_graphics を current_graphics_mode に改名し、バグ回避のため型変更。 / Rename can_use_graphics...
[hengband/hengband.git] / src / main-x11.c
index 55d99eb..c7f4999 100644 (file)
@@ -1,4 +1,4 @@
-/* File: main-x11.c */
+/* File: main-x11.c */
 
 /*
  * Copyright (c) 1997 Ben Harrison, and others
@@ -9,17 +9,17 @@
  */
 
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
 /*
- * ÆüËܸì(EUC-JAPAN)Âбþ (-DJP)
- *    ¡¦´Á»ú¥Õ¥©¥ó¥È¤Î°·¤¤¤òÄɲÃ
- *    ¡¦ÆüËܸì¤ò´Þ¤àʸ»úÎó¤Îɽ¼¨¥ë¡¼¥Á¥ó XDrawMultiString() ¤ÎÄɲÃ
- *    ¡¦ÆüËܸì¤Îɽ¼¨Éý¤Ï¡¤¥Õ¥©¥ó¥È¤Î¾ðÊó¤Ë¤è¤é¤¹ASCII¥Õ¥©¥ó¥È¤Î2Çܤ˸ÇÄê
+ * 日本語(EUC-JAPAN)対応 (-DJP)
+ *    ・漢字フォントの扱いを追加
+ *    ・日本語を含む文字列の表示ルーチン XDrawMultiString() の追加
+ *    ・日本語の表示幅は,フォントの情報によらすASCIIフォントの2倍に固定
  *
- * Ì¤Âбþ
- *      EUCȾ³Ñ¤Î°·¤¤
+ * 未対応
+ *      EUC半角の扱い
  *
- * 1996/6/7  Íû ¹¸¿­ (ri@kuis.kyoto-u.ac.jp)
+ * 1996/6/7  李 晃伸 (ri@kuis.kyoto-u.ac.jp)
  */
 #endif
 /*
 #if 0
 char *XSetIMValues(XIM, ...); /* Hack for XFree86 4.0 */
 #endif
+#include <X11/Xatom.h>
 #endif /* __MAKEDEPEND__ */
 
-
+#include <iconv.h>
 /*
  * Include some helpful X11 code.
  */
@@ -348,6 +349,7 @@ struct infofnt
        cptr name;
 
        s16b wid;
+       s16b twid;
        s16b hgt;
        s16b asc;
 
@@ -385,7 +387,7 @@ struct infofnt
 /* Init an infowin by giving father as an (info_win*) (or NULL), and data */
 #define Infowin_init_dad(D,X,Y,W,H,B,FG,BG) \
        Infowin_init_data(((D) ? ((D)->win) : (Window)(None)), \
-                         X,Y,W,H,B,FG,BG)
+                         X,Y,W,H,B,FG,BG)
 
 
 /* Init a top level infowin by pos,size,bord,Colors */
@@ -454,7 +456,7 @@ static infowin *Infowin = (infowin*)(NULL);
 static infowin *Focuswin = (infowin*)(NULL);
 #endif
 static infoclr *Infoclr = (infoclr*)(NULL);
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
 static infofnt *Infofnt = (infofnt*)(NULL);
 static infofnt *Infokfnt = (infofnt*)(NULL);
 #else
@@ -467,9 +469,9 @@ static infofnt *Infofnt = (infofnt*)(NULL);
 /**** Generic code ****/
 
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
 #define Infokfnt_set(I) \
-        (Infokfnt = (I))
+       (Infokfnt = (I))
 #endif
 /*
  * Init the current metadpy, with various initialization stuff.
@@ -744,7 +746,7 @@ static errr Infowin_init_real(Window xid)
  *     If 'dad == None' assume 'dad == root'
  */
 static errr Infowin_init_data(Window dad, int x, int y, int w, int h,
-                              int b, Pixell fg, Pixell bg)
+                             int b, Pixell fg, Pixell bg)
 {
        Window xid;
 
@@ -934,7 +936,7 @@ static errr Infowin_fill(void)
 {
        /* Execute the request */
        XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc,
-                      0, 0, Infowin->w, Infowin->h);
+                      0, 0, Infowin->w, Infowin->h);
 
        /* Success */
        return (0);
@@ -1160,7 +1162,7 @@ static errr Infoclr_init_data(Pixell fg, Pixell bg, int op, int stip)
 
        /* Set up the GC mask */
        gc_mask = (GCFunction | GCBackground | GCForeground |
-                  GCFillStyle | GCGraphicsExposures);
+                  GCFillStyle | GCGraphicsExposures);
 
        /* Create the GC detailed above */
        gc = XCreateGC(Metadpy->dpy, Metadpy->root, gc_mask, &gcv);
@@ -1226,7 +1228,7 @@ static errr Infofnt_nuke(void)
 {
        infofnt *ifnt = Infofnt;
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        infofnt *ikfnt = Infokfnt;
 #endif
        /* Deal with 'name' */
@@ -1236,21 +1238,26 @@ static errr Infofnt_nuke(void)
                string_free(ifnt->name);
        }
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        if (ikfnt->name)
        {
                /* Free the name */
                string_free(ikfnt->name);
        }
 #endif
+
        /* Nuke info if needed */
        if (ifnt->nuke)
        {
                /* Free the font */
+#ifdef USE_FONTSET
+               XFreeFontSet(Metadpy->dpy, ifnt->info);
+#else
                XFreeFont(Metadpy->dpy, ifnt->info);
+#endif
        }
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        if (ikfnt->nuke)
        {
                /* Free the font */
@@ -1267,7 +1274,7 @@ static errr Infofnt_nuke(void)
 /*
  * Prepare a new 'infofnt'
  */
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
 static errr Infofnt_prepare(XFontStruct *info, XFontStruct *kinfo)
 #else
 #ifdef USE_FONTSET
@@ -1280,7 +1287,7 @@ static errr Infofnt_prepare(XFontStruct *info)
 {
        infofnt *ifnt = Infofnt;
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        infofnt *ikfnt = Infokfnt;
 #endif
        XCharStruct *cs;
@@ -1303,7 +1310,7 @@ static errr Infofnt_prepare(XFontStruct *info)
                if(ascent < (*fontinfo)->ascent) ascent = (*fontinfo)->ascent;
                if(descent < (*fontinfo)->descent) descent = (*fontinfo)->descent;
                if(((*fontinfo)->max_byte1) > 0){
-                       /* Â¿¥Ð¥¤¥Èʸ»ú¤Î¾ì¹ç¤ÏÉýȾʬ(ü¿ôÀÚ¤ê¾å¤²)¤Çɾ²Á¤¹¤ë */
+                       /* 多バイト文字の場合は幅半分(端数切り上げ)で評価する */
                        if(width < (cs->width+1)/2) width = (cs->width+1)/2;
                }else{
                        if(width < cs->width) width = cs->width;
@@ -1324,7 +1331,12 @@ static errr Infofnt_prepare(XFontStruct *info)
        ifnt->wid = cs->width;
 #endif
 
-#ifdef _JP
+       if (use_bigtile)
+               ifnt->twid = 2 * ifnt->wid;
+       else
+               ifnt->twid = ifnt->wid;
+
+#ifdef USE_JP_FONTSTRUCT
     /* Assign the struct */
     ikfnt->info = kinfo;
  
@@ -1355,7 +1367,7 @@ static errr Infofnt_prepare(XFontStruct *info)
 /*
  * Initialize a new 'infofnt'.
  */
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
 static errr Infofnt_init_real(XFontStruct *info, XFontStruct *kinfo)
 #else
 #ifdef USE_FONTSET
@@ -1369,17 +1381,17 @@ static errr Infofnt_init_real(XFontStruct *info)
        /* Wipe the thing */
        (void)WIPE(Infofnt, infofnt);
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        WIPE(Infokfnt, infofnt);
 #endif
        /* No nuking */
        Infofnt->nuke = 0;
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        Infokfnt->nuke = 0;
 #endif
        /* Attempt to prepare it */
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        return (Infofnt_prepare (info, kinfo));
 #else
        return (Infofnt_prepare(info));
@@ -1396,10 +1408,10 @@ static errr Infofnt_init_real(XFontStruct *info)
  * Inputs:
  *     name: The name of the requested Font
  */
-#ifdef _JP
-static errr Infofnt_init_data(cptr name, cptr kname)
+#ifdef USE_JP_FONTSTRUCT
+static void Infofnt_init_data(cptr name, cptr kname)
 #else
-static errr Infofnt_init_data(cptr name)
+static void Infofnt_init_data(cptr name)
 #endif
 
 {
@@ -1413,16 +1425,16 @@ static errr Infofnt_init_data(cptr name)
 #endif
 
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        XFontStruct *kinfo;
 #endif
        /*** Load the info Fresh, using the name ***/
 
        /* If the name is not given, report an error */
-       if (!name) return (-1);
+       if (!name || !*name) quit("Missing font!");
 
-#ifdef _JP
-       if (!kname) return (-1);
+#ifdef USE_JP_FONTSTRUCT
+       if (!kname || !*kname) quit("Missing kanji font!");
 #endif
        /* Attempt to load the font */
 #ifdef USE_FONTSET
@@ -1436,16 +1448,16 @@ static errr Infofnt_init_data(cptr name)
        }
 #else
        info = XLoadQueryFont(Metadpy->dpy, name);
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        kinfo = XLoadQueryFont(Metadpy->dpy, kname);
 #endif
 #endif
 
 
        /* The load failed, try to recover */
-       if (!info) return (-1);
-#ifdef _JP
-       if (!kinfo) return (-1);
+       if (!info) quit_fmt("Failed to find font:\"%s\"", name);
+#ifdef USE_JP_FONTSTRUCT
+       if (!kinfo) quit_fmt("Failed to find font:\"%s\"", kname);
 #endif
 
 
@@ -1455,11 +1467,11 @@ static errr Infofnt_init_data(cptr name)
        /* Wipe the thing */
        (void)WIPE(Infofnt, infofnt);
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        WIPE(Infokfnt, infofnt);
 #endif
        /* Attempt to prepare it */
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        if (Infofnt_prepare(info, kinfo))
 #else
        if (Infofnt_prepare(info))
@@ -1471,34 +1483,31 @@ static errr Infofnt_init_data(cptr name)
                XFreeFontSet(Metadpy->dpy, info);
 #else
                XFreeFont(Metadpy->dpy, info);
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
                XFreeFont(Metadpy->dpy, kinfo);
 #endif
 #endif
                /* Fail */
-               return (-1);
+               quit_fmt("Failed to prepare font:\"%s\"", name);
        }
 
        /* Save a copy of the font name */
        Infofnt->name = string_make(name);
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        Infokfnt->name = string_make(kname);
 #endif
 
        /* Mark it as nukable */
        Infofnt->nuke = 1;
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        Infokfnt->nuke = 1;
 #endif
-
-       /* Success */
-       return (0);
 }
 
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
 /*
- * EUCÆüËܸ쥳¡¼¥É¤ò´Þ¤àʸ»úÎó¤òɽ¼¨¤¹¤ë (Xlib)
+ * EUC日本語コードを含む文字列を表示する (Xlib)
  */
 static void
 XDrawMultiString(display,d,gc, x, y, string, len, afont, 
@@ -1526,65 +1535,65 @@ XDrawMultiString(display,d,gc, x, y, string, len, afont,
 
 #ifdef TOFU      
       if ( (*str) == 0x7f ) {
-          
-          /* 0x7F¤Ï¢£¤Ç·è¤áÂǤÁ */
-          
-          /* Ï¢Â³¤¹¤ë0x7F¤ÎŤµ¤ò¸¡½Ð */
-          slen = 0;
-          while ( str < endp && (*str) == 0x7f ) {
-              slen++; 
+         
+         /* 0x7Fは■で決め打ち */
+         
+         /* 連続する0x7Fの長さを検出 */
+         slen = 0;
+         while ( str < endp && (*str) == 0x7f ) {
+             slen++; 
              str++;
-          }
-          
-          /* ÉÁ²è */
-          XFillRectangle( display, d, gc, x, y-afont_ascent, 
-                          slen * afont_width, afont_height);
+         }
+         
+         /* 描画 */
+         XFillRectangle( display, d, gc, x, y-afont_ascent, 
+                         slen * afont_width, afont_height);
  
-          /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
-          x += afont_width * slen;
+         /* ポインタを進める */
+         x += afont_width * slen;
       } 
       else  
 #endif
       if ( iskanji(*str) ) {
-          
-          /* UJIS¤Î»Ï¤Þ¤ê */
-          
-          /* Ï¢Â³¤¹¤ëUJISʸ»ú¤ÎŤµ¤ò¸¡½Ð */
-          slen = 0;
-          while ( str < endp && *str && iskanji(*str) ) {
-              kanji[slen].byte1 = *str++ & 0x7f;
-              kanji[slen++].byte2 = *str++ & 0x7f;
-          }
-          
-          /* ÉÁ²è */
-          XSetFont( display, gc, kfont->fid );
-          XDrawImageString16( display, d, gc, x, y, kanji, slen );
+         
+         /* UJISの始まり */
+         
+         /* 連続するUJIS文字の長さを検出 */
+         slen = 0;
+         while ( str < endp && *str && iskanji(*str) ) {
+             kanji[slen].byte1 = *str++ & 0x7f;
+             kanji[slen++].byte2 = *str++ & 0x7f;
+         }
+         
+         /* 描画 */
+         XSetFont( display, gc, kfont->fid );
+         XDrawImageString16( display, d, gc, x, y, kanji, slen );
 
  
-          /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
-          x += kfont_width * slen;
-          
+         /* ポインタを進める */
+         x += kfont_width * slen;
+         
       } else {
-          
-          /* Èó´Á»ú(=ASCII¤È²¾Äê)¤Î»Ï¤Þ¤ê */
-          
-          /* Ï¢Â³¤¹¤ëASCIIʸ»ú¤ò¸¡½Ð */
-          p = str;
-          slen = 0;
-          while ( str < endp && *str && !iskanji(*str) ) {
+         
+         /* 非漢字(=ASCIIと仮定)の始まり */
+         
+         /* 連続するASCII文字を検出 */
+         p = str;
+         slen = 0;
+         while ( str < endp && *str && !iskanji(*str) ) {
 #ifdef TOFU
-              if (*str == 0x7f)break;
-#endif
-              str++;
-              slen++;
-          }
-          
-          /* ÉÁ²è */
-          XSetFont( display, gc, afont->fid );
-          XDrawImageString( display, d, gc, x, y, p, slen );
-          
-          /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
-          x += afont_width * slen;
+             if (*str == 0x7f)break;
+#endif
+             str++;
+             slen++;
+         }
+         
+         /* 描画 */
+         XSetFont( display, gc, afont->fid );
+         XDrawImageString( display, d, gc, x, y, p, slen );
+         
+         /* ポインタを進める */
+         x += afont_width * slen;
       }
     }
 }
@@ -1606,7 +1615,6 @@ static errr Infofnt_text_std(int x, int y, cptr str, int len)
        /* Get the length of the string */
        if (len < 0) len = strlen(str);
 
-
        /*** Decide where to place the string, vertically ***/
 
        /* Ignore Vertical Justifications */
@@ -1621,19 +1629,17 @@ static errr Infofnt_text_std(int x, int y, cptr str, int len)
 
        /*** Actually draw 'str' onto the infowin ***/
 
-#if 1
-#ifndef JP
+#ifndef USE_FONTSET
        /* Be sure the correct font is ready */
        XSetFont(Metadpy->dpy, Infoclr->gc, Infofnt->info->fid);
 #endif
-#endif
 
        /*** Handle the fake mono we can enforce on fonts ***/
 
        /* Monotize the font */
        if (Infofnt->mono)
        {
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
                /* Be sure the correct font is ready */
                XSetFont(Metadpy->dpy, Infoclr->gc, Infofnt->info->fid);
 #endif
@@ -1642,7 +1648,7 @@ static errr Infofnt_text_std(int x, int y, cptr str, int len)
                {
                        /* Note that the Infoclr is set up to contain the Infofnt */
                        XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
-                                        x + i * Infofnt->wid + Infofnt->off, y, str + i, 1);
+                                        x + i * Infofnt->wid + Infofnt->off, y, str + i, 1);
                }
        }
 
@@ -1650,20 +1656,30 @@ static errr Infofnt_text_std(int x, int y, cptr str, int len)
        else
        {
                /* Note that the Infoclr is set up to contain the Infofnt */
-#ifdef _JP
-               /* ´Á»ú¥Õ¥©¥ó¥È¤Îɽ¼¨Éý¤Ï ASCII¥Õ¥©¥ó¥È¤Î2Çܤ˸ÇÄê */
+#ifdef USE_JP_FONTSTRUCT
+               /* 漢字フォントの表示幅は ASCIIフォントの2倍に固定 */
                XDrawMultiString(Metadpy->dpy, Infowin->win, Infoclr->gc,
-                                x, y, str, len,
-                                Infofnt->info, Infofnt->wid, Infofnt->hgt,
-                                 Infofnt->asc, 
-                                 Infokfnt->info, Infofnt->wid * 2);
+                                x, y, str, len,
+                                Infofnt->info, Infofnt->wid, Infofnt->hgt,
+                                Infofnt->asc, 
+                                Infokfnt->info, Infofnt->wid * 2);
 #else
 #ifdef USE_FONTSET
+
+               iconv_t cd = iconv_open("UTF-8", "EUC-JP");
+               size_t inlen = len;
+               size_t outlen = len * 2;
+               char *kanji = malloc(outlen);
+               char *sp = str; char *kp = kanji;
+               size_t n = iconv(cd, &sp, &inlen, &kp, &outlen);
+               iconv_close(cd);
+
                XmbDrawImageString(Metadpy->dpy, Infowin->win, Infofnt->info,
-                                  Infoclr->gc, x, y, str, len);
+                               Infoclr->gc, x, y, kanji, kp-kanji);
+               free(kanji);
 #else
                XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
-                                x, y, str, len);
+                                x, y, str, len);
 #endif
 #endif
 
@@ -1754,7 +1770,7 @@ struct term_data
        term t;
 
        infofnt *fnt;
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        infofnt *kfnt;
 #endif
 
@@ -1765,15 +1781,11 @@ struct term_data
 
        XImage *tiles;
 
-#ifdef USE_TRANSPARENCY
-
        /* Tempory storage for overlaying tiles. */
        XImage *TmpImage;
 
 #endif
 
-#endif
-
 };
 
 
@@ -1788,6 +1800,38 @@ struct term_data
 static term_data data[MAX_TERM_DATA];
 
 
+/* Use short names for the most commonly used elements of various structures. */
+#define DPY (Metadpy->dpy)
+#define WIN (Infowin->win)
+
+
+/* Describe a set of co-ordinates. */
+typedef struct co_ord co_ord;
+struct co_ord
+{
+       int x;
+       int y;
+};
+
+
+/*
+ * A special structure to store information about the text currently
+ * selected.
+ */
+typedef struct x11_selection_type x11_selection_type;
+struct x11_selection_type
+{
+       bool select; /* The selection is currently in use. */
+       bool drawn; /* The selection is currently displayed. */
+       term *t; /* The window where the selection is found. */
+       co_ord init; /* The starting co-ordinates. */
+       co_ord cur; /* The end co-ordinates (the current ones if still copying). */
+       co_ord old; /* The previous end co-ordinates. */
+       Time time; /* The time at which the selection was finalised. */
+};
+
+static x11_selection_type s_ptr[1];
+
 
 /*
  * Process a keypress event
@@ -1890,6 +1934,10 @@ static void react_keypress(XKeyEvent *xev)
                }
 
                case XK_Delete:
+               {
+                       Term_keypress(0x7f);
+                       return;
+               }
                case XK_BackSpace:
                {
                        Term_keypress('\010');
@@ -1902,18 +1950,18 @@ static void react_keypress(XKeyEvent *xev)
        if (ks)
        {
                sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
-                       mc ? "N" : "", ms ? "S" : "",
-                       mo ? "O" : "", mx ? "M" : "",
-                       (unsigned long)(ks), 13);
+                       mc ? "N" : "", ms ? "S" : "",
+                       mo ? "O" : "", mx ? "M" : "",
+                       (unsigned long)(ks), 13);
        }
 
        /* Hack -- Use the Keycode */
        else
        {
                sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
-                       mc ? "N" : "", ms ? "S" : "",
-                       mo ? "O" : "", mx ? "M" : "",
-                       ev->keycode, 13);
+                       mc ? "N" : "", ms ? "S" : "",
+                       mo ? "O" : "", mx ? "M" : "",
+                       ev->keycode, 13);
        }
 
        /* Enqueue the "macro trigger" string */
@@ -1929,6 +1977,528 @@ static void react_keypress(XKeyEvent *xev)
 }
 
 
+/*
+ * Find the square a particular pixel is part of.
+ */
+static void pixel_to_square(int * const x, int * const y,
+       const int ox, const int oy)
+{
+       (*x) = (ox - Infowin->ox) / Infofnt->wid;
+       (*y) = (oy - Infowin->oy) / Infofnt->hgt;
+}
+
+/*
+ * Find the pixel at the top-left corner of a square.
+ */
+static void square_to_pixel(int * const x, int * const y,
+       const int ox, const int oy)
+{
+       (*x) = ox * Infofnt->wid + Infowin->ox;
+       (*y) = oy * Infofnt->hgt + Infowin->oy;
+}
+
+/*
+ * Convert co-ordinates from starting corner/opposite corner to minimum/maximum.
+ */
+static void sort_co_ord(co_ord *min, co_ord *max,
+       const co_ord *b, const co_ord *a)
+{
+       min->x = MIN(a->x, b->x);
+       min->y = MIN(a->y, b->y);
+       max->x = MAX(a->x, b->x);
+       max->y = MAX(a->y, b->y);
+}
+
+/*
+ * Remove the selection by redrawing it.
+ */
+static void mark_selection_clear(int x1, int y1, int x2, int y2)
+{
+       Term_redraw_section(x1,y1,x2,y2);
+}
+
+/*
+ * Select an area by drawing a grey box around it.
+ * NB. These two functions can cause flicker as the selection is modified,
+ * as the game redraws the entire marked section.
+ */
+static void mark_selection_mark(int x1, int y1, int x2, int y2)
+{
+       square_to_pixel(&x1, &y1, x1, y1);
+       square_to_pixel(&x2, &y2, x2, y2);
+       XDrawRectangle(Metadpy->dpy, Infowin->win, clr[2]->gc, x1, y1,
+               x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
+}
+
+/*
+ * Mark a selection by drawing boxes around it (for now).
+ */
+static void mark_selection(void)
+{
+       co_ord min, max;
+       term *old = Term;
+       bool draw = s_ptr->select;
+       bool clear = s_ptr->drawn;
+
+       /* Open the correct term if necessary. */
+       if (s_ptr->t != old) Term_activate(s_ptr->t);
+
+       if (clear)
+       {
+               sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->old);
+               mark_selection_clear(min.x, min.y, max.x, max.y);
+       }
+       if (draw)
+       {
+               sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
+               mark_selection_mark(min.x, min.y, max.x, max.y);
+       }
+
+       /* Finish on the current term. */
+       if (s_ptr->t != old) Term_activate(old);
+
+       s_ptr->old.x = s_ptr->cur.x;
+       s_ptr->old.y = s_ptr->cur.y;
+       s_ptr->drawn = s_ptr->select;
+}
+
+/*
+ * Forget a selection for one reason or another.
+ */
+static void copy_x11_release(void)
+{
+       /* Deselect the current selection. */
+       s_ptr->select = FALSE;
+
+       /* Remove its graphical represesntation. */
+       mark_selection();
+}
+
+/*
+ * Start to select some text on the screen.
+ */
+static void copy_x11_start(int x, int y)
+{
+       if (s_ptr->select) copy_x11_release();
+
+       /* Remember where the selection started. */
+       s_ptr->t = Term;
+       s_ptr->init.x = s_ptr->cur.x = s_ptr->old.x = x;
+       s_ptr->init.y = s_ptr->cur.y = s_ptr->old.y = y;
+}
+
+/*
+ * Respond to movement of the mouse when selecting text.
+ */
+static void copy_x11_cont(int x, int y, unsigned int buttons)
+{
+       /* Use the nearest square within bounds if the mouse is outside. */
+       x = MIN(MAX(x, 0), Term->wid-1);
+       y = MIN(MAX(y, 0), Term->hgt-1);
+
+       /* The left mouse button isn't pressed. */
+       if (~buttons & Button1Mask) return;
+
+       /* Not a selection in this window. */
+       if (s_ptr->t != Term) return;
+
+       /* Not enough movement. */
+       if (x == s_ptr->old.x && y == s_ptr->old.y && s_ptr->select) return;
+
+       /* Something is being selected. */
+       s_ptr->select = TRUE;
+
+       /* Track the selection. */
+       s_ptr->cur.x = x;
+       s_ptr->cur.y = y;
+
+       /* Hack - display it inefficiently. */
+       mark_selection();
+}
+
+/*
+ * Respond to release of the left mouse button by putting the selected text in
+ * the primary buffer.
+ */
+static void copy_x11_end(const Time time)
+{
+       /* No selection. */
+       if (!s_ptr->select) return;
+
+       /* Not a selection in this window. */
+       if (s_ptr->t != Term) return;
+
+       /* Remember when the selection was finalised. */
+       s_ptr->time = time;
+
+       /* Acquire the primary selection. */
+       XSetSelectionOwner(Metadpy->dpy, XA_PRIMARY, Infowin->win, time);
+       if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) != Infowin->win)
+       {
+               /* Failed to acquire the selection, so forget it. */
+               /* bell("Failed to acquire primary buffer."); */
+               s_ptr->select = FALSE;
+               mark_selection();
+       }
+}
+
+
+static Atom xa_targets, xa_timestamp, xa_text, xa_compound_text;
+
+/*
+ * Set the required variable atoms at start-up to avoid errors later.
+ */
+static void set_atoms(void)
+{
+       xa_targets = XInternAtom(DPY, "TARGETS", False);
+       xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
+       xa_text = XInternAtom(DPY, "TEXT", False);
+       xa_compound_text = XInternAtom(DPY, "COMPOUND_TEXT", False);
+}
+
+
+static Atom request_target = 0;
+
+/*
+ * Send a message to request that the PRIMARY buffer be sent here.
+ */
+static void paste_x11_request(Atom target, const Time time)
+{
+       /*
+        * It's from some sample programs on the web.
+        * What does it mean? -- XXX
+        */
+       Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
+
+       /* Check the owner. */
+       if (XGetSelectionOwner(DPY, XA_PRIMARY) == None)
+       {
+               /* No selection. */
+               /* bell("No selection found."); */
+               return;
+       }
+
+       request_target = target;
+    
+       /* Request the event */
+       XConvertSelection(DPY, XA_PRIMARY, target, property, WIN, time);
+}
+
+
+/*
+ * Add the contents of the PRIMARY buffer to the input queue.
+ *
+ * Hack - This doesn't use the "time" of the event, and so accepts anything a
+ * client tries to send it.
+ */
+static void paste_x11_accept(const XSelectionEvent *ptr)
+{
+       unsigned long left;
+       const long offset = 0;
+       const long length = 32000;
+       XTextProperty xtextproperty;
+       errr err = 0;
+
+       /*
+        * It's from some sample programs on the web.
+        * What does it mean? -- XXX
+        */
+       Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
+
+
+       /* Failure. */
+       if (ptr->property == None)
+       {
+               if (request_target == xa_compound_text)
+               {
+                       /* Re-request as STRING */
+                       paste_x11_request(XA_STRING, ptr->time);
+               }
+               else
+               {
+                       request_target = 0;
+                       plog("Paste failure (remote client could not send).");
+               }
+               return;
+       }
+
+       if (ptr->selection != XA_PRIMARY)
+       {
+               plog("Paste failure (remote client did not send primary selection).");
+               return;
+       }
+
+       if (ptr->target != request_target)
+       {
+               plog("Paste failure (selection in unknown format).");
+               return;
+       }
+
+       /* Get text */
+       if (XGetWindowProperty(Metadpy->dpy, Infowin->win, property, offset,
+                              length, TRUE, request_target,
+                              &xtextproperty.encoding,
+                              &xtextproperty.format,
+                              &xtextproperty.nitems,
+                              &left,
+                              &xtextproperty.value)
+           != Success)
+       {
+               /* Failure */
+               return;
+       }
+
+       if (request_target == xa_compound_text)
+       {
+               char **list;
+               int count;
+               
+               XmbTextPropertyToTextList(DPY, &xtextproperty, &list, &count);
+
+               if (list)
+               {
+                       int i;
+
+                       for (i = 0; i < count; i++)
+                       {
+                               /* Paste the text. */
+                               err = type_string(list[i], 0);
+
+                               if (err) break;
+                       }
+
+                       /* Free the string */
+                       XFreeStringList(list);
+               }
+       }
+       else /* if (request_target == XA_STRING) */
+       {
+               /* Paste the text. */
+               err = type_string((char *)xtextproperty.value, xtextproperty.nitems);
+       }
+
+       /* Free the data pasted. */
+       XFree(xtextproperty.value); 
+
+       /* No room. */
+       if (err)
+       {
+               plog("Paste failure (too much text selected).");
+       }
+}
+
+
+/*
+ * Add a character to a string in preparation for sending it to another
+ * client as a STRING.
+ * This doesn't change anything, as clients tend not to have difficulty in
+ * receiving this format (although the standard specifies a restricted set).
+ * Strings do not have a colour.
+ */
+static bool paste_x11_send_text(XSelectionRequestEvent *rq)
+{
+       char buf[1024];
+       char *list[1000];
+       co_ord max, min;
+       int x,y,l,n;
+       byte a;
+       char c;
+
+       /* Too old, or incorrect call. */
+       if (rq->time < s_ptr->time) return FALSE;
+
+       /* Work out which way around to paste. */
+       sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
+
+       /* Paranoia. */
+       if (XGetSelectionOwner(DPY, XA_PRIMARY) != WIN)
+       {
+               /* bell("Someone stole my selection!"); */
+               return FALSE;
+       }
+
+       /* Delete the old value of the property. */
+       XDeleteProperty(DPY, rq->requestor, rq->property);
+
+       for (n = 0, y = 0; y < Term->hgt; y++)
+       {
+#ifdef JP
+               int kanji = 0;
+#endif
+               if (y < min.y) continue;
+               if (y > max.y) break;
+
+               for (l = 0, x = 0; x < Term->wid; x++)
+               {
+#ifdef JP
+                       if (x > max.x) break;
+
+                       /* Find the character. */
+                       Term_what(x, y, &a, &c);
+
+                       if (1 == kanji) kanji = 2;
+                       else if (iskanji(c)) kanji = 1;
+                       else kanji = 0;
+
+                       if (x < min.x) continue;
+
+                       /*
+                        * A single kanji character was divided in two...
+                        * Delete the garbage.
+                        */
+                       if ((2 == kanji && x == min.x) ||
+                           (1 == kanji && x == max.x))
+                               c = ' ';
+#else
+                       if (x > max.x) break;
+                       if (x < min.x) continue;
+
+                       /* Find the character. */
+                       Term_what(x, y, &a, &c);
+#endif
+
+                       /* Add it. */
+                       buf[l] = c;
+                       l++;
+               }
+
+               /* Ignore trailing spaces */
+               while (buf[l-1] == ' ') l--;
+
+               /* Terminate all line unless it's single line. */
+               if (min.y != max.y)
+               {
+                       buf[l] = '\n';
+                       l++;
+               }
+
+               /* End of string */
+               buf[l] = '\0';
+
+               list[n++] = (char *)string_make(buf);
+       }
+
+       /* End of the list */
+       list[n] = NULL;
+
+
+       if (rq->target == XA_STRING)
+       {
+               for (n = 0; list[n]; n++)
+               {
+                       /* Send the (non-empty) string. */
+                       XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
+                                       PropModeAppend, (unsigned char *)list[n], strlen(list[n]));
+               }
+       }
+
+       else if (rq->target == xa_text || 
+                rq->target == xa_compound_text)
+       {
+               XTextProperty text_prop;
+               XICCEncodingStyle style;
+
+               if (rq->target == xa_text)
+                       style = XStdICCTextStyle;
+               else /* if (rq->target == xa_compound_text) */
+                       style = XCompoundTextStyle;
+
+               if (Success ==
+                   XmbTextListToTextProperty(DPY, list, n, style, &text_prop))
+               {
+                       /* Send the compound text */
+                       XChangeProperty(DPY,
+                                       rq->requestor,
+                                       rq->property,
+                                       text_prop.encoding,
+                                       text_prop.format,
+                                       PropModeAppend,
+                                       text_prop.value,
+                                       text_prop.nitems);
+                               
+                       /* Free the data. */
+                       XFree(text_prop.value);
+               }
+       }
+
+       /* Free the list of strings */
+       for (n = 0; list[n]; n++)
+       {
+               string_free(list[n]);
+       }
+
+       return TRUE;
+}
+
+/*
+ * Send some text requested by another X client.
+ */
+static void paste_x11_send(XSelectionRequestEvent *rq)
+{
+       XEvent event;
+       XSelectionEvent *ptr = &(event.xselection);
+
+       /* Set the event parameters. */
+       ptr->type = SelectionNotify;
+       ptr->property = rq->property;
+       ptr->display = rq->display;
+       ptr->requestor = rq->requestor;
+       ptr->selection = rq->selection;
+       ptr->target = rq->target;
+       ptr->time = rq->time;
+
+       /* Paste the appropriate information for each target type.
+        * Note that this currently rejects MULTIPLE targets.
+        */
+
+       if (rq->target == XA_STRING ||
+           rq->target == xa_text ||
+           rq->target == xa_compound_text)
+       {
+               if (!paste_x11_send_text(rq))
+                       ptr->property = None;
+       }
+       else if (rq->target == xa_targets)
+       {
+               Atom target_list[4];
+               target_list[0] = XA_STRING;
+               target_list[1] = xa_text;
+               target_list[2] = xa_compound_text;
+               target_list[3] = xa_targets;
+               XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
+                       (8 * sizeof(target_list[0])), PropModeReplace,
+                       (unsigned char *)target_list,
+                       (sizeof(target_list) / sizeof(target_list[0])));
+       }
+       else if (rq->target == xa_timestamp)
+       {
+               XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
+                       (8 * sizeof(Time)), PropModeReplace,
+                       (unsigned char *)s_ptr->time, 1);
+       }
+       else
+       {
+               ptr->property = None;
+       }
+
+       /* Send whatever event we're left with. */
+       XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
+}
+
+
+/*
+ * Handle various events conditional on presses of a mouse button.
+ */
+static void handle_button(Time time, int x, int y, int button,
+       bool press)
+{
+       /* The co-ordinates are only used in Angband format. */
+       pixel_to_square(&x, &y, x, y);
+
+       if (press && button == 1) copy_x11_start(x, y);
+       if (!press && button == 1) copy_x11_end(time);
+       if (!press && button == 2) paste_x11_request(xa_compound_text, time);
+}
 
 
 /*
@@ -1943,7 +2513,7 @@ static errr CheckEvent(bool wait)
        term_data *td = NULL;
        infowin *iwin = NULL;
 
-       int i, x, y;
+       int i;
 
 #ifdef USE_XIM
  redo_checkevent:
@@ -1952,11 +2522,18 @@ static errr CheckEvent(bool wait)
        /* Do not wait unless requested */
        if (!wait && !XPending(Metadpy->dpy)) return (1);
 
+       /*
+        * Hack - redraw the selection, if needed.
+        * This doesn't actually check that one of its squares was drawn to,
+        * only that this may have happened.
+        */
+       if (s_ptr->select && !s_ptr->drawn) mark_selection();
+
        /* Load the Event */
        XNextEvent(Metadpy->dpy, xev);
 
 #ifdef USE_XIM
-// #define DEBUG_EVENT
+/* #define DEBUG_EVENT */
 #ifdef DEBUG_EVENT
        {
                printf("event: type=%d", xev->type);
@@ -2035,13 +2612,16 @@ static errr CheckEvent(bool wait)
        /* Switch on the Type */
        switch (xev->type)
        {
-
-#if 0
-
                case ButtonPress:
                case ButtonRelease:
                {
-                       int z = 0;
+                       bool press = (xev->type == ButtonPress);
+
+                       /* Where is the mouse */
+                       int x = xev->xbutton.x;
+                       int y = xev->xbutton.y;
+
+                       int z;
 
                        /* Which button is involved */
                        if (xev->xbutton.button == Button1) z = 1;
@@ -2049,12 +2629,10 @@ static errr CheckEvent(bool wait)
                        else if (xev->xbutton.button == Button3) z = 3;
                        else if (xev->xbutton.button == Button4) z = 4;
                        else if (xev->xbutton.button == Button5) z = 5;
-
-                       /* Where is the mouse */
-                       x = xev->xbutton.x;
-                       y = xev->xbutton.y;
+                       else z = 0;
 
                        /* XXX Handle */
+                       handle_button(xev->xbutton.time, x, y, z, press);
 
                        break;
                }
@@ -2062,10 +2640,6 @@ static errr CheckEvent(bool wait)
                case EnterNotify:
                case LeaveNotify:
                {
-                       /* Where is the mouse */
-                       x = xev->xcrossing.x;
-                       y = xev->xcrossing.y;
-
                        /* XXX Handle */
 
                        break;
@@ -2074,28 +2648,51 @@ static errr CheckEvent(bool wait)
                case MotionNotify:
                {
                        /* Where is the mouse */
-                       x = xev->xmotion.x;
-                       y = xev->xmotion.y;
+                       int x = xev->xmotion.x;
+                       int y = xev->xmotion.y;
+                       unsigned int z = xev->xmotion.state;
+
+                       /* Convert to co-ordinates Angband understands. */
+                       pixel_to_square(&x, &y, x, y);
+
+                       /* Highlight the current square, if appropriate. */
+                       /* highlight_square(window, y, x); */
+
+                       /* Alter the selection if appropriate. */
+                       copy_x11_cont(x, y, z);
 
                        /* XXX Handle */
 
                        break;
                }
 
+               case SelectionNotify:
+               {
+                       paste_x11_accept(&(xev->xselection));
+                       break;
+               }
+
+               case SelectionRequest:
+               {
+                       paste_x11_send(&(xev->xselectionrequest));
+                       break;
+               }
+
+               case SelectionClear:
+               {
+                       s_ptr->select = FALSE;
+                       mark_selection();
+                       break;
+               }
+
                case KeyRelease:
                {
                        /* Nothing */
                        break;
                }
 
-#endif
-
                case KeyPress:
                {
-                       /* Save the mouse location */
-                       x = xev->xkey.x;
-                       y = xev->xkey.y;
-
                        /* Hack -- use "old" term */
                        Term_activate(&old_td->t);
 
@@ -2163,14 +2760,17 @@ static errr CheckEvent(bool wait)
                        cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
                        rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
 
-                       /* Paranoia */
-                       if (td == &data[0]) cols = 80;
-                       if (td == &data[0]) rows = 24;
-
                        /* Hack -- minimal size */
                        if (cols < 1) cols = 1;
                        if (rows < 1) rows = 1;
 
+                       if (td == &data[0])
+                       {
+                               /* Hack the main window must be at least 80x24 */
+                               if (cols < 80) cols = 80;
+                               if (rows < 24) rows = 24;
+                       }
+
                        /* Desired size of window */
                        wid = cols * td->fnt->wid + (ox + ox);
                        hgt = rows * td->fnt->hgt + (oy + oy);
@@ -2202,7 +2802,7 @@ static errr CheckEvent(bool wait)
                        if(iwin->xic){
                                XUnsetICFocus(iwin->xic);
                        }
-                       // Focuswin = NULL;
+                       /* Focuswin = NULL;*/
                        break;
                }
 #endif
@@ -2221,6 +2821,80 @@ static errr CheckEvent(bool wait)
 }
 
 
+#ifdef USE_SOUND
+
+/*
+ * An array of sound file names
+ */
+static cptr sound_file[SOUND_MAX];
+
+/*
+ * Check for existance of a file
+ */
+static bool check_file(cptr s)
+{
+       FILE *fff;
+
+       fff = fopen(s, "r");
+       if (!fff) return (FALSE);
+       
+       fclose(fff);
+       return (TRUE);
+}
+
+/*
+ * Initialize sound
+ */
+static void init_sound(void)
+{
+       int i;
+       char wav[128];
+       char buf[1024];
+       char dir_xtra_sound[1024];
+               
+       /* Build the "sound" path */
+       path_build(dir_xtra_sound, sizeof(dir_xtra_sound), ANGBAND_DIR_XTRA, "sound");
+               
+       /* Prepare the sounds */
+       for (i = 1; i < SOUND_MAX; i++)
+       {
+               /* Extract name of sound file */
+               sprintf(wav, "%s.wav", angband_sound_name[i]);
+               
+               /* Access the sound */
+               path_build(buf, sizeof(buf), dir_xtra_sound, wav);
+               
+               /* Save the sound filename, if it exists */
+               if (check_file(buf)) sound_file[i] = string_make(buf);
+       }
+       use_sound = TRUE;
+       return;
+}
+
+/*
+ * Hack -- make a sound
+ */
+static errr Term_xtra_x11_sound(int v)
+{
+       char buf[1024];
+       
+       /* Sound disabled */
+       if (!use_sound) return (1);
+       
+       /* Illegal sound */
+       if ((v < 0) || (v >= SOUND_MAX)) return (1);
+       
+       /* Unknown sound */
+       if (!sound_file[v]) return (1);
+       
+       sprintf(buf,"./playwave.sh %s\n", sound_file[v]);
+       
+       return (system(buf) < 0);
+       
+}
+#endif /* USE_SOUND */
+
+
 /*
  * Handle "activation" of a term
  */
@@ -2236,7 +2910,7 @@ static errr Term_xtra_x11_level(int v)
 
                /* Activate the font */
                Infofnt_set(td->fnt);
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
                Infokfnt_set(td->kfnt);
 #endif
        }
@@ -2273,9 +2947,9 @@ static errr Term_xtra_x11_react(void)
 
                                /* Create pixel */
                                pixel = create_pixel(Metadpy->dpy,
-                                                    color_table[i][1],
-                                                    color_table[i][2],
-                                                    color_table[i][3]);
+                                                    color_table[i][1],
+                                                    color_table[i][2],
+                                                    color_table[i][3]);
 
                                /* Change the foreground */
                                Infoclr_set(clr[i]);
@@ -2300,6 +2974,11 @@ static errr Term_xtra_x11(int n, int v)
                /* Make a noise */
                case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
 
+#ifdef USE_SOUND
+               /* Make a special sound */
+               case TERM_XTRA_SOUND: return (Term_xtra_x11_sound(v));
+#endif
+
                /* Flush the output XXX XXX */
                case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
 
@@ -2316,7 +2995,7 @@ static errr Term_xtra_x11(int n, int v)
                case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
 
                /* Clear the screen */
-               case TERM_XTRA_CLEAR: Infowin_wipe(); return (0);
+               case TERM_XTRA_CLEAR: Infowin_wipe(); s_ptr->drawn = FALSE; return (0);
 
                /* Delay for some milliseconds */
                case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
@@ -2337,12 +3016,55 @@ static errr Term_xtra_x11(int n, int v)
  */
 static errr Term_curs_x11(int x, int y)
 {
-       /* Draw the cursor */
-       Infoclr_set(xor);
+       if (use_graphics)
+       {
+               XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
+                              x * Infofnt->wid + Infowin->ox,
+                              y * Infofnt->hgt + Infowin->oy,
+                              Infofnt->wid - 1, Infofnt->hgt - 1);
+               XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
+                              x * Infofnt->wid + Infowin->ox + 1,
+                              y * Infofnt->hgt + Infowin->oy + 1,
+                              Infofnt->wid - 3, Infofnt->hgt - 3);
+       }
+       else
+       {
+               /* Draw the cursor */
+               Infoclr_set(xor);
 
-       /* Hilite the cursor character */
-       Infofnt_text_non(x, y, " ", 1);
+               /* Hilite the cursor character */
+               Infofnt_text_non(x, y, " ", 1);
+       }
+
+       /* Success */
+       return (0);
+}
+
+
+/*
+ * Draw the double width cursor
+ */
+static errr Term_bigcurs_x11(int x, int y)
+{
+       if (use_graphics)
+       {
+               XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
+                              x * Infofnt->wid + Infowin->ox,
+                              y * Infofnt->hgt + Infowin->oy,
+                              Infofnt->twid - 1, Infofnt->hgt - 1);
+               XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
+                              x * Infofnt->wid + Infowin->ox + 1,
+                              y * Infofnt->hgt + Infowin->oy + 1,
+                              Infofnt->twid - 3, Infofnt->hgt - 3);
+       }
+       else
+       {
+               /* Draw the cursor */
+               Infoclr_set(xor);
 
+               /* Hilite the cursor character */
+               Infofnt_text_non(x, y, "  ", 2);
+       }
        /* Success */
        return (0);
 }
@@ -2359,6 +3081,9 @@ static errr Term_wipe_x11(int x, int y, int n)
        /* Mega-Hack -- Erase some space */
        Infofnt_text_non(x, y, "", n);
 
+       /* Redraw the selection if any, as it may have been obscured. (later) */
+       s_ptr->drawn = FALSE;
+
        /* Success */
        return (0);
 }
@@ -2375,6 +3100,9 @@ static errr Term_text_x11(int x, int y, int n, byte a, cptr s)
        /* Draw the text */
        Infofnt_text_std(x, y, s, n);
 
+       /* Redraw the selection if any, as it may have been obscured. (later) */
+       s_ptr->drawn = FALSE;
+
        /* Success */
        return (0);
 }
@@ -2385,19 +3113,13 @@ static errr Term_text_x11(int x, int y, int n, byte a, cptr s)
 /*
  * Draw some graphical characters.
  */
-# ifdef USE_TRANSPARENCY
 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
-# else /* USE_TRANSPARENCY */
-static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
-# endif /* USE_TRANSPARENCY */
 {
        int i, x1, y1;
 
        byte a;
        char c;
 
-
-#ifdef USE_TRANSPARENCY
        byte ta;
        char tc;
 
@@ -2405,7 +3127,6 @@ static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
        int k,l;
 
        unsigned long pixel, blank;
-#endif /* USE_TRANSPARENCY */
 
        term_data *td = (term_data*)(Term->data);
 
@@ -2416,34 +3137,48 @@ static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
        y += Infowin->oy;
        x += Infowin->ox;
 
-       for (i = 0; i < n; ++i)
+       for (i = 0; i < n; ++i, x += td->fnt->wid)
        {
                a = *ap++;
                c = *cp++;
 
                /* For extra speed - cache these values */
-               x1 = (c&0x7F) * td->fnt->wid;
+               x1 = (c&0x7F) * td->fnt->twid;
                y1 = (a&0x7F) * td->fnt->hgt;
 
-#ifdef USE_TRANSPARENCY
+               /* Illegal tile index */
+               if (td->tiles->width < x1 + td->fnt->wid ||
+                   td->tiles->height < y1 + td->fnt->hgt)
+               {
+                       /* Draw black square */
+                       XFillRectangle(Metadpy->dpy, td->win->win, clr[0]->gc,
+                                      x, y, 
+                                      td->fnt->twid, td->fnt->hgt);
+
+                       /* Skip drawing tile */
+                       continue;
+               }
 
                ta = *tap++;
                tc = *tcp++;
 
                /* For extra speed - cache these values */
-               x2 = (tc&0x7F) * td->fnt->wid;
+               x2 = (tc&0x7F) * td->fnt->twid;
                y2 = (ta&0x7F) * td->fnt->hgt;
                
                /* Optimise the common case */
-               if ((x1 == x2) && (y1 == y2))
+               if (((x1 == x2) && (y1 == y2)) ||
+                   !(((byte)ta & 0x80) && ((byte)tc & 0x80)) ||
+                   td->tiles->width < x2 + td->fnt->wid ||
+                   td->tiles->height < y2 + td->fnt->hgt)
                {
                        /* Draw object / terrain */
                        XPutImage(Metadpy->dpy, td->win->win,
-                               clr[0]->gc,
-                               td->tiles,
-                               x1, y1,
-                               x, y,
-                               td->fnt->wid, td->fnt->hgt);    
+                               clr[0]->gc,
+                               td->tiles,
+                               x1, y1,
+                               x, y,
+                               td->fnt->twid, td->fnt->hgt);   
                }
                else
                {
@@ -2451,7 +3186,7 @@ static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
                        /* Mega Hack^2 - assume the top left corner is "black" */
                        blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
 
-                       for (k = 0; k < td->fnt->wid; k++)
+                       for (k = 0; k < td->fnt->twid; k++)
                        {
                                for (l = 0; l < td->fnt->hgt; l++)
                                {
@@ -2471,26 +3206,16 @@ static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
                        /* Draw to screen */
 
                        XPutImage(Metadpy->dpy, td->win->win,
-                             clr[0]->gc,
-                            td->TmpImage,
-                            0, 0, x, y,
-                            td->fnt->wid, td->fnt->hgt);
+                             clr[0]->gc,
+                            td->TmpImage,
+                            0, 0, x, y,
+                            td->fnt->twid, td->fnt->hgt);
                }
-
-#else /* USE_TRANSPARENCY */
-
-               /* Draw object / terrain */
-               XPutImage(Metadpy->dpy, td->win->win,
-                         clr[0]->gc,
-                         td->tiles,
-                         x1, y1,
-                         x, y,
-                         td->fnt->wid, td->fnt->hgt);
-
-#endif /* USE_TRANSPARENCY */
-               x += td->fnt->wid;
        }
 
+       /* Redraw the selection if any, as it may have been obscured. (later) */
+       s_ptr->drawn = FALSE;
+
        /* Success */
        return (0);
 }
@@ -2508,6 +3233,10 @@ IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
        XIMStyles *xim_styles = NULL;
        int i;
 
+       /* Unused */
+       (void)unused1;
+       (void)unused2;
+
        xim = XOpenIM(display, NULL, NULL, NULL);
        if(!xim){
                printf("can't open IM\n");
@@ -2556,7 +3285,11 @@ static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
 {
        int i;
 
-    if (call_data == NULL){
+       /* Unused */
+       (void)xim;
+       (void)client_data;
+
+       if (call_data == NULL){
                XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
        }
 
@@ -2582,12 +3315,10 @@ static errr term_data_init(term_data *td, int i)
 {
        term *t = &td->t;
 
-       bool fixed = (i == 0);
-
        cptr name = angband_term_name[i];
 
        cptr font;
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        cptr kfont;
 #endif
 
@@ -2680,7 +3411,7 @@ static errr term_data_init(term_data *td, int i)
                }
        }
 
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        /* Window specific font name */
        sprintf(buf, "ANGBAND_X11_KFONT_%d", i);
 
@@ -2753,21 +3484,24 @@ static errr term_data_init(term_data *td, int i)
        y = (str != NULL) ? atoi(str) : -1;
 
 
-       if (!fixed)
-       {
-               /* Window specific cols */
-               sprintf(buf, "ANGBAND_X11_COLS_%d", i);
-               str = getenv(buf);
-               val = (str != NULL) ? atoi(str) : -1;
-               if (val > 0) cols = val;
+       /* Window specific cols */
+       sprintf(buf, "ANGBAND_X11_COLS_%d", i);
+       str = getenv(buf);
+       val = (str != NULL) ? atoi(str) : -1;
+       if (val > 0) cols = val;
 
-               /* Window specific rows */
-               sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
-               str = getenv(buf);
-               val = (str != NULL) ? atoi(str) : -1;
-               if (val > 0) rows = val;
-       }
+       /* Window specific rows */
+       sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
+       str = getenv(buf);
+       val = (str != NULL) ? atoi(str) : -1;
+       if (val > 0) rows = val;
 
+       /* Hack the main window must be at least 80x24 */
+       if (!i)
+       {
+               if (cols < 80) cols = 80;
+               if (rows < 24) rows = 24;
+       }
 
        /* Window specific inner border offset (ox) */
        sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
@@ -2783,7 +3517,7 @@ static errr term_data_init(term_data *td, int i)
 
 
        /* Prepare the standard font */
-#ifdef _JP
+#ifdef USE_JP_FONTSTRUCT
        MAKE(td->fnt, infofnt);
        Infofnt_set(td->fnt);
        MAKE(td->kfnt, infofnt);
@@ -2797,7 +3531,7 @@ static errr term_data_init(term_data *td, int i)
 
 
        /* Hack -- key buffer size */
-       num = (fixed ? 1024 : 16);
+       num = ((i == 0) ? 1024 : 16);
 
        /* Assume full size windows */
        wid = cols * td->fnt->wid + (ox + ox);
@@ -2807,23 +3541,13 @@ static errr term_data_init(term_data *td, int i)
        MAKE(td->win, infowin);
        Infowin_set(td->win);
        Infowin_init_top(x, y, wid, hgt, 0,
-                        Metadpy->fg, Metadpy->bg);
+                        Metadpy->fg, Metadpy->bg);
 
        /* Ask for certain events */
 #if defined(USE_XIM)
-#if 0
-       /* XIM ¤¬Í­¸ú¤Ê¤Î¤Ï¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤Î¤ß¤Ê¤Î¤Ç¡¢¼óÈø¤ò°ì´Ó¤µ¤»¤ë¤¿¤á
-          Ä̾ï¤Î¥­¡¼ÆþÎϤâ̵¸ú¤Ë¤¹¤ë */
-       if(i == 0){
-               Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask);
-       }else{
-               Infowin_set_mask(ExposureMask | StructureNotifyMask);
-       }
-#else
-       Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | FocusChangeMask);
-#endif
+       Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask);
 #else
-       Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask);
+       Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
 #endif
 
        /* Set the window name */
@@ -2853,19 +3577,21 @@ static errr term_data_init(term_data *td, int i)
        /* Oops */
        if (sh == NULL) quit("XAllocSizeHints failed");
 
-       /* Fixed window size */
-       if (fixed)
+       /* Main window has a differing minimum size */
+       if (i == 0)
        {
-               /* Fixed size */
+               /* Main window min size is 80x24 */
                sh->flags = PMinSize | PMaxSize;
-               sh->min_width = sh->max_width = wid;
-               sh->min_height = sh->max_height = hgt;
+               sh->min_width = 80 * td->fnt->wid + (ox + ox);
+               sh->min_height = 24 * td->fnt->hgt + (oy + oy);
+               sh->max_width = 255 * td->fnt->wid + (ox + ox);
+               sh->max_height = 255 * td->fnt->hgt + (oy + oy);
        }
 
-       /* Variable window size */
+       /* Other windows can be shrunk to 1x1 */
        else
        {
-               /* Variable size */
+               /* Other windows */
                sh->flags = PMinSize | PMaxSize;
                sh->min_width = td->fnt->wid + (ox + ox);
                sh->min_height = td->fnt->hgt + (oy + oy);
@@ -2915,6 +3641,7 @@ static errr term_data_init(term_data *td, int i)
        /* Hooks */
        t->xtra_hook = Term_xtra_x11;
        t->curs_hook = Term_curs_x11;
+       t->bigcurs_hook = Term_bigcurs_x11;
        t->wipe_hook = Term_wipe_x11;
        t->text_hook = Term_text_x11;
 
@@ -2938,7 +3665,7 @@ errr init_x11(int argc, char *argv[])
 
        cptr dpy_name = "";
 
-       int num_term = MAX_TERM_DATA;
+       int num_term = 3;
 
 #ifdef USE_GRAPHICS
 
@@ -2947,11 +3674,7 @@ errr init_x11(int argc, char *argv[])
        int pict_wid = 0;
        int pict_hgt = 0;
 
-#ifdef USE_TRANSPARENCY
-
        char *TmpData;
-#endif /* USE_TRANSPARENCY */
-
 #endif /* USE_GRAPHICS */
 
 
@@ -2970,6 +3693,24 @@ errr init_x11(int argc, char *argv[])
                        smoothRescaling = FALSE;
                        continue;
                }
+
+               if (prefix(argv[i], "-a"))
+               {
+                       arg_graphics = GRAPHICS_ADAM_BOLT;
+                       continue;
+               }
+
+               if (prefix(argv[i], "-o"))
+               {
+                       arg_graphics = GRAPHICS_ORIGINAL;
+                       continue;
+               }
+
+               if (prefix(argv[i], "-b"))
+               {
+                       arg_bigtile = use_bigtile = TRUE;
+                       continue;
+               }
 #endif /* USE_GRAPHICS */
 
                if (prefix(argv[i], "-n"))
@@ -2980,29 +3721,42 @@ errr init_x11(int argc, char *argv[])
                        continue;
                }
 
+               if (prefix(argv[i], "--"))
+               {
+                       /* Ignore */
+                       continue;
+               }
+
                plog_fmt("Ignoring option: %s", argv[i]);
        }
 
 #ifdef USE_LOCALE
+
+#ifdef JP
+       /* Get locale information from environment variables */
        setlocale(LC_ALL, "");
+
 #ifdef DEFAULT_LOCALE
        if(!strcmp(setlocale(LC_ALL, NULL), "C")){
                printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
                setlocale(LC_ALL, DEFAULT_LOCALE);
        }
 #endif
+
+       if(!strcmp(setlocale(LC_ALL, NULL), "C"))
        {
-               char *current_locale = setlocale(LC_ALL, NULL);
-//             printf("set locale to \"%s\"\n", current_locale);
-               if(!strcmp(current_locale, "C")){
-                       printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
-               }
+               printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
        }
 
        if(!XSupportsLocale()){
                printf("can't support locale in X\n");
                setlocale(LC_ALL, "C");
        }
+#else
+       /* Set locale to "C" without using environment variables */
+       setlocale(LC_ALL, "C");
+#endif /* JP */
+
 #endif /* USE_LOCALE */
 
 
@@ -3039,9 +3793,9 @@ errr init_x11(int argc, char *argv[])
                {
                        /* Create pixel */
                        pixel = create_pixel(Metadpy->dpy,
-                                            color_table[i][1],
-                                            color_table[i][2],
-                                            color_table[i][3]);
+                                            color_table[i][1],
+                                            color_table[i][2],
+                                            color_table[i][3]);
                }
 
                /* Initialize the color */
@@ -3049,6 +3803,10 @@ errr init_x11(int argc, char *argv[])
        }
 
 
+       /* Prepare required atoms. */
+       set_atoms();
+
+
        /* Initialize the windows */
        for (i = 0; i < num_term; i++)
        {
@@ -3075,46 +3833,53 @@ errr init_x11(int argc, char *argv[])
                if(!p || !*p){
                        p = XSetLocaleModifiers("@im=");
                }
-//             printf("XMODIFIERS=\"%s\"\n", p);
+/*             printf("XMODIFIERS=\"%s\"\n", p); */
        }
        XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
 #endif
 
+#ifdef USE_SOUND
+       /* initialize sound */
+       if (arg_sound) init_sound();
+#endif
+
 #ifdef USE_GRAPHICS
 
        /* Try graphics */
-       if (arg_graphics)
+       switch (arg_graphics)
        {
-               /* Try the "16x16.bmp" file */
-               path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/16x16.bmp");
+       case GRAPHICS_ORIGINAL:
+               /* Try the "8x8.bmp" file */
+               path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/8x8.bmp");
 
-               /* Use the "16x16.bmp" file if it exists */
+               /* Use the "8x8.bmp" file if it exists */
                if (0 == fd_close(fd_open(filename, O_RDONLY)))
                {
                        /* Use graphics */
                        use_graphics = TRUE;
 
-                       use_transparency = TRUE;
-
-                       pict_wid = pict_hgt = 16;
+                       pict_wid = pict_hgt = 8;
 
-                       ANGBAND_GRAF = "new";
+                       ANGBAND_GRAF = "old";
+                       break;
                }
-               else
+               /* Fall through */
+
+       case GRAPHICS_ADAM_BOLT:
+               /* Try the "16x16.bmp" file */
+               path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/16x16.bmp");
+
+               /* Use the "16x16.bmp" file if it exists */
+               if (0 == fd_close(fd_open(filename, O_RDONLY)))
                {
-                       /* Try the "8x8.bmp" file */
-                       path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/8x8.bmp");
+                       /* Use graphics */
+                       use_graphics = TRUE;
 
-                       /* Use the "8x8.bmp" file if it exists */
-                       if (0 == fd_close(fd_open(filename, O_RDONLY)))
-                       {
-                               /* Use graphics */
-                               use_graphics = TRUE;
+                       pict_wid = pict_hgt = 16;
 
-                               pict_wid = pict_hgt = 8;
+                       ANGBAND_GRAF = "new";
 
-                               ANGBAND_GRAF = "old";
-                       }
+                       break;
                }
        }
 
@@ -3144,11 +3909,10 @@ errr init_x11(int argc, char *argv[])
                        /* Resize tiles */
                        td->tiles =
                        ResizeImage(dpy, tiles_raw,
-                                   pict_wid, pict_hgt,
-                                   td->fnt->wid, td->fnt->hgt);
+                                   pict_wid, pict_hgt,
+                                   td->fnt->twid, td->fnt->hgt);
                }
 
-#ifdef USE_TRANSPARENCY
                /* Initialize the transparency masks */
                for (i = 0; i < num_term; i++)
                {
@@ -3163,18 +3927,16 @@ errr init_x11(int argc, char *argv[])
                        ii = 1;
                        jj = (depth - 1) >> 2;
                        while (jj >>= 1) ii <<= 1;
-                       total = td->fnt->wid * td->fnt->hgt * ii;
+                       total = td->fnt->twid * td->fnt->hgt * ii;
                        
                        
                        TmpData = (char *)malloc(total);
 
                        td->TmpImage = XCreateImage(dpy,visual,depth,
                                ZPixmap, 0, TmpData,
-                               td->fnt->wid, td->fnt->hgt, 8, 0);
+                               td->fnt->twid, td->fnt->hgt, 8, 0);
 
                }
-#endif /* USE_TRANSPARENCY */
-
 
                /* Free tiles_raw? XXX XXX */
        }