LCOV - code coverage report
Current view: top level - gutils - unicodelibinfo.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 4 18 22.2 %
Date: 2017-08-04 Functions: 1 8 12.5 %

          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

Generated by: LCOV version 1.10