1 /**
2  * xrdp: A Remote Desktop Protocol server.
3  *
4  * Copyright (C) Jay Sorg 2004-2012
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <windows.h>
20 #include <tchar.h>
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include "os_calls.h"
26 #include "arch.h"
27 
28 static HINSTANCE g_instance = 0;
29 static HWND g_wnd = 0;
30 static HWND g_lb = 0;
31 static HWND g_exit_button = 0;
32 static HWND g_go_button = 0;
33 static HWND g_font_list = 0;
34 static char g_font_name[512] = "";
35 static int g_font_size = 10;
36 static HFONT g_font = 0;
37 static int g_running = 0;
38 
39 #define FONT_DATASIZE(_w, _h) (((_h * ((_w + 7) / 8)) + 3) & ~3)
40 
41 /*****************************************************************************/
42 int
check_messages(void)43 check_messages(void)
44 {
45     MSG msg;
46 
47     while (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
48     {
49         GetMessage(&msg, NULL, 0, 0);
50         TranslateMessage(&msg);
51         DispatchMessage(&msg);
52     }
53 
54     return 0;
55 }
56 
57 /*****************************************************************************/
58 static int
msg(char * msg1,...)59 msg(char *msg1, ...)
60 {
61     va_list ap;
62     char text1[512];
63 
64     va_start(ap, msg1);
65     vsnprintf(text1, 511, msg1, ap);
66     SendMessageA(g_lb, LB_ADDSTRING, 0, (LPARAM)text1);
67     va_end(ap);
68     return 0;
69 }
70 
71 /*****************************************************************************/
72 static int
show_last_error(void)73 show_last_error(void)
74 {
75     LPVOID lpMsgBuf;
76 
77     FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
78                    NULL, GetLastError(),
79                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
80                    (LPSTR)&lpMsgBuf, 0, NULL);
81     msg("GetLastError - %s", lpMsgBuf);
82     LocalFree(lpMsgBuf);
83     return 0;
84 }
85 
86 /*****************************************************************************/
87 static int
font_dump(void)88 font_dump(void)
89 {
90     HDC dc;
91     HDC dc1;
92     RECT rect;
93     HBRUSH brush;
94     HGDIOBJ saved;
95     HBITMAP bitmap;
96     BITMAPINFO bi;
97     char *bits;
98     ABC abc;
99     SIZE sz;
100     char filename[256];
101     TCHAR text[256];
102     char zero1;
103     char *bmtext;
104     int bmtextindex;
105     int fd;
106     int x1;
107     int strlen1;
108     int index1;
109     int index2;
110     int len;
111     int pixel;
112     int red;
113     int green;
114     int blue;
115     int width;
116     int height;
117     int roller;
118     int outlen;
119     tui8 b1;
120     short x2;
121 
122     if (g_running)
123     {
124         return 0;
125     }
126 
127     g_running = 1;
128     msg("starting");
129     g_font_name[0] = 0;
130     SendMessageA(g_font_list, WM_GETTEXT, 255, (LPARAM)g_font_name);
131 
132     if (g_strlen(g_font_name) == 0)
133     {
134         msg("error font not set");
135         g_running = 0;
136         return 1;
137     }
138 
139     dc = GetDC(g_wnd);
140     height = -MulDiv(g_font_size, GetDeviceCaps(dc, LOGPIXELSY), 72);
141     g_font = CreateFontA(height, 0, 0, 0, FW_DONTCARE, 0, 0, 0, 0, 0, 0,
142                          0, 0, g_font_name);
143     ReleaseDC(g_wnd, dc);
144 
145     if (g_font == 0)
146     {
147         msg("error - Font creation failed");
148     }
149 
150     zero1 = 0;
151     g_snprintf(filename, 255, "%s-%d.fv1", g_font_name, g_font_size);
152     msg("creating file %s", filename);
153     g_file_delete(filename);
154     fd = g_file_open(filename);
155     g_file_write(fd, "FNT1", 4);
156     strlen1 = g_strlen(g_font_name);
157     g_file_write(fd, g_font_name, strlen1);
158     x1 = strlen1;
159 
160     while (x1 < 32)
161     {
162         g_file_write(fd, &zero1, 1);
163         x1++;
164     }
165 
166     x2 = g_font_size; /* font size */
167     g_file_write(fd, (char *)&x2, 2);
168     x2 = 1; /* style */
169     g_file_write(fd, (char *)&x2, 2);
170     /* pad */
171     index1 = 0;
172 
173     while (index1 < 8)
174     {
175         g_file_write(fd, &zero1, 1);
176         index1++;
177     }
178 
179     for (x1 = 32; x1 < 0x4e00; x1++)
180     {
181         check_messages();
182         dc = GetWindowDC(g_wnd);
183         saved = SelectObject(dc, g_font);
184 
185         if (!GetCharABCWidths(dc, x1, x1, &abc))
186         {
187             show_last_error();
188         }
189 
190         text[0] = (TCHAR)x1;
191         text[1] = 0;
192 
193         if (!GetTextExtentPoint32(dc, text, 1, &sz))
194         {
195             show_last_error();
196         }
197 
198         SelectObject(dc, saved);
199         ReleaseDC(g_wnd, dc);
200 
201         if ((sz.cx > 0) && (sz.cy > 0))
202         {
203             dc = GetWindowDC(g_wnd);
204             saved = SelectObject(dc, g_font);
205             SetBkColor(dc, RGB(255, 255, 255));
206 
207             if (!ExtTextOut(dc, 50, 50, ETO_OPAQUE, 0, text, 1, 0))
208             {
209                 show_last_error();
210             }
211 
212             SelectObject(dc, saved);
213             ReleaseDC(g_wnd, dc);
214             Sleep(10);
215             /* width */
216             x2 = abc.abcB;
217             g_file_write(fd, (char *)&x2, 2);
218             /* height */
219             x2 = sz.cy;
220             g_file_write(fd, (char *)&x2, 2);
221             /* baseline */
222             x2 = -sz.cy;
223             g_file_write(fd, (char *)&x2, 2);
224             /* offset */
225             x2 = abc.abcA;
226             g_file_write(fd, (char *)&x2, 2);
227             /* incby */
228             x2 = sz.cx;
229             g_file_write(fd, (char *)&x2, 2);
230             /* pad */
231             index1 = 0;
232 
233             while (index1 < 6)
234             {
235                 g_file_write(fd, &zero1, 1);
236                 index1++;
237             }
238 
239             dc = GetWindowDC(g_wnd);
240             rect.left = 50 + abc.abcA;
241             rect.top = 50;
242             rect.right = rect.left + abc.abcB;
243             rect.bottom = rect.top + sz.cy;
244             memset(&bi, 0, sizeof(bi));
245             width = (abc.abcB + 7) & (~7);
246             height = sz.cy;
247             bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
248             bi.bmiHeader.biWidth = width;
249             bi.bmiHeader.biHeight = height;
250             bi.bmiHeader.biPlanes = 1;
251             bi.bmiHeader.biBitCount = 32;
252             bitmap = CreateDIBSection(dc, &bi, DIB_RGB_COLORS, (void *)&bits, 0, 0);
253 
254             if (bitmap == 0)
255             {
256                 msg("error - CreateDIBSection failed");
257             }
258             else
259             {
260                 memset(bits, 0, width * height * 4);
261                 dc1 = CreateCompatibleDC(dc);
262                 SelectObject(dc1, bitmap);
263 
264                 if (!BitBlt(dc1, 0, 0, width, height, dc, rect.left, rect.top, SRCCOPY))
265                 {
266                     show_last_error();
267                 }
268 
269                 bmtext = (char *)g_malloc(width * height + 16, 1);
270                 bmtextindex = 0;
271 
272                 for (index1 = (height - 1); index1 >= 0; index1--)
273                 {
274                     for (index2 = 0; index2 < width; index2++)
275                     {
276                         pixel = ((int *)bits)[index1 * width + index2];
277                         red = (pixel >> 16) & 0xff;
278                         green = (pixel >> 8) & 0xff;
279                         blue = (pixel >> 0) & 0xff;
280 
281                         if (red == 0 && green == 0 && blue == 0)
282                         {
283                             bmtext[bmtextindex] = '1';
284                             bmtextindex++;
285                         }
286                         else
287                         {
288                             bmtext[bmtextindex] = '0';
289                             bmtextindex++;
290                         }
291                     }
292                 }
293 
294                 outlen = 0;
295                 b1 = 0;
296                 roller = 0;
297                 len = g_strlen(bmtext);
298 
299                 for (index2 = 0; index2 < len; index2++)
300                 {
301                     if (bmtext[index2] == '1')
302                     {
303                         switch (roller)
304                         {
305                             case 0:
306                                 b1 = b1 | 0x80;
307                                 break;
308                             case 1:
309                                 b1 = b1 | 0x40;
310                                 break;
311                             case 2:
312                                 b1 = b1 | 0x20;
313                                 break;
314                             case 3:
315                                 b1 = b1 | 0x10;
316                                 break;
317                             case 4:
318                                 b1 = b1 | 0x08;
319                                 break;
320                             case 5:
321                                 b1 = b1 | 0x04;
322                                 break;
323                             case 6:
324                                 b1 = b1 | 0x02;
325                                 break;
326                             case 7:
327                                 b1 = b1 | 0x01;
328                                 break;
329                         }
330                     }
331 
332                     roller++;
333 
334                     if (roller == 8)
335                     {
336                         roller = 0;
337                         g_file_write(fd, &b1, 1);
338                         outlen++;
339                         b1 = 0;
340                     }
341                 }
342 
343                 while ((outlen % 4) != 0)
344                 {
345                     g_file_write(fd, &zero1, 1);
346                     outlen++;
347                 }
348 
349                 free(bmtext);
350                 DeleteDC(dc1);
351                 DeleteObject(bitmap);
352             }
353 
354             if (sz.cx != (long)(abc.abcA + abc.abcB + abc.abcC))
355             {
356                 msg("error - width not right 1");
357             }
358 
359             brush = CreateSolidBrush(RGB(255, 255, 255));
360             FillRect(dc, &rect, brush);
361             DeleteObject(brush);
362             ReleaseDC(g_wnd, dc);
363         }
364         else
365         {
366             /* write out a blank glyph here */
367             /* width */
368             x2 = 1;
369             g_file_write(fd, (char *)&x2, 2);
370             /* height */
371             x2 = 1;
372             g_file_write(fd, (char *)&x2, 2);
373             /* baseline */
374             x2 = 0;
375             g_file_write(fd, (char *)&x2, 2);
376             /* offset */
377             x2 = 0;
378             g_file_write(fd, (char *)&x2, 2);
379             /* incby */
380             x2 = 1;
381             g_file_write(fd, (char *)&x2, 2);
382             /* pad */
383             index1 = 0;
384 
385             while (index1 < 6)
386             {
387                 g_file_write(fd, &zero1, 1);
388                 index1++;
389             }
390 
391             /* blank bitmap */
392             index1 = 0;
393 
394             while (index1 < 4)
395             {
396                 g_file_write(fd, &zero1, 1);
397                 index1++;
398             }
399         }
400     }
401 
402     g_file_close(fd);
403     msg("done");
404     g_running = 0;
405     return 0;
406 }
407 
408 /*****************************************************************************/
409 static LRESULT CALLBACK
wnd_proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)410 wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
411 {
412     PAINTSTRUCT ps;
413     HBRUSH brush;
414     RECT rect;
415 
416     switch (message)
417     {
418         case WM_PAINT:
419             BeginPaint(hWnd, &ps);
420             brush = CreateSolidBrush(RGB(255, 255, 255));
421             rect = ps.rcPaint;
422             FillRect(ps.hdc, &rect, brush);
423             DeleteObject(brush);
424             EndPaint(hWnd, &ps);
425             break;
426         case WM_CLOSE:
427             DestroyWindow(g_wnd);
428             g_wnd = 0;
429             break;
430         case WM_DESTROY:
431             PostQuitMessage(0);
432             break;
433         case WM_TIMER:
434             KillTimer(g_wnd, 1);
435             font_dump();
436             break;
437         case WM_COMMAND:
438 
439             if ((HWND)lParam == g_exit_button)
440             {
441                 PostMessage(g_wnd, WM_CLOSE, 0, 0);
442             }
443             else if ((HWND)lParam == g_go_button)
444             {
445                 while (SendMessage(g_lb, LB_GETCOUNT, 0, 0) > 0)
446                 {
447                     SendMessage(g_lb, LB_DELETESTRING, 0, 0);
448                 }
449 
450                 SetTimer(g_wnd, 1, 1000, 0);
451             }
452 
453             break;
454     }
455 
456     return DefWindowProc(hWnd, message, wParam, lParam);
457 }
458 
459 /*****************************************************************************/
460 static int
create_window(void)461 create_window(void)
462 {
463     WNDCLASS wc;
464     DWORD style;
465     HDC dc;
466     int height;
467     int left;
468     int top;
469 
470     ZeroMemory(&wc, sizeof(wc));
471     wc.lpfnWndProc = wnd_proc; /* points to window procedure */
472     /* name of window class */
473     wc.lpszClassName = _T("fontdump");
474     wc.hCursor = LoadCursor(0, IDC_ARROW);
475 
476     /* Register the window class. */
477     if (!RegisterClass(&wc))
478     {
479         return 0; /* Failed to register window class */
480     }
481 
482     style = WS_OVERLAPPED | WS_CAPTION | WS_POPUP | WS_MINIMIZEBOX |
483             WS_SYSMENU | WS_SIZEBOX | WS_MAXIMIZEBOX;
484     left = GetSystemMetrics(SM_CXSCREEN) / 2 - 640 / 2;
485     top = GetSystemMetrics(SM_CYSCREEN) / 2 - 480 / 2;
486     g_wnd = CreateWindow(wc.lpszClassName, _T("fontdump"),
487                          style, left, top, 640, 480,
488                          (HWND) NULL, (HMENU) NULL, g_instance,
489                          (LPVOID) NULL);
490     style = WS_CHILD | WS_VISIBLE | WS_BORDER;
491     g_lb = CreateWindow(_T("LISTBOX"), _T("LISTBOX1"), style,
492                         200, 10, 400, 400, g_wnd, 0, g_instance, 0);
493     style = WS_CHILD | WS_VISIBLE;
494     g_exit_button = CreateWindow(_T("BUTTON"), _T("Exit"), style,
495                                  540, 410, 75, 25, g_wnd, 0, g_instance, 0);
496     g_go_button = CreateWindow(_T("BUTTON"), _T("Go"), style,
497                                440, 410, 75, 25, g_wnd, 0, g_instance, 0);
498     style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWN;
499     g_font_list = CreateWindow(_T("COMBOBOX"), _T("COMBOBOX1"), style,
500                                50, 250, 125, 125, g_wnd, 0, g_instance, 0);
501     ShowWindow(g_wnd, SW_SHOWNORMAL);
502     PostMessage(g_wnd, WM_SETFONT, (WPARAM)g_font, 0);
503     SendMessageA(g_font_list, CB_ADDSTRING, 0, (LPARAM)"Tahoma");
504     SendMessageA(g_font_list, CB_ADDSTRING, 0, (LPARAM)"DejaVu Serif");
505     SendMessageA(g_font_list, CB_ADDSTRING, 0, (LPARAM)"DejaVu Sans");
506     SendMessageA(g_font_list, CB_ADDSTRING, 0, (LPARAM)"Arial");
507     SendMessageA(g_font_list, CB_ADDSTRING, 0, (LPARAM)"Comic Sans MS");
508     return 0;
509 }
510 
511 /*****************************************************************************/
512 static int
main_loop(void)513 main_loop(void)
514 {
515     MSG msg;
516 
517     while (GetMessage(&msg, NULL, 0, 0))
518     {
519         TranslateMessage(&msg);
520         DispatchMessage(&msg);
521     }
522 
523     return (int)(msg.wParam);
524 }
525 
526 /*****************************************************************************/
527 int WINAPI
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)528 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
529         LPSTR lpCmdLine, int nCmdShow)
530 {
531     g_instance = hInstance;
532     create_window();
533     return main_loop();
534 }
535