03720cacbba0865bed514409b477f0ce9ce6953b
[reactos.git] / reactos / dll / win32 / comdlg32 / colordlg16.c
1 /*
2 * COMMDLG - Color Dialog
3 *
4 * Copyright 1994 Martin Ayotte
5 * Copyright 1996 Albrecht Kleine
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 /* BUGS : still seems to not refresh correctly
23 sometimes, especially when 2 instances of the
24 dialog are loaded at the same time */
25
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "wine/winbase16.h"
35 #include "wine/winuser16.h"
36 #include "winuser.h"
37 #include "commdlg.h"
38 #include "dlgs.h"
39 #include "wine/debug.h"
40 #include "cderr.h"
41 #include "cdlg.h"
42 #include "cdlg16.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
45
46 /* Chose Color PRIVATE Structure:
47 *
48 * This is a duplicate of the 32bit code with
49 * an extra member
50 */
51 typedef struct CCPRIVATE
52 {
53 LPCHOOSECOLORW lpcc; /* points to public known data structure */
54 LPCHOOSECOLOR16 lpcc16; /* save the 16 bits pointer */
55 int nextuserdef; /* next free place in user defined color array */
56 HDC hdcMem; /* color graph used for BitBlt() */
57 HBITMAP hbmMem; /* color graph bitmap */
58 RECT fullsize; /* original dialog window size */
59 UINT msetrgb; /* # of SETRGBSTRING message (today not used) */
60 RECT old3angle; /* last position of l-marker */
61 RECT oldcross; /* last position of color/satuation marker */
62 BOOL updating; /* to prevent recursive WM_COMMAND/EN_UPDATE processing */
63 int h;
64 int s;
65 int l; /* for temporary storing of hue,sat,lum */
66 int capturedGraph; /* control mouse captured */
67 RECT focusRect; /* rectangle last focused item */
68 HWND hwndFocus; /* handle last focused item */
69 } *LCCPRIV;
70
71 /***********************************************************************
72 * CC_WMInitDialog16 [internal]
73 */
74 static LONG CC_WMInitDialog16( HWND hDlg, WPARAM wParam, LPARAM lParam )
75 {
76 int i, res;
77 int r, g, b;
78 HWND hwnd;
79 RECT rect;
80 POINT point;
81 LCCPRIV lpp;
82 CHOOSECOLORW *ch32;
83 CHOOSECOLOR16 *ch16 = (CHOOSECOLOR16 *) lParam;
84
85 TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
86 lpp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct CCPRIVATE) );
87
88 if (ch16->lStructSize != sizeof(CHOOSECOLOR16) )
89 {
90 HeapFree(GetProcessHeap(), 0, lpp);
91 EndDialog (hDlg, 0) ;
92 return FALSE;
93 }
94 ch32 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CHOOSECOLORW) );
95 lpp->lpcc = ch32;
96 lpp->lpcc16 = ch16;
97 ch32->lStructSize = sizeof(CHOOSECOLORW);
98 ch32->hwndOwner = HWND_32(ch16->hwndOwner);
99 /* Should be an HINSTANCE but MS made a typo */
100 ch32->hInstance = HWND_32(ch16->hInstance);
101 ch32->lpCustColors = MapSL(ch16->lpCustColors);
102 ch32->lpfnHook = (LPCCHOOKPROC) ch16->lpfnHook; /* only used as flag */
103 ch32->Flags = ch16->Flags;
104
105 SetWindowLongPtrW(hDlg, DWLP_USER, (LONG_PTR)lpp);
106
107 if (!(lpp->lpcc->Flags & CC_SHOWHELP))
108 ShowWindow( GetDlgItem(hDlg,0x40e), SW_HIDE);
109 lpp->msetrgb = RegisterWindowMessageA(SETRGBSTRINGA);
110
111 #if 0
112 cpos = MAKELONG(5,7); /* init */
113 if (lpp->lpcc->Flags & CC_RGBINIT)
114 {
115 for (i = 0; i < 6; i++)
116 for (j = 0; j < 8; j++)
117 if (predefcolors[i][j] == lpp->lpcc->rgbResult)
118 {
119 cpos = MAKELONG(i,j);
120 goto found;
121 }
122 }
123 found:
124 /* FIXME: Draw_a_focus_rect & set_init_values */
125 #endif
126
127 GetWindowRect(hDlg, &lpp->fullsize);
128 if (lpp->lpcc->Flags & CC_FULLOPEN || lpp->lpcc->Flags & CC_PREVENTFULLOPEN)
129 {
130 hwnd = GetDlgItem(hDlg, 0x2cf);
131 EnableWindow(hwnd, FALSE);
132 }
133 if (!(lpp->lpcc->Flags & CC_FULLOPEN ) || lpp->lpcc->Flags & CC_PREVENTFULLOPEN)
134 {
135 rect = lpp->fullsize;
136 res = rect.bottom - rect.top;
137 hwnd = GetDlgItem(hDlg, 0x2c6); /* cut at left border */
138 point.x = point.y = 0;
139 ClientToScreen(hwnd, &point);
140 ScreenToClient(hDlg,&point);
141 GetClientRect(hDlg, &rect);
142 point.x += GetSystemMetrics(SM_CXDLGFRAME);
143 SetWindowPos(hDlg, 0, 0, 0, point.x, res, SWP_NOMOVE|SWP_NOZORDER);
144
145 for (i = 0x2bf; i < 0x2c5; i++)
146 ShowWindow( GetDlgItem(hDlg, i), SW_HIDE);
147 for (i = 0x2d3; i < 0x2d9; i++)
148 ShowWindow( GetDlgItem(hDlg, i), SW_HIDE);
149 ShowWindow( GetDlgItem(hDlg, 0x2c9), SW_HIDE);
150 ShowWindow( GetDlgItem(hDlg, 0x2c8), SW_HIDE);
151 ShowWindow( GetDlgItem(hDlg, 0x2c6), SW_HIDE);
152 ShowWindow( GetDlgItem(hDlg, 0x2c5), SW_HIDE);
153 ShowWindow( GetDlgItem(hDlg, 1090 ), SW_HIDE);
154 }
155 else
156 CC_SwitchToFullSize(hDlg, lpp->lpcc->rgbResult, NULL);
157 res = TRUE;
158 for (i = 0x2bf; i < 0x2c5; i++)
159 SendMessageA( GetDlgItem(hDlg, i), EM_LIMITTEXT, 3, 0); /* max 3 digits: xyz */
160 if (CC_HookCallChk(lpp->lpcc))
161 {
162 res = CallWindowProc16( (WNDPROC16)lpp->lpcc16->lpfnHook,
163 HWND_16(hDlg), WM_INITDIALOG, wParam, lParam);
164 }
165
166 /* Set the initial values of the color chooser dialog */
167 r = GetRValue(lpp->lpcc->rgbResult);
168 g = GetGValue(lpp->lpcc->rgbResult);
169 b = GetBValue(lpp->lpcc->rgbResult);
170
171 CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
172 lpp->h = CC_RGBtoHSL('H', r, g, b);
173 lpp->s = CC_RGBtoHSL('S', r, g, b);
174 lpp->l = CC_RGBtoHSL('L', r, g, b);
175
176 /* Doing it the long way because CC_EditSetRGB/HSL doesn't seem to work */
177 SetDlgItemInt(hDlg, 703, lpp->h, TRUE);
178 SetDlgItemInt(hDlg, 704, lpp->s, TRUE);
179 SetDlgItemInt(hDlg, 705, lpp->l, TRUE);
180 SetDlgItemInt(hDlg, 706, r, TRUE);
181 SetDlgItemInt(hDlg, 707, g, TRUE);
182 SetDlgItemInt(hDlg, 708, b, TRUE);
183
184 CC_PaintCross(hDlg, lpp->h, lpp->s);
185 CC_PaintTriangle(hDlg, lpp->l);
186
187 return res;
188 }
189
190 /***********************************************************************
191 * CC_WMCommand16 [internal]
192 */
193 static LRESULT CC_WMCommand16( HWND hDlg, WPARAM wParam, LPARAM lParam, WORD notifyCode, HWND hwndCtl )
194 {
195 int r, g, b, i, xx;
196 UINT cokmsg;
197 HDC hdc;
198 COLORREF *cr;
199 LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER);
200 TRACE("CC_WMCommand wParam=%x lParam=%lx\n", wParam, lParam);
201 switch (wParam)
202 {
203 case 0x2c2: /* edit notify RGB */
204 case 0x2c3:
205 case 0x2c4:
206 if (notifyCode == EN_UPDATE && !lpp->updating)
207 {
208 i = CC_CheckDigitsInEdit(hwndCtl, 255);
209 r = GetRValue(lpp->lpcc->rgbResult);
210 g = GetGValue(lpp->lpcc->rgbResult);
211 b= GetBValue(lpp->lpcc->rgbResult);
212 xx = 0;
213 switch (wParam)
214 {
215 case 0x2c2: if ((xx = (i != r))) r = i; break;
216 case 0x2c3: if ((xx = (i != g))) g = i; break;
217 case 0x2c4: if ((xx = (i != b))) b = i; break;
218 }
219 if (xx) /* something has changed */
220 {
221 lpp->lpcc->rgbResult = RGB(r, g, b);
222 CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
223 lpp->h = CC_RGBtoHSL('H', r, g, b);
224 lpp->s = CC_RGBtoHSL('S', r, g, b);
225 lpp->l = CC_RGBtoHSL('L', r, g, b);
226 CC_EditSetHSL(hDlg, lpp->h, lpp->s, lpp->l);
227 CC_PaintCross(hDlg, lpp->h, lpp->s);
228 CC_PaintTriangle(hDlg, lpp->l);
229 }
230 }
231 break;
232
233 case 0x2bf: /* edit notify HSL */
234 case 0x2c0:
235 case 0x2c1:
236 if (notifyCode == EN_UPDATE && !lpp->updating)
237 {
238 i = CC_CheckDigitsInEdit(hwndCtl , wParam == 0x2bf ? 239:240);
239 xx = 0;
240 switch (wParam)
241 {
242 case 0x2bf: if ((xx = ( i != lpp->h))) lpp->h = i; break;
243 case 0x2c0: if ((xx = ( i != lpp->s))) lpp->s = i; break;
244 case 0x2c1: if ((xx = ( i != lpp->l))) lpp->l = i; break;
245 }
246 if (xx) /* something has changed */
247 {
248 r = CC_HSLtoRGB('R', lpp->h, lpp->s, lpp->l);
249 g = CC_HSLtoRGB('G', lpp->h, lpp->s, lpp->l);
250 b = CC_HSLtoRGB('B', lpp->h, lpp->s, lpp->l);
251 lpp->lpcc->rgbResult = RGB(r, g, b);
252 CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
253 CC_EditSetRGB(hDlg, lpp->lpcc->rgbResult);
254 CC_PaintCross(hDlg, lpp->h, lpp->s);
255 CC_PaintTriangle(hDlg, lpp->l);
256 }
257 }
258 break;
259
260 case 0x2cf:
261 CC_SwitchToFullSize(hDlg, lpp->lpcc->rgbResult, &lpp->fullsize);
262 SetFocus( GetDlgItem(hDlg, 0x2bf));
263 break;
264
265 case 0x2c8: /* add colors ... column by column */
266 cr = lpp->lpcc->lpCustColors;
267 cr[(lpp->nextuserdef % 2) * 8 + lpp->nextuserdef / 2] = lpp->lpcc->rgbResult;
268 if (++lpp->nextuserdef == 16)
269 lpp->nextuserdef = 0;
270 CC_PaintUserColorArray(hDlg, 2, 8, lpp->lpcc->lpCustColors);
271 break;
272
273 case 0x2c9: /* resulting color */
274 hdc = GetDC(hDlg);
275 lpp->lpcc->rgbResult = GetNearestColor(hdc, lpp->lpcc->rgbResult);
276 ReleaseDC(hDlg, hdc);
277 CC_EditSetRGB(hDlg, lpp->lpcc->rgbResult);
278 CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
279 r = GetRValue(lpp->lpcc->rgbResult);
280 g = GetGValue(lpp->lpcc->rgbResult);
281 b = GetBValue(lpp->lpcc->rgbResult);
282 lpp->h = CC_RGBtoHSL('H', r, g, b);
283 lpp->s = CC_RGBtoHSL('S', r, g, b);
284 lpp->l = CC_RGBtoHSL('L', r, g, b);
285 CC_EditSetHSL(hDlg, lpp->h, lpp->s, lpp->l);
286 CC_PaintCross(hDlg, lpp->h, lpp->s);
287 CC_PaintTriangle(hDlg, lpp->l);
288 break;
289
290 case 0x40e: /* Help! */ /* The Beatles, 1965 ;-) */
291 i = RegisterWindowMessageA(HELPMSGSTRINGA);
292 if (lpp->lpcc16)
293 {
294 if (lpp->lpcc->hwndOwner)
295 SendMessageA(lpp->lpcc->hwndOwner, i, 0, (LPARAM)lpp->lpcc16);
296 if ( CC_HookCallChk(lpp->lpcc))
297 CallWindowProc16( (WNDPROC16) lpp->lpcc16->lpfnHook,
298 HWND_16(hDlg), WM_COMMAND, psh15,
299 (LPARAM)lpp->lpcc16);
300 }
301 break;
302
303 case IDOK :
304 cokmsg = RegisterWindowMessageA(COLOROKSTRINGA);
305 if (lpp->lpcc16)
306 {
307 if (lpp->lpcc->hwndOwner)
308 if (SendMessageA(lpp->lpcc->hwndOwner, cokmsg, 0, (LPARAM)lpp->lpcc16))
309 break; /* do NOT close */
310 }
311 if (lpp->lpcc16)
312 {
313 BYTE *ptr = MapSL(lpp->lpcc16->lpCustColors);
314 memcpy(ptr, lpp->lpcc->lpCustColors, sizeof(COLORREF)*16);
315 lpp->lpcc16->rgbResult = lpp->lpcc->rgbResult;
316 }
317 EndDialog(hDlg, 1) ;
318 return TRUE ;
319
320 case IDCANCEL :
321 EndDialog(hDlg, 0) ;
322 return TRUE ;
323
324 }
325 return FALSE;
326 }
327
328 /***********************************************************************
329 * ColorDlgProc (COMMDLG.8)
330 */
331 BOOL16 CALLBACK ColorDlgProc16( HWND16 hDlg16, UINT16 message,
332 WPARAM16 wParam, LONG lParam )
333 {
334 BOOL16 res;
335 HWND hDlg = HWND_32(hDlg16);
336
337 LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER);
338 if (message != WM_INITDIALOG)
339 {
340 if (!lpp)
341 return FALSE;
342 res=0;
343 if (CC_HookCallChk(lpp->lpcc))
344 res = CallWindowProc16( (WNDPROC16)lpp->lpcc16->lpfnHook, hDlg16, message, wParam, lParam);
345 if (res)
346 return res;
347 }
348
349 /* FIXME: SetRGB message
350 if (message && message == msetrgb)
351 return HandleSetRGB(hDlg, lParam);
352 */
353
354 switch (message)
355 {
356 case WM_INITDIALOG:
357 return CC_WMInitDialog16(hDlg, wParam, lParam);
358 case WM_NCDESTROY:
359 DeleteDC(lpp->hdcMem);
360 DeleteObject(lpp->hbmMem);
361 HeapFree(GetProcessHeap(), 0, lpp->lpcc);
362 HeapFree(GetProcessHeap(), 0, lpp);
363 SetWindowLongPtrW(hDlg, DWLP_USER, 0); /* we don't need it anymore */
364 break;
365 case WM_COMMAND:
366 if (CC_WMCommand16(hDlg, wParam, lParam,
367 HIWORD(lParam), HWND_32(LOWORD(lParam))))
368 return TRUE;
369 break;
370 case WM_PAINT:
371 if (CC_WMPaint(hDlg, wParam, lParam))
372 return TRUE;
373 break;
374 case WM_LBUTTONDBLCLK:
375 if (CC_MouseCheckResultWindow(hDlg,lParam))
376 return TRUE;
377 break;
378 case WM_MOUSEMOVE:
379 if (CC_WMMouseMove(hDlg, lParam))
380 return TRUE;
381 break;
382 case WM_LBUTTONUP: /* FIXME: ClipCursor off (if in color graph)*/
383 if (CC_WMLButtonUp(hDlg, wParam, lParam))
384 return TRUE;
385 break;
386 case WM_LBUTTONDOWN:/* FIXME: ClipCursor on (if in color graph)*/
387 if (CC_WMLButtonDown(hDlg, wParam, lParam))
388 return TRUE;
389 break;
390 }
391 return FALSE ;
392 }
393
394 /***********************************************************************
395 * ChooseColor (COMMDLG.5)
396 */
397 BOOL16 WINAPI ChooseColor16( LPCHOOSECOLOR16 lpChCol )
398 {
399 HINSTANCE16 hInst;
400 HANDLE16 hDlgTmpl16 = 0, hResource16 = 0;
401 HGLOBAL16 hGlobal16 = 0;
402 BOOL16 bRet = FALSE;
403 LPCVOID template;
404 FARPROC16 ptr;
405
406 TRACE("ChooseColor\n");
407 if (!lpChCol) return FALSE;
408
409 if (lpChCol->Flags & CC_ENABLETEMPLATEHANDLE)
410 hDlgTmpl16 = lpChCol->hInstance;
411 else if (lpChCol->Flags & CC_ENABLETEMPLATE)
412 {
413 HANDLE16 hResInfo;
414 if (!(hResInfo = FindResource16(lpChCol->hInstance,
415 MapSL(lpChCol->lpTemplateName),
416 (LPSTR)RT_DIALOG)))
417 {
418 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
419 return FALSE;
420 }
421 if (!(hDlgTmpl16 = LoadResource16(lpChCol->hInstance, hResInfo)))
422 {
423 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
424 return FALSE;
425 }
426 hResource16 = hDlgTmpl16;
427 }
428 else
429 {
430 HRSRC hResInfo;
431 HGLOBAL hDlgTmpl32;
432 LPCVOID template32;
433 DWORD size;
434 if (!(hResInfo = FindResourceA(COMDLG32_hInstance, "CHOOSE_COLOR", (LPSTR)RT_DIALOG)))
435 {
436 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
437 return FALSE;
438 }
439 if (!(hDlgTmpl32 = LoadResource(COMDLG32_hInstance, hResInfo)) ||
440 !(template32 = LockResource(hDlgTmpl32)))
441 {
442 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
443 return FALSE;
444 }
445 size = SizeofResource(COMDLG32_hInstance, hResInfo);
446 hGlobal16 = GlobalAlloc16(0, size);
447 if (!hGlobal16)
448 {
449 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
450 ERR("alloc failure for %ld bytes\n", size);
451 return FALSE;
452 }
453 template = GlobalLock16(hGlobal16);
454 if (!template)
455 {
456 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
457 ERR("global lock failure for %x handle\n", hDlgTmpl16);
458 GlobalFree16(hGlobal16);
459 return FALSE;
460 }
461 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
462 hDlgTmpl16 = hGlobal16;
463 }
464
465 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 8);
466 hInst = GetWindowLongPtrA(HWND_32(lpChCol->hwndOwner), GWLP_HINSTANCE);
467 bRet = DialogBoxIndirectParam16(hInst, hDlgTmpl16, lpChCol->hwndOwner,
468 (DLGPROC16) ptr, (DWORD)lpChCol);
469 if (hResource16) FreeResource16(hDlgTmpl16);
470 if (hGlobal16)
471 {
472 GlobalUnlock16(hGlobal16);
473 GlobalFree16(hGlobal16);
474 }
475 return bRet;
476 }