1 |
package Xconfig::plugins; # $Id: plugins.pm 110085 2007-01-18 08:45:14Z pixel $ |
2 |
|
3 |
use diagnostics; |
4 |
use strict; |
5 |
|
6 |
use Xconfig::parse; |
7 |
use Xconfig::xfree; |
8 |
use common; |
9 |
|
10 |
my $dir = '/usr/share/libDrakX/x11-plugins'; |
11 |
|
12 |
sub list() { |
13 |
glob_("$dir/*.pl"); |
14 |
} |
15 |
|
16 |
sub _load { |
17 |
my ($plugin_pl_file) = @_; |
18 |
my $plugin = eval cat_($plugin_pl_file); |
19 |
$@ and die "bad $plugin_pl_file. error: $@\n"; |
20 |
|
21 |
#- ensure only one line |
22 |
$plugin->{summary} =~ s/\n/ /g; |
23 |
|
24 |
eval { $plugin->{raw} = Xconfig::parse::read_XF86Config_from_string($plugin->{conf}) }; |
25 |
$@ and die "bad $plugin_pl_file conf. error: $@\n"; |
26 |
|
27 |
$plugin; |
28 |
} |
29 |
|
30 |
my $mark = '# Using plugin'; |
31 |
sub parse_active_plugin { |
32 |
my ($raw_X) = @_; |
33 |
|
34 |
$raw_X->{plugins} and internal_error("parse_active_plugin must be done before doing anything with plugins"); |
35 |
|
36 |
my $first = $raw_X->{raw}[0]; |
37 |
if (my @l = $first->{pre_comment} =~ /^\Q$mark\E (.*)/gm) { |
38 |
$raw_X->{plugins} = [ map { { active => 1, summary => $_ } } @l ]; |
39 |
} |
40 |
} |
41 |
sub _mark_active_in_header { |
42 |
my ($raw_X, $summary) = @_; |
43 |
my $first = $raw_X->{raw}[0]; |
44 |
$first->{pre_comment} =~ s/\n/\n$mark $summary\n/; |
45 |
} |
46 |
sub _remove_active_in_header { |
47 |
my ($raw_X, $summary) = @_; |
48 |
my $first = $raw_X->{raw}[0]; |
49 |
$first->{pre_comment} =~ s/\Q$mark $summary\E\n//; |
50 |
} |
51 |
|
52 |
sub load { |
53 |
my ($raw_X, $plugin_pl_file) = @_; |
54 |
|
55 |
my $plugin = eval { _load($plugin_pl_file) }; |
56 |
$@ and log::l("bad plugin $plugin_pl_file: $@"), return; |
57 |
|
58 |
if (my $existing = find { $_->{summary} eq $plugin->{summary} } @{$raw_X->{plugins}}) { |
59 |
put_in_hash($existing, $plugin); |
60 |
$existing->{updated} = 1; |
61 |
} else { |
62 |
push @{$raw_X->{plugins}}, $plugin; |
63 |
} |
64 |
} |
65 |
|
66 |
sub val { &Xconfig::xfree::val } |
67 |
|
68 |
sub apply_plugin { |
69 |
my ($raw_X, $plugin) = @_; |
70 |
|
71 |
if ($plugin->{active}) { |
72 |
$plugin->{updated} or return; |
73 |
|
74 |
#- removing before re-applying again |
75 |
remove_plugin($raw_X, $plugin); |
76 |
} |
77 |
|
78 |
log::l("applying plugin $plugin->{summary}"); |
79 |
|
80 |
foreach my $e (@{$plugin->{raw}}) { |
81 |
_mark_lines_with_name($plugin->{summary}, $e); |
82 |
|
83 |
if (my @sections = _select_sections_to_modify($raw_X, $e)) { |
84 |
#- modifying existing sections |
85 |
#- if there is more than one, modify all of them! |
86 |
_merge_in_section($_, $e->{l}) foreach @sections; |
87 |
} else { |
88 |
#- adding the section |
89 |
$raw_X->add_Section($e->{name}, $e->{l}); |
90 |
} |
91 |
} |
92 |
|
93 |
_mark_active_in_header($raw_X, $plugin->{summary}); |
94 |
$plugin->{active} = 1; |
95 |
} |
96 |
|
97 |
sub _select_sections_to_modify { |
98 |
my ($raw_X, $e) = @_; |
99 |
|
100 |
my @sections = $raw_X->get_Sections($e->{name}) or return; |
101 |
|
102 |
if ($e->{l}{Identifier}) { |
103 |
if (my @l = grep { val($_->{Identifier}) eq $e->{l}{Identifier}{val} } @sections) { |
104 |
#- only modifying the section(s) matching the Driver (useful for InputDevice) |
105 |
delete $e->{l}{Identifier}; #- do not tag-with-comment this line used only to select the section |
106 |
@l; |
107 |
} else { |
108 |
#- if no matching section, we will create it |
109 |
(); |
110 |
} |
111 |
} elsif ($e->{l}{Driver}) { |
112 |
if (my @l = grep { val($_->{Driver}) eq $e->{l}{Driver}{val} } @sections) { |
113 |
#- only modifying the section(s) matching the Driver (useful for InputDevice) |
114 |
delete $e->{l}{Driver}; #- do not tag-with-comment this line used only to select the section |
115 |
@l; |
116 |
} else { |
117 |
#- hum, modifying existing sections, is that good? :-/ |
118 |
@sections; |
119 |
} |
120 |
} else { |
121 |
#- modifying existing sections |
122 |
@sections; |
123 |
} |
124 |
} |
125 |
|
126 |
sub _merge_in_section { |
127 |
my ($h, $h_to_add) = @_; |
128 |
|
129 |
foreach my $name (keys %$h_to_add) { |
130 |
if (exists $h->{$name}) { |
131 |
my $pre_comment = join('', map { "#HIDDEN $_->{val}\n" } deref_array($h->{$name})); |
132 |
my ($first, @other) = deref_array($h_to_add->{$name}); |
133 |
$first = { pre_comment => $pre_comment, %$first }; |
134 |
|
135 |
$h->{$name} = ref($h->{$name}) eq 'ARRAY' ? [ $first, @other ] : $first; |
136 |
} else { |
137 |
$h->{$name} = $h_to_add->{$name}; |
138 |
} |
139 |
} |
140 |
} |
141 |
|
142 |
sub _mark_lines_with_name { |
143 |
my ($summary, $e) = @_; |
144 |
if ($e->{l}) { |
145 |
_mark_lines_with_name($summary, $_) foreach map { deref_array($_) } values %{$e->{l}}; |
146 |
} else { |
147 |
$e->{comment_on_line} = " # $summary"; |
148 |
} |
149 |
} |
150 |
|
151 |
sub remove_plugin { |
152 |
my ($raw_X, $plugin) = @_; |
153 |
|
154 |
$plugin->{active} or return; |
155 |
|
156 |
log::l("removing plugin $plugin->{summary}"); |
157 |
|
158 |
@{$raw_X->{raw}} = map { |
159 |
_remove_plugin($plugin->{summary}, $_); |
160 |
} @{$raw_X->{raw}}; |
161 |
|
162 |
_remove_active_in_header($raw_X, $plugin->{summary}); |
163 |
$plugin->{active} = 0; |
164 |
} |
165 |
|
166 |
sub _remove_plugin { |
167 |
my ($summary, $e) = @_; |
168 |
if ($e->{l}) { |
169 |
my $removed; |
170 |
foreach my $k (keys %{$e->{l}}) { |
171 |
my $v = $e->{l}{$k}; |
172 |
my @v = map { _remove_plugin($summary, $_) } deref_array($v); |
173 |
if (@v) { |
174 |
if (ref($v) eq 'ARRAY') { |
175 |
@$v = @v; |
176 |
} else { |
177 |
$e->{l}{$k} = $v[0]; |
178 |
} |
179 |
} else { |
180 |
$removed = 1; |
181 |
delete $e->{l}{$k}; |
182 |
} |
183 |
} |
184 |
if_(!$removed || %{$e->{l}}, $e); |
185 |
} elsif ($e->{comment_on_line} eq " # $summary") { |
186 |
if (my @hidden = $e->{pre_comment} =~ /^#HIDDEN (.*)/gm) { |
187 |
delete $e->{comment_on_line}; |
188 |
delete $e->{pre_comment}; |
189 |
map { { %$e, val => $_ } } @hidden; |
190 |
} else { |
191 |
(); |
192 |
} |
193 |
} else { |
194 |
$e; |
195 |
} |
196 |
} |
197 |
|
198 |
sub apply_or_remove_plugin { |
199 |
my ($raw_X, $plugin, $apply) = @_; |
200 |
|
201 |
if ($apply) { |
202 |
apply_plugin($raw_X, $plugin); |
203 |
} else { |
204 |
remove_plugin($raw_X, $plugin); |
205 |
} |
206 |
} |
207 |
|
208 |
sub choose { |
209 |
my ($in, $raw_X) = @_; |
210 |
|
211 |
parse_active_plugin($raw_X) if !$raw_X->{plugins}; |
212 |
|
213 |
load($raw_X, $_) foreach list(); |
214 |
|
215 |
my $plugins = $raw_X->{plugins}; |
216 |
$_->{want_active} = $_->{active} foreach @$plugins; |
217 |
|
218 |
$in->ask_from_({}, |
219 |
[ { title => 1, label => N("Choose plugins") }, |
220 |
map { |
221 |
{ type => 'bool', val => \$_->{want_active}, text => $_->{summary} }, |
222 |
{ val => formatAlaTeX($_->{description}) }; |
223 |
} @$plugins ]) or return; |
224 |
|
225 |
foreach (@$plugins) { |
226 |
apply_or_remove_plugin($raw_X, $_, $_->{want_active}) |
227 |
if $_->{want_active} != $_->{active}; |
228 |
} |
229 |
|
230 |
1; |
231 |
} |
232 |
1; |