LCL: fixed loading ListView items on 64 bits targets

+ the LCL now reads/writes ListView.Items.LazData property which does not include ListItem.Data pointer value
* the only reads, but doesn't write ListView.Items.Data property. It assumes a 32 bit data field. This is to be compatible with existing lfm files and Delphi.

git-svn-id: trunk@10946 -
This commit is contained in:
vincents 2007-04-14 20:49:16 +00:00
parent f37189d56d
commit 263aa5147d
2 changed files with 71 additions and 36 deletions

View File

@ -673,8 +673,9 @@ type
procedure WSCreateCacheItem;
function WSUpdateAllowed: Boolean;
procedure ItemDestroying(const AItem: TListItem); //called by TListItem when freed
procedure ReadData(Stream: TStream);
procedure WriteData(Stream: TStream);
procedure ReadData(Stream: TStream); // read data in a Delphi compatible way
procedure ReadLazData(Stream: TStream); // read data in a 64 bits safe way
procedure WriteLazData(Stream: TStream); // write date in a 64 bits safe way
protected
procedure DefineProperties(Filer: TFiler); override;
function GetCount : Integer;

View File

@ -351,26 +351,31 @@ procedure TListItems.DefineProperties(Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineBinaryProperty('Data', @ReadData, @WriteData, WriteItems);
Filer.DefineBinaryProperty('Data', @ReadData, nil, false);
Filer.DefineBinaryProperty('LazData', @ReadLazData, @WriteLazData, WriteItems);
end;
type
PItemHeader = ^TItemHeader;
TItemHeader = record // packing is not needed (and not wanted since it controls also how this record is stored)
Size, Count: Integer;
Items: record end;
end;
PItemInfo = ^TItemInfo;
// for reading Delphi compatible TListItem.Data
TItemInfo = record // packing is not needed (and not wanted since it controls also how this record is stored)
ImageIndex: Integer;
StateIndex: Integer;
OverlayIndex: Integer;
SubItemCount: Integer;
Data: Pointer;
//Caption: string[255]; // all stings follow here
Data: Integer; // pointer field on 32 bits computers
end;
// Lazarus does not store ListItem.Data field, because a pointer field cannot
// be made 64 bits safe
TLazItemInfo = record // packing is not needed and not wanted
ImageIndex: Integer;
StateIndex: Integer;
OverlayIndex: Integer;
SubItemCount: Integer;
end;
ShortStr = string[255];
PShortStr = ^ShortStr;
procedure TListItems.ReadData(Stream: TStream);
function ReadString: String;
@ -391,7 +396,7 @@ var
begin
Clear;
StartPos := Stream.Position;
Size := Stream.ReadDWord;
Size := LEtoN(Integer(Stream.ReadDWord));
ItemCount := LEtoN(Integer(Stream.ReadDWord));
Owner.BeginUpdate;
try
@ -431,40 +436,71 @@ begin
end;
end;
procedure TListItems.WriteData(Stream: TStream);
function GetLength(const S: string): Integer;
begin
Result := Length(S);
if Result > 255 then Result := 255;
end;
procedure WriteString(const S: String);
var
Len: Integer;
begin
Len := Length(S);
if Len > 255 then Len := 255;
Stream.WriteByte(Len);
Stream.WriteBuffer(S[1], Len);
end;
procedure TListItems.ReadLazData(Stream: TStream);
var
I, J: Integer;
ItemInfo: TLazItemInfo;
ListItem: TListItem;
Size, ItemCount, SubCount: Integer;
StartPos: Int64;
begin
Clear;
StartPos := Stream.Position;
Size := LEtoN(Integer(Stream.ReadDWord));
ItemCount := LEtoN(Integer(Stream.ReadDWord));
Owner.BeginUpdate;
try
for I := 0 to ItemCount - 1 do
begin
Stream.ReadBuffer(ItemInfo, SizeOf(ItemInfo));
ListItem := Add;
ListItem.Caption := Stream.ReadAnsiString;
ListItem.ImageIndex := LEtoN(ItemInfo.ImageIndex);
// ListItem.StateIndex := LEtoN(ItemInfo.StateIndex);
// ListItem.OverlayIndex := LEtoN(ItemInfo.OverlayIndex);
SubCount := LEtoN(ItemInfo.SubItemCount);
for J := 0 to SubCount - 1 do
begin
ListItem.SubItems.Add(Stream.ReadAnsiString);
end;
end;
//read subitem images
if Stream.Position < StartPos + Size
then begin
for I := 0 to Count - 1 do
begin
ListItem := Item[I];
if ListItem.FSubItems = nil then Continue;
for J := 0 to ListItem.SubItems.Count - 1 do
ListItem.SubItemImages[J] := LEtoN(Integer(Stream.ReadDWord));
end;
end;
finally
Owner.EndUpdate;
end;
end;
procedure TListItems.WriteLazData(Stream: TStream);
var
I, J, Size, L : Integer;
ItemHeader : TItemHeader;
ItemInfo : TItemInfo;
ItemInfo : TLazItemInfo;
ListItem : TListItem;
begin
Size := SizeOf(ItemHeader);
for I := 0 to Count - 1 do
begin
L := GetLength(Item[I].Caption) + 1;
L := Length(Item[I].Caption) + 4;
for J := 0 to Item[I].SubItems.Count - 1 do
begin
Inc(L, GetLength(Item[I].SubItems[J]) + 1);
Inc(L, SizeOf(Integer));
Inc(L, Length(Item[I].SubItems[J]) + 4);
Inc(L, SizeOf(DWORD));
end;
Inc(Size, SizeOf(TItemInfo) - 255 + L);
Inc(Size, SizeOf(TLazItemInfo) + L);
end;
ItemHeader.Size := NtoLE(Size);
@ -482,17 +518,15 @@ begin
if ListItem.FSubItems = nil
then ItemInfo.SubItemCount := 0
else ItemInfo.SubItemCount := NtoLE(ListItem.SubItems.Count);
// TODO: check this
// Stream pointers ???
ItemInfo.Data := Pointer(NtoLE(PtrInt(ListItem.Data)));
Stream.WriteBuffer(ItemInfo, SizeOf(ItemInfo));
// Write the strings
WriteString(ListItem.Caption);
Stream.WriteAnsiString(ListItem.Caption);
for J := 0 to ItemInfo.SubItemCount - 1 do
begin
WriteString(ListItem.SubItems[J]);
Stream.WriteAnsiString(ListItem.SubItems[J]);
end;
end;