[LON-CAPA-cvs] cvs: loncom /interface loncommon.pm loncoursegroups.pm londropadd.pm

raeburn lon-capa-cvs@mail.lon-capa.org
Sat, 18 Feb 2006 01:27:12 -0000


This is a MIME encoded message

--raeburn1140226032
Content-Type: text/plain

raeburn		Fri Feb 17 20:27:12 2006 EDT

  Modified files:              
    /loncom/interface	londropadd.pm loncoursegroups.pm loncommon.pm 
  Log:
  Re-enable groups links in ENRL page. Add interface to allow group creator to specify mapping of different roles/sections to a group to support auto-add and auto-drop changes in group membership based on role changes of course participants. Implement ability to modify group settings, and to add new members. Changes to loncommon.pm to accommodate extraction of mapping options (roles & sections) when parsing group record in coursegroups.db file. Still working on ability to change functions/privileges/status of existing members.
  
  
--raeburn1140226032
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20060217202712.txt"

Index: loncom/interface/londropadd.pm
diff -u loncom/interface/londropadd.pm:1.136 loncom/interface/londropadd.pm:1.137
--- loncom/interface/londropadd.pm:1.136	Wed Feb  8 18:47:23 2006
+++ loncom/interface/londropadd.pm	Fri Feb 17 20:27:07 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to drop and add students in courses 
 #
-# $Id: londropadd.pm,v 1.136 2006/02/08 23:47:23 raeburn Exp $
+# $Id: londropadd.pm,v 1.137 2006/02/18 01:27:07 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -172,26 +172,26 @@
             permission => &Apache::lonnet::auto_run($cnum,$cdom),
             url  => '/adm/populate',
             },
-#          { text => 'Create a new group',
-#            help => 'Course_Create_Group',
-#            permission => $grp_manage_permission,
-#            url => '/adm/coursegroups?refpage=enrl&action=create',
-#            },
-#          { text => 'Modify an existing group',
-#            help => 'Course_Modify_Group',
-#            permission => $grp_manage_permission,
-#            url => '/adm/coursegroups?refpage=enrl&action=modify',
-#            },
-#          { text => 'Delete an existing group',
-#            help => 'Course_Delete_Group',
-#            permission => $grp_manage_permission,
-#            url => '/adm/coursegroups?refpage=enrl&action=delete',
-#            },
-#          { text => 'Enter an existing group',
-#            help => 'Course_Display_Group',
-#            permission => $grp_view_permission,
-#            url => '/adm/coursegroups?refpage=enrl&action=view',
-#            },
+          { text => 'Create a new group',
+            help => 'Course_Create_Group',
+            permission => $grp_manage_permission,
+            url => '/adm/coursegroups?refpage=enrl&action=create',
+            },
+          { text => 'Modify an existing group',
+            help => 'Course_Modify_Group',
+            permission => $grp_manage_permission,
+            url => '/adm/coursegroups?refpage=enrl&action=modify',
+            },
+          { text => 'Delete an existing group',
+            help => 'Course_Delete_Group',
+            permission => $grp_manage_permission,
+            url => '/adm/coursegroups?refpage=enrl&action=delete',
+            },
+          { text => 'Enter an existing group',
+            help => 'Course_Display_Group',
+            permission => $grp_view_permission,
+            url => '/adm/coursegroups?refpage=enrl&action=view',
+            },
           );
     my $menu_html = '';
     foreach my $menu_item (@menu) {
Index: loncom/interface/loncoursegroups.pm
diff -u loncom/interface/loncoursegroups.pm:1.4 loncom/interface/loncoursegroups.pm:1.5
--- loncom/interface/loncoursegroups.pm:1.4	Mon Nov 21 19:01:41 2005
+++ loncom/interface/loncoursegroups.pm	Fri Feb 17 20:27:07 2006
@@ -51,8 +51,7 @@
     }
 
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
-                                            ['action','refpage']);
-                                                                                      
+                        ['action','refpage','state','groupname','branch']);
     my $function = &Apache::loncommon::get_users_function();
     my $tabcol = &Apache::loncommon::designparm($function.'.tabbg');
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
@@ -62,7 +61,6 @@
           &Apache::lonnet::allowed('vcg',$env{'request.course.id'});
     my $manage_permission =
           &Apache::lonnet::allowed('mdg',$env{'request.course.id'});
-
     &Apache::lonhtmlcommon::clear_breadcrumbs();
 
     my %functions = (
@@ -80,49 +78,67 @@
     $idx{udom} = &Apache::loncoursedata::CL_SDOM();
     $idx{uname} = &Apache::loncoursedata::CL_SNAME();
 
+    my $rowColor1 = "#dddddd";
+    my $rowColor2 = "#eeeeee";
+
     my $action = $env{'form.action'};
     if ($action eq 'create' || $action eq 'modify' || $action eq 'view') { 
         if ($view_permission || $manage_permission) {
             &group_administration($r,$action,$cdom,$cnum,$function,$tabcol,
-                        \%functions,\%idx,$view_permission,$manage_permission);
+                                  \%functions,\%idx,$view_permission,
+                                  $manage_permission,$rowColor1,$rowColor2);
         } else {
             $r->print('You do not have group administration '.
                       'privileges in this course');
         }
     } else {
         &print_main_menu($r,$cdom,$cnum,$function,$tabcol,\%functions,\%idx,
-                                          $view_permission,$manage_permission);
+                         $view_permission,$manage_permission,$action,
+                         $rowColor1,$rowColor2);
     }
     return OK;
 }
 
 sub print_main_menu {
     my ($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,$view_permission,
-                                                          $manage_permission)
-                                                                          = @_;
+        $manage_permission,$action,$rowColor1,$rowColor2) = @_;
     $r->print(&header('Course Groups',&mt('LON-CAPA Course Groups'),
-                                                 undef,undef,undef,$function));
+              undef,undef,undef,undef,$function));
     &Apache::lonhtmlcommon::add_breadcrumb
         ({href=>"/adm/coursegroups",
           text=>"Course Groups",});
     $r->print(&Apache::lonhtmlcommon::breadcrumbs
-                (undef,'Course Groups'));
+              (undef,'Course Groups'));
     &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,
-                                          $view_permission,$manage_permission);
+                    $view_permission,$manage_permission,$action,$rowColor1,
+                    $rowColor2);
     $r->print(&footer());
     return;
 }
 
 sub display_groups {
     my ($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,$view_permission,
-                                                          $manage_permission) = @_;
+        $manage_permission,$action,$rowColor1,$rowColor2) = @_;
     my %curr_groups = ();
     my %grp_info = ();
-    my $rowColor1 = "#dddddd";
-    my $rowColor2 = "#eeeeee";
 
+    my %actionlinks = (
+      modify => '<a href="/adm/coursegroups?action=modify&state=pick_task&refpage='.
+                $env{'form.refpage'}.'&groupname=',
+      view => '<a href="/adm/'.$cdom.'/'.$cnum.'/',
+      delete => '<a href="/adm/coursegroups?action=delete&refpage='.
+                $env{'form.refpage'}.'&groupname=',
+    );
+    my %actiontext = &Apache::lonlocal::texthash( 
+                          modify => 'Modify',
+                          view => 'View',
+                          delete => 'Delete',
+                     );  
     $r->print('<br /><br />');
     if ($view_permission) {
+        if (!defined($action)) {
+            $action = 'view';
+        }
         my %curr_groups;
         if (&Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum)) {
             $r->print(&Apache::lonhtmlcommon::start_pick_box());
@@ -152,7 +168,8 @@
                 %{$grp_info{$group}} = 
                                   &Apache::loncommon::get_group_settings(
                                                          $curr_groups{$group});
-                my $members_result = &group_members($cdom,$cnum,$group,\%grp_info);
+                my $members_result = &group_members($cdom,$cnum,$group,
+                                                    \%grp_info);
                 my $files_result = &group_files($group,\%grp_info); 
                 if ($env{'form.sortby'} eq 'groupname') {
                     push(@{$Sortby{$group}},$group);
@@ -171,8 +188,7 @@
                     push(@{$Sortby{$grp_info{$group}{'totalmembers'}}},
                                                                        $group);
                 } elsif ($env{'form.sortby'} eq 'totalfiles') {
-                    push(@{$Sortby{$grp_info{$group}{'totalfiles'}}},
-                                                                       $group);
+                    push(@{$Sortby{$grp_info{$group}{'totalfiles'}}},$group);
                 } elsif ($env{'form.sortby'} eq 'boards') {
                     push(@{$Sortby{$grp_info{$group}{'boards'}}},$group);
                 } elsif ($env{'form.sortby'} eq 'diskuse') {
@@ -201,7 +217,7 @@
                     my $boards = $grp_info{$group}{'boards'};
                     my $diskuse = $grp_info{$group}{'diskuse'};
                     my $functionality;
-                    foreach my $tool (sort keys(%{$functions})) {
+                    foreach my $tool (sort(keys(%{$functions}))) {
                         if (defined($grp_info{$group}{functions}{$tool})) {
                             $functionality .= ' '.$tool;
                         }
@@ -209,8 +225,14 @@
                     if (!$functionality) {
                         $functionality = 'None available';
                     }
-                    $r->print('<tr bgcolor="'.$rowColor.'"><td align="right">
-   <a href="/adm/'.$cdom.'/'.$cnum.'/'.$group.'/grppg?register=1"/>View</a>&nbsp;<a href="/adm/coursegroups?action=modify&group='.$group.'">Modify</a></td><td><small>'.$group.'</small></td><td><small>'.$description.'</small></td><td><small>'.$creator.'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($creation).'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($modified).'</small></td><td><small>'.$functionality.'</small></td><td><small>'.$quota.'</small></td><td><small>'.$totalmembers.'</small></td><td><small>'.$totalfiles.'</small></td><td><small>'.$boards.'</small></td><td><small>'.$diskuse.'</small></td></tr>');
+                    my $link = $actionlinks{$action};
+                    if ($action eq 'modify' || $action eq 'delete') {
+                        $link .= $group;
+                    } else {
+                        $link .= $group.'/grppg?register=1';
+                    }
+                    $link .= '">'.$actiontext{$action}.'</a>';  
+                    $r->print('<tr bgcolor="'.$rowColor.'"><td><small>'.$link.'</small></td><td><small>'.$group.'</small></td><td><small>'.$description.'</small></td><td><small>'.$creator.'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($creation).'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($modified).'</small></td><td><small>'.$functionality.'</small></td><td><small>'.$quota.'</small></td><td><small>'.$totalmembers.'</small></td><td><small>'.$totalfiles.'</small></td><td><small>'.$boards.'</small></td><td><small>'.$diskuse.'</small></td></tr>');
                     $rowNum ++;
                 }
             }
@@ -226,9 +248,9 @@
             if (&Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum)) {
                 foreach my $group (@coursegroups) {
                     my %group_info =  &Apache::loncommon::get_group_settings(
-                                                   $curr_groups{$group});
+                                        $curr_groups{$group});
                     my $description = &Apache::lonnet::unescape(
-                                                     $group_info{description});
+                                        $group_info{description});
                     my ($uname,$udom) = split(/:/,$group_info{creator});
                     $r->print('<font size="+1"><a href="/adm/'.$udom.'/'.$uname.'/'.$group.'/grppg?register=1">'.$group,'</a><font><br /><small>'.$description.'</small><br /><br />');
                 }
@@ -242,7 +264,7 @@
 
 sub group_administration {
     my ($r,$action,$cdom,$cnum,$function,$tabcol,$functions,$idx,
-                                     $view_permission,$manage_permission) = @_;
+        $view_permission,$manage_permission,$rowColor1,$rowColor2) = @_;
     my %sectioncount = ();
     my @tools = ();
     my @types = ();
@@ -252,29 +274,87 @@
     my %userdata = ();
     my @members = ();
     my %usertools = ();
-
+    my %stored = ();
+    my %memchg;
+    my @member_changes = ('delete','expire','activate','reenable',
+                          'changefunc','changepriv');
     my $state = $env{'form.state'};
-    my ($groupname,$description,$startdate,$enddate);
+    my ($groupname,$description,$startdate,$enddate,$granularity,$specificity);
 
-    if ($action eq 'create') {
+    if (defined($env{'form.groupname'})) {
+        $groupname = $env{'form.groupname'};
+    }
+
+    if (($action eq 'create') && ($state eq '')) {
+        $state = 'pick_name';
+    }
+    if (($action eq 'create') || 
+        (($action eq 'modify') && ($state eq 'chgresult'))) { 
+        ($startdate,$enddate) = &get_dates_from_form();
+        if (defined($env{'form.description'})) {
+            $description = $env{'form.description'};
+        }
+        if (defined($env{'form.tool'})) {
+            @tools=&Apache::loncommon::get_env_multiple('form.tool');
+        }
+        if (defined($env{'form.granularity'})) {
+            $granularity=$env{'form.granularity'};
+        }
+        if (defined($env{'form.specificity'})) {
+            $specificity=$env{'form.specificity'};
+        }
+
+    }
+    if (($action eq 'create') || (($action eq 'modify') 
+        && (($state eq 'pick_privs') || ($state eq 'addresult')))) {
+        if (defined($env{'form.member'})) {
+            @members = &Apache::loncommon::get_env_multiple('form.member');
+            foreach my $user (@members) {
+                %{$usertools{$user}} = ();
+            }
+        }
+    }
+
+    if (($action eq 'modify') && (($state eq 'change_privs') || ($state eq 'memresult'))) {
+        foreach my $chg (@member_changes) {
+            if (defined($env{'form.'.$chg})) {
+                @{$memchg{$chg}} = &Apache::loncommon::get_env_multiple('form.'.$chg);
+            }
+        }
+        &check_changes(\@member_changes,\%memchg);
+        foreach my $change (@member_changes) {
+            if (($change eq 'delete') || ($change eq 'expire')) {
+                next;
+            } 
+            foreach my $user (@{$memchg{$change}}) {
+                %{$usertools{$user}} = ();
+            }
+        }
+    }
+
+    if ($action eq 'modify') {
         if ($state eq '') {
-            $state = 'pick_name';
+            $state = 'pick_group';
         } else {
-            ($startdate,$enddate) = &get_dates_from_form();
-            if (defined($env{'form.groupname'})) {
-                $groupname = $env{'form.groupname'};
-            }
-            if (defined($env{'form.description'})) {
-                $description = $env{'form.description'};
-            }
-            if (defined($env{'form.tool'})) {
-                @tools=&Apache::loncommon::get_env_multiple('form.tool');
-            }
-            if (defined($env{'form.member'})) {
-                @members = &Apache::loncommon::get_env_multiple('form.member');
-                foreach my $user (@members) {
-                    %{$usertools{$user}} = ();
+            %stored = &retrieve_settings($cdom,$cnum,$groupname);
+            if (ref($stored{'types'}) eq 'ARRAY') {
+                @types = @{$stored{'types'}};
+            }
+            if (ref($stored{'roles'}) eq 'ARRAY') {
+                @roles = @{$stored{'roles'}};
+            }
+            if (ref($stored{'sectionpick'}) eq 'ARRAY') {
+                @sections = @{$stored{'sectionpick'}};
+            }
+            unless ($state eq 'chgresult') {
+                if (ref($stored{'tool'}) eq 'ARRAY') { 
+                    @tools = @{$stored{'tool'}};
                 }
+                $startdate = $stored{'startdate'};
+                $enddate = $stored{'enddate'};
+                $description = $stored{'description'};
+                $granularity = $stored{'granularity'};
+                $specificity =  $stored{'specificity'};
             }
         }
     }
@@ -322,8 +402,6 @@
         startdate_hour => 'selectbox',
         enddate_month => 'selectbox',
         enddate_hour => 'selectbox',
-        types => 'selectbox',
-        roles => 'selectbox',
         startdate_day => 'text',
         startdate_year => 'text',
         startdate_minute => 'text',
@@ -338,19 +416,47 @@
         granularity => 'radio',
         no_end_date => 'checkbox',
     );
+    %{$elements{'modify'}{'change_settings'}} = (
+                                   %{$elements{'create'}{'pick_name'}},
+                                                specificity => 'radio',
+                                                defpriv => 'checkbox',
+                                                autorole => 'checkbox',
+                                                autoadd => 'radio',
+                                                autodrop => 'radio',
+                                   );
+    if (ref($stored{'autorole'}) eq 'ARRAY') {
+        foreach my $role (@{$stored{'autorole'}}) {
+            $elements{'modify'}{'change_settings'}{'sec_'.$role} = 'selectbox'; 
+        }
+    }
     %{$elements{'create'}{'pick_members'}} = (
         member => 'checkbox',
+        defpriv => 'checkbox',
+    );
+
+    %{$elements{'modify'}{'add_members'}} = (
+        types => 'selectbox',
+        roles => 'selectbox',
     );
+
     if (($action eq 'create') && ($state eq 'pick_name')) {
+        $elements{'create'}{'pick_name'}{'types'} = 'selectbox';
+        $elements{'create'}{'pick_name'}{'roles'} = 'selectbox';
+    }
+    if ((($action eq 'create') &&  
+        (($state eq 'pick_name') || ($state eq 'pick_privs'))) ||
+       (($action eq 'modify') && (($state eq 'change_settings') ||
+                                  ($state eq 'add_members')))) {
         my $numsections = &Apache::loncommon::get_sections($cdom,$cnum,
-                           \%sectioncount);
+                                                           \%sectioncount);
         if ($numsections > 0) {
             $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';
+            $elements{'modify'}{'change_mapping'}{'sectionpick'} = 'selectbox';
+            $elements{'modify'}{'add_members'}{'sectionpick'} = 'selectbox';
         }
     }
-                                                                                      
-    if (($action eq 'create') && (($state eq 'pick_members') ||
-                                  ($state eq 'pick_privs'))) {
+
+    if ($action eq 'create') {
         if (defined($env{'form.types'})) {
             @types=&Apache::loncommon::get_env_multiple('form.types');
         }
@@ -363,20 +469,24 @@
                 @sections = sort {$a cmp $b} keys(%sectioncount);
             }
         }
+    }
+
+    if (($state eq 'pick_members') || ($state eq 'pick_privs')) {
         &build_members_list($cdom,$cnum,\@types,\@roles,
-                        \@sections,\%users,\%userdata);
+                            \@sections,\%users,\%userdata);
         if ((keys(%users) > 0) && (@tools > 0)) {
             foreach my $tool (@tools) {
-                if ($env{'form.granularity'} eq 'Yes') {
-                    $elements{'create'}{'pick_members'}{'user_'.$tool} = 'checkbox';
+                if ($granularity eq 'Yes') {
+                    $elements{$action}{'pick_members'}{'user_'.$tool} = 'checkbox';
                 }
             }
-            $elements{'create'}{'pick_members'}{'specificity'} = 'radio';
+            $elements{$action}{'pick_members'}{'specificity'} = 'radio';
         }
     }
 
-    if (($action eq 'create') && (($state eq 'pick_privs') || (($state eq 'result') &&
-         ($env{'form.specificity'} eq 'No')))) {
+    if (($state eq 'pick_privs') || ($state eq 'change_privs') ||
+        (($specificity eq 'No') && 
+         (($state eq 'result') || ($state eq 'memresult')))) {
         foreach my $tool (@tools) {
             my @values = &Apache::loncommon::get_env_multiple('form.user_'.$tool);
             foreach my $user (@values) {
@@ -385,13 +495,13 @@
                 }
             }
         }
-        if (($state eq 'pick_privs') && ($env{'form.specificity'} eq 'Yes')) {
-            foreach my $member (@members) {
-                foreach my $tool (keys(%{$usertools{$member}})) {
+        if ((($state eq 'pick_privs') || ($state eq 'change_privs'))
+            && ($specificity eq 'Yes')) {
+            foreach my $user (sort(keys(%usertools))) {
+                foreach my $tool (keys(%{$usertools{$user}})) {
                     foreach my $priv (keys(%{$toolprivs{$tool}})) {
                         unless (exists($fixedprivs{$tool}{$priv})) {
-                            $elements{'create'}{'pick_privs'}{'userpriv_'.$priv} =
-                                                                   'checkbox';
+                            $elements{$action}{$state}{'userpriv_'.$priv} = 'checkbox';
                         }
                     }
                 }
@@ -399,10 +509,7 @@
         }
     }
  
-    my $jscript;
-    if ($env{'form.action'} eq 'create') {
-        $jscript = &Apache::loncommon::check_uncheck_jscript();
-    }
+    my $jscript = &Apache::loncommon::check_uncheck_jscript();
     $jscript .= qq|
 function nextPage(formname,nextstate) {
     formname.state.value= nextstate;
@@ -414,14 +521,38 @@
 }
                                                                                       
 |;
-                                                                                      
     $jscript .= &Apache::lonhtmlcommon::set_form_elements(
-                           \%{$elements{$action}{$state}});
-
+                           \%{$elements{$action}{$state}},\%stored);
+    my $page = 0;
+    my %states = ();
+    my %branchstates = ();
+    @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result');
+    @{$states{'modify'}} = ('pick_group','pick_task');
+    @{$branchstates{'noprivs'}} = ('result');
+    @{$branchstates{'settings'}} = ('change_settings','chgresult');
+    @{$branchstates{'members'}} = ('change_members','change_privs','memresult');
+    @{$branchstates{'adds'}} = ('add_members','pick_members','pick_privs',
+                                'addresult');
+    
+    if (defined($env{'form.branch'})) {
+        push (@{$states{$action}},@{$branchstates{$env{'form.branch'}}});
+    }
+
+    if (($action eq 'create') || ($action eq 'modify')) {
+        my $done = 0;
+        my $i=0;
+        while ($i<@{$states{$action}} && !$done) {
+            if ($states{$action}[$i] eq $state) {
+                $page = $i;
+                $done = 1;
+            }
+            $i++;
+        }
+    }
 
     my $loaditems =  &onload_action($action,$state);
     $r->print(&header('Course Groups Manager',&mt('LON-CAPA Groups Manager'),
-                               $jscript,$action,$state,$function,$loaditems));
+                          $jscript,$action,$state,$page,$function,$loaditems));
 
     if ($env{'form.refpage'} eq 'enrl') {
         &Apache::lonhtmlcommon::add_breadcrumb
@@ -435,19 +566,35 @@
           faq=>9,bug=>'Instructor Interface',});
     }
 
-    my %states = ();
-    @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result');
-    @{$states{'modify'}} = ();
-                                                                                      
     my %trail = ();
-    %{$trail{'create'}} = (
+    %{$trail{'create'}} = &Apache::lonlocal::texthash (
                             pick_name => 'Group Settings',
                             pick_members => 'Select Members',
                             pick_privs => 'Choose Privileges',
                             result => 'Creation Complete',
                           );
-    %{$trail{'modify'}} = ();
-                                                                                      
+    %{$trail{'modify'}} = &Apache::lonlocal::texthash(
+                            pick_group => 'Groups',
+                            pick_task => 'Choose Task',
+                            change_settings => 'Group Settings',
+                            change_members => 'Modify/Delete Members',
+                            change_privs => 'Change Privileges',
+                            change_mapping => 'Membership Mapping',
+                            add_members => 'Add Members',
+                            pick_members => 'Select Members',
+                            pick_privs => 'Choose Privileges',
+                            chgresult => 'Setting Changes Complete',
+                            memresult => 'Modifications Complete',
+                            addresult => 'Additions Complete',
+                          );
+    my %navbuttons = &Apache::lonlocal::texthash(
+                             gtns => 'Go to next step',
+                             gtps => 'Go to previous step',
+                             crgr => 'Create group',
+                             mose => 'Modify settings',
+                             gtpp => 'Go to previous page',
+                             adme => 'Add members',
+    );
     if ((($action eq 'create') || ($action eq 'modify')) &&
               ($manage_permission)) {
         for (my $i=0; $i<@{$states{$action}}; $i++) {
@@ -456,13 +603,16 @@
                    {text=>"$trail{$action}{$state}"});
                 $r->print(&Apache::lonhtmlcommon::breadcrumbs
                      (undef,'Course Groups Manager'));
-                &display_control($r,$cdom,$cnum,$tabcol,$action,$state,
-                         \%sectioncount,$groupname,$description,$functions,
-                         \@tools,\%toolprivs,\%fixedprivs,$startdate,$enddate,
-                         \%users,\%userdata,$idx,\@members,\%usertools);
+                &display_control($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                       \%sectioncount,$groupname,$description,$functions,
+                       \@tools,\%toolprivs,\%fixedprivs,$startdate,$enddate,
+                       \%users,\%userdata,$idx,\%memchg,\%usertools,
+                       $function,$view_permission,$manage_permission,
+                       \%stored,$granularity,$specificity,\@types,\@roles,
+                       \@sections,\%states,\%navbuttons,$rowColor1,$rowColor2);
                 last;
             } else {
-                if ($state eq 'result' && $i > 0) {
+                if (($state  =~ /^\w+result$/) && ($i > 0)) {
                     &Apache::lonhtmlcommon::add_breadcrumb(
     {href=>"javascript:backPage(document.$state,'$states{$action}[0]')",
       text=>"$trail{$action}{$states{$action}[$i]}"});
@@ -479,39 +629,159 @@
         $r->print(&Apache::lonhtmlcommon::breadcrumbs
                      (undef,'Course Groups Manager'));
         &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,
-                                        $view_permission,$manage_permission);
+                        $view_permission,$manage_permission,$action,
+                        $rowColor1,$rowColor2);
 
     }
     $r->print(&footer());
     return;
 }
 
+sub retrieve_settings {
+    my ($cdom,$cnum,$groupname) = @_;
+    my %groupinfo;
+    my %stored;
+    my %curr_groups;
+    my $numgroups = &Apache::loncommon::coursegroups(\%curr_groups,$cdom,
+                                                             $cnum,$groupname);
+    if ($numgroups > 0) {
+        %groupinfo = &Apache::loncommon::get_group_settings(
+                                                     $curr_groups{$groupname});
+        $stored{'description'} = &Apache::lonnet::unescape(
+                                                    $groupinfo{'description'});
+        $stored{'startdate'} = $groupinfo{'startdate'};
+        $stored{'enddate'} = $groupinfo{'enddate'};
+        if ($stored{'enddate'} == 0) {
+            $stored{'no_end_date'} = 1;
+        }
+        $stored{'granularity'} = $groupinfo{'granularity'};
+        $stored{'specificity'} = $groupinfo{'specificity'};
+        $stored{'creation'} = $groupinfo{'creation'};
+        $stored{'creator'} = $groupinfo{'creator'};
+
+        foreach my $tool (sort(keys(%{$groupinfo{'functions'}}))) {
+            if ($groupinfo{functions}{$tool} eq 'on') {
+                push(@{$stored{tool}},$tool);
+            }
+        }
+        foreach my $role (@{$groupinfo{'roles'}}) {
+            push(@{$stored{roles}},$role);
+        }
+        foreach my $type (@{$groupinfo{'types'}}) {
+            push(@{$stored{types}},$type);
+        }
+        foreach my $section (@{$groupinfo{'sectionpick'}}) {
+            push(@{$stored{sectionpick}},$section);
+        }
+        foreach my $defpriv (@{$groupinfo{'defpriv'}}) {
+            push(@{$stored{defpriv}},$defpriv);
+        }
+        $stored{'autoadd'} = $groupinfo{'autoadd'};
+        $stored{'autodrop'} = $groupinfo{'autodrop'};
+        if (exists($groupinfo{'autosec'})) {
+            foreach my $role (sort(keys(%{$groupinfo{'autosec'}}))) {
+                foreach my $section (@{$groupinfo{'autosec'}{$role}}) {
+                    push (@{$stored{'sec_'.$role}},$section);
+                }
+                if (@{$groupinfo{'autosec'}{$role}} > 0) {
+                    push(@{$stored{'autorole'}},$role);
+                }
+            }
+        }
+    }
+    return %stored;
+}
+
 sub display_control {
-    my ($r,$cdom,$cnum,$tabcol,$action,$state,$sectioncount,$groupname,
+    my ($r,$cdom,$cnum,$tabcol,$action,$state,$page,$sectioncount,$groupname,
         $description,$functions,$tools,$toolprivs,$fixedprivs,$startdate,
-                      $enddate,$users,$userdata,$idx,$members,$usertools) = @_;
+        $enddate,$users,$userdata,$idx,$memchg,$usertools,$function,
+        $view_permission,$manage_permission,$stored,$granularity,$specificity,
+        $types,$roles,$sections,$states,$navbuttons,$rowColor1,$rowColor2)=@_;
     if ($action eq 'create') {
         if ($state eq 'pick_name') {
-            &first_creation_form($r,$cdom,$cnum,$tabcol,$state,$functions,
-                                                                $sectioncount);
+            &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page,
+                                   $functions,$tools,$toolprivs,$fixedprivs,
+                                   $sectioncount,$stored,$states,$navbuttons,
+                                   $rowColor1,$rowColor2);
         } elsif ($state eq 'pick_members') {
-            &second_creation_form($r,$cdom,$cnum,$tabcol,$state,$groupname,
-                                  $description,$startdate,$enddate,$tools,
-                                             $functions,$users,$userdata,$idx);
+            &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                                 $groupname,$description,$granularity,
+                                 $startdate,$enddate,$tools,$fixedprivs,
+                                 $toolprivs,$functions,$users,$userdata,$idx,
+                                 $stored,$states,$navbuttons,$rowColor1,
+                                 $rowColor2);
         } elsif ($state eq 'pick_privs') {
-            &third_creation_form($r,$cdom,$cnum,$tabcol,$state,$startdate,
-                           $enddate,$tools,$functions,$toolprivs,$fixedprivs,
-                                           $userdata,$members,$usertools,$idx);
+            &choose_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                               $startdate,$enddate,$tools,$functions,
+                               $toolprivs,$fixedprivs,$userdata,$usertools,
+                               $idx,$states,$stored,$sectioncount,$navbuttons,
+                               $rowColor1,$rowColor2);
         } elsif ($state eq 'result') {
-            &completed_creation($r,$cdom,$cnum,$tabcol,$state,$groupname,
-                            $description,$userdata,$startdate,$enddate,$tools,
-                               $functions,$toolprivs,$members,$usertools,$idx);
+            &process_request($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                             $groupname,$description,$specificity,$userdata,
+                             $startdate,$enddate,$tools,$functions,
+                             $toolprivs,$usertools,$idx,$types,$roles,
+                             $sections,$states,$navbuttons,$memchg,
+                             $sectioncount,$stored,$rowColor1,$rowColor2);
+        }
+    } elsif ($action eq 'modify') {
+        my $groupname = $env{'form.groupname'};
+        if ($state eq 'pick_group') {
+            &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,
+                            $view_permission,$manage_permission,$action,
+                            $rowColor1,$rowColor2);
+        } elsif ($state eq 'pick_task') {
+            &modify_menu($r,$groupname,$page);
+        } elsif ($state eq 'change_settings') {
+            &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page,
+                                   $functions,$tools,$toolprivs,$fixedprivs,
+                                   $sectioncount,$stored,$states,$navbuttons,
+                                   $rowColor1,$rowColor2);
+        } elsif ($state eq 'change_members') {
+            &change_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                                 $groupname,$description,$startdate,$enddate,
+                                 $tools,$fixedprivs,$functions,$users,
+                                 $userdata,$granularity,$specificity,$idx,
+                                 $states,$navbuttons,$rowColor1,$rowColor2);
+        } elsif ($state eq 'add_members') {
+            &add_members_form($r,$tabcol,$action,$state,$page,$startdate,
+                              $enddate,$groupname,$description,$granularity,
+                              $sectioncount,$tools,$functions,$stored,$states,
+                              $navbuttons,$rowColor1,$rowColor2);
+        } elsif ($state eq 'pick_members') {
+            &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                                 $groupname,$description,$granularity,
+                                 $startdate,$enddate,$tools,$fixedprivs,
+                                 $toolprivs,$functions,$users,$userdata,$idx,
+                                 $stored,$states,$navbuttons,$rowColor1,
+                                 $rowColor2);
+        } elsif ($state eq 'pick_privs') {
+            &choose_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                               $startdate,$enddate,$tools,$functions,
+                               $toolprivs,$fixedprivs,$userdata,$usertools,
+                               $idx,$states,$stored,$sectioncount,$navbuttons,
+                               $rowColor1,$rowColor2);
+        } elsif ($state eq 'change_privs') {
+            &change_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                               $startdate,$enddate,$tools,$functions,
+                               $toolprivs,$fixedprivs,$userdata,$usertools,
+                               $memchg,$idx,$states,$stored,$sectioncount,
+                               $navbuttons,$rowColor1,$rowColor2) = @_;
+        } elsif ($state eq 'chgresult' || $state eq 'memresult' || 
+                 $state eq 'addresult') {
+            &process_request($r,$cdom,$cnum,$tabcol,$action,$state,$page,
+                             $groupname,$description,$specificity,$userdata,
+                             $startdate,$enddate,$tools,$functions,
+                             $toolprivs,$usertools,$idx,$types,$roles,
+                             $sections,$states,$navbuttons,$memchg,
+                             $sectioncount,$stored,$rowColor1,$rowColor2);
         }
     }
 }
 
 sub header {
-    my ($bodytitle,$title,$jscript,$action,$state,$function,$loaditems) = @_;
+    my ($bodytitle,$title,$jscript,$action,$state,$page,$function,$loaditems) = @_;
     my $html=&Apache::lonxml::xmlbegin();
     my $bodytag=&Apache::loncommon::bodytag($bodytitle,$function,$loaditems);
     my $output = <<"END";
@@ -531,6 +801,7 @@
  <input type="hidden" name="action" value="$action" />
  <input type="hidden" name="state" value="" />
  <input type="hidden" name="origin" value="$state" />
+ <input type="hidden" name="page" value="$page" />
 END
     }
     return $output;
@@ -547,6 +818,12 @@
              'onload="javascript:setFormElements(document.'.$state.')"';
         }
     }
+    if (($action eq 'modify') &&
+                ($state eq 'change_settings' || $state eq 'change_members' ||
+                 $state eq 'change_privs') || $state eq 'add_members') {
+            $loaditems =
+             'onload="javascript:setFormElements(document.'.$state.')"';
+    }
     return $loaditems;
 }
 
@@ -568,7 +845,7 @@
         $access{$type} = $type;
     }
     &Apache::loncommon::get_course_users($cdom,$cnum,\%access,$roles,
-                                          $sections,$users,$userdata);
+                                         $sections,$users,$userdata);
     return;
 }
 
@@ -610,85 +887,92 @@
 }
 
 
-sub first_creation_form {
-    my ($r,$cdom,$cnum,$tabcol,$formname,$functions,$sectioncount) = @_;
+sub general_settings_form {
+    my ($r,$cdom,$cnum,$action,$tabcol,$formname,$page,$functions,$tools,
+        $toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons,
+        $rowColor1,$rowColor2) = @_;
+    my ($nexttext,$prevtext);
+    $r->print(' <br />
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+');
+    &groupsettings_options($r,$tabcol,$functions,$action,$formname,$stored,1);
+    $r->print(' 
+  <tr>
+   <td colspan="4">&nbsp;</td>
+  </tr>');
+    &access_date_settings($r,$tabcol,$action,$formname,$stored,2);
+    $r->print('
+  <tr>
+   <td colspan="4">&nbsp;</td>
+  </tr>');
+    if ($action eq 'create') {
+        &membership_options($r,$action,$formname,$tabcol,$sectioncount,3);
+        $nexttext = $$navbuttons{'gtns'};
+    } else {
+        my @available = ();
+        my @unavailable = ();
+        &check_tools($functions,$tools,\@available,\@unavailable);
+        @{$tools} = sort(keys(%{$functions}));
+        &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,
+                               3,$tools,$stored,$toolprivs,$fixedprivs,
+                               \@available,$formname);
+        $r->print('
+  <tr>
+   <td colspan="4">&nbsp;</td>
+  </tr>');
+        &mapping_options($r,$action,$formname,$page,$tabcol,$sectioncount,
+                         $states,$stored,$navbuttons,4,5,$rowColor1,
+                         $rowColor2);
+        $nexttext = $$navbuttons{'mose'};
+    }
+    $prevtext = $$navbuttons{'gtpp'};
+    &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
+                        $$states{$action}[$page+1],$nexttext);
+    $r->print('
+ </table>');
+    return;
+}
+
+sub groupsettings_options {
+    my ($r,$tabcol,$functions,$action,$formname,$stored,$image) = @_;
     my %lt = &Apache::lonlocal::texthash(
-        'gmem' => 'Group membership options',
-        'picr' => 'Pick the criteria to use to build a list of course users '.
-                  'from which you will select members of the new group',   
         'gdat' => 'Group open and close dates',
         'sten' => 'Set a start date/time and end date/time for the group',
-        'acty' => 'Access types',
-        'coro' => 'Course roles',
-        'cose' => 'Course sections',
         'gfun' => 'Group functionality',
+        'gnde' => 'Group name, description and available functionality',
+        'desc' => 'Description',
+        'func' => 'Functionality',
+        'gnam' => 'Group Name',
+        'doyo' => 'Do you want to assign different functionality '.
+                  'to different group members?',
     );
-
-    my %status_types = (
-                   active => &mt('Currently has access'),
-                   previous => &mt('Previously had access'),
-                   future => &mt('Will have future access'),
-                   );
-
-    my @roles = ('st','cc','in','ta','ep','cr');
-
-    my $starttime = time;
-    my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
-    my ($start_table,$end_table) = &date_setting_table
-                                    ($starttime,$endtime,$formname);
-
-    my @sections = ();
-    my $section_sel = '';
-    my $numvisible = 4;
-
-    @sections = sort {$a cmp $b} keys(%{$sectioncount});
-    if (@sections > 0) {
-        unshift(@sections,'_all'); # Put 'all' at the front of the list
-        if (@sections < 4) {
-            $numvisible = @sections;
-        }
-        foreach (@sections) {
-            if ($_ eq '_all') {
-                $section_sel .= '  <option value="'.$_.'" />all sections'."\n";
-            } else {
-                $section_sel .= '  <option value="'.$_.'" />'.$_."\n";
-            }
-        }
-    }
-
-    $r->print(<<"END");
- <br />
- <table width="100%" cellpadding="0" cellspacing="0" border="0">
-   <tr bgcolor="$tabcol">
-     <td>&nbsp;</td>
-     <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step1.gif" 
-         valign="bottom">&nbsp;&nbsp;</nobr>
-     </td>
-     <td align="left"><nobr>
-       <font face="arial,helvetica,sans-serif"><b>Group name, description
-         and available functionality</b></font></nobr> 
-     </td>
-     <td width="100%">&nbsp;</td>
-   </tr>
-   <tr>
-    <td colspan="4">&nbsp;</td>
-   </tr>
+    &topic_bar($r,$tabcol,$image,$lt{'gnde'});
+    $r->print('
    <tr>
     <td>&nbsp;</td>
     <td colspan="3">
      <table border="0" cellpadding="2" cellspacing="2">
       <tr>
-       <td><b>Group Name:</b></td>
-       <td colspan="5"><input type="text" name="groupname" size="25" />
+       <td><b>'.$lt{'gnam'}.':</b></td>
+       <td colspan="5">
+');
+    if ($action eq 'create') {
+        $r->print('<input type="text" name="groupname" size="25" />');
+    } else {
+        $r->print('<input type="hidden" name="groupname" value="'.
+                         $env{'form.groupname'}.'" />'.$env{'form.groupname'});
+    }
+    $r->print(<<"END");
        </td>
       <tr>
       <tr>
-       <td><b>Description:</b></td>
-       <td colspan="5"><input type="text" name="description" size="40" />
+       <td><b>$lt{'desc'}:</b></td>
+       <td colspan="5"><input type="text" name="description" size="40"
+                                                    value="" />
        </td>
       <tr>
       <tr>
-       <td><b>Functionality:</b></td>
+       <td><b>$lt{'func'}:</b></td>
 END
     my $numitems = keys(%{$functions});
     my $halfnum = int($numitems/2);
@@ -696,7 +980,7 @@
     if ($remnum) {
         $halfnum ++;
     }
-    my @allfunctions = sort (keys (%{$functions}));
+    my @allfunctions = sort(keys (%{$functions}));
     for (my $i=0; $i<$halfnum; $i++) {
         $r->print('<td><input type="checkbox" name="tool" value="'.
                   $allfunctions[$i].'" />&nbsp;'.
@@ -715,78 +999,75 @@
     if ($remnum) {
         $r->print('<td>&nbsp;</td>');
     }
-    $r->print(<<"END"); 
+    $r->print('
        <td>
-        <input type="button" value="uncheck all" 
-          onclick="javascript:uncheckAll(document.$formname.tool)" />
+        <input type="button" value="uncheck all"
+          onclick="javascript:uncheckAll(document.'.$formname.'.tool)" />
        </td>
       </tr>
       <tr>
        <td><b>Granularity:</b></td>
-       <td colspan="9">Do you want to assign different functionality to different group members?&nbsp;<input type="radio" name="granularity" value="Yes" />Yes&nbsp;<input type="radio" name="granularity" value="No" checked="checked" />No</td>
-      </tr> 
+       <td colspan="9">'.$lt{'doyo'}.'&nbsp;<input type="radio" name="granularity" value="Yes" />'.&mt('Yes').'&nbsp;<input type="radio" name="granularity" value="No" checked="checked" />'.&mt('No'));
+    if ($action eq 'modify') {
+        $r->print('&nbsp;&nbsp;('.&mt('Currently set to "[_1]"',
+                                      $$stored{'granularity'}).')');
+    }
+    $r->print('
+       </td>
+      </tr>
      </table>
     </td>
    </tr>
-   <tr>
-    <td colspan="4">&nbsp;</td>
-   </tr>
-   <tr bgcolor="$tabcol">
-    <td>&nbsp;</td>
-    <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step2.gif" 
-        valign="bottom">&nbsp;&nbsp;</nobr>
-    </td>
-    <td align="left"><nobr>
-      <font face="arial,helvetica,sans-serif"><b>Start and end dates for group
-                                                  access</b></font></nobr>
-    </td>
-    <td width="100%">&nbsp;</td>
-   </tr>
-   <tr>
-    <td colspan="4">&nbsp;</td>
-   </tr>
-   <tr>
-    <td>&nbsp;</td>
-    <td colspan="3">$start_table</td>
-   <tr>
-   <tr>
-    <td colspan="4">&nbsp;</td>
-   </tr>
-   <tr>
-    <td>&nbsp;</td>
-    <td colspan="3">$end_table</td>
-   <tr>
-   <tr>
-    <td colspan="4">&nbsp;</td>
-   </tr>
-   <tr bgcolor="$tabcol">
-    <td>&nbsp;</td>
-    <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step3.gif" 
-        valign="bottom">&nbsp;&nbsp;</nobr>
-    </td>
-    <td align="left"><nobr>
-     <font face="arial,helvetica,sans-serif"><b>Pick parameters to generate 
-         membership list</b></nobr>
-     </font>
-    </td>
-    <td width="100%">&nbsp;</td>
-   </tr>
-   <tr>
-    <td colspan="4">&nbsp;</td>
-   </tr>
+');
+    return;
+}
+
+sub membership_options {
+    my ($r,$action,$state,$tabcol,$sectioncount,$image) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+                'pipa' => 'Pick parameters to generate membership list',
+                'gmem' => 'Group membership options',
+                'picr' => 'Pick the criteria to use to build a list of '.
+                          'course users from which you will select ',
+                'meof' => 'members of the new group.',
+                'adme' => 'additional members of the group.',
+                'ifno' => 'If you do not wish to add members when you first '.
+                          'create the group, do not make any selections',  
+                'acty' => 'Access types',
+                'coro' => 'Course roles',
+                'cose' => 'Course sections',
+             );
+    my %status_types = (
+                   active => &mt('Currently has access'),
+                   previous => &mt('Previously had access'),
+                   future => &mt('Will have future access'),
+                   );
+                                                                                 
+    my @roles = ('st','cc','in','ta','ep','cr');
+
+    my @sections = keys(%{$sectioncount});
+
+    &topic_bar($r,$tabcol,$image,$lt{'pipa'});
+    $r->print('
    <tr>
     <td>&nbsp;</td>
     <td colspan="3">
-     <b>$lt{'gmem'}</b><br/> $lt{'picr'}
-     <br /><br />
+     <b>'.$lt{'gmem'}.'</b><br/>'.$lt{'picr'});
+    if ($action eq 'create') {
+        $r->print($lt{'meof'}.'<br />'.$lt{'ifno'});
+    } else {
+        $r->print($lt{'adme'});
+    }
+    $r->print('
+     <br />
+     <br />
      <table border="0">
       <tr>
-       <td><b>$lt{'acty'}</b></td>
+       <td><b>'.$lt{'acty'}.'</b></td>
        <td>&nbsp;</td>
-       <td><b>$lt{'coro'}</b></td>
-END
+       <td><b>'.$lt{'coro'}.'</b></td>');
     if (@sections >0) {
-         $r->print('
+        $r->print('
        <td>&nbsp;</td>
        <td><b>'.$lt{'cose'}.'</b></td>
        <td>&nbsp;</td>');
@@ -796,239 +1077,344 @@
     $r->print('<td>&nbsp;</td>');
     $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles));
     if (@sections > 0) {
-        $r->print('
-       <td>&nbsp;</td>
-       <td colspan="3" align="center" valign="top">
-        <select name="sectionpick" multiple="true" size="'.$numvisible.'">
-          '.$section_sel.'
-        </select>
-       </td>');
+        @sections = sort {$a cmp $b} @sections;
+        unshift(@sections,'_all'); # Put 'all' at the front of the list
+        unshift(@sections,'_nosec'); # Put 'no sections' next
+        $r->print('<td>&nbsp;</td>
+                   <td colspan="3" align="center" valign="top">'.
+        &sections_selection(\@sections,'sectionpick').'</td>');
     }
     $r->print('
       </tr>
      </table>
     </td>
-   </tr>
+   </tr>');
+    return;
+}
+
+sub sections_selection {
+    my ($sections,$elementname) = @_;
+    my $section_sel;
+    my $numvisible = 4;
+    if (@{$sections} < 4) {
+        $numvisible = @{$sections};
+    }
+    foreach my $sec (@{$sections}) {
+        if ($sec eq '_all') {
+            $section_sel .= '  <option value="'.$sec.'" />all sections'."\n";
+        } elsif ($sec eq '_nosec') {
+            $section_sel .= '  <option value="'.$sec.'" />no section'."\n"; 
+        } else {
+            $section_sel .= '  <option value="'.$sec.'" />'.$sec."\n";
+        }
+    }
+    my $output = '
+        <select name="'.$elementname.'" multiple="true" size="'.$numvisible.'">
+          '.$section_sel.'
+        </select>';
+    return $output;
+}
+
+sub access_date_settings {
+    my ($r,$tabcol,$action,$formname,$stored,$image) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+                'sten' => 'Default start and end dates for group access',
+             );
+    my $starttime = time;
+    my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
+    if ($action eq 'modify') {
+        $starttime = $$stored{'startdate'};
+        unless ($$stored{'enddate'} == 0) {
+            $endtime = $$stored{'enddate'};
+        }
+    }
+    my ($start_table,$end_table) = &date_setting_table
+                                    ($starttime,$endtime,$formname);
+    &topic_bar($r,$tabcol,$image,$lt{'sten'});
+    $r->print('
+   <tr>
+    <td>&nbsp;</td>
+    <td colspan="3">'.$start_table.'</td>
+   <tr>
    <tr>
     <td colspan="4">&nbsp;</td>
    </tr>
    <tr>
     <td>&nbsp;</td>
-    <td colspan="3" align="left">
-     <input type="button" value="Go to next step"  
-     onclick="javascript:nextPage(document.'.$formname.','."'pick_members'".')>
-    </td>
-   </tr>
-</table>
-');
+    <td colspan="3">'.$end_table.'</td>
+   <tr>');
     return;
 }
 
-sub second_creation_form {
-    my ($r,$cdom,$cnum,$tabcol,$formname,$groupname,$description,$startdate,
-                        $enddate,$tools,$functions,$users,$userdata,$idx) = @_;
-    my @regexps = ('user_','userpriv_');
+sub choose_members_form {
+    my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description,
+        $granularity,$startdate,$enddate,$tools,$fixedprivs,$toolprivs,
+        $functions,$users,$userdata,$idx,$stored,$states,$navbuttons,
+        $rowColor1,$rowColor2) = @_;
+    my @regexps = ('user_','userpriv_','sec_');
+    my %origmembers;
     $r->print(&Apache::lonhtmlcommon::echo_form_input(
-                ['origin','action','state','member','specificity'],\@regexps));
-    my %sectioncount = ();
-    my $numsec = &Apache::loncommon::get_sections($cdom,$cnum,\%sectioncount);
-    my %curr_groups;
-    my $numgroups =  &Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum);
-    my $earlyout;
-    my $exitmsg = '<b>Invalid group name</b><br /><br />The group name entered "'.
-                  $groupname.'" ';
-    my $dupmsg = 'Group names and section names used in a course must be unique.'; 
-    if ($groupname =~ /\W/) {
-        $earlyout = $exitmsg.'is not a valid name.<br />Group names may only contain letters, numbers or underscores';
-    }
-    if ($numsec) {
-        if (exists($sectioncount{$groupname})) {
-            $earlyout = $exitmsg.'can not be used as it is the name of a '.
-                                 'section in this course.<br />'.$dupmsg;
-        }
-    }
-    if ($numgroups) {
-        if (exists($curr_groups{$groupname})) {
-            $earlyout = $exitmsg.'can not be used as it is the name of an 
-                                 existing group in this course.<br />'.$dupmsg;
-        }
-    }
-    if ($earlyout) {
-        $r->print('<table border="0" cellpadding="2" cellspacing="2">
- <tr>
-  <td>&nbsp;</td>
-  <td>'.$earlyout.'</td>
- </tr>
- <tr>
-  <td colspan="2">&nbsp;</td>
- </tr>
+         ['origin','action','state','page','member','specificity','branch',
+          'defpriv','autorole','autoadd','autodrop'],
+         \@regexps));
+    my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum);
+    $r->print('
+<table width="100%" cellpadding="0" cellspacing="0" border="0">
  <tr>
   <td>&nbsp;</td>
-  <td align="left">
-   <input type="button" name="previous" value = "Go to previous page"
-    onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>
-  </td>
- </tr>
-</table>
-        ');
+  <td colspan="3">
+');
+    if ($earlyout) {
+        $r->print($earlyout.'</td></tr>');
+        &display_navbuttons($r,$formname,$$states{$action}[$page-1],
+                           $$navbuttons{'gtps'});
+        $r->print('</table>');
         return;
+    } 
+    my ($specimg,$memimg);
+    my @available = ();
+    my @unavailable = ();
+    &check_tools($functions,$tools,\@available,\@unavailable);
+    if ($action eq 'create') {
+        &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,
+                                $functions,$startdate,$enddate,$groupname,
+                                $description,$granularity,\@available,
+                                \@unavailable);
+        $specimg = 4;
+        $memimg = 5;
+    } else {
+        $specimg = 2;
+        $memimg = 3;
+        my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
+                                                               $groupname);
+        foreach my $key (sort(keys(%membership))) {
+            if ($key =~ /^\Q$groupname\E:([^:]+):([^:]+)$/) {
+                my $uname = $1;
+                my $udom = $2;
+                my $user = $uname.':'.$udom;
+                $origmembers{$user} = 1; 
+            }
+        }
     }
-    my $rowColor1 = "#dddddd";
-    my $rowColor2 = "#eeeeee";
-    my $showstart = &Apache::lonlocal::locallocaltime($startdate);
-    my $showend = &Apache::lonlocal::locallocaltime($enddate);
-    $r->print('<table border="0" cellpadding="0" cellspacing="20">
-<tr>
- <td><font face="arial,helvetica,sans-serif"><b>New group selections</b></font>
-<br />When you create the new group, the following settings will apply:
- </td>
-</tr>
+    &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,
+                          $specimg,$tools,$stored,$toolprivs,
+                          $fixedprivs,\@available,$formname);
+    my $newusers = &pick_new_members($r,$action,$formname,$tabcol,$rowColor1,
+                                    $rowColor2,\@available,$idx,$stored,
+                                    $memimg,$users,$userdata,$granularity,
+                                    \%origmembers);
+    if ($newusers || $action eq 'create') {
+        &display_navbuttons($r,$formname,$$states{$action}[$page-1],
+                            $$navbuttons{'gtps'},$$states{$action}[$page+1],
+                            $$navbuttons{'gtns'});
+    } else {
+        &display_navbuttons($r,$formname,$$states{$action}[$page-1],
+                            $$navbuttons{'gtps'});
+    }
+    $r->print('</table>');
+    return;
+}
+
+sub display_navbuttons {
+    my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_;
+    $r->print('
+    <tr>
+     <td colspan="4">&nbsp;</td>
+    </tr>
+    <tr>
+     <td>&nbsp;</td>
+     <td colspan="3">');
+    if ($prev) {
+        $r->print('
+      <input type="button" name="previous" value = "'.$prevtext.'"
+    onclick="javascript:backPage(document.'.$formname.','."'".$prev."'".')"/>
+   &nbsp;&nbsp;&nbsp;');
+    }
+    if ($next) {
+        $r->print('
+      <input type="button" name="next" value="'.$nexttext.'"
+ onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');
+    }
+    $r->print('
+     </td>
+    </tr>
+');
+}
+
+sub check_tools {
+    my ($functions,$tools,$available,$unavailable) = @_;
+    foreach my $item (sort(keys(%{$functions}))) {
+        if (grep/^$item$/,@{$tools}) {
+            push(@{$available},$item);
+        } else {
+            push(@{$unavailable},$item);
+        }
+    }
+    return;
+}
+
+sub print_current_settings {
+    my ($r,$action,$tabcol,$rowColor1,$rowColor2,$functions,$startdate,$enddate,
+           $groupname,$description,$granularity,$available,$unavailable) =@_;
+
+    my %lt = &Apache::lonlocal::texthash(
+        grna => 'Group Name',
+        desc => 'Description',
+        grfn => 'Group Functions',
+        gran => 'Granularity',
+        dfac => 'Default access dates',
+        ygrs => 'Your group selections',
+        tfwa => 'The following settings will apply to the group:',
+        difn => 'Different functionality<br />for different users:',
+        stda => 'Start date',
+        enda => 'End date:',
+    );
+    my $showstart = &Apache::lonlocal::locallocaltime($startdate);
+    my $showend;
+    if ($enddate == 0) {
+        $showend = &mt('No end date set'); 
+    } else {
+        $showend = &Apache::lonlocal::locallocaltime($enddate);
+    }
+    $r->print('<table border="0" cellpadding="0" cellspacing="20">');
+    if ($action eq 'create') {
+        $r->print('
 <tr>
- <td>');
+ <td><font face="arial,helvetica,sans-serif"><b>'.$lt{'ygrs'}.'</b></font>
+<br />'.$lt{'tfwa'}.'
+ </td>
+</tr>');
+    }
+    $r->print('<tr><td>');
     $r->print(&Apache::lonhtmlcommon::start_pick_box());
     $r->print('
+<tr>
+ <td>
 <table cellspacing="1" cellpadding="4">
  <tr bgcolor="'.$tabcol.'" align="center">
-  <td><b>Group Name</b></td>
-  <td><b>Description</b></td>
-  <td><b>Group Functionality</b></td>
-  <td><b>Default access dates</b></td>
+  <td><b>'.$lt{'grna'}.'</b></td>
+  <td><b>'.$lt{'desc'}.'</b></td>
+  <td><b>'.$lt{'grfn'}.'</b></td>
+  <td><b>'.$lt{'gran'}.'</b></td>
+  <td><b>'.$lt{'dfac'}.'</b></td>
  </tr>
  <tr bgcolor="'.$rowColor2.'">
   <td valign="top"><small>'.$groupname.'</small></td>
   <td valign="top"><small>'.$description.'</small></td>
   <td>
 ');
-    my @available = ();
-    my @unavailable = ();
-    foreach my $item (sort(keys(%{$functions}))) {
-        if (grep/^$item$/,@{$tools}) {
-            push(@available,$item);
-        } else {
-            push(@unavailable,$item);
-        }
-    }
-    if (@available > 0) {
+    if (@{$available} > 0) {
         $r->print('<small><b>Available:</b></small>
                     <table cellpadding="" cellspacing="1"><tr>');
-        my $rowcell = int(@available/2) + @available%2;
-        for (my $i=0; $i<@available; $i++) {
-            if (@available > 3) {
+        my $rowcell = int(@{$available}/2) + @{$available}%2;
+        for (my $i=0; $i<@{$available}; $i++) {
+            if (@{$available} > 3) {
                 if ($i==$rowcell) {
                     $r->print('</tr><tr>');
                 }
             }
-            $r->print('<td><small>'.$$functions{$available[$i]}.
+            $r->print('<td><small>'.$$functions{$$available[$i]}.
                                           '</small></td><td>&nbsp;</td>');
         }
-        if ((@available > 3) && (@available%2)) {
+        if ((@{$available} > 3) && (@{$available}%2)) {
             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
         }
         $r->print('</tr></table><br />');
     }
-    if (@unavailable > 0) {
+    if (@{$unavailable} > 0) {
         $r->print('<small><b>Unavailable:</b></small>
                     <table cellpadding="0" cellspacing="1"  border="0"><tr>');
-        my $rowcell = int(@unavailable/2) + @unavailable%2;
-        for (my $j=0; $j<@unavailable; $j++) {
-            if (@unavailable > 3) {
+        my $rowcell = int(@{$unavailable}/2) + @{$unavailable}%2;
+        for (my $j=0; $j<@{$unavailable}; $j++) {
+            if (@{$unavailable} > 3) {
                 if ($j==$rowcell) {
                     $r->print('</tr><tr>');
                 }
             }
-            $r->print('<td><small>'.$$functions{$unavailable[$j]}.
+            $r->print('<td><small>'.$$functions{$$unavailable[$j]}.
                                               '</small></td><td>&nbsp;</td>');
         }
-        if ((@unavailable > 3) && (@unavailable%2)) {
+        if ((@{$unavailable} > 3) && (@{$unavailable}%2)) {
             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
         }
         $r->print('</tr></table>');
     }
     $r->print(<<"END");
   </td>
-  <td valign="top"><small><b>Start date:</b> $showstart<br />
-      <b>End date:</b> $showend</small>
+  <td valign="top"><small><b>$lt{'difn'}
+  </b> $granularity</small> 
+  <td valign="top"><small><b>$lt{'stda'}</b> $showstart<br />
+      <b>$lt{'enda'}</b> $showend</small>
   </td>
  </tr>
 </table>
+</td>
+</tr>
 END
     $r->print(&Apache::lonhtmlcommon::end_pick_box());
-    my %members = ();
+    $r->print('</td></tr></table><br />');
+    return;
+}
+
+sub pick_new_members {
+    my ($r,$action,$formname,$tabcol,$rowColor1,$rowColor2,$available,$idx,
+        $stored,$img,$users,$userdata,$granularity,$origmembers) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+          'gpme' => 'Group membership',
+          'addm' => 'Add members',
+          'setf' => 'Set functionality',
+          'func' => 'Functionality',
+          'nome' => 'No members to add at this time.',
+          'nnew' => 'There are no users to add as new members, as all users'.
+                    ' matching the specified type(s), role(s), and/or '.
+                    'section(s) are already affiliated with this group.',
+          'yoma' =>  'You may need to use the '."'".'modify existing, past or '.
+                     'future members'."'".' page if you need to re-enable '.
+                     'or activate access for previous or future members.',
+    );
+    my %members;
+    my $totalusers = 0;
+    my $newusers = 0;
     foreach my $role (keys(%{$users})) {
         foreach my $user (keys(%{$$users{$role}})) {
+            $totalusers ++;
+            if (ref($origmembers) eq 'HASH') {
+                if (exists($$origmembers{$user})) {
+                    next;
+                }
+            }    
             unless (defined($members{$user})) {
                 @{$members{$user}} = @{$$userdata{$user}};
+                $newusers ++;
             }
         }
     }
-    $r->print('</td></tr></table><br />');
     if (keys(%members) > 0) {
-        if ($env{'form.granularity'} eq 'Yes') {
-            $r->print('
-<script type="text/javascript">
-function checkAllTools(formname) {
-');
-            foreach my $tool (@available) {
-                $r->print('  checkAll(formname.user_'.$tool.');'."\n");
-            }
-            $r->print('
-}
-function uncheckAllTools(formname) {
-');
-            foreach my $tool (@available) {
-                $r->print('  uncheckAll(formname.user_'.$tool.');'."\n");
-            }
-            $r->print('
-}
-</script>
-            ');
-       }
-       $r->print(<<"END");
-<table width="100%" cellpadding="0" cellspacing="0" border="0">
- <tr bgcolor="$tabcol">
-  <td>&nbsp;</td>
-  <td valign="top" align="left">
-   <nobr><img src="/res/adm/pages/bl_step4.gif" valign="middle">&nbsp;</nobr>
-  </td>
-  <td alin="left">
-   <nobr>
-   <font face="arial,helvetica,sans-serif">
-    <b>Select group members</b>
-   </font></nobr>
-  </td>
-  <td width="100%">&nbsp;</td>
- </tr>
- <tr>
-  <td colspan="4">&nbsp;</td>
- </tr>
+        if (@{$available} > 0 && $granularity eq 'Yes') {
+            $r->print(&check_uncheck_tools($r,$available));
+        }
+    }
+    &topic_bar($r,$tabcol,$img,$lt{'gpme'});
+    if (keys(%members) > 0) {
+        $r->print('
  <tr>
   <td>&nbsp;</td>
-  <td colspan="2">
+  <td colspan="3">
     <table>
-     <tr>
-      <td>
-   <nobr>
-    <fieldset><legend><b>Add members</b></legend>
-     <input type="button" value="check all" 
-       onclick="javascript:checkAll(document.$formname.member)" />
-      &nbsp;&nbsp;
-     <input type="button" value="uncheck all" 
-      onclick="javascript:uncheckAll(document.$formname.member)" />
-    </fieldset></nobr></td>
-END
-        if (@available > 0 && $env{'form.granularity'} eq 'Yes') {
-            $r->print('<td><nobr><fieldset><legend><b> 
-                                      Set functionality</b></legend>
-     <input type="button" value="check all" 
-       onclick="javascript:checkAllTools(document.'.$formname.')" />
-       &nbsp;&nbsp;
-     <input type="button" value="uncheck all" 
+     <tr>');
+        &check_uncheck_buttons($r,$formname,'member',$lt{'addm'});
+        if (@{$available} > 0 && $granularity eq 'Yes') {
+            $r->print('<td><nobr>
+     <fieldset><legend><b>'.$lt{'setf'}.'</b></legend>
+      <input type="button" value="check all"
+        onclick="javascript:checkAllTools(document.'.$formname.')" />
+        &nbsp;&nbsp;
+      <input type="button" value="uncheck all"
         onclick="javascript:uncheckAllTools(document.'.$formname.')" />
-    </fieldset></nobr></td>');
+     </fieldset></nobr></td>');
         }
         $r->print('</tr></table>
   </td>
-  <td width="100%">&nbsp;</td>
  </tr>
  <tr>
   <td colspan="4">&nbsp;</td>
@@ -1038,20 +1424,33 @@
   <td colspan="3">
         ');
         $r->print(&Apache::lonhtmlcommon::start_pick_box());
-        $r->print(<<"END");
+        $r->print('
    <table border="0" cellpadding="4" cellspacing="1">
-    <tr bgcolor="$tabcol" align="center">
-     <td><b>Add?</b></td>
-     <td><b><a href="javascript:changeSort('fullname')">Name</a></b></td>
-     <td><b><a href="javascript:changeSort('username')">Username</a></b>
+    <tr bgcolor="'.$tabcol.'" align="center">
+     <td><b>'.&mt('Add?').'</b></td>
+     <td><b><a href="javascript:changeSort('."'fullname'".')">'.&mt('Name').'</a></b></td>
+     <td><b><a href="javascript:changeSort('."'username'".')">'.&mt('Username').'</a></b>
      </td>
-     <td><b><a href="javascript:changeSort('domain')">Domain</a></b></td>
-     <td><b><a href="javascript:changeSort('id')">ID</a></b></td>
-END
-        if (@available > 0) {
-            $r->print('<td><b>Functionality</b></td>');
+     <td><b><a href="javascript:changeSort('."'domain'".')">'.&mt('Domain').'</a></b></td>
+     <td><b><a href="javascript:changeSort('."'id'".')">ID</a></b></td>
+');
+        if (@{$available} > 0) {
+            $r->print('<td><b>'.$lt{'func'}.'</b></td>');
         }
         $r->print('</tr>');
+        if (@{$available} > 0) {
+            if ($granularity eq 'Yes') {
+                $r->print('<tr bgcolor="#cccccc">
+ <td colspan="5">&nbsp;</td>
+ <td align="center"><small><nobr><b>All:</b>&nbsp;');
+                foreach my $tool (@{$available}) {
+                    $r->print('<input type="checkbox" name="togglefunc" '.
+   'onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);">'.
+   '<b>'.$tool.'</b>&nbsp;&nbsp;&nbsp;');
+                }
+                $r->print('</nobr></small></td></tr>');
+            }
+        }
         my %Sortby = ();
         foreach my $user (sort(keys(%members))) {
             if ($env{'form.sortby'} eq 'fullname') {
@@ -1083,10 +1482,11 @@
    <input type="checkbox" name="member" value="'.$user.'" /></td><td><small>'.
     $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.
     $udom.'</small></td><td><small>'.$id.'</small></td>');
-                if (@available > 0) {
-                    $r->print('<td align="center"><small>'); 
-                    foreach my $tool (@available) {
-                        if ($env{'form.granularity'} eq 'Yes') {
+                if (@{$available} > 0) {
+                    $r->print('<td align="center"><nobr><small>'.
+                              '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
+                    foreach my $tool (@{$available}) {
+                        if ($granularity eq 'Yes') {
                             $r->print('<input type="checkbox" name="user_'.
                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                         } else {
@@ -1094,7 +1494,7 @@
                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                         }
                     }
-                    $r->print('</small></td>');
+                    $r->print('</small></nobr></td>');
                 }
                 $r->print('</tr>'."\n");
                 $rowNum ++;
@@ -1102,402 +1502,1450 @@
         }
         $r->print(&Apache::lonhtmlcommon::end_pick_box());
         $r->print('
+     </td>
+    </tr>');
+    } else {
+        $r->print('
+    <tr>
+     <td>&nbsp;</td>
+     <td colspan="3">
+');
+        if ($totalusers > 0) {
+            $r->print($lt{'nnew'}.'<br /><br />'.$lt{'yoma'});
+        } else { 
+            $r->print($lt{'nome'});
+        }
+        $r->print('
+     </td>
+    </tr>');
+    }
+    return $newusers;
+}
+
+sub privilege_specificity {
+    my ($r,$tabcol,$rowColor1,$rowColor2,$action,$img,$tools,$stored,
+        $toolprivs,$fixedprivs,$available,$formname) = @_;
+    my %lt = &Apache::lonlocal::texthash (
+      'uprv' => 'User privileges',
+      'frty' => 'For each type of functionality you have chosen to include, '.
+                'there is a set of standard privileges which apply to all '.
+                'of those for whom the functionality is enabled.',
+      'thar' => 'There are also additional privileges which can be set for '.
+                'some, or all, members. Please choose one of the following:',
+      'fort' => 'For the types of functionality you have chosen to include '.
+                'there are no additional privileges which can be set for some '.
+                'or all members.',
+      'eaty' => 'Each of the types of functionality includes standard '.
+                'privileges which apply to members with access to that '.
+                'functionality, and may also include additional privileges '.
+                'which can be set for specific members.',
+      'cutg' => 'Currently the group is configured ',
+      'sdif' => 'so different group members can receive different privileges.',
+      'sall' => 'so all group members will receive the same privileges.',
+      'algm' => 'All group members will receive the same privileges.',
+      'smgp' => 'Some group members will receive different privileges from '.
+                'others.',
+      'thwi' => 'These will be the privileges all group members receive, '. 
+                'if you selected the first option above.',
+      'thes' => 'These will be the privileges given to members assigned '.   
+                'in the future, including via automatic group assignment '.
+                'for specific sections/roles ',
+      'asyo' => 'As you have chosen not to include any functionality in the '.
+                'group, no default user privileges settings need to be set.',
+      'plin' => 'Please indicate which <b>optional</b> privileges members '.
+                'will receive by default.',
+      'oppr' => 'Optional privileges',
+      'defp' => 'The default privileges new members will receive are:', 
+    );
+    my $totaloptionalprivs = 0;
+    foreach my $tool (@{$tools}) {
+        foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
+            if (!exists($$fixedprivs{$tool}{$priv})) {
+                $totaloptionalprivs ++;
+            }
+        }
+    }
+    &topic_bar($r,$tabcol,$img,$lt{'uprv'});
+    $r->print('
+ <tr>
+  <td>&nbsp;</td>
+  <td colspan="3">
+  ');
+    if ((($action eq 'create') && (@{$available} > 0)) || 
+        (($action eq 'modify') && ($formname eq 'change_settings'))) {  
+        my %specific = (
+                      'No'  => 'checked="checked"',
+                      'Yes' => '',
+                  );
+        if ($action eq 'create') {
+            $r->print($lt{'frty'}.'<br />');
+            if ($totaloptionalprivs) {
+                $r->print($lt{'thar'});
+            } else {
+                $r->print($lt{'fort'});
+            }
+        } else {
+            $r->print($lt{'eaty'}.'&nbsp;'.$lt{cutg});
+            if ($$stored{'specificity'} eq 'Yes') {
+                $r->print($lt{'sdif'});
+                $specific{'Yes'} = $specific{'No'};
+                $specific{'No'} = '';
+            } else {
+                $r->print($lt{'sall'});
+            }
+        }
+        if ($totaloptionalprivs) {
+            $r->print('
+<br /><br /><nobr><input type="radio" name="specificity" value="No" '.$specific{'No'}.' />&nbsp;'.$lt{'algm'}.'</nobr><br/>
+<nobr><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' />&nbsp;'.$lt{'smgp'}.'</nobr>
   </td>
  </tr>
  <tr>
   <td colspan="4">&nbsp;</td>
  </tr>');
-        if (@available > 0) {
+        } else {
+            $r->print('<input type="hidden" name="specificity" value="No" />');
+        }
+        if ($totaloptionalprivs) {
             $r->print('
- <tr bgcolor="'.$tabcol.'">
+ <tr>
   <td>&nbsp;</td>
-  <td valign="middle" align="left">
-   <nobr><img src="/res/adm/pages/bl_step5.gif" valign="middle">&nbsp;</nobr>
-  </td>
-  <td align="left"><nobr>
-   <font face="arial,helvetica,sans-serif">
-    <b>User privileges</b>
-   </font></nobr>
+  <td colspan="3">'.$lt{'plin'});
+            if ($action eq 'create') {
+                $r->print(' '.$lt{'thwi'});
+            }
+            $r->print('<br />'.$lt{'thes'});
+            if ($action eq 'create') {
+                $r->print('('.&mt('if enabled on the next page').').');
+            } else {
+                $r->print('('.&mt('if enabled below').').');
+            }
+            $r->print('<br /><br />
   </td>
-  <td width="100%">&nbsp;</td>
  </tr>
  <tr>
   <td>&nbsp;</td>
+  <td colspan="2"><table><tr>');
+        &check_uncheck_buttons($r,$formname,'defpriv',$lt{'oppr'});
+        $r->print('
+    </tr>
+   </table>
+  </td>
+  <td width="100%">&nbsp;</td>
+ </tr><tr>
+  <td>&nbsp;</td>
   <td colspan="3">
    <br />
-   For each type of functionality you have chosen to include, there is a 
-set of standard privileges which apply to all of those for whom the functionality is enabled.<br />There are also additional privileges which can be set for some, or all, members. Please choose one of the following:<br />
-<br /><input type="radio" name="specificity" value="No" checked="checked" />&nbsp;All group members will receive the same privileges.<br/><input type="radio" name="specificity" value="Yes" />&nbsp;Some group members will receive different privileges from others.
-  </td>
- </tr>
- <tr>
-  <td colspan="4">&nbsp;</td>
- </tr>
 ');
+        } else {
+            $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'algm'}.'<br /><br />');
         }
-        $r->print('    
- <tr>
-  <td>&nbsp;</td>
-  <td colspan="3">
-   <input type="button" name="previous" value = "Go to previous page" 
-    onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>
-   &nbsp;&nbsp;&nbsp;
-   <input type="button" name="next" value="Go to next page" 
- onclick="javascript:nextPage(document.'.$formname.','."'pick_privs'".')" />
-  </td>
- </tr>
-        ');
+        &default_privileges($r,$action,$tabcol,$rowColor1,$rowColor2,
+                            $tools,$toolprivs,$fixedprivs,$available);
     } else {
-        $r->print('No members to add');
+        if ($action eq 'create') {
+            $r->print($lt{'asyo'});
+        } elsif ($action eq 'modify' && $formname eq 'pick_members') {
+            my @defprivs;
+            if (ref($$stored{'defpriv'}) eq 'ARRAY') {
+                @defprivs = @{$$stored{'defpriv'}};
+            }
+            $r->print($lt{'eaty'}.'&nbsp;'.$lt{cutg});
+            if ($$stored{'specificity'} eq 'Yes') {
+                $r->print($lt{'sdif'});
+            } else {
+                $r->print($lt{'sall'});
+            }
+            $r->print(' '.$lt{'defp'}.'<br /><br />');
+            &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools,
+                              $toolprivs,\@defprivs);
+        }
     }
     $r->print('
-   </table>
   </td>
  </tr>
-</table>');
+');
     return;
 }
 
-sub third_creation_form {
-    my ($r,$cdom,$cnum,$tabcol,$formname,$startdate,$enddate,$tools,$functions,
-               $toolprivs,$fixedprivs,$userdata,$members,$usertools,$idx) = @_;
-    my @regexps = ('userpriv_','allpriv_');
-    $r->print(&Apache::lonhtmlcommon::echo_form_input(
-                             ['origin','action','state'],\@regexps));
-    my %possibles = ();
-    my %showboxes = ();
-    my $totalboxes = 0;
-    my $rowColor1 = "#dddddd";
-    my $rowColor2 = "#eeeeee";
-    my $numtools = 1 + @{$tools};
+sub default_privileges {
+    my ($r,$action,$tabcol,$rowColor1,$rowColor2,$tools,$toolprivs,
+        $fixedprivs,$available) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+                                'addp' => 'Additional privileges',
+                                'fixp' => 'Fixed privileges',
+                                'oppr' => 'Optional privileges',
+                                'func' => 'Function',
+    );
+    $r->print(&Apache::lonhtmlcommon::start_pick_box());
+    $r->print('<tr>
+                <td bgcolor="'.$tabcol.'" valign="top">
+                 <table cellspacing="0" cellpadding="1">
+                  <tr>
+                   <td valign="top"><b>'.$lt{'func'}.'</b></td>
+                  </tr>
+                  <tr>
+                   <td valign="top"><b>'.$lt{'fixp'}.'</b></td>
+                  </tr>
+                  <tr>
+                   <td valign="top"><b>'.$lt{'oppr'}.'</b></td>
+                  </tr>
+                 </table>
+                </td>
+    ');
     foreach my $tool (@{$tools}) {
-        @{$showboxes{$tool}} = ();
-        foreach my $user (@{$members}) {
-            if (exists($$usertools{$user}{$tool})) {
-                foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
-                    unless (exists($$fixedprivs{$tool}{$priv})) {
-                        push(@{$possibles{$user}},$priv);
-                        unless(grep(/^$priv$/,@{$showboxes{$tool}})) {
-                            push(@{$showboxes{$tool}},$priv);
-                            $totalboxes ++;
-                        }
+        $r->print('<td align="center" valign="top">
+                    <table cellspacing="0" cellpadding="1">
+                     <tr bgcolor="#cccccc">
+                      <td colspan="2" align="center"><b>'.$tool.'</b></td>
+                     </tr>
+        ');
+        my $privcount = 0;
+        my $fixed = '';
+        my $dynamic = '';
+        foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
+            if (exists($$fixedprivs{$tool}{$priv})) {
+                $fixed .= '<input type="hidden" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
+                if ($action eq 'modify') {
+                    if (grep/^$tool$/,@{$available}) {
+                        $fixed .= '<small>'.&mt('(on)').'<small>&nbsp;';
+                    } else {
+                        $fixed .= '<small>'.&mt('(off)').'<small>&nbsp;';
                     }
                 }
+            } else {
+                $privcount ++;
+                if ($privcount == 3) {
+                    $dynamic .= '</tr>
+                                 <tr bgcolor="'.$rowColor1.'">'."\n";
+                }
+                $dynamic .= '<td><input type="checkbox" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'</td>'."\n";
             }
         }
-    }
-    if ($totalboxes > 0) {
-        $r->print('
-<script type="text/javascript">
-function checkAllTools(formname) {
-');
-        foreach my $tool (sort(keys(%showboxes))) {
-            foreach my $priv (@{$showboxes{$tool}}) {
-                $r->print('  checkAll(formname.userpriv_'.$priv.');'."\n");
-            }
+        if ($dynamic eq '') {
+            $dynamic = '<td>None</td>'."\n";
         }
-        $r->print('
+        if ($privcount < 3) {
+            $dynamic .= '</tr>
+                         <tr bgcolor="'.$rowColor1.'">
+                          <td colspan="2">&nbsp;</td>'."\n";
+        } elsif ($privcount%2) {
+            $dynamic = '<td>&nbsp;</td>'."\n";
+        }
+        $r->print('<tr bgcolor="'.$rowColor2.'">
+                    <td colspan="2" align="center"><nobr>'.$fixed.'</nobr></td>
+                   </tr>
+                   <tr bgcolor="'.$rowColor1.'">'."\n".$dynamic.'</tr>'."\n".'</table>'."\n".'</td>
+        ');
+    }
+    $r->print('</tr>'."\n");
+    $r->print(&Apache::lonhtmlcommon::end_pick_box());
+    $r->print('<br />');
+    return;
 }
-function uncheckAllTools(formname) {
-');
-        foreach my $tool (sort(keys(%showboxes))) {
-            foreach my $priv (@{$showboxes{$tool}}) {
-                $r->print('  uncheckAll(formname.userpriv_'.$priv.');'."\n");
+
+sub display_defprivs {
+    my ($r,$tabcol,$rowColor1,$rowColor2,$tools,$toolprivs,$defprivs) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+                                'priv' => 'Privileges',
+                                'func' => 'Function',
+    );
+    $r->print(&Apache::lonhtmlcommon::start_pick_box());
+    $r->print('<tr>');
+    my $numrows = 0;
+    my %currprivs;
+    foreach my $tool (@{$tools}) {
+        @{$currprivs{$tool}} = ();
+        foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
+            if (ref($defprivs) eq 'ARRAY') {
+                if (grep/^\Q$priv\E$/,@{$defprivs}) {
+                    push(@{$currprivs{$tool}},$priv);
+                }
             }
         }
-        $r->print('
+        my $rowcount = int(@{$currprivs{$tool}}/3);
+        if (@{$currprivs{$tool}}%3 > 0) {
+            $rowcount ++;
+        }
+        if ($rowcount > $numrows) {
+            $numrows = $rowcount;
+        }
+    }
+    my @rowCols = ($rowColor1,$rowColor2);
+    foreach my $tool (@{$tools}) {
+        $r->print('<td align="center" valign="top">
+                    <table cellspacing="0" cellpadding="5">
+                     <tr bgcolor="#cccccc">
+                      <td colspan="3" align="center"><b>'.$tool.'</b></td>
+                     </tr>
+        ');
+        my $rownum = 1;
+        my $privcount = 0;
+        $r->print('<tr bgcolor="'.$rowColor1.'">');
+        foreach my $priv (@{$currprivs{$tool}}) {
+            $privcount ++;
+            if ($privcount%4 == 0) {
+                $rownum ++;
+                my $bgcol = $rownum%2; 
+                $r->print('</tr>
+                             <tr bgcolor="'.$rowCols[$bgcol].'">'."\n");
+            }
+            $r->print('<td>'.$$toolprivs{$tool}{$priv}.'</td>'."\n");
+        }
+        if ($privcount%3 > 0) {
+            my $emptycells = 3-($privcount%3);
+            while($emptycells > 0) {
+                $r->print('<td>&nbsp;</td>'."\n");
+                $emptycells --;
+            }
+        }
+        while ($rownum < $numrows) {
+            $rownum ++;
+            my $bgcol = $rownum%2;
+            $r->print('<tr bgcolor="'.$rowCols[$bgcol].'"><td colspan="3">&nbsp;</td></tr>');
+        }
+        $r->print('</table>'."\n".'</td>');
+    }
+    $r->print('</tr>'."\n");
+    $r->print(&Apache::lonhtmlcommon::end_pick_box());
+    $r->print('<br />');
+    return;
 }
-</script>
-       ');
-   }
-   $r->print(<<"END");
+
+
+sub change_members_form {
+    my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description,
+        $startdate,$enddate,$tools,$fixedprivs,$functions,$users,$userdata,
+        $granularity,$specificity,$idx,$states,$navbuttons,$rowColor1,
+        $rowColor2) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+                                         grse => 'Group settings',
+                                         mogm => 'Modify group membership',
+                                        );
+    my @regexps = ('user_','userpriv_');
+    $r->print(&Apache::lonhtmlcommon::echo_form_input(
+                         ['origin','action','state','page','expire','delete',
+                          'changefunc','changepriv'],\@regexps));
+    my $rowimg = 1;
+    my @available = ();
+    my @unavailable = ();
+    &check_tools($functions,$tools,\@available,\@unavailable);
+    my $nexttext = $$navbuttons{'gtns'};
+    my $prevtext = $$navbuttons{'gtpp'};
+    $r->print('
 <br />
 <table width="100%" cellpadding="0" cellspacing="0" border="0">
- <tr bgcolor="$tabcol">
-  <td>&nbsp;</td>
-  <td valign="middle" align="left">
-   <nobr><img src="/res/adm/pages/bl_step6.gif" valign="middle">&nbsp;</nobr>
-  </td>
-  <th align="left"><nobr>
-    Group member privileges
-   </nobr>
-  </th>
-  <td width="100%">&nbsp;</td>
- </tr>
+');
+    &topic_bar($r,$tabcol,1,$lt{'grse'});
+    $r->print('
  <tr>
-  <td colspan="4">&nbsp;</td>
- </tr>
+  <td>&nbsp;</td>
+  <td colspan="3">
+');
+    &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,
+                            $functions,$startdate,$enddate,$groupname,
+                          $description,$granularity,\@available,\@unavailable);
+$r->print('
+</td></tr><tr><td colspan="4">&nbsp;</td></tr>');
+    &topic_bar($r,$tabcol,2,$lt{'mogm'});
+    $r->print('
  <tr>
   <td>&nbsp;</td>
   <td colspan="3">
-END
-    if ($env{'form.specificity'} eq 'Yes') {
-        $r->print('
-   <table border="0" cellspacing="2" cellpadding="2" border="0">
-    <tr>
-     <td valign="top">
 ');
-        $r->print(&Apache::lonhtmlcommon::start_pick_box());
-        $r->print(<<"END");
-   <tr bgcolor="$tabcol">
-    <th><b>Fullname</th>
-    <th><b>Username</th>
-    <th>Domain</th>
-    <th colspan="$numtools">Additional Privileges</th>
-  </tr>
-END
-    }
-    if ($env{'form.specificity'} eq 'Yes') {
-        &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,
-                             $usertools,$toolprivs,$fixedprivs,$userdata,$idx);
-    }
-    if ($env{'form.specificity'} eq 'Yes') {
-        $r->print('</td>');
-        $r->print(&Apache::lonhtmlcommon::end_pick_box());
-        $r->print('<td>&nbsp;</td>
-               <td>&nbsp;</td><td valign="top">');
-        my @toolboxes = sort(keys(%showboxes));
-        foreach my $tool (@{$tools}) {
-            if (@{$showboxes{$tool}} > 0) { 
-                $r->print('<table class="thinborder"><tr bgcolor="'.$tabcol.
-                      '"><th>'.$tool.'</th></tr>');
-                foreach my $priv (@{$showboxes{$tool}}) {
-                    $r->print(qq|
-       <tr><td>
-       <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>
-       <input type="button" value="check all"
-         onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />
-       &nbsp; 
-       <input type="button" value="uncheck all"
-        onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />
-      </nobr></fieldset></td></tr>|);
-                }
-                $r->print('</table><br /><br />');
-            }
-        }
-        $r->print('</td></tr></table>');
-    } else {
-        $r->print(&Apache::lonhtmlcommon::start_pick_box());
-        $r->print('<tr><td bgcolor="'.$tabcol.'" valign="top"><table cellspacing="0" cellpadding="1"><tr><td valign="top"><b>Function</b></td></tr><tr><td valign="top"><b>Fixed privileges</b>'.
-                  '</td></tr><tr><td valign="top"><b>Optional privileges</b></td></tr></table></td>');
-        foreach my $tool (@{$tools}) {
-            $r->print('<td align="center" valign="top"><table cellspacing="0" cellpadding="1"><tr bgcolor="#cccccc">'.
-                       '<td colspan="2" align="center"><b>'.$tool.'</b></td></tr>');
-            my $privcount = 0;
-            my $fixed = '';
-            my $dynamic = '';
-            foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
-                if (exists($$fixedprivs{$tool}{$priv})) {
-                    $fixed .= '<input type="hidden" name="allpriv_'.$priv.'" value="all" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
-                } else {
-                    $privcount ++;
-                    if ($privcount == 3) {
-                        $dynamic .= '</tr><tr bgcolor="'.$rowColor1.'">';
-                    }
-                    $dynamic .= '<td><input type="checkbox" name="allpriv_'.$priv.'" value="all" />'.$$toolprivs{$tool}{$priv}.'</td>';
-                }
-            }
-            if ($dynamic eq '') {
-                $dynamic = '<td>None</td>'; 
-            }
-            if ($privcount < 3) {
-                $dynamic .= '</tr><tr bgcolor="'.$rowColor1.'"><td colspan="2">&nbsp;</td>';
-            } elsif ($privcount%2) {
-                $dynamic = '<td>&nbsp;</td>';
+    &current_membership($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,
+                        $rowColor2,$groupname,\@available,\@unavailable,
+                        $fixedprivs,$granularity,$specificity);
+    $r->print('</td>');
+    &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
+                        $$states{$action}[$page+1],$nexttext);
+    $r->print('</table>');
+    return;
+}
+
+sub current_membership {
+    my ($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,$rowColor2,$groupname,
+        $available,$unavailable,$fixedprivs,$granularity,$specificity) = @_;
+    my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
+                                                                   $groupname);
+    my %lt = &Apache::lonlocal::texthash(
+                                          'expi' => 'Expire',
+                                          'reen' => 'Re-enable',
+                                          'acti' => 'Activate',
+                                          'dele' => 'Delete',
+                                          'curf' => 'Current Functionality',
+                                          'chfn' => 'Change Functions',
+                                          'chpr' => 'Change Privileges' 
+                                        );
+    if (keys(%membership) > 0) {
+        my %current = ();
+        my %allnames = ();
+        my $hastools = 0;
+        my $addtools = 0;
+        my $num_reenable = 0;
+        my $num_activate = 0;
+        my $num_expire - 0;
+        foreach my $key (sort(keys(%membership))) {
+            if ($key =~ /^\Q$groupname\E:([^:]+):([^:]+)$/) {
+                my $uname = $1;
+                my $udom = $2;
+                my $user = $uname.':'.$udom;
+                my($end,$start,@userprivs) = split(/:/,$membership{$key});
+                unless ($start == -1) {
+                    $allnames{$udom}{$uname} = 1;
+                    %{$current{$user}} = ();
+                    $current{$user}{uname} = $uname;
+                    $current{$user}{udom} = $udom;
+                    $current{$user}{start} = 
+                                     &Apache::lonlocal::locallocaltime($start);
+                    if ($end == 0) {
+                        $current{$user}{end} =  'No end date';
+                    } else {
+                        $current{$user}{end} = 
+                                     &Apache::lonlocal::locallocaltime($end);
+                    }
+                    my $now = time;
+                    if (($end > 0) && ($end < $now)) {
+                        $current{$user}{changestate} = 'reenable';
+                        $num_reenable++;
+                    } elsif (($start > $now)) {
+                        $current{$user}{changestate} = 'activate';
+                        $num_activate ++;
+                    } else {
+                        $current{$user}{changestate} = 'expire';
+                        $num_expire ++;
+                    }
+                    @{$current{$user}{currtools}} = ();
+                    @{$current{$user}{newtools}} = ();
+                    if (@userprivs > 0) {
+                        foreach my $tool (sort(keys(%{$fixedprivs}))) {
+                            foreach my $priv (keys(%{$$fixedprivs{$tool}})) {
+                                if (grep/^$priv$/,@userprivs) {
+                                    push(@{$current{$user}{currtools}},$tool);
+                                    last;
+                                }
+                            }
+                        }
+                        $hastools = 1;
+                    }
+                    if (@{$available} > 0) {
+                        if (@{$current{$user}{currtools}} > 0) {
+                            if ("@{$available}" ne "@{$current{$user}{currtools}}") {
+                                foreach my $tool (@{$available}) {
+                                    unless (grep/^$tool$/,@{$current{$user}{currtools}}) {
+                                        push(@{$current{$user}{newtools}},$tool);
+                                    }
+                                }
+                            }
+                        } else {
+                            @{$current{$user}{newtools}} = @{$available};
+                        }
+                        if (@{$current{$user}{newtools}} > 0) {
+                            $addtools = 1;
+                        }
+                    }
+                }
             }
-            $r->print('<tr bgcolor="'.$rowColor2.'"><td colspan="2" align="center"><nobr>'.$fixed.'</nobr></td></tr><tr bgcolor="'.$rowColor1.'">'.$dynamic.'</tr></table></td>');
         }
-        $r->print('</tr>');
-        $r->print(&Apache::lonhtmlcommon::end_pick_box());
-    }
-    $r->print('</td></tr>
+        if (keys(%current) > 0) {
+            my %idhash;
+            foreach my $udom (keys(%allnames)) {
+                %{$idhash{$udom}} = &Apache::lonnet::idrget($udom,
+                                                keys(%{$allnames{$udom}}));
+                foreach my $uname (keys(%{$idhash{$udom}})) {
+                    $current{$uname.':'.$udom}{'id'} = $idhash{$udom}{$uname};
+                }
+                foreach my $uname (keys(%{$allnames{$udom}})) {
+                    $current{$uname.':'.$udom}{'fullname'} =
+                                &Apache::loncommon::plainname($uname,$udom,
+                                                                  'lastname');
+                }
+            }
+            $r->print('
+ <tr>
+  <td>&nbsp;</td>
+  <td colspan="2">
+   <table>
+    <tr>');
+            if ($num_expire) {
+                &check_uncheck_buttons($r,$formname,'expire',$lt{'expi'});
+            }
+            if ($num_reenable) {
+                &check_uncheck_buttons($r,$formname,'reenable',$lt{'reen'});
+            }
+            if ($num_activate) {
+                &check_uncheck_buttons($r,$formname,'activate',$lt{'acti'});
+            }
+            &check_uncheck_buttons($r,$formname,'delete',$lt{'dele'});
+            if (@{$available} > 0) {
+                if ($granularity eq 'Yes') {
+                    &check_uncheck_buttons($r,$formname,'changefunc',$lt{'chfn'});
+                }
+                if ($specificity eq 'Yes') {
+                    &check_uncheck_buttons($r,$formname,'changepriv',$lt{'chpr'});
+                }
+                if ($granularity eq 'Yes') {
+                    $r->print(&check_uncheck_tools($r,$available));
+                    $r->print('
+     <td>
+      <nobr>
+       <fieldset><legend><b>'.$lt{'curf'}.'</b></legend>
+       <input type="button" value="check all"
+       onclick="javascript:checkAllTools(document.'.$formname.')" />
+       &nbsp;&nbsp;
+       <input type="button" value="uncheck all"
+        onclick="javascript:uncheckAllTools(document.'.$formname.')" />
+      </fieldset>
+     </nobr>
+    </td>
+');
+                }
+            }
+            $r->print(<<"END");
+   </tr>
+  </table>
+  </td>
+  <td width="100%">&nbsp;</td>
+ </tr>
  <tr>
   <td colspan="4">&nbsp;</td>
  </tr>
  <tr>
   <td>&nbsp;</td>
   <td colspan="3">
-   <input type="button" name="previous" value = "Go to previous page"
-    onclick="javascript:backPage(document.'.$formname.','."'pick_members'".')"/>
-   &nbsp;&nbsp;
-   <input type="button" name="next" value="Create group"
- onclick="javascript:nextPage(document.'.$formname.','."'result'".')" />
+END
+            $r->print(&Apache::lonhtmlcommon::start_pick_box());
+            $r->print(<<"END");
+   <table border="0" cellpadding="4" cellspacing="1">
+    <tr bgcolor="$tabcol" align="center">
+     <td><b>Action?</b></td>
+     <td><b><a href="javascript:changeSort('fullname')">Name</a></b></td>
+     <td><b><a href="javascript:changeSort('username')">Username</a></b>
+     </td>
+     <td><b><a href="javascript:changeSort('domain')">Domain</a></b></td>
+     <td><b><a href="javascript:changeSort('id')">ID</a></b></td>
+     <td><b><a href="javascript:changeSort('start')">Start Date</a></b></td>
+     <td><b><a href="javascript:changeSort('end')">End Date</a></b></td>
+END
+            if ($hastools) {
+                $r->print('<td><b>'.$lt{'curf'}.'</b></td>');
+            }
+            if ($addtools) {
+                $r->print('<td><b>Additional Functionality</b></td>');
+            }
+            $r->print('</tr>');
+            my %Sortby = ();
+            foreach my $user (sort(keys(%current))) {
+                if ($env{'form.sortby'} eq 'fullname') {
+                    push(@{$Sortby{$current{$user}{fullname}}},$user);
+                } elsif ($env{'form.sortby'} eq 'username') {
+                    push(@{$Sortby{$current{$user}{uname}}},$user);
+                } elsif ($env{'form.sortby'} eq 'domain') {
+                    push(@{$Sortby{$current{$user}{udom}}},$user);
+                } elsif ($env{'form.sortby'} eq 'id') {
+                    push(@{$Sortby{$current{$user}{id}}},$user);
+                } else {
+                    push(@{$Sortby{$current{$user}{fullname}}},$user);
+                }
+            }
+            my $rowNum = 0;
+            my $rowColor;
+            foreach my $key (sort(keys(%Sortby))) {
+                foreach my $user (@{$Sortby{$key}}) {
+                    if ($rowNum %2 == 1) {
+                        $rowColor = $rowColor1;
+                    } else {
+                        $rowColor = $rowColor2;
+                    }
+                    my $id = $current{$user}{id};
+                    my $fullname = $current{$user}{fullname};
+                    my $udom = $current{$user}{udom};
+                    my $uname = $current{$user}{uname};
+                    my $start = $current{$user}{start};
+                    my $end = $current{$user}{end};
+                    $r->print('<tr bgcolor="'.$rowColor.'">
+                                <td><small>');
+                    if ($current{$user}{changestate} eq 'reenable') {
+                        $r->print('<nobr>'. 
+   '<input type="checkbox" name="reenable" value="'.$user.'" />'.
+   $lt{'reen'}.'</nobr><br />');
+                    } elsif ($current{$user}{changestate} eq 'expire') {
+                        $r->print('<nobr>'.
+   '<input type="checkbox" name="expire" value="'.$user.'" />'.
+   $lt{'expi'}.'</nobr><br />');
+                    } elsif ($current{$user}{changestate} eq 'activate') {
+                        $r->print('<nobr>'.
+   '<input type="checkbox" name="activate" value="'.$user.'" />'.
+   $lt{'acti'}.'</nobr><br />');
+                    }
+                    $r->print('<nobr>'.
+   '<input type="checkbox" name="delete" value="'.$user.'" />'.
+   $lt{'dele'}.'</nobr>');
+                    if ($granularity eq 'Yes') {
+                        $r->print('<br /><nobr>'.
+   '<input type="checkbox" name="changefunc" value="'.$user.'" />'.$lt{'chfn'}.
+   '</nobr>');
+                    }
+                    if ($specificity eq 'Yes') {
+                        $r->print('<br /><nobr>'.
+   '<input type="checkbox" name="changepriv" value="'.$user.'" />'.$lt{'chpr'}.
+   '</nobr>');
+                    }
+                    $r->print('
+   </td>
+   <td><small>'.
+    $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.
+    $udom.'</small></td><td><small>'.$id.'</small></td><td><small>'.$start.
+    '</small></td><td><small>'.$end.'</small></td>');
+                    if ($hastools) {
+                        $r->print('<td align="left"><small><nobr>');
+                        foreach my $tool (@{$current{$user}{currtools}}) {
+                            if ($granularity eq 'Yes') {
+                                $r->print('<input type="checkbox" 
+                                       checked="checked"  
+                                       name="user_'.$tool.'" value="'.
+                                       $user.'" />');
+                             } else {
+                               $r->print('<input type="hidden"
+                                       checked="checked"
+                                       name="user_'.$tool.'" value="'.
+                                       $user.'" />');
+                             }
+                             $r->print($tool.'&nbsp;&nbsp;&nbsp;');
+                        }
+                        $r->print('</nobr></small></td>');
+                    }
+                    if ($addtools) {
+                        $r->print('<td align="left"><small>');
+                        if ($granularity eq 'Yes') {
+                            foreach my $tool (@{$current{$user}{newtools}}) {
+                                $r->print('<nobr><input type="checkbox"  
+                                          name="user_'.$tool.'" value="'.
+                                          $user.'" />'.$tool.
+                                                  '</nobr>&nbsp;&nbsp;&nbsp;');
+                            }
+                        } else {
+                            foreach my $tool (@{$current{$user}{newtools}}) {
+                                $r->print('<nobr><input type="hidden" 
+                                          name="user_'. $tool.'" value="'.
+                                          $user.'" />'.$tool.
+                                          '</nobr>&nbsp;&nbsp;&nbsp;');
+                            }
+                        }
+                        $r->print('</small></td>');
+                    }
+                    $r->print('</tr>'."\n");
+                    $rowNum ++;
+                }
+            }
+            $r->print(&Apache::lonhtmlcommon::end_pick_box());
+            $r->print('
   </td>
- </tr>
-    ');
+ </tr>');
+        }
+    }
+    return;
+}
+
+sub check_uncheck_buttons {
+    my ($r,$formname,$field,$title,$colspan) = @_;
     $r->print('
-</table>');
+     <td '.$colspan.'>
+      <nobr>
+       <fieldset>
+       <legend><b>'.$title.'</b></legend>
+       <input type="button" value="check all"
+       onclick="javascript:checkAll(document.'.$formname.'.'.$field.')" />
+       &nbsp;&nbsp;
+       <input type="button" value="uncheck all"
+       onclick="javascript:uncheckAll(document.'.$formname.'.'.$field.')" />
+       </fieldset>
+      </nobr>
+     </td>
+');
+}
 
+
+sub change_privs_form {
+    my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$startdate,$enddate,
+       $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,
+       $memchg,$idx,$states,$stored,$sectioncount,$navbuttons,$rowColor1,
+       $rowColor2) = @_;
+    my @regexps = ('userpriv_');
+    my $nexttext;
+                                                                                      
+    $r->print(&Apache::lonhtmlcommon::echo_form_input(
+         ['origin','action','state','page'],\@regexps));
+    $nexttext = $$navbuttons{'adme'};
+                                                                                      
+    $r->print('<br /><table width="100%" cellpadding="0" cellspacing="0" border="0">');
+    
+    &topic_bar($r,$tabcol,3,&mt('Group member privileges'));
+                                                                                      
+    &member_privileges_form($r,$tabcol,$action,$formname,$tools,$toolprivs,
+                            $fixedprivs,$userdata,$usertools,$idx,$memchg,
+                            $states,$stored,$rowColor1,$rowColor2);
+                                                                                      
+    $r->print('</td></tr><tr><td colspan="4">&nbsp;</td></tr>');
+    my $prevtext = $$navbuttons{'gtps'};
+    &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
+                        $$states{$action}[$page+1],$nexttext);
+    $r->print('</table>');
     return;
 }
 
-sub completed_creation {
-    my ($r,$cdom,$cnum,$tabcol,$formname,$groupname,$description,$userdata,
-$startdate,$enddate,$tools,$functions,$toolprivs,$members,$usertools,$idx) = @_;
+sub add_members_form {
+    my ($r,$tabcol,$action,$formname,$page,$startdate,$enddate,$groupname,
+        $description,$granularity,$sectioncount,$tools,$functions,$stored,
+        $states,$navbuttons,$rowColor1,$rowColor2) = @_; 
+    $r->print(' <br />
+<table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+  <td>&nbsp;</td>
+  <td colspan="3">
+');
+    my @available = ();
+    my @unavailable = ();
+    &check_tools($functions,$tools,\@available,\@unavailable);
+    &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,
+                            $functions,$startdate,$enddate,$groupname,
+                            $description,$granularity,\@available,\@unavailable);
+    $r->print('
+   </td>
+  </tr>
+  <tr>
+   <td colspan="4">&nbsp;</td>
+  </tr>');
+
+    &membership_options($r,$action,$formname,$tabcol,$sectioncount,1);
+    my $nexttext = $$navbuttons{'gtns'};
+    my $prevtext = $$navbuttons{'gtpp'};
+    &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
+                        $$states{$action}[$page+1],$nexttext);
+    $r->print('
+ </table>');
+    return;
+}
 
-    $r->print(&Apache::lonhtmlcommon::echo_form_input(
-                                        ['origin','action','state']));
-    my @added= ();
-    my @failed = ();
-    my $now = time;
-    my %group_privs = ();
-    my %tooltype = ();
-    foreach my $tool (@{$tools}) {
-        foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
-            $tooltype{$priv} = $tool;
-            if ($env{'form.specificity'} eq 'Yes') {
-                my @users =
-                  &Apache::loncommon::get_env_multiple('form.userpriv_'.$priv);
-                foreach my $user (@users) {
-                    $group_privs{$user} .= $priv.':';
+sub choose_privs_form {
+    my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$startdate,$enddate,
+       $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,$idx,
+       $states,$stored,$sectioncount,$navbuttons,$rowColor1,$rowColor2) = @_;
+
+    my @regexps = ('userpriv_');
+    my $nexttext;
+    
+    if ($action eq 'create') {
+        push(@regexps,'sec_');
+        $r->print(&Apache::lonhtmlcommon::echo_form_input(
+         ['origin','action','state','page','autoadd','autodrop'],
+         \@regexps));
+        $nexttext = $$navbuttons{'crgr'};
+    } else {
+        $r->print(&Apache::lonhtmlcommon::echo_form_input(
+         ['origin','action','state','page'],\@regexps));
+        $nexttext = $$navbuttons{'adme'};
+    }
+
+    $r->print('<br /><table width="100%" cellpadding="0" cellspacing="0" border="0">');
+    &topic_bar($r,$tabcol,6,&mt('Group member privileges'));
+
+    &member_privileges_form($r,$tabcol,$action,$formname,$tools,$toolprivs,
+                            $fixedprivs,$userdata,$usertools,$idx,undef,
+                            $states,$stored,$rowColor1,$rowColor2);
+
+    $r->print('</td></tr><tr><td colspan="4">&nbsp;</td></tr>');
+    if ($action eq 'create') {
+        if (keys(%{$sectioncount}) > 0) {
+            my $img1 = 7;
+            my $img2 = 8;
+            &mapping_options($r,$action,$formname,$page,$tabcol,$sectioncount,
+                             $states,$stored,$navbuttons,$img1,$img2,
+                             $rowColor1,$rowColor2);
+        }
+    }
+    my $prevtext = $$navbuttons{'gtps'};
+    &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
+                        $$states{$action}[$page+1],$nexttext);
+    $r->print('</table>');
+    return;
+}
+
+sub build_boxes {
+    my ($r,$tools,$usertools,$fixedprivs,$toolprivs,$showtools,
+        $showboxes,$prefix,$specificity) = @_;
+    my $totalboxes = 0;
+    if (@{$tools} > 0) {
+        if ($specificity eq 'Yes') {
+            foreach my $tool (@{$tools}) {
+                @{$$showboxes{$tool}} = ();
+                foreach my $user (sort(keys(%{$usertools}))) {
+                    unless (grep/^$tool$/,@{$showtools}) {
+                        push(@{$showtools},$tool);
+                    }
+                    foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
+                        unless (exists($$fixedprivs{$tool}{$priv})) {
+                            unless(grep(/^$priv$/,@{$$showboxes{$tool}})) {
+                                push(@{$$showboxes{$tool}},$priv);
+                                $totalboxes ++;
+                            }
+                        }
+                    }
                 }
-            } else {
-                if (defined($env{'form.allpriv_'.$priv})) {
-                    foreach my $user (@{$members}) {
-                        if ($$usertools{$user}{$tool}) {
-                            $group_privs{$user} .= $priv.':';
+            }
+            if ($totalboxes > 0) {
+                $r->print('
+<script type="text/javascript">
+function checkAllTools(formname) {
+');
+                foreach my $tool (sort(keys(%{$showboxes}))) {
+                    foreach my $priv (@{$$showboxes{$tool}}) {
+                        $r->print('  checkAll(formname.'.$prefix.$priv.');'."\n");
+                    }
+                }
+                $r->print('
+}
+function uncheckAllTools(formname) {
+');
+                foreach my $tool (sort(keys(%{$showboxes}))) {
+                    foreach my $priv (@{$$showboxes{$tool}}) {
+                        $r->print('  uncheckAll(formname'.$prefix.$priv.');'."\n");
+                    }
+                }
+                $r->print('
+}
+</script>
+                ');
+            }
+        }
+    }
+    return $totalboxes;
+}
+
+sub member_privileges_form {
+    my ($r,$tabcol,$action,$formname,$tools,$toolprivs,$fixedprivs,$userdata,
+        $usertools,$idx,$memchg,$states,$stored,$rowColor1,$rowColor2) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+            'addp' => 'Additional privileges',
+            'fixp' => 'Fixed privileges',
+            'oppr' => 'Optional privileges',
+            'func' => 'Function',
+            'forf' => 'For the functionality you have chosen to include '.
+                      'there are no optional privileges to set besides '.
+                      'the standard privileges.',
+            'algr' => 'All group members will receive the same privileges.',
+            'asno' => 'As no group members are being added, '.
+                      'there are no specific user privileges to set.',
+            'asng' => 'As no group tools will be made available to users, '.
+                      'there are no specific user privileges to set.',
+            'full' => 'Fullname',
+            'user' => 'Username',
+            'doma' => 'Domain',
+    );
+    my @defprivs;
+    my $specificity;
+    if ($action eq 'create') {
+        if (defined($env{'form.defpriv'})) {
+            @defprivs = &Apache::loncommon::get_env_multiple('form.defpriv');
+        }
+        $specificity = $env{'form.specificity'};
+    } else {
+        @defprivs = @{$$stored{'defpriv'}};
+        $specificity = $$stored{'specificity'};
+    }
+    my @showtools;
+    my %showboxes = ();
+    my $totalboxes = 0;
+    my $numtools = 1 + @{$tools};
+
+    $totalboxes = &build_boxes($r,$tools,$usertools,$fixedprivs,$toolprivs,
+                               \@showtools,\%showboxes,'userpriv_',
+                               $specificity);
+    if (@{$tools} > 0) {
+        if ($specificity eq 'Yes') {
+            if ($totalboxes > 0) {
+                my $numcells = 2;
+                my $colspan = $numcells + 1;
+                my %total;
+                $r->print('
+ <tr>
+  <td>&nbsp;</td>
+  <td colspan="3">
+   <table border="0" cellspacing="2" cellpadding="2" border="0">
+    <tr>
+');
+                foreach my $tool (@{$tools}) {
+                    if (@{$showboxes{$tool}} > 0) {
+                        $r->print('<td valign="top">');
+                        $r->print('<table class="thinborder"><tr bgcolor="'.$tabcol.
+                      '"><th colspan="'.$colspan.'">'.$tool.'</th></tr><tr>');
+                        my $privcount = 0;
+                        foreach my $priv (@{$showboxes{$tool}}) {
+                            $privcount ++;
+                            if (($privcount == @{$showboxes{$tool}}) && ($privcount > 1)) {
+                                if ($privcount%$numcells) {
+                                    $r->print('<td colspan="'.$colspan.'">');
+                                } else {
+                                    $r->print('<td>');
+                                }
+                            } else {
+                                $r->print('<td>');
+                            }
+                            $r->print(qq|
+       <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>
+       <nobr>
+       <input type="button" value="check all"
+         onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />
+       &nbsp;
+       <input type="button" value="uncheck all"
+        onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />
+      </nobr></fieldset><br />|);
+                            $r->print('</td>');
+                            if ($privcount < @{$showboxes{$tool}}) {
+                                if (@{$showboxes{$tool}} > 2) {
+                                    if ($privcount%$numcells == 0) {
+                                        $r->print('</tr><tr>');
+                                    }
+                                } else {
+                                    $r->print('<tr></tr>');
+                                }
+                            }
                         }
+                        $r->print('</tr></table></td><td>&nbsp;</td>');
                     }
                 }
+                $r->print('</tr></table></td></tr>');
+                $r->print('<tr><td colspan="4">&nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="3">');
+                $r->print(&Apache::lonhtmlcommon::start_pick_box());
+                $r->print(<<"END");
+   <tr bgcolor="$tabcol">
+    <th><b>$lt{'full'}</th>
+    <th><b>$lt{'user'}</th>
+    <th>$lt{'doma'}</th>
+    <th colspan="$numtools">$lt{'addp'}</th>
+  </tr>
+END
+                &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2,
+                                      $usertools,$toolprivs,$fixedprivs,
+                                      $userdata,$idx,\@showtools,\@defprivs);
+                $r->print('</td>');
+                $r->print(&Apache::lonhtmlcommon::end_pick_box());
+                $r->print('</td></tr>
+ <tr>
+  <td colspan="4">&nbsp;</td>
+ </tr>
+');
+            } else {
+                $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'forf'}.
+                          '<br />');
+                &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools,
+                            $toolprivs,\@defprivs);
+                                                                                      
+            }
+        } else {
+            if (keys(%{$usertools}) > 0) {
+                $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'algr'}.
+                          '<br /><br />');
+                &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools,
+                            $toolprivs,\@defprivs);
+            } else {
+                $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'asno'}.
+                          '<br />');
             }
         }
+    } else {
+        $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'asng'});
     }
-    foreach my $user (keys(%group_privs)) {
-        $group_privs{$user} =~ s/:$//;
+    return;
+}
+
+sub process_request {
+    my ($r,$cdom,$cnum,$tabcol,$action,$state,$page,$groupname,$description,
+        $specificity,$userdata,$startdate,$enddate,$tools,$functions,$toolprivs,
+        $usertools,$idx,$types,$roles,$sections,$states,$navbuttons,$memchg,
+        $sectioncount,$stored,$rowColor1,$rowColor2) = @_;
+
+    $r->print(&Apache::lonhtmlcommon::echo_form_input(
+                                        ['origin','action','state','page']));
+
+    my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum);
+    if ($earlyout) {
+        $r->print('
+<table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+  <td>&nbsp;</td>
+  <td colspan="3">
+'.$earlyout.'</td></tr>');
+        &display_navbuttons($r,$state,$$states{$action}[$page-1],
+                            $$navbuttons{'gtps'});
+        $r->print('</table>');
+        return;
+    }
+
+    my @defprivs = ();
+    if ($action eq 'create' || $state eq 'chgresult') { 
+        if (defined($env{'form.defpriv'})) {
+            @defprivs = &Apache::loncommon::get_env_multiple('form.defpriv');
+        }
+        if ($state eq 'chgresult') {
+            my @okprivs = ();
+            foreach my $tool (@{$tools}) {
+                foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
+                    push(@okprivs,$priv);
+                }
+            }
+            my @temp = ();
+            foreach my $defpriv (@defprivs) {
+                if (grep/^$defpriv$/,@okprivs) {
+                    push(@temp,$defpriv);
+                }
+            }
+            @defprivs = @temp; 
+        }
+    } else {
+        @defprivs = @{$$stored{'defpriv'}};
+    }
+
+    my $outcome;
+    if ($action eq 'create' || $state eq 'chgresult') {
+        $outcome = &write_group_data($r,$cdom,$cnum,$action,$state,$groupname,
+                                     $description,$startdate,$enddate,
+                                     $specificity,$functions,$tools,
+                                     $sectioncount,$roles,$types,$sections,
+                                     \@defprivs,$stored); 
+    }
+    if (($action eq 'create' && $outcome eq 'ok') || (($action eq 'modify') && 
+       (($state eq 'memresult') || ($state eq 'addresult')))) {
+        &process_membership($r,$cdom,$cnum,$groupname,$tools,$enddate,
+                            $startdate,$userdata,$idx,$toolprivs,$usertools,
+                            $specificity,\@defprivs);
+    }
+    return;
+}
+
+sub write_group_data {
+    my ($r,$cdom,$cnum,$action,$state,$groupname,$description,$startdate,
+        $enddate,$specificity,$functions,$tools,$sectioncount,$roles,$types,
+        $sections,$defprivs,$stored) = @_;
+    my $now = time;
+    my $creation = $now;
+    my $creator = $env{'user.name'}.':'.$env{'user.domain'};
+    if ($state eq 'chgresult') {
+        $creation = $$stored{'creation'};
+        $creator = $$stored{'creator'};
     }
     my $esc_description = &Apache::lonnet::escape($description);
-    my @attributes = ('description','functions','startdate','enddate','creation','modified','creator');
-        
+    my @single_attributes = ('description','functions','startdate','enddate',
+                             'creation','modified','creator','granularity',
+                             'specificity','autoadd','autodrop');
+    my @mult_attributes = ('roles','types','sectionpick','defpriv');
+                                                                                    
     my %groupinfo = (
-                      description => $esc_description,
-                      startdate => $startdate,
-                      enddate => $enddate,
-                      creation => $now,
-                      modified => $now,
-                      creator => $env{'user.name'}.':'.$env{'user.domain'}, 
-                    );
+                     description => $esc_description,
+                     startdate => $startdate,
+                     enddate => $enddate,
+                     creation => $creation,
+                     modified => $now,
+                     creator => $creator,
+                     granularity => $env{'form.granularity'},
+                     specificity => $specificity,
+                     autoadd => $env{'form.autoadd'},
+                     autodrop => $env{'form.autodrop'},
+                   );
     foreach my $func (keys(%{$functions})) {
         my $status;
         if (grep(/^$func$/,@{$tools})) {
             $status = 'on';
         } else {
             $status = 'off';
-        } 
+        }
         $groupinfo{'functions'} .=  qq|<name id="$func">$status</name>|;
     }
 
-    my %curr_groups = ();
+    $groupinfo{'roles'} = $roles;
+    $groupinfo{'types'} = $types;
+    $groupinfo{'sectionpick'} = $sections;
+    $groupinfo{'defpriv'} = $defprivs;
+
     my %groupsettings = ();
-    my %usersettings = ();
-    if (&Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum,$groupname)) {
-        if (exists($curr_groups{$groupname})) {
-            $r->print('Non-unique name - please choose another');
-            return; 
+    foreach my $item (@single_attributes) {
+        $groupsettings{$groupname} .= qq|<$item>$groupinfo{$item}</$item>|;
+    }
+    foreach my $item (@mult_attributes) {
+        foreach my $entry (@{$groupinfo{$item}}) {
+            $groupsettings{$groupname} .= qq|<$item>$entry</$item>|;
+        }
+    }
+    my $autosec;
+    my @autorole = &Apache::loncommon::get_env_multiple('form.autorole');
+                                                                                    
+    foreach my $role (@autorole) {
+        if (defined($env{'form.sec_'.$role})) {
+            my @autosections=&Apache::loncommon::get_env_multiple('form.sec_'.
+                                                                  $role);
+            if (grep/^_all$/,@autosections) {
+                @autosections = sort {$a cmp $b} keys(%{$sectioncount});
+            }
+            $autosec .= '<role id="'.$role.'">';
+            foreach my $sec (@autosections) {
+                $autosec .= '<section>'.$sec.'</section>';
+            }
+            $autosec .= '</role>';
         }
     }
-    my $groupentry;
-    foreach my $item (@attributes) {
-        $groupsettings{$groupname} .= qq|<$item>$groupinfo{$item}</$item>|;
+    if ($autosec) {
+        $groupsettings{$groupname} .= qq|<autosec>$autosec</autosec>|;
     }
     my $result = &Apache::lonnet::modify_coursegroup($cdom,$cnum,
-                                                          \%groupsettings);
+                                                     \%groupsettings);
+
     if ($result eq 'ok') {
-        my $put_result = &create_homepage($cdom,$cnum,$groupname,\%groupinfo,$tools);
-        foreach my $user (sort(@{$members})) {
-            $usersettings{$groupname.':'.$user} = $enddate.':'.$startdate.':'.$group_privs{$user};
-            if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
-                  $user,$enddate,$startdate,$group_privs{$user}) eq 'ok') {
-                push(@added,$user);
+        if ($action eq 'create') {
+            my $put_result = &create_homepage($cdom,$cnum,$groupname,
+                                              \%groupinfo,$tools);
+            $r->print('Group '.$groupname.' was created.<br />');
+        } else {
+            $r->print('Group '.$groupname.' was updated.<br />');
+        }
+    } else {
+        my %actiontype = (
+                          'create' => 'creating',
+                          'modify' => 'modifying',
+                         );
+        &Apache::lonnet::logthis('Failed to store group '.$groupname.
+                                 'in course: '.$cnum.' in domain: '.$cdom);
+        $r->print(&mt('An error occurred when [_1] the new group. '.
+                      'Please try again.',$actiontype{$action}));
+    }
+    return $result;
+}
+
+sub process_membership {
+    my ($r,$cdom,$cnum,$groupname,$tools,$enddate,$startdate,$userdata,$idx,
+        $toolprivs,$usertools,$specificity,$defprivs) = @_;
+    my %usersettings = ();
+    my @added= ();
+    my @failed = ();
+    my %group_privs = ();
+    my %tooltype = ();
+
+    foreach my $tool (@{$tools}) {
+        foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
+            $tooltype{$priv} = $tool;
+            if ($specificity eq 'Yes') {
+                my @users =
+                  &Apache::loncommon::get_env_multiple('form.userpriv_'.$priv);
+                foreach my $user (@users) {
+                    $group_privs{$user} .= $priv.':';
+                }
             } else {
-                push(@failed,$user);
+                if (@{$defprivs} > 0) {
+                    foreach my $priv (@{$defprivs}) {
+                        foreach my $user (sort(keys(%{$usertools}))) {
+                            if ($$usertools{$user}{$tool}) {
+                                $group_privs{$user} .= $priv.':';
+                            }
+                        }
+                    }
+                }
             }
         }
-        my $roster_result = &Apache::lonnet::modify_coursegroup_membership(
-             $cdom,$cnum,\%usersettings);
-        $r->print('
-Group '.$groupname.' was created.<br />');
-        if (@added > 0) {
-            $r->print('Users were added with following privileges:<br />');
-            foreach my $user (@added) {
-                my @privs = split(/:/,$group_privs{$user});
-                my $privlist= '';
-                my $curr_tool = '';
-                foreach my $priv (@privs) {
-                    unless ($curr_tool eq $tooltype{$priv}) {
-                        $curr_tool = $tooltype{$priv};
-                        $privlist .= '<b>'.$curr_tool.'</b>: ';
-                    }
-                    $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';
-                }
-                $privlist =~ s/, $//;
-                $r->print($$userdata{$user}[$$idx{fullname}].'&nbsp;-&nbsp;'.$user.': '.$privlist.'<br />');
-            }
-        }
-        if (@failed > 0) {
-            $r->print('Addition of the following users was unsuccessful:<br />');
-            foreach my $user (@failed) {
-                $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');
+    }
+    foreach my $user (keys(%group_privs)) {
+        $group_privs{$user} =~ s/:$//;
+    }
+
+    foreach my $user (sort(keys(%{$usertools}))) {
+        $usersettings{$groupname.':'.$user} = $enddate.':'.$startdate.':'.
+                                              $group_privs{$user};
+        if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
+                                                $user,$enddate,$startdate,
+                                                $group_privs{$user}) eq 'ok') {
+            push(@added,$user);
+        } else {
+            push(@failed,$user);
+        }
+    }
+    my $roster_result = &Apache::lonnet::modify_coursegroup_membership($cdom,
+                                                       $cnum,\%usersettings);
+    if (@added > 0) {
+        $r->print('Users were added with following privileges:<br />');
+        foreach my $user (@added) {
+            my @privs = split(/:/,$group_privs{$user});
+            my $privlist= '';
+            my $curr_tool = '';
+            foreach my $priv (@privs) {
+                unless ($curr_tool eq $tooltype{$priv}) {
+                    $curr_tool = $tooltype{$priv};
+                    $privlist .= '<b>'.$curr_tool.'</b>: ';
+                }
+                $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';
             }
+            $privlist =~ s/, $//;
+            $r->print($$userdata{$user}[$$idx{fullname}].'&nbsp;-&nbsp;'.$user.': '.$privlist.'<br />');
         }
-        if ($roster_result eq 'ok') {
-            $r->print('<br />Group membership list updated.');
-        } else {
-            $r->print('<br />An error occurred while updating the group membership list -'.$roster_result.'<br />');
-        } 
+    }
+    if (@failed > 0) {
+        $r->print('Addition of the following users was unsuccessful:<br />');
+        foreach my $user (@failed) {
+            $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');
+        }
+    }
+    if ($roster_result eq 'ok') {
+        $r->print('<br />Group membership list updated.');
     } else {
-        &Apache::lonnet::logthis('Failed to create group '.$groupname. 
-                                 'in course: '.$cnum.' in domain: '.$cdom);
+        $r->print('<br />An error occurred while updating the group membership list -'.$roster_result.'<br />');
+    }
+    return;
+}
 
-        $r->print('An error occurred when creating the new group. '.
-                                                      'Please try again.');
+sub mapping_options {
+    my ($r,$action,$formname,$page,$tabcol,$sectioncount,$states,$stored,
+        $navbuttons,$img1,$img2,$rowColor1,$rowColor2) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+        'auto' => 'Settings for automatic group enrollment',
+        'gmma' => 'Group membership mapping to specific sections/roles',
+        'endi' => 'Enable/disable automatic group enrollment for '.
+                          'users in specified roles and sections',
+        'adds'  => 'If automatic group enrollment is enabled, when a user is assigned a course-wide or section-specific role, he/she will automatically be added as a member of the group, with start and end access dates defined by the default dates set for the group, unless he/she is already a group member, with access dates that permit either current or future group access.',
+        'drops'  => "If automatic group disenrollment is enabled, when a user's role is expired, access to the group will be terminated unless the user continues to have other course-wide or section-specific active or future roles which receive automatic membership in the group.",
+        'pirs' => 'Pick roles and sections for automatic group enrollment',
+        'curr' => 'Currently set to',
+        'on' => 'on',
+        'off' => 'off',
+        'auad' => 'Automatically enable group membership when roles are added?',
+        'auex' => 'Automatically expire group membership when roles are removed?',
+        'mapr' => 'Mapping of roles and sections affected by automatic group enrollment/disenrollment follows scheme chosen below.',
+    );
+    &automapping($r,$action,$tabcol,$stored,\%lt,$img1);
+    $r->print('
+   <tr>
+    <td colspan="4">&nbsp;</td>
+   </tr>');
+    &mapping_settings($r,$tabcol,$rowColor1,$rowColor2,$sectioncount,\%lt,
+                                                       $stored,$img2);
+    return;
+}
+
+sub automapping {
+    my ($r,$action,$tabcol,$stored,$lt,$image) = @_;
+    my $add = 'off';
+    my $drop = 'off';
+    if (exists($$stored{'autoadd'})) {
+        $add = $$stored{'autoadd'};
     }
+    if (exists($$stored{'autodrop'})) {
+        $drop = $$stored{'autodrop'};
+    }
+    &topic_bar($r,$tabcol,$image,$$lt{'endi'});
+    $r->print('
+  <tr>
+   <td>&nbsp;</td>
+   <td colspan="3">
+    <b>'.$$lt{'gmma'}.':</b><br />'.$$lt{'adds'}.'<br />'.$$lt{'drops'}.'<br />
+   </td>
+  </tr>
+  <tr>
+   <td colspan="4">&nbsp;</td>
+  </tr>
+  <tr>
+   <td>&nbsp;</td>
+   <td colspan="3">
+   <nobr>'.$$lt{'auad'}.':&nbsp;
+    <input type="radio" name="autoadd" value="on" />on&nbsp;&nbsp;<input type="radio" name="autoadd" value="off" />off');
+    if ($action eq 'modify') {
+        $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$add}.'</b>)');
+    }
+    $r->print('
+    </nobr>
+   </td>
+  </tr>
+  <tr>
+   <td>&nbsp;</td>
+   <td colspan="3">
+    <nobr>'.$$lt{'auex'}.':&nbsp;
+    <input type="radio" name="autodrop" value="on" />on&nbsp;&nbsp;<input type="radio" name="autodrop" value="off" />off');
+    if ($action eq 'modify') {
+        $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$drop}.'</b>)');
+    }
+    $r->print('</nobr>
+   </td>
+  </tr>
+  <tr>
+   <td colspan="4">&nbsp;</td>
+  </tr>
+  <tr>
+   <td>&nbsp;</td>
+   <td colspan="3">'.$$lt{'mapr'}.'
+   </td>
+  </tr>
+');
+}
+
+sub mapping_settings {
+    my ($r,$tabcol,$rowColor1,$rowColor2,$sectioncount,$lt,$stored,$image) = @_;
+    my @sections = keys(%{$sectioncount});
+    if (@sections > 0) {
+        @sections = sort {$a cmp $b} @sections;
+        unshift(@sections,'_nosec'); # Put 'no sections' next
+        unshift(@sections,'_all'); # Put 'all' at the front of the list
+    }
+    &topic_bar($r,$tabcol,$image,$$lt{'pirs'});
+    $r->print('
+   <tr>
+    <td>&nbsp;</td>
+    <td colspan="3">
+');
+    my @roles = &standard_roles();
+    my %customroles = &my_custom_roles();
+    $r->print(&Apache::lonhtmlcommon::start_pick_box());
+    $r->print('
+                <tr bgcolor="'.$tabcol.'">
+                 <th>'.&mt('Active?').'</th>
+                 <th>'.&mt('Role').'</th>');
+    if (@sections > 0) {
+        $r->print('<th>'.&mt('Sections').'</th></tr>'."\n");
+    }
+    my $rowNum = 0;
+    my $rowColor;
+    foreach my $role (@roles) {
+        my $plrole=&Apache::lonnet::plaintext($role);
+        my $sections_sel;
+        if (@sections > 0) {
+            $sections_sel='<td>'.&sections_selection(\@sections,'sec_'.$role).
+                                                                       '</td>';
+        }
+        if ($rowNum %2 == 1) {
+            $rowColor = $rowColor1;
+        } else {
+            $rowColor = $rowColor2;
+        }
+        $r->print('<tr bgcolor="'.$rowColor.'"><td><input type="checkbox" '.
+                  'name="autorole" value="'.$role.'"></td><td>'.$plrole.
+                  '</td>'.$sections_sel.'</tr>');
+        $rowNum ++;
+    }
+    foreach my $role (sort(keys(%customroles))) {
+        my $sections_sel;
+        if (@sections > 0) {
+            $sections_sel = '<td>'.&sections_selection(\@sections,'sec_'.$role).
+                                                                        '</td>';
+        }
+        if ($rowNum %2 == 1) {
+            $rowColor = $rowColor1;
+        } else {
+            $rowColor = $rowColor2;
+        }
+        $r->print('<tr bgcolor="'.$rowColor.'"><td><input type="checkbox" '.
+                  'value="'.$role.'"></td><td>'.$role.'</td>'.
+                  $sections_sel.'</tr>');
+        $rowNum ++;
+    }
+    $r->print(&Apache::lonhtmlcommon::end_pick_box());
+    return;
+}
+
+sub standard_roles {
+    my @roles = ('st','ep','ta','in','cc');
+    return @roles;
+}
+
+sub my_custom_roles {
+    my %returnhash=();
+    my %rolehash=&Apache::lonnet::dump('roles');
+    foreach (keys %rolehash) {
+        if ($_=~/^rolesdef\_(\w+)$/) {
+            $returnhash{$1}=$1;
+        }
+    }
+    return %returnhash;
+}
+
+sub modify_menu {
+    my ($r,$groupname,$page) = @_;
+    my @menu =
+        (
+          { text => 'Modify default group settings',
+            help => 'Course_Modify_Group',
+            state => 'change_settings',
+            branch => 'settings',
+            },
+          { text => 'Modify access, tools and/or privileges for previous,future'.
+                    'or current members',
+            help => 'Course_Modify_Group_Membership',
+            state => 'change_members',
+            branch => 'members',
+            },
+          { text => 'Add member(s) to the group',
+            help => 'Course_Group_Add_Members',
+            state => 'add_members',
+            branch => 'adds',
+            },
+          );
+    my $menu_html = '';
+    foreach my $menu_item (@menu) {
+        $menu_html .=
+        '<p><font size="+1"><a href="/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state='.$menu_item->{'state'}.'&branch='.$menu_item->{'branch'}.'">';
+        $menu_html.= &mt($menu_item->{'text'}).'</a></font>';
+        if (exists($menu_item->{'help'})) {
+            $menu_html.=
+                &Apache::loncommon::help_open_topic($menu_item->{'help'});
+        }
+        $menu_html.='</p>'.$/;
+    }
+    $r->print($menu_html);
     return;
 }
 
 sub member_privs_entries {
-    my ($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,$usertools,$toolprivs,
-                                              $fixedprivs,$userdata,$idx) = @_;
+    my ($r,$tabcol,$rowColor1,$rowColor2,$usertools,$toolprivs,
+        $fixedprivs,$userdata,$idx,$showtools,$defprivs) = @_;
     my $rowColor;
     my $rowNum = 0;
-    foreach my $member (@{$members}) {
-        my ($uname,$udom) = split(/:/,$member);
+    foreach my $user (sort(keys(%{$usertools}))) {
+        my ($uname,$udom) = split(/:/,$user);
         if ($rowNum %2 == 1) {
             $rowColor = $rowColor1;
         } else {
             $rowColor = $rowColor2;
         }
         $r->print('<tr bgcolor="'.$rowColor.'">
-                <td>'.$$userdata{$member}[$$idx{fullname}].'</td>
+                <td>'.$$userdata{$user}[$$idx{fullname}].'</td>
                 <td>'.$uname.'</td>
                 <td>'.$udom.'</td>
                 <td valign="top"><table><tr><td><b>Function</b></td></tr><tr><td><b>Fixed</b></td></tr><tr><td><b>Optional</b></td></tr></table></td>');
-        foreach my $tool (@{$tools}) {
-            if (exists($$usertools{$member}{$tool})) {
+        foreach my $tool (@{$showtools}) {
+            if (exists($$usertools{$user}{$tool})) {
                 $r->print('<td valign="top"><table><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></tr>');
                 my $privcount = 0;
                 my $fixed = '';
                 my $dynamic = '';
                 foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                     if (exists($$fixedprivs{$tool}{$priv})) {
-                        $fixed .= '<input type="hidden" name="userpriv_'.$priv.'" value="'.$member.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
+                        $fixed .= '<input type="hidden" name="userpriv_'.$priv.'" value="'.$user.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
                     } else {
                         $privcount ++;
                         if ($privcount == 3) {
                             $dynamic .= '</tr><tr>';
                         }
-                        $dynamic .= '<td><input type="checkbox" name="userpriv_'.$priv.'" value="'.$member.'" />'.$$toolprivs{$tool}{$priv}.'</td>';
+                        $dynamic .='<td><nobr><input type="checkbox" '.
+                               'name="userpriv_'.$priv.'" value="'.$user.'"';
+                        if (grep/^\Q$priv\E$/,@{$defprivs}) {
+                            $dynamic .= ' checked="checked" ';
+                        }
+                        $dynamic .= ' />'.$$toolprivs{$tool}{$priv}.
+                                    '</nobr></td>';
                     }
                 }
                 $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>');
             } else {
-                $r->print('<td>&nbsp;</td>');
+                $r->print('<td valign="top"><table width="100%"><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></tr><tr><td>&nbsp;</td></tr><tr><td>&nbsp;</td></tr></table></td>');
             }
         }
         $rowNum ++;
     }
 }
 
-
 sub get_dates_from_form {
     my $startdate;
     my $enddate;
@@ -1507,7 +2955,8 @@
         $enddate = 0;
     }
     return ($startdate,$enddate);
-}                                                                                     
+}
+
 sub date_setting_table {
     my ($starttime,$endtime,$formname) = @_;
     my $startform = &Apache::lonhtmlcommon::date_setter($formname,
@@ -1553,5 +3002,147 @@
    return $putresult;
 }
 
+sub check_uncheck_tools {
+    my ($r,$available) = @_;
+    if (ref($available) eq 'ARRAY') { 
+        $r->print('
+<script type="text/javascript">
+function checkAllTools(formname) {
+');
+        foreach my $tool (@{$available}) {
+            $r->print('  checkAll(formname.user_'.$tool.');'."\n");
+        }
+        $r->print(' checkAll(formname.togglefunc);'."\n");
+        $r->print('
+}
+function uncheckAllTools(formname) {
+');
+        foreach my $tool (@{$available}) {
+            $r->print('  uncheckAll(formname.user_'.$tool.');'."\n");
+        }
+        $r->print(' uncheckAll(formname.togglefunc);'."\n");
+        $r->print('
+}
+function toggleTools(field,caller) {
+     if (caller.checked) {
+         checkAll(field);
+     } else {
+         uncheckAll(field);
+     }
+     return;   
+}
+</script>
+');
+    }
+    return;
+}
+
+sub validate_groupname {
+    my ($groupname,$action,$cdom,$cnum) = @_;
+    my %sectioncount;
+    my $numsec=&Apache::loncommon::get_sections($cdom,$cnum,\%sectioncount);
+    my %curr_groups;
+    my $numgroups=&Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum);
+                                                                                         
+    my %lt = &Apache::lonlocal::texthash (
+                      igna => 'Invalid group name',
+                      tgne => 'The group name entered ',
+                      grna => 'Group names and section names used in a course '.
+                              'must be unique.',
+                      isno => 'is not a valid name.',
+                      gnmo => 'Group names may only contain letters, numbers '.
+                              'or underscores.',
+                      cnnb => 'can not be used as it is the name of ',
+                      inth => ' in this course.',
+                      thgr => '- does not correspond to the name of an existing'.  
+                              ' group ',    
+    );
+                                                                                         
+    my $exitmsg = '<b>'.$lt{'igna'}.'</b><br /><br />'.$lt{'tgne'}.' "'.
+                  $groupname.'" ';
+    my $dupmsg = $lt{'grna'};
+    my $earlyout;
+    if (($groupname eq '') || ($groupname =~ /\W/)) {
+        $earlyout = $exitmsg.$lt{'isno'}.'<br />'.$lt{'gnmo'};
+        return $earlyout;
+    }
+    if ($numsec) {
+        if (exists($sectioncount{$groupname})) {
+            $earlyout = $exitmsg.$lt{'cnnb'}.&mt('a section').$lt{'inth'}.
+                        '<br />'.$lt{'grna'};
+            return $earlyout;
+        }
+    }
+    if ($action eq 'create') {
+        if ($numgroups) {
+            if (exists($curr_groups{$groupname})) {
+                $earlyout = $exitmsg.$lt{'cnnb'}.&mt('an existing group').
+                            $lt{'inth'}.'<br />'.$lt{'grna'};
+                return $earlyout;
+            }
+        }
+    } elsif ($action eq 'modify') {
+        unless(exists($curr_groups{$groupname})) {
+            $earlyout = &mt('Group name:').' '.$groupname.$lt{'thgr'}.$lt{'inth'};
+            return $earlyout;
+        }
+    }
+    return;
+}
+
+sub topic_bar {
+    my ($r,$tabcol,$imgnum,$title) = @_;
+    $r->print('
+ <tr bgcolor="'.$tabcol.'">
+  <td>&nbsp;</td>
+  <td valign="middle" align="left">
+   <nobr>
+    <img src="/res/adm/pages/bl_step'.$imgnum.'.gif" valign="middle">&nbsp;
+   </nobr>
+  </td>
+  <th align="left"><nobr>'.$title.'<nobr>
+  </th>
+  <td width="100%">&nbsp;</td>
+ </tr>
+ <tr>
+  <td colspan="4">&nbsp;</td>
+ </tr>
+');
+    return;
+}
+
+sub check_changes {
+    my ($member_changes,$memchg) = @_;
+    my %exclusions;
+    @{$exclusions{'changefunc'}} = ('expire');
+    @{$exclusions{'changepriv'}} = ('expire','changefunc');
+
+    foreach my $change (@{$member_changes}) {
+        if ($change eq 'delete') {
+            next;
+        }
+        my @checks = ('delete');
+        if (exists($exclusions{$change})) {
+            push(@checks,@{$exclusions{$change}});
+        }
+        my @temp = ();
+        foreach my $item (@{$$memchg{$change}}) {
+            my $match = 0;
+            foreach my $check (@checks) {
+                if (@{$$memchg{$check}} > 0) {
+                    if (grep/^$item$/,@{$$memchg{$check}}) {
+                        $match = 1;
+                        last;
+                    }
+                }
+            }
+            if ($match) {
+                next;
+            }
+            push(@temp,$item);
+        }
+        @{$$memchg{$change}} = @temp;
+    }
+}
 
 1;
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.302 loncom/interface/loncommon.pm:1.303
--- loncom/interface/loncommon.pm:1.302	Mon Jan  9 15:38:52 2006
+++ loncom/interface/loncommon.pm	Fri Feb 17 20:27:07 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.302 2006/01/09 20:38:52 albertel Exp $
+# $Id: loncommon.pm,v 1.303 2006/02/18 01:27:07 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -3170,7 +3170,7 @@
 Outer hash key is functions.
 Inner hash keys are chat,discussion,email,files,homepage,roster.
 Corresponding values are either on or off, depending on
-whther this type of functionality is available for the group.
+whether this type of functionality is available for the group.
 
 =cut
                                                                                  
@@ -3181,13 +3181,18 @@
     my $parser=HTML::TokeParser->new(\$groupinfo);
     my $token;
     my $tool = '';
+    my $role = '';
     my %content=();
     while ($token=$parser->get_token) {
         if ($token->[0] eq 'S')  {
             my $entry=$token->[1];
-            if ($entry eq 'functions') {
+            if ($entry eq 'functions' || $entry eq 'autosec') {
                 %{$content{$entry}} = ();
                 $tool = $entry;
+            } elsif ($entry eq 'role') {
+                if ($tool eq 'autosec') {
+                    $role = $token->[2]{id};
+                }
             } else {
                 my $value=$parser->get_text('/'.$entry);
                 if ($entry eq 'name') {
@@ -3197,14 +3202,24 @@
                     }
                 } elsif ($entry eq 'groupname') {
                     $content{$entry}=&Apache::lonnet::unescape($value);
+                } elsif (($entry eq 'roles') || ($entry eq 'types') ||
+                         ($entry eq 'sectionpick') || ($entry eq 'defpriv')) {
+                    push(@{$content{$entry}},$value);
+                } elsif ($entry eq 'section') {
+                    if ($tool eq 'autosec'  && $role ne '') {
+                        push(@{$content{$tool}{$role}},$value);
+                    }
                 } else {
                     $content{$entry}=$value;
                 }
             }
         } elsif ($token->[0] eq 'E') {
-            if ($token->[1] eq 'functions') {
+            if ($token->[1] eq 'functions' || $token->[1] eq 'autosec') {
                 $tool = '';
+            } elsif ($token->[1] eq 'role') {
+                $role = '';
             }
+
         }
     }
     return %content;

--raeburn1140226032--