/*******************************************************************************
 * Copyright (c) 2000, 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.internal;


import java.util.Hashtable;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.widgets.*;
/*
 * Wraps Win32 API used to bidi enable the StyledText widget.
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class BidiUtil {

	// Keyboard language ids
	public static final int KEYBOARD_NON_BIDI = 0;
	public static final int KEYBOARD_BIDI = 1;

	// bidi flag
	static int isBidiPlatform = -1;

	// getRenderInfo flag values
	public static final int CLASSIN = 1;
	public static final int LINKBEFORE = 2;
	public static final int LINKAFTER = 4;

	// variables used for providing a listener mechanism for keyboard language 
	// switching 
	static Hashtable languageMap = new Hashtable ();
	static Hashtable keyMap = new Hashtable ();
	static Hashtable oldProcMap = new Hashtable ();
	/*
	 * This code is intentionally commented.  In order
	 * to support CLDC, .class cannot be used because
	 * it does not compile on some Java compilers when
	 * they are targeted for CLDC.
	 */
	//	static Callback callback = new Callback (BidiUtil.class, "windowProc", 4);
	static final String CLASS_NAME = "org.eclipse.swt.internal.BidiUtil"; //$NON-NLS-1$
	static Callback callback;
	static {
		try {
			callback = new Callback (Class.forName (CLASS_NAME), "windowProc", 4); //$NON-NLS-1$
			if (callback.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
		} catch (ClassNotFoundException e) {}
	}

	// GetCharacterPlacement constants
	static final int GCP_REORDER = 0x0002;
	static final int GCP_GLYPHSHAPE = 0x0010;
	static final int GCP_LIGATE = 0x0020;
	static final int GCP_CLASSIN = 0x00080000;
	static final byte GCPCLASS_ARABIC = 2;
	static final byte GCPCLASS_HEBREW = 2;	
	static final byte GCPCLASS_LOCALNUMBER = 4;
	static final byte GCPCLASS_LATINNUMBER = 5;
	static final int GCPGLYPH_LINKBEFORE = 0x8000;
	static final int GCPGLYPH_LINKAFTER = 0x4000;
	// ExtTextOut constants
	static final int ETO_CLIPPED = 0x4;
	static final int ETO_GLYPH_INDEX = 0x0010;
	// Windows primary language identifiers
	static final int LANG_ARABIC = 0x01;
	static final int LANG_HEBREW = 0x0d;
	static final int LANG_FARSI = 0x29;
	// code page identifiers
	static final String CD_PG_HEBREW = "1255"; //$NON-NLS-1$
	static final String CD_PG_ARABIC = "1256"; //$NON-NLS-1$
	// ActivateKeyboard constants
	static final int HKL_NEXT = 1;
	static final int HKL_PREV = 0;

	/*
	 * Public character class constants are the same as Windows 
	 * platform constants. 
	 * Saves conversion of class array in getRenderInfo to arbitrary 
	 * constants for now.
	 */
	public static final int CLASS_HEBREW = GCPCLASS_ARABIC;
	public static final int CLASS_ARABIC = GCPCLASS_HEBREW;
	public static final int CLASS_LOCALNUMBER = GCPCLASS_LOCALNUMBER;
	public static final int CLASS_LATINNUMBER = GCPCLASS_LATINNUMBER;
	public static final int REORDER = GCP_REORDER;				
	public static final int LIGATE = GCP_LIGATE;
	public static final int GLYPHSHAPE = GCP_GLYPHSHAPE;

/**
 * Adds a language listener. The listener will get notified when the language of
 * the keyboard changes (via Alt-Shift on Win platforms).  Do this by creating a 
 * window proc for the Control so that the window messages for the Control can be
 * monitored.
 * <p>
 *
 * @param hwnd the handle of the Control that is listening for keyboard language 
 *  changes
 * @param runnable the code that should be executed when a keyboard language change
 *  occurs
 */
public static void addLanguageListener (long /*int*/ hwnd, Runnable runnable) {
	languageMap.put(new LONG(hwnd), runnable);
	subclass(hwnd);
}
public static void addLanguageListener (Control control, Runnable runnable) {
	addLanguageListener(control.handle, runnable);
}
/**
 * Proc used for OS.EnumSystemLanguageGroups call during isBidiPlatform test.
 */
static long /*int*/ EnumSystemLanguageGroupsProc(long /*int*/ lpLangGrpId, long /*int*/ lpLangGrpIdString, long /*int*/ lpLangGrpName, long /*int*/ options, long /*int*/ lParam) {
	if ((int)/*64*/lpLangGrpId == OS.LGRPID_HEBREW) {
		isBidiPlatform = 1;
		return 0;
	}
	if ((int)/*64*/lpLangGrpId == OS.LGRPID_ARABIC) {
		isBidiPlatform = 1;
		return 0;
	}
	return 1;
} 
/**
 * Wraps the ExtTextOut function.
 * <p>
 *
 * @param gc the gc to use for rendering
 * @param renderBuffer the glyphs to render as an array of characters
 * @param renderDx the width of each glyph in renderBuffer
 * @param x x position to start rendering
 * @param y y position to start rendering
 */
public static void drawGlyphs(GC gc, char[] renderBuffer, int[] renderDx, int x, int y) {
	int length = renderDx.length;
	
	if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
		if (OS.GetLayout (gc.handle) != 0) {
			reverse(renderDx);
			renderDx[length-1]--;               //fixes bug 40006
			reverse(renderBuffer);
		}
	}	
	// render transparently to avoid overlapping segments. fixes bug 40006
	int oldBkMode = OS.SetBkMode(gc.handle, OS.TRANSPARENT);
	OS.ExtTextOutW(gc.handle, x, y, ETO_GLYPH_INDEX , null, renderBuffer, renderBuffer.length, renderDx);
	OS.SetBkMode(gc.handle, oldBkMode);
}
/**
 * Return ordering and rendering information for the given text.  Wraps the GetFontLanguageInfo
 * and GetCharacterPlacement functions.
 * <p>
 * 
 * @param gc the GC to use for measuring of this line, input parameter
 * @param text text that bidi data should be calculated for, input parameter
 * @param order an array of integers representing the visual position of each character in
 *  the text array, output parameter
 * @param classBuffer an array of integers representing the type (e.g., ARABIC, HEBREW, 
 *  LOCALNUMBER) of each character in the text array, input/output parameter
 * @param dx an array of integers representing the pixel width of each glyph in the returned
 *  glyph buffer, output parameter
 * @param flags an integer representing rendering flag information, input parameter
 * @param offsets text segments that should be measured and reordered separately, input 
 *  parameter. See org.eclipse.swt.custom.BidiSegmentEvent for details.
 * @return buffer with the glyphs that should be rendered for the given text
 */
public static char[] getRenderInfo(GC gc, String text, int[] order, byte[] classBuffer, int[] dx, int flags, int [] offsets) {
	int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
	long /*int*/ hHeap = OS.GetProcessHeap();
	int[] lpCs = new int[8];
	int cs = OS.GetTextCharset(gc.handle);
	boolean isRightOriented = false;
	if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
		isRightOriented = OS.GetLayout(gc.handle) != 0;
	} 
	OS.TranslateCharsetInfo(cs, lpCs, OS.TCI_SRCCHARSET);
	TCHAR textBuffer = new TCHAR(lpCs[1], text, false);
	int byteCount = textBuffer.length();
	boolean linkBefore = (flags & LINKBEFORE) == LINKBEFORE;
	boolean linkAfter = (flags & LINKAFTER) == LINKAFTER;

	GCP_RESULTS result = new GCP_RESULTS();
	result.lStructSize = GCP_RESULTS.sizeof;
	result.nGlyphs = byteCount;
	long /*int*/ lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
	long /*int*/ lpDx = result.lpDx = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
	long /*int*/ lpClass = result.lpClass = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
	long /*int*/ lpGlyphs = result.lpGlyphs = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 2);

	// set required dwFlags
	int dwFlags = 0;
	int glyphFlags = 0;
	// Always reorder.  We assume that if we are calling this function we're
	// on a platform that supports bidi.  Fixes 20690.
	dwFlags |= GCP_REORDER;
	if ((fontLanguageInfo & GCP_LIGATE) == GCP_LIGATE) {
		dwFlags |= GCP_LIGATE;
		glyphFlags |= 0;
	}
	if ((fontLanguageInfo & GCP_GLYPHSHAPE) == GCP_GLYPHSHAPE) {
		dwFlags |= GCP_GLYPHSHAPE;
		if (linkBefore) {
			glyphFlags |= GCPGLYPH_LINKBEFORE;
		}
		if (linkAfter) {
			glyphFlags |= GCPGLYPH_LINKAFTER;
		}
	}
	byte[] lpGlyphs2;
	if (linkBefore || linkAfter) {
		lpGlyphs2 = new byte[2];
		lpGlyphs2[0]=(byte)glyphFlags;
		lpGlyphs2[1]=(byte)(glyphFlags >> 8);
	}
	else {
		lpGlyphs2 = new byte[] {(byte) glyphFlags};
	}
	OS.MoveMemory(result.lpGlyphs, lpGlyphs2, lpGlyphs2.length);

	if ((flags & CLASSIN) == CLASSIN) {
		// set classification values for the substring
		dwFlags |= GCP_CLASSIN;
		OS.MoveMemory(result.lpClass, classBuffer, classBuffer.length);
	}

	char[] glyphBuffer = new char[result.nGlyphs];
	int glyphCount = 0;
	for (int i=0; i<offsets.length-1; i++) {
		int offset = offsets [i];
		int length = offsets [i+1] - offsets [i];

		// The number of glyphs expected is <= length (segment length);
		// the actual number returned may be less in case of Arabic ligatures.
		result.nGlyphs = length;
		TCHAR textBuffer2 = new TCHAR(lpCs[1], text.substring(offset, offset + length), false);
		OS.GetCharacterPlacement(gc.handle, textBuffer2, textBuffer2.length(), 0, result, dwFlags);

		if (dx != null) {
			int [] dx2 = new int [result.nGlyphs];
			OS.MoveMemory(dx2, result.lpDx, dx2.length * 4);
			if (isRightOriented) { 
				reverse(dx2);
			} 
			System.arraycopy (dx2, 0, dx, glyphCount, dx2.length);
		}
		if (order != null) {
			int [] order2 = new int [length];
			OS.MoveMemory(order2, result.lpOrder, order2.length * 4);
			translateOrder(order2, glyphCount, isRightOriented);
			System.arraycopy (order2, 0, order, offset, length);
		}
		if (classBuffer != null) {
			byte [] classBuffer2 = new byte [length];
			OS.MoveMemory(classBuffer2, result.lpClass, classBuffer2.length);
			System.arraycopy (classBuffer2, 0, classBuffer, offset, length);
		}
		char[] glyphBuffer2 = new char[result.nGlyphs];
		OS.MoveMemory(glyphBuffer2, result.lpGlyphs, glyphBuffer2.length * 2);
		if (isRightOriented) {
			reverse(glyphBuffer2);
		} 
		System.arraycopy (glyphBuffer2, 0, glyphBuffer, glyphCount, glyphBuffer2.length);
		glyphCount += glyphBuffer2.length;

		// We concatenate successive results of calls to GCP.
		// For Arabic, it is the only good method since the number of output
		// glyphs might be less than the number of input characters.
		// This assumes that the whole line is built by successive adjacent
		// segments without overlapping.
		result.lpOrder += length * 4;
		result.lpDx += length * 4;
		result.lpClass += length;
		result.lpGlyphs += glyphBuffer2.length * 2;
	}

	/* Free the memory that was allocated. */
	OS.HeapFree(hHeap, 0, lpGlyphs);
	OS.HeapFree(hHeap, 0, lpClass);
	OS.HeapFree(hHeap, 0, lpDx);
	OS.HeapFree(hHeap, 0, lpOrder);
	return glyphBuffer;
}
/**
 * Return bidi ordering information for the given text.  Does not return rendering 
 * information (e.g., glyphs, glyph distances).  Use this method when you only need 
 * ordering information.  Doing so will improve performance.  Wraps the 
 * GetFontLanguageInfo and GetCharacterPlacement functions.
 * <p>
 * 
 * @param gc the GC to use for measuring of this line, input parameter
 * @param text text that bidi data should be calculated for, input parameter
 * @param order an array of integers representing the visual position of each character in
 *  the text array, output parameter
 * @param classBuffer an array of integers representing the type (e.g., ARABIC, HEBREW, 
 *  LOCALNUMBER) of each character in the text array, input/output parameter
 * @param flags an integer representing rendering flag information, input parameter
 * @param offsets text segments that should be measured and reordered separately, input 
 *  parameter. See org.eclipse.swt.custom.BidiSegmentEvent for details.
 */
public static void getOrderInfo(GC gc, String text, int[] order, byte[] classBuffer, int flags, int [] offsets) {
	int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
	long /*int*/ hHeap = OS.GetProcessHeap();
	int[] lpCs = new int[8];
	int cs = OS.GetTextCharset(gc.handle);
	OS.TranslateCharsetInfo(cs, lpCs, OS.TCI_SRCCHARSET);
	TCHAR textBuffer = new TCHAR(lpCs[1], text, false);
	int byteCount = textBuffer.length();
	boolean isRightOriented = false;
	if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
		isRightOriented = OS.GetLayout(gc.handle) != 0;
	} 

	GCP_RESULTS result = new GCP_RESULTS();
	result.lStructSize = GCP_RESULTS.sizeof;
	result.nGlyphs = byteCount;
	long /*int*/ lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
	long /*int*/ lpClass = result.lpClass = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);

	// set required dwFlags, these values will affect how the text gets rendered and
	// ordered
	int dwFlags = 0;
	// Always reorder.  We assume that if we are calling this function we're
	// on a platform that supports bidi.  Fixes 20690.
	dwFlags |= GCP_REORDER;
	if ((fontLanguageInfo & GCP_LIGATE) == GCP_LIGATE) {
		dwFlags |= GCP_LIGATE;
	}
	if ((fontLanguageInfo & GCP_GLYPHSHAPE) == GCP_GLYPHSHAPE) {
		dwFlags |= GCP_GLYPHSHAPE;
	}
	if ((flags & CLASSIN) == CLASSIN) {
		// set classification values for the substring, classification values
		// can be specified on input
		dwFlags |= GCP_CLASSIN;
		OS.MoveMemory(result.lpClass, classBuffer, classBuffer.length);
	}

	int glyphCount = 0;
	for (int i=0; i<offsets.length-1; i++) {
		int offset = offsets [i];
		int length = offsets [i+1] - offsets [i];
		// The number of glyphs expected is <= length (segment length);
		// the actual number returned may be less in case of Arabic ligatures.
		result.nGlyphs = length;
		TCHAR textBuffer2 = new TCHAR(lpCs[1], text.substring(offset, offset + length), false);
		OS.GetCharacterPlacement(gc.handle, textBuffer2, textBuffer2.length(), 0, result, dwFlags);

		if (order != null) {
			int [] order2 = new int [length];
			OS.MoveMemory(order2, result.lpOrder, order2.length * 4);
			translateOrder(order2, glyphCount, isRightOriented);
			System.arraycopy (order2, 0, order, offset, length);
		}
		if (classBuffer != null) {
			byte [] classBuffer2 = new byte [length];
			OS.MoveMemory(classBuffer2, result.lpClass, classBuffer2.length);
			System.arraycopy (classBuffer2, 0, classBuffer, offset, length);
		}
		glyphCount += result.nGlyphs;

		// We concatenate successive results of calls to GCP.
		// For Arabic, it is the only good method since the number of output
		// glyphs might be less than the number of input characters.
		// This assumes that the whole line is built by successive adjacent
		// segments without overlapping.
		result.lpOrder += length * 4;
		result.lpClass += length;
	}

	/* Free the memory that was allocated. */
	OS.HeapFree(hHeap, 0, lpClass);
	OS.HeapFree(hHeap, 0, lpOrder);
}
/**
 * Return bidi attribute information for the font in the specified gc.  
 * <p>
 *
 * @param gc the gc to query
 * @return bitwise OR of the REORDER, LIGATE and GLYPHSHAPE flags
 * 	defined by this class.
 */
public static int getFontBidiAttributes(GC gc) {
	int fontStyle = 0;
	int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
	if (((fontLanguageInfo & GCP_REORDER) != 0)) {
		fontStyle |= REORDER;
	}
	if (((fontLanguageInfo & GCP_LIGATE) != 0)) {
		fontStyle |= LIGATE;
	}
	if (((fontLanguageInfo & GCP_GLYPHSHAPE) != 0)) {
		fontStyle |= GLYPHSHAPE;
	}
	return fontStyle;	
}
/**
 * Return the active keyboard language type.  
 * <p>
 *
 * @return an integer representing the active keyboard language (KEYBOARD_BIDI,
 *  KEYBOARD_NON_BIDI)
 */
public static int getKeyboardLanguage() {
	long /*int*/ layout = OS.GetKeyboardLayout(0);
	return isBidiLang(layout) ? KEYBOARD_BIDI : KEYBOARD_NON_BIDI;
}
/**
 * Return the languages that are installed for the keyboard.  
 * <p>
 *
 * @return integer array with an entry for each installed language
 */
static long /*int*/[] getKeyboardLanguageList() {
	int maxSize = 10;
	long /*int*/[] tempList = new long /*int*/[maxSize];
	int size = OS.GetKeyboardLayoutList(maxSize, tempList);
	long /*int*/[] list = new long /*int*/[size];
	System.arraycopy(tempList, 0, list, 0, size);
	return list;
}
static boolean isBidiLang(long /*int*/ lang) {
	int id = OS.PRIMARYLANGID(OS.LOWORD(lang));
	return id == LANG_ARABIC || id == LANG_HEBREW || id == LANG_FARSI;
}
/**
 * Return whether or not the platform supports a bidi language.  Determine this
 * by looking at the languages that are installed.  
 * <p>
 *
 * @return true if bidi is supported, false otherwise. Always 
 * 	false on Windows CE.
 */
public static boolean isBidiPlatform() {
	if (OS.IsWinCE) return false;
	if (isBidiPlatform != -1) return isBidiPlatform == 1; // already set

	isBidiPlatform = 0;
	
	// The following test is a workaround for bug report 27629. On WinXP,
	// both bidi and complex script (e.g., Thai) languages must be installed
	// at the same time.  Since the bidi platform calls do not support
	// double byte characters, there is no way to run Eclipse using the
	// complex script languages on XP, so constrain this test to answer true
	// only if a bidi input language is defined.  Doing so will allow complex
	// script languages to work (e.g., one can install bidi and complex script 
	// languages, but only install the Thai keyboard).
	if (!isKeyboardBidi()) return false;
	
	Callback callback = null;
	try {
		callback = new Callback (Class.forName (CLASS_NAME), "EnumSystemLanguageGroupsProc", 5); //$NON-NLS-1$
		long /*int*/ lpEnumSystemLanguageGroupsProc = callback.getAddress ();	
		if (lpEnumSystemLanguageGroupsProc == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
		OS.EnumSystemLanguageGroups(lpEnumSystemLanguageGroupsProc, OS.LGRPID_INSTALLED, 0);
		callback.dispose ();
	} catch (ClassNotFoundException e) {
		//callback can only be null at this point
	}
	if (isBidiPlatform == 1) return true;
	// need to look at system code page for NT & 98 platforms since EnumSystemLanguageGroups is
	// not supported for these platforms
	String codePage = String.valueOf(OS.GetACP());
	if (CD_PG_ARABIC.equals(codePage) || CD_PG_HEBREW.equals(codePage)) {
		isBidiPlatform = 1;
	}
	return isBidiPlatform == 1;
}
/**
 * Return whether or not the keyboard supports input of a bidi language.  Determine this
 * by looking at the languages that are installed for the keyboard.  
 * <p>
 *
 * @return true if bidi is supported, false otherwise.
 */
public static boolean isKeyboardBidi() {
	long /*int*/[] list = getKeyboardLanguageList();
	for (int i=0; i<list.length; i++) {
		if (isBidiLang(list[i])) {
			return true;
		}
	}
	return false;
}
/**
 * Removes the specified language listener.
 * <p>
 *
 * @param hwnd the handle of the Control that is listening for keyboard language changes
 */
public static void removeLanguageListener (long /*int*/ hwnd) {
	languageMap.remove(new LONG(hwnd));
	unsubclass(hwnd);
}
public static void removeLanguageListener (Control control) {
	removeLanguageListener(control.handle);
}
/**
 * Switch the keyboard language to the specified language type.  We do
 * not distinguish between multiple bidi or multiple non-bidi languages, so
 * set the keyboard to the first language of the given type.
 * <p>
 *
 * @param language integer representing language. One of 
 * 	KEYBOARD_BIDI, KEYBOARD_NON_BIDI.
 */
public static void setKeyboardLanguage(int language) {
	if (language == getKeyboardLanguage()) return;
	boolean bidi = language == KEYBOARD_BIDI; 
	long /*int*/[] list = getKeyboardLanguageList();
	for (int i=0; i<list.length; i++) {
		if (bidi == isBidiLang(list[i])) {
			OS.ActivateKeyboardLayout(list[i], 0);
			return;
		}
	}
}
/**
 * Sets the orientation (writing order) of the specified control. Text will 
 * be right aligned for right to left writing order.
 * <p>
 * 
 * @param hwnd the handle of the Control to change the orientation of
 * @param orientation one of SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
 * @return true if the orientation was changed, false if the orientation 
 * 	could not be changed
 */
public static boolean setOrientation (long /*int*/ hwnd, int orientation) {
	if (OS.IsWinCE) return false;
	if (OS.WIN32_VERSION < OS.VERSION(4, 10)) return false;
	int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
	if ((orientation & SWT.RIGHT_TO_LEFT) != 0) {
		bits |= OS.WS_EX_LAYOUTRTL; 
	} else {
		bits &= ~OS.WS_EX_LAYOUTRTL;
	} 
	OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits);
	return true;
}
public static boolean setOrientation (Control control, int orientation) {
	return setOrientation(control.handle, orientation);
}
/**
 * Override the window proc.
 * 
 * @param hwnd control to override the window proc of
 */
static void subclass(long /*int*/ hwnd) {
	LONG key = new LONG(hwnd);
	if (oldProcMap.get(key) == null) {
		long /*int*/ oldProc = OS.GetWindowLongPtr(hwnd, OS.GWLP_WNDPROC);
		oldProcMap.put(key, new LONG(oldProc));
		OS.SetWindowLongPtr(hwnd, OS.GWLP_WNDPROC, callback.getAddress());
	}
}
/**
 *  Reverse the character array.  Used for right orientation.
 * 
 * @param charArray character array to reverse
 */
static void reverse(char[] charArray) {
	int length = charArray.length;
	for (int i = 0; i <= (length  - 1) / 2; i++) {
		char tmp = charArray[i];
		charArray[i] = charArray[length - 1 - i];
		charArray[length - 1 - i] = tmp;
	}
}	
/**
 *  Reverse the integer array.  Used for right orientation.
 * 
 * @param intArray integer array to reverse
 */
static void reverse(int[] intArray) {
	int length = intArray.length;
	for (int i = 0; i <= (length  - 1) / 2; i++) {
		int tmp = intArray[i];
		intArray[i] = intArray[length - 1 - i];
		intArray[length - 1 - i] = tmp;
	}
}	
/**
 * Adjust the order array so that it is relative to the start of the line.  Also reverse the order array if the orientation
 * is to the right.
 * 
 * @param orderArray  integer array of order values to translate
 * @param glyphCount  number of glyphs that have been processed for the current line
 * @param isRightOriented  flag indicating whether or not current orientation is to the right
*/
static void translateOrder(int[] orderArray, int glyphCount, boolean isRightOriented) {
	int maxOrder = 0;
	int length = orderArray.length;
	if (isRightOriented) {  
		for (int i=0; i<length; i++) {
			maxOrder = Math.max(maxOrder, orderArray[i]);
		}	
	} 
	for (int i=0; i<length; i++) {
		if (isRightOriented) orderArray[i] = maxOrder - orderArray[i]; 
		orderArray [i] += glyphCount;
	}
}
/**
 * Remove the overridden the window proc.
 * 
 * @param hwnd control to remove the window proc override for
 */
static void unsubclass(long /*int*/ hwnd) {
	LONG key = new LONG(hwnd);
	if (languageMap.get(key) == null && keyMap.get(key) == null) {
		LONG proc = (LONG) oldProcMap.remove(key);
		if (proc == null) return;
		OS.SetWindowLongPtr(hwnd, OS.GWLP_WNDPROC, proc.value);
	}	
}
/**
 * Window proc to intercept keyboard language switch event (WS_INPUTLANGCHANGE)
 * and widget orientation changes.
 * Run the Control's registered runnable when the keyboard language is switched.
 * 
 * @param hwnd handle of the control that is listening for the keyboard language
 *  change event
 * @param msg window message
 */
static long /*int*/ windowProc (long /*int*/ hwnd, long /*int*/ msg, long /*int*/ wParam, long /*int*/ lParam) {
	LONG key = new LONG (hwnd);
	switch ((int)/*64*/msg) {
		case OS.WM_INPUTLANGCHANGE:
			Runnable runnable = (Runnable) languageMap.get (key);
			if (runnable != null) runnable.run ();
			break;
		}
	LONG oldProc = (LONG)oldProcMap.get(key);
	return OS.CallWindowProc (oldProc.value, hwnd, (int)/*64*/msg, wParam, lParam);
}

}
