/*! ページを変更・ファイルコア函数 @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] uqNumber 選択されたファイルのUNIQUE番号 @return HRESULT 終了状態コード */ HRESULT DocMultiFileSelect( LPARAM uqNumber ) { FILES_ITR itNow; POINT stCaret; for( itNow = gltMultiFiles.begin(); itNow != gltMultiFiles.end(); itNow++ ) { if( uqNumber == itNow->dUnique ) break; } if( itNow == gltMultiFiles.end() ) return E_OUTOFMEMORY; ViewSelPageAll( -1 ); // 今開いてる頁の範囲選択を破棄 PageListClear( ); // ページリストビューも破棄 gitFileIt = itNow; // ファイルなう // TODO: 初回読み込み時のバイト数計算間違えてるようだ・なおった? PageListBuild( NULL ); // ページリスト作り直し AppTitleChange( itNow->atFileName ); // キャプションの内容も変更 gixFocusPage = itNow->dNowPage; DocModifyContent( itNow->dModify ); // 変更したかどうか DocCaretPosMemory( INIT_LOAD, &stCaret ); // 先に読み出さないと次でクルヤーされる PageListViewChange( gixFocusPage, -1 ); // 全部読み込んだのでラストページを表示する ViewPosResetCaret( stCaret.x, stCaret.y ); // Caret位置再設定 return S_OK; }
/*! 行末空白削除の面倒見る・選択行とか @param[in] pXdot 今のドット位置を受けて戻す・削除に巻き込まれた対応 @param[in] dLine 今の行数 @return HRESULT 終了状態コード */ HRESULT DocLastSpaceErase( PINT pXdot, INT dLine ) { UINT_PTR iLines; INT iTop, iBottom, i, xDelDot, xMotoDot; BOOLEAN bFirst = TRUE; LPTSTR ptBuffer = NULL; RECT rect; LINE_ITR itLine; TRACE( TEXT("行末空白削除") ); // 範囲確認 iLines = DocNowFilePageLineCount( ); iTop = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineTop; iBottom = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineBottom; if( 0 > iTop ) iTop = 0; if( 0 > iBottom ) iBottom = iLines - 1; ViewSelPageAll( -1 ); // 選択範囲無くなる itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin(); std::advance( itLine, iTop ); // 位置合わせ for( i = iTop; iBottom >= i; i++, itLine++ ) { xMotoDot = itLine->iDotCnt; ptBuffer = DocLastSpDel( &(itLine->vcLine) ); xDelDot = DocLineParamGet( i, NULL, NULL ); // サクった後の行末端すなわち削除位置 if( ptBuffer ) { SqnAppendString( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_DELETE, ptBuffer, xDelDot, i , bFirst ); bFirst = FALSE; } FREE( ptBuffer ); DocBadSpaceCheck( i ); // 状態をリセット・中で行書換でいいか? rect.top = i * LINE_HEIGHT; rect.bottom = rect.top + LINE_HEIGHT; rect.left = xDelDot; // 削ったら左側になる rect.right = xMotoDot + 20; // 元長さ+改行マーク ViewRedrawSetRect( &rect ); // ViewRedrawSetLine( i ); // 再描画COMMANDO } // キャレット位置ずれてたら適当に調整 DocLetterPosGetAdjust( pXdot, dLine, 0 ); // キャレット位置適当に調整 ViewDrawCaret( *pXdot, dLine, 1 ); DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! 右揃え線の面倒見る @param[in] pVoid なにか @return HRESULT 終了状態コード */ HRESULT DocRightGuideline( LPVOID pVoid ) { INT iTop, iBottom, i; TRACE( TEXT("右揃え線") ); iTop = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineTop; iBottom = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineBottom; DocRightGuideSet( iTop, iBottom ); ViewSelPageAll( -1 ); // 選択範囲無くなる if( 0 > iTop || 0 > iBottom ){ ViewRedrawSetLine( -1 ); } else{ for( i = iTop; iBottom >= i; i++ ){ ViewRedrawSetLine( i ); } } DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! 行頭半角空白をユニコードに変換・ファイルコア函数 */ HRESULT DocHeadHalfSpaceExchange( HWND hWnd ) { UINT_PTR iLines; INT iTop, iBottom, i; INT xDot; BOOLEAN bFirst = TRUE, bSeled = FALSE; TCHAR ch; LETR_ITR vcLtrItr; LINE_ITR itLine; // 範囲確認 iLines = DocNowFilePageLineCount( ); iTop = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineTop; iBottom = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineBottom; if( 0 <= iTop && 0 <= iBottom ) bSeled = TRUE; if( 0 > iTop ) iTop = 0; if( 0 > iBottom ) iBottom = iLines - 1; TRACE( TEXT("行頭半角をユニコードに") ); ViewSelPageAll( -1 ); // 選択範囲無くなる // 容量計算、バッド空白の確認と再描画必要 itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin(); std::advance( itLine, iTop ); // 行の位置合わせ for( i = iTop; iBottom >= i; i++, itLine++ ) // 範囲内の各行について { // 文字があるなら操作する if( 0 != itLine->vcLine.size( ) ) { vcLtrItr = itLine->vcLine.begin( ); ch = vcLtrItr->cchMozi; if( TEXT(' ') == ch ) // 半角なら { // 一旦削除して SqnAppendLetter( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_DELETE, ch, 0, i, bFirst ); bFirst = FALSE; DocIterateDelete( vcLtrItr, i ); // 先頭位置に5dotユニコード空白をアッー!。 ch = (TCHAR)0x2004; xDot = DocInputLetter( 0, i, ch ); SqnAppendLetter( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_INSERT, ch, 0, i, bFirst ); } DocBadSpaceCheck( i ); // 状態をリセット ViewRedrawSetLine( i ); } } // キャレット位置はずれない DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! 全体又は選択範囲を右に寄せる @param[in] pXdot 今のドット位置を受けて戻す @param[in] dLine 今の行数 @return HRESULT 終了状態コード */ HRESULT DocRightSlide( PINT pXdot, INT dLine ) { UINT_PTR iLines; INT iTop, iBottom, i; INT dSliDot, dRitDot, dPaDot, dInBgn; INT dMozi, dLefDot, dAdDot; BOOLEAN bFirst = TRUE; LPTSTR ptBuffer = NULL; LINE_ITR itLine; TRACE( TEXT("右寄せ") ); // 右寄せ限界確認 dSliDot = InitParamValue( INIT_LOAD, VL_RIGHT_SLIDE, 790 ); // 範囲確認 iLines = DocNowFilePageLineCount( ); iTop = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineTop; iBottom = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineBottom; if( 0 > iTop ) iTop = 0; if( 0 > iBottom ) iBottom = iLines - 1; ViewSelPageAll( -1 ); // 選択範囲無くなる dRitDot = DocPageMaxDotGet( iTop, iBottom ); // 一番右のドット確認 dPaDot = dSliDot - dRitDot; if( 0 > dPaDot ) { NotifyBalloonExist( TEXT("はみ出してるみたい"), TEXT("失敗"), NIIF_ERROR ); return E_FAIL; } itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin(); std::advance( itLine, iTop ); // 位置合わせ for( i = iTop; iBottom >= i; i++, itLine++ ) { dAdDot = dPaDot; // 行頭の開き状態を確認 dLefDot = LayerHeadSpaceCheck( &(itLine->vcLine), &dMozi ); if( 0 < dLefDot ) { dAdDot += dLefDot; // 手前に空白があるなら、その分含めてずらし用スペースを計算 DocRangeDeleteByMozi( 0, i, 0, dMozi, &bFirst ); bFirst = FALSE; } // 先頭からうめちゃう dInBgn = 0; ptBuffer = DocPaddingSpaceWithPeriod( dAdDot, NULL, NULL, NULL, TRUE ); DocInsertString( &dInBgn, &i, NULL, ptBuffer, 0, bFirst ); bFirst = FALSE; FREE(ptBuffer); ViewRedrawSetLine( i ); } // キャレット位置適当に調整 *pXdot = 0; DocLetterPosGetAdjust( pXdot, dLine, 0 ); // キャレット位置適当に調整 ViewDrawCaret( *pXdot, dLine, 1 ); DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! 各行の末端から800くらいまでを、指定した文字で埋める。 @param[in] ptFill 埋め文字列 */ HRESULT DocScreenFill( LPTSTR ptFill ) { UINT_PTR dLines, dRiDot, cchSize; BOOLEAN bSel = TRUE, bFirst; INT iTop, iBottom, i, iUnt, j, remain; INT nDot, sDot, mDot; LPTSTR ptBuffer; wstring wsBuffer; // 現在行数と、右ドット数・ルーラ位置を使う dLines = DocNowFilePageLineCount( ); dRiDot = gdRightRuler; // 選択範囲あるならそっち優先。ないなら画面全体 iTop = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineTop; iBottom = (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineBottom; if( 0 > iTop || 0 > iBottom ){ iTop = 0; iBottom = dLines - 1; bSel = FALSE; } ViewSelPageAll( -1 ); // 選択範囲無くなる // 埋め文字列の幅 mDot = ViewStringWidthGet( ptFill ); bFirst = TRUE; // 各行毎に追加する感じで for( i = iTop; iBottom >= i; i++ ) { nDot = DocLineParamGet( i , NULL, NULL ); // 呼び出せば中で面倒みてくれる sDot = dRiDot - nDot; // 残りドット if( 0 >= sDot ){ continue; } // 右端超えてるならなにもせんでいい iUnt = (sDot / mDot) + 1; // 埋める分・はみ出し・適当で良い // 入れる文字列作成 wsBuffer.clear( ); for( j = 0; iUnt > j; j++ ){ wsBuffer += wstring( ptFill ); } cchSize = wsBuffer.size( ) + 1; ptBuffer = (LPTSTR)malloc( cchSize * sizeof(TCHAR) ); StringCchCopy( ptBuffer, cchSize, wsBuffer.c_str( ) ); // 末端にブチこむ DocInsertString( &nDot, &i, NULL, ptBuffer, 0, bFirst ); bFirst = FALSE; FREE(ptBuffer); DocBadSpaceCheck( i ); // ここで空白チェキ・あまり意味はないが色換えは必要 } if( !(bSel) ) // 非選択状態で { remain = 40 - dLines; // とりあえず40行とする if( 0 < remain ) // 足りないなら { DocAdditionalLine( remain, &bFirst ); // とりあえず改行して dLines = DocNowFilePageLineCount( ); iUnt = (dRiDot / mDot) + 1; // 埋める分・はみ出し・適当で良い // 入れる文字列作成 wsBuffer.clear( ); for( j = 0; iUnt > j; j++ ){ wsBuffer += wstring( ptFill ); } cchSize = wsBuffer.size( ) + 1; ptBuffer = (LPTSTR)malloc( cchSize * sizeof(TCHAR) ); StringCchCopy( ptBuffer, cchSize, wsBuffer.c_str( ) ); iTop = iBottom + 1; iBottom = dLines - 1; for( i = iTop; iBottom >= i; i++ ) { // 末端にブチこむ nDot = DocLineParamGet( i , NULL, NULL ); // 多分0のハズ DocInsertString( &nDot, &i, NULL, ptBuffer, 0, bFirst ); bFirst = FALSE; DocBadSpaceCheck( i ); // ここで空白チェキ・あまり意味はないが色換えは必要 } FREE(ptBuffer); } } DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! 選択範囲を指定文字列で塗りつぶす @param[in] ptBrush ブラシ文字列・NULLなら空白 @param[in] pdDot キャレットドット位置・書き換える必要がある @param[in] pdLine 行番号・書き換える必要がある @return 非0塗った 0してない */ INT DocSelectedBrushFilling( LPTSTR ptBrush, PINT pdDot, PINT pdLine ) { UINT_PTR iMozis; UINT_PTR cchSize; INT i, j, dBeginX = 0, dBeginY = 0; INT iLct, dTgtDot, dBgnDot, dNowDot; BOOLEAN bFirst; LPTSTR ptReplc = NULL, ptDeled; // INT dZenSp, dHanSp, dUniSp; wstring wsBuffer; LETR_ITR itLtr, itEnd, itHead, itTail; LINE_ITR itLine; bFirst = TRUE; 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; } // 選択範囲が無かった dBeginY = i; // 選択肢のある行 dBeginX = 0; // 壱行ずつ処理していく itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin(); std::advance( itLine, i ); for( iLct = i; j >= iLct; iLct++, itLine++ ) { // 文字数確認して iMozis = itLine->vcLine.size( ); if( 0 < iMozis ) { itLtr = itLine->vcLine.begin( ); itEnd = itLine->vcLine.end( ); itHead = itEnd; itTail = itEnd; dBgnDot = 0; dTgtDot = 0; // 最初の選択部分を検索 for( ; itLtr != itEnd; itLtr++ ) { if( CT_SELECT & itLtr->mzStyle ) { itHead = itLtr; dTgtDot = itLtr->rdWidth; itLtr++; // 次の文字を参照 break; } dBgnDot += itLtr->rdWidth; } if( iLct == i ){ dBeginX = dBgnDot; } // 意味があるのは最後のところ // 選択されてない所まで検索 for( ; itLtr != itEnd; itLtr++ ) { if( !(CT_SELECT & itLtr->mzStyle) ) { itTail = itLtr; break; } dTgtDot += itLtr->rdWidth; // ドット数を確認 } // 当てはめるアレを計算する if( ptBrush ) { ptReplc = BrushStringMake( dTgtDot, ptBrush ); } else // 空白指定ということ { ptReplc = DocPaddingSpaceMake( dTgtDot ); } // ここで、埋め文字列が作成不可なら、この行の処理は飛ばす if( !(ptReplc) ) continue; // 該当部分の内容を記録<アンドゥ用 wsBuffer.clear(); for( itLtr = itHead; itLtr != itTail; itLtr++ ) { wsBuffer += itLtr->cchMozi; } cchSize = wsBuffer.size( ) + 1; ptDeled = (LPTSTR)malloc( cchSize * sizeof(TCHAR) ); StringCchCopy( ptDeled, cchSize, wsBuffer.c_str( ) ); // 該当部分を削除 itLine->vcLine.erase( itHead, itTail ); // ブラシ文字列で埋める StringCchLength( ptReplc, STRSAFE_MAX_CCH, &cchSize ); dNowDot = dBgnDot; DocStringAdd( &dNowDot, &iLct, ptReplc, cchSize ); SqnAppendString( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_DELETE, ptDeled, dBgnDot, iLct, bFirst ); bFirst = FALSE; SqnAppendString( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_INSERT, ptReplc, dBgnDot, iLct, bFirst ); FREE( ptDeled ); FREE( ptReplc ); ViewRedrawSetLine( iLct ); } } ViewSelPageAll( -1 ); // 選択範囲無くなる // カーソル位置移動せないかん *pdDot = dBeginX; *pdLine = dBeginY; return 1; }
/*! 選択されているところを全削除しちゃう @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; }