//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include <Printers.hpp>
#include "Unit1.h"
#include "fLayers.h"
#include "Unit2.h"
#include "Unit3.h"
#include "fSHX.h"
#include "fPaths.h"
#include <Math.h>
#include <Windows.hpp>
#include <SGExport.hpp>
#include <DXFImage.hpp>
#include <ShellAPI.hpp>
#include <DXFExport.hpp>
#include <CADToDXF.hpp>

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CSPIN"
#pragma resource "*.dfm"

AnsiString sNotVectorial = "Raster drawings can not be saved to DXF format";
TForm1 *Form1;
int Start;

struct tagRECTANGLEAROUND {
    TFRect Box;
    int PaperSpace;
} TRectangleAround;

//---------------------------------------------------------------------------

//#pragma option push -b-
//enum TSelectionMode = { smNone, smRectangle, smEllipse };
//#pragma option pop
//TSelectionMode FSelectionMode;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
TFPoint PtXMat(TFPoint P, TFMatrix M)
{
  TFPoint P1;
  P1.X = P.X * M[0][0] + P.Y * M[1][0] + P.Z * M[2][0] + M[3][0];
  P1.Y = P.X * M[0][1] + P.Y * M[1][1] + P.Z * M[2][1] + M[3][1];
  P1.Z = P.X * M[0][2] + P.Y * M[1][2] + P.Z * M[2][2] + M[3][2];
  return P1;
}

bool TForm1::CreateLines(int D, int AWidth, int AHeight)
{
  int I;
  int dx, dy;

  if (FIntPoints == NULL)
    FIntPoints = new TList;
  else
    FIntPoints->Clear();
  if (D <= 0)
    D = 1;
  dx = D;
  dy = D;
  for(I = 0;I*dx <= AWidth;I++)
  {
    FIntPoints->Add((void *)(I * dx));
    FIntPoints->Add(NULL);
    FIntPoints->Add((void *)(I * dx));
    FIntPoints->Add((void *)(AHeight));
  }
  for(I = 0; I*dy <= AHeight; I++)
  {
    FIntPoints->Add(NULL);
    FIntPoints->Add((void *)(I * dy));
    FIntPoints->Add((void *)(AWidth));
    FIntPoints->Add((void *)(I * dy));
  }
  if (FIntPoints->Count < 2)
    return false;
  else
    return true;
}

void TForm1::DrawPolyPolyLine(HDC DC)
{
  int C;
  unsigned long I, N;
  unsigned long *P;
  N = FIntPoints->Count >> 2;
  if (N == 0)
    return;
  C = FIntPoints->Count;
  for(I = 0; I < N; I++)
    FIntPoints->Add((void *)2);
  P = (unsigned long *)FIntPoints->List;
  P = P + C;
  PolyPolyline(DC,
    (tagPOINT *)FIntPoints->List,
    P,
    N);
  //PolyPolyline(
}

void TForm1::LoadOptions(void)
{
   if (!FOptions)
   {
    FOptions = new TIniFile(ExtractFilePath(Application->ExeName) + sSettings);
   }
   bUseSHXFonts = FOptions->ReadBool(sGeneral, sUseSHX, bUseSHXFonts);
   sSHXSearchPaths = FOptions->ReadString(sGeneral, sSHXPaths, sSHXSearchPaths);
   sDefaultSHXPath = FOptions->ReadString(sGeneral, sSHXPath, sDefaultSHXPath);
   sDefaultSHXFont = FOptions->ReadString(sGeneral, sSHXFont, sDefaultSHXFont);
}
//---------------------------------------------------------------------------

void TForm1::LoadStructure(void)
{
  AnsiString S_LStructure;
  try
  {
    ProgressBar1->Position = 0;
    ProgressBar1->Visible = true;
    Panel1->Caption = S_LStructure;
    Panel1->Update();
    TreeView1->Items->Clear();
    TreeView1->Items->BeginUpdate();
    if (FImg)
    {
      ProgressBar1->Max = FImg->Converter->Count();
      for (int i = 0; i < FImg->Converter->Main->Count; i++)
        AddTree(NULL, FImg->Converter->Main->Entities[i]);
    }
  }
  __finally
  {
    ProgressBar1->Position = 0;
    ProgressBar1->Visible = false;
    TreeView1->Items->EndUpdate();
    tbsStructure->Tag = 1;
  }
}


void TForm1::Time(void)
{
  int T = (GetCurrentTime() - Start) / 1000;
  TVarRec v[] = {T / 60, T % 60};
  Panel3->Caption = Format("%.2d:%.2d", v, ARRAYSIZE(v) - 1);
  Panel3->Update();
}

void TForm1::Open(AnsiString FileName)
{
  if (FileName == "") return;
  Start = GetCurrentTime();
  Screen->Cursor = crHourGlass;
  sgPaintBox->Orbit3D->Visible = false;
  try
  {
    MICloseClick(NULL);
    ProgressBar1->Visible = true;
    sgPaintBox->LoadFromFile(FileName);
    Graphics::TBitmap *Bmp = dynamic_cast<Graphics::TBitmap *>(sgPaintBox->Picture->Graphic);
    if (Bmp) sgPaintBox->Picture->Bitmap->HandleType = bmDDB;
    Panel1->Caption = UpperCase(ExtractFileName(FileName));
    HelpContext = 3;
    MIAutoClick(NULL);
    actMain->Update();
    if (FImg)
    {
      ViewLayouts();
      MiOEM->Checked = !FImg->Converter->OEM();
      SetImgOpt();
    }
    tbsStructure->TabVisible = true;
    Panel1->Caption = UpperCase(ExtractFileName(FileName));
    MIPrint->Enabled = true;
    MiOEMClick(NULL);
  }
  __finally
  {
	  cbLayoutsChange(cbLayouts);
	  pnlLayouts->Visible = (bool)(FImg);
    ProgressBar1->Position = 0;
    Screen->Cursor = crDefault;
	  ProgressBar1->Visible = false;
  }
}

void TForm1::AddTree(TTreeNode * Parent, TsgDXFEntity * E)
{
    Parent = TreeView1->Items->AddChildObject(Parent, E->EntName(), E);
    Application->ProcessMessages();
    ProgressBar1->Position =+ 1;
    for (int i = 0; i < E->Count; i++) AddTree(Parent, E->Entities[i]);
}

void __fastcall TForm1::MIAutoClick(TObject *Sender)
{
  sgPaintBoxScaling(NULL);
  MIAuto->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sgPaintBoxScaling(TObject *Sender)
{
  MIAuto->Enabled = true;
  BtnReal->Enabled = true;
  MIPrev->Enabled = sgPaintBox->HasPreviousView();
  BtnPrev->Enabled = MIPrev->Enabled;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MiOEMClick(TObject *Sender)
{
  MiOEM->Checked = !MiOEM->Checked;
  if (!FImg) return;
  if (MiOEM->Checked)
    FImg->Charset = OEM_CHARSET;
  else
    FImg->Charset = DEFAULT_CHARSET;
  ListBox1->Font->Charset = FImg->Charset;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SoftGoldHomePage1Click(TObject *Sender)
{
  ShellExecute(Handle, "open", "www.cadsofttools.com", "", "", SW_SHOW);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MIAboutClick(TObject *Sender)
{
  ShowMessage("DWG/DXF VCLs demo version \nPlease contact www.cadsofttools.com to order a full version");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  FsgPaintBox = new TSGDrawingNavigator(this);
  sgPaintBox->Parent = tbsImage;
  sgPaintBox->Align = alClient;
  sgPaintBox->RectZooming = true;
  sgPaintBox->ScalingOnMouseWheel = true;
  sgPaintBox->AutoFocus = true;
  sgPaintBox->OnPaint = sgPaintBoxPaint;
  sgPaintBox->OnChangeScale = sgPaintBoxScaling;
  sgPaintBox->OnProgress = sgPaintBoxProgress;
  sgPaintBox->OnMouseMove = sgPaintBoxMouseMove;
  LoadOptions();
  OpenDialog1->Filter = GraphicFilter(__classid(TGraphic));
  pnlLayouts->Visible = false;

  if (ParamCount > 0)
  {
    Open(ParamStr(1));
    OpenDialog1->FileName = ParamStr(1);
  }
  ProgressBar1->Align = alClient;
  ProgressBar1->Visible = false;
  btnWhiteBackgroundClick(NULL);
}
//---------------------------------------------------------------------------


void TForm1::Scroll(TShiftState Shift, bool Both, WORD Msg, WORD Code1,
  WORD Code2)
{
  if (Shift.Contains(ssCtrl)) Code1 = Code2;
  SendMessage(sgPaintBox->Handle, Msg, Code1, 0);
  if ((Both) && (Shift.Contains(ssCtrl)))
    SendMessage(sgPaintBox->Handle, WM_VSCROLL, Code1, 0);
}
void __fastcall TForm1::MICloseClick(TObject *Sender)
{
  FImg = NULL;
  sgPaintBox->Picture->Graphic = NULL;
  ListBox1->Clear();
  TreeView1->Items->Clear();
  Panel1->Caption = "";
  Panel3->Caption = "";
  pnlSize->Caption = "";
  pnlCoords->Caption = "";
  PageControl1->ActivePage = tbsImage;
  tbsStructure->TabVisible = false;
  tbsStructure->Tag = 0;
  ProgressBar1->Max = 100;
  HelpContext = 1;
  pnlLayouts->Visible = false;
  actMainUpdate(NULL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MIOpenClick(TObject *Sender)
{
  if (!OpenDialog1->Execute()) return;
  MICloseClick(NULL);
  Open(OpenDialog1->FileName);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::miSaveAsClick(TObject *Sender)
{
  TsgExport * E;
  TMetafileCanvas * vMC;
  TMetafile * vM;
  AnsiString vFileName;
  int vWidth, vHeight;
  double vRatio;
  TGraphic * vGr;

  if (sgPaintBox->Empty() || !SavePictureDialog->Execute()) return;
  vFileName = SavePictureDialog->FileName;
  vGr = sgPaintBox->Picture->Graphic;
  vWidth = vGr->Width;
  vHeight = vGr->Height;
  // Converting CAD-drawing width/height to Screen size for export
  if (vHeight)
    vRatio = (double)vWidth / vHeight;
  else
    vRatio = 1.0;
  if (vRatio <= 1.0)
  {
    vHeight = Screen->Height;
    vWidth = Ceil(vHeight * vRatio);
  }
  else
  {
    vWidth = Screen->Width;
    vHeight = Ceil(vWidth / vRatio);
  }
  switch (SavePictureDialog->FilterIndex)
  {
    case 1:
      if (AnsiLowerCase(ExtractFileExt(vFileName)) != ".bmp")
        vFileName = vFileName + ".bmp";
      break;
    case 2:
      if ((AnsiLowerCase(ExtractFileExt(vFileName)) != ".jpg") ||
         (AnsiLowerCase(ExtractFileExt(vFileName)) != ".jpeg"))
        vFileName = vFileName + ".jpg";
      break;
    case 3:
      if (AnsiLowerCase(ExtractFileExt(vFileName)) != ".emf")
        vFileName = vFileName + ".emf";
      break;
    case 4:
      vM = new TMetafile();
      try
      {
        vM->Width = vWidth;
        vM->Height = vHeight;
        vMC = new TMetafileCanvas(vM, 0);
        try
        {
          vMC->StretchDraw(Rect(0, 0, vWidth, vHeight), vGr);
        }
        __finally
        {
          delete vMC;
        }
        if (AnsiLowerCase(ExtractFileExt(vFileName)) != ".wmf")
          vFileName = vFileName + ".wmf";
        vM->SaveToFile(vFileName);
      }
      __finally
      {
        delete vM;
      }
      return;
    case 5:
      if (AnsiLowerCase(ExtractFileExt(vFileName)) != ".dxf")
        vFileName = vFileName + ".dxf";
      SaveToDXF(vFileName);
      return;
  }  /* switch SavePictureDialog->FilterIndex */
  E = new TsgExport();
  try
  {
    E->ExportTo(vGr, vFileName,
      TsgExportFormat(SavePictureDialog->FilterIndex-1), vWidth, vHeight);
  }
  __finally
  {
    delete E;
  }
}

//---------------------------------------------------------------------------
void __fastcall TForm1::MIPrintClick(TObject *Sender)
{
  if (sgPaintBox->Width > sgPaintBox->Height)
    Printer()->Orientation = poLandscape;
  else
    Printer()->Orientation = poPortrait;
  if (PrintDialog1->Execute())
  {
    double W = Printer()->PageWidth / sgPaintBox->Picture->Width;
    double H = Printer()->PageHeight / sgPaintBox->Picture->Height;
    if (W > H) W = H;
    int PW = W * sgPaintBox->Picture->Width;
    int PH = W * sgPaintBox->Picture->Height;
    Printer()->BeginDoc();
    Printer()->Canvas->StretchDraw(Bounds((Printer()->PageWidth - PW) / 2,
      (Printer()->PageHeight - PH) / 2, PW, PH), sgPaintBox->Picture->Graphic);
    Printer()->EndDoc();
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MIExitClick(TObject *Sender)
{
  Close();        
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MIPrevClick(TObject *Sender)
{
  sgPaintBox->CallPreviousView();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mmiScaleClick(TObject *Sender)
{
  if ((Sender == MIPrev)||(Sender == MIAuto)) return;
  sgPaintBox->AlterScale(((TComponent *)Sender)->Tag / 100.0, true,
    sgPaintBox->Center());
  ((TMenuItem *)Sender)->Checked = true;
  BtnReal->Enabled = !mmix100->Checked;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mmiDisabledClick(TObject *Sender)
{
  TsgDXFImage *sgDXFImage = dynamic_cast<TsgDXFImage *>(sgPaintBox->Picture->Graphic);
  if ((sgPaintBox->Empty()) || (sgDXFImage == NULL)) return;
  ((TsgDXFImage *)sgPaintBox->Picture->Graphic)->DrawMode = Dxfimage::dmGray;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mmiBlackClick(TObject *Sender)
{
  TsgDXFImage *sgDXFImage = dynamic_cast<TsgDXFImage *>(sgPaintBox->Picture->Graphic);
  if ((sgPaintBox->Empty()) || (sgDXFImage == NULL)) return;
  ((TsgDXFImage *)sgPaintBox->Picture->Graphic)->DrawMode = Dxfimage::dmBlack;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mmiNormalClick(TObject *Sender)
{
  TsgDXFImage *sgDXFImage = dynamic_cast<TsgDXFImage *>(sgPaintBox->Picture->Graphic);
  if ((sgPaintBox->Empty()) || (sgDXFImage == NULL)) return;
  ((TsgDXFImage *)sgPaintBox->Picture->Graphic)->DrawMode = Dxfimage::dmNormal;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TreeView1Change(TObject *Sender, TTreeNode *Node)
{
  if (!Node->Selected) return;
  TsgDXFEntity *E = ((TsgDXFEntity *)Node->Data);
  if (E == NULL)
    ListBox1->Clear();
  else
    if ((E->SrcStart == NULL) || (E->SrcEnd == NULL))
      ListBox1->Clear();
    else
    {
      AnsiString S = AnsiString(E->SrcStart, E->SrcEnd - E->SrcStart);
      ListBox1->Items->Text = S;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
  if (Key == VK_ESCAPE) Close();
  if (sgPaintBox->Empty()) return;
  if ((PageControl1->ActivePage != tbsImage) || (!Shift.Contains(ssCtrl))) return;
  switch (Key){
    case VK_ADD:
      BtnPlusClick(NULL);
      break;
    case VK_SUBTRACT:
      BtnMinusClick(NULL);
      break;
    case VK_MULTIPLY:
      BtnRealClick(NULL);
      break;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnPlusClick(TObject *Sender)
{
  sgPaintBox->AlterScale(2, false, sgPaintBox->Center());
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnMinusClick(TObject *Sender)
{
  sgPaintBox->AlterScale(0.5, false, sgPaintBox->Center());
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sgPaintBoxProgress(TObject *Sender,
      TProgressStage Stage, BYTE PercentDone, bool RedrawNow,
      const TRect &R, const AnsiString Msg)
{
  if (Stage == psStarting)
  {
    Panel1->Caption = Msg;
    Panel1->Update();
  }
  ProgressBar1->Position = PercentDone;
  Time();
  if (Stage == psEnding)
  {
    ProgressBar1->Position = 0;
    Panel1->Caption = UpperCase(ExtractFileName(OpenDialog1->FileName));
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PageControl1Changing(TObject *Sender,
      bool &AllowChange)
{
  FocusControl(NULL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnLayersClick(TObject *Sender)
{
  if (FImg) LayersDialogExecute(FImg, sgPaintBox);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::sgPaintBoxPaint(TObject *Sender)
{
  TFRect vExt;
  POINT vPt, vLeftTop, vRightBottom;
  TRect vPicRect;

  Graphics::TBitmap *vBmp = new Graphics::TBitmap();
  try
  {
    if ((sbShowBorder->Enabled)&&(sbShowBorder->Down))
    {
      vBmp->PixelFormat = pf8bit;
      vBmp->Width = sgPaintBox->Width;
      vBmp->Height = sgPaintBox->Height;
      vBmp->Assign(imgFrame->Picture->Bitmap);
      vBmp->Transparent = true;
      sgPaintBox->Canvas->StretchDraw(Rect(0, 0, sgPaintBox->Width, sgPaintBox->Height),
        vBmp);
    }
  }
  __finally
  {
    delete vBmp;
  }

  if (FImg)
  {
    vExt = FImg->Extents;
    vPicRect = sgPaintBox->PictureRect;
    if (FSelectionMode == 2)
    {
      vLeftTop.x = ceil((vPicRect.Right - vPicRect.Left) * (FTextBox.Left - vExt.Left) / (vExt.Right - vExt.Left)) + vPicRect.Left;
      vLeftTop.y = ceil((vPicRect.Bottom - vPicRect.Top) * (1 - (FTextBox.Top - vExt.Bottom) / (vExt.Top - vExt.Bottom))) + vPicRect.Top;
      vRightBottom.x = ceil((vPicRect.Right - vPicRect.Left) *  (FTextBox.Right - vExt.Left) / (vExt.Right - vExt.Left)) + vPicRect.Left;
      vRightBottom.y = ceil((vPicRect.Bottom - vPicRect.Top) * (1 - (FTextBox.Bottom - vExt.Bottom) / (vExt.Top - vExt.Bottom))) + vPicRect.Top;
      sgPaintBox->Canvas->Pen->Color = clRed;
      sgPaintBox->Canvas->Brush->Style = bsClear;
      sgPaintBox->Canvas->Ellipse(vLeftTop.x - 10, vLeftTop.y - 10, vRightBottom.x + 10, vRightBottom.y + 10);
    }
    if (sbDrid->Down)
    {
      if (CreateLines(ceil(FImg->AbsWidth()*FImg->Scale.X/speGridCount->Value),
        ceil(FImg->AbsWidth()*FImg->Scale.X),
        ceil(FImg->AbsHeight()*FImg->Scale.Y)))
      {
        sgPaintBox->Canvas->Pen->Color = clGray;
        OffsetViewportOrgEx(sgPaintBox->Canvas->Handle, vPicRect.Left, vPicRect.Top, &vPt);
        DrawPolyPolyLine(sgPaintBox->Canvas->Handle);
      }
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::btnIsWithoutBorderClick(TObject *Sender)
{
  if (FImg) FImg->IsWithoutBorder = !FImg->IsWithoutBorder;
}
//---------------------------------------------------------------------------

void TForm1::SetImgOpt(void)
{
  btnShowLineWeightClick(NULL);
  btnSplittedArcClick(NULL);
  btnDrawAllColorClick(NULL);
  btnWhiteBackgroundClick(NULL);
  SetPnlSizeCaption();
}

void TForm1::SetPnlSizeCaption(void)
{
  TsgDXFImage *vImg;
  #ifndef sgDXFONLY
  TsgHPGLImage *vHPGLImg;
  #endif
  if (!sgPaintBox->Empty())
  {
    #ifndef sgDXFONLY
    if (sgPaintBox->Picture->Graphic->ClassType() == __classid(TsgHPGLImage))
    {
      vHPGLImg = (TsgHPGLImage *)(sgPaintBox->Picture->Graphic);
      TVarRec v1[] = {vHPGLImg->MMWidth / 100.0, vHPGLImg->MMHeight / 100.0};
      pnlSize->Caption = Format("%.3f mm x %.3f mm", v1, 1);
    }
    else
    #endif
      if (sgPaintBox->Picture->Graphic->InheritsFrom(__classid(TsgDXFImage)))
      {
        vImg = (TsgDXFImage *)(sgPaintBox->Picture->Graphic);
        TVarRec v[] = {vImg->AbsWidth(), vImg->AbsHeight()};
        if (vImg->CurrentLayout->PlotSettings.PlotPaperUnits == 0)
          pnlSize->Caption = Format("%.3f in x %.3f in", v, 1);
        else
          pnlSize->Caption = Format("%.3f mm x %.3f mm", v, 1);
      }
  }
}

void __fastcall TForm1::btnFitToScreenClick(TObject *Sender)
{
  sgPaintBox->FitToSize();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::btnDrawAllColorClick(TObject *Sender)
{
  if (FImg)
  {
    if (btnDrawAllColor->Down)
      FImg->DrawMode = Dxfimage::dmNormal;
    else
      FImg->DrawMode = Dxfimage::dmBlack;
    sgPaintBox->Color = FImg->BackgroundColor;
  }
}
//---------------------------------------------------------------------------


void __fastcall TForm1::btnWhiteBackgroundClick(TObject *Sender)
{
  if (FImg)
  {
    if (btnWhiteBackground->Down)
    {
      FImg->BackgroundColor = clWhite;
      FImg->DefaultColor = clBlack;
    }
    else
    {
      FImg->BackgroundColor = clBlack;
      FImg->DefaultColor = clWhite;
    }
  }
  if (btnWhiteBackground->Down)
    sgPaintBox->Color = clWhite;
  else
    sgPaintBox->Color = clBlack;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::btnShowLineWeightClick(TObject *Sender)
{
  if (FImg)
    FImg->IsShowLineWeight = btnShowLineWeight->Down;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::btnSplittedArcClick(TObject *Sender)
{
  if (FImg)
    FImg->UseWinEllipse = !btnSplittedArc->Down;
}
//---------------------------------------------------------------------------

void TForm1::ViewLayouts()
{
  cbLayouts->Items->Clear();
  if (FImg)
  {
    for (int I = 0; I < FImg->LayoutsCount; I++)
      cbLayouts->Items->AddObject(FImg->Layouts[I]->Name, FImg->Layouts[I]);
    cbLayouts->ItemIndex = FImg->Converter->DefaultLayoutIndex;
    FImg->CurrentLayout = FImg->Layouts[cbLayouts->ItemIndex];
    pnlLayouts->Visible = true;
  }
}

void TForm1::Enable3DAxes(bool AIsEnabled)
{
  sb3DAxes->Down = false;
  sb3DAxes->Enabled = AIsEnabled;
  FImg->IsDraw3DAxes = sb3DAxes->Down;
}


void TForm1::Enable3DOrbit(bool AIsEnabled)
{
  sgPaintBox->Orbit3D->Visible = false;
  sb3DOrbit->Down = false;
  sb3DOrbit->Enabled = AIsEnabled;
}

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
  delete FIntPoints;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::sb3DOrbitClick(TObject *Sender)
{
  sb3DOrbit->Down = sb3DOrbit->Down | false;
  sgPaintBox->Orbit3D->Visible = sb3DOrbit->Down;
  sgPaintBox->Invalidate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::cbLayoutsChange(TObject *Sender)
{
  if (FImg)
  {
    if (FImg->CurrentLayout != FImg->Layouts[cbLayouts->ItemIndex])
    {
      if (cbLayouts->Items->Objects[cbLayouts->ItemIndex])
      {
        FImg->CurrentLayout = FImg->Layouts[cbLayouts->ItemIndex];
      }
    }
    Enable3DAxes(FImg->CurrentLayout->CADSpace != csUndefined);
    Enable3DOrbit(FImg->CurrentLayout->CADSpace != csUndefined);
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::sb3DAxesClick(TObject *Sender)
{
  sb3DAxes->Down = sb3DAxes->Down | false;
  if (sb3DAxes->Down)
    FImg->IsDraw3DAxes = true;
  else
    FImg->IsDraw3DAxes = false;
  sgPaintBox->Invalidate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::speNumPartsCircleChange(TObject *Sender)
{
  int Val = speNumPartsCircle->Value;
  if (Val >= 2)
  {
    FImg->Converter->NumberOfPartsInCircle = Val;
    sgPaintBox->Invalidate();
  }
  else
    speNumPartsCircle->Value = 2;
}

//---------------------------------------------------------------------------

void __fastcall TForm1::speNumPartsSplineChange(TObject *Sender)
{
  int Val = speNumPartsSpline->Value;
  if (Val >= 1)
  {
    FImg->Converter->NumberOfPartsInSpline = Val;
    sgPaintBox->Invalidate();
  }
  else
    speNumPartsSpline->Value = 1;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::sbShowBorderClick(TObject *Sender)
{
  sbShowBorder->Down = sbShowBorder->Down | false;
  sgPaintBox->Invalidate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::sbShowSHXFontsClick(TObject *Sender)
{
  SHXOptionsExecute(FOptions, Form1);
  sgPaintBox->Invalidate();
}
//---------------------------------------------------------------------------


void __fastcall TForm1::sbDridClick(TObject *Sender)
{
  sgPaintBox->Invalidate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::speGridCountChange(TObject *Sender)
{
  sgPaintBox->Invalidate();
}
//---------------------------------------------------------------------------

void TForm1::ActualGraphic(TMetafile *vResult)
{
  TMetafileCanvas *vMC;
  TRect vRect, vBoundRect, imgRectangle;
  HDC hDc;
  HRGN vRGN;
  TOSVersionInfo OSVersionInfo;
  double mmToPixelX, mmToPixelY;

  imgRectangle = sgPaintBox->ClientRect;

  hDc = GetDC(0);
  try
  {
    double hs = GetDeviceCaps(hDc,HORZSIZE);
    double hr = GetDeviceCaps(hDc,HORZRES);
    mmToPixelX = hs/hr;
    hs = GetDeviceCaps(hDc,VERTSIZE);
    hr = GetDeviceCaps(hDc,VERTRES);
    mmToPixelY = hs/hr;
  }
  __finally
  {
    ReleaseDC(Handle, hDc);
  }

  vRect = sgPaintBox->PictureRect;
  vRect.Left = vRect.Left - imgRectangle.Left;
  vRect.Top = vRect.Top - imgRectangle.Top;
  vRect.Right = vRect.Right - imgRectangle.Left;
  vRect.Bottom = vRect.Bottom - imgRectangle.Top;

  OSVersionInfo.dwOSVersionInfoSize = sizeof(TOSVersionInfo);
  GetVersionEx(&OSVersionInfo);
  if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  {
    vResult->MMWidth = (int)((imgRectangle.Right - imgRectangle.Left) * 1000 * mmToPixelX);
    vResult->MMHeight = (int)((imgRectangle.Bottom - imgRectangle.Top) * 1000 * mmToPixelY);
    vRect.Left = vRect.Left * 10;
    vRect.Top = vRect.Top * 10;
    vRect.Right = vRect.Right * 10;
    vRect.Bottom = vRect.Bottom * 10;
  }
  else // win9x
  {
    vResult->MMWidth = (int)((imgRectangle.Right - imgRectangle.Left) * 500 * mmToPixelX);
    vResult->MMHeight = (int)((imgRectangle.Bottom - imgRectangle.Top) * 500 * mmToPixelY);
    vRect.Left = vRect.Left * 5;
    vRect.Top = vRect.Top * 5;
    vRect.Right = vRect.Right * 5;
    vRect.Bottom = vRect.Bottom * 5;
  }
  vMC = new TMetafileCanvas(vResult, 0);
  try
  {
    if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
      vRGN = CreateRectRgn(0, 0, (imgRectangle.Right - imgRectangle.Left) * 10, (imgRectangle.Bottom - imgRectangle.Top) * 10);
    else
      vRGN = CreateRectRgn(0, 0, (imgRectangle.Right - imgRectangle.Left) * 5, (imgRectangle.Bottom - imgRectangle.Top) * 5);

    SelectClipRgn(vMC->Handle, vRGN);
    vMC->StretchDraw(vRect, sgPaintBox->Picture->Graphic);
    DeleteObject(vRGN);
  }
  __finally
  {
    delete vMC;
    if (FImg != NULL)
      FImg->IsShowBackground = True;
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BtnPrint2Click(TObject *Sender)
{
  POINT P;

  Win32Check(::GetCursorPos(&P));
  pmPrint->Popup((int)P.x, (int)P.y);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::pmiPrinrerClick(TObject *Sender)
{
  double W,H;
  int PW,PH;
  TMetafile *vGr;

  if (sgPaintBox->Picture != NULL)
  {
    if (sgPaintBox->Picture->Width > sgPaintBox->Picture->Height)
      Printer()->Orientation = poLandscape;
    else Printer()->Orientation = poPortrait;
  }
  if (PrintDialog1->Execute())
  {
    vGr = new TMetafile;
    try
    {
      ActualGraphic(vGr);
      W = (double)Printer()->PageWidth / (double)vGr->Width;
      H = (double)Printer()->PageHeight / (double)vGr->Height;
      if (W > H)
       W = H;
      PW = (int)(W * vGr->Width);
      PH = (int)(W * vGr->Height);
      Printer()->BeginDoc();
      Printer()->Canvas->StretchDraw(Bounds((Printer()->PageWidth-PW) / 2, (Printer()->PageHeight-PH) / 2, PW, PH), vGr);
      Printer()->EndDoc();
    }
    __finally
    {
     delete vGr;
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::pmiMetafileClick(TObject *Sender)
{
  TMetafile *vGr;

  SavePictureDialog->FilterIndex = 3;
  if ((sgPaintBox->Empty()) || (!SavePictureDialog->Execute()))
   return;
  vGr = new TMetafile;
  try
  {
    ActualGraphic(vGr);
    if (LowerCase(ExtractFileExt(SavePictureDialog->FileName)) == "")
      vGr->SaveToFile(SavePictureDialog->FileName+".emf");
    else
      vGr->SaveToFile(SavePictureDialog->FileName);
  }
  __finally
  {
    delete vGr;
  }
}
//---------------------------------------------------------------------------

TsgDXFEntity * TForm1::AddRectToConv(TFRect ABox)
{
  TsgDXFVertex *Vertex;
  TsgDXFPolyline *vPoly;

  vPoly = new TsgDXFPolyline;
  Vertex = new TsgDXFVertex;
  Vertex->Point = ABox.TopLeft;
  vPoly->AddEntity(Vertex);
  Vertex = new TsgDXFVertex;
  Vertex->Point = MakeFPoint(ABox.BottomRight.X, ABox.TopLeft.Y, ABox.TopLeft.Z);
  vPoly->AddEntity(Vertex);
  Vertex = new TsgDXFVertex;
  Vertex->Point = ABox.BottomRight;
  vPoly->AddEntity(Vertex);
  Vertex = new TsgDXFVertex;
  Vertex->Point = MakeFPoint(ABox.TopLeft.X, ABox.BottomRight.Y, ABox.BottomRight.Z);
  vPoly->AddEntity(Vertex);
  vPoly->SetColor(clRed);
  vPoly->SetLWeight(1);
  vPoly->Closed = true;
  return ((TsgDXFEntity *)vPoly);
}
//---------------------------------------------------------------------------

void TForm1::SelectEntities(void)
{
  int I;
  TsgDXFEntity *Ent;
  TsgDXFImage *Im;
  tagRECTANGLEAROUND *vRect;

  for(I = 0; I < FSelectedEntities->Count; I++)
  {
    vRect = (tagRECTANGLEAROUND *)(FSelectedEntities->Items[I]);

    Ent = AddRectToConv(vRect->Box);
    if (Ent)
    {
      Im = dynamic_cast<TsgDXFImage *>(sgPaintBox->Picture->Graphic);
      Im->Converter->Sections[csEntities]->AddEntity(Ent);
      if (Im->Converter->OnCreate != NULL)
        Im->Converter->OnCreate(Ent);
      Im->Converter->Loads(Ent);
      Ent->PaperSpace = vRect->PaperSpace;
      sgPaintBox->Invalidate();
    }
  }
}
//---------------------------------------------------------------------------

int __fastcall TForm1::ReadCADEntities(TsgDXFEntity *Entity)
{
  long double vScale;
  AnsiString S1, S2;
  double mmToPixelX;
  tagRECTANGLEAROUND *vRectAround;
  TFPoint P;
  TsgDXFAttrib *CurAttrib;
  TFRect vBox;
  bool vAttribFlag;

  if (FFindFlag)
    return 0;

  if((Entity->ClassType() == __classid(TsgDXFAttrib))||
     (Entity->ClassType() == __classid(TsgDXFMText))||
     (Entity->ClassType() == __classid(TsgDXFText)))
  {
    FTextPoint = ((TsgDXFAttrib *)Entity)->Point;
    if (Entity->ClassType() == __classid(TsgDXFMText))
    {
      //FTextPoint = ((TsgDXFMText *)Entity)->Point;
    }
    S1 = AnsiUpperCase(FSearchingText);
    S2 = AnsiUpperCase(((TsgDXFText *)(Entity))->Text);
    vAttribFlag = false;
    memset(&vBox, sizeof(TFRect), 0);
    if (FCADParams.Insert != NULL)
    {
      P = PtXMat(((TsgDXFText *)(Entity))->StartPoint, FCADParams.Matrix);
      CurAttrib = FCADParams.Insert->Attrib(S2, P);
      if (CurAttrib)
      {
        S2 = CurAttrib->Text;
        vBox = CurAttrib->Box;
        vAttribFlag = true;
      }
    }
    if (AnsiPos(S1, S2) > 0)
    {
      FSearchResult = true;
      FTextPoint = PtXMat(((TsgDXFText *)(Entity))->StartPoint, FCADParams.Matrix);
      mmToPixelX = GetDeviceCaps(GetDC(0),HORZSIZE);
      mmToPixelX /= GetDeviceCaps(GetDC(0),HORZRES);
      FTextBox.TopLeft = PtXMat(((TsgDXFText *)(Entity))->Box.TopLeft, FCADParams.Matrix);
      FTextBox.BottomRight = PtXMat(((TsgDXFText *)(Entity))->Box.BottomRight, FCADParams.Matrix);
      vScale = (mmToPixelX * sgPaintBox->Parent->Height) /
         fabs(FTextBox.TopLeft.Y - FTextBox.BottomRight.Y) * 5.0;
      sgPaintBox->ShowPoint(FTextPoint, vScale);
      if (!FSearchModeIsAll)
        FFindFlag = true;
      if (FSelectionMode == 1)//(FSelectionMode = smRectangle)
      {
        vRectAround = new tagRECTANGLEAROUND;
        if (!vAttribFlag)
        {
          vRectAround->Box.TopLeft = PtXMat(Entity->Box.TopLeft, FCADParams.Matrix);
          vRectAround->Box.BottomRight = PtXMat(Entity->Box.BottomRight, FCADParams.Matrix);
        }
        else
          vRectAround->Box = vBox;
        vRectAround->PaperSpace = (int)(FImg->Layouts[0] != FImg->CurrentLayout);
        FSelectedEntities->Add(vRectAround);
      }
    }
  }
  return 0;
}
//---------------------------------------------------------------------------

bool __fastcall TForm1::FindText(AnsiString S, int ASelection, bool ASearch)
{
  int I;

  FSearchingText = S;
  FSelectionMode = ASelection;
  FSearchModeIsAll = ASearch;
  FSearchResult = false;
  memset(FCADParams.Matrix, sizeof(TFMatrix), 0);
  FCADParams.Matrix[0][0] = 1.0;
  FCADParams.Matrix[1][1] = 1.0;
  FCADParams.Matrix[2][2] = 1.0;
  //Matrix = &FCADParams.Matrix[0][0];
  //*Matrix = IdentityMat();
  FImg->Converter->AutoInsert = true; // to get all the elements inside of inserts
  FFindFlag = false;
  FSelectedEntities = new TList;
  try
  {
    FImg->Converter->Iterate((TsgCADEntityProc)(& ReadCADEntities),
      NULL, FCADParams);
    SelectEntities();
  }
  __finally
  {
    for(I = 0; I < FSelectedEntities->Count; I++)
      delete ((tagRECTANGLEAROUND *)FSelectedEntities->Items[I]);
    FSelectedEntities->Free();
  }
  return FSearchResult;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mmiFindTextClick(TObject *Sender)
{
  TForm3 *Form3;

  Form3 = new TForm3(this);
  try
  {
    Form3->ShowModal();
  }
  __finally
  {
    Form3->Free();
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::sgPaintBoxMouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
  TFPoint vPt;
  AnsiString S, vUnits;
  if (GetImg())
  {
    vPt = sgPaintBox->GetDrawingCoords(X, Y, vUnits);
    TVarRec v[] = {vPt.X, vPt.Y, vPt.Z};
    S = Format("(%.3f; %.3f; %.3f)", v, 2);
    if ((vUnits != NULL)&&(vUnits != ""))
      S = S + " (" + vUnits + ")";
    pnlCoords->Caption = S;
  }
}
//---------------------------------------------------------------------------


void __fastcall TForm1::mmiShowPointClick(TObject *Sender)
{
  TfrmShowPoint *frmShowPoint;

  frmShowPoint = new TfrmShowPoint(this);
  try
  {
    frmShowPoint->ShowModal();
  }
  __finally
  {
    frmShowPoint->Free();
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::mmiObjectSnapAllClick(TObject *Sender)
{
  mmiObjectSnapAll->Checked = !mmiObjectSnapAll->Checked;
  //Object Snap. Snap mode setup
  if (mmiObjectSnapAll->Checked)
    sgPaintBox->SnapControl->SnapMode = osAll;
  else
    sgPaintBox->SnapControl->SnapMode = osNone;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormShow(TObject *Sender)
{
  Action = actMain;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::actMainUpdate(TObject *Sender)
{
  bool vNotEmpty;
  vNotEmpty = !sgPaintBox->Empty();
  FImg = GetImg();
  BtnSave->Enabled = vNotEmpty;
  BtnPrint->Enabled = vNotEmpty;
  BtnPrint2->Enabled = vNotEmpty;
  BtnPlus->Enabled = vNotEmpty;
  BtnMinus->Enabled = vNotEmpty;
  BtnReal->Enabled = vNotEmpty;
  BtnPrev->Enabled = vNotEmpty;
  btnLayers->Enabled = (bool)(FImg);
  btnFitToScreen->Enabled = vNotEmpty;
  btnIsWithoutBorder->Enabled = (bool)(FImg);
  btnDrawAllColor->Enabled = (bool)(FImg);
  btnBlackWhite->Enabled = (bool)(FImg);
  btnWhiteBackground->Enabled = true;
  btnBlackBackground->Enabled = true;
  btnShowLineWeight->Enabled = (bool)(FImg);
  btnHideLineWeight->Enabled = (bool)(FImg);
  btnSplittedArc->Enabled = (bool)(FImg);
  btnArcNormal->Enabled = (bool)(FImg);
  sb3DOrbit->Enabled = (bool)(FImg)&&(FImg->CurrentLayout->IsModel);
  sb3DAxes->Enabled = (bool)(FImg);
  sbShowBorder->Enabled = (bool)(FImg);
  sbDrid->Enabled = (bool)(FImg);
  miSaveAs->Enabled = vNotEmpty;
  MIPrint->Enabled = vNotEmpty;
  MIClose->Enabled = vNotEmpty;
  MiOEM->Enabled = (bool)(FImg);
  mmiShowPoint->Enabled = (bool)(FImg);
  mmiFindText->Enabled = (bool)(FImg);
  MIAuto->Enabled = vNotEmpty;
  MIPrev->Enabled = vNotEmpty;
  mmix10->Enabled = vNotEmpty;
  mmix25->Enabled = vNotEmpty;
  mmix50->Enabled = vNotEmpty;
  mmix100->Enabled = vNotEmpty;
  mmix200->Enabled = vNotEmpty;
  mmix400->Enabled = vNotEmpty;
  mmix800->Enabled = vNotEmpty;
  mmiDisabled->Enabled = (bool)(FImg);
  mmiBlack->Enabled = (bool)(FImg);
  mmiNormal->Enabled = (bool)(FImg);
  mmiObjectSnapAll->Enabled = (bool)(FImg);
  mmiSaveAsBigEMF->Enabled = (bool)(FImg);
}
//---------------------------------------------------------------------------

TsgDXFImage * __fastcall TForm1::GetImg()
{
  if (!(sgPaintBox->Empty())&&(sgPaintBox->Picture->Graphic->InheritsFrom(__classid(TsgDXFImage))))
    return (TsgDXFImage *)(sgPaintBox->Picture->Graphic);
  else
    return NULL;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BtnRealClick(TObject *Sender)
{
  sgPaintBox->Scale = 1;  
}
//---------------------------------------------------------------------------

void __fastcall TForm1::tbsStructureShow(TObject *Sender)
{
  if (!tbsStructure->Tag)
    LoadStructure();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
  if (!FOptions)
    FOptions->UpdateFile();
}
//---------------------------------------------------------------------------

/* TForm1::SaveToDXF

  Saving in DXF format.                      */
void __fastcall TForm1::SaveToDXF(AnsiString AFileName)
{
  TsgDXFExport * vExpMetafile;
  TsgCADtoDXF * vExpCADfile;
  TGraphic * vGr;

  vGr = sgPaintBox->Picture->Graphic;
  if (!vGr) return;
  if (vGr->InheritsFrom(__classid(TsgDXFImage)) ||
     vGr->InheritsFrom(__classid(TMetafile)))
  {
    if (!vGr->InheritsFrom(__classid(TsgDXFImage)))
    {
      vExpMetafile = new TsgDXFExport();
      try
      {
        vExpMetafile->Canvas->StretchDraw(Rect(0, 0, vGr->Width, vGr->Height), vGr);
        vExpMetafile->EndDraw();
        vExpMetafile->SaveToFile(AFileName);
      }
      __finally
      {
        delete vExpMetafile;
      }
    }
    else
    {
      vExpCADfile = new TsgCADtoDXF((TsgDXFImage *)vGr);
      try
      {
        vExpCADfile->SaveToFile(AFileName);
      }
      __finally
      {
        delete vExpCADfile;
      }
    }
    MessageBox(Application->Handle, "DXF Export is made via DXF Export VCL software which is not part of CAD Import VCL and should be bought additionally if needed.", "WARNING", MB_ICONWARNING);
  }
  else
    ShowMessage(sNotVectorial);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mmiSaveAsBigEMFClick(TObject *Sender)
{
  TsgDXFImage * vCAD;
  double vRatio;
  int vWidth, vHeight;

  vCAD = GetImg();
  if (!vCAD) return;
  SavePictureDialogEMF->FileName = "*.emf";
  if (!SavePictureDialogEMF->Execute()) return;
  if (LowerCase(ExtractFileExt(SavePictureDialogEMF->FileName)) != ".emf")
    SavePictureDialogEMF->FileName = ChangeFileExt(SavePictureDialogEMF->FileName, ".emf");

  if (vCAD->AbsHeight() != 0)
    vRatio = vCAD->AbsWidth() / vCAD->AbsHeight();
  else
    vRatio = 1.0;
  if (vRatio <= 1.0)
  {
    vHeight = 3276700;
    vWidth = Ceil(vHeight * vRatio);
  }
  else
  {
    vWidth = 3276700;
    vHeight = Ceil(vWidth / vRatio);
  }
  vCAD->ExportToMetafile(SavePictureDialogEMF->FileName, vWidth, vHeight);
}
//---------------------------------------------------------------------------

