1 /* NetHack 3.6	mhfont.c	$NHDT-Date: 1432512800 2015/05/25 00:13:20 $  $NHDT-Branch: master $:$NHDT-Revision: 1.18 $ */
2 /* Copyright (C) 2001 by Alex Kompel 	 */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /* font management and such */
6 
7 #include "mhfont.h"
8 
9 #define MAXFONTS 64
10 
11 /* font table - 64 fonts ought to be enough */
12 static struct font_table_entry {
13     int code;
14     HFONT hFont;
15 } font_table[MAXFONTS];
16 static int font_table_size = 0;
17 HFONT version_splash_font;
18 HFONT extrainfo_splash_font;
19 
20 #define NHFONT_CODE(win, attr) (((attr & 0xFF) << 8) | (win_type & 0xFF))
21 
22 static void __cdecl font_table_cleanup(void);
23 
24 /* create font based on window type, charater attributes and
25    window device context */
26 HGDIOBJ
mswin_get_font(int win_type,int attr,HDC hdc,BOOL replace)27 mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace)
28 {
29     HFONT fnt = NULL;
30     LOGFONT lgfnt;
31     int font_size;
32     int font_index;
33     static BOOL once = FALSE;
34 
35     if (!once) {
36         once = TRUE;
37         atexit(font_table_cleanup);
38     }
39 
40     ZeroMemory(&lgfnt, sizeof(lgfnt));
41 
42     /* try find font in the table */
43     for (font_index = 0; font_index < font_table_size; font_index++)
44         if (NHFONT_CODE(win_type, attr) == font_table[font_index].code)
45             break;
46 
47     if (!replace && font_index < font_table_size)
48         return font_table[font_index].hFont;
49 
50     switch (win_type) {
51     case NHW_STATUS:
52         lgfnt.lfHeight = -iflags.wc_fontsiz_status
53                          * GetDeviceCaps(hdc, LOGPIXELSY)
54                          / 72;             // height of font
55         lgfnt.lfWidth = 0;                 // average character width
56         lgfnt.lfEscapement = 0;            // angle of escapement
57         lgfnt.lfOrientation = 0;           // base-line orientation angle
58         lgfnt.lfWeight = FW_NORMAL;        // font weight
59         lgfnt.lfItalic = FALSE;            // italic attribute option
60         lgfnt.lfUnderline = FALSE;         // underline attribute option
61         lgfnt.lfStrikeOut = FALSE;         // strikeout attribute option
62         lgfnt.lfCharSet = mswin_charset(); // character set identifier
63         lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS;   // output precision
64         lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
65         lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
66         if (iflags.wc_font_status && *iflags.wc_font_status) {
67             lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
68             NH_A2W(iflags.wc_font_status, lgfnt.lfFaceName, LF_FACESIZE);
69         } else {
70             lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
71         }
72         break;
73 
74     case NHW_MENU:
75         lgfnt.lfHeight = -iflags.wc_fontsiz_menu
76                          * GetDeviceCaps(hdc, LOGPIXELSY)
77                          / 72;   // height of font
78         lgfnt.lfWidth = 0;       // average character width
79         lgfnt.lfEscapement = 0;  // angle of escapement
80         lgfnt.lfOrientation = 0; // base-line orientation angle
81         lgfnt.lfWeight = (attr == ATR_BOLD || attr == ATR_INVERSE)
82                              ? FW_BOLD
83                              : FW_NORMAL; // font weight
84         lgfnt.lfItalic =
85             (attr == ATR_BLINK) ? TRUE : FALSE; // italic attribute option
86         lgfnt.lfUnderline =
87             (attr == ATR_ULINE) ? TRUE : FALSE; // underline attribute option
88         lgfnt.lfStrikeOut = FALSE;              // strikeout attribute option
89         lgfnt.lfCharSet = mswin_charset();      // character set identifier
90         lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS;   // output precision
91         lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
92         lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
93         if (iflags.wc_font_menu && *iflags.wc_font_menu) {
94             lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
95             NH_A2W(iflags.wc_font_menu, lgfnt.lfFaceName, LF_FACESIZE);
96         } else {
97             lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
98         }
99         break;
100 
101     case NHW_MESSAGE:
102         font_size = (attr == ATR_INVERSE) ? iflags.wc_fontsiz_message + 1
103                                           : iflags.wc_fontsiz_message;
104         lgfnt.lfHeight = -font_size * GetDeviceCaps(hdc, LOGPIXELSY)
105                          / 72;   // height of font
106         lgfnt.lfWidth = 0;       // average character width
107         lgfnt.lfEscapement = 0;  // angle of escapement
108         lgfnt.lfOrientation = 0; // base-line orientation angle
109         lgfnt.lfWeight = (attr == ATR_BOLD || attr == ATR_INVERSE)
110                              ? FW_BOLD
111                              : FW_NORMAL; // font weight
112         lgfnt.lfItalic =
113             (attr == ATR_BLINK) ? TRUE : FALSE; // italic attribute option
114         lgfnt.lfUnderline =
115             (attr == ATR_ULINE) ? TRUE : FALSE; // underline attribute option
116         lgfnt.lfStrikeOut = FALSE;              // strikeout attribute option
117         lgfnt.lfCharSet = mswin_charset();      // character set identifier
118         lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS;   // output precision
119         lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
120         lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
121         if (iflags.wc_font_message && *iflags.wc_font_message) {
122             lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
123             NH_A2W(iflags.wc_font_message, lgfnt.lfFaceName, LF_FACESIZE);
124         } else {
125             lgfnt.lfPitchAndFamily = VARIABLE_PITCH; // pitch and family
126         }
127         break;
128 
129     case NHW_TEXT:
130         lgfnt.lfHeight = -iflags.wc_fontsiz_text
131                          * GetDeviceCaps(hdc, LOGPIXELSY)
132                          / 72;   // height of font
133         lgfnt.lfWidth = 0;       // average character width
134         lgfnt.lfEscapement = 0;  // angle of escapement
135         lgfnt.lfOrientation = 0; // base-line orientation angle
136         lgfnt.lfWeight = (attr == ATR_BOLD || attr == ATR_INVERSE)
137                              ? FW_BOLD
138                              : FW_NORMAL; // font weight
139         lgfnt.lfItalic =
140             (attr == ATR_BLINK) ? TRUE : FALSE; // italic attribute option
141         lgfnt.lfUnderline =
142             (attr == ATR_ULINE) ? TRUE : FALSE; // underline attribute option
143         lgfnt.lfStrikeOut = FALSE;              // strikeout attribute option
144         lgfnt.lfCharSet = mswin_charset();      // character set identifier
145         lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS;   // output precision
146         lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
147         lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
148         if (iflags.wc_font_text && *iflags.wc_font_text) {
149             lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
150             NH_A2W(iflags.wc_font_text, lgfnt.lfFaceName, LF_FACESIZE);
151         } else {
152             lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
153         }
154         break;
155     }
156 
157     fnt = CreateFontIndirect(&lgfnt);
158 
159     /* add font to the table */
160     if (font_index == font_table_size) {
161         if (font_table_size >= MAXFONTS)
162             panic("font table overflow!");
163         font_table_size++;
164     } else {
165         DeleteObject(font_table[font_index].hFont);
166     }
167 
168     font_table[font_index].code = NHFONT_CODE(win_type, attr);
169     font_table[font_index].hFont = fnt;
170     return fnt;
171 }
172 
173 UINT
mswin_charset()174 mswin_charset()
175 {
176     CHARSETINFO cis;
177     if (SYMHANDLING(H_IBM))
178         if (TranslateCharsetInfo((DWORD *) GetOEMCP(), &cis, TCI_SRCCODEPAGE))
179             return cis.ciCharset;
180         else
181             return OEM_CHARSET;
182     else if (TranslateCharsetInfo((DWORD *) GetACP(), &cis, TCI_SRCCODEPAGE))
183         return cis.ciCharset;
184     else
185         return ANSI_CHARSET;
186 }
187 
font_table_cleanup(void)188 void __cdecl font_table_cleanup(void)
189 {
190     int i;
191     for (i = 0; i < font_table_size; i++) {
192         DeleteObject(font_table[i].hFont);
193     }
194     font_table_size = 0;
195 }
196