summaryrefslogtreecommitdiffstats
path: root/zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43
diff options
context:
space:
mode:
Diffstat (limited to 'zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43')
-rw-r--r--zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43/attachment-0001.html122
-rw-r--r--zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43/attachment.html122
2 files changed, 244 insertions, 0 deletions
diff --git a/zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43/attachment-0001.html b/zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43/attachment-0001.html
new file mode 100644
index 000000000..813cc739e
--- /dev/null
+++ b/zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43/attachment-0001.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<title>[668] - do not hardcode domain name ( as this complexify deploymement on a separate </title>
+</head>
+<body>
+
+<style type="text/css"><!--
+#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
+#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
+#msg dt:after { content:':';}
+#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
+#msg dl a { font-weight: bold}
+#msg dl a:link { color:#fc3; }
+#msg dl a:active { color:#ff0; }
+#msg dl a:visited { color:#cc6; }
+h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
+#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
+#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
+#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
+#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
+#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
+#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
+#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
+#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
+#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
+#logmsg pre { background: #eee; padding: 1em; }
+#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
+#logmsg dl { margin: 0; }
+#logmsg dt { font-weight: bold; }
+#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
+#logmsg dd:before { content:'\00bb';}
+#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
+#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
+#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
+#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
+#logmsg table th.Corner { text-align: left; }
+#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
+#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
+#patch { width: 100%; }
+--></style>
+<div id="msg">
+<dl class="meta">
+<dt>Revision</dt> <dd>668</dd>
+<dt>Author</dt> <dd>misc</dd>
+<dt>Date</dt> <dd>2011-01-06 01:06:30 +0100 (Thu, 06 Jan 2011)</dd>
+</dl>
+
+<h3>Log Message</h3>
+<pre>- do not hardcode domain name ( as this complexify deploymement on a separate
+test set of server )</pre>
+
+<h3>Modified Paths</h3>
+<ul>
+<li><a href="#puppetmodulesbuildsystemtemplatesiurtcauldronconf">puppet/modules/buildsystem/templates/iurt.cauldron.conf</a></li>
+<li><a href="#puppetmodulesbuildsystemtemplatesiurtmandriva20101conf">puppet/modules/buildsystem/templates/iurt.mandriva2010.1.conf</a></li>
+<li><a href="#puppetmodulesbuildsystemtemplatesuploadconf">puppet/modules/buildsystem/templates/upload.conf</a></li>
+</ul>
+
+</div>
+<div id="patch"><pre>
+<a id="puppetmodulesbuildsystemtemplatesiurtcauldronconf">Modified: puppet/modules/buildsystem/templates/iurt.cauldron.conf</a>
+===================================================================
+--- puppet/modules/buildsystem/templates/iurt.cauldron.conf 2011-01-06 00:05:31 UTC (rev 667)
++++ puppet/modules/buildsystem/templates/iurt.cauldron.conf 2011-01-06 00:06:30 UTC (rev 668)
+@@ -4,9 +4,9 @@
+ upload =&gt; 'iurt@pkgsubmit:~/uploads/',
+ upload_queue =&gt; 'iurt@pkgsubmit:~/uploads/queue/',
+ unwanted_packages =&gt; '^monotone-',
+- repository =&gt; 'http://repository.mageia.org/distrib/',
++ repository =&gt; 'http://repository.&lt;%= domain %&gt;/distrib/',
+ rsync_to =&gt; 'iurt@pkgsubmit:/mnt/BIG/dis/uploads/build/',
+- log_url =&gt; 'http://pkgsubmit.mageia.org/queue/build/',
++ log_url =&gt; 'http://pkgsubmit.&lt;%= domain %&gt;/queue/build/',
+ admin =&gt; 'mageia-sysadm@mageia.org',
+ packager =&gt; 'Iurt the rebuild bot &lt;mageia-sysadm@mageia.org&gt;',
+ sendmail =&gt; 0,
+
+<a id="puppetmodulesbuildsystemtemplatesiurtmandriva20101conf">Modified: puppet/modules/buildsystem/templates/iurt.mandriva2010.1.conf</a>
+===================================================================
+--- puppet/modules/buildsystem/templates/iurt.mandriva2010.1.conf 2011-01-06 00:05:31 UTC (rev 667)
++++ puppet/modules/buildsystem/templates/iurt.mandriva2010.1.conf 2011-01-06 00:06:30 UTC (rev 668)
+@@ -4,9 +4,9 @@
+ upload =&gt; 'iurt@pkgsubmit:~/uploads/',
+ upload_queue =&gt; 'iurt@pkgsubmit:~/uploads/queue/',
+ unwanted_packages =&gt; '^monotone-',
+- repository =&gt; 'http://repository.mageia.org/mandriva/',
++ repository =&gt; 'http://repository.&lt;%= domain %&gt;/mandriva/',
+ rsync_to =&gt; 'iurt@pkgsubmit:/mnt/BIG/dis/uploads/build/',
+- log_url =&gt; 'http://pkgsubmit.mageia.org/queue/build/',
++ log_url =&gt; 'http://pkgsubmit.&lt;%= domain %&gt;/queue/build/',
+ admin =&gt; 'mageia-sysadm@mageia.org',
+ packager =&gt; 'Iurt the rebuild bot &lt;mageia-sysadm@mageia.org&gt;',
+ sendmail =&gt; 0,
+
+<a id="puppetmodulesbuildsystemtemplatesuploadconf">Modified: puppet/modules/buildsystem/templates/upload.conf</a>
+===================================================================
+--- puppet/modules/buildsystem/templates/upload.conf 2011-01-06 00:05:31 UTC (rev 667)
++++ puppet/modules/buildsystem/templates/upload.conf 2011-01-06 00:06:30 UTC (rev 668)
+@@ -11,7 +11,7 @@
+ i586 =&gt; [ qw(ecosse) ],
+ x86_64 =&gt; [ qw(jonund) ],
+ );
+-my $repository = &quot;http://repository.mageia.org/distrib/&quot;;
++my $repository = &quot;http://repository.&lt;%= domain %&gt;/distrib/&quot;;
+ my $homedir = &quot;/home/iurt&quot;;
+
+ {
+@@ -52,6 +52,6 @@
+ },
+ },
+ admin =&gt; 'mageia-sysadm@mageia.org',
+- http_queue =&gt; 'http://pkgsubmit.mageia.org/uploads',
++ http_queue =&gt; 'http://pkgsubmit.&lt;%= domain %&gt;/uploads',
+ upload_user =&gt; 'schedbot',
+ }
+
+</pre></div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43/attachment.html b/zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43/attachment.html
new file mode 100644
index 000000000..813cc739e
--- /dev/null
+++ b/zarb-ml/mageia-sysadm/attachments/20110106/6c7a8f43/attachment.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<title>[668] - do not hardcode domain name ( as this complexify deploymement on a separate </title>
+</head>
+<body>
+
+<style type="text/css"><!--
+#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
+#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
+#msg dt:after { content:':';}
+#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
+#msg dl a { font-weight: bold}
+#msg dl a:link { color:#fc3; }
+#msg dl a:active { color:#ff0; }
+#msg dl a:visited { color:#cc6; }
+h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
+#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
+#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
+#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
+#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
+#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
+#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
+#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
+#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
+#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
+#logmsg pre { background: #eee; padding: 1em; }
+#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
+#logmsg dl { margin: 0; }
+#logmsg dt { font-weight: bold; }
+#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
+#logmsg dd:before { content:'\00bb';}
+#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
+#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
+#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
+#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
+#logmsg table th.Corner { text-align: left; }
+#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
+#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
+#patch { width: 100%; }
+--></style>
+<div id="msg">
+<dl class="meta">
+<dt>Revision</dt> <dd>668</dd>
+<dt>Author</dt> <dd>misc</dd>
+<dt>Date</dt> <dd>2011-01-06 01:06:30 +0100 (Thu, 06 Jan 2011)</dd>
+</dl>
+
+<h3>Log Message</h3>
+<pre>- do not hardcode domain name ( as this complexify deploymement on a separate
+test set of server )</pre>
+
+<h3>Modified Paths</h3>
+<ul>
+<li><a href="#puppetmodulesbuildsystemtemplatesiurtcauldronconf">puppet/modules/buildsystem/templates/iurt.cauldron.conf</a></li>
+<li><a href="#puppetmodulesbuildsystemtemplatesiurtmandriva20101conf">puppet/modules/buildsystem/templates/iurt.mandriva2010.1.conf</a></li>
+<li><a href="#puppetmodulesbuildsystemtemplatesuploadconf">puppet/modules/buildsystem/templates/upload.conf</a></li>
+</ul>
+
+</div>
+<div id="patch"><pre>
+<a id="puppetmodulesbuildsystemtemplatesiurtcauldronconf">Modified: puppet/modules/buildsystem/templates/iurt.cauldron.conf</a>
+===================================================================
+--- puppet/modules/buildsystem/templates/iurt.cauldron.conf 2011-01-06 00:05:31 UTC (rev 667)
++++ puppet/modules/buildsystem/templates/iurt.cauldron.conf 2011-01-06 00:06:30 UTC (rev 668)
+@@ -4,9 +4,9 @@
+ upload =&gt; 'iurt@pkgsubmit:~/uploads/',
+ upload_queue =&gt; 'iurt@pkgsubmit:~/uploads/queue/',
+ unwanted_packages =&gt; '^monotone-',
+- repository =&gt; 'http://repository.mageia.org/distrib/',
++ repository =&gt; 'http://repository.&lt;%= domain %&gt;/distrib/',
+ rsync_to =&gt; 'iurt@pkgsubmit:/mnt/BIG/dis/uploads/build/',
+- log_url =&gt; 'http://pkgsubmit.mageia.org/queue/build/',
++ log_url =&gt; 'http://pkgsubmit.&lt;%= domain %&gt;/queue/build/',
+ admin =&gt; 'mageia-sysadm@mageia.org',
+ packager =&gt; 'Iurt the rebuild bot &lt;mageia-sysadm@mageia.org&gt;',
+ sendmail =&gt; 0,
+
+<a id="puppetmodulesbuildsystemtemplatesiurtmandriva20101conf">Modified: puppet/modules/buildsystem/templates/iurt.mandriva2010.1.conf</a>
+===================================================================
+--- puppet/modules/buildsystem/templates/iurt.mandriva2010.1.conf 2011-01-06 00:05:31 UTC (rev 667)
++++ puppet/modules/buildsystem/templates/iurt.mandriva2010.1.conf 2011-01-06 00:06:30 UTC (rev 668)
+@@ -4,9 +4,9 @@
+ upload =&gt; 'iurt@pkgsubmit:~/uploads/',
+ upload_queue =&gt; 'iurt@pkgsubmit:~/uploads/queue/',
+ unwanted_packages =&gt; '^monotone-',
+- repository =&gt; 'http://repository.mageia.org/mandriva/',
++ repository =&gt; 'http://repository.&lt;%= domain %&gt;/mandriva/',
+ rsync_to =&gt; 'iurt@pkgsubmit:/mnt/BIG/dis/uploads/build/',
+- log_url =&gt; 'http://pkgsubmit.mageia.org/queue/build/',
++ log_url =&gt; 'http://pkgsubmit.&lt;%= domain %&gt;/queue/build/',
+ admin =&gt; 'mageia-sysadm@mageia.org',
+ packager =&gt; 'Iurt the rebuild bot &lt;mageia-sysadm@mageia.org&gt;',
+ sendmail =&gt; 0,
+
+<a id="puppetmodulesbuildsystemtemplatesuploadconf">Modified: puppet/modules/buildsystem/templates/upload.conf</a>
+===================================================================
+--- puppet/modules/buildsystem/templates/upload.conf 2011-01-06 00:05:31 UTC (rev 667)
++++ puppet/modules/buildsystem/templates/upload.conf 2011-01-06 00:06:30 UTC (rev 668)
+@@ -11,7 +11,7 @@
+ i586 =&gt; [ qw(ecosse) ],
+ x86_64 =&gt; [ qw(jonund) ],
+ );
+-my $repository = &quot;http://repository.mageia.org/distrib/&quot;;
++my $repository = &quot;http://repository.&lt;%= domain %&gt;/distrib/&quot;;
+ my $homedir = &quot;/home/iurt&quot;;
+
+ {
+@@ -52,6 +52,6 @@
+ },
+ },
+ admin =&gt; 'mageia-sysadm@mageia.org',
+- http_queue =&gt; 'http://pkgsubmit.mageia.org/uploads',
++ http_queue =&gt; 'http://pkgsubmit.&lt;%= domain %&gt;/uploads',
+ upload_user =&gt; 'schedbot',
+ }
+
+</pre></div>
+
+</body>
+</html> \ No newline at end of file
#n602'>602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
package interactive; # $Id: interactive.pm 247292 2008-10-01 15:23:37Z tv $

use diagnostics;
use strict;

#-######################################################################################
#- misc imports
#-######################################################################################
use common;
use do_pkgs;

#- minimal example using interactive:
#
#- > use lib qw(/usr/lib/libDrakX);
#- > use interactive;
#- > my $in = interactive->vnew;
#- > $in->ask_okcancel('title', 'question');
#- > $in->exit;

#- ask_from_ takes global options ($common):
#-  title                => window title
#-  messages             => message displayed in the upper part of the window
#-  ok                   => force the name of the "Ok"/"Next" button
#-  cancel               => force the name of the "Cancel"/"Previous" button
#-  focus_cancel         => force focus on the "Cancel" button
#-  focus_first          => (deprecated) force focus on the first entry
#-  ok_disabled          => function returning wether {ok} should be disabled (grayed)
#-  validate             => function called when {ok} is pressed. If it returns false, the first entry is focused, otherwise it quits
#-  advanced             => (deprecated) function called when the "advanced" expander is toggled
#-  advanced_messages    => (deprecated) message displayed when "Advanced" is pressed
#-  advanced_label       => (deprecated) force the name of the "Advanced" button
#-  advanced_label_close => (deprecated) force the name of the "Basic" button
#-  advanced_state       => (deprecated) if set to 1, force the "Advanced" part of the dialog to be opened initially
#-  advanced_title       => (deprecated) title of the advanced item popup dialog (else reusing main title)
#-  callbacks            => (deprecated) functions called when something happen: complete advanced ok_disabled

#- ask_from_ takes a list of entries with fields:
#-  val      => reference to the value
#-  label    => description
#-  title    => a boolean: whether the label should be displayed as a title (see GNOME's HIG)
#-  icon     => icon to put before the description
#-  help     => tooltip
#-  advanced => (deprecated) wether it is shown in by default or only in advanced mode
#-  focus_out => function called when the entry is focused out
#-  changed  => function called when the entry is modified
#-  validate => function called when "Ok" is pressed. If it returns false, this entry is focused, otherwise it quits
#-  disabled => function returning wether it should be disabled (grayed)
#-  focus    => function returning wether it should be focused
#-  alignment => preferred alignment
#-  do_not_expand => do not eat all horizontal space
#-  install_button => if possible, use improved graphical style
#-  gtk      => gtk preferences
#-  type     => 
#-     button => (with clicked or clicked_may_quit)
#-               (type defaults to button if clicked or clicked_may_quit is there)
#-               (val need not be a reference) (if clicked_may_quit return true, it's as if "Ok" was pressed)
#-     label => (val need not be a reference) (type defaults to label if val is not a reference) 
#-     bool (with "text" or "image" (which overrides text) giving an image filename)
#-     range (with min, max, SpinButton)
#-     combo (with list, not_edit, format)
#-     list (with list, icon2f (aka icon), separator (aka tree), format (aka pre_format function),
#-           help can be a hash or a function,
#-           tree_expanded boolean telling wether the tree should be wide open by default
#-           quit_if_double_click boolean
#-           allow_empty_list disables the special cases for 0 and 1 element lists
#-           image2f is a subroutine which takes a value of the list as parameter, and returns image_file_name
#-     entry (the default) (with hidden)
#-     expander (with text, expanded, message, children(a list of sub entries))
#
#- heritate from this class and you'll get all made interactivity for same steps.
#- for this you need to provide
#- - ask_from_listW(o, title, messages, arrayref, default) returns one string of arrayref
#-
#- where
#- - o is the object
#- - title is a string
#- - messages is an refarray of strings
#- - default is an optional string (default is in arrayref)
#- - arrayref is an arrayref of strings
#- - arrayref2 contains booleans telling the default state,
#-
#- ask_from_list and ask_from_list_ are wrappers around ask_from_biglist and ask_from_smalllist
#-
#- ask_from_list_ just translate arrayref before calling ask_from_list and untranslate the result
#-
#- ask_from_listW should handle differently small lists and big ones.
#-


#-######################################################################################
#- OO Stuff
#-######################################################################################
our @ISA = qw(do_pkgs);

sub new($) {
    my ($type) = @_;

    bless {}, ref($type) || $type;
}

sub vnew {
    my ($_type, $o_su, $o_icon) = @_;
    my $su = $o_su eq "su";
    if ($ENV{INTERACTIVE_HTTP}) {
	require interactive::http;
	return interactive::http->new;
    }
    require c;
    if ($su) {
	$ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}";
	$su = '' if $::testing || $ENV{TESTING};
    }
    require_root_capability() if $su;
    if (check_for_xserver()) {
	eval { require interactive::gtk };
	if (!$@) {
	    my $o = interactive::gtk->new;
	    if ($o_icon && $o_icon ne 'default' && !$::isWizard) { $o->{icon} = $o_icon } else { undef $o->{icon} }
	    return $o;
	} elsif ($::testing) {
	    die;
	}
    }

    require interactive::curses;
    interactive::curses->new;
}

sub ok { N_("Ok") }
sub cancel { N_("Cancel") }

sub markup_parse {
    my ($s) = @_;
    my @l;
    my @attrs;

    while ($s) {
	if ($s =~ s!^<(\w+)(\s+[^>]*?)?>!!s) {
	    push @attrs, [ $1, $2 ];
	} elsif ($s =~ s!^</(\w+)>!!) {
	    my $previous = pop @attrs;
	    $previous->[0] eq $1 or return;
	} elsif ($s =~ s!^(&(amp|lt|gt);)!!) {
	    push @l, [ $1, @attrs ];
	} elsif ($s =~ s!^([^<>&]+)!!s) {
	    push @l, [ $1, @attrs ];
	} else {
	    return;
	}
    }
    markup_simplify(\@l);
    \@l;
}

sub markup_simplify {
    my ($l) = @_;
    foreach (@$l) {
	my ($s, @attrs) = @$_;
	my %attrs = map {
	    my ($tag, $attrs) = @$_;
	    my $long = { b => { weight => "bold" },
			 i => { style => "italic" },
			 big => { size => 'larger' },
		      }->{$tag};   
	    $long ? %$long : map { /^(.*?)=['"]?(.*?)['"]?$/ } split(' ', $attrs);
	} @attrs;

	$s = +{ '&amp;' => '&', '&lt;' => '<', '&gt;' => '>' }->{$s} || $s;

	@$_ = ($s, if_(%attrs, \%attrs));
    }
}

sub markup_remove {
    my ($s) = @_;
    if (my $l = markup_parse($s)) {
	join('', map { $_->[0] } @$l);
    } else {
	$s;
    }
}

#- drop markup as fallback
sub adapt_markup {
    my ($_o, $s) = @_;
    markup_remove($s);
}

sub enter_console {}
sub leave_console {}
sub suspend {}
sub resume {}
sub end {}
sub exit {
    if ($::isStandalone) {
        require standalone;
        standalone::exit($_[0]);
    } else {
        exit($_[0]);
    }
}


#-######################################################################################
#- Interactive functions
#-######################################################################################
sub ask_warn {
    my ($o, $title, $message, $o_icon) = @_;
    ask_warn_($o, { title => $title, messages => $message, icon => $o_icon });
}
sub ask_yesorno {
    my ($o, $title, $message, $b_def) = @_;
    ask_yesorno_($o, { title => $title, messages => $message }, $b_def);
}
sub ask_okcancel {
    my ($o, $title, $message, $b_def, $o_icon) = @_;
    ask_okcancel_($o, { title => $title, messages => $message, icon => $o_icon }, $b_def);
}

sub ask_warn_ {
    my ($o, $common) = @_;
    local $o->{modal} = $o->{modal} || $::isInstall; # make these popup at install time
    ask_from_listf_raw_no_check($o, $common, \&translate, [ $o->ok ]);
}

sub ask_yesorno_ {
    my ($o, $common, $b_def) = @_;
    $common->{cancel} = '';
    ask_from_listf_raw($o, $common, \&translate, [ N_("Yes"), N_("No") ], $b_def ? "Yes" : "No") eq "Yes";
}

sub ask_okcancel_ {
    my ($o, $common, $b_def) = @_;

    if ($::isWizard) {
	$common->{focus_cancel} = !$b_def;
    	ask_from_no_check($o, $common, []);
    } else {
	ask_from_listf_raw($o, $common, \&translate, [ $o->ok, $o->cancel ], $b_def ? $o->ok : $o->cancel) eq $o->ok;
    }
}

sub ask_filename {
    my ($o, $common) = @_;
    $common->{want_a_dir} = 0;
    $o->ask_fileW($common);
}

sub ask_directory {
    my ($o, $common) = @_;
    $common->{want_a_dir} = 1;
    $o->ask_fileW($common);
}

#- predecated
sub ask_file {
    my ($o, $title, $o_dir) = @_;
    $o->ask_fileW({ title => $title, want_a_dir => 0, directory => $o_dir });
}

sub ask_fileW {
    my ($o, $common) = @_;
    $o->ask_from_entry($common->{title}, $common->{message} || N("Choose a file"));
}

sub ask_from_list {
    my ($o, $title, $message, $l, $o_def) = @_;
    ask_from_listf($o, $title, $message, undef, $l, $o_def);
}

sub ask_from_list_ {
    my ($o, $title, $message, $l, $o_def) = @_;
    ask_from_listf($o, $title, $message, \&translate, $l, $o_def);
}

sub ask_from_listf_ {
    my ($o, $title, $message, $f, $l, $o_def) = @_;
    ask_from_listf($o, $title, $message, sub { translate($f->(@_)) }, $l, $o_def);
}
sub ask_from_listf {
    my ($o, $title, $message, $f, $l, $o_def) = @_;
    ask_from_listf_raw($o, { title => $title, messages => $message }, $f, $l, $o_def);
}
sub ask_from_listf_raw {
    my ($_o, $_common, $_f, $l, $_o_def) = @_;
    @$l == 0 and die "ask_from_list: empty list\n" . backtrace();
    @$l == 1 and return $l->[0];
    goto &ask_from_listf_raw_no_check;
}

sub ask_from_listf_raw_no_check {
    my ($o, $common, $f, $l, $o_def) = @_;

    if (@$l <= ($::isWizard ? 1 : 2)) {
	my ($ok, $cancel) = map { $_ && may_apply($f, $_) } @$l;
	if (length "$ok$cancel" < 70) {
	    my $ret = eval {
		put_in_hash($common, { ok => $ok, 
				       if_($cancel, cancel => $cancel, focus_cancel => $o_def eq $l->[1]) });
		ask_from_no_check($o, $common, []) ? $l->[0] : $l->[1];
	    };
	    die if $@ && $@ !~ /^wizcancel/;
	    return $@ ? undef : $ret;
	}
    }
    ask_from_no_check($o, $common, [ { val => \$o_def, type => 'list', list => $l, format => $f } ]) && $o_def;
}

sub ask_from_treelist {
    my ($o, $title, $message, $separator, $l, $o_def) = @_;
    ask_from_treelistf($o, $title, $message, $separator, undef, $l, $o_def);
}
sub ask_from_treelist_ {
    my ($o, $title, $message, $separator, $l, $o_def) = @_;
    my $transl = sub { join '|', map { translate($_) } split(quotemeta($separator), $_[0]) }; 
    ask_from_treelistf($o, $title, $message, $separator, $transl, $l, $o_def);
}
sub ask_from_treelistf {
    my ($o, $title, $message, $separator, $f, $l, $o_def) = @_;
    ask_from($o, $title, $message, [ { val => \$o_def, separator => $separator, list => $l, format => $f, sort => 1 } ]) or return;
    $o_def;
}

sub ask_many_from_list {
    my ($o, $title, $message, @l) = @_;
    @l = grep { @{$_->{list}} } @l or return '';
    foreach my $h (@l) {
	$h->{e}{$_} = {
	    text => may_apply($h->{label}, $_),
	    val => $h->{val} ? $h->{val}->($_) : do {
		my $i =
		  $h->{value} ? $h->{value}->($_) : 
		    $h->{values} ? member($_, @{$h->{values}}) : 0;
		\$i;
	    },
	    type => 'bool',
	    help => may_apply($h->{help}, $_, ''),
	    icon => may_apply($h->{icon2f}, $_, ''),
	} foreach @{$h->{list}};
	if ($h->{sort}) {
	    $h->{list} = [ sort { $h->{e}{$a}{text} cmp $h->{e}{$b}{text} } @{$h->{list}} ];
	}
    }
    $o->ask_from($title, $message, [ map { my $h = $_; map { $h->{e}{$_} } @{$h->{list}} } @l ]) or return;

    @l = map {
	my $h = $_;
	[ grep { ${$h->{e}{$_}{val}} } @{$h->{list}} ];
    } @l;
    wantarray() ? @l : $l[0];
}

sub ask_from_entry {
    my ($o, $title, $message, %callback) = @_;
    first(ask_from_entries($o, $title, $message, [''], %callback));
}
sub ask_from_entries {
    my ($o, $title, $message, $l, %callback) = @_;

    my @l = map { my $i = ''; { label => $_, val => \$i } } @$l;

    $o->ask_from_({ title => $title, messages => $message, %callback, 
		    focus_first => 1 }, \@l) or return;
    map { ${$_->{val}} } @l;
}

sub ask_from__add_modify_remove {
    my ($o, $title, $message, $l, %callback) = @_;
    die "ask_from__add_modify_remove only handles one item" if @$l != 1;

    $callback{$_} or internal_error("missing callback $_") foreach qw(Add Modify Remove);

    if ($o->can('ask_from__add_modify_removeW')) {
	$o->ask_from__add_modify_removeW($title, $message, $l, %callback);
    } else {
	my $e = $l->[0];
	my $chosen_element;
	put_in_hash($e, { allow_empty_list => 1, val => \$chosen_element, type => 'list' });

	while (1) {
	    my $continue;
	    my @l = (@$l, 
		     map { my $s = $_; { val => translate($_), clicked_may_quit => sub { 
					     my $r = $callback{$s}->($chosen_element);
					     defined $r or return;
					     $continue = 1;
					 } } }
		     N_("Add"), if_(@{$e->{list}} > 0, N_("Modify"), N_("Remove")));
	    $o->ask_from_({ title => $title, messages => $message, %callback }, \@l) or return;
	    return 1 if !$continue;
	}
    }
}


#- can get a hash of callback: validate
#- moreove if you pass a hash with a field list -> combo
#- if you pass a hash with a field hidden -> emulate stty -echo
sub ask_from {
    my ($o, $title, $message, $l, %callback) = @_;
    ask_from_($o, { title => $title, messages => $message, %callback }, $l);
}


sub _normalize_entry {
    my ($o, $e) = @_;

    if (my $li = $e->{list}) {
	ref($e->{val}) =~ /SCALAR|REF/ or internal_error($e->{val} ? "field {val} must be a reference (it is $e->{val})" : "field {val} is mandatory");	#-#
	if ($e->{sort} || @$li > 10 && !exists $e->{sort}) {
	    my @l2 = map { may_apply($e->{format}, $_) } @$li;
	    my @places = sort { $l2[$a] cmp $l2[$b] } 0 .. $#l2;
	    $e->{list} = $li = [ map { $li->[$_] } @places ];
	}
	$e->{type} = 'iconlist' if $e->{icon2f};
	$e->{type} = 'treelist' if $e->{separator} && $e->{type} ne 'combo';
	add2hash_($e, { not_edit => 1 });
	$e->{type} ||= 'combo';

	if (!$e->{not_edit}) {
	    die q(when using "not_edit" you must use strings, not a data structure) if ref(${$e->{val}}) || any { ref $_ } @$li;
	}
	if ($e->{type} ne 'combo' || $e->{not_edit}) {
	    ${$e->{val}} = $li->[0] if !member(may_apply($e->{format}, ${$e->{val}}), map { may_apply($e->{format}, $_) } @$li);
	}
    } elsif ($e->{type} eq 'range') {
	$e->{min} <= $e->{max} or die "bad range min $e->{min} > max $e->{max} (called from " . join(':', caller()) . ")";
	${$e->{val}} = max($e->{min}, min(${$e->{val}}, $e->{max}));
    } elsif ($e->{type} eq 'button' || $e->{clicked} || $e->{clicked_may_quit}) {
	$e->{type} = 'button';
	$e->{clicked_may_quit} ||= $e->{clicked} ? sub { $e->{clicked}(); 0 } : sub {};	    
	$e->{val} = \ (my $_v = $e->{val}) if !ref($e->{val});
    } elsif (!$e->{type} && !$e->{val}) {
	$e->{type} = 'only_label';
	$e->{val} = \ (my $_v = $o->adapt_markup(delete $e->{label}));
    } elsif ($e->{type} eq 'label' || !ref($e->{val})) {
	$e->{type} = 'label';
	$e->{val} = \ (my $_v = $e->{val}) if !ref($e->{val});
    } elsif ($e->{type} eq 'expander') {
	_normalize_entries($o, $e->{children});
    } else {
	$e->{type} ||= 'entry';
    }
    $e->{label} = $o->adapt_markup($e->{label}) if $e->{label};
}

sub _normalize_entries {
    my ($o, $l) = @_;

    ref($l) eq 'ARRAY' or internal_error('ask_from_normalize');

    _normalize_entry($o, $_) foreach @$l;

    #- do not display empty lists and one element lists
    @$l = grep { 
	if ($_->{list} && $_->{not_edit} && !$_->{allow_empty_list}) {
	    if (!@{$_->{list}}) {
		eval {
		    require 'log.pm'; #- "require log" causes some pb, perl thinking that "log" is the log() function
		    log::l("ask_from_normalize: empty list for $_->{label}\n" . backtrace());
		};
	    }
	    @{$_->{list}} > 1;
	} else {
	    1;
	}
    } @$l;
}

sub ask_from_normalize {
    my ($o, $common, $l) = @_;

    if ($common->{focus_first}) {
	if (my $e = find { $_->{val} } @$l) {
	    $e->{focus} = sub { 1 };
	}
    }

    _normalize_entries($o, $l);

    if (!$common->{title} && $::isStandalone) {
	($common->{title} = $0) =~ s|.*/||;
    }
    $common->{interactive_help} ||= $o->{interactive_help};
    $common->{interactive_help} ||= $common->{interactive_help_id} && $o->interactive_help_sub_get_id($common->{interactive_help_id});
    if (!$::isInstall) {
        delete $common->{$_} foreach qw(interactive_help interactive_help_id);
    }
    $common->{advanced_label} ||= N("Advanced");
    $common->{advanced_label_close} and log::l("advanced_label_close is not used anymore");
    $common->{$_} = $common->{$_} ? [ map { $o->adapt_markup($_) } deref($common->{$_}) ] : [] 
      foreach qw(messages advanced_messages);

    if ($common->{callbacks}) {
	$common->{callbacks}{changed} and internal_error(q(global "changed" callback is not handled anymore, use a per-entry changed callback));
	$common->{callbacks}{focus_out} and internal_error(q(global "focus_out" callback is not handled anymore, use a per-entry focus_out callback));
	add2hash($common, delete $common->{callbacks});
    }
    if (my $complete = delete $common->{complete}) {
	$common->{validate} = sub { !first($complete->()) };
    }
    add2hash_($common, { validate => sub { 1 } });
}

sub migrate_advanced {
    my ($common, $l) = @_;
    my ($l1, $l2) = partition { !$_->{advanced} } @$l;
    my $advanced_message = join("\n", @{$common->{advanced_messages}});
    [ @$l1, if_(@$l2, { type => 'expander', 
			if_($advanced_message, message => $advanced_message),
			text => $common->{advanced_label},
			expanded => $common->{advanced_state},
			children => $l2,
		    }) ];
}

sub ask_from_ {
    my ($o, $common, $l) = @_;
    ask_from_normalize($o, $common, $l);
    @$l or return 1;
    $common->{cancel} = '' if !defined wantarray();
    ask_from_real($o, $common, $l);
}
sub ask_from_no_check {
    my ($o, $common, $l) = @_;
    ask_from_normalize($o, $common, $l);
    $common->{cancel} = '' if !defined wantarray();
    my $l_ = migrate_advanced($common, $l);
    $o->ask_fromW($common, $l_);
}
sub ask_from_real {
    my ($o, $common, $l) = @_;
    my $l_ = migrate_advanced($common, $l);
    my $v = $o->ask_fromW($common, $l_);

    foreach my $e (@$l) {
	if ($e->{type} eq 'range') {
	    ${$e->{val}} = max($e->{min}, min(${$e->{val}}, $e->{max}));
	}
    }

    %$common = ();
    $v;
}


sub ask_browse_tree_info {
    my ($o, $title, $message, $common) = @_;
    $common->{interactive_help} ||= $common->{interactive_help_id} && $o->interactive_help_sub_get_id($common->{interactive_help_id});