Example #1
0
// 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;
}
Example #2
0
// 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 bExtendFonts)
{
	TODO("Во время ресайза консоль может подглючивать - отдает не то что нужно...");
	//_ASSERTE(*con.pConChar!=ucBoxDblVert);
	UINT nYMax = std::min(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];
				swprintf_c(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 = std::min(cbDstLineSize,cbSrcLineSize);
	int nCharsLeft = (anWidth > nWidth) ? (anWidth - nWidth) : 0;
	//int nY, nX;
	UINT nExtendStartsY = 0;
	//int nPrevDlgBorder = -1;

	// Собственно данные
	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);

		bool has_rowid = (cnSrcLineLen >= ROWID_USED_CELLS) && (GetRowIdFromAttrs(pnSrc) != 0);
		if (!has_rowid && cnSrcLineLen >= ROWID_USED_CELLS) {
			_ASSERTE(!(pnSrc[0]&COMMON_LVB_REVERSE_VIDEO));
			_ASSERTE(!(pnSrc[1]&COMMON_LVB_REVERSE_VIDEO));
			_ASSERTE(!(pnSrc[2]&COMMON_LVB_REVERSE_VIDEO));
			_ASSERTE(!(pnSrc[3]&COMMON_LVB_REVERSE_VIDEO));
		}

		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;
			bool inversed = false;
			bool is_rowid = has_rowid && (nX < ROWID_USED_CELLS);

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

			lca.ConAttr = *pnSrc;

			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
				{
					if (pcolSrc->style & AI_STYLE_REVERSE)
						inversed = true;

					if (pcolSrc->fg_valid)
					{
						hasTrueColor = true;
						hasFont = true;
						lca.nFontIndex = fnt_Normal; //bold/italic/underline will be set below

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

					// 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 && !is_rowid && ((*pnSrc) & COMMON_LVB_UNDERSCORE))
			{
				lca.nFontIndex = fnt_Underline;
			}

			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;
}