chmfilewriter.pas 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. { Copyright (C) <2005> <Andrew Haines> chmfilewriter.pas
  2. This library is free software; you can redistribute it and/or modify it
  3. under the terms of the GNU Library General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or (at your
  5. option) any later version.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  8. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  9. for more details.
  10. You should have received a copy of the GNU Library General Public License
  11. along with this library; if not, write to the Free Software Foundation,
  12. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  13. }
  14. {
  15. See the file COPYING.FPC, included in this distribution,
  16. for details about the copyright.
  17. }
  18. unit chmfilewriter;
  19. {$mode objfpc}{$H+}
  20. interface
  21. uses
  22. Classes, SysUtils, chmwriter;
  23. type
  24. TChmProject = class;
  25. TChmProgressCB = procedure (Project: TChmProject; CurrentFile: String) of object;
  26. { TChmProject }
  27. TChmProject = class
  28. private
  29. FWriter: TChmWriter;
  30. FAutoFollowLinks: Boolean;
  31. FDefaultFont: String;
  32. FDefaultPage: String;
  33. FFiles: TStrings;
  34. FIndexFileName: String;
  35. FMakeSearchable: Boolean;
  36. FFileName: String;
  37. FOnProgress: TChmProgressCB;
  38. FOutputFileName: String;
  39. FTableOfContentsFileName: String;
  40. FTitle: String;
  41. protected
  42. function GetData(const DataName: String; out PathInChm: String; out FileName: String; var Stream: TStream): Boolean;
  43. procedure LastFileAdded(Sender: TObject);
  44. public
  45. constructor Create;
  46. destructor Destroy; override;
  47. procedure LoadFromFile(AFileName: String);
  48. procedure SaveToFile(AFileName: String);
  49. procedure WriteChm(AOutStream: TStream);
  50. function ProjectDir: String;
  51. // though stored in the project file, it is only there for the program that uses the unit
  52. // since we actually write to a stream
  53. property OutputFileName: String read FOutputFileName write FOutputFileName;
  54. property FileName: String read FFileName write FFileName;
  55. property Files: TStrings read FFiles write FFiles;
  56. property AutoFollowLinks: Boolean read FAutoFollowLinks write FAutoFollowLinks;
  57. property TableOfContentsFileName: String read FTableOfContentsFileName write FTableOfContentsFileName;
  58. property Title: String read FTitle write FTitle;
  59. property IndexFileName: String read FIndexFileName write FIndexFileName;
  60. property MakeSearchable: Boolean read FMakeSearchable write FMakeSearchable;
  61. property DefaultPage: String read FDefaultPage write FDefaultPage;
  62. property DefaultFont: String read FDefaultFont write FDefaultFont;
  63. property OnProgress: TChmProgressCB read FOnProgress write FOnProgress;
  64. end;
  65. implementation
  66. uses XmlCfg;
  67. { TChmProject }
  68. function TChmProject.GetData(const DataName: String; out PathInChm: String; out
  69. FileName: String; var Stream: TStream): Boolean;
  70. begin
  71. Result := False; // Return true to abort compressing files
  72. TMemoryStream(Stream).LoadFromFile(ProjectDir+DataName);
  73. WriteLn('Reading: ', DataName);
  74. // clean up the filename
  75. FileName := StringReplace(ExtractFileName(DataName), '\', '/', [rfReplaceAll]);
  76. FileName := StringReplace(FileName, '//', '/', [rfReplaceAll]);
  77. PathInChm := '/'+ExtractFilePath(DataName);
  78. if Assigned(FOnProgress) then FOnProgress(Self, DataName);
  79. end;
  80. procedure TChmProject.LastFileAdded(Sender: TObject);
  81. var
  82. IndexStream: TFileStream;
  83. TOCStream: TFileStream;
  84. begin
  85. // Assign the TOC and index files
  86. if (IndexFileName <> '') and FileExists(IndexFileName) then begin
  87. IndexStream := TFileStream.Create(IndexFileName, fmOpenRead);
  88. FWriter.AppendIndex(IndexStream);
  89. IndexStream.Free;
  90. end;
  91. if (TableOfContentsFileName <> '') and FileExists(TableOfContentsFileName) then begin
  92. TOCStream := TFileStream.Create(TableOfContentsFileName, fmOpenRead);
  93. FWriter.AppendTOC(TOCStream);
  94. TOCStream.Free;
  95. end;
  96. end;
  97. constructor TChmProject.Create;
  98. begin
  99. FFiles := TStringList.Create;
  100. end;
  101. destructor TChmProject.Destroy;
  102. begin
  103. FFIles.Free;
  104. inherited Destroy;
  105. end;
  106. procedure TChmProject.LoadFromFile(AFileName: String);
  107. var
  108. Cfg: TXMLConfig;
  109. FileCount: Integer;
  110. I: Integer;
  111. begin
  112. Cfg := TXMLConfig.Create(nil);
  113. Cfg.Filename := AFileName;
  114. FileName := AFileName;
  115. Files.Clear;
  116. FileCount := Cfg.GetValue('Files/Count/Value', 0);
  117. for I := 0 to FileCount-1 do begin
  118. Files.Add(Cfg.GetValue('Files/FileName'+IntToStr(I)+'/Value',''));
  119. end;
  120. IndexFileName := Cfg.GetValue('Files/IndexFile/Value','');
  121. TableOfContentsFileName := Cfg.GetValue('Files/TOCFile/Value','');
  122. AutoFollowLinks := Cfg.GetValue('Settings/AutoFollowLinks/Value', False);
  123. MakeSearchable := Cfg.GetValue('Settings/MakeSearchable/Value', False);
  124. DefaultPage := Cfg.GetValue('Settings/DefaultPage/Value', '');
  125. Title := Cfg.GetValue('Settings/Title/Value', '');
  126. OutputFileName := Cfg.GetValue('Settings/OutputFileName/Value', '');
  127. DefaultFont := Cfg.GetValue('Settings/DefaultFont/Value', '');
  128. Cfg.Free;
  129. end;
  130. procedure TChmProject.SaveToFile(AFileName: String);
  131. var
  132. Cfg: TXMLConfig;
  133. I: Integer;
  134. begin
  135. Cfg := TXMLConfig.Create(nil);
  136. Cfg.StartEmpty := True;
  137. Cfg.Filename := FileName;
  138. Cfg.Clear;
  139. Cfg.SetValue('Files/Count/Value', Files.Count);
  140. for I := 0 to Files.Count-1 do begin
  141. Cfg.SetValue('Files/FileName'+IntToStr(I)+'/Value', Files.Strings[I]);
  142. end;
  143. Cfg.SetValue('Files/IndexFile/Value', IndexFileName);
  144. Cfg.SetValue('Files/TOCFile/Value', TableOfContentsFileName);
  145. Cfg.SetValue('Settings/AutoFollowLinks/Value', AutoFollowLinks);
  146. Cfg.SetValue('Settings/MakeSearchable/Value', MakeSearchable);
  147. Cfg.SetValue('Settings/DefaultPage/Value', DefaultPage);
  148. Cfg.SetValue('Settings/Title/Value', Title);
  149. Cfg.SetValue('Settings/OutputFileName/Value', OutputFileName);
  150. Cfg.SetValue('Settings/DefaultFont/Value', DefaultFont);
  151. Cfg.Free;
  152. end;
  153. function TChmProject.ProjectDir: String;
  154. begin
  155. Result := ExtractFilePath(FileName);
  156. end;
  157. procedure TChmProject.WriteChm(AOutStream: TStream);
  158. var
  159. Writer: TChmWriter;
  160. TOCStream,
  161. IndexStream: TFileStream;
  162. begin
  163. IndexStream := nil;
  164. TOCStream := nil;
  165. Writer := TChmWriter.Create(AOutStream, False);
  166. // our callback to get data
  167. Writer.OnGetFileData := @GetData;
  168. Writer.OnLastFile := @LastFileAdded;
  169. // give it the list of files
  170. Writer.FilesToCompress.AddStrings(Files);
  171. // now some settings in the chm
  172. Writer.DefaultPage := DefaultPage;
  173. Writer.Title := Title;
  174. Writer.DefaultFont := DefaultFont;
  175. Writer.FullTextSearch := MakeSearchable;
  176. // and write!
  177. Writer.Execute;
  178. if Assigned(TOCStream) then TOCStream.Free;
  179. if Assigned(IndexStream) then IndexStream.Free;
  180. end;
  181. end.