X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fmain-x11.c;h=c7f499987bcc9a40a9aad109eeafcbc0e051a7ca;hb=35255c58065928127995c6c7972ef514cbebcb93;hp=733946f2c2c932e9314c423ea5b92462937350e5;hpb=eaac4df8c0a956c79ba6c38c55b9fa7c5610c013;p=hengband%2Fhengband.git diff --git a/src/main-x11.c b/src/main-x11.c index 733946f2c..c7f499987 100644 --- a/src/main-x11.c +++ b/src/main-x11.c @@ -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 /* @@ -123,9 +123,10 @@ #if 0 char *XSetIMValues(XIM, ...); /* Hack for XFree86 4.0 */ #endif +#include #endif /* __MAKEDEPEND__ */ - +#include /* * Include some helpful X11 code. */ @@ -455,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 @@ -468,7 +469,7 @@ static infofnt *Infofnt = (infofnt*)(NULL); /**** Generic code ****/ -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT #define Infokfnt_set(I) \ (Infokfnt = (I)) #endif @@ -1227,7 +1228,7 @@ static errr Infofnt_nuke(void) { infofnt *ifnt = Infofnt; -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT infofnt *ikfnt = Infokfnt; #endif /* Deal with 'name' */ @@ -1237,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 */ @@ -1268,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 @@ -1281,7 +1287,7 @@ static errr Infofnt_prepare(XFontStruct *info) { infofnt *ifnt = Infofnt; -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT infofnt *ikfnt = Infokfnt; #endif XCharStruct *cs; @@ -1304,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; @@ -1330,7 +1336,7 @@ static errr Infofnt_prepare(XFontStruct *info) else ifnt->twid = ifnt->wid; -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT /* Assign the struct */ ikfnt->info = kinfo; @@ -1361,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 @@ -1375,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)); @@ -1402,7 +1408,7 @@ static errr Infofnt_init_real(XFontStruct *info) * Inputs: * name: The name of the requested Font */ -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT static void Infofnt_init_data(cptr name, cptr kname) #else static void Infofnt_init_data(cptr name) @@ -1419,7 +1425,7 @@ static void Infofnt_init_data(cptr name) #endif -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT XFontStruct *kinfo; #endif /*** Load the info Fresh, using the name ***/ @@ -1427,7 +1433,7 @@ static void Infofnt_init_data(cptr name) /* If the name is not given, report an error */ if (!name || !*name) quit("Missing font!"); -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT if (!kname || !*kname) quit("Missing kanji font!"); #endif /* Attempt to load the font */ @@ -1442,7 +1448,7 @@ static void Infofnt_init_data(cptr name) } #else info = XLoadQueryFont(Metadpy->dpy, name); -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT kinfo = XLoadQueryFont(Metadpy->dpy, kname); #endif #endif @@ -1450,7 +1456,7 @@ static void Infofnt_init_data(cptr name) /* The load failed, try to recover */ if (!info) quit_fmt("Failed to find font:\"%s\"", name); -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT if (!kinfo) quit_fmt("Failed to find font:\"%s\"", kname); #endif @@ -1461,11 +1467,11 @@ static void 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)) @@ -1477,7 +1483,7 @@ static void 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 @@ -1487,21 +1493,21 @@ static void Infofnt_init_data(cptr 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 } -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT /* - * EUCÆüËܸ쥳¡¼¥É¤ò´Þ¤àʸ»úÎó¤òɽ¼¨¤¹¤ë (Xlib) + * EUC日本語コードを含む文字列を表示する (Xlib) */ static void XDrawMultiString(display,d,gc, x, y, string, len, afont, @@ -1530,48 +1536,48 @@ XDrawMultiString(display,d,gc, x, y, string, len, afont, #ifdef TOFU if ( (*str) == 0x7f ) { - /* 0x7F¤Ï¢£¤Ç·è¤áÂǤÁ */ + /* 0x7Fは■で決め打ち */ - /* Ϣ³¤¹¤ë0x7F¤ÎŤµ¤ò¸¡½Ð */ + /* 連続する0x7Fの長さを検出 */ slen = 0; while ( str < endp && (*str) == 0x7f ) { slen++; str++; } - /* ÉÁ²è */ + /* 描画 */ XFillRectangle( display, d, gc, x, y-afont_ascent, slen * afont_width, afont_height); - /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */ + /* ポインタを進める */ x += afont_width * slen; } else #endif if ( iskanji(*str) ) { - /* UJIS¤Î»Ï¤Þ¤ê */ + /* UJISの始まり */ - /* Ϣ³¤¹¤ë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; } else { - /* Èó´Á»ú(=ASCII¤È²¾Äê)¤Î»Ï¤Þ¤ê */ + /* 非漢字(=ASCIIと仮定)の始まり */ - /* Ϣ³¤¹¤ëASCIIʸ»ú¤ò¸¡½Ð */ + /* 連続するASCII文字を検出 */ p = str; slen = 0; while ( str < endp && *str && !iskanji(*str) ) { @@ -1582,11 +1588,11 @@ XDrawMultiString(display,d,gc, x, y, string, len, afont, slen++; } - /* ÉÁ²è */ + /* 描画 */ XSetFont( display, gc, afont->fid ); XDrawImageString( display, d, gc, x, y, p, slen ); - /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */ + /* ポインタを進める */ x += afont_width * slen; } } @@ -1623,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 @@ -1652,8 +1656,8 @@ 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, @@ -1661,8 +1665,18 @@ static errr Infofnt_text_std(int x, int y, cptr str, int len) 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); @@ -1756,7 +1770,7 @@ struct term_data term t; infofnt *fnt; -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT infofnt *kfnt; #endif @@ -1767,15 +1781,11 @@ struct term_data XImage *tiles; -#ifdef USE_TRANSPARENCY - /* Tempory storage for overlaying tiles. */ XImage *TmpImage; #endif -#endif - }; @@ -1790,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 @@ -1935,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); +} /* @@ -1949,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: @@ -1958,6 +2522,13 @@ 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); @@ -2041,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; @@ -2055,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; } @@ -2068,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; @@ -2080,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); @@ -2297,9 +2888,8 @@ static errr Term_xtra_x11_sound(int v) if (!sound_file[v]) return (1); sprintf(buf,"./playwave.sh %s\n", sound_file[v]); - system(buf); - return (0); + return (system(buf) < 0); } #endif /* USE_SOUND */ @@ -2320,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 } @@ -2405,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); @@ -2491,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); } @@ -2507,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); } @@ -2517,18 +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; @@ -2536,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); @@ -2569,8 +3159,6 @@ static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp) continue; } -#ifdef USE_TRANSPARENCY - ta = *tap++; tc = *tcp++; @@ -2623,20 +3211,11 @@ static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp) 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->twid, td->fnt->hgt); - -#endif /* USE_TRANSPARENCY */ } + /* Redraw the selection if any, as it may have been obscured. (later) */ + s_ptr->drawn = FALSE; + /* Success */ return (0); } @@ -2739,7 +3318,7 @@ static errr term_data_init(term_data *td, int i) cptr name = angband_term_name[i]; cptr font; -#ifdef _JP +#ifdef USE_JP_FONTSTRUCT cptr kfont; #endif @@ -2832,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); @@ -2938,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); @@ -2966,9 +3545,9 @@ static errr term_data_init(term_data *td, int i) /* Ask for certain events */ #if defined(USE_XIM) - Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | FocusChangeMask); + 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 */ @@ -3095,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 */ @@ -3156,25 +3731,32 @@ errr init_x11(int argc, char *argv[]) } #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 */ @@ -3221,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++) { @@ -3327,7 +3913,6 @@ errr init_x11(int argc, char *argv[]) td->fnt->twid, td->fnt->hgt); } -#ifdef USE_TRANSPARENCY /* Initialize the transparency masks */ for (i = 0; i < num_term; i++) { @@ -3352,8 +3937,6 @@ errr init_x11(int argc, char *argv[]) td->fnt->twid, td->fnt->hgt, 8, 0); } -#endif /* USE_TRANSPARENCY */ - /* Free tiles_raw? XXX XXX */ }