⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clayoutmgr_new.cpp

📁 日本的开源编辑器源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//	$Id: CLayoutMgr_New.cpp,v 1.24 2004/08/18 14:03:05 genta Exp $
/*!	@file
	@brief テキストのレイアウト情報管理

	@author Norio Nakatani
	$Revision: 1.24 $
*/
/*
	Copyright (C) 1998-2001, Norio Nakatani
	Copyright (C) 2001, MIK
	Copyright (C) 2002, MIK
	Copyright (C) 2004, Moca

	This source code is designed for sakura editor.
	Please contact the copyright holder to use this code for other purpose.
*/

#include <mbstring.h>
#include "CLayoutMgr.h"
#include "charcode.h"
#include "etc_uty.h"
#include "debug.h"
#include <commctrl.h>
#include "CRunningTimer.h"
#include "CLayout.h"/// 2002/2/10 aroka
#include "CDocLine.h"/// 2002/2/10 aroka
#include "CDocLineMgr.h"// 2002/2/10 aroka
#include "CMemory.h"/// 2002/2/10 aroka
#include "CMemoryIterator.h"
#include "CEditDoc.h" /// 2003/07/20 genta

//レイアウト中の禁則タイプ	//@@@ 2002.04.20 MIK
#define	KINSOKU_TYPE_NONE			0	//なし
#define	KINSOKU_TYPE_WORDWRAP		1	//ワードラップ中
#define	KINSOKU_TYPE_KINSOKU_HEAD	2	//行頭禁則中
#define	KINSOKU_TYPE_KINSOKU_TAIL	3	//行末禁則中
#define	KINSOKU_TYPE_KINSOKU_KUTO	4	//句読点ぶら下げ中



/*!
	現在の折り返し文字数に合わせて全データのレイアウト情報を再生成します

	@date 2004.04.03 Moca TABが使われると折り返し位置がずれるのを防ぐため,
		nPosXがインデントを含む幅を保持するように変更.nMaxLineSizeは
		固定値となったが,既存コードの置き換えは避けて最初に値を代入するようにした.

*/
void CLayoutMgr::DoLayout(
		HWND	hwndProgress,
		BOOL	bDispSSTRING,	/* シングルクォーテーション文字列を表示する */
		BOOL	bDispWSTRING	/* ダブルクォーテーション文字列を表示する */
)
{
	MY_RUNNINGTIMER( cRunningTimer, "CLayoutMgr::DoLayout" );

	int			nLineNum;
	int			nLineLen;
	CDocLine*	pCDocLine;
	const char* pLine;
	int			nBgn;
	//!	メモリ上の位置(offset)
	int			nPos;
	/*	表示上のX位置
		2004.03.28 Moca nPosXはインデント幅を含むように変更(TAB位置調整のため)
	*/
	int			nPosX;
	int			nCharChars;
	int			nCharChars2;
	int			nCOMMENTMODE;
	int			nCOMMENTMODE_Prev;
	int			nCOMMENTEND;
	int			nWordBgn;
	int			nWordLen;
	int			nAllLineNum;
	bool		bKinsokuFlag;	//@@@ 2002.04.08 MIK
	int			nCharChars3;	//@@@ 2002.04.17 MIK
	int			nKinsokuType;	//@@@ 2002.04.20 MIK

	int			nIndent;			//	インデント幅
	CLayout*	pLayoutCalculated;	//	インデント幅計算済みのCLayout.
	int			nMaxLineSize;

// 2002/03/13 novice
	nCOMMENTMODE = COLORIDX_TEXT;
	nCOMMENTMODE_Prev = COLORIDX_TEXT;

	if( NULL != hwndProgress ){
		::PostMessage( hwndProgress, PBM_SETRANGE, 0, MAKELPARAM( 0, 100 ) );
		::PostMessage( hwndProgress, PBM_SETPOS, 0, 0 );
		/* 処理中のユーザー操作を可能にする */
		if( !::BlockingHook( NULL ) ){
			return;
		}
	}

	Empty();
	Init();
	nLineNum = 0;
	
	//	Nov. 16, 2002 genta
	//	折り返し幅 <= TAB幅のとき無限ループするのを避けるため,
	//	TABが折り返し幅以上の時はTAB=4としてしまう
	//	折り返し幅の最小値=10なのでこの値は問題ない
	if( m_nTabSpace >= m_nMaxLineSize ){
		m_nTabSpace = 4;
	}

//	pLine = m_pcDocLineMgr->GetFirstLinrStr( &nLineLen );
	pCDocLine = m_pcDocLineMgr->GetDocLineTop(); // 2002/2/10 aroka CDocLineMgr変更

// 2002/03/13 novice
	if( nCOMMENTMODE_Prev == COLORIDX_COMMENT ){	/* 行コメントである */
		nCOMMENTMODE_Prev = COLORIDX_TEXT;
	}
	nCOMMENTMODE = nCOMMENTMODE_Prev;
	nCOMMENTEND = 0;
	nAllLineNum = m_pcDocLineMgr->GetLineCount();

	/*
		2004.03.28 Moca TAB計算を正しくするためにインデントを幅で調整することはしない
		nMaxLineSizeは変更しないので,ここでm_nMaxLineSizeを設定する.
	*/
	nMaxLineSize = m_nMaxLineSize;

	while( NULL != pCDocLine ){
		pLine = pCDocLine->m_pLine->GetPtr( &nLineLen );
		nPosX = 0;
		nCharChars = 0;
		nBgn = 0;
		nPos = 0;
		nWordBgn = 0;
		nWordLen = 0;
		nKinsokuType = KINSOKU_TYPE_NONE;	//@@@ 2002.04.20 MIK

		int	nEol = pCDocLine->m_cEol.GetLen();
		int nEol_1 = nEol - 1;
		if( 0 >	nEol_1 ){
			nEol_1 = 0;
		}

		nIndent = 0;				//	インデント幅
		pLayoutCalculated = NULL;	//	インデント幅計算済みのCLayout.

		while( nPos < nLineLen - nEol_1 ){
			//	インデント幅の計算コストを下げるための方策
			if ( m_pLayoutBot && 
				 m_pLayoutBot != pLayoutCalculated &&
				 nBgn ){
				//	計算
				//	Oct, 1, 2002 genta Indentサイズを取得するように変更
				nIndent = (this->*getIndentOffset)( m_pLayoutBot );
				// 2004.03.28 Moca nMaxLineSizeを引く方法だと、タブ幅の計算が合わないので、nPosXの初期値をnIndentにする
				//	nMaxLineSize = m_nMaxLineSize - nIndent;
				
				//	計算済み
				pLayoutCalculated = m_pLayoutBot;
			}

			nCharChars = CMemory::MemCharNext( pLine, nLineLen, &pLine[nPos] ) - &pLine[nPos];
			if( 0 == nCharChars ){
				nCharChars = 1;
			}

			SEARCH_START:;
			
			//禁則処理中ならスキップする	@@@ 2002.04.20 MIK
			if( KINSOKU_TYPE_NONE != nKinsokuType )
			{
				//禁則処理の最後尾に達したら禁則処理中を解除する
				if( nPos >= nWordBgn + nWordLen )
				{
					if( nKinsokuType == KINSOKU_TYPE_KINSOKU_KUTO
					 && nPos == nWordBgn + nWordLen )
					{
						if( ! (m_bKinsokuRet && (nPos == nLineLen - nEol) && nEol ) )	//改行文字をぶら下げる		//@@@ 2002.04.14 MIK
						{
							AddLineBottom( CreateLayout(pCDocLine, nLineNum, nBgn, nPos - nBgn, nCOMMENTMODE_Prev, nIndent) );
							m_nLineTypeBot = nCOMMENTMODE;
							nCOMMENTMODE_Prev = nCOMMENTMODE;
							nBgn = nPos;
							// 2004.03.28 Moca nPosXはインデント幅を含むように変更(TAB位置調整のため)
							nPosX = nIndent = (this->*getIndentOffset)( m_pLayoutBot );
							pLayoutCalculated = m_pLayoutBot;
						}
					}
					
					nWordLen = 0;
					nKinsokuType = KINSOKU_TYPE_NONE;	//@@@ 2002.04.20 MIK
				}
			}
			else
			{
			
				/* ワードラップ処理 */
				if( m_bWordWrap	/* 英文ワードラップをする */
				 && nKinsokuType == KINSOKU_TYPE_NONE )
				{
//				if( 0 == nWordLen ){
					/* 英単語の先頭か */
					if( nPos >= nBgn &&
						nCharChars == 1 &&
//						( pLine[nPos] == '#' || __iscsym( pLine[nPos] ) )
						IS_KEYWORD_CHAR( pLine[nPos] )
					){
						/* キーワード文字列の終端を探す */
						int	i;
						for( i = nPos + 1; i <= nLineLen - 1; ){
							nCharChars2 = CMemory::MemCharNext( pLine, nLineLen, &pLine[i] ) - &pLine[i];
							if( 0 == nCharChars2 ){
								nCharChars2 = 1;
							}
							if( nCharChars2 == 1 &&
//								( pLine[i] == '#' || __iscsym( pLine[i] ) )
								IS_KEYWORD_CHAR( pLine[i] )
							){
							}else{
								break;
							}
							i += nCharChars2;
						}
						nWordBgn = nPos;
						nWordLen = i - nPos;
						nKinsokuType = KINSOKU_TYPE_WORDWRAP;	//@@@ 2002.04.20 MIK
						if( nPosX + i - nPos >= nMaxLineSize
						 && nPos - nBgn > 0
						){
							AddLineBottom( CreateLayout(pCDocLine, nLineNum, nBgn, nPos - nBgn, nCOMMENTMODE_Prev, nIndent) );
							m_nLineTypeBot = nCOMMENTMODE;
							nCOMMENTMODE_Prev = nCOMMENTMODE;
							nBgn = nPos;
							// 2004.03.28 Moca nPosXはインデント幅を含むように変更(TAB位置調整のため)
							nPosX = nIndent = (this->*getIndentOffset)( m_pLayoutBot );
							pLayoutCalculated = m_pLayoutBot;
//?							continue;
						}
					}
//				}else{
//					if( nPos == nWordBgn + nWordLen ){
//						nWordLen = 0;
//					}
//				}
				}

				//@@@ 2002.04.07 MIK start
				/* 句読点のぶらさげ */
				if( m_bKinsokuKuto
				 && (nMaxLineSize - nPosX < 2)
				 && (nKinsokuType == KINSOKU_TYPE_NONE) )
				{
					bKinsokuFlag = false;
					nCharChars2 = CMemory::MemCharNext( pLine, nLineLen, &pLine[nPos] ) - &pLine[nPos];
					switch( nMaxLineSize - nPosX )
					{
					case 1:	// 1文字前
						if( nCharChars2 == 2 )
						{
							bKinsokuFlag = true;
						}
						break;
					case 0:	// 
						if( nCharChars2 == 1 || nCharChars2 == 2 )
						{
							bKinsokuFlag = true;
						}
						break;
					}

					if( bKinsokuFlag && IsKinsokuKuto( &pLine[nPos], nCharChars2 ) )
					{
						//nPos += nCharChars2; nPosX += nCharChars2;
						nWordBgn = nPos;
						nWordLen = nCharChars2;
						nKinsokuType = KINSOKU_TYPE_KINSOKU_KUTO;
					}
				}

				/* 行頭禁則 */
				if( m_bKinsokuHead
				 && (nMaxLineSize - nPosX < 4)
				 && ( nPosX > nIndent )	//	2004.04.09 nPosXの解釈変更のため,行頭チェックも変更
				 && (nKinsokuType == KINSOKU_TYPE_NONE) )
				{
					bKinsokuFlag = false;
					nCharChars2 = CMemory::MemCharNext( pLine, nLineLen, &pLine[nPos] ) - &pLine[nPos];
					nCharChars3 = CMemory::MemCharNext( pLine, nLineLen, &pLine[nPos+nCharChars2] ) - &pLine[nPos+nCharChars2];
					switch( nMaxLineSize - nPosX )
					{
					//    321012  ↓マジックナンバー
					// 3 "る)" : 22 ")"の2バイト目で折り返しのとき
					// 2  "Z)" : 12 ")"の2バイト目で折り返しのとき
					// 2  "る)": 22 ")"で折り返しのとき
					// 2  "る)" : 21 ")"で折り返しのとき
					// 1   "Z)": 12 ")"で折り返しのとき
					// 1   "Z)" : 11 ")"で折り返しのとき
					//↑何文字前か?
					// ※ただし、"るZ"部分が禁則なら処理しない。
					case 3:	// 3文字前
						if( nCharChars2 == 2 && nCharChars3 == 2 )
						{
							bKinsokuFlag = true;
						}
						break;
					case 2:	// 2文字前
						if( 2 == nCharChars2 /*&& nCharChars3 > 0*/ )
						{
							bKinsokuFlag = true;
						}
						else if( nCharChars2 == 1 )
						{
							if( nCharChars3 == 2 )
							{
								bKinsokuFlag = true;
							}
						}
						break;
					case 1:	// 1文字前
						if( nCharChars2 == 1 /*&& nCharChars3 > 0*/ )
						{
							bKinsokuFlag = true;
						}
						break;
					}

					if( bKinsokuFlag
					 && IsKinsokuHead( &pLine[nPos+nCharChars2], nCharChars3 )
					 && ! IsKinsokuHead( &pLine[nPos], nCharChars2 )	//1文字前が行頭禁則でない
					 && ! IsKinsokuKuto( &pLine[nPos], nCharChars2 ) )	//句読点でない
					{
						//nPos += nCharChars2 + nCharChars3; nPosX += nCharChars2 + nCharChars3;
						nWordBgn = nPos;
						nWordLen = nCharChars2 + nCharChars3;
						nKinsokuType = KINSOKU_TYPE_KINSOKU_HEAD;
						AddLineBottom( CreateLayout(pCDocLine, nLineNum, nBgn, nPos - nBgn, nCOMMENTMODE_Prev, nIndent) );
						m_nLineTypeBot = nCOMMENTMODE;
						nCOMMENTMODE_Prev = nCOMMENTMODE;
						nBgn = nPos;
						// 2004.03.28 Moca nPosXはインデント幅を含むように変更(TAB位置調整のため)
						nPosX = nIndent = (this->*getIndentOffset)( m_pLayoutBot );
						pLayoutCalculated = m_pLayoutBot;
					}
				}

				/* 行末禁則 */
				if( m_bKinsokuTail
				 && (nMaxLineSize - nPosX < 4)
				 && ( nPosX > nIndent )	//	2004.04.09 nPosXの解釈変更のため,行頭チェックも変更
				 && (nKinsokuType == KINSOKU_TYPE_NONE) )
				{	/* 行末禁則する && 行末付近 && 行頭でないこと(無限に禁則してしまいそう) */
					bKinsokuFlag = false;
					nCharChars2 = CMemory::MemCharNext( pLine, nLineLen, &pLine[nPos] ) - &pLine[nPos];
					switch( nMaxLineSize - nPosX )
					{
					case 3:	// 3文字前
						if( nCharChars2 == 2 )
						{
							if( CMemory::MemCharNext( pLine, nLineLen, &pLine[nPos+nCharChars2] ) - &pLine[nPos+nCharChars2] == 2 )
							{
								// "(あ": "あ"の2バイト目で折り返しのとき
								bKinsokuFlag = true;
							}
						}
						break;
					case 2:	// 2文字前
						if( nCharChars2 == 2 )
						{
							// "(あ": "あ"で折り返しのとき
							bKinsokuFlag = true;
						}
						else if( nCharChars2 == 1 )
						{
							if( CMemory::MemCharNext( pLine, nLineLen, &pLine[nPos+nCharChars2] ) - &pLine[nPos+nCharChars2] == 2 )
							{
								// "(あ": "あ"の2バイト目で折り返しのとき
								bKinsokuFlag = true;
							}
						}
						break;
					case 1:	// 1文字前
						if( nCharChars2 == 1 )
						{
							// "(あ": "あ"で折り返しのとき
							bKinsokuFlag = true;
						}
						break;
					}

					if( bKinsokuFlag && IsKinsokuTail( &pLine[nPos], nCharChars2 ) )
					{
						//nPos += nCharChars2; nPosX += nCharChars2;
						nWordBgn = nPos;
						nWordLen = nCharChars2;
						nKinsokuType = KINSOKU_TYPE_KINSOKU_TAIL;
						AddLineBottom( CreateLayout(pCDocLine, nLineNum, nBgn, nPos - nBgn, nCOMMENTMODE_Prev, nIndent) );
						m_nLineTypeBot = nCOMMENTMODE;
						nCOMMENTMODE_Prev = nCOMMENTMODE;
						nBgn = nPos;
						// 2004.03.28 Moca nPosXはインデント幅を含むように変更(TAB位置調整のため)
						nPosX = nIndent = (this->*getIndentOffset)( m_pLayoutBot );
						pLayoutCalculated = m_pLayoutBot;
					}
				}
				//@@@ 2002.04.08 MIK end
			}	//if( KINSOKU_TYPE_NONE != nKinsokuTyoe ) 禁則処理中

			//@@@ 2002.09.22 YAZAKI
			bool bGotoSEARCH_START = CheckColorMODE( nCOMMENTMODE, nCOMMENTEND, nPos, nLineLen, pLine, bDispSSTRING, bDispWSTRING );
			if ( bGotoSEARCH_START )
				goto SEARCH_START;
			
			if( pLine[nPos] == TAB ){
				//	Sep. 23, 2002 genta せっかく作ったので関数を使う
				nCharChars = GetActualTabSpace( nPosX );
				if( nPosX + nCharChars > nMaxLineSize ){
					AddLineBottom( CreateLayout(pCDocLine, nLineNum, nBgn, nPos - nBgn, nCOMMENTMODE_Prev, nIndent) );
					m_nLineTypeBot = nCOMMENTMODE;
					nCOMMENTMODE_Prev = nCOMMENTMODE;
					nBgn = nPos;
					// 2004.03.28 Moca nPosXはインデント幅を含むように変更(TAB位置調整のため)
					nPosX = nIndent = (this->*getIndentOffset)( m_pLayoutBot );
					pLayoutCalculated = m_pLayoutBot;
					continue;
				}
				nPosX += nCharChars;
				nCharChars = 1;
				nPos+= nCharChars;
			}else{
				nCharChars = CMemory::MemCharNext( pLine, nLineLen, &pLine[nPos] ) - &pLine[nPos];
				if( 0 == nCharChars ){
					nCharChars = 1;
					break;	//@@@ 2002.04.16 MIK
				}
				if( nPosX + nCharChars > nMaxLineSize ){
					if( nKinsokuType != KINSOKU_TYPE_KINSOKU_KUTO )
					{
						if( ! (m_bKinsokuRet && (nPos == nLineLen - nEol) && nEol) )	//改行文字をぶら下げる		//@@@ 2002.04.14 MIK
						{	//@@@ 2002.04.14 MIK
							AddLineBottom( CreateLayout(pCDocLine, nLineNum, nBgn, nPos - nBgn, nCOMMENTMODE_Prev, nIndent) );
							m_nLineTypeBot = nCOMMENTMODE;
							nCOMMENTMODE_Prev = nCOMMENTMODE;
							nBgn = nPos;
							// 2004.03.28 Moca nPosXはインデント幅を含むように変更(TAB位置調整のため)
							nPosX = nIndent = (this->*getIndentOffset)( m_pLayoutBot );
							pLayoutCalculated = m_pLayoutBot;
							continue;
						}	//@@@ 2002.04.14 MIK
					}
				}
				nPos+= nCharChars;
				nPosX += nCharChars;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -