Diff for /loncom/homework/structuretags.pm between versions 1.497.2.6 and 1.498

version 1.497.2.6, 2011/12/27 19:48:31 version 1.498, 2011/12/10 17:53:45
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 70  BEGIN { Line 69  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 1060  sub reset_problem_globals { Line 960  sub reset_problem_globals {
     undef(%Apache::lonhomework::history);      undef(%Apache::lonhomework::history);
     undef(%Apache::lonhomework::results);      undef(%Apache::lonhomework::results);
     undef($Apache::inputtags::part);      undef($Apache::inputtags::part);
       if ($type eq 'Task') {
           undef($Apache::inputtags::slot_name);
       }
 #don't undef this, lonhomework.pm takes care of this, we use this to   #don't undef this, lonhomework.pm takes care of this, we use this to 
 #detect if we try to do 2 problems in one file  #detect if we try to do 2 problems in one file
 #   undef($Apache::lonhomework::parsing_a_problem);  #   undef($Apache::lonhomework::parsing_a_problem);
Line 1309  sub start_problem { Line 1212  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 1367  sub end_problem { Line 1268  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 1642  sub end_block { Line 1542  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
         # This should not even happen, since we should at least have the server language          if (!$preferred_languages[0]) { $preferred_languages[0]='en'; }
   # 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
     # If neither include/nor exlude is present the block is going             $result=1;
     # to get rendered.  
   
            my $found=0;             my $found=0;
            $render=1;  # Do we have an include argument?
   
    #  If include is specified,  don't render the block  
    #  unless the preferred language is included in the set.  
   
    if ($include) {     if ($include) {
               $render=0;  # If include is specified, by default, don't render the block
                 $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) {
                     $render=1;                       $result=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) {
               $render=1;                $result=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) {
                     $render=0;                      $result=0;
                     $found=1;                      $found=1;
     last; # Only need to find the first.  
                  }                   }
               }                }
    }     }
            if ($found) {              if ($found) { last; }
        last; # Done on any match of include or exclude.  
    }  
         }          }
  # If $render not true skip the entire block until </languageblock>   if ( ! $result ) {
  #  
   
  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]");
  }   }
  # If $render is true, we've not skipped the contents of the <languageglock>   $result='';
  # 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 1761  sub end_languageblock { Line 1614  sub end_languageblock {
     }      }
     return $result;      return $result;
 }  }
 #  languagblock specific tags:  
 {  
     # For chunks of a resource that has translations, this hash contains  
     # the translations available indexed by language name.  
     #  
   
     my %available_texts;         {
       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 1820  sub end_languageblock { Line 1635  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';
     if ($target eq 'tex') {      $result = $available_texts{$which};
  $result = &select_hyphenation($which);  
     }  
     $result .= $available_texts{$which};  
     $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 1897  sub end_languageblock { Line 1673  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.497.2.6  
changed lines
  Added in v.1.498


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