#include "util/int-char-converter.h"
#include "util/string-processor.h"
#include <algorithm>
+#include <memory>
+#include <span>
+#include <string>
/*
* Available graphic modes
#include <X11/Xft/Xft.h>
#endif
-#include <memory>
-#include <string>
-
/*
* Include some helpful X11 code.
*/
}
#ifdef USE_XFT
-static void Infofnt_text_std_xft_draw_str(int x, int y, concptr str, concptr str_end)
+static void Infofnt_text_std_xft_draw_str(int px, int py, const XftColor &fg, concptr str, concptr str_end)
{
int offset = 0;
while (str < str_end) {
return;
}
- XftDrawStringUtf8(Infowin->draw, &Infoclr->fg, Infofnt->info, x + Infofnt->wid * offset, y, (const FcChar8 *)str, byte_len);
+ XftDrawStringUtf8(Infowin->draw, &fg, Infofnt->info, px + Infofnt->wid * offset, py, (const FcChar8 *)str, byte_len);
offset += (byte_len > 1 ? 2 : 1);
str += byte_len;
}
}
+
+static void Infofnt_text_std_xft(int x, int y, int len, const XftColor &fg, const XftColor &bg, const char *str, int utf8_len)
+{
+ auto *draw = Infowin->draw;
+
+ const auto py = (y * Infofnt->hgt) + Infofnt->asc + Infowin->oy;
+ const auto px = (x * Infofnt->wid) + Infowin->ox;
+
+ XRectangle r{ 0, 0, static_cast<unsigned short>(Infofnt->wid * len), static_cast<unsigned short>(Infofnt->hgt) };
+ XftDrawSetClipRectangles(draw, px, py - Infofnt->asc, &r, 1);
+ XftDrawRect(draw, &bg, px, py - Infofnt->asc, r.width, r.height);
+ Infofnt_text_std_xft_draw_str(px, py, fg, str, str + utf8_len);
+ XftDrawSetClip(draw, 0);
+}
#endif
/*
len = strlen(str);
}
+#ifndef USE_XFT
y = (y * Infofnt->hgt) + Infofnt->asc + Infowin->oy;
x = (x * Infofnt->wid) + Infowin->ox;
+#endif
+
if (Infofnt->mono) {
#ifndef USE_XFT
int i;
#endif
#ifdef USE_XFT
- XftDraw *draw = Infowin->draw;
-
- XRectangle r;
- r.x = 0;
- r.y = 0;
- r.width = Infofnt->wid * len;
- r.height = Infofnt->hgt;
- XftDrawSetClipRectangles(draw, x, y - Infofnt->asc, &r, 1);
- XftDrawRect(draw, &Infoclr->bg, x, y - Infofnt->asc, Infofnt->wid * len, Infofnt->hgt);
- Infofnt_text_std_xft_draw_str(x, y, _(utf8_buf, str), _(utf8_buf + utf8_len, str + len));
- XftDrawSetClip(draw, 0);
+ Infofnt_text_std_xft(x, y, len, Infoclr->fg, Infoclr->bg, _(utf8_buf, str), _(utf8_len, len));
#else
XmbDrawImageString(Metadpy->dpy, Infowin->win, Infofnt->info, Infoclr->gc, x, y, _(utf8_buf, str), _(utf8_len, len));
#endif
max->y = std::max(a->y, b->y);
}
+#ifdef USE_XFT
+template <class T, class D>
+auto make_unique_ptr_with_deleter(T *p, D d) noexcept
+{
+ return std::unique_ptr<T, D>(p, std::move(d));
+}
+
+/*!
+ * @brief 矩形領域の枠を描画する
+ *
+ * ドラッグ時の選択範囲の表示に使用する。
+ *
+ * @param x 矩形領域の左上のX座標(ピクセル単位)
+ * @param y 矩形領域の左上のY座標(ピクセル単位)
+ * @param widht 矩形領域の幅(ピクセル単位)
+ * @param height 矩形領域の高さ(ピクセル単位)
+ */
+static void draw_rectangle_frame(int x, int y, int width, int height)
+{
+ auto gc = make_unique_ptr_with_deleter(XCreateGC(Metadpy->dpy, Infowin->win, 0, NULL),
+ [dpy = Metadpy->dpy](GC gc) { XFreeGC(dpy, gc); });
+
+ XSetForeground(Metadpy->dpy, gc.get(), WhitePixel(Metadpy->dpy, DefaultScreen(Metadpy->dpy)));
+ XDrawLine(Metadpy->dpy, Infowin->win, gc.get(), x, y, x + width, y);
+ XDrawLine(Metadpy->dpy, Infowin->win, gc.get(), x, y, x, y + height);
+ XDrawLine(Metadpy->dpy, Infowin->win, gc.get(), x + width, y, x + width, y + height);
+ XDrawLine(Metadpy->dpy, Infowin->win, gc.get(), x, y + height, x + width, y + height);
+}
+#endif
+
+#ifdef USE_XFT
+static void draw_cursor_xft(int x, int y, int len)
+{
+ // term_what() では中央寄せ時に座標がずれるので直接取得
+ const std::span<const char> cursor_chars(&game_term->scr->c[y][x], len);
+
+#ifdef JP
+ char utf8_buf[16];
+ const auto utf8_len = euc_to_utf8(cursor_chars.data(), cursor_chars.size(), utf8_buf, sizeof(utf8_buf));
+ if (utf8_len < 0) {
+ return;
+ }
+#endif
+ Infofnt_text_std_xft(x, y, len, Infoclr->bg, Infoclr->fg, _(utf8_buf, cursor_chars.data()), _(utf8_len, len));
+}
+#endif
+
+static void draw_cursor(int x, int y, int len)
+{
+#ifdef USE_XFT
+ draw_cursor_xft(x, y, len);
+#else
+ square_to_pixel(&x, &y, x, y);
+ const auto width = Infofnt->wid * len;
+ const auto height = Infofnt->hgt;
+ XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc, x, y, width, height);
+#endif
+}
+
/*
* Remove the selection by redrawing it.
*/
square_to_pixel(&x1, &y1, x1, y1);
square_to_pixel(&x2, &y2, x2, y2);
#ifdef USE_XFT
- XftDrawRect(Infowin->draw, &clr[2]->fg, x1, y1, x2 - x1 + Infofnt->wid - 1, y2 - y1 + Infofnt->hgt - 1);
+ draw_rectangle_frame(x1, y1, x2 - x1 + Infofnt->wid - 1, y2 - y1 + Infofnt->hgt - 1);
#else
XDrawRectangle(Metadpy->dpy, Infowin->win, clr[2]->gc, x1, y1, x2 - x1 + Infofnt->wid - 1, y2 - y1 + Infofnt->hgt - 1);
#endif
#endif
} else {
Infoclr_set(xor_.get());
- Infofnt_text_non(x, y, " ", 1);
+ draw_cursor(x, y, 1);
}
return 0;
#endif
} else {
Infoclr_set(xor_.get());
- Infofnt_text_non(x, y, " ", 2);
+ draw_cursor(x, y, 2);
}
return 0;