- CopyAcceleratorTable can cause a buffer overflow because it uses an
[wine] / dlls / cards / cards.c
1 /*
2  * Cards dll implementation
3  *
4  * Copyright (C) 2004 Sami Nopanen
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "wingdi.h"
29
30 #include "cards.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(cards);
34
35
36 void WINAPI cdtTerm(void);
37
38
39 static HINSTANCE hInst;
40 static int cardWidth;
41 static int cardHeight;
42 static HBITMAP cardBitmaps[CARD_MAX + 1];
43
44
45 /***********************************************************************
46  * Initializes the cards.dll library. Loads the card bitmaps from the
47  * resources, and initializes the card size variables.
48  */
49 BOOL WINAPI cdtInit(int *width, int *height)
50 {
51         BITMAP bm;
52         int i;
53
54         TRACE("(%p, %p)\n", width, height);
55
56         for(i = 0; i <= CARD_MAX; i++)
57                 cardBitmaps[i] = 0;
58
59         for(i = 0; i <= CARD_MAX; i++)
60         {
61                 cardBitmaps[i] = LoadBitmapA(hInst, MAKEINTRESOURCEA(i));
62                 if(cardBitmaps[i] == 0)
63                 {
64                         cdtTerm();
65                         return FALSE;
66                 }
67         }
68
69         GetObjectA(cardBitmaps[0], sizeof(BITMAP), &bm);
70         *width = cardWidth = bm.bmWidth;
71         *height = cardHeight = bm.bmHeight;
72         return TRUE;
73 }
74
75
76 /***********************************************************************
77  * Draw a card. Unlike cdtDrawCard, this version allows you to stretch
78  * card bitmaps to the size you specify (dx, dy). See cdtDraw for info
79  * on card, mode and color parameters.
80  */
81 BOOL WINAPI cdtDrawExt(HDC hdc, int x, int y, int dx, int dy, int card, int mode, DWORD color)
82 {
83         HDC hMemoryDC;
84         HBITMAP hCardBitmap;
85         HGDIOBJ result;
86         DWORD rasterOp = SRCCOPY;
87         BOOL roundCornersFlag;
88         COLORREF savedPixels[12];
89         BOOL eraseFlag = FALSE;
90         BOOL drawFlag = TRUE;
91
92         TRACE("(%p, %d, %d, %d, %d, %d, %d, %ld)\n", hdc, x, y, dx, dy, card, mode, color);
93
94         roundCornersFlag = !(mode & MODEFLAG_DONT_ROUND_CORNERS) &&
95                            (dx == cardWidth) && (dy == cardHeight);
96         mode &= ~MODEFLAG_DONT_ROUND_CORNERS;
97
98         if((card < 0) || (card > CARD_MAX))
99         {
100                 FIXME("Unexpected card: %d\n", card);
101                 return FALSE;
102         }
103
104         if((mode < MODE_FACEUP) || (mode > MODE_DECKO))
105         {
106                 FIXME("Unexpected mode: %d\n", mode);
107                 return FALSE;
108         }
109
110         switch(mode)
111         {
112         case MODE_FACEUP:
113                 break;
114         case MODE_FACEDOWN:
115                 break;
116         case MODE_HILITE:
117                 rasterOp = NOTSRCCOPY;
118                 break;
119         case MODE_GHOST:
120                 card = CARD_FREE_MASK;
121                 eraseFlag = TRUE;
122                 rasterOp = SRCAND;
123                 break;
124         case MODE_REMOVE:
125                 eraseFlag = TRUE;
126                 drawFlag = FALSE;
127                 break;
128         case MODE_INVISIBLEGHOST:
129                 card = CARD_FREE_MASK;
130                 rasterOp = SRCAND;
131                 break;
132         case MODE_DECKX:
133                 card = CARD_BACK_THE_X;
134                 break;
135         case MODE_DECKO:
136                 card = CARD_BACK_THE_O;
137                 break;
138         }
139
140         hMemoryDC = CreateCompatibleDC(hdc);
141         if(hMemoryDC == 0)
142                 return FALSE;
143
144         if(eraseFlag)
145         {
146                 HBRUSH hBrush;
147                 RECT rect;
148                 hBrush = CreateSolidBrush(color);
149                 rect.left = x;
150                 rect.top = y;
151                 rect.right = x + cardWidth - 1;
152                 rect.bottom = y + cardHeight - 1;
153                 FillRect(hdc, &rect, hBrush);
154         }
155
156         if(drawFlag)
157         {
158                 hCardBitmap = cardBitmaps[card];
159                 if(hCardBitmap == 0)
160                         return FALSE;
161
162                 result = SelectObject(hMemoryDC, hCardBitmap);
163                 if((result == 0) || (result == HGDI_ERROR))
164                 {
165                         DeleteDC(hMemoryDC);
166                         return FALSE;
167                 }
168
169                 SetBkColor(hdc, color);
170
171                 if(roundCornersFlag)
172                 {
173                         savedPixels[0] = GetPixel(hdc, x, y);
174                         savedPixels[1] = GetPixel(hdc, x + 1, y);
175                         savedPixels[2] = GetPixel(hdc, x, y + 1);
176                         savedPixels[3] = GetPixel(hdc, x + dx - 1, y);
177                         savedPixels[4] = GetPixel(hdc, x + dx - 2, y);
178                         savedPixels[5] = GetPixel(hdc, x + dx - 1, y + 1);
179                         savedPixels[6] = GetPixel(hdc, x, y + dy - 1);
180                         savedPixels[7] = GetPixel(hdc, x + 1, y + dy - 1);
181                         savedPixels[8] = GetPixel(hdc, x, y + dy - 2);
182                         savedPixels[9] = GetPixel(hdc, x + dx - 1, y + dy - 1);
183                         savedPixels[10] = GetPixel(hdc, x + dx - 2, y + dy - 1);
184                         savedPixels[11] = GetPixel(hdc, x + dx - 1, y + dy - 2);
185                 }
186
187                 if((cardWidth == dx) && (cardHeight == dy))
188                         BitBlt(hdc, x, y, cardWidth, cardHeight, hMemoryDC, 0, 0, rasterOp);
189                 else
190                         StretchBlt(hdc, x, y, dx, dy, hMemoryDC, 0, 0, cardWidth, cardHeight, rasterOp);
191
192                 if(roundCornersFlag)
193                 {
194                         SetPixel(hdc, x, y, savedPixels[0]);
195                         SetPixel(hdc, x + 1, y, savedPixels[1]);
196                         SetPixel(hdc, x, y + 1, savedPixels[2]);
197                         SetPixel(hdc, x + dx - 1, y, savedPixels[3]);
198                         SetPixel(hdc, x + dx - 2, y, savedPixels[4]);
199                         SetPixel(hdc, x + dx - 1, y + 1, savedPixels[5]);
200                         SetPixel(hdc, x, y + dy - 1, savedPixels[6]);
201                         SetPixel(hdc, x + 1, y + dy - 1, savedPixels[7]);
202                         SetPixel(hdc, x, y + dy - 2, savedPixels[8]);
203                         SetPixel(hdc, x + dx - 1, y + dy - 1, savedPixels[9]);
204                         SetPixel(hdc, x + dx - 2, y + dy - 1, savedPixels[10]);
205                         SetPixel(hdc, x + dx - 1, y + dy - 2, savedPixels[11]);
206                 }
207         }
208
209         DeleteDC(hMemoryDC);
210
211         return TRUE;
212 }
213
214
215 /***********************************************************************
216  * Draws a card at position x, y in its default size (as returned by
217  * cdtInit.
218  *
219  * Mode controls how the card gets drawn:
220  *   MODE_FACEUP                ; draw card facing up
221  *   MODE_FACEDOWN              ; draw card facing down
222  *   MODE_HILITE                ; draw face up, with NOTSRCCOPY
223  *   MODE_GHOST                 ; draw 'ghost' card
224  *   MODE_REMOVE                ; draw with background color
225  *   MODE_INVISIBLEGHOST        ; draw 'ghost' card, without clearing background
226  *   MODE_DECKX                 ; draw X
227  *   MODE_DECKO                 ; draw O
228  *
229  * The card parameter defines the card graphic to be drawn. If we are
230  * drawing fronts of cards, card should have a value from 0 through 51
231  * to represent the card face. If we are drawing card backs, 53 through
232  * 68 represent different card backs.
233  *
234  * When drawing card faces, two lowest bits represent the card suit
235  * (clubs, diamonds, hearts, spades), and the bits above that define the
236  * card value (ace, 2, ..., king). That is,
237  *   card = face * 4 + suit.
238  *
239  * Color parameter defines the background color, used when drawing some
240  * card backs.
241  */
242 BOOL WINAPI cdtDraw(HDC hdc, int x, int y, int card, int mode, DWORD color)
243 {
244         TRACE("(%p, %d, %d, %d, %d, %ld)\n", hdc, x, y, card, mode, color);
245
246         return cdtDrawExt(hdc, x, y, cardWidth, cardHeight, card, mode, color);
247 }
248
249
250 /***********************************************************************
251  * Animates the card backs, e.g. blinking lights on the robot, the sun
252  * donning sunglasses, bats flying across the caste, etc.. Works only
253  * for cards of normal size (as drawn with cdtDraw). To draw frames of
254  * the card back animation, start with frame = 0, and increment the
255  * frame by one, until cdtAnimate returns FALSE (to indicate that we
256  * have gone through all frames of animation).
257  */
258 BOOL WINAPI cdtAnimate(HDC hdc, int cardback, int x, int y, int frame)
259 {
260         TRACE("(%p, %d, %d, %d, %d)\n", hdc, cardback, x, y, frame);
261         FIXME("Implement me.\n");
262
263         return FALSE;
264 }
265
266
267 /***********************************************************************
268  * Frees resources reserved by cdtInitialize.
269  */
270 void WINAPI cdtTerm()
271 {
272         int i;
273
274         TRACE("()\n");
275
276         for(i = 0; i <= CARD_MAX; i++)
277         {
278                 if(cardBitmaps[i] != 0)
279                         DeleteObject(cardBitmaps[i]);
280                 cardBitmaps[i] = 0;
281         }
282 }
283
284
285 /***********************************************************************
286  * DllMain.
287  */
288 BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
289 {
290     switch (reason)
291     {
292     case DLL_PROCESS_ATTACH:
293         hInst = inst;
294         DisableThreadLibraryCalls( inst );
295         break;
296     case DLL_PROCESS_DETACH:
297         break;
298     }
299     return TRUE;
300 }