1 //========================================================================
5 // Copyright 2001-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
22 #include "GlobalParams.h"
23 #include "UnicodeMap.h"
25 //------------------------------------------------------------------------
29 struct UnicodeMapExt
{
30 Unicode u
; // Unicode char
31 char code
[maxExtCode
];
35 //------------------------------------------------------------------------
37 UnicodeMap
*UnicodeMap::parse(GString
*encodingNameA
) {
40 UnicodeMapRange
*range
;
44 int line
, nBytes
, i
, x
;
45 char *tok1
, *tok2
, *tok3
;
47 if (!(f
= globalParams
->getUnicodeMapFile(encodingNameA
))) {
48 error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
49 encodingNameA
->getCString());
53 map
= new UnicodeMap(encodingNameA
->copy());
56 map
->ranges
= (UnicodeMapRange
*)gmalloc(size
* sizeof(UnicodeMapRange
));
60 while (getLine(buf
, sizeof(buf
), f
)) {
61 if ((tok1
= strtok(buf
, " \t\r\n")) &&
62 (tok2
= strtok(NULL
, " \t\r\n"))) {
63 if (!(tok3
= strtok(NULL
, " \t\r\n"))) {
67 nBytes
= strlen(tok3
) / 2;
69 if (map
->len
== size
) {
71 map
->ranges
= (UnicodeMapRange
*)
72 grealloc(map
->ranges
, size
* sizeof(UnicodeMapRange
));
74 range
= &map
->ranges
[map
->len
];
75 sscanf(tok1
, "%x", &range
->start
);
76 sscanf(tok2
, "%x", &range
->end
);
77 sscanf(tok3
, "%x", &range
->code
);
78 range
->nBytes
= nBytes
;
80 } else if (tok2
== tok1
) {
81 if (map
->eMapsLen
== eMapsSize
) {
83 map
->eMaps
= (UnicodeMapExt
*)
84 grealloc(map
->eMaps
, eMapsSize
* sizeof(UnicodeMapExt
));
86 eMap
= &map
->eMaps
[map
->eMapsLen
];
87 sscanf(tok1
, "%x", &eMap
->u
);
88 for (i
= 0; i
< nBytes
; ++i
) {
89 sscanf(tok3
+ i
*2, "%2x", &x
);
90 eMap
->code
[i
] = (char)x
;
92 eMap
->nBytes
= nBytes
;
95 error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
96 line
, encodingNameA
->getCString());
99 error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
100 line
, encodingNameA
->getCString());
110 UnicodeMap::UnicodeMap(GString
*encodingNameA
) {
111 encodingName
= encodingNameA
;
113 kind
= unicodeMapUser
;
124 UnicodeMap::UnicodeMap(char *encodingNameA
, GBool unicodeOutA
,
125 UnicodeMapRange
*rangesA
, int lenA
) {
126 encodingName
= new GString(encodingNameA
);
127 unicodeOut
= unicodeOutA
;
128 kind
= unicodeMapResident
;
139 UnicodeMap::UnicodeMap(char *encodingNameA
, GBool unicodeOutA
,
140 UnicodeMapFunc funcA
) {
141 encodingName
= new GString(encodingNameA
);
142 unicodeOut
= unicodeOutA
;
143 kind
= unicodeMapFunc
;
153 UnicodeMap::~UnicodeMap() {
155 if (kind
== unicodeMapUser
&& ranges
) {
162 gDestroyMutex(&mutex
);
166 void UnicodeMap::incRefCnt() {
172 gUnlockMutex(&mutex
);
176 void UnicodeMap::decRefCnt() {
182 done
= --refCnt
== 0;
184 gUnlockMutex(&mutex
);
191 GBool
UnicodeMap::match(GString
*encodingNameA
) {
192 return !encodingName
->cmp(encodingNameA
);
195 int UnicodeMap::mapUnicode(Unicode u
, char *buf
, int bufSize
) {
196 int a
, b
, m
, n
, i
, j
;
199 if (kind
== unicodeMapFunc
) {
200 return (*func
)(u
, buf
, bufSize
);
205 if (u
>= ranges
[a
].start
) {
206 // invariant: ranges[a].start <= u < ranges[b].start
209 if (u
>= ranges
[m
].start
) {
211 } else if (u
< ranges
[m
].start
) {
215 if (u
<= ranges
[a
].end
) {
216 n
= ranges
[a
].nBytes
;
220 code
= ranges
[a
].code
+ (u
- ranges
[a
].start
);
221 for (i
= n
- 1; i
>= 0; --i
) {
222 buf
[i
] = (char)(code
& 0xff);
229 for (i
= 0; i
< eMapsLen
; ++i
) {
230 if (eMaps
[i
].u
== u
) {
232 for (j
= 0; j
< n
; ++j
) {
233 buf
[j
] = eMaps
[i
].code
[j
];
242 //------------------------------------------------------------------------
244 UnicodeMapCache::UnicodeMapCache() {
247 for (i
= 0; i
< unicodeMapCacheSize
; ++i
) {
252 UnicodeMapCache::~UnicodeMapCache() {
255 for (i
= 0; i
< unicodeMapCacheSize
; ++i
) {
257 cache
[i
]->decRefCnt();
262 UnicodeMap
*UnicodeMapCache::getUnicodeMap(GString
*encodingName
) {
266 if (cache
[0] && cache
[0]->match(encodingName
)) {
267 cache
[0]->incRefCnt();
270 for (i
= 1; i
< unicodeMapCacheSize
; ++i
) {
271 if (cache
[i
] && cache
[i
]->match(encodingName
)) {
273 for (j
= i
; j
>= 1; --j
) {
274 cache
[j
] = cache
[j
- 1];
281 if ((map
= UnicodeMap::parse(encodingName
))) {
282 if (cache
[unicodeMapCacheSize
- 1]) {
283 cache
[unicodeMapCacheSize
- 1]->decRefCnt();
285 for (j
= unicodeMapCacheSize
- 1; j
>= 1; --j
) {
286 cache
[j
] = cache
[j
- 1];