forked from ClickteamLLC/windows
-
Notifications
You must be signed in to change notification settings - Fork 0
/
UnicodeSDK.txt
278 lines (192 loc) · 8.53 KB
/
UnicodeSDK.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
How to convert an extension to Unicode
--------------------------------------
The Unicode version of MMF2 can load either Unicode or non Unicode extensions, but of course
Unicode characters are supported only by Unicode extensions, so if your extensions use text
you should create a Unicode version.
The MMF2 Unicode SDK allows you to compile extensions for both the non Unicode version of MMF2
and for the Unicode version.
How this works
--------------
To compile a Unicode extension, you have to add _UNICODE and UNICODE to the preprocessor
definitions in your project's settings.
If you don't define these symbols, the extension will be compiled in non Unicode mode.
So first thing to do, copy the extension folder to the MMF2SDK_Unicode/Extensions folder, and then :
- edit its project,
- add new Debug Unicode, Release Unicode and Runtime Unicode configurations based on the Debug,
Release and Runtime configurations (and a Vitalize Unicode config if your extension is "Vitalized")
- and add _UNICODE and UNICODE to the proprocessor definitions of those configs. The original
configs will be used to compile a non Unicode version for the normal version of MMF2.
Note: the Unicode extensions have to be installed to the Extensions\Unicode and Data\Runtime\Unicode
folders of MMF2 Unicode.
Note 2: if you use MSVC++ 2005 or above you have to set the "Threat wchar_t as Built-in Type" option
to "No" in the C++ / Language settings of the project otherwise you'll get link errors if you use functions
with text parameters in the DLL.
What do the _UNICODE/UNICODE symbols do
---------------------------------------
All the Windows structures and functions that use text, as well as all the MMF structures, exist
in 2 versions, a non Unicode version and a Unicode version. When _UNICODE/UNICODE are defined,
the Unicode version is used, when they are not defined then the non Unicode version is used.
For example the Windows DrawText function doesn't exist really, Windows contains 2 functions
DrawTextA and DrawTextW and DrawText is a macro set to DrawTextW if _UNICODE/UNICODE are defined,
and to DrawTextA if they are not defined.
Structures like LOGFONT are also macros, the real structures are LOGFONTA and LOGFONTW.
Those functions and structures don't use the 'char' or 'char*' types, they also use macros,
you have to use them in your extension to be able to compile it to both Unicode and non Unicode :
Instead of ... use ... :
char -> TCHAR
LPSTR -> LPTSTR
LPCSTR -> LPCTSTR
Note: you can still use char for characters that are always non Unicode, or WCHAR for charaters
that are always Unicode.
Functions from the C++ runtime library also have to be replaced by macros (defined in tchar.h) :
strlen -> _tcslen
strcpy -> _tcscpy
splitpath -> _tsplitpath
etc.
For constant strings, use the _T macro:
"this is a string" -> _T("This is a string")
If your extensions is compiled in Unicode mode, then _T("This is a string") will be replaced
by L"this is a string", otherwise it will be replaced by "this is a string".
-----------------
Changes in Main.h
-----------------
EDITDATA
--------
That's the most problematic part of the conversion.
If it doesn't contain any text, there is nothing to do.
If it contains text, you have to keep 2 versions of this structure :
- an EDITDATAA structure, non-Unicode, with char values (for example char array[2], LOGFONTA lfnt, etc)
- an EDITDATAW structure, Unicode, with WCHAR values (for example WCHAR array[2], LOGFONTW lfnt, etc)
and then define this :
#ifdef _UNICODE
#define EDITDATA EDITDATAW
#define LPEDATA LPEDATAW
#else
#define EDITDATA EDITDATAA
#define LPEDATA LPEDATAA
#endif
Do NOT use TCHAR in EDITDATA.
You also have to convert your EDITDATA structure to/from Unicode in the UpdateEditStructure
function, in General.cpp :
If you don't use the UpdateEditStructure function in your application already, you have to implement
it so that it can convert non Unicode EDITDATA from non Unicode applications to Unicode.
You can check if the application file that is being loaded is Unicode with mvIsUnicodeApp(pMV, pMV->mvEditApp).
If you need to convert text from/to Unicode, use the MultiByteToWideChar and WideCharToMultiByte functions,
and use mvGetAppCodePage(pMV, pMV->mvEditApp) as code page.
Look at the Simple Control example to see how to implement this.
And don't forgot to enable this function in the .DEF file!
If you already use UpdateEditStructure to update the EDITDATA structure of old versions
of your object, then it's a little more complicated, you should first update the old
EDITDATAA structure and then convert the updated EDITDATAA structure to Unicode.
RUNDATA
-------
Almost nothing to do in this structure : just use TCHAR, LPTSTR, etc.
-------------------------------
Changes in various source codes
-------------------------------
EditTime.cpp
------------
Replace LPSTR (or LPCSTR) by LPTSTR (or LPCTSTR) in the headers of the following functions :
GetObjInfos
GetHelpFileName
MakeIconEx
UsesFile
CreateFromFile
GetTextFont
GetCodeTitle
GetConditionTitle
GetActionTitle
GetExpressionTitle
GetConditionString
GetActionString
GetExpressionString
GetExpressionParam
GetParameterString
And replace the menucpy function by :
void menucpy(HMENU hTargetMenu, HMENU hSourceMenu)
{
#ifndef RUN_ONLY
int n, id, nMn;
LPTSTR strBuf;
HMENU hSubMenu;
nMn = GetMenuItemCount(hSourceMenu);
strBuf = (LPTSTR)calloc(80, sizeof(TCHAR));
for (n = 0; n < nMn; n++)
{
if (0 == (id = GetMenuItemID(hSourceMenu, n)))
AppendMenu(hTargetMenu, MF_SEPARATOR, 0, 0L);
else
{
GetMenuString(hSourceMenu, n, strBuf, 80, MF_BYPOSITION);
if (id != -1)
AppendMenu(hTargetMenu, GetMenuState(hSourceMenu, n, MF_BYPOSITION), id, strBuf);
else
{
hSubMenu = CreatePopupMenu();
AppendMenu(hTargetMenu, MF_POPUP | MF_STRING, (uint)hSubMenu, strBuf);
menucpy(hSubMenu, GetSubMenu(hSourceMenu, n));
}
}
}
free(strBuf);
#endif
}
Properties
----------
There are no changes in the properties, except in string properties. You were using
previously CPropDataValue to pass/retrieve strings to/from the MMF property manager.
There is now a new CPropStringValue class :
In the GetPropValue function :
Before :
case PROPID_MYSTRING:
return new CPropDataValue((LPCSTR)edPtr->myString);
Now:
case PROPID_MYSTRING:
return new CPropStringValue(edPtr->myString);
In the SetPropValue function :
Before:
case PROPID_MYSTRING:
LPSTR ps = (LPSTR)((CPropDataValue*)pValue)->m_pData;
Now:
case PROPID_MYSTRING:
LPCTSTR ps = ((CPropStringValue*)pValue)->GetString();
Runtime.cpp
-----------
Replace the header of the GetDebugItem function by :
void WINAPI DLLExport GetDebugItem(LPTSTR pBuffer, LPRDATA rdPtr, int id)
General.cpp
-----------
Add this in the GetInfos function :
case KGI_UNICODE:
#ifdef _UNICODE
return TRUE;
#else
return FALSE;
#endif
This will allow MMF to know if your extension is a Unicode extension or a non-Unicode
extension. MMF will then convert the strings if necessary before passing them to the
functions of your extension, or after retrieving them.
Replace LPCSTR by LPCTSTR in GetDependencies() and in the table it returns if any
(and add _T() in the dll names in the table).
Replace LPSTR by LPTSTR in the header of the UpdateFileNames function.
Implement the UpdateEditStructure if necessary, see above.
Main.cpp
--------
Actions/Conditions/Expressions: if your extension is a Unicode extension, it will receive
string parameters in Unicode format (and will have to return string parameters in Unicode
format). If your extension is not a Unicode extension, it will receive/return non Unicode
strings.
Note: the size parameter in the RFUNCTION_GETSTRINGSPACE and RFUNCTION_GETSTRINGSPACE_EX
functions is in bytes. Multiply the string length by sizeof(TCHAR) to get its size in bytes.
---------------------------------
Changes in the runtime structures
---------------------------------
No many changes in the internal runtime structure, but anyway if you compile a Unicode
version of your extension you haven't to care about those changes : the non Unicode
version of your extension will work fine when it will be executed by the non Unicode
version of MMF2 and the Unicode version of your extension will work fine when it will
be executed by the Unicode version of MMF2.
Problems happens when a non Unicode version of an extension is loaded by MMF2 Unicode
and want to access members of internal structures that are different in the Unicode version,
for example if a non Unicode extension needs to copy the oilName member of objInfoList and
is executed by MMF2 Unicode.