Index: bug_update_advanced_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update_advanced_page.php,v
retrieving revision 1.74
diff -u -r1.74 bug_update_advanced_page.php
--- bug_update_advanced_page.php	2 Aug 2004 18:16:20 -0000	1.74
+++ bug_update_advanced_page.php	3 Aug 2004 13:16:16 -0000
@@ -220,9 +220,7 @@
 		<?php echo lang_get( 'status' ) ?>
 	</td>
 	<td bgcolor="<?php echo get_status_color( $t_bug->status ) ?>">
-		<select name="status">
-			<?php print_enum_string_option_list_workflow( 'status', $t_bug->status ) ?>
-		</select>
+		<?php print_status_option_list( 'status', $t_bug->status ) ?>
 	</td>
 
 	<?php
Index: bug_update_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update_page.php,v
retrieving revision 1.78
diff -u -r1.78 bug_update_page.php
--- bug_update_page.php	2 Aug 2004 18:16:20 -0000	1.78
+++ bug_update_page.php	3 Aug 2004 13:16:39 -0000
@@ -218,9 +218,7 @@
 		<?php echo lang_get( 'status' ) ?>
 	</td>
 	<td bgcolor="<?php echo get_status_color( $t_bug->status ) ?>">
-		<select name="status">
-			<?php print_enum_string_option_list_workflow( 'status', $t_bug->status ) ?>
-		</select>
+		<?php print_status_option_list( 'status', $t_bug->status ) ?>
 	</td>
 
 	<?php
Index: config_defaults_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/config_defaults_inc.php,v
retrieving revision 1.188
diff -u -r1.188 config_defaults_inc.php
--- config_defaults_inc.php	1 Aug 2004 22:24:58 -0000	1.188
+++ config_defaults_inc.php	3 Aug 2004 13:07:48 -0000
@@ -735,17 +735,9 @@
 	# access level needed to report a bug
 	$g_report_bug_threshold			= REPORTER;
 
-	# access level needed to update bugs
+	# access level needed to update bugs (i.e., the update_bug_page)
 	$g_update_bug_threshold			= UPDATER;
 
-	# access level needed to re-open bugs
-	# Look in the constant_inc.php file if you want to set a different value
-	$g_reopen_bug_threshold			= DEVELOPER;
-
-	# access level needed to close bugs
-	# Look in the constant_inc.php file if you want to set a different value
-	$g_close_bug_threshold			= DEVELOPER;
-
 	# access level needed to monitor bugs
 	# Look in the constant_inc.php file if you want to set a different value
 	$g_monitor_bug_threshold		= REPORTER;
@@ -858,6 +850,14 @@
 	# threshold for viewing changelog
 	$g_view_changelog_threshold = VIEWER;
 
+	# status change thresholds
+	$g_update_bug_status_threshold = DEVELOPER;
+
+	# this array sets the access thresholds needed to enter each status listed.
+	# if a status is not listed, it falls back to $g_update_bug_status_threshold
+	# example: $g_set_status_threshold = array( ACKNOWLEDGED => MANAGER, CONFIRMED => DEVELOPER, CLOSED => MANAGER );
+	$g_set_status_threshold = array();
+	
 	# --- login method ----------------
 	# CRYPT or PLAIN or MD5 or LDAP or BASIC_AUTH
 	# You can simply change this at will. Mantis will try to figure out how the passwords were encrypted.
@@ -1284,4 +1284,4 @@
 	# Enable support for bug relationships where a bug can be a related, dependent on, or duplicate of another.
 	# See relationship_api.php for more details.
 	$g_enable_relationship = ON;
-?>
\ No newline at end of file
+?>
Index: core/access_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/access_api.php,v
retrieving revision 1.30
diff -u -r1.30 access_api.php
--- core/access_api.php	27 Jul 2004 14:24:57 -0000	1.30
+++ core/access_api.php	3 Aug 2004 13:01:27 -0000
@@ -128,17 +128,11 @@
 	#===================================
 
 	# --------------------
-	# Check the current user's access against the given value and return true
-	#  if the user's access is equal to or higher, false otherwise.
+	# Get the current user's access
 	#
 	# This function only checks the user's global access level, ignoring any
 	#  overrides they might have at a project level
-	function access_has_global_level( $p_access_level, $p_user_id = null ) {
-		# Short circuit the check in this case
-		if ( NOBODY == $p_access_level ) {
-			return false;
-		}
-
+	function access_get_global_level( $p_user_id = null ) {
 		if ( $p_user_id === null ) {
 		    $p_user_id = auth_get_current_user_id();
 		}
@@ -150,7 +144,24 @@
 			return false;
 		}
 
-		$t_access_level = user_get_field( $p_user_id, 'access_level' );
+		return user_get_field( $p_user_id, 'access_level' );
+	}
+
+	# --------------------
+	# Check the current user's access against the given value and return true
+	#  if the user's access is equal to or higher, false otherwise.
+	#
+	function access_has_global_level( $p_access_level, $p_user_id = null ) {
+		# Short circuit the check in this case
+		if ( NOBODY == $p_access_level ) {
+			return false;
+		}
+
+		if ( $p_user_id === null ) {
+		    $p_user_id = auth_get_current_user_id();
+		}
+
+		$t_access_level = access_get_global_level( $p_user_id );
 
 		return ( $t_access_level >= $p_access_level );
 	}
@@ -165,23 +176,17 @@
 	}
 
 	# --------------------
-	# Check the current user's access against the given value and return true
-	#  if the user's access is equal to or higher, false otherwise.
+	# Get the current user's access level
 	#
 	# This function checks the project access level first (for the current project
 	#  if none is specified) and if the user is not listed, it falls back on the
 	#  user's global access level.
-	function access_has_project_level( $p_access_level, $p_project_id = null, $p_user_id = null ) {
-		# Short circuit the check in this case
-		if ( NOBODY == $p_access_level ) {
-			return false;
-		}
-
+	function access_get_project_level( $p_project_id = null, $p_user_id = null ) {
 		# Deal with not logged in silently in this case
 		# @@@ we may be able to remove this and just error
 		#     and once we default to anon login, we can remove it for sure
 		if ( !auth_is_user_authenticated() ) {
-			return false;
+			return ANYBODY;
 		}
 
 		if ( null === $p_user_id ) {
@@ -193,11 +198,11 @@
 		}
 
 		if ( ALL_PROJECTS == $p_project_id ) {
-			return access_has_global_level( $p_access_level, $p_user_id );
+			$t_access_level = access_get_global_level( $p_user_id );
+		} else {
+			$t_access_level = access_get_local_level( $p_user_id, $p_project_id );
 		}
 
-		$t_access_level = access_get_local_level( $p_user_id, $p_project_id );
-
 		# Try to use the project access level.
 		# If the user is not listed in the project, then try to fall back
 		#  to the global access level
@@ -213,6 +218,28 @@
 			}
 		}
 
+		return $t_access_level;
+	}
+
+	# --------------------
+	# Check the current user's access against the given value and return true
+	#  if the user's access is equal to or higher, false otherwise.
+	#
+	function access_has_project_level( $p_access_level, $p_project_id = null, $p_user_id = null ) {
+		# Short circuit the check in this case
+		if ( NOBODY == $p_access_level ) {
+			return false;
+		}
+
+		if ( null === $p_user_id ) {
+		    $p_user_id = auth_get_current_user_id();
+		}
+		if ( null === $p_project_id ) {
+			$p_project_id = helper_get_current_project();
+		}
+
+		$t_access_level = access_get_project_level( $p_project_id, $p_user_id );
+
 		return ( $t_access_level >= $p_access_level );
 	}
 
@@ -310,7 +337,7 @@
 			return true;
 		}
 
-		return access_has_bug_level( config_get( 'close_bug_threshold' ), $p_bug_id, $p_user_id );
+		return access_has_bug_level( access_get_status_threshold( CLOSED ), $p_bug_id, $p_user_id );
 	}
 
 	# --------------------
@@ -352,6 +379,8 @@
 	# Data Access
 	#===================================
 
+	# get the user's access level specific to this project. 
+	# return false (0) if the user has no access override here
 	function access_get_local_level( $p_user_id, $p_project_id ) {
 		$p_project_id = (int)$p_project_id; # 000001 is different from 1.
 
@@ -363,4 +392,17 @@
 			return false;
 		}
 	}
-?>
\ No newline at end of file
+
+	# --------------------
+	# get the access level required to change the issue to the new status
+	#  If there is no specific differentiated access level, use the 
+	#  generic update_bug_status_threshold
+	function access_get_status_threshold( $p_status, $p_project_id = ALL_PROJECTS ) {
+		$t_thresh_array = config_get( 'set_status_threshold' );
+		if ( isset( $t_thresh_array[ $p_status ] ) ) {
+			return $t_thresh_array[$p_status];
+		} else {
+			return config_get( 'update_bug_status_threshold' );
+		}
+	}
+?>
Index: core/error_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/error_api.php,v
retrieving revision 1.31
diff -u -r1.31 error_api.php
--- core/error_api.php	1 Aug 2004 12:51:38 -0000	1.31
+++ core/error_api.php	3 Aug 2004 13:29:44 -0000
@@ -55,7 +55,7 @@
 				$t_error_type = 'SYSTEM NOTICE';
 				$t_error_description = $p_error;
 				if ( ON == config_get( 'show_notices' ) ) {
-					$t_method = 'inline';
+					$t_method = 'halt'; // 'inline';
 				}
 				break;
 			case E_USER_ERROR:
Index: core/html_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/html_api.php,v
retrieving revision 1.115
diff -u -r1.115 html_api.php
--- core/html_api.php	1 Aug 2004 08:56:38 -0000	1.115
+++ core/html_api.php	3 Aug 2004 13:32:14 -0000
@@ -405,7 +405,7 @@
 				$t_menu_options[] = '<a href="view_all_bug_page.php">' . lang_get( 'view_bugs_link' ) . '</a>';
 
 				# Report Bugs
-				if ( access_has_project_level( REPORTER ) ) {
+				if ( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) {
 					$t_menu_options[] = string_get_bug_report_link();
 				}
 
@@ -680,6 +680,57 @@
 	}
 
 	# --------------------
+	# Print Change Status to: button
+	#  This code is similar to print_status_option_list except
+	#   there is no masking, except for the current state
+	function html_button_bug_change_status( $p_bug_id ) {
+		$t_bug_project_id = bug_get_field( $p_bug_id, 'project_id' );
+		$t_bug_current_state = bug_get_field( $p_bug_id, 'status' );
+		$t_current_access = access_get_project_level( $t_bug_project_id );
+		
+		$t_enum_status = config_get( 'status_enum_string'); 
+		$t_enum_workflow = config_get( 'status_enum_workflow' );
+		if ( count( $t_enum_workflow ) < 1 ) {
+			# workflow not defined, use default enum
+			$t_arr  = explode_enum_string( $t_enum_status );
+		} else {
+			# workflow defined - find allowed states
+			$t_arr  = explode_enum_string( $t_enum_workflow[$t_bug_current_state] );
+		}
+
+		$t_enum_count = count( $t_arr );
+		$t_enum_list = array();
+		for ( $i = 0; $i < $t_enum_count; $i++ ) {
+			$t_elem  = explode_enum_arr( $t_arr[$i] );
+			$t_elem2 = get_enum_element( 'status', $t_elem[0] );
+			$t_status = $t_elem[0];
+			if ( ( $t_status <> $t_bug_current_state ) && ( $t_current_access >= access_get_status_threshold( $t_status ) ) ) {
+				$t_enum_list[$t_status] = $t_elem2;
+			}
+		} # end for
+
+		if ( count( $t_enum_list ) > 0 ) {
+			echo "&nbsp;<form method=\"post\" action=\"bug_change_status_page.php\">\n";
+
+			$t_button_text = lang_get( 'bug_status_to_button' );
+			echo "	<input type=\"submit\" class=\"button\" value=\"$t_button_text\" />\n";
+
+			echo "<select name=\"new_status\">";
+			foreach ( $t_enum_list as $key => $val ) {
+				echo "<option value=\"$key\"";
+				check_selected( $val, $t_bug_current_state );  # select current status which doesn't exist, hence no selection
+				echo ">$val</option>";
+			}
+			echo '</select>';
+
+			$t_bug_id = string_attribute( $p_bug_id );
+			echo "	<input type=\"hidden\" name=\"bug_id\" value=\"$t_bug_id\" />\n";
+
+			echo "</form>&nbsp;\n";
+		}
+	}
+
+	# --------------------
 	# Print Assign To: combo box of possible handlers
 	function html_button_bug_assign_to( $p_bug_id ) {
 		# make sure status is allowed of assign would cause auto-set-status
@@ -708,7 +759,7 @@
 			$t_default_assign_to = $t_current_user_id;
 		}
 
-		if ( ( $t_handler_id != $t_reporter_id ) &&
+		if ( ( $t_handler_id != $t_reporter_id ) && user_exists( $t_reporter_id ) &&
 			( access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id, $t_reporter_id ) ) ) {
 		    $t_options[] = array( $t_reporter_id, '[' . lang_get( 'reporter' ) . ']' );
 
@@ -717,7 +768,7 @@
 			}
 		}
 
-		PRINT "<form method=\"post\" action=\"bug_assign.php\">\n";
+		PRINT "&nbsp;<form method=\"post\" action=\"bug_assign.php\">\n";
 
 		$t_button_text = lang_get( 'bug_assign_to_button' );
 		PRINT "	<input type=\"submit\" class=\"button\" value=\"$t_button_text\" />\n";
@@ -759,7 +810,7 @@
 		$t_bug_id = string_attribute( $p_bug_id );
 		PRINT "	<input type=\"hidden\" name=\"bug_id\" value=\"$t_bug_id\" />\n";
 
-		PRINT "</form>\n";
+		PRINT "</form>&nbsp;\n";
 	}
 
 	# --------------------
@@ -814,9 +865,10 @@
 	 		  ( ON == config_get( 'allow_reporter_reopen' ) ) 
 			 	) )
 			 ) {
-			html_button( 'bug_reopen_page.php',
+			html_button( 'bug_change_status_page.php',
 						 lang_get( 'reopen_bug_button' ),
-						 array( 'bug_id' => $p_bug_id ) );
+						 array( 'bug_id' => $p_bug_id ,
+						 				'new_status' => config_get( 'bug_reopen_status' ) ) );
 		}
 	}
 
@@ -869,8 +921,9 @@
 		$t_resolved = config_get( 'bug_resolved_status_threshold' );
 		$t_status = bug_get_field( $p_bug_id, 'status' );
 
-		PRINT '<table><tr><td>';
+		PRINT '<table><tr>';
 		if ( !bug_is_readonly( $p_bug_id ) ) {
+			PRINT '<td>';
 			# UPDATE button
 			html_button_bug_update( $p_bug_id );
 
@@ -881,26 +934,24 @@
 
 			PRINT '</td><td>';
 
-			# RESOLVE button
-			html_button_bug_resolve( $p_bug_id );
-
-			PRINT '</td><td>';
-
 			# MOVE button
 			html_button_bug_move( $p_bug_id );
 
 			# # CREATE CHILD button
 			# PRINT '</td><td>';
 			# html_button_bug_create_child( $p_bug_id );
+		 
+			PRINT '</td>';
 		} else {
+			PRINT '<td>';
 			# REOPEN button
 			html_button_bug_reopen( $p_bug_id );
+			PRINT '</td>';
 		}
-		PRINT '</td>';
-
-		# CLOSE button
+		
 		PRINT '<td>';
-		html_button_bug_close( $p_bug_id );
+		# Change State button
+		html_button_bug_change_status( $p_bug_id );
 		PRINT '</td>';
 
 		# MONITOR/UNMONITOR button
@@ -919,4 +970,4 @@
 		html_button_bug_delete( $p_bug_id );
 		PRINT '</td></tr></table>';
 	}
-?>
\ No newline at end of file
+?>
Index: core/obsolete.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/obsolete.php,v
retrieving revision 1.25
diff -u -r1.25 obsolete.php
--- core/obsolete.php	8 May 2004 23:57:21 -0000	1.25
+++ core/obsolete.php	3 Aug 2004 13:01:57 -0000
@@ -88,4 +88,10 @@
 	config_obsolete( 'show_project_in_title', '' );
 
 	config_obsolete( 'hide_closed_default', 'hide_status_default' );
-?>
\ No newline at end of file
+
+	config_obsolete( 'close_bug_threshold', 'set_status_threshold' );
+	config_obsolete( 'reopen_bug_threshold', 'set_status_threshold' );
+	
+	config_obsolete( 'status_pulldown_enum_mask_string', '' );
+	
+?>
Index: core/print_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/print_api.php,v
retrieving revision 1.93
diff -u -r1.93 print_api.php
--- core/print_api.php	27 Jul 2004 00:59:08 -0000	1.93
+++ core/print_api.php	3 Aug 2004 13:23:57 -0000
@@ -586,29 +586,48 @@
 	# Select the proper enum values for status based on workflow
 	# or the input parameter if workflows are not used
 	# $p_enum_name : name of enumeration (eg: status)
-	# $p_val : current value
-	function print_enum_string_option_list_workflow( $p_enum_name, $p_val = 0 ) {
-		$t_config_var_name = $p_enum_name . '_enum_string';
-		$t_config_var_value = config_get( $t_config_var_name );
-		$t_enum_workflow = config_get( $p_enum_name . '_enum_workflow' );
+	# $p_current_value : current value
+	function print_status_option_list( $p_select_label, $p_current_value = 0 ) {
+		$t_config_var_value = config_get( 'status_enum_string' );
+		$t_enum_workflow = config_get( 'status_enum_workflow' );
+		$t_current_auth = access_get_project_level();
 
 		if ( count( $t_enum_workflow ) < 1 ) {
 			# workflow not defined, use default enum
 			$t_arr  = explode_enum_string( $t_config_var_value );
 		} else {
 			# workflow defined - find allowed states
-			$t_arr  = explode_enum_string( $t_enum_workflow[$p_val] );
+			$t_arr  = explode_enum_string( $t_enum_workflow[$p_current_value] );
 		}
 
 		$t_enum_count = count( $t_arr );
+		$t_enum_list = array();
+		$t_current_state = '';
 
 		for ( $i = 0; $i < $t_enum_count; $i++ ) {
 			$t_elem  = explode_enum_arr( $t_arr[$i] );
-			$t_elem2 = get_enum_element( $p_enum_name, $t_elem[0] );
-			echo "<option value=\"$t_elem[0]\"";
-			check_selected( $t_elem[0], $p_val );
-			echo ">$t_elem2</option>";
+			$t_elem2 = get_enum_element( 'status', $t_elem[0] );
+			$t_status = $t_elem[0];
+			if ( $t_status == $p_current_value ) {
+				$t_current_state = $t_elem2;
+			}
+			if ( $t_current_auth >= access_get_status_threshold( $t_status ) ) {
+				$t_enum_list[$t_status] = $t_elem2;
+			}
 		} # end for
+
+		if ( count( $t_enum_list ) > 0 ) {
+			echo '<select name="' . $p_select_label . '">';
+			foreach ( $t_enum_list as $key => $val ) {
+				echo "<option value=\"$key\"";
+				check_selected( $val, $p_current_value );
+				echo ">$val</option>";
+			}
+			echo '</select>';
+		} else {
+			echo $t_current_state;
+		}
+
 	}
 	# --------------------
 	# prints the list of a project's users
Index: lang/strings_english.txt
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/lang/strings_english.txt,v
retrieving revision 1.193
diff -u -r1.193 strings_english.txt
--- lang/strings_english.txt	2 Aug 2004 18:17:59 -0000	1.193
+++ lang/strings_english.txt	3 Aug 2004 13:33:38 -0000
@@ -391,12 +391,24 @@
 # bug_assign.php
 $s_bug_assign_msg = 'Issue has been successfully assigned...';
 
+# bug_change_status_page.php
+$s_new_bug_title = 'New Issue';
+$s_feedback_bug_title = 'Provide Feedback to Issue';
+$s_acknowledged_bug_title = 'Acknowledge Issue';
+$s_confirmed_bug_title = 'Confirm Issue';
+$s_assigned_bug_title = 'Assign Issue';
+$s_new_bug_button = 'New Issue';
+$s_feedback_bug_button = 'Provide Feedback';
+$s_acknowledged_bug_button = 'Acknowledge Issue';
+$s_confirmed_bug_button = 'Confirm Issue';
+$s_assigned_bug_button = 'Assign Issue';
+
 # bug_close.php
 $s_bug_close_msg = 'Issue has been closed...';
 $s_close_immediately = 'Close immediately:';
 
 # bug_close_page.php
-$s_close_bug_title = 'Close Issue';
+$s_closed_bug_title = 'Close Issue';
 
 # bug_delete.php
 $s_bug_deleted_msg = 'Issue has been deleted...';
@@ -424,8 +436,8 @@
 $s_bugnote_add_reopen_button = 'Add Note and Reopen Issue';
 
 # bug_resolve_page.php
-$s_resolve_bug_title = 'Resolve Issue';
-$s_resolve_bug_button = 'Resolve Issue';
+$s_resolved_bug_title = 'Resolve Issue';
+$s_resolved_bug_button = 'Resolve Issue';
 
 # bug_resolve_page2.php
 $s_bug_resolved_msg = 'Issue has been resolved. Enter note below...';
@@ -897,6 +909,7 @@
 $s_system_profile = 'System Description';
 $s_update_bug_button = 'Update Issue';
 $s_bug_assign_to_button = 'Assign To:';
+$s_bug_status_to_button = 'Change Status To:';
 $s_reopen_bug_button = 'Reopen Issue';
 $s_move_bug_button = 'Move Issue';
 $s_attached_files = 'Attached Files';
@@ -1007,4 +1020,4 @@
 
 # Source Control Integration
 $s_checkin = 'Checkin';
-?>
\ No newline at end of file
+?>
