--- loncom/interface/lonpreferences.pm	2002/08/19 13:10:55	1.9
+++ loncom/interface/lonpreferences.pm	2005/01/20 21:32:55	1.52
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Preferences
 #
-# $Id: lonpreferences.pm,v 1.9 2002/08/19 13:10:55 matthew Exp $
+# $Id: lonpreferences.pm,v 1.52 2005/01/20 21:32:55 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -25,18 +25,6 @@
 #
 # http://www.lon-capa.org/
 #
-# (Internal Server Error Handler
-#
-# (Login Screen
-# 5/21/99,5/22,5/25,5/26,5/31,6/2,6/10,7/12,7/14,
-# 1/14/00,5/29,5/30,6/1,6/29,7/1,11/9 Gerd Kortemeyer)
-#
-# 3/1/1 Gerd Kortemeyer)
-#
-# 3/1 Gerd Kortemeyer
-#
-# 2/13/02 2/14 2/15 Matthew Hall
-#
 # This package uses the "londes.js" javascript code. 
 #
 # TODOs that have to be completed:
@@ -50,6 +38,8 @@ use Apache::File;
 use Crypt::DES;
 use DynaLoader; # for Crypt::DES version
 use Apache::loncommon();
+use Apache::lonhtmlcommon();
+use Apache::lonlocal;
 
 #
 # Write lonnet::passwd to do the call below.
@@ -61,7 +51,7 @@ use Apache::loncommon();
 ##################################################
 sub des_keys {
     # Make a new key for DES encryption.
-    # Each key has two parts which are returned seperately.
+    # Each key has two parts which are returned separately.
     # Please note:  Each key must be passed through the &hex function
     # before it is output to the web browser.  The hex versions cannot
     # be used to decrypt.
@@ -100,30 +90,191 @@ sub des_decrypt {
 ################################################################
 
 ################################################################
+#         Language Change Subroutines                          #
+################################################################
+
+sub wysiwygchanger {
+    my $r = shift;
+    my %userenv = &Apache::lonnet::get
+        ('environment',['wysiwygeditor']);
+    my $offselect='';
+    my $onselect='checked="1"';
+    if ($userenv{'wysiwygeditor'}) {
+	$onselect='';
+	$offselect='checked="1"';
+    }
+    my $switchoff=&mt('Disable WYSIWYG editor');
+    my $switchon=&mt('Enable WYSIWYG editor');
+    $r->print(<<ENDLSCREEN);
+<form name="server" action="/adm/preferences" method="post">
+<input type="hidden" name="action" value="set_wysiwyg" />
+<br />
+<input type="radio" name="wysiwyg" value="off" $onselect /> $switchoff<br />
+<input type="radio" name="wysiwyg" value="on" $offselect /> $switchon
+ENDLSCREEN
+    $r->print('<br /><input type="submit" value="'.&mt('Change').'" />');
+}
+
+
+sub verify_and_change_wysiwyg {
+    my $r = shift;
+    my $newsetting=$ENV{'form.wysiwyg'};
+    &Apache::lonnet::put('environment',{'wysiwygeditor' => $newsetting});
+    &Apache::lonnet::appenv('environment.wysiwygeditor' => $newsetting);
+    $r->print('<p>'.&mt('Setting WYSIWYG editor to:').' '.&mt($newsetting).'</p>');
+}
+
+################################################################
+#         Language Change Subroutines                          #
+################################################################
+sub languagechanger {
+    my $r = shift;
+    my $user       = $ENV{'user.name'};
+    my $domain     = $ENV{'user.domain'};
+    my %userenv = &Apache::lonnet::get
+        ('environment',['languages']);
+    my $language=$userenv{'languages'};
+
+    my $pref=&mt('Preferred language');
+    my %langchoices=('' => 'No language preference');
+    foreach (&Apache::loncommon::languageids()) {
+	if (&Apache::loncommon::supportedlanguagecode($_)) {
+	    $langchoices{&Apache::loncommon::supportedlanguagecode($_)}
+	               = &Apache::loncommon::plainlanguagedescription($_);
+	}
+    }
+    my $selectionbox=&Apache::loncommon::select_form($language,'language',
+						     %langchoices);
+    $r->print(<<ENDLSCREEN);
+<form name="server" action="/adm/preferences" method="post">
+<input type="hidden" name="action" value="verify_and_change_languages" />
+<br />$pref: $selectionbox
+ENDLSCREEN
+    $r->print('<br /><input type="submit" value="'.&mt('Change').'" />');
+}
+
+
+sub verify_and_change_languages {
+    my $r = shift;
+    my $user       = $ENV{'user.name'};
+    my $domain     = $ENV{'user.domain'};
+# Screenname
+    my $newlanguage  = $ENV{'form.language'};
+    $newlanguage=~s/[^\-\w]//g;
+    my $message='';
+    if ($newlanguage) {
+        &Apache::lonnet::put('environment',{'languages' => $newlanguage});
+        &Apache::lonnet::appenv('environment.languages' => $newlanguage);
+        $message='Set new preferred languages to '.$newlanguage;
+    } else {
+        &Apache::lonnet::del('environment',['languages']);
+        &Apache::lonnet::delenv('environment\.languages');
+        $message='Reset preferred language';
+    }
+    $r->print(<<ENDVCSCREEN);
+</p>
+$message
+ENDVCSCREEN
+}
+
+################################################################
+#         Roles Page Preference Change Subroutines         #
+################################################################
+sub rolesprefchanger {
+    my $r = shift;
+    my $user       = $ENV{'user.name'};
+    my $domain     = $ENV{'user.domain'};
+    my %userenv = &Apache::lonnet::get
+        ('environment',['recentroles','recentrolesn']);
+    my $hotlist_flag=$userenv{'recentroles'};
+    my $hotlist_n=$userenv{'recentrolesn'};
+    my $checked;
+    if ($hotlist_flag) {
+	$checked = 'checked="checked"';
+    }
+    
+    if (!$hotlist_n) { $hotlist_n=3; }
+    my $options;
+    for (my $i=1; $i<10; $i++) {
+	my $select;
+	if ($hotlist_n == $i) { $select = 'selected="selected"'; }
+	$options .= "<option $select>$i</option>\n";
+    }
+
+    $r->print(<<ENDSCREEN);
+<p>Some LON-CAPA users have a long list of roles. The Recent Roles Hotlist
+feature keeps track of the last N roles which have been
+visited and places a table of these at the top of the roles page.
+People with very few roles should leave this feature disabled.
+</p>
+
+<form name="server" action="/adm/preferences" method="post">
+<input type="hidden" name="action" value="verify_and_change_rolespref" />
+<br />Enable Recent Roles Hotlist:
+<input type="checkbox" $checked name="recentroles" value="true" />
+<br />Number of roles in Hotlist:
+<select name="recentrolesn" size="1">
+$options
+</select>
+<br />
+<input type="submit" value="Change" />
+</form>
+ENDSCREEN
+}
+
+sub verify_and_change_rolespref {
+    my $r = shift;
+    my $user       = $ENV{'user.name'};
+    my $domain     = $ENV{'user.domain'};
+# Recent Roles Hotlist Flag
+    my $hotlist_flag  = $ENV{'form.recentroles'};
+    my $hotlist_n  = $ENV{'form.recentrolesn'};
+    my $message='';
+    if ($hotlist_flag) {
+        &Apache::lonnet::put('environment',{'recentroles' => $hotlist_flag});
+        &Apache::lonnet::appenv('environment.recentroles' => $hotlist_flag);
+        $message='Recent Roles Hotlist is Enabled';
+    } else {
+        &Apache::lonnet::del('environment',['recentroles']);
+        &Apache::lonnet::delenv('environment\.recentroles');
+        $message='Recent Roles Hotlist is Disabled';
+    }
+    if ($hotlist_n) {
+        &Apache::lonnet::put('environment',{'recentrolesn' => $hotlist_n});
+        &Apache::lonnet::appenv('environment.recentrolesn' => $hotlist_n);
+        if ($hotlist_flag) {
+            $message.="<br />Display $hotlist_n Most Recent Roles\n";
+        }
+    }
+
+    $r->print(<<ENDRPSCREEN);
+</p>
+$message
+ENDRPSCREEN
+}
+
+
+
+################################################################
 #         Anonymous Discussion Name Change Subroutines         #
 ################################################################
 sub screennamechanger {
     my $r = shift;
     my $user       = $ENV{'user.name'};
     my $domain     = $ENV{'user.domain'};
-    my %userenv = &Apache::lonnet::get('environment',['screenname']);
+    my %userenv = &Apache::lonnet::get
+        ('environment',['screenname','nickname']);
     my $screenname=$userenv{'screenname'};
+    my $nickname=$userenv{'nickname'};
     $r->print(<<ENDSCREEN);
-<html>
-<body bgcolor="#FFFFFF">
-<h1>Preferences for $user</h1>
-<h3>$user is a member of domain $domain</h3>
-<p>
-Change anonymous discussion screen name for $user
-</p>
 <form name="server" action="/adm/preferences" method="post">
 <input type="hidden" name="action" value="verify_and_change_screenname" />
-New screenname:
+<br />New screenname (shown if you post anonymously):
 <input type="text" size="20" value="$screenname" name="screenname" />
+<br />New nickname (shown if you post non-anonymously):
+<input type="text" size="20" value="$nickname" name="nickname" />
 <input type="submit" value="Change" />
 </form>
-</body>
-</html>
 ENDSCREEN
 }
 
@@ -131,8 +282,9 @@ sub verify_and_change_screenname {
     my $r = shift;
     my $user       = $ENV{'user.name'};
     my $domain     = $ENV{'user.domain'};
+# Screenname
     my $newscreen  = $ENV{'form.screenname'};
-    $newscreen=~s/\W//g;
+    $newscreen=~s/[^ \w]//g;
     my $message='';
     if ($newscreen) {
         &Apache::lonnet::put('environment',{'screenname' => $newscreen});
@@ -143,19 +295,242 @@ sub verify_and_change_screenname {
         &Apache::lonnet::delenv('environment\.screenname');
         $message='Reset screenname';
     }
+# Nickname
+    $message.='<br />';
+    $newscreen  = $ENV{'form.nickname'};
+    $newscreen=~s/[^ \w]//g;
+    if ($newscreen) {
+        &Apache::lonnet::put('environment',{'nickname' => $newscreen});
+        &Apache::lonnet::appenv('environment.nickname' => $newscreen);
+        $message.='Set new nickname to '.$newscreen;
+    } else {
+        &Apache::lonnet::del('environment',['nickname']);
+        &Apache::lonnet::delenv('environment\.nickname');
+        $message.='Reset nickname';
+    }
+
     $r->print(<<ENDVCSCREEN);
-<html>
-<body bgcolor="#FFFFFF">
-<h1>Preferences for $user</h1>
-<h3>$user is a member of domain $domain</h3>
-<p>
-Change anonymous discussion screen name for $user
 </p>
 $message
-</body></html>
 ENDVCSCREEN
 }
 
+################################################################
+#         Message Forward                                      #
+################################################################
+
+sub msgforwardchanger {
+    my $r = shift;
+    my $user       = $ENV{'user.name'};
+    my $domain     = $ENV{'user.domain'};
+    my %userenv = &Apache::lonnet::get('environment',['msgforward','notification','critnotification']);
+    my $msgforward=$userenv{'msgforward'};
+    my $notification=$userenv{'notification'};
+    my $critnotification=$userenv{'critnotification'};
+    my $forwardingHelp = Apache::loncommon::help_open_topic("Prefs_Forwarding",
+							    "What are forwarding ".
+							    "and notification ".
+							    "addresses");
+    my $criticalMessageHelp = Apache::loncommon::help_open_topic("Course_Critical_Message",
+								 "What are critical messages");
+
+    $r->print(<<ENDMSG);
+$forwardingHelp <br />
+<form name="server" action="/adm/preferences" method="post">
+<input type="hidden" name="action" value="verify_and_change_msgforward" />
+New Forwarding Address(es) (<tt>user:domain,user:domain,...</tt>):
+<input type="text" size="40" value="$msgforward" name="msgforward" /><hr />
+New Message Notification Email Address(es) (<tt>joe\@doe.com,jane\@doe.edu,...</tt>):
+<input type="text" size="40" value="$notification" name="notification" /><hr />
+New Critical Message Notification Email Address(es) (<tt>joe\@doe.com,jane\@doe.edu,...</tt>):
+<input type="text" size="40" value="$critnotification" name="critnotification" />$criticalMessageHelp<hr />
+<input type="submit" value="Change" />
+</form>
+ENDMSG
+}
+
+sub verify_and_change_msgforward {
+    my $r = shift;
+    my $user       = $ENV{'user.name'};
+    my $domain     = $ENV{'user.domain'};
+    my $newscreen  = '';
+    my $message='';
+    foreach (split(/\,/,$ENV{'form.msgforward'})) {
+	my ($msuser,$msdomain)=split(/[\@\:]/,$_);
+        $msuser=~s/\W//g;
+        $msdomain=~s/\W//g;
+        if (($msuser) && ($msdomain)) {
+	    if (&Apache::lonnet::homeserver($msuser,$msdomain) ne 'no_host') {
+               $newscreen.=$msuser.':'.$msdomain.',';
+	   } else {
+               $message.='No such user: '.$msuser.':'.$msdomain.'<br>';
+           }
+        }
+    }
+    $newscreen=~s/\,$//;
+    if ($newscreen) {
+        &Apache::lonnet::put('environment',{'msgforward' => $newscreen});
+        &Apache::lonnet::appenv('environment.msgforward' => $newscreen);
+        $message.='Set new message forwarding to '.$newscreen.'<br />';
+    } else {
+        &Apache::lonnet::del('environment',['msgforward']);
+        &Apache::lonnet::delenv('environment\.msgforward');
+        $message.='Reset message forwarding<br />';
+    }
+    my $notification=$ENV{'form.notification'};
+    $notification=~s/\s//gs;
+    if ($notification) {
+        &Apache::lonnet::put('environment',{'notification' => $notification});
+        &Apache::lonnet::appenv('environment.notification' => $notification);
+        $message.='Set message notification address to '.$notification.'<br />';
+    } else {
+        &Apache::lonnet::del('environment',['notification']);
+        &Apache::lonnet::delenv('environment\.notification');
+        $message.='Reset message notification<br />';
+    }
+    my $critnotification=$ENV{'form.critnotification'};
+    $critnotification=~s/\s//gs;
+    if ($critnotification) {
+        &Apache::lonnet::put('environment',{'critnotification' => $critnotification});
+        &Apache::lonnet::appenv('environment.critnotification' => $critnotification);
+        $message.='Set critical message notification address to '.$critnotification;
+    } else {
+        &Apache::lonnet::del('environment',['critnotification']);
+        &Apache::lonnet::delenv('environment\.critnotification');
+        $message.='Reset critical message notification<br />';
+    }
+    $r->print(<<ENDVCMSG);
+</p>
+$message
+ENDVCMSG
+}
+
+################################################################
+#         Colors                                               #
+################################################################
+
+sub colorschanger {
+    my $r = shift;
+# figure out colors
+    my $function='student';
+    if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {
+	$function='coordinator';
+    }
+    if ($ENV{'request.role'}=~/^(su|dc|ad|li)/) {
+	$function='admin';
+    }
+    if (($ENV{'request.role'}=~/^(au|ca)/) ||
+	($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {
+	$function='author';
+    }
+    my $domain=&Apache::loncommon::determinedomain();
+    my %colortypes=('pgbg'  => 'Page Background',
+                    'tabbg' => 'Header Background',
+                    'sidebg'=> 'Header Border',
+                    'font'  => 'Font',
+                    'link'  => 'Un-Visited Link',
+                    'vlink' => 'Visited Link',
+                    'alink' => 'Active Link');
+    my $chtable='';
+    foreach my $item (sort(keys(%colortypes))) {
+       my $curcol=&Apache::loncommon::designparm($function.'.'.$item,$domain);
+       $chtable.='<tr><td>'.$colortypes{$item}.'</td><td bgcolor="'.$curcol.
+        '">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td><td><input name="'.$item.
+        '" size="10" value="'.$curcol.
+'" /></td><td><a href="javascript:pjump('."'color_custom','".$colortypes{$item}.
+"','".$curcol."','"
+	    .$item."','parmform.pres','psub'".');">Select</a></td></tr>';
+    }
+    my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
+    $r->print(<<ENDCOL);
+<script>
+
+    function pclose() {
+        parmwin=window.open("/adm/rat/empty.html","LONCAPAparms",
+                 "height=350,width=350,scrollbars=no,menubar=no");
+        parmwin.close();
+    }
+
+    $pjump_def
+
+    function psub() {
+        pclose();
+        if (document.parmform.pres_marker.value!='') {
+            if (document.parmform.pres_type.value!='') {
+                eval('document.server.'+
+                     document.parmform.pres_marker.value+
+		     '.value=document.parmform.pres_value.value;');
+	    }
+        } else {
+            document.parmform.pres_value.value='';
+            document.parmform.pres_marker.value='';
+        }
+    }
+
+
+</script>
+<form name="parmform">
+<input type="hidden" name="pres_marker" />
+<input type="hidden" name="pres_type" />
+<input type="hidden" name="pres_value" />
+</form>
+<form name="server" action="/adm/preferences" method="post">
+<input type="hidden" name="action" value="verify_and_change_colors" />
+<table border="2">
+$chtable
+</table>
+<input type="submit" value="Change Custom Colors" />
+<input type="submit" name="resetall" value="Reset All Colors to Default" />
+</form>
+ENDCOL
+}
+
+sub verify_and_change_colors {
+    my $r = shift;
+# figure out colors
+    my $function='student';
+    if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {
+	$function='coordinator';
+    }
+    if ($ENV{'request.role'}=~/^(su|dc|ad|li)/) {
+	$function='admin';
+    }
+    if (($ENV{'request.role'}=~/^(au|ca)/) ||
+	($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {
+	$function='author';
+    }
+    my $domain=&Apache::loncommon::determinedomain();
+    my %colortypes=('pgbg'  => 'Page Background',
+                    'tabbg' => 'Header Background',
+                    'sidebg'=> 'Header Border',
+                    'font'  => 'Font',
+                    'link'  => 'Un-Visited Link',
+                    'vlink' => 'Visited Link',
+                    'alink' => 'Active Link');
+
+    my $message='';
+    foreach my $item (keys %colortypes) {
+        my $color=$ENV{'form.'.$item};
+        my $entry='color.'.$function.'.'.$item;
+	if (($color=~/^\#[0-9A-Fa-f]{6}$/) && (!$ENV{'form.resetall'})) {
+	    &Apache::lonnet::put('environment',{$entry => $color});
+	    &Apache::lonnet::appenv('environment.'.$entry => $color);
+	    $message.='Set '.$colortypes{$item}.' to '.$color.'<br />';
+	} else {
+	    &Apache::lonnet::del('environment',[$entry]);
+	    &Apache::lonnet::delenv('environment\.'.$entry);
+	    $message.='Reset '.$colortypes{$item}.'<br />';
+	}
+    }
+    $r->print(<<ENDVCCOL);
+</p>
+$message
+<form name="client" action="/adm/preferences" method="post">
+<input type="hidden" name="action" value="changecolors" />
+</form>
+ENDVCCOL
+}
+
 ######################################################
 #            password handler subroutines            #
 ######################################################
@@ -199,9 +574,6 @@ sub passwordchanger {
 	$r->print(<$jsh>);
     }
     $r->print(<<ENDFORM);
-</head>
-<body bgcolor="#FFFFFF" onLoad="init();">
-
 <script language="JavaScript">
 
     function send() {
@@ -209,37 +581,33 @@ sub passwordchanger {
         lextkey=this.document.client.elements.lkey_cpass.value;
         initkeys();
 
-        this.document.server.elements.currentpass.value
+        this.document.pserver.elements.currentpass.value
             =crypted(this.document.client.elements.currentpass.value);
 
         uextkey=this.document.client.elements.ukey_npass1.value;
         lextkey=this.document.client.elements.lkey_npass1.value;
         initkeys();
-        this.document.server.elements.newpass_1.value
+        this.document.pserver.elements.newpass_1.value
             =crypted(this.document.client.elements.newpass_1.value);
 
         uextkey=this.document.client.elements.ukey_npass2.value;
         lextkey=this.document.client.elements.lkey_npass2.value;
         initkeys();
-        this.document.server.elements.newpass_2.value
+        this.document.pserver.elements.newpass_2.value
             =crypted(this.document.client.elements.newpass_2.value);
 
-        this.document.server.submit();
+        this.document.pserver.submit();
     }
 
 </script>
-<h1>Preferences for $user</h1>
-<h3>$user is a member of domain $domain</h3>
 $errormessage
+
 <p>
-Change password for $user
-</p>
-<p>
-<!-- We seperate the forms into 'server' and 'client' in order to
+<!-- We separate the forms into 'server' and 'client' in order to
      ensure that unencrypted passwords will not be sent out by a
      crappy browser -->
 
-<form name="server" action="/adm/preferences" method="post">
+<form name="pserver" action="/adm/preferences" method="post">
 <input type="hidden" name="logtoken"    value="$logtoken" />
 <input type="hidden" name="action"      value="verify_and_change_pass" />
 <input type="hidden" name="currentpass" value="" />
@@ -315,9 +683,9 @@ ENDERROR
     }
     my ($ckey,$n1key,$n2key)=split(/&/,$tmpinfo);
     # 
-    my $currentpass = &des_decrypt($ckey ,$currentpass);
-    my $newpass1    = &des_decrypt($n1key,$newpass1);
-    my $newpass2    = &des_decrypt($n2key,$newpass2);
+    $currentpass = &des_decrypt($ckey ,$currentpass);
+    $newpass1    = &des_decrypt($n1key,$newpass1);
+    $newpass2    = &des_decrypt($n2key,$newpass2);
     # 
     if ($newpass1 ne $newpass2) {
 	&passwordchanger($r,
@@ -370,6 +738,149 @@ ENDERROR
     return;
 }
 
+################################################################
+#            discussion display subroutines 
+################################################################
+sub discussionchanger {
+    my $r = shift;
+    my $user       = $ENV{'user.name'};
+    my $domain     = $ENV{'user.domain'};
+    my %userenv = &Apache::lonnet::get
+        ('environment',['discdisplay','discmarkread']);
+    my $discdisp = 'allposts';
+    my $discmark = 'onmark';
+
+    if (defined($userenv{'discdisplay'})) {
+        unless ($userenv{'discdisplay'} eq '') { 
+            $discdisp = $userenv{'discdisplay'};
+        }
+    }
+    if (defined($userenv{'discmarkread'})) {
+        unless ($userenv{'discdisplay'} eq '') { 
+            $discmark = $userenv{'discmarkread'};
+        }
+    }
+
+    my $newdisp = 'unread';
+    my $newmark = 'ondisp';
+
+    my $function = &Apache::loncommon::get_users_function();
+    my $color = &Apache::loncommon::designparm($function.'.tabbg',
+                                                    $ENV{'user.domain'});
+    my %lt = &Apache::lonlocal::texthash(
+        'pref' => 'Display Preference',
+        'curr' => 'Current setting ',
+        'actn' => 'Action',
+        'sdpf' => 'Set display preferences for discussion posts for both bulletin boards and individual resources in all your courses.',
+        'prca' => 'Preferences can be set that determine',
+        'whpo' => 'Which posts are displayed when you display a bulletin board or resource, and',
+        'unwh' => 'Under what circumstances posts are identfied as "New"',
+        'allposts' => 'All posts',
+        'unread' => 'New posts only',
+        'ondisp' => 'Once displayed',
+        'onmark' => 'Once marked as read',
+        'disa' => 'Posts displayed?',
+        'npmr' => 'New posts cease to be identified as "New"?',
+        'thde'  => 'The preferences you set here can be overridden within each individual discussion.',
+        'chgt' => 'Change to '
+    );
+    my $dispchange = $lt{'unread'};
+    my $markchange = $lt{'ondisp'};
+    my $currdisp = $lt{'allposts'};
+    my $currmark = $lt{'onmark'};
+
+    if ($discdisp eq 'unread') {
+        $dispchange = $lt{'allposts'};
+        $currdisp = $lt{'unread'};
+        $newdisp = 'allposts';
+    }
+
+    if ($discmark eq 'ondisp') {
+        $markchange = $lt{'onmark'};
+        $currmark = $lt{'ondisp'};
+        $newmark = 'onmark';
+    }
+    
+    $r->print(<<"END");
+<form name="server" action="/adm/preferences" method="post">
+<input type="hidden" name="action" value="verify_and_change_discussion" />
+<br />
+$lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$lt{'whpo'}</li><li>$lt{'unwh'}</li></ol> 
+<br />
+<br />
+<table border="0" cellpadding="0" cellspacing="0">
+ <tr>
+  <td width="100%" bgcolor="#000000">
+   <table width="100%" border="0" cellpadding="1" cellspacing="0">
+    <tr>
+     <td width="100%" bgcolor="#000000">
+      <table border="0" cellpadding="3" cellspacing="3" bgcolor="#FFFFFF">
+       <tr bgcolor="$color">
+        <td><b>$lt{'pref'}</b></td>
+        <td><b>$lt{'curr'}</b></td>
+        <td><b>$lt{'actn'}?</b></td>
+       </tr>
+       <tr bgcolor="#dddddd">
+       <td>$lt{'disa'}</td>
+       <td>$lt{$discdisp}</td>
+       <td><input type="checkbox" name="discdisp" /><input type="hidden" name="newdisp" value="$newdisp" />&nbsp;$lt{'chgt'} "$dispchange"</td>
+      </tr><tr bgcolor="#eeeeee">
+       <td>$lt{'npmr'}</td>
+       <td>$lt{$discmark}</td>
+       <td><input type="checkbox" name="discmark" /><input type="hidden" name="newmark" value="$newmark" />&nbsp;$lt{'chgt'} "$markchange"</td>
+      </tr>
+     </table>
+    </td>
+   </tr>
+  </table>
+ </td>
+</tr>
+</table>
+<br />
+<br />
+<input type="submit" name="sub" value="Store Changes" />
+<br />
+<br />
+Note: $lt{'thde'}
+</form>
+END
+}
+                                                                                                                
+sub verify_and_change_discussion {
+    my $r = shift;
+    my $user     = $ENV{'user.name'};
+    my $domain   = $ENV{'user.domain'};
+    my $message='';
+    if (defined($ENV{'form.discdisp'}) ) {
+        my $newdisp  = $ENV{'form.newdisp'};
+        if ($newdisp eq 'unread') {
+            $message .='In discussions: only new posts will be displayed.<br/>';
+            &Apache::lonnet::put('environment',{'discdisplay' => $newdisp});
+            &Apache::lonnet::appenv('environment.discdisplay' => $newdisp);
+        } else {
+            $message .= 'In discussions: all posts will be displayed.<br/>';
+            &Apache::lonnet::del('environment',['discdisplay']);
+            &Apache::lonnet::delenv('environment\.discdisplay');
+        }
+    }
+    if (defined($ENV{'form.discmark'}) ) {
+        my $newmark = $ENV{'form.newmark'};
+        if ($newmark eq 'ondisp') {
+           $message.='In discussions: new posts will be cease to be identified as "new" after display.<br/>';
+            &Apache::lonnet::put('environment',{'discmarkread' => $newmark});
+            &Apache::lonnet::appenv('environment.discmarkread' => $newmark);
+        } else {
+            $message.='In discussions: posts will be identified as "new" until marked as read by the reader.<br/>';
+            &Apache::lonnet::del('environment',['discmarkread']);
+            &Apache::lonnet::delenv('environment\.discmarkread');
+        }
+    }
+    $r->print(<<ENDVCSCREEN);
+</p>
+$message
+ENDVCSCREEN
+}
+
 ######################################################
 #            other handler subroutines               #
 ######################################################
@@ -381,55 +892,251 @@ sub handler {
     my $r = shift;
     my $user = $ENV{'user.name'};
     my $domain = $ENV{'user.domain'};
-    $r->content_type('text/html');
+    &Apache::loncommon::content_type($r,'text/html');
     # Some pages contain DES keys and should not be cached.
     &Apache::loncommon::no_cache($r);
     $r->send_http_header;
     return OK if $r->header_only;
     #
-    if ($ENV{'form.action'} eq 'changepass') {
-	&passwordchanger($r);
-    } elsif ($ENV{'form.action'} eq 'verify_and_change_pass') {
-	&verify_and_change_password($r);
-    } elsif ($ENV{'form.action'} eq 'changescreenname') {
-        &screennamechanger($r);
-    } elsif ($ENV{'form.action'} eq 'verify_and_change_screenname') {
-        &verify_and_change_screenname($r);
-    } else {
-	$r->print(<<ENDHEADER);
+    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+                                            ['action','wysiwyg','returnurl']);
+    #
+    &Apache::lonhtmlcommon::clear_breadcrumbs();
+    &Apache::lonhtmlcommon::add_breadcrumb
+        ({href => '/adm/preferences',
+          text => 'Set User Preferences'});
+
+    my @Options;
+    # Determine current authentication method
+    my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
+    if ($currentauth =~ /^(unix|internal):/) {
+        push (@Options,({ action   => 'changepass',
+                          linktext => 'Change Password',
+                          href     => '/adm/preferences',
+                          help     => 'Change_Password',
+                          subroutine => \&passwordchanger,
+                          breadcrumb => 
+                              { href => '/adm/preferences?action=changepass',
+                                text => 'Change Password'},
+                          },
+                        { action => 'verify_and_change_pass',
+                          subroutine => \&verify_and_change_password,
+                          breadcrumb => 
+                              { href =>'/adm/preferences?action=changepass',
+                                text => 'Change Password'},
+                          printmenu => 'yes',
+                          }));
+    }
+    push (@Options,({ action   => 'changescreenname',
+                      linktext => 'Change Screen Name',
+                      href     => '/adm/preferences',
+                      help     => 'Prefs_Screen_Name_Nickname',
+                      subroutine => \&screennamechanger,
+                      breadcrumb => 
+                          { href => '/adm/preferences?action=changescreenname',
+                            text => 'Change Screen Name'},
+                      },
+                    { action   => 'verify_and_change_screenname',
+                      subroutine => \&verify_and_change_screenname,
+                      breadcrumb => 
+                          { href => '/adm/preferences?action=changescreenname',
+                            text => 'Change Screen Name'},
+                      printmenu => 'yes',
+                      }));
+
+    push (@Options,({ action   => 'changemsgforward',
+                      linktext => 'Change Message Forwarding and Notification Addresses',
+                      href     => '/adm/preferences',
+                      help     => 'Prefs_Forwarding',
+                      breadcrumb => 
+                          { href => '/adm/preferences?action=changemsgforward',
+                            text => 'Change Message Forwarding'},
+                      subroutine => \&msgforwardchanger,
+                      },
+                    { action => 'verify_and_change_msgforward',
+                      breadcrumb => 
+                          { href => '/adm/preferences?action=changemsgforward',
+                            text => 'Change Message Forwarding'},
+                      printmenu => 'yes',
+                      subroutine => \&verify_and_change_msgforward }));
+    my $aboutmeaction=
+        '/adm/'.$ENV{'user.domain'}.'/'.$ENV{'user.name'}.'/aboutme';
+    push (@Options,{ action => 'none', 
+                     linktext =>
+                         q{Edit the 'About Me' Personal Information Screen},
+		     help => 'Prefs_About_Me',
+                     href => $aboutmeaction});
+    push (@Options,({ action => 'changecolors',
+                      linktext => 'Change Color Scheme',
+                      href => '/adm/preferences',
+                      help => 'Change_Colors',
+                      breadcrumb => 
+                          { href => '/adm/preferences?action=changecolors',
+                            text => 'Change Colors'},
+                      subroutine => \&colorschanger,
+                  },
+                    { action => 'verify_and_change_colors',
+                      breadcrumb => 
+                          { href => '/adm/preferences?action=changecolors',
+                            text => 'Change Colors'},
+                      printmenu => 'yes',
+                      subroutine => \&verify_and_change_colors,
+                      }));
+    push (@Options,({ action => 'changelanguages',
+                      linktext => 'Change Language Preferences',
+                      href => '/adm/preferences',
+		      help => 'Prefs_Language',
+                      breadcrumb=>
+                          { href => '/adm/preferences?action=changelanguages',
+                            text => 'Change Language'},
+                      subroutine =>  \&languagechanger,
+                  },
+                    { action => 'verify_and_change_languages',
+                      breadcrumb=>
+                          {href => '/adm/preferences?action=changelanguages',
+                           text => 'Change Language'},
+                      printmenu => 'yes',
+                      subroutine=>\&verify_and_change_languages, }
+                    ));
+    push (@Options,({ action => 'changewysiwyg',
+                      linktext => 'Change WYSIWYG Editor Preferences',
+                      href => '/adm/preferences',
+                      breadcrumb => 
+                            { href => '/adm/preferences?action=changewysiwyg',
+                              text => 'Change WYSIWYG Preferences'},
+                      subroutine => \&wysiwygchanger,
+                  },
+                    { action => 'set_wysiwyg',
+                      breadcrumb =>
+                          { href => '/adm/preferences?action=changewysiwyg',
+                            text => 'Change WYSIWYG Preferences'},
+                      printmenu => 'yes',
+                      subroutine => \&verify_and_change_wysiwyg, }
+                    ));
+    push (@Options,({ action => 'changediscussions',
+                      linktext => 'Change Discussion Display Preferences',
+                      href => '/adm/preferences',
+                      help => 'Change_Discussion_Display',
+                      breadcrumb => 
+                            { href => '/adm/preferences?action=changediscussions',
+                              text => 'Change Discussion Preferences'},
+                      subroutine => \&discussionchanger,
+                  },
+                    { action => 'verify_and_change_discussion',
+                      breadcrumb =>
+                          { href => '/adm/preferences?action=changediscussions',
+                            text => 'Change Discussion Preferences'},
+                      printmenu => 'yes',
+                      subroutine => \&verify_and_change_discussion, }
+                    ));
+                       
+    push (@Options,({ action   => 'changerolespref',
+                      linktext => 'Change Roles Page Preferences',
+                      href     => '/adm/preferences',
+                      subroutine => \&rolesprefchanger,
+                      breadcrumb =>
+                          { href => '/adm/preferences?action=changerolespref',
+                            text => 'Change Roles Pref'},
+                      },
+                    { action   => 'verify_and_change_rolespref',
+                      subroutine => \&verify_and_change_rolespref,
+                      breadcrumb =>
+                          { href => '/adm/preferences?action=changerolespref',
+                            text => 'Change Roles Preferences'},
+                      printmenu => 'yes',
+                      }));
+
+
+    if ($ENV{'user.name'} =~ /^(albertel|fox|foxr|koretemey|korte|hallmat3|turtle)$/) {
+        push (@Options,({ action => 'debugtoggle',
+                          printmenu => 'yes',
+                          subroutine => \&toggle_debug,
+                          }));
+    }
+    $r->print(<<ENDHEADER);
 <html>
 <head>
 <title>LON-CAPA Preferences</title>
 </head>
-<body bgcolor="#FFFFFF" >
-<h1>Preferences for $user</h1>
-<h3>$user is a member of domain $domain</h3>
 ENDHEADER
-	# Determine current authentication method
-	my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
-	if ($currentauth =~ /^(unix|internal):/) {
-	    $r->print(<<ENDPASSWORDFORM);
-<form name="client" action="/adm/preferences" method="post">
-<input type="hidden" name="action" value="changepass">
-<input type="submit" value="Change password">
-</form>
-ENDPASSWORDFORM
-# Change screen name
-	    $r->print(<<ENDSCREENNAMEFORM);
-<form name="client" action="/adm/preferences" method="post">
-<input type="hidden" name="action" value="changescreenname">
-<input type="submit" value="Change anonymous discussion screen name">
-</form>
-ENDSCREENNAMEFORM
-            # Other preference setting code should be added here
-	}
+    my $call = undef;
+    my $help = undef;
+    my $printmenu = 'yes';
+    foreach my $option (@Options) {
+        if ($option->{'action'} eq $ENV{'form.action'}) {
+            $call = $option->{'subroutine'};
+            $printmenu = $option->{'printmenu'};
+            if (exists($option->{'breadcrumb'})) {
+                &Apache::lonhtmlcommon::add_breadcrumb
+                    ($option->{'breadcrumb'});
+            }
+	    $help=$option->{'help'};
+        }
+    }
+    $r->print(&Apache::loncommon::bodytag('Change Preferences'));
+    $r->print(&Apache::lonhtmlcommon::breadcrumbs
+              (undef,'Change Preferences',$help));
+    if (defined($call)) {
+        $call->($r);
+    }
+    if (($printmenu eq 'yes') && (!$ENV{'form.returnurl'})) {
+        my $optionlist = '<table cellpadding="5">';
+        if ($ENV{'user.name'} =~ 
+                         /^(albertel|kortemey|fox|foxr|korte|hallmat3|turtle)$/
+            ) {
+            push (@Options,({ action => 'debugtoggle',
+                              linktext => 'Toggle Debug Messages',
+                              text => 'Current Debug status is -'.
+                                  $ENV{'user.debug'}.'-.',
+                              href => '/adm/preferences',
+                              printmenu => 'yes',
+                              subroutine => \&toggle_debug,
+                              }));
+        }
+        foreach my $option(@Options) {
+            my $optiontext = '';
+            if (exists($option->{'href'})) {
+                $optiontext .= 
+                    '<a href="'.$option->{'href'}.
+                    '?action='.$option->{'action'}.'">'.
+                    &mt($option->{'linktext'}).'</a>';
+            }
+            if (exists($option->{'text'})) {
+                $optiontext .= ' '.&mt($option->{'text'});
+            }
+            if ($optiontext ne '') {
+                $optiontext = '<font size="+1">'.$optiontext.'</font>'; 
+                my $helplink = '&nbsp;';
+                if (exists($option->{'help'})) {
+                    $helplink = &Apache::loncommon::help_open_topic
+                                                    ($option->{'help'});
+                }
+                $optionlist .= '<tr>'.
+                    '<td>'.$helplink.'</td>'.
+                    '<td>'.$optiontext.'</td>'.
+                    '</tr>';
+            }
+        }
+        $optionlist .= '</table>';
+        $r->print($optionlist);
+    } elsif ($ENV{'form.returnurl'}) {
+	$r->print('<br /><a href="'.$ENV{'form.returnurl'}.'"><font size="+1">'.
+		  &mt('Return').'</font></a>');
     }
     $r->print(<<ENDFOOTER);
 </body>
 </html>
 ENDFOOTER
     return OK;
-} 
+}
+
+sub toggle_debug {
+    if ($ENV{'user.debug'}) {
+        &Apache::lonnet::delenv('user\.debug');
+    } else {
+        &Apache::lonnet::appenv('user.debug' => 1);
+    }
+}
 
 1;
 __END__