{------------------------------- StrRecListの処理についてまとめたユニットです 2009/01/07 ・InsertLineHeadStr→Strを削除 2009/01/09 ・LineMaxLength/TabToSpaceLine/AddStringPreLineBreak /LineRightFillSpace/LineRightFillTab をIndentChangeから移動 リファクタリングしてInsertQuoteで使用する 2010/10/29 ・TabToSpaceLine/AddStringPreLineBreakをStringUnitに移動 2010/11/10 ・TrimLeftからTrimFirstへ名前変更しました。 2011/10/05(水) ・WideStrRecListUnitからStrRecListUnitにコピーして作成 --------------------------------} unit StrRecListUnit; interface uses SysUtils, //+EmptyStr StringRecordList, ConstUnit, StringUnit, Math, MathUnit, uses_end; //type TInsertLineHeadOption = (ilhoAll, ilhoNoSpaceLine, ilhoMinIndentLineOnly); //function InsertLineHead(const S, InsertStr: String; Option: TInsertLineHeadOption): String; //type TInsertTextHeadOption = (ithoAll, ithoNoSpaceLine, ithoMinIndentLineOnly); //function InsertTextHead(const S, InsertStr: String; Option: TInsertTextHeadOption): String; type TInsertStringExecType = (ieInsertLineHead, ieInsertTextHead); type TInsertStringTargetLine = (itAll, itNoSpaceLine, itMinIndentLineOnly, itSpaceLineNext); function InsertString(const S, InsertStr: String; ExecType: TInsertStringExecType; TargetLine: TInsertStringTargetLine): String; type TLineMaxLength = record Index: Integer; Length: Integer; end; {↑行の中の最大長とその位置を返すrecord} function LineMaxLength(StrList: TStringRecordList; TabCount: Integer): TLineMaxLength; function LineRightFillSpace(const S: String; TabCount, MaxLength: Integer): String; function LineRightFillTab(const S: String; TabCount, MaxLength: Integer): String; function RecStrList_IndexOfNoLineBreak(StrList: TStringRecordList; SearchStr: String; CaseCompare: TCaseCompare = ccCaseSensitive): Integer; implementation function OrValue(S1: String; S2s: array of string): Boolean; var I: Integer; begin Result := False; for I := 0 to Length(S2s) - 1 do begin if S1 = S2s[I] then begin Result := True; Exit; end; end; end; {--------------------------------------- 行頭か文字先頭に文字を追加する関数 機能: 備考: 履歴: 2012/06/04(月) ・ InsertLineHead/InsertTextHeadを統合する }//(*----------------------------------- //2012/06/04(月) コメントアウト //行頭に文字を追加 //function InsertLineHead(const S, InsertStr: String; // Option: TInsertLineHeadOption): String; //var // StrList: TStringRecordList; // i: Integer; // LineText: String; // SpaceCount: Integer; //begin // if S = EmptyStr then // begin // Result := InsertStr; // end else // begin // StrList := TStringRecordList.Create; try // StrList.Text := S; // for i:=0 to StrList.Count-1 do // begin // SpaceCount := TrimFirstCharCount(StrList[I], Space+ZenkakuSpace+TAB); // LineText := Copy(StrList[I], SpaceCount + 1, MaxInt); // if Option = ilhoNoSpaceLine then // if OrValue(LineText, [CR, LF, CRLF, '']) then continue; // // StrList.Items[i] := InsertStr + StrList.Items[i]; // end; // Result := StrList.Text; // finally StrList.Free; end; // end; //end; //文字先頭に文字を追加 //function InsertTextHead(const S, InsertStr: String; // Option: TInsertTextHeadOption): String; //type TIndentSpaceKind = (iskNone, iskSpace, iskZenkakuSpace, iskTab); //var // StrList, IndentStrList, TextStrList: TStringRecordList; // I: Integer; // InsertPosition, SpaceCount: Integer; // // LineExecuteFlag: array of Boolean; // SpaceReplaceFlag: Boolean; // // SpaceString, InsertSpace: String; //begin // if S = EmptyStr then // begin // Result := InsertStr; // end else // begin // StrList := TStringRecordList.Create; try // IndentStrList := TStringRecordList.Create; try // TextStrList := TStringRecordList.Create; try // // StrList.Text := S; // // SetLength(LineExecuteFlag, StrList.Count); // for I := 0 to Length(LineExecuteFlag) - 1 do // LineExecuteFlag[I] := True; // //// SetLength(LineIndentFlag, StrList.Count); // // {↓インデントが特定のスペースだけで構成されているかどうかを調べる} // for I:=0 to StrList.Count-1 do // begin // SpaceCount := TrimFirstCharCount(StrList[I], Space+ZenkakuSpace+TAB); // IndentStrList.Add( Copy(StrList[I], 1, SpaceCount) ); // TextStrList.Add( Copy(StrList[I], SpaceCount + 1, MaxInt) ); // {↑行Textは改行コードだけの場合もあるが、終端行の時以外は空文字ではない} // end; // SpaceString := IndentStrList.Text; // if (CheckStrInTable(SpaceString, Space) = itAllInclude) // or (CheckStrInTable(SpaceString, ZenkakuSpace) = itAllInclude) // or (CheckStrInTable(SpaceString, TAB) = itAllInclude) then // begin // SpaceReplaceFlag := False; // end else // begin // SpaceReplaceFlag := True; // end; // // {↓文字先頭を求める処理} // InsertPosition := MaxInt; // for I := 0 to StrList.Count-1 do // begin // // if SpaceReplaceFlag then // begin // IndentStrList[I] := StringsReplace(TabToSpaceLine(IndentStrList[I]), // [ZenkakuSpace], [Space+Space]); // end; // // if OrValue(TextStrList[I], [CR, LF, CRLF, '']) then continue; // {↑空行なら文字先頭計算では無視} // SpaceCount := Length(IndentStrList[I]); // // if SpaceCount < InsertPosition then // begin // InsertPosition := SpaceCount; // InsertSpace := IndentStrList[I]; // if SpaceCount = 0 then break; // end; // end; // if InsertPosition = MaxInt then // begin {↑全て空行ならこれになる} // InsertPosition := 0; // InsertSpace := ''; // end; // // {↓先頭文字位置に文字を挿入する処理} // for i:=0 to StrList.Count-1 do // begin // if Option = ithoNoSpaceLine then // if OrValue(TextStrList[I], [CR, LF, CRLF, '']) then continue; // // if Option = ithoMinIndentLineOnly then // begin // if OrValue(TextStrList[I], [CR, LF, CRLF, '']) then continue; // if InsertPosition <> Length(IndentStrList[I]) then continue; // end; // // if CheckRange(0, InsertPosition, Length(IndentStrList[I])) then // begin // StrList[I] := CopyIndex(IndentStrList[I], 0, InsertPosition) + // InsertStr + // CopyIndex(IndentStrList[I] + TextStrList[I], InsertPosition+1, MaxInt); // end else // begin // StrList[I] := InsertSpace + InsertStr + LineBreakString(LastLineBreakStyle(StrList[I])); // end; // end; // // Result := StrList.Text; // finally TextStrList.Free; end; // finally IndentStrList.Free; end; // finally StrList.Free; end; // end; //end; function InsertString(const S, InsertStr: String; ExecType: TInsertStringExecType; TargetLine: TInsertStringTargetLine): String; type TIndentSpaceKind = (iskNone, iskSpace, iskZenkakuSpace, iskTab); var StrList, IndentStrList, TextStrList: TStringRecordList; I: Integer; InsertPosition, SpaceCount: Integer; LineExecuteFlag: array of Boolean; SpaceReplaceFlag: Boolean; SpaceString, InsertSpace: String; SpaceLineFlag: Boolean; begin if S = EmptyStr then begin Result := InsertStr; end else begin StrList := TStringRecordList.Create; try IndentStrList := TStringRecordList.Create; try TextStrList := TStringRecordList.Create; try {↑ StrList:文字列リスト IndentStrList:行頭スペースインデントだけの文字列リスト TextStrList:行頭スペースインデントを除いた文字列リスト} StrList.Text := S; SetLength(LineExecuteFlag, StrList.Count); for I := 0 to Length(LineExecuteFlag) - 1 do LineExecuteFlag[I] := True; // SetLength(LineIndentFlag, StrList.Count); {↓インデントが特定のスペースだけで構成されているかどうかを調べる} for I:=0 to StrList.Count-1 do begin SpaceCount := TrimFirstCharCount(StrList[I], Space+ZenkakuSpace+TAB); IndentStrList.Add( Copy(StrList[I], 1, SpaceCount) ); TextStrList.Add( Copy(StrList[I], SpaceCount + 1, MaxInt) ); {↑行Textは改行コードだけの場合もあるが、終端行の時以外は空文字ではない} end; SpaceString := IndentStrList.Text; if (CheckStrInTable(SpaceString, Space) = itAllInclude) or (CheckStrInTable(SpaceString, ZenkakuSpace) = itAllInclude) or (CheckStrInTable(SpaceString, TAB) = itAllInclude) then begin SpaceReplaceFlag := False; end else begin SpaceReplaceFlag := True; end; {↓文字先頭を求める処理} InsertPosition := MaxInt; for I := 0 to StrList.Count-1 do begin if SpaceReplaceFlag then begin IndentStrList[I] := StringsReplace(TabToSpaceLine(IndentStrList[I]), [ZenkakuSpace], [Space+Space]); end; if OrValue(TextStrList[I], [CR, LF, CRLF, '']) then continue; {↑空行なら文字先頭計算では無視} SpaceCount := Length(IndentStrList[I]); if SpaceCount < InsertPosition then begin InsertPosition := SpaceCount; InsertSpace := IndentStrList[I]; if SpaceCount = 0 then break; end; end; if InsertPosition = MaxInt then begin {↑全て空行ならこれになる} InsertPosition := 0; InsertSpace := ''; end; {↓文字を挿入する処理} SpaceLineFlag := True; for i:=0 to StrList.Count-1 do begin if TargetLine = itNoSpaceLine then if OrValue(TextStrList[I], [CR, LF, CRLF, '']) then Continue; if TargetLine = itMinIndentLineOnly then begin if OrValue(TextStrList[I], [CR, LF, CRLF, '']) then Continue; if InsertPosition <> Length(IndentStrList[I]) then Continue; end; if TargetLine = itSpaceLineNext then begin if OrValue(TextStrList[I], [CR, LF, CRLF, '']) then begin SpaceLineFlag := True; Continue; //空白行の場合は処理しない end else begin if SpaceLineFlag = False then begin Continue; end; //連続して空白行じゃないならContinue //空白行の後に空白行なら処理続行 SpaceLineFlag := False; end; end; case ExecType of ieInsertLineHead: //行頭に挿入 begin StrList[I] := InsertStr + StrList[I]; end; ieInsertTextHead: //文字先頭に挿入 begin if CheckRange(0, InsertPosition, Length(IndentStrList[I])) then begin StrList[I] := CopyIndex(IndentStrList[I], 0, InsertPosition) + InsertStr + CopyIndex(IndentStrList[I] + TextStrList[I], InsertPosition+1, MaxInt); end else begin StrList[I] := InsertSpace + InsertStr + LineBreakString(LastLineBreakStyle(StrList[I])); end; end; end; end; Result := StrList.Text; finally TextStrList.Free; end; finally IndentStrList.Free; end; finally StrList.Free; end; end; end; //------------------------------------*) {------------------------------- // 複数行の中から一番長い行の文字Byte数を返す関数 機能: 改行コードは含まない文字列長を返す RecordListの内容が一行もなければ Index=-1,Length=0を返す 備考: 実装上、リストの1行に [ABC\r\nCDF]等が入っている場合は対応不可能 [ABC\r\n]や[ABC]だけが入っているものに限り動作する 履歴: 2009/01/09(金) 00:58 //--▼----------------------▽--} function LineMaxLength(StrList: TStringRecordList; TabCount: Integer): TLineMaxLength; var i, j: Integer; LineLength: Integer; LineAnsiStr: String; begin Result.Index := -1; Result.Length := 0; for i := 0 to StrList.Count-1 do begin LineLength := 0; LineAnsiStr := TabToSpaceLine(StrList.Items[i]); {↑タブの文字数計算はスペースに変換しておくから大丈夫} j := 1; while j <= Length(LineAnsiStr) do begin if LineAnsiStr[j] in [CR, LF] then begin break; end else begin Inc(LineLength); end; Inc(j) end; if Result.Length < LineLength then begin Result.Index := i; Result.Length := LineLength; end; end; end; //--△----------------------▲-- {------------------------------- // 行文字列の右側を空白で埋める 備考: Sには行文字列、つまり [ABC\r\n]というような文字列がくるとする。 履歴: 2009/01/09(金) 00:58 //--▼----------------------▽--} function LineRightFillSpace(const S: String; TabCount, MaxLength: Integer): String; var IncrementCount: Integer; begin Result := S; ExcludeLineBreakProc(Result); IncrementCount := MaxLength - Length(AnsiString(TabToSpaceLine(Result))); Result := AddStringPreLineBreak(S, StringOfChar(' ', IncrementCount) ); end; //切り上げ除算 function PlusDiv(A, B: Integer): Integer; begin Result := A div B; if (A mod B)<>0 then Inc(Result); end; function LineRightFillTab(const S: String; TabCount, MaxLength: Integer): String; var IncrementCount: Integer; begin Result := S; ExcludeLineBreakProc(Result); IncrementCount := PlusDiv( (MaxLength - Length(AnsiString(TabToSpaceLine(Result)))), TabCount ); Result := AddStringPreLineBreak(S, StringOfChar(TAB, IncrementCount) ); end; //--△----------------------▲-- // {--------------------------------------- RecordStrListの改行を無視したIndexOf 機能: 備考: 履歴: 2010/10/07(木) ・ 作成 }//(*----------------------------------- function RecStrList_IndexOfNoLineBreak(StrList: TStringRecordList; SearchStr: String; CaseCompare: TCaseCompare = ccCaseSensitive): Integer; var I: Integer; begin Result := -1; ExcludeLineBreakProc(SearchStr); case CaseCompare of ccCaseSensitive: begin for I := 0 to StrList.Count - 1 do begin if SearchStr = ExcludeLineBreak(StrList[I]) then begin Result := I; Break; end; end; end; ccIgnoreCase: begin SearchStr := UpperCase(SearchStr); for I := 0 to StrList.Count - 1 do begin if SearchStr = UpperCase( ExcludeLineBreak(StrList[I]) ) then begin Result := I; Break; end; end; end; end; end; //------------------------------------*) end.