コード例 #1
0
ファイル: hkConsoleInput.cpp プロジェクト: 2asoft/ConEmu
// 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;
}
コード例 #2
0
ファイル: Background.cpp プロジェクト: ForNeVeR/ConEmu
bool CBackground::CreateField(int anWidth, int anHeight)
{
	if (!hBgDc || !hBgBitmap || anWidth != bgSize.X || anHeight != bgSize.Y)
	{
		Destroy();
	}
	else
	{
		return true; // уже создано
	}

	bool lbRc = false;
	// Создать MemoryDC
	const HDC hScreenDC = GetDC(ghWnd);
	hBgDc = CreateCompatibleDC(hScreenDC);

	if (hBgDc)
	{
		bgSize.X = klMin(32767,anWidth);
		bgSize.Y = klMin(32767,anHeight);
		hBgBitmap = CreateCompatibleBitmap(hScreenDC, bgSize.X, bgSize.Y);

		if (hBgBitmap)
		{
			// Выбрать в MemoryDC созданный Bitmap для установки его размера
			hOldBitmap = (HBITMAP)SelectObject(hBgDc, hBgBitmap);
			// И залить черным фоном
			RECT rcFull = MakeRect(bgSize.X, bgSize.Y);
			FillRect(hBgDc, &rcFull, (HBRUSH)GetStockObject(BLACK_BRUSH));
			// теперь - OK
			lbRc = true;
		}
	}

	ReleaseDC(ghWnd, hScreenDC);
	return lbRc;
}
コード例 #3
0
ファイル: Background.cpp プロジェクト: ForNeVeR/ConEmu
bool CBackground::FillBackground(
	const BITMAPFILEHEADER* apBkImgData, // Содержимое *.bmp файла
	LONG X, LONG Y, LONG Width, LONG Height, // Куда нужно положить картинку
	BackgroundOp Operation,              // {eUpLeft = 0, eStretch = 1, eTile = 2, eUpRight = 4, ...}
	bool abFade)                         // затемнение картинки, когда ConEmu НЕ в фокусе
{
	if (!hBgDc)
		return false;

	// Залить черным фоном
	RECT rcFull = MakeRect(X,Y,Width,Height);
	FillRect(hBgDc, &rcFull, (HBRUSH)GetStockObject(BLACK_BRUSH));

	if (apBkImgData == NULL ||
	        apBkImgData->bfType != 0x4D42/*BM*/ ||
	        IsBadReadPtr(apBkImgData, apBkImgData->bfSize))
	{
		return false;
	}

	bool lbRc = false;
	HDC         hLoadDC = NULL;
	HBITMAP     hLoadBmp = NULL;
	BITMAPINFO* pBmp  = (BITMAPINFO*)(apBkImgData+1);
	LPBYTE      pBits = ((LPBYTE)apBkImgData) + apBkImgData->bfOffBits;
	LPVOID      pDstBits = NULL;
	BITMAPINFOHEADER* pHdr = &pBmp->bmiHeader;

	if (pHdr->biPlanes != 1 || pHdr->biCompression != BI_RGB)  // BI_JPEG|BI_PNG
	{
		return false;
	}

	DWORD       nBitSize = apBkImgData->bfSize - apBkImgData->bfOffBits;
	TODO("Stride?");
	DWORD       nCalcSize = (pHdr->biWidth * pHdr->biHeight * pHdr->biBitCount) >> 3;

	if (nBitSize > nCalcSize)
		nBitSize = nCalcSize;

	if (!gpSet->isFadeInactive)
		abFade = false;

	// Создать MemoryDC
	const HDC hScreenDC = GetDC(ghWnd);

	if (hScreenDC)
	{
		hLoadDC = CreateCompatibleDC(hScreenDC);
		ReleaseDC(ghWnd, hScreenDC);

		if (hLoadDC)
		{
			hLoadBmp = CreateDIBSection(hLoadDC, pBmp, DIB_RGB_COLORS, &pDstBits, NULL, 0);

			if (hLoadBmp && pDstBits)
			{
				// Поместить биты из apBkImgData в hLoadDC
				HBITMAP hOldLoadBmp = (HBITMAP)SelectObject(hLoadDC, hLoadBmp);
				memmove(pDstBits, pBits, nBitSize);
				GdiFlush(); // Гарантировать commit битов
				// Теперь - скопировать биты из hLoadDC в hBgDc с учетом положения и Operation
				BLENDFUNCTION bf = {AC_SRC_OVER, 0, gpSet->bgImageDarker, 0};

				if (abFade)
				{
					// GetFadeColor возвращает ColorRef, поэтому при вызове для (0..255)
					// он должен вернуть "коэффициент" затемнения или осветления
					DWORD nHigh = (gpSet->GetFadeColor(255) & 0xFF);

					if (nHigh < 255)
					{
						// Затемнение фона
						bf.SourceConstantAlpha = LOBYTE(nHigh * bf.SourceConstantAlpha / 255);
					}

					//// "коэффициент" вернется в виде RGB (R==G==B)
					//DWORD nLow = gpSet->GetFadeColor(0);
					//if (nLow > 0 && ((nLow & 0xFF) < nHigh))
					//{
					//	// Осветление фона
					//	RECT r = {X,Y,X+Width,Y+Height};
					//	HBRUSH h = CreateSolidBrush(nLow);
					//	FillRect(hBgDc, &r, h);
					//	DeleteObject(h);
					//	// еще нужно убедиться, что сама картинка будет немного прозрачной,
					//	// чтобы это осветление было заметно
					//	if ((nLow & 0xFF) < 200)
					//		bf.SourceConstantAlpha = klMin((int)bf.SourceConstantAlpha, (int)(255 - (nLow & 0xFF)));
					//	else if (bf.SourceConstantAlpha >= 240)
					//		bf.SourceConstantAlpha = 240;
					//}
				}

				if ((Operation == eUpLeft) || (Operation == eUpRight)
					|| (Operation == eDownLeft) || (Operation == eDownRight)
					|| (Operation == eCenter))
				{
					int W = klMin(Width,pHdr->biWidth); int H = klMin(Height,pHdr->biHeight);

					if (GdiAlphaBlend(hBgDc, X, Y, W, H, hLoadDC, 0, 0, W, H, bf))
						lbRc = true;
				}
				else if (Operation == eStretch || Operation == eFit)
				{
					if (GdiAlphaBlend(hBgDc, X, Y, Width, Height, hLoadDC, 0, 0, pHdr->biWidth, pHdr->biHeight, bf))
						lbRc = true;
				}
				else if (Operation == eFill)
				{
					int srcX = 0, srcY = 0, srcW = pHdr->biWidth, srcH = pHdr->biHeight;
					if (Width && Width > Height)
					{
						srcH = klMin((srcW * Height / Width), _abs(pHdr->biHeight));
						srcY = (pHdr->biHeight - srcH) / 2;
					}
					else if (Height)
					{
						srcW = klMin((srcH * Width / Height), pHdr->biWidth);
						srcX = (pHdr->biWidth - srcW) / 2;
					}

					if (GdiAlphaBlend(hBgDc, X, Y, Width, Height, hLoadDC, srcX, srcY, srcW, srcH, bf))
						lbRc = true;
				}
				else if (Operation == eTile)
				{
					for (int DY = Y; DY < (Y+Height); DY += pHdr->biHeight)
					{
						for (int DX = X; DX < (X+Width); DX += pHdr->biWidth)
						{
							int W = klMin((Width-DX),pHdr->biWidth);
							int H = klMin((Height-DY),pHdr->biHeight);

							if (GdiAlphaBlend(hBgDc, DX, DY, W, H, hLoadDC, 0, 0, W, H, bf))
								lbRc = true;
						}
					}
				}

				_ASSERTE(lbRc && "GdiAlphaBlend failed in background creation?");

				TODO("Осветление картинки в Fade, когда gpSet->mn_FadeLow>0");
				//if (abFade)
				//{
				//	// "коэффициент" вернется в виде RGB (R==G==B)
				//	DWORD nLow = gpSet->GetFadeColor(0);
				//	if (nLow)
				//	{
				//		// Осветление фона
				//		RECT r = {X,Y,X+Width,Y+Height};
				//		HBRUSH h = CreateSolidBrush(nLow);
				//		// Осветлить картинку
				//		//FillRect(hBgDc, &r, h);
				//		DeleteObject(h);
				//	}
				//}
				SelectObject(hLoadDC, hOldLoadBmp);
			}

			if (hLoadBmp)
			{
				DeleteObject(hLoadBmp);
				hLoadBmp = NULL;
			}

			DeleteDC(hLoadDC);
			hLoadDC = NULL;
		}
	}

	return lbRc;
}
コード例 #4
0
ファイル: RConData.cpp プロジェクト: 2asoft/ConEmu
// returns count of *lines* were copied to pChar/pAttr
// nWidth & nHeight - dimension which VCon want to display
UINT CRConData::GetConsoleData(wchar_t* rpChar, CharAttr* rpAttr, UINT anWidth, UINT anHeight,
	wchar_t wSetChar, CharAttr lcaDef, CharAttr *lcaTable, CharAttr *lcaTableExt,
	bool bFade, bool bExtendColors, BYTE nExtendColorIdx, bool bExtendFonts)
{
	TODO("Во время ресайза консоль может подглючивать - отдает не то что нужно...");
	//_ASSERTE(*con.pConChar!=ucBoxDblVert);
	UINT nYMax = klMin(anHeight,nHeight);

	MFileMapping<AnnotationHeader>& TrueMap = mp_RCon->m_TrueColorerMap;
	const AnnotationInfo *pTrueData = mp_RCon->mp_TrueColorerData;

	wchar_t  *pszDst = rpChar;
	CharAttr *pcaDst = rpAttr;

	wchar_t  *pszSrc = pConChar;
	WORD     *pnSrc = pConAttr;

	bool lbIsFar = mp_RCon->isFar();

	// Т.к. есть блокировка (csData), то con.pConChar и con.pConAttr
	// не должны меняться во время выполнения этой функции
	const wchar_t* const pszSrcStart = pConChar;
	WORD* const pnSrcStart = pConAttr;
	size_t nSrcCells = (nWidth * nHeight);

	Assert(pszSrcStart==pszSrc && pnSrcStart==pnSrc);

	const AnnotationInfo *pcolSrc = NULL;
	const AnnotationInfo *pcolEnd = NULL;
	BOOL bUseColorData = FALSE, bStartUseColorData = FALSE;

	if (gpSet->isTrueColorer && TrueMap.IsValid() && pTrueData)
	{
		pcolSrc = pTrueData;
		pcolEnd = pTrueData + TrueMap.Ptr()->bufferSize;
		bUseColorData = TRUE;
		WARNING("Если far/w - pcolSrc нужно поднять вверх, bStartUseColorData=TRUE, bUseColorData=FALSE");
		if (m_sbi.dwSize.Y > (int)nHeight) // con.bBufferHeight
		{
			int lnShiftRows = (m_sbi.dwSize.Y - anHeight) - m_sbi.srWindow.Top;

			if (lnShiftRows > 0)
			{
				#ifdef _DEBUG
				if (nWidth != (m_sbi.srWindow.Right - m_sbi.srWindow.Left + 1))
				{
					_ASSERTE(nWidth == (m_sbi.srWindow.Right - m_sbi.srWindow.Left + 1));
				}
				#endif

				pcolSrc -= (lnShiftRows * nWidth);
				DEBUGSTRTRUEMOD(L"TrueMod skipped due to nShiftRows, bStartUseColorData was set");
				bUseColorData = FALSE;
				bStartUseColorData = TRUE;
			}
			#ifdef _DEBUG
			else if (lnShiftRows < 0)
			{
				//_ASSERTE(nShiftRows>=0);
				wchar_t szLog[200];
				_wsprintf(szLog, SKIPCOUNT(szLog) L"!!! CRealBuffer::GetConsoleData !!! "
					L"nShiftRows=%i nWidth=%i nHeight=%i Rect={%i,%i}-{%i,%i} Buf={%i,%i}",
					lnShiftRows, anWidth, anHeight,
					m_sbi.srWindow.Left, m_sbi.srWindow.Top, m_sbi.srWindow.Right, m_sbi.srWindow.Bottom,
					m_sbi.dwSize.X, m_sbi.dwSize.Y);
				mp_RCon->LogString(szLog);
			}
			#endif
		}
	}
	else
	{
		DEBUGSTRTRUEMOD(L"TrueMod is not allowed here");
	}

	DWORD cbDstLineSize = anWidth * 2;
	DWORD cnSrcLineLen = nWidth;
	DWORD cbSrcLineSize = cnSrcLineLen * 2;

	#ifdef _DEBUG
	if (nWidth != m_sbi.dwSize.X)
	{
		_ASSERTE(nWidth == m_sbi.dwSize.X); // Scrolling?
	}
	#endif

	DWORD cbLineSize = min(cbDstLineSize,cbSrcLineSize);
	int nCharsLeft = (anWidth > nWidth) ? (anWidth - nWidth) : 0;
	//int nY, nX;
	//120331 - Нехорошо заменять на "черный" с самого начала
	BYTE attrBackLast = 0;
	UINT nExtendStartsY = 0;
	//int nPrevDlgBorder = -1;

	bool lbStoreBackLast = false;
	if (bExtendColors)
	{
		BYTE FirstBackAttr = lcaTable[(*pnSrc) & 0xFF].nBackIdx;
		if (FirstBackAttr != nExtendColorIdx)
			attrBackLast = FirstBackAttr;

		const CEFAR_INFO_MAPPING* pFarInfo = lbIsFar ? mp_RCon->GetFarInfo() : NULL;
		if (pFarInfo)
		{
			// Если в качестве цвета "расширения" выбран цвет панелей - значит
			// пользователь просто настроил "другую" палитру для панелей фара.
			// К сожалению, таким образом нельзя заменить только цвета для элемента под курсором.
			if (CONBACKCOLOR(pFarInfo->nFarColors[col_PanelText]) != nExtendColorIdx)
				lbStoreBackLast = true;
			else
				attrBackLast = FirstBackAttr;

			if (pFarInfo->FarInterfaceSettings.AlwaysShowMenuBar || mp_RCon->isEditor() || mp_RCon->isViewer())
				nExtendStartsY = 1; // пропустить обработку строки меню
		}
		else
		{
			lbStoreBackLast = true;
		}
	}

	// Собственно данные
	for (UINT nY = 0; nY < nYMax; nY++)
	{
		if (nY == nExtendStartsY)
			lcaTable = lcaTableExt;

		// Текст
		memmove(pszDst, pszSrc, cbLineSize);

		if (nCharsLeft > 0)
			wmemset(pszDst+cnSrcLineLen, wSetChar, nCharsLeft);

		// Console text colors (Fg,Bg)
		BYTE PalIndex = MAKECONCOLOR(7,0);

		// While console is in recreate (shutdown console, startup new root)
		// it's shown using monochrome (gray on black)
		bool bForceMono = (mp_RCon->mn_InRecreate != 0);

		int iTail = cnSrcLineLen;
		wchar_t* pch = pszDst;
		for (UINT nX = 0;
			// Don't forget to advance same pointers at the and if bPair
			iTail-- > 0; nX++, pnSrc++, pcolSrc++, pch++)
		{
			CharAttr& lca = pcaDst[nX];
			bool hasTrueColor = false;
			bool hasFont = false;

			// If not "mono" we need only lower byte with color indexes
			if (!bForceMono)
			{
				if (((*pnSrc) & COMMON_LVB_REVERSE_VIDEO) && (((*pnSrc) & CHANGED_CONATTR) == COMMON_LVB_REVERSE_VIDEO))
					PalIndex = MAKECONCOLOR(CONBACKCOLOR(*pnSrc), CONFORECOLOR(*pnSrc)); // Inverse
				else
					PalIndex = ((*pnSrc) & 0xFF);
			}
			TODO("OPTIMIZE: lca = lcaTable[PalIndex];");
			lca = lcaTable[PalIndex];
			TODO("OPTIMIZE: вынести проверку bExtendColors за циклы");

			bool bPair = (iTail > 0);
			ucs32 wwch = ucs32_from_wchar(pch, bPair);
			_ASSERTE(wwch >= 0);

			// Colorer & Far - TrueMod
			TODO("OPTIMIZE: вынести проверку bUseColorData за циклы");

			if (bStartUseColorData && !bUseColorData)
			{
				// В случае "far /w" буфер цвета может начаться НИЖЕ верхней видимой границы,
				// если буфер немного прокручен вверх
				if (pcolSrc >= mp_RCon->mp_TrueColorerData)
				{
					DEBUGSTRTRUEMOD(L"TrueMod forced back due bStartUseColorData");
					bUseColorData = TRUE;
				}
			}

			if (bUseColorData)
			{
				if (pcolSrc >= pcolEnd)
				{
					DEBUGSTRTRUEMOD(L"TrueMod stopped - out of buffer");
					bUseColorData = FALSE;
				}
				else
				{
					TODO("OPTIMIZE: доступ к битовым полям тяжело идет...");

					if (pcolSrc->fg_valid)
					{
						hasTrueColor = true;
						hasFont = true;
						lca.nFontIndex = fnt_Normal; //bold/italic/underline will be set below
						lca.crForeColor = bFade ? gpSet->GetFadeColor(pcolSrc->fg_color) : pcolSrc->fg_color;

						if (pcolSrc->bk_valid)
							lca.crBackColor = bFade ? gpSet->GetFadeColor(pcolSrc->bk_color) : pcolSrc->bk_color;
					}
					else if (pcolSrc->bk_valid)
					{
						hasTrueColor = true;
						hasFont = true;
						lca.nFontIndex = fnt_Normal; //bold/italic/underline will be set below
						lca.crBackColor = bFade ? gpSet->GetFadeColor(pcolSrc->bk_color) : pcolSrc->bk_color;
					}

					// nFontIndex: 0 - normal, 1 - bold, 2 - italic, 3 - bold&italic,..., 4 - underline, ...
					if (pcolSrc->style)
					{
						hasFont = true;
						lca.nFontIndex = pcolSrc->style & fnt_StdFontMask;
					}
				}
			}

			if (!hasFont
				&& ((*pnSrc) & COMMON_LVB_UNDERSCORE)
				&& ((nX >= ROWID_USED_CELLS) || !((*pnSrc) & (CHANGED_CONATTR & ~COMMON_LVB_UNDERSCORE)))
				)
			{
				lca.nFontIndex = fnt_Underline;
			}

			if (!hasTrueColor && bExtendColors && (nY >= nExtendStartsY))
			{
				if (lca.nBackIdx == nExtendColorIdx)
				{
					// Have to change the color to adjacent(?) cell
					lca.nBackIdx = attrBackLast;
					// For the background nExtendColorIdx we use upper
					// palette range for text: 16..31 instead of 0..15
					lca.nForeIdx += 0x10;
					lca.crForeColor = lca.crOrigForeColor = mp_RCon->mp_Palette->m_Colors[lca.nForeIdx];
					lca.crBackColor = lca.crOrigBackColor = mp_RCon->mp_Palette->m_Colors[lca.nBackIdx];
				}
				else if (lbStoreBackLast)
				{
					// Remember last "normal" background
					attrBackLast = lca.nBackIdx;
				}
			}

			switch (get_wcwidth(wwch))
			{
			case 0:
				lca.Flags2 |= CharAttr2_Combining;
				break;
			case 2:
				lca.Flags2 |= CharAttr2_DoubleSpaced;
				break;
			}

			if (bPair)
			{
				lca.Flags2 |= CharAttr2_Surrogate;
				CharAttr& lca2 = pcaDst[nX+1];
				lca2 = lca;
				lca2.Flags2 = (lca.Flags2 & ~(CharAttr2_Combining)) | CharAttr2_NonSpacing;
				// advance +1 character
				nX++; pnSrc++; pcolSrc++; pch++; iTail--;
			}
		}

		// Залить остаток (если запрошен больший участок, чем есть консоль
		for (UINT nX = cnSrcLineLen; nX < anWidth; nX++)
		{
			pcaDst[nX] = lcaDef;
		}

		// Far2 показывает красный 'A' в правом нижнем углу консоли
		// Этот ярко красный цвет фона может попасть в Extend Font Colors
		if (bExtendFonts && ((nY+1) == nYMax) && lbIsFar
			&& (pszDst[anWidth-1] == L'A') && (PalIndex == 0xCF))
		{
			// Вернуть "родной" цвет и шрифт
			pcaDst[anWidth-1] = lcaTable[PalIndex];
		}

		// Next line
		pszDst += anWidth;
		pcaDst += anWidth;
		pszSrc += cnSrcLineLen;
	}

	#ifndef __GNUC__
	UNREFERENCED_PARAMETER(pszSrcStart);
	UNREFERENCED_PARAMETER(pnSrcStart);
	#endif
	UNREFERENCED_PARAMETER(nSrcCells);

	return nYMax;
}