713 lines
20 KiB
ObjectPascal
713 lines
20 KiB
ObjectPascal
{******************************************************************
|
|
|
|
JEDI-VCL Demo
|
|
|
|
Copyright (C) 2002 Project JEDI
|
|
|
|
Original author:
|
|
|
|
Contributor(s):
|
|
|
|
You may retrieve the latest version of this file at the JEDI-JVCL
|
|
home page, located at http://jvcl.sourceforge.net
|
|
|
|
The contents of this file are used with permission, subject to
|
|
the Mozilla Public License Version 1.1 (the "License"); you may
|
|
not use this file except in compliance with the License. You may
|
|
obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1_1Final.html
|
|
|
|
Software distributed under the License is distributed on an
|
|
"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
implied. See the License for the specific language governing
|
|
rights and limitations under the License.
|
|
|
|
******************************************************************}
|
|
|
|
{*******************************************************}
|
|
{ }
|
|
{ Delphi Visual Component Library }
|
|
{ }
|
|
{ Copyright (c) 1996,97 Borland International }
|
|
{ Portions copyright (c) 1997 Master-Bank }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
unit HexDump;
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
|
|
Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Menus;
|
|
|
|
const
|
|
MAXDIGITS = 16;
|
|
|
|
{ THexDump }
|
|
|
|
type
|
|
THexStr = array[0..2] of Char;
|
|
THexStrArray = array[0..MAXDIGITS-1] of THexStr;
|
|
|
|
THexDump = class(TCustomControl)
|
|
private
|
|
FActive: Boolean;
|
|
FAddress: Pointer;
|
|
FDataSize: Longint;
|
|
FTopLine: Longint;
|
|
FCurrentLine: Longint;
|
|
FVisibleLines: Integer;
|
|
FLineCount: Longint;
|
|
FBytesPerLine: Integer;
|
|
FItemHeight: Integer;
|
|
FItemWidth: Integer;
|
|
FFileColors: array[0..2] of TColor;
|
|
FShowLineMarker: Boolean;
|
|
FShowCharacters: Boolean;
|
|
FShowAddress: Boolean;
|
|
FRelativeAddress: Boolean;
|
|
FBorder: TBorderStyle;
|
|
FHexData: THexStrArray;
|
|
FLineChars: array[0..MAXDIGITS] of Char;
|
|
FLineAddr: array[0..15] of Char;
|
|
procedure CalcPaintParams;
|
|
procedure SetTopLine(Value: Longint);
|
|
procedure SetCurrentLine(Value: Longint);
|
|
procedure SetFileColor(Index: Integer; Value: TColor);
|
|
function GetFileColor(Index: Integer): TColor;
|
|
procedure SetShowCharacters(Value: Boolean);
|
|
procedure SetShowAddress(Value: Boolean);
|
|
procedure SetShowLineMarker(Value: Boolean);
|
|
procedure SetRelativeAddress(Value: Boolean);
|
|
procedure SetBorder(Value: TBorderStyle);
|
|
procedure SetAddress(Value: Pointer);
|
|
procedure SetDataSize(Value: Longint);
|
|
procedure AdjustScrollBars;
|
|
procedure InvalidateLineMarker;
|
|
procedure SetScroll(Value: Longint);
|
|
function LineAddr(Index: Longint): PChar;
|
|
function LineData(Index: Longint): PChar;
|
|
function LineChars(Index: Longint; MaxLen: Integer): PChar;
|
|
function ScrollIntoView: Boolean;
|
|
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
|
|
procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
|
|
procedure CMEnter(var Message: TCMGotFocus); message CM_ENTER;
|
|
procedure CMExit(var Message: TCMLostFocus); message CM_EXIT;
|
|
procedure WMSize(var Message: TWMSize); message WM_SIZE;
|
|
procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
|
|
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
|
|
protected
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
procedure Paint; override;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
property CurrentLine: Longint read FCurrentLine write SetCurrentLine;
|
|
property LineCount: Longint read FLineCount;
|
|
property Address: Pointer read FAddress write SetAddress;
|
|
property DataSize: Longint read FDataSize write SetDataSize;
|
|
published
|
|
property Align;
|
|
property Border: TBorderStyle read FBorder write SetBorder default bsSingle;
|
|
property Color default clWindow;
|
|
property Ctl3D default True;
|
|
property Font;
|
|
property ParentColor default False;
|
|
property ParentCtl3D;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property ShowHint;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Visible;
|
|
property ShowAddress: Boolean read FShowAddress write SetShowAddress default True;
|
|
property ShowCharacters: Boolean read FShowCharacters write SetShowCharacters default True;
|
|
property ShowLineMarker: Boolean read FShowLineMarker write SetShowLineMarker default True;
|
|
property RelativeAddress: Boolean read FRelativeAddress write SetRelativeAddress default False;
|
|
property AddressColor: TColor index 0 read GetFileColor write SetFileColor default clWindowText;
|
|
property HexDataColor: TColor index 1 read GetFileColor write SetFileColor default clWindowText;
|
|
property AnsiCharColor: TColor index 2 read GetFileColor write SetFileColor default clHighlight;
|
|
property OnClick;
|
|
property OnDblClick;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
end;
|
|
|
|
function CreateHexDump(AOwner: TWinControl): THexDump;
|
|
|
|
implementation
|
|
|
|
uses JvJCLUtils;
|
|
|
|
{ Create THexDump control }
|
|
|
|
function CreateHexDump(AOwner: TWinControl): THexDump;
|
|
begin
|
|
Result := THexDump.Create(AOwner);
|
|
with Result do begin
|
|
Parent := AOwner;
|
|
Font.Name := 'Courier';
|
|
Align := alClient;
|
|
end;
|
|
end;
|
|
|
|
{$IFNDEF WIN32}
|
|
function LongMulDiv(Mult1, Mult2, Div1: Longint): Longint; assembler;
|
|
{ copied from GRIDS.PAS }
|
|
type
|
|
Quadword = record
|
|
w0, w1, w2, w3: Word;
|
|
end;
|
|
var
|
|
Temp: Quadword;
|
|
asm
|
|
{ Mul }
|
|
MOV DX,Mult1.Word[2]
|
|
MOV AX,Mult1.Word[0]
|
|
MOV CX,Mult2.Word[2]
|
|
MOV BX,Mult2.Word[0]
|
|
MOV DI,DX
|
|
MOV SI,AX
|
|
MUL BX
|
|
MOV Temp.w0,AX
|
|
MOV Temp.w1,DX
|
|
MOV AX,DI
|
|
MUL CX
|
|
MOV Temp.w2,AX
|
|
MOV Temp.w3,DX
|
|
MOV AX,DI
|
|
MUL BX
|
|
ADD Temp.w1,AX
|
|
ADC Temp.w2,DX
|
|
ADC Temp.w3,0
|
|
MOV AX,SI
|
|
MUL CX
|
|
ADD Temp.w1,AX
|
|
ADC Temp.w2,DX
|
|
ADC Temp.w3,0
|
|
MOV DX,Temp.w3
|
|
MOV SI,Temp.w2
|
|
MOV BX,Temp.w1
|
|
MOV AX,Temp.w0
|
|
{ rounding }
|
|
MOV CX,Div1.Word[2]
|
|
MOV DI,Div1.Word[0]
|
|
SHR CX,1
|
|
RCR DI,1
|
|
ADD AX,DI
|
|
ADC BX,CX
|
|
ADC SI,0
|
|
ADC DX,0
|
|
{ Div }
|
|
MOV CX,32
|
|
CLC
|
|
@1: RCL AX,1
|
|
RCL BX,1
|
|
RCL SI,1
|
|
RCL DX,1
|
|
JNC @3
|
|
@2: SUB SI,Div1.Word[0]
|
|
SBB DX,Div1.Word[2]
|
|
STC
|
|
LOOP @1
|
|
JMP @5
|
|
@3: CMP DX,Div1.Word[2]
|
|
JC @4
|
|
JNE @2
|
|
CMP SI,Div1.Word[0]
|
|
JNC @2
|
|
@4: CLC
|
|
LOOP @1
|
|
@5: RCL AX,1
|
|
RCL BX,1
|
|
MOV CX,SI
|
|
MOV DX,BX
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{ THexDump }
|
|
|
|
constructor THexDump.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
ControlStyle := [csFramed, csOpaque, csCaptureMouse, csClickEvents,
|
|
csDoubleClicks];
|
|
Ctl3D := True;
|
|
FBorder := bsSingle;
|
|
FShowLineMarker := True;
|
|
ParentColor := False;
|
|
Color := clWindow;
|
|
FFileColors[0] := clWindowText;
|
|
FFileColors[1] := clWindowText;
|
|
FFileColors[2] := clHighlight;
|
|
FShowAddress := True;
|
|
FShowCharacters := True;
|
|
Width := 300;
|
|
Height := 200;
|
|
FillChar(FHexData, SizeOf(FHexData), #9);
|
|
TabStop := True;
|
|
end;
|
|
|
|
destructor THexDump.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure THexDump.CreateParams(var Params: TCreateParams);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
with Params do begin
|
|
if (FBorder = bsSingle) then
|
|
{$IFDEF WIN32}
|
|
if NewStyleControls and Ctl3D then
|
|
ExStyle := ExStyle or WS_EX_CLIENTEDGE
|
|
else Style := Style or WS_BORDER;
|
|
{$ELSE}
|
|
Style := Style or WS_BORDER;
|
|
{$ENDIF}
|
|
Style := Style or WS_VSCROLL;
|
|
end;
|
|
end;
|
|
|
|
{ VCL Command Messages }
|
|
|
|
procedure THexDump.CMFontChanged(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
Canvas.Font := Self.Font;
|
|
FItemHeight := Canvas.TextHeight('A') + 2;
|
|
FItemWidth := Canvas.TextWidth('D') + 1;
|
|
CalcPaintParams;
|
|
AdjustScrollBars;
|
|
end;
|
|
|
|
procedure THexDump.CMCtl3DChanged(var Message: TMessage);
|
|
begin
|
|
{$IFDEF WIN32}
|
|
if NewStyleControls and (FBorder = bsSingle) then RecreateWnd;
|
|
inherited;
|
|
{$ELSE}
|
|
inherited;
|
|
Invalidate;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure THexDump.CMEnter;
|
|
begin
|
|
inherited;
|
|
InvalidateLineMarker;
|
|
end;
|
|
|
|
procedure THexDump.CMExit;
|
|
begin
|
|
inherited;
|
|
InvalidateLineMarker;
|
|
end;
|
|
|
|
{ Windows Messages }
|
|
|
|
procedure THexDump.WMSize(var Message: TWMSize);
|
|
begin
|
|
inherited;
|
|
CalcPaintParams;
|
|
AdjustScrollBars;
|
|
end;
|
|
|
|
procedure THexDump.WMGetDlgCode(var Message: TWMGetDlgCode);
|
|
begin
|
|
Message.Result := DLGC_WANTARROWS;
|
|
end;
|
|
|
|
procedure THexDump.WMVScroll(var Message: TWMVScroll);
|
|
var
|
|
NewTopLine: Longint;
|
|
LinesMoved: Longint;
|
|
R: TRect;
|
|
begin
|
|
inherited;
|
|
if (DataSize = 0) or (Address = nil) then Exit;
|
|
NewTopLine := FTopLine;
|
|
case Message.ScrollCode of
|
|
SB_LINEDOWN: Inc(NewTopLine);
|
|
SB_LINEUP: Dec(NewTopLine);
|
|
SB_PAGEDOWN: Inc(NewTopLine, FVisibleLines - 1);
|
|
SB_PAGEUP: Dec(NewTopLine, FVisibleLines - 1);
|
|
SB_TOP: NewTopLine := 0;
|
|
SB_BOTTOM: NewTopLine := FLineCount - 1;
|
|
SB_THUMBPOSITION, SB_THUMBTRACK:
|
|
{$IFDEF WIN32}
|
|
NewTopLine := Message.Pos;
|
|
{$ELSE}
|
|
NewTopLine := LongMulDiv(Message.Pos, FLineCount - 1, MaxInt);
|
|
{$ENDIF}
|
|
end;
|
|
if NewTopLine >= FLineCount then NewTopLine := FLineCount - 1;
|
|
if NewTopLine < 0 then NewTopLine := 0;
|
|
if NewTopLine <> FTopLine then begin
|
|
LinesMoved := FTopLine - NewTopLine;
|
|
FTopLine := NewTopLine;
|
|
SetScroll(FTopLine);
|
|
if Abs(LinesMoved) = 1 then begin
|
|
R := Bounds(0, 0, ClientWidth, ClientHeight - FItemHeight);
|
|
if LinesMoved = 1 then OffsetRect(R, 0, FItemHeight);
|
|
ScrollWindow(Handle, 0, FItemHeight * LinesMoved, @R, nil);
|
|
if LinesMoved = -1 then
|
|
begin
|
|
R.Top := ClientHeight - FItemHeight;
|
|
R.Bottom := ClientHeight;
|
|
end
|
|
else
|
|
begin
|
|
R.Top := 0;
|
|
R.Bottom := FItemHeight;
|
|
end;
|
|
InvalidateRect(Handle, @R, False);
|
|
end
|
|
else Invalidate;
|
|
end;
|
|
end;
|
|
|
|
{ Painting Related }
|
|
|
|
procedure THexDump.CalcPaintParams;
|
|
const
|
|
Divisor: array[Boolean] of Integer = (3, 4);
|
|
var
|
|
CharsPerLine: Integer;
|
|
begin
|
|
if FItemHeight < 1 then Exit;
|
|
FVisibleLines := (ClientHeight div FItemHeight) + 1;
|
|
CharsPerLine := ClientWidth div FItemWidth;
|
|
if FShowAddress then Dec(CharsPerLine, 10);
|
|
FBytesPerLine := CharsPerLine div Divisor[FShowCharacters];
|
|
if FBytesPerLine < 1 then FBytesPerLine := 1
|
|
else if FBytesPerLine > MAXDIGITS then FBytesPerLine := MAXDIGITS;
|
|
FLineCount := (DataSize div FBytesPerLine);
|
|
if Boolean(DataSize mod FBytesPerLine) then Inc(FLineCount);
|
|
if (FLineCount - 1) < FCurrentLine then CurrentLine := FLineCount - 1;
|
|
if (FLineCount - 1) < FTopLine then SetTopLine(FLineCount - 1);
|
|
end;
|
|
|
|
procedure THexDump.SetScroll(Value: Longint);
|
|
begin
|
|
{$IFDEF WIN32}
|
|
SetScrollPos(Handle, SB_VERT, Value, True);
|
|
{$ELSE}
|
|
SetScrollPos(Handle, SB_VERT, LongMulDiv(Value, MaxInt,
|
|
FLineCount - 1), True);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure THexDump.AdjustScrollBars;
|
|
begin
|
|
{$IFDEF WIN32}
|
|
SetScrollRange(Handle, SB_VERT, 0, FLineCount - 1, True);
|
|
{$ELSE}
|
|
if FLineCount > 1 then SetScrollRange(Handle, SB_VERT, 0, MaxInt, True)
|
|
else SetScrollRange(Handle, SB_VERT, 0, 0, True);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
function THexDump.ScrollIntoView: Boolean;
|
|
begin
|
|
Result := False;
|
|
if FCurrentLine < FTopLine then begin
|
|
Result := True;
|
|
SetTopLine(FCurrentLine);
|
|
end
|
|
else if FCurrentLine >= (FTopLine + FVisibleLines) - 1 then begin
|
|
SetTopLine(FCurrentLine - (FVisibleLines - 2));
|
|
Result := True;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.SetTopLine(Value: Longint);
|
|
var
|
|
LinesMoved: Longint;
|
|
R: TRect;
|
|
begin
|
|
if Value >= FLineCount then Value := FLineCount - 1;
|
|
if Value < 0 then Value := 0;
|
|
if Value <> FTopLine then begin
|
|
LinesMoved := FTopLine - Value;
|
|
FTopLine := Value;
|
|
SetScroll(FTopLine);
|
|
if Abs(LinesMoved) = 1 then begin
|
|
R := Bounds(1, 0, ClientWidth, ClientHeight - FItemHeight);
|
|
if LinesMoved = 1 then OffsetRect(R, 0, FItemHeight);
|
|
ScrollWindow(Handle, 0, FItemHeight * LinesMoved, @R, nil);
|
|
if LinesMoved = -1 then begin
|
|
R.Top := ClientHeight - FItemHeight;
|
|
R.Bottom := ClientHeight;
|
|
end
|
|
else begin
|
|
R.Top := 0;
|
|
R.Bottom := FItemHeight;
|
|
end;
|
|
InvalidateRect(Handle, @R, False);
|
|
end
|
|
else Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.SetCurrentLine(Value: Longint);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if Value >= FLineCount then Value := FLineCount - 1;
|
|
if Value < 0 then Value := 0;
|
|
if (Value <> FCurrentLine) then begin
|
|
if (FCurrentLine >= FTopLine) and (FCurrentLine < FTopLine + FVisibleLines{ - 1}) then
|
|
begin
|
|
R := Bounds(0, 0, ClientWidth, FItemHeight);
|
|
OffsetRect(R, 0, (FCurrentLine - FTopLine) * FItemHeight);
|
|
if FShowLineMarker then {!!}
|
|
InvalidateRect(Handle, @R, True);
|
|
end;
|
|
FCurrentLine := Value;
|
|
R := Bounds(0, 0, ClientWidth, FItemHeight);
|
|
OffsetRect(R, 0, (FCurrentLine - FTopLine) * FItemHeight);
|
|
if FShowLineMarker then {!!}
|
|
InvalidateRect(Handle, @R, True);
|
|
ScrollIntoView;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.InvalidateLineMarker;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if FShowLineMarker then begin
|
|
R := Bounds(0, 0, ClientWidth, FItemHeight);
|
|
OffsetRect(R, 0, (FCurrentLine - FTopLine) * FItemHeight);
|
|
InvalidateRect(Handle, @R, True);
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.Paint;
|
|
var
|
|
R, ItemRect: TRect;
|
|
I: Integer;
|
|
AddressWidth: Integer;
|
|
TabStop: Integer;
|
|
ByteCnt: Integer;
|
|
begin
|
|
inherited Paint;
|
|
Canvas.Brush.Color := Self.Color;
|
|
Canvas.FillRect(Rect(0, 0, ClientWidth, ClientHeight));
|
|
if FShowAddress then AddressWidth := FItemWidth * 10
|
|
else AddressWidth := 0;
|
|
R := Bounds(1, 0, ClientWidth, FItemHeight);
|
|
TabStop := FItemWidth * 3;
|
|
Canvas.Font.Color := FFileColors[1];
|
|
ByteCnt := FBytesPerLine;
|
|
for I := 0 to FVisibleLines - 1 do begin
|
|
R.Left := 1;
|
|
if I + FTopLine < FLineCount then begin
|
|
if FShowAddress then begin
|
|
Canvas.Font.Color := FFileColors[0];
|
|
R.Right := R.Left + AddressWidth;
|
|
ExtTextOut(Canvas.Handle, R.Left, R.Top, ETO_OPAQUE or ETO_CLIPPED, @R,
|
|
LineAddr(I + FTopLine), 10, nil);
|
|
R.Left := R.Right;
|
|
R.Right := ClientWidth;
|
|
Canvas.Font.Color := FFileColors[1];
|
|
end;
|
|
if FShowLineMarker and ((I + FTopLine) = FCurrentLine) then begin
|
|
Canvas.Brush.Color := clHighlight;
|
|
Canvas.Font.Color := clHighlightText;
|
|
ItemRect := Bounds(AddressWidth, 0, (FItemWidth * (FBytesPerLine * 3)) -
|
|
FItemWidth + 1, FItemHeight);
|
|
OffsetRect(ItemRect, 0, (FCurrentLine - FTopLine) * FItemHeight);
|
|
Canvas.FillRect(ItemRect);
|
|
end;
|
|
if (I + FTopLine = FLineCount - 1) and ((DataSize mod FBytesPerLine) > 0) then
|
|
ByteCnt := DataSize mod FBytesPerLine;
|
|
TabbedTextOut(Canvas.Handle, R.Left, R.Top, LineData(I + FTopLine),
|
|
(ByteCnt * 3) - 1, 1, TabStop, R.Left);
|
|
if FShowLineMarker and ((I + FTopLine) = FCurrentLine) and Focused then
|
|
Canvas.DrawFocusRect(ItemRect);
|
|
Canvas.Brush.Color := Self.Color;
|
|
Canvas.Font.Color := FFileColors[1];
|
|
if FShowCharacters then begin
|
|
R.Left := AddressWidth + (FItemWidth * (FBytesPerLine * 3));
|
|
R.Right := ClientWidth;
|
|
Canvas.Font.Color := FFileColors[2];
|
|
ExtTextOut(Canvas.Handle, R.Left, R.Top, ETO_OPAQUE or ETO_CLIPPED, @R,
|
|
LineChars(I + FTopLine, ByteCnt), ByteCnt, nil);
|
|
Canvas.Font.Color := FFileColors[1];
|
|
end;
|
|
end
|
|
else ExtTextOut(Canvas.Handle, R.Left, R.Top, ETO_OPAQUE or ETO_CLIPPED,
|
|
@R, nil, 0, nil);
|
|
OffsetRect(R, 0, FItemHeight);
|
|
end;
|
|
end;
|
|
|
|
{ Event Overrides }
|
|
|
|
procedure THexDump.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
if not FActive then Exit;
|
|
case Key of
|
|
VK_DOWN:
|
|
if FShowLineMarker then
|
|
CurrentLine := CurrentLine + 1
|
|
else
|
|
CurrentLine := FTopLine + FVisibleLines - 1;
|
|
VK_UP:
|
|
if FShowLineMarker then
|
|
CurrentLine := CurrentLine - 1
|
|
else
|
|
CurrentLine := FTopLine - 1;
|
|
VK_NEXT: CurrentLine := CurrentLine + FVisibleLines;
|
|
VK_PRIOR: CurrentLine := CurrentLine - FVisibleLines;
|
|
VK_HOME: CurrentLine := 0;
|
|
VK_END: CurrentLine := FLineCount - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
if not Focused and CanFocus then SetFocus;
|
|
if (Button = mbLeft) and FActive then
|
|
CurrentLine := FTopLine + (Y div FItemHeight);
|
|
end;
|
|
|
|
{ Property Set/Get Routines }
|
|
|
|
procedure THexDump.SetBorder(Value: TBorderStyle);
|
|
begin
|
|
if Value <> FBorder then begin
|
|
FBorder := Value;
|
|
RecreateWnd;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.SetRelativeAddress(Value: Boolean);
|
|
begin
|
|
if FRelativeAddress <> Value then begin
|
|
FRelativeAddress := Value;
|
|
if ShowAddress then Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.SetShowAddress(Value: Boolean);
|
|
begin
|
|
if FShowAddress <> Value then begin
|
|
FShowAddress := Value;
|
|
CalcPaintParams;
|
|
Invalidate;
|
|
AdjustScrollBars;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.SetShowCharacters(Value: Boolean);
|
|
begin
|
|
if Value <> FShowCharacters then begin
|
|
FShowCharacters := Value;
|
|
CalcPaintParams;
|
|
Invalidate;
|
|
AdjustScrollBars;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.SetShowLineMarker(Value: Boolean);
|
|
begin
|
|
if Value <> FShowLineMarker then begin
|
|
FShowLineMarker := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.SetFileColor(Index: Integer; Value: TColor);
|
|
begin
|
|
if FFileColors[Index] <> Value then
|
|
begin
|
|
FFileColors[Index] := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
function THexDump.GetFileColor(Index: Integer): TColor;
|
|
begin
|
|
Result := FFileColors[Index];
|
|
end;
|
|
|
|
procedure THexDump.SetAddress(Value: Pointer);
|
|
begin
|
|
FActive := (Value <> nil);
|
|
FAddress := Value;
|
|
if not FActive then SetDataSize(0)
|
|
else Invalidate;
|
|
if FActive then begin
|
|
CurrentLine := 0;
|
|
ScrollIntoView;
|
|
end;
|
|
end;
|
|
|
|
procedure THexDump.SetDataSize(Value: Longint);
|
|
begin
|
|
FDataSize := Value;
|
|
CalcPaintParams;
|
|
Invalidate;
|
|
AdjustScrollBars;
|
|
end;
|
|
|
|
function THexDump.LineAddr(Index: Longint): PChar;
|
|
begin
|
|
if RelativeAddress then
|
|
Result := StrFmt(FLineAddr, '%p: ', [HugeOffset(Pointer(0),
|
|
Index * FBytesPerLine)])
|
|
else
|
|
Result := StrFmt(FLineAddr, '%p: ', [HugeOffset(FAddress,
|
|
Index * FBytesPerLine)]);
|
|
end;
|
|
|
|
function THexDump.LineData(Index: Longint): PChar;
|
|
|
|
procedure SetData(P: PChar);
|
|
const
|
|
HexDigits : array[0..15] of Char = '0123456789ABCDEF';
|
|
var
|
|
I: Integer;
|
|
B: Byte;
|
|
begin
|
|
for I := 0 to FBytesPerLine - 1 do begin
|
|
try
|
|
B := Byte(P[I]);
|
|
FHexData[I][0] := HexDigits[B SHR $04];
|
|
FHexData[I][1] := HexDigits[B AND $0F];
|
|
except
|
|
FHexData[I][0] := '?';
|
|
FHexData[I][1] := '?';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
SetData(PChar(HugeOffset(FAddress, Index * FBytesPerLine)));
|
|
Result := FHexData[0];
|
|
end;
|
|
|
|
function THexDump.LineChars(Index: Longint; MaxLen: Integer): PChar;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Move(HugeOffset(FAddress, Index * FBytesPerLine)^, FLineChars, MaxLen);
|
|
Result := FLineChars;
|
|
for I := 0 to MaxLen - 1 do
|
|
if Result[I] < #32 then Result[I] := '.';
|
|
end;
|
|
|
|
end.
|