Add Unicode support to the map
authorRay Chason <ray.chason@protonmail.com>
Mon, 17 Oct 2022 01:42:18 +0000 (21:42 -0400)
committerRay Chason <ray.chason@protonmail.com>
Mon, 17 Oct 2022 01:42:18 +0000 (21:42 -0400)
sys/windows/windsys.c
sys/windows/winos.h
win/win32/mhmap.c
win/win32/mswproc.c

index af51e9c5b10fc61765c2a4440a1e8fed7f373971..42115121ccb77472a913f353b7141a21931138c7 100644 (file)
@@ -543,10 +543,26 @@ winos_ascii_to_wide_str(const unsigned char * src, WCHAR * dst, size_t dstLength
     return dst;
 }
 
-WCHAR
-winos_ascii_to_wide(const unsigned char c)
+void
+winos_ascii_to_wide(WCHAR dst[3], UINT32 c)
 {
-    return cp437[c];
+#ifdef ENHANCED_SYMBOLS
+    if (SYMHANDLING(H_UTF8)) {
+        if (c <= 0xFFFF) {
+            dst[0] = (WCHAR) c;
+            dst[1] = L'\0';
+        } else {
+            /* UTF-16 surrogate pair */
+            dst[0] = (WCHAR) ((c >> 10) + 0xD7C0);
+            dst[1] = (WCHAR) ((c & 0x3FF) + 0xDC00);
+            dst[2] = L'\0';
+        }
+    } else
+#endif
+    {
+        dst[0] = cp437[c];
+        dst[1] = L'\0';
+    }
 }
 
 BOOL winos_font_support_cp437(HFONT hFont)
index 55300bda06045097a78f12cef8665eae648399a9..132b153e02fc6bf2953919e8dd067e10dbc70b58 100644 (file)
@@ -12,8 +12,8 @@ extern const WCHAR cp437[256];
 WCHAR *
 winos_ascii_to_wide_str(const unsigned char * src, WCHAR * dst, size_t dstLength);
 
-WCHAR
-winos_ascii_to_wide(const unsigned char c);
+void
+winos_ascii_to_wide(WCHAR dst[3], UINT32 c);
 
 BOOL winos_font_support_cp437(HFONT hFont);
 
index 1212395cbae0004dd09d14c4d37328af9863bb7f..723a0f7cea00742d659a0cfcc64c1dccbb771c55 100644 (file)
@@ -49,6 +49,7 @@ typedef struct mswin_nethack_map_window {
     POINT map_orig;             /* map origin point */
 
     HFONT hMapFont;             /* font for ASCII mode */
+    HFONT hMapFontUnicode;      /* font for Unicode mode */
     boolean bUnicodeFont;       /* font supports unicode page 437 */
 
     int tileWidth;              /* width of tile in pixels at 96 dpi */
@@ -252,6 +253,12 @@ mswin_map_layout(HWND hWnd, LPSIZE map_size)
 
         data->bUnicodeFont = winos_font_support_cp437(data->hMapFont);
 
+        // Same as above, but with ANSI_CHARSET for IBM and Unicode modes
+        lgfnt.lfCharSet = ANSI_CHARSET;
+        if (data->hMapFontUnicode)
+            DeleteObject(data->hMapFontUnicode);
+        data->hMapFontUnicode = CreateFontIndirect(&lgfnt);
+
         // set tile size to match font metrics
 
         data->xBackTile = textMetrics.tmAveCharWidth;
@@ -626,6 +633,8 @@ MapWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     case WM_DESTROY:
         if (data->hMapFont)
             DeleteObject(data->hMapFont);
+        if (data->hMapFontUnicode)
+            DeleteObject(data->hMapFontUnicode);
         if (data->hBackBuffer)
             DeleteBitmap(data->hBackBuffer);
         if (data->backBufferDC)
@@ -911,9 +920,11 @@ paintGlyph(PNHMapWindow data, int i, int j, RECT * rect)
 {
     if (data->map[i][j].glyph >= 0) {
 
-        char ch;
-        WCHAR wch;
+        glyph_info *glyphinfo;
+        uint32 ch;
+        WCHAR wch[3];
         int color;
+        uint32 rgbcolor;
 //        unsigned special;
 //        int mgch;
         HBRUSH back_brush;
@@ -925,12 +936,23 @@ paintGlyph(PNHMapWindow data, int i, int j, RECT * rect)
         FillRect(data->backBufferDC, rect, blackBrush);
         DeleteObject(blackBrush);
 
-    #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2)
-        nhglyph2charcolor(data->map[i][j], &ch, &color);
-        OldFg = SetTextColor(hDC, nhcolor_to_RGB(color));
-    #else
-        ch = (char) data->map[i][j].ttychar;
-        color = (int) data->map[i][j].gm.sym.color;
+        glyphinfo = &data->map[i][j];
+        ch = glyphinfo->ttychar;
+        color = (int) glyphinfo->gm.sym.color;
+        rgbcolor = nhcolor_to_RGB(color);
+#ifdef ENHANCED_SYMBOLS
+        if (SYMHANDLING(H_UTF8)
+            && glyphinfo->gm.u
+            && glyphinfo->gm.u->utf8str) {
+            ch = glyphinfo->gm.u->utf32ch;
+            if (glyphinfo->gm.u->ucolor != 0) {
+                rgbcolor = RGB(
+                        (glyphinfo->gm.u->ucolor >> 16) & 0xFF,
+                        (glyphinfo->gm.u->ucolor >>  8) & 0xFF,
+                        (glyphinfo->gm.u->ucolor >>  0) & 0xFF);
+            }
+        }
+#endif
         if (((data->map[i][j].gm.glyphflags & MG_PET) && iflags.hilite_pet)
             || ((data->map[i][j].gm.glyphflags & (MG_DETECT | MG_BW_LAVA))
                 && iflags.use_inverse)) {
@@ -946,21 +968,23 @@ paintGlyph(PNHMapWindow data, int i, int j, RECT * rect)
                 break;
             default:
                 OldFg =
-                    SetTextColor(data->backBufferDC, nhcolor_to_RGB(color));
+                    SetTextColor(data->backBufferDC, rgbcolor);
             }
         } else {
-            OldFg = SetTextColor(data->backBufferDC, nhcolor_to_RGB(color));
+            OldFg = SetTextColor(data->backBufferDC, rgbcolor);
         }
-    #endif
-        if (data->bUnicodeFont) {
-            wch = winos_ascii_to_wide(ch);
-            if (wch == 0x2591 || wch == 0x2592) {
+        if (data->bUnicodeFont || SYMHANDLING(H_UTF8)) {
+            winos_ascii_to_wide(wch, ch);
+            if (wch[0] == 0x2591 || wch[0] == 0x2592) {
                 int intensity = 80;
                 HBRUSH brush = CreateSolidBrush(RGB(intensity, intensity, intensity));
                 FillRect(data->backBufferDC, rect, brush);
                 DeleteObject(brush);
-                intensity = (wch == 0x2591 ? 100 : 200);
-                brush = CreateSolidBrush(RGB(intensity, intensity, intensity));
+                intensity = (wch[0] == 0x2591 ? 1 : 2);
+                brush = CreateSolidBrush(RGB(
+                            GetRValue(rgbcolor)*intensity/2,
+                            GetGValue(rgbcolor)*intensity/2,
+                            GetBValue(rgbcolor)*intensity/2));
                 RECT smallRect = {0};
                 smallRect.left = rect->left + 1;
                 smallRect.top = rect->top + 1;
@@ -969,12 +993,15 @@ paintGlyph(PNHMapWindow data, int i, int j, RECT * rect)
                 FillRect(data->backBufferDC, &smallRect, brush);
                 DeleteObject(brush);
             } else {
-                DrawTextW(data->backBufferDC, &wch, 1, rect,
+                SelectObject(data->backBufferDC, data->hMapFontUnicode);
+                DrawTextW(data->backBufferDC, wch, -1, rect,
                     DT_CENTER | DT_VCENTER | DT_NOPREFIX
                     | DT_SINGLELINE);
             }
         } else {
-            DrawTextA(data->backBufferDC, &ch, 1, rect,
+            char ch8 = (char) ch;
+            SelectObject(data->backBufferDC, data->hMapFont);
+            DrawTextA(data->backBufferDC, &ch8, 1, rect,
                         DT_CENTER | DT_VCENTER | DT_NOPREFIX
                             | DT_SINGLELINE);
         }
index 0b409ab060c616fd8adc4dc592e32afda7783ccb..efc655f1279af9084f0d37c223bee689cff7e3e1 100644 (file)
@@ -90,6 +90,9 @@ struct window_procs mswin_procs = {
         | WC_SPLASH_SCREEN | WC_POPUP_DIALOG | WC_MOUSE_SUPPORT,
 #ifdef STATUS_HILITES
     WC2_HITPOINTBAR | WC2_FLUSH_STATUS | WC2_RESET_STATUS | WC2_HILITE_STATUS |
+#endif
+#ifdef ENHANCED_SYMBOLS
+     WC2_U_UTF8STR | WC2_U_24BITCOLOR |
 #endif
     0L,
     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},   /* color availability */