diff --git a/sakura_core/doc/layout/CLayoutMgr.cpp b/sakura_core/doc/layout/CLayoutMgr.cpp index fcbc59c600..dc09c52a1e 100644 --- a/sakura_core/doc/layout/CLayoutMgr.cpp +++ b/sakura_core/doc/layout/CLayoutMgr.cpp @@ -873,8 +873,6 @@ void CLayoutMgr::LogicToLayout( else{ nCharKetas = GetLayoutXOfChar( pData, nDataLen, i ); } -// if( nCharKetas == 0 ) // 削除 サロゲートペア対策 2008/7/5 Uchi -// nCharKetas = CLayoutInt(1); //レイアウト加算 nCaretPosX += nCharKetas; @@ -1007,8 +1005,6 @@ checkloop:; else{ nCharKetas = GetLayoutXOfChar( pData, nDataLen, i ); } -// if( nCharKetas == 0 ) // 削除 サロゲートペア対策 2008/7/5 Uchi -// nCharKetas = CLayoutInt(1); //レイアウト加算 if( nX + nCharKetas > ptLayout.GetX2() && !bEOF ){ diff --git a/sakura_core/doc/layout/CLayoutMgr_DoLayout.cpp b/sakura_core/doc/layout/CLayoutMgr_DoLayout.cpp index 2de5300a63..10973b8f5d 100644 --- a/sakura_core/doc/layout/CLayoutMgr_DoLayout.cpp +++ b/sakura_core/doc/layout/CLayoutMgr_DoLayout.cpp @@ -49,12 +49,12 @@ static bool _GetKeywordLength( CLogicInt nWordLen = CLogicInt(0); CLayoutInt nWordKetas = CLayoutInt(0); while(nPos0){ @@ -188,7 +188,7 @@ void CLayoutMgr::_DoKutoBurasage(SLayoutWork* pWork) const if( _IsKinsokuPosKuto( GetMaxLineLayout() - pWork->nPosX, nCharKetas ) && IsKinsokuKuto( pWork->cLineStr.At( pWork->nPos ) ) ) { pWork->nWordBgn = pWork->nPos; - pWork->nWordLen = 1; + pWork->nWordLen = CNativeW::GetSizeOfChar( pWork->cLineStr, pWork->nPos ); pWork->eKinsokuType = KINSOKU_TYPE_KINSOKU_KUTO; } } @@ -203,24 +203,17 @@ void CLayoutMgr::_DoGyotoKinsoku(SLayoutWork* pWork, PF_OnLine pfOnLine) && (pWork->eKinsokuType == KINSOKU_TYPE_NONE) ) { // 2007.09.07 kobake レイアウトとロジックの区別 - CLayoutInt nCharKetas2 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos ); - CLayoutInt nCharKetas3 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos+1 ); - bool bLowSurrogate = false; + CLogicXInt nCharSize = CNativeW::GetSizeOfChar( pWork->cLineStr, pWork->nPos ); + CLayoutXInt nCharKetas1 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos ); + CLayoutXInt nCharKetas2 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos + nCharSize ); - if( nCharKetas3 == 0 && pWork->nPos + 2 < pWork->cLineStr.GetLength() ) - { - // サロゲートペア対策(取得した文字幅が0だったら下位側を読み取ったと判断し、次の位置に進ませる) - bLowSurrogate = true; - nCharKetas3 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos + 2 ); - } - - if( _IsKinsokuPosHead( GetMaxLineLayout() - pWork->nPosX, nCharKetas2, nCharKetas3 ) - && IsKinsokuHead( pWork->cLineStr.At( pWork->nPos + ( bLowSurrogate ? 2 : 1 ) ) ) + if( _IsKinsokuPosHead( GetMaxLineLayout() - pWork->nPosX, nCharKetas1, nCharKetas2 ) + && IsKinsokuHead( pWork->cLineStr.At( pWork->nPos + nCharSize ) ) && !IsKinsokuHead( pWork->cLineStr.At( pWork->nPos ) ) // 1字前が行頭禁則の対象でないこと && !IsKinsokuKuto( pWork->cLineStr.At( pWork->nPos ) ) ) // 1字前が句読点ぶら下げの対象でないこと { pWork->nWordBgn = pWork->nPos; - pWork->nWordLen = ( bLowSurrogate ? 3 : 2 ); + pWork->nWordLen = nCharSize + CNativeW::GetSizeOfChar( pWork->cLineStr, pWork->nPos + nCharSize ); pWork->eKinsokuType = KINSOKU_TYPE_KINSOKU_HEAD; (this->*pfOnLine)(pWork); @@ -236,13 +229,14 @@ void CLayoutMgr::_DoGyomatsuKinsoku(SLayoutWork* pWork, PF_OnLine pfOnLine) && ( pWork->nPosX > pWork->nIndent ) // 2004.04.09 pWork->nPosXの解釈変更のため,行頭チェックも変更 && (pWork->eKinsokuType == KINSOKU_TYPE_NONE) ) { - CLayoutInt nCharKetas2 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos ); - CLayoutInt nCharKetas3 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos+1 ); + CLogicXInt nCharSize = CNativeW::GetSizeOfChar( pWork->cLineStr, pWork->nPos ); + CLayoutXInt nCharKetas1 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos ); + CLayoutXInt nCharKetas2 = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos + nCharSize ); - if( _IsKinsokuPosTail( GetMaxLineLayout() - pWork->nPosX, nCharKetas2, nCharKetas3 ) && IsKinsokuTail( pWork->cLineStr.At( pWork->nPos ) ) ) + if( _IsKinsokuPosTail( GetMaxLineLayout() - pWork->nPosX, nCharKetas1, nCharKetas2 ) && IsKinsokuTail( pWork->cLineStr.At( pWork->nPos ) ) ) { pWork->nWordBgn = pWork->nPos; - pWork->nWordLen = 1; + pWork->nWordLen = nCharSize; pWork->eKinsokuType = KINSOKU_TYPE_KINSOKU_TAIL; (this->*pfOnLine)(pWork); @@ -260,7 +254,7 @@ bool CLayoutMgr::_DoTab(SLayoutWork* pWork, PF_OnLine pfOnLine) return true; } pWork->nPosX += nCharKetas; - pWork->nPos += CLogicInt(1); + pWork->nPos += CNativeW::GetSizeOfChar( pWork->cLineStr, pWork->nPos ); return false; } @@ -322,9 +316,6 @@ void CLayoutMgr::_MakeOneLine(SLayoutWork* pWork, PF_OnLine pfOnLine) } // 2007.09.07 kobake ロジック幅とレイアウト幅を区別 CLayoutInt nCharKetas = GetLayoutXOfChar( pWork->cLineStr, pWork->nPos ); -// if( 0 == nCharKetas ){ // 削除 サロゲートペア対策 2008/7/5 Uchi -// nCharKetas = CLayoutInt(1); -// } if( pWork->nPosX + nCharKetas > GetMaxLineLayout() ){ if( pWork->eKinsokuType != KINSOKU_TYPE_KINSOKU_KUTO ) @@ -336,7 +327,7 @@ void CLayoutMgr::_MakeOneLine(SLayoutWork* pWork, PF_OnLine pfOnLine) } } } - pWork->nPos += 1; + pWork->nPos += CNativeW::GetSizeOfChar( pWork->cLineStr, pWork->nPos ); pWork->nPosX += nCharKetas; } } diff --git a/sakura_core/mem/CMemoryIterator.h b/sakura_core/mem/CMemoryIterator.h index 6f41e873a9..ef985b32b7 100644 --- a/sakura_core/mem/CMemoryIterator.h +++ b/sakura_core/mem/CMemoryIterator.h @@ -110,8 +110,6 @@ class CMemoryIterator if( m_nSpacing ){ m_nColumn_Delta += CLayoutXInt(CNativeW::GetKetaOfChar(m_pLine, m_nLineLen, m_nIndex) * m_nSpacing); } -// if( 0 == m_nColumn_Delta ) // 削除 サロゲートペア対策 2008/7/5 Uchi -// m_nColumn_Delta = CLayoutInt(1); } } diff --git a/sakura_core/mem/CNativeW.h b/sakura_core/mem/CNativeW.h index e96cb59bf4..a3b2ee3cc5 100644 --- a/sakura_core/mem/CNativeW.h +++ b/sakura_core/mem/CNativeW.h @@ -153,19 +153,20 @@ class CNativeW final : public CNative{ public: // -- -- staticインターフェース -- -- // - static CLogicInt GetSizeOfChar( const wchar_t* pData, int nDataLen, int nIdx ); //!< 指定した位置の文字がwchar_t何個分かを返す - static CHabaXInt GetHabaOfChar( const wchar_t* pData, int nDataLen, int nIdx, - bool bEnableExtEol, CCharWidthCache& cache = GetCharWidthCache() ); + //! 指定した位置の文字がwchar_t何個分かを返す + static CLogicInt GetSizeOfChar( const wchar_t* pData, int nDataLen, int nIdx ); + static CLogicInt GetSizeOfChar( const CStringRef& cStr, int nIdx ) + { return GetSizeOfChar( cStr.GetPtr(), cStr.GetLength(), nIdx ); } //! 指定した位置の文字が半角何個分かを返す static CKetaXInt GetKetaOfChar( const wchar_t* pData, int nDataLen, int nIdx, CCharWidthCache& cache = GetCharWidthCache() ); + static CKetaXInt GetKetaOfChar(const CStringRef& cStr, int nIdx, CCharWidthCache& cache = GetCharWidthCache()) + { return GetKetaOfChar(cStr.GetPtr(), cStr.GetLength(), nIdx, cache); } static const wchar_t* GetCharNext( const wchar_t* pData, int nDataLen, const wchar_t* pDataCurrent ); //!< ポインタで示した文字の次にある文字の位置を返します static const wchar_t* GetCharPrev(const wchar_t* pData, size_t nDataLen, const wchar_t* pDataCurrent); //!< ポインタで示した文字の直前にある文字の位置を返します - static CKetaXInt GetKetaOfChar( const CStringRef& cStr, int nIdx ) //!< 指定した位置の文字が半角何個分かを返す - { - return GetKetaOfChar(cStr.GetPtr(), cStr.GetLength(), nIdx); - } + static CHabaXInt GetHabaOfChar( const wchar_t* pData, int nDataLen, int nIdx, + bool bEnableExtEol, CCharWidthCache& cache = GetCharWidthCache() ); static CLayoutXInt GetColmOfChar( const wchar_t* pData, int nDataLen, int nIdx, bool bEnableExtEol ) { return GetHabaOfChar(pData,nDataLen,nIdx, bEnableExtEol); } diff --git a/tests/unittests/test-cnative.cpp b/tests/unittests/test-cnative.cpp index 5982fc2ff5..6a795fd4f2 100644 --- a/tests/unittests/test-cnative.cpp +++ b/tests/unittests/test-cnative.cpp @@ -788,12 +788,16 @@ TEST(CNativeW, GetSizeOfChar) { // 基本多言語面の文字ならば1を返す。 EXPECT_EQ(CNativeW::GetSizeOfChar(L"a", 1, 0), 1); + EXPECT_EQ(CNativeW::GetSizeOfChar(CStringRef(L"a", 1), 0), 1); // 範囲外なら0を返す。 EXPECT_EQ(CNativeW::GetSizeOfChar(L"", 0, 0), 0); + EXPECT_EQ(CNativeW::GetSizeOfChar(CStringRef(L"", 0), 0), 0); // 上位・下位サロゲートの組み合わせであれば2を返す。 EXPECT_EQ(CNativeW::GetSizeOfChar(L"\xd83c\xdf38", 2, 0), 2); + EXPECT_EQ(CNativeW::GetSizeOfChar(CStringRef(L"\xd83c\xdf38", 2), 0), 2); // 指定位置が下位サロゲートならその他の文字と同様に1を返す。 EXPECT_EQ(CNativeW::GetSizeOfChar(L"\xd83c\xdf38", 2, 1), 1); + EXPECT_EQ(CNativeW::GetSizeOfChar(CStringRef(L"\xd83c\xdf38", 2), 1), 1); } /*! @@ -804,12 +808,16 @@ TEST(CNativeW, GetKetaOfChar) { // 範囲外なら0を返す。 EXPECT_EQ(CNativeW::GetKetaOfChar(L"", 0, 0), 0); + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(L"", 0), 0), 0); // 上位サロゲートなら2を返す。 EXPECT_EQ(CNativeW::GetKetaOfChar(L"\xd83c\xdf38", 2, 0), 2); + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(L"\xd83c\xdf38", 2), 0), 2); // 上位サロゲートに続く下位サロゲートであれば0を返す。 EXPECT_EQ(CNativeW::GetKetaOfChar(L"\xd83c\xdf38", 2, 1), 0); + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(L"\xd83c\xdf38", 2), 1), 0); // 下位サロゲートだけなら2を返す。 EXPECT_EQ(CNativeW::GetKetaOfChar(L"\xdf38", 1, 0), 2); + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(L"\xdf38", 1), 0), 2); // サクラエディタでは Unicode で表現できない文字コードの破壊を防ぐため、 // 不明バイトを下位サロゲートにマップして保持している。 @@ -819,12 +827,17 @@ TEST(CNativeW, GetKetaOfChar) // https://sourceforge.net/p/sakura-editor/patchunicode/57/ // http://sakura-editor.sourceforge.net/cgi-bin/cyclamen/cyclamen.cgi?log=unicode&v=833 EXPECT_EQ(CNativeW::GetKetaOfChar(L"\xdbff", 1, 0), 2); - for (wchar_t ch = 0xdc00; ch <= 0xdcff; ++ch) + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(L"\xdbff", 1), 0), 2); + for (wchar_t ch = 0xdc00; ch <= 0xdcff; ++ch) { EXPECT_EQ(CNativeW::GetKetaOfChar(&ch, 1, 0), 1); + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(&ch, 1), 0), 1); + } EXPECT_EQ(CNativeW::GetKetaOfChar(L"\xdd00", 1, 0), 2); + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(L"\xdd00", 1), 0), 2); // 文字が半角なら1を返す。 EXPECT_EQ(CNativeW::GetKetaOfChar(L"a", 1, 0), 1); + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(L"a", 1), 0), 1); // 文字が全角なら2を返す。 class FakeCache : public CCharWidthCache { @@ -832,6 +845,7 @@ TEST(CNativeW, GetKetaOfChar) bool CalcHankakuByFont(wchar_t c) override { return false; } } cache; EXPECT_EQ(CNativeW::GetKetaOfChar(L"あ", 1, 0, cache), 2); + EXPECT_EQ(CNativeW::GetKetaOfChar(CStringRef(L"あ", 1), 0, cache), 2); } /*!