[Win32k]
[reactos.git] / reactos / win32ss / user / ntuser / draw.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Win32ss internal drawing support.
5 * FILE: win32ss/user/ntuser/draw.c
6 * PROGRAMER:
7 */
8
9 //
10 // Original code from Wine see user32/windows/draw.c.
11 //
12 //
13
14 #include <win32k.h>
15
16 /* These tables are used in:
17 * UITOOLS_DrawDiagEdge()
18 * UITOOLS_DrawRectEdge()
19 */
20 static const signed char LTInnerNormal[] = {
21 -1, -1, -1, -1,
22 -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
23 -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1,
24 -1, -1, -1, -1
25 };
26
27 static const signed char LTOuterNormal[] = {
28 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
29 COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
30 COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
31 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1
32 };
33
34 static const signed char RBInnerNormal[] = {
35 -1, -1, -1, -1,
36 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
37 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
38 -1, -1, -1, -1
39 };
40
41 static const signed char RBOuterNormal[] = {
42 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
43 COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
44 COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
45 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1
46 };
47
48 static const signed char LTInnerSoft[] = {
49 -1, -1, -1, -1,
50 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
51 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
52 -1, -1, -1, -1
53 };
54
55 static const signed char LTOuterSoft[] = {
56 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
57 COLOR_3DLIGHT, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
58 COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
59 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1
60 };
61
62 #define RBInnerSoft RBInnerNormal /* These are the same */
63 #define RBOuterSoft RBOuterNormal
64
65 static const signed char LTRBOuterMono[] = {
66 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
67 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
68 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
69 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
70 };
71
72 static const signed char LTRBInnerMono[] = {
73 -1, -1, -1, -1,
74 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
75 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
76 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
77 };
78
79 static const signed char LTRBOuterFlat[] = {
80 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
81 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
82 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
83 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
84 };
85
86 static const signed char LTRBInnerFlat[] = {
87 -1, -1, -1, -1,
88 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE,
89 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE,
90 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE,
91 };
92
93 /* Ported from WINE20020904 */
94 /* Same as DrawEdge invoked with BF_DIAGONAL */
95 BOOL FASTCALL IntDrawDiagEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags)
96 {
97 POINT Points[4];
98 signed char InnerI, OuterI;
99 HPEN InnerPen, OuterPen;
100 POINT SavePoint;
101 HPEN SavePen;
102 int spx, spy;
103 int epx, epy;
104 int Width = rc->right - rc->left;
105 int Height= rc->bottom - rc->top;
106 int SmallDiam = Width > Height ? Height : Width;
107 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER
108 || (uType & BDR_OUTER) == BDR_OUTER)
109 && !(uFlags & (BF_FLAT|BF_MONO)) );
110 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
111 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
112
113 /* Init some vars */
114 OuterPen = InnerPen = (HPEN)NtGdiGetStockObject(NULL_PEN);
115 SavePen = (HPEN)NtGdiSelectPen(hdc, InnerPen);
116 spx = spy = epx = epy = 0; /* Satisfy the compiler... */
117
118 /* Determine the colors of the edges */
119 if(uFlags & BF_MONO)
120 {
121 InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
122 OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
123 }
124 else if(uFlags & BF_FLAT)
125 {
126 InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
127 OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
128 }
129 else if(uFlags & BF_SOFT)
130 {
131 if(uFlags & BF_BOTTOM)
132 {
133 InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
134 OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
135 }
136 else
137 {
138 InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
139 OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
140 }
141 }
142 else
143 {
144 if(uFlags & BF_BOTTOM)
145 {
146 InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
147 OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
148 }
149 else
150 {
151 InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
152 OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
153 }
154 }
155
156 if(InnerI != -1)
157 InnerPen = NtGdiGetStockObject(DC_PEN);
158 if(OuterI != -1)
159 OuterPen = NtGdiGetStockObject(DC_PEN);
160
161 GreMoveTo(hdc, 0, 0, &SavePoint);
162
163 /* Don't ask me why, but this is what is visible... */
164 /* This must be possible to do much simpler, but I fail to */
165 /* see the logic in the MS implementation (sigh...). */
166 /* So, this might look a bit brute force here (and it is), but */
167 /* it gets the job done;) */
168
169 switch(uFlags & BF_RECT)
170 {
171 case 0:
172 case BF_LEFT:
173 case BF_BOTTOM:
174 case BF_BOTTOMLEFT:
175 /* Left bottom endpoint */
176 epx = rc->left-1;
177 spx = epx + SmallDiam;
178 epy = rc->bottom;
179 spy = epy - SmallDiam;
180 break;
181
182 case BF_TOPLEFT:
183 case BF_BOTTOMRIGHT:
184 /* Left top endpoint */
185 epx = rc->left-1;
186 spx = epx + SmallDiam;
187 epy = rc->top-1;
188 spy = epy + SmallDiam;
189 break;
190
191 case BF_TOP:
192 case BF_RIGHT:
193 case BF_TOPRIGHT:
194 case BF_RIGHT|BF_LEFT:
195 case BF_RIGHT|BF_LEFT|BF_TOP:
196 case BF_BOTTOM|BF_TOP:
197 case BF_BOTTOM|BF_TOP|BF_LEFT:
198 case BF_BOTTOMRIGHT|BF_LEFT:
199 case BF_BOTTOMRIGHT|BF_TOP:
200 case BF_RECT:
201 /* Right top endpoint */
202 spx = rc->left;
203 epx = spx + SmallDiam;
204 spy = rc->bottom-1;
205 epy = spy - SmallDiam;
206 break;
207 }
208
209 GreMoveTo(hdc, spx, spy, NULL);
210 NtGdiSelectPen(hdc, OuterPen);
211 IntSetDCPenColor(hdc, IntGetSysColor(OuterI));
212 NtGdiLineTo(hdc, epx, epy);
213
214 NtGdiSelectPen(hdc, InnerPen);
215 IntSetDCPenColor(hdc, IntGetSysColor(InnerI));
216
217 switch(uFlags & (BF_RECT|BF_DIAGONAL))
218 {
219 case BF_DIAGONAL_ENDBOTTOMLEFT:
220 case (BF_DIAGONAL|BF_BOTTOM):
221 case BF_DIAGONAL:
222 case (BF_DIAGONAL|BF_LEFT):
223 GreMoveTo(hdc, spx-1, spy, NULL);
224 NtGdiLineTo(hdc, epx, epy-1);
225 Points[0].x = spx-add;
226 Points[0].y = spy;
227 Points[1].x = rc->left;
228 Points[1].y = rc->top;
229 Points[2].x = epx+1;
230 Points[2].y = epy-1-add;
231 Points[3] = Points[2];
232 break;
233
234 case BF_DIAGONAL_ENDBOTTOMRIGHT:
235 GreMoveTo(hdc, spx-1, spy, NULL);
236 NtGdiLineTo(hdc, epx, epy+1);
237 Points[0].x = spx-add;
238 Points[0].y = spy;
239 Points[1].x = rc->left;
240 Points[1].y = rc->bottom-1;
241 Points[2].x = epx+1;
242 Points[2].y = epy+1+add;
243 Points[3] = Points[2];
244 break;
245
246 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
247 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
248 case BF_DIAGONAL_ENDTOPRIGHT:
249 case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
250 GreMoveTo(hdc, spx+1, spy, NULL);
251 NtGdiLineTo(hdc, epx, epy+1);
252 Points[0].x = epx-1;
253 Points[0].y = epy+1+add;
254 Points[1].x = rc->right-1;
255 Points[1].y = rc->top+add;
256 Points[2].x = rc->right-1;
257 Points[2].y = rc->bottom-1;
258 Points[3].x = spx+add;
259 Points[3].y = spy;
260 break;
261
262 case BF_DIAGONAL_ENDTOPLEFT:
263 GreMoveTo(hdc, spx, spy-1, NULL);
264 NtGdiLineTo(hdc, epx+1, epy);
265 Points[0].x = epx+1+add;
266 Points[0].y = epy+1;
267 Points[1].x = rc->right-1;
268 Points[1].y = rc->top;
269 Points[2].x = rc->right-1;
270 Points[2].y = rc->bottom-1-add;
271 Points[3].x = spx;
272 Points[3].y = spy-add;
273 break;
274
275 case (BF_DIAGONAL|BF_TOP):
276 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
277 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
278 GreMoveTo(hdc, spx+1, spy-1, NULL);
279 NtGdiLineTo(hdc, epx, epy);
280 Points[0].x = epx-1;
281 Points[0].y = epy+1;
282 Points[1].x = rc->right-1;
283 Points[1].y = rc->top;
284 Points[2].x = rc->right-1;
285 Points[2].y = rc->bottom-1-add;
286 Points[3].x = spx+add;
287 Points[3].y = spy-add;
288 break;
289
290 case (BF_DIAGONAL|BF_RIGHT):
291 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
292 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
293 GreMoveTo(hdc, spx, spy, NULL);
294 NtGdiLineTo(hdc, epx-1, epy+1);
295 Points[0].x = spx;
296 Points[0].y = spy;
297 Points[1].x = rc->left;
298 Points[1].y = rc->top+add;
299 Points[2].x = epx-1-add;
300 Points[2].y = epy+1+add;
301 Points[3] = Points[2];
302 break;
303 }
304
305 /* Fill the interior if asked */
306 if((uFlags & BF_MIDDLE) && retval)
307 {
308 HBRUSH hbsave;
309 HPEN hpsave;
310 hbsave = (HBRUSH)NtGdiSelectBrush(hdc, NtGdiGetStockObject(DC_BRUSH));
311 hpsave = (HPEN)NtGdiSelectPen(hdc, NtGdiGetStockObject(DC_PEN));
312 IntSetDCBrushColor(hdc, IntGetSysColor(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE));
313 IntSetDCPenColor(hdc, IntGetSysColor(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE));
314 IntPolygon(hdc, Points, 4);
315 NtGdiSelectBrush(hdc, hbsave);
316 NtGdiSelectPen(hdc, hpsave);
317 }
318
319 /* Adjust rectangle if asked */
320 if(uFlags & BF_ADJUST)
321 {
322 if(uFlags & BF_LEFT)
323 rc->left += add;
324 if(uFlags & BF_RIGHT)
325 rc->right -= add;
326 if(uFlags & BF_TOP)
327 rc->top += add;
328 if(uFlags & BF_BOTTOM)
329 rc->bottom -= add;
330 }
331
332 /* Cleanup */
333 NtGdiSelectPen(hdc, SavePen);
334 GreMoveTo(hdc, SavePoint.x, SavePoint.y, NULL);
335
336 return retval;
337 }
338
339 /* Ported from WINE20020904 */
340 /* Same as DrawEdge invoked without BF_DIAGONAL
341 *
342 * 23-Nov-1997: Changed by Bertho Stultiens
343 *
344 * Well, I started testing this and found out that there are a few things
345 * that weren't quite as win95. The following rewrite should reproduce
346 * win95 results completely.
347 * The colorselection is table-driven to avoid awfull if-statements.
348 * The table below show the color settings.
349 *
350 * Pen selection table for uFlags = 0
351 *
352 * uType | LTI | LTO | RBI | RBO
353 * ------+-------+-------+-------+-------
354 * 0000 | x | x | x | x
355 * 0001 | x | 22 | x | 21
356 * 0010 | x | 16 | x | 20
357 * 0011 | x | x | x | x
358 * ------+-------+-------+-------+-------
359 * 0100 | x | 20 | x | 16
360 * 0101 | 20 | 22 | 16 | 21
361 * 0110 | 20 | 16 | 16 | 20
362 * 0111 | x | x | x | x
363 * ------+-------+-------+-------+-------
364 * 1000 | x | 21 | x | 22
365 * 1001 | 21 | 22 | 22 | 21
366 * 1010 | 21 | 16 | 22 | 20
367 * 1011 | x | x | x | x
368 * ------+-------+-------+-------+-------
369 * 1100 | x | x | x | x
370 * 1101 | x | x (22)| x | x (21)
371 * 1110 | x | x (16)| x | x (20)
372 * 1111 | x | x | x | x
373 *
374 * Pen selection table for uFlags = BF_SOFT
375 *
376 * uType | LTI | LTO | RBI | RBO
377 * ------+-------+-------+-------+-------
378 * 0000 | x | x | x | x
379 * 0001 | x | 20 | x | 21
380 * 0010 | x | 21 | x | 20
381 * 0011 | x | x | x | x
382 * ------+-------+-------+-------+-------
383 * 0100 | x | 22 | x | 16
384 * 0101 | 22 | 20 | 16 | 21
385 * 0110 | 22 | 21 | 16 | 20
386 * 0111 | x | x | x | x
387 * ------+-------+-------+-------+-------
388 * 1000 | x | 16 | x | 22
389 * 1001 | 16 | 20 | 22 | 21
390 * 1010 | 16 | 21 | 22 | 20
391 * 1011 | x | x | x | x
392 * ------+-------+-------+-------+-------
393 * 1100 | x | x | x | x
394 * 1101 | x | x (20)| x | x (21)
395 * 1110 | x | x (21)| x | x (20)
396 * 1111 | x | x | x | x
397 *
398 * x = don't care; (n) = is what win95 actually uses
399 * LTI = left Top Inner line
400 * LTO = left Top Outer line
401 * RBI = Right Bottom Inner line
402 * RBO = Right Bottom Outer line
403 * 15 = COLOR_BTNFACE
404 * 16 = COLOR_BTNSHADOW
405 * 20 = COLOR_BTNHIGHLIGHT
406 * 21 = COLOR_3DDKSHADOW
407 * 22 = COLOR_3DLIGHT
408 */
409 BOOL FASTCALL IntDrawRectEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags)
410 {
411 signed char LTInnerI, LTOuterI;
412 signed char RBInnerI, RBOuterI;
413 HPEN LTInnerPen, LTOuterPen;
414 HPEN RBInnerPen, RBOuterPen;
415 RECT InnerRect = *rc;
416 POINT SavePoint;
417 HPEN SavePen;
418 int LBpenplus = 0;
419 int LTpenplus = 0;
420 int RTpenplus = 0;
421 int RBpenplus = 0;
422 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER
423 || (uType & BDR_OUTER) == BDR_OUTER)
424 && !(uFlags & (BF_FLAT|BF_MONO)) );
425 /* Init some vars */
426 LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)NtGdiGetStockObject(NULL_PEN);
427 SavePen = (HPEN)NtGdiSelectPen(hdc, LTInnerPen);
428
429 /* Determine the colors of the edges */
430 if(uFlags & BF_MONO)
431 {
432 LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
433 LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
434 }
435 else if(uFlags & BF_FLAT)
436 {
437 LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
438 LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
439
440 /* Bertho Stultiens states above that this function exactly matches win95
441 * In win98 BF_FLAT rectangles have an inner border same color as the
442 * middle (COLOR_BTNFACE). I believe it's the same for win95 but since
443 * I don't know I go with Bertho and just sets it for win98 until proven
444 * otherwise.
445 * Dennis Björklund, 10 June, 99
446 */
447 if( LTInnerI != -1 )
448 LTInnerI = RBInnerI = COLOR_BTNFACE;
449 }
450 else if(uFlags & BF_SOFT)
451 {
452 LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
453 LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
454 RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
455 RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
456 }
457 else
458 {
459 LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
460 LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
461 RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
462 RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
463 }
464
465 if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT)
466 LBpenplus = 1;
467 if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT)
468 RTpenplus = 1;
469 if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT)
470 RBpenplus = 1;
471 if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)
472 LTpenplus = 1;
473
474 if(LTInnerI != -1)
475 LTInnerPen = NtGdiGetStockObject(DC_PEN);
476 if(LTOuterI != -1)
477 LTOuterPen = NtGdiGetStockObject(DC_PEN);
478 if(RBInnerI != -1)
479 RBInnerPen = NtGdiGetStockObject(DC_PEN);
480 if(RBOuterI != -1)
481 RBOuterPen = NtGdiGetStockObject(DC_PEN);
482 if((uFlags & BF_MIDDLE) && retval)
483 {
484 FillRect(hdc, &InnerRect, IntGetSysColorBrush(uFlags & BF_MONO ?
485 COLOR_WINDOW : COLOR_BTNFACE));
486 }
487 GreMoveTo(hdc, 0, 0, &SavePoint);
488
489 /* Draw the outer edge */
490 NtGdiSelectPen(hdc, LTOuterPen);
491 IntSetDCPenColor(hdc, IntGetSysColor(LTOuterI));
492 if(uFlags & BF_TOP)
493 {
494 GreMoveTo(hdc, InnerRect.left, InnerRect.top, NULL);
495 NtGdiLineTo(hdc, InnerRect.right, InnerRect.top);
496 }
497 if(uFlags & BF_LEFT)
498 {
499 GreMoveTo(hdc, InnerRect.left, InnerRect.top, NULL);
500 NtGdiLineTo(hdc, InnerRect.left, InnerRect.bottom);
501 }
502 NtGdiSelectPen(hdc, RBOuterPen);
503 IntSetDCPenColor(hdc, IntGetSysColor(RBOuterI));
504 if(uFlags & BF_BOTTOM)
505 {
506 GreMoveTo(hdc, InnerRect.left, InnerRect.bottom-1, NULL);
507 NtGdiLineTo(hdc, InnerRect.right, InnerRect.bottom-1);
508 }
509 if(uFlags & BF_RIGHT)
510 {
511 GreMoveTo(hdc, InnerRect.right-1, InnerRect.top, NULL);
512 NtGdiLineTo(hdc, InnerRect.right-1, InnerRect.bottom);
513 }
514
515 /* Draw the inner edge */
516 NtGdiSelectPen(hdc, LTInnerPen);
517 IntSetDCPenColor(hdc, IntGetSysColor(LTInnerI));
518 if(uFlags & BF_TOP)
519 {
520 GreMoveTo(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
521 NtGdiLineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
522 }
523 if(uFlags & BF_LEFT)
524 {
525 GreMoveTo(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
526 NtGdiLineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
527 }
528 NtGdiSelectPen(hdc, RBInnerPen);
529 IntSetDCPenColor(hdc, IntGetSysColor(RBInnerI));
530 if(uFlags & BF_BOTTOM)
531 {
532 GreMoveTo(hdc, InnerRect.left+LBpenplus, InnerRect.bottom-2, NULL);
533 NtGdiLineTo(hdc, InnerRect.right-RBpenplus, InnerRect.bottom-2);
534 }
535 if(uFlags & BF_RIGHT)
536 {
537 GreMoveTo(hdc, InnerRect.right-2, InnerRect.top+RTpenplus, NULL);
538 NtGdiLineTo(hdc, InnerRect.right-2, InnerRect.bottom-RBpenplus);
539 }
540
541 if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) )
542 {
543 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
544 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
545
546 if(uFlags & BF_LEFT)
547 InnerRect.left += add;
548 if(uFlags & BF_RIGHT)
549 InnerRect.right -= add;
550 if(uFlags & BF_TOP)
551 InnerRect.top += add;
552 if(uFlags & BF_BOTTOM)
553 InnerRect.bottom -= add;
554
555 if(uFlags & BF_ADJUST)
556 *rc = InnerRect;
557 }
558
559 /* Cleanup */
560 NtGdiSelectPen(hdc, SavePen);
561 GreMoveTo(hdc, SavePoint.x, SavePoint.y, NULL);
562 return retval;
563 }
564
565 int FASTCALL UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst)
566 {
567 int Width = src->right - src->left;
568 int Height = src->bottom - src->top;
569 int SmallDiam = Width > Height ? Height : Width;
570
571 *dst = *src;
572
573 /* Make it a square box */
574 if(Width < Height) /* SmallDiam == Width */
575 {
576 dst->top += (Height-Width)/2;
577 dst->bottom = dst->top + SmallDiam;
578 }
579 else if(Width > Height) /* SmallDiam == Height */
580 {
581 dst->left += (Width-Height)/2;
582 dst->right = dst->left + SmallDiam;
583 }
584
585 return SmallDiam;
586 }
587
588 /* Ported from WINE20020904 */
589 void FASTCALL UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect )
590 {
591 if(IntGetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
592 {
593 HBRUSH hbsave;
594 COLORREF bg;
595
596 FillRect(dc, rect, IntGetSysColorBrush(COLOR_BTNFACE));
597 bg = IntGdiSetBkColor(dc, RGB(255, 255, 255));
598 hbsave = NtGdiSelectBrush(dc, gpsi->hbrGray);
599 NtGdiPatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089);
600 NtGdiSelectBrush(dc, hbsave);
601 IntGdiSetBkColor(dc, bg);
602 }
603 else
604 {
605 FillRect(dc, rect, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT));
606 }
607 }
608
609 /* Ported from WINE20020904 */
610 /* Draw a push button coming from DrawFrameControl()
611 *
612 * Does a pretty good job in emulating MS behavior. Some quirks are
613 * however there because MS uses a TrueType font (Marlett) to draw
614 * the buttons.
615 *
616 * FIXME: This looks a little bit strange, needs to be rewritten completely
617 * (several quirks with adjust, DFCS_CHECKED aso)
618 */
619 BOOL FASTCALL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags)
620 {
621 UINT edge;
622 RECT myr = *r;
623
624 if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
625 edge = EDGE_SUNKEN;
626 else
627 edge = EDGE_RAISED;
628
629 if(uFlags & DFCS_CHECKED)
630 {
631 if(uFlags & DFCS_MONO)
632 IntDrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
633 else
634 IntDrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST);
635
636 UITOOLS_DrawCheckedRect( dc, &myr );
637 }
638 else
639 {
640 if(uFlags & DFCS_MONO)
641 {
642 IntDrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
643 FillRect(dc, &myr, IntGetSysColorBrush(COLOR_BTNFACE));
644 }
645 else
646 {
647 IntDrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT | BF_SOFT);
648 }
649 }
650
651 /* Adjust rectangle if asked */
652 if(uFlags & DFCS_ADJUSTRECT)
653 {
654 r->left += 2;
655 r->right -= 2;
656 r->top += 2;
657 r->bottom -= 2;
658 }
659
660 return TRUE;
661 }
662
663 BOOL FASTCALL UITOOLS95_DFC_ButtonCheckRadio(HDC dc, LPRECT r, UINT uFlags, BOOL Radio)
664 {
665 LOGFONTW lf;
666 HFONT hFont, hOldFont;
667 int i;
668 WCHAR OutRight, OutLeft, InRight, InLeft, Center;
669
670 if (Radio)
671 {
672 OutRight = 'j'; // Outer right
673 OutLeft = 'k'; // Outer left
674 InRight = 'l'; // inner left
675 InLeft = 'm'; // inner right
676 Center = 'n'; // center
677 } else
678 {
679 OutRight = 'c'; // Outer right
680 OutLeft = 'd'; // Outer left
681 InRight = 'e'; // inner left
682 InLeft = 'f'; // inner right
683 Center = 'g'; // center
684 }
685
686 RtlZeroMemory(&lf, sizeof(LOGFONTW));
687 lf.lfHeight = r->top - r->bottom;
688 lf.lfWidth = 0;
689 lf.lfWeight = FW_NORMAL;
690 lf.lfCharSet = DEFAULT_CHARSET;
691 RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
692 hFont = GreCreateFontIndirectW(&lf);
693 hOldFont = NtGdiSelectFont(dc, hFont);
694
695 if(Radio && ((uFlags & 0xff) == DFCS_BUTTONRADIOMASK))
696 {
697 IntGdiSetBkMode(dc, OPAQUE);
698 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
699 GreTextOutW(dc, r->left, r->top, &Center, 1);
700 IntGdiSetBkMode(dc, TRANSPARENT);
701 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
702 GreTextOutW(dc, r->left, r->top, &OutRight, 1);
703 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
704 GreTextOutW(dc, r->left, r->top, &OutLeft, 1);
705 }
706 else
707 {
708 IntGdiSetBkMode(dc, TRANSPARENT);
709
710 /* Center section, white for active, grey for inactive */
711 i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
712 IntGdiSetTextColor(dc, IntGetSysColor(i));
713 GreTextOutW(dc, r->left, r->top, &Center, 1);
714
715 if(uFlags & (DFCS_FLAT | DFCS_MONO))
716 {
717 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
718 GreTextOutW(dc, r->left, r->top, &OutRight, 1);
719 GreTextOutW(dc, r->left, r->top, &OutLeft, 1);
720 GreTextOutW(dc, r->left, r->top, &InRight, 1);
721 GreTextOutW(dc, r->left, r->top, &InLeft, 1);
722 }
723 else
724 {
725 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNSHADOW));
726 GreTextOutW(dc, r->left, r->top, &OutRight, 1);
727 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
728 GreTextOutW(dc, r->left, r->top, &OutLeft, 1);
729 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_3DDKSHADOW));
730 GreTextOutW(dc, r->left, r->top, &InRight, 1);
731 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_3DLIGHT));
732 GreTextOutW(dc, r->left, r->top, &InLeft, 1);
733 }
734 }
735
736 if(uFlags & DFCS_CHECKED)
737 {
738 WCHAR Check = (Radio) ? 'i' : 'b';
739
740 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWTEXT));
741 GreTextOutW(dc, r->left, r->top, &Check, 1);
742 }
743
744 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWTEXT));
745 NtGdiSelectFont(dc, hOldFont);
746 GreDeleteObject(hFont);
747
748 return TRUE;
749 }
750
751 /* Ported from WINE20020904 */
752 BOOL FASTCALL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState)
753 {
754 switch(uState & 0xff)
755 {
756 case DFCS_BUTTONPUSH:
757 return UITOOLS95_DFC_ButtonPush(hdc, rc, uState);
758
759 case DFCS_BUTTONCHECK:
760 case DFCS_BUTTON3STATE:
761 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, FALSE);
762
763 case DFCS_BUTTONRADIOIMAGE:
764 case DFCS_BUTTONRADIOMASK:
765 case DFCS_BUTTONRADIO:
766 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE);
767
768 /*
769 default:
770 DbgPrint("Invalid button state=0x%04x\n", uState);
771 */
772 }
773 return FALSE;
774 }
775
776 BOOL FASTCALL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
777 {
778 LOGFONTW lf;
779 HFONT hFont, hOldFont;
780 COLORREF clrsave;
781 RECT myr;
782 INT bkmode;
783 WCHAR Symbol;
784 switch(uFlags & 0xff)
785 {
786 case DFCS_CAPTIONCLOSE:
787 Symbol = 'r';
788 break;
789 case DFCS_CAPTIONHELP:
790 Symbol = 's';
791 break;
792 case DFCS_CAPTIONMIN:
793 Symbol = '0';
794 break;
795 case DFCS_CAPTIONMAX:
796 Symbol = '1';
797 break;
798 case DFCS_CAPTIONRESTORE:
799 Symbol = '2';
800 break;
801 default:
802 return FALSE;
803 }
804 IntDrawRectEdge(dc,r,(uFlags&DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT);
805 RtlZeroMemory(&lf, sizeof(LOGFONTW));
806 UITOOLS_MakeSquareRect(r, &myr);
807 myr.left += 1;
808 myr.top += 1;
809 myr.right -= 1;
810 myr.bottom -= 1;
811 if(uFlags & DFCS_PUSHED)
812 RECTL_vOffsetRect(&myr,1,1);
813 lf.lfHeight = myr.bottom - myr.top;
814 lf.lfWidth = 0;
815 lf.lfWeight = FW_NORMAL;
816 lf.lfCharSet = DEFAULT_CHARSET;
817 RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
818 hFont = GreCreateFontIndirectW(&lf);
819 /* save font and text color */
820 hOldFont = NtGdiSelectFont(dc, hFont);
821 clrsave = GreGetTextColor(dc);
822 bkmode = GreGetBkMode(dc);
823 /* set color and drawing mode */
824 IntGdiSetBkMode(dc, TRANSPARENT);
825 if(uFlags & DFCS_INACTIVE)
826 {
827 /* draw shadow */
828 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
829 GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
830 }
831 IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
832 /* draw selected symbol */
833 GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
834 /* restore previous settings */
835 IntGdiSetTextColor(dc, clrsave);
836 NtGdiSelectFont(dc, hOldFont);
837 IntGdiSetBkMode(dc, bkmode);
838 GreDeleteObject(hFont);
839 return TRUE;
840 }
841
842 BOOL FASTCALL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
843 {
844 LOGFONTW lf;
845 HFONT hFont, hOldFont;
846 COLORREF clrsave;
847 RECT myr;
848 INT bkmode;
849 WCHAR Symbol;
850 switch(uFlags & 0xff)
851 {
852 case DFCS_SCROLLCOMBOBOX:
853 case DFCS_SCROLLDOWN:
854 Symbol = '6';
855 break;
856
857 case DFCS_SCROLLUP:
858 Symbol = '5';
859 break;
860
861 case DFCS_SCROLLLEFT:
862 Symbol = '3';
863 break;
864
865 case DFCS_SCROLLRIGHT:
866 Symbol = '4';
867 break;
868
869 case DFCS_SCROLLSIZEGRIP:
870 case DFCS_SCROLLSIZEGRIPRIGHT:
871 RtlZeroMemory(&lf, sizeof(LOGFONTW));
872 UITOOLS_MakeSquareRect(r, &myr);
873 lf.lfHeight = myr.bottom - myr.top;
874 lf.lfWidth = 0;
875 lf.lfWeight = FW_NORMAL;
876 lf.lfCharSet = DEFAULT_CHARSET;
877 RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
878 hFont = GreCreateFontIndirectW(&lf);
879 /* save font and text color */
880 hOldFont = NtGdiSelectFont(dc, hFont);
881 clrsave = GreGetTextColor(dc);
882 bkmode = GreGetBkMode(dc);
883 /* set color and drawing mode */
884 IntGdiSetBkMode(dc, TRANSPARENT);
885 if (!(uFlags & (DFCS_MONO | DFCS_FLAT)))
886 {
887 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
888 /* draw selected symbol */
889 Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'o' : 'x';
890 GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
891 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNSHADOW));
892 } else
893 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
894 /* draw selected symbol */
895 Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'p' : 'y';
896 GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
897 /* restore previous settings */
898 IntGdiSetTextColor(dc, clrsave);
899 NtGdiSelectFont(dc, hOldFont);
900 IntGdiSetBkMode(dc, bkmode);
901 GreDeleteObject(hFont);
902 return TRUE;
903 default:
904 return FALSE;
905 }
906 IntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT);
907 RtlZeroMemory(&lf, sizeof(LOGFONTW));
908 UITOOLS_MakeSquareRect(r, &myr);
909 myr.left += 1;
910 myr.top += 1;
911 myr.right -= 1;
912 myr.bottom -= 1;
913 if(uFlags & DFCS_PUSHED)
914 RECTL_vOffsetRect(&myr,1,1);
915 lf.lfHeight = myr.bottom - myr.top;
916 lf.lfWidth = 0;
917 lf.lfWeight = FW_NORMAL;
918 lf.lfCharSet = DEFAULT_CHARSET;
919 RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
920 hFont = GreCreateFontIndirectW(&lf);
921 /* save font and text color */
922 hOldFont = NtGdiSelectFont(dc, hFont);
923 clrsave = GreGetTextColor(dc);
924 bkmode = GreGetBkMode(dc);
925 /* set color and drawing mode */
926 IntGdiSetBkMode(dc, TRANSPARENT);
927 if(uFlags & DFCS_INACTIVE)
928 {
929 /* draw shadow */
930 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
931 GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
932 }
933 IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
934 /* draw selected symbol */
935 GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
936 /* restore previous settings */
937 IntGdiSetTextColor(dc, clrsave);
938 NtGdiSelectFont(dc, hOldFont);
939 IntGdiSetBkMode(dc, bkmode);
940 GreDeleteObject(hFont);
941 return TRUE;
942 }
943
944 BOOL FASTCALL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
945 {
946 LOGFONTW lf;
947 HFONT hFont, hOldFont;
948 WCHAR Symbol;
949 switch(uFlags & 0xff)
950 {
951 case DFCS_MENUARROW:
952 Symbol = '8';
953 break;
954
955 case DFCS_MENUARROWRIGHT:
956 Symbol = 'w'; // FIXME: needs to confirm
957 break;
958
959 case DFCS_MENUBULLET:
960 Symbol = 'h';
961 break;
962
963 case DFCS_MENUCHECK:
964 Symbol = 'a';
965 break;
966
967 default:
968 /*
969 DbgPrint("Invalid menu; flags=0x%04x\n", uFlags);
970 */
971 return FALSE;
972 }
973 /* acquire ressources only if valid menu */
974 RtlZeroMemory(&lf, sizeof(LOGFONTW));
975 lf.lfHeight = r->bottom - r->top;
976 lf.lfWidth = 0;
977 lf.lfWeight = FW_NORMAL;
978 lf.lfCharSet = DEFAULT_CHARSET;
979 RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
980 hFont = GreCreateFontIndirectW(&lf);
981 /* save font */
982 hOldFont = NtGdiSelectFont(dc, hFont);
983 // FIXME selecting color doesn't work
984 #if 0
985 if(uFlags & DFCS_INACTIVE)
986 {
987 /* draw shadow */
988 IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
989 GreTextOutW(dc, r->left + 1, r->top + 1, &Symbol, 1);
990 }
991 IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
992 #endif
993 /* draw selected symbol */
994 GreTextOutW(dc, r->left, r->top, &Symbol, 1);
995 /* restore previous settings */
996 NtGdiSelectFont(dc, hOldFont);
997 GreDeleteObject(hFont);
998 return TRUE;
999 }
1000
1001 //
1002 //
1003 // Win32ss API support.
1004 //
1005 //
1006
1007
1008 INT WINAPI
1009 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1010 {
1011 BOOL Ret;
1012 HBRUSH prevhbr = NULL;
1013
1014 /* Select brush if specified */
1015 if (hbr)
1016 {
1017 /* Handle system colors */
1018 if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1))
1019 hbr = IntGetSysColorBrush(PtrToUlong(hbr) - 1);
1020
1021 prevhbr = NtGdiSelectBrush(hDC, hbr);
1022 if (prevhbr == NULL)
1023 return (INT)FALSE;
1024 }
1025
1026 Ret = NtGdiPatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left,
1027 lprc->bottom - lprc->top, PATCOPY);
1028
1029 /* Select old brush */
1030 if (prevhbr)
1031 NtGdiSelectBrush(hDC, prevhbr);
1032
1033 return (INT)Ret;
1034 }
1035
1036 BOOL WINAPI
1037 DrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags)
1038 {
1039 if (flags & BF_DIAGONAL)
1040 return IntDrawDiagEdge(hDC, rc, edge, flags);
1041 else
1042 return IntDrawRectEdge(hDC, rc, edge, flags);
1043 }
1044
1045 BOOL WINAPI
1046 DrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState)
1047 {
1048 if (GreGetMapMode(hDC) != MM_TEXT)
1049 return FALSE;
1050
1051 switch(uType)
1052 {
1053 case DFC_BUTTON:
1054 return UITOOLS95_DrawFrameButton(hDC, rc, uState);
1055 case DFC_CAPTION:
1056 return UITOOLS95_DrawFrameCaption(hDC, rc, uState);
1057 case DFC_MENU:
1058 return UITOOLS95_DrawFrameMenu(hDC, rc, uState);
1059 #if 0
1060 case DFC_POPUPMENU:
1061 UNIMPLEMENTED;
1062 break;
1063 #endif
1064 case DFC_SCROLL:
1065 return UITOOLS95_DrawFrameScroll(hDC, rc, uState);
1066 }
1067 return FALSE;
1068 }
1069