Implementation of the reordering algorithm by calling ICU's reordering
[wine] / dlls / gdi / bidi.c
1
2 /*
3  * GDI BiDirectional handling
4  *
5  * Copyright 2003 Shachar Shemesh
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23
24 #ifdef HAVE_UNICODE_UBIDI_H
25 #include <unicode/ubidi.h>
26 #endif
27
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "wine/debug.h"
31 #include "gdi.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(bidi);
34
35 #if HAVE_ICU
36 BOOL BidiAvail = TRUE;
37 #else
38 BOOL BidiAvail = FALSE;
39 #endif
40
41
42 /*************************************************************
43  *    BIDI_Reorder
44  */
45 BOOL BIDI_Reorder(
46                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
47                 INT uCount,     /* [in] Number of WCHARs in string. */
48                 DWORD dwFlags,  /* [in] GetCharacterPlacement compatible flags specifying how to process the string */
49                 DWORD dwWineGCP_Flags,       /* [in] Wine internal flags - Force paragraph direction */
50                 LPWSTR lpOutString, /* [out] Reordered string */
51                 INT uCountOut,  /* [in] Size of output buffer */
52                 UINT *lpOrder /* [out] Logical -> Visual order map */
53     )
54 {
55 #ifdef HAVE_ICU
56     TRACE("%s, %d, 0x%08lx\n",
57           debugstr_wn(lpString, uCount), uCount, dwFlags);
58
59     TRACE("lpOutString=%p, lpOrder=%p", lpOutString, lpOrder );
60
61     if ((dwFlags & GCP_REORDER) != 0) {
62         UBiDi *bidi;
63         UErrorCode err=0;
64         UBiDiLevel level;
65
66         bidi=ubidi_open();
67         if( bidi==NULL ) {
68             WARN("Failed to allocate structure\n");
69             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
70             return FALSE;
71         }
72
73         switch( dwWineGCP_Flags&WINE_GCPW_DIR_MASK )
74         {
75         case WINE_GCPW_FORCE_LTR:
76             level=0;
77             break;
78         case WINE_GCPW_FORCE_RTL:
79             level=1;
80             break;
81         case WINE_GCPW_LOOSE_LTR:
82             level=UBIDI_DEFAULT_LTR;
83             break;
84         case WINE_GCPW_LOOSE_RTL:
85             level=UBIDI_DEFAULT_RTL;
86             break;
87         }
88
89         ubidi_setPara( bidi, lpString, uCount, level, NULL, &err );
90         if( lpOutString!=NULL ) {
91             ubidi_writeReordered( bidi, lpOutString, uCount,
92                     (dwFlags&GCP_SYMSWAPOFF)?0:UBIDI_DO_MIRRORING, &err );
93         }
94
95         if( lpOrder!=NULL ) {
96             ubidi_getLogicalMap( bidi, lpOrder, &err );
97         }
98
99         ubidi_close( bidi );
100
101         if( U_FAILURE(err) ) {
102             FIXME("ICU Library return error code %d.\n", err );
103             FIXME("Please report this error to wine-devel@winehq.org so we can place "
104                     "descriptive Windows error codes here\n");
105             SetLastError(ERROR_INVALID_LEVEL); /* This error is cryptic enough not to mean anything, I hope */
106
107             return FALSE;
108         }
109     }
110     return TRUE;
111 #else  /* HAVE_ICU */
112     return FALSE;
113 #endif  /* HAVE_ICU */
114 }