#!/usr/bin/perl #***************************************************************************** # # ooffice - Wrapper script for OpenOffice.org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2, as # published by the Free Software Foundation. # # 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; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # #***************************************************************************** use strict; use XML::Twig; use MDK::Common; # Define OpenOffice.org version my $Version = "<OOVERSION>"; # Define user OOo versions file my $VersionFile = "$ENV{HOME}/.sversionrc"; # Define system installation directory my $SystemInstallDir = "/usr/lib/openoffice"; # Define user installation directory my $UserInstallDir = "$ENV{HOME}/.openoffice"; # Define user work directory ($HOME directory) my $UserWorkDir = "$ENV{HOME}"; # Define chkfontpath program my $ChkfontpathProgram = "/usr/sbin/chkfontpath"; # Define OOo setup program my $SetupProgram = "$SystemInstallDir/program/setup"; # Define setup autoresponse file for user installation my $SetupConfig = "/etc/openoffice/autoresponse.conf"; # Define user Setup.xml file my $SetupXML = "$UserInstallDir/user/config/registry/instance/org/openoffice/Setup.xml"; # Define user Common.xml file my $CommonXML = "$UserInstallDir/user/config/registry/instance/org/openoffice/Office/Common.xml"; # Define user Linguistic.xml file my $LinguisticXML = "$UserInstallDir/user/config/registry/instance/org/openoffice/Office/Linguistic.xml"; # Define global Linguistic.xml file my $SystemLinguisticXML = "$SystemInstallDir/share/config/registry/instance/org/openoffice/Office/Linguistic.xml"; # Define system ooffice script config my $SystemOOfficeRC = "/etc/openoffice/openoffice.conf"; # Define user ooffice script config my $OOfficeRC = "$ENV{HOME}/.oofficerc"; # Define system psprint.conf my $SystemPsprintConf = "$SystemInstallDir/share/psprint/psprint.conf"; # Define user psprint.conf my $PsprintConf = "$UserInstallDir/user/psprint/psprint.conf"; # Define if debug mode my $Debug = 0; #============================================================================= # Print debug output #============================================================================= sub debug { print @_ if ($Debug); } #============================================================================= # Read versions config file #============================================================================= sub ReadVersionFile($) { my ($file) = @_; my $e; my %entries; foreach (cat_("$file")) { chomp; if (/^\[(\w+)\]/) { $entries{$1} = $e = { }; } elsif (/^([^=]+)=([^\r\n]+)/) { $e->{$1} = $2; } } %entries; } #============================================================================= # Write versions config file #============================================================================= sub DoWriteVersionFile(%$) { my ($config, $file) = @_; local *F; if ($file) { open F, ">$file" or die "Cant write to $file\n"; select F; } local $\ = "\n"; while (my ($secname, $secvars) = each %$config) { print "[$secname]"; while (my ($key, $value) = each %$secvars) { print "$key=$value"; } print; } if ($file) { close F; select STDOUT; } } sub DumpVersionFile(%) { my (%config) = @_; DoWriteVersionFile \%config; } sub WriteVersionFile(%) { my (%config) = @_; DoWriteVersionFile \%config, "$VersionFile"; } #============================================================================= # Define default language -> country mappings #============================================================================= sub CountryOfLanguage($) { my ($lang) = @_; # Note if language is not in the table of exceptions below, it is # assumed that country is uc $lang my %countryOf = ("en" => "US", "cs" => "CZ", "ca" => "ES", "da" => "DK", "el" => "GR", "ja" => "JP", "ko" => "KR", "sv" => "SE"); $countryOf{$lang} || uc $lang; } #============================================================================= # Main #============================================================================= # Get global and user configs (user config file has precedence over system config). my %OOfficeConfig = (if_(-f "$SystemOOfficeRC", getVarsFromSh("$SystemOOfficeRC")), if_(-f "$OOfficeRC", getVarsFromSh("$OOfficeRC"))); # Parse command line arguments my @ooo_argv; my $override_lang; while ($ARGV[0]) { $_ = shift; if (m/^--lang(=(\S+))?/) { $override_lang = $2 || shift; } else { push @ooo_argv, $_; } } push @ooo_argv, "private:factory/s$1" if (!@ooo_argv && $0 =~ m/\/oo(calc|draw|impress|math|writer)$/); # Get current language code my $lang = $override_lang || $ENV{LC_MESSAGES} || $ENV{LANG} || "en_US"; $lang =~ tr/-/_/; $lang .= "_" . CountryOfLanguage $lang if ($lang !~ /_/); (my $isocode = $lang) =~ s/([a-z]+)_.*/\1/; (my $oolang = $lang) =~ tr/_/-/; # Remove any stale entry from versions file, if OOo was not already # installed from an MDK package. if ( -r "$VersionFile" ) { my %config = ReadVersionFile "$VersionFile"; my $versions = $config{Versions}; my $home = $versions->{"OpenOffice.org $Version"}; if ($home && $home ne "file://$UserInstallDir") { foreach (keys %$versions) { delete $versions->{$_} if ($versions->{$_} eq $home); } WriteVersionFile %config; } } # Perform a user installation, if necessary. if ( ! -d $UserInstallDir || ! -e "$UserInstallDir/soffice" || ! -e "$UserInstallDir/spadmin" ) { # First, make sure to remove any reference to $UserInstallDir, from older # (and broken) installation if ( -f $VersionFile ) { my %config = ReadVersionFile "$VersionFile"; my $versions = $config{Versions}; my $changed = 0; foreach (keys %$versions) { if ($versions->{$_} eq "file://$UserInstallDir") { delete $versions->{$_}; $changed = 1; } } WriteVersionFile %config if ($changed); } # We can safely do the installation now die "Installation of OpenOffice.org $Version failed\n" if (system("$SetupProgram -R:$SetupConfig -LANG:$isocode")); } # Clean the installation version tags. if ( -f "$VersionFile" ) { my %config = ReadVersionFile "$VersionFile"; my $versions = $config{Versions}; my $changed = 0; foreach (keys %$versions) { if ($_ =~ /^OpenOffice.org [.0-9]+/ && $_ ne "OpenOffice.org $Version") { delete $versions->{$_}; $changed = 1; } } # Add current version tag if it does not exist already. This # occurs when you upgrade from 1.0 to 1.0.1 for example. $versions->{"OpenOffice.org $Version"} = "file://$UserInstallDir" if (!$versions->{"OpenOffice.org $Version"}); WriteVersionFile %config if ($changed); } else { # The versions file is bound to exist unless we (or the user) # nuked it somehow. Regenerate it. We already have the # installation directory at this point. WriteVersionFile Versions => { "OpenOffice.org $Version" => "file://$UserInstallDir" }; } # Remove broken links and previous dictionaries symlinks. # As of 1.0.1-1mdk, dictionaries stuff is global in /usr/share/dict/ooo. my @stale_dictentries; foreach (glob_("$UserInstallDir/user/wordbook/*.aff")) { if ( -l $_ ) { (my $entry = $_) =~ s|.*/([^/]+)\.aff|\1|; push @stale_dictentries, $entry; unlink $_, ((dirname $_) . "/$entry.dic"); } } my $dict_list = "$UserInstallDir/user/wordbook/dictionary.lst"; my $dict_pattern = join "|", @stale_dictentries; substInFile { s|^(\s*DICT.*\s($dict_pattern))$|\# Removed: \1| } "$dict_list" if ( $dict_pattern && -f "$dict_list" ); # Remove dictionary.lst if it no longer contains any valid dictionary # (DICT) or hyphenation (HYPH) entries. unlink "$dict_list" if ( ! grep /^\s*(DICT|HYPH)/, cat_("$dict_list") ); # Expand TrueType and Type1 font paths my @exclude_fontpaths = ( "/usr/share/fonts/ttf/japanese" ); my @fontpath; if ( ! -x "$ChkfontpathProgram" ) { # OOo now correctly grabs chkfontpath output, so only add # "well-known" TrueType and Type1 font paths if that program is # not available push @fontpath, grep { -d $_ && (! member $_, @exclude_fontpaths ) } ( glob_("/usr/share/fonts/ttf/*"), "/usr/X11R6/lib/X11/fonts/TTF", "/usr/X11R6/lib/X11/fonts/drakfont/ttf", "/usr/X11R6/lib/X11/fonts/Type1", "/usr/share/fonts/default/Type1" ); } $ENV{SAL_FONTPATH_USER} = join(";", @fontpath) . ";$ENV{SAL_FONTPATH_USER}" if (@fontpath); # Create the user/work link for "Open..." menu command to work # flawlessly symlinkf $UserWorkDir, "$UserInstallDir/user/work" if ( ! -l "$UserInstallDir/user/work" && ! -d "$UserInstallDir/user/work" ); #============================================================================= # Dump XML tree into file specified by name #============================================================================= sub OutputXML($$) { my ($file, $tree) = @_; local *F; open F, ">$file" or die "Cannot write to file $file\n"; $tree->print(\*F); close F; } #============================================================================= # Define language -> font mappings #============================================================================= sub FontOfLanguage($) { my ($lang) = @_; my %fontOf = ("el-GR" => "Kerkis", "ja-JP" => "Kochi Gothic", "ko-KR" => "Baekmuk Gulim", "ru-RU" => "Nimbus Sans L", "zh-CN" => "AR PL KaitiM GB", "zh-TW" => "AR PL KaitiM Big5"); $fontOf{$lang} || "Luxi Sans"; } #============================================================================= # Return the MTIME of a file, -1 if it does not exist #============================================================================= sub TimeStamp($) { my ($file) = @_; -f "$file" ? (stat "$file")[9] : -1; } #============================================================================= # Misc configuration setup in user *.xml files #============================================================================= if ( $lang && ( -e "$SystemInstallDir/help/$lang" || -e "$SystemInstallDir/help/$isocode" || -e "$SystemInstallDir/help/$oolang" ) ) { # Initialize Twig XML parser my $p = XML::Twig->new(pretty_print => "indented", keep_encoding => 1); # Adjust user interface language, in Setup.xml my $setup_xml = $p->parsefile("$SetupXML"); my $oolocale_node; if (! ($oolocale_node = ($setup_xml->get_xpath("/Setup/L10N/ooLocale"))[0]) ) { # Glue in new <L10N> section, "en-US" is the default locale my $new_l10n_node = << "EOF;"; <L10N> <ooLocale cfg:type="string">en-US</ooLocale> </L10N> EOF; $oolocale_node = XML::Twig->new()->parsestring($new_l10n_node)->root; $oolocale_node->paste($setup_xml->root); $oolocale_node = ($oolocale_node->descendants("ooLocale"))[0]; } my $old_oolang = $oolocale_node->text(); $oolocale_node->set_text("$oolang"); OutputXML "$SetupXML", $setup_xml; # Update default language for documents, in Linguistic.xml # Create file if it does not exist yet. my $linguistic_file; if ( -f ( $linguistic_file = "$LinguisticXML" ) || -f ( $linguistic_file = "$SystemLinguisticXML" ) ) { my $linguistic_xml = $p->parsefile("$linguistic_file"); $_->set_text("$oolang") foreach ( $linguistic_xml->get_xpath("/Linguistic/General/DefaultLocale") ); OutputXML "$LinguisticXML", $linguistic_xml; } # Choose UI fonts according to the current UI language my $common_xml_changed = 0; my $common_xml = $p->parsefile("$CommonXML"); my $font_node; if (! ($font_node = ($common_xml->get_xpath("/Common/Font/Substitution/FontPairs/FontReplacement/SubstituteFont"))[0]) ) { # Glue in new <Font> section my $new_font_node = << "EOF;"; <Font> <Substitution> <FontPairs cfg:element-type="FontReplacement"> <FontReplacement state="replaced" cfg:name="_0"> <Always cfg:type="boolean">true</Always> <OnScreenOnly cfg:type="boolean">true</OnScreenOnly> <ReplaceFont cfg:type="string">Andale Sans UI</ReplaceFont> <SubstituteFont cfg:type="string">Luxi Sans</SubstituteFont> </FontReplacement> </FontPairs> <Replacement cfg:type="boolean">true</Replacement> </Substitution> </Font> EOF; $font_node = XML::Twig->new()->parsestring($new_font_node)->root; $font_node->paste($common_xml->root); $font_node = ($font_node->descendants("SubstituteFont"))[0]; $common_xml_changed = 1; } my $override_font = $OOfficeConfig{UI_FONT}; if ($override_font eq "AUTO") { # Set new font UI, following the first switch to current language if ((my $font = FontOfLanguage $oolang) ne FontOfLanguage $old_oolang) { $font_node->set_text("$font"); $common_xml_changed = 1; } } elsif ($override_font && $override_font ne $font_node->text) { $font_node->set_text("$override_font"); $common_xml_changed = 1; } # Set UI font scaling based on current display resolution, or user defined value my $scale; my $override_fontscaling = $OOfficeConfig{FONT_SCALING} || "100"; if ($override_fontscaling =~ /^([0-9]+)$/) { $scale = $1; } elsif ($override_fontscaling eq "AUTO") { # Get current resolution of screen #0 my ($width, $height); foreach ( reverse cat_("LC_ALL=C xdpyinfo |") ) { ($width, $height) = ($1, $2) if m|^\s+dimensions:\s+([0-9]+)x([0-9]+) pixels|; } # Map to a scale value my %ScaleOfResolution = ("640" => "120", "800" => "120", "1024" => "110", "1152" => "110"); $scale = $ScaleOfResolution{$width} || "100"; } my $scale_node; if (! ($scale_node = ($common_xml->get_xpath("/Common/View/FontScaling"))[0]) ) { # Glue in new <View> section my $new_view_node = << "EOF;"; <View> <FontAntiAliasing> <MinPixelHeight cfg:type="short">8</MinPixelHeight> </FontAntiAliasing> <FontScaling cfg:type="short">100</FontScaling> </View> EOF; $scale_node = XML::Twig->new()->parsestring($new_view_node)->root; $scale_node->paste($common_xml->root); $scale_node = ($scale_node->descendants("FontScaling"))[0]; } if ($scale ne $scale_node->text) { $scale_node->set_text("$scale"); $common_xml_changed = 1; } OutputXML "$CommonXML", $common_xml if ($common_xml_changed); # Default to paper size from locale setting my $paper_size = $OOfficeConfig{PAPER_SIZE}; # Get paper size dimension according to language set if ($paper_size eq "AUTO") { my ($width, $height); foreach (cat_("LC_ALL=$lang /usr/bin/locale -k LC_PAPER |")) { if (/^width=([0-9]+)/) { $width = $1; } elsif (/^height=([0-9]+)/) { $height = $1; } } my %PaperSizeOfDimensions = ("210x297" => "A4", "216x279" => "Letter"); $paper_size = $PaperSizeOfDimensions{"${width}x${height}"} || "A4"; } if ($paper_size) { # Always grab the newer system configuration as new printers # may have been configure in the meantime. output "$PsprintConf", ( cat_("$SystemPsprintConf"), "\n" ) if ( TimeStamp "$SystemPsprintConf" > TimeStamp "$PsprintConf" || ! grep /PDF.+Converter (Screen|Press)/, cat_("$PsprintConf") ); # Change "Generic Printer" section as this is the only valid # one provided that no other printer is configured and setup # as default, if any. Otherwise, printerdrake already # generates printer configuration with the right paper size. # NOTE: also change for PDF converters foreach my $category ( "Generic Printer", "PDF 1.4 Converter Screen", "PDF 1.4 Converter Press" ) { # psprint.conf happens to be a "Windows"-style file update_gnomekderc $PsprintConf, $category, PPD_PageSize => $paper_size; } } } # And here we go. ;-) exec "$UserInstallDir/soffice", @ooo_argv if (!$Debug); # Local variables: # tab-width: 4 # indent-tabs-mode: nil # End: