I have Grid with enabled columns moving, and code:
type
TRec = record
Col0,
Col1,
Col2: string;
end;
var
Data: TArray<TRec>;
procedure TFormMain.GridGetValue(Sender: TObject; const Col, Row: Integer; var Value: TValue);
begin
case Col of
0: Value := Data[Row].Col0;
1: Value := Data[Row].Col1;
2: Value := Data[Row].Col2;
end;
end;
When column is moved this OnGetValue code works incorrectly (shown columns data on the previous positions). How to fix this? Should I use OnColumnMoved event and remember new columns position manually?
Ok, this is my own answer:
We should add helper function to our TRec for reading fields by index:
type
TRec = record
Col0,
Col1,
Col2: string;
function GetField(AIndex: Integer): string;
end;
function TRec.GetField(AIndex: Integer): string;
begin
case AIndex of
0: Result := Col0;
1: Result := Col1;
2: Result := Col2;
else
Result := '';
end;
end;
Also 2 functions to save and restore TGrid columns using Ini file:
type
TColumnData = record
Pos: UInt8;
Visible: Boolean;
Width: UInt16;
end;
procedure LoadColumns(AGrid: TGrid; const ASection, AIdent: string);
var
I, J, ColsSize: Integer;
A: TArray<TColumnData>;
Col: TColumn;
begin
for I := 0 to AGrid.ColumnCount - 1 do
AGrid.Columns[I].Tag := I;
SetLength(A, AGrid.ColumnCount);
ColsSize := AGrid.ColumnCount*SizeOf(TColumnData);
if ReadIni(<FileName>, ASection, AIdent, (#A[0])^, ColsSize) = ColsSize then
for J := 0 to AGrid.ColumnCount - 1 do begin
for I := 0 to AGrid.ColumnCount - 1 do begin
Col := AGrid.Columns[I];
if Col.Tag = A[J].Pos then begin
Col.Index := J;
Col.Visible := A[J].Visible;
Col.Width := A[J].Width;
end;
end;
end;
end;
procedure SaveColumns(AGrid: TGrid; const ASection, AIdent: string);
var
I, ColsSize: Integer;
A: TArray<TColumnData>;
Col: TColumn;
begin
SetLength(A, AGrid.ColumnCount);
ColsSize := AGrid.ColumnCount*SizeOf(TColumnData);
for I := 0 to AGrid.ColumnCount - 1 do begin
Col := AGrid.Columns[I];
A[I].Pos := Col.Tag;
A[I].Visible := Col.Visible;
A[I].Width := Round(Col.Width);
end;
WriteIni(<FileName>, ASection, AIdent, (#A[0])^, ColsSize);
end;
Now we should call LoadColumns (which is also initialize Tag fields for Columns) from OnFormCreate and SaveColumns from OnFormDestroy. And finally OnGetValue code:
var
Data: TArray<TRec>;
procedure TFormMain.GridGetValue(Sender: TObject; const Col, Row: Integer; var Value: TValue);
begin
Value := Data[Row].GetField((Sender as TGrid).Columns[Col].Tag);
end;
Related
From the query below
Select FIELD1,FIELD2,FIELD3,FIELD4 FROM MyTable Order By FIELD1,FIELD2,FIELD3,FIELD4 Group By FIELD1,FIELD2,FIELD3,FIELD4
I have a recordset like this:
I need to show data in a treeview like this:
I'm stuck with the code below.
var
Node: TTreeNode;
RootLevelCount: Integer;
X: Integer;
CurrentTextField: String;
MyTreeNodeText: array [0..10] of String;
begin
RootLevelCount := 4;
while not dm1.Q1.Eof do
begin
for X := 0 to RootLevelCount do
begin
CurrentTextField:=dm1.Q1.Fields[x].AsString;
if CurrentTextField='' then CurrentTextField := 'Level '+IntToStr(x);
if MyTreeNodeText[x]<>CurrentTextField then
begin
MyTreeNodeText[X]:=CurrentTextField;
if x=0 then
begin
Node:=tree.Items.AddFirst(Node, CurrentTextField);
end else
begin
node:=tree.Items.AddChild(node.Parent, CurrentTextField);
end;
end else
begin
node.GetNext;
end;
end;
dm1.Q1.Next;
end;
The result I have is the following and it's not I want:
After a good lunch, my mind has reborn then I found the solution.
var
Node: TTreeNode;
RootLevelCount: Integer;
X,X1: Integer;
CurrentTextField: String;
MyTreeNodeText: array [0..10] of String;
MyTreeNode: array [0..10] of TTreeNode;
begin
RootLevelCount := 4; //Number of fields that you want to show in the treeview
while not dm1.Q1.Eof do
begin
ROW_ID:=dm1.Q1.FieldByName('ROW_ID').AsString;
for X := 0 to RootLevelCount-1 do
begin
CurrentTextField:=dm1.Q1.Fields[4+x].AsString;
if CurrentTextField='' then CurrentTextField := 'Level '+IntToStr(x);
if MyTreeNodeText[x]<>CurrentTextField then
begin
MyTreeNodeText[X]:=CurrentTextField;
for X1 := x+1 to RootLevelCount-1 do
MyTreeNodeText[x1]:='';
if x=0 then
begin
Node:=tree.Items.Add(nil, CurrentTextField);
TMyTreeNode(Node).Indice:=StrToInt(ROW_ID);
MyTreeNode[x]:=node;
end else
begin
node:=tree.Items.AddChild(MyTreeNode[x-1], CurrentTextField);
TMyTreeNode(Node).Indice:=StrToInt(ROW_ID);
MyTreeNode[x]:=node;
end;
end;
end;
MyTreeNodeText[RootLevelCount]:='';
dm1.Q1.Next;
end;
then the result is the following:
I want to fetch the entire line string (UTF8) and want to do operation on the line string. I have tried following code. but if we are having multibyte characters am not able to do this.
J:=1;
CurrentRowStr :='';
while True do
begin
//detect end of line
Buffer.EditPosition.Move(Changes[I].FLine,J);
CurrentRowStr := CurrentRowStr + Buffer.EditPosition.Character ;
J := J+1;
end;
CurrentRowStr := Buffer.EditPosition.Read(J-1);
if anyone can help me to get particular line string using OpenToolsAPI, it would be great help.
You can use a IOTAEditReader to get entire lines. The following code is from my Conversion Helper Package. Most of this revolves around the GetCurrentLineParams function:
function GetEditor: IOTASourceEditor;
var
ModuleServices: IOTAModuleServices;
Module: IOTAModule;
I: Integer;
begin
ModuleServices := BorlandIDEServices as IOTAModuleServices;
Module := ModuleServices.CurrentModule;
for I := 0 to Module.GetModuleFileCount - 1 do
if Supports(Module.GetModuleFileEditor(I), IOTASourceEditor, Result) then
Break;
end;
function GetLineAtCharPos(const Editor: IOTASourceEditor;
const EditView: IOTAEditView; CharPos: TOTACharPos): string;
var
EditReader: IOTAEditReader;
Start, Len: Integer;
Res: AnsiString;
begin
CharPos.CharIndex := 0;
Start := EditView.CharPosToPos(CharPos);
Inc(CharPos.Line);
Len := EditView.CharPosToPos(CharPos) - Start;
if Len > 0 then
begin
SetLength(Res, Len);
EditReader := Editor.CreateReader;
EditReader.GetText(Start, PAnsiChar(Res), Len);
Result := string(PAnsiChar(Res));
end;
end;
function GetCurrentLine(const Editor: IOTASourceEditor;
var BufferStart, Index: LongInt): string;
var
BufferLength: LongInt;
EditReader: IOTAEditReader;
Res: AnsiString;
begin
GetCurrentLineParams(Editor, BufferStart, BufferLength, Index);
SetLength(Res, BufferLength);
EditReader := Editor.CreateReader;
EditReader.GetText(BufferStart, PAnsiChar(Res), BufferLength);
Result := string(PAnsiChar(Res)); // just to be sure.
end;
function GetCurrentCharPos(const Editor: IOTASourceEditor; out EditView:
IOTAEditView): TOTACharPos;
var
CursorPos: TOTAEditPos;
begin
EditView := Editor.GetEditView(0);
CursorPos := EditView.CursorPos;
EditView.ConvertPos(True, CursorPos, Result);
end;
procedure GetCurrentLineParams(const Editor: IOTASourceEditor;
var Start, Length, Index: Integer);
var
EditView: IOTAEditView;
CharPos: TOTACharPos;
begin
CharPos := GetCurrentCharPos(Editor, EditView);
Index := CharPos.CharIndex + 1;
CharPos.CharIndex := 0;
Start := EditView.CharPosToPos(CharPos);
Inc(CharPos.Line);
Length := EditView.CharPosToPos(CharPos) - Start;
end;
function GetCurrentLineStart(const Editor: IOTASourceEditor): Integer;
var
L, I: Integer;
begin
GetCurrentLineParams(Editor, Result, L, I);
end;
function GetCurrentLineLength(const Editor: IOTASourceEditor): Integer;
var
S, I: Integer;
begin
GetCurrentLineParams(Editor, S, Result, I);
end;
in matrix(StringGrid) NxM sort the elements of each row in nondecreasing order?
var
Form1: TForm1;
n,m:integer;
I:integer;
implementation
{$R *.dfm}
procedure TForm1.btNapraviClick(Sender: TObject);
begin
with StringGrid1 do
begin
n:=StrToInt(edN.text)+1;
m:=StrToInt(edM.text)+1;
ColCount:=n;
RowCount:=m;
for I:=0 to n-1 do Cells[I,0]:=IntToStr(I);
for I:=1 to m-1 do Cells[0,I]:=IntToStr(I);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var J,P,K:integer;
begin
with StringGrid1 do
begin
for I:=1 to n do
for J:=1 to m-1 do
for K:=J+1 to m do
begin
if StrToInt(Cells[I,J]) <= StrToInt(Cells[I,K]) then
begin
P:=StrToInt(Cells[I,J]);
Cells[I,J]:=(Cells[I,K]);
Cells[I,K]:=IntToStr(P);
end;
end;
end;
end;
Each Row in a StringGrid decends from TStrings, so you can assign a row to a TStringList and do a custom sort on that one.
Here is some source code:
First I fill the grid with Random data:
procedure TForm60.FormCreate(Sender: TObject);
var
i, j: Integer;
begin
Randomize;
with StringGrid1 do
begin
ColCount := 10;
RowCount := 10;
for i := 0 to ColCount - 1 do
for j := 0 to RowCount - 1 do
Cells[i, j] := IntToStr(Random(5000));
end;
end;
Then at Button1.Click I sort each row in descending order:
function StringListSortCompare(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := StrToIntDef(List[Index2], 0) - StrToIntDef(List[Index1], 0)
end;
procedure TForm60.Button1Click(Sender: TObject);
var
i: Integer;
Buffer: TStringList;
begin
Buffer := TStringList.Create;
for i := 0 to StringGrid1.RowCount - 1 do
begin
Buffer.Assign(StringGrid1.Rows[i]);
Buffer.CustomSort(#StringListSortCompare);
StringGrid1.Rows[i].Assign(Buffer);
end;
FreeAndNil(Buffer);
end;
Since I subStract the integer value of List[Index2] from List[Index1] the list becomes sorted descending.
And the result:
Before
After
After reading your question again I'm not sure if you by "nondecreasing order" mean increasing order. If so just implement the sort procedure like this:
function StringListSortCompare(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := StrToIntDef(List[Index1], 0) - StrToIntDef(List[Index2], 0)
end;
I know the only way to do that is to remap keys with regedit.
Have someone has done that with delphi ? (disable it and enable it again)
http://www.northcode.com/blog.php/2007/07/25/Securing-Windows-For-Use-As-A-Kiosk
The information in the article would translate to Delphi as follows:
uses
Registry;
const
DisableScancodes: packed array[0..11] of DWORD = (
$00000000, // version = 0
$00000000, // flags = 0
$00000009, // # of mappings = 9
$E05B0000, // disable Windows key
$E05C0000, // disable Windows key
$E05D0000, // disable Windows menu key
$00440000, // disable F10 key
$001D0000, // disable Left Ctrl key
$00380000, // disable Left Alt key
$E01D0000, // disable Right Ctrl key
$E0380000, // disable Right Alt key
$00000000 // end of list
);
var
Reg: TRegistry;
begin
Reg := TRegistry.Create(KEY_WRITE);
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Keyboard Layout', True) then
begin
try
// to enable the mapping
Reg.WriteBinaryData('Scancode Map', DisableScancodes, SizeOf(DisableScancodes));
// to disable the mapping
Reg.DeleteValue('Scancode Map');
finally
Reg.CloseKey;
end;
end;
finally
Reg.Free;
end;
end;
If you need to be more dynamic about which scancodes you enable/disable, you will have to use TRegistry.ReadBinaryData() to read the current Scancode Map value (if it exists), modify it as needed, and then save the changes using TRegistry.WriteBinaryData(). Try something like this:
unit ScanCodeMap;
interface
type
TMappedScancode = record
Scancode: WORD;
MappedTo: WORD;
end;
procedure AddScancodeMappings(const Values: array of TMappedScancode);
procedure AddScancodeMapping(const Value: TMappedScancode);
procedure AddScancodeMapping(Scancode, MappedTo: WORD);
procedure RemoveScancodeMappings(const Scancodes: array of WORD);
procedure RemoveScancodeMapping(Scancode: WORD);
procedure DisableScancodes(Scancodes: array of WORD);
procedure DisableScancode(Scancode: WORD);
implementation
uses
Windows, Registry;
type
PScancodeMapHdr = ^TScancodeMapHdr;
TScancodeMapHdr = packed record
Version: DWORD;
Flags: DWORD;
NumMappings: DWORD;
end;
TScancodeMap = record
Version: DWORD;
Flags: DWORD;
Mappings: array of TMappedScancode;
end;
procedure AddScancodesToMap(var Map: TScancodeMap; const Values: array of TMappedScancode);
var
I, J, Idx: Integer;
begin
for I := 0 to High(Values) do
begin
Idx := -1;
for J := 0 to High(Map.Mappings) do
begin
if Map.Mappings[J].Scancode = Values[I].Scancode then
begin
Idx := J;
Break;
end;
end;
if Idx = -1 then
begin
SetLength(Map.Mappings, Length(Map.Mappings)+1);
Idx := High(Map.Mappings);
end;
Map.Mappings[Idx].MappedTo := Values[I].MappedTo;
end;
end;
procedure RemoveScancodesFromMap(var Map: TScancodeMap; const Scancodes: array of WORD);
var
I, J: Integer;
begin
for I := 0 to High(Scancodes) do
begin
for J := 0 to High(Map.Mappings) do
begin
if Map.Mappings[J].Scancode = Scancodes[I] then
begin
if J < High(Map.Mappings) then
Move(Map.Mappings[J+1], Map.Mappings[J], (High(Mappings)-J) * SizeOf(TMappedScancode));
SetLength(Map.Mappings, Length(Map.Mappings)-1);
Break;
end;
end;
end;
end;
procedure WriteScanCodeMap(const Map: TScancodeMap);
var
Reg: TRegistry;
Data: array of Byte;
Tmp: PByte;
Hdr: PScancodeMapHdr;
I: Integer;
begin
if Length(Map.Mappings) > 0 then
begin
SetLength(Data, sizeof(TScancodeMapHdr) + (Length(Map.Mappings) + 1) * SizeOf(DWORD));
Tmp := PByte(Data);
Hdr := PScancodeMapHdr(Tmp);
Hdr.Version := Map.Version;
Hdr.Flags := Map.Flags;
Hdr.NumMappings := Length(Map.Mappings) + 1;
Inc(Tmp, SizeOf(TScancodeMapHdr));
for I := 0 to High(Map.Mappings) do
begin
PDWORD(Tmp)^ := (DWORD(Map.Mappings[0].Scancode) shr 16) or DWORD(Map.Mappings[0].MappedTo);
Inc(Tmp, SizeOf(DWORD));
end;
PDWORD(Tmp)^ := 0;
end;
Reg := TRegistry.Create(KEY_WRITE);
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Keyboard Layout', True) then
begin
try
if Length(Data) > 0 then
Reg.WriteBinaryData('Scancode Map', Data[0], Length(Data))
else
Reg.DeleteValue('Scancode Map');
finally
Reg.CloseKey;
end;
end;
finally
Reg.Free;
end;
end;
procedure ReadScanCodeMap(var Map: TScancodeMap);
var
Reg: TRegistry;
Size: Integer;
Data: array of Byte;
Tmp: PByte;
Hdr: PScancodeMapHdr;
I: Integer;
begin
Map.Version := 0;
Map.Flags := 0;
SetLength(Map.Mappings, 0);
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Control\Keyboard Layout') then
begin
try
Size := Reg.GetDataSize('Scancode Map');
if Size > SizeOf(TScancodeMapHdr) then
begin
SetLength(Data, Size);
Reg.ReadBinaryData('Scancode Map', Data[0], Size);
Tmp := PByte(Data);
Hdr := PScancodeMapHdr(Tmp);
Map.Version := Hdr.Version;
Map.Flags := Hdr.Flags;
Inc(Tmp, SizeOf(TScancodeMapHdr));
if Hdr.NumMappings > 1 then
begin
SetLength(Map.Mappings, Hdr.NumMappings-1);
for I := 0 to High(Map.Mappings) do
begin
Map.Mappings[I].Scancode := HIWORD(PDWORD(Tmp)^);
Map.Mappings[I].MappedTo := LOWORD(PDWORD(Tmp)^);
end;
end;
end;
finally
Reg.CloseKey;
end;
end;
finally
Reg.Free;
end;
end;
procedure AddScancodeMappings(const Values: array of TMappedScancode);
var
Map: TScancodeMap;
begin
ReadScanCodeMap(Map);
AddScancodesToMap(Map, Values);
WriteScanCodeMap(Map);
end;
procedure AddScancodeMapping(const Value: TMappedScancode);
begin
AddScancodeMappings([Value]);
end;
procedure AddScancodeMapping(Scancode, MappedTo: WORD);
var
Value: array[0..0] of TMappedScancode;
begin
Value[0].Scancode := Scancode;
Value[0].MappedTo := MappedTo;
AddScancodeMappings([Value]);
end;
procedure RemoveScancodeMappings(const Scancodes: array of WORD);
var
Map: TScancodeMap;
begin
ReadScanCodeMap(Map);
RemoveScancodesFromMap(Map, Scancodes);
WriteScanCodeMap(Map);
end;
procedure RemoveScancodeMapping(Scancode: WORD);
begin
RemoveScancodeMappings([Scancode]);
end;
procedure DisableScancodes(Scancodes: array of WORD);
var
Values: array of TMappedScancode;
I: Integer;
begin
SetLength(Values, Length(Scancodes));
for I := 0 to High(Mappings) do
begin
Values[I].Scancode := Scancodes[I];
Values[I].MappedTo := $0000;
end;
AddScancodeMappings(Values);
end;
procedure DisableScancode(Scancode: WORD);
begin
AddScancodeMapping(Scancode, $0000);
end;
end.
Then you can do this:
uses
ScanCodeMap;
const
Scancodes: packed array[0..7] of WORD = (
$E05B, // Windows key
$E05C, // Windows key
$E05D, // Windows menu key
$0044, // F10 key
$001D, // Left Ctrl key
$0038, // Left Alt key
$E01D, // Right Ctrl key
$E038 // Right Alt key
);
procedure DisableCtrlAltDel;
begin
DisableScancodes(Scancodes);
end;
procedure EnableCtrlAltDel;
begin
RemoveScancodeMappings(Scancodes);
end;
So I have list of data that may contain different charters:
1dAAbt54
agFlE9dA
1295RTdd
First line data contains: 1d, AA, bt, 54. All I need is function that gives me the data of given index. Example: data of index 6 is Fl (Line - 2, Index in line is 2). Every line lenght is 8 and data length is 2;
How can I make such function in Delphi?
The result function should be something like this:
procedure (DataList: TStringList; DataIndex: Integer; var LineIndex: Integer; var PosInLine: Integer);
begin
//do the algorithm
end;
Sorry for my bad english...
Answer to the first version of your question
The following is an answer to the first version of your question (before you edited it):
function GetIndexOfInteger(DataList: TStringList; DataIndex: Integer;
out LineIndex: Integer; out PosInLine: Integer): boolean;
var
x, y: Integer;
InNum: boolean;
NumStart: integer;
ValIndex: integer;
begin
result := false;
for y := 0 to DataList.Count - 1 do
begin
InNum := false;
ValIndex := 0;
for x := 1 to Length(DataList[y]) do
begin
if (DataList[y][x] <> chr(32)) and not InNum then
begin
NumStart := x;
InNum := true;
inc(ValIndex);
end;
if InNum and ((DataList[y][x] = chr(32)) or
(x = Length(DataList[y]))) then
begin
if StrToInt(Copy(DataList[y], NumStart, x - NumStart +
IfThen(x = Length(DataList[y]), 1))) = DataIndex then
begin
LineIndex := y + 1;
PosInLine := ValIndex;
result := true; // Roberts is on D7.
Exit; //
end;
InNum := false;
Continue;
end;
end;
end;
end;
Try it:
procedure TForm4.FormCreate(Sender: TObject);
var
SR: TStringList;
line, col: integer;
begin
SR := TStringList.Create;
SR.Add('1 2 3');
SR.Add('4 5 6');
SR.Add('7 8 9');
SR.Add('10 11 12 13');
if GetIndexOfInteger(SR, 13, line, col) then
ShowMessage(Format('%d, %d', [line,col]));
end;
Answer to the second version of your question
(And this is so easy you could've done it yourself! :)
function GetIndexOfItemInListOfPairs(DataList: TStringList; Data: String; out LineIndex: Integer; out PosInLine: Integer): boolean;
var
x, y: Integer;
begin
result := false;
for y := 0 to DataList.Count - 1 do
for x := 0 to Length(DataList[y]) div 2 - 1 do
if Copy(DataList[y], 2*x + 1, 2) = Data then
begin
LineIndex := y + 1;
PosInLine := x + 1;
Exit(true);
end;
end;
procedure TForm4.FormCreate(Sender: TObject);
var
SR: TStringList;
line,col:integer;
begin
SR := TStringList.Create;
SR.Add('1dAAbt54');
SR.Add('agFlE9dA');
SR.Add('1295RTdd');
if GetIndexOfItemInListOfPairs(SR, 'RT', line, col) then
ShowMessage(Format('%d, %d', [line,col]));
end;
Answer to the third version of your question
procedure TForm4.FormCreate(Sender: TObject);
var
RowIndex, ColIndex: Word;
begin
DivMod(6 {index} - 1, 4 {items per row}, RowIndex, ColIndex);
inc(RowIndex);
inc(ColIndex);
ShowMessageFmt('%d, %d', [RowIndex, ColIndex]);
end;
How about ...
procedure Search( DataList: TStringList; DataIndex: Integer; var LineIndex: Integer; var PosInLine: Integer);
var
j, LineLen: integer;
Line: string;
begin
LineIndex := 0;
PosInLine := 0;
for j := 0 to DataList.Count - 1 do
begin
Line := DataList[j];
Inc( LineIndex);
LineLen := Length( Line) div 2;
if DataIndex >= LineLen then
begin
Dec( DataIndex, LineLen);
continue
end;
PosInLine := LineLen;
break
end;
if PosInLine = 0 then // No find
LineIndex := 0
end;
Oops. The question has been changed completely. Here is the procedure for the question v 1.0 :)
procedure FindIndex(Data:TStringList; Index:integer;var LineIndex,PosInLine:Integer);
var i:integer;
CurrentStr:String;
StrToFind:String;
begin
LineIndex:=0;
PosInLine:=0;
StrToFind:=intToStr(Index)+' ';
for i:=0 to Data.Count-1 do
begin
CurrentStr:=' '+Data.Strings[i]+' ';
IF POS(' '+StrToFind,CurrentStr)>0 then
begin
LineIndex:=i+1;
//now we need to find PosInLine
PosInLine:=1;
repeat
CurrentStr:=Trim(CurrentStr)+' ';
IF Pos(StrToFind,CurrentStr)=1 then exit; //we found it
CurrentStr:=copy(CurrentStr,POS(' ',CurrentStr),length(CurrentStr));
inc(PosInLine);
until (CurrentStr='');
exit;
end;
end;
end;
Tested with this code
var T:TStringList;
Li,Pi:integer;
i:integer;
begin
T:=TStringList.Create();
T.Add('1 2 3');
T.Add(' 4 5 6');
T.Add('7 8 9');
T.Add('10 11 12 ');
for i:=0 to 13 do
begin
FindIndex(T,i,Li,Pi);
Memo1.Lines.Add(IntToStr(i)+':'+IntToStr(Li)+'-'+IntToStr(Pi))
end;
end;