#?SuikaWikiConfig/2.0

Plugin:
  @Name: StyleSheet
  @Description:
    @@@: Stylesheet support
    @@lang:en
  @License: %%Perl%%
  @Author:
    @@Name:
      @@@@: Wakaba
      @@@lang:ja
      @@@script:Latn
    @@Mail[list]: w@suika.fam.cx
  @Date.RCS:
    $Date: 2005/03/15 08:50:05 $
  @RequiredPlugin[list]:
    Error
    HTML
  @RequiredModule[list]:
    URI
  @Use:
    use URI;
    use Message::Util::Error;
    my $WIKIRESOURCE;
  @Namespace:
    @@ss:
      http://suika.fam.cx/~wakaba/archive/2004/05/sw-stylesheet#
    @@media-type:
      http://suika.fam.cx/~wakaba/-temp/2004/04/24/mt#
    @@edit:
      http://suika.fam.cx/~wakaba/-temp/2004/7/25/sw-edit#

PluginConst:
  @NS_XHTML1:
    http://www.w3.org/1999/xhtml
  @WIKIRESOURCE:
    {($WIKIRESOURCE ||= SuikaWiki::Plugin->module_package ('WikiResource'))}

Format:
  @ModuleName:
    StyleSheet::CSS
  
  @Name: CSS
  @Type: text/css
  @Description:
    @@@: Cascading Style Sheets (CSS)
    @@lang: en
  
  @Use:
    use Message::Markup::XML::QName qw(NS_xml_URI);
  
  @Converter:
    @@Type: text/css
    @@Description:
      @@@: CSS -> CSS (no convertion)
      @@lang: en
    @@ToString:
      return $$source;
## BUG: Insecure specification MUST be removed

  @Converter:
    @@Type: text/html
    @@IsFragment: 1
    @@Description:
      @@@: CSS with some decoration, marked-up in HTML 
      @@lang: en
    @@Main:
      my $node = $opt->{-parent}->append_new_node 
                   (type => '#element',
                    namespace_uri => $NS_XHTML1,
                    local_name => 'pre');
      $node->set_attribute (class => 'text-css');
      $node->set_attribute (space => 'preserve', namespace_uri => NS_xml_URI);
      $node->append_text ($$source);
      return $node;

  @content_written:
    @@Main:
      if ($opt{wiki}->{config}->{<Q:ss:use-static>}) {
        $opt{wiki}->{db}->set (static__css => $opt{page} => ${$opt{new_content}});
      }

  @content_removed:
    @@Main:
      if ($opt{wiki}->{config}->{<Q:ss:use-static>}) {
        $opt{wiki}->{db}->delete (static__css => $opt{page});
      }

  @content_type_changed_from:
    @@Main:
      if ($opt{wiki}->{config}->{<Q:ss:use-static>}) {
        $opt{wiki}->{db}->delete (static__css => $opt{page});
      }

  @Prop:
    @@edit:new-mode--edit: edit
    @@edit:new-mode--adminedit: adminedit

ViewDefinition:
  @Mode: css
  @Condition:
    @@http-method[list]:
      GET
      HEAD
      POST
  @Description:
    @@@: CSS Style Sheet
    @@lang: en
  @template:
    @@http-status-code: 200
    @@media-type: text/css
    @@use-media-type-charset: 1
    @@expires: %%stylesheet%%
    @@body:
      %read (Type => {text/css}, return-type => {ToString},
             when-no-converter => 406);

FormattingRule:
  @Category[list]:
    view
    view-resource
  @Name: styles-wiki-html
  @Description:
    @@@:
      Stylesheet list as HTML (link element)
    @@lang: en
  @Paramater:
    @@Name: page
    @@Type: WikiName
    @@Default: (auto)
    @@Description:
      @@@@: WikiPage in which stylesheet list is defined
      @@@lang: en
  @Formatting:
    my $list = __FUNCPACK__->_get_stylelist_definition_page
                 (page => $o->{wiki}->name
                            ($p->{page} ||
                             $o->{wiki}->{config}->{page}
                                       ->{'StyleSheetList(text/html)'} ||
                             [qw!Wiki Style List text/html!]),
                  o => $o, wiki => $o->{wiki});
    return unless $list;
    my $parent = $p->{-parent};
    
    my $ua_apply;
    my $dg = $o->{wiki}->{var}->{client}->{downgrade};
    if ($dg->{stylesheet_non_standard}) {
      $ua_apply = $dg->{ua_netscape4} ? 'Netscape4'
                : $dg->{ua_winie60}   ? 'WinIE6.0'
                : $dg->{ua_winie55}   ? 'WinIE5.5'
                : $dg->{ua_winie50}   ? 'WinIE5.0'
                : $dg->{ua_winie40}   ? 'WinIE4.0'
                : $dg->{ua_winie30}   ? 'WinIE3.0'
                :                       1;
    }

    my $mkuri = $o->{wiki}->{config}->{<Q:ss:wikiname-to-uri>} ||
 \               \&__FUNCPACK__::generate_uri;
    
    for my $set (@{$list->child_nodes}) {
      if ($set->local_name eq 'StyleSet') {
        my $apply = $set->get_attribute_value ('Apply',
                                               default => ['alternate'],
                                               as_array => 1);
        my $type = {
                     map {$_ => 1}
   \                 @$apply
                   };
        next if $ua_apply and not $type->{$ua_apply};
        my $rel = $type->{alternate} ? 'alternate stylesheet' : 'stylesheet';
        my $title = __FUNCPACK__->_get_styleset_title
                                    (StyleSet => $set, o => $o,
                                     type => $type);
        for my $sheet (@{$set->child_nodes}) {
          if ($sheet->local_name eq 'StyleSheet') {
            my $stype = {
                    map {$_ => 1}
  \                 @{$sheet->get_attribute_value ('Apply', default => $apply,
                                                   as_array => 1)}
                   };
            next if $ua_apply and not $stype->{$ua_apply};
            next if not $ua_apply and (not $stype->{alternate} and
                                       not $stype->{preferred} and
                                       not $stype->{persistent});
            my $link = $parent->append_new_node
                                  (type => '#element',
                                   namespace_uri => $NS_XHTML1,
                                   local_name => 'link');
            $link->option (use_EmptyElemTag => 1);
            $link->set_attribute (rel => $rel);
            $link->set_attribute (title => $title) unless $type->{persistent};
            my $media_type = $sheet->get_attribute_value
                                       ('Type', default => 'text/css');
            ## TODO: parameter
            $link->set_attribute (type => $media_type);
            unless ($dg->{html_link_no_media}) {
              my $media_descriptor = $sheet->get_attribute_value ('Media');
              $link->set_attribute (media => $media_descriptor || 'all');
            }
            my $uri = $mkuri->(undef, o => $o, wiki => $o->{wiki},
                               wikiname => $o->{wiki}->name
                                         ($sheet->get_attribute_value
                                              ('WikiPage', default => '')),
                               mode => 'css'); ## ISSUE: Make this media-type independent!
            $link->set_attribute (href => $uri);
            $parent->append_text ("\n");
          }
        }
        
      }
    }

FormattingRule:
  @Category[list]:
    view
    view-resource
  @Name: styles-wiki-xml
  @Description:
    @@@:
      Stylesheet list in xml-stylesheet processing instructions
    @@lang: en
  @Parameter:
    @@Name: downgrade-html
    @@Type: boolean
    @@Default: "0"
    @@Description:
      @@@@:
        HTML downgrade mode.  PIs are not outputed if User-Agent does not
        support PIs (eg. Classic Mozilla).
      @@lang: en
  @Paramater:
    @@Name: page
    @@Type: WikiName
    @@Default: (auto)
    @@Description:
      @@@@: WikiPage in which stylesheet list is defined
      @@@lang: en
  @Formatting:
    __ATTRTEXT:%downgrade_html__;
    if ($p->{downgrade_html}) {
      return if $o->{wiki}->{var}->{client}->{downgrade}->{html_no_pi};
    }
    my $list = __FUNCPACK__->_get_stylelist_definition_page
                 (page => $o->{wiki}->name
                            ($p->{page} ||
                             $o->{wiki}->{config}->{page}
                                       ->{'StyleSheetList(text/html)'} ||
                             [qw!Wiki Style List text/html!]),
                  o => $o, wiki => $o->{wiki});
    return unless $list;
    my $parent = $p->{-parent};

    my $mkuri = $o->{wiki}->{config}->{<Q:ss:wikiname-to-uri>} ||
 \               \&__FUNCPACK__::generate_uri;
    
    for my $set (@{$list->child_nodes}) {
      if ($set->local_name eq 'StyleSet') {
        my $apply = $set->get_attribute_value
                             ('Apply', default => ['alternate'],
                              as_array => 1);
        my $type = {map {$_ => 1} @$apply};
        my $rel = $type->{alternate} ? 'alternate stylesheet' : 'stylesheet';
        my $title = __FUNCPACK__->_get_styleset_title
                                    (StyleSet => $set, o => $o,
                                     type => $type);
        for my $sheet (@{$set->child_nodes}) {
          if ($sheet->local_name eq 'StyleSheet') {
            my $stype = {
                    map {$_ => 1}
 \                  @{$sheet->get_attribute_value ('Apply', default => $apply,
                                                   as_array => 1)}
                   };
            next if (not $stype->{alternate} and
                     not $stype->{preferred} and
                     not $stype->{persistent});
            my $link = $parent->append_new_node
                                  (type => '#pi',
                                   local_name => 'xml-stylesheet');
            $link->set_attribute (alternate => $type->{preferred} ? 'no'
                                                                  : 'yes')
              unless $type->{persistent};
            $link->set_attribute (title => $title) unless $type->{persistent};
            my $media_type = $sheet->get_attribute_value
                                       ('Type', default => 'text/css');
            ## TODO: parameter
            $link->set_attribute (type => $media_type);
            unless ($o->{wiki}->{var}->{client}->{downgrade}
                      ->{html_link_no_media}) {
              my $media_descriptor = $sheet->get_attribute_value ('Media');
              $link->set_attribute (media => $media_descriptor || 'all');
            }
            my $uri = $mkuri->(undef, o => $o, wiki => $o->{wiki},
                               wikiname => $o->{wiki}->name
                                         ($sheet->get_attribute_value
                                              ('WikiPage', default => '')),
                               lm => time,     ## TODO: Should be last-modified
                               mode => 'css'); ## ISSUE: Make this media-type independent!
            $link->set_attribute (href => $uri);
            $parent->append_text ("\n");
          }
        }
      }
    }

Function:
  @Name: generate_uri
  @Description:
    @@@: Default generator for stylesheet URI
    @@lang: en
  @Main:
    my (undef, %opt) = @_;
    return $opt{wiki}->uri_reference
                                (page => $opt{wikiname},
                                 mode => $opt{mode},
                                 with_lm => 1, base => 1);

ViewDefinition:
  @Mode: ss--no-static
  @Condition:
    @@http-method[list]:
      GET
      HEAD
      POST
  @Description:
    @@@: Generate static version
    @@lang: en
  @method:
    @@Name: main
    @@@:
      require SuikaWiki::Output::HTTP;
      my $wiki = $self->{view}->{wiki};
      $wiki->init_db;

      GENSTATIC: {
        last GENSTATIC unless ref $wiki->{config}->{<Q:ss:uri-to-wikiname>} and
                              $wiki->{config}->{<Q:ss:use-static>} and
                              $wiki->{db} and $wiki->{input};
        my $uri = $wiki->{input}->meta_variable ('REDIRECT_URL');
        last GENSTATIC unless $uri;
        my $wn = $wiki->{config}->{<Q:ss:uri-to-wikiname>}
                      ->(undef, wiki => $wiki,
                         uri => URI->new ($uri));

        my $prop = $wiki->{db}->get (content_prop => $wn);
        my $mt = $prop->get_attribute_value (<Q:media-type:media-type>,
                                             default => '--');
        last GENSTATIC unless $mt eq 'IMT:text/css##';
        
        $wiki->{db}->set (static__css => $wn =>
                          $wiki->{db}->get (content => $wn));

        $uri = $wiki->{config}->{<Q:ss:wikiname-to-uri>}
                    ->(undef, wiki => $wiki,
                       wikiname => $wn);
        $uri = $uri->abs ($wiki->uri_reference);
        $uri->query (time);
        
        my $output = new SuikaWiki::Output::HTTP (wiki => $wiki);
        $output->set_redirect (uri => $uri, status_code => 303,
                               status_phrase => 'Created');
        $output->output (output => 'http-cgi');
        
        return;
      }
      my $output = new SuikaWiki::Output::HTTP (wiki => $wiki);
      $output->{status_code} = 404; 
      $output->{entity}->{media_type} = 'text/plain';
      $output->{entity}->{body} = '404';
      $output->output (output => 'http-cgi');

FormattingRule:
  @Category[list]:
    view
    view-resource
    form-input
  @Name: select-user-preferred-style
  @Description:
    @@@:
      Select user preferred style
    @@lang: en
  @Paramater:
    @@Name: page
    @@Type: WikiName
    @@Default: (auto)
    @@Description:
      @@@@: WikiPage in which stylesheet list is defined
      @@@lang: en
  @Formatting:
    __ATTRTEXT:%page__;
    my $list = __FUNCPACK__->_get_stylelist_definition_page
                 (page => $o->{wiki}->name
                            ($p->{page} ||
                             $o->{wiki}->{config}->{page}
                                       ->{'StyleSheetList(text/html)'} ||
                             [qw!Wiki Style List text/html!]),
                  o => $o, wiki => $o->{wiki});
    return unless $list;
    my $form = $p->{-parent}->append_new_node
                                  (type => '#element',
                                   namespace_uri => $NS_XHTML1,
                                   local_name => 'form');
    my $id = SuikaWiki::Plugin->module_package ('WikiFormCore')
                              ->control_id ($o,
                                            local_id => 'style-selector',
                                            require_local_id => 1);
    $form->set_attribute (id => $id->{global_id});
    my $div = $form->append_new_node
                                  (type => '#element',
                                   namespace_uri => $NS_XHTML1,
                                   local_name => 'div');
    my $parent = $div->append_new_node
                                  (type => '#element',
                                   namespace_uri => $NS_XHTML1,
                                   local_name => 'select');    
    $parent->set_attribute (id => $id->{global_id}.'-list');
    
    my $default = $parent->append_new_node
                              (type => '#element',
                               namespace_uri => $NS_XHTML1,
                               local_name => 'option');
    $default->set_attribute (value => 'no-style');
    $default->append_text ($WIKIRESOURCE->get (name => 'Style:Default',
                                               o => $o, wiki => $o->{wiki}));
    my $selected = 0;
    
    for my $set (@{$list->child_nodes}) {
      if ($set->local_name eq 'StyleSet') {
        my $type = {map {$_ => 1}
                   @{
                   $set->get_attribute_value ('Apply', default => ['alternate'])
                   }};
        next unless $type->{preferred} or $type->{alternate};
        my $title = __FUNCPACK__->_get_styleset_title
                                    (StyleSet => $set, o => $o,
                                     type => $type);
        my $link = $parent->append_new_node
                              (type => '#element',
                               namespace_uri => $NS_XHTML1,
                               local_name => 'option');
        $link->set_attribute (selected => 'selected'), $selected = 1
          if $type->{preferred};
        $link->set_attribute (value => $title);
        $link->append_text ($title);
        $parent->append_text ("\n");
      }
    }
    
    $default->set_attribute (selected => 'selected') unless $selected;
    
    for ($div->append_new_node (type => '#element',
                                namespace_uri => $NS_XHTML1,
                                local_name => 'input')) {
      $_->set_attribute (type => 'button');
      $_->set_attribute (id => $id->{global_id}.'-save');
      $_->set_attribute (value => $WIKIRESOURCE->get
                                    (name => 'Style:Save',
                                     o => $o, wiki => $o->{wiki}));
      $_->set_attribute (class => 'save');
      $_->option (use_EmptyElemTag => 1);
    }
    for ($div->append_new_node (type => '#element',
                                namespace_uri => $NS_XHTML1,
                                local_name => 'input')) {
      $_->set_attribute (type => 'reset');
      $_->set_attribute (id => $id->{global_id}.'-reset');
      $_->set_attribute (value => $WIKIRESOURCE->get
                                    (name => 'Style:Reset',
                                     o => $o, wiki => $o->{wiki}));
      $_->set_attribute (class => 'reset');
      $_->option (use_EmptyElemTag => 1);
    }
    
    return if $o->{wiki}->{var}->{client}->{downgrade}->{js_no_regex};
    __ATTRTEXT:%expires__;
    my $cookie_path = $o->{wiki}->uri_reference->path;
    for ($div->append_new_node (type => '#element', 
                                namespace_uri => $NS_XHTML1,
                                local_name => 'script')) {
      $_->set_attribute (type => $o->{wiki}->{var}->{client}->{downgrade}
                                   ->{media_type_no_app_js}
                                 ? 'text/javascript'
                                 : 'application/x-javascript');
      $_->set_attribute (defer => 'defer');
      ## Gecko assumes <script> content as CDATA even if it is XHTML,
      ## when it is labeled as text/html.  (Pseudo) comment declaration
      ## nor CDATA marked section can be used to keep compatibility and
      ## well-formedness.  Use #xml type, instead of #text, not to escape
      ## GREATER-THAN SIGN.
      $_->append_new_node (type => '#xml', value => <<EOH);
      
	function getCookieValue (name) {
	  var c = document.cookie.split(';');
	  for (var i = 0; c.length > i; i++) {
	    var v = c[i].split('=');
	    if (v[0].replace(/^\\s+/,'').replace(/\\s+\$/,'') == name) {
	      return decodeURIComponent (v[1].replace(/^\\s+/,'')
                                             .replace(/\\s+\$/,''));
	    }
	  }
          return '';
	}
	var selectList = document.getElementById('$id->{global_id}-list');
	selectList.value = getCookieValue('Selected');
	selectList.onchange = function () {
	  var selectList = document.getElementById('$id->{global_id}-list');
	  for (var i = 0; document.styleSheets.length > i; i++) {
	    var s = document.styleSheets.item(i);
	    if (s.href != document.URL) {
               if (s.title)
	         s.disabled = (s.title != selectList.value);
	    }
	  }
	}
	document.getElementById('$id->{global_id}-save').onclick = function () {
	  var selectList = document.getElementById('$id->{global_id}-list');
	  var expires = new Date();
	  expires.setTime (expires.getTime()
                          + 1000*3600*24*@{[$p->{expires}||365]});
	  document.cookie = 'Selected=' + encodeURIComponent(selectList.value)
                          + ';path=$cookie_path;expires='+expires.toGMTString();
	}
	document.getElementById('$id->{global_id}-reset').onclick = function () {
	  var expires = new Date();
	  expires.setTime (expires.getTime() - 3600);
	  document.cookie = 'Selected=;path=$cookie_path;expires='
                          + expires.toGMTString();
	}
      
      EOH
    }

FormattingRule:
  @Category[list]:
    view
    view-resource
    form-input
  @Name: apply-user-preferred-style
  @Description:
    @@@:
      Applying user preferred style
    @@lang: en
  @Formatting:
    return if $o->{wiki}->{var}->{client}->{downgrade}->{js_no_regex};
    for ($p->{-parent}->append_new_node
                               (type => '#element', 
                                namespace_uri => $NS_XHTML1,
                                local_name => 'script')) {
      $_->set_attribute (type => $o->{wiki}->{var}->{client}->{downgrade}
                                   ->{media_type_no_app_js}
                                 ? 'text/javascript'
                                 : 'application/x-javascript');
      $_->set_attribute (defer => 'defer');
      ## TODO: Some mechanism to prevent multiple outputing of same functions
      ##       required.
      $_->append_new_node (type => '#xml', value => <<EOH);
      
	function getCookieValue (name) {
	  var c = document.cookie.split(';');
	  for (var i = 0; c.length > i; i++) {
	    var v = c[i].split('=');
	    if (v[0].replace(/^\\s+/,'').replace(/\\s+\$/,'') == name) {
	      return decodeURIComponent (v[1].replace(/^\\s+/,'')
                                             .replace(/\\s+\$/,''));
	    }
	  }
          return '';
	}

	var styleName = getCookieValue('Selected');
	if (styleName) {
	  for (var i = 0; document.styleSheets.length > i; i++) {
	    var s = document.styleSheets.item(i);
	    if (s.href != document.URL) {
               if (s.title)
	         s.disabled = (s.title != styleName) ? true : false;
	    }
	  }
	}
      
      EOH
    }

Function:
  @Name: _get_stylelist_definition_page
  @Main:
    my (undef, %opt) = @_;
    my $content;
    my $content_prop;
    if ($opt{wiki}->{db}) {
      try {
        $content = $opt{wiki}->{db}->get (content => $opt{page});
        $content_prop = $opt{wiki}->{db}->get (content_prop => $opt{page});
      } catch SuikaWiki::DB::Util::Error with {
        my $err = shift;
        $err->throw if $err->{-type} eq 'ERROR_REPORTED';
        $content = undef;
      };
    }
    my $format = SuikaWiki::Plugin->module_package ('WikiFormat')
                                  ->handler (\$content,
                                             content_prop => $content_prop,
                                             o => $opt{o},
                                             wiki => $opt{o}->{wiki});
    my $cfg;
    try {
      $cfg = $format->convert (\$content,
                               Type => 'application/x.suikawiki.config',
                               Type_param => {version => '2.0'},
                               o => $opt{o}, page => $opt{page});
    } catch SuikaWiki::Format::Definition::error with {
      my $err = shift;
      if ($err->{-type} eq 'CONVERTER_NOT_FOUND') {
        SuikaWiki::Plugin->module_package ('Error')
                         ->report_error_simple
                             ($opt{o}->{wiki},
                              'Condition' => $err->stringify);
      } else {
        $err->throw;
      }
    };
    $cfg;

Function:
  @Name: _get_styleset_title
  @Description:
    @@@: Get "title" of the styleset
    @@lang: en
  @Main:
    my (undef, %opt) = @_;
    my $title;
        if (not $opt{type}->{persistent}) {
          $title = $opt{StyleSet}->get_attribute_value
                                     ('DisplayName', default => '');
          if (length $title) {
            try {
              $title = SuikaWiki::Plugin->formatter ('view_resource')
                                        ->replace ($title,
                                                   param => $opt{o})
                                        ->inner_text;
            } catch Message::Util::Formatter::error with {
              my $err = shift;
              if ($err->{-object}->{-category_name} eq 'view_resource') {
                my $wiki = $err->{option}->{param}->{wiki};
                SuikaWiki::Plugin->module_package ('Error')
                                 ->reporting_formatting_template_error
                                     ($err, $wiki,
                                      template => $title);
              } else {
                $err->throw;
              }
              $title ||= $opt{StyleSet}->get_attribute_value
                                           ('Name', default => '');
            };
          } else {
            $title = $opt{StyleSet}->get_attribute_value ('Name', default => '');
          }
        }
    return $title;

FormattingRule:
  @Category[list]:
    view
    view-resource
    form-input
  @Name: select-user-preferred-mode
  @Description:
    @@@:
      Select user preferred mode
    @@lang: en
  @Formatting:
    my $list = [grep /^[0-9A-Za-z_]/, keys %{$o->{wiki}->{view}->{definition}}];
    my $form = $p->{-parent}->append_new_node
                                  (type => '#element',
                                   namespace_uri => $NS_XHTML1,
                                   local_name => 'form');
    my $id = SuikaWiki::Plugin->module_package ('WikiFormCore')
                              ->control_id ($o,
                                            local_id => 'spss--mode-selector',
                                            require_local_id => 1);
    $form->set_attribute (id => $id->{global_id});
    my $div = $form->append_new_node
                                  (type => '#element',
                                   namespace_uri => $NS_XHTML1,
                                   local_name => 'div');
    my $parent = $div->append_new_node
                                  (type => '#element',
                                   namespace_uri => $NS_XHTML1,
                                   local_name => 'select');    
    $parent->set_attribute (id => $id->{global_id}.'-list');
    
    my $default = $parent->append_new_node
                              (type => '#element',
                               namespace_uri => $NS_XHTML1,
                               local_name => 'option');
    $default->set_attribute (value => 'default');
    $default->append_text ($WIKIRESOURCE->get (name => 'Mode:Default',
                                               o => $o, wiki => $o->{wiki}));
    $default->set_attribute (selected => 'selected');
    
    for my $set (@$list) {
        my $title = $WIKIRESOURCE->get (name => 'Mode:'.$set,
                                        o => $o, wiki => $o->{wiki});
        my $link = $parent->append_new_node
                              (type => '#element',
                               namespace_uri => $NS_XHTML1,
                               local_name => 'option');
        $link->set_attribute (value => $set);
        $link->append_text ($title);
        $parent->append_text ("\n");
    }
        
    for ($div->append_new_node (type => '#element',
                                namespace_uri => $NS_XHTML1,
                                local_name => 'input')) {
      $_->set_attribute (type => 'button');
      $_->set_attribute (id => $id->{global_id}.'-save');
      $_->set_attribute (value => $WIKIRESOURCE->get
                                    (name => 'Mode:Save',
                                     o => $o, wiki => $o->{wiki}));
      $_->set_attribute (class => 'save');
      $_->option (use_EmptyElemTag => 1);
    }
    for ($div->append_new_node (type => '#element',
                                namespace_uri => $NS_XHTML1,
                                local_name => 'input')) {
      $_->set_attribute (type => 'reset');
      $_->set_attribute (id => $id->{global_id}.'-reset');
      $_->set_attribute (value => $WIKIRESOURCE->get
                                    (name => 'Mode:Reset',
                                     o => $o, wiki => $o->{wiki}));
      $_->set_attribute (class => 'reset');
      $_->option (use_EmptyElemTag => 1);
    }
    
    return if $o->{wiki}->{var}->{client}->{downgrade}->{js_no_regex};
    __ATTRTEXT:%expires__;
    my $cookie_path = $o->{wiki}->uri_reference->path;
    for ($div->append_new_node (type => '#element', 
                                namespace_uri => $NS_XHTML1,
                                local_name => 'script')) {
      $_->set_attribute (type => $o->{wiki}->{var}->{client}->{downgrade}
                                   ->{media_type_no_app_js}
                                 ? 'text/javascript'
                                 : 'application/x-javascript');
      $_->set_attribute (defer => 'defer');
      $_->append_new_node (type => '#xml', value => <<EOH);
      
	function getCookieValue (name) {
	  var c = document.cookie.split(';');
	  for (var i = 0; c.length > i; i++) {
	    var v = c[i].split('=');
	    if (v[0].replace(/^\\s+/,'').replace(/\\s+\$/,'') == name) {
	      return decodeURIComponent (v[1].replace(/^\\s+/,'')
                                             .replace(/\\s+\$/,''));
	    }
	  }
          return '';
	}

	document.getElementById ('$id->{global_id}-list').value
                                = getCookieValue('SelectedMode');
	document.getElementById ('$id->{global_id}-save').onclick = function () {
	  var expires = new Date ();
	  expires.setTime (expires.getTime ()
                          + 1000*3600*24*@{[$p->{expires}||365]});
	  document.cookie = 'SelectedMode='
	                  + encodeURIComponent
                              (document.getElementById('$id->{global_id}-list')
	                               .value)
	                  + ';path=$cookie_path;expires='
	                  + expires.toGMTString ();
	}
	document.getElementById('$id->{global_id}-reset').onclick = function () {
	  var expires = new Date();
	  expires.setTime (expires.getTime() - 3600);
	  document.cookie = 'SelectedMode=;path=$cookie_path;expires='
	                  + expires.toGMTString();
	}
      
      EOH
    }

ViewFragment:
  @Name: ht--stylesheets-html
  @Order: 0
  @Description:
    @@@: Default stylesheets links
    @@lang: en
  @Formatting:
    %styles-wiki-html;

ViewFragment:
  @Name: ht--pre-element-content
  @Order: 0
  @Description:
    @@@: Default stylesheets links (as xml-stylesheet PIs)
    @@lang: en
  @Formatting:
    %styles-wiki-xml (downgrade-html);

ViewFragment:
  @Name: ws--footer
  @Order: 100000
  @Description:
    @@@: Apply user selected stylesheets
    @@lang: en
  @Formatting:
    %apply-user-preferred-style;

Resource:
  @Mode:css:
    @@@: Cascading Style Sheet output
    @@lang: en
  @Mode:Default:
    @@@:
      Default
    @@lang: en
  @Mode:Reset:
    @@@: Reset default mode selection
    @@lang: en
  @Mode:Save:
    @@@: Save default mode selection
    @@lang: en
  @Style:Default:
    @@@: 
      Basic Page Style
    @@: lang: en
  @Style:Reset:
    @@@:
      Reset style selection
    @@lang: en
  @Style:Save:
    @@@:
      Save style selection
    @@lang: en
  @WikiFormat:MediaType:Description:IMT:text/css##:
    @@@: CSS (Cascading Style Sheets)
    @@lang: en
  @WikiFormat:MediaType:Label:IMT:text/css##:
    @@@: CSS
    @@lang: en


