From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- support/autolatex/pm/AutoLaTeX/Core/Config.pm | 876 +++++++++ support/autolatex/pm/AutoLaTeX/Core/IntUtils.pm | 201 ++ support/autolatex/pm/AutoLaTeX/Core/Main.pm | 542 ++++++ support/autolatex/pm/AutoLaTeX/Core/OS.pm | 555 ++++++ support/autolatex/pm/AutoLaTeX/Core/Progress.pm | 535 ++++++ support/autolatex/pm/AutoLaTeX/Core/Translator.pm | 1308 +++++++++++++ support/autolatex/pm/AutoLaTeX/Core/Util.pm | 1467 +++++++++++++++ support/autolatex/pm/AutoLaTeX/GUI/AbstractGUI.pm | 175 ++ .../pm/AutoLaTeX/GUI/AbstractGeneralPanel.pm | 142 ++ .../pm/AutoLaTeX/GUI/AbstractToolPanel.pm | 135 ++ .../pm/AutoLaTeX/GUI/AbstractTranslatorPanel.pm | 202 ++ .../autolatex/pm/AutoLaTeX/GUI/Gtk/GeneralPanel.pm | 544 ++++++ .../autolatex/pm/AutoLaTeX/GUI/Gtk/ToolPanel.pm | 393 ++++ .../pm/AutoLaTeX/GUI/Gtk/TranslatorPanel.pm | 572 ++++++ .../autolatex/pm/AutoLaTeX/GUI/Gtk/WidgetUtil.pm | 544 ++++++ support/autolatex/pm/AutoLaTeX/GUI/Gtk/Window.pm | 426 +++++ support/autolatex/pm/AutoLaTeX/GUI/WidgetUtil.pm | 227 +++ support/autolatex/pm/AutoLaTeX/GUI/clean.png | Bin 0 -> 856 bytes support/autolatex/pm/AutoLaTeX/GUI/cleanall.png | Bin 0 -> 783 bytes .../autolatex/pm/AutoLaTeX/GUI/projectLevel.png | Bin 0 -> 378 bytes .../autolatex/pm/AutoLaTeX/GUI/projectLevel_c.png | Bin 0 -> 532 bytes .../autolatex/pm/AutoLaTeX/GUI/projectLevel_ko.png | Bin 0 -> 492 bytes .../autolatex/pm/AutoLaTeX/GUI/projectLevel_u.png | Bin 0 -> 294 bytes .../autolatex/pm/AutoLaTeX/GUI/projectLevel_uc.png | Bin 0 -> 505 bytes support/autolatex/pm/AutoLaTeX/GUI/systemLevel.png | Bin 0 -> 687 bytes .../autolatex/pm/AutoLaTeX/GUI/systemLevel_c.png | Bin 0 -> 759 bytes .../autolatex/pm/AutoLaTeX/GUI/systemLevel_ko.png | Bin 0 -> 740 bytes .../autolatex/pm/AutoLaTeX/GUI/systemLevel_u.png | Bin 0 -> 475 bytes .../autolatex/pm/AutoLaTeX/GUI/systemLevel_uc.png | Bin 0 -> 738 bytes support/autolatex/pm/AutoLaTeX/GUI/tools.png | Bin 0 -> 609 bytes support/autolatex/pm/AutoLaTeX/GUI/translators.png | Bin 0 -> 744 bytes .../autolatex/pm/AutoLaTeX/GUI/translators_err.png | Bin 0 -> 844 bytes support/autolatex/pm/AutoLaTeX/GUI/userLevel.png | Bin 0 -> 538 bytes support/autolatex/pm/AutoLaTeX/GUI/userLevel_c.png | Bin 0 -> 655 bytes .../autolatex/pm/AutoLaTeX/GUI/userLevel_ko.png | Bin 0 -> 644 bytes support/autolatex/pm/AutoLaTeX/GUI/userLevel_u.png | Bin 0 -> 416 bytes .../autolatex/pm/AutoLaTeX/GUI/userLevel_uc.png | Bin 0 -> 671 bytes support/autolatex/pm/AutoLaTeX/GUI/warning.png | Bin 0 -> 576 bytes .../AutoLaTeX/Interpreter/AbstractInterpreter.pm | 130 ++ .../autolatex/pm/AutoLaTeX/Interpreter/batch.pm | 145 ++ support/autolatex/pm/AutoLaTeX/Interpreter/js.pm | 145 ++ .../autolatex/pm/AutoLaTeX/Interpreter/python.pm | 153 ++ support/autolatex/pm/AutoLaTeX/Interpreter/ruby.pm | 153 ++ support/autolatex/pm/AutoLaTeX/Interpreter/sh.pm | 145 ++ .../autolatex/pm/AutoLaTeX/Interpreter/wincmd.pm | 145 ++ support/autolatex/pm/AutoLaTeX/Make/Make.pm | 1935 ++++++++++++++++++++ .../pm/AutoLaTeX/TeX/BibCitationAnalyzer.pm | 307 ++++ .../autolatex/pm/AutoLaTeX/TeX/DocumentDetector.pm | 145 ++ support/autolatex/pm/AutoLaTeX/TeX/Flattener.pm | 594 ++++++ .../autolatex/pm/AutoLaTeX/TeX/GlossaryAnalyzer.pm | 174 ++ .../autolatex/pm/AutoLaTeX/TeX/IndexAnalyzer.pm | 174 ++ .../pm/AutoLaTeX/TeX/TeXDependencyAnalyzer.pm | 393 ++++ support/autolatex/pm/AutoLaTeX/TeX/TeXParser.pm | 1672 +++++++++++++++++ support/autolatex/pm/README.ctan_flat_as_possible | 5 + 54 files changed, 15259 insertions(+) create mode 100644 support/autolatex/pm/AutoLaTeX/Core/Config.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Core/IntUtils.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Core/Main.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Core/OS.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Core/Progress.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Core/Translator.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Core/Util.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/AbstractGUI.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/AbstractGeneralPanel.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/AbstractToolPanel.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/AbstractTranslatorPanel.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/Gtk/GeneralPanel.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/Gtk/ToolPanel.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/Gtk/TranslatorPanel.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/Gtk/WidgetUtil.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/Gtk/Window.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/WidgetUtil.pm create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/clean.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/cleanall.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/projectLevel.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/projectLevel_c.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/projectLevel_ko.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/projectLevel_u.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/projectLevel_uc.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/systemLevel.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/systemLevel_c.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/systemLevel_ko.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/systemLevel_u.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/systemLevel_uc.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/tools.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/translators.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/translators_err.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/userLevel.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/userLevel_c.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/userLevel_ko.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/userLevel_u.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/userLevel_uc.png create mode 100644 support/autolatex/pm/AutoLaTeX/GUI/warning.png create mode 100644 support/autolatex/pm/AutoLaTeX/Interpreter/AbstractInterpreter.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Interpreter/batch.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Interpreter/js.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Interpreter/python.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Interpreter/ruby.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Interpreter/sh.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Interpreter/wincmd.pm create mode 100644 support/autolatex/pm/AutoLaTeX/Make/Make.pm create mode 100644 support/autolatex/pm/AutoLaTeX/TeX/BibCitationAnalyzer.pm create mode 100644 support/autolatex/pm/AutoLaTeX/TeX/DocumentDetector.pm create mode 100644 support/autolatex/pm/AutoLaTeX/TeX/Flattener.pm create mode 100644 support/autolatex/pm/AutoLaTeX/TeX/GlossaryAnalyzer.pm create mode 100644 support/autolatex/pm/AutoLaTeX/TeX/IndexAnalyzer.pm create mode 100644 support/autolatex/pm/AutoLaTeX/TeX/TeXDependencyAnalyzer.pm create mode 100644 support/autolatex/pm/AutoLaTeX/TeX/TeXParser.pm create mode 100644 support/autolatex/pm/README.ctan_flat_as_possible (limited to 'support/autolatex/pm') diff --git a/support/autolatex/pm/AutoLaTeX/Core/Config.pm b/support/autolatex/pm/AutoLaTeX/Core/Config.pm new file mode 100644 index 0000000000..9859ee8dec --- /dev/null +++ b/support/autolatex/pm/AutoLaTeX/Core/Config.pm @@ -0,0 +1,876 @@ +# autolatex - Config.pm +# Copyright (C) 1998-15 Stephane Galland +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +=pod + +=head1 NAME + +Config.pm - Configuration Files + +=head1 DESCRIPTION + +Provides a set of utilities for manipulating cofiguration files. + +To use this library, type C. + +=head1 FUNCTIONS + +The provided functions are: + +=over 4 + +=cut +package AutoLaTeX::Core::Config; + +$VERSION = '36.0'; +@ISA = ('Exporter'); +@EXPORT = qw( &getProjectConfigFilename &getUserConfigFilename &getSystemConfigFilename + &getSystemISTFilename &readConfiguration &readConfigFile &getUserConfigDirectory + &cfgBoolean &doConfigurationFileFixing &cfgToBoolean &writeConfigFile + &readOnlySystemConfiguration &readOnlyUserConfiguration &readOnlyProjectConfiguration + &setInclusionFlags &reinitInclusionFlags &cfgIsBoolean &rebuiltConfigValue ) ; +@EXPORT_OK = qw(); + +require 5.014; +use strict; +use utf8; +use warnings; +use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); + +use File::Spec; +use Config::Simple; + +use AutoLaTeX::Core::OS; +use AutoLaTeX::Core::Util; +use AutoLaTeX::Core::IntUtils; + +# Constant that is representing an empty string in the INI file. +# This constant is mandatory because Config::Simple does not +# support the empty values, such as "KEY =". In place, +# the INI file must contains something like "KEY = <<<>>>". +use constant EMPTY_INI_VALUE => '<<<>>>'; + +####################################################### +# Comments for the sections of the configuration file +my %SECTION_COMMENTS = ( + 'viewer' => _T("Configuration of the viewing functions"), + 'generation' => _T("Configuration of the generation functions"), + 'clean' => _T("Configuration of the several cleaning functions"), + 'scm' => _T("Configuration of the SCM functions"), + 'gtk' => _T("GTK interface configuration"), + 'qt' => _T("Qt interface configuration"), + 'windows' => _T("Windows interface configuration"), + 'macos' => _T("MacOS interface configuration"), + 'wxwidget' => _T("wxWidgets interface configuration"), +); + +####################################################### +# Comments for the public configuration entries +my %CONFIGURATION_COMMENTS = ( + # + # CLEAN + 'clean.files to clean' => _T( "List of additional files to remove when cleaning (shell ". + "wild cards are allowed). This list is used when the ". + "target 'clean' is invoked."), + 'clean.files to desintegrate' => _T( "List of additional files to remove when all cleaning ". + "(shell wild cards are allowed). This list is used when ". + "the target 'cleanall' is invoked."), + # GENERATION + 'generation.biblio' => _T( "Indicates if bibliography tool (bibtex,biber) should be run ('yes' or 'no')."), + 'generation.generate images' => _T( "Does the figures must be automatically generated ('yes' or 'no')?"), + 'generation.image directory' => _T( "Specify the directories inside which AutoLaTeX ". + "will find the pictures which must be processed ". + "by the translators. Each time this option is ". + "put on the command line, a directory is added ". + "inside the list of the directories to explore. ". + "The different paths are separated by the ". + "path-separator character (':' on Unix, ';' on ". + "Windows)"), + 'generation.main file' => _T( "Main filename (this option is only available in project's ". + "configuration files)."), + 'generation.generation type' => _T( "Type of generation.\n pdf : use pdflatex to create a ". + "PDF document."), + 'generation.makeglossaries' => _T( "Indicates if glossary tool (makeglossaries) should be run ('yes' or 'no')."), + 'generation.makeindex style' => _T( "Specify the style that must be used by makeindex.\n". + "Valid values are:\n if a filename ". + "was specified, AutoLaTeX assumes that it is the .ist ". + "file;\n \@system AutoLaTeX uses the system ". + "default .ist file (in AutoLaTeX distribution);\n". + " \@detect AutoLaTeX will tries to find a .ist ". + "file in the project's directory. If none was found, ". + "AutoLaTeX will not pass a style to makeindex;\n \@none". + " AutoLaTeX assumes that no .ist file must be ". + "passed to makeindex;\n AutoLaTeX assumes ". + "that no .ist file must be passed to makeindex."), + 'generation.post compilation runs' => _T( "Defines the minimal number of times the LaTeX compilation tools (usually ". + "pdflatex) is run during the last running stage of AutoLaTeX. The default value is 1."), + 'generation.translator include path' => _T( "Defines the paths from which the translators could be ". + "loaded. This is a list of paths separated by the path ". + "separator character used by your operating system: ':' ". + "on Unix platforms or ';' on Windows platforms for example."), + 'generation.synctex' => _T( "Indicates if the PDF document must be produced with the SyncTeX flag on or not. ". + "SyncTeX enables to link a PDF viewer (as evince) and a text editor (as Gedit). ". + "When you click inside one, the other is highlighting the line in its side."), + # SCM + 'scm.scm commit' => _T( "Tool to launch when a SCM commit action is requested. ". + "Basically the SCM tools are CVS, SVN, or GIT."), + 'scm.scm update' => _T( "Tool to launch when a SCM update action is requested. ". + "Basically the SCM tools are CVS, SVN, or GIT."), + # VIEWER + 'viewer.view' => _T( "Indicates if a viewer should be launch after the compilation. ". + "Valid values are 'yes' and 'no'."), + 'viewer.viewer' => _T( "Specify, if not commented,the command line of the viewer."), + 'viewer.asynchronous run' => _T( "Indicates if the viewer is launched in background, or not."), +); + +####################################################### +# Comments for the private configuration entries +# action.create config file +# action.create ist file +# action.fix config file +# config.command line +# input.project directory +# input.latex file +# output.directory +# ouput.ist file +# output.latex basename + + +=pod + +=item B + +Replies the name of a project's configuration file +which is located inside the given directory. + +I + +=over 8 + +=item * the components of the paths, each parameter is a directory in the path. + +=back + +I the configuration filename according to the current operating system rules. + +=cut +sub getProjectConfigFilename(@) { + my $operatingsystem = getOperatingSystem(); + if (("$operatingsystem" eq 'Unix')||(("$operatingsystem" eq 'Cygwin'))) { + return File::Spec->rel2abs(File::Spec->catfile(@_,".autolatex_project.cfg")); + } + else { + return File::Spec->rel2abs(File::Spec->catfile(@_,"autolatex_project.cfg")); + } +} + +=pod + +=item B + +Replies the name of a user's configuration file. + +I the configuration filename according to the current operating system rules. + +=cut +sub getUserConfigFilename() { + my $confdir = getUserConfigDirectory(); + if (-d "$confdir") { + return File::Spec->catfile("$confdir","autolatex.conf"); + } + my $operatingsystem = getOperatingSystem(); + if (("$operatingsystem" eq 'Unix')||(("$operatingsystem" eq 'Cygwin'))) { + return File::Spec->rel2abs(File::Spec->catfile($ENV{'HOME'},".autolatex")); + } + elsif ("$operatingsystem" eq 'Win32') { + return File::Spec->rel2abs(File::Spec->catfile("C:","Documents and Settings",$ENV{'USER'},"Local Settings","Application Data","autolatex.conf")); + } + else { + return File::Spec->rel2abs(File::Spec->catfile($ENV{'HOME'},"autolatex.conf")); + } +} + +=pod + +=item B + +Replies the name of a user's configuration directory. + +I the configuration directory according to the current operating system rules. + +=cut +sub getUserConfigDirectory() { + my $operatingsystem = getOperatingSystem(); + if (("$operatingsystem" eq 'Unix')||(("$operatingsystem" eq 'Cygwin'))) { + return File::Spec->rel2abs(File::Spec->catfile($ENV{'HOME'},".autolatex")); + } + elsif ("$operatingsystem" eq 'Win32') { + return File::Spec->rel2abs(File::Spec->catfile("C:","Documents and Settings",$ENV{'USER'},"Local Settings","Application Data","autolatex")); + } + else { + return File::Spec->rel2abs(File::Spec->catfile($ENV{'HOME'},"autolatex")); + } +} + +=pod + +=item B + +Replies the name of the configuration file for all users. + +I the configuration filename according to the current operating system rules. + +=cut +sub getSystemConfigFilename() { + return File::Spec->catfile(getAutoLaTeXDir(),"default.cfg"); +} + +=pod + +=item B + +Replies the name of the MakeIndex style file for all users. + +I the filename according to the current operating system rules. + +=cut +sub getSystemISTFilename() { + return File::Spec->catfile(getAutoLaTeXDir(),"default.ist"); +} + +=pod + +=item B + +Replies the Perl boolean value that corresponds to the specified +string. If the first parameter is not a valid boolean string, the second +parameter will be replied if it is specified; if not undef will be replied; + +The valid string are (case insensitive): S, S, S, S. + +I + +=over 8 + +=item * the value to test. + +=item * the data structure to fill + +=back + +I nothing + +=cut +sub cfgBoolean($;$) { + if ($_[0]) { + my $v = lc($_[0]); + return 1 if (($v eq 'yes')||($v eq 'true')); + return 0 if (($v eq 'no')||($v eq 'false')); + } + return $_[1]; +} + +=pod + +=item B + +Replies the configuration's file boolean value that corresponds to the specified +Perl boolean value. + +I + +=over 8 + +=item * the value to test. + +=back + +I nothing + +=cut +sub cfgToBoolean($) { + return ($_[0]) ? 'true' : 'false'; +} + +=pod + +=item B + +Replies if the specified string is a valid boolean string. + +I + +=over 8 + +=item * the value to test. + +=back + +I nothing + +=cut +sub cfgIsBoolean($) { + if (defined($_[0])) { + my $v = lc($_[0]); + return 1 + if (($v eq 'yes')||($v eq 'no')||($v eq 'true')||($v eq 'false')); + } + return 0; +} + +=pod + +=item B + +Replies the current configuration. The configuration +is extracted from the system configuration file +(from AutoLaTeX distribution) and from the user +configuration file. + +I a hashtable containing (attribute name, attribute value) pairs. +The attribute name could be S to describe the attribute inside +a section. + +=cut +sub readConfiguration() { + my %configuration = (); + my $systemFile = getSystemConfigFilename(); + my $userFile = getUserConfigFilename(); + readConfigFile("$systemFile",\%configuration); + readConfigFile("$userFile",\%configuration); + # Remove the main intput filename + if (exists $configuration{'generation.main file'}) { + delete $configuration{'generation.main file'}; + } + return %configuration; +} + +=pod + +=item B + +Replies the current configuration. The configuration +is extracted from the system configuration file +(from AutoLaTeX distribution) only. + +I a hashtable containing (attribute name, attribute value) pairs. +The attribute name could be S to describe the attribute inside +a section. + +=cut +sub readOnlySystemConfiguration(;$) { + my %configuration = (); + my $systemFile = getSystemConfigFilename(); + readConfigFile("$systemFile",\%configuration,$_[0]); + # Remove the main intput filename + if (exists $configuration{'generation.main file'}) { + delete $configuration{'generation.main file'}; + } + return %configuration; +} + +=pod + +=item B + +Replies the current configuration. The configuration +is extracted from the user configuration file +($HOME/.autolatex or $HOME/.autolatex/autolatex.conf) only. + +I a hashtable containing (attribute name, attribute value) pairs. +The attribute name could be S to describe the attribute inside +a section. + +=cut +sub readOnlyUserConfiguration(;$) { + my %configuration = (); + my $userFile = getUserConfigFilename(); + readConfigFile("$userFile",\%configuration,$_[0]); + # Remove the main intput filename + if (exists $configuration{'generation.main file'}) { + delete $configuration{'generation.main file'}; + } + return %configuration; +} + +=pod + +=item B + +Replies the current configuration. The configuration +is extracted from the project configuration file +($PROJECT_PATH/.autolatex_project.cfg) only. + +I a hashtable containing (attribute name, attribute value) pairs. +The attribute name could be S to describe the attribute inside +a section. + +=cut +sub readOnlyProjectConfiguration(@) { + my %configuration = (); + my $userFile = getProjectConfigFilename(@_); + if (-r "$userFile") { + readConfigFile("$userFile",\%configuration); + $configuration{'__private__'}{'input.project directory'} = File::Spec->catfile(@_); + return \%configuration; + } + return undef; +} + +=pod + +=item B + +Fill the configuration data structure from the specified file information. +The structure of the filled hashtable is a set of (attribute name, attribute value) pairs. +The attribute name could be S to describe the attribute inside +a section. + +I + +=over 8 + +=item * the name of the file to read + +=item * the data structure to fill + +=item * boolean value that indicates if a warning message should be ignored when an old fashion file was detected. + +=back + +I nothing + +=cut +sub readConfigFile($\%;$) { + my $filename = shift; + die('second parameter of readConfigFile() is not a hash') unless(isHash($_[0])); + printDbg(formatText(_T("Opening configuration file {}"),$filename)); + if (-r "$filename") { + my $cfgReader = new Config::Simple("$filename"); + if ($cfgReader) { + my %config = $cfgReader->vars(); + my $warningDisplayed = $_[1]; + while (my ($k,$v) = each (%config)) { + $k = lc("$k"); + if ($k !~ /^__private__/) { + ($k,$v) = ensureAccendentCompatibility("$k",$v,"$filename",$warningDisplayed); + $v = rebuiltConfigValue("$k",$v); + if ($v) { + $_[0]->{"$k"} = $v; + } + } + } + } + printDbg(_T("Succeed on reading")); + } + else { + printDbg(formatText(_T("Failed to read {}: {}"),$filename,$!)); + } + 1; +} + +# Put formatted comments inside an array +sub pushComment(\@$;$) { + my $limit = $_[2] || 60; + $limit = 1 unless ($limit>=1); + my @lines = split(/\n/, $_[1]); + foreach my $line (@lines) { + my @words = split(/\s+/, $line); + my $wline = ''; + if ($line =~ /^(\s+)/) { + $wline .= $1; + } + foreach my $w (@words) { + if ((length($wline)+length($w)+1)>$limit) { + push @{$_[0]}, "#$wline\n"; + if (length($w)>$limit) { + while (length($w)>$limit) { + push @{$_[0]}, "# ".substr($w,0,$limit)."\n"; + $w = substr($w,$limit); + } + } + $wline = " $w"; + } + else { + $wline .= " $w"; + } + } + if ($wline) { + push @{$_[0]}, "#$wline\n"; + } + } +} + +# Reformat the value to be written inside a configuration file. +# $_[0]: value name, +# $_[1]: value to validated. +sub serializeConfigValue($$) { + my $v = $_[1]; + if (isArray($v)) { + $v = ''; + foreach my $ev (@{$_[1]}) { + if ($v) { + $v .= ', '; + } + $v .= &serializeConfigValue($_[0], $ev); + } + } + elsif (isHash($v)) { + $v = ''; + while (my ($key, $value) = each(%{$_[1]})) { + if ($v) { + $v .= ', '; + } + $v .= "$key:{"; + $v .= &serializeConfigValue($_[0], $value); + $v .= "}"; + } + } + return $v; +} + +=pod + +=item B + +Write the specified configuration into a file. + +I + +=over 8 + +=item * the name of the file to write + +=item * the configuration data structure to write + +=item * (optional) indicates if the comments must be written + +=back + +I nothing + +=cut +sub writeConfigFile($\%;$) { + my $filename = shift; + die('second parameter of writeConfigFile() is not a hash') unless(isHash($_[0])); + + # Write the values + printDbg(formatText(_T("Writing configuration file {}"),$filename)); + printDbgIndent(); + my $cfgWriter = new Config::Simple(syntax=>'ini'); + my $has = 0; + while (my ($attr,$value) = each (%{$_[0]})) { + if ($value && $attr ne '__private__') { + $value = serializeConfigValue($attr, $value); + if ($value) { + $cfgWriter->param("$attr",$value); + $has = 1; + } + } + } + if ($has) { + $cfgWriter->write("$filename") or printErr($cfgWriter->error()); + + if ($_[1]) { + # Updating for comments + printDbg(_T("Adding configuration comments")); + local *CFGFILE; + open (*CFGFILE, "< $filename") or printErr("$filename:","$!"); + my @lines = (); + my $lastsection = undef; + while (my $l = ) { + if ($l =~ /^\s*\[\s*(.+?)\s*\]\s*$/) { + $lastsection = lc($1); + if ($SECTION_COMMENTS{"$lastsection"}) { + push @lines, "\n"; + pushComment @lines, $SECTION_COMMENTS{"$lastsection"}; + } + else { + push @lines, "\n"; + pushComment @lines, _T("Configuration of the translator")." '$lastsection'"; + } + } + elsif (($l =~ /^\s*(.*?)\s*=/)&&($lastsection)) { + my $attr = lc($1); + if ($CONFIGURATION_COMMENTS{"$lastsection.$attr"}) { + push @lines, "\n"; + pushComment @lines, $CONFIGURATION_COMMENTS{"$lastsection.$attr"}; + } + } + push @lines, $l; + } + close(*CFGFILE); + + printDbg(_T("Saving configuration comments")); + local *CFGFILE; + open (*CFGFILE, "> $filename") or printErr("$filename:","$!"); + print CFGFILE (@lines); + close(*CFGFILE); + } + } + else { + # Create an empty file + open (*CFGFILE, "> $filename") or printErr("$filename:","$!"); + close(*CFGFILE); + } + printDbgUnindent(); + 1; +} + +=pod + +=item B + +Fix the specified configuration file. + +I + +=over 8 + +=item * the name of the file to fix + +=back + +I nothing + +=cut +sub doConfigurationFileFixing($) { + my $filename = shift; + my %configuration = (); + + readConfigFile("$filename",%configuration,1); + + writeConfigFile("$filename",%configuration); + + 1; +} + +# Try to detect an old fashioned configuration file +# and fix the value +sub ensureAccendentCompatibility($$$$) { + my $k = $_[0]; + my $v = $_[1]; + my $changed = 0; + $v = '' unless (defined($v)); + + if ($k eq 'generation.bibtex') { + $k = 'generation.biblio'; + $changed = 1; + } + + if (!isArray($v)) { + # Remove comments on the same line as values + if ($v =~ /^\s*(.*?)\s*\#.*$/) { + $v = "$1" ; + $changed = 1; + } + + if ($v eq '@detect@system') { + $v = ['detect','system']; + $changed = 1; + } + } + + if (($changed)&&(!$_[3])) { + printWarn(formatText(_T("AutoLaTeX has detecting an old fashion syntax for the configuration file {}\nPlease regenerate this file with the command line option --fixconfig."), $_[2])); + $_[3] = 1; + } + + return ($k,$v); +} + +# Reformat the value from a configuration file to apply several rules +# which could not be directly applied by the configuration readed. +# $_[0]: value name, +# $_[1]: value to validated. +sub rebuiltConfigValue($$) { + my $v = $_[1]; + if (($_[0])&&($v)) { + my $v_str = trim($v); + # If the string "empty value" is detected, delete the value + if ($v_str eq EMPTY_INI_VALUE) { + $v = ''; + } + # Split the include path of translators + elsif ($_[0] eq 'generation.translator include path') { + my $sep = getPathListSeparator(); + if (isHash($v)) { + while (my ($key,$val) = each(%{$v})) { + my @tab = split(/\s*$sep\s*/,"$val"); + if (@tab>1) { + $v->{"$key"} = @tab; + } + else { + $v->{"$key"} = pop @tab; + } + } + } + else { + my @paths = (); + if (isArray($v)) { + foreach my $p (@{$v}) { + push @paths, split(/\s*$sep\s*/,"$p"); + } + } + else { + push @paths, split(/\s*$sep\s*/,"$v"); + } + if (@paths>1) { + $v = \@paths; + } + else { + $v = pop @paths; + } + } + } + } + return $v; +} + +=pod + +=item B + +Set the translator inclusion flags obtained from the configurations. + +This function assumed that the translator list is an hashtable of +(translator_name => { 'included' => { level => boolean } }) pairs. + +I + +=over 8 + +=item * the translator list. + +=item * the system configuration. + +=item * the user configuration. + +=item * the project configuration. + +=back + +I nothing + +=cut +sub setInclusionFlags(\%\%;\%\%) { + die('first parameter of setInclusionFlags() is not a hash') + unless (isHash($_[0])); + die('second parameter of setInclusionFlags() is not a hash') + unless (isHash($_[1])); + foreach my $trans (keys %{$_[0]}) { + if (!$_[0]->{"$trans"}{'included'}) { + $_[0]->{"$trans"}{'included'} = {}; + } + + if ((exists $_[1]->{"$trans.include module"})&&(cfgIsBoolean($_[1]->{"$trans.include module"}))) { + $_[0]->{"$trans"}{'included'}{'system'} = cfgBoolean($_[1]->{"$trans.include module"}); + } + else { + # On system level, a module which was not specified as not includable must + # be included even if it will cause conflicts + $_[0]->{"$trans"}{'included'}{'system'} = undef; + } + + if (($_[2])&& + (exists $_[2]->{"$trans.include module"})&& + (cfgIsBoolean($_[2]->{"$trans.include module"}))) { + $_[0]->{"$trans"}{'included'}{'user'} = cfgBoolean($_[2]->{"$trans.include module"}); + } + else { + $_[0]->{"$trans"}{'included'}{'user'} = undef; + } + + if (($_[3])&& + (exists $_[3]->{"$trans.include module"})&& + (cfgIsBoolean($_[3]->{"$trans.include module"}))) { + $_[0]->{"$trans"}{'included'}{'project'} = cfgBoolean($_[3]->{"$trans.include module"}); + } + else { + $_[0]->{"$trans"}{'included'}{'project'} = undef; + } + } +} + +=pod + +=item B + +Init the translator inclusion flags obtained from the configurations. + +This function assumed that the translator list is an hashtable of +(translator_name => { 'included' => { level => undef } }) pairs. + +I + +=over 8 + +=item * the translator list. + +=item * the system configuration. + +=item * the user configuration. + +=item * the project configuration. + +=back + +I nothing + +=cut +sub reinitInclusionFlags(\%\%;\%\%) { + die('first parameter of setInclusionFlags() is not a hash') + unless (isHash($_[0])); + die('second parameter of setInclusionFlags() is not a hash') + unless (isHash($_[1])); + foreach my $trans (keys %{$_[0]}) { + if (!$_[0]->{"$trans"}{'included'}) { + $_[0]->{"$trans"}{'included'} = {}; + } + + $_[0]->{"$trans"}{'included'}{'system'} = undef; + + if ($_[2]) { + $_[0]->{"$trans"}{'included'}{'user'} = undef; + } + + if ($_[3]) { + $_[0]->{"$trans"}{'included'}{'project'} = undef; + } + } +} + +1; +__END__ +=back + +=head1 BUG REPORT AND FEEDBACK + +To report bugs, provide feedback, suggest new features, etc. (in prefered order): a) visit the developer site on GitHub , b) visit the AutoLaTeX main page , or c) send email to the main author at galland@arakhne.org. + +=head1 LICENSE + +S + +=head1 COPYRIGHT + +Sgalland@arakhne.orgE> + +=head1 SEE ALSO + +L diff --git a/support/autolatex/pm/AutoLaTeX/Core/IntUtils.pm b/support/autolatex/pm/AutoLaTeX/Core/IntUtils.pm new file mode 100644 index 0000000000..7012f26a31 --- /dev/null +++ b/support/autolatex/pm/AutoLaTeX/Core/IntUtils.pm @@ -0,0 +1,201 @@ +# autolatex - IntUtils.pm +# Copyright (C) 2007-14 Stephane Galland +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +=pod + +=head1 NAME + +Locale.pm - Internationalization Utilities + +=head1 DESCRIPTION + +Provides a set of utilities for internationalization. + +To use this library, type C. + +=head1 FUNCTIONS + +The provided functions are: + +=over 4 + +=cut +package AutoLaTeX::Core::IntUtils; + +our @ISA = qw( Exporter ); +our @EXPORT = qw( &_T &initTextDomain &getCurrentLocale &getCurrentLanguage &getCurrentCodeset &getActiveTextDomains ); +our @EXPORT_OK = qw(); + +require 5.014; +use strict; +use utf8; +use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); +use Exporter; + +use Carp; +use Locale::gettext; + +our $VERSION = '1.1'; + +my @ACTIVE_DOMAINS = (); + +=pod + +=item B<_T($)> + +Marker for the internationalization. +The parameter of this function is a string that +may be localized. +Replies the localized string that is corresponding +to the given parameter. + +CAUTION: tries to find a translation in all the initialized +text domain (see initTextDomain function). + +=cut +sub _T($) { + my $previous; + foreach my $domain (@ACTIVE_DOMAINS) { + #print "SEARCH FOR '".$_[0]."' in $domain\n"; + my $p = textdomain($domain); + $previous = $p unless $previous; + my $translation = gettext($_[0]); + #print ">$translation<\n"; + if ($translation && $translation ne $_[0]) { + return $translation; + } + } + if ($previous) { + textdomain($previous); + } + return $_[0]; +} + +=pod + +=item B + +Initialize the internationalization domain. + +=over 4 + +=item domain: is the name of the text domain to use for internationalization. + +=item directory: is the directory where '.mo' (compiled '.po') could be found for the domain. + +=item codeset: is the code set used to encode the po files. + +=cut +sub initTextDomain($$;$) { + my $domain = shift || confess("initTextDomain must takes a domain as first parameter"); + my $directory = shift || confess("initTextDomain must takes a directory as second parameter"); + my $codeset = shift; + bindtextdomain($domain, $directory); + if ($codeset) { + bind_textdomain_codeset($domain, $codeset); + } + textdomain($domain); + push @ACTIVE_DOMAINS, $domain; +} + +=pod + +=item B + +Replies the active text domains. + +=cut +sub getActiveTextDomains() { + my @copy = @ACTIVE_DOMAINS; + return \@copy; +} + +=pod + +=item B + +Replies the current locale. + +=cut +sub getCurrentLocale() { + my $lang = $ENV{'LC_ALL'} || $ENV{'LANG'}; + if ($lang =~ /^([a-zA-Z]+_[a-zA-Z]+)/) { + return "$1"; + } + elsif ($lang =~ /^([a-zA-Z]+)/) { + return "$1"; + } + return undef; +} + +=pod + +=item B + +Replies the current codeset. + +=cut +sub getCurrentCodeset() { + my $lang = $ENV{'LC_ALL'} || $ENV{'LANG'}; + if ($lang =~ /^[a-zA-Z]+_[a-zA-Z]+\.(.*)$/) { + return "$1"; + } + elsif ($lang =~ /^[a-zA-Z]+\.(.*)$/) { + return "$1"; + } + return undef; +} + +=pod + +=item B + +Replies the current language. + +=cut +sub getCurrentLanguage() { + my $lang = $ENV{'LC_ALL'} || $ENV{'LANG'}; + if ($lang =~ /^([a-zA-Z]+)_[a-zA-Z]+/) { + return "$1"; + } + elsif ($lang =~ /^([a-zA-Z]+)/) { + return "$1"; + } + return undef; +} + + +1; +__END__ +=back + +=head1 BUG REPORT AND FEEDBACK + +To report bugs, provide feedback, suggest new features, etc. visit the AutoLaTeX Project management page at or send email to the author at L. + +=head1 LICENSE + +S + +=head1 COPYRIGHT + +Sgalland@arakhne.orgE> + +=head1 SEE ALSO + +L diff --git a/support/autolatex/pm/AutoLaTeX/Core/Main.pm b/support/autolatex/pm/AutoLaTeX/Core/Main.pm new file mode 100644 index 0000000000..f27e98e1ea --- /dev/null +++ b/support/autolatex/pm/AutoLaTeX/Core/Main.pm @@ -0,0 +1,542 @@ +# autolatex - Main.pm +# Copyright (C) 1998-16 Stephane Galland +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +=pod + +=head1 NAME + +Main.pm - Main program + +=head1 FUNCTIONS + +The provided functions are: + +=over 4 + +=cut +package AutoLaTeX::Core::Main; + +$VERSION = '37.0'; +$COPYRIGHT_YEAR = '2016'; +@ISA = ('Exporter'); +@EXPORT = qw( &analyzeCommandLineOptions &mainProgram &detectMainTeXFile ) ; +@EXPORT_OK = qw(); + +require 5.014; +use strict; +use utf8; +use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION $COPYRIGHT_YEAR); + +use Getopt::Long; +use File::Basename; +use AutoLaTeX::Core::Util; +use AutoLaTeX::Core::Config; +use AutoLaTeX::Core::OS; +use AutoLaTeX::Core::IntUtils; +use AutoLaTeX::TeX::DocumentDetector; + +#------------------------------------------------------ +# +# FUNCTION: analyze the command line options and update the configuration accordingly +# +#------------------------------------------------------ +sub analyzeCommandLineOptions(\%) { + printDbg(_T("Reading command line options")); + + my $realcfg = $_[0]; + $_[0]->{'__private__'}{'CLI.warning level'} = 1; + $_[0]->{'__private__'}{'config.command line'} = {}; + my $cfg = \%{$_[0]->{'__private__'}{'config.command line'}}; + my $debugLevel = getDebugLevel(); + + Getopt::Long::Configure ("bundling"); + if (!GetOptions( + + 'auto!' => sub { $cfg->{'generation.generate images'} = ($_[1] ? 'yes' : 'no'); }, + 'asyncview!' => sub { $cfg->{'viewer.asynchronous run'} = ($_[1] ? 'yes' : 'no'); }, + 'imgdirectory=s' => sub { $cfg->{'generation.image directory'} = $_[1]; }, + + 'continuous:i' => sub { + my $duration = int($_[1]); + $duration = 0 if ($duration<0); + $realcfg->{'__private__'}{'action.continuous mode'} = $duration; + $cfg->{'viewer.asynchronous run'} = 'true'; + }, + 'nocontinuous' => sub { + delete $realcfg->{'__private__'}{'action.continuous mode'}; + }, + + 'createconfig:s' => \$realcfg->{'__private__'}{'action.create config file'}, + + 'createist' => \$realcfg->{'__private__'}{'action.create ist file'}, + + 'debug' => \$realcfg->{'__private__'}{'action.create ist file'}, + + 'defaultist' => sub { + $cfg->{'generation.makeindex style'} = '@system'; + }, + + 'directory=s' => sub { + if (!$realcfg->{'__private__'}{'action.input directories'}) { + $realcfg->{'__private__'}{'action.input directories'} = []; + } + push @{$realcfg->{'__private__'}{'action.input directories'}}, $_[1]; + }, + + 'dvi' => sub { + $cfg->{'generation.generation type'} = 'dvi'; + }, + + 'biblio!' => sub { + $cfg->{'generation.biblio'} = ($_[1] ? 'yes' : 'no'); + $realcfg->{'__private__'}{'CLI.biblio'} = ($_[1] ? 'yes' : 'no'); # For makeflat action + }, + + 'exclude=s' => sub { + foreach my $module (split /\s*,\s*/,$_[1]) { + $module =~ s/[^a-zA-Z0-9_+-]+//g; + $cfg->{lc("$module").".include module"} = 'no'; + } + }, + + 'f=s' => \$realcfg->{'__private__'}{'input.latex file'}, + 'file=s' => \$realcfg->{'__private__'}{'input.latex file'}, + + 'file-line-warning' => \$realcfg->{'__private__'}{'CLI.is extended tex warnings'}, + + 'fixconfig:s' => sub { + $realcfg->{'__private__'}{'action.fix config file'} = $_[1]; + $realcfg->{'__private__'}{'action.fix config file'} = File::Spec->rel2abs($realcfg->{'__private__'}{'action.fix config file'}) if ($realcfg->{'__private__'}{'action.fix config file'}); + }, + + 'gloss!' => sub { $cfg->{'generation.makeglossaries'} = ($_[1] ? 'yes' : 'no'); }, + + 'help|?' => sub { showManual(getAutoLaTeXDocDir(),"autolatex.pod"); }, + + 'I=s@' => sub { + if (!$cfg->{'generation.translator include path'}) { + $cfg->{'generation.translator include path'} = []; + } + push @{$cfg->{'generation.translator include path'}}, $_[1]; + }, + + 'include=s' => sub { + my $sep = getPathListSeparator(); + foreach my $module (split /\s*$sep\s*/,$_[1]) { + $module =~ s/[^a-zA-Z0-9_+-]+//g; + $cfg->{lc("$module").".include module"} = 'yes'; + } + }, + + 'index:s' => sub { + if ($_[1]) { + $cfg->{'generation.makeindex style'} = $_[1]; + } + else { + $cfg->{'generation.makeindex style'} = ['@detect','@none']; + } + }, + + 'latex' => sub { + $cfg->{'generation.tex compiler'} = 'latex'; + }, + + + 'lualatex' => sub { + $cfg->{'generation.tex compiler'} = 'lualatex'; + }, + + 'noindex' => sub { + delete $cfg->{'generation.makeindex style'}; + }, + + 'noview' => sub { $cfg->{'viewer.view'} = 'no'; }, + + 'pdf' => sub { $cfg->{'generation.generation type'} = 'pdf'; }, + + 'pdflatex' => sub { + $cfg->{'generation.tex compiler'} = 'pdflatex'; + }, + + 'postcompilationruns=i' => sub { + my $number = int($_[1]); + $number = 1 if ($number<1); + $cfg->{'generation.post compilation runs'} = $number; + }, + + 'progress:s' => sub { + if ($_[1] eq 'n') { + $realcfg->{'__private__'}{'action.show progress'} = 'n'; + } + else { + $realcfg->{'__private__'}{'action.show progress'} = 'r'; + } + }, + + 'ps' => sub { + $cfg->{'generation.generation type'} = 'ps'; + }, + + 'quiet' => sub { $debugLevel = 0; }, + + 'search-project-from=s' => sub { + $realcfg->{'__private__'}{'action.search project from'} = $_[1]; + }, + + 'set=s%' => sub { $cfg->{'generation.set'}{$_[1]} = $_[2]; }, + + 'stdout' => sub { redirectToSTDOUT(); }, + + 'stderr' => sub { redirectToSTDERR(); }, + + 'synctex!' => sub { $cfg->{'generation.synctex'} = ($_[1] ? 'yes' : 'no'); }, + + 'xelatex' => sub { + $cfg->{'generation.tex compiler'} = 'xelatex'; + }, + + 'v+' => \$debugLevel, + + 'version' => sub { if (getAutoLaTeXLaunchingName() ne getAutoLaTeXName()) { + print formatText(_T("{} {} ({}) - {} platform\n(c) 1998-{} Stephane GALLAND (under GPL)\n"), + getAutoLaTeXLaunchingName(), + getAutoLaTeXVersion(), + getAutoLaTeXName(), + getOperatingSystem(), + $COPYRIGHT_YEAR); + } + else { + print formatText(_T("{} {} - {} platform\n(c) 1998-{} Stephane GALLAND (under GPL)\n"), + getAutoLaTeXLaunchingName(), + getAutoLaTeXVersion(), + getOperatingSystem(), + $COPYRIGHT_YEAR); + } + exit(0); }, + + 'view:s' => sub { + $cfg->{'viewer.view'} = 'yes'; + if ($_[1]) { + $cfg->{'viewer.viewer'} = $_[1]; + } + }, + + 'W' => sub { + $realcfg->{'__private__'}{'CLI.warning level'}++; + }, + 'Wall' => sub { + $realcfg->{'__private__'}{'CLI.warning level'} = 2; + }, + 'Wnone' => sub { + $realcfg->{'__private__'}{'CLI.warning level'} = 0; + }, + + )) { + exit(255); + } + + setDebugLevel($debugLevel); +} + +#------------------------------------------------------ +# +# FUNCTION: Seach for a TeX main file in the current directory +# +# Requires $_[0]->{__private__}{output.directory} +# Set $_[0]->{__private__}{input.latex file} +# +#------------------------------------------------------ +sub detectMainTeXFile(\%) { + my $configuration = shift; + local *DIR; + opendir(*DIR,$configuration->{'__private__'}{'output.directory'}) or printErr($configuration->{'__private__'}{'output.directory'}.":","$!"); + my @texfiles = (); + while (my $subfile = readdir(*DIR)) { + if ((!isIgnorableDirectory($subfile)) && $subfile =~ /\.tex$/i && $subfile ne 'autolatex_autogenerated.tex') { + push @texfiles, "$subfile"; + } + } + closedir(*DIR); + if (@texfiles==1) { + my $basename = pop @texfiles; + $configuration->{'__private__'}{'input.latex file'} = + File::Spec->catfile( + $configuration->{'__private__'}{'output.directory'}, + $basename); + printDbg(formatText(_T("Selecting TeX file '{}'"), $basename)); + } + else { + printDbg(formatText(_T("Detecting several TeX files: {}"),join(' ',@texfiles))); + # Issue #9: try to detect the file with the \documentclass + my @documents = (); + foreach my $file (@texfiles) { + if (isLaTeXDocument($file)) { + push @documents, $file; + } + } + if (@documents==1) { + my $basename = pop @documents; + $configuration->{'__private__'}{'input.latex file'} = + File::Spec->catfile( + $configuration->{'__private__'}{'output.directory'}, + $basename); + printDbg(formatText(_T("Selecting TeX file '{}'"), $basename)); + } + } +} + +#------------------------------------------------------ +# +# FUNCTION: Main program +# +#------------------------------------------------------ +sub mainProgram(;$) { + my $exitOnError = shift; + $exitOnError = 1 if (!defined($exitOnError)); + # Get system and user configurations + my %configuration = readConfiguration(); + + # Put the internationalization values in the configuration + $configuration{'__private__'}{'internationalization'}{'locale'} = getCurrentLocale(); + $configuration{'__private__'}{'internationalization'}{'language'} = getCurrentLanguage(); + $configuration{'__private__'}{'internationalization'}{'codeset'} = getCurrentCodeset(); + $configuration{'__private__'}{'internationalization'}{'domains'} = getActiveTextDomains(); + + # Analyze and apply the command line + analyzeCommandLineOptions(%configuration); + + # -- Bug fix: avoid the "No TeX file found" error message to be + # displayed when a non-generation action was requested + # on the command line + if (($exitOnError)&& + (($configuration{'__private__'}{'action.fix config file'})|| + ($configuration{'__private__'}{'action.create config file'})|| + ($configuration{'__private__'}{'action.create ist file'}))) { + $exitOnError = 0; + } + + # Search for the root directory + if ($configuration{'__private__'}{'action.search project from'}) { + my $file = $configuration{'__private__'}{'action.search project from'}; + if (-e "$file" && ! -d "$file") { + $file = dirname($file); + } + $file = File::Spec->rel2abs($file); + my $autolatex_dir = undef; + my $parent = dirname($file); + while (!$autolatex_dir && $parent && $file && $parent ne $file) { + my $cfgFile = getProjectConfigFilename($file); + if (-e "$cfgFile") { + $autolatex_dir = $file; + } + $file = $parent; + $parent = dirname($file); + } + if ($autolatex_dir && -d "$autolatex_dir") { + chdir($autolatex_dir) or printErr("$autolatex_dir: $!"); + } + } + + # detect main TeX file + $configuration{'__private__'}{'output.directory'} = File::Spec->curdir(); + $configuration{'__private__'}{'output.latex basename'} = undef; + + if (!$configuration{'__private__'}{'input.latex file'}) { + detectMainTeXFile(%configuration); + } + + # read project's configuration + { + my $projectConfigFilename = getProjectConfigFilename($configuration{'__private__'}{'output.directory'}); + if ( -f "$projectConfigFilename") { + readConfigFile("$projectConfigFilename",%configuration); + + # Remove the main intput filename + if (exists $configuration{'generation.main file'}) { + if (!$configuration{'__private__'}{'input.latex file'}) { + $configuration{'__private__'}{'input.latex file'} = basename($configuration{'generation.main file'}); + printDbg(formatText(_T("Detecting TeX file from project's configuration: '{}'"),$configuration{'__private__'}{'input.latex file'})); + } + delete $configuration{'generation.main file'}; + } + $configuration{'__private__'}{'input.project directory'} = dirname("$projectConfigFilename"); + } + } + + if (!$configuration{'__private__'}{'input.latex file'}) { + $configuration{'__private__'}{'input.latex file'} = 'Main.tex'; + } + + # final project main file management + if ($configuration{'__private__'}{'input.latex file'}) { + # check its value + if (-f $configuration{'__private__'}{'input.latex file'}) { + $configuration{'__private__'}{'output.directory'} = dirname($configuration{'__private__'}{'input.latex file'}); + $configuration{'__private__'}{'output.latex basename'} = basename($configuration{'__private__'}{'input.latex file'}); + $configuration{'__private__'}{'output.latex basename'} =~ s/\.tex$//i; + } + elsif (-f $configuration{'__private__'}{'input.latex file'}.".tex") { + $configuration{'__private__'}{'input.latex file'} .= ".tex"; + $configuration{'__private__'}{'output.directory'} = dirname($configuration{'__private__'}{'input.latex file'}); + $configuration{'__private__'}{'output.latex basename'} = basename($configuration{'__private__'}{'input.latex file'}); + } + } + + if ($configuration{'__private__'}{'input.latex file'}) { + printDbg(formatText(_T("Using TeX file '{}'"),$configuration{'__private__'}{'input.latex file'})); + } + elsif ($exitOnError) { + printErr(formatText(_T("No LaTeX file found nor specified for the directory '{}'.\n You must specify one on the command line option -f, or set the the variable 'generation.main file' in your configuration file, rename one of your files 'Main.tex'."), $configuration{'__private__'}{'output.directory'})); + } + + # now apply the command line options into the configuration + { + printDbg(_T("Applying command line options")); + if ($configuration{'__private__'}{'config.command line'}) { + while (my ($k,$v) = each(%{$configuration{'__private__'}{'config.command line'}})) { + if (isArray($v)) { + if (!$configuration{"$k"}) { + $configuration{"$k"} = $v; + } + elsif (isHash($configuration{"$k"})) { + for(my $i=0; $i<$#{$v}; $i=$i+2) { + $configuration{"$k"}{$v->[$i]} = $v->[$i+1]; + } + } + elsif (isArray($configuration{"$k"})) { + push @{$configuration{"$k"}}, @{$v}; + } + else { + unshift @{$v}, $configuration{"$k"}; + $configuration{"$k"} = $v; + } + } + elsif (isHash($v)) { + if (!$configuration{"$k"}) { + $configuration{"$k"} = $v; + } + elsif (isArray($configuration{"$k"})) { + push @{$configuration{"$k"}}, @{$v}; + } + elsif (isHash($configuration{"$k"})) { + while (my ($key,$val) = each(%{$v})) { + $configuration{"$k"}{$key} = $val; + } + } + else { + $v->{$configuration{"$k"}} = undef; + $configuration{"$k"} = $v; + } + } + else { + $configuration{"$k"} = $v; + } + } + if ($configuration{'generation.set'}) { + while (my ($k,$v) = each(%{$configuration{'generation.set'}})) { + $configuration{$k} = $v; + } + delete $configuration{'generation.set'} + } + delete $configuration{'__private__'}{'config.command line'}; + } + } + + # check MakeIndex parameters + if ($configuration{'generation.makeindex style'}) { + if (!isArray($configuration{'generation.makeindex style'})) { + $configuration{'generation.makeindex style'} = [$configuration{'generation.makeindex style'}]; + } + foreach my $isttype (@{$configuration{'generation.makeindex style'}}) { + if ($isttype) { + if ($isttype eq '@detect') { + # Seach for a MakeIndex style file in the current directory + local *DIR; + opendir(*DIR,$configuration{'__private__'}{'output.directory'}) or printErr($configuration{'__private__'}{'output.directory'}.":","$!"); + my @istfiles = (); + while (my $subfile = readdir(*DIR)) { + if (!isIgnorableDirectory($subfile) && $subfile =~ /\.ist$/i) { + push @istfiles, File::Spec->catfile( + $configuration{'__private__'}{'output.directory'}, + "$subfile"); + } + } + closedir(*DIR); + if (@istfiles==1) { + $configuration{'__private__'}{'output.ist file'} = File::Spec->rel2abs(pop @istfiles); + printDbg(formatText(_T("Selecting project's style for MakeIndex: {}"), $configuration{'__private__'}{'output.ist file'})); + } + else { + delete $configuration{'__private__'}{'output.ist file'}; + printDbg(formatText(_T("Unable to selected a project's style for MakeIndex: no file or too many .ist files in directory {}"), $configuration{'__private__'}{'output.directory'})); + } + } + elsif ($isttype eq '@system') { + $configuration{'__private__'}{'output.ist file'} = getSystemISTFilename(); + printDbg(formatText(_T("Selecting the system default style for MakeIndex"))); + } + elsif ($isttype eq '@none') { + delete $configuration{'__private__'}{'output.ist file'}; + printDbg(formatText(_T("Unselecting any style for MakeIndex"))); + } + + if (($configuration{'__private__'}{'output.ist file'})&& + (-r $configuration{'__private__'}{'output.ist file'})) { + last; + } + else { + delete $configuration{'__private__'}{'output.ist file'}; + } + } + } + } + + # set the project's directory if never set before + if (!$configuration{'__private__'}{'input.project directory'} && + $configuration{'__private__'}{'input.latex file'}) { + $configuration{'__private__'}{'input.project directory'} = File::Spec->rel2abs(dirname($configuration{'__private__'}{'input.latex file'})); + } + + # Set the directory of the pictures to a default value if not defined in + # the configuration nor given on the CLI + if (! defined($configuration{'generation.image directory'})) { + $configuration{'generation.image directory'} = $configuration{'__private__'}{'input.project directory'}; + } + + return %configuration; +} + +1; +__END__ +=back + +=head1 BUG REPORT AND FEEDBACK + +To report bugs, provide feedback, suggest new features, etc. visit the AutoLaTeX Project management page at or send email to the author at L. + +=head1 LICENSE + +S + +=head1 COPYRIGHT + +Sgalland@arakhne.orgE> + +=head1 SEE ALSO + +L diff --git a/support/autolatex/pm/AutoLaTeX/Core/OS.pm b/support/autolatex/pm/AutoLaTeX/Core/OS.pm new file mode 100644 index 0000000000..f33dcf69ff --- /dev/null +++ b/support/autolatex/pm/AutoLaTeX/Core/OS.pm @@ -0,0 +1,555 @@ +# autolatex - OS.pm +# Copyright (C) 1998-13 Stephane Galland +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +=pod + +=head1 NAME + +OS.pm - Operating System + +=head1 DESCRIPTION + +Identify the current operating system. + +To use this library, type C. + +=head1 FUNCTIONS + +The provided functions are: + +=over 4 + +=cut +package AutoLaTeX::Core::OS; + +$VERSION = '5.0'; +@ISA = ('Exporter'); +@EXPORT = qw( &getPathListSeparator &getOperatingSystem &getSupportedOperatingSystems &which + &touch &readlink_osindep &parseCLI &parseCLIWithExceptions &lastFileChange ) ; +@EXPORT_OK = qw(); + +require 5.014; +use strict; +use utf8; +use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); +use Config; # Perl configuration +use File::stat; +use File::Basename; +use File::Path qw(make_path); + +my %operatingsystem = + (MacOS => 'Mac', + MSWin32 => 'Win32', + os2 => 'OS2', + VMS => 'VMS', + epoc => 'Epoc', + NetWare => 'Win32', + symbian => 'Win32', + dos => 'OS2', + cygwin => 'Cygwin'); + +my $Is_VMS = ($^O eq 'VMS'); +my $Is_MacOS = ($^O eq 'MacOS'); +my $Is_DOSish = (($^O eq 'MSWin32') or + ($^O eq 'dos') or + ($^O eq 'os2')); + +# For Win32 systems, stores the extensions used for +# executable files +# For others, the empty string is used +# because 'perl' . '' eq 'perl' => easier +my @path_ext = (''); +if ($Is_DOSish) { + if ($ENV{PATHEXT} and $Is_DOSish) { # WinNT. PATHEXT might be set on Cygwin, but not used. + push @path_ext, split ';', $ENV{PATHEXT}; + } + else { + push @path_ext, qw(.com .exe .bat); # Win9X or other: doesn't have PATHEXT, so needs hardcoded. + } +} +elsif ($Is_VMS) { + push @path_ext, qw(.exe .com); +} + +=pod + +=item B + +Replies the separator of paths inside a path list. + +I the separator. + +=cut +sub getPathListSeparator() { + return $Config{'path_sep'} || ':'; +} + +=pod + +=item B + +Replies the name of the current operating system. + +I the name. + +=cut +sub getOperatingSystem() { + return $operatingsystem{$^O} || 'Unix'; +} + +=pod + +=item B + +Replies all the names of the supported operating systems. + +I the list of operating system's names. + +=cut +sub getSupportedOperatingSystems() { + my %list = (); + foreach my $v (values %operatingsystem) { + $list{"$v"} = 1; + } + return keys %list; +} + +sub expandShellCharsOnUnix(@) { + my $t = shift; + if ($t) { + my @parts = File::Spec->splitdir("$t"); + foreach my $e (@parts) { + if ($e eq '~') { + $e = $ENV{'HOME'}; + } + elsif ($e =~ /^~([a-zA-Z_][a-zA-Z_0-9]*)$/) { + my @p = File::Spec->split($ENV{'HOME'}); + pop @p; + $e = File::Spec->catdir(@p); + } + } + $t = File::Spec->catfile(@parts); + $t =~ s/\$([a-zA-Z_][a-zA-Z_0-9]*)/$ENV{$1}/g; + $t =~ s/\$\{([a-zA-Z_][a-zA-Z_0-9]*)\}/$ENV{$1}/g; + $t =~ s/\$\(([a-zA-Z_][a-zA-Z_0-9]*)\)/$ENV{$1}/g; + } + return $t; +} + +sub expandShellCharsOnWindows(@) { + my $t = shift; + if ($t) { + $t =~ s/\%{1,2}([a-zA-Z_][a-zA-Z_0-9]*)/$ENV{$1}/g; + $t =~ s/\%{1,2}\{([a-zA-Z_][a-zA-Z_0-9]*)\}/$ENV{$1}/g; + $t =~ s/\%{1,2}\(([a-zA-Z_][a-zA-Z_0-9]*)\)/$ENV{$1}/g; + } + return $t; +} + +=pod + +=item B + +Expand the specified value with the Shell metacommands. + +I + +=over 8 + +=item * the string to expand. + +=back + +I the result of the epxansion. + +=cut +sub expandShellChars($) { + my $operatingsystem = getOperatingSystem(); + if (("$operatingsystem" eq 'Unix')||(("$operatingsystem" eq 'Cygwin'))) { + return expandShellCharsOnUnix(@_); + } + else { + return expandShellCharsOnWindows(@_); + } +} + +=pod + +=item B + +Replies the paths to executable programs on systems under which the `which' program wasn't implemented in the shell. + +C searches the directories of the user's C (as returned by +Cpath()>), looking for executable files having the name specified +as a parameter to C. Under Win32 systems, which do not have a notion of +directly executable files, but uses special extensions such as C<.exe> and +C<.bat> to identify them, C takes extra steps to assure that you +will find the correct file (so for example, you might be searching for C, +it'll try C, C, etc.) + +If it finds an executable with the name you specified, C will return +the absolute path leading to this executable (for example, C or +C). + +If it does I find the executable, it returns C. + +If C is called in list context, it will return I the +matches. + +=over 4 + +=item C is the name used in the shell to call the program (for example, C). + +=back + +=cut +sub which(@) { + my ($exec) = @_; + + return undef unless $exec; + + my $all = wantarray; + my @results = (); + + # check for aliases first + if ($Is_VMS) { + my $symbol = `SHOW SYMBOL $exec`; + chomp($symbol); + if (!$?) { + return $symbol unless $all; + push @results, $symbol; + } + } + if ($Is_MacOS) { + my @aliases = split /\,/, $ENV{Aliases}; + foreach my $alias (@aliases) { + # This has not been tested!! + # PPT which says MPW-Perl cannot resolve `Alias $alias`, + # let's just hope it's fixed + if (lc($alias) eq lc($exec)) { + chomp(my $file = `Alias $alias`); + last unless $file; # if it failed, just go on the normal way + return $file unless $all; + push @results, $file; + # we can stop this loop as if it finds more aliases matching, + # it'll just be the same result anyway + last; + } + } + } + + my @path = File::Spec->path(); + unshift @path, File::Spec->curdir if $Is_DOSish or $Is_VMS or $Is_MacOS; + + for my $base (map { File::Spec->catfile($_, $exec) } @path) { + for my $ext (@path_ext) { + my $file = $base.$ext; + # print STDERR "$file\n"; + + if ((-x $file or # executable, normal case + ($Is_MacOS || # MacOS doesn't mark as executable so we check -e + ($Is_DOSish and grep { $file =~ /$_$/i } @path_ext[1..$#path_ext]) + # DOSish systems don't pass -x on non-exe/bat/com files. + # so we check -e. However, we don't want to pass -e on files + # that aren't in PATHEXT, like README. + and -e _) + ) and !-d _) + { # and finally, we don't want dirs to pass (as they are -x) + + # print STDERR "-x: ", -x $file, " -e: ", -e _, " -d: ", -d _, "\n"; + + return $file unless $all; + push @results, $file; # Make list to return later + } + } + } + + if($all) { + return @results; + } + else { + return undef; + } +} + +=pod + +=item B + +Change the time associated to the specified files. + +=cut +sub touch(@) { + #my ($atime, $mtime); + #$atime = $mtime = time; + foreach my $f (@_) { + make_path(dirname("$f")); + if (-e "$f") { + utime(undef, undef, "$f"); + } + else { + local *FILE; + open(*FILE, "> $f") or die("$f: $!\n"); + close(*FILE); + } + } +} + +=pod + +=item B + +Try to dereference symbolic links. + +=cut +sub _readlink($) { + my $f = shift; + while ( $f && -l "$f" ) { + $f = readlink("$f"); + } + return $f; +} +sub readlink_osindep(@) { + if (wantarray) { + my @result = (); + foreach my $s (@_) { + push @result, _readlink($s); + } + return @result; + } + else { + if ($_[0]) { + return _readlink($_[0]); + } + return undef; + } +} + +=pod + +=item B + +Parse the given strings as command lines and extract each component. +The components are separated by space characters. If you want a +space character inside a component, you muse enclose the component +with quotes. To have quotes in components, you must protect them +with the backslash character. +This function expand the environment variables. + +I Every paramerter that is an associative array is assumed to be an +environment of variables that should be used prior to C<@ENV> to expand the +environment variables. The elements in the parameter are treated from the +first to the last. Each time an environment was found, it is replacing any +previous additional environment. + +I + +=over 8 + +=item * c are the strings to parse. + +=back + +I the array of components if one string is given as parameter; or the array of arrays of components, +each sub array corresponds to one of the given parameters. + +=cut +sub parseCLI(@) { + my %e = (); + my @r = (); + my $addenv = undef; + if (@_>1) { + foreach my $s (@_) { + if (_ishash($s)) { + $addenv = $s; + } + else { + my @rr = _parseCLI($s,\%e,$addenv); + push @r, \@rr; + } + } + if (@r==1) { + @r = @{$r[0]}; + } + } + elsif (@_>0 && !_ishash($_[0])) { + @r = _parseCLI($_[0],\%e,$addenv); + } + return @r; +} + +=pod + +=item B + +Parse the given strings as command lines and extract each component. +The components are separated by space characters. If you want a +space character inside a component, you muse enclose the component +with quotes. To have quotes in components, you must protect them +with the backslash character. +This function expand the environment variables. + +I Every paramerter that is an associative array is assumed to be an +environment of variables that should be used prior to C<@ENV> to expand the +environment variables. The elements in the parameter are treated from the +first to the last. Each time an environment was found, it is replacing any +previous additional environment. + +I + +=over 8 + +=item * c are the names of the environment variables to not expand. + +=item * c are the strings to parse. + +=back + +I the array of components if one string is given as parameter; or the array of arrays of components, +each sub array corresponds to one of the given parameters. + +=cut +sub parseCLIWithExceptions(\@@) { + my $e = shift; + my %ex = (); + my $addenv = undef; + foreach my $e (@{$e}) { + $ex{$e} = undef; + } + my @r = (); + if (@_>1) { + foreach my $s (@_) { + if (_ishash($s)) { + $addenv = $s; + } + else { + my @rr = _parseCLI($s,\%ex,$addenv); + push @r, \@rr; + } + } + if (@r==1) { + @r = @{$r[0]}; + } + } + elsif (@_>0 && !_ishash($_[0])) { + @r = _parseCLI($_[0],\%ex,$addenv); + } + return @r; +} + +sub _parseCLI($$$) { + my $text = shift; + my $exceptions = shift; + my $addenv = shift; + my @r = (); + if ($text) { + $text =~ s/^\s+//gs; + $text =~ s/\s+$//gs; + if ($text) { + my $protect = ''; + my $value = ''; + while ($text && $text =~ /^(.*?)(["']|(?:\s+)|(?:\\.)|(?:\$[a-zA-Z0-9_]+)|(?:\$\{[a-zA-Z0-9_]+\}))(.*)$/s) { + (my $prefix, my $sep, $text) = ($1, $2, $3); + $value .= $prefix; + if ($sep =~ /^\\(.)$/) { + $value .= $1; + } + elsif ($sep =~ /^\$(?:([a-zA-Z0-9_]+))|(?:\{([a-zA-Z0-9_]+)\})$/) { + my $varname = $1 || $2; + if ($protect eq '\'' || exists $exceptions->{"$varname"}) { + $value .= $sep; + } + elsif ($addenv && exists $addenv->{$varname}) { + $value .= ($addenv->{$varname} || ''); + } + else { + $value .= ($ENV{$varname} || ''); + } + } + elsif ($sep eq '"' || $sep eq '\'') { + if (!$protect) { + $protect = $sep; + } + elsif ($protect eq $sep) { + $protect = ''; + } + else { + $value .= $sep; + } + } + elsif ($protect) { + $value .= $sep; + } + elsif ($value) { + push @r, $value; + $value = ''; + } + } + if ($text) { + $value .= $text; + } + if ($value) { + push @r, $value; + } + } + } + return @r; +} + +sub _ishash($) { + return 0 unless defined($_[0]) ; + my $r = ref( $_[0] ) ; + return ( $r eq "HASH" ) ; +} + +=pod + +=item B + +Replies the date of the last change for the specified file. +If the file does not exist, C is replied. + +=cut +sub lastFileChange($) { + my $file = shift; + return undef unless ($file); + my $stats = stat("$file"); + return undef unless ($stats); + return ($stats->mtime > $stats->ctime) ? $stats->mtime : $stats->ctime; +} + + +1; +__END__ +=back + +=head1 BUG REPORT AND FEEDBACK + +To report bugs, provide feedback, suggest new features, etc. visit the AutoLaTeX Project management page at or send email to the author at L. + +=head1 LICENSE + +S + +=head1 COPYRIGHT + +Sgalland@arakhne.orgE> + +=head1 SEE ALSO + +L diff --git a/support/autolatex/pm/AutoLaTeX/Core/Progress.pm b/support/autolatex/pm/AutoLaTeX/Core/Progress.pm new file mode 100644 index 0000000000..1e7b27ed9e --- /dev/null +++ b/support/autolatex/pm/AutoLaTeX/Core/Progress.pm @@ -0,0 +1,535 @@ +# autolatex - Progress.pm +# Copyright (C) 2013 Stephane Galland +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +=pod + +=head1 NAME + +Progress.pm - Implementation of a progress indicator + +=head1 DESCRIPTION + +Provides a tool to show the progress of the tasks. + +To use this library, type C. + +=head1 GETTING STARTED + +=head2 Initialization + +To create a progress tool, say something like this: + + use AutoLaTeX::Core::Progress; + + my $max = 100; + my $progress = AutoLaTeX::Core::Progress->new($max) ; + +...or something similar. + +=head1 METHOD DESCRIPTIONS + +This section contains only the methods in Progress.pm itself. + +=over + +=cut +package AutoLaTeX::Core::Progress; + +our @ISA = qw( Exporter ); +our @EXPORT = qw( ); +our @EXPORT_OK = qw(); + +require 5.014; +use strict; +use utf8; +use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); +use Exporter; +use Carp; +use AutoLaTeX::Core::IntUtils; +use AutoLaTeX::Core::Util qw($INTERNAL_MESSAGE_PREFIX); + +our $VERSION = '4.0'; + +#------------------------------------------------------ +# +# Constructor +# +#------------------------------------------------------ + +sub new(;$) : method { + my $proto = shift; + my $class = ref($proto) || $proto; + my $parent = ref($proto) && $proto ; + my $max = $_[0]; + if (!defined($max) || $max<0) { + $max = 100; + } + my $self; + if ( $parent ) { + %{$self} = %{$parent} ; + } + else { + $self = { + 'child' => undef, + 'max' => $max, + 'value' => 0, + 'parent' => undef, + 'bar-width' => 30, + 'comment' => '', + 'comment-to-display' => '', + 'previous-message-size' => 0, + 'carriage-return' => 1, + }; + } + bless( $self, $class ); + + return $self; +} + +sub _newChild($$$) : method { + my $proto = shift; + my $class = ref($proto) || $proto; + my $parent = shift; + my $min = shift; + my $max = shift; + my $self = { + 'child' => undef, + 'value' => 0, + 'parent' => $parent, + 'min-in-parent' => $min, + 'max-in-parent' => $max, + 'max' => 0, + 'comment' => '', + }; + bless( $self, $class ); + return $self; +} + +=pod + +=item * setCarriageReturn($) + +Enable or disable the use of the carraige-return character +C<\r> at the end of the lines. If the carriage-return +character is not used, the new-line character C<\n> is +used. + +=over 4 + +=item B + +=over + +=cut +sub setCarriageReturn($) : method { + my $self = shift; + $self->{'carriage-return'} = shift; +} + +=pod + +=item * getCarriageReturn() + +Replies if the carriage-return character is used at the end +of the output lines. + +=cut +sub getCarriageReturn() : method { + my $self = shift; + return $self->{'carriage-return'}; +} + +=pod + +=item * setBarWidth($) + +Set the number of characters for rendering the progress bar. + +=over 4 + +=item B is the number of characters of the bar. + +=over + +=cut +sub setBarWidth($) : method { + my $self = shift; + my $width = shift; + if ($self->{'parent'}) { + $self->{'parent'}->setBarWidth($width); + } + else { + $self->{'bar-width'} = $width; + } +} + +=pod + +=item * getBarWidth() + +Replies the number of characters for rendering the progress bar. + +=cut +sub getBarWidth() : method { + my $self = shift; + if ($self->{'parent'}) { + return $self->{'parent'}->getBarWidth(); + } + else { + return $self->{'bar-width'}; + } +} + +=pod + +=item * setComment($) + +Set the comment associated to the progress process. + +=over 4 + +=item B