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