/*! クリップボードの文字列を挿入する・いわゆる貼り付け @param[in,out] pNowDot 今のキャレットのドット位置 @param[in,out] pdLine 対象の行番号・絶対0インデックスか @param[in,out] pdMozi 今のキャレットの文字数 @param[in] bSqMode 非0強制矩形貼付・内容増やすならFlagに注意 @return 0壱行ですんだ 非0複数行に渡った */ INT DocInputFromClipboard( PINT pNowDot, PINT pdLine, PINT pdMozi, UINT bSqMode ) { LPTSTR ptString = NULL; UINT cchSize, dStyle = 0, i, j; INT dCrLf, dTop, dBtm; BOOLEAN bSelect; UINT dSqSel, iLines; // クリップボードからデータを頂く ptString = DocClipboardDataGet( &dStyle ); if( !(ptString) ) { NotifyBalloonExist( TEXT("テキストじゃないみたい。\t\n貼り付けられないよ。"), TEXT("お燐からのお知らせ"), NIIF_INFO ); return 0; } StringCchLength( ptString, STRSAFE_MAX_CCH, &cchSize ); // タブをヌく for( i = 0; cchSize > i; ) { if( CC_TAB == ptString[i] ) { for( j = i; cchSize > j; j++ ) { ptString[j] = ptString[j+1]; } cchSize--; continue; } i++; } bSelect = IsSelecting( &dSqSel ); // 選択状態であるか if( bSelect ) { DocSelRangeGet( &dTop, &dBtm ); dCrLf = DocSelectedDelete( pNowDot, pdLine, dSqSel, TRUE ); if( dCrLf ) // 処理した行以降全取っ替え { iLines = DocPageParamGet( NULL, NULL ); // 再計算も要るかも・・・ for( i = *pdLine; iLines >= i; i++ ){ ViewRedrawSetLine( i ); } } else{ ViewRedrawSetLine( *pdLine ); } } if( bSqMode ) dStyle |= D_SQUARE; // 矩形挿入として扱うか dCrLf = DocInsertString( pNowDot, pdLine, pdMozi, ptString, dStyle, TRUE ); FREE( ptString ); DocPageInfoRenew( -1, 1 ); return dCrLf; }
/*! 現在頁の末端に改行を追加する @param[in] addLine 追加する行数 @param[in] pFirst アンドゥの非0初めてのグループ 0続きの処理 @return 全体の行数 */ INT DocAdditionalLine( INT addLine, PBOOLEAN pFirst ) { UINT_PTR iLines; INT cbSize, cchMozi, i; INT dBaseDot, dBaseLine; LPTSTR ptBuffer = NULL; iLines = DocNowFilePageLineCount( ); // この頁の行数 // 追加するのは最終行の末端 dBaseLine = iLines - 1; cchMozi = CH_CRLF_CCH * addLine; // 改行の文字数+ぬるたーみねーた cbSize = (cchMozi + 1) * sizeof(TCHAR); ptBuffer = (LPTSTR)malloc( cbSize ); ZeroMemory( ptBuffer, cbSize ); for( i = 0; addLine > i; i++ ) { StringCchCat( ptBuffer, cchMozi + 1, CH_CRLFW ); ViewRedrawSetLine( dBaseLine + i ); // 再描画行を確定しておく } dBaseDot = DocLineParamGet( dBaseLine, NULL, NULL ); SqnAppendString( &(gitFileIt->vcCont.at( gixFocusPage ).stUndoLog), DO_INSERT, ptBuffer, dBaseDot, dBaseLine, *pFirst ); DocStringAdd( &dBaseDot, &dBaseLine, ptBuffer, cchMozi ); FREE( ptBuffer ); *pFirst = FALSE; return iLines; }
/*! ページ分割処理・カーソル位置の次の行から終わりまでを次の頁へ @param[in] hWnd ウインドウハンドル @param[in] hInst 実存ハンドル @param[in] iNow 今の行 @return HRESULT 終了状態コード */ HRESULT DocPageDivide( HWND hWnd, HINSTANCE hInst, INT iNow ) { INT iDivLine = iNow + 1; INT iLines, mRslt, iNewPage; // INT_PTR iTotal, iNext; ONELINE stLine; LINE_ITR itLine, itEnd; ZeroONELINE( &stLine ); //mRslt = MessageBox( hWnd, TEXT("分割しちゃったら復帰できないよ・・・\r\n本当にバラしていい?"), TEXT("確認です"), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 ); mRslt = MessageBoxCheckBox( hWnd, hInst, 1 ); if( IDNO == mRslt ){ return E_ABORT; } //分割は、アンドゥをリセットすべし<要は削除なので、リセットしなくてもいいかもだ //今の頁の該当部分を削除しちゃう iLines = DocNowFilePageLineCount( );//DocPageParamGet( NULL, NULL ); // 行数確保 if( iLines <= iDivLine ) return E_OUTOFMEMORY; // 今の頁の次に作成 //iTotal = DocNowFilePageCount( ); //iNext = gixFocusPage + 1; // 次の頁 //if( iTotal <= iNext ){ iNext = -1; } // 全頁より多いなら末端指定 iNewPage = DocPageCreate( gixFocusPage ); // 新頁 PageListInsert( iNewPage ); // ページリストビューに追加 // 空の壱行が作られてるので、削除しておく (*gitFileIt).vcCont.at( iNewPage ).ltPage.clear( ); itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin( ); std::advance( itLine, iDivLine ); // 該当行まで進める itEnd = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.end( ); // 末端位置確保 std::copy( itLine, itEnd, back_inserter( (*gitFileIt).vcCont.at( iNewPage ).ltPage ) ); (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.erase( itLine, itEnd ); SqnFreeAll( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog) ); // アンドゥログ削除 // バイト情報とかの取り直し DocPageByteCount( gitFileIt, gixFocusPage, NULL, NULL ); DocPageInfoRenew( gixFocusPage, TRUE ); DocPageByteCount( gitFileIt, iNewPage, NULL, NULL ); DocPageInfoRenew( iNewPage, FALSE ); ViewRedrawSetLine( -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; }
/*! 行頭に、文字(主に空白)を追加 @param[in] ch 追加する文字 @param[in] pXdot 今のドット位置を受けて戻す・削除に巻き込まれた対応 @param[in] dLine 今の行数 @return HRESULT 終了状態コード */ HRESULT DocTopLetterInsert( TCHAR ch, PINT pXdot, INT dLine ) { UINT_PTR iLines; INT iTop, iBottom, i, xDot = 0; BOOLEAN bFirst = TRUE, bSeled = FALSE; TRACE( TEXT("行頭空白を追加") ); // 範囲確認 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; // 選択範囲は、操作した行全体を選択状態にする for( i = iTop; iBottom >= i; i++ ) // 範囲内の各行について { // 先頭位置に文字桃得留。 xDot = DocInputLetter( 0, i, ch ); SqnAppendLetter( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_INSERT, ch, 0, i, bFirst ); bFirst = FALSE; if( bSeled ) { DocRangeSelStateToggle( -1, -1, i, 1 ); // 該当行全体を選択状態にする DocReturnSelStateToggle( i, 1 ); // 改行も選択で } DocBadSpaceCheck( i ); ViewRedrawSetLine( i ); } // キャレット位置ずれてたら適当に調整 *pXdot += xDot; DocLetterPosGetAdjust( pXdot, dLine, 0 ); // キャレット位置適当に調整 ViewDrawCaret( *pXdot, dLine, 1 ); DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! 指定行の内容を削除する・改行はそのまま @param[in] yLine 対象の行番号 @param[in] pFirst アンドゥの非0初めてのグループ 0続きの処理 @return HRESULT 終了状態コード */ HRESULT DocLineErase( INT yLine, PBOOLEAN pFirst ) { INT dLines, iMozis, i; INT_PTR cbSize, cchSize; LPTSTR ptBuffer; wstring wsString; LINE_ITR itLine; wsString.clear( ); dLines = DocNowFilePageLineCount( );//DocPageParamGet( NULL, NULL ); // 行数確認 if( dLines <= yLine ) return E_OUTOFMEMORY; // はみ出し確認 DocLineParamGet( yLine, &iMozis, NULL ); // 指定行の文字数確保 if( 0 >= iMozis ) return E_ABORT; // 文字がないならすること無い itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin(); std::advance( itLine, yLine ); for( i = 0; iMozis > i; i++ ) // 全文字を確保 { wsString += itLine->vcLine.at( i ).cchMozi; } cchSize = wsString.size( ) + 1; // NULLターミネータ分足す cbSize = cchSize * sizeof(TCHAR); // ユニコードなのでバイト数は2倍である ptBuffer = (LPTSTR)malloc( cbSize ); ZeroMemory( ptBuffer, cbSize ); StringCchCopy( ptBuffer, cchSize, wsString.c_str( ) ); SqnAppendString( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_DELETE, ptBuffer, 0, yLine, *pFirst ); *pFirst = FALSE; // 削除処理 itLine->vcLine.clear(); DocLineParamGet( yLine, NULL, NULL ); // 行内容の再計算 DocPageParamGet( NULL, NULL ); // 再計算 DocBadSpaceCheck( yLine ); // リセットに必要 ViewRedrawSetLine( yLine ); // 要らないかも return S_OK; }
/*! 現在のドット位置を含んでいる空白エリアを1ドットずらすシーケンス @param[in] vk 方向・右か左か @param[in] pXdot 今のドット位置を受けて戻す @param[in] dLine 今の行数 @return INT 非0ズレ値 0失敗 */ INT DocSpaceShiftProc( UINT vk, PINT pXdot, INT dLine ) { INT dDot, dMozi, dPreByte; // 20110720 0文字で操作するとあぼーんするので確認しておく dDot = DocLineParamGet( dLine, &dMozi, &dPreByte ); if( 0 >= dMozi ) return 0; dDot = DocSpaceDifference( vk, pXdot, dLine, TRUE ); DocLetterPosGetAdjust( pXdot, dLine, 0 ); // この中のDocLineParamGetでバイト数が計算されてる ViewRedrawSetLine( dLine ); ViewDrawCaret( *pXdot, dLine, 1 ); return dDot; }
/*! 新しいファイルを開く @param[in] hWnd 親にするウインドウハンドル @return HRESULT 終了状態コード */ HRESULT DocOpenFromNull( HWND hWnd ) { LPARAM dNumber; TCHAR atDummyName[MAX_PATH]; // 複数ファイル扱うなら、破棄は不要、新しいファイルインスタンス作って対応 // 新しいファイル置き場の準備 dNumber = DocMultiFileCreate( atDummyName ); // ファイルを新規作成するとき MultiFileTabAppend( dNumber, (*gitFileIt).atDummyName ); // ファイルの新規作成した AppTitleChange( atDummyName ); gixFocusPage = DocPageCreate( -1 ); PageListInsert( gixFocusPage ); // ページリストビューに追加 DocPageChange( 0 ); ViewRedrawSetLine( -1 ); return S_OK; }
/*! ずれ調整を実行する @param[in] pxDot 調整位置 @param[in] yLine 対象行 @return INT 調整したドット量 */ INT DocDiffAdjExec( PINT pxDot, INT yLine ) { INT dMotoDot = 0; INT dBgnDot, dEndDot, dBgnCnt, dRngCnt, iSabun, dTgtDot, nDot; UINT_PTR cchSize, cchPlus; BOOLEAN bIsSpace; LPTSTR ptPlus, ptBuffer; wstring wsDelBuf, wsAddBuf; LETR_ITR vcLtrBgn, vcLtrEnd, vcItr; LINE_ITR itLine; itLine = (*gitFileIt).vcCont.at( gixFocusPage ).ltPage.begin(); std::advance( itLine, yLine ); // 調整値の状況を確認 dTgtDot = DocLineStateCheckWithDot( *pxDot, yLine, &dBgnDot, &dEndDot, &dBgnCnt, &dRngCnt, &bIsSpace ); if( !(bIsSpace) ) { NotifyBalloonExist( TEXT("連続するスペースの部分にカーソルを当てるですぅ"), TEXT("調整不可能"), NIIF_ERROR ); return 0; } //今現在の空白幅を確認 // 対象行の長さを確認 dMotoDot = DocLineParamGet( yLine, NULL, NULL ); iSabun = gdDiffLock - dMotoDot; // 差分確認・マイナスならはみ出してる //まず全角半角で埋めて、半角が多いようならピリオド付けて再計算 dTgtDot += iSabun; // 変更後のドット数 if( 41 > dTgtDot ) // ユニコード使うなら確認しなくても大丈夫? { NotifyBalloonExist( TEXT("もう少し幅がないと調整できないですぅ"), TEXT("狭すぎ"), NIIF_ERROR ); return 0; } //埋め文字列作成 ptPlus = DocPaddingSpaceWithPeriod( dTgtDot, NULL, NULL, NULL, FALSE ); if( !(ptPlus) ) { NotifyBalloonExist( TEXT("調整出来なかったですぅ"), TEXT("自動調整失敗"), NIIF_ERROR ); return 0; } StringCchLength( ptPlus, STRSAFE_MAX_CCH, &cchPlus ); vcLtrBgn = itLine->vcLine.begin( ); vcLtrBgn += dBgnCnt; // 該当位置まで移動して vcLtrEnd = vcLtrBgn; vcLtrEnd += dRngCnt; // そのエリアの終端も確認 wsDelBuf.clear(); for( vcItr = vcLtrBgn; vcLtrEnd != vcItr; vcItr++ ){ wsDelBuf += vcItr->cchMozi; } // 該当部分を削除 itLine->vcLine.erase( vcLtrBgn, vcLtrEnd ); nDot = dBgnDot; cchSize = wsDelBuf.size( ) + 1; ptBuffer = (LPTSTR)malloc( cchSize * sizeof(TCHAR) ); StringCchCopy( ptBuffer, cchSize, wsDelBuf.c_str( ) ); SqnAppendString( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_DELETE, ptBuffer, dBgnDot, yLine, TRUE ); FREE( ptBuffer ); //ここで文字列追加 DocStringAdd( &nDot, &yLine, ptPlus, cchPlus ); SqnAppendString( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_INSERT, ptPlus, dBgnDot, yLine, FALSE ); FREE(ptPlus); //もろもろの位置合わせしておk *pxDot = nDot; DocLetterPosGetAdjust( pxDot, yLine, 0 ); ViewRedrawSetLine( yLine ); ViewDrawCaret( *pxDot, yLine, 1 ); return iSabun; }
/*! キャレット位置から、左右に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; }
/*! 行頭半角空白をユニコードに変換・ファイルコア函数 */ 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] hInst アプリの実存 @param[in] hWnd 親ウインドウハンドル・NULLで破壊処理 @return HRESULT 終了状態コード */ HRESULT DocPageNumInsert( HINSTANCE hInst, HWND hWnd ) { INT dNowPageBuffer; INT iLine, iDot; INT_PTR iRslt, maxPage, iNow; UINT ixNumber; BOOLEAN bFirst = TRUE; TCHAR atText[MAX_PATH]; PAGENUMINFO stInfo; // 今の頁を待避 dNowPageBuffer = gixFocusPage; maxPage = DocNowFilePageCount( ); // 頁数を確認 ZeroMemory( &stInfo, sizeof(PAGENUMINFO) ); stInfo.dStartNum = 1; // 設定を確認 stInfo.bInUnder = InitParamValue( INIT_LOAD, VL_PAGE_UNDER, BST_UNCHECKED ); // 頁番号を最下行に挿入するか stInfo.bOverride = InitParamValue( INIT_LOAD, VL_PAGE_OVWRITE, BST_UNCHECKED ); // 該当行の内容を削除して上書するか // 文字列フォーマット StringCchCopy( stInfo.atStyle, MAX_PATH, TEXT("%u") ); // デフォ設定 InitParamString( INIT_LOAD, VS_PAGE_FORMAT, stInfo.atStyle ); iRslt = DialogBoxParam( hInst, MAKEINTRESOURCE(IDD_PAGENUMBER_DLG), hWnd, PageNumDlgProc, (LPARAM)(&stInfo) ); if( IDOK == iRslt ) // 挿入する { #pragma message("ディレイロードしたら、頁番号挿入がおかしくなるはず") ixNumber = stInfo.dStartNum; // 開始番号について InitParamString( INIT_SAVE, VS_PAGE_FORMAT, stInfo.atStyle ); // 設定を保存 InitParamValue( INIT_SAVE, VL_PAGE_UNDER, stInfo.bInUnder ); InitParamValue( INIT_SAVE, VL_PAGE_OVWRITE, stInfo.bOverride ); for( iNow = 0; maxPage > iNow; iNow++, ixNumber++ ) { StringCchPrintf( atText, MAX_PATH, stInfo.atStyle, ixNumber ); if( NowPageInfoGet( iNow, NULL ) ) // ディレってないなら0 { // ディレイ文字列を操作するか DocDelayPageNumInsert( gitFileIt, iNow, &stInfo, atText ); // 展開する・頁が多いと重い・しなくていい //DocDelayPageLoad( gitFileIt, iNow ); } else { gixFocusPage = iNow; // 内部操作 if( stInfo.bInUnder ) // 頁最下部に挿入 { if( stInfo.bOverride ) // 該当行消して挿入である { iLine = DocPageParamGet( NULL, NULL ); iLine--; if( 0 > iLine ){ iLine = 0; } DocLineErase( iLine , &bFirst ); // 中でアンドゥ操作変換 } else { iLine = DocAdditionalLine( 1, &bFirst );// bFirst = FALSE; } } else // 壱行目に挿入 { iDot = 0; iLine = 0; if( stInfo.bOverride ) // 該当行消して挿入である { DocLineErase( 0 , &bFirst ); // 中でアンドゥ操作変換 } else { DocInsertString( &iDot, &iLine, NULL, CH_CRLFW, 0, bFirst ); bFirst = FALSE; } iLine = 0; } iDot = 0; // 頁番号の内容挿入 DocInsertString( &iDot, &iLine, NULL, atText, 0, bFirst ); bFirst = FALSE; } } // 頁元に戻す gixFocusPage = dNowPageBuffer; ViewRedrawSetLine( -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; }
/*! 行頭全角空白及びユニコード空白を削除する @param[in] pXdot 今のドット位置を受けて戻す・削除に巻き込まれた対応 @param[in] dLine 今の行数 @return HRESULT 終了状態コード */ HRESULT DocTopSpaceErase( PINT pXdot, INT dLine ) { UINT_PTR iLines; INT iTop, iBottom, i; 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("行頭空白を削除") ); // 選択範囲は、操作した行全体を選択状態にする 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( ( iswspace( ch ) && TEXT(' ') != ch ) ) { SqnAppendLetter( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_DELETE, ch, 0, i, bFirst ); bFirst = FALSE; DocIterateDelete( vcLtrItr, i ); } } if( bSeled ) { DocRangeSelStateToggle( -1, -1, i, 1 ); // 該当行全体を選択状態にする DocReturnSelStateToggle( i, 1 ); // 改行も選択で } DocBadSpaceCheck( i ); // 状態をリセット ViewRedrawSetLine( i ); } // キャレット位置ずれてたら適当に調整 *pXdot = 0; DocLetterPosGetAdjust( pXdot, dLine, 0 ); // キャレット位置適当に調整 ViewDrawCaret( *pXdot, dLine, 1 ); DocPageInfoRenew( -1, 1 ); return S_OK; }
/*! 文字列(矩形もアリ)を挿入する @param[in,out] pNowDot 今のキャレットのドット位置 @param[in,out] pdLine 対象の行番号・絶対0インデックスか @param[in,out] pdMozi 今のキャレットの文字数・NULLでもおk @param[in] ptText 挿入する文字列 @param[in] dStyle 矩形かどうか、不可視特別か @param[in] bFirst アンドゥ用・これが最初のアクションか @return 0壱行ですんだ 非0複数行に渡った */ INT DocInsertString( PINT pNowDot, PINT pdLine, PINT pdMozi, LPCTSTR ptText, UINT dStyle, BOOLEAN bFirst ) { INT dBaseDot, dBaseLine, dNeedLine; INT dCrLf, i, dLastLine; UINT_PTR cchSize; LPPOINT pstPoint; dBaseDot = *pNowDot; dBaseLine = *pdLine; dLastLine = *pdLine; if( !(ptText) ) return 0; // 挿入文字列がないなら直ぐ終わってよい StringCchLength( ptText, STRSAFE_MAX_CCH, &cchSize ); if( dStyle & D_SQUARE ) // 矩形用 { // 使う行数 dNeedLine = DocStringInfoCount( ptText, cchSize, NULL, NULL ); bFirst = DocSquareAddPreMod( *pNowDot, *pdLine, dNeedLine, bFirst ); // 中でアンドゥ追加までやる。 pstPoint = NULL; // NULL化必須 dCrLf = DocSquareAdd( pNowDot, pdLine, ptText, cchSize, &pstPoint ); // 貼付前の整形を含めて1Groupとして扱う必要がある SqnAppendSquare( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_INSERT, ptText, pstPoint, dCrLf, bFirst ); bFirst = FALSE; FREE( pstPoint ); dLastLine = *pdLine; } else { // この中で改行とか面倒見る dCrLf = DocStringAdd( pNowDot, pdLine, ptText, cchSize ); SqnAppendString( &((*gitFileIt).vcCont.at( gixFocusPage ).stUndoLog), DO_INSERT, ptText, dBaseDot, dBaseLine, bFirst ); bFirst = FALSE; dLastLine = DocPageParamGet( NULL, NULL );//再計算必要か? } if( dCrLf ) { for( i = dBaseLine; dLastLine >= i; i++ ){ ViewRedrawSetLine( i ); } } else { ViewRedrawSetLine( *pdLine ); } if( pdMozi ){ *pdMozi = DocLetterPosGetAdjust( pNowDot, *pdLine , 0 ); } // 今の文字位置を確認 // ヤバイ状態のときは操作しないようにする if( !(D_INVISI & dStyle) ) ViewDrawCaret( *pNowDot, *pdLine, TRUE ); return dCrLf; }
/*! 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] 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; }