[LON-CAPA-cvs] cvs: modules /droeschl lonmenu.pm

droeschl droeschl@source.lon-capa.org
Tue, 11 Aug 2009 13:18:33 -0000


This is a MIME encoded message

--droeschl1249996713
Content-Type: text/plain

droeschl		Tue Aug 11 13:18:33 2009 EDT

  Added files:                 
    /modules/droeschl	lonmenu.pm 
  Log:
  Work in progress. 
  Refactoring and cleaning up of sub innerregister.
  
  
--droeschl1249996713
Content-Type: text/plain
Content-Disposition: attachment; filename="droeschl-20090811131833.txt"


Index: modules/droeschl/lonmenu.pm
+++ modules/droeschl/lonmenu.pm
# The LearningOnline Network with CAPA
# Routines to control the menu
#
# $Id: lonmenu.pm,v 1.1 2009/08/11 13:18:32 droeschl Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
#
# There is one parameter controlling the action of this module:
#
# environment.remote - if this is 'on', the routines controll the remote
# control, otherwise they render the main window controls; 

=head1 NAME

Apache::lonmenu

=head1 SYNOPSIS

Coordinates the response to clicking an image.

This is part of the LearningOnline Network with CAPA project
described at http://www.lon-capa.org.

=head1 SUBROUTINES

=over

Little texts

=item initlittle()

=item menubuttons()

This gets called at the top of the body section

=item show_return_link()

=item registerurl()

This gets called in the header section

=item innerregister()

This gets called in order to register a URL, both with the Remote
and in the body of the document

=item loadevents()

=item unloadevents()

=item startupremote()

=item setflags()

=item maincall()

=item load_remote_msg()

=item get_menu_name()

=item reopenmenu()

=item open()

Open the menu

=item clear()

=item switch()

Switch a button or create a link
Switch acts on the javascript that is executed when a button is clicked.  
The javascript is usually similar to "go('/adm/roles')" or "cstrgo(..)".

=item secondlevel()

=item openmenu()

=item inlinemenu()

=item rawconfig()

=item close()

=item footer()

=item utilityfunctions()

=item serverform()

=item constspaceform()

=item get_nav_status()

=item convert_menu_function()

FIXME this needs to move into mydesktab and the other locations 
the text is generated

=item hidden_button_check()

=item roles_selector()

=item jump_to_role()

=back

=cut

package Apache::lonmenu;

#SD
use warnings;

use strict;
use Apache::lonnet;
use Apache::lonhtmlcommon();
use Apache::loncommon();
use Apache::lonenc();
use Apache::lonlocal;
use LONCAPA qw(:DEFAULT :match);

use vars qw(@desklines %category_names %category_members %category_positions $readdesk);


my @inlineremote;

#
# This routine returns a translated hash for the menu items in the top inline menu row
# Probably should be in mydesk.tab

sub initlittle {
    return &Apache::lonlocal::texthash('ret' => 'Return to Last Location',
				       'nav' => 'Navigate Contents',
				       'main' => 'Main Menu',
                                       'roles' => (&Apache::loncommon::show_course()?
                                                    'Courses':'Roles'),
                                       'other' => 'Other Roles',
                                       'docs' => 'Edit Course',
                                       'exit' => 'Logout',
                                       'login' => 'Log In',
				       'launch' => 'Launch Remote Control',
                                       'groups' => 'Groups',
                                       'gdoc' => 'Group Documents',
                                       );
}

sub menubuttons {
    my ($forcereg, $titletable) = @_;
#
# Early-out for pages that should not have a menu, triggered by query string "inhibitmenu=yes"
#
    &Apache::loncommon::get_unprocessed_cgi(
        $ENV{'QUERY_STRING'}, ['inhibitmenu']);

    return if (   $env{'form.inhibitmenu'} eq 'yes' 
               || $ENV{'REQUEST_URI'} eq '/adm/logout' 
               || $env{'request.noversionuri'} =~ m{^/res/adm/pages/});

    my %lt          = &initlittle();
    my $navmaps     = '';
    my $reloadlink  = '';
    my $docs        = '';
    my $groups      = '';
    my $roles       = '<a href="/adm/roles" target="_top">'.$lt{'roles'}.'</a>';
    my $showgroups  = 0;
    my $role_selector;
    my ($cnum,$cdom);
#
# if the URL is hidden, symbs and the non-versioned version of the URL would be encrypted
#
    my $escurl  = &escape(&Apache::lonenc::check_encrypt($env{'request.noversionuri'}));
    my $escsymb = &escape(&Apache::lonenc::check_encrypt($env{'request.symb'}));

    my $logo = '<a href="/adm/about.html"><img src="' 
                . &Apache::loncommon::lonhttpdurl("/adm/lonIcons/minilogo.gif")
                . '" alt="LON-CAPA Logo" class="LC_noBorder" /></a>';

    if ($env{'request.state'} eq 'construct') {
#
# We are in construction space
#
        if (($env{'request.noversionuri'} eq '') || (!defined($env{'request.noversionuri'}))) {
            my $returnurl  = $env{'request.filename'};
            $returnurl    =~ s{^/home/([^/]+)/public_html/(.*)$}{/priv/$1/$2};
            $escurl        = &escape($returnurl);
        }
    }
    if ($env{'request.course.id'}) {
#
# We are in a course
#
        $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
        $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};

        my %coursegroups;

        my $viewgrps_permission = &Apache::lonnet::allowed('vcg',
                    $env{'request.course.id'} 
                    . ( $env{'request.course.sec'}
                        ? '/' . $env{'request.course.sec'}
                        : '' ));

        if (!$viewgrps_permission) {
            %coursegroups = &Apache::lonnet::get_active_groups($env{'user.domain'},$env{'user.name'},$cdom,$cnum);
        }

        if (keys(%coursegroups) > 0 || $viewgrps_permission) {
            $showgroups = 1;
        }

        $role_selector = &roles_selector($cdom,$cnum);
        if ($role_selector) {
            $roles = '<span class="LC_nobreak">'.$role_selector.'&nbsp;&nbsp;<a href="/adm/roles" target="_top">'.$lt{'other'}.'</a></span>';
        }
    }

    #
    #Early-out if remote control is switched on
    #
    return '' unless $env{'environment.remote'} eq 'off';

# Remote Control is switched off
# figure out colors
    my $domain   = &Apache::loncommon::determinedomain();
    my $function = &Apache::loncommon::get_users_function();
    my $link     = &Apache::loncommon::designparm($function.'.link',$domain);
    my $alink    = &Apache::loncommon::designparm($function.'.alink',$domain);
    my $vlink    = &Apache::loncommon::designparm($function.'.vlink',$domain);
    my $sidebg   = &Apache::loncommon::designparm($function.'.sidebg',$domain);

    if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {
    #Public user requesting a page
        return (<<ENDINLINEMENU);
            <ol class="LC_smallMenu LC_right">
                <li>$logo</li>
                <li><a href="/adm/roles" target="_top">$lt{'login'}</a></li>
            </ol>
            <hr />
ENDINLINEMENU
    }

#
# User is logged in
#

    #Prepare inline menu links

    # Do we have a NAV link?
    if ($env{'request.course.id'}) 
    {# we're in a course

        #default link for navigate contents
        my $link = qq|/adm/navmaps?postdata=$escurl&amp;postsymb=$escsymb|;

           $link = "javascript:gonav('".$link."')"
                        if ($env{'environment.remotenavmap'} eq 'on');

        #Navigate Contents link
        $navmaps = inlinemenu_link( $link , $lt{'nav'} );
        #Groups link
        $groups  = inlinemenu_link( "/adm/coursegroups", $lt{'groups'} ) if $showgroups;


        {#Remote navigation window is switched on
            $link = "javascript:gonav('".$link."')";
        }



        my $is_group = &Apache::loncommon::course_type() eq 'Group';

        if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) 
        {#Edit Course link
            my $text = ($is_group) ? $lt{'gdoc'} : $lt{'docs'};
            $docs = inlinemenu_link( "/adm/coursedocs", $text );
        }

        if ($showgroups) 
        {
        }

        if ( &show_return_link() || $env{'request.state'} eq 'construct' ) 
        {#Return to last location link
            my $escreload = &escape('return:');
            $reloadlink = inlinemenu_link(
                "/adm/flip?postdata=$escreload", $lt{'ret'} );
        }

        if ($role_selector) 
        {#Role selection box
            $role_selector = qq|<li>$role_selector</li>|;
        }
    }

#SD this should be obsolete, since this is covered by adding 
#SD || $env{'request.state'} eq 'construct'
#SD to the 2nd last if, as i've done.
#SD	if ($env{'request.state'} eq 'construct' && $env{'request.course.id'}) 
#SD    {
#SD	    my $escreload = &escape('return:');
#SD	    $reloadlink = 
#SD            qq|<li><a href="/adm/flip?postdata=$escreload" target="_top">$lt{'ret'}</a></li>|;
#SD    }

    my $reg     = $forcereg ? &innerregister($forcereg,$titletable) : '';
    my $form    = &serverform();
    my $utility = &utilityfunctions();


    #prepare small menu links
    #message link that indicates the arrival of new mail
    my $messagelink = Apache::lonmsg::mynewmail() ? "Message (new)" : "Message";
       $messagelink = '<a href="javascript:go(\'/adm/communicate\');">'
                      . mt($messagelink) .'</a>';

       $roles    = qq|<a href="/adm/roles" target="_top">$lt{'roles'}</a>|;
    my $helplink = &Apache::loncommon::top_nav_help('Help');

	return (<<ENDINLINEMENU);
<script type="text/javascript">
// <![CDATA[
// BEGIN LON-CAPA Internal
$utility
// ]]>
</script>
<ol class="LC_smallMenu LC_right">
	<li>$logo</li>
	<li>$messagelink</li>
	<li>$roles</li>
	<li>$helplink</li>
	<li><a href="/adm/logout" target="_top">$lt{'exit'}</a></li>
</ol>
<ul id="LC_TabMainMenuContent">
<li><a href="/adm/menu" target="_top">$lt{'main'}</a></li>
$reloadlink
$navmaps
$docs
$groups
$role_selector
</ul>
$form
<script type="text/javascript">
// END LON-CAPA Internal
</script>
$reg
ENDINLINEMENU
}

sub show_return_link {
    return (($env{'request.noversionuri'}=~m{^/(res|public)/} &&
	     $env{'request.symb'} eq '')
	    ||
	    ($env{'request.noversionuri'}=~ m{^/cgi-bin/printout.pl})
	    ||
	    (($env{'request.noversionuri'}=~/^\/adm\//) &&
	     ($env{'request.noversionuri'}!~/^\/adm\/wrapper\//) &&
	     ($env{'request.noversionuri'}!~
	      m[^/adm/.*/(smppg|bulletinboard|aboutme)($|\?)])
	     ));
}


sub registerurl {
    my ($forcereg) = @_;
    my $result = '';
    if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; }
    my $force_title='';
    if ($env{'request.state'} eq 'construct') {
	$force_title=&Apache::lonxml::display_title();
    }
    if (($env{'environment.remote'} eq 'off') ||
        ((($env{'request.publicaccess'}) || 
         (!&Apache::lonnet::is_on_map(
	   &unescape($env{'request.noversionuri'})))) &&
        (!$forcereg))) {
 	return
        $result
       .'<script type="text/javascript">'."\n"
       .'// <![CDATA['."\n"
       .'function LONCAPAreg(){;} function LONCAPAstale(){}'."\n"
       .'// ]]>'."\n"
       .'</script>'
       .$force_title;
    }
# Graphical display after login only
    if ($env{'request.registered'} && !$forcereg) { return ''; }
    $result.=&innerregister($forcereg);
    return $result.$force_title;
}

#SD new subs

sub get_breadcrumbs {

    #SD early return if remote is activated or if we aren't requesting a resource
    #in a course
    return unless    $env{'environment.remote'} eq 'off'
                  && $env{'request.symb'}
                  && $env{'request.course.id'};

    my ($mapurl) = Apache::lonnet::decode_symb( Apache::lonnet::symbread() );

    #determine course, map and resource titles
    my $coursetitle = Apache::lonnet::current_course_title();
    my $maptitle    = Apache::lonnet::gettitle( $mapurl );
    my $restitle    = Apache::lonnet::gettitle( Apache::lonnet::symbread() );

    Apache::lonnet::logthis("Coursetitle in prepBread: $coursetitle\n");
    #Add default crumbs for mainmenu and dots for seperation
    my @crumbs   = (
        {
            text => "Course Content",
            href => "Javascript:gonav('/adm/navmaps')"
        },
        {
            text  => '...',
            no_mt => 1
        }
    );

    #we're looking at a map, so add maptitle to breadcrumbs
    push @crumbs, { text => $maptitle, no_mt => 1 }
      if  $maptitle
        && $maptitle ne 'default.sequence'
        && $maptitle ne $coursetitle ;

    #we're looking at a resource, so add resourcetitle to breadcrumbs
    push @crumbs, { text => $restitle, no_mt => 1 } if $restitle;

    #prepare breadcrumbs
    Apache::lonhtmlcommon::clear_breadcrumbs();
    Apache::lonhtmlcommon::add_breadcrumb( @crumbs );

    return Apache::lonhtmlcommon::breadcrumbs( undef, undef, 0 );
}

sub inlinemenu_link {
    my ($link, $text) = @_;
    return qq|<li><a href="$link" target="_top">$text</a></li>|;
}

sub remotecontrol_js {
    my ($reopen, $timesync,
        $newmail, $buttons, $requri, $cursymb, $navstatus, $hwkadd,
        $editbutton, $clearcstr) = @_;
    my $script = "var swmenu=null;\n";

    if ($newmail or $buttons or $requri or $cursymb or $navstatus or $hwkadd or
        $editbutton or $clearcstr) {
    #registered output
        $script .= (<<ENDREGTHIS);
            function LONCAPAreg() {
                swmenu=$reopen;
                swmenu.clearTimeout(swmenu.menucltim);
                $timesync
                $newmail
                $buttons
                swmenu.currentURL="$requri";
                swmenu.reloadURL=swmenu.currentURL+window.location.search;
                swmenu.currentSymb="$cursymb";
                swmenu.reloadSymb="$cursymb";
                swmenu.currentStale=0;
                $navstatus
                $hwkadd
                $editbutton
            }
            function LONCAPAstale() {
                swmenu=$reopen
                swmenu.currentStale=1;
                if (swmenu.reloadURL!='' && swmenu.reloadURL!= null) { 
                    swmenu.switchbutton
                    (3,1,'reload.gif','return','location','go(reloadURL)','Return to the last known location in the course sequence');
                }
                swmenu.clearbut(7,2);
                swmenu.clearbut(7,3);
                swmenu.menucltim=swmenu.setTimeout(
                    'clearbut(2,1);clearbut(2,3);clearbut(8,1);clearbut(8,2);clearbut(8,3);'+
                    'clearbut(9,1);clearbut(9,3);clearbut(6,3);$clearcstr', 2000);
            }
ENDREGTHIS
    } else {
    #not registered output
        $script .= (<<ENDDONOTREGTHIS);
            function LONCAPAreg() {
                swmenu=$reopen;
                $timesync
                swmenu.currentStale=1;

                swmenu.clearbut(2,1);
                swmenu.clearbut(2,3);
                swmenu.clearbut(8,1);
                swmenu.clearbut(8,2);
                swmenu.clearbut(8,3);

                if (swmenu.currentURL) {
                    swmenu.switchbutton(3,1,'reload.gif','return','location','go(currentURL)');
                } else {
                    swmenu.clearbut(3,1);
                }
            }
            function LONCAPAstale() {}
ENDDONOTREGTHIS
 
    }

    return Apache::lonhtmlcommon::scripttag($script, 1);
}

#SD END new subs

sub innerregister {
    my $forcereg = shift;    #SD titletable will be removed shortly

    #SD early return if a static html page is requested
    #SD this is quite unnecessary, since menubuttons and registerurl already
    #check for this?!
    return if $env{'request.noversionuri'} =~ m{^/res/adm/pages/};

    #SD indicates that remote is off
    my $noremote    =  $env{'environment.remote'} eq 'off' ;

    my $timesync   = $noremote ? '' : 'swmenu.syncclock(1000*' . time . ');';

    #SD $reopen contains some javascript to open an empty browser window
    #named LCmenu<hostid>
    my $reopen      = &Apache::lonmenu::reopenmenu();

    #SD Early out for pages that can or will not be registered
    #SD unless ( $env{'request.noversionuri'} !~ m{^/(res/)*adm/} || $forcereg ) 
    #SD easier to read:
    if ( $env{'request.noversionuri'} =~ m{^/(res/)*adm/} and not $forcereg )
    {
        return if $noremote;    #SD remote control is OFF
        return                  #SD remote control is ON
            remotecontrol_js( $reopen, $timesync );
    }
    #SD indicates that we're in construction space
    my $const_space =  $env{'request.state'} eq 'construct' ;

    #SD ?? What's this ??
    $env{'request.registered'} = 1;

    my $result  = '';
    my $newmail = '';

    #SD does this really need to be global?
    #where does it get filled?
    undef(@inlineremote);

    if ( &Apache::lonmsg::newmail() && !$noremote ) {
        # We have new mail and remote is up
        $newmail = 'swmenu.setstatus("you have","messages");';
    }


# ============================ End not registered

# ============================ This is for URLs that actually can be registered

    # SD if (($env{'request.noversionuri'}!~m{^/(res/)*adm/}) || ($forcereg)) 

    # -- This applies to homework problems for users with grading privileges
    my $crs  = '/' . $env{'request.course.id'};
       $crs .= '_' . $env{'request.course.sec'} if $env{'request.course.sec'};
       $crs =~ s{_}{/}g;

    my $hwkadd = '';

    if (   $env{'request.symb'} ne ''
        && $env{'request.filename'} =~
        /\.(problem|exam|quiz|assess|survey|form|task)$/ )
    {

        if ( &Apache::lonnet::allowed( 'mgr', $crs ) ) {

            $hwkadd .= &switch(
                '',
                '',
                7,
                2,
                'pgrd.gif',
                'problem[_1]',
                'grades[_4]',
                "gocmd('/adm/grades','gradingmenu')",
                'Modify user grades for this assessment resource'
            );

        }
        elsif ( &Apache::lonnet::allowed( 'vgr', $crs ) ) {

            $hwkadd .= &switch(
                '',
                '',
                7,
                2,
                'subm.gif',
                'view sub-[_1]',
                'missions[_1]',
                "gocmd('/adm/grades','submission')",
                'View user submissions for this assessment resource'
            );
        }
    }

    if (   $env{'request.symb'} ne ''
        && &Apache::lonnet::allowed( 'opa', $crs ) )
    {

        $hwkadd .= &switch(
            '',
            '',
            7,
            3,
            'pparm.gif',
            'problem[_2]',
            'parms[_2]',
            "gocmd('/adm/parmset','set')",
            'Modify parameter settings for this resource'
        );
    }

    # -- End Homework

    ###
    ### Determine whether or not to display the 'cstr' button for this
    ### resource
    ###

    my $editbutton   = '';
    my $noeditbutton = 1;
    my ( $cnum, $cdom );

    if ( $env{'request.course.id'} ) {
        $cnum = $env{ 'course.' . $env{'request.course.id'} . '.num' };
        $cdom = $env{ 'course.' . $env{'request.course.id'} . '.domain' };
    }

    #SD what's user.author exactly?
    #and how does it differ from request.role... next line?
    if ( $env{'user.author'} ) {
        if ( $env{'request.role'} =~ /^(aa|ca|au)/ ) {

            #
            # We have the role of an author
            #

            # Set defaults for authors
            my ( $top, $bottom ) = ( 'con-', 'struct' );

            my $action = "go('/priv/" . $env{'user.name'} . "');";
            my $cadom  = $env{'request.role.domain'};
            my $caname = $env{'user.name'};
            my $desc   = "Enter my construction space";

            # Set defaults for co-authors
            unless ( $env{'request.role'} =~ /^au/ ) {

                ( $cadom, $caname ) =
                  ( $env{'request.role'} =~
                      /($match_domain)\/($match_username)$/ );

                ( $top, $bottom ) = ( 'co con-', 'struct' );

                $action = "go('/priv/" . $caname . "');";

                $desc = 'Enter construction space as'
                        . $env{'request.role'} =~ /^aa/ ? ' assistant' : ''
                        . ' co-author';
            
            }


            # Check that we are on the correct machine
            my $home    = &Apache::lonnet::homeserver( $caname, $cadom );
            my $allowed = 0;
            my @ids     = &Apache::lonnet::current_machine_ids();

            foreach my $id (@ids) {
                if ( $id eq $home ) { $allowed = 1; }
            }

            if ( !$allowed ) {
                $editbutton =
                  &switch( '', '', 6, 1, $top,, $bottom, $action, $desc );
                $noeditbutton = 0;
            }
        }

#
# We are an author for some stuff, but currently do not have the role of author.
# Figure out if we have authoring privileges for the resource we are looking at.
# This should maybe become a privilege check in lonnet
#

        ##
        ## Determine if user can edit url.
        ##
        my $cfile = '';

        if ( $env{'request.filename'} ) {

            my $file = &Apache::lonnet::declutter( $env{'request.filename'} );

            unless ( defined $cnum
                && defined $cdom
                && is_course_upload( $file, $cnum, $cdom ) )
            {

                $file =~ s/^($match_domain)\/($match_username)/\/priv\/$2/;

                # Check that the user has permission to edit this resource
                my ( $cfuname, $cfudom ) =
                  &Apache::loncacc::constructaccess( $file, $1 );

                if ( defined($cfudom) ) {
                    my $homeserver =
                      &Apache::lonnet::homeserver( $cfuname, $cfudom );

                    foreach my $id ( Apache::lonnet::current_machine_ids() ) {
                        if ( $id eq $homeserver ) {
                            $cfile = $file;
                            last;
                        }
                    }

                }
            }
        }

        # Finally, turn the button on or off
        if ( $cfile && !$const_space ) {

            $editbutton = &switch(
                '', '', 6, 1, 'pcstr.gif', 'edit[_1]', 'resource[_2]',
                "go('" . $cfile . "');",
                "Edit this resource"
            );

            $noeditbutton = 0;

        }
        elsif ( $editbutton eq '' ) {
            $editbutton = &clear( 6, 1 );
        }
    }

    if (   $noeditbutton
        && $env{'request.filename'}
        && &Apache::lonnet::allowed( 'mdc', $env{'request.course.id'} )
        && defined($cnum)
        && defined($cdom) )
    {
        my $file = &Apache::lonnet::declutter( $env{'request.filename'} );

        if ( &is_course_upload( $file, $cnum, $cdom ) ) {

            my $cfile = &edit_course_upload( $file, $cnum, $cdom );

            if ($cfile) {
                $editbutton = &switch(
                    '', '', 6, 1, 'pcstr.gif', 'edit[_1]', 'resource[_2]',
                    "go('" . $cfile . "');",
                    'Edit this resource'
                );
            }
        }
    }

    # Prepare the rest of the buttons
    my $menuitems;

    if ($const_space) {

        #
        # We are in construction space
        #

        my ( $uname, $thisdisfn ) =
          ( $env{'request.filename'} =~ m{^/home/([^/]+)/public_html/(.*)} );

        my $currdir = "/priv/$uname/$thisdisfn";

        #no menu for directories
        unless ( $currdir =~ m{/$} ) {

            $currdir =~ s{[^/]+$}{};
            my $cleandisfn  = &Apache::loncommon::escape_single($thisdisfn);
            my $esc_currdir = &Apache::loncommon::escape_single($currdir);

            #
            # Probably should be in mydesk.tab
            #
            $menuitems = (<<ENDMENUITEMS);
s&6&1&list.gif&list[_1]&dir[_1]&golist('$esc_currdir')&List current directory
s&6&2&rtrv.gif&retrieve[_1]&version[_1]&gocstr('/adm/retrieve','/~$uname/$cleandisfn')&Retrieve old version
s&6&3&pub.gif&publish[_1]&resource[_3]&gocstr('/adm/publish','/~$uname/$cleandisfn')&Publish this resource
s&7&1&del.gif&delete[_1]&resource[_2]&gocstr('/adm/cfile?action=delete','/~$uname/$cleandisfn')&Delete this resource
s&7&2&prt.gif&prepare[_1]&printout[_1]&gocstr('/adm/printout','/~$uname/$cleandisfn')&Prepare a printable document
ENDMENUITEMS
        }

    }

    elsif ( defined $env{'request.course.id'}
        && $env{'request.symb'} ne '' )
    {

        #
        # We are in a course and looking at a registred URL
        # Should probably be in mydesk.tab
        #

        $menuitems = (<<ENDMENUITEMS);
c&3&1
s&2&1&back.gif&backward[_1]&&gopost('/adm/flip','back:'+currentURL)&Go to the previous resource in the course sequence&&1
s&2&3&forw.gif&forward[_1]&&gopost('/adm/flip','forward:'+currentURL)&Go to the next resource in the course sequence&&3
c&6&3
c&8&1
c&8&2
s&8&3&prt.gif&prepare[_1]&printout[_1]&gopost('/adm/printout',currentURL)&Prepare a printable document
s&9&1&sbkm.gif&set[_1]&bookmark[_2]&set_bookmark()&Set a bookmark for this resource&&1
ENDMENUITEMS

        my $currentURL = &Apache::loncommon::get_symb();

        my ( $symb_old, $symb_old_enc ) =
          &Apache::loncommon::clean_symb($currentURL);

        my $annotation =
          &Apache::loncommon::get_annotation( $symb_old, $symb_old_enc );

        $menuitems .= "s&9&3&";
        $menuitems .= length($annotation) > 0 ? "anot2.gif" : "anot.gif";

        $menuitems .= "&anno-[_1]&tations[_1]&annotate()&";
        $menuitems .= "Make notes and annotations about this resource&&1\n";

        unless ( $env{'request.noversionuri'} =~
            /\/(bulletinboard|smppg|navmaps|syllabus|aboutme)(\?|$)/ )
        {

            if ( !$env{'request.enc'} ) {
                $menuitems .= (<<ENDREALRES);
s&6&3&catalog.gif&catalog[_2]&info[_1]&catalog_info()&Show Metadata
ENDREALRES
            }

            $menuitems .= (<<ENDREALRES);
s&8&1&eval.gif&evaluate[_1]&this[_1]&gopost('/adm/evaluate',currentURL,1)&Provide my evaluation of this resource
s&8&2&fdbk.gif&feedback[_1]&discuss[_1]&gopost('/adm/feedback',currentURL,1)&Provide feedback messages or contribute to the course discussion about this resource
ENDREALRES
        }

    }

    if ( $env{'request.uri'} =~ /^\/res/ ) {
        $menuitems .= (<<ENDMENUITEMS);
s&8&3&prt.gif&prepare[_1]&printout[_1]&gopost('/adm/printout',currentURL)&Prepare a printable document
ENDMENUITEMS
    }
    my $buttons = '';
    foreach ( split( /\n/, $menuitems ) ) {
        my ( $command, @rest ) = split( /\&/, $_ );
        my $idx = 10 * $rest[0] + $rest[1];
        if ( &hidden_button_check() eq 'yes' ) {
            if ( $idx == 21 || $idx == 23 ) {
                $buttons .= &switch( '', '', @rest );
            }
            else {
                $buttons .= &clear(@rest);
            }
        }
        else {
            if ( $command eq 's' ) {
                $buttons .= &switch( '', '', @rest );
            }
            else {
                $buttons .= &clear(@rest);
            }
        }
    }

    if ($noremote) {
        my $addremote = 0;
        foreach (@inlineremote) {
            if ( $_ ne '' ) { $addremote = 1; last; }
        }
        my $inlinebuttons = '';
        if ($addremote) {

            # Registered, textual output
            if ( $env{'environment.icons'} eq 'iconsonly' ) {
                $inlinebuttons = (<<ENDARROWSINLINE);
<tr><td>
$inlineremote[21] $inlineremote[23]
ENDARROWSINLINE
                if ( &hidden_button_check() ne 'yes' ) {
                    $inlinebuttons .= (<<ENDINLINEICONS);
$inlineremote[61] $inlineremote[63]
$inlineremote[71] $inlineremote[72] $inlineremote[73]
$inlineremote[81] $inlineremote[82] $inlineremote[83]
$inlineremote[91] $inlineremote[92] $inlineremote[93]</td></tr>
ENDINLINEICONS
                }
            }
            else {
                if ( $inlineremote[21] ne '' || $inlineremote[23] ne '' ) {
                    $inlinebuttons = (<<ENDFIRSTLINE);
<tr><td>$inlineremote[21]</td><td>&nbsp;</td><td>$inlineremote[23]</td></tr>
ENDFIRSTLINE
                }
                if ( &hidden_button_check() ne 'yes' ) {
                    foreach my $row ( 6 .. 9 ) {
                        if (   $inlineremote[ ${row} . '1' ] ne ''
                            || $inlineremote[ $row . '2' ] ne ''
                            || $inlineremote[ $row . '3' ] ne '' )
                        {
                            $inlinebuttons .= <<"ENDLINE";
<tr><td>$inlineremote["${row}1"]</td><td>$inlineremote["${row}2"]</td><td>$inlineremote["${row}3"]</td></tr>
ENDLINE
                        }
                    }
                }
            }
        }
        #SD Prepare breadcrumbs
        my $breadcrumb = get_breadcrumbs();
        $result = (<<ENDREGTEXT);
<script type="text/javascript">
// BEGIN LON-CAPA Internal
</script>
$timesync
$breadcrumb
<table id="LC_menubuttons">
$inlinebuttons
</table>
$newmail
<script type="text/javascript">
// END LON-CAPA Internal
</script>

ENDREGTEXT

        # Registered, graphical output (remote control)
    }
    else {
        my $requri = &Apache::lonnet::clutter(
            &Apache::lonnet::fixversion(
                ( split( /\?/, $env{'request.noversionuri'} ) )[0]
            )
        );
        $requri = &Apache::lonenc::check_encrypt( &unescape($requri) );
        my $cursymb   = &Apache::lonenc::check_encrypt( $env{'request.symb'} );
        my $navstatus = &get_nav_status();
        my $clearcstr;

        if ( $env{'user.adv'} ) { $clearcstr = 'clearbut(6,1)'; }
            $result = remotecontrol_js($reopen, $timesync, $newmail, $buttons, $requri, $cursymb, $navstatus, $hwkadd,
        $editbutton, $clearcstr);
#SD         $result = (<<ENDREGTHIS);
#SD      
#SD <script type="text/javascript">
#SD // <![CDATA[
#SD // BEGIN LON-CAPA Internal
#SD     var swmenu=null;
#SD 
#SD     function LONCAPAreg() {
#SD         swmenu=$reopen;
#SD         swmenu.clearTimeout(swmenu.menucltim);
#SD         $timesync
#SD         $newmail
#SD         $buttons
#SD         swmenu.currentURL="$requri";
#SD         swmenu.reloadURL=swmenu.currentURL+window.location.search;
#SD         swmenu.currentSymb="$cursymb";
#SD         swmenu.reloadSymb="$cursymb";
#SD         swmenu.currentStale=0;
#SD         $navstatus
#SD         $hwkadd
#SD         $editbutton
#SD     }
#SD 
#SD     function LONCAPAstale() {
#SD         swmenu=$reopen
#SD         swmenu.currentStale=1;
#SD         if (swmenu.reloadURL!='' && swmenu.reloadURL!= null) { 
#SD             swmenu.switchbutton
#SD             (3,1,'reload.gif','return','location','go(reloadURL)','Return to the last known location in the course sequence');
#SD         }
#SD         swmenu.clearbut(7,2);
#SD         swmenu.clearbut(7,3);
#SD         swmenu.menucltim=swmenu.setTimeout(
#SD             'clearbut(2,1);clearbut(2,3);clearbut(8,1);clearbut(8,2);clearbut(8,3);'+
#SD             'clearbut(9,1);clearbut(9,3);clearbut(6,3);$clearcstr', 2000);
#SD     }
#SD 
#SD // END LON-CAPA Internal 
#SD // ]]>
#SD </script>
#SD ENDREGTHIS
    }
# =============================================================================
#SD     } else {
#SD # ========================================== This can or will not be registered
#SD         if ($noremote) {
#SD # Not registered
#SD             $result= (<<ENDDONOTREGTEXT);
#SD ENDDONOTREGTEXT
#SD         } else {
#SD # Not registered, graphical
#SD            $result = (<<ENDDONOTREGTHIS);
#SD
#SD <script type="text/javascript">
#SD // BEGIN LON-CAPA Internal
#SD var swmenu=null;
#SD
#SD     function LONCAPAreg() {
#SD 	  swmenu=$reopen
#SD           $timesync
#SD           swmenu.currentStale=1;
#SD           swmenu.clearbut(2,1);
#SD           swmenu.clearbut(2,3);
#SD           swmenu.clearbut(8,1);
#SD           swmenu.clearbut(8,2);
#SD           swmenu.clearbut(8,3);
#SD           if (swmenu.currentURL) {
#SD              swmenu.switchbutton
#SD               (3,1,'reload.gif','return','location','go(currentURL)');
#SD  	  } else {
#SD 	      swmenu.clearbut(3,1);
#SD           }
#SD     }
#SD
#SD     function LONCAPAstale() {
#SD     }
#SD
#SD // END LON-CAPA Internal
#SD </script>
#SD ENDDONOTREGTHIS
#SD        }
#SD # =============================================================================
#SD     }
    return $result;
}

sub is_course_upload {
    my ($file,$cnum,$cdom) = @_;
    my $uploadpath = &LONCAPA::propath($cdom,$cnum);
    $uploadpath =~ s{^\/}{};
    if (($file =~ m{^\Q$uploadpath\E/userfiles/docs/}) ||
        ($file =~ m{^userfiles/\Q$cdom\E/\Q$cnum\E/docs/})) {
        return 1;
    }
    return;
}

sub edit_course_upload {
    my ($file,$cnum,$cdom) = @_;
    my $cfile;
    if ($file =~/\.(htm|html|css|js|txt)$/) {
        my $ext = $1;
        my $url = &Apache::lonnet::hreflocation('',$file);
        my $home = &Apache::lonnet::homeserver($cnum,$cdom);
        my @ids=&Apache::lonnet::current_machine_ids();
        my $dest;
        if ($home && grep(/^\Q$home\E$/,@ids)) {
            $dest = $url.'?forceedit=1';
        } else {
            unless (&Apache::lonnet::get_locks()) {
                $dest = '/adm/switchserver?otherserver='.
                        $home.'&role='.$env{'request.role'}.
                        '&url='.$url.'&forceedit=1';
            }
        }
        if ($dest) {
            $cfile = &HTML::Entities::encode($dest,'"<>&');
        }
    }
    return $cfile;
}

sub loadevents() {
    if ($env{'request.state'} eq 'construct' ||
	$env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; }
    return 'LONCAPAreg();';
}

sub unloadevents() {
    if ($env{'request.state'} eq 'construct' ||
	$env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; }
    return 'LONCAPAstale();';
}


sub startupremote {
    my ($lowerurl)=@_;
    if ($env{'environment.remote'} eq 'off') {
     return ('<meta HTTP-EQUIV="Refresh" CONTENT="0.5; url='.$lowerurl.'" />');
    }
#
# The Remote actually gets launched!
#
    my $configmenu=&rawconfig();
    my $esclowerurl=&escape($lowerurl);
    my $message=&mt('"Waiting for Remote Control window to load: "+[_1]','waited');
    return(<<ENDREMOTESTARTUP);
<script type="text/javascript">
// <![CDATA[
var timestart;
function wheelswitch() {
    if (typeof(document.wheel) != 'undefined') {
	if (typeof(document.wheel.spin) != 'undefined') {
	    var date=new Date();
	    var waited=Math.round(30-((date.getTime()-timestart)/1000));
	    document.wheel.spin.value=$message;
	}
    }
   if (window.status=='|') { 
      window.status='/'; 
   } else {
      if (window.status=='/') {
         window.status='-';
      } else {
         if (window.status=='-') { 
            window.status='\\\\'; 
         } else {
            if (window.status=='\\\\') { window.status='|'; }
         }
      }
   } 
}

// ---------------------------------------------------------- The wait function
var canceltim;
function wait() {
   if ((menuloaded==1) || (tim==1)) {
      window.status='Done.';
      if (tim==0) {
         clearTimeout(canceltim);
         $configmenu
         window.location='$lowerurl';  
      } else {
	  window.location='/adm/remote?action=collapse&url=$esclowerurl';
      }
   } else {
      wheelswitch();
      setTimeout('wait();',200);
   }
}

function main() {
   canceltim=setTimeout('tim=1;',30000);
   window.status='-';
   var date=new Date();
   timestart=date.getTime();
   wait();
}

// ]]>
</script>
ENDREMOTESTARTUP
}

sub setflags() {
    return(<<ENDSETFLAGS);
<script type="text/javascript">
// <![CDATA[
    menuloaded=0;
    tim=0;
// ]]>
</script>
ENDSETFLAGS
}

sub maincall() {
    if ($env{'environment.remote'} eq 'off') { return ''; }
    return(<<ENDMAINCALL);
<script type="text/javascript">
// <![CDATA[
    main();
// ]]>
</script>
ENDMAINCALL
}

sub load_remote_msg {
    my ($lowerurl)=@_;

    if ($env{'environment.remote'} eq 'off') { return ''; }

    my $esclowerurl=&escape($lowerurl);
    my $link=&mt('[_1]Continue[_2] on in Inline Menu mode'
                ,'<a href="/adm/remote?action=collapse&amp;url='.$esclowerurl.'">'
                ,'</a>');
    return(<<ENDREMOTEFORM);
<p>
<form name="wheel">
<input name="spin" type="text" size="60" />
</form>
</p>
<p>$link</p>
ENDREMOTEFORM
}

sub get_menu_name {
    my $hostid = $Apache::lonnet::perlvar{'lonHostID'};
    $hostid =~ s/\W//g;
    return 'LCmenu'.$hostid;
}


sub reopenmenu {
   if ($env{'environment.remote'} eq 'off') { return ''; }
   my $menuname = &get_menu_name();
   my $nothing = &Apache::lonhtmlcommon::javascript_nothing();
   return('window.open('.$nothing.',"'.$menuname.'","",false);');
} 


sub open {
    my $returnval='';
    if ($env{'environment.remote'} eq 'off') { 
	return
        '<script type="text/javascript">'."\n"
       .'// <![CDATA['."\n"
       .'self.name="loncapaclient";'."\n"
       .'// ]]>'."\n"
       .'</script>';
    }
    my $menuname = &get_menu_name();
    
#    unless (shift eq 'unix') {
# resizing does not work on linux because of virtual desktop sizes
#       $returnval.=(<<ENDRESIZE);
#if (window.screen) {
#    self.resizeTo(screen.availWidth-215,screen.availHeight-55);
#    self.moveTo(190,15);
#}
#ENDRESIZE
#    }
    $returnval=(<<ENDOPEN);
// <![CDATA[
window.status='Opening LON-CAPA Remote Control';
var menu=window.open("/res/adm/pages/menu.html?inhibitmenu=yes","$menuname",
"height=375,width=150,scrollbars=no,menubar=no,top=5,left=5,screenX=5,screenY=5");
self.name='loncapaclient';
// ]]>
ENDOPEN
    return '<script type="text/javascript">'.$returnval.'</script>';
}


# ================================================================== Raw Config

sub clear {
    my ($row,$col)=@_;
    unless ($env{'environment.remote'} eq 'off') {
       if (($row<1) || ($row>13)) { return ''; }
       return "\n".qq(window.status+='.';swmenu.clearbut($row,$col););
   } else { 
       $inlineremote[10*$row+$col]='';
       return ''; 
   }
}

# ============================================ Switch a button or create a link
# Switch acts on the javascript that is executed when a button is clicked.  
# The javascript is usually similar to "go('/adm/roles')" or "cstrgo(..)".

sub switch {
    my (
        $uname, $udom, $row,  $col, $img, $top,
        $bot,   $act,  $desc, $cat, $nobreak
    ) = @_;

    $act =~ s/\$uname/$uname/g;
    $act =~ s/\$udom/$udom/g;
    $top  = &mt($top);
    $bot  = &mt($bot);
    $desc = &mt($desc);

    if (   ( $env{'environment.remote'} ne 'off' )
        || ( $env{'environment.icons'} eq 'classic' ) )
    {
        $img = &mt($img);
    }
    
    my $idx = 10 * $row + $col;
    $category_members{$cat} .= ':' . $idx;

    unless ( $env{'environment.remote'} eq 'off' ) {
        if ( ( $row < 1 ) || ( $row > 13 ) ) { return ''; }

        # Remote
        return "\n"
          . qq(window.status+='.';swmenu.switchbutton($row,$col,"$img","$top","$bot","$act","$desc"););
    }
    else {

        # Inline Remote
        if ( $env{'environment.icons'} ne 'classic' ) {
            $img =~ s/\.gif$/\.png/;
        }
        if ( $nobreak == 2 ) { return ''; }
        my $text = $top . ' ' . $bot;
        $text =~ s/\s*\-\s*//gs;

        my $pic =
            '<img alt="' 
          . $text
          . '" src="'
          . &Apache::loncommon::lonhttpdurl( '/res/adm/pages/' . $img )
          . '" align="'
          . ( $nobreak == 3 ? 'right' : 'left' )
          . '" class="LC_noBorder" />';
        if ( $env{'browser.interface'} eq 'faketextual' ) {

            # Main Menu
            if ( $nobreak == 3 ) {
                $inlineremote[$idx] = "\n"
                  . '<td class="LC_menubuttons_text" align="right">'
                  . $text
                  . '</td><td align="left">'
                  . '<a href="javascript:'
                  . $act . ';">'
                  . $pic
                  . '</a></td></tr>';
            }
            elsif ($nobreak) {
                $inlineremote[$idx] =
                    "\n<tr>"
                  . '<td align="left">'
                  . '<a href="javascript:'
                  . $act . ';">'
                  . $pic
                  . '</a></td>
                    <td class="LC_menubuttons_text" align="left"><a class="LC_menubuttons_link" href="javascript:'
                  . $act
                  . ';"><span class="LC_menubuttons_inline_text">'
                  . $text
                  . '</span></a></td>';
            }
            else {
                $inlineremote[$idx] =
                    "\n<tr>"
                  . '<td align="left">'
                  . '<a href="javascript:'
                  . $act . ';">'
                  . $pic
                  . '</a></td><td class="LC_menubuttons_text" colspan="3">'
                  . '<a class="LC_menubuttons_link" href="javascript:'
                  . $act
                  . ';"><span class="LC_menubuttons_inline_text">'
                  . $desc
                  . '</span></a></td></tr>';
            }
        }
        else {

            # Inline Menu
            if ( $env{'environment.icons'} eq 'iconsonly' ) {
                $inlineremote[$idx] =
                    '<a title="' 
                  . $desc
                  . '" href="javascript:'
                  . $act . ';">'
                  . $pic . '</a>';
            }
            else {
                $inlineremote[$idx] =
                    '<a class="LC_menubuttons_link" href="javascript:' 
                  . $act . ';">'
                  . $pic
                  . '<span class="LC_menubuttons_inline_text">'
                  . $desc
                  . '</span></a>';
            }
        }
    }
    return '';
}

sub secondlevel {
    my $output='';
    my 
    ($uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat)=@_;
    if ($prt eq 'any') {
	   $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
    } elsif ($prt=~/^r(\w+)/) {
        if ($rol eq $1) {
           $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
        }
    }
    return $output;
}

sub openmenu {
    my $menuname = &get_menu_name();
    if ($env{'environment.remote'} eq 'off') { return ''; }
    my $nothing = &Apache::lonhtmlcommon::javascript_nothing();
    return "window.open(".$nothing.",'".$menuname."');";
}

sub inlinemenu {
    undef(@inlineremote);
    undef(%category_members);
# calling rawconfig with "1" will evaluate mydesk.tab, even if there is no active remote control
    &rawconfig(1);
    my $output='<table id="LC_mainmenu"><tr>';
    for (my $col=1; $col<=2; $col++) {
        $output.='<td class="LC_mainmenu_col_fieldset">';
        for (my $row=1; $row<=8; $row++) {
            foreach my $cat (keys(%category_members)) {
               if ($category_positions{$cat} ne "$col,$row") { next; }
               #$output.='<table><tr><td colspan="4" class="LC_menubuttons_category">'.&mt($category_names{$cat}).'</td></tr>';
               $output.='<div class="LC_Box">';
	       $output.='<h4 class="LC_hcell">'.&mt($category_names{$cat}).'</h4>';
               $output.='<table>';
               my %active=();
               foreach my $menu_item (split(/\:/,$category_members{$cat})) {
                  if ($inlineremote[$menu_item]) {
                     $active{$menu_item}=1;
                  }
               }  
               foreach my $item (sort(keys(%active))) {
                  $output.=$inlineremote[$item];
               }
               $output.='</table>';
               $output.='</div>';
            }
         }
         $output.="</td>";
    }
    $output.="</tr></table>";
    return $output;
}

sub rawconfig {
#
# This evaluates mydesk.tab
# Need to add more positions and more privileges to deal with all
# menu items.
#
    my $textualoverride=shift;
    my $output='';
    unless ($env{'environment.remote'} eq 'off') {
       $output.=
 "window.status='Opening Remote Control';var swmenu=".&openmenu().
"\nwindow.status='Configuring Remote Control ';";
    } else {
       unless ($textualoverride) { return ''; }
    }
    my $uname=$env{'user.name'};
    my $udom=$env{'user.domain'};
    my $adv=$env{'user.adv'};
    my $show_course=&Apache::loncommon::show_course();
    my $author=$env{'user.author'};
    my $crs='';
    if ($env{'request.course.id'}) {
       $crs='/'.$env{'request.course.id'};
       if ($env{'request.course.sec'}) {
	   $crs.='_'.$env{'request.course.sec'};
       }
       $crs=~s/\_/\//g;
    }
    my $pub=($env{'request.state'} eq 'published');
    my $con=($env{'request.state'} eq 'construct');
    my $rol=$env{'request.role'};
    my $requested_domain = $env{'request.role.domain'};
    foreach my $line (@desklines) {
        my ($row,$col,$pro,$prt,$img,$top,$bot,$act,$desc,$cat)=split(/\:/,$line);
        $prt=~s/\$uname/$uname/g;
        $prt=~s/\$udom/$udom/g;
        $prt=~s/\$crs/$crs/g; 
        $prt=~s/\$requested_domain/$requested_domain/g;
        if ($category_names{$cat}!~/\w/) { $cat='oth'; }
        my $type = &Apache::loncommon::course_type();
#
# I don't think we support this
#
#        if ($type eq 'Group') {
#            $desc = &convert_menu_function($desc,$type);
#        }
        if ($pro eq 'clear') {
	    $output.=&clear($row,$col);
        } elsif ($pro eq 'any') {
               $output.=&secondlevel(
	  $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
	} elsif ($pro eq 'smp') {
            unless ($adv) {
               $output.=&secondlevel(
          $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
            }
        } elsif ($pro eq 'adv') {
            if ($adv) {
               $output.=&secondlevel(
	  $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
            }
	} elsif ($pro eq 'shc') {
            if ($show_course) {
               $output.=&secondlevel(
          $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
            }
        } elsif ($pro eq 'nsc') {
            if (!$show_course) {
               $output.=&secondlevel(
	  $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
            }
        } elsif (($pro=~/^p(\w+)/) && ($prt)) {
	    if (&Apache::lonnet::allowed($1,$prt)) {
               $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
            }
        } elsif ($pro eq 'course') {
            if ($env{'request.course.fn'}) {
               $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
	    }
        } elsif ($pro =~ /^courseenv_(.*)$/) {
            my $key = $1;
            if ($env{'course.'.$env{'request.course.id'}.'.'.$key}) {
                $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
            }
        } elsif ($pro =~ /^course_(.*)$/) {
            # Check for permissions inside of a course
            if (($env{'request.course.id'}) &&
                (&Apache::lonnet::allowed($1,$env{'request.course.id'}.
            ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))
                 )) {
                $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
	    }
        } elsif ($pro eq 'author') {
            if ($author) {
                if ((($prt eq 'rca') && ($env{'request.role'}=~/^ca/)) ||
                    (($prt eq 'raa') && ($env{'request.role'}=~/^aa/)) || 
                    (($prt eq 'rau') && ($env{'request.role'}=~/^au/))) {
                    # Check that we are on the correct machine
                    my $cadom=$requested_domain;
                    my $caname=$env{'user.name'};
                    if (($prt eq 'rca') || ($prt eq 'raa')) {
		       ($cadom,$caname)=
                               ($env{'request.role'}=~/($match_domain)\/($match_username)$/);
                    }                       
                    $act =~ s/\$caname/$caname/g;
                    my $home = &Apache::lonnet::homeserver($caname,$cadom);
		    my $allowed=0;
		    my @ids=&Apache::lonnet::current_machine_ids();
		    foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
		    if ($allowed) {
                        $output.=&switch($caname,$cadom,
                                        $row,$col,$img,$top,$bot,$act,$desc,$cat);
                    }
                }
            }
        } elsif ($pro eq 'tools') {
            my @tools = ('aboutme','blog','portfolio');
            if (grep(/^\Q$prt\E$/,@tools)) {
                if (!&Apache::lonnet::usertools_access($env{'user.name'},
                                                       $env{'user.domain'},
                                                       $prt,undef,'tools')) {
                    $output.=&clear($row,$col);
                    next;
                }
            } elsif (($prt eq 'reqcrsnsc') || ($prt eq 'reqcrsshc')) {
                next if (&Apache::lonnet::allowed('mky',$requested_domain));
                if (($prt eq 'reqcrsnsc') && ($show_course))   {
                    next;
                }
                if (($prt eq 'reqcrsshc') && (!$show_course)) {
                    next;
                }
                my $showreqcrs = 0;
                foreach my $type ('official','unofficial','community') {
                    if (&Apache::lonnet::usertools_access($env{'user.name'},
                                                    $env{'user.domain'},
                                                    $type,undef,'requestcourses')) {
                        $showreqcrs = 1;
                        last;
                    }
                }
                if (!$showreqcrs) {
                    $output.=&clear($row,$col);
                    next;
                }
            }
            $prt='any';
            $output.=&secondlevel(
          $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
        }
    }
    unless ($env{'environment.remote'} eq 'off') {
       $output.="\nwindow.status='Synchronizing Time';swmenu.syncclock(1000*".time.");\nwindow.status='Remote Control Configured.';";
       if (&Apache::lonmsg::newmail()) { 
	   $output.='swmenu.setstatus("you have","messages");';
       }
    }

    return $output;
}

# ======================================================================= Close

sub close {
    if ($env{'environment.remote'} eq 'off') { return ''; }
    my $menuname = &get_menu_name();
    return(<<ENDCLOSE);
<script type="text/javascript">
// <![CDATA[
window.status='Accessing Remote Control';
menu=window.open("/adm/rat/empty.html","$menuname",
                 "height=350,width=150,scrollbars=no,menubar=no");
window.status='Disabling Remote Control';
menu.active=0;
menu.autologout=0;
window.status='Closing Remote Control';
menu.close();
window.status='Done.';
// ]]>
</script>
ENDCLOSE
}

# ====================================================================== Footer

sub footer {

}

sub nav_control_js {
    my $nav=($env{'environment.remotenavmap'} eq 'on');
    return (<<NAVCONTROL);
    var w_loncapanav_flag="$nav";


function gonav(url) {
   if (w_loncapanav_flag != 1) {
      gopost(url,'');
   }  else {
      navwindow=window.open(url,
                  "loncapanav","height=600,width=400,scrollbars=1"); 
   }
}
NAVCONTROL
}

sub utilityfunctions {
    my $caller = shift;
    unless ($env{'environment.remote'} eq 'off' || 
            $caller eq '/adm/menu') { 
            return ''; }
            
    my $currenturl=&Apache::lonnet::clutter(&Apache::lonnet::fixversion((split(/\?/,$env{'request.noversionuri'}))[0]));
    $currenturl=&Apache::lonenc::check_encrypt(&unescape($currenturl));
    
    my $currentsymb=&Apache::lonenc::check_encrypt($env{'request.symb'});
    my $nav_control=&nav_control_js();

    my $start_page_annotate = 
        &Apache::loncommon::start_page('Annotator',undef,
				       {'only_body' => 1,
					'js_ready'  => 1,
					'bgcolor'   => '#BBBBBB',
					'add_entries' => {
					    'onload' => 'javascript:document.goannotate.submit();'}});

    my $end_page_annotate = 
        &Apache::loncommon::end_page({'js_ready' => 1});

    my $start_page_bookmark = 
        &Apache::loncommon::start_page('Bookmarks',undef,
				       {'only_body' => 1,
					'js_ready'  => 1,
					'bgcolor'   => '#BBBBBB',});

    my $end_page_bookmark = 
        &Apache::loncommon::end_page({'js_ready' => 1});

return (<<ENDUTILITY)

    var currentURL="$currenturl";
    var reloadURL="$currenturl";
    var currentSymb="$currentsymb";

$nav_control

function go(url) {
   if (url!='' && url!= null) {
       currentURL = null;
       currentSymb= null;
       window.location.href=url;
   }
}

function gopost(url,postdata) {
   if (url!='') {
      this.document.server.action=url;
      this.document.server.postdata.value=postdata;
      this.document.server.command.value='';
      this.document.server.url.value='';
      this.document.server.symb.value='';
      this.document.server.submit();
   }
}

function gocmd(url,cmd) {
   if (url!='') {
      this.document.server.action=url;
      this.document.server.postdata.value='';
      this.document.server.command.value=cmd;
      this.document.server.url.value=currentURL;
      this.document.server.symb.value=currentSymb;
      this.document.server.submit();
   }
}

function gocstr(url,filename) {
    if (url == '/adm/cfile?action=delete') {
        this.document.cstrdelete.filename.value = filename
        this.document.cstrdelete.submit();
        return;
    }
    if (url == '/adm/printout') {
        this.document.cstrprint.postdata.value = filename
        this.document.cstrprint.curseed.value = 0;
        this.document.cstrprint.problemtype.value = 0;
        if (this.document.lonhomework) {
            if ((this.document.lonhomework.rndseed) && (this.document.lonhomework.rndseed.value != null) && (this.document.lonhomework.rndseed.value != '')) {
                this.document.cstrprint.curseed.value = this.document.lonhomework.rndseed.value
            }
            if (this.document.lonhomework.problemtype) {
		if (this.document.lonhomework.problemtype.value) {
		    this.document.cstrprint.problemtype.value = 
			this.document.lonhomework.problemtype.value;
		} else if (this.document.lonhomework.problemtype.options) {
		    for (var i=0; i<this.document.lonhomework.problemtype.options.length; i++) {
			if (this.document.lonhomework.problemtype.options[i].selected) {
			    if (this.document.lonhomework.problemtype.options[i].value != null && this.document.lonhomework.problemtype.options[i].value != '') { 
				this.document.cstrprint.problemtype.value = this.document.lonhomework.problemtype.options[i].value
				}
			}
		    }
		}
	    }
	}
        this.document.cstrprint.submit();
        return;
    }
    if (url !='') {
        this.document.constspace.filename.value = filename;
        this.document.constspace.action = url;
        this.document.constspace.submit();
    }
}

function golist(url) {
   if (url!='' && url!= null) {
       currentURL = null;
       currentSymb= null;
       top.location.href=url;
   }
}



function catalog_info() {
   loncatinfo=window.open(window.location.pathname+'.meta',"LONcatInfo",'height=320,width=280,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');
}

function chat_win() {
   lonchat=window.open('/res/adm/pages/chatroom.html',"LONchat",'height=320,width=280,resizable=yes,location=no,menubar=no,toolbar=no');
}

function group_chat(group) {
   var url = '/adm/groupchat?group='+group;
   var winName = 'LONchat_'+group;
   grpchat=window.open(url,winName,'height=320,width=280,resizable=yes,location=no,menubar=no,toolbar=no');
}

function edit_bookmarks() {
   go('');
   w_BookmarkPal_flag=1;
   bookmarkpal=window.open("/adm/bookmarks",
               "BookmarkPal", "width=400,height=505,scrollbars=0");
}

function annotate() {
   w_Annotator_flag=1;
   annotator=window.open('','Annotator','width=365,height=265,scrollbars=0');
   annotator.document.write(
   '$start_page_annotate'
  +"<form name='goannotate' target='Annotator' method='post' "
  +"action='/adm/annotations'>"
  +"<input type='hidden' name='symbnew' value='"+currentSymb+"' />"
  +"<\\/form>"
  +'$end_page_annotate');
   annotator.document.close();
}

function set_bookmark() {
   go('');
   clienttitle=document.title;
   clienthref=location.pathname;
   w_bmquery_flag=1;
   bmquery=window.open('','bmquery','width=365,height=165,scrollbars=0');
   bmquery.document.write(
   '$start_page_bookmark'
   +'<center><form method="post"'
   +' name="newlink" action="/adm/bookmarks" target="bmquery" '
   +'> <table width="340" height="150" '
   +'bgcolor="#FFFFFF" align="center"><tr><td>Link Name:<br /><input '
   +'type="text" name="title" size="45" value="'+clienttitle+'" />'
   +'<br />Address:<br /><input type="text" name="address" size="45" '
   +'value="'+clienthref+'" /><br /><center><input type="submit" '
   +'value="Save" /> <input type="button" value="Close" '
   +'onclick="javascript:window.close();" /></center></td>'
   +'</tr></table></form></center>'
   +'$end_page_bookmark' );
   bmquery.document.close();
}

ENDUTILITY
}

sub serverform {
    return(<<ENDSERVERFORM);
<form name="server" action="/adm/logout" method="post" target="_top">
<input type="hidden" name="postdata" value="none" />
<input type="hidden" name="command" value="none" />
<input type="hidden" name="url" value="none" />
<input type="hidden" name="symb" value="none" />
</form>
ENDSERVERFORM
}

sub constspaceform {
    return(<<ENDCONSTSPACEFORM);
<form name="constspace" action="/adm/logout" method="post" target="_top">
<input type="hidden" name="filename" value="" />
</form>
<form name="cstrdelete" action="/adm/cfile" method="post" target="_top">
<input type="hidden" name="action" value="delete" /> 
<input type="hidden" name="filename" value="" />
</form>
<form name="cstrprint" action="/adm/printout" target="_parent" method="post">
<input type="hidden" name="postdata" value="" />
<input type="hidden" name="curseed" value="" />
<input type="hidden" name="problemtype" value="" />
</form>

ENDCONSTSPACEFORM
}


sub get_nav_status {
    my $navstatus="swmenu.w_loncapanav_flag=";
    if ($env{'environment.remotenavmap'} eq 'on') {
	$navstatus.="1";
    } else {
	$navstatus.="-1";
    }
    return $navstatus;
}

#FIXME this needs to move into mydesk.tab and the other locations 
# the text is generated
#
# We currently do not support this anyway.
#
#sub convert_menu_function {
#    my ($rolename,$type) = @_;
#    if ($type eq 'Group') {
#        $rolename =~ s/student/member/g;
#        $rolename =~ s/group/team/g;
#        $rolename =~ s/course/group/g;
#        $rolename =~ s/Course/Group/g;
#    }
#    return $rolename;
#}

sub hidden_button_check {
    my $hidden;
    if ($env{'request.course.id'} eq '') {
        return;
    }
    if ($env{'request.role.adv'}) {
        return;
    }
    my $buttonshide = &Apache::lonnet::EXT('resource.0.buttonshide');
    return $buttonshide; 
}

sub roles_selector {
    my ($cdom,$cnum) = @_;
    my $now = time;
    my (%courseroles,%seccount);
    my $is_cc;
    my $role_selector;
    if ($env{'user.role.cc./'.$cdom.'/'.$cnum}) {
        my ($start,$end) = split(/\./,$env{'user.role.cc./'.$cdom.'/'.$cnum});
        
        if ((($start) && ($start<0)) || 
            (($end) && ($end<$now))  ||
            (($start) && ($now<$start))) {
            $is_cc = 0;
        } else {
            $is_cc = 1;
        }
    }
    if ($is_cc) {
        &get_all_courseroles($cdom,$cnum,\%courseroles,\%seccount);
    } else {
        my %gotnosection;
        foreach my $item (keys(%env)) {
            if ($item =~ m-^user\.role\.([^.]+)\./\Q$cdom\E/\Q$cnum\E/?(\w*)$-) {
                my $role = $1;
                my $sec = $2;
                next if ($role eq 'gr');
                my ($start,$end) = split(/\./,$env{$item});
                next if (($start && $start > $now) || ($end && $end < $now));
                if ($sec eq '') {
                    if (!$gotnosection{$role}) {
                        $seccount{$role} ++;
                        $gotnosection{$role} = 1;
                    }
                }
                if (ref($courseroles{$role}) eq 'ARRAY') {
                    if ($sec ne '') {
                        if (!grep(/^\Q$sec\E$/,@{$courseroles{$role}})) {
                            push(@{$courseroles{$role}},$sec);
                            $seccount{$role} ++;
                        }
                    }
                } else {
                    @{$courseroles{$role}} = ();
                    if ($sec ne '') {
                        $seccount{$role} ++;
                        push(@{$courseroles{$role}},$sec);
                    }
                }
            }
        }
    }
    my @roles_order = ('cc','in','ta','ep','ad','st');
    if (keys(%courseroles) > 1) {
        $role_selector = &jump_to_role($cdom,$cnum,\%seccount,\%courseroles);
        $role_selector .= '<form name="rolechooser" method="post" action="/adm/roles">
                          <select name="switchrole" onchange="javascript:adhocRole('."'switchrole'".')">';
        $role_selector .= '<option value="">'.&mt('Switch course role to...').'</option>';
        foreach my $role (@roles_order) {
            if (defined($courseroles{$role})) {
                $role_selector .= "\n".'<option value="'.$role.'">'.&Apache::lonnet::plaintext($role).'</option>'; 
            }
        }
        foreach my $role (sort(keys(%courseroles))) {
            if ($role =~ /^cr/) {
                $role_selector .= "\n".'<option value="'.$role.'">'.&Apache::lonnet::plaintext($role).'</option>'; 
            }
        }
        $role_selector .= '</select>'."\n".
               '<input type="hidden" name="destinationurl" value="'.
               $ENV{'REQUEST_URI'}.'" />'."\n".
               '<input type="hidden" name="gotorole" value="1" />'."\n".
               '<input type="hidden" name="selectrole" value="" />'."\n".
               '<input type="hidden" name="switch" value="1" />'."\n".
               '</form>';
    }
    return $role_selector;
}

sub get_all_courseroles {
    my ($cdom,$cnum,$courseroles,$seccount) = @_;
    unless ((ref($courseroles) eq 'HASH') && (ref($seccount) eq 'HASH')) {
        return;
    }
    my ($result,$cached) = 
        &Apache::lonnet::is_cached_new('getcourseroles',$cdom.'_'.$cnum);
    if (defined($cached)) {
        if (ref($result) eq 'HASH') {
            if ((ref($result->{'roles'}) eq 'HASH') && 
                (ref($result->{'seccount'}) eq 'HASH')) {
                %{$courseroles} = %{$result->{'roles'}};
                %{$seccount} = %{$result->{'seccount'}};
                return;
            }
        }
    }
    my %gotnosection;
    my %adv_roles =
         &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1);
    foreach my $role (keys(%adv_roles)) {
        my ($urole,$usec) = split(/:/,$role);
        if (!$gotnosection{$urole}) {
            $seccount->{$urole} ++;
            $gotnosection{$urole} = 1;
        }
        if (ref($courseroles->{$urole}) eq 'ARRAY') {
            if ($usec ne '') {
                if (!grep(/^Q$usec\E$/,@{$courseroles->{$urole}})) {
                    push(@{$courseroles->{$urole}},$usec);
                    $seccount->{$urole} ++;
                }
            }
        } else {
            @{$courseroles->{$urole}} = ();
            if ($usec ne '') {
                $seccount->{$urole} ++;
                push(@{$courseroles->{$urole}},$usec);
            }
        }
    }
    my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum,['st']);
    @{$courseroles->{'st'}} = ();
    if (keys(%sections_count) > 0) {
        push(@{$courseroles->{'st'}},keys(%sections_count));
        $seccount->{'st'} = scalar(keys(%sections_count)); 
    }
    my $rolehash = {
                     'roles'    => $courseroles,
                     'seccount' => $seccount,
                   };
    &Apache::lonnet::do_cache_new('getcourseroles',$cdom.'_'.$cnum,$rolehash);
    return;
}

sub jump_to_role {
    my ($cdom,$cnum,$seccount,$courseroles) = @_;
    my %lt = &Apache::lonlocal::texthash(
                this => 'This role has section(s) associated with it.',
                ente => 'Enter a specific section.',
                orlb => 'Enter a specific section, or leave blank for no section.',
                avai => 'Available sections are:',
                youe => 'You entered an invalid section choice:',
                plst => 'Please try again',
    );
    my $js;
    if (ref($courseroles) eq 'HASH') {
        $js = '    var secpick = new Array("'.$lt{'ente'}.'","'.$lt{'orlb'}.'");'."\n". 
              '    var numsec = new Array();'."\n".
              '    var rolesections = new Array();'."\n".
              '    var rolenames = new Array();'."\n".
              '    var roleseclist = new Array();'."\n";
        my @items = keys(%{$courseroles});
        for (my $i=0; $i<@items; $i++) {
            $js .= '    rolenames['.$i.'] = "'.$items[$i].'";'."\n";
            my ($secs,$secstr);
            if (ref($courseroles->{$items[$i]}) eq 'ARRAY') {
                my @sections = sort { $a <=> $b } @{$courseroles->{$items[$i]}};
                $secs = join('","',@sections);
                $secstr = join(', ',@sections);
            }
            $js .= '    rolesections['.$i.'] = new Array("'.$secs.'");'."\n".
                   '    roleseclist['.$i.'] = "'.$secstr.'";'."\n".
                   '    numsec['.$i.'] = "'.$seccount->{$items[$i]}.'";'."\n";
        }
    }
    return <<"END";
<script type="text/javascript">
//<![CDATA[
function adhocRole(roleitem) {
    $js
    var newrole =  document.rolechooser.elements[roleitem].options[document.rolechooser.elements[roleitem].selectedIndex].value;
    if (newrole == '') {
        return; 
    } 
    var fullrole = newrole+'./$cdom/$cnum';
    var selidx = '';
    for (var i=0; i<rolenames.length; i++) {
        if (rolenames[i] == newrole) {
            selidx = i;
        }
    }
    var secok = 1;
    var secchoice = '';
    if (selidx >= 0) {
        if (numsec[selidx] > 1) {
            secok = 0;
            var numrolesec = rolesections[selidx].length;
            var msgidx = numsec[selidx] - numrolesec;
            secchoice = prompt("$lt{'this'}\\n"+secpick[msgidx]+"\\n$lt{'avai'} "+roleseclist[selidx],"");
            if (secchoice == '') {
                if (msgidx > 0) {
                    secok = 1;
                }
            } else {
                for (var j=0; j<rolesections[selidx].length; j++) {
                    if (rolesections[selidx][j] == secchoice) {
                        secok = 1;
                    }
                }
            }
        } else {
            if (rolesections[selidx].length == 1) {
                secchoice = rolesections[selidx][0];
            }
        }
    }
    if (secok == 1) {
        if (secchoice != '') {
            fullrole += '/'+secchoice;
        }
    } else {
        document.rolechooser.elements[roleitem].selectedIndex = 0;
        if (secchoice != null) {
            alert("$lt{'youe'} \\""+secchoice+"\\".\\n $lt{'plst'}");
        }
        return;
    }
    if (fullrole == "$env{'request.role'}") {
        return;
    }
    itemid = retrieveIndex('gotorole');
    if (itemid != -1) {
        document.rolechooser.elements[itemid].name = fullrole;
    }
    document.rolechooser.elements[roleitem].options[document.rolechooser.elements[roleitem].selectedIndex].value = fullrole;
    document.rolechooser.selectrole.value = '1';
    document.rolechooser.submit();
    return;
}

function retrieveIndex(item) {
    for (var i=0;i<document.rolechooser.elements.length;i++) {
        if (document.rolechooser.elements[i].name == item) {
            return i;
        }
    }
    return -1;
}
// ]]>
</script>
END
}


# ================================================================ Main Program

BEGIN {
    if (! defined($readdesk)) {
	{
	    my $tabfile = $Apache::lonnet::perlvar{'lonTabDir'}.'/mydesk.tab';
	    if ( CORE::open( my $config,"<$tabfile") ) {
		while (my $configline=<$config>) {
		    $configline=(split(/\#/,$configline))[0];
		    $configline=~s/^\s+//;
		    chomp($configline);
                    if ($configline=~/^cat\:/) {
                       my @entries=split(/\:/,$configline);
                       $category_positions{$entries[2]}=$entries[1];
                       $category_names{$entries[2]}=$entries[3];
		    } elsif ($configline) {
			push(@desklines,$configline);
		    }
		}
		CORE::close($config);
	    }
	}
	$readdesk='done';
    }
}

1;
__END__


--droeschl1249996713--