Browse Source

* initial hhp loading in chmproject.
* chmproject now supports #Windows (the CHM feature, not the OS), but doesn't pass it to writer yet.
* Some keys in chmproject moved from files/ to settings/ were they belong.
hopefully with backwards compat loading capability.

Low errorchecking etc, and only initially tested. Not for 2.4.2

git-svn-id: trunk@15444 -

marco 15 years ago
parent
commit
b2ad17dd2a
2 changed files with 543 additions and 12 deletions
  1. 370 10
      packages/chm/src/chmfilewriter.pas
  2. 173 2
      packages/chm/src/chmtypes.pas

+ 370 - 10
packages/chm/src/chmfilewriter.pas

@@ -25,7 +25,7 @@ unit chmfilewriter;
 interface
 
 uses
-  Classes, SysUtils, chmwriter;
+  Classes, SysUtils, chmwriter, inifiles, contnrs;
 
 type
   TChmProject = class;
@@ -49,13 +49,18 @@ type
     FOutputFileName: String;
     FTableOfContentsFileName: String;
     FTitle: String;
+    FWindows : TObjectList;
+    FMergeFiles : TStringlist;
+    fDefaultWindow : string;
   protected
     function GetData(const DataName: String; out PathInChm: String; out FileName: String; var Stream: TStream): Boolean;
     procedure LastFileAdded(Sender: TObject);
+    procedure readIniOptions(keyvaluepairs:tstringlist);
   public
     constructor Create; virtual;
     destructor Destroy; override;
     procedure LoadFromFile(AFileName: String); virtual;
+    procedure LoadFromhhp (AFileName:String;LeaveInclude:Boolean); virtual;
     procedure SaveToFile(AFileName: String); virtual;
     procedure WriteChm(AOutStream: TStream); virtual;
     function ProjectDir: String;
@@ -74,8 +79,10 @@ type
     property MakeSearchable: Boolean read FMakeSearchable write FMakeSearchable;
     property DefaultPage: String read FDefaultPage write FDefaultPage;
     property DefaultFont: String read FDefaultFont write FDefaultFont;
-
+    property Windows :TObjectList read FWindows write FWindows;
+    property MergeFiles :TStringlist read FMergeFiles write FMergefiles;
     property OnProgress: TChmProgressCB read FOnProgress write FOnProgress;
+    property DefaultWindow : String read FDefaultWindow write FDefaultWindow;
   end;
 
   TChmContextNode = Class
@@ -86,7 +93,7 @@ type
 
 implementation
 
-uses XmlCfg, chmsitemap;
+uses XmlCfg, chmsitemap, CHMTypes;
 
 { TChmProject }
 
@@ -153,6 +160,8 @@ end;
 constructor TChmProject.Create;
 begin
   FFiles := TStringList.Create;
+  FWindows:=TObjectList.Create(True);
+  FMergeFiles:=TStringlist.Create;
 end;
 
 destructor TChmProject.Destroy;
@@ -160,16 +169,111 @@ var i : integer;
 begin
   for i:=0 to ffiles.count -1 do
     ffiles.objects[i].free;
+  FMergeFiles.Free;
   FFiles.Free;
+  FWindows.Free;
   inherited Destroy;
 end;
 
+
+Type
+   TSectionEnum = (secOptions,secWindows,secFiles,secMergeFiles,secAlias,secMap,secInfoTypes,secTextPopups,secUnknown);
+   TOptionEnum = (OPTAUTO_INDEX,OPTAUTO_TOC,OPTBINARY_INDEX,OPTBINARY_TOC,OPTCITATION,
+       OPTCOMPRESS,OPTCOPYRIGHT,OPTCOMPATIBILITY,OPTCOMPILED_FILE,OPTCONTENTS_FILE,
+       OPTCREATE_CHI_FILE,OPTDBCS,OPTDEFAULT_FONT,OPTDEFAULT_WINDOW,OPTDEFAULT_TOPIC,
+       OPTDISPLAY_COMPILE_NOTES,OPTDISPLAY_COMPILE_PROGRESS,OPTENHANCED_DECOMPILATION,OPTERROR_LOG_FILE,OPTFLAT,
+       OPTFULL_TEXT_SEARCH_STOP_LIST,OPTFULL_TEXT_SEARCH,OPTIGNORE,OPTINDEX_FILE,OPTLANGUAGE,OPTPREFIX,
+       OPTSAMPLE_STAGING_PATH,OPTSAMPLE_LIST_FILE,OPTTMPDIR,OPTTITLE,OPTCUSTOM_TAB,OPTUNKNOWN);
+
+Const
+  SectionNames : Array[TSectionEnum] of String =
+      ('OPTIONS','WINDOWS','FILES','MERGE FILES','ALIAS','MAP','INFOTYPES','TEXT POPUPS','UNKNOWN');
+
+  OptionKeys : array [TOptionEnum] of String =
+      ('AUTO INDEX','AUTO TOC','BINARY INDEX','BINARY TOC','CITATION',
+       'COMPRESS','COPYRIGHT','COMPATIBILITY','COMPILED FILE','CONTENTS FILE',
+       'CREATE CHI FILE','DBCS','DEFAULT FONT','DEFAULT WINDOW','DEFAULT TOPIC',
+       'DISPLAY COMPILE NOTES','DISPLAY COMPILE PROGRESS','ENHANCED DECOMPILATION','ERROR LOG FILE','FLAT',
+       'FULL-TEXT SEARCH STOP LIST','FULL TEXT SEARCH','IGNORE','INDEX FILE','LANGUAGE','PREFIX',
+       'SAMPLE STAGING PATH','SAMPLE LIST FILE','TMPDIR','TITLE','CUSTOM TAB','UNKNOWN');
+
+
+
+function FindSectionName (const name:string):TSectionEnum;
+
+begin
+  result:=low(TSectionEnum);
+  while (result<secUnknown) and (name<>SectionNames[Result]) do
+    inc(result);
+end;
+
+function FindOptionName(Const name:string):TOptionEnum;
+
+begin
+  result:=low(TOptionEnum);
+  while (result<optUnknown) and (name<>OptionKeys[Result]) do
+    inc(result);
+end;
+
+procedure TChmProject.readIniOptions(keyvaluepairs:tstringlist);
+var i : integer;
+    Opt : TOptionEnum;
+    OptVal,
+    OptValUpper : string;
+begin
+  for i:=0 to keyvaluepairs.count-1 do
+    begin
+      Opt:=findoptionname(uppercase(keyvaluepairs.names[i]));
+      optval :=keyvaluepairs.valuefromindex[i];
+      optvalupper:=uppercase(OptVal);
+      case Opt Of
+      OPTAUTO_INDEX                : ;
+      OPTAUTO_TOC                  : ;
+      OPTBINARY_INDEX              : MakeBinaryIndex:=optvalupper='YES';
+      OPTBINARY_TOC                : MakeBinaryToc  :=optvalupper='YES';
+      OPTCITATION                  : ;
+      OPTCOMPRESS                  : ; // Doesn't seem to have effect in workshop
+      OPTCOPYRIGHT                 : ;
+      OPTCOMPATIBILITY             : ;
+      OPTCOMPILED_FILE             : OutputFilename:=optval;
+      OPTCONTENTS_FILE             : TableOfContentsFileName:=optval;
+      OPTCREATE_CHI_FILE           : ;
+      OPTDBCS                      : ; // What this field makes unicode is not known?
+      OPTDEFAULT_FONT              : defaultfont:=optval;
+      OPTDEFAULT_WINDOW            : defaultwindow:=optval;
+      OPTDEFAULT_TOPIC             : defaultpage:=optval;
+      OPTDISPLAY_COMPILE_NOTES     : ;
+      OPTDISPLAY_COMPILE_PROGRESS  : ;
+      OPTENHANCED_DECOMPILATION    : ;
+      OPTERROR_LOG_FILE            : ;
+      OPTFLAT                      : ;
+      OPTFULL_TEXT_SEARCH_STOP_LIST: ;
+      OPTIGNORE                    : ;
+      OPTINDEX_FILE                : Indexfilename:=optval;
+      OPTLANGUAGE                  : ;
+      OPTPREFIX                    : ;  // doesn't seem to have effect
+      OPTSAMPLE_STAGING_PATH       : ;
+      OPTSAMPLE_LIST_FILE          : ;
+      OPTTMPDIR                    : ;
+      OPTTITLE                     : Title:=optval;
+      OPTCUSTOM_TAB                : ;
+      OPTUNKNOWN                   : ;  // can be used for errors on unknown keys
+      end;
+    end;
+end;
+
+
 procedure TChmProject.LoadFromFile(AFileName: String);
 var
   Cfg: TXMLConfig;
+  MergeFileCount,
+  WinCount,
   FileCount: Integer;
   I  : Integer;
   nd : TChmContextNode;
+  win: TCHMWindow;
+  s  : String;
+
 begin
   Cfg := TXMLConfig.Create(nil);
   Cfg.Filename := AFileName;
@@ -185,20 +289,257 @@ begin
       nd.contextname:=Cfg.GetValue('Files/FileName'+IntToStr(I)+'/ContextName','');
       Files.AddObject(nd.urlname,nd);
     end;
+
+  WinCount:= Cfg.GetValue('Windows/Count/Value', 0);
+  for i:=0 To WinCount-1 do
+    begin
+      win:=TCHMWindow.Create;
+      win.loadfromxml(cfg,'Windows/item'+inttostr(i)+'/');
+      fwindows.add(win);
+    end;
+
+  Mergefilecount:=Cfg.getValue('MergeFiles/Count/Value', 0);
+  for i:=0 To MergeFileCount-1 do
+    Mergefiles.add(Cfg.getValue('MergeFiles/FileName'+IntToStr(I)+'/value',''));
+
+  // load some values that changed key backwards compatible.
+
   IndexFileName := Cfg.GetValue('Files/IndexFile/Value','');
+  if IndexFileName='' Then
+    IndexFileName := Cfg.GetValue('Settings/IndexFile/Value','');
+
   TableOfContentsFileName := Cfg.GetValue('Files/TOCFile/Value','');
+  If TableOfContentsFileName='' then
+    TableOfContentsFileName := Cfg.GetValue('Settings/TOCFile/Value','');
+
   // For chm file merging, bintoc must be false and binindex true. Change defaults in time?
-  MakeBinaryTOC := Cfg.GetValue('Files/MakeBinaryTOC/Value', True);
-  MakeBinaryIndex:= Cfg.GetValue('Files/MakeBinaryIndex/Value', False);
+  // OTOH, merging will be mostly done for fpdoc files, and that doesn't care about defaults.
+
+  S:=Cfg.GetValue('Files/MakeBinaryTOC/Value', '');
+  if s='' Then
+    MakeBinaryTOC := Cfg.GetValue('Settings/MakeBinaryTOC/Value', True)
+  else
+    MakeBinaryTOC := Cfg.GetValue('Files/MakeBinaryTOC/Value', True);
+
+  S:=Cfg.GetValue('Files/MakeBinaryIndex/Value', '');
+  if s='' Then
+    MakeBinaryIndex := Cfg.GetValue('Settings/MakeBinaryIndex/Value', False)
+  else
+    MakeBinaryIndex := Cfg.GetValue('Files/MakeBinaryIndex/Value', False);
+
   AutoFollowLinks := Cfg.GetValue('Settings/AutoFollowLinks/Value', False);
   MakeSearchable := Cfg.GetValue('Settings/MakeSearchable/Value', False);
   DefaultPage := Cfg.GetValue('Settings/DefaultPage/Value', '');
   Title := Cfg.GetValue('Settings/Title/Value', '');
   OutputFileName := Cfg.GetValue('Settings/OutputFileName/Value', '');
-  DefaultFont := Cfg.GetValue('Settings/DefaultFont/Value', '');
+  DefaultFont  := Cfg.GetValue('Settings/DefaultFont/Value', '');
+  DefaultWindow:= Cfg.GetValue('Settings/DefaultWindow/Value', '');
   Cfg.Free;
 end;
 
+function cleanupstring(const s:string):string;
+var
+  i:integer;
+begin
+  i:=pos(';',s);
+  if i>0 then
+    result:=trim(copy(s,1,i-1))
+  else
+    result:=trim(s);
+end;
+
+procedure TChmProject.LoadFromhhp (AFileName:String;LeaveInclude:Boolean);
+// leaveinclude=true leaves includefiles includefiles.
+
+procedure addalias(const key,value :string);
+
+var i,j : integer;
+    node: TCHMContextNode;
+    keyupper : string;
+begin
+ {$ifdef hhp_debug}
+   writeln('alias entry:',key,'=',value);
+ {$endif}
+ keyupper:=uppercase(value);
+ i:=0; j:=files.count;
+ while (i<j) and (uppercase(TCHMContextnode(files.objects[i]).UrlName)<>keyupper) do
+  inc(i);
+ if i=j then
+  begin
+   {$ifdef hhp_debug}
+    writeln('alias new node:',key);
+   {$endif}
+    node:=TCHMContextNode.create;
+    node.URLName:=value;
+    node.contextname:=key;
+  end
+ else
+  begin
+    node:=TCHMContextNode(Files.objects[i]);
+    node.ContextName:=key;
+  end;
+end;
+
+procedure processalias(strs:TStringlist);
+var i,j : integer;
+    s : string;
+    strls2:tstringlist;
+
+begin
+ for i:=0 to strs.count-1 do
+  begin
+    s:=cleanupstring(strs[i]);
+    if uppercase(copy(s,1,8))='#INCLUDE' then
+      begin
+        delete(s,1,8);
+        s:=trim(s);
+        if fileexists(s) then
+          begin
+            strls2:=TstringList.create;
+            strls2.loadfromfile(s);
+            processalias(strls2);
+            strls2.free;
+          end;
+
+      end
+    else
+     begin
+       s:=cleanupstring(s);
+       j:=pos('=',s);
+       if j>0 then
+         addalias(trim(copy(s,1,j-1)),copy(s,j+1,length(s)-j));
+     end;
+  end;
+end;
+
+procedure addmap(const key,value :string);
+
+var i,j : integer;
+    node: TCHMContextNode;
+    keyupper : string;
+begin
+ {$ifdef hhp_debug}
+ writeln('map entry:',key,'=',value);
+ {$endif}
+ keyupper:=uppercase(key);
+ i:=0; j:=files.count;
+ while (i<j) and (uppercase(TCHMContextnode(files.objects[i]).contextname)<>keyupper) do
+  inc(i);
+ if i=j then
+    raise Exception.create('context "'+key+'" not found!')
+ else
+  begin
+    node:=TCHMContextNode(Files.objects[i]);
+    node.Contextnumber:=strtointdef(value,0);
+  end;
+end;
+
+procedure processmap(strs:TStringlist);
+var i,j : integer;
+    s : string;
+    strls2:tstringlist;
+
+begin
+ for i:=0 to strs.count-1 do
+  begin
+    s:=cleanupstring(strs[i]);
+    {$ifdef hhp_debug}
+      writeln('map item:',s);
+    {$endif}
+    if uppercase(copy(s,1,8))='#INCLUDE' then
+      begin
+        delete(s,1,8);
+        s:=trim(s);
+        if fileexists(s) then
+          begin
+            strls2:=TstringList.create;
+            strls2.loadfromfile(s);
+            processmap(strls2);
+            strls2.free;
+          end;
+      end
+    else
+     begin
+       s:=cleanupstring(s);
+       if uppercase(copy(s,1,7))='#DEFINE' Then
+         begin
+           delete(s,1,7);
+           s:=trim(s);
+           j:=pos(' ',s);
+           if j>0 then
+             addmap(trim(copy(s,1,j-1)),copy(s,j+1,length(s)-j));
+         end
+       else
+         begin
+            {$ifdef hhp_debug}
+              writeln('map leftover:',s);
+            {$endif}
+         end;
+     end;
+  end;
+end;
+
+var
+  Fini      : TMemIniFile;  // TMemInifile is more compatible with Delphi. Delphi's API based TIniFile fails on .hhp files.
+  secs,strs : TStringList;
+  i,j       : Integer;
+  section   : TSectionEnum;
+  nd        : TChmContextNode;
+
+begin
+  Fini:=TMeminiFile.Create(AFileName);
+  secs := TStringList.create;
+  strs := TStringList.create;
+  fini.readsections(secs);
+
+  // Do the files section first so that we can emit errors if
+  // other sections reference unknown files.
+
+  fini.readsectionvalues(SectionNames[secFiles] ,strs);
+  if strs.count>0 then
+    for j:=0 to strs.count-1 do
+      begin
+          nd:=TChmContextNode.Create;
+          nd.urlname:=strs[j];
+          nd.contextnumber:=0;
+          nd.contextname:='';
+          Files.AddObject(nd.urlname,nd);
+        end;
+
+  // aliases also add file nodes.
+
+  fini.readsectionvalues(SectionNames[secAlias] ,strs); // resolve all aliases.
+  if strs.count>0 then
+    processalias(strs);
+
+  // map files only add to existing file nodes.
+  fini.readsectionvalues(SectionNames[secmap] ,strs);
+  if strs.count>0 then
+    processmap(strs);
+
+
+  for i:=0 to secs.count-1 do
+    begin
+      section:=FindSectionName(Uppercase(Secs[i]));
+      if section<>secunknown then
+        fini.readsectionvalues(secs[i] ,strs);
+      case section of
+      secOptions   : readinioptions(strs);
+      secWindows   : for j:=0 to strs.count-1 do
+                       FWindows.add(TCHMWindow.Create(strs[j]));
+      secFiles     : ; // already done
+      secMergeFiles: FMergeFiles.Assign(Strs); // just a filelist
+      secAlias     : ; // already done
+      secMap       : ; // already done
+      secInfoTypes : ; // unused for now.
+      secTextPopups: ; // rarely used.
+      end;
+    end;
+  secs.free;
+  strs.free;
+  fini.free;
+end;
+
 procedure TChmProject.AddFileWithContext(contextid:integer;filename:ansistring;contextname:ansistring='');
 var x : integer;
     nd : TChmContextNode;
@@ -247,16 +588,35 @@ begin
         Cfg.SetValue('Files/FileName'+IntToStr(I)+'/ContextName', nd.contextname);
       end;
   end;
-  Cfg.SetValue('Files/IndexFile/Value', IndexFileName);
-  Cfg.SetValue('Files/TOCFile/Value', TableOfContentsFileName);
-  Cfg.SetValue('Files/MakeBinaryTOC/Value',MakeBinaryTOC);
-  Cfg.SetValue('Files/MakeBinaryIndex/Value',MakeBinaryIndex);
+
+  Cfg.SetValue('Windows/Count/Value', FWindows.count);
+  for i:=0 To FWindows.Count-1 do
+    TCHMWindow(FWindows[i]).savetoxml(cfg,'Windows/item'+inttostr(i)+'/');
+
+  Cfg.SetValue('MergeFiles/Count/Value', FMergeFiles.count);
+  for i:=0 To FMergeFiles.Count-1 do
+    Cfg.SetValue('MergeFiles/FileName'+IntToStr(I)+'/value',FMergeFiles[i]);
+
+  // delete legacy keys.
+  Cfg.SetValue('Files/IndexFile/Value','');
+  Cfg.SetValue('Files/TOCFile/Value', '');
+  Cfg.SetValue('Files/MakeBinaryTOC/Value','');
+  Cfg.SetValue('Files/MakeBinaryIndex/Value','');
+  Cfg.SetValue('Settings/IndexFile/Value', IndexFileName);
+  Cfg.SetValue('Settings/TOCFile/Value', TableOfContentsFileName);
+  Cfg.SetValue('Settings/MakeBinaryTOC/Value',MakeBinaryTOC);
+  Cfg.SetValue('Settings/MakeBinaryIndex/Value',MakeBinaryIndex);
+
   Cfg.SetValue('Settings/AutoFollowLinks/Value', AutoFollowLinks);
   Cfg.SetValue('Settings/MakeSearchable/Value', MakeSearchable);
   Cfg.SetValue('Settings/DefaultPage/Value', DefaultPage);
   Cfg.SetValue('Settings/Title/Value', Title);
   Cfg.SetValue('Settings/OutputFileName/Value', OutputFileName);
   Cfg.SetValue('Settings/DefaultFont/Value', DefaultFont);
+
+  Cfg.SetValue('Settings/DefaultWindow/Value', DefaultWindow);
+
+
   Cfg.Flush;
   Cfg.Free;
 end;

+ 173 - 2
packages/chm/src/chmtypes.pas

@@ -25,7 +25,7 @@ unit chmtypes;
 interface
 
 uses
-  Classes, SysUtils;
+  Classes, SysUtils,xmlcfg;
 
 type
   TSectionName = (snMSCompressed, snUnCompressed);
@@ -91,6 +91,38 @@ type
 
   end;
 
+  TCHMWindow = Class
+                window_type,
+                Title_bar_text,
+                Toc_file,
+                index_file,
+                Default_File,
+                Home_button_file,
+                Jumpbutton_1_File,
+                Jumpbutton_1_Text,
+                Jumpbutton_2_File,
+                Jumpbutton_2_Text : string;
+                nav_style    : integer;  // overlay with bitfields (next 2 also)
+                navpanewidth : integer;
+                buttons      : integer;
+                left,
+                top,
+                right,
+                bottom       : integer;
+                styleflags   ,
+                xtdstyleflags,
+                window_show_state,
+                navpane_initially_closed,
+                navpane_default,
+                navpane_location,
+                wm_notify_id : integer;
+                Constructor create(s:string='');
+                procedure load_from_ini(txt:string);
+                procedure savetoxml(cfg:TXMLConfig;key:string);
+                procedure loadfromxml(cfg:TXMLConfig;key:string);
+                end;
+
+
   TTOCIdxHeader = record
     BlockSize: DWord; // 4096
     EntriesOffset: DWord;
@@ -392,5 +424,144 @@ begin
   //WriteLn(ChunkLevelCount);
 end;
 
-end.
+function getnext(const s:string;var i: integer;len:integer):string;
+var
+    ind : integer;
+
+begin
+ if i>len then exit('');
+ ind:=i;
+ if s[ind]='"' then
+   begin
+     inc(ind);
+     while (ind<=len) and (s[ind]<>'"') do inc(ind);
+     result:=copy(s,i+1,ind-i-1);
+     inc(ind); // skip "
+   end
+ else
+   begin
+     while (ind<=len) and (s[ind]<>',') do inc(ind);
+     result:=copy(s,i,ind-i);
+   end;
+ i:=ind+1; // skip ,
+end;
+
+function getnextint(const txt:string;var ind: integer;len:integer):integer;
+
+var s : string;
+begin
+  s:=getnext(txt,ind,len);
+  result:=strtointdef(s,0);  // I think this does C style hex, if not fixup here.
+end;
+
+procedure TCHMWindow.load_from_ini(txt:string);
+var ind,len,
+    j,k     : integer;
+    arr     : array[0..3] of integer;
+    s2      : string;
+begin
+  j:=pos('=',txt);
+  if j>0 then
+    txt[j]:=',';
+  ind:=1; len:=length(txt);
+  window_type       :=getnext(txt,ind,len);
+  Title_bar_text    :=getnext(txt,ind,len);
+  index_file        :=getnext(txt,ind,len);
+  Toc_file          :=getnext(txt,ind,len);
+  Default_File      :=getnext(txt,ind,len);
+  Home_button_file  :=getnext(txt,ind,len);
+  Jumpbutton_1_File :=getnext(txt,ind,len);
+  Jumpbutton_1_Text :=getnext(txt,ind,len);
+  Jumpbutton_2_File :=getnext(txt,ind,len);
+  Jumpbutton_2_Text :=getnext(txt,ind,len);
+
+  nav_style         :=getnextint(txt,ind,len);
+  navpanewidth      :=getnextint(txt,ind,len);
+  buttons           :=getnextint(txt,ind,len);
+  k:=0;
+  repeat
+   s2:=getnext(txt,ind,len);
+   if (length(s2)>0) and (s2[1]='[') then delete(s2,1,1);
+   j:=pos(']',s2);
+   if j>0 then delete(s2,j,1);
+   arr[k]:=strtointdef(s2,0);
+   inc(k);
+  until (j<>0) or (ind>len);
+  left  :=arr[0];
+  top   :=arr[1];
+  right :=arr[2];
+  bottom:=arr[3];
+  styleflags               :=getnextint(txt,ind,len);
+  xtdstyleflags            :=getnextint(txt,ind,len);
+  window_show_state        :=getnextint(txt,ind,len);
+  navpane_initially_closed :=getnextint(txt,ind,len);
+  navpane_default          :=getnextint(txt,ind,len);
+  navpane_location         :=getnextint(txt,ind,len);
+  wm_notify_id             :=getnextint(txt,ind,len);
+end;
+
+procedure TCHMWindow.savetoxml(cfg:TXMLConfig;key:string);
+begin
+  cfg.setvalue(key+'window_type',window_type);
+  cfg.setvalue(key+'title_bar_text',title_bar_text);
+  cfg.setvalue(key+'toc_file',   Toc_file  );
+  cfg.setvalue(key+'index_file',   index_file  );
+  cfg.setvalue(key+'default_file',   Default_File    );
+  cfg.setvalue(key+'home_button_file',   Home_button_file);
+  cfg.setvalue(key+'jumpbutton_1_file',   Jumpbutton_1_File     );
+  cfg.setvalue(key+'jumpbutton_1_text',   Jumpbutton_1_Text     );
+  cfg.setvalue(key+'jumpbutton_2_file',   Jumpbutton_2_File   );
+  cfg.setvalue(key+'jumpbutton_2_text',   Jumpbutton_2_Text     );
+  cfg.setvalue(key+'nav_style',   nav_style );
+  cfg.setvalue(key+'navpanewidth',   navpanewidth    );
+  cfg.setvalue(key+'buttons',   buttons   );
+  cfg.setvalue(key+'left',   left);
+  cfg.setvalue(key+'top',   top );
+  cfg.setvalue(key+'right',   right     );
+  cfg.setvalue(key+'bottom',   bottom    );
+  cfg.setvalue(key+'styleflags',   styleflags);
+  cfg.setvalue(key+'xtdstyleflags',   xtdstyleflags   );
+  cfg.setvalue(key+'window_show_state',   window_show_state     );
+  cfg.setvalue(key+'navpane_initially_closed',navpane_initially_closed  );
+  cfg.setvalue(key+'navpane_default',navpane_default);
+  cfg.setvalue(key+'navpane_location',navpane_location    );
+  cfg.setvalue(key+'wm_notify_id',wm_notify_id  );
+end;
 
+procedure TCHMWindow.loadfromxml(cfg:TXMLConfig;key:string);
+
+begin
+  window_type           :=cfg.getvalue(key+'window_type','');
+  Title_bar_text        :=cfg.getvalue(key+'title_bar_text','');
+  Toc_file              :=cfg.getvalue(key+'toc_file','');
+  Index_file              :=cfg.getvalue(key+'index_file','');
+  Default_File          :=cfg.getvalue(key+'default_file','');
+  Home_button_file      :=cfg.getvalue(key+'home_button_file','');
+  Jumpbutton_1_File     :=cfg.getvalue(key+'jumpbutton_1_file','');
+  Jumpbutton_1_Text     :=cfg.getvalue(key+'jumpbutton_1_text','');
+  Jumpbutton_2_File     :=cfg.getvalue(key+'jumpbutton_2_file','');
+  Jumpbutton_2_Text     :=cfg.getvalue(key+'jumpbutton_2_text','');
+  nav_style             :=cfg.getvalue(key+'nav_style',0);
+  navpanewidth          :=cfg.getvalue(key+'navpanewidth',0);
+  buttons               :=cfg.getvalue(key+'buttons',0);
+  left                  :=cfg.getvalue(key+'left',0);
+  top                   :=cfg.getvalue(key+'top',0);
+  right                 :=cfg.getvalue(key+'right',0);
+  bottom                :=cfg.getvalue(key+'bottom',0);
+  styleflags            :=cfg.getvalue(key+'styleflags',0);
+  xtdstyleflags         :=cfg.getvalue(key+'xtdstyleflags',0);
+  window_show_state     :=cfg.getvalue(key+'window_show_state',0);
+  navpane_initially_closed :=cfg.getvalue(key+'navpane_initially_closed',0);
+  navpane_default       :=cfg.getvalue(key+'navpane_default',0);
+  navpane_location      :=cfg.getvalue(key+'navpane_location',0);
+  wm_notify_id          :=cfg.getvalue(key+'wm_notify_id',0);
+end;
+
+Constructor TCHMWindow.create(s:string='');
+
+begin
+ if s<>'' then
+   load_from_ini(s);
+end;
+
+end.