1 /* vim:expandtab:ts=2 sw=2:
2 */
3 /*  Grafx2 - The Ultimate 256-color bitmap paint program
4 
5 	Copyright owned by various GrafX2 authors, see COPYRIGHT.txt for details.
6 
7     Grafx2 is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; version 2
10     of the License.
11 
12     Grafx2 is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with Grafx2; if not, see <http://www.gnu.org/licenses/>
19 */
20 #include <math.h>
21 #include <string.h>
22 #include <stdlib.h>
23 
24 #include "const.h"
25 #include "struct.h"
26 #include "global.h"
27 #include "misc.h"
28 #include "osdep.h"
29 #include "engine.h"
30 #include "graph.h"
31 #include "operatio.h"
32 #include "buttons.h"
33 #include "pages.h"
34 #include "errors.h"
35 #include "screen.h"
36 #include "brush.h"
37 #include "windows.h"
38 #include "input.h"
39 #include "special.h"
40 #include "tiles.h"
41 #include "keyboard.h"
42 
43 // PI is NOT part of math.h according to C standards...
44 #if defined(__GP2X__) || defined(__VBCC__)
45     #define M_PI 3.14159265358979323846
46 #endif
47 
48 /// Time (in SDL ticks) when the next airbrush drawing should be done. Also used
49 /// for discontinuous freehand drawing.
50 dword Airbrush_next_time;
51 
52 // Panning needs its own operation storage because it may interrupt another
53 // interrupting operation
54 static enum OPERATIONS Operation_before_pan;
55 
Start_operation_stack(word new_operation)56 void Start_operation_stack(word new_operation)
57 {
58   // This part handles things that must be done when exiting an operation.
59   Brush_rotation_center_is_defined=0;
60   switch(Current_operation)
61   {
62     case OPERATION_ROTATE_BRUSH:
63       End_brush_rotation();
64     break;
65 
66     default:
67     break;
68   }
69 
70   // On mémorise l'opération précédente si on démarre une interruption
71   switch(new_operation)
72   {
73     case OPERATION_MAGNIFY:
74     case OPERATION_COLORPICK:
75     case OPERATION_RMB_COLORPICK:
76     case OPERATION_GRAB_BRUSH:
77     case OPERATION_POLYBRUSH:
78     case OPERATION_STRETCH_BRUSH:
79       Operation_before_interrupt=Current_operation;
80       // On passe à l'operation demandée
81       Current_operation=new_operation;
82       break;
83     case OPERATION_PAN_VIEW:
84       // Use separate operation-before storage for panning
85       Operation_before_pan=Current_operation;
86       // On passe à l'operation demandée
87       Current_operation=new_operation;
88       break;
89     case OPERATION_ROTATE_BRUSH:
90       Begin_brush_rotation();
91       Operation_before_interrupt=Current_operation;
92       // On passe à l'operation demandée
93       Current_operation=new_operation;
94       break;
95     default :
96       // On passe à l'operation demandée
97       Current_operation=new_operation;
98       Operation_before_interrupt=Current_operation;
99   }
100 
101   // On spécifie si l'opération autorise le changement de couleur au clavier
102   switch(new_operation)
103   {
104     case OPERATION_CONTINUOUS_DRAW:
105     case OPERATION_DISCONTINUOUS_DRAW:
106     case OPERATION_AIRBRUSH:
107     case OPERATION_CENTERED_LINES:
108       Allow_color_change_during_operation=1;
109       break;
110     default :
111       Allow_color_change_during_operation=0;
112   }
113 
114   // Et on passe au curseur qui va avec
115   Cursor_shape=CURSOR_FOR_OPERATION[new_operation];
116   Operation_stack_size=0;
117 }
118 
119 
Init_start_operation(void)120 void Init_start_operation(void)
121 {
122   Operation_in_magnifier=(Mouse_X>=Main.X_zoom);
123   Smear_start=1;
124 }
125 
126 
Operation_push(short value)127 void Operation_push(short value)
128 {
129   Operation_stack[++Operation_stack_size]=value;
130 }
131 
132 
Operation_pop(short * value)133 void Operation_pop(short * value)
134 {
135   *value=Operation_stack[Operation_stack_size--];
136 }
137 
138 
139 byte Paintbrush_shape_before_operation;
140 byte Paintbrush_hidden_before_scroll;
141 
142 
143 
Distance(short x1,short y1,short x2,short y2)144 short Distance(short x1, short y1, short x2, short y2)
145 {
146   short x2_moins_x1=x2-x1;
147   short y2_minus_y1=y2-y1;
148 
149   return Round( sqrt( (x2_moins_x1*x2_moins_x1) + (y2_minus_y1*y2_minus_y1) ) );
150 }
151 
152 
Display_coords_rel_or_abs(short start_x,short start_y)153 void Display_coords_rel_or_abs(short start_x, short start_y)
154 {
155   char str[6];
156 
157   if (Config.Coords_rel)
158   {
159     if (Menu_is_visible)
160     {
161       if (Paintbrush_X>start_x)
162       {
163         Num2str(Paintbrush_X-start_x,str,5);
164         str[0]='+';
165       }
166       else if (Paintbrush_X<start_x)
167       {
168         Num2str(start_x-Paintbrush_X,str,5);
169         str[0]='-';
170       }
171       else
172         strcpy(str,"\xb1   0");
173       Print_in_menu(str,2);
174 
175       if (Paintbrush_Y>start_y)
176       {
177         Num2str(Paintbrush_Y-start_y,str,5);
178         str[0]='+';
179       }
180       else if (Paintbrush_Y<start_y)
181       {
182         Num2str(start_y-Paintbrush_Y,str,5);
183         str[0]='-';
184       }
185       else
186         strcpy(str,"\xb1   0");
187       Print_in_menu(str,12);
188     }
189   }
190   else
191     Print_coordinates();
192 }
193 
194 //////////////////////////////////////////////////// OPERATION_CONTINUOUS_DRAW
195 
Freehand_mode1_1_0(void)196 void Freehand_mode1_1_0(void)
197 //  Opération   : OPERATION_CONTINUOUS_DRAW
198 //  Click Souris: 1
199 //  Taille_Pile : 0
200 //
201 //  Souris effacée: Oui
202 {
203   Init_start_operation();
204   Backup();
205   Shade_table=Shade_table_left;
206   // On affiche définitivement le pinceau
207   Draw_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color);
208   Operation_push(Paintbrush_X);
209   Operation_push(Paintbrush_Y);
210 }
211 
212 
Freehand_mode1_1_2(void)213 void Freehand_mode1_1_2(void)
214 //  Opération   : OPERATION_CONTINUOUS_DRAW
215 //  Click Souris: 1
216 //  Taille_Pile : 2
217 //
218 //  Souris effacée: Non
219 {
220   short start_x;
221   short start_y;
222 
223   Operation_pop(&start_y);
224   Operation_pop(&start_x);
225 
226   if ( (start_y!=Paintbrush_Y) || (start_x!=Paintbrush_X) )
227   {
228     Hide_cursor();
229     Print_coordinates();
230     Draw_line_permanent(start_x,start_y,Paintbrush_X,Paintbrush_Y,Fore_color);
231     Display_cursor();
232   }
233 
234   Operation_push(Paintbrush_X);
235   Operation_push(Paintbrush_Y);
236 }
237 
238 
Freehand_mode12_0_2(void)239 void Freehand_mode12_0_2(void)
240 //  Opération   : OPERATION_DESSIN_[DIS]CONTINU
241 //  Click Souris: 0
242 //  Taille_Pile : 2
243 //
244 //  Souris effacée: Non
245 {
246   Operation_stack_size=0;
247   End_of_modification();
248 }
249 
250 
Freehand_mode1_2_0(void)251 void Freehand_mode1_2_0(void)
252 //  Opération   : OPERATION_CONTINUOUS_DRAW
253 //  Click Souris: 2
254 //  Taille_Pile : 0
255 //
256 //  Souris effacée: Oui
257 {
258   if (Rightclick_colorpick(0))
259     return;
260 
261   Init_start_operation();
262   Backup();
263   Shade_table=Shade_table_right;
264   // On affiche définitivement le pinceau
265   Draw_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color);
266   Operation_push(Paintbrush_X);
267   Operation_push(Paintbrush_Y);
268 }
269 
270 
Freehand_mode1_2_2(void)271 void Freehand_mode1_2_2(void)
272 //  Opération   : OPERATION_CONTINUOUS_DRAW
273 //  Click Souris: 2
274 //  Taille_Pile : 2
275 //
276 //  Souris effacée: Non
277 {
278   short start_x;
279   short start_y;
280 
281   Operation_pop(&start_y);
282   Operation_pop(&start_x);
283 
284   if ( (start_y!=Paintbrush_Y) || (start_x!=Paintbrush_X) )
285   {
286     Print_coordinates();
287     Hide_cursor();
288     Draw_line_permanent(start_x,start_y,Paintbrush_X,Paintbrush_Y,Back_color);
289     Display_cursor();
290   }
291 
292   Operation_push(Paintbrush_X);
293   Operation_push(Paintbrush_Y);
294 }
295 
296 
297 ///////////////////////////////////////////////// OPERATION_DISCONTINUOUS_DRAW
298 
Freehand_mode2_1_0(void)299 void Freehand_mode2_1_0(void)
300 //  Opération   : OPERATION_DISCONTINUOUS_DRAW
301 //  Click Souris: 1
302 //  Taille_Pile : 0
303 //
304 //  Souris effacée: Oui
305 {
306   Init_start_operation();
307   Backup();
308   Shade_table=Shade_table_left;
309   // On affiche définitivement le pinceau
310   Draw_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color);
311   Operation_push(Paintbrush_X);
312   Operation_push(Paintbrush_Y);
313   Print_coordinates();
314   Airbrush_next_time = GFX2_GetTicks() + Airbrush_delay*10;
315 }
316 
317 
Freehand_mode2_1_2(void)318 void Freehand_mode2_1_2(void)
319 //  Opération   : OPERATION_DISCONTINUOUS_DRAW
320 //  Click Souris: 1
321 //  Taille_Pile : 2
322 //
323 //  Souris effacée: Non
324 {
325   short start_x;
326   short start_y;
327 
328   Operation_pop(&start_y);
329   Operation_pop(&start_x);
330 
331   if ( (start_x!=Paintbrush_X) || (start_y!=Paintbrush_Y) )
332   {
333     Print_coordinates();
334     if (GFX2_GetTicks()>Airbrush_next_time)
335     {
336       Airbrush_next_time+=Airbrush_delay*10;
337       Hide_cursor();
338       // On affiche définitivement le pinceau
339       Draw_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color);
340       Display_cursor();
341     }
342   }
343 
344   Operation_push(Paintbrush_X);
345   Operation_push(Paintbrush_Y);
346 }
347 
348 // ----------
349 
Freehand_mode2_2_0(void)350 void Freehand_mode2_2_0(void)
351 //  Opération   : OPERATION_DISCONTINUOUS_DRAW
352 //  Click Souris: 2
353 //  Taille_Pile : 0
354 //
355 //  Souris effacée: Oui
356 {
357   if (Rightclick_colorpick(0))
358     return;
359 
360   Init_start_operation();
361   Backup();
362   Shade_table=Shade_table_right;
363   Operation_push(Paintbrush_X);
364   Operation_push(Paintbrush_Y);
365   Print_coordinates();
366   Airbrush_next_time = GFX2_GetTicks() + Airbrush_delay*10;
367   // On affiche définitivement le pinceau
368   Draw_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color);
369 }
370 
371 
Freehand_mode2_2_2(void)372 void Freehand_mode2_2_2(void)
373 //  Opération   : OPERATION_DISCONTINUOUS_DRAW
374 //  Click Souris: 2
375 //  Taille_Pile : 2
376 //
377 //  Souris effacée: Non
378 {
379   short start_x;
380   short start_y;
381 
382   Operation_pop(&start_y);
383   Operation_pop(&start_x);
384 
385   if ( (start_x!=Paintbrush_X) || (start_y!=Paintbrush_Y) )
386   {
387     Print_coordinates();
388     if (GFX2_GetTicks()>Airbrush_next_time)
389     {
390       Airbrush_next_time+=Airbrush_delay*10;
391       Hide_cursor();
392       // On affiche définitivement le pinceau
393       Draw_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color);
394       Display_cursor();
395     }
396   }
397 
398   Operation_push(Paintbrush_X);
399   Operation_push(Paintbrush_Y);
400 }
401 
402 
403 ////////////////////////////////////////////////////// OPERATION_POINT_DRAW
404 
Freehand_mode3_1_0(void)405 void Freehand_mode3_1_0(void)
406 //  Opération   : OPERATION_POINT_DRAW
407 //  Click Souris: 1
408 //  Taille_Pile : 0
409 //
410 //  Souris effacée: Oui
411 {
412   Init_start_operation();
413   Backup();
414   Shade_table=Shade_table_left;
415   // On affiche définitivement le pinceau
416   Draw_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color);
417   Operation_push(0);  // On change simplement l'état de la pile...
418 }
419 
420 
Freehand_Mode3_2_0(void)421 void Freehand_Mode3_2_0(void)
422 //  Opération   : OPERATION_POINT_DRAW
423 //  Click Souris: 2
424 //  Taille_Pile : 0
425 //
426 //  Souris effacée: Oui
427 {
428   if (Rightclick_colorpick(0))
429     return;
430 
431   Init_start_operation();
432   Backup();
433   Shade_table=Shade_table_right;
434   // On affiche définitivement le pinceau
435   Draw_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color);
436   Operation_push(0);  // On change simplement l'état de la pile...
437 }
438 
439 
Freehand_mode3_0_1(void)440 void Freehand_mode3_0_1(void)
441 //  Opération   : OPERATION_POINT_DRAW
442 //  Click Souris: 0
443 //  Taille_Pile : 1
444 //
445 //  Souris effacée: Non
446 {
447   End_of_modification();
448   Operation_stack_size--;
449 }
450 
451 
452 ///////////////////////////////////////////////////////////// OPERATION_LINE
453 
Line_12_0(void)454 void Line_12_0(void)
455 // Opération   : OPERATION_LINE
456 // Click Souris: 1 ou 2
457 // Taille_Pile : 0
458 //
459 //  Souris effacée: Oui
460 
461 //  Début du tracé d'une ligne (premier clic)
462 {
463   if (Rightclick_colorpick(0))
464     return;
465 
466   Init_start_operation();
467   Backup();
468   Paintbrush_shape_before_operation=Paintbrush_shape;
469   Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
470 
471   if (Mouse_K==LEFT_SIDE)
472   {
473     Shade_table=Shade_table_left;
474     Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Fore_color);
475     Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
476     Operation_push(Fore_color);
477   }
478   else
479   {
480     Shade_table=Shade_table_right;
481     Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Back_color);
482     Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
483     Operation_push(Back_color);
484   }
485 
486   if ((Config.Coords_rel) && (Menu_is_visible))
487     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
488 
489   Operation_push(Paintbrush_X);
490   Operation_push(Paintbrush_Y);
491   Operation_push(Paintbrush_X);
492   Operation_push(Paintbrush_Y);
493 }
494 
495 
Line_12_5(void)496 void Line_12_5(void)
497 // Opération   : OPERATION_LINE
498 // Click Souris: 1
499 // Taille_Pile : 5
500 //
501 // Souris effacée: Non
502 
503 // Poursuite du tracé d'une ligne (déplacement de la souris en gardant le
504 // curseur appuyé)
505 {
506   short start_x;
507   short start_y;
508   short end_x;
509   short end_y;
510 
511   short cursor_x;
512   short cursor_y;
513 
514   Operation_pop(&end_y);
515   Operation_pop(&end_x);
516   Operation_pop(&start_y);
517   Operation_pop(&start_x);
518 
519   cursor_x = Paintbrush_X;
520   cursor_y = Paintbrush_Y;
521 
522   // On corrige les coordonnées de la ligne si la touche shift est appuyée...
523   if(Get_Key_modifiers() & GFX2_MOD_SHIFT)
524     Clamp_coordinates_regular_angle(start_x,start_y,&cursor_x,&cursor_y);
525 
526   // On vient de bouger
527   if ((cursor_x!=end_x) || (cursor_y!=end_y))
528   {
529       Hide_cursor();
530 
531     Display_coords_rel_or_abs(start_x,start_y);
532 
533     Hide_line_preview(start_x,start_y,end_x,end_y);
534     if (Mouse_K==LEFT_SIDE)
535     {
536       Pixel_figure_preview (start_x,start_y,Fore_color);
537       Draw_line_preview (start_x,start_y,cursor_x,cursor_y,Fore_color);
538     }
539     else
540     {
541       Pixel_figure_preview (start_x,start_y,Back_color);
542       Draw_line_preview (start_x,start_y,cursor_x,cursor_y,Back_color);
543     }
544 
545     Operation_push(start_x);
546     Operation_push(start_y);
547     Operation_push(cursor_x);
548     Operation_push(cursor_y);
549 
550     Display_cursor();
551   }
552   else
553   {
554     Operation_push(start_x);
555     Operation_push(start_y);
556     Operation_push(end_x);
557     Operation_push(end_y);
558   }
559 }
560 
561 
Line_0_5(void)562 void Line_0_5(void)
563 // Opération   : OPERATION_LINE
564 // Click Souris: 0
565 // Taille_Pile : 5
566 //
567 // Souris effacée: Oui
568 
569 // End du tracé d'une ligne (relachage du bouton)
570 {
571   short start_x;
572   short start_y;
573   short end_x;
574   short end_y;
575   short color;
576 
577   Operation_pop(&end_y);
578   Operation_pop(&end_x);
579   Operation_pop(&start_y);
580   Operation_pop(&start_x);
581   Operation_pop(&color);
582 
583   Paintbrush_shape=Paintbrush_shape_before_operation;
584 
585   Pixel_figure_preview_auto  (start_x,start_y);
586   Hide_line_preview (start_x,start_y,end_x,end_y);
587   Draw_paintbrush            (start_x,start_y,color);
588   Draw_line_permanent(start_x,start_y,end_x,end_y,color);
589 
590   End_of_modification();
591   if ( (Config.Coords_rel) && (Menu_is_visible) )
592   {
593     Print_in_menu("X:       Y:             ",0);
594     Print_coordinates();
595   }
596 }
597 
598 
599 /////////////////////////////////////////////////////////// OPERATION_K_LINE
600 
601 
K_line_12_0(void)602 void K_line_12_0(void)
603 // Opération   : OPERATION_K_LINE
604 // Click Souris: 1 ou 2
605 // Taille_Pile : 0
606 //
607 //  Souris effacée: Oui
608 {
609   byte color;
610 
611   if (Rightclick_colorpick(0))
612     return;
613 
614   Init_start_operation();
615   Backup();
616   Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
617   Paintbrush_shape_before_operation=Paintbrush_shape;
618   Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
619 
620   color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
621 
622   // On place temporairement le début de la ligne qui ne s'afficherait pas sinon
623   Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color);
624 
625   if ((Config.Coords_rel) && (Menu_is_visible))
626     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
627 
628   Operation_push(Mouse_K | 0x80);
629   Operation_push(color);
630   Operation_push(Paintbrush_X);
631   Operation_push(Paintbrush_Y);
632   Operation_push(Paintbrush_X);
633   Operation_push(Paintbrush_Y);
634   // Taille de pile 6 : phase d'appui, non interruptible
635 }
636 
637 
K_line_12_6(void)638 void K_line_12_6(void)
639 // Opération   : OPERATION_K_LINE
640 // Click Souris: 1 ou 2 | 0
641 // Taille_Pile : 6      | 7
642 //
643 // Souris effacée: Non
644 {
645   short start_x;
646   short start_y;
647   short end_x;
648   short end_y;
649   short color;
650 
651   Operation_pop(&end_y);
652   Operation_pop(&end_x);
653 
654   if ((Paintbrush_X!=end_x) || (Paintbrush_Y!=end_y))
655   {
656     Hide_cursor();
657     Operation_pop(&start_y);
658     Operation_pop(&start_x);
659     Operation_pop(&color);
660 
661     Display_coords_rel_or_abs(start_x,start_y);
662 
663     Hide_line_preview(start_x,start_y,end_x,end_y);
664     Pixel_figure_preview (start_x,start_y,color);
665     Draw_line_preview (start_x,start_y,Paintbrush_X,Paintbrush_Y,color);
666 
667     Operation_push(color);
668     Operation_push(start_x);
669     Operation_push(start_y);
670     Display_cursor();
671   }
672 
673   Operation_push(Paintbrush_X);
674   Operation_push(Paintbrush_Y);
675 }
676 
677 
K_line_0_6(void)678 void K_line_0_6(void)
679 // Opération   : OPERATION_K_LINE
680 // Click Souris: 0
681 // Taille_Pile : 6
682 //
683 // Souris effacée: Oui
684 {
685   short start_x;
686   short start_y;
687   short end_x;
688   short end_y;
689   short color;
690   short direction;
691 
692   Operation_pop(&end_y);
693   Operation_pop(&end_x);
694   Operation_pop(&start_y);
695   Operation_pop(&start_x);
696   Operation_pop(&color);
697   Operation_pop(&direction);
698 
699   if ((Config.Coords_rel) && (Menu_is_visible))
700     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
701 
702   Pixel_figure_preview_auto  (start_x,start_y);
703   Hide_line_preview (start_x,start_y,end_x,end_y);
704   /* Doesn't work if fast moving
705   Pixel_figure_preview_xor (start_x,start_y, 0);
706   Draw_line_preview_xor (start_x,start_y,end_x,end_y,0);
707   */
708   Paintbrush_shape=Paintbrush_shape_before_operation;
709   if (direction & 0x80)
710   {
711     Draw_paintbrush(start_x,start_y,color);
712     direction=(direction & 0x7F);
713   }
714   Draw_line_permanent(start_x,start_y,Paintbrush_X,Paintbrush_Y,color);
715   Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
716 
717   Operation_push(direction);
718   Operation_push(direction); // Valeur bidon servant de nouvel état de pile
719   Operation_push(color);
720   Operation_push(Paintbrush_X);
721   Operation_push(Paintbrush_Y);
722   Operation_push(Paintbrush_X);
723   Operation_push(Paintbrush_Y);
724   // Taille de pile 7 : phase de "repos", interruptible (comme Elliot Ness :))
725 }
726 
727 
K_line_12_7(void)728 void K_line_12_7(void)
729 // Opération   : OPERATION_K_LINE
730 // Click Souris: 1 ou 2
731 // Taille_Pile : 7
732 //
733 // Souris effacée: Oui
734 {
735   short start_x;
736   short start_y;
737   short end_x;
738   short end_y;
739   short color;
740   short direction;
741 
742   Operation_pop(&end_y);
743   Operation_pop(&end_x);
744   Operation_pop(&start_y);
745   Operation_pop(&start_x);
746   Operation_pop(&color);
747   Operation_pop(&direction);
748   Operation_pop(&direction);
749 
750   if (direction==Mouse_K)
751   {
752     Operation_push(direction);
753     Operation_push(color);
754     Operation_push(start_x);
755     Operation_push(start_y);
756     Operation_push(end_x);
757     Operation_push(end_y);
758     // Taille de pile 6 : phase d'appui, non interruptible
759   }
760   else
761   {
762     // La série de ligne est terminée, il faut donc effacer la dernière
763     // preview de ligne
764     Pixel_figure_preview_auto  (start_x,start_y);
765     Hide_line_preview (start_x,start_y,end_x,end_y);
766 
767     Display_cursor();
768     Wait_end_of_click();
769     Hide_cursor();
770     Paintbrush_shape=Paintbrush_shape_before_operation;
771 
772     End_of_modification();
773     if ( (Config.Coords_rel) && (Menu_is_visible) )
774     {
775       Print_in_menu("X:       Y:             ",0);
776       Print_coordinates();
777     }
778   }
779 }
780 
781 /////////////////////////////////////////////////// OPERATION_RECTANGLE_?????
782 
Rectangle_12_0(void)783 void Rectangle_12_0(void)
784 // Opération   : OPERATION_EMPTY_RECTANGLE / OPERATION_FILLED_RECTANGLE
785 // Click Souris: 1 ou 2
786 // Taille_Pile : 0
787 //
788 // Souris effacée: Oui
789 {
790   if (Rightclick_colorpick(0))
791     return;
792 
793   Init_start_operation();
794 
795   if ((Config.Coords_rel) && (Menu_is_visible))
796     Print_in_menu("\035:   1   \022:   1",0);
797   // On laisse une trace du curseur à l'écran
798   Display_cursor();
799 
800   if (Mouse_K==LEFT_SIDE)
801   {
802     Shade_table=Shade_table_left;
803     Operation_push(Fore_color);
804   }
805   else
806   {
807     Shade_table=Shade_table_right;
808     Operation_push(Back_color);
809   }
810 
811   Operation_push(Paintbrush_X);
812   Operation_push(Paintbrush_Y);
813   Operation_push(Paintbrush_X);
814   Operation_push(Paintbrush_Y);
815 }
816 
817 
Rectangle_12_5(void)818 void Rectangle_12_5(void)
819 // Opération   : OPERATION_EMPTY_RECTANGLE / OPERATION_FILLED_RECTANGLE
820 // Click Souris: 1 ou 2
821 // Taille_Pile : 5
822 //
823 // Souris effacée: Non
824 {
825   short start_x;
826   short start_y;
827   short old_x;
828   short old_y;
829   char  str[5];
830 
831   Operation_pop(&old_y);
832   Operation_pop(&old_x);
833 
834   if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y))
835   {
836     Operation_pop(&start_y);
837     Operation_pop(&start_x);
838 
839     if ((Config.Coords_rel) && (Menu_is_visible))
840     {
841       Num2str(((start_x<Paintbrush_X)?Paintbrush_X-start_x:start_x-Paintbrush_X)+1,str,4);
842       Print_in_menu(str,2);
843       Num2str(((start_y<Paintbrush_Y)?Paintbrush_Y-start_y:start_y-Paintbrush_Y)+1,str,4);
844       Print_in_menu(str,11);
845     }
846     else
847       Print_coordinates();
848 
849     Operation_push(start_x);
850     Operation_push(start_y);
851   }
852 
853   Operation_push(Paintbrush_X);
854   Operation_push(Paintbrush_Y);
855 }
856 
857 
Empty_rectangle_0_5(void)858 void Empty_rectangle_0_5(void)
859 // Opération   : OPERATION_EMPTY_RECTANGLE
860 // Click Souris: 0
861 // Taille_Pile : 5
862 //
863 // Souris effacée: Oui
864 {
865   short old_paintbrush_x;
866   short old_paintbrush_y;
867   short color;
868 
869   // On mémorise la position courante du pinceau:
870 
871   old_paintbrush_x=Paintbrush_X;
872   old_paintbrush_y=Paintbrush_Y;
873 
874   // On lit l'ancienne position du pinceau:
875 
876   Operation_pop(&Paintbrush_Y);
877   Operation_pop(&Paintbrush_X);
878   Operation_pop(&Paintbrush_Y);
879   Operation_pop(&Paintbrush_X);
880 
881   // On va devoir effacer l'ancien curseur qu'on a laissé trainer:
882   Hide_cursor();
883 
884   // On lit la couleur du rectangle:
885   Operation_pop(&color);
886 
887   // On fait un petit backup de l'image:
888   Backup();
889 
890   // Et on trace le rectangle:
891   Draw_empty_rectangle(Paintbrush_X,Paintbrush_Y,old_paintbrush_x,old_paintbrush_y,color);
892 
893   // Enfin, on rétablit la position du pinceau:
894   Paintbrush_X=old_paintbrush_x;
895   Paintbrush_Y=old_paintbrush_y;
896 
897   End_of_modification();
898 
899   if ((Config.Coords_rel) && (Menu_is_visible))
900     Print_in_menu("X:       Y:",0);
901   Print_coordinates();
902 }
903 
904 
Filled_rectangle_0_5(void)905 void Filled_rectangle_0_5(void)
906 // Opération   : OPERATION_FILLED_RECTANGLE
907 // Click Souris: 0
908 // Taille_Pile : 5
909 //
910 // Souris effacée: Oui
911 {
912   short old_paintbrush_x;
913   short old_paintbrush_y;
914   short color;
915 
916   // On mémorise la position courante du pinceau:
917 
918   old_paintbrush_x=Paintbrush_X;
919   old_paintbrush_y=Paintbrush_Y;
920 
921   // On lit l'ancienne position du pinceau:
922 
923   Operation_pop(&Paintbrush_Y);
924   Operation_pop(&Paintbrush_X);
925   Operation_pop(&Paintbrush_Y);
926   Operation_pop(&Paintbrush_X);
927 
928   // On va devoir effacer l'ancien curseur qu'on a laissé trainer:
929   Hide_cursor();
930 
931   // On lit la couleur du rectangle:
932   Operation_pop(&color);
933 
934   // On fait un petit backup de l'image:
935   Backup();
936 
937   // Et on trace le rectangle:
938   Draw_filled_rectangle(Paintbrush_X,Paintbrush_Y,old_paintbrush_x,old_paintbrush_y,color);
939 
940   // Enfin, on rétablit la position du pinceau:
941   Paintbrush_X=old_paintbrush_x;
942   Paintbrush_Y=old_paintbrush_y;
943 
944   End_of_modification();
945   if ( (Config.Coords_rel) && (Menu_is_visible) )
946   {
947     Print_in_menu("X:       Y:",0);
948     Print_coordinates();
949   }
950 }
951 
952 
953 ////////////////////////////////////////////////////// OPERATION_CERCLE_?????
954 
955 
Circle_12_0(void)956 void Circle_12_0(void)
957 //
958 // Opération   : OPERATION_EMPTY_CIRCLE / OPERATION_FILLED_CIRCLE
959 // Click Souris: 1 ou 2
960 // Taille_Pile : 0
961 //
962 // Souris effacée: Oui
963 {
964   if (Rightclick_colorpick(0))
965     return;
966 
967   Init_start_operation();
968   Backup();
969 
970   Paintbrush_shape_before_operation=Paintbrush_shape;
971   Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
972 
973   if (Mouse_K==LEFT_SIDE)
974   {
975     Shade_table=Shade_table_left;
976     Operation_push(Fore_color);
977   }
978   else
979   {
980     Shade_table=Shade_table_right;
981     Operation_push(Back_color);
982   }
983 
984   if ((Config.Coords_rel) && (Menu_is_visible))
985     Print_in_menu("Radius:   0    ",0);
986 
987   Operation_push(Paintbrush_X);
988   Operation_push(Paintbrush_Y);
989   Operation_push(Paintbrush_X);
990   Operation_push(Paintbrush_Y);
991 }
992 
993 
Circle_12_5(void)994 void Circle_12_5(void)
995 //
996 // Opération   : OPERATION_EMPTY_CIRCLE / OPERATION_FILLED_CIRCLE
997 // Click Souris: 1 ou 2
998 // Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
999 //
1000 // Souris effacée: Non
1001 //
1002 {
1003   short tangent_x;
1004   short tangent_y;
1005   short center_x;
1006   short center_y;
1007   short color;
1008   long limit;
1009   char  str[5];
1010 
1011   Operation_pop(&tangent_y);
1012   Operation_pop(&tangent_x);
1013   Operation_pop(&center_y);
1014   Operation_pop(&center_x);
1015   Operation_pop(&color);
1016 
1017   if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) )
1018   {
1019     Hide_cursor();
1020     Cursor_shape=CURSOR_SHAPE_TARGET;
1021     if ((Config.Coords_rel) && (Menu_is_visible))
1022     {
1023       Num2str(Distance(center_x,center_y,Paintbrush_X,Paintbrush_Y),str,4);
1024       Print_in_menu(str,7);
1025     }
1026     else
1027       Print_coordinates();
1028 
1029     limit=((tangent_x-center_x)*(tangent_x-center_x))+
1030            ((tangent_y-center_y)*(tangent_y-center_y));
1031     Hide_empty_circle_preview(center_x,center_y,limit);
1032 
1033     limit=((Paintbrush_X-center_x)*(Paintbrush_X-center_x))+
1034            ((Paintbrush_Y-center_y)*(Paintbrush_Y-center_y));
1035     Draw_empty_circle_preview(center_x,center_y,limit,color);
1036 
1037     Display_cursor();
1038   }
1039 
1040   Operation_push(color);
1041   Operation_push(center_x);
1042   Operation_push(center_y);
1043   Operation_push(Paintbrush_X);
1044   Operation_push(Paintbrush_Y);
1045 }
1046 
1047 
Empty_circle_0_5(void)1048 void Empty_circle_0_5(void)
1049 //
1050 // Opération   : OPERATION_EMPTY_CIRCLE
1051 // Click Souris: 0
1052 // Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
1053 //
1054 // Souris effacée: Oui
1055 //
1056 {
1057   short tangent_x;
1058   short tangent_y;
1059   short center_x;
1060   short center_y;
1061   short color;
1062   long limit;
1063 
1064   Operation_pop(&tangent_y);
1065   Operation_pop(&tangent_x);
1066   Operation_pop(&center_y);
1067   Operation_pop(&center_x);
1068   Operation_pop(&color);
1069 
1070   limit=((tangent_x-center_x)*(tangent_x-center_x))+
1071          ((tangent_y-center_y)*(tangent_y-center_y));
1072   Hide_empty_circle_preview(center_x,center_y,limit);
1073 
1074   Paintbrush_shape=Paintbrush_shape_before_operation;
1075 
1076   Draw_empty_circle_permanent(center_x,center_y,limit,color);
1077 
1078   End_of_modification();
1079 
1080   if ( (Config.Coords_rel) && (Menu_is_visible) )
1081   {
1082     Print_in_menu("X:       Y:",0);
1083     Print_coordinates();
1084   }
1085   Cursor_shape=CURSOR_SHAPE_XOR_TARGET;
1086 }
1087 
1088 
Filled_circle_0_5(void)1089 void Filled_circle_0_5(void)
1090 //
1091 // Opération   : OPERATION_FILLED_CIRCLE
1092 // Click Souris: 0
1093 // Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
1094 //
1095 // Souris effacée: Oui
1096 //
1097 {
1098   short tangent_x;
1099   short tangent_y;
1100   short center_x;
1101   short center_y;
1102   short color;
1103   long limit;
1104 
1105   Operation_pop(&tangent_y);
1106   Operation_pop(&tangent_x);
1107   Operation_pop(&center_y);
1108   Operation_pop(&center_x);
1109   Operation_pop(&color);
1110 
1111   limit=((tangent_x-center_x)*(tangent_x-center_x))+
1112          ((tangent_y-center_y)*(tangent_y-center_y));
1113   Hide_empty_circle_preview(center_x,center_y,limit);
1114 
1115   Paintbrush_shape=Paintbrush_shape_before_operation;
1116 
1117   Draw_filled_circle(center_x,center_y,limit,color);
1118 
1119   End_of_modification();
1120   if ( (Config.Coords_rel) && (Menu_is_visible) )
1121   {
1122     Print_in_menu("X:       Y:",0);
1123     Print_coordinates();
1124   }
1125   Cursor_shape=CURSOR_SHAPE_XOR_TARGET;
1126 }
1127 
1128 
1129 ///////////////////////////////////////////////////// OPERATION_ELLIPSE_?????
1130 
1131 
Ellipse_12_0(void)1132 void Ellipse_12_0(void)
1133 //
1134 // Opération   : OPERATION_EMPTY_ELLIPSE / OPERATION_FILLED_ELLIPSE
1135 // Click Souris: 1 ou 2
1136 // Taille_Pile : 0
1137 //
1138 // Souris effacée: Oui
1139 {
1140   if (Rightclick_colorpick(0))
1141     return;
1142 
1143   Init_start_operation();
1144   Backup();
1145 
1146   Paintbrush_shape_before_operation=Paintbrush_shape;
1147   Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
1148 
1149   if (Mouse_K==LEFT_SIDE)
1150   {
1151     Shade_table=Shade_table_left;
1152     Operation_push(Fore_color);
1153   }
1154   else
1155   {
1156     Shade_table=Shade_table_right;
1157     Operation_push(Back_color);
1158   }
1159 
1160   if ((Config.Coords_rel) && (Menu_is_visible))
1161     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
1162 
1163   Operation_push(Paintbrush_X);
1164   Operation_push(Paintbrush_Y);
1165   Operation_push(Paintbrush_X);
1166   Operation_push(Paintbrush_Y);
1167 }
1168 
1169 
Ellipse_12_5(void)1170 void Ellipse_12_5(void)
1171 //
1172 // Opération   : OPERATION_EMPTY_ELLIPSE / OPERATION_FILLED_ELLIPSE
1173 // Click Souris: 1 ou 2
1174 // Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
1175 //
1176 // Souris effacée: Non
1177 //
1178 {
1179   short tangent_x;
1180   short tangent_y;
1181   short center_x;
1182   short center_y;
1183   short color;
1184   short horizontal_radius;
1185   short vertical_radius;
1186 
1187   Operation_pop(&tangent_y);
1188   Operation_pop(&tangent_x);
1189   Operation_pop(&center_y);
1190   Operation_pop(&center_x);
1191   Operation_pop(&color);
1192 
1193 
1194   if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) )
1195   {
1196     Hide_cursor();
1197     Display_coords_rel_or_abs(center_x,center_y);
1198 
1199     if ((Selected_circle_ellipse_mode & MASK_CENTER_CORNERS) == MODE_CENTER)
1200     {
1201       Cursor_shape=CURSOR_SHAPE_TARGET;
1202       horizontal_radius=(tangent_x>center_x)?tangent_x-center_x
1203                                              :center_x-tangent_x;
1204       vertical_radius  =(tangent_y>center_y)?tangent_y-center_y
1205                                              :center_y-tangent_y;
1206       Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius);
1207 
1208       horizontal_radius=(Paintbrush_X>center_x)?Paintbrush_X-center_x
1209                                            :center_x-Paintbrush_X;
1210       vertical_radius  =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y
1211                                            :center_y-Paintbrush_Y;
1212       Draw_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color);
1213     }
1214     else
1215     {
1216       Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y);
1217       Draw_empty_inscribed_ellipse_preview(center_x,center_y,Paintbrush_X,Paintbrush_Y,color);
1218     }
1219 
1220     Display_cursor();
1221   }
1222 
1223   Operation_push(color);
1224   Operation_push(center_x);
1225   Operation_push(center_y);
1226   Operation_push(Paintbrush_X);
1227   Operation_push(Paintbrush_Y);
1228 }
1229 
1230 
Empty_ellipse_0_5(void)1231 void Empty_ellipse_0_5(void)
1232 //
1233 // Opération   : OPERATION_EMPTY_ELLIPSE
1234 // Click Souris: 0
1235 // Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
1236 //
1237 // Souris effacée: Oui
1238 //
1239 {
1240   short tangent_x;
1241   short tangent_y;
1242   short center_x;
1243   short center_y;
1244   short color;
1245   short horizontal_radius;
1246   short vertical_radius;
1247 
1248   Operation_pop(&tangent_y);
1249   Operation_pop(&tangent_x);
1250   Operation_pop(&center_y);
1251   Operation_pop(&center_x);
1252   Operation_pop(&color);
1253 
1254   if ((Selected_circle_ellipse_mode & MASK_CENTER_CORNERS) == MODE_CENTER)
1255   {
1256     horizontal_radius=(tangent_x>center_x)?tangent_x-center_x
1257                                            :center_x-tangent_x;
1258     vertical_radius  =(tangent_y>center_y)?tangent_y-center_y
1259                                            :center_y-tangent_y;
1260     Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius);
1261     Paintbrush_shape=Paintbrush_shape_before_operation;
1262     Draw_empty_ellipse_permanent(center_x,center_y,horizontal_radius,vertical_radius,color);
1263   }
1264   else
1265   {
1266     Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y);
1267     Paintbrush_shape=Paintbrush_shape_before_operation;
1268     Draw_empty_inscribed_ellipse_permanent(center_x,center_y,tangent_x,tangent_y,color);
1269   }
1270 
1271   End_of_modification();
1272 
1273   if ( (Config.Coords_rel) && (Menu_is_visible) )
1274   {
1275     Print_in_menu("X:       Y:             ",0);
1276     Print_coordinates();
1277   }
1278   Cursor_shape=CURSOR_SHAPE_XOR_TARGET;
1279 }
1280 
1281 
Filled_ellipse_0_5(void)1282 void Filled_ellipse_0_5(void)
1283 //
1284 // Opération   : OPERATION_FILLED_ELLIPSE
1285 // Click Souris: 0
1286 // Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
1287 //
1288 // Souris effacée: Oui
1289 //
1290 {
1291   short tangent_x;
1292   short tangent_y;
1293   short center_x;
1294   short center_y;
1295   short color;
1296   short horizontal_radius;
1297   short vertical_radius;
1298 
1299   Operation_pop(&tangent_y);
1300   Operation_pop(&tangent_x);
1301   Operation_pop(&center_y);
1302   Operation_pop(&center_x);
1303   Operation_pop(&color);
1304 
1305   if ((Selected_circle_ellipse_mode & MASK_CENTER_CORNERS) == MODE_CENTER)
1306   {
1307     horizontal_radius=(tangent_x>center_x)?tangent_x-center_x
1308                                            :center_x-tangent_x;
1309     vertical_radius  =(tangent_y>center_y)?tangent_y-center_y
1310                                            :center_y-tangent_y;
1311     Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius);
1312     Paintbrush_shape=Paintbrush_shape_before_operation;
1313     Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,color);
1314   }
1315   else
1316   {
1317     Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y);
1318     Paintbrush_shape=Paintbrush_shape_before_operation;
1319     Draw_filled_inscribed_ellipse(center_x,center_y,tangent_x,tangent_y,color);
1320   }
1321 
1322   End_of_modification();
1323   if ( (Config.Coords_rel) && (Menu_is_visible) )
1324   {
1325     Print_in_menu("X:       Y:             ",0);
1326     Print_coordinates();
1327   }
1328   Cursor_shape=CURSOR_SHAPE_XOR_TARGET;
1329 }
1330 
1331 
1332 ////////////////////////////////////////////////////////////// OPERATION_FILL
1333 
1334 
Fill_1_0(void)1335 void Fill_1_0(void)
1336 //
1337 // Opération   : OPERATION_FILL
1338 // Click Souris: 1
1339 // Taille_Pile : 0
1340 //
1341 // Souris effacée: Oui
1342 //
1343 {
1344   Hide_cursor();
1345   // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas
1346   // le Fill, et on se fout de savoir si on est dans la partie gauche ou
1347   // droite de la loupe.
1348   // On ne s'occupe pas de faire un Backup: c'est "Fill_general" qui s'en charge.
1349   Shade_table=Shade_table_left;
1350   Fill_general(Fore_color);
1351   Display_cursor();
1352   End_of_modification();
1353   Wait_end_of_click();
1354 }
1355 
1356 
Fill_2_0(void)1357 void Fill_2_0(void)
1358 //
1359 // Opération   : OPERATION_FILL
1360 // Click Souris: 2
1361 // Taille_Pile : 0
1362 //
1363 // Souris effacée: Non
1364 //
1365 {
1366   if (Rightclick_colorpick(1))
1367     return;
1368 
1369   Hide_cursor();
1370   // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas
1371   // le Fill, et on se fout de savoir si on est dans la partie gauche ou
1372   // droite de la loupe.
1373   // On ne s'occupe pas de faire un Backup: c'est "Fill_general" qui s'en charge.
1374   Shade_table=Shade_table_right;
1375   Fill_general(Back_color);
1376   Display_cursor();
1377   End_of_modification();
1378   Wait_end_of_click();
1379 }
1380 
1381 
1382 ///////////////////////////////////////////////////////// OPERATION_REPLACE
1383 
1384 
Replace_1_0(void)1385 void Replace_1_0(void)
1386 //
1387 // Opération   : OPERATION_REPLACE
1388 // Click Souris: 1
1389 // Taille_Pile : 0
1390 //
1391 // Souris effacée: Non
1392 //
1393 {
1394   Hide_cursor();
1395   Init_start_operation();
1396   Backup();
1397 //  Shade_table=Shade_table_left;
1398   Replace(Fore_color);
1399   End_of_modification();
1400   Display_all_screen();
1401   Display_cursor();
1402   Wait_end_of_click();
1403 }
1404 
1405 
Replace_2_0(void)1406 void Replace_2_0(void)
1407 //
1408 // Opération   : OPERATION_REPLACE
1409 // Click Souris: 2
1410 // Taille_Pile : 0
1411 //
1412 // Souris effacée: Non
1413 //
1414 {
1415   if (Rightclick_colorpick(1))
1416     return;
1417 
1418   Hide_cursor();
1419   Init_start_operation();
1420   Backup();
1421 //  Shade_table=Shade_table_right;
1422   Replace(Back_color);
1423   End_of_modification();
1424   Display_all_screen();
1425   Display_cursor();
1426   Wait_end_of_click();
1427 }
1428 
1429 
1430 /////////////////////////////////////////////////// OPERATION_4_POINTS_CURVE
1431 
1432 
Draw_curve_cross(short x_pos,short y_pos)1433 void Draw_curve_cross(short x_pos, short y_pos)
1434 {
1435   short start_x,end_x;
1436   short start_y,end_y;
1437   short i,temp;
1438   //byte  temp2;
1439 
1440   if (x_pos>=Limit_left+3)
1441     start_x=0;
1442   else
1443     start_x=3-(x_pos-Limit_left);
1444 
1445   if (y_pos>=Limit_top+3)
1446     start_y=0;
1447   else
1448     start_y=3-(y_pos-Limit_top);
1449 
1450   if (x_pos<=Limit_visible_right-3)
1451     end_x=6;
1452   else
1453     end_x=3+(Limit_visible_right-x_pos);
1454 
1455   if (y_pos<=Limit_visible_bottom-3)
1456     end_y=6;
1457   else
1458     end_y=3+(Limit_visible_bottom-y_pos);
1459 
1460   if (start_x<=end_x && start_y<=end_y)
1461   {
1462     for (i=start_x; i<=end_x; i++)
1463     {
1464       temp=x_pos+i-3;
1465       Pixel_preview(temp,y_pos,xor_lut[Read_pixel(temp -Main.offset_X,
1466                                           y_pos-Main.offset_Y)]);
1467     }
1468     for (i=start_y; i<=end_y; i++)
1469     {
1470       temp=y_pos+i-3;
1471       Pixel_preview(x_pos,temp,xor_lut[Read_pixel(x_pos-Main.offset_X,
1472                                           temp -Main.offset_Y)]);
1473     }
1474     Update_part_of_screen(x_pos+start_x-3,y_pos+start_y-3,end_x-start_x+1,end_y-start_y+1);
1475   }
1476 }
1477 
1478 
Curve_34_points_1_0(void)1479 void Curve_34_points_1_0(void)
1480 //
1481 //  Opération   : OPERATION_COURBE_?_POINTS
1482 //  Click Souris: 1
1483 //  Taille_Pile : 0
1484 //
1485 //  Souris effacée: Oui
1486 //
1487 {
1488   Init_start_operation();
1489   Backup();
1490   Shade_table=Shade_table_left;
1491 
1492   Paintbrush_hidden=1;
1493 
1494   Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Fore_color);
1495   Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
1496 
1497   if ((Config.Coords_rel) && (Menu_is_visible))
1498     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
1499 
1500   Operation_push(Fore_color);
1501   Operation_push(Paintbrush_X);
1502   Operation_push(Paintbrush_Y);
1503   Operation_push(Paintbrush_X);
1504   Operation_push(Paintbrush_Y);
1505 }
1506 
Curve_34_points_2_0(void)1507 void Curve_34_points_2_0(void)
1508 //
1509 //  Opération   : OPERATION_COURBE_?_POINTS
1510 //  Click Souris: 2
1511 //  Taille_Pile : 0
1512 //
1513 //  Souris effacée: Oui
1514 //
1515 {
1516   if (Rightclick_colorpick(0))
1517     return;
1518 
1519   Init_start_operation();
1520   Backup();
1521   Shade_table=Shade_table_right;
1522 
1523   Paintbrush_hidden=1;
1524 
1525   Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Back_color);
1526   Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
1527 
1528   if ((Config.Coords_rel) && (Menu_is_visible))
1529     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
1530 
1531   Operation_push(Back_color);
1532   Operation_push(Paintbrush_X);
1533   Operation_push(Paintbrush_Y);
1534   Operation_push(Paintbrush_X);
1535   Operation_push(Paintbrush_Y);
1536 }
1537 
1538 
Curve_34_points_1_5(void)1539 void Curve_34_points_1_5(void)
1540 //
1541 //  Opération   : OPERATION_COURBE_?_POINTS
1542 //  Click Souris: 1
1543 //  Taille_Pile : 5
1544 //
1545 //  Souris effacée: Non
1546 //
1547 {
1548   short x1,x2,y1,y2;
1549 
1550   Operation_pop(&y2);
1551   Operation_pop(&x2);
1552   Operation_pop(&y1);
1553   Operation_pop(&x1);
1554 
1555   if ( (y2!=Paintbrush_Y) || (x2!=Paintbrush_X) )
1556   {
1557     Hide_cursor();
1558     Display_coords_rel_or_abs(x1,y1);
1559 
1560     Hide_line_preview(x1,y1,x2,y2);
1561     Pixel_figure_preview (x1,y1,Fore_color);
1562     Draw_line_preview (x1,y1,Paintbrush_X,Paintbrush_Y,Fore_color);
1563 
1564     Display_cursor();
1565   }
1566 
1567   Operation_push(x1);
1568   Operation_push(y1);
1569   Operation_push(Paintbrush_X);
1570   Operation_push(Paintbrush_Y);
1571 }
1572 
Curve_34_points_2_5(void)1573 void Curve_34_points_2_5(void)
1574 //
1575 //  Opération   : OPERATION_COURBE_?_POINTS
1576 //  Click Souris: 2
1577 //  Taille_Pile : 5
1578 //
1579 //  Souris effacée: Non
1580 //
1581 {
1582   short x1,x2,y1,y2;
1583 
1584   Operation_pop(&y2);
1585   Operation_pop(&x2);
1586   Operation_pop(&y1);
1587   Operation_pop(&x1);
1588 
1589   if ( (y2!=Paintbrush_Y) || (x2!=Paintbrush_X) )
1590   {
1591     Hide_cursor();
1592     Display_coords_rel_or_abs(x1,y1);
1593 
1594     Hide_line_preview(x1,y1,x2,y2);
1595     Pixel_figure_preview (x1,y1,Back_color);
1596     Draw_line_preview (x1,y1,Paintbrush_X,Paintbrush_Y,Back_color);
1597 
1598     Display_cursor();
1599   }
1600 
1601   Operation_push(x1);
1602   Operation_push(y1);
1603   Operation_push(Paintbrush_X);
1604   Operation_push(Paintbrush_Y);
1605 }
1606 
1607 
1608 byte Cursor_hidden_before_curve;
1609 
Curve_4_points_0_5(void)1610 void Curve_4_points_0_5(void)
1611 //
1612 //  Opération   : OPERATION_4_POINTS_CURVE
1613 //  Click Souris: 0
1614 //  Taille_Pile : 5
1615 //
1616 //  Souris effacée: Oui
1617 //
1618 {
1619   short x1,y1,x2,y2,x3,y3,x4,y4;
1620   short third_x,third_y;
1621   short color;
1622 
1623   Operation_pop(&y4);
1624   Operation_pop(&x4);
1625   Operation_pop(&y1);
1626   Operation_pop(&x1);
1627   Operation_pop(&color);
1628 
1629   third_x=Round_div(abs(x4-x1),3);
1630   third_y=Round_div(abs(y4-y1),3);
1631 
1632   if (x1<x4)
1633   {
1634     x2=x1+third_x;
1635     x3=x4-third_x;
1636   }
1637   else
1638   {
1639     x3=x4+third_x;
1640     x2=x1-third_x;
1641   }
1642 
1643   if (y1<y4)
1644   {
1645     y2=y1+third_y;
1646     y3=y4-third_y;
1647   }
1648   else
1649   {
1650     y3=y4+third_y;
1651     y2=y1-third_y;
1652   }
1653 
1654   Hide_line_preview(x1,y1,x4,y4);
1655   Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
1656 
1657   // On trace les petites croix montrant les 2 points intermédiares
1658   Draw_curve_cross(x2,y2);
1659   Draw_curve_cross(x3,y3);
1660 
1661   Cursor_hidden_before_curve=Cursor_hidden;
1662   Cursor_hidden=0;
1663 
1664   Operation_push(color);
1665   Operation_push(x1);
1666   Operation_push(y1);
1667   Operation_push(x2);
1668   Operation_push(y2);
1669   Operation_push(x3);
1670   Operation_push(y3);
1671   Operation_push(x4);
1672   Operation_push(y4);
1673 
1674   if ( (Config.Coords_rel) && (Menu_is_visible) )
1675   {
1676     Print_in_menu("X:       Y:             ",0);
1677     Print_coordinates();
1678   }
1679 }
1680 
1681 
Curve_4_points_1_9(void)1682 void Curve_4_points_1_9(void)
1683 //
1684 //  Opération   : OPERATION_4_POINTS_CURVE
1685 //  Click Souris: 1
1686 //  Taille_Pile : 9
1687 //
1688 //  Souris effacée: Non
1689 //
1690 {
1691   short x1,y1,x2,y2,x3,y3,x4,y4;
1692   short color;
1693   byte  it_is_x2;
1694 
1695   Operation_pop(&y4);
1696   Operation_pop(&x4);
1697   Operation_pop(&y3);
1698   Operation_pop(&x3);
1699   Operation_pop(&y2);
1700   Operation_pop(&x2);
1701   Operation_pop(&y1);
1702   Operation_pop(&x1);
1703   Operation_pop(&color);
1704 
1705   it_is_x2=(Distance(Paintbrush_X,Paintbrush_Y,x2,y2) < Distance(Paintbrush_X,Paintbrush_Y,x3,y3));
1706 
1707   if ( (   it_is_x2  && ( (Paintbrush_X!=x2) || (Paintbrush_Y!=y2) ) )
1708     || ( (!it_is_x2) && ( (Paintbrush_X!=x3) || (Paintbrush_Y!=y3) ) ) )
1709   {
1710     Hide_cursor();
1711     Print_coordinates();
1712 
1713     Draw_curve_cross(x2,y2);
1714     Draw_curve_cross(x3,y3);
1715 
1716     Hide_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
1717 
1718     if (it_is_x2)
1719     {
1720       x2=Paintbrush_X;
1721       y2=Paintbrush_Y;
1722     }
1723     else
1724     {
1725       x3=Paintbrush_X;
1726       y3=Paintbrush_Y;
1727     }
1728 
1729     Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
1730 
1731     Draw_curve_cross(x2,y2);
1732     Draw_curve_cross(x3,y3);
1733 
1734     Display_cursor();
1735   }
1736 
1737   Operation_push(color);
1738   Operation_push(x1);
1739   Operation_push(y1);
1740   Operation_push(x2);
1741   Operation_push(y2);
1742   Operation_push(x3);
1743   Operation_push(y3);
1744   Operation_push(x4);
1745   Operation_push(y4);
1746 }
1747 
1748 
Curve_4_points_2_9(void)1749 void Curve_4_points_2_9(void)
1750 //
1751 //  Opération   : OPERATION_4_POINTS_CURVE
1752 //  Click Souris: 2
1753 //  Taille_Pile : 9
1754 //
1755 //  Souris effacée: Oui
1756 //
1757 {
1758   short x1,y1,x2,y2,x3,y3,x4,y4;
1759   short color;
1760 
1761   Operation_pop(&y4);
1762   Operation_pop(&x4);
1763   Operation_pop(&y3);
1764   Operation_pop(&x3);
1765   Operation_pop(&y2);
1766   Operation_pop(&x2);
1767   Operation_pop(&y1);
1768   Operation_pop(&x1);
1769   Operation_pop(&color);
1770 
1771   Hide_cursor();
1772 
1773   Draw_curve_cross(x2,y2);
1774   Draw_curve_cross(x3,y3);
1775 
1776   Paintbrush_hidden=0;
1777   Cursor_hidden=Cursor_hidden_before_curve;
1778 
1779   Hide_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
1780   Draw_curve_permanent(x1,y1,x2,y2,x3,y3,x4,y4,color);
1781 
1782   Display_cursor();
1783   End_of_modification();
1784   Wait_end_of_click();
1785 }
1786 
1787 
1788 /////////////////////////////////////////////////// OPERATION_3_POINTS_CURVE
1789 
1790 
Compute_3_point_curve(short x1,short y1,short x4,short y4,short * x2,short * y2,short * x3,short * y3)1791 void Compute_3_point_curve(short x1, short y1, short x4, short y4,
1792                               short * x2, short * y2, short * x3, short * y3)
1793 {
1794   float cx,cy; // Centre de (x1,y1) et (x4,y4)
1795   float bx,by; // Intersect. des dtes ((x1,y1),(x2,y2)) et ((x3,y3),(x4,y4))
1796 
1797   cx=(float)(x1+x4)/2.0;              // P1*--_               Legend:
1798   cy=(float)(y1+y4)/2.0;              //   ·   \·· P2         -_\|/ : curve
1799                                       //   ·    \ ·*·         * : important point
1800   bx=cx+((8.0/3.0)*(Paintbrush_X-cx));//   ·     |   ··       · : dotted line
1801   by=cy+((8.0/3.0)*(Paintbrush_Y-cy));//   ·     |P    ··  B
1802                                       // C *·····*·········*  P=Pencil position
1803   *x2=Round((bx+x1)/2.0);             //   ·     |     ··     C=middle of [P1,P4]
1804   *y2=Round((by+y1)/2.0);             //   ·     |   ··       B=point computed as
1805                                       //   ·    / ·*·         C->B=(8/3) * C->P
1806   *x3=Round((bx+x4)/2.0);             //   ·  _/·· P3         P2=middle of [P1,B]
1807   *y3=Round((by+y4)/2.0);             // P4*--                P3=middle of [P4,B]
1808 }
1809 
1810 
Curve_3_points_0_5(void)1811 void Curve_3_points_0_5(void)
1812 //
1813 //  Opération   : OPERATION_3_POINTS_CURVE
1814 //  Click Souris: 0
1815 //  Taille_Pile : 5
1816 //
1817 //  Souris effacée: Oui
1818 //
1819 {
1820   short x1,y1,x2,y2,x3,y3,x4,y4;
1821   short color;
1822 
1823   Operation_pop(&y4);
1824   Operation_pop(&x4);
1825   Operation_pop(&y1);
1826   Operation_pop(&x1);
1827   Operation_pop(&color);
1828 
1829   Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3);
1830 
1831   if (!Config.Stylus_mode)
1832   {
1833     Hide_line_preview(x1,y1,x4,y4);
1834     Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
1835   }
1836 
1837   if ( (Config.Coords_rel) && (Menu_is_visible) )
1838   {
1839     Print_in_menu("X:       Y:             ",0);
1840     Print_coordinates();
1841   }
1842 
1843   Operation_push(color);
1844   Operation_push(x1);
1845   Operation_push(y1);
1846   Operation_push(x2);
1847   Operation_push(y2);
1848   Operation_push(x3);
1849   Operation_push(y3);
1850   Operation_push(x4);
1851   Operation_push(y4);
1852   Operation_push(Paintbrush_X);
1853   Operation_push(Paintbrush_Y);
1854 
1855   if (Config.Stylus_mode)
1856   {
1857     Display_cursor();
1858     while(!Mouse_K)
1859       Get_input(20);
1860     Hide_cursor();
1861 
1862     Hide_line_preview(x1,y1,x4,y4);
1863   }
1864 }
1865 
Curve_drag(void)1866 void Curve_drag(void)
1867 {
1868   short x1,y1,x2,y2,x3,y3,x4,y4;
1869   short old_x,old_y;
1870   short color;
1871 
1872   Operation_pop(&old_y);
1873   Operation_pop(&old_x);
1874 
1875   if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) )
1876   {
1877     Operation_pop(&y4);
1878     Operation_pop(&x4);
1879     Operation_pop(&y3);
1880     Operation_pop(&x3);
1881     Operation_pop(&y2);
1882     Operation_pop(&x2);
1883     Operation_pop(&y1);
1884     Operation_pop(&x1);
1885     Operation_pop(&color);
1886 
1887     Hide_cursor();
1888     Print_coordinates();
1889 
1890     Hide_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
1891     Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3);
1892     Draw_curve_preview (x1,y1,x2,y2,x3,y3,x4,y4,color);
1893     Display_cursor();
1894 
1895     Operation_push(color);
1896     Operation_push(x1);
1897     Operation_push(y1);
1898     Operation_push(x2);
1899     Operation_push(y2);
1900     Operation_push(x3);
1901     Operation_push(y3);
1902     Operation_push(x4);
1903     Operation_push(y4);
1904   }
1905   Operation_push(Paintbrush_X);
1906   Operation_push(Paintbrush_Y);
1907 }
Curve_finalize(void)1908 void Curve_finalize(void)
1909 {
1910   short x1,y1,x2,y2,x3,y3,x4,y4;
1911   short old_x,old_y;
1912   short color;
1913 
1914   Operation_pop(&old_y);
1915   Operation_pop(&old_x);
1916   Operation_pop(&y4);
1917   Operation_pop(&x4);
1918   Operation_pop(&y3);
1919   Operation_pop(&x3);
1920   Operation_pop(&y2);
1921   Operation_pop(&x2);
1922   Operation_pop(&y1);
1923   Operation_pop(&x1);
1924   Operation_pop(&color);
1925 
1926   Paintbrush_hidden=0;
1927 
1928   Hide_cursor();
1929 
1930   Hide_curve_preview (x1,y1,x2,y2,x3,y3,x4,y4,color);
1931   Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3);
1932   Draw_curve_permanent(x1,y1,x2,y2,x3,y3,x4,y4,color);
1933 
1934   End_of_modification();
1935   Display_cursor();
1936   Wait_end_of_click();
1937 }
1938 
Curve_3_points_0_11(void)1939 void Curve_3_points_0_11(void)
1940 //
1941 //  Opération   : OPERATION_3_POINTS_CURVE
1942 //  Click Souris: 0
1943 //  Taille_Pile : 11
1944 //
1945 //  Souris effacée: Non
1946 //
1947 {
1948   if (!Config.Stylus_mode)
1949     Curve_drag();
1950   else
1951     Curve_finalize();
1952 }
1953 
1954 
Curve_3_points_12_11(void)1955 void Curve_3_points_12_11(void)
1956 //
1957 //  Opération   : OPERATION_3_POINTS_CURVE
1958 //  Click Souris: 1 ou 2
1959 //  Taille_Pile : 11
1960 //
1961 //  Souris effacée: Oui
1962 //
1963 {
1964   if (!Config.Stylus_mode)
1965     Curve_finalize();
1966   else
1967     Curve_drag();
1968 }
1969 
1970 
1971 ///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH
1972 
Airbrush_1_0(void)1973 void Airbrush_1_0(void)
1974 //
1975 //  Opération   : OPERATION_AIRBRUSH
1976 //  Click Souris: 1
1977 //  Taille_Pile : 0
1978 //
1979 //  Souris effacée: Non
1980 //
1981 {
1982   Init_start_operation();
1983   Backup();
1984   Shade_table=Shade_table_left;
1985 
1986   if (GFX2_GetTicks()>Airbrush_next_time)
1987   {
1988     Airbrush(LEFT_SIDE);
1989     Airbrush_next_time = GFX2_GetTicks()+Airbrush_delay*10;
1990   }
1991 
1992   Operation_push(Paintbrush_X);
1993   Operation_push(Paintbrush_Y);
1994 }
1995 
Airbrush_2_0(void)1996 void Airbrush_2_0(void)
1997 //
1998 //  Opération   : OPERATION_AIRBRUSH
1999 //  Click Souris: 2
2000 //  Taille_Pile : 0
2001 //
2002 //  Souris effacée: Non
2003 //
2004 {
2005   if (Rightclick_colorpick(1))
2006     return;
2007 
2008   Init_start_operation();
2009   Backup();
2010   Shade_table=Shade_table_right;
2011   if (GFX2_GetTicks()>Airbrush_next_time)
2012   {
2013     Airbrush(RIGHT_SIDE);
2014     Airbrush_next_time = GFX2_GetTicks()+Airbrush_delay*10;
2015   }
2016 
2017   Operation_push(Paintbrush_X);
2018   Operation_push(Paintbrush_Y);
2019 }
2020 
Airbrush_12_2(void)2021 void Airbrush_12_2(void)
2022 //
2023 //  Opération   : OPERATION_AIRBRUSH
2024 //  Click Souris: 1 ou 2
2025 //  Taille_Pile : 2
2026 //
2027 //  Souris effacée: Non
2028 //
2029 {
2030   short old_x,old_y;
2031   dword now;
2032 
2033   Operation_pop(&old_y);
2034   Operation_pop(&old_x);
2035 
2036   if ( (Menu_is_visible) && ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) )
2037   {
2038     Hide_cursor();
2039     Print_coordinates();
2040     Display_cursor();
2041   }
2042 
2043   now=GFX2_GetTicks();
2044   if (now>Airbrush_next_time)
2045   {
2046     //Airbrush_next_time+=Airbrush_delay*10;
2047     // Time is now reset, because the += was death spiral
2048     // if drawing took more time than the frequency.
2049     Airbrush_next_time=now+Airbrush_delay*10;
2050     Airbrush(Mouse_K_unique);
2051   }
2052 
2053   Operation_push(Paintbrush_X);
2054   Operation_push(Paintbrush_Y);
2055 }
2056 
Airbrush_0_2(void)2057 void Airbrush_0_2(void)
2058 //
2059 //  Opération   : OPERATION_AIRBRUSH
2060 //  Click Souris: 0
2061 //  Taille_Pile : 2
2062 //
2063 //  Souris effacée: Non
2064 //
2065 {
2066   Operation_stack_size-=2;
2067   End_of_modification();
2068 }
2069 
2070 
2071 ////////////////////////////////////////////////////////// OPERATION_POLYGON
2072 
2073 
Polygon_12_0(void)2074 void Polygon_12_0(void)
2075 // Opération   : OPERATION_POLYGON
2076 // Click Souris: 1 ou 2
2077 // Taille_Pile : 0
2078 //
2079 // Souris effacée: Oui
2080 {
2081   byte color;
2082 
2083   if (Rightclick_colorpick(0))
2084     return;
2085 
2086   Init_start_operation();
2087   Backup();
2088   Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
2089   Paintbrush_shape_before_operation=Paintbrush_shape;
2090   Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
2091 
2092   color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
2093 
2094   // On place temporairement le début de la ligne qui ne s'afficherait pas sinon
2095   Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color);
2096   Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
2097 
2098   if ((Config.Coords_rel) && (Menu_is_visible))
2099     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
2100 
2101   Operation_push(Paintbrush_X);
2102   Operation_push(Paintbrush_Y);
2103   Operation_push(Mouse_K | 0x80);
2104   Operation_push(color);
2105   Operation_push(Paintbrush_X);
2106   Operation_push(Paintbrush_Y);
2107   Operation_push(Paintbrush_X);
2108   Operation_push(Paintbrush_Y);
2109   // Taille de pile 8 : phase d'appui, non interruptible
2110 }
2111 
2112 
2113 
Polygon_12_9(void)2114 void Polygon_12_9(void)
2115 // Opération   : OPERATION_POLYGON
2116 // Click Souris: 1 ou 2
2117 // Taille_Pile : 9
2118 //
2119 // Souris effacée: Oui
2120 {
2121   short start_x;
2122   short start_y;
2123   short end_x;
2124   short end_y;
2125   short color;
2126   short direction;
2127 
2128   Operation_pop(&end_y);
2129   Operation_pop(&end_x);
2130   Operation_pop(&start_y);
2131   Operation_pop(&start_x);
2132   Operation_pop(&color);
2133   Operation_pop(&direction);
2134   Operation_pop(&direction);
2135 
2136   if (direction==Mouse_K)
2137   {
2138     Operation_push(direction);
2139     Operation_push(color);
2140     Operation_push(start_x);
2141     Operation_push(start_y);
2142     Operation_push(end_x);
2143     Operation_push(end_y);
2144     // Taille de pile 8 : phase d'appui, non interruptible
2145   }
2146   else
2147   {
2148     //   La série de ligne est terminée, il faut donc effacer la dernière
2149     // preview de ligne et relier le dernier point avec le premier
2150     Pixel_figure_preview_auto  (start_x,start_y);
2151     Hide_line_preview (start_x,start_y,end_x,end_y);
2152     Operation_pop(&end_y);
2153     Operation_pop(&end_x);
2154     Paintbrush_shape=Paintbrush_shape_before_operation;
2155     // Le pied aurait été de ne pas repasser sur le 1er point de la 1ère ligne
2156     // mais c'est pas possible :(
2157     Draw_line_permanent(start_x,start_y,end_x,end_y,color);
2158     Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
2159 
2160     Display_cursor();
2161     End_of_modification();
2162     Wait_end_of_click();
2163     Hide_cursor();
2164 
2165     if ( (Config.Coords_rel) && (Menu_is_visible) )
2166     {
2167       Print_in_menu("X:       Y:             ",0);
2168       Print_coordinates();
2169     }
2170 
2171     Paintbrush_shape=Paintbrush_shape_before_operation;
2172   }
2173 }
2174 
2175 
2176 ////////////////////////////////////////////////////////// OPERATION_POLYFILL
2177 
Polyfill_12_0(void)2178 void Polyfill_12_0(void)
2179 // Opération   : OPERATION_POLYFILL
2180 // Click Souris: 1 ou 2
2181 // Taille_Pile : 0
2182 //
2183 // Souris effacée: Oui
2184 {
2185   byte color;
2186 
2187   if (Rightclick_colorpick(0))
2188     return;
2189 
2190   Init_start_operation();
2191   Backup();
2192   Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
2193   Paintbrush_hidden=1;
2194 
2195   color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
2196 
2197   Polyfill_table_of_points=(short *) malloc((Config.Nb_max_vertices_per_polygon<<1)*sizeof(short));
2198   Polyfill_table_of_points[0]=Paintbrush_X;
2199   Polyfill_table_of_points[1]=Paintbrush_Y;
2200   Polyfill_number_of_points=1;
2201 
2202   // On place temporairement le début de la ligne qui ne s'afficherait pas sinon
2203   Pixel_figure_preview_xor(Paintbrush_X,Paintbrush_Y,0);
2204   Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
2205 
2206   if ((Config.Coords_rel) && (Menu_is_visible))
2207     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
2208 
2209   Operation_push(Paintbrush_X);
2210   Operation_push(Paintbrush_Y);
2211   Operation_push(Mouse_K | 0x80);
2212   Operation_push(color);
2213   Operation_push(Paintbrush_X);
2214   Operation_push(Paintbrush_Y);
2215   Operation_push(Paintbrush_X);
2216   Operation_push(Paintbrush_Y);
2217   // Taille de pile 8 : phase d'appui, non interruptible
2218 }
2219 
2220 
Polyfill_0_8(void)2221 void Polyfill_0_8(void)
2222 // Opération   : OPERATION_POLYFILL
2223 // Click Souris: 0
2224 // Taille_Pile : 8
2225 //
2226 // Souris effacée: Oui
2227 {
2228   short start_x;
2229   short start_y;
2230   short end_x;
2231   short end_y;
2232   short color;
2233   short direction;
2234 
2235   Operation_pop(&end_y);
2236   Operation_pop(&end_x);
2237   Operation_pop(&start_y);
2238   Operation_pop(&start_x);
2239   Operation_pop(&color);
2240   Operation_pop(&direction);
2241 
2242   if ((Config.Coords_rel) && (Menu_is_visible))
2243     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
2244 
2245   Draw_line_preview_xor(start_x,start_y,end_x,end_y,0);
2246 
2247   if (direction & 0x80)
2248     direction=(direction & 0x7F);
2249 
2250   Operation_push(direction); // Valeur bidon servant de nouvel état de pile
2251   Operation_push(direction);
2252   Operation_push(color);
2253 
2254   Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0);
2255 
2256   if (Polyfill_number_of_points<Config.Nb_max_vertices_per_polygon)
2257   {
2258     Polyfill_table_of_points[Polyfill_number_of_points<<1]    =Paintbrush_X;
2259     Polyfill_table_of_points[(Polyfill_number_of_points<<1)+1]=Paintbrush_Y;
2260     Polyfill_number_of_points++;
2261 
2262     Operation_push(Paintbrush_X);
2263     Operation_push(Paintbrush_Y);
2264     Operation_push(Paintbrush_X);
2265     Operation_push(Paintbrush_Y);
2266   }
2267   else
2268   {
2269     Operation_push(start_x);
2270     Operation_push(start_y);
2271     Operation_push(Paintbrush_X);
2272     Operation_push(Paintbrush_Y);
2273   }
2274   // Taille de pile 9 : phase de "repos", interruptible (comme Elliot Ness :))
2275 }
2276 
2277 
Polyfill_12_8(void)2278 void Polyfill_12_8(void)
2279 // Opération   : OPERATION_POLYFILL
2280 // Click Souris: 1 ou 2 | 0
2281 // Taille_Pile : 8      | 9
2282 //
2283 // Souris effacée: Non
2284 {
2285   short start_x;
2286   short start_y;
2287   short end_x;
2288   short end_y;
2289 
2290   Operation_pop(&end_y);
2291   Operation_pop(&end_x);
2292 
2293   if ((Paintbrush_X!=end_x) || (Paintbrush_Y!=end_y))
2294   {
2295     Hide_cursor();
2296     Operation_pop(&start_y);
2297     Operation_pop(&start_x);
2298 
2299     Display_coords_rel_or_abs(start_x,start_y);
2300 
2301     Draw_line_preview_xor(start_x,start_y,end_x,end_y,0);
2302     Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0);
2303 
2304     Operation_push(start_x);
2305     Operation_push(start_y);
2306     Display_cursor();
2307   }
2308 
2309   Operation_push(Paintbrush_X);
2310   Operation_push(Paintbrush_Y);
2311 }
2312 
2313 
Polyfill_12_9(void)2314 void Polyfill_12_9(void)
2315 // Opération   : OPERATION_POLYFILL
2316 // Click Souris: 1 ou 2
2317 // Taille_Pile : 9
2318 //
2319 // Souris effacée: Oui
2320 {
2321   short start_x;
2322   short start_y;
2323   short end_x;
2324   short end_y;
2325   short color;
2326   short direction;
2327 
2328   Operation_pop(&end_y);
2329   Operation_pop(&end_x);
2330   Operation_pop(&start_y);
2331   Operation_pop(&start_x);
2332   Operation_pop(&color);
2333   Operation_pop(&direction);
2334   Operation_pop(&direction);
2335 
2336   if (direction==Mouse_K)
2337   {
2338     Operation_push(direction);
2339     Operation_push(color);
2340     Operation_push(start_x);
2341     Operation_push(start_y);
2342     Operation_push(end_x);
2343     Operation_push(end_y);
2344     // Taille de pile 8 : phase d'appui, non interruptible
2345   }
2346   else
2347   {
2348     //   La série de lignes est terminée, il faut donc effacer la dernière
2349     // preview de ligne et relier le dernier point avec le premier
2350     Hide_cursor();
2351     Draw_line_preview_xor(start_x,start_y,end_x,end_y,0);
2352     Operation_pop(&end_y);
2353     Operation_pop(&end_x);
2354     Draw_line_preview_xor(start_x,start_y,end_x,end_y,0);
2355 
2356     Display_all_screen();
2357     Polyfill(Polyfill_number_of_points,Polyfill_table_of_points,color);
2358     free(Polyfill_table_of_points);
2359     Polyfill_table_of_points = NULL;
2360 
2361     End_of_modification();
2362     if ( (Config.Coords_rel) && (Menu_is_visible) )
2363     {
2364       Print_in_menu("X:       Y:             ",0);
2365       Print_coordinates();
2366     }
2367 
2368     Paintbrush_hidden=0;
2369 
2370     Display_cursor();
2371     Wait_end_of_click();
2372   }
2373 }
2374 
2375 
2376 ////////////////////////////////////////////////////////// OPERATION_POLYFORM
2377 
2378 
Polyform_12_0(void)2379 void Polyform_12_0(void)
2380 //  Opération   : OPERATION_POLYFORM
2381 //  Click Souris: 1 ou 2
2382 //  Taille_Pile : 0
2383 //
2384 //  Souris effacée: Oui
2385 {
2386   short color;
2387 
2388   if (Rightclick_colorpick(0))
2389     return;
2390 
2391   Init_start_operation();
2392   Backup();
2393   Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
2394 
2395   color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
2396 
2397   // On place un premier pinceau en (Paintbrush_X,Paintbrush_Y):
2398   Draw_paintbrush(Paintbrush_X,Paintbrush_Y,color);
2399   // Et on affiche un pixel de preview en (Paintbrush_X,Paintbrush_Y):
2400   Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color);
2401 
2402   Operation_push(Paintbrush_X); // X Initial
2403   Operation_push(Paintbrush_Y); // X Initial
2404   Operation_push(color);   // color de remplissage
2405   Operation_push(Paintbrush_X); // Start X
2406   Operation_push(Paintbrush_Y); // Start Y
2407   Operation_push(Paintbrush_X); // End X
2408   Operation_push(Paintbrush_Y); // End Y
2409   Operation_push(Mouse_K);   // click
2410 }
2411 
2412 
Polyform_12_8(void)2413 void Polyform_12_8(void)
2414 //  Opération   : OPERATION_POLYFORM
2415 //  Click Souris: 1 ou 2
2416 //  Taille_Pile : 8
2417 //
2418 //  Souris effacée: Non
2419 {
2420   short click;
2421   short end_y;
2422   short end_x;
2423   short start_y;
2424   short start_x;
2425   short color;
2426   short initial_y;
2427   short initial_x;
2428 
2429   Operation_pop(&click);
2430   Operation_pop(&end_y);
2431   Operation_pop(&end_x);
2432   Operation_pop(&start_y);
2433   Operation_pop(&start_x);
2434 
2435   if (click==Mouse_K)
2436   {
2437     // L'utilisateur clic toujours avec le bon bouton de souris
2438 
2439     if ((start_x!=Paintbrush_X) || (start_y!=Paintbrush_Y))
2440     {
2441       // Il existe un segment définit par (start_x,start_y)-(Paintbrush_X,Paintbrush_Y)
2442 
2443       Hide_cursor();
2444       Print_coordinates();
2445 
2446       Operation_pop(&color);
2447 
2448       // On efface la preview du segment validé:
2449       Pixel_figure_preview_auto  (start_x,start_y);
2450       Hide_line_preview(start_x,start_y,end_x,end_y);
2451 
2452       // On l'affiche de façon définitive:
2453       Draw_line_permanent(start_x,start_y,Paintbrush_X,Paintbrush_Y,color);
2454 
2455       // Et on affiche un pixel de preview en (Paintbrush_X,Paintbrush_Y):
2456       Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color);
2457 
2458       Operation_push(color);
2459 
2460       Display_cursor();
2461     }
2462 
2463     Operation_push(Paintbrush_X); // Nouveau start_x
2464     Operation_push(Paintbrush_Y); // Nouveau start_y
2465     Operation_push(Paintbrush_X); // Nouveau end_x
2466     Operation_push(Paintbrush_Y); // Nouveau end_y
2467     Operation_push(click);
2468   }
2469   else
2470   {
2471     // L'utilisateur souhaite arrêter l'opération et refermer le polygone
2472 
2473     Operation_pop(&color);
2474     Operation_pop(&initial_y);
2475     Operation_pop(&initial_x);
2476 
2477     Hide_cursor();
2478     Print_coordinates();
2479 
2480     // On efface la preview du segment annulé:
2481     Hide_line_preview(start_x,start_y,end_x,end_y);
2482 
2483     // On affiche de façon définitive le bouclage du polygone:
2484     Draw_line_permanent(start_x,start_y,initial_x,initial_y,color);
2485 
2486     Display_cursor();
2487     End_of_modification();
2488     Wait_end_of_click();
2489   }
2490 }
2491 
2492 
Polyform_0_8(void)2493 void Polyform_0_8(void)
2494 //  Opération   : OPERATION_POLYFORM
2495 //  Click Souris: 0
2496 //  Taille_Pile : 8
2497 //
2498 //  Souris effacée: Non
2499 {
2500   short click;
2501   short end_y;
2502   short end_x;
2503   short start_y;
2504   short start_x;
2505   short color;
2506 
2507   Operation_pop(&click);
2508   Operation_pop(&end_y);
2509   Operation_pop(&end_x);
2510 
2511   if ((end_x!=Paintbrush_X) || (end_y!=Paintbrush_Y))
2512   {
2513     Hide_cursor();
2514     Print_coordinates();
2515 
2516     Operation_pop(&start_y);
2517     Operation_pop(&start_x);
2518     Operation_pop(&color);
2519 
2520     // On met à jour l'affichage de la preview du prochain segment:
2521     Hide_line_preview(start_x,start_y,end_x,end_y);
2522     Draw_line_preview (start_x,start_y,Paintbrush_X,Paintbrush_Y,color);
2523 
2524     Operation_push(color);
2525     Operation_push(start_x);
2526     Operation_push(start_y);
2527 
2528     Display_cursor();
2529   }
2530 
2531   Operation_push(Paintbrush_X);
2532   Operation_push(Paintbrush_Y);
2533   Operation_push(click);
2534 }
2535 
2536 
2537 /////////////////////////////////////////////////// OPERATION_FILLED_POLYFORM
2538 
2539 
Filled_polyform_12_0(void)2540 void Filled_polyform_12_0(void)
2541 //  Opération   : OPERATION_FILLED_POLYFORM
2542 //  Click Souris: 1 ou 2
2543 //  Taille_Pile : 0
2544 //
2545 //  Souris effacée: Oui
2546 {
2547   short color;
2548 
2549   if (Rightclick_colorpick(0))
2550     return;
2551 
2552   Init_start_operation();
2553 
2554   // Cette opération étant également utilisée pour le lasso, on ne fait pas de
2555   // backup si on prend une brosse au lasso avec le bouton gauche.
2556   if ((Current_operation==OPERATION_FILLED_POLYFORM) || (Current_operation==OPERATION_FILLED_CONTOUR) || (Mouse_K==RIGHT_SIDE))
2557     Backup();
2558 
2559   Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
2560   Paintbrush_hidden=1;
2561 
2562   color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
2563 
2564   Polyfill_table_of_points=(short *) malloc((Config.Nb_max_vertices_per_polygon<<1)*sizeof(short));
2565   Polyfill_table_of_points[0]=Paintbrush_X;
2566   Polyfill_table_of_points[1]=Paintbrush_Y;
2567   Polyfill_number_of_points=1;
2568 
2569   // On place temporairement le début de la ligne qui ne s'afficherait pas sinon
2570   Pixel_figure_preview_xor(Paintbrush_X,Paintbrush_Y,0);
2571   Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
2572 
2573   Operation_push(Paintbrush_X); // X Initial
2574   Operation_push(Paintbrush_Y); // X Initial
2575   Operation_push(color);   // color de remplissage
2576   Operation_push(Paintbrush_X); // Start X
2577   Operation_push(Paintbrush_Y); // Start Y
2578   Operation_push(Paintbrush_X); // End X
2579   Operation_push(Paintbrush_Y); // End Y
2580   Operation_push(Mouse_K);   // click
2581 }
2582 
2583 
Filled_polyform_12_8(void)2584 void Filled_polyform_12_8(void)
2585 //  Opération   : OPERATION_FILLED_POLYFORM
2586 //  Click Souris: 1 ou 2
2587 //  Taille_Pile : 8
2588 //
2589 //  Souris effacée: Non
2590 {
2591   short click;
2592   short end_y;
2593   short end_x;
2594   short start_y;
2595   short start_x;
2596   short color;
2597   short initial_y;
2598   short initial_x;
2599 
2600   Operation_pop(&click);
2601   Operation_pop(&end_y);
2602   Operation_pop(&end_x);
2603   Operation_pop(&start_y);
2604   Operation_pop(&start_x);
2605 
2606   if (click==Mouse_K)
2607   {
2608     // L'utilisateur clique toujours avec le bon bouton de souris
2609 
2610     if (((start_x!=Paintbrush_X) || (start_y!=Paintbrush_Y)) &&
2611         (Polyfill_number_of_points<Config.Nb_max_vertices_per_polygon))
2612     {
2613       // Il existe un nouveau segment défini par
2614       // (start_x,start_y)-(Paintbrush_X,Paintbrush_Y)
2615 
2616       Hide_cursor();
2617       Print_coordinates();
2618 
2619       // On le place à l'écran
2620       if (Current_operation==OPERATION_FILLED_CONTOUR)
2621       {
2622         Draw_line_preview_xorback(start_x,start_y,end_x,end_y,0);
2623         Draw_line_preview_xorback(start_x,start_y,Paintbrush_X,Paintbrush_Y,0);
2624       }
2625       else
2626       {
2627         Draw_line_preview_xor(start_x,start_y,end_x,end_y,0);
2628         Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0);
2629       }
2630 
2631       // On peut le rajouter au polygone
2632 
2633       Polyfill_table_of_points[Polyfill_number_of_points<<1]    =Paintbrush_X;
2634       Polyfill_table_of_points[(Polyfill_number_of_points<<1)+1]=Paintbrush_Y;
2635       Polyfill_number_of_points++;
2636 
2637       Operation_push(Paintbrush_X); // Nouveau start_x
2638       Operation_push(Paintbrush_Y); // Nouveau start_y
2639       Operation_push(Paintbrush_X); // Nouveau end_x
2640       Operation_push(Paintbrush_Y); // Nouveau end_y
2641       Operation_push(click);
2642 
2643       Display_cursor();
2644     }
2645     else
2646     {
2647       if (Polyfill_number_of_points==Config.Nb_max_vertices_per_polygon)
2648       {
2649         // Le curseur bouge alors qu'on ne peut plus stocker de segments ?
2650 
2651         if ((end_x!=Paintbrush_X) || (end_y!=Paintbrush_Y))
2652         {
2653           Hide_cursor();
2654           Print_coordinates();
2655 
2656           // On le place à l'écran
2657           Draw_line_preview_xor(start_x,start_y,end_x,end_y,0);
2658           Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0);
2659           Display_cursor();
2660         }
2661 
2662         // On remet les mêmes valeurs (comme si on n'avait pas cliqué):
2663         Operation_push(start_x);
2664         Operation_push(start_y);
2665         Operation_push(Paintbrush_X);
2666         Operation_push(Paintbrush_Y);
2667         Operation_push(click);
2668       }
2669       else
2670       {
2671         Operation_push(Paintbrush_X); // Nouveau start_x
2672         Operation_push(Paintbrush_Y); // Nouveau start_y
2673         Operation_push(Paintbrush_X); // Nouveau end_x
2674         Operation_push(Paintbrush_Y); // Nouveau end_y
2675         Operation_push(click);
2676       }
2677     }
2678   }
2679   else
2680   {
2681     // L'utilisateur souhaite arrêter l'opération et refermer le polygone
2682 
2683     Operation_pop(&color);
2684     Operation_pop(&initial_y);
2685     Operation_pop(&initial_x);
2686 
2687     Hide_cursor();
2688     Print_coordinates();
2689 
2690     // Pas besoin d'effacer la ligne (start_x,start_y)-(end_x,end_y)
2691     // puisque on les effaces toutes d'un coup.
2692 
2693     Display_all_screen();
2694     Polyfill(Polyfill_number_of_points,Polyfill_table_of_points,color);
2695     free(Polyfill_table_of_points);
2696     Polyfill_table_of_points = NULL;
2697 
2698     Paintbrush_hidden=0;
2699 
2700     Display_cursor();
2701     End_of_modification();
2702     Wait_end_of_click();
2703   }
2704 }
2705 
2706 
Filled_polyform_0_8(void)2707 void Filled_polyform_0_8(void)
2708 //  Opération   : OPERATION_FILLED_POLYFORM
2709 //  Click Souris: 0
2710 //  Taille_Pile : 8
2711 //
2712 //  Souris effacée: Non
2713 {
2714   short click;
2715   short end_y;
2716   short end_x;
2717   short start_y;
2718   short start_x;
2719 
2720   Operation_pop(&click);
2721   Operation_pop(&end_y);
2722   Operation_pop(&end_x);
2723 
2724   if ((end_x!=Paintbrush_X) || (end_y!=Paintbrush_Y))
2725   {
2726     Hide_cursor();
2727     Print_coordinates();
2728 
2729     Operation_pop(&start_y);
2730     Operation_pop(&start_x);
2731 
2732     // On met à jour l'affichage de la preview du prochain segment:
2733     Draw_line_preview_xor(start_x,start_y,end_x,end_y,0);
2734     Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0);
2735 
2736     Operation_push(start_x);
2737     Operation_push(start_y);
2738 
2739     Display_cursor();
2740   }
2741 
2742   Operation_push(Paintbrush_X);
2743   Operation_push(Paintbrush_Y);
2744   Operation_push(click);
2745 }
2746 
Filled_contour_0_8(void)2747 void Filled_contour_0_8(void)
2748 //  Opération   : OPERATION_FILLED_CONTOUR
2749 //  Click Souris: 0
2750 //  Taille_Pile : 8
2751 //
2752 //  Souris effacée: Non
2753 {
2754   short click;
2755   short end_y;
2756   short end_x;
2757   short start_y;
2758   short start_x;
2759   short color;
2760   short initial_y;
2761   short initial_x;
2762 
2763   Operation_pop(&click);
2764   Operation_pop(&end_y);
2765   Operation_pop(&end_x);
2766   Operation_pop(&start_y);
2767   Operation_pop(&start_x);
2768   Operation_pop(&color);
2769   Operation_pop(&initial_y);
2770   Operation_pop(&initial_x);
2771 
2772   Hide_cursor();
2773   Print_coordinates();
2774 
2775   // Pas besoin d'effacer la ligne (start_x,start_y)-(end_x,end_y)
2776   // puisque on les effaces toutes d'un coup.
2777 
2778   Display_all_screen();
2779   Polyfill(Polyfill_number_of_points,Polyfill_table_of_points,color);
2780   free(Polyfill_table_of_points);
2781   Polyfill_table_of_points = NULL;
2782 
2783   Paintbrush_hidden=0;
2784 
2785   Display_cursor();
2786   End_of_modification();
2787 }
2788 
2789 
2790 //////////////////////////////////////////////////////////// OPERATION_SCROLL
2791 
2792 
2793 byte Cursor_hidden_before_scroll;
2794 
Scroll_12_0(void)2795 void Scroll_12_0(void)
2796 //
2797 //  Opération   : OPERATION_SCROLL
2798 //  Click Souris: 1 ou 2
2799 //  Taille_Pile : 0
2800 //
2801 //  Souris effacée: Oui
2802 //
2803 {
2804   Init_start_operation();
2805   Operation_push(Paintbrush_X);
2806   Operation_push(Paintbrush_Y);
2807   Operation_push(Paintbrush_X);
2808   Operation_push(Paintbrush_Y);
2809   Operation_push(Mouse_K); // LEFT_SIDE or RIGHT_SIDE
2810   if (Mouse_K == LEFT_SIDE)
2811     Backup();
2812   else
2813   {
2814     Backup_layers(LAYER_ALL); // Main.layers_visible
2815     if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
2816     {
2817       // Ensure the backup visible image is up-to-date
2818       // (after swapping some layers on/off, it gets outdated)
2819       memcpy(Main_visible_image_backup.Image,
2820              Main.visible_image.Image,
2821              Main.image_width*Main.image_height);
2822     }
2823   }
2824   Update_screen_targets();
2825 
2826   Cursor_hidden_before_scroll=Cursor_hidden;
2827   Cursor_hidden=1;
2828   if ((Config.Coords_rel) && (Menu_is_visible))
2829     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
2830 }
2831 
2832 
Scroll_12_5(void)2833 void Scroll_12_5(void)
2834 //
2835 //  Opération   : OPERATION_SCROLL
2836 //  Click Souris: 1 ou 2
2837 //  Taille_Pile : 5
2838 //
2839 //  Souris effacée: Non
2840 //
2841 {
2842   short center_x;
2843   short center_y;
2844   short x_pos;
2845   short y_pos;
2846   short x_offset;
2847   short y_offset;
2848   short side;
2849   //char  str[5];
2850 
2851   Operation_pop(&side);
2852   Operation_pop(&y_pos);
2853   Operation_pop(&x_pos);
2854   Operation_pop(&center_y);
2855   Operation_pop(&center_x);
2856 
2857   if ( (Paintbrush_X!=x_pos) || (Paintbrush_Y!=y_pos) )
2858   {
2859     // L'utilisateur a bougé, il faut scroller l'image
2860 
2861     if (Paintbrush_X>=center_x)
2862       x_offset=(Paintbrush_X-center_x)%Main.image_width;
2863     else
2864       x_offset=Main.image_width-((center_x-Paintbrush_X)%Main.image_width);
2865 
2866     if (Paintbrush_Y>=center_y)
2867       y_offset=(Paintbrush_Y-center_y)%Main.image_height;
2868     else
2869       y_offset=Main.image_height-((center_y-Paintbrush_Y)%Main.image_height);
2870 
2871     Display_coords_rel_or_abs(center_x,center_y);
2872 
2873     if (side == RIGHT_SIDE)
2874     {
2875       // All layers at once
2876       Scroll_picture(Screen_backup, Main_screen, x_offset,y_offset);
2877     }
2878     else
2879     {
2880       // One layer at once
2881       Scroll_picture(Main.backups->Pages->Next->Image[Main.current_layer].Pixels, Main.backups->Pages->Image[Main.current_layer].Pixels, x_offset, y_offset);
2882       Redraw_current_layer();
2883     }
2884 
2885     Display_all_screen();
2886   }
2887 
2888   Operation_push(center_x);
2889   Operation_push(center_y);
2890   Operation_push(Paintbrush_X);
2891   Operation_push(Paintbrush_Y);
2892   Operation_push(side);
2893 }
2894 
Scroll_0_5(void)2895 void Scroll_0_5(void)
2896 //
2897 //  Opération   : OPERATION_SCROLL
2898 //  Click Souris: 0
2899 //  Taille_Pile : 5
2900 //
2901 //  Souris effacée: Oui
2902 //
2903 {
2904   // All layers at once
2905   short center_x;
2906   short center_y;
2907   short x_pos;
2908   short y_pos;
2909   short x_offset;
2910   short y_offset;
2911   short side;
2912   int i;
2913 
2914 
2915   Operation_pop(&side);
2916   Operation_pop(&y_pos);
2917   Operation_pop(&x_pos);
2918   Operation_pop(&center_y);
2919   Operation_pop(&center_x);
2920 
2921   if (side == RIGHT_SIDE)
2922   {
2923     // All layers at once
2924     if (x_pos>=center_x)
2925       x_offset=(x_pos-center_x)%Main.image_width;
2926     else
2927       x_offset=Main.image_width-((center_x-x_pos)%Main.image_width);
2928 
2929     if (y_pos>=center_y)
2930       y_offset=(y_pos-center_y)%Main.image_height;
2931     else
2932       y_offset=Main.image_height-((center_y-y_pos)%Main.image_height);
2933 
2934     // Do the actual scroll operation on all layers.
2935     for (i=0; i<Main.backups->Pages->Nb_layers; i++)
2936       //if ((1<<i) & Main.layers_visible)
2937       Scroll_picture(Main.backups->Pages->Next->Image[i].Pixels, Main.backups->Pages->Image[i].Pixels, x_offset, y_offset);
2938     // Update the depth buffer too ...
2939     // It would be faster to scroll it, but we don't have method
2940     // for in-place scrolling.
2941     Update_depth_buffer();
2942   }
2943   else
2944   {
2945     // One layer : everything was done while dragging the mouse
2946   }
2947   if (Main.tilemap_mode)
2948     Tilemap_update();
2949 
2950   Cursor_hidden=Cursor_hidden_before_scroll;
2951 
2952   End_of_modification();
2953   if ((Config.Coords_rel) && (Menu_is_visible))
2954   {
2955     Print_in_menu("X:       Y:             ",0);
2956     Print_coordinates();
2957   }
2958 }
2959 
2960 
2961 //////////////////////////////////////////////////// OPERATION_GRAD_CIRCLE
2962 
2963 
Grad_circle_12_0(void)2964 void Grad_circle_12_0(void)
2965 //
2966 // Opération   : OPERATION_GRAD_CIRCLE
2967 // Click Souris: 1 ou 2
2968 // Taille_Pile : 0
2969 //
2970 // Souris effacée: Oui
2971 {
2972   byte color;
2973 
2974   Init_start_operation();
2975   Backup();
2976   Load_gradient_data(Current_gradient);
2977 
2978   Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
2979   color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
2980 
2981   Paintbrush_hidden_before_scroll=Paintbrush_hidden;
2982   Paintbrush_hidden=1;
2983 
2984   Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color);
2985   Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
2986 
2987   if ((Config.Coords_rel) && (Menu_is_visible))
2988     Print_in_menu("Radius:   0    ",0);
2989 
2990   Operation_push(Mouse_K);
2991   Operation_push(color);
2992   Operation_push(Paintbrush_X);
2993   Operation_push(Paintbrush_Y);
2994   Operation_push(Paintbrush_X);
2995   Operation_push(Paintbrush_Y);
2996 }
2997 
2998 
Grad_circle_12_6(void)2999 void Grad_circle_12_6(void)
3000 //
3001 // Opération   : OPERATION_GRAD_CIRCLE
3002 // Click Souris: 1 ou 2
3003 // Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
3004 //
3005 // Souris effacée: Non
3006 //
3007 {
3008   short tangent_x;
3009   short tangent_y;
3010   short center_x;
3011   short center_y;
3012   short color;
3013   long limit;
3014   char  str[5];
3015 
3016   Operation_pop(&tangent_y);
3017   Operation_pop(&tangent_x);
3018   Operation_pop(&center_y);
3019   Operation_pop(&center_x);
3020   Operation_pop(&color);
3021 
3022 
3023   if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) )
3024   {
3025     Hide_cursor();
3026     Cursor_shape=CURSOR_SHAPE_TARGET;
3027     if ((Config.Coords_rel) && (Menu_is_visible))
3028     {
3029       Num2str(Distance(center_x,center_y,Paintbrush_X,Paintbrush_Y),str,4);
3030       Print_in_menu(str,7);
3031     }
3032     else
3033       Print_coordinates();
3034 
3035     limit=((tangent_x-center_x)*(tangent_x-center_x))+
3036            ((tangent_y-center_y)*(tangent_y-center_y));
3037     Hide_empty_circle_preview(center_x,center_y,limit);
3038 
3039     limit=((Paintbrush_X-center_x)*(Paintbrush_X-center_x))+
3040                   ((Paintbrush_Y-center_y)*(Paintbrush_Y-center_y));
3041     Draw_empty_circle_preview(center_x,center_y,limit,color);
3042 
3043     Display_cursor();
3044   }
3045 
3046   Operation_push(color);
3047   Operation_push(center_x);
3048   Operation_push(center_y);
3049   Operation_push(Paintbrush_X);
3050   Operation_push(Paintbrush_Y);
3051 }
3052 
3053 
Grad_circle_0_6(void)3054 void Grad_circle_0_6(void)
3055 //
3056 // Opération   : OPERATION_GRAD_CIRCLE
3057 // Click Souris: 0
3058 // Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
3059 //
3060 // Souris effacée: Oui
3061 //
3062 {
3063   short tangent_x;
3064   short tangent_y;
3065   short center_x;
3066   short center_y;
3067   short color;
3068   short click;
3069 
3070   Operation_pop(&tangent_y);
3071   Operation_pop(&tangent_x);
3072   Operation_pop(&center_y);
3073   Operation_pop(&center_x);
3074 
3075   Operation_pop(&color);
3076   Operation_pop(&click);
3077 
3078   if (click==LEFT_SIDE)
3079   {
3080     Operation_push(click);
3081     Operation_push(color);
3082 
3083     Operation_push(center_x);
3084     Operation_push(center_y);
3085     Operation_push(tangent_x);
3086     Operation_push(tangent_y);
3087 
3088     Operation_push(Paintbrush_X);
3089     Operation_push(Paintbrush_Y);
3090 
3091     // On change la forme du curseur
3092     Cursor_shape=CURSOR_SHAPE_XOR_TARGET;
3093 
3094     // On affiche une croix XOR au centre du cercle
3095     Draw_curve_cross(center_x,center_y);
3096 
3097     if (Menu_is_visible)
3098     {
3099       if (Config.Coords_rel)
3100         Print_in_menu("X:        Y:",0);
3101       else
3102         Print_in_menu("X:       Y:             ",0);
3103       Display_coords_rel_or_abs(center_x,center_y);
3104     }
3105   }
3106   else
3107   {
3108     long limit;
3109     limit=((tangent_x-center_x)*(tangent_x-center_x))+
3110            ((tangent_y-center_y)*(tangent_y-center_y));
3111     Hide_empty_circle_preview(center_x,center_y,limit);
3112 
3113     Paintbrush_hidden=Paintbrush_hidden_before_scroll;
3114     Cursor_shape=CURSOR_SHAPE_TARGET;
3115 
3116     Draw_filled_circle(center_x,center_y,limit,Back_color);
3117 
3118     End_of_modification();
3119     if ((Config.Coords_rel) && (Menu_is_visible))
3120     {
3121       Print_in_menu("X:       Y:             ",0);
3122       Print_coordinates();
3123     }
3124   }
3125 }
3126 
3127 
Grad_circle_12_8(void)3128 void Grad_circle_12_8(void)
3129 //
3130 // Opération   : OPERATION_GRAD_CIRCLE
3131 // Click Souris: 0
3132 // Taille_Pile : 8 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente, old_x, old_y)
3133 //
3134 // Souris effacée: Oui
3135 //
3136 {
3137   short tangent_x;
3138   short tangent_y;
3139   short center_x;
3140   short center_y;
3141   short color;
3142   short old_mouse_k;
3143   long limit;
3144 
3145   Operation_stack_size-=2;   // On fait sauter les 2 derniers élts de la pile
3146   Operation_pop(&tangent_y);
3147   Operation_pop(&tangent_x);
3148   Operation_pop(&center_y);
3149   Operation_pop(&center_x);
3150   Operation_pop(&color);
3151   Operation_pop(&old_mouse_k);
3152 
3153   Hide_cursor();
3154   // On efface la croix XOR au centre du cercle
3155   Draw_curve_cross(center_x,center_y);
3156 
3157   limit=((tangent_x-center_x)*(tangent_x-center_x))+
3158          ((tangent_y-center_y)*(tangent_y-center_y));
3159   Hide_empty_circle_preview(center_x,center_y,limit);
3160 
3161   Paintbrush_hidden=Paintbrush_hidden_before_scroll;
3162   Cursor_shape=CURSOR_SHAPE_TARGET;
3163 
3164   if (Mouse_K==old_mouse_k)
3165     Draw_grad_circle(center_x,center_y,limit,Paintbrush_X,Paintbrush_Y);
3166   Cursor_shape=CURSOR_SHAPE_XOR_TARGET;
3167 
3168   Display_cursor();
3169   End_of_modification();
3170   Wait_end_of_click();
3171 
3172   if ((Config.Coords_rel) && (Menu_is_visible))
3173   {
3174     Print_in_menu("X:       Y:             ",0);
3175     Print_coordinates();
3176   }
3177 }
3178 
3179 
Grad_circle_or_ellipse_0_8(void)3180 void Grad_circle_or_ellipse_0_8(void)
3181 //
3182 // Opération   : OPERATION_{CERCLE|ELLIPSE}_DEGRADE
3183 // Click Souris: 0
3184 // Taille_Pile : 8
3185 //
3186 // Souris effacée: Non
3187 //
3188 {
3189   short start_x;
3190   short start_y;
3191   short tangent_x;
3192   short tangent_y;
3193   short old_x;
3194   short old_y;
3195 
3196   Operation_pop(&old_y);
3197   Operation_pop(&old_x);
3198 
3199   if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y))
3200   {
3201     Operation_pop(&tangent_y);
3202     Operation_pop(&tangent_x);
3203     Operation_pop(&start_y);
3204     Operation_pop(&start_x);
3205     Display_coords_rel_or_abs(start_x,start_y);
3206     Operation_push(start_x);
3207     Operation_push(start_y);
3208     Operation_push(tangent_x);
3209     Operation_push(tangent_y);
3210   }
3211 
3212   Operation_push(Paintbrush_X);
3213   Operation_push(Paintbrush_Y);
3214 }
3215 
3216 
3217 ////////////////////////////////////////////////// OPERATION_GRAD_ELLIPSE
3218 
3219 
Grad_ellipse_12_0(void)3220 void Grad_ellipse_12_0(void)
3221 //
3222 // Opération   : OPERATION_GRAD_ELLIPSE
3223 // Click Souris: 1 ou 2
3224 // Taille_Pile : 0
3225 //
3226 // Souris effacée: Oui
3227 {
3228   byte color;
3229 
3230   Init_start_operation();
3231   Backup();
3232   Load_gradient_data(Current_gradient);
3233 
3234 
3235   Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
3236   color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
3237 
3238   Paintbrush_hidden_before_scroll=Paintbrush_hidden;
3239   Paintbrush_hidden=1;
3240 
3241   Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color);
3242   Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
3243 
3244   if ((Config.Coords_rel) && (Menu_is_visible))
3245     Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
3246 
3247   Operation_push(Mouse_K);
3248   Operation_push(color);
3249   Operation_push(Paintbrush_X);
3250   Operation_push(Paintbrush_Y);
3251   Operation_push(Paintbrush_X);
3252   Operation_push(Paintbrush_Y);
3253 }
3254 
3255 
Grad_ellipse_12_6(void)3256 void Grad_ellipse_12_6(void)
3257 //
3258 // Opération   : OPERATION_GRAD_ELLIPSE
3259 // Click Souris: 1 ou 2
3260 // Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
3261 //
3262 // Souris effacée: Non
3263 //
3264 {
3265   short tangent_x;
3266   short tangent_y;
3267   short center_x;
3268   short center_y;
3269   short color;
3270   short horizontal_radius;
3271   short vertical_radius;
3272 
3273   Operation_pop(&tangent_y);
3274   Operation_pop(&tangent_x);
3275   Operation_pop(&center_y);
3276   Operation_pop(&center_x);
3277   Operation_pop(&color);
3278 
3279   if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) )
3280   {
3281     Hide_cursor();
3282     Display_coords_rel_or_abs(center_x,center_y);
3283 
3284     if ((Selected_circle_ellipse_mode & MASK_CENTER_CORNERS) == MODE_CENTER)
3285     {
3286       Cursor_shape=CURSOR_SHAPE_TARGET;
3287       horizontal_radius=(tangent_x>center_x)?tangent_x-center_x
3288                                              :center_x-tangent_x;
3289       vertical_radius  =(tangent_y>center_y)?tangent_y-center_y
3290                                              :center_y-tangent_y;
3291       Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius);
3292 
3293       horizontal_radius=(Paintbrush_X>center_x)?Paintbrush_X-center_x
3294                                            :center_x-Paintbrush_X;
3295       vertical_radius  =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y
3296                                            :center_y-Paintbrush_Y;
3297       Draw_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color);
3298     }
3299     else
3300     {
3301       Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y);
3302       Draw_empty_inscribed_ellipse_preview(center_x,center_y,Paintbrush_X,Paintbrush_Y,color);
3303     }
3304 
3305     Display_cursor();
3306   }
3307 
3308   Operation_push(color);
3309   Operation_push(center_x);
3310   Operation_push(center_y);
3311   Operation_push(Paintbrush_X);
3312   Operation_push(Paintbrush_Y);
3313 }
3314 
3315 
Grad_ellipse_0_6(void)3316 void Grad_ellipse_0_6(void)
3317 //
3318 // Opération   : OPERATION_GRAD_ELLIPSE
3319 // Click Souris: 0
3320 // Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente)
3321 //
3322 // Souris effacée: Oui
3323 //
3324 {
3325   short tangent_x;
3326   short tangent_y;
3327   short center_x;
3328   short center_y;
3329   short color;
3330   short click;
3331   //short radius;
3332   short horizontal_radius;
3333   short vertical_radius;
3334 
3335   Operation_pop(&tangent_y);
3336   Operation_pop(&tangent_x);
3337   Operation_pop(&center_y);
3338   Operation_pop(&center_x);
3339 
3340   Operation_pop(&color);
3341   Operation_pop(&click);
3342 
3343   if (click==LEFT_SIDE)
3344   {
3345     Operation_push(click);
3346     Operation_push(color);
3347 
3348     Operation_push(center_x);
3349     Operation_push(center_y);
3350     Operation_push(tangent_x);
3351     Operation_push(tangent_y);
3352 
3353     Operation_push(Paintbrush_X);
3354     Operation_push(Paintbrush_Y);
3355 
3356     // On change la forme du curseur
3357     Cursor_shape=CURSOR_SHAPE_XOR_TARGET;
3358 
3359     // On affiche une croix XOR au centre du cercle
3360     if ((Selected_circle_ellipse_mode & MASK_CENTER_CORNERS) == MODE_CENTER)
3361       Draw_curve_cross(center_x,center_y);
3362     else
3363       Draw_curve_cross((center_x+tangent_x)/2, (center_y+tangent_y)/2);
3364 
3365     if (Menu_is_visible)
3366     {
3367       if (Config.Coords_rel)
3368         Print_in_menu("X:        Y:",0);
3369       else
3370         Print_in_menu("X:       Y:             ",0);
3371       Display_coords_rel_or_abs(center_x,center_y);
3372     }
3373   }
3374   else
3375   {
3376     Paintbrush_hidden=Paintbrush_hidden_before_scroll;
3377     Cursor_shape=CURSOR_SHAPE_TARGET;
3378 
3379     if ((Selected_circle_ellipse_mode & MASK_CENTER_CORNERS) == MODE_CENTER)
3380     {
3381       horizontal_radius=(tangent_x>center_x)?tangent_x-center_x
3382                                              :center_x-tangent_x;
3383       vertical_radius  =(tangent_y>center_y)?tangent_y-center_y
3384                                              :center_y-tangent_y;
3385       Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius);
3386       Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Back_color);
3387     }
3388     else
3389     {
3390       Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y);
3391       Draw_filled_inscribed_ellipse(center_x,center_y,tangent_x,tangent_y,Back_color);
3392     }
3393 
3394     End_of_modification();
3395     if ((Config.Coords_rel) && (Menu_is_visible))
3396     {
3397       Print_in_menu("X:       Y:             ",0);
3398       Print_coordinates();
3399     }
3400   }
3401 }
3402 
3403 
Grad_ellipse_12_8(void)3404 void Grad_ellipse_12_8(void)
3405 //
3406 // Opération   : OPERATION_GRAD_ELLIPSE
3407 // Click Souris: 0
3408 // Taille_Pile : 8 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente, old_x, old_y)
3409 //
3410 // Souris effacée: Oui
3411 //
3412 {
3413   short tangent_x;
3414   short tangent_y;
3415   short center_x;
3416   short center_y;
3417   short color;
3418   short horizontal_radius=0;
3419   short vertical_radius=0;
3420   short old_mouse_k;
3421 
3422   Operation_stack_size-=2;   // On fait sauter les 2 derniers élts de la pile
3423   Operation_pop(&tangent_y);
3424   Operation_pop(&tangent_x);
3425   Operation_pop(&center_y);
3426   Operation_pop(&center_x);
3427   Operation_pop(&color);
3428   Operation_pop(&old_mouse_k);
3429 
3430   Hide_cursor();
3431   // On efface la croix XOR au centre de l'ellipse
3432   if ((Selected_circle_ellipse_mode & MASK_CENTER_CORNERS) == MODE_CENTER)
3433   {
3434     Draw_curve_cross(center_x,center_y);
3435     horizontal_radius=(tangent_x>center_x)?tangent_x-center_x
3436                                            :center_x-tangent_x;
3437     vertical_radius  =(tangent_y>center_y)?tangent_y-center_y
3438                                            :center_y-tangent_y;
3439     Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius);
3440   }
3441   else
3442   {
3443     Draw_curve_cross((center_x+tangent_x)/2, (center_y+tangent_y)/2);
3444     Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y);
3445   }
3446 
3447   Paintbrush_hidden=Paintbrush_hidden_before_scroll;
3448   Cursor_shape=CURSOR_SHAPE_XOR_TARGET;
3449 
3450   if (Mouse_K==old_mouse_k)
3451   {
3452     if ((Selected_circle_ellipse_mode & MASK_CENTER_CORNERS) == MODE_CENTER)
3453       Draw_grad_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Paintbrush_X,Paintbrush_Y);
3454     else
3455       Draw_grad_inscribed_ellipse(center_x,center_y,tangent_x,tangent_y,Paintbrush_X,Paintbrush_Y);
3456   }
3457 
3458   Display_cursor();
3459   End_of_modification();
3460   Wait_end_of_click();
3461 
3462   if ((Config.Coords_rel) && (Menu_is_visible))
3463   {
3464     Print_in_menu("X:       Y:             ",0);
3465     Print_coordinates();
3466   }
3467 }
3468 
3469 /******************************
3470 * Operation_Rectangle_Degrade *
3471 ******************************/
3472 
3473 // 1) tracé d'un rectangle classique avec les lignes XOR
3474 // 2) tracé d'une ligne vecteur de dégradé, comme une ligne normale
3475 // 3) dessin du dégradé
3476 
3477 
Grad_rectangle_12_0(void)3478 void Grad_rectangle_12_0(void)
3479 // Opération   : OPERATION_GRAD_RECTANGLE
3480 // Click Souris: 1 ou 2
3481 // Taille_Pile : 0
3482 //
3483 // Souris effacée: Oui
3484 
3485 // Initialisation de l'étape 1, on commence à dessiner le rectangle
3486 {
3487   Init_start_operation();
3488   Backup();
3489   Load_gradient_data(Current_gradient);
3490 
3491   if ((Config.Coords_rel) && (Menu_is_visible))
3492     Print_in_menu("\035:   1   \022:   1",0);
3493   // On laisse une trace du curseur à l'écran
3494   Display_cursor();
3495 
3496   if (Mouse_K==LEFT_SIDE)
3497   {
3498     Shade_table=Shade_table_left;
3499     Operation_push(Mouse_K);
3500   }
3501   else
3502   {
3503     Shade_table=Shade_table_right;
3504     Operation_push(Mouse_K);
3505   }
3506 
3507   Operation_push(Paintbrush_X);
3508   Operation_push(Paintbrush_Y);
3509   Operation_push(Paintbrush_X);
3510   Operation_push(Paintbrush_Y);
3511 }
3512 
3513 
Grad_rectangle_12_5(void)3514 void Grad_rectangle_12_5(void)
3515 // Opération   : OPERATION_GRAD_RECTANGLE
3516 // Click Souris: 1 ou 2
3517 // Taille_Pile : 5
3518 //
3519 // Souris effacée: Non
3520 
3521 // Modification de la taille du rectangle
3522 {
3523   short start_x;
3524   short start_y;
3525   short old_x;
3526   short old_y;
3527   char  str[5];
3528 
3529   Operation_pop(&old_y);
3530   Operation_pop(&old_x);
3531 
3532   if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y))
3533   {
3534     Operation_pop(&start_y);
3535     Operation_pop(&start_x);
3536 
3537     if ((Config.Coords_rel) && (Menu_is_visible))
3538     {
3539       Num2str(((start_x<Paintbrush_X)?Paintbrush_X-start_x:start_x-Paintbrush_X)+1,str,4);
3540       Print_in_menu(str,2);
3541       Num2str(((start_y<Paintbrush_Y)?Paintbrush_Y-start_y:start_y-Paintbrush_Y)+1,str,4);
3542       Print_in_menu(str,11);
3543     }
3544     else
3545       Print_coordinates();
3546 
3547     Operation_push(start_x);
3548     Operation_push(start_y);
3549   }
3550 
3551   Operation_push(Paintbrush_X);
3552   Operation_push(Paintbrush_Y);
3553 }
3554 
3555 // Start and End coordinates must be sorted
Draw_xor_rect(short start_x,short start_y,short end_x,short end_y)3556 void Draw_xor_rect(short start_x, short start_y, short end_x, short end_y)
3557 {
3558   short offset_width = 0;
3559   short offset_height = 0;
3560   short offset_left = 0;
3561   short offset_top = 0;
3562   short width = end_x-start_x;
3563   short height = end_y-start_y;
3564 
3565   // Handle clipping
3566   if (end_x-Main.offset_X > Min(Main.image_width,
3567     Main.magnifier_mode?Main.separator_position:Screen_width))
3568   {
3569     offset_width = end_x - Min(Main.image_width,
3570       Main.magnifier_mode?Main.separator_position:Screen_width);
3571   }
3572 
3573   if (end_y-Main.offset_Y > Min(Main.image_height, Menu_Y))
3574     offset_height = end_y - Min(Main.image_height, Menu_Y);
3575 
3576   if (width == 0)
3577   {
3578     // Single line
3579     Vertical_XOR_line(start_x-Main.offset_X, start_y
3580       - Main.offset_Y, height - offset_height + 1);
3581   }
3582   else if (height == 0)
3583   {
3584     // Single line
3585     Horizontal_XOR_line(start_x-Main.offset_X,
3586       start_y - Main.offset_Y, width - offset_width + 1);
3587   }
3588   else
3589   {
3590     // Dessin dans la zone de dessin normale
3591     Horizontal_XOR_line(start_x-Main.offset_X,
3592       start_y - Main.offset_Y, width - offset_width + 1);
3593 
3594     // If not, this line is out of the picture so there is no need to draw it
3595     if (offset_height == 0 || end_y - 1 > Menu_Y + Main.offset_Y)
3596     {
3597       Horizontal_XOR_line(start_x - Main.offset_X, end_y
3598         - Main.offset_Y, width - offset_width + 1);
3599     }
3600 
3601     if (height > offset_height + 2)
3602     {
3603       Vertical_XOR_line(start_x-Main.offset_X, start_y
3604         - Main.offset_Y + 1, height - offset_height - 1);
3605 
3606       if (offset_width == 0)
3607       {
3608         Vertical_XOR_line(end_x - Main.offset_X, start_y
3609           - Main.offset_Y + 1, height - offset_height - 1);
3610       }
3611     }
3612   }
3613 
3614   Update_rect(start_x - Main.offset_X, start_y - Main.offset_Y,
3615     width + 1 - offset_width, height + 1 - offset_height);
3616 
3617   // Dessin dans la zone zoomée
3618   if (Main.magnifier_mode && start_x <= Limit_right_zoom
3619     && end_x > Limit_left_zoom
3620     && start_y <= Limit_bottom_zoom
3621     && end_y > Limit_top_zoom )
3622   {
3623     offset_width = 0;
3624     offset_height = 0;
3625 
3626     if (start_x<Limit_left_zoom) // On dépasse du zoom à gauche
3627     {
3628       offset_width += Limit_left_zoom - start_x;
3629       offset_left = Limit_left_zoom;
3630     }
3631 
3632     if(end_x>Limit_right_zoom) // On dépasse du zoom à droite
3633         offset_width += end_x - Limit_right_zoom;
3634 
3635     if(start_y<Limit_top_zoom) // On dépasse du zoom en haut
3636     {
3637         offset_height += Limit_top_zoom - start_y;
3638         offset_top = Limit_top_zoom;
3639     }
3640 
3641     if(end_y>Limit_bottom_zoom) // On dépasse du zoom en bas
3642         offset_height += end_y - Limit_bottom_zoom;
3643 
3644     if(width > offset_width)
3645     {
3646       if(offset_top==0) // La ligne du haut est visible
3647         Horizontal_XOR_line_zoom(offset_left>0?offset_left:start_x,start_y,width-offset_width+1);
3648 
3649       if(height!=0 && end_y<=Limit_bottom_zoom) // La  ligne du bas est visible
3650         Horizontal_XOR_line_zoom(offset_left>0?offset_left:start_x,end_y,width-offset_width+1);
3651     }
3652     if (width==0 && height!=0 && height > offset_height && offset_left==0)
3653     {
3654       // Single vertical line
3655       Vertical_XOR_line_zoom(start_x,offset_top!=0?offset_top:start_y,height-offset_height);
3656     }
3657     else
3658     {
3659       if(height > offset_height + 2)
3660       {
3661         if(offset_left==0) // La ligne de gauche est visible
3662           Vertical_XOR_line_zoom(start_x,offset_top!=0?offset_top:(start_y+1),height-offset_height-(offset_top==0)+(end_y>Limit_bottom_zoom));
3663 
3664         if(end_x<=Limit_right_zoom) // La ligne de droite est visible
3665           Vertical_XOR_line_zoom(end_x,offset_top!=0?offset_top:(start_y+1),height-offset_height-(offset_top==0)+(end_y>Limit_bottom_zoom));
3666       }
3667     }
3668   }
3669 }
Grad_rectangle_0_5(void)3670 void Grad_rectangle_0_5(void)
3671 // OPERATION_GRAD_RECTANGLE
3672 // click souris 0
3673 // Taile pile : 5
3674 //
3675 // Souris effacée : non
3676 
3677 // Le rectangle est en place, maintenant il faut tracer le vecteur de dégradé,
3678 // on doit donc attendre que l'utilisateur clique quelque part
3679 // On stocke tout de suite les coordonnées du pinceau comme ça on change d'état et on passe à la suite
3680 {
3681   // !!! Cette fonction remet start_x start_y end_x end_y dans la pile à la fin donc il ne faut pas les modifier ! (sauf éventuellement un tri)
3682   short start_x;
3683   short start_y;
3684   short end_x;
3685   short end_y;
3686 
3687   // Tracé propre du rectangle
3688   Operation_pop(&end_y);
3689   Operation_pop(&end_x);
3690   Operation_pop(&start_y);
3691   Operation_pop(&start_x);
3692 
3693   // This trick will erase the large crosshair at original position,
3694   // in normal and zoomed views.
3695   Paintbrush_X = start_x;
3696   Paintbrush_Y = start_y;
3697 
3698   if (start_x>end_x)
3699     SWAP_SHORTS(start_x, end_x)
3700 
3701   if (start_y>end_y)
3702     SWAP_SHORTS(start_y, end_y)
3703 
3704   Hide_cursor();
3705 
3706   // Check if the rectangle is not fully outside the picture
3707   if (start_x > Main.image_width                  // Rectangle at right of picture
3708       || start_y > Main.image_height              // Rectangle below picture
3709       || start_y - 1 - Main.offset_Y > Menu_Y )   // Rectangle below viewport
3710   {
3711     Operation_pop(&end_y); // reset the stack
3712     return; // cancel the operation
3713   }
3714   Draw_xor_rect(start_x, start_y, end_x, end_y);
3715 
3716   Operation_push(start_x);
3717   Operation_push(start_y);
3718   Operation_push(end_x);
3719   Operation_push(end_y);
3720 
3721   // On ajoute des trucs dans la pile pour forcer le passage à l'étape suivante
3722   Operation_push(end_x);
3723   Operation_push(end_y);
3724 }
3725 
Grad_rectangle_0_7(void)3726 void Grad_rectangle_0_7(void)
3727 // OPERATION_GRAD_RECTANGLE
3728 // click souris 0
3729 // Taile pile : 5
3730 //
3731 // Souris effacée : non
3732 
3733 // On continue à attendre que l'utilisateur clique en gardant les coords à jour
3734 {
3735     Operation_stack_size -= 2;
3736     Print_coordinates();
3737     Operation_push(Paintbrush_X);
3738     Operation_push(Paintbrush_Y);
3739 }
3740 
Grad_rectangle_12_7(void)3741 void Grad_rectangle_12_7(void)
3742 // Opération   : OPERATION_GRAD_RECTANGLE
3743 // Click Souris: 1 ou 2
3744 // Taille_Pile : 7
3745 //
3746 //  Souris effacée: Oui
3747 
3748 //  Début du tracé du vecteur (premier clic)
3749 // On garde les anciennes coordonnées dans la pile, et on ajoute les nouvelles par dessus
3750 
3751 // Si l'utilisateur utilise le mauvais bouton, on annule le tracé. Mais ça nous oblige à vider toute la pile pour vérifier :(
3752 {
3753   short start_x,end_x,start_y,end_y,vax,vay,click;
3754 
3755   Operation_pop(&vay);
3756   Operation_pop(&vax);
3757   Operation_pop(&end_y);
3758   Operation_pop(&end_x);
3759   Operation_pop(&start_y);
3760   Operation_pop(&start_x);
3761   Operation_pop(&click);
3762 
3763 
3764   if(click==Mouse_K)
3765   {
3766       Operation_push(click);
3767       Operation_push(start_x);
3768       Operation_push(start_y);
3769       Operation_push(end_x);
3770       Operation_push(end_y);
3771       Operation_push(vax);
3772       Operation_push(vay);
3773       Operation_push(Paintbrush_X);
3774       Operation_push(Paintbrush_Y);
3775 
3776   }
3777   else
3778   {
3779       // Mauvais bouton > anulation de l'opération.
3780       // On a déjà vidé la pile, il reste à effacer le rectangle XOR
3781       Draw_xor_rect(start_x, start_y, end_x, end_y);
3782   }
3783 }
3784 
Grad_rectangle_12_9(void)3785 void Grad_rectangle_12_9(void)
3786     // Opération   : OPERATION_GRAD_RECTANGLE
3787     // Click Souris: 1
3788     // Taille_Pile : 9
3789     //
3790     // Souris effacée: Oui
3791 
3792     // Poursuite du tracé du vecteur (déplacement de la souris en gardant le curseur appuyé)
3793 {
3794     short start_x;
3795     short start_y;
3796     short end_x;
3797     short end_y;
3798     short cursor_x;
3799     short cursor_y;
3800 
3801     Operation_pop(&end_y);
3802     Operation_pop(&end_x);
3803     Operation_pop(&start_y);
3804     Operation_pop(&start_x);
3805 
3806     cursor_x = Paintbrush_X;
3807     cursor_y = Paintbrush_Y;
3808     // On corrige les coordonnées de la ligne si la touche shift est appuyée...
3809     if(Get_Key_modifiers() & GFX2_MOD_SHIFT)
3810         Clamp_coordinates_regular_angle(start_x,start_y,&cursor_x,&cursor_y);
3811 
3812     if ((cursor_x!=end_x) || (cursor_y!=end_y))
3813     {
3814         Display_coords_rel_or_abs(start_x,start_y);
3815 
3816         Draw_line_preview_xor(start_x,start_y,end_x,end_y,0);
3817         Draw_line_preview_xor(start_x,start_y,cursor_x,cursor_y,0);
3818 
3819     }
3820 
3821 
3822     Operation_push(start_x);
3823     Operation_push(start_y);
3824     Operation_push(cursor_x);
3825     Operation_push(cursor_y);
3826 }
3827 
Grad_rectangle_0_9(void)3828 void Grad_rectangle_0_9(void)
3829     // Opération   : OPERATION_GRAD_RECTANGLE
3830     // Click Souris: 0
3831     // Taille_Pile : 9
3832     //
3833     //  Souris effacée: Oui
3834 
3835     // Ouf, fini ! on dessine enfin le rectangle avec son dégradé
3836 {
3837     short rect_start_x;
3838     short rect_start_y;
3839     short rect_end_x;
3840     short rect_end_y;
3841 
3842     short vector_start_x;
3843     short vector_start_y;
3844     short vector_end_x;
3845     short vector_end_y;
3846 
3847     Operation_pop(&vector_end_y);
3848     Operation_pop(&vector_end_x);
3849     Operation_pop(&vector_start_y);
3850     Operation_pop(&vector_start_x);
3851     Operation_pop(&rect_end_y);
3852     Operation_pop(&rect_end_x);
3853     Operation_pop(&rect_start_y);
3854     Operation_pop(&rect_start_x);
3855     Operation_stack_size--;
3856 
3857     Hide_cursor();
3858     // Maintenant on efface tout le bazar temporaire : rectangle et ligne XOR
3859     Draw_xor_rect(rect_start_x, rect_start_y, rect_end_x, rect_end_y);
3860     Hide_line_preview(vector_start_x,vector_start_y,vector_end_x,vector_end_y);
3861 
3862     // Et enfin on trace le rectangle avec le dégradé dedans !
3863     if (vector_end_x==vector_start_x && vector_end_y==vector_start_y)
3864     {
3865         // Vecteur nul > pas de rectangle tracé
3866     }
3867     else
3868     {
3869         Draw_grad_rectangle(rect_start_x,rect_start_y,rect_end_x,rect_end_y,vector_start_x,vector_start_y,vector_end_x,vector_end_y);
3870     }
3871     Display_cursor();
3872     End_of_modification();
3873     Wait_end_of_click();
3874 
3875     if ((Config.Coords_rel) && (Menu_is_visible))
3876     {
3877         Print_in_menu("X:       Y:             ",0);
3878         Print_coordinates();
3879     }
3880 }
3881 /////////////////////////////////////////////////// OPERATION_CENTERED_LINES
3882 
3883 
Centered_lines_12_0(void)3884 void Centered_lines_12_0(void)
3885     // Opération   : OPERATION_CENTERED_LINES
3886     // Click Souris: 1 ou 2
3887     // Taille_Pile : 0
3888     //
3889     //  Souris effacée: Oui
3890 {
3891     if (Rightclick_colorpick(0))
3892       return;
3893 
3894     Init_start_operation();
3895     Backup();
3896     Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
3897 
3898     if ((Config.Coords_rel) && (Menu_is_visible))
3899         Print_in_menu("X:\xb1   0   Y:\xb1   0",0);
3900 
3901     Operation_push(Mouse_K);
3902     Operation_push(Paintbrush_X);
3903     Operation_push(Paintbrush_Y);
3904 }
3905 
3906 
Centered_lines_12_3(void)3907 void Centered_lines_12_3(void)
3908     // Opération   : OPERATION_CENTERED_LINES
3909     // Click Souris: 1 ou 2
3910     // Taille_Pile : 3
3911     //
3912     // Souris effacée: Non
3913 {
3914     short start_x;
3915     short start_y;
3916 
3917     Operation_pop(&start_y);
3918     Operation_pop(&start_x);
3919     Operation_push(Paintbrush_X);
3920     Operation_push(Paintbrush_Y);
3921 }
3922 
3923 
Centered_lines_0_3(void)3924 void Centered_lines_0_3(void)
3925     // Opération   : OPERATION_CENTERED_LINES
3926     // Click Souris: 0
3927     // Taille_Pile : 3
3928     //
3929     // Souris effacée: Oui
3930 {
3931     short start_x;
3932     short start_y;
3933     short Button;
3934     short color;
3935 
3936     Operation_pop(&start_y);
3937     Operation_pop(&start_x);
3938     Operation_pop(&Button);
3939 
3940     color=(Button==LEFT_SIDE)?Fore_color:Back_color;
3941 
3942     Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color);
3943     Paintbrush_shape_before_operation=Paintbrush_shape;
3944     Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
3945 
3946     Operation_push(Button);
3947     Operation_push(Paintbrush_X); // Nouveau début X
3948     Operation_push(Paintbrush_Y); // Nouveau début Y
3949     Operation_push(Paintbrush_X); // Nouvelle dernière fin X
3950     Operation_push(Paintbrush_Y); // Nouvelle dernière fin Y
3951     Operation_push(Paintbrush_X); // Nouvelle dernière position X
3952     Operation_push(Paintbrush_Y); // Nouvelle dernière position Y
3953 }
3954 
3955 
Centered_lines_12_7(void)3956 void Centered_lines_12_7(void)
3957     // Opération   : OPERATION_CENTERED_LINES
3958     // Click Souris: 1 ou 2
3959     // Taille_Pile : 7
3960     //
3961     // Souris effacée: Non
3962 {
3963     short Button;
3964     short start_x;
3965     short start_y;
3966     short end_x;
3967     short end_y;
3968     short last_x;
3969     short last_y;
3970     short color;
3971 
3972     Operation_pop(&last_y);
3973     Operation_pop(&last_x);
3974     Operation_pop(&end_y);
3975     Operation_pop(&end_x);
3976     Operation_pop(&start_y);
3977     Operation_pop(&start_x);
3978     Operation_pop(&Button);
3979 
3980     if (Mouse_K==Button)
3981     {
3982         if ( (end_x!=Paintbrush_X) || (end_y!=Paintbrush_Y) ||
3983                 (last_x!=Paintbrush_X) || (last_y!=Paintbrush_Y) )
3984         {
3985             Hide_cursor();
3986 
3987             color=(Button==LEFT_SIDE)?Fore_color:Back_color;
3988 
3989             Paintbrush_shape=Paintbrush_shape_before_operation;
3990 
3991             Pixel_figure_preview_auto  (start_x,start_y);
3992             Hide_line_preview (start_x,start_y,last_x,last_y);
3993 
3994             Smear_start=1;
3995             Draw_paintbrush            (start_x,start_y,color);
3996             Draw_line_permanent(start_x,start_y,Paintbrush_X,Paintbrush_Y,color);
3997 
3998             Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
3999             Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color);
4000             Draw_line_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y,color);
4001 
4002             Display_cursor();
4003         }
4004 
4005         Operation_push(Button);
4006         Operation_push(start_x);
4007         Operation_push(start_y);
4008         Operation_push(Paintbrush_X);
4009         Operation_push(Paintbrush_Y);
4010         Operation_push(Paintbrush_X);
4011         Operation_push(Paintbrush_Y);
4012     }
4013     else
4014     {
4015         Hide_cursor();
4016 
4017         Paintbrush_shape=Paintbrush_shape_before_operation;
4018 
4019         Pixel_figure_preview_auto  (start_x,start_y);
4020         Hide_line_preview (start_x,start_y,last_x,last_y);
4021 
4022         if ( (Config.Coords_rel) && (Menu_is_visible) )
4023         {
4024             Print_in_menu("X:       Y:             ",0);
4025             Print_coordinates();
4026         }
4027 
4028         Display_cursor();
4029         End_of_modification();
4030         Wait_end_of_click();
4031     }
4032 }
4033 
4034 
Centered_lines_0_7(void)4035 void Centered_lines_0_7(void)
4036     // Opération   : OPERATION_CENTERED_LINES
4037     // Click Souris: 0
4038     // Taille_Pile : 7
4039     //
4040     // Souris effacée: Non
4041 {
4042     short Button;
4043     short start_x;
4044     short start_y;
4045     short end_x;
4046     short end_y;
4047     short last_x;
4048     short last_y;
4049     short color;
4050 
4051     Operation_pop(&last_y);
4052     Operation_pop(&last_x);
4053     Operation_pop(&end_y);
4054     Operation_pop(&end_x);
4055 
4056     if ((Paintbrush_X!=last_x) || (Paintbrush_Y!=last_y))
4057     {
4058         Hide_cursor();
4059         Operation_pop(&start_y);
4060         Operation_pop(&start_x);
4061         Operation_pop(&Button);
4062 
4063         color=(Button==LEFT_SIDE)?Fore_color:Back_color;
4064 
4065         Display_coords_rel_or_abs(start_x,start_y);
4066 
4067         Hide_line_preview(start_x,start_y,last_x,last_y);
4068 
4069         Pixel_figure_preview(start_x,start_y,color);
4070         Draw_line_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y,color);
4071 
4072         Operation_push(Button);
4073         Operation_push(start_x);
4074         Operation_push(start_y);
4075         Display_cursor();
4076     }
4077 
4078     Operation_push(end_x);
4079     Operation_push(end_y);
4080     Operation_push(Paintbrush_X);
4081     Operation_push(Paintbrush_Y);
4082 }
4083 
4084 ///////////////////////////////////////////////////////////// OPERATION_PAN_VIEW
4085 
Pan_view_0_0(void)4086 void Pan_view_0_0(void)
4087 // Opération   : OPERATION_PAN_VIEW
4088 // Click Souris: 0
4089 // Taille_Pile : 0
4090 //
4091 //  Souris effacée: Non
4092 {
4093   if (Pan_shortcut_pressed)
4094   {
4095     Print_coordinates();
4096   }
4097   else
4098   {
4099     // End of operation, return to previous
4100     Hide_cursor();
4101     Start_operation_stack(Operation_before_pan);
4102     Display_cursor();
4103   }
4104 }
4105 
Pan_view_12_0(void)4106 void Pan_view_12_0(void)
4107 // Opération   : OPERATION_PAN_VIEW
4108 // Click Souris: 1 ou 2
4109 // Taille_Pile : 0
4110 //
4111 //  Souris effacée: Non
4112 
4113 //  First time the user clicks
4114 {
4115   Init_start_operation();
4116 
4117   Operation_push(Paintbrush_X);
4118   Operation_push(Paintbrush_Y);
4119 }
4120 
Pan_view_12_2(void)4121 void Pan_view_12_2(void)
4122 // Opération   : OPERATION_PAN_VIEW
4123 // Click Souris: 1 ou 2
4124 // Taille_Pile : 2
4125 //
4126 //  Souris effacée: Non
4127 
4128 //  While dragging view
4129 {
4130   short start_x;
4131   short start_y;
4132 
4133   Operation_pop(&start_y);
4134   Operation_pop(&start_x);
4135 
4136   if (Paintbrush_X!=start_x || Paintbrush_Y!=start_y)
4137   {
4138     // User moved
4139     if (Main.magnifier_mode)
4140       Scroll_magnifier(start_x-Paintbrush_X,start_y-Paintbrush_Y);
4141     else
4142       Scroll_screen(start_x-Paintbrush_X,start_y-Paintbrush_Y);
4143   }
4144   // The "scroll" functions have actualized the Paintbrush_X and Y
4145   if (Paintbrush_X!=start_x || Paintbrush_Y!=start_y)
4146   {
4147     Print_coordinates();
4148   }
4149   Operation_push(Paintbrush_X);
4150   Operation_push(Paintbrush_Y);
4151 }
4152 
Pan_view_0_2(void)4153 void Pan_view_0_2(void)
4154 // Opération   : OPERATION_PAN_VIEW
4155 // Click Souris: 0
4156 // Taille_Pile : 2
4157 //
4158 //  Souris effacée: Non
4159 
4160 //  When releasing after dragging
4161 {
4162   short start_x;
4163   short start_y;
4164 
4165   Operation_pop(&start_y);
4166   Operation_pop(&start_x);
4167 
4168   if (!Pan_shortcut_pressed)
4169   {
4170     // End of operation, return to previous
4171     Hide_cursor();
4172     Start_operation_stack(Operation_before_pan);
4173     Display_cursor();
4174   }
4175 }
4176