source: oup/current/Tools/BinEdit.pas

Last change on this file was 248, checked in by alloc, 15 years ago
File size: 28.1 KB
Line 
1unit BinEdit;
2
3interface
4
5uses
6  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7  Dialogs, VirtualTrees, Grids, Wrapgrid, MPHexEditor,
8  StdCtrls, Menus, ExtCtrls, Buttons,
9  Data, TypeDefs, ConnectionManager,
10  _TemplateFileList, VTHeaderPopup, ComCtrls;
11
12type
13  TForm_BinEdit = class(TForm_TemplateFileList)
14    panel_imexport: TPanel;
15    btn_export: TButton;
16    btn_import: TButton;
17    hex: TMPHexEditor;
18    Splitter2: TSplitter;
19    value_viewer: TWrapGrid;
20    Splitter3: TSplitter;
21    VST: TVirtualStringTree;
22    VTHPopup: TVTHeaderPopupMenu;
23    value_viewer_context: TPopupMenu;
24    value_viewer_context_copy: TMenuItem;
25    value_viewer_context_copyasdec: TMenuItem;
26    value_viewer_context_copyasfloat: TMenuItem;
27    value_viewer_context_copyasbitset: TMenuItem;
28    value_viewer_context_copyasstring: TMenuItem;
29    value_viewer_context_copyashex: TMenuItem;
30    procedure NewFile(fileinfo: TFileInfo);
31
32    function Save: Boolean;
33    function GetValue(datatype: Word; offset: Integer): String;
34    procedure SetNewValue(datatype: Word; offset: Integer; Value: String);
35
36    procedure WriteStructureInfos;
37    procedure ClearStructViewer;
38
39    procedure ClearValues;
40    procedure WriteValues;
41
42    procedure FormCreate(Sender: TObject);
43    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
44    procedure hexChange(Sender: TObject);
45    procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
46    procedure hexSelectionChanged(Sender: TObject);
47    procedure value_viewerDblClick(Sender: TObject);
48    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
49    procedure value_viewer_contextPopup(Sender: TObject);
50    procedure value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
51      Shift: TShiftState; X, Y: Integer);
52    procedure value_viewer_context_copyClick(Sender: TObject);
53    procedure VSTDblClick(Sender: TObject);
54    procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
55      Column: TColumnIndex);
56    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
57      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
58    procedure VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
59      OldPosition: Integer);
60    procedure VTHPopupColumnChange(const Sender: TBaseVirtualTree;
61      const Column: TColumnIndex; Visible: Boolean);
62  private
63    fileid: Integer;
64    ConID: Integer;
65    rawlist: TRawDataList;
66  public
67  end;
68
69implementation
70{$R *.dfm}
71uses ValueEdit, Main, Functions, DatStructureLoader, RawEdit, RawList, 
72  StrUtils, Clipbrd, _TemplateFile;
73
74
75type
76  PNodeData = ^TNodeData;
77
78  TNodeData = record
79    Caption:  String;
80    Offset:   LongInt;
81    DataType: Word;
82    Value:    String;
83    Description: String;
84  end;
85
86
87
88procedure TForm_BinEdit.FormCreate(Sender: TObject);
89begin
90  inherited;
91  Self.OnNewFileSelected := NewFile;
92
93  Self.Caption := '';
94  fileid     := 0;
95  VST.NodeDataSize := SizeOf(TNodeData);
96  value_viewer.ColCount := 2;
97  value_viewer.RowCount := 8;
98  value_viewer.FixedRows := 1;
99  value_viewer.FixedCols := 1;
100  value_viewer.Cells[0, 0] := 'Type';
101  value_viewer.Cells[1, 0] := 'Value';
102  value_viewer.Cells[0, 1] := '1 byte, unsigned';
103  value_viewer.Cells[0, 2] := '2 bytes, unsigned';
104  value_viewer.Cells[0, 3] := '4 bytes, unsigned';
105  value_viewer.Cells[0, 4] := 'Bitset';
106  value_viewer.Cells[0, 5] := 'Float';
107  value_viewer.Cells[0, 6] := 'String';
108  value_viewer.Cells[0, 7] := 'Selected length';
109  value_viewer.ColWidths[0] := 120;
110  value_viewer.ColWidths[1] := 1000;
111//  hex.Height := content.Height - 215;
112  //
113  value_viewer.Font.Charset := AppSettings.CharSet;
114  VST.Font.Charset := AppSettings.CharSet;
115  hex.Translation := tkAsIs;
116  hex.Font.Charset := AppSettings.CharSet;
117  //
118end;
119
120
121procedure TForm_BinEdit.NewFile(fileinfo: TFileInfo);
122var
123  mem:  TMemoryStream;
124begin
125  if ConID <> -1 then
126  begin
127    if hex.Modified then
128    begin
129      if not Save then
130      begin
131        Self.SelectFileID(ConnectionID, FileID);
132        Exit;
133      end;
134    end;
135  end;
136  if fileinfo.ID >= 0 then
137  begin
138    fileid := fileinfo.ID;
139    ConID := ConnectionID;
140//    if ConManager.Connection[ConID].ExtractFileIDOfName(filelist.Items.Strings[filelist.ItemIndex]) <> fileid then
141//      Self.SelectFileID(ConnectionID, fileid);
142    Self.ClearStructViewer;
143    ClearValues;
144    mem := nil;
145    hex.DataSize := 0;
146    if fileinfo.Size > 0 then
147    begin
148      ConManager.Connection[ConID].LoadDatFile(fileid, TStream(mem));
149      rawlist := ConManager.Connection[ConID].GetRawList(fileid);
150      hex.LoadFromStream(mem);
151      mem.Free;
152      WriteStructureInfos;
153    end;
154  end
155  else
156  begin
157    fileid := -1;
158    ConID := -1;
159    Self.ClearStructViewer;
160    ClearValues;
161    hex.DataSize := 0;
162    SetLength(rawlist, 0);
163  end;
164end;
165
166
167
168
169function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
170  ARecord: TNodeData): PVirtualNode;
171var
172  Data: PNodeData;
173begin
174  Result := AVST.AddChild(ANode);
175  Data   := AVST.GetNodeData(Result);
176  AVST.ValidateNode(Result, False);
177  Data^ := ARecord;
178end;
179
180
181
182
183
184function TForm_BinEdit.GetValue(datatype: Word; offset: Integer): String;
185var
186  Data: TByteData;
187  i:    Integer;
188  floatformat: TFormatSettings;
189begin
190  floatformat.DecimalSeparator := '.';
191  case datatype of
192    1:
193      Result := IntToStr(hex.Data[offset]);
194    2:
195      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
196    3:
197      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
198    4:
199      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
200        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
201    5:
202      Result := '0x' + IntToHex(hex.Data[offset], 2);
203    6:
204      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256, 4);
205    7:
206      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
207        hex.Data[offset + 2] * 256 * 256, 6);
208    8:
209      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
210        hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8);
211    9:
212    begin
213      SetLength(Data, 4);
214      Data[0] := hex.Data[offset];
215      Data[1] := hex.Data[offset + 1];
216      Data[2] := hex.Data[offset + 2];
217      Data[3] := hex.Data[offset + 3];
218      Result  := FloatToStr(Decode_Float(Data), floatformat);
219    end;
220    10:
221      Result := IntToBin(hex.Data[offset]);
222    11:
223    begin
224      if Length(rawlist) > 0 then
225      begin
226        for i := 0 to High(rawlist) do
227          if rawlist[i].SrcOffset = offset then
228          begin
229            if rawlist[i].RawAddr > 0 then
230              Result := '0x' + IntToHex(rawlist[i].RawAddr, 8)
231            else
232              Result := 'unused';
233            Break;
234          end;
235        if i > High(rawlist) then
236          Result := 'unused';
237      end;
238    end;
239    12:
240      if hex.Data[offset] = 1 then
241        Result := FormatNumber(hex.Data[offset + 1] + hex.Data[offset + 2] * 256 +
242          hex.Data[offset + 3] * 256 * 256, 5, '0')
243      else
244        Result := 'no link';
245    13:
246      Result := IntToStr(hex.Data[offset]);
247    14:
248      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
249    15:
250      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
251    16:
252      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
253        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
254    17:
255      Result := IntToStr((hex.Data[offset + 3]) div 2);
256    100..300:
257    begin
258      Result := '';
259      for i := 1 to datatype - 100 do
260      begin
261        if hex.Data[offset + i - 1] >= 32 then
262          Result := Result + Chr(hex.Data[offset + i - 1])
263        else
264          Break;
265      end;
266    end;
267    1000..9999:
268    begin
269      Result := '';
270      for i := 1 to datatype - 1000 do
271      begin
272        if hex.Data[offset + i - 1] >= 32 then
273          Result := Result + Chr(hex.Data[offset + i - 1])
274        else
275          Result := Result + '.';
276      end;
277    end;
278    10000..65535:
279    begin
280      Result := '';
281      for i := 1 to datatype - 10000 do
282      begin
283        if hex.Data[offset + i - 1] >= 32 then
284          Result := Result + Chr(hex.Data[offset + i - 1])
285        else
286          Result := Result + '.';
287      end;
288    end;
289  end;
290end;
291
292
293
294
295procedure TForm_BinEdit.WriteStructureInfos;
296var
297  i, j:    Integer;
298  pdata:   PNodeData;
299  Data:    TNodeData;
300  node:    PVirtualNode;
301  structs: TStructDef;
302begin
303  VST.BeginUpdate;
304  if VST.RootNodeCount = 0 then
305  begin
306    structs := LoadStructureDefinition(ConID, fileid);
307    if structs.Data then
308    begin
309      if Length(structs.Global) > 0 then
310      begin
311        for i := 0 to High(structs.Global) do
312        begin
313          Data.Caption  := structs.Global[i].Name;
314          Data.Offset   := structs.Global[i].offset;
315          Data.DataType := structs.Global[i].datatype;
316          Data.Value    := GetValue(structs.Global[i].datatype, structs.Global[i].offset);
317          Data.Description := structs.Global[i].description;
318          AddVSTEntry(VST, nil, Data);
319        end;
320      end;
321      if Length(structs.Subs) > 0 then
322      begin
323        for i := 0 to High(structs.Subs) do
324        begin
325          with structs.Subs[i] do
326          begin
327            if Length(Entries) > 0 then
328            begin
329              if Pos('#', SubName) > 0 then
330              begin
331                Data.Offset  := StrToInt('$'+MidStr(SubName, Pos('#', SubName) + 1, 8));
332                Data.Value   := '$' +
333                  MidStr(SubName, PosEx('#', SubName, Pos('#', SubName) + 1) + 1, 8);
334                Data.Caption := MidStr(SubName, 1, Pos('#', SubName) - 1);
335                Data.Description := SubDesc;
336              end
337              else
338              begin
339                Data.Caption := SubName;
340                Data.Description := SubDesc;
341                Data.Offset := 0;
342                Data.Value := '';
343              end;
344              Data.DataType := 0;
345              node := AddVSTEntry(VST, nil, Data);
346              Data.Description := '';
347              for j := 0 to High(Entries) do
348              begin
349                Data.Caption  := Entries[j].Name;
350                Data.Offset   := Entries[j].offset;
351                Data.DataType := Entries[j].datatype;
352                Data.Value    := GetValue(Entries[j].datatype, Entries[j].offset);
353                Data.Description := Entries[j].description;
354                AddVSTEntry(VST, node, Data);
355              end;
356            end;
357          end;
358        end;
359      end;
360    end;
361    if VST.RootNodeCount > 0 then
362      VST.FocusedNode := VST.GetFirst;
363  end
364  else
365  begin
366    Node := VST.GetFirst;
367    while Assigned(Node) do
368    begin
369      pdata := VST.GetNodeData(Node);
370      if pdata.DataType > 0 then
371        pdata.Value := GetValue(pdata.Datatype, pdata.Offset);
372      Node := VST.GetNext(Node);
373    end;
374  end;
375  VST.EndUpdate;
376end;
377
378
379
380
381procedure TForm_BinEdit.ClearValues;
382var
383  i: Byte;
384begin
385  for i := 1 to value_viewer.RowCount - 1 do
386  begin
387    value_viewer.Cells[1, i] := '';
388  end;
389end;
390
391
392
393
394procedure TForm_BinEdit.WriteValues;
395var
396  i, j:  Integer;
397  Data:  TByteData;
398  str:   String;
399  Value: Integer;
400  floatformat: TFormatSettings;
401begin
402  floatformat.DecimalSeparator := '.';
403  for i := 1 to value_viewer.RowCount - 1 do
404  begin
405    if value_viewer.Cells[0, i] = '1 byte, unsigned' then
406    begin
407      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
408        ((hex.SelStart + 1) > hex.DataSize) then
409      begin
410        Value := hex.Data[hex.SelStart];
411        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 2);
412      end
413      else
414        value_viewer.Cells[1, i] := '';
415    end;
416    if value_viewer.Cells[0, i] = '2 bytes, unsigned' then
417    begin
418      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
419        ((hex.SelStart + 2) > hex.DataSize) then
420      begin
421        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
422        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 4);
423      end
424      else
425        value_viewer.Cells[1, i] := '';
426    end;
427    if value_viewer.Cells[0, i] = '4 bytes, unsigned' then
428    begin
429      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
430        ((hex.SelStart + 4) > hex.DataSize) then
431      begin
432        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
433          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
434        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 8);
435      end
436      else
437        value_viewer.Cells[1, i] := '';
438    end;
439    if value_viewer.Cells[0, i] = 'Bitset' then
440    begin
441      if (hex.SelCount <= 8) then
442      begin
443        if hex.SelCount = 0 then
444        begin
445          SetLength(Data, 1);
446          Data[0] := hex.Data[hex.SelStart];
447        end
448        else
449        begin
450          SetLength(Data, hex.SelCount);
451          for j := 0 to hex.SelCount - 1 do
452            Data[j] := hex.Data[hex.SelStart + j];
453        end;
454        value_viewer.Cells[1, i] := DataToBin(Data);
455      end
456      else
457        value_viewer.Cells[1, i] := '';
458    end;
459    if value_viewer.Cells[0, i] = 'Float' then
460    begin
461      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
462        ((hex.SelStart + 4) > hex.DataSize) then
463      begin
464        SetLength(Data, 4);
465        for j := 0 to 3 do
466          Data[j] := hex.Data[hex.SelStart + j];
467        value_viewer.Cells[1, i] := FloatToStr(Decode_Float(Data), floatformat);
468      end
469      else
470        value_viewer.Cells[1, i] := '';
471    end;
472    if value_viewer.Cells[0, i] = 'Selected length' then
473    begin
474      value_viewer.Cells[1, i] := IntToStr(hex.SelCount) + ' bytes';
475    end;
476    if value_viewer.Cells[0, i] = 'String' then
477    begin
478      j   := 0;
479      str := '';
480      if hex.SelCount = 0 then
481      begin
482        while (hex.SelStart + j) < hex.DataSize do
483        begin
484          if hex.Data[hex.SelStart + j] = 0 then
485            Break;
486          if hex.Data[hex.selstart + j] >= 32 then
487            str := str + Char(hex.Data[hex.SelStart + j])
488          else
489            str := str + '.';
490          Inc(j);
491        end;
492      end
493      else
494      begin
495        for j := 0 to hex.SelCount - 1 do
496          if hex.Data[hex.selstart + j] >= 32 then
497            str := str + Char(hex.Data[hex.SelStart + j])
498          else if hex.Data[hex.selstart + j] > 0 then
499            str := str + '.'
500          else
501            Break;
502      end;
503      value_viewer.Cells[1, i] := str;
504    end;
505  end;
506end;
507
508
509
510
511function TForm_BinEdit.Save: Boolean;
512var
513  mem:  TMemoryStream;
514  i:    Integer;
515begin
516  case MessageBox(Self.Handle, PChar('Save changes to file ' +
517      ConManager.Connection[ConID].GetFileInfo(fileid).Name + '?'), PChar('Data changed...'),
518      MB_YESNOCANCEL + MB_ICONQUESTION) of
519    idYes:
520    begin
521      mem := TMemoryStream.Create;
522      hex.SaveToStream(mem);
523      mem.Seek(0, soFromBeginning);
524      ConManager.Connection[ConID].UpdateDatFile(fileid, mem);
525      mem.Free;
526      hex.Modified := False;
527      for i := 0 to hex.Datasize - 1 do
528        hex.ByteChanged[i] := False;
529      Result := True;
530    end;
531    idNo:
532      Result := True;
533    idCancel:
534    begin
535      Result := False;
536    end;
537  end;
538end;
539
540
541
542
543procedure TForm_BinEdit.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
544begin
545  if hex.Modified then
546  begin
547    if not Save then
548      CanClose := False;
549  end;
550end;
551
552
553
554
555procedure TForm_BinEdit.ClearStructViewer;
556begin
557  VST.Clear;
558end;
559
560
561
562
563
564
565procedure TForm_BinEdit.hexChange(Sender: TObject);
566begin
567  ClearValues;
568  if hex.DataSize > 0 then
569  begin
570    WriteStructureInfos;
571    WriteValues;
572  end;
573end;
574
575
576
577
578procedure TForm_BinEdit.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
579//var
580//  temps: String;
581begin
582  if (Shift = [ssCtrl]) and (Key = Ord('C')) then
583  begin
584    if hex.SelCount > 0 then
585    begin
586      if hex.InCharField then
587        Clipboard.AsText := hex.SelectionAsText
588      else
589        Clipboard.AsText := hex.SelectionAsHex;
590    end;
591  end;
592  if (Shift = [ssCtrl]) and (Key = Ord('V')) then
593  begin
594{      temps:=Clipboard.AsText;
595      IF hex.SelStart+Length(temps)>hex.DataSize THEN
596        SetLength(temps, hex.DataSize-hex.SelStart);
597      hex.Sel
598      hex.SelCount:=Length(temps);
599      hex.ReplaceSelection(temps,Length(temps));
600}    end;
601end;
602
603
604
605
606procedure TForm_BinEdit.hexSelectionChanged(Sender: TObject);
607var
608  selstart: Integer;
609  node:     PVirtualNode;
610  pdata:    PNodeData;
611begin
612  if hex.DataSize > 0 then
613  begin
614    WriteValues;
615    selstart := hex.SelStart;
616    if VST.RootNodeCount > 0 then
617    begin
618      Node := VST.GetFirst;
619      while Assigned(Node) do
620      begin
621        pdata := VST.GetNodeData(Node);
622        if pdata.DataType > 0 then
623        begin
624          if ((selstart - pdata.Offset) < GetDataTypeLength(pdata.DataType)) and
625            ((selstart - pdata.Offset) >= 0) then
626          begin
627            VST.FocusedNode    := Node;
628            VST.Selected[Node] := True;
629            Break;
630          end;
631        end;
632        Node := VST.GetNext(Node);
633      end;
634    end;
635  end;
636end;
637
638
639
640
641procedure TForm_BinEdit.value_viewer_contextPopup(Sender: TObject);
642var
643  i: Byte;
644begin
645  for i := 0 to value_viewer_context.Items.Count - 1 do
646    value_viewer_context.Items.Items[i].Visible := False;
647  with value_viewer do
648  begin
649    if (Col = 1) and (Row > 0) and (Length(Cells[Col, Row]) > 0) then
650    begin
651      if Pos(' byte', Cells[0, Row]) = 2 then
652      begin
653        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
654        value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible := True;
655        value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible := True;
656      end;
657      if Pos('Float', Cells[0, Row]) = 1 then
658        value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible := True;
659      if Pos('Bitset', Cells[0, Row]) = 1 then
660        value_viewer_context.Items.Find(
661          'Copy to clipboard (as &bitset)').Visible := True;
662      if Pos('String', Cells[0, Row]) = 1 then
663        value_viewer_context.Items.Find(
664          'Copy to clipboard (as &string)').Visible := True;
665      if Pos('Selected length', Cells[0, Row]) = 1 then
666        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
667    end;
668  end;
669end;
670
671
672
673
674procedure TForm_BinEdit.value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
675  Shift: TShiftState; X, Y: Integer);
676var
677  ACol, ARow: Integer;
678begin
679  if Button = mbRight then
680  begin
681    value_viewer.MouseToCell(x, y, ACol, ARow);
682    if ARow > 0 then
683    begin
684      value_viewer.Col := ACol;
685      value_viewer.Row := ARow;
686    end;
687  end;
688end;
689
690
691
692
693procedure TForm_BinEdit.value_viewer_context_copyClick(Sender: TObject);
694var
695  Name:  String;
696  Value: Integer;
697begin
698  Name := TMenuItem(Sender).Name;
699  if Pos('asstring', Name) > 0 then
700  begin
701    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
702  end
703  else if Pos('asfloat', Name) > 0 then
704  begin
705    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
706  end
707  else if Pos('asbitset', Name) > 0 then
708  begin
709    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
710  end
711  else if (Pos('ashex', Name) > 0) or (Pos('asdec', Name) > 0) then
712  begin
713    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
714    begin
715      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
716        ((hex.SelStart + 1) > hex.DataSize) then
717        Value := hex.Data[hex.SelStart];
718    end;
719    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
720    begin
721      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
722        ((hex.SelStart + 2) > hex.DataSize) then
723        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
724    end;
725    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
726    begin
727      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
728        ((hex.SelStart + 4) > hex.DataSize) then
729        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
730          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
731    end;
732    if Pos('asdec', Name) > 0 then
733    begin
734      Clipboard.AsText := IntToStr(Value);
735    end
736    else
737    begin
738      if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
739        Clipboard.AsText := '0x' + IntToHex(Value, 2);
740      if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
741        Clipboard.AsText := '0x' + IntToHex(Value, 4);
742      if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
743        Clipboard.AsText := '0x' + IntToHex(Value, 8);
744    end;
745  end
746  else
747  begin
748    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
749  end;
750end;
751
752
753
754
755procedure TForm_BinEdit.VSTDblClick(Sender: TObject);
756var
757  node: PVirtualNode;
758  nodedata: PNodeData;
759  rawinfo: TRawDataInfo;
760  form: TForm_TemplateFileList;
761begin
762  if VST.FocusedColumn = 3 then
763  begin
764    node     := VST.FocusedNode;
765    nodedata := VST.GetNodeData(node);
766
767    if not (nodedata.datatype in [11, 12]) and
768      ((nodedata.DataType < 100) or (nodedata.DataType > 300)) then
769    begin
770      Form_ValueEdit.MakeVarInput(nodedata.Caption, nodedata.offset,
771        nodedata.datatype, nodedata.Value, Self);
772    end
773    else
774    begin
775      if (nodedata.DataType = 11) and (nodedata.Value <> 'unused') then
776      begin
777        rawinfo := ConManager.Connection[ConID].GetRawInfo(fileid, nodedata.offset);
778        if rawinfo.RawSize > 0 then
779        begin
780          form := nil;
781          form := TForm_TemplateFileList(Form_Main.open_child('rawedit', ConID, fileid));
782          if Assigned(form) then
783            TForm_RawEdit(form).LoadRaw(rawinfo);
784        end;
785      end;
786      if (nodedata.DataType = 12) and (nodedata.Value <> 'no link') then
787      begin
788        if (StrToInt(nodedata.Value) < ConManager.Connection[ConID].GetFileCount) and
789          (StrToInt(nodedata.Value) > 0) and
790          (StrToInt(nodedata.Value) <> fileid) then
791        begin
792          if ConManager.Connection[ConID].GetFileInfo(StrToInt(nodedata.Value)).Size > 0 then
793            Form_Main.open_child('binedit', ConID, StrToInt(nodedata.Value))
794          else
795            ShowMessage('Linked filed is a zero-byte-file');
796        end;
797      end;
798      if (nodedata.DataType >= 100) and (nodedata.DataType <= 300) then
799      begin
800        form := TForm_TemplateFileList(Form_Main.open_child('binedit', ConID));
801        if Assigned(form) then
802          form.SetFileFilters(nodedata.Value, '', False);
803      end;
804    end;
805
806  end;
807end;
808
809
810
811
812procedure TForm_BinEdit.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
813  Column: TColumnIndex);
814var
815  Data: PNodeData;
816begin
817  Data := VST.GetNodeData(node);
818  if Data.DataType > 0 then
819  begin
820    hex.SelStart := Data.Offset;
821    hex.SelEnd   := Data.Offset + GetDataTypeLength(Data.DataType) - 1;
822  end
823  else
824  begin
825    hex.SelStart := Data.Offset;
826    hex.SelEnd   := Data.Offset + StrToInt(Data.Value) - 1;
827  end;
828end;
829
830
831
832
833procedure TForm_BinEdit.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
834  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
835var
836  Data: PNodeData;
837begin
838  Data     := Sender.GetNodeData(Node);
839  CellText := '';
840  if TextType = ttNormal then
841  begin
842    case Column of
843      0:
844        CellText := Data.Caption;
845      1:
846        if Data.DataType > 0 then
847          CellText := '0x' + IntToHex(Data.Offset, 8)
848        else if Data.Offset > 0 then
849          CellText := '0x' + IntToHex(Data.Offset, 8);
850      2:
851        if Data.DataType > 0 then
852          CellText := GetDataType(Data.DataType);
853      3:
854        if Data.DataType > 0 then
855          CellText := Data.Value //GetValue(data.DataType, data.Offset)
856        else if Length(Data.Value) > 0 then
857          CellText := IntToStr(StrToInt(Data.Value)) + ' Bytes';
858      4:
859        CellText := Data.Description;
860    end;
861  end;
862end;
863
864
865
866
867procedure TForm_BinEdit.VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
868  OldPosition: Integer);
869begin
870  if Sender.Columns.Items[column].Position < 1 then
871    Sender.Columns.Items[column].Position := OldPosition;
872end;
873
874
875
876
877procedure TForm_BinEdit.VTHPopupColumnChange(const Sender: TBaseVirtualTree;
878  const Column: TColumnIndex; Visible: Boolean);
879begin
880  if column = 0 then
881    TVirtualStringTree(Sender).Header.Columns.Items[column].Options :=
882      TVirtualStringTree(Sender).Header.Columns.Items[column].Options + [coVisible];
883end;
884
885
886
887
888procedure TForm_BinEdit.SetNewValue(datatype: Word; offset: Integer; Value: String);
889var
890  Data: TByteData;
891  value_int: LongWord;
892  value_float: Single;
893  i: Word;
894begin
895  case datatype of
896    1..4:
897    begin
898      value_int := StrToInt(Value);
899      SetLength(Data, datatype);
900      for i := 0 to datatype - 1 do
901      begin
902        Data[i]   := value_int mod 256;
903        value_int := value_int div 256;
904      end;
905    end;
906    5..8:
907    begin
908      value_int := StrToInt('$' + Value);
909      SetLength(Data, datatype - 4);
910      for i := 0 to datatype - 5 do
911      begin
912        Data[i]   := value_int mod 256;
913        value_int := value_int div 256;
914      end;
915    end;
916    9:
917    begin
918      value_float := StrToFloat(Value);
919      Data := Encode_Float(value_float);
920    end;
921    10:
922    begin
923      value_int := BinToInt(Value);
924      SetLength(Data, 1);
925      Data[0] := value_int;
926    end;
927    10000..65535:
928    begin
929      SetLength(Data, datatype - 10000);
930      for i := 1 to datatype - 10000 do
931      begin
932        if i <= Length(Value) then
933          Data[i - 1] := Ord(Value[i])
934        else
935          Data[i - 1] := 0;
936      end;
937    end;
938  end;
939  for i := 0 to High(Data) do
940  begin
941    if hex.Data[offset + i] <> Data[i] then
942      hex.ByteChanged[offset + i] := True;
943    hex.Data[offset + i] := Data[i];
944  end;
945  hex.Modified := True;
946  hexChange(Self);
947  hex.Repaint;
948end;
949
950
951
952
953procedure TForm_BinEdit.value_viewerDblClick(Sender: TObject);
954var
955  offset:     Integer;
956  datatype:   Word;
957  objectname: String;
958  Value:      String;
959begin
960  if (value_viewer.Col = 1) and (Length(value_viewer.Cells[1, value_viewer.Row]) > 0) then
961  begin
962    offset := hex.SelStart;
963    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
964      datatype := 1;
965    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
966      datatype := 2;
967    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
968      datatype := 4;
969    if value_viewer.Cells[0, value_viewer.Row] = 'Bitset' then
970      datatype := 10;
971    if value_viewer.Cells[0, value_viewer.Row] = 'Float' then
972      datatype := 9;
973    if value_viewer.Cells[0, value_viewer.Row] = 'Selected length' then
974      Exit;
975    if value_viewer.Cells[0, value_viewer.Row] = 'String' then
976    begin
977      if hex.SelCount > 0 then
978        datatype := 10000 + hex.SelCount
979      else
980        datatype := 10000 + Length(value_viewer.Cells[1, value_viewer.Row]);
981    end;
982    objectname := '';
983    Value      := GetValue(datatype, offset);
984    Form_ValueEdit.MakeVarInput(objectname, offset, datatype, Value, Self);
985  end;
986end;
987
988
989
990procedure TForm_BinEdit.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
991begin
992  if (Shift = [ssCtrl]) and (Key = 83) then
993    if hex.Modified then
994      if not Save then
995        Exit;
996end;
997
998
999begin
1000  AddToolListEntry('binedit', 'Binary .dat-Editor', '');
1001end.
Note: See TracBrowser for help on using the repository browser.