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 
21 ////////////////////////////////////////////////////////////////////////////
22 ///@file buttons_effects.c
23 /// Handles all the effects buttons and setup windows in the effects menu.
24 ////////////////////////////////////////////////////////////////////////////
25 
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "gfx2log.h"
30 #include "brush.h"
31 #include "buttons.h"
32 #include "engine.h"
33 #include "global.h"
34 #include "graph.h"
35 #include "help.h"
36 #include "input.h"
37 #include "misc.h"
38 #include "pages.h"
39 #include "readline.h"
40 #include "screen.h"
41 #include "struct.h"
42 #include "windows.h"
43 #include "tiles.h"
44 #include "oldies.h"
45 #include "palette.h"
46 #include "layers.h"
47 
48 #ifndef MIN
49 #define MIN(a,b) ((a)<(b)?(a):(b))
50 #endif
51 
52 //---------- Menu dans lequel on tagge des couleurs (genre Stencil) ----------
Menu_tag_colors(char * window_title,byte * table,byte * mode,byte can_cancel,const char * help_section,word close_shortcut)53 void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section, word close_shortcut)
54 {
55   short clicked_button;
56   byte backup_table[256];
57   word index;
58   word old_mouse_x;
59   word old_mouse_y;
60   byte old_mouse_k;
61   byte tagged_color;
62   byte color;
63   byte click;
64 
65 
66   Open_window(176,150,window_title);
67 
68   Window_set_palette_button(6,38);                            // 1
69   Window_set_normal_button( 7, 19,78,14,"Clear" ,1,1,KEY_c); // 2
70   Window_set_normal_button(91, 19,78,14,"Invert",1,1,KEY_i); // 3
71   if (can_cancel)
72   {
73     Window_set_normal_button(91,129,78,14,"OK"    ,0,1,KEY_RETURN); // 4
74     Window_set_normal_button( 7,129,78,14,"Cancel",0,1,KEY_ESC);  // 5
75     // On enregistre la table dans un backup au cas où on ferait Cancel
76     memcpy(backup_table,table,256);
77   }
78   else
79     Window_set_normal_button(49,129,78,14,"OK"    ,0,1,KEY_RETURN); // 4
80 
81   // On affiche l'état actuel de la table
82   for (index=0; index<=255; index++)
83     Stencil_tag_color(index, (table[index])?MC_Black:MC_Light);
84 
85   Update_window_area(0,0,Window_width, Window_height);
86   Display_cursor();
87 
88   do
89   {
90     old_mouse_x=Mouse_X;
91     old_mouse_y=Mouse_Y;
92     old_mouse_k=Mouse_K;
93 
94     clicked_button=Window_clicked_button();
95 
96     switch (clicked_button)
97     {
98       case  0 :
99         break;
100       case -1 :
101       case  1 : // Palette
102         if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) )
103         {
104           Hide_cursor();
105           tagged_color=(clicked_button==1) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y);
106           table[tagged_color]=(Mouse_K==LEFT_SIDE);
107           Stencil_tag_color(tagged_color,(Mouse_K==LEFT_SIDE)?MC_Black:MC_Light);
108           Display_cursor();
109           Stencil_update_color(tagged_color);
110         }
111         break;
112       case  2 : // Clear
113         memset(table,0,256);
114         Hide_cursor();
115         for (index=0; index<=255; index++)
116           Stencil_tag_color(index,MC_Light);
117         Display_cursor();
118         Update_window_area(0,0,Window_width, Window_height);
119         break;
120       case  3 : // Invert
121         Hide_cursor();
122         for (index=0; index<=255; index++)
123           Stencil_tag_color(index,(table[index]^=1)?MC_Black:MC_Light);
124         Display_cursor();
125         Update_window_area(0,0,Window_width, Window_height);
126     }
127 
128     if (!Mouse_K)
129     switch (Key)
130     {
131       case KEY_BACKQUOTE : // Récupération d'une couleur derrière le menu
132       case KEY_COMMA :
133         Get_color_behind_window(&color,&click);
134         if (click)
135         {
136           Hide_cursor();
137           tagged_color=color;
138           table[tagged_color]=(click==LEFT_SIDE);
139           Stencil_tag_color(tagged_color,(click==LEFT_SIDE)?MC_Black:MC_Light);
140           Stencil_update_color(tagged_color);
141           Display_cursor();
142           Wait_end_of_click();
143         }
144         Key=0;
145         break;
146       default:
147       if (Is_shortcut(Key,0x100+BUTTON_HELP))
148       {
149         Window_help(BUTTON_EFFECTS, help_section);
150         Key=0;
151         break;
152       }
153       else if (Is_shortcut(Key,close_shortcut))
154       {
155         clicked_button=4;
156       }
157     }
158   }
159   while (clicked_button<4);
160 
161   Close_window();
162 
163   if (clicked_button==5) // Cancel
164     memcpy(table,backup_table,256);
165   else // OK
166     *mode=1;
167 
168   Display_cursor();
169 }
170 
171 
172 /// Block Constraint check
173 ///
174 /// This function count the number of colors in a block and reports errors
175 /// by marking the pixel in color 17 in layer 2.
176 /// @param mode
177 /// @return -1 if the mode is invalid
178 /// @return the number of constraint errors detected
Check_block_constraints(enum IMAGE_MODES mode)179 static int Check_block_constraints(enum IMAGE_MODES mode)
180 {
181   int x, y, x2, y2;
182   int block_width = 8, block_height = 8, max_colors = 2;  // default values
183   int error_count = 0;
184   byte errcol = 17;
185   byte pal_mask;
186 
187   switch (mode)
188   {
189     case IMAGE_MODE_TMS9918G2:
190     case IMAGE_MODE_THOMSON:
191       block_height = 1;
192       break;
193     case IMAGE_MODE_ZX:
194     case IMAGE_MODE_C64HIRES:
195       break;
196     case IMAGE_MODE_C64MULTI:
197       block_width = 4;
198       max_colors = 3; // 3 + background color
199       break;
200     case IMAGE_MODE_GBC:
201       max_colors = 4;
202       errcol = 33;
203       break;
204     case IMAGE_MODE_MEGADRIVE:
205       max_colors = 16;
206       errcol = 65;
207       break;
208     default:
209       return -1;  // unsupported mode
210   }
211   pal_mask = ~(max_colors - 1);
212 
213   for (y = 0; y <= Main.image_height - block_height; y += block_height)
214   {
215     for (x = 0; x <= Main.image_width - block_width; x += block_width)
216     {
217       int count = 0;
218       byte c[16];   // colors already used in block
219 
220       for (y2 = 0; y2 < block_height; y2++)
221       {
222         for (x2 = 0; x2 < block_width; x2++)
223         {
224           int i;
225           byte col = Read_pixel_from_layer(0, x+x2, y+y2);
226           if (mode == IMAGE_MODE_GBC || mode == IMAGE_MODE_MEGADRIVE)
227           {
228             if (count == 0)
229               c[count++] = col;
230             else if ((col & pal_mask) != (c[0] & pal_mask))  // compare palettes
231             {
232               if (Main.backups->Pages->Nb_layers < 2)
233                 Add_layer(Main.backups, 1);
234               Pixel_in_layer(1, x+x2, y+y2, errcol);
235               error_count++;
236             }
237             continue;
238           }
239           if (col > 15) // forbidden color !
240           {
241             if (Main.backups->Pages->Nb_layers < 2)
242               Add_layer(Main.backups, 1);
243             Pixel_in_layer(1, x+x2, y+y2, errcol);
244             error_count++;
245             continue;
246           }
247           if (mode == IMAGE_MODE_C64MULTI && col == 0)  // Background color
248             continue;
249           // search color in already used ones
250           for (i = 0; i < count; i++)
251           {
252             if (col == c[i])
253               break;
254             // ZX Spectrum : consider both blacks as the same color
255             if (mode == IMAGE_MODE_ZX && (col & 7) == 0 && (c[i] & 7) == 0)
256               break;
257           }
258           if (i >= count) // not found
259           {
260             // ZX Spectrum : check that both colors have same intensity (except black)
261             if (mode == IMAGE_MODE_ZX && count > 0)
262             {
263               if ((col & 8) != (c[0] & 8) && (col & 7) != 0 && (c[0] & 7) != 0)
264               {
265                 GFX2_Log(GFX2_INFO, "Check_block_constraints() intensity error at (%d,%d) color=%d (other color=%d)\n", x+x2, y+y2, col, c[0]);
266                 if (Main.backups->Pages->Nb_layers < 2)
267                   Add_layer(Main.backups, 1);
268                 Pixel_in_layer(1, x+x2, y+y2, errcol);
269                 error_count++;
270                 continue;
271               }
272             }
273             if (count >= max_colors)
274             {
275               // constraint error : add color 17 pixel in layer 2
276               GFX2_Log(GFX2_INFO, "Check_block_constraints() constraint error at (%d,%d)\n", x+x2, y+y2);
277               if (Main.backups->Pages->Nb_layers < 2)
278                 Add_layer(Main.backups, 1);
279               if (mode == IMAGE_MODE_TMS9918G2)
280               {
281                 Pixel_in_layer(1, x+x2, y+y2, col); // put color in sprite layer
282                 Pixel_in_layer(0, x+x2, y+y2, c[0]); // put other color in picture layer
283               }
284               else
285                 Pixel_in_layer(1, x+x2, y+y2, errcol);
286               error_count++;
287             }
288             else
289               c[count++] = col;
290           }
291         }
292       }
293     }
294   }
295   if (error_count > 0)
296     Main.current_layer = 0; // activate layer 1 again
297   return error_count;
298 }
299 
300 /// convert a picture to the HGR mode
301 ///
302 /// Recognize monochrome pictures.
303 /// Color pictures should use the 8 first colors.
Convert_to_hgr(void)304 static void Convert_to_hgr(void)
305 {
306   int i;
307   word count, x, y;
308   dword usage[256];
309 
310   count = Count_used_colors(usage);
311   if (count <= 1) // blank picture, nothing to do :)
312     return;
313   if (count == 2) // monochrome !
314   {
315     byte bg, fg;
316     i = 0;
317     while (usage[i] == 0 && i < 256)
318       i++;
319     bg = (byte)i;
320     i++;
321     while (usage[i] == 0 && i < 256)
322       i++;
323     fg = (byte)i;
324     GFX2_Log(GFX2_DEBUG, "Convert_to_hgr() monochrome bg=%u fg=%u\n", bg, fg);
325     if (!(bg == 0 && fg == 3) && !(bg == 4 && fg == 7))
326     {
327       // convert to B&W
328       for (y = 0; y < Main.image_height; y++)
329       {
330         for (x = 0; x < Main.image_width; x++)
331         {
332           byte c = Read_pixel_from_layer(0, x, y);
333           Pixel_in_layer(0, x, y, (c == fg) ? 3 : 0);
334         }
335       }
336     }
337   }
338   else
339   {
340     // "convert" color picture to B&W
341     for (y = 0; y < Main.image_height; y++)
342     {
343       for (x = 0; x < Main.image_width; x++)
344       {
345         byte c = Read_pixel_from_layer(0, x, y);
346         switch (c & 3)
347         {
348           case 0: // black
349           case 3: // white
350             Pixel_in_layer(0, x, y, c);
351             break;
352           case 1: // green/orange
353           case 2: // purple/blue
354             Pixel_in_layer(0, x, y, (c & 4) | (((c & 1) ^ (x & 1) ^ 1) * 3));
355         }
356       }
357     }
358   }
359   // update color layer
360   for (y = 0; y < Main.image_height; y++)
361   {
362     for (x = 0; x < Main.image_width; x++)
363     {
364       Update_color_hgr_pixel(x, y, 0);
365     }
366   }
367 }
368 
369 /// convert a picture to the DHGR mode
370 ///
371 /// Recognize monochrome pictures.
Convert_to_dhgr(void)372 static void Convert_to_dhgr(void)
373 {
374   int i;
375   word count, x, y;
376   dword usage[256];
377 
378   count = Count_used_colors(usage);
379   if (count <= 1) // blank picture, nothing to do :)
380     return;
381   if (count == 2) // monochrome !
382   {
383     byte bg, fg;
384     i = 0;
385     while (usage[i] == 0 && i < 256)
386       i++;
387     bg = (byte)i;
388     i++;
389     while (usage[i] == 0 && i < 256)
390       i++;
391     fg = (byte)i;
392     GFX2_Log(GFX2_DEBUG, "Convert_to_dhgr() monochrome bg=%u fg=%u\n", bg, fg);
393     if (!(bg == 0 && fg == 3) && !(bg == 4 && fg == 7))
394     {
395       // convert to B&W
396       for (y = 0; y < Main.image_height; y++)
397       {
398         for (x = 0; x < Main.image_width; x++)
399         {
400           byte c = Read_pixel_from_layer(0, x, y);
401           Pixel_in_layer(0, x, y, (c == fg) ? 15 : 0);
402         }
403       }
404     }
405   }
406   else
407   {
408     // "convert" color picture to B&W
409     for (y = 0; y < Main.image_height; y++)
410     {
411       for (x = 0; x < Main.image_width; x += 4)
412       {
413         byte c = Read_pixel_from_layer(0, x, y);
414         Pixel_in_layer(0, x, y, c & 0x18);
415         Pixel_in_layer(0, x + 1, y, c & 0x14);
416         Pixel_in_layer(0, x + 2, y, c & 0x12);
417         Pixel_in_layer(0, x + 3, y, c & 0x11);
418       }
419     }
420   }
421   // update color layer
422   for (y = 0; y < Main.image_height; y++)
423   {
424     for (x = 0; x < Main.image_width; x += 4)
425     {
426       Update_color_dhgr_pixel(x, y, 0);
427     }
428   }
429 }
430 
431 
432 /// Constaint enforcer/checker
433 ///
434 /// A call toggles between constraint mode and Layered mode.
Button_Constraint_mode(void)435 void Button_Constraint_mode(void)
436 {
437   int pixel;
438 
439   if (Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION)
440   {
441     // Disable
442     Switch_layer_mode(IMAGE_MODE_LAYERED);
443     return;
444   }
445 
446   if (Selected_Constraint_Mode <= IMAGE_MODE_ANIMATION)
447     Selected_Constraint_Mode = IMAGE_MODE_EGX;  ///@todo load prefered/last used contrained mode from config ?
448 
449   if (Selected_Constraint_Mode == IMAGE_MODE_MODE5 && (Main.image_width%48))
450   {
451     Verbose_message("Error!", "Emulation of Amstrad CPC's Mode5 can only be used on an image whose width is a multiple of 48.");
452     return;
453   }
454   if (Selected_Constraint_Mode == IMAGE_MODE_C64FLI && ((Main.image_width < 160) || (Main.image_height < 200)))
455   {
456     Verbose_message("Error!", "Emulation of Commodore 64 FLI Mode needs a 160x200 sized image.");
457     return;
458   }
459 
460   // now check the constraints on existing pixels
461   switch (Selected_Constraint_Mode)
462   {
463   case IMAGE_MODE_MODE5:
464   case IMAGE_MODE_RASTER:
465     // switch to layer mode if needed
466     if (Main.backups->Pages->Image_mode != IMAGE_MODE_LAYERED)
467       Switch_layer_mode(IMAGE_MODE_LAYERED);
468     // auto-create extra layers
469     while (Main.backups->Pages->Nb_layers < 5)
470       if (Add_layer(Main.backups, Main.backups->Pages->Nb_layers))
471       {
472         Verbose_message("Error!", "Failed to create the 5 layers needed by Emulation of Amstrad CPC's rasters.");
473         return;
474       }
475     for (pixel=0; pixel < Main.image_width*Main.image_height; pixel++)
476     {
477       if (Main.backups->Pages->Image[4].Pixels[pixel]>3)
478       {
479         GFX2_Log(GFX2_INFO, "pixel[%u]=0x%02x\n", pixel, Main.backups->Pages->Image[4].Pixels[pixel]);
480         Verbose_message("Error!", "Emulation of Amstrad CPC's rasters needs all pixels of layer 5 to use colors 0-3.");
481         return;
482       }
483     }
484     break;
485   case IMAGE_MODE_C64FLI:
486     // switch to layer mode if needed
487     if (Main.backups->Pages->Image_mode != IMAGE_MODE_LAYERED)
488       Switch_layer_mode(IMAGE_MODE_LAYERED);
489     Main.backups->Pages->Transparent_color = 16;
490     // auto-create extra layers
491     while (Main.backups->Pages->Nb_layers < 3)
492       if (Add_layer(Main.backups, 0))
493       {
494         Verbose_message("Error!", "Failed to create the 3 layers needed by C64 Flexible Line Interpretation mode.");
495         return;
496       }
497     {
498       word x, y;
499       byte bitmap[8000],screen_ram[1024*8],color_ram[1024];
500       byte background[200];
501 
502       memset(bitmap, 0, sizeof(bitmap));
503       memset(screen_ram, 0, sizeof(screen_ram));
504       memset(color_ram, 0, sizeof(color_ram));
505       memset(background, 0, sizeof(background));
506 
507       // give "hints" to the converter
508       for (y = 0; y < 200; y++)
509         background[y] = Read_pixel_from_layer(0, 0, y);
510       for (y = 0; y < 25; y++)
511       {
512         for (x = 0; x < 40; x++)
513           color_ram[x + y*40] = Read_pixel_from_layer(1, x*4, y*8);
514       }
515 
516       if (C64_pixels_to_FLI(bitmap, screen_ram, color_ram, background, Main.backups->Pages->Image[2].Pixels, Main.image_width, 1) > 0)
517       {
518         // put errors in layer 4 if not already done
519         if (Main.backups->Pages->Nb_layers < 4)
520         {
521           Add_layer(Main.backups, Main.backups->Pages->Nb_layers);
522           C64_pixels_to_FLI(bitmap, screen_ram, color_ram, background, Main.backups->Pages->Image[2].Pixels, Main.image_width, 1);
523         }
524       }
525 
526       // copy background to layer 1
527       // and color RAM to layer 2
528       for (y = 0; y < 200; y++)
529       {
530         for (x = 0; x < 160; x++)
531         {
532           Pixel_in_layer(0, x, y, background[y]);
533           Pixel_in_layer(1, x, y, color_ram[(x >> 2) + (y >> 3)*40]);
534         }
535       }
536     }
537     break;
538   case IMAGE_MODE_HGR:
539   case IMAGE_MODE_DHGR:
540     // switch to layer mode if needed
541     if (Main.backups->Pages->Image_mode != IMAGE_MODE_LAYERED)
542       Switch_layer_mode(IMAGE_MODE_LAYERED);
543     // auto-create extra layers
544     while (Main.backups->Pages->Nb_layers < 2)
545       if (Add_layer(Main.backups, Main.backups->Pages->Nb_layers))
546       {
547         Verbose_message("Error!", "Failed to create the 2 layers needed by Emulation of Apple II HGR or DHGR.");
548         return;
549       }
550     if (Selected_Constraint_Mode == IMAGE_MODE_HGR)
551       Convert_to_hgr();
552     else
553       Convert_to_dhgr();
554     break;
555   case IMAGE_MODE_TMS9918G2:
556     // switch to layer mode if needed
557     if (Main.backups->Pages->Image_mode != IMAGE_MODE_LAYERED)
558       Switch_layer_mode(IMAGE_MODE_LAYERED);
559     Main.backups->Pages->Transparent_color = 0;
560     Check_block_constraints(Selected_Constraint_Mode);
561     break;
562   default:
563     Check_block_constraints(Selected_Constraint_Mode);
564   }
565   /// Setting the palette is done in @ref Button_Constraint_menu (8-bit constraint window)
566 
567   /// @todo backup
568   Switch_layer_mode(Selected_Constraint_Mode);
569 }
570 
571 
Button_Constraint_menu(void)572 void Button_Constraint_menu(void)
573 {
574   unsigned int i;
575   int set_palette = 1;
576   int set_pic_size = 0;
577   int set_grid = 1;
578   short clicked_button;
579   T_Dropdown_button* dropdown;
580   const char * label;
581   const char * summary;
582   static const struct {
583     enum IMAGE_MODES mode;
584     const char * label;
585     const char * summary;
586     int grid;
587   } modes[] = {
588     {IMAGE_MODE_ZX,      "ZX Spectrum",   "2 colors per 8x8 block", 1}, // 256x192
589     {IMAGE_MODE_GBC,     "Game Boy Color","4 colors per 8x8 block", 1}, // 160x144 to 256x256
590     {IMAGE_MODE_MEGADRIVE,"Sega MegaDrive","16colors per 8x8 block",1}, // 256x224 to 1024x256
591     {IMAGE_MODE_THOMSON, "40col (MO/TO)", "2 colors per 8x1 block", 1}, // 320x200
592     {IMAGE_MODE_EGX,     "EGX (CPC)",     "Alternate Mode0/Mode1 ", 0}, // 320x200
593     {IMAGE_MODE_EGX2,    "EGX2 (CPC)",    "Alternate Mode1/Mode2 ", 0}, // 640x200
594     {IMAGE_MODE_MODE5,   "Mode 5 (CPC)",  "Mode5                 ", 0}, // 288x256
595     {IMAGE_MODE_RASTER,  "Rasters (CPC)", "CPC Rasters           ", 1},
596     {IMAGE_MODE_C64HIRES,"C64 HiRes",     "2 colors per 8x8 block", 1}, // 320x200
597     {IMAGE_MODE_C64MULTI,"C64 Multicolor","4 colors per 4x1 block", 1}, // 160x200
598     {IMAGE_MODE_C64FLI,  "C64 FLI",       "improved multicolor   ", 1}, // 160x200
599     {IMAGE_MODE_HGR,     "Apple II HGR",  "6 colors              ", 1},  // 280x192
600     {IMAGE_MODE_DHGR,    "Apple II DHGR", "\"Le Chat Mauve\" mode3 ", 1},  // 560x192
601     {IMAGE_MODE_TMS9918G2,"TMS9918 Mode 2","MSX Screen2, etc.    ", 1},  // 256x192
602   };
603 
604   Open_window(194,95+36,"8-bit constraints");
605 
606   Window_set_normal_button(31,71+36,51,14,"Cancel",0,1,KEY_ESC);  // 1
607   Window_set_normal_button(112,71+36,51,14,"OK"    ,0,1,KEY_RETURN); // 2
608 
609   label = "Constraints";
610   summary = "";
611   for (i = 0; i < sizeof(modes)/sizeof(modes[0]) ; i++)
612     if (Selected_Constraint_Mode == modes[i].mode)
613     {
614       label = modes[i].label;
615       summary = modes[i].summary;
616       set_grid = modes[i].grid;
617       break;
618     }
619   dropdown = Window_set_dropdown_button(32, 21, 130, 14, 120, label, 1, 0, 1, RIGHT_SIDE|LEFT_SIDE, 0); // 3
620   for (i = 0; i < sizeof(modes)/sizeof(modes[0]) ; i++)
621     Window_dropdown_add_item(dropdown, modes[i].mode, modes[i].label);
622   Print_in_window(10, 21+18, summary, MC_Dark, MC_Light);
623 
624   Window_set_normal_button(10, 51, 14, 14, set_palette?"X":" ", 0, 1, KEY_p);  // 4
625   Print_in_window_underscore(10+18, 51+3, "Set palette", MC_Dark, MC_Light, 5);
626 
627   Window_set_normal_button(10, 69, 14, 14, set_pic_size?"X":" ", 0, 1, KEY_s);  // 5
628   Print_in_window_underscore(10+18, 69+3, "Set picture size", MC_Dark, MC_Light, 13);
629 
630   Window_set_normal_button(10, 87, 14, 14, set_grid?"X":" ", 0, 1, KEY_g);  // 6
631   Print_in_window_underscore(10+18, 87+3, "Enable grid", MC_Dark, MC_Light, 8);
632 
633   Update_window_area(0,0,Window_width, Window_height);
634   Display_cursor();
635 
636   do
637   {
638     clicked_button=Window_clicked_button();
639     if (Is_shortcut(Key, 0x100+BUTTON_HELP))
640     {
641       Key = 0;
642       Window_help(BUTTON_EFFECTS, "8 BIT");
643     }
644     else if (clicked_button == 3)
645     {
646       if (Selected_Constraint_Mode == IMAGE_MODE_GBC || Selected_Constraint_Mode == IMAGE_MODE_MEGADRIVE)
647         set_palette = 1;  // activate palette back when switching from GBC
648       Selected_Constraint_Mode = Window_attribute2;
649       for (i = 0; i < sizeof(modes)/sizeof(modes[0]) ; i++)
650         if (Selected_Constraint_Mode == modes[i].mode)
651         {
652           set_grid = modes[i].grid;
653           Hide_cursor();
654           Print_in_window(10, 21+18, modes[i].summary, MC_Dark, MC_Light);
655           Display_cursor();
656           break;
657         }
658       if (Selected_Constraint_Mode == IMAGE_MODE_GBC || Selected_Constraint_Mode == IMAGE_MODE_MEGADRIVE)
659         set_palette = 0;
660     }
661     else if (clicked_button == 4) // palette
662       set_palette = !set_palette;
663     else if (clicked_button == 5) // picture size
664       set_pic_size = !set_pic_size;
665     else if (clicked_button == 6) // enable grid
666       set_grid = !set_grid;
667 
668     if (clicked_button > 0) // refresh buttons
669     {
670       Hide_cursor();
671       Print_in_window(10+3, 51+3, set_palette?"X":" ", MC_Black, MC_Light);
672       Print_in_window(10+3, 69+3, set_pic_size?"X":" ", MC_Black, MC_Light);
673       Print_in_window(10+3, 87+3, set_grid?"X":" ", MC_Black, MC_Light);
674       Display_cursor();
675     }
676   }
677   while ( (clicked_button!=1) && (clicked_button!=2) );
678 
679   Close_window();
680 
681   if (clicked_button==2) // OK
682   {
683     if (Selected_Constraint_Mode > IMAGE_MODE_ANIMATION)
684     {
685       if (set_pic_size)
686       {
687         switch (Selected_Constraint_Mode)
688         {
689           case IMAGE_MODE_ZX:
690             Resize_image(256, 192);
691             End_of_modification();
692             break;
693           case IMAGE_MODE_GBC:
694             Resize_image(160, 144);
695             End_of_modification();
696             break;
697           case IMAGE_MODE_MODE5:
698             Resize_image(288, 256);
699             End_of_modification();
700             break;
701           case IMAGE_MODE_EGX:
702           case IMAGE_MODE_THOMSON:
703           case IMAGE_MODE_C64HIRES:
704             Resize_image(320, 200);
705             End_of_modification();
706             break;
707           case IMAGE_MODE_EGX2:
708             Resize_image(640, 200);
709             End_of_modification();
710             break;
711           case IMAGE_MODE_C64MULTI:
712           case IMAGE_MODE_C64FLI:
713             Resize_image(160, 200);
714             End_of_modification();
715             /// @todo enable WIDE pixels when switching to 160x200
716             break;
717           case IMAGE_MODE_HGR:
718             Resize_image(280, 192);
719             End_of_modification();
720             break;
721           case IMAGE_MODE_DHGR:
722             Resize_image(560, 192);
723             End_of_modification();
724             /// @todo enable TALL pixels when switching to 560x192
725             break;
726           case IMAGE_MODE_TMS9918G2:
727             Resize_image(256, 192);
728             End_of_modification();
729             break;
730           default:
731             break;
732         }
733       }
734       if (Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION)
735         Button_Constraint_mode();  // unactivate current mode
736       Button_Constraint_mode();  // activate selected Mode
737       if (set_grid)
738       {
739         switch (Selected_Constraint_Mode)
740         {
741           case IMAGE_MODE_ZX:
742           case IMAGE_MODE_GBC:
743           case IMAGE_MODE_C64HIRES:
744           case IMAGE_MODE_MEGADRIVE:
745             Snap_width = 8;
746             Snap_height = 8;
747             break;
748           case IMAGE_MODE_C64MULTI:
749           case IMAGE_MODE_C64FLI:
750             Snap_width = 4;
751             Snap_height = 8;
752             break;
753           case IMAGE_MODE_RASTER:
754           case IMAGE_MODE_THOMSON:
755           case IMAGE_MODE_TMS9918G2:
756             Snap_width = 8;
757             Snap_height = 999;  // maximum value (3 digits)
758             break;
759           case IMAGE_MODE_HGR:
760             Snap_width = 7;
761             Snap_height = 999;  // maximum value (3 digits)
762             break;
763           case IMAGE_MODE_DHGR:
764             Snap_width = 4;
765             Snap_height = 999;  // maximum value (3 digits)
766             break;
767           default:
768             set_grid = 0;
769         }
770         if (set_grid)
771         {
772           Show_grid = 1;
773           Snap_offset_X = 0;
774           Snap_offset_Y = 0;
775           Snap_mode = 0;
776           //Tilemap_update();
777           Display_all_screen();
778         }
779       }
780       if (set_palette)
781       {
782         switch (Selected_Constraint_Mode)
783         {
784           case IMAGE_MODE_ZX:
785             memset(Main.palette, 0, sizeof(T_Palette));
786             ZX_Spectrum_set_palette(Main.palette);
787             First_color_in_palette = 0;
788             Fore_color = 7;
789             Back_color = 0;
790             break;
791           case IMAGE_MODE_MEGADRIVE:  // 64 colors among 512
792             memset(Main.palette + 64, 0, sizeof(T_Components) * (256 - 64));
793             Main.palette[65].R = 255; // for color clashes
794             First_color_in_palette = 0;
795             Fore_color = 15;
796             Back_color = 0;
797             break;
798           case IMAGE_MODE_GBC:  // 32 colors among 32768
799             memset(Main.palette + 32, 0, sizeof(T_Components) * (256 - 32));
800             Main.palette[33].R = 255; // for color clashes
801             First_color_in_palette = 0;
802             Fore_color = 3;
803             Back_color = 0;
804             break;
805           case IMAGE_MODE_THOMSON:
806             {
807               static const T_MultipleChoice moto_choices[] = {
808                 { MACHINE_TO7, "TO7 / TO7/70", "16 colors" },
809                 { MACHINE_MO5, "MO5", "16 colors" },
810                 { MACHINE_TO8, "TO9/TO8/TO9+", "4096 colors" },
811                 { MACHINE_MO6, "MO6", "4096 colors" },
812                 { -1, NULL, NULL }
813               };
814               int machine = Dialog_multiple_choice("Select machine", moto_choices, -1);
815               if (machine >= 0)
816               {
817                 memset(Main.palette, 0, sizeof(T_Palette));
818                 if (machine == MACHINE_MO5 || machine == MACHINE_MO6)
819                   MOTO_set_MO5_palette(Main.palette);
820                 else
821                   MOTO_set_TO7_palette(Main.palette);
822                 if (machine == MACHINE_MO6 || machine == MACHINE_TO8)
823                 {
824                   Set_palette_Gamma(Config.MOTO_gamma);
825                   Set_palette_RGB_scale(16);
826                 }
827                 First_color_in_palette = 0;
828                 Fore_color = 7;
829                 Back_color = 0;
830               }
831             }
832             break;
833           case IMAGE_MODE_EGX:
834           case IMAGE_MODE_EGX2:
835             {
836               static const T_MultipleChoice cpc_choices[] = {
837                 { 1, "CPC", "27 colors" },
838                 { 2, "CPC+", "4096 colors" },
839                 { -1, NULL, NULL }
840               };
841               int machine = Dialog_multiple_choice("Select machine", cpc_choices, -1);
842               if (machine >= 0)
843               {
844                 memset(Main.palette, 0, sizeof(T_Palette));
845                 CPC_set_default_BASIC_palette(Main.palette);
846                 First_color_in_palette = 0;
847                 Fore_color = 1;
848                 Back_color = 0;
849                 if (machine == 2)
850                   Set_palette_RGB_scale(16);
851                 else
852                   Set_palette_RGB_scale(3);
853               }
854             }
855             break;
856           case IMAGE_MODE_MODE5:
857           case IMAGE_MODE_RASTER:
858             memset(Main.palette, 0, sizeof(T_Palette));
859             // setup colors 0,1,2,3 to see something in the thumbnail preview of layer 5
860             Main.palette[1].R = 60;
861             Main.palette[2].B = 60;
862             Main.palette[3].G = 60;
863             CPC_set_HW_palette(Main.palette + 0x40);
864             First_color_in_palette = 64;
865             Fore_color = 0x4b;
866             Back_color = 0x54;
867             break;
868           case IMAGE_MODE_C64HIRES:
869           case IMAGE_MODE_C64MULTI:
870           case IMAGE_MODE_C64FLI:
871             memset(Main.palette, 0, sizeof(T_Palette));
872             C64_set_palette(Main.palette);
873             First_color_in_palette = 0;
874             Fore_color = 1;
875             Back_color = 0;
876             break;
877           case IMAGE_MODE_HGR:
878             memset(Main.palette, 0, sizeof(T_Palette));
879             HGR_set_palette(Main.palette);
880             First_color_in_palette = 0;
881             Fore_color = 3;
882             Back_color = 0;
883             break;
884           case IMAGE_MODE_DHGR:
885             memset(Main.palette, 0, sizeof(T_Palette));
886             DHGR_set_palette(Main.palette);
887             First_color_in_palette = 0;
888             Fore_color = 15;
889             Back_color = 0;
890             break;
891           case IMAGE_MODE_TMS9918G2:
892             memset(Main.palette, 0, sizeof(T_Palette));
893             MSX_set_palette(Main.palette);
894             First_color_in_palette = 0;
895             Fore_color = 15;  // White
896             Back_color = 1;   // Black
897             break;
898           default:
899             break;
900         }
901         for (i = 0; i < 4; i++)
902           memcpy(Main.palette + 252 + i, Favorite_GUI_color(i), sizeof(T_Components));
903         // Refresh palette
904         Set_palette(Main.palette);
905         Compute_optimal_menu_colors(Main.palette);
906         Remap_screen_after_menu_colors_change();
907         Redraw_layered_image();
908         Check_menu_mode();
909         Display_all_screen();
910         //Display_menu_palette();
911         Display_menu();
912       }
913     }
914   }
915 
916   Display_cursor();
917 }
918 
919 // Tilemap mode
Button_Tilemap_mode(void)920 void Button_Tilemap_mode(void)
921 {
922   Main.tilemap_mode=!Main.tilemap_mode;
923   Tilemap_update();
924 }
925 
Button_Tilemap_menu(void)926 void Button_Tilemap_menu(void)
927 {
928   short clicked_button;
929 
930   byte flip_x=Config.Tilemap_allow_flipped_x;
931   byte flip_y=Config.Tilemap_allow_flipped_y;
932   byte count=Config.Tilemap_show_count;
933 
934   Open_window(166,120,"Tilemap options");
935 
936   Window_set_normal_button(6,102,51,14,"Cancel",0,1,KEY_ESC);  // 1
937   Window_set_normal_button(110,102,51,14,"OK"    ,0,1,KEY_RETURN); // 2
938 
939   Print_in_window(24,21, "Detect mirrored",MC_Dark,MC_Light);
940   Window_display_frame(5,17,155,56);
941 
942   Print_in_window(37,37, "Horizontally",MC_Black,MC_Light);
943   Window_set_normal_button(18,34,13,13,flip_x?"X":"",0,1,0);  // 3
944 
945   Print_in_window(37,55, "Vertically",MC_Black,MC_Light);
946   Window_set_normal_button(18,52,13,13,flip_y?"X":"",0,1,0);  // 4
947 
948   Print_in_window(27,81, "Show count",MC_Black,MC_Light);
949   Window_set_normal_button(7,78,13,13,count?"X":"",0,1,0);  // 5
950 
951   Update_window_area(0,0,Window_width, Window_height);
952 
953   Display_cursor();
954 
955   do
956   {
957     clicked_button=Window_clicked_button();
958 
959     switch (clicked_button)
960     {
961       case 3 : // Horizontal flip
962         flip_x=!flip_x;
963         Hide_cursor();
964         Print_in_window(21,37,flip_x?"X":" ", MC_Black, MC_Light);
965         Display_cursor();
966         break;
967       case 4 : // Vertical flip
968         flip_y=!flip_y;
969         Hide_cursor();
970         Print_in_window(21,55,flip_y?"X":" ", MC_Black, MC_Light);
971         Display_cursor();
972         break;
973       case 5 : // Count
974         count=!count;
975         Hide_cursor();
976         Print_in_window(10,81,count?"X":" ", MC_Black, MC_Light);
977         Display_cursor();
978         break;
979     }
980     if (Is_shortcut(Key,0x100+BUTTON_HELP))
981       Window_help(BUTTON_EFFECTS, "TILEMAP");
982   }
983   while ( (clicked_button!=1) && (clicked_button!=2) );
984 
985   if (clicked_button==2) // OK
986   {
987     byte changed =
988       Config.Tilemap_allow_flipped_x!=flip_x ||
989       Config.Tilemap_allow_flipped_y!=flip_y ||
990       !Main.tilemap_mode;
991 
992     Config.Tilemap_allow_flipped_x=flip_x;
993     Config.Tilemap_allow_flipped_y=flip_y;
994     Config.Tilemap_show_count=count;
995 
996     if (changed)
997     {
998       Main.tilemap_mode=1;
999       Tilemap_update();
1000     }
1001   }
1002   Close_window();
1003   Display_cursor();
1004 }
1005 
1006 //--------------------------------- Stencil ----------------------------------
Button_Stencil_mode(void)1007 void Button_Stencil_mode(void)
1008 {
1009   Stencil_mode=!Stencil_mode;
1010 }
1011 
1012 
Stencil_tag_color(byte color,byte tag_color)1013 void Stencil_tag_color(byte color, byte tag_color)
1014 {
1015   Window_rectangle(Window_palette_button_list->Pos_X+4+(color >> 4)*10,
1016         Window_palette_button_list->Pos_Y+3+(color & 15)* 5,
1017         2,5,tag_color);
1018 }
1019 
Stencil_update_color(byte color)1020 void Stencil_update_color(byte color)
1021 {
1022   Update_window_area(Window_palette_button_list->Pos_X+4+(color >> 4)*10,
1023       Window_palette_button_list->Pos_Y+3+(color & 15)* 5,
1024       2,5);
1025 }
1026 
Button_Stencil_menu(void)1027 void Button_Stencil_menu(void)
1028 {
1029   Menu_tag_colors("Stencil",Stencil,&Stencil_mode,1, "STENCIL", SPECIAL_STENCIL_MENU);
1030 }
1031 
1032 
1033 //--------------------------------- Masque -----------------------------------
Button_Mask_mode(void)1034 void Button_Mask_mode(void)
1035 {
1036   Mask_mode=!Mask_mode;
1037 }
1038 
1039 
Button_Mask_menu(void)1040 void Button_Mask_menu(void)
1041 {
1042   Menu_tag_colors("Mask",Mask_table,&Mask_mode,1, "MASK", SPECIAL_MASK_MENU);
1043 }
1044 
1045 
1046 // -------------------------------- Grille -----------------------------------
1047 
Button_Snap_mode(void)1048 void Button_Snap_mode(void)
1049 {
1050   Hide_cursor();
1051   Snap_mode=!Snap_mode;
1052   Compute_paintbrush_coordinates();
1053   Display_cursor();
1054 }
1055 
1056 
Button_Grid_menu(void)1057 void Button_Grid_menu(void)
1058 {
1059   short clicked_button;
1060   word  chosen_X =Snap_width;
1061   word  chosen_Y =Snap_height;
1062   short dx_selected=Snap_offset_X;
1063   short dy_selected=Snap_offset_Y;
1064 
1065   // Entering this window automatically enables "snap"
1066   char snapgrid = 1;
1067 
1068   T_Special_button * input_x_button;
1069   T_Special_button * input_y_button;
1070   T_Special_button * input_dx_button;
1071   T_Special_button * input_dy_button;
1072 
1073   char str[4];
1074 
1075 
1076   Open_window(149,118,"Grid");
1077 
1078   Window_set_normal_button(12,92,51,14,"Cancel",0,1,KEY_ESC);  // 1
1079   Window_set_normal_button(86,92,51,14,"OK"    ,0,1,KEY_RETURN); // 2
1080 
1081   Print_in_window(11,26, "X:",MC_Dark,MC_Light);
1082   input_x_button = Window_set_input_button(29,24,3); // 3
1083   Num2str(MIN(chosen_X, 999), str, 3);
1084   Window_input_content(input_x_button,str);
1085 
1086   Print_in_window(11,47, "Y:",MC_Dark,MC_Light);
1087   input_y_button = Window_set_input_button(29,45,3); // 4
1088   Num2str(MIN(chosen_Y, 999), str, 3);
1089   Window_input_content(input_y_button,str);
1090 
1091   Print_in_window(77,26,"dX:",MC_Dark,MC_Light);
1092   input_dx_button = Window_set_input_button(103,24,3); // 5
1093   Num2str(dx_selected,str,3);
1094   Window_input_content(input_dx_button,str);
1095 
1096   Print_in_window(77,47,"dY:",MC_Dark,MC_Light);
1097   input_dy_button = Window_set_input_button(103,45,3); // 6
1098   Num2str(dy_selected,str,3);
1099 
1100   Window_set_normal_button(12, 62, 14, 14, " ", 0, 1, 0);  // 7
1101   if (snapgrid)
1102     Print_in_window(16, 65, "X", MC_Black, MC_Light);
1103   Print_in_window(32, 65,"Snap",MC_Dark,MC_Light);
1104 
1105   Window_input_content(input_dy_button,str);
1106   Update_window_area(0,0,Window_width, Window_height);
1107 
1108   Display_cursor();
1109 
1110   do
1111   {
1112     clicked_button=Window_clicked_button();
1113 
1114     switch (clicked_button)
1115     {
1116       case 3 :
1117         Num2str(MIN(chosen_X, 999), str, 3);
1118         Readline(31,26,str,3,INPUT_TYPE_INTEGER);
1119         chosen_X=atoi(str);
1120         // On corrige les dimensions
1121         if ((!chosen_X) || (chosen_X>999))
1122         {
1123           if (!chosen_X)
1124             chosen_X=1;
1125           else
1126             chosen_X=999;
1127           Num2str(chosen_X,str,3);
1128           Window_input_content(input_x_button,str);
1129         }
1130         if (dx_selected>=chosen_X)
1131         {
1132           dx_selected=chosen_X-1;
1133           Num2str(dx_selected,str,3);
1134           Window_input_content(input_dx_button,str);
1135         }
1136         Display_cursor();
1137         break;
1138       case 4 :
1139         Num2str(MIN(chosen_Y, 999), str, 3);
1140         Readline(31,47,str,3,INPUT_TYPE_INTEGER);
1141         chosen_Y=atoi(str);
1142         // On corrige les dimensions
1143         if ((!chosen_Y) || (chosen_Y>999))
1144         {
1145           if (!chosen_Y)
1146             chosen_Y=1;
1147           else
1148             chosen_Y=999;
1149           Num2str(chosen_Y,str,3);
1150           Window_input_content(input_y_button,str);
1151         }
1152         if (dy_selected>=chosen_Y)
1153         {
1154           dy_selected=chosen_Y-1;
1155           Num2str(dy_selected,str,3);
1156           Window_input_content(input_dy_button,str);
1157         }
1158         Display_cursor();
1159         break;
1160       case 5 :
1161         Num2str(dx_selected,str,3);
1162         Readline(105,26,str,3,INPUT_TYPE_INTEGER);
1163         dx_selected=atoi(str);
1164         // On corrige les dimensions
1165         if (dx_selected>=chosen_X)
1166           dx_selected=chosen_X-1;
1167 
1168         Num2str(dx_selected,str,3);
1169         Window_input_content(input_dx_button,str);
1170 
1171         Display_cursor();
1172         break;
1173       case 6 :
1174         Num2str(dy_selected,str,3);
1175         Readline(105,47,str,3,INPUT_TYPE_INTEGER);
1176         dy_selected=atoi(str);
1177         // On corrige les dimensions
1178         if (dy_selected>=chosen_Y)
1179           dy_selected=chosen_Y-1;
1180 
1181         Num2str(dy_selected,str,3);
1182         Window_input_content(input_dy_button,str);
1183 
1184         Display_cursor();
1185         break;
1186       case 7:
1187         snapgrid = !snapgrid;
1188         Hide_cursor();
1189         Print_in_window(16, 65, snapgrid?"X":" ", MC_Black, MC_Light);
1190         Display_cursor();
1191         break;
1192     }
1193     if (Is_shortcut(Key,0x100+BUTTON_HELP))
1194       Window_help(BUTTON_EFFECTS, "GRID");
1195   }
1196   while ( (clicked_button!=1) && (clicked_button!=2) );
1197 
1198   if (clicked_button==2) // OK
1199   {
1200     byte modified;
1201 
1202     modified = Snap_width!=chosen_X
1203     || Snap_height!=chosen_Y
1204     || Snap_offset_X!=dx_selected
1205     || Snap_offset_Y!=dy_selected;
1206 
1207     Snap_width=chosen_X;
1208     Snap_height=chosen_Y;
1209     Snap_offset_X=dx_selected;
1210     Snap_offset_Y=dy_selected;
1211     Snap_mode=snapgrid;
1212 
1213     if (modified)
1214     {
1215       Tilemap_update();
1216       Disable_tilemap(&Spare);
1217     }
1218   }
1219 
1220   Close_window();
1221 
1222   Display_cursor();
1223 }
1224 
Button_Show_grid(void)1225 void Button_Show_grid(void)
1226 {
1227   Show_grid = !Show_grid;
1228   Hide_cursor();
1229   Display_all_screen();
1230   Display_cursor();
1231 }
1232 
1233 
1234 // -- Mode Smooth -----------------------------------------------------------
Button_Smooth_mode(void)1235 void Button_Smooth_mode(void)
1236 {
1237   if (Smooth_mode)
1238     Effect_function=No_effect;
1239   else
1240   {
1241     Effect_function=Effect_smooth;
1242     Shade_mode=0;
1243     Quick_shade_mode=0;
1244     Colorize_mode=0;
1245     Tiling_mode=0;
1246     Smear_mode=0;
1247   }
1248   Smooth_mode=!Smooth_mode;
1249 }
1250 
1251 
1252 static const byte Smooth_default_matrices[4][3][3]=
1253 {
1254  { {1,2,1}, {2,4,2}, {1,2,1} },
1255  { {1,3,1}, {3,9,3}, {1,3,1} },
1256  { {0,1,0}, {1,2,1}, {0,1,0} },
1257  { {2,3,2}, {3,1,3}, {2,3,2} }
1258 };
1259 
Button_Smooth_menu(void)1260 void Button_Smooth_menu(void)
1261 {
1262   short clicked_button;
1263   word x,y,i,j;
1264   byte  chosen_matrix[3][3];
1265   T_Special_button * matrix_input[3][3];
1266   char  str[4];
1267 
1268   Open_window(142,109,"Smooth");
1269 
1270   Window_set_normal_button(82,59,53,14,"Cancel",0,1,KEY_ESC); // 1
1271   Window_set_normal_button(82,88,53,14,"OK"    ,0,1,KEY_RETURN); // 2
1272 
1273   Window_display_frame(6,17,130,37);
1274   for (x=11,y=0; y<4; x+=31,y++)
1275   {
1276     Window_set_normal_button(x,22,27,27,"",0,1,KEY_NONE);      // 3,4,5,6
1277     for (j=0; j<3; j++)
1278       for (i=0; i<3; i++)
1279         Print_char_in_window(x+2+(i<<3),24+(j<<3),'0'+Smooth_default_matrices[y][i][j],MC_Black,MC_Light);
1280   }
1281 
1282   Window_display_frame(6,58, 69,45);
1283   for (j=0; j<3; j++)
1284     for (i=0; i<3; i++)
1285     {
1286       matrix_input[i][j]=Window_set_input_button(10+(i*21),62+(j*13),2); // 7..15
1287       chosen_matrix[i][j] = Smooth_matrix[i][j] ;
1288       Num2str(chosen_matrix[i][j], str, 2);
1289       Window_input_content(matrix_input[i][j],str);
1290     }
1291   Update_window_area(0,0,Window_width, Window_height);
1292 
1293   Display_cursor();
1294 
1295   do
1296   {
1297     clicked_button=Window_clicked_button();
1298 
1299     if (clicked_button>2)
1300     {
1301       if (clicked_button<=6)
1302       {
1303         memcpy(chosen_matrix,Smooth_default_matrices[clicked_button-3],sizeof(chosen_matrix));
1304         Hide_cursor();
1305         for (j=0; j<3; j++)
1306           for (i=0; i<3; i++)
1307           {
1308             Num2str(chosen_matrix[i][j],str,2);
1309             Window_input_content(matrix_input[i][j],str);
1310           }
1311         Display_cursor();
1312       }
1313       else
1314       {
1315         i=clicked_button-7; x=i%3; y=i/3;
1316         Num2str(chosen_matrix[x][y],str,2);
1317         Readline(matrix_input[x][y]->Pos_X+2,
1318                  matrix_input[x][y]->Pos_Y+2,
1319                  str,2,INPUT_TYPE_INTEGER);
1320         chosen_matrix[x][y]=atoi(str);
1321         Display_cursor();
1322       }
1323     }
1324     if (Is_shortcut(Key,0x100+BUTTON_HELP))
1325       Window_help(BUTTON_EFFECTS, "SMOOTH");
1326     else if (Is_shortcut(Key,SPECIAL_SMOOTH_MENU))
1327       clicked_button=2;
1328   }
1329   while ((clicked_button!=1) && (clicked_button!=2));
1330 
1331   Close_window();
1332 
1333   if (clicked_button==2) // OK
1334   {
1335     memcpy(Smooth_matrix,chosen_matrix,sizeof(Smooth_matrix));
1336     Smooth_mode=0; // On le met à 0 car la fonct° suivante va le passer à 1
1337     Button_Smooth_mode();
1338   }
1339 
1340   Display_cursor();
1341 }
1342 
1343 
1344 // -- Mode Smear ------------------------------------------------------------
Button_Smear_mode(void)1345 void Button_Smear_mode(void)
1346 {
1347   if (!Smear_mode)
1348   {
1349     if (!Colorize_mode)
1350       Effect_function=No_effect;
1351     Shade_mode=0;
1352     Quick_shade_mode=0;
1353     Smooth_mode=0;
1354     Tiling_mode=0;
1355   }
1356   Smear_mode=!Smear_mode;
1357 }
1358 
1359 // -- Mode Colorize ---------------------------------------------------------
Compute_colorize_table(void)1360 void Compute_colorize_table(void)
1361 {
1362   word  index;
1363   word  factor_a;
1364   word  factor_b;
1365 
1366   factor_a=256*(100-Colorize_opacity)/100;
1367   factor_b=256*(    Colorize_opacity)/100;
1368 
1369   for (index=0;index<256;index++)
1370   {
1371     Factors_table[index]=index*factor_a;
1372     Factors_inv_table[index]=index*factor_b;
1373   }
1374 }
1375 
1376 
Button_Colorize_mode(void)1377 void Button_Colorize_mode(void)
1378 {
1379   if (Colorize_mode)
1380     Effect_function=No_effect;
1381   else
1382   {
1383     switch(Colorize_current_mode)
1384     {
1385       case 0 :
1386         Effect_function=Effect_interpolated_colorize;
1387         break;
1388       case 1 :
1389         Effect_function=Effect_additive_colorize;
1390         break;
1391       case 2 :
1392         Effect_function=Effect_substractive_colorize;
1393         break;
1394       case 3 :
1395         Effect_function=Effect_alpha_colorize;
1396     }
1397     Shade_mode=0;
1398     Quick_shade_mode=0;
1399     Smooth_mode=0;
1400     Tiling_mode=0;
1401   }
1402   Colorize_mode=!Colorize_mode;
1403 }
1404 
1405 
Button_Colorize_display_selection(int mode)1406 void Button_Colorize_display_selection(int mode)
1407 {
1408   short y_pos=0; // Ligne où afficher les flèches de sélection
1409 
1410   // On commence par effacer les anciennes sélections:
1411     // Partie gauche
1412   Print_in_window(4,37," ",MC_Black,MC_Light);
1413   Print_in_window(4,57," ",MC_Black,MC_Light);
1414   Print_in_window(4,74," ",MC_Black,MC_Light);
1415   Print_in_window(4,91," ",MC_Black,MC_Light);
1416     // Partie droite
1417   Print_in_window(129,37," ",MC_Black,MC_Light);
1418   Print_in_window(129,57," ",MC_Black,MC_Light);
1419   Print_in_window(129,74," ",MC_Black,MC_Light);
1420   Print_in_window(129,91," ",MC_Black,MC_Light);
1421 
1422   // Ensuite, on affiche la flèche là où il le faut:
1423   switch(mode)
1424   {
1425     case 0 : // Méthode interpolée
1426       y_pos=37;
1427       break;
1428     case 1 : // Méthode additive
1429       y_pos=57;
1430       break;
1431     case 2 : // Méthode soustractive
1432       y_pos=74;
1433       break;
1434     case 3 : // Méthode alpha
1435       y_pos=91;
1436   }
1437   Print_in_window(4,y_pos,"\020",MC_Black,MC_Light);
1438   Print_in_window(129,y_pos,"\021",MC_Black,MC_Light);
1439 }
1440 
Button_Colorize_menu(void)1441 void Button_Colorize_menu(void)
1442 {
1443   short chosen_opacity;
1444   short selected_mode;
1445   short clicked_button;
1446   char  str[4];
1447 
1448   Open_window(140,135,"Transparency");
1449 
1450   Print_in_window(16,23,"Opacity:",MC_Dark,MC_Light);
1451   Window_set_input_button(87,21,3);                               // 1
1452   Print_in_window(117,23,"%",MC_Dark,MC_Light);
1453   Window_set_normal_button(16,34,108,14,"Interpolate",1,1,KEY_i); // 2
1454   Window_display_frame(12,18,116,34);
1455 
1456   Window_set_normal_button(16,54,108,14,"Additive"   ,2,1,KEY_d); // 3
1457   Window_set_normal_button(16,71,108,14,"Subtractive",1,1,KEY_s); // 4
1458   Window_set_normal_button(16,88,108,14,"Alpha",1,1,KEY_a); // 4
1459 
1460   Window_set_normal_button(16,111, 51,14,"Cancel"     ,0,1,KEY_ESC); // 5
1461   Window_set_normal_button(73,111, 51,14,"OK"         ,0,1,KEY_RETURN); // 6
1462 
1463   Num2str(Colorize_opacity,str,3);
1464   Window_input_content(Window_special_button_list,str);
1465   Button_Colorize_display_selection(Colorize_current_mode);
1466 
1467   chosen_opacity=Colorize_opacity;
1468   selected_mode    =Colorize_current_mode;
1469 
1470   Update_window_area(0,0,Window_width, Window_height);
1471   Display_cursor();
1472 
1473   do
1474   {
1475     clicked_button=Window_clicked_button();
1476 
1477     switch(clicked_button)
1478     {
1479       case 1: // Zone de saisie de l'opacité
1480         Num2str(chosen_opacity,str,3);
1481         Readline(89,23,str,3,INPUT_TYPE_INTEGER);
1482         chosen_opacity=atoi(str);
1483         // On corrige le pourcentage
1484         if (chosen_opacity>100)
1485         {
1486           chosen_opacity=100;
1487           Num2str(chosen_opacity,str,3);
1488           Window_input_content(Window_special_button_list,str);
1489         }
1490         Display_cursor();
1491         break;
1492       case 2: // Interpolated method
1493       case 3: // Additive method
1494       case 4: // Substractive method
1495       case 5: // Alpha method
1496         selected_mode=clicked_button-2;
1497         Hide_cursor();
1498         Button_Colorize_display_selection(selected_mode);
1499         Display_cursor();
1500     }
1501     if (Is_shortcut(Key,0x100+BUTTON_HELP))
1502       Window_help(BUTTON_EFFECTS, "TRANSPARENCY");
1503       else if (Is_shortcut(Key,SPECIAL_COLORIZE_MENU))
1504         clicked_button=7;
1505   }
1506   while (clicked_button<6);
1507 
1508   Close_window();
1509 
1510   if (clicked_button==7) // OK
1511   {
1512     Colorize_opacity      =chosen_opacity;
1513     Colorize_current_mode=selected_mode;
1514     Compute_colorize_table();
1515     Colorize_mode=0; // On le met à 0 car la fonct° suivante va le passer à 1
1516     Button_Colorize_mode();
1517   }
1518 
1519   Display_cursor();
1520 }
1521 
1522 
1523 // -- Mode Tiling -----------------------------------------------------------
Button_Tiling_mode(void)1524 void Button_Tiling_mode(void)
1525 {
1526   if (Tiling_mode)
1527     Effect_function=No_effect;
1528   else
1529   {
1530     Effect_function=Effect_tiling;
1531     Shade_mode=0;
1532     Quick_shade_mode=0;
1533     Colorize_mode=0;
1534     Smooth_mode=0;
1535     Smear_mode=0;
1536   }
1537   Tiling_mode=!Tiling_mode;
1538 }
1539 
1540 
Button_Tiling_menu(void)1541 void Button_Tiling_menu(void)
1542 {
1543   short clicked_button;
1544   short chosen_offset_x=Tiling_offset_X;
1545   short chosen_offset_y=Tiling_offset_Y;
1546   char  str[5];
1547   T_Special_button * input_offset_x_button;
1548   T_Special_button * input_offset_y_button;
1549 
1550   Open_window(138,79,"Tiling");
1551 
1552   Window_set_normal_button(13,55,51,14,"Cancel",0,1,KEY_ESC);  // 1
1553   Window_set_normal_button(74,55,51,14,"OK"    ,0,1,KEY_RETURN); // 2
1554   input_offset_x_button = Window_set_input_button(91,21,4);   // 3
1555   input_offset_y_button = Window_set_input_button(91,35,4);   // 4
1556   Print_in_window(12,23,"Offset X:",MC_Dark,MC_Light);
1557   Print_in_window(12,37,"Offset Y:",MC_Dark,MC_Light);
1558 
1559   Num2str(Tiling_offset_X,str,4);
1560   Window_input_content(input_offset_x_button,str);
1561   Num2str(Tiling_offset_Y,str,4);
1562   Window_input_content(input_offset_y_button,str);
1563 
1564   Update_window_area(0,0,Window_width, Window_height);
1565   Display_cursor();
1566 
1567   do
1568   {
1569     clicked_button=Window_clicked_button();
1570 
1571     if (clicked_button==3)  // Zone de saisie du décalage X
1572     {
1573       Num2str(chosen_offset_x,str,4);
1574       Readline(93,23,str,4,INPUT_TYPE_INTEGER);
1575       chosen_offset_x=atoi(str);
1576       // On corrige le décalage en X
1577       if (chosen_offset_x>=Brush_width)
1578       {
1579         chosen_offset_x=Brush_width-1;
1580         Num2str(chosen_offset_x,str,4);
1581         Window_input_content(input_offset_x_button,str);
1582       }
1583       Display_cursor();
1584     }
1585     else
1586     if (clicked_button==4)  // Zone de saisie du décalage Y
1587     {
1588       Num2str(chosen_offset_y,str,4);
1589       Readline(93,37,str,4,INPUT_TYPE_INTEGER);
1590       chosen_offset_y=atoi(str);
1591       // On corrige le décalage en Y
1592       if (chosen_offset_y>=Brush_height)
1593       {
1594         chosen_offset_y=Brush_height-1;
1595         Num2str(chosen_offset_y,str,4);
1596         Window_input_content(input_offset_y_button,str);
1597       }
1598       Display_cursor();
1599     }
1600     if (Is_shortcut(Key,0x100+BUTTON_HELP))
1601       Window_help(BUTTON_EFFECTS, "TILING");
1602   }
1603   while ( (clicked_button!=1) && (clicked_button!=2) );
1604 
1605   Close_window();
1606 
1607   if (clicked_button==2) // OK
1608   {
1609     Tiling_offset_X=chosen_offset_x;
1610     Tiling_offset_Y=chosen_offset_y;
1611     if (!Tiling_mode)
1612       Button_Tiling_mode();
1613   }
1614 
1615   Display_cursor();
1616 }
1617 
1618 // -- All modes off ---------------------------------------------------------
Effects_off(void)1619 void Effects_off(void)
1620 {
1621   Effect_function=No_effect;
1622   Shade_mode=0;
1623   Quick_shade_mode=0;
1624   Colorize_mode=0;
1625   Smooth_mode=0;
1626   Tiling_mode=0;
1627   Smear_mode=0;
1628   Stencil_mode=0;
1629   Mask_mode=0;
1630   Sieve_mode=0;
1631   Snap_mode=0;
1632   Main.tilemap_mode=0;
1633 }
1634 
1635 
1636 // -- Mode Sieve (Sieve) ----------------------------------------------------
1637 
Button_Sieve_mode(void)1638 void Button_Sieve_mode(void)
1639 {
1640   Sieve_mode=!Sieve_mode;
1641 }
1642 
1643 
Draw_sieve_scaled(short origin_x,short origin_y)1644 void Draw_sieve_scaled(short origin_x, short origin_y)
1645 {
1646   short x_pos;
1647   short y_pos;
1648   short x_size;
1649   short y_size;
1650   short start_x=Window_pos_X+(Menu_factor_X*230);
1651   short start_y=Window_pos_Y+(Menu_factor_Y*78);
1652 
1653   x_size=Menu_factor_X*5; // |_ Taille d'une case
1654   y_size=Menu_factor_Y*5; // |  de la trame zoomée
1655 
1656   // On efface de contenu précédent
1657   Block(origin_x,origin_y,
1658         Menu_factor_X*Window_special_button_list->Width,
1659         Menu_factor_Y*Window_special_button_list->Height,MC_Light);
1660 
1661   for (y_pos=0; y_pos<Sieve_height; y_pos++)
1662     for (x_pos=0; x_pos<Sieve_width; x_pos++)
1663     {
1664       // Bordures de la case
1665       Block(origin_x+(x_pos*x_size),
1666             origin_y+((y_pos+1)*y_size)-Menu_factor_Y,
1667             x_size, Menu_factor_Y,MC_Dark);
1668       Block(origin_x+((x_pos+1)*x_size)-Menu_factor_X,
1669             origin_y+(y_pos*y_size),
1670             Menu_factor_X, y_size-1,MC_Dark);
1671       // Contenu de la case
1672       Block(origin_x+(x_pos*x_size), origin_y+(y_pos*y_size),
1673             x_size-Menu_factor_X, y_size-Menu_factor_Y,
1674             (Sieve[x_pos][y_pos])?MC_White:MC_Black);
1675     }
1676 
1677   // Dessiner la preview de la trame
1678   x_size=Menu_factor_X*51; // |_ Taille de la fenêtre
1679   y_size=Menu_factor_Y*71; // |  de la preview
1680   for (y_pos=0; y_pos<y_size; y_pos++)
1681     for (x_pos=0; x_pos<x_size; x_pos++)
1682       Pixel(start_x+x_pos,start_y+y_pos,(Sieve[x_pos%Sieve_width][y_pos%Sieve_height])?MC_White:MC_Black);
1683   Update_rect(start_x,start_y,x_size,y_size);
1684 }
1685 
1686 
Draw_preset_sieve_patterns(void)1687 void Draw_preset_sieve_patterns(void)
1688 {
1689   short index;
1690   short i,j;
1691   //short x_size,y_size;
1692   short Zoom;
1693 
1694   Zoom=Min(Menu_factor_X,Menu_factor_Y);
1695 
1696   //x_size=1;//Menu_factor_X/Pixel_height;
1697   //y_size=1;//Menu_factor_Y/Pixel_width;
1698 
1699   for (index=0; index<12; index++)
1700     for (j=0; j<16*Menu_factor_Y/Zoom; j++)
1701       for (i=0; i<16*Menu_factor_X/Zoom; i++)
1702         Block(((index*23+10)*Menu_factor_X)+i*Zoom+Window_pos_X,
1703           (22*Menu_factor_Y)+j*Zoom+Window_pos_Y,Zoom,Zoom,
1704           ((Gfx->Sieve_pattern[index][j&0xF]>>(15-(i&0xF)))&1)?MC_White:MC_Black);
1705 
1706   Update_rect(ToWinX(10),ToWinY(22),ToWinL(12*23+16),ToWinH(16));
1707 }
1708 
1709 
Copy_preset_sieve(byte index)1710 void Copy_preset_sieve(byte index)
1711 {
1712   short i,j;
1713 
1714   for (j=0; j<16; j++)
1715     for (i=0; i<16; i++)
1716       Sieve[i][j]=(Gfx->Sieve_pattern[index][j]>>(15-i))&1;
1717   Sieve_width=16;
1718   Sieve_height=16;
1719 }
1720 
1721 
Invert_trame(void)1722 void Invert_trame(void)
1723 {
1724   byte x_pos,y_pos;
1725 
1726   for (y_pos=0; y_pos<Sieve_height; y_pos++)
1727     for (x_pos=0; x_pos<Sieve_width; x_pos++)
1728       Sieve[x_pos][y_pos]=!(Sieve[x_pos][y_pos]);
1729 }
1730 
1731 // Rafraichit toute la zone correspondant à la trame zoomee.
Update_sieve_area(short x,short y)1732 void Update_sieve_area(short x, short y)
1733 {
1734   Update_rect(x,y,80*Menu_factor_X,80*Menu_factor_Y);
1735 }
1736 
1737 
Button_Sieve_menu(void)1738 void Button_Sieve_menu(void)
1739 {
1740   short clicked_button;
1741   short index;
1742   short x_pos;
1743   short y_pos;
1744   short old_x_pos=0;
1745   short old_y_pos=0;
1746   short origin_x;
1747   short origin_y;
1748   static byte default_bg_color=0;
1749   T_Normal_button * button_bg_color;
1750   char  str[3];
1751   byte  temp; // Octet temporaire servant à n'importe quoi
1752   short old_sieve_width=Sieve_width;
1753   short old_sieve_height=Sieve_height;
1754   byte  old_sieve[16][16];
1755 
1756   memcpy(old_sieve,Sieve,256);
1757 
1758   Open_window(290,179,"Sieve");
1759 
1760   Window_display_frame      (  7, 65,130,43);
1761   Window_display_frame      (  7,110,130,43);
1762   Window_display_frame_in(142, 68, 82,82);
1763   Window_display_frame_in(229, 77, 53,73);
1764 
1765   Print_in_window(228, 68,"Preview",MC_Dark,MC_Light);
1766   Print_in_window( 27, 83,"Scroll" ,MC_Dark,MC_Light);
1767   Print_in_window( 23,120,"Width:" ,MC_Dark,MC_Light);
1768   Print_in_window( 15,136,"Height:",MC_Dark,MC_Light);
1769 
1770   Window_set_special_button(143,69,80,80,0);                     // 1
1771 
1772   Window_set_normal_button(175,157,51,14,"Cancel",0,1,KEY_ESC); // 2
1773   Window_set_normal_button(230,157,51,14,"OK"    ,0,1,KEY_RETURN); // 3
1774 
1775   Window_set_normal_button(  8,157,51,14,"Clear" ,1,1,KEY_c); // 4
1776   Window_set_normal_button( 63,157,51,14,"Invert",1,1,KEY_i); // 5
1777 
1778   Window_set_normal_button(  8,46,131,14,"Get from brush"   ,1,1,KEY_g); // 6
1779   Window_set_normal_button(142,46,139,14,"Transfer to brush",1,1,KEY_t); // 7
1780 
1781   Window_set_normal_button(109,114,11,11,"\030",0,1,KEY_UP|GFX2_MOD_SHIFT); // 8
1782   Window_set_normal_button(109,138,11,11,"\031",0,1,KEY_DOWN|GFX2_MOD_SHIFT); // 9
1783   Window_set_normal_button( 97,126,11,11,"\033",0,1,KEY_LEFT|GFX2_MOD_SHIFT); // 10
1784   Window_set_normal_button(121,126,11,11,"\032",0,1,KEY_RIGHT|GFX2_MOD_SHIFT); // 11
1785   button_bg_color = Window_set_normal_button(109,126,11,11,""    ,0,1,KEY_INSERT); // 12
1786   Window_rectangle(button_bg_color->Pos_X+2,
1787         button_bg_color->Pos_Y+2,
1788         7, 7, (default_bg_color)?MC_White:MC_Black);
1789 
1790   Window_set_repeatable_button(109, 69,11,11,"\030",0,1,KEY_UP); // 13
1791   Window_set_repeatable_button(109, 93,11,11,"\031",0,1,KEY_DOWN); // 14
1792   Window_set_repeatable_button( 97, 81,11,11,"\033",0,1,KEY_LEFT); // 15
1793   Window_set_repeatable_button(121, 81,11,11,"\032",0,1,KEY_RIGHT); // 16
1794 
1795   for (index=0; index<12; index++)
1796     Window_set_normal_button((index*23)+8,20,20,20,"",0,1,KEY_F1+index); // 17 -> 28
1797   Draw_preset_sieve_patterns();
1798 
1799   origin_x=Window_pos_X+(Menu_factor_X*Window_special_button_list->Pos_X);
1800   origin_y=Window_pos_Y+(Menu_factor_Y*Window_special_button_list->Pos_Y);
1801 
1802   Num2str(Sieve_width,str,2);
1803   Print_in_window(71,120,str,MC_Black,MC_Light);
1804   Num2str(Sieve_height,str,2);
1805   Print_in_window(71,136,str,MC_Black,MC_Light);
1806   Draw_sieve_scaled(origin_x,origin_y);
1807 
1808   Update_window_area(0,0,Window_width, Window_height);
1809 
1810   Display_cursor();
1811 
1812   do
1813   {
1814     clicked_button=Window_clicked_button();
1815 
1816     origin_x=Window_pos_X+(Menu_factor_X*Window_special_button_list->Pos_X);
1817     origin_y=Window_pos_Y+(Menu_factor_Y*Window_special_button_list->Pos_Y);
1818 
1819 
1820     switch (clicked_button)
1821     {
1822       case -1 :
1823       case  0 :
1824         break;
1825 
1826       case  1 : // Zone de dessin de la trame
1827         /* // Version qui n'accepte pas les clicks sur la grille
1828         x_pos=(Mouse_X-origin_x)/Menu_factor_X;
1829         y_pos=(Mouse_Y-origin_y)/Menu_factor_Y;
1830         if ( (x_pos%5<4) && (y_pos%5<4) )
1831         {
1832           x_pos/=5;
1833           y_pos/=5;
1834           if ( (x_pos<Sieve_width) && (y_pos<Sieve_height) )
1835         }
1836         */
1837         x_pos=(Mouse_X-origin_x)/(Menu_factor_X*5);
1838         y_pos=(Mouse_Y-origin_y)/(Menu_factor_Y*5);
1839         if ( (x_pos<Sieve_width) && (y_pos<Sieve_height) )
1840         {
1841           temp=(Mouse_K==LEFT_SIDE);
1842           if ( (x_pos!=old_x_pos) || (y_pos!=old_y_pos)
1843             || (Sieve[x_pos][y_pos]!=temp) )
1844           {
1845             old_x_pos=x_pos;
1846             old_y_pos=y_pos;
1847             Sieve[x_pos][y_pos]=temp;
1848             x_pos=Menu_factor_X*5;
1849             y_pos=Menu_factor_Y*5;
1850             Hide_cursor();
1851             if (temp)
1852               temp=MC_White;
1853             else
1854               temp=MC_Black;
1855             // Affichage du pixel dans la fenêtre zoomée
1856             Block(origin_x+(old_x_pos*x_pos), origin_y+(old_y_pos*y_pos),
1857                   x_pos-Menu_factor_X, y_pos-Menu_factor_Y, temp);
1858             // Mise à jour de la preview
1859             Draw_sieve_scaled(origin_x,origin_y);
1860             Display_cursor();
1861             // Maj de la case seule
1862             Update_rect(origin_x+(old_x_pos*x_pos), origin_y+(old_y_pos*y_pos),Menu_factor_X*5,Menu_factor_Y*5);
1863           }
1864         }
1865         break;
1866 
1867       case  2 : // Cancel
1868       case  3 : // OK
1869         break;
1870 
1871       case  4 : // Clear
1872         Hide_cursor();
1873         memset(Sieve,default_bg_color,256);
1874         Draw_sieve_scaled(origin_x,origin_y);
1875         Display_cursor();
1876         Update_sieve_area(origin_x, origin_y);
1877         break;
1878 
1879       case  5 : // Invert
1880         Hide_cursor();
1881         Invert_trame();
1882         Draw_sieve_scaled(origin_x,origin_y);
1883         Display_cursor();
1884         Update_sieve_area(origin_x, origin_y);
1885         break;
1886 
1887       case  6 : // Get from brush
1888         Hide_cursor();
1889         Sieve_width=(Brush_width>16)?16:Brush_width;
1890         Sieve_height=(Brush_height>16)?16:Brush_height;
1891         for (y_pos=0; y_pos<Sieve_height; y_pos++)
1892           for (x_pos=0; x_pos<Sieve_width; x_pos++)
1893             Sieve[x_pos][y_pos]=(Read_pixel_from_brush(x_pos,y_pos)!=Back_color);
1894         Draw_sieve_scaled(origin_x,origin_y);
1895         Num2str(Sieve_height,str,2);
1896         Print_in_window(71,136,str,MC_Black,MC_Light);
1897         Num2str(Sieve_width,str,2);
1898         Print_in_window(71,120,str,MC_Black,MC_Light);
1899         Display_cursor();
1900         Update_sieve_area(origin_x, origin_y);
1901         break;
1902 
1903       case  7 : // Transfer to brush
1904 
1905         if (Realloc_brush(Sieve_width, Sieve_height, NULL, NULL))
1906           break;
1907 
1908         for (y_pos=0; y_pos<Sieve_height; y_pos++)
1909           for (x_pos=0; x_pos<Sieve_width; x_pos++)
1910             *(Brush_original_pixels + y_pos * Brush_width + x_pos) = (Sieve[x_pos][y_pos])?Fore_color:Back_color;
1911 
1912         // Grab palette
1913         memcpy(Brush_original_palette, Main.palette,sizeof(T_Palette));
1914         // Remap (no change)
1915         Remap_brush();
1916 
1917         Brush_offset_X=(Brush_width>>1);
1918         Brush_offset_Y=(Brush_height>>1);
1919 
1920         Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
1921         break;
1922 
1923       case  8 : // Réduire hauteur
1924         if (Sieve_height>1)
1925         {
1926           Hide_cursor();
1927           Sieve_height--;
1928           Num2str(Sieve_height,str,2);
1929           Print_in_window(71,136,str,MC_Black,MC_Light);
1930           Draw_sieve_scaled(origin_x,origin_y);
1931           Display_cursor();
1932           Update_sieve_area(origin_x, origin_y);
1933         }
1934         break;
1935 
1936       case  9 : // Agrandir hauteur
1937         if (Sieve_height<16)
1938         {
1939           Hide_cursor();
1940           for (index=0; index<Sieve_width; index++)
1941             Sieve[index][Sieve_height]=default_bg_color;
1942           Sieve_height++;
1943           Num2str(Sieve_height,str,2);
1944           Print_in_window(71,136,str,MC_Black,MC_Light);
1945           Draw_sieve_scaled(origin_x,origin_y);
1946           Display_cursor();
1947           Update_sieve_area(origin_x, origin_y);
1948         }
1949         break;
1950 
1951       case 10 : // Réduire largeur
1952         if (Sieve_width>1)
1953         {
1954           Hide_cursor();
1955           Sieve_width--;
1956           Num2str(Sieve_width,str,2);
1957           Print_in_window(71,120,str,MC_Black,MC_Light);
1958           Draw_sieve_scaled(origin_x,origin_y);
1959           Display_cursor();
1960           Update_sieve_area(origin_x, origin_y);
1961         }
1962         break;
1963 
1964       case 11 : // Agrandir largeur
1965         if (Sieve_width<16)
1966         {
1967           Hide_cursor();
1968           for (index=0; index<Sieve_height; index++)
1969             Sieve[Sieve_width][index]=default_bg_color;
1970           Sieve_width++;
1971           Num2str(Sieve_width,str,2);
1972           Print_in_window(71,120,str,MC_Black,MC_Light);
1973           Draw_sieve_scaled(origin_x,origin_y);
1974           Display_cursor();
1975           Update_sieve_area(origin_x, origin_y);
1976         }
1977         break;
1978 
1979       case 12 : // Toggle octets insérés
1980         Hide_cursor();
1981         default_bg_color=!default_bg_color;
1982         Window_rectangle(button_bg_color->Pos_X+2,
1983               button_bg_color->Pos_Y+2,
1984               7, 7, (default_bg_color)?MC_White:MC_Black);
1985         Display_cursor();
1986         Update_window_area(
1987           button_bg_color->Pos_X+2,
1988           button_bg_color->Pos_Y+2,
1989           7,
1990           7);
1991 
1992         break;
1993 
1994       case 13 : // Scroll vers le haut
1995         Hide_cursor();
1996         for (x_pos=0; x_pos<Sieve_width; x_pos++)
1997         {
1998           temp=Sieve[x_pos][0]; // Octet temporaire
1999           for (y_pos=1; y_pos<Sieve_height; y_pos++)
2000             Sieve[x_pos][y_pos-1]=Sieve[x_pos][y_pos];
2001           Sieve[x_pos][Sieve_height-1]=temp;
2002         }
2003         Draw_sieve_scaled(origin_x,origin_y);
2004         Display_cursor();
2005         Update_sieve_area(origin_x, origin_y);
2006         break;
2007 
2008       case 14 : // Scroll vers le bas
2009         Hide_cursor();
2010         for (x_pos=0; x_pos<Sieve_width; x_pos++)
2011         {
2012           temp=Sieve[x_pos][Sieve_height-1]; // Octet temporaire
2013           for (y_pos=Sieve_height-1; y_pos>0; y_pos--)
2014             Sieve[x_pos][y_pos]=Sieve[x_pos][y_pos-1];
2015           Sieve[x_pos][0]=temp;
2016         }
2017         Draw_sieve_scaled(origin_x,origin_y);
2018         Display_cursor();
2019         Update_sieve_area(origin_x, origin_y);
2020         break;
2021 
2022       case 15 : // Scroll vers la gauche
2023         Hide_cursor();
2024         for (y_pos=0; y_pos<Sieve_height; y_pos++)
2025         {
2026           temp=Sieve[0][y_pos]; // Octet temporaire
2027           for (x_pos=1; x_pos<Sieve_width; x_pos++)
2028             Sieve[x_pos-1][y_pos]=Sieve[x_pos][y_pos];
2029           Sieve[Sieve_width-1][y_pos]=temp;
2030         }
2031         Draw_sieve_scaled(origin_x,origin_y);
2032         Display_cursor();
2033         Update_sieve_area(origin_x, origin_y);
2034         break;
2035 
2036       case 16 : // Scroll vers la droite
2037         Hide_cursor();
2038         for (y_pos=0; y_pos<Sieve_height; y_pos++)
2039         {
2040           temp=Sieve[Sieve_width-1][y_pos]; // Octet temporaire
2041           for (x_pos=Sieve_width-1; x_pos>0; x_pos--)
2042             Sieve[x_pos][y_pos]=Sieve[x_pos-1][y_pos];
2043           Sieve[0][y_pos]=temp;
2044         }
2045         Draw_sieve_scaled(origin_x,origin_y);
2046         Display_cursor();
2047         Update_sieve_area(origin_x, origin_y);
2048         break;
2049 
2050       default : // Boutons de trames prédéfinies
2051         Hide_cursor();
2052         Copy_preset_sieve(clicked_button-17);
2053         Draw_sieve_scaled(origin_x,origin_y);
2054         Num2str(Sieve_width,str,2);
2055         Print_in_window(71,120,str,MC_Black,MC_Light);
2056         Num2str(Sieve_height,str,2);
2057         Print_in_window(71,136,str,MC_Black,MC_Light);
2058         Draw_sieve_scaled(origin_x,origin_y);
2059         Display_cursor();
2060         Update_sieve_area(origin_x, origin_y);
2061     }
2062     if (Is_shortcut(Key,0x100+BUTTON_HELP))
2063     {
2064       Key=0;
2065       Window_help(BUTTON_EFFECTS, "SIEVE");
2066     }
2067   }
2068   while ( (clicked_button!=2) && (clicked_button!=3) );
2069 
2070 
2071   Close_window();
2072 
2073   if (clicked_button==2) // Cancel
2074   {
2075     Sieve_width=old_sieve_width;
2076     Sieve_height=old_sieve_height;
2077     memcpy(Sieve,old_sieve,256);
2078   }
2079 
2080   if ( (clicked_button==3) && (!Sieve_mode) ) // OK
2081     Button_Sieve_mode();
2082 
2083   Display_cursor();
2084 }
2085 
2086 
2087