{------------------------------- WideStrRecListの処理についてまとめたユニットです 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へ名前変更しました。 --------------------------------} unit WideStrRecListUnit; interface uses SysUtils, //+EmptyStr WideStringRecordList, ConstUnit, StringUnit, Math, MathUnit, uses_end; type TInsertLineHeadOption = (ilhoAll, ilhoNoSpaceLine); function InsertLineHead(const S, InsertStr: WideString; Option: TInsertLineHeadOption): WideString; type TInsertTextHeadOption = (ithoAll, ithoNoSpaceLine, ithoMinIndentLineOnly); function InsertTextHead(const S, InsertStr: WideString; Option: TInsertTextHeadOption): WideString; type TLineMaxLength = record Index: Integer; Length: Integer; end; {↑行の中の最大長とその位置を返すrecord} function LineMaxLength(StrList: TWideStringRecordList; TabCount: Integer): TLineMaxLength; function LineRightFillSpace(const S: WideString; TabCount, MaxLength: Integer): WideString; function LineRightFillTab(const S: WideString; TabCount, MaxLength: Integer): WideString; function WideRecStrList_IndexOfNoLineBreak(StrList: TWideStringRecordList; SearchStr: WideString; 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; //行頭に文字を追加 function InsertLineHead(const S, InsertStr: WideString; Option: TInsertLineHeadOption): WideString; var StrList: TWideStringRecordList; i: Integer; LineText: WideString; SpaceCount: Integer; begin if S = EmptyStr then begin Result := InsertStr; end else begin StrList := TWideStringRecordList.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: WideString; Option: TInsertTextHeadOption): WideString; type TIndentSpaceKind = (iskNone, iskSpace, iskZenkakuSpace, iskTab); var StrList, IndentStrList, TextStrList: TWideStringRecordList; I: Integer; InsertPosition, SpaceCount: Integer; LineExecuteFlag: array of Boolean; SpaceReplaceFlag: Boolean; SpaceString, InsertSpace: WideString; begin if S = EmptyStr then begin Result := InsertStr; end else begin StrList := TWideStringRecordList.Create; try IndentStrList := TWideStringRecordList.Create; try TextStrList := TWideStringRecordList.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; {------------------------------- // 複数行の中から一番長い行の文字Byte数を返す関数 機能: 改行コードは含まない文字列長を返す RecordListの内容が一行もなければ Index=-1,Length=0を返す 備考: 実装上、リストの1行に [ABC\r\nCDF]等が入っている場合は対応不可能 [ABC\r\n]や[ABC]だけが入っているものに限り動作する 履歴: 2009/01/09(金) 00:58 //--▼----------------------▽--} function LineMaxLength(StrList: TWideStringRecordList; 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: WideString; TabCount, MaxLength: Integer): WideString; 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: WideString; TabCount, MaxLength: Integer): WideString; var IncrementCount: Integer; begin Result := S; ExcludeLineBreakProc(Result); IncrementCount := PlusDiv( (MaxLength - Length(AnsiString(TabToSpaceLine(Result)))), TabCount ); Result := AddStringPreLineBreak(S, StringOfChar(TAB, IncrementCount) ); end; //--△----------------------▲-- // {--------------------------------------- WideRecordStrListの改行を無視したIndexOf 機能: 備考: 履歴: 2010/10/07(木) ・ 作成 }//(*----------------------------------- function WideRecStrList_IndexOfNoLineBreak(StrList: TWideStringRecordList; SearchStr: WideString; 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.