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