PageRenderTime 75ms CodeModel.GetById 18ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/src/backend/win32/ftk_display_win32.cpp

http://ftk.googlecode.com/
C++ | 522 lines | 423 code | 63 blank | 36 comment | 39 complexity | e3b5cc65bb023b01c863fd4da27c0b80 MD5 | raw file
  1/*
  2 * File: ftk_display_win32_win32.c
  3 * Author:  Li XianJing <xianjimli@hotmail.com>
  4 * Brief:   win32 display
  5 *
  6 * Copyright (c) 2009 - 2010  Li XianJing <xianjimli@hotmail.com>
  7 *
  8 * Licensed under the Academic Free License version 2.1
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License as published by
 12 * the Free Software Foundation; either version 2 of the License, or
 13 * (at your option) any later version.
 14 *
 15 * This program is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 * GNU General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU General Public License
 21 * along with this program; if not, write to the Free Software
 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23 */
 24
 25/*
 26 * History:
 27 * ================================================================
 28 * 2009-11-17 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include <windows.h>
 33
 34#include "ftk.h"
 35#include "ftk_typedef.h"
 36#include "ftk_log.h"
 37#include "ftk_bitmap.h"
 38#include "ftk_event.h"
 39#include "ftk_globals.h"
 40#include "ftk_wnd_manager.h"
 41#include "ftk_display_win32.h"
 42#include "ftk_input_method_manager.h"
 43#include "ftk_input_method_win32.h"
 44
 45#define DISPLAY_WIDTH  640
 46#define DISPLAY_HEIGHT 480
 47
 48static char szClassName[ ] = "FtkEmulator";
 49static LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);
 50
 51static HWND ftk_create_display_window(void)
 52{
 53    HWND hwnd;               /* This is the handle for our window */
 54    WNDCLASSEX wincl;        /* Data structure for the windowclass */
 55	int width = DISPLAY_WIDTH + GetSystemMetrics(SM_CXFRAME) * 2;
 56	int height = DISPLAY_HEIGHT + GetSystemMetrics(SM_CYFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
 57
 58    /* The Window structure */
 59    wincl.hInstance = NULL;
 60    wincl.lpszClassName = szClassName;
 61    wincl.lpfnWndProc = WinProc;      /* This function is called by windows */
 62    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
 63    wincl.cbSize = sizeof (WNDCLASSEX);
 64
 65    /* Use default icon and mouse-pointer */
 66    wincl.hIcon = NULL;
 67    wincl.hIconSm = NULL;
 68	wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
 69    wincl.lpszMenuName = NULL;                 /* No menu */
 70    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
 71    wincl.cbWndExtra = 64;                      /* structure or the window instance */
 72    /* Use Windows's default color as the background of the window */
 73    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 74
 75    /* Register the window class, and if it fails quit the program */
 76    if (!RegisterClassEx (&wincl))
 77        return 0;
 78
 79    /* The class is registered, let's create the program*/
 80    hwnd = CreateWindowEx (
 81           0,                   /* Extended possibilites for variation */
 82           szClassName,         /* Classname */
 83           "FtkEmulator",       /* Title Text */
 84           WS_OVERLAPPEDWINDOW, /* default window */
 85           CW_USEDEFAULT,       /* Windows decides the position */
 86           CW_USEDEFAULT,       /* where the window ends up on the screen */
 87           width,       /* The programs width */
 88           height,      /* and height in pixels */
 89           HWND_DESKTOP,        /* The window is a child-window to desktop */
 90           NULL,                /* No menu */
 91           NULL,                /* Program Instance handler */
 92           NULL                 /* No Window Creation data */
 93           );
 94
 95	return hwnd;
 96}
 97
 98
 99typedef struct _PrivInfo
100{
101	HWND wnd;
102	void* bits;
103	void* revert_bits;
104	HBITMAP hBitmap;
105	FtkEvent event;
106}PrivInfo;
107
108static LRESULT WinOnPaint(HWND hwnd)
109{
110	HDC dc = NULL;
111	PAINTSTRUCT ps;
112	HBITMAP hBitmap;
113	PrivInfo* priv = NULL;
114	HBITMAP hDisplay = NULL;
115	
116	BeginPaint(hwnd, &ps);
117	priv = (PrivInfo*)GetWindowLong(hwnd, GWL_USERDATA);
118	hDisplay = priv->hBitmap;
119	dc = CreateCompatibleDC(ps.hdc);
120	hBitmap = (HBITMAP)SelectObject(dc, hDisplay);
121	BitBlt(ps.hdc, 0, 0, DISPLAY_WIDTH,	DISPLAY_HEIGHT, dc, 0, 0, SRCCOPY);
122	SelectObject(dc, hBitmap);
123	DeleteObject(dc);
124
125	EndPaint(hwnd, &ps);
126
127	return 0;
128}
129
130static int s_key_map[0xff] = {0};
131
132static Ret ftk_on_key_event(PrivInfo* priv, int down, unsigned char vkey)
133{
134	priv->event.type = down ? FTK_EVT_KEY_DOWN : FTK_EVT_KEY_UP;
135	priv->event.u.key.code = s_key_map[vkey];
136
137	return RET_OK;
138}
139
140static char* ftk_on_ime_event(HWND hwnd, LPARAM lParam)
141{
142	LONG n;
143	char* gb2312;
144	wchar_t* unicode;
145	char* utf8;
146	HIMC himc;
147
148	himc = ImmGetContext(hwnd);
149	if(himc == NULL)
150	{
151		return NULL;
152	}
153	n = ImmGetCompositionString(himc, GCS_RESULTSTR, NULL, 0);
154	if(n <= 0)
155	{
156		ImmReleaseContext(hwnd, himc);
157		return NULL;
158	}
159	gb2312 = (char*) FTK_ALLOC(n + 1);
160	if(gb2312 == NULL)
161	{
162		ImmReleaseContext(hwnd, himc);
163		return NULL;
164	}
165	if(ImmGetCompositionString(himc, GCS_RESULTSTR, gb2312, n) != n)
166	{
167		FTK_FREE(gb2312);
168		ImmReleaseContext(hwnd, himc);
169		return NULL;
170	}
171	ImmReleaseContext(hwnd, himc);
172
173	gb2312[n] = '\0';
174	ftk_logd("%s:%d WM_IME_COMPOSITION:%s\n", __FILE__, __LINE__, gb2312);
175	n = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
176	if(n < 1)
177	{
178		FTK_FREE(gb2312);
179		return NULL;
180	}
181	unicode = (wchar_t*) FTK_ALLOC(n * 2);
182	if(unicode == NULL)
183	{
184		FTK_FREE(gb2312);
185		return NULL;
186	}
187	n = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, unicode, n);
188	if(n < 1)
189	{
190		FTK_FREE(gb2312);
191		FTK_FREE(unicode);
192		return NULL;
193	}
194
195	FTK_FREE(gb2312);
196
197	n = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
198	if(n < 1)
199	{
200		FTK_FREE(unicode);
201		return NULL;
202	}
203	utf8 = (char*) FTK_ALLOC(n);
204	if(utf8 == NULL)
205	{
206		FTK_FREE(unicode);
207		return NULL;
208	}
209	n = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf8, n, NULL, NULL);
210	if(n < 1)
211	{
212		FTK_FREE(unicode);
213		FTK_FREE(utf8);
214		return NULL;
215	}
216
217	FTK_FREE(unicode);
218
219	return utf8;
220}
221
222static LRESULT CALLBACK WinProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
223{
224	PrivInfo* priv = (PrivInfo*)GetWindowLong(hwnd, GWL_USERDATA);
225
226	if(priv != NULL)
227	{
228		memset(&priv->event, 0, sizeof(FtkEvent));
229	}
230
231    switch (message)                  /* handle the messages */
232    {
233        case WM_DESTROY:
234            FTK_QUIT();
235            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
236            break;
237		case WM_PAINT:
238			{
239				WinOnPaint(hwnd);
240				break;
241			}
242		case WM_KEYDOWN:
243		case WM_KEYUP:
244			{
245				ftk_on_key_event(priv, message==WM_KEYDOWN, 0xFF & wParam);
246				break;
247			}
248		case WM_LBUTTONUP:
249		case WM_LBUTTONDOWN:
250			{
251				int xPos = LOWORD(lParam); 
252				int yPos = HIWORD(lParam); 
253				priv->event.u.mouse.x = xPos;
254				priv->event.u.mouse.y = yPos;
255				priv->event.type = message == WM_LBUTTONUP? FTK_EVT_MOUSE_UP : FTK_EVT_MOUSE_DOWN;
256
257				break;
258			}
259		case WM_MOUSEMOVE:
260			{
261				int xPos = LOWORD(lParam); 
262				int yPos = HIWORD(lParam); 
263				priv->event.u.mouse.x = xPos;
264				priv->event.u.mouse.y = yPos;
265				priv->event.type = FTK_EVT_MOUSE_MOVE;
266
267				break;
268			}
269		case WM_IME_COMPOSITION:
270			{
271				char* buf;
272				FtkInputMethod* im = NULL;
273
274				if(!(lParam & GCS_RESULTSTR))
275				{
276					return DefWindowProc(hwnd, message, wParam, lParam);
277				}
278				if(ftk_input_method_manager_get(ftk_default_input_method_manager(), 2, &im) == RET_FAIL || im == NULL)
279				{
280					return DefWindowProc(hwnd, message, wParam, lParam);
281				}
282				if(ftk_input_method_win32_get_editor(im) == NULL)
283				{
284					return DefWindowProc(hwnd, message, wParam, lParam);
285				}
286
287				buf = ftk_on_ime_event(hwnd, lParam);
288				if(buf == NULL)
289				{
290					return DefWindowProc(hwnd, message, wParam, lParam);
291				}
292				priv->event.u.extra = buf;
293				priv->event.type = FTK_EVT_OS_IM_COMMIT;
294				break;
295			}
296        default:                      /* for messages that we don't deal with */
297            return DefWindowProc (hwnd, message, wParam, lParam);
298    }
299
300	if(priv->event.type != FTK_EVT_NOP)
301	{
302		ftk_wnd_manager_queue_event_auto_rotate(ftk_default_wnd_manager(), &priv->event);
303		priv->event.type = FTK_EVT_NOP;
304	}
305    return 0;
306}
307
308static Ret ftk_display_win32_update(FtkDisplay* thiz, FtkBitmap* bitmap, FtkRect* rect, int xoffset, int yoffset)
309{
310	int i = 0;
311	int j = 0;
312	MSG msg;
313	DECL_PRIV(thiz, priv);
314	BITMAPINFO bmi;
315	int display_width  = DISPLAY_WIDTH;
316	int display_height = DISPLAY_HEIGHT;
317	FtkColor* bits = (FtkColor*)priv->bits;
318
319	memset(&bmi, 0x00, sizeof(bmi));
320	bmi.bmiHeader.biBitCount = 32;
321	bmi.bmiHeader.biCompression = BI_RGB;
322	bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
323	bmi.bmiHeader.biWidth = DISPLAY_WIDTH;
324	bmi.bmiHeader.biHeight = DISPLAY_HEIGHT;
325	bmi.bmiHeader.biPlanes = 1;
326
327	ftk_bitmap_copy_to_data_bgra32(bitmap, rect, 
328		priv->bits, xoffset, yoffset, display_width, display_height); 
329
330	/* top-down bitmap */
331	FtkColor* src = (FtkColor*)priv->bits;
332	FtkColor* dst = (FtkColor*)priv->revert_bits + ((DISPLAY_HEIGHT - 1) * DISPLAY_WIDTH);
333	for(j = 0; j < DISPLAY_HEIGHT; j++)
334	{
335		for(i = 0; i < DISPLAY_WIDTH; i++)
336		{
337			dst[i] = src[i];
338		}
339		src += DISPLAY_WIDTH;
340		dst -= DISPLAY_WIDTH;
341	}
342
343	/* The origin for DIBs is the lower-left corner of the bitmap */
344	::SetDIBits(GetDC(priv->wnd), priv->hBitmap, 0, DISPLAY_HEIGHT, priv->revert_bits, &bmi, DIB_RGB_COLORS);
345
346	InvalidateRect(priv->wnd, NULL, FALSE);
347
348	while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
349	{
350		TranslateMessage(&msg);
351		DispatchMessage(&msg);
352		if(msg.message == WM_PAINT) break;
353	}
354
355	return RET_OK;
356}
357
358static int ftk_display_win32_width(FtkDisplay* thiz)
359{
360	return DISPLAY_WIDTH;
361}
362
363static int ftk_display_win32_height(FtkDisplay* thiz)
364{
365	return DISPLAY_HEIGHT;
366}
367
368static Ret ftk_display_win32_snap(FtkDisplay* thiz, FtkRect* r, FtkBitmap* bitmap)
369{
370	FtkRect rect = {0};
371	DECL_PRIV(thiz, priv);
372	int w = ftk_display_width(thiz);
373	int h = ftk_display_height(thiz);
374	int bw = ftk_bitmap_width(bitmap);
375	int bh = ftk_bitmap_height(bitmap);
376	
377	rect.x = r->x;
378	rect.y = r->y;
379	rect.width = FTK_MIN(bw, r->width);
380	rect.height = FTK_MIN(bh, r->height);
381
382	return ftk_bitmap_copy_from_data_bgra32(bitmap, priv->bits, w, h, &rect);
383}
384
385static void ftk_display_win32_destroy(FtkDisplay* thiz)
386{
387	DECL_PRIV(thiz, priv);
388	if(priv != NULL)
389	{
390		CloseWindow(priv->wnd);
391		FTK_FREE(priv->bits);
392		FTK_FREE(priv->revert_bits);
393		DeleteObject(priv->hBitmap);
394		FTK_FREE(thiz);
395	}
396
397	return;
398}
399
400static void ftk_keymap_init(void)
401{
402	s_key_map[0xBD] = FTK_KEY_MINUS;
403	s_key_map[0x20] = FTK_KEY_SPACE;
404	s_key_map[0xBB] = FTK_KEY_EQUAL;
405	s_key_map[0x08] = FTK_KEY_BACKSPACE;
406	s_key_map[0x09] = FTK_KEY_TAB;
407	s_key_map[0xC0] = FTK_KEY_QUOTELEFT;
408	s_key_map[0xDE] = FTK_KEY_QUOTERIGHT;
409	s_key_map[0xDB] = FTK_KEY_BRACKETLEFT;
410	s_key_map[0xDD] = FTK_KEY_BRACKETRIGHT;
411	s_key_map[0x0d] = FTK_KEY_ENTER;
412	s_key_map[0xBA] = FTK_KEY_SEMICOLON;
413	s_key_map[0x30] = FTK_KEY_0;
414	s_key_map[0x31] = FTK_KEY_1; 
415	s_key_map[0x32] = FTK_KEY_2;
416	s_key_map[0x33] = FTK_KEY_3;
417	s_key_map[0x34] = FTK_KEY_4;
418	s_key_map[0x35] = FTK_KEY_5;
419	s_key_map[0x36] = FTK_KEY_6;
420	s_key_map[0x37] = FTK_KEY_7;
421	s_key_map[0x38] = FTK_KEY_8;
422	s_key_map[0x39] = FTK_KEY_9;
423	s_key_map[0x70] = FTK_KEY_F1; 
424	s_key_map[0x71] = FTK_KEY_F2;
425	s_key_map[0x72] = FTK_KEY_F3;
426	s_key_map[0x73] = FTK_KEY_F4;
427	s_key_map[0x74] = FTK_KEY_F5;
428	s_key_map[0x75] = FTK_KEY_F6;
429	s_key_map[0x76] = FTK_KEY_F7;
430	s_key_map[0x77] = FTK_KEY_F8;
431	s_key_map[0x78] = FTK_KEY_F9;
432	s_key_map[0xBC] = FTK_KEY_COMMA;
433	s_key_map[0xBE] = FTK_KEY_DOT;
434	s_key_map[0xBF] = FTK_KEY_SLASH;
435	s_key_map[0x10] = FTK_KEY_RIGHTSHIFT;
436	s_key_map[0x11] = FTK_KEY_LEFTCTRL;
437	s_key_map[0x14] = FTK_KEY_CAPSLOCK;
438	s_key_map[0x40] = FTK_KEY_LEFTALT;
439	s_key_map[0x41] = FTK_KEY_a;
440	s_key_map[0x42] = FTK_KEY_b;
441	s_key_map[0x43] = FTK_KEY_c;
442	s_key_map[0x44] = FTK_KEY_d;
443	s_key_map[0x45] = FTK_KEY_e;
444	s_key_map[0x46] = FTK_KEY_f;
445	s_key_map[0x47] = FTK_KEY_g;
446	s_key_map[0x48] = FTK_KEY_h;
447	s_key_map[0x49] = FTK_KEY_i;
448	s_key_map[0x4a] = FTK_KEY_j;
449	s_key_map[0x4b] = FTK_KEY_k;
450	s_key_map[0x4c] = FTK_KEY_l;
451	s_key_map[0x4d] = FTK_KEY_m;
452	s_key_map[0x4e] = FTK_KEY_n;
453	s_key_map[0x4f] = FTK_KEY_o;
454	s_key_map[0x50] = FTK_KEY_p;
455	s_key_map[0x51] = FTK_KEY_q;
456	s_key_map[0x52] = FTK_KEY_r;
457	s_key_map[0x53] = FTK_KEY_s;
458	s_key_map[0x54] = FTK_KEY_t;
459	s_key_map[0x55] = FTK_KEY_u;
460	s_key_map[0x56] = FTK_KEY_v;
461	s_key_map[0x57] = FTK_KEY_w;
462	s_key_map[0x58] = FTK_KEY_x;
463	s_key_map[0x59] = FTK_KEY_y;
464	s_key_map[0x5a] = FTK_KEY_z;
465	s_key_map[0x21] = FTK_KEY_PAGEUP;
466	s_key_map[0x25] = FTK_KEY_LEFT;
467	s_key_map[0x27] = FTK_KEY_RIGHT;
468	s_key_map[0x24] = FTK_KEY_HOME;
469	s_key_map[0x23] = FTK_KEY_END;
470	s_key_map[0x28] = FTK_KEY_DOWN;
471	s_key_map[0x22] = FTK_KEY_PAGEDOWN;
472	s_key_map[0x2d] = FTK_KEY_INSERT;
473	s_key_map[0x2e] = FTK_KEY_DELETE;
474	s_key_map[0x26] = FTK_KEY_UP;
475
476	return;
477}
478
479FtkDisplay* ftk_display_win32_create(void)
480{
481	FtkDisplay* thiz = (FtkDisplay*)FTK_ZALLOC(sizeof(FtkDisplay) + sizeof(PrivInfo));
482
483	if(thiz != NULL)
484	{
485		PrivInfo* p = NULL;
486		BITMAPINFO bmi = {0};
487		HBITMAP hBitmap = NULL;
488		DECL_PRIV(thiz, priv);
489
490		thiz->update   = ftk_display_win32_update;
491		thiz->width    = ftk_display_win32_width;
492		thiz->height   = ftk_display_win32_height;
493		thiz->snap     = ftk_display_win32_snap;
494		thiz->destroy  = ftk_display_win32_destroy;
495
496		priv->wnd = ftk_create_display_window();
497
498		memset(&bmi, 0x00, sizeof(bmi));
499
500		bmi.bmiHeader.biBitCount = 32;
501		bmi.bmiHeader.biHeight   = DISPLAY_HEIGHT;
502		bmi.bmiHeader.biWidth    = DISPLAY_HEIGHT;
503		bmi.bmiHeader.biSize     = sizeof(bmi.bmiHeader);
504		bmi.bmiHeader.biPlanes   = 1;
505		bmi.bmiHeader.biCompression = BI_RGB;
506		bmi.bmiHeader.biSizeImage = 0;
507
508		hBitmap = CreateBitmap(DISPLAY_WIDTH, DISPLAY_HEIGHT, 1, 32, NULL);
509		priv->hBitmap = hBitmap;
510		priv->bits = FTK_ZALLOC(DISPLAY_WIDTH * DISPLAY_HEIGHT * 4);
511		priv->revert_bits = FTK_ZALLOC(DISPLAY_WIDTH * DISPLAY_HEIGHT * 4);
512
513		SetWindowLong(priv->wnd, GWL_USERDATA, (LONG)priv);
514		ShowWindow (priv->wnd, SW_SHOW);
515		UpdateWindow(priv->wnd);
516
517		ftk_keymap_init();
518	}
519
520	return thiz;
521}
522