1 //========================================================================
5 // Copyright 2001-2002 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;
121 UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
122 UnicodeMapRange *rangesA, int lenA) {
123 encodingName = new GString(encodingNameA);
124 unicodeOut = unicodeOutA;
125 kind = unicodeMapResident;
133 UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
134 UnicodeMapFunc funcA) {
135 encodingName = new GString(encodingNameA);
136 unicodeOut = unicodeOutA;
137 kind = unicodeMapFunc;
144 UnicodeMap::~UnicodeMap() {
146 if (kind == unicodeMapUser && ranges) {
154 void UnicodeMap::incRefCnt() {
158 void UnicodeMap::decRefCnt() {
164 GBool UnicodeMap::match(GString *encodingNameA) {
165 return !encodingName->cmp(encodingNameA);
168 int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
169 int a, b, m, n, i, j;
172 if (kind == unicodeMapFunc) {
173 return (*func)(u, buf, bufSize);
178 if (u < ranges[a].start) {
181 // invariant: ranges[a].start <= u < ranges[b].start
184 if (u >= ranges[m].start) {
186 } else if (u < ranges[m].start) {
190 if (u <= ranges[a].end) {
191 n = ranges[a].nBytes;
195 code = ranges[a].code + (u - ranges[a].start);
196 for (i = n - 1; i >= 0; --i) {
197 buf[i] = (char)(code & 0xff);
203 for (i = 0; i < eMapsLen; ++i) {
204 if (eMaps[i].u == u) {
206 for (j = 0; j < n; ++j) {
207 buf[j] = eMaps[i].code[j];
216 //------------------------------------------------------------------------
218 UnicodeMapCache::UnicodeMapCache() {
221 for (i = 0; i < unicodeMapCacheSize; ++i) {
226 UnicodeMapCache::~UnicodeMapCache() {
229 for (i = 0; i < unicodeMapCacheSize; ++i) {
231 cache[i]->decRefCnt();
236 UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) {
240 if (cache[0] && cache[0]->match(encodingName)) {
241 cache[0]->incRefCnt();
244 for (i = 1; i < unicodeMapCacheSize; ++i) {
245 if (cache[i] && cache[i]->match(encodingName)) {
247 for (j = i; j >= 1; --j) {
248 cache[j] = cache[j - 1];
255 if ((map = UnicodeMap::parse(encodingName))) {
256 if (cache[unicodeMapCacheSize - 1]) {
257 cache[unicodeMapCacheSize - 1]->decRefCnt();
259 for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
260 cache[j] = cache[j - 1];