Simple fixes to get navit compiling with MSVC
[profile/ivi/navit.git] / navit / navit / graphics / win32 / graphics_win32.c
1 #include <windows.h>
2 #include <windowsx.h>
3 #include <wingdi.h>
4 #include <glib.h>
5 #include <math.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include "config.h"
9 #include "debug.h"
10 #include "point.h"
11 #include "graphics.h"
12 #include "color.h"
13 #include "callback.h"
14 #include "plugin.h"
15 #include "item.h"
16 #include "window.h"
17 #include "graphics_win32.h"
18 #include "xpm2bmp.h"
19 #include "support/win32/ConvertUTF.h"
20 #include "profile.h"
21 #include "keys.h"
22
23 #ifdef HAVE_API_WIN32_CE
24 #include "libc.h"
25 #endif
26
27 //#define FAST_TRANSPARENCY 1
28
29 #if defined(_WIN32_WCE) && _WIN32_WCE < 0x500 && !defined(__MINGW32CE__)
30
31 typedef struct {
32                 int BlendOp;
33                 int BlendFlags;
34                 int SourceConstantAlpha;
35                 int AlphaFormat;
36 } BLENDFUNCTION;
37
38 #define AC_SRC_OVER 1
39 #define AC_SRC_ALPHA 2
40 #endif
41
42 typedef BOOL (WINAPI *FP_AlphaBlend) ( HDC hdcDest,
43                                        int nXOriginDest,
44                                        int nYOriginDest,
45                                        int nWidthDest,
46                                        int nHeightDest,
47                                        HDC hdcSrc,
48                                        int nXOriginSrc,
49                                        int nYOriginSrc,
50                                        int nWidthSrc,
51                                        int nHeightSrc,
52                                        BLENDFUNCTION blendFunction
53                                      );
54
55 typedef int (WINAPI *FP_SetStretchBltMode) (HDC dc,int mode);
56
57 struct graphics_priv
58 {
59     struct navit *nav;
60     struct window window;
61     struct point p;
62     int width;
63     int height;
64     int disabled;
65     HANDLE wnd_parent_handle;
66     HANDLE wnd_handle;
67     COLORREF bg_color;
68     struct callback_list *cbl;
69     enum draw_mode_num mode;
70     struct graphics_priv* parent;
71     struct graphics_priv *overlays;
72     struct graphics_priv *next;
73     struct color transparent_color;
74     DWORD* pPixelData;
75     HDC hMemDC;
76     HDC hPrebuildDC;
77     HBITMAP hBitmap;
78     HBITMAP hPrebuildBitmap;
79     HBITMAP hOldBitmap;
80     HBITMAP hOldPrebuildBitmap;
81     FP_AlphaBlend AlphaBlend;
82     FP_SetStretchBltMode SetStretchBltMode;
83     BOOL (WINAPI *ChangeWindowMessageFilter)(UINT message, DWORD dwFlag);
84     BOOL (WINAPI *ChangeWindowMessageFilterEx)( HWND hWnd, UINT message, DWORD action, void *pChangeFilterStruct);
85     HANDLE hCoreDll;
86     HANDLE hUser32Dll;
87     HANDLE hGdi32Dll;
88     GHashTable *image_cache_hash;
89 };
90
91 struct window_priv
92 {
93     HANDLE hBackLight;
94 };
95
96 static HWND g_hwnd = NULL;
97
98 #ifdef HAVE_API_WIN32_CE
99 static int fullscr = 0;
100 #endif
101
102
103 #ifndef GET_WHEEL_DELTA_WPARAM
104 #define GET_WHEEL_DELTA_WPARAM(wParam)  ((short)HIWORD(wParam))
105 #endif
106
107
108 HFONT EzCreateFont (HDC hdc, TCHAR * szFaceName, int iDeciPtHeight,
109                     int iDeciPtWidth, int iAttributes, BOOL fLogRes) ;
110
111 #define EZ_ATTR_BOLD          1
112 #define EZ_ATTR_ITALIC        2
113 #define EZ_ATTR_UNDERLINE     4
114 #define EZ_ATTR_STRIKEOUT     8
115
116 HFONT EzCreateFont (HDC hdc, TCHAR * szFaceName, int iDeciPtHeight,
117                     int iDeciPtWidth, int iAttributes, BOOL fLogRes)
118 {
119     FLOAT      cxDpi, cyDpi ;
120     HFONT      hFont ;
121     LOGFONT    lf ;
122     POINT      pt ;
123     TEXTMETRIC tm ;
124
125     SaveDC (hdc) ;
126
127 #ifndef HAVE_API_WIN32_CE
128     SetGraphicsMode (hdc, GM_ADVANCED) ;
129     ModifyWorldTransform (hdc, NULL, MWT_IDENTITY) ;
130 #endif
131     SetViewportOrgEx (hdc, 0, 0, NULL) ;
132 #ifndef HAVE_API_WIN32_CE
133     SetWindowOrgEx   (hdc, 0, 0, NULL) ;
134 #endif
135
136     if (fLogRes)
137     {
138         cxDpi = (FLOAT) GetDeviceCaps (hdc, LOGPIXELSX) ;
139         cyDpi = (FLOAT) GetDeviceCaps (hdc, LOGPIXELSY) ;
140     }
141     else
142     {
143         cxDpi = (FLOAT) (25.4 * GetDeviceCaps (hdc, HORZRES) /
144                          GetDeviceCaps (hdc, HORZSIZE)) ;
145
146         cyDpi = (FLOAT) (25.4 * GetDeviceCaps (hdc, VERTRES) /
147                          GetDeviceCaps (hdc, VERTSIZE)) ;
148     }
149
150     pt.x = (int) (iDeciPtWidth  * cxDpi / 72) ;
151     pt.y = (int) (iDeciPtHeight * cyDpi / 72) ;
152
153 #ifndef HAVE_API_WIN32_CE
154     DPtoLP (hdc, &pt, 1) ;
155 #endif
156     lf.lfHeight         = - (int) (fabs (pt.y) / 10.0 + 0.5) ;
157     lf.lfWidth          = 0 ;
158     lf.lfEscapement     = 0 ;
159     lf.lfOrientation    = 0 ;
160     lf.lfWeight         = iAttributes & EZ_ATTR_BOLD      ? 700 : 0 ;
161     lf.lfItalic         = iAttributes & EZ_ATTR_ITALIC    ?   1 : 0 ;
162     lf.lfUnderline      = iAttributes & EZ_ATTR_UNDERLINE ?   1 : 0 ;
163     lf.lfStrikeOut      = iAttributes & EZ_ATTR_STRIKEOUT ?   1 : 0 ;
164     lf.lfCharSet        = DEFAULT_CHARSET ;
165     lf.lfOutPrecision   = 0 ;
166     lf.lfClipPrecision  = 0 ;
167     lf.lfQuality        = 0 ;
168     lf.lfPitchAndFamily = 0 ;
169
170     lstrcpy (lf.lfFaceName, szFaceName) ;
171
172     hFont = CreateFontIndirect (&lf) ;
173
174     if (iDeciPtWidth != 0)
175     {
176         hFont = (HFONT) SelectObject (hdc, hFont) ;
177
178         GetTextMetrics (hdc, &tm) ;
179
180         DeleteObject (SelectObject (hdc, hFont)) ;
181
182         lf.lfWidth = (int) (tm.tmAveCharWidth *
183                             fabs (pt.x) / fabs (pt.y) + 0.5) ;
184
185         hFont = CreateFontIndirect (&lf) ;
186     }
187
188     RestoreDC (hdc, -1) ;
189     return hFont ;
190 }
191
192 struct graphics_image_priv
193 {
194     PXPM2BMP pxpm;
195         int width,height,row_bytes,channels;
196     unsigned char *png_pixels;
197     HBITMAP hBitmap;
198     struct point hot;
199 };
200
201
202 static void ErrorExit(LPTSTR lpszFunction)
203 {
204     // Retrieve the system error message for the last-error code
205
206         LPVOID lpMsgBuf;
207     LPVOID lpDisplayBuf;
208     DWORD dw = GetLastError();
209
210     FormatMessage(
211         FORMAT_MESSAGE_ALLOCATE_BUFFER |
212         FORMAT_MESSAGE_FROM_SYSTEM |
213         FORMAT_MESSAGE_IGNORE_INSERTS,
214         NULL,
215         dw,
216         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
217         (LPTSTR) &lpMsgBuf,
218         0, NULL );
219
220     lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
221                                       (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
222     _tprintf((LPTSTR)lpDisplayBuf, TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
223
224     dbg(0, "%s failed with error %d: %s", lpszFunction, dw, lpMsgBuf);
225     MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
226
227     LocalFree(lpMsgBuf);
228     LocalFree(lpDisplayBuf);
229     ExitProcess(dw);
230 }
231
232
233
234 struct graphics_gc_priv
235 {
236     HWND        hwnd;
237     int         line_width;
238     COLORREF    fg_color;
239     int         fg_alpha;
240     COLORREF    bg_color;
241     HPEN hpen;
242     HBRUSH hbrush;
243     struct graphics_priv *gr;
244 };
245
246
247 static void create_memory_dc(struct graphics_priv *gr)
248 {
249     HDC hdc;
250     BITMAPINFO bOverlayInfo;
251
252     if (gr->hMemDC)
253     {
254         (void)SelectBitmap(gr->hMemDC, gr->hOldBitmap);
255         DeleteBitmap(gr->hBitmap);
256         DeleteDC(gr->hMemDC);
257
258         (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap);
259         DeleteBitmap(gr->hPrebuildBitmap);
260         DeleteDC(gr->hPrebuildDC);
261         gr->hPrebuildDC = 0;
262     }
263
264
265     hdc = GetDC( gr->wnd_handle );
266     // Creates memory DC
267     gr->hMemDC = CreateCompatibleDC(hdc);
268     dbg(0, "resize memDC to: %d %d \n", gr->width, gr->height );
269
270
271 #ifndef  FAST_TRANSPARENCY
272
273     memset(&bOverlayInfo, 0, sizeof(BITMAPINFO));
274     bOverlayInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
275     bOverlayInfo.bmiHeader.biWidth = gr->width;
276     bOverlayInfo.bmiHeader.biHeight = -gr->height;
277     bOverlayInfo.bmiHeader.biBitCount = 32;
278     bOverlayInfo.bmiHeader.biCompression = BI_RGB;
279     bOverlayInfo.bmiHeader.biPlanes = 1;
280     gr->hPrebuildDC = CreateCompatibleDC(NULL);
281     gr->hPrebuildBitmap = CreateDIBSection(gr->hMemDC, &bOverlayInfo, DIB_RGB_COLORS , (void **)&gr->pPixelData, NULL, 0);
282     gr->hOldPrebuildBitmap = SelectBitmap(gr->hPrebuildDC, gr->hPrebuildBitmap);
283
284 #endif
285     gr->hBitmap = CreateCompatibleBitmap(hdc, gr->width, gr->height );
286
287     if ( gr->hBitmap )
288     {
289         gr->hOldBitmap = SelectBitmap( gr->hMemDC, gr->hBitmap);
290     }
291     ReleaseDC( gr->wnd_handle, hdc );
292 }
293
294 static void HandleButtonClick( struct graphics_priv *gra_priv, int updown, int button, long lParam )
295 {
296     struct point pt = { LOWORD(lParam), HIWORD(lParam) };
297     callback_list_call_attr_3(gra_priv->cbl, attr_button, (void *)updown, (void *)button, (void *)&pt);
298 }
299
300 static void HandleKeyChar(struct graphics_priv *gra_priv, WPARAM wParam)
301 {
302     TCHAR key = (TCHAR) wParam;
303     char *s=NULL;
304     char k[]={0,0};
305     dbg(1,"HandleKey %d\n",key);
306         switch (key) {
307     default:
308                 k[0]=key;
309                 s=k;
310         break;
311     }
312     if (s) 
313         callback_list_call_attr_1(gra_priv->cbl, attr_keypress, (void *)s);
314 }
315
316 static void HandleKeyDown(struct graphics_priv *gra_priv, WPARAM wParam)
317 {
318     int key = (int) wParam;
319     char up[]={NAVIT_KEY_UP,0};
320     char down[]={NAVIT_KEY_DOWN,0};
321     char left[]={NAVIT_KEY_LEFT,0};
322     char right[]={NAVIT_KEY_RIGHT,0};
323     char *s=NULL;
324     dbg(1,"HandleKey %d\n",key);
325         switch (key) {
326     case 37:
327                 s=left;
328         break;
329     case 38:
330                 s=up;
331         break;
332     case 39:
333                 s=right;
334         break;
335     case 40:
336                 s=down;
337         break;
338     }
339     if (s) 
340         callback_list_call_attr_1(gra_priv->cbl, attr_keypress, (void *)s);
341 }
342
343
344 static LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
345 {
346
347     struct graphics_priv* gra_priv = (struct graphics_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
348
349     switch (Message)
350     {
351     case WM_CREATE:
352     {
353         if ( gra_priv )
354         {
355             RECT rc ;
356
357             GetClientRect( hwnd, &rc );
358             gra_priv->width = rc.right;
359             gra_priv->height = rc.bottom;
360             create_memory_dc(gra_priv);
361         }
362     }
363     break;
364     case WM_COMMAND:
365         switch (LOWORD(wParam))
366         {
367         case WM_USER + 1:
368             break;
369         }
370         break;
371     case WM_CLOSE:
372         DestroyWindow(hwnd);
373         break;
374     case WM_USER+1:
375         if ( gra_priv )
376         {
377             RECT rc ;
378
379             GetClientRect( hwnd, &rc );
380             gra_priv->width = rc.right;
381             gra_priv->height = rc.bottom;
382
383             create_memory_dc(gra_priv);
384             callback_list_call_attr_2(gra_priv->cbl, attr_resize, (void *)gra_priv->width, (void *)gra_priv->height);
385         }
386         break;
387     case WM_USER+2:
388     {
389         struct callback_list *cbl = (struct callback_list*)wParam;
390 #ifdef HAVE_API_WIN32_CE
391         /* FIXME: Reset the idle timer  need a better place */
392         SystemIdleTimerReset();
393 #endif
394         callback_list_call_0(cbl);
395     }
396     break;
397
398     case WM_SIZE:
399         if ( gra_priv )
400         {
401             gra_priv->width = LOWORD( lParam );
402             gra_priv->height  = HIWORD( lParam );
403             create_memory_dc(gra_priv);
404             dbg(0, "resize gfx to: %d %d \n", gra_priv->width, gra_priv->height );
405             callback_list_call_attr_2(gra_priv->cbl, attr_resize, (void *)gra_priv->width, (void *)gra_priv->height);
406         }
407         break;
408     case WM_DESTROY:
409 #ifdef HAVE_API_WIN32_CE
410         if ( gra_priv && gra_priv->window.priv )
411         {
412             struct window_priv *win_priv = gra_priv->window.priv;
413             if (win_priv->hBackLight)
414             {
415                 ReleasePowerRequirement(win_priv->hBackLight);
416             }
417         }
418 #endif
419         PostQuitMessage(0);
420         break;
421     case WM_PAINT:
422         if ( gra_priv && gra_priv->hMemDC)
423         {
424             struct graphics_priv* overlay;
425             PAINTSTRUCT ps = { 0 };
426             HDC hdc;
427             profile(0, NULL);
428             dbg(1, "WM_PAINT\n");
429             overlay = gra_priv->overlays;
430
431 #ifndef FAST_TRANSPARENCY
432                         BitBlt( gra_priv->hPrebuildDC, 0, 0, gra_priv->width , gra_priv->height, gra_priv->hMemDC, 0, 0, SRCCOPY);
433 #endif
434                         while ( !gra_priv->disabled && overlay)
435                         {
436                                 if ( !overlay->disabled && overlay->p.x >= 0 &&
437                                          overlay->p.y >= 0 &&
438                                          overlay->p.x < gra_priv->width &&
439                                          overlay->p.y < gra_priv->height )
440                                 {
441                                         int x,y;
442                                         int destPixel, srcPixel;
443                     int h,w;
444 #ifdef FAST_TRANSPARENCY
445                                         if ( !overlay->hPrebuildDC )
446                                         {
447                                                 overlay->hPrebuildBitmap = CreateBitmap(overlay->width,overlay->height,1,1,NULL);
448                                                 overlay->hPrebuildDC = CreateCompatibleDC(NULL);
449                                                 overlay->hOldPrebuildBitmap = SelectBitmap( overlay->hPrebuildDC, overlay->hPrebuildBitmap);
450                                                 SetBkColor(overlay->hMemDC,RGB(overlay->transparent_color.r >> 8,overlay->transparent_color.g >> 8,overlay->transparent_color.b >> 8));
451                                                 BitBlt(overlay->hPrebuildDC,0,0,overlay->width,overlay->height,overlay->hMemDC,0,0,SRCCOPY);
452                                                 BitBlt(overlay->hMemDC,0,0,overlay->width,overlay->height,overlay->hPrebuildDC,0,0,SRCINVERT);
453                                         }
454
455 #else
456                                         const COLORREF transparent_color = RGB(overlay->transparent_color.r >> 8,overlay->transparent_color.g >> 8,overlay->transparent_color.b >> 8);
457
458                                         BitBlt( overlay->hPrebuildDC, 0, 0, overlay->width , overlay->height, overlay->hMemDC, 0, 0, SRCCOPY);
459
460                                         h=overlay->height;
461                                         w=overlay->width;
462                                         if (w > gra_priv->width-overlay->p.x)
463                                                 w=gra_priv->width-overlay->p.x;
464                                         if (h > gra_priv->height-overlay->p.y)
465                                                 h=gra_priv->height-overlay->p.y;
466                                         for ( y = 0; y < h ;y++ )
467                                         {
468                                                 for ( x = 0; x < w; x++ )
469                                                 {
470                                                         srcPixel = y*overlay->width+x;
471                                                         destPixel = ((overlay->p.y + y) * gra_priv->width) + (overlay->p.x + x);
472                                                         if ( overlay->pPixelData[srcPixel] == transparent_color )
473                                                         {
474                                                                 destPixel = ((overlay->p.y + y) * gra_priv->width) + (overlay->p.x + x);
475
476                                                                 gra_priv->pPixelData[destPixel] = RGB ( ((65535 - overlay->transparent_color.a) * GetRValue(gra_priv->pPixelData[destPixel]) + overlay->transparent_color.a * GetRValue(overlay->pPixelData[srcPixel])) / 65535,
477                                                                                                                                 ((65535 - overlay->transparent_color.a) * GetGValue(gra_priv->pPixelData[destPixel]) + overlay->transparent_color.a * GetGValue(overlay->pPixelData[srcPixel])) / 65535,
478                                                                                                                                 ((65535 - overlay->transparent_color.a) * GetBValue(gra_priv->pPixelData[destPixel]) + overlay->transparent_color.a * GetBValue(overlay->pPixelData[srcPixel])) / 65535);
479
480                                                         }
481                                                         else
482                                                         {
483                                                                 gra_priv->pPixelData[destPixel] = overlay->pPixelData[srcPixel];
484                                                         }
485                                                 }
486
487                                         }
488 #endif
489                                 }
490                                 overlay = overlay->next;
491                         }
492
493
494 #ifndef FAST_TRANSPARENCY
495             hdc = BeginPaint(hwnd, &ps);
496             BitBlt( hdc, 0, 0, gra_priv->width , gra_priv->height, gra_priv->hPrebuildDC, 0, 0, SRCCOPY );
497 #else
498             HDC hdc = BeginPaint(hwnd, &ps);
499
500             BitBlt( hdc, 0, 0, gra_priv->width , gra_priv->height, gra_priv->hMemDC, 0, 0, SRCCOPY );
501
502             overlay = gra_priv->overlays;
503             while ( !gra_priv->disabled && overlay && !overlay->disabled )
504             {
505                 if ( overlay->p.x > 0 &&
506                         overlay->p.y > 0 &&
507                         overlay->p.x + overlay->width < gra_priv->width &&
508                         overlay->p.y + overlay->height < gra_priv->height )
509                 {
510                     BitBlt(hdc,overlay->p.x,overlay->p.y,overlay->width,overlay->height,overlay->hPrebuildDC,0,0,SRCAND);
511                     BitBlt(hdc,overlay->p.x,overlay->p.y,overlay->width,overlay->height,overlay->hMemDC,0,0,SRCPAINT);
512                 }
513                 overlay = overlay->next;
514             }
515 #endif
516             EndPaint(hwnd, &ps);
517             profile(0, "WM_PAINT\n");
518         }
519         break;
520     case WM_MOUSEMOVE:
521     {
522         struct point pt = { LOWORD(lParam), HIWORD(lParam) };
523         callback_list_call_attr_1(gra_priv->cbl, attr_motion, (void *)&pt);
524     }
525     break;
526
527     case WM_LBUTTONDOWN:
528     {
529         dbg(1, "LBUTTONDOWN\n");
530         HandleButtonClick( gra_priv, 1, 1, lParam);
531     }
532     break;
533     case WM_LBUTTONUP:
534     {
535         dbg(1, "LBUTTONUP\n");
536         HandleButtonClick( gra_priv, 0, 1, lParam);
537     }
538     break;
539     case WM_RBUTTONDOWN:
540         HandleButtonClick( gra_priv, 1, 3,lParam );
541         break;
542     case WM_RBUTTONUP:
543         HandleButtonClick( gra_priv, 0, 3,lParam );
544         break;
545     case WM_LBUTTONDBLCLK:
546         dbg(1, "LBUTTONDBLCLK\n");
547         HandleButtonClick( gra_priv, 1, 6,lParam );
548         break;
549     case WM_CHAR:
550         HandleKeyChar( gra_priv, wParam);
551         break;
552     case WM_KEYDOWN:
553         HandleKeyDown( gra_priv, wParam);
554         break;
555    case WM_COPYDATA:
556         dbg(0,"got WM_COPYDATA\n");
557         callback_list_call_attr_2(gra_priv->cbl, attr_wm_copydata, (void *)wParam, (void*)lParam);
558         break;
559 #ifdef HAVE_API_WIN32_CE
560     case WM_SETFOCUS:
561         if (fullscr) {
562            HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
563            // deactivate the SIP button
564            ShowWindow(hwndSip, SW_HIDE);
565         }
566         break;
567    case WM_KILLFOCUS:
568         if (fullscr != 1) {
569            HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
570            // active the SIP button
571            ShowWindow(hwndSip, SW_SHOW);
572         }
573         break;
574 #endif
575     default:
576         return DefWindowProc(hwnd, Message, wParam, lParam);
577     }
578     return 0;
579 }
580
581 static int fullscreen(struct window *win, int on)
582 {
583
584 #ifdef HAVE_API_WIN32_CE
585     HWND hwndTaskbar = FindWindow(L"HHTaskBar", NULL);
586     HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
587     RECT taskbar_rect;
588     fullscr = on;
589         if (on) {
590         ShowWindow(hwndTaskbar, SW_HIDE);
591         MoveWindow(g_hwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
592         
593         // deactivate the SIP button
594         ShowWindow(hwndSip, SW_HIDE);
595         
596         } else {
597         ShowWindow(hwndTaskbar, SW_SHOW);
598         GetWindowRect(  hwndTaskbar, &taskbar_rect);
599         MoveWindow(g_hwnd, 0, taskbar_rect.bottom, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) - taskbar_rect.bottom, FALSE);
600     
601         // activate the SIP button
602         ShowWindow(hwndSip, SW_SHOW);
603     }
604
605 #else
606         if (on) {
607         ShowWindow(g_hwnd, SW_MAXIMIZE);
608         } else {
609         ShowWindow(g_hwnd, SW_RESTORE);
610     }
611
612 #endif
613
614     return 0;
615 }
616
617 extern void WINAPI SystemIdleTimerReset(void);
618 static struct event_timeout *
619             event_win32_add_timeout(int timeout, int multi, struct callback *cb);
620
621 static void disable_suspend(struct window *win)
622 {
623 #ifdef HAVE_API_WIN32_CE
624     struct window_priv *win_priv = win->priv;
625     if ( win_priv && !win_priv->hBackLight )
626     {
627         win_priv->hBackLight = SetPowerRequirement(TEXT("BKL1:"), 0, 0x01, NULL, 0);
628         event_win32_add_timeout(29000, 1, callback_new(SystemIdleTimerReset, 0, NULL));
629     }
630
631     SystemIdleTimerReset();
632 #endif
633 }
634
635 static const TCHAR g_szClassName[] = {'N','A','V','G','R','A','\0'};
636
637 static HANDLE CreateGraphicsWindows( struct graphics_priv* gr, HMENU hMenu )
638 {
639     int wStyle = WS_VISIBLE;
640     HWND hwnd;
641 #ifdef HAVE_API_WIN32_CE
642     WNDCLASS wc;
643 #else
644     WNDCLASSEX wc;
645     wc.cbSize            = sizeof(WNDCLASSEX);
646     wc.hIconSm           = NULL;
647 #endif
648
649     wc.style     = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
650     wc.lpfnWndProc      = WndProc;
651     wc.cbClsExtra       = 0;
652     wc.cbWndExtra       = 64;
653     wc.hInstance        = GetModuleHandle(NULL);
654     wc.hIcon    = NULL;
655     wc.hCursor  = LoadCursor(NULL, IDC_ARROW);
656     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
657     wc.lpszMenuName  = NULL;
658     wc.lpszClassName = g_szClassName;
659
660
661 #ifdef HAVE_API_WIN32_CE
662     gr->width = GetSystemMetrics(SM_CXSCREEN);
663     gr->height = GetSystemMetrics(SM_CYSCREEN);
664
665 #if 0
666     HWND hwndTaskbar = FindWindow(L"HHTaskBar", NULL);
667     RECT taskbar_rect;
668     GetWindowRect(  hwndTaskbar, &taskbar_rect);
669
670     gr->height -= taskbar_rect.bottom;
671 #endif
672
673
674
675 #endif
676
677 #ifdef HAVE_API_WIN32_CE
678     if (!RegisterClass(&wc))
679 #else
680     if (!RegisterClassEx(&wc))
681 #endif
682     {
683         dbg(0, "Window registration failed\n");
684         return NULL;
685     }
686
687     if ( hMenu )
688     {
689         wStyle = WS_CHILD;
690         } else {
691         wStyle = WS_OVERLAPPED|WS_VISIBLE;
692     }
693
694 #ifdef HAVE_API_WIN32_CE
695     g_hwnd = hwnd = CreateWindow(g_szClassName,
696                                  TEXT("Navit"),
697                                  wStyle,
698                                  CW_USEDEFAULT,
699                                  CW_USEDEFAULT,
700                                  CW_USEDEFAULT,
701                                  CW_USEDEFAULT,
702                                  gr->wnd_parent_handle,
703                                  hMenu,
704                                  GetModuleHandle(NULL),
705                                  NULL);
706 #else
707     g_hwnd = hwnd = CreateWindow(g_szClassName,
708                                  TEXT("Navit"),
709                                  wStyle,
710                                  0,
711                                  0,
712                                  gr->width,
713                                  gr->height,
714                                  gr->wnd_parent_handle,
715                                  hMenu,
716                                  GetModuleHandle(NULL),
717                                  NULL);
718 #endif
719     if (hwnd == NULL)
720     {
721         dbg(0, "Window creation failed: %d\n",  GetLastError());
722         return NULL;
723     }
724     /* For Vista, we need here ChangeWindowMessageFilter(WM_COPYDATA,MSGFLT_ADD); since Win7 we need above one or ChangeWindowMessageFilterEx (MSDN), both are
725       not avail for earlier Win and not present in my mingw :(. ChangeWindowMessageFilter may not be present in later Win versions. Welcome late binding!
726     */
727     if(gr->ChangeWindowMessageFilter)
728         gr->ChangeWindowMessageFilter(WM_COPYDATA,1 /*MSGFLT_ADD*/);
729     else if(gr->ChangeWindowMessageFilterEx) 
730         gr->ChangeWindowMessageFilterEx(hwnd,WM_COPYDATA,1 /*MSGFLT_ALLOW*/,NULL);
731
732     gr->wnd_handle = hwnd;
733
734     callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->width, (void *)gr->height);
735     create_memory_dc(gr);
736
737     SetWindowLongPtr( hwnd , DWLP_USER, (LONG_PTR)gr );
738
739     ShowWindow( hwnd, SW_SHOW );
740     UpdateWindow( hwnd );
741
742     PostMessage( gr->wnd_parent_handle, WM_USER + 1, 0, 0 );
743
744     return hwnd;
745 }
746
747
748
749 static void graphics_destroy(struct graphics_priv *gr)
750 {
751     g_free( gr );
752 }
753
754
755 static void gc_destroy(struct graphics_gc_priv *gc)
756 {
757     DeleteObject( gc->hpen );
758     DeleteObject( gc->hbrush );
759     g_free( gc );
760 }
761
762 static void gc_set_linewidth(struct graphics_gc_priv *gc, int w)
763 {
764     DeleteObject (gc->hpen);
765     gc->line_width = w;
766     gc->hpen = CreatePen( PS_SOLID, gc->line_width, gc->fg_color );
767 }
768
769 static void gc_set_dashes(struct graphics_gc_priv *gc, int width, int offset, unsigned char dash_list[], int n)
770 {
771 //      gdk_gc_set_dashes(gc->gc, 0, (gint8 *)dash_list, n);
772 //      gdk_gc_set_line_attributes(gc->gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND);
773 }
774
775
776 static void gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
777 {
778     gc->fg_color = RGB( c->r >> 8, c->g >> 8, c->b >> 8);
779     gc->fg_alpha = c->a;
780
781     DeleteObject (gc->hpen);
782     DeleteObject (gc->hbrush);
783     gc->hpen = CreatePen( PS_SOLID, gc->line_width, gc->fg_color );
784     gc->hbrush = CreateSolidBrush( gc->fg_color );
785         if ( gc->gr && c->a < 0xFFFF )
786     {
787             gc->gr->transparent_color = *c;
788     }
789
790 }
791
792 static void gc_set_background(struct graphics_gc_priv *gc, struct color *c)
793 {
794     gc->bg_color = RGB( c->r >> 8, c->g >> 8, c->b >> 8);
795     if ( gc->gr && gc->gr->hMemDC )
796         SetBkColor( gc->gr->hMemDC, gc->bg_color );
797
798 }
799
800 static struct graphics_gc_methods gc_methods =
801 {
802     gc_destroy,
803     gc_set_linewidth,
804     gc_set_dashes,
805     gc_set_foreground,
806     gc_set_background,
807     NULL, //gc_set_stipple
808 };
809
810 static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
811 {
812     struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1);
813     *meth=gc_methods;
814     gc->hwnd = gr->wnd_handle;
815     gc->line_width = 1;
816     gc->fg_color = RGB( 0,0,0 );
817     gc->bg_color = RGB( 255,255,255 );
818     gc->hpen = CreatePen( PS_SOLID, gc->line_width, gc->fg_color );
819     gc->hbrush = CreateSolidBrush( gc->fg_color );
820     gc->gr = gr;
821     return gc;
822 }
823
824
825 static void draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
826 {
827     int i;
828
829     HPEN hpenold = SelectObject( gr->hMemDC, gc->hpen );
830
831     int first = 1;
832     for ( i = 0; i< count; i++ )
833     {
834         if ( first )
835         {
836             first = 0;
837             MoveToEx( gr->hMemDC, p[0].x, p[0].y, NULL );
838         }
839         else
840         {
841             LineTo( gr->hMemDC, p[i].x, p[i].y );
842         }
843     }
844
845     SelectObject( gr->hMemDC, hpenold);
846 }
847
848 static void draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
849 {
850     HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
851     HBRUSH holdbrush = SelectObject( gr->hMemDC, gc->hbrush );
852     if (sizeof(POINT) != sizeof(struct point)) {
853             int i;
854             POINT* points=g_alloca(sizeof(POINT)*count);
855             for ( i=0;i< count; i++ )
856             {
857                 points[i].x = p[i].x;
858                 points[i].y = p[i].y;
859             }
860             Polygon( gr->hMemDC, points,count );
861     } else
862             Polygon( gr->hMemDC, (POINT *)p, count);
863     SelectObject( gr->hMemDC, holdbrush);
864     SelectObject( gr->hMemDC, holdpen);
865 }
866
867
868 static void draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
869 {
870     HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
871     HBRUSH holdbrush = SelectObject( gr->hMemDC, gc->hbrush );
872
873     Rectangle(gr->hMemDC, p->x, p->y, p->x+w, p->y+h);
874
875     SelectObject( gr->hMemDC, holdbrush);
876     SelectObject( gr->hMemDC, holdpen);
877 }
878
879 static void draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r)
880 {
881     HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
882     HBRUSH holdbrush = SelectObject( gr->hMemDC, GetStockObject(NULL_BRUSH));
883
884     r=r/2;
885
886     Ellipse( gr->hMemDC, p->x - r, p->y -r, p->x + r, p->y + r );
887
888     SelectObject( gr->hMemDC, holdbrush);
889     SelectObject( gr->hMemDC, holdpen);
890 }
891
892
893
894 static void draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
895 {
896     InvalidateRect( gr->wnd_handle, NULL, FALSE );
897 }
898
899 static void draw_drag(struct graphics_priv *gr, struct point *p)
900 {
901     if ( p )
902     {
903         gr->p.x    = p->x;
904         gr->p.y    = p->y;
905
906         if ( p->x < 0 || p->y < 0 ||
907                 ( gr->parent && ((p->x + gr->width > gr->parent->width) || (p->y + gr->height > gr->parent->height) )))
908         {
909             gr->disabled = TRUE;
910         }
911         else
912         {
913             gr->disabled = FALSE;
914         }
915     }
916 }
917
918 static void draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
919 {
920     dbg( 1, "set draw_mode to %x, %d\n", gr, (int)mode );
921
922     if ( mode == draw_mode_begin )
923     {
924         if ( gr->wnd_handle == NULL )
925         {
926             CreateGraphicsWindows( gr, (HMENU)ID_CHILD_GFX );
927         }
928         if ( gr->mode != draw_mode_begin )
929         {
930             if ( gr->hMemDC )
931             {
932                 dbg(1, "Erase dc: %x, w: %d, h: %d, bg_color: %x\n", gr, gr->width, gr->height, gr->bg_color);
933 #ifdef  FAST_TRANSPARENCY
934                 if ( gr->hPrebuildDC )
935                 {
936                     (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap );
937                     DeleteBitmap(gr->hPrebuildBitmap);
938                     DeleteDC(gr->hPrebuildDC);
939                     gr->hPrebuildDC = 0;
940                 }
941 #endif
942             }
943         }
944 #ifdef  FAST_TRANSPARENCY
945         else if ( gr->hPrebuildDC )
946         {
947             (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap );
948             DeleteBitmap(gr->hPrebuildBitmap);
949             DeleteDC(gr->hPrebuildDC);
950             gr->hPrebuildDC = 0;
951         }
952 #endif
953     }
954
955     // force paint
956     if (mode == draw_mode_end && gr->mode == draw_mode_begin)
957     {
958         InvalidateRect( gr->wnd_handle, NULL, FALSE );
959     }
960
961     gr->mode=mode;
962
963 }
964
965 static void * get_data(struct graphics_priv *this_, const char *type)
966 {
967     if ( strcmp( "wnd_parent_handle_ptr", type ) == 0 )
968     {
969         return &( this_->wnd_parent_handle );
970     }
971     if ( strcmp( "START_CLIENT", type ) == 0 )
972     {
973         CreateGraphicsWindows( this_, (HMENU)ID_CHILD_GFX );
974         return NULL;
975     }
976     if (!strcmp(type, "window"))
977     {
978         CreateGraphicsWindows( this_ , NULL);
979
980         this_->window.fullscreen = fullscreen;
981         this_->window.disable_suspend = disable_suspend;
982
983         this_->window.priv=g_new0(struct window_priv, 1);
984
985         return &this_->window;
986     }
987     return NULL;
988 }
989
990
991 static void background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
992 {
993     RECT rcClient = { 0, 0, gr->width, gr->height };
994     HBRUSH bgBrush;
995
996     bgBrush = CreateSolidBrush( gc->bg_color  );
997     gr->bg_color = gc->bg_color;
998
999     FillRect( gr->hMemDC, &rcClient, bgBrush );
1000     DeleteObject( bgBrush );
1001 }
1002
1003 struct graphics_font_priv
1004 {
1005     LOGFONT lf;
1006     HFONT hfont;
1007     int size;
1008 };
1009
1010 static void draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy)
1011 {
1012     RECT rcClient;
1013     int prevBkMode;
1014     HFONT hOldFont;
1015     double angle;
1016
1017     GetClientRect( gr->wnd_handle, &rcClient );
1018
1019     SetTextColor(gr->hMemDC, fg->fg_color);
1020     prevBkMode = SetBkMode( gr->hMemDC, TRANSPARENT );
1021
1022     if ( NULL == font->hfont )
1023     {
1024 #ifdef WIN_USE_SYSFONT
1025         font->hfont = (HFONT) GetStockObject (SYSTEM_FONT);
1026         GetObject (font->hfont, sizeof (LOGFONT), &font->lf);
1027 #else
1028         font->hfont = EzCreateFont (gr->hMemDC, TEXT ("Arial"), font->size/2, 0, 0, TRUE);
1029         GetObject ( font->hfont, sizeof (LOGFONT), &font->lf) ;
1030 #endif
1031     }
1032
1033
1034     angle = -atan2( dy, dx ) * 180 / 3.14159 ;
1035     if (angle < 0)
1036         angle += 360;
1037
1038     SetTextAlign (gr->hMemDC, TA_BASELINE) ;
1039     SetViewportOrgEx (gr->hMemDC, p->x, p->y, NULL) ;
1040     font->lf.lfEscapement = font->lf.lfOrientation = ( angle * 10 ) ;
1041     DeleteObject (font->hfont) ;
1042
1043     font->hfont = CreateFontIndirect (&font->lf);
1044     hOldFont = SelectObject(gr->hMemDC, font->hfont );
1045
1046     {
1047         wchar_t utf16[1024];
1048         const UTF8 *utf8 = (UTF8 *)text;
1049         UTF16 *utf16p = (UTF16 *) utf16;
1050         SetBkMode (gr->hMemDC, TRANSPARENT);
1051         if (ConvertUTF8toUTF16(&utf8, utf8+strlen(text),
1052                                &utf16p, utf16p+sizeof(utf16),
1053                                lenientConversion) == conversionOK)
1054         {
1055             ExtTextOutW(gr->hMemDC, 0, 0, 0, NULL,
1056                         utf16, (wchar_t*) utf16p - utf16, NULL);
1057         }
1058     }
1059
1060
1061     SelectObject(gr->hMemDC, hOldFont);
1062     DeleteObject (font->hfont) ;
1063
1064     SetBkMode( gr->hMemDC, prevBkMode );
1065
1066     SetViewportOrgEx (gr->hMemDC, 0, 0, NULL) ;
1067 }
1068
1069 static void font_destroy(struct graphics_font_priv *font)
1070 {
1071     if ( font->hfont )
1072     {
1073         DeleteObject(font->hfont);
1074     }
1075     g_free(font);
1076 }
1077
1078 static struct graphics_font_methods font_methods =
1079 {
1080     font_destroy
1081 };
1082
1083 static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, char *name, int size, int flags)
1084 {
1085     struct graphics_font_priv *font=g_new(struct graphics_font_priv, 1);
1086     *meth = font_methods;
1087
1088     font->hfont = NULL;
1089     font->size = size;
1090
1091     return font;
1092 }
1093
1094 #include "png.h"
1095
1096 static int
1097 pngdecode(struct graphics_priv *gr, char *name, struct graphics_image_priv *img)
1098 {
1099     png_struct    *png_ptr = NULL;
1100     png_info      *info_ptr = NULL;
1101     png_byte      buf[8];
1102     png_byte      **row_pointers = NULL;
1103
1104     int           bit_depth;
1105     int           color_type;
1106     int           alpha_present;
1107     int           ret;
1108     int           i;
1109     FILE *png_file;
1110     BITMAPINFO pnginfo;
1111     HDC dc;
1112
1113     dbg(1,"enter %s\n",name);
1114     png_file=fopen(name, "rb");
1115     if (!png_file)
1116     {
1117         dbg(1,"failed to open %s\n",name);
1118         return FALSE;
1119     }
1120
1121
1122     /* read and check signature in PNG file */
1123     ret = fread (buf, 1, 8, png_file);
1124     if (ret != 8)
1125     {
1126         fclose(png_file);
1127         return FALSE;
1128     }
1129
1130     ret = png_check_sig (buf, 8);
1131     if (!ret)
1132     {
1133         fclose(png_file);
1134         return FALSE;
1135     }
1136
1137     /* create png and info structures */
1138
1139     png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
1140                                       NULL, NULL, NULL);
1141     if (!png_ptr)
1142     {
1143         fclose(png_file);
1144         return FALSE;   /* out of memory */
1145     }
1146
1147     info_ptr = png_create_info_struct (png_ptr);
1148     if (!info_ptr)
1149     {
1150         fclose(png_file);
1151         png_destroy_read_struct (&png_ptr, NULL, NULL);
1152         return FALSE;   /* out of memory */
1153     }
1154
1155     if (setjmp (png_jmpbuf(png_ptr)))
1156     {
1157         fclose(png_file);
1158         png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
1159         return FALSE;
1160     }
1161
1162     /* set up the input control for C streams */
1163     png_init_io (png_ptr, png_file);
1164     png_set_sig_bytes (png_ptr, 8);  /* we already read the 8 signature bytes */
1165
1166     /* read the file information */
1167     png_read_info (png_ptr, info_ptr);
1168
1169     /* get size and bit-depth of the PNG-image */
1170     png_get_IHDR (png_ptr, info_ptr,
1171                   (png_uint_32*)&img->width, (png_uint_32*)&img->height, &bit_depth, &color_type,
1172                   NULL, NULL, NULL);
1173
1174     /* set-up the transformations */
1175
1176     /* transform paletted images into full-color rgb */
1177     if (color_type == PNG_COLOR_TYPE_PALETTE)
1178         png_set_palette_to_rgb(png_ptr);
1179
1180     /* expand images to bit-depth 8 (only applicable for grayscale images) */
1181     if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8) 
1182         png_set_gray_1_2_4_to_8(png_ptr);
1183
1184     /* Expand grayscale to rgb */
1185     if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1186           png_set_gray_to_rgb(png_ptr);
1187
1188     /* expand colored images to bit-depth 8 */
1189     if (color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8)
1190         png_set_packing(png_ptr);
1191
1192     /* transform transparency maps into full alpha-channel */
1193     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
1194         png_set_tRNS_to_alpha(png_ptr);
1195
1196     /* Add opaque alpha channel if no alpha channel exist */
1197     if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE)
1198         png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
1199
1200     /* Strip the pixels down to 8 bit */
1201     if (bit_depth == 16)
1202         png_set_strip_16(png_ptr);
1203
1204     png_set_bgr(png_ptr);
1205
1206     /* all transformations have been registered; now update info_ptr data,
1207      * get rowbytes, and allocate image memory */
1208
1209     png_read_update_info (png_ptr, info_ptr);
1210
1211     img->channels = 4;
1212     alpha_present = 1;
1213     
1214     /* row_bytes is the width x number of channels x (bit-depth / 8) */
1215     img->row_bytes = png_get_rowbytes (png_ptr, info_ptr);
1216
1217     memset(&pnginfo, 0, sizeof(pnginfo));
1218     pnginfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1219     pnginfo.bmiHeader.biWidth = img->width;
1220     pnginfo.bmiHeader.biHeight = -img->height;
1221     pnginfo.bmiHeader.biBitCount = 32;
1222     pnginfo.bmiHeader.biCompression = BI_RGB;
1223     pnginfo.bmiHeader.biPlanes = 1;
1224     dc = CreateCompatibleDC(NULL);
1225     img->hBitmap = CreateDIBSection(dc, &pnginfo, DIB_RGB_COLORS , (void **)&img->png_pixels, NULL, 0);
1226     DeleteDC(dc);
1227
1228     if ((row_pointers = (png_byte **) g_malloc (img->height * sizeof (png_bytep))) == NULL)
1229     {
1230         fclose(png_file);
1231         png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
1232         g_free (img->png_pixels);
1233         img->png_pixels = NULL;
1234         img->hBitmap = NULL;
1235         return FALSE;
1236     }
1237
1238     /* set the individual row_pointers to point at the correct offsets */
1239     for (i = 0; i < (img->height); i++)
1240         row_pointers[i] = img->png_pixels + i * img->row_bytes;
1241
1242     /* now we can go ahead and just read the whole image */
1243     png_read_image (png_ptr, row_pointers);
1244
1245     /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
1246     png_read_end (png_ptr, info_ptr);
1247
1248     /* clean up after the read, and free any memory allocated - REQUIRED */
1249     png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);
1250
1251     if (row_pointers != (unsigned char**) NULL)
1252         g_free (row_pointers);
1253     img->hot.x=img->width/2-1;
1254     img->hot.y=img->height/2-1;
1255     dbg(1,"ok\n");
1256     fclose(png_file);
1257     return TRUE;
1258
1259 } /* end of source */
1260
1261 static void pngscale(struct graphics_image_priv *img, struct graphics_priv *gr, int width, int height)
1262 {
1263         HBITMAP origBmp;
1264         BITMAPINFO pnginfo;
1265         HDC dc1, dc2;
1266         png_byte *origPixels;
1267         
1268         origBmp=img->hBitmap;
1269         origPixels=img->png_pixels;
1270
1271         memset(&pnginfo, 0, sizeof(pnginfo));
1272         pnginfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1273         pnginfo.bmiHeader.biWidth = width;
1274         pnginfo.bmiHeader.biHeight = -height;
1275         pnginfo.bmiHeader.biBitCount = 32;
1276         pnginfo.bmiHeader.biCompression = BI_RGB;
1277         pnginfo.bmiHeader.biPlanes = 1;
1278         dc1 = CreateCompatibleDC(NULL);
1279         dc2 = CreateCompatibleDC(NULL);
1280         img->hBitmap = CreateDIBSection(dc1, &pnginfo, DIB_RGB_COLORS , (void **)&(img->png_pixels), NULL, 0);
1281
1282         if(gr->SetStretchBltMode) {
1283                 gr->SetStretchBltMode(dc1,STRETCH_HALFTONE);
1284                 SetBrushOrgEx(dc1,0,0,NULL);
1285         }
1286
1287         SelectBitmap(dc1,img->hBitmap);
1288         SelectBitmap(dc2,origBmp);
1289
1290         StretchBlt(dc1,0,0,width, height, dc2, 0,0, img->width, img->height,SRCCOPY);
1291         img->width=width;
1292         img->height=height;
1293         img->hot.x=width/2-1;
1294         img->hot.y=height/2-1;
1295         
1296         DeleteDC(dc1);
1297         DeleteDC(dc2);
1298         DeleteObject(origBmp);
1299 }
1300
1301
1302 static void
1303 pngrender(struct graphics_image_priv *img, struct graphics_priv *gr, int x0, int y0)
1304 {
1305         if (gr->AlphaBlend && img->hBitmap)
1306         {
1307                 HDC hdc;
1308                 HBITMAP oldBitmap;
1309                 BLENDFUNCTION blendFunction ;
1310                 blendFunction.BlendOp = AC_SRC_OVER;
1311                 blendFunction.BlendFlags = 0;
1312                 blendFunction.SourceConstantAlpha = 255;
1313                 blendFunction.AlphaFormat = AC_SRC_ALPHA;
1314                 hdc = CreateCompatibleDC(NULL);
1315                 oldBitmap = SelectBitmap(hdc, img->hBitmap);
1316                 gr->AlphaBlend(gr->hMemDC, x0, y0, img->width, img->height, hdc, 0, 0, img->width, img->height, blendFunction);
1317                 (void)SelectBitmap(hdc, oldBitmap);
1318                 DeleteDC(hdc);
1319         }
1320         else
1321         {
1322                 int x, y;
1323                 HDC hdc=gr->hMemDC;
1324                 png_byte *pix_ptr = img->png_pixels;
1325                 COLORREF *pixeldata;
1326                 HDC dc;
1327                 HBITMAP bitmap;
1328                 HBITMAP oldBitmap;
1329
1330                 BITMAPINFO pnginfo;
1331
1332                 memset(&pnginfo, 0, sizeof(pnginfo));
1333                 pnginfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1334                 pnginfo.bmiHeader.biWidth = img->width;
1335                 pnginfo.bmiHeader.biHeight = -img->height;
1336                 pnginfo.bmiHeader.biBitCount = 32;
1337                 pnginfo.bmiHeader.biCompression = BI_RGB;
1338                 pnginfo.bmiHeader.biPlanes = 1;
1339                 dc = CreateCompatibleDC(NULL);
1340                 bitmap = CreateDIBSection(hdc, &pnginfo, DIB_RGB_COLORS, (void **)&pixeldata, NULL, 0);
1341                 oldBitmap = SelectBitmap(dc, bitmap);
1342                 BitBlt(dc, 0, 0, img->width, img->height, hdc, x0, y0, SRCCOPY);
1343                 for (y=0 ; y < img->width ; y++)
1344                 {
1345                         for (x=0 ; x < img->height ; x++)
1346                         {
1347                                 int b = pix_ptr[0];
1348                                 int g = pix_ptr[1];
1349                                 int r = pix_ptr[2];
1350                                 int a = pix_ptr[3];
1351                                 if (a != 0xff)
1352                                 {
1353                                         int p = *pixeldata;
1354                                         int ai = 0xff - a;
1355                                         r = (r * a + ((p >> 16) & 0xff) * ai) / 255;
1356                                         g = (g * a + ((p >>  8) & 0xff) * ai) / 255;
1357                                         b = (b * a + ((p >>  0) & 0xff) * ai) / 255;
1358                                 }
1359                                 *pixeldata++ = (r << 16) | (g << 8) | b;
1360                                 pix_ptr+=img->channels;
1361                         }
1362                 }
1363
1364                 BitBlt(hdc, x0, y0, img->width, img->height, dc, 0, 0, SRCCOPY);
1365                 (void)SelectBitmap(dc, oldBitmap);
1366                 DeleteBitmap(bitmap);
1367                 DeleteDC(dc);
1368         }
1369 }
1370
1371 static int
1372 xpmdecode(char *name, struct graphics_image_priv *img)
1373 {
1374     img->pxpm = Xpm2bmp_new();
1375     if (Xpm2bmp_load( img->pxpm, name ) != 0)
1376     {
1377         g_free(img->pxpm);
1378         return FALSE;
1379     }
1380     img->width=img->pxpm->size_x;
1381     img->height=img->pxpm->size_y;
1382     img->hot.x=img->pxpm->hotspot_x;
1383     img->hot.y=img->pxpm->hotspot_y;
1384     return TRUE;
1385 }
1386
1387
1388
1389 static struct graphics_image_priv *image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h, struct point *hot, int rotation)
1390 {
1391     struct graphics_image_priv* ret;
1392     
1393     char* hash_key = g_strdup_printf("%s_%d_%d_%d",name,*w,*h,rotation);
1394     
1395     if ( !g_hash_table_lookup_extended( gr->image_cache_hash, hash_key, NULL, (gpointer)&ret) )
1396     {
1397         int len=strlen(name);
1398         int rc=0;
1399
1400         if (len >= 4)
1401         {
1402             char *ext;
1403             dbg(2, "loading image '%s'\n", name );
1404             ret = g_new0( struct graphics_image_priv, 1 );
1405             ext = name+len-4;
1406             if (!strcmp(ext,".xpm")) {
1407                 rc=xpmdecode(name, ret);
1408             } else if (!strcmp(ext,".png")) {
1409                 rc=pngdecode(gr, name, ret);
1410             }
1411         }
1412         if (!rc) {
1413             dbg(1, "failed loading '%s'\n", name );
1414             g_free(ret);
1415             ret=NULL;
1416         }
1417
1418         g_hash_table_insert(gr->image_cache_hash, hash_key,  (gpointer)ret );
1419         /* Hash_key will be freed ater the hash table, so set it to NULL here to disable freing it on this function return */
1420         hash_key=NULL;
1421         if(ret) {
1422             if (*w==-1)
1423                 *w=ret->width;
1424             if (*h==-1)
1425                 *h=ret->height;
1426             if (*w!=ret->width || *h!=ret->height) {
1427                 if(ret->png_pixels && ret->hBitmap)
1428                     pngscale(ret, gr, *w, *h);
1429             }
1430        }
1431     }
1432     if (ret) {
1433         *w=ret->width;
1434         *h=ret->height;
1435         if (hot)
1436             *hot=ret->hot;
1437     }
1438     g_free(hash_key);
1439     return ret;
1440 }
1441
1442
1443 static void draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
1444 {
1445     if (img->pxpm)
1446         Xpm2bmp_paint( img->pxpm , gr->hMemDC, p->x, p->y );
1447     if (img->png_pixels)
1448         pngrender(img, gr, p->x, p->y);
1449 }
1450
1451 static struct graphics_priv *
1452             graphics_win32_new_helper(struct graphics_methods *meth);
1453
1454 static void overlay_resize(struct graphics_priv *gr, struct point *p, int w, int h, int alpha, int wraparound)
1455 {
1456     dbg(1, "resize overlay: %x, x: %d, y: %d, w: %d, h: %d, alpha: %x, wraparound: %d\n", gr, p->x, p->y, w, h, alpha, wraparound);
1457
1458     if ( gr->width != w || gr->height != h )
1459     {
1460         gr->width  = w;
1461         gr->height = h;
1462         create_memory_dc(gr);
1463     }
1464     gr->p.x    = p->x;
1465     gr->p.y    = p->y;
1466
1467 }
1468
1469
1470 static struct graphics_priv *
1471             overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound)
1472 {
1473     struct graphics_priv *this=graphics_win32_new_helper(meth);
1474     dbg(1, "overlay: %x, x: %d, y: %d, w: %d, h: %d, alpha: %x, wraparound: %d\n", this, p->x, p->y, w, h, alpha, wraparound);
1475     this->width  = w;
1476     this->height = h;
1477     this->parent = gr;
1478     this->p.x    = p->x;
1479     this->p.y    = p->y;
1480     this->disabled = 0;
1481     this->hPrebuildDC = 0;
1482     this->AlphaBlend = gr->AlphaBlend;
1483     this->image_cache_hash = gr->image_cache_hash;
1484     
1485     this->next = gr->overlays;
1486     gr->overlays = this;
1487     this->wnd_handle = gr->wnd_handle;
1488
1489     if (wraparound)
1490     {
1491         if ( p->x < 0 )
1492         {
1493             this->p.x += gr->width;
1494         }
1495
1496         if ( p->y < 0 )
1497         {
1498             this->p.y += gr->height;
1499         }
1500     }
1501
1502     create_memory_dc(this);
1503     return this;
1504 }
1505
1506 static void overlay_disable(struct graphics_priv *gr, int disable)
1507 {
1508     dbg(1, "overlay: %x, disable: %d\n", gr, disable);
1509     gr->disabled = disable;
1510 }
1511
1512 static void get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret, int estimate)
1513 {
1514     int len = g_utf8_strlen(text, -1);
1515     int xMin = 0;
1516     int yMin = 0;
1517     int yMax = 13*font->size/256;
1518     int xMax = 9*font->size*len/256;
1519
1520     dbg(2, "Get bbox for %s\n", text);
1521
1522     ret[0].x = xMin;
1523     ret[0].y = -yMin;
1524     ret[1].x = xMin;
1525     ret[1].y = -yMax;
1526     ret[2].x = xMax;
1527     ret[2].y = -yMax;
1528     ret[3].x = xMax;
1529     ret[3].y = -yMin;
1530 }
1531
1532
1533 static struct graphics_methods graphics_methods =
1534 {
1535     graphics_destroy,
1536     draw_mode,
1537     draw_lines,
1538     draw_polygon,
1539     draw_rectangle,
1540     draw_circle,
1541     draw_text,
1542     draw_image,
1543 #ifdef HAVE_IMLIB2
1544     NULL, // draw_image_warp,
1545 #else
1546     NULL,
1547 #endif
1548     draw_restore,
1549     draw_drag,
1550     font_new,
1551     gc_new,
1552     background_gc,
1553     overlay_new,
1554     image_new,
1555     get_data,
1556     NULL,   //image_free
1557     get_text_bbox,
1558     overlay_disable,
1559     overlay_resize,
1560 };
1561
1562
1563 static struct graphics_priv *
1564             graphics_win32_new_helper(struct graphics_methods *meth)
1565 {
1566     struct graphics_priv *this_=g_new0(struct graphics_priv,1);
1567     *meth=graphics_methods;
1568     this_->mode = -1;
1569     return this_;
1570 }
1571
1572 static void bind_late(struct graphics_priv* gra_priv)
1573 {
1574 #if HAVE_API_WIN32_CE
1575     gra_priv->hCoreDll = LoadLibrary(TEXT("coredll.dll"));
1576 #else
1577     gra_priv->hCoreDll = LoadLibrary(TEXT("msimg32.dll"));
1578     gra_priv->hGdi32Dll = LoadLibrary(TEXT("gdi32.dll"));
1579     gra_priv->hUser32Dll = GetModuleHandle("user32.dll");
1580 #endif
1581     if ( gra_priv->hCoreDll )
1582     {
1583         gra_priv->AlphaBlend  = (FP_AlphaBlend)GetProcAddress(gra_priv->hCoreDll, TEXT("AlphaBlend") );
1584         if (!gra_priv->AlphaBlend)
1585         {
1586             dbg(1, "AlphaBlend not supported\n");
1587         }
1588 #if HAVE_API_WIN32_CE
1589         gra_priv->SetStretchBltMode= (FP_SetStretchBltMode)GetProcAddress(gra_priv->hCoreDll, TEXT("SetStretchBltMode") );
1590 #else
1591         gra_priv->SetStretchBltMode= (FP_SetStretchBltMode)GetProcAddress(gra_priv->hGdi32Dll, TEXT("SetStretchBltMode") );
1592 #endif
1593         if (!gra_priv->SetStretchBltMode)
1594         {
1595             dbg(1, "SetStretchBltMode not supported\n");
1596         }
1597     }
1598     else
1599     {
1600         dbg(0, "Error loading coredll\n");
1601     }
1602     
1603     if(gra_priv->hUser32Dll) {
1604         gra_priv->ChangeWindowMessageFilterEx=GetProcAddress(gra_priv->hUser32Dll,"ChangeWindowMessageFilterEx");
1605         gra_priv->ChangeWindowMessageFilter=GetProcAddress(gra_priv->hUser32Dll,"ChangeWindowMessageFilter");
1606     }
1607 }
1608
1609
1610
1611 static struct graphics_priv*
1612             graphics_win32_new( struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
1613 {
1614     struct attr *attr;
1615
1616     struct graphics_priv* this_;
1617     HMODULE user32;
1618     if (!event_request_system("win32","graphics_win32"))
1619         return NULL;
1620     this_=graphics_win32_new_helper(meth);
1621     this_->nav=nav;
1622     this_->width=792;
1623     if ((attr=attr_search(attrs, NULL, attr_w)))
1624         this_->width=attr->u.num;
1625     this_->height=547;
1626     if ((attr=attr_search(attrs, NULL, attr_h)))
1627         this_->height=attr->u.num;
1628     this_->overlays = NULL;
1629     this_->cbl=cbl;
1630     this_->parent = NULL;
1631     this_->window.priv = NULL;
1632     this_->image_cache_hash = g_hash_table_new(g_str_hash, g_str_equal);
1633
1634     bind_late(this_);
1635
1636     return this_;
1637 }
1638
1639
1640 static void
1641 event_win32_main_loop_run(void)
1642 {
1643     MSG msg;
1644
1645     dbg(0,"enter\n");
1646     while (GetMessage(&msg, 0, 0, 0))
1647     {
1648         TranslateMessage(&msg);       /*  Keyboard input.      */
1649         DispatchMessage(&msg);
1650     }
1651
1652 }
1653
1654 static void event_win32_main_loop_quit(void)
1655 {
1656 #ifdef HAVE_API_WIN32_CE
1657     HWND hwndTaskbar;
1658     HWND hwndSip;
1659 #endif
1660
1661     dbg(0,"enter\n");
1662
1663 #ifdef HAVE_API_WIN32_CE
1664     hwndTaskbar = FindWindow(L"HHTaskBar", NULL);
1665     hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
1666     // activate the SIP button
1667     ShowWindow(hwndSip, SW_SHOW);
1668     ShowWindow(hwndTaskbar, SW_SHOW);
1669 #endif
1670
1671     DestroyWindow(g_hwnd);
1672 }
1673
1674 static struct event_watch *
1675             event_win32_add_watch(void *h, enum event_watch_cond cond, struct callback *cb)
1676 {
1677     dbg(0,"enter\n");
1678     return NULL;
1679 }
1680
1681 static void
1682 event_win32_remove_watch(struct event_watch *ev)
1683 {
1684     dbg(0,"enter\n");
1685 }
1686
1687 static GList *timers;
1688 struct event_timeout
1689 {
1690     UINT_PTR timer_id;
1691     int multi;
1692     struct callback *cb;
1693     struct event_timeout *next;
1694 };
1695
1696 static void run_timer(UINT_PTR idEvent)
1697 {
1698     GList *l;
1699     struct event_timeout *t;
1700     l = timers;
1701     while (l)
1702     {
1703         t = l->data;
1704         if (t->timer_id == idEvent)
1705         {
1706             struct callback *cb = t->cb;
1707             dbg(2, "Timer %d (multi: %d)\n", t->timer_id, t->multi);
1708             if (!t->multi)
1709             {
1710                 KillTimer(NULL, t->timer_id);
1711                 timers = g_list_remove(timers, t);
1712                 g_free(t);
1713             }
1714             callback_call_0(cb);
1715             return;
1716         }
1717         l = g_list_next(l);
1718     }
1719     dbg(0, "timer %d not found\n", idEvent);
1720 }
1721
1722 static VOID CALLBACK win32_timer_cb(HWND hwnd, UINT uMsg,
1723                                     UINT_PTR idEvent,
1724                                     DWORD dwTime)
1725 {
1726     run_timer(idEvent);
1727 }
1728
1729 static struct event_timeout *
1730             event_win32_add_timeout(int timeout, int multi, struct callback *cb)
1731 {
1732     struct event_timeout *t;
1733     t = g_new0(struct event_timeout, 1);
1734     if (!t)
1735         return t;
1736     t->multi = multi;
1737     timers = g_list_prepend(timers, t);
1738     t->cb = cb;
1739     t->timer_id = SetTimer(NULL, 0, timeout, win32_timer_cb);
1740     dbg(1, "Started timer %d for %d (multi: %d)\n", t->timer_id, timeout, multi);
1741     return t;
1742 }
1743
1744 static void
1745 event_win32_remove_timeout(struct event_timeout *to)
1746 {
1747     if (to)
1748     {
1749         GList *l;
1750         struct event_timeout *t=NULL;
1751         dbg(1, "Try stopping timer %d\n", to->timer_id);
1752         l = timers;
1753         while (l)
1754         {
1755             t = l->data;
1756             /* Use the pointer not the ID, IDs are reused */
1757             if (t == to)
1758             {
1759                 KillTimer(NULL, t->timer_id);
1760                 timers = g_list_remove(timers, t);
1761                 g_free(t);
1762                 return;
1763             }
1764             l = g_list_next(l);
1765         }
1766         dbg(0, "Timer %d not found\n", to->timer_id);
1767         g_free(to);
1768     }
1769 }
1770
1771 static struct event_idle *
1772             event_win32_add_idle(int priority, struct callback *cb)
1773 {
1774         return (struct event_idle *)event_win32_add_timeout(1, 1, cb);
1775 }
1776
1777 static void
1778 event_win32_remove_idle(struct event_idle *ev)
1779 {
1780     event_win32_remove_timeout((struct event_timeout *)ev);
1781 }
1782
1783 static void
1784 event_win32_call_callback(struct callback_list *cb)
1785 {
1786     PostMessage(g_hwnd, WM_USER+2, (WPARAM)cb , (LPARAM)0);
1787 }
1788
1789 static struct event_methods event_win32_methods =
1790 {
1791     event_win32_main_loop_run,
1792     event_win32_main_loop_quit,
1793     event_win32_add_watch,
1794     event_win32_remove_watch,
1795     event_win32_add_timeout,
1796     event_win32_remove_timeout,
1797     event_win32_add_idle,
1798     event_win32_remove_idle,
1799     event_win32_call_callback,
1800 };
1801
1802 static struct event_priv *
1803             event_win32_new(struct event_methods *meth)
1804 {
1805     *meth=event_win32_methods;
1806     return NULL;
1807 }
1808
1809 void
1810 plugin_init(void)
1811 {
1812     plugin_register_graphics_type("win32", graphics_win32_new);
1813     plugin_register_event_type("win32", event_win32_new);
1814 }