Files
KiTTY/kitty_image.c
T

1504 lines
46 KiB
C

#ifdef FLJ
#undef MOD_BACKGROUNDIMAGE
#endif
#include <setjmp.h>
#include "jpeg/jpeglib.h"
#include <stdio.h>
#include <windows.h>
#ifdef MOD_BACKGROUNDIMAGE
#include <math.h>
#include "putty.h"
#include "terminal.h"
#include "kitty_image.h"
extern Conf *conf ;// extern Config cfg;
//extern int offset_width, offset_height ;
//extern int font_width, font_height ;
#ifndef NCFGCOLOURS
#define NCFGCOLOURS 24
#endif
#ifndef NEXTCOLOURS
#define NEXTCOLOURS 240
#endif
#ifndef NALLCOLOURS
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
#endif
//extern COLORREF colours[NALLCOLOURS] ;
extern HWND MainHwnd ;
int stricmp(const char *s1, const char *s2) ;
int GetSessionField( const char * session_in, const char * folder_in, const char * field, char * result ) ;
int get_param( const char * val ) ;
int return_offset_height(void) ;
int return_offset_width(void) ;
int return_font_height(void) ;
int return_font_width(void) ;
COLORREF return_colours258(void) ;
static BOOL (WINAPI * pAlphaBlend)( HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION ) = 0 ;
//static HWND hwnd;
HDC textdc = NULL ;
HBITMAP textbm = NULL ;
COLORREF colorinpixel;
HDC colorinpixeldc = NULL ;
HBITMAP colorinpixelbm = NULL;
HDC backgrounddc = NULL ;
HBITMAP backgroundbm = NULL ;
HDC backgroundblenddc = NULL ;
HBITMAP backgroundblendbm = NULL;
BOOL bBgRelToTerm;
bool resizing;
RECT size_before;
#ifdef DLL
#define TARGET extern __declspec(dllexport)
#else
#define TARGET
#endif
static int ShrinkBitmapEnable = 1 ;
void SetShrinkBitmapEnable( int v ) {
if( v ) ShrinkBitmapEnable = 1 ;
else ShrinkBitmapEnable = 0 ;
}
//
// Fonctions de shrink de bitmap
//
#define Alloc(p,t) (t *)malloc((p)*sizeof(t))
#define For(i,n) for ((i)=0;(i)<(n);(i)++)
#define iFor(n) For (i,n)
#define jFor(n) For (j,n)
typedef struct {
WORD x, y ; // dimensions
WORD l ; // bytes per scan-line (32-bit allignment)
BYTE *b ; // bits of bitmap,3 bytes/pixel, BGR
} tWorkBMP ; // 24-bit working bitmap
void CreateWorkingBitmap( WORD dx, WORD dy, tWorkBMP *w ) {
w->x=dx ;
w->y=dy ;
w->l=(dx+1)*3&0xfffc ;
w->b=Alloc( w->l*dy, BYTE ) ;
}
HBITMAP CreateEmptyBitmap( WORD dx, WORD dy ) {
HDC h = GetDC( NULL ) ;
HBITMAP b = CreateCompatibleBitmap( h, dx, dy ) ;
ReleaseDC( NULL, h ) ;
return(b) ;
}
void SetBMIHeader( BITMAPINFO *b, short dx, short dy ) {
b->bmiHeader.biSize = sizeof(BITMAPINFOHEADER) ;
b->bmiHeader.biWidth = dx ;
b->bmiHeader.biHeight = -dy ;
b->bmiHeader.biPlanes = 1 ;
b->bmiHeader.biBitCount = 24 ;
b->bmiHeader.biCompression = BI_RGB ;
b->bmiHeader.biSizeImage = 0 ;
b->bmiHeader.biXPelsPerMeter = 1 ;
b->bmiHeader.biYPelsPerMeter = 1 ;
b->bmiHeader.biClrUsed = 0 ;
b->bmiHeader.biClrImportant = 0 ;
}
POINT GetBitmapSize( HBITMAP h ) {
POINT p ;
BITMAP o ;
GetObject( h, sizeof(o), &o ) ;
p.x = o.bmWidth ;
p.y = o.bmHeight ;
return(p) ;
}
void OpenBitmapForWork( HBITMAP b, tWorkBMP *w ) {
BITMAPINFO s ;
HDC h = GetDC( NULL ) ;
POINT v = GetBitmapSize( b ) ;
CreateWorkingBitmap( v.x, v.y, w ) ;
SetBMIHeader( &s,w->x, w->y ) ;
GetDIBits( h, b, 0, w->y, w->b, &s, DIB_RGB_COLORS ) ;
ReleaseDC( NULL, h ) ;
}
void SaveWorkingBitmap( tWorkBMP *w, HBITMAP b ) {
BITMAPINFO s ;
HDC h = GetDC( NULL ) ;
SetBMIHeader( &s, w->x, w->y ) ;
SetDIBits( h, b, 0, w->y, w->b, &s, DIB_RGB_COLORS ) ;
ReleaseDC( NULL, h ) ;
}
void ShrinkWorkingBitmap( tWorkBMP *a, tWorkBMP *b, WORD bx, WORD by ) {
BYTE *uy = a->b, *ux, i ;
WORD x, y, nx, ny = 0 ;
DWORD df = 3*bx, nf = df*by, j ;
float k, qx[2], qy[2], q[4], *f = Alloc( nf, float ) ;
CreateWorkingBitmap( bx, by, b) ;
jFor (nf) f[j]=0;
j=0;
For( y, a->y ) {
ux=uy;
uy+=a->l;
nx=0;
ny+=by;
if (ny>a->y) {
qy[0]=1-(qy[1]=(ny-a->y)/(float)by);
For (x,a->x) {
nx+=bx;
if (nx>a->x) {
qx[0]=1-(qx[1]=(nx-a->x)/(float)bx);
iFor (4) q[i]=qx[i&1]*qy[i>>1];
iFor (3) {
f[j]+=(*ux)*q[0];
f[j+3]+=(*ux)*q[1];
f[j+df]+=(*ux)*q[2];
f[(j++)+df+3]+=(*(ux++))*q[3];
}
} else iFor (3) {
f[j+i]+=(*ux)*qy[0];
f[j+df+i]+=(*(ux++))*qy[1];
}
if (nx>=a->x) nx-=a->x;
if (!nx) j+=3;
}
} else {
For (x,a->x) {
nx+=bx;
if (nx>a->x) {
qx[0]=1-(qx[1]=(nx-a->x)/(float)bx);
iFor (3) {
f[j]+=(*ux)*qx[0];
f[(j++)+3]+=(*(ux++))*qx[1];
}
}
else iFor (3) f[j+i]+=*(ux++);
if (nx>=a->x) nx-=a->x;
if (!nx) j+=3;
}
if (ny<a->y) j-=df;
}
if (ny>=a->y) ny-=a->y;
}
nf=0;
k=bx*by/(float)(a->x*a->y);
uy=b->b;
For (y,by) {
jFor (df) uy[j]=(unsigned char)(f[nf++]*k+.5);
uy+=b->l;
}
free (f);
}
TARGET HBITMAP ShrinkBitmap( HBITMAP a, WORD bx, WORD by )
// creates and returns new bitmap with dimensions of
// [bx,by] by shrinking bitmap a both [bx,by] must be less or equal
// than the dims of a, unless the result is nonsense
{
tWorkBMP in, out ;
HBITMAP b=CreateEmptyBitmap( bx, by ) ;
OpenBitmapForWork( a, &in ) ;
ShrinkWorkingBitmap( &in, &out, bx, by ) ;
free( in.b ) ;
SaveWorkingBitmap( &out, b ) ;
free( out.b ) ;
return( b ) ;
}
HBITMAP ResizeBmp( HBITMAP hBmpSrc, WORD bx, WORD by ) {
SIZE newSize ;
newSize.cx = bx;
newSize.cy = by;
// taille actuelle
BITMAP bmpInfo;
GetObject(hBmpSrc, sizeof(BITMAP), &bmpInfo);
SIZE oldSize;
oldSize.cx = bmpInfo.bmWidth;
oldSize.cy = bmpInfo.bmHeight;
// selection source ds un DC
HDC hdc = GetDC(NULL);
HDC hDCSrc = CreateCompatibleDC(hdc);
HBITMAP hOldBmpSrc = (HBITMAP)SelectObject(hDCSrc, hBmpSrc);
// création bitmap dest et sélection ds un DC
HDC hDCDst = CreateCompatibleDC(hdc);
HBITMAP hBmpDst = CreateCompatibleBitmap(hdc, newSize.cx, newSize.cy);
HBITMAP hOldBmpDst = (HBITMAP)SelectObject(hDCDst, hBmpDst);
// resize
StretchBlt(hDCDst, 0, 0, newSize.cx, newSize.cy, hDCSrc, 0, 0, oldSize.cx, oldSize.cy, SRCCOPY);
// libération ressources
SelectObject(hDCSrc, hOldBmpSrc);
SelectObject(hDCDst, hOldBmpDst);
DeleteDC(hDCSrc);
DeleteDC(hDCDst);
ReleaseDC(NULL, hdc);
return hBmpDst;
}
static void fill_dc(HDC dc, int width, int height, COLORREF color)
{
HBRUSH clrBrush = CreateSolidBrush(color);
HPEN clrPen = CreatePen(PS_SOLID, 0, color);
HBRUSH oldBrush;
HPEN oldPen;
oldBrush = SelectObject(dc, clrBrush);
oldPen = SelectObject(dc, clrPen);
Rectangle(dc, 0, 0, width, height);
SelectObject(dc, oldBrush);
SelectObject(dc, oldPen);
}
static BOOL load_wallpaper_bmp(HBITMAP* rawImage, int* style, int* x, int* y)
{
LONG lRes;
HKEY kDesktop;
DWORD pathLen = MAX_PATH;
DWORD numBufLen = 10;
char wpPath[MAX_PATH];
char wpStyleBuf[10];
char wpTileBuf[10];
int wpStyle = -1;
int wpTile = -1;
// NOTE: In the non-wallpaper case (i.e., load_file_bmp), we load parameters
// like x, y and style from cfg, but in the wallpaper case we ignore our
// stored configuration and get that information from the system.
// ENHANCE: It's possible to set WallpaperOriginX and WallpaperOriginY to
// specify an exact position for the start of the wallpaper, but this
// function doesn't support that yet. I don't think it's possible to set
// it through the normal UI anyway, you have to hack the registry to do it.
// For now, we'll never return an (x,y) positioning request to the caller.
*x = *y = 0;
lRes = RegOpenKeyEx(
HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_READ, &kDesktop
);
if(lRes != ERROR_SUCCESS)
{
RegCloseKey(kDesktop);
return FALSE; // TODO: Should the error be reported to the user here?
}
lRes = RegQueryValueEx(kDesktop, "Wallpaper", NULL, NULL, (LPBYTE)wpPath, &pathLen);
if(lRes != ERROR_SUCCESS)
{
RegCloseKey(kDesktop);
return FALSE; // TODO: Should the error be reported to the user here?
}
lRes = RegQueryValueEx( kDesktop, "WallpaperStyle", NULL, NULL, (LPBYTE)wpStyleBuf, &numBufLen );
if(lRes == ERROR_SUCCESS)
wpStyle = atoi(wpStyleBuf);
lRes = RegQueryValueEx( kDesktop, "TileWallpaper", NULL, NULL, (LPBYTE)wpTileBuf, &numBufLen );
if(lRes == ERROR_SUCCESS)
wpTile = atoi(wpTileBuf);
if(wpStyle < 0 && wpStyle > 3)
wpStyle = 0; // Default to tile.
else if(wpTile > 0)
wpStyle = 0; // Force tile.
else if(wpStyle == 0 && wpTile == 0)
wpStyle = 1; // For Explorer, wpStyle == wpTile == 0 means center, and
// it doesn't ever set wpStyle to 1. We call wpStyle == 1
// center and don't use wpTile, to simplify things after
// this point.
RegCloseKey(kDesktop);
if( *rawImage!=NULL ) { DeleteObject( *rawImage ) ; *rawImage=NULL ; }
*rawImage = LoadImage(
NULL, wpPath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE
);
if(*rawImage == 0)
return FALSE; // TODO: Should the error be reported to the user here?
*style = wpStyle;
return TRUE;
}
static BOOL load_file_bmp(HBITMAP* rawImage, int* style, int* x, int* y)
{
*x = conf_get_int( conf,CONF_bg_image_abs_x);
*y = conf_get_int( conf,CONF_bg_image_abs_y );
*style = conf_get_int( conf,CONF_bg_image_style);
if( *rawImage!=NULL ) { DeleteObject( *rawImage ) ; *rawImage=NULL ; }
*rawImage = LoadImage(
NULL, conf_get_filename( conf, CONF_bg_image_filename )->path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE
);
if(*rawImage == 0)
return FALSE; // TODO: Should the error be reported to the user here?
return TRUE;
}
jmp_buf JPEG_bailout;
int usePalette = 0;
char *loadError = NULL;
COLORREF skycolour = RGB(0, 0, 255);
HBITMAP CreateHBitmap(int w, int h, LPVOID *lpBits)
{
HBITMAP bitmap;
BITMAPINFOHEADER BIH ;
int iSize = sizeof(BITMAPINFOHEADER) ;
memset(&BIH, 0, iSize);
// Fill in the header info.
BIH.biSize = iSize;
BIH.biWidth = w;
BIH.biHeight = h;
BIH.biPlanes = 1;
BIH.biBitCount = 24;
BIH.biCompression = BI_RGB;
HDC hDC = CreateCompatibleDC(NULL);
bitmap = CreateDIBSection(hDC,
(BITMAPINFO*)&BIH,
DIB_RGB_COLORS,
lpBits,
NULL,
0);
DeleteDC(hDC);
return bitmap;
}
// LOADJPEGIMAGE -- Load JPEG image into memory
HBITMAP loadJPEGimage(FILE *input_file, HGLOBAL *LimageBitmap, int *LsizeX, int *LsizeY)
{
int i;
LPBITMAPINFOHEADER bh;
DWORD bmpsize;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPARRAY colormap;
LPBYTE pix;
int linewid;
int pixbytes;
static LPBYTE sl = NULL;
static HGLOBAL imageBitmap = NULL; // In-memory bitmap
sl = NULL;
imageBitmap = NULL;
if (setjmp(JPEG_bailout) != 0) {
/* Since we arrive here via longjmp() from
parts unknown, we may have allocated
the line buffer or bitmap prior to bailing
out. If they've been allocated, release them. */
if (sl != NULL) {
GlobalFree(sl);
sl = NULL;
}
if (imageBitmap != NULL) {
GlobalFree(imageBitmap);
imageBitmap = NULL;
}
return NULL;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, input_file);
jpeg_read_header(&cinfo, TRUE);
cinfo.desired_number_of_colors = 254;
cinfo.quantize_colors = usePalette;
jpeg_start_decompress(&cinfo);
pixbytes = (usePalette ? 1 : 3);
sl = GlobalAlloc(GMEM_FIXED, cinfo.output_width * pixbytes);
if (sl == NULL) {
loadError = "Cannot allocate JPEG decoder row buffer";
return NULL;
}
linewid = ((((cinfo.output_width * pixbytes) + (sizeof(LONG) - 1)) / sizeof(LONG)) * sizeof(LONG));
bmpsize = sizeof(BITMAPINFOHEADER) +
(usePalette ? (256 * sizeof(RGBQUAD)) : 0) +
(linewid * cinfo.output_height);
imageBitmap = GlobalAlloc(GMEM_FIXED, bmpsize);
if (imageBitmap == NULL) {
loadError = "Cannot allocate bitmap for decoded JPEG image";
GlobalFree(sl);
return NULL;
}
// Plug in header fields with information from cinfo
bh = (LPBITMAPINFOHEADER) imageBitmap;
pix = ((LPBYTE) imageBitmap) + sizeof(BITMAPINFOHEADER) +
(usePalette ? (256 * sizeof(RGBQUAD)) : 0);
pix = pix + 0 ; // Pour eviter un warning de compilation
bh->biSize = sizeof(BITMAPINFOHEADER);
bh->biWidth = cinfo.output_width;
bh->biHeight = cinfo.output_height;
bh->biPlanes = 1;
bh->biBitCount = usePalette ? 8 : 24;
bh->biCompression = BI_RGB;
bh->biSizeImage = 0;
bh->biXPelsPerMeter = bh->biYPelsPerMeter = 2835;
bh->biClrUsed = 0;
bh->biClrImportant = 0;
/* Construct the palette from the colour map optimised
for the JPEG file. */
if (usePalette) {
colormap = cinfo.colormap;
for (i = 0; i < cinfo.actual_number_of_colors; i++) {
if (cinfo.num_components == 1) {
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbRed =
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbGreen =
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbBlue = GETJSAMPLE(colormap[0][i]);
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbReserved = 0;
} else {
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbRed = GETJSAMPLE(colormap[0][i]);
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbGreen = GETJSAMPLE(colormap[1][i]);
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbBlue = GETJSAMPLE(colormap[2][i]);
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbReserved = 0;
}
}
/* Plug black and our text colour in the last two slots
of the palette so we canbe sure they're available. */
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[254])->rgbRed =
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[254])->rgbGreen =
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[254])->rgbBlue =
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[254])->rgbReserved = 0;
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[255])->rgbRed = GetRValue(skycolour);
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[255])->rgbGreen = GetGValue(skycolour);
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[255])->rgbBlue = GetBValue(skycolour);
((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[255])->rgbReserved = 0;
}
// Return scan lines and transfer to the pixel array
BYTE *pDst = NULL;
HBITMAP hBitmap = CreateHBitmap(bh->biWidth, bh->biHeight, (void**)&pDst);
int nStorageWidth = ((bh->biWidth * 24 + 31) & ~31) >> 3; //dword alignment
JSAMPARRAY ppDst = &pDst;
/*
LPBYTE px = pix + (linewid * (bh->biHeight - 1));
for (i = 0; i < (int) cinfo.output_height; i++) {
unsigned char *slp[1] = { sl };
jpeg_read_scanlines(&cinfo, slp, 1);
if (usePalette) {
memcpy(px, sl, cinfo.output_width);
} else {
int j, k;
if (cinfo.num_components == 3) {
for (j = k = 0; j < (int) cinfo.output_width; j++, k += 3) {
px[k] = sl[k + 2];
px[k + 1] = sl[k + 1];
px[k + 2] = sl[k];
}
} else {
for (j = k = 0; j < (int) cinfo.output_width; j++, k += 3) {
px[k] = sl[j];
px[k + 1] = sl[j];
px[k + 2] = sl[j];
}
}
}
px -= linewid;
}
*/
pDst = pDst + (cinfo.output_height-1)*nStorageWidth ;
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines (&cinfo, ppDst, 1);
if(cinfo.out_color_components==3) {
//swap R & B
BYTE* p = pDst;
int i ;
for( i=0;i<bh->biWidth;i++) {
BYTE r = p[0];
p[0] = p[2];
p[2] = r;
p += 3;
}
}
//pDst += nStorageWidth;
pDst -= nStorageWidth;
}
GlobalFree(sl);
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
*LsizeX = (int) bh->biWidth;
*LsizeY = (int) bh->biHeight;
*LimageBitmap = imageBitmap;
return hBitmap;
}
static BOOL load_file_jpeg(HBITMAP* rawImage, int* style, int* x, int* y) {
*x = conf_get_int( conf, CONF_bg_image_abs_x );
*y = conf_get_int( conf, CONF_bg_image_abs_y );
*style = conf_get_int( conf, CONF_bg_image_style );
int res=TRUE, LsizeX, LsizeY ;
FILE *fp ;
HGLOBAL LimageBitmap = NULL ;
if( ( fp=fopen( conf_get_filename( conf,CONF_bg_image_filename)->path, "rb" ) ) == NULL ) return FALSE ;
if( *rawImage!=NULL ) { DeleteObject( *rawImage ) ; *rawImage=NULL ; }
*rawImage = loadJPEGimage(fp, &LimageBitmap,&LsizeX, &LsizeY) ;
if( rawImage == NULL ) res =FALSE ;
fclose( fp ) ;
GlobalFree(LimageBitmap);
return res;
}
static HBITMAP CreateDIBSectionWithFileMapping(HDC dc, int width, int height, HANDLE fmap)
{
BITMAPINFOHEADER BMI;
BMI.biSize = sizeof(BITMAPINFOHEADER);
BMI.biWidth = width;
BMI.biHeight = height;
BMI.biPlanes = 1;
BMI.biBitCount = 32;
BMI.biCompression = BI_RGB;
BMI.biSizeImage = 0;
BMI.biXPelsPerMeter = 0;
BMI.biYPelsPerMeter = 0;
BMI.biClrUsed = 0;
BMI.biClrImportant = 0;
return(CreateDIBSection(dc, (BITMAPINFO *)&BMI, DIB_RGB_COLORS, 0, fmap, 0));
}
/***********SCREEN CAPTURE*******************/
/******************************/
void init_dc_blend(void) {
//HMODULE * msimg32_dll = LoadLibrary("msimg32.dll");
HMODULE msimg32_dll = LoadLibrary("msimg32.dll");
if(msimg32_dll)
pAlphaBlend = GetProcAddress(msimg32_dll, "AlphaBlend");
if(pAlphaBlend) {
HDC hdc = GetDC(MainHwnd);
// Create one pixel size bitmap for use in color_blend.
if( colorinpixeldc !=NULL ) { DeleteDC(colorinpixeldc ) ; } colorinpixeldc = CreateCompatibleDC(hdc);
if( colorinpixelbm!=NULL ) { DeleteObject(colorinpixelbm) ; } colorinpixelbm = CreateCompatibleBitmap(hdc, 1, 1);
SelectObject(colorinpixeldc, colorinpixelbm);
colorinpixel = 0;
SetPixelV(colorinpixeldc, 0, 0, colorinpixel);
ReleaseDC(MainHwnd, hdc);
}
}
void color_blend(
HDC destDc, int x, int y, int width, int height,
COLORREF alphacolor, int opacity)
{
if(pAlphaBlend) {
// Fast alpha blending for Win98&2000 and newer...
BLENDFUNCTION blender;
// Create one pixel size bitmap for use in color_blend.
if(colorinpixel != alphacolor)
{
colorinpixel = alphacolor;
SetPixelV(colorinpixeldc, 0, 0, alphacolor);
}
blender.BlendOp = AC_SRC_OVER;
blender.BlendFlags = 0;
blender.SourceConstantAlpha = (0xff * opacity) / 100;
blender.AlphaFormat = 0;
(*pAlphaBlend)(destDc, x, y, width, height, colorinpixeldc, 0, 0, 1, 1, blender);
}
else
{
// Slow alpha blending for Win95&NT...
// Note: Only tested with WinXP, should work on 95/NT.. probably.
int i, alphacolorR, alphacolorG, alphacolorB, bk_opacity;
HBITMAP tmpbm;
HDC tmpdc;
static HANDLE fmap;
static int fmap_size;
static unsigned char * pRGB;
if(fmap_size < width * height * 4)
{
if(fmap) {
UnmapViewOfFile(pRGB);
CloseHandle(fmap);
}
fmap_size = width * height * 4;
fmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, fmap_size, NULL);
pRGB = MapViewOfFile(fmap, FILE_MAP_ALL_ACCESS, 0, 0, fmap_size);
}
// Create DIBSection so we get pixels easily.
tmpdc = CreateCompatibleDC(destDc);
tmpbm = CreateDIBSectionWithFileMapping(destDc, width, height, fmap);
SelectObject(tmpdc, tmpbm);
// Copy bitmap to temporary bitmap for easy pixel access.
BitBlt(tmpdc, 0, 0, width, height, destDc, x, y, SRCCOPY);
// Moved stuff out from the loop
alphacolorR = GetRValue(alphacolor) * opacity;
alphacolorG = GetGValue(alphacolor) * opacity;
alphacolorB = GetBValue(alphacolor) * opacity;
bk_opacity = 100 - opacity;
for(i=0; i<width*height*4; i+=4)
{
pRGB[i + 0] = (pRGB[i + 0] * bk_opacity + alphacolorB) / 100;
pRGB[i + 1] = (pRGB[i + 1] * bk_opacity + alphacolorG) / 100;
pRGB[i + 2] = (pRGB[i + 2] * bk_opacity + alphacolorR) / 100;
}
// Copy temporary bitmap back to original
BitBlt(destDc, x, y, width, height, tmpdc, 0, 0, SRCCOPY);
DeleteObject(tmpbm);
DeleteDC(tmpdc);
}
}
static void color_opacity_gradient( HDC destDc, int x, int y, int width, int height, COLORREF alphacolor, int style ) {
int i, alphacolorR, alphacolorG, alphacolorB, bk_opacity, opacity, h, w ;
double l ;
HBITMAP tmpbm;
HDC tmpdc;
static HANDLE fmap;
static int fmap_size;
static unsigned char * pRGB;
int OpacityMin = 0, OpacityMax = 100 ;
char buf[256] = "" ;
if( GetSessionField( conf_get_str(conf,CONF_sessionname), conf_get_str(conf,CONF_folder), "BgOpacityRange", buf ) ) {
sscanf( buf, "%d-%d", &OpacityMin, &OpacityMax ) ;
if( OpacityMin == OpacityMax ) { OpacityMin = 0 ; OpacityMax = 100 ; }
}
if(fmap_size < width * height * 4) {
if(fmap) { UnmapViewOfFile(pRGB) ; CloseHandle(fmap) ; }
fmap_size = width * height * 4;
fmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, fmap_size, NULL);
pRGB = MapViewOfFile(fmap, FILE_MAP_ALL_ACCESS, 0, 0, fmap_size);
}
// Create DIBSection so we get pixels easily.
tmpdc = CreateCompatibleDC(destDc);
tmpbm = CreateDIBSectionWithFileMapping(destDc, width, height, fmap);
SelectObject(tmpdc, tmpbm);
// Copy bitmap to temporary bitmap for easy pixel access.
BitBlt(tmpdc, 0, 0, width, height, destDc, x, y, SRCCOPY);
opacity = 0 ; bk_opacity = 100 ; alphacolorR = 0 ; alphacolorG = 0 ; alphacolorB = 0 ;
w = 0 ; h = 0 ;
for(i=0; i<width*height*4; i+=4) {
switch( style ) {
case 2: // De bas en haut
if( (i%(4*width)) == 0 ) {
h++ ;
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * (1.0*h)/(1.0*height) ;
opacity = 100 - opacity ;
}
break ;
case 3: // De gauche a droite
w++ ; if( w >= width ) { w = 0 ; }
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * (1.0*w)/(1.0*width) ;
break ;
case 4: // De droite a gauche
w++ ; if( w >= width ) { w = 0 ; }
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * (1.0*w)/(1.0*width) ;
opacity = 100 - opacity ;
break ;
case 5: // Du centre vers l'exterieur
if( (i%(4*width)) == 0 ) { h++ ; }
w++ ; if( w >= width ) { w = 0 ; }
l = sqrt( pow(1.0*width/2.0-w,2.0)+pow(1.0*height/2.0-h,2.0) ) /
sqrt( pow(1.0*width/2.0,2.0)+pow(1.0*height/2.0,2.0) );
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ;
break ;
case 6: // De l'exterieur vers le centre
if( (i%(4*width)) == 0 ) { h++ ; }
w++ ; if( w >= width ) { w = 0 ; }
l = sqrt( pow(1.0*width/2.0-w,2.0)+pow(1.0*height/2.0-h,2.0) ) /
sqrt( pow(1.0*width/2.0,2.0)+pow(1.0*height/2.0,2.0) );
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ;
opacity = 100 - opacity ;
break ;
case 7:
if( (i%(4*width)) == 0 ) { h++ ; }
w++ ; if( w >= width ) { w = 0 ; }
l = sqrt( pow(1.0*w,2.0)+pow(1.0*h,2.0) )/sqrt( pow(1.0*width,2.0)+pow(1.0*height,2.0) ) ;
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ;
break ;
case 8:
if( (i%(4*width)) == 0 ) { h++ ; }
w++ ; if( w >= width ) { w = 0 ; }
l = sqrt( pow(1.0*w,2.0)+pow(1.0*h,2.0) )/sqrt( pow(1.0*width,2.0)+pow(1.0*height,2.0) ) ;
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ;
opacity = 100 - opacity ;
break ;
case 9:
if( (i%(4*width)) == 0 ) { h++ ; }
w++ ; if( w >= width ) { w = 0 ; }
l = sqrt( pow(1.0*(width-w),2.0)+pow(1.0*h,2.0) )/sqrt( pow(1.0*width,2.0)+pow(1.0*height,2.0) ) ;
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ;
break ;
case 10:
if( (i%(4*width)) == 0 ) { h++ ; }
w++ ; if( w >= width ) { w = 0 ; }
l = sqrt( pow(1.0*(width-w),2.0)+pow(1.0*h,2.0) )/sqrt( pow(1.0*width,2.0)+pow(1.0*height,2.0) ) ;
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ;
opacity = 100 - opacity ;
break ;
default: // De haut en bas
if( (i%(4*width)) == 0 ) {
h++ ;
opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * (1.0*h)/(1.0*height) ;
}
break ;
}
if( opacity < 0 ) opacity = 0 ;
if( opacity > 100 ) opacity = 100 ;
alphacolorR = GetRValue(alphacolor) * opacity;
alphacolorG = GetGValue(alphacolor) * opacity;
alphacolorB = GetBValue(alphacolor) * opacity;
bk_opacity = 100 - opacity ;
pRGB[i + 0] = (pRGB[i + 0] * bk_opacity + alphacolorB) / 100;
pRGB[i + 1] = (pRGB[i + 1] * bk_opacity + alphacolorG) / 100;
pRGB[i + 2] = (pRGB[i + 2] * bk_opacity + alphacolorR) / 100;
}
// Copy temporary bitmap back to original
BitBlt(destDc, x, y, width, height, tmpdc, 0, 0, SRCCOPY);
DeleteObject(tmpbm);
DeleteDC(tmpdc);
}
void CreateBlankBitmap( HBITMAP * rawImage, const int width, const int height ) {
HDC dc= CreateCompatibleDC(NULL);
BITMAPINFO bi;
ZeroMemory( &bi.bmiHeader, sizeof(BITMAPINFOHEADER) );
bi.bmiHeader.biWidth=width; // Set size you need
bi.bmiHeader.biHeight=height; // Set size you need
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biBitCount=24; // Can be 8, 16, 32 bpp or
bi.bmiHeader.biSizeImage=0;
bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biClrUsed= 0;
bi.bmiHeader.biClrImportant= 0;
VOID *pvBits;
if( *rawImage!=NULL ) { DeleteObject( *rawImage ) ; *rawImage=NULL ; }
*rawImage = CreateDIBSection( dc,&bi,DIB_RGB_COLORS,&pvBits,NULL,0 );
ReleaseDC(NULL, dc) ;
HDC hDC = GetDC(MainHwnd);
HDC hDCDst = CreateCompatibleDC(hDC); // memory device context for dest bitmap
ReleaseDC(NULL, hDC);
// hdcMem contains your rendered particle
HBRUSH hBrush = CreateSolidBrush(RGB(255,0,0));
// Paints the rectangular band with the brush
RECT Rect = {0, 0, width-1, height-1};
FillRect(hDCDst, &Rect, hBrush);
// Deletes the brush
DeleteObject(hBrush);
HGDIOBJ holdDIBDst = SelectObject(hDCDst, *rawImage);
// transfer the image to your DIB bitmap
BitBlt(hDCDst, 0, 0 ,width, height, hDC, 0, 0, SRCCOPY);
// clean up
SelectObject(hDCDst, holdDIBDst);
DeleteDC(hDCDst);
}
BOOL load_bg_bmp()
{
HBITMAP rawImage = NULL;
BITMAP rawImageInfo;
HDC hdcPrimary;
HDC bmpdc;
int deskWidth, deskHeight, clientWidth, clientHeight;
int x, y;
int style;
//COLORREF backgroundcolor = colours[258]; // Default Background
COLORREF backgroundcolor = return_colours258() ;
COLORREF alphacolor = backgroundcolor;
// Start off assuming this is true.
bBgRelToTerm = conf_get_int( conf,CONF_bg_image_abs_fixed);
RECT clientRect;
GetWindowRect( MainHwnd, &clientRect ) ;
clientWidth = clientRect.right-clientRect.left+1 ;
clientHeight = clientRect.bottom-clientRect.top+1 ;
switch( conf_get_int( conf,CONF_bg_type) )
{
// Solid
case 0:
// No bitmap file to load. We'll handle this case below.
break;
// Wallpaper
case 1:
backgroundcolor = GetSysColor(COLOR_BACKGROUND);
bBgRelToTerm = FALSE; // Wallpaper is never positioned relative to term.
if(!load_wallpaper_bmp(&rawImage, &style, &x, &y))
rawImage = NULL; // Make sure rawImage is still NULL.
break;
// Image
case 2:
{
backgroundcolor = GetSysColor(COLOR_BACKGROUND) ;
if( conf_get_filename(conf,CONF_bg_image_filename)->path[0] == '#' ) {
int r=0,g=0,b=0;
sscanf( conf_get_filename(conf,CONF_bg_image_filename)->path, "#%02X%02X%02X", &r, &g, &b ) ;
backgroundcolor = RGB( r, g, b ) ;
BYTE *pDst = NULL;
rawImage = CreateHBitmap(10, 10, (void**)&pDst);
style = 4 ;
}
else if( !stricmp( conf_get_filename(conf,CONF_bg_image_filename)->path+strlen(conf_get_filename(conf,CONF_bg_image_filename)->path)-4, ".jpg" ) ) {
if(!load_file_jpeg(&rawImage, &style, &x, &y))
rawImage = NULL; // Make sure rawImage is still NULL.
}
else if( !stricmp( conf_get_filename(conf,CONF_bg_image_filename)->path+strlen(conf_get_filename(conf,CONF_bg_image_filename)->path)-5, ".jpeg" ) ) {
if(!load_file_jpeg(&rawImage, &style, &x, &y))
rawImage = NULL; // Make sure rawImage is still NULL.
}
else
if(!load_file_bmp(&rawImage, &style, &x, &y))
rawImage = NULL; // Make sure rawImage is still NULL.
break;
}
}
hdcPrimary = GetDC(MainHwnd);
deskWidth = GetDeviceCaps(hdcPrimary, HORZRES);
deskHeight = GetDeviceCaps(hdcPrimary, VERTRES);
// Securite pour ne pas depacer les limites de l'ecran principal
if( (bBgRelToTerm == 0)
&&((clientRect.right>deskWidth)||(clientRect.bottom>deskHeight)) ) {
//DeleteObject(rawImage); rawImage = NULL ;
bBgRelToTerm = 1 ;
}
if(rawImage == NULL)
{
// Create a solid bitmap. We'll get here in two cases: either the user
// selected the Solid background option, or the attempt to do something
// fancier (use the system wallpaper or an image file) failed.
/*
if( backgrounddc!=NULL ) DeleteDC(backgrounddc) ; backgrounddc = CreateCompatibleDC(hdcPrimary);
if( backgroundbm!=NULL ) DeleteObject(backgroundbm); backgroundbm
= CreateCompatibleBitmap(hdcPrimary, deskWidth, deskHeight);
SelectObject(backgrounddc, backgroundbm);
*/
// Do not create anything, use default 'no background'-code instead.
}
else
{
// We've managed to load a good image. Now, we need to manipulate it to
// the right size, location, etc.
// Find the width and height of the image we just loaded.
GetObject(rawImage, sizeof(rawImageInfo), &rawImageInfo);
// Create a temporary DC to wrap the raw image.
bmpdc = CreateCompatibleDC(hdcPrimary);
SelectObject(bmpdc, rawImage);
// Create a memory DC that has a new bitmap of the appropriate final
// image size.
if( textdc!=NULL ) { DeleteDC(textdc) ; } textdc = CreateCompatibleDC(hdcPrimary);
if( textbm!= NULL ) { DeleteObject(textbm) ; } textbm = CreateCompatibleBitmap(hdcPrimary, deskWidth, deskHeight);
SelectObject(textdc, textbm);
if( backgrounddc!=NULL ) { DeleteDC(backgrounddc) ; } backgrounddc = CreateCompatibleDC(hdcPrimary);
if( backgroundbm!=NULL ) { DeleteObject(backgroundbm) ; } backgroundbm = CreateCompatibleBitmap(hdcPrimary, deskWidth, deskHeight) ;
SelectObject(backgrounddc, backgroundbm);
switch(style)
{
case 0: { // Tile
for(y = 0; y < deskHeight; y += rawImageInfo.bmHeight)
{
for(x = 0; x < deskWidth; x += rawImageInfo.bmWidth)
{
BitBlt(
backgrounddc,
x, y, rawImageInfo.bmWidth, rawImageInfo.bmHeight,
bmpdc, 0, 0, SRCCOPY
);
}
}
}
break;
case 1: // Center
// Calculate x & y, ignoring values they may already have, then drop
// down to the (X,Y) placement case below.
x = (deskWidth - rawImageInfo.bmWidth) / 2;
y = (deskHeight - rawImageInfo.bmHeight) / 2;
case 3: { // Absolute Place at given (X,Y)
// Start out with a background color fill.
fill_dc(backgrounddc, deskWidth, deskHeight, backgroundcolor);
BitBlt(
backgrounddc,
x, y, rawImageInfo.bmWidth, rawImageInfo.bmHeight,
bmpdc, 0, 0, SRCCOPY
);
break;
}
case 2: // Stretch
StretchBlt(
backgrounddc, 0, 0, deskWidth, deskHeight,
bmpdc, 0, 0, rawImageInfo.bmWidth, rawImageInfo.bmHeight,
SRCCOPY
);
break;
case 4: // blank background
fill_dc(backgrounddc, deskWidth, deskHeight, backgroundcolor) ;
break ;
case 5: // Stretch a la taille de la fenetre
{
if( (ShrinkBitmapEnable)&&(clientWidth<rawImageInfo.bmWidth)&&(clientHeight<rawImageInfo.bmHeight) ) {
HBITMAP newhbmpBMP ;
if( (newhbmpBMP = ShrinkBitmap( rawImage,clientWidth,clientHeight)) != NULL ) {
//if( (newhbmpBMP = ResizeBmp( rawImage,clientWidth,clientHeight)) != NULL ) {
DeleteDC(bmpdc) ;
bmpdc = CreateCompatibleDC(0) ;
DeleteDC(backgrounddc); backgrounddc = GetDC(MainHwnd);
SelectObject(bmpdc, newhbmpBMP ) ;
BitBlt(backgrounddc, 0, 0,clientWidth,clientHeight, bmpdc, 0, 0, SRCCOPY ) ;
DeleteObject(newhbmpBMP);
}
else
StretchBlt( backgrounddc,0,0,clientWidth,clientHeight,bmpdc,0,0,rawImageInfo.bmWidth,rawImageInfo.bmHeight,SRCCOPY);
}
else
StretchBlt( backgrounddc,0,0,clientWidth,clientHeight,bmpdc,0,0,rawImageInfo.bmWidth,rawImageInfo.bmHeight,SRCCOPY);
}
break ;
}
// Create a version of the background DC with opacity already applied
// for fast screen fill in areas with no text.
if( backgroundblenddc!=NULL ) { DeleteDC(backgroundblenddc) ; } backgroundblenddc = CreateCompatibleDC(hdcPrimary);
if( backgroundblendbm!=NULL ) { DeleteObject(backgroundblendbm) ; } backgroundblendbm = CreateCompatibleBitmap( hdcPrimary, deskWidth, deskHeight );
DeleteObject(rawImage);
DeleteDC(bmpdc);
SelectObject(backgroundblenddc, backgroundblendbm);
BitBlt(
backgroundblenddc, 0, 0, deskWidth, deskHeight,
backgrounddc, 0, 0, SRCCOPY
);
if( conf_get_int(conf,CONF_bg_opacity) >= 0 )
{ color_blend( backgroundblenddc, 0, 0, deskWidth, deskHeight, alphacolor, conf_get_int(conf,CONF_bg_opacity)); }
else
{
if( bBgRelToTerm == 1 ) {
deskWidth = clientWidth ;
deskHeight = clientHeight ;
}
color_opacity_gradient( backgroundblenddc, 0, 0, deskWidth, deskHeight, alphacolor, -conf_get_int(conf,CONF_bg_opacity) );
}
}
ReleaseDC(MainHwnd, hdcPrimary);
//DeleteDC(hdcPrimary);
return TRUE;
}
void paint_term_edges(Terminal*term, HDC hdc, LONG paint_left, LONG paint_top, LONG paint_right, LONG paint_bottom)
{
if(backgrounddc == 0)
load_bg_bmp();
if(backgrounddc)
{
LONG topLeftX = paint_left;
LONG topLeftY = paint_top;
LONG width = (paint_right - paint_left);
LONG height = (paint_bottom - paint_top);
HDC srcdc = backgroundblenddc;
POINT srcTopLeft;
RECT size_now;
srcTopLeft.x = topLeftX;
srcTopLeft.y = topLeftY;
if(!bBgRelToTerm)
ClientToScreen(MainHwnd, &srcTopLeft);
if(!srcdc)
srcdc = backgrounddc;
if(resizing)
{
GetClientRect(MainHwnd, &size_now);
if(size_now.bottom > size_before.bottom || size_now.right > size_before.right)
{
// Draw on full area on resize.
BitBlt(hdc, topLeftX, topLeftY, width, height, srcdc, srcTopLeft.x, srcTopLeft.y, SRCCOPY);
return;
}
}
//debug_log("1: %d %d %d %d\n",size_before.top,size_before.bottom,size_before.left,size_before.right) ;
//debug_log("2: %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %d\n",topLeftX,topLeftY,width,height,srcTopLeft.x,srcTopLeft.y,size_now.top,size_now.bottom,size_now.left,size_now.right,resizing) ;
// Draw top edge
BitBlt(
hdc, topLeftX, topLeftY, width, return_offset_height(),
srcdc, srcTopLeft.x, srcTopLeft.y, SRCCOPY
);
// Draw left edge
BitBlt(
hdc, topLeftX, topLeftY+1, return_offset_width(), height-2,
srcdc, srcTopLeft.x, srcTopLeft.y+1, SRCCOPY
);
// Draw right edge (extra width for clean resizing)
BitBlt(
hdc, topLeftX+width-1, topLeftY+1, return_offset_width(), height-2,
srcdc, srcTopLeft.x+width-1, srcTopLeft.y+1, SRCCOPY
);
// Draw bottom edge (extra height for clean resizing)
BitBlt(
hdc, topLeftX, topLeftY+height-1, width, return_offset_height(),
srcdc, srcTopLeft.x, srcTopLeft.y+height-1, SRCCOPY
);
}
else
{
HBRUSH bgbrush, oldbrush;
HPEN edge, oldpen;
//COLORREF backgroundcolor = colours[258];
COLORREF backgroundcolor = return_colours258() ;
bgbrush = CreateSolidBrush(backgroundcolor);
edge = CreatePen(PS_SOLID, 0, backgroundcolor);
oldbrush = SelectObject(hdc, bgbrush);
oldpen = SelectObject(hdc, edge);
/*
* Jordan Russell reports that this apparently
* ineffectual IntersectClipRect() call masks a
* Windows NT/2K bug causing strange display
* problems when the PuTTY window is taller than
* the primary monitor. It seems harmless enough...
*/
IntersectClipRect(hdc,
paint_left, paint_top,
paint_right, paint_bottom);
ExcludeClipRect(hdc,
return_offset_width(), return_offset_height(),
return_offset_width()+return_font_width()*(term->cols),
return_offset_height()+return_font_height()*(term->rows));
//debug_log("3: %d %d %d %d %d %d %d\n",resizing,paint_left, paint_top, paint_right, paint_bottom,offset_width,offset_height ) ;
//debug_log("4: %d %d %d %d\n",size_before.top,size_before.bottom,size_before.left,size_before.right) ;
//debug_log("5: %d %d %d %d %d %d\n",paint_top,paint_bottom,paint_left,paint_right,term->cols,term->rows);
Rectangle(hdc, paint_left, paint_top,
paint_right, paint_bottom);
SelectObject(hdc, oldpen);
DeleteObject(edge);
SelectObject(hdc, oldbrush);
DeleteObject(bgbrush);
}
}
/*
void original_paint_term_edges(HDC hdc, LONG paint_left, LONG paint_top, LONG paint_right, LONG paint_bottom)
{
if(backgrounddc == 0)
load_bg_bmp();
if(backgrounddc)
{
LONG topLeftX = paint_left;
LONG topLeftY = paint_top;
LONG width = (paint_right - paint_left);
LONG height = (paint_bottom - paint_top);
HDC srcdc = backgroundblenddc;
POINT srcTopLeft;
RECT size_now;
srcTopLeft.x = topLeftX;
srcTopLeft.y = topLeftY;
if(!bBgRelToTerm)
ClientToScreen(hwnd, &srcTopLeft);
if(!srcdc)
srcdc = backgrounddc;
if(resizing)
{
GetClientRect(hwnd, &size_now);
if(size_now.bottom > size_before.bottom || size_now.right > size_before.right)
{
// Draw on full area on resize.
BitBlt(hdc, topLeftX, topLeftY, width, height, srcdc, srcTopLeft.x, srcTopLeft.y, SRCCOPY);
return;
}
}
//debug_log("1: %d %d %d %d\n",size_before.top,size_before.bottom,size_before.left,size_before.right) ;
//debug_log("2: %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %d\n",topLeftX,topLeftY,width,height,srcTopLeft.x,srcTopLeft.y,size_now.top,size_now.bottom,size_now.left,size_now.right,resizing) ;
// Draw top edge
BitBlt(
hdc, topLeftX, topLeftY, width, offset_height,
srcdc, srcTopLeft.x, srcTopLeft.y, SRCCOPY
);
// Draw left edge
BitBlt(
hdc, topLeftX, topLeftY+1, offset_width, height-2,
srcdc, srcTopLeft.x, srcTopLeft.y+1, SRCCOPY
);
// Draw right edge (extra width for clean resizing)
BitBlt(
hdc, topLeftX+width-1, topLeftY+1, offset_width, height-2,
srcdc, srcTopLeft.x+width-1, srcTopLeft.y+1, SRCCOPY
);
// Draw bottom edge (extra height for clean resizing)
BitBlt(
hdc, topLeftX, topLeftY+height-1, width, offset_height,
srcdc, srcTopLeft.x, srcTopLeft.y+height-1, SRCCOPY
);
}
else
{
HBRUSH bgbrush, oldbrush;
HPEN edge, oldpen;
COLORREF backgroundcolor = colours[258];
bgbrush = CreateSolidBrush(backgroundcolor);
edge = CreatePen(PS_SOLID, 0, backgroundcolor);
oldbrush = SelectObject(hdc, bgbrush);
oldpen = SelectObject(hdc, edge);
//
// * Jordan Russell reports that this apparently
// * ineffectual IntersectClipRect() call masks a
// * Windows NT/2K bug causing strange display
// * problems when the PuTTY window is taller than
// * the primary monitor. It seems harmless enough...
IntersectClipRect(hdc,
paint_left, paint_top,
paint_right, paint_bottom);
ExcludeClipRect(hdc,
offset_width, offset_height,
offset_width+font_width*(term->cols),
offset_height+font_height*(term->rows));
//debug_log("3: %d %d %d %d %d %d %d\n",resizing,paint_left, paint_top, paint_right, paint_bottom,offset_width,offset_height ) ;
//debug_log("4: %d %d %d %d\n",size_before.top,size_before.bottom,size_before.left,size_before.right) ;
//debug_log("5: %d %d %d %d %d %d\n",paint_top,paint_bottom,paint_left,paint_right,term->cols,term->rows);
Rectangle(hdc, paint_left, paint_top,
paint_right, paint_bottom);
SelectObject(hdc, oldpen);
DeleteObject(edge);
SelectObject(hdc, oldbrush);
DeleteObject(bgbrush);
}
}
*/
void clean_bg(void) {
DeleteDC(textdc);textdc=NULL;
DeleteObject(textbm);textbm=NULL;
//DeleteObject(colorinpixel);
//DeleteDC(colorinpixeldc);
//DeleteObject(colorinpixelbm);
DeleteDC(backgrounddc);backgrounddc=NULL;
DeleteObject(backgroundbm);backgroundbm=NULL;
DeleteDC(backgroundblenddc);backgroundblenddc=NULL;
DeleteObject(backgroundblendbm);backgroundblendbm=NULL;
}
void RedrawBackground( HWND hwnd ) {
if(
1 && // On inhibe cette fonction a cause du probleme de fuite memoire due a l'image de fond !!! , mais probleme de rafraichissement ?
(get_param("BACKGROUNDIMAGE"))&&(!get_param("PUTTY"))&&(conf_get_int(conf,CONF_bg_type) != 0) )
{
clean_bg() ;
load_bg_bmp(); // Apparement c'est ça qui faisait la fuite memoire !!!
}
/*
InvalidateRect(hwnd, NULL, true) ;
RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
*/
RedrawWindow( hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_UPDATENOW ) ;
}
#ifdef MOD_STARTBUTTON
/*
* Patch permettant de gerer le probleme de chargement de l'image de fond arrive avec putty 0.61
*/
void BackgroundImagePatch( int num ) {
int key=0x47 ;
if( num == 1 ) { // Double-clic sur une session, on fait ALT-G + Down + ALT-O
key = 0x47 ; /* VK_G 71 */
keybd_event(VK_LMENU , 0, 0, 0) ;
keybd_event( key, 0, 0, 0);
keybd_event( key, 0, KEYEVENTF_KEYUP, 0) ;
keybd_event(VK_LMENU, 0, KEYEVENTF_KEYUP, 0) ;
keybd_event(VK_DOWN, 0, 0, 0) ;
keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0) ;
key=0x4F ; /* VK_O */
keybd_event(VK_LMENU , 0, 0, 0) ;
keybd_event( key, 0, 0, 0);
keybd_event( key, 0, KEYEVENTF_KEYUP, 0) ;
keybd_event(VK_LMENU, 0, KEYEVENTF_KEYUP, 0) ;
}
}
#endif
#endif
HBITMAP HWND_to_HBITMAP(HWND hWnd)
{
RECT r;
HDC hdcMem, hdcScr;
HBITMAP hbmMem, hbmOld;
GetWindowRect(hWnd, &r);
hdcScr = GetWindowDC(hWnd);
hdcMem = CreateCompatibleDC(hdcScr);
hbmMem = CreateCompatibleBitmap(hdcScr, r.right -= r.left, r.bottom -= r.top) ;
hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
BitBlt(hdcMem, 0, 0, r.right, r.bottom, hdcScr, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
ReleaseDC(hWnd, hdcScr);
DeleteDC(hdcMem);
return hbmMem;
}
BOOL HBITMAP_to_JPG(HBITMAP hbm, LPCTSTR jpgfile, int quality)
{
BITMAP bm;
BITMAPINFO bi;
BYTE *pPixels;
JSAMPROW jrows[1], jrow;
HDC hdcScr, hdcMem1, hdcMem2;
HBITMAP hbmMem, hbmOld1, hbmOld2;
FILE *fp = fopen(jpgfile, "wb");
struct jpeg_compress_struct jpeg;
struct jpeg_error_mgr jerr;
if(!hbm)
return 0;
if(!GetObject(hbm, sizeof(bm), &bm))
return 0;
if(!fp)
return 0;
ZeroMemory(&bi, sizeof(bi));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = bm.bmWidth;
bi.bmiHeader.biHeight = bm.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biCompression = BI_RGB;
hdcScr = GetDC(0);
hdcMem1 = CreateCompatibleDC(hdcScr);
hbmOld1 = (HBITMAP)SelectObject(hdcMem1,hbm);
hdcMem2 = CreateCompatibleDC(hdcScr);
hbmMem = CreateDIBSection(hdcScr, &bi, DIB_RGB_COLORS, (VOID **)&pPixels, 0, 0);
hbmOld2 = (HBITMAP)SelectObject(hdcMem2, hbmMem);
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY);
SelectObject(hdcMem1, hbmOld1);
SelectObject(hdcMem2, hbmOld2);
ReleaseDC(0, hdcScr);
DeleteDC(hdcMem1);
DeleteDC(hdcMem2);
jpeg.err = jpeg_std_error(&jerr);
jpeg_create_compress(&jpeg);
jpeg_stdio_dest(&jpeg, fp);
jpeg.image_width = bm.bmWidth;
jpeg.image_height = bm.bmHeight;
jpeg.input_components = 3;
jpeg.in_color_space = JCS_RGB;
jpeg.dct_method = JDCT_FLOAT;
jpeg_set_defaults(&jpeg);
jpeg_set_quality(&jpeg, (quality < 0 || quality > 100) ? 100 : quality, TRUE);
jpeg_start_compress(&jpeg, TRUE);
char *comment=NULL ;
if( comment ) {
jpeg_write_marker(&jpeg, JPEG_COM, (const JOCTET*)comment, strlen(comment));
}
while(jpeg.next_scanline < jpeg.image_height)
{
unsigned int i, j, tmp;
jrow = &pPixels[(jpeg.image_height - jpeg.next_scanline - 1) * ((((bm.bmWidth * 24) + 31) / 32) * 4)];
for(i = 0; i < jpeg.image_width; i++)
{
j = i * 3;
tmp = jrow[j];
jrow[j] = jrow[j + 2];
jrow[j + 2] = tmp;
}
jrows[0] = jrow;
jpeg_write_scanlines(&jpeg, jrows, 1);
}
jpeg_finish_compress(&jpeg);
jpeg_destroy_compress(&jpeg);
DeleteObject(hbmMem);
fclose(fp);
return 1;
}
void MakeScreenShot() {
HBITMAP hbm = HWND_to_HBITMAP(GetDesktopWindow());
if(hbm) {
HBITMAP_to_JPG(hbm, "screenshot.jpg", 85) ;
DeleteObject(hbm);
}
}
int screenCapturePart(int x, int y, int w, int h, LPCSTR fname,int quality) {
int return_code = 0 ;
HDC hdcSource = GetDC(NULL);
HDC hdcMemory = CreateCompatibleDC(hdcSource);
//int capX = GetDeviceCaps(hdcSource, HORZRES);
//int capY = GetDeviceCaps(hdcSource, VERTRES);
HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, w, h);
HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
BitBlt(hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hdcMemory, hBitmapOld);
DeleteDC(hdcSource);
DeleteDC(hdcMemory);
//HPALETTE hpal = NULL;
if( HBITMAP_to_JPG( hBitmap,fname, quality) ) { return_code = 1 ; }
DeleteObject(hBitmap);
return return_code ;
}
int screenCaptureClientRect( HWND hwnd, LPCSTR fname, int quality ) {
RECT rc;
POINT p;
GetClientRect(hwnd, &rc);
p.x=rc.left; p.y=rc.top,
ClientToScreen(hwnd,&p);
rc.left=p.x;rc.top=p.y;
return screenCapturePart(rc.left,rc.top,rc.right,rc.bottom,fname,quality) ;
}
int screenCaptureWinRect( HWND hwnd, LPCSTR fname, int quality ) {
RECT r;
GetWindowRect(hwnd, &r);
return screenCapturePart(r.left,r.top,r.right-r.left,r.bottom-r.top,fname,quality) ;
}
int screenCaptureAll( LPCSTR fname, int quality ) {
return screenCapturePart(0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics (SM_CYSCREEN),fname,quality) ;
}