[paint] fix rectangular selection tool
[reactos.git] / reactos / base / applications / paint / mouse.c
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/paint/mouse.c
5 * PURPOSE: Things which should not be in the mouse event handler itself
6 * PROGRAMMERS: Benedikt Freisen
7 */
8
9 /* INCLUDES *********************************************************/
10
11 #include "globalvar.h"
12 #include "dib.h"
13 #include "drawing.h"
14 #include "history.h"
15
16 /* FUNCTIONS ********************************************************/
17
18 void
19 placeSelWin()
20 {
21 MoveWindow(hSelection, rectSel_dest[0] * zoom / 1000, rectSel_dest[1] * zoom / 1000,
22 rectSel_dest[2] * zoom / 1000 + 6, rectSel_dest[3] * zoom / 1000 + 6, TRUE);
23 BringWindowToTop(hSelection);
24 SendMessage(hImageArea, WM_PAINT, 0, 0);
25 //SendMessage(hSelection, WM_PAINT, 0, 0);
26 }
27
28 POINT pointStack[256];
29 short pointSP;
30 POINT *ptStack = NULL;
31 int ptSP = 0;
32
33 void
34 startPaintingL(HDC hdc, short x, short y, int fg, int bg)
35 {
36 startX = x;
37 startY = y;
38 lastX = x;
39 lastY = y;
40 switch (activeTool)
41 {
42 case 1:
43 ShowWindow(hSelection, SW_HIDE);
44 if (ptStack != NULL)
45 HeapFree(GetProcessHeap(), 0, ptStack);
46 ptStack = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * 1024);
47 ptSP = 0;
48 ptStack[0].x = x;
49 ptStack[0].y = y;
50 break;
51 case 10:
52 case 11:
53 case 13:
54 case 15:
55 case 16:
56 newReversible();
57 break;
58 case 2:
59 newReversible();
60 ShowWindow(hSelection, SW_HIDE);
61 rectSel_src[2] = rectSel_src[3] = 0;
62 break;
63 case 3:
64 newReversible();
65 Erase(hdc, x, y, x, y, bg, rubberRadius);
66 break;
67 case 4:
68 newReversible();
69 Fill(hdc, x, y, fg);
70 break;
71 case 7:
72 newReversible();
73 SetPixel(hdc, x, y, fg);
74 break;
75 case 8:
76 newReversible();
77 Brush(hdc, x, y, x, y, fg, brushStyle);
78 break;
79 case 9:
80 newReversible();
81 Airbrush(hdc, x, y, fg, airBrushWidth);
82 break;
83 case 12:
84 pointStack[pointSP].x = x;
85 pointStack[pointSP].y = y;
86 if (pointSP == 0)
87 {
88 newReversible();
89 pointSP++;
90 }
91 break;
92 case 14:
93 pointStack[pointSP].x = x;
94 pointStack[pointSP].y = y;
95 if (pointSP + 1 >= 2)
96 Poly(hdc, pointStack, pointSP + 1, fg, bg, lineWidth, shapeStyle, FALSE);
97 if (pointSP == 0)
98 {
99 newReversible();
100 pointSP++;
101 }
102 break;
103 }
104 }
105
106 void
107 whilePaintingL(HDC hdc, short x, short y, int fg, int bg)
108 {
109 switch (activeTool)
110 {
111 case 1:
112 if (ptSP == 0)
113 newReversible();
114 ptSP++;
115 if (ptSP % 1024 == 0)
116 ptStack = HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, ptStack, sizeof(POINT) * (ptSP + 1024));
117 ptStack[ptSP].x = max(0, min(x, imgXRes));
118 ptStack[ptSP].y = max(0, min(y, imgYRes));
119 resetToU1();
120 Poly(hdc, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE);
121 break;
122 case 2:
123 {
124 short tempX;
125 short tempY;
126 resetToU1();
127 tempX = max(0, min(x, imgXRes));
128 tempY = max(0, min(y, imgYRes));
129 rectSel_dest[0] = rectSel_src[0] = min(startX, tempX);
130 rectSel_dest[1] = rectSel_src[1] = min(startY, tempY);
131 rectSel_dest[2] = rectSel_src[2] = max(startX, tempX) - min(startX, tempX);
132 rectSel_dest[3] = rectSel_src[3] = max(startY, tempY) - min(startY, tempY);
133 RectSel(hdc, startX, startY, tempX, tempY);
134 break;
135 }
136 case 3:
137 Erase(hdc, lastX, lastY, x, y, bg, rubberRadius);
138 break;
139 case 7:
140 Line(hdc, lastX, lastY, x, y, fg, 1);
141 break;
142 case 8:
143 Brush(hdc, lastX, lastY, x, y, fg, brushStyle);
144 break;
145 case 9:
146 Airbrush(hdc, x, y, fg, airBrushWidth);
147 break;
148 case 11:
149 resetToU1();
150 Line(hdc, startX, startY, x, y, fg, lineWidth);
151 break;
152 case 12:
153 resetToU1();
154 pointStack[pointSP].x = x;
155 pointStack[pointSP].y = y;
156 switch (pointSP)
157 {
158 case 1:
159 Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, fg,
160 lineWidth);
161 break;
162 case 2:
163 Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], fg, lineWidth);
164 break;
165 case 3:
166 Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], fg, lineWidth);
167 break;
168 }
169 break;
170 case 13:
171 resetToU1();
172 Rect(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
173 break;
174 case 14:
175 resetToU1();
176 pointStack[pointSP].x = x;
177 pointStack[pointSP].y = y;
178 if (pointSP + 1 >= 2)
179 Poly(hdc, pointStack, pointSP + 1, fg, bg, lineWidth, shapeStyle, FALSE);
180 break;
181 case 15:
182 resetToU1();
183 Ellp(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
184 break;
185 case 16:
186 resetToU1();
187 RRect(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
188 break;
189 }
190
191 lastX = x;
192 lastY = y;
193 }
194
195 void
196 endPaintingL(HDC hdc, short x, short y, int fg, int bg)
197 {
198 switch (activeTool)
199 {
200 case 1:
201 {
202 POINT *ptStackCopy;
203 int i;
204 rectSel_src[0] = rectSel_src[1] = 0x7fffffff;
205 rectSel_src[2] = rectSel_src[3] = 0;
206 for (i = 0; i <= ptSP; i++)
207 {
208 if (ptStack[i].x < rectSel_src[0])
209 rectSel_src[0] = ptStack[i].x;
210 if (ptStack[i].y < rectSel_src[1])
211 rectSel_src[1] = ptStack[i].y;
212 if (ptStack[i].x > rectSel_src[2])
213 rectSel_src[2] = ptStack[i].x;
214 if (ptStack[i].y > rectSel_src[3])
215 rectSel_src[3] = ptStack[i].y;
216 }
217 rectSel_src[2] += 1 - rectSel_src[0];
218 rectSel_src[3] += 1 - rectSel_src[1];
219 rectSel_dest[0] = rectSel_src[0];
220 rectSel_dest[1] = rectSel_src[1];
221 rectSel_dest[2] = rectSel_src[2];
222 rectSel_dest[3] = rectSel_src[3];
223 if (ptSP != 0)
224 {
225 DeleteObject(hSelMask);
226 hSelMask = CreateBitmap(rectSel_src[2], rectSel_src[3], 1, 1, NULL);
227 DeleteObject(SelectObject(hSelDC, hSelMask));
228 ptStackCopy = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * (ptSP + 1));
229 for (i = 0; i <= ptSP; i++)
230 {
231 ptStackCopy[i].x = ptStack[i].x - rectSel_src[0];
232 ptStackCopy[i].y = ptStack[i].y - rectSel_src[1];
233 }
234 Poly(hSelDC, ptStackCopy, ptSP + 1, 0x00ffffff, 0x00ffffff, 1, 2, TRUE);
235 HeapFree(GetProcessHeap(), 0, ptStackCopy);
236 SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(rectSel_src[2], rectSel_src[3]));
237 resetToU1();
238 MaskBlt(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], hDrawingDC, rectSel_src[0],
239 rectSel_src[1], hSelMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS));
240 Poly(hdc, ptStack, ptSP + 1, bg, bg, 1, 2, TRUE);
241 newReversible();
242
243 placeSelWin();
244 ShowWindow(hSelection, SW_SHOW);
245 }
246 HeapFree(GetProcessHeap(), 0, ptStack);
247 ptStack = NULL;
248 break;
249 }
250 case 2:
251 resetToU1();
252 if ((rectSel_src[2] != 0) && (rectSel_src[3] != 0))
253 {
254 DeleteObject(hSelMask);
255 hSelMask = CreateBitmap(rectSel_src[2], rectSel_src[3], 1, 1, NULL);
256 DeleteObject(SelectObject(hSelDC, hSelMask));
257 Rect(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], 0x00ffffff, 0x00ffffff, 1, 2);
258 SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(rectSel_src[2], rectSel_src[3]));
259 resetToU1();
260 BitBlt(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], hDrawingDC, rectSel_src[0],
261 rectSel_src[1], SRCCOPY);
262 Rect(hdc, rectSel_src[0], rectSel_src[1], rectSel_src[0] + rectSel_src[2],
263 rectSel_src[1] + rectSel_src[3], bgColor, bgColor, 0, TRUE);
264 newReversible();
265
266 placeSelWin();
267 ShowWindow(hSelection, SW_SHOW);
268 }
269 break;
270 case 3:
271 Erase(hdc, lastX, lastY, x, y, bg, rubberRadius);
272 break;
273 case 7:
274 Line(hdc, lastX, lastY, x, y, fg, 1);
275 SetPixel(hdc, x, y, fg);
276 break;
277 case 11:
278 resetToU1();
279 Line(hdc, startX, startY, x, y, fg, lineWidth);
280 break;
281 case 12:
282 pointSP++;
283 if (pointSP == 4)
284 pointSP = 0;
285 break;
286 case 13:
287 resetToU1();
288 Rect(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
289 break;
290 case 14:
291 resetToU1();
292 pointStack[pointSP].x = x;
293 pointStack[pointSP].y = y;
294 pointSP++;
295 if (pointSP >= 2)
296 {
297 if ((pointStack[0].x - x) * (pointStack[0].x - x) +
298 (pointStack[0].y - y) * (pointStack[0].y - y) <= lineWidth * lineWidth + 1)
299 {
300 Poly(hdc, pointStack, pointSP, fg, bg, lineWidth, shapeStyle, TRUE);
301 pointSP = 0;
302 }
303 else
304 {
305 Poly(hdc, pointStack, pointSP, fg, bg, lineWidth, shapeStyle, FALSE);
306 }
307 }
308 if (pointSP == 255)
309 pointSP--;
310 break;
311 case 15:
312 resetToU1();
313 Ellp(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
314 break;
315 case 16:
316 resetToU1();
317 RRect(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
318 break;
319 }
320 }
321
322 void
323 startPaintingR(HDC hdc, short x, short y, int fg, int bg)
324 {
325 startX = x;
326 startY = y;
327 lastX = x;
328 lastY = y;
329 switch (activeTool)
330 {
331 case 1:
332 case 10:
333 case 11:
334 case 13:
335 case 15:
336 case 16:
337 newReversible();
338 break;
339 case 3:
340 newReversible();
341 Replace(hdc, x, y, x, y, fg, bg, rubberRadius);
342 break;
343 case 4:
344 newReversible();
345 Fill(hdc, x, y, bg);
346 break;
347 case 7:
348 newReversible();
349 SetPixel(hdc, x, y, bg);
350 break;
351 case 8:
352 newReversible();
353 Brush(hdc, x, y, x, y, bg, brushStyle);
354 break;
355 case 9:
356 newReversible();
357 Airbrush(hdc, x, y, bg, airBrushWidth);
358 break;
359 case 12:
360 pointStack[pointSP].x = x;
361 pointStack[pointSP].y = y;
362 if (pointSP == 0)
363 {
364 newReversible();
365 pointSP++;
366 }
367 break;
368 case 14:
369 pointStack[pointSP].x = x;
370 pointStack[pointSP].y = y;
371 if (pointSP + 1 >= 2)
372 Poly(hdc, pointStack, pointSP + 1, bg, fg, lineWidth, shapeStyle, FALSE);
373 if (pointSP == 0)
374 {
375 newReversible();
376 pointSP++;
377 }
378 break;
379 }
380 }
381
382 void
383 whilePaintingR(HDC hdc, short x, short y, int fg, int bg)
384 {
385 switch (activeTool)
386 {
387 case 3:
388 Replace(hdc, lastX, lastY, x, y, fg, bg, rubberRadius);
389 break;
390 case 7:
391 Line(hdc, lastX, lastY, x, y, bg, 1);
392 break;
393 case 8:
394 Brush(hdc, lastX, lastY, x, y, bg, brushStyle);
395 break;
396 case 9:
397 Airbrush(hdc, x, y, bg, airBrushWidth);
398 break;
399 case 11:
400 resetToU1();
401 Line(hdc, startX, startY, x, y, bg, lineWidth);
402 break;
403 case 12:
404 resetToU1();
405 pointStack[pointSP].x = x;
406 pointStack[pointSP].y = y;
407 switch (pointSP)
408 {
409 case 1:
410 Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, bg,
411 lineWidth);
412 break;
413 case 2:
414 Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], bg, lineWidth);
415 break;
416 case 3:
417 Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], bg, lineWidth);
418 break;
419 }
420 break;
421 case 13:
422 resetToU1();
423 Rect(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
424 break;
425 case 14:
426 resetToU1();
427 pointStack[pointSP].x = x;
428 pointStack[pointSP].y = y;
429 if (pointSP + 1 >= 2)
430 Poly(hdc, pointStack, pointSP + 1, bg, fg, lineWidth, shapeStyle, FALSE);
431 break;
432 case 15:
433 resetToU1();
434 Ellp(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
435 break;
436 case 16:
437 resetToU1();
438 RRect(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
439 break;
440 }
441
442 lastX = x;
443 lastY = y;
444 }
445
446 void
447 endPaintingR(HDC hdc, short x, short y, int fg, int bg)
448 {
449 switch (activeTool)
450 {
451 case 3:
452 Replace(hdc, lastX, lastY, x, y, fg, bg, rubberRadius);
453 break;
454 case 7:
455 Line(hdc, lastX, lastY, x, y, bg, 1);
456 SetPixel(hdc, x, y, bg);
457 break;
458 case 11:
459 resetToU1();
460 Line(hdc, startX, startY, x, y, bg, lineWidth);
461 break;
462 case 12:
463 pointSP++;
464 if (pointSP == 4)
465 pointSP = 0;
466 break;
467 case 13:
468 resetToU1();
469 Rect(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
470 break;
471 case 14:
472 resetToU1();
473 pointStack[pointSP].x = x;
474 pointStack[pointSP].y = y;
475 pointSP++;
476 if (pointSP >= 2)
477 {
478 if ((pointStack[0].x - x) * (pointStack[0].x - x) +
479 (pointStack[0].y - y) * (pointStack[0].y - y) <= lineWidth * lineWidth + 1)
480 {
481 Poly(hdc, pointStack, pointSP, bg, fg, lineWidth, shapeStyle, TRUE);
482 pointSP = 0;
483 }
484 else
485 {
486 Poly(hdc, pointStack, pointSP, bg, fg, lineWidth, shapeStyle, FALSE);
487 }
488 }
489 if (pointSP == 255)
490 pointSP--;
491 break;
492 case 15:
493 resetToU1();
494 Ellp(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
495 break;
496 case 16:
497 resetToU1();
498 RRect(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
499 break;
500 }
501 }