2 # This file is part of the LibreOffice project.
4 # This Source Code Form is subject to the terms of the Mozilla Public
5 # License, v. 2.0. If a copy of the MPL was not distributed with this
6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 # This file incorporates work covered by the following license notice:
10 # Licensed to the Apache Software Foundation (ASF) under one or more
11 # contributor license agreements. See the NOTICE file distributed
12 # with this work for additional information regarding copyright
13 # ownership. The ASF licenses this file to you under the Apache
14 # License, Version 2.0 (the "License"); you may not use this file
15 # except in compliance with the License. You may obtain a copy of
16 # the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 package installer
::windows
::feature
;
21 use installer
::exiter
;
23 use installer
::globals
;
24 use installer
::worker
;
25 use installer
::windows
::idtglobal
;
26 use installer
::windows
::language
;
28 ##############################################################
29 # Returning the gid for a feature.
30 # Attention: Maximum length
31 ##############################################################
35 my ($onefeature) = @_;
39 if ( $onefeature->{'gid'} ) { $gid = $onefeature->{'gid'}; }
41 # Attention: Maximum feature length is 38!
42 installer
::windows
::idtglobal
::shorten_feature_gid
(\
$gid);
47 ##############################################################
48 # Returning the gid of the parent.
49 # Attention: Maximum length
50 ##############################################################
52 sub get_feature_parent
54 my ($onefeature) = @_;
58 if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; }
60 # The modules, hanging directly below the root, have to be root modules.
61 # Only then it is possible to make the "real" root module invisible by
62 # setting the display to "0".
64 if ( $parentgid eq $installer::globals
::rootmodulegid
) { $parentgid = ""; }
66 # Attention: Maximum feature length is 38!
67 installer
::windows
::idtglobal
::shorten_feature_gid
(\
$parentgid);
72 ##############################################################
73 # Returning the display for a feature.
74 # 0: Feature is not shown
75 # odd: subfeatures are shown
76 # even: subfeatures are not shown
77 ##############################################################
79 sub get_feature_display
81 my ($onefeature) = @_;
86 if ( $onefeature->{'ParentID'} ) { $parentid = $onefeature->{'ParentID'}; }
88 if ( $parentid eq "" )
90 $display = "0"; # root module is not visible
92 elsif ( $onefeature->{'gid'} eq "gid_Module_Prg") # program module shows subfeatures
94 $display = "1"; # root module shows subfeatures
98 $display = "2"; # all other modules do not show subfeatures
101 # special case: Feature has flag "HIDDEN_ROOT" -> $display is 0
103 if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
104 if ( $styles =~ /\bHIDDEN_ROOT\b/ ) { $display = "0"; }
106 # Special handling for language modules. Only visible in multilingual installation set
107 if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( ! $installer::globals
::ismultilingual
)) { $display = "0"; }
109 # No program module visible.
110 if ( $onefeature->{'gid'} eq "gid_Module_Prg" ) { $display = "0"; }
112 # making all feature invisible in Language packs and in Help packs!
113 if ( $installer::globals
::languagepack
|| $installer::globals
::helppack
) { $display = "0"; }
118 ##############################################################
119 # Returning the level for a feature.
120 ##############################################################
122 sub get_feature_level
124 my ($onefeature) = @_;
126 my $level = "20"; # the default
128 my $localdefault = "";
130 if ( $onefeature->{'Default'} ) { $localdefault = $onefeature->{'Default'}; }
132 if ( $localdefault eq "NO" ) # explicitly set Default = "NO"
134 $level = "200"; # deselected in default installation, base is 100
137 # special handling for Java and Ada
138 if ( $onefeature->{'Name'} )
140 if ( $onefeature->{'Name'} =~ /java/i ) { $level = $level + 40; }
143 # if FeatureLevel is defined in scp, this will be used
145 if ( $onefeature->{'FeatureLevel'} ) { $level = $onefeature->{'FeatureLevel'}; }
150 ##############################################################
151 # Returning the directory for a feature.
152 ##############################################################
154 sub get_feature_directory
156 my ($onefeature) = @_;
160 $directory = "INSTALLLOCATION";
165 ##############################################################
166 # Returning the directory for a feature.
167 ##############################################################
169 sub get_feature_attributes
171 my ($onefeature) = @_;
175 # No advertising of features and no leaving on network.
176 # Feature without parent must not have the "2"
179 if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; }
181 if (( $parentgid eq "" ) || ( $parentgid eq $installer::globals
::rootmodulegid
)) { $attributes = "8"; }
182 elsif ( get_feature_display
($onefeature) eq "0" ) { $attributes = "26"; } # fdo#33798
183 else { $attributes = "10"; }
188 #################################################################################
189 # Collecting the feature recursively.
190 #################################################################################
192 sub collect_modules_recursive
194 my ($modulesref, $parentid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted) = @_;
196 my @allchildren = ();
197 my $childrenexist = 0;
199 # Collecting children from Module $parentid
202 foreach $modulegid ( keys %{$directparent})
204 if ( $directparent->{$modulegid} eq $parentid )
206 push @allchildren, [ $directsortkey->{$modulegid}, $modulegid ];
213 if ( $childrenexist )
216 @allchildren = map { $_->[1] }
217 sort { $a->[0] <=> $b->[0] }
220 # Adding children to new array
221 foreach my $gid ( @allchildren )
223 # Saving all lines, that have this 'gid'
226 foreach $unique ( keys %{$directgid} )
228 if ( $directgid->{$unique} eq $gid )
230 push(@
{$feature}, ${$modulesref}[$directaccess->{$unique}]);
231 if ( $sorted->{$unique} == 1 ) { installer
::exiter
::exit_program
("ERROR: Sorting feature failed! \"$unique\" already sorted.", "sort_feature"); }
232 $sorted->{$unique} = 1;
236 collect_modules_recursive
($modulesref, $gid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted);
241 #################################################################################
242 # Sorting the feature in specified order. Evaluated is the key "Sortkey", that
243 # is set in scp2 projects.
244 # The display order of modules in Windows Installer is dependent from the order
245 # in the idt file. Therefore the order of the modules array has to be adapted
246 # to the Sortkey order, before the idt file is created.
247 #################################################################################
251 my ($modulesref) = @_;
255 my %directaccess = ();
256 my %directparent = ();
258 my %directsortkey = ();
261 for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
263 my $onefeature = ${$modulesref}[$i];
265 my $uniquekey = $onefeature->{'uniquekey'};
266 my $modulegid = $onefeature->{'gid'};
268 $directaccess{$uniquekey} = $i;
270 $directgid{$uniquekey} = $onefeature->{'gid'};
272 # ParentID and Sortkey are not saved for the 'uniquekey', but only for the 'gid'
274 if ( $onefeature->{'ParentID'} ) { $directparent{$modulegid} = $onefeature->{'ParentID'}; }
275 else { $directparent{$modulegid} = ""; }
277 if ( $onefeature->{'Sortkey'} ) { $directsortkey{$modulegid} = $onefeature->{'Sortkey'}; }
278 else { $directsortkey{$modulegid} = "9999"; }
281 $sorted{$uniquekey} = 0;
284 # Searching all feature recursively, beginning with ParentID = ""
286 collect_modules_recursive
($modulesref, $parentid, \
@feature, \
%directaccess, \
%directgid, \
%directparent, \
%directsortkey, \
%sorted);
290 foreach $modulekey ( keys %sorted )
292 if ( $sorted{$modulekey} == 0 )
294 my $infoline = "Warning: Module \"$modulekey\" could not be sorted. Added to the end of the module array.\n";
295 push(@installer::globals
::logfileinfo
, $infoline);
296 push(@feature, ${$modulesref}[$directaccess{$modulekey}]);
303 #################################################################################
304 # Adding a unique key to the modules array. The gid is not unique for
305 # multilingual modules. Only the combination from gid and specific language
306 # is unique. Uniqueness is required for sorting mechanism.
307 #################################################################################
311 my ( $modulesref ) = @_;
313 for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
315 my $uniquekey = ${$modulesref}[$i]->{'gid'};
316 if ( ${$modulesref}[$i]->{'specificlanguage'} ) { $uniquekey = $uniquekey . "_" . ${$modulesref}[$i]->{'specificlanguage'}; }
317 ${$modulesref}[$i]->{'uniquekey'} = $uniquekey;
321 #################################################################################
322 # Creating the file Feature.idt dynamically
324 # Feature Feature_Parent Title Description Display Level Directory_ Attributes
325 #################################################################################
327 sub create_feature_table
329 my ($modulesref, $basedir, $languagesarrayref, $allvariableshashref) = @_;
331 for ( my $m = 0; $m <= $#{$languagesarrayref}; $m++ )
333 my $onelanguage = ${$languagesarrayref}[$m];
337 my @featuretable = ();
339 installer
::windows
::idtglobal
::write_idt_header
(\
@featuretable, "feature");
341 for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
343 my $onefeature = ${$modulesref}[$i];
345 # Java and Ada only, if the correct settings are set
347 if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
349 # Controlling the language!
350 # Only language independent feature or feature with the correct language will be included into the table
351 # But help packs are different. They have en-US added as setup language.
353 if (! (!(( $onefeature->{'ismultilingual'} )) || ( $onefeature->{'specificlanguage'} eq $onelanguage ) || $installer::globals
::helppack
) ) { next; }
357 $feature{'feature'} = get_feature_gid
($onefeature);
358 $feature{'feature_parent'} = get_feature_parent
($onefeature);
359 $feature{'Title'} = $onefeature->{'Name'};
360 $feature{'Description'} = $onefeature->{'Description'};
361 $feature{'Description'} =~ s/\\\"/\"/g; # no more masquerading of '"'
362 $feature{'Display'} = get_feature_display
($onefeature);
363 $feature{'Level'} = get_feature_level
($onefeature);
364 $feature{'Directory_'} = get_feature_directory
($onefeature);
365 $feature{'Attributes'} = get_feature_attributes
($onefeature);
367 my $oneline = $feature{'feature'} . "\t" . $feature{'feature_parent'} . "\t" . $feature{'Title'} . "\t"
368 . $feature{'Description'} . "\t" . $feature{'Display'} . "\t" . $feature{'Level'} . "\t"
369 . $feature{'Directory_'} . "\t" . $feature{'Attributes'} . "\n";
371 push(@featuretable, $oneline);
373 # collecting all feature in global feature collector (so that properties can be set in property table)
374 if ( ! grep {$_ eq $feature{'feature'}} @installer::globals
::featurecollector
)
376 push(@installer::globals
::featurecollector
, $feature{'feature'});
379 # collecting all language feature in feature collector for check of language selection
380 if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( $onefeature->{'ParentID'} ne $installer::globals
::rootmodulegid
))
382 $installer::globals
::multilingual_only_modules
{$feature{'feature'}} = 1;
385 # collecting all application feature in global feature collector for check of application selection
386 if ( $styles =~ /\bAPPLICATIONMODULE\b/ )
388 $installer::globals
::application_modules
{$feature{'feature'}} = 1;
394 my $featuretablename = $basedir . $installer::globals
::separator
. "Feature.idt" . "." . $onelanguage;
395 installer
::files
::save_file
($featuretablename ,\
@featuretable);
396 $infoline = "Created idt file: $featuretablename\n";
397 push(@installer::globals
::logfileinfo
, $infoline);