unit codesnippet;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ToolWin, engine, ExtCtrls, xmldom, XMLIntf,
  msxmldom, XMLDoc, Menus;

type
  TSnipWin = class(TForm)
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    Panel1: TPanel;
    Button1: TButton;
    Button2: TButton;
    CML: TXMLDocument;
    TrackBar1: TTrackBar;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    ToolButton8: TToolButton;
    FD: TFindDialog;
    PopupMenu1: TPopupMenu;
    Copy1: TMenuItem;
    Cut1: TMenuItem;
    Paste1: TMenuItem;
    N1: TMenuItem;
    Undo1: TMenuItem;
    Redo1: TMenuItem;
    ToolButton9: TToolButton;
    ToolButton10: TToolButton;
    ToolButton11: TToolButton;
    RD: TReplaceDialog;
    N2: TMenuItem;
    SelectAll1: TMenuItem;
    Memo1: TMemo;
    procedure FormHide(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure ToolButton1Click(Sender: TObject);
    procedure Memo1Change(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure ToolButton7Click(Sender: TObject);
    procedure ToolButton8Click(Sender: TObject);
    procedure ToolButton3Click(Sender: TObject);
    procedure ToolButton4Click(Sender: TObject);
    procedure ToolButton5Click(Sender: TObject);
    procedure ToolButton10Click(Sender: TObject);
    procedure FDFind(Sender: TObject);
    procedure RDFind(Sender: TObject);
    procedure RDReplace(Sender: TObject);
    procedure ToolButton11Click(Sender: TObject);
    procedure SelectAll1Click(Sender: TObject);
    procedure FormDeactivate(Sender: TObject);
  private
    fModified: Boolean;
    IsExtended: boolean;
    procedure WMNCLButtondblclk(var Msg: TWMNCLButtondblclk); message WM_NCLBUTTONDBLCLK;
    procedure SetModified(const Value: Boolean);
  public
    oldHeight: integer;
   CurrentSelected: TEdRawNode;
   procedure SetRoll(Extended: Boolean);
   Procedure SelectNode(NodeToSelect: TEdRawNode);
   procedure WM(Var msg: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING;
   Function ValidateXML(Var ErrMsg: String): Boolean;
   Property Modified: Boolean read fModified write SetModified;
   Procedure UpdateSnippet;
   Procedure CopyToClipboard;
   Procedure PasteFromClipboard;
   Function FindText(SearchStr: String; Text: string; Pos: Integer; Down: boolean; CaseSensitive: boolean): Integer;
   Procedure ReplaceAll;
  end;

var
  SnipWin: TSnipWin;

implementation

{$R *.dfm}

Uses SnapTo, main, procsandtypes, objbrowsewin;

{ TSnipWin }

procedure TSnipWin.WM(var msg: TWMWindowPosChanging);
begin
 SnapTo.WMWindowPosChanging(MSG, self);
end;

procedure TSnipWin.FormHide(Sender: TObject);
begin
 oeMain.actionSnippet.Checked := False;
end;

procedure TSnipWin.FormShow(Sender: TObject);
begin
 oeMain.actionSnippet.Checked := True;
 UpdateSnippet;
end;

procedure TSnipWin.SelectNode(NodeToSelect: TEdRawNode);
Var
 S: String;
begin
 If NodeToSelect = nil then begin
  Memo1.Text := 'Nothing selected';
  Modified := false;
  Memo1.Enabled := false;
  ToolButton1.Enabled := false;
  exit;
 end;
 If (NodeToSelect.NodeType = ntDisplay) or (NodeToSelect.NodeType = ntCML) or (NodeToSelect.Name = '_ROOTNODE_') then begin
  S := '';
  Case NodeToSelect.NodeType of
   ntUndefined: begin
                 S := 'CML Node selected, this node cannot be altered.';
                end;
   ntCML: begin
           S := 'CML Node selected, this node cannot be altered.';
          end;
   ntDisplay: Begin
               S := 'Display node selected, this node cannot be altered.';
              end;
  end;
  Modified := false;
  Memo1.Enabled := false;
  Memo1.Text := S;
  ToolButton1.Enabled := false;
  exit;
 end;
 If not Memo1.Enabled then begin
  Memo1.Enabled := true;
 end;
 ToolButton1.Enabled := true;
 oeMain.VarMgr.ResetSaveCount;
 Memo1.Text := NodeToSelect.WriteXML();
 CurrentSelected := NodeToSelect;
 Modified := false;
end;

procedure TSnipWin.ToolButton1Click(Sender: TObject);
begin
 If CurrentSelected.Parent = nil then begin
  MessageDlg('Already showing top level.', mtInformation, [mbOK], 0);
  exit;
 end;
 oeMain.SelectNode(CurrentSelected.Parent);
end;

procedure TSnipWin.SetModified(const Value: Boolean);
begin
  fModified := Value;
  If Value then Panel1.Visible := true
   else Panel1.Visible := false;
end;

procedure TSnipWin.Memo1Change(Sender: TObject);
begin
 Modified := true;
end;

procedure TSnipWin.Button1Click(Sender: TObject);
Var
 ErrMsg: String;
 XML: String;
 SelNode: TEdRawNode;
 ParentNode: TEdRawNode;
begin
 If not validateXML(ErrMsg) then begin
  MessageDlg(ErrMsg, mtError, [mbOK], 0);
  exit;
 end;
 Modified := false;
 XML := Memo1.Text;
 // We add an extra toplevel this way we can use the loadchildren function under the parent.
 XML := '<xml>' + XML + '</xml>';
 CML.XML.Text := XML;
 // First you need to delete the currentnode
 SelNode := CurrentSelected;
 ParentNode := CurrentSelected.Parent;
 oeMain.Select.Clear;
 SelNode.DeleteSelf;
 // then you need to loadchildren through the parent
 CML.Active := true;
 ParentNode.LoadChildren(CML.ChildNodes[0], ParentNode);
 CML.Active := False;
 // SelectNode
 oeMain.SelectNode(ParentNode.Node[ParentNode.Count - 1]);
 ObjBrowser.LoadFromNode();
end;

function TSnipWin.ValidateXML(Var ErrMsg: string): boolean;
begin
 Result := true;
 CML.Active := false;
 CML.XML.Text := Memo1.Lines.Text;
 Try
  CML.Active := true;
 except
  on EDOMParseError do begin
   ErrMsg := (ExceptObject as Exception).Message;
   Result := false;
  end;
 end;
 CML.Active := false;
end;

procedure TSnipWin.Button2Click(Sender: TObject);
begin
 Memo1.Text := CurrentSelected.WriteXML('');
 Modified := false;
end;

procedure TSnipWin.UpdateSnippet;
begin
 If Visible then begin
  SelectNode(oeMain.CurrentSelectNode);
 end;
end;

procedure TSnipWin.FormActivate(Sender: TObject);
begin
 oeMain.SetHotKeyStates(self);
 If (Options.ToolWindows.AutoRollUp and (not Options.ToolWindows.ARUExcept.SnipWin)) then begin
  SetRoll(true);
 end;
end;

procedure TSnipWin.CopyToClipboard;
begin
 StrToClipbrd(memo1.SelText);
end;

procedure TSnipWin.PasteFromClipboard;
begin
 Memo1.SelText := GetStrFromClipbrd;
end;

procedure TSnipWin.FormCreate(Sender: TObject);
begin
 left := 50;
 top := 50;
 oldheight := clientheight;
 IsExtended := true;
end;

procedure TSnipWin.WMNCLButtondblclk(var Msg: TWMNCLButtondblclk);
begin
 If ((msg.HitTest = HTCAPTION) and (not(Options.ToolWindows.AutoRollUp and (not Options.ToolWindows.ARUExcept.SnipWin)))) then begin
  SetRoll(not IsExtended);
 end;
end;

procedure TSnipWin.SetRoll(Extended: Boolean);
begin
 If not extended then begin
  If not IsExtended then exit;
  oldHeight := ClientHeight;
  ClientHeight := TrackBar1.Height;
  Toolbar1.Visible := false;
  IsExtended := false;
 end
  else
 begin
  If IsExtended then exit;
  ClientHeight := oldHeight;
  Toolbar1.Visible := true;
  IsExtended := true;
 end;
end;

procedure TSnipWin.TrackBar1Change(Sender: TObject);
begin
  AlphaBlendValue := TrackBar1.Position;
end;

procedure TSnipWin.ToolButton7Click(Sender: TObject);
begin
 memo1.Undo;
end;

procedure TSnipWin.ToolButton8Click(Sender: TObject);
begin
 // memo1.Redo;
 ShowMessage('Unavailable - Couldn''t find the SynMemo source');
end;

procedure TSnipWin.ToolButton3Click(Sender: TObject);
begin
 Memo1.CopyToClipboard;
end;

procedure TSnipWin.ToolButton4Click(Sender: TObject);
begin
 Memo1.CutToClipboard;
end;

procedure TSnipWin.ToolButton5Click(Sender: TObject);
begin
 Memo1.PasteFromClipboard;
end;

procedure TSnipWin.ToolButton10Click(Sender: TObject);
begin
 FD.FindText := memo1.SelText;
 FD.Execute;
end;

function TSnipWin.FindText(SearchStr, Text: string; Pos: Integer; Down,
  CaseSensitive: boolean): Integer;
begin
 Result := -1;
 Repeat
  If CaseSensitive then begin
   If Copy(Text, Pos, length(SearchStr)) = SearchStr then begin
    Result := Pos;
   end;
  end
   else
  begin
   If uppercase(Copy(Text, Pos, length(SearchStr))) = uppercase(SearchStr) then begin
    Result := Pos;
   end;
  end;
  If down then begin
   Inc(Pos);
  end
   else
  begin
   Dec(Pos);
  end;
 until (Result > -1) or (Pos < 1) or (Pos > length(Text));
 If Result > -1 then Dec(Result);
end;

procedure TSnipWin.FDFind(Sender: TObject);
var
  FoundAt: LongInt;
  StartPos: Integer;
  d, c: boolean;
begin
  with Memo1 do
  begin
    d := (frDown in FD.Options);
    c := (frMatchCase in FD.Options);

    { begin the search after the current selection if there is one }
    { otherwise, begin at the start of the text }
    if SelLength <> 0 then begin
     If d then StartPos := SelStart + SelLength + 1
      else StartPos := selStart - 1;
    end
     else
    begin
      StartPos := 0;
    end;

    { ToEnd is the length from StartPos to the end of the text in the rich edit control }

    FoundAt := FindText(FD.FindText, Memo1.Text, StartPos, d, c);
    if FoundAt <> -1 then begin
     SetFocus;
     SelStart := FoundAt;
     SelLength := Length(FD.FindText);
    end
     else
    begin
     MessageDlg('Search complete. There are no occurances within the selected scope.', mtInformation, [mbOK], 0);
    end;
  end;
end;

procedure TSnipWin.RDFind(Sender: TObject);
var
  FoundAt: LongInt;
  StartPos: Integer;
  d, c: boolean;
begin
  with Memo1 do
  begin
    d := (frDown in RD.Options);
    c := (frMatchCase in RD.Options);

    { begin the search after the current selection if there is one }
    { otherwise, begin at the start of the text }
    if SelLength <> 0 then begin
     If d then StartPos := SelStart + SelLength + 1
      else StartPos := selStart - 1;
    end
     else
    begin
      StartPos := 0;
    end;

    { ToEnd is the length from StartPos to the end of the text in the rich edit control }

    FoundAt := FindText(RD.FindText, Memo1.Text, StartPos, d, c);
    if FoundAt <> -1 then begin
     SetFocus;
     SelStart := FoundAt;
     SelLength := Length(RD.FindText);
    end
     else
    begin
     MessageDlg('Search complete. There are no occurances within the selected scope.', mtInformation, [mbOK], 0);
    end;
  end;
end;

procedure TSnipWin.RDReplace(Sender: TObject);
begin
 If Memo1.SelText <> '' then begin
  Memo1.SelText := RD.ReplaceText;
 end;
 If (frReplaceAll in RD.Options) then begin
  ReplaceALL;
 end;
end;

procedure TSnipWin.ToolButton11Click(Sender: TObject);
begin
 RD.FindText := memo1.SelText;
 RD.Execute;
end;

procedure TSnipWin.ReplaceAll;
var
  FoundAt: LongInt;
  StartPos, Cnt: Integer;
  c: boolean;
begin
  memo1.SelStart := 0;
  memo1.SelLength := 0;
  StartPos := 0;
  Cnt := 0;
  c := (frMatchCase in RD.Options);
  Repeat
   FoundAt := FindText(RD.FindText, Memo1.Text, StartPos, true, c);
   If FoundAt <> -1 then begin
    inc(Cnt);
    StartPos := FoundAt + 1;
    SetFocus;
    memo1.SelStart := FoundAt;
    memo1.SelLength := Length(RD.FindText);
    memo1.SelText := RD.ReplaceText;
   end;
  Until FoundAt = -1;
  MessageDlg('Replacing is done. The word "' + RD.FindText + '" has been replaced with "' + RD.ReplaceText + '", ' + IntToStr(cnt) + ' times', mtWarning, [mbOK], 0);
end;

procedure TSnipWin.SelectAll1Click(Sender: TObject);
begin
 Memo1.SelectAll;
end;

procedure TSnipWin.FormDeactivate(Sender: TObject);
begin
 If (Options.ToolWindows.AutoRollUp and (not Options.ToolWindows.ARUExcept.SnipWin)) then begin
  SetRoll(false);
 end;
end;

end.
