/* vim:expandtab:ts=2 sw=2: */ /* Grafx2 - The Ultimate 256-color bitmap paint program Copyright 2011 Pawel Góralski Copyright 2009 Pasi Kallinen Copyright 2008 Peter Gordon Copyright 2008 Franck Charlet Copyright 2007 Adrien Destugues Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) 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 */ #define GLOBAL_VARIABLES // time.h defines timeval which conflicts with the one in amiga SDK #ifdef __amigaos__ #include #else #include #endif #include #include #include #include #ifndef _MSC_VER #include #else #if _MSC_VER < 1900 #define snprintf _snprintf #endif #endif #if defined(USE_SDL) || defined(USE_SDL2) #include #include #endif #if defined(WIN32) #include #include #elif defined (__MINT__) #include #elif defined(__macosx__) #import #import #elif defined(__FreeBSD__) #include #endif #if !defined(WIN32) #if defined(__macosx__) #include #elif defined(__FreeBSD__) #include #else #include #endif #endif #include "gfx2log.h" #include "const.h" #include "struct.h" #include "global.h" #include "graph.h" #include "misc.h" #include "init.h" #include "buttons.h" #include "engine.h" #include "pages.h" #include "loadsave.h" #include "screen.h" #include "errors.h" #include "readini.h" #include "saveini.h" #include "io.h" #include "text.h" #include "setup.h" #include "windows.h" #include "brush.h" #include "palette.h" #include "realpath.h" #include "input.h" #include "help.h" #include "filesel.h" #if defined(WIN32) && !(defined(USE_SDL) || defined(USE_SDL2)) #include "win32screen.h" #endif #if defined (WIN32) && (defined(USE_SDL) || defined(USE_SDL2)) // On Windows, SDL_putenv is not present in any compilable header. // It can be linked anyway, this declaration only avoids // a compilation warning. extern DECLSPEC int SDLCALL SDL_putenv(const char *variable); #endif extern char Program_version[]; // generated in pversion.c static int setsize_width; static int setsize_height; #if defined(USE_SDL) || defined(USE_SDL2) /// Pointer to the current joystick controller. static SDL_Joystick* Joystick; #endif //--- Affichage de la syntaxe, et de la liste des modes vidéos disponibles --- void Display_syntax(void) { int mode_index, i; char modes[1024*2]; const char * syntax = "Syntax: grafx2 [] [] []\n\n" " can be:\n" "\t-? -h -H -help for this help screen\n" "\t-verbose to increase log verbosity\n" "\t-wide to emulate a video mode with wide pixels (2x1)\n" "\t-tall to emulate a video mode with tall pixels (1x2)\n" "\t-double to emulate a video mode with double pixels (2x2)\n" "\t-wide2 to emulate a video mode with double wide pixels (4x2)\n" "\t-tall2 to emulate a video mode with double tall pixels (2x4)\n" "\t-triple to emulate a video mode with triple pixels (3x3)\n" "\t-quadruple to emulate a video mode with quadruple pixels (4x4)\n" "\t-rgb n to reduce RGB precision (2 to 256, 256=max precision)\n" "\t-gamma n to adjust Gamma correction (1 to 30, 10=no correction)\n" "\t-skin to use an alternate file with the menu graphics\n" "\t-mode to set a video mode\n" "\t-size to set the image size\n" "Arguments can be prefixed either by / - or --\n" "They can also be abbreviated.\n\n"; fputs(syntax, stdout); i = snprintf(modes, sizeof(modes), "Available video modes:\n\n"); for (mode_index = 0; mode_index < Nb_video_modes; mode_index += 12) { int k; for (k = 0; k < 6; k++) { if (mode_index + k >= Nb_video_modes) break; i += snprintf(modes + i, sizeof(modes) - i, "%12s", Mode_label(mode_index + k)); } i += snprintf(modes + i, sizeof(modes) - i, "\n"); } fputs(modes, stdout); #if defined(WIN32) MessageBoxA(GFX2_Get_Window_Handle(), syntax, "GrafX2", MB_OK); MessageBoxA(GFX2_Get_Window_Handle(), modes, "GrafX2", MB_OK); #endif } // ---------------------------- Sortie impromptue ---------------------------- void Warning_function(const char *message, const char *filename, int line_number, const char *function_name) { GFX2_Log(GFX2_WARNING, "Warning in file %s, line %d, function %s : %s\n", filename, line_number, function_name, message); } // ---------------------------- Sortie impromptue ---------------------------- void Error_function(int error_code, const char *filename, int line_number, const char *function_name) { T_Palette temp_palette; T_Palette backup_palette; int index; char msg_buffer[512]; snprintf(msg_buffer, sizeof(msg_buffer), "Error number %d occured in file %s, line %d, function %s.\n", error_code, filename,line_number,function_name); fputs(msg_buffer, stderr); #if defined(_MSC_VER) && defined(DEBUG) OutputDebugStringA(msg_buffer); #endif if (error_code==0) { // L'erreur 0 n'est pas une vraie erreur, elle fait seulement un flash rouge de l'écran pour dire qu'il y a un problème. // Toutes les autres erreurs déclenchent toujours une sortie en catastrophe du programme ! memcpy(backup_palette, Get_current_palette(), sizeof(T_Palette)); memcpy(temp_palette, backup_palette, sizeof(T_Palette)); for (index=0;index<=255;index++) temp_palette[index].R=255; Set_palette(temp_palette); Delay_with_active_mouse(50); // Half a second of red flash Set_palette(backup_palette); } else { const char * msg = NULL; switch (error_code) { case ERROR_GUI_MISSING : snprintf(msg_buffer, sizeof(msg_buffer), "Error: File containing the GUI graphics is missing!\n" "This program cannot run without this file.\n" "\n%s", Gui_loading_error_message); msg = msg_buffer; break; case ERROR_GUI_CORRUPTED : msg = "Error: File containing the GUI graphics couldn't be parsed!\n" "This program cannot run without a correct version of this file.\n"; break; case ERROR_INI_MISSING : msg = "Error: File gfx2def.ini is missing!\n" "This program cannot run without this file.\n"; break; case ERROR_MEMORY : msg = "Error: Not enough memory!\n\n" "You should try exiting other programs to free some bytes for Grafx2.\n\n"; break; case ERROR_FORBIDDEN_MODE : msg = "Error: The requested video mode has been disabled from the resolution menu!\n" "If you want to run the program in this mode, you'll have to start it with an\n" "enabled mode, then enter the resolution menu and enable the mode you want.\n" "Check also if the 'Default_video_mode' parameter in gfx2.ini is correct.\n"; break; case ERROR_FORBIDDEN_SIZE : msg = "Error: The image dimensions all have to be in the range 1-9999!\n"; break; case ERROR_COMMAND_LINE : msg = "Error: Invalid parameter or file not found.\n\n"; break; case ERROR_SAVING_CFG : msg = "Error: Write error while saving settings!\n" "Settings have not been saved correctly, and the gfx2.cfg file may have been\n" "corrupt. If so, please delete it and Grafx2 will restore default settings.\n"; break; case ERROR_MISSING_DIRECTORY : msg = "Error: Directory you ran the program from not found!\n"; break; case ERROR_INI_CORRUPTED : snprintf(msg_buffer, sizeof(msg_buffer), "Error: File gfx2.ini is corrupt!\n" "It contains bad values at line %d.\n" "You can re-generate it by deleting the file and running GrafX2 again.\n", Line_number_in_INI_file); msg = msg_buffer; break; case ERROR_SAVING_INI : msg = "Error: Cannot rewrite file gfx2.ini!\n"; break; case ERROR_SORRY_SORRY_SORRY : msg = "Error: Sorry! Sorry! Sorry! Please forgive me!\n"; break; } if(msg != NULL) { fputs(msg, stderr); #if defined(WIN32) #if defined(DEBUG) OutputDebugStringA(msg); #endif MessageBoxA(GFX2_Get_Window_Handle(), msg, "GrafX2 error", MB_OK | MB_ICONERROR); #endif } if (error_code == ERROR_COMMAND_LINE) Display_syntax(); #if defined(USE_SDL) || defined(USE_SDL2) SDL_Quit(); #endif exit(error_code); } } enum CMD_PARAMS { CMDPARAM_HELP, CMDPARAM_MODE, CMDPARAM_PIXELRATIO_TALL, CMDPARAM_PIXELRATIO_WIDE, CMDPARAM_PIXELRATIO_DOUBLE, CMDPARAM_PIXELRATIO_TRIPLE, CMDPARAM_PIXELRATIO_QUAD, CMDPARAM_PIXELRATIO_TALL2, CMDPARAM_PIXELRATIO_TALL3, CMDPARAM_PIXELRATIO_WIDE2, CMDPARAM_RGB, CMDPARAM_GAMMA, CMDPARAM_SKIN, CMDPARAM_SIZE, CMDPARAM_VERBOSE, }; struct { const char *param; int id; } cmdparams[] = { {"?", CMDPARAM_HELP}, {"h", CMDPARAM_HELP}, {"H", CMDPARAM_HELP}, {"help", CMDPARAM_HELP}, {"mode", CMDPARAM_MODE}, {"tall", CMDPARAM_PIXELRATIO_TALL}, {"wide", CMDPARAM_PIXELRATIO_WIDE}, {"double", CMDPARAM_PIXELRATIO_DOUBLE}, {"triple", CMDPARAM_PIXELRATIO_TRIPLE}, {"quadruple", CMDPARAM_PIXELRATIO_QUAD}, {"tall2", CMDPARAM_PIXELRATIO_TALL2}, {"tall3", CMDPARAM_PIXELRATIO_TALL3}, {"wide2", CMDPARAM_PIXELRATIO_WIDE2}, {"rgb", CMDPARAM_RGB}, {"gamma", CMDPARAM_GAMMA}, {"skin", CMDPARAM_SKIN}, {"size", CMDPARAM_SIZE}, {"verbose", CMDPARAM_VERBOSE}, }; #define ARRAY_SIZE(x) (int)(sizeof(x) / sizeof(x[0])) // --------------------- Analyse de la ligne de commande --------------------- int Analyze_command_line(int argc, char * argv[], char *main_filename, char *main_directory, char *spare_filename, char *spare_directory) { char *buffer ; int index; int file_in_command_line; file_in_command_line = 0; Resolution_in_command_line = 0; Current_resolution = Config.Default_resolution; for (index = 1; index 256) { Error(ERROR_COMMAND_LINE); exit(0); } Set_palette_RGB_scale(scale); } else { Error(ERROR_COMMAND_LINE); exit(0); } break; case CMDPARAM_GAMMA: /* Gamma correction */ index++; if (index 30) { Error(ERROR_COMMAND_LINE); exit(0); } Set_palette_Gamma(scale); } else { Error(ERROR_COMMAND_LINE); exit(0); } break; case CMDPARAM_SKIN: // GUI skin file index++; if (index 9999 || setsize_width < 1 || setsize_width > 9999) { Error(ERROR_FORBIDDEN_SIZE); exit(0); } } else { Error(ERROR_COMMAND_LINE); exit(0); } break; case CMDPARAM_VERBOSE: GFX2_verbosity_level++; break; default: // Si ce n'est pas un paramètre, c'est le nom du fichier à ouvrir if (file_in_command_line > 1) { // Il y a déjà 2 noms de fichiers et on vient d'en trouver un 3ème Error(ERROR_COMMAND_LINE); exit(0); } else if (File_exists(argv[index])) { file_in_command_line ++; buffer = Realpath(argv[index], NULL); if (file_in_command_line == 1) { // Separate path from filename Extract_path(main_directory, buffer); Extract_filename(main_filename, buffer); } else { // Separate path from filename Extract_path(spare_directory, buffer); Extract_filename(spare_filename, buffer); } free(buffer); buffer = NULL; } else { Error(ERROR_COMMAND_LINE); exit(0); } break; } } return file_in_command_line; } // Compile-time assertions: #define CT_ASSERT(e) extern char (*ct_assert(void)) [sizeof(char[1 - 2*!(e)])] // This line will raise an error at compile time // when sizeof(T_Components) is not 3. CT_ASSERT(sizeof(T_Components)==3); // This line will raise an error at compile time // when sizeof(T_Palette) is not 768. CT_ASSERT(sizeof(T_Palette)==768); // ------------------------ Initialiser le programme ------------------------- // Returns 0 on fail int Init_program(int argc,char * argv[]) { int temp; int starting_videomode; enum IMAGE_MODES starting_image_mode; static char program_directory[MAX_PATH_CHARACTERS]; T_Gui_skin *gfx; int file_in_command_line; T_Gradient_array initial_gradients; static char main_filename [MAX_PATH_CHARACTERS]; #ifdef ENABLE_FILENAMES_ICONV static word main_filename_unicode[MAX_PATH_CHARACTERS]; #endif static char main_directory[MAX_PATH_CHARACTERS]; static char spare_filename [MAX_PATH_CHARACTERS]; static char spare_directory[MAX_PATH_CHARACTERS]; #if defined(__MINT__) printf("===============================\n"); printf(" /|\\ GrafX2 %.19s\n", Program_version); printf(" compilation date: %.16s\n", __DATE__); printf("===============================\n"); #endif #ifdef ENABLE_FILENAMES_ICONV // iconv is used to convert filenames cd = iconv_open(TOCODE, FROMCODE); // From UTF8 to ANSI cd_inv = iconv_open(FROMCODE, TOCODE); // From ANSI to UTF8 #if (defined(SDL_BYTEORDER) && (SDL_BYTEORDER == SDL_BIG_ENDIAN)) || (defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)) cd_utf16 = iconv_open("UTF-16BE", FROMCODE); // From UTF8 to UTF16 cd_utf16_inv = iconv_open(FROMCODE, "UTF-16BE"); // From UTF16 to UTF8 #else cd_utf16 = iconv_open("UTF-16LE", FROMCODE); // From UTF8 to UTF16 cd_utf16_inv = iconv_open(FROMCODE, "UTF-16LE"); // From UTF16 to UTF8 #endif #endif /* ENABLE_FILENAMES_ICONV */ // On crée dès maintenant les descripteurs des listes de pages pour la page // principale et la page de brouillon afin que leurs champs ne soient pas // invalide lors des appels aux multiples fonctions manipulées à // l'initialisation du programme. Main.backups=(T_List_of_pages *)malloc(sizeof(T_List_of_pages)); Spare.backups=(T_List_of_pages *)malloc(sizeof(T_List_of_pages)); Init_list_of_pages(Main.backups); Init_list_of_pages(Spare.backups); // Determine the executable directory Set_program_directory(argv[0],program_directory); // Choose directory for data (read only) Set_data_directory(program_directory,Data_directory); // Choose directory for settings (read/write) Set_config_directory(program_directory,Config_directory); // On détermine le répertoire courant: Get_current_directory(Main.selector.Directory,Main.selector.Directory_unicode,MAX_PATH_CHARACTERS); // On en profite pour le mémoriser dans le répertoire principal: strcpy(Initial_directory,Main.selector.Directory); // On initialise les données sur le nom de fichier de l'image de brouillon: strcpy(Spare.selector.Directory,Main.selector.Directory); Main.fileformat=DEFAULT_FILEFORMAT; Spare.fileformat =DEFAULT_FILEFORMAT; strcpy(Brush_selector.Directory,Main.selector.Directory); strcpy(Brush_file_directory,Main.selector.Directory); strcpy(Brush_filename ,"NO_NAME.GIF"); Brush_fileformat =DEFAULT_FILEFORMAT; strcpy(Palette_selector.Directory,Main.selector.Directory); // On initialise ce qu'il faut pour que les fileselects ne plantent pas: Main.selector.Position=0; // Au début, le fileselect est en haut de la liste des fichiers Main.selector.Offset=0; // Au début, le fileselect est en haut de la liste des fichiers Main.selector.Format_filter=FORMAT_ALL_IMAGES; Main.current_layer=0; Main.layers_visible=0xFFFFFFFF; Main.layers_visible_backup=0xFFFFFFFF; Spare.current_layer=0; Spare.layers_visible=0xFFFFFFFF; Spare.layers_visible_backup=0xFFFFFFFF; Spare.selector.Position=0; Spare.selector.Offset=0; Spare.selector.Format_filter=FORMAT_ALL_IMAGES; Brush_selector.Position=0; Brush_selector.Offset=0; Brush_selector.Format_filter=FORMAT_ALL_IMAGES; Palette_selector.Position=0; Palette_selector.Offset=0; Palette_selector.Format_filter=FORMAT_ALL_PALETTES; // On initialise d'ot' trucs Main.offset_X=0; Main.offset_Y=0; Main.separator_position=0; Main.X_zoom=0; Main.separator_proportion=INITIAL_SEPARATOR_PROPORTION; Main.magnifier_mode=0; Main.magnifier_factor=DEFAULT_ZOOM_FACTOR; Main.magnifier_height=0; Main.magnifier_width=0; Main.magnifier_offset_X=0; Main.magnifier_offset_Y=0; Spare.offset_X=0; Spare.offset_Y=0; Spare.separator_position=0; Spare.X_zoom=0; Spare.separator_proportion=INITIAL_SEPARATOR_PROPORTION; Spare.magnifier_mode=0; Spare.magnifier_factor=DEFAULT_ZOOM_FACTOR; Spare.magnifier_height=0; Spare.magnifier_width=0; Spare.magnifier_offset_X=0; Spare.magnifier_offset_Y=0; Keyboard_click_allowed = 1; Main.safety_backup_prefix = SAFETYBACKUP_PREFIX_A[0]; Spare.safety_backup_prefix = SAFETYBACKUP_PREFIX_B[0]; Main.time_of_safety_backup = 0; Spare.time_of_safety_backup = 0; // analyse commande line as soon as possible file_in_command_line=Analyze_command_line(argc, argv, main_filename, main_directory, spare_filename, spare_directory); #if defined(USE_SDL) || defined(USE_SDL2) // SDL if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0) { // The program can't continue without that anyway printf("Couldn't initialize SDL.\n"); return(0); } #if defined(USE_SDL2) SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE); #endif Joystick = SDL_JoystickOpen(0); #endif #if defined(USE_SDL) SDL_EnableKeyRepeat(250, 32); SDL_EnableUNICODE(SDL_ENABLE); SDL_WM_SetCaption("GrafX2","GrafX2"); #endif Define_icon(); // Texte Init_text(); // On initialise tous les modes vidéo Set_all_video_modes(); Pixel_ratio=PIXEL_SIMPLE; // On initialise les données sur l'état du programme: // Donnée sur la sortie du programme: Quit_is_required=0; Quitting=0; // Données sur l'état du menu: Menu_is_visible=1; // Données sur les couleurs et la palette: First_color_in_palette=0; // Données sur le curseur: Cursor_shape=CURSOR_SHAPE_TARGET; Cursor_hidden=0; // Données sur le pinceau: Paintbrush_X=0; Paintbrush_Y=0; Paintbrush_hidden=0; // On initialise tout ce qui concerne les opérations et les effets Operation_stack_size=0; Selected_freehand_mode=OPERATION_CONTINUOUS_DRAW; Selected_line_mode =OPERATION_LINE; Selected_curve_mode =OPERATION_3_POINTS_CURVE; Effect_function=No_effect; // On initialise les infos de la loupe: Main.magnifier_mode=0; Main.magnifier_factor=DEFAULT_ZOOM_FACTOR; Main.separator_proportion=INITIAL_SEPARATOR_PROPORTION; Spare.separator_proportion=INITIAL_SEPARATOR_PROPORTION; // On initialise les infos du mode smear: Smear_mode=0; Smear_brush_width=PAINTBRUSH_WIDTH; Smear_brush_height=PAINTBRUSH_HEIGHT; // On initialise les infos du mode smooth: Smooth_mode=0; // On initialise les infos du mode shade: Shade_mode=0; // Les autres infos du Shade sont chargées avec la config Quick_shade_mode=0; // idem // On initialise les infos sur les dégradés: Gradient_pixel =Display_pixel; // Les autres infos sont chargées avec la config // On initialise les infos de la grille: Snap_mode=0; Snap_width=8; Snap_height=8; Snap_offset_X=0; Snap_offset_Y=0; // On initialise les infos du mode Colorize: Colorize_mode=0; // Mode colorize inactif par défaut Colorize_opacity=50; // Une interpolation de 50% par défaut Colorize_current_mode=0; // Par défaut, la méthode par interpolation Compute_colorize_table(); // On initialise les infos du mode Tiling: Tiling_mode=0; // Pas besoin d'initialiser les décalages car ça se fait // en prenant une brosse (toujours mis à 0). // On initialise les infos du mode Mask: Mask_mode=0; // Infos du Spray Airbrush_mode=1; // Mode Mono Airbrush_size=31; Airbrush_delay=1; Airbrush_mono_flow=10; memset(Airbrush_multi_flow,0,256); srand(time(NULL)); // On randomize un peu tout ça... // Initialisation des boutons Init_buttons(); // Initialisation des opérations Init_operations(); // Initialize the brush container Init_brush_container(); Windows_open=0; // Paintbrush if (!(Paintbrush_sprite=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY); // Load preset paintbrushes (uses Paintbrush_ variables) Init_paintbrushes(); // Set a valid paintbrush afterwards *Paintbrush_sprite=1; Paintbrush_width=1; Paintbrush_height=1; Paintbrush_offset_X=0; Paintbrush_offset_Y=0; Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND; #if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) // Prefer cycling active by default Cycling_mode=1; #endif // Charger la configuration des touches Set_config_defaults(); switch(Load_CFG(1)) { case ERROR_CFG_MISSING: // Pas un problème, on a les valeurs par défaut. break; case ERROR_CFG_CORRUPTED: GFX2_Log(GFX2_ERROR, "Corrupted CFG file.\n"); break; case ERROR_CFG_OLD: GFX2_Log(GFX2_WARNING, "Unknown CFG file version, not loaded.\n"); break; } // Charger la configuration du .INI temp=Load_INI(&Config); if (temp) Error(temp); if(!Config.Allow_multi_shortcuts) { Remove_duplicate_shortcuts(); } Compute_menu_offsets(); Current_help_section=0; Help_position=0; // Load sprites, palette etc. gfx = Load_graphics(Config.Skin_file, &initial_gradients); if (gfx == NULL) { gfx = Load_graphics(DEFAULT_SKIN_FILENAME, &initial_gradients); if (gfx == NULL) { Error(ERROR_GUI_MISSING); } } Set_current_skin(Config.Skin_file, gfx); // Override colors // Gfx->Default_palette[MC_Black]=Config.Fav_menu_colors[0]; // Gfx->Default_palette[MC_Dark] =Config.Fav_menu_colors[1]; // Gfx->Default_palette[MC_Light]=Config.Fav_menu_colors[2]; // Gfx->Default_palette[MC_White]=Config.Fav_menu_colors[3]; // Even when using the skin's palette, if RGB range is small // the colors will be unusable. Compute_optimal_menu_colors(Gfx->Default_palette); // Infos sur les trames (Sieve) Sieve_mode=0; Copy_preset_sieve(0); // Font if (!(Menu_font=Load_font(Config.Font_file, 1))) if (!(Menu_font=Load_font(DEFAULT_FONT_FILENAME, 1))) { snprintf(Gui_loading_error_message, sizeof(Gui_loading_error_message), "Unable to open the default font file: %s\n", DEFAULT_FONT_FILENAME); Error(ERROR_GUI_MISSING); } Load_Unicode_fonts(); memcpy(Main.palette, Gfx->Default_palette, sizeof(T_Palette)); Fore_color=Best_color_range(255,255,255,Config.Palette_cells_X*Config.Palette_cells_Y); Back_color=Best_color_range(0,0,0,Config.Palette_cells_X*Config.Palette_cells_Y); // Allocation de mémoire pour la brosse if (!(Brush =(byte *)malloc( 1* 1))) Error(ERROR_MEMORY); if (!(Smear_brush =(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY); starting_videomode=Current_resolution; Horizontal_line_buffer=NULL; Screen_width=Screen_height=Current_resolution=0; Init_mode_video( Video_mode[starting_videomode].Width, Video_mode[starting_videomode].Height, Video_mode[starting_videomode].Fullscreen, Pixel_ratio); // Windows only: move back the window to its original position. #if defined(WIN32) if (!Video_mode[starting_videomode].Fullscreen) { if (Config.Window_pos_x != 9999 && Config.Window_pos_y != 9999) { //RECT r; #if defined(USE_SDL) || defined(USE_SDL2) //GetWindowRect(window, &r); SetWindowPos(GFX2_Get_Window_Handle(), 0, Config.Window_pos_x, Config.Window_pos_y, 0, 0, SWP_NOSIZE); #endif } } // Open a console for debugging... //ActivateConsole(); #endif Main.image_width=Screen_width/Pixel_width; Main.image_height=Screen_height/Pixel_height; Spare.image_width=Screen_width/Pixel_width; Spare.image_height=Screen_height/Pixel_height; starting_image_mode = Config.Default_mode_layers ? IMAGE_MODE_LAYERED : IMAGE_MODE_ANIMATION; // Allocation de mémoire pour les différents écrans virtuels (et brosse) if (Init_all_backup_lists(starting_image_mode , Screen_width, Screen_height)==0) Error(ERROR_MEMORY); // Update toolbars' visibility, now that the current image has a mode Check_menu_mode(); // Nettoyage de l'écran virtuel (les autres recevront celui-ci par copie) memset(Main_screen,0,Main.image_width*Main.image_height); // If image size was specified on command line, set that now if (setsize_width != 0 && setsize_height != 0) { Main.image_width=setsize_width; Main.image_height=setsize_height; Spare.image_width=setsize_width; Spare.image_height=setsize_height; } // Now that the backup system is there, we can store the gradients. memcpy(Main.backups->Pages->Gradients->Range, initial_gradients.Range, sizeof(initial_gradients.Range)); memcpy(Spare.backups->Pages->Gradients->Range, initial_gradients.Range, sizeof(initial_gradients.Range)); Gradient_function=Gradient_basic; Gradient_lower_bound=0; Gradient_upper_bound=0; Gradient_random_factor=1; Gradient_bounds_range=1; Current_gradient=0; // Initialisation de diverses variables par calcul: Compute_magnifier_data(); Compute_limits(); Compute_paintbrush_coordinates(); // On affiche le menu: Display_paintbrush_in_menu(); Display_sprite_in_menu(BUTTON_PAL_LEFT,Config.Palette_vertical?MENU_SPRITE_VERTICAL_PALETTE_SCROLL:-1); Display_menu(); Draw_menu_button(BUTTON_PAL_LEFT,BUTTON_RELEASED); Draw_menu_button(BUTTON_PAL_RIGHT,BUTTON_RELEASED); // On affiche le curseur pour débuter correctement l'état du programme: Display_cursor(); Spare.image_is_modified=0; Main.image_is_modified=0; // Gestionnaire de signaux, quand il ne reste plus aucun espoir Init_sighandler(); // Le programme débute en mode de dessin à la main Select_button(BUTTON_DRAW,LEFT_SIDE); // On initialise la brosse initiale à 1 pixel blanc: Brush_width=1; Brush_height=1; for (temp=0;temp<256;temp++) Brush_colormap[temp]=temp; Capture_brush(0,0,0,0,0); *Brush=MC_White; *Brush_original_pixels=MC_White; // Make sure the load dialog points to the right place when first shown. // Done after loading everything else, but before checking for emergency // backups if (file_in_command_line > 0) { strcpy(Main.selector.Directory, main_directory); } // Test de recuperation de fichiers sauvés switch (Check_recovery()) { T_IO_Context context; default: // Some files were loaded from last crash-exit. // Do not load files from command-line, nor show splash screen. Compute_optimal_menu_colors(Main.palette); Check_menu_mode(); Display_all_screen(); Display_menu(); Display_cursor(); Verbose_message("Images recovered", "Grafx2 has recovered images from\n" "last session, before a crash or\n" "shutdown. Browse the history using\n" "the Undo/Redo button, and when\n" "you find a state that you want to\n" "save, use the 'Save as' button to\n" "save the image.\n" "Some backups can be present in\n" "the spare page too.\n"); break; case -1: // Unable to write lock file Verbose_message("Warning", "Safety backups (every minute) are\n" "disabled because Grafx2 is running\n" "from a read-only device, or other\n" "instances are running."); break; case 0: switch (file_in_command_line) { case 0: if (Config.Opening_message) Button_Message_initial(); break; case 2: // Load this file Init_context_layered_image(&context, spare_filename, spare_directory); Load_image(&context); Destroy_context(&context); Redraw_layered_image(); End_of_modification(); Button_Page(BUTTON_PAGE); // no break ! proceed with the other file now case 1: Init_context_layered_image(&context, main_filename, main_directory); #ifdef ENABLE_FILENAMES_ICONV { char * input = main_filename; size_t inbytesleft = strlen(main_filename); char * output = (char *)main_filename_unicode; size_t outbytesleft = sizeof(main_filename_unicode) - 2; if (cd_utf16 != (iconv_t)-1) { size_t r = iconv(cd_utf16, &input, &inbytesleft, &output, &outbytesleft); if (r != (size_t)-1) { output[0] = '\0'; output[1] = '\0'; context.File_name_unicode = main_filename_unicode; } } } #endif Load_image(&context); Destroy_context(&context); Redraw_layered_image(); End_of_modification(); // If only one image was loaded, assume the spare has same image type if (file_in_command_line==1) Spare.backups->Pages->Image_mode = Main.backups->Pages->Image_mode; Hide_cursor(); Compute_optimal_menu_colors(Main.palette); Back_color=Main.backups->Pages->Background_transparent ? Main.backups->Pages->Transparent_color : Best_color_range(0,0,0,Config.Palette_cells_X*Config.Palette_cells_Y); Fore_color=Main.palette[Back_color].R+Main.palette[Back_color].G+Main.palette[Back_color].B < 3*127 ? Best_color_range(255,255,255,Config.Palette_cells_X*Config.Palette_cells_Y) : Best_color_range(0,0,0,Config.Palette_cells_X*Config.Palette_cells_Y); Check_menu_mode(); Display_all_screen(); Display_menu(); Display_cursor(); Resolution_in_command_line = 0; break; default: break; } } Allow_drag_and_drop(1); return(1); } // ------------------------- Program Shutdown -------------------------- // Free all allocated resources #define FREE_POINTER(p) free(p); p = NULL void Program_shutdown(void) { int i; int return_code; // Windows only: Recover the window position. #if defined(WIN32) #if defined(USE_SDL) || defined(USE_SDL2) { RECT r; GetWindowRect(GFX2_Get_Window_Handle(), &r); Config.Window_pos_x = r.left; Config.Window_pos_y = r.top; } #endif // Config.Window_pos_x / Config.Window_pos_y are set in win32screen.c #elif !defined(USE_X11) // All other targets: irrelevant dimensions. // Do not attempt to force them back on next program run. Config.Window_pos_x = 9999; Config.Window_pos_y = 9999; #endif // Remove the safety backups, this is normal exit Delete_safety_backups(); // On libère le buffer de gestion de lignes free(Horizontal_line_buffer); Horizontal_line_buffer = NULL; // On libère le pinceau spécial free(Paintbrush_sprite); Paintbrush_sprite = NULL; // Free Brushes FREE_POINTER(Brush); FREE_POINTER(Smear_brush); FREE_POINTER(Brush_original_pixels); // Free all images Set_number_of_backups(-1); // even delete the main page FREE_POINTER(Main.visible_image.Image); FREE_POINTER(Spare.visible_image.Image); FREE_POINTER(Main_visible_image_backup.Image); FREE_POINTER(Main_visible_image_depth_buffer.Image); FREE_POINTER(Main.backups); FREE_POINTER(Spare.backups); // Free the skin (Gui graphics) data free(Gfx); Gfx=NULL; free(Menu_font); Menu_font = NULL; while (Unicode_fonts != NULL) { T_Unicode_Font * ufont = Unicode_fonts->Next; free(Unicode_fonts->FontData); free(Unicode_fonts); Unicode_fonts = ufont; } // On prend bien soin de passer dans le répertoire initial: if (Change_directory(Initial_directory)==0) { // On sauvegarde les données dans le .CFG et dans le .INI if (Config.Auto_save) { return_code=Save_CFG(); if (return_code) Error(return_code); return_code=Save_INI(&Config); if (return_code) Error(return_code); } } else Error(ERROR_MISSING_DIRECTORY); // Free Config FREE_POINTER(Config.Skin_file); FREE_POINTER(Config.Font_file); for (i=0;i 0) { for (k = 0; ShortFileName[k] != 0; k++) arg_buffer[i++] = ShortFileName[k]; } else { for (k = 0; TmpArg[k] != 0; k++) arg_buffer[i++] = TmpArg[k]; } arg_buffer[i++] = 0; k = 0; continue; } } TmpArg[k++] = pCmdLine[j]; } TmpArg[k] = '\0'; if (k > 0) { argv[argc++] = arg_buffer + i; if (GetShortPathName(TmpArg, ShortFileName, MAX_PATH) > 0) { for (k = 0; ShortFileName[k] != 0; k++) arg_buffer[i++] = ShortFileName[k]; } else { for (k = 0; TmpArg[k] != 0; k++) arg_buffer[i++] = TmpArg[k]; } arg_buffer[i++] = 0; } // TODO : nCmdShow indicates if the window must be maximized, etc. #endif if(!Init_program(argc,argv)) { Program_shutdown(); return 0; } Main_handler(); Program_shutdown(); return 0; } #if defined(WIN32) && !defined(USE_SDL) && !defined(USE_SDL2) && !defined(_MSC_VER) int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR _lpCmdLine, int nCmdShow) { WCHAR *lpCmdLine = GetCommandLineW(); if (__argc == 1) { // avoids GetCommandLineW bug that does not always quote the program name if no arguments do { ++lpCmdLine; } while (*lpCmdLine); } else { BOOL quoted = lpCmdLine[0] == L'"'; ++lpCmdLine; // skips the " or the first letter (all paths are at least 1 letter) while (*lpCmdLine) { if (quoted && lpCmdLine[0] == L'"') quoted = FALSE; // found end quote else if (!quoted && lpCmdLine[0] == L' ') { // found an unquoted space, now skip all spaces do { ++lpCmdLine; } while (lpCmdLine[0] == L' '); break; } ++lpCmdLine; } } return wWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); } #endif