KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > internal > BidiUtil


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.internal;
12
13
14 import java.util.Hashtable JavaDoc;
15
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.graphics.GC;
18 import org.eclipse.swt.internal.win32.*;
19 /*
20  * Wraps Win32 API used to bidi enable the StyledText widget.
21  */

22 public class BidiUtil {
23
24     // Keyboard language ids
25
public static final int KEYBOARD_NON_BIDI = 0;
26     public static final int KEYBOARD_BIDI = 1;
27
28     // bidi flag
29
static int isBidiPlatform = -1;
30
31     // getRenderInfo flag values
32
public static final int CLASSIN = 1;
33     public static final int LINKBEFORE = 2;
34     public static final int LINKAFTER = 4;
35
36     // variables used for providing a listener mechanism for keyboard language
37
// switching
38
static Hashtable JavaDoc languageMap = new Hashtable JavaDoc ();
39     static Hashtable JavaDoc keyMap = new Hashtable JavaDoc ();
40     static Hashtable JavaDoc oldProcMap = new Hashtable JavaDoc ();
41     /*
42      * This code is intentionally commented. In order
43      * to support CLDC, .class cannot be used because
44      * it does not compile on some Java compilers when
45      * they are targeted for CLDC.
46      */

47     // static Callback callback = new Callback (BidiUtil.class, "windowProc", 4);
48
static final String JavaDoc CLASS_NAME = "org.eclipse.swt.internal.BidiUtil"; //$NON-NLS-1$
49
static Callback callback;
50     static {
51         try {
52             callback = new Callback (Class.forName (CLASS_NAME), "windowProc", 4); //$NON-NLS-1$
53
if (callback.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
54         } catch (ClassNotFoundException JavaDoc e) {}
55     }
56
57     // GetCharacterPlacement constants
58
static final int GCP_REORDER = 0x0002;
59     static final int GCP_GLYPHSHAPE = 0x0010;
60     static final int GCP_LIGATE = 0x0020;
61     static final int GCP_CLASSIN = 0x00080000;
62     static final byte GCPCLASS_ARABIC = 2;
63     static final byte GCPCLASS_HEBREW = 2;
64     static final byte GCPCLASS_LOCALNUMBER = 4;
65     static final byte GCPCLASS_LATINNUMBER = 5;
66     static final int GCPGLYPH_LINKBEFORE = 0x8000;
67     static final int GCPGLYPH_LINKAFTER = 0x4000;
68     // ExtTextOut constants
69
static final int ETO_CLIPPED = 0x4;
70     static final int ETO_GLYPH_INDEX = 0x0010;
71     // Windows primary language identifiers
72
static final int LANG_ARABIC = 0x01;
73     static final int LANG_HEBREW = 0x0d;
74     // code page identifiers
75
static final String JavaDoc CD_PG_HEBREW = "1255"; //$NON-NLS-1$
76
static final String JavaDoc CD_PG_ARABIC = "1256"; //$NON-NLS-1$
77
// ActivateKeyboard constants
78
static final int HKL_NEXT = 1;
79     static final int HKL_PREV = 0;
80
81     /*
82      * Public character class constants are the same as Windows
83      * platform constants.
84      * Saves conversion of class array in getRenderInfo to arbitrary
85      * constants for now.
86      */

87     public static final int CLASS_HEBREW = GCPCLASS_ARABIC;
88     public static final int CLASS_ARABIC = GCPCLASS_HEBREW;
89     public static final int CLASS_LOCALNUMBER = GCPCLASS_LOCALNUMBER;
90     public static final int CLASS_LATINNUMBER = GCPCLASS_LATINNUMBER;
91     public static final int REORDER = GCP_REORDER;
92     public static final int LIGATE = GCP_LIGATE;
93     public static final int GLYPHSHAPE = GCP_GLYPHSHAPE;
94
95 /**
96  * Adds a language listener. The listener will get notified when the language of
97  * the keyboard changes (via Alt-Shift on Win platforms). Do this by creating a
98  * window proc for the Control so that the window messages for the Control can be
99  * monitored.
100  * <p>
101  *
102  * @param hwnd the handle of the Control that is listening for keyboard language
103  * changes
104  * @param runnable the code that should be executed when a keyboard language change
105  * occurs
106  */

107 public static void addLanguageListener (int hwnd, Runnable JavaDoc runnable) {
108     languageMap.put(new Integer JavaDoc(hwnd), runnable);
109     subclass(hwnd);
110 }
111 /**
112  * Proc used for OS.EnumSystemLanguageGroups call during isBidiPlatform test.
113  */

114 static int EnumSystemLanguageGroupsProc(int lpLangGrpId, int lpLangGrpIdString, int lpLangGrpName, int options, int lParam) {
115     if (lpLangGrpId == OS.LGRPID_HEBREW) {
116         isBidiPlatform = 1;
117         return 0;
118     }
119     if (lpLangGrpId == OS.LGRPID_ARABIC) {
120         isBidiPlatform = 1;
121         return 0;
122     }
123     return 1;
124 }
125 /**
126  * Wraps the ExtTextOut function.
127  * <p>
128  *
129  * @param gc the gc to use for rendering
130  * @param renderBuffer the glyphs to render as an array of characters
131  * @param renderDx the width of each glyph in renderBuffer
132  * @param x x position to start rendering
133  * @param y y position to start rendering
134  */

135 public static void drawGlyphs(GC gc, char[] renderBuffer, int[] renderDx, int x, int y) {
136     int length = renderDx.length;
137     
138     if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
139         if (OS.GetLayout (gc.handle) != 0) {
140             reverse(renderDx);
141             renderDx[length-1]--; //fixes bug 40006
142
reverse(renderBuffer);
143         }
144     }
145     // render transparently to avoid overlapping segments. fixes bug 40006
146
int oldBkMode = OS.SetBkMode(gc.handle, OS.TRANSPARENT);
147     OS.ExtTextOutW(gc.handle, x, y, ETO_GLYPH_INDEX , null, renderBuffer, renderBuffer.length, renderDx);
148     OS.SetBkMode(gc.handle, oldBkMode);
149 }
150 /**
151  * Return ordering and rendering information for the given text. Wraps the GetFontLanguageInfo
152  * and GetCharacterPlacement functions.
153  * <p>
154  *
155  * @param gc the GC to use for measuring of this line, input parameter
156  * @param text text that bidi data should be calculated for, input parameter
157  * @param order an array of integers representing the visual position of each character in
158  * the text array, output parameter
159  * @param classBuffer an array of integers representing the type (e.g., ARABIC, HEBREW,
160  * LOCALNUMBER) of each character in the text array, input/output parameter
161  * @param dx an array of integers representing the pixel width of each glyph in the returned
162  * glyph buffer, output parameter
163  * @param flags an integer representing rendering flag information, input parameter
164  * @param offsets text segments that should be measured and reordered separately, input
165  * parameter. See org.eclipse.swt.custom.BidiSegmentEvent for details.
166  * @return buffer with the glyphs that should be rendered for the given text
167  */

168 public static char[] getRenderInfo(GC gc, String JavaDoc text, int[] order, byte[] classBuffer, int[] dx, int flags, int [] offsets) {
169     int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
170     int hHeap = OS.GetProcessHeap();
171     int[] lpCs = new int[8];
172     int cs = OS.GetTextCharset(gc.handle);
173     boolean isRightOriented = false;
174     if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
175         isRightOriented = OS.GetLayout(gc.handle) != 0;
176     }
177     OS.TranslateCharsetInfo(cs, lpCs, OS.TCI_SRCCHARSET);
178     TCHAR textBuffer = new TCHAR(lpCs[1], text, false);
179     int byteCount = textBuffer.length();
180     boolean linkBefore = (flags & LINKBEFORE) == LINKBEFORE;
181     boolean linkAfter = (flags & LINKAFTER) == LINKAFTER;
182
183     GCP_RESULTS result = new GCP_RESULTS();
184     result.lStructSize = GCP_RESULTS.sizeof;
185     result.nGlyphs = byteCount;
186     int lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
187     int lpDx = result.lpDx = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
188     int lpClass = result.lpClass = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
189     int lpGlyphs = result.lpGlyphs = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 2);
190
191     // set required dwFlags
192
int dwFlags = 0;
193     int glyphFlags = 0;
194     // Always reorder. We assume that if we are calling this function we're
195
// on a platform that supports bidi. Fixes 20690.
196
dwFlags |= GCP_REORDER;
197     if ((fontLanguageInfo & GCP_LIGATE) == GCP_LIGATE) {
198         dwFlags |= GCP_LIGATE;
199         glyphFlags |= 0;
200     }
201     if ((fontLanguageInfo & GCP_GLYPHSHAPE) == GCP_GLYPHSHAPE) {
202         dwFlags |= GCP_GLYPHSHAPE;
203         if (linkBefore) {
204             glyphFlags |= GCPGLYPH_LINKBEFORE;
205         }
206         if (linkAfter) {
207             glyphFlags |= GCPGLYPH_LINKAFTER;
208         }
209     }
210     byte[] lpGlyphs2;
211     if (linkBefore || linkAfter) {
212         lpGlyphs2 = new byte[2];
213         lpGlyphs2[0]=(byte)glyphFlags;
214         lpGlyphs2[1]=(byte)(glyphFlags >> 8);
215     }
216     else {
217         lpGlyphs2 = new byte[] {(byte) glyphFlags};
218     }
219     OS.MoveMemory(result.lpGlyphs, lpGlyphs2, lpGlyphs2.length);
220
221     if ((flags & CLASSIN) == CLASSIN) {
222         // set classification values for the substring
223
dwFlags |= GCP_CLASSIN;
224         OS.MoveMemory(result.lpClass, classBuffer, classBuffer.length);
225     }
226
227     char[] glyphBuffer = new char[result.nGlyphs];
228     int glyphCount = 0;
229     for (int i=0; i<offsets.length-1; i++) {
230         int offset = offsets [i];
231         int length = offsets [i+1] - offsets [i];
232
233         // The number of glyphs expected is <= length (segment length);
234
// the actual number returned may be less in case of Arabic ligatures.
235
result.nGlyphs = length;
236         TCHAR textBuffer2 = new TCHAR(lpCs[1], text.substring(offset, offset + length), false);
237         OS.GetCharacterPlacement(gc.handle, textBuffer2, textBuffer2.length(), 0, result, dwFlags);
238
239         if (dx != null) {
240             int [] dx2 = new int [result.nGlyphs];
241             OS.MoveMemory(dx2, result.lpDx, dx2.length * 4);
242             if (isRightOriented) {
243                 reverse(dx2);
244             }
245             System.arraycopy (dx2, 0, dx, glyphCount, dx2.length);
246         }
247         if (order != null) {
248             int [] order2 = new int [length];
249             OS.MoveMemory(order2, result.lpOrder, order2.length * 4);
250             translateOrder(order2, glyphCount, isRightOriented);
251             System.arraycopy (order2, 0, order, offset, length);
252         }
253         if (classBuffer != null) {
254             byte [] classBuffer2 = new byte [length];
255             OS.MoveMemory(classBuffer2, result.lpClass, classBuffer2.length);
256             System.arraycopy (classBuffer2, 0, classBuffer, offset, length);
257         }
258         char[] glyphBuffer2 = new char[result.nGlyphs];
259         OS.MoveMemory(glyphBuffer2, result.lpGlyphs, glyphBuffer2.length * 2);
260         if (isRightOriented) {
261             reverse(glyphBuffer2);
262         }
263         System.arraycopy (glyphBuffer2, 0, glyphBuffer, glyphCount, glyphBuffer2.length);
264         glyphCount += glyphBuffer2.length;
265
266         // We concatenate successive results of calls to GCP.
267
// For Arabic, it is the only good method since the number of output
268
// glyphs might be less than the number of input characters.
269
// This assumes that the whole line is built by successive adjacent
270
// segments without overlapping.
271
result.lpOrder += length * 4;
272         result.lpDx += length * 4;
273         result.lpClass += length;
274         result.lpGlyphs += glyphBuffer2.length * 2;
275     }
276
277     /* Free the memory that was allocated. */
278     OS.HeapFree(hHeap, 0, lpGlyphs);
279     OS.HeapFree(hHeap, 0, lpClass);
280     OS.HeapFree(hHeap, 0, lpDx);
281     OS.HeapFree(hHeap, 0, lpOrder);
282     return glyphBuffer;
283 }
284 /**
285  * Return bidi ordering information for the given text. Does not return rendering
286  * information (e.g., glyphs, glyph distances). Use this method when you only need
287  * ordering information. Doing so will improve performance. Wraps the
288  * GetFontLanguageInfo and GetCharacterPlacement functions.
289  * <p>
290  *
291  * @param gc the GC to use for measuring of this line, input parameter
292  * @param text text that bidi data should be calculated for, input parameter
293  * @param order an array of integers representing the visual position of each character in
294  * the text array, output parameter
295  * @param classBuffer an array of integers representing the type (e.g., ARABIC, HEBREW,
296  * LOCALNUMBER) of each character in the text array, input/output parameter
297  * @param flags an integer representing rendering flag information, input parameter
298  * @param offsets text segments that should be measured and reordered separately, input
299  * parameter. See org.eclipse.swt.custom.BidiSegmentEvent for details.
300  */

301 public static void getOrderInfo(GC gc, String JavaDoc text, int[] order, byte[] classBuffer, int flags, int [] offsets) {
302     int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
303     int hHeap = OS.GetProcessHeap();
304     int[] lpCs = new int[8];
305     int cs = OS.GetTextCharset(gc.handle);
306     OS.TranslateCharsetInfo(cs, lpCs, OS.TCI_SRCCHARSET);
307     TCHAR textBuffer = new TCHAR(lpCs[1], text, false);
308     int byteCount = textBuffer.length();
309     boolean isRightOriented = false;
310     if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
311         isRightOriented = OS.GetLayout(gc.handle) != 0;
312     }
313
314     GCP_RESULTS result = new GCP_RESULTS();
315     result.lStructSize = GCP_RESULTS.sizeof;
316     result.nGlyphs = byteCount;
317     int lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
318     int lpClass = result.lpClass = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
319
320     // set required dwFlags, these values will affect how the text gets rendered and
321
// ordered
322
int dwFlags = 0;
323     // Always reorder. We assume that if we are calling this function we're
324
// on a platform that supports bidi. Fixes 20690.
325
dwFlags |= GCP_REORDER;
326     if ((fontLanguageInfo & GCP_LIGATE) == GCP_LIGATE) {
327         dwFlags |= GCP_LIGATE;
328     }
329     if ((fontLanguageInfo & GCP_GLYPHSHAPE) == GCP_GLYPHSHAPE) {
330         dwFlags |= GCP_GLYPHSHAPE;
331     }
332     if ((flags & CLASSIN) == CLASSIN) {
333         // set classification values for the substring, classification values
334
// can be specified on input
335
dwFlags |= GCP_CLASSIN;
336         OS.MoveMemory(result.lpClass, classBuffer, classBuffer.length);
337     }
338
339     int glyphCount = 0;
340     for (int i=0; i<offsets.length-1; i++) {
341         int offset = offsets [i];
342         int length = offsets [i+1] - offsets [i];
343         // The number of glyphs expected is <= length (segment length);
344
// the actual number returned may be less in case of Arabic ligatures.
345
result.nGlyphs = length;
346         TCHAR textBuffer2 = new TCHAR(lpCs[1], text.substring(offset, offset + length), false);
347         OS.GetCharacterPlacement(gc.handle, textBuffer2, textBuffer2.length(), 0, result, dwFlags);
348
349         if (order != null) {
350             int [] order2 = new int [length];
351             OS.MoveMemory(order2, result.lpOrder, order2.length * 4);
352             translateOrder(order2, glyphCount, isRightOriented);
353             System.arraycopy (order2, 0, order, offset, length);
354         }
355         if (classBuffer != null) {
356             byte [] classBuffer2 = new byte [length];
357             OS.MoveMemory(classBuffer2, result.lpClass, classBuffer2.length);
358             System.arraycopy (classBuffer2, 0, classBuffer, offset, length);
359         }
360         glyphCount += result.nGlyphs;
361
362         // We concatenate successive results of calls to GCP.
363
// For Arabic, it is the only good method since the number of output
364
// glyphs might be less than the number of input characters.
365
// This assumes that the whole line is built by successive adjacent
366
// segments without overlapping.
367
result.lpOrder += length * 4;
368         result.lpClass += length;
369     }
370
371     /* Free the memory that was allocated. */
372     OS.HeapFree(hHeap, 0, lpClass);
373     OS.HeapFree(hHeap, 0, lpOrder);
374 }
375 /**
376  * Return bidi attribute information for the font in the specified gc.
377  * <p>
378  *
379  * @param gc the gc to query
380  * @return bitwise OR of the REORDER, LIGATE and GLYPHSHAPE flags
381  * defined by this class.
382  */

383 public static int getFontBidiAttributes(GC gc) {
384     int fontStyle = 0;
385     int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
386     if (((fontLanguageInfo & GCP_REORDER) != 0)) {
387         fontStyle |= REORDER;
388     }
389     if (((fontLanguageInfo & GCP_LIGATE) != 0)) {
390         fontStyle |= LIGATE;
391     }
392     if (((fontLanguageInfo & GCP_GLYPHSHAPE) != 0)) {
393         fontStyle |= GLYPHSHAPE;
394     }
395     return fontStyle;
396 }
397 /**
398  * Return the active keyboard language type.
399  * <p>
400  *
401  * @return an integer representing the active keyboard language (KEYBOARD_BIDI,
402  * KEYBOARD_NON_BIDI)
403  */

404 public static int getKeyboardLanguage() {
405     int layout = OS.GetKeyboardLayout(0);
406     // only interested in low 2 bytes, which is the primary
407
// language identifier
408
layout = layout & 0x000000FF;
409     if (layout == LANG_HEBREW) return KEYBOARD_BIDI;
410     if (layout == LANG_ARABIC) return KEYBOARD_BIDI;
411     // return non-bidi for all other languages
412
return KEYBOARD_NON_BIDI;
413 }
414 /**
415  * Return the languages that are installed for the keyboard.
416  * <p>
417  *
418  * @return integer array with an entry for each installed language
419  */

420 static int[] getKeyboardLanguageList() {
421     int maxSize = 10;
422     int[] tempList = new int[maxSize];
423     int size = OS.GetKeyboardLayoutList(maxSize, tempList);
424     int[] list = new int[size];
425     System.arraycopy(tempList, 0, list, 0, size);
426     return list;
427 }
428 /**
429  * Return whether or not the platform supports a bidi language. Determine this
430  * by looking at the languages that are installed.
431  * <p>
432  *
433  * @return true if bidi is supported, false otherwise. Always
434  * false on Windows CE.
435  */

436 public static boolean isBidiPlatform() {
437     if (OS.IsWinCE) return false;
438     if (isBidiPlatform != -1) return isBidiPlatform == 1; // already set
439

440     isBidiPlatform = 0;
441     
442     // The following test is a workaround for bug report 27629. On WinXP,
443
// both bidi and complex script (e.g., Thai) languages must be installed
444
// at the same time. Since the bidi platform calls do not support
445
// double byte characters, there is no way to run Eclipse using the
446
// complex script languages on XP, so constrain this test to answer true
447
// only if a bidi input language is defined. Doing so will allow complex
448
// script languages to work (e.g., one can install bidi and complex script
449
// languages, but only install the Thai keyboard).
450
if (!isKeyboardBidi()) return false;
451     
452     Callback callback = null;
453     try {
454         callback = new Callback (Class.forName (CLASS_NAME), "EnumSystemLanguageGroupsProc", 5); //$NON-NLS-1$
455
int lpEnumSystemLanguageGroupsProc = callback.getAddress ();
456         if (lpEnumSystemLanguageGroupsProc == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
457         OS.EnumSystemLanguageGroups(lpEnumSystemLanguageGroupsProc, OS.LGRPID_INSTALLED, 0);
458         callback.dispose ();
459     } catch (ClassNotFoundException JavaDoc e) {
460         if (callback != null) callback.dispose();
461     }
462     if (isBidiPlatform == 1) return true;
463     // need to look at system code page for NT & 98 platforms since EnumSystemLanguageGroups is
464
// not supported for these platforms
465
String JavaDoc codePage = String.valueOf(OS.GetACP());
466     if (CD_PG_ARABIC.equals(codePage) || CD_PG_HEBREW.equals(codePage)) {
467         isBidiPlatform = 1;
468     }
469     return isBidiPlatform == 1;
470 }
471 /**
472  * Return whether or not the keyboard supports input of a bidi language. Determine this
473  * by looking at the languages that are installed for the keyboard.
474  * <p>
475  *
476  * @return true if bidi is supported, false otherwise.
477  */

478 public static boolean isKeyboardBidi() {
479     int[] list = getKeyboardLanguageList();
480     for (int i=0; i<list.length; i++) {
481         int id = list[i] & 0x000000FF;
482         if ((id == LANG_ARABIC) || (id == LANG_HEBREW)) {
483             return true;
484         }
485     }
486     return false;
487 }
488 /**
489  * Removes the specified language listener.
490  * <p>
491  *
492  * @param hwnd the handle of the Control that is listening for keyboard language changes
493  */

494 public static void removeLanguageListener (int hwnd) {
495     languageMap.remove(new Integer JavaDoc(hwnd));
496     unsubclass(hwnd);
497 }
498 /**
499  * Switch the keyboard language to the specified language type. We do
500  * not distinguish between multiple bidi or multiple non-bidi languages, so
501  * set the keyboard to the first language of the given type.
502  * <p>
503  *
504  * @param language integer representing language. One of
505  * KEYBOARD_BIDI, KEYBOARD_NON_BIDI.
506  */

507 public static void setKeyboardLanguage(int language) {
508     // don't switch the keyboard if it doesn't need to be
509
if (language == getKeyboardLanguage()) return;
510     
511     if (language == KEYBOARD_BIDI) {
512         // get the list of active languages
513
int[] list = getKeyboardLanguageList();
514         // set to first bidi language
515
for (int i=0; i<list.length; i++) {
516             int id = list[i] & 0x000000FF;
517             if ((id == LANG_ARABIC) || (id == LANG_HEBREW)) {
518                 OS.ActivateKeyboardLayout(list[i], 0);
519                 return;
520             }
521         }
522     } else {
523         // get the list of active languages
524
int[] list = getKeyboardLanguageList();
525         // set to the first non-bidi language (anything not
526
// Hebrew or Arabic)
527
for (int i=0; i<list.length; i++) {
528             int id = list[i] & 0x000000FF;
529             if ((id != LANG_HEBREW) && (id != LANG_ARABIC)) {
530                 OS.ActivateKeyboardLayout(list[i], 0);
531                 return;
532             }
533         }
534     }
535 }
536 /**
537  * Sets the orientation (writing order) of the specified control. Text will
538  * be right aligned for right to left writing order.
539  * <p>
540  *
541  * @param hwnd the handle of the Control to change the orientation of
542  * @param orientation one of SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
543  * @return true if the orientation was changed, false if the orientation
544  * could not be changed
545  */

546 public static boolean setOrientation (int hwnd, int orientation) {
547     if (OS.IsWinCE) return false;
548     if (OS.WIN32_VERSION < OS.VERSION(4, 10)) return false;
549     int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
550     if ((orientation & SWT.RIGHT_TO_LEFT) != 0) {
551         bits |= OS.WS_EX_LAYOUTRTL;
552     } else {
553         bits &= ~OS.WS_EX_LAYOUTRTL;
554     }
555     OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits);
556     return true;
557 }
558 /**
559  * Override the window proc.
560  *
561  * @param hwnd control to override the window proc of
562  */

563 static void subclass(int hwnd) {
564     Integer JavaDoc key = new Integer JavaDoc(hwnd);
565     if (oldProcMap.get(key) == null) {
566         int oldProc = OS.GetWindowLong(hwnd, OS.GWL_WNDPROC);
567         oldProcMap.put(key, new Integer JavaDoc(oldProc));
568         OS.SetWindowLong(hwnd, OS.GWL_WNDPROC, callback.getAddress());
569     }
570 }
571 /**
572  * Reverse the character array. Used for right orientation.
573  *
574  * @param charArray character array to reverse
575  */

576 static void reverse(char[] charArray) {
577     int length = charArray.length;
578     for (int i = 0; i <= (length - 1) / 2; i++) {
579         char tmp = charArray[i];
580         charArray[i] = charArray[length - 1 - i];
581         charArray[length - 1 - i] = tmp;
582     }
583 }
584 /**
585  * Reverse the integer array. Used for right orientation.
586  *
587  * @param intArray integer array to reverse
588  */

589 static void reverse(int[] intArray) {
590     int length = intArray.length;
591     for (int i = 0; i <= (length - 1) / 2; i++) {
592         int tmp = intArray[i];
593         intArray[i] = intArray[length - 1 - i];
594         intArray[length - 1 - i] = tmp;
595     }
596 }
597 /**
598  * Adjust the order array so that it is relative to the start of the line. Also reverse the order array if the orientation
599  * is to the right.
600  *
601  * @param orderArray integer array of order values to translate
602  * @param glyphCount number of glyphs that have been processed for the current line
603  * @param isRightOriented flag indicating whether or not current orientation is to the right
604 */

605 static void translateOrder(int[] orderArray, int glyphCount, boolean isRightOriented) {
606     int maxOrder = 0;
607     int length = orderArray.length;
608     if (isRightOriented) {
609         for (int i=0; i<length; i++) {
610             maxOrder = Math.max(maxOrder, orderArray[i]);
611         }
612     }
613     for (int i=0; i<length; i++) {
614         if (isRightOriented) orderArray[i] = maxOrder - orderArray[i];
615         orderArray [i] += glyphCount;
616     }
617 }
618 /**
619  * Remove the overridden the window proc.
620  *
621  * @param hwnd control to remove the window proc override for
622  */

623 static void unsubclass(int hwnd) {
624     Integer JavaDoc key = new Integer JavaDoc(hwnd);
625     if (languageMap.get(key) == null && keyMap.get(key) == null) {
626         Integer JavaDoc proc = (Integer JavaDoc) oldProcMap.remove(key);
627         if (proc == null) return;
628         OS.SetWindowLong(hwnd, OS.GWL_WNDPROC, proc.intValue());
629     }
630 }
631 /**
632  * Window proc to intercept keyboard language switch event (WS_INPUTLANGCHANGE)
633  * and widget orientation changes.
634  * Run the Control's registered runnable when the keyboard language is switched.
635  *
636  * @param hwnd handle of the control that is listening for the keyboard language
637  * change event
638  * @param msg window message
639  */

640 static int windowProc (int hwnd, int msg, int wParam, int lParam) {
641     Integer JavaDoc key = new Integer JavaDoc (hwnd);
642     switch (msg) {
643         case 0x51 /*OS.WM_INPUTLANGCHANGE*/:
644             Runnable JavaDoc runnable = (Runnable JavaDoc) languageMap.get (key);
645             if (runnable != null) runnable.run ();
646             break;
647         }
648     Integer JavaDoc oldProc = (Integer JavaDoc)oldProcMap.get(key);
649     return OS.CallWindowProc (oldProc.intValue(), hwnd, msg, wParam, lParam);
650 }
651
652 }
653
Popular Tags