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