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