--- loncom/interface/loncommon.pm	2004/03/19 03:47:09	1.187
+++ loncom/interface/loncommon.pm	2004/12/01 23:18:23	1.237
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.187 2004/03/19 03:47:09 albertel Exp $
+# $Id: loncommon.pm,v 1.237 2004/12/01 23:18:23 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -59,7 +59,6 @@ use Apache::lonnet();
 use GDBM_File;
 use POSIX qw(strftime mktime);
 use Apache::Constants qw(:common :http :methods);
-use Apache::lonmsg();
 use Apache::lonmenu();
 use Apache::lonlocal;
 use HTML::Entities;
@@ -74,6 +73,7 @@ my $readit;
 my %language;
 my %supported_language;
 my %cprtag;
+my %scprtag;
 my %fe; my %fd;
 my %category_extensions;
 
@@ -131,6 +131,20 @@ BEGIN {
             close($fh);
         }
     }
+# ------------------------------------------------------------------ source copyrights
+    {
+        my $sourcecopyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
+                                  '/source_copyright.tab';
+        if ( open (my $fh,"<$sourcecopyrightfile") ) {
+            while (<$fh>) {
+                next if /^\#/;
+                chomp;
+                my ($key,$val)=(split(/\s+/,$_,2));
+                $scprtag{$key}=$val;
+            }
+            close($fh);
+        }
+    }
 
 # -------------------------------------------------------------- domain designs
 
@@ -235,8 +249,11 @@ of the element the selection from the se
 =cut
 
 sub browser_and_searcher_javascript {
+    my ($mode)=@_;
+    if (!defined($mode)) { $mode='edit'; }
     my $resurl=&lastresurl();
     return <<END;
+// <!-- BEGIN LON-CAPA Internal
     var editbrowser = null;
     function openbrowser(formname,elementname,only,omit,titleelement) {
         var url = '$resurl/?';
@@ -244,20 +261,26 @@ sub browser_and_searcher_javascript {
             url += 'launch=1&';
         }
         url += 'catalogmode=interactive&';
-        url += 'mode=edit&';
+        url += 'mode=$mode&';
         url += 'form=' + formname + '&';
         if (only != null) {
             url += 'only=' + only + '&';
-        } 
+        } else {
+            url += 'only=&';
+	}
         if (omit != null) {
             url += 'omit=' + omit + '&';
-        }
+        } else {
+            url += 'omit=&';
+	}
         if (titleelement != null) {
             url += 'titleelement=' + titleelement + '&';
-        }
+        } else {
+	    url += 'titleelement=&';
+	}
         url += 'element=' + elementname + '';
         var title = 'Browser';
-        var options = 'scrollbars=1,resizable=1,menubar=0';
+        var options = 'scrollbars=1,resizable=1,menubar=1,location=1';
         options += ',width=700,height=600';
         editbrowser = open(url,title,options,'1');
         editbrowser.focus();
@@ -269,11 +292,13 @@ sub browser_and_searcher_javascript {
             url += 'launch=1&';
         }
         url += 'catalogmode=interactive&';
-        url += 'mode=edit&';
+        url += 'mode=$mode&';
         url += 'form=' + formname + '&';
         if (titleelement != null) {
             url += 'titleelement=' + titleelement + '&';
-        }
+        } else {
+	    url += 'titleelement=&';
+	}
         url += 'element=' + elementname + '';
         var title = 'Search';
         var options = 'scrollbars=1,resizable=1,menubar=0';
@@ -281,6 +306,7 @@ sub browser_and_searcher_javascript {
         editsearcher = open(url,title,options,'1');
         editsearcher.focus();
     }
+// END LON-CAPA Internal -->
 END
 }
 
@@ -353,7 +379,7 @@ sub coursebrowser_javascript {
    return (<<ENDSTDBRW);
 <script type="text/javascript" language="Javascript" >
     var stdeditbrowser;
-    function opencrsbrowser(formname,uname,udom,desc) {
+    function opencrsbrowser(formname,uname,udom,desc,extra_element) {
         var url = '/adm/pickcourse?';
         var filter;
         if (filter != null) {
@@ -370,6 +396,12 @@ sub coursebrowser_javascript {
         url += 'form=' + formname + '&cnumelement='+uname+
 	                            '&cdomelement='+udom+
                                     '&cnameelement='+desc;
+        if (extra_element !=null && extra_element != '' && formname == 'rolechoice') {
+            url += '&roleelement='+extra_element;
+            if (domainfilter == null || domainfilter == '') {
+                url += '&domainfilter='+extra_element;
+            }
+        }
         var title = 'Course_Browser';
         var options = 'scrollbars=1,resizable=1,menubar=0';
         options += ',width=700,height=600';
@@ -381,9 +413,9 @@ ENDSTDBRW
 }
 
 sub selectcourse_link {
-   my ($form,$unameele,$udomele,$desc)=@_;
+   my ($form,$unameele,$udomele,$desc,$extra_element)=@_;
     return "<a href='".'javascript:opencrsbrowser("'.$form.'","'.$unameele.
-        '","'.$udomele.'","'.$desc.'");'."'>".&mt('Select Course')."</a>";
+        '","'.$udomele.'","'.$desc.'","'.$extra_element.'");'."'>".&mt('Select Course')."</a>";
 }
 
 =pod
@@ -466,7 +498,7 @@ sub linked_select_forms {
     my $first = "document.$formname.$firstselectname";
     # output the javascript to do the changing
     my $result = '';
-    $result.="<script>\n";
+    $result.="<script type=\"text/javascript\">\n";
     $result.="var select2data = new Object();\n";
     $" = '","';
     my $debug = '';
@@ -594,8 +626,9 @@ sub help_open_topic {
 
     # Add the graphic
     my $title = &mt('Online Help');
+    my $helpicon=&lonhttpdurl("/adm/help/gif/smallHelp.gif");
     $template .= <<"ENDTEMPLATE";
- <a href="$link" title="$title"><image src="/adm/help/gif/smallHelp.gif" border="0" alt="(Help: $topic)" /></a>
+ <a href="$link" title="$title"><img src="$helpicon" border="0" alt="(Help: $topic)" /></a>
 ENDTEMPLATE
     if ($text ne '') { $template.='</td></tr></table>' };
     return $template;
@@ -622,6 +655,78 @@ sub helpLatexCheatsheet {
 	.'</td></tr></table>';
 }
 
+sub help_open_menu {
+    my ($color,$topic,$component_help,$function,$faq,$bug,$stayOnPage,$width,$height,$text) = @_;
+    $text = "" if (not defined $text);
+    $stayOnPage = 0 if (not defined $stayOnPage);
+    if ($ENV{'browser.interface'} eq 'textual' ||
+        $ENV{'environment.remote'} eq 'off' ) {
+        $stayOnPage=1;
+    }
+    $width = 620 if (not defined $width);
+    $height = 600 if (not defined $height);
+    my $link='';
+    my $title = &mt('Get help');
+    my $origurl = $ENV{'REQUEST_URI'};
+    $origurl=~s|^/~|/priv/|;
+    my $timestamp = time;
+    foreach (\$color,\$function,\$topic,\$component_help,\$faq,\$bug,\$origurl) {
+        $$_ = &Apache::lonnet::escape($$_);
+    }
+
+    if (!$stayOnPage) {
+         $link = "javascript:helpMenu('open')";
+    } else {
+        $link = "javascript:helpMenu('display')";
+    }
+    my $banner_link = "/adm/helpmenu?page=banner&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage";
+    my $details_link = "/adm/helpmenu?page=body&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp";
+    my $template;
+    if ($text ne "") {
+	$template .= 
+  "<table bgcolor='#773311' cellspacing='1' cellpadding='1' border='0'><tr>".
+  "<td bgcolor='#886622'><a href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
+    }
+    my $helpicon=&lonhttpdurl("/adm/lonIcons/helpgateway.gif");
+    $template .= <<"ENDTEMPLATE";
+ <script type="text/javascript">
+//<!-- BEGIN LON-CAPA Internal
+function helpMenu(caller) {
+    if (caller == 'open') {
+        newWindow =  window.open("","helpmenu","HEIGHT=$height,WIDTH=$width,resize=yes,scrollbars=yes" )
+        caller = newWindow.document
+    } else {
+        caller = this.document
+    }
+    caller.write("<html><head><title>LON-CAPA Help Menu</title><meta http-equiv='pragma' content='no-cache'></head>")
+    caller.write("<frameset rows='105,*' border='0'><frame name='bannerframe'  src='$banner_link'><frame name='bodyframe' src='$details_link'></frameset>")
+    caller.write("</html>")
+    caller.close()
+    if (caller == newWindow.document) {
+        caller.focus()
+    }
+}
+// END LON-CAPA Internal -->
+ </script>
+ <a href="$link" title="$title"><img src="$helpicon" border="0" alt="(Help Menu)" /></a>
+ENDTEMPLATE
+    if ($component_help) {
+	if (!$text) {
+	    $template=&help_open_topic($component_help,undef,$stayOnPage,
+				       $width,$height).' '.$template;
+	} else {
+	    my $help_text;
+	    $help_text=&Apache::lonnet::unescape($topic);
+	    $template='<table><tr><td>'.
+		&help_open_topic($component_help,$help_text,$stayOnPage,
+				 $width,$height).'</td><td>'.$template.
+				 '</td></tr></table>';
+	}
+    }
+    if ($text ne '') { $template.='</td></tr></table>' };
+    return $template;
+}
+
 sub help_open_bug {
     my ($topic, $text, $stayOnPage, $width, $height) = @_;
     unless ($ENV{'user.adv'}) { return ''; }
@@ -658,8 +763,9 @@ sub help_open_bug {
 
     # Add the graphic
     my $title = &mt('Report a Bug');
+    my $bugicon=&lonhttpdurl("/adm/lonMisc/smallBug.gif");
     $template .= <<"ENDTEMPLATE";
- <a href="$link" title="$title"><image src="/adm/lonMisc/smallBug.gif" border="0" alt="(Bug: $topic)" /></a>
+ <a href="$link" title="$title"><img src="$bugicon" border="0" alt="(Bug: $topic)" /></a>
 ENDTEMPLATE
     if ($text ne '') { $template.='</td></tr></table>' };
     return $template;
@@ -702,8 +808,9 @@ sub help_open_faq {
 
     # Add the graphic
     my $title = &mt('View the FAQ');
+    my $faqicon=&lonhttpdurl("/adm/lonMisc/smallFAQ.gif");
     $template .= <<"ENDTEMPLATE";
- <a href="$link" title="$title"><image src="/adm/lonMisc/smallFAQ.gif" border="0" alt="(FAQ: $topic)" /></a>
+ <a href="$link" title="$title"><img src="$faqicon" border="0" alt="(FAQ: $topic)" /></a>
 ENDTEMPLATE
     if ($text ne '') { $template.='</td></tr></table>' };
     return $template;
@@ -727,7 +834,7 @@ format.
 sub csv_translate {
     my $text = shift;
     $text =~ s/\"/\"\"/g;
-    $text =~ s/\n//g;
+    $text =~ s/\n/ /g;
     return $text;
 }
 
@@ -778,7 +885,7 @@ sub define_excel_formats {
     $format->{'h2'}   = $workbook->add_format(bold=>1, size=>16);
     $format->{'h3'}   = $workbook->add_format(bold=>1, size=>14);
     $format->{'date'} = $workbook->add_format(num_format=>
-                                            'mmm d yyyy hh:mm AM/PM');
+                                            'mm/dd/yyyy hh:mm:ss');
     return $format;
 }
 
@@ -907,21 +1014,27 @@ sub domain_select {
     } &get_domains;
     if ($multiple) {
 	$domains{''}=&mt('Any domain');
-	return &multiple_select_form($name,$value,%domains);
+	return &multiple_select_form($name,$value,4,%domains);
     } else {
 	return &select_form($name,$value,%domains);
     }
 }
 
 sub multiple_select_form {
-    my ($name,$value,%hash)=@_;
+    my ($name,$value,$size,%hash)=@_;
     my %selected = map { $_ => 1 } ref($value)?@{$value}:($value);
     my $output='';
-    my $size =(scalar keys %hash<4?scalar keys %hash:4);
+    if (! defined($size)) {
+        $size = 4;
+        if (scalar(keys(%hash))<4) {
+            $size = scalar(keys(%hash));
+        }
+    }
     $output.="\n<select name='$name' size='$size' multiple='1'>";
-    foreach (sort keys %hash) {
-        $output.="<option name='$_'".
-            ($selected{$_}?' selected="1"' :'').">$hash{$_}</option>\n";
+    foreach (sort(keys(%hash))) {
+        $output.='<option value="'.$_.'" ';
+        $output.='selected ' if ($selected{$_});
+        $output.='>'.$hash{$_}."</option>\n";
     }
     $output.="</select>\n";
     return $output;
@@ -1634,23 +1747,29 @@ sub get_related_words {
 
 =over 4
 
-=item * plainname($uname,$udom)
+=item * plainname($uname,$udom,$first)
 
 Takes a users logon name and returns it as a string in
-"first middle last generation" form
+"first middle last generation" form 
+if $first is set to 'lastname' then it returns it as
+'lastname generation, firstname middlename' if their is a lastname
 
 =cut
 
 ###############################################################
 sub plainname {
-    my ($uname,$udom)=@_;
+    my ($uname,$udom,$first)=@_;
     my %names=&Apache::lonnet::get('environment',
                     ['firstname','middlename','lastname','generation'],
 					 $udom,$uname);
-    my $name=$names{'firstname'}.' '.$names{'middlename'}.' '.
-	$names{'lastname'}.' '.$names{'generation'};
+    my $name=&Apache::lonnet::format_name($names{'firstname'},
+					  $names{'middlename'},
+					  $names{'lastname'},
+					  $names{'generation'},$first);
+    $name=~s/^\s+//;
     $name=~s/\s+$//;
     $name=~s/\s+/ /g;
+    if ($name !~ /\S/) { $name=$uname.'@'.$udom; }
     return $name;
 }
 
@@ -1673,8 +1792,19 @@ if the user does not
 
 sub nickname {
     my ($uname,$udom)=@_;
-    my %names=&Apache::lonnet::get('environment',
-  ['nickname','firstname','middlename','lastname','generation'],$udom,$uname);
+    my %names;
+    if ($uname eq $ENV{'user.name'} &&
+	$udom eq $ENV{'user.domain'}) {
+	%names=('nickname'   => $ENV{'environment.nickname'}  ,
+		'firstname'  => $ENV{'environment.firstname'} ,
+		'middlename' => $ENV{'environment.middlename'},
+		'lastname'   => $ENV{'environment.lastname'}  ,
+		'generation' => $ENV{'environment.generation'});
+    } else {
+	%names=&Apache::lonnet::get('environment',
+				    ['nickname','firstname','middlename',
+				     'lastname','generation'],$udom,$uname);
+    }
     my $name=$names{'nickname'};
     if ($name) {
        $name='&quot;'.$name.'&quot;'; 
@@ -1700,17 +1830,21 @@ Gets a users screenname and returns it a
 
 sub screenname {
     my ($uname,$udom)=@_;
-    my %names=
- &Apache::lonnet::get('environment',['screenname'],$udom,$uname);
+    if ($uname eq $ENV{'user.name'} &&
+	$udom eq $ENV{'user.domain'}) {return $ENV{'environment.screenname'};}
+    my %names=&Apache::lonnet::get('environment',['screenname'],$udom,$uname);
     return $names{'screenname'};
 }
 
+
 # ------------------------------------------------------------- Message Wrapper
 
 sub messagewrapper {
-    my ($link,$un,$do)=@_;
+    my ($link,$username,$domain)=@_;
     return 
-"<a href='/adm/email?compose=individual&recname=$un&recdom=$do'>$link</a>";
+        '<a href="/adm/email?compose=individual&'.
+        'recname='.$username.'&recdom='.$domain.'" '.
+        'title="'.&mt('Send message').'">'.$link.'</a>';
 }
 # --------------------------------------------------------------- Notes Wrapper
 
@@ -1723,8 +1857,8 @@ sub noteswrapper {
 
 sub aboutmewrapper {
     my ($link,$username,$domain,$target)=@_;
-    return "<a href='/adm/$domain/$username/aboutme'".
-	($target?" target='$target'":'').">$link</a>";
+    return '<a href="/adm/'.$domain.'/'.$username.'/aboutme"'.
+	($target?' target="$target"':'').' title="'.&mt('View this users personal page').'">'.$link.'</a>';
 }
 
 # ------------------------------------------------------------ Syllabus Wrapper
@@ -1735,9 +1869,28 @@ sub syllabuswrapper {
     if ($fontcolor) { 
         $linktext='<font color="'.$fontcolor.'">'.$linktext.'</font>'; 
     }
-    return "<a href='/public/$domain/$coursedir/syllabus'>$linktext</a>";
+    return qq{<a href="/public/$domain/$coursedir/syllabus">$linktext</a>};
 }
 
+sub track_student_link {
+    my ($linktext,$sname,$sdom,$target) = @_;
+    my $link ="/adm/trackstudent";
+    my $title = 'View recent activity';
+    if (defined($sname) && $sname !~ /^\s*$/ &&
+        defined($sdom)  && $sdom  !~ /^\s*$/) {
+        $link .= "?selected_student=$sname:$sdom";
+        $title .= ' of this student';
+    }
+    if (defined($target) && $target !~ /^\s*$/) {
+        $target = qq{target="$target"};
+    } else {
+        $target = '';
+    }
+    return qq{<a href="$link" title="$title" $target>$linktext</a>};
+}
+
+
+
 =pod
 
 =back
@@ -1807,6 +1960,30 @@ sub copyrightdescription {
 
 =pod
 
+=item * source_copyrightids() 
+
+returns list of all source copyrights
+
+=cut
+
+sub source_copyrightids {
+    return sort(keys(%scprtag));
+}
+
+=pod
+
+=item * source_copyrightdescription() 
+
+returns description of a specified source copyright id
+
+=cut
+
+sub source_copyrightdescription {
+    return &mt($scprtag{shift(@_)});
+}
+
+=pod
+
 =item * filecategories() 
 
 returns list of all file categories
@@ -1845,7 +2022,7 @@ sub fileembstyle {
 
 sub filecategoryselect {
     my ($name,$value)=@_;
-    return &select_form($name,$value,
+    return &select_form($value,$name,
 			'' => &mt('Any category'),
 			map { $_,$_ } sort(keys(%category_extensions)));
 }
@@ -1859,7 +2036,9 @@ returns description for a specified file
 =cut
 
 sub filedescription {
-    return &mt($fd{lc(shift(@_))});
+    my $file_description = $fd{lc(shift())};
+    $file_description =~ s:([\[\]]):~$1:g;
+    return &mt($file_description);
 }
 
 =pod
@@ -1873,7 +2052,9 @@ extra formatting
 
 sub filedescriptionex {
     my $ex=shift;
-    return '.'.$ex.' '.&mt($fd{lc($ex)});
+    my $file_description = $fd{lc($ex)};
+    $file_description =~ s:([\[\]]):~$1:g;
+    return '.'.$ex.' '.&mt($file_description);
 }
 
 # End of .tab access
@@ -2104,7 +2285,7 @@ sub get_student_view {
   if (defined($moreenv)) {
       %form=(%form,%{$moreenv});
   }
-  if ($target eq 'tex') {$form{'grade_target'} = 'tex';}
+  if (defined($target)) { $form{'grade_target'} = $target; }
   $feedurl=&Apache::lonnet::clutter($feedurl);
   my $userview=&Apache::lonnet::ssi_body($feedurl,%form);
   $userview=~s/\<body[^\>]*\>//gi;
@@ -2190,7 +2371,7 @@ sub maketime {
     my %th=@_;
     return POSIX::mktime(
         ($th{'seconds'},$th{'minutes'},$th{'hours'},
-         $th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,$th{'dlsav'}));
+         $th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,-1));
 }
 
 #########################################
@@ -2261,10 +2442,8 @@ sub domainlogo {
     my $domain = &determinedomain(shift);    
      # See if there is a logo
     if (-e '/home/httpd/html/adm/lonDomLogos/'.$domain.'.gif') {
-	my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};
-	if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
-        return '<img src="http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.
-	    '/adm/lonDomLogos/'.$domain.'.gif" alt="'.$domain.'" />';
+	my $logo=&lonhttpdurl("/adm/lonDomLogos/$domain.gif");
+        return '<img src="'.$logo.'" alt="'.$domain.'" />';
     } elsif(exists($Apache::lonnet::domaindescription{$domain})) {
         return $Apache::lonnet::domaindescription{$domain};
     } else {
@@ -2350,7 +2529,7 @@ other decorations will be returned.
 =cut
 
 sub bodytag {
-    my ($title,$function,$addentries,$bodyonly,$domain,$forcereg)=@_;
+    my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,$customtitle)=@_;
     $title=&mt($title);
     $function = &get_users_function() if (!$function);
     my $img=&designparm($function.'.img',$domain);
@@ -2383,7 +2562,7 @@ sub bodytag {
     if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
 # construct main body tag
     my $bodytag = <<END;
-<style>
+<style type="text/css">
 h1, h2, h3, th { font-family: Arial, Helvetica, sans-serif }
 a:focus { color: red; background: yellow } 
 </style>
@@ -2396,20 +2575,74 @@ END
         return $bodytag;
     } elsif ($ENV{'browser.interface'} eq 'textual') {
 # Accessibility
+          
         return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',
                                                       $forcereg).
                '<h1>LON-CAPA: '.$title.'</h1>';
     } elsif ($ENV{'environment.remote'} eq 'off') {
 # No Remote
-        return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',
-                                                      $forcereg).
-      '<table bgcolor="'.$pgbg.'" width="100%" border="0" cellspacing="3" cellpadding="3"><tr><td bgcolor="'.$tabbg.'"><font face="Arial, Helvetica, sans-serif" size="+3" color="'.$font.'"><b>'.$title.
-'</b></font></td></tr></table>';
+	my $roleinfo=(<<ENDROLE);
+<td bgcolor="$tabbg" align="right">
+<font size="2" face="Arial, Helvetica, sans-serif">
+    $ENV{'environment.firstname'}
+    $ENV{'environment.middlename'}
+    $ENV{'environment.lastname'}
+    $ENV{'environment.generation'}
+    </font>&nbsp;
+<br />
+<font size="2" face="Arial, Helvetica, sans-serif">$role</font>&nbsp;
+<br />
+<font size="2" face="Arial, Helvetica, sans-serif">$realm</font>&nbsp;
+</td>
+ENDROLE
+        my $titleinfo = '<font face="Arial, Helvetica, sans-serif" size="+3" color="'.
+		$font.'"><b>'.$title.'</b></font>';
+        if ($customtitle) {
+            $titleinfo = $customtitle;
+        }
+
+	if ($ENV{'request.state'} eq 'construct') {
+	    my ($uname,$thisdisfn)=
+		($ENV{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|);
+	    my $formaction='/priv/'.$uname.'/'.$thisdisfn;
+	    $formaction=~s/\/+/\//g;
+            unless ($customtitle) {  #this is for resources; directories have customtitle, and crumbs and select recent are created in lonpubdir.pm  
+                my $parentpath = '';
+                if ($thisdisfn =~ m-(.+/)[^/]*$-) {
+                    $parentpath = $1;
+                }
+	        $titleinfo = &Apache::loncommon::help_open_menu('','','','',3,'Authoring').
+                      '<font face="Arial, Helvetica, sans-serif"><b>Construction Space</b>:</font>&nbsp;'. 
+                      '<form name="dirs" method="post" action="'.$formaction
+		    .'" target="_top"><tt><b>'
+		    .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv','','+1',1)."</b></tt><br />"
+		    .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()')
+		    .'</form>'
+		    .&Apache::lonmenu::constspaceform();
+
+            }
+	    $forcereg=1;
+        }
+        my $titletable = '<table bgcolor="'.$pgbg.'" width="100%" border="0" '.
+                         'cellspacing="3" cellpadding="3">'.
+                         '<tr><td rowspan="3" bgcolor="'.$tabbg.'">'.
+                         $titleinfo.'</td>'.$roleinfo.'</tr></table>';
+        if ($ENV{'request.state'} eq 'construct') {
+            $bodytag .= &Apache::lonmenu::menubuttons($forcereg,'web',$forcereg,$titletable);
+	} else {
+            $bodytag .= &Apache::lonmenu::menubuttons($forcereg,'web',$forcereg).
+                        $titletable;
+        }
+        return $bodytag;
     }
 
 #
 # Top frame rendering, Remote is up
 #
+    my $titleinfo = '&nbsp;<font size="5" face="Arial, Helvetica, sans-serif"><b>'.$title.'</b></font>';
+    if ($customtitle) {
+        $titleinfo = $customtitle;
+    }
     return(<<ENDBODY);
 $bodytag
 <table width="100%" cellspacing="0" border="0" cellpadding="0">
@@ -2419,7 +2652,7 @@ $upperleft</td>
 </tr>
 <tr>
 <td rowspan="3" bgcolor="$tabbg">
-&nbsp;<font size="5" face="Arial, Helvetica, sans-serif"><b>$title</b></font>
+$titleinfo
 <td bgcolor="$tabbg" align="right">
 <font size="2" face="Arial, Helvetica, sans-serif">
     $ENV{'environment.firstname'}
@@ -2434,7 +2667,7 @@ $upperleft</td>
 </td></tr>
 <tr>
 <td bgcolor="$tabbg" align="right"><font size="2" face="Arial, Helvetica, sans-serif">$realm</font>&nbsp;</td></tr>
-</table><br>
+</table><br />
 ENDBODY
 }
 
@@ -2467,6 +2700,76 @@ sub get_users_function {
 
 ###############################################
 
+=pod
+
+=item get_sections
+
+Determines all the sections for a course including
+sections with students and sections containing other roles.
+Incoming parameters: domain, course number, reference to 
+section hash (keys to be section/group IDs), reference to 
+array containing roles for which sections should be gathered
+(optional). If the fourth argument is undefined, sections
+are gathered for any role.
+ 
+Returns number of sections.
+
+=cut
+
+###############################################
+sub get_sections {
+    my ($cdom,$cnum,$sectioncount,$possible_roles) = @_;
+    my $cid = $cdom.'_'.$cnum;
+    my $numsections = 0;
+    if ($cdom && $cnum) {
+        if (!defined($possible_roles) || (grep/^st$/,@$possible_roles)) {
+            my ($classlist) = &Apache::loncoursedata::get_classlist($cid,$cdom,$cnum);
+            my $sec_index = &Apache::loncoursedata::CL_SECTION();
+            my $status_index = &Apache::loncoursedata::CL_STATUS();
+            while (my ($student,$data) = each %$classlist) {
+                my ($section,$status) = ($data->[$sec_index],
+                                         $data->[$status_index]);
+                unless ($section eq '' || $section =~ /^\s*$/) {
+                    if (!defined($$sectioncount{$section})) {
+                        $$sectioncount{$section} = 1;
+                        $numsections ++;
+                    } else {
+                        $$sectioncount{$section} ++;
+                    }
+                }
+            }
+        }
+        my %courseroles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
+        foreach my $user (sort keys %courseroles) {
+            if ($user =~ /^(\w{2})/) {
+                my $role = $1;
+                if (!defined($possible_roles) || (grep/^$role$/,@$possible_roles)) {
+                    if ($role eq 'cr') {
+                        if ($user =~ m-^$role/[^/]*/[^/]*/[^/]*:[^:]*:[^:]*:(\w+)-) {
+                            if (!defined($$sectioncount{$1})) {
+                                $$sectioncount{$1} = 1;
+                                $numsections ++;
+                            } else {
+                                $$sectioncount{$1} ++;
+                            }
+                        }
+                    }
+                    if ($user =~ /^$role:[^:]*:[^:]*:(\w+)/) {
+                        if (!defined($$sectioncount{$1})) {
+                            $$sectioncount{$1} = 1;
+                            $numsections ++;
+                        } else {
+                            $$sectioncount{$1} ++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return $numsections;
+}
+
+
 sub get_posted_cgi {
     my $r=shift;
 
@@ -2575,12 +2878,12 @@ returns cache-controlling header code
 =cut
 
 sub cacheheader {
-  unless ($ENV{'request.method'} eq 'GET') { return ''; }
-  my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime);
-  my $output .='<meta HTTP-EQUIV="Expires" CONTENT="'.$date.'" />
+    unless ($ENV{'request.method'} eq 'GET') { return ''; }
+    my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime);
+    my $output .='<meta HTTP-EQUIV="Expires" CONTENT="'.$date.'" />
                 <meta HTTP-EQUIV="Cache-control" CONTENT="no-cache" />
                 <meta HTTP-EQUIV="Pragma" CONTENT="no-cache" />';
-  return $output;
+    return $output;
 }
 
 =pod
@@ -2592,12 +2895,13 @@ specifies header code to not have cache
 =cut
 
 sub no_cache {
-  my ($r) = @_;
-  unless ($ENV{'request.method'} eq 'GET') { return ''; }
-  #my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime);
-  $r->no_cache(1);
-  $r->header_out("Pragma" => "no-cache");
-  #$r->header_out("Expires" => $date);
+    my ($r) = @_;
+    if ($ENV{'REQUEST_METHOD'} ne 'GET' &&
+	$ENV{'request.method'} ne 'GET') { return ''; }
+    my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime(time));
+    $r->no_cache(1);
+    $r->header_out("Expires" => $date);
+    $r->header_out("Pragma" => "no-cache");
 }
 
 sub content_type {
@@ -3092,13 +3396,28 @@ sub DrawBarGraph {
                   '#66ccff', '#ff9999', '#cccc33', '#660000', '#33cc66',
                   ]; 
     }
+    my $extra_settings = {};
+    if (ref($Values[-1]) eq 'HASH') {
+        $extra_settings = pop(@Values);
+    }
     #
     my $identifier = &get_cgi_id();
     my $id = 'cgi.'.$identifier;        
     if (! @Values || ref($Values[0]) ne 'ARRAY') {
         return '';
     }
+    #
+    my @Labels;
+    if (defined($labels)) {
+        @Labels = @$labels;
+    } else {
+        for (my $i=0;$i<@{$Values[0]};$i++) {
+            push (@Labels,$i+1);
+        }
+    }
+    #
     my $NumBars = scalar(@{$Values[0]});
+    if ($NumBars < scalar(@Labels)) { $NumBars = scalar(@Labels); }
     my %ValuesHash;
     my $NumSets=1;
     foreach my $array (@Values) {
@@ -3108,7 +3427,15 @@ sub DrawBarGraph {
     }
     #
     my ($height,$width,$xskip,$bar_width) = (200,120,1,15);
-    if ($NumBars < 10) {
+    if ($NumBars < 3) {
+        $width = 120+$NumBars*32;
+        $xskip = 1;
+        $bar_width = 30;
+    } elsif ($NumBars < 5) {
+        $width = 120+$NumBars*20;
+        $xskip = 1;
+        $bar_width = 20;
+    } elsif ($NumBars < 10) {
         $width = 120+$NumBars*15;
         $xskip = 1;
         $bar_width = 15;
@@ -3126,15 +3453,6 @@ sub DrawBarGraph {
         $bar_width = 4;
     }
     #
-    my @Labels;
-    if (defined($labels)) {
-        @Labels = @$labels;
-    } else {
-        for (my $i=0;$i<@{$Values[0]};$i++) {
-            push (@Labels,$i+1);
-        }
-    }
-    #
     $Max = 1 if ($Max < 1);
     if ( int($Max) < $Max ) {
         $Max++;
@@ -3157,6 +3475,11 @@ sub DrawBarGraph {
     $ValuesHash{$id.'.bar_width'} = $bar_width;
     $ValuesHash{$id.'.labels'} = join(',',@Labels);
     #
+    # Deal with other parameters
+    while (my ($key,$value) = each(%$extra_settings)) {
+        $ValuesHash{$id.'.'.$key} = $value;
+    }
+    #
     &Apache::lonnet::appenv(%ValuesHash);
     return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
 }
@@ -3391,8 +3714,8 @@ Inputs:
 sub chartlink {
     my ($linktext, $sname, $sdomain) = @_;
     my $link = '<a href="/adm/statistics?reportSelected=student_assessment'.
-        '&SelectedStudent='.&Apache::lonnet::escape($sname.':'.$sdomain).
-        '&chartoutputmode='.HTML::Entities::encode('html, with all links').
+        '&amp;SelectedStudent='.&Apache::lonnet::escape($sname.':'.$sdomain).
+        '&amp;chartoutputmode='.HTML::Entities::encode('html, with all links').
        '">'.$linktext.'</a>';
 }
 
@@ -3529,6 +3852,45 @@ sub icon {
     return $iconname;
 } 
 
+sub lonhttpdurl {
+    my ($url)=@_;
+    my $lonhttpd_port=$Apache::lonnet::perlvar{'lonhttpdPort'};
+    if (!defined($lonhttpd_port)) { $lonhttpd_port='8080'; }
+    return 'http://'.$ENV{'SERVER_NAME'}.':'.$lonhttpd_port.$url;
+}
+
+sub connection_aborted {
+    my ($r)=@_;
+    $r->print(" ");$r->rflush();
+    my $c = $r->connection;
+    return $c->aborted();
+}
+
+#    Escapes strings that may have embedded 's that will be put into
+#    strings as 'strings'.
+sub escape_single {
+    my ($input) = @_;
+    $input =~ s/\\/\\\\/g;	# Escape the \'s..(must be first)>
+    $input =~ s/\'/\\\'/g;	# Esacpe the 's....
+    return $input;
+}
+
+#  Same as escape_single, but escape's "'s  This 
+#  can be used for  "strings"
+sub escape_double {
+    my ($input) = @_;
+    $input =~ s/\\/\\\\/g;	# Escape the /'s..(must be first)>
+    $input =~ s/\"/\\\"/g;	# Esacpe the "s....
+    return $input;
+}
+ 
+#   Escapes the last element of a full URL.
+sub escape_url {
+    my ($url)   = @_;
+    my @urlslices = split(/\//, $url);
+    my $lastitem = &Apache::lonnet::escape(pop(@urlslices));
+    return join('/',@urlslices).'/'.$lastitem;
+}
 =pod
 
 =back