Load from clipboard
This commit is contained in:
parent
b706566f57
commit
3876bb03e1
@ -154,6 +154,7 @@ enum FILE_FORMATS
|
||||
FORMAT_MOTO, ///< Thomson MO/TO computers pictures
|
||||
FORMAT_HGR, ///< Apple II HGR and DHGR
|
||||
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image (or recoil)
|
||||
FORMAT_CLIPBOARD ///< To load/save from/to Clipboard
|
||||
};
|
||||
|
||||
/// Default format for 'save as'
|
||||
|
||||
@ -1613,6 +1613,7 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context
|
||||
char initial_comment[COMMENT_SIZE+1];
|
||||
short window_shortcut;
|
||||
const char * directory_to_change_to = NULL;
|
||||
int load_from_clipboard = 0;
|
||||
|
||||
Selector=settings;
|
||||
|
||||
@ -1730,7 +1731,14 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context
|
||||
Window_display_icon_sprite(bookmark_dropdown[temp]->Pos_X+3,bookmark_dropdown[temp]->Pos_Y+2,ICON_STAR);
|
||||
Display_bookmark(bookmark_dropdown[temp],temp);
|
||||
}
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
if (load)
|
||||
Window_set_normal_button(62,180,115,14,"From Clipboard",0,1,MOD_CTRL|KEY_v); // 14
|
||||
else
|
||||
Window_set_normal_button(62,180,115,14,"To Clipboard",0,1,MOD_CTRL|KEY_c); // 14
|
||||
#endif
|
||||
|
||||
Change_directory(context->File_directory);
|
||||
Get_current_directory(Selector->Directory, Selector->Directory_unicode, MAX_PATH_CHARACTERS);
|
||||
|
||||
@ -2089,6 +2097,19 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context
|
||||
New_preview_is_needed=1;
|
||||
Reset_quicksearch();
|
||||
break;
|
||||
case 14: // From/to clipboard
|
||||
if (load)
|
||||
{
|
||||
// paste from clipboard
|
||||
load_from_clipboard = 1;
|
||||
New_preview_is_needed = 1;
|
||||
Reset_quicksearch();
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy to clipboard
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (clicked_button>=10 && clicked_button<10+NB_BOOKMARKS)
|
||||
{
|
||||
@ -2374,13 +2395,21 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context
|
||||
|
||||
if (Timer_state==1) // Il faut afficher la preview
|
||||
{
|
||||
if ( (Selector->Position+Selector->Offset>=Filelist.Nb_directories) && (Filelist.Nb_elements) )
|
||||
if ( load_from_clipboard || ((Selector->Position+Selector->Offset>=Filelist.Nb_directories) && (Filelist.Nb_elements)) )
|
||||
{
|
||||
T_IO_Context preview_context;
|
||||
|
||||
Init_context_preview(&preview_context, Selector_filename, Selector->Directory);
|
||||
preview_context.Format = Selector->Format_filter;
|
||||
preview_context.File_name_unicode = Selector_filename_unicode;
|
||||
|
||||
if (load_from_clipboard)
|
||||
{
|
||||
Init_context_preview(&preview_context, NULL, NULL);
|
||||
preview_context.Format = FORMAT_CLIPBOARD;
|
||||
}
|
||||
else
|
||||
{
|
||||
Init_context_preview(&preview_context, Selector_filename, Selector->Directory);
|
||||
preview_context.Format = Selector->Format_filter;
|
||||
preview_context.File_name_unicode = Selector_filename_unicode;
|
||||
}
|
||||
Hide_cursor();
|
||||
if (context->Type == CONTEXT_PALETTE)
|
||||
preview_context.Type = CONTEXT_PREVIEW_PALETTE;
|
||||
@ -2390,7 +2419,6 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context
|
||||
|
||||
Update_window_area(0,0,Window_width,Window_height);
|
||||
Display_cursor();
|
||||
|
||||
}
|
||||
|
||||
Timer_state=2; // On arrête le chrono
|
||||
@ -2400,12 +2428,21 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context
|
||||
|
||||
if (has_clicked_ok)
|
||||
{
|
||||
strcpy(context->File_name, Selector_filename);
|
||||
if (context->File_name_unicode)
|
||||
Unicode_strlcpy(context->File_name_unicode, Selector_filename_unicode, MAX_PATH_CHARACTERS);
|
||||
strcpy(context->File_directory, Selector->Directory);
|
||||
if (!load)
|
||||
context->Format = Selector->Format_filter;
|
||||
if (load_from_clipboard)
|
||||
{
|
||||
strcpy(context->File_name, "CLIPBOARD.GIF");
|
||||
context->File_name_unicode[0] = 0;
|
||||
context->Format = FORMAT_CLIPBOARD;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(context->File_name, Selector_filename);
|
||||
if (context->File_name_unicode)
|
||||
Unicode_strlcpy(context->File_name_unicode, Selector_filename_unicode, MAX_PATH_CHARACTERS);
|
||||
strcpy(context->File_directory, Selector->Directory);
|
||||
if (!load)
|
||||
context->Format = Selector->Format_filter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
314
src/loadsave.c
314
src/loadsave.c
@ -85,6 +85,9 @@ void Load_SDL_Image(T_IO_Context *);
|
||||
void Load_Recoil_Image(T_IO_Context *);
|
||||
#endif
|
||||
|
||||
// clipboard
|
||||
static void Load_ClipBoard_Image(T_IO_Context *);
|
||||
|
||||
// ENUM Name TestFunc LoadFunc SaveFunc PalOnly Comment Layers Ext Exts
|
||||
const T_Format File_formats[] = {
|
||||
{FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "",
|
||||
@ -578,82 +581,101 @@ void Load_image(T_IO_Context *context)
|
||||
// charger le format du fichier:
|
||||
File_error=1;
|
||||
|
||||
f = Open_file_read(context);
|
||||
if (f == NULL)
|
||||
if (context->Format == FORMAT_CLIPBOARD)
|
||||
{
|
||||
Warning("Cannot open file for reading");
|
||||
Error(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->Format>FORMAT_ALL_FILES)
|
||||
{
|
||||
format = Get_fileformat(context->Format);
|
||||
if (format->Test)
|
||||
format->Test(context, f);
|
||||
}
|
||||
|
||||
if (File_error)
|
||||
{
|
||||
// Sinon, on va devoir scanner les différents formats qu'on connait pour
|
||||
// savoir à quel format est le fichier:
|
||||
for (index=0; index < Nb_known_formats(); index++)
|
||||
Load_ClipBoard_Image(context);
|
||||
if (File_error != 0)
|
||||
{
|
||||
format = Get_fileformat(index);
|
||||
// Loadable format
|
||||
if (format->Test == NULL)
|
||||
continue;
|
||||
|
||||
fseek(f, 0, SEEK_SET); // rewind
|
||||
// On appelle le testeur du format:
|
||||
format->Test(context, f);
|
||||
// On s'arrête si le fichier est au bon format:
|
||||
if (File_error==0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
if (File_error)
|
||||
{
|
||||
context->Format = DEFAULT_FILEFORMAT;
|
||||
// try with recoil
|
||||
#ifndef NORECOIL
|
||||
Load_Recoil_Image(context);
|
||||
if (File_error)
|
||||
#endif
|
||||
#if defined(USE_SDL) || defined(USE_SDL2)
|
||||
{
|
||||
// Last try: with SDL_image
|
||||
Load_SDL_Image(context);
|
||||
}
|
||||
|
||||
if (File_error)
|
||||
#endif
|
||||
{
|
||||
// Sinon, l'appelant sera au courant de l'échec grace à File_error;
|
||||
// et si on s'apprêtait à faire un chargement définitif de l'image (pas
|
||||
// une preview), alors on flash l'utilisateur.
|
||||
//if (Pixel_load_function!=Pixel_load_in_preview)
|
||||
// Error(0);
|
||||
Error(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
// Si on a su déterminer avec succès le format du fichier:
|
||||
{
|
||||
context->Format = format->Identifier;
|
||||
// On peut charger le fichier:
|
||||
// Dans certains cas il est possible que le chargement plante
|
||||
// après avoir modifié la palette. TODO
|
||||
format->Load(context);
|
||||
}
|
||||
|
||||
if (File_error>0)
|
||||
{
|
||||
GFX2_Log(GFX2_WARNING, "Unable to load file %s (error %d)! format:%s\n", context->File_name, File_error, format->Label);
|
||||
if (context->Type!=CONTEXT_SURFACE)
|
||||
if (context->File_name == NULL || context->File_directory == NULL)
|
||||
{
|
||||
GFX2_Log(GFX2_ERROR, "Load_Image() called with NULL file name or directory\n");
|
||||
Error(0);
|
||||
return;
|
||||
}
|
||||
|
||||
f = Open_file_read(context);
|
||||
if (f == NULL)
|
||||
{
|
||||
Warning("Cannot open file for reading");
|
||||
Error(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->Format > FORMAT_ALL_FILES)
|
||||
{
|
||||
format = Get_fileformat(context->Format);
|
||||
if (format->Test)
|
||||
format->Test(context, f);
|
||||
}
|
||||
|
||||
if (File_error)
|
||||
{
|
||||
// Sinon, on va devoir scanner les différents formats qu'on connait pour
|
||||
// savoir à quel format est le fichier:
|
||||
for (index=0; index < Nb_known_formats(); index++)
|
||||
{
|
||||
format = Get_fileformat(index);
|
||||
// Loadable format
|
||||
if (format->Test == NULL)
|
||||
continue;
|
||||
|
||||
fseek(f, 0, SEEK_SET); // rewind
|
||||
// On appelle le testeur du format:
|
||||
format->Test(context, f);
|
||||
// On s'arrête si le fichier est au bon format:
|
||||
if (File_error==0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
if (File_error)
|
||||
{
|
||||
context->Format = DEFAULT_FILEFORMAT;
|
||||
// try with recoil
|
||||
#ifndef NORECOIL
|
||||
Load_Recoil_Image(context);
|
||||
if (File_error)
|
||||
#endif
|
||||
#if defined(USE_SDL) || defined(USE_SDL2)
|
||||
{
|
||||
// Last try: with SDL_image
|
||||
Load_SDL_Image(context);
|
||||
}
|
||||
|
||||
if (File_error)
|
||||
#endif
|
||||
{
|
||||
// Sinon, l'appelant sera au courant de l'échec grace à File_error;
|
||||
// et si on s'apprêtait à faire un chargement définitif de l'image (pas
|
||||
// une preview), alors on flash l'utilisateur.
|
||||
//if (Pixel_load_function!=Pixel_load_in_preview)
|
||||
// Error(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
// Si on a su déterminer avec succès le format du fichier:
|
||||
{
|
||||
context->Format = format->Identifier;
|
||||
// On peut charger le fichier:
|
||||
// Dans certains cas il est possible que le chargement plante
|
||||
// après avoir modifié la palette. TODO
|
||||
format->Load(context);
|
||||
}
|
||||
|
||||
if (File_error>0)
|
||||
{
|
||||
GFX2_Log(GFX2_WARNING, "Unable to load file %s (error %d)! format:%s\n", context->File_name, File_error, format->Label);
|
||||
if (context->Type!=CONTEXT_SURFACE)
|
||||
Error(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Post-load
|
||||
@ -1186,6 +1208,162 @@ T_GFX2_Surface * Load_surface(char *full_name, T_Gradient_array *gradients)
|
||||
}
|
||||
|
||||
|
||||
static void Load_ClipBoard_Image(T_IO_Context * context)
|
||||
{
|
||||
#ifdef WIN32
|
||||
UINT format;
|
||||
HANDLE clipboard;
|
||||
|
||||
if (!OpenClipboard(GFX2_Get_Window_Handle()))
|
||||
{
|
||||
GFX2_Log(GFX2_ERROR, "Failed to open Clipboard\n");
|
||||
return;
|
||||
}
|
||||
|
||||
format = EnumClipboardFormats(0);
|
||||
while (format != 0)
|
||||
{
|
||||
const char * format_name = NULL;
|
||||
char format_name_buffer[256];
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case CF_TEXT:
|
||||
format_name = "TEXT";
|
||||
break;
|
||||
case CF_OEMTEXT:
|
||||
format_name = "OEMTEXT";
|
||||
break;
|
||||
case CF_UNICODETEXT:
|
||||
format_name = "UNICODE TEXT";
|
||||
break;
|
||||
case CF_DIB:
|
||||
format_name = "DIB (BITMAPINFO)";
|
||||
break;
|
||||
case CF_DIBV5:
|
||||
format_name = "DIBV5 (BITMAPV5HEADER)";
|
||||
break;
|
||||
case CF_BITMAP:
|
||||
format_name = "HBITMAP";
|
||||
break;
|
||||
case CF_METAFILEPICT:
|
||||
format_name = "METAFILEPICT";
|
||||
break;
|
||||
case CF_PALETTE:
|
||||
format_name = "Palette";
|
||||
break;
|
||||
case CF_TIFF:
|
||||
format_name = "TIFF";
|
||||
break;
|
||||
case CF_ENHMETAFILE:
|
||||
format_name = "HENMETAFILE";
|
||||
break;
|
||||
default:
|
||||
if (GetClipboardFormatNameA(format, format_name_buffer, sizeof(format_name_buffer)) <= 0)
|
||||
GFX2_Log(GFX2_WARNING, "Failed to get name for clipboard format %u\n", format);
|
||||
else
|
||||
format_name = format_name_buffer;
|
||||
}
|
||||
if (format_name != NULL)
|
||||
GFX2_Log(GFX2_DEBUG, "Available format %5u \"%s\"\n", format, format_name);
|
||||
|
||||
format = EnumClipboardFormats(format); // get next format
|
||||
}
|
||||
clipboard = GetClipboardData(CF_DIB);
|
||||
if (clipboard != NULL)
|
||||
{
|
||||
const PBITMAPINFO bmi = (PBITMAPINFO)GlobalLock(clipboard);
|
||||
if (bmi != NULL)
|
||||
{
|
||||
unsigned long width, height;
|
||||
width = bmi->bmiHeader.biWidth;
|
||||
height = (bmi->bmiHeader.biHeight > 0) ? bmi->bmiHeader.biHeight : -bmi->bmiHeader.biHeight;
|
||||
|
||||
GFX2_Log(GFX2_DEBUG, "DIB %ldx%ld planes=%u bpp=%u compression=%u size=%u ClrUsed=%u\n",
|
||||
bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
|
||||
bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount,
|
||||
bmi->bmiHeader.biCompression, bmi->bmiHeader.biSizeImage,
|
||||
bmi->bmiHeader.biClrUsed);
|
||||
if (bmi->bmiHeader.biCompression != BI_RGB)
|
||||
GFX2_Log(GFX2_INFO, "Unsupported DIB compression %u\n", bmi->bmiHeader.biCompression);
|
||||
else if (width > 9999 || height > 9999)
|
||||
GFX2_Log(GFX2_INFO, "Image too big : %lux%lu\n", width, height);
|
||||
else
|
||||
{
|
||||
unsigned i, color_count;
|
||||
const byte * pixels;
|
||||
unsigned int x, y;
|
||||
|
||||
File_error = 0; // have to be set before calling Pre_load()
|
||||
Pre_load(context, width, height, bmi->bmiHeader.biSizeImage, FORMAT_CLIPBOARD, PIXEL_SIMPLE, bmi->bmiHeader.biBitCount);
|
||||
|
||||
color_count = bmi->bmiHeader.biClrUsed;
|
||||
if (bmi->bmiHeader.biBitCount <= 8)
|
||||
{ // get palette
|
||||
if (color_count == 0)
|
||||
color_count = 1 << bmi->bmiHeader.biBitCount;
|
||||
for (i = 0; i < color_count; i++)
|
||||
{
|
||||
context->Palette[i].R = bmi->bmiColors[i].rgbRed;
|
||||
context->Palette[i].G = bmi->bmiColors[i].rgbGreen;
|
||||
context->Palette[i].B = bmi->bmiColors[i].rgbBlue;
|
||||
}
|
||||
}
|
||||
pixels = (const byte *)(&bmi->bmiColors[color_count]);
|
||||
switch (bmi->bmiHeader.biBitCount)
|
||||
{
|
||||
case 8:
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
const byte * line;
|
||||
if (bmi->bmiHeader.biHeight > 0)
|
||||
line = pixels + (height - y - 1) * bmi->bmiHeader.biWidth;
|
||||
else
|
||||
line = pixels + y * bmi->bmiHeader.biWidth;
|
||||
for (x = 0; x < width; x++)
|
||||
Set_pixel(context, x, y, line[x]);
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
const byte * line;
|
||||
if (bmi->bmiHeader.biHeight > 0)
|
||||
line = pixels + (height - y - 1) * bmi->bmiHeader.biWidth * 3;
|
||||
else
|
||||
line = pixels + y * bmi->bmiHeader.biWidth * 3;
|
||||
for (x = 0; x < width; x++)
|
||||
Set_pixel_24b(context, x, y, line[x*3 + 2], line[x*3 + 1], line[x*3]);
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
const byte * line;
|
||||
if (bmi->bmiHeader.biHeight > 0)
|
||||
line = pixels + (height - y - 1) * bmi->bmiHeader.biWidth * 4;
|
||||
else
|
||||
line = pixels + y * bmi->bmiHeader.biWidth * 4;
|
||||
for (x = 0; x < width; x++)
|
||||
Set_pixel_24b(context, x, y, line[x*4 + 2], line[x*4 + 1], line[x*4]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GFX2_Log(GFX2_ERROR, "Loading %ubpp pictures from Clipboard is not implemented yet!\n", bmi->bmiHeader.biBitCount);
|
||||
File_error = 1;
|
||||
}
|
||||
}
|
||||
GlobalUnlock(clipboard);
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
#else
|
||||
GFX2_Log(GFX2_ERROR, "Load_ClipBoard_Image() not implemented on this platform yet\n");
|
||||
File_error = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// Saves an image.
|
||||
/// This routine will only be called when all hope is lost, memory thrashed, etc
|
||||
/// It's the last chance to save anything, but the code has to be extremely
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user