Line data Source code
1 : /* -*- coding: utf-8 -*- */
2 : /* Copyright (C) 2013 by Jose Da Silva */
3 : /*
4 : * Redistribution and use in source and binary forms, with or without
5 : * modification, are permitted provided that the following conditions are met:
6 :
7 : * Redistributions of source code must retain the above copyright notice, this
8 : * list of conditions and the following disclaimer.
9 :
10 : * Redistributions in binary form must reproduce the above copyright notice,
11 : * this list of conditions and the following disclaimer in the documentation
12 : * and/or other materials provided with the distribution.
13 :
14 : * The name of the author may not be used to endorse or promote products
15 : * derived from this software without specific prior written permission.
16 :
17 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : */
28 :
29 : #ifndef _GUTILS_UNICODELIBINFO_C_
30 : #define _GUTILS_UNICODELIBINFO_C_
31 :
32 : #include <fontforge-config.h>
33 :
34 : #include "unicodelibinfo.h"
35 : #include <ustring.h>
36 : #include "../fontforge/ffglib.h"
37 : #include <glib/gprintf.h>
38 : #include "xvasprintf.h"
39 :
40 :
41 : #ifndef _NO_LIBUNINAMESLIST
42 : #include <uninameslist.h>
43 : #else
44 : struct unicode_block {
45 : int start, end;
46 : const char *name;
47 : };
48 : #endif
49 : const struct unicode_nameannot * const *const *_UnicodeNameAnnot = NULL; /* deprecated */
50 : const struct unicode_block *_UnicodeBlock = NULL;
51 : #ifndef _NO_LIBUNICODENAMES
52 : #include <libunicodenames.h>
53 : uninm_names_db names_db; /* Unicode character names and annotations database */
54 : uninm_blocks_db blocks_db;
55 : #endif
56 :
57 : static char *chosung[] = { "G", "GG", "N", "D", "DD", "L", "M", "B", "BB", "S", "SS", "", "J", "JJ", "C", "K", "T", "P", "H", NULL };
58 : static char *jungsung[] = { "A", "AE", "YA", "YAE", "EO", "E", "YEO", "YE", "O", "WA", "WAE", "OE", "YO", "U", "WEO", "WE", "WI", "YU", "EU", "YI", "I", NULL };
59 : static char *jongsung[] = { "", "G", "GG", "GS", "N", "NJ", "NH", "D", "L", "LG", "LM", "LB", "LS", "LT", "LP", "LH", "M", "B", "BS", "S", "SS", "NG", "J", "C", "K", "T", "P", "H", NULL };
60 :
61 40 : void inituninameannot(void) {
62 : /* Initialize unicode name-annotation library access for FontForge */
63 : /* TODO: Library pluginloading currently disabled - see 20120731-b */
64 : /* for existing code if you want to re-enable this feature again. */
65 :
66 : #if _NO_LIBUNINAMESLIST
67 40 : _UnicodeNameAnnot = NULL; /* libuninameslist not available */
68 40 : _UnicodeBlock = NULL;
69 : #else
70 : /* backward compatibility for other programs using libuninames */
71 : _UnicodeNameAnnot = UnicodeNameAnnot;
72 : _UnicodeBlock = UnicodeBlock;
73 : #endif
74 :
75 : #ifndef _NO_LIBUNICODENAMES
76 : /* Open database file, read data for this 'local', then close. */
77 : char *names_db_file;
78 : char *blocks_db_file;
79 :
80 : /* Load character names and annotations that come from the Unicode NamesList.txt */
81 : /* This should not be done until after the locale has been set */
82 : names_db_file = uninm_find_names_db(NULL);
83 : names_db = (names_db_file == NULL) ? ((uninm_names_db) 0) : uninm_names_db_open(names_db_file);
84 : free(names_db_file);
85 : /* NOTE: you need to do uninm_names_db_close(names_db); when you exit program */
86 :
87 : blocks_db_file = uninm_find_blocks_db(NULL);
88 : blocks_db = (blocks_db_file == NULL) ? ((uninm_blocks_db) 0) : uninm_blocks_db_open(blocks_db_file);
89 : free(blocks_db_file);
90 : /* NOTE: you need to do uninm_blocks_db_close(blocks_db); when you exit program */
91 : #endif
92 40 : }
93 :
94 0 : char *unicode_name(int32 unienc) {
95 : /* Return the unicode name for the value given from a data library. */
96 : /* If there's no data available for this code, or no library, return NULL */
97 : /* User should free the return string when finished with this information */
98 :
99 : #if _NO_LIBUNINAMESLIST && _NO_LIBUNICODENAMES
100 : /* no nameslist library code available to use */
101 : //fprintf(stderr,"no library\n");
102 0 : return( NULL );
103 : #else
104 : /* have nameslist library code available to use */
105 : if ( unienc<0 || unienc>=0x110000 )
106 : return( NULL );
107 :
108 : char *name_data=NULL;
109 : #ifndef _NO_LIBUNINAMESLIST
110 : #if (_LIBUNINAMESLIST_FUN <= 3)
111 : /* old libuninameslist library code */
112 : if ( _UnicodeNameAnnot!=NULL &&
113 : _UnicodeNameAnnot[unienc>>16][(unienc>>8)&0xff][unienc&0xff].name!=NULL ) {
114 : name_data=copy(_UnicodeNameAnnot[unienc>>16][(unienc>>8)&0xff][unienc&0xff].name);
115 : }
116 : //fprintf(stderr,"use old code library ->%s<-\n",name_data);
117 : #else
118 : /* new libuninameslist library code */
119 : name_data=copy(uniNamesList_name(unienc));
120 : //fprintf(stderr,"new library ->%s<-\n",name_data\n");
121 : #endif
122 : #else
123 : /* libunicodesnames library code */
124 : name_data=copy(uninm_name(names_db,(unsigned int)(unienc)));
125 : //fprintf(stderr,"libunicodes library ->%s<-\n",name_data);
126 : #endif
127 :
128 : /* George Williams' improvisation on Hangul Syllable range
129 : * As of Unicode 6.3.0 0xAC00 - 0xD7A3 is defined as a block
130 : * without individual code point names.
131 : * Code moved here from fontforgeexe/fontview.c
132 : * FIXME: maybe this belongs to lower library stack instead,
133 : * revisit later.
134 : */
135 : if( ( unienc >= 0xAC00 && unienc <= 0xD7A3 ) && ( name_data == NULL ) ) {
136 : if( ( ( unienc - 0xAC00 ) % 28 ) == 0 ) {
137 : name_data = xasprintf( "Hangul Syllable %s-%s",
138 : chosung [ (unienc - 0xAC00) / (21*28) ],
139 : jungsung[ ((unienc - 0xAC00) / 28 ) % 21 ] );
140 : } else {
141 : name_data = xasprintf( "Hangul Syllable %s-%s-%s",
142 : chosung [ (unienc - 0xAC00) / (21*28) ],
143 : jungsung[ ((unienc - 0xAC00) / 28 ) % 21 ],
144 : jongsung[ (unienc - 0xAC00) % 28 ] );
145 : }
146 : }
147 :
148 : return( name_data );
149 : #endif
150 : }
151 :
152 : #ifndef _NO_LIBUNINAMESLIST
153 : static char *unicode_nicer(const char *from) {
154 : /* Return nicer looking unicode annotations by changing the '*' to bullet */
155 : /* and other markers to fancier utf8 style symbols. if empty, return NULL */
156 : /* User should free the return string when finished with this information */
157 : const char *pf;
158 : char ch,*to,*pt;
159 : long c;
160 : int l;
161 :
162 : if ( from==NULL )
163 : return( NULL );
164 :
165 : /* check if we need to convert some chars to bullets and symbols */
166 : c=l=0;
167 : for ( pf=from; (ch=*pf++)!='\0'; ++l ) if ( ch=='\t' ) {
168 : /* require extra space for these larger utf8 type chars */
169 : if ( *pf=='*' || *pf=='x' || *pf==':' || *pf=='#' ) ++c;
170 : }
171 :
172 : if ( (pt=to=malloc(l+c+c+1))!=NULL ) {
173 : if ( c ) {
174 : while ( (ch=*pt++=*from++)!='\0' ) if (ch=='\t' ) {
175 : if ( *from=='*' ) {
176 : c=0x2022; goto unicode_expand_c; /* 0x2022, bullet */
177 : } else if ( *from=='x' ) {
178 : c=0x2192; goto unicode_expand_c; /* 0x2192, right-arrow */
179 : } else if ( *from==':' ) {
180 : c=0x224d; goto unicode_expand_c; /* 0x224d, nearly equal */
181 : } else if ( *from=='#' ) {
182 : c=0x2245; goto unicode_expand_c; /* 0x2245, approx equal */
183 : unicode_expand_c:
184 : ++from;
185 : *pt++ =0xe0+((c>>12)&0x0f);
186 : *pt++ =0x80+((c>>6)&0x3f);
187 : *pt++ =0x80+(c&0x3f);
188 : }
189 : }
190 : } else
191 : /* simply copy information verbatim, without the need to edit */
192 : while ( (*pt++=*from++)!='\0' );
193 : }
194 :
195 : return( to );
196 : }
197 :
198 : static int unicode_block_check(int block_i) {
199 : #if (_LIBUNINAMESLIST_FUN <= 3)
200 : /* Older uninameslist database needs to be checked from start since we do */
201 : /* not know which is the last block. Currently this should be around 234. */
202 : if ( _UnicodeBlock!=NULL ) {
203 : int i;
204 :
205 : for ( i=0; i<block_i; ++i )
206 : if ( _UnicodeBlock[i].end>=0x10ffff )
207 : break;
208 : if ( i==block_i )
209 : return( i );
210 : }
211 : return( -1 );
212 : #else
213 : /* libuninameslist-0.4.2014____ has a function to return block count. */
214 : if ( _UnicodeBlock!=NULL && block_i < uniNamesList_blockCount() )
215 : return( block_i );
216 : return( -1 );
217 : #endif
218 : }
219 : #endif
220 :
221 0 : char *unicode_annot(int32 unienc) {
222 : /* Return the unicode annotation for the value given from a data library. */
223 : /* If there's no data available for this code, or no library, return NULL */
224 : /* User should free the return string when finished with this information */
225 :
226 : #if _NO_LIBUNINAMESLIST && _NO_LIBUNICODENAMES
227 : /* no nameslist library code available to use */
228 : //fprintf(stderr,"no library - annotation\n");
229 0 : return( NULL );
230 : #else
231 : /* have nameslist library code available to use */
232 : if ( unienc<0 || unienc>=0x110000 )
233 : return( NULL );
234 :
235 : char *annot_data=NULL;
236 :
237 : #ifndef _NO_LIBUNINAMESLIST
238 : #if (_LIBUNINAMESLIST_FUN <= 3)
239 : /* old libuninameslist library code */
240 : if ( _UnicodeNameAnnot!=NULL &&
241 : _UnicodeNameAnnot[unienc>>16][(unienc>>8)&0xff][unienc&0xff].annot!=NULL ) {
242 : annot_data=unicode_nicer(_UnicodeNameAnnot[unienc>>16][(unienc>>8)&0xff][unienc&0xff].annot);
243 : }
244 : //fprintf(stderr,"use old code unicode_annot() - annotation ->%s<-\n",annot_data);
245 : #else
246 : /* new libuninameslist library code */
247 : annot_data=unicode_nicer(uniNamesList_annot(unienc));
248 : //fprintf(stderr,"new unicode_annot() - annotation ->%s<-\n",annot_data);
249 : #endif
250 : #else
251 : /* libunicodesnames library code */
252 : annot_data=copy(uninm_annotation(names_db,(unsigned int)(unienc)));
253 : //fprintf(stderr,"libunicodes unicode_annot() - annotation ->%s<-\n",annot_data);
254 : #endif
255 :
256 : return( annot_data );
257 : #endif
258 : }
259 :
260 0 : int32 unicode_block_count(void) {
261 : /* Return the number of unicode blocks contained in this NameList library */
262 : #if _NO_LIBUNINAMESLIST && _NO_LIBUNICODENAMES
263 : /* no nameslist library available to use */
264 0 : return( -1 );
265 : #else
266 : int32 unicount;
267 :
268 : unicount=-1;
269 : #ifndef _NO_LIBUNINAMESLIST
270 : #if (_LIBUNINAMESLIST_FUN >= 4)
271 : /* version 0.4+ have function to do this */
272 : unicount=uniNamesList_blockCount();
273 : //fprintf(stderr,"ver 0.4+ unicode_block_count(), have %d\n",unicount);
274 : #else
275 : /* old libuninameslist<=0.3 library code */
276 : if ( _UnicodeBlock!=NULL ) {
277 : int i;
278 :
279 : for ( i=0; i<100000; ++i )
280 : if ( _UnicodeBlock[i].end>=0x10ffff )
281 : break;
282 : if ( i>0 )
283 : unicount = i;
284 : //fprintf(stderr,"old code unicode_block_count(), have %d, %d\n",i,unicount);
285 : }
286 : #endif
287 : #else
288 : /* libunicodesnames library code */
289 : unicount=uninm_num_blocks(blocks_db);
290 : //fprintf(stderr,"libunicodes unicode_block_count() have %d\n",unicount);
291 : #endif
292 :
293 : return( unicount );
294 : #endif
295 : }
296 :
297 0 : int32 unicode_block_start(int32 block_i) {
298 : /* Return the unicode value for the start of next unicode block. If no */
299 : /* library or data available, then return -1. */
300 :
301 : #if _NO_LIBUNINAMESLIST && _NO_LIBUNICODENAMES
302 : /* no nameslist library available to use */
303 : //fprintf(stderr,"no block library\n");
304 0 : return( -1 );
305 : #else
306 : int32 unistart;
307 :
308 : unistart=-1;
309 : #ifndef _NO_LIBUNINAMESLIST
310 : #if (_LIBUNINAMESLIST_FUN >= 4)
311 : /* version 0.4+ have function to do this */
312 : unistart=uniNamesList_blockStart(block_i);
313 : //fprintf(stderr,"ver 0.4+ code unicode_block_start(), have %d %d\n",block_i,unistart);
314 : #else
315 : /* old libuninameslist<=0.3 library code */
316 : if ( (unistart=unicode_block_check(block_i))>=0 )
317 : unistart=_UnicodeBlock[unistart].start;
318 : //fprintf(stderr,"use old code unicode_block_start(), have %d %d\n",block_i,unistart);
319 : #endif
320 : #else
321 : /* libunicodesnames library code */
322 : unistart=uninm_block_start(blocks_db,(unsigned int)(block_i));
323 : //fprintf(stderr,"libunicodes unicode_block_start()have %d %d\n",block_i,unistart);
324 : #endif
325 :
326 : return( unistart );
327 : #endif
328 : }
329 :
330 0 : int32 unicode_block_end(int32 block_i) {
331 : /* Return the unicode value for the end of this unicode block. If there */
332 : /* is no library or data available, then return -1 */
333 :
334 : #if _NO_LIBUNINAMESLIST && _NO_LIBUNICODENAMES
335 : /* no nameslist library available to use */
336 : //fprintf(stderr,"no block library\n");
337 0 : return( -1 );
338 : #else
339 : int32 uniend;
340 :
341 : uniend=-1;
342 : #ifndef _NO_LIBUNINAMESLIST
343 : #if (_LIBUNINAMESLIST_FUN >= 4)
344 : /* version 0.4+ have function to do this */
345 : uniend=uniNamesList_blockEnd(block_i);
346 : //fprintf(stderr,"ver 0.4+ code unicode_block_end(), have %d %d\n",block_i,uniend);
347 : #else
348 : /* old libuninameslist<=0.3 library code */
349 : if ( (uniend=unicode_block_check(block_i))>=0 )
350 : uniend=_UnicodeBlock[uniend].end;
351 : //fprintf(stderr,"use old code unicode_block_end(), have %d %d\n",block_i,uniend);
352 : #endif
353 : #else
354 : /* libunicodesnames library code */
355 : uniend=uninm_block_end(blocks_db,(unsigned int)(block_i));
356 : //fprintf(stderr,"libunicodes unicode_block_end(), have %d %d\n",block_i,uniend);
357 : #endif
358 :
359 : return( uniend );
360 : #endif
361 : }
362 :
363 0 : char *unicode_block_name(int32 block_i) {
364 : /* Return the unicode name for this unicode block. If there is no library */
365 : /* then return NULL */
366 :
367 : #if _NO_LIBUNINAMESLIST && _NO_LIBUNICODENAMES
368 : /* no nameslist library code available to use */
369 : //fprintf(stderr,"no library\n");
370 0 : return( NULL );
371 : #else
372 : char *name_data=NULL;
373 : #ifndef _NO_LIBUNINAMESLIST
374 : #if (_LIBUNINAMESLIST_FUN >= 4)
375 : /* version 0.4+ have function to do this */
376 : name_data=copy(uniNamesList_blockName(block_i));
377 : //fprintf(stderr,"ver 0.4+ code unicode_block_name(), have %d ->%s<-\n",block_i,name_data);
378 : #else
379 : int i;
380 : /* old libuninameslist<=0.3 library code */
381 : if ( (i=unicode_block_check(block_i))>=0 )
382 : name_data=copy(_UnicodeBlock[i].name);
383 : //fprintf(stderr,"use old code unicode_block_name(), have %d %d ->%s<-\n",i,block_i,name_data);
384 : #endif
385 : #else
386 : /* libunicodesnames library code */
387 : name_data=copy(uninm_block_name(blocks_db,(unsigned int)(block_i)));
388 : //fprintf(stderr,"libunicodes unicode_block_name() %d ->%s<-\n",block_i,name_data);
389 : #endif
390 :
391 : return( name_data );
392 : #endif
393 : }
394 :
395 0 : char *unicode_library_version(void) {
396 : /* Return the unicode version for this library. Sometimes users still use */
397 : /* older libuninameslist or libunincodenames libraries because they don't */
398 : /* realize that these need to be updated to keep current too but not made */
399 : /* at same time that FontForge is released (release dates not in sync). */
400 :
401 : #if !(_NO_LIBUNINAMESLIST) && (_LIBUNINAMESLIST_FUN >= 3)
402 : /* libuninameslist-0.3.20130501-1 and later have a "version" function */
403 : char *version_str;
404 :
405 : version_str=copy(uniNamesList_NamesListVersion());
406 :
407 : return( version_str );
408 : #else
409 : /* Libunicodenames and older versions of libuninames don't have a ver */
410 : /* function so we need to either test various annotations to find out */
411 : /* what version we have, or we keep it simple and just return nothing */
412 0 : return( NULL );
413 : #endif
414 : }
415 :
416 : #endif
|