--- loncom/interface/loncommon.pm	2008/04/30 23:36:56	1.652
+++ loncom/interface/loncommon.pm	2008/05/29 15:39:16	1.656
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.652 2008/04/30 23:36:56 raeburn Exp $
+# $Id: loncommon.pm,v 1.656 2008/05/29 15:39:16 www Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -150,6 +150,7 @@ sub ssi_with_retries {
 
 # ----------------------------------------------- Filetypes/Languages/Copyright
 my %language;
+my %timezone;
 my %supported_language;
 my %cprtag;
 my %scprtag;
@@ -192,6 +193,22 @@ BEGIN {
             close($fh);
         }
     }
+# ------------------------------------------------------------------- timezones
+    {
+        my $timetabfile = $Apache::lonnet::perlvar{'lonTabDir'}.
+                                   '/timezone.tab';
+        if ( open(my $fh,"<$timetabfile") ) {
+            while (my $line = <$fh>) {
+                next if ($line=~/^\#/);
+                chomp($line);
+                my $value=$line;
+                $value=~s/\_/ /g;
+                $timezone{$line}=$value;
+            }
+            close($fh);
+        }
+    }
+
 # ------------------------------------------------------------------ copyrights
     {
         my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
@@ -447,6 +464,25 @@ sub selectstudent_link {
    return '';
 }
 
+sub authorbrowser_javascript {
+    return <<"ENDAUTHORBRW";
+<script type="text/javascript">
+var stdeditbrowser;
+
+function openauthorbrowser(formname,udom) {
+    var url = '/adm/pickauthor?';
+    url += 'form='+formname+'&roledom='+udom;
+    var title = 'Author_Browser';
+    var options = 'scrollbars=1,resizable=1,menubar=0';
+    options += ',width=700,height=600';
+    stdeditbrowser = open(url,title,options,'1');
+    stdeditbrowser.focus();
+}
+
+</script>
+ENDAUTHORBRW
+}
+
 sub coursebrowser_javascript {
     my ($domainfilter,$sec_element,$formname)=@_;
     my $crs_or_grp_alert = &mt('Please select the type of LON-CAPA entity - Course or Group - for which you wish to add/modify a user role');
@@ -584,6 +620,12 @@ sub selectcourse_link {
         '","'.$udomele.'","'.$desc.'","'.$extra_element.'","'.$multflag.'","'.$selecttype.'");'."'>".&mt('Select Course')."</a>";
 }
 
+sub selectauthor_link {
+   my ($form,$udom)=@_;
+   return '<a href="javascript:openauthorbrowser('."'$form','$udom'".');">'.
+          &mt('Select Author').'</a>';
+}
+
 sub check_uncheck_jscript {
     my $jscript = <<"ENDSCRT";
 function checkAll(field) {
@@ -609,6 +651,19 @@ ENDSCRT
     return $jscript;
 }
 
+sub select_timezone {
+   my ($name,$selected,$onchange)=@_;
+   my $output="<select name='$name' $onchange>\n";
+   foreach my $key (sort(keys(%timezone))) {
+      $output.="<option value='$timezone{$key}'";
+      if ($key eq $selected) {
+         $output.=" selected='selected'";
+      }
+      $output.=">$timezone{$key}</option>\n";
+   }
+   $output.="</select>";
+   return $output;
+}
 
 =pod
 
@@ -2907,10 +2962,14 @@ sub display_languages {
 
 sub preferred_languages {
     my @languages=();
+    if (($env{'request.role.adv'}) && ($env{'form.languages'})) {
+        @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$env{'form.languages'}));
+    }
     if ($env{'course.'.$env{'request.course.id'}.'.languages'}) {
 	@languages=(@languages,split(/\s*(\,|\;|\:)\s*/,
 	         $env{'course.'.$env{'request.course.id'}.'.languages'}));
     }
+
     if ($env{'environment.languages'}) {
 	@languages=(@languages,
 		    split(/\s*(\,|\;|\:)\s*/,$env{'environment.languages'}));
@@ -7926,7 +7985,9 @@ defdom (domain for which to retrieve con
 origmail (scalar - email address of recipient from loncapa.conf, 
 i.e., predates configuration by DC via domainprefs.pm 
 
-Returns: comma separated list of addresses to which to send e-mail.   
+Returns: comma separated list of addresses to which to send e-mail.
+
+=back
 
 =cut
 
@@ -7977,6 +8038,172 @@ sub build_recipient_list {
 ############################################################
 ############################################################
 
+=pod
+
+=head1 Course Catalog Routines
+
+=over 4
+
+=item * &gather_categories()
+
+Converts category definitions - keys of categories hash stored in  
+coursecategories in configuration.db on the primary library server in a 
+domain - to an array.  Also generates javascript and idx hash used to 
+generate Domain Coordinator interface for editing Course Categories.
+
+Inputs:
+categories (reference to hash of category definitions).
+cats (reference to array of arrays/hashes which encapsulates hierarchy of
+      categories and subcategories).
+idx (reference to hash of counters used in Domain Coordinator interface for 
+      editing Course Categories).
+jsarray (reference to array of categories used to create Javascript arrays for
+         Domain Coordinator interface for editing Course Categories).
+
+Returns: nothing
+
+Side effects: populates cats, idx and jsarray. 
+
+=cut
+
+sub gather_categories {
+    my ($categories,$cats,$idx,$jsarray) = @_;
+    my %counters;
+    my $num = 0;
+    foreach my $item (keys(%{$categories})) {
+        my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item);
+        if ($container eq '' && $depth == 0) {
+            $cats->[$depth][$categories->{$item}] = $cat;
+        } else {
+            $cats->[$depth]{$container}[$categories->{$item}] = $cat;
+        }
+        my ($escitem,$tail) = split(/:/,$item,2);
+        if ($counters{$tail} eq '') {
+            $counters{$tail} = $num;
+            $num ++;
+        }
+        if (ref($idx) eq 'HASH') {
+            $idx->{$item} = $counters{$tail};
+        }
+        if (ref($jsarray) eq 'ARRAY') {
+            push(@{$jsarray->[$counters{$tail}]},$item);
+        }
+    }
+    return;
+}
+
+=pod
+
+=item * &extract_categories()
+
+Used to generate breadcrumb trails for course categories.
+
+Inputs:
+categories (reference to hash of category definitions).
+cats (reference to array of arrays/hashes which encapsulates hierarchy of
+      categories and subcategories).
+trails (reference to array of breacrumb trails for each category).
+allitems (reference to hash - key is category key 
+         (format: escaped(name):escaped(parent category):depth in hierarchy).
+idx (reference to hash of counters used in Domain Coordinator interface for
+      editing Course Categories).
+jsarray (reference to array of categories used to create Javascript arrays for
+         Domain Coordinator interface for editing Course Categories).
+
+Returns: nothing
+
+Side effects: populates trails and allitems hash references.
+
+=cut
+
+sub extract_categories {
+    my ($categories,$cats,$trails,$allitems,$idx,$jsarray) = @_;
+    if (ref($categories) eq 'HASH') {
+        &gather_categories($categories,$cats,$idx,$jsarray);
+        if (ref($cats->[0]) eq 'ARRAY') {
+            for (my $i=0; $i<@{$cats->[0]}; $i++) {
+                my $name = $cats->[0][$i];
+                my $item = &escape($name).'::0';
+                my $trailstr;
+                if ($name eq 'instcode') {
+                    $trailstr = &mt('Official courses (with institutional codes)');
+                } else {
+                    $trailstr = $name;
+                }
+                if ($allitems->{$item} eq '') {
+                    push(@{$trails},$trailstr);
+                    $allitems->{$item} = scalar(@{$trails})-1;
+                }
+                my @parents = ($name);
+                if (ref($cats->[1]{$name}) eq 'ARRAY') {
+                    for (my $j=0; $j<@{$cats->[1]{$name}}; $j++) {
+                        my $category = $cats->[1]{$name}[$j];
+                        &recurse_categories($cats,2,$category,$trails,$allitems,\@parents);
+                    }
+                }
+            }
+        }
+    }
+    return;
+}
+
+=pod
+
+=item *&recurse_categories()
+
+Recursively used to generate breadcrumb trails for course categories.
+
+Inputs:
+cats (reference to array of arrays/hashes which encapsulates hierarchy of
+      categories and subcategories).
+depth (current depth in hierarchy of categories and sub-categories - 0 indexed).
+category (current course category, for which breadcrumb trail is being generated).   
+trails (reference to array of breacrumb trails for each category).
+allitems (reference to hash - key is category key
+         (format: escaped(name):escaped(parent category):depth in hierarchy).
+parents (array containing containers directories for current category, 
+         back to top level). 
+
+Returns: nothing
+
+Side effects: populates trails and allitems hash references
+
+=back
+
+=cut
+
+sub recurse_categories {
+    my ($cats,$depth,$category,$trails,$allitems,$parents) = @_;
+    my $shallower = $depth - 1;
+    if (ref($cats->[$depth]{$category}) eq 'ARRAY') {
+        for (my $k=0; $k<@{$cats->[$depth]{$category}}; $k++) {
+            my $name = $cats->[$depth]{$category}[$k];
+            my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower;
+            my $trailstr = join(' -&gt; ',(@{$parents},$category));
+            if ($allitems->{$item} eq '') {
+                push(@{$trails},$trailstr);
+                $allitems->{$item} = scalar(@{$trails})-1;
+            }
+            my $deeper = $depth+1;
+            push(@{$parents},$category);
+            &recurse_categories($cats,$deeper,$name,$trails,$allitems,$parents);
+            pop(@{$parents});
+        }
+    } else {
+        my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower;
+        my $trailstr = join(' -&gt; ',(@{$parents},$category));
+        if ($allitems->{$item} eq '') {
+            push(@{$trails},$trailstr);
+            $allitems->{$item} = scalar(@{$trails})-1;
+        }
+    }
+    return;
+}
+
+############################################################
+############################################################
+
+
 sub commit_customrole {
     my ($udom,$uname,$url,$three,$four,$five,$start,$end) = @_;
     my $output = &mt('Assigning custom role').' "'.$five.'" by '.$four.':'.$three.' in '.$url.