Diff for /loncom/homework/structuretags.pm between versions 1.499 and 1.500

version 1.499, 2011/12/20 22:46:40 version 1.500, 2011/12/27 20:13:22
Line 61  use Apache::lonlocal; Line 61  use Apache::lonlocal;
 use Apache::lonxml;  use Apache::lonxml;
 use Apache::londefdef;  use Apache::londefdef;
 use Apache::lonenc();  use Apache::lonenc();
   use Apache::loncommon();
 use Time::HiRes qw( gettimeofday tv_interval );  use Time::HiRes qw( gettimeofday tv_interval );
 use lib '/home/httpd/lib/perl/';  use lib '/home/httpd/lib/perl/';
 use LONCAPA;  use LONCAPA;
Line 69  BEGIN { Line 70  BEGIN {
     &Apache::lonxml::register('Apache::structuretags',('block','languageblock','translated','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startpartmarker','startouttext','endpartmarker','endouttext','simpleeditbutton','definetag'));      &Apache::lonxml::register('Apache::structuretags',('block','languageblock','translated','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startpartmarker','startouttext','endpartmarker','endouttext','simpleeditbutton','definetag'));
 }  }
   
   
   #---------------------------------------------------------------------------------
   # 
   #  This section of code deals with hyphenation management.
   #  We must do three things:
   #  - keep track fo the desired languages to alter the header.
   #  - provide hyphenation selection as needed by each language that appears in the
   #    text.
   #  - Provide the header text needed to make available the desired hyphenations.
   #
   #
   
   # Hash whose keys are the languages encountered in the document/resource.
   #
   
   my %languages_required;
   ##
   #   Given a language selection as input returns a chunk of LaTeX that
   #   selects the required hyphenator.
   #
   #  @param language - the language being selected.
   #  @return string
   #  @retval The LaTeX needed to select the hyphenation appropriate to the language. 
   #   
   sub select_hyphenation {
       my $language  = shift;
   
       $language = &Apache::loncommon::latexlanguage($language); # Translate -> latex language.
   
       # If there is no latex language there's not much we can do:
   
       if ($language) {
    &require_language($language);
    my $babel_hyphenation = "\\selectlanguage{$language}";
   
    return $babel_hyphenation;
       } else {
    return '';
       }
   }
   ##
   # Selects hyphenation based on the current problem metadata.
   # This requires that
   # - There is a language metadata item set for the problem.
   # - The language has a latex/babel hyphenation.
   #
   # @note: Uses &Apache::lonxml::request to locate the Uri associated with
   #        this problem.
   # @return string (possibly empty).
   # @retval If not empty an appropriate \selectlanguage{} directive.
   #
   sub select_metadata_hyphenation {
       my $uri      = $Apache::lonxml::request->uri;
       my $language = &Apache::lonnet::metadata($uri, 'language'); 
       my $latex_language = &Apache::loncommon::latexhyphenation($language);
       if ($latex_language) {
    return '\selectlanguage{'.$latex_language."}\n";
       }
       return ''; # no latex hyphenation or no lang metadata.
   }
   
   
   ##
   #  Clears the set of languages required by the document being rendered.
   #
   sub clear_required_languages {
       %languages_required = ();
   }
   ##
   # Allows an external client of this module to register a need for a language:
   #
   # @param LaTeX language required:
   #
   sub require_language {
       my $language = shift;
       $languages_required{$language} = 1;
   }
   
   ##
   # Provides the header for babel that indicates the languages
   # the document requires.
   # @return string
   # @retval \usepackage[lang1,lang2...]{babel}
   # @retval ''   if there are no languages_required.
   sub languages_header {
       my $header    ='';
       my @languages = (keys(%languages_required));
   
       # Only generate the header if there are languages:
   
       if (scalar @languages) {
    my $language_list = join(',', (@languages));
    $header  = '\usepackage['.$language_list."]{babel}\n";
       }
       return $header;
   }
   
   #----------------------------------------------------------------------------------
   
 sub start_web {  sub start_web {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     if ($target ne 'edit' && $target ne 'modified') {      if ($target ne 'edit' && $target ne 'modified') {
Line 1228  sub start_problem { Line 1328  sub start_problem {
             }              }
  } elsif ($target eq 'tex') {   } elsif ($target eq 'tex') {
     $result .= 'INSERTTEXFRONTMATTERHERE';      $result .= 'INSERTTEXFRONTMATTERHERE';
       $result .= &select_metadata_hyphenation();
       
   
  }   }
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
Line 1284  sub end_problem { Line 1386  sub end_problem {
  }   }
  my $name_of_resourse= &Apache::lonxml::latex_special_symbols(&get_resource_name($parstack,$safeeval),'header');   my $name_of_resourse= &Apache::lonxml::latex_special_symbols(&get_resource_name($parstack,$safeeval),'header');
  my $begin_doc=' \typeout{STAMPOFPASSEDRESOURCESTART Resource <h2>"'.$name_of_resourse.'"</h2> located in <br /><small><b>'.$env{'request.uri'}.'</b></small><br /> STAMPOFPASSEDRESOURCEEND} \noindent ';   my $begin_doc=' \typeout{STAMPOFPASSEDRESOURCESTART Resource <h2>"'.$name_of_resourse.'"</h2> located in <br /><small><b>'.$env{'request.uri'}.'</b></small><br /> STAMPOFPASSEDRESOURCEEND} \noindent ';
    &clear_required_languages();
  my $toc_line='\vskip 1 mm\noindent '.$startminipage.   my $toc_line='\vskip 1 mm\noindent '.$startminipage.
     '\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}';      '\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}';
   
Line 1558  sub end_block { Line 1661  sub end_block {
     }      }
     return $result;      return $result;
 }  }
   #
   #  <languageblock [include='lang1,lang2...'] [exclude='lang1,lang2...']>
   #  ...
   #  </languageblock>
   #
   #   This declares the intent to provide content that can be rendered in the
   #   set of languages in the include specificatino but not in the exclude
   #   specification.  If a currently preferred language is in the include list
   #   the content in the <languageblock>...</languageblock> is rendered
   #   If the currently preferred language is in the exclude list,
   #   the content in the <languageblock>..></languageblock is not rendered.
   #
   #   Pathalogical case handling:
   #     - Include specified, without the preferred language but exclude  specified
   #       also without the preferred langauge results in rendering the block.
   #     - Exclude specified without include and excluden not containing a 
   #       preferred language renders the block.
   #     - Include and exclude both specifying the preferred language does not
   #       render the block.
   #     - If neither include/exclude is specified, the block gets rendered.
   #
   #  This tag has no effect when target is in {edit, modified}
   #
 sub start_languageblock {  sub start_languageblock {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
     my $result;      my $result = '';
   
     if ($target eq 'web' || $target eq 'grade'   || $target eq 'answer' ||      if ($target eq 'web' || $target eq 'grade'   || $target eq 'answer' ||
  $target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') {   $target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') {
  my $include = $token->[2]->{'include'};   my $include = $token->[2]->{'include'};
  my $exclude = $token->[2]->{'exclude'};   my $exclude = $token->[2]->{'exclude'};
         my @preferred_languages=&Apache::lonlocal::preferred_languages();          my @preferred_languages=&Apache::lonlocal::preferred_languages();
 # This should not even happen, since we should at least have the server language  
         if (!$preferred_languages[0]) { $preferred_languages[0]='en'; }          # This should not even happen, since we should at least have the server language
 # Now loop over all languages in order of preference  
           if (!$preferred_languages[0]) { 
       $preferred_languages[0]='en'; 
    }
   
           # Now loop over all languages in order of preference
   
    my $render;
         foreach my $preferred_language (@preferred_languages) {          foreach my $preferred_language (@preferred_languages) {
 # If the languageblock has no arguments, show the contents  
            $result=1;      # If neither include/nor exlude is present the block is going
       # to get rendered.
   
            my $found=0;             my $found=0;
 # Do we have an include argument?             $render=1;
   
      #  If include is specified,  don't render the block
      #  unless the preferred language is included in the set.
   
    if ($include) {     if ($include) {
 # If include is specified, by default, don't render the block                $render=0;
               $result=0;  
               foreach my $included_language (split(/\,/,$include)) {                foreach my $included_language (split(/\,/,$include)) {
 # ... but if my preferred language is included, render it  
                  if ($included_language eq $preferred_language) {                   if ($included_language eq $preferred_language) {
                     $result=1;                       $render=1; 
                     $found=1;                       $found=1; 
       last; # Only need to find the first.
                  }                   }
               }                }
    }     }
 # Do we have an exclude argument?             # Do we have an exclude argument?
      # If so, and one of the languages matches a preferred language
      # inhibit rendering the block.  Note that in the pathalogical case the
      # author has specified a preferred language in both the include and exclude
      # attribte exclude is preferred.  
   
            if ($exclude) {             if ($exclude) {
               $result=1;                $render=1;
               foreach my $excluded_language (split(/\,/,$exclude)) {                foreach my $excluded_language (split(/\,/,$exclude)) {
                  if ($excluded_language eq $preferred_language) {                   if ($excluded_language eq $preferred_language) {
                     $result=0;                      $render=0;
                     $found=1;                      $found=1;
       last; # Only need to find the first.
                  }                   }
               }                }
    }     }
            if ($found) { last; }             if ($found) { 
          last; # Done on any match of include or exclude.
      }
         }          }
  if ( ! $result ) {   # If $render not true skip the entire block until </languageblock>
    #
   
    if ( ! $render ) {
     my $skip=&Apache::lonxml::get_all_text("/languageblock",$parser,      my $skip=&Apache::lonxml::get_all_text("/languageblock",$parser,
    $style);     $style);
     &Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]");      &Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]");
  }   }
  $result='';   # If $render is true, we've not skipped the contents of the <languageglock>
    # and the normal loncapa processing flow will render it as a matter of course.
   
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result .=&Apache::edit::tag_start($target,$token);   $result .=&Apache::edit::tag_start($target,$token);
  $result .=&Apache::edit::text_arg(&mt('Include Language:'),'include',   $result .=&Apache::edit::text_arg(&mt('Include Language:'),'include',
Line 1630  sub end_languageblock { Line 1780  sub end_languageblock {
     }      }
     return $result;      return $result;
 }  }
   #  languagblock specific tags:
 {  {
     my %available_texts;      # For chunks of a resource that has translations, this hash contains
       # the translations available indexed by language name.
       #
   
       my %available_texts;       
   
       # <translated> starts a block of a resource that has multiple translations.
       # See the <lang> tag as well.
       # When </translated> is encountered if there is a translation for the 
       # currently preferred language, that is rendered inthe web/tex/webgrade
       # targets.  Otherwise, the default text is rendered.
       #
       # Note that <lang> is only registered for the duration of the 
       #  <translated>...</translated> block 
       #
       # Pathalogical case handling:
       #   - If there is no <lang> that specifies a 'default' and there is no
       #     translation that matches a preferred language, nothing is rendered.
       #   - Nested <translated>...</translated> might be linguistically supported by
       #     XML due to the stack nature of tag registration(?) however the rendered
       #     output will be incorrect because there is only one %available_texts
       #     has and end_translated clears it.
       #   - Material outside of a <lang>...</lang> block within the
       #     <translated>...<translated> block won't render either e.g.:
       #    <translated>
       #      The following will be in your preferred langauge:
       #      <lang which='en'>
       #         This section in english
       #      </lang>
       #      <lang which='sgeiso'>
       #         Hier es ist auf Deutsch.
       #      </lang>
       #      <lang which='sfriso'>
       #         En Francais
       #      </lang>
       #    </translated>
       #
       #    The introductory text prior to the first <lang> tag is not rendered.
       #
     sub start_translated {      sub start_translated {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  &Apache::lonxml::register('Apache::structuretags',('lang'));   &Apache::lonxml::register('Apache::structuretags',('lang'));
Line 1651  sub end_languageblock { Line 1839  sub end_languageblock {
     my @possibilities = keys(%available_texts);      my @possibilities = keys(%available_texts);
     my $which =       my $which = 
  &Apache::loncommon::languages(\@possibilities) || 'default';   &Apache::loncommon::languages(\@possibilities) || 'default';
     $result = $available_texts{$which};      if ($target eq 'tex') {
    $result = &select_hyphenation($which);
       }
       $result .= $available_texts{$which};
       if ($target eq 'tex') {
    $result .= &select_metadata_hyphenation(); # Restore original language.
       }
  }   }
  undef(%available_texts);   undef(%available_texts);
  &Apache::lonxml::deregister('Apache::structuretags',('lang'));   &Apache::lonxml::deregister('Apache::structuretags',('lang'));
  return $result;   return $result;
     }      }
   
       # <lang [which='language-name'] [other='lang1,lang2...']>  
       #  Specifies that the block contained within it is a translation 
       #  for a specific language specified by the 'which' attribute. The
       #   'other' attribute can be used by itself or in conjunction with
       #   which to specify this tag _may_ be used as a translation for some
       #   list of languages. e.g.:  <lang which='senisoUS' other='senisoCA,senisoAU,seniso'>
       #   specifying that the block provides a translation for US (primary)
       #   Canadian, Australian and UK Englush.
       #   
       # Comment: this seems a bit silly why not just support a list of languages
       #           e.g. <lang which='l1,l2...'> and ditch the other attribute?
       #
       #  Effect:
       #    The material within the <lang>..</lang> block is stored in the
       #    specified set of $available_texts hash entries, the appropriate one
       #    is selected at </translated> time.
       #
       #  Pathalogical case handling:
       #    If a language occurs multiple times within a <translated> block,
       #    only the last one is rendered e.g.:
       #
       #    <translated>
       #       <lang which='senisoUS', other='senisoCA,senisoAU,seniso'>
       #          Red green color blindness is quite common affecting about 7.8% of 
       #          the male population, but onloy about .65% of the female population.
       #       </lang>
       #          Red green colour blindness is quite common affecting about 7.8% of 
       #          the male population, but onloy about .65% of the female population.
       #       <lang which='seniso', other='senisoCA,senisoAU'>
       #     </translated>
       #
       #    renders the correct spelling of color (colour) for people who have specified
       #    a preferred language that is one of the British Commonwealth languages
       #    even though those are also listed as valid selections for the US english
       #    <lang> block.
       #
     sub start_lang {      sub start_lang {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  if ($target eq 'web' || $target eq 'grade'   || $target eq 'answer' ||   if ($target eq 'web' || $target eq 'grade'   || $target eq 'answer' ||
Line 1689  sub end_languageblock { Line 1918  sub end_languageblock {
  }   }
  return '';   return '';
     }      }
 }  } # end langauge block specific tags.
   
   
 sub start_instructorcomment {  sub start_instructorcomment {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;

Removed from v.1.499  
changed lines
  Added in v.1.500


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>