1#*************************************************************************
2#
3# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4#
5# Copyright 2000, 2010 Oracle and/or its affiliates.
6#
7# OpenOffice.org - a multi-platform office productivity suite
8#
9# This file is part of OpenOffice.org.
10#
11# OpenOffice.org is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Lesser General Public License version 3
13# only, as published by the Free Software Foundation.
14#
15# OpenOffice.org is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU Lesser General Public License version 3 for more details
19# (a copy is included in the LICENSE file that accompanied this code).
20#
21# You should have received a copy of the GNU Lesser General Public License
22# version 3 along with OpenOffice.org.  If not, see
23# <http://www.openoffice.org/license.html>
24# for a copy of the LGPLv3 License.
25#
26#*************************************************************************
27
28package installer::windows::feature;
29
30use installer::existence;
31use installer::exiter;
32use installer::files;
33use installer::globals;
34use installer::sorter;
35use installer::worker;
36use installer::windows::idtglobal;
37use installer::windows::language;
38
39##############################################################
40# Returning the gid for a feature.
41# Attention: Maximum length
42##############################################################
43
44sub get_feature_gid
45{
46	my ($onefeature) = @_;
47
48	my $gid = "";
49
50	if ( $onefeature->{'gid'} ) { $gid = $onefeature->{'gid'}; }
51
52	# Attention: Maximum feature length is 38!
53	installer::windows::idtglobal::shorten_feature_gid(\$gid);
54
55	return $gid
56}
57
58##############################################################
59# Returning the gid of the parent.
60# Attention: Maximum length
61##############################################################
62
63sub get_feature_parent
64{
65	my ($onefeature) = @_;
66
67	my $parentgid = "";
68
69	if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; }
70
71	# The modules, hanging directly below the root, have to be root modules.
72	# Only then it is possible to make the "real" root module invisible by
73	# setting the display to "0".
74
75	if ( $parentgid eq $installer::globals::rootmodulegid ) { $parentgid = ""; }
76
77	# Attention: Maximum feature length is 38!
78	installer::windows::idtglobal::shorten_feature_gid(\$parentgid);
79
80	return $parentgid
81}
82
83##############################################################
84# Returning the display for a feature.
85# 0: Feature is not shown
86# odd: subfeatures are shown
87# even:  subfeatures are not shown
88##############################################################
89
90sub get_feature_display
91{
92	my ($onefeature) = @_;
93
94	my $display;
95	my $parentid = "";
96
97	if ( $onefeature->{'ParentID'} ) { $parentid = $onefeature->{'ParentID'}; }
98
99	if ( $parentid eq "" )
100	{
101		$display = "0";									# root module is not visible
102	}
103	elsif ( $onefeature->{'gid'} eq "gid_Module_Prg")	# program module shows subfeatures
104	{
105		$display = "1";									# root module shows subfeatures
106	}
107	else
108	{
109		$display = "2";									# all other modules do not show subfeatures
110	}
111
112	# special case: Feature has flag "HIDDEN_ROOT" -> $display is 0
113	my $styles = "";
114	if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
115	if ( $styles =~ /\bHIDDEN_ROOT\b/ ) { $display = "0"; }
116
117	# Special handling for language modules. Only visible in multilingual installation set
118	if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( ! $installer::globals::ismultilingual )) { $display = "0"; }
119
120	# Special handling for c05office. No program module visible.
121	if (( $onefeature->{'gid'} eq "gid_Module_Prg" ) && ( $installer::globals::product =~ /c05office/i )) { $display = "0";	}
122
123	# making all feature invisible in Language packs!
124	if ( $installer::globals::languagepack ) { $display = "0"; }
125
126	return $display
127}
128
129##############################################################
130# Returning the level for a feature.
131##############################################################
132
133sub get_feature_level
134{
135	my ($onefeature) = @_;
136
137	my $level = "20";	# the default
138
139	my $localdefault = "";
140
141	if ( $onefeature->{'Default'} ) { $localdefault = $onefeature->{'Default'}; }
142
143	if ( $localdefault eq "NO" )	# explicitely set Default = "NO"
144	{
145		$level = "200";				# deselected in default installation, base is 100
146		if ( $installer::globals::patch ) { $level = "20"; }
147	}
148
149	# special handling for Java and Ada
150	if ( $onefeature->{'Name'} )
151	{
152		if ( $onefeature->{'Name'} =~ /java/i ) { $level = $level + 40; }
153	}
154
155	# if FeatureLevel is defined in scp, this will be used
156
157	if ( $onefeature->{'FeatureLevel'} ) { $level = $onefeature->{'FeatureLevel'}; }
158
159	return $level
160}
161
162##############################################################
163# Returning the directory for a feature.
164##############################################################
165
166sub get_feature_directory
167{
168	my ($onefeature) = @_;
169
170	my $directory;
171
172	$directory = "INSTALLLOCATION";
173
174	return $directory
175}
176
177##############################################################
178# Returning the directory for a feature.
179##############################################################
180
181sub get_feature_attributes
182{
183	my ($onefeature) = @_;
184
185	my $attributes;
186
187	# No advertising of features and no leaving on network.
188	# Feature without parent must not have the "2"
189
190	my $parentgid = "";
191	if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; }
192
193	if (( $parentgid eq "" ) || ( $parentgid eq $installer::globals::rootmodulegid )) { $attributes = "8"; }
194	else { $attributes = "10"; }
195
196	return $attributes
197}
198
199#################################################################################
200# Replacing one variable in one files
201#################################################################################
202
203sub replace_one_variable
204{
205	my ($translationfile, $variable, $searchstring) = @_;
206
207	for ( my $i = 0; $i <= $#{$translationfile}; $i++ )
208	{
209		${$translationfile}[$i] =~ s/\%$searchstring/$variable/g;
210	}
211}
212
213#################################################################################
214# Replacing the variables in the feature names and descriptions
215#################################################################################
216
217sub replace_variables
218{
219	my ($translationfile, $variableshashref) = @_;
220
221	foreach $key (keys %{$variableshashref})
222	{
223		my $value = $variableshashref->{$key};
224		replace_one_variable($translationfile, $value, $key);
225	}
226}
227
228#################################################################################
229# Collecting the feature recursively.
230#################################################################################
231
232sub collect_modules_recursive
233{
234	my ($modulesref, $parentid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted) = @_;
235
236	my @allchildren = ();
237	my $childrenexist = 0;
238
239	# Collecting children from Module $parentid
240
241	my $modulegid;
242	foreach $modulegid ( keys %{$directparent})
243	{
244		if ( $directparent->{$modulegid} eq $parentid )
245		{
246			my %childhash = ( "gid" => "$modulegid", "Sortkey" => "$directsortkey->{$modulegid}");
247			push(@allchildren, \%childhash);
248			$childrenexist = 1;
249		}
250	}
251
252	# Sorting children
253
254	if ( $childrenexist )
255	{
256		# Sort children
257		installer::sorter::sort_array_of_hashes_numerically(\@allchildren, "Sortkey");
258
259		# Adding children to new array
260		my $childhashref;
261		foreach $childhashref ( @allchildren )
262		{
263			my $gid = $childhashref->{'gid'};
264
265			# Saving all lines, that have this 'gid'
266
267			my $unique;
268			foreach $unique ( keys %{$directgid} )
269			{
270				if ( $directgid->{$unique} eq $gid )
271				{
272					push(@{$feature}, ${$modulesref}[$directaccess->{$unique}]);
273					if ( $sorted->{$unique} == 1 ) { installer::exiter::exit_program("ERROR: Sorting feature failed! \"$unique\" already sorted.", "sort_feature"); }
274					$sorted->{$unique} = 1;
275				}
276			}
277
278			collect_modules_recursive($modulesref, $gid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted);
279		}
280	}
281}
282
283#################################################################################
284# Sorting the feature in specified order. Evaluated is the key "Sortkey", that
285# is set in scp2 projects.
286# The display order of modules in Windows Installer is dependent from the order
287# in the idt file. Therefore the order of the modules array has to be adapted
288# to the Sortkey order, before the idt file is created.
289#################################################################################
290
291sub sort_feature
292{
293	my ($modulesref) = @_;
294
295	my @feature = ();
296
297	my %directaccess = ();
298	my %directparent = ();
299	my %directgid = ();
300	my %directsortkey = ();
301	my %sorted = ();
302
303	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
304	{
305		my $onefeature = ${$modulesref}[$i];
306
307		my $uniquekey = $onefeature->{'uniquekey'};
308		my $modulegid = $onefeature->{'gid'};
309
310		$directaccess{$uniquekey} = $i;
311
312		$directgid{$uniquekey} = $onefeature->{'gid'};
313
314		# ParentID and Sortkey are not saved for the 'uniquekey', but only for the 'gid'
315
316		if ( $onefeature->{'ParentID'} ) { $directparent{$modulegid} = $onefeature->{'ParentID'}; }
317		else { $directparent{$modulegid} = ""; }
318
319		if ( $onefeature->{'Sortkey'} ) { $directsortkey{$modulegid} = $onefeature->{'Sortkey'}; }
320		else { $directsortkey{$modulegid} = "9999"; }
321
322		# Bookkeeping:
323		$sorted{$uniquekey} = 0;
324	}
325
326	# Searching all feature recursively, beginning with ParentID = ""
327	my $parentid = "";
328	collect_modules_recursive($modulesref, $parentid, \@feature, \%directaccess, \%directgid, \%directparent, \%directsortkey, \%sorted);
329
330	# Bookkeeping
331	my $modulekey;
332	foreach $modulekey ( keys %sorted )
333	{
334		if ( $sorted{$modulekey} == 0 )
335		{
336			my $infoline = "Warning: Module \"$modulekey\" could not be sorted. Added to the end of the module array.\n";
337			push(@installer::globals::logfileinfo, $infoline);
338			push(@feature, ${$modulesref}[$directaccess{$modulekey}]);
339		}
340	}
341
342	return \@feature;
343}
344
345#################################################################################
346# Adding a unique key to the modules array. The gid is not unique for
347# multilingual modules. Only the combination from gid and specific language
348# is unique. Uniqueness is required for sorting mechanism.
349#################################################################################
350
351sub add_uniquekey
352{
353	my ( $modulesref ) = @_;
354
355	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
356	{
357		my $uniquekey = ${$modulesref}[$i]->{'gid'};
358		if ( ${$modulesref}[$i]->{'specificlanguage'} ) { $uniquekey = $uniquekey . "_" . ${$modulesref}[$i]->{'specificlanguage'}; }
359		${$modulesref}[$i]->{'uniquekey'} = $uniquekey;
360	}
361}
362
363#################################################################################
364# Creating the file Feature.idt dynamically
365# Content:
366# Feature Feature_Parent Title Description Display Level Directory_ Attributes
367#################################################################################
368
369sub create_feature_table
370{
371	my ($modulesref, $basedir, $languagesarrayref, $allvariableshashref) = @_;
372
373	for ( my $m = 0; $m <= $#{$languagesarrayref}; $m++ )
374	{
375		my $onelanguage = ${$languagesarrayref}[$m];
376
377		my $infoline;
378
379		my @featuretable = ();
380
381		installer::windows::idtglobal::write_idt_header(\@featuretable, "feature");
382
383		for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
384		{
385			my $onefeature = ${$modulesref}[$i];
386
387			# Java and Ada only, if the correct settings are set
388			my $styles = "";
389			if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
390			if (( $styles =~ /\bJAVAMODULE\b/ ) && ( ! ($allvariableshashref->{'JAVAPRODUCT'} ))) { next; }
391			if (( $styles =~ /\bADAMODULE\b/ ) && ( ! ($allvariableshashref->{'ADAPRODUCT'} ))) { next; }
392
393			# Controlling the language!
394			# Only language independent feature or feature with the correct language will be included into the table
395
396			if (! (!(( $onefeature->{'ismultilingual'} )) || ( $onefeature->{'specificlanguage'} eq $onelanguage )) )  { next; }
397
398			my %feature = ();
399
400			$feature{'feature'} = get_feature_gid($onefeature);
401			$feature{'feature_parent'} = get_feature_parent($onefeature);
402			# if ( $onefeature->{'ParentID'} eq "" ) { $feature{'feature_parent'} = ""; }	# Root has no parent
403			$feature{'Title'} = $onefeature->{'Name'};
404			$feature{'Description'} = $onefeature->{'Description'};
405			$feature{'Display'} = get_feature_display($onefeature);
406			$feature{'Level'} = get_feature_level($onefeature);
407			$feature{'Directory_'} = get_feature_directory($onefeature);
408			$feature{'Attributes'} = get_feature_attributes($onefeature);
409
410			my $oneline = $feature{'feature'} . "\t" . $feature{'feature_parent'} . "\t" . $feature{'Title'} . "\t"
411					. $feature{'Description'} . "\t" . $feature{'Display'} . "\t" . $feature{'Level'} . "\t"
412					. $feature{'Directory_'} . "\t" . $feature{'Attributes'} . "\n";
413
414			push(@featuretable, $oneline);
415
416			# collecting all feature in global feature collector (so that properties can be set in property table)
417			if ( ! installer::existence::exists_in_array($feature{'feature'}, \@installer::globals::featurecollector) )
418			{
419				push(@installer::globals::featurecollector, $feature{'feature'});
420			}
421
422			# collecting all language feature in feature collector for check of language selection
423			if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( $onefeature->{'ParentID'} ne $installer::globals::rootmodulegid ))
424			{
425				$installer::globals::multilingual_only_modules{$feature{'feature'}} = 1;
426			}
427
428			# collecting all application feature in global feature collector for check of application selection
429			if ( $styles =~ /\bAPPLICATIONMODULE\b/ )
430			{
431				$installer::globals::application_modules{$feature{'feature'}} = 1;
432			}
433		}
434
435		# Saving the file
436
437		my $featuretablename = $basedir . $installer::globals::separator . "Feature.idt" . "." . $onelanguage;
438		installer::files::save_file($featuretablename ,\@featuretable);
439		$infoline = "Created idt file: $featuretablename\n";
440		push(@installer::globals::logfileinfo, $infoline);
441	}
442
443}
444
4451;
446