Properly implement DllCanUnloadNow ref counting.
[wine] / dlls / commdlg / colordlg.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 "winuser.h"
35 #include "commdlg.h"
36 #include "dlgs.h"
37 #include "wine/debug.h"
38 #include "cderr.h"
39 #include "cdlg.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
42
43 static INT_PTR CALLBACK ColorDlgProc( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam );
44
45 #define CONV_LPARAMTOPOINT(lp,p) do { (p)->x = (short)LOWORD(lp); (p)->y = (short)HIWORD(lp); } while(0)
46
47 static const COLORREF predefcolors[6][8]=
48 {
49  { 0x008080FFL, 0x0080FFFFL, 0x0080FF80L, 0x0080FF00L,
50    0x00FFFF80L, 0x00FF8000L, 0x00C080FFL, 0x00FF80FFL },
51  { 0x000000FFL, 0x0000FFFFL, 0x0000FF80L, 0x0040FF00L,
52    0x00FFFF00L, 0x00C08000L, 0x00C08080L, 0x00FF00FFL },
53
54  { 0x00404080L, 0x004080FFL, 0x0000FF00L, 0x00808000L,
55    0x00804000L, 0x00FF8080L, 0x00400080L, 0x008000FFL },
56  { 0x00000080L, 0x000080FFL, 0x00008000L, 0x00408000L,
57    0x00FF0000L, 0x00A00000L, 0x00800080L, 0x00FF0080L },
58
59  { 0x00000040L, 0x00004080L, 0x00004000L, 0x00404000L,
60    0x00800000L, 0x00400000L, 0x00400040L, 0x00800040L },
61  { 0x00000000L, 0x00008080L, 0x00408080L, 0x00808080L,
62    0x00808040L, 0x00C0C0C0L, 0x00400040L, 0x00FFFFFFL },
63 };
64
65 /* Chose Color PRIVATE Structure:
66  *
67  * This structure is duplicated in the 16 bit code with
68  * a extra member
69  */
70
71 typedef struct CCPRIVATE
72 {
73     LPCHOOSECOLORW lpcc; /* points to public known data structure */
74     int nextuserdef;     /* next free place in user defined color array */
75     HDC hdcMem;          /* color graph used for BitBlt() */
76     HBITMAP hbmMem;      /* color graph bitmap */
77     RECT fullsize;       /* original dialog window size */
78     UINT msetrgb;        /* # of SETRGBSTRING message (today not used)  */
79     RECT old3angle;      /* last position of l-marker */
80     RECT oldcross;       /* last position of color/satuation marker */
81     BOOL updating;       /* to prevent recursive WM_COMMAND/EN_UPDATE processing */
82     int h;
83     int s;
84     int l;               /* for temporary storing of hue,sat,lum */
85     int capturedGraph;   /* control mouse captured */
86     RECT focusRect;      /* rectangle last focused item */
87     HWND hwndFocus;      /* handle last focused item */
88 } *LCCPRIV;
89
90 /***********************************************************************
91  *                             CC_HSLtoRGB                    [internal]
92  */
93 int CC_HSLtoRGB(char c, int hue, int sat, int lum)
94 {
95  int res = 0, maxrgb;
96
97  /* hue */
98  switch(c)
99  {
100   case 'R': if (hue > 80)  hue -= 80; else hue += 160; break;
101   case 'G': if (hue > 160) hue -= 160; else hue += 80; break;
102   case 'B': break;
103  }
104
105  /* l below 120 */
106  maxrgb = (256 * min(120,lum)) / 120;  /* 0 .. 256 */
107  if (hue < 80)
108   res = 0;
109  else
110   if (hue < 120)
111   {
112    res = (hue - 80) * maxrgb;           /* 0...10240 */
113    res /= 40;                        /* 0...256 */
114   }
115   else
116    if (hue < 200)
117     res = maxrgb;
118    else
119     {
120      res= (240 - hue) * maxrgb;
121      res /= 40;
122     }
123  res = res - maxrgb / 2;                 /* -128...128 */
124
125  /* saturation */
126  res = maxrgb / 2 + (sat * res) / 240;    /* 0..256 */
127
128  /* lum above 120 */
129  if (lum > 120 && res < 256)
130   res += ((lum - 120) * (256 - res)) / 120;
131
132  return min(res, 255);
133 }
134
135 /***********************************************************************
136  *                             CC_RGBtoHSL                    [internal]
137  */
138 int CC_RGBtoHSL(char c, int r, int g, int b)
139 {
140  WORD maxi, mini, mmsum, mmdif, result = 0;
141  int iresult = 0;
142
143  maxi = max(r, b);
144  maxi = max(maxi, g);
145  mini = min(r, b);
146  mini = min(mini, g);
147
148  mmsum = maxi + mini;
149  mmdif = maxi - mini;
150
151  switch(c)
152  {
153   /* lum */
154   case 'L': mmsum *= 120;              /* 0...61200=(255+255)*120 */
155            result = mmsum / 255;        /* 0...240 */
156            break;
157   /* saturation */
158   case 'S': if (!mmsum)
159             result = 0;
160            else
161             if (!mini || maxi == 255)
162              result = 240;
163            else
164            {
165             result = mmdif * 240;       /* 0...61200=255*240 */
166             result /= (mmsum > 255 ? mmsum = 510 - mmsum : mmsum); /* 0..255 */
167            }
168            break;
169   /* hue */
170   case 'H': if (!mmdif)
171             result = 160;
172            else
173            {
174             if (maxi == r)
175             {
176              iresult = 40 * (g - b);       /* -10200 ... 10200 */
177              iresult /= (int) mmdif;    /* -40 .. 40 */
178              if (iresult < 0)
179               iresult += 240;          /* 0..40 and 200..240 */
180             }
181             else
182              if (maxi == g)
183              {
184               iresult = 40 * (b - r);
185               iresult /= (int) mmdif;
186               iresult += 80;           /* 40 .. 120 */
187              }
188              else
189               if (maxi == b)
190               {
191                iresult = 40 * (r - g);
192                iresult /= (int) mmdif;
193                iresult += 160;         /* 120 .. 200 */
194               }
195             result = iresult;
196            }
197            break;
198  }
199  return result;    /* is this integer arithmetic precise enough ? */
200 }
201
202
203 /***********************************************************************
204  *                  CC_DrawCurrentFocusRect                       [internal]
205  */
206 void CC_DrawCurrentFocusRect( LCCPRIV lpp )
207 {
208   if (lpp->hwndFocus)
209   {
210     HDC hdc = GetDC(lpp->hwndFocus);
211     DrawFocusRect(hdc, &lpp->focusRect);
212     ReleaseDC(lpp->hwndFocus, hdc);
213   }
214 }
215
216 /***********************************************************************
217  *                  CC_DrawFocusRect                       [internal]
218  */
219 void CC_DrawFocusRect( LCCPRIV lpp, HWND hwnd, int x, int y, int rows, int cols)
220 {
221   RECT rect;
222   int dx, dy;
223   HDC hdc;
224
225   CC_DrawCurrentFocusRect(lpp); /* remove current focus rect */
226   /* calculate new rect */
227   GetClientRect(hwnd, &rect);
228   dx = (rect.right - rect.left) / cols;
229   dy = (rect.bottom - rect.top) / rows;
230   rect.left += (x * dx) - 2;
231   rect.top += (y * dy) - 2;
232   rect.right = rect.left + dx;
233   rect.bottom = rect.top + dy;
234   /* draw it */
235   hdc = GetDC(hwnd);
236   DrawFocusRect(hdc, &rect);
237   CopyRect(&lpp->focusRect, &rect);
238   lpp->hwndFocus = hwnd;
239   ReleaseDC(hwnd, hdc);
240 }
241
242 #define DISTANCE 4
243
244 /***********************************************************************
245  *                CC_MouseCheckPredefColorArray               [internal]
246  *                returns 1 if one of the predefined colors is clicked
247  */
248 static int CC_MouseCheckPredefColorArray( LCCPRIV lpp, HWND hDlg, int dlgitem, int rows, int cols,
249             LPARAM lParam )
250 {
251  HWND hwnd;
252  POINT point;
253  RECT rect;
254  int dx, dy, x, y;
255
256  CONV_LPARAMTOPOINT(lParam, &point);
257  ClientToScreen(hDlg, &point);
258  hwnd = GetDlgItem(hDlg, dlgitem);
259  GetWindowRect(hwnd, &rect);
260  if (PtInRect(&rect, point))
261  {
262   dx = (rect.right - rect.left) / cols;
263   dy = (rect.bottom - rect.top) / rows;
264   ScreenToClient(hwnd, &point);
265
266   if (point.x % dx < ( dx - DISTANCE) && point.y % dy < ( dy - DISTANCE))
267   {
268    x = point.x / dx;
269    y = point.y / dy;
270    lpp->lpcc->rgbResult = predefcolors[y][x];
271    CC_DrawFocusRect(lpp, hwnd, x, y, rows, cols);
272    return 1;
273   }
274  }
275  return 0;
276 }
277
278 /***********************************************************************
279  *                  CC_MouseCheckUserColorArray               [internal]
280  *                  return 1 if the user clicked a color
281  */
282 static int CC_MouseCheckUserColorArray( LCCPRIV lpp, HWND hDlg, int dlgitem, int rows, int cols,
283             LPARAM lParam )
284 {
285  HWND hwnd;
286  POINT point;
287  RECT rect;
288  int dx, dy, x, y;
289  COLORREF *crarr = lpp->lpcc->lpCustColors;
290
291  CONV_LPARAMTOPOINT(lParam, &point);
292  ClientToScreen(hDlg, &point);
293  hwnd = GetDlgItem(hDlg, dlgitem);
294  GetWindowRect(hwnd, &rect);
295  if (PtInRect(&rect, point))
296  {
297   dx = (rect.right - rect.left) / cols;
298   dy = (rect.bottom - rect.top) / rows;
299   ScreenToClient(hwnd, &point);
300
301   if (point.x % dx < (dx - DISTANCE) && point.y % dy < (dy - DISTANCE))
302   {
303    x = point.x / dx;
304    y = point.y / dy;
305    lpp->lpcc->rgbResult = crarr[x + (cols * y) ];
306    CC_DrawFocusRect(lpp, hwnd, x, y, rows, cols);
307    return 1;
308   }
309  }
310  return 0;
311 }
312
313 #define MAXVERT  240
314 #define MAXHORI  239
315
316 /*  240  ^......        ^^ 240
317          |     .        ||
318     SAT  |     .        || LUM
319          |     .        ||
320          +-----> 239   ----
321            HUE
322 */
323 /***********************************************************************
324  *                  CC_MouseCheckColorGraph                   [internal]
325  */
326 static int CC_MouseCheckColorGraph( HWND hDlg, int dlgitem, int *hori, int *vert, LPARAM lParam )
327 {
328  HWND hwnd;
329  POINT point;
330  RECT rect;
331  long x,y;
332
333  CONV_LPARAMTOPOINT(lParam, &point);
334  ClientToScreen(hDlg, &point);
335  hwnd = GetDlgItem( hDlg, dlgitem );
336  GetWindowRect(hwnd, &rect);
337  if (PtInRect(&rect, point))
338  {
339   GetClientRect(hwnd, &rect);
340   ScreenToClient(hwnd, &point);
341
342   x = (long) point.x * MAXHORI;
343   x /= rect.right;
344   y = (long) (rect.bottom - point.y) * MAXVERT;
345   y /= rect.bottom;
346
347   if (hori)
348    *hori = x;
349   if (vert)
350    *vert = y;
351   return 1;
352  }
353  else
354   return 0;
355 }
356 /***********************************************************************
357  *                  CC_MouseCheckResultWindow                 [internal]
358  *                  test if double click one of the result colors
359  */
360 int CC_MouseCheckResultWindow( HWND hDlg, LPARAM lParam )
361 {
362  HWND hwnd;
363  POINT point;
364  RECT rect;
365
366  CONV_LPARAMTOPOINT(lParam, &point);
367  ClientToScreen(hDlg, &point);
368  hwnd = GetDlgItem(hDlg, 0x2c5);
369  GetWindowRect(hwnd, &rect);
370  if (PtInRect(&rect, point))
371  {
372   PostMessageA(hDlg, WM_COMMAND, 0x2c9, 0);
373   return 1;
374  }
375  return 0;
376 }
377
378 /***********************************************************************
379  *                       CC_CheckDigitsInEdit                 [internal]
380  */
381 int CC_CheckDigitsInEdit( HWND hwnd, int maxval )
382 {
383  int i, k, m, result, value;
384  long editpos;
385  char buffer[30];
386
387  GetWindowTextA(hwnd, buffer, sizeof(buffer));
388  m = strlen(buffer);
389  result = 0;
390
391  for (i = 0 ; i < m ; i++)
392   if (buffer[i] < '0' || buffer[i] > '9')
393   {
394    for (k = i + 1; k <= m; k++)  /* delete bad character */
395    {
396     buffer[i] = buffer[k];
397     m--;
398    }
399    buffer[m] = 0;
400    result = 1;
401   }
402
403  value = atoi(buffer);
404  if (value > maxval)       /* build a new string */
405  {
406   sprintf(buffer, "%d", maxval);
407   result = 2;
408  }
409  if (result)
410  {
411   editpos = SendMessageA(hwnd, EM_GETSEL, 0, 0);
412   SetWindowTextA(hwnd, buffer );
413   SendMessageA(hwnd, EM_SETSEL, 0, editpos);
414  }
415  return value;
416 }
417
418
419
420 /***********************************************************************
421  *                    CC_PaintSelectedColor                   [internal]
422  */
423 void CC_PaintSelectedColor( HWND hDlg, COLORREF cr )
424 {
425  RECT rect;
426  HDC  hdc;
427  HBRUSH hBrush;
428  HWND hwnd = GetDlgItem(hDlg, 0x2c5);
429  if (IsWindowVisible( GetDlgItem(hDlg, 0x2c6) ))   /* if full size */
430  {
431   hdc = GetDC(hwnd);
432   GetClientRect(hwnd, &rect) ;
433   hBrush = CreateSolidBrush(cr);
434   if (hBrush)
435   {
436    hBrush = SelectObject(hdc, hBrush) ;
437    Rectangle(hdc, rect.left, rect.top, rect.right/2, rect.bottom);
438    DeleteObject ( SelectObject(hdc, hBrush) ) ;
439    hBrush = CreateSolidBrush( GetNearestColor(hdc, cr) );
440    if (hBrush)
441    {
442     hBrush = SelectObject(hdc, hBrush) ;
443     Rectangle(hdc, rect.right/2-1, rect.top, rect.right, rect.bottom);
444     DeleteObject(SelectObject(hdc, hBrush)) ;
445    }
446   }
447   ReleaseDC(hwnd, hdc);
448  }
449 }
450
451 /***********************************************************************
452  *                    CC_PaintTriangle                        [internal]
453  */
454 void CC_PaintTriangle( HWND hDlg, int y)
455 {
456  HDC hDC;
457  long temp;
458  int w = LOWORD(GetDialogBaseUnits());
459  POINT points[3];
460  int height;
461  int oben;
462  RECT rect;
463  HWND hwnd = GetDlgItem(hDlg, 0x2be);
464  LCCPRIV lpp = (LCCPRIV)GetWindowLongA( hDlg, DWL_USER);
465
466  if (IsWindowVisible( GetDlgItem(hDlg, 0x2c6)))   /* if full size */
467  {
468    GetClientRect(hwnd, &rect);
469    height = rect.bottom;
470    hDC = GetDC(hDlg);
471    points[0].y = rect.top;
472    points[0].x = rect.right;     /*  |  /|  */
473    ClientToScreen(hwnd, points); /*  | / |  */
474    ScreenToClient(hDlg, points); /*  |<  |  */
475    oben = points[0].y;           /*  | \ |  */
476                                  /*  |  \|  */
477    temp = (long)height * (long)y;
478    points[0].y = oben + height - temp / (long)MAXVERT;
479    points[1].y = points[0].y + w;
480    points[2].y = points[0].y - w;
481    points[2].x = points[1].x = points[0].x + w;
482
483    FillRect(hDC, &lpp->old3angle, (HBRUSH)GetClassLongA( hwnd, GCL_HBRBACKGROUND));
484    lpp->old3angle.left  = points[0].x;
485    lpp->old3angle.right = points[1].x + 1;
486    lpp->old3angle.top   = points[2].y - 1;
487    lpp->old3angle.bottom= points[1].y + 1;
488    Polygon(hDC, points, 3);
489    ReleaseDC(hDlg, hDC);
490  }
491 }
492
493
494 /***********************************************************************
495  *                    CC_PaintCross                           [internal]
496  */
497 void CC_PaintCross( HWND hDlg, int x, int y)
498 {
499  HDC hDC;
500  int w = GetDialogBaseUnits();
501  HWND hwnd = GetDlgItem(hDlg, 0x2c6);
502  LCCPRIV lpp = (LCCPRIV)GetWindowLongA( hDlg, DWL_USER );
503  RECT rect;
504  POINT point, p;
505  HPEN hPen;
506
507  if (IsWindowVisible( GetDlgItem(hDlg, 0x2c6) ))   /* if full size */
508  {
509    GetClientRect(hwnd, &rect);
510    hDC = GetDC(hwnd);
511    SelectClipRgn( hDC, CreateRectRgnIndirect(&rect));
512    hPen = CreatePen(PS_SOLID, 2, 0xffffff); /* -white- color */
513    hPen = SelectObject(hDC, hPen);
514    point.x = ((long)rect.right * (long)x) / (long)MAXHORI;
515    point.y = rect.bottom - ((long)rect.bottom * (long)y) / (long)MAXVERT;
516    if ( lpp->oldcross.left != lpp->oldcross.right )
517      BitBlt(hDC, lpp->oldcross.left, lpp->oldcross.top,
518               lpp->oldcross.right - lpp->oldcross.left,
519               lpp->oldcross.bottom - lpp->oldcross.top,
520               lpp->hdcMem, lpp->oldcross.left, lpp->oldcross.top, SRCCOPY);
521    lpp->oldcross.left   = point.x - w - 1;
522    lpp->oldcross.right  = point.x + w + 1;
523    lpp->oldcross.top    = point.y - w - 1;
524    lpp->oldcross.bottom = point.y + w + 1;
525
526    MoveToEx(hDC, point.x - w, point.y, &p);
527    LineTo(hDC, point.x + w, point.y);
528    MoveToEx(hDC, point.x, point.y - w, &p);
529    LineTo(hDC, point.x, point.y + w);
530    DeleteObject( SelectObject(hDC, hPen)) ;
531    ReleaseDC(hwnd, hDC);
532  }
533 }
534
535
536 #define XSTEPS 48
537 #define YSTEPS 24
538
539
540 /***********************************************************************
541  *                    CC_PrepareColorGraph                    [internal]
542  */
543 static void CC_PrepareColorGraph( HWND hDlg )
544 {
545  int sdif, hdif, xdif, ydif, r, g, b, hue, sat;
546  HWND hwnd = GetDlgItem(hDlg, 0x2c6);
547  LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
548  HBRUSH hbrush;
549  HDC hdc ;
550  RECT rect, client;
551  HCURSOR hcursor = SetCursor( LoadCursorA(0, (LPSTR)IDC_WAIT) );
552
553  GetClientRect(hwnd, &client);
554  hdc = GetDC(hwnd);
555  lpp->hdcMem = CreateCompatibleDC(hdc);
556  lpp->hbmMem = CreateCompatibleBitmap(hdc, client.right, client.bottom);
557  SelectObject(lpp->hdcMem, lpp->hbmMem);
558
559  xdif = client.right / XSTEPS;
560  ydif = client.bottom / YSTEPS+1;
561  hdif = 239 / XSTEPS;
562  sdif = 240 / YSTEPS;
563  for (rect.left = hue = 0; hue < 239 + hdif; hue += hdif)
564  {
565   rect.right = rect.left + xdif;
566   rect.bottom = client.bottom;
567   for(sat = 0; sat < 240 + sdif; sat += sdif)
568   {
569    rect.top = rect.bottom - ydif;
570    r = CC_HSLtoRGB('R', hue, sat, 120);
571    g = CC_HSLtoRGB('G', hue, sat, 120);
572    b = CC_HSLtoRGB('B', hue, sat, 120);
573    hbrush = CreateSolidBrush( RGB(r, g, b));
574    FillRect(lpp->hdcMem, &rect, hbrush);
575    DeleteObject(hbrush);
576    rect.bottom = rect.top;
577   }
578   rect.left = rect.right;
579  }
580  ReleaseDC(hwnd, hdc);
581  SetCursor(hcursor);
582 }
583
584 /***********************************************************************
585  *                          CC_PaintColorGraph                [internal]
586  */
587 static void CC_PaintColorGraph( HWND hDlg )
588 {
589  HWND hwnd = GetDlgItem( hDlg, 0x2c6 );
590  LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
591  HDC  hDC;
592  RECT rect;
593  if (IsWindowVisible(hwnd))   /* if full size */
594  {
595   if (!lpp->hdcMem)
596    CC_PrepareColorGraph(hDlg);   /* should not be necessary */
597
598   hDC = GetDC(hwnd);
599   GetClientRect(hwnd, &rect);
600   if (lpp->hdcMem)
601       BitBlt(hDC, 0, 0, rect.right, rect.bottom, lpp->hdcMem, 0, 0, SRCCOPY);
602   else
603       WARN("choose color: hdcMem is not defined\n");
604   ReleaseDC(hwnd, hDC);
605  }
606 }
607
608 /***********************************************************************
609  *                           CC_PaintLumBar                   [internal]
610  */
611 static void CC_PaintLumBar( HWND hDlg, int hue, int sat )
612 {
613  HWND hwnd = GetDlgItem(hDlg, 0x2be);
614  RECT rect, client;
615  int lum, ldif, ydif, r, g, b;
616  HBRUSH hbrush;
617  HDC hDC;
618
619  if (IsWindowVisible(hwnd))
620  {
621   hDC = GetDC(hwnd);
622   GetClientRect(hwnd, &client);
623   rect = client;
624
625   ldif = 240 / YSTEPS;
626   ydif = client.bottom / YSTEPS+1;
627   for (lum = 0; lum < 240 + ldif; lum += ldif)
628   {
629    rect.top = max(0, rect.bottom - ydif);
630    r = CC_HSLtoRGB('R', hue, sat, lum);
631    g = CC_HSLtoRGB('G', hue, sat, lum);
632    b = CC_HSLtoRGB('B', hue, sat, lum);
633    hbrush = CreateSolidBrush( RGB(r, g, b) );
634    FillRect(hDC, &rect, hbrush);
635    DeleteObject(hbrush);
636    rect.bottom = rect.top;
637   }
638   GetClientRect(hwnd, &rect);
639   FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH) );
640   ReleaseDC(hwnd, hDC);
641  }
642 }
643
644 /***********************************************************************
645  *                             CC_EditSetRGB                  [internal]
646  */
647 void CC_EditSetRGB( HWND hDlg, COLORREF cr )
648 {
649  char buffer[10];
650  LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
651  int r = GetRValue(cr);
652  int g = GetGValue(cr);
653  int b = GetBValue(cr);
654  if (IsWindowVisible( GetDlgItem(hDlg, 0x2c6) ))   /* if full size */
655  {
656    lpp->updating = TRUE;
657    sprintf(buffer, "%d", r);
658    SetWindowTextA( GetDlgItem(hDlg, 0x2c2), buffer);
659    sprintf(buffer, "%d", g);
660    SetWindowTextA( GetDlgItem(hDlg, 0x2c3), buffer);
661    sprintf( buffer, "%d", b );
662    SetWindowTextA( GetDlgItem(hDlg, 0x2c4),buffer);
663    lpp->updating = FALSE;
664  }
665 }
666
667 /***********************************************************************
668  *                             CC_EditSetHSL                  [internal]
669  */
670 void CC_EditSetHSL( HWND hDlg, int h, int s, int l )
671 {
672  char buffer[10];
673  LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
674  lpp->updating = TRUE;
675  if (IsWindowVisible( GetDlgItem(hDlg, 0x2c6) ))   /* if full size */
676  {
677    lpp->updating = TRUE;
678    sprintf(buffer, "%d", h);
679    SetWindowTextA( GetDlgItem(hDlg, 0x2bf), buffer);
680    sprintf(buffer, "%d", s);
681    SetWindowTextA( GetDlgItem(hDlg, 0x2c0), buffer);
682    sprintf(buffer, "%d", l);
683    SetWindowTextA( GetDlgItem(hDlg, 0x2c1), buffer);
684    lpp->updating = FALSE;
685  }
686  CC_PaintLumBar(hDlg, h, s);
687 }
688
689 /***********************************************************************
690  *                       CC_SwitchToFullSize                  [internal]
691  */
692 void CC_SwitchToFullSize( HWND hDlg, COLORREF result, LPRECT lprect )
693 {
694  int i;
695  LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
696
697  EnableWindow( GetDlgItem(hDlg, 0x2cf), FALSE);
698  CC_PrepareColorGraph(hDlg);
699  for (i = 0x2bf; i < 0x2c5; i++)
700    ShowWindow( GetDlgItem(hDlg, i), SW_SHOW);
701  for (i = 0x2d3; i < 0x2d9; i++)
702    ShowWindow( GetDlgItem(hDlg, i), SW_SHOW);
703  ShowWindow( GetDlgItem(hDlg, 0x2c9), SW_SHOW);
704  ShowWindow( GetDlgItem(hDlg, 0x2c8), SW_SHOW);
705  ShowWindow( GetDlgItem(hDlg, 1090), SW_SHOW);
706
707  if (lprect)
708   SetWindowPos(hDlg, 0, 0, 0, lprect->right-lprect->left,
709    lprect->bottom-lprect->top, SWP_NOMOVE|SWP_NOZORDER);
710
711  ShowWindow( GetDlgItem(hDlg, 0x2be), SW_SHOW);
712  ShowWindow( GetDlgItem(hDlg, 0x2c5), SW_SHOW);
713
714  CC_EditSetRGB(hDlg, result);
715  CC_EditSetHSL(hDlg, lpp->h, lpp->s, lpp->l);
716  ShowWindow( GetDlgItem( hDlg, 0x2c6), SW_SHOW);
717  UpdateWindow( GetDlgItem(hDlg, 0x2c6) );
718 }
719
720 /***********************************************************************
721  *                           CC_PaintPredefColorArray         [internal]
722  *                Paints the default standard 48 colors
723  */
724 static void CC_PaintPredefColorArray( HWND hDlg, int rows, int cols)
725 {
726  HWND hwnd = GetDlgItem(hDlg, 0x2d0);
727  RECT rect;
728  HDC  hdc;
729  HBRUSH hBrush;
730  int dx, dy, i, j, k;
731  LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
732
733  GetClientRect(hwnd, &rect);
734  dx = rect.right / cols;
735  dy = rect.bottom / rows;
736  k = rect.left;
737
738  hdc = GetDC(hwnd);
739  GetClientRect(hwnd, &rect);
740  FillRect(hdc, &rect, (HBRUSH)GetClassLongA(hwnd, GCL_HBRBACKGROUND));
741  for ( j = 0; j < rows; j++ )
742  {
743   for ( i = 0; i < cols; i++ )
744   {
745    hBrush = CreateSolidBrush(predefcolors[j][i]);
746    if (hBrush)
747    {
748     hBrush = SelectObject(hdc, hBrush);
749     Rectangle(hdc, rect.left, rect.top,
750                 rect.left + dx - DISTANCE, rect.top + dy - DISTANCE);
751     rect.left = rect.left + dx;
752     DeleteObject(SelectObject(hdc, hBrush)) ;
753    }
754   }
755   rect.top = rect.top + dy;
756   rect.left = k;
757  }
758  ReleaseDC(hwnd, hdc);
759  if (lpp->hwndFocus == hwnd)
760    CC_DrawCurrentFocusRect(lpp);
761 }
762 /***********************************************************************
763  *                             CC_PaintUserColorArray         [internal]
764  *               Paint the 16 user-selected colors
765  */
766 void CC_PaintUserColorArray( HWND hDlg, int rows, int cols, COLORREF* lpcr )
767 {
768  HWND hwnd = GetDlgItem(hDlg, 0x2d1);
769  RECT rect;
770  HDC  hdc;
771  HBRUSH hBrush;
772  int dx, dy, i, j, k;
773  LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
774
775  GetClientRect(hwnd, &rect);
776
777  dx = rect.right / cols;
778  dy = rect.bottom / rows;
779  k = rect.left;
780
781  hdc = GetDC(hwnd);
782  if (hdc)
783  {
784   FillRect(hdc, &rect, (HBRUSH)GetClassLongA(hwnd, GCL_HBRBACKGROUND) );
785   for (j = 0; j < rows; j++)
786   {
787    for (i = 0; i < cols; i++)
788    {
789     hBrush = CreateSolidBrush(lpcr[i+j*cols]);
790     if (hBrush)
791     {
792      hBrush = SelectObject(hdc, hBrush) ;
793      Rectangle(hdc, rect.left, rect.top,
794                   rect.left + dx - DISTANCE, rect.top + dy - DISTANCE);
795      rect.left = rect.left + dx;
796      DeleteObject( SelectObject(hdc, hBrush) ) ;
797     }
798    }
799    rect.top = rect.top + dy;
800    rect.left = k;
801   }
802   ReleaseDC(hwnd, hdc);
803  }
804  if (lpp->hwndFocus == hwnd)
805    CC_DrawCurrentFocusRect(lpp);
806 }
807
808
809
810 /***********************************************************************
811  *                             CC_HookCallChk                 [internal]
812  */
813 BOOL CC_HookCallChk( LPCHOOSECOLORW lpcc )
814 {
815  if (lpcc)
816   if(lpcc->Flags & CC_ENABLEHOOK)
817    if (lpcc->lpfnHook)
818     return TRUE;
819  return FALSE;
820 }
821
822 /***********************************************************************
823  *                              CC_WMInitDialog                  [internal]
824  */
825 LONG CC_WMInitDialog( HWND hDlg, WPARAM wParam, LPARAM lParam )
826 {
827    int i, res;
828    int r, g, b;
829    HWND hwnd;
830    RECT rect;
831    POINT point;
832    LCCPRIV lpp;
833
834    TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
835    lpp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct CCPRIVATE) );
836
837    lpp->lpcc = (LPCHOOSECOLORW) lParam;
838    if (lpp->lpcc->lStructSize != sizeof(CHOOSECOLORW) )
839    {
840        HeapFree(GetProcessHeap(), 0, lpp);
841        EndDialog (hDlg, 0) ;
842        return FALSE;
843    }
844
845    SetWindowLongA(hDlg, DWL_USER, (LONG)lpp);
846
847    if (!(lpp->lpcc->Flags & CC_SHOWHELP))
848       ShowWindow( GetDlgItem(hDlg,0x40e), SW_HIDE);
849    lpp->msetrgb = RegisterWindowMessageA(SETRGBSTRINGA);
850
851 #if 0
852    cpos = MAKELONG(5,7); /* init */
853    if (lpp->lpcc->Flags & CC_RGBINIT)
854    {
855      for (i = 0; i < 6; i++)
856        for (j = 0; j < 8; j++)
857         if (predefcolors[i][j] == lpp->lpcc->rgbResult)
858         {
859           cpos = MAKELONG(i,j);
860           goto found;
861         }
862    }
863    found:
864    /* FIXME: Draw_a_focus_rect & set_init_values */
865 #endif
866
867    GetWindowRect(hDlg, &lpp->fullsize);
868    if (lpp->lpcc->Flags & CC_FULLOPEN || lpp->lpcc->Flags & CC_PREVENTFULLOPEN)
869    {
870       hwnd = GetDlgItem(hDlg, 0x2cf);
871       EnableWindow(hwnd, FALSE);
872    }
873    if (!(lpp->lpcc->Flags & CC_FULLOPEN ) || lpp->lpcc->Flags & CC_PREVENTFULLOPEN)
874    {
875       rect = lpp->fullsize;
876       res = rect.bottom - rect.top;
877       hwnd = GetDlgItem(hDlg, 0x2c6); /* cut at left border */
878       point.x = point.y = 0;
879       ClientToScreen(hwnd, &point);
880       ScreenToClient(hDlg,&point);
881       GetClientRect(hDlg, &rect);
882       point.x += GetSystemMetrics(SM_CXDLGFRAME);
883       SetWindowPos(hDlg, 0, 0, 0, point.x, res, SWP_NOMOVE|SWP_NOZORDER);
884
885       for (i = 0x2bf; i < 0x2c5; i++)
886          ShowWindow( GetDlgItem(hDlg, i), SW_HIDE);
887       for (i = 0x2d3; i < 0x2d9; i++)
888          ShowWindow( GetDlgItem(hDlg, i), SW_HIDE);
889       ShowWindow( GetDlgItem(hDlg, 0x2c9), SW_HIDE);
890       ShowWindow( GetDlgItem(hDlg, 0x2c8), SW_HIDE);
891       ShowWindow( GetDlgItem(hDlg, 0x2c6), SW_HIDE);
892       ShowWindow( GetDlgItem(hDlg, 0x2c5), SW_HIDE);
893       ShowWindow( GetDlgItem(hDlg, 1090 ), SW_HIDE);
894    }
895    else
896       CC_SwitchToFullSize(hDlg, lpp->lpcc->rgbResult, NULL);
897    res = TRUE;
898    for (i = 0x2bf; i < 0x2c5; i++)
899      SendMessageA( GetDlgItem(hDlg, i), EM_LIMITTEXT, 3, 0);  /* max 3 digits:  xyz  */
900    if (CC_HookCallChk(lpp->lpcc))
901    {
902           res = CallWindowProcA( (WNDPROC)lpp->lpcc->lpfnHook, hDlg, WM_INITDIALOG, wParam, lParam);
903    }
904
905    /* Set the initial values of the color chooser dialog */
906    r = GetRValue(lpp->lpcc->rgbResult);
907    g = GetGValue(lpp->lpcc->rgbResult);
908    b = GetBValue(lpp->lpcc->rgbResult);
909
910    CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
911    lpp->h = CC_RGBtoHSL('H', r, g, b);
912    lpp->s = CC_RGBtoHSL('S', r, g, b);
913    lpp->l = CC_RGBtoHSL('L', r, g, b);
914
915    /* Doing it the long way because CC_EditSetRGB/HSL doesn't seem to work */
916    SetDlgItemInt(hDlg, 703, lpp->h, TRUE);
917    SetDlgItemInt(hDlg, 704, lpp->s, TRUE);
918    SetDlgItemInt(hDlg, 705, lpp->l, TRUE);
919    SetDlgItemInt(hDlg, 706, r, TRUE);
920    SetDlgItemInt(hDlg, 707, g, TRUE);
921    SetDlgItemInt(hDlg, 708, b, TRUE);
922
923    CC_PaintCross(hDlg, lpp->h, lpp->s);
924    CC_PaintTriangle(hDlg, lpp->l);
925
926    return res;
927 }
928
929
930 /***********************************************************************
931  *                              CC_WMCommand                  [internal]
932  */
933 LRESULT CC_WMCommand( HWND hDlg, WPARAM wParam, LPARAM lParam, WORD notifyCode, HWND hwndCtl )
934 {
935     int  r, g, b, i, xx;
936     UINT cokmsg;
937     HDC hdc;
938     COLORREF *cr;
939     LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
940     TRACE("CC_WMCommand wParam=%x lParam=%lx\n", wParam, lParam);
941     switch (wParam)
942     {
943           case 0x2c2:  /* edit notify RGB */
944           case 0x2c3:
945           case 0x2c4:
946                if (notifyCode == EN_UPDATE && !lpp->updating)
947                          {
948                            i = CC_CheckDigitsInEdit(hwndCtl, 255);
949                            r = GetRValue(lpp->lpcc->rgbResult);
950                            g = GetGValue(lpp->lpcc->rgbResult);
951                            b= GetBValue(lpp->lpcc->rgbResult);
952                            xx = 0;
953                            switch (wParam)
954                            {
955                             case 0x2c2: if ((xx = (i != r))) r = i; break;
956                             case 0x2c3: if ((xx = (i != g))) g = i; break;
957                             case 0x2c4: if ((xx = (i != b))) b = i; break;
958                            }
959                            if (xx) /* something has changed */
960                            {
961                             lpp->lpcc->rgbResult = RGB(r, g, b);
962                             CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
963                             lpp->h = CC_RGBtoHSL('H', r, g, b);
964                             lpp->s = CC_RGBtoHSL('S', r, g, b);
965                             lpp->l = CC_RGBtoHSL('L', r, g, b);
966                             CC_EditSetHSL(hDlg, lpp->h, lpp->s, lpp->l);
967                             CC_PaintCross(hDlg, lpp->h, lpp->s);
968                             CC_PaintTriangle(hDlg, lpp->l);
969                            }
970                          }
971                  break;
972
973           case 0x2bf:  /* edit notify HSL */
974           case 0x2c0:
975           case 0x2c1:
976                if (notifyCode == EN_UPDATE && !lpp->updating)
977                          {
978                            i = CC_CheckDigitsInEdit(hwndCtl , wParam == 0x2bf ? 239:240);
979                            xx = 0;
980                            switch (wParam)
981                            {
982                             case 0x2bf: if ((xx = ( i != lpp->h))) lpp->h = i; break;
983                             case 0x2c0: if ((xx = ( i != lpp->s))) lpp->s = i; break;
984                             case 0x2c1: if ((xx = ( i != lpp->l))) lpp->l = i; break;
985                            }
986                            if (xx) /* something has changed */
987                            {
988                             r = CC_HSLtoRGB('R', lpp->h, lpp->s, lpp->l);
989                             g = CC_HSLtoRGB('G', lpp->h, lpp->s, lpp->l);
990                             b = CC_HSLtoRGB('B', lpp->h, lpp->s, lpp->l);
991                             lpp->lpcc->rgbResult = RGB(r, g, b);
992                             CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
993                             CC_EditSetRGB(hDlg, lpp->lpcc->rgbResult);
994                             CC_PaintCross(hDlg, lpp->h, lpp->s);
995                             CC_PaintTriangle(hDlg, lpp->l);
996                            }
997                          }
998                break;
999
1000           case 0x2cf:
1001                CC_SwitchToFullSize(hDlg, lpp->lpcc->rgbResult, &lpp->fullsize);
1002                SetFocus( GetDlgItem(hDlg, 0x2bf));
1003                break;
1004
1005           case 0x2c8:    /* add colors ... column by column */
1006                cr = lpp->lpcc->lpCustColors;
1007                cr[(lpp->nextuserdef % 2) * 8 + lpp->nextuserdef / 2] = lpp->lpcc->rgbResult;
1008                if (++lpp->nextuserdef == 16)
1009                    lpp->nextuserdef = 0;
1010                CC_PaintUserColorArray(hDlg, 2, 8, lpp->lpcc->lpCustColors);
1011                break;
1012
1013           case 0x2c9:              /* resulting color */
1014                hdc = GetDC(hDlg);
1015                lpp->lpcc->rgbResult = GetNearestColor(hdc, lpp->lpcc->rgbResult);
1016                ReleaseDC(hDlg, hdc);
1017                CC_EditSetRGB(hDlg, lpp->lpcc->rgbResult);
1018                CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
1019                r = GetRValue(lpp->lpcc->rgbResult);
1020                g = GetGValue(lpp->lpcc->rgbResult);
1021                b = GetBValue(lpp->lpcc->rgbResult);
1022                lpp->h = CC_RGBtoHSL('H', r, g, b);
1023                lpp->s = CC_RGBtoHSL('S', r, g, b);
1024                lpp->l = CC_RGBtoHSL('L', r, g, b);
1025                CC_EditSetHSL(hDlg, lpp->h, lpp->s, lpp->l);
1026                CC_PaintCross(hDlg, lpp->h, lpp->s);
1027                CC_PaintTriangle(hDlg, lpp->l);
1028                break;
1029
1030           case 0x40e:           /* Help! */ /* The Beatles, 1965  ;-) */
1031                i = RegisterWindowMessageA(HELPMSGSTRINGA);
1032                    if (lpp->lpcc->hwndOwner)
1033                        SendMessageA(lpp->lpcc->hwndOwner, i, 0, (LPARAM)lpp->lpcc);
1034                    if ( CC_HookCallChk(lpp->lpcc))
1035                        CallWindowProcA( (WNDPROC) lpp->lpcc->lpfnHook, hDlg,
1036                           WM_COMMAND, psh15, (LPARAM)lpp->lpcc);
1037                break;
1038
1039           case IDOK :
1040                 cokmsg = RegisterWindowMessageA(COLOROKSTRINGA);
1041                     if (lpp->lpcc->hwndOwner)
1042                         if (SendMessageA(lpp->lpcc->hwndOwner, cokmsg, 0, (LPARAM)lpp->lpcc))
1043                         break;    /* do NOT close */
1044                 EndDialog(hDlg, 1) ;
1045                 return TRUE ;
1046
1047           case IDCANCEL :
1048                 EndDialog(hDlg, 0) ;
1049                 return TRUE ;
1050
1051        }
1052        return FALSE;
1053 }
1054
1055 /***********************************************************************
1056  *                              CC_WMPaint                    [internal]
1057  */
1058 LRESULT CC_WMPaint( HWND hDlg, WPARAM wParam, LPARAM lParam )
1059 {
1060     HDC hdc;
1061     PAINTSTRUCT ps;
1062     LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
1063
1064     hdc = BeginPaint(hDlg, &ps);
1065     /* we have to paint dialog children except text and buttons */
1066     CC_PaintPredefColorArray(hDlg, 6, 8);
1067     CC_PaintUserColorArray(hDlg, 2, 8, lpp->lpcc->lpCustColors);
1068     CC_PaintLumBar(hDlg, lpp->h, lpp->s);
1069     CC_PaintCross(hDlg, lpp->h, lpp->s);
1070     CC_PaintTriangle(hDlg, lpp->l);
1071     CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
1072     CC_PaintColorGraph(hDlg);
1073     EndPaint(hDlg, &ps);
1074
1075  return TRUE;
1076 }
1077
1078 /***********************************************************************
1079  *                              CC_WMLButtonUp              [internal]
1080  */
1081 LRESULT CC_WMLButtonUp( HWND hDlg, WPARAM wParam, LPARAM lParam )
1082 {
1083    LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
1084    if (lpp->capturedGraph)
1085    {
1086        lpp->capturedGraph = 0;
1087        ReleaseCapture();
1088        CC_PaintCross(hDlg, lpp->h, lpp->s);
1089        return 1;
1090    }
1091    return 0;
1092 }
1093
1094 /***********************************************************************
1095  *                              CC_WMMouseMove              [internal]
1096  */
1097 LRESULT CC_WMMouseMove( HWND hDlg, LPARAM lParam )
1098 {
1099    LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
1100    int r, g, b;
1101
1102    if (lpp->capturedGraph)
1103    {
1104       int *ptrh = NULL, *ptrs = &lpp->l;
1105       if (lpp->capturedGraph == 0x2c6)
1106       {
1107           ptrh = &lpp->h;
1108           ptrs = &lpp->s;
1109       }
1110       if (CC_MouseCheckColorGraph( hDlg, lpp->capturedGraph, ptrh, ptrs, lParam))
1111       {
1112           r = CC_HSLtoRGB('R', lpp->h, lpp->s, lpp->l);
1113           g = CC_HSLtoRGB('G', lpp->h, lpp->s, lpp->l);
1114           b = CC_HSLtoRGB('B', lpp->h, lpp->s, lpp->l);
1115           lpp->lpcc->rgbResult = RGB(r, g, b);
1116           CC_EditSetRGB(hDlg, lpp->lpcc->rgbResult);
1117           CC_EditSetHSL(hDlg,lpp->h, lpp->s, lpp->l);
1118           CC_PaintCross(hDlg, lpp->h, lpp->s);
1119           CC_PaintTriangle(hDlg, lpp->l);
1120           CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
1121       }
1122       else
1123       {
1124           ReleaseCapture();
1125           lpp->capturedGraph = 0;
1126       }
1127       return 1;
1128    }
1129    return 0;
1130 }
1131
1132 /***********************************************************************
1133  *                              CC_WMLButtonDown              [internal]
1134  */
1135 LRESULT CC_WMLButtonDown( HWND hDlg, WPARAM wParam, LPARAM lParam )
1136 {
1137    LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
1138    int r, g, b, i;
1139    i = 0;
1140
1141    if (CC_MouseCheckPredefColorArray(lpp, hDlg, 0x2d0, 6, 8, lParam))
1142       i = 1;
1143    else
1144       if (CC_MouseCheckUserColorArray(lpp, hDlg, 0x2d1, 2, 8, lParam))
1145          i = 1;
1146       else
1147          if (CC_MouseCheckColorGraph(hDlg, 0x2c6, &lpp->h, &lpp->s, lParam))
1148          {
1149             i = 2;
1150             lpp->capturedGraph = 0x2c6;
1151          }
1152          else
1153             if (CC_MouseCheckColorGraph(hDlg, 0x2be, NULL, &lpp->l, lParam))
1154             {
1155                i = 2;
1156                lpp->capturedGraph = 0x2be;
1157             }
1158    if ( i == 2 )
1159    {
1160       SetCapture(hDlg);
1161       r = CC_HSLtoRGB('R', lpp->h, lpp->s, lpp->l);
1162       g = CC_HSLtoRGB('G', lpp->h, lpp->s, lpp->l);
1163       b = CC_HSLtoRGB('B', lpp->h, lpp->s, lpp->l);
1164       lpp->lpcc->rgbResult = RGB(r, g, b);
1165    }
1166    if ( i == 1 )
1167    {
1168       r = GetRValue(lpp->lpcc->rgbResult);
1169       g = GetGValue(lpp->lpcc->rgbResult);
1170       b = GetBValue(lpp->lpcc->rgbResult);
1171       lpp->h = CC_RGBtoHSL('H', r, g, b);
1172       lpp->s = CC_RGBtoHSL('S', r, g, b);
1173       lpp->l = CC_RGBtoHSL('L', r, g, b);
1174    }
1175    if (i)
1176    {
1177       CC_EditSetRGB(hDlg, lpp->lpcc->rgbResult);
1178       CC_EditSetHSL(hDlg,lpp->h, lpp->s, lpp->l);
1179       CC_PaintCross(hDlg, lpp->h, lpp->s);
1180       CC_PaintTriangle(hDlg, lpp->l);
1181       CC_PaintSelectedColor(hDlg, lpp->lpcc->rgbResult);
1182       return TRUE;
1183    }
1184    return FALSE;
1185 }
1186
1187 /***********************************************************************
1188  *           ColorDlgProc32 [internal]
1189  *
1190  */
1191 static INT_PTR CALLBACK ColorDlgProc( HWND hDlg, UINT message,
1192                                    WPARAM wParam, LPARAM lParam )
1193 {
1194
1195  int res;
1196  LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER);
1197  if (message != WM_INITDIALOG)
1198  {
1199   if (!lpp)
1200      return FALSE;
1201   res = 0;
1202   if (CC_HookCallChk(lpp->lpcc))
1203      res = CallWindowProcA( (WNDPROC)lpp->lpcc->lpfnHook, hDlg, message, wParam, lParam);
1204   if ( res )
1205      return res;
1206  }
1207
1208  /* FIXME: SetRGB message
1209  if (message && message == msetrgb)
1210     return HandleSetRGB(hDlg, lParam);
1211  */
1212
1213  switch (message)
1214         {
1215           case WM_INITDIALOG:
1216                         return CC_WMInitDialog(hDlg, wParam, lParam);
1217           case WM_NCDESTROY:
1218                         DeleteDC(lpp->hdcMem);
1219                         DeleteObject(lpp->hbmMem);
1220                         HeapFree(GetProcessHeap(), 0, lpp);
1221                         SetWindowLongA(hDlg, DWL_USER, 0L); /* we don't need it anymore */
1222                         break;
1223           case WM_COMMAND:
1224                         if (CC_WMCommand( hDlg, wParam, lParam, HIWORD(wParam), (HWND) lParam))
1225                            return TRUE;
1226                         break;
1227           case WM_PAINT:
1228                         if ( CC_WMPaint(hDlg, wParam, lParam))
1229                            return TRUE;
1230                         break;
1231           case WM_LBUTTONDBLCLK:
1232                         if (CC_MouseCheckResultWindow(hDlg, lParam))
1233                           return TRUE;
1234                         break;
1235           case WM_MOUSEMOVE:
1236                         if (CC_WMMouseMove(hDlg, lParam))
1237                           return TRUE;
1238                         break;
1239           case WM_LBUTTONUP:  /* FIXME: ClipCursor off (if in color graph)*/
1240                         if (CC_WMLButtonUp(hDlg, wParam, lParam))
1241                            return TRUE;
1242                         break;
1243           case WM_LBUTTONDOWN:/* FIXME: ClipCursor on  (if in color graph)*/
1244                         if (CC_WMLButtonDown(hDlg, wParam, lParam))
1245                            return TRUE;
1246                         break;
1247         }
1248      return FALSE ;
1249 }
1250
1251 /***********************************************************************
1252  *            ChooseColorW  (COMDLG32.@)
1253  */
1254 BOOL WINAPI ChooseColorW( LPCHOOSECOLORW lpChCol )
1255 {
1256     HANDLE hDlgTmpl = 0;
1257     BOOL bRet = FALSE;
1258     LPCVOID template;
1259
1260     TRACE("ChooseColor\n");
1261     if (!lpChCol) return FALSE;
1262
1263     if (lpChCol->Flags & CC_ENABLETEMPLATEHANDLE)
1264     {
1265         if (!(template = LockResource(lpChCol->hInstance)))
1266         {
1267             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1268             return FALSE;
1269         }
1270     }
1271     else if (lpChCol->Flags & CC_ENABLETEMPLATE)
1272     {
1273         HRSRC hResInfo;
1274         if (!(hResInfo = FindResourceW((HINSTANCE)lpChCol->hInstance,
1275                                         lpChCol->lpTemplateName,
1276                                         (LPWSTR)RT_DIALOG)))
1277         {
1278             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
1279             return FALSE;
1280         }
1281         if (!(hDlgTmpl = LoadResource((HINSTANCE)lpChCol->hInstance, hResInfo)) ||
1282             !(template = LockResource(hDlgTmpl)))
1283         {
1284             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1285             return FALSE;
1286         }
1287     }
1288     else
1289     {
1290         HRSRC hResInfo;
1291         HGLOBAL hDlgTmpl;
1292         if (!(hResInfo = FindResourceA(COMDLG32_hInstance, "CHOOSE_COLOR", (LPSTR)RT_DIALOG)))
1293         {
1294             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
1295             return FALSE;
1296         }
1297         if (!(hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo )) ||
1298             !(template = LockResource(hDlgTmpl)))
1299         {
1300             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1301             return FALSE;
1302         }
1303     }
1304
1305     bRet = DialogBoxIndirectParamW(COMDLG32_hInstance, template, lpChCol->hwndOwner,
1306                      ColorDlgProc, (DWORD)lpChCol);
1307     return bRet;
1308 }
1309
1310 /***********************************************************************
1311  *            ChooseColorA  (COMDLG32.@)
1312  */
1313 BOOL WINAPI ChooseColorA( LPCHOOSECOLORA lpChCol )
1314
1315 {
1316   BOOL ret;
1317   LPCHOOSECOLORW lpcc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CHOOSECOLORW));
1318   lpcc->lStructSize = sizeof(*lpcc);
1319   lpcc->hwndOwner = lpChCol->hwndOwner;
1320   lpcc->hInstance = lpChCol->hInstance;
1321   lpcc->rgbResult = lpChCol->rgbResult;
1322   lpcc->lpCustColors = lpChCol->lpCustColors;
1323   lpcc->Flags = lpChCol->Flags;
1324   lpcc->lCustData = lpChCol->lCustData;
1325   lpcc->lpfnHook = (LPCCHOOKPROC) lpChCol->lpfnHook;
1326   if ((lpcc->Flags & CC_ENABLETEMPLATE) && (lpChCol->lpTemplateName)) {
1327       if (HIWORD(lpChCol->lpTemplateName)) {
1328           INT len = MultiByteToWideChar( CP_ACP, 0, lpChCol->lpTemplateName, -1, NULL, 0);
1329           lpcc->lpTemplateName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
1330           MultiByteToWideChar( CP_ACP, 0, lpChCol->lpTemplateName, -1, (LPWSTR)lpcc->lpTemplateName, len );
1331       } else {
1332           lpcc->lpTemplateName = (LPWSTR)lpChCol->lpTemplateName;
1333       }
1334   }
1335
1336   ret = ChooseColorW(lpcc);
1337
1338   if (ret)
1339       lpChCol->rgbResult = lpcc->rgbResult;
1340   if (HIWORD(lpcc->lpTemplateName)) HeapFree(GetProcessHeap(), 0, (LPSTR)lpcc->lpTemplateName);
1341   HeapFree(GetProcessHeap(), 0, lpcc);
1342   return ret;
1343 }