ReadConsoleA: use ir as pointer to (req+1).
[wine] / controls / static.c
1 /*
2  * Static control
3  *
4  * Copyright  David W. Metcalfe, 1993
5  *
6  */
7
8 #include "wine/winuser16.h"
9 #include "win.h"
10 #include "bitmap.h"
11 #include "cursoricon.h"
12 #include "static.h"
13 #include "heap.h"
14 #include "debugtools.h"
15 #include "tweak.h"
16
17 DEFAULT_DEBUG_CHANNEL(static)
18
19 static void STATIC_PaintTextfn( WND *wndPtr, HDC hdc );
20 static void STATIC_PaintRectfn( WND *wndPtr, HDC hdc );
21 static void STATIC_PaintIconfn( WND *wndPtr, HDC hdc );
22 static void STATIC_PaintBitmapfn( WND *wndPtr, HDC hdc );
23 static void STATIC_PaintEtchedfn( WND *wndPtr, HDC hdc );
24
25 static COLORREF color_windowframe, color_background, color_window;
26
27
28 typedef void (*pfPaint)( WND *, HDC );
29
30 static pfPaint staticPaintFunc[SS_TYPEMASK+1] =
31 {
32     STATIC_PaintTextfn,      /* SS_LEFT */
33     STATIC_PaintTextfn,      /* SS_CENTER */
34     STATIC_PaintTextfn,      /* SS_RIGHT */
35     STATIC_PaintIconfn,      /* SS_ICON */
36     STATIC_PaintRectfn,      /* SS_BLACKRECT */
37     STATIC_PaintRectfn,      /* SS_GRAYRECT */
38     STATIC_PaintRectfn,      /* SS_WHITERECT */
39     STATIC_PaintRectfn,      /* SS_BLACKFRAME */
40     STATIC_PaintRectfn,      /* SS_GRAYFRAME */
41     STATIC_PaintRectfn,      /* SS_WHITEFRAME */
42     NULL,                    /* Not defined */
43     STATIC_PaintTextfn,      /* SS_SIMPLE */
44     STATIC_PaintTextfn,      /* SS_LEFTNOWORDWRAP */
45     NULL,                    /* SS_OWNERDRAW */
46     STATIC_PaintBitmapfn,    /* SS_BITMAP */
47     NULL,                    /* SS_ENHMETAFILE */
48     STATIC_PaintEtchedfn,    /* SS_ETCHEDHORIZ */
49     STATIC_PaintEtchedfn,    /* SS_ETCHEDVERT */
50     STATIC_PaintEtchedfn,    /* SS_ETCHEDFRAME */
51 };
52
53
54 /***********************************************************************
55  *           STATIC_SetIcon
56  *
57  * Set the icon for an SS_ICON control.
58  */
59 static HICON16 STATIC_SetIcon( WND *wndPtr, HICON16 hicon )
60 {
61     HICON16 prevIcon;
62     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
63     CURSORICONINFO *info = hicon?(CURSORICONINFO *) GlobalLock16( hicon ):NULL;
64
65     if ((wndPtr->dwStyle & SS_TYPEMASK) != SS_ICON) return 0;
66     if (hicon && !info) {
67         ERR("huh? hicon!=0, but info=0???\n");
68         return 0;
69     }
70     prevIcon = infoPtr->hIcon;
71     infoPtr->hIcon = hicon;
72     if (hicon)
73     {
74         SetWindowPos( wndPtr->hwndSelf, 0, 0, 0, info->nWidth, info->nHeight,
75                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
76         GlobalUnlock16( hicon );
77     }
78     return prevIcon;
79 }
80
81 /***********************************************************************
82  *           STATIC_SetBitmap
83  *
84  * Set the bitmap for an SS_BITMAP control.
85  */
86 static HICON16 STATIC_SetBitmap( WND *wndPtr, HICON16 hicon )
87 {
88     HICON16 prevIcon;
89     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
90     BITMAPOBJ *info = (BITMAPOBJ *)GDI_HEAP_LOCK(hicon);
91
92     if ((wndPtr->dwStyle & SS_TYPEMASK) != SS_BITMAP) return 0;
93     if (hicon && !info) {
94         ERR("huh? hicon!=0, but info=0???\n");
95         return 0;
96     }
97     prevIcon = infoPtr->hIcon;
98     infoPtr->hIcon = hicon;
99     if (hicon)
100     {
101         SetWindowPos( wndPtr->hwndSelf, 0, 0, 0, info->bitmap.bmWidth, info->bitmap.bmHeight,
102                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
103     }
104     GDI_HEAP_UNLOCK( hicon );
105     return prevIcon;
106 }
107
108
109 /***********************************************************************
110  *           STATIC_LoadIcon
111  *
112  * Load the icon for an SS_ICON control.
113  */
114 static HICON16 STATIC_LoadIcon( WND *wndPtr, LPCSTR name )
115 {
116     HICON16 hicon;
117
118     if (wndPtr->flags & WIN_ISWIN32)
119     {
120         if (!HIWORD(wndPtr->hInstance)) {
121             LPSTR segname = SEGPTR_STRDUP(name);
122             hicon = LoadIcon16( wndPtr->hInstance, SEGPTR_GET(segname) );
123             SEGPTR_FREE(segname);
124         } else
125             hicon = LoadIconA( wndPtr->hInstance, name );
126     } else {
127         LPSTR segname = SEGPTR_STRDUP(name);
128
129         if (HIWORD(wndPtr->hInstance))
130                 FIXME("win16 window class, but win32 hinstance??\n");
131         hicon = LoadIcon16( wndPtr->hInstance, SEGPTR_GET(segname) );
132         SEGPTR_FREE(segname);
133     }
134     if (!hicon)
135         hicon = LoadIconA( 0, name );
136     return hicon;
137 }
138
139 /***********************************************************************
140  *           STATIC_LoadBitmap
141  *
142  * Load the bitmap for an SS_BITMAP control.
143  */
144 static HBITMAP16 STATIC_LoadBitmap( WND *wndPtr, LPCSTR name )
145 {
146     HBITMAP16 hbitmap;
147
148     if (wndPtr->flags & WIN_ISWIN32)
149     {
150         hbitmap = LoadBitmapA( wndPtr->hInstance, name );
151         if (!hbitmap)  /* Try OEM icon (FIXME: is this right?) */
152             hbitmap = LoadBitmapA( 0, name );
153     }
154     else
155     {
156         LPSTR segname = SEGPTR_STRDUP(name);
157         hbitmap = LoadBitmap16( wndPtr->hInstance, SEGPTR_GET(segname) );
158         if (!hbitmap)  /* Try OEM icon (FIXME: is this right?) */
159             hbitmap = LoadBitmapA( 0, segname );
160         SEGPTR_FREE(segname);
161     }
162     return hbitmap;
163 }
164
165
166 /***********************************************************************
167  *           StaticWndProc
168  */
169 LRESULT WINAPI StaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam,
170                               LPARAM lParam )
171 {
172     LRESULT lResult = 0;
173     WND *wndPtr = WIN_FindWndPtr(hWnd);
174     LONG style = wndPtr->dwStyle & SS_TYPEMASK;
175     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
176
177     switch (uMsg)
178     {
179     case WM_NCCREATE: {
180         CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
181
182         if ((TWEAK_WineLook > WIN31_LOOK) && (wndPtr->dwStyle & SS_SUNKEN))
183             wndPtr->dwExStyle |= WS_EX_STATICEDGE;
184
185         if (style == SS_ICON)
186         {
187             if (cs->lpszName)
188             {
189                 if (!HIWORD(cs->lpszName) || cs->lpszName[0])
190                     STATIC_SetIcon( wndPtr,
191                                 STATIC_LoadIcon( wndPtr, cs->lpszName ));
192             }
193             lResult = 1;
194             goto END;
195         }
196         if (style == SS_BITMAP)
197         {
198             if (cs->lpszName)
199                 STATIC_SetBitmap( wndPtr,
200                                 STATIC_LoadBitmap( wndPtr, cs->lpszName ));
201             WARN("style SS_BITMAP, dwStyle is 0x%08lx\n",
202                         wndPtr->dwStyle);
203             lResult = 1;
204             goto END;
205         }
206         if (!HIWORD(cs->lpszName) && (cs->lpszName))
207         {
208                 FIXME("windowName is 0x%04x, not doing DefWindowProc\n",
209                     LOWORD(cs->lpszName));
210                 lResult = 1;
211                 goto END;
212         }
213         lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
214         goto END;
215     }
216     case WM_CREATE:
217         if (style < 0L || style > SS_TYPEMASK)
218         {
219             ERR("Unknown style 0x%02lx\n", style );
220             lResult = -1L;
221             break;
222         }
223         /* initialise colours */
224         color_windowframe  = GetSysColor(COLOR_WINDOWFRAME);
225         color_background   = GetSysColor(COLOR_BACKGROUND);
226         color_window       = GetSysColor(COLOR_WINDOW);
227         break;
228
229     case WM_NCDESTROY:
230         if (style == SS_ICON) {
231 /*
232  * FIXME
233  *           DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
234  * 
235  * We don't want to do this yet because DestroyIcon32 is broken. If the icon
236  * had already been loaded by the application the last thing we want to do is
237  * GlobalFree16 the handle.
238  */
239         } else {
240             lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
241         }
242         break;
243
244     case WM_PAINT:
245         {
246             PAINTSTRUCT ps;
247             BeginPaint( hWnd, &ps );
248             if (staticPaintFunc[style])
249                 (staticPaintFunc[style])( wndPtr, ps.hdc );
250             EndPaint( hWnd, &ps );
251         }
252         break;
253
254     case WM_ENABLE:
255         InvalidateRect( hWnd, NULL, FALSE );
256         break;
257
258     case WM_SYSCOLORCHANGE:
259         color_windowframe  = GetSysColor(COLOR_WINDOWFRAME);
260         color_background   = GetSysColor(COLOR_BACKGROUND);
261         color_window       = GetSysColor(COLOR_WINDOW);
262         InvalidateRect( hWnd, NULL, TRUE );
263         break;
264
265     case WM_SETTEXT:
266         if (style == SS_ICON)
267             /* FIXME : should we also return the previous hIcon here ??? */
268             STATIC_SetIcon( wndPtr, STATIC_LoadIcon( wndPtr, (LPCSTR)lParam ));
269         else if (style == SS_BITMAP) 
270             STATIC_SetBitmap(wndPtr,STATIC_LoadBitmap(wndPtr,(LPCSTR)lParam ));
271         else
272             DEFWND_SetText( wndPtr, (LPCSTR)lParam );
273         InvalidateRect( hWnd, NULL, FALSE );
274         UpdateWindow( hWnd );
275         break;
276
277     case WM_SETFONT:
278         if (style == SS_ICON)
279         {
280             lResult = 0;
281             goto END;
282         }
283         if (style == SS_BITMAP)
284         {
285             lResult = 0;
286             goto END;
287         }
288         infoPtr->hFont = (HFONT16)wParam;
289         if (LOWORD(lParam))
290         {
291             InvalidateRect( hWnd, NULL, FALSE );
292             UpdateWindow( hWnd );
293         }
294         break;
295
296     case WM_GETFONT:
297         lResult = infoPtr->hFont;
298         goto END;
299
300     case WM_NCHITTEST:
301         lResult = HTTRANSPARENT;
302         goto END;
303
304     case WM_GETDLGCODE:
305         lResult = DLGC_STATIC;
306         goto END;
307
308     case STM_GETIMAGE:
309     case STM_GETICON16:
310     case STM_GETICON:
311         lResult = infoPtr->hIcon;
312         goto END;
313
314     case STM_SETIMAGE:
315         /* FIXME: handle wParam */
316         lResult = STATIC_SetBitmap( wndPtr, (HBITMAP)lParam );
317         InvalidateRect( hWnd, NULL, FALSE );
318         UpdateWindow( hWnd );
319         break;
320
321     case STM_SETICON16:
322     case STM_SETICON:
323         lResult = STATIC_SetIcon( wndPtr, (HICON16)wParam );
324         InvalidateRect( hWnd, NULL, FALSE );
325         UpdateWindow( hWnd );
326         break;
327
328     default:
329         lResult = DefWindowProcA(hWnd, uMsg, wParam, lParam);
330         break;
331     }
332     
333 END:
334     WIN_ReleaseWndPtr(wndPtr);
335     return lResult;
336 }
337
338
339 static void STATIC_PaintTextfn( WND *wndPtr, HDC hdc )
340 {
341     RECT rc;
342     HBRUSH hBrush;
343     WORD wFormat;
344
345     LONG style = wndPtr->dwStyle;
346     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
347
348     GetClientRect( wndPtr->hwndSelf, &rc);
349
350     switch (style & SS_TYPEMASK)
351     {
352     case SS_LEFT:
353         wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
354         break;
355
356     case SS_CENTER:
357         wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
358         break;
359
360     case SS_RIGHT:
361         wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
362         break;
363
364     case SS_SIMPLE:
365         wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP;
366         break;
367
368     case SS_LEFTNOWORDWRAP:
369         wFormat = DT_LEFT | DT_EXPANDTABS | DT_VCENTER;
370         break;
371
372     default:
373         return;
374     }
375
376     if (style & SS_NOPREFIX)
377         wFormat |= DT_NOPREFIX;
378
379     if (infoPtr->hFont) SelectObject( hdc, infoPtr->hFont );
380     hBrush = SendMessageA( GetParent(wndPtr->hwndSelf), WM_CTLCOLORSTATIC,
381                              hdc, wndPtr->hwndSelf );
382     if (!hBrush) hBrush = GetStockObject(WHITE_BRUSH);
383     FillRect( hdc, &rc, hBrush );
384     if (wndPtr->text) DrawTextA( hdc, wndPtr->text, -1, &rc, wFormat );
385 }
386
387 static void STATIC_PaintRectfn( WND *wndPtr, HDC hdc )
388 {
389     RECT rc;
390     HBRUSH hBrush;
391
392     GetClientRect( wndPtr->hwndSelf, &rc);
393     
394     switch (wndPtr->dwStyle & SS_TYPEMASK)
395     {
396     case SS_BLACKRECT:
397         hBrush = CreateSolidBrush(color_windowframe);
398         FillRect( hdc, &rc, hBrush );
399         break;
400     case SS_GRAYRECT:
401         hBrush = CreateSolidBrush(color_background);
402         FillRect( hdc, &rc, hBrush );
403         break;
404     case SS_WHITERECT:
405         hBrush = CreateSolidBrush(color_window);
406         FillRect( hdc, &rc, hBrush );
407         break;
408     case SS_BLACKFRAME:
409         hBrush = CreateSolidBrush(color_windowframe);
410         FrameRect( hdc, &rc, hBrush );
411         break;
412     case SS_GRAYFRAME:
413         hBrush = CreateSolidBrush(color_background);
414         FrameRect( hdc, &rc, hBrush );
415         break;
416     case SS_WHITEFRAME:
417         hBrush = CreateSolidBrush(color_window);
418         FrameRect( hdc, &rc, hBrush );
419         break;
420     default:
421         return;
422     }
423     DeleteObject( hBrush );
424 }
425
426
427 static void STATIC_PaintIconfn( WND *wndPtr, HDC hdc )
428 {
429     RECT rc;
430     HBRUSH hbrush;
431     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
432
433     GetClientRect( wndPtr->hwndSelf, &rc );
434     hbrush = SendMessageA( GetParent(wndPtr->hwndSelf), WM_CTLCOLORSTATIC,
435                              hdc, wndPtr->hwndSelf );
436     FillRect( hdc, &rc, hbrush );
437     if (infoPtr->hIcon) DrawIcon( hdc, rc.left, rc.top, infoPtr->hIcon );
438 }
439
440 static void STATIC_PaintBitmapfn(WND *wndPtr, HDC hdc )
441 {
442     RECT rc;
443     HBRUSH hbrush;
444     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
445     HDC hMemDC;
446     HBITMAP oldbitmap;
447
448     GetClientRect( wndPtr->hwndSelf, &rc );
449     hbrush = SendMessageA( GetParent(wndPtr->hwndSelf), WM_CTLCOLORSTATIC,
450                              hdc, wndPtr->hwndSelf );
451     FillRect( hdc, &rc, hbrush );
452     if (infoPtr->hIcon) {
453         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_HEAP_LOCK( infoPtr->hIcon );
454
455         if (!bmp) return;
456         if (!(hMemDC = CreateCompatibleDC( hdc ))) return;
457
458         oldbitmap = SelectObject(hMemDC,infoPtr->hIcon);
459         BitBlt(hdc,bmp->size.cx,bmp->size.cy,bmp->bitmap.bmWidth,bmp->bitmap.bmHeight,hMemDC,0,0,SRCCOPY);
460         DeleteDC(hMemDC);
461         GDI_HEAP_UNLOCK(infoPtr->hIcon);
462     }
463 }
464
465
466 static void STATIC_PaintEtchedfn( WND *wndPtr, HDC hdc )
467 {
468     RECT rc;
469     HBRUSH hbrush;
470     HPEN hpen;
471
472     if (TWEAK_WineLook == WIN31_LOOK)
473         return;
474
475     GetClientRect( wndPtr->hwndSelf, &rc );
476     hbrush = SendMessageA( GetParent(wndPtr->hwndSelf), WM_CTLCOLORSTATIC,
477                              hdc, wndPtr->hwndSelf );
478     FillRect( hdc, &rc, hbrush );
479
480     switch (wndPtr->dwStyle & SS_TYPEMASK)
481     {
482         case SS_ETCHEDHORZ:
483             hpen = SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
484             MoveToEx (hdc, rc.left, rc.bottom / 2 - 1, NULL);
485             LineTo (hdc, rc.right - 1, rc.bottom / 2 - 1);
486             SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
487             MoveToEx (hdc, rc.left, rc.bottom / 2, NULL);
488             LineTo (hdc, rc.right, rc.bottom / 2);
489             LineTo (hdc, rc.right, rc.bottom / 2 - 1);
490             SelectObject (hdc, hpen);
491             break;
492
493         case SS_ETCHEDVERT:
494             hpen = SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
495             MoveToEx (hdc, rc.right / 2 - 1, rc.top, NULL);
496             LineTo (hdc, rc.right / 2 - 1, rc.bottom - 1);
497             SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
498             MoveToEx (hdc, rc.right / 2, rc.top, NULL);
499             LineTo (hdc, rc.right / 2, rc.bottom);
500             LineTo (hdc, rc.right / 2 -1 , rc.bottom);
501             SelectObject (hdc, hpen); 
502             break;
503
504         case SS_ETCHEDFRAME:
505             DrawEdge (hdc, &rc, EDGE_ETCHED, BF_RECT);
506             break;
507     }
508 }
509