diff -u -r putty-orig/CONFIG.C putty/CONFIG.C --- putty-orig/CONFIG.C 2005-10-07 00:30:14.000000000 -0500 +++ putty/CONFIG.C 2005-10-06 20:27:17.078125000 -0500 @@ -1359,6 +1359,64 @@ I(offsetof(Config,window_border)), I(-1)); /* + * The Window/Background panel. + * (This would really belong in Appearance but we overflowed -- to much + * stuff on one page otherwise). + */ + str = dupprintf("Configure the background of %s's window", appname); + ctrl_settitle(b, "Window/Background", str); + sfree(str); + + s = ctrl_getset(b, "Window/Background", "bg_style", + "Background settings"); + ctrl_radiobuttons(s, "Background Style:", NO_SHORTCUT, 3, + HELPCTX(appearance_background), + dlg_stdradiobutton_handler, + I(offsetof(Config, bg_type)), + "Solid", NO_SHORTCUT, I(0), // TODO: Define shortcuts for these. + "Desktop", NO_SHORTCUT, I(1), + "Image", NO_SHORTCUT, I(2), + NULL); + + s = ctrl_getset(b, "Window/Background", "bg_wp_img_settings", + "Desktop and image settings"); + ctrl_editbox(s, "Opacity:", NO_SHORTCUT, 20, + HELPCTX(appearance_background), + dlg_stdeditbox_handler, + I(offsetof(Config,bg_opacity)), I(-1)); + + s = ctrl_getset(b, "Window/Background", "bg_img_settings", + "Image settings"); + ctrl_filesel(s, "Image file:", 'k', + FILTER_IMAGE_FILES, FALSE, "Select background image file", + HELPCTX(appearance_background), + dlg_stdfilesel_handler, I(offsetof(Config, bg_image_filename))); + ctrl_radiobuttons(s, "Image placement:", NO_SHORTCUT, 4, + HELPCTX(appearance_background), + dlg_stdradiobutton_handler, + I(offsetof(Config, bg_image_style)), + "Tile", NO_SHORTCUT, I(0), // TODO: Define shortcuts for these. + "Center", NO_SHORTCUT, I(1), + "Stretch", NO_SHORTCUT, I(2), + "Absolute (X,Y)", NO_SHORTCUT, I(3), + NULL); + ctrl_editbox(s, "Absolute Left (X):", NO_SHORTCUT, 20, + HELPCTX(appearance_background), + dlg_stdeditbox_handler, + I(offsetof(Config,bg_image_abs_x)), I(-1)); + ctrl_editbox(s, "Absolute Top (Y):", NO_SHORTCUT, 20, + HELPCTX(appearance_background), + dlg_stdeditbox_handler, + I(offsetof(Config,bg_image_abs_y)), I(-1)); + ctrl_radiobuttons(s, "Image placement is relative to:", NO_SHORTCUT, 2, + HELPCTX(appearance_background), + dlg_stdradiobutton_handler, + I(offsetof(Config, bg_image_abs_fixed)), + "Desktop", NO_SHORTCUT, I(0), // TODO: Define shortcuts for these. + "Terminal Window", NO_SHORTCUT, I(1), + NULL); + + /* * The Window/Behaviour panel. */ str = dupprintf("Configure the behaviour of %s's window", appname); diff -u -r putty-orig/PUTTY.H putty/PUTTY.H --- putty-orig/PUTTY.H 2005-10-07 00:30:14.000000000 -0500 +++ putty/PUTTY.H 2005-10-06 20:37:19.328125000 -0500 @@ -509,6 +509,13 @@ int hide_mouseptr; int sunken_edge; int window_border; + int bg_opacity; + int bg_type; /* 0=solid 1=wallpaper 2=bitmap */ + int bg_image_style; /* 0=tile 1=center 2=stretch 3=(x,y) */ + int bg_image_abs_x; + int bg_image_abs_y; + int bg_image_abs_fixed; /* 0=fixed to desktop, 1=fixed to term wnd */ + Filename bg_image_filename; char answerback[256]; char printer[128]; int arabicshaping; diff -u -r putty-orig/SETTINGS.C putty/SETTINGS.C --- putty-orig/SETTINGS.C 2005-10-07 00:30:14.000000000 -0500 +++ putty/SETTINGS.C 2005-10-06 20:29:36.796875000 -0500 @@ -344,6 +344,10 @@ write_setting_i(sesskey, "HideMousePtr", cfg->hide_mouseptr); write_setting_i(sesskey, "SunkenEdge", cfg->sunken_edge); write_setting_i(sesskey, "WindowBorder", cfg->window_border); + write_setting_i(sesskey, "BgOpacity", cfg->bg_opacity); + write_setting_i(sesskey, "BgType", cfg->bg_type); + write_setting_i(sesskey, "BgImageStyle", cfg->bg_image_style); + write_setting_filename(sesskey, "BgImageFile", cfg->bg_image_filename); write_setting_i(sesskey, "CurType", cfg->cursor_type); write_setting_i(sesskey, "BlinkCur", cfg->blink_cur); write_setting_i(sesskey, "Beep", cfg->beep); @@ -617,6 +621,10 @@ gppi(sesskey, "HideMousePtr", 0, &cfg->hide_mouseptr); gppi(sesskey, "SunkenEdge", 0, &cfg->sunken_edge); gppi(sesskey, "WindowBorder", 1, &cfg->window_border); + gppi(sesskey, "BgOpacity", 50, &cfg->bg_opacity); + gppi(sesskey, "BgType", 0, &cfg->bg_type); + gppi(sesskey, "BgImageStyle", 0, &cfg->bg_image_style); + gppfile(sesskey, "BgImageFile", &cfg->bg_image_filename); gppi(sesskey, "CurType", 0, &cfg->cursor_type); gppi(sesskey, "BlinkCur", 0, &cfg->blink_cur); /* pedantic compiler tells me I can't use &cfg->beep as an int * :-) */ diff -u -r putty-orig/VERSION.C putty/VERSION.C --- putty-orig/VERSION.C 2005-10-07 00:30:14.000000000 -0500 +++ putty/VERSION.C 2005-10-06 20:33:24.484375000 -0500 @@ -25,7 +25,7 @@ #else -char ver[] = "Unidentified build, " __DATE__ " " __TIME__; +char ver[] = "PuTTY + Transparency (covidimus.net), " __DATE__ " " __TIME__; char sshver[] = "PuTTY-Local: " __DATE__ " " __TIME__; #endif diff -u -r putty-orig/WINDOWS/WINDOW.C putty/WINDOWS/WINDOW.C --- putty-orig/WINDOWS/WINDOW.C 2005-10-07 00:30:06.000000000 -0500 +++ putty/WINDOWS/WINDOW.C 2005-10-06 20:22:43.687500000 -0500 @@ -79,6 +79,7 @@ static void deinit_fonts(void); static void set_input_locale(HKL); static void update_savedsess_menu(void); +static void init_dc_blend(void); static int is_full_screen(void); static void make_full_screen(void); @@ -114,6 +115,8 @@ static const struct telnet_special *specials; static int n_specials; +static BOOL (WINAPI * pAlphaBlend)(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION) = 0; + #define TIMING_TIMER_ID 1234 static long timing_next_time; @@ -169,6 +172,19 @@ static LPLOGPALETTE logpal; static RGBTRIPLE defpal[NALLCOLOURS]; +static HWND hwnd; + +static HDC textdc; +static HBITMAP textbm; +static COLORREF colorinpixel; +static HDC colorinpixeldc; +static HBITMAP colorinpixelbm; +static HDC backgrounddc; +static HBITMAP backgroundbm; +static HDC backgroundblenddc; +static HBITMAP backgroundblendbm; +static BOOL bBgRelToTerm; + static HBITMAP caretbm; static int dbltime, lasttime, lastact; @@ -184,6 +200,9 @@ static int compose_state = 0; +static int resizing; +static RECT size_before; + static UINT wm_mousewheel = WM_MOUSEWHEEL; /* Dummy routine, only required in plink. */ @@ -655,6 +674,8 @@ } { + const char* winname = appname; + int winmode = WS_OVERLAPPEDWINDOW | WS_VSCROLL; int exwinmode = 0; if (!cfg.scrollbar) @@ -665,10 +686,34 @@ exwinmode |= WS_EX_TOPMOST; if (cfg.sunken_edge) exwinmode |= WS_EX_CLIENTEDGE; - hwnd = CreateWindowEx(exwinmode, appname, appname, + + // TODO: This is the beginning of some work to have windows with fancy + // no-client-edge borders. It's not ready yet. + if(0) + { + winmode = WS_POPUP; + exwinmode = 0; + winname = NULL; + + // TODO: This is proof-of-concept. For this to really work, we'll + // have to do some additional mods, like creating our own title/move + // window to glue to the top, and some kind of drag-resizing window + // to glue to the bottom-right. Otherwise there'll be no way to move + // or resize the window, which will get old extremely quickly. Finally, + // this won't work as written anyway, b/c when you call SetWindowText + // anywhere Win32 forces a window border to appear anyway. So, we'll + // want to create a new function, set_window_text, that checks whether + // to really call SetWindowText or to set the window text in whatever + // other location is necessary for our custom window text display for + // when we're handling our own border here. + } + + hwnd = CreateWindowEx(exwinmode, appname, winname, winmode, CW_USEDEFAULT, CW_USEDEFAULT, guess_width, guess_height, NULL, NULL, inst, NULL); + + init_dc_blend(); } /* @@ -1853,7 +1898,479 @@ return FALSE; } -static int resizing; +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; + int pathLen = MAX_PATH; + int 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, 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, wpStyleBuf, &numBufLen + ); + if(lRes == ERROR_SUCCESS) + wpStyle = atoi(wpStyleBuf); + + lRes = RegQueryValueEx( + kDesktop, "TileWallpaper", NULL, NULL, 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); + + *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 = cfg.bg_image_abs_x; + *y = cfg.bg_image_abs_y; + *style = cfg.bg_image_style; + + *rawImage = LoadImage( + NULL, cfg.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; +} + +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)); +} + +static void init_dc_blend(void) +{ + HMODULE * msimg32_dll = LoadLibrary("msimg32.dll"); + + if(msimg32_dll) + pAlphaBlend = GetProcAddress(msimg32_dll, "AlphaBlend"); + + if(pAlphaBlend) + { + HDC hdc = GetDC(hwnd); + + // Create one pixel size bitmap for use in color_blend. + colorinpixeldc = CreateCompatibleDC(hdc); + colorinpixelbm = CreateCompatibleBitmap(hdc, 1, 1); + SelectObject(colorinpixeldc, colorinpixelbm); + colorinpixel = 0; + SetPixelV(colorinpixeldc, 0, 0, colorinpixel); + + ReleaseDC(hwnd, hdc); + } +} + +static 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 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; + } + } + + // 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); + + Rectangle(hdc, paint_left, paint_top, + paint_right, paint_bottom); + + SelectObject(hdc, oldpen); + DeleteObject(edge); + SelectObject(hdc, oldbrush); + DeleteObject(bgbrush); + } +} void notify_remote_exit(void *fe) { /* stub not needed in this frontend */ } @@ -1869,7 +2386,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - HDC hdc; static int ignore_clip = FALSE; static int need_backend_resize = FALSE; static int fullscr_on_max = FALSE; @@ -2022,6 +2538,30 @@ if (!reconfig_result) break; + if(textdc) + { + DeleteObject(textbm); + DeleteDC(textdc); + textdc = NULL; + textbm = NULL; + } + + if(backgrounddc) + { + DeleteObject(backgroundbm); + DeleteDC(backgrounddc); + backgrounddc = NULL; + backgroundbm = NULL; + } + + if(backgroundblenddc) + { + DeleteObject(backgroundblendbm); + DeleteDC(backgroundblenddc); + backgroundblenddc = NULL; + backgroundblendbm = NULL; + } + { /* Disable full-screen if resizing forbidden */ HMENU m = GetSystemMenu (hwnd, FALSE); @@ -2390,14 +2930,27 @@ case WM_PAINT: { PAINTSTRUCT p; + HDC hdc, hdcScreen, hdcBack = 0; - HideCaret(hwnd); - hdc = BeginPaint(hwnd, &p); - if (pal) { - SelectPalette(hdc, pal, TRUE); - RealizePalette(hdc); - } + HideCaret(hwnd); + hdcScreen = BeginPaint(hwnd, &p); + // We'll draw into a temporary buffer then copy to the screen. After + // this point, the rest of this routine is written to use hdc and not + // care whether hdc is a screen or back buffer, until the very end, + // where the back buffer, if it exists, is blitted to the screen. That + // keeps the routine flexible for use with different drawing policies, + // though right now the only policy we ever use is the one implied by + // the next line, where we always use a back buffer. + //hdc = hdcBack = CreateCompatibleDC(hdcScreen); + hdc = hdcScreen; + + if(pal) + { + SelectPalette(hdcScreen, pal, TRUE); + RealizePalette(hdcScreen); + } + /* * We have to be careful about term_paint(). It will * set a bunch of character cells to INVALID and then @@ -2430,58 +2983,37 @@ * current terminal appearance so that WM_PAINT becomes * completely trivial. However, this should do for now. */ - term_paint(term, hdc, - (p.rcPaint.left-offset_width)/font_width, - (p.rcPaint.top-offset_height)/font_height, - (p.rcPaint.right-offset_width-1)/font_width, - (p.rcPaint.bottom-offset_height-1)/font_height, - !term->window_update_pending); - - if (p.fErase || - p.rcPaint.left < offset_width || - p.rcPaint.top < offset_height || - p.rcPaint.right >= offset_width + font_width*term->cols || - p.rcPaint.bottom>= offset_height + font_height*term->rows) - { - HBRUSH fillcolour, oldbrush; - HPEN edge, oldpen; - fillcolour = CreateSolidBrush ( - colours[ATTR_DEFBG>>ATTR_BGSHIFT]); - oldbrush = SelectObject(hdc, fillcolour); - edge = CreatePen(PS_SOLID, 0, - colours[ATTR_DEFBG>>ATTR_BGSHIFT]); - oldpen = SelectObject(hdc, edge); + term_paint(term, hdc, + (p.rcPaint.left-offset_width)/font_width, + (p.rcPaint.top-offset_height)/font_height, + (p.rcPaint.right-offset_width-1)/font_width, + (p.rcPaint.bottom-offset_height-1)/font_height, + !term->window_update_pending); + + SelectObject(hdc, GetStockObject(SYSTEM_FONT)); + SelectObject(hdc, GetStockObject(WHITE_PEN)); - /* - * 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, - p.rcPaint.left, p.rcPaint.top, - p.rcPaint.right, p.rcPaint.bottom); - - ExcludeClipRect(hdc, - offset_width, offset_height, - offset_width+font_width*term->cols, - offset_height+font_height*term->rows); - - Rectangle(hdc, p.rcPaint.left, p.rcPaint.top, - p.rcPaint.right, p.rcPaint.bottom); - - /* SelectClipRgn(hdc, NULL); */ - - SelectObject(hdc, oldbrush); - DeleteObject(fillcolour); - SelectObject(hdc, oldpen); - DeleteObject(edge); - } - SelectObject(hdc, GetStockObject(SYSTEM_FONT)); - SelectObject(hdc, GetStockObject(WHITE_PEN)); - EndPaint(hwnd, &p); - ShowCaret(hwnd); + if(hdcBack) + { + // Blit the back buffer to the real DC. + BitBlt( + hdcScreen, + p.rcPaint.left - offset_width, + p.rcPaint.top - offset_height, + p.rcPaint.right - p.rcPaint.left + offset_width, + p.rcPaint.bottom - p.rcPaint.top + offset_height, + hdcBack, p.rcPaint.left, p.rcPaint.top, SRCCOPY + ); + + DeleteDC(hdcBack); + hdc = hdcScreen; + } + + // Last paint edges + paint_term_edges(hdc, p.rcPaint.left, p.rcPaint.top, p.rcPaint.right, p.rcPaint.bottom); + + EndPaint(hwnd, &p); + ShowCaret(hwnd); } return 0; case WM_NETEVENT: @@ -2508,6 +3040,7 @@ debug((27, "WM_ENTERSIZEMOVE")); #endif EnableSizeTip(1); + GetClientRect(hwnd, &size_before); resizing = TRUE; need_backend_resize = FALSE; break; @@ -2616,9 +3149,53 @@ case WM_FULLSCR_ON_MAX: fullscr_on_max = TRUE; break; + case WM_DISPLAYCHANGE: case WM_MOVE: + if(backgrounddc) + { + // When using a background image based on the desktop, correct display + // may depend on the current position of the window. + InvalidateRect(hwnd, NULL, TRUE); + } sys_cursor_update(); break; + +case WM_SETTINGCHANGE: + // It's sometimes hard to tell what setting changed, but our decisions + // regarding background drawing depends on some system settings, so force + // it to be redone. + + if(textdc) + { + DeleteObject(textbm); + DeleteDC(textdc); + textdc = NULL; + textbm = NULL; + } + + if(backgrounddc) + { + DeleteObject(backgroundbm); + DeleteDC(backgrounddc); + backgrounddc = NULL; + backgroundbm = NULL; + } + + if(backgroundblenddc) + { + DeleteObject(backgroundblendbm); + DeleteDC(backgroundblenddc); + backgroundblenddc = NULL; + backgroundblendbm = NULL; + } + + if(textdc || backgrounddc || backgroundblenddc) + { + InvalidateRect(hwnd, NULL, TRUE); + } + + break; + case WM_SIZE: #ifdef RDB_DEBUG_PATCH debug((27, "WM_SIZE %s (%d,%d)", @@ -3041,6 +3618,8 @@ int fnt_width, char_width; int text_adjust = 0; static int *IpDx = 0, IpDxLEN = 0; + int transBg = backgrounddc ? 1 : 0; + UINT etoFlagOpaque = transBg ? 0 : ETO_OPAQUE; lattr &= LATTR_MODE; @@ -3164,17 +3743,47 @@ } fg = colours[nfg]; bg = colours[nbg]; + + line_box.left = x; + line_box.top = y; + line_box.right = x + char_width * len; + line_box.bottom = y + font_height; + + if(textdc) + { + int x = line_box.left; + int y = line_box.top; + int width = line_box.right - line_box.left; + int height = line_box.bottom - line_box.top; + + POINT bgloc = { x, y }; + COLORREF backgroundcolor = colours[258]; // Default Background + + if(!bBgRelToTerm) + ClientToScreen(hwnd, &bgloc); + + if(bg == backgroundcolor) + { + // Use fast screen fill for default background. + BitBlt(textdc, x, y, width, height, backgroundblenddc, bgloc.x, bgloc.y, SRCCOPY); + } + else + { + BitBlt(textdc, x, y, width, height, backgrounddc, bgloc.x, bgloc.y, SRCCOPY); + + color_blend(textdc, x, y, width, height, bg, cfg.bg_opacity); + } + + hdc = textdc; + } + SelectObject(hdc, fonts[nfont]); SetTextColor(hdc, fg); SetBkColor(hdc, bg); - if (attr & TATTR_COMBINING) + if (transBg || attr & TATTR_COMBINING) SetBkMode(hdc, TRANSPARENT); else SetBkMode(hdc, OPAQUE); - line_box.left = x; - line_box.top = y; - line_box.right = x + char_width * len; - line_box.bottom = y + font_height; /* Only want the left half of double width lines */ if (line_box.right > font_width*term->cols+offset_width) @@ -3218,7 +3827,7 @@ ExtTextOutW(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust, - ETO_CLIPPED | ETO_OPAQUE, &line_box, uni_buf, nlen, IpDx); + ETO_CLIPPED | etoFlagOpaque, &line_box, uni_buf, nlen, IpDx); if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) { SetBkMode(hdc, TRANSPARENT); ExtTextOutW(hdc, x - 1, @@ -3242,7 +3851,7 @@ ExtTextOut(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust, - ETO_CLIPPED | ETO_OPAQUE, &line_box, directbuf, len, IpDx); + ETO_CLIPPED | etoFlagOpaque, &line_box, directbuf, len, IpDx); if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) { SetBkMode(hdc, TRANSPARENT); @@ -3275,10 +3884,10 @@ /* print Glyphs as they are, without Windows' Shaping*/ exact_textout(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust, - &line_box, wbuf, len, IpDx, !(attr & TATTR_COMBINING)); + &line_box, wbuf, len, IpDx, !(attr & TATTR_COMBINING) &&!transBg); /* ExtTextOutW(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust, - ETO_CLIPPED | ETO_OPAQUE, &line_box, wbuf, len, IpDx); + ETO_CLIPPED | etoFlagOpaque, &line_box, wbuf, len, IpDx); */ /* And the shadow bold hack. */ @@ -3304,6 +3913,17 @@ oldpen = SelectObject(hdc, oldpen); DeleteObject(oldpen); } + + if(textdc) + { + int x = line_box.left; + int y = line_box.top; + int width = line_box.right - line_box.left; + int height = line_box.bottom - line_box.top; + + // Copy the result to the working DC. + BitBlt(ctx, x, y, width, height, hdc, x, y, SRCCOPY); + } } /* diff -u -r putty-orig/WINDOWS/WINHELP.H putty/WINDOWS/WINHELP.H --- putty-orig/WINDOWS/WINHELP.H 2005-10-07 00:30:06.000000000 -0500 +++ putty/WINDOWS/WINHELP.H 2005-10-06 20:22:58.671875000 -0500 @@ -66,6 +66,7 @@ #define WINHELP_CTX_appearance_title "appearance.title" #define WINHELP_CTX_appearance_hidemouse "appearance.hidemouse" #define WINHELP_CTX_appearance_border "appearance.border" +#define WINHELP_CTX_appearance_background "appearance.background" #define WINHELP_CTX_connection_termtype "connection.termtype" #define WINHELP_CTX_connection_termspeed "connection.termspeed" #define WINHELP_CTX_connection_username "connection.username" diff -u -r putty-orig/WINDOWS/WINSTUFF.H putty/WINDOWS/WINSTUFF.H --- putty-orig/WINDOWS/WINSTUFF.H 2005-10-07 00:30:06.000000000 -0500 +++ putty/WINDOWS/WINSTUFF.H 2005-10-06 20:25:12.812500000 -0500 @@ -131,6 +131,8 @@ "All Files (*.*)\0*\0\0\0") #define FILTER_WAVE_FILES ("Wave Files (*.wav)\0*.WAV\0" \ "All Files (*.*)\0*\0\0\0") +#define FILTER_IMAGE_FILES ("Image Files (*.bmp)\0*.BMP\0" \ + "All Files (*.*)\0*\0\0\0") /* * On some versions of Windows, it has been known for WM_TIMER to Only in putty: putty-trans.diff