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 *)gmallocn(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 greallocn(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 greallocn(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];