mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-07 20:38:11 +02:00
596 lines
16 KiB
ObjectPascal
596 lines
16 KiB
ObjectPascal
unit unit1;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, types, chmsitemap, chmfilewriter,
|
|
Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls, Menus, ExtCtrls, EditBtn,
|
|
LazFileUtils, UTF8Process;
|
|
|
|
type
|
|
|
|
{ TCHMForm }
|
|
|
|
TCHMForm = class(TForm)
|
|
AddFilesBtn: TButton;
|
|
AutoAddLinksBtn: TButton;
|
|
AddAllBtn: TButton;
|
|
CompileViewBtn: TButton;
|
|
CompileBtn: TButton;
|
|
DefaultPageCombo: TComboBox;
|
|
ChmFileNameEdit: TFileNameEdit;
|
|
FollowLinksCheck: TCheckBox;
|
|
CreateSearchableCHMCheck: TCheckBox;
|
|
CompileTimeOptionsLabel: TLabel;
|
|
FilesNoteLabel: TLabel;
|
|
DefaultPageLabel: TLabel;
|
|
CHMFilenameLabel: TLabel;
|
|
OpenDialog2: TOpenDialog;
|
|
RemoveFilesBtn: TButton;
|
|
TOCEditBtn: TButton;
|
|
IndexEditBtn: TButton;
|
|
IndexEdit: TFileNameEdit;
|
|
GroupBox1: TGroupBox;
|
|
FileListBox: TListBox;
|
|
TableOfContentsLabel: TLabel;
|
|
IndexLabel: TLabel;
|
|
MainMenu1: TMainMenu;
|
|
MenuItem1: TMenuItem;
|
|
ProjSaveItem: TMenuItem;
|
|
ProjSaveAsItem: TMenuItem;
|
|
MenuItem12: TMenuItem;
|
|
ProjQuitItem: TMenuItem;
|
|
CompileItem: TMenuItem;
|
|
CompileProjItem: TMenuItem;
|
|
CompileOpenBttn: TMenuItem;
|
|
ProjCloseItem: TMenuItem;
|
|
MenuItem3: TMenuItem;
|
|
HelpHelpItem: TMenuItem;
|
|
MenuItem5: TMenuItem;
|
|
HelpAboutItem: TMenuItem;
|
|
ProjNewItem: TMenuItem;
|
|
ProjOpenItem: TMenuItem;
|
|
MenuItem9: TMenuItem;
|
|
OpenDialog1: TOpenDialog;
|
|
MainPanel: TPanel;
|
|
Panel2: TPanel;
|
|
SaveDialog1: TSaveDialog;
|
|
StatusBar1: TStatusBar;
|
|
TOCEdit: TFileNameEdit;
|
|
procedure AddAllBtnClick(Sender: TObject);
|
|
procedure AddFilesBtnClick(Sender: TObject);
|
|
procedure AutoAddLinksBtnClick(Sender: TObject);
|
|
procedure Button1Click(Sender: TObject);
|
|
procedure Button2Click(Sender: TObject);
|
|
procedure ChmFileNameEditAcceptFileName(Sender: TObject; var Value: String);
|
|
procedure CompileBtnClick(Sender: TObject);
|
|
procedure CompileViewBtnClick(Sender: TObject);
|
|
procedure FileListBoxDrawItem({%H-}Control: TWinControl; Index: Integer;
|
|
ARect: TRect; {%H-}State: TOwnerDrawState);
|
|
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure IndexEditAcceptFileName(Sender: TObject; var Value: String);
|
|
procedure IndexEditBtnClick(Sender: TObject);
|
|
procedure ProjCloseItemClick(Sender: TObject);
|
|
procedure ProjNewItemClick(Sender: TObject);
|
|
procedure ProjOpenItemClick(Sender: TObject);
|
|
procedure ProjQuitItemClick(Sender: TObject);
|
|
procedure ProjSaveAsItemClick(Sender: TObject);
|
|
procedure ProjSaveItemClick(Sender: TObject);
|
|
procedure RemoveFilesBtnClick(Sender: TObject);
|
|
procedure TOCEditAcceptFileName(Sender: TObject; var Value: String);
|
|
procedure TOCEditBtnClick(Sender: TObject);
|
|
private
|
|
FModified: Boolean;
|
|
procedure AddItems({%H-}AParentItem: TTreeNode; {%H-}ChmItems: TChmSiteMapItems);
|
|
|
|
function GetModified: Boolean;
|
|
procedure Save(aAs: Boolean);
|
|
procedure CloseProject;
|
|
|
|
procedure AddFilesToProject(Strings: TStrings);
|
|
procedure InitFileDialog(Dlg: TFileDialog);
|
|
procedure ProjectDirChanged;
|
|
function CreateRelativeProjectFile(Filename: string): string;
|
|
function CreateAbsoluteProjectFile(Filename: string): string;
|
|
public
|
|
Project: TChmProject;
|
|
procedure OpenProject(AFileName: String);
|
|
// Dirty flag: has project been modified since opening?
|
|
property Modified: Boolean read GetModified write FModified;
|
|
end;
|
|
|
|
var
|
|
CHMForm: TCHMForm;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
uses CHMSiteMapEditor, LHelpControl, Process;
|
|
|
|
{ TCHMForm }
|
|
|
|
procedure TCHMForm.AddItems(AParentItem: TTreeNode; ChmItems: TChmSiteMapItems);
|
|
begin
|
|
{ for I := 0 to ChmItems.Count-1 do begin
|
|
Item := TreeView1.Items.AddChild(AParentItem, ChmItems.Item[I].Text);
|
|
AddItems(Item, ChmItems.Item[I].Children);
|
|
end;
|
|
} end;
|
|
|
|
procedure TCHMForm.Button1Click(Sender: TObject);
|
|
begin
|
|
{SiteMap := TChmSiteMap.Create(stTOC);
|
|
OpenDialog1.InitialDir := GetCurrentDir;
|
|
if OpenDialog1.Execute = False then Exit;
|
|
SiteMap.LoadFromFile(OpenDialog1.FileName);
|
|
AddItems(nil, sitemap.Items);
|
|
|
|
Stream := TMemoryStream.Create;
|
|
|
|
Sitemap.SaveToStream(Stream);
|
|
Stream.Position := 0;
|
|
|
|
SynEdit1.Lines.LoadFromStream(Stream);
|
|
Stream.Free;
|
|
}
|
|
end;
|
|
|
|
procedure TCHMForm.AddFilesBtnClick(Sender: TObject);
|
|
begin
|
|
InitFileDialog(OpenDialog2);
|
|
if OpenDialog2.Execute = False then exit;
|
|
Modified := True;
|
|
AddFilesToProject(OpenDialog2.Files);
|
|
end;
|
|
|
|
procedure TCHMForm.AddAllBtnClick(Sender: TObject);
|
|
var
|
|
Files: TStrings;
|
|
procedure AddDir(ADir: String);
|
|
var
|
|
SearchRec: TSearchRec;
|
|
FileName: String;
|
|
begin
|
|
// WriteLn('Adding Dir: ', ADir);
|
|
if FindFirst(ADir+'*', faAnyFile or faDirectory, SearchRec) = 0 then
|
|
begin
|
|
repeat
|
|
if (SearchRec.Attr and faDirectory) <> 0 then
|
|
begin
|
|
if Pos('.', SearchRec.Name) = 0 then
|
|
begin
|
|
AddDir(IncludeTrailingPathDelimiter(ADir+SearchRec.Name));
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
FileName := ADir+SearchRec.Name;
|
|
FileName := ExtractRelativepath(Project.ProjectDir, FileName);
|
|
if Files.IndexOf(FileName) = -1 then
|
|
Files.Add(FileName);
|
|
end;
|
|
until FindNext(SearchRec) <> 0;
|
|
FindClose(SearchRec);
|
|
end;
|
|
end;
|
|
begin
|
|
if MessageDlg('This will add all files in the project directory ' + LineEnding +
|
|
'recursively. Do you want to continue?',
|
|
mtConfirmation, [mbYes, mbNo],0) <> mrYes then exit;
|
|
Modified := True;
|
|
Files := TStringList.Create;
|
|
try
|
|
Files.AddStrings(FileListBox.Items);
|
|
AddDir(Project.ProjectDir);
|
|
FileListBox.Items.Assign(Files);
|
|
finally
|
|
Files.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCHMForm.AutoAddLinksBtnClick(Sender: TObject);
|
|
begin
|
|
Modified := True;
|
|
end;
|
|
|
|
procedure TCHMForm.Button2Click(Sender: TObject);
|
|
begin
|
|
{
|
|
if OpenDialog1.Execute = False then Exit;
|
|
OutStream := TFileStream.Create('/home/andrew/test.chm', fmCreate or fmOpenWrite);
|
|
Chm := TChmWriter.Create(OutStream, False);
|
|
Chm.FilesToCompress.AddStrings(OpenDialog1.Files);
|
|
Chm.GetFileData := @GetData;
|
|
Chm.Title := 'test';
|
|
Chm.DefaultPage := 'index.html';
|
|
Chm.Execute;
|
|
OutStream.Free;
|
|
Chm.Free;
|
|
}
|
|
|
|
|
|
end;
|
|
|
|
procedure TCHMForm.ChmFileNameEditAcceptFileName(Sender: TObject; var Value: String);
|
|
begin
|
|
if ExtractFileExt(Value) = '' then Value := Value+'.chm';
|
|
end;
|
|
|
|
procedure TCHMForm.CompileBtnClick(Sender: TObject);
|
|
var
|
|
OutFile: TFileStream;
|
|
begin
|
|
if ChmFileNameEdit.FileName = '' then
|
|
begin
|
|
MessageDlg('You must set a filename for the output CHM file!', mtError, [mbCancel], 0);
|
|
Exit;
|
|
end;
|
|
Save(False);
|
|
OutFile := TFileStream.Create(Project.OutputFileName, fmCreate or fmOpenWrite);
|
|
try
|
|
Project.WriteChm(OutFile);
|
|
ShowMessage('CHM file '+ChmFileNameEdit.FileName+' was created.');
|
|
finally
|
|
OutFile.Free;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TCHMForm.CompileViewBtnClick(Sender: TObject);
|
|
var
|
|
LHelpName: String;
|
|
LHelpConn: TLHelpConnection;
|
|
Proc: TProcessUTF8;
|
|
ext: String;
|
|
begin
|
|
if ChmFileNameEdit.FileName = '' then
|
|
begin
|
|
MessageDlg('You must set a filename for the output CHM file!', mtError, [mbCancel], 0);
|
|
Exit;
|
|
end;
|
|
CompileBtnClick(Sender);
|
|
// open
|
|
// ...
|
|
ext := ExtractFileExt(Application.ExeName);
|
|
LHelpName := '../../components/chmhelp/lhelp/lhelp' + ext;
|
|
if not FileExists(LHelpName) then
|
|
begin
|
|
if MessageDlg('LHelp could not be located at '+ LHelpName +' Try to build using lazbuild?', mtError, [mbCancel, mbYes], 0) = mrYes then
|
|
begin
|
|
if not FileExists('../../lazbuild' + ext) then
|
|
begin
|
|
MessageDlg('lazbuild coul not be found.', mtError, [mbCancel], 0);
|
|
Exit;
|
|
end;
|
|
Proc := TProcessUTF8.Create(Self);
|
|
Proc.CommandLine := '../../../lazbuild ./lhelp.lpi';
|
|
SetCurrentDir('../../components/chmhelp/lhelp/');
|
|
Proc.Options := [poWaitOnExit];
|
|
Proc.Execute;
|
|
SetCurrentDir('../../../tools/chmmaker/');
|
|
if Proc.ExitStatus <> 0 then
|
|
begin
|
|
MessageDlg('lhelp failed to build', mtError, [mbCancel], 0);
|
|
Exit;
|
|
end;
|
|
Proc.Free;
|
|
end
|
|
else
|
|
Exit;
|
|
end;
|
|
LHelpConn := TLHelpConnection.Create;
|
|
try
|
|
LHelpConn.StartHelpServer('chmmaker', LHelpName);
|
|
LHelpConn.OpenFile(ChmFileNameEdit.FileName);
|
|
finally
|
|
LHelpConn.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCHMForm.FileListBoxDrawItem(Control: TWinControl; Index: Integer;
|
|
ARect: TRect; State: TOwnerDrawState);
|
|
begin
|
|
FileListbox.Canvas.FillRect(ARect);
|
|
if Pos('..', FileListBox.Items.Strings[Index]) > 0 then
|
|
begin
|
|
// These items won't be added to the chm because they are not within the project dir
|
|
// so mark them with a red rectangle
|
|
Dec(ARect.Right);
|
|
Dec(ARect.Bottom);
|
|
FileListBox.Canvas.Pen.Color := clRed;
|
|
FileListBox.Canvas.Frame(ARect);
|
|
end;
|
|
// Draw item text
|
|
FileListBox.Canvas.TextRect(ARect,
|
|
2, (ARect.Top + ARect.Bottom - FileListbox.Canvas.TextHeight('Tg')) div 2,
|
|
FileListBox.Items[Index]
|
|
);
|
|
end;
|
|
|
|
procedure TCHMForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
|
|
var
|
|
MResult: Integer;
|
|
begin
|
|
if Modified then
|
|
begin
|
|
MResult := MessageDlg('Project is modified would you like to save the changes?', mtConfirmation,
|
|
[mbYes, mbNo, mbCancel], 0);
|
|
case MResult of
|
|
mrYes: Save(False);
|
|
mrNo: CloseAction := caFree;
|
|
mrCancel: CloseAction := caNone;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCHMForm.FormCreate(Sender: TObject);
|
|
begin
|
|
CloseProject;
|
|
end;
|
|
|
|
procedure TCHMForm.FormDestroy(Sender: TObject);
|
|
begin
|
|
CloseProject;
|
|
end;
|
|
|
|
procedure TCHMForm.IndexEditAcceptFileName(Sender: TObject; var Value: String);
|
|
begin
|
|
Modified := True;
|
|
//Value := ExtractRelativepath(Project.ProjectDir, Value);
|
|
//WriteLn(Value);
|
|
Project.IndexFileName := Value;
|
|
end;
|
|
|
|
procedure TCHMForm.IndexEditBtnClick(Sender: TObject);
|
|
var
|
|
Stream: TStream;
|
|
FileName: String;
|
|
begin
|
|
FileName := IndexEdit.FileName;
|
|
if FileName = '' then
|
|
begin
|
|
FileName := Project.ProjectDir+'_index.hhk'
|
|
end;
|
|
|
|
if FileExists(FileName) then
|
|
begin
|
|
Stream := TFileStream.Create(FileName, fmOpenReadWrite);
|
|
end
|
|
else
|
|
begin
|
|
Stream := TFileStream.Create(FileName, fmCreate or fmOpenReadWrite);
|
|
end;
|
|
|
|
try
|
|
if SitemapEditForm.Execute(Stream, stIndex, FileListBox.Items) then IndexEdit.FileName := FileName;
|
|
finally
|
|
Stream.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCHMForm.ProjCloseItemClick(Sender: TObject);
|
|
begin
|
|
CloseProject;
|
|
end;
|
|
|
|
procedure TCHMForm.ProjNewItemClick(Sender: TObject);
|
|
begin
|
|
InitFileDialog(SaveDialog1);
|
|
If SaveDialog1.Execute then
|
|
begin
|
|
if FileExists(SaveDialog1.FileName)
|
|
and (MessageDlg('File Already Exists! Ovewrite?', mtWarning, [mbYes, mbNo],0) <> mrYes) then Exit;
|
|
OpenProject(SaveDialog1.FileName);
|
|
Project.SaveToFile(SaveDialog1.FileName);
|
|
end;
|
|
end;
|
|
|
|
procedure TCHMForm.ProjOpenItemClick(Sender: TObject);
|
|
begin
|
|
InitFileDialog(OpenDialog1);
|
|
if OpenDialog1.Execute then
|
|
begin
|
|
CloseProject;
|
|
OpenProject(OpenDialog1.FileName);
|
|
end;
|
|
end;
|
|
|
|
procedure TCHMForm.ProjQuitItemClick(Sender: TObject);
|
|
begin
|
|
Close;
|
|
end;
|
|
|
|
procedure TCHMForm.ProjSaveAsItemClick(Sender: TObject);
|
|
begin
|
|
Save(True);
|
|
end;
|
|
|
|
procedure TCHMForm.ProjSaveItemClick(Sender: TObject);
|
|
begin
|
|
Save(False);
|
|
end;
|
|
|
|
procedure TCHMForm.RemoveFilesBtnClick(Sender: TObject);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Modified := True;
|
|
for I := FileListBox.Items.Count-1 downto 0 do
|
|
if FileListBox.Selected[I] then FileListBox.Items.Delete(I);
|
|
DefaultPageCombo.Items.Assign(FileListBox.Items);
|
|
end;
|
|
|
|
procedure TCHMForm.TOCEditAcceptFileName(Sender: TObject; var Value: String);
|
|
begin
|
|
Modified := True;
|
|
Project.TableOfContentsFileName := Value;
|
|
end;
|
|
|
|
procedure TCHMForm.TOCEditBtnClick(Sender: TObject);
|
|
var
|
|
Stream: TStream;
|
|
FileName: String;
|
|
BDir: String;
|
|
begin
|
|
FileName := TOCEdit.FileName;
|
|
if FileName = '' then
|
|
begin
|
|
FileName := Project.ProjectDir+'_table_of_contents.hhc'
|
|
end;
|
|
|
|
if FileExists(FileName) then
|
|
begin
|
|
Stream := TFileStream.Create(FileName, fmOpenReadWrite);
|
|
end
|
|
else
|
|
begin
|
|
Stream := TFileStream.Create(FileName, fmCreate or fmOpenReadWrite);
|
|
end;
|
|
|
|
try
|
|
BDir := ExtractFilePath(Project.FileName);
|
|
FileName := ExtractRelativepath(BDir, FileName);
|
|
if SitemapEditForm.Execute(Stream, stTOC, FileListBox.Items) then TOCEdit.FileName := FileName;
|
|
finally
|
|
Stream.Free;
|
|
end;
|
|
end;
|
|
|
|
function TCHMForm.GetModified: Boolean;
|
|
begin
|
|
Result := (Project <> nil) and FModified;
|
|
end;
|
|
|
|
procedure TCHMForm.Save(aAs: Boolean);
|
|
begin
|
|
if aAs or (Project.FileName = '') then
|
|
begin
|
|
InitFileDialog(SaveDialog1);
|
|
if SaveDialog1.Execute then
|
|
begin
|
|
Project.FileName := ChangeFileExt(SaveDialog1.FileName,'.hfp');
|
|
ProjectDirChanged;
|
|
end;
|
|
end;
|
|
Project.Files.Assign(FileListBox.Items);
|
|
Project.TableOfContentsFileName := CreateRelativeProjectFile(TOCEdit.FileName);
|
|
Project.IndexFileName := CreateRelativeProjectFile(IndexEdit.FileName);
|
|
Project.DefaultPage := DefaultPageCombo.Text;
|
|
Project.AutoFollowLinks := FollowLinksCheck.Checked;
|
|
Project.MakeSearchable := CreateSearchableCHMCheck.Checked;
|
|
Project.OutputFileName := CreateRelativeProjectFile(ChmFileNameEdit.FileName);
|
|
|
|
Project.SaveToFile(Project.FileName);
|
|
Modified := False;
|
|
end;
|
|
|
|
procedure TCHMForm.CloseProject;
|
|
begin
|
|
FileListBox.Clear;
|
|
DefaultPageCombo.Clear;
|
|
TOCEdit.Clear;
|
|
IndexEdit.Clear;
|
|
GroupBox1.Enabled := False;
|
|
MainPanel.Enabled := False;
|
|
CompileItem.Enabled := False;
|
|
ProjSaveAsItem.Enabled := False;
|
|
ProjSaveItem.Enabled := False;
|
|
ProjCloseItem.Enabled := False;
|
|
|
|
FollowLinksCheck.Checked := False;
|
|
CreateSearchableCHMCheck.Checked := False;
|
|
FreeAndNil(Project);
|
|
end;
|
|
|
|
procedure TCHMForm.OpenProject(AFileName: String);
|
|
begin
|
|
if not Assigned(Project) then Project := TChmProject.Create;
|
|
Project.LoadFromFile(AFileName);
|
|
GroupBox1.Enabled := True;
|
|
MainPanel.Enabled := True;
|
|
CompileItem.Enabled := True;
|
|
ProjSaveAsItem.Enabled := True;
|
|
ProjSaveItem.Enabled := True;
|
|
ProjCloseItem.Enabled := True;
|
|
|
|
FileListBox.Items.AddStrings(Project.Files);
|
|
TOCEdit.FileName := Project.TableOfContentsFileName;
|
|
IndexEdit.FileName := Project.IndexFileName;
|
|
DefaultPageCombo.Items.Assign(FileListBox.Items);
|
|
DefaultPageCombo.Text := Project.DefaultPage;
|
|
FollowLinksCheck.Checked := Project.AutoFollowLinks;
|
|
CreateSearchableCHMCheck.Checked := Project.MakeSearchable;
|
|
ChmFileNameEdit.FileName := Project.OutputFileName;
|
|
|
|
ProjectDirChanged;
|
|
end;
|
|
|
|
procedure TCHMForm.AddFilesToProject(Strings: TStrings);
|
|
var
|
|
BDir: String;
|
|
I: Integer;
|
|
RelativePath: String;
|
|
FileName: String;
|
|
begin
|
|
Modified := True;
|
|
BDir := ExtractFilePath(Project.FileName);
|
|
|
|
for I := 0 to Strings.Count-1 do begin
|
|
FileName := Strings.Strings[I];
|
|
|
|
RelativePath := ExtractRelativepath(BDir, FileName);
|
|
if Pos('..', RelativePath) > 0 then
|
|
FileListBox.Items.AddObject(RelativePath, TObject(1))
|
|
else
|
|
FileListBox.Items.AddObject(RelativePath, TObject(0));
|
|
end;
|
|
DefaultPageCombo.Items.Assign(FileListBox.Items);
|
|
end;
|
|
|
|
procedure TCHMForm.InitFileDialog(Dlg: TFileDialog);
|
|
var
|
|
Dir: String;
|
|
begin
|
|
Dir:='';
|
|
if (Project<>nil) then
|
|
Dir:=ExtractFilePath(Project.FileName);
|
|
if not DirPathExists(Dir) then
|
|
Dir:=GetCurrentDirUTF8;
|
|
Dlg.InitialDir:=Dir;
|
|
end;
|
|
|
|
procedure TCHMForm.ProjectDirChanged;
|
|
var
|
|
Dir: String;
|
|
begin
|
|
if Project=nil then exit;
|
|
Dir:=ExtractFilePath(Project.FileName);
|
|
|
|
TOCEdit.InitialDir:=Dir;
|
|
IndexEdit.InitialDir:=Dir;
|
|
ChmFileNameEdit.InitialDir:=Dir;
|
|
end;
|
|
|
|
function TCHMForm.CreateRelativeProjectFile(Filename: string): string;
|
|
begin
|
|
Result:=Filename;
|
|
if (Project=nil) or (not FilenameIsAbsolute(Project.FileName)) then exit;
|
|
Result:=CreateRelativePath(Filename,ExtractFilePath(Project.FileName));
|
|
end;
|
|
|
|
function TCHMForm.CreateAbsoluteProjectFile(Filename: string): string;
|
|
begin
|
|
Result:=Filename;
|
|
if FilenameIsAbsolute(Result) then exit;
|
|
if (Project=nil) or (not FilenameIsAbsolute(Project.FileName)) then exit;
|
|
Result:=ExtractFilePath(Project.FileName)+Filename;
|
|
end;
|
|
|
|
end.
|
|
|