a6b6d92200fae5bc17b0c212d3db90d03d950c4a
[reactos.git] / reactos / lib / rosky / libskygi / libskygi.c
1 /*
2 * ROSky - SkyOS Application Layer
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 /* $Id: libskygi.c,v 1.9 2004/08/14 01:03:38 weiden Exp $
20 *
21 * PROJECT: SkyOS GI library
22 * FILE: lib/libskygi/libskygi.c
23 * PURPOSE: SkyOS GI library
24 *
25 * UPDATE HISTORY:
26 * 08/12/2004 Created
27 */
28 #include <windows.h>
29 #include <stdio.h>
30 #include <rosky/rosky.h>
31 #include "libskygi.h"
32 #include "resource.h"
33
34 typedef struct
35 {
36 s_window Window;
37 HWND hWnd;
38 } SKY_WINDOW, *PSKY_WINDOW;
39
40 typedef struct
41 {
42 widget_menu Menu;
43 HMENU hMenu;
44 } SKY_MENU, *PSKY_MENU;
45
46 typedef struct
47 {
48 widget_menu_item MenuItem;
49 MENUITEMINFOW MenuItemInfo;
50 } SKY_MENUITEM, *PSKY_MENUITEM;
51
52 typedef struct
53 {
54 GC GraphicsContext;
55 HDC hDC;
56 } SKY_GC, *PSKY_GC;
57
58 typedef struct
59 {
60 DIB Dib;
61 HBITMAP hBitmap;
62 HDC hAssociateDC;
63 } SKY_DIB, *PSKY_DIB;
64
65 static ATOM SkyClassAtom;
66 static BOOL SkyClassRegistered = FALSE;
67
68 /**
69 * Map a SkyOS window style to Windows one.
70 *
71 * @param SkyStyle SkyOS window style (WF_* flags).
72 * @param ExStyle Contains Windows extended window style on exit.
73 *
74 * @return Windows window style (WS_* flags).
75 *
76 * @todo Handle
77 * WF_MODAL, WF_HAS_MENU, WF_HAS_STATUSBAR, WF_FREEFORM, WF_FOCUSABLE,
78 * WF_USER, WF_DESKTOP, WF_NOT_MOVEABLE, WF_NO_BUTTONS, WF_TRANSPARENT,
79 * WF_NO_INITIAL_DRAW, WF_USE_BACKGROUND, WF_DONT_EREASE_BACKGROUND,
80 * WF_NO_FRAME.
81 */
82 ULONG
83 IntMapWindowStyle(ULONG SkyStyle, ULONG *ExStyle)
84 {
85 ULONG Style;
86
87 Style = (SkyStyle & WF_HIDE) ? 0 : WS_VISIBLE;
88 Style |= (SkyStyle & WF_NO_TITLE) ? 0 : WS_CAPTION;
89 Style |= (SkyStyle & WF_NOT_SIZEABLE) ? WS_THICKFRAME : 0;
90 Style |= (SkyStyle & WF_POPUP) ? WS_POPUP : 0;
91 Style |= (SkyStyle & WF_NO_BUTTONS) ? 0 :
92 ((SkyStyle & WF_NOT_SIZEABLE) ? 0 : WS_MAXIMIZEBOX) |
93 WS_MINIMIZEBOX | WS_SYSMENU;
94 *ExStyle = (SkyStyle & WF_SMALL_TITLE) ? WS_EX_TOOLWINDOW : 0;
95
96 return Style;
97 }
98
99
100 /**
101 * Dispatch a Sky Message to the appropriate window callback
102 *
103 * @param win Specifies the destination window
104 * @param type The type of the message (see MSG_ constants)
105 * @param para1 Additional parameter 1
106 * @param para2 Additional parameter 2
107 *
108 * @return Returns the return value of the window callback function
109 */
110 unsigned long
111 IntDispatchMsg(s_window *win, unsigned int type, unsigned int para1, unsigned int para2)
112 {
113 s_gi_msg msg;
114 unsigned long Ret;
115
116 /* fill the members of the struct */
117 msg.win = win;
118 msg.type = type;
119 msg.para1 = para1;
120 msg.para2 = para2;
121 msg.next = NULL; /* ??? */
122 msg.prev = NULL; /* ??? */
123 /* FIXME */
124 msg.timestamp = (unsigned long long)GetTickCount() * 1000LL;
125
126 DBG("Dispatching window (0x%x) message type %d\n", win, type);
127 Ret = win->win_func(win, &msg);
128 DBG("Dispatched window (0x%x) message type %d, returned 0x%x\n", win, type, Ret);
129 return Ret;
130 }
131
132
133 /**
134 * Dispatch a Sky Message with a update rect to the appropriate window callback
135 *
136 * @param win Specifies the destination window
137 * @param type The type of the message (see MSG_ constants)
138 * @param para1 Additional parameter 1
139 * @param para2 Additional parameter 2
140 * @param rect Rectangle of the window to be repainted
141 *
142 * @return Returns the return value of the window callback function
143 */
144 unsigned long
145 IntDispatchMsgRect(s_window *win, unsigned int type, unsigned int para1, unsigned int para2, s_region *rect)
146 {
147 s_gi_msg msg;
148 unsigned long Ret;
149
150 /* fill the members of the struct */
151 msg.win = win;
152 msg.type = type;
153 msg.para1 = para1;
154 msg.para2 = para2;
155 msg.next = NULL; /* ??? */
156 msg.prev = NULL; /* ??? */
157 msg.rect = *rect;
158 /* FIXME */
159 msg.timestamp = (unsigned long long)GetTickCount() * 1000LL;
160
161 DBG("Dispatching window (0x%x) message type %d\n", win, type);
162 Ret = win->win_func(win, &msg);
163 DBG("Dispatched window (0x%x) message type %d, returned 0x%x\n", win, type, Ret);
164 return Ret;
165 }
166
167
168 /**
169 * Determines whether a win32 message should cause a Sky message to be dispatched
170 *
171 * @param skw Specifies the destination window
172 * @param Msg Contains the win32 message
173 * @param smsg Address to the sky message structure that will be filled in with
174 * appropriate information in case a sky message should be dispatched
175 *
176 * @return Returns TRUE if a Sky message should be dispatched
177 */
178 BOOL
179 IntIsSkyMessage(PSKY_WINDOW skw, MSG *Msg, s_gi_msg *smsg)
180 {
181 smsg->win = skw;
182
183 switch(Msg->message)
184 {
185 case WM_DESTROY:
186 smsg->type = MSG_DESTROY;
187 smsg->para1 = 0;
188 smsg->para2 = 0;
189 return TRUE;
190
191 case WM_PAINT:
192 {
193 RECT rc;
194 PAINTSTRUCT ps;
195
196 if(GetUpdateRect(skw->hWnd, &rc, FALSE))
197 {
198 BeginPaint(skw->hWnd, &ps);
199 EndPaint(skw->hWnd, &ps);
200
201 smsg->type = MSG_GUI_REDRAW;
202 smsg->para1 = 0;
203 smsg->para2 = 0;
204
205 smsg->rect.x1 = rc.left;
206 smsg->rect.y1 = rc.top;
207 smsg->rect.x2 = rc.right;
208 smsg->rect.y2 = rc.bottom;
209
210 return TRUE;
211 }
212 break;
213 }
214
215 case WM_QUIT:
216 smsg->type = MSG_QUIT;
217 smsg->para1 = 0;
218 smsg->para2 = 0;
219 return TRUE;
220
221 case WM_LBUTTONDOWN:
222 case WM_LBUTTONUP:
223 case WM_RBUTTONDOWN:
224 case WM_RBUTTONUP:
225 {
226 POINT pt;
227
228 switch (Msg->message)
229 {
230 case WM_LBUTTONDOWN: smsg->type = MSG_MOUSE_BUT1_PRESSED; break;
231 case WM_LBUTTONUP: smsg->type = MSG_MOUSE_BUT1_RELEASED; break;
232 case WM_RBUTTONDOWN: smsg->type = MSG_MOUSE_BUT2_PRESSED; break;
233 case WM_RBUTTONUP: smsg->type = MSG_MOUSE_BUT2_RELEASED; break;
234 }
235 #if 0
236 pt.x = LOWORD(Msg->lParam);
237 pt.y = HIWORD(Msg->lParam);
238 #else
239 pt = Msg->pt;
240 MapWindowPoints(NULL, skw->hWnd, &pt, 1);
241 #endif
242 smsg->para1 = pt.x;
243 smsg->para2 = pt.y;
244 return TRUE;
245 }
246
247 case WM_COMMAND:
248 smsg->type = MSG_COMMAND;
249 smsg->para1 = LOWORD(Msg->wParam);
250 return TRUE;
251 }
252
253 return FALSE;
254 }
255
256
257 /**
258 * The standard win32 window procedure that handles win32 messages delivered from ReactOS
259 *
260 * @param hWnd Handle of the window
261 * @param msg Specifies the type of the message
262 * @param wParam Additional data to the message
263 * @param lParam Additional data to the message
264 *
265 * @return Depends on the message type
266 */
267 LRESULT CALLBACK
268 IntDefaultWin32Proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
269 {
270 PSKY_WINDOW skw;
271
272 if (msg == WM_NCCREATE)
273 {
274 /*
275 * Save the pointer to the structure so we can access it later when
276 * dispatching the Win32 messages so we know which sky window it is
277 * and dispatch the right messages.
278 */
279 skw = (PSKY_WINDOW)((LPCREATESTRUCTW)lParam)->lpCreateParams;
280 SetWindowLongPtr(hWnd, GWL_USERDATA, (ULONG_PTR)skw);
281 }
282 else
283 {
284 skw = (PSKY_WINDOW)GetWindowLongPtr(hWnd, GWL_USERDATA);
285 if (skw == NULL)
286 return DefWindowProcW(hWnd, msg, wParam, lParam);
287 }
288
289 switch(msg)
290 {
291 case WM_CLOSE:
292 IntDispatchMsg(&skw->Window, MSG_DESTROY, 0, 0);
293 return 0;
294
295 case WM_CREATE:
296 return 1;
297
298 /* FIXME: Find a more general solution! */
299 /* We can get there for message sent by SendMessage. */
300 case WM_PAINT:
301 {
302 PAINTSTRUCT ps;
303 s_region srect;
304
305 BeginPaint(hWnd, &ps);
306 srect.x1 = ps.rcPaint.left;
307 srect.y1 = ps.rcPaint.top;
308 srect.x2 = ps.rcPaint.right;
309 srect.y2 = ps.rcPaint.bottom;
310 IntDispatchMsgRect(&skw->Window, MSG_GUI_REDRAW, 0, 0, &srect);
311 EndPaint(hWnd, &ps);
312
313 return 0;
314 }
315
316 case WM_COMMAND:
317 IntDispatchMsg(&skw->Window, MSG_COMMAND, LOWORD(wParam), 0);
318 return 0;
319
320 case WM_ERASEBKGND:
321 return 1; /* don't handle this message */
322 }
323
324 return DefWindowProcW(hWnd, msg, wParam, lParam);
325 }
326
327
328 /**
329 * Registers a Win32 window class for all Sky windows
330 *
331 * @return Returns the atom of the class registered.
332 */
333 ATOM
334 IntRegisterClass(void)
335 {
336 WNDCLASSW wc;
337
338 wc.lpszClassName = L"ROSkyWindow";
339 wc.lpfnWndProc = IntDefaultWin32Proc;
340 wc.style = CS_VREDRAW | CS_HREDRAW;
341 wc.hInstance = GetModuleHandleW(NULL);
342 wc.hIcon = LoadIcon(NULL, (LPCTSTR)IDI_APPLICATION);
343 wc.hCursor = LoadCursor(NULL, (LPCTSTR)IDC_ARROW);
344 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
345 wc.lpszMenuName = NULL;
346 wc.cbClsExtra = 0;
347 wc.cbWndExtra = 0;
348
349 return RegisterClassW(&wc);
350 }
351
352
353 /*
354 * @implemented
355 */
356 s_window* __cdecl
357 GI_create_app(app_para *p)
358 {
359 PSKY_WINDOW skw;
360 ULONG Style, ExStyle;
361 WCHAR WindowName[sizeof(p->cpName) / sizeof(p->cpName[0])];
362 RECT ClientRect;
363
364 DBG("GI_create_app(0x%x)\n", p);
365
366 /* FIXME - lock */
367 if(!SkyClassRegistered)
368 {
369 SkyClassAtom = IntRegisterClass();
370 SkyClassRegistered = SkyClassAtom != 0;
371
372 if(!SkyClassRegistered)
373 {
374 DBG("Unable to register the ROSkyWindow class\n");
375 return NULL;
376 }
377 }
378 /* FIXME - unlock */
379
380 skw = (PSKY_WINDOW)HeapAlloc(GetProcessHeap(),
381 HEAP_ZERO_MEMORY,
382 sizeof(SKY_WINDOW));
383 if(skw == NULL)
384 {
385 DBG("Not enough memory to allocate a SKY_WINDOW structure!\n");
386 return NULL;
387 }
388
389 /* Convert the Sky window style to a Win32 window style */
390 Style = IntMapWindowStyle(p->ulStyle, &ExStyle);
391
392 /* convert the window caption to unicode */
393 MultiByteToWideChar(CP_UTF8, 0, p->cpName, -1, WindowName,
394 sizeof(WindowName) / sizeof(WindowName[0]));
395
396 skw->Window.win_func = p->win_func;
397 /* FIXME - fill the window structure */
398
399 /*
400 * We must convert the client rect passed in to the window rect expected
401 * by CreateWindowExW.
402 */
403 ClientRect.left = 0;
404 ClientRect.top = 0;
405 ClientRect.right = 0 + p->ulWidth;
406 ClientRect.bottom = 0 + p->ulHeight;
407 AdjustWindowRectEx(&ClientRect, Style, p->ulStyle & WF_HAS_MENU, ExStyle);
408
409 DBG("Menu: %x\n", p->pMenu ? ((PSKY_MENU)p->pMenu)->hMenu : NULL);
410
411 /* create the Win32 window */
412 skw->hWnd = CreateWindowExW(ExStyle,
413 L"ROSkyWindow",
414 WindowName,
415 WS_OVERLAPPEDWINDOW,
416 p->ulX,
417 p->ulY,
418 ClientRect.right - ClientRect.left,
419 ClientRect.bottom - ClientRect.top,
420 NULL,
421 p->pMenu ? ((PSKY_MENU)p->pMenu)->hMenu : NULL,
422 GetModuleHandleW(NULL),
423 skw);
424
425 if(skw->hWnd == NULL)
426 {
427 DBG("CreateWindow() failed!\n");
428 HeapFree(GetProcessHeap(), 0, skw);
429 return NULL;
430 }
431
432 DBG("Created Win32 window: 0x%x\n", skw->hWnd);
433
434 return &skw->Window;
435 }
436
437 /*
438 * @implemented
439 */
440 int __cdecl
441 GI_destroy_window(s_window *win)
442 {
443 PSKY_WINDOW skw = (PSKY_WINDOW)win;
444
445 DBG("GI_destroy_window(0x%x)\n", win);
446 DestroyWindow(skw->hWnd);
447 HeapFree(GetProcessHeap(), 0, skw);
448
449 return 0;
450 }
451
452
453 /*
454 * @implemented
455 */
456 unsigned int __cdecl
457 GI_wait_message(s_gi_msg *m,
458 s_window* w)
459 {
460 MSG Msg;
461 BOOL Ret, SkyMessage;
462 HWND hwndFilter;
463 PSKY_WINDOW msgwnd;
464
465 DBG("GI_wait_message(0x%x, 0x%x)\n", m, w);
466
467 hwndFilter = (w != NULL ? ((PSKY_WINDOW)w)->hWnd : NULL);
468 do
469 {
470 Ret = GetMessage(&Msg, hwndFilter, 0, 0);
471
472 /* loop until we found a message that a sky app would handle, too */
473 RtlZeroMemory(m, sizeof(s_gi_msg));
474
475 if(Msg.hwnd != NULL && (msgwnd = (PSKY_WINDOW)GetWindowLongW(Msg.hwnd, GWL_USERDATA)))
476 {
477 SkyMessage = IntIsSkyMessage(msgwnd, &Msg, m);
478 }
479 else
480 {
481 SkyMessage = FALSE;
482 }
483
484 if (!SkyMessage)
485 {
486 /* We're not interested in dispatching a sky message, try again */
487 TranslateMessage(&Msg);
488 DispatchMessage(&Msg);
489 }
490 }
491 while (!SkyMessage);
492
493 return Ret;
494 }
495
496
497 /*
498 * @implemented
499 */
500 int __cdecl
501 GI_dispatch_message(s_window *win,
502 s_gi_msg *m)
503 {
504 PSKY_WINDOW skywnd = (PSKY_WINDOW)win;
505 DBG("GI_dispatch_message(0x%x, 0x%x - %d)\n", win, m, m->type);
506 /* dispatch the SkyOS message to the SkyOS window procedure */
507 if (skywnd != 0)
508 return skywnd->Window.win_func(win, m);
509 return 1;
510 }
511
512
513 /*
514 * @implemented
515 */
516 HRESULT __cdecl
517 GI_ShowApplicationWindow(s_window *win)
518 {
519 PSKY_WINDOW skywnd = (PSKY_WINDOW)win;
520 DBG("GI_ShowApplicationWindow(0x%x)\n", win);
521 ShowWindow(skywnd->hWnd, SW_SHOW);
522 return 1;
523 }
524
525
526 /*
527 * @implemented
528 */
529 int __cdecl
530 GI_redraw_window(s_window *win)
531 {
532 PSKY_WINDOW skywnd = (PSKY_WINDOW)win;
533 DBG("GI_redraw_window(0x%x)!\n", win);
534 if(skywnd != NULL)
535 {
536 RedrawWindow(skywnd->hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
537 }
538 return 1;
539 }
540
541
542 /*
543 * @implemented
544 */
545 void __cdecl
546 GI_post_quit(s_window *win)
547 {
548 DBG("GI_post_quit(0x%x)\n", win);
549 PostMessage(((PSKY_WINDOW)win)->hWnd, WM_QUIT, 0, 0);
550 }
551
552
553 /*
554 * @implemented
555 */
556 sCreateApplication* __cdecl
557 GI_CreateApplicationStruct(void)
558 {
559 sCreateApplication *app;
560
561 app = (sCreateApplication*)HeapAlloc(GetProcessHeap(),
562 HEAP_ZERO_MEMORY,
563 sizeof(sCreateApplication));
564 STUB("GI_CreateApplicationStruct() returns 0x%x (allocated structure on the heap)!\n", app);
565
566 return app;
567 }
568
569
570 /*
571 * @implemented
572 */
573 int __cdecl
574 GI_GetWindowX(s_window *win)
575 {
576 RECT rc;
577 PSKY_WINDOW skywnd = (PSKY_WINDOW)win;
578 if((skywnd != NULL) && GetWindowRect(skywnd->hWnd, &rc))
579 {
580 MapWindowPoints(HWND_DESKTOP, GetParent(skywnd->hWnd), (LPPOINT)&rc, 2);
581 DBG("GI_GetWindowS(0x%x) returns %d!\n", win, rc.left);
582 return rc.left;
583 }
584 #if DEBUG
585 else
586 {
587 DBG("GI_GetWindowS(0x%x) failed!\n", win);
588 }
589 #endif
590 return 0;
591 }
592
593
594 /*
595 * @implemented
596 */
597 int __cdecl
598 GI_GetWindowY(s_window *win)
599 {
600 RECT rc;
601 PSKY_WINDOW skywnd = (PSKY_WINDOW)win;
602 if((skywnd != NULL) && GetWindowRect(skywnd->hWnd, &rc))
603 {
604 MapWindowPoints(HWND_DESKTOP, GetParent(skywnd->hWnd), (LPPOINT)&rc, 2);
605 DBG("GI_GetWindowY(0x%x) returns %d!\n", win, rc.top);
606 return rc.left;
607 }
608 #if DEBUG
609 else
610 {
611 DBG("GI_GetWindowY(0x%x) failed!\n", win);
612 }
613 #endif
614 return 0;
615 }
616
617
618 /*
619 * @implemented
620 */
621 int __cdecl
622 GI_GetWindowWidth(s_window *win)
623 {
624 RECT rc;
625 PSKY_WINDOW skywnd = (PSKY_WINDOW)win;
626 if((skywnd != NULL) && GetWindowRect(skywnd->hWnd, &rc))
627 {
628 DBG("GI_GetWindowWidth(0x%x) returns %d!\n", win, (rc.right - rc.left));
629 return (rc.right - rc.left);
630 }
631 #if DEBUG
632 else
633 {
634 DBG("GI_GetWindowWidth(0x%x) failed!\n", win);
635 }
636 #endif
637 return 0;
638 }
639
640
641 /*
642 * @implemented
643 */
644 int __cdecl
645 GI_GetWindowHeight(s_window *win)
646 {
647 RECT rc;
648 PSKY_WINDOW skywnd = (PSKY_WINDOW)win;
649 if((skywnd != NULL) && GetWindowRect(skywnd->hWnd, &rc))
650 {
651 DBG("GI_GetWindowHeight(0x%x) returns %d!\n", win, (rc.bottom - rc.top));
652 return (rc.bottom - rc.top);
653 }
654 #if DEBUG
655 else
656 {
657 DBG("GI_GetWindowHeight(0x%x) failed!\n", win);
658 }
659 #endif
660 return 0;
661 }
662
663
664 /*
665 * @unimplemented
666 */
667 s_window* __cdecl
668 GI_GetTopLevelWindow(s_window *win)
669 {
670 STUB("GI_GetTopLevelWindow(0x%x) returns 0x%x!\n", win, win);
671 return win;
672 }
673
674
675 /*
676 * @implemented
677 */
678 DIB* __cdecl
679 GI_create_DIB(void *Data,
680 unsigned int Width,
681 unsigned int Height,
682 unsigned int Bpp,
683 void *Palette,
684 unsigned int PaletteSize)
685 {
686 SKY_DIB *Dib;
687 BITMAPINFO *BitmapInfo;
688
689 DBG("GI_create_DIB(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
690 Data, Width, Height, Bpp, Palette, PaletteSize);
691
692 Dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SKY_DIB));
693 if (Dib == NULL)
694 {
695 return NULL;
696 }
697
698 BitmapInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) +
699 PaletteSize * sizeof(RGBQUAD));
700 if (BitmapInfo == NULL)
701 {
702 HeapFree(GetProcessHeap(), 0, Dib);
703 return NULL;
704 }
705
706 Dib->Dib.color = Bpp;
707 Dib->Dib.width = Width;
708 Dib->Dib.height = Height;
709 Dib->Dib.data = Data;
710 Dib->Dib.palette_size = PaletteSize;
711 Dib->Dib.palette = Palette;
712
713 BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
714 BitmapInfo->bmiHeader.biWidth = Width;
715 BitmapInfo->bmiHeader.biHeight = Height;
716 BitmapInfo->bmiHeader.biPlanes = 1;
717 BitmapInfo->bmiHeader.biBitCount = Bpp;
718 BitmapInfo->bmiHeader.biCompression = BI_RGB;
719 BitmapInfo->bmiHeader.biSizeImage = 0;
720 BitmapInfo->bmiHeader.biXPelsPerMeter = 0;
721 BitmapInfo->bmiHeader.biYPelsPerMeter = 0;
722 BitmapInfo->bmiHeader.biClrUsed = PaletteSize;
723 BitmapInfo->bmiHeader.biClrImportant = 0;
724 RtlCopyMemory(BitmapInfo->bmiColors, Palette, PaletteSize * sizeof(RGBQUAD));
725
726 Dib->hBitmap = CreateDIBSection(NULL,
727 BitmapInfo,
728 DIB_RGB_COLORS,
729 Data,
730 NULL,
731 0);
732 HeapFree(GetProcessHeap(), 0, BitmapInfo);
733 if (Dib->hBitmap == NULL)
734 {
735 HeapFree(GetProcessHeap(), 0, Dib);
736 return NULL;
737 }
738
739 return (DIB*)Dib;
740 }
741
742
743 /*
744 * @implemented
745 */
746 GC* __cdecl
747 GC_create_connected(unsigned int Type,
748 unsigned int Width,
749 unsigned int Height,
750 s_window *Win)
751 {
752 SKY_GC *Gc;
753
754 DBG("GC_create_connected(0x%x, 0x%x, 0x%x, 0x%x)\n",
755 Type, Width, Height, Win);
756
757 if(Win == NULL)
758 {
759 DBG("GC_create_connected: no window specified! returned NULL!\n");
760 return NULL;
761 }
762
763 Gc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SKY_GC));
764 if (Gc == NULL)
765 {
766 return NULL;
767 }
768
769 Gc->GraphicsContext.type = Type;
770 Gc->GraphicsContext.width = Width;
771 Gc->GraphicsContext.height = Height;
772
773 switch (Type)
774 {
775 case GC_TYPE_DIB:
776 Gc->hDC = CreateCompatibleDC(0);
777 if (Gc->hDC)
778 {
779 Gc->GraphicsContext.hDIB = (DIB*)Win;
780 SelectObject(Gc->hDC, ((PSKY_DIB)Win)->hBitmap);
781 ((PSKY_DIB)Win)->hAssociateDC = Gc->hDC;
782 }
783 break;
784
785 case GC_TYPE_WINDOW:
786 Gc->hDC = GetDC(((PSKY_WINDOW)Win)->hWnd);
787 Gc->GraphicsContext.window = Win;
788 break;
789
790 default:
791 DBG("Unknown GC type: %x\n", Type);
792 }
793
794 if (Gc->hDC == NULL)
795 {
796 HeapFree(GetProcessHeap(), 0, Gc);
797 return NULL;
798 }
799 else
800 {
801 SelectObject(Gc->hDC, GetStockObject(DC_BRUSH));
802 SelectObject(Gc->hDC, GetStockObject(DC_PEN));
803 }
804
805 return (GC*)Gc;
806 }
807
808
809 /*
810 * @implemented
811 */
812 int __cdecl
813 GC_set_fg_color(GC *Gc,
814 COLOR Color)
815 {
816 if(Gc != NULL)
817 {
818 Gc->fg_color = Color;
819 SetDCPenColor(((PSKY_GC)Gc)->hDC, Color);
820 return 1;
821 }
822 #if DEBUG
823 else
824 {
825 DBG("GC_set_fg_color: Gc == NULL!\n");
826 }
827 #endif
828 return 0;
829 }
830
831
832 /*
833 * @implemented
834 */
835 int __cdecl
836 GC_set_bg_color(GC *Gc,
837 COLOR Color)
838 {
839 if(Gc != NULL)
840 {
841 Gc->bg_color = Color;
842 SetDCBrushColor(((PSKY_GC)Gc)->hDC, Color);
843 return 1;
844 }
845 #if DEBUG
846 else
847 {
848 DBG("GC_set_bg_color: Gc == NULL!\n");
849 }
850 #endif
851 return 0;
852 }
853
854
855 /*
856 * @implemented
857 */
858 int __cdecl
859 GC_draw_pixel(GC *Gc,
860 int X,
861 int Y)
862 {
863 if(Gc != NULL)
864 {
865 SetPixelV(((PSKY_GC)Gc)->hDC, X, Y, Gc->fg_color);
866 return 1;
867 }
868 #if DEBUG
869 else
870 {
871 DBG("GC_draw_pixel: Gc == NULL!\n");
872 }
873 #endif
874 return 0;
875 }
876
877
878 /*
879 * @implemented
880 */
881 int __cdecl
882 GC_blit_from_DIB(GC *Gc,
883 DIB *Dib,
884 int X,
885 int Y)
886 {
887 int Result;
888 HDC hSrcDC;
889 HBITMAP hOldBitmap;
890
891 DBG("GC_blit_from_DIB(0x%x, 0x%x, 0x%x, 0x%x)\n", Gc, Dib, X, Y);
892
893 if (((PSKY_DIB)Dib)->hAssociateDC == NULL)
894 {
895 hSrcDC = CreateCompatibleDC(0);
896 hOldBitmap = SelectObject(hSrcDC, ((PSKY_DIB)Dib)->hBitmap);
897 }
898 else
899 {
900 hSrcDC = ((PSKY_DIB)Dib)->hAssociateDC;
901 }
902
903 Result = BitBlt(((PSKY_GC)Gc)->hDC, X, Y, Dib->width, Dib->height,
904 hSrcDC, 0, 0, SRCCOPY);
905
906 if (((PSKY_DIB)Dib)->hAssociateDC == NULL)
907 {
908 SelectObject(hSrcDC, hOldBitmap);
909 DeleteDC(hSrcDC);
910 }
911
912 return !Result;
913 }
914
915
916 /*
917 * @implemented
918 */
919 int __cdecl
920 GC_draw_rect_fill(GC *Gc,
921 int X,
922 int Y,
923 int Width,
924 int Height)
925 {
926 DBG("GC_draw_rect_fill(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
927 Gc, X, Y, Width, Height);
928
929 if(Gc != NULL)
930 {
931 HBRUSH hBrush;
932 RECT Rect;
933
934 Rect.left = X;
935 Rect.top = Y;
936 Rect.right = X + Width;
937 Rect.bottom = Y + Height;
938
939 hBrush = CreateSolidBrush(Gc->bg_color);
940 FillRect(((PSKY_GC)Gc)->hDC, &Rect, hBrush);
941 DeleteObject(hBrush);
942
943 return 1;
944 }
945 #if DEBUG
946 else
947 {
948 DBG("GC_draw_rect_fill: Gc == NULL!\n");
949 }
950 #endif
951 return 0;
952 }
953
954
955 /*
956 * @implemented
957 */
958 int __cdecl
959 GC_draw_line(GC *Gc,
960 int x1,
961 int y1,
962 int x2,
963 int y2)
964 {
965 DBG("GC_draw_line(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", Gc, x1, y1, x2, y2);
966 if(Gc != NULL)
967 {
968 MoveToEx(((PSKY_GC)Gc)->hDC, x1, y1, NULL);
969 LineTo(((PSKY_GC)Gc)->hDC, x2, y2);
970 return 1;
971 }
972 #if DEBUG
973 else
974 {
975 DBG("GC_draw_line: Gc == NULL!\n");
976 }
977 #endif
978 return 0;
979 }
980
981
982 /*
983 * @implemented
984 */
985 int __cdecl
986 GC_destroy(GC *Gc)
987 {
988 DBG("GC_destroy(0x%x)\n", Gc);
989 if (Gc != NULL)
990 {
991 switch (Gc->type)
992 {
993 case GC_TYPE_DIB:
994 DeleteDC(((PSKY_GC)Gc)->hDC);
995 break;
996
997 case GC_TYPE_WINDOW:
998 ReleaseDC(((PSKY_WINDOW)Gc->window)->hWnd, ((PSKY_GC)Gc)->hDC);
999 break;
1000
1001 default:
1002 DBG("Unknown GC type: %x\n", Gc->type);
1003 }
1004 HeapFree(GetProcessHeap(), 0, Gc);
1005 return 1;
1006 }
1007 #if DEBUG
1008 else
1009 {
1010 DBG("GC_destroy: Gc == NULL!\n");
1011 }
1012 #endif
1013 return 0;
1014 }
1015
1016
1017 /*
1018 * @implemented
1019 */
1020 widget_menu* __cdecl
1021 GI_create_menu(s_window *win)
1022 {
1023 PSKY_MENU Menu;
1024
1025 DBG("GI_create_menu(0x%x)\n", win);
1026
1027 Menu = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SKY_MENU));
1028 if (Menu == NULL)
1029 {
1030 return NULL;
1031 }
1032
1033 /* Shouldn't we use CreatePopupMenu in some cases? */
1034 Menu->hMenu = CreateMenu();
1035 if (Menu->hMenu == NULL)
1036 {
1037 HeapFree(GetProcessHeap(), 0, Menu);
1038 return NULL;
1039 }
1040
1041 if (win)
1042 {
1043 SetMenu(((PSKY_WINDOW)win)->hWnd, Menu->hMenu);
1044 }
1045
1046 return (widget_menu *)Menu;
1047 }
1048
1049
1050 /*
1051 * @implemented
1052 */
1053 widget_menu_item* __cdecl
1054 GI_create_menu_item(unsigned char *Text,
1055 unsigned int Id,
1056 unsigned int Flags,
1057 unsigned int Enabled)
1058 {
1059 PSKY_MENUITEM MenuItem;
1060 ULONG TextLength;
1061
1062 DBG("GI_create_menu_item(0x%x, 0x%x, 0x%x, 0x%x)\n",
1063 Text, Id, Flags, Enabled);
1064
1065 TextLength = MultiByteToWideChar(CP_UTF8, 0, Text, -1, NULL, 0);
1066 MenuItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1067 sizeof(SKY_MENUITEM) + TextLength * sizeof(WCHAR));
1068 if (MenuItem == NULL)
1069 {
1070 return NULL;
1071 }
1072
1073 lstrcpyA(MenuItem->MenuItem.text, Text);
1074 MenuItem->MenuItem.ID = Id;
1075 MenuItem->MenuItem.flags = Flags;
1076 MenuItem->MenuItem.enabled = Enabled;
1077
1078 MenuItem->MenuItemInfo.cbSize = sizeof(MENUITEMINFOW);
1079 MenuItem->MenuItemInfo.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
1080 if (Flags & MENU_SEPERATOR)
1081 MenuItem->MenuItemInfo.fType = MF_SEPARATOR;
1082 else
1083 MenuItem->MenuItemInfo.fType = MF_STRING;
1084 MenuItem->MenuItemInfo.fState = Enabled ? MFS_ENABLED : 0;
1085 MenuItem->MenuItemInfo.wID = Id;
1086 MenuItem->MenuItemInfo.dwTypeData = (LPWSTR)(MenuItem + 1);
1087 MenuItem->MenuItemInfo.cch = TextLength;
1088 MultiByteToWideChar(CP_UTF8, 0, Text, TextLength, (LPWSTR)(MenuItem + 1),
1089 TextLength);
1090
1091 return (widget_menu_item *)MenuItem;
1092 }
1093
1094
1095 /*
1096 * @implemented
1097 */
1098 int __cdecl
1099 GI_add_menu_item(widget_menu *Menu,
1100 widget_menu_item *Item)
1101 {
1102 DBG("GI_add_menu_item(0x%x, 0x%x)\n", Menu, Item);
1103 InsertMenuItemW(((PSKY_MENU)Menu)->hMenu, -1, TRUE,
1104 &((PSKY_MENUITEM)Item)->MenuItemInfo);
1105 return 1;
1106 }
1107
1108
1109 /*
1110 * @implemented
1111 */
1112 int __cdecl
1113 GI_add_menu_sub(widget_menu *Menu,
1114 widget_menu_item *Item,
1115 widget_menu *Sub)
1116 {
1117 PSKY_MENUITEM MenuItem = (PSKY_MENUITEM)Item;
1118
1119 DBG("GI_add_menu_sub(0x%x, 0x%x, 0x%x)\n", Menu, Item, Sub);
1120 MenuItem->MenuItemInfo.fMask |= MIIM_SUBMENU;
1121 MenuItem->MenuItemInfo.hSubMenu = ((PSKY_MENU)Sub)->hMenu;
1122 InsertMenuItemW(((PSKY_MENU)Menu)->hMenu, -1, TRUE,
1123 &MenuItem->MenuItemInfo);
1124 return 1;
1125 }
1126
1127
1128 /*
1129 * @unimplemented
1130 */
1131 int __cdecl
1132 GI_messagebox(s_window *win,
1133 unsigned int Flags,
1134 char *Title,
1135 char *Fmt,
1136 ...)
1137 {
1138 CHAR Buffer[4096];
1139 va_list ArgList;
1140
1141 DBG("GI_messagebox(0x%x, 0x%x, 0x%x, 0x%x, ...)\n",
1142 win, Flags, Title, Fmt);
1143
1144 va_start(ArgList, Fmt);
1145 _vsnprintf(Buffer, sizeof(Buffer) / sizeof(Buffer[0]), Fmt, ArgList);
1146 va_end(ArgList);
1147
1148 /** @todo Convert flags and fix return value! */
1149 MessageBoxA(win ? ((PSKY_WINDOW)win)->hWnd : NULL,
1150 Buffer, Title, MB_OK);
1151
1152 return 1;
1153 }
1154
1155 /* EOF */