diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java index d8a050fff0c..7e40759e82e 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java @@ -146,11 +146,22 @@ public class DefaultCodeFormatterConstants { * FORMATTER / Option for alignment of conditional expression * - option id: "org.eclipse.cdt.core.formatter.alignment_for_conditional_expression" * - possible values: values returned by createAlignmentValue(boolean, int, int) call - * - default: createAlignmentValue(false, WRAP_ONE_PER_LINE, INDENT_DEFAULT) + * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_ON_COLUMN) * * @see #createAlignmentValue(boolean, int, int) */ public static final String FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION = CCorePlugin.PLUGIN_ID + ".formatter.alignment_for_conditional_expression"; //$NON-NLS-1$ + /** + *
+	 * FORMATTER / Option for alignment of a chain of conditional expressions.
+	 *     - option id:         "org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain"
+	 *     - possible values:   values returned by createAlignmentValue(boolean, int, int) call
+	 *     - default:           createAlignmentValue(false, WRAP_COMPACT, INDENT_ON_COLUMN)
+	 * 
+ * @see #createAlignmentValue(boolean, int, int) + * @since 5.3 + */ + public static final String FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION_CHAIN = CCorePlugin.PLUGIN_ID + ".formatter.alignment_for_conditional_expression_chain"; //$NON-NLS-1$ /** *
 	 * FORMATTER / Option for alignment of a declarator list
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java
index 835361b9bff..c1187c2037a 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java
@@ -172,7 +172,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 	private static class ListOptions {
 		final int fMode;
 		int fSeparatorToken = Token.tCOMMA;
-		boolean fInsertNewLineBeforeListIfNecessary;
 		boolean fSpaceBeforeSeparator;
 		boolean fSpaceAfterSeparator = true;
 		boolean fSpaceAfterOpeningParen;
@@ -1223,6 +1222,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 			final ListOptions options= new ListOptions(Alignment.M_COMPACT_SPLIT);
 			options.fSpaceAfterSeparator= preferences.insert_space_after_comma_in_template_parameters;
 			options.fSpaceBeforeSeparator= preferences.insert_space_before_comma_in_template_parameters;
+			options.fTieBreakRule = Alignment.R_OUTERMOST;
 			formatList(Arrays.asList(templateParameters), options, false, false, null);
 		}
 		scribe.printNextToken(new int[] { Token.tGT, Token.tSHIFTR }, preferences.insert_space_before_closing_angle_bracket_in_template_parameters);
@@ -1485,7 +1485,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 
 	private ListOptions createListOptionsForFunctionDeclarationParameters() {
 		final ListOptions options= new ListOptions(preferences.alignment_for_parameters_in_method_declaration);
-		options.fInsertNewLineBeforeListIfNecessary= true;
 		options.fSpaceBeforeOpeningParen= preferences.insert_space_before_opening_paren_in_method_declaration;
 		options.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_declaration;
 		options.fSpaceBeforeClosingParen= preferences.insert_space_before_closing_paren_in_method_declaration;
@@ -2031,91 +2030,63 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 			if (options.fSpaceAfterOpeningParen) {
 				scribe.space();
 			}
-			Alignment wrapperAlignment = null;
 
 			final int continuationIndentation= options.fContinuationIndentation >= 0 ?
 					options.fContinuationIndentation : preferences.continuation_indentation;
-			if (options.fInsertNewLineBeforeListIfNecessary &&
-					(options.fMode & Alignment.M_INDENT_ON_COLUMN) != 0) {
-				wrapperAlignment = scribe.createAlignment(
-						Alignment.COLUMN_WRAPPER,
-						Alignment.M_COMPACT_FIRST_BREAK_SPLIT,
-						Alignment.R_INNERMOST,
-						1,
-						scribe.scanner.getCurrentPosition(),
-						continuationIndentation,
-						false);
-				scribe.enterAlignment(wrapperAlignment);
-			}
-			boolean success = false;
+			Alignment alignment = scribe.createAlignment(
+					Alignment.LIST_ELEMENTS_PREFIX +
+							(elements.isEmpty() ? "ellipsis" : elements.get(0).getClass().getSimpleName()), //$NON-NLS-1$
+					options.fMode,
+					options.fTieBreakRule,
+					elementsLength + (addEllipsis ? 1 : 0),
+					scribe.scanner.getCurrentPosition(),
+					continuationIndentation,
+					false);
+			scribe.enterAlignment(alignment);
+			boolean ok = false;
 			do {
-				if (wrapperAlignment != null)
-					scribe.alignFragment(wrapperAlignment, 0);
-
 				try {
-					Alignment alignment = scribe.createAlignment(
-							Alignment.LIST_ELEMENTS_PREFIX +
-									(elements.isEmpty() ? "ellipsis" : elements.get(0).getClass().getSimpleName()), //$NON-NLS-1$
-							options.fMode,
-							options.fTieBreakRule,
-							elementsLength + (addEllipsis ? 1 : 0),
-							scribe.scanner.getCurrentPosition(),
-							wrapperAlignment == null ? continuationIndentation : 0,
-							false);
-					scribe.enterAlignment(alignment);
-					boolean ok = false;
-					do {
-						try {
-							int i;
-							for (i = 0; i < elementsLength; i++) {
-								final IASTNode node= elements.get(i);
-								if (i < alignment.fragmentCount - 1) {
-									scribe.setTailFormatter(
-											new TrailingTokenFormatter(options.fSeparatorToken,
-													options.fSpaceBeforeSeparator,
-													options.fSpaceAfterSeparator));
-								} else {
-									scribe.setTailFormatter(tailFormatter);
-								}
-								scribe.alignFragment(alignment, i);
-								if (node instanceof ICPPASTConstructorChainInitializer) {
-									// Constructor chain initializer is a special case.
-									visit((ICPPASTConstructorChainInitializer) node);
-								} else {
-									node.accept(this);
-								}
-								if (i < alignment.fragmentCount - 1) {
-									scribe.runTailFormatter();
-								}
-							}
-							if (addEllipsis) {
-								if (i > 0) {
-									scribe.printNextToken(options.fSeparatorToken, options.fSpaceBeforeSeparator);
-									scribe.printTrailingComment();
-								}
-								scribe.alignFragment(alignment, i);
-								if (i > 0 && options.fSpaceAfterSeparator) {
-									scribe.space();
-								}
-								scribe.printNextToken(Token.tELIPSE);
-							}
-							scribe.runTailFormatter();
-							ok = true;
-						} catch (AlignmentException e) {
-							scribe.redoAlignment(e);
-						} catch (ASTProblemException e) {
+					int i;
+					for (i = 0; i < elementsLength; i++) {
+						final IASTNode node= elements.get(i);
+						if (i < alignment.fragmentCount - 1) {
+							scribe.setTailFormatter(
+									new TrailingTokenFormatter(options.fSeparatorToken,
+											options.fSpaceBeforeSeparator,
+											options.fSpaceAfterSeparator));
+						} else {
+							scribe.setTailFormatter(tailFormatter);
 						}
-					} while (!ok);
-					scribe.exitAlignment(alignment, true);
-					success = true;
+						scribe.alignFragment(alignment, i);
+						if (node instanceof ICPPASTConstructorChainInitializer) {
+							// Constructor chain initializer is a special case.
+							visit((ICPPASTConstructorChainInitializer) node);
+						} else {
+							node.accept(this);
+						}
+						if (i < alignment.fragmentCount - 1) {
+							scribe.runTailFormatter();
+						}
+					}
+					if (addEllipsis) {
+						if (i > 0) {
+							scribe.printNextToken(options.fSeparatorToken, options.fSpaceBeforeSeparator);
+							scribe.printTrailingComment();
+						}
+						scribe.alignFragment(alignment, i);
+						if (i > 0 && options.fSpaceAfterSeparator) {
+							scribe.space();
+						}
+						scribe.printNextToken(Token.tELIPSE);
+					}
+					scribe.runTailFormatter();
+					ok = true;
 				} catch (AlignmentException e) {
-					if (wrapperAlignment == null)
-						throw e;
 					scribe.redoAlignment(e);
+				} catch (ASTProblemException e) {
 				}
-			} while (wrapperAlignment != null && !success);
-			if (wrapperAlignment != null)
-				scribe.exitAlignment(wrapperAlignment, true);
+			} while (!ok);
+			scribe.exitAlignment(alignment, true);
 		} else if (tailFormatter != null) {
 			tailFormatter.run();
 		}
@@ -2180,72 +2151,89 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 	}
 
 	private int visit(IASTConditionalExpression node) {
+		// Count nested conditional expressions.
+		int numConditions = 0;
+		for (IASTExpression expression = node; expression instanceof IASTConditionalExpression;
+				expression = ((IASTConditionalExpression) expression).getNegativeResultExpression()) {
+			numConditions++;
+		}
+
 		Runnable tailFormatter = scribe.takeTailFormatter();
 
+		Alignment alignment = scribe.createAlignment(
+    			Alignment.CONDITIONAL_EXPRESSION_CHAIN,
+    			preferences.alignment_for_conditional_expression_chain,
+    			Alignment.R_OUTERMOST,
+    			numConditions,
+				scribe.scanner.getCurrentPosition());
+
+    	scribe.enterAlignment(alignment);
+    	boolean ok = false;
+    	do {
+    		try {
+        		IASTConditionalExpression expression = node;
+    			for (int i = 0; ; i++) {
+	    			scribe.alignFragment(alignment, i);
+	    			boolean last = i == numConditions - 1;
+    		    	formatConditionalExpression(expression, last ? tailFormatter : null);
+    		    	if (last)
+    		    		break;
+    		    	expression = (IASTConditionalExpression) expression.getNegativeResultExpression();
+				}
+    			ok = true;
+    		} catch (AlignmentException e) {
+    			scribe.redoAlignment(e);
+    		}
+    	} while (!ok);
+    	scribe.exitAlignment(alignment, true);
+
+		return PROCESS_SKIP;
+    }
+
+	private void formatConditionalExpression(IASTConditionalExpression node, Runnable tailFormatter) {
 		scribe.setTailFormatter(new TrailingTokenFormatter(Token.tQUESTION, node,
 				preferences.insert_space_before_question_in_conditional,
 				preferences.insert_space_after_question_in_conditional));
 		node.getLogicalConditionExpression().accept(this);
 		scribe.runTailFormatter();
 
-		Alignment wrapperAlignment = scribe.createAlignment(
-				Alignment.CONDITIONAL_EXPRESSION_WRAPPER,
-				Alignment.M_COMPACT_FIRST_BREAK_SPLIT,
-				Alignment.R_OUTERMOST,
-				1,
-				scribe.scanner.getCurrentPosition(),
-				preferences.continuation_indentation,
-				false);
-		scribe.enterAlignment(wrapperAlignment);
-		boolean success = false;
-		do {
-			scribe.alignFragment(wrapperAlignment, 0);
+		final IASTExpression positiveExpression = node.getPositiveResultExpression();
+		final IASTExpression negativeExpression = node.getNegativeResultExpression();
 
-			try {
-				Alignment alignment = scribe.createAlignment(
-		    			Alignment.CONDITIONAL_EXPRESSION,
-		    			preferences.alignment_for_conditional_expression,
-		    			Alignment.R_OUTERMOST,
-		    			2,
-						scribe.scanner.getCurrentPosition(),
-						0,
-						false);
-		
-		    	scribe.enterAlignment(alignment);
-		    	boolean ok = false;
-		    	do {
-		    		try {
-		    			scribe.alignFragment(alignment, 0);
-		    			final IASTExpression positiveExpression = node.getPositiveResultExpression();
-		    			final IASTExpression negativeExpression = node.getNegativeResultExpression();
-		    			scribe.setTailFormatter(new TrailingTokenFormatter(Token.tCOLON, node,
-		    					preferences.insert_space_before_colon_in_conditional,
-		    					preferences.insert_space_after_colon_in_conditional));
-	    				// A gcc extension allows the positive expression to be omitted.
-		    			if (positiveExpression != null) {
-		    				positiveExpression.accept(this);
-		    			}
-		    			scribe.runTailFormatter();
-		
-		    			scribe.alignFragment(alignment, 1);
-		    			scribe.setTailFormatter(tailFormatter);
-		    			negativeExpression.accept(this);
-		    			scribe.runTailFormatter();
-		    			ok = true;
-		    		} catch (AlignmentException e) {
-		    			scribe.redoAlignment(e);
-		    		}
-		    	} while (!ok);
-		    	scribe.exitAlignment(alignment, true);
-				success = true;
-			} catch (AlignmentException e) {
-				scribe.redoAlignment(e);
-			}
-		} while (!success);
-		scribe.exitAlignment(wrapperAlignment, true);
+		Alignment alignment = scribe.createAlignment(
+    			Alignment.CONDITIONAL_EXPRESSION,
+    			preferences.alignment_for_conditional_expression,
+    			Alignment.R_OUTERMOST,
+    			negativeExpression instanceof IASTConditionalExpression ? 1 : 2,
+				scribe.scanner.getCurrentPosition());
 
-		return PROCESS_SKIP;
-    }
+    	scribe.enterAlignment(alignment);
+    	boolean ok = false;
+    	do {
+    		try {
+    			scribe.alignFragment(alignment, 0);
+    			scribe.setTailFormatter(new TrailingTokenFormatter(Token.tCOLON, node,
+    					preferences.insert_space_before_colon_in_conditional,
+    					preferences.insert_space_after_colon_in_conditional));
+				// A gcc extension allows the positive expression to be omitted.
+    			if (positiveExpression != null) {
+    				positiveExpression.accept(this);
+    			}
+    			scribe.runTailFormatter();
+
+    			if (!(negativeExpression instanceof IASTConditionalExpression)) {
+	    			scribe.alignFragment(alignment, 1);
+	    			scribe.setTailFormatter(tailFormatter);
+	    			negativeExpression.accept(this);
+	    			scribe.runTailFormatter();
+    			}
+    			ok = true;
+    		} catch (AlignmentException e) {
+    			scribe.redoAlignment(e);
+    		}
+    	} while (!ok);
+    	scribe.exitAlignment(alignment, true);
+	}
 
 	private int visit(IASTFunctionCallExpression node) {
 		Runnable tailFormatter = scribe.takeTailFormatter();
@@ -2284,7 +2272,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 		}
 		final ListOptions options= new ListOptions(preferences.alignment_for_arguments_in_method_invocation);
 		options.fSeparatorToken = Token.tCOMMA;
-		options.fInsertNewLineBeforeListIfNecessary= true;
 		options.fSpaceBeforeOpeningParen= preferences.insert_space_before_opening_paren_in_method_invocation;
 		options.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_invocation;
 		options.fSpaceBeforeClosingParen= preferences.insert_space_before_closing_paren_in_method_invocation;
@@ -2393,7 +2380,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 	    	do {
 	    		try {
 	    			scribe.alignFragment(alignment, 0);
-
 	   				node.getInitializerClause().accept(this);
 	    			ok = true;
 	    		} catch (AlignmentException e) {
@@ -2656,7 +2642,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
     	Alignment expressionAlignment= scribe.createAlignment(
     			Alignment.ASSIGNMENT_EXPRESSION,
     			preferences.alignment_for_assignment,
-    			Alignment.R_OUTERMOST,
+    			Alignment.R_INNERMOST,
     			1,
     			scribe.scanner.getCurrentPosition());
 
@@ -2717,70 +2703,42 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 			scribe.space();
 		}
 
-		Alignment wrapperAlignment = null;
-		if ((preferences.alignment_for_overloaded_left_shift_chain & Alignment.M_INDENT_ON_COLUMN) != 0) {
-			wrapperAlignment = scribe.createAlignment(
-					Alignment.COLUMN_WRAPPER,
-					Alignment.M_COMPACT_FIRST_BREAK_SPLIT,
-					Alignment.R_INNERMOST,
-					1,
-					scribe.scanner.getCurrentPosition(),
-					preferences.continuation_indentation,
-					false);
-			scribe.enterAlignment(wrapperAlignment);
-		}
-		boolean success = false;
+		Alignment alignment = scribe.createAlignment(
+				Alignment.OVERLOADED_LEFT_SHIFT_CHAIN,
+				preferences.alignment_for_overloaded_left_shift_chain,
+				Alignment.R_OUTERMOST,
+				elements.size(),
+				scribe.scanner.getCurrentPosition(),
+				preferences.continuation_indentation,
+				false);
+		scribe.enterAlignment(alignment);
+		boolean ok = false;
 		do {
-			if (wrapperAlignment != null)
-				scribe.alignFragment(wrapperAlignment, 0);
-
 			try {
-				Alignment alignment = scribe.createAlignment(
-						Alignment.OVERLOADED_LEFT_SHIFT_CHAIN,
-						preferences.alignment_for_overloaded_left_shift_chain,
-						Alignment.R_OUTERMOST,
-						elements.size(),
-						scribe.scanner.getCurrentPosition(),
-						wrapperAlignment == null ? preferences.continuation_indentation : 0,
-						false);
-				scribe.enterAlignment(alignment);
-				boolean ok = false;
-				do {
-					try {
-						for (int i = 0; i < elements.size(); i++) {
-							scribe.alignFragment(alignment, i);
-							int token= peekNextToken();
-							if (token == Token.tSHIFTL) {
-								scribe.printNextToken(token, preferences.insert_space_before_binary_operator);
-								scribe.printTrailingComment();
-								if (preferences.insert_space_after_binary_operator) {
-									scribe.space();
-								}
-							}
-							node= elements.get(i);
-							if (i == alignment.fragmentCount - 1) {
-								scribe.setTailFormatter(tailFormatter);
-							}
-							node.accept(this);
+				for (int i = 0; i < elements.size(); i++) {
+					scribe.alignFragment(alignment, i);
+					int token= peekNextToken();
+					if (token == Token.tSHIFTL) {
+						scribe.printNextToken(token, preferences.insert_space_before_binary_operator);
+						scribe.printTrailingComment();
+						if (preferences.insert_space_after_binary_operator) {
+							scribe.space();
 						}
-						scribe.runTailFormatter();
-						ok = true;
-					} catch (AlignmentException e) {
-						scribe.redoAlignment(e);
-					} catch (ASTProblemException e) {
 					}
-				} while (!ok);
-				scribe.exitAlignment(alignment, true);
-				success = true;
+					node= elements.get(i);
+					if (i == alignment.fragmentCount - 1) {
+						scribe.setTailFormatter(tailFormatter);
+					}
+					node.accept(this);
+				}
+				scribe.runTailFormatter();
+				ok = true;
 			} catch (AlignmentException e) {
-				if (wrapperAlignment == null)
-					throw e;
 				scribe.redoAlignment(e);
+			} catch (ASTProblemException e) {
 			}
-		} while (wrapperAlignment != null && !success);
-		if (wrapperAlignment != null)
-			scribe.exitAlignment(wrapperAlignment, true);
-
+		} while (!ok);
+		scribe.exitAlignment(alignment, true);
     	return PROCESS_SKIP;
 	}
 
@@ -3365,6 +3323,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 			final ListOptions options= new ListOptions(Alignment.M_COMPACT_SPLIT);
 			options.fSpaceAfterSeparator= preferences.insert_space_after_comma_in_template_arguments;
 			options.fSpaceBeforeSeparator= preferences.insert_space_before_comma_in_template_arguments;
+			options.fTieBreakRule = Alignment.R_OUTERMOST;
 			formatList(Arrays.asList(templateArguments), options, false, false, null);
 		}
 		if (peekNextToken() == Token.tSHIFTR) {
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java
index cff64a79311..5e940f6617a 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -59,6 +59,7 @@ public class DefaultCodeFormatterOptions {
 	public int alignment_for_base_clause_in_type_declaration;
 	public int alignment_for_binary_expression;
 	public int alignment_for_compact_if;
+	public int alignment_for_conditional_expression_chain;
 	public int alignment_for_conditional_expression;
 	public int alignment_for_declarator_list;
 	public int alignment_for_enumerator_list;
@@ -275,6 +276,7 @@ public class DefaultCodeFormatterOptions {
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_BINARY_EXPRESSION, getAlignment(this.alignment_for_binary_expression));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_COMPACT_IF, getAlignment(this.alignment_for_compact_if));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION, getAlignment(this.alignment_for_conditional_expression));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION_CHAIN, getAlignment(this.alignment_for_conditional_expression_chain));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_DECLARATOR_LIST, getAlignment(this.alignment_for_declarator_list));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ENUMERATOR_LIST, getAlignment(this.alignment_for_enumerator_list));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_INITIALIZER_LIST, getAlignment(this.alignment_for_expressions_in_initializer_list));
@@ -528,9 +530,19 @@ public class DefaultCodeFormatterOptions {
 			try {
 				this.alignment_for_conditional_expression = Integer.parseInt((String) alignmentForConditionalExpressionOption);
 			} catch (NumberFormatException e) {
-				this.alignment_for_conditional_expression = Alignment.M_ONE_PER_LINE_SPLIT;
+				this.alignment_for_conditional_expression = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
 			} catch (ClassCastException e) {
-				this.alignment_for_conditional_expression = Alignment.M_ONE_PER_LINE_SPLIT;
+				this.alignment_for_conditional_expression = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
+			}
+		}
+		final Object alignmentForConditionalExpressionChainOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION_CHAIN);
+		if (alignmentForConditionalExpressionChainOption != null) {
+			try {
+				this.alignment_for_conditional_expression_chain = Integer.parseInt((String) alignmentForConditionalExpressionChainOption);
+			} catch (NumberFormatException e) {
+				this.alignment_for_conditional_expression_chain = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
+			} catch (ClassCastException e) {
+				this.alignment_for_conditional_expression_chain = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
 			}
 		}
 		final Object alignmentForDeclaratorListOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_DECLARATOR_LIST);
@@ -1484,7 +1496,8 @@ public class DefaultCodeFormatterOptions {
 		this.alignment_for_base_clause_in_type_declaration = Alignment.M_NEXT_PER_LINE_SPLIT;
 		this.alignment_for_binary_expression = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_compact_if = Alignment.M_COMPACT_SPLIT;
-		this.alignment_for_conditional_expression = Alignment.M_NEXT_PER_LINE_SPLIT;
+		this.alignment_for_conditional_expression = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
+		this.alignment_for_conditional_expression_chain = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
 		this.alignment_for_declarator_list = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_enumerator_list = Alignment.M_ONE_PER_LINE_SPLIT;
 		this.alignment_for_expressions_in_initializer_list = Alignment.M_COMPACT_SPLIT;
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java
index fc85663b663..834a7722152 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java
@@ -227,9 +227,7 @@ public class Scribe {
 	}
 
 	public void alignFragment(Alignment alignment, int fragmentIndex) {
-		alignment.fragmentIndex= fragmentIndex;
-		alignment.checkColumn();
-		alignment.performFragmentEffect();
+		alignment.alignFragment(fragmentIndex);
 	}
 
 	public void consumeNextToken() {
@@ -577,11 +575,22 @@ public class Scribe {
 	}
 
 	public void handleLineTooLong() {
-		// Search for closest breakable alignment, using tie break rules
-		// look for outermost breakable one.
+		// Search for closest breakable alignment, using tie break rules.
+		// Look for innermost breakable one.
 		int relativeDepth= 0;
-		int outerMostDepth= -1;
 		Alignment targetAlignment= currentAlignment;
+		while (targetAlignment != null && targetAlignment.tieBreakRule == Alignment.R_INNERMOST) {
+			if (targetAlignment.couldBreak()) {
+				throwAlignmentException(AlignmentException.LINE_TOO_LONG, relativeDepth);
+			}
+			targetAlignment= targetAlignment.enclosing;
+			relativeDepth++;
+		}
+
+		// Look for outermost breakable one.
+		relativeDepth= 0;
+		int outerMostDepth= -1;
+		targetAlignment= currentAlignment;
 		while (targetAlignment != null) {
 			if (targetAlignment.tieBreakRule == Alignment.R_OUTERMOST && targetAlignment.couldBreak()) {
 				outerMostDepth= relativeDepth;
@@ -592,7 +601,8 @@ public class Scribe {
 		if (outerMostDepth >= 0) {
 			throwAlignmentException(AlignmentException.LINE_TOO_LONG, outerMostDepth);
 		}
-		// Look for innermost breakable one
+		// Look for innermost breakable one but don't stop if we encounter a R_OUTERMOST
+		// tie-breaking rule.
 		relativeDepth= 0;
 		targetAlignment= currentAlignment;
 		while (targetAlignment != null) {
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java
index efab363a4da..c05c7964829 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java
@@ -11,6 +11,8 @@
  *******************************************************************************/
 package org.eclipse.cdt.internal.formatter.align;
 
+import java.util.Arrays;
+
 import org.eclipse.cdt.internal.formatter.Location;
 import org.eclipse.cdt.internal.formatter.Scribe;
 
@@ -23,10 +25,9 @@ public class Alignment {
 	// Alignment names.
 	public static final String ASSIGNMENT_EXPRESSION = "assignmentExpression"; //$NON-NLS-1$
 	public static final String BINARY_EXPRESSION = "binaryExpression"; //$NON-NLS-1$
-	public static final String COLUMN_WRAPPER = "columnWrapper"; //$NON-NLS-1$
 	public static final String COMPACT_IF = "compactIf"; //$NON-NLS-1$
-	public static final String CONDITIONAL_EXPRESSION_WRAPPER = "conditionalExpressionWrapper"; //$NON-NLS-1$
 	public static final String CONDITIONAL_EXPRESSION = "conditionalExpression"; //$NON-NLS-1$
+	public static final String CONDITIONAL_EXPRESSION_CHAIN = "conditionalExpressionChain"; //$NON-NLS-1$
 	public static final String DECLARATION_INITIALIZER = "declarationInitializer"; //$NON-NLS-1$
 	public static final String DESIGNATED_INITIALIZER = "designatedInitializer"; //$NON-NLS-1$
 	public static final String EXCEPTION_SPECIFICATION = "exceptionSpecification"; //$NON-NLS-1$
@@ -65,7 +66,7 @@ public class Alignment {
 	// Break management
 	public int originalIndentationLevel;
 	public int breakIndentationLevel;
-	public int shiftBreakIndentationLevel;
+	public int alternativeBreakIndentationLevel;
 	public int[] fragmentBreaks;
 	public boolean wasSplit;
 	public int currentFragmentStartLine;
@@ -146,9 +147,9 @@ public class Alignment {
 	public int tieBreakRule;
 	
 	// Alignment effects on a per fragment basis
+	public static final int BREAK_NOT_ALLOWED = -1;
 	public static final int NONE = 0;
-	public static final int BREAK = 1;
-	public static final int BREAK_NOT_ALLOWED = 2;
+	public static final int BREAK = 2;
 	
 	// Chunk kind
 	public static final int CHUNK_FIELD = 1;
@@ -169,6 +170,7 @@ public class Alignment {
 		this.wasSplit = false;
 		this.fragmentIndentations = new int[this.fragmentCount];
 		this.fragmentBreaks = new int[this.fragmentCount];
+		Arrays.fill(this.fragmentBreaks, (this.mode & M_FORCE) == 0 ? BREAK_NOT_ALLOWED : NONE);
 		this.currentFragmentStartLine = this.scribe.line;
 
 		int currentColumn = this.location.outputColumn;
@@ -183,17 +185,14 @@ public class Alignment {
 		if ((mode & M_INDENT_ON_COLUMN) != 0) {
 			// Indent broken fragments at next indentation level, based on current column
 			this.breakIndentationLevel = this.scribe.getNextIndentationLevel(currentColumn);
-			if (this.breakIndentationLevel == this.location.outputIndentationLevel) {
-				this.breakIndentationLevel += continuationIndent * indentSize;
-			}
-			if (continuationIndent == 0) {
-				this.fragmentBreaks[0] = BREAK_NOT_ALLOWED;
-			}
+			this.alternativeBreakIndentationLevel =
+					this.location.outputIndentationLevel + continuationIndent * indentSize;
 		} else {
 			int baseIndentationLevel = this.location.outputIndentationLevel;
 			if (name != TRAILING_TEXT && this.scribe.currentAlignment != null &&
-					(this.scribe.currentAlignment.mode & M_INDENT_ON_COLUMN) != 0) {
-				baseIndentationLevel = this.scribe.getNextIndentationLevel(currentColumn);
+					(this.scribe.currentAlignment.mode & M_INDENT_ON_COLUMN) != 0 &&
+					this.scribe.currentAlignment.fragmentCount > 1) {
+				baseIndentationLevel = this.scribe.currentAlignment.breakIndentationLevel;
 			}
 			if ((mode & M_INDENT_BY_ONE) != 0) {
 				// Indent broken fragments exactly one level deeper than current indentation
@@ -201,11 +200,12 @@ public class Alignment {
 			} else {
 				this.breakIndentationLevel = baseIndentationLevel + continuationIndent * indentSize;
 			}
+			this.alternativeBreakIndentationLevel = this.breakIndentationLevel;
 		}
-		this.shiftBreakIndentationLevel = this.breakIndentationLevel + indentSize;
 
 		// Check for forced alignments
 		if ((this.mode & M_FORCE) != 0) {
+			this.fragmentBreaks[this.fragmentIndex] = NONE;
 			couldBreak();
 		}
 	}
@@ -289,6 +289,15 @@ public class Alignment {
 				i = this.fragmentIndex;
 				do {
 					if (this.fragmentBreaks[i] == NONE) {
+						if ((this.mode & M_INDENT_ON_COLUMN) != 0 && i == 0) {
+							if (this.breakIndentationLevel <= this.alternativeBreakIndentationLevel) {
+								// Does not make sense to break here unless indentation is reduced.
+								break;
+							}
+							// Change break indentation level and erase previously created breaks.
+							this.breakIndentationLevel = this.alternativeBreakIndentationLevel;
+							eraseExistingBreaks(i);
+						}
 						this.fragmentBreaks[i] = BREAK;
 						this.fragmentIndentations[i] = this.breakIndentationLevel;
 						return wasSplit = true;
@@ -308,7 +317,8 @@ public class Alignment {
 					this.fragmentIndentations[0] = this.breakIndentationLevel;
 					for (i = 1; i < this.fragmentCount; i++) {
 						this.fragmentBreaks[i] = BREAK;
-						this.fragmentIndentations[i] = this.shiftBreakIndentationLevel;
+						this.fragmentIndentations[i] =
+								this.breakIndentationLevel + this.scribe.indentationSize;
 					}
 					return wasSplit = true;
 				}
@@ -335,7 +345,7 @@ public class Alignment {
 			 *      #CCCC);
 			 */
 			case M_NEXT_PER_LINE_SPLIT:
-				if (this.fragmentBreaks[0] == NONE) {
+				if (this.fragmentBreaks[0] != BREAK) {
 					if (this.fragmentCount > 1 && this.fragmentBreaks[1] == NONE) {
 						if ((this.mode & M_INDENT_ON_COLUMN) != 0) {
 							this.fragmentIndentations[0] = this.breakIndentationLevel;
@@ -351,6 +361,15 @@ public class Alignment {
 		}
 		return false; // Cannot split better
 	}
+
+	private void eraseExistingBreaks(int startFragmentIndex) {
+		for (int j = startFragmentIndex + 1; j < this.fragmentIndentations.length; j++) {
+			if (this.fragmentBreaks[j] == BREAK) {
+				this.fragmentBreaks[j] = NONE;
+				this.fragmentIndentations[j] = 0;
+			}
+		}
+	}
 	
 	public Alignment getAlignment(String targetName) {
 		if (targetName.equals(this.name)) return this;
@@ -358,8 +377,27 @@ public class Alignment {
 		
 		return this.enclosing.getAlignment(targetName);
 	}
-		
-	// perform alignment effect for current fragment
+
+	public void alignFragment(int fragmentIndex) {
+		this.fragmentIndex= fragmentIndex;
+		if (this.fragmentBreaks[fragmentIndex] == BREAK_NOT_ALLOWED) {
+			this.fragmentBreaks[fragmentIndex] = NONE;	// Allow line break.
+		}
+		switch (this.mode & SPLIT_MASK) {
+		case Alignment.M_NEXT_PER_LINE_SPLIT:
+		case Alignment.M_ONE_PER_LINE_SPLIT:
+			for (int i = fragmentIndex + 1; i < this.fragmentBreaks.length; i++) {
+				if (this.fragmentBreaks[i] == BREAK_NOT_ALLOWED) {
+					this.fragmentBreaks[i] = NONE;	// Allow line break.
+				}
+			}
+			break;
+		}
+		checkColumn();
+		performFragmentEffect();
+	}
+
+	// Performs alignment effect for current fragment.
 	public void performFragmentEffect() {
 		if ((this.mode & M_MULTICOLUMN) == 0) {
 			switch (this.mode & SPLIT_MASK) {
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java
index 03b146dc723..788dc08c87e 100644
--- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java
@@ -1137,9 +1137,8 @@ public class CodeFormatterTest extends BaseUITestCase {
 	//int function_with_a_long_name(int, int);
 	//
 	//void test() {
-	//    function_with_a_long_name(function(1000000, 2000000, 3000000, 4000000,
-	//                                       5000000),
-	//                              6000000);
+	//    function_with_a_long_name(
+	//            function(1000000, 2000000, 3000000, 4000000, 5000000), 6000000);
 	//}
 	public void testFunctionCall_2() throws Exception {
 		fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
@@ -2089,21 +2088,43 @@ public class CodeFormatterTest extends BaseUITestCase {
 
 	//void test() {
 	//    int variable1 = 1000000 < 2000000 ? 3000000 + 40000000 : 8000000 + 90000000;
-	//    int variable2 = 1000000 < 2000000 ?
-	//            3000000 + 40000000 : 8000000 + 900000000;
-	//    int variable3 = 1000000 < 2000000 ?
-	//            3000000 + 4000000 + 5000000 + 6000000 + 7000000 : 8000000 + 9000000;
-	//    int variable4 = 1000000 < 2000000 ?
-	//            3000000 + 4000000 + 5000000 + 6000000 + 7000000 :
-	//            8000000 + 90000000;
-	//}
+	//    int variable2 =
+	//            1000000 < 2000000 ? 3000000 + 40000000 : 8000000 + 900000000;
+	//    int variable3 =
+	//            1000000 < 2000000 ?
+	//                    3000000 + 4000000 + 5000000 + 6000000 + 7000000 :
+	//                    8000000 + 9000000;
+	//    int variable4 =
+	//            1000000 < 2000000 ?
+	//                    3000000 + 4000000 + 5000000 + 6000000 + 7000000 :
+	//                    8000000 + 90000000;
+    //}
 	public void testConditionalExpression() throws Exception {
 		fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
-		fOptions.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION,
-				Integer.toString(Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN));
 		assertFormatterResult();
 	}
 
+	//int variable_with_a_long_name, another_variable_with_a_long_name;
+	//
+	//int variable = variable_with_a_long_name < another_variable_with_a_long_name ?
+	//variable_with_a_long_name + another_variable_with_a_long_name :
+	//variable_with_a_long_name * 2 > another_variable_with_a_long_name ?
+	//variable_with_a_long_name + another_variable_with_a_long_name :
+	//variable_with_a_long_name - another_variable_with_a_long_name;
+
+	//int variable_with_a_long_name, another_variable_with_a_long_name;
+	//
+	//int variable =
+	//        variable_with_a_long_name < another_variable_with_a_long_name ?
+	//                variable_with_a_long_name + another_variable_with_a_long_name :
+	//        variable_with_a_long_name * 2 > another_variable_with_a_long_name ?
+	//                variable_with_a_long_name + another_variable_with_a_long_name :
+	//                variable_with_a_long_name - another_variable_with_a_long_name;
+	public void testConditionalExpressionChain() throws Exception {
+		fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
+		assertFormatterResult();
+	}
+	
 	//// Breaking at '<=' is preferred to breaking at '+'.
 	//bool x = 1000000 + 2000000 + 3000000 + 4000000 <= 5000000 + 6000000 + 7000000 + 8000000;
 
@@ -2293,7 +2314,7 @@ public class CodeFormatterTest extends BaseUITestCase {
 	//
 	//void test() {
 	//    stream << (variable_with_a_long_name + another_variable_with_a_long_name)
-	//                      * variable_with_a_long_name
+	//                   * variable_with_a_long_name
 	//           << "01234567890123456789";
 	//}
 	public void testOverloadedLeftShiftChain_4() throws Exception {
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CIndenter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CIndenter.java
index 0656445bf92..d32891c7e6b 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CIndenter.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CIndenter.java
@@ -116,8 +116,8 @@ public final class CIndenter {
 			prefBlockIndent= prefBlockIndent();
 			prefArrayIndent= prefArrayIndent();
 			prefArrayDeepIndent= prefArrayDeepIndent();
-			prefTernaryDeepAlign= prefTernaryDeepAlign();
-			prefTernaryIndent= prefTernaryIndent();
+			prefTernaryDeepAlign= false;
+			prefTernaryIndent= prefContinuationIndent();
 			prefCaseIndent= prefCaseIndent();
 			prefCaseBlockIndent= prefCaseBlockIndent();
 			prefAssignmentIndent= prefAssignmentIndent();
@@ -183,30 +183,6 @@ public final class CIndenter {
 			return true;
 		}
 
-		private boolean prefTernaryDeepAlign() {
-			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION);
-			try {
-				return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
-			} catch (IllegalArgumentException e) {
-				// ignore and return default
-			}
-			return false;
-		}
-
-		private int prefTernaryIndent() {
-			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION);
-			try {
-				if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
-					return 1;
-				else
-					return prefContinuationIndent();
-			} catch (IllegalArgumentException e) {
-				// ignore and return default
-			}
-
-			return prefContinuationIndent();
-		}
-
 		private int prefCaseIndent() {
 			if (DefaultCodeFormatterConstants.TRUE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH)))
 				return 1;
@@ -1031,7 +1007,7 @@ public final class CIndenter {
 				return skipToPreviousListItemOrListStart();
 			}
 			fPosition= pos;
-			return skipToStatementStart(danglingElse, false);
+			return skipToPreviousListItemOrListStart();
 
 		case Symbols.TokenQUESTIONMARK:
 			if (fPrefs.prefTernaryDeepAlign) {
@@ -1041,7 +1017,7 @@ public final class CIndenter {
 			}
 			return fPosition;
 
-		// indentation for blockless introducers:
+		// Indentation for blockless introducers:
 		case Symbols.TokenDO:
 		case Symbols.TokenWHILE:
 		case Symbols.TokenELSE: