{
*******************************************************************
*******************************************************************
**                  Dev-Pascal                                   **
**                                                                **
** Main.pas: Main unit for the IDE. Parent form.                 **
**                                                               **
** Copyright Bloodshed Software.                                 **
** UNDER THE GNU GENERAL PUBLIC LICENSE. See Copying.txt before  **
** modifiyng or distributing the sources and binaries of         **
** Dev-Pascal                                                    **
**                                                               **
** Please send your modification to dev@bloodshed.net            **
**                                                               **
** Colin Laplace                                                 **
** email: webmaster@bloodshed.net                                **
** http://www.bloodshed.net/                                     **
*******************************************************************
*******************************************************************
}
{$ifdef ver100}
   {$define Old_Delphi}
{$endif}

{$ifdef ver120}
   {$define Old_Delphi}
{$endif}


unit Main;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, Registry, Clipbrd, marsCap, ComCtrls, TB97, IniFiles,
  Project, Utils, ExtCtrls, Version, ImgList, StdCtrls, MdiEdit, SynEditHighlighter, SynEditExport,
  TB97Tlbr, TB97Ctls;

type
  TIconType = Byte;
  TMainForm = class(TForm)
    MainMenu: TMainMenu;
    FileMenu: TMenuItem;
    NewItem: TMenuItem;
    N1: TMenuItem;
    ExitItem: TMenuItem;
    WindowMenu: TMenuItem;
    TileItem: TMenuItem;
    CascadeItem: TMenuItem;
    ArrangeiconsItem: TMenuItem;
    OpenFileDialog: TOpenDialog;
    HelpDevPasMenu: TMenuItem;
    HelponDevPasItem: TMenuItem;
    N2: TMenuItem;
    AboutBloodshedDevPasItem: TMenuItem;
    SaveasItem: TMenuItem;
    PrintItem: TMenuItem;
    PrinterSetupItem: TMenuItem;
    CloseItem: TMenuItem;
    N3: TMenuItem;
    StatusBar: TStatusBar;
    EditMenu: TMenuItem;
    SearchMenu: TMenuItem;
    FindItem: TMenuItem;
    FindnextItem: TMenuItem;
    CompileMenu: TMenuItem;
    CompileItem: TMenuItem;
    RunItem: TMenuItem;
    UndoItem: TMenuItem;
    N4: TMenuItem;
    CutItem: TMenuItem;
    CopyItem: TMenuItem;
    PasteItem: TMenuItem;
    N5: TMenuItem;
    SelectallItem: TMenuItem;
    PrinterSetupDialog: TPrinterSetupDialog;
    OptionsMenu: TMenuItem;
    CompileroptionsItem: TMenuItem;
    EnvironmentoptionsItem: TMenuItem;
    ToolsMenu: TMenuItem;
    ExplorerItem: TMenuItem;
    DosshellItem: TMenuItem;
    N7: TMenuItem;
    GotolineItem: TMenuItem;
    MarsCaption: TMarsCaption;
    N8: TMenuItem;
    DebugItem: TMenuItem;
    ReOpenItem: TMenuItem;
    ClearhistoryItem: TMenuItem;
    N11: TMenuItem;
    N12: TMenuItem;
    NewprojectItem: TMenuItem;
    OpenprojectItem: TMenuItem;
    CloseprojectItem: TMenuItem;
    SaveUnitItem: TMenuItem;
    ProjectMenu: TMenuItem;
    AddtoprojectItem: TMenuItem;
    RemovefromprojectItem: TMenuItem;
    SaveProject: TSaveDialog;
    OpenAddDialog: TOpenDialog;
    SaveallItem: TMenuItem;
    N6: TMenuItem;
    ProjectoptionsItem: TMenuItem;
    MainToolBar: TToolbar97;
    NewProjectBtn: TToolbarButton97;
    SaveBtn: TToolbarButton97;
    NewFileBtn: TToolbarButton97;
    OpenBtn: TToolbarButton97;
    ToolbarSep971: TToolbarSep97;
    CloseBtn: TToolbarButton97;
    ToolbarSep972: TToolbarSep97;
    UndoBtn: TToolbarButton97;
    FindBtn: TToolbarButton97;
    PrintBtn: TToolbarButton97;
    CompileToolbar: TToolbar97;
    DebugBtn: TToolbarButton97;
    RunBtn: TToolbarButton97;
    CompileBtn: TToolbarButton97;
    DockUpperTop: TDock97;
    OptToolbar: TToolbar97;
    AboutBtn: TToolbarButton97;
    HelpBtn: TToolbarButton97;
    ToolsBtn: TToolbarButton97;
    ExplorerBtn: TToolbarButton97;
    EnvOptBtn: TToolbarButton97;
    CompOptBtn: TToolbarButton97;
    ToolbarSep974: TToolbarSep97;
    ToolbarSep975: TToolbarSep97;
    CheckforDevPasUpdatesItem: TMenuItem;
    ToolbarSep976: TToolbarSep97;
    CheckBtn: TToolbarButton97;
    DockTop: TDock97;
    ViewMenu: TMenuItem;
    ToolbarsItem: TMenuItem;
    MainItem: TMenuItem;
    ProjectItem: TMenuItem;
    OptionItem: TMenuItem;
    StatusbarItem: TMenuItem;
    DockRight: TDock97;
    N13: TMenuItem;
    CloseAllItem: TMenuItem;
    N9: TMenuItem;
    CompilingresultsItem: TMenuItem;
    PopupMenu: TPopupMenu;
    ClearPopItem: TMenuItem;
    EditresourcefileItem: TMenuItem;
    N10: TMenuItem;
    CompilandRunItem: TMenuItem;
    CompileAndRunBtn: TToolbarButton97;
    CompResultBtn: TToolbarButton97;
    ToggleBookmarksItem: TMenuItem;
    Bookmark9: TMenuItem;
    Bookmark8: TMenuItem;
    Bookmark7: TMenuItem;
    Bookmark6: TMenuItem;
    Bookmark5: TMenuItem;
    Bookmark4: TMenuItem;
    Bookmark3: TMenuItem;
    Bookmark2: TMenuItem;
    Bookmark1: TMenuItem;
    Bookmark0: TMenuItem;
    GotoBookmarksItem: TMenuItem;
    Bookmark92: TMenuItem;
    Bookmark82: TMenuItem;
    Bookmark72: TMenuItem;
    Bookmark62: TMenuItem;
    Bookmark52: TMenuItem;
    Bookmark42: TMenuItem;
    Bookmark32: TMenuItem;
    Bookmark22: TMenuItem;
    Bookmark12: TMenuItem;
    Bookmark02: TMenuItem;
    N14: TMenuItem;
    RedoItem: TMenuItem;
    InsertItem: TMenuItem;
    CommentheaderItem: TMenuItem;
    MainFunctionItem: TMenuItem;
    SpecialsBar: TToolbar97;
    ToggleBtn: TToolbarButton97;
    InsertMenu: TPopupMenu;
    CommentheaderPopItem: TMenuItem;
    MainfunctionPopItem: TMenuItem;
    NewAllBtn: TToolbarButton97;
    ToolbarSep977: TToolbarSep97;
    ToolbarSep978: TToolbarSep97;
    GotoBtn: TToolbarButton97;
    SpecialsItem: TMenuItem;
    ToggleMenu: TPopupMenu;
    GotoMenu: TPopupMenu;
    Bookmark03: TMenuItem;
    Bookmark13: TMenuItem;
    Bookmark23: TMenuItem;
    Bookmark33: TMenuItem;
    Bookmark43: TMenuItem;
    Bookmark53: TMenuItem;
    Bookmark63: TMenuItem;
    Bookmark73: TMenuItem;
    Bookmark83: TMenuItem;
    Bookmark93: TMenuItem;
    Bookmark04: TMenuItem;
    Bookmark14: TMenuItem;
    Bookmark24: TMenuItem;
    Bookmark34: TMenuItem;
    Bookmark44: TMenuItem;
    Bookmark54: TMenuItem;
    Bookmark64: TMenuItem;
    Bookmark74: TMenuItem;
    Bookmark84: TMenuItem;
    Bookmark94: TMenuItem;
    ProjectManagerViewItem: TMenuItem;
    ProjectImage_Default: TImageList;
    WinMainfunctionItem: TMenuItem;
    WinMainfunctionPopItem: TMenuItem;
    MessageBoxItem: TMenuItem;
    MessageBoxPopItem: TMenuItem;
    UnitPopup: TPopupMenu;
    RemoveFilefromprojectPopItem: TMenuItem;
    ProjectPopup: TPopupMenu;
    AddtoprojectPopItem: TMenuItem;
    RemovefromprojectPopItem: TMenuItem;
    N16: TMenuItem;
    ProjectoptionsPopItem: TMenuItem;
    EditresourcefilePopItem: TMenuItem;
    ReplaceItem: TMenuItem;
    ExporttoItem: TMenuItem;
    HTMLItem: TMenuItem;
    RTFItem: TMenuItem;
    NewunitinprojectItem: TMenuItem;
    RenamefilePopItem: TMenuItem;
    NewunitinprojectPopItem: TMenuItem;
    N19: TMenuItem;
    ProjecttoHTMLItem: TMenuItem;
    SetupCreatorItem: TMenuItem;
    SetupBtn: TToolbarButton97;
    TutorialItem: TMenuItem;
    GNUDebuggerhelpItem: TMenuItem;
    HelpMenu: TPopupMenu;
    HelponDevPasPopItem: TMenuItem;
    TutorialPopItem: TMenuItem;
    GNUDebuggerhelpPopItem: TMenuItem;
    MenuImages_Gnome: TImageList;
    GotoLineBtn: TToolbarButton97;
    N20: TMenuItem;
    N21: TMenuItem;
    ifPopItem: TMenuItem;
    whilePopItem: TMenuItem;
    dowhilePopItem: TMenuItem;
    N23: TMenuItem;
    forPopItem: TMenuItem;
    ifItem: TMenuItem;
    whileItem: TMenuItem;
    dowhileItem: TMenuItem;
    forItem: TMenuItem;
    N25: TMenuItem;
    N26: TMenuItem;
    N27: TMenuItem;
    MessageControl: TPageControl;
    CompSheet: TTabSheet;
    CompilerOutput: TListView;
    ResSheet: TTabSheet;
    ResourceOutput: TListBox;
    ToolbarSep979: TToolbarSep97;
    MinimizeallItem: TMenuItem;
    N28: TMenuItem;
    NextItem: TMenuItem;
    PreviousItem: TMenuItem;
    N30: TMenuItem;
    ClosefilePopItem: TMenuItem;
    ExportDialog: TSaveDialog;
    ProjectView: TTreeView;
    SplitterLeft: TSplitter;
    N31: TMenuItem;
    CopyPopItem: TMenuItem;
    SplitterBottom: TSplitter;
    ProjectToolbar: TToolbar97;
    AddToProjBtn: TToolbarButton97;
    RemoveFromProjBtn: TToolbarButton97;
    ProjOptBtn: TToolbarButton97;
    EditResBtn: TToolbarButton97;
    ToolbarSep973: TToolbarSep97;
    CompileandRunItem: TMenuItem;
    N17: TMenuItem;
    GenerateMakeFileItem: TMenuItem;
    ToolbarSep9710: TToolbarSep97;
    MakeFileBtn: TToolbarButton97;
    N18: TMenuItem;
    BloodshedSoftwarehomepageItem: TMenuItem;
    MingwcompilerhomepageItem: TMenuItem;
    N32: TMenuItem;
    RebuildallItem: TMenuItem;
    RebuildAllBtn: TToolbarButton97;
    LogSheet: TTabSheet;
    LogBox: TMemo;
    DateandtimeItem: TMenuItem;
    DateandtimePopItem: TMenuItem;
    NewresourcefileItem: TMenuItem;
    N33: TMenuItem;
    NewTemplatefile1: TMenuItem;
    N34: TMenuItem;
    N15: TMenuItem;
    InsertBtn: TToolbarButton97;
    ToolbarSep9711: TToolbarSep97;
    NewAllMenu: TPopupMenu;
    NewProjectPopItem: TMenuItem;
    NewTemplatePopItem: TMenuItem;
    N35: TMenuItem;
    NewSourcefilePopItem: TMenuItem;
    NewResourcefilePopItem: TMenuItem;
    Fullscreenmode: TMenuItem;
    N36: TMenuItem;
    CompileroutputItem: TMenuItem;
    ShowCompilerOutput1: TMenuItem;
    N37: TMenuItem;
    Showonlywhenneeded1: TMenuItem;
    PackageManagerItem: TMenuItem;
    ConfiguretoolsItem: TMenuItem;
    ToolSeparator: TMenuItem;
    MenuImages_Default: TImageList;
    N29: TMenuItem;
    Default1: TMenuItem;
    ToolbarIconsStyle1: TMenuItem;
    Gnome1: TMenuItem;
    ProjectImage_Gnome: TImageList;
    Setmainunit1: TMenuItem;
    SetMainUnitBtn: TToolbarButton97;
    Unitbeginend1: TMenuItem;
    Unitbeginend2: TMenuItem;
    GNUPascalhelpitem: TMenuItem;
    procedure ExitItemClick(Sender: TObject);
    procedure NewItemClick(Sender: TObject);
    procedure TileItemClick(Sender: TObject);
    procedure CascadeItemClick(Sender: TObject);
    procedure ArrangeiconsItemClick(Sender: TObject);
    procedure ToolButton3Click(Sender: TObject);
    procedure PrinterSetupItemClick(Sender: TObject);
    procedure AboutBloodshedDevPasItemClick(Sender: TObject);
    procedure CompileroptionsItemClick(Sender: TObject);
    procedure EnvironmentoptionsItemClick(Sender: TObject);
    procedure ExplorerItemClick(Sender: TObject);
    procedure DosshellItemClick(Sender: TObject);
    procedure DevPasHelpPopupClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure SavePosition;       // Save form position
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormActivate(Sender: TObject);
    procedure OpenHistory;
    procedure SaveFileHistory(const Filename:string);
    procedure ClearhistoryItemClick(Sender: TObject);
    procedure CloseBtnClick(Sender: TObject);
    procedure SaveFileMenu(Sender: TObject);
    procedure PrintBtnClick(Sender: TObject);
    procedure UndoBtnClick(Sender: TObject);
    procedure FindBtnClick(Sender: TObject);
    procedure RunBtnClick(Sender: TObject);
    procedure DebugBtnClick(Sender: TObject);
    procedure NewprojectItemClick(Sender: TObject);
    procedure FileMenuClick(Sender: TObject);
    procedure EditMenuClick(Sender: TObject);
    procedure ProjectMenuClick(Sender: TObject);
    procedure CompileMenuClick(Sender: TObject);
    procedure CompileBtnClick(Sender: TObject);
    procedure CutItemClick(Sender: TObject);
    procedure CloseItemClick(Sender: TObject);
    procedure CopyItemClick(Sender: TObject);
    procedure PasteItemClick(Sender: TObject);
    procedure SelectallItemClick(Sender: TObject);
    procedure FindnextItemClick(Sender: TObject);
    procedure GotolineItemClick(Sender: TObject);
    procedure SearchMenuClick(Sender: TObject);
    procedure OpenprojectItemClick(Sender: TObject);
    procedure CloseprojectItemClick(Sender: TObject);
    function Compile(Sender: TObject; RebuildAll : boolean) : boolean;
    procedure AddtoprojectItemClick(Sender: TObject);
    procedure RemovefromprojectItemClick(Sender: TObject);
    procedure SaveallItemClick(Sender: TObject);
    procedure ProjectoptionsItemClick(Sender: TObject);
    procedure CheckParams;
    procedure SaveasItemClick(Sender: TObject);
    procedure CreateNewIniFile(CreateIni : boolean);
    procedure CheckforDevPasUpdatesItemClick(Sender: TObject);
    procedure MainItemClick(Sender: TObject);
    procedure ProjectItemClick(Sender: TObject);
    procedure OptionItemClick(Sender: TObject);
    procedure StatusbarItemClick(Sender: TObject);
    procedure ViewMenuClick(Sender: TObject);
    procedure ToolbarsItemClick(Sender: TObject);
    procedure CloseAllClick(Sender: TObject);
    procedure AnalyseOutput;
    procedure CompilingresultsItemClick(Sender: TObject);
    procedure OutputDblClick(Sender: TObject);
    procedure ShowAllOutPut;
    procedure OutputClick(Sender: TObject);
    procedure OpenHistoryFile(Sender: TObject);
    procedure ClearPopItemClick(Sender: TObject);
    procedure SaveOutputPosition;
    procedure EditresourcefileItemClick(Sender: TObject);
    procedure CompileAndExecuteClick(Sender: TObject);
    procedure MouseEnter(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Bookmark0Click(Sender: TObject);
    procedure Bookmark02Click(Sender: TObject);
    procedure RedoItemClick(Sender: TObject);
    procedure CommentheaderItemClick(Sender: TObject);
    procedure MainFunctionItemClick(Sender: TObject);
    procedure ifdefItemClick(Sender: TObject);
    procedure ifndefItemClick(Sender: TObject);
    procedure includeItemClick(Sender: TObject);
    procedure InsertItemClick(Sender: TObject);
    procedure InsertBtnClick(Sender: TObject);
    procedure InsertMenuPopup(Sender: TObject);
    procedure SpecialsItemClick(Sender: TObject);
    procedure SpecialsBarClose(Sender: TObject);
    procedure OptToolbarClose(Sender: TObject);
    procedure CompileToolbarClose(Sender: TObject);
    procedure MainToolBarClose(Sender: TObject);
    procedure MouseExit(Sender: TObject);
    procedure ToggleBtnClick(Sender: TObject);
    procedure GotoBtnClick(Sender: TObject);
    procedure ProjectManagerViewItemClick(Sender: TObject);
    function MakeProjectNode(Name : string) : TTreeNode;
    function MakeNewFileNode(s : string) : TTreeNode;
    procedure WinMainfunctionItemClick(Sender: TObject);
    procedure MessageBoxItemClick(Sender: TObject);
    procedure UpdateSyntaxColor;
    procedure RemoveFilefromprojectPopItemClick(Sender: TObject);
    procedure ReplaceItemClick(Sender: TObject);
    procedure HTMLItemClick(Sender: TObject);
    procedure RenamefilePopItemClick(Sender: TObject);
    procedure WriteDllFiles(DllName, DllFileName, DllSourceName, TestDllName, TestFileName, TestSourceName : string);
    procedure ProjecttoHTMLItemClick(Sender: TObject);
    procedure WindowMenuClick(Sender: TObject);
    procedure ProjectManagerBarClose(Sender: TObject);
    procedure CompileBarClose(Sender: TObject);
    procedure SetIDEMode(NotProj : boolean);
    procedure SetupCreatorClick(Sender: TObject);
    procedure TutorialItemClick(Sender: TObject);
    procedure StandardLibraryItemClick(Sender: TObject);
    procedure GNUDebuggerhelpItemClick(Sender: TObject);
    procedure ifPopItemClick(Sender: TObject);
    procedure whilePopItemClick(Sender: TObject);
    procedure dowhilePopItemClick(Sender: TObject);
    procedure forPopItemClick(Sender: TObject);
    procedure MessageControlChange(Sender: TObject);
    procedure MinimizeallItemClick(Sender: TObject);
    procedure NextItemClick(Sender: TObject);
    procedure PreviousItemClick(Sender: TObject);
    procedure ProjectViewMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ClosefilePopItemClick(Sender: TObject);
    procedure RTFItemClick(Sender: TObject);
    procedure HelponDevPasItemClick(Sender: TObject);
    procedure CopyPopItemClick(Sender: TObject);
    procedure AddHistory(s : string);
    procedure CompileandRunItemClick(Sender: TObject);
    procedure CreateNewCompletionFile;
    procedure CreateNewDefaultFile;
    procedure ProjectToolbarClose(Sender: TObject);
    function  SaveFile : boolean;
    procedure GenerateMakeFileItemClick(Sender: TObject);
    procedure BloodshedSoftwarehomepageItemClick(Sender: TObject);
    procedure MingwcompilerhomepageItemClick(Sender: TObject);
    procedure SelectErrorLine(MdiForm : TEditForm);
    procedure GetDirectories;
    procedure FormDestroy(Sender: TObject);
    procedure RebuildallClick(Sender: TObject);
    procedure DateandtimeItemClick(Sender: TObject);
    procedure DateandtimePopItemClick(Sender: TObject);
    procedure ProjectViewChange(Sender: TObject; Node: TTreeNode);
    procedure ProjectViewExpanded(Sender: TObject; Node: TTreeNode);
    procedure NewresourcefileItemClick(Sender: TObject);
    procedure NewTemplatefile1Click(Sender: TObject);
    procedure NewAllBtnClick(Sender: TObject);
    procedure Win32MenuClick(Sender: TObject);
    procedure LibCMenuClick(Sender: TObject);
    procedure MakeMenuClick(Sender: TObject);
    procedure FullscreenmodeClick(Sender: TObject);
    procedure ExporttoItemClick(Sender: TObject);
    procedure ShowCompilerOutput1Click(Sender: TObject);
    procedure Showonlywhenneeded1Click(Sender: TObject);
    procedure Compileroutput1Click(Sender: TObject);
    procedure PackageManagerItemClick(Sender: TObject);
    procedure ConfiguretoolsItemClick(Sender: TObject);
    procedure ToolsMenuClick(Sender: TObject);
    procedure OnToolClick(sender : TObject);
    procedure ChangeIconStyleClick(Sender: TObject);
    procedure ToolbarIconsStyle1Click(Sender: TObject);
    procedure Setmainunit1Click(Sender: TObject);
    procedure Unitbeginend1Click(Sender: TObject);
    procedure Unitbeginend2Click(Sender: TObject);
    procedure GNUPascalhelpitemClick(Sender: TObject);

  { Private declarations }
  private
    LastOpenName,
    IniFileName : string;
    SelectedNode : TTreeNode;
    ProjIniFile : TIniFile;
    MdiList : TList;
    UnitNumber : integer;
    MainImageList, ProjectImageList : TImageList;

  { Public declarations }
  public
    IniFile : TIniFile;
    BinDir, PasDir, LibDir : string;
    C_PasDir, C_LibDir   : string;
    DevPasPath  : string;
    Project  : TProject;
    ProjectCount : integer;
    ProjectNode : TTreeNode;
    Directories : record     // for storing include and lib directories
                    Pas, Lib, All : string;
                  end;
    CompileFileOutput : TStringList;
    IconStyle : (isDefault, isGnome);

    procedure AddChild(AForm: TEditForm);
    procedure RemoveChild(AForm: TEditForm);
    function  CloseAll : boolean;
    procedure ReloadDirectories;
    procedure AddItem(c, s1, s2: string);
    function  ParseParams(s : string) : string;
    procedure UpdateIcons(IconType: TIconType);
    procedure Execute(ExeParams : string);
    Procedure RestoreEditorDesktop;
  end;

const ToolMenuItemCount = 8;

const
  itDefault = 0;
  itGnome = 1;

var
  MainForm : TMainForm;
  File_Open, InvalidateLine : boolean;
  PasParams, UserParams : string;
  CompilerOptionsModified : boolean = True;
  NotProject : boolean; // to know if Dev-Pascal work with a project or a source file

  Type
  Compiler_Support = (FreePascal, GPC, Unknown);

  Var
  ThisCompiler : Compiler_Support = FreePascal;
  Default_Compiler : String [255] = 'ppc386 ';
  CompilerString : String = ' (Freepascal)';
  ThisCaption : String = '';

  Type
  CPUType = (i384, i486, Pentium, Pentium2, Other);

  Const
  CPUStrings : Array [0..4] of String =
                  ('386', '486', 'P5', 'P6', 'OTHER');

  GPC_CPUSwitches : Array [0..4] of String =
                  (' -march=i386 -mcpu=i386 ',
                   ' -march=i486 -mcpu=i486 ',
                   ' -march=i586 -mcpu=i586 ',
                   ' -march=i686 -mcpu=i686 ',
                   ' -march=i386 -mcpu=i386 ');

  FPC_CPUSwitches : Array [0..4] of String =
                  ('-Op1 ', '-Op1 ', '-Op2 ', '-Op2 ', '-Op1 ');

  function CompileFile(Cmd, WorkDir: String): string;
  Procedure SetupCompiler;
  FUNCTION AddBackslash ( CONST S : string ) : String;

implementation

uses ShellApi, CompOptions, EnvirOpt, RemoveUnit, DebugFrm,
  ProjectOptions, checkfrm, InfoFrm, OutputFrm, About,
  MsgBox, NewProject, DllDialog, SetupCreator, ResEdit, UMakefileForm,
  TemplateFrm, ToolFrm, ToolEditFrm, FirstFrm, SetMainUnit;

{$R *.DFM}

Var
UnitSwitch : String = '-Fu';
LibSwitch  : String = '-Fl';
BinSwitch,
ConsoleSwitch,
GUISwitch,
PreprocessorSwitch,
LinkerSwitch : String;

FUNCTION AddBackslash ( CONST S : string ) : String;
begin
   Result := s;
   If s [length(s)] <> '\' then Result := Result + '\';
end;

procedure TMainForm.ExitItemClick(Sender: TObject);
begin
{
  s := '';
  If Assigned (Project) then s := Project.FileName
  else if MdiChildCount > 0 then begin
     for i := 0 to Pred (MdiChildCount) do
      s := s + ' ' + TEditForm(MdiChildren[i]).PathName;
  end;
 }
//  s := inttostr (MdiChildCount);
//  s := inttostr (ProjectCount);
//  messagebox (0, pchar(s), pchar (TEditForm(MdiChildren[0]).pathname), 0);
//  messagebox (0, pchar(s), pchar (TEditForm(MdiChildren[0]).Caption), 0);
// messagebox (0, pchar(s),  pchar (ProjectView.Items.Item[0].Text), 0);
//if assigned (project) then messagebox (0, pchar(s),  pchar (Project.Filename), 0);
// messagebox (0, pchar(s),  pchar ('ha'), 0);

  RestoreEditorDesktop;
  SavePosition;
  SaveOutputPosition;
  if CloseAll then
     Application.Terminate;
end;

procedure TMainForm.TileItemClick(Sender: TObject);
begin
  Tile;
end;

procedure TMainForm.CascadeItemClick(Sender: TObject);
begin
  Cascade;
end;

procedure TMainForm.ArrangeiconsItemClick(Sender: TObject);
begin
  ArrangeIcons;
end;

procedure TMainForm.ToolButton3Click(Sender: TObject);
begin
  ActiveMDIChild.Close;
end;

procedure TMainForm.PrinterSetupItemClick(Sender: TObject);
begin
  PrinterSetupDialog.Execute;
end;

procedure TMainForm.AboutBloodshedDevPasItemClick(Sender: TObject);
begin
  Aboutbox:=TAboutbox.Create(Self);
  with Aboutbox do
  try
     ShowModal;
     if ModalResult = MrYes then
        CheckforDevPasUpdatesItemClick(Sender);
  finally
     Free;
  end;
end;

procedure TMainForm.ReloadDirectories;
begin
  BinDir := IniFile.ReadString('Directories','BinDir',BinDir);
  PasDir := IniFile.ReadString('Directories','PasDir',PasDir);
  LibDir := IniFile.ReadString('Directories','LibDir',LibDir);
end;

procedure TMainForm.CompileroptionsItemClick(Sender: TObject);
begin
  CompForm := TCompForm.Create(Self);
  with CompForm do
  try
     ShowModal;
  finally
     Free;
  end;
end;

procedure TMainForm.EnvironmentoptionsItemClick(Sender: TObject);
begin
  EnvirForm := TEnvirForm.Create(Self);
  with EnvirForm do
  try
     ShowModal;
  finally
     Free;
  end;
end;

procedure TMainForm.ExplorerItemClick(Sender: TObject);
begin
  ExecuteFile('Explorer.Exe','','',SW_SHOW);  // Execute Windows' explorer
end;

procedure TMainForm.DosshellItemClick(Sender: TObject);
begin
  Case ThisCompiler of
    GPC :
     begin
       If WinExec ('cmd.exe', sw_show) < 33 then
        WinExec ('command.com', sw_show);
     end;
    Freepascal :
    // Execute the dos shell (doscom.exe)
    ExecuteFile(ExtractFilePath(Application.Exename) + 'DosCom.exe','',ExtractFilePath(Application.Exename), SW_SHOW);
  end; // Case 
end;

procedure TMainForm.DevPasHelpPopupClick(Sender: TObject);
begin
  HelpMenu.Popup(HelpBtn.ClientOrigin.x+HelpBtn.Width, HelpBtn.ClientOrigin.y);
end;

procedure TMainForm.CreateNewIniFile(CreateIni : boolean);
begin

 if FileExists(IniFileName) then DeleteFile(PChar(IniFileName));

 if CreateIni = True
 then begin
     IniFileName := ExtractFilePath(Application.Exename)+ ChangeFileExt(lowercase(ExtractFileName(Application.Exename)), '.ini');
     IniFile := TIniFile.Create(IniFilename);
 end;

 with IniFile
 do begin
  WriteBool('Start','Registry',True);
  WriteString('Start','Version',DevPasVersion);

  WriteString('Options','Color','White');
  WriteBool('Options','SavePos',True);
  WriteBool('Options','SaveDesktop',True);
  WriteBool('Options','SaveEditor',False);
  WriteString('Options','Font','Courier New');
  WriteInteger('Options','Fontsize',10);
  WriteBool('Options','Backup',False);
  WriteBool('Options','Minimize',True);
  WriteBool('Options','AutoIndent',True);
  WriteBool('Options','TabsToSpaces',True);
  WriteBool('Options','ShowGutter',True);
  WriteBool('Options','SmartTabs',True);
  WriteInteger('Options','TabIndent',4);
  WriteBool('Options','ShowScrollHint', True);
  WriteBool('Options','ToolBarSave', True);
  WriteBool('Options','CompileStayOnTop', False);
  WriteBool('Options','ExeInDir',True);
  WriteBool('Options','NoOpen', False);
  WriteBool('Options','Output',True);
  WriteBool('Options','OutputOnlyWhenNeeded',True);

  WriteInteger('Position','SizeY',534);
  WriteInteger('Position','SizeX',800);
  WriteInteger('Position','Left',-4);
  WriteInteger('Position','Top',-4);
  WriteInteger('Position','SizeEditorX',516);
  WriteInteger('Position','SizeEditorY',326);
  WriteInteger('Position','EditorLeft',0);
  WriteInteger('Position','EditorTop',0);
  WriteInteger('Position','Line',50);
  WriteInteger('Position','File',200);
  WriteInteger('Position','Message',480);

  WriteBool('Code_Generation','IOCheck',False);
  WriteBool('Code_Generation','StackCheck',False);
  WriteBool('Code_Generation','Overflow',False);

  WriteBool('Optimization','SmallCode',False);
  WriteBool('Optimization','QuickOpt',True);
  WriteBool('Optimization','Best',False);

  WriteBool('Linker','DebugInfo',False);
  WriteBool('Linker','NoReloc',False);

  WriteBool('Pascal_Compiler','Ansi',False);
  WriteBool('Pascal_Compiler','LinkDyn',False);
  WriteBool('Pascal_Compiler','LinkSmart',False);
  WriteBool('Pascal_Compiler','StripSymbols',False);
  WriteBool('Pascal_Compiler','CInline',False);
  WriteBool('Pascal_Compiler','Assert',False);
  WriteBool('Pascal_Compiler','COp',False);

  Case ThisCompiler of
    GPC :
    begin
      WriteBool('Pascal_Compiler','DelphiExt',False);
      WriteBool('Pascal_Compiler','TP7',False);
      WriteBool('Pascal_Compiler','LabelGoto',False);
      WriteBool('Pascal_Compiler','DelphiComp',False);
      WriteBool('Pascal_Compiler','Macros',True);
      WriteBool('Pascal_Compiler','NoCheckUnit',False);
    end; // GPC
    Freepascal :
    begin
     WriteBool('Pascal_Compiler','DelphiExt',True);
     WriteBool('Pascal_Compiler','TP7',True);
     WriteBool('Pascal_Compiler','LabelGoto',True);
     WriteBool('Pascal_Compiler','DelphiComp',True);
     WriteBool('Pascal_Compiler','Macros',False);
     WriteBool('Pascal_Compiler','NoCheckUnit',True);
    end; // Freepascal
  end; // Case

  WriteString('Directories','BinDir',AddBackSlash (ExtractFilePath(Application.ExeName)+'Bin'));
  WriteString('Directories','PasDir',AddBackSlash (ExtractFilePath(Application.ExeName)+'Units'));
  WriteString('Directories','LibDir',AddBackSlash (ExtractFilePath(Application.ExeName)+'Units'));
  BinDir := AddBackSlash (ExtractFilePath(Application.ExeName)+'Bin');

  WriteString('EditorColor','WhiteSpace','16777215');
  WriteString('EditorColor','CommentAttri','8388608, -2147483643, 0, 1, 0');
  WriteString('EditorColor','IdentifierAttri','-2147483640, -2147483643, 0, 0, 0');
  WriteString('EditorColor','KeyAttri','-2147483640, -2147483643, 1, 0, 0');
  WriteString('EditorColor','NumberAttri','16711680, -2147483643, 0, 0, 0');
  WriteString('EditorColor','SpaceAttri','-2147483640, -2147483643, 0, 0, 0');
  WriteString('EditorColor','StringAttri','255, -2147483643, 0, 0, 0');
  WriteString('EditorColor','SymbolAttri','-2147483640, -2147483643, 0, 0, 0');
  WriteString('EditorColor','DirecAttri','32768, 16777215, 0, 0, 0');

  WriteInteger('Colors','Comment',4);
  WriteInteger('Colors','Identifier',0);
  WriteInteger('Colors','Key',0);
  WriteInteger('Colors','Number',5);
  WriteInteger('Colors','Space',15);
  WriteInteger('Colors','String',9);
  WriteInteger('Colors','Symbol',0);
  WriteInteger('Colors','Color',0);

  WriteBool('Toolbars','Compile',True);
  WriteBool('Toolbars','Project',True);
  WriteBool('Toolbars','Options',True);
  WriteBool('Toolbars','Specials',True);
  WriteBool('Toolbars','StatusBar',True);
 end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
var Reg     : TRegistry;
    UserDir : string;
    Assign_Dp_Files, Assign_Pas_Files: boolean;
    NewMenu : TMenuItem;
    k : integer;
begin
 DevPasPath := ExtractFilePath(Application.ExeName);
 MdiList := TList.Create;

  if not FileExists(ExtractFilePath(Application.ExeName) + 'devpas.ini')
  then begin
    CreateNewIniFile(True);

    try
      FirstForm := TFirstForm.Create(self);
      FirstForm.ShowModal;
      if FirstForm.AssignC.Checked then
         IniFile.WriteBool('Start','Registry',True)
      else IniFile.WriteBool('Start','Registry',False);

      if FirstForm.AssignDev.Checked then
         IniFile.WriteBool('Start','DevFiles',True)
      else IniFile.WriteBool('Start','DevFiles',False);

      if FirstForm.IconBox.Text = 'Gnome' then
         IniFile.WriteInteger('Options','IconStyle',1)
      else IniFile.WriteInteger('Options','IconStyle',0)

    finally
      FirstForm.Free;
    end;
    {$IFDEF BUGS}
    MessageDlg('BETA VERSION, SO PLEASE SEND ANY BUG REPORT TO:'+#10#13+'webmaster@bloodshed.net'
               , mtInformation, [mbOK], 0);
    {$ENDIF}

    if IsWinNTor2K then
       MessageDlg('Dev-Pascal will now write to the registry. You must be in Administrator mode to do so, or an error will occur.', mtWarning, [mbOK], 0);
 end
 else begin
    IniFileName := ExtractFilePath(Application.Exename)+ ChangeFileExt(ExtractFileName(Application.Exename), '.ini');
    IniFile := TIniFile.Create(IniFilename);
 end;

 ReloadDirectories;

 Caption := 'Dev-Pascal '+ DevPasVersion + CompilerString;
 Application.HelpFile := ExtractFilePath(Application.ExeName) + 'DevPas.hlp';

 if (IniFile.ReadBool('Start','NotFirst',False)= False) or
    (IniFile.ReadString('Start','Version','') <> DevPasVersion) then
    CreateNewIniFile(False);

 IniFile.WriteString('Start','Version',DevPasVersion);

 OpenHistory;

 OpenFileDialog.InitialDir:=IniFile.ReadString('Options','DefaultDir',OpenFileDialog.InitialDir);

 if IniFile.ReadBool('Directories','AddDir',True) then
    UserDir := UnitSwitch + IniFile.ReadString('Directories','Dir',UserDir);

 { Read from inifile the last values of form's position }
 if IniFile.ReadBool('Options','SavePos',True) then
  begin
   { if IniFile.ReadBool('Position', 'Max', True) then
       WindowState := wsMaximized
    else begin}

    ClientWidth  := IniFile.ReadInteger('Position', 'SizeX', 800);
    ClientHeight := IniFile.ReadInteger('Position', 'SizeY', 600);
    Left         := IniFile.ReadInteger('Position', 'Left', 0);
    Top          := IniFile.ReadInteger('Position', 'Top',  0);

    CompilerOutput.Columns.Items[0].Width := IniFile.ReadInteger('Position','Line',60);
    CompilerOutput.Columns.Items[1].Width := IniFile.ReadInteger('Position','File',226);
    CompilerOutput.Columns.Items[2].Width := IniFile.ReadInteger('Position','Message',330);
  end;

  Assign_Pas_Files := IniFile.ReadBool('Start','Registry',True);
  Assign_Dp_Files := IniFile.ReadBool('Start','DevFiles',True);

  if (Assign_Dp_Files or Assign_Pas_Files) and
     (not IniFile.ReadBool('Start','NotFirst',False)) then
     begin
       Reg := TRegistry.Create;
       with Reg do
       try
         RootKey := HKEY_CLASSES_ROOT;

         if Assign_Pas_Files then begin
            OpenKey('.pas', True);
            WriteString('', 'DevPas.pas');
            CloseKey;
            OpenKey('DevPas.pas', True);
            WriteString('', 'Pascal Source File');
            OpenKey('DefaultIcon', True);
            WriteString('', '"'+ParamStr(0)+'"' + ',2');
            CloseKey;
            OpenKey('DevPas.pas\Shell\Open\Command', True);
            WriteString('', '"'+ParamStr(0)+'"' + ' "%1"');
            CloseKey;

            OpenKey('.pp', True);
            WriteString('', 'DevPas.pp');
            CloseKey;
            OpenKey('DevPas.pp', True);
            WriteString('', 'Free Pascal Source File');
            OpenKey('DefaultIcon', True);
            WriteString('', '"'+ParamStr(0)+'"' + ',3');
            CloseKey;
            OpenKey('DevPas.pp\Shell\Open\Command', True);
            WriteString('', '"'+ParamStr(0)+'"' + ' "%1"');
            CloseKey;
         end;

         if Assign_Dp_Files then begin
            OpenKey('.dp', True);
            WriteString('', 'DevPas.dp');
            CloseKey;
            OpenKey('DevPas.dp', True);
            WriteString('', 'Dev-Pascal Project File');
            OpenKey('DefaultIcon', True);
            WriteString('', '"'+ParamStr(0)+'"'+',1');
            CloseKey;
            OpenKey('DevPas.dp\Shell\Open\Command', True);
            WriteString('', '"'+ParamStr(0)+'"' + ' "%1"');
            CloseKey;
         end;
      except
           MessageDlg('Dev-Pascal was not able to write to the registry. This possible cause is that you are running NT not in administrator mode. To remove this message, go to Environment options, Misc. sheet and uncheck the "Assign" options.', mtError, [mbOK], 0);
           Free;
      end;
  end;

  if not IniFile.ReadBool('Start','NotFirst',False) then
     WindowState := wsMaximized;

  IniFile.WriteBool('Start','NotFirst',True);

  k := 1;

  if FileExists(DevPasPath + 'Help\win32.hlp') or
     FileExists(DevPasPath + 'Help\libc.hlp') or
     FileExists(DevPasPath + 'Help\make.hlp') then begin
     inc(k);
     NewMenu := TMenuItem.Create(MainMenu);
     NewMenu.Caption := '-';
     HelpMenu.Items.Insert(k, NewMenu);

     NewMenu := TMenuItem.Create(MainMenu);
     NewMenu.Caption := '-';
     HelpDevPasMenu.Insert(k, NewMenu);
  end;

  if FileExists(DevPasPath + 'Help\win32.hlp') then begin
     inc(k);
     NewMenu := TMenuItem.Create(MainMenu);
     NewMenu.Caption := 'Win32 API Reference';
     NewMenu.OnClick := Win32MenuClick;
     NewMenu.ImageIndex := 59;
     HelpDevPasMenu.Insert(k, NewMenu);

     NewMenu := TMenuItem.Create(MainMenu);
     NewMenu.Caption := 'Win32 API Reference';
     NewMenu.OnClick := Win32MenuClick;
     NewMenu.ImageIndex := 59;
     HelpMenu.Items.Insert(k, NewMenu);
  end;

  if FileExists(DevPasPath + 'Help\libc.hlp') then begin
     inc(k);
     NewMenu := TMenuItem.Create(MainMenu);
     NewMenu.Caption := 'Standard C Library Reference';
     NewMenu.OnClick := LibCMenuClick;
     NewMenu.ImageIndex := 37;
     HelpDevPasMenu.Insert(k, NewMenu);

     NewMenu := TMenuItem.Create(MainMenu);
     NewMenu.Caption := 'Standard C Library Reference';
     NewMenu.OnClick := LibCMenuClick;
     NewMenu.ImageIndex := 37;
     HelpMenu.Items.Insert(k, NewMenu);
  end;

  if FileExists(DevPasPath + 'Help\make.hlp')
  then begin
     inc(k);
     NewMenu := TMenuItem.Create(MainMenu);
     NewMenu.Caption := 'GNU Make help file';
     NewMenu.OnClick := MakeMenuClick;
     NewMenu.ImageIndex := 37;
     HelpDevPasMenu.Insert(k+1, NewMenu);

     NewMenu := TMenuItem.Create(MainMenu);
     NewMenu.Caption := 'GNU Make help file';
     NewMenu.OnClick := MakeMenuClick;
     NewMenu.ImageIndex := 37;
     HelpMenu.Items.Insert(k+1, NewMenu);
  end;

  UpdateIcons(IniFile.ReadInteger('Options', 'IconStyle', itDefault));

  Case ThisCompiler of
   GPC :
   begin
      MingwcompilerhomepageItem.Caption := '&Mingw homepage';
      GNUPascalHelpitem.Visible := True;
   end;
   Freepascal : GNUPascalHelpitem.Visible := False;
  end; // Case

  LastOpenName := Inifile.ReadString ('History_Open', 'Name', '');  
end;

procedure TMainForm.Win32MenuClick(Sender: TObject);
begin
  ExecuteFile('win32.hlp','',ExtractFilePath(Application.ExeName)+'Help\',SW_SHOW);
end;

procedure TMainForm.LibCMenuClick(Sender: TObject);
begin
  ExecuteFile('LibC.hlp','',ExtractFilePath(Application.ExeName)+'Help\',SW_SHOW);
end;

procedure TMainForm.MakeMenuClick(Sender: TObject);
begin
  ExecuteFile('Make.hlp','',ExtractFilePath(Application.ExeName)+'Help\',SW_SHOW);
end;

procedure TMainForm.SavePosition;
begin
  { Save to the ini file the form position }
  if (Screen.Height <> Height) and (Screen.Width <> Width) then 
  with IniFile do begin
     WriteInteger('Position', 'SizeY', ClientHeight);
     WriteInteger('Position', 'SizeX', ClientWidth);
     WriteInteger('Position', 'Left', Left);
     WriteInteger('Position', 'Top',  Top);
     { Modified by Hongli }
     WriteBool('Position', 'Max', WindowState = wsMaximized);
  end;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  RestoreEditorDesktop;
  SavePosition;
  SaveOutputPosition;
  if CloseAll then begin
     if InfoForm <> nil then
        InfoForm.Free;
     Action := caFree
  end
  else Action := caNone;
end;

Type TCharset = set of char;

FUNCTION Tokenise ( CONST s : String; T : TStrings; Marker : TCharSet ) : Longint;
VAR
s1 : AnsiString;
i : longint;
BEGIN
   Result := - 1;
   IF not Assigned ( T ) THEN Exit;
   T.Clear;
   s1 := '';
   Result := 0;
   FOR i := 1 TO length ( s )
   DO BEGIN
       IF ( s [i] IN Marker )
       THEN BEGIN
          Inc ( Result );
          T.Add ( s1 );
          s1 := '';
       END ELSE s1 := s1 + s [i];
   END;

   IF length ( s1 ) > 0 // ( Result = 0 ) AND ( length ( s ) > 0 )
   THEN BEGIN
      Inc ( Result );
      T.Add ( s1 );
   END;
END;



procedure TMainForm.FormActivate(Sender: TObject);
var
FileName,
tmp : string;
i   : integer;
ts  : TStringList;

begin
  FileName := '';
  If LastOpenName <> '' then FileName := LastOpenName + ',';

  ts := TStringList.Create;

  for i := 1 to ParamCount
  do begin
     FileName := FileName + ParamStr (i) + ',' ;
  end;

  filename := Trim (filename);
  i := length (filename);
  if i > 0 then if filename[i] = ',' then Delete (filename, i, 1);
  Tokenise (FileName, ts, [',']);

  LastOpenName := '';

  if NotProject
  then begin
     ProjectManagerViewItem.Checked := False;
     ProjectView.Visible := False;
  end
  else begin
     ProjectView.Visible := not IniFile.ReadBool('Options','NoProjExpl',False);
     ProjectManagerViewItem.Checked := ProjectView.Visible;
  end;

  if  (ts.Count > 0{Trim (FileName) <> ''})
  and (MdiChildCount = 0)
  and (File_Open = false)
  then begin
     for i := 0 to Pred (ts.Count)
     do begin
         tmp := ts [i];
         if ExtractFileExt (tmp) = '.dp' then
         try
            Application.ProcessMessages;
            SetIDEMode (False);
            Project := TProject.Create (tmp, '__FileOpen');
            Inc (ProjectCount);
            Caption := 'Dev-Pascal ' + DevPasVersion + ' - ' + Project.Name;
         finally
            File_Open := true;
         end
         else begin
              SetIDEMode(True);

              with TEditForm.Create(self)
              do begin
                 Open (tmp);
                 if ts.Count = 1 then PostMessage(Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
              end;

              Caption := 'Dev-Pascal ' + DevPasVersion + ' - ' + tmp;
              File_Open := true;
         end;
         AddHistory(tmp);
         SaveFileHistory(tmp);
     end; // for i
  end;

  ts.Free;

  tmp := IniFile.ReadString('Options','DefaultDir','');

  if IniFile.ReadBool('Options','ToolbarSave',False)
  then begin
     MainItem.Checked := IniFile.ReadBool('Toolbars','Main',True);
     MainToolBar.Visible := MainItem.Checked;

     CompileAndRunItem.Checked := IniFile.ReadBool('Toolbars','Compile',True);
     CompileToolBar.Visible := CompileAndRunItem.Checked;

     ProjectItem.Checked := IniFile.ReadBool('Toolbars','Project',True);
     ProjectToolBar.Visible := ProjectItem.Checked;

     OptionItem.Checked := IniFile.ReadBool('Toolbars','Options',True);
     OptToolBar.Visible := OptionItem.Checked;

     SpecialsItem.Checked := IniFile.ReadBool('Toolbars','Specials',True);
     SpecialsBar.Visible := SpecialsItem.Checked;

     StatusBarItem.Checked := IniFile.ReadBool('Toolbars','StatusBar',True);
     StatusBar.Visible := StatusBarItem.Checked;
  end;

  if tmp <> '' then begin
     OpenFileDialog.InitialDir := tmp;
     OpenAddDialog.InitialDir  := tmp;
     SaveProject.InitialDir  := tmp;
     ExportDialog.InitialDir := tmp;
  end;

  ShowCompilerOutput1.Checked := IniFile.ReadBool('Options','Output',True);
  Showonlywhenneeded1.Checked := IniFile.ReadBool('Options','OutputOnlyWhenNeeded',False);
  MessageControl.Visible := ShowCompilerOutput1.Checked or (ResourceOutput.Items.Count <> 0) or
                               (CompilerOutput.Items.Count <> 0);
end;

procedure TMainForm.OpenHistory;
var
   List:TStringList;
   i       : integer;
begin
 i := ReOpenItem.Count-1;

 if ReOpenItem.Count <> 2 then
    repeat
       ReOpenItem.Remove(ReOpenItem.Items[i]);
       dec(i);
    until ReOpenItem.Count = 2;

   List:=TStringList.Create;
   IniFile.ReadSectionValues('History',List);
   for i := 0 to List.Count-1 do begin
      if FileExists(List.Values[IntToStr(I)]) then
         AddHistory(List.Values[IntToStr(I)]);
   end;
   List.Free;
end;

procedure TMainForm.AddHistory(s : string);
var
   NewMenuItem:TMenuItem;
   i : integer;
begin
  for i := 2 to ReOpenItem.Count-1 do
      if lowercase(ReOpenItem.Items[i].Caption) = lowercase(s) then
         exit;

  NewMenuItem:=TMenuItem.Create(Self);
  NewMenuItem.Caption:= s;
  NewMenuItem.OnClick:= OpenHistoryFile;
  ReOpenItem.Insert(2,NewMenuItem);
end;

procedure TMainForm.OpenHistoryFile(Sender: TObject);
var
i : integer;
s : string;
begin
  if ProjectOpen then
     CloseprojectItemClick(Sender);

  s := TMenuItem(Sender).Caption;

  { check for orphan shortcut marker: from D6 onwards }
    i := Pos ('&', s);
    If i > 0 then Delete (s, i, 1);
  { end check }

  if lowercase(ExtractFileExt(s)) = '.dp'
  then begin
     SetIDEMode(False);
     Project := TProject.Create (s, '__FileOpen');
     Inc(ProjectCount);
     Caption := 'Dev-Pascal ' + DevPasVersion + ' - ' + Project.Name;
  end
  else if lowercase(ExtractFileExt(s)) = '.rc' then
          EditResource(self, s)
  else begin
     SetIDEMode(True);

     for i := 0 to MdiChildCount-1 do
         if MdiChildren[i].WindowState = wsMaximized then
            MdiChildren[i].WindowState := wsNormal;

     with TEditForm.Create(self)
     do begin
          PathName := s;
          Open(PathName);

          if MainForm.MdiChildCount = 1 then
             PostMessage(Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
     end
  end
end;

procedure TMainForm.SaveFileHistory(const Filename:string);
var
   LastNum, i : integer;
   List:TStringList;
begin
   List:=TStringList.Create;
   IniFile.ReadSectionValues('History',List);
   for I:=0 to List.Count-1 do
       if List.Values[IntToStr(I)]= Filename then begin
          List.Free;
          Exit;
       end;
   LastNum:=IniFile.ReadInteger('History','Last',0);

   IniFile.WriteInteger('History','Last',LastNum+1);
   IniFile.WriteString('History',IntToStr(LastNum+1),Filename);
end;

procedure TMainForm.ClearhistoryItemClick(Sender: TObject);
var i : integer;
begin
  IniFile.EraseSection('History');
  i := ReOpenItem.Count-1;

  if ReOpenItem.Count <> 2 then
    repeat
       ReOpenItem.Remove(ReOpenItem.Items[i]);
       dec(i);
    until ReOpenItem.Count = 2;
end;

procedure TMainForm.CloseBtnClick(Sender: TObject);
begin
  if MdiChildCount <> 0 then
     ActiveMdiChild.Close;
end;

function TMainForm.SaveFile : boolean;
var ReturnFile : string;
    Index      : integer;
begin
  if MdiChildCount = 0 then begin
     Result := False;
     Exit;
  end;

  Result := True;

  Index := (ActiveMdiChild as TEditForm).GetIndex-1;

  if NotProject = False then begin
     if (ActiveMdiChild as TEditForm).PathName = '' then begin
         ReturnFile := (ActiveMdiChild as TEditForm).Saveas1Click(Project.FileName);
     end
     else begin
         if (ActiveMdiChild as TEditForm).PathName <> '' then
            (ActiveMdiChild as TEditForm).Save1Click(self)
     end;

     (ActiveMdiChild as TEditForm).Modified := False;

     ProjIniFile := TIniFile.Create(Project.FileName);
     Project.Units[Index].FileTime := GetFileTime((ActiveMdiChild as TEditForm).PathName);
     ProjIniFile.WriteInteger('Unit'+IntToStr(Index+1),'FileTime', Project.Units[Index].FileTime);
  end else begin
     if (ActiveMdiChild as TEditForm).PathName = '' then
        (ActiveMdiChild as TEditForm).SaveOneSource
     else
        (ActiveMdiChild as TEditForm).Save1Click(self);

     if (ActiveMdiChild as TEditForm).PathName = '' then
        Result := False;
  end;
end;

procedure TMainForm.SaveFileMenu(Sender: TObject);
begin
  SaveFile;
end;

procedure TMainForm.PrintBtnClick(Sender: TObject);
begin
  if MdiChildCount <> 0 then
     (ActiveMdiChild as TEditForm).PrintFile;
end;

procedure TMainForm.UndoBtnClick(Sender: TObject);
begin
  if MdiChildCount <> 0 then
     (ActiveMdiChild as TEditForm).Undo(Sender);
end;

procedure TMainForm.FindBtnClick(Sender: TObject);
begin
  if MdiChildCount <> 0 then
     (ActiveMdiChild as TEditForm).Search;
end;

procedure TMainForm.RunBtnClick(Sender: TObject);
begin
  Execute('');
end;

procedure TMainForm.Execute(ExeParams : string);
var FileToRun, Params, Dir : string;
    Wait : boolean;
begin
  if (ProjectOpen = False) and (MdiChildCount = 0) then
     Exit;

  Wait := False;

  if NotProject = False then begin
     if Project.IsDll then exit;
     FileToRun := ChangeFileExt(Project.FileName,'.exe')
  end
  else FileToRun := ChangeFileExt((ActiveMdiChild as TEditForm).PathName,'.exe');

  if not FileExists(FileToRun) then
     begin
         CompileAndExecuteClick(self);
         Exit;
     end;

  if (IniFile.ReadBool('Options','Minimize',True)) and (not IsWinNTor2k)then
     Application.Minimize;

  if (IniFile.ReadBool('Options','Minimize',True)) then
     Wait := True;

  if IniFile.ReadBool('Options','ExecParam',True) then
     Params := IniFile.ReadString('Options','Params','');

  if ExeParams <> '' then
     Params := Params + ' ' + ExeParams;

  if IniFile.ReadBool('Options','ExeInDir',True) then
     Dir := ExtractFilePath(FileToRun)
  else Dir := '';

  try
     if not IsWinNTor2K then
        RunFile(FileToRun, Params, Dir, Wait)
     else
        WinExec(pChar(FileToRun +' '+ Params), SW_SHOW);
  except
     if IniFile.ReadBool('Options','Minimize',True) then
        Application.Restore;
     MessageDlg('Error executing file. You may have errors in your source code or maybe your file isn''t an application.', MtError, [MbOK],0);
     exit;
  end;
{
  If i < 33 then
     MessageDlg('Error executing . You may have errors in your source code or maybe your file isn''t an application.', MtError, [MbOK],0);
}
  if (IniFile.ReadBool('Options','Minimize',True)) then
     Application.Restore;
end;

procedure TMainForm.DebugBtnClick(Sender: TObject);
var
  FileToRun : String;
begin
  if ((ProjectOpen = False) and (MdiChildCount = 0)) then Exit;

  if (NotProject = False) and Project.IsDll then exit;

  if NotProject then begin
     FileToRun := ChangeFileExt((ActiveMdiChild as TEditForm).PathName, '.exe');
     ChDir(ExtractFilePath((ActiveMdiChild as TEditForm).PathName));
  end
  else begin
     FileToRun := ChangeFileExt(Project.FileName, '.exe');
     ChDir(ExtractFilePath(Project.FileName));
  end;

  DbgForm.FileName := GetShortName(FileToRun);

  if not FileExists(FileToRun) then
     begin
         MessageDlg('Executing file '+ FileToRun +' doesn''t exist. Try to compile file before debugging',MtError,[MbOK],0);
         ChDir(ExtractFilePath(DevPasPath));
         Exit;
     end
  else
    begin
     {$IFNDEF CD_VERSION}
     if IniFile.ReadBool('Debugger','NoMsg',False)= False then
        DbgForm.ShowModal
     else
        DbgForm.ContinueBtnClick(Sender);
     {$ELSE}
        DbgForm.ContinueBtnClick(Sender);
     {$ENDIF}
    end;

  ChDir(ExtractFilePath(DevPasPath));
end;

function TMainForm.MakeProjectNode(Name : string) : TTreeNode;
begin
  MakeProjectNode:=ProjectView.Items.Add(nil, Name);
  MakeProjectNode.SelectedIndex:=0;
  MakeProjectNode.ImageIndex:=0;
  ProjectView.FullExpand;
end;

function TMainForm.MakeNewFileNode(s : string) : TTreeNode;
begin
  MakeNewFileNode:=ProjectView.Items.AddChild(ProjectNode, ExtractFileName(s));
  MakeNewFileNode.SelectedIndex:=1;
  MakeNewFileNode.ImageIndex:=1;
  ProjectView.FullExpand;
end;

procedure TMainForm.WriteDllFiles(DllName, DllFileName, DllSourceName, TestDllName, TestFileName, TestSourceName : string);
var F : TextFile;
    DllSource, TestSource : string;
begin
DllSource := ExtractFilePath(DllFileName)+DllSourceName+'.pas';
TestSource := ExtractFilePath(TestFileName)+TestSourceName+'.pas';

AssignFile(F,DllFileName);
Rewrite(F);

Writeln(F,'[Project]');
Writeln(F,'FileName='+DllFileName);
Writeln(F,'Name='+DllName);
Writeln(F,'MainUnit='+DllSource);
Writeln(F,'UnitCount=1');
Writeln(F,'NoConsole=1');
Writeln(F,'IsDll=1');
Writeln(F);
Writeln(F,'[Unit1]');
Writeln(F,'FileName='+DllSource);

CloseFile(F);

AssignFile(F,DllSource);
Rewrite(F);

writeln(F,'library Untitled;');
writeln(F,'');
writeln(F,'procedure MyDllProcedure; export;');
writeln(F,'begin');
writeln(F,'');
writeln(F,'end;');
writeln(F,'');
writeln(F,'exports');
writeln(F,'  MyDllProcedure;');
writeln(F,'');
writeln(F,'begin');
writeln(F,'');
writeln(F,'end.');

CloseFile(F);

AssignFile(F,TestFileName);
Rewrite(F);

Writeln(F,'[Project]');
Writeln(F,'FileName='+TestFileName);
Writeln(F,'Name='+TestDllName);
Writeln(F,'UnitCount=1');
Writeln(F,'NoConsole=0');
Writeln(F,'IsDll=0');
Writeln(F,'MainUnit='+TestSource);
Writeln(F);
Writeln(F,'[Unit1]');
Writeln(F,'FileName='+TestSource);

CloseFile(F);

AssignFile(F,TestSource);
Rewrite(F);

Writeln(F,'program Untitled;');
Writeln(F,'');
Writeln(F,'procedure MyDllProcedure;');
Writeln(F,'  external '''+ChangeFileExt(DllFileName,'.dll')+''' name ''MyDllProcedure'';');
Writeln(F,'');
Writeln(F,'begin');
Writeln(F,'  MyDllProcedure;');
Writeln(F,'end.');

CloseFile(F);
end;

procedure TMainForm.NewprojectItemClick(Sender: TObject);
var Name : string;
begin
  Try
  NewProjForm := TNewProjForm.Create(Self);
  except end;
  
  if ProjectOpen then
     if MessageDlg('Are you sure you want to close '+Project.Name+' and create a new project ?',MtInformation,[MbYes,MbNo],0)
        = MrYes then
        CloseProjectItemClick(Sender)
     else Exit;

  Application.ProcessMessages;

  CloseAll;

  if NewProjForm.ShowModal <> mrOK then exit;

  if ProjectType = TDll then begin
     DllForm := TDllForm.Create(Self);
     with DllForm do try
       ShowModal;
       if ModalResult = MrOk then begin
          WriteDllFiles(DllName.Text, DllFileName.Text, DllSourceName.Text, TestDllName.Text, TestFileName.Text, TestSourceName.Text);
          MessageDlg('Dev-Pascal will now open your DLL project. After compiling it, you will be able to test your DLL with the project:'+#13+ TestFileName.Text, mtInformation, [mbOK], 0);
          Project := TProject.Create(DllFileName.Text, '__FileOpen');
          Inc(ProjectCount);
          Caption := 'Dev-Pascal ' + DevPasVersion + ' - ' + Project.Name;
          AddHistory(DllFileName.Text);
          SaveFileHistory(DllFileName.Text);
       end;
     finally
       Free;
     end;
     Exit;
  end;

  Inc(ProjectCount);
  If ThisCompiler = GPC
     then Name := 'Project'+ IntToStr(ProjectCount)
     else Name := 'Project '+ IntToStr(ProjectCount);

  if ProjectType = TOther then
     if InputQuery('New project', 'Project name', Name) = False then
     begin
        Dec(ProjectCount);
        Exit;
     end;

  SaveProject.FileName := Name + '.dp';

  if SaveProject.Execute then
  begin
     if FileExists(SaveProject.FileName) then
        case MessageDlg('File already exists. Overwrite it ?',MtInformation,[MbYes,MbNo],0) of
             MrYes : DeleteFile(PChar(SaveProject.FileName));
             MrNo  : Exit;
        end;

     SetIDEMode(False);
     Project := TProject.Create(SaveProject.FileName, Name);
     Caption := 'Dev-Pascal ' + DevPasVersion + ' - ' + Project.Name;

     if ProjectType = TTemplateDoc then
     begin
        Project.Name := NewProjForm.TheTemplate.ProjectName;
        Project.CompilerOptions := NewProjForm.TheTemplate.CompilerOptions;
        Project.IncludeDirs := NewProjForm.TheTemplate.IncludeDirs;
        Project.NoConsole := not NewProjForm.TheTemplate.Console;
        Project.ObjFile := NewProjForm.TheTemplate.Libs;
        Project.IsDll := NewProjForm.TheTemplate.DLL;
     end;
     AddHistory(SaveProject.FileName);
     SaveFileHistory(SaveProject.FileName);
  end else Dec(ProjectCount);

  if MdiChildCount > 0 then
     (ActiveMdiChild as TEDitForm).Editor.SetFocus;
  NewProjForm.Free;
end;

procedure TMainForm.FileMenuClick(Sender: TObject);
begin
  if ProjectOpen = True then
     CloseProjectItem.Enabled := True
  else
     CloseProjectItem.Enabled := False;

  if MainForm.MDIChildCount > 0 then begin
     SaveUnitItem.Enabled := True;
     SaveasItem.Enabled := True;
     SaveAllItem.Enabled := True;
     CloseItem.Enabled := True;
     PrintItem.Enabled := True;
     ExporttoItem.Enabled := True;
  end
  else begin
     SaveUnitItem.Enabled := False;
     SaveasItem.Enabled := False;
     SaveAllItem.Enabled := False;
     CloseItem.Enabled := False;
     PrintItem.Enabled := False;
     ExporttoItem.Enabled := False;
  end;

  OpenHistory;

  if ReOpenItem.Count = 2 then begin
     ReOpenItem.Enabled := False
  end else
     ReOpenItem.Enabled := True;

  if NotProject then SaveAllItem.Enabled := False;
end;

procedure TMainForm.EditMenuClick(Sender: TObject);
begin
  if MainForm.MDIChildCount > 0 then
     with(ActiveMdiChild as TEditForm) do begin
       UndoItem.Enabled := Editor.CanUndo;
       RedoItem.Enabled := Editor.CanRedo;
       CutItem.Enabled := True;
       CopyItem.Enabled := True;
       PasteItem.Enabled := Clipboard.HasFormat(CF_TEXT);
       SelectAllItem.Enabled := True;
       InsertItem.Enabled := True;
       ToggleBookmarksItem.Enabled := True;
       GotoBookmarksItem.Enabled := True;
     end
  else begin
     UndoItem.Enabled := False;
     RedoItem.Enabled := False;
     CutItem.Enabled := False;
     CopyItem.Enabled := False;
     PasteItem.Enabled := False;
     SelectAllItem.Enabled := False;
     InsertItem.Enabled := False;
     ToggleBookmarksItem.Enabled := False;
     GotoBookmarksItem.Enabled := False;
   end;
end;

procedure TMainForm.ProjectMenuClick(Sender: TObject);
begin
  if ProjectOpen = True then begin
     AddToProjectItem.Enabled := True;
     RemoveFromProjectItem.Enabled := True;
     ProjectoptionsItem.Enabled := True;
     EditresourcefileItem.Enabled := True;
     NewunitinprojectItem.Enabled := True;
     GenerateMakeFileItem.Enabled := True;
     SetMainUnit1.Enabled := True;
  end
  else begin
     AddToProjectItem.Enabled := False;
     RemoveFromProjectItem.Enabled := False;
     ProjectoptionsItem.Enabled := False;
     EditresourcefileItem.Enabled := False;
     NewunitinprojectItem.Enabled := False;
     GenerateMakeFileItem.Enabled := False;
     SetMainUnit1.Enabled := False;
   end
end;

procedure TMainForm.CompileMenuClick(Sender: TObject);
begin
  if (ProjectOpen = True) or (NotProject = True) then begin
     CompileItem.Enabled := True;
     RunItem.Enabled := True;
     DebugItem.Enabled := True;
     CompilandRunItem.Enabled := True;
     RebuildallItem.Enabled := True;
  end
  else begin
     CompileItem.Enabled := False;
     RunItem.Enabled := False;
     DebugItem.Enabled := False;
     CompilandRunItem.Enabled := False;
     RebuildallItem.Enabled := False;
  end
end;

procedure TMainForm.NewItemClick(Sender: TObject);
begin
  if ProjectOpen then
     Project.AddUnit('Untitled', False, True)
  else begin
     SetIDEMode(True);

     with TEditForm.Create(self) do begin
          if MainForm.MdiChildCount > 1 then
             inc(UnitNumber)
          else UnitNumber := 1;

          Caption := 'Untitled'+ IntToStr(UnitNumber);
          if FileExists(MainForm.BinDir + DEFAULTCODE_FILE) then
             DefaultOpen(MainForm.BinDir + DEFAULTCODE_FILE);

          if (MainForm.MdiChildCount = 1) and (WindowState <> wsMaximized) then
             PostMessage(Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
          else if (MainForm.ActiveMdiChild.WindowState = wsMaximized) then
             PostMessage(Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);

          Application.ProcessMessages;
     end;
  end;

  if (IniFile.ReadBool('Options','Arrange',True)) {and (not NotProject) }then
      MainForm.Cascade; // if the user has check the Auto-Arrange option, arrange windows
end;


procedure TMainForm.CompileBtnClick(Sender: TObject);
begin
  if (ProjectOpen = True) or (MdiChildCount > 0) then // there must be a project or a file to compile
     Compile(Sender, False);
end;

procedure TMainForm.SaveOutputPosition;
begin
  IniFile.WriteInteger('Position','Line',CompilerOutput.Columns.Items[0].Width);
  IniFile.WriteInteger('Position','File',CompilerOutput.Columns.Items[1].Width);
  IniFile.WriteInteger('Position','Message',CompilerOutput.Columns.Items[2].Width);
end;

procedure TMainForm.CutItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).Cut(Sender);
end;

procedure TMainForm.CloseItemClick(Sender: TObject);
begin
  ActiveMdiChild.Close;
end;

procedure TMainForm.CopyItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).Copy(Sender);
end;

procedure TMainForm.PasteItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).Paste(Sender);
end;

procedure TMainForm.SelectallItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).SelectAll(Sender);
end;

procedure TMainForm.FindnextItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).FindNext;
end;

procedure TMainForm.GotolineItemClick(Sender: TObject);
begin
  if MdiChildCount > 0 then
     (ActiveMdiChild as TEditForm).GotoLine1Click(Sender);
end;

procedure TMainForm.SearchMenuClick(Sender: TObject);
begin
  if MainForm.MDIChildCount > 0 then begin
     FindItem.Enabled := True;
     FindNextItem.Enabled := True;
     GotoLineItem.Enabled := True;
     ReplaceItem.Enabled := True;
  end
  else  begin
     FindItem.Enabled := False;
     FindNextItem.Enabled := False;
     GotoLineItem.Enabled := False;
     ReplaceItem.Enabled := False;
  end
end;

procedure TMainForm.OpenprojectItemClick(Sender: TObject);
var i : integer;
begin
   if OpenFileDialog.Execute then begin
      // open project
      if lowercase(ExtractFileExt(OpenFileDialog.FileName)) = '.dp' then begin
         SetIDEMode(False);
         if ProjectOpen = True then begin
            Project.Free;
            CloseProjectItemClick(Sender);
         end
         else CloseAll;

         Project := TProject.Create(OpenFileDialog.FileName, '__FileOpen');
         Inc(ProjectCount);
         Caption := 'Dev-Pascal ' + DevPasVersion + ' - '+Project.Name;
         Exit;
      end
      // open resource file
      else if lowercase(ExtractFileExt(OpenFileDialog.FileName)) = '.rc' then
              EditResource(self,OpenFileDialog.FileName)
      // open source file
      else begin
           if ProjectOpen then
              if MessageDlg('Are you sure you want to close '+Project.Name+' and open "'+OpenFileDialog.FileName+'" ?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
                 CloseProjectItemClick(Sender)
              else exit;

           if not ProjectOpen then
              SetIDEMode(True);

           for i := 0 to MdiChildCount-1 do
               if MdiChildren[i].WindowState = wsMaximized then
                  MdiChildren[i].WindowState := wsNormal;

           with TEditForm.Create(self) do begin
                Open(OpenFileDialog.FileName);

                if MainForm.MdiChildCount = 1 then
                   PostMessage(Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
           end;
      end;

      // save filename in history
      AddHistory(OpenFileDialog.FileName);
      SaveFileHistory(OpenFileDialog.FileName);
   end;
end;

procedure TMainForm.CloseprojectItemClick(Sender: TObject);
begin
  ProjectView.Items.Clear;
  CompilerOutput.Items.Clear;
  ResourceOutput.Items.Clear;

  Project.Free;

  CloseAll;

  Caption := 'Dev-Pas ' + DevPasVersion + CompilerString;
  ProjectOpen := False;
  Project := Nil;
end;

procedure TMainForm.CheckParams;
Var
i : integer;
begin

  { Check user's compiler options }
  if not CompilerOptionsModified then exit;

  PasParams := '';
  UserParams := '';

 if not NotProject then
     UserParams := Project.CompilerOptions;

 if IniFile.ReadBool('Directories','AddCommands',True) then
      UserParams := UserParams + ' '+ IniFile.ReadString('Directories','Commands',UserParams);

 i := IniFile.ReadInteger('Code_Generation','Target_Cpu', 0);

 If ThisCompiler = GPC
 then begin
  if IniFile.ReadBool('Code_Generation','GUI',True) then
     PasParams := PasParams + '-mwindows ';

  if IniFile.ReadBool('Pascal_Compiler','Ansi',False) then
     PasParams := PasParams + '-fstandard-pascal ';

  if IniFile.ReadBool('Pascal_Compiler','CInline',False) then
     PasParams := PasParams  + ''
     else PasParams := PasParams  + '-fno-inline ';

  if IniFile.ReadBool('Pascal_Compiler','Macros',False) then
     PasParams := PasParams + ''
     else PasParams := PasParams  + '-fno-macros ';

  if IniFile.ReadBool('Pascal_Compiler','StripSymbols',False) then
     PasParams := PasParams + '-s ';

  if IniFile.ReadBool('Code_Generation','IOCheck',False) then
     PasParams := PasParams + '-fio-checking '
     else PasParams := PasParams  + '-fno-io-checking ';

  if IniFile.ReadBool('Code_Generation','StackCheck',False) then
     PasParams := PasParams + '-fstack-checking '
     else PasParams := PasParams  + '-fno-stack-checking ';

  if IniFile.ReadBool('Optimization','SmallCode',False) then
     PasParams := PasParams + '-Os ';

  if IniFile.ReadBool('Optimization','QuickOpt',True) then
     PasParams := PasParams + '-O1 ';

  if IniFile.ReadBool('Optimization','Best',False) then
     PasParams := PasParams + '-O3 ';

  PasParams := PasParams + GPC_CPUSwitches[i];

 end
 else begin
  if IniFile.ReadBool('Pascal_Compiler','TP7',True) then
     PasParams := PasParams + '-So ';

  if IniFile.ReadBool('Pascal_Compiler','DelphiComp',True) then
     PasParams := PasParams + '-Sd ';

  if IniFile.ReadBool('Pascal_Compiler','DelphiExt',True) then
     PasParams := '-S2 ';

  if IniFile.ReadBool('Pascal_Compiler','Assert',False) then
     PasParams := PasParams + '-Sa ';

  if IniFile.ReadBool('Pascal_Compiler','COp',False) then
     PasParams := PasParams + '-Sc ';

  if IniFile.ReadBool('Pascal_Compiler','LabelGoto',True) then
     PasParams := PasParams + '-Sg ';

  if IniFile.ReadBool('Pascal_Compiler','LinkDyn',False) then
     PasParams := PasParams + '-XD ';

  if IniFile.ReadBool('Pascal_Compiler','LinkSmart',False) then
     PasParams := PasParams + '-XX ';

  if IniFile.ReadBool('Pascal_Compiler','NoCheckUnit',True) then
     PasParams := PasParams + '-Un ';

  if IniFile.ReadBool('Code_Generation','Overflow',False) then
     PasParams := PasParams + '-Co ';

    if IniFile.ReadBool('Linker','NoReloc',False) then
     PasParams := PasParams + '-WN ';

  if IniFile.ReadBool('Pascal_Compiler','Ansi',False) then
     PasParams := PasParams + '-Sh ';

  if IniFile.ReadBool('Pascal_Compiler','CInline',False) then
     PasParams := PasParams  + '-Si '
     else PasParams := PasParams  + '';

  if IniFile.ReadBool('Pascal_Compiler','Macros',False) then
     PasParams := PasParams + '-Sm '
     else PasParams := PasParams  + '';

  if IniFile.ReadBool('Pascal_Compiler','StripSymbols',False) then
     PasParams := PasParams + '-Xs ';

  if IniFile.ReadBool('Code_Generation','IOCheck',False) then
     PasParams := PasParams + '-Ci '
     else PasParams := PasParams  + '';

  if IniFile.ReadBool('Code_Generation','StackCheck',False) then
     PasParams := PasParams + '-Ct '
     else PasParams := PasParams  + '';

  if IniFile.ReadBool('Optimization','SmallCode',False) then
     PasParams := PasParams + '-Og ';

  if IniFile.ReadBool('Optimization','QuickOpt',True) then
     PasParams := PasParams + '-O1 ';

  if IniFile.ReadBool('Optimization','Best',False) then
     PasParams := PasParams + '-O3 ';

  if IniFile.ReadBool('Linker','DebugInfo',False) then
     PasParams := PasParams + '-g ';

  PasParams := PasParams + FPC_CPUSwitches [i];
 end;
end;


procedure ResFileDoesNotExists(s : string);
begin
  MainForm.ResourceOutput.Items.Add('Resource file '+s+' does not exist. Check in Project Options.');
  MainForm.MessageControl.ActivePage := MainForm.ResSheet;
end;

{procedure ExecConsoleApp(CommandLine: String; BinDir : string);
const
  BufSize = $4000;
var
  StartupInfo : TStartupInfo;
  ProcessInfo : TProcessInformation;
begin
  FillChar(StartupInfo,SizeOf(StartupInfo), 0);

  with StartupInfo do
  begin
    cb:= SizeOf(StartupInfo);
    dwFlags:= STARTF_USESHOWWINDOW or
               STARTF_USESTDHANDLES;
    wShowWindow:= SW_HIDE;
  end;

  if not CreateProcess(nil, PChar(CommandLine), nil, nil,
     false, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,
     nil, nil, StartupInfo, ProcessInfo) then begin
      MessageDlg('Could not execute compiler. Check the directories in Compiler Options or reinstall Dev-Pascal', mtError, [mbOK],0);
      Exit;
     end
  else
  begin
    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
  end;
end; }

type
  TOutputEvent = procedure(AChar: PChar) of Object;

function CompileFile(Cmd, WorkDir: String): string;
var
  tsi: TStartupInfo;
  tpi: TProcessInformation;
  nRead: DWORD;
  aBuf: Array[0..101] of char;
  sa: TSecurityAttributes;
  hOutputReadTmp, hOutputRead, hOutputWrite, hInputWriteTmp, hInputRead,
  hInputWrite, hErrorWrite: THandle;
  FOutput: String;
begin
  FOutput := '';

  sa.nLength              := SizeOf(TSecurityAttributes);
  sa.lpSecurityDescriptor := nil;
  sa.bInheritHandle       := True;

  CreatePipe(hOutputReadTmp, hOutputWrite, @sa, 0);
  DuplicateHandle(GetCurrentProcess(), hOutputWrite, GetCurrentProcess(),
    @hErrorWrite, 0, true, DUPLICATE_SAME_ACCESS);
  CreatePipe(hInputRead, hInputWriteTmp, @sa, 0);

  // Create new output read handle and the input write handle. Set
  // the inheritance properties to FALSE. Otherwise, the child inherits
  // the these handles; resulting in non-closeable handles to the pipes
  // being created.
  DuplicateHandle(GetCurrentProcess(), hOutputReadTmp,  GetCurrentProcess(),
    @hOutputRead,  0, false, DUPLICATE_SAME_ACCESS);
  DuplicateHandle(GetCurrentProcess(), hInputWriteTmp, GetCurrentProcess(),
    @hInputWrite, 0, false, DUPLICATE_SAME_ACCESS);
  CloseHandle(hOutputReadTmp);
  CloseHandle(hInputWriteTmp);

  FillChar(tsi, SizeOf(TStartupInfo), 0);
  tsi.cb         := SizeOf(TStartupInfo);
  tsi.dwFlags    := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  tsi.hStdInput  := hInputRead;
  tsi.hStdOutput := hOutputWrite;
  tsi.hStdError  := hErrorWrite;

  If Not CreateProcess(nil, PChar(Cmd), @sa, @sa, true, 0, nil, PChar(WorkDir),
    tsi, tpi)
  then begin
     OutputForm.Output.Lines.Add ('The command: '+#13#10+'"'+Cmd+'"'+#13#10+'was not successfully executed.');
     OutputForm.Output.Lines.Add ('');
     OutputForm.Output.Lines.Add ('Please check that your "bin" directory is correct!');
     MessageDlg ('Fatal error: I could not execute the compiler!', mtError, [mbOK], 0);
  end;
  
  CloseHandle(hOutputWrite);
  CloseHandle(hInputRead );
  CloseHandle(hErrorWrite);
  Application.ProcessMessages;

  repeat
     if (not ReadFile(hOutputRead, aBuf, 16, nRead, nil)) or (nRead = 0) then
     begin
        if GetLastError = ERROR_BROKEN_PIPE then Break
        else MessageDlg('Pipe read error, could not execute file', mtError, [mbOK], 0);
     end;
     aBuf[nRead] := #0;
     FOutput := FOutput + PChar(@aBuf[0]);
     Application.ProcessMessages;
  until False;

  Result := FOutput;

  //GetExitCodeProcess(tpi.hProcess, nRead) = True;
end;

procedure TMainForm.AddItem(c, s1, s2: string);
var
  ListItem: TListItem;
begin
  ListItem:=CompilerOutput.Items.Add;
  ListItem.Caption:=c;
  ListItem.SubItems.Add(s1);
  ListItem.SubItems.Add(s2);
end;

procedure TMainForm.AnalyseOutput;
const MaxError = 30;
var c : char;
    MessageStr, LineStr, UnitStr, tmp : string;
    TotalError, current, i : integer;
    DoDec : boolean;

label Start, GoOut, CompileError, TestAgain, FatalError;

// Get next character from compiler output
function Getch : char;
begin
  c := CompileFileOutput.Text[current];
  tmp := tmp + c ;
  Result := c;
  inc(current);
end;

// Delete line break from error message
function CureStr(s : string) : string;
begin
  while pos(#10, s)<>0 do
    Delete(s,pos(#10, s),1);
  while pos(#13, s)<>0 do
    Delete(s,pos(#13, s),1);
  Result := s;
end;

begin
current := 1;
  // reads the compiler message files for errors and warnings and interprets it

if CompileFileOutput.Text <> '' then begin
  if NotProject = False then begin
     ProjectNode.SelectedIndex:= 3;    // 3 is not-compiled bitmap
     ProjectNode.ImageIndex := 3;
     ProjectView.Refresh;
  end;

  TotalError := 0;

  If CompileFileOutput.Count = 0 then exit;

  if pos('Error:', CompileFileOutput[0])<>0 then
     goto Start;

  If CompileFileOutput.Count > 0 then
  CompileFileOutput.Delete(0);

  If CompileFileOutput.Count = 0 then exit;

  If CompileFileOutput.Count > 0 then
  CompileFileOutput.Delete(0);

  If CompileFileOutput.Count = 0 then exit;

  if pos('Target OS:', CompileFileOutput[0])<>0 then
  If CompileFileOutput.Count > 0 then
     CompileFileOutput.Delete(0);

  If CompileFileOutput.Count = 0 then exit;

  i := 0;
  repeat
    DoDec := False;
    if pos('Compiling ',CompileFileOutput[i])<>0 then
    begin
       CompileFileOutput.Delete(i);
       DoDec := True;
    end;

    if pos('Linking ',CompileFileOutput[i])<>0 then
    begin
       CompileFileOutput.Delete(i);
       DoDec := True;
    end;

    if pos('Lines compiled,',CompileFileOutput[i])<>0 then begin
       CompileFileOutput.Delete(i);
       DoDec := True;
    end;

    if not DoDec then
       inc(i);
  until i >= CompileFileOutput.Count-1;

  Start:

  MessageStr := '';
  LineStr := '';
  UnitStr := '';
  tmp := '';
  c := 'A';   // initiate analyser

While (c <> '') do begin
    if TotalError > MaxError then
       goto GoOut;

    UnitStr := '';
    Getch;

    if c = '' then goto GoOut;

    repeat
      if c <> '(' then
         UnitStr := UnitStr + c;
      if Getch = '' then goto GoOut;
    until (c = '(') or (c = '') or (c = ':');

    while Pos('\\', UnitStr)<>0 do Delete(UnitStr, Pos('\\', UnitStr), 1);
    if Getch = '' then goto GoOut;

    if UnitStr = 'Fatal' then begin
       UnitStr := 'Fatal Error';
       goto FatalError;
    end;

    linestr:='';
    while c in ['0'..'9'] do begin
       LineStr := LineStr + c;
       if Getch = '' then goto GoOut;
       if (c = '') then goto GoOut;
    end;

    if c = ',' then begin
       if Getch = '' then goto GoOut;
       LineStr := LineStr+' / ';
       while c in ['0'..'9'] do begin
         LineStr := LineStr + c;
         if Getch = '' then goto GoOut;
         if (c = '') then goto GoOut;
       end;
    end;

    FatalError :

    if Getch = '' then goto GoOut;
    MessageStr := c;
    if Getch = '' then goto GoOut;

    repeat
        MessageStr := MessageStr + c;
        if Getch = '' then goto GoOut;
    until (c = #13) or (c = '');

    if Getch = '' then goto GoOut;

    while Pos('  ', MessageStr)<>0 do Delete(MessageStr, Pos('  ', MessageStr), 1);

    if (Pos('\\',MessageStr)=0) then begin
        if NotProject = False then begin
           if Project.FileAlreadyExists(UnitStr) then
              AddItem(LineStr,ExtractFileName(UnitStr),CureStr(MessageStr))
           else AddItem(LineStr,lowercase(UnitStr),CureStr(MessageStr))
        end
        else
           AddItem(LineStr,lowercase(UnitStr),CureStr(MessageStr));

        if (pos('Warning:', MessageStr)=0) and (pos('Hint:', MessageStr)=0)
           and (pos('Note:', MessageStr)=0) then
           inc(TotalError);
    end
    else if (c = '') then goto GoOut
    else goto Start;
  end;

  GoOut:

  InfoForm.TotalErrors.Caption := IntToStr(TotalError);

  {$ifndef Old_Delphi}
  if (MessageControl.ActivePage <> CompSheet) and (CompilerOutput.Items.Count > 0) then
     CompSheet.Highlighted := True;
  {$endif}
     
end;
end;

procedure TMainForm.GetDirectories;
var tmp, UserDir, ExtraDirs : string;
    i : integer;
begin
  BinDir := GetShortName(BinDir);
  UserDir := '';
  if (IniFile.ReadBool('Directories','AddDir',False)) and
     (IniFile.ReadString('Directories','Dir','') <> '') then
     UserDir := UnitSwitch + IniFile.ReadString('Directories','Dir',UserDir);

  if (not NotProject) and (Project <> nil) and (Project.IncludeDirs <> '') then begin
      tmp := '';
      ExtraDirs := '';
      for i := 1 to 255 do begin
        if Project.IncludeDirs[i] = '' then begin
           if ExtraDirs <> '' then
              ExtraDirs := ExtraDirs+';'+GetShortName(tmp)
           else ExtraDirs := GetShortName(tmp);
           break;
        end;

        if (Project.IncludeDirs[i] <> ';') then
           tmp := tmp + Project.IncludeDirs[i]
        else begin
           if ExtraDirs <> '' then begin
              if GetShortName(tmp) = '' then
                 ExtraDirs := ExtraDirs+';'+tmp
              else ExtraDirs := ExtraDirs+';'+GetShortName(tmp)
           end
           else ExtraDirs := GetShortName(tmp);
           tmp := '';
        end;
      end;

      if UserDir <> '' then
         UserDir := UserDir + ' ';

      UserDir := UserDir + UnitSwitch + ExtraDirs;

      while pos(';', UserDir) <> 0 do begin
            Insert(UnitSwitch,UserDir, pos(';', UserDir));
            Delete(UserDir, pos(';', UserDir), 1);
      end;

      if (UserDir[length(UserDir)-1] = '-') and
         (UserDir[length(UserDir)] = 'I') then
          Delete(UserDir, length(UserDir)-1, 3);
  end;

  // Get include and lib directories from a comma-sorted list
  if CompilerOptionsModified then begin
     tmp := '';

     tmp := '';
     C_PasDir := '';
     for i := 1 to 255 do begin
        if PasDir[i] = '' then begin
           if C_PasDir <> '' then
              C_PasDir := C_PasDir + ';' + GetShortName(tmp)
           else C_PasDir := GetShortName(tmp);
           break;
        end;

        if (PasDir[i] <> ';') then
           tmp := tmp + PasDir[i]
        else begin
           if C_PasDir <> '' then
              C_PasDir := C_PasDir + ';' + GetShortName(tmp)
           else C_PasDir := GetShortName(tmp);
           tmp := '';
        end;
     end;

     tmp := '';
     C_LibDir := '';
     for i := 1 to 255 do begin
        if LibDir[i] = '' then begin
           if C_LibDir <> '' then
              C_LibDir := C_LibDir+';'+GetShortName(tmp)
           else C_LibDir := GetShortName(tmp);
           break;
        end;

     if (LibDir[i] <> ';') then
         tmp := tmp + LibDir[i]
     else begin
         if C_LibDir <> '' then
            C_LibDir := C_LibDir+';'+GetShortName(tmp)
         else C_LibDir := GetShortName(tmp);
         tmp := '';
     end;
   end;
  end;

  Case ThisCompiler of
  GPC :
    begin
       Directories.Pas := UnitSwitch + PasDir;
    end;
  Freepascal :
    begin
      Directories.Pas := UnitSwitch + C_PasDir;
      while pos(';', Directories.Pas) <> 0
      do begin
        Insert(UnitSwitch,Directories.Pas, pos(';', Directories.Pas));
        Delete(Directories.Pas, pos(';', Directories.Pas), 1);
      end;
      if (Directories.Pas[length(Directories.Pas)-2] = '-') and
       (Directories.Pas[length(Directories.Pas)] = 'F')
       then Delete(Directories.Pas, length(Directories.Pas)-1, 3);
    end;   
  end;

  Directories.Lib := LibSwitch + C_LibDir;
  while pos(';', Directories.Lib) <> 0 do begin
     Insert(LibSwitch,Directories.Lib, pos(';', Directories.Lib));
     Delete(Directories.Lib, pos(';', Directories.Lib), 1);
  end;

  if (Directories.Lib[length(Directories.Lib)-1] = '-') and
     (Directories.Lib[length(Directories.Lib)] = 'L')
     then Delete(Directories.Lib, length(Directories.Lib)-1, 3);

  // all directories and parameters are now in saved
  Directories.All := ' '+ Directories.Pas + ' ' + Directories.Lib
  + BinSwitch + BinDir + ' '+ UserDir;

  // modify Directories record for the resource compiler
 If ThisCompiler = GPC
 then begin
    //
 end else
   while pos('-Fu', Directories.Pas)<> 0 do begin
     Insert('--include-dir ', Directories.Pas, pos('-Fu',Directories.Pas));
     Delete(Directories.Pas, pos('-Fu',Directories.Pas), 3);
     Delete(Directories.Pas, pos('  ',Directories.Pas), 1);
   end;
end;

{$ifndef ver140}
function ExcludeTrailingBackslash(const S: string): string;
begin
   Result := s;
   If Result [Length (Result)] = '\' then Delete (Result, Length (Result), 1);
end;
{$endif}

procedure TransformMacroPath(var ObjFile : string);
begin
  while pos('$(LIBPATH)', ObjFile)<>0 do begin
     insert(MainForm.LibDir, ObjFile, pos('$(LIBPATH)', ObjFile));
     delete(ObjFile, pos('$(LIBPATH)', ObjFile), length('$(LIBPATH)'));
     ObjFile := ExcludeTrailingBackSlash(ObjFile);
  end;
end;

function TMainForm.Compile(Sender: TObject; RebuildAll : boolean) : boolean;
var SrcExePath, ExeParams, tmp,
    Files, CompleteFileName, ResObjFile,
    ReturnFile, LogParams, ObjFile : string;

    i, pos_name, ResCount : integer;
    FileSaved : Boolean;

    ResFile : array [1..20] of record
                FileName : string;
                ObjFile  : string;
              end;

    Res : TStringList;
begin

{
  This procedure is quite big, it does nearly everything in
  the compilation stages. The comments should help you understanding
  what thie IDE is currently doing
}

  Result := False;
  ResCount := 0;

  // reset compiler output messages
  CompilerOutPut.Items.Clear;
  ResourceOutput.Items.Clear;
  CompileFileOutput := TStringList.Create;
  CompileFileOutput.Clear;
  OutputForm.Output.Clear;
  LogBox.Clear;

{$ifndef Old_Delphi}
  CompSheet.Highlighted := False;
  ResSheet.Highlighted := False;
{$endif}

  ReloadDirectories;

  GetDirectories;

  CheckParams;  // check compiler params from inifile

  // check if resource file needs to be compiled
  if NotProject = False
  then begin
     ProjIniFile := TIniFile.Create(Project.FileName);
     if (Project.Icon <> '') and (not FileExists(Project.Icon)) and (not Project.IsDll)
     then begin
        if FileExists(ExtractFilePath(Application.ExeName)+ICON_DIR+ExtractFileName(Project.Icon))
        then begin
           Project.Icon := ExtractFilePath(Application.ExeName)+ICON_DIR+ExtractFileName(Project.Icon);
           ProjIniFile.WriteString('Project','Icon',Project.Icon);

           if FileExists(ExtractFilePath(Project.FileName)+'rsrc.rc')
           then begin
              Res := TStringList.Create;
              Res.LoadFromFile(ExtractFilePath(Project.FileName)+'rsrc.rc');
              for i := 0 to Res.Count-1 do
                  if pos('500 ICON MOVEABLE PURE LOADONCALL DISCARDABLE', Res[i])<>0
                  then begin
                     Res.Delete(i);
                     Res.Add('500 ICON MOVEABLE PURE LOADONCALL DISCARDABLE "'+Project.Icon+'"');
                     Res.SaveToFile(ExtractFilePath(Project.FileName)+'rsrc.rc');
                     break;
                  end;
              Res.Free;
           end;
        end else begin
           AddItem('','Resource file','Icon file not found (please change it in Project Options)');
           Exit;
        end;
  end;

  FileSaved := False;

  // save files
  for i := 0 to MdiChildCount-1 do begin
    if (MdiChildren[i] as TEditForm).PathName = '' then begin
        ReturnFile := (MdiChildren[i] as TEditForm).Saveas1Click(Project.FileName);
        if ReturnFile <> '' then
           FileSaved := True;
    end
    else if (MdiChildren[i] as TEditForm).Modified then begin
            (MdiChildren[i] as TEditForm).Save1Click(Sender);
            FileSaved := True;
    end;

     if FileSaved then begin
        Project.Units[(ActiveMdiChild as TEditForm).GetIndex-1].FileTime := GetFileTime((ActiveMdiChild as TEditForm).PathName);
        ProjIniFile.WriteInteger('Unit'+IntToStr((ActiveMdiChild as TEditForm).GetIndex),'FileTime', Project.Units[(ActiveMdiChild as TEditForm).GetIndex-1].FileTime);
     end;

     if (MdiChildren[i] as TEditForm).PathName = '' then
       Exit;
   end; //end for loop

   SrcExePath := lowercase(GetShortName(Project.FileName));

   if Project.IsDll = False
   then begin
      SrcExePath := ChangeFileExt(SrcExePath,'.exe');
      if FileExists(ChangeFileExt(Project.FileName,'.exe')) then
         DeleteFile(pChar(ChangeFileExt(Project.FileName,'.exe')))
   end
   else begin
      SrcExePath := ChangeFileExt(SrcExePath,'.dll');
      if FileExists(ChangeFileExt(Project.FileName,'.dll')) then
         DeleteFile(pChar(ChangeFileExt(Project.FileName,'.dll')));
      if FileExists(ExtractFilePath(Project.FileName)+'lib'+ExtractFileName(ChangeFileExt(Project.FileName,'.a'))) then
         DeleteFile(pChar(ExtractFilePath(Project.FileName)+'lib'+ExtractFileName(ChangeFileExt(Project.FileName,'.a'))));
   end;

   if not NotProject
   then begin
      Files := GetShortName(Project.MainUnit);
      CompleteFileName := Project.MainUnit;
      ObjFile := Project.ObjFile;
      TransformMacroPath(ObjFile);
      ExeParams := '-o' + SrcExePath + ' ' + PasParams + UserParams + Directories.All + ' ' + ObjFile;

      if Project.NoConsole then
         ExeParams := ExeParams + GUISwitch
      else ExeParams := ExeParams + ConsoleSwitch;
   end;

   tmp := '';
   ResObjFile := '';

   // check for resource files
   if (not Project.IsDll) and (Project.ResFiles <> '')
   then begin
      if pos(';',Project.ResFiles) = 0
      then begin
         if (not FileExists(Project.ResFiles)) and
           (FileExists(ExtractFilePath(Project.FileName)+ExtractFileName(Project.ResFiles))) then begin
            Project.ResFiles := ExtractFilePath(Project.FileName)+ExtractFileName(Project.ResFiles);
            ProjIniFile.WriteString('Project','ResFiles',Project.ResFiles)
         end else if (not FileExists(Project.ResFiles))
         then begin
            ResFileDoesNotExists(Project.ResFiles);
            Exit;
         end;

         ResFile[1].FileName := {GetShortName}(Project.ResFiles);
         ResFile[1].ObjFile  := ChangeFileExt(GetShortName(Project.ResFiles),'.o');
         ResObjFile := LinkerSwitch + ResFile[1].ObjFile;
         ResCount := 1;
      end else
      for i := 1 to 255
      do begin
          if Project.ResFiles[i] = ''
          then begin
             inc(ResCount);

             if not FileExists(tmp)
             then begin
                ResFileDoesNotExists(tmp);
                exit;
             end;

             ResFile[ResCount].FileName := GetShortName(tmp);
             ResFile[ResCount].ObjFile  := ChangeFileExt(ResFile[ResCount].FileName,'.o');
             ResObjFile := ResObjFile + LinkerSwitch + ResFile[ResCount].ObjFile;
             break;
          end;

          if (Project.ResFiles[i] <> ';') then
             tmp := tmp + Project.ResFiles[i]
          else begin
             Inc(ResCount);
             ResFile[ResCount].FileName := GetShortName(tmp);
             ResFile[ResCount].ObjFile  := ChangeFileExt(ResFile[ResCount].FileName,'.o');
             ResObjFile := ResObjFile + LinkerSwitch + ResFile[ResCount].ObjFile;
             tmp := '';
          end;
       end;
  end;
  end else begin // compile just a source file
    if not SaveFile then  // try to save the file
       exit;
    Files := GetShortName((ActiveMdiChild as TEditForm).PathName);
    CompleteFileName := (ActiveMdiChild as TEditForm).PathName;
    SrcExePath := ChangeFileExt(lowercase(GetShortName(CompleteFileName)), '.exe');

    ExeParams := '-o' + SrcExePath+' ' + PasParams + UserParams + Directories.All
  end;

  pos_name := Pos(ExtractFileName(SrcExePath),SrcExePath);
  if pos_name <> 0 then
     SrcExePath[pos_name] := Upcase(SrcExePath[pos_name]);

  InfoForm.ModalResult := mrNone;
  if NotProject = False then
     InfoForm.ProjName.Caption := Project.Name
  else begin
     InfoForm.ProjName.Caption := CompleteFileName;
     InfoForm.Caption := 'Please wait while compiling...';
  end;

  InfoForm.TotalErrors.Caption := '';
  InfoForm.SizeFile.Caption := '';

  try
     ChDir(BinDir);
  except
     MessageDlg('Could not open the Bin directory'+#13,MtError,[MbOK],0);
     Exit;
  end;

  BinDir := GetShortName(BinDir);
  tmp := '';

  if FileExists(SrcExePath) then
     DeleteFile(PChar(SrcExePath));

  // delete executable if it exists
  if (NotProject) and (FileExists(ChangeFileExt((MainForm.ActiveMdiChild as TEditForm).PathName, '.exe'))) then
     DeleteFile(PChar(ChangeFileExt((MainForm.ActiveMdiChild as TEditForm).PathName, '.exe')))
  else if (not NotProject) and (FileExists(ChangeFileExt(MainForm.Project.FileName, '.exe'))) then
     DeleteFile(PChar(ChangeFileExt(MainForm.Project.FileName, '.exe')));

  with InfoForm do begin
     OkBtn.Enabled := False;
     ShowResultsBtn.Enabled := False;
     ExecBtn.Enabled := False;
     MoreBtn.Enabled := False;
     Show;
  end;

  Application.ProcessMessages;
  LogParams := '';

  // begin compilation
  if (NotProject = False) then begin
     if (Project.IsDll = False) then begin
        if (Project.ResFiles <> '') then begin // compile resource files
         InfoForm.Caption := 'Building resource file...';
         LogBox.Lines.Add('Building resource file...');
         Application.ProcessMessages;

         for i := 1 to ResCount do begin
            CopyFile(ResFile[i].FileName,ChangeFileExt(ResFile[i].FileName,'.rc_')); // just to make a new date for the resource.
            DeleteFile(pchar(ResFile[i].FileName));
            RenameFile(ChangeFileExt(ResFile[i].FileName,'.rc_'), ResFile[i].FileName);

            // compile resource file
            if not FileExists(ResFile[i].ObjFile)
               or Project.ResFileModified
               or RebuildAll then begin
                DeleteFile(pchar(ResFile[i].ObjFile));

                // Get all compile parameters in LogParams
                LogParams := BinDir + 'windres ';
                If  ThisCompiler <> GPC then LogParams := LogParams + Directories.Pas;
                LogParams := LogParams
                          + ' -i ' + ResFile[i].FileName
                          + ' -o ' + lowercase(ResFile[i].ObjFile)
                          + PreprocessorSwitch;
                LogBox.Lines.Add(LogParams);

                ResourceOutput.Items.Text := CompileFile(LogParams, BinDir)
            end
            else if not((GetFileTime(ResFile[i].ObjFile) > GetFileTime(ResFile[i].FileName)-30) or
                    (GetFileTime(ResFile[i].ObjFile) < GetFileTime(ResFile[i].FileName)+30)) then begin
                DeleteFile(pchar(ResFile[i].ObjFile));

                // Get all compile parameters in LogParams
                LogParams := BinDir + 'windres ';
                If  ThisCompiler <> GPC then LogParams := LogParams + Directories.Pas;
                LogParams := LogParams
                          + ' -I rc -O coff -i '
                          + ResFile[i].FileName+' -o '
                          + lowercase(ResFile[i].ObjFile)
                          + PreprocessorSwitch;
                LogBox.Lines.Add(LogParams);

                ResourceOutput.Items.Text :=  CompileFile(LogParams, BinDir)
            end;

            if not FileExists(ResFile[i].ObjFile) then begin
               AddItem('','Resource','Error in resource file');
               {$ifndef Old_Delphi}ResSheet.Highlighted := True;{$endif}
               InfoForm.Caption := 'Compilation stopped';
               InfoForm.OkBtn.Enabled := True;
               Exit;
            end;

            CopyFile(ResFile[i].ObjFile,ChangeFileExt(ResFile[i].ObjFile,'.o_')); // just to make a new date for the resource object.
            DeleteFile(pchar(ResFile[i].ObjFile));
            RenameFile(ChangeFileExt(ResFile[i].ObjFile,'.o_'), lowercase(ResFile[i].ObjFile));
            Project.ResFileModified := False;
         end;
       end;

       try
         ChDir(ExtractFilePath(Project.FileName));
       except
         MessageDlg('Could not open the project directory'+#13,MtError,[MbOK],0);
         Exit;
       end;

        // compile
        if Files <> ''
        then begin
           InfoForm.Caption := 'Compiling files...';
           LogBox.Lines.Add('Compiling files :');

           // Get all compile parameters in LogParams
           LogParams :=
                     AddBackSlash (BinDir)
                     + Default_Compiler
                     + Files
                     + ' '
                     + ExeParams
                     + ResObjFile;
           LogBox.Lines.Add(LogParams);
           CompileFileOutput.Text := CompileFile(LogParams,ExtractFilePath(Project.FileName));
        end;
   end
   else if Project.IsDLL then begin
       try
          ChDir(ExtractFilePath(Project.FileName));
       except
          MessageDlg('Could not open the project directory'+#13,MtError,[MbOK],0);
          Exit;
       end;

       // compile dll
       if Files <> '' then begin
          InfoForm.Caption := 'Compiling files...';
          LogBox.Lines.Add('Compiling files :');

          // Get all compile parameters in LogParams
          LogParams := AddBackSlash (BinDir) + Default_Compiler + Files + ' ' + ExeParams;
          LogBox.Lines.Add(LogParams);
          CompileFileOutput.Text := CompileFile(LogParams,ExtractFilePath(Project.FileName));
       end;

       try
          ChDir(BinDir);
       except
          MessageDlg('Could not open the Bin directory'+#13,MtError,[MbOK],0);
          Exit;
       end;
     end;
  end
  else begin // compile only a source file
    try
       ChDir(ExtractFilePath((ActiveMdiChild as TEditForm).PathName));
    except
       MessageDlg('Could not open the source file directory'+#13,MtError,[MbOK],0);
       Exit;
    end;

    LogParams := AddBackSlash (BinDir) + Default_Compiler + lowercase(Files)+ ' '+ExeParams;

    LogBox.Lines.Add('Compiling files :');
    LogBox.Lines.Add(LogParams);
    CompileFileOutput.Text := CompileFile(LogParams, ExtractFilePath((ActiveMdiChild as TEditForm).PathName))
  end;

  // rename the executable to its correct name (was in dos 8.3 format)
  if FileExists(SrcExePath)
  then begin
     if NotProject then
        RenameFile(SrcExePath, ChangeFileExt((MainForm.ActiveMdiChild as TEditForm).PathName, '.exe'))
     else if not Project.IsDll then
        RenameFile(SrcExePath, ChangeFileExt(MainForm.Project.FileName, '.exe'))
     else RenameFile(SrcExePath, ChangeFileExt(MainForm.Project.FileName, '.dll'))
  end;

  if ResourceOutput.Items.Text <> '' then
     OutputForm.Output.Lines.Add(ResourceOutput.Items.Text)
  else if CompileFileOutput.Text <> '' then
     OutputForm.Output.Lines.Add(CompileFileOutput.Text);

  AnalyseOutput;

  InfoForm.Caption := 'Compilation completed';
  if InfoForm.TotalErrors.Caption = '' then
     InfoForm.TotalErrors.Caption := '0';

  InfoForm.OkBtn.Enabled := True;
  InfoForm.ShowResultsBtn.Enabled := True;

  // rename executable to its right name
  if NotProject = False then begin
     for i := 0 to Project.UnitCount-1 do
         Project.Units[i].Modified := False;

     if (Project.IsDll) then
        SrcExePath := ChangeFileExt(Project.FileName, '.dll')
     else
        SrcExePath := ChangeFileExt(Project.FileName, '.exe');
  end
  else
     SrcExePath := ChangeFileExt((ActiveMdiChild as TEditForm).PathName, '.exe');

  if FileExists(SrcExePath) then begin
     if NotProject = False then begin
        AddItem('','',Project.Name +' compiled successfully');
        ProjectNode.SelectedIndex:= 2; // 2 is Compile bitmap
        ProjectNode.ImageIndex := 2;
        ProjectView.Refresh;
     end
     else
        AddItem('','',(ActiveMdiChild as TEditForm).PathName +' compiled successfully');

     InfoForm.SizeFile.Caption := IntToStr(GetFileSize(SrcExePath));

     if (not NotProject) and (Project.IsDll) then begin
        InfoForm.ExecBtn.Enabled := False;
        InfoForm.MoreBtn.Enabled := False;
     end else begin
        InfoForm.ExecBtn.Enabled := True;
        InfoForm.MoreBtn.Enabled := True;
        InfoForm.ShowResultsBtn.Enabled := False;
     end;
     Result := True;
  end
  else begin
     InfoForm.SizeFile.Caption := '0';
     InfoForm.ShowResultsBtn.Enabled := True;
  end;

  if (InfoForm.SizeFile.Caption = '0') and
     (InfoForm.TotalErrors.Caption = '0') then
     ShowAllOutPut;

  ChDir(ExtractFilePath(Application.ExeName));

  CompilerOptionsModified := False;

  for i := 0 to MdiChildCount-1 do
      (MdiChildren[i] as TEditForm).Modified := False;

  if MainForm.IniFile.ReadBool('Options','CompileStayOnTop',False) then
     InfoForm.FormStyle := fsStayOnTop
  else InfoForm.FormStyle := fsNormal;
  InfoForm.Show;

  if (Showonlywhenneeded1.Checked) then
  try

     tmp := CompilerOutput.Items.Item[0].SubItems.Strings[1];
     tmp := Copy(tmp, Length(tmp) - Length('compiled successfully') + 1,
                 Length('compiled successfully'));
     MessageControl.Visible := ((tmp = 'compiled successfully') and
                               (ResourceOutput.Items.Count = 0) and
                               (CompilerOutput.Items.Count = 0)) = False;

  except
     { Do nothing }
  end;
end;

procedure TMainForm.ShowAllOutPut;
begin
  if FileExists(BinDir+'compile.msg') then
     OutputForm.Output.Lines.LoadFromFile(BinDir+'compile.msg');
  OutputForm.Show;
end;

procedure TMainForm.AddtoprojectItemClick(Sender: TObject);
label Start;
var i : integer;
begin
  if ProjectOpen = False then
     Exit;

  if OpenAddDialog.InitialDir = '' then
     OpenAddDialog.InitialDir := ExtractFilePath(Project.FileName);

  Start:
  if OpenAddDialog.Execute then begin
     for i := 0 to OpenAddDialog.Files.Count-1 do begin
         if Project.FileAlreadyExists(OpenAddDialog.Files[i]) then begin
            MessageDlg('A file named "'+ExtractFileName(OpenAddDialog.Files[i])+'" already exists in '+Project.Name+'.'+#13'Please specify another filename.', MtError, [mbOK],0);
            goto Start;
         end
         else if lowercase(ExtractFileName(ChangeFileExt(OpenAddDialog.Files[i],'.dp'))) = lowercase(ExtractFileName(Project.FileName)) then begin
            MessageDlg('A unit file cannot have the same name as the project file.', MtError, [mbOK],0);
            goto Start;
         end
         else
            Project.AddUnit(OpenAddDialog.Files[i], False, True);
     end;
  end;
end;

procedure TMainForm.RemovefromprojectItemClick(Sender: TObject);
var i : integer;
    tmp : string;
begin
  if ProjectOpen = False then
     Exit;

  ProjIniFile := TIniFile.Create(Project.Filename);

  RemoveUnitForm := TRemoveUnitForm.Create(Self);
  with RemoveUnitForm do begin
    for i := 1 to Project.UnitCount do begin
        if ProjIniFile.ReadString('Unit'+IntToStr(i),'FileName',tmp) <> '' then
          begin
           tmp := ProjIniFile.ReadString('Unit'+IntToStr(i),'FileName',tmp);
           try
             RemoveUnitForm.UnitList.Items.Add(tmp);
           except
             MessageDlg('There is a problem in your project file',MtError,[MbOK],0);
           end;
      end;
    end;

   ShowModal;

   if ModalResult = MrOK then begin
       if UnitList.ItemIndex = -1 then
          Exit;

      ProjIniFile.EraseSection('Unit'+IntToStr(UnitList.ItemIndex+1));

      for i := 0 to MainForm.MdiChildCount-1 do
          if lowercase(ExtractFileName((MainForm.MdiChildren[i] as TEditForm).Caption)) = lowercase(ExtractFileName(ProjectView.Items.Item[UnitList.ItemIndex+1].Text)) then
             MainForm.MdiChildren[i].Close;

      ProjectView.Items.Delete(Project.Units[UnitList.ItemIndex].Node);//ProjectView.Items.Item[UnitList.ItemIndex+1]);

      Dec(Project.UnitCount);
      ProjIniFile.WriteInteger('Project','UnitCount',Project.UnitCount);

      for i := UnitList.ItemIndex+1 to Project.UnitCount+1 do
          ProjIniFile.WriteString('Unit'+IntToStr(i),'FileName',ProjIniFile.ReadString('Unit'+IntToStr(i+1),'FileName',''));

      for i := UnitList.ItemIndex to Project.UnitCount do begin
          Project.Units[i] := Project.Units[i+1];
      end;

      Project.Units[Project.UnitCount].FileName := '';
      ProjIniFile.EraseSection('Unit'+IntToStr(Project.UnitCount+1));
      ProjIniFile.Free;
   end;

   UnitList.Items.Clear;
   end;
end;

procedure TMainForm.SaveallItemClick(Sender: TObject);
var i : integer;
begin
  for i := 0 to MdiChildCount-1 do begin
    if (MdiChildren[i] as TEditForm).PathName = '' then
       (MdiChildren[i] as TEditForm).SaveAs1Click(Project.FileName)
    else
       (MdiChildren[i] as TEditForm).Save1Click(Sender);
  end;
end;

procedure TMainForm.ProjectoptionsItemClick(Sender: TObject);
var F       : TextFile;
    s       : TStringList;
    tmp     : string;
    j       : integer;
begin
  if ProjectOpen = False then Exit;
  ProjIniFile := TIniFile.Create(Project.FileName);

  ProjectOpt := TProjectOpt.Create(Self);
  with ProjectOpt do
  try
     try
        IconFileName := ProjIniFile.ReadString('Project', 'Icon', IconFileName);
        if FileExists(IconFileName) then
           Icon.Picture.LoadFromFile(IconFileName)
        else if FileExists(ExtractFilePath(BinDir)+ExtractFileName(IconFileName)) then begin
                IconFileName := ExtractFilePath(BinDir)+ExtractFileName(IconFileName);
                Icon.Picture.LoadFromFile(IconFileName);
                ProjIniFile.WriteString('Project','Icon',IconFileName);
                Project.Icon := IconFileName;
             end;
     except
        MessageDlg('Error loading icon', MtError, [MbOK], 0);
     end;

    { if not FileExists(ExtractFilePath(Project.Filename) + 'rsrc.rc') then
        Project.CreateNewResFile(DevPasPath+'Icon\MAINICON.ICO'); }

     NoConsole.Checked := Project.NoConsole;
     CreateDll.Checked := Project.IsDll;

     ProjectName.Text := Project.Name;
     CompilerOpt.Text := Project.CompilerOptions;
     ObjFileName.Text := Project.ObjFile;
     ResFiles.Text := Project.ResFiles;
     IncDir.Text := Project.IncludeDirs;

     if ShowModal = MrOK then
     begin
        CompilerOptionsModified := True;

        ProjIniFile.WriteString('Project','Icon',IconFileName);
        Project.Icon := IconFileName;

        s := TStringList.Create;

        if FileExists(ExtractFilePath(Project.FileName)+'rsrc.rc') and
           (Pos('rsrc.rc', Project.ResFiles)<>0) then begin
           AssignFile(F,ExtractFilePath(Project.FileName)+'rsrc.rc');
           Reset(F);

           while Pos('\', IconFileName)<>0 do begin
             j := Pos('\', IconFileName);
             Delete(IconFileName,j,1);
             Insert('/', IconFileName, j);
           end;

           s.Add('500 ICON MOVEABLE PURE LOADONCALL DISCARDABLE "'+IconFileName+'"');
           repeat
             ReadLn(F,tmp);
             if Pos('ICON MOVEABLE PURE LOADONCALL',tmp)=0 then
                s.Add(tmp);
             until eof(F);
             CloseFile(F);

             s.SaveToFile(ExtractFilePath(Project.FileName)+'rsrc.rc');
        end;

        Project.Name := ProjectName.Text;
        ProjIniFile.WriteString('Project','Name',Project.Name);
        if MainForm.ProjectView <> nil then
           MainForm.ProjectView.Items[0].Text := Project.Name;

        Project.CompilerOptions := CompilerOpt.Text;
        ProjIniFile.WriteString('Project', 'CompilerOptions', CompilerOpt.Text);

        Project.IncludeDirs := IncDir.Text;
        ProjIniFile.WriteString('Project', 'IncludeDirs', IncDir.Text);

        Project.ObjFile := ObjFileName.Text;
        ProjIniFile.WriteString('Project','ObjFile',ObjFileName.Text);

        Project.ResFiles := ResFiles.Text;
        ProjIniFile.WriteString('Project','ResFiles',ResFiles.Text);

        Project.NoConsole := NoConsole.Checked;
        ProjIniFile.WriteBool('Project','NoConsole',NoConsole.Checked);

        Project.IsDll := CreateDll.Checked;
        ProjIniFile.WriteBool('Project','IsDll',CreateDll.Checked);
     end;
  finally
     Free;
  end;
  Caption := 'Dev-Pascal '+ DevPasVersion + ' - ' + Project.Name;
  ProjIniFile.Free;
end;

procedure TMainForm.SaveasItemClick(Sender: TObject);
begin
  if NotProject then
     (ActiveMdiChild as TEditForm).SaveOneSource
  else
     (ActiveMdiChild as TEditForm).Saveas1Click(Project.FileName);
end;

procedure TMainForm.CheckforDevPasUpdatesItemClick(Sender: TObject);
begin
  CheckForm := TCheckForm.Create(Self);
  with CheckForm do
  try
     ShowModal;
  finally
    Free;
  end;
end;

procedure TMainForm.MainItemClick(Sender: TObject);
begin
  MainItem.Checked := not MainItem.Checked;
  MainToolbar.Visible := MainItem.Checked;

  if IniFile.ReadBool('Options','ToolbarSave', True) then
     IniFile.WriteBool('ToolBars','Main',MainToolBar.Visible);
end;

procedure TMainForm.ProjectItemClick(Sender: TObject);
begin
  ProjectItem.Checked := not ProjectItem.Checked;
  ProjectToolbar.Visible := ProjectItem.Checked;

  if IniFile.ReadBool('Options','ToolbarSave', False) then
     IniFile.WriteBool('ToolBars','Project',ProjectToolBar.Visible);  
end;

procedure TMainForm.OptionItemClick(Sender: TObject);
begin
  OptionItem.Checked := not OptionItem.Checked;
  OptToolbar.Visible := OptionItem.Checked;
  if IniFile.ReadBool('Options','ToolbarSave', False) then
     IniFile.WriteBool('ToolBars','Options',OptToolBar.Visible);
end;

procedure TMainForm.StatusbarItemClick(Sender: TObject);
begin
  StatusbarItem.Checked := not StatusbarItem.Checked;
  StatusBar.Visible := StatusbarItem.Checked;

  if IniFile.ReadBool('Options','ToolbarSave', True) then
     IniFile.WriteBool('ToolBars','StatusBar',StatusBar.Visible);
end;

procedure TMainForm.ViewMenuClick(Sender: TObject);
begin
  StatusbarItem.Checked := StatusBar.Visible;
end;

procedure TMainForm.ToolbarsItemClick(Sender: TObject);
begin
  MainItem.Checked := MainToolBar.Visible;
  ProjectItem.Checked := ProjectToolbar.Visible;
  OptionItem.Checked := OptToolbar.Visible;
end;

function TMainForm.CloseAll;
var i : integer;
begin
  Result := True;
  if MdiChildCount > 0 then
     for i := MdiChildCount-1 downto 0 do begin
         MdiChildren[i].Close;
         Application.ProcessMessages;
         if MdiChildren[i] <> nil then begin
            Result := False;
            Break;
         end;
     end;
end;

procedure TMainForm.CloseAllClick(Sender: TObject);
begin
  CloseAll;
end;

procedure TMainForm.CompilingresultsItemClick(Sender: TObject);
begin
  InfoForm.ModalResult := mrNone;
  if MainForm.IniFile.ReadBool('Options','CompileStayOnTop',False) then
     InfoForm.FormStyle := fsStayOnTop
  else InfoForm.FormStyle := fsNormal;
  InfoForm.Show;
  if InfoForm.ModalResult = MrYes then begin
     OutputForm.Output.Lines.LoadFromFile(BinDir+'compile.msg');
     OutputForm.Show;
  end;
end;

procedure TMainForm.SelectErrorLine(MdiForm : TEditForm);
var i : integer;
    sY : string;
    c : char;
begin
with MdiForm do begin
  sY := '';

  i := 0;
  c := 'A';
  while (c <> ' ') and (c <> #0) do begin
    inc(i);
    c := CompilerOutput.ItemFocused.Caption[i];
    if (c <> ' ') and (c <> #0) then
       sY := sY + c;
  end;

  Editor.SelectedColor.BackGround := clRed;
  if StrtoInt(sY) > Editor.Lines.Count then
     Editor.CaretY := StrToInt(sY)-1
  else Editor.CaretY := StrToInt(sY);

  Show;
  Editor.SetFocus;
  Application.ProcessMessages;

  InvalidateLine := True;
  if HighlightedLine <> Editor.CaretY then begin
     Editor.InvalidateLine(HighlightedLine);
     HighlightedLine := Editor.CaretY;
     Editor.InvalidateLine(HighlightedLine);
  end;
end;
end;

procedure TMainForm.OutputDblClick(Sender: TObject);
var i, k : integer;
begin
  if not NotProject then
     if (CompilerOutput.ItemFocused = nil) or
        (CompilerOutput.ItemFocused.SubItems.Strings[0] = 'Compiler') or
        (CompilerOutput.ItemFocused.SubItems.Strings[0] = '') or
        (ProjectView.Items[0].ImageIndex = 2) then // means project has been compiled successfully
        exit;

  if ((NotProject = True) and
     (MdiChildCount = 0)) or
     (pos('successfully',CompilerOutput.ItemFocused.SubItems.Strings[1])<>0) or
     (CompilerOutput.ItemFocused.SubItems.Strings[0] = 'Compiler') or
     (CompilerOutput.ItemFocused.SubItems.Strings[0] = '') then
     Exit;

  for i := 0 to MdiChildCount-1 do begin
    if (lowercase(ExtractFileName((MdiChildren[i] as TEditForm).PathName)) = lowercase(ExtractFileName(CompilerOutput.ItemFocused.SubItems.Strings[0]))) or
       (lowercase(ExtractFileName(GetShortName((MdiChildren[i] as TEditForm).PathName))) = lowercase(ExtractFileName(CompilerOutput.ItemFocused.SubItems.Strings[0])))
     then begin
            SelectErrorLine(MdiChildren[i] as TEditForm);
            Exit;
    end;
  end;

   if NotProject = False then begin
       for k := 0 to Project.UnitCount-1 do
           if (lowercase(ExtractFileName(Project.Units[k].FileName)) = lowercase(ExtractFileName(CompilerOutput.ItemFocused.SubItems.Strings[0]))) or
              (lowercase(ExtractFileName(GetShortName(Project.Units[k].FileName))) = lowercase(ExtractFileName(CompilerOutput.ItemFocused.SubItems.Strings[0]))) then
           begin
              Project.ShowUnit(Project.Units[k].FileName);
              Application.ProcessMessages;
              SelectErrorLine(ActiveMdiChild as TEditForm);
              Exit;
           end;
    end
    else with TEditForm.Create(self) do begin
         PathName := CompilerOutput.ItemFocused.SubItems.Strings[0];
         Caption := ExtractFileName(PathName);
         if FileExists(PathName) then
            Open(PathName);
    end
end;

procedure TMainForm.OutputClick(Sender: TObject);
begin
  if (ProjectOpen = False) or (CompilerOutput.Items.Count=0)
     or (CompilerOutput.ItemFocused = nil) then Exit;
  CompilerOutput.ShowHint := True;
  if CompilerOutput.ItemFocused.Caption <> '' then
     CompilerOutput.Hint := 'Line '+CompilerOutput.ItemFocused.Caption+': '+CompilerOutput.ItemFocused.SubItems.Strings[1]
  else CompilerOutput.Hint := CompilerOutput.ItemFocused.SubItems.Strings[1];
end;

procedure TMainForm.ClearPopItemClick(Sender: TObject);
begin
  if MessageControl.ActivePage = CompSheet then begin
     CompilerOutput.Items.Clear;
     CompilerOutput.ShowHint := False;
  end
  else if (MessageControl.ActivePage = ResSheet) then begin
     ResourceOutput.Items.Clear;
     ResourceOutput.ShowHint := False;
  end
  else if (MessageControl.ActivePage = LogSheet) then begin
     LogBox.Lines.Clear;
     LogBox.ShowHint := False;
  end
end;

procedure TMainForm.EditresourcefileItemClick(Sender: TObject);
var
  Res_File : string;
begin
  if ProjectOpen = False then Exit;

  {if not FileExists(ExtractFilePath(Project.Filename) + 'rsrc.rc') then
     Project.CreateNewResFile(DevPasPath+'Icon\MAINICON.ICO');}

  if FileExists(Project.ResFiles) then
     Res_File := Project.ResFiles
  else if FileExists(ExtractFilePath(Project.Filename) + 'rsrc.rc') then
     Res_File := ExtractFilePath(Project.Filename) + 'rsrc.rc';

  EditResource(self,Res_File);
end;

procedure TMainForm.CompileAndExecuteClick(Sender: TObject);
begin
  if (ProjectOpen = False) and (MdiChildCount = 0) then exit;
  if Compile(Sender, False) = True then
     RunBtnClick(Sender);
end;

procedure TMainForm.MouseEnter(Sender: TObject);
begin
StatusBar.SimpleText := (Sender as TToolbarButton97).Hint;
end;

procedure TMainForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
StatusBar.SimpleText := '';
end;

procedure TMainForm.Bookmark0Click(Sender: TObject);
begin
  if MdiChildCount = 0 then
     Exit;
  (ActiveMdiChild as TEditForm).Bookmark01Click(Sender);
end;

procedure TMainForm.Bookmark02Click(Sender: TObject);
begin
  if MdiChildCount = 0 then
     Exit;
  (ActiveMdiChild as TEditForm).Bookmark02Click(Sender);
end;

procedure TMainForm.RedoItemClick(Sender: TObject);
begin
  if MdiChildCount = 0 then
     Exit;
  (ActiveMdiChild as TEditForm).Redo(Sender);
end;

procedure TMainForm.CommentheaderItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteCommentHeader;
end;

procedure TMainForm.MainFunctionItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteMainFunction;
end;

procedure TMainForm.ifdefItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteIfdef;
end;

procedure TMainForm.ifndefItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteIfndef;
end;

procedure TMainForm.includeItemClick(Sender: TObject);
var s : string;
begin
  InputQuery('Include directive','Please specify filename: ',s);
  (ActiveMdiChild as TEditForm).WriteInclude(s);
end;

procedure TMainForm.InsertItemClick(Sender: TObject);
begin
  if MainForm.MDIChildCount > 0 then begin
     CommentheaderItem.Enabled := True;
     MainFunctionItem.Enabled := True;
     WinMainFunctionItem.Enabled := True;
     MessageBoxItem.Enabled := True;
     ifItem.Enabled := True;
     whileItem.Enabled := True;
     dowhileItem.Enabled := True;
     forItem.Enabled := True;
  end
  else begin
     CommentheaderItem.Enabled := False;
     MainFunctionItem.Enabled := False;
     WinMainFunctionItem.Enabled := False;
     MessageBoxItem.Enabled := False;
     ifItem.Enabled := False;
     whileItem.Enabled := False;
     dowhileItem.Enabled := False;
     forItem.Enabled := False;
  end;
end;

procedure TMainForm.InsertBtnClick(Sender: TObject);
begin
  InsertMenu.Popup(InsertBtn.ClientOrigin.x+InsertBtn.Width, InsertBtn.ClientOrigin.y);
end;

procedure TMainForm.InsertMenuPopup(Sender: TObject);
begin
  if MainForm.MDIChildCount > 0 then begin
     CommentheaderPopItem.Enabled := True;
     MainFunctionPopItem.Enabled := True;
     WinMainFunctionPopItem.Enabled := True;
     MessageBoxPopItem.Enabled := True;
     ifPopItem.Enabled := True;
     whilePopItem.Enabled := True;
     dowhilePopItem.Enabled := True;
     forPopItem.Enabled := True;
     DateandtimePopItem.Enabled := True;
     Unitbeginend1.Enabled := True;
  end
  else begin
     CommentheaderPopItem.Enabled := False;
     MainFunctionPopItem.Enabled := False;
     WinMainFunctionPopItem.Enabled := False;
     MessageBoxPopItem.Enabled := False;
     ifPopItem.Enabled := False;
     whilePopItem.Enabled := False;
     dowhilePopItem.Enabled := False;
     forPopItem.Enabled := False;
     DateandtimePopItem.Enabled := False;
     Unitbeginend1.Enabled := False;
  end;
end;

procedure TMainForm.SpecialsItemClick(Sender: TObject);
begin
  SpecialsItem.Checked := not SpecialsItem.Checked;
  Specialsbar.Visible := SpecialsItem.Checked;

  if IniFile.ReadBool('Options','ToolbarSave', False) then
     IniFile.WriteBool('ToolBars','Specials',SpecialsBar.Visible);
end;

procedure TMainForm.SpecialsBarClose(Sender: TObject);
begin
  SpecialsItem.Checked := not SpecialsItem.Checked;
  if IniFile.ReadBool('Options','ToolbarSave', True) then
     IniFile.WriteBool('ToolBars','Specials',False);
end;

procedure TMainForm.OptToolbarClose(Sender: TObject);
begin
  OptionItem.Checked := not OptionItem.Checked;
  if IniFile.ReadBool('Options','ToolbarSave', True) then
     IniFile.WriteBool('ToolBars','Options',False);
end;

procedure TMainForm.CompileToolbarClose(Sender: TObject);
begin
  CompileAndRunItem.Checked := not CompileAndRunItem.Checked;
  if IniFile.ReadBool('Options','ToolbarSave', True) then
     IniFile.WriteBool('ToolBars','Compile',False);
end;

procedure TMainForm.MainToolBarClose(Sender: TObject);
begin
  MainItem.Checked := not MainItem.Checked;
  if IniFile.ReadBool('Options','ToolbarSave', True) then
     IniFile.WriteBool('ToolBars','Main',False);
end;

procedure TMainForm.MouseExit(Sender: TObject);
begin
  StatusBar.SimpleText := '';
end;

procedure TMainForm.ToggleBtnClick(Sender: TObject);
var i : integer;
begin
  if MdiChildCount > 0 then
     for i := 0 to ToggleMenu.Items.Count-1 do
         ToggleMenu.Items[i].Enabled := True
  else
     for i := 0 to ToggleMenu.Items.Count-1 do
         ToggleMenu.Items[i].Enabled := False;

  ToggleMenu.Popup(ToggleBtn.ClientOrigin.x+ToggleBtn.Width, ToggleBtn.ClientOrigin.y);
end;

procedure TMainForm.GotoBtnClick(Sender: TObject);
var i : integer;
begin
  if MdiChildCount > 0 then
     for i := 0 to GotoMenu.Items.Count-1 do
         GotoMenu.Items[i].Enabled := True
  else
     for i := 0 to GotoMenu.Items.Count-1 do
         GotoMenu.Items[i].Enabled := False;

  GotoMenu.Popup(GotoBtn.ClientOrigin.x+GotoBtn.Width, GotoBtn.ClientOrigin.y);
end;

procedure TMainForm.ProjectManagerViewItemClick(Sender: TObject);
begin
  ProjectManagerViewItem.Checked := not ProjectManagerViewItem.Checked;
  ProjectView.Visible := ProjectManagerViewItem.Checked;
end;

procedure TMainForm.WinMainfunctionItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteWinMainFunction;
end;

procedure TMainForm.MessageBoxItemClick(Sender: TObject);
var
    MsgForm : TMessageBoxForm;
begin
  MsgForm := TMessageBoxForm.Create(Self);
  try
     if MsgForm.ShowModal = mrOk then
        (ActiveMdiChild as TEditForm).WriteMessageBox(MsgForm.Text, MsgForm.TitleText, MsgForm.Buttons);
  finally
     MsgForm.Free;
  end;
end;

procedure TMainForm.UpdateSyntaxColor;
var i : integer;
begin
  for i := 0 to MdiChildCount-1 do
      (MdiChildren[i] as TEditForm).ReadSyntaxColor;
end;

procedure TMainForm.RemoveFilefromprojectPopItemClick(Sender: TObject);
var CurrentNode, i : integer;
begin
try
if SelectedNode = nil then exit;

if SelectedNode.ImageIndex = 1 then begin
   ProjIniFile := TIniFile.Create(Project.FileName);

   CurrentNode := Project.GetUnitIndex(ProjectView.Selected.Text)+1;//SelectedNode.Index+1;

   ProjIniFile.EraseSection('Unit'+IntToStr(CurrentNode));

   Dec(Project.UnitCount);
   ProjIniFile.WriteInteger('Project','UnitCount',Project.UnitCount);

   for i := 0 to MdiChildCount-1 do
       if lowercase(ExtractFileName((MdiChildren[i] as TEditForm).Caption)) = lowercase(ExtractFileName(ProjectView.Items.Item[CurrentNode].Text)) then
          MainForm.MdiChildren[i].Close;

   for i := CurrentNode to Project.UnitCount+1 do
       ProjIniFile.WriteString('Unit'+IntToStr(i),'FileName',ProjIniFile.ReadString('Unit'+IntToStr(i+1),'FileName',''));

   for i := CurrentNode-1 to Project.UnitCount-1 do
       Project.Units[i].FileName := Project.Units[i+1].FileName;

   if ProjectNode.HasChildren = True then
      ProjectNode.DeleteChildren;

   for i := 0 to Project.UnitCount-1 do
       MakeNewFileNode(Project.Units[i].FileName);
   ProjectNode.Expand(True);

   Project.Units[Project.UnitCount].FileName := '';
   ProjIniFile.EraseSection('Unit'+IntToStr(Project.UnitCount+1));

   ProjIniFile.Free;
end;
except
end;
end;

procedure TMainForm.ReplaceItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).ReplaceDialog.Execute;
end;

procedure TMainForm.HTMLItemClick(Sender: TObject);
begin
  ExportDialog.FileName := ChangeFileExt(ExtractFileName(ActiveMdiChild.Caption),'.html');
  ExportDialog.FilterIndex := 1;

  if ExportDialog.Execute then
  with (ActiveMdiChild as TEditForm) do begin
    SynExporterHTML.ExportAll(Editor.Lines);
    SynExporterHTML.SaveToFile(ExportDialog.FileName);
    Editor.BlockEnd := Editor.BlockBegin;
  end;
end;

procedure TMainForm.RenamefilePopItemClick(Sender: TObject);
var From, s : string;
    i, index : integer;
begin
if SelectedNode = nil then exit;
index := Project.GetUnitIndex(ProjectView.Selected.Text);
From := Project.Units[index].FileName;
s := ExtractFilePath(From);
if InputQuery('Rename file','File shoud be renamed to:',s)
   and  (ExtractFileName(s) <> '') then
try
  RenameFile(From, s);
  Project.Units[index].FileName := s;

  for i := 0 to MdiChildCount-1 do
      if (MdiChildren[i] as TEditForm).PathName = From then begin
         MdiChildren[i].Caption := ExtractFileName(s);
         (MdiChildren[i] as TEditForm).PathName := s;
      end
      else if ((MdiChildren[i] as TEditForm).PathName = '') and
              ((MdiChildren[i] as TEditForm).Caption = ExtractFileName(From)) then
           MdiChildren[i].Caption := ExtractFileName(s);

  ProjIniFile := TIniFile.Create(Project.FileName);

  ProjIniFile.WriteString('Unit'+IntToStr(Index+1),'FileName',s);
  SelectedNode.Text := ExtractFileName(s);

  ProjIniFile.Free;
except
  MessageDlg('Could not rename file.',mtError, [mbOK], 0);
end;
end;

procedure TMainForm.ProjecttoHTMLItemClick(Sender: TObject);
var
  F: TextFile;
  FileName: String;
  i: integer;
begin
  if ProjectOpen = False then Exit;
  AssignFile(F, ChangeFileExt(Project.FileName, '.html'));
  Rewrite(F);
  Writeln(F, '<!-- This file was generated by Bloodshed Dev-Pascal '+DevPasVersion+'-->');
  Writeln(F, '<!-- http://www.bloodshed.net/ -->');
  Writeln(F, '');
  Writeln(F, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">');
  Writeln(F, '');
  Writeln(F, '<HTML>');
  Writeln(F, '<HEAD>');
  Writeln(F, '  <META HTTP-EQUIV=Content-Type CONTENT="text/html; charset=iso-8859-1">');
  Writeln(F, '  <META NAME=Generator CONTENT="Bloodshed Dev-Pascal">');
  Writeln(F, '  <TITLE>'+Project.Name+' project</TITLE>');
  Writeln(F, '</HEAD>');
  Writeln(F, '');
  Writeln(F, '<BODY BGCOLOR=#FFFFFF>');
  Writeln(F, '');
  Writeln(F, '<P><FONT COLOR=#000080><STRONG><H1>Dev-Pascal Project:' +
    Project.Name + '</H1></STRONG></FONT></P>');
  Writeln(F, '');

  if Project.IsDll then
     FileName := ChangeFileExt(Project.FileName,'.dll')
  else
     FileName := ChangeFileExt(Project.FileName,'.exe');

  if FileExists(FileName) then begin
     Writeln(F, '<P><STRONG>compiled on: ' + IntToStr(GetFileTime(FileName)) + '</STRONG></P>');
     Writeln(F, '<P><STRONG>Executable is: ' + IntToStr(GetFileSize(FileName)) + ' bytes</STRONG></P>');
  end;
  Writeln(F, '');

  Writeln(F, '<TABLE BORDER=1>');
  Writeln(F, '<TR><TD COLSPAN=2><STRONG>Unit information</STRONG></TD></TR>');

  for i := 0 to Project.UnitCount-1 do begin
     Writeln(F, '<TR>');
     Writeln(F, '  <TD>Unit ' + IntToStr(i + 1) + ':</TD>');
     Writeln(F, '  <TD>' + Project.Units[i].FileName + '</TD>');
     Writeln(F, '</TR>');
  end;

  Writeln(F, '</TABLE>');
  Writeln(F, '');
  Writeln(F, '<P><STRONG>Project settings:</STRONG></P>');

  Writeln(F, 'Number of unit : ' + IntToStr(Project.UnitCount) + '<BR>');

  if Project.NoConsole = True then
     Writeln(F, 'Create a console : NO<BR>')
  else
     Writeln(F, 'Create a console : YES<BR>');

  Writeln(F, 'Icon filename : ' + Project.Icon + '<BR>');
  Writeln(F, 'Object files or linker options : ' + Project.ObjFile + '<BR>');
  Writeln(F, 'Compiler options : ' + Project.CompilerOptions + '<BR>');
  Writeln(F, 'Include directories : ' + Project.IncludeDirs + '<BR>');


  if Project.IsDll then
     Writeln(F, 'DLL : YES<BR>')
  else
     Writeln(F, 'DLL : NO<BR>');

  Writeln(F, '</P>');
  Writeln(F, '');
  Writeln(F, '</BODY>');
  Write(F, '</HTML>');

  CloseFile(F);

  MessageBeep($7777);
  MessageDlg('Your project has been converted to HTML in file ' +
             ChangeFileExt(Project.FileName, '.html'), MtInformation, [mbOK], 0);
end;

procedure TMainForm.WindowMenuClick(Sender: TObject);
begin
if MdiChildCount > 0 then begin
   TileItem.Enabled := True;
   CascadeItem.Enabled := True;
   ArrangeiconsItem.Enabled := True;
   CloseAllItem.Enabled := True;
   MinimizeallItem.Enabled := True;
   NextItem.Enabled := True;
   PreviousItem.Enabled := True;
   N32.Visible := True;
end
else begin
   TileItem.Enabled := False;
   CascadeItem.Enabled := False;
   ArrangeiconsItem.Enabled := False;
   CloseAllItem.Enabled := False;
   MinimizeallItem.Enabled := False;
   NextItem.Enabled := False;
   PreviousItem.Enabled := False;
   N32.Visible := False;
end;
end;

procedure TMainForm.ProjectManagerBarClose(Sender: TObject);
begin
  ProjectManagerViewItem.Checked := False;
end;

procedure TMainForm.CompileBarClose(Sender: TObject);
begin
  CompilerOutputItem.Checked := False;
end;

procedure TMainForm.SetIDEMode(NotProj : boolean);
begin
  NotProject := NotProj;
  ProjectMenu.Enabled := not NotProj;
  if NotProject then begin
     ProjectManagerViewItem.Checked := False;
     ProjectView.Visible := False;
  end else begin
     ProjectView.Visible := not IniFile.ReadBool('Options','NoProjExpl',False);
     ProjectManagerViewItem.Checked := ProjectView.Visible;
  end;
  CompilerOptionsModified := True;
end;


procedure TMainForm.SetupCreatorClick(Sender: TObject);
begin
  SetupCreatorWindow := TSetupCreatorWindow.Create(self);
  SetupCreatorWindow.Show;
end;

procedure TMainForm.TutorialItemClick(Sender: TObject);
begin
  ExecuteFile('tutorial.hlp','',ExtractFilePath(Application.ExeName)+'Help\',SW_SHOW);
end;

procedure TMainForm.StandardLibraryItemClick(Sender: TObject);
begin
  ExecuteFile('stl.hlp','',ExtractFilePath(Application.ExeName)+'Help\',SW_SHOW);
end;

procedure TMainForm.GNUDebuggerhelpItemClick(Sender: TObject);
begin
ExecuteFile('Gdb.hlp','',ExtractFilePath(Application.ExeName)+'Help\',SW_SHOW);
end;

procedure TMainForm.ifPopItemClick(Sender: TObject);
begin
(ActiveMdiChild as TEditForm).WriteIf;
end;

procedure TMainForm.whilePopItemClick(Sender: TObject);
begin
(ActiveMdiChild as TEditForm).WriteWhile;
end;

procedure TMainForm.dowhilePopItemClick(Sender: TObject);
begin
(ActiveMdiChild as TEditForm).WriteRepeat;
end;

procedure TMainForm.forPopItemClick(Sender: TObject);
begin
(ActiveMdiChild as TEditForm).WriteFor;
end;

procedure TMainForm.MessageControlChange(Sender: TObject);
begin
  {$ifndef Old_Delphi}MessageControl.ActivePage.Highlighted := False;{$endif}
end;

procedure TMainForm.MinimizeallItemClick(Sender: TObject);
var i : integer;
begin
  if MdiChildCount <> 0 then begin
     for i := 0 to MdiChildCount-1 do
         ActiveMdiChild.WindowState := wsMinimized;
  end;
end;

procedure TMainForm.NextItemClick(Sender: TObject);
begin
  Next;
  Application.ProcessMessages;
  ActiveMdiChild.OnPaint(sender);
end;

procedure TMainForm.PreviousItemClick(Sender: TObject);
begin
  Previous;
  Application.ProcessMessages;
  ActiveMdiChild.OnPaint(sender);
end;

procedure TMainForm.ProjectViewMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var s, tmp : string;
    i : integer;
    ReOpenUnit : boolean;
label RightClick;
begin
  if (not ProjectOpen) or (ProjectView.TopItem.TreeView.GetNodeAt(x,y) = nil) then
      exit;

  if (Button = mbRight) or (ProjectView.TopItem.TreeView.GetNodeAt(x,y) = ProjectView.TopItem) then
     goto RightClick;

  s := lowercase(ProjectView.TopItem.TreeView.GetNodeAt(x,y).Text);

  if s <> lowercase(ExtractFileName(ChangeFileExt(Project.FileName,''))) then begin
     ReOpenUnit := True;
     if ProjectView.TopItem.TreeView.GetNodeAt(x,y).ImageIndex = 1 then // only units have 1 for their imageindex property
        for i := 0 to MdiChildCount-1 do begin
            if lowercase(s) = lowercase(MDIChildren[i].Caption) then begin
               tmp := MdiChildren[i].Caption;
               MdiChildren[i].BringToFront;
               Application.ProcessMessages;
               if MaxiMode then
                  Caption := 'Dev-Pascal ' + DevPasVersion + ' - ' + MainForm.Project.Name + ' - [' + tmp +']';

               ReOpenUnit := False;
               break;
            end;
        end;

     if ReOpenUnit then
        Project.ShowUnit(Project.GetUnit(s).FileName);//Project.Units[ProjectView.TopItem.TreeView.GetNodeAt(x,y).Index].FileName, ProjectView.Selected.Index+1);
  end;

  RightClick :
  if (ProjectView.TopItem.TreeView.GetNodeAt(x,y) = nil) or (Button = mbLeft) then exit;

  if ((ProjectView.TopItem.TreeView.GetNodeAt(x,y).ImageIndex = 0) or // only project have these imageindex
     (ProjectView.TopItem.TreeView.GetNodeAt(x,y).ImageIndex = 2)  or
     (ProjectView.TopItem.TreeView.GetNodeAt(x,y).ImageIndex = 3)) then begin
      ProjectPopup.Popup(X+MainForm.Left,Y+MainForm.Top);
      ProjectView.Selected := ProjectView.TopItem.TreeView.GetNodeAt(x,y);
  end
  else begin
     SelectedNode := ProjectView.TopItem.TreeView.GetNodeAt(x,y);
     ProjectView.Selected := SelectedNode;
     UnitPopup.Popup(X+MainForm.Left,Y+60+MainForm.Top)
  end;
end;

procedure TMainForm.ClosefilePopItemClick(Sender: TObject);
begin
  if MdiChildCount > 0 then
     ActiveMdiChild.Close;
end;

procedure TMainForm.RTFItemClick(Sender: TObject);
begin
  ExportDialog.FileName := ChangeFileExt(ExtractFileName(ActiveMdiChild.Caption),'.rtf');
  ExportDialog.FilterIndex := 2;

  if ExportDialog.Execute then
  with (ActiveMdiChild as TEditForm) do begin
    SynExporterRTF.ExportAll(Editor.Lines);
    SynExporterRTF.SaveToFile(ExportDialog.FileName);
    Editor.BlockEnd := Editor.BlockBegin;
  end;
end;

procedure TMainForm.HelponDevPasItemClick(Sender: TObject);
begin
  ExecuteFile(DevPasPath+'Help\DevPas.hlp','','', SW_SHOW);
end;

procedure TMainForm.CopyPopItemClick(Sender: TObject);
begin
  if (MessageControl.ActivePage = CompSheet) and (CompilerOutput.ItemFocused <> nil) then
     ClipBoard.AsText := CompilerOutput.ItemFocused.Caption + ' ' + CompilerOutput.ItemFocused.SubItems.Text
  else if (MessageControl.ActivePage = ResSheet) then
     ClipBoard.AsText := ResourceOutput.Items.Text
  else if (MessageControl.ActivePage = LogSheet) then
     LogBox.CopyToClipBoard;
end;

procedure TMainForm.CompileandRunItemClick(Sender: TObject);
begin
  CompileAndRunItem.Checked := not CompileAndRunItem.Checked;
  CompileToolbar.Visible := CompileAndRunItem.Checked;
  if IniFile.ReadBool('Options','ToolbarSave', False) then
     IniFile.WriteBool('ToolBars','Compile',CompileToolBar.Visible);
end;

procedure TMainForm.CreateNewDefaultFile;
var F : TextFile;
begin
  AssignFile(F,BinDir+DEFAULTCODE_FILE);
  Rewrite(F);

  Writeln(F,'unit Untitled;');
  Writeln(F,'interface');
  Writeln(F,'');
  Writeln(F,'implementation');
  Writeln(F,'');
  Writeln(F,'begin');
  Writeln(F,'');
  Writeln(F,'end.');

  CloseFile(F);
end;

procedure TMainForm.CreateNewCompletionFile;
var F : TextFile;
begin
  AssignFile(F,BinDir+COMPLETION_FILE);
  {$i-}
  Rewrite(F);

  Writeln(F,'if');
  Writeln(F,'while');
  Writeln(F,'do');
  Writeln(F,'for');
  Writeln(F,'repeat');
  Writeln(F,'until');
  Writeln(F,'begin');
  Writeln(F,'end');
  Writeln(F,'program');

  CloseFile(F);
  {$i+}
  If ioresult <> 0 then
    messagebox (handle, pchar (BinDir+COMPLETION_FILE), 'File creation Error', 0);
end;

procedure TMainForm.ProjectToolbarClose(Sender: TObject);
begin
  ProjectItem.Checked := not ProjectItem.Checked;
  if IniFile.ReadBool('Options','ToolbarSave', False) then
     IniFile.WriteBool('ToolBars','Project',False);
end;

procedure TMainForm.GenerateMakeFileItemClick(Sender: TObject);
{$I Makefile.inc}
var
  F: TextFile;
  i: Integer;

  FSources, { The source files (all *.pas, *.pp files) }
  FObjects, { The object files (*.o) }
  CompilerFlags, { The parameters given to the compiler }
  OutputFile,    { The compiled EXE or DLL }
  OutputCommand, { The command line to execute the output file }
  FCompiler,     { The compiler's command line }
  FLinker,       { The linker's command line }
  FResource      { The resource compiler's command line }
  : String;
begin
  if not ProjectOpen then Exit;
  MakefileForm := TMakefileForm.Create(Self);
  with MakefileForm do
  try
     GetDirectories;
     CheckParams;

     CompilerName.Text := Default_Compiler;
     CompilerFlags := PasParams + UserParams + Directories.All + ' ' + CFlags.Text;

     if ShowModal <> mrOk then Exit;
     CheckParams;

     FSources := '';
     FObjects := '';
     for i := Project.UnitCount - 1 downto 0 do
     begin
       FSources := '"'+Project.Units[i].FileName + '" ' + FSources;
       FObjects := '"'+ChangeFileExt(Project.Units[i].FileName, '.ow') + '" ' + FObjects;
     end;
     FObjects := FObjects + Project.ObjFile;

     if Project.ResFiles <> '' then
        FObjects := FObjects +' "' + ExtractFilePath(Project.FileName) + 'rsrc.res"';

     FCompiler := #9+'$(CC) -c $(SRCS) $(CFLAGS)';

     if Project.IsDll then
        OutputFile := '"' + ExtractFileName(ChangeFileExt(Project.FileName,
          '.dll')) + '"'
     else
        OutputFile := '"' + ExtractFileName(ChangeFileExt(Project.FileName,
          '.exe')) + '"';

     OutputCommand := ExtractRelativePath(Project.FileName, OutputFile);
     while Pos('\', OutputCommand) > 0 do
           OutputCommand[Pos('\', OutputCommand)] := '/';

     FResource := '';
     if Project.ResFiles <> ''
     then begin
        FResource := #9+'windres ';
        If  ThisCompiler <> GPC then FResource := FResource + Directories.Pas;
        FResource := FResource
          + ' -I rc -O coff -i '
          + '"'+GetShortName(Project.ResFiles) + '" -o "'
          + ChangeFileExt(GetShortName(Project.ResFiles),'.o')+ '"'
          + PreprocessorSwitch;
     end;
     
     AssignFile(F, ExtractFilePath(Project.FileName) + 'Makefile');
     Rewrite(F);
     Writeln(F, Format(TheMakefile,
       [Project.Name, CompilerName.Text, CompilerFlags, OutputCommand, FSources,
        FObjects, FCompiler, FLinker, FResource]
     ));
     CloseFile(F);

     if Application.MessageBox('The Makefile has been generated.' + #13#10 +
        'Do you want to view it?', 'Makefile Generated', MB_YESNO +
        MB_ICONQUESTION) = 6 then
        WinExec(PChar('notepad.exe "' + ExtractFilePath(Project.FileName) +
          'Makefile' + '"'), 1);
  finally
     Free;
  end;
end;

procedure TMainForm.BloodshedSoftwarehomepageItemClick(Sender: TObject);
begin
  ExecuteFile('http://www.bloodshed.net','','',SW_SHOW);
end;

procedure TMainForm.MingwcompilerhomepageItemClick(Sender: TObject);
begin
 If ThisCompiler = GPC
    then ExecuteFile('http://www.mingw.org','','',SW_SHOW)
    else ExecuteFile('http://www.freepascal.org','','',SW_SHOW);
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  MdiList.Free;
end;


procedure TMainForm.AddChild(AForm: TEditForm);
begin
  MdiList.Add(AForm);
  WindowMenu.Add(AForm.MenuItem);
end;

procedure TMainForm.RemoveChild(AForm: TEditForm);
begin
  MdiList.Remove(AForm);
end;

procedure TMainForm.RebuildallClick(Sender: TObject);
begin
 if not((ProjectOpen = False) and (MdiChildCount = 0)) then
    Compile(Sender, True);
end;

procedure TMainForm.DateandtimeItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteDateTime;
end;

procedure TMainForm.DateandtimePopItemClick(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteDateTime;
end;

procedure TMainForm.ProjectViewChange(Sender: TObject; Node: TTreeNode);
begin
  ProjectView.AlphaSort;
  ProjectVIew.Update;
end;

procedure TMainForm.ProjectViewExpanded(Sender: TObject; Node: TTreeNode);
begin
  ProjectView.AlphaSort;
  ProjectVIew.Update;
end;

procedure TMainForm.NewresourcefileItemClick(Sender: TObject);
begin
  EditResource(self,'')
end;

procedure TMainForm.NewTemplatefile1Click(Sender: TObject);
begin
  TemplateForm := TTemplateForm.Create(self);
  TemplateForm.Show;
end;

procedure TMainForm.NewAllBtnClick(Sender: TObject);
begin
  NewAllMenu.Popup(NewAllBtn.ClientOrigin.x+NewAllBtn.Width, NewAllBtn.ClientOrigin.y);
end;

procedure TMainForm.FullscreenmodeClick(Sender: TObject);
begin
  if not FullScreenMode.Checked then begin
     Height := Screen.Height;
     Width := Screen.Width;
     Left := 0;
     Top := 0;

     FullScreenMode.Checked := True;
     FullScreenMode.Caption := '&Back to normal mode';
  end
  else begin
     ClientWidth  := IniFile.ReadInteger('Position', 'SizeX', 800);
     ClientHeight := IniFile.ReadInteger('Position', 'SizeY', 600);
     Left         := IniFile.ReadInteger('Position', 'Left', 0);
     Top          := IniFile.ReadInteger('Position', 'Top',  0);

     FullScreenMode.Checked := False;
     FullScreenMode.Caption := '&Full screen mode';
  end;
end;

procedure TMainForm.ExporttoItemClick(Sender: TObject);
begin
  if ProjectOpen then
     ProjecttoHTMLItem.Enabled := True
  else ProjecttoHTMLItem.Enabled := False
end;

procedure TMainForm.ShowCompilerOutput1Click(Sender: TObject);
begin
  ShowCompilerOutput1.Checked := not ShowCompilerOutput1.Checked;
  Showonlywhenneeded1.Checked := not ShowCompilerOutput1.Checked;
  MessageControl.Visible := ShowCompilerOutput1.Checked;
  IniFile.WriteBool('Options', 'Output', ShowCompilerOutput1.Checked);
  IniFile.WriteBool('Options', 'OutputOnlyWhenNeeded', Showonlywhenneeded1.Checked);
end;

procedure TMainForm.Showonlywhenneeded1Click(Sender: TObject);
begin
  Showonlywhenneeded1.Checked := not Showonlywhenneeded1.Checked;
  ShowCompilerOutput1.Checked := not Showonlywhenneeded1.Checked;
  MessageControl.Visible := ShowCompilerOutput1.Checked;
  IniFile.WriteBool('Options', 'OutputOnlyWhenNeeded', Showonlywhenneeded1.Checked);
  IniFile.WriteBool('Options', 'Output', ShowCompilerOutput1.Checked);
end;

procedure TMainForm.Compileroutput1Click(Sender: TObject);
begin
  ShowCompilerOutput1.Checked := IniFile.ReadBool('Options','Output',True);
  Showonlywhenneeded1.Checked := IniFile.ReadBool('Options','OutputOnlyWhenNeeded',False);
end;

procedure TMainForm.PackageManagerItemClick(Sender: TObject);
begin
  ExecuteFile(ExtractFilePath(Application.Exename) + 'PackMan.exe','',ExtractFilePath(Application.Exename), SW_SHOW);
end;

procedure TMainForm.ConfiguretoolsItemClick(Sender: TObject);
begin
  try
    ToolForm := TToolForm.Create(self);
    ToolEditForm := TToolEditForm.Create(self);
    ToolForm.ShowModal;
  finally
    ToolForm.Free;
    ToolEditForm.Free;
  end;
end;

procedure TMainForm.ToolsMenuClick(Sender: TObject);
var Ini : TiniFile;
    i, ToolCount : integer;
    M : TMenuItem;
begin
  Ini := TIniFile.Create(DevPasPath + 'Tools.ini');

  i := ToolsMenu.Count-1;
  if ToolsMenu.Count > ToolMenuItemCount then
     repeat
       ToolsMenu.Remove(ToolsMenu.Items[i]);
       dec(i);
     until ToolsMenu.Count = ToolMenuItemCount;

  ToolCount := Ini.ReadInteger('Tools','Count',0);
  if ToolCount = 0 then
     exit;

  for i := 1 to ToolCount do begin
      M := TMenuItem.Create(MainMenu);
      M.Caption := Ini.ReadString(IntToStr(i),'Title','No title');
      M.Tag := i;
      M.OnClick := OnToolClick;
      ToolsMenu.Add(M);
  end;

  Ini.Free;
end;

function TMainForm.ParseParams(s : string) : string;
var tmp : string;
begin
  if (not NotProject) and ProjectOpen then begin
     if Project.IsDLL then
        tmp := ChangeFileExt(Project.FileName,'.dll')
     else tmp := ChangeFileExt(Project.FileName,'.exe');

     while pos('<EXENAME>', s) <> 0 do begin
           Insert(tmp, s, pos('<EXENAME>',s));
           Delete(s, pos('<EXENAME>', s), length('<EXENAME>'));
     end;

     tmp := Project.FileName;

     while pos('<PROJECTNAME>', s) <> 0 do begin
           Insert(tmp, s, pos('<PROJECTNAME>',s));
           Delete(s, pos('<PROJECTNAME>', s), length('<PROJECTNAME>'));
     end;

     tmp := ExtractFilePath(Project.FileName);

     while pos('<PROJECTPATH>', s) <> 0 do begin
           Insert(tmp, s, pos('<PROJECTPATH>',s));
           Delete(s, pos('<PROJECTPATH>', s), length('<PROJECTPATH>'));
     end;
  end
  else if MdiChildCount > 0 then begin
     tmp := ChangeFileExt((ActiveMdiChild as TEditForm).PathName,'.exe');

     while pos('<EXENAME>', s) <> 0 do begin
           Insert(tmp, s, pos('<EXENAME>',s));
           Delete(s, pos('<EXENAME>', s), length('<EXENAME>'));
     end;

     tmp := (ActiveMdiChild as TEditForm).PathName;

     while pos('<PROJECTNAME>', s) <> 0 do begin
           Insert(tmp, s, pos('<PROJECTNAME>',s));
           Delete(s, pos('<PROJECTNAME>', s), length('<PROJECTNAME>'));
     end;

     tmp := ExtractFilePath((ActiveMdiChild as TEditForm).PathName);

     while pos('<PROJECTPATH>', s) <> 0 do begin
           Insert(tmp, s, pos('<PROJECTPATH>',s));
           Delete(s, pos('<PROJECTPATH>', s), length('<PROJECTPATH>'));
     end;
  end;

  if MdiChildCount > 0 then
     tmp := (ActiveMdiChild as TEditForm).PathName
  else tmp := '';

  while pos('<CURRENTSOURCENAME>', s) <> 0 do begin
        Insert(tmp, s, pos('<CURRENTSOURCENAME>',s));
        Delete(s, pos('<CURRENTSOURCENAME>', s), length('<CURRENTSOURCENAME>'));
  end;

  Result := s;
end;

procedure TMainForm.UpdateIcons(IconType: TIconType);
  procedure UpdateToolbarIcons(Toolbar: TToolbar97);
  var
    i: Integer;
  begin
     for i := 0 to Toolbar.ControlCount - 1 do
     if (Toolbar.Controls[i] is TToolbarButton97) then
        TToolbarButton97(Toolbar.Controls[i]).Images := MainImageList;
  end;
begin
   case IconType of
   itDefault:
      begin
         MainImageList := MenuImages_Default;
         ProjectImageList := ProjectImage_Default;
         IconStyle := isDefault;
      end;
   itGnome:
      begin
         MainImageList := MenuImages_Gnome;
         ProjectImageList := ProjectImage_Gnome;
         IconStyle := isGnome;
      end;
   end;
   MainMenu.Images := MainImageList;
   NewAllMenu.Images := MainImageList;
   UnitPopup.Images := MainImageList;
   ProjectPopup.Images := MainImageList;
   HelpMenu.Images := MainImageList;
   MessageControl.Images := MainImageList;
   ProjectView.Images := ProjectImageList;

   UpdateToolbarIcons(MainToolbar);
   UpdateToolbarIcons(CompileToolbar);
   UpdateToolbarIcons(ProjectToolbar);
   UpdateToolbarIcons(OptToolbar);
   UpdateToolbarIcons(SpecialsBar);
end;

procedure TMainForm.OnToolClick(sender : TObject);
var Ini : TIniFile;
    Params : string;
begin
  Ini := TIniFile.Create(DevPasPath + 'Tools.ini');

  Params := ParseParams(Ini.ReadString(IntToStr((Sender as TMenuItem).Tag), 'Params', ''));

  ExecuteFile(Ini.ReadString(IntToStr((Sender as TMenuItem).Tag), 'Program', ''),
              Params, Ini.ReadString(IntToStr((Sender as TMenuItem).Tag), 'WorkDir', ''), SW_SHOW);

  Ini.Free;
end;

procedure TMainForm.ChangeIconStyleClick(Sender: TObject);
begin
  UpdateIcons(TMenuItem(Sender).Tag);
  TMenuItem(Sender).Checked := True;
  IniFile.WriteInteger('Options', 'IconStyle', TMenuItem(Sender).Tag);
end;

procedure TMainForm.ToolbarIconsStyle1Click(Sender: TObject);
begin
  case IniFile.ReadInteger('Options', 'IconStyle', 0) of
    itDefault : Default1.Checked := True;
    itGnome   : Gnome1.Checked := True;
  end;
end;

procedure TMainForm.Setmainunit1Click(Sender: TObject);
var i : integer;
    tmp : string;
begin
  if ProjectOpen = False then
     Exit;

  ProjIniFile := TIniFile.Create(Project.Filename);

  MainUnitForm := TMainUnitForm.Create(Self);
  with MainUnitForm do begin
    for i := 1 to Project.UnitCount do begin
        if ProjIniFile.ReadString('Unit'+IntToStr(i),'FileName',tmp) <> '' then
          begin
           tmp := ProjIniFile.ReadString('Unit'+IntToStr(i),'FileName',tmp);
           try
             RemoveUnitForm.UnitList.Items.Add(tmp);
           except
             MessageDlg('There is a problem in your project file',MtError,[MbOK],0);
           end;
      end;
    end;

   ShowModal;

   if (ModalResult = MrOK) and (UnitList.ItemIndex = -1) then
      Project.SetMainUnit(Project.Units[UnitList.ItemIndex].FileName);

   UnitList.Items.Clear;
   ProjIniFile.Free;
   end;
end;

procedure TMainForm.Unitbeginend1Click(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteUnitFunction;
end;

procedure TMainForm.Unitbeginend2Click(Sender: TObject);
begin
  (ActiveMdiChild as TEditForm).WriteUnitFunction;
end;

procedure TMainForm.RestoreEditorDesktop;
var
s : string;
i : integer;
begin
  s := '';
  if IniFile.ReadBool('Options','SaveDesktop',False)
  then begin
       If Assigned (Project) then s := Project.FileName
       else if MdiChildCount > 0
       then begin
            for i := 0 to Pred (MdiChildCount) do
            s := s + TEditForm(MdiChildren[i]).PathName+ ',';
       end;
       s := Trim (s);
       i := length (s);
       if i > 0 then if s[i] = ',' then System.Delete (s, i, 1);
  end;

  IniFile.WriteString('History_Open', 'Name', s);
end;

Procedure SetupCompiler;
Var
StartIniFile : TIniFile;
IniFileName : String;
i : integer;
begin

  IniFileName := ExtractFilePath(Application.Exename)
              + ChangeFileExt(ExtractFileName(Application.Exename), '.ini');

  try
    StartIniFile := TIniFile.Create(IniFilename);
    i := StartIniFile.ReadInteger('Compiler', 'CompilerName', 0);
  finally
    StartIniFile.Free;
  end;

  ThisCompiler := Compiler_Support (i);

  Case ThisCompiler of
   GPC :
     begin
        CompilerString := ' (GNU Pascal)';
        CompilerVersion := 'GNU Pascal compiler v2.1';
        Default_Compiler := 'gpc --automake ';
        UnitSwitch       := ' -funit-path=';
        LibSwitch        := ' -B';  // -L
        BinSwitch        := ' -B';
        ConsoleSwitch    := ' -mconsole';
        GUISwitch        := ' -mwindows';
        LinkerSwitch     := ' -Xlinker ';
        PreprocessorSwitch := '';
     end;
   Freepascal :
     begin
        CompilerString := ' (Freepascal)';
        {$IFDEF FULL_VERSION}
        CompilerVersion := 'Free Pascal compiler v1.00';
        {$ELSE}
        CompilerVersion := 'Executable version';
        {$ENDIF}
        Default_Compiler := 'ppc386 ';
        UnitSwitch       := '-Fu';
        LibSwitch        := '-Fl';
        BinSwitch        := ' -FD';
        ConsoleSwitch    := ' -WC';
        GUISwitch        := ' -WG';
        LinkerSwitch     := ' -k';
        PreprocessorSwitch := ' --preprocessor cpp';
     end;
  end; // Case;
  ThisCaption := 'Dev-Pascal ' + DevPasVersion + CompilerString;
end;

procedure TMainForm.GNUPascalhelpitemClick(Sender: TObject);
begin
  ShellExecute (GetDesktopWindow, 'open', pChar (DevPasPath + 'info\gpc.chm'), nil, nil, sw_show);
end;


initialization
  SetupCompiler;
end.

