View | Details | Raw Unified | Return to bug 466345 | Differences between
and this patch

Collapse All | Expand All

(-)a/bundles/org.eclipse.jface/src/org/eclipse/jface/util/BidiUtils.java (-1 / +225 lines)
Lines 12-21 Link Here
12
package org.eclipse.jface.util;
12
package org.eclipse.jface.util;
13
13
14
import java.util.HashMap;
14
import java.util.HashMap;
15
import java.util.Locale;
15
import java.util.Map;
16
import java.util.Map;
16
17
18
import org.eclipse.equinox.bidi.StructuredTextProcessor;
17
import org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory;
19
import org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory;
18
import org.eclipse.jface.internal.InternalPolicy;
20
import org.eclipse.jface.internal.InternalPolicy;
21
import org.eclipse.jface.window.Window;
19
import org.eclipse.swt.SWT;
22
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.custom.BidiSegmentEvent;
23
import org.eclipse.swt.custom.BidiSegmentEvent;
21
import org.eclipse.swt.custom.BidiSegmentListener;
24
import org.eclipse.swt.custom.BidiSegmentListener;
Lines 90-95 Link Here
90
	public static final String VISUAL_RIGHT_TO_LEFT = "visualrtl";//$NON-NLS-1$
93
	public static final String VISUAL_RIGHT_TO_LEFT = "visualrtl";//$NON-NLS-1$
91
94
92
	/**
95
	/**
96
	 * For applying bidi processing for formatting messages.
97
	 *
98
	 * @see #applyBidiProcessing(PROCESSING_TYPE, Object...)
99
	 */
100
	public enum PROCESSING_TYPE {
101
		/**
102
		 * For applying bidi processing on message placeholders.
103
		 *
104
		 * @see #applyBidiProcessing(PROCESSING_TYPE, Object...)
105
		 */
106
		MESSAGEWITHPLACEHOLDERS, /**
107
									 * For applying bidi processing on
108
									 * concatenation of strings.
109
									 *
110
									 * @see #applyBidiProcessing(PROCESSING_TYPE,
111
									 *      Object...)
112
									 */
113
		CONCATENATION
114
	}
115
116
	/**
93
	 * Segment listener for LTR Base Text Direction
117
	 * Segment listener for LTR Base Text Direction
94
	 */
118
	 */
95
	private static final SegmentListener BASE_TEXT_DIRECTION_LTR = new BaseTextDirectionSegmentListener(LEFT_TO_RIGHT);
119
	private static final SegmentListener BASE_TEXT_DIRECTION_LTR = new BaseTextDirectionSegmentListener(LEFT_TO_RIGHT);
Lines 142-147 Link Here
142
	 * The RLE char
166
	 * The RLE char
143
	 */
167
	 */
144
	static final char RLE = 0x202B;
168
	static final char RLE = 0x202B;
169
170
	/**
171
	 * The RLM char
172
	 */
173
	static final char RLM = 0x200F;
145
174
146
	/**
175
	/**
147
	 * The LRO char
176
	 * The LRO char
Lines 538-541 Link Here
538
			control.setTextDirection(textDir);
567
			control.setTextDirection(textDir);
539
		}
568
		}
540
	}
569
	}
541
}
570
571
	/**
572
	 * Applies bidi processing to the given string.
573
	 *
574
	 * <p>
575
	 * Possible values for <code>handlingType</code> are:
576
	 * <ul>
577
	 * <li>{@link BidiUtils#LEFT_TO_RIGHT}</li>
578
	 * <li>{@link BidiUtils#RIGHT_TO_LEFT}</li>
579
	 * <li>{@link BidiUtils#AUTO}</li>
580
	 * <li>{@link BidiUtils#BTD_DEFAULT}</li>
581
	 * <li>{@link BidiUtils#VISUAL_LEFT_TO_RIGHT}</li>
582
	 * <li>{@link BidiUtils#VISUAL_RIGHT_TO_LEFT}</li>
583
	 * <li>the <code>String</code> constants in
584
	 * {@link StructuredTextTypeHandlerFactory}</li>
585
	 * <li>if OSGi is running, the types that have been contributed to the
586
	 * <code>org.eclipse.equinox.bidi.bidiTypes</code> extension point.</li>
587
	 * </ul>
588
	 * <p>
589
	 * The 3 values {@link #LEFT_TO_RIGHT}, {@link #RIGHT_TO_LEFT}, and
590
	 * {@link #AUTO} are usable whether {@link #getBidiSupport() bidi support}
591
	 * is enabled or disabled.
592
	 * <p>
593
	 * The remaining values only have an effect if bidi support is enabled.
594
	 * <p>
595
	 * The 4 first values {@link #LEFT_TO_RIGHT}, {@link #RIGHT_TO_LEFT},
596
	 * {@link #AUTO}, and {@link #BTD_DEFAULT} are for Base Text Direction (BTD)
597
	 * handling. The remaining values are for Structured Text handling.
598
	 * <p>
599
	 * <strong>Note:</strong> The Structured Text handling only works if the
600
	 * <code>org.eclipse.equinox.bidi</code> bundle is on the classpath!
601
	 * <p>
602
	 * <strong>Note:</strong> To deprocess the string you must use
603
	 * {@link BidiUtils#deprocessBidi(String)} for the 6 first values or
604
	 * {@link StructuredTextProcessor#deprocessTyped(String, String)} for the
605
	 * remaining values.
606
	 * </p>
607
	 *
608
	 * @param string
609
	 *            the string
610
	 * @param handlingType
611
	 *            the type of handling
612
	 * @return the bidi processed string
613
	 * @throws IllegalArgumentException
614
	 *             if <code>handlingType</code> is not a known type identifier
615
	 */
616
	public static String applyBidiProcessing(String string, String handlingType) {
617
		if (LEFT_TO_RIGHT.equals(handlingType)) {
618
			return addUCC(string, false, handlingType);
619
		} else if (RIGHT_TO_LEFT.equals(handlingType)) {
620
			return addUCC(string, true, handlingType);
621
		} else if (AUTO.equals(handlingType)) {
622
			return addUCC(string, isRTLValue(string), handlingType);
623
624
		} else if (getBidiSupport()) {
625
			if (BTD_DEFAULT.equals(handlingType)) {
626
				if (LEFT_TO_RIGHT.equals(getTextDirection())) {
627
					return addUCC(string, false, handlingType);
628
				} else if (RIGHT_TO_LEFT.equals(getTextDirection())) {
629
					return addUCC(string, true, handlingType);
630
				} else if (AUTO.equals(getTextDirection())) {
631
					return addUCC(string, isRTLValue(string), handlingType);
632
				}
633
			} else if (VISUAL_LEFT_TO_RIGHT.equals(handlingType)) {
634
				return (InternalPolicy.DEBUG_BIDI_UTILS ? handlingType : "") + LRO + string + PDF; //$NON-NLS-1$
635
			} else if (VISUAL_RIGHT_TO_LEFT.equals(handlingType)) {
636
				return (InternalPolicy.DEBUG_BIDI_UTILS ? handlingType : "") + RLO + string + PDF; //$NON-NLS-1$
637
			} else {
638
				return StructuredTextProcessor.processTyped(string, handlingType);
639
			}
640
		}
641
		return string;
642
	}
643
644
	/**
645
	 * Strips off Unicode control characters from the given string.
646
	 *
647
	 *
648
	 * @param string
649
	 *            the string
650
	 * @return the bidi deprocessed string
651
	 */
652
	public static String deprocessBidi(String string) {
653
		String header1 = "" + LRM + LRE, header2 = "" + RLM + RLE; //$NON-NLS-1$ //$NON-NLS-2$
654
		String tailer1 = "" + LRM + PDF, tailer2 = "" + RLM + PDF; //$NON-NLS-1$ //$NON-NLS-2$
655
656
		if (InternalPolicy.DEBUG_BIDI_UTILS) {
657
			string = string.replaceFirst(LEFT_TO_RIGHT, "").replaceFirst(RIGHT_TO_LEFT, "").replaceFirst(AUTO, "") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
658
					.replaceFirst(BTD_DEFAULT, "").replaceFirst(VISUAL_LEFT_TO_RIGHT, "") //$NON-NLS-1$ //$NON-NLS-2$
659
					.replaceFirst(VISUAL_RIGHT_TO_LEFT, ""); //$NON-NLS-1$
660
		}
661
		if ((string.startsWith(header1) && string.endsWith(tailer1))
662
				|| (string.startsWith(header2) && string.endsWith(tailer2))) {
663
			return string.substring(2, string.length() - 2);
664
		} else if ((string.charAt(0) == LRO || string.charAt(0) == RLO) && string.charAt(string.length() - 1) == PDF) {
665
			return string.substring(1, string.length() - 1);
666
		}
667
		return string;
668
	}
669
670
	/**
671
	 * Applies bidi processing for formatting messages. <strong>Note:</strong>
672
	 * The number of arguments in <code>params</code> should always be even and
673
	 * greater than 0. Each pair is composed of the string to bidi process and
674
	 * the type of handling as specified in
675
	 * {@link #applyBidiProcessing(Text, String)}. If the number of arguments is
676
	 * odd no bidi processing will occur.
677
	 * </p>
678
	 *
679
	 * @param typeOfContext
680
	 *            message with placeholders or concatenation ?
681
	 * @param params
682
	 *            unlimited number of arguments associated with either
683
	 *            placeholders or concatenated strings. It is always even number
684
	 *            since for each placeholder / piece of text, we need to specify
685
	 *            which type of handling is required (i.e. text direction
686
	 *            enforcement, structured text, no handling).
687
	 * @return the bidi processed placeholders or the concatenated string.
688
	 */
689
	public static Object[] applyBidiProcessing(PROCESSING_TYPE typeOfContext, Object... params) {
690
		if (typeOfContext == PROCESSING_TYPE.MESSAGEWITHPLACEHOLDERS) {
691
			char prefix = isBidiLocale() ? RLM : LRM;
692
			return applyBidiProcessing(prefix, params);
693
		} else if (typeOfContext == PROCESSING_TYPE.CONCATENATION) {
694
			char prefix = Window.getDefaultOrientation() == SWT.RIGHT_TO_LEFT ? RLM : LRM;
695
			Object[] results = applyBidiProcessing(prefix, params);
696
			StringBuffer sb = new StringBuffer();
697
			for (int i = 0; i < results.length; i++) {
698
				sb.append(results[i]);
699
			}
700
			String[] result = new String[1];
701
			result[0] = sb.toString();
702
			return result;
703
		}
704
		return params;
705
	}
706
707
	private static Object[] applyBidiProcessing(char prefix, Object... params) {
708
709
		if (params.length == 0 || params.length % 2 == 1) {
710
			return params;
711
		}
712
		int numPlaceHolders = params.length / 2;
713
		Object[] results = new Object[numPlaceHolders];
714
		for (int i = 0; i < numPlaceHolders; i++) {
715
			results[i] = prefix + applyBidiProcessing(params[2 * i].toString(), params[2 * i + 1].toString());
716
		}
717
		return results;
718
	}
719
720
	private static String addUCC(String string, boolean isRTL, String handlingType) {
721
		StringBuffer sb = new StringBuffer();
722
		if (InternalPolicy.DEBUG_BIDI_UTILS) {
723
			sb.append(handlingType);
724
		}
725
		if (isRTL) {
726
			sb.append(RLM).append(RLE);
727
		} else {
728
			sb.append(LRM).append(LRE);
729
		}
730
		sb.append(string);
731
		if (isRTL) {
732
			sb.append(RLM);
733
		} else {
734
			sb.append(LRM);
735
		}
736
		sb.append(PDF);
737
		return sb.toString();
738
	}
739
740
	private static boolean isRTLValue(String stringValue) {
741
		for (int i = 0; i < stringValue.length(); i++) {
742
			if (Character.getDirectionality(stringValue.charAt(i)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT
743
					|| Character
744
							.getDirectionality(stringValue.charAt(i)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC
745
					|| Character.getDirectionality(stringValue.charAt(i)) == Character.DIRECTIONALITY_ARABIC_NUMBER)
746
				return true;
747
			else if (Character.getDirectionality(stringValue.charAt(i)) == Character.DIRECTIONALITY_LEFT_TO_RIGHT) {
748
				return false;
749
			}
750
		}
751
		return false;
752
	}
753
754
	private static boolean isBidiLocale() {
755
		Locale defaultLocale = Locale.getDefault();
756
		String language = defaultLocale.getLanguage();
757
		boolean isBidi = "iw".equals(language) || //$NON-NLS-1$
758
				"he".equals(language) || //$NON-NLS-1$
759
				"ar".equals(language) || //$NON-NLS-1$
760
				"fa".equals(language) || //$NON-NLS-1$
761
				"ur".equals(language); //$NON-NLS-1$
762
		return isBidi;
763
	}
764
765
}

Return to bug 466345