summaryrefslogtreecommitdiffabout
path: root/libkcal/versit/vobject.c
Unidiff
Diffstat (limited to 'libkcal/versit/vobject.c') (more/less context) (show whitespace changes)
-rw-r--r--libkcal/versit/vobject.c297
1 files changed, 159 insertions, 138 deletions
diff --git a/libkcal/versit/vobject.c b/libkcal/versit/vobject.c
index 637efb2..3fac63e 100644
--- a/libkcal/versit/vobject.c
+++ b/libkcal/versit/vobject.c
@@ -37,220 +37,239 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
37***************************************************************************/ 37***************************************************************************/
38 38
39/* 39/*
40 * src: vobject.c 40 * src: vobject.c
41 * doc: vobject and APIs to construct vobject, APIs pretty print 41 * doc: vobject and APIs to construct vobject, APIs pretty print
42 * vobject, and convert a vobject into its textual representation. 42 * vobject, and convert a vobject into its textual representation.
43 */ 43 */
44 44
45#include <stdlib.h> 45#ifdef WIN32
46#define snprintf _snprintf
47#define strcasecmp stricmp
48#endif
46 49
47#include "vobject.h" 50#include "vobject.h"
51#include <stdlib.h>
48#include <string.h> 52#include <string.h>
49#include <stdio.h> 53#include <stdio.h>
50#ifdef _WIN32_ 54#include <fcntl.h>
51 55
52 #define strcasecmp _stricmp
53
54#endif
55 56
56 #define NAME_OF(o) o->id 57 #define NAME_OF(o) o->id
57 #define VALUE_TYPE(o) o->valType 58 #define VALUE_TYPE(o) o->valType
58 #define STRINGZ_VALUE_OF(o) o->val.strs 59 #define STRINGZ_VALUE_OF(o) o->val.strs
59 #define USTRINGZ_VALUE_OF(o)o->val.ustrs 60 #define USTRINGZ_VALUE_OF(o)o->val.ustrs
60 #define INTEGER_VALUE_OF(o) o->val.i 61 #define INTEGER_VALUE_OF(o) o->val.i
61 #define LONG_VALUE_OF(o) o->val.l 62 #define LONG_VALUE_OF(o) o->val.l
62 #define ANY_VALUE_OF(o) o->val.any 63 #define ANY_VALUE_OF(o) o->val.any
63 #define VOBJECT_VALUE_OF(o) o->val.vobj 64 #define VOBJECT_VALUE_OF(o) o->val.vobj
64 65
66typedef union ValueItem {
67 const char *strs;
68 const wchar_t *ustrs;
69 unsigned int i;
70 unsigned long l;
71 void *any;
72 VObject *vobj;
73 } ValueItem;
74
75struct VObject {
76 VObject *next;
77 const char *id;
78 VObject *prop;
79 unsigned short valType;
80 ValueItem val;
81 };
82
83typedef struct StrItem StrItem;
84
85struct StrItem {
86 StrItem *next;
87 const char *s;
88 unsigned int refCnt;
89 };
90
65const char** fieldedProp; 91const char** fieldedProp;
66 92
67 93
68 94
69/*---------------------------------------------------------------------- 95/*----------------------------------------------------------------------
70 The following functions involve with memory allocation: 96 The following functions involve with memory allocation:
71 newVObject 97 newVObject
72 deleteVObject 98 deleteVObject
73 dupStr 99 dupStr
74 deleteStr 100 deleteStr
75 newStrItem 101 newStrItem
76 deleteStrItem 102 deleteStrItem
77 ----------------------------------------------------------------------*/ 103 ----------------------------------------------------------------------*/
78 104
79VObject* newVObject_(const char *id) 105DLLEXPORT(VObject*) newVObject_(const char *id)
80{ 106{
81 VObject *p = (VObject*)malloc(sizeof(VObject)); 107 VObject *p = (VObject*)malloc(sizeof(VObject));
82 p->next = 0; 108 p->next = 0;
83 p->id = id; 109 p->id = id;
84 p->prop = 0; 110 p->prop = 0;
85 VALUE_TYPE(p) = 0; 111 VALUE_TYPE(p) = 0;
86 ANY_VALUE_OF(p) = 0; 112 ANY_VALUE_OF(p) = 0;
87 return p; 113 return p;
88} 114}
89 115
90VObject* newVObject(const char *id) 116DLLEXPORT(VObject*) newVObject(const char *id)
91{ 117{
92 return newVObject_(lookupStr(id)); 118 return newVObject_(lookupStr(id));
93} 119}
94 120
95void deleteVObject(VObject *p) 121DLLEXPORT(void) deleteVObject(VObject *p)
96{ 122{
97 if (p->id)
98 unUseStr(p->id); 123 unUseStr(p->id);
99 if (p)
100 free(p); 124 free(p);
101 p = NULL;
102} 125}
103 126
104char* dupStr(const char *s, unsigned int size) 127DLLEXPORT(char*) dupStr(const char *s, unsigned int size)
105{ 128{
106 char *t; 129 char *t;
107 if (size == 0) { 130 if (size == 0) {
108 size = strlen(s); 131 size = strlen(s);
109 } 132 }
110 t = (char*)malloc(size+1); 133 t = (char*)malloc(size+1);
111 if (t) { 134 if (t) {
112 memcpy(t,s,size); 135 memcpy(t,s,size);
113 t[size] = 0; 136 t[size] = 0;
114 return t; 137 return t;
115 } 138 }
116 else { 139 else {
117 return (char*)0; 140 return (char*)0;
118 } 141 }
119} 142}
120 143
121void deleteStr(const char *p) 144DLLEXPORT(void) deleteStr(const char *p)
122{ 145{
123 if (p) 146 if (p) free((void*)p);
124 free((void*)p);
125 p = NULL;
126} 147}
127 148
128 149
129static StrItem* newStrItem(const char *s, StrItem *next) 150static StrItem* newStrItem(const char *s, StrItem *next)
130{ 151{
131 StrItem *p = (StrItem*)malloc(sizeof(StrItem)); 152 StrItem *p = (StrItem*)malloc(sizeof(StrItem));
132 p->next = next; 153 p->next = next;
133 p->s = s; 154 p->s = s;
134 p->refCnt = 1; 155 p->refCnt = 1;
135 return p; 156 return p;
136} 157}
137 158
138static void deleteStrItem(StrItem *p) 159static void deleteStrItem(StrItem *p)
139{ 160{
140 if (p)
141 free((void*)p); 161 free((void*)p);
142 p = NULL;
143} 162}
144 163
145 164
146/*---------------------------------------------------------------------- 165/*----------------------------------------------------------------------
147 The following function provide accesses to VObject's value. 166 The following function provide accesses to VObject's value.
148 ----------------------------------------------------------------------*/ 167 ----------------------------------------------------------------------*/
149 168
150const char* vObjectName(VObject *o) 169DLLEXPORT(const char*) vObjectName(VObject *o)
151{ 170{
152 return NAME_OF(o); 171 return NAME_OF(o);
153} 172}
154 173
155void setVObjectName(VObject *o, const char* id) 174DLLEXPORT(void) setVObjectName(VObject *o, const char* id)
156{ 175{
157 NAME_OF(o) = id; 176 NAME_OF(o) = id;
158} 177}
159 178
160const char* vObjectStringZValue(VObject *o) 179DLLEXPORT(const char*) vObjectStringZValue(VObject *o)
161{ 180{
162 return STRINGZ_VALUE_OF(o); 181 return STRINGZ_VALUE_OF(o);
163} 182}
164 183
165void setVObjectStringZValue(VObject *o, const char *s) 184DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s)
166{ 185{
167 STRINGZ_VALUE_OF(o) = dupStr(s,0); 186 STRINGZ_VALUE_OF(o) = dupStr(s,0);
168 VALUE_TYPE(o) = VCVT_STRINGZ; 187 VALUE_TYPE(o) = VCVT_STRINGZ;
169} 188}
170 189
171void setVObjectStringZValue_(VObject *o, const char *s) 190DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s)
172{ 191{
173 STRINGZ_VALUE_OF(o) = s; 192 STRINGZ_VALUE_OF(o) = s;
174 VALUE_TYPE(o) = VCVT_STRINGZ; 193 VALUE_TYPE(o) = VCVT_STRINGZ;
175} 194}
176 195
177const wchar_t* vObjectUStringZValue(VObject *o) 196DLLEXPORT(const wchar_t*) vObjectUStringZValue(VObject *o)
178{ 197{
179 return USTRINGZ_VALUE_OF(o); 198 return USTRINGZ_VALUE_OF(o);
180} 199}
181 200
182void setVObjectUStringZValue(VObject *o, const wchar_t *s) 201DLLEXPORT(void) setVObjectUStringZValue(VObject *o, const wchar_t *s)
183{ 202{
184 USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2); 203 USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2);
185 VALUE_TYPE(o) = VCVT_USTRINGZ; 204 VALUE_TYPE(o) = VCVT_USTRINGZ;
186} 205}
187 206
188void setVObjectUStringZValue_(VObject *o, const wchar_t *s) 207DLLEXPORT(void) setVObjectUStringZValue_(VObject *o, const wchar_t *s)
189{ 208{
190 USTRINGZ_VALUE_OF(o) = s; 209 USTRINGZ_VALUE_OF(o) = s;
191 VALUE_TYPE(o) = VCVT_USTRINGZ; 210 VALUE_TYPE(o) = VCVT_USTRINGZ;
192} 211}
193 212
194unsigned int vObjectIntegerValue(VObject *o) 213DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o)
195{ 214{
196 return INTEGER_VALUE_OF(o); 215 return INTEGER_VALUE_OF(o);
197} 216}
198 217
199void setVObjectIntegerValue(VObject *o, unsigned int i) 218DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i)
200{ 219{
201 INTEGER_VALUE_OF(o) = i; 220 INTEGER_VALUE_OF(o) = i;
202 VALUE_TYPE(o) = VCVT_UINT; 221 VALUE_TYPE(o) = VCVT_UINT;
203} 222}
204 223
205unsigned long vObjectLongValue(VObject *o) 224DLLEXPORT(unsigned long) vObjectLongValue(VObject *o)
206{ 225{
207 return LONG_VALUE_OF(o); 226 return LONG_VALUE_OF(o);
208} 227}
209 228
210void setVObjectLongValue(VObject *o, unsigned long l) 229DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l)
211{ 230{
212 LONG_VALUE_OF(o) = l; 231 LONG_VALUE_OF(o) = l;
213 VALUE_TYPE(o) = VCVT_ULONG; 232 VALUE_TYPE(o) = VCVT_ULONG;
214} 233}
215 234
216void* vObjectAnyValue(VObject *o) 235DLLEXPORT(void*) vObjectAnyValue(VObject *o)
217{ 236{
218 return ANY_VALUE_OF(o); 237 return ANY_VALUE_OF(o);
219} 238}
220 239
221void setVObjectAnyValue(VObject *o, void *t) 240DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t)
222{ 241{
223 ANY_VALUE_OF(o) = t; 242 ANY_VALUE_OF(o) = t;
224 VALUE_TYPE(o) = VCVT_RAW; 243 VALUE_TYPE(o) = VCVT_RAW;
225} 244}
226 245
227VObject* vObjectVObjectValue(VObject *o) 246DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o)
228{ 247{
229 return VOBJECT_VALUE_OF(o); 248 return VOBJECT_VALUE_OF(o);
230} 249}
231 250
232void setVObjectVObjectValue(VObject *o, VObject *p) 251DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p)
233{ 252{
234 VOBJECT_VALUE_OF(o) = p; 253 VOBJECT_VALUE_OF(o) = p;
235 VALUE_TYPE(o) = VCVT_VOBJECT; 254 VALUE_TYPE(o) = VCVT_VOBJECT;
236} 255}
237 256
238int vObjectValueType(VObject *o) 257DLLEXPORT(int) vObjectValueType(VObject *o)
239{ 258{
240 return VALUE_TYPE(o); 259 return VALUE_TYPE(o);
241} 260}
242 261
243 262
244/*---------------------------------------------------------------------- 263/*----------------------------------------------------------------------
245 The following functions can be used to build VObject. 264 The following functions can be used to build VObject.
246 ----------------------------------------------------------------------*/ 265 ----------------------------------------------------------------------*/
247 266
248VObject* addVObjectProp(VObject *o, VObject *p) 267DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p)
249{ 268{
250 /* circular link list pointed to tail */ 269 /* circular link list pointed to tail */
251 /* 270 /*
252 o {next,id,prop,val} 271 o {next,id,prop,val}
253 V 272 V
254 pn {next,id,prop,val} 273 pn {next,id,prop,val}
255 V 274 V
256 ... 275 ...
@@ -275,106 +294,106 @@ VObject* addVObjectProp(VObject *o, VObject *p)
275 o->prop = tail->next = p; 294 o->prop = tail->next = p;
276 } 295 }
277 else { 296 else {
278 o->prop = p->next = p; 297 o->prop = p->next = p;
279 } 298 }
280 return p; 299 return p;
281} 300}
282 301
283VObject* addProp(VObject *o, const char *id) 302DLLEXPORT(VObject*) addProp(VObject *o, const char *id)
284{ 303{
285 return addVObjectProp(o,newVObject(id)); 304 return addVObjectProp(o,newVObject(id));
286} 305}
287 306
288VObject* addProp_(VObject *o, const char *id) 307DLLEXPORT(VObject*) addProp_(VObject *o, const char *id)
289{ 308{
290 return addVObjectProp(o,newVObject_(id)); 309 return addVObjectProp(o,newVObject_(id));
291} 310}
292 311
293void addList(VObject **o, VObject *p) 312DLLEXPORT(void) addList(VObject **o, VObject *p)
294{ 313{
295 p->next = 0; 314 p->next = 0;
296 if (*o == 0) { 315 if (*o == 0) {
297 *o = p; 316 *o = p;
298 } 317 }
299 else { 318 else {
300 VObject *t = *o; 319 VObject *t = *o;
301 while (t->next) { 320 while (t->next) {
302 t = t->next; 321 t = t->next;
303 } 322 }
304 t->next = p; 323 t->next = p;
305 } 324 }
306} 325}
307 326
308VObject* nextVObjectInList(VObject *o) 327DLLEXPORT(VObject*) nextVObjectInList(VObject *o)
309{ 328{
310 return o->next; 329 return o->next;
311} 330}
312 331
313VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size) 332DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size)
314{ 333{
315 VObject *sizeProp; 334 VObject *sizeProp;
316 setVObjectAnyValue(prop, val); 335 setVObjectAnyValue(prop, val);
317 sizeProp = addProp(prop,VCDataSizeProp); 336 sizeProp = addProp(prop,VCDataSizeProp);
318 setVObjectLongValue(sizeProp, size); 337 setVObjectLongValue(sizeProp, size);
319 return prop; 338 return prop;
320} 339}
321 340
322VObject* setValueWithSize(VObject *prop, void *val, unsigned int size) 341DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size)
323{ 342{
324 void *p = dupStr(val,size); 343 void *p = dupStr((const char *)val,size);
325 return setValueWithSize_(prop,p,p?size:0); 344 return setValueWithSize_(prop,p,p?size:0);
326} 345}
327 346
328void initPropIterator(VObjectIterator *i, VObject *o) 347DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o)
329{ 348{
330 i->start = o->prop; 349 i->start = o->prop;
331 i->next = 0; 350 i->next = 0;
332} 351}
333 352
334void initVObjectIterator(VObjectIterator *i, VObject *o) 353DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o)
335{ 354{
336 i->start = o->next; 355 i->start = o->next;
337 i->next = 0; 356 i->next = 0;
338} 357}
339 358
340int moreIteration(VObjectIterator *i) 359DLLEXPORT(int) moreIteration(VObjectIterator *i)
341{ 360{
342 return (i->start && (i->next==0 || i->next!=i->start)); 361 return (i->start && (i->next==0 || i->next!=i->start));
343} 362}
344 363
345VObject* nextVObject(VObjectIterator *i) 364DLLEXPORT(VObject*) nextVObject(VObjectIterator *i)
346{ 365{
347 if (i->start && i->next != i->start) { 366 if (i->start && i->next != i->start) {
348 if (i->next == 0) { 367 if (i->next == 0) {
349 i->next = i->start->next; 368 i->next = i->start->next;
350 return i->next; 369 return i->next;
351 } 370 }
352 else { 371 else {
353 i->next = i->next->next; 372 i->next = i->next->next;
354 return i->next; 373 return i->next;
355 } 374 }
356 } 375 }
357 else return (VObject*)0; 376 else return (VObject*)0;
358} 377}
359 378
360VObject* isAPropertyOf(VObject *o, const char *id) 379DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id)
361{ 380{
362 VObjectIterator i; 381 VObjectIterator i;
363 initPropIterator(&i,o); 382 initPropIterator(&i,o);
364 while (moreIteration(&i)) { 383 while (moreIteration(&i)) {
365 VObject *each = nextVObject(&i); 384 VObject *each = nextVObject(&i);
366 if (!strcasecmp(id,each->id)) 385 if (!stricmp(id,each->id))
367 return each; 386 return each;
368 } 387 }
369 return (VObject*)0; 388 return (VObject*)0;
370} 389}
371 390
372VObject* addGroup(VObject *o, const char *g) 391DLLEXPORT(VObject*) addGroup(VObject *o, const char *g)
373{ 392{
374 /* 393 /*
375 a.b.c 394 a.b.c
376 --> 395 -->
377 prop(c) 396 prop(c)
378 prop(VCGrouping=b) 397 prop(VCGrouping=b)
379 prop(VCGrouping=a) 398 prop(VCGrouping=a)
380 */ 399 */
@@ -405,34 +424,34 @@ VObject* addGroup(VObject *o, const char *g)
405 } while (n != gs); 424 } while (n != gs);
406 deleteStr(gs); 425 deleteStr(gs);
407 return p; 426 return p;
408 } 427 }
409 else 428 else
410 return addProp_(o,lookupProp(g)); 429 return addProp_(o,lookupProp(g));
411} 430}
412 431
413VObject* addPropValue(VObject *o, const char *p, const char *v) 432DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v)
414{ 433{
415 VObject *prop; 434 VObject *prop;
416 prop = addProp(o,p); 435 prop = addProp(o,p);
417 setVObjectUStringZValue_(prop, fakeUnicode(v,0)); 436 setVObjectUStringZValue_(prop, fakeUnicode(v,0));
418 return prop; 437 return prop;
419} 438}
420 439
421VObject* addPropSizedValue_(VObject *o, const char *p, const char *v, 440DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v,
422 unsigned int size) 441 unsigned int size)
423{ 442{
424 VObject *prop; 443 VObject *prop;
425 prop = addProp(o,p); 444 prop = addProp(o,p);
426 setValueWithSize_(prop, (void*)v, size); 445 setValueWithSize_(prop, (void*)v, size);
427 return prop; 446 return prop;
428} 447}
429 448
430VObject* addPropSizedValue(VObject *o, const char *p, const char *v, 449DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v,
431 unsigned int size) 450 unsigned int size)
432{ 451{
433 return addPropSizedValue_(o,p,dupStr(v,size),size); 452 return addPropSizedValue_(o,p,dupStr(v,size),size);
434} 453}
435 454
436 455
437 456
438/*---------------------------------------------------------------------- 457/*----------------------------------------------------------------------
@@ -523,38 +542,38 @@ static void printVObject_(FILE *fp, VObject *o, int level)
523 } 542 }
524 } 543 }
525 544
526void printVObject(FILE *fp,VObject *o) 545void printVObject(FILE *fp,VObject *o)
527{ 546{
528 printVObject_(fp,o,0); 547 printVObject_(fp,o,0);
529} 548}
530 549
531void printVObjectToFile(char *fname,VObject *o) 550DLLEXPORT(void) printVObjectToFile(char *fname,VObject *o)
532{ 551{
533 FILE *fp = fopen(fname,"w"); 552 FILE *fp = fopen(fname,"w");
534 if (fp) { 553 if (fp) {
535 printVObject(fp,o); 554 printVObject(fp,o);
536 fclose(fp); 555 fclose(fp);
537 } 556 }
538} 557}
539 558
540void printVObjectsToFile(char *fname,VObject *list) 559DLLEXPORT(void) printVObjectsToFile(char *fname,VObject *list)
541{ 560{
542 FILE *fp = fopen(fname,"w"); 561 FILE *fp = fopen(fname,"w");
543 if (fp) { 562 if (fp) {
544 while (list) { 563 while (list) {
545 printVObject(fp,list); 564 printVObject(fp,list);
546 list = nextVObjectInList(list); 565 list = nextVObjectInList(list);
547 } 566 }
548 fclose(fp); 567 fclose(fp);
549 } 568 }
550} 569}
551 570
552void cleanVObject(VObject *o) 571DLLEXPORT(void) cleanVObject(VObject *o)
553{ 572{
554 if (o == 0) return; 573 if (o == 0) return;
555 if (o->prop) { 574 if (o->prop) {
556 /* destroy time: cannot use the iterator here. 575 /* destroy time: cannot use the iterator here.
557 Have to break the cycle in the circular link 576 Have to break the cycle in the circular link
558 list and turns it into regular NULL-terminated 577 list and turns it into regular NULL-terminated
559 list -- since at some point of destruction, 578 list -- since at some point of destruction,
560 the reference entry for the iterator to work 579 the reference entry for the iterator to work
@@ -578,17 +597,17 @@ void cleanVObject(VObject *o)
578 break; 597 break;
579 case VCVT_VOBJECT: 598 case VCVT_VOBJECT:
580 cleanVObject(VOBJECT_VALUE_OF(o)); 599 cleanVObject(VOBJECT_VALUE_OF(o));
581 break; 600 break;
582 } 601 }
583 deleteVObject(o); 602 deleteVObject(o);
584} 603}
585 604
586void cleanVObjects(VObject *list) 605DLLEXPORT(void) cleanVObjects(VObject *list)
587{ 606{
588 while (list) { 607 while (list) {
589 VObject *t = list; 608 VObject *t = list;
590 list = nextVObjectInList(list); 609 list = nextVObjectInList(list);
591 cleanVObject(t); 610 cleanVObject(t);
592 } 611 }
593} 612}
594 613
@@ -605,77 +624,73 @@ static unsigned int hashStr(const char *s)
605 unsigned int h = 0; 624 unsigned int h = 0;
606 int i; 625 int i;
607 for (i=0;s[i];i++) { 626 for (i=0;s[i];i++) {
608 h += s[i]*i; 627 h += s[i]*i;
609 } 628 }
610 return h % STRTBLSIZE; 629 return h % STRTBLSIZE;
611} 630}
612 631
613const char* lookupStr(const char *s) 632DLLEXPORT(const char*) lookupStr(const char *s)
614{ 633{
615 char *newS;
616
617 StrItem *t; 634 StrItem *t;
618 unsigned int h = hashStr(s); 635 unsigned int h = hashStr(s);
619 if ((t = strTbl[h]) != 0) { 636 if ((t = strTbl[h]) != 0) {
620 do { 637 do {
621 if (strcasecmp(t->s,s) == 0) { 638 if (stricmp(t->s,s) == 0) {
622 t->refCnt++; 639 t->refCnt++;
623 return t->s; 640 return t->s;
624 } 641 }
625 t = t->next; 642 t = t->next;
626 } while (t); 643 } while (t);
627 } 644 }
628 newS = dupStr(s,0); 645 s = dupStr(s,0);
629 strTbl[h] = newStrItem(newS,strTbl[h]); 646 strTbl[h] = newStrItem(s,strTbl[h]);
630 return newS; 647 return s;
631} 648}
632 649
633void unUseStr(const char *s) 650DLLEXPORT(void) unUseStr(const char *s)
634{ 651{
635 StrItem *cur, *prev; 652 StrItem *t, *p;
636
637 unsigned int h = hashStr(s); 653 unsigned int h = hashStr(s);
638 cur = strTbl[h]; 654 if ((t = strTbl[h]) != 0) {
639 prev = cur; 655 p = t;
640 while (cur != 0) { 656 do {
641 if (strcasecmp(cur->s,s) == 0) { 657 if (stricmp(t->s,s) == 0) {
642 cur->refCnt--; 658 t->refCnt--;
643 /* if that was the last reference to this string, kill it. */ 659 if (t->refCnt == 0) {
644 if (cur->refCnt == 0) { 660 if (p == strTbl[h]) {
645 if (cur == strTbl[h]) { 661 strTbl[h] = t->next;
646 strTbl[h] = cur->next; 662 }
647 deleteStr(prev->s); 663 else {
648 deleteStrItem(prev); 664 p->next = t->next;
649 } else {
650 prev->next = cur->next;
651 deleteStr(cur->s);
652 deleteStrItem(cur);
653 } 665 }
666 deleteStr(t->s);
667 deleteStrItem(t);
654 return; 668 return;
655 } 669 }
656 } 670 }
657 prev = cur; 671 p = t;
658 cur = cur->next; 672 t = t->next;
673 } while (t);
659 } 674 }
660} 675}
661 676
662void cleanStrTbl() 677DLLEXPORT(void) cleanStrTbl()
663{ 678{
664 int i; 679 int i;
665 for (i=0; i<STRTBLSIZE;i++) { 680 for (i=0; i<STRTBLSIZE;i++) {
666 StrItem *t = strTbl[i]; 681 StrItem *t = strTbl[i];
667 while (t) { 682 while (t) {
668 StrItem *p; 683 StrItem *p;
669 deleteStr(t->s); 684 deleteStr(t->s);
670 p = t; 685 p = t;
671 t = t->next; 686 t = t->next;
672 deleteStrItem(p); 687 deleteStrItem(p);
673 } 688 } while (t);
674 strTbl[i] = 0; 689 strTbl[i] = 0;
675 } 690 }
676} 691}
677 692
678 693
679struct PreDefProp { 694struct PreDefProp {
680 const char *name; 695 const char *name;
681 const char *alias; 696 const char *alias;
@@ -802,17 +817,17 @@ static struct PreDefProp propNames[] = {
802 { VCDTstartProp, 0, 0, 0 }, 817 { VCDTstartProp, 0, 0, 0 },
803 { VCDueProp, 0, 0, 0 }, 818 { VCDueProp, 0, 0, 0 },
804 { VCEmailAddressProp, 0, 0, 0 }, 819 { VCEmailAddressProp, 0, 0, 0 },
805 { VCEncodingProp, 0, 0, 0 }, 820 { VCEncodingProp, 0, 0, 0 },
806 { VCEndProp, 0, 0, 0 }, 821 { VCEndProp, 0, 0, 0 },
807 { VCEventProp, 0, 0, PD_BEGIN }, 822 { VCEventProp, 0, 0, PD_BEGIN },
808 { VCEWorldProp, 0, 0, 0 }, 823 { VCEWorldProp, 0, 0, 0 },
809 { VCExNumProp, 0, 0, 0 }, 824 { VCExNumProp, 0, 0, 0 },
810 { VCExDateProp, 0, 0, 0 }, 825 { VCExpDateProp, 0, 0, 0 },
811 { VCExpectProp, 0, 0, 0 }, 826 { VCExpectProp, 0, 0, 0 },
812 { VCExtAddressProp, 0, 0, 0 }, 827 { VCExtAddressProp, 0, 0, 0 },
813 { VCFamilyNameProp, 0, 0, 0 }, 828 { VCFamilyNameProp, 0, 0, 0 },
814 { VCFaxProp, 0, 0, 0 }, 829 { VCFaxProp, 0, 0, 0 },
815 { VCFullNameProp, 0, 0, 0 }, 830 { VCFullNameProp, 0, 0, 0 },
816 { VCGeoLocationProp, 0, 0, 0 }, 831 { VCGeoLocationProp, 0, 0, 0 },
817 { VCGeoProp, 0, 0, 0 }, 832 { VCGeoProp, 0, 0, 0 },
818 { VCGIFProp, 0, 0, 0 }, 833 { VCGIFProp, 0, 0, 0 },
@@ -916,44 +931,44 @@ static struct PreDefProp propNames[] = {
916 931
917 932
918static struct PreDefProp* lookupPropInfo(const char* str) 933static struct PreDefProp* lookupPropInfo(const char* str)
919{ 934{
920 /* brute force for now, could use a hash table here. */ 935 /* brute force for now, could use a hash table here. */
921 int i; 936 int i;
922 937
923 for (i = 0; propNames[i].name; i++) 938 for (i = 0; propNames[i].name; i++)
924 if (strcasecmp(str, propNames[i].name) == 0) { 939 if (stricmp(str, propNames[i].name) == 0) {
925 return &propNames[i]; 940 return &propNames[i];
926 } 941 }
927 942
928 return 0; 943 return 0;
929} 944}
930 945
931 946
932const char* lookupProp_(const char* str) 947DLLEXPORT(const char*) lookupProp_(const char* str)
933{ 948{
934 int i; 949 int i;
935 950
936 for (i = 0; propNames[i].name; i++) 951 for (i = 0; propNames[i].name; i++)
937 if (strcasecmp(str, propNames[i].name) == 0) { 952 if (stricmp(str, propNames[i].name) == 0) {
938 const char* s; 953 const char* s;
939 s = propNames[i].alias?propNames[i].alias:propNames[i].name; 954 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
940 return lookupStr(s); 955 return lookupStr(s);
941 } 956 }
942 return lookupStr(str); 957 return lookupStr(str);
943} 958}
944 959
945 960
946const char* lookupProp(const char* str) 961DLLEXPORT(const char*) lookupProp(const char* str)
947{ 962{
948 int i; 963 int i;
949 964
950 for (i = 0; propNames[i].name; i++) 965 for (i = 0; propNames[i].name; i++)
951 if (strcasecmp(str, propNames[i].name) == 0) { 966 if (stricmp(str, propNames[i].name) == 0) {
952 const char *s; 967 const char *s;
953 fieldedProp = propNames[i].fields; 968 fieldedProp = propNames[i].fields;
954 s = propNames[i].alias?propNames[i].alias:propNames[i].name; 969 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
955 return lookupStr(s); 970 return lookupStr(s);
956 } 971 }
957 fieldedProp = 0; 972 fieldedProp = 0;
958 return lookupStr(str); 973 return lookupStr(str);
959} 974}
@@ -967,21 +982,17 @@ typedef struct OFile {
967 FILE *fp; 982 FILE *fp;
968 char *s; 983 char *s;
969 int len; 984 int len;
970 int limit; 985 int limit;
971 int alloc:1; 986 int alloc:1;
972 int fail:1; 987 int fail:1;
973 } OFile; 988 } OFile;
974 989
975
976/* vCalendar files need crlf linebreaks. The disabled functions didn't provide
977 that. */
978#if 0 990#if 0
979
980static void appendsOFile(OFile *fp, const char *s) 991static void appendsOFile(OFile *fp, const char *s)
981{ 992{
982 int slen; 993 int slen;
983 if (fp->fail) return; 994 if (fp->fail) return;
984 slen = strlen(s); 995 slen = strlen(s);
985 if (fp->fp) { 996 if (fp->fp) {
986 fwrite(s,1,slen,fp->fp); 997 fwrite(s,1,slen,fp->fp);
987 } 998 }
@@ -990,20 +1001,17 @@ stuff:
990 if (fp->len + slen < fp->limit) { 1001 if (fp->len + slen < fp->limit) {
991 memcpy(fp->s+fp->len,s,slen); 1002 memcpy(fp->s+fp->len,s,slen);
992 fp->len += slen; 1003 fp->len += slen;
993 return; 1004 return;
994 } 1005 }
995 else if (fp->alloc) { 1006 else if (fp->alloc) {
996 fp->limit = fp->limit + OFILE_REALLOC_SIZE; 1007 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
997 if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen; 1008 if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
998 if (fp->s) 1009 fp->s = (char *) realloc(fp->s,fp->limit);
999 fp->s = realloc(fp->s,fp->limit);
1000 else
1001 fp->s = malloc(fp->limit);
1002 if (fp->s) goto stuff; 1010 if (fp->s) goto stuff;
1003 } 1011 }
1004 if (fp->alloc) 1012 if (fp->alloc)
1005 free(fp->s); 1013 free(fp->s);
1006 fp->s = 0; 1014 fp->s = 0;
1007 fp->fail = 1; 1015 fp->fail = 1;
1008 } 1016 }
1009} 1017}
@@ -1018,28 +1026,26 @@ static void appendcOFile(OFile *fp, char c)
1018stuff: 1026stuff:
1019 if (fp->len+1 < fp->limit) { 1027 if (fp->len+1 < fp->limit) {
1020 fp->s[fp->len] = c; 1028 fp->s[fp->len] = c;
1021 fp->len++; 1029 fp->len++;
1022 return; 1030 return;
1023 } 1031 }
1024 else if (fp->alloc) { 1032 else if (fp->alloc) {
1025 fp->limit = fp->limit + OFILE_REALLOC_SIZE; 1033 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
1026 fp->s = realloc(fp->s,fp->limit); 1034 fp->s = (char *) realloc(fp->s,fp->limit);
1027 if (fp->s) goto stuff; 1035 if (fp->s) goto stuff;
1028 } 1036 }
1029 if (fp->alloc) 1037 if (fp->alloc)
1030 free(fp->s); 1038 free(fp->s);
1031 fp->s = 0; 1039 fp->s = 0;
1032 fp->fail = 1; 1040 fp->fail = 1;
1033 } 1041 }
1034} 1042}
1035
1036#else 1043#else
1037
1038static void appendcOFile_(OFile *fp, char c) 1044static void appendcOFile_(OFile *fp, char c)
1039{ 1045{
1040 if (fp->fail) return; 1046 if (fp->fail) return;
1041 if (fp->fp) { 1047 if (fp->fp) {
1042 fputc(c,fp->fp); 1048 fputc(c,fp->fp);
1043 } 1049 }
1044 else { 1050 else {
1045stuff: 1051stuff:
@@ -1140,52 +1146,65 @@ static int writeBase64(OFile *fp, unsigned char *s, long len)
1140 appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : ""))); 1146 appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
1141 numQuads = (numQuads + 1) % MAXQUADS; 1147 numQuads = (numQuads + 1) % MAXQUADS;
1142 } 1148 }
1143 appendcOFile(fp,'\n'); 1149 appendcOFile(fp,'\n');
1144 1150
1145 return 1; 1151 return 1;
1146} 1152}
1147 1153
1148/* this function really sucks. Too basic. */ 1154static void writeString(OFile *fp, const char *s)
1149static void writeQPString(OFile *fp, const char *s, int qp) 1155{
1156 appendsOFile(fp,s);
1157}
1158
1159static void writeQPString(OFile *fp, const char *s)
1150{ 1160{
1161 char buf[4];
1162 int count=0;
1151 const char *p = s; 1163 const char *p = s;
1164
1152 while (*p) { 1165 while (*p) {
1153 if (*p == '\n') { 1166 /* break up lines biggger than 75 chars */
1154 if (p[1]) appendsOFile(fp,"=0A="); 1167 if(count >=74){
1168 count=0;
1169 appendsOFile(fp,"=\n");
1155 } 1170 }
1156 if (*p == '=' && qp) 1171
1157 appendsOFile(fp,"=3D"); 1172 /* escape any non ASCII characters and '=' as per rfc1521 */
1158 else 1173 if (*p<= 0x1f || *p >=0x7f || *p == '=' ) {
1174 sprintf(buf,"=%02X",(unsigned char)*p);
1175 appendsOFile(fp,buf);
1176 count+=3;
1177 } else {
1159 appendcOFile(fp,*p); 1178 appendcOFile(fp,*p);
1179 count++;
1180 }
1160 p++; 1181 p++;
1161 } 1182 }
1162} 1183}
1163 1184
1185
1186
1164static void writeVObject_(OFile *fp, VObject *o); 1187static void writeVObject_(OFile *fp, VObject *o);
1165 1188
1166static void writeValue(OFile *fp, VObject *o, unsigned long size) 1189static void writeValue(OFile *fp, VObject *o, unsigned long size,int quote)
1167{ 1190{
1168 if (o == 0) return; 1191 if (o == 0) return;
1169 switch (VALUE_TYPE(o)) { 1192 switch (VALUE_TYPE(o)) {
1170 case VCVT_USTRINGZ: { 1193 case VCVT_USTRINGZ: {
1171 char *s = fakeCString(USTRINGZ_VALUE_OF(o)); 1194 char *s = fakeCString(USTRINGZ_VALUE_OF(o));
1172 if (isAPropertyOf(o, VCQuotedPrintableProp)) 1195 if(quote) writeQPString(fp, s);
1173 writeQPString(fp, s, 1); 1196 else writeString(fp,s);
1174 else
1175 writeQPString(fp, s, 0);
1176 deleteStr(s); 1197 deleteStr(s);
1177 break; 1198 break;
1178 } 1199 }
1179 case VCVT_STRINGZ: { 1200 case VCVT_STRINGZ: {
1180 if (isAPropertyOf(o, VCQuotedPrintableProp)) 1201 if(quote) writeQPString(fp, STRINGZ_VALUE_OF(o));
1181 writeQPString(fp, STRINGZ_VALUE_OF(o), 1); 1202 else writeString(fp,STRINGZ_VALUE_OF(o));
1182 else
1183 writeQPString(fp, STRINGZ_VALUE_OF(o), 0);
1184 break; 1203 break;
1185 } 1204 }
1186 case VCVT_UINT: { 1205 case VCVT_UINT: {
1187 char buf[16]; 1206 char buf[16];
1188 sprintf(buf,"%u", INTEGER_VALUE_OF(o)); 1207 sprintf(buf,"%u", INTEGER_VALUE_OF(o));
1189 appendsOFile(fp,buf); 1208 appendsOFile(fp,buf);
1190 break; 1209 break;
1191 } 1210 }
@@ -1215,47 +1234,47 @@ static void writeAttrValue(OFile *fp, VObject *o)
1215 if (pi && ((pi->flags & PD_INTERNAL) != 0)) return; 1234 if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
1216 appendcOFile(fp,';'); 1235 appendcOFile(fp,';');
1217 appendsOFile(fp,NAME_OF(o)); 1236 appendsOFile(fp,NAME_OF(o));
1218 } 1237 }
1219 else 1238 else
1220 appendcOFile(fp,';'); 1239 appendcOFile(fp,';');
1221 if (VALUE_TYPE(o)) { 1240 if (VALUE_TYPE(o)) {
1222 appendcOFile(fp,'='); 1241 appendcOFile(fp,'=');
1223 writeValue(fp,o,0); 1242 writeValue(fp,o,0,0);
1224 } 1243 }
1225} 1244}
1226 1245
1227static void writeGroup(OFile *fp, VObject *o) 1246static void writeGroup(OFile *fp, VObject *o)
1228{ 1247{
1229 char buf1[256]; 1248 char buf1[256];
1230 char buf2[256]; 1249 char buf2[256];
1231 strcpy(buf1,NAME_OF(o)); 1250 strcpy(buf1,NAME_OF(o));
1232 while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { 1251 while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
1233 strncpy(buf2,STRINGZ_VALUE_OF(o),sizeof(buf2)); 1252 strcpy(buf2,STRINGZ_VALUE_OF(o));
1234 buf2[sizeof(buf2)] = '\0'; 1253 strcat(buf2,".");
1235 strncat(buf2,".",sizeof(buf2)-strlen(buf2)-1); 1254 strcat(buf2,buf1);
1236 strncat(buf2,buf1,sizeof(buf2)-strlen(buf2)-1);
1237 strcpy(buf1,buf2); 1255 strcpy(buf1,buf2);
1238 } 1256 }
1239 appendsOFile(fp,buf1); 1257 appendsOFile(fp,buf1);
1240} 1258}
1241 1259
1242static int inList(const char **list, const char *s) 1260static int inList(const char **list, const char *s)
1243{ 1261{
1244 if (list == 0) return 0; 1262 if (list == 0) return 0;
1245 while (*list) { 1263 while (*list) {
1246 if (strcasecmp(*list,s) == 0) return 1; 1264 if (stricmp(*list,s) == 0) return 1;
1247 list++; 1265 list++;
1248 } 1266 }
1249 return 0; 1267 return 0;
1250} 1268}
1251 1269
1252static void writeProp(OFile *fp, VObject *o) 1270static void writeProp(OFile *fp, VObject *o)
1253{ 1271{
1272 int isQuoted=0;
1254 if (NAME_OF(o)) { 1273 if (NAME_OF(o)) {
1255 struct PreDefProp *pi; 1274 struct PreDefProp *pi;
1256 VObjectIterator t; 1275 VObjectIterator t;
1257 const char **fields_ = 0; 1276 const char **fields_ = 0;
1258 pi = lookupPropInfo(NAME_OF(o)); 1277 pi = lookupPropInfo(NAME_OF(o));
1259 if (pi && ((pi->flags & PD_BEGIN) != 0)) { 1278 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1260 writeVObject_(fp,o); 1279 writeVObject_(fp,o);
1261 return; 1280 return;
@@ -1265,45 +1284,47 @@ static void writeProp(OFile *fp, VObject *o)
1265 else 1284 else
1266 appendsOFile(fp,NAME_OF(o)); 1285 appendsOFile(fp,NAME_OF(o));
1267 if (pi) fields_ = pi->fields; 1286 if (pi) fields_ = pi->fields;
1268 initPropIterator(&t,o); 1287 initPropIterator(&t,o);
1269 while (moreIteration(&t)) { 1288 while (moreIteration(&t)) {
1270 const char *s; 1289 const char *s;
1271 VObject *eachProp = nextVObject(&t); 1290 VObject *eachProp = nextVObject(&t);
1272 s = NAME_OF(eachProp); 1291 s = NAME_OF(eachProp);
1273 if (strcasecmp(VCGroupingProp,s) && !inList(fields_,s)) 1292 if (stricmp(VCGroupingProp,s) && !inList(fields_,s))
1274 writeAttrValue(fp,eachProp); 1293 writeAttrValue(fp,eachProp);
1294 if (stricmp(VCQPProp,s)==0 || stricmp(VCQuotedPrintableProp,s)==0)
1295 isQuoted=1;
1275 } 1296 }
1276 if (fields_) { 1297 if (fields_) {
1277 int i = 0, n = 0; 1298 int i = 0, n = 0;
1278 const char** fields = fields_; 1299 const char** fields = fields_;
1279 /* output prop as fields */ 1300 /* output prop as fields */
1280 appendcOFile(fp,':'); 1301 appendcOFile(fp,':');
1281 while (*fields) { 1302 while (*fields) {
1282 VObject *tl = isAPropertyOf(o,*fields); 1303 VObject *t = isAPropertyOf(o,*fields);
1283 i++; 1304 i++;
1284 if (tl) n = i; 1305 if (t) n = i;
1285 fields++; 1306 fields++;
1286 } 1307 }
1287 fields = fields_; 1308 fields = fields_;
1288 for (i=0;i<n;i++) { 1309 for (i=0;i<n;i++) {
1289 writeValue(fp,isAPropertyOf(o,*fields),0); 1310 writeValue(fp,isAPropertyOf(o,*fields),0,isQuoted);
1290 fields++; 1311 fields++;
1291 if (i<(n-1)) appendcOFile(fp,';'); 1312 if (i<(n-1)) appendcOFile(fp,';');
1292 } 1313 }
1293 } 1314 }
1294 } 1315 }
1295 1316
1296 if (VALUE_TYPE(o)) { 1317 if (VALUE_TYPE(o)) {
1297 unsigned long size = 0; 1318 unsigned long size = 0;
1298 VObject *p = isAPropertyOf(o,VCDataSizeProp); 1319 VObject *p = isAPropertyOf(o,VCDataSizeProp);
1299 if (p) size = LONG_VALUE_OF(p); 1320 if (p) size = LONG_VALUE_OF(p);
1300 appendcOFile(fp,':'); 1321 appendcOFile(fp,':');
1301 writeValue(fp,o,size); 1322 writeValue(fp,o,size,isQuoted);
1302 } 1323 }
1303 1324
1304 appendcOFile(fp,'\n'); 1325 appendcOFile(fp,'\n');
1305} 1326}
1306 1327
1307static void writeVObject_(OFile *fp, VObject *o) 1328static void writeVObject_(OFile *fp, VObject *o)
1308{ 1329{
1309 if (NAME_OF(o)) { 1330 if (NAME_OF(o)) {
@@ -1330,64 +1351,64 @@ static void writeVObject_(OFile *fp, VObject *o)
1330 1351
1331void writeVObject(FILE *fp, VObject *o) 1352void writeVObject(FILE *fp, VObject *o)
1332{ 1353{
1333 OFile ofp; 1354 OFile ofp;
1334 initOFile(&ofp,fp); 1355 initOFile(&ofp,fp);
1335 writeVObject_(&ofp,o); 1356 writeVObject_(&ofp,o);
1336} 1357}
1337 1358
1338void writeVObjectToFile(char *fname, VObject *o) 1359DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
1339{ 1360{
1340 FILE *fp = fopen(fname,"w"); 1361 FILE *fp = fopen(fname,"w");
1341 if (fp) { 1362 if (fp) {
1342 writeVObject(fp,o); 1363 writeVObject(fp,o);
1343 fclose(fp); 1364 fclose(fp);
1344 } 1365 }
1345} 1366}
1346 1367
1347void writeVObjectsToFile(char *fname, VObject *list) 1368DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
1348{ 1369{
1349 FILE *fp = fopen(fname,"w"); 1370 FILE *fp = fopen(fname,"w");
1350 if (fp) { 1371 if (fp) {
1351 while (list) { 1372 while (list) {
1352 writeVObject(fp,list); 1373 writeVObject(fp,list);
1353 list = nextVObjectInList(list); 1374 list = nextVObjectInList(list);
1354 } 1375 }
1355 fclose(fp); 1376 fclose(fp);
1356 } 1377 }
1357} 1378}
1358 1379
1359char* writeMemVObject(char *s, int *len, VObject *o) 1380DLLEXPORT(char*) writeMemVObject(char *s, int *len, VObject *o)
1360{ 1381{
1361 OFile ofp; 1382 OFile ofp;
1362 initMemOFile(&ofp,s,len?*len:0); 1383 initMemOFile(&ofp,s,len?*len:0);
1363 writeVObject_(&ofp,o); 1384 writeVObject_(&ofp,o);
1364 if (len) *len = ofp.len; 1385 if (len) *len = ofp.len;
1365 appendcOFile(&ofp,0); 1386 appendcOFile(&ofp,0);
1366 return ofp.s; 1387 return ofp.s;
1367} 1388}
1368 1389
1369char* writeMemVObjects(char *s, int *len, VObject *list) 1390DLLEXPORT(char*) writeMemVObjects(char *s, int *len, VObject *list)
1370{ 1391{
1371 OFile ofp; 1392 OFile ofp;
1372 initMemOFile(&ofp,s,len?*len:0); 1393 initMemOFile(&ofp,s,len?*len:0);
1373 while (list) { 1394 while (list) {
1374 writeVObject_(&ofp,list); 1395 writeVObject_(&ofp,list);
1375 list = nextVObjectInList(list); 1396 list = nextVObjectInList(list);
1376 } 1397 }
1377 if (len) *len = ofp.len; 1398 if (len) *len = ofp.len;
1378 appendcOFile(&ofp,0); 1399 appendcOFile(&ofp,0);
1379 return ofp.s; 1400 return ofp.s;
1380} 1401}
1381 1402
1382/*---------------------------------------------------------------------- 1403/*----------------------------------------------------------------------
1383 APIs to do fake Unicode stuff. 1404 APIs to do fake Unicode stuff.
1384 ----------------------------------------------------------------------*/ 1405 ----------------------------------------------------------------------*/
1385wchar_t* fakeUnicode(const char *ps, int *bytes) 1406DLLEXPORT(wchar_t*) fakeUnicode(const char *ps, int *bytes)
1386{ 1407{
1387 wchar_t *r, *pw; 1408 wchar_t *r, *pw;
1388 int len = strlen(ps)+1; 1409 int len = strlen(ps)+1;
1389 1410
1390 pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len); 1411 pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len);
1391 if (bytes) 1412 if (bytes)
1392 *bytes = len * sizeof(wchar_t); 1413 *bytes = len * sizeof(wchar_t);
1393 1414
@@ -1400,28 +1421,28 @@ wchar_t* fakeUnicode(const char *ps, int *bytes)
1400 *pw = (wchar_t)(unsigned char)*ps; 1421 *pw = (wchar_t)(unsigned char)*ps;
1401 ps++; pw++; 1422 ps++; pw++;
1402 } 1423 }
1403 *pw = (wchar_t)0; 1424 *pw = (wchar_t)0;
1404 1425
1405 return r; 1426 return r;
1406} 1427}
1407 1428
1408int uStrLen(const wchar_t *u) 1429DLLEXPORT(int) uStrLen(const wchar_t *u)
1409{ 1430{
1410 int i = 0; 1431 int i = 0;
1411 while (*u != (wchar_t)0) { u++; i++; } 1432 while (*u != (wchar_t)0) { u++; i++; }
1412 return i; 1433 return i;
1413} 1434}
1414 1435
1415char* fakeCString(const wchar_t *u) 1436DLLEXPORT(char*) fakeCString(const wchar_t *u)
1416{ 1437{
1417 char *s, *t; 1438 char *s, *t;
1418 int len = uStrLen(u) + 1; 1439 int len = uStrLen(u) + 1;
1419 t = s = (char*)malloc(len+1); 1440 t = s = (char*)malloc(len);
1420 while (*u) { 1441 while (*u) {
1421 if (*u == (wchar_t)0x2028) 1442 if (*u == (wchar_t)0x2028)
1422 *t = '\n'; 1443 *t = '\n';
1423 else if (*u == (wchar_t)0x2029) 1444 else if (*u == (wchar_t)0x2029)
1424 *t = '\r'; 1445 *t = '\r';
1425 else 1446 else
1426 *t = (char)*u; 1447 *t = (char)*u;
1427 u++; t++; 1448 u++; t++;