0024722: Move functionality of WOK command wgendoc to OCCT tool gendoc
[occt.git] / adm / occaux.tcl
1 # =======================================================================
2 # Created on: 2014-03-21
3 # Created by: OMY
4 # Copyright (c) 1996-1999 Matra Datavision
5 # Copyright (c) 1999-2014 OPEN CASCADE SAS
6 #
7 # This file is part of Open CASCADE Technology software library.
8 #
9 # This library is free software; you can redistribute it and/or modify it under
10 # the terms of the GNU Lesser General Public License version 2.1 as published
11 # by the Free Software Foundation, with special exception defined in the file
12 # OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 # distribution for complete text of the license and disclaimer of any warranty.
14 #
15 # Alternatively, this file may be used under the terms of Open CASCADE
16 # commercial license or contractual agreement.
17
18 # Brief: This script contains auxilary functions which can be used 
19 #         in documentation generation process
20 # =======================================================================
21
22 # ==============================================
23 # Commonly used functions
24 # ==============================================
25
26 # Parses arguments line like "-arg1=val1 -arg2=val2 ..." to array args_names and map args_values
27 proc OCCDoc_ParseArguments {arguments} {
28   global args_names
29   global args_values
30   set args_names {}
31   array set args_values {}
32
33   foreach arg $arguments {
34     if {[regexp {^(-)[a-z]+$} $arg] == 1} {
35       set name [string range $arg 1 [string length $arg]-1]
36       lappend args_names $name
37       set args_values($name) "NULL"
38       continue
39     } elseif {[regexp {^(-)[a-z]+=.+$} $arg] == 1} {
40       set equal_symbol_position [string first "=" $arg]
41       set name [string range $arg 1 $equal_symbol_position-1]
42       lappend args_names $name
43       set value [string range $arg $equal_symbol_position+1 [string length $arguments]-1]
44       
45       # To parse a list of values for -m parameter
46       if { [string first "," $value] != -1 } {
47         set value [split $value ","];
48       }
49
50       set args_values($name) $value
51
52     } else {
53       puts "Error in argument $arg."
54       return 1
55     }
56   }
57   return 0
58 }
59
60 # Returns script parent folder
61 proc OCCDoc_GetDoxDir {} {
62   return [file normalize [file dirname [info script]]/../dox]
63 }
64
65 # Returns OCCT root dir
66 proc OCCDoc_GetOCCTRootDir {} {
67   set path [OCCDoc_GetDoxDir]
68   return [file normalize $path/..]
69 }
70
71 # Returns root dir
72 proc OCCDoc_GetRootDir { {theProductsPath ""} } {
73
74   if { $theProductsPath == "" } {
75     return [OCCDoc_GetOCCTRootDir]
76   } else {
77     return [file normalize $theProductsPath]
78   }
79 }
80
81 # Returns OCCT include dir
82 proc OCCDoc_GetIncDir { {theProductsPath ""} } {
83   set path [OCCDoc_GetRootDir $theProductsPath]
84   return "$path/inc"
85 }
86
87 # Returns OCCT source dir
88 proc OCCDoc_GetSourceDir { {theProductsPath ""} } {
89   set path [OCCDoc_GetRootDir $theProductsPath]
90   return "$path/src"
91 }
92
93 # Returns name of the package from the current toolkit
94 proc OCCDoc_GetNameFromPath { thePath } {
95
96   set splitted_path [split $thePath "/" ]
97   set package_name  [lindex $splitted_path end]
98
99   return $package_name
100 }
101
102 # Returns the relative path between two folders
103 proc OCCDoc_GetRelPath {thePathFrom thePathTo} {
104   if { [file isdirectory "$thePathFrom"] == 0 } {
105     return ""
106   }
107
108   set aPathFrom [file normalize "$thePathFrom"]
109   set aPathTo   [file normalize "$thePathTo"]
110
111   set aCutedPathFrom "${aPathFrom}/dummy"
112   set aRelatedDeepPath ""
113
114   while { "$aCutedPathFrom" != [file normalize "$aCutedPathFrom/.."] } {
115     set aCutedPathFrom [file normalize "$aCutedPathFrom/.."]
116     # does aPathTo contain aCutedPathFrom?
117     regsub -all $aCutedPathFrom $aPathTo "" aPathFromAfterCut
118     if { "$aPathFromAfterCut" != "$aPathTo" } { # if so
119       if { "$aCutedPathFrom" == "$aPathFrom" } { # just go higher, for example, ./somefolder/someotherfolder
120         set aPathTo ".${aPathTo}"
121       } elseif { "$aCutedPathFrom" == "$aPathTo" } { # remove the last "/"
122         set aRelatedDeepPath [string replace $aRelatedDeepPath end end ""]
123       }
124       regsub -all $aCutedPathFrom $aPathTo $aRelatedDeepPath aPathToAfterCut
125       regsub -all "//" $aPathToAfterCut "/" aPathToAfterCut
126       return $aPathToAfterCut
127     }
128     set aRelatedDeepPath "$aRelatedDeepPath../"
129   }
130
131   return $thePathTo
132 }
133
134 # Returns OCCT version string from file Standard_Version.hxx (if available)
135 proc OCCDoc_DetectCasVersion {} {
136   set occt_ver 6.7.0
137   set occt_ver_add ""
138   set filename "[OCCDoc_GetSourceDir]/Standard/Standard_Version.hxx"
139   if { [file exists $filename] } {
140     set fh [open $filename "r"]
141     set fh_loaded [read $fh]
142     close $fh
143     regexp {[^/]\s*#\s*define\s+OCC_VERSION_COMPLETE\s+\"([^\s]*)\"} $fh_loaded dummy occt_ver
144     regexp {[^/]\s*#\s*define\s+OCC_VERSION_DEVELOPMENT\s+\"([^\s]*)\"} $fh_loaded dummy occt_ver_add
145     if { "$occt_ver_add" != "" } { set occt_ver ${occt_ver}.$occt_ver_add }
146   }
147   return $occt_ver
148 }
149
150 # Checks if the necessary tools exist
151 proc OCCDoc_DetectNecessarySoftware { DOXYGEN_PATH GRAPHVIZ_PATH INKSCAPE_PATH HHC_PATH PDFLATEX_PATH } {
152
153   upvar 1 DOXYGEN_PATH  doxy_path
154   upvar 1 GRAPHVIZ_PATH graph_path
155   upvar 1 INKSCAPE_PATH inkscape_path
156   upvar 1 HHC_PATH      hhc_path
157   upvar 1 PDFLATEX_PATH latex_path
158
159   set doxy_path     ""
160   set graph_path    ""
161   set inkscape_path ""
162   set latex_path    ""
163   set hhc_path      ""
164
165   set is_win "no"
166   if { "$::tcl_platform(platform)" == "windows" } {
167     set is_win "yes"
168   }
169   if {"$is_win" == "yes"} {
170     set exe ".exe"
171   } else {
172     set exe ""
173   }
174
175   set g_flag "no"
176   set d_flag "no"
177   set i_flag "no"
178   set h_flag "no"
179   set l_flag "no"
180
181   puts ""
182   set envPath $::env(PATH)
183   if { $is_win == "yes" } {
184     set searchPathsList [split $envPath ";"]
185   } else {
186     set searchPathsList [split $envPath ":"]
187   }
188
189   foreach path $searchPathsList {
190     if { ($is_win == "no") && 
191          (($path == "/usr/bin") || ($path == "/usr/local/bin")) } {
192         # Avoid searching in default bin location
193         continue
194     }
195     if {$d_flag == "no"} {
196       if { [file exists $path/doxygen$exe] } {
197         catch { exec $path/doxygen -V } version_string 
198         set version [lindex [split $version_string "\n"] 0]
199         puts "Info: $version "
200         puts "      found in $path."
201         set doxy_path "$path/doxygen$exe"
202         set d_flag "yes"
203       }
204     }
205     if {$g_flag == "no"} {
206       if { [file exists $path/dot$exe] } {
207         catch { exec $path/dot -V } version
208
209         puts "Info: $version "
210         puts "      found in $path."
211         set graph_path "$path/dot$exe"
212         set g_flag "yes"
213       }
214     }
215     if {$i_flag == "no"} {
216       if { [file exists $path/inkscape$exe] } {
217         catch { exec $path/inkscape -V } version
218         puts "Info: $version " 
219         puts "      found in $path."
220         set inkscape_path "$path/inkscape$exe"
221         set i_flag "yes"
222       }
223     }
224     if {$l_flag == "no"} {
225       if { [file exists $path/pdflatex$exe] } {
226         catch { exec $path/pdflatex -version } version
227         set version [lindex [split $version "\n"] 0]
228         puts "Info: $version " 
229         puts "      found in $path."
230         set latex_path "$path/pdflatex$exe"
231         set l_flag "yes"
232       }
233     }
234     if { ("$is_win" == "yes") && ($h_flag == "no") } {
235       if { [file exists $path/hhc.exe] } {
236         puts "Info: hhc " 
237         puts "      found in $path."
238         set hhc_path "hhc$exe"
239         set h_flag "yes"
240       }
241     }
242     if { ($d_flag == "yes") &&
243          ($i_flag == "yes") &&
244          ($g_flag == "yes") &&
245          ($l_flag == "yes") &&
246          (($is_win == "yes") && 
247           ($h_flag == "yes")) } {
248       break
249     }
250   }
251
252   # On Windows search for hhc.exe in the default location 
253   # if it has not been found yet
254   if { ("$is_win" == "yes") && ($h_flag == "no") } {
255     if { [info exists ::env(ProgramFiles\(x86\))] } {
256       set h_flag "yes"
257       set path "$::env(ProgramFiles\(x86\))\\HTML Help Workshop"
258       set hhc_path "$path\\hhc.exe"
259       puts "Info: hhc " 
260       puts "      found in $path."
261     } else {
262       if { [info exists ::env(ProgramFiles)] } {
263         set h_flag   "yes"
264         set path     "$::env(ProgramFiles)\\HTML Help Workshop"
265         set hhc_path "$path\\hhc.exe"
266         puts "Info: hhc" 
267         puts "      found in $path."
268       }
269     }
270   }
271
272   # On *nix-like platforms, 
273   # check the default binary locations if the tools had not been found yet
274   if {  $is_win == "no"  &&
275       (($d_flag == "no") ||
276        ($i_flag == "no") ||
277        ($g_flag == "no") ||
278        ($l_flag == "no")) } {
279
280     set default_path { "/usr/bin" "/usr/local/bin" }
281     foreach path $default_path {
282       if {$d_flag == "no"} {
283         if { [file exists $path/doxygen$exe] } {
284           catch { exec $path/doxygen -V } version_string 
285           set version [lindex [split $version_string "\n"] 0]
286           puts "Info: $version "
287           puts "      found in $path."
288           set doxy_path "$path/doxygen$exe"
289           set d_flag "yes"
290         }
291       }
292       if {$g_flag == "no"} {
293         if { [file exists $path/dot$exe] } {
294           catch { exec $path/dot -V } version
295
296           puts "Info: $version "
297           puts "      found in $path."
298           set graph_path "$path/dot$exe"
299           set g_flag "yes"
300         }
301       }
302       if {$i_flag == "no"} {
303         if { [file exists $path/inkscape$exe] } {
304           catch { exec $path/inkscape -V } version
305           puts "Info: $version " 
306           puts "      found in $path."
307           set inkscape_path "$path/inkscape$exe"
308           set i_flag "yes"
309         }
310       }
311       if {$l_flag == "no"} {
312         if { [file exists $path/pdflatex$exe] } {
313           catch { exec $path/pdflatex -version } version
314           set version [lindex [split $version "\n"] 0]
315           puts "Info: $version " 
316           puts "      found in $path."
317           set latex_path "$path/pdflatex$exe"
318           set l_flag "yes"
319         }
320       }
321     }
322   }
323
324   # Check if tools have been found
325   if { $d_flag == "no" } {
326     puts "Warning: Could not find doxygen installed."
327     return -1
328   }
329   if { $g_flag == "no" } {
330     puts "Warning: Could not find graphviz installed."
331   }
332   if { $i_flag == "no" } {
333     puts "Warning: Could not find inkscape installed."
334   }  
335   if { $l_flag == "no" } {
336     puts "Warning: Could not find pdflatex installed."
337   }
338   if { ("$::tcl_platform(platform)" == "windows") && ($h_flag == "no") } {
339     puts "Warning: Could not find hhc installed."
340   }
341
342   puts ""
343 }
344
345 # Convert SVG files to PDF format to allow including them to PDF
346 # (requires InkScape to be in PATH)
347 proc OCCDoc_ProcessSvg {latexDir verboseMode} {
348
349   foreach file [glob -nocomplain $latexDir/*.svg] {
350     if {$verboseMode == "YES"} {
351       puts "Info: Converting file $file..."
352     }
353     set pdffile "[file rootname $file].pdf"
354     if { [catch {exec inkscape -z -D --file=$file --export-pdf=$pdffile} res] } {
355       #puts "Error: $res."
356       return
357     }
358   }
359 }
360
361 # ==============================================
362 # Reference Manual-specific functions
363 # ==============================================
364
365 # Finds dependencies between all modules  
366 proc OCCDoc_CreateModulesDependencyGraph {dir filename modules mpageprefix} {
367   global module_dependency
368
369   if {![catch {open $dir/$filename.dot "w"} file]} {
370     puts $file "digraph $filename"
371     puts $file "\{"
372
373     foreach mod $modules {
374       if { $mod == "" } {
375         continue
376       }
377       puts $file "\t$mod \[ URL = \"[string tolower $mpageprefix$mod.html]\" \]"
378       foreach mod_depend $module_dependency($mod) {
379         puts $file "\t$mod_depend -> $mod \[ dir = \"back\", color = \"midnightblue\", style = \"solid\" \]"
380       }
381     }
382     
383     puts $file "\}"
384     close $file
385
386     return $filename
387   }
388 }
389
390 # Finds dependencies between all toolkits in module
391 proc OCCDoc_CreateModuleToolkitsDependencyGraph {dir filename modulename tpageprefix} {
392   global toolkits_in_module
393   global toolkit_dependency
394   global toolkit_parent_module
395
396   if {![catch {open $dir/$filename.dot "w"} file]} {
397     puts $file "digraph $filename"
398     puts $file "\{"
399
400     foreach tk $toolkits_in_module($modulename) {
401       puts $file "\t$tk \[ URL = \"[string tolower $tpageprefix$tk.html]\"\ ]"
402       foreach tkd $toolkit_dependency($tk) {
403         if { [info exists toolkit_parent_module($tkd)] } {
404           if {$toolkit_parent_module($tkd) == $modulename} {
405             puts $file "\t$tkd -> $tk \[ dir = \"back\", color = \"midnightblue\", style = \"solid\" \]"    
406           }
407         }
408       }
409     }
410     
411     puts $file "\}"
412     close $file
413     
414     return $filename
415   }
416 }
417
418 # Finds dependencies between the current toolkit and other toolkits
419 proc OCCDoc_CreateToolkitDependencyGraph {dir filename toolkitname tpageprefix} {
420   global toolkit_dependency
421   
422   if {![catch {open $dir/$filename.dot "w"} file]} {
423     puts $file "digraph $filename"
424     puts $file "\{"
425     
426     puts $file "\t$toolkitname \[ URL = \"[string tolower $tpageprefix$toolkitname.html]\"\, shape = box ]"
427     foreach tkd $toolkit_dependency($toolkitname) {
428       puts $file "\t$tkd \[ URL = \"[string tolower $tpageprefix$tkd.html]\"\ , shape = box ]"
429       puts $file "\t$toolkitname -> $tkd \[ color = \"midnightblue\", style = \"solid\" \]"    
430     }
431     
432     if {[llength $toolkit_dependency($toolkitname)] > 1} {
433     puts $file "\taspect = 1"
434     }
435     
436     puts $file "\}"
437     close $file
438     
439     return $filename
440   }
441 }
442
443 # Fills arrays of modules, toolkits, dependency of modules/toolkits etc 
444 proc OCCDoc_LoadData { {theProductsDir ""} } {
445   global toolkits_in_module
446   global toolkit_dependency
447   global toolkit_parent_module
448   global module_dependency
449
450   if { $theProductsDir == ""} {
451     set modules_files [glob -nocomplain -type f -directory "[OCCDoc_GetSourceDir $theProductsDir]/OS/" *.tcl]
452   } else {
453     set modules_files [glob -nocomplain -type f -directory "[OCCDoc_GetSourceDir $theProductsDir]/VAS/" *.tcl]
454   }
455
456   foreach module_file $modules_files {
457     source $module_file
458   }
459
460   set modules [OCCDoc_GetModulesList $theProductsDir]
461   foreach mod $modules {
462
463     if { $mod == "" } {
464       continue
465     }
466     # Get toolkits of current module
467     set toolkits_in_module($mod) [$mod:toolkits]
468     # Get all dependence of current toolkit 
469     foreach tk $toolkits_in_module($mod) {
470       # set parent module of current toolkit
471       set toolkit_parent_module($tk) $mod
472       set exlibfile      [open "[OCCDoc_GetSourceDir $theProductsDir]/$tk/EXTERNLIB" r]
473       set exlibfile_data [read $exlibfile]
474       set exlibfile_data [split $exlibfile_data "\n"]
475         
476       set toolkit_dependency($tk) {}
477       foreach dtk $exlibfile_data {
478         if { ([string first "TK" $dtk 0] == 0) || 
479              ([string first "P"  $dtk 0] == 0) } {
480           lappend toolkit_dependency($tk) $dtk
481         }
482       }
483       close $exlibfile
484     }
485   }
486
487   # Get modules dependency
488   foreach mod $modules {
489     set module_dependency($mod) {}
490     foreach tk $toolkits_in_module($mod) {
491       foreach tkd $toolkit_dependency($tk) {
492         if { [info exists toolkit_parent_module($tkd)] } {
493           if { $toolkit_parent_module($tkd) != $mod &&
494                [lsearch $module_dependency($mod) $toolkit_parent_module($tkd)] == -1} {
495             lappend module_dependency($mod) $toolkit_parent_module($tkd)
496           }
497         }
498       }
499     }
500   }
501 }
502
503 # Returns list of packages of the given toolkit
504 proc OCCDoc_GetPackagesList { theToolKitPath } {
505
506   set packages_list {}
507   
508   # Open file with list of packages of the given toolkit
509   set fileid [open "$theToolKitPath/PACKAGES" "r"]
510   
511   while { [eof $fileid] == 0 } {
512     set str [gets $fileid]
513     if { $str != "" } {
514       lappend packages_list $str
515     }
516   }
517
518   close $fileid
519   
520   return $packages_list
521 }
522
523 # Returns list of modules from UDLIST
524 proc OCCDoc_GetModulesList { {theProductsDir ""} } {
525
526   if { $theProductsDir == "" } {
527     source "[OCCDoc_GetSourceDir $theProductsDir]/OS/Modules.tcl"
528     # load a command from this file
529     set modules [OS:Modules]
530   } else {
531     source "[OCCDoc_GetSourceDir $theProductsDir]/VAS/Products.tcl"
532     # load a command from this file
533     set modules [VAS:Products]
534   }
535
536   return $modules
537 }
538
539 # Returns list of desired files in the specified location
540 proc OCCDoc_GetHeadersList { theDesiredContent theFileType thePackageName {theProductsDir ""} } {
541
542   # Get file type
543   set file_type_pattern "*.*"
544   if { $theFileType == "pubinclude" } {
545     set file_type_pattern "*.*"
546   } elseif { $theFileType == "privinclude" } {
547     set file_type_pattern "*.ixx"
548   }
549   
550   # Get content according to desired type ('p' for path and 'f' for filenames only)
551   if { $theDesiredContent == "p" } {
552
553     # Get list of files with path
554     set files_list [split [glob -nocomplain -type f -directory "[OCCDoc_GetIncDir $theProductsDir]" "$thePackageName$file_type_pattern"]]
555
556     return $files_list
557   } elseif { $theDesiredContent == "f" } {
558   # Get list of files without path
559     set files_list [split [glob -nocomplain -type f -directory "[OCCDoc_GetIncDir $theProductsDir]" "$thePackageName$file_type_pattern"]]
560
561     # Cut paths from filenames
562     foreach file $files_list {
563       set elem_index [lsearch $files_list $file]
564       lset files_list $elem_index [OCCDoc_GetNameFromPath [lindex $files_list $elem_index]]
565     }
566     return $files_list
567   }
568 }
569
570 # Returns location of the toolkit
571 proc OCCDoc_Locate { theToolKitName {theProductsDir ""} } {
572   set tk_dir "[OCCDoc_GetSourceDir $theProductsDir]/[OCCDoc_GetNameFromPath $theToolKitName]"
573   return $tk_dir
574 }
575
576 # Gets contents of the given html node (for Post-processing)
577 proc OCCDoc_GetNodeContents {node props html} {
578   set openTag "<$node$props>"
579   set closingTag "</$node>"
580   set start [string first $openTag $html]
581   if {$start == -1} {
582     return ""
583   }
584   set start [expr $start + [string length $openTag]]
585   set end   [string length $html]
586   set html  [string range $html $start $end]
587   set start [string first $closingTag $html]
588   set end   [string length $html]
589   if {$start == -1} {
590     return ""
591   }
592   set start [expr $start - 1]
593   return [string range $html 0 $start]
594 }
595
596 # Generates main page file describing module structure
597 proc OCCDoc_MakeMainPage {outDir outFile modules {theProductsDir ""} } {
598   global env
599
600   set one_module [expr [llength $modules] == 1]
601   set fd [open $outFile "w"]
602
603   set module_prefix "module_"
604   set toolkit_prefix "toolkit_"
605   set package_prefix "package_"
606
607   if { ! [file exists "$outDir/html"] } {
608     file mkdir "$outDir/html"
609   }
610
611   OCCDoc_LoadData $theProductsDir
612
613   # Main page: list of modules
614   if { ! $one_module } {
615     puts $fd "/**"
616     puts $fd "\\mainpage Open CASCADE Technology"
617
618     foreach mod $modules {
619         puts $fd "\\li \\subpage [string tolower $module_prefix$mod]"
620     }
621     # insert modules relationship diagramm
622     puts $fd "\\dotfile [OCCDoc_CreateModulesDependencyGraph $outDir/html schema_all_modules $modules $module_prefix]"
623     puts $fd "**/\n"
624   }
625
626   # One page per module: list of toolkits
627   set toolkits {}
628   foreach mod $modules {
629     if { $mod == "" } {
630         continue
631     }
632     puts $fd "/**"
633     if { $one_module } {
634         puts $fd "\\mainpage OCCT Module [$mod:name]"
635     } else {
636         puts $fd "\\page [string tolower module_$mod] Module [$mod:name]"
637     }
638     foreach tk [lsort [$mod:toolkits]] {
639         lappend toolkits $tk
640         puts $fd "\\li \\subpage [string tolower $toolkit_prefix$tk]"
641     }
642     puts $fd "\\dotfile [OCCDoc_CreateModuleToolkitsDependencyGraph $outDir/html schema_$mod $mod $toolkit_prefix]"
643     puts $fd "**/\n"
644   }
645
646   # One page per toolkit: list of packages
647   set packages {}
648   foreach tk $toolkits {
649     puts $fd "/**"
650     puts $fd "\\page [string tolower toolkit_$tk] Toolkit $tk"
651     foreach pk [lsort [OCCDoc_GetPackagesList [OCCDoc_Locate $tk $theProductsDir]]] {
652         lappend packages $pk
653         set u [OCCDoc_GetNameFromPath $pk]
654         puts $fd "\\li \\subpage [string tolower $package_prefix$u]"
655     }
656     puts $fd "\\dotfile [OCCDoc_CreateToolkitDependencyGraph $outDir/html schema_$tk $tk $toolkit_prefix]"
657     puts $fd "**/\n"
658   }
659
660   # One page per package: list of classes
661   foreach pk $packages {
662     set u [OCCDoc_GetNameFromPath $pk]
663     puts $fd "/**"
664     puts $fd "\\page [string tolower $package_prefix$u] Package $u"
665     foreach hdr [lsort [OCCDoc_GetHeadersList "f" "pubinclude" "$pk" "$theProductsDir"]] {
666       if { ! [regexp {^Handle_} $hdr] && [regexp {(.*)[.]hxx} $hdr str obj] } {
667         puts $fd "\\li \\subpage $obj"
668       }
669     }
670     puts $fd "**/\n"
671   }
672
673   close $fd
674
675   return $outFile
676 }
677
678 # Parses generated files to add a navigation path 
679 proc OCCDoc_PostProcessor {outDir} {
680   puts "[clock format [clock seconds] -format {%Y.%m.%d %H:%M}] Post-process is started ..."
681   append outDir "/html"
682   set files [glob -nocomplain -type f $outDir/package_*]
683   if { $files != {} } {
684     foreach f [lsort $files] {
685       set packageFilePnt  [open $f r]
686       set packageFile     [read $packageFilePnt]
687       set navPath         [OCCDoc_GetNodeContents "div" " id=\"nav-path\" class=\"navpath\"" $packageFile]
688       set packageName     [OCCDoc_GetNodeContents "div" " class=\"title\"" $packageFile]
689       regsub -all {<[^<>]*>} $packageName "" packageName 
690
691       # add package link to nav path
692       set first           [expr 1 + [string last "/" $f]]
693       set last            [expr [string length $f] - 1]
694       set packageFileName [string range $f $first $last]
695       set end             [string first "</ul>" $navPath]
696       set end             [expr $end - 1]
697       set navPath         [string range $navPath 0 $end]
698       append navPath "  <li class=\"navelem\"><a class=\"el\" href=\"$packageFileName\">$packageName</a>      </li>\n    </ul>"
699
700       # get list of files to update
701       set listContents [OCCDoc_GetNodeContents "div" " class=\"textblock\"" $packageFile]
702       set listContents [OCCDoc_GetNodeContents "ul" "" $listContents]
703       set lines [split $listContents "\n"]
704       foreach line $lines {
705         if {[regexp {href=\"([^\"]*)\"} $line tmpLine classFileName]} {
706           # check if anchor is there
707           set anchorPos [string first "#" $classFileName]
708           if {$anchorPos != -1} {
709             set classFileName [string range $classFileName 0 [expr $anchorPos - 1]]
710           }
711
712           # read class file
713           set classFilePnt [open $outDir/$classFileName r+]
714           set classFile    [read $classFilePnt]
715
716           # find position of content block 
717           set contentPos   [string first "<div class=\"header\">" $classFile]
718           set navPart      [string range $classFile 0 [expr $contentPos - 1]]
719
720           # position where to insert nav path
721           set posToInsert  [string last "</div>" $navPart]
722           set prePart      [string range $classFile 0 [expr $posToInsert - 1]]
723           set postPart     [string range $classFile $posToInsert [string length $classFile]]
724           set newClassFile ""
725           append newClassFile $prePart "  <div id=\"nav-path\" class=\"navpath\">" $navPath \n "  </div>" \n $postPart
726
727           # write updated content
728           seek $classFilePnt 0
729           puts $classFilePnt $newClassFile
730           close $classFilePnt
731         } 
732       }
733       close $packageFilePnt
734     }
735     return 0
736   } else {
737     puts "no files found"
738     return 1
739   }
740 }
741
742 # ======================================
743 #  User Guides-specific functions
744 # ======================================
745
746 # Loads a list of docfiles from file FILES.txt
747 proc OCCDoc_LoadFilesList {} {
748
749   set INPUTDIR [OCCDoc_GetDoxDir]
750
751   global available_docfiles
752   set available_docfiles {}
753
754   # Read data from file
755   if { [file exists "$INPUTDIR/FILES_HTML.txt"] == 1 } {
756     set FILE [open "$INPUTDIR/FILES_HTML.txt" r]
757     while {1} {
758       set line [string trim [gets $FILE]]
759
760       # trim possible comments starting with '#'
761       set line [regsub {\#.*} $line {}]
762       if {$line != ""} {
763         lappend available_docfiles $line
764       }
765       if {[eof $FILE]} {
766         close $FILE
767         break
768       }
769     }
770   } else {
771     return -1
772   }
773
774   global available_pdf
775   set    available_pdf {}
776
777   # Read data from file
778   if { [file exists "$INPUTDIR/FILES_PDF.txt"] } {
779     set FILE [open "$INPUTDIR/FILES_PDF.txt" r]
780     while {1} {
781       set line [string trim [gets $FILE]]
782
783       # Trim possible comments starting with '#'
784       set line [regsub {\#.*} $line {}]
785       if {$line != ""} {
786         lappend available_pdf $line
787       }
788       if {[eof $FILE]} {
789         close $FILE
790         break
791       }
792     }
793   } else {
794     return -1
795   }
796   return 0
797 }
798
799 # Writes new TeX file for conversion from tex to pdf for a specific doc
800 proc OCCDoc_MakeRefmanTex {fileName latexDir verboseMode latexFilesList} {
801
802   if { $verboseMode == "YES" } {
803     puts "Info: Making refman.tex file for $fileName..."
804   }
805   set DOCNAME "$latexDir/refman.tex"
806   if {[file exists $DOCNAME] == 1} {
807     file delete -force $DOCNAME
808   }
809
810   # Copy template file to latex folder
811   file copy "[OCCDoc_GetDoxDir]/resources/occt_pdf_template.tex" $DOCNAME
812
813   # Get templatized data
814   set texfile [open $DOCNAME "r"]
815   set texfile_loaded [read $texfile]
816   close $texfile
817
818   # Replace dummy values 
819   set year       [clock format [clock seconds] -format {%Y}]
820   set texfile    [open $DOCNAME "w"]
821   set casVersion [OCCDoc_DetectCasVersion]
822
823   # Get name of the document
824   set docLabel   ""
825   foreach aFileName $latexFilesList {
826     # Find the file in FILES_PDF.txt
827     set parsedFileName [split $aFileName "/" ]
828     set newfileName [string range $fileName [expr [string first "__" $fileName] + 2] end]
829
830     if { [lsearch -nocase $parsedFileName "$newfileName.md" ] != -1 } {
831       set filepath "[OCCDoc_GetDoxDir]/$aFileName"
832       if { [file exists $filepath] } {
833         set MDFile   [open $filepath "r"]
834         set label    [split [gets $MDFile] "\{"]
835         set docLabel [lindex $label 0]
836         close $MDFile
837         
838         break
839       }
840     }
841   }
842
843   set texfile_loaded [string map [list DEFDOCLABEL "$docLabel" DEFCASVERSION "$casVersion" DEFFILENAME "$fileName" DEFYEAR "$year"] $texfile_loaded]
844
845   # Get data
846   puts $texfile $texfile_loaded
847
848   close $texfile
849 }
850
851 # Postprocesses generated TeX files
852 proc OCCDoc_ProcessTex {{texFiles {}} {latexDir} verboseMode} {
853
854   foreach TEX $texFiles {
855     if {$verboseMode == "YES"} {
856       puts "Info: Preprocessing file $TEX..."
857     }
858
859     if {![file exists $TEX]} {
860       puts "Error: file $TEX does not exist."
861       return -1
862     }
863
864     set IN_F        [open "$TEX" "r"]
865     set TMPFILENAME "$latexDir/temp.tex"
866     set OUT_F       [open $TMPFILENAME w]
867
868         while {1} {
869             set line [gets $IN_F]
870             if { [string first "\\includegraphics" $line] != -1 } {
871               # replace svg extension by pdf
872               set line [regsub {[.]svg} $line ".pdf"]
873               # Center images in TeX files
874               set line "\\begin{center}\n $line\n\\end{center}"
875             } elseif { [string first "\\subsection" $line] != -1 } {
876                 # Replace \subsection with \section tag
877                 regsub -all "\\\\subsection" $line "\\\\section" line
878             } elseif { [string first "\\subsubsection" $line] != -1 } {
879                 # Replace \subsubsection with \subsection tag
880                 regsub -all "\\\\subsubsection" $line "\\\\subsection" line
881             } elseif { [string first "\\paragraph" $line] != -1 } {
882                 # Replace \paragraph with \subsubsection tag
883                 regsub -all "\\\\paragraph" $line "\\\\subsubsection" line
884             }
885             puts $OUT_F $line
886
887       if {[eof $IN_F]} {
888         close $IN_F
889         close $OUT_F
890         break
891       }
892     }
893
894     file delete -force $TEX
895     file rename $TMPFILENAME $TEX
896   }
897 }