/*! キャレット位置から、左右に1dotずつずらす。文字なら空白に置き換えながら @param[in] vk 方向・右か左か @param[in] pXdot 今のドット位置を受けて戻す @param[in] dLine 今の行数 @return HRESULT 終了状態コード */ HRESULT DocCentreWidthShift( UINT vk, PINT pXdot, INT dLine ) { UINT_PTR iLines, cchSz; UINT dRslt, dFirst; INT iBaseDot, iTop, iBottom, iBufDot; INT wid, iDot, iLin, iMzCnt; INT iFnlDot; BOOLEAN bSeled = FALSE; BOOLEAN bRight; // 非0右へ 0左へ LPTSTR ptRepl; TCHAR ch, chOneSp; LPUNDOBUFF pstUndoBuff; LETR_ITR vcLtrItr; LINE_ITR itLine; chOneSp = gaatPaddingSpDotW[1][0]; // 幅1dot・文字間に挿入 //中心部分が空白なら、その空白を伸び縮みさせる。 //文字と文字の間開けるなら、抽芯になってる字の左側を開けるようにする //潰すときは、抽芯字を空白に置き換えて、それを縮める pstUndoBuff = &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog); iBaseDot = *pXdot; // 基準点、なるべく動かないようにせないかん TRACE( TEXT("中間ずらし %dDOT"), iBaseDot ); iFnlDot = iBaseDot; if( VK_RIGHT == vk ) bRight = TRUE; else if( VK_LEFT == vk ) bRight = FALSE; else return E_INVALIDARG; if( 0 == iBaseDot ) // 基準が0なら、全体左右ずらしってこと { return DocPositionShift( vk, pXdot, dLine ); } // 範囲確認 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; // そのままだと容量が狂う・一旦選択状態を解除して計算しなおす if( bSeled ){ DocPageSelStateToggle( -1 ); } // 壱行ずつ面倒見ていく itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin(); std::advance( itLine, iTop ); // 位置合わせ //なんか時々連続空白ができる dFirst = TRUE; // 順番に処理していく for( iLin = iTop; iBottom >= iLin; iLin++, itLine++ ) { iDot = itLine->iDotCnt; if( iBaseDot >= iDot ){ continue; } // 操作位置に満たないのなら、何もする必要は無い // 操作開始 iDot = iBaseDot; // 調整位置確定 iMzCnt = DocLetterPosGetAdjust( &iDot, iLin, -1 ); // 常に左側をみる // 操作する位置の文字確認 // 該当位置が空白なら、伸び縮み兼用 iBufDot = iDot; // 値ズレるのでそのまま使うとイケない dRslt = DocSpaceDifference( vk, &iBufDot, iLin, dFirst ); // iBufDotはズラしたら使えない if( dRslt ) // ズラし成功 { if( iLin == dLine ){ iFnlDot = iBaseDot; } // ずらした後の位置の面倒見る dFirst = FALSE; } else // 返り値0なら、文字なので処理を { vcLtrItr = itLine->vcLine.begin( ); std::advance( vcLtrItr, iMzCnt ); // 注目位置の文字まで移動して ch = vcLtrItr->cchMozi; wid = vcLtrItr->rdWidth; // 該当の文字の幅を確認 if( bRight ) // 右に動かす { if( iswspace( ch ) ) // 右側の文字は空白であったら { iBufDot = iDot + wid; // その空白を延ばす DocSpaceDifference( vk, &iBufDot, iLin, dFirst ); // iBufDotは使えない if( iLin == dLine ){ iFnlDot = iBaseDot; } // ずらした後の位置の面倒見る } else { SqnAppendLetter( pstUndoBuff, DO_INSERT, chOneSp, iDot, iLin, dFirst ); DocInputLetter( iDot, iLin, chOneSp ); // その場所に1dotスペース足せばおk if( iLin == dLine ){ iFnlDot = iDot + 1; } // ずらした後の位置の面倒見る } dFirst = FALSE; } else // 左に動かす { if( iLin == dLine ){ iFnlDot = iDot; } // ずらす前の位置の面倒見る // 今の文字を削除 SqnAppendLetter( pstUndoBuff, DO_DELETE, ch, iDot, iLin, dFirst ); dFirst = FALSE; DocIterateDelete( vcLtrItr , iLin ); if( 2 <= wid ) // 幅が1なら、削除だけでおk { ptRepl = DocPaddingSpaceMake( wid-1 ); // 必要な空白確保 StringCchLength( ptRepl , STRSAFE_MAX_CCH, &cchSz ); // 文字数確認 SqnAppendString( pstUndoBuff, DO_INSERT, ptRepl, iDot, iLin, dFirst ); dFirst = FALSE; DocStringAdd( &iDot, &iLin, ptRepl, cchSz ); // そして先頭に空白をアッー! FREE(ptRepl); // 開放忘れないように } } } if( bSeled ) // 選択状態でヤッてたのなら、選択状態を維持する { if( iLin == iTop ) { iDot = iBaseDot; DocLetterPosGetAdjust( &iDot, iLin, 0 ); // キャレット位置適当に調整 DocRangeSelStateToggle( iDot, -1, iLin , 1 ); // 該当行全体を選択状態にする } else { DocRangeSelStateToggle( -1, -1, iLin , 1 ); // 該当行全体を選択状態にする } // 次の行があるなら改行も選択で if( iBottom > iLin ) DocReturnSelStateToggle( iLin, 1 ); } DocBadSpaceCheck( iLin ); // 状態をリセット ViewRedrawSetLine( iLin ); } if( bSeled ) // 選択範囲はり直し { (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineTop = iTop; (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineBottom = iBottom; } // キャレット位置調整 DocLetterPosGetAdjust( &iFnlDot, dLine, 0 ); // キャレット位置適当に調整 *pXdot = iFnlDot; // 位置を戻す ViewDrawCaret( iFnlDot, dLine, 1 ); // 再描画 DocPageByteCount( gitFileIt, gixFocusPage, NULL, NULL ); DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! AA全体を、1dotずつずらす。文字なら空白に置き換えながら @param[in] vk 方向・右か左か @param[in] pXdot 今のドット位置を受けて戻す @param[in] dLine 今の行数 @return HRESULT 終了状態コード */ HRESULT DocPositionShift( UINT vk, PINT pXdot, INT dLine ) { UINT_PTR iLines, cchSz; INT iTop, iBottom, i; INT wid, iDot, iLin, iMzCnt; INT iTgtWid, iLefDot, iRitDot; BOOLEAN bFirst = TRUE, bSeled = FALSE, bDone = FALSE; BOOLEAN bRight; // 非0右へ 0左へ BOOLEAN bIsSp; LPTSTR ptRepl; TCHAR ch, chOneSp; LPUNDOBUFF pstUndoBuff; LETR_ITR vcLtrItr; LINE_ITR itLine; chOneSp = gaatPaddingSpDotW[1][0]; pstUndoBuff = &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog); TRACE( TEXT("全体ずらし") ); if( VK_RIGHT == vk ) bRight = TRUE; else if( VK_LEFT == vk ) bRight = FALSE; else return E_INVALIDARG; // 範囲確認 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; // そのままだと容量が狂う・一旦選択状態を解除して計算しなおす if( bSeled ){ DocPageSelStateToggle( -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; wid = vcLtrItr->rdWidth; // 文字幅 bDone = FALSE; if( !(iswspace(ch)) ) // 空白ではなく { if( bRight ) // 右ずらしなら { // 先頭に1dotスペース足せばおk DocInputLetter( 0, i, chOneSp ); SqnAppendLetter( pstUndoBuff, DO_INSERT, chOneSp, 0, i, bFirst ); bFirst = FALSE; bDone = TRUE; // 処理しちゃった } else // 左イクなら、先頭文字を空白にして調整する { ptRepl = DocPaddingSpaceMake( wid ); // 必要な空白確保 StringCchLength( ptRepl, STRSAFE_MAX_CCH, &cchSz ); // 今の文字を削除 SqnAppendLetter( pstUndoBuff, DO_DELETE, ch, 0, i, bFirst ); bFirst = FALSE; DocIterateDelete( vcLtrItr, i ); // そして先頭に空白をアッー! iDot = 0; iLin = i; DocStringAdd( &iDot, &iLin, ptRepl, cchSz ); SqnAppendString( pstUndoBuff, DO_INSERT, ptRepl, 0, i, bFirst ); bFirst = FALSE; FREE(ptRepl); // 開放忘れないように } } // この先Beginイテレータ無効 if( !(bDone) ) // 未処理であるなら・この時点で、先頭文字は空白確定 { // 空白範囲を確認 iTgtWid = DocLineStateCheckWithDot( 0, i, &iLefDot, &iRitDot, NULL, &iMzCnt, &bIsSp ); if( bRight ) iTgtWid++; // 方向に合わせて else iTgtWid--; // ドット数を求める if( 0 > iTgtWid ) iTgtWid = 0; // マイナスは無いと思うけど念のため ptRepl = DocPaddingSpaceMake( iTgtWid ); // 必要な空白確保 // ターゲット幅が0ならNULLなので、先頭文字の削除だけでおk DocRangeDeleteByMozi( 0, i, 0, iMzCnt, &bFirst ); // 元の部分削除して if( ptRepl ) // 必要な文字を入れる { StringCchLength( ptRepl, STRSAFE_MAX_CCH, &cchSz ); iDot = 0; iLin = i; DocStringAdd( &iDot, &iLin, ptRepl, cchSz ); SqnAppendString( pstUndoBuff, DO_INSERT, ptRepl, 0, i, bFirst ); bFirst = FALSE; FREE(ptRepl); // 開放忘れないように } } if( bSeled ) // 選択状態でヤッてたのなら、選択状態を維持する { DocRangeSelStateToggle( -1, -1, i , 1 ); // 該当行全体を選択状態にする // 次の行があるなら改行も選択で if( iBottom > i ) DocReturnSelStateToggle( i, 1 ); } DocBadSpaceCheck( i ); // 状態をリセット ViewRedrawSetLine( i ); } } if( bSeled ) // 選択範囲はり直し { (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineTop = iTop; (*gitFileIt).vcCont.at( gixFocusPage ).dSelLineBottom = iBottom; } // キャレット位置調整 iDot = 0; DocLetterPosGetAdjust( &iDot, dLine, 0 ); // キャレット位置適当に調整 ViewDrawCaret( iDot, dLine, 1 ); DocPageByteCount( gitFileIt, gixFocusPage, NULL, NULL ); DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! 抽出対象領域を取り出す @param[in] hInst 実存値 @return HRESULT 終了状態コード */ HRESULT DocExtractExecute( HINSTANCE hInst ) { INT dOffDot, dCount; BOOLEAN bLnFirst, bMzFirst, bIsVoid; LPTSTR ptSpace, ptString; UINT_PTR cch;//, i; LINE_ITR itLnFirst, itLnLast, itLnErate, itLnEnd; LETR_ITR itMozi, itMzEnd; wstring wsBuffer; if( 0 >= DocNowFilePageCount( ) ) return S_FALSE; // 開始行と終止行・オフセット量を検索 itLnErate = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin(); itLnEnd = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.end(); itLnFirst = itLnErate; itLnLast = itLnEnd; dOffDot = DocPageMaxDotGet( -1, -1 ); // MAX位置を初期にしとけばおk bLnFirst = TRUE; for( ; itLnEnd != itLnErate; itLnErate++ ) // 行サーチ { itMozi = itLnErate->vcLine.begin(); itMzEnd = itLnErate->vcLine.end(); dCount = 0; for( ; itMzEnd != itMozi; itMozi++ ) // 文字サーチ { if( CT_SELECT & itMozi->mzStyle ) // 選択状態発見 { if( bLnFirst ) // 最初の行が未発見であれば { itLnFirst = itLnErate; // 今の行を記録する bLnFirst = FALSE; } itLnLast = itLnErate; // 選択状態があるので終止行を更新 // そこまでのオフセット量よりさらに小さければ更新 if( dOffDot > dCount ) dOffDot = dCount; break; // 次の行に移動 } dCount += itMozi->rdWidth; // そこまでのドット数をため込む } } if( itLnLast != itLnEnd ) itLnLast++; // 終止の次の行を示しておく if( bLnFirst ) return S_FALSE; // 選択範囲がなかったら死にます wsBuffer.clear(); // 開始行から内容を確保していく for( itLnErate = itLnFirst; itLnLast != itLnErate; itLnErate++ ) // 行サーチ { itMozi = itLnErate->vcLine.begin(); itMzEnd = itLnErate->vcLine.end(); bMzFirst = TRUE; bIsVoid = FALSE; dCount = 0; for( ; itMzEnd != itMozi; itMozi++ ) // 文字サーチ { if( CT_SELECT & itMozi->mzStyle ) // 選択状態発見 { if( bIsVoid ) // 直前まで未選択状態 { if( bMzFirst ) // 最初の空白部分であれば { dCount -= dOffDot; // オフセットする if( 0 > dCount ) dCount = 0; bMzFirst = FALSE; } // 埋めSpaceを作る・不可ならNULLが返る ptSpace = DocPaddingSpaceMake( dCount ); if( ptSpace ) { wsBuffer += ptSpace; //StringCchLength( ptSpace, STRSAFE_MAX_CCH, &cch ); //for( i = 0; cch > i; i++ ) //{ // wsBuffer += (ptSpace[i]); //} FREE(ptSpace); } } wsBuffer += itMozi->cchMozi; dCount = 0; // リセット bIsVoid = FALSE; } else { dCount += itMozi->rdWidth; // そこまでのドット数をため込む bIsVoid = TRUE; } } wsBuffer += CH_CRLFW; // 改行追加 } // この時点で、wsBufferに全体が入っているはず cch = wsBuffer.size( ) + 1; ptString = (LPTSTR)malloc( cch * sizeof(TCHAR) ); StringCchCopy( ptString, cch, wsBuffer.c_str( ) ); if( hInst ) // 実存してるならレイヤボックスへ { LayerBoxVisibalise( hInst, ptString, 0x00 ); } else // ないならクルッペボード { DocClipboardDataSet( ptString, cch * sizeof(TCHAR), D_UNI ); } FREE(ptString); return S_OK; }
/*! 内容を書き込む @param[in] hWnd ウインドウハンドル・あまり意味はない @return HRESULT 終了状態コード */ HRESULT VertScriptInsert( HWND hWnd ) { LPTSTR ptText; INT iTgtRow, iMaxRow, iMaxClm; INT iRitDot, iNeedPadd; HWND hLyrWnd; INT iX, iY; RECT rect; wstring wsBuffer; // 作った文字列を入れちゃう VTIM_ITR itVtitm; VTIM_RITR itRvsVtitm; //右からなら逆にたどる。左からなら正順。Rowを基準値にして、直前位置とのスキマは空白埋め //改行とか入れまくって一繋がりの文字列にして、ステルスレイヤで貼る。 // 縦横の大きさを求める iMaxRow = 0; iMaxClm = 0; for( itVtitm = gvcVertItem.begin(); itVtitm != gvcVertItem.end(); itVtitm++ ) { if( iMaxRow < itVtitm->iRow ) iMaxRow = itVtitm->iRow; if( iMaxClm < itVtitm->iColumn ) iMaxClm = itVtitm->iColumn; } ptText = NULL; wsBuffer.clear(); for( iTgtRow = 0; iMaxRow >= iTgtRow; iTgtRow++ ) // 文字位置を上から順番に見ていく { iRitDot = 0; if( gbLeftGo ) // 左から { for( itVtitm = gvcVertItem.begin(); itVtitm != gvcVertItem.end(); itVtitm++ ) { if( iTgtRow == itVtitm->iRow ) // 注目ROWが一致したら { iNeedPadd = itVtitm->iOffset - iRitDot; // ここまでの右端からのドット数 if( 0 > iNeedPadd ) { iNeedPadd = 0; // 重なった場合とかあり得る } ptText = DocPaddingSpaceMake( iNeedPadd ); // 0ならNULLが返る if( ptText ) // 埋め分を継ぎ足す { wsBuffer += wstring( ptText ); FREE( ptText ); } wsBuffer += itVtitm->cch; // 本命の文字を入れる iRitDot += iNeedPadd; // ここまでの埋め量と iRitDot += itVtitm->iWidth; // 使用幅を埋める } } } else { // 右から for( itRvsVtitm = gvcVertItem.rbegin(); itRvsVtitm != gvcVertItem.rend(); itRvsVtitm++ ) { if( iTgtRow == itRvsVtitm->iRow ) // 注目ROWが一致したら { iNeedPadd = itRvsVtitm->iOffset - iRitDot; // ここまでの右端からのドット数 if( 0 > iNeedPadd ) { iNeedPadd = 0; // 重なった場合とかあり得る } ptText = DocPaddingSpaceMake( iNeedPadd ); // 0ならNULLが返る if( ptText ) // 埋め分を継ぎ足す { wsBuffer += wstring( ptText ); FREE( ptText ); } wsBuffer += itRvsVtitm->cch; // 本命の文字を入れる iRitDot += iNeedPadd; // ここまでの埋め量と iRitDot += itRvsVtitm->iWidth; // 使用幅を埋める } } } wsBuffer += wstring( CH_CRLFW ); // 壱行終わったら改行 } // 挿入処理には、レイヤボックスを非表示処理で使う hLyrWnd = LayerBoxVisibalise( GetModuleHandle(NULL), wsBuffer.c_str(), 0x10 ); // レイヤの位置を変更 GetWindowRect( ghVertViewWnd, &rect ); LayerBoxPositionChange( hLyrWnd, (rect.left + gstFrmSz.x), (rect.top + gstFrmSz.y) ); // 設定によれば、空白を全部透過指定にする if( gbSpTrans ) { LayerTransparentToggle( hLyrWnd, 1 ); } // 上書きする LayerContentsImportable( hLyrWnd, IDM_LYB_OVERRIDE, &iX, &iY, D_INVISI ); ViewPosResetCaret( iX, iY ); // 終わったら閉じる DestroyWindow( hLyrWnd ); 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; }