Don't crash if queuing an APC on a thread that doesn't wait.
[wine/wine64.git] / dlls / commdlg / colordlg.c
blob9b74f5e0e2402a8520a12a165bde0069816289fe
1 /*
2 * COMMDLG - File Dialog
4 * Copyright 1994 Martin Ayotte
5 * Copyright 1996 Albrecht Kleine
6 */
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "winbase.h"
12 #include "wine/winbase16.h"
13 #include "wine/winuser16.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "commdlg.h"
17 #include "resource.h"
18 #include "dialog.h"
19 #include "dlgs.h"
20 #include "module.h"
21 #include "debug.h"
22 #include "winproc.h"
23 #include "cderr.h"
25 DEFAULT_DEBUG_CHANNEL(commdlg)
27 #include "cdlg.h"
29 /***********************************************************************
30 * ChooseColor (COMMDLG.5)
32 BOOL16 WINAPI ChooseColor16(LPCHOOSECOLOR16 lpChCol)
34 HINSTANCE16 hInst;
35 HANDLE16 hDlgTmpl = 0;
36 BOOL16 bRet = FALSE, win32Format = FALSE;
37 LPCVOID template;
38 HWND hwndDialog;
40 TRACE(commdlg,"ChooseColor\n");
41 if (!lpChCol) return FALSE;
43 if (lpChCol->Flags & CC_ENABLETEMPLATEHANDLE)
45 if (!(template = LockResource16( lpChCol->hInstance )))
47 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
48 return FALSE;
51 else if (lpChCol->Flags & CC_ENABLETEMPLATE)
53 HANDLE16 hResInfo;
54 if (!(hResInfo = FindResource16(lpChCol->hInstance,
55 lpChCol->lpTemplateName,
56 RT_DIALOG16)))
58 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
59 return FALSE;
61 if (!(hDlgTmpl = LoadResource16( lpChCol->hInstance, hResInfo )) ||
62 !(template = LockResource16( hDlgTmpl )))
64 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
65 return FALSE;
68 else
70 HANDLE hResInfo, hDlgTmpl;
71 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "CHOOSE_COLOR", RT_DIALOGA)))
73 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
74 return FALSE;
76 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
77 !(template = LockResource( hDlgTmpl )))
79 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
80 return FALSE;
82 win32Format = TRUE;
85 hInst = WIN_GetWindowInstance( lpChCol->hwndOwner );
86 hwndDialog = DIALOG_CreateIndirect( hInst, template, win32Format,
87 lpChCol->hwndOwner,
88 (DLGPROC16)MODULE_GetWndProcEntry16("ColorDlgProc"),
89 (DWORD)lpChCol, WIN_PROC_16 );
90 if (hwndDialog) bRet = DIALOG_DoDialogBox( hwndDialog, lpChCol->hwndOwner);
91 if (hDlgTmpl) FreeResource16( hDlgTmpl );
93 return bRet;
97 static const COLORREF predefcolors[6][8]=
99 { 0x008080FFL, 0x0080FFFFL, 0x0080FF80L, 0x0080FF00L,
100 0x00FFFF80L, 0x00FF8000L, 0x00C080FFL, 0x00FF80FFL },
101 { 0x000000FFL, 0x0000FFFFL, 0x0000FF80L, 0x0040FF00L,
102 0x00FFFF00L, 0x00C08000L, 0x00C08080L, 0x00FF00FFL },
104 { 0x00404080L, 0x004080FFL, 0x0000FF00L, 0x00808000L,
105 0x00804000L, 0x00FF8080L, 0x00400080L, 0x008000FFL },
106 { 0x00000080L, 0x000080FFL, 0x00008000L, 0x00408000L,
107 0x00FF0000L, 0x00A00000L, 0x00800080L, 0x00FF0080L },
109 { 0x00000040L, 0x00004080L, 0x00004000L, 0x00404000L,
110 0x00800000L, 0x00400000L, 0x00400040L, 0x00800040L },
111 { 0x00000000L, 0x00008080L, 0x00408080L, 0x00808080L,
112 0x00808040L, 0x00C0C0C0L, 0x00400040L, 0x00FFFFFFL },
115 struct CCPRIVATE
117 LPCHOOSECOLOR16 lpcc; /* points to public known data structure */
118 int nextuserdef; /* next free place in user defined color array */
119 HDC16 hdcMem; /* color graph used for BitBlt() */
120 HBITMAP16 hbmMem; /* color graph bitmap */
121 RECT16 fullsize; /* original dialog window size */
122 UINT16 msetrgb; /* # of SETRGBSTRING message (today not used) */
123 RECT16 old3angle; /* last position of l-marker */
124 RECT16 oldcross; /* last position of color/satuation marker */
125 BOOL updating; /* to prevent recursive WM_COMMAND/EN_UPDATE procesing */
126 int h;
127 int s;
128 int l; /* for temporary storing of hue,sat,lum */
131 /***********************************************************************
132 * CC_HSLtoRGB [internal]
134 static int CC_HSLtoRGB(char c,int hue,int sat,int lum)
136 int res=0,maxrgb;
138 /* hue */
139 switch(c)
141 case 'R':if (hue>80) hue-=80; else hue+=160; break;
142 case 'G':if (hue>160) hue-=160; else hue+=80; break;
143 case 'B':break;
146 /* l below 120 */
147 maxrgb=(256*MIN(120,lum))/120; /* 0 .. 256 */
148 if (hue< 80)
149 res=0;
150 else
151 if (hue< 120)
153 res=(hue-80)* maxrgb; /* 0...10240 */
154 res/=40; /* 0...256 */
156 else
157 if (hue< 200)
158 res=maxrgb;
159 else
161 res=(240-hue)* maxrgb;
162 res/=40;
164 res=res-maxrgb/2; /* -128...128 */
166 /* saturation */
167 res=maxrgb/2 + (sat*res) /240; /* 0..256 */
169 /* lum above 120 */
170 if (lum>120 && res<256)
171 res+=((lum-120) * (256-res))/120;
173 return MIN(res,255);
176 /***********************************************************************
177 * CC_RGBtoHSL [internal]
179 static int CC_RGBtoHSL(char c,int r,int g,int b)
181 WORD maxi,mini,mmsum,mmdif,result=0;
182 int iresult=0;
184 maxi=MAX(r,b);
185 maxi=MAX(maxi,g);
186 mini=MIN(r,b);
187 mini=MIN(mini,g);
189 mmsum=maxi+mini;
190 mmdif=maxi-mini;
192 switch(c)
194 /* lum */
195 case 'L':mmsum*=120; /* 0...61200=(255+255)*120 */
196 result=mmsum/255; /* 0...240 */
197 break;
198 /* saturation */
199 case 'S':if (!mmsum)
200 result=0;
201 else
202 if (!mini || maxi==255)
203 result=240;
204 else
206 result=mmdif*240; /* 0...61200=255*240 */
207 result/= (mmsum>255 ? mmsum=510-mmsum : mmsum); /* 0..255 */
209 break;
210 /* hue */
211 case 'H':if (!mmdif)
212 result=160;
213 else
215 if (maxi==r)
217 iresult=40*(g-b); /* -10200 ... 10200 */
218 iresult/=(int)mmdif; /* -40 .. 40 */
219 if (iresult<0)
220 iresult+=240; /* 0..40 and 200..240 */
222 else
223 if (maxi==g)
225 iresult=40*(b-r);
226 iresult/=(int)mmdif;
227 iresult+=80; /* 40 .. 120 */
229 else
230 if (maxi==b)
232 iresult=40*(r-g);
233 iresult/=(int)mmdif;
234 iresult+=160; /* 120 .. 200 */
236 result=iresult;
238 break;
240 return result; /* is this integer arithmetic precise enough ? */
243 #define DISTANCE 4
245 /***********************************************************************
246 * CC_MouseCheckPredefColorArray [internal]
248 static int CC_MouseCheckPredefColorArray(HWND16 hDlg,int dlgitem,int rows,int cols,
249 LPARAM lParam,COLORREF *cr)
251 HWND16 hwnd;
252 POINT16 point = MAKEPOINT16(lParam);
253 RECT16 rect;
254 int dx,dy,x,y;
256 ClientToScreen16(hDlg,&point);
257 hwnd=GetDlgItem(hDlg,dlgitem);
258 GetWindowRect16(hwnd,&rect);
259 if (PtInRect16(&rect,point))
261 dx=(rect.right-rect.left)/cols;
262 dy=(rect.bottom-rect.top)/rows;
263 ScreenToClient16(hwnd,&point);
265 if (point.x % dx < (dx-DISTANCE) && point.y % dy < (dy-DISTANCE))
267 x=point.x/dx;
268 y=point.y/dy;
269 *cr=predefcolors[y][x];
270 /* FIXME: Draw_a_Focus_Rect() */
271 return 1;
274 return 0;
277 /***********************************************************************
278 * CC_MouseCheckUserColorArray [internal]
280 static int CC_MouseCheckUserColorArray(HWND16 hDlg,int dlgitem,int rows,int cols,
281 LPARAM lParam,COLORREF *cr,COLORREF*crarr)
283 HWND16 hwnd;
284 POINT16 point = MAKEPOINT16(lParam);
285 RECT16 rect;
286 int dx,dy,x,y;
288 ClientToScreen16(hDlg,&point);
289 hwnd=GetDlgItem(hDlg,dlgitem);
290 GetWindowRect16(hwnd,&rect);
291 if (PtInRect16(&rect,point))
293 dx=(rect.right-rect.left)/cols;
294 dy=(rect.bottom-rect.top)/rows;
295 ScreenToClient16(hwnd,&point);
297 if (point.x % dx < (dx-DISTANCE) && point.y % dy < (dy-DISTANCE))
299 x=point.x/dx;
300 y=point.y/dy;
301 *cr=crarr[x+cols*y];
302 /* FIXME: Draw_a_Focus_Rect() */
303 return 1;
306 return 0;
309 #define MAXVERT 240
310 #define MAXHORI 239
312 /* 240 ^...... ^^ 240
313 | . ||
314 SAT | . || LUM
315 | . ||
316 +-----> 239 ----
319 /***********************************************************************
320 * CC_MouseCheckColorGraph [internal]
322 static int CC_MouseCheckColorGraph(HWND16 hDlg,int dlgitem,int *hori,int *vert,LPARAM lParam)
324 HWND hwnd;
325 POINT16 point = MAKEPOINT16(lParam);
326 RECT16 rect;
327 long x,y;
329 ClientToScreen16(hDlg,&point);
330 hwnd=GetDlgItem(hDlg,dlgitem);
331 GetWindowRect16(hwnd,&rect);
332 if (PtInRect16(&rect,point))
334 GetClientRect16(hwnd,&rect);
335 ScreenToClient16(hwnd,&point);
337 x=(long)point.x*MAXHORI;
338 x/=rect.right;
339 y=(long)(rect.bottom-point.y)*MAXVERT;
340 y/=rect.bottom;
342 if (hori)
343 *hori=x;
344 if (vert)
345 *vert=y;
346 return 1;
348 else
349 return 0;
351 /***********************************************************************
352 * CC_MouseCheckResultWindow [internal]
354 static int CC_MouseCheckResultWindow(HWND16 hDlg,LPARAM lParam)
356 HWND16 hwnd;
357 POINT16 point = MAKEPOINT16(lParam);
358 RECT16 rect;
360 ClientToScreen16(hDlg,&point);
361 hwnd=GetDlgItem(hDlg,0x2c5);
362 GetWindowRect16(hwnd,&rect);
363 if (PtInRect16(&rect,point))
365 PostMessage16(hDlg,WM_COMMAND,0x2c9,0);
366 return 1;
368 return 0;
371 /***********************************************************************
372 * CC_CheckDigitsInEdit [internal]
374 static int CC_CheckDigitsInEdit(HWND16 hwnd,int maxval)
376 int i,k,m,result,value;
377 long editpos;
378 char buffer[30];
379 GetWindowTextA(hwnd,buffer,sizeof(buffer));
380 m=strlen(buffer);
381 result=0;
383 for (i=0;i<m;i++)
384 if (buffer[i]<'0' || buffer[i]>'9')
386 for (k=i+1;k<=m;k++) /* delete bad character */
388 buffer[i]=buffer[k];
389 m--;
391 buffer[m]=0;
392 result=1;
395 value=atoi(buffer);
396 if (value>maxval) /* build a new string */
398 sprintf(buffer,"%d",maxval);
399 result=2;
401 if (result)
403 editpos=SendMessage16(hwnd,EM_GETSEL16,0,0);
404 SetWindowTextA(hwnd,buffer);
405 SendMessage16(hwnd,EM_SETSEL16,0,editpos);
407 return value;
412 /***********************************************************************
413 * CC_PaintSelectedColor [internal]
415 static void CC_PaintSelectedColor(HWND16 hDlg,COLORREF cr)
417 RECT16 rect;
418 HDC hdc;
419 HBRUSH hBrush;
420 HWND hwnd=GetDlgItem(hDlg,0x2c5);
421 if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */
423 hdc=GetDC(hwnd);
424 GetClientRect16 (hwnd, &rect) ;
425 hBrush = CreateSolidBrush(cr);
426 if (hBrush)
428 hBrush = SelectObject (hdc, hBrush) ;
429 Rectangle(hdc, rect.left,rect.top,rect.right/2,rect.bottom);
430 DeleteObject (SelectObject (hdc,hBrush)) ;
431 hBrush=CreateSolidBrush(GetNearestColor(hdc,cr));
432 if (hBrush)
434 hBrush= SelectObject (hdc, hBrush) ;
435 Rectangle( hdc, rect.right/2-1,rect.top,rect.right,rect.bottom);
436 DeleteObject( SelectObject (hdc, hBrush)) ;
439 ReleaseDC(hwnd,hdc);
443 /***********************************************************************
444 * CC_PaintTriangle [internal]
446 static void CC_PaintTriangle(HWND16 hDlg,int y)
448 HDC hDC;
449 long temp;
450 int w=GetDialogBaseUnits();
451 POINT16 points[3];
452 int height;
453 int oben;
454 RECT16 rect;
455 HWND16 hwnd=GetDlgItem(hDlg,0x2be);
456 struct CCPRIVATE *lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
458 if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */
460 GetClientRect16(hwnd,&rect);
461 height=rect.bottom;
462 hDC=GetDC(hDlg);
464 points[0].y=rect.top;
465 points[0].x=rect.right; /* | /| */
466 ClientToScreen16(hwnd,points); /* | / | */
467 ScreenToClient16(hDlg,points); /* |< | */
468 oben=points[0].y; /* | \ | */
469 /* | \| */
470 temp=(long)height*(long)y;
471 points[0].y=oben+height -temp/(long)MAXVERT;
472 points[1].y=points[0].y+w;
473 points[2].y=points[0].y-w;
474 points[2].x=points[1].x=points[0].x + w;
476 if (lpp->old3angle.left)
477 FillRect16(hDC,&lpp->old3angle,GetStockObject(WHITE_BRUSH));
478 lpp->old3angle.left =points[0].x;
479 lpp->old3angle.right =points[1].x+1;
480 lpp->old3angle.top =points[2].y-1;
481 lpp->old3angle.bottom=points[1].y+1;
482 Polygon16(hDC,points,3);
483 ReleaseDC(hDlg,hDC);
488 /***********************************************************************
489 * CC_PaintCross [internal]
491 static void CC_PaintCross(HWND16 hDlg,int x,int y)
493 HDC hDC;
494 int w=GetDialogBaseUnits();
495 HWND16 hwnd=GetDlgItem(hDlg,0x2c6);
496 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
497 RECT16 rect;
498 POINT16 point;
499 HPEN hPen;
501 if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */
503 GetClientRect16(hwnd,&rect);
504 hDC=GetDC(hwnd);
505 SelectClipRgn(hDC,CreateRectRgnIndirect16(&rect));
506 hPen=CreatePen(PS_SOLID,2,0);
507 hPen=SelectObject(hDC,hPen);
508 point.x=((long)rect.right*(long)x)/(long)MAXHORI;
509 point.y=rect.bottom-((long)rect.bottom*(long)y)/(long)MAXVERT;
510 if (lpp->oldcross.left!=lpp->oldcross.right)
511 BitBlt(hDC,lpp->oldcross.left,lpp->oldcross.top,
512 lpp->oldcross.right-lpp->oldcross.left,
513 lpp->oldcross.bottom-lpp->oldcross.top,
514 lpp->hdcMem,lpp->oldcross.left,lpp->oldcross.top,SRCCOPY);
515 lpp->oldcross.left =point.x-w-1;
516 lpp->oldcross.right =point.x+w+1;
517 lpp->oldcross.top =point.y-w-1;
518 lpp->oldcross.bottom=point.y+w+1;
520 MoveTo16(hDC,point.x-w,point.y);
521 LineTo(hDC,point.x+w,point.y);
522 MoveTo16(hDC,point.x,point.y-w);
523 LineTo(hDC,point.x,point.y+w);
524 DeleteObject(SelectObject(hDC,hPen));
525 ReleaseDC(hwnd,hDC);
530 #define XSTEPS 48
531 #define YSTEPS 24
534 /***********************************************************************
535 * CC_PrepareColorGraph [internal]
537 static void CC_PrepareColorGraph(HWND16 hDlg)
539 int sdif,hdif,xdif,ydif,r,g,b,hue,sat;
540 HWND hwnd=GetDlgItem(hDlg,0x2c6);
541 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
542 HBRUSH hbrush;
543 HDC hdc ;
544 RECT16 rect,client;
545 HCURSOR16 hcursor=SetCursor16(LoadCursor16(0,IDC_WAIT16));
547 GetClientRect16(hwnd,&client);
548 hdc=GetDC(hwnd);
549 lpp->hdcMem = CreateCompatibleDC(hdc);
550 lpp->hbmMem = CreateCompatibleBitmap(hdc,client.right,client.bottom);
551 SelectObject(lpp->hdcMem,lpp->hbmMem);
553 xdif=client.right /XSTEPS;
554 ydif=client.bottom/YSTEPS+1;
555 hdif=239/XSTEPS;
556 sdif=240/YSTEPS;
557 for(rect.left=hue=0;hue<239+hdif;hue+=hdif)
559 rect.right=rect.left+xdif;
560 rect.bottom=client.bottom;
561 for(sat=0;sat<240+sdif;sat+=sdif)
563 rect.top=rect.bottom-ydif;
564 r=CC_HSLtoRGB('R',hue,sat,120);
565 g=CC_HSLtoRGB('G',hue,sat,120);
566 b=CC_HSLtoRGB('B',hue,sat,120);
567 hbrush=CreateSolidBrush(RGB(r,g,b));
568 FillRect16(lpp->hdcMem,&rect,hbrush);
569 DeleteObject(hbrush);
570 rect.bottom=rect.top;
572 rect.left=rect.right;
574 ReleaseDC(hwnd,hdc);
575 SetCursor16(hcursor);
578 /***********************************************************************
579 * CC_PaintColorGraph [internal]
581 static void CC_PaintColorGraph(HWND16 hDlg)
583 HWND hwnd=GetDlgItem(hDlg,0x2c6);
584 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
585 HDC hDC;
586 RECT16 rect;
587 if (IsWindowVisible(hwnd)) /* if full size */
589 if (!lpp->hdcMem)
590 CC_PrepareColorGraph(hDlg); /* should not be necessary */
592 hDC=GetDC(hwnd);
593 GetClientRect16(hwnd,&rect);
594 if (lpp->hdcMem)
595 BitBlt(hDC,0,0,rect.right,rect.bottom,lpp->hdcMem,0,0,SRCCOPY);
596 else
597 WARN(commdlg,"choose color: hdcMem is not defined\n");
598 ReleaseDC(hwnd,hDC);
601 /***********************************************************************
602 * CC_PaintLumBar [internal]
604 static void CC_PaintLumBar(HWND16 hDlg,int hue,int sat)
606 HWND hwnd=GetDlgItem(hDlg,0x2be);
607 RECT16 rect,client;
608 int lum,ldif,ydif,r,g,b;
609 HBRUSH hbrush;
610 HDC hDC;
612 if (IsWindowVisible(hwnd))
614 hDC=GetDC(hwnd);
615 GetClientRect16(hwnd,&client);
616 rect=client;
618 ldif=240/YSTEPS;
619 ydif=client.bottom/YSTEPS+1;
620 for(lum=0;lum<240+ldif;lum+=ldif)
622 rect.top=MAX(0,rect.bottom-ydif);
623 r=CC_HSLtoRGB('R',hue,sat,lum);
624 g=CC_HSLtoRGB('G',hue,sat,lum);
625 b=CC_HSLtoRGB('B',hue,sat,lum);
626 hbrush=CreateSolidBrush(RGB(r,g,b));
627 FillRect16(hDC,&rect,hbrush);
628 DeleteObject(hbrush);
629 rect.bottom=rect.top;
631 GetClientRect16(hwnd,&rect);
632 FrameRect16(hDC,&rect,GetStockObject(BLACK_BRUSH));
633 ReleaseDC(hwnd,hDC);
637 /***********************************************************************
638 * CC_EditSetRGB [internal]
640 static void CC_EditSetRGB(HWND16 hDlg,COLORREF cr)
642 char buffer[10];
643 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
644 int r=GetRValue(cr);
645 int g=GetGValue(cr);
646 int b=GetBValue(cr);
647 if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */
649 lpp->updating=TRUE;
650 sprintf(buffer,"%d",r);
651 SetWindowTextA(GetDlgItem(hDlg,0x2c2),buffer);
652 sprintf(buffer,"%d",g);
653 SetWindowTextA(GetDlgItem(hDlg,0x2c3),buffer);
654 sprintf(buffer,"%d",b);
655 SetWindowTextA(GetDlgItem(hDlg,0x2c4),buffer);
656 lpp->updating=FALSE;
660 /***********************************************************************
661 * CC_EditSetHSL [internal]
663 static void CC_EditSetHSL(HWND16 hDlg,int h,int s,int l)
665 char buffer[10];
666 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
667 lpp->updating=TRUE;
668 if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */
670 lpp->updating=TRUE;
671 sprintf(buffer,"%d",h);
672 SetWindowTextA(GetDlgItem(hDlg,0x2bf),buffer);
673 sprintf(buffer,"%d",s);
674 SetWindowTextA(GetDlgItem(hDlg,0x2c0),buffer);
675 sprintf(buffer,"%d",l);
676 SetWindowTextA(GetDlgItem(hDlg,0x2c1),buffer);
677 lpp->updating=FALSE;
679 CC_PaintLumBar(hDlg,h,s);
682 /***********************************************************************
683 * CC_SwitchToFullSize [internal]
685 static void CC_SwitchToFullSize(HWND16 hDlg,COLORREF result,LPRECT16 lprect)
687 int i;
688 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
690 EnableWindow(GetDlgItem(hDlg,0x2cf),FALSE);
691 CC_PrepareColorGraph(hDlg);
692 for (i=0x2bf;i<0x2c5;i++)
693 EnableWindow(GetDlgItem(hDlg,i),TRUE);
694 for (i=0x2d3;i<0x2d9;i++)
695 EnableWindow(GetDlgItem(hDlg,i),TRUE);
696 EnableWindow(GetDlgItem(hDlg,0x2c9),TRUE);
697 EnableWindow(GetDlgItem(hDlg,0x2c8),TRUE);
699 if (lprect)
700 SetWindowPos(hDlg,0,0,0,lprect->right-lprect->left,
701 lprect->bottom-lprect->top, SWP_NOMOVE|SWP_NOZORDER);
703 ShowWindow(GetDlgItem(hDlg,0x2c6),SW_SHOW);
704 ShowWindow(GetDlgItem(hDlg,0x2be),SW_SHOW);
705 ShowWindow(GetDlgItem(hDlg,0x2c5),SW_SHOW);
707 CC_EditSetRGB(hDlg,result);
708 CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l);
711 /***********************************************************************
712 * CC_PaintPredefColorArray [internal]
714 static void CC_PaintPredefColorArray(HWND16 hDlg,int rows,int cols)
716 HWND hwnd=GetDlgItem(hDlg,0x2d0);
717 RECT16 rect;
718 HDC hdc;
719 HBRUSH hBrush;
720 int dx,dy,i,j,k;
722 GetClientRect16(hwnd,&rect);
723 dx=rect.right/cols;
724 dy=rect.bottom/rows;
725 k=rect.left;
727 hdc=GetDC(hwnd);
728 GetClientRect16 (hwnd, &rect) ;
730 for (j=0;j<rows;j++)
732 for (i=0;i<cols;i++)
734 hBrush = CreateSolidBrush(predefcolors[j][i]);
735 if (hBrush)
737 hBrush = SelectObject (hdc, hBrush) ;
738 Rectangle(hdc, rect.left, rect.top,
739 rect.left+dx-DISTANCE, rect.top+dy-DISTANCE);
740 rect.left=rect.left+dx;
741 DeleteObject( SelectObject (hdc, hBrush)) ;
744 rect.top=rect.top+dy;
745 rect.left=k;
747 ReleaseDC(hwnd,hdc);
748 /* FIXME: draw_a_focus_rect */
750 /***********************************************************************
751 * CC_PaintUserColorArray [internal]
753 static void CC_PaintUserColorArray(HWND16 hDlg,int rows,int cols,COLORREF* lpcr)
755 HWND hwnd=GetDlgItem(hDlg,0x2d1);
756 RECT16 rect;
757 HDC hdc;
758 HBRUSH hBrush;
759 int dx,dy,i,j,k;
761 GetClientRect16(hwnd,&rect);
763 dx=rect.right/cols;
764 dy=rect.bottom/rows;
765 k=rect.left;
767 hdc=GetDC(hwnd);
768 if (hdc)
770 for (j=0;j<rows;j++)
772 for (i=0;i<cols;i++)
774 hBrush = CreateSolidBrush(lpcr[i+j*cols]);
775 if (hBrush)
777 hBrush = SelectObject (hdc, hBrush) ;
778 Rectangle( hdc, rect.left, rect.top,
779 rect.left+dx-DISTANCE, rect.top+dy-DISTANCE);
780 rect.left=rect.left+dx;
781 DeleteObject( SelectObject (hdc, hBrush)) ;
784 rect.top=rect.top+dy;
785 rect.left=k;
787 ReleaseDC(hwnd,hdc);
789 /* FIXME: draw_a_focus_rect */
794 /***********************************************************************
795 * CC_HookCallChk [internal]
797 static BOOL CC_HookCallChk(LPCHOOSECOLOR16 lpcc)
799 if (lpcc)
800 if(lpcc->Flags & CC_ENABLEHOOK)
801 if (lpcc->lpfnHook)
802 return TRUE;
803 return FALSE;
806 /***********************************************************************
807 * CC_WMInitDialog [internal]
809 static LONG CC_WMInitDialog(HWND16 hDlg, WPARAM16 wParam, LPARAM lParam)
811 int i,res;
812 int r, g, b;
813 HWND16 hwnd;
814 RECT16 rect;
815 POINT16 point;
816 struct CCPRIVATE * lpp;
818 TRACE(commdlg,"WM_INITDIALOG lParam=%08lX\n", lParam);
819 lpp=calloc(1,sizeof(struct CCPRIVATE));
820 lpp->lpcc=(LPCHOOSECOLOR16)lParam;
822 if (lpp->lpcc->lStructSize != sizeof(CHOOSECOLOR16))
824 EndDialog (hDlg, 0) ;
825 return FALSE;
827 SetWindowLongA(hDlg, DWL_USER, (LONG)lpp);
829 if (!(lpp->lpcc->Flags & CC_SHOWHELP))
830 ShowWindow(GetDlgItem(hDlg,0x40e),SW_HIDE);
831 lpp->msetrgb=RegisterWindowMessageA( SETRGBSTRING );
833 #if 0
834 cpos=MAKELONG(5,7); /* init */
835 if (lpp->lpcc->Flags & CC_RGBINIT)
837 for (i=0;i<6;i++)
838 for (j=0;j<8;j++)
839 if (predefcolors[i][j]==lpp->lpcc->rgbResult)
841 cpos=MAKELONG(i,j);
842 goto found;
845 found:
846 /* FIXME: Draw_a_focus_rect & set_init_values */
847 #endif
849 GetWindowRect16(hDlg,&lpp->fullsize);
850 if (lpp->lpcc->Flags & CC_FULLOPEN || lpp->lpcc->Flags & CC_PREVENTFULLOPEN)
852 hwnd=GetDlgItem(hDlg,0x2cf);
853 EnableWindow(hwnd,FALSE);
855 if (!(lpp->lpcc->Flags & CC_FULLOPEN) || lpp->lpcc->Flags & CC_PREVENTFULLOPEN)
857 rect=lpp->fullsize;
858 res=rect.bottom-rect.top;
859 hwnd=GetDlgItem(hDlg,0x2c6); /* cut at left border */
860 point.x=point.y=0;
861 ClientToScreen16(hwnd,&point);
862 ScreenToClient16(hDlg,&point);
863 GetClientRect16(hDlg,&rect);
864 point.x+=GetSystemMetrics(SM_CXDLGFRAME);
865 SetWindowPos(hDlg,0,0,0,point.x,res,SWP_NOMOVE|SWP_NOZORDER);
867 ShowWindow(GetDlgItem(hDlg,0x2c6),SW_HIDE);
868 ShowWindow(GetDlgItem(hDlg,0x2c5),SW_HIDE);
870 else
871 CC_SwitchToFullSize(hDlg,lpp->lpcc->rgbResult,NULL);
872 res=TRUE;
873 for (i=0x2bf;i<0x2c5;i++)
874 SendMessage16(GetDlgItem(hDlg,i),EM_LIMITTEXT16,3,0); /* max 3 digits: xyz */
875 if (CC_HookCallChk(lpp->lpcc))
876 res=CallWindowProc16(lpp->lpcc->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
879 /* Set the initial values of the color chooser dialog */
880 r = GetRValue(lpp->lpcc->rgbResult);
881 g = GetGValue(lpp->lpcc->rgbResult);
882 b = GetBValue(lpp->lpcc->rgbResult);
884 CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
885 lpp->h=CC_RGBtoHSL('H',r,g,b);
886 lpp->s=CC_RGBtoHSL('S',r,g,b);
887 lpp->l=CC_RGBtoHSL('L',r,g,b);
889 /* Doing it the long way becaus CC_EditSetRGB/HSL doesn'nt seem to work */
890 SetDlgItemInt(hDlg, 703, lpp->h, TRUE);
891 SetDlgItemInt(hDlg, 704, lpp->s, TRUE);
892 SetDlgItemInt(hDlg, 705, lpp->l, TRUE);
893 SetDlgItemInt(hDlg, 706, r, TRUE);
894 SetDlgItemInt(hDlg, 707, g, TRUE);
895 SetDlgItemInt(hDlg, 708, b, TRUE);
897 CC_PaintCross(hDlg,lpp->h,lpp->s);
898 CC_PaintTriangle(hDlg,lpp->l);
900 return res;
903 /***********************************************************************
904 * CC_WMCommand [internal]
906 static LRESULT CC_WMCommand(HWND16 hDlg, WPARAM16 wParam, LPARAM lParam)
908 int r,g,b,i,xx;
909 UINT16 cokmsg;
910 HDC hdc;
911 COLORREF *cr;
912 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
913 TRACE(commdlg,"CC_WMCommand wParam=%x lParam=%lx\n",wParam,lParam);
914 switch (wParam)
916 case 0x2c2: /* edit notify RGB */
917 case 0x2c3:
918 case 0x2c4:
919 if (HIWORD(lParam)==EN_UPDATE && !lpp->updating)
921 i=CC_CheckDigitsInEdit(LOWORD(lParam),255);
922 r=GetRValue(lpp->lpcc->rgbResult);
923 g=GetGValue(lpp->lpcc->rgbResult);
924 b=GetBValue(lpp->lpcc->rgbResult);
925 xx=0;
926 switch (wParam)
928 case 0x2c2:if ((xx=(i!=r))) r=i;break;
929 case 0x2c3:if ((xx=(i!=g))) g=i;break;
930 case 0x2c4:if ((xx=(i!=b))) b=i;break;
932 if (xx) /* something has changed */
934 lpp->lpcc->rgbResult=RGB(r,g,b);
935 CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
936 lpp->h=CC_RGBtoHSL('H',r,g,b);
937 lpp->s=CC_RGBtoHSL('S',r,g,b);
938 lpp->l=CC_RGBtoHSL('L',r,g,b);
939 CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l);
940 CC_PaintCross(hDlg,lpp->h,lpp->s);
941 CC_PaintTriangle(hDlg,lpp->l);
944 break;
946 case 0x2bf: /* edit notify HSL */
947 case 0x2c0:
948 case 0x2c1:
949 if (HIWORD(lParam)==EN_UPDATE && !lpp->updating)
951 i=CC_CheckDigitsInEdit(LOWORD(lParam),wParam==0x2bf?239:240);
952 xx=0;
953 switch (wParam)
955 case 0x2bf:if ((xx=(i!=lpp->h))) lpp->h=i;break;
956 case 0x2c0:if ((xx=(i!=lpp->s))) lpp->s=i;break;
957 case 0x2c1:if ((xx=(i!=lpp->l))) lpp->l=i;break;
959 if (xx) /* something has changed */
961 r=CC_HSLtoRGB('R',lpp->h,lpp->s,lpp->l);
962 g=CC_HSLtoRGB('G',lpp->h,lpp->s,lpp->l);
963 b=CC_HSLtoRGB('B',lpp->h,lpp->s,lpp->l);
964 lpp->lpcc->rgbResult=RGB(r,g,b);
965 CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
966 CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult);
967 CC_PaintCross(hDlg,lpp->h,lpp->s);
968 CC_PaintTriangle(hDlg,lpp->l);
971 break;
973 case 0x2cf:
974 CC_SwitchToFullSize(hDlg,lpp->lpcc->rgbResult,&lpp->fullsize);
975 InvalidateRect( hDlg, NULL, TRUE );
976 SetFocus(GetDlgItem(hDlg,0x2bf));
977 break;
979 case 0x2c8: /* add colors ... column by column */
980 cr=PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors);
981 cr[(lpp->nextuserdef%2)*8 + lpp->nextuserdef/2]=lpp->lpcc->rgbResult;
982 if (++lpp->nextuserdef==16)
983 lpp->nextuserdef=0;
984 CC_PaintUserColorArray(hDlg,2,8,PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors));
985 break;
987 case 0x2c9: /* resulting color */
988 hdc=GetDC(hDlg);
989 lpp->lpcc->rgbResult=GetNearestColor(hdc,lpp->lpcc->rgbResult);
990 ReleaseDC(hDlg,hdc);
991 CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult);
992 CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
993 r=GetRValue(lpp->lpcc->rgbResult);
994 g=GetGValue(lpp->lpcc->rgbResult);
995 b=GetBValue(lpp->lpcc->rgbResult);
996 lpp->h=CC_RGBtoHSL('H',r,g,b);
997 lpp->s=CC_RGBtoHSL('S',r,g,b);
998 lpp->l=CC_RGBtoHSL('L',r,g,b);
999 CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l);
1000 CC_PaintCross(hDlg,lpp->h,lpp->s);
1001 CC_PaintTriangle(hDlg,lpp->l);
1002 break;
1004 case 0x40e: /* Help! */ /* The Beatles, 1965 ;-) */
1005 i=RegisterWindowMessageA( HELPMSGSTRING );
1006 if (lpp->lpcc->hwndOwner)
1007 SendMessage16(lpp->lpcc->hwndOwner,i,0,(LPARAM)lpp->lpcc);
1008 if (CC_HookCallChk(lpp->lpcc))
1009 CallWindowProc16(lpp->lpcc->lpfnHook,hDlg,
1010 WM_COMMAND,psh15,(LPARAM)lpp->lpcc);
1011 break;
1013 case IDOK :
1014 cokmsg=RegisterWindowMessageA( COLOROKSTRING );
1015 if (lpp->lpcc->hwndOwner)
1016 if (SendMessage16(lpp->lpcc->hwndOwner,cokmsg,0,(LPARAM)lpp->lpcc))
1017 break; /* do NOT close */
1019 EndDialog (hDlg, 1) ;
1020 return TRUE ;
1022 case IDCANCEL :
1023 EndDialog (hDlg, 0) ;
1024 return TRUE ;
1027 return FALSE;
1030 /***********************************************************************
1031 * CC_WMPaint [internal]
1033 static LRESULT CC_WMPaint(HWND16 hDlg, WPARAM16 wParam, LPARAM lParam)
1035 HDC hdc;
1036 PAINTSTRUCT ps;
1037 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
1039 hdc=BeginPaint(hDlg,&ps);
1040 EndPaint(hDlg,&ps);
1041 /* we have to paint dialog children except text and buttons */
1043 CC_PaintPredefColorArray(hDlg,6,8);
1044 CC_PaintUserColorArray(hDlg,2,8,PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors));
1045 CC_PaintColorGraph(hDlg);
1046 CC_PaintLumBar(hDlg,lpp->h,lpp->s);
1047 CC_PaintCross(hDlg,lpp->h,lpp->s);
1048 CC_PaintTriangle(hDlg,lpp->l);
1049 CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
1051 /* special necessary for Wine */
1052 ValidateRect(GetDlgItem(hDlg,0x2d0),NULL);
1053 ValidateRect(GetDlgItem(hDlg,0x2d1),NULL);
1054 ValidateRect(GetDlgItem(hDlg,0x2c6),NULL);
1055 ValidateRect(GetDlgItem(hDlg,0x2be),NULL);
1056 ValidateRect(GetDlgItem(hDlg,0x2c5),NULL);
1057 /* hope we can remove it later -->FIXME */
1058 return TRUE;
1062 /***********************************************************************
1063 * CC_WMLButtonDown [internal]
1065 static LRESULT CC_WMLButtonDown(HWND16 hDlg, WPARAM16 wParam, LPARAM lParam)
1067 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
1068 int r,g,b,i;
1069 i=0;
1070 if (CC_MouseCheckPredefColorArray(hDlg,0x2d0,6,8,lParam,&lpp->lpcc->rgbResult))
1071 i=1;
1072 else
1073 if (CC_MouseCheckUserColorArray(hDlg,0x2d1,2,8,lParam,&lpp->lpcc->rgbResult,
1074 PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors)))
1075 i=1;
1076 else
1077 if (CC_MouseCheckColorGraph(hDlg,0x2c6,&lpp->h,&lpp->s,lParam))
1078 i=2;
1079 else
1080 if (CC_MouseCheckColorGraph(hDlg,0x2be,NULL,&lpp->l,lParam))
1081 i=2;
1082 if (i==2)
1084 r=CC_HSLtoRGB('R',lpp->h,lpp->s,lpp->l);
1085 g=CC_HSLtoRGB('G',lpp->h,lpp->s,lpp->l);
1086 b=CC_HSLtoRGB('B',lpp->h,lpp->s,lpp->l);
1087 lpp->lpcc->rgbResult=RGB(r,g,b);
1089 if (i==1)
1091 r=GetRValue(lpp->lpcc->rgbResult);
1092 g=GetGValue(lpp->lpcc->rgbResult);
1093 b=GetBValue(lpp->lpcc->rgbResult);
1094 lpp->h=CC_RGBtoHSL('H',r,g,b);
1095 lpp->s=CC_RGBtoHSL('S',r,g,b);
1096 lpp->l=CC_RGBtoHSL('L',r,g,b);
1098 if (i)
1100 CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult);
1101 CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l);
1102 CC_PaintCross(hDlg,lpp->h,lpp->s);
1103 CC_PaintTriangle(hDlg,lpp->l);
1104 CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
1105 return TRUE;
1107 return FALSE;
1110 /***********************************************************************
1111 * ColorDlgProc (COMMDLG.8)
1113 LRESULT WINAPI ColorDlgProc16(HWND16 hDlg, UINT16 message,
1114 WPARAM16 wParam, LONG lParam)
1116 int res;
1117 struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLongA(hDlg, DWL_USER);
1118 if (message!=WM_INITDIALOG)
1120 if (!lpp)
1121 return FALSE;
1122 res=0;
1123 if (CC_HookCallChk(lpp->lpcc))
1124 res=CallWindowProc16(lpp->lpcc->lpfnHook,hDlg,message,wParam,lParam);
1125 if (res)
1126 return res;
1129 /* FIXME: SetRGB message
1130 if (message && message==msetrgb)
1131 return HandleSetRGB(hDlg,lParam);
1134 switch (message)
1136 case WM_INITDIALOG:
1137 return CC_WMInitDialog(hDlg,wParam,lParam);
1138 case WM_NCDESTROY:
1139 DeleteDC(lpp->hdcMem);
1140 DeleteObject(lpp->hbmMem);
1141 free(lpp);
1142 SetWindowLongA(hDlg, DWL_USER, 0L); /* we don't need it anymore */
1143 break;
1144 case WM_COMMAND:
1145 if (CC_WMCommand(hDlg, wParam, lParam))
1146 return TRUE;
1147 break;
1148 case WM_PAINT:
1149 if (CC_WMPaint(hDlg, wParam, lParam))
1150 return TRUE;
1151 break;
1152 case WM_LBUTTONDBLCLK:
1153 if (CC_MouseCheckResultWindow(hDlg,lParam))
1154 return TRUE;
1155 break;
1156 case WM_MOUSEMOVE: /* FIXME: calculate new hue,sat,lum (if in color graph) */
1157 break;
1158 case WM_LBUTTONUP: /* FIXME: ClipCursor off (if in color graph)*/
1159 break;
1160 case WM_LBUTTONDOWN:/* FIXME: ClipCursor on (if in color graph)*/
1161 if (CC_WMLButtonDown(hDlg, wParam, lParam))
1162 return TRUE;
1163 break;
1165 return FALSE ;
1169 /***********************************************************************
1170 * ChooseColorA (COMDLG32.1)
1172 BOOL WINAPI ChooseColorA(LPCHOOSECOLORA lpChCol )
1175 BOOL16 ret;
1176 char *str = NULL;
1177 COLORREF* ccref=SEGPTR_ALLOC(64);
1178 LPCHOOSECOLOR16 lpcc16=SEGPTR_ALLOC(sizeof(CHOOSECOLOR16));
1180 memset(lpcc16,'\0',sizeof(*lpcc16));
1181 lpcc16->lStructSize=sizeof(*lpcc16);
1182 lpcc16->hwndOwner=lpChCol->hwndOwner;
1183 lpcc16->hInstance=MapHModuleLS(lpChCol->hInstance);
1184 lpcc16->rgbResult=lpChCol->rgbResult;
1185 memcpy(ccref,lpChCol->lpCustColors,64);
1186 lpcc16->lpCustColors=(COLORREF*)SEGPTR_GET(ccref);
1187 lpcc16->Flags=lpChCol->Flags;
1188 lpcc16->lCustData=lpChCol->lCustData;
1189 lpcc16->lpfnHook=(WNDPROC16)lpChCol->lpfnHook;
1190 if (lpChCol->lpTemplateName)
1191 str = SEGPTR_STRDUP(lpChCol->lpTemplateName );
1192 lpcc16->lpTemplateName=SEGPTR_GET(str);
1194 ret = ChooseColor16(lpcc16);
1196 if(ret)
1197 lpChCol->rgbResult = lpcc16->rgbResult;
1199 if(str)
1200 SEGPTR_FREE(str);
1201 memcpy(lpChCol->lpCustColors,ccref,64);
1202 SEGPTR_FREE(ccref);
1203 SEGPTR_FREE(lpcc16);
1204 return (BOOL)ret;
1207 /***********************************************************************
1208 * ChooseColorW (COMDLG32.2)
1210 BOOL WINAPI ChooseColorW(LPCHOOSECOLORW lpChCol )
1213 BOOL16 ret;
1214 char *str = NULL;
1215 COLORREF* ccref=SEGPTR_ALLOC(64);
1216 LPCHOOSECOLOR16 lpcc16=SEGPTR_ALLOC(sizeof(CHOOSECOLOR16));
1218 memset(lpcc16,'\0',sizeof(*lpcc16));
1219 lpcc16->lStructSize=sizeof(*lpcc16);
1220 lpcc16->hwndOwner=lpChCol->hwndOwner;
1221 lpcc16->hInstance=MapHModuleLS(lpChCol->hInstance);
1222 lpcc16->rgbResult=lpChCol->rgbResult;
1223 memcpy(ccref,lpChCol->lpCustColors,64);
1224 lpcc16->lpCustColors=(COLORREF*)SEGPTR_GET(ccref);
1225 lpcc16->Flags=lpChCol->Flags;
1226 lpcc16->lCustData=lpChCol->lCustData;
1227 lpcc16->lpfnHook=(WNDPROC16)lpChCol->lpfnHook;
1228 if (lpChCol->lpTemplateName)
1229 str = SEGPTR_STRDUP_WtoA(lpChCol->lpTemplateName );
1230 lpcc16->lpTemplateName=SEGPTR_GET(str);
1232 ret = ChooseColor16(lpcc16);
1234 if(ret)
1235 lpChCol->rgbResult = lpcc16->rgbResult;
1237 if(str)
1238 SEGPTR_FREE(str);
1239 memcpy(lpChCol->lpCustColors,ccref,64);
1240 SEGPTR_FREE(ccref);
1241 SEGPTR_FREE(lpcc16);
1242 return (BOOL)ret;