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 #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
22 #include <proto/dos.h>
23 #include <sys/types.h>
24 #endif
25
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <string.h>
29 #if !defined(_MSC_VER)
30 #include <strings.h>
31 #else
32 #define strdup _strdup
33 #define strncasecmp _strnicmp
34 #if _MSC_VER < 1900
35 #define snprintf _snprintf
36 #endif
37 #endif
38 #include <stdlib.h>
39 #if !defined(__VBCC__) && !defined(_MSC_VER)
40 #include <unistd.h>
41 #endif
42 #include <ctype.h>
43 #include <sys/stat.h>
44
45 #include "const.h"
46 #include "struct.h"
47 #include "global.h"
48 #include "misc.h"
49 #include "osdep.h"
50 #include "graph.h"
51 #include "engine.h"
52 #include "readline.h"
53 #include "filesel.h"
54 #include "fileseltools.h"
55 #include "loadsave.h"
56 #include "init.h"
57 #include "buttons.h"
58 #include "operatio.h"
59 #include "pages.h"
60 #include "palette.h"
61 #include "errors.h"
62 #include "readini.h"
63 #include "saveini.h"
64 #include "shade.h"
65 #include "io.h"
66 #include "help.h"
67 #include "text.h"
68 #include "screen.h"
69 #include "windows.h"
70 #include "brush.h"
71 #include "input.h"
72 #include "special.h"
73 #include "tiles.h"
74 #include "setup.h"
75 #include "unicode.h"
76 #include "keycodes.h"
77
78 #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
79 #include <proto/dos.h>
80 #include <dirent.h>
81 #elif defined(__MINT__)
82 #include <mint/sysbind.h>
83 #include <dirent.h>
84 #elif defined(WIN32)
85 #ifndef _MSC_VER
86 #include <dirent.h>
87 #endif
88 #else
89 #include <dirent.h>
90 #endif
91
92 extern char Program_version[]; // generated in pversion.c
93
94 extern short Old_MX;
95 extern short Old_MY;
96
97
98 //-- MODELE DE BOUTON DE MENU ------------------------------------------------
99 /*
100 void Bouton_***(void)
101 {
102 short clicked_button;
103
104 Open_window(310,190,"***");
105
106 Window_set_normal_button(103,137,80,14,"OK",0,1,KEY_RETURN); // 1
107 Window_set_scroller_button(18,44,88,16,4,0); // 2
108
109 Update_window_area(0,0,Window_width, Window_height);
110
111 Display_cursor();
112
113 do
114 {
115 clicked_button=Window_clicked_button();
116 }
117 while (clicked_button!=1);
118
119 Close_window();
120 Unselect_button(BOUTON_***);
121 Display_cursor();
122 }
123 */
124
Message_out_of_memory(void)125 void Message_out_of_memory(void)
126 {
127 short clicked_button;
128
129 Open_window(216,76,"Not enough memory!");
130
131 Print_in_window(8,20,"Please consult the manual",MC_Black,MC_Light);
132 Print_in_window(24,28,"to know how to obtain",MC_Black,MC_Light);
133 Print_in_window(36,36,"more memory space.",MC_Black,MC_Light);
134 Window_set_normal_button(60,53,40,14,"OK",1,1,KEY_RETURN); // 1
135 Update_window_area(0,0,Window_width, Window_height);
136 Display_cursor();
137
138 do
139 clicked_button=Window_clicked_button();
140 while ((clicked_button<=0) && (Key!=KEY_ESC) && (Key!=KEY_o));
141
142 if(clicked_button<=0) Key=0;
143 Close_window();
144 Display_cursor();
145 }
146
147
Button_Message_initial(void)148 void Button_Message_initial(void)
149 {
150 char str[30];
151 int x_pos,offs_y,x,y;
152 int clicked_button=0;
153
154 snprintf(str,sizeof(str),"GrafX2 version %s",Program_version);
155 Open_window(260,172,str);
156
157 Window_display_frame_in(10,20,239,62);
158 Window_rectangle(11,21,237,60,MC_Black);
159 for (y=23,offs_y=0; y<79; offs_y+=231,y++)
160 for (x=14,x_pos=0; x_pos<231; x_pos++,x++)
161 Pixel_in_window(x,y,Gfx->Logo_grafx2[offs_y+x_pos]);
162
163 Print_in_window(130-4*26,88,"Copyright (c) 2007-2020 by",MC_Dark,MC_Light);
164 Print_in_window(130-4*23,100,"the Grafx2 project team",MC_Black,MC_Light);
165 Print_in_window(130-4*26,112,"Copyright (c) 1996-2001 by",MC_Dark,MC_Light);
166 Print_in_window(130-4*13,122,"Sunset Design",MC_Black,MC_Light);
167 //Print_in_window( 120-4*13,128,"(placeholder)",MC_Dark,MC_Light);
168 Print_in_window(130-4*16,136,"http://grafx2.tk",MC_Dark,MC_Light);
169
170 Window_set_normal_button(56, 151, 71, 14, "Anim", 1, (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION), KEY_a);
171 Window_set_normal_button(133, 151, 71, 14, "Layers", 1, (Main.backups->Pages->Image_mode != IMAGE_MODE_LAYERED), KEY_l);
172
173 Update_window_area(0,0,Window_width, Window_height);
174
175 Display_cursor();
176
177 while(!Mouse_K && !Key && !Quit_is_required)
178 Get_input(20);
179 if (Mouse_K)
180 {
181 clicked_button = Window_get_clicked_button();
182 Wait_end_of_click();
183 }
184 else
185 clicked_button = Window_get_button_shortcut();
186 GFX2_Log(GFX2_DEBUG, "Button_Message_initial() clicked_button=%d\n", clicked_button);
187 Close_window();
188
189 if (clicked_button > 0)
190 {
191 if (Main.backups->Pages->Image_mode == IMAGE_MODE_LAYERED)
192 {
193 Switch_layer_mode(IMAGE_MODE_ANIMATION);
194 Config.Default_mode_layers = 0;
195 }
196 else
197 {
198 Switch_layer_mode(IMAGE_MODE_LAYERED);
199 Config.Default_mode_layers = 1;
200 }
201 if (Check_menu_mode())
202 {
203 Display_menu();
204 Display_all_screen();
205 }
206 // Modify the mode for the spare too
207 Spare.backups->Pages->Image_mode = Main.backups->Pages->Image_mode;
208 Update_spare_buffers(Spare.image_width,Spare.image_height);
209 Redraw_spare_image();
210 }
211 Display_cursor();
212 }
213
214
215
Change_paintbrush_shape(byte shape)216 void Change_paintbrush_shape(byte shape)
217 {
218 Paintbrush_shape=shape;
219 Display_paintbrush_in_menu();
220
221 switch (Current_operation)
222 {
223 case OPERATION_FILL :
224 Paintbrush_shape_before_fill=shape;
225 Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
226 break;
227 case OPERATION_COLORPICK :
228 Paintbrush_shape_before_colorpicker=shape;
229 Paintbrush_shape=PAINTBRUSH_SHAPE_NONE;
230 break;
231 // Note: Il existe un Paintbrush_shape_before_lasso, mais comme le lasso aura
232 // été automatiquement désactivé avant d'arriver ici, y'a pas de problème.
233 }
234 }
235
236
237 //-------------------------------- UNDO/REDO ---------------------------------
Button_Undo(int btn)238 void Button_Undo(int btn)
239 {
240 Hide_cursor();
241 Undo();
242 Set_palette(Main.palette);
243 Compute_optimal_menu_colors(Main.palette);
244
245 Check_menu_mode();
246 Display_all_screen();
247 Unselect_button(btn);
248 Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
249 Display_menu();
250 Display_cursor();
251 }
252
Button_Redo(int btn)253 void Button_Redo(int btn)
254 {
255 Hide_cursor();
256 Redo();
257 Set_palette(Main.palette);
258 Compute_optimal_menu_colors(Main.palette);
259
260 Check_menu_mode();
261 Display_all_screen();
262 Unselect_button(btn);
263 Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
264 Display_menu();
265 Display_cursor();
266 }
267
268 //---------------------------- SCROLL PALETTE LEFT ---------------------------
Button_Pal_left(int btn)269 void Button_Pal_left(int btn)
270 {
271 short cells;
272 cells = (Config.Palette_vertical)?Palette_cells_X():Palette_cells_Y();
273
274 Hide_cursor();
275 if (First_color_in_palette)
276 {
277 if (First_color_in_palette>=cells)
278 First_color_in_palette-=cells;
279 else
280 First_color_in_palette=0;
281 Display_menu_palette();
282 }
283 Unselect_button(btn);
284 Display_cursor();
285 }
286
Button_Pal_left_fast(int btn)287 void Button_Pal_left_fast(int btn)
288 {
289 short cells_x = Palette_cells_X();
290 short cells_y = Palette_cells_Y();
291
292 Hide_cursor();
293 if (First_color_in_palette)
294 {
295 if (First_color_in_palette>=cells_y*cells_x)
296 First_color_in_palette-=cells_y*cells_x;
297 else
298 First_color_in_palette=0;
299 Display_menu_palette();
300 }
301 Unselect_button(btn);
302 Display_cursor();
303 }
304
305
306 //--------------------------- SCROLL PALETTE RIGHT ---------------------------
Button_Pal_right(int btn)307 void Button_Pal_right(int btn)
308 {
309 short cells;
310 cells = (Config.Palette_vertical)?Palette_cells_X():Palette_cells_Y();
311
312 Hide_cursor();
313 if ((int)First_color_in_palette+Palette_cells_X()*Palette_cells_Y()<256)
314 {
315 First_color_in_palette+=cells;
316 Display_menu_palette();
317 }
318
319 Unselect_button(btn);
320 Display_cursor();
321 }
322
Button_Pal_right_fast(int btn)323 void Button_Pal_right_fast(int btn)
324 {
325 short cells_x = Palette_cells_X();
326 short cells_y = Palette_cells_Y();
327
328 Hide_cursor();
329 if ((int)First_color_in_palette+cells_y*cells_x<256)
330 {
331 if ((int)First_color_in_palette+(cells_y)*cells_x*2<256)
332 First_color_in_palette+=cells_x*cells_y;
333 else
334 {
335 if (Config.Palette_vertical)
336 First_color_in_palette=255/cells_x*cells_x-(cells_y-1)*cells_x;
337 else
338 First_color_in_palette=255/cells_y*cells_y-(cells_x-1)*cells_y;
339 }
340 Display_menu_palette();
341 }
342 Unselect_button(btn);
343 Display_cursor();
344 }
345
346 //-------------------- item de la forecolor dans le menu --------------------
Button_Select_forecolor(int btn)347 void Button_Select_forecolor(int btn)
348 {
349 static long time_click = 0;
350 long time_previous;
351 int color;
352
353 time_previous = time_click;
354 time_click = GFX2_GetTicks();
355
356 color=Pick_color_in_palette();
357
358 if (color == Fore_color)
359 {
360 // Check if it's a double-click
361 if (time_click - time_previous < Config.Double_click_speed)
362 {
363 // Open palette window
364 Button_Palette(btn);
365 return;
366 }
367 }
368
369 do
370 {
371 if (color != Fore_color && color!=-1)
372 {
373 Hide_cursor();
374 Set_fore_color(color);
375 Display_cursor();
376 }
377 // Wait loop after initial click
378 while(Mouse_K)
379 {
380 Get_input(20);
381
382 if (Button_under_mouse()==btn)
383 {
384 color=Pick_color_in_palette();
385 if (color != Fore_color && color!=-1)
386 {
387 Hide_cursor();
388 Status_print_palette_color(color);
389 Set_fore_color(color);
390 Display_cursor();
391 }
392 }
393 }
394 } while(Mouse_K);
395 }
396
397 //-------------------- item de la backcolor dans le menu --------------------
Button_Select_backcolor(int btn)398 void Button_Select_backcolor(int btn)
399 {
400 int color;
401
402 do
403 {
404 color=Pick_color_in_palette();
405
406 if (color!=-1 && color != Back_color)
407 {
408 Hide_cursor();
409 Status_print_palette_color(color);
410 Set_back_color(color);
411 Display_cursor();
412 }
413 // Wait loop after initial click
414 do
415 {
416 Get_input(20);
417
418 if (Button_under_mouse()==btn)
419 break; // This will repeat this button's action
420
421 } while(Mouse_K);
422 } while(Mouse_K);
423 }
424
Button_Hide_menu(int btn)425 void Button_Hide_menu(int btn)
426 {
427 Hide_cursor();
428 if (Menu_is_visible)
429 {
430 Menu_is_visible=0;
431 Menu_Y=Screen_height;
432
433 if (Main.magnifier_mode)
434 {
435 Compute_magnifier_data();
436 }
437
438 // On repositionne le décalage de l'image pour qu'il n'y ait pas d'in-
439 // -cohérences lorsqu'on sortira du mode Loupe.
440 if (Main.offset_Y+Screen_height>Main.image_height)
441 {
442 if (Screen_height>Main.image_height)
443 Main.offset_Y=0;
444 else
445 Main.offset_Y=Main.image_height-Screen_height;
446 }
447 // On fait pareil pour le brouillon
448 if (Spare.offset_Y+Screen_height>Spare.image_height)
449 {
450 if (Screen_height>Spare.image_height)
451 Spare.offset_Y=0;
452 else
453 Spare.offset_Y=Spare.image_height-Screen_height;
454 }
455
456 Compute_magnifier_data();
457 if (Main.magnifier_mode)
458 Position_screen_according_to_zoom();
459 Compute_limits();
460 Compute_paintbrush_coordinates();
461 Display_all_screen();
462 }
463 else
464 {
465 byte current_menu;
466 Menu_is_visible=1;
467 Menu_Y=Screen_height;
468 for (current_menu = 0; current_menu < MENUBAR_COUNT; current_menu++)
469 if (Menu_bars[current_menu].Visible)
470 Menu_Y -= Menu_bars[current_menu].Height * Menu_factor_Y;
471
472 Compute_magnifier_data();
473 if (Main.magnifier_mode)
474 Position_screen_according_to_zoom();
475 Compute_limits();
476 Compute_paintbrush_coordinates();
477 Display_menu();
478 if (Main.magnifier_mode)
479 Display_all_screen();
480 }
481 Unselect_button(btn);
482 Display_cursor();
483 }
484
Button_Toggle_toolbar(int btn)485 void Button_Toggle_toolbar(int btn)
486 {
487 T_Dropdown_button dropdown;
488 T_Dropdown_choice *item;
489 static char menu_name_tools[9] = " Tools";
490 static char menu_name_layers[9]= " Layers";
491 static char menu_name_anim[9] = " Anim";
492
493
494 menu_name_tools[0] = Menu_bars[MENUBAR_TOOLS ].Visible ? 22 : ' ';
495 menu_name_layers[0] = Menu_bars[MENUBAR_LAYERS].Visible ? 22 : ' ';
496 menu_name_anim[0] = Menu_bars[MENUBAR_ANIMATION].Visible ? 22 : ' ';
497
498 Hide_cursor();
499
500 dropdown.Pos_X =Buttons_Pool[BUTTON_HIDE].X_offset;
501 dropdown.Pos_Y =Buttons_Pool[BUTTON_HIDE].Y_offset;
502 dropdown.Height =Buttons_Pool[BUTTON_HIDE].Height;
503 dropdown.Dropdown_width=70;
504 dropdown.First_item =NULL;
505 dropdown.Bottom_up =1;
506
507 Window_dropdown_add_item(&dropdown, 0, menu_name_tools);
508
509 if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION ||
510 Main.backups->Pages->Nb_layers==1)
511 Window_dropdown_add_item(&dropdown, 1, menu_name_layers);
512
513 if (Main.backups->Pages->Image_mode == IMAGE_MODE_ANIMATION ||
514 (Main.backups->Pages->Image_mode == IMAGE_MODE_LAYERED && Main.backups->Pages->Nb_layers==1))
515 Window_dropdown_add_item(&dropdown, 2, menu_name_anim);
516
517 item=Dropdown_activate(&dropdown,0,Menu_Y+Menu_bars[MENUBAR_STATUS].Top*Menu_factor_Y);
518
519 if (item)
520 {
521 switch (item->Number)
522 {
523 case 0: // tools
524 Set_bar_visibility(MENUBAR_TOOLS, !Menu_bars[MENUBAR_TOOLS].Visible, 0);
525 break;
526 case 1: // layers
527 if (Menu_bars[MENUBAR_ANIMATION].Visible)
528 {
529 Set_bar_visibility(MENUBAR_ANIMATION, 0, 0);
530 Config.Default_mode_layers=1;
531 }
532 Set_bar_visibility(MENUBAR_LAYERS, !Menu_bars[MENUBAR_LAYERS].Visible, 0);
533
534 if (Main.backups->Pages->Image_mode == IMAGE_MODE_ANIMATION)
535 Switch_layer_mode(IMAGE_MODE_LAYERED);
536
537 break;
538 case 2: // anim
539 if (Menu_bars[MENUBAR_LAYERS].Visible)
540 {
541 Set_bar_visibility(MENUBAR_LAYERS, 0, 0);
542 Config.Default_mode_layers=0;
543 }
544 Set_bar_visibility(MENUBAR_ANIMATION, !Menu_bars[MENUBAR_ANIMATION].Visible, 0);
545
546 if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
547 Switch_layer_mode(IMAGE_MODE_ANIMATION);
548
549 break;
550 }
551 // redraw image and menu
552 Display_menu();
553 Display_all_screen();
554 }
555
556 // Closing
557 Window_dropdown_clear_items(&dropdown);
558
559 Unselect_button(btn);
560 Display_cursor();
561 }
562
Button_Toggle_all_toolbars(int btn)563 void Button_Toggle_all_toolbars(int btn)
564 {
565 // This is used to memorize the bars' visibility when temporarily hidden
566 static word Last_visibility = 0xFFFF;
567 int i;
568 word current_visibility;
569
570 Hide_cursor();
571
572 // Check which bars are visible
573 current_visibility=0;
574 for (i=MENUBAR_STATUS+1;i<MENUBAR_COUNT;i++)
575 if (Menu_bars[i].Visible)
576 current_visibility |= (1<<i);
577
578 if (current_visibility)
579 {
580 // At least one is visible: Hide all
581 Last_visibility=current_visibility;
582 for (i=MENUBAR_STATUS+1;i<MENUBAR_COUNT;i++)
583 Set_bar_visibility(i,0, 0);
584 }
585 else
586 {
587 // Restore all
588 for (i=MENUBAR_STATUS+1;i<MENUBAR_COUNT;i++)
589 Set_bar_visibility(i,(Last_visibility & (1<<i)) ? 1 : 0, 0);
590 }
591 Check_menu_mode();
592 Display_menu();
593 Display_all_screen();
594
595 Unselect_button(btn);
596 Display_cursor();
597 }
598
599 //--------------------------- Quitter le programme ---------------------------
Button_Quit_local_function(void)600 byte Button_Quit_local_function(void)
601 {
602 short clicked_button;
603 byte old_cursor_shape;
604 char * filename;
605 int exists;
606
607 if (!Main.image_is_modified)
608 return 1;
609
610 // On commence par afficher la fenêtre de QUIT
611 Open_window(160,84,"Quit ?");
612 Window_set_normal_button(20,20,120,14,"Stay",0,1,KEY_ESC); // 1
613 Window_set_normal_button(20,40,120,14,"Save & quit",1,1,KEY_s); // 2
614 Window_set_normal_button(20,60,120,14,"Discard (Quit)",1,1,KEY_d);// 3
615 Update_window_area(0,0,Window_width, Window_height);
616 Display_cursor();
617
618 do
619 {
620 Quit_is_required = 0; // ignore other QUIT messages from the system
621 clicked_button = Window_clicked_button();
622 if (Is_shortcut(Key,0x100+BUTTON_HELP))
623 Window_help(BUTTON_QUIT, NULL);
624 else if (Is_shortcut(Key,0x100+BUTTON_QUIT))
625 clicked_button=1;
626 }
627 while (clicked_button<=0);
628
629 Close_window();
630 Display_cursor();
631
632 switch(clicked_button)
633 {
634 case 1 : return 0; // Rester
635 case 2 : // Sauver et enregistrer
636 filename = Filepath_append_to_dir(Main.backups->Pages->File_directory, Main.backups->Pages->Filename);
637 exists = File_exists(filename);
638 free(filename);
639 if ( !exists || Confirmation_box("Erase old file ?") )
640 {
641 T_IO_Context save_context;
642
643 Hide_cursor();
644 old_cursor_shape=Cursor_shape;
645 Cursor_shape=CURSOR_SHAPE_HOURGLASS;
646 Display_cursor();
647
648 Init_context_layered_image(&save_context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
649 save_context.File_name_unicode = Main.backups->Pages->Filename_unicode;
650 Save_image(&save_context);
651 Destroy_context(&save_context);
652
653 Hide_cursor();
654 Cursor_shape=old_cursor_shape;
655 Display_cursor();
656
657 if (!File_error)
658 // L'ayant sauvée avec succès,
659 return 1; // On peut quitter
660 else
661 // Il y a eu une erreur lors de la sauvegarde,
662 return 0; // On ne peut donc pas quitter
663 }
664 else
665 // L'utilisateur ne veut pas écraser l'ancien fichier,
666 return 0; // On doit donc rester
667 case 3 : return 1; // Quitter
668 }
669 return 0;
670 }
671
672
Button_Quit(int btn)673 void Button_Quit(int btn)
674 {
675 //short clicked_button;
676
677 if (Button_Quit_local_function())
678 {
679 if (Spare.image_is_modified)
680 {
681 Button_Page(BUTTON_PAGE); // On passe sur le brouillon
682 // Si l'utilisateur présente les derniers symptomes de l'abandon
683 if (Button_Quit_local_function())
684 Quitting=1;
685 }
686 else
687 Quitting=1;
688 }
689
690 if ( (Menu_is_visible) && (Mouse_Y+8>Menu_Y) )
691 Hide_cursor();
692
693 Unselect_button(btn);
694
695 if ( (Menu_is_visible) && (Mouse_Y+8>Menu_Y) )
696 Display_cursor();
697 }
698
699
700 //---------------------------- Effacer l'écran -------------------------------
Button_Clear(int btn)701 void Button_Clear(int btn)
702 {
703 Hide_cursor();
704 Backup();
705 if (Stencil_mode && Config.Clear_with_stencil)
706 Clear_current_image_with_stencil(Main.backups->Pages->Transparent_color,Stencil);
707 else
708 Clear_current_image(Main.backups->Pages->Transparent_color);
709 Redraw_layered_image();
710 End_of_modification();
711 Display_all_screen();
712 Unselect_button(btn);
713 Display_cursor();
714 }
715
Button_Clear_with_backcolor(int btn)716 void Button_Clear_with_backcolor(int btn)
717 {
718 Hide_cursor();
719 Backup();
720 if (Stencil_mode && Config.Clear_with_stencil)
721 Clear_current_image_with_stencil(Back_color,Stencil);
722 else
723 Clear_current_image(Back_color);
724 Redraw_layered_image();
725 End_of_modification();
726 Display_all_screen();
727 Unselect_button(btn);
728 Display_cursor();
729 }
730
731
732 //------------------------------- Paramètres ---------------------------------
733
734 #define SETTING_PER_PAGE 11
735 #define SETTING_PAGES 5
736
737 #define SETTING_HEIGHT 12
738
739 typedef struct {
740 const char* Label; // Use NULL label to stop an array
741 int Code;
742 } T_Lookup;
743
744 const T_Lookup Lookup_YesNo[] = {
745 {"NO",0},
746 {"YES",1},
747 {NULL,-1},
748 };
749
750 const T_Lookup Lookup_FFF[] = {
751 {"All",0},
752 {"Files",1},
753 {"Dirs.",2},
754 {NULL,-1},
755 };
756
757 const T_Lookup Lookup_AutoRes[] = {
758 {"Internal",1},
759 {"Real",2},
760 {NULL,-1},
761 };
762
763 const T_Lookup Lookup_Coords[] = {
764 {"Relative",1},
765 {"Absolute",2},
766 {NULL,-1},
767 };
768
769 const T_Lookup Lookup_MenuRatio[] = {
770 {"None",0},
771 {"x2",254}, // -2
772 {"x3",253}, // -3
773 {"x4",252}, // -4
774 {"Moderate",2},
775 {"Maximum",1},
776 {NULL,-1},
777 };
778
779 const T_Lookup Lookup_MouseSpeed[] = {
780 {"Normal",1},
781 {"/2",2},
782 {"/3",3},
783 {"/4",4},
784 {NULL,-1},
785 };
786
787 const T_Lookup Lookup_SwapButtons[] = {
788 {"None",0},
789 {"Control",GFX2_MOD_CTRL},
790 {"Alt",GFX2_MOD_ALT},
791 {NULL,-1},
792 };
793
794 const T_Lookup Lookup_VirtualKeyboard[] = {
795 {"Auto",0},
796 {"ON",1},
797 {"OFF",2},
798 {NULL,-1},
799 };
800
801 typedef struct {
802 const char* Label;
803 byte Type; // 0: label, 1+: setting (size in bytes)
804 void * Value;
805 int Min_value;
806 int Max_value;
807 int Digits; // Could be computed from Max_value...but don't bother.
808 const T_Lookup * Lookup;
809 } T_Setting;
810
Get_setting_value(const T_Setting * item)811 long int Get_setting_value(const T_Setting *item)
812 {
813 switch(item->Type)
814 {
815 case 1:
816 return *((byte *)(item->Value));
817 break;
818 case 2:
819 return *((word *)(item->Value));
820 break;
821 case 4:
822 default:
823 return *((long int *)(item->Value));
824 break;
825 }
826 }
827
Set_setting_value(const T_Setting * item,long int value)828 void Set_setting_value(const T_Setting *item, long int value)
829 {
830 switch(item->Type)
831 {
832 case 1:
833 *((byte *)(item->Value)) = value;
834 break;
835 case 2:
836 *((word *)(item->Value)) = value;
837 break;
838 case 4:
839 default:
840 *((long int *)(item->Value)) = value;
841 break;
842 }
843 }
844
845 // Fetch a label in a lookup table. Unknown values get label 0.
Lookup_code(int code,const T_Lookup * lookup)846 const char *Lookup_code(int code, const T_Lookup *lookup)
847 {
848 int i;
849
850 for(i=0; lookup[i].Label!=NULL; i++)
851 {
852 if (lookup[i].Code == code)
853 return lookup[i].Label;
854 }
855 return lookup[0].Label;
856 }
857
858 /// Increase an enum to next-higher value (wrapping).
Lookup_next(int code,const T_Lookup * lookup)859 int Lookup_next(int code, const T_Lookup *lookup)
860 {
861 int i;
862
863 for(i=0; lookup[i].Label!=NULL; i++)
864 {
865 if (lookup[i].Code == code)
866 {
867 if (lookup[i+1].Label==NULL)
868 return lookup[0].Code;
869 return lookup[i+1].Code;
870 }
871 }
872 return 0;
873 }
874
875 /// Decrease an enum to previous value (wrapping).
Lookup_previous(int code,const T_Lookup * lookup)876 int Lookup_previous(int code, const T_Lookup *lookup)
877 {
878 int count;
879 int current=-1;
880
881 for(count=0; lookup[count].Label!=NULL; count++)
882 {
883 if (lookup[count].Code == code)
884 current=count;
885 }
886
887 return lookup[(current + count - 1) % count].Code;
888 }
889
Settings_display_config(const T_Setting * setting,T_Config * conf,T_Special_button * panel)890 void Settings_display_config(const T_Setting *setting, T_Config * conf, T_Special_button *panel)
891 {
892 int i;
893
894 // A single button
895 Print_in_window(155,166,(conf->Auto_save)?"YES":" NO",MC_Black,MC_Light);
896
897 // Clear all
898 Window_rectangle(panel->Pos_X, panel->Pos_Y, panel->Width, panel->Height+1, MC_Light);
899 for (i=0; i<SETTING_PER_PAGE; i++)
900 {
901 Print_in_window(panel->Pos_X+3, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, setting[i].Label, i==0?MC_White:MC_Dark, MC_Light);
902 if(setting[i].Value)
903 {
904
905 int value = Get_setting_value(&setting[i]);
906
907 if (setting[i].Lookup)
908 {
909 // Use a lookup table to print a label
910 const char *str;
911 str = Lookup_code(value,setting[i].Lookup);
912 Print_in_window(panel->Pos_X+3+176, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, str, MC_Black, MC_Light);
913 }
914 else
915 {
916 // Print a number
917 char str[10];
918 Num2str(value,str,setting[i].Digits);
919 Print_in_window(panel->Pos_X+3+176, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, str, MC_Black, MC_Light);
920 }
921 }
922 }
923 Update_window_area(panel->Pos_X, panel->Pos_Y, panel->Width, panel->Height+1);
924 }
925
Settings_save_config(T_Config * conf)926 void Settings_save_config(T_Config * conf)
927 {
928 if (Save_CFG())
929 Error(0);
930 else
931 if (Save_INI(conf))
932 Error(0);
933 }
934
Settings_load_config(T_Config * conf)935 void Settings_load_config(T_Config * conf)
936 {
937 if (Load_CFG(0))
938 Error(0);
939 else
940 if (Load_INI(conf))
941 Error(0);
942 }
943
Button_Settings(int btn)944 void Button_Settings(int btn)
945 {
946 short clicked_button;
947 T_Config selected_config;
948 byte config_is_reloaded=0;
949 T_Special_button *panel;
950 byte need_redraw=1;
951 static byte current_page=0;
952
953 // Definition of settings pages
954 // Label,Type (0 = label, 1+ = setting size in bytes),
955 // Value, min, max, digits, Lookup)
956
957 const T_Setting setting[SETTING_PER_PAGE*SETTING_PAGES] = {
958
959 {" --- GUI ---",0,NULL,0,0,0,NULL},
960 {"Opening message:",1,&(selected_config.Opening_message),0,1,0,Lookup_YesNo},
961 {"Menu ratio adapt:",1,&(selected_config.Ratio),0,1,0,Lookup_MenuRatio},
962 {"Draw limits:",1,&(selected_config.Display_image_limits),0,1,0,Lookup_YesNo},
963 {"Coordinates:",1,&(selected_config.Coords_rel),0,1,0,Lookup_Coords},
964 {"Separate colors:",1,&(selected_config.Separate_colors),0,1,0,Lookup_YesNo},
965 {"Safety colors:",1,&(selected_config.Safety_colors),0,1,0,Lookup_YesNo},
966 {"Sync views:",1,&(selected_config.Sync_views),0,1,0,Lookup_YesNo},
967 {"",0,NULL,0,0,0,NULL},
968 {"",0,NULL,0,0,0,NULL},
969 {"",0,NULL,0,0,0,NULL},
970
971 {" --- Input ---",0,NULL,0,0,0,NULL},
972 {"Scrollbar speed",0,NULL,0,0,0,NULL},
973 {" on left click:",1,&(selected_config.Delay_left_click_on_slider),1,255,4,NULL},
974 {" on right click:",1,&(selected_config.Delay_right_click_on_slider),1,255,4,NULL},
975 {"Merge movement:",1,&(selected_config.Mouse_merge_movement),0,100,4,NULL},
976 {"Double click speed:",2,&(selected_config.Double_click_speed),1,1999,4,NULL},
977 {"Double key speed:",2,&(selected_config.Double_key_speed),1,1999,4,NULL},
978 //{"Mouse speed (fullscreen)",0,NULL,0,0,0,NULL},
979 //{" horizontally:",1,&(selected_config.Mouse_sensitivity_index_x),1,4,0,Lookup_MouseSpeed},
980 //{" vertically:",1,&(selected_config.Mouse_sensitivity_index_y),1,4,0,Lookup_MouseSpeed},
981 {"Key to swap buttons:",2,&(selected_config.Swap_buttons),0,0,0,Lookup_SwapButtons},
982 {"Virtual keyboard",1,&(selected_config.Use_virtual_keyboard),0,2,0,Lookup_VirtualKeyboard},
983 {"",0,NULL,0,0,0,NULL},
984 {"",0,NULL,0,0,0,NULL},
985
986 {" --- Editing ---",0,NULL,0,0,0,NULL},
987 {"Adjust brush pick:",1,&(selected_config.Adjust_brush_pick),0,1,0,Lookup_YesNo},
988 {"Undo pages:",1,&(selected_config.Max_undo_pages),1,99,5,NULL},
989 {"Vertices per polygon:",4,&(selected_config.Nb_max_vertices_per_polygon),2,16384,5,NULL},
990 {"Fast zoom:",1,&(selected_config.Fast_zoom),0,1,0,Lookup_YesNo},
991 {"Clear with stencil:",1,&(selected_config.Clear_with_stencil),0,1,0,Lookup_YesNo},
992 {"Auto discontinuous:",1,&(selected_config.Auto_discontinuous),0,1,0,Lookup_YesNo},
993 {"Auto count colors:",1,&(selected_config.Auto_nb_used),0,1,0,Lookup_YesNo},
994 {"Right click colorpick:",1,&(selected_config.Right_click_colorpick),0,1,0,Lookup_YesNo},
995 {"Multi shortcuts:",1,&(selected_config.Allow_multi_shortcuts),0,1,0,Lookup_YesNo},
996 {"",0,NULL,0,0,0,NULL},
997
998 {" --- File selector ---",0,NULL,0,0,0,NULL},
999 {"Show in fileselector",0,NULL,0,0,0,NULL},
1000 {" Hidden files:",4,&(selected_config.Show_hidden_files),0,1,0,Lookup_YesNo},
1001 {" Hidden dirs:",4,&(selected_config.Show_hidden_directories),0,1,0,Lookup_YesNo},
1002 {"Preview delay:",4,&(selected_config.Timer_delay), 1,256,3,NULL},
1003 {"Maximize preview:",1,&(selected_config.Maximize_preview), 0,1,0,Lookup_YesNo},
1004 {"Find file fast:",1,&(selected_config.Find_file_fast), 0,2,0,Lookup_FFF},
1005 {"Auto set resolution:",1,&(selected_config.Auto_set_res), 0,1,0,Lookup_YesNo},
1006 {" According to:",1,&(selected_config.Set_resolution_according_to), 1,2,0,Lookup_AutoRes},
1007 {"Backup:",1,&(selected_config.Backup), 0,1,0,Lookup_YesNo},
1008 {"",0,NULL,0,0,0,NULL},
1009
1010 {" --- Format options ---",0,NULL,0,0,0,NULL},
1011 {"Screen size in GIF:",1,&(selected_config.Screen_size_in_GIF),0,1,0,Lookup_YesNo},
1012 {"Clear palette:",1,&(selected_config.Clear_palette),0,1,0,Lookup_YesNo},
1013 {"MO6/TO8 palette gamma",1,&(selected_config.MOTO_gamma),10,30,2,NULL},
1014 {"",0,NULL,0,0,0,NULL},
1015 {"",0,NULL,0,0,0,NULL},
1016 {"",0,NULL,0,0,0,NULL},
1017 {"",0,NULL,0,0,0,NULL},
1018 {"",0,NULL,0,0,0,NULL},
1019 {"",0,NULL,0,0,0,NULL},
1020 {"",0,NULL,0,0,0,NULL},
1021
1022
1023 };
1024
1025 const char * help_section[SETTING_PAGES] = {
1026 "GUI",
1027 "INPUT",
1028 "EDITING",
1029 "FILE SELECTOR",
1030 "FILE FORMAT OPTIONS",
1031 };
1032
1033 selected_config=Config;
1034
1035 Open_window(307,182,"Settings");
1036
1037 // Button Reload
1038 Window_set_normal_button( 6,163, 51,14,"Reload" ,1,1,KEY_r); // 1
1039 // Button Auto-save
1040 Window_set_normal_button( 73,163,107,14,"Auto-save: ",1,1,KEY_a); // 2
1041 // Button Save
1042 Window_set_normal_button(183,163, 51,14,"Save" ,1,1,KEY_s); // 3
1043 // Button Close
1044 Window_set_normal_button(250,163, 51,14,"Close" ,0,1,KEY_ESC); // 4
1045
1046 panel=Window_set_special_button(10, 21, 272,SETTING_PER_PAGE*SETTING_HEIGHT,0); // 5
1047 Window_set_scroller_button(285,21,SETTING_PER_PAGE*SETTING_HEIGHT,SETTING_PAGES,1,current_page); // 6
1048
1049 Update_window_area(0,0,Window_width, Window_height);
1050 Display_cursor();
1051
1052 do
1053 {
1054 if (need_redraw)
1055 {
1056 Hide_cursor();
1057 Settings_display_config(setting+current_page*SETTING_PER_PAGE, &selected_config, panel);
1058 if (need_redraw & 2)
1059 {
1060 // Including slider position
1061 Window_scroller_button_list->Position=current_page;
1062 Window_draw_slider(Window_scroller_button_list);
1063 }
1064
1065 Display_cursor();
1066
1067 need_redraw=0;
1068 }
1069
1070 clicked_button=Window_clicked_button();
1071
1072 switch(clicked_button)
1073 {
1074
1075 case 1 : // Reload
1076 Settings_load_config(&selected_config);
1077 config_is_reloaded=1;
1078 need_redraw=1;
1079 break;
1080 case 2 : // Auto-save
1081 selected_config.Auto_save=!selected_config.Auto_save;
1082 need_redraw=1;
1083 break;
1084 case 3 : // Save
1085 Settings_save_config(&selected_config);
1086 break;
1087 // case 4: // Close
1088
1089 case 5: // Panel area
1090 {
1091
1092 int num=(((short)Mouse_Y-Window_pos_Y)/Menu_factor_Y - panel->Pos_Y)/SETTING_HEIGHT;
1093 if (num >= 0 && num < SETTING_PER_PAGE)
1094 {
1095 const T_Setting * item = &setting[current_page*SETTING_PER_PAGE+num];
1096 if (item->Type!=0)
1097 {
1098 // Remember which button is clicked
1099 byte old_mouse_k = Mouse_K;
1100
1101 if (Window_normal_button_onclick(panel->Pos_X, panel->Pos_Y+num*SETTING_HEIGHT, panel->Width, SETTING_HEIGHT+1, 5))
1102 {
1103 int value = Get_setting_value(item);
1104
1105 if (item->Lookup)
1106 {
1107 // Enum: toggle it
1108 if (old_mouse_k & LEFT_SIDE)
1109 value = Lookup_next(value, item->Lookup);
1110 else
1111 value = Lookup_previous(value, item->Lookup);
1112 Set_setting_value(item, value);
1113 }
1114 else
1115 {
1116 // Numeric: edit it
1117 char str[10];
1118 str[0]='\0';
1119 if (! (old_mouse_k & RIGHT_SIDE))
1120 Num2str(value,str,item->Digits+1);
1121 if (Readline(panel->Pos_X+3+176, panel->Pos_Y+num*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2,str,item->Digits+1,INPUT_TYPE_INTEGER))
1122 {
1123 value=atoi(str);
1124 if (value<item->Min_value)
1125 value = item->Min_value;
1126 else if (value>item->Max_value)
1127 value = item->Max_value;
1128
1129 Set_setting_value(item, value);
1130 }
1131 Key=0; // Need to discard keys used during editing
1132 }
1133 }
1134 }
1135 }
1136 }
1137 need_redraw=1;
1138 break;
1139 case 6: // Scroller
1140 current_page = Window_attribute2;
1141 need_redraw=1;
1142 break;
1143
1144 }
1145
1146 if (Key == KEY_MOUSEWHEELDOWN)
1147 {
1148 if (current_page < (SETTING_PAGES-1))
1149 {
1150 current_page++;
1151 need_redraw=2;
1152 }
1153 }
1154 else if (Key == KEY_MOUSEWHEELUP)
1155 {
1156 if (current_page > 0)
1157 {
1158 current_page--;
1159 need_redraw=2;
1160 }
1161 }
1162 else if (Is_shortcut(Key,0x100+BUTTON_HELP))
1163 Window_help(NB_BUTTONS+0, help_section[current_page]);
1164 else if (Is_shortcut(Key,0x100+BUTTON_SETTINGS))
1165 clicked_button=4;
1166 }
1167 while ( (clicked_button!=4) && (Key!=KEY_RETURN) && !Quit_is_required);
1168
1169 // Checks on change
1170 if (Config.Show_hidden_directories!=selected_config.Show_hidden_directories
1171 ||Config.Show_hidden_files!=selected_config.Show_hidden_files)
1172 {
1173 // Reset fileselector offsets
1174 // since different files are shown now
1175 Main.selector.Position=0;
1176 Main.selector.Offset=0;
1177 Spare.selector.Position=0;
1178 Spare.selector.Offset=0;
1179 Brush_selector.Position=0;
1180 Brush_selector.Offset=0;
1181 Palette_selector.Position=0;
1182 Palette_selector.Offset=0;
1183 }
1184 if(Config.Allow_multi_shortcuts && !selected_config.Allow_multi_shortcuts)
1185 {
1186 // User just disabled multi shortcuts: make them unique now.
1187 Remove_duplicate_shortcuts();
1188 }
1189 // Copy all
1190 Config=selected_config;
1191
1192 if (config_is_reloaded)
1193 Compute_optimal_menu_colors(Main.palette);
1194
1195 Close_window();
1196 Unselect_button(btn);
1197 // Raffichage du menu pour que les inscriptions qui y figurent soient
1198 // retracées avec la nouvelle fonte
1199 Display_menu();
1200 Display_cursor();
1201
1202 // On vérifie qu'on peut bien allouer le nombre de pages Undo.
1203 Set_number_of_backups(Config.Max_undo_pages);
1204 }
1205
1206 // Data for skin selector
1207 T_Fileselector Skin_files_list;
1208
1209
1210 // Data for font selector
1211 T_Fileselector Font_files_list;
1212
1213 //
Format_font_filename(const char * fname)1214 char * Format_font_filename(const char * fname)
1215 {
1216 static char result[12];
1217 int c;
1218 int length;
1219
1220 fname+=strlen(FONT_PREFIX); // Omit file prefix
1221 length=strlen(fname) - 4; // assume .png extension
1222
1223 for (c=0;c<11 && c<length ;c++)
1224 {
1225 result[c]=fname[c];
1226 }
1227 result[c]='\0';
1228 if (length>11)
1229 result[10] = ELLIPSIS_CHARACTER;
1230
1231 return result;
1232 }
1233
1234 // Add a skin to the list
Add_font_or_skin(const char * full_name,const char * fname)1235 static void Add_font_or_skin(const char * full_name, const char * fname)
1236 {
1237 size_t namelength;
1238 (void)full_name;
1239
1240 namelength = strlen(fname);
1241 if (namelength>=10 && fname[0]!='_' && !strncasecmp(fname, SKIN_PREFIX, strlen(SKIN_PREFIX))
1242 && (!strcasecmp(fname + namelength - 4,".png")
1243 || !strcasecmp(fname + namelength - 4,".gif")))
1244 {
1245 Add_element_to_list(&Skin_files_list, fname, Format_filename(fname, 19, 0), FSOBJECT_FILE, ICON_NONE);
1246
1247 if (fname[0]=='\0')
1248 return;
1249 }
1250 else if (namelength>=10 && !strncasecmp(fname, FONT_PREFIX, strlen(FONT_PREFIX))
1251 && (!strcasecmp(fname + namelength - 4, ".png")))
1252 {
1253 Add_element_to_list(&Font_files_list, fname, Format_font_filename(fname), FSOBJECT_FILE, ICON_NONE);
1254
1255 if (fname[0]=='\0')
1256 return;
1257 }
1258
1259 }
1260
1261 // Callback to display a skin name in the list
Draw_one_skin_name(word x,word y,word index,byte highlighted)1262 void Draw_one_skin_name(word x, word y, word index, byte highlighted)
1263 {
1264 T_Fileselector_item * current_item;
1265
1266 if (Skin_files_list.Nb_elements)
1267 {
1268 current_item = Get_item_by_index(&Skin_files_list, index);
1269 Print_in_window(x, y, current_item->Short_name, MC_Black,
1270 (highlighted)?MC_Dark:MC_Light);
1271 }
1272 }
1273
1274 /// Skin selector window
Button_Skins(int btn)1275 void Button_Skins(int btn)
1276 {
1277 short clicked_button;
1278 short temp;
1279 char * skinsdir;
1280 T_Dropdown_button * font_dropdown;
1281 T_Dropdown_button * cursor_dropdown;
1282 T_List_button * skin_list;
1283 T_Scroller_button * file_scroller;
1284 int selected_font = 0;
1285 int selected_cursor = Config.Cursor;
1286 byte separatecolors = Config.Separate_colors;
1287 byte showlimits = Config.Display_image_limits;
1288 byte need_load=1;
1289 int button;
1290
1291 word x, y, x_pos, offs_y;
1292
1293 const char * cursors[] = { "Solid", "Transparent", "Thin" };
1294 T_Gui_skin * gfx = NULL;
1295 byte * new_font;
1296
1297 #define FILESEL_Y 34
1298
1299 // --- Read the contents of skins/ directory ------------------
1300
1301 // Here we use the same data container as the fileselectors.
1302 // Reinitialize the list
1303 Free_fileselector_list(&Skin_files_list);
1304 Free_fileselector_list(&Font_files_list);
1305 // Browse the "skins" directory
1306 skinsdir = Filepath_append_to_dir(Data_directory, SKINS_SUBDIRECTORY);
1307 // Add each found file to the list
1308 For_each_file(skinsdir, Add_font_or_skin);
1309 // Sort it
1310 Sort_list_of_files(&Skin_files_list);
1311 Sort_list_of_files(&Font_files_list);
1312
1313 selected_font = Find_file_in_fileselector(&Font_files_list, Config.Font_file);
1314 if (selected_font < 0)
1315 selected_font = 0;
1316
1317 // --------------------------------------------------------------
1318
1319 Open_window(290, 140, "Skins");
1320
1321 // Frames
1322 Window_display_frame_in(6, FILESEL_Y - 2, 148, 84); // File selector
1323
1324 // Texts
1325 Print_in_window( 172, 33,"Font:" ,MC_Black,MC_Light);
1326 Print_in_window( 172, 59,"Cursor:" ,MC_Black,MC_Light);
1327
1328 // Ok button
1329 Window_set_normal_button(6, 120, 51, 14, "OK", 0, 1, KEY_RETURN); // 1
1330
1331 // List of skins
1332 skin_list = Window_set_list_button(
1333 // Fileselector
1334 Window_set_special_button(8, FILESEL_Y + 1, 144, 80,0), // 2
1335 // Scroller for the fileselector
1336 (file_scroller = Window_set_scroller_button(155, FILESEL_Y - 1, 82,
1337 Skin_files_list.Nb_elements, 10, 0)), // 3
1338 Draw_one_skin_name, 2); // 4
1339
1340 skin_list->Cursor_position = Find_file_in_fileselector(&Skin_files_list, Config.Skin_file);
1341 if (skin_list->Cursor_position < 0)
1342 skin_list->Cursor_position = 0;
1343
1344 // Buttons to choose a font
1345 font_dropdown = Window_set_dropdown_button(172, 43, 104, 11, 0, Get_item_by_index(&Font_files_list,selected_font)->Short_name,1,0,1,RIGHT_SIDE|LEFT_SIDE,0); // 5
1346 for (temp=0; temp<Font_files_list.Nb_files; temp++)
1347 Window_dropdown_add_item(font_dropdown,temp,Get_item_by_index(&Font_files_list,temp)->Short_name);
1348
1349 // Cancel
1350 Window_set_normal_button(61, 120, 51,14,"Cancel",0,1,KEY_ESCAPE); // 6
1351
1352 // Dropdown list to choose cursor type
1353 cursor_dropdown = Window_set_dropdown_button(172, 69, 104, 11, 0,
1354 cursors[selected_cursor], 1, 0, 1, RIGHT_SIDE|LEFT_SIDE,0); // 7
1355 for (temp = 0; temp<3; temp++)
1356 Window_dropdown_add_item(cursor_dropdown, temp, cursors[temp]);
1357
1358 Window_set_normal_button(172, 87, 14, 14,
1359 (Config.Display_image_limits)?"X":" ", -1, 1, KEY_NONE); // 8
1360 Print_in_window( 190, 85,"Draw picture", MC_Dark, MC_Light);
1361 Print_in_window( 190, 94,"limits", MC_Dark, MC_Light);
1362
1363 Window_set_normal_button(172, 111, 14, 14,
1364 (Config.Separate_colors)?"X":" ", -1, 1, KEY_NONE); // 9
1365 Print_in_window( 190, 109,"Separate", MC_Dark, MC_Light);
1366 Print_in_window( 190, 118,"colors", MC_Dark, MC_Light);
1367
1368 Window_redraw_list(skin_list);
1369
1370 for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++)
1371 for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++)
1372 Pixel_in_window(x, y, Gfx->Preview[offs_y][x_pos]);
1373
1374 Update_window_area(0, 0, Window_width, Window_height);
1375
1376 Display_cursor();
1377
1378 do
1379 {
1380 if (need_load)
1381 {
1382 need_load=0;
1383
1384 Hide_cursor();
1385 // (Re-)load GUI graphics from selected skins
1386 free(skinsdir);
1387 skinsdir = strdup(Get_item_by_index(&Skin_files_list,
1388 skin_list->List_start + skin_list->Cursor_position)->Full_name);
1389
1390 gfx = Load_graphics(skinsdir, NULL);
1391 if (gfx == NULL) // Error
1392 {
1393 Display_cursor();
1394 Verbose_message("Error!", Gui_loading_error_message);
1395 Hide_cursor();
1396 // Update preview
1397 Window_rectangle(6, 14, 173, 16, MC_Light);
1398 }
1399 else
1400 {
1401 // Update preview
1402
1403 // Display the bitmap according to its own color indices
1404 for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++)
1405 for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++)
1406 {
1407 if (gfx->Preview[offs_y][x_pos] == gfx->Color[0])
1408 Pixel_in_window(x, y, MC_Black);
1409 else if (gfx->Preview[offs_y][x_pos] == gfx->Color[1])
1410 Pixel_in_window(x, y, MC_Dark);
1411 else if (gfx->Preview[offs_y][x_pos] == gfx->Color[3])
1412 Pixel_in_window(x, y, MC_White);
1413 else if (gfx->Preview[offs_y][x_pos] == gfx->Color[2])
1414 Pixel_in_window(x, y, MC_Light);
1415 }
1416 // Actualize current screen according to preferred GUI colors
1417 // Note this only updates onscreen colors
1418 Set_color(
1419 MC_Black,
1420 gfx->Default_palette[gfx->Color[0]].R,
1421 gfx->Default_palette[gfx->Color[0]].G,
1422 gfx->Default_palette[gfx->Color[0]].B);
1423 Set_color(
1424 MC_Dark,
1425 gfx->Default_palette[gfx->Color[1]].R,
1426 gfx->Default_palette[gfx->Color[1]].G,
1427 gfx->Default_palette[gfx->Color[1]].B);
1428 Set_color(
1429 MC_Light,
1430 gfx->Default_palette[gfx->Color[2]].R,
1431 gfx->Default_palette[gfx->Color[2]].G,
1432 gfx->Default_palette[gfx->Color[2]].B);
1433 Set_color(
1434 MC_White,
1435 gfx->Default_palette[gfx->Color[3]].R,
1436 gfx->Default_palette[gfx->Color[3]].G,
1437 gfx->Default_palette[gfx->Color[3]].B);
1438 }
1439 Update_window_area(6, 14, 173, 16);
1440 Display_cursor();
1441 }
1442
1443 clicked_button=Window_clicked_button();
1444 if (Is_shortcut(Key,0x100+BUTTON_HELP))
1445 Window_help(BUTTON_SETTINGS, "SKINS");
1446
1447 switch(clicked_button)
1448 {
1449 case 1 : // OK
1450 break;
1451 case 2 : // double-click file: do nothing
1452 break;
1453 case 3 : // doesn't happen
1454 break;
1455 case 4 : // a file is selected
1456 need_load=1;
1457 break;
1458 case 5 : // Font dropdown
1459 {
1460 T_Fileselector_item* fontName;
1461 selected_font = Window_attribute2; // Get the index of the chosen font.
1462 fontName = Get_item_by_index(&Font_files_list,selected_font);
1463 new_font = Load_font(fontName->Full_name, 1);
1464 if (new_font)
1465 {
1466 free(Menu_font);
1467 Menu_font = new_font;
1468 Print_in_window( 172, 33,"Font:" ,MC_Black,MC_Light);
1469 Print_in_window_limited(font_dropdown->Pos_X+2,font_dropdown->Pos_Y+(font_dropdown->Height-7)/2,
1470 fontName->Short_name,(byte)strlen(fontName->Short_name) ,MC_Black,MC_Light);
1471 Update_window_area(172, 33, 8 * 5, 8);
1472 }
1473 break;
1474 }
1475 // 6: Cancel
1476 case 7 : // Cursor
1477 selected_cursor = Window_attribute2;
1478 break;
1479 case 8: // Display limits
1480 showlimits = !showlimits;
1481 Hide_cursor();
1482 Print_in_window(175, 90, (showlimits)?"X":" ", MC_Black, MC_Light);
1483 Display_cursor();
1484 break;
1485 case 9: // Separate colors
1486 separatecolors = !separatecolors;
1487 Hide_cursor();
1488 Print_in_window(175, 114, (separatecolors)?"X":" ", MC_Black, MC_Light);
1489 Display_cursor();
1490 break;
1491 }
1492 }
1493 while ( (clicked_button!=1) && (clicked_button !=6) && (Key != KEY_ESCAPE) && !Quit_is_required);
1494
1495 if(clicked_button == 1)
1496 {
1497 if (gfx != NULL)
1498 {
1499 Set_current_skin(skinsdir, gfx);
1500 }
1501 // (Re-)load the selected font
1502 new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name, 1);
1503 if (new_font)
1504 {
1505 const char * fname;
1506
1507 free(Menu_font);
1508 Menu_font = new_font;
1509 fname = Get_item_by_index(&Font_files_list,selected_font)->Full_name;
1510 free(Config.Font_file);
1511 Config.Font_file = (char *)strdup(fname);
1512 }
1513 // Confirm the change of cursor shape
1514 Config.Cursor = selected_cursor;
1515 Config.Display_image_limits = showlimits;
1516 Config.Separate_colors = separatecolors;
1517
1518 // Now find the best colors for the new skin in the current palette
1519 // and remap the skin
1520 Compute_optimal_menu_colors(Main.palette);
1521
1522 }
1523
1524 // We don't want to keep the skin's palette, as this would corrupt the current picture's one.
1525 Set_palette(Main.palette);
1526
1527 Close_window();
1528 Unselect_button(btn);
1529
1530 // Raffichage du menu pour que les inscriptions qui y figurent soient retracées avec la nouvelle fonte
1531 Display_menu();
1532 // Redraw all buttons, to ensure all specific sprites are in place.
1533 // This is necessary for multi-state buttons, for example Freehand.
1534 for (button=0; button<NB_BUTTONS; button++)
1535 {
1536 byte state=Buttons_Pool[button].Pressed;
1537 switch(button)
1538 {
1539 case BUTTON_MAGNIFIER:
1540 state|=Main.magnifier_mode;
1541 break;
1542 case BUTTON_EFFECTS:
1543 state|=Any_effect_active();
1544 break;
1545 }
1546 Draw_menu_button(button,state);
1547 }
1548 Display_cursor();
1549 free(skinsdir);
1550 }
1551
1552
1553 //---------------------------- Changement de page ----------------------------
Button_Page(int btn)1554 void Button_Page(int btn)
1555 {
1556 byte factor_index;
1557 T_Document temp_doc;
1558
1559 Hide_cursor();
1560
1561 if (Config.Sync_views)
1562 Copy_view_to_spare();
1563
1564 // First update the page descriptors before swapping them
1565 Upload_infos_page(&Main);
1566 Upload_infos_page(&Spare);
1567
1568 // SWAP
1569 memcpy(&temp_doc, &Main, sizeof(T_Document));
1570 memcpy(&Main, &Spare, sizeof(T_Document));
1571 memcpy(&Spare, &temp_doc, sizeof(T_Document));
1572
1573 Pixel_preview=(Main.magnifier_mode)?Pixel_preview_magnifier:Pixel_preview_normal;
1574
1575 //Redraw_layered_image();
1576 // replaced by
1577 Update_buffers(Main.image_width, Main.image_height);
1578 Update_depth_buffer();
1579 Update_screen_targets();
1580 End_of_modification();
1581 // --
1582
1583 // A la fin, on affiche l'écran
1584 for (factor_index=0; ZOOM_FACTOR[factor_index]!=Main.magnifier_factor; factor_index++);
1585 //Change.magnifier_factor(factor_index,0);
1586 Compute_magnifier_data();
1587 if (Main.magnifier_mode)
1588 Pixel_preview=Pixel_preview_magnifier;
1589 else
1590 Pixel_preview=Pixel_preview_normal;
1591 Compute_limits();
1592 Compute_paintbrush_coordinates();
1593
1594 Set_palette(Main.palette);
1595 Compute_optimal_menu_colors(Main.palette);
1596 Check_menu_mode();
1597 Display_all_screen();
1598 Unselect_button(btn);
1599 Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
1600 // Tilemap mode might be different
1601 Draw_menu_button(BUTTON_EFFECTS,Any_effect_active());
1602 Display_menu();
1603
1604 Display_cursor();
1605 }
1606
1607
1608 // -- Copie de page ---------------------------------------------------------
1609
Copy_image_only(void)1610 void Copy_image_only(void)
1611 {
1612 word old_width=Spare.image_width;
1613 word old_height=Spare.image_height;
1614
1615 if (Backup_and_resize_the_spare(Main.image_width,Main.image_height))
1616 {
1617 byte i;
1618
1619 for (i=0; i<Spare.backups->Pages->Nb_layers; i++)
1620 {
1621 if (i == Spare.current_layer)
1622 {
1623 // Copy the current layer
1624 memcpy(Spare.backups->Pages->Image[i].Pixels,Main.backups->Pages->Image[Main.current_layer].Pixels,Main.image_width*Main.image_height);
1625 }
1626 else
1627 {
1628 // Resize the original layer
1629 Copy_part_of_image_to_another(
1630 Spare.backups->Pages->Next->Image[i].Pixels,0,0,Min(old_width,Spare.image_width),
1631 Min(old_height,Spare.image_height),old_width,
1632 Spare.backups->Pages->Image[i].Pixels,0,0,Spare.image_width);
1633 }
1634 }
1635
1636 // Copie des dimensions de l'image
1637 /*
1638 C'est inutile, le "Backuper et redimensionner brouillon" a déjà modifié
1639 ces valeurs pour qu'elles soient correctes.
1640 */
1641 /*
1642 Spare.image_width=Main.image_width;
1643 Spare.image_height=Main.image_height;
1644 */
1645
1646 Copy_view_to_spare();
1647
1648 // Update the visible buffer of the spare.
1649 // It's a bit complex because at the moment, to save memory,
1650 // the spare doesn't have a full visible_buffer + depth_buffer,
1651 // so I can't use exactly the same technique as for Main page.
1652 // (It's the same reason that the "Page" function gets complex,
1653 // it needs to rebuild a depth buffer only, trusting the
1654 // depth buffer that was already available in Spare_.)
1655 Update_spare_buffers(Spare.image_width,Spare.image_height);
1656 Redraw_spare_image();
1657
1658 }
1659 else
1660 Message_out_of_memory();
1661 }
1662
1663
Copy_some_colors(void)1664 void Copy_some_colors(void)
1665 {
1666 short index;
1667 byte confirmation=0;
1668 static byte mask_color_to_copy[256]; // static to use less stack
1669
1670 memset(mask_color_to_copy,1,256);
1671 Menu_tag_colors("Tag colors to copy",mask_color_to_copy,&confirmation,0, NULL, 0xFFFF);
1672
1673 if (confirmation)
1674 {
1675 // Make a backup with the same pixel data as previous history steps
1676 Backup_the_spare(LAYER_NONE);
1677 for (index=0; index<256; index++)
1678 {
1679 if (mask_color_to_copy[index])
1680 memcpy(Spare.palette+index,Main.palette+index,
1681 sizeof(T_Components));
1682 }
1683 }
1684 }
1685
1686
Button_Copy_page(int btn)1687 void Button_Copy_page(int btn)
1688 {
1689 short clicked_button;
1690
1691
1692 Open_window(168,137,"Copy to spare page");
1693
1694 Window_set_normal_button(10, 20,148,14,"Pixels + palette" , 0,1,KEY_RETURN); // 1
1695 Window_set_normal_button(10, 37,148,14,"Pixels only" , 3,1,KEY_x); // 2
1696 Window_set_normal_button(10, 54,148,14,"Palette only" , 1,1,KEY_p); // 3
1697 Window_set_normal_button(10, 71,148,14,"Some colors only" , 6,1,KEY_c); // 4
1698 Window_set_normal_button(10, 88,148,14,"Palette and remap",13,1,KEY_r); // 5
1699 Window_set_normal_button(44,114, 80,14,"Cancel" , 0,1,KEY_ESC); // 6
1700 Update_window_area(0,0,Window_width, Window_height);
1701
1702 Display_cursor();
1703
1704 do
1705 {
1706 clicked_button=Window_clicked_button();
1707 if (Is_shortcut(Key,0x100+BUTTON_HELP))
1708 Window_help(BUTTON_PAGE, NULL);
1709 else if (Is_shortcut(Key,0x200+BUTTON_PAGE))
1710 clicked_button=6;
1711 }
1712 while (clicked_button<=0 && !Quit_is_required);
1713
1714 Close_window();
1715 Display_cursor();
1716
1717 switch (clicked_button)
1718 {
1719 case 1: // Pixels+palette
1720 // backup is done by the following function
1721 Copy_image_only();
1722 // copie de la palette
1723 memcpy(Spare.palette,Main.palette,sizeof(T_Palette));
1724 // Equivalent of 'end_of_modifications' for spare.
1725 Update_spare_buffers(Spare.image_width,Spare.image_height);
1726 Redraw_spare_image();
1727 Spare.image_is_modified=1;
1728 if (Spare.tilemap_mode)
1729 Disable_tilemap(&Spare);
1730 break;
1731
1732 case 2: // Pixels only
1733 // backup is done by the following function
1734 Copy_image_only();
1735 // Equivalent of 'end_of_modifications' for spare.
1736 Update_spare_buffers(Spare.image_width,Spare.image_height);
1737 Redraw_spare_image();
1738 Spare.image_is_modified=1;
1739 if (Spare.tilemap_mode)
1740 Disable_tilemap(&Spare);
1741 break;
1742
1743 case 3: // Palette only
1744 Backup_the_spare(LAYER_NONE);
1745 // Copy palette
1746 memcpy(Spare.palette,Main.palette,sizeof(T_Palette));
1747 // Equivalent of 'end_of_modifications' for spare.
1748 Update_spare_buffers(Spare.image_width,Spare.image_height);
1749 Redraw_spare_image();
1750 Spare.image_is_modified=1;
1751 break;
1752
1753 case 4: // Some colors
1754 // Will backup if needed
1755 Copy_some_colors();
1756 break;
1757
1758 case 5: // Palette and remap
1759 Backup_the_spare(LAYER_ALL);
1760 Remap_spare();
1761 // Copy palette
1762 memcpy(Spare.palette,Main.palette,sizeof(T_Palette));
1763 // Equivalent of 'end_of_modifications' for spare.
1764 Update_spare_buffers(Spare.image_width,Spare.image_height);
1765 Redraw_spare_image();
1766 Spare.image_is_modified=1;
1767 break;
1768 }
1769
1770 Hide_cursor();
1771 Unselect_button(btn);
1772 Display_cursor();
1773 }
1774
1775
1776 // -- Suppression d'une page -------------------------------------------------
Button_Kill(int btn)1777 void Button_Kill(int btn)
1778 {
1779 if ( (Main.backups->List_size==1)
1780 || (!Confirmation_box("Delete the current page?")) )
1781 {
1782 if (Main.backups->List_size==1)
1783 Warning_message("You can't delete the last page.");
1784 Hide_cursor();
1785 Unselect_button(btn);
1786 Display_cursor();
1787 }
1788 else
1789 {
1790 Hide_cursor();
1791 Free_current_page();
1792
1793 Set_palette(Main.palette);
1794 Compute_optimal_menu_colors(Main.palette);
1795
1796 Display_all_screen();
1797 Unselect_button(btn);
1798 Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
1799 Display_menu();
1800 Display_cursor();
1801 }
1802 }
1803
1804
1805 //------------------------- Dimensions Image/Screen ---------------------------
1806
Check_mode_button(short x_pos,short y_pos,byte state)1807 void Check_mode_button(short x_pos, short y_pos, byte state)
1808 {
1809 byte color;
1810
1811 switch (state & 0x7F)
1812 {
1813 case 0 : color=MC_White; break;
1814 case 1 : color=MC_Light; break;
1815 case 2 : color=MC_Dark; break;
1816 default: color=MC_Black;
1817 }
1818 Window_rectangle(x_pos, y_pos, 9, 3, color);
1819 Update_window_area(x_pos, y_pos,9,3);
1820 }
1821
1822 /// Number of video modes to display in the resolution menu
1823 #define MODELIST_LINES 10
1824
Display_modes_list(short list_start,short cursor_position)1825 void Display_modes_list(short list_start, short cursor_position)
1826 {
1827 short index,current_mode;
1828 short y_pos;
1829 byte text_color,background_color;
1830 char str[29];
1831 char *ratio;
1832
1833 for (current_mode=list_start,index=0; index<MODELIST_LINES && current_mode < Nb_video_modes ; index++,current_mode++)
1834 {
1835 y_pos=86+(index<<3);
1836 Check_mode_button(19,y_pos+2,Video_mode[current_mode].State);
1837
1838 if (cursor_position!=index)
1839 {
1840 background_color =MC_Black;
1841 if ((Video_mode[current_mode].State & 3) == 3)
1842 text_color=MC_Dark;
1843 else
1844 text_color=MC_Light;
1845 }
1846 else
1847 {
1848 background_color =MC_Dark;
1849 if ((Video_mode[current_mode].State & 3) == 3)
1850 text_color=MC_Light;
1851 else
1852 text_color=MC_White;
1853 }
1854 snprintf(str, sizeof(str), "%4hu %4hu", Video_mode[current_mode].Width, Video_mode[current_mode].Height);
1855
1856 if(Video_mode[current_mode].Fullscreen == 0)
1857 memcpy(str+9," Window ",20);
1858 else
1859 {
1860 memcpy(str+9," Fullscreen ",13);
1861
1862 if (Video_mode[current_mode].Width*3 == Video_mode[current_mode].Height*4)
1863 ratio=" 4:3";
1864 else if (Video_mode[current_mode].Width*9 == Video_mode[current_mode].Height*16)
1865 ratio=" 16:9";
1866 else if (Video_mode[current_mode].Width*10 == Video_mode[current_mode].Height*16)
1867 ratio=" 16:10";
1868 else if (Video_mode[current_mode].Width*145 == Video_mode[current_mode].Height*192)
1869 ratio="192:145";
1870 else if (Video_mode[current_mode].Width*2 == Video_mode[current_mode].Height*3)
1871 ratio=" 3:2";
1872 else if (Video_mode[current_mode].Width*3 == Video_mode[current_mode].Height*5)
1873 ratio=" 5:3";
1874 else if (Video_mode[current_mode].Width*4 == Video_mode[current_mode].Height*5)
1875 ratio=" 5:4";
1876 else if (Video_mode[current_mode].Width*16 == Video_mode[current_mode].Height*25)
1877 ratio=" 25:16";
1878 else
1879 ratio=" ";
1880
1881 strcpy(str+21,ratio);
1882 }
1883
1884 Print_in_window(38,y_pos,str,text_color,background_color);
1885 }
1886 }
1887
1888
Scroll_list_of_modes(short list_start,short cursor_position,int * selected_mode)1889 void Scroll_list_of_modes(short list_start, short cursor_position, int * selected_mode)
1890 {
1891 Hide_cursor();
1892 *selected_mode=list_start+cursor_position;
1893 if (Window_scroller_button_list->Position!=list_start)
1894 {
1895 Window_scroller_button_list->Position=list_start;
1896 Window_draw_slider(Window_scroller_button_list);
1897 }
1898 Display_modes_list(list_start,cursor_position);
1899 Display_cursor();
1900 }
1901
Button_Resolution(int btn)1902 void Button_Resolution(int btn)
1903 {
1904 short clicked_button;
1905 int selected_mode;
1906 word chosen_width;
1907 word chosen_height;
1908 byte chosen_pixel;
1909 short list_start;
1910 short cursor_position;
1911 short temp;
1912 char str[8];
1913 T_Special_button * input_width_button, * input_button_height;
1914 T_Dropdown_button * pixel_button;
1915 static const char *pixel_ratio_labels[PIXEL_MAX] ={
1916 "Normal (1x1)",
1917 "Wide (2x1)",
1918 "Tall (1x2)",
1919 "Double (2x2)",
1920 "Triple (3x3)",
1921 "Wide2 (4x2)",
1922 "Tall2 (2x4)",
1923 "Tall3 (3x4)",
1924 "Quadruple (4x4)"};
1925
1926 Open_window(299,190,"Picture & screen sizes");
1927
1928 Print_in_window( 12, 21,"Picture size:" ,MC_Dark,MC_Light);
1929 Window_display_frame ( 8,17,195, 33);
1930
1931 Window_set_normal_button(223, 18,67,14,"OK" ,0,1,KEY_RETURN); // 1
1932 Window_set_normal_button(223, 35,67,14,"Cancel" ,0,1,KEY_ESC); // 2
1933
1934 Print_in_window_underscore( 12, 37,"Width:",MC_Dark,MC_Light,1);
1935 input_width_button=Window_set_input_button_s( 60, 35,4,KEY_w); // 3
1936
1937 Print_in_window_underscore(108, 37,"Height:",MC_Dark,MC_Light,1);
1938 input_button_height=Window_set_input_button_s(164, 35,4,KEY_h); // 4
1939
1940 Window_display_frame ( 8,72,283,110);
1941 Window_display_frame_in (37,84,228,84);
1942 Window_rectangle (38,85,226,82,MC_Black);
1943 Print_in_window( 16, 76,"OK" ,MC_Dark,MC_Light);
1944 Print_in_window( 55, 76,"X Y" ,MC_Dark,MC_Light);
1945 Print_in_window(120, 76,"Win / Full" ,MC_Dark,MC_Light);
1946 Print_in_window(219, 76,"Ratio" ,MC_Dark,MC_Light);
1947 Print_in_window( 30,170,"\03" ,MC_Dark,MC_Light);
1948 Print_in_window( 62,170,"OK" ,MC_Dark,MC_Light);
1949 Print_in_window(102,170,"Imperfect" ,MC_Dark,MC_Light);
1950 Print_in_window(196,170,"Unsupported" ,MC_Dark,MC_Light);
1951 Window_set_special_button(38,86,225,80,0); // 5
1952
1953 selected_mode=Current_resolution;
1954 if (selected_mode>=MODELIST_LINES/2 && Nb_video_modes > MODELIST_LINES)
1955 {
1956 if (selected_mode<Nb_video_modes-MODELIST_LINES/2)
1957 {
1958 list_start=selected_mode-(MODELIST_LINES/2-1);
1959 cursor_position=(MODELIST_LINES/2-1);
1960 }
1961 else
1962 {
1963 list_start=Nb_video_modes-MODELIST_LINES;
1964 cursor_position=selected_mode-list_start;
1965 }
1966 }
1967 else
1968 {
1969 list_start=0;
1970 cursor_position=selected_mode;
1971 }
1972 Window_set_scroller_button(271,85,81,Nb_video_modes,MODELIST_LINES,list_start); // 6
1973
1974 chosen_pixel=Pixel_ratio;
1975 Print_in_window( 12, 57,"Pixel size:" ,MC_Dark,MC_Light);
1976 pixel_button=Window_set_dropdown_button(108,55,17*8,11,17*8,pixel_ratio_labels[Pixel_ratio],1,0,1,LEFT_SIDE|RIGHT_SIDE,0); // 7
1977 for (temp=0;temp<PIXEL_MAX;temp++)
1978 Window_dropdown_add_item(pixel_button,temp,pixel_ratio_labels[temp]);
1979
1980 // 10 little buttons for the state of each visible mode
1981 for (temp=0; temp<MODELIST_LINES && temp < Nb_video_modes; temp++)
1982 Window_set_normal_button(17,86+(temp<<3),13,7,"",0,1,KEY_NONE);// 8..17
1983
1984 // Dummy buttons as explainations of colors
1985 Window_draw_normal_bouton( 16,170,13,7,"",0,0);
1986 Check_mode_button( 18,172,0);
1987 Window_draw_normal_bouton( 48,170,13,7,"",0,0);
1988 Check_mode_button( 50,172,1);
1989 Window_draw_normal_bouton( 88,170,13,7,"",0,0);
1990 Check_mode_button( 90,172,2);
1991 Window_draw_normal_bouton(182,170,13,7,"",0,0);
1992 Check_mode_button(184,172,3);
1993
1994
1995 chosen_width=Main.image_width;
1996 Num2str(chosen_width,str,4);
1997 Window_input_content(input_width_button,str);
1998
1999 chosen_height=Main.image_height;
2000 Num2str(chosen_height,str,4);
2001 Window_input_content(input_button_height,str);
2002
2003 Display_modes_list(list_start,cursor_position);
2004
2005 Update_window_area(0,0,Window_width, Window_height);
2006
2007 Display_cursor();
2008
2009 do
2010 {
2011 clicked_button=Window_clicked_button();
2012
2013 switch (clicked_button)
2014 { case -1: case 0: case 1: case 2:
2015 break;
2016
2017 case 3 : // Largeur
2018 Num2str(chosen_width,str,4);
2019 Readline(62,37,str,4,INPUT_TYPE_INTEGER);
2020 chosen_width=atoi(str);
2021 // On corrige les dimensions
2022 if (chosen_width==0)
2023 {
2024 chosen_width=1;
2025 Num2str(chosen_width,str,4);
2026 Window_input_content(input_width_button,str);
2027 }
2028 Display_cursor();
2029 break;
2030
2031 case 4 : // Height
2032 Num2str(chosen_height,str,4);
2033 Readline(166,37,str,4,INPUT_TYPE_INTEGER);
2034 chosen_height=atoi(str);
2035 // On corrige les dimensions
2036 if (chosen_height==0)
2037 {
2038 chosen_height=1;
2039 Num2str(chosen_height,str,4);
2040 Window_input_content(input_button_height,str);
2041 }
2042 Display_cursor();
2043 break;
2044
2045 case 5: // Liste des modes
2046 temp=(((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-86)>>3;
2047 if (temp<Nb_video_modes && ((Mouse_K==2) || (temp!=cursor_position)))
2048 {
2049 Hide_cursor();
2050 if (temp!=cursor_position)
2051 {
2052 cursor_position=temp;
2053 Display_modes_list(list_start,cursor_position);
2054 }
2055 selected_mode=list_start+cursor_position;
2056 // Si l'utilisateur s'est servi du bouton droit de la souris:
2057 if (Mouse_K==2)
2058 {
2059 // On affecte également les dimensions de l'image:
2060 chosen_width=Video_mode[selected_mode].Width/Pixel_width;
2061 Num2str(chosen_width,str,4);
2062 Window_input_content(input_width_button,str);
2063
2064 chosen_height=Video_mode[selected_mode].Height/Pixel_height;
2065 Num2str(chosen_height,str,4);
2066 Window_input_content(input_button_height,str);
2067 }
2068 Display_cursor();
2069 }
2070 Wait_end_of_click();
2071 break;
2072
2073 case 6: // Scroller
2074 list_start=Window_attribute2;
2075 selected_mode=list_start+cursor_position;
2076 Display_modes_list(list_start,cursor_position);
2077 break;
2078
2079 case 7: // Pixel size
2080 chosen_pixel=Window_attribute2;
2081 break;
2082
2083 default: // Boutons de tag des états des modes
2084 temp=list_start+clicked_button-8;
2085 if (Video_mode[temp].Fullscreen==1 && // On n'a pas le droit de cocher le mode fenêtré
2086 !(Video_mode[temp].State & 128)) // Ni ceux non détectés par SDL
2087 {
2088 if (Window_attribute1==LEFT_SIDE)
2089 Video_mode[temp].State=((Video_mode[temp].State&0x7F)+1)&3;
2090 else
2091 Video_mode[temp].State=((Video_mode[temp].State&0x7F)+3)&3;
2092
2093 Hide_cursor();
2094 //Check_mode_button(19,16+(clicked_button<<3),Video_mode[temp].State);
2095 Display_modes_list(list_start,cursor_position);
2096 Display_cursor();
2097 }
2098 }
2099
2100 // Gestion des touches de déplacement dans la liste
2101 switch (Key)
2102 {
2103 case KEY_UP : // Haut
2104 if (cursor_position>0)
2105 cursor_position--;
2106 else
2107 if (list_start>0)
2108 list_start--;
2109 Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
2110 Key=0;
2111 break;
2112 case KEY_DOWN : // Bas
2113 if (cursor_position<(MODELIST_LINES-1) && cursor_position<(Nb_video_modes-1))
2114 cursor_position++;
2115 else
2116 if (list_start<Nb_video_modes-MODELIST_LINES)
2117 list_start++;
2118 Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
2119 Key=0;
2120 break;
2121 case KEY_PAGEUP : // PageUp
2122 if (cursor_position>0)
2123 cursor_position=0;
2124 else
2125 {
2126 if (list_start>(MODELIST_LINES-1))
2127 list_start-=(MODELIST_LINES-1);
2128 else
2129 list_start=0;
2130 }
2131 Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
2132 Key=0;
2133 break;
2134 case KEY_PAGEDOWN : // PageDown
2135 if (Nb_video_modes<MODELIST_LINES)
2136 cursor_position=Nb_video_modes-1;
2137 else if (cursor_position<(MODELIST_LINES-1))
2138 cursor_position=(MODELIST_LINES-1);
2139 else
2140 {
2141 if (list_start<Nb_video_modes-(MODELIST_LINES*2-1))
2142 list_start+=(MODELIST_LINES-1);
2143 else
2144 list_start=Nb_video_modes-MODELIST_LINES;
2145 }
2146 Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
2147 Key=0;
2148 break;
2149 case KEY_HOME : // Home
2150 list_start=0;
2151 cursor_position=0;
2152 Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
2153 Key=0;
2154 break;
2155 case KEY_END : // End
2156 if (Nb_video_modes<MODELIST_LINES)
2157 cursor_position=Nb_video_modes-1;
2158 else
2159 {
2160 list_start=Nb_video_modes-MODELIST_LINES;
2161 cursor_position=(MODELIST_LINES-1);
2162 }
2163 Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
2164 Key=0;
2165 break;
2166 default:
2167 if (Is_shortcut(Key,0x100+BUTTON_HELP))
2168 {
2169 Window_help(BUTTON_RESOL, NULL);
2170 Key=0;
2171 break;
2172 }
2173 }
2174
2175 }
2176 while ((clicked_button!=1) && (clicked_button!=2) && !Quit_is_required);
2177
2178 Close_window();
2179
2180 if (clicked_button==1) // OK
2181 {
2182 if (Main.magnifier_mode)
2183 Unselect_button(BUTTON_MAGNIFIER);
2184
2185 if ( (chosen_width!=Main.image_width)
2186 || (chosen_height!=Main.image_height) )
2187 {
2188 Resize_image(chosen_width,chosen_height);
2189 End_of_modification();
2190 Tilemap_update();
2191 }
2192
2193 if ((Video_mode[selected_mode].State & 3) == 3 ||
2194 Init_mode_video(
2195 Video_mode[selected_mode].Width,
2196 Video_mode[selected_mode].Height,
2197 Video_mode[selected_mode].Fullscreen,
2198 chosen_pixel))
2199 {
2200 Error(0); // Tell user it is an invalid mode
2201 Pixel_ratio=PIXEL_SIMPLE;
2202 Init_mode_video(
2203 Video_mode[Current_resolution].Width,
2204 Video_mode[Current_resolution].Height,
2205 Video_mode[Current_resolution].Fullscreen,
2206 Pixel_ratio);
2207 }
2208
2209 Display_menu();
2210 Reposition_palette();
2211 Display_all_screen();
2212 }
2213 Paintbrush_X = Mouse_X;
2214 Paintbrush_Y = Mouse_Y;
2215
2216
2217 Unselect_button(btn);
2218 Display_cursor();
2219 }
2220
2221
Button_Safety_resolution(int btn)2222 void Button_Safety_resolution(int btn)
2223 {
2224 // In windowed mode, do nothing
2225 if (Current_resolution==0)
2226 {
2227 Hide_cursor();
2228 Unselect_button(btn);
2229 Display_cursor();
2230 return;
2231 }
2232
2233 Hide_cursor();
2234
2235 Unselect_button(BUTTON_MAGNIFIER);
2236
2237 Init_mode_video(
2238 Video_mode[0].Width,
2239 Video_mode[0].Height,
2240 Video_mode[0].Fullscreen,
2241 PIXEL_SIMPLE);
2242 Current_resolution=0;
2243 Display_menu();
2244 Reposition_palette();
2245 Display_all_screen();
2246
2247 Unselect_button(btn);
2248 // Le pinceau est affiché à la position du clic et pas
2249 Display_cursor();
2250 }
2251
2252
2253 //------------------ Gestion des boutons de dessin à la main -----------------
2254
Button_Draw(int btn)2255 void Button_Draw(int btn)
2256 {
2257 (void)btn;
2258 Hide_cursor();
2259 Start_operation_stack(Selected_freehand_mode);
2260 Display_cursor();
2261 }
2262
2263
Button_Draw_switch_mode(int btn)2264 void Button_Draw_switch_mode(int btn)
2265 {
2266 char icon;
2267
2268 T_Dropdown_button dropdown;
2269 T_Dropdown_choice *item = NULL;
2270 int i;
2271 static const char text[4][14] =
2272 {"Continuous", "Discontinuous", "Single", "Contour fill"};
2273
2274 dropdown.Pos_X =Buttons_Pool[btn].X_offset;
2275 dropdown.Pos_Y =Buttons_Pool[btn].Y_offset;
2276 dropdown.Height =Buttons_Pool[btn].Height;
2277 dropdown.Dropdown_width=14*8;
2278 dropdown.First_item =NULL;
2279 dropdown.Bottom_up =1;
2280
2281 Hide_cursor();
2282
2283 // If we get here from a keyboard shortcut, don't show the menu and directly
2284 // switch to the next drawing mode.
2285 if (Mouse_K != 0) {
2286
2287 for(i = 0; i < 4; i++) {
2288 Window_dropdown_add_item(&dropdown, i, text[i]);
2289 }
2290
2291 item=Dropdown_activate(&dropdown,0,Menu_Y);
2292 }
2293
2294 if (item)
2295 {
2296 Selected_freehand_mode = item->Number;
2297 } else {
2298 Selected_freehand_mode++;
2299 if (Selected_freehand_mode>OPERATION_FILLED_CONTOUR)
2300 Selected_freehand_mode=OPERATION_CONTINUOUS_DRAW;
2301 }
2302
2303 switch(Selected_freehand_mode)
2304 {
2305 default:
2306 case OPERATION_CONTINUOUS_DRAW:
2307 icon=-1;
2308 break;
2309 case OPERATION_DISCONTINUOUS_DRAW:
2310 icon=MENU_SPRITE_DISCONTINUOUS_DRAW;
2311 break;
2312 case OPERATION_POINT_DRAW:
2313 icon=MENU_SPRITE_POINT_DRAW;
2314 break;
2315 case OPERATION_FILLED_CONTOUR:
2316 icon=MENU_SPRITE_CONTOUR_DRAW;
2317 break;
2318 }
2319 Display_sprite_in_menu(btn,icon);
2320 Draw_menu_button(btn,BUTTON_PRESSED);
2321 Start_operation_stack(Selected_freehand_mode);
2322
2323 Display_cursor();
2324 Window_dropdown_clear_items(&dropdown);
2325 }
2326
2327
2328 // -- Gestion des boutons de rectangle vide et plein ------------------------
2329
Button_Empty_rectangle(int btn)2330 void Button_Empty_rectangle(int btn)
2331 {
2332 (void)btn;
2333 Hide_cursor();
2334 Start_operation_stack(OPERATION_EMPTY_RECTANGLE);
2335 Display_cursor();
2336 }
2337
2338
Button_Filled_rectangle(int btn)2339 void Button_Filled_rectangle(int btn)
2340 {
2341 (void)btn;
2342 Hide_cursor();
2343 Start_operation_stack(OPERATION_FILLED_RECTANGLE);
2344 Display_cursor();
2345 }
2346
2347
2348 // -- Gestion des boutons de cercle (ellipse) vide et plein(e) --------------
2349
Button_circle_ellipse(int btn)2350 void Button_circle_ellipse(int btn)
2351 {
2352 word operation;
2353
2354 switch (btn)
2355 {
2356 default:
2357 case BUTTON_CIRCLES:
2358 operation = OPERATION_EMPTY_CIRCLE_CTR;
2359 break;
2360 case BUTTON_FILLCIRC:
2361 operation = OPERATION_FILLED_CIRCLE_CTR;
2362 break;
2363 case BUTTON_SPHERES:
2364 operation = OPERATION_GRAD_CIRCLE_CTR;
2365 break;
2366 }
2367 operation += Selected_circle_ellipse_mode; // CIRCLE_CTR/CIRCLE_CRN/ELLIPSE_CTR/ELLIPSE_CRN;
2368 Hide_cursor();
2369 Start_operation_stack(operation);
2370 Display_cursor();
2371 }
2372
Button_Circle_switch_mode(int btn)2373 void Button_Circle_switch_mode(int btn)
2374 {
2375 T_Dropdown_button dropdown;
2376 T_Dropdown_choice *item = NULL;
2377 int i;
2378 static const char * text[4] =
2379 { "Circle (center/radius)", "Circle (corners)",
2380 "Ellipse (center/radiuses)", "Ellipse (corners)" };
2381
2382 dropdown.Pos_X =Buttons_Pool[btn].X_offset;
2383 dropdown.Pos_Y =Buttons_Pool[btn].Y_offset;
2384 dropdown.Height =Buttons_Pool[btn].Height;
2385 dropdown.Dropdown_width=26*8;
2386 dropdown.First_item =NULL;
2387 dropdown.Bottom_up =1;
2388
2389 Hide_cursor();
2390
2391 // If we get here from a keyboard shortcut, don't show the menu and directly
2392 // switch to the next drawing mode.
2393 if (Mouse_K != 0) {
2394 for(i = 0; i < 4; i++) {
2395 Window_dropdown_add_item(&dropdown, i, text[i]);
2396 }
2397 item=Dropdown_activate(&dropdown,0,Menu_Y);
2398 }
2399
2400 if (item)
2401 {
2402 Selected_circle_ellipse_mode = item->Number;
2403 } else {
2404 Selected_circle_ellipse_mode = (Selected_circle_ellipse_mode + 1) & 3;
2405 }
2406
2407 Display_sprite_in_menu(BUTTON_CIRCLES,
2408 (Selected_circle_ellipse_mode >= 2) ? MENU_SPRITE_ELLIPSES : -1);
2409 Draw_menu_button(BUTTON_CIRCLES,BUTTON_RELEASED);
2410 Display_sprite_in_menu(BUTTON_FILLCIRC,
2411 (Selected_circle_ellipse_mode >= 2) ? MENU_SPRITE_ELLIPSES : -1);
2412 Draw_menu_button(BUTTON_FILLCIRC,BUTTON_RELEASED);
2413 Display_sprite_in_menu(BUTTON_SPHERES,
2414 (Selected_circle_ellipse_mode >= 2) ? MENU_SPRITE_GRAD_ELLIPSE : -1);
2415 Draw_menu_button(BUTTON_SPHERES,BUTTON_RELEASED);
2416 Draw_menu_button(btn,BUTTON_PRESSED);
2417
2418 Display_cursor();
2419 Button_circle_ellipse(btn);
2420 Window_dropdown_clear_items(&dropdown);
2421 }
2422
2423 // -- Gestion du menu des dégradés ------------------------------------------
Draw_button_gradient_style(short x_pos,short y_pos,int technique)2424 void Draw_button_gradient_style(short x_pos,short y_pos,int technique)
2425 {
2426 short line;
2427
2428 // On commence par afficher les 2 côtés qui constituent le dégradé de base:
2429 // Côté gauche (noir)
2430 Window_rectangle(x_pos+2, y_pos+2, 6, 10, MC_Black);
2431 // Côté droit (blanc)
2432 Window_rectangle(x_pos+8, y_pos+2, 5, 10, MC_White);
2433
2434 switch(technique)
2435 {
2436 case 1 : // Dégradé de trames simples
2437 // Au centre, on place 10 lignes tramées simplement
2438 for (line=2;line<2+10;line++)
2439 if (line&1)
2440 {
2441 // Lignes impaires
2442 Pixel_in_window(x_pos+ 5,y_pos+line,MC_White);
2443 Pixel_in_window(x_pos+ 7,y_pos+line,MC_White);
2444 Pixel_in_window(x_pos+ 8,y_pos+line,MC_Black);
2445 }
2446 else
2447 {
2448 // Lignes paires
2449 Pixel_in_window(x_pos+ 6,y_pos+line,MC_White);
2450 Pixel_in_window(x_pos+ 9,y_pos+line,MC_Black);
2451 }
2452 break;
2453 case 2 : // Dégradé de trames étendues
2454 // Au centre, on place 10 lignes tramées de façon compliquée
2455 for (line=2;line<2+10;line++)
2456 if (line&1)
2457 {
2458 // Lignes impaires
2459 Pixel_in_window(x_pos+ 7,y_pos+line,MC_White);
2460 Pixel_in_window(x_pos+ 8,y_pos+line,MC_Black);
2461 Pixel_in_window(x_pos+10,y_pos+line,MC_Black);
2462 }
2463 else
2464 {
2465 // Lignes paires
2466 Pixel_in_window(x_pos+ 4,y_pos+line,MC_White);
2467 Pixel_in_window(x_pos+ 6,y_pos+line,MC_White);
2468 }
2469 }
2470
2471 Update_window_area(x_pos+2,y_pos+2,10,10);
2472 }
2473
Load_gradient_data(int index)2474 void Load_gradient_data(int index)
2475 {
2476 if (Main.backups->Pages->Gradients->Range[index].Start>Main.backups->Pages->Gradients->Range[index].End)
2477 Error(0);
2478 Gradient_lower_bound =Main.backups->Pages->Gradients->Range[index].Start;
2479 Gradient_upper_bound =Main.backups->Pages->Gradients->Range[index].End;
2480 Gradient_is_inverted =Main.backups->Pages->Gradients->Range[index].Inverse;
2481 Gradient_random_factor=Main.backups->Pages->Gradients->Range[index].Mix+1;
2482
2483 Gradient_bounds_range=(Gradient_lower_bound<Gradient_upper_bound)?
2484 Gradient_upper_bound-Gradient_lower_bound:
2485 Gradient_lower_bound-Gradient_upper_bound;
2486 Gradient_bounds_range++;
2487
2488 switch(Main.backups->Pages->Gradients->Range[index].Technique)
2489 {
2490 case 0 : // Degradé de base
2491 Gradient_function=Gradient_basic;
2492 break;
2493 case 1 : // Dégradé de trames simples
2494 Gradient_function=Gradient_dithered;
2495 break;
2496 case 2 : // Dégradé de trames étendues
2497 Gradient_function=Gradient_extra_dithered;
2498 }
2499 }
2500
2501 /// draw the gradient preview for the Gradation menu
Draw_gradient_preview(short start_x,short start_y,short width,short height,int index)2502 static void Draw_gradient_preview(short start_x,short start_y,short width,short height,int index)
2503 {
2504 short x_pos; // Variables de balayage du block en bas de l'écran.
2505 short y_pos;
2506 short end_x;
2507 short end_y;
2508
2509 Load_gradient_data(index);
2510
2511 start_x=Window_pos_X+(start_x*Menu_factor_X);
2512 start_y=Window_pos_Y+(start_y*Menu_factor_Y);
2513
2514 Gradient_total_range=width*Menu_factor_X;
2515
2516 end_x=start_x+Gradient_total_range;
2517 end_y=start_y+(height*Menu_factor_Y);
2518
2519 for (y_pos=start_y;y_pos<end_y;y_pos++)
2520 for (x_pos=start_x;x_pos<end_x;x_pos++)
2521 Gradient_function(x_pos-start_x,x_pos,y_pos);
2522 Update_rect(start_x,start_y,width*Menu_factor_X,height*Menu_factor_Y);
2523 }
2524
2525 /// Tag colors from a gradient range
Tag_color_gradient_range(const T_Gradient_range * range)2526 static void Tag_color_gradient_range(const T_Gradient_range * range)
2527 {
2528 Tag_color_range(range->Start, range->End);
2529 }
2530
2531 /// Print the Color cycling speed in Hz, ms and in DP2E unit
Print_color_cycling_details(short y_pos)2532 static void Print_color_cycling_details(short y_pos)
2533 {
2534 char str[24];
2535
2536 Num2str(Main.backups->Pages->Gradients->Range[Current_gradient].Speed, str, 3);
2537 Print_in_window(73+134, y_pos, str, MC_Black, MC_Light);
2538 if (Main.backups->Pages->Gradients->Range[Current_gradient].Speed > 0)
2539 {
2540 snprintf(str, sizeof(str), "Speed %7.4fHz %4ums",
2541 Main.backups->Pages->Gradients->Range[Current_gradient].Speed * 0.2856,
2542 (unsigned)(1000.0 / (Main.backups->Pages->Gradients->Range[Current_gradient].Speed * 0.2856)));
2543 Print_in_window(8, y_pos, str, MC_Black, MC_Light);
2544 }
2545 else
2546 Print_in_window(8, y_pos, " STOPPED", MC_Black, MC_Light);
2547 }
2548
Button_Gradients(int btn)2549 void Button_Gradients(int btn)
2550 {
2551 short clicked_button;
2552 char str[4];
2553 T_Gradient_array backup_gradients;
2554 int old_current_gradient;
2555 T_Scroller_button * mix_scroller;
2556 T_Scroller_button * speed_scroller;
2557 T_Scroller_button * gradient_scroller;
2558 short old_mouse_x;
2559 short old_mouse_y;
2560 byte old_mouse_k;
2561 byte temp_color;
2562 byte first_color;
2563 byte last_color;
2564 byte color;
2565 byte click;
2566 int changed_gradient_index;
2567 byte cycling_mode=Cycling_mode;
2568
2569 (void)btn;
2570 // Enable cycling while this window is open
2571 Cycling_mode=1;
2572
2573 Gradient_pixel=Pixel;
2574 old_current_gradient=Current_gradient;
2575 changed_gradient_index=0;
2576 memcpy(&backup_gradients,Main.backups->Pages->Gradients,sizeof(T_Gradient_array));
2577
2578 Open_window(235,146+12,"Gradation menu");
2579
2580 Window_set_palette_button(48,19); // 1
2581 // Slider for gradient selection
2582 gradient_scroller=Window_set_scroller_button(218,20,75,16,1,Current_gradient); // 2
2583 // Slider for mix
2584 mix_scroller = Window_set_scroller_button(31,20,84,256,1,
2585 Main.backups->Pages->Gradients->Range[Current_gradient].Mix); // 3
2586 // Direction
2587 Window_set_normal_button(8,20,15,14,
2588 (Main.backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",0,1,KEY_TAB); // 4
2589 // Technique
2590 Window_set_normal_button(8,90,15,14,"",0,1,KEY_TAB|GFX2_MOD_SHIFT); // 5
2591 Draw_button_gradient_style(8,90,Main.backups->Pages->Gradients->Range[Current_gradient].Technique);
2592
2593 Window_set_normal_button(178,128+12,51,14,"OK",0,1,KEY_RETURN); // 6
2594 Window_set_normal_button(123,128+12,51,14,"Cancel",0,1,KEY_ESC); // 7
2595 // Scrolling speed
2596 //((250/2 = 125)+1 = 126) +24 = 150
2597 speed_scroller = Window_set_horizontal_scroller_button(79, 111, 150, COLOR_CYCLING_SPEED_MAX + 1, 1,
2598 Main.backups->Pages->Gradients->Range[Current_gradient].Speed); // 8
2599 Print_color_cycling_details(113 + 14);
2600
2601 Print_in_window(5,58,"MIX",MC_Dark,MC_Light);
2602
2603 // Cycling mode on/off
2604 Window_set_normal_button(8,109,62,14,"",0,1,KEY_NONE); // 9
2605 Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
2606
2607 // On tagge les couleurs qui vont avec
2608 Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
2609
2610 Num2str(Current_gradient+1,str,2);
2611 Print_in_window(215,100,str,MC_Black,MC_Light);
2612
2613 // On affiche le cadre autour de la préview
2614 Window_display_frame_in(7,127+12,110,16);
2615 // On affiche la preview
2616 Draw_gradient_preview(8,128+12,108,14,Current_gradient);
2617
2618 first_color=last_color=(Main.backups->Pages->Gradients->Range[Current_gradient].Inverse)?Main.backups->Pages->Gradients->Range[Current_gradient].End:Main.backups->Pages->Gradients->Range[Current_gradient].Start;
2619 Update_window_area(0,0,Window_width, Window_height);
2620
2621 Display_cursor();
2622
2623 do
2624 {
2625 old_mouse_x=Mouse_X;
2626 old_mouse_y=Mouse_Y;
2627 old_mouse_k=Mouse_K;
2628 if (changed_gradient_index)
2629 {
2630 // User has changed which gradient (0-15) he's watching
2631 changed_gradient_index=0;
2632
2633 Hide_cursor();
2634
2635 // On affiche la valeur sous la jauge
2636 Num2str(Current_gradient+1,str,2);
2637 Print_in_window(215,100,str,MC_Black,MC_Light);
2638
2639 // On tagge les couleurs qui vont avec
2640 Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
2641
2642 // On affiche le sens qui va avec
2643 Print_in_window(12,23,(Main.backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light);
2644
2645 // On raffiche le mélange (jauge) qui va avec
2646 mix_scroller->Position=Main.backups->Pages->Gradients->Range[Current_gradient].Mix;
2647 Window_draw_slider(mix_scroller);
2648
2649 // Update speed
2650 speed_scroller->Position=Main.backups->Pages->Gradients->Range[Current_gradient].Speed;
2651 Window_draw_slider(speed_scroller);
2652 Print_color_cycling_details(113 + 14);
2653
2654 // Gradient #
2655 gradient_scroller->Position=Current_gradient;
2656 Window_draw_slider(gradient_scroller);
2657
2658 // Technique (flat, dithered, very dithered)
2659 Draw_button_gradient_style(8,90,Main.backups->Pages->Gradients->Range[Current_gradient].Technique);
2660
2661 // Rectangular gradient preview
2662 Draw_gradient_preview(8,128+12,108,14,Current_gradient);
2663
2664 Display_cursor();
2665 }
2666
2667 clicked_button=Window_clicked_button();
2668 if (Input_sticky_control!=8 || !Mouse_K)
2669 {
2670 Allow_colorcycling=0;
2671 // Restore palette
2672 Set_palette(Main.palette);
2673 }
2674
2675 switch(clicked_button)
2676 {
2677 case -1 :
2678 case 1 : // Palette
2679 if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) )
2680 {
2681 Hide_cursor();
2682 temp_color=(clicked_button==1) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y);
2683
2684 if (!old_mouse_k)
2685 {
2686 // On vient de clicker
2687
2688 // On met à jour l'intervalle du dégradé
2689 first_color=last_color=Main.backups->Pages->Gradients->Range[Current_gradient].Start=Main.backups->Pages->Gradients->Range[Current_gradient].End=temp_color;
2690 // On tagge le bloc
2691 Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
2692 // Tracé de la preview:
2693 Draw_gradient_preview(8,128+12,108,14,Current_gradient);
2694 }
2695 else
2696 {
2697 // On maintient le click, on va donc tester si le curseur bouge
2698 if (temp_color!=last_color)
2699 {
2700 // On commence par ordonner la 1ère et dernière couleur du bloc
2701 if (first_color<temp_color)
2702 {
2703 Main.backups->Pages->Gradients->Range[Current_gradient].Start=first_color;
2704 Main.backups->Pages->Gradients->Range[Current_gradient].End =temp_color;
2705 }
2706 else if (first_color>temp_color)
2707 {
2708 Main.backups->Pages->Gradients->Range[Current_gradient].Start=temp_color;
2709 Main.backups->Pages->Gradients->Range[Current_gradient].End =first_color;
2710 }
2711 else
2712 Main.backups->Pages->Gradients->Range[Current_gradient].Start=Main.backups->Pages->Gradients->Range[Current_gradient].End=first_color;
2713 // On tagge le bloc
2714 Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
2715 // Tracé de la preview:
2716 Draw_gradient_preview(8,128+12,108,14,Current_gradient);
2717 last_color=temp_color;
2718 }
2719 }
2720 Display_cursor();
2721 }
2722 break;
2723 case 2 : // Nouvel indice de dégradé
2724 // Nouvel indice dans Window_attribute2
2725 Current_gradient=Window_attribute2;
2726 changed_gradient_index=1;
2727 break;
2728 case 3 : // Nouveau mélange de dégradé
2729 Hide_cursor();
2730 // Nouvel mélange dans Window_attribute2
2731 Main.backups->Pages->Gradients->Range[Current_gradient].Mix=Window_attribute2;
2732 // On affiche la nouvelle preview
2733 Draw_gradient_preview(8,128+12,108,14,Current_gradient);
2734 Display_cursor();
2735 break;
2736 case 4 : // Changement de sens
2737 Hide_cursor();
2738 // On inverse le sens (par un XOR de 1)
2739 Main.backups->Pages->Gradients->Range[Current_gradient].Inverse^=1;
2740 Print_in_window(12,23,(Main.backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light);
2741 // On affiche la nouvelle preview
2742 Draw_gradient_preview(8,128+12,108,14,Current_gradient);
2743 Display_cursor();
2744 break;
2745 case 5 : // Changement de technique
2746 Hide_cursor();
2747 // On change la technique par (+1)%3
2748 Main.backups->Pages->Gradients->Range[Current_gradient].Technique=(Main.backups->Pages->Gradients->Range[Current_gradient].Technique+1)%3;
2749 Draw_button_gradient_style(8,90,Main.backups->Pages->Gradients->Range[Current_gradient].Technique);
2750 // On affiche la nouvelle preview
2751 Draw_gradient_preview(8,128+12,108,14,Current_gradient);
2752 Display_cursor();
2753 break;
2754 case 8 : // Speed
2755 Main.backups->Pages->Gradients->Range[Current_gradient].Speed=Window_attribute2;
2756 Hide_cursor();
2757 Print_color_cycling_details(113 + 14);
2758 Display_cursor();
2759 Allow_colorcycling=1;
2760 break;
2761 case 9: // Cycling on/off
2762 cycling_mode = !cycling_mode;
2763 Hide_cursor();
2764 Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
2765 Display_cursor();
2766 break;
2767 }
2768
2769 if (!Mouse_K)
2770 switch (Key)
2771 {
2772 case KEY_BACKQUOTE : // Récupération d'une couleur derrière le menu
2773 case KEY_COMMA :
2774 Get_color_behind_window(&color,&click);
2775 if (click)
2776 {
2777 Hide_cursor();
2778 temp_color=color;
2779
2780 // On met à jour l'intervalle du dégradé
2781 first_color=last_color=Main.backups->Pages->Gradients->Range[Current_gradient].Start=Main.backups->Pages->Gradients->Range[Current_gradient].End=temp_color;
2782 // On tagge le bloc
2783 Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
2784 // Tracé de la preview:
2785 Draw_gradient_preview(8,128+12,108,14,Current_gradient);
2786 Display_cursor();
2787 Wait_end_of_click();
2788 }
2789 Key=0;
2790 break;
2791 case KEY_MOUSEWHEELUP:
2792 if (Current_gradient>0)
2793 {
2794 Current_gradient--;
2795 changed_gradient_index=1;
2796 }
2797 break;
2798 case KEY_MOUSEWHEELDOWN:
2799 if (Current_gradient<15)
2800 {
2801 Current_gradient++;
2802 changed_gradient_index=1;
2803 }
2804 break;
2805
2806 default:
2807 if (Is_shortcut(Key,0x100+BUTTON_HELP))
2808 {
2809 Window_help(BUTTON_GRADRECT, NULL);
2810 Key=0;
2811 break;
2812 }
2813 else if (Is_shortcut(Key,0x200+BUTTON_GRADRECT))
2814 clicked_button=6;
2815 else if (Is_shortcut(Key,SPECIAL_CYCLE_MODE))
2816 {
2817 // Cycling on/off
2818 cycling_mode = !cycling_mode;
2819 Hide_cursor();
2820 Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
2821 Display_cursor();
2822 }
2823 }
2824 }
2825 while (clicked_button!=6 && clicked_button!=7 && !Quit_is_required);
2826
2827 Close_window();
2828 // The Grad rect operation uses the same button as Grad menu.
2829 if (Current_operation != OPERATION_GRAD_RECTANGLE)
2830 Unselect_button(BUTTON_GRADRECT);
2831
2832 Display_cursor();
2833
2834 Gradient_pixel=Display_pixel;
2835 Cycling_mode=cycling_mode;
2836 if (clicked_button==7) // Cancel
2837 {
2838 Current_gradient=old_current_gradient;
2839 memcpy(Main.backups->Pages->Gradients,&backup_gradients,sizeof(T_Gradient_array));
2840 }
2841 }
2842
2843
2844 // -- Gestion des boutons de cercle / ellipse / rectangle dégradés --------------------
2845
Button_Grad_rectangle(int btn)2846 void Button_Grad_rectangle(int btn)
2847 {
2848 (void)btn;
2849 Hide_cursor();
2850 Start_operation_stack(OPERATION_GRAD_RECTANGLE);
2851 Display_cursor();
2852 }
2853
2854
2855 // -- Gestion du bouton de remplissage ---------------------------------------
2856
Button_Fill(int btn)2857 void Button_Fill(int btn)
2858 {
2859 (void)btn;
2860 if (Current_operation!=OPERATION_FILL)
2861 {
2862 Hide_cursor();
2863
2864 if (Current_operation!=OPERATION_REPLACE)
2865 {
2866 Paintbrush_shape_before_fill=Paintbrush_shape;
2867 Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
2868 }
2869 else
2870 if ( (Mouse_Y<Menu_Y) && (Menu_is_visible) &&
2871 ( (!Main.magnifier_mode) || (Mouse_X<Main.separator_position) || (Mouse_X>=Main.X_zoom) ) )
2872 Print_in_menu("X: Y: ",0);
2873 Start_operation_stack(OPERATION_FILL);
2874 Display_cursor();
2875 }
2876 }
2877
2878
Button_Replace(int btn)2879 void Button_Replace(int btn)
2880 {
2881 (void)btn;
2882 if (Current_operation!=OPERATION_REPLACE)
2883 {
2884 Hide_cursor();
2885 if (Current_operation!=OPERATION_FILL)
2886 {
2887 Paintbrush_shape_before_fill=Paintbrush_shape;
2888 Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
2889 }
2890 if ( (Mouse_Y<Menu_Y) && (Menu_is_visible) &&
2891 ( (!Main.magnifier_mode) || (Mouse_X<Main.separator_position) || (Mouse_X>=Main.X_zoom) ) )
2892 Print_in_menu("X: Y: ( )",0);
2893 Start_operation_stack(OPERATION_REPLACE);
2894 Display_cursor();
2895 }
2896 }
2897
2898
Button_Unselect_fill(int btn)2899 void Button_Unselect_fill(int btn)
2900 {
2901 (void)btn;
2902 Paintbrush_shape=Paintbrush_shape_before_fill;
2903
2904 if (Current_operation==OPERATION_REPLACE)
2905 if ( (Mouse_Y<Menu_Y) && (Menu_is_visible) &&
2906 ( (!Main.magnifier_mode) || (Mouse_X<Main.separator_position) || (Mouse_X>=Main.X_zoom) ) )
2907 Print_in_menu("X: Y: ",0);
2908 }
2909
2910
2911 //---------------------------- Menu des pinceaux -----------------------------
2912
2913 /// Checks if the current brush is identical to a preset one.
Same_paintbrush(byte index)2914 byte Same_paintbrush(byte index)
2915 {
2916 if (Paintbrush_shape!=Paintbrush[index].Shape ||
2917 Paintbrush_width!=Paintbrush[index].Width ||
2918 Paintbrush_height!=Paintbrush[index].Height)
2919 return 0;
2920
2921 if (Paintbrush_shape==PAINTBRUSH_SHAPE_MISC)
2922 {
2923 // Check all pixels
2924 int x,y;
2925 for(y=0;y<Paintbrush_height;y++)
2926 for(x=0;x<Paintbrush_width;x++)
2927 if(Paintbrush_sprite[(y*MAX_PAINTBRUSH_SIZE)+x]!=Paintbrush[index].Sprite[y][x])
2928 return 0;
2929 }
2930 return 1;
2931 }
2932
Button_Paintbrush_menu(int btn)2933 void Button_Paintbrush_menu(int btn)
2934 {
2935 short clicked_button;
2936 short x_pos,y_pos;
2937 byte index;
2938
2939 Open_window(310,180,"Paintbrush menu");
2940
2941 Window_display_frame(8,21,294,132);
2942
2943 Window_set_normal_button(10,158,67,14,"Cancel",0,1,KEY_ESC); // 1
2944
2945 Window_set_dropdown_button(216, 158, 84,14,84,"Preset...", 0,0,1,RIGHT_SIDE|LEFT_SIDE,1);
2946 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_ROUND, "Round");
2947 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_SQUARE, "Square");
2948 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_HORIZONTAL_BAR,"Horizontal");
2949 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_VERTICAL_BAR, "Vertical");
2950 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_SLASH, "Slash");
2951 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_ANTISLASH, "Antislash");
2952 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_RANDOM, "Random");
2953 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_CROSS, "Cross");
2954 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_PLUS, "Plus");
2955 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_DIAMOND, "Diamond");
2956 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_SIEVE_ROUND, "Sieve Rnd");
2957 Window_dropdown_add_item(Window_dropdown_button_list,PAINTBRUSH_SHAPE_SIEVE_SQUARE, "Sieve Sqr");
2958
2959 for (index=0; index<NB_PAINTBRUSH_SPRITES; index++)
2960 {
2961 x_pos=13+(index%12)*24;
2962 y_pos=27+(index/12)*25;
2963 //Window_set_normal_button(x_pos ,y_pos ,20,20,"",0,1,KEY_NONE);
2964 Window_set_dropdown_button(x_pos ,y_pos ,20,20,28,NULL, 0,0,0,RIGHT_SIDE,0);
2965 Window_dropdown_add_item(Window_dropdown_button_list, 1, "Set");
2966 // Highlight selected brush
2967 if (Same_paintbrush(index))
2968 Window_rectangle(x_pos,y_pos,20,20,MC_White);
2969
2970 Display_paintbrush_in_window(x_pos+2,y_pos+2,index);
2971 }
2972 for (index=0; index<BRUSH_CONTAINER_COLUMNS*BRUSH_CONTAINER_ROWS; index++)
2973 {
2974 x_pos=13+((index+NB_PAINTBRUSH_SPRITES)%12)*24;
2975 y_pos=27+((index+NB_PAINTBRUSH_SPRITES)/12)*25;
2976 Window_set_dropdown_button(x_pos ,y_pos ,20,20,28,NULL, 0,0,0,RIGHT_SIDE,0);
2977 Window_dropdown_add_item(Window_dropdown_button_list, 1, "Set");
2978 Display_stored_brush_in_window(x_pos+2, y_pos+2, index);
2979 }
2980
2981 Update_window_area(0,0,Window_width, Window_height);
2982
2983 Display_cursor();
2984
2985 do
2986 {
2987 clicked_button=Window_clicked_button();
2988 if (Is_shortcut(Key,0x100+BUTTON_HELP))
2989 Window_help(BUTTON_PAINTBRUSHES, NULL);
2990 // Brush container
2991 if (clicked_button>=(NB_PAINTBRUSH_SPRITES+3))
2992 {
2993 index = clicked_button-NB_PAINTBRUSH_SPRITES-3;
2994
2995 if (Window_attribute2==1) // Set
2996 {
2997 // Store
2998
2999 x_pos=13+((index+NB_PAINTBRUSH_SPRITES)%12)*24;
3000 y_pos=27+((index+NB_PAINTBRUSH_SPRITES)/12)*25;
3001
3002 Store_brush(index);
3003 Hide_cursor();
3004 Display_stored_brush_in_window(x_pos+2, y_pos+2, index);
3005 Display_cursor();
3006 }
3007 else
3008 {
3009 // Restore and exit
3010
3011 if (Restore_brush(index))
3012 {
3013 Close_window();
3014 break;
3015 }
3016 }
3017
3018 }
3019 else if (clicked_button>=3)
3020 // Standard paintbrushes
3021 {
3022 if (Window_attribute2!=1)
3023 {
3024 // Select paintbrush
3025 Close_window();
3026 Select_paintbrush(clicked_button-3);
3027 break;
3028 }
3029 else if (Window_attribute2==1)
3030 {
3031 // Store current
3032 index=clicked_button-3;
3033 if (!Store_paintbrush(index))
3034 {
3035 // Redraw
3036 Hide_cursor();
3037 x_pos=13+(index%12)*24;
3038 y_pos=27+(index/12)*25;
3039 Window_rectangle(x_pos,y_pos,20,20,MC_White);
3040 Display_paintbrush_in_window(x_pos+2,y_pos+2,index);
3041 Display_cursor();
3042 }
3043 }
3044 }
3045 else if (clicked_button==1 || Is_shortcut(Key,0x100+BUTTON_PAINTBRUSHES))
3046 {
3047 Close_window();
3048 break;
3049 }
3050 else if (clicked_button==2)
3051 {
3052 int size;
3053 // Pick a standard shape
3054 Paintbrush_shape=Window_attribute2;
3055 // Assign a reasonable size
3056 size=Max(Paintbrush_width,Paintbrush_height);
3057 if (size==1)
3058 size=3;
3059
3060 switch (Paintbrush_shape)
3061 {
3062 case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
3063 Set_paintbrush_size(size, 1);
3064 break;
3065 case PAINTBRUSH_SHAPE_VERTICAL_BAR:
3066 Set_paintbrush_size(1, size);
3067 break;
3068 case PAINTBRUSH_SHAPE_CROSS:
3069 case PAINTBRUSH_SHAPE_PLUS:
3070 case PAINTBRUSH_SHAPE_DIAMOND:
3071 Set_paintbrush_size(size|1,size|1);
3072 break;
3073 default:
3074 Set_paintbrush_size(size,size);
3075 break;
3076
3077 }
3078 Close_window();
3079 Change_paintbrush_shape(Paintbrush_shape);
3080 break;
3081 }
3082 }
3083 while (1);
3084
3085 Unselect_button(btn);
3086 Display_cursor();
3087 }
3088
3089
Button_Brush_monochrome(int btn)3090 void Button_Brush_monochrome(int btn)
3091 {
3092 Hide_cursor();
3093 // On passe en brosse monochrome:
3094 Change_paintbrush_shape(PAINTBRUSH_SHAPE_MONO_BRUSH);
3095
3096 Unselect_button(btn);
3097
3098 Display_cursor();
3099 }
3100
3101 // -- Fonction renvoyant le mode vidéo le plus adapté à l'image chargée -----
3102 #define TOLERANCE_X 8
3103 #define TOLERANCE_Y 4
Best_video_mode(void)3104 static int Best_video_mode(void)
3105 {
3106 short best_width,best_height;
3107 int best_mode;
3108 short temp_x,temp_y;
3109 int mode;
3110
3111 // Si mode fenêtre, on reste dans ce mode.
3112 if (Current_resolution == 0)
3113 return 0;
3114
3115 // On commence par borner les dimensions, ou du moins les rendre cohérentes
3116 if ((Original_screen_X<=0) || (Config.Set_resolution_according_to==2))
3117 Original_screen_X=Main.image_width;
3118 else
3119 if (Original_screen_X<320)
3120 Original_screen_X=320;
3121
3122 if ((Original_screen_Y<=0) || (Config.Set_resolution_according_to==2))
3123 Original_screen_Y=Main.image_height;
3124 else
3125 if (Original_screen_Y<200)
3126 Original_screen_Y=200;
3127
3128 GFX2_Log(GFX2_DEBUG, "Best_video_mode() looking for %dx%d\n", (int)Original_screen_X, (int)Original_screen_Y);
3129
3130 if ((Original_screen_X > Video_mode[Nb_video_modes-1].Width) ||
3131 (Original_screen_Y > Video_mode[Nb_video_modes-1].Height))
3132 {
3133 // return the "biggest" video mode
3134 return Nb_video_modes-1;
3135 }
3136
3137 // Maintenant on peut chercher le mode qui correspond le mieux
3138 best_mode=Current_resolution;
3139 best_width=0;
3140 best_height=0;
3141
3142
3143 for (mode=1; mode<Nb_video_modes; mode++)
3144 {
3145 if (Video_mode[mode].Fullscreen && (Video_mode[mode].State&3)<2)
3146 {
3147 temp_x=Video_mode[mode].Width;
3148 temp_y=Video_mode[mode].Height;
3149
3150 if ( (Original_screen_X-TOLERANCE_X<=temp_x)
3151 && (Original_screen_Y-TOLERANCE_Y<=temp_y) )
3152 return mode;
3153 else
3154 {
3155 if ( (best_width<=temp_x)
3156 && (best_height<=temp_y)
3157 && (temp_x-TOLERANCE_X<=Original_screen_X)
3158 && (temp_y-TOLERANCE_Y<=Original_screen_Y) )
3159 {
3160 best_width=temp_x;
3161 best_height=temp_y;
3162 best_mode=mode;
3163 }
3164 }
3165 }
3166 }
3167
3168 return best_mode;
3169 }
3170
Load_picture(enum CONTEXT_TYPE type)3171 void Load_picture(enum CONTEXT_TYPE type)
3172 {
3173 byte confirm;
3174 byte old_cursor_shape;
3175 int new_mode;
3176 T_IO_Context context;
3177 word * filename_unicode = NULL;
3178 T_Selector_settings * selector;
3179
3180 switch (type)
3181 {
3182 case CONTEXT_MAIN_IMAGE:
3183 filename_unicode = Main.backups->Pages->Filename_unicode;
3184 Init_context_layered_image(&context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
3185 selector = &Main.selector;
3186 break;
3187 case CONTEXT_BRUSH:
3188 filename_unicode = Brush_filename_unicode;
3189 Init_context_brush(&context, Brush_filename, Brush_file_directory);
3190 selector = &Brush_selector;
3191 break;
3192 case CONTEXT_PALETTE:
3193 Init_context_layered_image(&context, "", Main.backups->Pages->File_directory);
3194 context.Type = CONTEXT_PALETTE;
3195 context.Format = FORMAT_PAL;
3196 selector = &Palette_selector;
3197 break;
3198 default:
3199 return; // DO NOTHING
3200 }
3201 context.File_name_unicode = Unicode_strdup(filename_unicode);
3202 confirm = Button_Load_or_Save(selector, 1, &context);
3203
3204 if (confirm)
3205 {
3206 if (type==CONTEXT_MAIN_IMAGE)
3207 {
3208 if (Main.image_is_modified)
3209 confirm=Confirmation_box("Discard unsaved changes?");
3210 }
3211 }
3212
3213 // confirm is modified inside the first if, that's why we check it
3214 // again here
3215 if (confirm)
3216 {
3217 short old_image_width, old_image_height;
3218
3219 old_image_width = Main.image_width;
3220 old_image_height = Main.image_height;
3221 old_cursor_shape=Cursor_shape;
3222 Hide_cursor();
3223 Cursor_shape=CURSOR_SHAPE_HOURGLASS;
3224 Display_cursor();
3225
3226 if (type==CONTEXT_MAIN_IMAGE)
3227 {
3228 Original_screen_X=0;
3229 Original_screen_Y=0;
3230 }
3231
3232 Load_image(&context);
3233
3234 if (type==CONTEXT_BRUSH)
3235 {
3236 free(Brush_filename);
3237 Brush_filename = context.File_name; // "steal" heap string
3238 context.File_name = NULL;
3239 free(Brush_filename_unicode);
3240 Brush_filename_unicode = context.File_name_unicode; // "steal" heap string
3241 context.File_name_unicode = NULL;
3242 free(Brush_file_directory);
3243 Brush_file_directory = context.File_directory; // "steal" heap string
3244 context.File_directory = NULL;
3245 Brush_fileformat = context.Format;
3246
3247 Tiling_offset_X=0;
3248 Tiling_offset_Y=0;
3249
3250 Brush_offset_X=(Brush_width>>1);
3251 Brush_offset_Y=(Brush_height>>1);
3252
3253 Select_button(BUTTON_DRAW,LEFT_SIDE);
3254 if (Config.Auto_discontinuous)
3255 {
3256 // On se place en mode Dessin discontinu à la main
3257 while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
3258 Select_button(BUTTON_DRAW,RIGHT_SIDE);
3259 }
3260 Hide_cursor();
3261 // On passe en brosse couleur:
3262 Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
3263 }
3264 else
3265 {
3266 Hide_cursor();
3267 Cursor_shape=old_cursor_shape;
3268 }
3269
3270
3271 if ( (File_error==1) || (Get_fileformat(Main.fileformat)->Palette_only) )
3272 {
3273 if (File_error!=1)
3274 Compute_optimal_menu_colors(Main.palette);
3275 }
3276 else
3277 {
3278 if (type==CONTEXT_MAIN_IMAGE)
3279 {
3280 if (Main.magnifier_mode &&
3281 (Main.image_width > old_image_width || Main.image_height > old_image_height))
3282 {
3283 // disable magnifier
3284 Pixel_preview = Pixel_preview_normal;
3285 Main.magnifier_mode = 0;
3286 Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
3287 }
3288
3289 new_mode=Best_video_mode();
3290 if ((Config.Auto_set_res) && (new_mode!=Current_resolution))
3291 {
3292 Init_mode_video(
3293 Video_mode[new_mode].Width,
3294 Video_mode[new_mode].Height,
3295 Video_mode[new_mode].Fullscreen,
3296 Pixel_ratio);
3297 Display_menu();
3298 }
3299 // In window mode, activate wide or tall pixels if the image says so.
3300 else if (!Video_mode[Current_resolution].Fullscreen &&
3301 ((context.Ratio == PIXEL_WIDE &&
3302 Pixel_ratio != PIXEL_WIDE && Pixel_ratio != PIXEL_WIDE2) ||
3303 (context.Ratio == PIXEL_TALL &&
3304 Pixel_ratio != PIXEL_TALL && Pixel_ratio != PIXEL_TALL2) ||
3305 (context.Ratio == PIXEL_TALL3 &&
3306 Pixel_ratio != PIXEL_TALL3) ))
3307 {
3308 Init_mode_video(
3309 Video_mode[Current_resolution].Width,
3310 Video_mode[Current_resolution].Height,
3311 Video_mode[Current_resolution].Fullscreen,
3312 context.Ratio);
3313 Display_menu();
3314 }
3315 else
3316 {
3317 if (Main.image_width > old_image_width || Main.image_height > old_image_height)
3318 {
3319 Main.offset_X = 0;
3320 Main.offset_Y = 0;
3321 }
3322 Compute_limits();
3323 Compute_paintbrush_coordinates();
3324 }
3325
3326 Compute_optimal_menu_colors(Main.palette);
3327 Redraw_layered_image();
3328 End_of_modification();
3329 Check_menu_mode();
3330 Display_all_screen();
3331 Main.image_is_modified=0;
3332 }
3333 }
3334
3335 Display_menu();
3336 Display_cursor();
3337 }
3338
3339 Destroy_context(&context);
3340
3341 Hide_cursor();
3342 Print_filename();
3343 Display_cursor();
3344 Set_palette(Main.palette);
3345 }
3346
3347
Button_Load(int btn)3348 void Button_Load(int btn)
3349 {
3350 (void)btn;
3351 // On sauve l'état actuel des paramètres de l'image pour pouvoir les
3352 // restituer en cas d'erreur n'affectant pas l'image
3353 Upload_infos_page(&Main);
3354
3355 Load_picture(CONTEXT_MAIN_IMAGE);
3356 Tilemap_update();
3357 }
3358
3359
Button_Reload(int btn)3360 void Button_Reload(int btn)
3361 {
3362 byte old_cursor_shape;
3363 int new_mode;
3364
3365 (void)btn;
3366 // On sauve l'état actuel des paramètres de l'image pour pouvoir les
3367 // restituer en cas d'erreur n'affectant pas l'image
3368 Upload_infos_page(&Main);
3369
3370 if ( (!Main.image_is_modified) || Confirmation_box("Discard unsaved changes ?") )
3371 {
3372 T_IO_Context context;
3373
3374 Hide_cursor();
3375 old_cursor_shape=Cursor_shape;
3376 Cursor_shape=CURSOR_SHAPE_HOURGLASS;
3377 Display_cursor();
3378
3379 Original_screen_X=0;
3380 Original_screen_Y=0;
3381
3382 Init_context_layered_image(&context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
3383 Load_image(&context);
3384
3385 Hide_cursor();
3386 Cursor_shape=old_cursor_shape;
3387
3388 if (File_error!=1)
3389 {
3390 if (Main.magnifier_mode)
3391 {
3392 Pixel_preview=Pixel_preview_normal;
3393 Main.magnifier_mode=0;
3394 Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
3395 }
3396
3397 new_mode=Best_video_mode();
3398 if ( ((Config.Auto_set_res) && (new_mode!=Current_resolution)) &&
3399 (!Resolution_in_command_line) )
3400 {
3401 Init_mode_video(
3402 Video_mode[new_mode].Width,
3403 Video_mode[new_mode].Height,
3404 Video_mode[new_mode].Fullscreen,
3405 Pixel_ratio);
3406 Display_menu();
3407 }
3408 // In window mode, activate wide or tall pixels if the image says so.
3409 else if (!Video_mode[Current_resolution].Fullscreen &&
3410 ((context.Ratio == PIXEL_WIDE &&
3411 Pixel_ratio != PIXEL_WIDE && Pixel_ratio != PIXEL_WIDE2) ||
3412 (context.Ratio == PIXEL_TALL &&
3413 Pixel_ratio != PIXEL_TALL && Pixel_ratio != PIXEL_TALL2 &&
3414 Pixel_ratio != PIXEL_TALL3)))
3415 {
3416 Init_mode_video(
3417 Video_mode[Current_resolution].Width,
3418 Video_mode[Current_resolution].Height,
3419 Video_mode[Current_resolution].Fullscreen,
3420 context.Ratio);
3421 Display_menu();
3422 }
3423 else
3424 {
3425 Main.offset_X=0;
3426 Main.offset_Y=0;
3427 Compute_limits();
3428 Compute_paintbrush_coordinates();
3429 }
3430 Tilemap_update();
3431 Redraw_layered_image();
3432 End_of_modification();
3433 Check_menu_mode();
3434 Display_all_screen();
3435
3436 Main.image_is_modified=0;
3437 }
3438 Destroy_context(&context);
3439 }
3440 else
3441 Hide_cursor();
3442
3443 Compute_optimal_menu_colors(Main.palette);
3444 Display_menu();
3445 if (Config.Display_image_limits)
3446 Display_image_limits();
3447
3448 Unselect_button(BUTTON_LOAD);
3449
3450 Display_cursor();
3451 }
3452
3453
Backup_existing_file(const char * filename)3454 static void Backup_existing_file(const char * filename)
3455 {
3456 char * new_filename; // full filename of the backup file
3457 char * p;
3458 int i;
3459 size_t len;
3460
3461 if (filename == NULL)
3462 return;
3463 len = strlen(filename);
3464 new_filename = malloc(len + 1 + 4); // spare bytes to concat ".BAK"
3465 memcpy(new_filename, filename, len + 1);
3466 p = Find_last_separator(new_filename); // pointer to the filename part (after directory)
3467 if (p == NULL)
3468 p = new_filename;
3469 else
3470 p++;
3471 i = Position_last_dot(p);
3472 if (i >= 0)
3473 memcpy(p + i + 1, "BAK", 4);
3474 else
3475 memcpy(new_filename + len, ".BAK", 5);
3476
3477 File_error=0;
3478
3479 // On fait un backup si le nom du fichier n'est pas celui qu'on a choisi
3480 // pour nommer les backups (c'est évident!).
3481 if (strcmp(new_filename,filename))
3482 {
3483 // S'il y avait déjà un fichier Backup, on l'efface
3484 if ((File_exists(new_filename))
3485 && (Remove_path(new_filename)!=0))
3486 File_error=1;
3487
3488 if ((!File_error)
3489 && (rename(filename,new_filename)!=0))
3490 File_error=1;
3491 }
3492 free(new_filename);
3493 }
3494
3495
Save_picture(enum CONTEXT_TYPE type)3496 void Save_picture(enum CONTEXT_TYPE type)
3497 {
3498 byte confirm;
3499 byte old_cursor_shape;
3500 T_IO_Context save_context;
3501 word * filename_unicode = NULL;
3502 T_Selector_settings * selector;
3503
3504 if (type == CONTEXT_MAIN_IMAGE)
3505 {
3506 filename_unicode = Main.backups->Pages->Filename_unicode;
3507 Init_context_layered_image(&save_context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
3508 save_context.Format = Main.fileformat;
3509 selector = &Main.selector;
3510 }
3511 else if (type == CONTEXT_BRUSH)
3512 {
3513 filename_unicode = Brush_filename_unicode;
3514 Init_context_brush(&save_context, Brush_filename, Brush_file_directory);
3515 save_context.Format = Brush_fileformat;
3516 selector = &Brush_selector;
3517 }
3518 else if (type == CONTEXT_PALETTE)
3519 {
3520 char* pal_filename;
3521 char* dotpos;
3522 size_t len = strlen(Main.backups->Pages->Filename);
3523
3524 pal_filename = malloc(len + 4 + 1); // reserve space for ".pal"
3525 memcpy(pal_filename, Main.backups->Pages->Filename, len + 1);
3526 // Replace extension with PAL
3527 dotpos = strrchr(pal_filename, '.');
3528 if (dotpos == NULL)
3529 dotpos = pal_filename + len;
3530 strcpy(dotpos, ".pal");
3531
3532 Init_context_layered_image(&save_context, pal_filename, Main.backups->Pages->File_directory);
3533 save_context.Type = CONTEXT_PALETTE;
3534
3535 free(pal_filename);
3536
3537 // Set format to PAL
3538 save_context.Format = FORMAT_PAL;
3539 selector = &Palette_selector;
3540 }
3541 else
3542 return;
3543
3544 save_context.File_name_unicode = Unicode_strdup(filename_unicode);
3545 confirm=Button_Load_or_Save(selector, 0, &save_context);
3546
3547 if (confirm && File_exists(save_context.File_name))
3548 {
3549 confirm=Confirmation_box("Erase old file ?");
3550 if (confirm && (Config.Backup))
3551 {
3552 char * full_filename = Filepath_append_to_dir(save_context.File_directory, save_context.File_name);
3553 Backup_existing_file(full_filename);
3554 free(full_filename);
3555 if (File_error)
3556 {
3557 confirm=0;
3558 Error(0);
3559 }
3560 }
3561 }
3562
3563 if (confirm)
3564 {
3565 const T_Format * format;
3566
3567 old_cursor_shape=Cursor_shape;
3568 Hide_cursor();
3569 Cursor_shape=CURSOR_SHAPE_HOURGLASS;
3570 Display_cursor();
3571
3572 Save_image(&save_context);
3573
3574 format=Get_fileformat(save_context.Format);
3575 if (!File_error && type == CONTEXT_MAIN_IMAGE && !format->Palette_only && (Main.backups->Pages->Nb_layers==1 || format->Supports_layers))
3576 {
3577 Main.image_is_modified = 0;
3578 Main.fileformat = save_context.Format;
3579 free(Main.backups->Pages->Filename);
3580 Main.backups->Pages->Filename = save_context.File_name; // "steal" string from heap
3581 save_context.File_name = NULL;
3582 free(Main.backups->Pages->Filename_unicode);
3583 Main.backups->Pages->Filename_unicode = save_context.File_name_unicode; // "steal" string
3584 save_context.File_name_unicode = NULL;
3585 free(Main.backups->Pages->File_directory);
3586 Main.backups->Pages->File_directory = save_context.File_directory;
3587 save_context.File_directory = NULL;
3588 }
3589 if (type == CONTEXT_BRUSH)
3590 {
3591 Brush_fileformat = save_context.Format;
3592 free(Brush_filename);
3593 Brush_filename = save_context.File_name;
3594 save_context.File_name = NULL;
3595 free(Brush_filename_unicode);
3596 Brush_filename_unicode = save_context.File_name_unicode;
3597 save_context.File_name_unicode = NULL;
3598 free(Brush_file_directory);
3599 Brush_file_directory = save_context.File_directory;
3600 save_context.File_directory = NULL;
3601 }
3602 Hide_cursor();
3603 Cursor_shape=old_cursor_shape;
3604 Display_cursor();
3605 }
3606 Destroy_context(&save_context);
3607
3608 Print_filename();
3609 Set_palette(Main.palette);
3610 }
3611
3612
Button_Save(int btn)3613 void Button_Save(int btn)
3614 {
3615 (void)btn;
3616 Save_picture(CONTEXT_MAIN_IMAGE);
3617 }
3618
3619 /// Save main image over existing file (no fileselector)
Button_Autosave(int btn)3620 void Button_Autosave(int btn)
3621 {
3622 byte old_cursor_shape;
3623 char * filename;
3624 byte file_already_exists;
3625
3626 (void)btn;
3627 filename = Filepath_append_to_dir(Main.backups->Pages->File_directory, Main.backups->Pages->Filename);
3628 file_already_exists = File_exists(filename);
3629
3630 if ( (!file_already_exists) || Confirmation_box("Erase old file ?") )
3631 {
3632 if ((file_already_exists) && (Config.Backup))
3633 Backup_existing_file(filename);
3634 else
3635 File_error=0;
3636
3637 Hide_cursor();
3638
3639 if (!File_error)
3640 {
3641 T_IO_Context save_context;
3642
3643 old_cursor_shape=Cursor_shape;
3644 Cursor_shape=CURSOR_SHAPE_HOURGLASS;
3645 Display_cursor();
3646
3647 Init_context_layered_image(&save_context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
3648 save_context.File_name_unicode = Unicode_strdup(Main.backups->Pages->Filename_unicode);
3649 Save_image(&save_context);
3650 if (!File_error)
3651 {
3652 Main.image_is_modified=0;
3653 }
3654 Destroy_context(&save_context);
3655
3656 Hide_cursor();
3657 Cursor_shape=old_cursor_shape;
3658 }
3659 else
3660 Error(0);
3661 }
3662 else
3663 Hide_cursor();
3664
3665 free(filename);
3666 Unselect_button(BUTTON_SAVE);
3667
3668 Display_cursor();
3669 }
3670
3671
3672 // -- Gestion des boutons de ligne ------------------------------------------
3673
Button_Lines(int btn)3674 void Button_Lines(int btn)
3675 {
3676 (void)btn;
3677 Hide_cursor();
3678 Start_operation_stack(Selected_line_mode);
3679 Display_cursor();
3680 }
3681
3682
Button_Lines_switch_mode(int btn)3683 void Button_Lines_switch_mode(int btn)
3684 {
3685 char icon;
3686
3687 if (Selected_line_mode==OPERATION_LINE)
3688 {
3689 Selected_line_mode=OPERATION_K_LINE;
3690 icon=MENU_SPRITE_K_LINE;
3691 }
3692 else if (Selected_line_mode==OPERATION_K_LINE)
3693 {
3694 Selected_line_mode=OPERATION_CENTERED_LINES;
3695 icon=MENU_SPRITE_CENTERED_LINES;
3696 }
3697 else
3698 {
3699 Selected_line_mode=OPERATION_LINE;
3700 icon=-1;
3701 }
3702
3703 Hide_cursor();
3704 Display_sprite_in_menu(btn,icon);
3705 Draw_menu_button(btn,BUTTON_PRESSED);
3706 Start_operation_stack(Selected_line_mode);
3707 Display_cursor();
3708 }
3709
3710
3711 // -- Button de brosse ------------------------------------------------------
3712
Button_Brush(int btn)3713 void Button_Brush(int btn)
3714 {
3715 Hide_cursor();
3716
3717 if (Current_operation!=OPERATION_GRAB_BRUSH)
3718 Start_operation_stack(OPERATION_GRAB_BRUSH);
3719 else
3720 Unselect_button(btn);
3721
3722 Display_cursor();
3723 }
3724
3725
Button_Unselect_brush(int btn)3726 void Button_Unselect_brush(int btn)
3727 {
3728 (void)btn;
3729 // On fait de notre mieux pour restaurer l'ancienne opération:
3730 Start_operation_stack(Operation_before_interrupt);
3731 }
3732
3733
Button_Restore_brush(int btn)3734 void Button_Restore_brush(int btn)
3735 {
3736 Hide_cursor();
3737 // On passe en brosse couleur:
3738 Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
3739
3740 Unselect_button(btn);
3741
3742 Display_cursor();
3743 }
3744
3745
3746 // -- Button de prise de brosse au lasso ------------------------------------
3747
Button_Lasso(int btn)3748 void Button_Lasso(int btn)
3749 {
3750 Hide_cursor();
3751
3752 if (Current_operation!=OPERATION_POLYBRUSH)
3753 {
3754 Paintbrush_shape_before_lasso=Paintbrush_shape;
3755 Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
3756 Start_operation_stack(OPERATION_POLYBRUSH);
3757 }
3758 else
3759 Unselect_button(btn);
3760
3761 Display_cursor();
3762 }
3763
3764
Button_Unselect_lasso(int btn)3765 void Button_Unselect_lasso(int btn)
3766 {
3767 (void)btn;
3768
3769 // If we aren't in OPERATION_POLYBRUSH, then we didn't save a brush shape,
3770 // and we shouldn't try to restore it.
3771 if (Current_operation==OPERATION_POLYBRUSH)
3772 Paintbrush_shape=Paintbrush_shape_before_lasso;
3773
3774 // On fait de notre mieux pour restaurer l'ancienne opération:
3775 Start_operation_stack(Operation_before_interrupt);
3776 }
3777
3778
3779 // -- Button de pipette -----------------------------------------------------
3780
Button_Colorpicker(int btn)3781 void Button_Colorpicker(int btn)
3782 {
3783 Hide_cursor();
3784
3785 if (Current_operation!=OPERATION_COLORPICK)
3786 {
3787 Colorpicker_color=-1;
3788 Start_operation_stack(OPERATION_COLORPICK);
3789 Paintbrush_shape_before_colorpicker=Paintbrush_shape;
3790 Paintbrush_shape=PAINTBRUSH_SHAPE_NONE;
3791 if (Operation_before_interrupt!=OPERATION_REPLACE)
3792 if ( (Mouse_Y<Menu_Y) && (Menu_is_visible) &&
3793 ( (!Main.magnifier_mode) || (Mouse_X<Main.separator_position) || (Mouse_X>=Main.X_zoom) ) )
3794 Print_in_menu("X: Y: ( )",0);
3795 }
3796 else
3797 Unselect_button(btn);
3798
3799 Display_cursor();
3800 }
3801
3802
Button_Unselect_colorpicker(int btn)3803 void Button_Unselect_colorpicker(int btn)
3804 {
3805 (void)btn;
3806 // Erase the color block which shows the picked color
3807 if (Operation_before_interrupt!=OPERATION_REPLACE)
3808 if ( (Mouse_Y<Menu_Y) && (Menu_is_visible) &&
3809 ( (!Main.magnifier_mode) || (Mouse_X<Main.separator_position) || (Mouse_X>=Main.X_zoom) ) )
3810 Print_in_menu("X: Y: ",0);
3811
3812 // On fait de notre mieux pour restaurer l'ancienne opération:
3813 if (Current_operation==OPERATION_COLORPICK)
3814 {
3815 Start_operation_stack(Operation_before_interrupt);
3816 Paintbrush_shape=Paintbrush_shape_before_colorpicker;
3817 }
3818 }
3819
3820
3821 // -- Inversion de la couleur Fore et de la couleur Back --
Button_Invert_foreback(int btn)3822 void Button_Invert_foreback(int btn)
3823 {
3824 byte temp_color;
3825
3826 temp_color=Fore_color;
3827 Fore_color =Back_color;
3828 Back_color =temp_color;
3829
3830 Hide_cursor();
3831 Frame_menu_color(Back_color);
3832 Frame_menu_color(Fore_color);
3833 Reposition_palette();
3834 Display_foreback();
3835 Unselect_button(btn);
3836 Display_cursor();
3837 }
3838
3839
3840 // -- Gestion du bouton Loupe -----------------------------------------------
3841
3842 byte Coming_from_zoom_factor_menu=0;
3843
Button_Magnify(int btn)3844 void Button_Magnify(int btn)
3845 {
3846 Hide_cursor();
3847 if ( (Current_operation==OPERATION_MAGNIFY) || (Main.magnifier_mode) )
3848 {
3849 Unselect_button(btn);
3850 }
3851 else
3852 {
3853 Compute_magnifier_data();
3854 if ((!Config.Fast_zoom) || (Mouse_Y>=Menu_Y) || Coming_from_zoom_factor_menu)
3855 {
3856 Coming_from_zoom_factor_menu=0;
3857 Start_operation_stack(OPERATION_MAGNIFY);
3858 }
3859 else
3860 { /* Ceci est de la duplication de code de presque toute l'opération de */
3861 /* la loupe... Il serait peut-être plus propre de faire une procédure */
3862 /* qui s'en charge... */
3863 // On passe en mode loupe
3864 Main.magnifier_mode=1;
3865
3866 // La fonction d'affichage dans la partie image est désormais un affichage
3867 // spécial loupe.
3868 Pixel_preview=Pixel_preview_magnifier;
3869
3870 // On calcule l'origine de la loupe
3871 Main.magnifier_offset_X=Mouse_X-(Main.magnifier_width>>1);
3872 Main.magnifier_offset_Y=Mouse_Y-(Main.magnifier_height>>1);
3873
3874 // Calcul des coordonnées absolues de ce coin DANS L'IMAGE
3875 Main.magnifier_offset_X+=Main.offset_X;
3876 Main.magnifier_offset_Y+=Main.offset_Y;
3877
3878 Clip_magnifier_offsets(&Main.magnifier_offset_X, &Main.magnifier_offset_Y);
3879
3880 // On calcule les bornes visibles dans l'écran
3881 Position_screen_according_to_zoom();
3882 Compute_limits();
3883 Display_all_screen();
3884
3885 // Repositionner le curseur en fonction des coordonnées visibles
3886 Compute_paintbrush_coordinates();
3887 }
3888 }
3889 Display_cursor();
3890 Update_rect(0,0,0,0);
3891 }
3892
Button_Magnify_menu(int btn)3893 void Button_Magnify_menu(int btn)
3894 {
3895 T_Dropdown_button dropdown;
3896 T_Dropdown_choice *item;
3897 int i;
3898 static const char * text[NB_ZOOM_FACTORS] =
3899 {"x2", "x3", "x4", "x5", "x6", "x8", "x10", "x12", "x14", "x16", "x18", "x20",
3900 "x24", "x28", "x32"};
3901
3902 (void)btn;
3903 Hide_cursor();
3904
3905 dropdown.Pos_X =Buttons_Pool[BUTTON_MAGNIFIER].X_offset;
3906 dropdown.Pos_Y =Buttons_Pool[BUTTON_MAGNIFIER].Y_offset;
3907 dropdown.Height =Buttons_Pool[BUTTON_MAGNIFIER].Height;
3908 dropdown.Dropdown_width=28;
3909 dropdown.First_item =NULL;
3910 dropdown.Bottom_up =1;
3911
3912 for(i = 0; i < NB_ZOOM_FACTORS; i++) {
3913 Window_dropdown_add_item(&dropdown, i, text[i]);
3914 }
3915
3916 item=Dropdown_activate(&dropdown,0,Menu_Y);
3917
3918 if (item)
3919 {
3920 Change_magnifier_factor(item->Number,0);
3921 }
3922
3923 if ( (!item) && (!Main.magnifier_mode) && (Current_operation!=OPERATION_MAGNIFY) ) // Cancel
3924 Unselect_button(BUTTON_MAGNIFIER);
3925
3926 Display_all_screen();
3927 Display_cursor();
3928 Update_rect(Main.separator_position,0,Screen_width-Main.separator_position,Menu_Y);
3929
3930 if ( (item) && (!Main.magnifier_mode) && (Current_operation!=OPERATION_MAGNIFY) ) // Passage en mode zoom
3931 {
3932 Coming_from_zoom_factor_menu=1;
3933 Select_button(BUTTON_MAGNIFIER,LEFT_SIDE);
3934 }
3935
3936 Window_dropdown_clear_items(&dropdown);
3937 }
3938
Button_Unselect_magnifier(int btn)3939 void Button_Unselect_magnifier(int btn)
3940 {
3941 (void)btn;
3942 if (Main.magnifier_mode)
3943 {
3944 // On sort du mode loupe
3945 Main.magnifier_mode=0;
3946
3947
3948 // --> Recalculer le décalage de l'écran lorsqu'on sort de la loupe <--
3949 // Centrage "brut" de lécran par rapport à la loupe
3950 Main.offset_X=Main.magnifier_offset_X-((Screen_width-Main.magnifier_width)>>1);
3951 Main.offset_Y=Main.magnifier_offset_Y-((Menu_Y-Main.magnifier_height)>>1);
3952
3953 // Correction en cas de débordement de l'image
3954 if (Main.offset_X+Screen_width>Main.image_width)
3955 Main.offset_X=Main.image_width-Screen_width;
3956 if (Main.offset_X<0)
3957 Main.offset_X=0;
3958
3959 if (Main.offset_Y+Menu_Y>Main.image_height)
3960 Main.offset_Y=Main.image_height-Menu_Y;
3961 if (Main.offset_Y<0)
3962 Main.offset_Y=0;
3963
3964 // La fonction d'affichage dans l'image est désormais un affichage normal.
3965 Pixel_preview=Pixel_preview_normal;
3966
3967 // Calculer les bornes visibles dans l'écran
3968 Compute_limits();
3969 Display_all_screen(); // <=> Display_screen();
3970 // Repositionner le curseur en fonction des coordonnées visibles
3971 Compute_paintbrush_coordinates();
3972
3973 Old_MX = -1;
3974 Old_MY = -1;
3975 }
3976 else // On fait de notre mieux pour restaurer l'ancienne opération:
3977 Start_operation_stack(Operation_before_interrupt);
3978 }
3979
3980
3981 // ----------------------- Modifications de brosse ---------------------------
3982
Button_Brush_FX(int btn)3983 void Button_Brush_FX(int btn)
3984 {
3985 short clicked_button;
3986 short index;
3987
3988 Open_window(310,162,"Brush effects");
3989
3990 Window_display_frame( 6,19,298,61);
3991 Window_display_frame( 6,83,122,53);
3992 Window_display_frame(137,83,167,53);
3993
3994 Window_set_normal_button(236,141, 67,14,"Cancel" ,0,1,KEY_ESC); // 1
3995 Window_set_normal_button( 19, 46, 27,14,"X\035" ,0,1,Config_Key[SPECIAL_FLIP_X][0]); // 2
3996 Window_set_normal_button( 19, 61, 27,14,"Y\022" ,0,1,Config_Key[SPECIAL_FLIP_Y][0]); // 3
3997 Window_set_normal_button( 58, 46, 37,14,"90\xb0" ,0,1,Config_Key[SPECIAL_ROTATE_90][0]); // 4
3998 Window_set_normal_button( 96, 46, 37,14,"180\xb0" ,0,1,Config_Key[SPECIAL_ROTATE_180][0]); // 5
3999 Window_set_normal_button( 58, 61, 75,14,"any angle" ,0,1,Config_Key[SPECIAL_ROTATE_ANY_ANGLE][0]); // 6
4000 Window_set_normal_button(145, 46, 67,14,"Stretch" ,0,1,Config_Key[SPECIAL_STRETCH][0]); // 7
4001 Window_set_normal_button(145, 61, 67,14,"Distort" ,0,1,Config_Key[SPECIAL_DISTORT][0]); // 8
4002 Window_set_normal_button(155, 99,131,14,"Recolorize" ,0,1,Config_Key[SPECIAL_RECOLORIZE_BRUSH][0]); // 9
4003 Window_set_normal_button(155,117,131,14,"Get brush colors",0,1,Config_Key[SPECIAL_GET_BRUSH_COLORS][0]); // 10
4004
4005 // Boutons représentant les coins du brush handle: (HG,HD,C,BG,BD)
4006 Window_set_normal_button( 75, 90,11,11,"",0,1,Config_Key[SPECIAL_TOP_LEFT_ATTACHMENT][0]); // 11
4007 Window_set_normal_button(103, 90,11,11,"",0,1,Config_Key[SPECIAL_TOP_RIGHT_ATTACHMENT][0]); // 12
4008 Window_set_normal_button( 89,104,11,11,"",0,1,Config_Key[SPECIAL_CENTER_ATTACHMENT][0]); // 13
4009 Window_set_normal_button( 75,118,11,11,"",0,1,Config_Key[SPECIAL_BOTTOM_LEFT_ATTACHMENT][0]); // 14
4010 Window_set_normal_button(103,118,11,11,"",0,1,Config_Key[SPECIAL_BOTTOM_RIGHT_ATTACHMENT][0]); // 15
4011
4012 Window_set_normal_button(224,46,67,14,"Outline",0,1,Config_Key[SPECIAL_OUTLINE][0]); // 16
4013 Window_set_normal_button(224,61,67,14,"Nibble" ,0,1,Config_Key[SPECIAL_NIBBLE][0]); // 17
4014
4015 Window_set_normal_button( 7,141, 60,14,"Load",0,1,Config_Key[SPECIAL_LOAD_BRUSH][0]); // 18
4016 Window_set_normal_button( 70,141, 60,14,"Save",0,1,Config_Key[SPECIAL_SAVE_BRUSH][0]); // 19
4017
4018 Print_in_window( 80, 24,"Shape modifications",MC_Dark,MC_Light);
4019 Print_in_window( 10, 36,"Mirror",MC_Dark,MC_Light);
4020 Print_in_window( 72, 36,"Rotate",MC_Dark,MC_Light);
4021 Print_in_window(155, 36,"Deform",MC_Dark,MC_Light);
4022 Print_in_window(230, 36,"Borders",MC_Dark,MC_Light);
4023 Print_in_window(141, 88,"Colors modifications",MC_Dark,MC_Light);
4024 Print_in_window( 20,102,"Brush",MC_Dark,MC_Light);
4025 Print_in_window( 16,110,"handle",MC_Dark,MC_Light);
4026
4027 // Dessin des pointillés pour le "brush handle"
4028 for (index=0; index<13; index+=2)
4029 {
4030 Pixel_in_window( 88+index, 92,MC_Dark);
4031 Pixel_in_window( 88+index,126,MC_Dark);
4032 Pixel_in_window( 77,103+index,MC_Dark);
4033 Pixel_in_window(111,103+index,MC_Dark);
4034 }
4035 // Dessin des coins et du centre pour les boutons du "brush handle"
4036 // Coin HG
4037 Window_rectangle(77, 92, 7, 1, MC_Black);
4038 Window_rectangle(77, 92, 1, 7, MC_Black);
4039 // Coin HD
4040 Window_rectangle(105, 92, 7, 1, MC_Black);
4041 Window_rectangle(111, 92, 1, 7, MC_Black);
4042 // Centre
4043 Window_rectangle(91, 109, 7, 1, MC_Black);
4044 Window_rectangle(94, 106, 1, 7, MC_Black);
4045 // Coin BG
4046 Window_rectangle(77, 126, 7, 1, MC_Black);
4047 Window_rectangle(77, 120, 1, 7, MC_Black);
4048 // Coin BD
4049 Window_rectangle(105, 126, 7, 1, MC_Black);
4050 Window_rectangle(111, 120, 1, 7, MC_Black);
4051
4052 Update_window_area(0,0,Window_width, Window_height);
4053
4054 Display_cursor();
4055
4056 do
4057 {
4058 clicked_button=Window_clicked_button();
4059 if (Is_shortcut(Key,0x100+BUTTON_HELP))
4060 {
4061 Key=0;
4062 Window_help(BUTTON_BRUSH_EFFECTS, NULL);
4063 }
4064 else if (Is_shortcut(Key,0x100+BUTTON_BRUSH_EFFECTS))
4065 {
4066 clicked_button=1;
4067 }
4068 }
4069 while (clicked_button<=0 && !Quit_is_required);
4070
4071 Close_window();
4072 Unselect_button(btn);
4073
4074 // Gestion du bouton clické
4075 switch (clicked_button)
4076 {
4077 case 2 : // Flip X
4078 Flip_X_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
4079 // Remap according to the last used remap table
4080 Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
4081 break;
4082 case 3 : // Flip Y
4083 Flip_Y_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
4084 // Remap according to the last used remap table
4085 Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
4086 break;
4087 case 4 : // 90° Rotation
4088 Rotate_90_deg();
4089 break;
4090 case 5 : // 180° Rotation
4091 Rotate_180_deg_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
4092 Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
4093 Brush_offset_X=(Brush_width>>1);
4094 Brush_offset_Y=(Brush_height>>1);
4095 break;
4096 case 6 : // Any angle rotation
4097 Start_operation_stack(OPERATION_ROTATE_BRUSH);
4098 break;
4099 case 7 : // Stretch
4100 Start_operation_stack(OPERATION_STRETCH_BRUSH);
4101 break;
4102 case 8 : // Distort
4103 Start_operation_stack(OPERATION_DISTORT_BRUSH);
4104 break;
4105 case 9 : // Recolorize
4106 Remap_brush();
4107 break;
4108 case 10 : // Get brush colors
4109 Display_cursor();
4110 Get_colors_from_brush();
4111 Hide_cursor();
4112 break;
4113 case 11 : // Brush Attachment: Top-Left
4114 Brush_offset_X=0;
4115 Brush_offset_Y=0;
4116 break;
4117 case 12 : // Brush Attachment: Top-Right
4118 Brush_offset_X=(Brush_width-1);
4119 Brush_offset_Y=0;
4120 break;
4121 case 13 : // Brush Attachment: Center
4122 Brush_offset_X=(Brush_width>>1);
4123 Brush_offset_Y=(Brush_height>>1);
4124 break;
4125 case 14 : // Brush Attachment: Bottom-Left
4126 Brush_offset_X=0;
4127 Brush_offset_Y=(Brush_height-1);
4128 break;
4129 case 15 : // Brush Attachment: Bottom-Right
4130 Brush_offset_X=(Brush_width-1);
4131 Brush_offset_Y=(Brush_height-1);
4132 break;
4133 case 16 : // Outline
4134 Outline_brush();
4135 break;
4136 case 17 : // Nibble
4137 Nibble_brush();
4138 break;
4139 case 18 : // Load
4140 Display_cursor();
4141 Load_picture(CONTEXT_BRUSH);
4142 Hide_cursor();
4143 break;
4144 case 19 : // Save
4145 Display_cursor();
4146 Save_picture(CONTEXT_BRUSH);
4147 Hide_cursor();
4148 break;
4149 }
4150
4151 Display_cursor();
4152 }
4153
4154
4155 //---------------------------- Courbes de Bézier ----------------------------
4156
Button_Curves(int btn)4157 void Button_Curves(int btn)
4158 {
4159 (void)btn;
4160 Hide_cursor();
4161 Start_operation_stack(Selected_curve_mode);
4162 Display_cursor();
4163 }
4164
4165
Button_Curves_switch_mode(int btn)4166 void Button_Curves_switch_mode(int btn)
4167 {
4168 if (Selected_curve_mode==OPERATION_4_POINTS_CURVE)
4169 Selected_curve_mode=OPERATION_3_POINTS_CURVE;
4170 else
4171 Selected_curve_mode=OPERATION_4_POINTS_CURVE;
4172
4173 Hide_cursor();
4174 Display_sprite_in_menu(btn,Selected_curve_mode==OPERATION_4_POINTS_CURVE?MENU_SPRITE_4_POINTS_CURVE:-1);
4175 Draw_menu_button(btn,BUTTON_PRESSED);
4176 Start_operation_stack(Selected_curve_mode);
4177 Display_cursor();
4178 }
4179
4180
4181 //--------------------------------- Spray -----------------------------------
4182
Button_Airbrush(int btn)4183 void Button_Airbrush(int btn)
4184 {
4185 (void)btn;
4186 Hide_cursor();
4187 Start_operation_stack(OPERATION_AIRBRUSH);
4188 Display_cursor();
4189 }
4190
4191
Refresh_airbrush_settings(byte selected_color,byte update_slider)4192 void Refresh_airbrush_settings(byte selected_color, byte update_slider)
4193 {
4194 char str[4];
4195
4196 if (update_slider)
4197 {
4198 Window_scroller_button_list->Position=49-Airbrush_multi_flow[selected_color];
4199 Window_draw_slider(Window_scroller_button_list);
4200 }
4201 Num2str(Airbrush_multi_flow[selected_color],str,2);
4202 Print_in_window(196,130,str,MC_Black,MC_Light);
4203
4204 Update_window_area(Window_palette_button_list->Pos_X+4+(selected_color >> 4)*10,
4205 Window_palette_button_list->Pos_Y+3+(selected_color & 15)* 5,
4206 2,5);
4207 }
4208
4209
Button_Airbrush_menu(int btn)4210 void Button_Airbrush_menu(int btn)
4211 {
4212 static byte spray_init=1;
4213 short clicked_button;
4214 char str[4];
4215 word index;
4216 byte selected_color=Fore_color;
4217 byte old_airbrush_mode =Airbrush_mode;
4218 short old_airbrush_size =Airbrush_size;
4219 byte old_airbrush_delay =Airbrush_delay;
4220 byte old_airbrush_mono_flow=Airbrush_mono_flow;
4221 byte old_airbrush_multi_flow[256];
4222 T_Special_button * input_size_button;
4223 T_Special_button * input_delay_button;
4224 T_Special_button * input_flow_button;
4225 T_Special_button * input_init_button;
4226 word old_mouse_x;
4227 word old_mouse_y;
4228 byte old_mouse_k;
4229 byte color;
4230 byte click;
4231
4232 (void)btn;
4233 memcpy(old_airbrush_multi_flow,Airbrush_multi_flow,256);
4234
4235
4236 Open_window(226,170,"Spray");
4237
4238 Window_set_normal_button(110,148,51,14,"Cancel" ,0,1,KEY_ESC); // 1
4239 Window_set_normal_button(166,148,51,14,"OK" ,0,1,KEY_RETURN); // 2
4240
4241 Window_set_scroller_button(178,62,74,50,1,49-Airbrush_multi_flow[selected_color]); // 3
4242
4243 Window_set_palette_button(7,56); // 4
4244
4245 Window_set_normal_button( 8,148,83,14,"Mode: ",0,1,KEY_TAB); // 5
4246 if (Airbrush_mode)
4247 Print_in_window(50,151," Mono",MC_Black,MC_Light);
4248 else
4249 Print_in_window(50,151,"Multi",MC_Black,MC_Light);
4250
4251 Window_set_normal_button(194, 62,19,14,"+1" ,0,1,KEY_KP_PLUS); // 6
4252 Window_set_normal_button(194, 79,19,14,"-1" ,0,1,KEY_KP_MINUS); // 7
4253 Window_set_normal_button(194, 96,19,14,"x2" ,0,1,KEY_KP_MULTIPLY); // 8
4254 Window_set_normal_button(194,113,19,14,"\xf7""2" ,0,1,KEY_KP_ENTER); // 9
4255
4256 Window_set_normal_button( 8, 37,43,14,"Clear" ,1,1,KEY_c); // 10
4257
4258 Print_in_window_underscore(142,25,"Size:" ,MC_Dark,MC_Light,1);
4259 input_size_button = Window_set_input_button_s(186,23,3,KEY_s); // 11
4260 Num2str(Airbrush_size,str,3);
4261 Window_input_content(input_size_button,str);
4262
4263 Print_in_window_underscore(142,39,"Delay:" ,MC_Dark,MC_Light,1);
4264 input_delay_button = Window_set_input_button_s(194,37,2,KEY_d); // 12
4265 Num2str(Airbrush_delay,str,2);
4266 Window_input_content(input_delay_button,str);
4267
4268 Print_in_window_underscore( 27,24,"Mono-Flow:",MC_Dark,MC_Light,1);
4269 input_flow_button = Window_set_input_button_s(111,22,2,KEY_m); // 13
4270 Num2str(Airbrush_mono_flow,str,2);
4271 Window_input_content(input_flow_button,str);
4272
4273 Print_in_window_underscore( 67,40,"Init:",MC_Dark,MC_Light,1);
4274 input_init_button = Window_set_input_button_s(111,38,2,KEY_i); // 14
4275 Num2str(spray_init,str,2);
4276 Window_input_content(input_init_button,str);
4277
4278 Window_display_frame(173,56,45,86);
4279 Window_display_frame(137,19,81,33);
4280
4281 // On tagge toutes les couleurs utilisées
4282 for (index=0; index<256; index++)
4283 if (Airbrush_multi_flow[index])
4284 Stencil_tag_color(index,MC_Black);
4285 // Et enfin, on tagge la couleur sélectionnée
4286 Stencil_tag_color(selected_color,MC_White);
4287 Refresh_airbrush_settings(selected_color,0);
4288
4289 Update_window_area(0,0,Window_width, Window_height);
4290 Display_cursor();
4291 Stencil_update_color(selected_color);
4292
4293
4294 do
4295 {
4296 old_mouse_x=Mouse_X;
4297 old_mouse_y=Mouse_Y;
4298 old_mouse_k=Mouse_K;
4299
4300 clicked_button=Window_clicked_button();
4301
4302 switch (clicked_button)
4303 {
4304 case 0 :
4305 case 2 : // OK
4306 break;
4307
4308 case 1 : // Cancel
4309 Airbrush_mode =old_airbrush_mode;
4310 Airbrush_size =old_airbrush_size;
4311 Airbrush_delay =old_airbrush_delay;
4312 Airbrush_mono_flow=old_airbrush_mono_flow;
4313 memcpy(Airbrush_multi_flow,old_airbrush_multi_flow,256);
4314 break;
4315
4316 case 3 : // Scroller
4317 Hide_cursor();
4318 Airbrush_multi_flow[selected_color]=49-Window_attribute2;
4319 Refresh_airbrush_settings(selected_color,0);
4320 Display_cursor();
4321 break;
4322
4323 case -1 :
4324 case 4 : // Palette
4325 if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) )
4326 {
4327 Hide_cursor();
4328 Stencil_tag_color(selected_color,(Airbrush_multi_flow[selected_color])?MC_Black:MC_Light);
4329 Stencil_update_color(selected_color);
4330 // Mettre la couleur sélectionnée à jour suivant le click
4331 selected_color=(clicked_button==4) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y);
4332 if (Mouse_K==2)
4333 Airbrush_multi_flow[selected_color]=0;
4334 else
4335 if (Airbrush_multi_flow[selected_color]==0)
4336 Airbrush_multi_flow[selected_color]=spray_init;
4337
4338 // Tagger la couleur sélectionnée en blanc
4339 Stencil_tag_color(selected_color,MC_White);
4340 Refresh_airbrush_settings(selected_color,1);
4341 Display_cursor();
4342 Stencil_update_color(selected_color);
4343 }
4344 break;
4345
4346 case 5 : // Toggle Mode
4347 Airbrush_mode=(Airbrush_mode+1)&1;
4348 Hide_cursor();
4349 if (Airbrush_mode)
4350 Print_in_window(50,151," Mono",MC_Black,MC_Light);
4351 else
4352 Print_in_window(50,151,"Multi",MC_Black,MC_Light);
4353 Update_window_area(50,151,5*8,8);
4354 Display_cursor();
4355 break;
4356
4357 case 6 : // +1
4358 for (index=0; index<256; index++)
4359 {
4360 if ( (Airbrush_multi_flow[index]) && (Airbrush_multi_flow[index]<49) )
4361 Airbrush_multi_flow[index]++;
4362 }
4363 Hide_cursor();
4364 Refresh_airbrush_settings(selected_color,1);
4365 Display_cursor();
4366 break;
4367
4368 case 7 : // -1
4369 for (index=0; index<256; index++)
4370 {
4371 if (Airbrush_multi_flow[index]>1)
4372 Airbrush_multi_flow[index]--;
4373 }
4374 Hide_cursor();
4375 Refresh_airbrush_settings(selected_color,1);
4376 Display_cursor();
4377 break;
4378
4379 case 8 : // x2
4380 for (index=0; index<256; index++)
4381 {
4382 if (Airbrush_multi_flow[index])
4383 {
4384 Airbrush_multi_flow[index]<<=1;
4385 if (Airbrush_multi_flow[index]>49)
4386 Airbrush_multi_flow[index]=49;
4387 }
4388 }
4389 Hide_cursor();
4390 Refresh_airbrush_settings(selected_color,1);
4391 Display_cursor();
4392 break;
4393
4394 case 9 : // ÷2
4395 for (index=0; index<256; index++)
4396 {
4397 if (Airbrush_multi_flow[index]>1)
4398 Airbrush_multi_flow[index]>>=1;
4399 }
4400 Hide_cursor();
4401 Refresh_airbrush_settings(selected_color,1);
4402 Display_cursor();
4403 break;
4404
4405 case 10 : // Clear
4406 memset(Airbrush_multi_flow,0,256);
4407 // On raffiche les infos de la couleur sélectionnée
4408 Refresh_airbrush_settings(selected_color,1);
4409 // On efface les anciens TAGs
4410 Window_clear_tags();
4411 // Tagger la couleur sélectionnée en blanc
4412 Stencil_tag_color(selected_color,MC_White);
4413 Stencil_update_color(selected_color);
4414 break;
4415
4416 case 11 : // Size
4417 Num2str(Airbrush_size,str,3);
4418 Readline(188,25,str,3,INPUT_TYPE_INTEGER);
4419 Airbrush_size=atoi(str);
4420 // On corrige les dimensions
4421 if (Airbrush_size>256)
4422 {
4423 Airbrush_size=256;
4424 Num2str(Airbrush_size,str,3);
4425 Window_input_content(input_size_button,str);
4426 }
4427 else if (!Airbrush_size)
4428 {
4429 Airbrush_size=1;
4430 Num2str(Airbrush_size,str,3);
4431 Window_input_content(input_size_button,str);
4432 }
4433 Display_cursor();
4434 break;
4435
4436 case 12 : // Delay
4437 Num2str(Airbrush_delay,str,2);
4438 Readline(196,39,str,2,INPUT_TYPE_INTEGER);
4439 Airbrush_delay=atoi(str);
4440 // On corrige le delai
4441 if (Airbrush_delay>99)
4442 {
4443 Airbrush_delay=99;
4444 Num2str(Airbrush_delay,str,2);
4445 Window_input_content(input_delay_button,str);
4446 }
4447 Display_cursor();
4448 break;
4449
4450 case 13 : // Mono-Flow
4451 Num2str(Airbrush_mono_flow,str,2);
4452 Readline(113,24,str,2,INPUT_TYPE_INTEGER);
4453 Airbrush_mono_flow=atoi(str);
4454 // On corrige le flux
4455 if (!Airbrush_mono_flow)
4456 {
4457 Airbrush_mono_flow=1;
4458 Num2str(Airbrush_mono_flow,str,2);
4459 Window_input_content(input_flow_button,str);
4460 }
4461 Display_cursor();
4462 break;
4463
4464 case 14 : // Init
4465 Num2str(spray_init,str,2);
4466 Readline(113,40,str,2,INPUT_TYPE_INTEGER);
4467 spray_init=atoi(str);
4468 // On corrige la valeur
4469 if (spray_init>=50)
4470 {
4471 spray_init=49;
4472 Num2str(spray_init,str,2);
4473 Window_input_content(input_init_button,str);
4474 }
4475 else if (spray_init<1)
4476 {
4477 spray_init=1;
4478 Num2str(spray_init,str,2);
4479 Window_input_content(input_init_button,str);
4480 }
4481 Display_cursor();
4482 break;
4483 }
4484
4485 if (!Mouse_K)
4486 switch (Key)
4487 {
4488 case KEY_BACKQUOTE : // Récupération d'une couleur derrière le menu
4489 case KEY_COMMA :
4490 Get_color_behind_window(&color,&click);
4491 if (click)
4492 {
4493 Hide_cursor();
4494 Stencil_tag_color(selected_color,(Airbrush_multi_flow[selected_color])?MC_Black:MC_Light);
4495 Stencil_update_color(selected_color);
4496 // Mettre la couleur sélectionnée à jour suivant le click
4497 selected_color=color;
4498 if (click==2)
4499 Airbrush_multi_flow[selected_color]=0;
4500 else
4501 if (Airbrush_multi_flow[selected_color]==0)
4502 Airbrush_multi_flow[selected_color]=spray_init;
4503
4504 // Tagger la couleur sélectionnée en blanc
4505 Stencil_tag_color(selected_color,MC_White);
4506 Refresh_airbrush_settings(selected_color,1);
4507 Display_cursor();
4508 Stencil_update_color(selected_color);
4509 Wait_end_of_click();
4510 }
4511 Key=0;
4512 break;
4513 default:
4514 if (Is_shortcut(Key,0x100+BUTTON_HELP))
4515 {
4516 Window_help(BUTTON_AIRBRUSH, NULL);
4517 Key=0;
4518 break;
4519 }
4520 if (Is_shortcut(Key,0x200+BUTTON_AIRBRUSH))
4521 {
4522 clicked_button=2;
4523 break;
4524 }
4525 }
4526 }
4527 while ( (clicked_button!=1) && (clicked_button!=2) && !Quit_is_required);
4528
4529 Close_window();
4530
4531 /*
4532 // Tant que l'on aura pas résolu le problème du désenclenchement du mode
4533 // de dessin précedent, il faudra laisser ça en remarque et donc passer en
4534 // spray même si on a clické sur Cancel (idem pour OK (un peu plus bas)).
4535 if (clicked_button==1) // Cancel
4536 {
4537 if (Current_operation!=OPERATION_AIRBRUSH)
4538 Unselect_button(BUTTON_AIRBRUSH);
4539 }
4540 */
4541
4542 Display_cursor();
4543
4544 /*
4545 if (clicked_button==2) // OK
4546 */
4547 if (Current_operation!=OPERATION_AIRBRUSH)
4548 Select_button(BUTTON_AIRBRUSH,LEFT_SIDE);
4549 }
4550
4551
4552 // -- Gestion des boutons de polygone vide et plein -------------------------
4553
Button_polygon(int btn)4554 void Button_polygon(int btn)
4555 {
4556 (void)btn;
4557 Hide_cursor();
4558 Start_operation_stack(OPERATION_POLYGON);
4559 Display_cursor();
4560 }
4561
4562
Button_Polyform(int btn)4563 void Button_Polyform(int btn)
4564 {
4565 (void)btn;
4566 Hide_cursor();
4567 Start_operation_stack(OPERATION_POLYFORM);
4568 Display_cursor();
4569 }
4570
4571
Button_Polyfill(int btn)4572 void Button_Polyfill(int btn)
4573 {
4574 (void)btn;
4575 Hide_cursor();
4576 Start_operation_stack(OPERATION_POLYFILL);
4577 Display_cursor();
4578 }
4579
4580
Button_Filled_polyform(int btn)4581 void Button_Filled_polyform(int btn)
4582 {
4583 (void)btn;
4584 Hide_cursor();
4585 Start_operation_stack(OPERATION_FILLED_POLYFORM);
4586 Display_cursor();
4587 }
4588
4589
4590 // -- Boutons d'ajustement de l'image ---------------------------------------
4591
Button_Adjust(int btn)4592 void Button_Adjust(int btn)
4593 {
4594 (void)btn;
4595 Hide_cursor();
4596 Start_operation_stack(OPERATION_SCROLL);
4597 Display_cursor();
4598 }
4599
4600
4601 // -- Menu des effets (Shade, Stencil, etc...) ------------------------------
4602
Display_effect_sprite(int sprite_number,short start_x,short start_y)4603 void Display_effect_sprite(int sprite_number, short start_x, short start_y)
4604 {
4605 short x,y,x_pos,y_pos;
4606
4607 for (y=0,y_pos=start_y;y<EFFECT_SPRITE_HEIGHT;y++,y_pos++)
4608 for (x=0,x_pos=start_x;x<EFFECT_SPRITE_WIDTH;x++,x_pos++)
4609 Pixel_in_window(x_pos,y_pos,Gfx->Effect_sprite[sprite_number][y][x]);
4610
4611 Update_rect(ToWinX(start_x),ToWinY(start_y),EFFECT_SPRITE_WIDTH*Menu_factor_X,EFFECT_SPRITE_HEIGHT*Menu_factor_Y);
4612 }
4613
4614
Display_effect_state(short x,short y,char * label,byte state)4615 void Display_effect_state(short x, short y, char * label, byte state)
4616 {
4617 Window_rectangle(x+22,y+5,12,8,MC_Light);
4618
4619 Print_in_window(x+22,y+5,label,(state)?MC_White:MC_Black,MC_Light);
4620 if (state)
4621 Window_select_normal_button(x, y, 16, 16);
4622 else
4623 Window_unselect_normal_button(x, y, 16, 16);
4624 }
4625
4626 #define C1 10
4627 #define C2 99
4628 #define C3 184
4629
4630 #define L1 19
4631 #define L2 38
4632 #define L3 57
4633 #define L4 76
4634 #define L5 95
4635
Display_effect_states(void)4636 void Display_effect_states(void)
4637 {
4638 Display_effect_state(C1, L2, "Shade" ,Shade_mode);
4639 Display_effect_state(C1, L3, "Q-shade",Quick_shade_mode);
4640 Display_effect_state(C1, L4, "Transp.",Colorize_mode);
4641 Display_effect_state(C1, L5, "Smooth" ,Smooth_mode);
4642 Display_effect_state(C2, L5, "Smear" ,Smear_mode);
4643 Display_effect_state(C2, L1, "Stencil",Stencil_mode);
4644 Display_effect_state(C2, L2, "Mask" ,Mask_mode);
4645 Display_effect_state(C2, L3, "Sieve" ,Sieve_mode);
4646 Display_effect_state(C3, L2, "Snap" ,Snap_mode);
4647 Display_effect_state(C3, L4, "Tiling" ,Tiling_mode);
4648
4649 Display_effect_state(C2,L4, "8 bit" ,Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION);
4650 Display_effect_state(C3,L3, "Tilemap",Main.tilemap_mode);
4651 }
4652
4653
Display_feedback_state(void)4654 void Display_feedback_state(void)
4655 {
4656 Print_in_window(14,24,(Config.FX_Feedback)?"X":" ",MC_Black,MC_Light);
4657 }
4658
4659
Button_Effects(int btn)4660 void Button_Effects(int btn)
4661 {
4662 short clicked_button;
4663 byte exit_by_close_button=0;
4664
4665 Open_window(270,152,"Drawing modes (effects)");
4666
4667 Window_set_normal_button(C1, L2, 16,16,"",0,1,Config_Key[SPECIAL_SHADE_MODE][0]); // 1
4668 Window_set_normal_button(C1, L3, 16,16,"",0,1,Config_Key[SPECIAL_QUICK_SHADE_MODE][0]); // 2
4669 Window_set_normal_button(C1, L4, 16,16,"",0,1,Config_Key[SPECIAL_COLORIZE_MODE][0]); // 3
4670 Window_set_normal_button(C1, L5, 16,16,"",0,1,Config_Key[SPECIAL_SMOOTH_MODE][0]); // 4
4671 Window_set_normal_button(C2, L5, 16,16,"",0,1,Config_Key[SPECIAL_SMEAR_MODE][0]); // 5
4672 Window_set_normal_button(C2, L1, 16,16,"",0,1,Config_Key[SPECIAL_STENCIL_MODE][0]); // 6
4673 Window_set_normal_button(C2, L2, 16,16,"",0,1,Config_Key[SPECIAL_MASK_MODE][0]); // 7
4674 Window_set_normal_button(C2, L3, 16,16,"",0,1,Config_Key[SPECIAL_SIEVE_MODE][0]); // 8
4675 Window_set_normal_button(C3, L2, 16,16,"",0,1,Config_Key[SPECIAL_GRID_MODE][0]); // 9
4676 Window_set_normal_button(C3, L4, 16,16,"",0,1,Config_Key[SPECIAL_TILING_MODE][0]); // 10
4677
4678 Window_set_normal_button(195,131, 68,14,"Close",0,1,KEY_RETURN); // 11
4679 Window_set_normal_button(118,131, 68,14,"All off",0,1,KEY_DELETE); // 12
4680
4681 // "Feedback" frame
4682 Window_display_frame_mono(C1-5,L1+8,90,88,MC_Dark);
4683 Window_rectangle(C1-1, L1+2, 78, 14, MC_Light);
4684
4685 Window_set_normal_button(C1+1,L1+2,14,14," ",0,1,KEY_f); // 13
4686 Print_in_window_underscore(28,24,"Feedback",MC_Dark,MC_Light,1);
4687
4688 Window_set_normal_button(C2, L4, 16,16,"",0,1,Config_Key[SPECIAL_FORMAT_CHECKER_MENU][0]); // 14
4689 Window_set_normal_button(C3, L3, 16,16,"",0,1,Config_Key[SPECIAL_TILEMAP_MODE][0]); // 15
4690
4691 // "Grid" frame
4692 Window_display_frame_mono(C3-5,L1+8,86,88,MC_Dark);
4693 Window_rectangle(C3-1, L1+2, 52, 14, MC_Light);
4694
4695 Window_set_normal_button(C3+1,L1+2,14,14,Show_grid?"X":" ",0,1,Config_Key[SPECIAL_SHOW_GRID][0]); // 16
4696 Print_in_window(C3+17,L1+5,"Grid",MC_Dark,MC_Light);
4697
4698 Display_feedback_state();
4699 Display_effect_sprite(EFFECTS_SPRITE_SHADE, C1+1,L2+1);
4700 Display_effect_sprite(EFFECTS_SPRITE_SHADE, C1+1,L3+1);
4701 Display_effect_sprite(EFFECTS_SPRITE_TRANSP, C1+1,L4+1);
4702 Display_effect_sprite(EFFECTS_SPRITE_SMOOTH, C1+1,L5+1);
4703 Display_effect_sprite(EFFECTS_SPRITE_SMEAR, C2+1,L5+1);
4704 Display_effect_sprite(EFFECTS_SPRITE_STENCIL,C2+1,L1+1);
4705 Display_effect_sprite(EFFECTS_SPRITE_MASK, C2+1,L2+1);
4706 Display_effect_sprite(EFFECTS_SPRITE_SIEVE, C2+1,L3+1);
4707 Display_effect_sprite(EFFECTS_SPRITE_GRID, C3+1,L2+1);
4708 Display_effect_sprite(EFFECTS_SPRITE_TILING, C3+1,L4+1);
4709 Display_effect_sprite(EFFECTS_SPRITE_8BIT, C2+1,L4+1);
4710 Display_effect_sprite(EFFECTS_SPRITE_TILING, C3+1,L3+1); // tilemap
4711 Display_effect_states();
4712
4713 Print_in_window(12,118,"click:",MC_Dark,MC_Light);
4714 Print_in_window(16,128,"Left:Switch",MC_Dark,MC_Light);
4715 Print_in_window(16,138,"Right:Edit",MC_Dark,MC_Light);
4716
4717 Update_window_area(0,0,Window_width, Window_height);
4718 Display_cursor();
4719
4720 do
4721 {
4722 clicked_button = Window_clicked_button();
4723
4724 if (Key==KEY_ESC || Is_shortcut(Key,0x100+BUTTON_EFFECTS))
4725 {
4726 clicked_button=11;
4727 Key=0;
4728 }
4729 else if (Is_shortcut(Key,0x100+BUTTON_HELP))
4730 {
4731 // Aide contextuelle
4732 switch(Window_get_clicked_button())
4733 {
4734 case 1:
4735 Window_help(BUTTON_EFFECTS, "SHADE");
4736 break;
4737 case 2:
4738 Window_help(BUTTON_EFFECTS, "QUICK SHADE");
4739 break;
4740 case 3:
4741 Window_help(BUTTON_EFFECTS, "TRANSPARENCY");
4742 break;
4743 case 4:
4744 Window_help(BUTTON_EFFECTS, "SMOOTH");
4745 break;
4746 case 5:
4747 Window_help(BUTTON_EFFECTS, "SMEAR");
4748 break;
4749 case 6:
4750 Window_help(BUTTON_EFFECTS, "STENCIL");
4751 break;
4752 case 7:
4753 Window_help(BUTTON_EFFECTS, "MASK");
4754 break;
4755 case 8:
4756 Window_help(BUTTON_EFFECTS, "SIEVE");
4757 break;
4758 case 9:
4759 Window_help(BUTTON_EFFECTS, "GRID");
4760 break;
4761 case 10:
4762 Window_help(BUTTON_EFFECTS, "TILING");
4763 break;
4764 case 14:
4765 Window_help(BUTTON_EFFECTS, "8 BIT");
4766 break;
4767 case 15:
4768 Window_help(BUTTON_EFFECTS, "TILEMAP");
4769 break;
4770 default:
4771 Window_help(BUTTON_EFFECTS, NULL);
4772 }
4773 // Hack because we have used Window_get_clicked_button()
4774 Input_sticky_control=0;
4775 //
4776 }
4777
4778 switch (clicked_button)
4779 {
4780 case 1 : // Shade
4781 if (Window_attribute1==LEFT_SIDE)
4782 {
4783 Button_Shade_mode();
4784 Hide_cursor();
4785 Display_effect_states();
4786 Display_cursor();
4787 }
4788 else
4789 {
4790 Close_window();
4791 Display_cursor();
4792 Button_Shade_menu();
4793 clicked_button=11;
4794 }
4795 break;
4796 case 2 : // Quick-shade
4797 if (Window_attribute1==LEFT_SIDE)
4798 {
4799 Button_Quick_shade_mode();
4800 Hide_cursor();
4801 Display_effect_states();
4802 Display_cursor();
4803 }
4804 else
4805 {
4806 Close_window();
4807 Display_cursor();
4808 Button_Quick_shade_menu();
4809 clicked_button=11;
4810 }
4811 break;
4812 case 3 : // Colorize / Transparency
4813 if (Window_attribute1==LEFT_SIDE)
4814 {
4815 Button_Colorize_mode();
4816 Hide_cursor();
4817 Display_effect_states();
4818 Display_cursor();
4819 }
4820 else
4821 {
4822 Close_window();
4823 Display_cursor();
4824 Button_Colorize_menu();
4825 clicked_button=11;
4826 }
4827 break;
4828 case 4 : // Smooth
4829 if (Window_attribute1==LEFT_SIDE)
4830 {
4831 Button_Smooth_mode();
4832 Hide_cursor();
4833 Display_effect_states();
4834 Display_cursor();
4835 }
4836 else
4837 {
4838 Close_window();
4839 Display_cursor();
4840 Button_Smooth_menu();
4841 clicked_button=11;
4842 }
4843 break;
4844 case 5 : // Smear
4845 Button_Smear_mode();
4846 Hide_cursor();
4847 Display_effect_states();
4848 Display_cursor();
4849 break;
4850 case 6 : // Stencil
4851 if (Window_attribute1==LEFT_SIDE)
4852 {
4853 Button_Stencil_mode();
4854 Hide_cursor();
4855 Display_effect_state(C2,L1,"Stencil",Stencil_mode);
4856 Display_cursor();
4857 }
4858 else
4859 {
4860 Close_window();
4861 Display_cursor();
4862 Button_Stencil_menu();
4863 clicked_button=11;
4864 }
4865 break;
4866 case 7 : // Mask
4867 if (Window_attribute1==LEFT_SIDE)
4868 {
4869 Button_Mask_mode();
4870 Hide_cursor();
4871 Display_effect_state(C2,L2,"Mask",Mask_mode);
4872 Display_cursor();
4873 }
4874 else
4875 {
4876 Close_window();
4877 Display_cursor();
4878 Button_Mask_menu();
4879 clicked_button=11;
4880 }
4881 break;
4882 case 8 : // Sieve
4883 if (Window_attribute1==LEFT_SIDE)
4884 {
4885 Button_Sieve_mode();
4886 Hide_cursor();
4887 Display_effect_state(C2,L3,"Sieve",Sieve_mode);
4888 Display_cursor();
4889 }
4890 else
4891 {
4892 Close_window();
4893 Display_cursor();
4894 Button_Sieve_menu();
4895 clicked_button=11;
4896 }
4897 break;
4898 case 9 : // Grid
4899 if (Window_attribute1==LEFT_SIDE)
4900 {
4901 Button_Snap_mode();
4902 Hide_cursor();
4903 Display_effect_state(C3,L2,"Snap",Snap_mode);
4904 Display_cursor();
4905 }
4906 else
4907 {
4908 Close_window();
4909 Display_cursor();
4910 Button_Grid_menu();
4911 clicked_button=11;
4912 }
4913 break;
4914 case 10 : // Tiling
4915 if (Window_attribute1==LEFT_SIDE)
4916 {
4917 Button_Tiling_mode();
4918 Hide_cursor();
4919 Display_effect_states();
4920 Display_cursor();
4921 }
4922 else
4923 {
4924 Close_window();
4925 Display_cursor();
4926 Button_Tiling_menu();
4927 clicked_button=11;
4928 }
4929 break;
4930 case 11 : // Close
4931 exit_by_close_button=1;
4932 break;
4933 case 12 : // All off
4934 Effects_off();
4935 Hide_cursor();
4936 Display_effect_states();
4937 Display_cursor();
4938 break;
4939 case 13 : // Feedback (pour Colorize et Shade)
4940 Config.FX_Feedback = !Config.FX_Feedback;
4941 Update_FX_feedback(Config.FX_Feedback);
4942 Hide_cursor();
4943 Display_feedback_state();
4944 Display_cursor();
4945 break;
4946
4947
4948 case 14: // Constraint checker/enforcer
4949 if (Window_attribute1==LEFT_SIDE && Selected_Constraint_Mode > IMAGE_MODE_ANIMATION)
4950 {
4951 Button_Constraint_mode();
4952 Hide_cursor();
4953 Display_effect_state(C2,L4, "8 bit" ,Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION);
4954 Display_cursor();
4955 } else {
4956 Close_window();
4957 Display_cursor();
4958 Button_Constraint_menu();
4959 clicked_button = 11;
4960 }
4961 break;
4962 case 15: // Tilemap
4963 if (Window_attribute1==LEFT_SIDE)
4964 {
4965 Button_Tilemap_mode();
4966 Hide_cursor();
4967 Display_effect_state(C3,L3, "Tilemap" ,Main.tilemap_mode);
4968 Display_cursor();
4969 }
4970 else
4971 {
4972 Close_window();
4973 Display_cursor();
4974 Button_Tilemap_menu();
4975 clicked_button=11;
4976 }
4977 break;
4978 case 16: // Show grid
4979 Show_grid = !Show_grid;
4980 Hide_cursor();
4981 Print_in_window(C3+4, L1+5, Show_grid?"X":" ", MC_Black, MC_Light);
4982 Display_cursor();
4983 }
4984 }
4985 while (clicked_button!=11 && !Quit_is_required);
4986
4987 if (exit_by_close_button || Quit_is_required)
4988 Close_window();
4989 else
4990 Hide_cursor();
4991
4992 if (!Any_effect_active())
4993 Unselect_button(btn);
4994
4995 Display_cursor();
4996 }
4997
4998 #undef C2
4999
5000 // Callback to display a font name in the list
Draw_one_font_name(word x,word y,word index,byte highlighted)5001 void Draw_one_font_name(word x, word y, word index, byte highlighted)
5002 {
5003 Print_in_window(x,y,Font_label(index), MC_Black, (highlighted)?MC_Dark:MC_Light);
5004 }
5005
Button_Text(int btn)5006 void Button_Text(int btn)
5007 {
5008 static char str[256]="";
5009 static int font_size=32;
5010 static int antialias=1;
5011 static short list_start=0; // index de le premiere fonte dans le selector
5012 static short cursor_position=0; // index de la ligne active dans le selector
5013 static short selected_font_index=0;
5014 static short is_bold=0;
5015 static short is_italic=0;
5016
5017 byte * new_brush=NULL;
5018 T_Palette text_palette;
5019 int new_width;
5020 int new_height;
5021 int clicked_button;
5022 const int NB_FONTS=8;
5023 char size_buffer[4];
5024 T_Special_button * input_size_button;
5025 T_Special_button * input_text_button;
5026 T_Special_button * preview_button;
5027 T_Special_button * font_list_button;
5028 T_Scroller_button * font_scroller;
5029 T_List_button * font_list;
5030
5031 byte redraw_is_needed=1;
5032 byte preview_is_needed=1;
5033
5034 (void)btn;
5035 Open_window(288,180,"Text");
5036
5037 // Texte saisi
5038 Print_in_window_underscore(6,20,"Text:",MC_Dark,MC_Light,1);
5039 input_text_button = Window_set_input_button_s(48,18,29,KEY_t); // 1
5040
5041 // TrueType options
5042 Window_display_frame_in(182,34,100,68);
5043 Print_in_window(199,31,"TrueType", MC_Dark, MC_Light);
5044 // AA
5045 Window_set_normal_button(188,58,13,11,antialias?"X":" ",0,1,KEY_a); // 2
5046 Print_in_window_underscore(206,60,"AntiAlias", MC_Dark, MC_Light,5);
5047 // Bold
5048 Window_set_normal_button(188,72,13,11,is_bold?"X":" ",0,1,KEY_b); // 3
5049 Print_in_window_underscore(206,75,"Bold", MC_Dark, MC_Light,1);
5050 // Italic
5051 Window_set_normal_button(188,86,13,11,is_italic?"X":" ",0,1,KEY_i); // 4
5052 Print_in_window_underscore(206,89,"Italic", MC_Dark, MC_Light,1);
5053
5054 // Scroller des fontes
5055 font_scroller = Window_set_scroller_button(165,35,NB_FONTS*8,Font_count(),NB_FONTS,list_start); // 5
5056 // Liste des fontes disponibles
5057 font_list_button = Window_set_special_button(8,35,152,NB_FONTS*8,0); // 6
5058 Window_display_frame_in(7, 33, 154, NB_FONTS*8+4);
5059
5060 // Taille texte
5061 input_size_button = Window_set_input_button_s(220,43,3,KEY_s); // 7
5062 Window_set_repeatable_button(202,43,13,11,"-",0,1,KEY_NONE); // 8
5063 Window_set_repeatable_button(251,43,13,11,"+",0,1,KEY_NONE); // 9
5064
5065 // Preview
5066 preview_button = Window_set_special_button(8,106,273,50,0); // 10
5067 Window_display_frame_in(7, 105, 275, 52);
5068
5069 Window_set_normal_button(8,160,40,14,"OK",0,1,KEY_RETURN); // 11
5070 Window_set_normal_button(54,160,60,14,"Cancel",0,1,KEY_ESC); // 12
5071
5072 // List of fonts
5073 font_list = Window_set_list_button(font_list_button, font_scroller, Draw_one_font_name, 2); // 13
5074 // Restore its settings from last passage in screen
5075 font_list->List_start = list_start;
5076 font_list->Cursor_position = cursor_position;
5077
5078 Window_redraw_list(font_list);
5079
5080 Update_window_area(0,0,Window_width, Window_height);
5081
5082 // str texte
5083 Window_input_content(input_text_button,str);
5084 // Taille police
5085 redraw_is_needed=1;
5086 // --
5087
5088 while (1)
5089 {
5090 if (redraw_is_needed)
5091 {
5092 // Taille
5093 Num2str(font_size,size_buffer,3);
5094 Window_input_content(input_size_button,size_buffer);
5095 }
5096 if (preview_is_needed)
5097 {
5098 const char * preview_string = "AaBbCcDdEeFf012345";
5099 byte is_truetype;
5100
5101 if (str[0])
5102 preview_string=str;
5103 is_truetype=TrueType_font(selected_font_index);
5104 free(new_brush);
5105 new_brush = Render_text(preview_string, selected_font_index, font_size, antialias, is_bold, is_italic, &new_width, &new_height, text_palette);
5106 // Background:
5107 if (antialias&&is_truetype)
5108 // Solid
5109 Window_rectangle(8, 106, 273, 50,MC_Black);
5110 else if (is_truetype)
5111 {
5112 long l = text_palette[Fore_color].R+text_palette[Fore_color].G+text_palette[Fore_color].B;
5113 Window_rectangle(8, 106, 273, 50,l>128*3? MC_Black:MC_Light);
5114 }
5115 else
5116 {
5117 long l = text_palette[Back_color].R+text_palette[Back_color].G+text_palette[Back_color].B;
5118 Window_rectangle(8, 106, 273, 50,l>128*3? MC_Light:MC_Black);
5119 }
5120 if (new_brush)
5121 {
5122 if (!is_truetype || (is_truetype&&antialias))
5123 {
5124 // Display brush in remapped form.
5125 byte *remapped_brush;
5126
5127 remapped_brush=(byte *)malloc(new_width*new_height);
5128 if (remapped_brush)
5129 {
5130 // This code is mostly copied from Remap_brush()
5131 short x_pos;
5132 short y_pos;
5133 int color;
5134 byte colmap[256];
5135
5136 for (color=0;color<=255;color++)
5137 colmap[color]=0;
5138
5139 for (y_pos=0;y_pos<new_height;y_pos++)
5140 for (x_pos=0;x_pos<new_width;x_pos++)
5141 colmap[*(new_brush + y_pos * new_width + x_pos)]=1;
5142
5143 colmap[Back_color]=0;
5144
5145 for (color=0;color<=255;color++)
5146 if (colmap[color] != 0)
5147 {
5148 byte r,g,b;
5149 r=text_palette[color].R;
5150 g=text_palette[color].G;
5151 b=text_palette[color].B;
5152
5153 //if (r==Main.palette[color].R && g==Main.palette[color].G && b==Main.palette[color].B)
5154 // colmap[color]=color;
5155 //else
5156 colmap[color]=Best_color_perceptual_except(r,g,b,Back_color);
5157 }
5158
5159 colmap[Back_color]=Back_color;
5160 Remap_general_lowlevel(colmap,new_brush,remapped_brush,new_width,new_height,new_width);
5161
5162 Display_brush(
5163 remapped_brush,
5164 Window_pos_X+preview_button->Pos_X*Menu_factor_X,
5165 Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
5166 0,
5167 0,
5168 Min(preview_button->Width*Menu_factor_X, new_width),
5169 Min(preview_button->Height*Menu_factor_Y, new_height),
5170 Back_color,
5171 new_width);
5172
5173 free(remapped_brush);
5174 }
5175
5176 }
5177 else
5178 {
5179 // Solid
5180 Display_brush(
5181 new_brush,
5182 Window_pos_X+preview_button->Pos_X*Menu_factor_X,
5183 Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
5184 0,
5185 0,
5186 Min(preview_button->Width*Menu_factor_X, new_width),
5187 Min(preview_button->Height*Menu_factor_Y, new_height),
5188 Back_color,
5189 new_width);
5190 }
5191
5192 }
5193 Update_window_area(
5194 preview_button->Pos_X,
5195 preview_button->Pos_Y,
5196 preview_button->Width,
5197 preview_button->Height);
5198 }
5199 if (redraw_is_needed || preview_is_needed)
5200 {
5201 redraw_is_needed=0;
5202 preview_is_needed=0;
5203 Display_cursor();
5204 }
5205
5206 clicked_button=Window_clicked_button();
5207 if (Quit_is_required)
5208 clicked_button = 12; // cancel
5209 if (clicked_button==0)
5210 {
5211 if (Is_shortcut(Key,0x100+BUTTON_HELP))
5212 Window_help(BUTTON_TEXT, NULL);
5213 else if (Is_shortcut(Key,0x100+BUTTON_TEXT))
5214 clicked_button = 12; // cancel
5215 }
5216 switch(clicked_button)
5217 {
5218 case 1: // Texte saisi
5219 Readline_ex(50,20,str,29,250,INPUT_TYPE_STRING,0);
5220 preview_is_needed=1;
5221 break;
5222
5223 case 2: // AA
5224 antialias = (antialias==0);
5225 Hide_cursor();
5226 Print_in_window(191,60,antialias?"X":" ", MC_Black, MC_Light);
5227 preview_is_needed=1;
5228 break;
5229
5230 case 3: // Bold
5231 is_bold = (is_bold==0);
5232 Hide_cursor();
5233 Print_in_window(191,74,is_bold?"X":" ", MC_Black, MC_Light);
5234 preview_is_needed=1;
5235 break;
5236
5237 case 4: // Italic
5238 is_italic = (is_italic==0);
5239 Hide_cursor();
5240 Print_in_window(191,88,is_italic?"X":" ", MC_Black, MC_Light);
5241 preview_is_needed=1;
5242 break;
5243
5244 case 5: // Scroller des fontes
5245 /* Cannot happen, event is catched by the list control */
5246 break;
5247
5248 case 13: // Font selection
5249 selected_font_index = Window_attribute2;
5250 Hide_cursor();
5251 preview_is_needed=1;
5252 break;
5253
5254 case 7: // Taille du texte (nombre)
5255 Readline(222,45,size_buffer,3,INPUT_TYPE_INTEGER);
5256 font_size=atoi(size_buffer);
5257 // On corrige les dimensions
5258 if (font_size < 1)
5259 {
5260 font_size = 1;
5261 }
5262 else if (font_size>500)
5263 {
5264 font_size = 500;
5265 }
5266 redraw_is_needed=1;
5267 preview_is_needed=1;
5268 break;
5269
5270 case 8: // Taille -
5271 if (font_size > 1)
5272 {
5273 font_size--;
5274 Hide_cursor();
5275 redraw_is_needed=1;
5276 preview_is_needed=1;
5277 }
5278 break;
5279
5280 case 9: // Taille +
5281 if (font_size < 255)
5282 {
5283 font_size++;
5284 Hide_cursor();
5285 redraw_is_needed=1;
5286 preview_is_needed=1;
5287 }
5288 break;
5289
5290
5291 case 6: // Double-click font selector
5292 case 11: // OK
5293 // Save the selector settings
5294 list_start = font_list->List_start;
5295 cursor_position = font_list->Cursor_position;
5296
5297 if (!new_brush)
5298 {
5299 // Si echec de rendu
5300 Close_window();
5301 Unselect_button(BUTTON_TEXT);
5302 Display_cursor();
5303 Error(0);
5304 return;
5305 }
5306 if (Realloc_brush(new_width, new_height, new_brush, NULL))
5307 {
5308 free(new_brush);
5309 Close_window();
5310 Unselect_button(BUTTON_TEXT);
5311 Display_cursor();
5312 Error(0);
5313 }
5314 // Grab palette
5315 memcpy(Brush_original_palette, text_palette,sizeof(T_Palette));
5316 // Remap to image's palette
5317 Remap_brush();
5318
5319 Brush_offset_X=Brush_width>>1;
5320 Brush_offset_Y=Brush_height>>1;
5321
5322 // Fermeture
5323 Close_window();
5324 Unselect_button(BUTTON_TEXT);
5325
5326 // On passe en brosse:
5327 Display_cursor();
5328 if (antialias || !TrueType_font(selected_font_index))
5329 Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
5330 else
5331 Change_paintbrush_shape(PAINTBRUSH_SHAPE_MONO_BRUSH);
5332 // Activate alpha mode
5333 if (antialias && TrueType_font(selected_font_index))
5334 {
5335 Shade_mode=0;
5336 Quick_shade_mode=0;
5337 Smooth_mode=0;
5338 Tiling_mode=0;
5339 Smear_mode=0;
5340 Colorize_mode=1;
5341 Colorize_current_mode=3;
5342 Effect_function=Effect_alpha_colorize;
5343
5344 Draw_menu_button(BUTTON_EFFECTS,BUTTON_PRESSED);
5345 }
5346
5347 Select_button(BUTTON_DRAW,LEFT_SIDE);
5348 if (Config.Auto_discontinuous)
5349 {
5350 // On se place en mode Dessin discontinu à la main
5351 while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
5352 Select_button(BUTTON_DRAW,RIGHT_SIDE);
5353 }
5354 //Display_cursor();
5355 return;
5356
5357 case 12: // Cancel
5358 // Save the selector settings
5359 list_start = font_list->List_start;
5360 cursor_position = font_list->Cursor_position;
5361
5362 free(new_brush);
5363 new_brush = NULL;
5364 Close_window();
5365 Unselect_button(BUTTON_TEXT);
5366 Display_cursor();
5367 return;
5368 }
5369 }
5370 }
5371
Display_stored_brush_in_window(word x_pos,word y_pos,int index)5372 void Display_stored_brush_in_window(word x_pos,word y_pos,int index)
5373 {
5374 if (Brush_container[index].Paintbrush_shape < PAINTBRUSH_SHAPE_MAX)
5375 {
5376 int x,y;
5377 int offset_x=0, offset_y=0;
5378 //int brush_offset_x=0, brush_offset_y=0;
5379
5380 // Determine draw offset (small brushes are stacked on corner of their preview)
5381 if (Brush_container[index].Width<BRUSH_CONTAINER_PREVIEW_WIDTH)
5382 offset_x = (BRUSH_CONTAINER_PREVIEW_WIDTH-Brush_container[index].Width)/2;
5383 if (Brush_container[index].Height<BRUSH_CONTAINER_PREVIEW_HEIGHT)
5384 offset_y = (BRUSH_CONTAINER_PREVIEW_HEIGHT-Brush_container[index].Height)/2;
5385 // Determine corner pixel of paintbrush to draw (if bigger than preview area)
5386 //
5387
5388 // Clear
5389 Window_rectangle(x_pos,y_pos,BRUSH_CONTAINER_PREVIEW_WIDTH,BRUSH_CONTAINER_PREVIEW_HEIGHT,MC_Light);
5390
5391 // Draw up to 16x16
5392 for (y=0; y<Brush_container[index].Height && y<BRUSH_CONTAINER_PREVIEW_HEIGHT; y++)
5393 {
5394 for (x=0; x<Brush_container[index].Width && x<BRUSH_CONTAINER_PREVIEW_WIDTH; x++)
5395 {
5396 byte color;
5397 if (Brush_container[index].Paintbrush_shape <= PAINTBRUSH_SHAPE_MISC)
5398 color = Brush_container[index].Thumbnail[y][x]?MC_Black:MC_Light;
5399 else
5400 color = Brush_container[index].Colormap[Brush_container[index].Thumbnail[y][x]];
5401 Pixel_in_window(x_pos+x+offset_x,y_pos+y+offset_y,color);
5402 }
5403 }
5404 Update_window_area(x_pos,y_pos,BRUSH_CONTAINER_PREVIEW_WIDTH,BRUSH_CONTAINER_PREVIEW_HEIGHT);
5405
5406 }
5407 }
5408
5409 /// Store the current brush in brush container
Store_brush(int index)5410 void Store_brush(int index)
5411 {
5412 if (Brush_container[index].Paintbrush_shape < PAINTBRUSH_SHAPE_MAX)
5413 {
5414 // Free previous stored brush
5415 Brush_container[index].Paintbrush_shape = PAINTBRUSH_SHAPE_MAX;
5416 free(Brush_container[index].Brush);
5417 Brush_container[index].Brush = NULL;
5418 }
5419
5420 // Store a mono brush
5421 if (Paintbrush_shape <= PAINTBRUSH_SHAPE_MISC)
5422 {
5423 int x,y;
5424 int brush_offset_x=0, brush_offset_y=0;
5425
5426 Brush_container[index].Paintbrush_shape=Paintbrush_shape;
5427 Brush_container[index].Width=Paintbrush_width;
5428 Brush_container[index].Height=Paintbrush_height;
5429 //memcpy(Brush_container[index].Palette,Main.palette,sizeof(T_Palette));
5430 // Preview: pick center for big mono brush
5431 if (Paintbrush_width>BRUSH_CONTAINER_PREVIEW_WIDTH)
5432 brush_offset_x = (Paintbrush_width-BRUSH_CONTAINER_PREVIEW_WIDTH)/2;
5433 if (Paintbrush_height>BRUSH_CONTAINER_PREVIEW_HEIGHT)
5434 brush_offset_y = (Paintbrush_height-BRUSH_CONTAINER_PREVIEW_HEIGHT)/2;
5435
5436 for (y=0; y<BRUSH_CONTAINER_PREVIEW_HEIGHT && y<Paintbrush_height; y++)
5437 for (x=0; x<BRUSH_CONTAINER_PREVIEW_WIDTH && x<Paintbrush_width; x++)
5438 Brush_container[index].Thumbnail[y][x]=Paintbrush_sprite[((y+brush_offset_y)*MAX_PAINTBRUSH_SIZE)+x+brush_offset_x];
5439 // Re-init the rest
5440 Brush_container[index].Transp_color=0;
5441 }
5442 else if (Paintbrush_shape == PAINTBRUSH_SHAPE_MONO_BRUSH &&
5443 Brush_width <= BRUSH_CONTAINER_PREVIEW_WIDTH &&
5444 Brush_height <= BRUSH_CONTAINER_PREVIEW_HEIGHT)
5445 {
5446 // Color brush transformed into a real mono paintbrush
5447 int x,y;
5448
5449 Brush_container[index].Paintbrush_shape=PAINTBRUSH_SHAPE_MISC;
5450 Brush_container[index].Width=Brush_width;
5451 Brush_container[index].Height=Brush_height;
5452 // Preview: pick center for big mono brush
5453 for (y=0; y<BRUSH_CONTAINER_PREVIEW_HEIGHT && y<Brush_height; y++)
5454 for (x=0; x<BRUSH_CONTAINER_PREVIEW_WIDTH && x<Brush_width; x++)
5455 Brush_container[index].Thumbnail[y][x]=(Brush[y*Brush_width+x]!=Back_color);
5456 // Re-init the rest
5457 Brush_container[index].Transp_color=0;
5458 }
5459 else if (Paintbrush_shape == PAINTBRUSH_SHAPE_COLOR_BRUSH ||
5460 Paintbrush_shape == PAINTBRUSH_SHAPE_MONO_BRUSH)
5461 {
5462 // Color brush : saved bitmap and palette
5463 byte * buffer;
5464 buffer=(byte *)malloc(Brush_width*Brush_height);
5465 if (buffer)
5466 {
5467 Brush_container[index].Brush=buffer;
5468 Brush_container[index].Paintbrush_shape=Paintbrush_shape;
5469 Brush_container[index].Width=Brush_width;
5470 Brush_container[index].Height=Brush_height;
5471
5472 memcpy(Brush_container[index].Brush, Brush_original_pixels,Brush_height*Brush_width);
5473 memcpy(Brush_container[index].Palette, Brush_original_palette,sizeof(T_Palette));
5474 memcpy(Brush_container[index].Colormap, Brush_colormap,256);
5475
5476 // Scale for preview
5477 if (Brush_width>BRUSH_CONTAINER_PREVIEW_WIDTH ||
5478 Brush_height>BRUSH_CONTAINER_PREVIEW_HEIGHT)
5479 {
5480 // Scale
5481 Rescale(Brush_original_pixels, Brush_width, Brush_height, (byte *)(Brush_container[index].Thumbnail), BRUSH_CONTAINER_PREVIEW_WIDTH, BRUSH_CONTAINER_PREVIEW_HEIGHT, 0, 0);
5482 }
5483 else
5484 {
5485 // Direct copy
5486 Copy_part_of_image_to_another(Brush_original_pixels, 0,0,Brush_width, Brush_height,Brush_width,(byte *)(Brush_container[index].Thumbnail),0,0,BRUSH_CONTAINER_PREVIEW_WIDTH);
5487 }
5488 }
5489 else
5490 {
5491 Error(0);
5492 }
5493 }
5494 }
5495
5496 /// Retrieve a normal paintbrush
Select_paintbrush(int index)5497 void Select_paintbrush(int index)
5498 {
5499 int x_pos,y_pos;
5500
5501 Paintbrush_shape=Paintbrush[index].Shape;
5502
5503 if (Paintbrush[index].Width<=PAINTBRUSH_WIDTH &&
5504 Paintbrush[index].Height<=PAINTBRUSH_HEIGHT)
5505 {
5506 Paintbrush_width=Paintbrush[index].Width;
5507 Paintbrush_height=Paintbrush[index].Height;
5508 Paintbrush_offset_X=Paintbrush[index].Offset_X;
5509 Paintbrush_offset_Y=Paintbrush[index].Offset_Y;
5510
5511 for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
5512 for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
5513 Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=Paintbrush[index].Sprite[y_pos][x_pos];
5514 }
5515 else
5516 {
5517 // Too big to read from the preview: need re-generate it
5518 Set_paintbrush_size(Paintbrush[index].Width,Paintbrush[index].Height);
5519 }
5520 Change_paintbrush_shape(Paintbrush[index].Shape);
5521 }
5522
5523 /// Store the current brush in paintbrush slot, if possible.
Store_paintbrush(int index)5524 byte Store_paintbrush(int index)
5525 {
5526 // Store a mono brush
5527 if (Paintbrush_shape <= PAINTBRUSH_SHAPE_MISC)
5528 {
5529 int x_pos,y_pos, x_off=0, y_off=0;
5530
5531 Paintbrush[index].Shape=Paintbrush_shape;
5532 Paintbrush[index].Width=Paintbrush_width;
5533 Paintbrush[index].Height=Paintbrush_height;
5534 Paintbrush[index].Offset_X=Paintbrush_offset_X;
5535 Paintbrush[index].Offset_Y=Paintbrush_offset_Y;
5536
5537 if (Paintbrush_width>PAINTBRUSH_WIDTH)
5538 x_off=(Paintbrush_width-PAINTBRUSH_WIDTH)/2;
5539 if (Paintbrush_height>PAINTBRUSH_HEIGHT)
5540 y_off=(Paintbrush_height-PAINTBRUSH_HEIGHT)/2;
5541
5542 for (y_pos=0; y_pos<Paintbrush_height && y_pos<PAINTBRUSH_HEIGHT; y_pos++)
5543 for (x_pos=0; x_pos<Paintbrush_width && x_pos<PAINTBRUSH_WIDTH; x_pos++)
5544 Paintbrush[index].Sprite[y_pos][x_pos]=Paintbrush_sprite[((y_pos+y_off)*MAX_PAINTBRUSH_SIZE)+(x_pos+x_off)];
5545
5546 return 0;
5547 }
5548
5549 else if ((Paintbrush_shape == PAINTBRUSH_SHAPE_MONO_BRUSH ||
5550 Paintbrush_shape == PAINTBRUSH_SHAPE_COLOR_BRUSH))
5551 {
5552 // Color brush transformed into a real mono paintbrush
5553 int x_pos,y_pos;
5554
5555 Paintbrush[index].Shape=PAINTBRUSH_SHAPE_MISC;
5556 Paintbrush[index].Width=Min(Brush_width,PAINTBRUSH_WIDTH);
5557 Paintbrush[index].Height=Min(Brush_height,PAINTBRUSH_HEIGHT);
5558 Paintbrush[index].Offset_X=Brush_offset_X*Paintbrush[index].Width/Brush_width;
5559 Paintbrush[index].Offset_Y=Brush_offset_Y*Paintbrush[index].Height/Brush_height;
5560
5561 for (y_pos=0; y_pos<Brush_height&&y_pos<PAINTBRUSH_HEIGHT; y_pos++)
5562 for (x_pos=0; x_pos<Brush_width&&x_pos<PAINTBRUSH_WIDTH; x_pos++)
5563 Paintbrush[index].Sprite[y_pos][x_pos]=Brush[(y_pos*Brush_width)+x_pos]!=Back_color;
5564
5565 return 0;
5566 }
5567 // Can't store it
5568 return 1;
5569 }
5570
Restore_brush(int index)5571 byte Restore_brush(int index)
5572 {
5573 byte shape;
5574 word x_pos;
5575 word y_pos;
5576
5577 shape = Brush_container[index].Paintbrush_shape;
5578
5579 if (shape == PAINTBRUSH_SHAPE_MAX)
5580 return 0;
5581 // Mono brushes
5582 if (shape <= PAINTBRUSH_SHAPE_MISC)
5583 {
5584 Paintbrush_shape=shape;
5585 Paintbrush_width=Brush_container[index].Width;
5586 Paintbrush_height=Brush_container[index].Height;
5587 if (shape == PAINTBRUSH_SHAPE_HORIZONTAL_BAR)
5588 Paintbrush_height=1;
5589 else if (shape == PAINTBRUSH_SHAPE_VERTICAL_BAR)
5590 Paintbrush_width=1;
5591
5592 if (Paintbrush_width <= BRUSH_CONTAINER_PREVIEW_WIDTH &&
5593 Paintbrush_height <= BRUSH_CONTAINER_PREVIEW_HEIGHT)
5594 {
5595 // Manually copy the "pixels"
5596 for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
5597 for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
5598 Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=Brush_container[index].Thumbnail[y_pos][x_pos];
5599
5600 Paintbrush_offset_X=Paintbrush_width>>1;
5601 Paintbrush_offset_Y=Paintbrush_height>>1;
5602 }
5603 else
5604 {
5605 // Recreate the brush pixels from its shape and dimensions
5606 Set_paintbrush_size(Paintbrush_width,Paintbrush_height);
5607 }
5608 }
5609 // Color brushes
5610 if (shape == PAINTBRUSH_SHAPE_COLOR_BRUSH ||
5611 shape == PAINTBRUSH_SHAPE_MONO_BRUSH)
5612 {
5613 Paintbrush_shape=shape;
5614 if (!Realloc_brush(Brush_container[index].Width,Brush_container[index].Height,NULL,NULL))
5615 {
5616 // Recover pixels
5617 memcpy(Brush_original_pixels, Brush_container[index].Brush, (long)Brush_height*Brush_width);
5618 // Grab palette
5619 memcpy(Brush_original_palette, Brush_container[index].Palette, sizeof(T_Palette));
5620 // Recover colormap
5621 memcpy(Brush_colormap, Brush_container[index].Colormap, 256);
5622 // Remap using current colormap
5623 Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
5624
5625 Brush_offset_X=Brush_width>>1;
5626 Brush_offset_Y=Brush_height>>1;
5627 }
5628
5629 }
5630 Change_paintbrush_shape(shape);
5631
5632 return 1;
5633 }
5634
Button_Brush_container(void)5635 void Button_Brush_container(void)
5636 {
5637 short clicked_button;
5638 short x_pos,y_pos;
5639 byte index;
5640
5641 Open_window(BRUSH_CONTAINER_COLUMNS*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+8,
5642 BRUSH_CONTAINER_ROWS*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+40,
5643 "Brushes");
5644
5645 Window_set_normal_button(
5646 (BRUSH_CONTAINER_COLUMNS*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)-59)/2,
5647 (BRUSH_CONTAINER_ROWS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18,
5648 67,14,"Cancel",0,1,KEY_ESC); // 1
5649
5650 index=0;
5651 for (index=0; index < BRUSH_CONTAINER_ROWS*BRUSH_CONTAINER_COLUMNS; index++)
5652 {
5653 x_pos = (index % BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+7;
5654 y_pos = (index / BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18;
5655 Window_set_normal_button(
5656 x_pos,
5657 y_pos,
5658 BRUSH_CONTAINER_PREVIEW_WIDTH+2,
5659 BRUSH_CONTAINER_PREVIEW_HEIGHT+2,
5660 "",0,1,KEY_NONE
5661 );
5662 Display_stored_brush_in_window(x_pos+1, y_pos+1, index);
5663 }
5664 Update_window_area(0,0,Window_width, Window_height);
5665
5666 Display_cursor();
5667
5668 do
5669 {
5670 clicked_button=Window_clicked_button();
5671 //if (Is_shortcut(Key,0x100+BUTTON_HELP))
5672 // Window_help(BUTTON_PAINTBRUSHES, NULL);
5673
5674 if (clicked_button == 1)
5675 break;
5676
5677 if (clicked_button>1)
5678 {
5679 index = clicked_button-2;
5680
5681 if (Window_attribute1==RIGHT_SIDE)
5682 {
5683 // Store
5684
5685 x_pos = (index % BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+7;
5686 y_pos = (index / BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18;
5687
5688 Store_brush(index);
5689 Hide_cursor();
5690 Display_stored_brush_in_window(x_pos+1, y_pos+1, index);
5691 Display_cursor();
5692 }
5693 else
5694 {
5695 // Restore and exit
5696
5697 if (Restore_brush(index))
5698 break;
5699 }
5700 }
5701 }
5702 while (1);
5703 Close_window();
5704
5705 //Unselect_button(BUTTON_PAINTBRUSHES);
5706 Display_cursor();
5707 }
5708
Any_effect_active(void)5709 byte Any_effect_active(void)
5710 {
5711 return Shade_mode||Quick_shade_mode||Colorize_mode||Smooth_mode||Tiling_mode||Smear_mode
5712 ||Stencil_mode||Mask_mode||Sieve_mode||Snap_mode||Main.tilemap_mode || (Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION);
5713 }
5714