/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright owned by various GrafX2 authors, see COPYRIGHT.txt for details.
Grafx2 is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.
Grafx2 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Grafx2; if not, see
*/
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include
#include
#endif
#include
#include
#include
#if !defined(_MSC_VER)
#include
#else
#define strdup _strdup
#define strncasecmp _strnicmp
#if _MSC_VER < 1900
#define snprintf _snprintf
#endif
#endif
#include
#if !defined(__VBCC__) && !defined(_MSC_VER)
#include
#endif
#include
#include
#include "const.h"
#include "struct.h"
#include "global.h"
#include "misc.h"
#include "osdep.h"
#include "graph.h"
#include "engine.h"
#include "readline.h"
#include "filesel.h"
#include "fileseltools.h"
#include "loadsave.h"
#include "init.h"
#include "buttons.h"
#include "operatio.h"
#include "pages.h"
#include "palette.h"
#include "errors.h"
#include "readini.h"
#include "saveini.h"
#include "shade.h"
#include "io.h"
#include "help.h"
#include "text.h"
#include "screen.h"
#include "windows.h"
#include "brush.h"
#include "input.h"
#include "special.h"
#include "tiles.h"
#include "setup.h"
#include "unicode.h"
#include "keycodes.h"
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include
#include
#elif defined(__MINT__)
#include
#include
#elif defined(WIN32)
#ifndef _MSC_VER
#include
#endif
#else
#include
#endif
extern char Program_version[]; // generated in pversion.c
extern short Old_MX;
extern short Old_MY;
//-- MODELE DE BOUTON DE MENU ------------------------------------------------
/*
void Bouton_***(void)
{
short clicked_button;
Open_window(310,190,"***");
Window_set_normal_button(103,137,80,14,"OK",0,1,KEY_RETURN); // 1
Window_set_scroller_button(18,44,88,16,4,0); // 2
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
}
while (clicked_button!=1);
Close_window();
Unselect_button(BOUTON_***);
Display_cursor();
}
*/
void Message_out_of_memory(void)
{
short clicked_button;
Open_window(216,76,"Not enough memory!");
Print_in_window(8,20,"Please consult the manual",MC_Black,MC_Light);
Print_in_window(24,28,"to know how to obtain",MC_Black,MC_Light);
Print_in_window(36,36,"more memory space.",MC_Black,MC_Light);
Window_set_normal_button(60,53,40,14,"OK",1,1,KEY_RETURN); // 1
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
clicked_button=Window_clicked_button();
while ((clicked_button<=0) && (Key!=KEY_ESC) && (Key!=KEY_o));
if(clicked_button<=0) Key=0;
Close_window();
Display_cursor();
}
void Button_Message_initial(void)
{
char str[30];
int x_pos,offs_y,x,y;
int clicked_button=0;
snprintf(str,sizeof(str),"GrafX2 version %s",Program_version);
Open_window(260,172,str);
Window_display_frame_in(10,20,239,62);
Window_rectangle(11,21,237,60,MC_Black);
for (y=23,offs_y=0; y<79; offs_y+=231,y++)
for (x=14,x_pos=0; x_pos<231; x_pos++,x++)
Pixel_in_window(x,y,Gfx->Logo_grafx2[offs_y+x_pos]);
Print_in_window(130-4*26,88,"Copyright (c) 2007-2020 by",MC_Dark,MC_Light);
Print_in_window(130-4*23,100,"the Grafx2 project team",MC_Black,MC_Light);
Print_in_window(130-4*26,112,"Copyright (c) 1996-2001 by",MC_Dark,MC_Light);
Print_in_window(130-4*13,122,"Sunset Design",MC_Black,MC_Light);
//Print_in_window( 120-4*13,128,"(placeholder)",MC_Dark,MC_Light);
Print_in_window(130-4*16,136,"http://grafx2.tk",MC_Dark,MC_Light);
Window_set_normal_button(56, 151, 71, 14, "Anim", 1, (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION), KEY_a);
Window_set_normal_button(133, 151, 71, 14, "Layers", 1, (Main.backups->Pages->Image_mode != IMAGE_MODE_LAYERED), KEY_l);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
while(!Mouse_K && !Key && !Quit_is_required)
Get_input(20);
if (Mouse_K)
{
clicked_button = Window_get_clicked_button();
Wait_end_of_click();
}
else
clicked_button = Window_get_button_shortcut();
GFX2_Log(GFX2_DEBUG, "Button_Message_initial() clicked_button=%d\n", clicked_button);
Close_window();
if (clicked_button > 0)
{
if (Main.backups->Pages->Image_mode == IMAGE_MODE_LAYERED)
{
Switch_layer_mode(IMAGE_MODE_ANIMATION);
Config.Default_mode_layers = 0;
}
else
{
Switch_layer_mode(IMAGE_MODE_LAYERED);
Config.Default_mode_layers = 1;
}
if (Check_menu_mode())
{
Display_menu();
Display_all_screen();
}
// Modify the mode for the spare too
Spare.backups->Pages->Image_mode = Main.backups->Pages->Image_mode;
Update_spare_buffers(Spare.image_width,Spare.image_height);
Redraw_spare_image();
}
Display_cursor();
}
void Change_paintbrush_shape(byte shape)
{
Paintbrush_shape=shape;
Display_paintbrush_in_menu();
switch (Current_operation)
{
case OPERATION_FILL :
Paintbrush_shape_before_fill=shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
break;
case OPERATION_COLORPICK :
Paintbrush_shape_before_colorpicker=shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_NONE;
break;
// Note: Il existe un Paintbrush_shape_before_lasso, mais comme le lasso aura
// été automatiquement désactivé avant d'arriver ici, y'a pas de problème.
}
}
//-------------------------------- UNDO/REDO ---------------------------------
void Button_Undo(int btn)
{
Hide_cursor();
Undo();
Set_palette(Main.palette);
Compute_optimal_menu_colors(Main.palette);
Check_menu_mode();
Display_all_screen();
Unselect_button(btn);
Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
Display_menu();
Display_cursor();
}
void Button_Redo(int btn)
{
Hide_cursor();
Redo();
Set_palette(Main.palette);
Compute_optimal_menu_colors(Main.palette);
Check_menu_mode();
Display_all_screen();
Unselect_button(btn);
Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
Display_menu();
Display_cursor();
}
//---------------------------- SCROLL PALETTE LEFT ---------------------------
void Button_Pal_left(int btn)
{
short cells;
cells = (Config.Palette_vertical)?Palette_cells_X():Palette_cells_Y();
Hide_cursor();
if (First_color_in_palette)
{
if (First_color_in_palette>=cells)
First_color_in_palette-=cells;
else
First_color_in_palette=0;
Display_menu_palette();
}
Unselect_button(btn);
Display_cursor();
}
void Button_Pal_left_fast(int btn)
{
short cells_x = Palette_cells_X();
short cells_y = Palette_cells_Y();
Hide_cursor();
if (First_color_in_palette)
{
if (First_color_in_palette>=cells_y*cells_x)
First_color_in_palette-=cells_y*cells_x;
else
First_color_in_palette=0;
Display_menu_palette();
}
Unselect_button(btn);
Display_cursor();
}
//--------------------------- SCROLL PALETTE RIGHT ---------------------------
void Button_Pal_right(int btn)
{
short cells;
cells = (Config.Palette_vertical)?Palette_cells_X():Palette_cells_Y();
Hide_cursor();
if ((int)First_color_in_palette+Palette_cells_X()*Palette_cells_Y()<256)
{
First_color_in_palette+=cells;
Display_menu_palette();
}
Unselect_button(btn);
Display_cursor();
}
void Button_Pal_right_fast(int btn)
{
short cells_x = Palette_cells_X();
short cells_y = Palette_cells_Y();
Hide_cursor();
if ((int)First_color_in_palette+cells_y*cells_x<256)
{
if ((int)First_color_in_palette+(cells_y)*cells_x*2<256)
First_color_in_palette+=cells_x*cells_y;
else
{
if (Config.Palette_vertical)
First_color_in_palette=255/cells_x*cells_x-(cells_y-1)*cells_x;
else
First_color_in_palette=255/cells_y*cells_y-(cells_x-1)*cells_y;
}
Display_menu_palette();
}
Unselect_button(btn);
Display_cursor();
}
//-------------------- item de la forecolor dans le menu --------------------
void Button_Select_forecolor(int btn)
{
static long time_click = 0;
long time_previous;
int color;
time_previous = time_click;
time_click = GFX2_GetTicks();
color=Pick_color_in_palette();
if (color == Fore_color)
{
// Check if it's a double-click
if (time_click - time_previous < Config.Double_click_speed)
{
// Open palette window
Button_Palette(btn);
return;
}
}
do
{
if (color != Fore_color && color!=-1)
{
Hide_cursor();
Set_fore_color(color);
Display_cursor();
}
// Wait loop after initial click
while(Mouse_K)
{
Get_input(20);
if (Button_under_mouse()==btn)
{
color=Pick_color_in_palette();
if (color != Fore_color && color!=-1)
{
Hide_cursor();
Status_print_palette_color(color);
Set_fore_color(color);
Display_cursor();
}
}
}
} while(Mouse_K);
}
//-------------------- item de la backcolor dans le menu --------------------
void Button_Select_backcolor(int btn)
{
int color;
do
{
color=Pick_color_in_palette();
if (color!=-1 && color != Back_color)
{
Hide_cursor();
Status_print_palette_color(color);
Set_back_color(color);
Display_cursor();
}
// Wait loop after initial click
do
{
Get_input(20);
if (Button_under_mouse()==btn)
break; // This will repeat this button's action
} while(Mouse_K);
} while(Mouse_K);
}
void Button_Hide_menu(int btn)
{
Hide_cursor();
if (Menu_is_visible)
{
Menu_is_visible=0;
Menu_Y=Screen_height;
if (Main.magnifier_mode)
{
Compute_magnifier_data();
}
// On repositionne le décalage de l'image pour qu'il n'y ait pas d'in-
// -cohérences lorsqu'on sortira du mode Loupe.
if (Main.offset_Y+Screen_height>Main.image_height)
{
if (Screen_height>Main.image_height)
Main.offset_Y=0;
else
Main.offset_Y=Main.image_height-Screen_height;
}
// On fait pareil pour le brouillon
if (Spare.offset_Y+Screen_height>Spare.image_height)
{
if (Screen_height>Spare.image_height)
Spare.offset_Y=0;
else
Spare.offset_Y=Spare.image_height-Screen_height;
}
Compute_magnifier_data();
if (Main.magnifier_mode)
Position_screen_according_to_zoom();
Compute_limits();
Compute_paintbrush_coordinates();
Display_all_screen();
}
else
{
byte current_menu;
Menu_is_visible=1;
Menu_Y=Screen_height;
for (current_menu = 0; current_menu < MENUBAR_COUNT; current_menu++)
if (Menu_bars[current_menu].Visible)
Menu_Y -= Menu_bars[current_menu].Height * Menu_factor_Y;
Compute_magnifier_data();
if (Main.magnifier_mode)
Position_screen_according_to_zoom();
Compute_limits();
Compute_paintbrush_coordinates();
Display_menu();
if (Main.magnifier_mode)
Display_all_screen();
}
Unselect_button(btn);
Display_cursor();
}
void Button_Toggle_toolbar(int btn)
{
T_Dropdown_button dropdown;
T_Dropdown_choice *item;
static char menu_name_tools[9] = " Tools";
static char menu_name_layers[9]= " Layers";
static char menu_name_anim[9] = " Anim";
menu_name_tools[0] = Menu_bars[MENUBAR_TOOLS ].Visible ? 22 : ' ';
menu_name_layers[0] = Menu_bars[MENUBAR_LAYERS].Visible ? 22 : ' ';
menu_name_anim[0] = Menu_bars[MENUBAR_ANIMATION].Visible ? 22 : ' ';
Hide_cursor();
dropdown.Pos_X =Buttons_Pool[BUTTON_HIDE].X_offset;
dropdown.Pos_Y =Buttons_Pool[BUTTON_HIDE].Y_offset;
dropdown.Height =Buttons_Pool[BUTTON_HIDE].Height;
dropdown.Dropdown_width=70;
dropdown.First_item =NULL;
dropdown.Bottom_up =1;
Window_dropdown_add_item(&dropdown, 0, menu_name_tools);
if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION ||
Main.backups->Pages->Nb_layers==1)
Window_dropdown_add_item(&dropdown, 1, menu_name_layers);
if (Main.backups->Pages->Image_mode == IMAGE_MODE_ANIMATION ||
(Main.backups->Pages->Image_mode == IMAGE_MODE_LAYERED && Main.backups->Pages->Nb_layers==1))
Window_dropdown_add_item(&dropdown, 2, menu_name_anim);
item=Dropdown_activate(&dropdown,0,Menu_Y+Menu_bars[MENUBAR_STATUS].Top*Menu_factor_Y);
if (item)
{
switch (item->Number)
{
case 0: // tools
Set_bar_visibility(MENUBAR_TOOLS, !Menu_bars[MENUBAR_TOOLS].Visible, 0);
break;
case 1: // layers
if (Menu_bars[MENUBAR_ANIMATION].Visible)
{
Set_bar_visibility(MENUBAR_ANIMATION, 0, 0);
Config.Default_mode_layers=1;
}
Set_bar_visibility(MENUBAR_LAYERS, !Menu_bars[MENUBAR_LAYERS].Visible, 0);
if (Main.backups->Pages->Image_mode == IMAGE_MODE_ANIMATION)
Switch_layer_mode(IMAGE_MODE_LAYERED);
break;
case 2: // anim
if (Menu_bars[MENUBAR_LAYERS].Visible)
{
Set_bar_visibility(MENUBAR_LAYERS, 0, 0);
Config.Default_mode_layers=0;
}
Set_bar_visibility(MENUBAR_ANIMATION, !Menu_bars[MENUBAR_ANIMATION].Visible, 0);
if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
Switch_layer_mode(IMAGE_MODE_ANIMATION);
break;
}
// redraw image and menu
Display_menu();
Display_all_screen();
}
// Closing
Window_dropdown_clear_items(&dropdown);
Unselect_button(btn);
Display_cursor();
}
void Button_Toggle_all_toolbars(int btn)
{
// This is used to memorize the bars' visibility when temporarily hidden
static word Last_visibility = 0xFFFF;
int i;
word current_visibility;
Hide_cursor();
// Check which bars are visible
current_visibility=0;
for (i=MENUBAR_STATUS+1;iPages->File_directory, Main.backups->Pages->Filename);
exists = File_exists(filename);
free(filename);
if ( !exists || Confirmation_box("Erase old file ?") )
{
T_IO_Context save_context;
Hide_cursor();
old_cursor_shape=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Init_context_layered_image(&save_context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
save_context.File_name_unicode = Main.backups->Pages->Filename_unicode;
Save_image(&save_context);
Destroy_context(&save_context);
Hide_cursor();
Cursor_shape=old_cursor_shape;
Display_cursor();
if (!File_error)
// L'ayant sauvée avec succès,
return 1; // On peut quitter
else
// Il y a eu une erreur lors de la sauvegarde,
return 0; // On ne peut donc pas quitter
}
else
// L'utilisateur ne veut pas écraser l'ancien fichier,
return 0; // On doit donc rester
case 3 : return 1; // Quitter
}
return 0;
}
void Button_Quit(int btn)
{
//short clicked_button;
if (Button_Quit_local_function())
{
if (Spare.image_is_modified)
{
Button_Page(BUTTON_PAGE); // On passe sur le brouillon
// Si l'utilisateur présente les derniers symptomes de l'abandon
if (Button_Quit_local_function())
Quitting=1;
}
else
Quitting=1;
}
if ( (Menu_is_visible) && (Mouse_Y+8>Menu_Y) )
Hide_cursor();
Unselect_button(btn);
if ( (Menu_is_visible) && (Mouse_Y+8>Menu_Y) )
Display_cursor();
}
//---------------------------- Effacer l'écran -------------------------------
void Button_Clear(int btn)
{
Hide_cursor();
Backup();
if (Stencil_mode && Config.Clear_with_stencil)
Clear_current_image_with_stencil(Main.backups->Pages->Transparent_color,Stencil);
else
Clear_current_image(Main.backups->Pages->Transparent_color);
Redraw_layered_image();
End_of_modification();
Display_all_screen();
Unselect_button(btn);
Display_cursor();
}
void Button_Clear_with_backcolor(int btn)
{
Hide_cursor();
Backup();
if (Stencil_mode && Config.Clear_with_stencil)
Clear_current_image_with_stencil(Back_color,Stencil);
else
Clear_current_image(Back_color);
Redraw_layered_image();
End_of_modification();
Display_all_screen();
Unselect_button(btn);
Display_cursor();
}
//------------------------------- Paramètres ---------------------------------
#define SETTING_PER_PAGE 11
#define SETTING_PAGES 5
#define SETTING_HEIGHT 12
typedef struct {
const char* Label; // Use NULL label to stop an array
int Code;
} T_Lookup;
const T_Lookup Lookup_YesNo[] = {
{"NO",0},
{"YES",1},
{NULL,-1},
};
const T_Lookup Lookup_FFF[] = {
{"All",0},
{"Files",1},
{"Dirs.",2},
{NULL,-1},
};
const T_Lookup Lookup_AutoRes[] = {
{"Internal",1},
{"Real",2},
{NULL,-1},
};
const T_Lookup Lookup_Coords[] = {
{"Relative",1},
{"Absolute",2},
{NULL,-1},
};
const T_Lookup Lookup_MenuRatio[] = {
{"None",0},
{"x2",254}, // -2
{"x3",253}, // -3
{"x4",252}, // -4
{"Moderate",2},
{"Maximum",1},
{NULL,-1},
};
const T_Lookup Lookup_MouseSpeed[] = {
{"Normal",1},
{"/2",2},
{"/3",3},
{"/4",4},
{NULL,-1},
};
const T_Lookup Lookup_SwapButtons[] = {
{"None",0},
{"Control",GFX2_MOD_CTRL},
{"Alt",GFX2_MOD_ALT},
{NULL,-1},
};
const T_Lookup Lookup_VirtualKeyboard[] = {
{"Auto",0},
{"ON",1},
{"OFF",2},
{NULL,-1},
};
typedef struct {
const char* Label;
byte Type; // 0: label, 1+: setting (size in bytes)
void * Value;
int Min_value;
int Max_value;
int Digits; // Could be computed from Max_value...but don't bother.
const T_Lookup * Lookup;
} T_Setting;
long int Get_setting_value(const T_Setting *item)
{
switch(item->Type)
{
case 1:
return *((byte *)(item->Value));
break;
case 2:
return *((word *)(item->Value));
break;
case 4:
default:
return *((long int *)(item->Value));
break;
}
}
void Set_setting_value(const T_Setting *item, long int value)
{
switch(item->Type)
{
case 1:
*((byte *)(item->Value)) = value;
break;
case 2:
*((word *)(item->Value)) = value;
break;
case 4:
default:
*((long int *)(item->Value)) = value;
break;
}
}
// Fetch a label in a lookup table. Unknown values get label 0.
const char *Lookup_code(int code, const T_Lookup *lookup)
{
int i;
for(i=0; lookup[i].Label!=NULL; i++)
{
if (lookup[i].Code == code)
return lookup[i].Label;
}
return lookup[0].Label;
}
/// Increase an enum to next-higher value (wrapping).
int Lookup_next(int code, const T_Lookup *lookup)
{
int i;
for(i=0; lookup[i].Label!=NULL; i++)
{
if (lookup[i].Code == code)
{
if (lookup[i+1].Label==NULL)
return lookup[0].Code;
return lookup[i+1].Code;
}
}
return 0;
}
/// Decrease an enum to previous value (wrapping).
int Lookup_previous(int code, const T_Lookup *lookup)
{
int count;
int current=-1;
for(count=0; lookup[count].Label!=NULL; count++)
{
if (lookup[count].Code == code)
current=count;
}
return lookup[(current + count - 1) % count].Code;
}
void Settings_display_config(const T_Setting *setting, T_Config * conf, T_Special_button *panel)
{
int i;
// A single button
Print_in_window(155,166,(conf->Auto_save)?"YES":" NO",MC_Black,MC_Light);
// Clear all
Window_rectangle(panel->Pos_X, panel->Pos_Y, panel->Width, panel->Height+1, MC_Light);
for (i=0; iPos_X+3, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, setting[i].Label, i==0?MC_White:MC_Dark, MC_Light);
if(setting[i].Value)
{
int value = Get_setting_value(&setting[i]);
if (setting[i].Lookup)
{
// Use a lookup table to print a label
const char *str;
str = Lookup_code(value,setting[i].Lookup);
Print_in_window(panel->Pos_X+3+176, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, str, MC_Black, MC_Light);
}
else
{
// Print a number
char str[10];
Num2str(value,str,setting[i].Digits);
Print_in_window(panel->Pos_X+3+176, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, str, MC_Black, MC_Light);
}
}
}
Update_window_area(panel->Pos_X, panel->Pos_Y, panel->Width, panel->Height+1);
}
void Settings_save_config(T_Config * conf)
{
if (Save_CFG())
Error(0);
else
if (Save_INI(conf))
Error(0);
}
void Settings_load_config(T_Config * conf)
{
if (Load_CFG(0))
Error(0);
else
if (Load_INI(conf))
Error(0);
}
void Button_Settings(int btn)
{
short clicked_button;
T_Config selected_config;
byte config_is_reloaded=0;
T_Special_button *panel;
byte need_redraw=1;
static byte current_page=0;
// Definition of settings pages
// Label,Type (0 = label, 1+ = setting size in bytes),
// Value, min, max, digits, Lookup)
const T_Setting setting[SETTING_PER_PAGE*SETTING_PAGES] = {
{" --- GUI ---",0,NULL,0,0,0,NULL},
{"Opening message:",1,&(selected_config.Opening_message),0,1,0,Lookup_YesNo},
{"Menu ratio adapt:",1,&(selected_config.Ratio),0,1,0,Lookup_MenuRatio},
{"Draw limits:",1,&(selected_config.Display_image_limits),0,1,0,Lookup_YesNo},
{"Coordinates:",1,&(selected_config.Coords_rel),0,1,0,Lookup_Coords},
{"Separate colors:",1,&(selected_config.Separate_colors),0,1,0,Lookup_YesNo},
{"Safety colors:",1,&(selected_config.Safety_colors),0,1,0,Lookup_YesNo},
{"Sync views:",1,&(selected_config.Sync_views),0,1,0,Lookup_YesNo},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{" --- Input ---",0,NULL,0,0,0,NULL},
{"Scrollbar speed",0,NULL,0,0,0,NULL},
{" on left click:",1,&(selected_config.Delay_left_click_on_slider),1,255,4,NULL},
{" on right click:",1,&(selected_config.Delay_right_click_on_slider),1,255,4,NULL},
{"Merge movement:",1,&(selected_config.Mouse_merge_movement),0,100,4,NULL},
{"Double click speed:",2,&(selected_config.Double_click_speed),1,1999,4,NULL},
{"Double key speed:",2,&(selected_config.Double_key_speed),1,1999,4,NULL},
//{"Mouse speed (fullscreen)",0,NULL,0,0,0,NULL},
//{" horizontally:",1,&(selected_config.Mouse_sensitivity_index_x),1,4,0,Lookup_MouseSpeed},
//{" vertically:",1,&(selected_config.Mouse_sensitivity_index_y),1,4,0,Lookup_MouseSpeed},
{"Key to swap buttons:",2,&(selected_config.Swap_buttons),0,0,0,Lookup_SwapButtons},
{"Virtual keyboard",1,&(selected_config.Use_virtual_keyboard),0,2,0,Lookup_VirtualKeyboard},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{" --- Editing ---",0,NULL,0,0,0,NULL},
{"Adjust brush pick:",1,&(selected_config.Adjust_brush_pick),0,1,0,Lookup_YesNo},
{"Undo pages:",1,&(selected_config.Max_undo_pages),1,99,5,NULL},
{"Vertices per polygon:",4,&(selected_config.Nb_max_vertices_per_polygon),2,16384,5,NULL},
{"Fast zoom:",1,&(selected_config.Fast_zoom),0,1,0,Lookup_YesNo},
{"Clear with stencil:",1,&(selected_config.Clear_with_stencil),0,1,0,Lookup_YesNo},
{"Auto discontinuous:",1,&(selected_config.Auto_discontinuous),0,1,0,Lookup_YesNo},
{"Auto count colors:",1,&(selected_config.Auto_nb_used),0,1,0,Lookup_YesNo},
{"Right click colorpick:",1,&(selected_config.Right_click_colorpick),0,1,0,Lookup_YesNo},
{"Multi shortcuts:",1,&(selected_config.Allow_multi_shortcuts),0,1,0,Lookup_YesNo},
{"",0,NULL,0,0,0,NULL},
{" --- File selector ---",0,NULL,0,0,0,NULL},
{"Show in fileselector",0,NULL,0,0,0,NULL},
{" Hidden files:",4,&(selected_config.Show_hidden_files),0,1,0,Lookup_YesNo},
{" Hidden dirs:",4,&(selected_config.Show_hidden_directories),0,1,0,Lookup_YesNo},
{"Preview delay:",4,&(selected_config.Timer_delay), 1,256,3,NULL},
{"Maximize preview:",1,&(selected_config.Maximize_preview), 0,1,0,Lookup_YesNo},
{"Find file fast:",1,&(selected_config.Find_file_fast), 0,2,0,Lookup_FFF},
{"Auto set resolution:",1,&(selected_config.Auto_set_res), 0,1,0,Lookup_YesNo},
{" According to:",1,&(selected_config.Set_resolution_according_to), 1,2,0,Lookup_AutoRes},
{"Backup:",1,&(selected_config.Backup), 0,1,0,Lookup_YesNo},
{"",0,NULL,0,0,0,NULL},
{" --- Format options ---",0,NULL,0,0,0,NULL},
{"Screen size in GIF:",1,&(selected_config.Screen_size_in_GIF),0,1,0,Lookup_YesNo},
{"Clear palette:",1,&(selected_config.Clear_palette),0,1,0,Lookup_YesNo},
{"MO6/TO8 palette gamma",1,&(selected_config.MOTO_gamma),10,30,2,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
};
const char * help_section[SETTING_PAGES] = {
"GUI",
"INPUT",
"EDITING",
"FILE SELECTOR",
"FILE FORMAT OPTIONS",
};
selected_config=Config;
Open_window(307,182,"Settings");
// Button Reload
Window_set_normal_button( 6,163, 51,14,"Reload" ,1,1,KEY_r); // 1
// Button Auto-save
Window_set_normal_button( 73,163,107,14,"Auto-save: ",1,1,KEY_a); // 2
// Button Save
Window_set_normal_button(183,163, 51,14,"Save" ,1,1,KEY_s); // 3
// Button Close
Window_set_normal_button(250,163, 51,14,"Close" ,0,1,KEY_ESC); // 4
panel=Window_set_special_button(10, 21, 272,SETTING_PER_PAGE*SETTING_HEIGHT,0); // 5
Window_set_scroller_button(285,21,SETTING_PER_PAGE*SETTING_HEIGHT,SETTING_PAGES,1,current_page); // 6
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
if (need_redraw)
{
Hide_cursor();
Settings_display_config(setting+current_page*SETTING_PER_PAGE, &selected_config, panel);
if (need_redraw & 2)
{
// Including slider position
Window_scroller_button_list->Position=current_page;
Window_draw_slider(Window_scroller_button_list);
}
Display_cursor();
need_redraw=0;
}
clicked_button=Window_clicked_button();
switch(clicked_button)
{
case 1 : // Reload
Settings_load_config(&selected_config);
config_is_reloaded=1;
need_redraw=1;
break;
case 2 : // Auto-save
selected_config.Auto_save=!selected_config.Auto_save;
need_redraw=1;
break;
case 3 : // Save
Settings_save_config(&selected_config);
break;
// case 4: // Close
case 5: // Panel area
{
int num=(((short)Mouse_Y-Window_pos_Y)/Menu_factor_Y - panel->Pos_Y)/SETTING_HEIGHT;
if (num >= 0 && num < SETTING_PER_PAGE)
{
const T_Setting * item = &setting[current_page*SETTING_PER_PAGE+num];
if (item->Type!=0)
{
// Remember which button is clicked
byte old_mouse_k = Mouse_K;
if (Window_normal_button_onclick(panel->Pos_X, panel->Pos_Y+num*SETTING_HEIGHT, panel->Width, SETTING_HEIGHT+1, 5))
{
int value = Get_setting_value(item);
if (item->Lookup)
{
// Enum: toggle it
if (old_mouse_k & LEFT_SIDE)
value = Lookup_next(value, item->Lookup);
else
value = Lookup_previous(value, item->Lookup);
Set_setting_value(item, value);
}
else
{
// Numeric: edit it
char str[10];
str[0]='\0';
if (! (old_mouse_k & RIGHT_SIDE))
Num2str(value,str,item->Digits+1);
if (Readline(panel->Pos_X+3+176, panel->Pos_Y+num*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2,str,item->Digits+1,INPUT_TYPE_INTEGER))
{
value=atoi(str);
if (valueMin_value)
value = item->Min_value;
else if (value>item->Max_value)
value = item->Max_value;
Set_setting_value(item, value);
}
Key=0; // Need to discard keys used during editing
}
}
}
}
}
need_redraw=1;
break;
case 6: // Scroller
current_page = Window_attribute2;
need_redraw=1;
break;
}
if (Key == KEY_MOUSEWHEELDOWN)
{
if (current_page < (SETTING_PAGES-1))
{
current_page++;
need_redraw=2;
}
}
else if (Key == KEY_MOUSEWHEELUP)
{
if (current_page > 0)
{
current_page--;
need_redraw=2;
}
}
else if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(NB_BUTTONS+0, help_section[current_page]);
else if (Is_shortcut(Key,0x100+BUTTON_SETTINGS))
clicked_button=4;
}
while ( (clicked_button!=4) && (Key!=KEY_RETURN) && !Quit_is_required);
// Checks on change
if (Config.Show_hidden_directories!=selected_config.Show_hidden_directories
||Config.Show_hidden_files!=selected_config.Show_hidden_files)
{
// Reset fileselector offsets
// since different files are shown now
Main.selector.Position=0;
Main.selector.Offset=0;
Spare.selector.Position=0;
Spare.selector.Offset=0;
Brush_selector.Position=0;
Brush_selector.Offset=0;
Palette_selector.Position=0;
Palette_selector.Offset=0;
}
if(Config.Allow_multi_shortcuts && !selected_config.Allow_multi_shortcuts)
{
// User just disabled multi shortcuts: make them unique now.
Remove_duplicate_shortcuts();
}
// Copy all
Config=selected_config;
if (config_is_reloaded)
Compute_optimal_menu_colors(Main.palette);
Close_window();
Unselect_button(btn);
// Raffichage du menu pour que les inscriptions qui y figurent soient
// retracées avec la nouvelle fonte
Display_menu();
Display_cursor();
// On vérifie qu'on peut bien allouer le nombre de pages Undo.
Set_number_of_backups(Config.Max_undo_pages);
}
// Data for skin selector
T_Fileselector Skin_files_list;
// Data for font selector
T_Fileselector Font_files_list;
//
char * Format_font_filename(const char * fname)
{
static char result[12];
int c;
int length;
fname+=strlen(FONT_PREFIX); // Omit file prefix
length=strlen(fname) - 4; // assume .png extension
for (c=0;c<11 && c11)
result[10] = ELLIPSIS_CHARACTER;
return result;
}
// Add a skin to the list
static void Add_font_or_skin(const char * full_name, const char * fname)
{
size_t namelength;
(void)full_name;
namelength = strlen(fname);
if (namelength>=10 && fname[0]!='_' && !strncasecmp(fname, SKIN_PREFIX, strlen(SKIN_PREFIX))
&& (!strcasecmp(fname + namelength - 4,".png")
|| !strcasecmp(fname + namelength - 4,".gif")))
{
Add_element_to_list(&Skin_files_list, fname, Format_filename(fname, 19, 0), FSOBJECT_FILE, ICON_NONE);
if (fname[0]=='\0')
return;
}
else if (namelength>=10 && !strncasecmp(fname, FONT_PREFIX, strlen(FONT_PREFIX))
&& (!strcasecmp(fname + namelength - 4, ".png")))
{
Add_element_to_list(&Font_files_list, fname, Format_font_filename(fname), FSOBJECT_FILE, ICON_NONE);
if (fname[0]=='\0')
return;
}
}
// Callback to display a skin name in the list
void Draw_one_skin_name(word x, word y, word index, byte highlighted)
{
T_Fileselector_item * current_item;
if (Skin_files_list.Nb_elements)
{
current_item = Get_item_by_index(&Skin_files_list, index);
Print_in_window(x, y, current_item->Short_name, MC_Black,
(highlighted)?MC_Dark:MC_Light);
}
}
/// Skin selector window
void Button_Skins(int btn)
{
short clicked_button;
short temp;
char * skinsdir;
T_Dropdown_button * font_dropdown;
T_Dropdown_button * cursor_dropdown;
T_List_button * skin_list;
T_Scroller_button * file_scroller;
int selected_font = 0;
int selected_cursor = Config.Cursor;
byte separatecolors = Config.Separate_colors;
byte showlimits = Config.Display_image_limits;
byte need_load=1;
int button;
word x, y, x_pos, offs_y;
const char * cursors[] = { "Solid", "Transparent", "Thin" };
T_Gui_skin * gfx = NULL;
byte * new_font;
#define FILESEL_Y 34
// --- Read the contents of skins/ directory ------------------
// Here we use the same data container as the fileselectors.
// Reinitialize the list
Free_fileselector_list(&Skin_files_list);
Free_fileselector_list(&Font_files_list);
// Browse the "skins" directory
skinsdir = Filepath_append_to_dir(Data_directory, SKINS_SUBDIRECTORY);
// Add each found file to the list
For_each_file(skinsdir, Add_font_or_skin);
// Sort it
Sort_list_of_files(&Skin_files_list);
Sort_list_of_files(&Font_files_list);
selected_font = Find_file_in_fileselector(&Font_files_list, Config.Font_file);
if (selected_font < 0)
selected_font = 0;
// --------------------------------------------------------------
Open_window(290, 140, "Skins");
// Frames
Window_display_frame_in(6, FILESEL_Y - 2, 148, 84); // File selector
// Texts
Print_in_window( 172, 33,"Font:" ,MC_Black,MC_Light);
Print_in_window( 172, 59,"Cursor:" ,MC_Black,MC_Light);
// Ok button
Window_set_normal_button(6, 120, 51, 14, "OK", 0, 1, KEY_RETURN); // 1
// List of skins
skin_list = Window_set_list_button(
// Fileselector
Window_set_special_button(8, FILESEL_Y + 1, 144, 80,0), // 2
// Scroller for the fileselector
(file_scroller = Window_set_scroller_button(155, FILESEL_Y - 1, 82,
Skin_files_list.Nb_elements, 10, 0)), // 3
Draw_one_skin_name, 2); // 4
skin_list->Cursor_position = Find_file_in_fileselector(&Skin_files_list, Config.Skin_file);
if (skin_list->Cursor_position < 0)
skin_list->Cursor_position = 0;
// Buttons to choose a font
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
for (temp=0; tempShort_name);
// Cancel
Window_set_normal_button(61, 120, 51,14,"Cancel",0,1,KEY_ESCAPE); // 6
// Dropdown list to choose cursor type
cursor_dropdown = Window_set_dropdown_button(172, 69, 104, 11, 0,
cursors[selected_cursor], 1, 0, 1, RIGHT_SIDE|LEFT_SIDE,0); // 7
for (temp = 0; temp<3; temp++)
Window_dropdown_add_item(cursor_dropdown, temp, cursors[temp]);
Window_set_normal_button(172, 87, 14, 14,
(Config.Display_image_limits)?"X":" ", -1, 1, KEY_NONE); // 8
Print_in_window( 190, 85,"Draw picture", MC_Dark, MC_Light);
Print_in_window( 190, 94,"limits", MC_Dark, MC_Light);
Window_set_normal_button(172, 111, 14, 14,
(Config.Separate_colors)?"X":" ", -1, 1, KEY_NONE); // 9
Print_in_window( 190, 109,"Separate", MC_Dark, MC_Light);
Print_in_window( 190, 118,"colors", MC_Dark, MC_Light);
Window_redraw_list(skin_list);
for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++)
for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++)
Pixel_in_window(x, y, Gfx->Preview[offs_y][x_pos]);
Update_window_area(0, 0, Window_width, Window_height);
Display_cursor();
do
{
if (need_load)
{
need_load=0;
Hide_cursor();
// (Re-)load GUI graphics from selected skins
free(skinsdir);
skinsdir = strdup(Get_item_by_index(&Skin_files_list,
skin_list->List_start + skin_list->Cursor_position)->Full_name);
gfx = Load_graphics(skinsdir, NULL);
if (gfx == NULL) // Error
{
Display_cursor();
Verbose_message("Error!", Gui_loading_error_message);
Hide_cursor();
// Update preview
Window_rectangle(6, 14, 173, 16, MC_Light);
}
else
{
// Update preview
// Display the bitmap according to its own color indices
for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++)
for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++)
{
if (gfx->Preview[offs_y][x_pos] == gfx->Color[0])
Pixel_in_window(x, y, MC_Black);
else if (gfx->Preview[offs_y][x_pos] == gfx->Color[1])
Pixel_in_window(x, y, MC_Dark);
else if (gfx->Preview[offs_y][x_pos] == gfx->Color[3])
Pixel_in_window(x, y, MC_White);
else if (gfx->Preview[offs_y][x_pos] == gfx->Color[2])
Pixel_in_window(x, y, MC_Light);
}
// Actualize current screen according to preferred GUI colors
// Note this only updates onscreen colors
Set_color(
MC_Black,
gfx->Default_palette[gfx->Color[0]].R,
gfx->Default_palette[gfx->Color[0]].G,
gfx->Default_palette[gfx->Color[0]].B);
Set_color(
MC_Dark,
gfx->Default_palette[gfx->Color[1]].R,
gfx->Default_palette[gfx->Color[1]].G,
gfx->Default_palette[gfx->Color[1]].B);
Set_color(
MC_Light,
gfx->Default_palette[gfx->Color[2]].R,
gfx->Default_palette[gfx->Color[2]].G,
gfx->Default_palette[gfx->Color[2]].B);
Set_color(
MC_White,
gfx->Default_palette[gfx->Color[3]].R,
gfx->Default_palette[gfx->Color[3]].G,
gfx->Default_palette[gfx->Color[3]].B);
}
Update_window_area(6, 14, 173, 16);
Display_cursor();
}
clicked_button=Window_clicked_button();
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_SETTINGS, "SKINS");
switch(clicked_button)
{
case 1 : // OK
break;
case 2 : // double-click file: do nothing
break;
case 3 : // doesn't happen
break;
case 4 : // a file is selected
need_load=1;
break;
case 5 : // Font dropdown
{
T_Fileselector_item* fontName;
selected_font = Window_attribute2; // Get the index of the chosen font.
fontName = Get_item_by_index(&Font_files_list,selected_font);
new_font = Load_font(fontName->Full_name, 1);
if (new_font)
{
free(Menu_font);
Menu_font = new_font;
Print_in_window( 172, 33,"Font:" ,MC_Black,MC_Light);
Print_in_window_limited(font_dropdown->Pos_X+2,font_dropdown->Pos_Y+(font_dropdown->Height-7)/2,
fontName->Short_name,(byte)strlen(fontName->Short_name) ,MC_Black,MC_Light);
Update_window_area(172, 33, 8 * 5, 8);
}
break;
}
// 6: Cancel
case 7 : // Cursor
selected_cursor = Window_attribute2;
break;
case 8: // Display limits
showlimits = !showlimits;
Hide_cursor();
Print_in_window(175, 90, (showlimits)?"X":" ", MC_Black, MC_Light);
Display_cursor();
break;
case 9: // Separate colors
separatecolors = !separatecolors;
Hide_cursor();
Print_in_window(175, 114, (separatecolors)?"X":" ", MC_Black, MC_Light);
Display_cursor();
break;
}
}
while ( (clicked_button!=1) && (clicked_button !=6) && (Key != KEY_ESCAPE) && !Quit_is_required);
if(clicked_button == 1)
{
if (gfx != NULL)
{
Set_current_skin(skinsdir, gfx);
}
// (Re-)load the selected font
new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name, 1);
if (new_font)
{
const char * fname;
free(Menu_font);
Menu_font = new_font;
fname = Get_item_by_index(&Font_files_list,selected_font)->Full_name;
free(Config.Font_file);
Config.Font_file = (char *)strdup(fname);
}
// Confirm the change of cursor shape
Config.Cursor = selected_cursor;
Config.Display_image_limits = showlimits;
Config.Separate_colors = separatecolors;
// Now find the best colors for the new skin in the current palette
// and remap the skin
Compute_optimal_menu_colors(Main.palette);
}
// We don't want to keep the skin's palette, as this would corrupt the current picture's one.
Set_palette(Main.palette);
Close_window();
Unselect_button(btn);
// Raffichage du menu pour que les inscriptions qui y figurent soient retracées avec la nouvelle fonte
Display_menu();
// Redraw all buttons, to ensure all specific sprites are in place.
// This is necessary for multi-state buttons, for example Freehand.
for (button=0; buttonPages->Nb_layers; i++)
{
if (i == Spare.current_layer)
{
// Copy the current layer
memcpy(Spare.backups->Pages->Image[i].Pixels,Main.backups->Pages->Image[Main.current_layer].Pixels,Main.image_width*Main.image_height);
}
else
{
// Resize the original layer
Copy_part_of_image_to_another(
Spare.backups->Pages->Next->Image[i].Pixels,0,0,Min(old_width,Spare.image_width),
Min(old_height,Spare.image_height),old_width,
Spare.backups->Pages->Image[i].Pixels,0,0,Spare.image_width);
}
}
// Copie des dimensions de l'image
/*
C'est inutile, le "Backuper et redimensionner brouillon" a déjà modifié
ces valeurs pour qu'elles soient correctes.
*/
/*
Spare.image_width=Main.image_width;
Spare.image_height=Main.image_height;
*/
Copy_view_to_spare();
// Update the visible buffer of the spare.
// It's a bit complex because at the moment, to save memory,
// the spare doesn't have a full visible_buffer + depth_buffer,
// so I can't use exactly the same technique as for Main page.
// (It's the same reason that the "Page" function gets complex,
// it needs to rebuild a depth buffer only, trusting the
// depth buffer that was already available in Spare_.)
Update_spare_buffers(Spare.image_width,Spare.image_height);
Redraw_spare_image();
}
else
Message_out_of_memory();
}
void Copy_some_colors(void)
{
short index;
byte confirmation=0;
static byte mask_color_to_copy[256]; // static to use less stack
memset(mask_color_to_copy,1,256);
Menu_tag_colors("Tag colors to copy",mask_color_to_copy,&confirmation,0, NULL, 0xFFFF);
if (confirmation)
{
// Make a backup with the same pixel data as previous history steps
Backup_the_spare(LAYER_NONE);
for (index=0; index<256; index++)
{
if (mask_color_to_copy[index])
memcpy(Spare.palette+index,Main.palette+index,
sizeof(T_Components));
}
}
}
void Button_Copy_page(int btn)
{
short clicked_button;
Open_window(168,137,"Copy to spare page");
Window_set_normal_button(10, 20,148,14,"Pixels + palette" , 0,1,KEY_RETURN); // 1
Window_set_normal_button(10, 37,148,14,"Pixels only" , 3,1,KEY_x); // 2
Window_set_normal_button(10, 54,148,14,"Palette only" , 1,1,KEY_p); // 3
Window_set_normal_button(10, 71,148,14,"Some colors only" , 6,1,KEY_c); // 4
Window_set_normal_button(10, 88,148,14,"Palette and remap",13,1,KEY_r); // 5
Window_set_normal_button(44,114, 80,14,"Cancel" , 0,1,KEY_ESC); // 6
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_PAGE, NULL);
else if (Is_shortcut(Key,0x200+BUTTON_PAGE))
clicked_button=6;
}
while (clicked_button<=0 && !Quit_is_required);
Close_window();
Display_cursor();
switch (clicked_button)
{
case 1: // Pixels+palette
// backup is done by the following function
Copy_image_only();
// copie de la palette
memcpy(Spare.palette,Main.palette,sizeof(T_Palette));
// Equivalent of 'end_of_modifications' for spare.
Update_spare_buffers(Spare.image_width,Spare.image_height);
Redraw_spare_image();
Spare.image_is_modified=1;
if (Spare.tilemap_mode)
Disable_tilemap(&Spare);
break;
case 2: // Pixels only
// backup is done by the following function
Copy_image_only();
// Equivalent of 'end_of_modifications' for spare.
Update_spare_buffers(Spare.image_width,Spare.image_height);
Redraw_spare_image();
Spare.image_is_modified=1;
if (Spare.tilemap_mode)
Disable_tilemap(&Spare);
break;
case 3: // Palette only
Backup_the_spare(LAYER_NONE);
// Copy palette
memcpy(Spare.palette,Main.palette,sizeof(T_Palette));
// Equivalent of 'end_of_modifications' for spare.
Update_spare_buffers(Spare.image_width,Spare.image_height);
Redraw_spare_image();
Spare.image_is_modified=1;
break;
case 4: // Some colors
// Will backup if needed
Copy_some_colors();
break;
case 5: // Palette and remap
Backup_the_spare(LAYER_ALL);
Remap_spare();
// Copy palette
memcpy(Spare.palette,Main.palette,sizeof(T_Palette));
// Equivalent of 'end_of_modifications' for spare.
Update_spare_buffers(Spare.image_width,Spare.image_height);
Redraw_spare_image();
Spare.image_is_modified=1;
break;
}
Hide_cursor();
Unselect_button(btn);
Display_cursor();
}
// -- Suppression d'une page -------------------------------------------------
void Button_Kill(int btn)
{
if ( (Main.backups->List_size==1)
|| (!Confirmation_box("Delete the current page?")) )
{
if (Main.backups->List_size==1)
Warning_message("You can't delete the last page.");
Hide_cursor();
Unselect_button(btn);
Display_cursor();
}
else
{
Hide_cursor();
Free_current_page();
Set_palette(Main.palette);
Compute_optimal_menu_colors(Main.palette);
Display_all_screen();
Unselect_button(btn);
Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
Display_menu();
Display_cursor();
}
}
//------------------------- Dimensions Image/Screen ---------------------------
void Check_mode_button(short x_pos, short y_pos, byte state)
{
byte color;
switch (state & 0x7F)
{
case 0 : color=MC_White; break;
case 1 : color=MC_Light; break;
case 2 : color=MC_Dark; break;
default: color=MC_Black;
}
Window_rectangle(x_pos, y_pos, 9, 3, color);
Update_window_area(x_pos, y_pos,9,3);
}
/// Number of video modes to display in the resolution menu
#define MODELIST_LINES 10
void Display_modes_list(short list_start, short cursor_position)
{
short index,current_mode;
short y_pos;
byte text_color,background_color;
char str[29];
char *ratio;
for (current_mode=list_start,index=0; indexPosition!=list_start)
{
Window_scroller_button_list->Position=list_start;
Window_draw_slider(Window_scroller_button_list);
}
Display_modes_list(list_start,cursor_position);
Display_cursor();
}
void Button_Resolution(int btn)
{
short clicked_button;
int selected_mode;
word chosen_width;
word chosen_height;
byte chosen_pixel;
short list_start;
short cursor_position;
short temp;
char str[8];
T_Special_button * input_width_button, * input_button_height;
T_Dropdown_button * pixel_button;
static const char *pixel_ratio_labels[PIXEL_MAX] ={
"Normal (1x1)",
"Wide (2x1)",
"Tall (1x2)",
"Double (2x2)",
"Triple (3x3)",
"Wide2 (4x2)",
"Tall2 (2x4)",
"Tall3 (3x4)",
"Quadruple (4x4)"};
Open_window(299,190,"Picture & screen sizes");
Print_in_window( 12, 21,"Picture size:" ,MC_Dark,MC_Light);
Window_display_frame ( 8,17,195, 33);
Window_set_normal_button(223, 18,67,14,"OK" ,0,1,KEY_RETURN); // 1
Window_set_normal_button(223, 35,67,14,"Cancel" ,0,1,KEY_ESC); // 2
Print_in_window_underscore( 12, 37,"Width:",MC_Dark,MC_Light,1);
input_width_button=Window_set_input_button_s( 60, 35,4,KEY_w); // 3
Print_in_window_underscore(108, 37,"Height:",MC_Dark,MC_Light,1);
input_button_height=Window_set_input_button_s(164, 35,4,KEY_h); // 4
Window_display_frame ( 8,72,283,110);
Window_display_frame_in (37,84,228,84);
Window_rectangle (38,85,226,82,MC_Black);
Print_in_window( 16, 76,"OK" ,MC_Dark,MC_Light);
Print_in_window( 55, 76,"X Y" ,MC_Dark,MC_Light);
Print_in_window(120, 76,"Win / Full" ,MC_Dark,MC_Light);
Print_in_window(219, 76,"Ratio" ,MC_Dark,MC_Light);
Print_in_window( 30,170,"\03" ,MC_Dark,MC_Light);
Print_in_window( 62,170,"OK" ,MC_Dark,MC_Light);
Print_in_window(102,170,"Imperfect" ,MC_Dark,MC_Light);
Print_in_window(196,170,"Unsupported" ,MC_Dark,MC_Light);
Window_set_special_button(38,86,225,80,0); // 5
selected_mode=Current_resolution;
if (selected_mode>=MODELIST_LINES/2 && Nb_video_modes > MODELIST_LINES)
{
if (selected_mode>3;
if (temp0)
cursor_position--;
else
if (list_start>0)
list_start--;
Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
Key=0;
break;
case KEY_DOWN : // Bas
if (cursor_position<(MODELIST_LINES-1) && cursor_position<(Nb_video_modes-1))
cursor_position++;
else
if (list_start0)
cursor_position=0;
else
{
if (list_start>(MODELIST_LINES-1))
list_start-=(MODELIST_LINES-1);
else
list_start=0;
}
Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
Key=0;
break;
case KEY_PAGEDOWN : // PageDown
if (Nb_video_modesNumber;
} else {
Selected_freehand_mode++;
if (Selected_freehand_mode>OPERATION_FILLED_CONTOUR)
Selected_freehand_mode=OPERATION_CONTINUOUS_DRAW;
}
switch(Selected_freehand_mode)
{
default:
case OPERATION_CONTINUOUS_DRAW:
icon=-1;
break;
case OPERATION_DISCONTINUOUS_DRAW:
icon=MENU_SPRITE_DISCONTINUOUS_DRAW;
break;
case OPERATION_POINT_DRAW:
icon=MENU_SPRITE_POINT_DRAW;
break;
case OPERATION_FILLED_CONTOUR:
icon=MENU_SPRITE_CONTOUR_DRAW;
break;
}
Display_sprite_in_menu(btn,icon);
Draw_menu_button(btn,BUTTON_PRESSED);
Start_operation_stack(Selected_freehand_mode);
Display_cursor();
Window_dropdown_clear_items(&dropdown);
}
// -- Gestion des boutons de rectangle vide et plein ------------------------
void Button_Empty_rectangle(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_EMPTY_RECTANGLE);
Display_cursor();
}
void Button_Filled_rectangle(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_FILLED_RECTANGLE);
Display_cursor();
}
// -- Gestion des boutons de cercle (ellipse) vide et plein(e) --------------
void Button_circle_ellipse(int btn)
{
word operation;
switch (btn)
{
default:
case BUTTON_CIRCLES:
operation = OPERATION_EMPTY_CIRCLE_CTR;
break;
case BUTTON_FILLCIRC:
operation = OPERATION_FILLED_CIRCLE_CTR;
break;
case BUTTON_SPHERES:
operation = OPERATION_GRAD_CIRCLE_CTR;
break;
}
operation += Selected_circle_ellipse_mode; // CIRCLE_CTR/CIRCLE_CRN/ELLIPSE_CTR/ELLIPSE_CRN;
Hide_cursor();
Start_operation_stack(operation);
Display_cursor();
}
void Button_Circle_switch_mode(int btn)
{
T_Dropdown_button dropdown;
T_Dropdown_choice *item = NULL;
int i;
static const char * text[4] =
{ "Circle (center/radius)", "Circle (corners)",
"Ellipse (center/radiuses)", "Ellipse (corners)" };
dropdown.Pos_X =Buttons_Pool[btn].X_offset;
dropdown.Pos_Y =Buttons_Pool[btn].Y_offset;
dropdown.Height =Buttons_Pool[btn].Height;
dropdown.Dropdown_width=26*8;
dropdown.First_item =NULL;
dropdown.Bottom_up =1;
Hide_cursor();
// If we get here from a keyboard shortcut, don't show the menu and directly
// switch to the next drawing mode.
if (Mouse_K != 0) {
for(i = 0; i < 4; i++) {
Window_dropdown_add_item(&dropdown, i, text[i]);
}
item=Dropdown_activate(&dropdown,0,Menu_Y);
}
if (item)
{
Selected_circle_ellipse_mode = item->Number;
} else {
Selected_circle_ellipse_mode = (Selected_circle_ellipse_mode + 1) & 3;
}
Display_sprite_in_menu(BUTTON_CIRCLES,
(Selected_circle_ellipse_mode >= 2) ? MENU_SPRITE_ELLIPSES : -1);
Draw_menu_button(BUTTON_CIRCLES,BUTTON_RELEASED);
Display_sprite_in_menu(BUTTON_FILLCIRC,
(Selected_circle_ellipse_mode >= 2) ? MENU_SPRITE_ELLIPSES : -1);
Draw_menu_button(BUTTON_FILLCIRC,BUTTON_RELEASED);
Display_sprite_in_menu(BUTTON_SPHERES,
(Selected_circle_ellipse_mode >= 2) ? MENU_SPRITE_GRAD_ELLIPSE : -1);
Draw_menu_button(BUTTON_SPHERES,BUTTON_RELEASED);
Draw_menu_button(btn,BUTTON_PRESSED);
Display_cursor();
Button_circle_ellipse(btn);
Window_dropdown_clear_items(&dropdown);
}
// -- Gestion du menu des dégradés ------------------------------------------
void Draw_button_gradient_style(short x_pos,short y_pos,int technique)
{
short line;
// On commence par afficher les 2 côtés qui constituent le dégradé de base:
// Côté gauche (noir)
Window_rectangle(x_pos+2, y_pos+2, 6, 10, MC_Black);
// Côté droit (blanc)
Window_rectangle(x_pos+8, y_pos+2, 5, 10, MC_White);
switch(technique)
{
case 1 : // Dégradé de trames simples
// Au centre, on place 10 lignes tramées simplement
for (line=2;line<2+10;line++)
if (line&1)
{
// Lignes impaires
Pixel_in_window(x_pos+ 5,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 7,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 8,y_pos+line,MC_Black);
}
else
{
// Lignes paires
Pixel_in_window(x_pos+ 6,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 9,y_pos+line,MC_Black);
}
break;
case 2 : // Dégradé de trames étendues
// Au centre, on place 10 lignes tramées de façon compliquée
for (line=2;line<2+10;line++)
if (line&1)
{
// Lignes impaires
Pixel_in_window(x_pos+ 7,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 8,y_pos+line,MC_Black);
Pixel_in_window(x_pos+10,y_pos+line,MC_Black);
}
else
{
// Lignes paires
Pixel_in_window(x_pos+ 4,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 6,y_pos+line,MC_White);
}
}
Update_window_area(x_pos+2,y_pos+2,10,10);
}
void Load_gradient_data(int index)
{
if (Main.backups->Pages->Gradients->Range[index].Start>Main.backups->Pages->Gradients->Range[index].End)
Error(0);
Gradient_lower_bound =Main.backups->Pages->Gradients->Range[index].Start;
Gradient_upper_bound =Main.backups->Pages->Gradients->Range[index].End;
Gradient_is_inverted =Main.backups->Pages->Gradients->Range[index].Inverse;
Gradient_random_factor=Main.backups->Pages->Gradients->Range[index].Mix+1;
Gradient_bounds_range=(Gradient_lower_boundPages->Gradients->Range[index].Technique)
{
case 0 : // Degradé de base
Gradient_function=Gradient_basic;
break;
case 1 : // Dégradé de trames simples
Gradient_function=Gradient_dithered;
break;
case 2 : // Dégradé de trames étendues
Gradient_function=Gradient_extra_dithered;
}
}
/// draw the gradient preview for the Gradation menu
static void Draw_gradient_preview(short start_x,short start_y,short width,short height,int index)
{
short x_pos; // Variables de balayage du block en bas de l'écran.
short y_pos;
short end_x;
short end_y;
Load_gradient_data(index);
start_x=Window_pos_X+(start_x*Menu_factor_X);
start_y=Window_pos_Y+(start_y*Menu_factor_Y);
Gradient_total_range=width*Menu_factor_X;
end_x=start_x+Gradient_total_range;
end_y=start_y+(height*Menu_factor_Y);
for (y_pos=start_y;y_posStart, range->End);
}
/// Print the Color cycling speed in Hz, ms and in DP2E unit
static void Print_color_cycling_details(short y_pos)
{
char str[24];
Num2str(Main.backups->Pages->Gradients->Range[Current_gradient].Speed, str, 3);
Print_in_window(73+134, y_pos, str, MC_Black, MC_Light);
if (Main.backups->Pages->Gradients->Range[Current_gradient].Speed > 0)
{
snprintf(str, sizeof(str), "Speed %7.4fHz %4ums",
Main.backups->Pages->Gradients->Range[Current_gradient].Speed * 0.2856,
(unsigned)(1000.0 / (Main.backups->Pages->Gradients->Range[Current_gradient].Speed * 0.2856)));
Print_in_window(8, y_pos, str, MC_Black, MC_Light);
}
else
Print_in_window(8, y_pos, " STOPPED", MC_Black, MC_Light);
}
void Button_Gradients(int btn)
{
short clicked_button;
char str[4];
T_Gradient_array backup_gradients;
int old_current_gradient;
T_Scroller_button * mix_scroller;
T_Scroller_button * speed_scroller;
T_Scroller_button * gradient_scroller;
short old_mouse_x;
short old_mouse_y;
byte old_mouse_k;
byte temp_color;
byte first_color;
byte last_color;
byte color;
byte click;
int changed_gradient_index;
byte cycling_mode=Cycling_mode;
(void)btn;
// Enable cycling while this window is open
Cycling_mode=1;
Gradient_pixel=Pixel;
old_current_gradient=Current_gradient;
changed_gradient_index=0;
memcpy(&backup_gradients,Main.backups->Pages->Gradients,sizeof(T_Gradient_array));
Open_window(235,146+12,"Gradation menu");
Window_set_palette_button(48,19); // 1
// Slider for gradient selection
gradient_scroller=Window_set_scroller_button(218,20,75,16,1,Current_gradient); // 2
// Slider for mix
mix_scroller = Window_set_scroller_button(31,20,84,256,1,
Main.backups->Pages->Gradients->Range[Current_gradient].Mix); // 3
// Direction
Window_set_normal_button(8,20,15,14,
(Main.backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",0,1,KEY_TAB); // 4
// Technique
Window_set_normal_button(8,90,15,14,"",0,1,KEY_TAB|GFX2_MOD_SHIFT); // 5
Draw_button_gradient_style(8,90,Main.backups->Pages->Gradients->Range[Current_gradient].Technique);
Window_set_normal_button(178,128+12,51,14,"OK",0,1,KEY_RETURN); // 6
Window_set_normal_button(123,128+12,51,14,"Cancel",0,1,KEY_ESC); // 7
// Scrolling speed
//((250/2 = 125)+1 = 126) +24 = 150
speed_scroller = Window_set_horizontal_scroller_button(79, 111, 150, COLOR_CYCLING_SPEED_MAX + 1, 1,
Main.backups->Pages->Gradients->Range[Current_gradient].Speed); // 8
Print_color_cycling_details(113 + 14);
Print_in_window(5,58,"MIX",MC_Dark,MC_Light);
// Cycling mode on/off
Window_set_normal_button(8,109,62,14,"",0,1,KEY_NONE); // 9
Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
// On tagge les couleurs qui vont avec
Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
Num2str(Current_gradient+1,str,2);
Print_in_window(215,100,str,MC_Black,MC_Light);
// On affiche le cadre autour de la préview
Window_display_frame_in(7,127+12,110,16);
// On affiche la preview
Draw_gradient_preview(8,128+12,108,14,Current_gradient);
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;
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
old_mouse_x=Mouse_X;
old_mouse_y=Mouse_Y;
old_mouse_k=Mouse_K;
if (changed_gradient_index)
{
// User has changed which gradient (0-15) he's watching
changed_gradient_index=0;
Hide_cursor();
// On affiche la valeur sous la jauge
Num2str(Current_gradient+1,str,2);
Print_in_window(215,100,str,MC_Black,MC_Light);
// On tagge les couleurs qui vont avec
Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
// On affiche le sens qui va avec
Print_in_window(12,23,(Main.backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light);
// On raffiche le mélange (jauge) qui va avec
mix_scroller->Position=Main.backups->Pages->Gradients->Range[Current_gradient].Mix;
Window_draw_slider(mix_scroller);
// Update speed
speed_scroller->Position=Main.backups->Pages->Gradients->Range[Current_gradient].Speed;
Window_draw_slider(speed_scroller);
Print_color_cycling_details(113 + 14);
// Gradient #
gradient_scroller->Position=Current_gradient;
Window_draw_slider(gradient_scroller);
// Technique (flat, dithered, very dithered)
Draw_button_gradient_style(8,90,Main.backups->Pages->Gradients->Range[Current_gradient].Technique);
// Rectangular gradient preview
Draw_gradient_preview(8,128+12,108,14,Current_gradient);
Display_cursor();
}
clicked_button=Window_clicked_button();
if (Input_sticky_control!=8 || !Mouse_K)
{
Allow_colorcycling=0;
// Restore palette
Set_palette(Main.palette);
}
switch(clicked_button)
{
case -1 :
case 1 : // Palette
if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) )
{
Hide_cursor();
temp_color=(clicked_button==1) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y);
if (!old_mouse_k)
{
// On vient de clicker
// On met à jour l'intervalle du dégradé
first_color=last_color=Main.backups->Pages->Gradients->Range[Current_gradient].Start=Main.backups->Pages->Gradients->Range[Current_gradient].End=temp_color;
// On tagge le bloc
Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
// Tracé de la preview:
Draw_gradient_preview(8,128+12,108,14,Current_gradient);
}
else
{
// On maintient le click, on va donc tester si le curseur bouge
if (temp_color!=last_color)
{
// On commence par ordonner la 1ère et dernière couleur du bloc
if (first_colorPages->Gradients->Range[Current_gradient].Start=first_color;
Main.backups->Pages->Gradients->Range[Current_gradient].End =temp_color;
}
else if (first_color>temp_color)
{
Main.backups->Pages->Gradients->Range[Current_gradient].Start=temp_color;
Main.backups->Pages->Gradients->Range[Current_gradient].End =first_color;
}
else
Main.backups->Pages->Gradients->Range[Current_gradient].Start=Main.backups->Pages->Gradients->Range[Current_gradient].End=first_color;
// On tagge le bloc
Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
// Tracé de la preview:
Draw_gradient_preview(8,128+12,108,14,Current_gradient);
last_color=temp_color;
}
}
Display_cursor();
}
break;
case 2 : // Nouvel indice de dégradé
// Nouvel indice dans Window_attribute2
Current_gradient=Window_attribute2;
changed_gradient_index=1;
break;
case 3 : // Nouveau mélange de dégradé
Hide_cursor();
// Nouvel mélange dans Window_attribute2
Main.backups->Pages->Gradients->Range[Current_gradient].Mix=Window_attribute2;
// On affiche la nouvelle preview
Draw_gradient_preview(8,128+12,108,14,Current_gradient);
Display_cursor();
break;
case 4 : // Changement de sens
Hide_cursor();
// On inverse le sens (par un XOR de 1)
Main.backups->Pages->Gradients->Range[Current_gradient].Inverse^=1;
Print_in_window(12,23,(Main.backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light);
// On affiche la nouvelle preview
Draw_gradient_preview(8,128+12,108,14,Current_gradient);
Display_cursor();
break;
case 5 : // Changement de technique
Hide_cursor();
// On change la technique par (+1)%3
Main.backups->Pages->Gradients->Range[Current_gradient].Technique=(Main.backups->Pages->Gradients->Range[Current_gradient].Technique+1)%3;
Draw_button_gradient_style(8,90,Main.backups->Pages->Gradients->Range[Current_gradient].Technique);
// On affiche la nouvelle preview
Draw_gradient_preview(8,128+12,108,14,Current_gradient);
Display_cursor();
break;
case 8 : // Speed
Main.backups->Pages->Gradients->Range[Current_gradient].Speed=Window_attribute2;
Hide_cursor();
Print_color_cycling_details(113 + 14);
Display_cursor();
Allow_colorcycling=1;
break;
case 9: // Cycling on/off
cycling_mode = !cycling_mode;
Hide_cursor();
Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
Display_cursor();
break;
}
if (!Mouse_K)
switch (Key)
{
case KEY_BACKQUOTE : // Récupération d'une couleur derrière le menu
case KEY_COMMA :
Get_color_behind_window(&color,&click);
if (click)
{
Hide_cursor();
temp_color=color;
// On met à jour l'intervalle du dégradé
first_color=last_color=Main.backups->Pages->Gradients->Range[Current_gradient].Start=Main.backups->Pages->Gradients->Range[Current_gradient].End=temp_color;
// On tagge le bloc
Tag_color_gradient_range(&Main.backups->Pages->Gradients->Range[Current_gradient]);
// Tracé de la preview:
Draw_gradient_preview(8,128+12,108,14,Current_gradient);
Display_cursor();
Wait_end_of_click();
}
Key=0;
break;
case KEY_MOUSEWHEELUP:
if (Current_gradient>0)
{
Current_gradient--;
changed_gradient_index=1;
}
break;
case KEY_MOUSEWHEELDOWN:
if (Current_gradient<15)
{
Current_gradient++;
changed_gradient_index=1;
}
break;
default:
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Window_help(BUTTON_GRADRECT, NULL);
Key=0;
break;
}
else if (Is_shortcut(Key,0x200+BUTTON_GRADRECT))
clicked_button=6;
else if (Is_shortcut(Key,SPECIAL_CYCLE_MODE))
{
// Cycling on/off
cycling_mode = !cycling_mode;
Hide_cursor();
Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
Display_cursor();
}
}
}
while (clicked_button!=6 && clicked_button!=7 && !Quit_is_required);
Close_window();
// The Grad rect operation uses the same button as Grad menu.
if (Current_operation != OPERATION_GRAD_RECTANGLE)
Unselect_button(BUTTON_GRADRECT);
Display_cursor();
Gradient_pixel=Display_pixel;
Cycling_mode=cycling_mode;
if (clicked_button==7) // Cancel
{
Current_gradient=old_current_gradient;
memcpy(Main.backups->Pages->Gradients,&backup_gradients,sizeof(T_Gradient_array));
}
}
// -- Gestion des boutons de cercle / ellipse / rectangle dégradés --------------------
void Button_Grad_rectangle(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_GRAD_RECTANGLE);
Display_cursor();
}
// -- Gestion du bouton de remplissage ---------------------------------------
void Button_Fill(int btn)
{
(void)btn;
if (Current_operation!=OPERATION_FILL)
{
Hide_cursor();
if (Current_operation!=OPERATION_REPLACE)
{
Paintbrush_shape_before_fill=Paintbrush_shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
}
else
if ( (Mouse_Y=Main.X_zoom) ) )
Print_in_menu("X: Y: ",0);
Start_operation_stack(OPERATION_FILL);
Display_cursor();
}
}
void Button_Replace(int btn)
{
(void)btn;
if (Current_operation!=OPERATION_REPLACE)
{
Hide_cursor();
if (Current_operation!=OPERATION_FILL)
{
Paintbrush_shape_before_fill=Paintbrush_shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
}
if ( (Mouse_Y=Main.X_zoom) ) )
Print_in_menu("X: Y: ( )",0);
Start_operation_stack(OPERATION_REPLACE);
Display_cursor();
}
}
void Button_Unselect_fill(int btn)
{
(void)btn;
Paintbrush_shape=Paintbrush_shape_before_fill;
if (Current_operation==OPERATION_REPLACE)
if ( (Mouse_Y=Main.X_zoom) ) )
Print_in_menu("X: Y: ",0);
}
//---------------------------- Menu des pinceaux -----------------------------
/// Checks if the current brush is identical to a preset one.
byte Same_paintbrush(byte index)
{
if (Paintbrush_shape!=Paintbrush[index].Shape ||
Paintbrush_width!=Paintbrush[index].Width ||
Paintbrush_height!=Paintbrush[index].Height)
return 0;
if (Paintbrush_shape==PAINTBRUSH_SHAPE_MISC)
{
// Check all pixels
int x,y;
for(y=0;y=(NB_PAINTBRUSH_SPRITES+3))
{
index = clicked_button-NB_PAINTBRUSH_SPRITES-3;
if (Window_attribute2==1) // Set
{
// Store
x_pos=13+((index+NB_PAINTBRUSH_SPRITES)%12)*24;
y_pos=27+((index+NB_PAINTBRUSH_SPRITES)/12)*25;
Store_brush(index);
Hide_cursor();
Display_stored_brush_in_window(x_pos+2, y_pos+2, index);
Display_cursor();
}
else
{
// Restore and exit
if (Restore_brush(index))
{
Close_window();
break;
}
}
}
else if (clicked_button>=3)
// Standard paintbrushes
{
if (Window_attribute2!=1)
{
// Select paintbrush
Close_window();
Select_paintbrush(clicked_button-3);
break;
}
else if (Window_attribute2==1)
{
// Store current
index=clicked_button-3;
if (!Store_paintbrush(index))
{
// Redraw
Hide_cursor();
x_pos=13+(index%12)*24;
y_pos=27+(index/12)*25;
Window_rectangle(x_pos,y_pos,20,20,MC_White);
Display_paintbrush_in_window(x_pos+2,y_pos+2,index);
Display_cursor();
}
}
}
else if (clicked_button==1 || Is_shortcut(Key,0x100+BUTTON_PAINTBRUSHES))
{
Close_window();
break;
}
else if (clicked_button==2)
{
int size;
// Pick a standard shape
Paintbrush_shape=Window_attribute2;
// Assign a reasonable size
size=Max(Paintbrush_width,Paintbrush_height);
if (size==1)
size=3;
switch (Paintbrush_shape)
{
case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
Set_paintbrush_size(size, 1);
break;
case PAINTBRUSH_SHAPE_VERTICAL_BAR:
Set_paintbrush_size(1, size);
break;
case PAINTBRUSH_SHAPE_CROSS:
case PAINTBRUSH_SHAPE_PLUS:
case PAINTBRUSH_SHAPE_DIAMOND:
Set_paintbrush_size(size|1,size|1);
break;
default:
Set_paintbrush_size(size,size);
break;
}
Close_window();
Change_paintbrush_shape(Paintbrush_shape);
break;
}
}
while (1);
Unselect_button(btn);
Display_cursor();
}
void Button_Brush_monochrome(int btn)
{
Hide_cursor();
// On passe en brosse monochrome:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_MONO_BRUSH);
Unselect_button(btn);
Display_cursor();
}
// -- Fonction renvoyant le mode vidéo le plus adapté à l'image chargée -----
#define TOLERANCE_X 8
#define TOLERANCE_Y 4
static int Best_video_mode(void)
{
short best_width,best_height;
int best_mode;
short temp_x,temp_y;
int mode;
// Si mode fenêtre, on reste dans ce mode.
if (Current_resolution == 0)
return 0;
// On commence par borner les dimensions, ou du moins les rendre cohérentes
if ((Original_screen_X<=0) || (Config.Set_resolution_according_to==2))
Original_screen_X=Main.image_width;
else
if (Original_screen_X<320)
Original_screen_X=320;
if ((Original_screen_Y<=0) || (Config.Set_resolution_according_to==2))
Original_screen_Y=Main.image_height;
else
if (Original_screen_Y<200)
Original_screen_Y=200;
GFX2_Log(GFX2_DEBUG, "Best_video_mode() looking for %dx%d\n", (int)Original_screen_X, (int)Original_screen_Y);
if ((Original_screen_X > Video_mode[Nb_video_modes-1].Width) ||
(Original_screen_Y > Video_mode[Nb_video_modes-1].Height))
{
// return the "biggest" video mode
return Nb_video_modes-1;
}
// Maintenant on peut chercher le mode qui correspond le mieux
best_mode=Current_resolution;
best_width=0;
best_height=0;
for (mode=1; modePages->Filename_unicode;
Init_context_layered_image(&context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
selector = &Main.selector;
break;
case CONTEXT_BRUSH:
filename_unicode = Brush_filename_unicode;
Init_context_brush(&context, Brush_filename, Brush_file_directory);
selector = &Brush_selector;
break;
case CONTEXT_PALETTE:
Init_context_layered_image(&context, "", Main.backups->Pages->File_directory);
context.Type = CONTEXT_PALETTE;
context.Format = FORMAT_PAL;
selector = &Palette_selector;
break;
default:
return; // DO NOTHING
}
context.File_name_unicode = Unicode_strdup(filename_unicode);
confirm = Button_Load_or_Save(selector, 1, &context);
if (confirm)
{
if (type==CONTEXT_MAIN_IMAGE)
{
if (Main.image_is_modified)
confirm=Confirmation_box("Discard unsaved changes?");
}
}
// confirm is modified inside the first if, that's why we check it
// again here
if (confirm)
{
short old_image_width, old_image_height;
old_image_width = Main.image_width;
old_image_height = Main.image_height;
old_cursor_shape=Cursor_shape;
Hide_cursor();
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
if (type==CONTEXT_MAIN_IMAGE)
{
Original_screen_X=0;
Original_screen_Y=0;
}
Load_image(&context);
if (type==CONTEXT_BRUSH)
{
free(Brush_filename);
Brush_filename = context.File_name; // "steal" heap string
context.File_name = NULL;
free(Brush_filename_unicode);
Brush_filename_unicode = context.File_name_unicode; // "steal" heap string
context.File_name_unicode = NULL;
free(Brush_file_directory);
Brush_file_directory = context.File_directory; // "steal" heap string
context.File_directory = NULL;
Brush_fileformat = context.Format;
Tiling_offset_X=0;
Tiling_offset_Y=0;
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
Select_button(BUTTON_DRAW,LEFT_SIDE);
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu à la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Select_button(BUTTON_DRAW,RIGHT_SIDE);
}
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
}
else
{
Hide_cursor();
Cursor_shape=old_cursor_shape;
}
if ( (File_error==1) || (Get_fileformat(Main.fileformat)->Palette_only) )
{
if (File_error!=1)
Compute_optimal_menu_colors(Main.palette);
}
else
{
if (type==CONTEXT_MAIN_IMAGE)
{
if (Main.magnifier_mode &&
(Main.image_width > old_image_width || Main.image_height > old_image_height))
{
// disable magnifier
Pixel_preview = Pixel_preview_normal;
Main.magnifier_mode = 0;
Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
}
new_mode=Best_video_mode();
if ((Config.Auto_set_res) && (new_mode!=Current_resolution))
{
Init_mode_video(
Video_mode[new_mode].Width,
Video_mode[new_mode].Height,
Video_mode[new_mode].Fullscreen,
Pixel_ratio);
Display_menu();
}
// In window mode, activate wide or tall pixels if the image says so.
else if (!Video_mode[Current_resolution].Fullscreen &&
((context.Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE && Pixel_ratio != PIXEL_WIDE2) ||
(context.Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL && Pixel_ratio != PIXEL_TALL2) ||
(context.Ratio == PIXEL_TALL3 &&
Pixel_ratio != PIXEL_TALL3) ))
{
Init_mode_video(
Video_mode[Current_resolution].Width,
Video_mode[Current_resolution].Height,
Video_mode[Current_resolution].Fullscreen,
context.Ratio);
Display_menu();
}
else
{
if (Main.image_width > old_image_width || Main.image_height > old_image_height)
{
Main.offset_X = 0;
Main.offset_Y = 0;
}
Compute_limits();
Compute_paintbrush_coordinates();
}
Compute_optimal_menu_colors(Main.palette);
Redraw_layered_image();
End_of_modification();
Check_menu_mode();
Display_all_screen();
Main.image_is_modified=0;
}
}
Display_menu();
Display_cursor();
}
Destroy_context(&context);
Hide_cursor();
Print_filename();
Display_cursor();
Set_palette(Main.palette);
}
void Button_Load(int btn)
{
(void)btn;
// On sauve l'état actuel des paramètres de l'image pour pouvoir les
// restituer en cas d'erreur n'affectant pas l'image
Upload_infos_page(&Main);
Load_picture(CONTEXT_MAIN_IMAGE);
Tilemap_update();
}
void Button_Reload(int btn)
{
byte old_cursor_shape;
int new_mode;
(void)btn;
// On sauve l'état actuel des paramètres de l'image pour pouvoir les
// restituer en cas d'erreur n'affectant pas l'image
Upload_infos_page(&Main);
if ( (!Main.image_is_modified) || Confirmation_box("Discard unsaved changes ?") )
{
T_IO_Context context;
Hide_cursor();
old_cursor_shape=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Original_screen_X=0;
Original_screen_Y=0;
Init_context_layered_image(&context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
Load_image(&context);
Hide_cursor();
Cursor_shape=old_cursor_shape;
if (File_error!=1)
{
if (Main.magnifier_mode)
{
Pixel_preview=Pixel_preview_normal;
Main.magnifier_mode=0;
Draw_menu_button(BUTTON_MAGNIFIER,Main.magnifier_mode);
}
new_mode=Best_video_mode();
if ( ((Config.Auto_set_res) && (new_mode!=Current_resolution)) &&
(!Resolution_in_command_line) )
{
Init_mode_video(
Video_mode[new_mode].Width,
Video_mode[new_mode].Height,
Video_mode[new_mode].Fullscreen,
Pixel_ratio);
Display_menu();
}
// In window mode, activate wide or tall pixels if the image says so.
else if (!Video_mode[Current_resolution].Fullscreen &&
((context.Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE && Pixel_ratio != PIXEL_WIDE2) ||
(context.Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL && Pixel_ratio != PIXEL_TALL2 &&
Pixel_ratio != PIXEL_TALL3)))
{
Init_mode_video(
Video_mode[Current_resolution].Width,
Video_mode[Current_resolution].Height,
Video_mode[Current_resolution].Fullscreen,
context.Ratio);
Display_menu();
}
else
{
Main.offset_X=0;
Main.offset_Y=0;
Compute_limits();
Compute_paintbrush_coordinates();
}
Tilemap_update();
Redraw_layered_image();
End_of_modification();
Check_menu_mode();
Display_all_screen();
Main.image_is_modified=0;
}
Destroy_context(&context);
}
else
Hide_cursor();
Compute_optimal_menu_colors(Main.palette);
Display_menu();
if (Config.Display_image_limits)
Display_image_limits();
Unselect_button(BUTTON_LOAD);
Display_cursor();
}
static void Backup_existing_file(const char * filename)
{
char * new_filename; // full filename of the backup file
char * p;
int i;
size_t len;
if (filename == NULL)
return;
len = strlen(filename);
new_filename = malloc(len + 1 + 4); // spare bytes to concat ".BAK"
memcpy(new_filename, filename, len + 1);
p = Find_last_separator(new_filename); // pointer to the filename part (after directory)
if (p == NULL)
p = new_filename;
else
p++;
i = Position_last_dot(p);
if (i >= 0)
memcpy(p + i + 1, "BAK", 4);
else
memcpy(new_filename + len, ".BAK", 5);
File_error=0;
// On fait un backup si le nom du fichier n'est pas celui qu'on a choisi
// pour nommer les backups (c'est évident!).
if (strcmp(new_filename,filename))
{
// S'il y avait déjà un fichier Backup, on l'efface
if ((File_exists(new_filename))
&& (Remove_path(new_filename)!=0))
File_error=1;
if ((!File_error)
&& (rename(filename,new_filename)!=0))
File_error=1;
}
free(new_filename);
}
void Save_picture(enum CONTEXT_TYPE type)
{
byte confirm;
byte old_cursor_shape;
T_IO_Context save_context;
word * filename_unicode = NULL;
T_Selector_settings * selector;
if (type == CONTEXT_MAIN_IMAGE)
{
filename_unicode = Main.backups->Pages->Filename_unicode;
Init_context_layered_image(&save_context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
save_context.Format = Main.fileformat;
selector = &Main.selector;
}
else if (type == CONTEXT_BRUSH)
{
filename_unicode = Brush_filename_unicode;
Init_context_brush(&save_context, Brush_filename, Brush_file_directory);
save_context.Format = Brush_fileformat;
selector = &Brush_selector;
}
else if (type == CONTEXT_PALETTE)
{
char* pal_filename;
char* dotpos;
size_t len = strlen(Main.backups->Pages->Filename);
pal_filename = malloc(len + 4 + 1); // reserve space for ".pal"
memcpy(pal_filename, Main.backups->Pages->Filename, len + 1);
// Replace extension with PAL
dotpos = strrchr(pal_filename, '.');
if (dotpos == NULL)
dotpos = pal_filename + len;
strcpy(dotpos, ".pal");
Init_context_layered_image(&save_context, pal_filename, Main.backups->Pages->File_directory);
save_context.Type = CONTEXT_PALETTE;
free(pal_filename);
// Set format to PAL
save_context.Format = FORMAT_PAL;
selector = &Palette_selector;
}
else
return;
save_context.File_name_unicode = Unicode_strdup(filename_unicode);
confirm=Button_Load_or_Save(selector, 0, &save_context);
if (confirm && File_exists(save_context.File_name))
{
confirm=Confirmation_box("Erase old file ?");
if (confirm && (Config.Backup))
{
char * full_filename = Filepath_append_to_dir(save_context.File_directory, save_context.File_name);
Backup_existing_file(full_filename);
free(full_filename);
if (File_error)
{
confirm=0;
Error(0);
}
}
}
if (confirm)
{
const T_Format * format;
old_cursor_shape=Cursor_shape;
Hide_cursor();
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Save_image(&save_context);
format=Get_fileformat(save_context.Format);
if (!File_error && type == CONTEXT_MAIN_IMAGE && !format->Palette_only && (Main.backups->Pages->Nb_layers==1 || format->Supports_layers))
{
Main.image_is_modified = 0;
Main.fileformat = save_context.Format;
free(Main.backups->Pages->Filename);
Main.backups->Pages->Filename = save_context.File_name; // "steal" string from heap
save_context.File_name = NULL;
free(Main.backups->Pages->Filename_unicode);
Main.backups->Pages->Filename_unicode = save_context.File_name_unicode; // "steal" string
save_context.File_name_unicode = NULL;
free(Main.backups->Pages->File_directory);
Main.backups->Pages->File_directory = save_context.File_directory;
save_context.File_directory = NULL;
}
if (type == CONTEXT_BRUSH)
{
Brush_fileformat = save_context.Format;
free(Brush_filename);
Brush_filename = save_context.File_name;
save_context.File_name = NULL;
free(Brush_filename_unicode);
Brush_filename_unicode = save_context.File_name_unicode;
save_context.File_name_unicode = NULL;
free(Brush_file_directory);
Brush_file_directory = save_context.File_directory;
save_context.File_directory = NULL;
}
Hide_cursor();
Cursor_shape=old_cursor_shape;
Display_cursor();
}
Destroy_context(&save_context);
Print_filename();
Set_palette(Main.palette);
}
void Button_Save(int btn)
{
(void)btn;
Save_picture(CONTEXT_MAIN_IMAGE);
}
/// Save main image over existing file (no fileselector)
void Button_Autosave(int btn)
{
byte old_cursor_shape;
char * filename;
byte file_already_exists;
(void)btn;
filename = Filepath_append_to_dir(Main.backups->Pages->File_directory, Main.backups->Pages->Filename);
file_already_exists = File_exists(filename);
if ( (!file_already_exists) || Confirmation_box("Erase old file ?") )
{
if ((file_already_exists) && (Config.Backup))
Backup_existing_file(filename);
else
File_error=0;
Hide_cursor();
if (!File_error)
{
T_IO_Context save_context;
old_cursor_shape=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Init_context_layered_image(&save_context, Main.backups->Pages->Filename, Main.backups->Pages->File_directory);
save_context.File_name_unicode = Unicode_strdup(Main.backups->Pages->Filename_unicode);
Save_image(&save_context);
if (!File_error)
{
Main.image_is_modified=0;
}
Destroy_context(&save_context);
Hide_cursor();
Cursor_shape=old_cursor_shape;
}
else
Error(0);
}
else
Hide_cursor();
free(filename);
Unselect_button(BUTTON_SAVE);
Display_cursor();
}
// -- Gestion des boutons de ligne ------------------------------------------
void Button_Lines(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(Selected_line_mode);
Display_cursor();
}
void Button_Lines_switch_mode(int btn)
{
char icon;
if (Selected_line_mode==OPERATION_LINE)
{
Selected_line_mode=OPERATION_K_LINE;
icon=MENU_SPRITE_K_LINE;
}
else if (Selected_line_mode==OPERATION_K_LINE)
{
Selected_line_mode=OPERATION_CENTERED_LINES;
icon=MENU_SPRITE_CENTERED_LINES;
}
else
{
Selected_line_mode=OPERATION_LINE;
icon=-1;
}
Hide_cursor();
Display_sprite_in_menu(btn,icon);
Draw_menu_button(btn,BUTTON_PRESSED);
Start_operation_stack(Selected_line_mode);
Display_cursor();
}
// -- Button de brosse ------------------------------------------------------
void Button_Brush(int btn)
{
Hide_cursor();
if (Current_operation!=OPERATION_GRAB_BRUSH)
Start_operation_stack(OPERATION_GRAB_BRUSH);
else
Unselect_button(btn);
Display_cursor();
}
void Button_Unselect_brush(int btn)
{
(void)btn;
// On fait de notre mieux pour restaurer l'ancienne opération:
Start_operation_stack(Operation_before_interrupt);
}
void Button_Restore_brush(int btn)
{
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
Unselect_button(btn);
Display_cursor();
}
// -- Button de prise de brosse au lasso ------------------------------------
void Button_Lasso(int btn)
{
Hide_cursor();
if (Current_operation!=OPERATION_POLYBRUSH)
{
Paintbrush_shape_before_lasso=Paintbrush_shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
Start_operation_stack(OPERATION_POLYBRUSH);
}
else
Unselect_button(btn);
Display_cursor();
}
void Button_Unselect_lasso(int btn)
{
(void)btn;
// If we aren't in OPERATION_POLYBRUSH, then we didn't save a brush shape,
// and we shouldn't try to restore it.
if (Current_operation==OPERATION_POLYBRUSH)
Paintbrush_shape=Paintbrush_shape_before_lasso;
// On fait de notre mieux pour restaurer l'ancienne opération:
Start_operation_stack(Operation_before_interrupt);
}
// -- Button de pipette -----------------------------------------------------
void Button_Colorpicker(int btn)
{
Hide_cursor();
if (Current_operation!=OPERATION_COLORPICK)
{
Colorpicker_color=-1;
Start_operation_stack(OPERATION_COLORPICK);
Paintbrush_shape_before_colorpicker=Paintbrush_shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_NONE;
if (Operation_before_interrupt!=OPERATION_REPLACE)
if ( (Mouse_Y=Main.X_zoom) ) )
Print_in_menu("X: Y: ( )",0);
}
else
Unselect_button(btn);
Display_cursor();
}
void Button_Unselect_colorpicker(int btn)
{
(void)btn;
// Erase the color block which shows the picked color
if (Operation_before_interrupt!=OPERATION_REPLACE)
if ( (Mouse_Y=Main.X_zoom) ) )
Print_in_menu("X: Y: ",0);
// On fait de notre mieux pour restaurer l'ancienne opération:
if (Current_operation==OPERATION_COLORPICK)
{
Start_operation_stack(Operation_before_interrupt);
Paintbrush_shape=Paintbrush_shape_before_colorpicker;
}
}
// -- Inversion de la couleur Fore et de la couleur Back --
void Button_Invert_foreback(int btn)
{
byte temp_color;
temp_color=Fore_color;
Fore_color =Back_color;
Back_color =temp_color;
Hide_cursor();
Frame_menu_color(Back_color);
Frame_menu_color(Fore_color);
Reposition_palette();
Display_foreback();
Unselect_button(btn);
Display_cursor();
}
// -- Gestion du bouton Loupe -----------------------------------------------
byte Coming_from_zoom_factor_menu=0;
void Button_Magnify(int btn)
{
Hide_cursor();
if ( (Current_operation==OPERATION_MAGNIFY) || (Main.magnifier_mode) )
{
Unselect_button(btn);
}
else
{
Compute_magnifier_data();
if ((!Config.Fast_zoom) || (Mouse_Y>=Menu_Y) || Coming_from_zoom_factor_menu)
{
Coming_from_zoom_factor_menu=0;
Start_operation_stack(OPERATION_MAGNIFY);
}
else
{ /* Ceci est de la duplication de code de presque toute l'opération de */
/* la loupe... Il serait peut-être plus propre de faire une procédure */
/* qui s'en charge... */
// On passe en mode loupe
Main.magnifier_mode=1;
// La fonction d'affichage dans la partie image est désormais un affichage
// spécial loupe.
Pixel_preview=Pixel_preview_magnifier;
// On calcule l'origine de la loupe
Main.magnifier_offset_X=Mouse_X-(Main.magnifier_width>>1);
Main.magnifier_offset_Y=Mouse_Y-(Main.magnifier_height>>1);
// Calcul des coordonnées absolues de ce coin DANS L'IMAGE
Main.magnifier_offset_X+=Main.offset_X;
Main.magnifier_offset_Y+=Main.offset_Y;
Clip_magnifier_offsets(&Main.magnifier_offset_X, &Main.magnifier_offset_Y);
// On calcule les bornes visibles dans l'écran
Position_screen_according_to_zoom();
Compute_limits();
Display_all_screen();
// Repositionner le curseur en fonction des coordonnées visibles
Compute_paintbrush_coordinates();
}
}
Display_cursor();
Update_rect(0,0,0,0);
}
void Button_Magnify_menu(int btn)
{
T_Dropdown_button dropdown;
T_Dropdown_choice *item;
int i;
static const char * text[NB_ZOOM_FACTORS] =
{"x2", "x3", "x4", "x5", "x6", "x8", "x10", "x12", "x14", "x16", "x18", "x20",
"x24", "x28", "x32"};
(void)btn;
Hide_cursor();
dropdown.Pos_X =Buttons_Pool[BUTTON_MAGNIFIER].X_offset;
dropdown.Pos_Y =Buttons_Pool[BUTTON_MAGNIFIER].Y_offset;
dropdown.Height =Buttons_Pool[BUTTON_MAGNIFIER].Height;
dropdown.Dropdown_width=28;
dropdown.First_item =NULL;
dropdown.Bottom_up =1;
for(i = 0; i < NB_ZOOM_FACTORS; i++) {
Window_dropdown_add_item(&dropdown, i, text[i]);
}
item=Dropdown_activate(&dropdown,0,Menu_Y);
if (item)
{
Change_magnifier_factor(item->Number,0);
}
if ( (!item) && (!Main.magnifier_mode) && (Current_operation!=OPERATION_MAGNIFY) ) // Cancel
Unselect_button(BUTTON_MAGNIFIER);
Display_all_screen();
Display_cursor();
Update_rect(Main.separator_position,0,Screen_width-Main.separator_position,Menu_Y);
if ( (item) && (!Main.magnifier_mode) && (Current_operation!=OPERATION_MAGNIFY) ) // Passage en mode zoom
{
Coming_from_zoom_factor_menu=1;
Select_button(BUTTON_MAGNIFIER,LEFT_SIDE);
}
Window_dropdown_clear_items(&dropdown);
}
void Button_Unselect_magnifier(int btn)
{
(void)btn;
if (Main.magnifier_mode)
{
// On sort du mode loupe
Main.magnifier_mode=0;
// --> Recalculer le décalage de l'écran lorsqu'on sort de la loupe <--
// Centrage "brut" de lécran par rapport à la loupe
Main.offset_X=Main.magnifier_offset_X-((Screen_width-Main.magnifier_width)>>1);
Main.offset_Y=Main.magnifier_offset_Y-((Menu_Y-Main.magnifier_height)>>1);
// Correction en cas de débordement de l'image
if (Main.offset_X+Screen_width>Main.image_width)
Main.offset_X=Main.image_width-Screen_width;
if (Main.offset_X<0)
Main.offset_X=0;
if (Main.offset_Y+Menu_Y>Main.image_height)
Main.offset_Y=Main.image_height-Menu_Y;
if (Main.offset_Y<0)
Main.offset_Y=0;
// La fonction d'affichage dans l'image est désormais un affichage normal.
Pixel_preview=Pixel_preview_normal;
// Calculer les bornes visibles dans l'écran
Compute_limits();
Display_all_screen(); // <=> Display_screen();
// Repositionner le curseur en fonction des coordonnées visibles
Compute_paintbrush_coordinates();
Old_MX = -1;
Old_MY = -1;
}
else // On fait de notre mieux pour restaurer l'ancienne opération:
Start_operation_stack(Operation_before_interrupt);
}
// ----------------------- Modifications de brosse ---------------------------
void Button_Brush_FX(int btn)
{
short clicked_button;
short index;
Open_window(310,162,"Brush effects");
Window_display_frame( 6,19,298,61);
Window_display_frame( 6,83,122,53);
Window_display_frame(137,83,167,53);
Window_set_normal_button(236,141, 67,14,"Cancel" ,0,1,KEY_ESC); // 1
Window_set_normal_button( 19, 46, 27,14,"X\035" ,0,1,Config_Key[SPECIAL_FLIP_X][0]); // 2
Window_set_normal_button( 19, 61, 27,14,"Y\022" ,0,1,Config_Key[SPECIAL_FLIP_Y][0]); // 3
Window_set_normal_button( 58, 46, 37,14,"90\xb0" ,0,1,Config_Key[SPECIAL_ROTATE_90][0]); // 4
Window_set_normal_button( 96, 46, 37,14,"180\xb0" ,0,1,Config_Key[SPECIAL_ROTATE_180][0]); // 5
Window_set_normal_button( 58, 61, 75,14,"any angle" ,0,1,Config_Key[SPECIAL_ROTATE_ANY_ANGLE][0]); // 6
Window_set_normal_button(145, 46, 67,14,"Stretch" ,0,1,Config_Key[SPECIAL_STRETCH][0]); // 7
Window_set_normal_button(145, 61, 67,14,"Distort" ,0,1,Config_Key[SPECIAL_DISTORT][0]); // 8
Window_set_normal_button(155, 99,131,14,"Recolorize" ,0,1,Config_Key[SPECIAL_RECOLORIZE_BRUSH][0]); // 9
Window_set_normal_button(155,117,131,14,"Get brush colors",0,1,Config_Key[SPECIAL_GET_BRUSH_COLORS][0]); // 10
// Boutons représentant les coins du brush handle: (HG,HD,C,BG,BD)
Window_set_normal_button( 75, 90,11,11,"",0,1,Config_Key[SPECIAL_TOP_LEFT_ATTACHMENT][0]); // 11
Window_set_normal_button(103, 90,11,11,"",0,1,Config_Key[SPECIAL_TOP_RIGHT_ATTACHMENT][0]); // 12
Window_set_normal_button( 89,104,11,11,"",0,1,Config_Key[SPECIAL_CENTER_ATTACHMENT][0]); // 13
Window_set_normal_button( 75,118,11,11,"",0,1,Config_Key[SPECIAL_BOTTOM_LEFT_ATTACHMENT][0]); // 14
Window_set_normal_button(103,118,11,11,"",0,1,Config_Key[SPECIAL_BOTTOM_RIGHT_ATTACHMENT][0]); // 15
Window_set_normal_button(224,46,67,14,"Outline",0,1,Config_Key[SPECIAL_OUTLINE][0]); // 16
Window_set_normal_button(224,61,67,14,"Nibble" ,0,1,Config_Key[SPECIAL_NIBBLE][0]); // 17
Window_set_normal_button( 7,141, 60,14,"Load",0,1,Config_Key[SPECIAL_LOAD_BRUSH][0]); // 18
Window_set_normal_button( 70,141, 60,14,"Save",0,1,Config_Key[SPECIAL_SAVE_BRUSH][0]); // 19
Print_in_window( 80, 24,"Shape modifications",MC_Dark,MC_Light);
Print_in_window( 10, 36,"Mirror",MC_Dark,MC_Light);
Print_in_window( 72, 36,"Rotate",MC_Dark,MC_Light);
Print_in_window(155, 36,"Deform",MC_Dark,MC_Light);
Print_in_window(230, 36,"Borders",MC_Dark,MC_Light);
Print_in_window(141, 88,"Colors modifications",MC_Dark,MC_Light);
Print_in_window( 20,102,"Brush",MC_Dark,MC_Light);
Print_in_window( 16,110,"handle",MC_Dark,MC_Light);
// Dessin des pointillés pour le "brush handle"
for (index=0; index<13; index+=2)
{
Pixel_in_window( 88+index, 92,MC_Dark);
Pixel_in_window( 88+index,126,MC_Dark);
Pixel_in_window( 77,103+index,MC_Dark);
Pixel_in_window(111,103+index,MC_Dark);
}
// Dessin des coins et du centre pour les boutons du "brush handle"
// Coin HG
Window_rectangle(77, 92, 7, 1, MC_Black);
Window_rectangle(77, 92, 1, 7, MC_Black);
// Coin HD
Window_rectangle(105, 92, 7, 1, MC_Black);
Window_rectangle(111, 92, 1, 7, MC_Black);
// Centre
Window_rectangle(91, 109, 7, 1, MC_Black);
Window_rectangle(94, 106, 1, 7, MC_Black);
// Coin BG
Window_rectangle(77, 126, 7, 1, MC_Black);
Window_rectangle(77, 120, 1, 7, MC_Black);
// Coin BD
Window_rectangle(105, 126, 7, 1, MC_Black);
Window_rectangle(111, 120, 1, 7, MC_Black);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Key=0;
Window_help(BUTTON_BRUSH_EFFECTS, NULL);
}
else if (Is_shortcut(Key,0x100+BUTTON_BRUSH_EFFECTS))
{
clicked_button=1;
}
}
while (clicked_button<=0 && !Quit_is_required);
Close_window();
Unselect_button(btn);
// Gestion du bouton clické
switch (clicked_button)
{
case 2 : // Flip X
Flip_X_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
break;
case 3 : // Flip Y
Flip_Y_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
break;
case 4 : // 90° Rotation
Rotate_90_deg();
break;
case 5 : // 180° Rotation
Rotate_180_deg_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
break;
case 6 : // Any angle rotation
Start_operation_stack(OPERATION_ROTATE_BRUSH);
break;
case 7 : // Stretch
Start_operation_stack(OPERATION_STRETCH_BRUSH);
break;
case 8 : // Distort
Start_operation_stack(OPERATION_DISTORT_BRUSH);
break;
case 9 : // Recolorize
Remap_brush();
break;
case 10 : // Get brush colors
Display_cursor();
Get_colors_from_brush();
Hide_cursor();
break;
case 11 : // Brush Attachment: Top-Left
Brush_offset_X=0;
Brush_offset_Y=0;
break;
case 12 : // Brush Attachment: Top-Right
Brush_offset_X=(Brush_width-1);
Brush_offset_Y=0;
break;
case 13 : // Brush Attachment: Center
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
break;
case 14 : // Brush Attachment: Bottom-Left
Brush_offset_X=0;
Brush_offset_Y=(Brush_height-1);
break;
case 15 : // Brush Attachment: Bottom-Right
Brush_offset_X=(Brush_width-1);
Brush_offset_Y=(Brush_height-1);
break;
case 16 : // Outline
Outline_brush();
break;
case 17 : // Nibble
Nibble_brush();
break;
case 18 : // Load
Display_cursor();
Load_picture(CONTEXT_BRUSH);
Hide_cursor();
break;
case 19 : // Save
Display_cursor();
Save_picture(CONTEXT_BRUSH);
Hide_cursor();
break;
}
Display_cursor();
}
//---------------------------- Courbes de Bézier ----------------------------
void Button_Curves(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(Selected_curve_mode);
Display_cursor();
}
void Button_Curves_switch_mode(int btn)
{
if (Selected_curve_mode==OPERATION_4_POINTS_CURVE)
Selected_curve_mode=OPERATION_3_POINTS_CURVE;
else
Selected_curve_mode=OPERATION_4_POINTS_CURVE;
Hide_cursor();
Display_sprite_in_menu(btn,Selected_curve_mode==OPERATION_4_POINTS_CURVE?MENU_SPRITE_4_POINTS_CURVE:-1);
Draw_menu_button(btn,BUTTON_PRESSED);
Start_operation_stack(Selected_curve_mode);
Display_cursor();
}
//--------------------------------- Spray -----------------------------------
void Button_Airbrush(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_AIRBRUSH);
Display_cursor();
}
void Refresh_airbrush_settings(byte selected_color, byte update_slider)
{
char str[4];
if (update_slider)
{
Window_scroller_button_list->Position=49-Airbrush_multi_flow[selected_color];
Window_draw_slider(Window_scroller_button_list);
}
Num2str(Airbrush_multi_flow[selected_color],str,2);
Print_in_window(196,130,str,MC_Black,MC_Light);
Update_window_area(Window_palette_button_list->Pos_X+4+(selected_color >> 4)*10,
Window_palette_button_list->Pos_Y+3+(selected_color & 15)* 5,
2,5);
}
void Button_Airbrush_menu(int btn)
{
static byte spray_init=1;
short clicked_button;
char str[4];
word index;
byte selected_color=Fore_color;
byte old_airbrush_mode =Airbrush_mode;
short old_airbrush_size =Airbrush_size;
byte old_airbrush_delay =Airbrush_delay;
byte old_airbrush_mono_flow=Airbrush_mono_flow;
byte old_airbrush_multi_flow[256];
T_Special_button * input_size_button;
T_Special_button * input_delay_button;
T_Special_button * input_flow_button;
T_Special_button * input_init_button;
word old_mouse_x;
word old_mouse_y;
byte old_mouse_k;
byte color;
byte click;
(void)btn;
memcpy(old_airbrush_multi_flow,Airbrush_multi_flow,256);
Open_window(226,170,"Spray");
Window_set_normal_button(110,148,51,14,"Cancel" ,0,1,KEY_ESC); // 1
Window_set_normal_button(166,148,51,14,"OK" ,0,1,KEY_RETURN); // 2
Window_set_scroller_button(178,62,74,50,1,49-Airbrush_multi_flow[selected_color]); // 3
Window_set_palette_button(7,56); // 4
Window_set_normal_button( 8,148,83,14,"Mode: ",0,1,KEY_TAB); // 5
if (Airbrush_mode)
Print_in_window(50,151," Mono",MC_Black,MC_Light);
else
Print_in_window(50,151,"Multi",MC_Black,MC_Light);
Window_set_normal_button(194, 62,19,14,"+1" ,0,1,KEY_KP_PLUS); // 6
Window_set_normal_button(194, 79,19,14,"-1" ,0,1,KEY_KP_MINUS); // 7
Window_set_normal_button(194, 96,19,14,"x2" ,0,1,KEY_KP_MULTIPLY); // 8
Window_set_normal_button(194,113,19,14,"\xf7""2" ,0,1,KEY_KP_ENTER); // 9
Window_set_normal_button( 8, 37,43,14,"Clear" ,1,1,KEY_c); // 10
Print_in_window_underscore(142,25,"Size:" ,MC_Dark,MC_Light,1);
input_size_button = Window_set_input_button_s(186,23,3,KEY_s); // 11
Num2str(Airbrush_size,str,3);
Window_input_content(input_size_button,str);
Print_in_window_underscore(142,39,"Delay:" ,MC_Dark,MC_Light,1);
input_delay_button = Window_set_input_button_s(194,37,2,KEY_d); // 12
Num2str(Airbrush_delay,str,2);
Window_input_content(input_delay_button,str);
Print_in_window_underscore( 27,24,"Mono-Flow:",MC_Dark,MC_Light,1);
input_flow_button = Window_set_input_button_s(111,22,2,KEY_m); // 13
Num2str(Airbrush_mono_flow,str,2);
Window_input_content(input_flow_button,str);
Print_in_window_underscore( 67,40,"Init:",MC_Dark,MC_Light,1);
input_init_button = Window_set_input_button_s(111,38,2,KEY_i); // 14
Num2str(spray_init,str,2);
Window_input_content(input_init_button,str);
Window_display_frame(173,56,45,86);
Window_display_frame(137,19,81,33);
// On tagge toutes les couleurs utilisées
for (index=0; index<256; index++)
if (Airbrush_multi_flow[index])
Stencil_tag_color(index,MC_Black);
// Et enfin, on tagge la couleur sélectionnée
Stencil_tag_color(selected_color,MC_White);
Refresh_airbrush_settings(selected_color,0);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
Stencil_update_color(selected_color);
do
{
old_mouse_x=Mouse_X;
old_mouse_y=Mouse_Y;
old_mouse_k=Mouse_K;
clicked_button=Window_clicked_button();
switch (clicked_button)
{
case 0 :
case 2 : // OK
break;
case 1 : // Cancel
Airbrush_mode =old_airbrush_mode;
Airbrush_size =old_airbrush_size;
Airbrush_delay =old_airbrush_delay;
Airbrush_mono_flow=old_airbrush_mono_flow;
memcpy(Airbrush_multi_flow,old_airbrush_multi_flow,256);
break;
case 3 : // Scroller
Hide_cursor();
Airbrush_multi_flow[selected_color]=49-Window_attribute2;
Refresh_airbrush_settings(selected_color,0);
Display_cursor();
break;
case -1 :
case 4 : // Palette
if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) )
{
Hide_cursor();
Stencil_tag_color(selected_color,(Airbrush_multi_flow[selected_color])?MC_Black:MC_Light);
Stencil_update_color(selected_color);
// Mettre la couleur sélectionnée à jour suivant le click
selected_color=(clicked_button==4) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y);
if (Mouse_K==2)
Airbrush_multi_flow[selected_color]=0;
else
if (Airbrush_multi_flow[selected_color]==0)
Airbrush_multi_flow[selected_color]=spray_init;
// Tagger la couleur sélectionnée en blanc
Stencil_tag_color(selected_color,MC_White);
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
Stencil_update_color(selected_color);
}
break;
case 5 : // Toggle Mode
Airbrush_mode=(Airbrush_mode+1)&1;
Hide_cursor();
if (Airbrush_mode)
Print_in_window(50,151," Mono",MC_Black,MC_Light);
else
Print_in_window(50,151,"Multi",MC_Black,MC_Light);
Update_window_area(50,151,5*8,8);
Display_cursor();
break;
case 6 : // +1
for (index=0; index<256; index++)
{
if ( (Airbrush_multi_flow[index]) && (Airbrush_multi_flow[index]<49) )
Airbrush_multi_flow[index]++;
}
Hide_cursor();
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
break;
case 7 : // -1
for (index=0; index<256; index++)
{
if (Airbrush_multi_flow[index]>1)
Airbrush_multi_flow[index]--;
}
Hide_cursor();
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
break;
case 8 : // x2
for (index=0; index<256; index++)
{
if (Airbrush_multi_flow[index])
{
Airbrush_multi_flow[index]<<=1;
if (Airbrush_multi_flow[index]>49)
Airbrush_multi_flow[index]=49;
}
}
Hide_cursor();
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
break;
case 9 : // ÷2
for (index=0; index<256; index++)
{
if (Airbrush_multi_flow[index]>1)
Airbrush_multi_flow[index]>>=1;
}
Hide_cursor();
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
break;
case 10 : // Clear
memset(Airbrush_multi_flow,0,256);
// On raffiche les infos de la couleur sélectionnée
Refresh_airbrush_settings(selected_color,1);
// On efface les anciens TAGs
Window_clear_tags();
// Tagger la couleur sélectionnée en blanc
Stencil_tag_color(selected_color,MC_White);
Stencil_update_color(selected_color);
break;
case 11 : // Size
Num2str(Airbrush_size,str,3);
Readline(188,25,str,3,INPUT_TYPE_INTEGER);
Airbrush_size=atoi(str);
// On corrige les dimensions
if (Airbrush_size>256)
{
Airbrush_size=256;
Num2str(Airbrush_size,str,3);
Window_input_content(input_size_button,str);
}
else if (!Airbrush_size)
{
Airbrush_size=1;
Num2str(Airbrush_size,str,3);
Window_input_content(input_size_button,str);
}
Display_cursor();
break;
case 12 : // Delay
Num2str(Airbrush_delay,str,2);
Readline(196,39,str,2,INPUT_TYPE_INTEGER);
Airbrush_delay=atoi(str);
// On corrige le delai
if (Airbrush_delay>99)
{
Airbrush_delay=99;
Num2str(Airbrush_delay,str,2);
Window_input_content(input_delay_button,str);
}
Display_cursor();
break;
case 13 : // Mono-Flow
Num2str(Airbrush_mono_flow,str,2);
Readline(113,24,str,2,INPUT_TYPE_INTEGER);
Airbrush_mono_flow=atoi(str);
// On corrige le flux
if (!Airbrush_mono_flow)
{
Airbrush_mono_flow=1;
Num2str(Airbrush_mono_flow,str,2);
Window_input_content(input_flow_button,str);
}
Display_cursor();
break;
case 14 : // Init
Num2str(spray_init,str,2);
Readline(113,40,str,2,INPUT_TYPE_INTEGER);
spray_init=atoi(str);
// On corrige la valeur
if (spray_init>=50)
{
spray_init=49;
Num2str(spray_init,str,2);
Window_input_content(input_init_button,str);
}
else if (spray_init<1)
{
spray_init=1;
Num2str(spray_init,str,2);
Window_input_content(input_init_button,str);
}
Display_cursor();
break;
}
if (!Mouse_K)
switch (Key)
{
case KEY_BACKQUOTE : // Récupération d'une couleur derrière le menu
case KEY_COMMA :
Get_color_behind_window(&color,&click);
if (click)
{
Hide_cursor();
Stencil_tag_color(selected_color,(Airbrush_multi_flow[selected_color])?MC_Black:MC_Light);
Stencil_update_color(selected_color);
// Mettre la couleur sélectionnée à jour suivant le click
selected_color=color;
if (click==2)
Airbrush_multi_flow[selected_color]=0;
else
if (Airbrush_multi_flow[selected_color]==0)
Airbrush_multi_flow[selected_color]=spray_init;
// Tagger la couleur sélectionnée en blanc
Stencil_tag_color(selected_color,MC_White);
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
Stencil_update_color(selected_color);
Wait_end_of_click();
}
Key=0;
break;
default:
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Window_help(BUTTON_AIRBRUSH, NULL);
Key=0;
break;
}
if (Is_shortcut(Key,0x200+BUTTON_AIRBRUSH))
{
clicked_button=2;
break;
}
}
}
while ( (clicked_button!=1) && (clicked_button!=2) && !Quit_is_required);
Close_window();
/*
// Tant que l'on aura pas résolu le problème du désenclenchement du mode
// de dessin précedent, il faudra laisser ça en remarque et donc passer en
// spray même si on a clické sur Cancel (idem pour OK (un peu plus bas)).
if (clicked_button==1) // Cancel
{
if (Current_operation!=OPERATION_AIRBRUSH)
Unselect_button(BUTTON_AIRBRUSH);
}
*/
Display_cursor();
/*
if (clicked_button==2) // OK
*/
if (Current_operation!=OPERATION_AIRBRUSH)
Select_button(BUTTON_AIRBRUSH,LEFT_SIDE);
}
// -- Gestion des boutons de polygone vide et plein -------------------------
void Button_polygon(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_POLYGON);
Display_cursor();
}
void Button_Polyform(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_POLYFORM);
Display_cursor();
}
void Button_Polyfill(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_POLYFILL);
Display_cursor();
}
void Button_Filled_polyform(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_FILLED_POLYFORM);
Display_cursor();
}
// -- Boutons d'ajustement de l'image ---------------------------------------
void Button_Adjust(int btn)
{
(void)btn;
Hide_cursor();
Start_operation_stack(OPERATION_SCROLL);
Display_cursor();
}
// -- Menu des effets (Shade, Stencil, etc...) ------------------------------
void Display_effect_sprite(int sprite_number, short start_x, short start_y)
{
short x,y,x_pos,y_pos;
for (y=0,y_pos=start_y;yEffect_sprite[sprite_number][y][x]);
Update_rect(ToWinX(start_x),ToWinY(start_y),EFFECT_SPRITE_WIDTH*Menu_factor_X,EFFECT_SPRITE_HEIGHT*Menu_factor_Y);
}
void Display_effect_state(short x, short y, char * label, byte state)
{
Window_rectangle(x+22,y+5,12,8,MC_Light);
Print_in_window(x+22,y+5,label,(state)?MC_White:MC_Black,MC_Light);
if (state)
Window_select_normal_button(x, y, 16, 16);
else
Window_unselect_normal_button(x, y, 16, 16);
}
#define C1 10
#define C2 99
#define C3 184
#define L1 19
#define L2 38
#define L3 57
#define L4 76
#define L5 95
void Display_effect_states(void)
{
Display_effect_state(C1, L2, "Shade" ,Shade_mode);
Display_effect_state(C1, L3, "Q-shade",Quick_shade_mode);
Display_effect_state(C1, L4, "Transp.",Colorize_mode);
Display_effect_state(C1, L5, "Smooth" ,Smooth_mode);
Display_effect_state(C2, L5, "Smear" ,Smear_mode);
Display_effect_state(C2, L1, "Stencil",Stencil_mode);
Display_effect_state(C2, L2, "Mask" ,Mask_mode);
Display_effect_state(C2, L3, "Sieve" ,Sieve_mode);
Display_effect_state(C3, L2, "Snap" ,Snap_mode);
Display_effect_state(C3, L4, "Tiling" ,Tiling_mode);
Display_effect_state(C2,L4, "8 bit" ,Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION);
Display_effect_state(C3,L3, "Tilemap",Main.tilemap_mode);
}
void Display_feedback_state(void)
{
Print_in_window(14,24,(Config.FX_Feedback)?"X":" ",MC_Black,MC_Light);
}
void Button_Effects(int btn)
{
short clicked_button;
byte exit_by_close_button=0;
Open_window(270,152,"Drawing modes (effects)");
Window_set_normal_button(C1, L2, 16,16,"",0,1,Config_Key[SPECIAL_SHADE_MODE][0]); // 1
Window_set_normal_button(C1, L3, 16,16,"",0,1,Config_Key[SPECIAL_QUICK_SHADE_MODE][0]); // 2
Window_set_normal_button(C1, L4, 16,16,"",0,1,Config_Key[SPECIAL_COLORIZE_MODE][0]); // 3
Window_set_normal_button(C1, L5, 16,16,"",0,1,Config_Key[SPECIAL_SMOOTH_MODE][0]); // 4
Window_set_normal_button(C2, L5, 16,16,"",0,1,Config_Key[SPECIAL_SMEAR_MODE][0]); // 5
Window_set_normal_button(C2, L1, 16,16,"",0,1,Config_Key[SPECIAL_STENCIL_MODE][0]); // 6
Window_set_normal_button(C2, L2, 16,16,"",0,1,Config_Key[SPECIAL_MASK_MODE][0]); // 7
Window_set_normal_button(C2, L3, 16,16,"",0,1,Config_Key[SPECIAL_SIEVE_MODE][0]); // 8
Window_set_normal_button(C3, L2, 16,16,"",0,1,Config_Key[SPECIAL_GRID_MODE][0]); // 9
Window_set_normal_button(C3, L4, 16,16,"",0,1,Config_Key[SPECIAL_TILING_MODE][0]); // 10
Window_set_normal_button(195,131, 68,14,"Close",0,1,KEY_RETURN); // 11
Window_set_normal_button(118,131, 68,14,"All off",0,1,KEY_DELETE); // 12
// "Feedback" frame
Window_display_frame_mono(C1-5,L1+8,90,88,MC_Dark);
Window_rectangle(C1-1, L1+2, 78, 14, MC_Light);
Window_set_normal_button(C1+1,L1+2,14,14," ",0,1,KEY_f); // 13
Print_in_window_underscore(28,24,"Feedback",MC_Dark,MC_Light,1);
Window_set_normal_button(C2, L4, 16,16,"",0,1,Config_Key[SPECIAL_FORMAT_CHECKER_MENU][0]); // 14
Window_set_normal_button(C3, L3, 16,16,"",0,1,Config_Key[SPECIAL_TILEMAP_MODE][0]); // 15
// "Grid" frame
Window_display_frame_mono(C3-5,L1+8,86,88,MC_Dark);
Window_rectangle(C3-1, L1+2, 52, 14, MC_Light);
Window_set_normal_button(C3+1,L1+2,14,14,Show_grid?"X":" ",0,1,Config_Key[SPECIAL_SHOW_GRID][0]); // 16
Print_in_window(C3+17,L1+5,"Grid",MC_Dark,MC_Light);
Display_feedback_state();
Display_effect_sprite(EFFECTS_SPRITE_SHADE, C1+1,L2+1);
Display_effect_sprite(EFFECTS_SPRITE_SHADE, C1+1,L3+1);
Display_effect_sprite(EFFECTS_SPRITE_TRANSP, C1+1,L4+1);
Display_effect_sprite(EFFECTS_SPRITE_SMOOTH, C1+1,L5+1);
Display_effect_sprite(EFFECTS_SPRITE_SMEAR, C2+1,L5+1);
Display_effect_sprite(EFFECTS_SPRITE_STENCIL,C2+1,L1+1);
Display_effect_sprite(EFFECTS_SPRITE_MASK, C2+1,L2+1);
Display_effect_sprite(EFFECTS_SPRITE_SIEVE, C2+1,L3+1);
Display_effect_sprite(EFFECTS_SPRITE_GRID, C3+1,L2+1);
Display_effect_sprite(EFFECTS_SPRITE_TILING, C3+1,L4+1);
Display_effect_sprite(EFFECTS_SPRITE_8BIT, C2+1,L4+1);
Display_effect_sprite(EFFECTS_SPRITE_TILING, C3+1,L3+1); // tilemap
Display_effect_states();
Print_in_window(12,118,"click:",MC_Dark,MC_Light);
Print_in_window(16,128,"Left:Switch",MC_Dark,MC_Light);
Print_in_window(16,138,"Right:Edit",MC_Dark,MC_Light);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button = Window_clicked_button();
if (Key==KEY_ESC || Is_shortcut(Key,0x100+BUTTON_EFFECTS))
{
clicked_button=11;
Key=0;
}
else if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
// Aide contextuelle
switch(Window_get_clicked_button())
{
case 1:
Window_help(BUTTON_EFFECTS, "SHADE");
break;
case 2:
Window_help(BUTTON_EFFECTS, "QUICK SHADE");
break;
case 3:
Window_help(BUTTON_EFFECTS, "TRANSPARENCY");
break;
case 4:
Window_help(BUTTON_EFFECTS, "SMOOTH");
break;
case 5:
Window_help(BUTTON_EFFECTS, "SMEAR");
break;
case 6:
Window_help(BUTTON_EFFECTS, "STENCIL");
break;
case 7:
Window_help(BUTTON_EFFECTS, "MASK");
break;
case 8:
Window_help(BUTTON_EFFECTS, "SIEVE");
break;
case 9:
Window_help(BUTTON_EFFECTS, "GRID");
break;
case 10:
Window_help(BUTTON_EFFECTS, "TILING");
break;
case 14:
Window_help(BUTTON_EFFECTS, "8 BIT");
break;
case 15:
Window_help(BUTTON_EFFECTS, "TILEMAP");
break;
default:
Window_help(BUTTON_EFFECTS, NULL);
}
// Hack because we have used Window_get_clicked_button()
Input_sticky_control=0;
//
}
switch (clicked_button)
{
case 1 : // Shade
if (Window_attribute1==LEFT_SIDE)
{
Button_Shade_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Shade_menu();
clicked_button=11;
}
break;
case 2 : // Quick-shade
if (Window_attribute1==LEFT_SIDE)
{
Button_Quick_shade_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Quick_shade_menu();
clicked_button=11;
}
break;
case 3 : // Colorize / Transparency
if (Window_attribute1==LEFT_SIDE)
{
Button_Colorize_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Colorize_menu();
clicked_button=11;
}
break;
case 4 : // Smooth
if (Window_attribute1==LEFT_SIDE)
{
Button_Smooth_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Smooth_menu();
clicked_button=11;
}
break;
case 5 : // Smear
Button_Smear_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
break;
case 6 : // Stencil
if (Window_attribute1==LEFT_SIDE)
{
Button_Stencil_mode();
Hide_cursor();
Display_effect_state(C2,L1,"Stencil",Stencil_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Stencil_menu();
clicked_button=11;
}
break;
case 7 : // Mask
if (Window_attribute1==LEFT_SIDE)
{
Button_Mask_mode();
Hide_cursor();
Display_effect_state(C2,L2,"Mask",Mask_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Mask_menu();
clicked_button=11;
}
break;
case 8 : // Sieve
if (Window_attribute1==LEFT_SIDE)
{
Button_Sieve_mode();
Hide_cursor();
Display_effect_state(C2,L3,"Sieve",Sieve_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Sieve_menu();
clicked_button=11;
}
break;
case 9 : // Grid
if (Window_attribute1==LEFT_SIDE)
{
Button_Snap_mode();
Hide_cursor();
Display_effect_state(C3,L2,"Snap",Snap_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Grid_menu();
clicked_button=11;
}
break;
case 10 : // Tiling
if (Window_attribute1==LEFT_SIDE)
{
Button_Tiling_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Tiling_menu();
clicked_button=11;
}
break;
case 11 : // Close
exit_by_close_button=1;
break;
case 12 : // All off
Effects_off();
Hide_cursor();
Display_effect_states();
Display_cursor();
break;
case 13 : // Feedback (pour Colorize et Shade)
Config.FX_Feedback = !Config.FX_Feedback;
Update_FX_feedback(Config.FX_Feedback);
Hide_cursor();
Display_feedback_state();
Display_cursor();
break;
case 14: // Constraint checker/enforcer
if (Window_attribute1==LEFT_SIDE && Selected_Constraint_Mode > IMAGE_MODE_ANIMATION)
{
Button_Constraint_mode();
Hide_cursor();
Display_effect_state(C2,L4, "8 bit" ,Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION);
Display_cursor();
} else {
Close_window();
Display_cursor();
Button_Constraint_menu();
clicked_button = 11;
}
break;
case 15: // Tilemap
if (Window_attribute1==LEFT_SIDE)
{
Button_Tilemap_mode();
Hide_cursor();
Display_effect_state(C3,L3, "Tilemap" ,Main.tilemap_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Tilemap_menu();
clicked_button=11;
}
break;
case 16: // Show grid
Show_grid = !Show_grid;
Hide_cursor();
Print_in_window(C3+4, L1+5, Show_grid?"X":" ", MC_Black, MC_Light);
Display_cursor();
}
}
while (clicked_button!=11 && !Quit_is_required);
if (exit_by_close_button || Quit_is_required)
Close_window();
else
Hide_cursor();
if (!Any_effect_active())
Unselect_button(btn);
Display_cursor();
}
#undef C2
// Callback to display a font name in the list
void Draw_one_font_name(word x, word y, word index, byte highlighted)
{
Print_in_window(x,y,Font_label(index), MC_Black, (highlighted)?MC_Dark:MC_Light);
}
void Button_Text(int btn)
{
static char str[256]="";
static int font_size=32;
static int antialias=1;
static short list_start=0; // index de le premiere fonte dans le selector
static short cursor_position=0; // index de la ligne active dans le selector
static short selected_font_index=0;
static short is_bold=0;
static short is_italic=0;
byte * new_brush=NULL;
T_Palette text_palette;
int new_width;
int new_height;
int clicked_button;
const int NB_FONTS=8;
char size_buffer[4];
T_Special_button * input_size_button;
T_Special_button * input_text_button;
T_Special_button * preview_button;
T_Special_button * font_list_button;
T_Scroller_button * font_scroller;
T_List_button * font_list;
byte redraw_is_needed=1;
byte preview_is_needed=1;
(void)btn;
Open_window(288,180,"Text");
// Texte saisi
Print_in_window_underscore(6,20,"Text:",MC_Dark,MC_Light,1);
input_text_button = Window_set_input_button_s(48,18,29,KEY_t); // 1
// TrueType options
Window_display_frame_in(182,34,100,68);
Print_in_window(199,31,"TrueType", MC_Dark, MC_Light);
// AA
Window_set_normal_button(188,58,13,11,antialias?"X":" ",0,1,KEY_a); // 2
Print_in_window_underscore(206,60,"AntiAlias", MC_Dark, MC_Light,5);
// Bold
Window_set_normal_button(188,72,13,11,is_bold?"X":" ",0,1,KEY_b); // 3
Print_in_window_underscore(206,75,"Bold", MC_Dark, MC_Light,1);
// Italic
Window_set_normal_button(188,86,13,11,is_italic?"X":" ",0,1,KEY_i); // 4
Print_in_window_underscore(206,89,"Italic", MC_Dark, MC_Light,1);
// Scroller des fontes
font_scroller = Window_set_scroller_button(165,35,NB_FONTS*8,Font_count(),NB_FONTS,list_start); // 5
// Liste des fontes disponibles
font_list_button = Window_set_special_button(8,35,152,NB_FONTS*8,0); // 6
Window_display_frame_in(7, 33, 154, NB_FONTS*8+4);
// Taille texte
input_size_button = Window_set_input_button_s(220,43,3,KEY_s); // 7
Window_set_repeatable_button(202,43,13,11,"-",0,1,KEY_NONE); // 8
Window_set_repeatable_button(251,43,13,11,"+",0,1,KEY_NONE); // 9
// Preview
preview_button = Window_set_special_button(8,106,273,50,0); // 10
Window_display_frame_in(7, 105, 275, 52);
Window_set_normal_button(8,160,40,14,"OK",0,1,KEY_RETURN); // 11
Window_set_normal_button(54,160,60,14,"Cancel",0,1,KEY_ESC); // 12
// List of fonts
font_list = Window_set_list_button(font_list_button, font_scroller, Draw_one_font_name, 2); // 13
// Restore its settings from last passage in screen
font_list->List_start = list_start;
font_list->Cursor_position = cursor_position;
Window_redraw_list(font_list);
Update_window_area(0,0,Window_width, Window_height);
// str texte
Window_input_content(input_text_button,str);
// Taille police
redraw_is_needed=1;
// --
while (1)
{
if (redraw_is_needed)
{
// Taille
Num2str(font_size,size_buffer,3);
Window_input_content(input_size_button,size_buffer);
}
if (preview_is_needed)
{
const char * preview_string = "AaBbCcDdEeFf012345";
byte is_truetype;
if (str[0])
preview_string=str;
is_truetype=TrueType_font(selected_font_index);
free(new_brush);
new_brush = Render_text(preview_string, selected_font_index, font_size, antialias, is_bold, is_italic, &new_width, &new_height, text_palette);
// Background:
if (antialias&&is_truetype)
// Solid
Window_rectangle(8, 106, 273, 50,MC_Black);
else if (is_truetype)
{
long l = text_palette[Fore_color].R+text_palette[Fore_color].G+text_palette[Fore_color].B;
Window_rectangle(8, 106, 273, 50,l>128*3? MC_Black:MC_Light);
}
else
{
long l = text_palette[Back_color].R+text_palette[Back_color].G+text_palette[Back_color].B;
Window_rectangle(8, 106, 273, 50,l>128*3? MC_Light:MC_Black);
}
if (new_brush)
{
if (!is_truetype || (is_truetype&&antialias))
{
// Display brush in remapped form.
byte *remapped_brush;
remapped_brush=(byte *)malloc(new_width*new_height);
if (remapped_brush)
{
// This code is mostly copied from Remap_brush()
short x_pos;
short y_pos;
int color;
byte colmap[256];
for (color=0;color<=255;color++)
colmap[color]=0;
for (y_pos=0;y_posPos_X*Menu_factor_X,
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
0,
0,
Min(preview_button->Width*Menu_factor_X, new_width),
Min(preview_button->Height*Menu_factor_Y, new_height),
Back_color,
new_width);
free(remapped_brush);
}
}
else
{
// Solid
Display_brush(
new_brush,
Window_pos_X+preview_button->Pos_X*Menu_factor_X,
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
0,
0,
Min(preview_button->Width*Menu_factor_X, new_width),
Min(preview_button->Height*Menu_factor_Y, new_height),
Back_color,
new_width);
}
}
Update_window_area(
preview_button->Pos_X,
preview_button->Pos_Y,
preview_button->Width,
preview_button->Height);
}
if (redraw_is_needed || preview_is_needed)
{
redraw_is_needed=0;
preview_is_needed=0;
Display_cursor();
}
clicked_button=Window_clicked_button();
if (Quit_is_required)
clicked_button = 12; // cancel
if (clicked_button==0)
{
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_TEXT, NULL);
else if (Is_shortcut(Key,0x100+BUTTON_TEXT))
clicked_button = 12; // cancel
}
switch(clicked_button)
{
case 1: // Texte saisi
Readline_ex(50,20,str,29,250,INPUT_TYPE_STRING,0);
preview_is_needed=1;
break;
case 2: // AA
antialias = (antialias==0);
Hide_cursor();
Print_in_window(191,60,antialias?"X":" ", MC_Black, MC_Light);
preview_is_needed=1;
break;
case 3: // Bold
is_bold = (is_bold==0);
Hide_cursor();
Print_in_window(191,74,is_bold?"X":" ", MC_Black, MC_Light);
preview_is_needed=1;
break;
case 4: // Italic
is_italic = (is_italic==0);
Hide_cursor();
Print_in_window(191,88,is_italic?"X":" ", MC_Black, MC_Light);
preview_is_needed=1;
break;
case 5: // Scroller des fontes
/* Cannot happen, event is catched by the list control */
break;
case 13: // Font selection
selected_font_index = Window_attribute2;
Hide_cursor();
preview_is_needed=1;
break;
case 7: // Taille du texte (nombre)
Readline(222,45,size_buffer,3,INPUT_TYPE_INTEGER);
font_size=atoi(size_buffer);
// On corrige les dimensions
if (font_size < 1)
{
font_size = 1;
}
else if (font_size>500)
{
font_size = 500;
}
redraw_is_needed=1;
preview_is_needed=1;
break;
case 8: // Taille -
if (font_size > 1)
{
font_size--;
Hide_cursor();
redraw_is_needed=1;
preview_is_needed=1;
}
break;
case 9: // Taille +
if (font_size < 255)
{
font_size++;
Hide_cursor();
redraw_is_needed=1;
preview_is_needed=1;
}
break;
case 6: // Double-click font selector
case 11: // OK
// Save the selector settings
list_start = font_list->List_start;
cursor_position = font_list->Cursor_position;
if (!new_brush)
{
// Si echec de rendu
Close_window();
Unselect_button(BUTTON_TEXT);
Display_cursor();
Error(0);
return;
}
if (Realloc_brush(new_width, new_height, new_brush, NULL))
{
free(new_brush);
Close_window();
Unselect_button(BUTTON_TEXT);
Display_cursor();
Error(0);
}
// Grab palette
memcpy(Brush_original_palette, text_palette,sizeof(T_Palette));
// Remap to image's palette
Remap_brush();
Brush_offset_X=Brush_width>>1;
Brush_offset_Y=Brush_height>>1;
// Fermeture
Close_window();
Unselect_button(BUTTON_TEXT);
// On passe en brosse:
Display_cursor();
if (antialias || !TrueType_font(selected_font_index))
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
else
Change_paintbrush_shape(PAINTBRUSH_SHAPE_MONO_BRUSH);
// Activate alpha mode
if (antialias && TrueType_font(selected_font_index))
{
Shade_mode=0;
Quick_shade_mode=0;
Smooth_mode=0;
Tiling_mode=0;
Smear_mode=0;
Colorize_mode=1;
Colorize_current_mode=3;
Effect_function=Effect_alpha_colorize;
Draw_menu_button(BUTTON_EFFECTS,BUTTON_PRESSED);
}
Select_button(BUTTON_DRAW,LEFT_SIDE);
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu à la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Select_button(BUTTON_DRAW,RIGHT_SIDE);
}
//Display_cursor();
return;
case 12: // Cancel
// Save the selector settings
list_start = font_list->List_start;
cursor_position = font_list->Cursor_position;
free(new_brush);
new_brush = NULL;
Close_window();
Unselect_button(BUTTON_TEXT);
Display_cursor();
return;
}
}
}
void Display_stored_brush_in_window(word x_pos,word y_pos,int index)
{
if (Brush_container[index].Paintbrush_shape < PAINTBRUSH_SHAPE_MAX)
{
int x,y;
int offset_x=0, offset_y=0;
//int brush_offset_x=0, brush_offset_y=0;
// Determine draw offset (small brushes are stacked on corner of their preview)
if (Brush_container[index].WidthBRUSH_CONTAINER_PREVIEW_WIDTH)
brush_offset_x = (Paintbrush_width-BRUSH_CONTAINER_PREVIEW_WIDTH)/2;
if (Paintbrush_height>BRUSH_CONTAINER_PREVIEW_HEIGHT)
brush_offset_y = (Paintbrush_height-BRUSH_CONTAINER_PREVIEW_HEIGHT)/2;
for (y=0; yBRUSH_CONTAINER_PREVIEW_WIDTH ||
Brush_height>BRUSH_CONTAINER_PREVIEW_HEIGHT)
{
// Scale
Rescale(Brush_original_pixels, Brush_width, Brush_height, (byte *)(Brush_container[index].Thumbnail), BRUSH_CONTAINER_PREVIEW_WIDTH, BRUSH_CONTAINER_PREVIEW_HEIGHT, 0, 0);
}
else
{
// Direct copy
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);
}
}
else
{
Error(0);
}
}
}
/// Retrieve a normal paintbrush
void Select_paintbrush(int index)
{
int x_pos,y_pos;
Paintbrush_shape=Paintbrush[index].Shape;
if (Paintbrush[index].Width<=PAINTBRUSH_WIDTH &&
Paintbrush[index].Height<=PAINTBRUSH_HEIGHT)
{
Paintbrush_width=Paintbrush[index].Width;
Paintbrush_height=Paintbrush[index].Height;
Paintbrush_offset_X=Paintbrush[index].Offset_X;
Paintbrush_offset_Y=Paintbrush[index].Offset_Y;
for (y_pos=0; y_posPAINTBRUSH_WIDTH)
x_off=(Paintbrush_width-PAINTBRUSH_WIDTH)/2;
if (Paintbrush_height>PAINTBRUSH_HEIGHT)
y_off=(Paintbrush_height-PAINTBRUSH_HEIGHT)/2;
for (y_pos=0; y_pos>1;
Paintbrush_offset_Y=Paintbrush_height>>1;
}
else
{
// Recreate the brush pixels from its shape and dimensions
Set_paintbrush_size(Paintbrush_width,Paintbrush_height);
}
}
// Color brushes
if (shape == PAINTBRUSH_SHAPE_COLOR_BRUSH ||
shape == PAINTBRUSH_SHAPE_MONO_BRUSH)
{
Paintbrush_shape=shape;
if (!Realloc_brush(Brush_container[index].Width,Brush_container[index].Height,NULL,NULL))
{
// Recover pixels
memcpy(Brush_original_pixels, Brush_container[index].Brush, (long)Brush_height*Brush_width);
// Grab palette
memcpy(Brush_original_palette, Brush_container[index].Palette, sizeof(T_Palette));
// Recover colormap
memcpy(Brush_colormap, Brush_container[index].Colormap, 256);
// Remap using current colormap
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Brush_offset_X=Brush_width>>1;
Brush_offset_Y=Brush_height>>1;
}
}
Change_paintbrush_shape(shape);
return 1;
}
void Button_Brush_container(void)
{
short clicked_button;
short x_pos,y_pos;
byte index;
Open_window(BRUSH_CONTAINER_COLUMNS*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+8,
BRUSH_CONTAINER_ROWS*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+40,
"Brushes");
Window_set_normal_button(
(BRUSH_CONTAINER_COLUMNS*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)-59)/2,
(BRUSH_CONTAINER_ROWS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18,
67,14,"Cancel",0,1,KEY_ESC); // 1
index=0;
for (index=0; index < BRUSH_CONTAINER_ROWS*BRUSH_CONTAINER_COLUMNS; index++)
{
x_pos = (index % BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+7;
y_pos = (index / BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18;
Window_set_normal_button(
x_pos,
y_pos,
BRUSH_CONTAINER_PREVIEW_WIDTH+2,
BRUSH_CONTAINER_PREVIEW_HEIGHT+2,
"",0,1,KEY_NONE
);
Display_stored_brush_in_window(x_pos+1, y_pos+1, index);
}
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
//if (Is_shortcut(Key,0x100+BUTTON_HELP))
// Window_help(BUTTON_PAINTBRUSHES, NULL);
if (clicked_button == 1)
break;
if (clicked_button>1)
{
index = clicked_button-2;
if (Window_attribute1==RIGHT_SIDE)
{
// Store
x_pos = (index % BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+7;
y_pos = (index / BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18;
Store_brush(index);
Hide_cursor();
Display_stored_brush_in_window(x_pos+1, y_pos+1, index);
Display_cursor();
}
else
{
// Restore and exit
if (Restore_brush(index))
break;
}
}
}
while (1);
Close_window();
//Unselect_button(BUTTON_PAINTBRUSHES);
Display_cursor();
}
byte Any_effect_active(void)
{
return Shade_mode||Quick_shade_mode||Colorize_mode||Smooth_mode||Tiling_mode||Smear_mode
||Stencil_mode||Mask_mode||Sieve_mode||Snap_mode||Main.tilemap_mode || (Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION);
}