Imported Upstream version 0.1.0
Aron Xu
11 years ago
0 | cmake_minimum_required(VERSION 2.6) | |
1 | ||
2 | project(fcitx-unikey) | |
3 | ||
4 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) | |
5 | ||
6 | # uninstall target | |
7 | configure_file( | |
8 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" | |
9 | "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" | |
10 | IMMEDIATE @ONLY) | |
11 | ||
12 | add_custom_target(uninstall | |
13 | COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) | |
14 | ||
15 | set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-sign-compare -Wno-unused-parameter -fvisibility=hidden ${CMAKE_C_FLAGS}") | |
16 | set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-sign-compare -Wno-unused-parameter -fvisibility=hidden ${CMAKE_CXX_FLAGS}") | |
17 | set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}") | |
18 | set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_MODULE_LINKER_FLAGS}") | |
19 | ||
20 | find_package(Fcitx 4.2.3 REQUIRED) | |
21 | find_package(Libiconv REQUIRED) | |
22 | find_package(Gettext REQUIRED) | |
23 | ||
24 | configure_file(config.h.in config.h) | |
25 | ||
26 | add_subdirectory(src) | |
27 | add_subdirectory(data) | |
28 | add_subdirectory(po)⏎ |
0 | GNU GENERAL PUBLIC LICENSE | |
1 | Version 3, 29 June 2007 | |
2 | ||
3 | Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | |
4 | Everyone is permitted to copy and distribute verbatim copies | |
5 | of this license document, but changing it is not allowed. | |
6 | ||
7 | Preamble | |
8 | ||
9 | The GNU General Public License is a free, copyleft license for | |
10 | software and other kinds of works. | |
11 | ||
12 | The licenses for most software and other practical works are designed | |
13 | to take away your freedom to share and change the works. By contrast, | |
14 | the GNU General Public License is intended to guarantee your freedom to | |
15 | share and change all versions of a program--to make sure it remains free | |
16 | software for all its users. We, the Free Software Foundation, use the | |
17 | GNU General Public License for most of our software; it applies also to | |
18 | any other work released this way by its authors. You can apply it to | |
19 | your programs, too. | |
20 | ||
21 | When we speak of free software, we are referring to freedom, not | |
22 | price. Our General Public Licenses are designed to make sure that you | |
23 | have the freedom to distribute copies of free software (and charge for | |
24 | them if you wish), that you receive source code or can get it if you | |
25 | want it, that you can change the software or use pieces of it in new | |
26 | free programs, and that you know you can do these things. | |
27 | ||
28 | To protect your rights, we need to prevent others from denying you | |
29 | these rights or asking you to surrender the rights. Therefore, you have | |
30 | certain responsibilities if you distribute copies of the software, or if | |
31 | you modify it: responsibilities to respect the freedom of others. | |
32 | ||
33 | For example, if you distribute copies of such a program, whether | |
34 | gratis or for a fee, you must pass on to the recipients the same | |
35 | freedoms that you received. You must make sure that they, too, receive | |
36 | or can get the source code. And you must show them these terms so they | |
37 | know their rights. | |
38 | ||
39 | Developers that use the GNU GPL protect your rights with two steps: | |
40 | (1) assert copyright on the software, and (2) offer you this License | |
41 | giving you legal permission to copy, distribute and/or modify it. | |
42 | ||
43 | For the developers' and authors' protection, the GPL clearly explains | |
44 | that there is no warranty for this free software. For both users' and | |
45 | authors' sake, the GPL requires that modified versions be marked as | |
46 | changed, so that their problems will not be attributed erroneously to | |
47 | authors of previous versions. | |
48 | ||
49 | Some devices are designed to deny users access to install or run | |
50 | modified versions of the software inside them, although the manufacturer | |
51 | can do so. This is fundamentally incompatible with the aim of | |
52 | protecting users' freedom to change the software. The systematic | |
53 | pattern of such abuse occurs in the area of products for individuals to | |
54 | use, which is precisely where it is most unacceptable. Therefore, we | |
55 | have designed this version of the GPL to prohibit the practice for those | |
56 | products. If such problems arise substantially in other domains, we | |
57 | stand ready to extend this provision to those domains in future versions | |
58 | of the GPL, as needed to protect the freedom of users. | |
59 | ||
60 | Finally, every program is threatened constantly by software patents. | |
61 | States should not allow patents to restrict development and use of | |
62 | software on general-purpose computers, but in those that do, we wish to | |
63 | avoid the special danger that patents applied to a free program could | |
64 | make it effectively proprietary. To prevent this, the GPL assures that | |
65 | patents cannot be used to render the program non-free. | |
66 | ||
67 | The precise terms and conditions for copying, distribution and | |
68 | modification follow. | |
69 | ||
70 | TERMS AND CONDITIONS | |
71 | ||
72 | 0. Definitions. | |
73 | ||
74 | "This License" refers to version 3 of the GNU General Public License. | |
75 | ||
76 | "Copyright" also means copyright-like laws that apply to other kinds of | |
77 | works, such as semiconductor masks. | |
78 | ||
79 | "The Program" refers to any copyrightable work licensed under this | |
80 | License. Each licensee is addressed as "you". "Licensees" and | |
81 | "recipients" may be individuals or organizations. | |
82 | ||
83 | To "modify" a work means to copy from or adapt all or part of the work | |
84 | in a fashion requiring copyright permission, other than the making of an | |
85 | exact copy. The resulting work is called a "modified version" of the | |
86 | earlier work or a work "based on" the earlier work. | |
87 | ||
88 | A "covered work" means either the unmodified Program or a work based | |
89 | on the Program. | |
90 | ||
91 | To "propagate" a work means to do anything with it that, without | |
92 | permission, would make you directly or secondarily liable for | |
93 | infringement under applicable copyright law, except executing it on a | |
94 | computer or modifying a private copy. Propagation includes copying, | |
95 | distribution (with or without modification), making available to the | |
96 | public, and in some countries other activities as well. | |
97 | ||
98 | To "convey" a work means any kind of propagation that enables other | |
99 | parties to make or receive copies. Mere interaction with a user through | |
100 | a computer network, with no transfer of a copy, is not conveying. | |
101 | ||
102 | An interactive user interface displays "Appropriate Legal Notices" | |
103 | to the extent that it includes a convenient and prominently visible | |
104 | feature that (1) displays an appropriate copyright notice, and (2) | |
105 | tells the user that there is no warranty for the work (except to the | |
106 | extent that warranties are provided), that licensees may convey the | |
107 | work under this License, and how to view a copy of this License. If | |
108 | the interface presents a list of user commands or options, such as a | |
109 | menu, a prominent item in the list meets this criterion. | |
110 | ||
111 | 1. Source Code. | |
112 | ||
113 | The "source code" for a work means the preferred form of the work | |
114 | for making modifications to it. "Object code" means any non-source | |
115 | form of a work. | |
116 | ||
117 | A "Standard Interface" means an interface that either is an official | |
118 | standard defined by a recognized standards body, or, in the case of | |
119 | interfaces specified for a particular programming language, one that | |
120 | is widely used among developers working in that language. | |
121 | ||
122 | The "System Libraries" of an executable work include anything, other | |
123 | than the work as a whole, that (a) is included in the normal form of | |
124 | packaging a Major Component, but which is not part of that Major | |
125 | Component, and (b) serves only to enable use of the work with that | |
126 | Major Component, or to implement a Standard Interface for which an | |
127 | implementation is available to the public in source code form. A | |
128 | "Major Component", in this context, means a major essential component | |
129 | (kernel, window system, and so on) of the specific operating system | |
130 | (if any) on which the executable work runs, or a compiler used to | |
131 | produce the work, or an object code interpreter used to run it. | |
132 | ||
133 | The "Corresponding Source" for a work in object code form means all | |
134 | the source code needed to generate, install, and (for an executable | |
135 | work) run the object code and to modify the work, including scripts to | |
136 | control those activities. However, it does not include the work's | |
137 | System Libraries, or general-purpose tools or generally available free | |
138 | programs which are used unmodified in performing those activities but | |
139 | which are not part of the work. For example, Corresponding Source | |
140 | includes interface definition files associated with source files for | |
141 | the work, and the source code for shared libraries and dynamically | |
142 | linked subprograms that the work is specifically designed to require, | |
143 | such as by intimate data communication or control flow between those | |
144 | subprograms and other parts of the work. | |
145 | ||
146 | The Corresponding Source need not include anything that users | |
147 | can regenerate automatically from other parts of the Corresponding | |
148 | Source. | |
149 | ||
150 | The Corresponding Source for a work in source code form is that | |
151 | same work. | |
152 | ||
153 | 2. Basic Permissions. | |
154 | ||
155 | All rights granted under this License are granted for the term of | |
156 | copyright on the Program, and are irrevocable provided the stated | |
157 | conditions are met. This License explicitly affirms your unlimited | |
158 | permission to run the unmodified Program. The output from running a | |
159 | covered work is covered by this License only if the output, given its | |
160 | content, constitutes a covered work. This License acknowledges your | |
161 | rights of fair use or other equivalent, as provided by copyright law. | |
162 | ||
163 | You may make, run and propagate covered works that you do not | |
164 | convey, without conditions so long as your license otherwise remains | |
165 | in force. You may convey covered works to others for the sole purpose | |
166 | of having them make modifications exclusively for you, or provide you | |
167 | with facilities for running those works, provided that you comply with | |
168 | the terms of this License in conveying all material for which you do | |
169 | not control copyright. Those thus making or running the covered works | |
170 | for you must do so exclusively on your behalf, under your direction | |
171 | and control, on terms that prohibit them from making any copies of | |
172 | your copyrighted material outside their relationship with you. | |
173 | ||
174 | Conveying under any other circumstances is permitted solely under | |
175 | the conditions stated below. Sublicensing is not allowed; section 10 | |
176 | makes it unnecessary. | |
177 | ||
178 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. | |
179 | ||
180 | No covered work shall be deemed part of an effective technological | |
181 | measure under any applicable law fulfilling obligations under article | |
182 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or | |
183 | similar laws prohibiting or restricting circumvention of such | |
184 | measures. | |
185 | ||
186 | When you convey a covered work, you waive any legal power to forbid | |
187 | circumvention of technological measures to the extent such circumvention | |
188 | is effected by exercising rights under this License with respect to | |
189 | the covered work, and you disclaim any intention to limit operation or | |
190 | modification of the work as a means of enforcing, against the work's | |
191 | users, your or third parties' legal rights to forbid circumvention of | |
192 | technological measures. | |
193 | ||
194 | 4. Conveying Verbatim Copies. | |
195 | ||
196 | You may convey verbatim copies of the Program's source code as you | |
197 | receive it, in any medium, provided that you conspicuously and | |
198 | appropriately publish on each copy an appropriate copyright notice; | |
199 | keep intact all notices stating that this License and any | |
200 | non-permissive terms added in accord with section 7 apply to the code; | |
201 | keep intact all notices of the absence of any warranty; and give all | |
202 | recipients a copy of this License along with the Program. | |
203 | ||
204 | You may charge any price or no price for each copy that you convey, | |
205 | and you may offer support or warranty protection for a fee. | |
206 | ||
207 | 5. Conveying Modified Source Versions. | |
208 | ||
209 | You may convey a work based on the Program, or the modifications to | |
210 | produce it from the Program, in the form of source code under the | |
211 | terms of section 4, provided that you also meet all of these conditions: | |
212 | ||
213 | a) The work must carry prominent notices stating that you modified | |
214 | it, and giving a relevant date. | |
215 | ||
216 | b) The work must carry prominent notices stating that it is | |
217 | released under this License and any conditions added under section | |
218 | 7. This requirement modifies the requirement in section 4 to | |
219 | "keep intact all notices". | |
220 | ||
221 | c) You must license the entire work, as a whole, under this | |
222 | License to anyone who comes into possession of a copy. This | |
223 | License will therefore apply, along with any applicable section 7 | |
224 | additional terms, to the whole of the work, and all its parts, | |
225 | regardless of how they are packaged. This License gives no | |
226 | permission to license the work in any other way, but it does not | |
227 | invalidate such permission if you have separately received it. | |
228 | ||
229 | d) If the work has interactive user interfaces, each must display | |
230 | Appropriate Legal Notices; however, if the Program has interactive | |
231 | interfaces that do not display Appropriate Legal Notices, your | |
232 | work need not make them do so. | |
233 | ||
234 | A compilation of a covered work with other separate and independent | |
235 | works, which are not by their nature extensions of the covered work, | |
236 | and which are not combined with it such as to form a larger program, | |
237 | in or on a volume of a storage or distribution medium, is called an | |
238 | "aggregate" if the compilation and its resulting copyright are not | |
239 | used to limit the access or legal rights of the compilation's users | |
240 | beyond what the individual works permit. Inclusion of a covered work | |
241 | in an aggregate does not cause this License to apply to the other | |
242 | parts of the aggregate. | |
243 | ||
244 | 6. Conveying Non-Source Forms. | |
245 | ||
246 | You may convey a covered work in object code form under the terms | |
247 | of sections 4 and 5, provided that you also convey the | |
248 | machine-readable Corresponding Source under the terms of this License, | |
249 | in one of these ways: | |
250 | ||
251 | a) Convey the object code in, or embodied in, a physical product | |
252 | (including a physical distribution medium), accompanied by the | |
253 | Corresponding Source fixed on a durable physical medium | |
254 | customarily used for software interchange. | |
255 | ||
256 | b) Convey the object code in, or embodied in, a physical product | |
257 | (including a physical distribution medium), accompanied by a | |
258 | written offer, valid for at least three years and valid for as | |
259 | long as you offer spare parts or customer support for that product | |
260 | model, to give anyone who possesses the object code either (1) a | |
261 | copy of the Corresponding Source for all the software in the | |
262 | product that is covered by this License, on a durable physical | |
263 | medium customarily used for software interchange, for a price no | |
264 | more than your reasonable cost of physically performing this | |
265 | conveying of source, or (2) access to copy the | |
266 | Corresponding Source from a network server at no charge. | |
267 | ||
268 | c) Convey individual copies of the object code with a copy of the | |
269 | written offer to provide the Corresponding Source. This | |
270 | alternative is allowed only occasionally and noncommercially, and | |
271 | only if you received the object code with such an offer, in accord | |
272 | with subsection 6b. | |
273 | ||
274 | d) Convey the object code by offering access from a designated | |
275 | place (gratis or for a charge), and offer equivalent access to the | |
276 | Corresponding Source in the same way through the same place at no | |
277 | further charge. You need not require recipients to copy the | |
278 | Corresponding Source along with the object code. If the place to | |
279 | copy the object code is a network server, the Corresponding Source | |
280 | may be on a different server (operated by you or a third party) | |
281 | that supports equivalent copying facilities, provided you maintain | |
282 | clear directions next to the object code saying where to find the | |
283 | Corresponding Source. Regardless of what server hosts the | |
284 | Corresponding Source, you remain obligated to ensure that it is | |
285 | available for as long as needed to satisfy these requirements. | |
286 | ||
287 | e) Convey the object code using peer-to-peer transmission, provided | |
288 | you inform other peers where the object code and Corresponding | |
289 | Source of the work are being offered to the general public at no | |
290 | charge under subsection 6d. | |
291 | ||
292 | A separable portion of the object code, whose source code is excluded | |
293 | from the Corresponding Source as a System Library, need not be | |
294 | included in conveying the object code work. | |
295 | ||
296 | A "User Product" is either (1) a "consumer product", which means any | |
297 | tangible personal property which is normally used for personal, family, | |
298 | or household purposes, or (2) anything designed or sold for incorporation | |
299 | into a dwelling. In determining whether a product is a consumer product, | |
300 | doubtful cases shall be resolved in favor of coverage. For a particular | |
301 | product received by a particular user, "normally used" refers to a | |
302 | typical or common use of that class of product, regardless of the status | |
303 | of the particular user or of the way in which the particular user | |
304 | actually uses, or expects or is expected to use, the product. A product | |
305 | is a consumer product regardless of whether the product has substantial | |
306 | commercial, industrial or non-consumer uses, unless such uses represent | |
307 | the only significant mode of use of the product. | |
308 | ||
309 | "Installation Information" for a User Product means any methods, | |
310 | procedures, authorization keys, or other information required to install | |
311 | and execute modified versions of a covered work in that User Product from | |
312 | a modified version of its Corresponding Source. The information must | |
313 | suffice to ensure that the continued functioning of the modified object | |
314 | code is in no case prevented or interfered with solely because | |
315 | modification has been made. | |
316 | ||
317 | If you convey an object code work under this section in, or with, or | |
318 | specifically for use in, a User Product, and the conveying occurs as | |
319 | part of a transaction in which the right of possession and use of the | |
320 | User Product is transferred to the recipient in perpetuity or for a | |
321 | fixed term (regardless of how the transaction is characterized), the | |
322 | Corresponding Source conveyed under this section must be accompanied | |
323 | by the Installation Information. But this requirement does not apply | |
324 | if neither you nor any third party retains the ability to install | |
325 | modified object code on the User Product (for example, the work has | |
326 | been installed in ROM). | |
327 | ||
328 | The requirement to provide Installation Information does not include a | |
329 | requirement to continue to provide support service, warranty, or updates | |
330 | for a work that has been modified or installed by the recipient, or for | |
331 | the User Product in which it has been modified or installed. Access to a | |
332 | network may be denied when the modification itself materially and | |
333 | adversely affects the operation of the network or violates the rules and | |
334 | protocols for communication across the network. | |
335 | ||
336 | Corresponding Source conveyed, and Installation Information provided, | |
337 | in accord with this section must be in a format that is publicly | |
338 | documented (and with an implementation available to the public in | |
339 | source code form), and must require no special password or key for | |
340 | unpacking, reading or copying. | |
341 | ||
342 | 7. Additional Terms. | |
343 | ||
344 | "Additional permissions" are terms that supplement the terms of this | |
345 | License by making exceptions from one or more of its conditions. | |
346 | Additional permissions that are applicable to the entire Program shall | |
347 | be treated as though they were included in this License, to the extent | |
348 | that they are valid under applicable law. If additional permissions | |
349 | apply only to part of the Program, that part may be used separately | |
350 | under those permissions, but the entire Program remains governed by | |
351 | this License without regard to the additional permissions. | |
352 | ||
353 | When you convey a copy of a covered work, you may at your option | |
354 | remove any additional permissions from that copy, or from any part of | |
355 | it. (Additional permissions may be written to require their own | |
356 | removal in certain cases when you modify the work.) You may place | |
357 | additional permissions on material, added by you to a covered work, | |
358 | for which you have or can give appropriate copyright permission. | |
359 | ||
360 | Notwithstanding any other provision of this License, for material you | |
361 | add to a covered work, you may (if authorized by the copyright holders of | |
362 | that material) supplement the terms of this License with terms: | |
363 | ||
364 | a) Disclaiming warranty or limiting liability differently from the | |
365 | terms of sections 15 and 16 of this License; or | |
366 | ||
367 | b) Requiring preservation of specified reasonable legal notices or | |
368 | author attributions in that material or in the Appropriate Legal | |
369 | Notices displayed by works containing it; or | |
370 | ||
371 | c) Prohibiting misrepresentation of the origin of that material, or | |
372 | requiring that modified versions of such material be marked in | |
373 | reasonable ways as different from the original version; or | |
374 | ||
375 | d) Limiting the use for publicity purposes of names of licensors or | |
376 | authors of the material; or | |
377 | ||
378 | e) Declining to grant rights under trademark law for use of some | |
379 | trade names, trademarks, or service marks; or | |
380 | ||
381 | f) Requiring indemnification of licensors and authors of that | |
382 | material by anyone who conveys the material (or modified versions of | |
383 | it) with contractual assumptions of liability to the recipient, for | |
384 | any liability that these contractual assumptions directly impose on | |
385 | those licensors and authors. | |
386 | ||
387 | All other non-permissive additional terms are considered "further | |
388 | restrictions" within the meaning of section 10. If the Program as you | |
389 | received it, or any part of it, contains a notice stating that it is | |
390 | governed by this License along with a term that is a further | |
391 | restriction, you may remove that term. If a license document contains | |
392 | a further restriction but permits relicensing or conveying under this | |
393 | License, you may add to a covered work material governed by the terms | |
394 | of that license document, provided that the further restriction does | |
395 | not survive such relicensing or conveying. | |
396 | ||
397 | If you add terms to a covered work in accord with this section, you | |
398 | must place, in the relevant source files, a statement of the | |
399 | additional terms that apply to those files, or a notice indicating | |
400 | where to find the applicable terms. | |
401 | ||
402 | Additional terms, permissive or non-permissive, may be stated in the | |
403 | form of a separately written license, or stated as exceptions; | |
404 | the above requirements apply either way. | |
405 | ||
406 | 8. Termination. | |
407 | ||
408 | You may not propagate or modify a covered work except as expressly | |
409 | provided under this License. Any attempt otherwise to propagate or | |
410 | modify it is void, and will automatically terminate your rights under | |
411 | this License (including any patent licenses granted under the third | |
412 | paragraph of section 11). | |
413 | ||
414 | However, if you cease all violation of this License, then your | |
415 | license from a particular copyright holder is reinstated (a) | |
416 | provisionally, unless and until the copyright holder explicitly and | |
417 | finally terminates your license, and (b) permanently, if the copyright | |
418 | holder fails to notify you of the violation by some reasonable means | |
419 | prior to 60 days after the cessation. | |
420 | ||
421 | Moreover, your license from a particular copyright holder is | |
422 | reinstated permanently if the copyright holder notifies you of the | |
423 | violation by some reasonable means, this is the first time you have | |
424 | received notice of violation of this License (for any work) from that | |
425 | copyright holder, and you cure the violation prior to 30 days after | |
426 | your receipt of the notice. | |
427 | ||
428 | Termination of your rights under this section does not terminate the | |
429 | licenses of parties who have received copies or rights from you under | |
430 | this License. If your rights have been terminated and not permanently | |
431 | reinstated, you do not qualify to receive new licenses for the same | |
432 | material under section 10. | |
433 | ||
434 | 9. Acceptance Not Required for Having Copies. | |
435 | ||
436 | You are not required to accept this License in order to receive or | |
437 | run a copy of the Program. Ancillary propagation of a covered work | |
438 | occurring solely as a consequence of using peer-to-peer transmission | |
439 | to receive a copy likewise does not require acceptance. However, | |
440 | nothing other than this License grants you permission to propagate or | |
441 | modify any covered work. These actions infringe copyright if you do | |
442 | not accept this License. Therefore, by modifying or propagating a | |
443 | covered work, you indicate your acceptance of this License to do so. | |
444 | ||
445 | 10. Automatic Licensing of Downstream Recipients. | |
446 | ||
447 | Each time you convey a covered work, the recipient automatically | |
448 | receives a license from the original licensors, to run, modify and | |
449 | propagate that work, subject to this License. You are not responsible | |
450 | for enforcing compliance by third parties with this License. | |
451 | ||
452 | An "entity transaction" is a transaction transferring control of an | |
453 | organization, or substantially all assets of one, or subdividing an | |
454 | organization, or merging organizations. If propagation of a covered | |
455 | work results from an entity transaction, each party to that | |
456 | transaction who receives a copy of the work also receives whatever | |
457 | licenses to the work the party's predecessor in interest had or could | |
458 | give under the previous paragraph, plus a right to possession of the | |
459 | Corresponding Source of the work from the predecessor in interest, if | |
460 | the predecessor has it or can get it with reasonable efforts. | |
461 | ||
462 | You may not impose any further restrictions on the exercise of the | |
463 | rights granted or affirmed under this License. For example, you may | |
464 | not impose a license fee, royalty, or other charge for exercise of | |
465 | rights granted under this License, and you may not initiate litigation | |
466 | (including a cross-claim or counterclaim in a lawsuit) alleging that | |
467 | any patent claim is infringed by making, using, selling, offering for | |
468 | sale, or importing the Program or any portion of it. | |
469 | ||
470 | 11. Patents. | |
471 | ||
472 | A "contributor" is a copyright holder who authorizes use under this | |
473 | License of the Program or a work on which the Program is based. The | |
474 | work thus licensed is called the contributor's "contributor version". | |
475 | ||
476 | A contributor's "essential patent claims" are all patent claims | |
477 | owned or controlled by the contributor, whether already acquired or | |
478 | hereafter acquired, that would be infringed by some manner, permitted | |
479 | by this License, of making, using, or selling its contributor version, | |
480 | but do not include claims that would be infringed only as a | |
481 | consequence of further modification of the contributor version. For | |
482 | purposes of this definition, "control" includes the right to grant | |
483 | patent sublicenses in a manner consistent with the requirements of | |
484 | this License. | |
485 | ||
486 | Each contributor grants you a non-exclusive, worldwide, royalty-free | |
487 | patent license under the contributor's essential patent claims, to | |
488 | make, use, sell, offer for sale, import and otherwise run, modify and | |
489 | propagate the contents of its contributor version. | |
490 | ||
491 | In the following three paragraphs, a "patent license" is any express | |
492 | agreement or commitment, however denominated, not to enforce a patent | |
493 | (such as an express permission to practice a patent or covenant not to | |
494 | sue for patent infringement). To "grant" such a patent license to a | |
495 | party means to make such an agreement or commitment not to enforce a | |
496 | patent against the party. | |
497 | ||
498 | If you convey a covered work, knowingly relying on a patent license, | |
499 | and the Corresponding Source of the work is not available for anyone | |
500 | to copy, free of charge and under the terms of this License, through a | |
501 | publicly available network server or other readily accessible means, | |
502 | then you must either (1) cause the Corresponding Source to be so | |
503 | available, or (2) arrange to deprive yourself of the benefit of the | |
504 | patent license for this particular work, or (3) arrange, in a manner | |
505 | consistent with the requirements of this License, to extend the patent | |
506 | license to downstream recipients. "Knowingly relying" means you have | |
507 | actual knowledge that, but for the patent license, your conveying the | |
508 | covered work in a country, or your recipient's use of the covered work | |
509 | in a country, would infringe one or more identifiable patents in that | |
510 | country that you have reason to believe are valid. | |
511 | ||
512 | If, pursuant to or in connection with a single transaction or | |
513 | arrangement, you convey, or propagate by procuring conveyance of, a | |
514 | covered work, and grant a patent license to some of the parties | |
515 | receiving the covered work authorizing them to use, propagate, modify | |
516 | or convey a specific copy of the covered work, then the patent license | |
517 | you grant is automatically extended to all recipients of the covered | |
518 | work and works based on it. | |
519 | ||
520 | A patent license is "discriminatory" if it does not include within | |
521 | the scope of its coverage, prohibits the exercise of, or is | |
522 | conditioned on the non-exercise of one or more of the rights that are | |
523 | specifically granted under this License. You may not convey a covered | |
524 | work if you are a party to an arrangement with a third party that is | |
525 | in the business of distributing software, under which you make payment | |
526 | to the third party based on the extent of your activity of conveying | |
527 | the work, and under which the third party grants, to any of the | |
528 | parties who would receive the covered work from you, a discriminatory | |
529 | patent license (a) in connection with copies of the covered work | |
530 | conveyed by you (or copies made from those copies), or (b) primarily | |
531 | for and in connection with specific products or compilations that | |
532 | contain the covered work, unless you entered into that arrangement, | |
533 | or that patent license was granted, prior to 28 March 2007. | |
534 | ||
535 | Nothing in this License shall be construed as excluding or limiting | |
536 | any implied license or other defenses to infringement that may | |
537 | otherwise be available to you under applicable patent law. | |
538 | ||
539 | 12. No Surrender of Others' Freedom. | |
540 | ||
541 | If conditions are imposed on you (whether by court order, agreement or | |
542 | otherwise) that contradict the conditions of this License, they do not | |
543 | excuse you from the conditions of this License. If you cannot convey a | |
544 | covered work so as to satisfy simultaneously your obligations under this | |
545 | License and any other pertinent obligations, then as a consequence you may | |
546 | not convey it at all. For example, if you agree to terms that obligate you | |
547 | to collect a royalty for further conveying from those to whom you convey | |
548 | the Program, the only way you could satisfy both those terms and this | |
549 | License would be to refrain entirely from conveying the Program. | |
550 | ||
551 | 13. Use with the GNU Affero General Public License. | |
552 | ||
553 | Notwithstanding any other provision of this License, you have | |
554 | permission to link or combine any covered work with a work licensed | |
555 | under version 3 of the GNU Affero General Public License into a single | |
556 | combined work, and to convey the resulting work. The terms of this | |
557 | License will continue to apply to the part which is the covered work, | |
558 | but the special requirements of the GNU Affero General Public License, | |
559 | section 13, concerning interaction through a network will apply to the | |
560 | combination as such. | |
561 | ||
562 | 14. Revised Versions of this License. | |
563 | ||
564 | The Free Software Foundation may publish revised and/or new versions of | |
565 | the GNU General Public License from time to time. Such new versions will | |
566 | be similar in spirit to the present version, but may differ in detail to | |
567 | address new problems or concerns. | |
568 | ||
569 | Each version is given a distinguishing version number. If the | |
570 | Program specifies that a certain numbered version of the GNU General | |
571 | Public License "or any later version" applies to it, you have the | |
572 | option of following the terms and conditions either of that numbered | |
573 | version or of any later version published by the Free Software | |
574 | Foundation. If the Program does not specify a version number of the | |
575 | GNU General Public License, you may choose any version ever published | |
576 | by the Free Software Foundation. | |
577 | ||
578 | If the Program specifies that a proxy can decide which future | |
579 | versions of the GNU General Public License can be used, that proxy's | |
580 | public statement of acceptance of a version permanently authorizes you | |
581 | to choose that version for the Program. | |
582 | ||
583 | Later license versions may give you additional or different | |
584 | permissions. However, no additional obligations are imposed on any | |
585 | author or copyright holder as a result of your choosing to follow a | |
586 | later version. | |
587 | ||
588 | 15. Disclaimer of Warranty. | |
589 | ||
590 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | |
591 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | |
592 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | |
593 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | |
594 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
595 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | |
596 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | |
597 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |
598 | ||
599 | 16. Limitation of Liability. | |
600 | ||
601 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |
602 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | |
603 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | |
604 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | |
605 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | |
606 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | |
607 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | |
608 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | |
609 | SUCH DAMAGES. | |
610 | ||
611 | 17. Interpretation of Sections 15 and 16. | |
612 | ||
613 | If the disclaimer of warranty and limitation of liability provided | |
614 | above cannot be given local legal effect according to their terms, | |
615 | reviewing courts shall apply local law that most closely approximates | |
616 | an absolute waiver of all civil liability in connection with the | |
617 | Program, unless a warranty or assumption of liability accompanies a | |
618 | copy of the Program in return for a fee. | |
619 | ||
620 | END OF TERMS AND CONDITIONS | |
621 | ||
622 | How to Apply These Terms to Your New Programs | |
623 | ||
624 | If you develop a new program, and you want it to be of the greatest | |
625 | possible use to the public, the best way to achieve this is to make it | |
626 | free software which everyone can redistribute and change under these terms. | |
627 | ||
628 | To do so, attach the following notices to the program. It is safest | |
629 | to attach them to the start of each source file to most effectively | |
630 | state the exclusion of warranty; and each file should have at least | |
631 | the "copyright" line and a pointer to where the full notice is found. | |
632 | ||
633 | <one line to give the program's name and a brief idea of what it does.> | |
634 | Copyright (C) <year> <name of author> | |
635 | ||
636 | This program is free software: you can redistribute it and/or modify | |
637 | it under the terms of the GNU General Public License as published by | |
638 | the Free Software Foundation, either version 3 of the License, or | |
639 | (at your option) any later version. | |
640 | ||
641 | This program is distributed in the hope that it will be useful, | |
642 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
643 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
644 | GNU General Public License for more details. | |
645 | ||
646 | You should have received a copy of the GNU General Public License | |
647 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
648 | ||
649 | Also add information on how to contact you by electronic and paper mail. | |
650 | ||
651 | If the program does terminal interaction, make it output a short | |
652 | notice like this when it starts in an interactive mode: | |
653 | ||
654 | <program> Copyright (C) <year> <name of author> | |
655 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |
656 | This is free software, and you are welcome to redistribute it | |
657 | under certain conditions; type `show c' for details. | |
658 | ||
659 | The hypothetical commands `show w' and `show c' should show the appropriate | |
660 | parts of the General Public License. Of course, your program's commands | |
661 | might be different; for a GUI interface, you would use an "about box". | |
662 | ||
663 | You should also get your employer (if you work as a programmer) or school, | |
664 | if any, to sign a "copyright disclaimer" for the program, if necessary. | |
665 | For more information on this, and how to apply and follow the GNU GPL, see | |
666 | <http://www.gnu.org/licenses/>. | |
667 | ||
668 | The GNU General Public License does not permit incorporating your program | |
669 | into proprietary programs. If your program is a subroutine library, you | |
670 | may consider it more useful to permit linking proprietary applications with | |
671 | the library. If this is what you want to do, use the GNU Lesser General | |
672 | Public License instead of this License. But first, please read | |
673 | <http://www.gnu.org/philosophy/why-not-lgpl.html>. |
0 | # Try to find Libiconv functionality | |
1 | # Once done this will define | |
2 | # | |
3 | # LIBICONV_FOUND - system has Libiconv | |
4 | # LIBICONV_INCLUDE_DIR - Libiconv include directory | |
5 | # LIBICONV_LIBRARIES - Libraries needed to use Libiconv | |
6 | # LIBICONV_SECOND_ARGUMENT_IS_CONST - iconv second argument is const | |
7 | # | |
8 | # TODO: This will enable translations only if Gettext functionality is | |
9 | # present in libc. Must have more robust system for release, where Gettext | |
10 | # functionality can also reside in standalone Gettext library, or the one | |
11 | # embedded within kdelibs (cf. gettext.m4 from Gettext source). | |
12 | ||
13 | # Copyright (c) 2006, Chusslove Illich, <caslav.ilic@gmx.net> | |
14 | # Copyright (c) 2007, Alexander Neundorf, <neundorf@kde.org> | |
15 | # | |
16 | # Redistribution and use is allowed according to the terms of the BSD license. | |
17 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. | |
18 | ||
19 | if(LIBICONV_INCLUDE_DIR AND LIBICONV_LIB_FOUND) | |
20 | set(Libiconv_FIND_QUIETLY TRUE) | |
21 | endif(LIBICONV_INCLUDE_DIR AND LIBICONV_LIB_FOUND) | |
22 | ||
23 | include(CheckCCompilerFlag) | |
24 | include(CheckCSourceCompiles) | |
25 | ||
26 | find_path(LIBICONV_INCLUDE_DIR iconv.h) | |
27 | ||
28 | set(LIBICONV_LIB_FOUND FALSE) | |
29 | ||
30 | if(LIBICONV_INCLUDE_DIR) | |
31 | include(CheckFunctionExists) | |
32 | check_function_exists(iconv_open LIBICONV_LIBC_HAS_ICONV_OPEN) | |
33 | ||
34 | if (LIBICONV_LIBC_HAS_ICONV_OPEN) | |
35 | set(LIBICONV_LIBRARIES) | |
36 | set(LIBICONV_LIB_FOUND TRUE) | |
37 | else (LIBICONV_LIBC_HAS_ICONV_OPEN) | |
38 | find_library(LIBICONV_LIBRARIES NAMES iconv) | |
39 | if(LIBICONV_LIBRARIES) | |
40 | set(LIBICONV_LIB_FOUND TRUE) | |
41 | endif(LIBICONV_LIBRARIES) | |
42 | endif (LIBICONV_LIBC_HAS_ICONV_OPEN) | |
43 | ||
44 | if (LIBICONV_LIB_FOUND) | |
45 | check_c_compiler_flag("-Werror" ICONV_HAVE_WERROR) | |
46 | set (CMAKE_C_FLAGS_BACKUP "${CMAKE_C_FLAGS}") | |
47 | if(ICONV_HAVE_WERROR) | |
48 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") | |
49 | endif(ICONV_HAVE_WERROR) | |
50 | set(CMAKE_REQUIRED_INCLUDES "${LIBICONV_INCLUDE_DIR}") | |
51 | set(CMAKE_REQUIRED_LIBRARIES "${LIBICONV_LIBRARIES}") | |
52 | check_c_source_compiles(" | |
53 | #include <iconv.h> | |
54 | int main(){ | |
55 | iconv_t conv = 0; | |
56 | const char* in = 0; | |
57 | size_t ilen = 0; | |
58 | char* out = 0; | |
59 | size_t olen = 0; | |
60 | iconv(conv, &in, &ilen, &out, &olen); | |
61 | return 0; | |
62 | } | |
63 | " LIBICONV_SECOND_ARGUMENT_IS_CONST ) | |
64 | set(CMAKE_REQUIRED_INCLUDES) | |
65 | set(CMAKE_REQUIRED_LIBRARIES) | |
66 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_BACKUP}") | |
67 | endif(LIBICONV_LIB_FOUND) | |
68 | ||
69 | endif(LIBICONV_INCLUDE_DIR) | |
70 | ||
71 | include(FindPackageHandleStandardArgs) | |
72 | find_package_handle_standard_args(Libiconv DEFAULT_MSG LIBICONV_INCLUDE_DIR LIBICONV_LIB_FOUND) | |
73 | ||
74 | mark_as_advanced(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARIES LIBICONV_LIBC_HAS_ICONV_OPEN LIBICONV_LIB_FOUND) |
0 | if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") | |
1 | message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") | |
2 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") | |
3 | ||
4 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) | |
5 | string(REGEX REPLACE "\n" ";" files "${files}") | |
6 | foreach (file ${files}) | |
7 | message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") | |
8 | if (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}") | |
9 | execute_process( | |
10 | COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}" | |
11 | OUTPUT_VARIABLE rm_out | |
12 | RESULT_VARIABLE rm_retval | |
13 | ) | |
14 | if(NOT ${rm_retval} EQUAL 0) | |
15 | message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") | |
16 | endif (NOT ${rm_retval} EQUAL 0) | |
17 | else (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}") | |
18 | message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") | |
19 | endif (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}") | |
20 | endforeach(file)⏎ |
0 | #cmakedefine LIBICONV_SECOND_ARGUMENT_IS_CONST⏎ |
0 | fcitx_add_addon_conf_file(fcitx-unikey.conf) | |
1 | fcitx_add_configdesc_file(fcitx-unikey.desc) | |
2 | fcitx_add_inputmethod_conf_file(unikey.conf) | |
3 | ||
4 | install(FILES unikey.png DESTINATION ${FCITX4_PREFIX}/share/fcitx/skin/default/) | |
5 | install(FILES unikey.png RENAME fcitx-unikey.png DESTINATION share/icons/hicolor/256x256/apps/)⏎ |
0 | [Addon] | |
1 | Name=fcitx-unikey | |
2 | _GeneralName=Unikey | |
3 | _Comment=Unikey Wrapper For Fcitx | |
4 | Category=InputMethod | |
5 | Enabled=True | |
6 | Library=fcitx-unikey.so | |
7 | Type=SharedLibrary | |
8 | IMRegisterMethod=ConfigFile |
0 | [Unikey/InputMethod] | |
1 | Type=Enum | |
2 | DefaultValue=Telex | |
3 | Description=Input Method | |
4 | EnumCount=4 | |
5 | Enum0=Telex | |
6 | Enum1=Vni | |
7 | Enum2=STelex | |
8 | Enum3=STelex2 | |
9 | ||
10 | [Unikey/OutputCharset] | |
11 | Type=Enum | |
12 | DefaultValue=Unicode | |
13 | Description=Output Charset | |
14 | EnumCount=8 | |
15 | Enum0=Unicode | |
16 | Enum1=TCVN3 | |
17 | Enum2=VNI Win | |
18 | Enum3=VIQR | |
19 | Enum4=BK HCM 2 | |
20 | Enum5=CString | |
21 | Enum6=NCR Decimal | |
22 | Enum7=NCR Hex | |
23 | ||
24 | [Unikey/SpellCheck] | |
25 | Type=Boolean | |
26 | DefaultValue=True | |
27 | Description=Enable spell check | |
28 | ||
29 | [Unikey/Macro] | |
30 | Type=Boolean | |
31 | DefaultValue=False | |
32 | Description=Enable macro | |
33 | ||
34 | [Unikey/ModernStyle] | |
35 | Type=Boolean | |
36 | DefaultValue=False | |
37 | Description=Use oà, _uý (instead of òa, úy) | |
38 | ||
39 | [Unikey/FreeMarking] | |
40 | Type=Boolean | |
41 | DefaultValue=True | |
42 | Description=Allow type with more freedom | |
43 | ||
44 | [Unikey/AutoNonVnRestore] | |
45 | Type=Boolean | |
46 | DefaultValue=True | |
47 | Description=Auto restore keys with invalid words | |
48 | ||
49 | [Unikey/ProcessWAtBegin] | |
50 | Type=Boolean | |
51 | DefaultValue=True | |
52 | Description=Process W at word begin | |
53 | ||
54 | [DescriptionFile] | |
55 | LocaleDomain=fcitx-unikey |
0 | [InputMethod] | |
1 | UniqueName=unikey | |
2 | _Name=Unikey | |
3 | IconName=unikey | |
4 | Priority=1 | |
5 | LangCode=vi | |
6 | Parent=fcitx-unikey |
Binary diff not shown
0 | file(GLOB PO_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.po) | |
1 | file(RELATIVE_PATH REL_SOURCE_ROOT ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}) | |
2 | if ("${REL_SOURCE_ROOT}" STREQUAL "") | |
3 | set(REL_SOURCE_ROOT ".") | |
4 | endif("${REL_SOURCE_ROOT}" STREQUAL "") | |
5 | ||
6 | set(POT_FILE fcitx-unikey.pot) | |
7 | ||
8 | configure_file(POTFILES.in.in ${CMAKE_CURRENT_BINARY_DIR}/POTFILES.in) | |
9 | ||
10 | extract_fcitx_addon_conf_postring() | |
11 | ||
12 | add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/desc.po | |
13 | COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/getdescpo ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} | |
14 | DEPENDS getdescpo) | |
15 | ||
16 | add_custom_target( | |
17 | pot | |
18 | COMMAND INTLTOOL_EXTRACT=${INTLTOOL_EXTRACT} srcdir=${CMAKE_CURRENT_BINARY_DIR} ${INTLTOOL_UPDATE} --gettext-package fcitx-unikey --pot | |
19 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | |
20 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/conf.po ${CMAKE_CURRENT_BINARY_DIR}/desc.po | |
21 | ) | |
22 | ||
23 | # Update .po files and compile them to binary .gmo files | |
24 | gettext_create_translations(${POT_FILE} ALL ${PO_FILES}) | |
25 |
0 | # List of source files which contain translatable strings. | |
1 | ./po/desc.po | |
2 | ./po/conf.po | |
3 | @REL_SOURCE_ROOT@/src/unikey-ui.cpp | |
4 | @REL_SOURCE_ROOT@/src/unikey-config.cpp | |
5 | @REL_SOURCE_ROOT@/src/unikey-config.h | |
6 | @REL_SOURCE_ROOT@/src/unikey-im.cpp | |
7 | @REL_SOURCE_ROOT@/src/unikey-im.h | |
8 | @REL_SOURCE_ROOT@/data/fcitx-unikey.conf.in | |
9 | @REL_SOURCE_ROOT@/data/unikey.conf.in |
0 | # SOME DESCRIPTIVE TITLE. | |
1 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | |
2 | # This file is distributed under the same license as the PACKAGE package. | |
3 | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | |
4 | # | |
5 | #, fuzzy | |
6 | msgid "" | |
7 | msgstr "" | |
8 | "Project-Id-Version: PACKAGE VERSION\n" | |
9 | "Report-Msgid-Bugs-To: \n" | |
10 | "POT-Creation-Date: 2012-05-05 16:38+0800\n" | |
11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | |
12 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | |
13 | "Language-Team: LANGUAGE <LL@li.org>\n" | |
14 | "Language: \n" | |
15 | "MIME-Version: 1.0\n" | |
16 | "Content-Type: text/plain; charset=UTF-8\n" | |
17 | "Content-Transfer-Encoding: 8bit\n" | |
18 | ||
19 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:4 | |
20 | msgid "Input Method" | |
21 | msgstr "" | |
22 | ||
23 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:14 | |
24 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:137 | |
25 | msgid "Output Charset" | |
26 | msgstr "" | |
27 | ||
28 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:28 | |
29 | msgid "Enable spell check" | |
30 | msgstr "" | |
31 | ||
32 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:33 | |
33 | msgid "Enable macro" | |
34 | msgstr "" | |
35 | ||
36 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:38 | |
37 | msgid "Use oà, _uý (instead of òa, úy)" | |
38 | msgstr "" | |
39 | ||
40 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:43 | |
41 | msgid "Allow type with more freedom" | |
42 | msgstr "" | |
43 | ||
44 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:48 | |
45 | msgid "Auto restore keys with invalid words" | |
46 | msgstr "" | |
47 | ||
48 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:53 | |
49 | msgid "Process W at word begin" | |
50 | msgstr "" | |
51 | ||
52 | # unknown | |
53 | #: /home/saber/Develop/fcitx-unikey/build/po/tmp/fcitx-unikey.conf.in.h:1 | |
54 | #: /home/saber/Develop/fcitx-unikey/build/po/tmp/unikey.conf.in.h:1 | |
55 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-im.cpp:131 | |
56 | msgid "Unikey" | |
57 | msgstr "" | |
58 | ||
59 | #: unknown | |
60 | msgid "BK HCM 2" | |
61 | msgstr "" | |
62 | ||
63 | #: unknown | |
64 | msgid "CString" | |
65 | msgstr "" | |
66 | ||
67 | #: unknown | |
68 | msgid "NCR Decimal" | |
69 | msgstr "" | |
70 | ||
71 | #: unknown | |
72 | msgid "NCR Hex" | |
73 | msgstr "" | |
74 | ||
75 | #: unknown | |
76 | msgid "STelex" | |
77 | msgstr "" | |
78 | ||
79 | #: unknown | |
80 | msgid "STelex2" | |
81 | msgstr "" | |
82 | ||
83 | #: unknown | |
84 | msgid "TCVN3" | |
85 | msgstr "" | |
86 | ||
87 | #: unknown | |
88 | msgid "Telex" | |
89 | msgstr "" | |
90 | ||
91 | #: unknown | |
92 | msgid "Unicode" | |
93 | msgstr "" | |
94 | ||
95 | #: unknown | |
96 | msgid "VIQR" | |
97 | msgstr "" | |
98 | ||
99 | #: unknown | |
100 | msgid "Vni" | |
101 | msgstr "" | |
102 | ||
103 | #: unknown | |
104 | msgid "VNI Win" | |
105 | msgstr "" | |
106 | ||
107 | #: /home/saber/Develop/fcitx-unikey/build/po/tmp/fcitx-unikey.conf.in.h:2 | |
108 | msgid "Unikey Wrapper For Fcitx" | |
109 | msgstr "" | |
110 | ||
111 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:86 | |
112 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:153 | |
113 | msgid "Choose input method" | |
114 | msgstr "" | |
115 | ||
116 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:94 | |
117 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:159 | |
118 | msgid "Choose output charset" | |
119 | msgstr "" | |
120 | ||
121 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:100 | |
122 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:163 | |
123 | msgid "Spell Check" | |
124 | msgstr "" | |
125 | ||
126 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:101 | |
127 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:164 | |
128 | msgid "Enable Spell Check" | |
129 | msgstr "" | |
130 | ||
131 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:108 | |
132 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:168 | |
133 | msgid "Macro" | |
134 | msgstr "" | |
135 | ||
136 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:109 | |
137 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:169 | |
138 | msgid "Enable Macro" | |
139 | msgstr "" | |
140 | ||
141 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:123 | |
142 | msgid "Unikey Input Method" | |
143 | msgstr "" | |
144 | ||
145 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:163 | |
146 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:168 | |
147 | msgid "N" | |
148 | msgstr "" |
0 | #!/bin/sh | |
1 | filename=desc.po | |
2 | indir=$1 | |
3 | outdir=$2 | |
4 | ||
5 | cd "$outdir" | |
6 | ||
7 | rm -f "$outdir/$filename"; touch "$outdir/$filename" | |
8 | ||
9 | cat > "$outdir/$filename" <<EOF | |
10 | # SOME DESCRIPTIVE TITLE. | |
11 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | |
12 | # This file is distributed under the same license as the PACKAGE package. | |
13 | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | |
14 | # | |
15 | #, fuzzy | |
16 | msgid "" | |
17 | msgstr "" | |
18 | "Project-Id-Version: PACKAGE VERSION\n" | |
19 | "Report-Msgid-Bugs-To: fcitx-dev@googlegroups.com\n" | |
20 | "POT-Creation-Date: 2010-11-17 11:48+0800\n" | |
21 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | |
22 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | |
23 | "Language-Team: LANGUAGE <LL@li.org>\n" | |
24 | "Language: \n" | |
25 | "MIME-Version: 1.0\n" | |
26 | "Content-Type: text/plain; charset=UTF-8\n" | |
27 | "Content-Transfer-Encoding: 8bit\n" | |
28 | EOF | |
29 | ||
30 | cd $indir | |
31 | ||
32 | descfiles=`find "$indir" -name ".hg" -prune -or -name "test" -prune -or -iname "*.desc" | grep desc` | |
33 | ||
34 | # Extract Description | |
35 | for f in $descfiles | |
36 | do | |
37 | awk '/^[\t ]*Description=/ { print "\n#: '$f':" NR"\n" "msgid \"" substr($0, 13)"\"\n" "msgstr \"\""}' "$f" >> "$outdir/$filename" | |
38 | done | |
39 | ||
40 | # Extract Group Name | |
41 | grep -nH '^\[' $descfiles | grep -v 'DescriptionFile' | awk ' "^[" { split($0, a, ":"); split(a[3], b, "/"); print substr(b[1], 2); }' | sort | uniq | awk '{ print "# unknown\nmsgid \""$0"\"\nmsgstr \"\"\n"; }' >> "$outdir/$filename" | |
42 | ||
43 | # Extract Enum Name | |
44 | grep -h 'Enum[0-9]' $descfiles | sed -e 's/Enum[0-9]=//g' | sort | uniq | awk '{ print "#: unknown\nmsgid \""$0"\"\nmsgstr \"\"\n"; }' >> "$outdir/$filename" | |
45 |
0 | # Vietnamese translations for ibus-unikey package | |
1 | # Bản dịch Việt ngữ cho gói tin ibus-unikey. | |
2 | # Copyright (C) 2009 Free Software Foundation, Inc. | |
3 | # This file is distributed under the same license as the ibus-unikey package. | |
4 | # | |
5 | # Lê Quốc Tuấn <mr.lequoctuan@gmail.com>, 2009. | |
6 | # Weng Xuetian <wengxt@gmail.com>, 2012. | |
7 | msgid "" | |
8 | msgstr "" | |
9 | "Project-Id-Version: ibus-unikey 0.6.1\n" | |
10 | "Report-Msgid-Bugs-To: \n" | |
11 | "POT-Creation-Date: 2012-05-05 16:38+0800\n" | |
12 | "PO-Revision-Date: 2012-05-05 16:39+0800\n" | |
13 | "Last-Translator: Weng Xuetian <wengxt@gmail.com>\n" | |
14 | "Language-Team: Chinese Simplified <kde-i18n-doc@kde.org>\n" | |
15 | "Language: zh_CN\n" | |
16 | "MIME-Version: 1.0\n" | |
17 | "Content-Type: text/plain; charset=UTF-8\n" | |
18 | "Content-Transfer-Encoding: 8bit\n" | |
19 | "Plural-Forms: nplurals=1; plural=0;\n" | |
20 | "X-Poedit-Language: Vietnamese\n" | |
21 | "X-Poedit-Country: VIET NAM\n" | |
22 | "X-Poedit-SourceCharset: utf-8\n" | |
23 | "X-Generator: Lokalize 1.4\n" | |
24 | ||
25 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:43 | |
26 | msgid "Allow type with more freedom" | |
27 | msgstr "Tự động trả phím khi gõ từ không hợp lệ" | |
28 | ||
29 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:48 | |
30 | msgid "Auto restore keys with invalid words" | |
31 | msgstr "Tự động trả phím khi gõ từ không hợp lệ" | |
32 | ||
33 | #: unknown | |
34 | msgid "BK HCM 2" | |
35 | msgstr "BK HCM 2" | |
36 | ||
37 | #: unknown | |
38 | msgid "CString" | |
39 | msgstr "CString" | |
40 | ||
41 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:86 | |
42 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:153 | |
43 | msgid "Choose input method" | |
44 | msgstr "Chọn kiểu gõ" | |
45 | ||
46 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:94 | |
47 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:159 | |
48 | msgid "Choose output charset" | |
49 | msgstr "Chọn bảng mã" | |
50 | ||
51 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:109 | |
52 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:169 | |
53 | msgid "Enable Macro" | |
54 | msgstr "Bật gõ tắt" | |
55 | ||
56 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:101 | |
57 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:164 | |
58 | msgid "Enable Spell Check" | |
59 | msgstr "Bật kiểm tra chính tả" | |
60 | ||
61 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:33 | |
62 | msgid "Enable macro" | |
63 | msgstr "Bật gõ tắt" | |
64 | ||
65 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:28 | |
66 | msgid "Enable spell check" | |
67 | msgstr "Bật kiểm tra chính tả" | |
68 | ||
69 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:4 | |
70 | msgid "Input Method" | |
71 | msgstr "Kiểu gõ" | |
72 | ||
73 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:108 | |
74 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:168 | |
75 | msgid "Macro" | |
76 | msgstr "gõ tắt" | |
77 | ||
78 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:163 | |
79 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:168 | |
80 | msgid "N" | |
81 | msgstr "N" | |
82 | ||
83 | #: unknown | |
84 | msgid "NCR Decimal" | |
85 | msgstr "NCR Decimal" | |
86 | ||
87 | #: unknown | |
88 | msgid "NCR Hex" | |
89 | msgstr "NCR Hex" | |
90 | ||
91 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:14 | |
92 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:137 | |
93 | msgid "Output Charset" | |
94 | msgstr "Bảng mã" | |
95 | ||
96 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:53 | |
97 | msgid "Process W at word begin" | |
98 | msgstr "Xử lý phím W ở đầu từ" | |
99 | ||
100 | #: unknown | |
101 | msgid "STelex" | |
102 | msgstr "STelex" | |
103 | ||
104 | #: unknown | |
105 | msgid "STelex2" | |
106 | msgstr "STelex2" | |
107 | ||
108 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:100 | |
109 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:163 | |
110 | msgid "Spell Check" | |
111 | msgstr "kiểm tra chính tả" | |
112 | ||
113 | #: unknown | |
114 | msgid "TCVN3" | |
115 | msgstr "TCVN3" | |
116 | ||
117 | #: unknown | |
118 | msgid "Telex" | |
119 | msgstr "Telex" | |
120 | ||
121 | #: unknown | |
122 | msgid "Unicode" | |
123 | msgstr "Unicode" | |
124 | ||
125 | # unknown | |
126 | #: /home/saber/Develop/fcitx-unikey/build/po/tmp/fcitx-unikey.conf.in.h:1 | |
127 | #: /home/saber/Develop/fcitx-unikey/build/po/tmp/unikey.conf.in.h:1 | |
128 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-im.cpp:131 | |
129 | msgid "Unikey" | |
130 | msgstr "Unikey" | |
131 | ||
132 | #: /home/saber/Develop/fcitx-unikey/build/po/../..//src/unikey-ui.cpp:123 | |
133 | msgid "Unikey Input Method" | |
134 | msgstr "Unikey Kiểu gõ" | |
135 | ||
136 | #: /home/saber/Develop/fcitx-unikey/build/po/tmp/fcitx-unikey.conf.in.h:2 | |
137 | msgid "Unikey Wrapper For Fcitx" | |
138 | msgstr "" | |
139 | ||
140 | #: /home/saber/Develop/fcitx-unikey/data/fcitx-unikey.desc:38 | |
141 | msgid "Use oà, _uý (instead of òa, úy)" | |
142 | msgstr "Dùng oà, _uý (thay vì òa, úy)" | |
143 | ||
144 | #: unknown | |
145 | msgid "VIQR" | |
146 | msgstr "VIQR" | |
147 | ||
148 | #: unknown | |
149 | msgid "VNI Win" | |
150 | msgstr "VNI Win" | |
151 | ||
152 | #: unknown | |
153 | msgid "Vni" | |
154 | msgstr "Vni" | |
155 | ||
156 | #~ msgid "(replace text)" | |
157 | #~ msgstr "(chuỗi thay thế)" | |
158 | ||
159 | #~ msgid "<b>Input/Output</b>" | |
160 | #~ msgstr "<b>Nhập/Xuất</b>" | |
161 | ||
162 | #~ msgid "<b>Options</b>" | |
163 | #~ msgstr "<b>Tùy chọn</b>" | |
164 | ||
165 | #~ msgid "Auto send PreEdit string to Application when mouse move or click" | |
166 | #~ msgstr "" | |
167 | #~ "Tự động gửi chuỗi PreEdit đến ứng dụng khi chuột di chuyển hoặc click" | |
168 | ||
169 | #~ msgid "Capture _mouse event" | |
170 | #~ msgstr "Bắt sự _kiện chuột" | |
171 | ||
172 | #~ msgid "Capture mouse event" | |
173 | #~ msgstr "Bắt sự kiện chuột" | |
174 | ||
175 | #~ msgid "Choose file to export" | |
176 | #~ msgstr "Chọn tập tin để xuất" | |
177 | ||
178 | #~ msgid "Choose file to import" | |
179 | #~ msgstr "Chọn tập tin để nhập" | |
180 | ||
181 | #~ msgid "Delete _all" | |
182 | #~ msgstr "Xóa _hết" | |
183 | ||
184 | #~ msgid "Full setup utility for IBus-Unikey" | |
185 | #~ msgstr "Tiện ích cài đặt đầy đủ cho IBus-Unikey" | |
186 | ||
187 | #~ msgid "Full setup..." | |
188 | #~ msgstr "Cài đặt đầy đủ..." | |
189 | ||
190 | #~ msgid "IBus-Unikey Setup" | |
191 | #~ msgstr "Cài đặt IBus-Unikey" | |
192 | ||
193 | #~ msgid "If enable, you can decrease mistake when typing" | |
194 | #~ msgstr "Nếu bật, bạn có thể giảm lỗi chính tả khi gõ" | |
195 | ||
196 | #~ msgid "Macro table definition" | |
197 | #~ msgstr "Định nghĩa bảng gõ tắt" | |
198 | ||
199 | #~ msgid "Options" | |
200 | #~ msgstr "Tùy chọn" | |
201 | ||
202 | #~ msgid "Options for Unikey" | |
203 | #~ msgstr "Tùy chọn cho Unikey" | |
204 | ||
205 | #~ msgid "Replace with" | |
206 | #~ msgstr "Thay thế bởi" | |
207 | ||
208 | #~ msgid "Simple Telex" | |
209 | #~ msgstr "Simple Telex" | |
210 | ||
211 | #~ msgid "Simple Telex 2" | |
212 | #~ msgstr "Simple Telex 2" | |
213 | ||
214 | #, fuzzy | |
215 | #~ msgid "Toggle Macro" | |
216 | #~ msgstr "Bật gõ tắt" | |
217 | ||
218 | #, fuzzy | |
219 | #~ msgid "Toggle Spell Check" | |
220 | #~ msgstr "Bật kiểm tra chính tả" | |
221 | ||
222 | #~ msgid "" | |
223 | #~ "Vietnamese Input Method Engine for IBus using Unikey Engine\n" | |
224 | #~ "Usage:\n" | |
225 | #~ " - Choose input method, output charset, options in language bar.\n" | |
226 | #~ " - There are 4 input methods: Telex, Vni, STelex (simple telex) and " | |
227 | #~ "STelex2 (which same as STelex, the difference is it use w as ư).\n" | |
228 | #~ " - And 7 output charsets: Unicode (UTF-8), TCVN3, VNI Win, VIQR, " | |
229 | #~ "CString, NCR Decimal and NCR Hex.\n" | |
230 | #~ " - Use <Shift>+<Space> or <Shift>+<Shift> to restore keystrokes.\n" | |
231 | #~ " - Use <Control> to commit a word." | |
232 | #~ msgstr "" | |
233 | #~ "Bộ gõ tiếng Việt cho IBus dùng Unikey Engine\n" | |
234 | #~ "Sử dụng:\n" | |
235 | #~ " - Chọn kiểu gõ, bảng mã, tùy chọn trên thanh ngôn ngữ.\n" | |
236 | #~ " - Có 4 kiểu gõ: Telex, Vni, STelex (telex đơn giản) và STelex2 (giống " | |
237 | #~ "như STelex, chỉ khác là nó dùng w như ư).\n" | |
238 | #~ " - Và 7 bảng mã: Unicode (UTF-8), TCVN3, VNI Win, VIQR, CString, NCR " | |
239 | #~ "Decimal và NCR Hex.\n" | |
240 | #~ " - Dùng <Shift>+<Space> hoặc <Shift>+<Shift> để khôi phục phím.\n" | |
241 | #~ " - Dùng <Control> để xác nhận từ (kết thúc từ)." | |
242 | ||
243 | #~ msgid "Word" | |
244 | #~ msgstr "Từ" | |
245 | ||
246 | #~ msgid "_Edit macro" | |
247 | #~ msgstr "_Sửa bảng gõ tắt" | |
248 | ||
249 | #~ msgid "_Export..." | |
250 | #~ msgstr "_Xuất..." | |
251 | ||
252 | #~ msgid "_Import..." | |
253 | #~ msgstr "_Nhập..." |
0 | include_directories ( | |
1 | ${PROJECT_SOURCE_DIR}/unikey | |
2 | ${FCITX4_FCITX_INCLUDE_DIRS} | |
3 | ${FCITX4_FCITX_CONFIG_INCLUDE_DIRS} | |
4 | ${FCITX4_FCITX_UTILS_INCLUDE_DIRS} | |
5 | ${PROJECT_BINARY_DIR} | |
6 | ${LIBICONV_INCLUDE_DIR} | |
7 | ) | |
8 | ||
9 | set( fcitx_unikey_sources | |
10 | unikey-im.cpp | |
11 | unikey-config.cpp | |
12 | unikey-ui.cpp | |
13 | ) | |
14 | ||
15 | set(UNIKEY_SRCS | |
16 | ../unikey/byteio.cpp | |
17 | ../unikey/byteio.h | |
18 | ../unikey/charset.cpp | |
19 | ../unikey/charset.h | |
20 | ../unikey/convert.cpp | |
21 | ../unikey/data.cpp | |
22 | ../unikey/data.h | |
23 | ../unikey/error.cpp | |
24 | ../unikey/inputproc.cpp | |
25 | ../unikey/inputproc.h | |
26 | ../unikey/keycons.h | |
27 | ../unikey/mactab.cpp | |
28 | ../unikey/mactab.h | |
29 | ../unikey/pattern.cpp | |
30 | ../unikey/pattern.h | |
31 | ../unikey/ukengine.cpp | |
32 | ../unikey/ukengine.h | |
33 | ../unikey/unikey.cpp | |
34 | ../unikey/unikey.h | |
35 | ../unikey/usrkeymap.cpp | |
36 | ../unikey/usrkeymap.h | |
37 | ../unikey/vnconv.h | |
38 | ../unikey/vnlexi.h | |
39 | ) | |
40 | ||
41 | add_definitions( -DLOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/share/locale\" ) | |
42 | ||
43 | fcitx_add_addon(fcitx-unikey ${fcitx_unikey_sources} ${UNIKEY_SRCS} ) |
0 | /*************************************************************************** | |
1 | * Copyright (C) 2012~2012 by CSSlayer * | |
2 | * wengxt@gmail.com * | |
3 | * * | |
4 | * This program is free software: you can redistribute it and/or modify * | |
5 | * it under the terms of the GNU General Public License as published by * | |
6 | * the Free Software Foundation, either version 3 of the License, or * | |
7 | * (at your option) any later version. * | |
8 | * * | |
9 | * This program is distributed in the hope that it will be useful, * | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
12 | * GNU General Public License for more details. * | |
13 | * * | |
14 | * You should have received a copy of the GNU General Public License * | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
16 | * * | |
17 | ***************************************************************************/ | |
18 | ||
19 | #include "unikey-config.h" | |
20 | ||
21 | /* USE fcitx provided macro to bind config and variable */ | |
22 | CONFIG_BINDING_BEGIN(UnikeyConfig) | |
23 | CONFIG_BINDING_REGISTER("Unikey", "InputMethod", im) | |
24 | CONFIG_BINDING_REGISTER("Unikey", "OuputCharset", oc) | |
25 | CONFIG_BINDING_REGISTER("Unikey", "SpellCheck", spellCheck) | |
26 | CONFIG_BINDING_REGISTER("Unikey", "Macro", macro) | |
27 | CONFIG_BINDING_REGISTER("Unikey", "ModernStyle", modernStyle) | |
28 | CONFIG_BINDING_REGISTER("Unikey", "FreeMarking", freeMarking) | |
29 | CONFIG_BINDING_REGISTER("Unikey", "AutoNonVnRestore", autoNonVnRestore) | |
30 | CONFIG_BINDING_REGISTER("Unikey", "ProcessWAtBegin", process_w_at_begin) | |
31 | CONFIG_BINDING_END()⏎ |
0 | /*************************************************************************** | |
1 | * Copyright (C) 2012~2012 by CSSlayer * | |
2 | * wengxt@gmail.com * | |
3 | * * | |
4 | * This program is free software: you can redistribute it and/or modify * | |
5 | * it under the terms of the GNU General Public License as published by * | |
6 | * the Free Software Foundation, either version 3 of the License, or * | |
7 | * (at your option) any later version. * | |
8 | * * | |
9 | * This program is distributed in the hope that it will be useful, * | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
12 | * GNU General Public License for more details. * | |
13 | * * | |
14 | * You should have received a copy of the GNU General Public License * | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
16 | * * | |
17 | ***************************************************************************/ | |
18 | ||
19 | #ifndef UNIKEY_CONFIG_H | |
20 | #define UNIKEY_CONFIG_H | |
21 | #include <keycons.h> | |
22 | #include <fcitx-config/fcitx-config.h> | |
23 | ||
24 | enum UkConv { | |
25 | UKCONV_XUTF8, | |
26 | UKCONV_TCVN3, | |
27 | UKCONV_VNIWIN, | |
28 | UKCONV_VIQR, | |
29 | UKCONV_BKHCM2, | |
30 | UKCONV_UNI_CSTRING, | |
31 | UKCONV_UNIREF, | |
32 | UKCONV_UNIREF_HEX | |
33 | }; | |
34 | ||
35 | struct UnikeyConfig | |
36 | { | |
37 | FcitxGenericConfig gconfig; | |
38 | UkInputMethod im; | |
39 | UkConv oc; | |
40 | boolean spellCheck; | |
41 | boolean macro; | |
42 | boolean process_w_at_begin; | |
43 | boolean autoNonVnRestore; | |
44 | boolean modernStyle; | |
45 | boolean freeMarking; | |
46 | }; | |
47 | ||
48 | ||
49 | CONFIG_BINDING_DECLARE(UnikeyConfig); | |
50 | ||
51 | #endif // UNIKEY_CONFIG_H⏎ |
0 | /*************************************************************************** | |
1 | * Copyright (C) 2012~2012 by CSSlayer * | |
2 | * wengxt@gmail.com * | |
3 | * * | |
4 | * This program is free software: you can redistribute it and/or modify * | |
5 | * it under the terms of the GNU General Public License as published by * | |
6 | * the Free Software Foundation, either version 3 of the License, or * | |
7 | * (at your option) any later version. * | |
8 | * * | |
9 | * This program is distributed in the hope that it will be useful, * | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
12 | * GNU General Public License for more details. * | |
13 | * * | |
14 | * You should have received a copy of the GNU General Public License * | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
16 | * * | |
17 | ***************************************************************************/ | |
18 | ||
19 | #include <iconv.h> | |
20 | ||
21 | #include <string> | |
22 | ||
23 | #include <fcitx/fcitx.h> | |
24 | #include <fcitx/ime.h> | |
25 | #include <fcitx/hook.h> | |
26 | #include <fcitx/instance.h> | |
27 | #include <fcitx-config/xdg.h> | |
28 | #include <fcitx-utils/log.h> | |
29 | #include <errno.h> | |
30 | ||
31 | #include "config.h" | |
32 | #include "unikey.h" | |
33 | #include "keycons.h" | |
34 | #include "vnconv.h" | |
35 | #include "unikey-config.h" | |
36 | #include "unikey-im.h" | |
37 | #include "unikey-ui.h" | |
38 | ||
39 | #define CONVERT_BUF_SIZE 1024 | |
40 | ||
41 | #ifdef LIBICONV_SECOND_ARGUMENT_IS_CONST | |
42 | typedef const char* IconvStr; | |
43 | #else | |
44 | typedef char* IconvStr; | |
45 | #endif | |
46 | ||
47 | static void* FcitxUnikeyCreate(FcitxInstance* instance); | |
48 | static void FcitxUnikeyDestroy(void* arg); | |
49 | static INPUT_RETURN_VALUE FcitxUnikeyDoInput(void* arg, FcitxKeySym sym, unsigned int state); | |
50 | static boolean FcitxUnikeyInit(void* arg); | |
51 | static void FcitxUnikeyReset(void* arg); | |
52 | static void FcitxUnikeyResetUI(void* arg); | |
53 | static INPUT_RETURN_VALUE FcitxUnikeyDoInputPreedit(FcitxUnikey* unikey, FcitxKeySym sym, unsigned int state); | |
54 | static void FcitxUnikeyEraseChars(FcitxUnikey *unikey, int num_chars); | |
55 | static void FcitxUnikeyUpdatePreedit(FcitxUnikey *unikey); | |
56 | ||
57 | static boolean LoadUnikeyConfig(UnikeyConfig* config); | |
58 | static void ConfigUnikey(FcitxUnikey* unikey); | |
59 | static void ReloadConfigFcitxUnikey(void* arg); | |
60 | static void SaveUnikeyConfig(UnikeyConfig* fa); | |
61 | ||
62 | static int latinToUtf(unsigned char* dst, unsigned char* src, int inSize, int* pOutSize); | |
63 | ||
64 | FCITX_EXPORT_API | |
65 | FcitxIMClass ime = { | |
66 | FcitxUnikeyCreate, | |
67 | FcitxUnikeyDestroy | |
68 | }; | |
69 | FCITX_EXPORT_API | |
70 | int ABI_VERSION = FCITX_ABI_VERSION; | |
71 | static const unsigned int Unikey_OC[] = {CONV_CHARSET_XUTF8, | |
72 | CONV_CHARSET_TCVN3, | |
73 | CONV_CHARSET_VNIWIN, | |
74 | CONV_CHARSET_VIQR, | |
75 | CONV_CHARSET_BKHCM2, | |
76 | CONV_CHARSET_UNI_CSTRING, | |
77 | CONV_CHARSET_UNIREF, | |
78 | CONV_CHARSET_UNIREF_HEX}; | |
79 | static const unsigned int NUM_OUTPUTCHARSET = sizeof(Unikey_OC)/sizeof(Unikey_OC[0]); | |
80 | ||
81 | static const unsigned char WordBreakSyms[] = | |
82 | { | |
83 | ',', ';', ':', '.', '\"', '\'', '!', '?', ' ', | |
84 | '<', '>', '=', '+', '-', '*', '/', '\\', | |
85 | '_', '~', '`', '@', '#', '$', '%', '^', '&', '(', ')', '{', '}', '[', ']', | |
86 | '|' | |
87 | }; | |
88 | ||
89 | static const unsigned char WordAutoCommit[] = | |
90 | { | |
91 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |
92 | 'b', 'c', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', | |
93 | 'p', 'q', 'r', 's', 't', 'v', 'x', 'z', | |
94 | 'B', 'C', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', | |
95 | 'P', 'Q', 'R', 'S', 'T', 'V', 'X', 'Z' | |
96 | }; | |
97 | ||
98 | ||
99 | ||
100 | int FcitxUnikeyUcs4ToUtf8(FcitxUnikey* unikey, const unsigned int c, char buf[UTF8_MAX_LENGTH + 1]) | |
101 | { | |
102 | unsigned int str[2]; | |
103 | str[0] = c; | |
104 | str[1] = 0; | |
105 | ||
106 | size_t ucslen = 1; | |
107 | size_t len = UTF8_MAX_LENGTH; | |
108 | len *= sizeof(char); | |
109 | ucslen *= sizeof(unsigned int); | |
110 | char* p = buf; | |
111 | IconvStr src = (IconvStr) str; | |
112 | iconv(unikey->conv, &src, &ucslen, &p, &len); | |
113 | return (UTF8_MAX_LENGTH - len) / sizeof(char); | |
114 | } | |
115 | ||
116 | ||
117 | void* FcitxUnikeyCreate(FcitxInstance* instance) | |
118 | { | |
119 | FcitxUnikey* unikey = (FcitxUnikey*) fcitx_utils_malloc0(sizeof(FcitxUnikey)); | |
120 | ||
121 | if (!LoadUnikeyConfig(&unikey->config)) | |
122 | { | |
123 | free(unikey); | |
124 | return NULL; | |
125 | } | |
126 | unikey->owner = instance; | |
127 | unikey->preeditstr = new std::string; | |
128 | union { | |
129 | short s; | |
130 | unsigned char b[2]; | |
131 | } endian; | |
132 | endian.s = 0x1234; | |
133 | if (endian.b[0] == 0x12) | |
134 | unikey->conv = iconv_open("utf-8", "ucs-4be"); | |
135 | else | |
136 | unikey->conv = iconv_open("utf-8", "ucs-4le"); | |
137 | ||
138 | FcitxIMIFace iface; | |
139 | memset(&iface, 0, sizeof(FcitxIMIFace)); | |
140 | iface.Init = FcitxUnikeyInit; | |
141 | iface.ResetIM = FcitxUnikeyReset; | |
142 | iface.DoInput = FcitxUnikeyDoInput; | |
143 | iface.ReloadConfig = ReloadConfigFcitxUnikey; | |
144 | ||
145 | FcitxInstanceRegisterIMv2( | |
146 | instance, | |
147 | unikey, | |
148 | "unikey", | |
149 | _("Unikey"), | |
150 | "unikey", | |
151 | iface, | |
152 | 1, | |
153 | "vi" | |
154 | ); | |
155 | ||
156 | UnikeySetup(); | |
157 | ||
158 | InitializeBar(unikey); | |
159 | InitializeMenu(unikey); | |
160 | ||
161 | ConfigUnikey(unikey); | |
162 | ||
163 | FcitxIMEventHook hk; | |
164 | hk.arg = unikey; | |
165 | hk.func = FcitxUnikeyResetUI; | |
166 | ||
167 | FcitxInstanceRegisterResetInputHook(instance, hk); | |
168 | ||
169 | return unikey; | |
170 | } | |
171 | ||
172 | void FcitxUnikeyDestroy(void* arg) | |
173 | { | |
174 | UnikeyCleanup(); | |
175 | } | |
176 | ||
177 | ||
178 | boolean FcitxUnikeyInit(void* arg) | |
179 | { | |
180 | return true; | |
181 | } | |
182 | ||
183 | void FcitxUnikeyReset(void* arg) | |
184 | { | |
185 | FcitxUnikey* unikey = (FcitxUnikey*) arg; | |
186 | ||
187 | UnikeyResetBuf(); | |
188 | unikey->preeditstr->clear(); | |
189 | } | |
190 | ||
191 | void FcitxUnikeyCommit(FcitxUnikey* unikey) | |
192 | { | |
193 | if (unikey->preeditstr->length() > 0) { | |
194 | FcitxInstanceCommitString(unikey->owner, FcitxInstanceGetCurrentIC(unikey->owner), unikey->preeditstr->c_str()); | |
195 | } | |
196 | FcitxUnikeyReset(unikey); | |
197 | } | |
198 | ||
199 | INPUT_RETURN_VALUE FcitxUnikeyDoInput(void* arg, FcitxKeySym sym, unsigned int state) | |
200 | { | |
201 | FcitxUnikey* unikey = (FcitxUnikey*) arg; | |
202 | INPUT_RETURN_VALUE tmp; | |
203 | FcitxInputState* input = FcitxInstanceGetInputState(unikey->owner); | |
204 | /* use origin sym and state here */ | |
205 | sym = (FcitxKeySym) FcitxInputStateGetKeySym(input); | |
206 | state = FcitxInputStateGetKeyState(input); | |
207 | ||
208 | tmp = FcitxUnikeyDoInputPreedit(unikey, sym, state); | |
209 | ||
210 | // check last keyevent with shift | |
211 | if (sym >= FcitxKey_space && sym <=FcitxKey_asciitilde) | |
212 | { | |
213 | unikey->last_key_with_shift = state & FcitxKeyState_Shift; | |
214 | } | |
215 | else | |
216 | { | |
217 | unikey->last_key_with_shift = false; | |
218 | } // end check last keyevent with shift | |
219 | ||
220 | return tmp; | |
221 | } | |
222 | ||
223 | INPUT_RETURN_VALUE FcitxUnikeyDoInputPreedit(FcitxUnikey* unikey, FcitxKeySym sym, unsigned int state) | |
224 | { | |
225 | ||
226 | if (state & FcitxKeyState_Ctrl | |
227 | || state & FcitxKeyState_Alt // alternate mask | |
228 | || sym == FcitxKey_Control_L | |
229 | || sym == FcitxKey_Control_R | |
230 | || sym == FcitxKey_Tab | |
231 | || sym == FcitxKey_Return | |
232 | || sym == FcitxKey_Delete | |
233 | || sym == FcitxKey_KP_Enter | |
234 | || (sym >= FcitxKey_Home && sym <= FcitxKey_Insert) | |
235 | || (sym >= FcitxKey_KP_Home && sym <= FcitxKey_KP_Delete) | |
236 | ) | |
237 | { | |
238 | FcitxUnikeyCommit(unikey); | |
239 | return IRV_FLAG_FORWARD_KEY; | |
240 | } | |
241 | ||
242 | else if ((sym >= FcitxKey_Caps_Lock && sym <= FcitxKey_Hyper_R) | |
243 | || (!(state & FcitxKeyState_Shift) && (sym == FcitxKey_Shift_L || sym == FcitxKey_Shift_R)) // when press one shift key | |
244 | ) | |
245 | { | |
246 | return IRV_TO_PROCESS; | |
247 | } | |
248 | ||
249 | // capture BackSpace | |
250 | else if (sym == FcitxKey_BackSpace) | |
251 | { | |
252 | UnikeyBackspacePress(); | |
253 | ||
254 | if (UnikeyBackspaces == 0 || unikey->preeditstr->empty()) | |
255 | { | |
256 | FcitxUnikeyCommit(unikey); | |
257 | return IRV_FLAG_FORWARD_KEY; | |
258 | } | |
259 | else | |
260 | { | |
261 | if (unikey->preeditstr->length() <= (unsigned int)UnikeyBackspaces) | |
262 | { | |
263 | unikey->preeditstr->clear(); | |
264 | unikey->auto_commit = true; | |
265 | } | |
266 | else | |
267 | { | |
268 | FcitxUnikeyEraseChars(unikey, UnikeyBackspaces); | |
269 | FcitxUnikeyUpdatePreedit(unikey); | |
270 | } | |
271 | ||
272 | // change tone position after press backspace | |
273 | if (UnikeyBufChars > 0) | |
274 | { | |
275 | if (unikey->config.oc == UKCONV_XUTF8) | |
276 | { | |
277 | unikey->preeditstr->append((const char*)UnikeyBuf, UnikeyBufChars); | |
278 | } | |
279 | else | |
280 | { | |
281 | static unsigned char buf[CONVERT_BUF_SIZE]; | |
282 | int bufSize = CONVERT_BUF_SIZE; | |
283 | ||
284 | latinToUtf(buf, UnikeyBuf, UnikeyBufChars, &bufSize); | |
285 | unikey->preeditstr->append((const char*)buf, CONVERT_BUF_SIZE - bufSize); | |
286 | } | |
287 | ||
288 | unikey->auto_commit = false; | |
289 | FcitxUnikeyUpdatePreedit(unikey); | |
290 | } | |
291 | } | |
292 | return IRV_DISPLAY_MESSAGE; | |
293 | } // end capture BackSpace | |
294 | ||
295 | else if (sym >=FcitxKey_KP_Multiply && sym <=FcitxKey_KP_9) | |
296 | { | |
297 | FcitxUnikeyCommit(unikey); | |
298 | return IRV_FLAG_FORWARD_KEY; | |
299 | } | |
300 | ||
301 | // capture ascii printable char | |
302 | else if ((sym >= FcitxKey_space && sym <=FcitxKey_asciitilde) | |
303 | || sym == FcitxKey_Shift_L || sym == FcitxKey_Shift_R) // sure this have FcitxKey_SHIFT_MASK | |
304 | { | |
305 | unsigned int i = 0; | |
306 | ||
307 | UnikeySetCapsState(state & FcitxKeyState_Shift, state & FcitxKeyState_CapsLock); | |
308 | ||
309 | // process sym | |
310 | ||
311 | // auto commit word that never need to change later in preedit string (like consonant - phu am) | |
312 | // if macro enabled, then not auto commit. Because macro may change any word | |
313 | if (unikey->ukopt.macroEnabled == 0 && (UnikeyAtWordBeginning() || unikey->auto_commit)) | |
314 | { | |
315 | for (i =0; i < sizeof(WordAutoCommit); i++) | |
316 | { | |
317 | if (sym == WordAutoCommit[i]) | |
318 | { | |
319 | UnikeyPutChar(sym); | |
320 | unikey->auto_commit = true; | |
321 | return IRV_FLAG_FORWARD_KEY; | |
322 | } | |
323 | } | |
324 | } // end auto commit | |
325 | ||
326 | if ((unikey->config.im == UkTelex || unikey->config.im == UkSimpleTelex2) | |
327 | && unikey->config.process_w_at_begin == false | |
328 | && UnikeyAtWordBeginning() | |
329 | && (sym == FcitxKey_w || sym == FcitxKey_W)) | |
330 | { | |
331 | UnikeyPutChar(sym); | |
332 | if (unikey->ukopt.macroEnabled == 0) | |
333 | { | |
334 | return IRV_TO_PROCESS; | |
335 | } | |
336 | else | |
337 | { | |
338 | unikey->preeditstr->append(sym==FcitxKey_w?"w":"W"); | |
339 | FcitxUnikeyUpdatePreedit(unikey); | |
340 | return IRV_DISPLAY_MESSAGE; | |
341 | } | |
342 | } | |
343 | ||
344 | unikey->auto_commit = false; | |
345 | ||
346 | // shift + space, shift + shift event | |
347 | if ((unikey->last_key_with_shift == false && state & FcitxKeyState_Shift | |
348 | && sym == FcitxKey_space && !UnikeyAtWordBeginning()) | |
349 | || (sym == FcitxKey_Shift_L || sym == FcitxKey_Shift_R) // (&& state & FcitxKey_SHIFT_MASK), sure this have FcitxKey_SHIFT_MASK | |
350 | ) | |
351 | { | |
352 | UnikeyRestoreKeyStrokes(); | |
353 | } // end shift + space, shift + shift event | |
354 | ||
355 | else | |
356 | { | |
357 | UnikeyFilter(sym); | |
358 | } | |
359 | // end process sym | |
360 | ||
361 | // process result of ukengine | |
362 | if (UnikeyBackspaces > 0) | |
363 | { | |
364 | if (unikey->preeditstr->length() <= (unsigned int)UnikeyBackspaces) | |
365 | { | |
366 | unikey->preeditstr->clear(); | |
367 | } | |
368 | else | |
369 | { | |
370 | FcitxUnikeyEraseChars(unikey, UnikeyBackspaces); | |
371 | } | |
372 | } | |
373 | ||
374 | if (UnikeyBufChars > 0) | |
375 | { | |
376 | if (unikey->config.oc == UKCONV_XUTF8) | |
377 | { | |
378 | unikey->preeditstr->append((const char*)UnikeyBuf, UnikeyBufChars); | |
379 | } | |
380 | else | |
381 | { | |
382 | unsigned char buf[CONVERT_BUF_SIZE + 1]; | |
383 | int bufSize = CONVERT_BUF_SIZE; | |
384 | ||
385 | latinToUtf(buf, UnikeyBuf, UnikeyBufChars, &bufSize); | |
386 | unikey->preeditstr->append((const char*)buf, CONVERT_BUF_SIZE - bufSize); | |
387 | } | |
388 | } | |
389 | else if (sym != FcitxKey_Shift_L && sym != FcitxKey_Shift_R) // if ukengine not process | |
390 | { | |
391 | int n; | |
392 | char s[7] = {0, 0, 0, 0, 0, 0, 0}; | |
393 | ||
394 | n = FcitxUnikeyUcs4ToUtf8(unikey, (unsigned int)sym, s); // convert ucs4 to utf8 char | |
395 | unikey->preeditstr->append(s, n); | |
396 | } | |
397 | // end process result of ukengine | |
398 | ||
399 | // commit string: if need | |
400 | if (unikey->preeditstr->length() > 0) | |
401 | { | |
402 | unsigned int i; | |
403 | for (i = 0; i < sizeof(WordBreakSyms); i++) | |
404 | { | |
405 | if (WordBreakSyms[i] == unikey->preeditstr->at(unikey->preeditstr->length()-1) | |
406 | && WordBreakSyms[i] == sym) | |
407 | { | |
408 | FcitxUnikeyCommit(unikey); | |
409 | return IRV_DO_NOTHING; | |
410 | } | |
411 | } | |
412 | } | |
413 | // end commit string | |
414 | ||
415 | FcitxUnikeyUpdatePreedit(unikey); | |
416 | return IRV_DISPLAY_MESSAGE; | |
417 | } //end capture printable char | |
418 | ||
419 | // non process key | |
420 | ||
421 | FcitxUnikeyCommit(unikey); | |
422 | return IRV_FLAG_FORWARD_KEY; | |
423 | } | |
424 | ||
425 | ||
426 | // code from x-unikey, for convert charset that not is XUtf-8 | |
427 | int latinToUtf(unsigned char* dst, unsigned char* src, int inSize, int* pOutSize) | |
428 | { | |
429 | int i; | |
430 | int outLeft; | |
431 | unsigned char ch; | |
432 | ||
433 | outLeft = *pOutSize; | |
434 | ||
435 | for (i=0; i<inSize; i++) | |
436 | { | |
437 | ch = *src++; | |
438 | if (ch < 0x80) | |
439 | { | |
440 | outLeft -= 1; | |
441 | if (outLeft >= 0) | |
442 | *dst++ = ch; | |
443 | } | |
444 | else | |
445 | { | |
446 | outLeft -= 2; | |
447 | if (outLeft >= 0) | |
448 | { | |
449 | *dst++ = (0xC0 | ch >> 6); | |
450 | *dst++ = (0x80 | (ch & 0x3F)); | |
451 | } | |
452 | } | |
453 | } | |
454 | ||
455 | *pOutSize = outLeft; | |
456 | return (outLeft >= 0); | |
457 | } | |
458 | ||
459 | ||
460 | static void FcitxUnikeyEraseChars(FcitxUnikey *unikey, int num_chars) | |
461 | { | |
462 | int i, k; | |
463 | unsigned char c; | |
464 | k = num_chars; | |
465 | ||
466 | for ( i = unikey->preeditstr->length()-1; i >= 0 && k > 0; i--) | |
467 | { | |
468 | c = unikey->preeditstr->at(i); | |
469 | ||
470 | // count down if byte is begin byte of utf-8 char | |
471 | if (c < (unsigned char)'\x80' || c >= (unsigned char)'\xC0') | |
472 | { | |
473 | k--; | |
474 | } | |
475 | } | |
476 | ||
477 | unikey->preeditstr->erase(i+1); | |
478 | } | |
479 | ||
480 | ||
481 | static void FcitxUnikeyUpdatePreedit(FcitxUnikey *unikey) | |
482 | { | |
483 | FcitxInputState* input = FcitxInstanceGetInputState(unikey->owner); | |
484 | FcitxMessages* preedit = FcitxInputStateGetPreedit(input); | |
485 | FcitxMessages* clientPreedit = FcitxInputStateGetClientPreedit(input); | |
486 | FcitxInputContext* ic = FcitxInstanceGetCurrentIC(unikey->owner); | |
487 | FcitxProfile* profile = FcitxInstanceGetProfile(unikey->owner); | |
488 | FcitxInstanceCleanInputWindowUp(unikey->owner); | |
489 | if (ic && ((ic->contextCaps & CAPACITY_PREEDIT) == 0 || !profile->bUsePreedit)) { | |
490 | FcitxMessagesAddMessageAtLast(preedit, MSG_INPUT, "%s", unikey->preeditstr->c_str()); | |
491 | FcitxInputStateSetCursorPos(input, unikey->preeditstr->size()); | |
492 | } | |
493 | FcitxMessagesAddMessageAtLast(clientPreedit, MSG_INPUT, "%s", unikey->preeditstr->c_str()); | |
494 | FcitxInputStateSetClientCursorPos(input, unikey->preeditstr->size()); | |
495 | } | |
496 | ||
497 | CONFIG_DESC_DEFINE(GetUnikeyConfigDesc, "fcitx-unikey.desc") | |
498 | ||
499 | boolean LoadUnikeyConfig(UnikeyConfig* config) | |
500 | { | |
501 | FcitxConfigFileDesc *configDesc = GetUnikeyConfigDesc(); | |
502 | if (!configDesc) | |
503 | return false; | |
504 | ||
505 | FILE *fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-unikey.config", "r", NULL); | |
506 | ||
507 | if (!fp) | |
508 | { | |
509 | if (errno == ENOENT) | |
510 | SaveUnikeyConfig(config); | |
511 | } | |
512 | FcitxConfigFile *cfile = FcitxConfigParseConfigFileFp(fp, configDesc); | |
513 | ||
514 | UnikeyConfigConfigBind(config, cfile, configDesc); | |
515 | FcitxConfigBindSync(&config->gconfig); | |
516 | ||
517 | if (fp) | |
518 | fclose(fp); | |
519 | return true; | |
520 | } | |
521 | ||
522 | void ConfigUnikey(FcitxUnikey* unikey) | |
523 | { | |
524 | unikey->ukopt.macroEnabled = unikey->config.macro; | |
525 | unikey->ukopt.spellCheckEnabled = unikey->config.spellCheck; | |
526 | unikey->ukopt.autoNonVnRestore = unikey->config.autoNonVnRestore; | |
527 | unikey->ukopt.modernStyle = unikey->config.modernStyle; | |
528 | unikey->ukopt.freeMarking = unikey->config.freeMarking; | |
529 | UnikeySetInputMethod(unikey->config.im); | |
530 | UnikeySetOutputCharset(Unikey_OC[unikey->config.oc]); | |
531 | UnikeySetOptions(&unikey->ukopt); | |
532 | ||
533 | UpdateUnikeyUI(unikey); | |
534 | } | |
535 | ||
536 | void ReloadConfigFcitxUnikey(void* arg) | |
537 | { | |
538 | FcitxUnikey* unikey = (FcitxUnikey*) arg; | |
539 | LoadUnikeyConfig(&unikey->config); | |
540 | ConfigUnikey(unikey); | |
541 | } | |
542 | ||
543 | void SaveUnikeyConfig(UnikeyConfig* fa) | |
544 | { | |
545 | FcitxConfigFileDesc *configDesc = GetUnikeyConfigDesc(); | |
546 | FILE *fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-unikey.config", "w", NULL); | |
547 | FcitxConfigSaveConfigFileFp(fp, &fa->gconfig, configDesc); | |
548 | if (fp) | |
549 | fclose(fp); | |
550 | } | |
551 | ||
552 | void FcitxUnikeyResetUI(void* arg) | |
553 | { | |
554 | FcitxUnikey* unikey = (FcitxUnikey*) arg; | |
555 | FcitxInstance* instance = unikey->owner; | |
556 | FcitxIM* im = FcitxInstanceGetCurrentIM(instance); | |
557 | boolean visible; | |
558 | if (!im || strcmp(im->uniqueName, "unikey") != 0) | |
559 | visible = false; | |
560 | else | |
561 | visible = true; | |
562 | FcitxUISetStatusVisable(instance, "unikey-input-method", visible); | |
563 | FcitxUISetStatusVisable(instance, "unikey-output-charset", visible); | |
564 | FcitxUISetStatusVisable(instance, "unikey-spell-check", visible); | |
565 | FcitxUISetStatusVisable(instance, "unikey-macro", visible); | |
566 | } | |
567 | ||
568 | void UpdateUnikeyConfig(FcitxUnikey* unikey) | |
569 | { | |
570 | ConfigUnikey(unikey); | |
571 | SaveUnikeyConfig(&unikey->config); | |
572 | } | |
573 |
0 | /*************************************************************************** | |
1 | * Copyright (C) 2012~2012 by CSSlayer * | |
2 | * wengxt@gmail.com * | |
3 | * * | |
4 | * This program is free software: you can redistribute it and/or modify * | |
5 | * it under the terms of the GNU General Public License as published by * | |
6 | * the Free Software Foundation, either version 3 of the License, or * | |
7 | * (at your option) any later version. * | |
8 | * * | |
9 | * This program is distributed in the hope that it will be useful, * | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
12 | * GNU General Public License for more details. * | |
13 | * * | |
14 | * You should have received a copy of the GNU General Public License * | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
16 | * * | |
17 | ***************************************************************************/ | |
18 | ||
19 | #ifndef UNIKEY_IM_H | |
20 | #define UNIKEY_IM_H | |
21 | #include <iconv.h> | |
22 | #include <string> | |
23 | #include <fcitx/instance.h> | |
24 | #include <libintl.h> | |
25 | ||
26 | #define _(x) dgettext("fcitx-unikey", (x)) | |
27 | #include "unikey-config.h" | |
28 | ||
29 | struct FcitxUnikey | |
30 | { | |
31 | UnikeyConfig config; | |
32 | std::string* preeditstr; | |
33 | UnikeyOptions ukopt; | |
34 | FcitxInstance* owner; | |
35 | bool auto_commit; | |
36 | bool last_key_with_shift; | |
37 | iconv_t conv; | |
38 | FcitxUIMenu imMenu; | |
39 | FcitxUIMenu ocMenu; | |
40 | }; | |
41 | ||
42 | void UpdateUnikeyConfig(FcitxUnikey* unikey); | |
43 | ||
44 | #endif //UNIKEY_IM_H⏎ |
0 | /*************************************************************************** | |
1 | * Copyright (C) 2012~2012 by CSSlayer * | |
2 | * wengxt@gmail.com * | |
3 | * * | |
4 | * This program is free software: you can redistribute it and/or modify * | |
5 | * it under the terms of the GNU General Public License as published by * | |
6 | * the Free Software Foundation, either version 3 of the License, or * | |
7 | * (at your option) any later version. * | |
8 | * * | |
9 | * This program is distributed in the hope that it will be useful, * | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
12 | * GNU General Public License for more details. * | |
13 | * * | |
14 | * You should have received a copy of the GNU General Public License * | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
16 | * * | |
17 | ***************************************************************************/ | |
18 | ||
19 | #include "unikey-im.h" | |
20 | ||
21 | const char* Unikey_IMNames[] = {"Telex", "Vni", "STelex", "STelex2"}; | |
22 | const UkInputMethod Unikey_IM[] = {UkTelex, UkVni, UkSimpleTelex, UkSimpleTelex2}; | |
23 | const unsigned int NUM_INPUTMETHOD = sizeof(Unikey_IM)/sizeof(Unikey_IM[0]); | |
24 | ||
25 | const char* Unikey_OCNames[] = {"Unicode", | |
26 | "TCVN3", | |
27 | "VNI Win", | |
28 | "VIQR", | |
29 | "BK HCM 2", | |
30 | "CString", | |
31 | "NCR Decimal", | |
32 | "NCR Hex"}; | |
33 | const unsigned int NUM_OUTPUTCHARSET = sizeof(Unikey_OCNames)/sizeof(Unikey_OCNames[0]); | |
34 | ||
35 | void UpdateIMMenu(FcitxUIMenu *menu) | |
36 | { | |
37 | FcitxUnikey* unikey = (FcitxUnikey*) menu->priv; | |
38 | menu->mark = unikey->config.im; | |
39 | } | |
40 | ||
41 | boolean IMMenuAction(FcitxUIMenu *menu, int index) | |
42 | { | |
43 | FcitxUnikey* unikey = (FcitxUnikey*) menu->priv; | |
44 | unikey->config.im = (UkInputMethod) index; | |
45 | UpdateUnikeyConfig(unikey); | |
46 | return true; | |
47 | } | |
48 | ||
49 | void UpdateOCMenu(FcitxUIMenu *menu) | |
50 | { | |
51 | FcitxUnikey* unikey = (FcitxUnikey*) menu->priv; | |
52 | menu->mark = unikey->config.oc; | |
53 | } | |
54 | ||
55 | boolean OCMenuAction(FcitxUIMenu *menu, int index) | |
56 | { | |
57 | FcitxUnikey* unikey = (FcitxUnikey*) menu->priv; | |
58 | unikey->config.oc =(UkConv) index; | |
59 | UpdateUnikeyConfig(unikey); | |
60 | return true; | |
61 | } | |
62 | ||
63 | static const char* GetIMIconName(void* arg) | |
64 | { | |
65 | return ""; | |
66 | } | |
67 | ||
68 | static const char* GetOCIconName(void* arg) | |
69 | { | |
70 | return ""; | |
71 | } | |
72 | ||
73 | void ToggleSpellCheck(void *arg) | |
74 | { | |
75 | FcitxUnikey* unikey = (FcitxUnikey*) arg; | |
76 | unikey->config.spellCheck = !unikey->config.spellCheck; | |
77 | UpdateUnikeyConfig(unikey); | |
78 | } | |
79 | ||
80 | boolean GetSpellCheck(void *arg) | |
81 | { | |
82 | FcitxUnikey* unikey = (FcitxUnikey*) arg; | |
83 | return unikey->config.spellCheck; | |
84 | } | |
85 | ||
86 | void ToggleMacro(void *arg) | |
87 | { | |
88 | FcitxUnikey* unikey = (FcitxUnikey*) arg; | |
89 | unikey->config.macro = !unikey->config.macro; | |
90 | UpdateUnikeyConfig(unikey); | |
91 | } | |
92 | ||
93 | boolean GetMacro(void *arg) | |
94 | { | |
95 | FcitxUnikey* unikey = (FcitxUnikey*) arg; | |
96 | return unikey->config.spellCheck; | |
97 | } | |
98 | ||
99 | void InitializeBar(FcitxUnikey* unikey) { | |
100 | FcitxInstance* instance = unikey->owner; | |
101 | FcitxUIRegisterComplexStatus(instance, unikey, | |
102 | "unikey-input-method", | |
103 | "", | |
104 | _("Choose input method"), | |
105 | NULL, | |
106 | GetIMIconName | |
107 | ); | |
108 | ||
109 | FcitxUIRegisterComplexStatus(instance, unikey, | |
110 | "unikey-output-charset", | |
111 | "", | |
112 | _("Choose output charset"), | |
113 | NULL, | |
114 | GetOCIconName | |
115 | ); | |
116 | FcitxUIRegisterStatus(instance, unikey, | |
117 | "unikey-spell-check", | |
118 | _("Spell Check"), | |
119 | _("Enable Spell Check"), | |
120 | ToggleSpellCheck, | |
121 | GetSpellCheck | |
122 | ); | |
123 | ||
124 | FcitxUIRegisterStatus(instance, unikey, | |
125 | "unikey-macro", | |
126 | _("Macro"), | |
127 | _("Enable Macro"), | |
128 | ToggleMacro, | |
129 | GetMacro | |
130 | ); | |
131 | FcitxUISetStatusVisable(instance, "unikey-input-method", false); | |
132 | FcitxUISetStatusVisable(instance, "unikey-output-charset", false); | |
133 | FcitxUISetStatusVisable(instance, "unikey-spell-check", false); | |
134 | FcitxUISetStatusVisable(instance, "unikey-macro", false); | |
135 | } | |
136 | ||
137 | void InitializeMenu(FcitxUnikey* unikey) { | |
138 | FcitxInstance* instance = unikey->owner; | |
139 | FcitxMenuInit(&unikey->imMenu); | |
140 | FcitxUIMenu* imMenu = &unikey->imMenu; | |
141 | imMenu->name = strdup(_("Unikey Input Method")); | |
142 | imMenu->candStatusBind = strdup("unikey-input-method"); | |
143 | imMenu->UpdateMenu = UpdateIMMenu; | |
144 | imMenu->MenuAction = IMMenuAction; | |
145 | imMenu->priv = unikey; | |
146 | imMenu->isSubMenu = false; | |
147 | int i; | |
148 | for (i = 0; i < NUM_INPUTMETHOD; i ++) | |
149 | FcitxMenuAddMenuItem(imMenu, _(Unikey_IMNames[i]), MENUTYPE_SIMPLE, NULL); | |
150 | ||
151 | FcitxUIRegisterMenu(instance, imMenu); | |
152 | ||
153 | FcitxMenuInit(&unikey->ocMenu); | |
154 | FcitxUIMenu* ocMenu = &unikey->ocMenu; | |
155 | ocMenu->name = strdup(_("Output Charset")); | |
156 | ocMenu->candStatusBind = strdup("unikey-output-charset"); | |
157 | ocMenu->UpdateMenu = UpdateOCMenu; | |
158 | ocMenu->MenuAction = OCMenuAction; | |
159 | ocMenu->priv = unikey; | |
160 | ocMenu->isSubMenu = false; | |
161 | for (i = 0; i < NUM_INPUTMETHOD; i ++) | |
162 | FcitxMenuAddMenuItem(ocMenu, _(Unikey_OCNames[i]), MENUTYPE_SIMPLE, NULL); | |
163 | FcitxUIRegisterMenu(instance, ocMenu); | |
164 | } | |
165 | ||
166 | void UpdateUnikeyUI(FcitxUnikey* unikey) | |
167 | { | |
168 | FcitxUISetStatusString(unikey->owner, | |
169 | "unikey-input-method", | |
170 | _(Unikey_IMNames[unikey->config.im]), | |
171 | _("Choose input method")); | |
172 | ||
173 | ||
174 | FcitxUISetStatusString(unikey->owner, | |
175 | "unikey-output-charset", | |
176 | _(Unikey_OCNames[unikey->config.oc]), | |
177 | _("Choose output charset")); | |
178 | ||
179 | FcitxUISetStatusString(unikey->owner, | |
180 | "unikey-spell-check", | |
181 | unikey->config.spellCheck? _("Spell Check"): _("N"), | |
182 | _("Enable Spell Check")); | |
183 | ||
184 | FcitxUISetStatusString(unikey->owner, | |
185 | "unikey-macro", | |
186 | unikey->config.macro? _("Macro"): _("N"), | |
187 | _("Enable Macro")); | |
188 | } |
0 | /*************************************************************************** | |
1 | * Copyright (C) 2012~2012 by CSSlayer * | |
2 | * wengxt@gmail.com * | |
3 | * * | |
4 | * This program is free software: you can redistribute it and/or modify * | |
5 | * it under the terms of the GNU General Public License as published by * | |
6 | * the Free Software Foundation, either version 3 of the License, or * | |
7 | * (at your option) any later version. * | |
8 | * * | |
9 | * This program is distributed in the hope that it will be useful, * | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
12 | * GNU General Public License for more details. * | |
13 | * * | |
14 | * You should have received a copy of the GNU General Public License * | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | |
16 | * * | |
17 | ***************************************************************************/ | |
18 | ||
19 | #ifndef UNIKEY_UI_H | |
20 | #define UNIKEY_UI_H | |
21 | #include "unikey-im.h" | |
22 | ||
23 | void InitializeBar(FcitxUnikey* unikey); | |
24 | void InitializeMenu(FcitxUnikey* unikey); | |
25 | void UpdateUnikeyUI(FcitxUnikey* unikey); | |
26 | ||
27 | #endif //UNIKEY_UI_H⏎ |
0 | GNU LIBRARY GENERAL PUBLIC LICENSE | |
1 | Version 2, June 1991 | |
2 | ||
3 | Copyright (C) 1991 Free Software Foundation, Inc. | |
4 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | Everyone is permitted to copy and distribute verbatim copies | |
6 | of this license document, but changing it is not allowed. | |
7 | ||
8 | [This is the first released version of the library GPL. It is | |
9 | numbered 2 because it goes with version 2 of the ordinary GPL.] | |
10 | ||
11 | Preamble | |
12 | ||
13 | The licenses for most software are designed to take away your | |
14 | freedom to share and change it. By contrast, the GNU General Public | |
15 | Licenses are intended to guarantee your freedom to share and change | |
16 | free software--to make sure the software is free for all its users. | |
17 | ||
18 | This license, the Library General Public License, applies to some | |
19 | specially designated Free Software Foundation software, and to any | |
20 | other libraries whose authors decide to use it. You can use it for | |
21 | your libraries, too. | |
22 | ||
23 | When we speak of free software, we are referring to freedom, not | |
24 | price. Our General Public Licenses are designed to make sure that you | |
25 | have the freedom to distribute copies of free software (and charge for | |
26 | this service if you wish), that you receive source code or can get it | |
27 | if you want it, that you can change the software or use pieces of it | |
28 | in new free programs; and that you know you can do these things. | |
29 | ||
30 | To protect your rights, we need to make restrictions that forbid | |
31 | anyone to deny you these rights or to ask you to surrender the rights. | |
32 | These restrictions translate to certain responsibilities for you if | |
33 | you distribute copies of the library, or if you modify it. | |
34 | ||
35 | For example, if you distribute copies of the library, whether gratis | |
36 | or for a fee, you must give the recipients all the rights that we gave | |
37 | you. You must make sure that they, too, receive or can get the source | |
38 | code. If you link a program with the library, you must provide | |
39 | complete object files to the recipients so that they can relink them | |
40 | with the library, after making changes to the library and recompiling | |
41 | it. And you must show them these terms so they know their rights. | |
42 | ||
43 | Our method of protecting your rights has two steps: (1) copyright | |
44 | the library, and (2) offer you this license which gives you legal | |
45 | permission to copy, distribute and/or modify the library. | |
46 | ||
47 | Also, for each distributor's protection, we want to make certain | |
48 | that everyone understands that there is no warranty for this free | |
49 | library. If the library is modified by someone else and passed on, we | |
50 | want its recipients to know that what they have is not the original | |
51 | version, so that any problems introduced by others will not reflect on | |
52 | the original authors' reputations. | |
53 | ||
54 | Finally, any free program is threatened constantly by software | |
55 | patents. We wish to avoid the danger that companies distributing free | |
56 | software will individually obtain patent licenses, thus in effect | |
57 | transforming the program into proprietary software. To prevent this, | |
58 | we have made it clear that any patent must be licensed for everyone's | |
59 | free use or not licensed at all. | |
60 | ||
61 | Most GNU software, including some libraries, is covered by the ordinary | |
62 | GNU General Public License, which was designed for utility programs. This | |
63 | license, the GNU Library General Public License, applies to certain | |
64 | designated libraries. This license is quite different from the ordinary | |
65 | one; be sure to read it in full, and don't assume that anything in it is | |
66 | the same as in the ordinary license. | |
67 | ||
68 | The reason we have a separate public license for some libraries is that | |
69 | they blur the distinction we usually make between modifying or adding to a | |
70 | program and simply using it. Linking a program with a library, without | |
71 | changing the library, is in some sense simply using the library, and is | |
72 | analogous to running a utility program or application program. However, in | |
73 | a textual and legal sense, the linked executable is a combined work, a | |
74 | derivative of the original library, and the ordinary General Public License | |
75 | treats it as such. | |
76 | ||
77 | Because of this blurred distinction, using the ordinary General | |
78 | Public License for libraries did not effectively promote software | |
79 | sharing, because most developers did not use the libraries. We | |
80 | concluded that weaker conditions might promote sharing better. | |
81 | ||
82 | However, unrestricted linking of non-free programs would deprive the | |
83 | users of those programs of all benefit from the free status of the | |
84 | libraries themselves. This Library General Public License is intended to | |
85 | permit developers of non-free programs to use free libraries, while | |
86 | preserving your freedom as a user of such programs to change the free | |
87 | libraries that are incorporated in them. (We have not seen how to achieve | |
88 | this as regards changes in header files, but we have achieved it as regards | |
89 | changes in the actual functions of the Library.) The hope is that this | |
90 | will lead to faster development of free libraries. | |
91 | ||
92 | The precise terms and conditions for copying, distribution and | |
93 | modification follow. Pay close attention to the difference between a | |
94 | "work based on the library" and a "work that uses the library". The | |
95 | former contains code derived from the library, while the latter only | |
96 | works together with the library. | |
97 | ||
98 | Note that it is possible for a library to be covered by the ordinary | |
99 | General Public License rather than by this special one. | |
100 | ||
101 | GNU LIBRARY GENERAL PUBLIC LICENSE | |
102 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
103 | ||
104 | 0. This License Agreement applies to any software library which | |
105 | contains a notice placed by the copyright holder or other authorized | |
106 | party saying it may be distributed under the terms of this Library | |
107 | General Public License (also called "this License"). Each licensee is | |
108 | addressed as "you". | |
109 | ||
110 | A "library" means a collection of software functions and/or data | |
111 | prepared so as to be conveniently linked with application programs | |
112 | (which use some of those functions and data) to form executables. | |
113 | ||
114 | The "Library", below, refers to any such software library or work | |
115 | which has been distributed under these terms. A "work based on the | |
116 | Library" means either the Library or any derivative work under | |
117 | copyright law: that is to say, a work containing the Library or a | |
118 | portion of it, either verbatim or with modifications and/or translated | |
119 | straightforwardly into another language. (Hereinafter, translation is | |
120 | included without limitation in the term "modification".) | |
121 | ||
122 | "Source code" for a work means the preferred form of the work for | |
123 | making modifications to it. For a library, complete source code means | |
124 | all the source code for all modules it contains, plus any associated | |
125 | interface definition files, plus the scripts used to control compilation | |
126 | and installation of the library. | |
127 | ||
128 | Activities other than copying, distribution and modification are not | |
129 | covered by this License; they are outside its scope. The act of | |
130 | running a program using the Library is not restricted, and output from | |
131 | such a program is covered only if its contents constitute a work based | |
132 | on the Library (independent of the use of the Library in a tool for | |
133 | writing it). Whether that is true depends on what the Library does | |
134 | and what the program that uses the Library does. | |
135 | ||
136 | 1. You may copy and distribute verbatim copies of the Library's | |
137 | complete source code as you receive it, in any medium, provided that | |
138 | you conspicuously and appropriately publish on each copy an | |
139 | appropriate copyright notice and disclaimer of warranty; keep intact | |
140 | all the notices that refer to this License and to the absence of any | |
141 | warranty; and distribute a copy of this License along with the | |
142 | Library. | |
143 | ||
144 | You may charge a fee for the physical act of transferring a copy, | |
145 | and you may at your option offer warranty protection in exchange for a | |
146 | fee. | |
147 | ||
148 | 2. You may modify your copy or copies of the Library or any portion | |
149 | of it, thus forming a work based on the Library, and copy and | |
150 | distribute such modifications or work under the terms of Section 1 | |
151 | above, provided that you also meet all of these conditions: | |
152 | ||
153 | a) The modified work must itself be a software library. | |
154 | ||
155 | b) You must cause the files modified to carry prominent notices | |
156 | stating that you changed the files and the date of any change. | |
157 | ||
158 | c) You must cause the whole of the work to be licensed at no | |
159 | charge to all third parties under the terms of this License. | |
160 | ||
161 | d) If a facility in the modified Library refers to a function or a | |
162 | table of data to be supplied by an application program that uses | |
163 | the facility, other than as an argument passed when the facility | |
164 | is invoked, then you must make a good faith effort to ensure that, | |
165 | in the event an application does not supply such function or | |
166 | table, the facility still operates, and performs whatever part of | |
167 | its purpose remains meaningful. | |
168 | ||
169 | (For example, a function in a library to compute square roots has | |
170 | a purpose that is entirely well-defined independent of the | |
171 | application. Therefore, Subsection 2d requires that any | |
172 | application-supplied function or table used by this function must | |
173 | be optional: if the application does not supply it, the square | |
174 | root function must still compute square roots.) | |
175 | ||
176 | These requirements apply to the modified work as a whole. If | |
177 | identifiable sections of that work are not derived from the Library, | |
178 | and can be reasonably considered independent and separate works in | |
179 | themselves, then this License, and its terms, do not apply to those | |
180 | sections when you distribute them as separate works. But when you | |
181 | distribute the same sections as part of a whole which is a work based | |
182 | on the Library, the distribution of the whole must be on the terms of | |
183 | this License, whose permissions for other licensees extend to the | |
184 | entire whole, and thus to each and every part regardless of who wrote | |
185 | it. | |
186 | ||
187 | Thus, it is not the intent of this section to claim rights or contest | |
188 | your rights to work written entirely by you; rather, the intent is to | |
189 | exercise the right to control the distribution of derivative or | |
190 | collective works based on the Library. | |
191 | ||
192 | In addition, mere aggregation of another work not based on the Library | |
193 | with the Library (or with a work based on the Library) on a volume of | |
194 | a storage or distribution medium does not bring the other work under | |
195 | the scope of this License. | |
196 | ||
197 | 3. You may opt to apply the terms of the ordinary GNU General Public | |
198 | License instead of this License to a given copy of the Library. To do | |
199 | this, you must alter all the notices that refer to this License, so | |
200 | that they refer to the ordinary GNU General Public License, version 2, | |
201 | instead of to this License. (If a newer version than version 2 of the | |
202 | ordinary GNU General Public License has appeared, then you can specify | |
203 | that version instead if you wish.) Do not make any other change in | |
204 | these notices. | |
205 | ||
206 | Once this change is made in a given copy, it is irreversible for | |
207 | that copy, so the ordinary GNU General Public License applies to all | |
208 | subsequent copies and derivative works made from that copy. | |
209 | ||
210 | This option is useful when you wish to copy part of the code of | |
211 | the Library into a program that is not a library. | |
212 | ||
213 | 4. You may copy and distribute the Library (or a portion or | |
214 | derivative of it, under Section 2) in object code or executable form | |
215 | under the terms of Sections 1 and 2 above provided that you accompany | |
216 | it with the complete corresponding machine-readable source code, which | |
217 | must be distributed under the terms of Sections 1 and 2 above on a | |
218 | medium customarily used for software interchange. | |
219 | ||
220 | If distribution of object code is made by offering access to copy | |
221 | from a designated place, then offering equivalent access to copy the | |
222 | source code from the same place satisfies the requirement to | |
223 | distribute the source code, even though third parties are not | |
224 | compelled to copy the source along with the object code. | |
225 | ||
226 | 5. A program that contains no derivative of any portion of the | |
227 | Library, but is designed to work with the Library by being compiled or | |
228 | linked with it, is called a "work that uses the Library". Such a | |
229 | work, in isolation, is not a derivative work of the Library, and | |
230 | therefore falls outside the scope of this License. | |
231 | ||
232 | However, linking a "work that uses the Library" with the Library | |
233 | creates an executable that is a derivative of the Library (because it | |
234 | contains portions of the Library), rather than a "work that uses the | |
235 | library". The executable is therefore covered by this License. | |
236 | Section 6 states terms for distribution of such executables. | |
237 | ||
238 | When a "work that uses the Library" uses material from a header file | |
239 | that is part of the Library, the object code for the work may be a | |
240 | derivative work of the Library even though the source code is not. | |
241 | Whether this is true is especially significant if the work can be | |
242 | linked without the Library, or if the work is itself a library. The | |
243 | threshold for this to be true is not precisely defined by law. | |
244 | ||
245 | If such an object file uses only numerical parameters, data | |
246 | structure layouts and accessors, and small macros and small inline | |
247 | functions (ten lines or less in length), then the use of the object | |
248 | file is unrestricted, regardless of whether it is legally a derivative | |
249 | work. (Executables containing this object code plus portions of the | |
250 | Library will still fall under Section 6.) | |
251 | ||
252 | Otherwise, if the work is a derivative of the Library, you may | |
253 | distribute the object code for the work under the terms of Section 6. | |
254 | Any executables containing that work also fall under Section 6, | |
255 | whether or not they are linked directly with the Library itself. | |
256 | ||
257 | 6. As an exception to the Sections above, you may also compile or | |
258 | link a "work that uses the Library" with the Library to produce a | |
259 | work containing portions of the Library, and distribute that work | |
260 | under terms of your choice, provided that the terms permit | |
261 | modification of the work for the customer's own use and reverse | |
262 | engineering for debugging such modifications. | |
263 | ||
264 | You must give prominent notice with each copy of the work that the | |
265 | Library is used in it and that the Library and its use are covered by | |
266 | this License. You must supply a copy of this License. If the work | |
267 | during execution displays copyright notices, you must include the | |
268 | copyright notice for the Library among them, as well as a reference | |
269 | directing the user to the copy of this License. Also, you must do one | |
270 | of these things: | |
271 | ||
272 | a) Accompany the work with the complete corresponding | |
273 | machine-readable source code for the Library including whatever | |
274 | changes were used in the work (which must be distributed under | |
275 | Sections 1 and 2 above); and, if the work is an executable linked | |
276 | with the Library, with the complete machine-readable "work that | |
277 | uses the Library", as object code and/or source code, so that the | |
278 | user can modify the Library and then relink to produce a modified | |
279 | executable containing the modified Library. (It is understood | |
280 | that the user who changes the contents of definitions files in the | |
281 | Library will not necessarily be able to recompile the application | |
282 | to use the modified definitions.) | |
283 | ||
284 | b) Accompany the work with a written offer, valid for at | |
285 | least three years, to give the same user the materials | |
286 | specified in Subsection 6a, above, for a charge no more | |
287 | than the cost of performing this distribution. | |
288 | ||
289 | c) If distribution of the work is made by offering access to copy | |
290 | from a designated place, offer equivalent access to copy the above | |
291 | specified materials from the same place. | |
292 | ||
293 | d) Verify that the user has already received a copy of these | |
294 | materials or that you have already sent this user a copy. | |
295 | ||
296 | For an executable, the required form of the "work that uses the | |
297 | Library" must include any data and utility programs needed for | |
298 | reproducing the executable from it. However, as a special exception, | |
299 | the source code distributed need not include anything that is normally | |
300 | distributed (in either source or binary form) with the major | |
301 | components (compiler, kernel, and so on) of the operating system on | |
302 | which the executable runs, unless that component itself accompanies | |
303 | the executable. | |
304 | ||
305 | It may happen that this requirement contradicts the license | |
306 | restrictions of other proprietary libraries that do not normally | |
307 | accompany the operating system. Such a contradiction means you cannot | |
308 | use both them and the Library together in an executable that you | |
309 | distribute. | |
310 | ||
311 | 7. You may place library facilities that are a work based on the | |
312 | Library side-by-side in a single library together with other library | |
313 | facilities not covered by this License, and distribute such a combined | |
314 | library, provided that the separate distribution of the work based on | |
315 | the Library and of the other library facilities is otherwise | |
316 | permitted, and provided that you do these two things: | |
317 | ||
318 | a) Accompany the combined library with a copy of the same work | |
319 | based on the Library, uncombined with any other library | |
320 | facilities. This must be distributed under the terms of the | |
321 | Sections above. | |
322 | ||
323 | b) Give prominent notice with the combined library of the fact | |
324 | that part of it is a work based on the Library, and explaining | |
325 | where to find the accompanying uncombined form of the same work. | |
326 | ||
327 | 8. You may not copy, modify, sublicense, link with, or distribute | |
328 | the Library except as expressly provided under this License. Any | |
329 | attempt otherwise to copy, modify, sublicense, link with, or | |
330 | distribute the Library is void, and will automatically terminate your | |
331 | rights under this License. However, parties who have received copies, | |
332 | or rights, from you under this License will not have their licenses | |
333 | terminated so long as such parties remain in full compliance. | |
334 | ||
335 | 9. You are not required to accept this License, since you have not | |
336 | signed it. However, nothing else grants you permission to modify or | |
337 | distribute the Library or its derivative works. These actions are | |
338 | prohibited by law if you do not accept this License. Therefore, by | |
339 | modifying or distributing the Library (or any work based on the | |
340 | Library), you indicate your acceptance of this License to do so, and | |
341 | all its terms and conditions for copying, distributing or modifying | |
342 | the Library or works based on it. | |
343 | ||
344 | 10. Each time you redistribute the Library (or any work based on the | |
345 | Library), the recipient automatically receives a license from the | |
346 | original licensor to copy, distribute, link with or modify the Library | |
347 | subject to these terms and conditions. You may not impose any further | |
348 | restrictions on the recipients' exercise of the rights granted herein. | |
349 | You are not responsible for enforcing compliance by third parties to | |
350 | this License. | |
351 | ||
352 | 11. If, as a consequence of a court judgment or allegation of patent | |
353 | infringement or for any other reason (not limited to patent issues), | |
354 | conditions are imposed on you (whether by court order, agreement or | |
355 | otherwise) that contradict the conditions of this License, they do not | |
356 | excuse you from the conditions of this License. If you cannot | |
357 | distribute so as to satisfy simultaneously your obligations under this | |
358 | License and any other pertinent obligations, then as a consequence you | |
359 | may not distribute the Library at all. For example, if a patent | |
360 | license would not permit royalty-free redistribution of the Library by | |
361 | all those who receive copies directly or indirectly through you, then | |
362 | the only way you could satisfy both it and this License would be to | |
363 | refrain entirely from distribution of the Library. | |
364 | ||
365 | If any portion of this section is held invalid or unenforceable under any | |
366 | particular circumstance, the balance of the section is intended to apply, | |
367 | and the section as a whole is intended to apply in other circumstances. | |
368 | ||
369 | It is not the purpose of this section to induce you to infringe any | |
370 | patents or other property right claims or to contest validity of any | |
371 | such claims; this section has the sole purpose of protecting the | |
372 | integrity of the free software distribution system which is | |
373 | implemented by public license practices. Many people have made | |
374 | generous contributions to the wide range of software distributed | |
375 | through that system in reliance on consistent application of that | |
376 | system; it is up to the author/donor to decide if he or she is willing | |
377 | to distribute software through any other system and a licensee cannot | |
378 | impose that choice. | |
379 | ||
380 | This section is intended to make thoroughly clear what is believed to | |
381 | be a consequence of the rest of this License. | |
382 | ||
383 | 12. If the distribution and/or use of the Library is restricted in | |
384 | certain countries either by patents or by copyrighted interfaces, the | |
385 | original copyright holder who places the Library under this License may add | |
386 | an explicit geographical distribution limitation excluding those countries, | |
387 | so that distribution is permitted only in or among countries not thus | |
388 | excluded. In such case, this License incorporates the limitation as if | |
389 | written in the body of this License. | |
390 | ||
391 | 13. The Free Software Foundation may publish revised and/or new | |
392 | versions of the Library General Public License from time to time. | |
393 | Such new versions will be similar in spirit to the present version, | |
394 | but may differ in detail to address new problems or concerns. | |
395 | ||
396 | Each version is given a distinguishing version number. If the Library | |
397 | specifies a version number of this License which applies to it and | |
398 | "any later version", you have the option of following the terms and | |
399 | conditions either of that version or of any later version published by | |
400 | the Free Software Foundation. If the Library does not specify a | |
401 | license version number, you may choose any version ever published by | |
402 | the Free Software Foundation. | |
403 | ||
404 | 14. If you wish to incorporate parts of the Library into other free | |
405 | programs whose distribution conditions are incompatible with these, | |
406 | write to the author to ask for permission. For software which is | |
407 | copyrighted by the Free Software Foundation, write to the Free | |
408 | Software Foundation; we sometimes make exceptions for this. Our | |
409 | decision will be guided by the two goals of preserving the free status | |
410 | of all derivatives of our free software and of promoting the sharing | |
411 | and reuse of software generally. | |
412 | ||
413 | NO WARRANTY | |
414 | ||
415 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO | |
416 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. | |
417 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR | |
418 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY | |
419 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE | |
420 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
421 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE | |
422 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME | |
423 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |
424 | ||
425 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN | |
426 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY | |
427 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU | |
428 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR | |
429 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE | |
430 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING | |
431 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A | |
432 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF | |
433 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | |
434 | DAMAGES. | |
435 | ||
436 | END OF TERMS AND CONDITIONS | |
437 | ||
438 | How to Apply These Terms to Your New Libraries | |
439 | ||
440 | If you develop a new library, and you want it to be of the greatest | |
441 | possible use to the public, we recommend making it free software that | |
442 | everyone can redistribute and change. You can do so by permitting | |
443 | redistribution under these terms (or, alternatively, under the terms of the | |
444 | ordinary General Public License). | |
445 | ||
446 | To apply these terms, attach the following notices to the library. It is | |
447 | safest to attach them to the start of each source file to most effectively | |
448 | convey the exclusion of warranty; and each file should have at least the | |
449 | "copyright" line and a pointer to where the full notice is found. | |
450 | ||
451 | <one line to give the library's name and a brief idea of what it does.> | |
452 | Copyright (C) <year> <name of author> | |
453 | ||
454 | This library is free software; you can redistribute it and/or | |
455 | modify it under the terms of the GNU Library General Public | |
456 | License as published by the Free Software Foundation; either | |
457 | version 2 of the License, or (at your option) any later version. | |
458 | ||
459 | This library is distributed in the hope that it will be useful, | |
460 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
461 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
462 | Library General Public License for more details. | |
463 | ||
464 | You should have received a copy of the GNU Library General Public | |
465 | License along with this library; if not, write to the | |
466 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
467 | Boston, MA 02111-1307 USA. | |
468 | ||
469 | Also add information on how to contact you by electronic and paper mail. | |
470 | ||
471 | You should also get your employer (if you work as a programmer) or your | |
472 | school, if any, to sign a "copyright disclaimer" for the library, if | |
473 | necessary. Here is a sample; alter the names: | |
474 | ||
475 | Yoyodyne, Inc., hereby disclaims all copyright interest in the | |
476 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. | |
477 | ||
478 | <signature of Ty Coon>, 1 April 1990 | |
479 | Ty Coon, President of Vice | |
480 | ||
481 | That's all there is to it! |
0 | This folder contains ukengine (with changes | |
1 | for better use in my project) taking from project | |
2 | x-unikey (http://www.unikey.org). | |
3 | ||
4 | Read COPYING for License of ukengine. | |
5 |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | #include <string.h> | |
2 | #include "byteio.h" | |
3 | ||
4 | //------------------------------------------------ | |
5 | StringBIStream::StringBIStream(UKBYTE *data, int len, int elementSize) | |
6 | { | |
7 | m_data = m_current = data; | |
8 | m_len = m_left = len; | |
9 | if (len == -1) { | |
10 | if (elementSize == 2) | |
11 | m_eos = (*(UKWORD *)data == 0); | |
12 | else if (elementSize == 4) | |
13 | m_eos = (*(UKDWORD *)data == 4); | |
14 | else | |
15 | m_eos = (*data == 0); | |
16 | } | |
17 | else | |
18 | m_eos = (len <= 0); | |
19 | m_didBookmark = 0; | |
20 | } | |
21 | ||
22 | //------------------------------------------------ | |
23 | int StringBIStream::eos() | |
24 | { | |
25 | return m_eos; | |
26 | } | |
27 | ||
28 | //------------------------------------------------ | |
29 | int StringBIStream::getNext(UKBYTE & b) | |
30 | { | |
31 | if (m_eos) | |
32 | return 0; | |
33 | b = *m_current++; | |
34 | if (m_len == -1) { | |
35 | m_eos = (b == 0); | |
36 | } | |
37 | else { | |
38 | m_left--; | |
39 | m_eos = (m_left <= 0); | |
40 | } | |
41 | return 1; | |
42 | } | |
43 | ||
44 | //------------------------------------------------ | |
45 | int StringBIStream::unget(UKBYTE b) | |
46 | { | |
47 | if (m_current != m_data) { | |
48 | *--m_current = b; | |
49 | m_eos = 0; | |
50 | if (m_len != -1) | |
51 | m_left++; | |
52 | } | |
53 | return 1; | |
54 | } | |
55 | ||
56 | //------------------------------------------------ | |
57 | int StringBIStream::getNextW(UKWORD & w) | |
58 | { | |
59 | if (m_eos) return 0; | |
60 | w = *((UKWORD *)m_current); | |
61 | m_current += 2; | |
62 | if (m_len == -1) | |
63 | m_eos = (w == 0); | |
64 | else { | |
65 | m_left -= 2; | |
66 | m_eos = (m_left <= 0); | |
67 | } | |
68 | return 1; | |
69 | } | |
70 | ||
71 | //------------------------------------------------ | |
72 | int StringBIStream::getNextDW(UKDWORD & dw) | |
73 | { | |
74 | if (m_eos) return 0; | |
75 | ||
76 | dw = *((UKDWORD *)m_current); | |
77 | m_current += 4; | |
78 | if (m_len == -1) | |
79 | m_eos = (dw == 0); | |
80 | else { | |
81 | m_left -= 4; | |
82 | m_eos = (m_left <= 0); | |
83 | } | |
84 | return 1; | |
85 | } | |
86 | ||
87 | //------------------------------------------------ | |
88 | int StringBIStream::peekNext(UKBYTE & b) | |
89 | { | |
90 | if (m_eos) | |
91 | return 0; | |
92 | b = *m_current; | |
93 | return 1; | |
94 | } | |
95 | ||
96 | //------------------------------------------------ | |
97 | int StringBIStream::peekNextW(UKWORD & w) | |
98 | { | |
99 | if (m_eos) | |
100 | return 0; | |
101 | w = *((UKWORD *)m_current); | |
102 | return 1; | |
103 | } | |
104 | ||
105 | /* | |
106 | //------------------------------------------------ | |
107 | int StringBIStream::peekNextDW(UKDWORD & dw) | |
108 | { | |
109 | if (m_eos) | |
110 | return 0; | |
111 | dw = *((UKDWORD *)m_current); | |
112 | return 1; | |
113 | } | |
114 | */ | |
115 | ||
116 | //------------------------------------------------ | |
117 | void StringBIStream::reopen() | |
118 | { | |
119 | m_current = m_data; | |
120 | m_left = m_len; | |
121 | if (m_len == -1) | |
122 | m_eos = (m_data == 0); | |
123 | else | |
124 | m_eos = (m_len <= 0); | |
125 | m_didBookmark = 0; | |
126 | } | |
127 | ||
128 | //------------------------------------------------ | |
129 | int StringBIStream::bookmark() | |
130 | { | |
131 | m_didBookmark = 1; | |
132 | m_bookmark.current = m_current; | |
133 | m_bookmark.data = m_data; | |
134 | m_bookmark.eos = m_eos; | |
135 | m_bookmark.left = m_left; | |
136 | m_bookmark.len = m_len; | |
137 | return 1; | |
138 | } | |
139 | ||
140 | //------------------------------------------------ | |
141 | int StringBIStream::gotoBookmark() | |
142 | { | |
143 | if (!m_didBookmark) | |
144 | return 0; | |
145 | m_current = m_bookmark.current; | |
146 | m_data = m_bookmark.data; | |
147 | m_eos = m_bookmark.eos; | |
148 | m_left = m_bookmark.left; | |
149 | m_len = m_bookmark.len; | |
150 | return 1; | |
151 | } | |
152 | ||
153 | //------------------------------------------------ | |
154 | int StringBIStream::close() | |
155 | { | |
156 | return 1; | |
157 | }; | |
158 | ||
159 | ////////////////////////////////////////////////// | |
160 | // Class StringBOStream | |
161 | ////////////////////////////////////////////////// | |
162 | ||
163 | //------------------------------------------------ | |
164 | StringBOStream::StringBOStream(UKBYTE *buf, int len) | |
165 | { | |
166 | m_current = m_buf = buf; | |
167 | m_len = len; | |
168 | m_out = 0; | |
169 | m_bad = 0; | |
170 | } | |
171 | ||
172 | //------------------------------------------------ | |
173 | int StringBOStream::putB(UKBYTE b) | |
174 | { | |
175 | m_out++; | |
176 | /* | |
177 | if (m_out >= 2147483647) { | |
178 | int err; | |
179 | err = 1; | |
180 | } | |
181 | */ | |
182 | if (m_bad) | |
183 | return 0; | |
184 | /* | |
185 | if (m_out < 0) { | |
186 | int i; | |
187 | i = 1; | |
188 | } | |
189 | */ | |
190 | if (m_out <= m_len) { | |
191 | *m_current++ = b; | |
192 | return 1; | |
193 | } | |
194 | m_bad = 1; | |
195 | return 0; | |
196 | } | |
197 | ||
198 | //------------------------------------------------ | |
199 | int StringBOStream::putW(UKWORD w) | |
200 | { | |
201 | m_out += 2; | |
202 | if (m_bad) | |
203 | return 0; | |
204 | if (m_out <= m_len) { | |
205 | *((UKWORD *)m_current) = w; | |
206 | m_current += 2; | |
207 | return 1; | |
208 | } | |
209 | m_bad = 1; | |
210 | return 0; | |
211 | } | |
212 | ||
213 | //------------------------------------------------ | |
214 | int StringBOStream::puts(const char *s, int size) | |
215 | { | |
216 | if (size == -1) { | |
217 | while (*s) { | |
218 | m_out++; | |
219 | if (m_out <= m_len) | |
220 | *m_current++ = *s; | |
221 | s++; | |
222 | } | |
223 | if (!m_bad && m_out > m_len) | |
224 | m_bad = 1; | |
225 | return (!m_bad); | |
226 | } | |
227 | ||
228 | int n; | |
229 | if (!m_bad && m_out <= m_len) { | |
230 | n = m_len - m_out; | |
231 | if (n>size) | |
232 | n = size; | |
233 | memcpy(m_current, s, n); | |
234 | m_current += n; | |
235 | } | |
236 | ||
237 | m_out += size; | |
238 | if (!m_bad && m_out > m_len) | |
239 | m_bad = 1; | |
240 | return (!m_bad); | |
241 | } | |
242 | ||
243 | //------------------------------------------------ | |
244 | void StringBOStream::reopen() | |
245 | { | |
246 | m_current = m_buf; | |
247 | m_out = 0; | |
248 | m_bad = 0; | |
249 | } | |
250 | ||
251 | ||
252 | //------------------------------------------------ | |
253 | int StringBOStream::isOK() | |
254 | { | |
255 | return !m_bad; | |
256 | } | |
257 | ||
258 | ||
259 | //////////////////////////////////////////////////// | |
260 | // Class FileBIStream // | |
261 | //////////////////////////////////////////////////// | |
262 | ||
263 | //---------------------------------------------------- | |
264 | FileBIStream::FileBIStream(int bufSize, char *buf) | |
265 | { | |
266 | m_file = NULL; | |
267 | m_buf = buf; | |
268 | m_bufSize = bufSize; | |
269 | m_own = 1; | |
270 | m_didBookmark = 0; | |
271 | ||
272 | m_readAhead = 0; | |
273 | m_lastIsAhead = 0; | |
274 | } | |
275 | ||
276 | //---------------------------------------------------- | |
277 | FileBIStream::~FileBIStream() | |
278 | { | |
279 | if (m_own) | |
280 | close(); | |
281 | } | |
282 | ||
283 | //---------------------------------------------------- | |
284 | int FileBIStream::open(const char *fileName) | |
285 | { | |
286 | m_file = fopen(fileName, "rb"); | |
287 | if (m_file == NULL) | |
288 | return 0; | |
289 | setvbuf(m_file, m_buf, _IOFBF, m_bufSize); | |
290 | m_own = 0; | |
291 | m_readAhead = 0; | |
292 | m_lastIsAhead = 0; | |
293 | return 1; | |
294 | } | |
295 | ||
296 | //---------------------------------------------------- | |
297 | int FileBIStream::close() | |
298 | { | |
299 | if (m_file != NULL) { | |
300 | fclose(m_file); | |
301 | m_file = NULL; | |
302 | } | |
303 | return 1; | |
304 | } | |
305 | ||
306 | //---------------------------------------------------- | |
307 | void FileBIStream::attach(FILE * f) | |
308 | { | |
309 | m_file = f; | |
310 | m_own = 0; | |
311 | m_readAhead = 0; | |
312 | m_lastIsAhead = 0; | |
313 | } | |
314 | ||
315 | //---------------------------------------------------- | |
316 | int FileBIStream::eos() | |
317 | { | |
318 | if (m_readAhead) | |
319 | return 0; | |
320 | return feof(m_file); | |
321 | } | |
322 | ||
323 | //---------------------------------------------------- | |
324 | int FileBIStream::getNext(UKBYTE &b) | |
325 | { | |
326 | if (m_readAhead) { | |
327 | m_readAhead = 0; | |
328 | b = m_readByte; | |
329 | m_lastIsAhead = 1; | |
330 | return 1; | |
331 | } | |
332 | ||
333 | m_lastIsAhead = 0; | |
334 | b = fgetc(m_file); | |
335 | return (!feof(m_file)); | |
336 | } | |
337 | ||
338 | //---------------------------------------------------- | |
339 | int FileBIStream::peekNext(UKBYTE &b) | |
340 | { | |
341 | if (m_readAhead) { | |
342 | b = m_readByte; | |
343 | return 1; | |
344 | } | |
345 | ||
346 | b = fgetc(m_file); | |
347 | if (feof(m_file)) | |
348 | return 0; | |
349 | ungetc(b, m_file); | |
350 | return 1; | |
351 | } | |
352 | ||
353 | //---------------------------------------------------- | |
354 | int FileBIStream::unget(UKBYTE b) | |
355 | { | |
356 | if (m_lastIsAhead) { | |
357 | m_lastIsAhead = 0; | |
358 | m_readAhead = 1; | |
359 | m_readByte = b; | |
360 | return 1; | |
361 | } | |
362 | ||
363 | ungetc(b, m_file); | |
364 | return 1; | |
365 | } | |
366 | ||
367 | //---------------------------------------------------- | |
368 | int FileBIStream::getNextW(UKWORD &w) | |
369 | { | |
370 | UKBYTE b1, b2; | |
371 | ||
372 | if (getNext(b1)) { | |
373 | if (getNext(b2)) { | |
374 | *((UKBYTE *)&w) = b1; | |
375 | *(((UKBYTE *)&w)+1) = b2; | |
376 | return 1; | |
377 | } | |
378 | } | |
379 | return 0; | |
380 | } | |
381 | ||
382 | //---------------------------------------------------- | |
383 | int FileBIStream::getNextDW(UKDWORD &dw) | |
384 | { | |
385 | UKWORD w1, w2; | |
386 | if (getNextW(w1)) { | |
387 | if (getNextW(w2)) { | |
388 | *((UKWORD *)&dw) = w1; | |
389 | *(((UKWORD *)&dw)+1) = w2; | |
390 | return 1; | |
391 | } | |
392 | } | |
393 | return 0; | |
394 | ||
395 | } | |
396 | //---------------------------------------------------- | |
397 | int FileBIStream::peekNextW(UKWORD &w) | |
398 | { | |
399 | UKBYTE hi, low; | |
400 | if (getNext(low)) { | |
401 | if (getNext(hi)) { | |
402 | unget(hi); | |
403 | w = hi; | |
404 | w = (w << 8) + low; | |
405 | m_readAhead = 1; | |
406 | m_readByte = low; | |
407 | m_lastIsAhead = 0; | |
408 | return 1; | |
409 | } | |
410 | ||
411 | m_readAhead = 1; | |
412 | m_readByte = low; | |
413 | m_lastIsAhead = 0; | |
414 | return 0; | |
415 | } | |
416 | return 0; | |
417 | } | |
418 | ||
419 | //---------------------------------------------------- | |
420 | int FileBIStream::bookmark() | |
421 | { | |
422 | m_didBookmark = 1; | |
423 | m_bookmark.pos = ftell(m_file); | |
424 | return 1; | |
425 | } | |
426 | ||
427 | ||
428 | //---------------------------------------------------- | |
429 | int FileBIStream::gotoBookmark() | |
430 | { | |
431 | if (!m_didBookmark) | |
432 | return 0; | |
433 | fseek(m_file, m_bookmark.pos, SEEK_SET); | |
434 | return 1; | |
435 | } | |
436 | ||
437 | //////////////////////////////////////////////////// | |
438 | // Class FileBOStream // | |
439 | //////////////////////////////////////////////////// | |
440 | //---------------------------------------------------- | |
441 | FileBOStream::FileBOStream(int bufSize, char *buf) | |
442 | { | |
443 | m_file = NULL; | |
444 | m_buf = buf; | |
445 | m_bufSize = bufSize; | |
446 | m_own = 1; | |
447 | m_bad = 1; | |
448 | } | |
449 | ||
450 | //---------------------------------------------------- | |
451 | FileBOStream::~FileBOStream() | |
452 | { | |
453 | if (m_own) | |
454 | close(); | |
455 | } | |
456 | ||
457 | //---------------------------------------------------- | |
458 | int FileBOStream::open(const char *fileName) | |
459 | { | |
460 | m_file = fopen(fileName, "wb"); | |
461 | if (m_file == NULL) | |
462 | return 0; | |
463 | m_bad = 0; | |
464 | setvbuf(m_file, m_buf, _IOFBF, m_bufSize); | |
465 | m_own = 1; | |
466 | return 1; | |
467 | } | |
468 | ||
469 | //---------------------------------------------------- | |
470 | void FileBOStream::attach(FILE * f) | |
471 | { | |
472 | m_file = f; | |
473 | m_own = 0; | |
474 | m_bad = 0; | |
475 | } | |
476 | ||
477 | //---------------------------------------------------- | |
478 | int FileBOStream::close() | |
479 | { | |
480 | if (m_file != NULL) { | |
481 | fclose(m_file); | |
482 | m_file = NULL; | |
483 | } | |
484 | return 1; | |
485 | } | |
486 | ||
487 | //---------------------------------------------------- | |
488 | int FileBOStream::putB(UKBYTE b) | |
489 | { | |
490 | if (m_bad) | |
491 | return 0; | |
492 | m_bad = (fputc(b, m_file) == EOF); | |
493 | return (!m_bad); | |
494 | } | |
495 | ||
496 | //---------------------------------------------------- | |
497 | int FileBOStream::putW(UKWORD w) | |
498 | { | |
499 | if (m_bad) | |
500 | return 0; | |
501 | // m_bad = (fputwc(w, m_file) == WEOF); | |
502 | m_bad = (fputc((UKBYTE)w, m_file) == EOF); | |
503 | if (m_bad) | |
504 | return 0; | |
505 | m_bad = (fputc((UKBYTE)(w >> 8), m_file) == EOF); | |
506 | return (!m_bad); | |
507 | } | |
508 | ||
509 | //---------------------------------------------------- | |
510 | int FileBOStream::puts(const char *s, int size) | |
511 | { | |
512 | if (m_bad) | |
513 | return 0; | |
514 | if (size == -1) { | |
515 | m_bad = (fputs(s, m_file) == EOF); | |
516 | return (!m_bad); | |
517 | } | |
518 | int out = fwrite(s, 1, size, m_file); | |
519 | m_bad = (out != size); | |
520 | return (!m_bad); | |
521 | } | |
522 | ||
523 | //---------------------------------------------------- | |
524 | int FileBOStream::isOK() | |
525 | { | |
526 | return !m_bad; | |
527 | } |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | #ifndef BYTE_IO_STREAM_H | |
2 | #define BYTE_IO_STREAM_H | |
3 | ||
4 | ||
5 | //#include "vnconv.h" | |
6 | #include <stdio.h> | |
7 | ||
8 | typedef unsigned char UKBYTE; | |
9 | typedef unsigned short UKWORD; | |
10 | typedef unsigned int UKDWORD; | |
11 | ||
12 | //---------------------------------------------------- | |
13 | class ByteStream { | |
14 | public: | |
15 | virtual ~ByteStream(){}; | |
16 | }; | |
17 | ||
18 | //---------------------------------------------------- | |
19 | class ByteInStream: public ByteStream | |
20 | { | |
21 | public: | |
22 | virtual int getNext(UKBYTE &b) = 0; | |
23 | virtual int peekNext(UKBYTE &b) = 0; | |
24 | virtual int unget(UKBYTE b) = 0; | |
25 | ||
26 | virtual int getNextW(UKWORD &w) = 0; | |
27 | virtual int peekNextW(UKWORD &w) = 0; | |
28 | ||
29 | virtual int getNextDW(UKDWORD &dw) = 0; | |
30 | ||
31 | virtual int bookmark() //no support for bookmark by default | |
32 | { | |
33 | return 0; | |
34 | } | |
35 | ||
36 | virtual int gotoBookmark() | |
37 | { | |
38 | return 0; | |
39 | } | |
40 | ||
41 | virtual int eos() = 0; //end of stream | |
42 | virtual int close() = 0; | |
43 | }; | |
44 | ||
45 | //---------------------------------------------------- | |
46 | class ByteOutStream: public ByteStream | |
47 | { | |
48 | public: | |
49 | virtual int putB(UKBYTE b) = 0; | |
50 | virtual int putW(UKWORD w) = 0; | |
51 | virtual int puts(const char *s, int size = -1) = 0; // write an 8-bit string | |
52 | virtual int isOK() = 0;// get current stream state | |
53 | }; | |
54 | ||
55 | //---------------------------------------------------- | |
56 | class StringBIStream : public ByteInStream | |
57 | { | |
58 | protected: | |
59 | int m_eos; | |
60 | UKBYTE *m_data, *m_current; | |
61 | int m_len, m_left; | |
62 | ||
63 | struct { | |
64 | int eos; | |
65 | UKBYTE *data, *current; | |
66 | int len, left; | |
67 | } m_bookmark; | |
68 | ||
69 | int m_didBookmark; | |
70 | ||
71 | public: | |
72 | StringBIStream(UKBYTE *data, int len, int elementSize = 1); | |
73 | virtual int getNext(UKBYTE &b); | |
74 | virtual int peekNext(UKBYTE &b); | |
75 | virtual int unget(UKBYTE b); | |
76 | ||
77 | virtual int getNextW(UKWORD &w); | |
78 | virtual int peekNextW(UKWORD &w); | |
79 | ||
80 | virtual int getNextDW(UKDWORD &dw); | |
81 | ||
82 | virtual int eos(); //end of stream | |
83 | virtual int close(); | |
84 | ||
85 | virtual int bookmark(); | |
86 | virtual int gotoBookmark(); | |
87 | ||
88 | void reopen(); | |
89 | int left() { | |
90 | return m_left; | |
91 | } | |
92 | }; | |
93 | ||
94 | //---------------------------------------------------- | |
95 | class FileBIStream : public ByteInStream | |
96 | { | |
97 | protected: | |
98 | FILE *m_file; | |
99 | int m_bufSize; | |
100 | char *m_buf; | |
101 | int m_own; | |
102 | int m_didBookmark; | |
103 | ||
104 | struct { | |
105 | long pos; | |
106 | } m_bookmark; | |
107 | ||
108 | //some systems don't have wide char IO functions | |
109 | //we have to use this variables to implement that | |
110 | UKBYTE m_readByte; | |
111 | int m_readAhead; | |
112 | int m_lastIsAhead; | |
113 | ||
114 | public: | |
115 | ||
116 | FileBIStream(int bufsize = 8192, char *buf = NULL); | |
117 | // FileBIStream(char *fileName, int bufsize = 8192, void *buf = NULL); | |
118 | ||
119 | int open(const char *fileName); | |
120 | void attach(FILE *f); | |
121 | virtual int close(); | |
122 | ||
123 | virtual int getNext(UKBYTE &b); | |
124 | virtual int peekNext(UKBYTE &b); | |
125 | virtual int unget(UKBYTE b); | |
126 | ||
127 | virtual int getNextW(UKWORD &w); | |
128 | virtual int peekNextW(UKWORD &w); | |
129 | ||
130 | virtual int getNextDW(UKDWORD &dw); | |
131 | ||
132 | virtual int eos(); //end of stream | |
133 | ||
134 | virtual int bookmark(); | |
135 | virtual int gotoBookmark(); | |
136 | ||
137 | virtual ~FileBIStream(); | |
138 | }; | |
139 | ||
140 | ||
141 | //---------------------------------------------------- | |
142 | class StringBOStream : public ByteOutStream | |
143 | { | |
144 | protected: | |
145 | UKBYTE *m_buf, *m_current; | |
146 | int m_out; | |
147 | int m_len; | |
148 | int m_bad; | |
149 | public: | |
150 | StringBOStream(UKBYTE *buf, int len); | |
151 | virtual int putB(UKBYTE b); | |
152 | virtual int putW(UKWORD w); | |
153 | virtual int puts(const char *s, int size = -1); | |
154 | virtual int isOK(); // get current stream state | |
155 | ||
156 | virtual int close() | |
157 | { | |
158 | return 1; | |
159 | }; | |
160 | ||
161 | void reopen(); | |
162 | int getOutBytes() { | |
163 | return m_out; | |
164 | } | |
165 | }; | |
166 | ||
167 | //---------------------------------------------------- | |
168 | class FileBOStream : public ByteOutStream | |
169 | { | |
170 | protected: | |
171 | FILE *m_file; | |
172 | int m_bufSize; | |
173 | char *m_buf; | |
174 | int m_own; | |
175 | int m_bad; | |
176 | ||
177 | public: | |
178 | FileBOStream(int bufsize = 8192, char *buf = NULL); | |
179 | // FileBOStream(char *fileName, int bufsize = 8192, void *buf = NULL); | |
180 | ||
181 | int open(const char *fileName); | |
182 | void attach(FILE *); | |
183 | virtual int close(); | |
184 | ||
185 | virtual int putB(UKBYTE b); | |
186 | virtual int putW(UKWORD w); | |
187 | virtual int puts(const char *s, int size = -1); | |
188 | virtual int isOK(); // get current stream state | |
189 | virtual ~FileBOStream(); | |
190 | }; | |
191 | ||
192 | ||
193 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | VnConv: Vietnamese Encoding Converter Library | |
3 | UniKey Project: http://unikey.sourceforge.net | |
4 | Copyleft (C) 1998-2002 Pham Kim Long | |
5 | Contact: longp@cslab.felk.cvut.cz | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License | |
9 | as published by the Free Software Foundation; either version 2 | |
10 | of the License, or (at your option) any later version. | |
11 | ||
12 | This program 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 | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | --------------------------------------------------------------------------------*/ | |
21 | ||
22 | #include <stddef.h> | |
23 | #include <search.h> | |
24 | #include <memory.h> | |
25 | #include <ctype.h> | |
26 | #include <stdlib.h> | |
27 | ||
28 | #include "charset.h" | |
29 | #include "data.h" | |
30 | ||
31 | int LoVowel['z'-'a'+1]; | |
32 | int HiVowel['Z'-'A'+1]; | |
33 | ||
34 | #define IS_VOWEL(x) ((x >= 'a' && x <= 'z' && LoVowel[x-'a']) || (x >= 'A' && x <= 'Z' && HiVowel[x-'A'])) | |
35 | ||
36 | SingleByteCharset *SgCharsets[CONV_TOTAL_SINGLE_CHARSETS]; | |
37 | DoubleByteCharset *DbCharsets[CONV_TOTAL_DOUBLE_CHARSETS]; | |
38 | ||
39 | DllExport CVnCharsetLib VnCharsetLibObj; | |
40 | ||
41 | ////////////////////////////////////////////////////// | |
42 | // Generic VnCharset class | |
43 | ////////////////////////////////////////////////////// | |
44 | int VnCharset::elementSize() | |
45 | { | |
46 | return 1; | |
47 | } | |
48 | ||
49 | //------------------------------------------- | |
50 | int VnInternalCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
51 | { | |
52 | if (!is.getNextDW(stdChar)) { | |
53 | bytesRead = 0; | |
54 | return 0; | |
55 | } | |
56 | bytesRead = sizeof(UKDWORD); | |
57 | return 1; | |
58 | } | |
59 | ||
60 | //------------------------------------------- | |
61 | int VnInternalCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
62 | { | |
63 | outLen = sizeof(StdVnChar); | |
64 | os.putW((UKWORD)stdChar); | |
65 | return os.putW((UKWORD)(stdChar>>(sizeof(UKWORD)*8))); | |
66 | } | |
67 | ||
68 | //------------------------------------------- | |
69 | int VnInternalCharset::elementSize() | |
70 | { | |
71 | return 4; | |
72 | } | |
73 | ||
74 | //------------------------------------------- | |
75 | SingleByteCharset::SingleByteCharset(unsigned char * vnChars) | |
76 | { | |
77 | int i; | |
78 | m_vnChars = vnChars; | |
79 | memset(m_stdMap, 0, 256*sizeof(UKWORD)); | |
80 | for (i=0; i<TOTAL_VNCHARS; i++) { | |
81 | if (vnChars[i] != 0 && (i==TOTAL_VNCHARS-1 || vnChars[i] != vnChars[i+1])) | |
82 | m_stdMap[vnChars[i]] = i + 1; | |
83 | } | |
84 | } | |
85 | ||
86 | //------------------------------------------- | |
87 | int SingleByteCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
88 | { | |
89 | unsigned char ch; | |
90 | if (!is.getNext(ch)) { | |
91 | bytesRead = 0; | |
92 | return 0; | |
93 | } | |
94 | ||
95 | stdChar = (m_stdMap[ch])? (VnStdCharOffset + m_stdMap[ch] - 1) : ch; | |
96 | bytesRead = 1; | |
97 | return 1; | |
98 | } | |
99 | ||
100 | ||
101 | //------------------------------------------- | |
102 | int SingleByteCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
103 | { | |
104 | int ret; | |
105 | unsigned char ch; | |
106 | if (stdChar >= VnStdCharOffset) { | |
107 | outLen = 1; | |
108 | ch = m_vnChars[stdChar - VnStdCharOffset]; | |
109 | if (ch == 0) | |
110 | ch = (stdChar == StdStartQuote)? PadStartQuote : | |
111 | ((stdChar == StdEndQuote)? PadEndQuote : | |
112 | ((stdChar == StdEllipsis)? PadEllipsis: PadChar) ); | |
113 | ret = os.putB(ch); | |
114 | } | |
115 | else { | |
116 | if (stdChar > 255 || m_stdMap[stdChar]) { | |
117 | //this character is missing in the charset | |
118 | // output padding character | |
119 | outLen = 1; | |
120 | ret = os.putB(PadChar); | |
121 | } | |
122 | else { | |
123 | outLen = 1; | |
124 | ret = os.putB((UKBYTE)stdChar); | |
125 | } | |
126 | } | |
127 | return ret; | |
128 | } | |
129 | ||
130 | //------------------------------------------- | |
131 | int wideCharCompare(const void *ele1, const void *ele2) | |
132 | { | |
133 | UKWORD ch1 = LOWORD(*((UKDWORD *)ele1)); | |
134 | UKWORD ch2 = LOWORD(*((UKDWORD *)ele2)); | |
135 | return (ch1 == ch2)? 0 : ((ch1 > ch2)? 1 : -1); | |
136 | } | |
137 | ||
138 | //------------------------------------------- | |
139 | UnicodeCharset::UnicodeCharset(UnicodeChar *vnChars) | |
140 | { | |
141 | UKDWORD i; | |
142 | m_toUnicode = vnChars; | |
143 | for (i=0; i<TOTAL_VNCHARS; i++) | |
144 | m_vnChars[i] = (i << 16) + vnChars[i]; // high word is used for index | |
145 | qsort(m_vnChars, TOTAL_VNCHARS, sizeof(UKDWORD), wideCharCompare); | |
146 | } | |
147 | ||
148 | //------------------------------------------- | |
149 | int UnicodeCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
150 | { | |
151 | UnicodeChar uniCh; | |
152 | if (!is.getNextW(uniCh)) { | |
153 | bytesRead = 0; | |
154 | return 0; | |
155 | } | |
156 | bytesRead = sizeof(UnicodeChar); | |
157 | UKDWORD key = uniCh; | |
158 | UKDWORD *pChar = (UKDWORD *)bsearch(&key, m_vnChars, TOTAL_VNCHARS, sizeof(UKDWORD), wideCharCompare); | |
159 | if (pChar) | |
160 | stdChar = VnStdCharOffset + HIWORD(*pChar); | |
161 | else | |
162 | stdChar = uniCh; | |
163 | return 1; | |
164 | } | |
165 | ||
166 | //------------------------------------------- | |
167 | int UnicodeCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
168 | { | |
169 | outLen = sizeof(UnicodeChar); | |
170 | return os.putW((stdChar >= VnStdCharOffset)? | |
171 | m_toUnicode[stdChar-VnStdCharOffset] : (UnicodeChar)stdChar); | |
172 | } | |
173 | ||
174 | //------------------------------------------- | |
175 | int UnicodeCharset::elementSize() | |
176 | { | |
177 | return 2; | |
178 | } | |
179 | ||
180 | //////////////////////////////////////// | |
181 | // Unicode decomposed | |
182 | //////////////////////////////////////// | |
183 | //------------------------------------------- | |
184 | int uniCompInfoCompare(const void *ele1, const void *ele2) | |
185 | { | |
186 | UKDWORD ch1 = ((UniCompCharInfo *)ele1)->compChar; | |
187 | UKDWORD ch2 = ((UniCompCharInfo *)ele2)->compChar; | |
188 | return (ch1 == ch2)? 0 : ((ch1 > ch2)? 1 : -1); | |
189 | } | |
190 | ||
191 | UnicodeCompCharset::UnicodeCompCharset(UnicodeChar *uniChars, UKDWORD *uniCompChars) | |
192 | { | |
193 | int i,k; | |
194 | m_uniCompChars = uniCompChars; | |
195 | m_totalChars = 0; | |
196 | for (i=0; i<TOTAL_VNCHARS; i++) { | |
197 | m_info[i].compChar = uniCompChars[i]; | |
198 | m_info[i].stdIndex = i; | |
199 | m_totalChars++; | |
200 | } | |
201 | ||
202 | for (k=0, i=TOTAL_VNCHARS; k<TOTAL_VNCHARS; k++) | |
203 | if (uniChars[k] != uniCompChars[k]) { | |
204 | m_info[i].compChar = uniChars[k]; | |
205 | m_info[i].stdIndex = k; | |
206 | m_totalChars++; | |
207 | i++; | |
208 | } | |
209 | ||
210 | qsort(m_info, m_totalChars, sizeof(UniCompCharInfo), uniCompInfoCompare); | |
211 | } | |
212 | ||
213 | //--------------------------------------------- | |
214 | int UnicodeCompCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
215 | { | |
216 | // read first char | |
217 | ||
218 | UniCompCharInfo key; | |
219 | UKWORD w; | |
220 | if (!is.getNextW(w)) { | |
221 | bytesRead = 0; | |
222 | return 0; | |
223 | } | |
224 | key.compChar = w; | |
225 | bytesRead = 2; | |
226 | ||
227 | UniCompCharInfo *pInfo = (UniCompCharInfo *)bsearch(&key, m_info, m_totalChars, | |
228 | sizeof(UniCompCharInfo), uniCompInfoCompare); | |
229 | if (!pInfo) | |
230 | stdChar = key.compChar; | |
231 | else { | |
232 | stdChar = pInfo->stdIndex + VnStdCharOffset; | |
233 | if (is.peekNextW(w)) { | |
234 | UKDWORD hi = w; | |
235 | if (hi > 0) { | |
236 | key.compChar += hi << 16; | |
237 | pInfo = (UniCompCharInfo *)bsearch(&key, m_info, m_totalChars, | |
238 | sizeof(UniCompCharInfo), uniCompInfoCompare); | |
239 | if (pInfo) { | |
240 | stdChar = pInfo->stdIndex + VnStdCharOffset; | |
241 | bytesRead += 2; | |
242 | is.getNextW(w); | |
243 | } | |
244 | } | |
245 | } | |
246 | } | |
247 | return 1; | |
248 | } | |
249 | ||
250 | //--------------------------------------------- | |
251 | int UnicodeCompCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
252 | { | |
253 | int ret; | |
254 | if (stdChar >= VnStdCharOffset) { | |
255 | UKDWORD uniCompCh = m_uniCompChars[stdChar-VnStdCharOffset]; | |
256 | UKWORD lo = LOWORD(uniCompCh); | |
257 | UKWORD hi = HIWORD(uniCompCh); | |
258 | outLen = 2; | |
259 | ret = os.putW(lo); | |
260 | if (hi > 0) { | |
261 | outLen += 2; | |
262 | ret = os.putW(hi); | |
263 | } | |
264 | } | |
265 | else { | |
266 | outLen = 2; | |
267 | ret = os.putW((UKWORD)stdChar); | |
268 | } | |
269 | return ret; | |
270 | } | |
271 | ||
272 | //------------------------------------------- | |
273 | int UnicodeCompCharset::elementSize() | |
274 | { | |
275 | return 2; | |
276 | } | |
277 | ||
278 | //////////////////////////////// | |
279 | // Unicode UTF-8 // | |
280 | //////////////////////////////// | |
281 | int UnicodeUTF8Charset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
282 | { | |
283 | UKWORD w1, w2, w3; | |
284 | UKBYTE first, second, third; | |
285 | UnicodeChar uniCh; | |
286 | ||
287 | bytesRead = 0; | |
288 | if (!is.getNext(first)) | |
289 | return 0; | |
290 | bytesRead = 1; | |
291 | ||
292 | if (first < 0x80) | |
293 | uniCh = first; // 1-byte sequence | |
294 | else if ((first & 0xE0) == 0xC0) { | |
295 | //2-byte sequence | |
296 | if (!is.peekNext(second)) | |
297 | return 0; | |
298 | if ((second & 0xC0) != 0x80) { | |
299 | stdChar = INVALID_STD_CHAR; | |
300 | return 1; | |
301 | } | |
302 | is.getNext(second); | |
303 | bytesRead = 2; | |
304 | w1 = first; | |
305 | w2 = second; | |
306 | uniCh = ((w1 & 0x001F) << 6) | (w2 & 0x3F); | |
307 | } | |
308 | else if ((first & 0xF0) == 0xE0) { | |
309 | //3-byte sequence | |
310 | if (!is.peekNext(second)) | |
311 | return 0; | |
312 | if ((second & 0xC0) != 0x80) { | |
313 | stdChar = INVALID_STD_CHAR; | |
314 | return 1; | |
315 | } | |
316 | is.getNext(second); | |
317 | bytesRead = 2; | |
318 | if (!is.peekNext(third)) | |
319 | return 0; | |
320 | if ((third & 0xC0) != 0x80) { | |
321 | stdChar = INVALID_STD_CHAR; | |
322 | return 1; | |
323 | } | |
324 | is.getNext(third); | |
325 | bytesRead = 3; | |
326 | w1 = first; | |
327 | w2 = second; | |
328 | w3 = third; | |
329 | uniCh = ((w1 & 0x000F) << 12) | ((w2 & 0x003F) << 6) | (w3 & 0x003F); | |
330 | } | |
331 | else { | |
332 | stdChar = INVALID_STD_CHAR; | |
333 | return 1; | |
334 | } | |
335 | ||
336 | // translate to StdVnChar | |
337 | UKDWORD key = uniCh; | |
338 | UKDWORD *pChar = (UKDWORD *)bsearch(&key, m_vnChars, TOTAL_VNCHARS, sizeof(UKDWORD), wideCharCompare); | |
339 | if (pChar) | |
340 | stdChar = VnStdCharOffset + HIWORD(*pChar); | |
341 | else stdChar = uniCh; | |
342 | return 1; | |
343 | } | |
344 | ||
345 | //------------------------------------------- | |
346 | int UnicodeUTF8Charset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
347 | { | |
348 | UnicodeChar uChar = (stdChar < VnStdCharOffset)? | |
349 | (UnicodeChar)stdChar : m_toUnicode[stdChar-VnStdCharOffset]; | |
350 | int ret; | |
351 | if (uChar < 0x0080) { | |
352 | outLen = 1; | |
353 | ret = os.putB((UKBYTE)uChar); | |
354 | } else if (uChar < 0x0800) { | |
355 | outLen = 2; | |
356 | os.putB(0xC0 | (UKBYTE)(uChar >> 6)); | |
357 | ret = os.putB(0x80 | (UKBYTE)(uChar & 0x003F)); | |
358 | } else { | |
359 | outLen = 3; | |
360 | os.putB(0xE0 | (UKBYTE)(uChar >> 12)); | |
361 | os.putB(0x80 | (UKBYTE)((uChar >> 6) & 0x003F)); | |
362 | ret = os.putB(0x80 | (UKBYTE)(uChar & 0x003F)); | |
363 | } | |
364 | return ret; | |
365 | } | |
366 | ||
367 | //////////////////////////////////////// | |
368 | // Unicode character reference &#D; // | |
369 | //////////////////////////////////////// | |
370 | int hexDigitValue(unsigned char digit) | |
371 | { | |
372 | if (digit >= 'a' && digit <= 'f') | |
373 | return digit-'a'+10; | |
374 | if (digit >= 'A' && digit <= 'F') | |
375 | return digit-'A'+10; | |
376 | if (digit >= '0' && digit <= '9') | |
377 | return digit-'0'; | |
378 | return 0; | |
379 | } | |
380 | ||
381 | ||
382 | //-------------------------------------- | |
383 | int UnicodeRefCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
384 | { | |
385 | unsigned char ch; | |
386 | UnicodeChar uniCh; | |
387 | bytesRead = 0; | |
388 | if (!is.getNext(ch)) | |
389 | return 0; | |
390 | bytesRead = 1; | |
391 | uniCh = ch; | |
392 | if (ch == '&') { | |
393 | if (is.peekNext(ch) && ch == '#') { | |
394 | is.getNext(ch); | |
395 | bytesRead++; | |
396 | if (!is.eos()) { | |
397 | is.peekNext(ch); | |
398 | if (ch != 'x' && ch != 'X') { | |
399 | UKWORD code = 0; | |
400 | int digits = 0; | |
401 | while (is.peekNext(ch) && isdigit(ch) && digits < 5) { | |
402 | is.getNext(ch); | |
403 | bytesRead++; | |
404 | code = code*10 + (ch - '0'); | |
405 | digits++; | |
406 | } | |
407 | if (is.peekNext(ch) && ch == ';') { | |
408 | is.getNext(ch); | |
409 | bytesRead++; | |
410 | uniCh = code; | |
411 | } | |
412 | } | |
413 | else { | |
414 | is.getNext(ch); | |
415 | bytesRead++; | |
416 | UKWORD code = 0; | |
417 | int digits = 0; | |
418 | while (is.peekNext(ch) && isxdigit(ch) && digits < 4) { | |
419 | is.getNext(ch); | |
420 | bytesRead++; | |
421 | code = (code << 4) + hexDigitValue(ch); | |
422 | digits++; | |
423 | } | |
424 | if (is.peekNext(ch) && ch == ';') { | |
425 | is.getNext(ch); | |
426 | bytesRead++; | |
427 | uniCh = code; | |
428 | } | |
429 | } // hex digits | |
430 | } | |
431 | } | |
432 | } | |
433 | ||
434 | // translate to StdVnChar | |
435 | UKDWORD key = uniCh; | |
436 | UKDWORD *pChar = (UKDWORD *)bsearch(&key, m_vnChars, TOTAL_VNCHARS, sizeof(UKDWORD), wideCharCompare); | |
437 | if (pChar) | |
438 | stdChar = VnStdCharOffset + HIWORD(*pChar); | |
439 | else stdChar = uniCh; | |
440 | return 1; | |
441 | } | |
442 | ||
443 | ||
444 | //-------------------------------- | |
445 | int UnicodeRefCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
446 | { | |
447 | UnicodeChar uChar = (stdChar < VnStdCharOffset)? | |
448 | (UnicodeChar)stdChar : m_toUnicode[stdChar-VnStdCharOffset]; | |
449 | int ret; | |
450 | if (uChar < 128) { | |
451 | outLen = 1; | |
452 | ret = os.putB((UKBYTE)uChar); | |
453 | } | |
454 | else { | |
455 | outLen = 2; | |
456 | os.putB((UKBYTE)'&'); | |
457 | os.putB((UKBYTE)'#'); | |
458 | ||
459 | int i, digit, prev, base; | |
460 | prev = 0; | |
461 | base = 10000; | |
462 | for (i=0; i < 5; i++) { | |
463 | digit = uChar / base; | |
464 | if (digit || prev) { | |
465 | prev = 1; | |
466 | outLen++; | |
467 | os.putB('0' + (unsigned char)digit); | |
468 | } | |
469 | uChar %= base; | |
470 | base /= 10; | |
471 | } | |
472 | ret = os.putB((UKBYTE)';'); | |
473 | outLen++; | |
474 | } | |
475 | return ret; | |
476 | } | |
477 | ||
478 | #define HEX_DIGIT(x) ((x < 10)? ('0'+x) : ('A'+x-10)) | |
479 | ||
480 | //-------------------------------- | |
481 | int UnicodeHexCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
482 | { | |
483 | UnicodeChar uChar = (stdChar < VnStdCharOffset)? | |
484 | (UnicodeChar)stdChar : m_toUnicode[stdChar-VnStdCharOffset]; | |
485 | int ret; | |
486 | if (uChar < 256) { | |
487 | outLen = 1; | |
488 | ret = os.putB((UKBYTE)uChar); | |
489 | } | |
490 | else { | |
491 | outLen = 3; | |
492 | os.putB('&'); | |
493 | os.putB('#'); | |
494 | os.putB('x'); | |
495 | ||
496 | int i, digit; | |
497 | int prev = 0; | |
498 | int shifts = 12; | |
499 | ||
500 | for (i=0; i < 4; i++) { | |
501 | digit = ((uChar >> shifts) & 0x000F); | |
502 | if (digit > 0 || prev) { | |
503 | prev = 1; | |
504 | outLen++; | |
505 | os.putB((UKBYTE)HEX_DIGIT(digit)); | |
506 | } | |
507 | shifts -= 4; | |
508 | } | |
509 | ret = os.putB(';'); | |
510 | outLen++; | |
511 | } | |
512 | return ret; | |
513 | } | |
514 | ||
515 | ||
516 | ///////////////////////////////// | |
517 | // Class UnicodeCStringCharset / | |
518 | ///////////////////////////////// | |
519 | void UnicodeCStringCharset::startInput() | |
520 | { | |
521 | m_prevIsHex = 0; | |
522 | } | |
523 | ||
524 | //---------------------------------------- | |
525 | int UnicodeCStringCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
526 | { | |
527 | unsigned char ch; | |
528 | UnicodeChar uniCh; | |
529 | bytesRead = 0; | |
530 | if (!is.getNext(ch)) | |
531 | return 0; | |
532 | bytesRead = 1; | |
533 | uniCh = ch; | |
534 | if (ch == '\\') { | |
535 | if (is.peekNext(ch) && (ch=='x' || ch=='X')) { | |
536 | is.getNext(ch); | |
537 | bytesRead++; | |
538 | UKWORD code = 0; | |
539 | int digits = 0; | |
540 | while (is.peekNext(ch) && isxdigit(ch) && digits < 4) { | |
541 | is.getNext(ch); | |
542 | bytesRead++; | |
543 | code = (code << 4) + hexDigitValue(ch); | |
544 | digits++; | |
545 | } | |
546 | uniCh = code; | |
547 | } | |
548 | } | |
549 | ||
550 | // translate to StdVnChar | |
551 | UKDWORD key = uniCh; | |
552 | UKDWORD *pChar = (UKDWORD *)bsearch(&key, m_vnChars, TOTAL_VNCHARS, sizeof(UKDWORD), wideCharCompare); | |
553 | if (pChar) | |
554 | stdChar = VnStdCharOffset + HIWORD(*pChar); | |
555 | else stdChar = uniCh; | |
556 | return 1; | |
557 | } | |
558 | ||
559 | //------------------------------------ | |
560 | int UnicodeCStringCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
561 | { | |
562 | UnicodeChar uChar = (stdChar < VnStdCharOffset)? | |
563 | (UnicodeChar)stdChar : m_toUnicode[stdChar-VnStdCharOffset]; | |
564 | int ret; | |
565 | if (uChar < 128 && !isxdigit(uChar) && uChar != 'x' && uChar != 'X') { | |
566 | outLen = 1; | |
567 | ret = os.putB((UKBYTE)uChar); | |
568 | } | |
569 | else { | |
570 | outLen = 2; | |
571 | os.putB('\\'); | |
572 | os.putB('x'); | |
573 | ||
574 | int i, digit; | |
575 | int prev = 0; | |
576 | int shifts = 12; | |
577 | ||
578 | for (i=0; i < 4; i++) { | |
579 | digit = ((uChar >> shifts) & 0x000F); | |
580 | if (digit > 0 || prev) { | |
581 | prev = 1; | |
582 | outLen++; | |
583 | os.putB((UKBYTE)HEX_DIGIT(digit)); | |
584 | } | |
585 | shifts -= 4; | |
586 | } | |
587 | ret = os.isOK(); | |
588 | m_prevIsHex = 1; | |
589 | } | |
590 | return ret; | |
591 | } | |
592 | ||
593 | ///////////////////////////////// | |
594 | // Double-byte charsets // | |
595 | ///////////////////////////////// | |
596 | DoubleByteCharset::DoubleByteCharset(UKWORD *vnChars) | |
597 | { | |
598 | m_toDoubleChar = vnChars; | |
599 | memset(m_stdMap, 0, 256*sizeof(UKWORD)); | |
600 | for (int i=0; i<TOTAL_VNCHARS; i++) { | |
601 | if (vnChars[i] >> 8) // a 2-byte character | |
602 | m_stdMap[vnChars[i] >> 8] = 0xFFFF; //INVALID_STD_CHAR; | |
603 | else if (m_stdMap[vnChars[i]] == 0) | |
604 | m_stdMap[vnChars[i]] = i+1; | |
605 | m_vnChars[i] = (i << 16) + vnChars[i]; // high word is used for StdChar index | |
606 | } | |
607 | qsort(m_vnChars, TOTAL_VNCHARS, sizeof(UKDWORD), wideCharCompare); | |
608 | } | |
609 | ||
610 | //--------------------------------------------- | |
611 | int DoubleByteCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
612 | { | |
613 | unsigned char ch; | |
614 | ||
615 | // read first byte | |
616 | bytesRead = 0; | |
617 | if (!is.getNext(ch)) | |
618 | return 0; | |
619 | bytesRead = 1; | |
620 | stdChar = m_stdMap[ch]; | |
621 | if (stdChar == 0) | |
622 | stdChar = ch; | |
623 | else if (stdChar == 0xFFFF) | |
624 | stdChar = INVALID_STD_CHAR; | |
625 | else { | |
626 | stdChar += VnStdCharOffset - 1; | |
627 | UKBYTE hi; | |
628 | if (is.peekNext(hi) && hi > 0) { | |
629 | //test if a double-byte character is encountered | |
630 | UKDWORD key = MAKEWORD(ch,hi); | |
631 | UKDWORD *pChar = (UKDWORD *)bsearch(&key, m_vnChars, TOTAL_VNCHARS, sizeof(UKDWORD), wideCharCompare); | |
632 | if (pChar) { | |
633 | stdChar = VnStdCharOffset + HIWORD(*pChar); | |
634 | bytesRead = 2; | |
635 | is.getNext(hi); | |
636 | } | |
637 | } | |
638 | } | |
639 | return 1; | |
640 | } | |
641 | ||
642 | //--------------------------------------------- | |
643 | int DoubleByteCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
644 | { | |
645 | int ret; | |
646 | if (stdChar >= VnStdCharOffset) { | |
647 | UKWORD wCh = m_toDoubleChar[stdChar-VnStdCharOffset]; | |
648 | ||
649 | if (wCh & 0xFF00) { | |
650 | outLen = 2; | |
651 | os.putB((UKBYTE)(wCh & 0x00FF)); | |
652 | ret = os.putB((UKBYTE)(wCh >> 8)); | |
653 | } | |
654 | else { | |
655 | unsigned char b = (unsigned char)wCh; | |
656 | if (m_stdMap[b] == 0xFFFF) | |
657 | b = PadChar; | |
658 | outLen = 1; | |
659 | ret = os.putB(b); | |
660 | } | |
661 | /* | |
662 | outLen = 1; | |
663 | ret = os.putB((UKBYTE)(wCh & 0x00FF)); | |
664 | if (wCh & 0xFF00) { | |
665 | outLen = 2; | |
666 | ret = os.putB((UKBYTE)(wCh >> 8)); | |
667 | } | |
668 | */ | |
669 | } | |
670 | else { | |
671 | if (stdChar > 255 || m_stdMap[stdChar]) { | |
672 | outLen = 1; | |
673 | ret = os.putB((UKBYTE)PadChar); | |
674 | } | |
675 | else { | |
676 | outLen = 1; | |
677 | ret = os.putB((UKBYTE)stdChar); | |
678 | } | |
679 | } | |
680 | return ret; | |
681 | } | |
682 | ||
683 | ///////////////////////////////////////////// | |
684 | // Class: VIQRCharset // | |
685 | ///////////////////////////////////////////// | |
686 | ||
687 | unsigned char VIQRTones[] = {'\'','`','?','~','.'}; | |
688 | ||
689 | const char *VIQREscapes[] = { | |
690 | "://", | |
691 | "/", | |
692 | "@", | |
693 | "mailto:", | |
694 | "email:", | |
695 | "news:", | |
696 | "www", | |
697 | "ftp" | |
698 | }; | |
699 | ||
700 | const int VIQREscCount = sizeof(VIQREscapes) / sizeof(char*); | |
701 | ||
702 | VIQRCharset::VIQRCharset(UKDWORD *vnChars) | |
703 | { | |
704 | memset(m_stdMap, 0, 256*sizeof(UKWORD)); | |
705 | int i; | |
706 | UKDWORD dw; | |
707 | m_vnChars = vnChars; | |
708 | for (i=0; i<TOTAL_VNCHARS; i++) { | |
709 | dw = m_vnChars[i]; | |
710 | if (!(dw & 0xffffff00)) { //single byte | |
711 | //ch = (unsigned char)(dw & 0xff); | |
712 | m_stdMap[dw] = i+256; | |
713 | } | |
714 | } | |
715 | ||
716 | // set offset from base characters according to tone marks | |
717 | m_stdMap[(unsigned char)'\''] = 2; | |
718 | m_stdMap[(unsigned char)'`'] = 4; | |
719 | m_stdMap[(unsigned char)'?'] = 6; | |
720 | m_stdMap[(unsigned char)'~'] = 8; | |
721 | m_stdMap[(unsigned char)'.'] = 10; | |
722 | m_stdMap[(unsigned char)'^'] = 12; | |
723 | ||
724 | m_stdMap[(unsigned char)'('] = 24; | |
725 | m_stdMap[(unsigned char)'+'] = 26; | |
726 | m_stdMap[(unsigned char)'*'] = 26; | |
727 | } | |
728 | ||
729 | //--------------------------------------------------- | |
730 | void VIQRCharset::startInput() | |
731 | { | |
732 | m_suspicious = 0; | |
733 | m_atWordBeginning = 1; | |
734 | m_gotTone = 0; | |
735 | m_escAll = 0; | |
736 | if (VnCharsetLibObj.m_options.viqrEsc) | |
737 | VnCharsetLibObj.m_VIQREscPatterns.reset(); | |
738 | } | |
739 | ||
740 | //--------------------------------------------------- | |
741 | int VIQRCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
742 | { | |
743 | unsigned char ch1; | |
744 | bytesRead = 0; | |
745 | ||
746 | if (!is.getNext(ch1)) | |
747 | return 0; | |
748 | bytesRead = 1; | |
749 | stdChar = m_stdMap[ch1]; | |
750 | ||
751 | if (VnCharsetLibObj.m_options.viqrEsc) { | |
752 | if (VnCharsetLibObj.m_VIQREscPatterns.foundAtNextChar(ch1)!=-1) { | |
753 | m_escAll = 1; | |
754 | } | |
755 | } | |
756 | ||
757 | if (m_escAll && (ch1==' ' || ch1=='\t' || ch1=='\r' || ch1=='\n')) | |
758 | m_escAll = 0; | |
759 | ||
760 | if (ch1 == '\\') { | |
761 | // ecape character , try to read next | |
762 | if (!is.getNext(ch1)) { | |
763 | bytesRead++; | |
764 | stdChar = m_stdMap[ch1]; | |
765 | } | |
766 | } | |
767 | ||
768 | if (stdChar < 256) { | |
769 | stdChar = ch1; | |
770 | } | |
771 | else if (!m_escAll && !is.eos()) { | |
772 | // try to read the next byte | |
773 | unsigned char ch2; | |
774 | is.peekNext(ch2); | |
775 | unsigned char upper = toupper(ch1); | |
776 | if ((!VnCharsetLibObj.m_options.smartViqr || m_atWordBeginning) && | |
777 | upper == 'D' && (ch2 == 'd' || ch2 == 'D')) | |
778 | { | |
779 | is.getNext(ch2); | |
780 | bytesRead++; | |
781 | stdChar += 2; // dd is 2 positions after d. | |
782 | } | |
783 | else { | |
784 | StdVnChar index = m_stdMap[ch2]; | |
785 | ||
786 | int cond; | |
787 | if (m_suspicious) { | |
788 | cond = IS_VOWEL(ch1) && | |
789 | ( index == 2 || index == 4 || index == 8 || //not accepting ? . in suspicious mode | |
790 | (index == 12 && (upper == 'A' || upper == 'E' || upper == 'O')) || | |
791 | (m_stdMap[ch2] == 24 && upper== 'A') || | |
792 | (m_stdMap[ch2] == 26 && (upper == 'O' || upper == 'U')) ); | |
793 | if (cond) | |
794 | m_suspicious = 0; | |
795 | } | |
796 | else | |
797 | cond = IS_VOWEL(ch1) && | |
798 | ((index <= 10 && index > 0 && (!m_gotTone || (index!=6 && index!=10)) ) || | |
799 | (index == 12 && (upper == 'A' || upper == 'E' || upper == 'O')) || | |
800 | (m_stdMap[ch2] == 24 && upper== 'A') || | |
801 | (m_stdMap[ch2] == 26 && (upper == 'O' || upper == 'U')) ); | |
802 | ||
803 | if (cond) { | |
804 | if (index > 0) | |
805 | m_gotTone = 1; //we have a tone/breve/hook in the current word | |
806 | ||
807 | // ok, take this byte | |
808 | is.getNext(ch2); | |
809 | bytesRead++; | |
810 | int offset = m_stdMap[ch2]; | |
811 | if (offset == 26) offset = 24; | |
812 | if (offset == 24 && (ch1 == 'u' || ch1 == 'U')) | |
813 | offset = 12; | |
814 | stdChar += offset; | |
815 | // check next byte | |
816 | if (is.peekNext(ch2)) { | |
817 | if (index > 10 && m_stdMap[ch2] > 0 && m_stdMap[ch2] <= 10) { | |
818 | // ok, take one more byte | |
819 | is.getNext(ch2); | |
820 | bytesRead++; | |
821 | stdChar += m_stdMap[ch2]; | |
822 | } | |
823 | } | |
824 | } | |
825 | } | |
826 | } | |
827 | m_atWordBeginning = (stdChar < 256); | |
828 | if (stdChar < 256) { | |
829 | m_gotTone = 0; //reset this flag because we are at the beginning of a new word | |
830 | } | |
831 | ||
832 | // adjust stdChar | |
833 | if (stdChar >= 256) | |
834 | stdChar += VnStdCharOffset - 256; | |
835 | return 1; | |
836 | } | |
837 | ||
838 | //--------------------------------------------------- | |
839 | void VIQRCharset::startOutput() | |
840 | { | |
841 | m_escapeBowl = 0; | |
842 | m_escapeRoof = 0; | |
843 | m_escapeHook = 0; | |
844 | m_escapeTone = 0; | |
845 | m_noOutEsc = 0; | |
846 | VnCharsetLibObj.m_VIQROutEscPatterns.reset(); | |
847 | } | |
848 | ||
849 | //--------------------------------------------------- | |
850 | int VIQRCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
851 | { | |
852 | int ret; | |
853 | UKBYTE b; | |
854 | if (stdChar >= VnStdCharOffset) { | |
855 | outLen = 1; | |
856 | UKDWORD dw = m_vnChars[stdChar-VnStdCharOffset]; | |
857 | ||
858 | unsigned char first = (unsigned char)dw; | |
859 | unsigned char firstUpper = toupper(first); | |
860 | ||
861 | b = (UKBYTE)dw; | |
862 | ret = os.putB(b); | |
863 | if (VnCharsetLibObj.m_VIQROutEscPatterns.foundAtNextChar(b) != -1) | |
864 | m_noOutEsc = 1; | |
865 | ||
866 | if (m_noOutEsc && (b==' ' || b=='\t' || b=='\r' || b=='\n')) | |
867 | m_noOutEsc = 0; | |
868 | ||
869 | if (dw & 0x0000FF00) { | |
870 | // second byte is present | |
871 | unsigned char second = (UKBYTE)(dw >> 8); | |
872 | outLen++; | |
873 | ret = os.putB(second); | |
874 | ||
875 | if (dw & 0x00FF0000) { | |
876 | //third byte is present | |
877 | outLen++; | |
878 | ret = os.putB((UKBYTE)(dw >> 16)); | |
879 | m_escapeTone = 0; | |
880 | } | |
881 | else { | |
882 | UKWORD index = m_stdMap[second]; | |
883 | m_escapeTone = (index == 12 || index == 24 || index == 26); | |
884 | } | |
885 | ||
886 | VnCharsetLibObj.m_VIQROutEscPatterns.reset(); | |
887 | ||
888 | m_escapeBowl = 0; | |
889 | m_escapeHook = 0; | |
890 | m_escapeRoof = 0; | |
891 | } | |
892 | else { | |
893 | m_escapeTone = IS_VOWEL(first); | |
894 | m_escapeBowl = (firstUpper == 'A'); | |
895 | m_escapeHook = (firstUpper == 'U' || firstUpper == 'O'); | |
896 | m_escapeRoof = (firstUpper == 'A' || firstUpper == 'E' || firstUpper == 'O'); | |
897 | } | |
898 | } | |
899 | else { | |
900 | if (stdChar > 255) { | |
901 | outLen = 1; | |
902 | ret = os.putB((UKBYTE)PadChar); | |
903 | if (VnCharsetLibObj.m_VIQROutEscPatterns.foundAtNextChar((UKBYTE)PadChar) != -1) | |
904 | m_noOutEsc = 1; | |
905 | } | |
906 | else { | |
907 | outLen = 1; | |
908 | UKWORD index = m_stdMap[stdChar]; | |
909 | if (!VnCharsetLibObj.m_options.viqrMixed && !m_noOutEsc && | |
910 | (stdChar=='\\' || | |
911 | (index > 0 && index <= 10 && m_escapeTone) || | |
912 | (index == 12 && m_escapeRoof) || | |
913 | (index == 24 && m_escapeBowl) || | |
914 | (index == 26 && m_escapeHook))) { | |
915 | //(m_stdMap[stdChar] > 0 && m_stdMap[stdChar] <= 26)) { | |
916 | // tone mark, needs an escape character | |
917 | outLen++; | |
918 | ret = os.putB('\\'); | |
919 | if (VnCharsetLibObj.m_VIQROutEscPatterns.foundAtNextChar('\\') != -1) | |
920 | m_noOutEsc = 1; | |
921 | } | |
922 | b = (UKBYTE)stdChar; | |
923 | ret = os.putB(b); | |
924 | if (VnCharsetLibObj.m_VIQROutEscPatterns.foundAtNextChar(b) != -1) | |
925 | m_noOutEsc = 1; | |
926 | if (m_noOutEsc && (b==' ' || b=='\t' || b=='\r' || b=='\n')) | |
927 | m_noOutEsc = 0; | |
928 | } | |
929 | // reset escape marks | |
930 | m_escapeBowl = 0; | |
931 | m_escapeRoof = 0; | |
932 | m_escapeHook = 0; | |
933 | m_escapeTone = 0; | |
934 | } | |
935 | return ret; | |
936 | } | |
937 | ||
938 | ///////////////////////////////////////////// | |
939 | // Class: UTF8VIQRCharset // | |
940 | ///////////////////////////////////////////// | |
941 | ||
942 | //----------------------------------------- | |
943 | UTF8VIQRCharset::UTF8VIQRCharset(UnicodeUTF8Charset *pUtf, VIQRCharset *pViqr) | |
944 | { | |
945 | m_pUtf = pUtf; | |
946 | m_pViqr = pViqr; | |
947 | } | |
948 | ||
949 | //----------------------------------------- | |
950 | void UTF8VIQRCharset::startInput() | |
951 | { | |
952 | m_pUtf->startInput(); | |
953 | m_pViqr->startInput(); | |
954 | } | |
955 | ||
956 | //----------------------------------------- | |
957 | void UTF8VIQRCharset::startOutput() | |
958 | { | |
959 | m_pUtf->startOutput(); | |
960 | m_pViqr->startOutput(); | |
961 | } | |
962 | ||
963 | //----------------------------------------- | |
964 | int UTF8VIQRCharset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
965 | { | |
966 | UKBYTE ch; | |
967 | ||
968 | if (!is.peekNext(ch)) | |
969 | return 0; | |
970 | ||
971 | if (ch > 0xBF && ch < 0xFE) { | |
972 | m_pViqr->startInput(); // just to reset the VIQR object state | |
973 | m_pViqr->m_suspicious = 1; | |
974 | return m_pUtf->nextInput(is, stdChar, bytesRead); | |
975 | } | |
976 | ||
977 | return m_pViqr->nextInput(is, stdChar, bytesRead); | |
978 | } | |
979 | ||
980 | //----------------------------------------- | |
981 | int UTF8VIQRCharset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
982 | { | |
983 | return m_pViqr->putChar(os, stdChar, outLen); | |
984 | } | |
985 | ||
986 | ||
987 | //----------------------------------------- | |
988 | CVnCharsetLib::CVnCharsetLib() | |
989 | { | |
990 | unsigned char ch; | |
991 | for (ch = 'a'; ch < 'z'; ch++) | |
992 | LoVowel[ch-'a'] = 0; | |
993 | LoVowel['a'-'a'] = 1; | |
994 | LoVowel['e'-'a'] = 1; | |
995 | LoVowel['i'-'a'] = 1; | |
996 | LoVowel['o'-'a'] = 1; | |
997 | LoVowel['u'-'a'] = 1; | |
998 | LoVowel['y'-'a'] = 1; | |
999 | ||
1000 | for (ch = 'A'; ch < 'Z'; ch++) | |
1001 | HiVowel[ch-'A'] = 0; | |
1002 | HiVowel['A'-'A'] = 1; | |
1003 | HiVowel['E'-'A'] = 1; | |
1004 | HiVowel['I'-'A'] = 1; | |
1005 | HiVowel['O'-'A'] = 1; | |
1006 | HiVowel['U'-'A'] = 1; | |
1007 | HiVowel['Y'-'A'] = 1; | |
1008 | ||
1009 | m_pUniCharset = NULL; | |
1010 | m_pUniCompCharset = NULL; | |
1011 | m_pUniUTF8 = NULL; | |
1012 | m_pUniRef = NULL; | |
1013 | m_pUniHex = NULL; | |
1014 | m_pVIQRCharObj = NULL; | |
1015 | m_pUVIQRCharObj = NULL; | |
1016 | m_pWinCP1258 = NULL; | |
1017 | m_pVnIntCharset = NULL; | |
1018 | ||
1019 | int i; | |
1020 | for (i = 0; i < CONV_TOTAL_SINGLE_CHARSETS; i++) | |
1021 | m_sgCharsets[i] = NULL; | |
1022 | ||
1023 | for (i = 0; i < CONV_TOTAL_DOUBLE_CHARSETS; i++) | |
1024 | m_dbCharsets[i] = NULL; | |
1025 | ||
1026 | VnConvResetOptions(&m_options); | |
1027 | m_VIQREscPatterns.init((char**)VIQREscapes, VIQREscCount); | |
1028 | m_VIQROutEscPatterns.init((char**)VIQREscapes, VIQREscCount); | |
1029 | } | |
1030 | ||
1031 | ||
1032 | //----------------------------------------- | |
1033 | CVnCharsetLib::~CVnCharsetLib() | |
1034 | { | |
1035 | if (m_pUniCharset) | |
1036 | delete m_pUniCharset; | |
1037 | if (m_pUniUTF8) | |
1038 | delete m_pUniUTF8; | |
1039 | if (m_pUniRef) | |
1040 | delete m_pUniRef; | |
1041 | if (m_pUniHex) | |
1042 | delete m_pUniHex; | |
1043 | if (m_pVIQRCharObj) | |
1044 | delete m_pVIQRCharObj; | |
1045 | if (m_pUVIQRCharObj) | |
1046 | delete m_pUVIQRCharObj; | |
1047 | if (m_pWinCP1258) | |
1048 | delete m_pWinCP1258; | |
1049 | if (m_pUniCString) | |
1050 | delete m_pUniCString; | |
1051 | if (m_pVnIntCharset) | |
1052 | delete m_pVnIntCharset; | |
1053 | ||
1054 | int i; | |
1055 | for (i = 0; i < CONV_TOTAL_SINGLE_CHARSETS; i++) | |
1056 | if (m_sgCharsets[i]) delete m_sgCharsets[i]; | |
1057 | ||
1058 | for (i = 0; i < CONV_TOTAL_DOUBLE_CHARSETS; i++) | |
1059 | if (m_dbCharsets[i]) delete m_dbCharsets[i]; | |
1060 | ||
1061 | } | |
1062 | ||
1063 | //----------------------------------------- | |
1064 | VnCharset * CVnCharsetLib::getVnCharset(int charsetIdx) | |
1065 | { | |
1066 | switch (charsetIdx) { | |
1067 | ||
1068 | case CONV_CHARSET_UNICODE: | |
1069 | if (m_pUniCharset == NULL) | |
1070 | m_pUniCharset = new UnicodeCharset(UnicodeTable); | |
1071 | return m_pUniCharset; | |
1072 | case CONV_CHARSET_UNIDECOMPOSED: | |
1073 | if (m_pUniCompCharset == NULL) | |
1074 | m_pUniCompCharset = new UnicodeCompCharset(UnicodeTable, UnicodeComposite); | |
1075 | return m_pUniCompCharset; | |
1076 | case CONV_CHARSET_UNIUTF8: | |
1077 | case CONV_CHARSET_XUTF8: | |
1078 | if (m_pUniUTF8 == NULL) | |
1079 | m_pUniUTF8 = new UnicodeUTF8Charset(UnicodeTable); | |
1080 | return m_pUniUTF8; | |
1081 | ||
1082 | case CONV_CHARSET_UNIREF: | |
1083 | if (m_pUniRef == NULL) | |
1084 | m_pUniRef = new UnicodeRefCharset(UnicodeTable); | |
1085 | return m_pUniRef; | |
1086 | ||
1087 | case CONV_CHARSET_UNIREF_HEX: | |
1088 | if (m_pUniHex == NULL) | |
1089 | m_pUniHex = new UnicodeHexCharset(UnicodeTable); | |
1090 | return m_pUniHex; | |
1091 | ||
1092 | case CONV_CHARSET_UNI_CSTRING: | |
1093 | if (m_pUniCString == NULL) | |
1094 | m_pUniCString = new UnicodeCStringCharset(UnicodeTable); | |
1095 | return m_pUniCString; | |
1096 | ||
1097 | case CONV_CHARSET_WINCP1258: | |
1098 | if (m_pWinCP1258 == NULL) | |
1099 | m_pWinCP1258 = new WinCP1258Charset(WinCP1258, WinCP1258Pre); | |
1100 | return m_pWinCP1258; | |
1101 | ||
1102 | case CONV_CHARSET_VIQR: | |
1103 | if (m_pVIQRCharObj == NULL) | |
1104 | m_pVIQRCharObj = new VIQRCharset(VIQRTable); | |
1105 | return m_pVIQRCharObj; | |
1106 | ||
1107 | case CONV_CHARSET_VNSTANDARD: | |
1108 | if (m_pVnIntCharset == NULL) | |
1109 | m_pVnIntCharset = new VnInternalCharset(); | |
1110 | return m_pVnIntCharset; | |
1111 | ||
1112 | case CONV_CHARSET_UTF8VIQR: | |
1113 | if (m_pUVIQRCharObj == NULL) { | |
1114 | if (m_pVIQRCharObj == NULL) | |
1115 | m_pVIQRCharObj = new VIQRCharset(VIQRTable); | |
1116 | ||
1117 | if (m_pUniUTF8 == NULL) | |
1118 | m_pUniUTF8 = new UnicodeUTF8Charset(UnicodeTable); | |
1119 | m_pUVIQRCharObj = new UTF8VIQRCharset(m_pUniUTF8, m_pVIQRCharObj); | |
1120 | } | |
1121 | return m_pUVIQRCharObj; | |
1122 | ||
1123 | default: | |
1124 | if (IS_SINGLE_BYTE_CHARSET(charsetIdx)) { | |
1125 | int i = charsetIdx - CONV_CHARSET_TCVN3; | |
1126 | if (m_sgCharsets[i] == NULL) | |
1127 | m_sgCharsets[i] = new SingleByteCharset(SingleByteTables[i]); | |
1128 | return m_sgCharsets[i]; | |
1129 | } | |
1130 | else if (IS_DOUBLE_BYTE_CHARSET(charsetIdx)) { | |
1131 | int i = charsetIdx - CONV_CHARSET_VNIWIN; | |
1132 | if (m_dbCharsets[i] == NULL) | |
1133 | m_dbCharsets[i] = new DoubleByteCharset(DoubleByteTables[i]); | |
1134 | return m_dbCharsets[i]; | |
1135 | } | |
1136 | } | |
1137 | return NULL; | |
1138 | } | |
1139 | ||
1140 | ||
1141 | //------------------------------------------------- | |
1142 | DllExport void VnConvSetOptions(VnConvOptions *pOptions) | |
1143 | { | |
1144 | VnCharsetLibObj.m_options = *pOptions; | |
1145 | } | |
1146 | ||
1147 | //------------------------------------------------- | |
1148 | DllExport void VnConvGetOptions(VnConvOptions *pOptions) | |
1149 | { | |
1150 | *pOptions = VnCharsetLibObj.m_options; | |
1151 | } | |
1152 | ||
1153 | //------------------------------------------------- | |
1154 | DllExport void VnConvResetOptions(VnConvOptions *pOptions) | |
1155 | { | |
1156 | pOptions->viqrEsc = 1; | |
1157 | pOptions->viqrMixed = 0; | |
1158 | pOptions->toUpper = 0; | |
1159 | pOptions->toLower = 0; | |
1160 | pOptions->removeTone = 0; | |
1161 | pOptions->smartViqr = 1; | |
1162 | } | |
1163 | ||
1164 | ||
1165 | ///////////////////////////////////////////// | |
1166 | // Class WinCP1258Charset | |
1167 | ///////////////////////////////////////////// | |
1168 | WinCP1258Charset::WinCP1258Charset(UKWORD *compositeChars, UKWORD *precomposedChars) | |
1169 | { | |
1170 | int i,k; | |
1171 | m_toDoubleChar = compositeChars; | |
1172 | memset(m_stdMap, 0, 256*sizeof(UKWORD)); | |
1173 | ||
1174 | // encode composite chars | |
1175 | for (i=0; i<TOTAL_VNCHARS; i++) { | |
1176 | if (compositeChars[i] >> 8) // a 2-byte character | |
1177 | m_stdMap[compositeChars[i] >> 8] = 0xFFFF; //INVALID_STD_CHAR; | |
1178 | else if (m_stdMap[compositeChars[i]] == 0) | |
1179 | m_stdMap[compositeChars[i]] = i+1; | |
1180 | ||
1181 | m_vnChars[i] = (i << 16) + compositeChars[i]; // high word is used for StdChar index | |
1182 | } | |
1183 | ||
1184 | m_totalChars = TOTAL_VNCHARS; | |
1185 | ||
1186 | //add precomposed chars to the table | |
1187 | for (k=0, i=TOTAL_VNCHARS; k<TOTAL_VNCHARS; k++) | |
1188 | if (precomposedChars[k] != compositeChars[k]) { | |
1189 | if (precomposedChars[k] >> 8) // a 2-byte character | |
1190 | m_stdMap[precomposedChars[k] >> 8] = 0xFFFF; //INVALID_STD_CHAR; | |
1191 | else if (m_stdMap[precomposedChars[k]] == 0) | |
1192 | m_stdMap[precomposedChars[k]] = k+1; | |
1193 | ||
1194 | m_vnChars[i] = (k << 16) + precomposedChars[k]; | |
1195 | m_totalChars++; | |
1196 | i++; | |
1197 | } | |
1198 | ||
1199 | qsort(m_vnChars, m_totalChars, sizeof(UKDWORD), wideCharCompare); | |
1200 | } | |
1201 | ||
1202 | ||
1203 | //--------------------------------------------------------------------- | |
1204 | // This fuction is basically the same as that of DoubleByteCharset | |
1205 | // with m_totalChars is used instead of constant TOTAL_VNCHARS | |
1206 | //--------------------------------------------------------------------- | |
1207 | int WinCP1258Charset::nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) | |
1208 | { | |
1209 | unsigned char ch; | |
1210 | ||
1211 | // read first byte | |
1212 | bytesRead = 0; | |
1213 | if (!is.getNext(ch)) | |
1214 | return 0; | |
1215 | bytesRead = 1; | |
1216 | stdChar = m_stdMap[ch]; | |
1217 | if (stdChar == 0) | |
1218 | stdChar = ch; | |
1219 | else if (stdChar == 0xFFFF) | |
1220 | stdChar = INVALID_STD_CHAR; | |
1221 | else { | |
1222 | stdChar += VnStdCharOffset - 1; | |
1223 | UKBYTE hi; | |
1224 | if (is.peekNext(hi) && hi > 0) { | |
1225 | //test if a double-byte character is encountered | |
1226 | UKDWORD key = MAKEWORD(ch,hi); | |
1227 | UKDWORD *pChar = (UKDWORD *)bsearch(&key, m_vnChars, m_totalChars, sizeof(UKDWORD), wideCharCompare); | |
1228 | if (pChar) { | |
1229 | stdChar = VnStdCharOffset + HIWORD(*pChar); | |
1230 | bytesRead = 2; | |
1231 | is.getNext(hi); | |
1232 | } | |
1233 | } | |
1234 | } | |
1235 | return 1; | |
1236 | } | |
1237 | ||
1238 | //--------------------------------------------------------------------- | |
1239 | // This fuction is exactly the same as that of DoubleByteCharset | |
1240 | //--------------------------------------------------------------------- | |
1241 | int WinCP1258Charset::putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) | |
1242 | { | |
1243 | int ret; | |
1244 | if (stdChar >= VnStdCharOffset) { | |
1245 | UKWORD wCh = m_toDoubleChar[stdChar-VnStdCharOffset]; | |
1246 | ||
1247 | if (wCh & 0xFF00) { | |
1248 | outLen = 2; | |
1249 | os.putB((UKBYTE)(wCh & 0x00FF)); | |
1250 | ret = os.putB((UKBYTE)(wCh >> 8)); | |
1251 | } | |
1252 | else { | |
1253 | unsigned char b = (unsigned char)wCh; | |
1254 | if (m_stdMap[b] == 0xFFFF) | |
1255 | b = PadChar; | |
1256 | outLen = 1; | |
1257 | ret = os.putB(b); | |
1258 | } | |
1259 | } | |
1260 | else { | |
1261 | if (stdChar > 255 || m_stdMap[stdChar]) { | |
1262 | outLen = 1; | |
1263 | ret = os.putB((UKBYTE)PadChar); | |
1264 | } | |
1265 | else { | |
1266 | outLen = 1; | |
1267 | ret = os.putB((UKBYTE)stdChar); | |
1268 | } | |
1269 | } | |
1270 | return ret; | |
1271 | } | |
1272 | ||
1273 | #define IS_ODD(x) (x & 1) | |
1274 | #define IS_EVEN(x) (!(x & 1)) | |
1275 | ||
1276 | StdVnChar StdVnToUpper(StdVnChar ch) | |
1277 | { | |
1278 | if (ch >= VnStdCharOffset && | |
1279 | ch<(VnStdCharOffset + TOTAL_ALPHA_VNCHARS) && | |
1280 | IS_ODD(ch)) | |
1281 | ch -= 1; | |
1282 | return ch; | |
1283 | } | |
1284 | ||
1285 | //---------------------------------------- | |
1286 | StdVnChar StdVnToLower(StdVnChar ch) | |
1287 | { | |
1288 | if (ch >= VnStdCharOffset && | |
1289 | ch<(VnStdCharOffset + TOTAL_ALPHA_VNCHARS) && | |
1290 | IS_EVEN(ch)) | |
1291 | ch += 1; | |
1292 | return ch; | |
1293 | } | |
1294 | ||
1295 | //---------------------------------------- | |
1296 | StdVnChar StdVnGetRoot(StdVnChar ch) | |
1297 | { | |
1298 | if (ch >= VnStdCharOffset && ch<VnStdCharOffset+TOTAL_VNCHARS) | |
1299 | ch = VnStdCharOffset + StdVnRootChar[ch-VnStdCharOffset]; | |
1300 | return ch; | |
1301 | } |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | VnConv: Vietnamese Encoding Converter Library | |
3 | UniKey Project: http://unikey.sourceforge.net | |
4 | Copyleft (C) 1998-2002 Pham Kim Long | |
5 | Contact: longp@cslab.felk.cvut.cz | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License | |
9 | as published by the Free Software Foundation; either version 2 | |
10 | of the License, or (at your option) any later version. | |
11 | ||
12 | This program 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 | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | --------------------------------------------------------------------------------*/ | |
21 | ||
22 | #ifndef __CHARSET_CONVERT_H | |
23 | #define __CHARSET_CONVERT_H | |
24 | ||
25 | #if !defined(_WIN32) | |
26 | #include <stdint.h> | |
27 | #endif | |
28 | ||
29 | #if defined(_WIN32) | |
30 | #if defined(UNIKEYHOOK) | |
31 | #define DllInterface __declspec( dllexport ) | |
32 | #else | |
33 | #define DllInterface __declspec( dllimport ) | |
34 | #endif | |
35 | #else | |
36 | #define DllInterface //not used | |
37 | #define DllExport | |
38 | #define DllImport | |
39 | #endif | |
40 | ||
41 | #include "vnconv.h" | |
42 | #include "byteio.h" | |
43 | #include "pattern.h" | |
44 | ||
45 | #define TOTAL_VNCHARS 213 | |
46 | #define TOTAL_ALPHA_VNCHARS 186 | |
47 | ||
48 | #if defined(_WIN32) | |
49 | typedef unsigned __int32 StdVnChar; | |
50 | typedef unsigned __int16 UnicodeChar; | |
51 | typedef unsigned __int16 UKWORD; | |
52 | typedef unsigned __int32 UKDWORD; | |
53 | #else | |
54 | //typedef unsigned int StdVnChar; //the size should be more specific | |
55 | typedef uint32_t StdVnChar; | |
56 | typedef uint16_t UnicodeChar; | |
57 | typedef uint16_t UKWORD; | |
58 | typedef uint32_t UKDWORD; | |
59 | #endif | |
60 | ||
61 | //typedef unsigned short UnicodeChar; | |
62 | //typedef unsigned short UKWORD; | |
63 | ||
64 | //typedef unsigned int UKDWORD; //the size should be more specific | |
65 | ||
66 | #ifndef LOWORD | |
67 | #define LOWORD(l) ((UKWORD)(l)) | |
68 | #endif | |
69 | ||
70 | #ifndef HIWORD | |
71 | #define HIWORD(l) ((UKWORD)(((UKDWORD)(l) >> 16) & 0xFFFF)) | |
72 | #endif | |
73 | ||
74 | #ifndef MAKEWORD | |
75 | #define MAKEWORD(a, b) ((UKWORD)(((UKBYTE)(a)) | ((UKWORD)((UKBYTE)(b))) << 8)) | |
76 | #endif | |
77 | ||
78 | const StdVnChar VnStdCharOffset = 0x10000; | |
79 | const StdVnChar INVALID_STD_CHAR = 0xFFFFFFFF; | |
80 | //const unsigned char PadChar = '?'; //? is used for VIQR charset | |
81 | const unsigned char PadChar = '#'; | |
82 | const unsigned char PadStartQuote = '\"'; | |
83 | const unsigned char PadEndQuote = '\"'; | |
84 | const unsigned char PadEllipsis = '.'; | |
85 | ||
86 | class DllInterface VnCharset { | |
87 | public: | |
88 | virtual void startInput() {}; | |
89 | virtual void startOutput() {}; | |
90 | // virtual UKBYTE *nextInput(UKBYTE *input, int inLen, StdVnChar & stdChar, int & bytesRead) = 0; | |
91 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead) = 0; | |
92 | ||
93 | //------------------------------------------------------------------------ | |
94 | // put a character to the output after converting it | |
95 | // Arguments: | |
96 | // output[in]: output buffer | |
97 | // stdChar[in]: character in standard charset | |
98 | // outLen[out]: length of converted sequence | |
99 | // maxAvail[in]: max length available. | |
100 | // Returns: next position in output | |
101 | //------------------------------------------------------------------------ | |
102 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen) = 0; | |
103 | virtual int elementSize(); | |
104 | virtual ~VnCharset() {} | |
105 | }; | |
106 | ||
107 | //-------------------------------------------------- | |
108 | class SingleByteCharset: public VnCharset { | |
109 | protected: | |
110 | UKWORD m_stdMap[256]; | |
111 | unsigned char * m_vnChars; | |
112 | public: | |
113 | SingleByteCharset(unsigned char * vnChars); | |
114 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
115 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
116 | }; | |
117 | ||
118 | //-------------------------------------------------- | |
119 | class VnInternalCharset: public VnCharset { | |
120 | public: | |
121 | VnInternalCharset() {}; | |
122 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
123 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
124 | virtual int elementSize(); | |
125 | }; | |
126 | ||
127 | //-------------------------------------------------- | |
128 | class UnicodeCharset: public VnCharset { | |
129 | protected: | |
130 | UKDWORD m_vnChars[TOTAL_VNCHARS]; | |
131 | UnicodeChar * m_toUnicode; | |
132 | public: | |
133 | UnicodeCharset(UnicodeChar *vnChars); | |
134 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
135 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
136 | virtual int elementSize(); | |
137 | }; | |
138 | ||
139 | //-------------------------------------------------- | |
140 | class DoubleByteCharset: public VnCharset { | |
141 | protected: | |
142 | UKWORD m_stdMap[256]; | |
143 | UKDWORD m_vnChars[TOTAL_VNCHARS]; | |
144 | UKWORD * m_toDoubleChar; | |
145 | public: | |
146 | DoubleByteCharset(UKWORD *vnChars); | |
147 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
148 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
149 | }; | |
150 | ||
151 | //-------------------------------------------------- | |
152 | class UnicodeUTF8Charset: public UnicodeCharset | |
153 | { | |
154 | public: | |
155 | UnicodeUTF8Charset(UnicodeChar *vnChars) : UnicodeCharset(vnChars) {} | |
156 | ||
157 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
158 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
159 | }; | |
160 | ||
161 | //-------------------------------------------------- | |
162 | class UnicodeRefCharset: public UnicodeCharset | |
163 | { | |
164 | public: | |
165 | UnicodeRefCharset(UnicodeChar *vnChars) : UnicodeCharset(vnChars) {} | |
166 | ||
167 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
168 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
169 | }; | |
170 | ||
171 | //-------------------------------------------------- | |
172 | class UnicodeHexCharset: public UnicodeRefCharset | |
173 | { | |
174 | public: | |
175 | UnicodeHexCharset(UnicodeChar *vnChars) : UnicodeRefCharset(vnChars) {} | |
176 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
177 | }; | |
178 | ||
179 | //-------------------------------------------------- | |
180 | class UnicodeCStringCharset: public UnicodeCharset | |
181 | { | |
182 | protected: | |
183 | int m_prevIsHex; | |
184 | public: | |
185 | UnicodeCStringCharset(UnicodeChar *vnChars) : UnicodeCharset(vnChars) {} | |
186 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
187 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
188 | virtual void startInput(); | |
189 | }; | |
190 | ||
191 | //-------------------------------------------------- | |
192 | class WinCP1258Charset: public VnCharset { | |
193 | protected: | |
194 | UKWORD m_stdMap[256]; | |
195 | UKDWORD m_vnChars[TOTAL_VNCHARS*2]; | |
196 | UKWORD *m_toDoubleChar; | |
197 | int m_totalChars; | |
198 | ||
199 | public: | |
200 | WinCP1258Charset(UKWORD *compositeChars, UKWORD *precomposedChars); | |
201 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
202 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
203 | }; | |
204 | ||
205 | //-------------------------------------------------- | |
206 | struct UniCompCharInfo { | |
207 | UKDWORD compChar; | |
208 | int stdIndex; | |
209 | }; | |
210 | ||
211 | class UnicodeCompCharset: public VnCharset { | |
212 | protected: | |
213 | UniCompCharInfo m_info[TOTAL_VNCHARS*2]; | |
214 | UKDWORD *m_uniCompChars; | |
215 | int m_totalChars; | |
216 | public: | |
217 | UnicodeCompCharset(UnicodeChar *uniChars, UKDWORD *uniCompChars); | |
218 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
219 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
220 | virtual int elementSize(); | |
221 | }; | |
222 | ||
223 | //-------------------------------------------------- | |
224 | class VIQRCharset: public VnCharset { | |
225 | protected: | |
226 | UKDWORD *m_vnChars; | |
227 | UKWORD m_stdMap[256]; | |
228 | int m_atWordBeginning; | |
229 | int m_escapeBowl; | |
230 | int m_escapeRoof; | |
231 | int m_escapeHook; | |
232 | int m_escapeTone; | |
233 | int m_gotTone; | |
234 | int m_escAll; | |
235 | int m_noOutEsc; | |
236 | public: | |
237 | int m_suspicious; | |
238 | VIQRCharset(UKDWORD *vnChars); | |
239 | virtual void startInput(); | |
240 | virtual void startOutput(); | |
241 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
242 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
243 | }; | |
244 | ||
245 | //-------------------------------------------------- | |
246 | class UTF8VIQRCharset: public VnCharset { | |
247 | ||
248 | protected: | |
249 | VIQRCharset *m_pViqr; | |
250 | UnicodeUTF8Charset *m_pUtf; | |
251 | ||
252 | public: | |
253 | UTF8VIQRCharset(UnicodeUTF8Charset *pUtf, VIQRCharset *pViqr); | |
254 | virtual void startInput(); | |
255 | virtual void startOutput(); | |
256 | virtual int nextInput(ByteInStream & is, StdVnChar & stdChar, int & bytesRead); | |
257 | virtual int putChar(ByteOutStream & os, StdVnChar stdChar, int & outLen); | |
258 | }; | |
259 | ||
260 | ||
261 | //-------------------------------------------------- | |
262 | class DllInterface CVnCharsetLib { | |
263 | protected: | |
264 | SingleByteCharset * m_sgCharsets[CONV_TOTAL_SINGLE_CHARSETS]; | |
265 | DoubleByteCharset * m_dbCharsets[CONV_TOTAL_DOUBLE_CHARSETS]; | |
266 | UnicodeCharset * m_pUniCharset; | |
267 | UnicodeCompCharset * m_pUniCompCharset; | |
268 | UnicodeUTF8Charset * m_pUniUTF8; | |
269 | UnicodeRefCharset * m_pUniRef; | |
270 | UnicodeHexCharset * m_pUniHex; | |
271 | VIQRCharset * m_pVIQRCharObj; | |
272 | UTF8VIQRCharset * m_pUVIQRCharObj; | |
273 | WinCP1258Charset * m_pWinCP1258; | |
274 | UnicodeCStringCharset *m_pUniCString; | |
275 | VnInternalCharset *m_pVnIntCharset; | |
276 | ||
277 | public: | |
278 | PatternList m_VIQREscPatterns, m_VIQROutEscPatterns; | |
279 | VnConvOptions m_options; | |
280 | CVnCharsetLib(); | |
281 | ~CVnCharsetLib(); | |
282 | VnCharset * getVnCharset(int charsetIdx); | |
283 | }; | |
284 | ||
285 | extern unsigned char SingleByteTables[][TOTAL_VNCHARS]; | |
286 | extern UKWORD DoubleByteTables[][TOTAL_VNCHARS]; | |
287 | extern UnicodeChar UnicodeTable[TOTAL_VNCHARS]; | |
288 | extern UKDWORD VIQRTable[TOTAL_VNCHARS]; | |
289 | extern UKDWORD UnicodeComposite[TOTAL_VNCHARS]; | |
290 | extern UKWORD WinCP1258[TOTAL_VNCHARS]; | |
291 | extern UKWORD WinCP1258Pre[TOTAL_VNCHARS]; | |
292 | ||
293 | extern DllInterface CVnCharsetLib VnCharsetLibObj; | |
294 | extern VnConvOptions VnConvGlobalOptions; | |
295 | extern int StdVnNoTone[TOTAL_VNCHARS]; | |
296 | extern int StdVnRootChar[TOTAL_VNCHARS]; | |
297 | ||
298 | DllInterface int genConvert(VnCharset & incs, VnCharset & outcs, ByteInStream & input, ByteOutStream & output); | |
299 | ||
300 | StdVnChar StdVnToUpper(StdVnChar ch); | |
301 | StdVnChar StdVnToLower(StdVnChar ch); | |
302 | StdVnChar StdVnGetRoot(StdVnChar ch); | |
303 | ||
304 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | VnConv: Vietnamese Encoding Converter Library | |
3 | UniKey Project: http://unikey.sourceforge.net | |
4 | Copyleft (C) 1998-2002 Pham Kim Long | |
5 | Contact: longp@cslab.felk.cvut.cz | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License | |
9 | as published by the Free Software Foundation; either version 2 | |
10 | of the License, or (at your option) any later version. | |
11 | ||
12 | This program 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 | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | --------------------------------------------------------------------------------*/ | |
21 | ||
22 | #include "charset.h" | |
23 | #include <stdio.h> | |
24 | #include <stdlib.h> | |
25 | #include <string.h> | |
26 | ||
27 | #if defined(_WIN32) | |
28 | #include <io.h> | |
29 | #include <fcntl.h> | |
30 | #endif | |
31 | ||
32 | #include "vnconv.h" | |
33 | ||
34 | int vnFileStreamConvert(int inCharset, int outCharset, FILE * inf, FILE *outf); | |
35 | ||
36 | DllExport int genConvert(VnCharset & incs, VnCharset & outcs, ByteInStream & input, ByteOutStream & output) | |
37 | { | |
38 | StdVnChar stdChar; | |
39 | int bytesRead, bytesWritten; | |
40 | ||
41 | incs.startInput(); | |
42 | outcs.startOutput(); | |
43 | ||
44 | int ret = 1; | |
45 | while (!input.eos()) { | |
46 | stdChar = 0; | |
47 | if (incs.nextInput(input, stdChar, bytesRead)) { | |
48 | if (stdChar != INVALID_STD_CHAR) { | |
49 | if (VnCharsetLibObj.m_options.toLower) | |
50 | stdChar = StdVnToLower(stdChar); | |
51 | else if (VnCharsetLibObj.m_options.toUpper) | |
52 | stdChar = StdVnToUpper(stdChar); | |
53 | if (VnCharsetLibObj.m_options.removeTone) | |
54 | stdChar = StdVnGetRoot(stdChar); | |
55 | ret = outcs.putChar(output, stdChar, bytesWritten); | |
56 | } | |
57 | } | |
58 | else break; | |
59 | } | |
60 | return (ret? 0 : VNCONV_OUT_OF_MEMORY); | |
61 | } | |
62 | ||
63 | //---------------------------------------------- | |
64 | // Arguments: | |
65 | // inCharset: charset of input | |
66 | // outCharset: charset of output | |
67 | // input: input data | |
68 | // output: output data | |
69 | // inLen: [in] size of input. if inLen = -1, input data is null-terminated. | |
70 | // [out] if input inLen != -1, output iLen is the numbers of byte left in input. | |
71 | // maxOutLen: [in] size of output. | |
72 | // [out] number of bytes output, if enough memory | |
73 | // number of bytes needed for output, if not enough memory | |
74 | // Returns: 0 if successful | |
75 | // error code: if failed | |
76 | //---------------------------------------------- | |
77 | //int VnConvert(int inCharset, int outCharset, UKBYTE *input, UKBYTE *output, int & inLen, int & maxOutLen) | |
78 | ||
79 | DllExport int VnConvert(int inCharset, int outCharset, UKBYTE *input, UKBYTE *output, | |
80 | int * pInLen, int * pMaxOutLen) | |
81 | { | |
82 | int inLen, maxOutLen; | |
83 | int ret = -1; | |
84 | ||
85 | inLen = *pInLen; | |
86 | maxOutLen = *pMaxOutLen; | |
87 | ||
88 | if (inLen != -1 && inLen < 0) // invalid inLen | |
89 | return ret; | |
90 | ||
91 | VnCharset *pInCharset = VnCharsetLibObj.getVnCharset(inCharset); | |
92 | VnCharset *pOutCharset = VnCharsetLibObj.getVnCharset(outCharset); | |
93 | ||
94 | if (!pInCharset || !pOutCharset) | |
95 | return VNCONV_INVALID_CHARSET; | |
96 | ||
97 | StringBIStream is(input, inLen, pInCharset->elementSize()); | |
98 | StringBOStream os(output, maxOutLen); | |
99 | ||
100 | ret = genConvert(*pInCharset, *pOutCharset, is, os); | |
101 | *pMaxOutLen = os.getOutBytes(); | |
102 | *pInLen = is.left(); | |
103 | return ret; | |
104 | } | |
105 | ||
106 | //--------------------------------------- | |
107 | // Arguments: | |
108 | // inFile: input file name. NULL if STDIN is used | |
109 | // outFile: output file name, NULL if STDOUT is used | |
110 | // Returns: | |
111 | // 0: successful | |
112 | // errCode: if failed | |
113 | //--------------------------------------- | |
114 | DllExport int VnFileConvert(int inCharset, int outCharset, const char *inFile, const char *outFile) | |
115 | { | |
116 | FILE *inf = NULL; | |
117 | FILE *outf = NULL; | |
118 | int ret = 0; | |
119 | char tmpName[32]; | |
120 | ||
121 | if (inFile == NULL) { | |
122 | inf = stdin; | |
123 | #if defined(_WIN32) | |
124 | _setmode( _fileno(stdin), _O_BINARY); | |
125 | #endif | |
126 | } | |
127 | else { | |
128 | inf = fopen(inFile, "rb"); | |
129 | if (inf == NULL) { | |
130 | ret = VNCONV_ERR_INPUT_FILE; | |
131 | goto end; | |
132 | } | |
133 | } | |
134 | ||
135 | if (outFile == NULL) | |
136 | outf = stdout; | |
137 | else { | |
138 | // setup temporary output file (because real output file may be the same as input file | |
139 | char outDir[256]; | |
140 | strcpy(outDir, outFile); | |
141 | ||
142 | #if defined(_WIN32) | |
143 | char *p = strrchr(outDir, '\\'); | |
144 | #else | |
145 | char *p = strrchr(outDir, '/'); | |
146 | #endif | |
147 | ||
148 | if (p == NULL) | |
149 | outDir[0] = 0; | |
150 | else | |
151 | *p = 0; | |
152 | ||
153 | strcpy(tmpName, outDir); | |
154 | strcat(tmpName, "XXXXXX"); | |
155 | ||
156 | if (mkstemp(tmpName) == -1) { | |
157 | fclose(inf); | |
158 | ret = VNCONV_ERR_OUTPUT_FILE; | |
159 | goto end; | |
160 | } | |
161 | outf = fopen(tmpName, "wb"); | |
162 | ||
163 | if (outf == NULL) { | |
164 | fclose(inf); | |
165 | ret = VNCONV_ERR_OUTPUT_FILE; | |
166 | goto end; | |
167 | } | |
168 | } | |
169 | ||
170 | ||
171 | ret = vnFileStreamConvert(inCharset, outCharset, inf, outf); | |
172 | if (inf != stdin) | |
173 | fclose(inf); | |
174 | if (outf != stdout) { | |
175 | fclose(outf); | |
176 | ||
177 | // delete output file if exisits | |
178 | if (ret == 0) { | |
179 | remove(outFile); | |
180 | #if !defined(_WIN32) | |
181 | char cmd[256]; | |
182 | sprintf(cmd, "mv %s %s", tmpName, outFile); | |
183 | cmd[0] = system(cmd); | |
184 | #else | |
185 | if (rename(tmpName, outFile) != 0) { | |
186 | remove(tmpName); | |
187 | ret = VNCONV_ERR_OUTPUT_FILE; | |
188 | goto end; | |
189 | } | |
190 | #endif | |
191 | } | |
192 | else | |
193 | remove(tmpName); | |
194 | } | |
195 | ||
196 | end: | |
197 | #if defined(_WIN32) | |
198 | if (inf == stdin) { | |
199 | _setmode( _fileno(stdin), _O_BINARY); | |
200 | } | |
201 | #endif | |
202 | return ret; | |
203 | } | |
204 | ||
205 | //------------------------------------------------ | |
206 | // Returns: | |
207 | // 0: successful | |
208 | // errCode: if failed | |
209 | //--------------------------------------- | |
210 | int vnFileStreamConvert(int inCharset, int outCharset, FILE * inf, FILE *outf) | |
211 | { | |
212 | VnCharset *pInCharset = VnCharsetLibObj.getVnCharset(inCharset); | |
213 | VnCharset *pOutCharset = VnCharsetLibObj.getVnCharset(outCharset); | |
214 | ||
215 | if (!pInCharset || !pOutCharset) | |
216 | return VNCONV_INVALID_CHARSET; | |
217 | ||
218 | if (outCharset == CONV_CHARSET_UNICODE) { | |
219 | UKWORD sign = 0xFEFF; | |
220 | fwrite(&sign, sizeof(UKWORD), 1, outf); | |
221 | } | |
222 | ||
223 | FileBIStream is; | |
224 | FileBOStream os; | |
225 | ||
226 | is.attach(inf); | |
227 | os.attach(outf); | |
228 | ||
229 | return genConvert(*pInCharset, *pOutCharset, is, os); | |
230 | } | |
231 | ||
232 | const char *ErrTable[VNCONV_LAST_ERROR] = | |
233 | {"No error", | |
234 | "Unknown error", | |
235 | "Invalid charset", | |
236 | "Error opening input file", | |
237 | "Error opening output file", | |
238 | "Error writing to output stream", | |
239 | "Not enough memory", | |
240 | }; | |
241 | ||
242 | DllExport const char * VnConvErrMsg(int errCode) | |
243 | { | |
244 | if (errCode < 0 || errCode >= VNCONV_LAST_ERROR) | |
245 | errCode = VNCONV_UNKNOWN_ERROR; | |
246 | return ErrTable[errCode]; | |
247 | } | |
248 |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | VnConv: Vietnamese Encoding Converter Library | |
3 | UniKey Project: http://unikey.sourceforge.net | |
4 | Copyleft (C) 1998-2002 Pham Kim Long | |
5 | Contact: longp@cslab.felk.cvut.cz | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License | |
9 | as published by the Free Software Foundation; either version 2 | |
10 | of the License, or (at your option) any later version. | |
11 | ||
12 | This program 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 | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | --------------------------------------------------------------------------------*/ | |
21 | ||
22 | #include "charset.h" | |
23 | ||
24 | /* | |
25 | Instructions on how to add more charset supports | |
26 | ||
27 | Each charset enumerates all its characters according to a fixed order. | |
28 | To understand this order, copy the TCVN3 charset bellow to some application | |
29 | and view it with some TCVN3 font. | |
30 | ||
31 | Steps to add an 1-byte charset: | |
32 | ||
33 | - Determine the Id for your charset. See "vnconv.h". The Id | |
34 | for your charset is equal to the id of the last 1-byte charset PLUS 1. | |
35 | Then define a constant for that Id (e.g. #define MY_NEW_CHARSET 25) | |
36 | - In "vnconv.h": Increase the variable CONV_TOTAL_SINGLE_CHARSETS by 1. | |
37 | - Add an entry for your charset to the end of CharsetIdMap (in this file) | |
38 | - Add your charset to the end of SingleBytesTable | |
39 | - Note that and the end of each charset (after character z) there's a section | |
40 | for the symbols in western charsets (see TCVN3). Just copy | |
41 | this section for your charset, and set zero for each code point | |
42 | that is occupied by your charset (for representing Vietnamese characters). | |
43 | ||
44 | Steps to add a 2-byte charset: | |
45 | - Determine the Id for your charset. See "vnconv.h". The Id | |
46 | for your charset is equal to the id of the last 2-byte charset PLUS 1. | |
47 | Then define a constant for that Id (e.g. #define MY_NEW_CHARSET 44) | |
48 | - In "vnconv.h": Increase the variable CONV_TOTAL_DOUBLE_CHARSETS by 1. | |
49 | - Add an entry for your charset to the end of CharsetIdMap (in this file) | |
50 | - Add your charset to the end of DoubleByteTables | |
51 | - Note that and the end of each charset (after character z) there's a section | |
52 | for the symbols in western charsets. Just copy this section from | |
53 | VNI-WIN charset to your charset | |
54 | - Double-byte characters are represented as a word in which the | |
55 | low byte is base character, high byte is tone mark (if present). | |
56 | */ | |
57 | extern CharsetNameId CharsetIdMap[]; | |
58 | extern const int CharsetCount; | |
59 | ||
60 | CharsetNameId CharsetIdMap[] = { | |
61 | {"BKHCM1", CONV_CHARSET_BKHCM1}, | |
62 | {"BKHCM2", CONV_CHARSET_BKHCM2}, | |
63 | {"ISC", CONV_CHARSET_ISC}, | |
64 | {"NCR-DEC", CONV_CHARSET_UNIREF}, | |
65 | {"NCR-HEX", CONV_CHARSET_UNIREF_HEX}, | |
66 | {"TCVN3", CONV_CHARSET_TCVN3}, | |
67 | {"UNI-COMP", CONV_CHARSET_UNIDECOMPOSED}, | |
68 | {"UNICODE", CONV_CHARSET_UNICODE}, | |
69 | {"UTF-8", CONV_CHARSET_UNIUTF8}, | |
70 | {"UTF8", CONV_CHARSET_UNIUTF8}, | |
71 | {"UVIQR", CONV_CHARSET_UTF8VIQR}, | |
72 | {"VIETWARE-F", CONV_CHARSET_VIETWAREF}, | |
73 | {"VIETWARE-X", CONV_CHARSET_VIETWAREX}, | |
74 | {"VIQR", CONV_CHARSET_VIQR}, | |
75 | {"VISCII", CONV_CHARSET_VISCII}, | |
76 | {"VNI-MAC", CONV_CHARSET_VNIMAC}, | |
77 | {"VNI-WIN", CONV_CHARSET_VNIWIN}, | |
78 | {"VPS", CONV_CHARSET_VPS}, | |
79 | {"WINCP-1258", CONV_CHARSET_WINCP1258} | |
80 | }; | |
81 | ||
82 | const int CharsetCount = sizeof(CharsetIdMap)/sizeof(CharsetNameId); | |
83 | ||
84 | /* Western symbols that need to be mapped | |
85 | 0x80, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, | |
86 | 0x89, 0x8A, 0x8B, 0x8C, 0x8E, 0x91, 0x92, 0x93, | |
87 | 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, | |
88 | 0x9C, 0x9E, 0x9F, | |
89 | ||
90 | If a single byte charset occupies a certain symbol, | |
91 | its code point in the charset must be set to zero. | |
92 | See TCVN3 & VPS below for examples | |
93 | */ | |
94 | ||
95 | unsigned char SingleByteTables[][TOTAL_VNCHARS] = | |
96 | ||
97 | // TCVN3 | |
98 | {{'A','a','¸','¸','µ','µ','¶','¶','·','·','¹','¹', // 0: a | |
99 | '¢','©','Ê','Ê','Ç','Ç','È','È','É','É','Ë','Ë', // 1: a^ | |
100 | '¡','¨','¾','¾','»','»','¼','¼','½','½','Æ','Æ', // 2: a( | |
101 | 'B','b','C','c','D','d', | |
102 | '§','®', | |
103 | 'E','e','Ð','Ð','Ì','Ì','Î','Î','Ï','Ï','Ñ','Ñ', // 3: e | |
104 | '£','ª','Õ','Õ','Ò','Ò','Ó','Ó','Ô','Ô','Ö','Ö', // 4: e^ | |
105 | 'F','f','G','g','H','h', | |
106 | 'I','i','Ý','Ý','×','×','Ø','Ø','Ü','Ü','Þ','Þ', // 5: i | |
107 | 'J','j','K','k','L','l','M','m','N','n', | |
108 | 'O','o','ã','ã','ß','ß','á','á','â','â','ä','ä', // 6: o | |
109 | '¤','«','è','è','å','å','æ','æ','ç','ç','é','é', // 7: o^ | |
110 | '¥','¬','í','í','ê','ê','ë','ë','ì','ì','î','î', // 8: o+ | |
111 | 'P','p','Q','q','R','r','S','s','T','t', | |
112 | 'U','u','ó','ó','ï','ï','ñ','ñ','ò','ò','ô','ô', // 9: u | |
113 | '¦','','ø','ø','õ','õ','ö','ö','÷','÷','ù','ù', //10: u+ | |
114 | 'V','v','W','w','X','x', | |
115 | 'Y','y','ý','ý','ú','ú','û','û','ü','ü','þ','þ', //11: y | |
116 | 'Z','z', | |
117 | 0x80, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, | |
118 | 0x89, 0x8A, 0x8B, 0x8C, 0x8E, 0x91, 0x92, 0x93, | |
119 | 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, | |
120 | 0x9C, 0x9E, 0x9F}, | |
121 | //VPS | |
122 | { 'A','a','¡','·','Ä','‡','Å','‰','Ç','„','Â','Â', | |
123 | 'Â','â','ƒ','Ã','„','À','…','Ä','Å','Å','Æ','Æ', | |
124 | '','æ','','¡','','¢','','£','ð','¤','¥','¥', | |
125 | 'B','b','C','c','D','d', | |
126 | 'ñ','Ç', | |
127 | 'E','e','É','é','×','è','Þ','È','þ','ë','Ë','Ë', | |
128 | ' ','Í','ê','â','ì','ä','î','ã','ï','Õ','å','å', | |
129 | 'F','f','G','g','H','h', | |
130 | 'I','i','´','í','µ','ì','·','Ì','¸','ï','Î','Î', | |
131 | 'J','j','K','k','L','l','M','m','N','n', | |
132 | 'O','o','¹','ó','¼','ò','½','Õ','¾','õ','†','†', | |
133 | 'Ô','ô','–','Ó','—','Ò','˜','°','™','‡','¶','¶', | |
134 | '÷','Ö','','§','','©','','ª','¦','«','®','®', | |
135 | 'P','p','Q','q','R','r','S','s','T','t', | |
136 | 'U','u','Ú','ú','¨','ù','Ñ','û','¬','Û','ø','ø', | |
137 | 'Ð','Ü','','Ù','¯','Ø','±','º','»','»','¿','¿', | |
138 | 'V','v','W','w','X','x', | |
139 | 'Y','y','Ý','š','²','ÿ','ý','›','³','Ï','œ','œ', | |
140 | 'Z','z', | |
141 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
142 | 0x00, 0x00, 0x00, 0x00, 0x8E, 0x91, 0x92, 0x00, | |
143 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
144 | 0x00, 0x9E, 0x00}, | |
145 | //VISCII | |
146 | { 'A','a','Á','á','À','à','Ä','ä','Ã','ã','€','Õ', | |
147 | 'Â','â','„','¤','…','¥','†','¦','ç','ç','‡','§', | |
148 | '≈','Â','Å','°','Ç','¢','∆','∆','«','«','É','£', | |
149 | 'B','b','C','c','D','d', | |
150 | 'Ð','ð', | |
151 | 'E','e','É','é','È','è','Ë','ë','ˆ','¨','‰','©', | |
152 | 'Ê','ê','','ª','','«','','¬','','','','®', | |
153 | 'F','f','G','g','H','h', | |
154 | 'I','i','Í','í','Ì','ì','›','ï','Î','î','˜','¸', | |
155 | 'J','j','K','k','L','l','M','m','N','n', | |
156 | 'O','o','Ó','ó','Ò','ò','™','ö','õ','õ','š','÷', | |
157 | '‘','Ù','è','Ø','ê','∞','ë','±','í','≤','ì','µ', | |
158 | '´','½','•','¾','–','¶','—','·','³','Þ','”','þ', | |
159 | 'P','p','Q','q','R','r','S','s','T','t', | |
160 | 'U','u','Ú','ú','Ù','ù','','ü','','û','','ø', | |
161 | '¿','ß','º','Ñ','»','×','¼','Ø','ÿ','æ','¹','ñ', | |
162 | 'V','v','W','w','X','x', | |
163 | 'Y','y','Ý','ý','Ÿ','Ï','Ö','Ö','Û','Û','Ü','Ü', | |
164 | 'Z','z', | |
165 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
166 | 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, | |
167 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
168 | 0x00, 0x9E, 0x00}, | |
169 | // BKHCM1 | |
170 | {'A','a','','¾','','¿','','À','','Á','','Â', | |
171 | 'Ÿ','Ý','~','Þ','¡','ß','¢','à','£','á','¤','â', | |
172 | '','×','','Ø','','Ù','','Ú','','Û','','Ü', | |
173 | 'B','b','C','c','D','d', | |
174 | '}','½', | |
175 | 'E','e','…','Ã','†','Ä','‡','Å','ˆ','Æ','‰','Ç', | |
176 | '¥','ã','¦','ä','§','å','¨','æ','©','ç','ª','è', | |
177 | 'F','f','G','g','H','h', | |
178 | 'I','i','ä','»','ã','…','å',' ','ç','À','é','Ã', | |
179 | 'J','j','K','k','L','l','M','m','N','n', | |
180 | 'O','o','è','Õ','ê','Œ','ë','œ','í','–','ì','—', | |
181 | '«','é','¬','ê','','ë','®','ì','¯','í','°','î', | |
182 | '±','ï','²','ð','³','ñ','´','ò','µ','ó','¶','ô', | |
183 | 'P','p','Q','q','R','r','S','s','T','t', | |
184 | 'U','u','”','Ò','•','Ó','–','Ô','—','Õ','˜','Ö', | |
185 | '·','õ','¸','ö','¹','÷','º','ø','»','ù','¼','ú', | |
186 | 'V','v','W','w','X','x', | |
187 | 'Y','y','{','û','^','ü','`','ý','|','þ','Ž','ÿ', | |
188 | 'Z','z', | |
189 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
190 | 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, | |
191 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
192 | 0x00, 0x9E, 0x00}, | |
193 | //Vietware-F | |
194 | { 'A','a','À','À','ª','ª','¶','¶','º','º','Á','Á', | |
195 | '—','¡','Ê','Ê','Ç','Ç','È','È','É','É','Ë','Ë', | |
196 | '–','Ÿ','Å','Å','Â','Â','Ã','Ã','Ä','Ä','Æ','Æ', | |
197 | 'B','b','C','c','D','d', | |
198 | '˜','¢', | |
199 | 'E','e','Ï','Ï','Ì','Ì','Í','Í','Î','Î','Ñ','Ñ', | |
200 | '™','£','Õ','Õ','Ò','Ò','Ó','Ó','Ô','Ô','Ö','Ö', | |
201 | 'F','f','G','g','H','h', | |
202 | 'I','i','Û','Û','Ø','Ø','Ù','Ù','Ú','Ú','Ü','Ü', | |
203 | 'J','j','K','k','L','l','M','m','N','n', | |
204 | 'O','o','â','â','ß','ß','à','à','á','á','ã','ã', | |
205 | 'š','¤','ç','ç','ä','ä','å','å','æ','æ','è','è', | |
206 | '›','¥','ì','ì','é','é','ê','ê','ë','ë','í','í', | |
207 | 'P','p','Q','q','R','r','S','s','T','t', | |
208 | 'U','u','ò','ò','î','î','ï','ï','ñ','ñ','ó','ó', | |
209 | 'œ','§','÷','÷','ô','ô','õ','õ','ö','ö','ø','ø', | |
210 | 'V','v','W','w','X','x', | |
211 | 'Y','y','ü','ü','ù','ù','ú','ú','û','û','ÿ','ÿ', | |
212 | 'Z','z', | |
213 | 0x80, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, | |
214 | 0x89, 0x8A, 0x8B, 0x8C, 0x8E, 0x91, 0x92, 0x93, | |
215 | 0x94, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
216 | 0x00, 0x9E, 0x00}, | |
217 | // ISC | |
218 | {'A','a','É','∏','Ä','µ','Å','∂','Ç','∑','Ñ','π', | |
219 | '¢','©','Ä',' ','Á','Ç','Â','È','Ã','É','†','Ë', | |
220 | '¡','¨','À','¾','¯','»','º','¼','¿','½','…','Æ', | |
221 | 'B','b','C','c','D','d', | |
222 | '§','®', | |
223 | 'E','e','Ð','Š','‡','Ì','ˆ','Î','‰','Ï','Ñ','‹', | |
224 | '£','ª','Ú','Õ','Å','Ò','Í','Ó','Ù','Ô','Œ','Ö', | |
225 | 'F','f','G','g','H','h', | |
226 | 'I','i','','Ý','','×','','Ø','','Ü','','Þ', | |
227 | 'J','j','K','k','L','l','M','m','N','n', | |
228 | 'O','o','•','ã','’','ß','“','á','”','â','–','ä', | |
229 | '¤','«','ÿ','è','Û','å','à','æ','ð','ç','—','é', | |
230 | '¥','¬','›','í','˜','ê','™','ë','š','ì','œ','î', | |
231 | 'P','p','Q','q','R','r','S','s','T','t', | |
232 | 'U','u','@','Û','ù','Ô','û','Ò','ü','Ú','|','Ù', | |
233 | '¦','','`','ø',0x5C,'õ','^','ö','~','÷','#','ù', | |
234 | 'V','v','W','w','X','x', | |
235 | 'Y','y','³','ý','°','ú','±','û','²','ü','´','þ', | |
236 | 'Z','z', | |
237 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
238 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x12, 0x13, | |
239 | 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
240 | 0x00, 0x00, 0x00} | |
241 | }; | |
242 | ||
243 | UKWORD DoubleByteTables[][TOTAL_VNCHARS] = { | |
244 | //VNI-WIN | |
245 | { 0x0041, 0x0061, 0xd941, 0xf961, 0xd841, 0xf861, 0xdb41, 0xfb61, 0xd541, 0xf561, 0xcf41, 0xef61, //a | |
246 | 0xc241, 0xe261, 0xc141, 0xe161, 0xc041, 0xe061, 0xc541, 0xe561, 0xc341, 0xe361, 0xc441, 0xe461, //a^ | |
247 | 0xca41, 0xea61, 0xc941, 0xe961, 0xc841, 0xe861, 0xda41, 0xfa61, 0xdc41, 0xfc61, 0xcb41, 0xeb61, //a( | |
248 | 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, //B b C c D d | |
249 | 0x00d1, 0x00f1, //DD, dd | |
250 | 0x0045, 0x0065, 0xd945, 0xf965, 0xd845, 0xf865, 0xdb45, 0xfb65, 0xd545, 0xf565, 0xcf45, 0xef65, //e | |
251 | 0xc245, 0xe265, 0xc145, 0xe165, 0xc045, 0xe065, 0xc545, 0xe565, 0xc345, 0xe365, 0xc445, 0xe465, //e^ | |
252 | 0x0046, 0x0066, 0x0047, 0x0067, 0x0048, 0x0068, // F f G g H h | |
253 | 0x0049, 0x0069, 0x00cd, 0x00ed, 0x00cc, 0x00ec, 0x00c6, 0x00e6, 0x00d3, 0x00f3, 0x00d2, 0x00f2, //i | |
254 | 0x004a, 0x006a, 0x004b, 0x006b, 0x004c, 0x006c, 0x004d, 0x006d, 0x004e, 0x006e, // J j K k L l M m N n | |
255 | 0x004f, 0x006f, 0xd94f, 0xf96f, 0xd84f, 0xf86f, 0xdb4f, 0xfb6f, 0xd54f, 0xf56f, 0xcf4f, 0xef6f, //o | |
256 | 0xc24f, 0xe26f, 0xc14f, 0xe16f, 0xc04f, 0xe06f, 0xc54f, 0xe56f, 0xc34f, 0xe36f, 0xc44f, 0xe46f, //o^ | |
257 | 0x00d4, 0x00f4, 0xd9d4, 0xf9f4, 0xd8d4, 0xf8f4, 0xdbd4, 0xfbf4, 0xd5d4, 0xf5f4, 0xcfd4, 0xeff4, //o+ | |
258 | 0x0050, 0x0070, 0x0051, 0x0071, 0x0052, 0x0072, 0x0053, 0x0073, 0x0054, 0x0074, //P p Q q R r S s T t | |
259 | 0x0055, 0x0075, 0xd955, 0xf975, 0xd855, 0xf875, 0xdb55, 0xfb75, 0xd555, 0xf575, 0xcf55, 0xef75, //u | |
260 | 0x00d6, 0x00f6, 0xd9d6, 0xf9f6, 0xd8d6, 0xf8f6, 0xdbd6, 0xfbf6, 0xd5d6, 0xf5f6, 0xcfd6, 0xeff6, //u+ | |
261 | 0x0056, 0x0076, 0x0057, 0x0077, 0x0058, 0x0078, // V v W w X x | |
262 | 0x0059, 0x0079, 0xd959, 0xf979, 0xd859, 0xf879, 0xdb59, 0xfb79, 0xd559, 0xf579, 0x00ce, 0x00ee, //y | |
263 | 0x005a, 0x007a, // Z z | |
264 | 0x0080, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, | |
265 | 0x0089, 0x008A, 0x008B, 0x008C, 0x008E, 0x0091, 0x0092, 0x0093, | |
266 | 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, | |
267 | 0x009C, 0x009E, 0x009F}, | |
268 | //BKHCM2 | |
269 | { 0x0041, 0x0061, 0xC141, 0xe161, 0xC241, 0xe261, 0xC341, 0xe361, 0xC441, 0xe461, 0xC541, 0xe561, //a | |
270 | 0x00CA, 0x00EA, 0xCBCA, 0xEBEA, 0xCCCA, 0xECEA, 0xCDCA, 0xEDEA, 0xCECA, 0xEEEA, 0xC5CA, 0xE5EA, //a^ | |
271 | 0x00D9, 0x00F9, 0xC6D9, 0xE6F9, 0xC7D9, 0xE7F9, 0xC8D9, 0xE8F9, 0xC9D9, 0xE9F9, 0xC5D9, 0xE5F9, | |
272 | 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, //B b C c D d | |
273 | 0x00C0, 0x00E0, | |
274 | 0x0045, 0x0065, 0xC145, 0xE165, 0xC245, 0xE265, 0xC345, 0xE365, 0xC445, 0xE465, 0xC545, 0xE565, //e | |
275 | 0x00CF, 0x00EF, 0xCBCF, 0xEBEF, 0xCCCF, 0xECEF, 0xCDCF, 0xEDEF, 0xCECF, 0xEEEF, 0xE5CF, 0xE5EF, //e^ | |
276 | 0x0046, 0x0066, 0x0047, 0x0067, 0x0048, 0x0068, // F f G g H h | |
277 | 0x0049, 0x0069, 0x00D1, 0x00F1, 0x00D2, 0x00F2, 0x00D3, 0x00F3, 0x00D4, 0x00F4, 0x00D5, 0x00F5, //i | |
278 | 0x004a, 0x006a, 0x004b, 0x006b, 0x004c, 0x006c, 0x004d, 0x006d, 0x004e, 0x006e, // J j K k L l M m N n | |
279 | 0x004F, 0x006F, 0xC14F, 0xE16F, 0xC24F, 0xE26F, 0xC34F, 0xE36F, 0xC44F, 0xE46F, 0xC54F, 0xE56F, //o | |
280 | 0x00D6, 0x00F6, 0xCBD6, 0xEBF6, 0xCCD6, 0xECF6, 0xCDD6, 0xEDF6, 0xCED6, 0xEEF6, 0xC5D6, 0xE5F6, //o^ | |
281 | 0x00DA, 0x00FA, 0xC1DA, 0xE1FA, 0xC2DA, 0xE2FA, 0xC3DA, 0xE3FA, 0xC4DA, 0xE4FA, 0xC5DA, 0xE5FA, //o+ | |
282 | 0x0050, 0x0070, 0x0051, 0x0071, 0x0052, 0x0072, 0x0053, 0x0073, 0x0054, 0x0074, //P p Q q R r S s T t | |
283 | 0x0055, 0x0075, 0xC155, 0xE175, 0xC255, 0xE275, 0xC355, 0xE375, 0xC455, 0xE475, 0xC555, 0xE575, //u | |
284 | 0x00DB, 0x00FB, 0xC1DB, 0xE1FB, 0xC2DB, 0xE2FB, 0xC3DB, 0xE3FB, 0xC4DB, 0xE4FB, 0xC5DB, 0xE5FB, //u+ | |
285 | 0x0056, 0x0076, 0x0057, 0x0077, 0x0058, 0x0078, // V v W w X x | |
286 | 0x0059, 0x0079, 0xC159, 0xE179, 0xC259, 0xE279, 0xC359, 0xE379, 0xC459, 0xE479, 0xC559, 0xE579, | |
287 | 0x005a, 0x007a,// Z z | |
288 | 0x0080, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, | |
289 | 0x0089, 0x008A, 0x008B, 0x008C, 0x008E, 0x0091, 0x0092, 0x0093, | |
290 | 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, | |
291 | 0x009C, 0x009E, 0x009F}, | |
292 | //VIETWARE-X | |
293 | { 0x0041, 0x0061, 0xCF41, 0xEF61, 0xCC41, 0xEC61, 0xCD41, 0xED61, 0xCE41, 0xEE61, 0xDB41, 0xFB61, //a | |
294 | 0x00C1, 0x00E1, 0xDAC1, 0xFAE1, 0xD6C1, 0xF6E1, 0xD8C1, 0xF8E1, 0xD9C1, 0xF9E1, 0xDBC1, 0xFBE1, //a^ | |
295 | 0x00C0, 0x00E0, 0xD5C0, 0xF5E0, 0xD2C0, 0xF2E0, 0xD3C0, 0xF3E0, 0xD4C0, 0xF4E0, 0xDBC0, 0xFBE0, //a( | |
296 | 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, //B b C c D d | |
297 | 0x00C2, 0x00E2, | |
298 | 0x0045, 0x0065, 0xCF45, 0xEF65, 0xCC45, 0xEC65, 0xCD45, 0xED65, 0xCE45, 0xEE65, 0xDB45, 0xFB65, //e | |
299 | 0x00C3, 0x00E3, 0xDAC3, 0xFAE3, 0xD6C3, 0xF6E3, 0xD8C3, 0xF8E3, 0xD9C3, 0xF9E3, 0xDBC3, 0xFBE3, //e^ | |
300 | 0x0046, 0x0066, 0x0047, 0x0067, 0x0048, 0x0068, // F f G g H h | |
301 | 0x0049, 0x0069, 0x00CA, 0x00EA, 0x00C7, 0x00E7, 0x00C8, 0x00E8, 0x00C9, 0x00E9, 0x00CB, 0x00EB, //i | |
302 | 0x004a, 0x006a, 0x004b, 0x006b, 0x004c, 0x006c, 0x004d, 0x006d, 0x004e, 0x006e, // J j K k L l M m N n | |
303 | 0x004F, 0x006F, 0xCF4F, 0xEF6F, 0xCC4F, 0xEC6F, 0xCD4F, 0xED6F, 0xCE4F, 0xEE6F, 0xDC4F, 0xFC6F, //o | |
304 | 0x00C4, 0x00E4, 0xDAC4, 0xFAE4, 0xD6C4, 0xF6E4, 0xD8C4, 0xF8E4, 0xD9C4, 0xF9E4, 0xDCC4, 0xFCE4, //o^ | |
305 | 0x00C5, 0x00E5, 0xCFC5, 0xEFE5, 0xCCC5, 0xECE5, 0xCDC5, 0xEDE5, 0xCEC5, 0xEEE5, 0xDCC5, 0xFCE5, //o+ | |
306 | 0x0050, 0x0070, 0x0051, 0x0071, 0x0052, 0x0072, 0x0053, 0x0073, 0x0054, 0x0074, //P p Q q R r S s T t | |
307 | 0x0055, 0x0075, 0xCF55, 0xEF75, 0xCC55, 0xEC75, 0xCD55, 0xED75, 0xCE55, 0xEE75, 0xDB55, 0xFB75, //u | |
308 | 0x00C6, 0x00E6, 0xCFC6, 0xEFE6, 0xCCC6, 0xECE6, 0xCDC6, 0xEDE6, 0xCEC6, 0xEEE6, 0xDBC6, 0xFBE6, //u+ | |
309 | 0x0056, 0x0076, 0x0057, 0x0077, 0x0058, 0x0078, // V v W w X x | |
310 | 0x0059, 0x0079, 0xCF59, 0xEF79, 0xCC59, 0xEC79, 0xCD59, 0xED79, 0xCE59, 0xEE79, 0xD159, 0xF179, //Y | |
311 | 0x005a, 0x007a,// Z z | |
312 | 0x0080, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, | |
313 | 0x0089, 0x008A, 0x008B, 0x008C, 0x008E, 0x0091, 0x0092, 0x0093, | |
314 | 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, | |
315 | 0x009C, 0x009E, 0x009F}, | |
316 | // VNI-MAC | |
317 | { 0x0041, 0x0061, 0xf441, 0x9d61, 0xaf41, 0xbf61, 0xf341, 0x9e61, 0xcd41, 0x9b61, 0xec41, 0x9561, //a | |
318 | 0xe541, 0x8961, 0xe741, 0x8761, 0xcb41, 0x8861, 0x8141, 0x8c61, 0xcc41, 0x8b61, 0x8041, 0x8a61, //a^ | |
319 | 0xe641, 0x9061, 0x8341, 0x8e61, 0xe941, 0x8f61, 0xf241, 0x9c61, 0x8641, 0x9f61, 0xe841, 0x9161, //a( | |
320 | 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, //B b C c D d | |
321 | 0x0084, 0x0096, //DD, dd | |
322 | 0x0045, 0x0065, 0xf445, 0x9d65, 0xaf45, 0xbf65, 0xf345, 0x9e65, 0xcd45, 0x9b65, 0xec45, 0x9565, //e | |
323 | 0xe545, 0x8965, 0xe745, 0x8765, 0xcb45, 0x8865, 0x8145, 0x8c65, 0xcc45, 0x8b65, 0x8045, 0x8a65, //e^ | |
324 | 0x0046, 0x0066, 0x0047, 0x0067, 0x0048, 0x0068, // F f G g H h | |
325 | 0x0049, 0x0069, 0x00ea, 0x0092, 0x00ed, 0x0093, 0x00ae, 0x00be, 0x00ee, 0x0097, 0x00f1, 0x0098, //i | |
326 | 0x004a, 0x006a, 0x004b, 0x006b, 0x004c, 0x006c, 0x004d, 0x006d, 0x004e, 0x006e, // J j K k L l M m N n | |
327 | 0x004f, 0x006f, 0xf44f, 0x9d6f, 0xaf4f, 0xbf6f, 0xf34f, 0x9e6f, 0xcd4f, 0x9b6f, 0xec4f, 0x956f, //o | |
328 | 0xe54f, 0x896f, 0xe74f, 0x876f, 0xcb4f, 0x886f, 0x814f, 0x8c6f, 0xcc4f, 0x8b6f, 0x804f, 0x8a6f, //o^ | |
329 | 0x00ef, 0x0099, 0xf4ef, 0x9d99, 0xafef, 0xbf99, 0xf3ef, 0x9e99, 0xcdef, 0x9b99, 0xecef, 0x9599, //o+ | |
330 | 0x0050, 0x0070, 0x0051, 0x0071, 0x0052, 0x0072, 0x0053, 0x0073, 0x0054, 0x0074, //P p Q q R r S s T t | |
331 | 0x0055, 0x0075, 0xf455, 0x9d75, 0xaf55, 0xbf75, 0xf355, 0x9e75, 0xcd55, 0x9b75, 0xec55, 0x9575, //u | |
332 | 0x0085, 0x009a, 0xf485, 0x9d9a, 0xaf85, 0xbf9a, 0xf385, 0x9e9a, 0xcd85, 0x9b9a, 0xec85, 0x959a, //u+ | |
333 | 0x0056, 0x0076, 0x0057, 0x0077, 0x0058, 0x0078, // V v W w X x | |
334 | 0x0059, 0x0079, 0xf459, 0x9d79, 0xaf59, 0xbf79, 0xf359, 0x9e79, 0xcd59, 0x9b79, 0x00eb, 0x0094, //y | |
335 | 0x005a, 0x007a, // Z z | |
336 | 0x00db, 0x00e2, 0x00c4, 0x00e3, 0x00c9, 0x00a0, 0x00e0, 0x00f6, | |
337 | 0x00e4, 0x003f, 0x00dc, 0x00ce, 0x003f, 0x00d4, 0x00d5, 0x00d2, | |
338 | 0x00d3, 0x00a5, 0x00d0, 0x00d1, 0x00f7, 0x00aa, 0x003f, 0x00dd, | |
339 | 0x00cf, 0x003f, 0x00d9} | |
340 | }; | |
341 | ||
342 | UKWORD WinCP1258[TOTAL_VNCHARS]= | |
343 | //Windows CP 1258 | |
344 | { 0x0041, 0x0061, 0xec41, 0xec61, 0xcc41, 0xcc61, 0xd241, 0xd261, 0xde41, 0xde61, 0xf241, 0xf261, //a | |
345 | 0x00c2, 0x00e2, 0xecc2, 0xece2, 0xccc2, 0xcce2, 0xd2c2, 0xd2e2, 0xdec2, 0xdee2, 0xf2c2, 0xf2e2, //a^ | |
346 | 0x00c3, 0x00e3, 0xecc3, 0xece3, 0xccc3, 0xcce3, 0xd2c3, 0xd2e3, 0xdec3, 0xdee3, 0xf2c3, 0xf2e3, //a( | |
347 | 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, //B b C c D d | |
348 | 0x00d0, 0x00f0, //DD, dd | |
349 | 0x0045, 0x0065, 0xec45, 0xec65, 0xcc45, 0xcc65, 0xd245, 0xd265, 0xde45, 0xde65, 0xf245, 0xf265, //e | |
350 | 0x00ca, 0x00ea, 0xecca, 0xecea, 0xccca, 0xccea, 0xd2ca, 0xd2ea, 0xdeca, 0xdeea, 0xf2ca, 0xf2ea, //e^ | |
351 | 0x0046, 0x0066, 0x0047, 0x0067, 0x0048, 0x0068, // F f G g H h | |
352 | 0x0049, 0x0069, 0xec49, 0xec69, 0xcc49, 0xcc69, 0xd249, 0xd269, 0xde49, 0xde69, 0xf249, 0xf269, //i | |
353 | 0x004a, 0x006a, 0x004b, 0x006b, 0x004c, 0x006c, 0x004d, 0x006d, 0x004e, 0x006e, // J j K k L l M m N n | |
354 | 0x004f, 0x006f, 0xec4f, 0xec6f, 0xcc4f, 0xcc6f, 0xd24f, 0xd26f, 0xde4f, 0xde6f, 0xf24f, 0xf26f, //o | |
355 | 0x00d4, 0x00f4, 0xecd4, 0xecf4, 0xccd4, 0xccf4, 0xd2d4, 0xd2f4, 0xded4, 0xdef4, 0xf2d4, 0xf2f4, //o^ | |
356 | 0x00d5, 0x00f5, 0xecd5, 0xecf5, 0xccd5, 0xccf5, 0xd2d5, 0xd2f5, 0xded5, 0xdef5, 0xf2d5, 0xf2f5, //o+ | |
357 | 0x0050, 0x0070, 0x0051, 0x0071, 0x0052, 0x0072, 0x0053, 0x0073, 0x0054, 0x0074, //P p Q q R r S s T t | |
358 | 0x0055, 0x0075, 0xec55, 0xec75, 0xcc55, 0xcc75, 0xd255, 0xd275, 0xde55, 0xde75, 0xf255, 0xf275, //u | |
359 | 0x00dd, 0x00fd, 0xecdd, 0xecfd, 0xccdd, 0xccfd, 0xd2dd, 0xd2fd, 0xdedd, 0xdefd, 0xf2dd, 0xf2fd, //u+ | |
360 | 0x0056, 0x0076, 0x0057, 0x0077, 0x0058, 0x0078, // V v W w X x | |
361 | 0x0059, 0x0079, 0xec59, 0xec79, 0xcc59, 0xcc79, 0xd259, 0xd279, 0xde59, 0xde79, 0xf259, 0xf279, //y | |
362 | 0x005a, 0x007a, // Z z | |
363 | 0x0080, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, | |
364 | 0x0089, 0x008A, 0x008B, 0x008C, 0x008E, 0x0091, 0x0092, 0x0093, | |
365 | 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, | |
366 | 0x009C, 0x009E, 0x009F}; | |
367 | ||
368 | UKWORD WinCP1258Pre[TOTAL_VNCHARS]= | |
369 | //Windows CP1258 - with some more precomposed characters | |
370 | { 0x0041, 0x0061, 0x00c1, 0x00e1, 0x00c0, 0x00e0, 0xd241, 0xd261, 0xde41, 0xde61, 0xf241, 0xf261, //a | |
371 | 0x00c2, 0x00e2, 0xecc2, 0xece2, 0xccc2, 0xcce2, 0xd2c2, 0xd2e2, 0xdec2, 0xdee2, 0xf2c2, 0xf2e2, //a^ | |
372 | 0x00c3, 0x00e3, 0xecc3, 0xece3, 0xccc3, 0xcce3, 0xd2c3, 0xd2e3, 0xdec3, 0xdee3, 0xf2c3, 0xf2e3, //a( | |
373 | 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, //B b C c D d | |
374 | 0x00d0, 0x00f0, //DD, dd | |
375 | 0x0045, 0x0065, 0x00c9, 0x00e9, 0x00c8, 0x00e8, 0xd245, 0xd265, 0xde45, 0xde65, 0xf245, 0xf265, //e | |
376 | 0x00ca, 0x00ea, 0xecca, 0xecea, 0xccca, 0xccea, 0xd2ca, 0xd2ea, 0xdeca, 0xdeea, 0xf2ca, 0xf2ea, //e^ | |
377 | 0x0046, 0x0066, 0x0047, 0x0067, 0x0048, 0x0068, // F f G g H h | |
378 | 0x0049, 0x0069, 0x00cd, 0x00ed, 0xcc49, 0xcc69, 0xd249, 0xd269, 0xde49, 0xde69, 0xf249, 0xf269, //i | |
379 | 0x004a, 0x006a, 0x004b, 0x006b, 0x004c, 0x006c, 0x004d, 0x006d, 0x004e, 0x006e, // J j K k L l M m N n | |
380 | 0x004f, 0x006f, 0x00d3, 0x00f3, 0xcc4f, 0xcc6f, 0xd24f, 0xd26f, 0xde4f, 0xde6f, 0xf24f, 0xf26f, //o | |
381 | 0x00d4, 0x00f4, 0xecd4, 0xecf4, 0xccd4, 0xccf4, 0xd2d4, 0xd2f4, 0xded4, 0xdef4, 0xf2d4, 0xf2f4, //o^ | |
382 | 0x00d5, 0x00f5, 0xecd5, 0xecf5, 0xccd5, 0xccf5, 0xd2d5, 0xd2f5, 0xded5, 0xdef5, 0xf2d5, 0xf2f5, //o+ | |
383 | 0x0050, 0x0070, 0x0051, 0x0071, 0x0052, 0x0072, 0x0053, 0x0073, 0x0054, 0x0074, //P p Q q R r S s T t | |
384 | 0x0055, 0x0075, 0x00da, 0x00fa, 0x00d9, 0x00f9, 0xd255, 0xd275, 0xde55, 0xde75, 0xf255, 0xf275, //u | |
385 | 0x00dd, 0x00fd, 0xecdd, 0xecfd, 0xccdd, 0xccfd, 0xd2dd, 0xd2fd, 0xdedd, 0xdefd, 0xf2dd, 0xf2fd, //u+ | |
386 | 0x0056, 0x0076, 0x0057, 0x0077, 0x0058, 0x0078, // V v W w X x | |
387 | 0x0059, 0x0079, 0xec59, 0xec79, 0xcc59, 0xcc79, 0xd259, 0xd279, 0xde59, 0xde79, 0xf259, 0xf279, //y | |
388 | 0x005a, 0x007a, // Z z | |
389 | 0x0080, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, | |
390 | 0x0089, 0x008A, 0x008B, 0x008C, 0x008E, 0x0091, 0x0092, 0x0093, | |
391 | 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, | |
392 | 0x009C, 0x009E, 0x009F}; | |
393 | ||
394 | UnicodeChar UnicodeTable[TOTAL_VNCHARS] = | |
395 | {0x0041, 0x0061, 0x00c1, 0x00e1, 0x00c0, 0x00e0, 0x1ea2, 0x1ea3, 0x00c3, 0x00e3, 0x1ea0, 0x1ea1, //a | |
396 | 0x00c2, 0x00e2, 0x1ea4, 0x1ea5, 0x1ea6, 0x1ea7, 0x1ea8, 0x1ea9, 0x1eaa, 0x1eab, 0x1eac, 0x1ead, //a^ | |
397 | 0x0102, 0x0103, 0x1eae, 0x1eaf, 0x1eb0, 0x1eb1, 0x1eb2, 0x1eb3, 0x1eb4, 0x1eb5, 0x1eb6, 0x1eb7, //a( | |
398 | 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, //B b C c D d | |
399 | 0x0110, 0x0111, // DD, dd | |
400 | 0x0045, 0x0065, 0x00c9, 0x00e9, 0x00c8, 0x00e8, 0x1eba, 0x1ebb, 0x1ebc, 0x1ebd, 0x1eb8, 0x1eb9, //e | |
401 | 0x00ca, 0x00ea, 0x1ebe, 0x1ebf, 0x1ec0, 0x1ec1, 0x1ec2, 0x1ec3, 0x1ec4, 0x1ec5, 0x1ec6, 0x1ec7, //e^ | |
402 | 0x0046, 0x0066, 0x0047, 0x0067, 0x0048, 0x0068, // F f G g H h | |
403 | 0x0049, 0x0069, 0x00cd, 0x00ed, 0x00cc, 0x00ec, 0x1ec8, 0x1ec9, 0x0128, 0x0129, 0x1eca, 0x1ecb, //i | |
404 | 0x004a, 0x006a, 0x004b, 0x006b, 0x004c, 0x006c, 0x004d, 0x006d, 0x004e, 0x006e, // J j K k L l M m N n | |
405 | 0x004f, 0x006f, 0x00d3, 0x00f3, 0x00d2, 0x00f2, 0x1ece, 0x1ecf, 0x00d5, 0x00f5, 0x1ecc, 0x1ecd, //o | |
406 | 0x00d4, 0x00f4, 0x1ed0, 0x1ed1, 0x1ed2, 0x1ed3, 0x1ed4, 0x1ed5, 0x1ed6, 0x1ed7, 0x1ed8, 0x1ed9, //o^ | |
407 | 0x01a0, 0x01a1, 0x1eda, 0x1edb, 0x1edc, 0x1edd, 0x1ede, 0x1edf, 0x1ee0, 0x1ee1, 0x1ee2, 0x1ee3, //o+ | |
408 | 0x0050, 0x0070, 0x0051, 0x0071, 0x0052, 0x0072, 0x0053, 0x0073, 0x0054, 0x0074, //P p Q q R r S s T t | |
409 | 0x0055, 0x0075, 0x00da, 0x00fa, 0x00d9, 0x00f9, 0x1ee6, 0x1ee7, 0x0168, 0x0169, 0x1ee4, 0x1ee5, //u | |
410 | 0x01af, 0x01b0, 0x1ee8, 0x1ee9, 0x1eea, 0x1eeb, 0x1eec, 0x1eed, 0x1eee, 0x1eef, 0x1ef0, 0x1ef1, //u+ | |
411 | 0x0056, 0x0076, 0x0057, 0x0077, 0x0058, 0x0078, // V v W w X x | |
412 | 0x0059, 0x0079, 0x00dd, 0x00fd, 0x1ef2, 0x1ef3, 0x1ef6, 0x1ef7, 0x1ef8, 0x1ef9, 0x1ef4, 0x1ef5, //y | |
413 | 0x005a, 0x007a, // Z z | |
414 | // Symbols that have different code points in Unicode and Western charsets | |
415 | 0x20AC, 0x20A1, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, | |
416 | 0x2030, 0x0160, 0x2039, 0x0152, 0x017D, 0x2018, 0x2019, 0x201C, | |
417 | 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, | |
418 | 0x0153, 0x017E, 0x0178}; | |
419 | ||
420 | /* | |
421 | unsigned char WesternSymbols[] = | |
422 | {0x80, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, | |
423 | 0x89, 0x8A, 0x8B, 0x8C, 0x8E, 0x91, 0x92, 0x93, | |
424 | 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, | |
425 | 0x9C, 0x9E, 0x9F}; | |
426 | */ | |
427 | ||
428 | /* | |
429 | ' 0x27 | |
430 | ` 0x60 | |
431 | ? 0x3f | |
432 | ~ 0x7e | |
433 | . 0x2e | |
434 | ||
435 | ^ 0x5e | |
436 | ( 0x28 | |
437 | + 0x2b | |
438 | ||
439 | */ | |
440 | UKDWORD VIQRTable[TOTAL_VNCHARS] = | |
441 | { 0x41, 0x61, 0x2741, 0x2761, 0x6041, 0x6061, 0x3f41, 0x3f61, 0x7e41, 0x7e61, 0x2e41, 0x2e61, //a | |
442 | 0x5e41, 0x5e61, 0x275e41, 0x275e61, 0x605e41, 0x605e61, 0x3f5e41, 0x3f5e61, 0x7e5e41, 0x7e5e61, 0x2e5e41, 0x2e5e61, //a^ | |
443 | 0x2841, 0x2861, 0x272841, 0x272861, 0x602841, 0x602861, 0x3f2841, 0x3f2861, 0x7e2841, 0x7e2861, 0x2e2841, 0x2e2861, //a( | |
444 | 0x42, 0x62, 0x43, 0x63, 0x44, 0x64, //B b C c D d | |
445 | 0x4444, 0x6464, // DD, dd | |
446 | 0x45, 0x65, 0x2745, 0x2765, 0x6045, 0x6065, 0x3f45, 0x3f65, 0x7e45, 0x7e65, 0x2e45, 0x2e65, //e | |
447 | 0x5e45, 0x5e65, 0x275e45, 0x275e65, 0x605e45, 0x605e65, 0x3f5e45, 0x3f5e65, 0x7e5e45, 0x7e5e65, 0x2e5e45, 0x2e5e65, //e^ | |
448 | 0x46, 0x66, 0x47, 0x67, 0x48, 0x68, // F f G g H h | |
449 | 0x49, 0x69, 0x2749, 0x2769, 0x6049, 0x6069, 0x3f49, 0x3f69, 0x7e49, 0x7e69, 0x2e49, 0x2e69, //i | |
450 | 0x4a, 0x6a, 0x4b, 0x6b, 0x4c, 0x6c, 0x4d, 0x6d, 0x4e, 0x6e, // J j K k L l M m N n | |
451 | 0x4f, 0x6f, 0x274f, 0x276f, 0x604f, 0x606f, 0x3f4f, 0x3f6f, 0x7e4f, 0x7e6f, 0x2e4f, 0x2e6f, //o | |
452 | 0x5e4f, 0x5e6f, 0x275e4f, 0x275e6f, 0x605e4f, 0x605e6f, 0x3f5e4f, 0x3f5e6f, 0x7e5e4f, 0x7e5e6f, 0x2e5e4f, 0x2e5e6f, //o^ | |
453 | 0x2b4f, 0x2b6f, 0x272b4f, 0x272b6f, 0x602b4f, 0x602b6f, 0x3f2b4f, 0x3f2b6f, 0x7e2b4f, 0x7e2b6f, 0x2e2b4f, 0x2e2b6f, //o+ | |
454 | 0x50, 0x70, 0x51, 0x71, 0x52, 0x72, 0x53, 0x73, 0x54, 0x74, //P p Q q R r S s T t | |
455 | 0x55, 0x75, 0x2755, 0x2775, 0x6055, 0x6075, 0x3f55, 0x3f75, 0x7e55, 0x7e75, 0x2e55, 0x2e75, //u | |
456 | 0x2b55, 0x2b75, 0x272b55, 0x272b75, 0x602b55, 0x602b75, 0x3f2b55, 0x3f2b75, 0x7e2b55, 0x7e2b75, 0x2e2b55, 0x2e2b75, //u+ | |
457 | 0x56, 0x76, 0x57, 0x77, 0x58, 0x78, // V v W w X x | |
458 | 0x59, 0x79, 0x2759, 0x2779, 0x6059, 0x6079, 0x3f59, 0x3f79, 0x7e59, 0x7e79, 0x2e59, 0x2e79, | |
459 | 0x5a, 0x7a, // Z z | |
460 | 0x80, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, | |
461 | 0x89, 0x8A, 0x8B, 0x8C, 0x8E, 0x91, 0x92, 0x93, | |
462 | 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, | |
463 | 0x9C, 0x9E, 0x9F}; | |
464 | ||
465 | ||
466 | UKDWORD UnicodeComposite[TOTAL_VNCHARS] = | |
467 | { 0x00000041, 0x00000061, 0x03010041, 0x03010061, 0x03000041, 0x03000061, //a | |
468 | 0x03090041, 0x03090061, 0x03030041, 0x03030061, 0x03230041, 0x03230061, //a | |
469 | ||
470 | 0x000000c2, 0x000000e2, 0x030100c2, 0x030100e2, 0x030000c2, 0x030000e2, | |
471 | 0x030900c2, 0x030900e2, 0x030300c2, 0x030300e2, 0x032300c2, 0x032300e2, //a^ | |
472 | ||
473 | 0x00000102, 0x00000103, 0x03010102, 0x03010103, 0x03000102, 0x03000103, | |
474 | 0x03090102, 0x03090103, 0x03030102, 0x03030103, 0x03230102, 0x03230103, //a( | |
475 | ||
476 | 0x0042, 0x0062, 0x0043, 0x0063, 0x0044, 0x0064, //B b C c D d | |
477 | 0x0110, 0x0111, //0x00d1, 0x00f1, //DD, dd | |
478 | ||
479 | 0x00000045, 0x00000065, 0x03010045, 0x03010065, 0x03000045, 0x03000065, | |
480 | 0x03090045, 0x03090065, 0x03030045, 0x03030065, 0x03230045, 0x03230065, //e | |
481 | ||
482 | 0x000000ca, 0x000000ea, 0x030100ca, 0x030100ea, 0x030000ca, 0x030000ea, | |
483 | 0x030900ca, 0x030900ea, 0x030300ca, 0x030300ea, 0x032300ca, 0x032300ea, //e^ | |
484 | ||
485 | 0x0046, 0x0066, 0x0047, 0x0067, 0x0048, 0x0068, // F f G g H h | |
486 | ||
487 | 0x00000049, 0x00000069, 0x03010049, 0x03010069, 0x03000049, 0x03000069, | |
488 | 0x03090049, 0x03090069, 0x03030049, 0x03030069, 0x03230049, 0x03230069, //i | |
489 | ||
490 | 0x004a, 0x006a, 0x004b, 0x006b, 0x004c, 0x006c, 0x004d, 0x006d, 0x004e, 0x006e, // J j K k L l M m N n | |
491 | ||
492 | 0x0000004f, 0x0000006f, 0x0301004f, 0x0301006f, 0x0300004f, 0x0300006f, | |
493 | 0x0309004f, 0x0309006f, 0x0303004f, 0x0303006f, 0x0323004f, 0x0323006f, //o | |
494 | ||
495 | 0x000000d4, 0x000000f4, 0x030100d4, 0x030100f4, 0x030000d4, 0x030000f4, | |
496 | 0x030900d4, 0x030900f4, 0x030300d4, 0x030300f4, 0x032300d4, 0x032300f4, //o^ | |
497 | ||
498 | 0x000001a0, 0x000001a1, 0x030101a0, 0x030101a1, 0x030001a0, 0x030001a1, | |
499 | 0x030901a0, 0x030901a1, 0x030301a0, 0x030301a1, 0x032301a0, 0x032301a1, //o+ | |
500 | ||
501 | 0x0050, 0x0070, 0x0051, 0x0071, 0x0052, 0x0072, 0x0053, 0x0073, 0x0054, 0x0074, //P p Q q R r S s T t | |
502 | ||
503 | 0x00000055, 0x00000075, 0x03010055, 0x03010075, 0x03000055, 0x03000075, | |
504 | 0x03090055, 0x03090075, 0x03030055, 0x03030075, 0x03230055, 0x03230075, //u | |
505 | ||
506 | 0x000001af, 0x000001b0, 0x030101af, 0x030101b0, 0x030001af, 0x030001b0, | |
507 | 0x030901af, 0x030901b0, 0x030301af, 0x030301b0, 0x032301af, 0x032301b0, //u+ | |
508 | ||
509 | 0x0056, 0x0076, 0x0057, 0x0077, 0x0058, 0x0078, // V v W w X x | |
510 | ||
511 | 0x00000059, 0x00000079, 0x03010059, 0x03010079, 0x03000059, 0x03000079, | |
512 | 0x03090059, 0x03090079, 0x03030059, 0x03030079, 0x03230059, 0x03230079, //y | |
513 | 0x005a, 0x007a, // Z z | |
514 | // Symbols that have different code points in Unicode and Western charsets | |
515 | 0x20AC, 0x20A1, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, | |
516 | 0x2030, 0x0160, 0x2039, 0x0152, 0x017D, 0x2018, 0x2019, 0x201C, | |
517 | 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, | |
518 | 0x0153, 0x017E, 0x0178}; | |
519 | ||
520 | int StdVnRootChar[TOTAL_VNCHARS] = { | |
521 | 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, //a [A=0] | |
522 | 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, //a^ -> a | |
523 | 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, //a( -> a | |
524 | 36, 37, 38, 39, 40, 41, // bcd [D=40, d=41] | |
525 | 40, 41, // DD dd [mapped to D, d] | |
526 | 44, 45, 44, 45, 44, 45, 44, 45, 44, 45, 44, 45, // 3: e [E = 44] | |
527 | 44, 45, 44, 45, 44, 45, 44, 45, 44, 45, 44, 45, // 4: e^ -> e | |
528 | 68, 69, 70, 71, 72, 73, // fgh | |
529 | 74, 75, 74, 75, 74, 75, 74, 75, 74, 75, 74, 75, // 5: i | |
530 | 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, //jklmn | |
531 | 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, // 6: o [o=96] | |
532 | 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, // 7: o^ -> o | |
533 | 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, // 8: o+ -> o | |
534 | 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, // pqrst | |
535 | 142, 143, 142, 143, 142, 143, 142, 143, 142, 143, 142, 143, // 9: u [U=142] | |
536 | 142, 143, 142, 143, 142, 143, 142, 143, 142, 143, 142, 143, //10: u+ -> u | |
537 | 166, 167, 168, 169, 170, 171, //vwx | |
538 | 172, 173, 172, 173, 172, 173, 172, 173, 172, 173, 172, 173, //11: y [Y=172] | |
539 | 184, 185, // z | |
540 | 186, 187, 188, 189, 190, 191, 192, 193, | |
541 | 194, 195, 196, 197, 198, 199, 200, 201, | |
542 | 202, 203, 204, 205, 206, 207, 208, 209, | |
543 | 210, 211, 212 | |
544 | }; | |
545 | ||
546 | int StdVnNoTone[TOTAL_VNCHARS] = { | |
547 | 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, //a [A=0] | |
548 | 12, 13, 12, 13, 12, 13, 12, 13, 12, 13, 12, 13, //a^ | |
549 | 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, //a( | |
550 | 36, 37, 38, 39, 40, 41, // bcd [D=40, d=41] | |
551 | 42, 43, // DD dd | |
552 | 44, 45, 44, 45, 44, 45, 44, 45, 44, 45, 44, 45, // 3: e [E = 44] | |
553 | 56, 57, 56, 57, 56, 57, 56, 57, 56, 57, 56, 57, // 4: e^ | |
554 | 68, 69, 70, 71, 72, 73, // fgh | |
555 | 74, 75, 74, 75, 74, 75, 74, 75, 74, 75, 74, 75, // 5: i | |
556 | 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, //jklmn | |
557 | 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, // 6: o [o=96] | |
558 | 108, 109, 108, 109, 108, 109, 108, 109, 108, 109, 108, 109, // 7: o^ | |
559 | 120, 121, 120, 121, 120, 121, 120, 121, 120, 121, 120, 121, // 8: o+ | |
560 | 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, // pqrst | |
561 | 142, 143, 142, 143, 142, 143, 142, 143, 142, 143, 142, 143, // 9: u [U=142] | |
562 | 154, 155, 154, 155, 154, 155, 154, 155, 154, 155, 154, 155, //10: u+ | |
563 | 166, 167, 168, 169, 170, 171, //vwx | |
564 | 172, 173, 172, 173, 172, 173, 172, 173, 172, 173, 172, 173, //11: y [Y=172] | |
565 | 184, 185, // z | |
566 | 186, 187, 188, 189, 190, 191, 192, 193, | |
567 | 194, 195, 196, 197, 198, 199, 200, 201, | |
568 | 202, 203, 204, 205, 206, 207, 208, 209, | |
569 | 210, 211, 212 | |
570 | }; |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | #ifndef VIETNAMESE_CHARSET_DATA_H | |
2 | #define VIETNAMESE_CHARSET_DATA_H | |
3 | ||
4 | // This header defines some special characters | |
5 | const StdVnChar StdStartQuote = (VnStdCharOffset + 201); // 0x93 in the Western charset | |
6 | // 201 is the offset of character 0x93 (start quote) in Vn charsets | |
7 | const StdVnChar StdEndQuote = (VnStdCharOffset + 202); // 0x94 in the Western charset | |
8 | const StdVnChar StdEllipsis = (VnStdCharOffset + 190); // 0x85 in Western charet. | |
9 | ||
10 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | VnConv: Vietnamese Encoding Converter Library | |
3 | UniKey Project: http://unikey.sourceforge.net | |
4 | Copyleft (C) 1998-2002 Pham Kim Long | |
5 | Contact: longp@cslab.felk.cvut.cz | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License | |
9 | as published by the Free Software Foundation; either version 2 | |
10 | of the License, or (at your option) any later version. | |
11 | ||
12 | This program 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 | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | --------------------------------------------------------------------------------*/ | |
21 | // For some unknown reasons, the functions in this file cannot be exported | |
22 | // We had to move them to convert.cpp. | |
23 | // TODO: inspect this problem later! | |
24 | /* | |
25 | #include "stdafx.h" | |
26 | #include "vnconv.h" | |
27 | ||
28 | char *ErrTable[VNCONV_LAST_ERROR] = | |
29 | {"No error", | |
30 | "Unknown error", | |
31 | "Invalid charset", | |
32 | "Error opening input file", | |
33 | "Error opening output file", | |
34 | "Error writing to output stream", | |
35 | "Not enough memory", | |
36 | }; | |
37 | ||
38 | DllExport const char * VnConvErrMsg(int errCode) | |
39 | { | |
40 | if (errCode < 0 || errCode >= VNCONV_LAST_ERROR) | |
41 | errCode = VNCONV_UNKNOWN_ERROR; | |
42 | return ErrTable[errCode]; | |
43 | } | |
44 | ||
45 | */⏎ |
0 | // -*- mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include <iostream> | |
24 | #include "inputproc.h" | |
25 | ||
26 | using namespace std; | |
27 | ||
28 | /* | |
29 | unsigned char WordBreakSyms[] = { | |
30 | ',', ';', ':', '.', '\"', '\'', '!', '?', ' ', | |
31 | '<', '>', '=', '+', '-', '*', '/', '\\', | |
32 | '_', '~', '`', '@', '#', '$', '%', '^', '&', '(', ')', '{', '}', '[', ']'}; | |
33 | */ | |
34 | ||
35 | unsigned char WordBreakSyms[] = { | |
36 | ',', ';', ':', '.', '\"', '\'', '!', '?', ' ', | |
37 | '<', '>', '=', '+', '-', '*', '/', '\\', | |
38 | '_', '@', '#', '$', '%', '&', '(', ')', '{', '}', '[', ']', '|'}; //we excluded ~, `, ^ | |
39 | ||
40 | VnLexiName AZLexiUpper[] = | |
41 | {vnl_A, vnl_B, vnl_C, vnl_D, vnl_E, vnl_F, vnl_G, vnl_H, vnl_I, vnl_J, | |
42 | vnl_K, vnl_L, vnl_M, vnl_N, vnl_O, vnl_P, vnl_Q, vnl_R, vnl_S, vnl_T, | |
43 | vnl_U, vnl_V, vnl_W, vnl_X, vnl_Y, vnl_Z}; | |
44 | ||
45 | VnLexiName AZLexiLower[] = | |
46 | {vnl_a, vnl_b, vnl_c, vnl_d, vnl_e, vnl_f, vnl_g, vnl_h, vnl_i, vnl_j, | |
47 | vnl_k, vnl_l, vnl_m, vnl_n, vnl_o, vnl_p, vnl_q, vnl_r, vnl_s, vnl_t, | |
48 | vnl_u, vnl_v, vnl_w, vnl_x, vnl_y, vnl_z}; | |
49 | ||
50 | UkCharType UkcMap[256]; | |
51 | ||
52 | struct _ascVnLexi { | |
53 | int asc; | |
54 | VnLexiName lexi; | |
55 | }; | |
56 | ||
57 | //List of western characters outside range A-Z that are | |
58 | //also Vietnamese characters | |
59 | _ascVnLexi AscVnLexiList[] = { | |
60 | {0xC0, vnl_A2}, | |
61 | {0xC1, vnl_A1}, | |
62 | {0xC2, vnl_Ar}, | |
63 | {0xC2, vnl_A4}, | |
64 | {0xC8, vnl_E2}, | |
65 | {0xC9, vnl_E1}, | |
66 | {0xCA, vnl_Er}, | |
67 | {0xCC, vnl_I2}, | |
68 | {0xCD, vnl_I1}, | |
69 | {0xD2, vnl_O2}, | |
70 | {0xD3, vnl_O1}, | |
71 | {0xD4, vnl_Or}, | |
72 | {0xD5, vnl_O4}, | |
73 | {0xD9, vnl_U2}, | |
74 | {0xDA, vnl_U1}, | |
75 | {0xDD, vnl_Y1}, | |
76 | {0xE0, vnl_a2}, | |
77 | {0xE1, vnl_a1}, | |
78 | {0xE2, vnl_ar}, | |
79 | {0xE3, vnl_a4}, | |
80 | {0xE8, vnl_e2}, | |
81 | {0xE9, vnl_e1}, | |
82 | {0xEA, vnl_er}, | |
83 | {0xEC, vnl_i2}, | |
84 | {0xED, vnl_i1}, | |
85 | {0xF2, vnl_o2}, | |
86 | {0xF3, vnl_o1}, | |
87 | {0xF4, vnl_or}, | |
88 | {0xF5, vnl_o4}, | |
89 | {0xF9, vnl_u2}, | |
90 | {0xFA, vnl_u1}, | |
91 | {0xFD, vnl_y1}, | |
92 | {0x00, vnl_nonVnChar} | |
93 | }; | |
94 | ||
95 | VnLexiName IsoVnLexiMap[256]; | |
96 | ||
97 | bool ClassifierTableInitialized = false; | |
98 | ||
99 | DllExport UkKeyMapping TelexMethodMapping[] = { | |
100 | {'Z', vneTone0}, | |
101 | {'S', vneTone1}, | |
102 | {'F', vneTone2}, | |
103 | {'R', vneTone3}, | |
104 | {'X', vneTone4}, | |
105 | {'J', vneTone5}, | |
106 | {'W', vne_telex_w}, | |
107 | {'A', vneRoof_a}, | |
108 | {'E', vneRoof_e}, | |
109 | {'O', vneRoof_o}, | |
110 | {'D', vneDd}, | |
111 | {'[', vneCount + vnl_oh}, | |
112 | {']', vneCount + vnl_uh}, | |
113 | {'{', vneCount + vnl_Oh}, | |
114 | {'}', vneCount + vnl_Uh}, | |
115 | {0, vneNormal} | |
116 | }; | |
117 | ||
118 | DllExport UkKeyMapping SimpleTelexMethodMapping[] = { | |
119 | {'Z', vneTone0}, | |
120 | {'S', vneTone1}, | |
121 | {'F', vneTone2}, | |
122 | {'R', vneTone3}, | |
123 | {'X', vneTone4}, | |
124 | {'J', vneTone5}, | |
125 | {'W', vneHookAll}, | |
126 | {'A', vneRoof_a}, | |
127 | {'E', vneRoof_e}, | |
128 | {'O', vneRoof_o}, | |
129 | {'D', vneDd}, | |
130 | {0, vneNormal} | |
131 | }; | |
132 | ||
133 | DllExport UkKeyMapping SimpleTelex2MethodMapping[] = { | |
134 | {'Z', vneTone0}, | |
135 | {'S', vneTone1}, | |
136 | {'F', vneTone2}, | |
137 | {'R', vneTone3}, | |
138 | {'X', vneTone4}, | |
139 | {'J', vneTone5}, | |
140 | {'W', vne_telex_w}, | |
141 | {'A', vneRoof_a}, | |
142 | {'E', vneRoof_e}, | |
143 | {'O', vneRoof_o}, | |
144 | {'D', vneDd}, | |
145 | {0, vneNormal} | |
146 | }; | |
147 | ||
148 | DllExport UkKeyMapping VniMethodMapping[] = { | |
149 | {'0', vneTone0}, | |
150 | {'1', vneTone1}, | |
151 | {'2', vneTone2}, | |
152 | {'3', vneTone3}, | |
153 | {'4', vneTone4}, | |
154 | {'5', vneTone5}, | |
155 | {'6', vneRoofAll}, | |
156 | {'7', vneHook_uo}, | |
157 | {'8', vneBowl}, | |
158 | {'9', vneDd}, | |
159 | {0, vneNormal} | |
160 | }; | |
161 | ||
162 | DllExport UkKeyMapping VIQRMethodMapping[] = { | |
163 | {'0', vneTone0}, | |
164 | {'\'', vneTone1}, | |
165 | {'`', vneTone2}, | |
166 | {'?', vneTone3}, | |
167 | {'~', vneTone4}, | |
168 | {'.', vneTone5}, | |
169 | {'^', vneRoofAll}, | |
170 | {'+', vneHook_uo}, | |
171 | {'*', vneHook_uo}, | |
172 | {'(', vneBowl}, | |
173 | {'D', vneDd}, | |
174 | {'\\', vneEscChar}, | |
175 | {0, vneNormal} | |
176 | }; | |
177 | ||
178 | DllExport UkKeyMapping MsViMethodMapping[] = { | |
179 | {'5', vneTone2}, | |
180 | {'%', vneTone2}, | |
181 | {'6', vneTone3}, | |
182 | {'^', vneTone3}, | |
183 | {'7', vneTone4}, | |
184 | {'&', vneTone4}, | |
185 | {'8', vneTone1}, | |
186 | {'*', vneTone1}, | |
187 | {'9', vneTone5}, | |
188 | {'(', vneTone5}, | |
189 | {'1', vneCount + vnl_ab}, | |
190 | {'!', vneCount + vnl_Ab}, | |
191 | {'2', vneCount + vnl_ar}, | |
192 | {'@', vneCount + vnl_Ar}, | |
193 | {'3', vneCount + vnl_er}, | |
194 | {'#', vneCount + vnl_Er}, | |
195 | {'4', vneCount + vnl_or}, | |
196 | {'$', vneCount + vnl_Or}, | |
197 | {'0', vneCount + vnl_dd}, | |
198 | {')', vneCount + vnl_DD}, | |
199 | {'[', vneCount + vnl_uh}, | |
200 | {']', vneCount + vnl_oh}, | |
201 | {'{', vneCount + vnl_Uh}, | |
202 | {'}', vneCount + vnl_Oh}, | |
203 | {0, vneNormal} | |
204 | }; | |
205 | ||
206 | //------------------------------------------- | |
207 | void SetupInputClassifierTable() | |
208 | { | |
209 | unsigned int c; | |
210 | int i; | |
211 | ||
212 | for (c=0; c<=32; c++) { | |
213 | UkcMap[c] = ukcReset; | |
214 | } | |
215 | ||
216 | for (c=33; c<256; c++) { | |
217 | UkcMap[c] = ukcNonVn; | |
218 | } | |
219 | ||
220 | /* | |
221 | for (c = '0'; c <= '9'; c++) | |
222 | UkcMap[c] = ukcNonVn; | |
223 | */ | |
224 | ||
225 | for (c = 'a'; c <= 'z'; c++) | |
226 | UkcMap[c] = ukcVn; | |
227 | for (c = 'A'; c <= 'Z'; c++) | |
228 | UkcMap[c] = ukcVn; | |
229 | ||
230 | for (i=0; AscVnLexiList[i].asc; i++) { | |
231 | UkcMap[AscVnLexiList[i].asc] = ukcVn; | |
232 | } | |
233 | ||
234 | UkcMap[(unsigned char)'j'] = ukcNonVn; | |
235 | UkcMap[(unsigned char)'J'] = ukcNonVn; | |
236 | UkcMap[(unsigned char)'f'] = ukcNonVn; | |
237 | UkcMap[(unsigned char)'F'] = ukcNonVn; | |
238 | UkcMap[(unsigned char)'w'] = ukcNonVn; | |
239 | UkcMap[(unsigned char)'W'] = ukcNonVn; | |
240 | ||
241 | int count = sizeof(WordBreakSyms)/sizeof(unsigned char); | |
242 | for (i = 0; i < count; i++) | |
243 | UkcMap[WordBreakSyms[i]] = ukcWordBreak; | |
244 | ||
245 | //Calculate IsoVnLexiMap | |
246 | for (i = 0; i < 256; i++) { | |
247 | IsoVnLexiMap[i] = vnl_nonVnChar; | |
248 | } | |
249 | ||
250 | for (i = 0; AscVnLexiList[i].asc; i++) { | |
251 | IsoVnLexiMap[AscVnLexiList[i].asc] = AscVnLexiList[i].lexi; | |
252 | } | |
253 | ||
254 | for (c = 'a'; c <= 'z'; c++) { | |
255 | IsoVnLexiMap[c] = AZLexiLower[c - 'a']; | |
256 | } | |
257 | ||
258 | for (c = 'A'; c <= 'Z'; c++) { | |
259 | IsoVnLexiMap[c] = AZLexiUpper[c - 'A']; | |
260 | } | |
261 | } | |
262 | ||
263 | //------------------------------------------- | |
264 | void UkInputProcessor::init() | |
265 | { | |
266 | if (!ClassifierTableInitialized) { | |
267 | SetupInputClassifierTable(); | |
268 | ClassifierTableInitialized = true; | |
269 | } | |
270 | setIM(UkTelex); | |
271 | } | |
272 | ||
273 | //------------------------------------------- | |
274 | int UkInputProcessor::setIM(UkInputMethod im) | |
275 | { | |
276 | m_im = im; | |
277 | switch (im) { | |
278 | case UkTelex: | |
279 | useBuiltIn(TelexMethodMapping); | |
280 | break; | |
281 | case UkSimpleTelex: | |
282 | useBuiltIn(SimpleTelexMethodMapping); | |
283 | break; | |
284 | case UkSimpleTelex2: | |
285 | useBuiltIn(SimpleTelex2MethodMapping); | |
286 | break; | |
287 | case UkVni: | |
288 | useBuiltIn(VniMethodMapping); | |
289 | break; | |
290 | case UkViqr: | |
291 | useBuiltIn(VIQRMethodMapping); | |
292 | break; | |
293 | case UkMsVi: | |
294 | useBuiltIn(MsViMethodMapping); | |
295 | break; | |
296 | default: | |
297 | m_im = UkTelex; | |
298 | useBuiltIn(TelexMethodMapping); | |
299 | } | |
300 | return 1; | |
301 | } | |
302 | ||
303 | //------------------------------------------- | |
304 | int UkInputProcessor::setIM(int map[256]) | |
305 | { | |
306 | int i; | |
307 | m_im = UkUsrIM; | |
308 | for (i=0; i<256; i++) | |
309 | m_keyMap[i] = map[i]; | |
310 | return 1; | |
311 | } | |
312 | ||
313 | ||
314 | //------------------------------------------- | |
315 | void UkResetKeyMap(int keyMap[256]) | |
316 | { | |
317 | unsigned int c; | |
318 | for (c=0; c<256; c++) | |
319 | keyMap[c] = vneNormal; | |
320 | } | |
321 | ||
322 | //------------------------------------------- | |
323 | void UkInputProcessor::useBuiltIn(UkKeyMapping *map) | |
324 | { | |
325 | UkResetKeyMap(m_keyMap); | |
326 | for (int i=0; map[i].key; i++) { | |
327 | m_keyMap[map[i].key] = map[i].action; | |
328 | if (map[i].action < vneCount) { | |
329 | if (islower(map[i].key)) { | |
330 | m_keyMap[toupper(map[i].key)] = map[i].action; | |
331 | } | |
332 | else if (isupper(map[i].key)) { | |
333 | m_keyMap[tolower(map[i].key)] = map[i].action; | |
334 | } | |
335 | } | |
336 | } | |
337 | } | |
338 | ||
339 | //------------------------------------------- | |
340 | void UkInputProcessor::keyCodeToEvent(unsigned int keyCode, UkKeyEvent & ev) | |
341 | { | |
342 | ev.keyCode = keyCode; | |
343 | if (keyCode > 255) { | |
344 | ev.evType = vneNormal; | |
345 | ev.vnSym = IsoToVnLexi(keyCode); | |
346 | ev.chType = (ev.vnSym == vnl_nonVnChar)? ukcNonVn : ukcVn; | |
347 | } | |
348 | else { | |
349 | ev.chType = UkcMap[keyCode]; | |
350 | ev.evType = m_keyMap[keyCode]; | |
351 | ||
352 | if (ev.evType >= vneTone0 && ev.evType <= vneTone5) { | |
353 | ev.tone = ev.evType - vneTone0; | |
354 | } | |
355 | ||
356 | if (ev.evType >= vneCount) { | |
357 | ev.chType = ukcVn; | |
358 | ev.vnSym = (VnLexiName)(ev.evType - vneCount); | |
359 | ev.evType = vneMapChar; | |
360 | } | |
361 | else { | |
362 | ev.vnSym = IsoToVnLexi(keyCode); | |
363 | } | |
364 | } | |
365 | } | |
366 | ||
367 | //---------------------------------------------------------------- | |
368 | // This method translates a key stroke to a symbol. | |
369 | // Key strokes are simply considered character input, not action keys as in | |
370 | // keyCodeToEvent method | |
371 | //---------------------------------------------------------------- | |
372 | void UkInputProcessor::keyCodeToSymbol(unsigned int keyCode, UkKeyEvent & ev) | |
373 | { | |
374 | ev.keyCode = keyCode; | |
375 | ev.evType = vneNormal; | |
376 | ev.vnSym = IsoToVnLexi(keyCode); | |
377 | if (keyCode > 255) { | |
378 | ev.chType = (ev.vnSym == vnl_nonVnChar)? ukcNonVn : ukcVn; | |
379 | } | |
380 | else { | |
381 | ev.chType = UkcMap[keyCode]; | |
382 | } | |
383 | } | |
384 | ||
385 | //------------------------------------------- | |
386 | UkCharType UkInputProcessor::getCharType(unsigned int keyCode) | |
387 | { | |
388 | if (keyCode > 255) | |
389 | return (IsoToVnLexi(keyCode) == vnl_nonVnChar) ? ukcNonVn : ukcVn; | |
390 | return UkcMap[keyCode]; | |
391 | } | |
392 | ||
393 | //------------------------------------------- | |
394 | void UkInputProcessor::getKeyMap(int map[256]) | |
395 | { | |
396 | int i; | |
397 | for (i=0; i<256; i++) | |
398 | map[i] = m_keyMap[i]; | |
399 | } | |
400 |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | #ifndef __UK_INPUT_PROCESSOR_H | |
23 | #define __UK_INPUT_PROCESSOR_H | |
24 | ||
25 | #include "keycons.h" | |
26 | #include "vnlexi.h" | |
27 | ||
28 | #if defined(_WIN32) | |
29 | #define DllExport __declspec( dllexport ) | |
30 | #define DllImport __declspec( dllimport ) | |
31 | #if defined(UNIKEYHOOK) | |
32 | #define DllInterface __declspec( dllexport ) | |
33 | #else | |
34 | #define DllInterface __declspec( dllimport ) | |
35 | #endif | |
36 | #else | |
37 | #define DllInterface //not used | |
38 | #define DllExport | |
39 | #define DllImport | |
40 | #endif | |
41 | ||
42 | enum UkKeyEvName { | |
43 | vneRoofAll, vneRoof_a, vneRoof_e, vneRoof_o, | |
44 | vneHookAll, vneHook_uo, vneHook_u, vneHook_o, vneBowl, | |
45 | vneDd, | |
46 | vneTone0, vneTone1, vneTone2, vneTone3, vneTone4, vneTone5, | |
47 | vne_telex_w, //special for telex | |
48 | vneMapChar, //e.g. [ -> u+ , ] -> o+ | |
49 | vneEscChar, | |
50 | vneNormal, //does not belong to any of the above categories | |
51 | vneCount //just to count how many event types there are | |
52 | }; | |
53 | ||
54 | enum UkCharType { | |
55 | ukcVn, | |
56 | ukcWordBreak, | |
57 | ukcNonVn, | |
58 | ukcReset | |
59 | }; | |
60 | ||
61 | struct UkKeyEvent { | |
62 | int evType; | |
63 | UkCharType chType; | |
64 | VnLexiName vnSym; //meaningful only when chType==ukcVn | |
65 | unsigned int keyCode; | |
66 | int tone; //meaningful only when this is a vowel | |
67 | }; | |
68 | ||
69 | struct UkKeyMapping { | |
70 | unsigned char key; | |
71 | int action; | |
72 | }; | |
73 | ||
74 | /////////////////////////////////////////// | |
75 | class UkInputProcessor { | |
76 | ||
77 | public: | |
78 | //don't do anything with constructor, because | |
79 | //this object can be allocated in shared memory | |
80 | //Use init method instead | |
81 | //UkInputProcessor(); | |
82 | ||
83 | void init(); | |
84 | ||
85 | UkInputMethod getIM() | |
86 | { | |
87 | return m_im; | |
88 | } | |
89 | ||
90 | void keyCodeToEvent(unsigned int keyCode, UkKeyEvent & ev); | |
91 | void keyCodeToSymbol(unsigned int keyCode, UkKeyEvent & ev); | |
92 | int setIM(UkInputMethod im); | |
93 | int setIM(int map[256]); | |
94 | void getKeyMap(int map[256]); | |
95 | ||
96 | UkCharType getCharType(unsigned int keyCode); | |
97 | ||
98 | protected: | |
99 | static bool m_classInit; | |
100 | ||
101 | UkInputMethod m_im; | |
102 | int m_keyMap[256]; | |
103 | ||
104 | void useBuiltIn(UkKeyMapping *map); | |
105 | ||
106 | }; | |
107 | ||
108 | void UkResetKeyMap(int keyMap[256]); | |
109 | void SetupInputClassifierTable(); | |
110 | ||
111 | DllInterface extern UkKeyMapping TelexMethodMapping[]; | |
112 | DllInterface extern UkKeyMapping SimpleTelexMethodMapping[]; | |
113 | DllInterface extern UkKeyMapping VniMethodMapping[]; | |
114 | DllInterface extern UkKeyMapping VIQRMethodMapping[]; | |
115 | DllInterface extern UkKeyMapping MsViMethodMapping[]; | |
116 | ||
117 | extern VnLexiName IsoVnLexiMap[]; | |
118 | inline VnLexiName IsoToVnLexi(unsigned int keyCode) | |
119 | { | |
120 | return (keyCode >= 256)? vnl_nonVnChar : IsoVnLexiMap[keyCode]; | |
121 | } | |
122 | ||
123 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | UniKey - Open-source Vietnamese Keyboard | |
3 | Copyright (C) 1998-2004 Pham Kim Long | |
4 | Contact: | |
5 | unikey@gmail.com | |
6 | http://unikey.org | |
7 | ||
8 | This program is free software; you can redistribute it and/or | |
9 | modify it under the terms of the GNU General Public License | |
10 | as published by the Free Software Foundation; either version 2 | |
11 | of the License, or (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
21 | --------------------------------------------------------------------------------*/ | |
22 | #ifndef __KEY_CONS_H | |
23 | #define __KEY_CONS_H | |
24 | ||
25 | // macro table constants | |
26 | #define MAX_MACRO_KEY_LEN 16 | |
27 | //#define MAX_MACRO_TEXT_LEN 256 | |
28 | #define MAX_MACRO_TEXT_LEN 1024 | |
29 | #define MAX_MACRO_ITEMS 1024 | |
30 | #define MAX_MACRO_LINE (MAX_MACRO_TEXT_LEN + MAX_MACRO_KEY_LEN) | |
31 | ||
32 | #define MACRO_MEM_SIZE (1024*128) //128 KB | |
33 | ||
34 | #define CP_US_ANSI 1252 | |
35 | ||
36 | typedef enum {UkTelex, UkVni, UkViqr, UkMsVi, UkUsrIM, UkSimpleTelex, UkSimpleTelex2} UkInputMethod; | |
37 | typedef struct _UnikeyOptions UnikeyOptions; | |
38 | ||
39 | struct _UnikeyOptions | |
40 | { | |
41 | int freeMarking; | |
42 | int modernStyle; | |
43 | int macroEnabled; | |
44 | int useUnicodeClipboard; | |
45 | int alwaysMacro; | |
46 | int strictSpellCheck; | |
47 | int useIME; //for Win32 only | |
48 | int spellCheckEnabled; | |
49 | int autoNonVnRestore; | |
50 | }; | |
51 | ||
52 | #define UKOPT_FLAG_ALL 0xFFFFFFFF | |
53 | #define UKOPT_FLAG_FREE_STYLE 0x00000001 | |
54 | //#define UKOPT_FLAG_MANUAL_TONE 0x00000002 | |
55 | #define UKOPT_FLAG_MODERN 0x00000004 | |
56 | #define UKOPT_FLAG_MACRO_ENABLED 0x00000008 | |
57 | #define UKOPT_FLAG_USE_CLIPBOARD 0x00000010 | |
58 | #define UKOPT_FLAG_ALWAYS_MACRO 0x00000020 | |
59 | #define UKOPT_FLAG_STRICT_SPELL 0x00000040 | |
60 | #define UKOPT_FLAG_USE_IME 0x00000080 | |
61 | #define UKOPT_FLAG_SPELLCHECK_ENABLED 0x00000100 | |
62 | ||
63 | #if defined(WIN32) | |
64 | typedef struct _UnikeySysInfo UnikeySysInfo; | |
65 | struct _UnikeySysInfo | |
66 | { | |
67 | int switchKey; | |
68 | HHOOK keyHook; | |
69 | HHOOK mouseHook; | |
70 | HWND hMainDlg; | |
71 | UINT iconMsgId; | |
72 | HICON hVietIcon,hEnIcon; | |
73 | int unicodePlatform; | |
74 | DWORD winMajorVersion, winMinorVersion; | |
75 | }; | |
76 | #endif | |
77 | ||
78 | typedef enum {UkCharOutput, UkKeyOutput} UkOutputType; | |
79 | ||
80 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include <stdio.h> | |
24 | #include <stdlib.h> | |
25 | #include <string.h> | |
26 | #include <iostream> | |
27 | #include "mactab.h" | |
28 | #include "vnconv.h" | |
29 | ||
30 | using namespace std; | |
31 | #define UKMACRO_VERSION_UTF8 1 | |
32 | ||
33 | //--------------------------------------------------------------- | |
34 | void CMacroTable::init() | |
35 | { | |
36 | m_memSize = MACRO_MEM_SIZE; | |
37 | m_count = 0; | |
38 | m_occupied = 0; | |
39 | } | |
40 | ||
41 | //--------------------------------------------------------------- | |
42 | char *MacCompareStartMem; | |
43 | ||
44 | #define STD_TO_LOWER(x) (((x) >= VnStdCharOffset && \ | |
45 | (x) < (VnStdCharOffset + TOTAL_ALPHA_VNCHARS) && \ | |
46 | !((x) & 1)) ? \ | |
47 | (x+1) : (x)) | |
48 | ||
49 | int macCompare(const void *p1, const void *p2) | |
50 | { | |
51 | StdVnChar *s1 = (StdVnChar *) ((char *)MacCompareStartMem + ((MacroDef *)p1)->keyOffset); | |
52 | StdVnChar *s2 = (StdVnChar *) ((char *)MacCompareStartMem + ((MacroDef *)p2)->keyOffset); | |
53 | ||
54 | int i; | |
55 | StdVnChar ls1, ls2; | |
56 | ||
57 | for (i=0; s1[i] != 0 && s2[i] != 0; i++) { | |
58 | ls1 = STD_TO_LOWER(s1[i]); | |
59 | ls2 = STD_TO_LOWER(s2[i]); | |
60 | if (ls1 > ls2) | |
61 | return 1; | |
62 | if (ls1 < ls2) | |
63 | return -1; | |
64 | /* | |
65 | if (s1[i] > s2[i]) | |
66 | return 1; | |
67 | if (s1[i] < s2[i]) | |
68 | return -1; | |
69 | */ | |
70 | } | |
71 | if (s1[i] == 0) | |
72 | return (s2[i] == 0)? 0 : -1; | |
73 | return 1; | |
74 | } | |
75 | ||
76 | //--------------------------------------------------------------- | |
77 | int macKeyCompare(const void *key, const void *ele) | |
78 | { | |
79 | StdVnChar *s1 = (StdVnChar *)key; | |
80 | StdVnChar *s2 = (StdVnChar *) ((char *)MacCompareStartMem + ((MacroDef *)ele)->keyOffset); | |
81 | ||
82 | StdVnChar ls1, ls2; | |
83 | int i; | |
84 | for (i=0; s1[i] != 0 && s2[i] != 0; i++) { | |
85 | ls1 = STD_TO_LOWER(s1[i]); | |
86 | ls2 = STD_TO_LOWER(s2[i]); | |
87 | if (ls1 > ls2) | |
88 | return 1; | |
89 | if (ls1 < ls2) | |
90 | return -1; | |
91 | /* | |
92 | if (s1[i] > s2[i]) | |
93 | return 1; | |
94 | if (s1[i] < s2[i]) | |
95 | return -1; | |
96 | */ | |
97 | } | |
98 | if (s1[i] == 0) | |
99 | return (s2[i] == 0)? 0 : -1; | |
100 | return 1; | |
101 | } | |
102 | ||
103 | //--------------------------------------------------------------- | |
104 | const StdVnChar *CMacroTable::lookup(StdVnChar *key) | |
105 | { | |
106 | MacCompareStartMem = m_macroMem; | |
107 | MacroDef *p = (MacroDef *)bsearch(key, m_table, m_count, sizeof(MacroDef), macKeyCompare); | |
108 | if (p) | |
109 | return (StdVnChar *)(m_macroMem + p->textOffset); | |
110 | return 0; | |
111 | } | |
112 | ||
113 | //---------------------------------------------------------------------------- | |
114 | // Read header, if it's present in the file. Get the version of the file | |
115 | // If header is absent, go back to the beginning of file and set version to 0 | |
116 | // Return false if reading failed. | |
117 | // | |
118 | // Header format: ;[DO NOT DELETE THIS LINE]***version=n | |
119 | //---------------------------------------------------------------------------- | |
120 | bool CMacroTable::readHeader(FILE *f, int & version) | |
121 | { | |
122 | char line[MAX_MACRO_LINE]; | |
123 | if (!fgets(line, sizeof(line), f)) { | |
124 | if (feof(f)) { | |
125 | fseek(f, 0, SEEK_SET); | |
126 | version = 0; | |
127 | return true; | |
128 | } | |
129 | return false; | |
130 | } | |
131 | ||
132 | //if BOM is available, skip it | |
133 | char *p = line; | |
134 | size_t len = strlen(line); | |
135 | if (len >= 3 && (unsigned char)line[0] == 0xEF && (unsigned char)line[1] == 0xBB && | |
136 | (unsigned char)line[2] == 0xBF) | |
137 | { | |
138 | p += 3; | |
139 | } | |
140 | ||
141 | //read version number | |
142 | p = strstr(p, "***"); | |
143 | if (p) { | |
144 | p += 3; | |
145 | //skip possible spaces | |
146 | while (*p == ' ') p++; | |
147 | if (sscanf(p, "version=%d", &version) == 1) | |
148 | return true; | |
149 | } | |
150 | ||
151 | fseek(f, 0, SEEK_SET); | |
152 | version = 0; | |
153 | return true; | |
154 | } | |
155 | ||
156 | //---------------------------------------------------------------- | |
157 | void CMacroTable::writeHeader(FILE *f) | |
158 | { | |
159 | #if defined(WIN32) | |
160 | fprintf(f, "\xEF\xBB\xBF;DO NOT DELETE THIS LINE*** version=%d ***\n", UKMACRO_VERSION_UTF8); | |
161 | #else | |
162 | fprintf(f, "DO NOT DELETE THIS LINE*** version=%d ***\n", UKMACRO_VERSION_UTF8); | |
163 | #endif | |
164 | } | |
165 | //--------------------------------------------------------------- | |
166 | int CMacroTable::loadFromFile(const char *fname) | |
167 | { | |
168 | FILE *f; | |
169 | #if defined(WIN32) | |
170 | f = _tfopen(fname, _TEXT("rt")); | |
171 | #else | |
172 | f = fopen(fname, "r"); | |
173 | #endif | |
174 | ||
175 | if (f == NULL) | |
176 | return 0; | |
177 | char line[MAX_MACRO_LINE]; | |
178 | size_t len; | |
179 | ||
180 | resetContent(); | |
181 | ||
182 | //read possible header | |
183 | int version; | |
184 | if (!readHeader(f, version)) { | |
185 | version = 0; | |
186 | } | |
187 | ||
188 | while (fgets(line, sizeof(line), f)) { | |
189 | len = strlen(line); | |
190 | if (len > 0 && line[len-1] == '\n') | |
191 | line[len-1] = 0; | |
192 | if (len > 1 && line[len-2] == '\r') | |
193 | line[len-2] = 0; | |
194 | if (version == UKMACRO_VERSION_UTF8) | |
195 | addItem(line, CONV_CHARSET_UNIUTF8); | |
196 | else | |
197 | addItem(line, CONV_CHARSET_VIQR); | |
198 | } | |
199 | fclose(f); | |
200 | MacCompareStartMem = m_macroMem; | |
201 | qsort(m_table, m_count, sizeof(MacroDef), macCompare); | |
202 | // Convert old version | |
203 | if (version != UKMACRO_VERSION_UTF8) { | |
204 | writeToFile(fname); | |
205 | } | |
206 | return 1; | |
207 | } | |
208 | ||
209 | //--------------------------------------------------------------- | |
210 | int CMacroTable::writeToFile(const char *fname) | |
211 | { | |
212 | int ret; | |
213 | int inLen, maxOutLen; | |
214 | FILE *f; | |
215 | #if defined(WIN32) | |
216 | f = _tfopen(fname, _TEXT("wt")); | |
217 | #else | |
218 | f = fopen(fname, "w"); | |
219 | #endif | |
220 | ||
221 | if (f == NULL) | |
222 | return 0; | |
223 | ||
224 | char line[MAX_MACRO_LINE*3]; //1 VnChar may need 3 chars in UTF8 | |
225 | char key[MAX_MACRO_KEY_LEN*3]; | |
226 | char text[MAX_MACRO_TEXT_LEN*3]; | |
227 | ||
228 | writeHeader(f); | |
229 | ||
230 | UKBYTE *p; | |
231 | for (int i=0; i < m_count; i++) { | |
232 | p = (UKBYTE *)m_macroMem + m_table[i].keyOffset; | |
233 | inLen = -1; | |
234 | maxOutLen = sizeof(key); | |
235 | ret = VnConvert(CONV_CHARSET_VNSTANDARD, CONV_CHARSET_UNIUTF8, | |
236 | (UKBYTE *) p, (UKBYTE *)key, | |
237 | &inLen, &maxOutLen); | |
238 | if (ret != 0) | |
239 | continue; | |
240 | ||
241 | p = (UKBYTE *)m_macroMem + m_table[i].textOffset; | |
242 | inLen = -1; | |
243 | maxOutLen = sizeof(text); | |
244 | ret = VnConvert(CONV_CHARSET_VNSTANDARD, CONV_CHARSET_UNIUTF8, | |
245 | p, (UKBYTE *)text, | |
246 | &inLen, &maxOutLen); | |
247 | if (ret != 0) | |
248 | continue; | |
249 | if (i < m_count-1) | |
250 | sprintf(line, "%s:%s\n", key, text); | |
251 | else | |
252 | sprintf(line, "%s:%s", key, text); | |
253 | fputs(line, f); | |
254 | } | |
255 | ||
256 | fclose(f); | |
257 | return 1; | |
258 | } | |
259 | ||
260 | //--------------------------------------------------------------- | |
261 | int CMacroTable::addItem(const void *key, const void *text, int charset) | |
262 | { | |
263 | int ret; | |
264 | int inLen, maxOutLen; | |
265 | int offset = m_occupied; | |
266 | char *p = m_macroMem + offset; | |
267 | ||
268 | if (m_count >= MAX_MACRO_ITEMS) | |
269 | return -1; | |
270 | ||
271 | m_table[m_count].keyOffset = offset; | |
272 | ||
273 | // Convert macro key to VN standard | |
274 | inLen = -1; //input is null-terminated | |
275 | maxOutLen = MAX_MACRO_KEY_LEN * sizeof(StdVnChar); | |
276 | if (maxOutLen + offset > m_memSize) | |
277 | maxOutLen = m_memSize - offset; | |
278 | ret = VnConvert(charset, CONV_CHARSET_VNSTANDARD, | |
279 | (UKBYTE *)key, (UKBYTE *)p, | |
280 | &inLen, &maxOutLen); | |
281 | if (ret != 0) | |
282 | return -1; | |
283 | ||
284 | offset += maxOutLen; | |
285 | p += maxOutLen; | |
286 | ||
287 | //convert macro text to VN standard | |
288 | m_table[m_count].textOffset = offset; | |
289 | inLen = -1; //input is null-terminated | |
290 | maxOutLen = MAX_MACRO_TEXT_LEN * sizeof(StdVnChar); | |
291 | if (maxOutLen + offset > m_memSize) | |
292 | maxOutLen = m_memSize - offset; | |
293 | ret = VnConvert(charset, CONV_CHARSET_VNSTANDARD, | |
294 | (UKBYTE *)text, (UKBYTE *)p, | |
295 | &inLen, &maxOutLen); | |
296 | if (ret != 0) | |
297 | return -1; | |
298 | ||
299 | m_occupied = offset + maxOutLen; | |
300 | m_count++; | |
301 | return (m_count-1); | |
302 | } | |
303 | ||
304 | //--------------------------------------------------------------- | |
305 | // add a new macro into the sorted macro table | |
306 | // item format: key:text (key and text are separated by a colon) | |
307 | //--------------------------------------------------------------- | |
308 | int CMacroTable::addItem(const char *item, int charset) | |
309 | { | |
310 | char key[MAX_MACRO_KEY_LEN]; | |
311 | ||
312 | // Parse the input item | |
313 | char * pos = (char*)strchr(item, ':'); | |
314 | if (pos == NULL) | |
315 | return -1; | |
316 | int keyLen = (int)(pos - item); | |
317 | if (keyLen > MAX_MACRO_KEY_LEN-1) | |
318 | keyLen = MAX_MACRO_KEY_LEN-1; | |
319 | strncpy(key, item, keyLen); | |
320 | key[keyLen] = '\0'; | |
321 | return addItem(key, ++pos, charset); | |
322 | } | |
323 | ||
324 | //--------------------------------------------------------------- | |
325 | void CMacroTable::resetContent() | |
326 | { | |
327 | m_occupied = 0; | |
328 | m_count = 0; | |
329 | } | |
330 | ||
331 | //--------------------------------------------------------------- | |
332 | const StdVnChar *CMacroTable::getKey(int idx) | |
333 | { | |
334 | if (idx < 0 || idx >= m_count) | |
335 | return 0; | |
336 | return (StdVnChar *)(m_macroMem + m_table[idx].keyOffset); | |
337 | } | |
338 | ||
339 | //--------------------------------------------------------------- | |
340 | const StdVnChar *CMacroTable::getText(int idx) | |
341 | { | |
342 | if (idx < 0 || idx >= m_count) | |
343 | return 0; | |
344 | return (StdVnChar *)(m_macroMem + m_table[idx].textOffset); | |
345 | } |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #ifndef __MACRO_TABLE_H | |
24 | #define __MACRO_TABLE_H | |
25 | ||
26 | #include "keycons.h" | |
27 | #include "charset.h" | |
28 | ||
29 | #if defined(_WIN32) | |
30 | #if defined(UNIKEYHOOK) | |
31 | #define DllInterface __declspec( dllexport ) | |
32 | #else | |
33 | #define DllInterface __declspec( dllimport ) | |
34 | #endif | |
35 | #else | |
36 | #define DllInterface //not used | |
37 | #define DllExport | |
38 | #define DllImport | |
39 | #endif | |
40 | ||
41 | struct MacroDef | |
42 | { | |
43 | int keyOffset; | |
44 | int textOffset; | |
45 | }; | |
46 | ||
47 | #if !defined(WIN32) | |
48 | typedef char TCHAR; | |
49 | #endif | |
50 | ||
51 | class DllInterface CMacroTable | |
52 | { | |
53 | public: | |
54 | void init(); | |
55 | int loadFromFile(const char *fname); | |
56 | int writeToFile(const char *fname); | |
57 | ||
58 | const StdVnChar *lookup(StdVnChar *key); | |
59 | const StdVnChar *getKey(int idx); | |
60 | const StdVnChar *getText(int idx); | |
61 | int getCount() { return m_count; } | |
62 | void resetContent(); | |
63 | int addItem(const char *item, int charset); | |
64 | int addItem(const void *key, const void *text, int charset); | |
65 | ||
66 | protected: | |
67 | bool readHeader(FILE *f, int & version); | |
68 | void writeHeader(FILE *f); | |
69 | ||
70 | MacroDef m_table[MAX_MACRO_ITEMS]; | |
71 | char m_macroMem[MACRO_MEM_SIZE]; | |
72 | ||
73 | int m_count; | |
74 | int m_memSize, m_occupied; | |
75 | }; | |
76 | ||
77 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | VnConv: Vietnamese Encoding Converter Library | |
3 | UniKey Project: http://unikey.sourceforge.net | |
4 | Copyleft (C) 1998-2002 Pham Kim Long | |
5 | Contact: longp@cslab.felk.cvut.cz | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License | |
9 | as published by the Free Software Foundation; either version 2 | |
10 | of the License, or (at your option) any later version. | |
11 | ||
12 | This program 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 | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | --------------------------------------------------------------------------------*/ | |
21 | ||
22 | #include "pattern.h" | |
23 | ||
24 | ////////////////////////////////////////////////// | |
25 | // Pattern matching (based on KPM algorithm) | |
26 | ////////////////////////////////////////////////// | |
27 | ||
28 | //---------------------------- | |
29 | void PatternState::reset() | |
30 | { | |
31 | m_pos = 0; | |
32 | m_found = 0; | |
33 | } | |
34 | ||
35 | //---------------------------- | |
36 | void PatternState::init(char *pattern) | |
37 | { | |
38 | m_pos = 0; | |
39 | m_found = 0; | |
40 | m_pattern = pattern; | |
41 | ||
42 | int i=0, j=-1; | |
43 | m_border[i]=j; | |
44 | while (m_pattern[i]) | |
45 | { | |
46 | while (j>=0 && m_pattern[i]!=m_pattern[j]) j=m_border[j]; | |
47 | i++; j++; | |
48 | m_border[i]=j; | |
49 | } | |
50 | } | |
51 | ||
52 | //----------------------------------------------------- | |
53 | //get next input char, returns 1 if pattern is found. | |
54 | //----------------------------------------------------- | |
55 | int PatternState::foundAtNextChar(char ch) | |
56 | { | |
57 | int ret = 0; | |
58 | //int j = m_pos; | |
59 | while (m_pos>=0 && ch!=m_pattern[m_pos]) m_pos=m_border[m_pos]; | |
60 | m_pos++; | |
61 | if (m_pattern[m_pos]==0) { | |
62 | m_found++; | |
63 | m_pos = m_border[m_pos]; | |
64 | ret = 1; | |
65 | } | |
66 | return ret; | |
67 | } | |
68 | ||
69 | //----------------------------------------------------- | |
70 | void PatternList::init(char **patterns, int count) | |
71 | { | |
72 | m_count = count; | |
73 | delete [] m_patterns; | |
74 | m_patterns = new PatternState[count]; | |
75 | for (int i=0; i<count; i++) | |
76 | m_patterns[i].init(patterns[i]); | |
77 | } | |
78 | ||
79 | //----------------------------------------------------- | |
80 | // return the order number of the pattern that is found. | |
81 | // If more than 1 pattern is found, returns any pattern | |
82 | // Returns -1 if no pattern is found | |
83 | //----------------------------------------------------- | |
84 | int PatternList::foundAtNextChar(char ch) | |
85 | { | |
86 | int patternFound = -1; | |
87 | for (int i=0; i<m_count; i++) { | |
88 | if (m_patterns[i].foundAtNextChar(ch)) | |
89 | patternFound = i; | |
90 | } | |
91 | return patternFound; | |
92 | } | |
93 | ||
94 | //----------------------------------------------------- | |
95 | void PatternList::reset() | |
96 | { | |
97 | for (int i=0; i<m_count; i++) | |
98 | m_patterns[i].reset(); | |
99 | } |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | VnConv: Vietnamese Encoding Converter Library | |
3 | UniKey Project: http://unikey.sourceforge.net | |
4 | Copyleft (C) 1998-2002 Pham Kim Long | |
5 | Contact: longp@cslab.felk.cvut.cz | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License | |
9 | as published by the Free Software Foundation; either version 2 | |
10 | of the License, or (at your option) any later version. | |
11 | ||
12 | This program 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 | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | --------------------------------------------------------------------------------*/ | |
21 | ||
22 | #ifndef __PATTERN_H | |
23 | #define __PATTERN_H | |
24 | ||
25 | #if defined(_WIN32) | |
26 | #if defined(UNIKEYHOOK) | |
27 | #define DllInterface __declspec( dllexport ) | |
28 | #else | |
29 | #define DllInterface __declspec( dllimport ) | |
30 | #endif | |
31 | #else | |
32 | #define DllInterface //not used | |
33 | #endif | |
34 | ||
35 | #define MAX_PATTERN_LEN 40 | |
36 | ||
37 | class DllInterface PatternState | |
38 | { | |
39 | public: | |
40 | char *m_pattern; | |
41 | int m_border[MAX_PATTERN_LEN+1]; | |
42 | int m_pos; | |
43 | int m_found; | |
44 | void init(char *pattern); | |
45 | void reset(); | |
46 | int foundAtNextChar(char ch); //get next input char, returns 1 if pattern is found. | |
47 | }; | |
48 | ||
49 | class DllInterface PatternList | |
50 | { | |
51 | public: | |
52 | PatternState *m_patterns; | |
53 | int m_count; | |
54 | void init(char **patterns, int count); | |
55 | int foundAtNextChar(char ch); | |
56 | void reset(); | |
57 | ||
58 | PatternList() { | |
59 | m_count = 0; | |
60 | m_patterns = 0; | |
61 | } | |
62 | ||
63 | ~PatternList() | |
64 | { | |
65 | if (m_patterns) | |
66 | delete [] m_patterns; | |
67 | } | |
68 | }; | |
69 | ||
70 | ||
71 | #endif |
0 | // -*- mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | #include <iostream> | |
26 | #include "keycons.h" | |
27 | ||
28 | /* | |
29 | #if defined(_WIN32) | |
30 | #include "keyhook.h" | |
31 | #endif | |
32 | */ | |
33 | ||
34 | #include "vnlexi.h" | |
35 | #include "ukengine.h" | |
36 | ||
37 | #include "charset.h" | |
38 | ||
39 | using namespace std; | |
40 | ||
41 | #define ENTER_CHAR 13 | |
42 | #define IS_ODD(x) (x & 1) | |
43 | #define IS_EVEN(x) (!(x & 1)) | |
44 | ||
45 | #define IS_STD_VN_LOWER(x) ((x) >= VnStdCharOffset && (x) < (VnStdCharOffset + TOTAL_ALPHA_VNCHARS) && IS_ODD(x)) | |
46 | #define IS_STD_VN_UPPER(x) ((x) >= VnStdCharOffset && (x) < (VnStdCharOffset + TOTAL_ALPHA_VNCHARS) && IS_EVEN(x)) | |
47 | ||
48 | bool IsVnVowel[vnl_lastChar]; | |
49 | ||
50 | extern VnLexiName AZLexiUpper[]; //defined in inputproc.cpp | |
51 | extern VnLexiName AZLexiLower[]; | |
52 | ||
53 | //see vnconv/data.cpp for explanation of these characters | |
54 | unsigned char SpecialWesternChars[] = { | |
55 | 0x80, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, | |
56 | 0x89, 0x8A, 0x8B, 0x8C, 0x8E, 0x91, 0x92, 0x93, | |
57 | 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, | |
58 | 0x9C, 0x9E, 0x9F, 0x00}; | |
59 | ||
60 | StdVnChar IsoStdVnCharMap[256]; | |
61 | ||
62 | inline StdVnChar IsoToStdVnChar(int keyCode) | |
63 | { | |
64 | return (keyCode < 256)? IsoStdVnCharMap[keyCode] : keyCode; | |
65 | } | |
66 | ||
67 | struct VowelSeqInfo { | |
68 | int len; | |
69 | int complete; | |
70 | int conSuffix; //allow consonnant suffix | |
71 | VnLexiName v[3]; | |
72 | VowelSeq sub[3]; | |
73 | ||
74 | int roofPos; | |
75 | VowelSeq withRoof; | |
76 | ||
77 | int hookPos; | |
78 | VowelSeq withHook; //hook & bowl | |
79 | }; | |
80 | ||
81 | VowelSeqInfo VSeqList[] = { | |
82 | {1, 1, 1, {vnl_a, vnl_nonVnChar, vnl_nonVnChar}, {vs_a, vs_nil, vs_nil}, -1, vs_ar, -1, vs_ab}, | |
83 | {1, 1, 1, {vnl_ar, vnl_nonVnChar, vnl_nonVnChar}, {vs_ar, vs_nil, vs_nil}, 0, vs_nil, -1, vs_ab}, | |
84 | {1, 1, 1, {vnl_ab, vnl_nonVnChar, vnl_nonVnChar}, {vs_ab, vs_nil, vs_nil}, -1, vs_ar, 0, vs_nil}, | |
85 | {1, 1, 1, {vnl_e, vnl_nonVnChar, vnl_nonVnChar}, {vs_e, vs_nil, vs_nil}, -1, vs_er, -1, vs_nil}, | |
86 | {1, 1, 1, {vnl_er, vnl_nonVnChar, vnl_nonVnChar}, {vs_er, vs_nil, vs_nil}, 0, vs_nil, -1, vs_nil}, | |
87 | {1, 1, 1, {vnl_i, vnl_nonVnChar, vnl_nonVnChar}, {vs_i, vs_nil, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
88 | {1, 1, 1, {vnl_o, vnl_nonVnChar, vnl_nonVnChar}, {vs_o, vs_nil, vs_nil}, -1, vs_or, -1, vs_oh}, | |
89 | {1, 1, 1, {vnl_or, vnl_nonVnChar, vnl_nonVnChar}, {vs_or, vs_nil, vs_nil}, 0, vs_nil, -1, vs_oh}, | |
90 | {1, 1, 1, {vnl_oh, vnl_nonVnChar, vnl_nonVnChar}, {vs_oh, vs_nil, vs_nil}, -1, vs_or, 0, vs_nil}, | |
91 | {1, 1, 1, {vnl_u, vnl_nonVnChar, vnl_nonVnChar}, {vs_u, vs_nil, vs_nil}, -1, vs_nil, -1, vs_uh}, | |
92 | {1, 1, 1, {vnl_uh, vnl_nonVnChar, vnl_nonVnChar}, {vs_uh, vs_nil, vs_nil}, -1, vs_nil, 0, vs_nil}, | |
93 | {1, 1, 1, {vnl_y, vnl_nonVnChar, vnl_nonVnChar}, {vs_y, vs_nil, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
94 | {2, 1, 0, {vnl_a, vnl_i, vnl_nonVnChar}, {vs_a, vs_ai, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
95 | {2, 1, 0, {vnl_a, vnl_o, vnl_nonVnChar}, {vs_a, vs_ao, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
96 | {2, 1, 0, {vnl_a, vnl_u, vnl_nonVnChar}, {vs_a, vs_au, vs_nil}, -1, vs_aru, -1, vs_nil}, | |
97 | {2, 1, 0, {vnl_a, vnl_y, vnl_nonVnChar}, {vs_a, vs_ay, vs_nil}, -1, vs_ary, -1, vs_nil}, | |
98 | {2, 1, 0, {vnl_ar, vnl_u, vnl_nonVnChar}, {vs_ar, vs_aru, vs_nil}, 0, vs_nil, -1, vs_nil}, | |
99 | {2, 1, 0, {vnl_ar, vnl_y, vnl_nonVnChar}, {vs_ar, vs_ary, vs_nil}, 0, vs_nil, -1, vs_nil}, | |
100 | {2, 1, 0, {vnl_e, vnl_o, vnl_nonVnChar}, {vs_e, vs_eo, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
101 | {2, 0, 0, {vnl_e, vnl_u, vnl_nonVnChar}, {vs_e, vs_eu, vs_nil}, -1, vs_eru, -1, vs_nil}, | |
102 | {2, 1, 0, {vnl_er, vnl_u, vnl_nonVnChar}, {vs_er, vs_eru, vs_nil}, 0, vs_nil, -1, vs_nil}, | |
103 | {2, 1, 0, {vnl_i, vnl_a, vnl_nonVnChar}, {vs_i, vs_ia, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
104 | {2, 0, 1, {vnl_i, vnl_e, vnl_nonVnChar}, {vs_i, vs_ie, vs_nil}, -1, vs_ier, -1, vs_nil}, | |
105 | {2, 1, 1, {vnl_i, vnl_er, vnl_nonVnChar}, {vs_i, vs_ier, vs_nil}, 1, vs_nil, -1, vs_nil}, | |
106 | {2, 1, 0, {vnl_i, vnl_u, vnl_nonVnChar}, {vs_i, vs_iu, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
107 | {2, 1, 1, {vnl_o, vnl_a, vnl_nonVnChar}, {vs_o, vs_oa, vs_nil}, -1, vs_nil, -1, vs_oab}, | |
108 | {2, 1, 1, {vnl_o, vnl_ab, vnl_nonVnChar}, {vs_o, vs_oab, vs_nil}, -1, vs_nil, 1, vs_nil}, | |
109 | {2, 1, 1, {vnl_o, vnl_e, vnl_nonVnChar}, {vs_o, vs_oe, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
110 | {2, 1, 0, {vnl_o, vnl_i, vnl_nonVnChar}, {vs_o, vs_oi, vs_nil}, -1, vs_ori, -1, vs_ohi}, | |
111 | {2, 1, 0, {vnl_or, vnl_i, vnl_nonVnChar}, {vs_or, vs_ori, vs_nil}, 0, vs_nil, -1, vs_ohi}, | |
112 | {2, 1, 0, {vnl_oh, vnl_i, vnl_nonVnChar}, {vs_oh, vs_ohi, vs_nil}, -1, vs_ori, 0, vs_nil}, | |
113 | {2, 1, 1, {vnl_u, vnl_a, vnl_nonVnChar}, {vs_u, vs_ua, vs_nil}, -1, vs_uar, -1, vs_uha}, | |
114 | {2, 1, 1, {vnl_u, vnl_ar, vnl_nonVnChar}, {vs_u, vs_uar, vs_nil}, 1, vs_nil, -1, vs_nil}, | |
115 | {2, 0, 1, {vnl_u, vnl_e, vnl_nonVnChar}, {vs_u, vs_ue, vs_nil}, -1, vs_uer, -1, vs_nil}, | |
116 | {2, 1, 1, {vnl_u, vnl_er, vnl_nonVnChar}, {vs_u, vs_uer, vs_nil}, 1, vs_nil, -1, vs_nil}, | |
117 | {2, 1, 0, {vnl_u, vnl_i, vnl_nonVnChar}, {vs_u, vs_ui, vs_nil}, -1, vs_nil, -1, vs_uhi}, | |
118 | {2, 0, 1, {vnl_u, vnl_o, vnl_nonVnChar}, {vs_u, vs_uo, vs_nil}, -1, vs_uor, -1, vs_uho}, | |
119 | {2, 1, 1, {vnl_u, vnl_or, vnl_nonVnChar}, {vs_u, vs_uor, vs_nil}, 1, vs_nil, -1, vs_uoh}, | |
120 | {2, 1, 1, {vnl_u, vnl_oh, vnl_nonVnChar}, {vs_u, vs_uoh, vs_nil}, -1, vs_uor, 1, vs_uhoh}, | |
121 | {2, 0, 0, {vnl_u, vnl_u, vnl_nonVnChar}, {vs_u, vs_uu, vs_nil}, -1, vs_nil, -1, vs_uhu}, | |
122 | {2, 1, 1, {vnl_u, vnl_y, vnl_nonVnChar}, {vs_u, vs_uy, vs_nil}, -1, vs_nil, -1, vs_nil}, | |
123 | {2, 1, 0, {vnl_uh, vnl_a, vnl_nonVnChar}, {vs_uh, vs_uha, vs_nil}, -1, vs_nil, 0, vs_nil}, | |
124 | {2, 1, 0, {vnl_uh, vnl_i, vnl_nonVnChar}, {vs_uh, vs_uhi, vs_nil}, -1, vs_nil, 0, vs_nil}, | |
125 | {2, 0, 1, {vnl_uh, vnl_o, vnl_nonVnChar}, {vs_uh, vs_uho, vs_nil}, -1, vs_nil, 0, vs_uhoh}, | |
126 | {2, 1, 1, {vnl_uh, vnl_oh, vnl_nonVnChar}, {vs_uh, vs_uhoh, vs_nil}, -1, vs_nil, 0, vs_nil}, | |
127 | {2, 1, 0, {vnl_uh, vnl_u, vnl_nonVnChar}, {vs_uh, vs_uhu, vs_nil}, -1, vs_nil, 0, vs_nil}, | |
128 | {2, 0, 1, {vnl_y, vnl_e, vnl_nonVnChar}, {vs_y, vs_ye, vs_nil}, -1, vs_yer, -1, vs_nil}, | |
129 | {2, 1, 1, {vnl_y, vnl_er, vnl_nonVnChar}, {vs_y, vs_yer, vs_nil}, 1, vs_nil, -1, vs_nil}, | |
130 | {3, 0, 0, {vnl_i, vnl_e, vnl_u}, {vs_i, vs_ie, vs_ieu}, -1, vs_ieru, -1, vs_nil}, | |
131 | {3, 1, 0, {vnl_i, vnl_er, vnl_u}, {vs_i, vs_ier, vs_ieru}, 1, vs_nil, -1, vs_nil}, | |
132 | {3, 1, 0, {vnl_o, vnl_a, vnl_i}, {vs_o, vs_oa, vs_oai}, -1, vs_nil, -1, vs_nil}, | |
133 | {3, 1, 0, {vnl_o, vnl_a, vnl_y}, {vs_o, vs_oa, vs_oay}, -1, vs_nil, -1, vs_nil}, | |
134 | {3, 1, 0, {vnl_o, vnl_e, vnl_o}, {vs_o, vs_oe, vs_oeo}, -1, vs_nil, -1, vs_nil}, | |
135 | {3, 0, 0, {vnl_u, vnl_a, vnl_y}, {vs_u, vs_ua, vs_uay}, -1, vs_uary, -1, vs_nil}, | |
136 | {3, 1, 0, {vnl_u, vnl_ar, vnl_y}, {vs_u, vs_uar, vs_uary}, 1, vs_nil, -1, vs_nil}, | |
137 | {3, 0, 0, {vnl_u, vnl_o, vnl_i}, {vs_u, vs_uo, vs_uoi}, -1, vs_uori, -1, vs_uhoi}, | |
138 | {3, 0, 0, {vnl_u, vnl_o, vnl_u}, {vs_u, vs_uo, vs_uou}, -1, vs_nil, -1, vs_uhou}, | |
139 | {3, 1, 0, {vnl_u, vnl_or, vnl_i}, {vs_u, vs_uor, vs_uori}, 1, vs_nil, -1, vs_uohi}, | |
140 | {3, 0, 0, {vnl_u, vnl_oh, vnl_i}, {vs_u, vs_uoh, vs_uohi}, -1, vs_uori, 1, vs_uhohi}, | |
141 | {3, 0, 0, {vnl_u, vnl_oh, vnl_u}, {vs_u, vs_uoh, vs_uohu}, -1, vs_nil, 1, vs_uhohu}, | |
142 | {3, 1, 0, {vnl_u, vnl_y, vnl_a}, {vs_u, vs_uy, vs_uya}, -1, vs_nil, -1, vs_nil}, | |
143 | {3, 0, 1, {vnl_u, vnl_y, vnl_e}, {vs_u, vs_uy, vs_uye}, -1, vs_uyer, -1, vs_nil}, | |
144 | {3, 1, 1, {vnl_u, vnl_y, vnl_er}, {vs_u, vs_uy, vs_uyer}, 2, vs_nil, -1, vs_nil}, | |
145 | {3, 1, 0, {vnl_u, vnl_y, vnl_u}, {vs_u, vs_uy, vs_uyu}, -1, vs_nil, -1, vs_nil}, | |
146 | {3, 0, 0, {vnl_uh, vnl_o, vnl_i}, {vs_uh, vs_uho, vs_uhoi}, -1, vs_nil, 0, vs_uhohi}, | |
147 | {3, 0, 0, {vnl_uh, vnl_o, vnl_u}, {vs_uh, vs_uho, vs_uhou}, -1, vs_nil, 0, vs_uhohu}, | |
148 | {3, 1, 0, {vnl_uh, vnl_oh, vnl_i}, {vs_uh, vs_uhoh, vs_uhohi}, -1, vs_nil, 0, vs_nil}, | |
149 | {3, 1, 0, {vnl_uh, vnl_oh, vnl_u}, {vs_uh, vs_uhoh, vs_uhohu}, -1, vs_nil, 0, vs_nil}, | |
150 | {3, 0, 0, {vnl_y, vnl_e, vnl_u}, {vs_y, vs_ye, vs_yeu}, -1, vs_yeru, -1, vs_nil}, | |
151 | {3, 1, 0, {vnl_y, vnl_er, vnl_u}, {vs_y, vs_yer, vs_yeru}, 1, vs_nil, -1, vs_nil} | |
152 | }; | |
153 | ||
154 | struct ConSeqInfo { | |
155 | int len; | |
156 | VnLexiName c[3]; | |
157 | bool suffix; | |
158 | }; | |
159 | ||
160 | ConSeqInfo CSeqList[] = { | |
161 | {1, {vnl_b, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
162 | {1, {vnl_c, vnl_nonVnChar, vnl_nonVnChar}, true}, | |
163 | {2, {vnl_c, vnl_h, vnl_nonVnChar}, true}, | |
164 | {1, {vnl_d, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
165 | {1, {vnl_dd, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
166 | {2, {vnl_d, vnl_z, vnl_nonVnChar}, false}, | |
167 | {1, {vnl_g, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
168 | {2, {vnl_g, vnl_h, vnl_nonVnChar}, false}, | |
169 | {2, {vnl_g, vnl_i, vnl_nonVnChar}, false}, | |
170 | {3, {vnl_g, vnl_i, vnl_n}, false}, | |
171 | {1, {vnl_h, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
172 | {1, {vnl_k, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
173 | {2, {vnl_k, vnl_h, vnl_nonVnChar}, false}, | |
174 | {1, {vnl_l, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
175 | {1, {vnl_m, vnl_nonVnChar, vnl_nonVnChar}, true}, | |
176 | {1, {vnl_n, vnl_nonVnChar, vnl_nonVnChar}, true}, | |
177 | {2, {vnl_n, vnl_g, vnl_nonVnChar}, true}, | |
178 | {3, {vnl_n, vnl_g, vnl_h}, false}, | |
179 | {2, {vnl_n, vnl_h, vnl_nonVnChar}, true}, | |
180 | {1, {vnl_p, vnl_nonVnChar, vnl_nonVnChar}, true}, | |
181 | {2, {vnl_p, vnl_h, vnl_nonVnChar}, false}, | |
182 | {1, {vnl_q, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
183 | {2, {vnl_q, vnl_u, vnl_nonVnChar}, false}, | |
184 | {1, {vnl_r, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
185 | {1, {vnl_s, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
186 | {1, {vnl_t, vnl_nonVnChar, vnl_nonVnChar}, true}, | |
187 | {2, {vnl_t, vnl_h, vnl_nonVnChar}, false}, | |
188 | {2, {vnl_t, vnl_r, vnl_nonVnChar}, false}, | |
189 | {1, {vnl_v, vnl_nonVnChar, vnl_nonVnChar}, false}, | |
190 | {1, {vnl_x, vnl_nonVnChar, vnl_nonVnChar}, false} | |
191 | }; | |
192 | ||
193 | const int VSeqCount = sizeof(VSeqList)/sizeof(VowelSeqInfo); | |
194 | struct VSeqPair { | |
195 | VnLexiName v[3]; | |
196 | VowelSeq vs; | |
197 | }; | |
198 | VSeqPair SortedVSeqList[VSeqCount]; | |
199 | ||
200 | const int CSeqCount = sizeof(CSeqList)/sizeof(ConSeqInfo); | |
201 | struct CSeqPair { | |
202 | VnLexiName c[3]; | |
203 | ConSeq cs; | |
204 | }; | |
205 | CSeqPair SortedCSeqList[CSeqCount]; | |
206 | ||
207 | struct VCPair { | |
208 | VowelSeq v; | |
209 | ConSeq c; | |
210 | }; | |
211 | ||
212 | VCPair VCPairList [] = { | |
213 | {vs_a, cs_c}, {vs_a, cs_ch}, {vs_a, cs_m}, {vs_a, cs_n}, {vs_a, cs_ng}, | |
214 | {vs_a, cs_nh}, {vs_a, cs_p}, {vs_a, cs_t}, | |
215 | {vs_ar, cs_c}, {vs_ar, cs_m}, {vs_ar, cs_n}, {vs_ar, cs_ng}, {vs_ar, cs_p}, {vs_ar, cs_t}, | |
216 | {vs_ab, cs_c}, {vs_ab, cs_m}, {vs_ab, cs_n}, {vs_ab, cs_ng}, {vs_ab, cs_p}, {vs_ab, cs_t}, | |
217 | ||
218 | {vs_e, cs_c}, {vs_e, cs_ch}, {vs_e, cs_m}, {vs_e, cs_n}, {vs_e, cs_ng}, | |
219 | {vs_e, cs_nh}, {vs_e, cs_p}, {vs_e, cs_t}, | |
220 | {vs_er, cs_c}, {vs_er, cs_ch}, {vs_er, cs_m}, {vs_er, cs_n}, {vs_er, cs_nh}, | |
221 | {vs_er, cs_p}, {vs_er, cs_t}, | |
222 | ||
223 | {vs_i, cs_c}, {vs_i, cs_ch}, {vs_i, cs_m}, {vs_i, cs_n}, {vs_i, cs_nh}, {vs_i, cs_p}, {vs_i, cs_t}, | |
224 | ||
225 | {vs_o, cs_c}, {vs_o, cs_m}, {vs_o, cs_n}, {vs_o, cs_ng}, {vs_o, cs_p}, {vs_o, cs_t}, | |
226 | {vs_or, cs_c}, {vs_or, cs_m}, {vs_or, cs_n}, {vs_or, cs_ng}, {vs_or, cs_p}, {vs_or, cs_t}, | |
227 | {vs_oh, cs_m}, {vs_oh, cs_n}, {vs_oh, cs_p}, {vs_oh, cs_t}, | |
228 | ||
229 | {vs_u, cs_c}, {vs_u, cs_m}, {vs_u, cs_n}, {vs_u, cs_ng}, {vs_u, cs_p}, {vs_u, cs_t}, | |
230 | {vs_uh, cs_c}, {vs_uh, cs_m}, {vs_uh, cs_n}, {vs_uh, cs_ng}, {vs_uh, cs_t}, | |
231 | ||
232 | {vs_y, cs_t}, | |
233 | {vs_ie, cs_c}, {vs_ie, cs_m}, {vs_ie, cs_n}, {vs_ie, cs_ng}, {vs_ie, cs_p}, {vs_ie, cs_t}, | |
234 | {vs_ier, cs_c}, {vs_ier, cs_m}, {vs_ier, cs_n}, {vs_ier, cs_ng}, {vs_ier, cs_p}, {vs_ier, cs_t}, | |
235 | ||
236 | {vs_oa, cs_c}, {vs_oa, cs_ch}, {vs_oa, cs_m}, {vs_oa, cs_n}, {vs_oa, cs_ng}, | |
237 | {vs_oa, cs_nh}, {vs_oa, cs_p}, {vs_oa, cs_t}, | |
238 | {vs_oab, cs_c}, {vs_oab, cs_m}, {vs_oab, cs_n}, {vs_oab, cs_ng}, {vs_oab, cs_t}, | |
239 | ||
240 | {vs_oe, cs_n}, {vs_oe, cs_t}, | |
241 | ||
242 | {vs_ua, cs_n}, {vs_ua, cs_ng}, {vs_ua, cs_t}, | |
243 | {vs_uar, cs_n}, {vs_uar, cs_ng}, {vs_uar, cs_t}, | |
244 | ||
245 | {vs_ue, cs_c}, {vs_ue, cs_ch}, {vs_ue, cs_n}, {vs_ue, cs_nh}, | |
246 | {vs_uer, cs_c}, {vs_uer, cs_ch}, {vs_uer, cs_n}, {vs_uer, cs_nh}, | |
247 | ||
248 | {vs_uo, cs_c}, {vs_uo, cs_m}, {vs_uo, cs_n}, {vs_uo, cs_ng}, {vs_uo, cs_p}, {vs_uo, cs_t}, | |
249 | {vs_uor, cs_c}, {vs_uor, cs_m}, {vs_uor, cs_n}, {vs_uor, cs_ng}, {vs_uor, cs_t}, | |
250 | {vs_uho, cs_c}, {vs_uho, cs_m}, {vs_uho, cs_n}, {vs_uho, cs_ng}, {vs_uho, cs_p}, {vs_uho, cs_t}, | |
251 | {vs_uhoh, cs_c}, {vs_uhoh, cs_m}, {vs_uhoh, cs_n}, {vs_uhoh, cs_ng}, {vs_uhoh, cs_p}, {vs_uhoh, cs_t}, | |
252 | ||
253 | {vs_uy, cs_c}, {vs_uy, cs_ch}, {vs_uy, cs_n}, {vs_uy, cs_nh}, {vs_uy, cs_p}, {vs_uy, cs_t}, | |
254 | ||
255 | {vs_ye, cs_m}, {vs_ye, cs_n}, {vs_ye, cs_ng}, {vs_ye, cs_p}, {vs_ye, cs_t}, | |
256 | {vs_yer, cs_m}, {vs_yer, cs_n}, {vs_yer, cs_ng}, {vs_yer, cs_t}, | |
257 | ||
258 | {vs_uye, cs_n}, {vs_uye, cs_t}, | |
259 | {vs_uyer, cs_n}, {vs_uyer, cs_t} | |
260 | ||
261 | }; | |
262 | ||
263 | const int VCPairCount = sizeof(VCPairList)/sizeof(VCPair); | |
264 | ||
265 | //TODO: auto-complete: e.g. luan -> lua^n | |
266 | ||
267 | typedef int (UkEngine::* UkKeyProc)(UkKeyEvent & ev); | |
268 | ||
269 | UkKeyProc UkKeyProcList[vneCount] = { | |
270 | &UkEngine::processRoof, //vneRoofAll | |
271 | &UkEngine::processRoof, //vneRoof_a | |
272 | &UkEngine::processRoof, //vneRoof_e | |
273 | &UkEngine::processRoof, //vneRoof_o | |
274 | &UkEngine::processHook, //vneHookAll | |
275 | &UkEngine::processHook, //vneHook_uo | |
276 | &UkEngine::processHook, //vneHook_u | |
277 | &UkEngine::processHook, //vneHook_o | |
278 | &UkEngine::processHook, //vneBowl | |
279 | &UkEngine::processDd, //vneDd | |
280 | &UkEngine::processTone, //vneTone0 | |
281 | &UkEngine::processTone, //vneTone1 | |
282 | &UkEngine::processTone, //vneTone2 | |
283 | &UkEngine::processTone, //vneTone3 | |
284 | &UkEngine::processTone, //vneTone4 | |
285 | &UkEngine::processTone, //vneTone5 | |
286 | &UkEngine::processTelexW, //vne_telex_w | |
287 | &UkEngine::processMapChar, //vneMapChar | |
288 | &UkEngine::processEscChar, //vneEscChar | |
289 | &UkEngine::processAppend //vneNormal | |
290 | }; | |
291 | ||
292 | ||
293 | VowelSeq lookupVSeq(VnLexiName v1, VnLexiName v2 = vnl_nonVnChar, VnLexiName v3 = vnl_nonVnChar); | |
294 | ConSeq lookupCSeq(VnLexiName c1, VnLexiName c2 = vnl_nonVnChar, VnLexiName c3 = vnl_nonVnChar); | |
295 | ||
296 | bool UkEngine::m_classInit = false; | |
297 | ||
298 | //------------------------------------------------ | |
299 | int tripleVowelCompare(const void *p1, const void *p2) | |
300 | { | |
301 | VSeqPair *t1 = (VSeqPair *)p1; | |
302 | VSeqPair *t2 = (VSeqPair *)p2; | |
303 | ||
304 | for (int i=0; i<3; i++) { | |
305 | if (t1->v[i] < t2->v[i]) | |
306 | return -1; | |
307 | if (t1->v[i] > t2->v[i]) | |
308 | return 1; | |
309 | } | |
310 | return 0; | |
311 | } | |
312 | ||
313 | //------------------------------------------------ | |
314 | int tripleConCompare(const void *p1, const void *p2) | |
315 | { | |
316 | CSeqPair *t1 = (CSeqPair *)p1; | |
317 | CSeqPair *t2 = (CSeqPair *)p2; | |
318 | ||
319 | for (int i=0; i<3; i++) { | |
320 | if (t1->c[i] < t2->c[i]) | |
321 | return -1; | |
322 | if (t1->c[i] > t2->c[i]) | |
323 | return 1; | |
324 | } | |
325 | return 0; | |
326 | } | |
327 | ||
328 | //------------------------------------------------ | |
329 | int VCPairCompare(const void *p1, const void *p2) | |
330 | { | |
331 | VCPair *t1 = (VCPair *)p1; | |
332 | VCPair *t2 = (VCPair *)p2; | |
333 | ||
334 | if (t1->v < t2->v) | |
335 | return -1; | |
336 | if (t1->v > t2->v) | |
337 | return 1; | |
338 | ||
339 | if (t1->c < t2->c) | |
340 | return -1; | |
341 | if (t1->c > t2->c) | |
342 | return 1; | |
343 | return 0; | |
344 | } | |
345 | ||
346 | //---------------------------------------------------------- | |
347 | bool isValidCV(ConSeq c, VowelSeq v) | |
348 | { | |
349 | if (c == cs_nil || v == vs_nil) | |
350 | return true; | |
351 | ||
352 | VowelSeqInfo & vInfo = VSeqList[v]; | |
353 | ||
354 | if ((c == cs_gi && vInfo.v[0] == vnl_i) || | |
355 | (c == cs_qu && vInfo.v[0] == vnl_u)) | |
356 | return false; // gi doesn't go with i, qu doesn't go with u | |
357 | ||
358 | if (c == cs_k) { | |
359 | // k can only go with the following vowel sequences | |
360 | static VowelSeq kVseq[] = {vs_e, vs_i, vs_y, vs_er, vs_eo, vs_eu, | |
361 | vs_eru, vs_ia, vs_ie, vs_ier, vs_ieu, vs_ieru, vs_nil}; | |
362 | int i; | |
363 | for (i=0; kVseq[i] != vs_nil && kVseq[i] != v; i++); | |
364 | return (kVseq[i] != vs_nil); | |
365 | } | |
366 | ||
367 | //More checks | |
368 | return true; | |
369 | } | |
370 | ||
371 | //---------------------------------------------------------- | |
372 | bool isValidVC(VowelSeq v, ConSeq c) | |
373 | { | |
374 | if (v == vs_nil || c == cs_nil) | |
375 | return true; | |
376 | ||
377 | VowelSeqInfo & vInfo = VSeqList[v]; | |
378 | if (!vInfo.conSuffix) | |
379 | return false; | |
380 | ||
381 | ConSeqInfo & cInfo = CSeqList[c]; | |
382 | if (!cInfo.suffix) | |
383 | return false; | |
384 | ||
385 | VCPair p; | |
386 | p.v = v; | |
387 | p.c = c; | |
388 | if (bsearch(&p, VCPairList, VCPairCount, sizeof(VCPair), VCPairCompare)) | |
389 | return true; | |
390 | ||
391 | return false; | |
392 | } | |
393 | ||
394 | //---------------------------------------------------------- | |
395 | bool isValidCVC(ConSeq c1, VowelSeq v, ConSeq c2) | |
396 | { | |
397 | if (v == vs_nil) | |
398 | return (c1 == cs_nil || c2 != cs_nil); | |
399 | ||
400 | if (c1 == cs_nil) | |
401 | return isValidVC(v, c2); | |
402 | ||
403 | if (c2 == cs_nil) | |
404 | return isValidCV(c1, v); | |
405 | ||
406 | bool okCV = isValidCV(c1, v); | |
407 | bool okVC = isValidVC(v, c2); | |
408 | ||
409 | if (okCV && okVC) | |
410 | return true; | |
411 | ||
412 | if (!okVC) { | |
413 | //check some exceptions: vc fails but cvc passes | |
414 | ||
415 | // quyn, quynh | |
416 | if (c1 == cs_qu && v == vs_y && (c2 == cs_n || c2 == cs_nh)) | |
417 | return true; | |
418 | ||
419 | // gieng, gie^ng | |
420 | if (c1 == cs_gi && (v == vs_e || v == vs_er) && (c2 == cs_n || c2 == cs_ng)) | |
421 | return true; | |
422 | } | |
423 | return false; | |
424 | } | |
425 | ||
426 | //------------------------------------------------ | |
427 | void engineClassInit() | |
428 | { | |
429 | int i, j; | |
430 | ||
431 | for (i=0; i < VSeqCount; i++) { | |
432 | for (j=0; j<3; j++) | |
433 | SortedVSeqList[i].v[j] = VSeqList[i].v[j]; | |
434 | SortedVSeqList[i].vs = (VowelSeq)i; | |
435 | } | |
436 | ||
437 | for (i=0; i < CSeqCount; i++) { | |
438 | for (j=0; j<3; j++) | |
439 | SortedCSeqList[i].c[j] = CSeqList[i].c[j]; | |
440 | SortedCSeqList[i].cs = (ConSeq)i; | |
441 | } | |
442 | ||
443 | qsort(SortedVSeqList, VSeqCount, sizeof(VSeqPair), tripleVowelCompare); | |
444 | qsort(SortedCSeqList, CSeqCount, sizeof(CSeqPair), tripleConCompare); | |
445 | qsort(VCPairList, VCPairCount, sizeof(VCPair), VCPairCompare); | |
446 | ||
447 | for (i=0; i<vnl_lastChar; i++) | |
448 | IsVnVowel[i] = true; | |
449 | ||
450 | unsigned char ch; | |
451 | for (ch='a'; ch <= 'z'; ch++) { | |
452 | if (ch != 'a' && ch != 'e' && ch != 'i' && | |
453 | ch != 'o' && ch != 'u' && ch != 'y') { | |
454 | IsVnVowel[AZLexiLower[ch-'a']] = false; | |
455 | IsVnVowel[AZLexiUpper[ch-'a']] = false; | |
456 | } | |
457 | } | |
458 | IsVnVowel[vnl_dd] = false; | |
459 | IsVnVowel[vnl_DD] = false; | |
460 | } | |
461 | ||
462 | //------------------------------------------------ | |
463 | VowelSeq lookupVSeq(VnLexiName v1, VnLexiName v2, VnLexiName v3) | |
464 | { | |
465 | VSeqPair key; | |
466 | key.v[0] = v1; | |
467 | key.v[1] = v2; | |
468 | key.v[2] = v3; | |
469 | ||
470 | VSeqPair *pInfo = (VSeqPair *)bsearch(&key, SortedVSeqList, VSeqCount, sizeof(VSeqPair), tripleVowelCompare); | |
471 | if (pInfo == 0) | |
472 | return vs_nil; | |
473 | return pInfo->vs; | |
474 | } | |
475 | ||
476 | //------------------------------------------------ | |
477 | ConSeq lookupCSeq(VnLexiName c1, VnLexiName c2, VnLexiName c3) | |
478 | { | |
479 | CSeqPair key; | |
480 | key.c[0] = c1; | |
481 | key.c[1] = c2; | |
482 | key.c[2] = c3; | |
483 | ||
484 | CSeqPair *pInfo = (CSeqPair *)bsearch(&key, SortedCSeqList, CSeqCount, sizeof(CSeqPair), tripleConCompare); | |
485 | if (pInfo == 0) | |
486 | return cs_nil; | |
487 | return pInfo->cs; | |
488 | } | |
489 | ||
490 | //------------------------------------------------------------------ | |
491 | int UkEngine::processRoof(UkKeyEvent & ev) | |
492 | { | |
493 | if (!m_pCtrl->vietKey || m_current < 0 || m_buffer[m_current].vOffset < 0) | |
494 | return processAppend(ev); | |
495 | ||
496 | VnLexiName target; | |
497 | switch (ev.evType) { | |
498 | case vneRoof_a: | |
499 | target = vnl_ar; | |
500 | break; | |
501 | case vneRoof_e: | |
502 | target = vnl_er; | |
503 | break; | |
504 | case vneRoof_o: | |
505 | target = vnl_or; | |
506 | break; | |
507 | default: | |
508 | target = vnl_nonVnChar; | |
509 | } | |
510 | ||
511 | ||
512 | VowelSeq vs, newVs; | |
513 | int i, vStart, vEnd; | |
514 | int curTonePos, newTonePos, tone; | |
515 | int changePos; | |
516 | bool roofRemoved = false; | |
517 | ||
518 | vEnd = m_current - m_buffer[m_current].vOffset; | |
519 | vs = m_buffer[vEnd].vseq; | |
520 | vStart = vEnd - (VSeqList[vs].len - 1); | |
521 | curTonePos = vStart + getTonePosition(vs, vEnd == m_current); | |
522 | tone = m_buffer[curTonePos].tone; | |
523 | ||
524 | bool doubleChangeUO = false; | |
525 | if (vs == vs_uho || vs == vs_uhoh || vs == vs_uhoi || vs == vs_uhohi) { | |
526 | //special cases: u+o+ -> uo^, u+o -> uo^, u+o+i -> uo^i, u+oi -> uo^i | |
527 | newVs = lookupVSeq(vnl_u, vnl_or, VSeqList[vs].v[2]); | |
528 | doubleChangeUO = true; | |
529 | } | |
530 | else { | |
531 | newVs = VSeqList[vs].withRoof; | |
532 | } | |
533 | ||
534 | VowelSeqInfo *pInfo; | |
535 | ||
536 | if (newVs == vs_nil) { | |
537 | if (VSeqList[vs].roofPos == -1) | |
538 | return processAppend(ev); //roof is not applicable | |
539 | ||
540 | //a roof already exists -> undo roof | |
541 | VnLexiName curCh = m_buffer[vStart + VSeqList[vs].roofPos].vnSym; | |
542 | if (target != vnl_nonVnChar && curCh != target) | |
543 | return processAppend(ev); //specific roof and the roof character don't match | |
544 | ||
545 | VnLexiName newCh = (curCh == vnl_ar)? vnl_a : ((curCh == vnl_er)? vnl_e : vnl_o); | |
546 | changePos = vStart + VSeqList[vs].roofPos; | |
547 | ||
548 | if (!m_pCtrl->options.freeMarking && changePos != m_current) | |
549 | return processAppend(ev); | |
550 | ||
551 | markChange(changePos); | |
552 | m_buffer[changePos].vnSym = newCh; | |
553 | ||
554 | if (VSeqList[vs].len == 3) | |
555 | newVs = lookupVSeq(m_buffer[vStart].vnSym, m_buffer[vStart+1].vnSym, m_buffer[vStart+2].vnSym); | |
556 | else if (VSeqList[vs].len == 2) | |
557 | newVs = lookupVSeq(m_buffer[vStart].vnSym, m_buffer[vStart+1].vnSym); | |
558 | else | |
559 | newVs = lookupVSeq(m_buffer[vStart].vnSym); | |
560 | ||
561 | pInfo = &VSeqList[newVs]; | |
562 | roofRemoved = true; | |
563 | } | |
564 | else { | |
565 | pInfo = &VSeqList[newVs]; | |
566 | if (target != vnl_nonVnChar && pInfo->v[pInfo->roofPos] != target) | |
567 | return processAppend(ev); | |
568 | ||
569 | //check validity of new VC and CV | |
570 | bool valid = true; | |
571 | ConSeq c1 = cs_nil; | |
572 | ConSeq c2 = cs_nil; | |
573 | if (m_buffer[m_current].c1Offset != -1) | |
574 | c1 = m_buffer[m_current-m_buffer[m_current].c1Offset].cseq; | |
575 | ||
576 | if (m_buffer[m_current].c2Offset != -1) | |
577 | c2 = m_buffer[m_current-m_buffer[m_current].c2Offset].cseq; | |
578 | ||
579 | valid = isValidCVC(c1, newVs, c2); | |
580 | if (!valid) | |
581 | return processAppend(ev); | |
582 | ||
583 | if (doubleChangeUO) { | |
584 | changePos = vStart; | |
585 | } | |
586 | else { | |
587 | changePos = vStart + pInfo->roofPos; | |
588 | } | |
589 | if (!m_pCtrl->options.freeMarking && changePos != m_current) | |
590 | return processAppend(ev); | |
591 | markChange(changePos); | |
592 | if (doubleChangeUO) { | |
593 | m_buffer[vStart].vnSym = vnl_u; | |
594 | m_buffer[vStart+1].vnSym = vnl_or; | |
595 | } | |
596 | else { | |
597 | m_buffer[changePos].vnSym = pInfo->v[pInfo->roofPos]; | |
598 | } | |
599 | } | |
600 | ||
601 | for (i=0; i < pInfo->len; i++) { //update sub-sequences | |
602 | m_buffer[vStart+i].vseq = pInfo->sub[i]; | |
603 | } | |
604 | ||
605 | //check if tone re-position is needed | |
606 | newTonePos = vStart + getTonePosition(newVs, vEnd == m_current); | |
607 | /* //For now, users don't seem to like the following processing, thus commented out | |
608 | if (roofRemoved && tone != 0 && | |
609 | (!pInfo->complete || changePos == curTonePos)) { | |
610 | //remove tone if the vowel sequence becomes incomplete as a result of roof removal OR | |
611 | //if removed roof is at the same position as the current tone | |
612 | markChange(curTonePos); | |
613 | m_buffer[curTonePos].tone = 0; | |
614 | } else | |
615 | */ | |
616 | if (curTonePos != newTonePos && tone != 0) { | |
617 | markChange(newTonePos); | |
618 | m_buffer[newTonePos].tone = tone; | |
619 | markChange(curTonePos); | |
620 | m_buffer[curTonePos].tone = 0; | |
621 | } | |
622 | ||
623 | if (roofRemoved) { | |
624 | m_singleMode = false; | |
625 | processAppend(ev); | |
626 | m_reverted = true; | |
627 | } | |
628 | ||
629 | return 1; | |
630 | } | |
631 | ||
632 | //------------------------------------------------------------------ | |
633 | // can only be called from processHook | |
634 | //------------------------------------------------------------------ | |
635 | int UkEngine::processHookWithUO(UkKeyEvent & ev) | |
636 | { | |
637 | VowelSeq vs, newVs; | |
638 | int i, vStart, vEnd; | |
639 | int curTonePos, newTonePos, tone; | |
640 | bool hookRemoved = false; | |
641 | bool removeWithUndo = true; | |
642 | bool toneRemoved = false; | |
643 | ||
644 | (void)toneRemoved; // fix warning | |
645 | ||
646 | VnLexiName *v; | |
647 | ||
648 | if (!m_pCtrl->options.freeMarking && m_buffer[m_current].vOffset != 0) | |
649 | return processAppend(ev); | |
650 | ||
651 | vEnd = m_current - m_buffer[m_current].vOffset; | |
652 | vs = m_buffer[vEnd].vseq; | |
653 | vStart = vEnd - (VSeqList[vs].len - 1); | |
654 | v = VSeqList[vs].v; | |
655 | curTonePos = vStart + getTonePosition(vs, vEnd == m_current); | |
656 | tone = m_buffer[curTonePos].tone; | |
657 | ||
658 | switch (ev.evType) { | |
659 | case vneHook_u: | |
660 | if (v[0] == vnl_u) { | |
661 | newVs = VSeqList[vs].withHook; | |
662 | markChange(vStart); | |
663 | m_buffer[vStart].vnSym = vnl_uh; | |
664 | } | |
665 | else {// v[0] = vnl_uh, -> uo | |
666 | newVs = lookupVSeq(vnl_u, vnl_o, v[2]); | |
667 | markChange(vStart); | |
668 | m_buffer[vStart].vnSym = vnl_u; | |
669 | m_buffer[vStart+1].vnSym = vnl_o; | |
670 | hookRemoved = true; | |
671 | toneRemoved = (m_buffer[vStart].tone != 0); | |
672 | } | |
673 | break; | |
674 | case vneHook_o: | |
675 | if (v[1] == vnl_o || v[1] == vnl_or) { | |
676 | if (vEnd == m_current && VSeqList[vs].len == 2 && | |
677 | m_buffer[m_current].form == vnw_cv && m_buffer[m_current-2].cseq == cs_th) | |
678 | { | |
679 | // o|o^ -> o+ | |
680 | newVs = VSeqList[vs].withHook; | |
681 | markChange(vStart+1); | |
682 | m_buffer[vStart+1].vnSym = vnl_oh; | |
683 | } | |
684 | else { | |
685 | newVs = lookupVSeq(vnl_uh, vnl_oh, v[2]); | |
686 | if (v[0] == vnl_u) { | |
687 | markChange(vStart); | |
688 | m_buffer[vStart].vnSym = vnl_uh; | |
689 | m_buffer[vStart+1].vnSym = vnl_oh; | |
690 | } | |
691 | else { | |
692 | markChange(vStart+1); | |
693 | m_buffer[vStart+1].vnSym = vnl_oh; | |
694 | } | |
695 | } | |
696 | } | |
697 | else {// v[1] = vnl_oh, -> uo | |
698 | newVs = lookupVSeq(vnl_u, vnl_o, v[2]); | |
699 | if (v[0] == vnl_uh) { | |
700 | markChange(vStart); | |
701 | m_buffer[vStart].vnSym = vnl_u; | |
702 | m_buffer[vStart+1].vnSym = vnl_o; | |
703 | } | |
704 | else { | |
705 | markChange(vStart+1); | |
706 | m_buffer[vStart+1].vnSym = vnl_o; | |
707 | } | |
708 | hookRemoved = true; | |
709 | toneRemoved = (m_buffer[vStart+1].tone != 0); | |
710 | } | |
711 | break; | |
712 | default: //vneHookAll, vneHookUO: | |
713 | if (v[0] == vnl_u) { | |
714 | if (v[1] == vnl_o || v[1] == vnl_or) { | |
715 | //uo -> uo+ if prefixed by "th" | |
716 | if ((vs == vs_uo || vs == vs_uor) && vEnd == m_current && | |
717 | m_buffer[m_current].form == vnw_cv && m_buffer[m_current-2].cseq == cs_th) | |
718 | { | |
719 | newVs = vs_uoh; | |
720 | markChange(vStart+1); | |
721 | m_buffer[vStart+1].vnSym = vnl_oh; | |
722 | } | |
723 | else { | |
724 | //uo -> u+o+ | |
725 | newVs = VSeqList[vs].withHook; | |
726 | markChange(vStart); | |
727 | m_buffer[vStart].vnSym = vnl_uh; | |
728 | newVs = VSeqList[newVs].withHook; | |
729 | m_buffer[vStart+1].vnSym = vnl_oh; | |
730 | } | |
731 | } | |
732 | else {//uo+ -> u+o+ | |
733 | newVs = VSeqList[vs].withHook; | |
734 | markChange(vStart); | |
735 | m_buffer[vStart].vnSym = vnl_uh; | |
736 | } | |
737 | } | |
738 | else {//v[0] == vnl_uh | |
739 | if (v[1] == vnl_o) { // u+o -> u+o+ | |
740 | newVs = VSeqList[vs].withHook; | |
741 | markChange(vStart+1); | |
742 | m_buffer[vStart+1].vnSym = vnl_oh; | |
743 | } | |
744 | else { //v[1] == vnl_oh, u+o+ -> uo | |
745 | newVs = lookupVSeq(vnl_u, vnl_o, v[2]); //vs_uo; | |
746 | markChange(vStart); | |
747 | m_buffer[vStart].vnSym = vnl_u; | |
748 | m_buffer[vStart+1].vnSym = vnl_o; | |
749 | hookRemoved = true; | |
750 | toneRemoved = (m_buffer[vStart].tone != 0 || m_buffer[vStart+1].tone != 0); | |
751 | } | |
752 | } | |
753 | break; | |
754 | } | |
755 | ||
756 | VowelSeqInfo *p = &VSeqList[newVs]; | |
757 | for (i=0; i < p->len; i++) { //update sub-sequences | |
758 | m_buffer[vStart+i].vseq = p->sub[i]; | |
759 | } | |
760 | ||
761 | //check if tone re-position is needed | |
762 | newTonePos = vStart + getTonePosition(newVs, vEnd == m_current); | |
763 | /* //For now, users don't seem to like the following processing, thus commented out | |
764 | if (hookRemoved && tone != 0 && (!p->complete || toneRemoved)) { | |
765 | //remove tone if the vowel sequence becomes incomplete as a result of hook removal | |
766 | //OR if a removed hook is at the same position as the current tone | |
767 | markChange(curTonePos); | |
768 | m_buffer[curTonePos].tone = 0; | |
769 | } | |
770 | else | |
771 | */ | |
772 | if (curTonePos != newTonePos && tone != 0) { | |
773 | markChange(newTonePos); | |
774 | m_buffer[newTonePos].tone = tone; | |
775 | markChange(curTonePos); | |
776 | m_buffer[curTonePos].tone = 0; | |
777 | } | |
778 | ||
779 | if (hookRemoved && removeWithUndo) { | |
780 | m_singleMode = false; | |
781 | processAppend(ev); | |
782 | m_reverted = true; | |
783 | } | |
784 | ||
785 | return 1; | |
786 | } | |
787 | ||
788 | //------------------------------------------------------------------ | |
789 | int UkEngine::processHook(UkKeyEvent & ev) | |
790 | { | |
791 | if (!m_pCtrl->vietKey || m_current < 0 || m_buffer[m_current].vOffset < 0) | |
792 | return processAppend(ev); | |
793 | ||
794 | VowelSeq vs, newVs; | |
795 | int i, vStart, vEnd; | |
796 | int curTonePos, newTonePos, tone; | |
797 | int changePos; | |
798 | bool hookRemoved = false; | |
799 | VowelSeqInfo *pInfo; | |
800 | VnLexiName *v; | |
801 | ||
802 | vEnd = m_current - m_buffer[m_current].vOffset; | |
803 | vs = m_buffer[vEnd].vseq; | |
804 | ||
805 | v = VSeqList[vs].v; | |
806 | ||
807 | if (VSeqList[vs].len > 1 && | |
808 | ev.evType != vneBowl && | |
809 | (v[0] == vnl_u || v[0] == vnl_uh) && | |
810 | (v[1] == vnl_o || v[1] == vnl_oh || v[1] == vnl_or)) | |
811 | return processHookWithUO(ev); | |
812 | ||
813 | vStart = vEnd - (VSeqList[vs].len - 1); | |
814 | curTonePos = vStart + getTonePosition(vs, vEnd == m_current); | |
815 | tone = m_buffer[curTonePos].tone; | |
816 | ||
817 | newVs = VSeqList[vs].withHook; | |
818 | if (newVs == vs_nil) { | |
819 | if (VSeqList[vs].hookPos == -1) | |
820 | return processAppend(ev); //hook is not applicable | |
821 | ||
822 | //a hook already exists -> undo hook | |
823 | VnLexiName curCh = m_buffer[vStart + VSeqList[vs].hookPos].vnSym; | |
824 | VnLexiName newCh = (curCh == vnl_ab)? vnl_a : ((curCh == vnl_uh)? vnl_u : vnl_o); | |
825 | changePos = vStart + VSeqList[vs].hookPos; | |
826 | if (!m_pCtrl->options.freeMarking && changePos != m_current) | |
827 | return processAppend(ev); | |
828 | ||
829 | switch (ev.evType) { | |
830 | case vneHook_u: | |
831 | if (curCh != vnl_uh) | |
832 | return processAppend(ev); | |
833 | break; | |
834 | case vneHook_o: | |
835 | if (curCh != vnl_oh) | |
836 | return processAppend(ev); | |
837 | break; | |
838 | case vneBowl: | |
839 | if (curCh != vnl_ab) | |
840 | return processAppend(ev); | |
841 | break; | |
842 | default: | |
843 | if (ev.evType == vneHook_uo && curCh == vnl_ab) | |
844 | return processAppend(ev); | |
845 | } | |
846 | ||
847 | markChange(changePos); | |
848 | m_buffer[changePos].vnSym = newCh; | |
849 | ||
850 | if (VSeqList[vs].len == 3) | |
851 | newVs = lookupVSeq(m_buffer[vStart].vnSym, m_buffer[vStart+1].vnSym, m_buffer[vStart+2].vnSym); | |
852 | else if (VSeqList[vs].len == 2) | |
853 | newVs = lookupVSeq(m_buffer[vStart].vnSym, m_buffer[vStart+1].vnSym); | |
854 | else | |
855 | newVs = lookupVSeq(m_buffer[vStart].vnSym); | |
856 | ||
857 | pInfo = &VSeqList[newVs]; | |
858 | hookRemoved = true; | |
859 | } | |
860 | else { | |
861 | pInfo = &VSeqList[newVs]; | |
862 | ||
863 | switch (ev.evType) { | |
864 | case vneHook_u: | |
865 | if (pInfo->v[pInfo->hookPos] != vnl_uh) | |
866 | return processAppend(ev); | |
867 | break; | |
868 | case vneHook_o: | |
869 | if (pInfo->v[pInfo->hookPos] != vnl_oh) | |
870 | return processAppend(ev); | |
871 | break; | |
872 | case vneBowl: | |
873 | if (pInfo->v[pInfo->hookPos] != vnl_ab) | |
874 | return processAppend(ev); | |
875 | break; | |
876 | default: //vneHook_uo, vneHookAll | |
877 | if (ev.evType == vneHook_uo && pInfo->v[pInfo->hookPos] == vnl_ab) | |
878 | return processAppend(ev); | |
879 | } | |
880 | ||
881 | //check validity of new VC and CV | |
882 | bool valid = true; | |
883 | ConSeq c1 = cs_nil; | |
884 | ConSeq c2 = cs_nil; | |
885 | if (m_buffer[m_current].c1Offset != -1) | |
886 | c1 = m_buffer[m_current-m_buffer[m_current].c1Offset].cseq; | |
887 | ||
888 | if (m_buffer[m_current].c2Offset != -1) | |
889 | c2 = m_buffer[m_current-m_buffer[m_current].c2Offset].cseq; | |
890 | ||
891 | valid = isValidCVC(c1, newVs, c2); | |
892 | ||
893 | if (!valid) | |
894 | return processAppend(ev); | |
895 | ||
896 | changePos = vStart + pInfo->hookPos; | |
897 | if (!m_pCtrl->options.freeMarking && changePos != m_current) | |
898 | return processAppend(ev); | |
899 | ||
900 | markChange(changePos); | |
901 | m_buffer[changePos].vnSym = pInfo->v[pInfo->hookPos]; | |
902 | } | |
903 | ||
904 | for (i=0; i < pInfo->len; i++) { //update sub-sequences | |
905 | m_buffer[vStart+i].vseq = pInfo->sub[i]; | |
906 | } | |
907 | ||
908 | //check if tone re-position is needed | |
909 | newTonePos = vStart + getTonePosition(newVs, vEnd == m_current); | |
910 | /* //For now, users don't seem to like the following processing, thus commented out | |
911 | if (hookRemoved && tone != 0 && | |
912 | (!pInfo->complete || (hookRemoved && curTonePos == changePos))) { | |
913 | //remove tone if the vowel sequence becomes incomplete as a result of hook removal | |
914 | //OR if a removed hook was at the same position as the current tone | |
915 | markChange(curTonePos); | |
916 | m_buffer[curTonePos].tone = 0; | |
917 | } | |
918 | else */ | |
919 | if (curTonePos != newTonePos && tone != 0) { | |
920 | markChange(newTonePos); | |
921 | m_buffer[newTonePos].tone = tone; | |
922 | markChange(curTonePos); | |
923 | m_buffer[curTonePos].tone = 0; | |
924 | } | |
925 | ||
926 | if (hookRemoved) { | |
927 | m_singleMode = false; | |
928 | processAppend(ev); | |
929 | m_reverted = true; | |
930 | } | |
931 | ||
932 | return 1; | |
933 | } | |
934 | ||
935 | //---------------------------------------------------------- | |
936 | int UkEngine::getTonePosition(VowelSeq vs, bool terminated) | |
937 | { | |
938 | VowelSeqInfo & info = VSeqList[vs]; | |
939 | if (info.len == 1) | |
940 | return 0; | |
941 | ||
942 | if (info.roofPos != -1) | |
943 | return info.roofPos; | |
944 | if (info.hookPos != -1) { | |
945 | if (vs == vs_uhoh || vs == vs_uhohi || vs == vs_uhohu) //u+o+, u+o+u, u+o+i | |
946 | return 1; | |
947 | return info.hookPos; | |
948 | } | |
949 | ||
950 | if (info.len == 3) | |
951 | return 1; | |
952 | ||
953 | if (m_pCtrl->options.modernStyle && | |
954 | (vs == vs_oa || vs == vs_oe ||vs == vs_uy)) | |
955 | return 1; | |
956 | ||
957 | return terminated ? 0 : 1; | |
958 | } | |
959 | ||
960 | //---------------------------------------------------------- | |
961 | int UkEngine::processTone(UkKeyEvent & ev) | |
962 | { | |
963 | if (m_current < 0 || !m_pCtrl->vietKey) | |
964 | return processAppend(ev); | |
965 | ||
966 | if (m_buffer[m_current].form == vnw_c && | |
967 | (m_buffer[m_current].cseq == cs_gi || m_buffer[m_current].cseq == cs_gin)) { | |
968 | int p = (m_buffer[m_current].cseq == cs_gi)? m_current : m_current - 1; | |
969 | if (m_buffer[p].tone == 0 && ev.tone == 0) | |
970 | return processAppend(ev); | |
971 | markChange(p); | |
972 | if (m_buffer[p].tone == ev.tone) { | |
973 | m_buffer[p].tone = 0; | |
974 | m_singleMode = false; | |
975 | processAppend(ev); | |
976 | m_reverted = true; | |
977 | return 1; | |
978 | } | |
979 | m_buffer[p].tone = ev.tone; | |
980 | return 1; | |
981 | } | |
982 | ||
983 | if (m_buffer[m_current].vOffset < 0) | |
984 | return processAppend(ev); | |
985 | ||
986 | int vEnd; | |
987 | VowelSeq vs; | |
988 | ||
989 | vEnd = m_current - m_buffer[m_current].vOffset; | |
990 | vs = m_buffer[vEnd].vseq; | |
991 | VowelSeqInfo & info = VSeqList[vs]; | |
992 | if (m_pCtrl->options.spellCheckEnabled && !m_pCtrl->options.freeMarking && !info.complete) | |
993 | return processAppend(ev); | |
994 | ||
995 | if (m_buffer[m_current].form == vnw_vc || m_buffer[m_current].form == vnw_cvc) { | |
996 | ConSeq cs = m_buffer[m_current].cseq; | |
997 | if ((cs == cs_c || cs == cs_ch || cs == cs_p || cs == cs_t) && | |
998 | (ev.tone == 2 || ev.tone == 3 || ev.tone == 4)) | |
999 | return processAppend(ev); // c, ch, p, t suffixes don't allow ` ? ~ | |
1000 | } | |
1001 | ||
1002 | int toneOffset = getTonePosition(vs, vEnd == m_current); | |
1003 | int tonePos = vEnd - (info.len -1 ) + toneOffset; | |
1004 | if (m_buffer[tonePos].tone == 0 && ev.tone == 0) | |
1005 | return processAppend(ev); | |
1006 | ||
1007 | if (m_buffer[tonePos].tone == ev.tone) { | |
1008 | markChange(tonePos); | |
1009 | m_buffer[tonePos].tone = 0; | |
1010 | m_singleMode = false; | |
1011 | processAppend(ev); | |
1012 | m_reverted = true; | |
1013 | return 1; | |
1014 | } | |
1015 | ||
1016 | markChange(tonePos); | |
1017 | m_buffer[tonePos].tone = ev.tone; | |
1018 | return 1; | |
1019 | } | |
1020 | ||
1021 | //---------------------------------------------------------- | |
1022 | int UkEngine::processDd(UkKeyEvent & ev) | |
1023 | { | |
1024 | if (!m_pCtrl->vietKey || m_current < 0) | |
1025 | return processAppend(ev); | |
1026 | ||
1027 | int pos; | |
1028 | ||
1029 | // we want to allow dd even in non-vn sequence, because dd is used a lot in abbreviation | |
1030 | // we allow dd only if preceding character is not a vowel | |
1031 | if (m_buffer[m_current].form == vnw_nonVn && | |
1032 | m_buffer[m_current].vnSym == vnl_d && | |
1033 | (m_buffer[m_current-1].vnSym == vnl_nonVnChar ||!IsVnVowel[m_buffer[m_current-1].vnSym])) | |
1034 | { | |
1035 | m_singleMode = true; | |
1036 | pos = m_current; | |
1037 | markChange(pos); | |
1038 | m_buffer[pos].cseq = cs_dd; | |
1039 | m_buffer[pos].vnSym = vnl_dd; | |
1040 | m_buffer[pos].form = vnw_c; | |
1041 | m_buffer[pos].c1Offset = 0; | |
1042 | m_buffer[pos].c2Offset = -1; | |
1043 | m_buffer[pos].vOffset = -1; | |
1044 | return 1; | |
1045 | } | |
1046 | ||
1047 | if (m_buffer[m_current].c1Offset < 0) { | |
1048 | return processAppend(ev); | |
1049 | } | |
1050 | ||
1051 | pos = m_current - m_buffer[m_current].c1Offset; | |
1052 | if (!m_pCtrl->options.freeMarking && pos != m_current) | |
1053 | return processAppend(ev); | |
1054 | ||
1055 | if (m_buffer[pos].cseq == cs_d) { | |
1056 | markChange(pos); | |
1057 | m_buffer[pos].cseq = cs_dd; | |
1058 | m_buffer[pos].vnSym = vnl_dd; | |
1059 | //never spellcheck a word which starts with dd, because it's used alot in abbreviation | |
1060 | m_singleMode = true; | |
1061 | return 1; | |
1062 | } | |
1063 | ||
1064 | if (m_buffer[pos].cseq == cs_dd) { | |
1065 | //undo dd | |
1066 | markChange(pos); | |
1067 | m_buffer[pos].cseq = cs_d; | |
1068 | m_buffer[pos].vnSym = vnl_d; | |
1069 | m_singleMode = false; | |
1070 | processAppend(ev); | |
1071 | m_reverted = true; | |
1072 | return 1; | |
1073 | } | |
1074 | ||
1075 | return processAppend(ev); | |
1076 | } | |
1077 | ||
1078 | //---------------------------------------------------------- | |
1079 | VnLexiName changeCase(VnLexiName x) | |
1080 | { | |
1081 | if (x == vnl_nonVnChar) | |
1082 | return x; | |
1083 | if (!(x & 0x01)) | |
1084 | return (VnLexiName)(x+1); | |
1085 | return (VnLexiName)(x-1); | |
1086 | } | |
1087 | ||
1088 | //---------------------------------------------------------- | |
1089 | inline VnLexiName vnToLower(VnLexiName x) | |
1090 | { | |
1091 | if (x == vnl_nonVnChar) | |
1092 | return x; | |
1093 | if (!(x & 0x01)) //even | |
1094 | return (VnLexiName)(x+1); | |
1095 | return x; | |
1096 | } | |
1097 | ||
1098 | //---------------------------------------------------------- | |
1099 | int UkEngine::processMapChar(UkKeyEvent & ev) | |
1100 | { | |
1101 | int capsLockOn = 0; | |
1102 | int shiftPressed = 0; | |
1103 | if (m_keyCheckFunc) | |
1104 | m_keyCheckFunc(&shiftPressed, &capsLockOn); | |
1105 | ||
1106 | if (capsLockOn) | |
1107 | ev.vnSym = changeCase(ev.vnSym); | |
1108 | ||
1109 | int ret = processAppend(ev); | |
1110 | if (!m_pCtrl->vietKey) | |
1111 | return ret; | |
1112 | ||
1113 | if (m_current >= 0 && m_buffer[m_current].form != vnw_empty && | |
1114 | m_buffer[m_current].form != vnw_nonVn) { | |
1115 | return 1; | |
1116 | } | |
1117 | ||
1118 | if (m_current < 0) | |
1119 | return 0; | |
1120 | ||
1121 | // mapChar doesn't apply | |
1122 | m_current--; | |
1123 | WordInfo & entry = m_buffer[m_current]; | |
1124 | ||
1125 | bool undo = false; | |
1126 | // test if undo is needed | |
1127 | if (entry.form != vnw_empty && entry.form != vnw_nonVn) { | |
1128 | VnLexiName prevSym = entry.vnSym; | |
1129 | if (entry.caps) { | |
1130 | prevSym = (VnLexiName)(prevSym - 1); | |
1131 | } | |
1132 | if (prevSym == ev.vnSym) { | |
1133 | if (entry.form != vnw_c) { | |
1134 | int vStart, vEnd, curTonePos, newTonePos, tone; | |
1135 | VowelSeq vs, newVs; | |
1136 | ||
1137 | vEnd = m_current - entry.vOffset; | |
1138 | vs = m_buffer[vEnd].vseq; | |
1139 | vStart = vEnd - VSeqList[vs].len +1; | |
1140 | curTonePos = vStart + getTonePosition(vs, vEnd == m_current); | |
1141 | tone = m_buffer[curTonePos].tone; | |
1142 | markChange(m_current); | |
1143 | m_current--; | |
1144 | ||
1145 | //check if tone position is needed | |
1146 | if (tone != 0 && m_current >= 0 && | |
1147 | (m_buffer[m_current].form == vnw_v || m_buffer[m_current].form == vnw_cv)) { | |
1148 | newVs = m_buffer[m_current].vseq; | |
1149 | newTonePos = vStart + getTonePosition(newVs, true); | |
1150 | if (newTonePos != curTonePos) { | |
1151 | markChange(newTonePos); | |
1152 | m_buffer[newTonePos].tone = tone; | |
1153 | markChange(curTonePos); | |
1154 | m_buffer[curTonePos].tone = 0; | |
1155 | } | |
1156 | } | |
1157 | } | |
1158 | else { | |
1159 | markChange(m_current); | |
1160 | m_current--; | |
1161 | } | |
1162 | undo = true; | |
1163 | } | |
1164 | } | |
1165 | ||
1166 | ev.evType = vneNormal; | |
1167 | ev.chType = m_pCtrl->input.getCharType(ev.keyCode); | |
1168 | ev.vnSym = IsoToVnLexi(ev.keyCode); | |
1169 | ret = processAppend(ev); | |
1170 | if (undo) { | |
1171 | m_singleMode = false; | |
1172 | m_reverted = true; | |
1173 | return 1; | |
1174 | } | |
1175 | return ret; | |
1176 | } | |
1177 | ||
1178 | //---------------------------------------------------------- | |
1179 | int UkEngine::processTelexW(UkKeyEvent & ev) | |
1180 | { | |
1181 | if (!m_pCtrl->vietKey) | |
1182 | return processAppend(ev); | |
1183 | ||
1184 | int ret; | |
1185 | static bool usedAsMapChar = false; | |
1186 | int capsLockOn = 0; | |
1187 | int shiftPressed = 0; | |
1188 | if (m_keyCheckFunc) | |
1189 | m_keyCheckFunc(&shiftPressed, &capsLockOn); | |
1190 | ||
1191 | if (usedAsMapChar) { | |
1192 | ev.evType = vneMapChar; | |
1193 | ev.vnSym = isupper(ev.keyCode)? vnl_Uh : vnl_uh; | |
1194 | if (capsLockOn) | |
1195 | ev.vnSym = changeCase(ev.vnSym); | |
1196 | ev.chType = ukcVn; | |
1197 | ret = processMapChar(ev); | |
1198 | if (ret == 0) { | |
1199 | if (m_current >= 0) | |
1200 | m_current--; | |
1201 | usedAsMapChar = false; | |
1202 | ev.evType = vneHookAll; | |
1203 | return processHook(ev); | |
1204 | } | |
1205 | return ret; | |
1206 | } | |
1207 | ||
1208 | ev.evType = vneHookAll; | |
1209 | usedAsMapChar = false; | |
1210 | ret = processHook(ev); | |
1211 | if (ret == 0) { | |
1212 | if (m_current >= 0) | |
1213 | m_current--; | |
1214 | ev.evType = vneMapChar; | |
1215 | ev.vnSym = isupper(ev.keyCode)? vnl_Uh : vnl_uh; | |
1216 | if (capsLockOn) | |
1217 | ev.vnSym = changeCase(ev.vnSym); | |
1218 | ev.chType = ukcVn; | |
1219 | usedAsMapChar = true; | |
1220 | return processMapChar(ev); | |
1221 | } | |
1222 | return ret; | |
1223 | } | |
1224 | ||
1225 | //---------------------------------------------------------- | |
1226 | int UkEngine::checkEscapeVIQR(UkKeyEvent & ev) | |
1227 | { | |
1228 | if (m_current < 0) | |
1229 | return 0; | |
1230 | WordInfo & entry = m_buffer[m_current]; | |
1231 | int escape = 0; | |
1232 | if (entry.form == vnw_v || entry.form == vnw_cv) { | |
1233 | switch (ev.keyCode) { | |
1234 | case '^': | |
1235 | escape = (entry.vnSym == vnl_a || entry.vnSym == vnl_o || entry.vnSym == vnl_e); | |
1236 | break; | |
1237 | case '(': | |
1238 | escape = (entry.vnSym == vnl_a); | |
1239 | break; | |
1240 | case '+': | |
1241 | escape = (entry.vnSym == vnl_o || entry.vnSym == vnl_u); | |
1242 | break; | |
1243 | case '\'': | |
1244 | case '`': | |
1245 | case '?': | |
1246 | case '~': | |
1247 | case '.': | |
1248 | escape = (entry.tone == 0); | |
1249 | break; | |
1250 | } | |
1251 | } | |
1252 | else if (entry.form == vnw_nonVn) { | |
1253 | unsigned char ch = toupper(entry.keyCode); | |
1254 | switch (ev.keyCode) { | |
1255 | case '^': | |
1256 | escape = (ch == 'A' || ch == 'O' || ch == 'E'); | |
1257 | break; | |
1258 | case '(': | |
1259 | escape = (ch == 'A'); | |
1260 | break; | |
1261 | case '+': | |
1262 | escape = (ch == 'O' || ch == 'U'); | |
1263 | break; | |
1264 | case '\'': | |
1265 | case '`': | |
1266 | case '?': | |
1267 | case '~': | |
1268 | case '.': | |
1269 | escape = (ch == 'A' || ch == 'E' || ch == 'I' || | |
1270 | ch == 'O' || ch == 'U' || ch == 'Y'); | |
1271 | break; | |
1272 | } | |
1273 | } | |
1274 | ||
1275 | if (escape) { | |
1276 | m_current++; | |
1277 | WordInfo *p = &m_buffer[m_current]; | |
1278 | p->form = (ev.chType == ukcWordBreak) ? vnw_empty : vnw_nonVn; | |
1279 | p->c1Offset = p->c2Offset = p->vOffset = -1; | |
1280 | p->keyCode = '?'; | |
1281 | p->vnSym = vnl_nonVnChar; | |
1282 | ||
1283 | m_current++; | |
1284 | p++; | |
1285 | p->form = (ev.chType == ukcWordBreak) ? vnw_empty : vnw_nonVn; | |
1286 | p->c1Offset = p->c2Offset = p->vOffset = -1; | |
1287 | p->keyCode = ev.keyCode; | |
1288 | p->vnSym = vnl_nonVnChar; | |
1289 | ||
1290 | //write output | |
1291 | m_pOutBuf[0] = '\\'; | |
1292 | m_pOutBuf[1] = ev.keyCode; | |
1293 | *m_pOutSize = 2; | |
1294 | m_outputWritten = true; | |
1295 | } | |
1296 | return escape; | |
1297 | } | |
1298 | ||
1299 | //---------------------------------------------------------- | |
1300 | int UkEngine::processAppend(UkKeyEvent & ev) | |
1301 | { | |
1302 | int ret = 0; | |
1303 | switch (ev.chType) { | |
1304 | case ukcReset: | |
1305 | #if defined(_WIN32) | |
1306 | if (ev.keyCode == ENTER_CHAR) { | |
1307 | if (m_pCtrl->options.macroEnabled && macroMatch(ev)) | |
1308 | return 1; | |
1309 | } | |
1310 | #endif | |
1311 | reset(); | |
1312 | return 0; | |
1313 | case ukcWordBreak: | |
1314 | m_singleMode = false; | |
1315 | return processWordEnd(ev); | |
1316 | case ukcNonVn: | |
1317 | { | |
1318 | if (m_pCtrl->vietKey && m_pCtrl->charsetId == CONV_CHARSET_VIQR && checkEscapeVIQR(ev)) | |
1319 | return 1; | |
1320 | ||
1321 | m_current++; | |
1322 | WordInfo & entry = m_buffer[m_current]; | |
1323 | entry.form = (ev.chType == ukcWordBreak) ? vnw_empty : vnw_nonVn; | |
1324 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
1325 | entry.keyCode = ev.keyCode; | |
1326 | entry.vnSym = vnToLower(ev.vnSym); | |
1327 | entry.tone = 0; | |
1328 | entry.caps = (entry.vnSym != ev.vnSym); | |
1329 | if (!m_pCtrl->vietKey || m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) | |
1330 | return 0; | |
1331 | markChange(m_current); | |
1332 | return 1; | |
1333 | } | |
1334 | case ukcVn: | |
1335 | { | |
1336 | if (IsVnVowel[ev.vnSym]) { | |
1337 | VnLexiName v = (VnLexiName)StdVnNoTone[vnToLower(ev.vnSym)]; | |
1338 | if (m_current >= 0 && m_buffer[m_current].form == vnw_c && | |
1339 | ((m_buffer[m_current].cseq == cs_q && v == vnl_u) || | |
1340 | (m_buffer[m_current].cseq == cs_g && v == vnl_i))) { | |
1341 | return appendConsonnant(ev); //process u after q, i after g as consonnants | |
1342 | } | |
1343 | return appendVowel(ev); | |
1344 | } | |
1345 | return appendConsonnant(ev); | |
1346 | } | |
1347 | break; | |
1348 | } | |
1349 | ||
1350 | return ret; | |
1351 | } | |
1352 | ||
1353 | //---------------------------------------------------------- | |
1354 | int UkEngine::appendVowel(UkKeyEvent & ev) | |
1355 | { | |
1356 | bool autoCompleted = false; | |
1357 | ||
1358 | m_current++; | |
1359 | WordInfo & entry = m_buffer[m_current]; | |
1360 | ||
1361 | VnLexiName lowerSym = vnToLower(ev.vnSym); | |
1362 | VnLexiName canSym = (VnLexiName)StdVnNoTone[lowerSym]; | |
1363 | ||
1364 | entry.vnSym = canSym; | |
1365 | entry.caps = (lowerSym != ev.vnSym); | |
1366 | entry.tone = (lowerSym - canSym)/2; | |
1367 | entry.keyCode = ev.keyCode; | |
1368 | ||
1369 | if (m_current == 0 || !m_pCtrl->vietKey) { | |
1370 | entry.form = vnw_v; | |
1371 | entry.c1Offset = entry.c2Offset = -1; | |
1372 | entry.vOffset = 0; | |
1373 | entry.vseq = lookupVSeq(canSym); | |
1374 | ||
1375 | if (!m_pCtrl->vietKey || | |
1376 | ((m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) && isalpha(entry.keyCode)) ) { | |
1377 | return 0; | |
1378 | } | |
1379 | markChange(m_current); | |
1380 | return 1; | |
1381 | } | |
1382 | ||
1383 | WordInfo & prev = m_buffer[m_current-1]; | |
1384 | VowelSeq vs, newVs; | |
1385 | ConSeq cs; | |
1386 | int prevTonePos; | |
1387 | int tone, newTone, tonePos, newTonePos; | |
1388 | ||
1389 | switch (prev.form) { | |
1390 | ||
1391 | case vnw_empty: | |
1392 | entry.form = vnw_v; | |
1393 | entry.c1Offset = entry.c2Offset = -1; | |
1394 | entry.vOffset = 0; | |
1395 | entry.vseq = newVs = lookupVSeq(canSym); | |
1396 | break; | |
1397 | ||
1398 | case vnw_nonVn: | |
1399 | case vnw_cvc: | |
1400 | case vnw_vc: | |
1401 | entry.form = vnw_nonVn; | |
1402 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
1403 | break; | |
1404 | ||
1405 | case vnw_v: | |
1406 | case vnw_cv: | |
1407 | vs = prev.vseq; | |
1408 | prevTonePos = (m_current - 1) - (VSeqList[vs].len - 1) + getTonePosition(vs, true); | |
1409 | tone = m_buffer[prevTonePos].tone; | |
1410 | ||
1411 | if (lowerSym != canSym && tone != 0) //new sym has a tone, but there's is already a preceeding tone | |
1412 | newVs = vs_nil; | |
1413 | else { | |
1414 | if (VSeqList[vs].len == 3) | |
1415 | newVs = vs_nil; | |
1416 | else if (VSeqList[vs].len == 2) | |
1417 | newVs = lookupVSeq(VSeqList[vs].v[0], VSeqList[vs].v[1], canSym); | |
1418 | else | |
1419 | newVs = lookupVSeq(VSeqList[vs].v[0], canSym); | |
1420 | } | |
1421 | ||
1422 | if (newVs != vs_nil && prev.form == vnw_cv) { | |
1423 | cs = m_buffer[m_current - 1 - prev.c1Offset].cseq; | |
1424 | if (!isValidCV(cs, newVs)) | |
1425 | newVs = vs_nil; | |
1426 | } | |
1427 | ||
1428 | if (newVs == vs_nil) { | |
1429 | entry.form = vnw_nonVn; | |
1430 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
1431 | break; | |
1432 | } | |
1433 | ||
1434 | entry.form = prev.form; | |
1435 | if (prev.form == vnw_cv) | |
1436 | entry.c1Offset = prev.c1Offset + 1; | |
1437 | else | |
1438 | entry.c1Offset = -1; | |
1439 | entry.c2Offset = -1; | |
1440 | entry.vOffset = 0; | |
1441 | entry.vseq = newVs; | |
1442 | entry.tone = 0; | |
1443 | ||
1444 | newTone = (lowerSym - canSym)/2; | |
1445 | if (tone == 0) { | |
1446 | if (newTone != 0) { | |
1447 | tone = newTone; | |
1448 | tonePos = getTonePosition(newVs, true) + ((m_current - 1) - VSeqList[vs].len + 1); | |
1449 | markChange(tonePos); | |
1450 | m_buffer[tonePos].tone = tone; | |
1451 | return 1; | |
1452 | } | |
1453 | } | |
1454 | else { | |
1455 | newTonePos = getTonePosition(newVs, true) + ((m_current - 1) - VSeqList[vs].len + 1); | |
1456 | if (newTonePos != prevTonePos) { | |
1457 | markChange(prevTonePos); | |
1458 | m_buffer[prevTonePos].tone = 0; | |
1459 | markChange(newTonePos); | |
1460 | if (newTone != 0) | |
1461 | tone = newTone; | |
1462 | m_buffer[newTonePos].tone = tone; | |
1463 | return 1; | |
1464 | } | |
1465 | if (newTone != 0 && newTone != tone) { | |
1466 | tone = newTone; | |
1467 | markChange(prevTonePos); | |
1468 | m_buffer[prevTonePos].tone = tone; | |
1469 | return 1; | |
1470 | } | |
1471 | ||
1472 | } | |
1473 | ||
1474 | break; | |
1475 | case vnw_c: | |
1476 | newVs = lookupVSeq(canSym); | |
1477 | cs = prev.cseq; | |
1478 | if (!isValidCV(cs, newVs)) { | |
1479 | entry.form = vnw_nonVn; | |
1480 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
1481 | break; | |
1482 | } | |
1483 | ||
1484 | entry.form = vnw_cv; | |
1485 | entry.c1Offset = 1; | |
1486 | entry.c2Offset = -1; | |
1487 | entry.vOffset = 0; | |
1488 | entry.vseq = newVs; | |
1489 | ||
1490 | if (cs == cs_gi && prev.tone != 0) { | |
1491 | if (entry.tone == 0) | |
1492 | entry.tone = prev.tone; | |
1493 | markChange(m_current - 1); | |
1494 | prev.tone = 0; | |
1495 | return 1; | |
1496 | } | |
1497 | ||
1498 | break; | |
1499 | } | |
1500 | ||
1501 | if (!autoCompleted && | |
1502 | (m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) && | |
1503 | isalpha(entry.keyCode)) { | |
1504 | return 0; | |
1505 | } | |
1506 | ||
1507 | markChange(m_current); | |
1508 | return 1; | |
1509 | } | |
1510 | ||
1511 | //---------------------------------------------------------- | |
1512 | int UkEngine::appendConsonnant(UkKeyEvent & ev) | |
1513 | { | |
1514 | bool complexEvent = false; | |
1515 | m_current++; | |
1516 | WordInfo & entry = m_buffer[m_current]; | |
1517 | ||
1518 | VnLexiName lowerSym = vnToLower(ev.vnSym); | |
1519 | ||
1520 | entry.vnSym = lowerSym; | |
1521 | entry.caps = (lowerSym != ev.vnSym); | |
1522 | entry.keyCode = ev.keyCode; | |
1523 | entry.tone = 0; | |
1524 | ||
1525 | if (m_current == 0 || !m_pCtrl->vietKey) { | |
1526 | entry.form = vnw_c; | |
1527 | entry.c1Offset = 0; | |
1528 | entry.c2Offset = -1; | |
1529 | entry.vOffset = -1; | |
1530 | entry.cseq = lookupCSeq(lowerSym); | |
1531 | if (!m_pCtrl->vietKey || m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) | |
1532 | return 0; | |
1533 | markChange(m_current); | |
1534 | return 1; | |
1535 | } | |
1536 | ||
1537 | ConSeq cs, newCs, c1; | |
1538 | VowelSeq vs, newVs; | |
1539 | bool isValid; | |
1540 | ||
1541 | WordInfo & prev = m_buffer[m_current-1]; | |
1542 | ||
1543 | switch (prev.form) { | |
1544 | case vnw_nonVn: | |
1545 | entry.form = vnw_nonVn; | |
1546 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
1547 | if (m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) | |
1548 | return 0; | |
1549 | markChange(m_current); | |
1550 | return 1; | |
1551 | case vnw_empty: | |
1552 | entry.form = vnw_c; | |
1553 | entry.c1Offset = 0; | |
1554 | entry.c2Offset = -1; | |
1555 | entry.vOffset = -1; | |
1556 | entry.cseq = lookupCSeq(lowerSym); | |
1557 | if (m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) | |
1558 | return 0; | |
1559 | markChange(m_current); | |
1560 | return 1; | |
1561 | case vnw_v: | |
1562 | case vnw_cv: | |
1563 | vs = prev.vseq; | |
1564 | newVs = vs; | |
1565 | if (vs == vs_uoh || vs == vs_uho) { | |
1566 | newVs = vs_uhoh; | |
1567 | } | |
1568 | ||
1569 | c1 = cs_nil; | |
1570 | if (prev.c1Offset != -1) | |
1571 | c1 = m_buffer[m_current-1-prev.c1Offset].cseq; | |
1572 | ||
1573 | newCs = lookupCSeq(lowerSym); | |
1574 | isValid = isValidCVC(c1, newVs, newCs); | |
1575 | ||
1576 | if (isValid) { | |
1577 | //check u+o -> u+o+ | |
1578 | if (vs == vs_uho) { | |
1579 | markChange(m_current-1); | |
1580 | prev.vnSym = vnl_oh; | |
1581 | prev.vseq = vs_uhoh; | |
1582 | complexEvent = true; | |
1583 | } | |
1584 | else if (vs == vs_uoh) { | |
1585 | markChange(m_current-2); | |
1586 | m_buffer[m_current-2].vnSym = vnl_uh; | |
1587 | m_buffer[m_current-2].vseq = vs_uh; | |
1588 | prev.vseq = vs_uhoh; | |
1589 | complexEvent = true; | |
1590 | } | |
1591 | ||
1592 | if (prev.form == vnw_v) { | |
1593 | entry.form = vnw_vc; | |
1594 | entry.c1Offset = -1; | |
1595 | entry.c2Offset = 0; | |
1596 | entry.vOffset = 1; | |
1597 | } | |
1598 | else { //prev == vnw_cv | |
1599 | entry.form = vnw_cvc; | |
1600 | entry.c1Offset = prev.c1Offset + 1; | |
1601 | entry.c2Offset = 0; | |
1602 | entry.vOffset = 1; | |
1603 | } | |
1604 | entry.cseq = newCs; | |
1605 | ||
1606 | //reposition tone if needed | |
1607 | int oldIdx = (m_current-1) - (VSeqList[vs].len - 1) + getTonePosition(vs, true); | |
1608 | if (m_buffer[oldIdx].tone != 0) { | |
1609 | int newIdx = (m_current-1) - (VSeqList[newVs].len - 1) + getTonePosition(newVs, false); | |
1610 | if (newIdx != oldIdx) { | |
1611 | markChange(newIdx); | |
1612 | m_buffer[newIdx].tone = m_buffer[oldIdx].tone; | |
1613 | markChange(oldIdx); | |
1614 | m_buffer[oldIdx].tone = 0; | |
1615 | return 1; | |
1616 | } | |
1617 | } | |
1618 | } | |
1619 | else { | |
1620 | entry.form = vnw_nonVn; | |
1621 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
1622 | } | |
1623 | ||
1624 | if (complexEvent) { | |
1625 | return 1; | |
1626 | } | |
1627 | ||
1628 | if (m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) | |
1629 | return 0; | |
1630 | markChange(m_current); | |
1631 | return 1; | |
1632 | case vnw_c: | |
1633 | case vnw_vc: | |
1634 | case vnw_cvc: | |
1635 | cs = prev.cseq; | |
1636 | if (CSeqList[cs].len == 3) | |
1637 | newCs = cs_nil; | |
1638 | else if (CSeqList[cs].len == 2) | |
1639 | newCs = lookupCSeq(CSeqList[cs].c[0], CSeqList[cs].c[1], lowerSym); | |
1640 | else | |
1641 | newCs = lookupCSeq(CSeqList[cs].c[0], lowerSym); | |
1642 | ||
1643 | if (newCs != cs_nil && (prev.form == vnw_vc || prev.form == vnw_cvc)) { | |
1644 | // Check CVC combination | |
1645 | c1 = cs_nil; | |
1646 | if (prev.c1Offset != -1) | |
1647 | c1 = m_buffer[m_current-1-prev.c1Offset].cseq; | |
1648 | ||
1649 | int vIdx = (m_current - 1) - prev.vOffset; | |
1650 | vs = m_buffer[vIdx].vseq; | |
1651 | isValid = isValidCVC(c1, vs, newCs); | |
1652 | ||
1653 | if (!isValid) | |
1654 | newCs = cs_nil; | |
1655 | } | |
1656 | ||
1657 | if (newCs == cs_nil) { | |
1658 | entry.form = vnw_nonVn; | |
1659 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
1660 | } | |
1661 | else { | |
1662 | if (prev.form == vnw_c) { | |
1663 | entry.form = vnw_c; | |
1664 | entry.c1Offset = 0; | |
1665 | entry.c2Offset = -1; | |
1666 | entry.vOffset = -1; | |
1667 | } | |
1668 | else if (prev.form == vnw_vc) { | |
1669 | entry.form = vnw_vc; | |
1670 | entry.c1Offset = -1; | |
1671 | entry.c2Offset = 0; | |
1672 | entry.vOffset = prev.vOffset + 1; | |
1673 | } | |
1674 | else { //vnw_cvc | |
1675 | entry.form = vnw_cvc; | |
1676 | entry.c1Offset = prev.c1Offset + 1; | |
1677 | entry.c2Offset = 0; | |
1678 | entry.vOffset = prev.vOffset + 1; | |
1679 | } | |
1680 | entry.cseq = newCs; | |
1681 | } | |
1682 | if (m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) | |
1683 | return 0; | |
1684 | markChange(m_current); | |
1685 | return 1; | |
1686 | } | |
1687 | ||
1688 | if (m_pCtrl->charsetId != CONV_CHARSET_UNI_CSTRING) | |
1689 | return 0; | |
1690 | markChange(m_current); | |
1691 | return 1; | |
1692 | } | |
1693 | ||
1694 | //---------------------------------------------------------- | |
1695 | int UkEngine::processEscChar(UkKeyEvent & ev) | |
1696 | { | |
1697 | if (m_pCtrl->vietKey && | |
1698 | m_current >=0 && m_buffer[m_current].form != vnw_empty && m_buffer[m_current].form != vnw_nonVn) { | |
1699 | m_toEscape = true; | |
1700 | } | |
1701 | return processAppend(ev); | |
1702 | } | |
1703 | ||
1704 | //---------------------------------------------------------- | |
1705 | void UkEngine::pass(int keyCode) | |
1706 | { | |
1707 | UkKeyEvent ev; | |
1708 | m_pCtrl->input.keyCodeToEvent(keyCode, ev); | |
1709 | processAppend(ev); | |
1710 | } | |
1711 | ||
1712 | //--------------------------------------------- | |
1713 | // This can be called only after other processing have been done. | |
1714 | // The new event is supposed to be put into m_buffer already | |
1715 | //--------------------------------------------- | |
1716 | int UkEngine::processNoSpellCheck(UkKeyEvent & ev) | |
1717 | { | |
1718 | WordInfo & entry = m_buffer[m_current]; | |
1719 | if (IsVnVowel[entry.vnSym]) { | |
1720 | entry.form = vnw_v; | |
1721 | entry.vOffset = 0; | |
1722 | entry.vseq = lookupVSeq(entry.vnSym); | |
1723 | entry.c1Offset = entry.c2Offset = -1; | |
1724 | } | |
1725 | else { | |
1726 | entry.form = vnw_c; | |
1727 | entry.c1Offset = 0; | |
1728 | entry.c2Offset = -1; | |
1729 | entry.vOffset = -1; | |
1730 | entry.cseq = lookupCSeq(entry.vnSym); | |
1731 | } | |
1732 | ||
1733 | if (ev.evType == vneNormal && | |
1734 | ((entry.keyCode >= 'a' && entry.keyCode <= 'z') || | |
1735 | (entry.keyCode >= 'A' && entry.keyCode <= 'Z') ) ) | |
1736 | return 0; | |
1737 | markChange(m_current); | |
1738 | return 1; | |
1739 | } | |
1740 | //---------------------------------------------------------- | |
1741 | int UkEngine::process(unsigned int keyCode, int & backs, unsigned char *outBuf, int & outSize, UkOutputType & outType) | |
1742 | { | |
1743 | UkKeyEvent ev; | |
1744 | prepareBuffer(); | |
1745 | m_backs = 0; | |
1746 | m_changePos = m_current+1; | |
1747 | m_pOutBuf = outBuf; | |
1748 | m_pOutSize = &outSize; | |
1749 | m_outputWritten = false; | |
1750 | m_reverted = false; | |
1751 | m_keyRestored = false; | |
1752 | m_keyRestoring = false; | |
1753 | m_outType = UkCharOutput; | |
1754 | ||
1755 | m_pCtrl->input.keyCodeToEvent(keyCode, ev); | |
1756 | ||
1757 | int ret; | |
1758 | if (!m_toEscape) { | |
1759 | ret = (this->*UkKeyProcList[ev.evType])(ev); | |
1760 | } | |
1761 | else { | |
1762 | m_toEscape = false; | |
1763 | if (m_current < 0 || ev.evType == vneNormal || ev.evType == vneEscChar) { | |
1764 | ret = processAppend(ev); | |
1765 | } | |
1766 | else { | |
1767 | m_current--; | |
1768 | processAppend(ev); | |
1769 | markChange(m_current); //this will assign m_backs to 1 and mark the character for output | |
1770 | ret = 1; | |
1771 | } | |
1772 | } | |
1773 | ||
1774 | if ( m_pCtrl->vietKey && | |
1775 | m_current >= 0 && m_buffer[m_current].form == vnw_nonVn && | |
1776 | ev.chType == ukcVn && | |
1777 | (!m_pCtrl->options.spellCheckEnabled || m_singleMode) ) | |
1778 | { | |
1779 | ||
1780 | //The spell check has failed, but because we are in non-spellcheck mode, | |
1781 | //we consider the new character as the beginning of a new word | |
1782 | ret = processNoSpellCheck(ev); | |
1783 | /* | |
1784 | if ((!m_pCtrl->options.spellCheckEnabled || m_singleMode) || | |
1785 | ( !m_reverted && | |
1786 | (m_current < 1 || m_buffer[m_current-1].form != vnw_nonVn)) ) { | |
1787 | ||
1788 | ret = processNoSpellCheck(ev); | |
1789 | } | |
1790 | */ | |
1791 | } | |
1792 | ||
1793 | //we add key to key buffer only if that key has not caused a reset | |
1794 | if (m_current >= 0) { | |
1795 | ev.chType = m_pCtrl->input.getCharType(ev.keyCode); | |
1796 | m_keyCurrent++; | |
1797 | m_keyStrokes[m_keyCurrent].ev = ev; | |
1798 | m_keyStrokes[m_keyCurrent].converted = (ret && !m_keyRestored); | |
1799 | } | |
1800 | ||
1801 | if (ret == 0) { | |
1802 | backs = 0; | |
1803 | outSize = 0; | |
1804 | outType = m_outType; | |
1805 | return 0; | |
1806 | } | |
1807 | ||
1808 | backs = m_backs; | |
1809 | if (!m_outputWritten) { | |
1810 | writeOutput(outBuf, outSize); | |
1811 | } | |
1812 | outType = m_outType; | |
1813 | ||
1814 | return ret; | |
1815 | } | |
1816 | ||
1817 | ||
1818 | //---------------------------------------------------------- | |
1819 | // Returns 0 on success | |
1820 | // error code otherwise | |
1821 | // outBuf: buffer to write | |
1822 | // outSize: [in] size of buffer in bytes | |
1823 | // [out] bytes written to buffer | |
1824 | //---------------------------------------------------------- | |
1825 | int UkEngine::writeOutput(unsigned char *outBuf, int & outSize) | |
1826 | { | |
1827 | StdVnChar stdChar; | |
1828 | int i, bytesWritten; | |
1829 | int ret = 1; | |
1830 | StringBOStream os(outBuf, outSize); | |
1831 | VnCharset *pCharset = VnCharsetLibObj.getVnCharset(m_pCtrl->charsetId); | |
1832 | pCharset->startOutput(); | |
1833 | ||
1834 | for (i = m_changePos; i <= m_current; i++) { | |
1835 | if (m_buffer[i].vnSym != vnl_nonVnChar) { | |
1836 | //process vn symbol | |
1837 | stdChar = m_buffer[i].vnSym + VnStdCharOffset; | |
1838 | if (m_buffer[i].caps) | |
1839 | stdChar--; | |
1840 | if (m_buffer[i].tone != 0) | |
1841 | stdChar += m_buffer[i].tone * 2; | |
1842 | } | |
1843 | else { | |
1844 | stdChar = IsoToStdVnChar(m_buffer[i].keyCode); | |
1845 | } | |
1846 | ||
1847 | if (stdChar != INVALID_STD_CHAR) | |
1848 | ret = pCharset->putChar(os, stdChar, bytesWritten); | |
1849 | } | |
1850 | ||
1851 | outSize = os.getOutBytes(); | |
1852 | return (ret? 0 : VNCONV_OUT_OF_MEMORY); | |
1853 | } | |
1854 | ||
1855 | //--------------------------------------------- | |
1856 | // Returns the number of backspaces needed to | |
1857 | // go back from last to first | |
1858 | //--------------------------------------------- | |
1859 | int UkEngine::getSeqSteps(int first, int last) | |
1860 | { | |
1861 | StdVnChar stdChar; | |
1862 | ||
1863 | if (last < first) | |
1864 | return 0; | |
1865 | ||
1866 | if (m_pCtrl->charsetId == CONV_CHARSET_XUTF8 || | |
1867 | m_pCtrl->charsetId == CONV_CHARSET_UNICODE) | |
1868 | return (last - first + 1); | |
1869 | ||
1870 | StringBOStream os(0, 0); | |
1871 | int i, bytesWritten; | |
1872 | ||
1873 | VnCharset *pCharset = VnCharsetLibObj.getVnCharset(m_pCtrl->charsetId); | |
1874 | pCharset->startOutput(); | |
1875 | ||
1876 | for (i = first; i <= last; i++) { | |
1877 | if (m_buffer[i].vnSym != vnl_nonVnChar) { | |
1878 | //process vn symbol | |
1879 | stdChar = m_buffer[i].vnSym + VnStdCharOffset; | |
1880 | if (m_buffer[i].caps) | |
1881 | stdChar--; | |
1882 | if (m_buffer[i].tone != 0) | |
1883 | stdChar += m_buffer[i].tone*2; | |
1884 | } | |
1885 | else { | |
1886 | stdChar = m_buffer[i].keyCode; | |
1887 | } | |
1888 | ||
1889 | if (stdChar != INVALID_STD_CHAR) | |
1890 | pCharset->putChar(os, stdChar, bytesWritten); | |
1891 | } | |
1892 | ||
1893 | int len = os.getOutBytes(); | |
1894 | if (m_pCtrl->charsetId == CONV_CHARSET_UNIDECOMPOSED) | |
1895 | len = len / 2; | |
1896 | return len; | |
1897 | } | |
1898 | ||
1899 | //--------------------------------------------- | |
1900 | void UkEngine::markChange(int pos) | |
1901 | { | |
1902 | if (pos < m_changePos) { | |
1903 | m_backs += getSeqSteps(pos, m_changePos-1); | |
1904 | m_changePos = pos; | |
1905 | } | |
1906 | } | |
1907 | ||
1908 | //---------------------------------------------------------------- | |
1909 | // Called from processBackspace to keep | |
1910 | // character buffer (m_buffer) and key stroke buffer in synch | |
1911 | //---------------------------------------------------------------- | |
1912 | void UkEngine::synchKeyStrokeBuffer() | |
1913 | { | |
1914 | //synchronize with key-stroke buffer | |
1915 | if (m_keyCurrent >= 0) | |
1916 | m_keyCurrent--; | |
1917 | if (m_current >= 0 && m_buffer[m_current].form == vnw_empty) { | |
1918 | //in character buffer, we have reached a word break, | |
1919 | //so we also need to move key stroke pointer backward to corresponding word break | |
1920 | while (m_keyCurrent >= 0 && m_keyStrokes[m_keyCurrent].ev.chType != ukcWordBreak) | |
1921 | { | |
1922 | m_keyCurrent--; | |
1923 | } | |
1924 | } | |
1925 | } | |
1926 | ||
1927 | //--------------------------------------------- | |
1928 | int UkEngine::processBackspace(int & backs, unsigned char *outBuf, int & outSize, UkOutputType & outType) | |
1929 | { | |
1930 | outType = UkCharOutput; | |
1931 | if (!m_pCtrl->vietKey || m_current < 0) { | |
1932 | backs = 0; | |
1933 | outSize = 0; | |
1934 | return 0; | |
1935 | } | |
1936 | ||
1937 | m_backs = 0; | |
1938 | m_changePos = m_current + 1; | |
1939 | markChange(m_current); | |
1940 | ||
1941 | if (m_current == 0 || | |
1942 | m_buffer[m_current].form == vnw_empty || | |
1943 | m_buffer[m_current].form == vnw_nonVn || | |
1944 | m_buffer[m_current].form == vnw_c || | |
1945 | m_buffer[m_current-1].form == vnw_c || | |
1946 | m_buffer[m_current-1].form == vnw_cvc || | |
1947 | m_buffer[m_current-1].form == vnw_vc) { | |
1948 | ||
1949 | m_current--; | |
1950 | backs = m_backs; | |
1951 | outSize = 0; | |
1952 | synchKeyStrokeBuffer(); | |
1953 | return (backs > 1); | |
1954 | } | |
1955 | ||
1956 | VowelSeq vs, newVs; | |
1957 | int curTonePos, newTonePos, tone, vStart, vEnd; | |
1958 | ||
1959 | vEnd = m_current - m_buffer[m_current].vOffset; | |
1960 | vs = m_buffer[vEnd].vseq; | |
1961 | vStart = vEnd - VSeqList[vs].len + 1; | |
1962 | newVs = m_buffer[m_current-1].vseq; | |
1963 | curTonePos = vStart + getTonePosition(vs, vEnd == m_current); | |
1964 | newTonePos = vStart + getTonePosition(newVs, true); | |
1965 | tone = m_buffer[curTonePos].tone; | |
1966 | ||
1967 | if (tone == 0 || curTonePos == newTonePos || | |
1968 | (curTonePos == m_current && m_buffer[m_current].tone != 0)) { | |
1969 | m_current--; | |
1970 | backs = m_backs; | |
1971 | outSize = 0; | |
1972 | synchKeyStrokeBuffer(); | |
1973 | return (backs > 1); | |
1974 | } | |
1975 | ||
1976 | markChange(newTonePos); | |
1977 | m_buffer[newTonePos].tone = tone; | |
1978 | markChange(curTonePos); | |
1979 | m_buffer[curTonePos].tone = 0; | |
1980 | m_current--; | |
1981 | synchKeyStrokeBuffer(); | |
1982 | backs = m_backs; | |
1983 | writeOutput(outBuf, outSize); | |
1984 | return 1; | |
1985 | } | |
1986 | ||
1987 | //------------------------------------------------ | |
1988 | void UkEngine::reset() | |
1989 | { | |
1990 | m_current = -1; | |
1991 | m_keyCurrent = -1; | |
1992 | m_singleMode = false; | |
1993 | m_toEscape = false; | |
1994 | } | |
1995 | ||
1996 | //------------------------------------------------ | |
1997 | void UkEngine::resetKeyBuf() | |
1998 | { | |
1999 | m_keyCurrent = -1; | |
2000 | } | |
2001 | ||
2002 | //------------------------------------------------ | |
2003 | UkEngine::UkEngine() | |
2004 | { | |
2005 | if (!m_classInit) { | |
2006 | engineClassInit(); | |
2007 | m_classInit = true; | |
2008 | } | |
2009 | m_pCtrl = 0; | |
2010 | m_bufSize = MAX_UK_ENGINE; | |
2011 | m_keyBufSize = MAX_UK_ENGINE; | |
2012 | m_current = -1; | |
2013 | m_keyCurrent = -1; | |
2014 | m_singleMode = false; | |
2015 | m_keyCheckFunc = 0; | |
2016 | m_reverted = false; | |
2017 | m_toEscape = false; | |
2018 | m_keyRestored = false; | |
2019 | } | |
2020 | ||
2021 | //---------------------------------------------------- | |
2022 | // make sure there are at least 10 entries available | |
2023 | //---------------------------------------------------- | |
2024 | void UkEngine::prepareBuffer() | |
2025 | { | |
2026 | int rid; | |
2027 | //prepare symbol buffer | |
2028 | if (m_current >= 0 && m_current + 10 >= m_bufSize) { | |
2029 | // Get rid of at least half of the current entries | |
2030 | // don't get rid from the middle of a word. | |
2031 | for (rid = m_current/2; m_buffer[rid].form != vnw_empty && rid < m_current; rid++); | |
2032 | if (rid == m_current) { | |
2033 | m_current = -1; | |
2034 | } | |
2035 | else { | |
2036 | rid++; | |
2037 | memmove(m_buffer, m_buffer+rid, (m_current-rid+1)*sizeof(WordInfo)); | |
2038 | m_current -= rid; | |
2039 | } | |
2040 | } | |
2041 | ||
2042 | //prepare key stroke buffer | |
2043 | if (m_keyCurrent > 0 && m_keyCurrent + 1 >= m_keyBufSize) { | |
2044 | // Get rid of at least half of the current entries | |
2045 | rid = m_keyCurrent/2; | |
2046 | memmove(m_keyStrokes, m_keyStrokes + rid, (m_keyCurrent-rid+1)*sizeof(m_keyStrokes[0])); | |
2047 | m_keyCurrent -= rid; | |
2048 | } | |
2049 | ||
2050 | } | |
2051 | ||
2052 | #define ENTER_CHAR 13 | |
2053 | enum VnCaseType {VnCaseNoChange, VnCaseAllCapital, VnCaseAllSmall}; | |
2054 | ||
2055 | //---------------------------------------------------- | |
2056 | int UkEngine::macroMatch(UkKeyEvent & ev) | |
2057 | { | |
2058 | int capsLockOn = 0; | |
2059 | int shiftPressed = 0; | |
2060 | if (m_keyCheckFunc) | |
2061 | m_keyCheckFunc(&shiftPressed, &capsLockOn); | |
2062 | ||
2063 | if (shiftPressed && (ev.keyCode ==' ' || ev.keyCode == ENTER_CHAR)) | |
2064 | return 0; | |
2065 | ||
2066 | const StdVnChar *pMacText = NULL; | |
2067 | StdVnChar key[MAX_MACRO_KEY_LEN+1]; | |
2068 | StdVnChar *pKeyStart; | |
2069 | ||
2070 | // Use static macro text so we can gain a bit of performance | |
2071 | // by avoiding memory allocation each time this function is called | |
2072 | static StdVnChar macroText[MAX_MACRO_TEXT_LEN+1]; | |
2073 | ||
2074 | int i, j; | |
2075 | ||
2076 | i = m_current; | |
2077 | while (i >= 0 && (m_current-i + 1) < MAX_MACRO_KEY_LEN) { | |
2078 | while (i>=0 && m_buffer[i].form != vnw_empty && (m_current-i + 1) < MAX_MACRO_KEY_LEN) | |
2079 | i--; | |
2080 | if (i>=0 && m_buffer[i].form != vnw_empty) | |
2081 | return 0; | |
2082 | ||
2083 | if (i>=0) { | |
2084 | if (m_buffer[i].vnSym != vnl_nonVnChar) { | |
2085 | key[0] = m_buffer[i].vnSym + VnStdCharOffset; | |
2086 | if (m_buffer[i].caps) | |
2087 | key[0]--; | |
2088 | key[0] += m_buffer[i].tone*2; | |
2089 | } | |
2090 | else | |
2091 | key[0] = m_buffer[i].keyCode; | |
2092 | } | |
2093 | ||
2094 | for (j=i+1; j<=m_current; j++) { | |
2095 | if (m_buffer[j].vnSym != vnl_nonVnChar) { | |
2096 | key[j-i] = m_buffer[j].vnSym + VnStdCharOffset; | |
2097 | if (m_buffer[j].caps) | |
2098 | key[j-i]--; | |
2099 | key[j-i] += m_buffer[j].tone*2; | |
2100 | } | |
2101 | else | |
2102 | key[j-i] = m_buffer[j].keyCode; | |
2103 | } | |
2104 | key[m_current-i+1] = 0; | |
2105 | //search macro table | |
2106 | pMacText = m_pCtrl->macStore.lookup(key+1); | |
2107 | if (pMacText) { | |
2108 | i++; //mark the position where change is needed | |
2109 | pKeyStart = key + 1; | |
2110 | break; | |
2111 | } | |
2112 | if (i>=0) { | |
2113 | pMacText = m_pCtrl->macStore.lookup(key); | |
2114 | if (pMacText) { | |
2115 | pKeyStart = key; | |
2116 | break; | |
2117 | } | |
2118 | } | |
2119 | i--; | |
2120 | } | |
2121 | ||
2122 | if (!pMacText) { | |
2123 | return 0; | |
2124 | } | |
2125 | ||
2126 | markChange(i); | |
2127 | ||
2128 | // determine the form of macro replacements: ALL CAPITALS, First Character Capital, or no change | |
2129 | VnCaseType macroCase; | |
2130 | if (IS_STD_VN_LOWER(*pKeyStart)) { | |
2131 | macroCase = VnCaseAllSmall; | |
2132 | } | |
2133 | else if (IS_STD_VN_UPPER(*pKeyStart)) { | |
2134 | macroCase = VnCaseAllCapital; | |
2135 | for (i=1; pKeyStart[i]; i++) { | |
2136 | if (IS_STD_VN_LOWER(pKeyStart[i])) { | |
2137 | macroCase = VnCaseNoChange; | |
2138 | } | |
2139 | } | |
2140 | } | |
2141 | else macroCase = VnCaseNoChange; | |
2142 | ||
2143 | // Convert case of macro text according to macroCase | |
2144 | int charCount = 0; | |
2145 | while (pMacText[charCount] != 0) | |
2146 | charCount++; | |
2147 | ||
2148 | for (i = 0; i < charCount; i++) | |
2149 | { | |
2150 | if (macroCase == VnCaseAllCapital) | |
2151 | macroText[i] = StdVnToUpper(pMacText[i]); | |
2152 | else if (macroCase == VnCaseAllSmall) | |
2153 | macroText[i] = StdVnToLower(pMacText[i]); | |
2154 | else | |
2155 | macroText[i] = pMacText[i]; | |
2156 | } | |
2157 | ||
2158 | // Convert to target output charset | |
2159 | int outSize; | |
2160 | int maxOutSize = *m_pOutSize; | |
2161 | int inLen = charCount * sizeof(StdVnChar); | |
2162 | VnConvert(CONV_CHARSET_VNSTANDARD, m_pCtrl->charsetId, | |
2163 | (UKBYTE *) macroText, (UKBYTE *)m_pOutBuf, | |
2164 | &inLen, &maxOutSize); | |
2165 | outSize = maxOutSize; | |
2166 | ||
2167 | //write the last input character | |
2168 | StdVnChar vnChar; | |
2169 | if (outSize < *m_pOutSize) { | |
2170 | maxOutSize = *m_pOutSize - outSize; | |
2171 | if (ev.vnSym != vnl_nonVnChar) | |
2172 | vnChar = ev.vnSym + VnStdCharOffset; | |
2173 | else | |
2174 | vnChar = ev.keyCode; | |
2175 | inLen = sizeof(StdVnChar); | |
2176 | VnConvert(CONV_CHARSET_VNSTANDARD, m_pCtrl->charsetId, | |
2177 | (UKBYTE *) &vnChar, ((UKBYTE *)m_pOutBuf) + outSize, | |
2178 | &inLen, &maxOutSize); | |
2179 | outSize += maxOutSize; | |
2180 | } | |
2181 | int backs = m_backs; //store m_backs before calling reset | |
2182 | reset(); | |
2183 | m_outputWritten = true; | |
2184 | m_backs = backs; | |
2185 | *m_pOutSize = outSize; | |
2186 | return 1; | |
2187 | } | |
2188 | ||
2189 | //---------------------------------------------------- | |
2190 | int UkEngine::restoreKeyStrokes(int & backs, unsigned char *outBuf, int & outSize, UkOutputType & outType) | |
2191 | { | |
2192 | outType = UkKeyOutput; | |
2193 | if (!lastWordHasVnMark()) { | |
2194 | backs = 0; | |
2195 | outSize = 0; | |
2196 | return 0; | |
2197 | } | |
2198 | ||
2199 | m_backs = 0; | |
2200 | m_changePos = m_current+1; | |
2201 | ||
2202 | int keyStart; | |
2203 | bool converted = false; | |
2204 | for (keyStart = m_keyCurrent; keyStart >= 0 && m_keyStrokes[keyStart].ev.chType != ukcWordBreak; keyStart--) { | |
2205 | if (m_keyStrokes[keyStart].converted) { | |
2206 | converted = true; | |
2207 | } | |
2208 | } | |
2209 | keyStart++; | |
2210 | ||
2211 | if (!converted) { | |
2212 | //no key stroke has been converted, so it doesn't make sense to restore key strokes | |
2213 | backs = 0; | |
2214 | outSize = 0; | |
2215 | return 0; | |
2216 | } | |
2217 | ||
2218 | //int i = m_current; | |
2219 | while (m_current >=0 && m_buffer[m_current].form != vnw_empty) | |
2220 | m_current--; | |
2221 | markChange(m_current+1); | |
2222 | backs = m_backs; | |
2223 | ||
2224 | int count; | |
2225 | int i; | |
2226 | UkKeyEvent ev; | |
2227 | m_keyRestoring = true; | |
2228 | for (i=keyStart, count = 0; i <= m_keyCurrent; i++) { | |
2229 | if (count<outSize) { | |
2230 | outBuf[count++] = (unsigned char)m_keyStrokes[i].ev.keyCode; | |
2231 | } | |
2232 | m_pCtrl->input.keyCodeToSymbol(m_keyStrokes[i].ev.keyCode, ev); | |
2233 | m_keyStrokes[i].converted = false; | |
2234 | processAppend(ev); | |
2235 | } | |
2236 | outSize = count; | |
2237 | m_keyRestoring = false; | |
2238 | ||
2239 | return 1; | |
2240 | } | |
2241 | ||
2242 | //-------------------------------------------------- | |
2243 | void UkEngine::setSingleMode() | |
2244 | { | |
2245 | m_singleMode = true; | |
2246 | } | |
2247 | ||
2248 | //-------------------------------------------------- | |
2249 | void SetupUnikeyEngine() | |
2250 | { | |
2251 | SetupInputClassifierTable(); | |
2252 | int i; | |
2253 | VnLexiName lexi; | |
2254 | ||
2255 | //Calculate IsoStdVnCharMap | |
2256 | for (i=0; i < 256; i++) { | |
2257 | IsoStdVnCharMap[i] = i; | |
2258 | } | |
2259 | ||
2260 | for (i=0; SpecialWesternChars[i]; i++) { | |
2261 | IsoStdVnCharMap[SpecialWesternChars[i]] = (vnl_lastChar + i) + VnStdCharOffset; | |
2262 | } | |
2263 | ||
2264 | for (i=0; i < 256; i++) { | |
2265 | if ((lexi = IsoToVnLexi(i)) != vnl_nonVnChar) { | |
2266 | IsoStdVnCharMap[i] = lexi + VnStdCharOffset; | |
2267 | } | |
2268 | } | |
2269 | } | |
2270 | ||
2271 | //-------------------------------------------------- | |
2272 | bool UkEngine::atWordBeginning() | |
2273 | { | |
2274 | return (m_current < 0 || m_buffer[m_current].form == vnw_empty); | |
2275 | } | |
2276 | ||
2277 | //-------------------------------------------------- | |
2278 | // Check for macro first, if there's a match, expand macro. If not: | |
2279 | // Spell-check, if is valid Vietnamese, return normally, if not: | |
2280 | // restore key strokes if auto-restore is enabled | |
2281 | //-------------------------------------------------- | |
2282 | int UkEngine::processWordEnd(UkKeyEvent & ev) | |
2283 | { | |
2284 | if (m_pCtrl->options.macroEnabled && macroMatch(ev)) | |
2285 | return 1; | |
2286 | ||
2287 | if (!m_pCtrl->options.spellCheckEnabled || m_singleMode || m_current < 0 || m_keyRestoring) { | |
2288 | m_current++; | |
2289 | WordInfo & entry = m_buffer[m_current]; | |
2290 | entry.form = vnw_empty; | |
2291 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
2292 | entry.keyCode = ev.keyCode; | |
2293 | entry.vnSym = vnToLower(ev.vnSym); | |
2294 | entry.caps = (entry.vnSym != ev.vnSym); | |
2295 | return 0; | |
2296 | } | |
2297 | ||
2298 | int outSize = 0; | |
2299 | if (m_pCtrl->options.autoNonVnRestore && lastWordIsNonVn()) { | |
2300 | outSize = *m_pOutSize; | |
2301 | if (restoreKeyStrokes(m_backs, m_pOutBuf, outSize, m_outType)) { | |
2302 | m_keyRestored = true; | |
2303 | m_outputWritten = true; | |
2304 | } | |
2305 | } | |
2306 | ||
2307 | m_current++; | |
2308 | WordInfo & entry = m_buffer[m_current]; | |
2309 | entry.form = vnw_empty; | |
2310 | entry.c1Offset = entry.c2Offset = entry.vOffset = -1; | |
2311 | entry.keyCode = ev.keyCode; | |
2312 | entry.vnSym = vnToLower(ev.vnSym); | |
2313 | entry.caps = (entry.vnSym != ev.vnSym); | |
2314 | ||
2315 | if (m_keyRestored && outSize < *m_pOutSize) { | |
2316 | m_pOutBuf[outSize] = ev.keyCode; | |
2317 | outSize++; | |
2318 | *m_pOutSize = outSize; | |
2319 | return 1; | |
2320 | } | |
2321 | ||
2322 | return 0; | |
2323 | } | |
2324 | ||
2325 | //--------------------------------------------------------------------------- | |
2326 | // Test if last word is a non-Vietnamese word, so that | |
2327 | // the engine can restore key strokes if it is indeed not a Vietnamese word | |
2328 | //--------------------------------------------------------------------------- | |
2329 | bool UkEngine::lastWordIsNonVn() | |
2330 | { | |
2331 | if (m_current < 0) | |
2332 | return false; | |
2333 | ||
2334 | switch (m_buffer[m_current].form) { | |
2335 | case vnw_nonVn: | |
2336 | return true; | |
2337 | case vnw_empty: | |
2338 | case vnw_c: | |
2339 | return false; | |
2340 | case vnw_v: | |
2341 | case vnw_cv: | |
2342 | return !VSeqList[m_buffer[m_current].vseq].complete; | |
2343 | case vnw_vc: | |
2344 | case vnw_cvc: { | |
2345 | int vIndex = m_current - m_buffer[m_current].vOffset; | |
2346 | VowelSeq vs = m_buffer[vIndex].vseq; | |
2347 | if (!VSeqList[vs].complete) | |
2348 | return true; | |
2349 | ConSeq cs = m_buffer[m_current].cseq; | |
2350 | ConSeq c1 = cs_nil; | |
2351 | if (m_buffer[m_current].c1Offset != -1) | |
2352 | c1 = m_buffer[m_current-m_buffer[m_current].c1Offset].cseq; | |
2353 | ||
2354 | if (!isValidCVC(c1, vs, cs)) { | |
2355 | return true; | |
2356 | } | |
2357 | ||
2358 | int tonePos = (vIndex - VSeqList[vs].len + 1) + getTonePosition(vs, false); | |
2359 | int tone = m_buffer[tonePos].tone; | |
2360 | if ((cs == cs_c || cs == cs_ch || cs == cs_p || cs == cs_t) && | |
2361 | (tone == 2 || tone == 3 || tone == 4)) | |
2362 | { | |
2363 | return true; | |
2364 | } | |
2365 | } | |
2366 | } | |
2367 | return false; | |
2368 | } | |
2369 | ||
2370 | //--------------------------------------------------------------------------- | |
2371 | // Test if last word has a Vietnamese mark, that is tones, decorators | |
2372 | //--------------------------------------------------------------------------- | |
2373 | bool UkEngine::lastWordHasVnMark() | |
2374 | { | |
2375 | for (int i=m_current; i>=0 && m_buffer[i].form != vnw_empty; i--) { | |
2376 | VnLexiName sym = m_buffer[i].vnSym; | |
2377 | if (sym != vnl_nonVnChar) { | |
2378 | if (IsVnVowel[sym]) { | |
2379 | if (m_buffer[i].tone) | |
2380 | return true; | |
2381 | } | |
2382 | if (sym != StdVnRootChar[sym] ) | |
2383 | return true; | |
2384 | } | |
2385 | } | |
2386 | return false; | |
2387 | } |
0 | // -*- mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #ifndef __UKENGINE_H | |
24 | #define __UKENGINE_H | |
25 | ||
26 | #include "charset.h" | |
27 | #include "vnlexi.h" | |
28 | #include "inputproc.h" | |
29 | #include "mactab.h" | |
30 | ||
31 | //This is a shared object among processes, do not put any pointer in it | |
32 | struct UkSharedMem { | |
33 | //states | |
34 | int initialized; | |
35 | int vietKey; | |
36 | ||
37 | UnikeyOptions options; | |
38 | UkInputProcessor input; | |
39 | int usrKeyMapLoaded; | |
40 | int usrKeyMap[256]; | |
41 | int charsetId; | |
42 | ||
43 | CMacroTable macStore; | |
44 | }; | |
45 | ||
46 | #define MAX_UK_ENGINE 128 | |
47 | ||
48 | enum VnWordForm {vnw_nonVn, vnw_empty, vnw_c, vnw_v, vnw_cv, vnw_vc, vnw_cvc}; | |
49 | ||
50 | typedef void (* CheckKeyboardCaseCb)(int *pShiftPressed, int *pCapslockOn); | |
51 | ||
52 | struct KeyBufEntry { | |
53 | UkKeyEvent ev; | |
54 | bool converted; | |
55 | }; | |
56 | ||
57 | class UkEngine | |
58 | { | |
59 | public: | |
60 | UkEngine(); | |
61 | void setCtrlInfo(UkSharedMem *p) | |
62 | { | |
63 | m_pCtrl = p; | |
64 | } | |
65 | ||
66 | void setCheckKbCaseFunc(CheckKeyboardCaseCb pFunc) | |
67 | { | |
68 | m_keyCheckFunc = pFunc; | |
69 | } | |
70 | ||
71 | bool atWordBeginning(); | |
72 | ||
73 | int process(unsigned int keyCode, int & backs, unsigned char *outBuf, int & outSize, UkOutputType & outType); | |
74 | void pass(int keyCode); //just pass through without filtering | |
75 | void setSingleMode(); | |
76 | ||
77 | int processBackspace(int & backs, unsigned char *outBuf, int & outSize, UkOutputType & outType); | |
78 | void reset(); | |
79 | int restoreKeyStrokes(int & backs, unsigned char *outBuf, int & outSize, UkOutputType & outType); | |
80 | ||
81 | //following methods must be public just to enable the use of pointers to them | |
82 | //they should not be called from outside. | |
83 | int processTone(UkKeyEvent & ev); | |
84 | int processRoof(UkKeyEvent & ev); | |
85 | int processHook(UkKeyEvent & ev); | |
86 | int processAppend(UkKeyEvent & ev); | |
87 | int appendVowel(UkKeyEvent & ev); | |
88 | int appendConsonnant(UkKeyEvent & ev); | |
89 | int processDd(UkKeyEvent & ev); | |
90 | int processMapChar(UkKeyEvent & ev); | |
91 | int processTelexW(UkKeyEvent & ev); | |
92 | int processEscChar(UkKeyEvent & ev); | |
93 | ||
94 | protected: | |
95 | static bool m_classInit; | |
96 | CheckKeyboardCaseCb m_keyCheckFunc; | |
97 | UkSharedMem *m_pCtrl; | |
98 | ||
99 | int m_changePos; | |
100 | int m_backs; | |
101 | int m_bufSize; | |
102 | int m_current; | |
103 | int m_singleMode; | |
104 | ||
105 | int m_keyBufSize; | |
106 | //unsigned int m_keyStrokes[MAX_UK_ENGINE]; | |
107 | KeyBufEntry m_keyStrokes[MAX_UK_ENGINE]; | |
108 | int m_keyCurrent; | |
109 | bool m_toEscape; | |
110 | ||
111 | //varables valid in one session | |
112 | unsigned char *m_pOutBuf; | |
113 | int *m_pOutSize; | |
114 | bool m_outputWritten; | |
115 | bool m_reverted; | |
116 | bool m_keyRestored; | |
117 | bool m_keyRestoring; | |
118 | UkOutputType m_outType; | |
119 | ||
120 | struct WordInfo { | |
121 | //info for word ending at this position | |
122 | VnWordForm form; | |
123 | int c1Offset, vOffset, c2Offset; | |
124 | ||
125 | union { | |
126 | VowelSeq vseq; | |
127 | ConSeq cseq; | |
128 | }; | |
129 | ||
130 | //info for current symbol | |
131 | int caps, tone; | |
132 | //canonical symbol, after caps, tone are removed | |
133 | //for non-Vn, vnSym == -1 | |
134 | VnLexiName vnSym; | |
135 | int keyCode; | |
136 | }; | |
137 | ||
138 | WordInfo m_buffer[MAX_UK_ENGINE]; | |
139 | ||
140 | int processHookWithUO(UkKeyEvent & ev); | |
141 | int macroMatch(UkKeyEvent & ev); | |
142 | void markChange(int pos); | |
143 | void prepareBuffer(); //make sure we have a least 10 entries available | |
144 | int writeOutput(unsigned char *outBuf, int & outSize); | |
145 | //int getSeqLength(int first, int last); | |
146 | int getSeqSteps(int first, int last); | |
147 | int getTonePosition(VowelSeq vs, bool terminated); | |
148 | void resetKeyBuf(); | |
149 | int checkEscapeVIQR(UkKeyEvent & ev); | |
150 | int processNoSpellCheck(UkKeyEvent & ev); | |
151 | int processWordEnd(UkKeyEvent & ev); | |
152 | void synchKeyStrokeBuffer(); | |
153 | bool lastWordHasVnMark(); | |
154 | bool lastWordIsNonVn(); | |
155 | }; | |
156 | ||
157 | void SetupUnikeyEngine(); | |
158 | ||
159 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | UniKey - Open-source Vietnamese Keyboard | |
3 | Copyright (C) 1998-2004 Pham Kim Long | |
4 | Contact: | |
5 | longcz@yahoo.com | |
6 | http://unikey.sf.net | |
7 | ||
8 | This program is free software; you can redistribute it and/or | |
9 | modify it under the terms of the GNU General Public License | |
10 | as published by the Free Software Foundation; either version 2 | |
11 | of the License, or (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
21 | --------------------------------------------------------------------------------*/ | |
22 | ||
23 | #include <ctype.h> | |
24 | #include <memory.h> | |
25 | #include <stdio.h> | |
26 | #include <iostream> | |
27 | #include "unikey.h" | |
28 | #include "ukengine.h" | |
29 | #include "usrkeymap.h" | |
30 | ||
31 | using namespace std; | |
32 | ||
33 | //---- exported variables for use in UkEnginge class ---- | |
34 | UkSharedMem *pShMem = 0; | |
35 | ||
36 | UkEngine MyKbEngine; | |
37 | ||
38 | int UnikeyCapsLockOn = 0; | |
39 | int UnikeyShiftPressed = 0; | |
40 | //---------------------------------------------------- | |
41 | ||
42 | unsigned char UnikeyBuf[1024]; | |
43 | int UnikeyBackspaces; | |
44 | int UnikeyBufChars; | |
45 | UkOutputType UnikeyOutput; | |
46 | ||
47 | //-------------------------------------------- | |
48 | void UnikeySetInputMethod(UkInputMethod im) | |
49 | { | |
50 | if (im == UkTelex || im == UkVni || im == UkSimpleTelex || im == UkSimpleTelex2) { | |
51 | pShMem->input.setIM(im); | |
52 | MyKbEngine.reset(); | |
53 | } | |
54 | else if (im == UkUsrIM && pShMem->usrKeyMapLoaded) { | |
55 | //cout << "Switched to user mode\n"; //DEBUG | |
56 | pShMem->input.setIM(pShMem->usrKeyMap); | |
57 | MyKbEngine.reset(); | |
58 | } | |
59 | ||
60 | //cout << "IM changed to: " << im << endl; //DEBUG | |
61 | } | |
62 | ||
63 | ||
64 | //-------------------------------------------- | |
65 | void UnikeySetCapsState(int shiftPressed, int CapsLockOn) | |
66 | { | |
67 | //UnikeyCapsAll = (shiftPressed && !CapsLockOn) || (!shiftPressed && CapsLockOn); | |
68 | UnikeyCapsLockOn = CapsLockOn; | |
69 | UnikeyShiftPressed = shiftPressed; | |
70 | } | |
71 | ||
72 | //-------------------------------------------- | |
73 | int UnikeySetOutputCharset(int charset) | |
74 | { | |
75 | pShMem->charsetId = charset; | |
76 | MyKbEngine.reset(); | |
77 | return 1; | |
78 | } | |
79 | ||
80 | //-------------------------------------------- | |
81 | void UnikeySetOptions(UnikeyOptions *pOpt) | |
82 | { | |
83 | pShMem->options.freeMarking = pOpt->freeMarking; | |
84 | pShMem->options.modernStyle = pOpt->modernStyle; | |
85 | pShMem->options.macroEnabled = pOpt->macroEnabled; | |
86 | pShMem->options.useUnicodeClipboard = pOpt->useUnicodeClipboard; | |
87 | pShMem->options.alwaysMacro = pOpt->alwaysMacro; | |
88 | pShMem->options.spellCheckEnabled = pOpt->spellCheckEnabled; | |
89 | pShMem->options.autoNonVnRestore = pOpt->autoNonVnRestore; | |
90 | } | |
91 | ||
92 | //-------------------------------------------- | |
93 | void UnikeyGetOptions(UnikeyOptions *pOpt) | |
94 | { | |
95 | *pOpt = pShMem->options; | |
96 | } | |
97 | ||
98 | //-------------------------------------------- | |
99 | void CreateDefaultUnikeyOptions(UnikeyOptions *pOpt) | |
100 | { | |
101 | pOpt->freeMarking = 1; | |
102 | pOpt->modernStyle = 0; | |
103 | pOpt->macroEnabled = 0; | |
104 | pOpt->useUnicodeClipboard = 0; | |
105 | pOpt->alwaysMacro = 0; | |
106 | pOpt->spellCheckEnabled = 1; | |
107 | pOpt->autoNonVnRestore = 0; | |
108 | } | |
109 | ||
110 | //-------------------------------------------- | |
111 | void UnikeyCheckKbCase(int *pShiftPressed, int *pCapsLockOn) | |
112 | { | |
113 | *pShiftPressed = UnikeyShiftPressed; | |
114 | *pCapsLockOn = UnikeyCapsLockOn; | |
115 | } | |
116 | ||
117 | //-------------------------------------------- | |
118 | void UnikeySetup() | |
119 | { | |
120 | SetupUnikeyEngine(); | |
121 | pShMem = new UkSharedMem; | |
122 | pShMem->input.init(); | |
123 | pShMem->macStore.init(); | |
124 | pShMem->vietKey = 1; | |
125 | pShMem->usrKeyMapLoaded = 0; | |
126 | MyKbEngine.setCtrlInfo(pShMem); | |
127 | MyKbEngine.setCheckKbCaseFunc(&UnikeyCheckKbCase); | |
128 | UnikeySetInputMethod(UkTelex); | |
129 | UnikeySetOutputCharset(CONV_CHARSET_XUTF8); | |
130 | pShMem->initialized = 1; | |
131 | CreateDefaultUnikeyOptions(&pShMem->options); | |
132 | } | |
133 | ||
134 | //-------------------------------------------- | |
135 | void UnikeyCleanup() | |
136 | { | |
137 | delete pShMem; | |
138 | } | |
139 | ||
140 | //-------------------------------------------- | |
141 | void UnikeyFilter(unsigned int ch) | |
142 | { | |
143 | UnikeyBufChars = sizeof(UnikeyBuf); | |
144 | MyKbEngine.process(ch, UnikeyBackspaces, UnikeyBuf, UnikeyBufChars, UnikeyOutput); | |
145 | } | |
146 | ||
147 | //-------------------------------------------- | |
148 | void UnikeyPutChar(unsigned int ch) | |
149 | { | |
150 | MyKbEngine.pass(ch); | |
151 | UnikeyBufChars = 0; | |
152 | UnikeyBackspaces = 0; | |
153 | } | |
154 | ||
155 | //-------------------------------------------- | |
156 | void UnikeyResetBuf() | |
157 | { | |
158 | MyKbEngine.reset(); | |
159 | } | |
160 | ||
161 | //-------------------------------------------- | |
162 | void UnikeySetSingleMode() | |
163 | { | |
164 | MyKbEngine.setSingleMode(); | |
165 | } | |
166 | ||
167 | //-------------------------------------------- | |
168 | void UnikeyBackspacePress() | |
169 | { | |
170 | UnikeyBufChars = sizeof(UnikeyBuf); | |
171 | MyKbEngine.processBackspace(UnikeyBackspaces, UnikeyBuf, UnikeyBufChars, UnikeyOutput); | |
172 | // printf("Backspaces: %d\n",UnikeyBackspaces); | |
173 | } | |
174 | ||
175 | //-------------------------------------------- | |
176 | int UnikeyLoadMacroTable(const char *fileName) | |
177 | { | |
178 | return pShMem->macStore.loadFromFile(fileName); | |
179 | } | |
180 | ||
181 | //-------------------------------------------- | |
182 | int UnikeyLoadUserKeyMap(const char *fileName) | |
183 | { | |
184 | if (UkLoadKeyMap(fileName, pShMem->usrKeyMap)) { | |
185 | //cout << "User key map loaded!\n"; //DEBUG | |
186 | pShMem->usrKeyMapLoaded = 1; | |
187 | return 1; | |
188 | } | |
189 | return 0; | |
190 | } | |
191 | ||
192 | //-------------------------------------------- | |
193 | void UnikeyRestoreKeyStrokes() | |
194 | { | |
195 | UnikeyBufChars = sizeof(UnikeyBuf); | |
196 | MyKbEngine.restoreKeyStrokes(UnikeyBackspaces, UnikeyBuf, UnikeyBufChars, UnikeyOutput); | |
197 | } | |
198 | ||
199 | bool UnikeyAtWordBeginning() | |
200 | { | |
201 | return MyKbEngine.atWordBeginning(); | |
202 | } | |
203 |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | UniKey - Open-source Vietnamese Keyboard | |
3 | Copyright (C) 2000-2005 Pham Kim Long | |
4 | Contact: | |
5 | unikey@gmail.com | |
6 | http://unikey.org | |
7 | ||
8 | This program is free software; you can redistribute it and/or | |
9 | modify it under the terms of the GNU General Public License | |
10 | as published by the Free Software Foundation; either version 2 | |
11 | of the License, or (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
21 | --------------------------------------------------------------------------------*/ | |
22 | ||
23 | #ifndef __UNIKEY_H | |
24 | #define __UNIKEY_H | |
25 | ||
26 | #include "keycons.h" | |
27 | ||
28 | /*---------------------------------------------------- | |
29 | Initialization steps: | |
30 | 1. UnikeySetup: This will initialized Unikey module, | |
31 | with default options, input method = TELEX, output format = UTF-8 | |
32 | 2. If you want a different settings: | |
33 | + Call UnikeySetInputMethod to change input method | |
34 | + Call UnikeySetOutputVIQR/UTF8 to chang output format | |
35 | + Call UnikeySetOptions to change extra options | |
36 | ||
37 | Key event handling: | |
38 | ||
39 | - Call UnikeyFilter when a key event occurs, examine results in | |
40 | + UnikeyBackspaces: number of backspaces that need to be sent | |
41 | + UnikeyBufChars: number of chars in buffer that need to be sent | |
42 | + UnikeyAnsiBuf: buffer containing output characters. | |
43 | + UnikeyUniBuf: not used | |
44 | ||
45 | You should also call UnikeySetCapsState() before calling UnikeyFilter. | |
46 | ||
47 | To make this module portable across platforms, UnikeyFilter should not | |
48 | be called on special keys: Enter, Tab, movement keys, delete, backspace... | |
49 | ||
50 | - Special events: | |
51 | + Call UnikeyResetBuf to reset the engine's state in situations such as: | |
52 | focus lost, movement keys: arrow keys, pgup, pgdown.... | |
53 | + If a backspace is received, call UnikeyBackspacePress, | |
54 | then examine the result: | |
55 | UnikeyBackspaces is the number of backspaces actually required to | |
56 | remove one character. | |
57 | ||
58 | Clean up: | |
59 | - When the Engine is no longer needed, call UnikeyCleanup | |
60 | ------------------------------------------------------*/ | |
61 | ||
62 | #if defined(__cplusplus) | |
63 | extern "C" { | |
64 | #endif | |
65 | extern unsigned char UnikeyBuf[]; | |
66 | extern int UnikeyBackspaces; | |
67 | extern int UnikeyBufChars; | |
68 | extern UkOutputType UnikeyOutput; | |
69 | ||
70 | void UnikeySetup(); // always call this first | |
71 | void UnikeyCleanup(); // call this when unloading unikey module | |
72 | ||
73 | // call this to reset Unikey's state when focus, context is changed or | |
74 | // some control key is pressed | |
75 | void UnikeyResetBuf(); | |
76 | ||
77 | // main handler, call every time a character input is received | |
78 | void UnikeyFilter(unsigned int ch); | |
79 | void UnikeyPutChar(unsigned int ch); // put new char without filtering | |
80 | ||
81 | // call this before UnikeyFilter for correctly processing some TELEX shortcuts | |
82 | void UnikeySetCapsState(int shiftPressed, int CapsLockOn); | |
83 | ||
84 | // call this when backspace is pressed | |
85 | void UnikeyBackspacePress(); | |
86 | ||
87 | // call this to restore to original key strokes | |
88 | void UnikeyRestoreKeyStrokes(); | |
89 | ||
90 | //set extra options | |
91 | void UnikeySetOptions(UnikeyOptions *pOpt); | |
92 | void CreateDefaultUnikeyOptions(UnikeyOptions *pOpt); | |
93 | ||
94 | void UnikeyGetOptions(UnikeyOptions *pOpt); | |
95 | ||
96 | // set input method | |
97 | // im: TELEX_INPUT, VNI_INPUT, VIQR_INPUT, VIQR_STAR_INPUT | |
98 | void UnikeySetInputMethod(UkInputMethod im); | |
99 | // set output format | |
100 | // void UnikeySetOutputVIQR(); | |
101 | // void UnikeySetOutputUTF8(); | |
102 | int UnikeySetOutputCharset(int charset); | |
103 | ||
104 | int UnikeyLoadMacroTable(const char *fileName); | |
105 | int UnikeyLoadUserKeyMap(const char *fileName); | |
106 | ||
107 | //call this to enable typing vietnamese even in a non-vn sequence | |
108 | //e.g: GD&DDT,QDDND... | |
109 | //The engine will return to normal mode when a word-break occurs. | |
110 | void UnikeySetSingleMode(); | |
111 | ||
112 | bool UnikeyAtWordBeginning(); | |
113 | #if defined(__cplusplus) | |
114 | } | |
115 | #endif | |
116 | ||
117 | #endif |
0 | // -*- mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include <iostream> | |
24 | #include <string.h> | |
25 | #include <stdio.h> | |
26 | using namespace std; | |
27 | ||
28 | #include <ctype.h> | |
29 | #include "usrkeymap.h" | |
30 | ||
31 | ||
32 | int getLabelIndex(int action); | |
33 | void initKeyMap(int keyMap[256]); | |
34 | ||
35 | #define OPT_COMMENT_CHAR ';' | |
36 | ||
37 | struct UkEventLabelPair | |
38 | { | |
39 | char label[32]; | |
40 | int ev; | |
41 | }; | |
42 | ||
43 | UkEventLabelPair UkEvLabelList[] = { | |
44 | {"Tone0", vneTone0}, | |
45 | {"Tone1", vneTone1}, | |
46 | {"Tone2", vneTone2}, | |
47 | {"Tone3", vneTone3}, | |
48 | {"Tone4", vneTone4}, | |
49 | {"Tone5", vneTone5}, | |
50 | {"Roof-All", vneRoofAll}, | |
51 | {"Roof-A", vneRoof_a}, | |
52 | {"Roof-E", vneRoof_e}, | |
53 | {"Roof-O", vneRoof_o}, | |
54 | {"Hook-Bowl", vneHookAll}, | |
55 | {"Hook-UO", vneHook_uo}, | |
56 | {"Hook-U", vneHook_u}, | |
57 | {"Hook-O", vneHook_o}, | |
58 | {"Bowl", vneBowl}, | |
59 | {"D-Mark", vneDd}, | |
60 | {"Telex-W", vne_telex_w}, | |
61 | {"Escape", vneEscChar}, | |
62 | {"DD", vneCount + vnl_DD}, | |
63 | {"dd", vneCount + vnl_dd}, | |
64 | {"A^", vneCount + vnl_Ar}, | |
65 | {"a^", vneCount + vnl_ar}, | |
66 | {"A(", vneCount + vnl_Ab}, | |
67 | {"a(", vneCount + vnl_ab}, | |
68 | {"E^", vneCount + vnl_Er}, | |
69 | {"e^", vneCount + vnl_er}, | |
70 | {"O^", vneCount + vnl_Or}, | |
71 | {"o^", vneCount + vnl_or}, | |
72 | {"O+", vneCount + vnl_Oh}, | |
73 | {"o+", vneCount + vnl_oh}, | |
74 | {"U+", vneCount + vnl_Uh}, | |
75 | {"u+", vneCount + vnl_uh} | |
76 | }; | |
77 | ||
78 | const int UkEvLabelCount = sizeof(UkEvLabelList)/sizeof(UkEventLabelPair); | |
79 | ||
80 | //-------------------------------------------------- | |
81 | static int parseNameValue(char *line, char **name, char **value) | |
82 | { | |
83 | char *p, *mark; | |
84 | char ch; | |
85 | ||
86 | if (line == 0) | |
87 | return 0; | |
88 | ||
89 | // get rid of comment | |
90 | p = strchr(line, OPT_COMMENT_CHAR); | |
91 | if (p) | |
92 | *p = 0; | |
93 | ||
94 | //get option name | |
95 | for (p=line; *p == ' '; p++); | |
96 | if (*p == 0) | |
97 | return 0; | |
98 | ||
99 | *name = p; | |
100 | mark = p; //mark the last non-space character | |
101 | p++; | |
102 | while ((ch=*p) != '=' && ch!=0) { | |
103 | if (ch != ' ') | |
104 | mark = p; | |
105 | p++; | |
106 | } | |
107 | ||
108 | if (ch == 0) | |
109 | return 0; | |
110 | *(mark+1) = 0; //terminate name with a null character | |
111 | ||
112 | //get option value | |
113 | p++; | |
114 | while (*p == ' ') p++; | |
115 | if (*p == 0) | |
116 | return 0; | |
117 | ||
118 | *value = p; | |
119 | mark = p; | |
120 | while (*p) { //strip trailing spaces | |
121 | if (*p != ' ') | |
122 | mark = p; | |
123 | p++; | |
124 | } | |
125 | *++mark = 0; | |
126 | return 1; | |
127 | } | |
128 | ||
129 | //----------------------------------------------------- | |
130 | DllExport int UkLoadKeyMap(const char *fileName, int keyMap[256]) | |
131 | { | |
132 | int i, mapCount; | |
133 | UkKeyMapPair orderMap[256]; | |
134 | if (!UkLoadKeyOrderMap(fileName, orderMap, &mapCount)) | |
135 | return 0; | |
136 | ||
137 | initKeyMap(keyMap); | |
138 | for (i=0; i < mapCount; i++) { | |
139 | keyMap[orderMap[i].key] = orderMap[i].action; | |
140 | if (orderMap[i].action < vneCount) { | |
141 | keyMap[tolower(orderMap[i].key)] = orderMap[i].action; | |
142 | } | |
143 | } | |
144 | return 1; | |
145 | } | |
146 | ||
147 | //------------------------------------------------------------------ | |
148 | DllExport int UkLoadKeyOrderMap(const char *fileName, UkKeyMapPair *pMap, int *pMapCount) | |
149 | { | |
150 | FILE *f; | |
151 | char *buf; | |
152 | char *name, *value; | |
153 | size_t len; | |
154 | int i, bufSize, lineCount; | |
155 | unsigned char c; | |
156 | int mapCount; | |
157 | int keyMap[256]; | |
158 | ||
159 | f = fopen(fileName, "r"); | |
160 | if (f == 0) { | |
161 | cerr << "Failed to open file: " << fileName << endl; | |
162 | return 0; | |
163 | } | |
164 | ||
165 | initKeyMap(keyMap); | |
166 | bufSize = 256; | |
167 | buf = new char[bufSize]; | |
168 | ||
169 | lineCount = 0; | |
170 | mapCount = 0; | |
171 | while (!feof(f)) { | |
172 | if (fgets((char *)buf, bufSize, f) == 0) | |
173 | break; | |
174 | lineCount++; | |
175 | len = strlen(buf); | |
176 | if (len == 0) | |
177 | break; | |
178 | ||
179 | if (buf[len-1] == '\n') | |
180 | buf[len-1] = 0; | |
181 | if (parseNameValue(buf, (char **)&name, (char **)&value)) { | |
182 | if (strlen(name) == 1) { | |
183 | for (i=0; i < UkEvLabelCount; i++) { | |
184 | if (strcmp(UkEvLabelList[i].label, value) == 0) { | |
185 | c = (unsigned char)name[0]; | |
186 | if (keyMap[c] != vneNormal) { | |
187 | //already assigned, don't accept this map | |
188 | break; | |
189 | } | |
190 | //cout << "key: " << c << " value: " << UkEvLabelList[i].ev << endl; //DEBUG | |
191 | keyMap[c] = UkEvLabelList[i].ev; | |
192 | pMap[mapCount].action = UkEvLabelList[i].ev; | |
193 | if (keyMap[c] < vneCount) { | |
194 | pMap[mapCount].key = toupper(c); | |
195 | keyMap[toupper(c)] = UkEvLabelList[i].ev; | |
196 | } | |
197 | else { | |
198 | pMap[mapCount].key = c; | |
199 | } | |
200 | mapCount++; | |
201 | break; | |
202 | } | |
203 | } | |
204 | if (i == UkEvLabelCount) { | |
205 | cerr << "Error in user key layout, line " << lineCount << ": command not found" << endl; | |
206 | } | |
207 | } | |
208 | else { | |
209 | cerr << "Error in user key layout, line " << lineCount | |
210 | << ": key name is not a single character" << endl; | |
211 | } | |
212 | } | |
213 | } | |
214 | delete [] buf; | |
215 | fclose(f); | |
216 | ||
217 | *pMapCount = mapCount; | |
218 | ||
219 | return 1; | |
220 | } | |
221 | ||
222 | //------------------------------------------- | |
223 | void initKeyMap(int keyMap[256]) | |
224 | { | |
225 | unsigned int c; | |
226 | for (c=0; c<256; c++) | |
227 | keyMap[c] = vneNormal; | |
228 | } | |
229 | ||
230 | const char *UkKeyMapHeader = | |
231 | "; This is UniKey user-defined key mapping file, generated from UniKey (Windows)\n\n"; | |
232 | ||
233 | DllExport int UkStoreKeyOrderMap(const char *fileName, UkKeyMapPair *pMap, int mapCount) | |
234 | { | |
235 | FILE *f; | |
236 | int i; | |
237 | int labelIndex; | |
238 | char line[128]; | |
239 | ||
240 | f = fopen(fileName, "wt"); | |
241 | if (f == 0) { | |
242 | cerr << "Failed to open file: " << fileName << endl; | |
243 | return 0; | |
244 | } | |
245 | ||
246 | fputs(UkKeyMapHeader, f); | |
247 | for (i=0; i < mapCount; i++) { | |
248 | labelIndex = getLabelIndex(pMap[i].action); | |
249 | if (labelIndex != -1) { | |
250 | sprintf(line, "%c = %s\n", pMap[i].key, UkEvLabelList[labelIndex].label); | |
251 | fputs(line, f); | |
252 | } | |
253 | } | |
254 | fclose(f); | |
255 | return 1; | |
256 | } | |
257 | ||
258 | int getLabelIndex(int event) | |
259 | { | |
260 | int i; | |
261 | for (i = 0; i < UkEvLabelCount; i++) { | |
262 | if (UkEvLabelList[i].ev == event) | |
263 | return i; | |
264 | } | |
265 | return -1; | |
266 | } |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #ifndef __UNIKEY_USER_KEY_MAP_H | |
24 | #define __UNIKEY_USER_KEY_MAP_H | |
25 | ||
26 | #include "inputproc.h" | |
27 | struct UkKeyMapPair { | |
28 | unsigned char key; | |
29 | int action; | |
30 | }; | |
31 | ||
32 | DllInterface int UkLoadKeyMap(const char *fileName, int keyMap[256]); | |
33 | DllInterface int UkLoadKeyOrderMap(const char *fileName, UkKeyMapPair *pMap, int *pMapCount); | |
34 | DllInterface int UkStoreKeyOrderMap(const char *fileName, UkKeyMapPair *pMap, int mapCount); | |
35 | ||
36 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /*------------------------------------------------------------------------------ | |
2 | VnConv: Vietnamese Encoding Converter Library | |
3 | UniKey Project: http://unikey.sourceforge.net | |
4 | Copyleft (C) 1998-2002 Pham Kim Long | |
5 | Contact: longp@cslab.felk.cvut.cz | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License | |
9 | as published by the Free Software Foundation; either version 2 | |
10 | of the License, or (at your option) any later version. | |
11 | ||
12 | This program 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 | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 | --------------------------------------------------------------------------------*/ | |
21 | ||
22 | // | |
23 | #ifndef __VN_CONVERT_H | |
24 | #define __VN_CONVERT_H | |
25 | ||
26 | #if defined(_WIN32) | |
27 | #if defined(UNIKEYHOOK) | |
28 | #define DllInterface __declspec( dllexport ) | |
29 | #else | |
30 | #define DllInterface __declspec( dllimport ) | |
31 | #endif | |
32 | #define DllExport __declspec( dllexport ) | |
33 | #define DllImport __declspec( dllimport ) | |
34 | #else | |
35 | #define DllInterface //not used | |
36 | #define DllExport | |
37 | #define DllImport | |
38 | #endif | |
39 | ||
40 | #define CONV_CHARSET_UNICODE 0 | |
41 | #define CONV_CHARSET_UNIUTF8 1 | |
42 | #define CONV_CHARSET_UNIREF 2 //&#D; | |
43 | #define CONV_CHARSET_UNIREF_HEX 3 | |
44 | #define CONV_CHARSET_UNIDECOMPOSED 4 | |
45 | #define CONV_CHARSET_WINCP1258 5 | |
46 | #define CONV_CHARSET_UNI_CSTRING 6 | |
47 | #define CONV_CHARSET_VNSTANDARD 7 | |
48 | ||
49 | #define CONV_CHARSET_VIQR 10 | |
50 | #define CONV_CHARSET_UTF8VIQR 11 | |
51 | #define CONV_CHARSET_XUTF8 12 | |
52 | ||
53 | #define CONV_CHARSET_TCVN3 20 | |
54 | #define CONV_CHARSET_VPS 21 | |
55 | #define CONV_CHARSET_VISCII 22 | |
56 | #define CONV_CHARSET_BKHCM1 23 | |
57 | #define CONV_CHARSET_VIETWAREF 24 | |
58 | #define CONV_CHARSET_ISC 25 | |
59 | ||
60 | #define CONV_CHARSET_VNIWIN 40 | |
61 | #define CONV_CHARSET_BKHCM2 41 | |
62 | #define CONV_CHARSET_VIETWAREX 42 | |
63 | #define CONV_CHARSET_VNIMAC 43 | |
64 | ||
65 | #define CONV_TOTAL_SINGLE_CHARSETS 6 | |
66 | #define CONV_TOTAL_DOUBLE_CHARSETS 4 | |
67 | ||
68 | ||
69 | #define IS_SINGLE_BYTE_CHARSET(x) (x >= CONV_CHARSET_TCVN3 && x < CONV_CHARSET_TCVN3+CONV_TOTAL_SINGLE_CHARSETS) | |
70 | #define IS_DOUBLE_BYTE_CHARSET(x) (x >= CONV_CHARSET_VNIWIN && x < CONV_CHARSET_VNIWIN+CONV_TOTAL_DOUBLE_CHARSETS) | |
71 | ||
72 | typedef unsigned char UKBYTE; | |
73 | ||
74 | #if defined(__cplusplus) | |
75 | extern "C" { | |
76 | #endif | |
77 | DllInterface int VnConvert(int inCharset, int outCharset, UKBYTE *input, UKBYTE *output, | |
78 | int * pInLen, int * pMaxOutLen); | |
79 | ||
80 | DllInterface int VnFileConvert(int inCharset, int outCharset, const char *inFile, const char *outFile); | |
81 | ||
82 | #if defined(__cplusplus) | |
83 | } | |
84 | #endif | |
85 | ||
86 | DllInterface const char * VnConvErrMsg(int errCode); | |
87 | ||
88 | enum VnConvError { | |
89 | VNCONV_NO_ERROR, | |
90 | VNCONV_UNKNOWN_ERROR, | |
91 | VNCONV_INVALID_CHARSET, | |
92 | VNCONV_ERR_INPUT_FILE, | |
93 | VNCONV_ERR_OUTPUT_FILE, | |
94 | VNCONV_OUT_OF_MEMORY, | |
95 | VNCONV_ERR_WRITING, | |
96 | VNCONV_LAST_ERROR | |
97 | }; | |
98 | ||
99 | typedef struct _CharsetNameId CharsetNameId; | |
100 | ||
101 | struct _CharsetNameId { | |
102 | const char *name; | |
103 | int id; | |
104 | }; | |
105 | ||
106 | typedef struct _VnConvOptions VnConvOptions; | |
107 | ||
108 | struct _VnConvOptions { | |
109 | int viqrMixed; | |
110 | int viqrEsc; | |
111 | int toUpper; | |
112 | int toLower; | |
113 | int removeTone; | |
114 | int smartViqr; | |
115 | }; | |
116 | ||
117 | DllInterface void VnConvSetOptions(VnConvOptions *pOptions); | |
118 | DllInterface void VnConvGetOptions(VnConvOptions *pOptions); | |
119 | DllInterface void VnConvResetOptions(VnConvOptions *pOptions); | |
120 | ||
121 | #endif |
0 | // -*- coding:unix; mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- | |
1 | /* Unikey Vietnamese Input Method | |
2 | * Copyright (C) 2000-2005 Pham Kim Long | |
3 | * Contact: | |
4 | * unikey@gmail.com | |
5 | * UniKey project: http://unikey.org | |
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 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 | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #ifndef __VN_LEXI_H | |
24 | #define __VN_LEXI_H | |
25 | ||
26 | enum VnLexiName { | |
27 | vnl_nonVnChar = -1, | |
28 | vnl_A, vnl_a, vnl_A1, vnl_a1, vnl_A2, vnl_a2, vnl_A3, vnl_a3, vnl_A4, vnl_a4, vnl_A5, vnl_a5, | |
29 | vnl_Ar, vnl_ar, vnl_Ar1, vnl_ar1, vnl_Ar2, vnl_ar2, vnl_Ar3, vnl_ar3, vnl_Ar4, vnl_ar4, vnl_Ar5, vnl_ar5, | |
30 | vnl_Ab, vnl_ab, vnl_Ab1, vnl_ab1, vnl_Ab2, vnl_ab2, vnl_Ab3, vnl_ab3, vnl_Ab4, vnl_ab4, vnl_Ab5, vnl_ab5, | |
31 | vnl_B, vnl_b, vnl_C, vnl_c, | |
32 | vnl_D, vnl_d, vnl_DD, vnl_dd, | |
33 | vnl_E, vnl_e, vnl_E1, vnl_e1, vnl_E2, vnl_e2, vnl_E3, vnl_e3, vnl_E4, vnl_e4, vnl_E5, vnl_e5, | |
34 | vnl_Er, vnl_er, vnl_Er1, vnl_er1, vnl_Er2, vnl_er2, vnl_Er3, vnl_er3, vnl_Er4, vnl_er4, vnl_Er5, vnl_er5, | |
35 | vnl_F, vnl_f, vnl_G, vnl_g, vnl_H, vnl_h, | |
36 | vnl_I, vnl_i, vnl_I1, vnl_i1, vnl_I2, vnl_i2, vnl_I3, vnl_i3, vnl_I4, vnl_i4, vnl_I5, vnl_i5, | |
37 | vnl_J, vnl_j, vnl_K, vnl_k, vnl_L, vnl_l, vnl_M, vnl_m, vnl_N, vnl_n, | |
38 | vnl_O, vnl_o, vnl_O1, vnl_o1, vnl_O2, vnl_o2, vnl_O3, vnl_o3, vnl_O4, vnl_o4, vnl_O5, vnl_o5, | |
39 | vnl_Or, vnl_or, vnl_Or1, vnl_or1, vnl_Or2, vnl_or2, vnl_Or3, vnl_or3, vnl_Or4, vnl_or4, vnl_Or5, vnl_or5, | |
40 | vnl_Oh, vnl_oh, vnl_Oh1, vnl_oh1, vnl_Oh2, vnl_oh2, vnl_Oh3, vnl_oh3, vnl_Oh4, vnl_oh4, vnl_Oh5, vnl_oh5, | |
41 | vnl_P, vnl_p, vnl_Q, vnl_q, vnl_R, vnl_r, vnl_S, vnl_s, vnl_T, vnl_t, | |
42 | vnl_U, vnl_u, vnl_U1, vnl_u1, vnl_U2, vnl_u2, vnl_U3, vnl_u3, vnl_U4, vnl_u4, vnl_U5, vnl_u5, | |
43 | vnl_Uh, vnl_uh, vnl_Uh1, vnl_uh1, vnl_Uh2, vnl_uh2, vnl_Uh3, vnl_uh3, vnl_Uh4, vnl_uh4, vnl_Uh5, vnl_uh5, | |
44 | vnl_V, vnl_v, vnl_W, vnl_w, vnl_X, vnl_x, | |
45 | vnl_Y, vnl_y, vnl_Y1, vnl_y1, vnl_Y2, vnl_y2, vnl_Y3, vnl_y3, vnl_Y4, vnl_y4, vnl_Y5, vnl_y5, | |
46 | vnl_Z, vnl_z, | |
47 | ||
48 | vnl_lastChar, | |
49 | }; | |
50 | ||
51 | enum VowelSeq { | |
52 | vs_nil = -1, | |
53 | vs_a, | |
54 | vs_ar, | |
55 | vs_ab, | |
56 | vs_e, | |
57 | vs_er, | |
58 | vs_i, | |
59 | vs_o, | |
60 | vs_or, | |
61 | vs_oh, | |
62 | vs_u, | |
63 | vs_uh, | |
64 | vs_y, | |
65 | vs_ai, | |
66 | vs_ao, | |
67 | vs_au, | |
68 | vs_ay, | |
69 | vs_aru, | |
70 | vs_ary, | |
71 | vs_eo, | |
72 | vs_eu, | |
73 | vs_eru, | |
74 | vs_ia, | |
75 | vs_ie, | |
76 | vs_ier, | |
77 | vs_iu, | |
78 | vs_oa, | |
79 | vs_oab, | |
80 | vs_oe, | |
81 | vs_oi, | |
82 | vs_ori, | |
83 | vs_ohi, | |
84 | vs_ua, | |
85 | vs_uar, | |
86 | vs_ue, | |
87 | vs_uer, | |
88 | vs_ui, | |
89 | vs_uo, | |
90 | vs_uor, | |
91 | vs_uoh, | |
92 | vs_uu, | |
93 | vs_uy, | |
94 | vs_uha, | |
95 | vs_uhi, | |
96 | vs_uho, | |
97 | vs_uhoh, | |
98 | vs_uhu, | |
99 | vs_ye, | |
100 | vs_yer, | |
101 | vs_ieu, | |
102 | vs_ieru, | |
103 | vs_oai, | |
104 | vs_oay, | |
105 | vs_oeo, | |
106 | vs_uay, | |
107 | vs_uary, | |
108 | vs_uoi, | |
109 | vs_uou, | |
110 | vs_uori, | |
111 | vs_uohi, | |
112 | vs_uohu, | |
113 | vs_uya, | |
114 | vs_uye, | |
115 | vs_uyer, | |
116 | vs_uyu, | |
117 | vs_uhoi, | |
118 | vs_uhou, | |
119 | vs_uhohi, | |
120 | vs_uhohu, | |
121 | vs_yeu, | |
122 | vs_yeru | |
123 | }; | |
124 | ||
125 | enum ConSeq { | |
126 | cs_nil = -1, | |
127 | cs_b, | |
128 | cs_c, | |
129 | cs_ch, | |
130 | cs_d, | |
131 | cs_dd, | |
132 | cs_dz, | |
133 | cs_g, | |
134 | cs_gh, | |
135 | cs_gi, | |
136 | cs_gin, | |
137 | cs_h, | |
138 | cs_k, | |
139 | cs_kh, | |
140 | cs_l, | |
141 | cs_m, | |
142 | cs_n, | |
143 | cs_ng, | |
144 | cs_ngh, | |
145 | cs_nh, | |
146 | cs_p, | |
147 | cs_ph, | |
148 | cs_q, | |
149 | cs_qu, | |
150 | cs_r, | |
151 | cs_s, | |
152 | cs_t, | |
153 | cs_th, | |
154 | cs_tr, | |
155 | cs_v, | |
156 | cs_x | |
157 | }; | |
158 | ||
159 | ||
160 | ||
161 | #endif |