/*!
	指定行のドット位置(キャレット位置)に文字列を追加する・こっちが下位函数
	@param[in]	pNowDot	今のキャレットのドット位置のポインター
	@param[in]	pdLine	対象の行番号・絶対0インデックスか
	@param[in]	ptStr	追加したい文字列
	@param[in]	cchSize	文字列の文字数・ヌルターミネータ含まず
	@return		INT		0改行無し 1〜改行した回数
*/
INT DocStringAdd( PINT pNowDot, PINT pdLine, LPCTSTR ptStr, INT cchSize )
{
	INT	i, insDot, dLn, dCrLf;

	assert( ptStr );

	dCrLf  = 0;
	dLn    = *pdLine;
	insDot = *pNowDot;

#ifdef DO_TRY_CATCH
	try{
#endif
	for( i = 0; cchSize > i; i++ )
	{
		if( CC_CR == ptStr[i] && CC_LF == ptStr[i+1] )	//	改行であったら
		{
			DocInputReturn( insDot, *pdLine );
			i++;			//	0x0D,0x0Aだから、壱文字飛ばすのがポイント
			(*pdLine)++;	//	改行したからFocusは次の行へ
			insDot =  0;	//	そして行の先頭である
			dCrLf++;		//	改行した回数カウント
		}
		else if( CC_TAB == ptStr[i] )
		{
			//	タブは挿入しない
		}
		else
		{
			insDot += DocInputLetter( insDot, *pdLine, ptStr[i] );
		}
	}

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return (INT)ETC_MSG( err.what(), 0 );	}
	catch( ... ){	return (INT)ETC_MSG( ("etc error"), 0 );	}
#endif


#ifdef DO_TRY_CATCH
	try{
#endif
	//	ここで空白チェキ・開始行から終了行までブンブンする
	for( i = dLn; *pdLine >= i; i++ )
	{
		DocBadSpaceCheck( i );
	}

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return (INT)ETC_MSG( err.what(), 0 );	}
	catch( ... ){	return (INT)ETC_MSG( ("etc error"), 0 );	}
#endif
	//	アンドゥリドゥはここではなく呼んだほうで面倒見るほうがいい

	*pNowDot = insDot;

	return dCrLf;
}
/*!
	ページを変更・ファイルコア函数
	@param[in]	dPageNum	変更したい頁番号
	@return		HRESULT	終了状態コード
*/
HRESULT DocPageChange( INT dPageNum )
{
	INT	iPrePage;

	//	今の表示内容破棄とかいろいろある
#ifdef DO_TRY_CATCH
	try{
#endif

	ViewSelPageAll( -1 );	//	範囲選択を破棄

	iPrePage = gixFocusPage;
	gixFocusPage = dPageNum;	//	先に変更して

	(*gitFileIt).dNowPage = dPageNum;	//	記録

	//	まだ展開されてないなら
	DocDelayPageLoad( gitFileIt, dPageNum );

	PageListViewChange( dPageNum, iPrePage );

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return (HRESULT)ETC_MSG( err.what(), E_UNEXPECTED );	}
	catch( ... ){	return (HRESULT)ETC_MSG( ("etc error") , E_UNEXPECTED );	}
#endif

	return S_OK;
}
/*!
	頁を削除・ファイルコア函数
	@param[in]	iPage	削除する頁の番号
	@param[in]	iBack	−1無視 0〜削除したあと移動する頁指定
	@return		HRESULT	終了状態コード
*/
HRESULT DocPageDelete( INT iPage, INT iBack )
{
	INT	i, iNew;
	PAGE_ITR	itPage;

	if( 1 >= DocNowFilePageCount( ) )	return E_ACCESSDENIED;

#ifdef DO_TRY_CATCH
	try{
#endif

	//	ここでバックアップを?

	//	街頭位置までイテレータをもっていく
	itPage = (*gitFileIt).vcCont.begin(  );
	for( i = 0; iPage > i; i++ ){	itPage++;	}

	FREE( itPage->ptRawData );

	SqnFreeAll( &(itPage->stUndoLog)  );	//	アンドゥログ削除
	(*gitFileIt).vcCont.erase( itPage  );	//	さっくり削除
	gixFocusPage = -1;	//	頁選択無効にする


	PageListDelete( iPage );

	if( 0 <= iBack )	//	戻り先指定
	{
		iNew = iBack;
	}
	else
	{
		iNew = iPage - 1;	//	削除したら一つ前の頁へ
		if( 0 > iNew )	iNew = 0;
	}

	DocPageChange( iNew );	//	削除したら頁移動

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return ETC_MSG( err.what(), E_FAIL );	}
	catch( ... ){	return  ETC_MSG( ("etc error"), E_FAIL );	}
#endif

	return S_OK;
}
/*!
	新しいファイル置き場を作ってフォーカスする・ファイルコア函数
	@param[in]	ptDmyName	ダミー名を返す。NULL可。MAX_PATHであること
	@return		LPARAM	対応するユニーク番号
*/
LPARAM DocMultiFileCreate( LPTSTR ptDmyName )
{
	ONEFILE	stFile;
	FILES_ITR	itNew;

#ifdef DO_TRY_CATCH
	try{
#endif

	ZeroMemory( stFile.atFileName, sizeof(stFile.atFileName) );
	stFile.dModify   = FALSE;
	stFile.dNowPage  = 0;
	stFile.dUnique   = gdNextNumber++;
	stFile.stCaret.x = 0;
	stFile.stCaret.y = 0;

	ZeroMemory( stFile.atDummyName, sizeof(stFile.atDummyName) );
	StringCchPrintf( stFile.atDummyName, MAX_PATH, TEXT("%s%d.%s"), NAME_DUMMY_NAME, stFile.dUnique, NAME_DUMMY_EXT );

	if( ptDmyName ){	StringCchCopy( ptDmyName, MAX_PATH, stFile.atDummyName );	}

	stFile.vcCont.clear(  );

	gltMultiFiles.push_back( stFile );

	//	新規作成の準備
	gixFocusPage = -1;

	PageListClear(  );	//	ページリストビューも破棄


	itNew = gltMultiFiles.end( );
	itNew--;	//	末端に追加したからこれでおk

	gitFileIt = itNew;	//	ファイルなう

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return ETC_MSG( err.what(), 0 );	}
	catch( ... ){	return  ETC_MSG( ("etc error"), 0 );	}
#endif

	return stFile.dUnique;
}
/*!
	ページ全体を文字列で確保する・freeは呼んだ方でやる
	@param[in]	itFile	確保するファイル
	@param[in]	dPage	確保する頁番号
	@param[in]	bStyle	1ユニコードかシフトJISで、矩形かどうか
	@param[out]	pText	確保した領域を返す・ワイド文字かマルチ文字になる・NULLだと必要バイト数を返すのみ
	@param[in]	bCrLf	末端に改行付けるか
	@return				確保したバイト数・NULLターミネータ含む
*/
INT DocPageTextGetAlloc( FILES_ITR itFile, INT dPage, UINT bStyle, LPVOID *pText, BOOLEAN bCrLf )
{
	UINT_PTR	iLines, iLetters, j, iSize;
	UINT_PTR	i;
	UINT_PTR	cchSize;

	LPSTR		pcStr;

	string	srString;
	wstring	wsString;

	LINE_ITR	itLines;

#ifdef DO_TRY_CATCH
	try{
#endif

	srString.clear( );
	wsString.clear( );

	//	デフォ的な
	if( 0 > dPage ){	dPage = gixFocusPage;	}


	if( itFile->vcCont.at( dPage ).ptRawData )	//	生データ状態なら
	{
		if( bStyle & D_UNI )	//	ユニコードである
		{
			wsString = wstring( itFile->vcCont.at( dPage ).ptRawData );
			if( bCrLf ){	wsString += wstring( CH_CRLFW );	}
		}
		else	//	ShiftJISである
		{
			pcStr = SjisEncodeAlloc( itFile->vcCont.at( dPage ).ptRawData );	//	ページ全体を文字列で確保
			if( pcStr )
			{
				srString = string( pcStr );
				if( bCrLf ){	srString +=  string( CH_CRLFA );	}

				FREE( pcStr );
			}
		}
	}
	else	//	ロード済みなら
	{
		//	全文字を頂く
		iLines = itFile->vcCont.at( dPage ).ltPage.size( );

		for( itLines = itFile->vcCont.at( dPage ).ltPage.begin(), i = 0;
		itLines != itFile->vcCont.at( dPage ).ltPage.end();
		itLines++, i++ )
		{
			iLetters = itLines->vcLine.size( );

			for( j = 0; iLetters > j; j++ )
			{
				srString +=  string( itLines->vcLine.at( j ).acSjis );
				wsString += itLines->vcLine.at( j ).cchMozi;
			}

			if( !(1 == iLines && 0 == iLetters) )	//	壱行かつ零文字は空である
			{
				if( iLines > (i+1) )	//	とりあえずファイル末端改行はここでは付けない
				{
					srString +=  string( CH_CRLFA );
					wsString += wstring( CH_CRLFW );
				}
			}
		}

		if( bCrLf )
		{
			srString +=  string( CH_CRLFA );
			wsString += wstring( CH_CRLFW );
		}
	}

	if( bStyle & D_UNI )
	{
		cchSize = wsString.size(  ) + 1;	//	NULLターミネータ
		iSize = cchSize * sizeof(TCHAR);	//	ユニコードなのでバイト数は2倍である

		if( pText )
		{
			*pText = (LPTSTR)malloc( iSize );
			ZeroMemory( *pText, iSize );
			StringCchCopy( (LPTSTR)(*pText), cchSize, wsString.c_str( ) );
		}
	}
	else
	{
		iSize = srString.size( ) + 1;	//	NULLターミネータ

		if( pText )
		{
			*pText = (LPSTR)malloc( iSize );
			ZeroMemory( *pText, iSize );
			StringCchCopyA( (LPSTR)(*pText), iSize, srString.c_str( ) );
		}
	}

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return (INT)ETC_MSG( err.what(), 0 );	}
	catch( ... ){	return (INT)ETC_MSG( ("etc error") , 0 );	}
#endif

	return (INT)iSize;
}
/*!
	ページ追加処理・ファイルコア函数
	@param[in]	iAdding	この指定ページの次に追加・-1で末端に追加
	@return	INT	新規作成したページ番号
*/
INT DocPageCreate( INT iAdding )
{
	INT_PTR		iTotal, iNext;
	UINT_PTR	iAddPage = 0;
	INT		i;

	ONELINE	stLine;
	ONEPAGE	stPage;

	PAGE_ITR	itPage;

#ifdef DO_TRY_CATCH
	try{
#endif

	ZeroONELINE( &stLine  );	//	新規作成したら、壱行目が0文字な枠を作る

	//	こっちもZeroONEPAGEとかにまとめるか
	ZeroMemory( stPage.atPageName, sizeof(stPage.atPageName) );
//	stPage.dDotCnt = 0;
	stPage.dByteSz = 0;
	stPage.ltPage.clear(  );
	stPage.ltPage.push_back( stLine );	//	1頁の枠を作って
	stPage.dSelLineTop    =  -1;		//	無効は−1を注意
	stPage.dSelLineBottom =  -1;		//	
	stPage.ptRawData = NULL;
	SqnInitialise( &(stPage.stUndoLog) );

	//	今の頁の次に作成
	iTotal = DocNowFilePageCount(  );

	if( 0 <= iAdding )
	{
		iNext = iAdding + 1;	//	次の頁
		if( iTotal <= iNext ){	iNext =  -1;	}	//	全頁より多いなら末端指定
	}
	else
	{
		iNext = -1;
	}

	if( 0 >  iNext )	//	末尾に追加
	{
		(*gitFileIt).vcCont.push_back( stPage  );	//	ファイル構造体に追加

		iAddPage = DocNowFilePageCount( );
		iAddPage--;	//	末端に追加したんだから、個数数えて−1したら0インデックス番号
	}
	else
	{
		itPage = (*gitFileIt).vcCont.begin(  );
		for( i = 0; iNext >  i; i++ ){	itPage++;	}
		(*gitFileIt).vcCont.insert( itPage, stPage );

		iAddPage = iNext;
	}

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return ETC_MSG( err.what(), 0 );	}
	catch( ... ){	return  ETC_MSG( ("etc error"), 0 );	}
#endif

	return iAddPage;	//	追加したページ番号
}
/*!
	指定行のドット位置(キャレット位置)に壱文字追加する・この函数内ではアンドゥの面倒は見ない
	@param[in]	nowDot	挿入するドット位置
	@param[in]	rdLine	対象の行番号・絶対0インデックスか
	@param[in]	ch		追加したい文字
	@return		INT		追加した文字のドット数
*/
INT DocInputLetter( INT nowDot, INT rdLine, TCHAR ch )
{
	INT_PTR	iLetter, iCount, iLines;
	LETTER	stLetter;
	LETR_ITR	vcItr;
	LINE_ITR	itLine;

	//	アンドゥリドゥは呼んだところで

#ifdef DO_TRY_CATCH
	try{
#endif

	if( 0 == ch )
	{
		TRACE( TEXT("NULL文字が入った") );
		return 0;
	}

	iLines = DocNowFilePageLineCount( );

	if( iLines <= rdLine )
	{
		TRACE( TEXT("OutOfRange 指定[%d] 行数[%d]"), rdLine, iLines );
		return 0;
	}

	iLetter = DocLetterPosGetAdjust( &nowDot, rdLine, 0 );	//	今の文字位置を確認

	itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin();
	std::advance( itLine, rdLine );	//	対象行までイテレートする

	//	文字数確認
	iCount = itLine->vcLine.size( );

	//	データ作成
	DocLetterDataCheck( &stLetter, ch );	//	指定行のドット位置(キャレット位置)に壱文字追加するとき

	if( iLetter >=  iCount )	//	文字数同じなら末端に追加ということ
	{
		itLine->vcLine.push_back( stLetter );
	}
	else	//	そうでないなら途中に追加
	{
		vcItr = itLine->vcLine.begin( );
		vcItr += iLetter;
		itLine->vcLine.insert( vcItr, stLetter );
	}

	itLine->iDotCnt += stLetter.rdWidth;
	itLine->iByteSz += stLetter.mzByte;

	(*gitFileIt).vcCont.at( gixFocusPage ).dByteSz += stLetter.mzByte;

//	DocBadSpaceCheck( rdLine );	呼んだところでまとめてやる

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return ETC_MSG( err.what(), 0 );	}
	catch( ... ){	return  ETC_MSG( ("etc error"), 0 );	}
#endif

	return stLetter.rdWidth;
}
/*!
	指定行のドット位置(キャレット位置)で改行する
	@param[in]	nowDot	今のキャレットのドット位置
	@param[in]	rdLine	対象の行番号・絶対0インデックスか
	@return		HRESULT	終了状態コード
*/
HRESULT DocInputReturn( INT nowDot, INT rdLine )
{
	INT_PTR	iLetter, iLines, iCount;
	ONELINE	stLine;

	LETR_ITR	vcLtrItr, vcLtrEnd;

	LINE_ITR	itLine, ltLineItr;

#ifdef DO_TRY_CATCH
	try{
#endif

	iLines = DocNowFilePageLineCount( );

	if( iLines <= rdLine )	return E_OUTOFMEMORY;

	ZeroONELINE( &stLine );

	iLetter = DocLetterPosGetAdjust( &nowDot, rdLine, 0 );	//	今の文字位置を確認

	//	文字数確認
	itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin();
	std::advance( itLine, rdLine );

	iCount = itLine->vcLine.size( );

	if( iLetter < iCount )	//	もし行の途中で改行したら?
	{
		ltLineItr = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin( );
		std::advance( ltLineItr, (rdLine+1) );

		//	今の行の次の場所に行のデータを挿入
		(*gitFileIt).vcCont.at( gixFocusPage ).ltPage.insert( ltLineItr, stLine );

		//	その行の、文字データの先頭をとる
		ltLineItr = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin( );
		std::advance( ltLineItr, (rdLine+1) );	//	追加した行まで移動

		//	ぶった切った場所を設定しなおして
		itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin();
		std::advance( itLine, rdLine );

		vcLtrItr  = itLine->vcLine.begin( );
		vcLtrItr += iLetter;	//	今の文字位置を示した
		vcLtrEnd  = itLine->vcLine.end( );	//	末端

		//	その部分を次の行にコピーする
		std::copy( vcLtrItr, vcLtrEnd, back_inserter(ltLineItr->vcLine) );

		//	元の文字列を削除する
		itLine->vcLine.erase( vcLtrItr, vcLtrEnd );


		//	総ドット数再計算
		DocLineParamGet( rdLine,   NULL, NULL );
		DocLineParamGet( rdLine+1, NULL, NULL );
	}
	else	//	末端で改行した
	{
		if( (iLines - 1) == rdLine )	//	EOF的なところ
		{
			(*gitFileIt).vcCont.at( gixFocusPage ).ltPage.push_back( stLine );
		}
		else
		{
			ltLineItr = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin( );
			std::advance( ltLineItr, (rdLine+1) );	//	今の行を示した

			//	次の場所に行のデータを挿入
			(*gitFileIt).vcCont.at( gixFocusPage ).ltPage.insert( ltLineItr, stLine );
		}
	}

	DocBadSpaceCheck( rdLine   );	//	ここで空白チェキ
	DocBadSpaceCheck( rdLine+1 );	//	空白チェキ・次の行も確認

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return (HRESULT)ETC_MSG( err.what(), E_UNEXPECTED );	}
	catch( ... ){	return (HRESULT)ETC_MSG( ("etc error") , E_UNEXPECTED );	}
#endif

	return S_OK;
}
Exemple #9
0
/*!
	選択されているところを全削除しちゃう
	@param[in]	pdDot	キャレットドット位置・書き換える必要がある
	@param[in]	pdLine	行番号・書き換える必要がある
	@param[in]	bSqSel	矩形選択してるのかどうか・D_SQUARE
	@param[in]	bFirst	アンドゥ用・これが最初のアクションか
	@return	非0改行あった 0壱行のみ
*/
INT DocSelectedDelete( PINT pdDot, PINT pdLine, UINT bSqSel, BOOLEAN bFirst )
{
//	UINT_PTR	iLines;
	UINT_PTR	iMozis;
	INT			i, j, dBeginX = 0, dBeginY = 0, cbSize;
	INT			iLct, k, bCrLf;
	LPTSTR		ptText;
	LPPOINT		pstPt;

	LETR_ITR	itLtr, itEnd, itHead, itTail;
	LINE_ITR	itLine;

#ifdef DO_TRY_CATCH
	try{
#endif

	bSqSel &= D_SQUARE;	//	矩形ビットだけ残す

	//	ページ全体の行数
//	iLines = DocNowFilePageLineCount( );
	i = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineTop;
	j = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineBottom;
	TRACE( TEXT("範囲削除[T%d - B%d]"), i, j );
	if( 0 > i ){	return 0;	}	//	選択範囲が無かった


//アンドゥバッファリングの準備
	iLct = j - i + 1;	//	含まれる行なので、数えるの注意
	cbSize = DocSelectTextGetAlloc( D_UNI | bSqSel, (LPVOID *)(&ptText), NULL );
	pstPt = (LPPOINT)malloc( iLct * sizeof(POINT) );
	ZeroMemory( pstPt, iLct * sizeof(POINT) );
	k = iLct - 1;

	bCrLf = iLct - 1;

	dBeginY = i;	//	選択肢のある行

	itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin();
	std::advance( itLine, j );

	for( ; i <= j; j--, k--, itLine-- )//beginを超えたらアウツ!
	{
		//	continueは使えない・

		iMozis = itLine->vcLine.size( );
		if( 0 < iMozis )
		{
			itLtr = itLine->vcLine.begin(  );
			itEnd = itLine->vcLine.end(  );
			itHead = itEnd;
			itTail = itEnd;

			dBeginX = 0;

			//	最初の選択部分を検索
			for( ; itLtr != itEnd; itLtr++ )
			{
				if( CT_SELECT & itLtr->mzStyle )
				{
					itHead =  itLtr;
					break;
				}

				dBeginX += itLtr->rdWidth;	//	意味があるのは最後のところなので、常時上書きでおk
			}

			//	選択されてない所まで検索
			for( ; itLtr != itEnd; itLtr++ )
			{
				if( !(CT_SELECT & itLtr->mzStyle) )
				{
					itTail =  itLtr;
					break;
				}
			}
		}

		pstPt[k].x = dBeginX;
		pstPt[k].y = j;

		if( 0 < iMozis )
		{
			//	該当範囲を削除・末端は、該当部分の直前までが対象・末端自体は非対象
			itLine->vcLine.erase( itHead, itTail );
		}

		//	改行が含まれていたら
		if( CT_SELRTN & itLine->dStyle ){	DocLineCombine( j );	}

		DocLineParamGet( j, NULL, NULL );	//	バイト数再計算

		//	矩形の場合は、各行毎に面倒みないかん
		if( D_SQUARE & bSqSel ){	DocBadSpaceCheck( j );	}

		//	改行サクるとこれによりatが無効になる?
	
	//	iLines = DocNowFilePageLineCount( );	//	ページ全体の行数再設定?

		if( (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin() == itLine )	break;
		//	位置的に末端だったらループせずに終わる
	}

	ViewSelPageAll( -1 );	//	選択範囲無くなる

	//	カーソル位置移動せないかん
	*pdDot = dBeginX;	*pdLine = dBeginY;

	//	最終的に残っている行のチェックだけすればいい
	if( !(D_SQUARE & bSqSel)  ){	DocBadSpaceCheck( dBeginY );	}

	if( bSqSel ){	SqnAppendSquare( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_DELETE, ptText, pstPt, iLct , bFirst );	}
	else{		SqnAppendString( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_DELETE, ptText, dBeginX, dBeginY, bFirst );	}

	FREE( ptText );

	FREE( pstPt );

#ifdef DO_TRY_CATCH
	}
	catch( exception &err ){	return (INT)ETC_MSG( err.what(), 0 );	}
	catch( ... ){	return (INT)ETC_MSG( ("etc error"), 0 );	}
#endif

	return bCrLf;
}