CBackground::CBackground() { bgSize = MakeCoord(-1,-1); hBgDc = NULL; hBgBitmap = NULL; hOldBitmap = NULL; //// Alpha blending //mh_MsImg32 = LoadLibrary(L"Msimg32.dll"); //if (mh_MsImg32) { // fAlphaBlend = (AlphaBlend_t)GetProcAddress(mh_MsImg32, "AlphaBlend"); //} else { // fAlphaBlend = NULL; //} #ifdef __GNUC__ HMODULE hGdi32 = GetModuleHandle(L"gdi32.dll"); GdiAlphaBlend = (AlphaBlend_t)(hGdi32 ? GetProcAddress(hGdi32, "GdiAlphaBlend") : NULL); #endif mb_NeedBgUpdate = false; mb_BgLastFade = false; mp_BkImgData = NULL; mn_BkImgDataMax = 0; mb_BkImgChanged = FALSE; mb_BkImgExist = /*mb_BkImgDelete =*/ FALSE; mp_BkEmfData = NULL; mn_BkEmfDataMax = 0; mb_BkEmfChanged = FALSE; mcs_BkImgData = NULL; mn_BkImgWidth = mn_BkImgHeight = 0; }
// Helper function: support Tab-completion in cmd.exe and others COORD FixupReadStartCursorPos(DWORD nNumberOfCharsToRead, CONSOLE_SCREEN_BUFFER_INFO& csbi, const MY_CONSOLE_READCONSOLE_CONTROL* pInputControl) { COORD crStartCursorPos = csbi.dwCursorPosition; if (pInputControl && (pInputControl->nLength >= sizeof(*pInputControl))) { if (pInputControl->nInitialChars < nNumberOfCharsToRead) { // Part of input is already "printed" to the buffer, take it into account int nNewX = (int)crStartCursorPos.X - pInputControl->nInitialChars; int nNewY = (int)crStartCursorPos.Y; if (nNewX < 0) { int nRows = klMin(nNewY, (int)((-nNewX) / csbi.dwSize.X)); if ((nRows < nNewY) && ((nNewX + (nRows * csbi.dwSize.X)) < 0)) nRows++; _ASSERTE(((nNewY - nRows) >= 0) && ((nNewX + (nRows * csbi.dwSize.X)) >= 0)); nNewX += (nRows * csbi.dwSize.X); nNewY -= nRows; } if (nNewX >= 0 && nNewY >= 0) { crStartCursorPos = MakeCoord(nNewX, nNewY); csbi.dwCursorPosition = crStartCursorPos; } else { _ASSERTE(nNewX >= 0 && nNewY >= 0); } } } return crStartCursorPos; }
void TermX::Reset() { AppCursorKeys = false; MouseButtons = 0; LastMousePos = MakeCoord(-1,-1); LastDeadCharVK = 0; }
// Должна вернуть true, если данные изменились (то есть будет isForce при полной перерисовке) bool CBackground::PrepareBackground(CVirtualConsole* pVCon, HDC&/*OUT*/ phBgDc, COORD&/*OUT*/ pbgBmpSize) { if (!this) { _ASSERTE(this!=NULL); return false; } _ASSERTE(isMainThread() && "Must be executed in main thread"); bool bSucceeded = true; bool lbForceUpdate = false; LONG lBgWidth = 0, lBgHeight = 0; BOOL lbVConImage = FALSE; if (gpSet->isBgPluginAllowed) { if (HasPluginBackgroundImage(&lBgWidth, &lBgHeight) && lBgWidth && lBgHeight) { lbVConImage = TRUE; } } LONG lMaxBgWidth = 0, lMaxBgHeight = 0; bool bIsForeground = gpConEmu->isMeForeground(true); // Если плагин свой фон не подсунул if (!lbVConImage) { //if (mp_PluginBg) //{ // delete mp_PluginBg; // mp_PluginBg = NULL; //} #ifndef APPDISTINCTBACKGROUND // То работаем на общих основаниях, через настройки (или AppDistinct) return gpSetCls->PrepareBackground(pVCon, &phBgDc, &pbgBmpSize); #else CBackgroundInfo* pBgFile = pVCon->GetBackgroundObject(); if (!pBgFile) { _ASSERTE(FALSE && "Background object must be created in VCon"); return false; } if (!mb_NeedBgUpdate) { if ((hBgDc == NULL) || (mb_BgLastFade == bIsForeground && gpSet->isFadeInactive) || (!gpSet->isFadeInactive && mb_BgLastFade)) { NeedBackgroundUpdate(); } } pBgFile->PollBackgroundFile(); RECT rcWork = {0, 0, pVCon->GetVConWidth(), pVCon->GetVConHeight()}; // необходимо проверить размер требуемой картинки // -- здесь - всегда только файловая подложка if ((gpSet->bgOperation == eUpLeft) || (gpSet->bgOperation == eUpRight) || (gpSet->bgOperation == eDownLeft) || (gpSet->bgOperation == eDownRight) || (gpSet->bgOperation == eCenter)) { // MemoryDC создается всегда по размеру картинки, т.е. изменение размера окна - игнорируется } else { // Смотрим дальше if (gpSet->bgOperation == eStretch) { // Строго по размеру клиентской (точнее Workspace) области окна lMaxBgWidth = rcWork.right - rcWork.left; lMaxBgHeight = rcWork.bottom - rcWork.top; } else if (gpSet->bgOperation == eFit || gpSet->bgOperation == eFill) { lMaxBgWidth = rcWork.right - rcWork.left; lMaxBgHeight = rcWork.bottom - rcWork.top; // Correct aspect ratio const BITMAPFILEHEADER* pBgImgData = pBgFile->GetBgImgData(); const BITMAPINFOHEADER* pBmp = pBgImgData ? (const BITMAPINFOHEADER*)(pBgImgData+1) : NULL; if (pBmp && (rcWork.bottom - rcWork.top) > 0 && (rcWork.right - rcWork.left) > 0) { double ldVCon = (rcWork.right - rcWork.left) / (double)(rcWork.bottom - rcWork.top); double ldImg = pBmp->biWidth / (double)pBmp->biHeight; if (ldVCon > ldImg) { if (gpSet->bgOperation == eFit) lMaxBgWidth = (LONG)(lMaxBgHeight * ldImg); else lMaxBgHeight = (LONG)(lMaxBgWidth / ldImg); } else { if (gpSet->bgOperation == eFill) lMaxBgWidth = (LONG)(lMaxBgHeight * ldImg); else lMaxBgHeight = (LONG)(lMaxBgWidth / ldImg); } } } else if (gpSet->bgOperation == eTile) { // Max между клиентской (точнее Workspace) областью окна и размером текущего монитора // Окно может быть растянуто на несколько мониторов, т.е. размер клиентской области может быть больше HMONITOR hMon = MonitorFromWindow(ghWnd, MONITOR_DEFAULTTONEAREST); MONITORINFO mon = {sizeof(MONITORINFO)}; GetMonitorInfo(hMon, &mon); // lMaxBgWidth = klMax(rcWork.right - rcWork.left,mon.rcMonitor.right - mon.rcMonitor.left); lMaxBgHeight = klMax(rcWork.bottom - rcWork.top,mon.rcMonitor.bottom - mon.rcMonitor.top); } if (bgSize.X != lMaxBgWidth || bgSize.Y != lMaxBgHeight) NeedBackgroundUpdate(); } if (mb_NeedBgUpdate) { mb_NeedBgUpdate = false; lbForceUpdate = true; _ASSERTE(isMainThread()); //MSectionLock SBG; SBG.Lock(&mcs_BgImgData); //BITMAPFILEHEADER* pImgData = mp_BgImgData; BackgroundOp op = (BackgroundOp)gpSet->bgOperation; const BITMAPFILEHEADER* pBgImgData = pBgFile->GetBgImgData(); BOOL lbImageExist = (pBgImgData != NULL); //BOOL lbVConImage = FALSE; //LONG lBgWidth = 0, lBgHeight = 0; //CVirtualConsole* pVCon = gpConEmu->ActiveCon(); ////MSectionLock SBK; //if (apVCon && gpSet->isBgPluginAllowed) //{ // //SBK.Lock(&apVCon->csBkImgData); // if (apVCon->HasBackgroundImage(&lBgWidth, &lBgHeight) // && lBgWidth && lBgHeight) // { // lbVConImage = lbImageExist = TRUE; // } //} //mb_WasVConBgImage = lbVConImage; if (lbImageExist) { mb_BgLastFade = (!bIsForeground && gpSet->isFadeInactive); TODO("Переделать, ориентироваться только на размер картинки - неправильно"); TODO("DoubleView - скорректировать X,Y"); //if (lbVConImage) //{ // if (lMaxBgWidth && lMaxBgHeight) // { // lBgWidth = lMaxBgWidth; // lBgHeight = lMaxBgHeight; // } // if (!mp_Bg->CreateField(lBgWidth, lBgHeight) || // !apVCon->PutBackgroundImage(mp_Bg, 0,0, lBgWidth, lBgHeight)) // { // delete mp_Bg; // mp_Bg = NULL; // } //} //else { const BITMAPINFOHEADER* pBmp = (const BITMAPINFOHEADER*)(pBgImgData+1); if (!lMaxBgWidth || !lMaxBgHeight) { // Сюда мы можем попасть только в случае eUpLeft/eUpRight/eDownLeft/eDownRight lMaxBgWidth = pBmp->biWidth; lMaxBgHeight = pBmp->biHeight; } //LONG lImgX = 0, lImgY = 0, lImgW = lMaxBgWidth, lImgH = lMaxBgHeight; //if ((gpSet->bgOperation == eFit || gpSet->bgOperation == eFill) // && (rcWork.bottom - rcWork.top) > 0 && (rcWork.right - rcWork.left) > 0) //{ // double ldVCon = (rcWork.right - rcWork.left) / (double)(rcWork.bottom - rcWork.top); // double ldImg = pBmp->biWidth / (double)pBmp->biHeight; // if (ldVCon > ldImg) // { // if (gpSet->bgOperation == eFit) // lMaxBgWidth = lMaxBgHeight * ldImg; // else // lMaxBgHeight = lMaxBgWidth / ldImg; // } // else // { // if (gpSet->bgOperation == eFill) // lMaxBgWidth = lMaxBgHeight * ldImg; // else // lMaxBgHeight = lMaxBgWidth / ldImg; // } //} if (!CreateField(lMaxBgWidth, lMaxBgHeight) || !FillBackground(pBgImgData, 0,0,lMaxBgWidth,lMaxBgHeight, op, mb_BgLastFade)) { bSucceeded = false; } } } else { bSucceeded = false; } } pBgFile->Release(); #endif } else { if (!mb_NeedBgUpdate) { if ((mb_BgLastFade == bIsForeground && gpSet->isFadeInactive) || (!gpSet->isFadeInactive && mb_BgLastFade)) { NeedBackgroundUpdate(); } } //if (mp_PluginBg == NULL) //{ // NeedBackgroundUpdate(); //} if (mb_NeedBgUpdate) { mb_NeedBgUpdate = false; lbForceUpdate = true; //if (!mp_PluginBg) // mp_PluginBg = new CBackground; mb_BgLastFade = (!bIsForeground && gpSet->isFadeInactive); TODO("Переделать, ориентироваться только на размер картинки - неправильно"); TODO("DoubleView - скорректировать X,Y"); if (lMaxBgWidth && lMaxBgHeight) { lBgWidth = lMaxBgWidth; lBgHeight = lMaxBgHeight; } if (!CreateField(lBgWidth, lBgHeight) || !PutPluginBackgroundImage(0,0, lBgWidth, lBgHeight)) { //delete mp_PluginBg; //mp_PluginBg = NULL; bSucceeded = false; } } // Check if the bitmap was prepared for the current Far state if ((mp_BkImgData && pVCon) // Don't use isFilePanel here because it is `false` when any dialog is active in Panels && ((!(pVCon->isEditor || pVCon->isViewer) && !(mp_BkImgData->dwDrawnPlaces & pbp_Panels)) || (pVCon->isEditor && !(mp_BkImgData->dwDrawnPlaces & pbp_Editor)) || (pVCon->isViewer && !(mp_BkImgData->dwDrawnPlaces & pbp_Viewer)) )) { lbForceUpdate = false; phBgDc = NULL; pbgBmpSize = MakeCoord(0, 0); goto wrap; } } if (bSucceeded) { phBgDc = hBgDc; pbgBmpSize = bgSize; } else { phBgDc = NULL; pbgBmpSize = MakeCoord(0,0); } wrap: return lbForceUpdate; }