Back to index

lightning-sunbird  0.9+nobinonly
nsVCardObj.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /***************************************************************************
00039 (C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International             
00040 Business Machines Corporation and Siemens Rolm Communications Inc.             
00041                                                                                
00042 For purposes of this license notice, the term Licensors shall mean,            
00043 collectively, Apple Computer, Inc., AT&T Corp., International                  
00044 Business Machines Corporation and Siemens Rolm Communications Inc.             
00045 The term Licensor shall mean any of the Licensors.                             
00046                                                                                
00047 Subject to acceptance of the following conditions, permission is hereby        
00048 granted by Licensors without the need for written agreement and without        
00049 license or royalty fees, to use, copy, modify and distribute this              
00050 software for any purpose.                                                      
00051                                                                                
00052 The above copyright notice and the following four paragraphs must be           
00053 reproduced in all copies of this software and any software including           
00054 this software.                                                                 
00055                                                                                
00056 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE       
00057 ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR       
00058 MODIFICATIONS.                                                                 
00059                                                                                
00060 IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,              
00061 INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT         
00062 OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH         
00063 DAMAGE.                                                                        
00064                                                                                
00065 EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,       
00066 INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE            
00067 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR             
00068 PURPOSE.                                                                       
00069 
00070 The software is provided with RESTRICTED RIGHTS.  Use, duplication, or         
00071 disclosure by the government are subject to restrictions set forth in          
00072 DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.                         
00073 
00074 ***************************************************************************/
00075 
00076 /*
00077  * doc: vobject and APIs to construct vobject, APIs pretty print 
00078  * vobject, and convert a vobject into its textual representation.
00079  */
00080 
00081 #include "prlog.h"
00082 #include "nsVCard.h"
00083 #include "nsVCardObj.h"
00084 #include "prmem.h"
00085 #include "plstr.h"
00086 #include "msgCore.h"
00087 #include "prprf.h"
00088 
00089 /* debugging utilities */
00090 #define DBG_(x)
00091 
00092 #ifdef __cplusplus
00093 extern "C" {
00094 #endif
00095 
00096   char    **fieldedProp;
00097 
00098 #ifdef __cplusplus
00099     }
00100 #endif
00101 
00102 
00103 
00104 static VObject* newVObject_(const char *id);
00105 #if 0
00106 static int vObjectValueType(VObject *o);
00107 static void initVObjectIterator(VObjectIterator *i, VObject *o);
00108 #endif
00109 
00110 /*----------------------------------------------------------------------
00111    The following functions involve with memory allocation:
00112   newVObject
00113   deleteVObject
00114   dupStr
00115   deleteString
00116   newStrItem
00117   deleteStrItem
00118    ----------------------------------------------------------------------*/
00119 
00120 static PRBool needsQuotedPrintable (const char *s)
00121 {
00122   const unsigned char *p = (const unsigned char *)s;
00123 
00124   while (*p) {
00125     if (*p & 0x80 || *p == '\015' || *p == '\012')
00126       return PR_TRUE;
00127     p++;
00128   }
00129 
00130   return PR_FALSE;
00131 }
00132 
00133 VObject* newVObject_(const char *id)
00134 {
00135     VObject *p = (VObject*) new(VObject);
00136     p->next = 0;
00137     p->id = id;
00138     p->prop = 0;
00139     VALUE_TYPE(p) = 0;
00140   ANY_VALUE_OF(p) = 0;
00141     return p;
00142 }
00143 
00144 VObject* newVObject(const char *id)
00145 {
00146     return newVObject_(lookupStr(id));
00147 }
00148 
00149 void deleteVObject(VObject *p)
00150 {
00151     unUseStr(p->id);
00152     delete (p);
00153 }
00154 
00155 char* dupStr(const char *s, unsigned int size)
00156 {
00157     char *t;
00158     if  (size == 0) {
00159   size = PL_strlen(s);
00160   }
00161   t = (char*)PR_CALLOC(size+1);
00162   if (t) {
00163   memcpy(t,s,size);
00164   t[size] = 0;
00165   return t;
00166   }
00167     else {
00168   return (char*)0;
00169   }
00170 }
00171 
00172 static StrItem* newStrItem(const char *s, StrItem *next)
00173 {
00174     StrItem *p = (StrItem*)PR_CALLOC(sizeof(StrItem));
00175     p->next = next;
00176     p->s = s;
00177     p->refCnt = 1;
00178     return p;
00179 }
00180 
00181 extern "C" 
00182 void deleteString(char *p)
00183 {
00184     if (p) 
00185       PR_Free ((void*)p);
00186 }
00187 
00188 extern "C"
00189 void deleteStrItem(StrItem *p)
00190 {
00191     if (p) 
00192       PR_FREEIF (p);
00193 }
00194 
00195 
00196 
00197 /*----------------------------------------------------------------------
00198   The following function provide accesses to VObject's value.
00199   ----------------------------------------------------------------------*/
00200 
00201 const char* vObjectName(VObject *o)
00202 {
00203     return NAME_OF(o);
00204 }
00205 
00206 void setVObjectName(VObject *o, const char* id)
00207 {
00208     NAME_OF(o) = id;
00209 }
00210 
00211 const char* vObjectStringZValue(VObject *o)
00212 {
00213     return STRINGZ_VALUE_OF(o);
00214 }
00215 
00216 void setVObjectStringZValue(VObject *o, const char *s)
00217 {
00218     STRINGZ_VALUE_OF(o) = dupStr(s,0);
00219     VALUE_TYPE(o) = VCVT_STRINGZ;
00220 }
00221 
00222 void setVObjectStringZValue_(VObject *o, const char *s)
00223 {
00224     STRINGZ_VALUE_OF(o) = s;
00225     VALUE_TYPE(o) = VCVT_STRINGZ;
00226 }
00227 
00228 const vwchar_t* vObjectUStringZValue(VObject *o)
00229 {
00230     return USTRINGZ_VALUE_OF(o);
00231 }
00232 
00233 void setVObjectUStringZValue(VObject *o, const vwchar_t *s)
00234 {
00235     USTRINGZ_VALUE_OF(o) = (vwchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2);
00236     VALUE_TYPE(o) = VCVT_USTRINGZ;
00237 }
00238 
00239 void setVObjectUStringZValue_(VObject *o, const vwchar_t *s)
00240 {
00241     USTRINGZ_VALUE_OF(o) = s;
00242     VALUE_TYPE(o) = VCVT_USTRINGZ;
00243 }
00244 
00245 unsigned int vObjectIntegerValue(VObject *o)
00246 {
00247     return INTEGER_VALUE_OF(o);
00248 }
00249 
00250 void setVObjectIntegerValue(VObject *o, unsigned int i)
00251 {
00252     INTEGER_VALUE_OF(o) = i;
00253     VALUE_TYPE(o) = VCVT_UINT;
00254 }
00255 
00256 unsigned long vObjectLongValue(VObject *o)
00257 {
00258     return LONG_VALUE_OF(o);
00259 }
00260 
00261 void setVObjectLongValue(VObject *o, unsigned long l)
00262 {
00263     LONG_VALUE_OF(o) = l;
00264     VALUE_TYPE(o) = VCVT_ULONG;
00265 }
00266 
00267 void* vObjectAnyValue(VObject *o)
00268 {
00269     return ANY_VALUE_OF(o);
00270 }
00271 
00272 void setVObjectAnyValue(VObject *o, void *t)
00273 {
00274     ANY_VALUE_OF(o) = t;
00275     VALUE_TYPE(o) = VCVT_RAW;
00276 }
00277 
00278 VObject* vObjectVObjectValue(VObject *o)
00279 {
00280     return VOBJECT_VALUE_OF(o);
00281 }
00282 
00283 void setVObjectVObjectValue(VObject *o, VObject *p)
00284 {
00285     VOBJECT_VALUE_OF(o) = p;
00286     VALUE_TYPE(o) = VCVT_VOBJECT;
00287 }
00288 
00289 #if 0
00290 int vObjectValueType(VObject *o)
00291 {
00292     return VALUE_TYPE(o);
00293 }
00294 #endif
00295 
00296 
00297 /*----------------------------------------------------------------------
00298   The following functions can be used to build VObject.
00299   ----------------------------------------------------------------------*/
00300 
00301 VObject* addVObjectProp(VObject *o, VObject *p)
00302 {
00303     /* circular link list pointed to tail */
00304     /*
00305     o {next,id,prop,val}
00306                 V
00307   pn {next,id,prop,val}
00308              V
00309       ...
00310   p1 {next,id,prop,val}
00311              V
00312        pn
00313     -->
00314     o {next,id,prop,val}
00315                 V
00316   pn {next,id,prop,val}
00317              V
00318   p {next,id,prop,val}
00319       ...
00320   p1 {next,id,prop,val}
00321              V
00322        pn
00323     */
00324 
00325     VObject *tail = o->prop;
00326     if (tail) {
00327   p->next = tail->next;
00328   o->prop = tail->next = p;
00329   }
00330     else {
00331   o->prop = p->next = p;
00332   }
00333     return p;
00334 }
00335 
00336 VObject* addProp(VObject *o, const char *id)
00337 {
00338     return addVObjectProp(o,newVObject(id));
00339 }
00340 
00341 VObject* addProp_(VObject *o, const char *id)
00342 {
00343     return addVObjectProp(o,newVObject_(id));
00344 }
00345 
00346 void addList(VObject **o, VObject *p)
00347 {
00348     p->next = 0;
00349     if (*o == 0) {
00350   *o = p;
00351   }
00352     else {
00353   VObject *t = *o;
00354   while (t->next) {
00355      t = t->next;
00356      }
00357   t->next = p;
00358   }
00359 }
00360 
00361 VObject* nextVObjectInList(VObject *o)
00362 {
00363     return o->next;
00364 }
00365 
00366 VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size)
00367 {
00368     VObject *sizeProp;
00369     setVObjectAnyValue(prop, val);
00370     sizeProp = addProp(prop,VCDataSizeProp);
00371     setVObjectLongValue(sizeProp, size);
00372     return prop;
00373 }
00374 
00375 VObject* setValueWithSize(VObject *prop, void *val, unsigned int size)
00376 {
00377   void *p = dupStr((const char *)val,size);
00378     return setValueWithSize_(prop,p,p?size:0);
00379 }
00380 
00381 void initPropIterator(VObjectIterator *i, VObject *o)
00382 {
00383     i->start = o->prop; 
00384     i->next = 0;
00385 }
00386 
00387 #if 0
00388 void initVObjectIterator(VObjectIterator *i, VObject *o)
00389 {
00390     i->start = o->next; 
00391     i->next = 0;
00392 }
00393 #endif
00394 
00395 int moreIteration(VObjectIterator *i)
00396 { 
00397     return (i->start && (i->next==0 || i->next!=i->start));
00398 }
00399 
00400 VObject* nextVObject(VObjectIterator *i)
00401 {
00402     if (i->start && i->next != i->start) {
00403   if (i->next == 0) {
00404       i->next = i->start->next;
00405       return i->next;
00406       }
00407   else {
00408       i->next = i->next->next;
00409       return i->next;
00410       }
00411   }
00412     else return (VObject*)0;
00413 }
00414 
00415 VObject* isAPropertyOf(VObject *o, const char *id)
00416 {
00417     VObjectIterator i;
00418     initPropIterator(&i,o);
00419     while (moreIteration(&i)) {
00420   VObject *each = nextVObject(&i);
00421   if (!PL_strcasecmp(id,each->id))
00422       return each;
00423   }
00424     return (VObject*)0;
00425 }
00426 
00427 VObject* addGroup(VObject *o, const char *g)
00428 {
00429     /*
00430   a.b.c
00431   -->
00432   prop(c)
00433       prop(VCGrouping=b)
00434     prop(VCGrouping=a)
00435      */
00436     char *dot = PL_strrchr(g,'.');
00437     if (dot) {
00438   VObject *p, *t;
00439   char *gs, *n = dot+1;
00440   gs = dupStr(g,0); /* so we can write to it. */
00441   t = p = addProp_(o,lookupProp(n));
00442   dot = PL_strrchr(gs,'.');
00443   *dot = 0;
00444   do {
00445       dot = PL_strrchr(gs,'.');
00446       if (dot) {
00447     n = dot+1;
00448     *dot=0;
00449     }
00450       else
00451     n = gs;
00452       /* property(VCGroupingProp=n);
00453        *  and the value may have VCGrouping property
00454        */
00455       t = addProp(t,VCGroupingProp);
00456       setVObjectStringZValue(t,lookupProp_(n));
00457       } while (n != gs);
00458   deleteString(gs); 
00459   return p;
00460   }
00461     else
00462   return addProp_(o,lookupProp(g));
00463 }
00464 
00465 VObject* addPropValue(VObject *o, const char *p, const char *v)
00466 {
00467     VObject *prop;
00468     prop = addProp(o,p);
00469   if (v) {
00470     setVObjectUStringZValue_(prop, fakeUnicode(v,0));
00471     if (needsQuotedPrintable (v)) {
00472       if (PL_strcasecmp (VCCardProp, vObjectName(o)) == 0) 
00473         addProp (prop, VCQuotedPrintableProp);
00474       else
00475         addProp (o, VCQuotedPrintableProp);
00476     }
00477   }
00478   else
00479     setVObjectUStringZValue_(prop, fakeUnicode("",0));
00480 
00481     return prop;
00482 }
00483 
00484 VObject* addPropSizedValue_(VObject *o, const char *p, const char *v,
00485   unsigned int size)
00486 {
00487     VObject *prop;
00488     prop = addProp(o,p);
00489     setValueWithSize_(prop, (void*)v, size);
00490     return prop;
00491 }
00492 
00493 VObject* addPropSizedValue(VObject *o, const char *p, const char *v,
00494   unsigned int size)
00495 {
00496     return addPropSizedValue_(o,p,dupStr(v,size),size);
00497 }
00498 
00499 
00500 
00501 /*----------------------------------------------------------------------
00502   The following pretty print a VObject
00503   ----------------------------------------------------------------------*/
00504 
00505 static void indent(nsOutputFileStream *fp, int level)
00506 {
00507   int i;
00508   for (i=0;i<level*4;i++) {
00509     fp->write(" ", 1);
00510   }
00511 }
00512 
00513 static void printValue(nsOutputFileStream *fp, VObject *o, int level)
00514 {
00515   char *buf = nsnull;
00516 
00517   switch (VALUE_TYPE(o)) {
00518   case VCVT_USTRINGZ: {
00519     char c;
00520     char *t,*s;
00521     s = t = fakeCString(USTRINGZ_VALUE_OF(o));
00522     fp->write("'",1);
00523     while (c=*t,c) {
00524       fp->write(&c,1);
00525       if (c == '\n') indent(fp,level+2);
00526       t++;
00527     }
00528     fp->write("'",1);
00529     deleteString(s);
00530     break;
00531                       }
00532   case VCVT_STRINGZ: {
00533     char c;
00534     char *str = &c;
00535     const char *s = STRINGZ_VALUE_OF(o);
00536     fp->write("'",1);
00537     while (c=*s,c) {
00538       fp->write(str,1);
00539       if (c == '\n') indent(fp,level+2);
00540       s++;
00541     }
00542     fp->write("'",1);
00543     break;
00544                      }
00545   case VCVT_UINT:    
00546     buf = PR_smprintf("%d", INTEGER_VALUE_OF(o)); 
00547     if (buf)
00548     {
00549       fp->write(buf, strlen(buf));
00550       PR_FREEIF(buf);
00551     }
00552     break;
00553 
00554   case VCVT_ULONG:
00555     buf = PR_smprintf("%ld", LONG_VALUE_OF(o)); 
00556     if (buf)
00557     {
00558       fp->write(buf, strlen(buf));
00559       PR_FREEIF(buf);
00560     }
00561     break;
00562 
00563   case VCVT_RAW:
00564     fp->write("[raw data]", 10); 
00565     break;
00566 
00567   case VCVT_VOBJECT:
00568     fp->write("[vobject]\n", 11);
00569     printVObject_(fp,VOBJECT_VALUE_OF(o),level+1);
00570     break;
00571 
00572   case 0:
00573     fp->write("[none]", 6); 
00574     break;
00575   default:
00576     fp->write("[unknown]", 9); 
00577     break;
00578   }
00579 }
00580 
00581 static void printNameValue(nsOutputFileStream *fp,VObject *o, int level)
00582 {
00583   char  *buf;
00584 
00585   indent(fp,level);
00586   if (NAME_OF(o)) 
00587   {
00588     buf = PR_smprintf("%s", NAME_OF(o)); 
00589     if (buf)
00590     {
00591       fp->write(buf, strlen(buf));
00592       PR_FREEIF(buf);
00593     }
00594   }
00595 
00596   if (VALUE_TYPE(o)) 
00597   {
00598     fp->write("=",1);
00599     printValue(fp,o, level);
00600   }
00601 
00602   fp->write("\n", 1);
00603 }
00604 
00605 void printVObject_(nsOutputFileStream *fp, VObject *o, int level)
00606 {
00607   VObjectIterator t;
00608   if (o == 0) {
00609     fp->write("[NULL]\n", 7);
00610     return;
00611   }
00612 
00613   printNameValue(fp,o,level);
00614   initPropIterator(&t,o);
00615 
00616   while (moreIteration(&t)) 
00617   {
00618     VObject *eachProp = nextVObject(&t);
00619     printVObject_(fp,eachProp,level+1);
00620   }
00621 }
00622 
00623 void printVObject(nsOutputFileStream *fp,VObject *o)
00624 {
00625   printVObject_(fp,o,0);
00626 }
00627 
00628 void printVObjectToFile(nsFileSpec *fname, VObject *o)
00629 {
00630 #if !defined(MOZADDRSTANDALONE)
00631   nsOutputFileStream *fp = new nsOutputFileStream(*fname, PR_WRONLY | PR_CREATE_FILE, 00600);
00632 
00633   if (fp) {
00634     printVObject(fp,o);
00635     fp->close();
00636   }
00637 #else
00638   NS_ASSERTION(PR_FALSE, "1.10 <rhp@netscape.com> 06 Jan 2000 08:01");
00639 #endif
00640 }
00641 
00642 void printVObjectsToFile(nsFileSpec *fname,VObject *list)
00643 {
00644 #if !defined(MOZADDRSTANDALONE)
00645   nsOutputFileStream *fp = new nsOutputFileStream(*fname, PR_WRONLY | PR_CREATE_FILE, 00600);
00646   if (fp) {
00647     while (list) {
00648       printVObject(fp,list);
00649       list = nextVObjectInList(list);
00650     }
00651     fp->close();
00652   }
00653 #else
00654   NS_ASSERTION(PR_FALSE, "1.10 <rhp@netscape.com> 06 Jan 2000 08:01");
00655 #endif
00656 }
00657 
00658 
00659 void cleanVObject(VObject *o)
00660 {
00661     if (o == 0) return;
00662     if (o->prop) {
00663   /* destroy time: cannot use the iterator here.
00664      Have to break the cycle in the circular link
00665      list and turns it into regular NULL-terminated
00666      list -- since at some point of destruction,
00667      the reference entry for the iterator to work
00668      will not longer be valid.
00669      */
00670   VObject *p;
00671   p = o->prop->next;
00672   o->prop->next = 0;
00673   do {
00674      VObject *t = p->next;
00675      cleanVObject(p);
00676      p = t;
00677      } while (p);
00678   }
00679     switch (VALUE_TYPE(o)) {
00680   case VCVT_USTRINGZ:
00681   case VCVT_STRINGZ:
00682   case VCVT_RAW:
00683       /* assume they are all allocated by malloc. */
00684       if ((char*) STRINGZ_VALUE_OF(o)) 
00685         PR_Free ((char*)STRINGZ_VALUE_OF(o));
00686       break;
00687   case VCVT_VOBJECT:
00688       cleanVObject(VOBJECT_VALUE_OF(o));
00689       break;
00690   }
00691     deleteVObject(o);
00692 }
00693 
00694 void cleanVObjects(VObject *list)
00695 {
00696     while (list) {
00697   VObject *t = list;
00698   list = nextVObjectInList(list);
00699   cleanVObject(t);
00700   }
00701 }
00702 
00703 /*----------------------------------------------------------------------
00704   The following is a String Table Facilities.
00705   ----------------------------------------------------------------------*/
00706 
00707 #define STRTBLSIZE 255
00708 
00709 static StrItem *strTbl[STRTBLSIZE];
00710 
00711 static unsigned int hashStr(const char *s)
00712 {
00713     unsigned int h = 0;
00714     int i;
00715     for (i=0;s[i];i++) {
00716   h += s[i]*i;
00717   }
00718     return h % STRTBLSIZE;
00719 }
00720 
00721 void unUseStr(const char *s)
00722 {
00723   StrItem *t, *p;
00724   unsigned int h = hashStr(s);
00725   if ((t = strTbl[h]) != 0) {
00726     p = t;
00727     do {
00728       if (PL_strcasecmp(t->s,s) == 0) {
00729         t->refCnt--;
00730         if (t->refCnt == 0) {
00731           if (t == strTbl[h]) {
00732             strTbl[h] = t->next;
00733           }
00734           else {
00735             p->next = t->next;
00736           }
00737           deleteString((char *)t->s);
00738           deleteStrItem(t);
00739           return;
00740         }
00741       }
00742       p = t;
00743       t = t->next;
00744      } while (t);
00745   }
00746 }
00747 
00748 struct PreDefProp {
00749     const char *name;
00750     const char *alias;
00751     const char** fields;
00752     unsigned int flags;
00753     };
00754 
00755 /* flags in PreDefProp */
00756 #define PD_BEGIN  0x1
00757 #define PD_INTERNAL 0x2
00758 
00759 static const char *adrFields[] = {
00760     VCPostalBoxProp,
00761     VCExtAddressProp,
00762     VCStreetAddressProp,
00763     VCCityProp,
00764     VCRegionProp,
00765     VCPostalCodeProp,
00766     VCCountryNameProp,
00767     0
00768 };
00769 
00770 static const char *nameFields[] = {
00771     VCFamilyNameProp,
00772     VCGivenNameProp,
00773     VCAdditionalNamesProp,
00774     VCNamePrefixesProp,
00775     VCNameSuffixesProp,
00776     NULL
00777     };
00778 
00779 static const char *orgFields[] = {
00780     VCOrgNameProp,
00781     VCOrgUnitProp,
00782     VCOrgUnit2Prop,
00783     VCOrgUnit3Prop,
00784     VCOrgUnit4Prop,
00785     NULL
00786     };
00787 
00788 static const char *AAlarmFields[] = {
00789     VCRunTimeProp,
00790     VCSnoozeTimeProp,
00791     VCRepeatCountProp,
00792     VCAudioContentProp,
00793     0
00794     };
00795 
00796 static const char *coolTalkFields[] = {
00797     VCCooltalkAddress,
00798   VCUseServer,
00799     0
00800     };
00801 
00802 /* ExDate -- has unamed fields */
00803 /* RDate -- has unamed fields */
00804 
00805 static const char *DAlarmFields[] = {
00806     VCRunTimeProp,
00807     VCSnoozeTimeProp,
00808     VCRepeatCountProp,
00809     VCDisplayStringProp,
00810     0
00811     };
00812 
00813 static const char *MAlarmFields[] = {
00814     VCRunTimeProp,
00815     VCSnoozeTimeProp,
00816     VCRepeatCountProp,
00817     VCEmailAddressProp,
00818     VCNoteProp,
00819     0
00820     };
00821 
00822 static const char *PAlarmFields[] = {
00823     VCRunTimeProp,
00824     VCSnoozeTimeProp,
00825     VCRepeatCountProp,
00826     VCProcedureNameProp,
00827     0
00828     };
00829 
00830 static struct PreDefProp propNames[] = {
00831     { VC7bitProp, 0, 0, 0 },
00832   { VC8bitProp, 0, 0, 0 },
00833     { VCAAlarmProp, 0, AAlarmFields, 0 },
00834     { VCAdditionalNamesProp, 0, 0, 0 },
00835     { VCAdrProp, 0, adrFields, 0 },
00836     { VCAgentProp, 0, 0, 0 },
00837     { VCAIFFProp, 0, 0, 0 },
00838     { VCAOLProp, 0, 0, 0 },
00839     { VCAppleLinkProp, 0, 0, 0 },
00840   { VCAttachProp, 0, 0, 0 },
00841     { VCAttendeeProp, 0, 0, 0 },
00842     { VCATTMailProp, 0, 0, 0 },
00843     { VCAudioContentProp, 0, 0, 0 },
00844     { VCAVIProp, 0, 0, 0 },
00845     { VCBase64Prop, 0, 0, 0 },
00846     { VCBBSProp, 0, 0, 0 },
00847     { VCBirthDateProp, 0, 0, 0 },
00848     { VCBMPProp, 0, 0, 0 },
00849     { VCBodyProp, 0, 0, 0 },
00850     { VCBusinessRoleProp, 0, 0, 0 },
00851     { VCCalProp, 0, 0, PD_BEGIN },
00852     { VCCaptionProp, 0, 0, 0 },
00853     { VCCardProp, 0, 0, PD_BEGIN },
00854     { VCCarProp, 0, 0, 0 },
00855     { VCCategoriesProp, 0, 0, 0 },
00856     { VCCellularProp, 0, 0, 0 },
00857     { VCCGMProp, 0, 0, 0 },
00858     { VCCharSetProp, 0, 0, 0 },
00859     { VCCIDProp, VCContentIDProp, 0, 0 },
00860     { VCCISProp, 0, 0, 0 },
00861     { VCCityProp, 0, 0, 0 },
00862     { VCClassProp, 0, 0, 0 },
00863     { VCCommentProp, 0, 0, 0 },
00864     { VCCompletedProp, 0, 0, 0 },
00865     { VCContentIDProp, 0, 0, 0 },
00866     { VCCountryNameProp, 0, 0, 0 },
00867     { VCDAlarmProp, 0, DAlarmFields, 0 },
00868     { VCDataSizeProp, 0, 0, PD_INTERNAL },
00869   { VCDayLightProp, 0, 0 ,0 },
00870     { VCDCreatedProp, 0, 0, 0 },
00871     { VCDeliveryLabelProp, 0, 0, 0 },
00872     { VCDescriptionProp, 0, 0, 0 },
00873     { VCDIBProp, 0, 0, 0 },
00874     { VCDisplayStringProp, 0, 0, 0 },
00875     { VCDomesticProp, 0, 0, 0 },
00876     { VCDTendProp, 0, 0, 0 },
00877     { VCDTstartProp, 0, 0, 0 },
00878     { VCDueProp, 0, 0, 0 },
00879     { VCEmailAddressProp, 0, 0, 0 },
00880     { VCEncodingProp, 0, 0, 0 },
00881     { VCEndProp, 0, 0, 0 },
00882     { VCEventProp, 0, 0, PD_BEGIN },
00883     { VCEWorldProp, 0, 0, 0 },
00884     { VCExNumProp, 0, 0, 0 },
00885     { VCExpDateProp, 0, 0, 0 },
00886     { VCExpectProp, 0, 0, 0 },
00887     { VCExtAddressProp, 0, 0, 0 },
00888     { VCFamilyNameProp, 0, 0, 0 },
00889     { VCFaxProp, 0, 0, 0 },
00890     { VCFullNameProp, 0, 0, 0 },
00891     { VCGeoLocationProp, 0, 0, 0 },
00892     { VCGeoProp, 0, 0, 0 },
00893     { VCGIFProp, 0, 0, 0 },
00894     { VCGivenNameProp, 0, 0, 0 },
00895     { VCGroupingProp, 0, 0, 0 },
00896     { VCHomeProp, 0, 0, 0 },
00897     { VCIBMMailProp, 0, 0, 0 },
00898     { VCInlineProp, 0, 0, 0 },
00899     { VCInternationalProp, 0, 0, 0 },
00900     { VCInternetProp, 0, 0, 0 },
00901     { VCISDNProp, 0, 0, 0 },
00902     { VCJPEGProp, 0, 0, 0 },
00903     { VCLanguageProp, 0, 0, 0 },
00904     { VCLastModifiedProp, 0, 0, 0 },
00905     { VCLastRevisedProp, 0, 0, 0 },
00906     { VCLocationProp, 0, 0, 0 },
00907     { VCLogoProp, 0, 0, 0 },
00908     { VCMailerProp, 0, 0, 0 },
00909     { VCMAlarmProp, 0, MAlarmFields, 0 },
00910     { VCMCIMailProp, 0, 0, 0 },
00911     { VCMessageProp, 0, 0, 0 },
00912     { VCMETProp, 0, 0, 0 },
00913     { VCModemProp, 0, 0, 0 },
00914     { VCMPEG2Prop, 0, 0, 0 },
00915     { VCMPEGProp, 0, 0, 0 },
00916     { VCMSNProp, 0, 0, 0 },
00917     { VCNamePrefixesProp, 0, 0, 0 },
00918     { VCNameProp, 0, nameFields, 0 },
00919     { VCNameSuffixesProp, 0, 0, 0 },
00920     { VCNoteProp, 0, 0, 0 },
00921     { VCOrgNameProp, 0, 0, 0 },
00922     { VCOrgProp, 0, orgFields, 0 },
00923     { VCOrgUnit2Prop, 0, 0, 0 },
00924     { VCOrgUnit3Prop, 0, 0, 0 },
00925     { VCOrgUnit4Prop, 0, 0, 0 },
00926     { VCOrgUnitProp, 0, 0, 0 },
00927     { VCPagerProp, 0, 0, 0 },
00928     { VCPAlarmProp, 0, PAlarmFields, 0 },
00929     { VCParcelProp, 0, 0, 0 },
00930     { VCPartProp, 0, 0, 0 },
00931     { VCPCMProp, 0, 0, 0 },
00932     { VCPDFProp, 0, 0, 0 },
00933     { VCPGPProp, 0, 0, 0 },
00934     { VCPhotoProp, 0, 0, 0 },
00935     { VCPICTProp, 0, 0, 0 },
00936     { VCPMBProp, 0, 0, 0 },
00937     { VCPostalBoxProp, 0, 0, 0 },
00938     { VCPostalCodeProp, 0, 0, 0 },
00939     { VCPostalProp, 0, 0, 0 },
00940     { VCPowerShareProp, 0, 0, 0 },
00941     { VCPreferredProp, 0, 0, 0 },
00942     { VCPriorityProp, 0, 0, 0 },
00943     { VCProcedureNameProp, 0, 0, 0 },
00944     { VCProdIdProp, 0, 0, 0 },
00945     { VCProdigyProp, 0, 0, 0 },
00946     { VCPronunciationProp, 0, 0, 0 },
00947     { VCPSProp, 0, 0, 0 },
00948     { VCPublicKeyProp, 0, 0, 0 },
00949     { VCQPProp, VCQuotedPrintableProp, 0, 0 },
00950     { VCQuickTimeProp, 0, 0, 0 },
00951     { VCQuotedPrintableProp, 0, 0, 0 },
00952     { VCRDateProp, 0, 0, 0 },
00953     { VCRegionProp, 0, 0, 0 },
00954     { VCRelatedToProp, 0, 0, 0 },
00955     { VCRepeatCountProp, 0, 0, 0 },
00956     { VCResourcesProp, 0, 0, 0 },
00957     { VCRNumProp, 0, 0, 0 },
00958     { VCRoleProp, 0, 0, 0 },
00959     { VCRRuleProp, 0, 0, 0 },
00960     { VCRSVPProp, 0, 0, 0 },
00961     { VCRunTimeProp, 0, 0, 0 },
00962     { VCSequenceProp, 0, 0, 0 },
00963     { VCSnoozeTimeProp, 0, 0, 0 },
00964     { VCStartProp, 0, 0, 0 },
00965     { VCStatusProp, 0, 0, 0 },
00966     { VCStreetAddressProp, 0, 0, 0 },
00967     { VCSubTypeProp, 0, 0, 0 },
00968     { VCSummaryProp, 0, 0, 0 },
00969     { VCTelephoneProp, 0, 0, 0 },
00970     { VCTIFFProp, 0, 0, 0 },
00971     { VCTimeZoneProp, 0, 0, 0 },
00972     { VCTitleProp, 0, 0, 0 },
00973     { VCTLXProp, 0, 0, 0 },
00974     { VCTodoProp, 0, 0, PD_BEGIN },
00975     { VCTranspProp, 0, 0, 0 },
00976     { VCUniqueStringProp, 0, 0, 0 },
00977     { VCURLProp, 0, 0, 0 },
00978     { VCURLValueProp, 0, 0, 0 },
00979     { VCValueProp, 0, 0, 0 },
00980     { VCVersionProp, 0, 0, 0 },
00981     { VCVideoProp, 0, 0, 0 },
00982     { VCVoiceProp, 0, 0, 0 },
00983     { VCWAVEProp, 0, 0, 0 },
00984     { VCWMFProp, 0, 0, 0 },
00985     { VCWorkProp, 0, 0, 0 },
00986     { VCX400Prop, 0, 0, 0 },
00987     { VCX509Prop, 0, 0, 0 },
00988     { VCXRuleProp, 0, 0, 0 },
00989   { VCCooltalk, 0, coolTalkFields, 0 },
00990   { VCCooltalkAddress, 0, 0, 0 },
00991   { VCUseServer, 0, 0, 0 },
00992   { VCUseHTML, 0, 0, 0 },
00993     { 0,0,0,0 }
00994     };
00995 
00996 
00997 static struct PreDefProp* lookupPropInfo(const char* str)
00998 {
00999     /* brute force for now, could use a hash table here. */
01000     int i;
01001   
01002     for (i = 0; propNames[i].name; i++) 
01003   if (PL_strcasecmp(str, propNames[i].name) == 0) {
01004       return &propNames[i];
01005       }
01006     
01007     return 0;
01008 }
01009 
01010 
01011 const char* lookupProp_(const char* str)
01012 {
01013     int i;
01014   
01015     for (i = 0; propNames[i].name; i++)
01016   if (PL_strcasecmp(str, propNames[i].name) == 0) {
01017       const char* s;
01018       s = propNames[i].alias?propNames[i].alias:propNames[i].name;
01019       return lookupStr(s);
01020       }
01021     return lookupStr(str);
01022 }
01023 
01024 
01025 const char* lookupProp(const char* str)
01026 {
01027     int i;
01028   
01029     for (i = 0; propNames[i].name; i++)
01030   if (PL_strcasecmp(str, propNames[i].name) == 0) {
01031       const char *s;
01032       fieldedProp = (char **)propNames[i].fields;
01033       s = propNames[i].alias?propNames[i].alias:propNames[i].name;
01034       return lookupStr(s);
01035       }
01036     fieldedProp = 0;
01037     return lookupStr(str);
01038 }
01039 
01040 
01041 /*----------------------------------------------------------------------
01042   APIs to Output text form.
01043   ----------------------------------------------------------------------*/
01044 #define OFILE_REALLOC_SIZE 256
01045 /* typedef struct OFile {
01046     nsOutputFileStream *fp;
01047     char *s;
01048     int len;
01049     int limit;
01050     int alloc:1;
01051     int fail:1;
01052     } OFile; */
01053 
01054 static void appendcOFile_(OFile *fp, char c)
01055 {
01056   if (fp->fail) 
01057     return;
01058   if (fp->fp) {
01059     fp->fp->write(&c,1);
01060   }
01061   else {
01062 stuff:
01063   if (fp->len+1 < fp->limit) {
01064     fp->s[fp->len] = c;
01065     fp->len++;
01066     return;
01067   }
01068   else if (fp->alloc) {
01069     fp->limit = fp->limit + OFILE_REALLOC_SIZE;
01070     fp->s = (char *)PR_Realloc(fp->s,fp->limit);
01071     if (fp->s) goto stuff;
01072   }
01073   if (fp->alloc)
01074     PR_FREEIF(fp->s);
01075   fp->s = 0;
01076   fp->fail = 1;
01077   }
01078 }
01079 
01080 static void appendcOFile(OFile *fp, char c)
01081 {
01082 /*  int i = 0; */
01083     if (c == '\n') {
01084   /* write out as <CR><LF> */
01085   /* for (i = 0; i < LINEBREAK_LEN; i++)
01086     appendcOFile_(fp,LINEBREAK [ i ]); */
01087   appendcOFile_(fp,0xd); 
01088   appendcOFile_(fp,0xa); 
01089   }
01090     else
01091   appendcOFile_(fp,c);
01092 }
01093 
01094 static void appendsOFile(OFile *fp, const char *s)
01095 {
01096     int i, slen;
01097     slen  = PL_strlen (s);
01098     for (i=0; i<slen; i++) {
01099   appendcOFile(fp,s[i]);
01100   }
01101 }
01102 
01103 static void initOFile(OFile *fp, nsOutputFileStream *ofp)
01104 {
01105     fp->fp = ofp;
01106     fp->s = 0;
01107     fp->len = 0;
01108     fp->limit = 0;
01109     fp->alloc = 0;
01110     fp->fail = 0;
01111 }
01112 
01113 static void initMemOFile(OFile *fp, char *s, int len)
01114 {
01115     fp->fp = 0;
01116     fp->s = s;
01117     fp->len = 0;
01118     fp->limit = s?len:0;
01119     fp->alloc = s?0:1;
01120     fp->fail = 0;
01121 }
01122 
01123 
01124 static int writeBase64(OFile *fp, unsigned char *s, long len)
01125 {
01126     long cur = 0;
01127     int i, numQuads = 0;
01128     unsigned long trip;
01129     unsigned char b;
01130     char quad[5];
01131 #define PR_MAXQUADS 16
01132 
01133     quad[4] = 0;
01134 
01135     while (cur < len) {
01136   /* collect the triplet of bytes into 'trip' */
01137   trip = 0;
01138   for (i = 0; i < 3; i++) {
01139       b = (cur < len) ? *(s + cur) : 0;
01140       cur++;
01141       trip = trip << 8 | b;
01142       }
01143   /* fill in 'quad' with the appropriate four characters */
01144   for (i = 3; i >= 0; i--) {
01145       b = (unsigned char)(trip & 0x3F);
01146       trip = trip >> 6;
01147       if ((3 - i) < (cur - len))
01148     quad[i] = '='; /* pad char */
01149       else if (b < 26) quad[i] = (char)b + 'A';
01150       else if (b < 52) quad[i] = (char)(b - 26) + 'a';
01151       else if (b < 62) quad[i] = (char)(b - 52) + '0';
01152       else if (b == 62) quad[i] = '+';
01153       else quad[i] = '/';
01154       }
01155   /* now output 'quad' with appropriate whitespace and line ending */
01156   appendsOFile(fp, (numQuads == 0 ? "    " : ""));
01157   appendsOFile(fp, quad);
01158   appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==PR_MAXQUADS-1?"\n" : "")));
01159   numQuads = (numQuads + 1) % PR_MAXQUADS;
01160   }
01161     appendcOFile(fp,'\n');
01162 
01163     return 1;
01164 }
01165 
01166 static void writeQPString(OFile *fp, const char *s)
01167 {
01168     const unsigned char *p = (const unsigned char *)s;
01169   int current_column = 0;
01170   static const char hexdigits[] = "0123456789ABCDEF";
01171   PRBool white = PR_FALSE;
01172   PRBool contWhite = PR_FALSE;
01173   PRBool mb_p = PR_FALSE;
01174 
01175   if (needsQuotedPrintable (s)) 
01176   {
01177     while (*p) {
01178       if (*p == nsCRT::CR || *p == nsCRT::LF)
01179       {
01180         /* Whitespace cannot be allowed to occur at the end of the line.
01181         So we encode " \n" as " =\n\n", that is, the whitespace, a
01182         soft line break, and then a hard line break.
01183         */
01184 
01185         if (white)
01186         {
01187           appendcOFile(fp,'=');
01188           appendcOFile(fp,'\n');
01189           appendcOFile(fp,'\t');
01190           appendsOFile(fp,"=0D");
01191           appendsOFile(fp,"=0A");
01192           appendcOFile(fp,'=');
01193           appendcOFile(fp,'\n');
01194           appendcOFile(fp,'\t');
01195         }
01196         else
01197         {
01198           appendsOFile(fp,"=0D");
01199           appendsOFile(fp,"=0A");
01200           appendcOFile(fp,'=');
01201           appendcOFile(fp,'\n');
01202           appendcOFile(fp,'\t');
01203           contWhite = PR_FALSE;
01204         }
01205 
01206         /* If its CRLF, swallow two chars instead of one. */
01207         if (*p == nsCRT::CR && *(p+1) == nsCRT::LF)
01208           p++;
01209         white = PR_FALSE;
01210         current_column = 0;
01211       }
01212       else
01213       {
01214         if ((*p >= 33 && *p <= 60) ||   /* safe printing chars */
01215           (*p >= 62 && *p <= 126) ||
01216           (mb_p && (*p == 61 || *p == 127 || *p == 0x1B)))
01217         {
01218           appendcOFile(fp,*p);
01219           current_column++;
01220           white = PR_FALSE;
01221           contWhite = PR_FALSE;
01222         }
01223         else if (*p == ' ' || *p == '\t')   /* whitespace */
01224         {
01225           if (contWhite) 
01226           {
01227             appendcOFile(fp,'=');
01228             appendcOFile(fp,hexdigits[*p >> 4]);
01229             appendcOFile(fp,hexdigits[*p & 0xF]);
01230             current_column += 3;
01231             contWhite = PR_FALSE;
01232           }
01233           else
01234           {
01235             appendcOFile(fp,*p);
01236             current_column++;
01237           }
01238           white = PR_TRUE;
01239         }
01240         else                    /* print as =FF */
01241         {
01242           appendcOFile(fp,'=');
01243           appendcOFile(fp,hexdigits[*p >> 4]);
01244           appendcOFile(fp,hexdigits[*p & 0xF]);
01245           current_column += 3;
01246           white = PR_FALSE;
01247           contWhite = PR_FALSE;
01248         }
01249 
01250         NS_ASSERTION(current_column <= 76, "1.10 <rhp@netscape.com> 06 Jan 2000 08:01"); /* Hard limit required by spec */
01251 
01252         if (current_column >= 73 || ((*(p+1) == ' ') && (current_column + 3 >= 73)))    /* soft line break: "=\r\n" */
01253         {
01254           appendcOFile(fp,'=');
01255           appendcOFile(fp,'\n');
01256           appendcOFile(fp,'\t');
01257           current_column = 0;
01258           if (white)
01259             contWhite = PR_TRUE;
01260           else 
01261             contWhite = PR_FALSE;
01262           white = PR_FALSE;
01263         }
01264       } 
01265       p++;
01266     }  /* while */
01267   }  /* if */
01268   else 
01269   {
01270       while (*p) {
01271       appendcOFile(fp,*p);
01272       p++;
01273     }
01274   }
01275 }
01276 
01277 
01278 static void writeValue(OFile *fp, VObject *o, unsigned long size)
01279 {
01280     if (o == 0) return;
01281     switch (VALUE_TYPE(o)) {
01282   case VCVT_USTRINGZ: {
01283       char *s = fakeCString(USTRINGZ_VALUE_OF(o));
01284       writeQPString(fp, s);
01285       deleteString(s);
01286       break;
01287       }
01288   case VCVT_STRINGZ: {
01289       writeQPString(fp, STRINGZ_VALUE_OF(o));
01290       break;
01291       }
01292   case VCVT_UINT: {
01293       char buf[16];
01294       sprintf(buf,"%u", INTEGER_VALUE_OF(o));
01295       appendsOFile(fp,buf);
01296       break;
01297       }
01298   case VCVT_ULONG: {
01299       char buf[16];
01300       sprintf(buf,"%lu", LONG_VALUE_OF(o));
01301       appendsOFile(fp,buf);
01302       break;
01303       }
01304   case VCVT_RAW: {
01305       appendcOFile(fp,'\n');
01306       writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
01307       break;
01308       }
01309   case VCVT_VOBJECT:
01310       appendcOFile(fp,'\n');
01311       writeVObject_(fp,VOBJECT_VALUE_OF(o));
01312       break;
01313   }
01314 }
01315 
01316 static void writeAttrValue(OFile *fp, VObject *o, int* length)
01317 {
01318   int ilen = 0;
01319     if (NAME_OF(o)) {
01320   struct PreDefProp *pi;
01321   pi = lookupPropInfo(NAME_OF(o));
01322   if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
01323   appendcOFile(fp,';');
01324   if (*length != -1)
01325     (*length)++;
01326   appendsOFile(fp,NAME_OF(o));
01327   if (*length != -1)
01328     (*length) += PL_strlen (NAME_OF(o));
01329   }
01330     else {
01331     appendcOFile(fp,';');
01332     (*length)++;
01333   }
01334     if (VALUE_TYPE(o)) {
01335   appendcOFile(fp,'=');
01336   if (*length != -1) {
01337     (*length)++;
01338     for (ilen = 0; ilen < MAXMOZPROPNAMESIZE - (*length); ilen++)
01339       appendcOFile(fp,' ');
01340   }
01341   writeValue(fp,o,0);
01342   }
01343 }
01344 
01345 static void writeGroup(OFile *fp, VObject *o)
01346 {
01347   nsCAutoString buf(NAME_OF(o));
01348 
01349   while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
01350     buf.Insert(NS_LITERAL_CSTRING("."), 0);
01351     buf.Insert(STRINGZ_VALUE_OF(o), 0);
01352   }
01353   appendsOFile(fp, buf.get());
01354 }
01355 
01356 static int inList(const char **list, const char *s)
01357 {
01358     if (list == 0) return 0;
01359     while (*list) {
01360   if (PL_strcasecmp(*list,s) == 0) return 1;
01361   list++;
01362   }
01363     return 0;
01364 }
01365 
01366 static void writeProp(OFile *fp, VObject *o)
01367 {
01368   int length = -1;
01369   //int ilen = 0;
01370 
01371     if (NAME_OF(o)) {
01372   struct PreDefProp *pi;
01373   VObjectIterator t;
01374   const char **fields_ = 0;
01375   pi = lookupPropInfo(NAME_OF(o));
01376   if (pi && ((pi->flags & PD_BEGIN) != 0)) {
01377       writeVObject_(fp,o);
01378       return;
01379       }
01380   if (isAPropertyOf(o,VCGroupingProp))
01381       writeGroup(fp,o);
01382   else 
01383       appendsOFile(fp,NAME_OF(o));
01384   if (pi) fields_ = pi->fields;
01385   initPropIterator(&t,o);
01386   while (moreIteration(&t)) {
01387       const char *s;
01388       VObject *eachProp = nextVObject(&t);
01389       s = NAME_OF(eachProp);
01390       if (PL_strcasecmp(VCGroupingProp,s) && !inList(fields_,s))
01391     writeAttrValue(fp,eachProp, &length);
01392       }
01393   if (fields_) {
01394       int i = 0, n = 0;
01395       const char** fields = fields_;
01396       /* output prop as fields */
01397       appendcOFile(fp,':');
01398       while (*fields) {
01399     VObject *tt = isAPropertyOf(o,*fields);
01400     i++;
01401     if (tt) n = i;
01402     fields++;
01403     }
01404       fields = fields_;
01405       for (i=0;i<n;i++) {
01406     writeValue(fp,isAPropertyOf(o,*fields),0);
01407     fields++;
01408     if (i<(n-1)) appendcOFile(fp,';');
01409     }
01410       }
01411   }
01412   
01413     if (VALUE_TYPE(o)) {
01414   unsigned long size = 0;
01415         VObject *p = isAPropertyOf(o,VCDataSizeProp);
01416   if (p) size = LONG_VALUE_OF(p);
01417   appendcOFile(fp,':');
01418   writeValue(fp,o,size);
01419   }
01420     appendcOFile(fp,'\n');
01421 }
01422 
01423 void writeVObject_(OFile *fp, VObject *o)
01424 {
01425   //int ilen = 0;
01426     if (NAME_OF(o)) {
01427   struct PreDefProp *pi;
01428   pi = lookupPropInfo(NAME_OF(o));
01429 
01430   if (pi && ((pi->flags & PD_BEGIN) != 0)) {
01431       VObjectIterator t;
01432       const char *begin = NAME_OF(o);
01433       appendsOFile(fp,"begin:");
01434       appendsOFile(fp,begin);
01435       appendcOFile(fp,'\n');
01436       initPropIterator(&t,o);
01437       while (moreIteration(&t)) {
01438       VObject *eachProp = nextVObject(&t);
01439       writeProp(fp, eachProp);
01440     }
01441       appendsOFile(fp,"end:");
01442       appendsOFile(fp,begin);
01443       appendsOFile(fp,"\n\n");
01444       }
01445   }
01446 }
01447 
01448 void writeVObject(nsOutputFileStream *fp, VObject *o)
01449 {
01450     OFile ofp;
01451     initOFile(&ofp,fp);
01452     writeVObject_(&ofp,o);
01453 }
01454 
01455 void writeVObjectToFile(nsFileSpec *fname, VObject *o)
01456 {
01457 #if !defined(MOZADDRSTANDALONE)
01458   nsOutputFileStream *fp = new nsOutputFileStream(*fname, PR_WRONLY | PR_CREATE_FILE, 00600);
01459   
01460   if (fp) {
01461     writeVObject(fp,o);
01462     fp->close();
01463   }
01464 #else
01465   NS_ASSERTION(PR_FALSE, "1.10 <rhp@netscape.com> 06 Jan 2000 08:01");
01466 #endif
01467 }
01468 
01469 void writeVObjectsToFile(nsFileSpec *fname, VObject *list)
01470 {
01471 #if !defined(MOZADDRSTANDALONE)
01472   nsOutputFileStream *fp = new nsOutputFileStream(*fname, PR_WRONLY | PR_CREATE_FILE, 00600);
01473     if (fp) {
01474   while (list) {
01475       writeVObject(fp,list);
01476       list = nextVObjectInList(list);
01477       }
01478   fp->close();
01479   }
01480 #else
01481   NS_ASSERTION(PR_FALSE, "1.10 <rhp@netscape.com> 06 Jan 2000 08:01");
01482 #endif
01483 }
01484 
01485 char* writeMemVObject(char *s, int *len, VObject *o)
01486 {
01487     OFile ofp;
01488     initMemOFile(&ofp,s,len?*len:0);
01489     writeVObject_(&ofp,o);
01490     if (len) *len = ofp.len;
01491     appendcOFile(&ofp,0);
01492     return ofp.s;
01493 }
01494 
01495 extern "C" 
01496 char * writeMemoryVObjects(char *s, int *len, VObject *list, PRBool expandSpaces)
01497 {
01498     OFile ofp;
01499     initMemOFile(&ofp,s,len?*len:0);
01500     while (list) {
01501   writeVObject_(&ofp,list);
01502   list = nextVObjectInList(list);
01503   }
01504     if (len) *len = ofp.len;
01505     appendcOFile(&ofp,0);
01506     return ofp.s;
01507 }
01508 
01509 /*----------------------------------------------------------------------
01510   APIs to do fake Unicode stuff.
01511   ----------------------------------------------------------------------*/
01512 vwchar_t* fakeUnicode(const char *ps, int *bytes)
01513 {
01514     vwchar_t *r, *pw;
01515     int len = strlen(ps)+1;
01516 
01517     pw = r = (vwchar_t*)PR_CALLOC(sizeof(vwchar_t)*len);
01518     if (bytes)
01519   *bytes = len * sizeof(vwchar_t);
01520 
01521     while (*ps) { 
01522   if (*ps == '\n')
01523       *pw = (vwchar_t)0x2028;
01524   else if (*ps == '\r')
01525       *pw = (vwchar_t)0x2029;
01526   else
01527       *pw = (vwchar_t)(unsigned char)*ps;
01528   ps++; pw++;
01529   }        
01530     *pw = (vwchar_t)0;
01531   
01532     return r;
01533 }
01534 
01535 int uStrLen(const vwchar_t *u)
01536 {
01537     int i = 0;
01538     while (*u != (vwchar_t)0) { u++; i++; }
01539     return i;
01540 }
01541 
01542 char* fakeCString(const vwchar_t *u)
01543 {
01544     char *s, *t;
01545     int len = uStrLen(u) + 1;
01546     t = s = (char*)PR_CALLOC(len);
01547     while (*u) {
01548   if (*u == (vwchar_t)0x2028)
01549       *t = '\n';
01550   else if (*u == (vwchar_t)0x2029)
01551       *t = '\r';
01552   else
01553       *t = (char)*u;
01554   u++; t++;
01555   }
01556     *t = 0;
01557     return s;
01558 }
01559 
01560 const char* lookupStr(const char *s)
01561 {
01562     StrItem *t;
01563     unsigned int h = hashStr(s);
01564     if ((t = strTbl[h]) != 0) {
01565   do {
01566       if (PL_strcasecmp(t->s,s) == 0) {
01567     t->refCnt++;
01568     return t->s;
01569     }
01570       t = t->next;
01571       } while (t);
01572   }
01573     s = dupStr(s,0);
01574     strTbl[h] = newStrItem(s,strTbl[h]);
01575     return s;
01576 }