Changeset 63


Ignore:
Timestamp:
Apr 25, 2001, 8:55:35 PM (24 years ago)
Author:
umoeller
Message:

Misc. fixes.

Location:
trunk/src/helpers
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/cctl_chart.c

    r25 r63  
    340340                        // by halving each color component
    341341                        gpihManipulateRGB(&ab.lColor,
    342                                           1,        // multiplier
    343                                           2);       // divisor
     342                                          .5);       // factor
    344343
    345344                    // set the area (fill) color
  • trunk/src/helpers/configsys.c

    r47 r63  
    163163 *@@changed V0.9.7 (2001-01-15) [umoeller]: moved this here from stringh.c; renamed from strhFindKey
    164164 *@@changed V0.9.7 (2001-01-15) [umoeller]: now checking for tabs too
     165 *@@changed V0.9.11 (2001-04-25) [umoeller]: this never found lines which had leading spaces, fixed
    165166 */
    166167
     
    180181        p = strhistr(p, pcszKey);
    181182
    182         if ((p) && (p >= pcszSearchIn))
     183        if (    (p)
     184             && (p >= pcszSearchIn)
     185           )
    183186        {
    184187            // make sure the key is at the beginning of a line
    185188            // by going backwards until we find a char != " "
    186189            const char *pStartOfLine = p;
    187             while (     (   (*pStartOfLine == ' ')
    188                          || (*pStartOfLine == '\t')       // allow tabs too
    189                         )
    190                      && (pStartOfLine > pcszSearchIn)
     190
     191            // fixed this V0.9.11 (2001-04-25) [umoeller]
     192            while (    (pStartOfLine > pcszSearchIn)
     193                    && (    (*(pStartOfLine - 1) == ' ')
     194                         || (*(pStartOfLine - 1) == '\t')       // allow tabs too
     195                       )
    191196                  )
    192                 pStartOfLine--;
     197                --pStartOfLine;
    193198
    194199            // if we're at the beginning of a line or
     
    368373                        ulOldParamOfs,
    369374                        ulToReplace,
    370                         &strReplaceWith);
     375                        strReplaceWith.psz,
     376                        strReplaceWith.ulLength);      // adjusted V0.9.11 (2001-04-22) [umoeller]
    371377
    372378                xstrClear(&strReplaceWith);
     
    10061012}
    10071013
    1008 
     1014// testcase
     1015
     1016/* int main()
     1017{
     1018    PSZ pszContents = NULL;
     1019    if (0 == csysLoadConfigSys(NULL, &pszContents))
     1020    {
     1021        CHAR    szValue[1000];
     1022        PSZ pszValue = csysGetParameter(pszContents,
     1023                                        "IFS=",
     1024                                        szValue,
     1025                                        sizeof(szValue));
     1026        if (pszValue)
     1027            printf("Value: %s", szValue);
     1028    }
     1029
     1030    return (0);
     1031} */
  • trunk/src/helpers/dosh.c

    r60 r63  
    346346                    BOOL fSkipRemoveables) // in: if TRUE, only non-removeable disks will be returned
    347347{
    348     CHAR szName[5] = "";
    349     ULONG ulLogicalDrive = 1, // start with drive A:
    350           ulFound = 0;        // found drives count
    351     APIRET arc            = NO_ERROR; // return code
     348    CHAR    szName[5] = "";
     349    ULONG   ulLogicalDrive = 1, // start with drive A:
     350            ulFound = 0;        // found drives count
     351    APIRET  arc = NO_ERROR; // return code
    352352
    353353    if (fSkipRemoveables)
     
    379379                          1,
    380380                          &dataLen);
    381 
    382         /* _Pmpf(("  ul = %d, Drive %c: arc = %d nonRemoveable = %d",
    383                     ulLogicalDrive,
    384                     G_acDriveLetters[ulLogicalDrive],
    385                     arc,
    386                     nonRemovable)); */
    387381
    388382        if (    // fixed disk and non-removeable
     
    471465 *@@changed V0.9.4 (2000-08-03) [umoeller]: more network fixes
    472466 *@@changed V0.9.9 (2001-03-19) [pr]: validate drive number
     467 *@@changed V0.9.11 (2001-04-23) [umoeller]: added an extra check for floppies
    473468 */
    474469
     
    517512            // sigh...
    518513        case ERROR_NOT_SUPPORTED: // 50
    519         {
    520514            // this is returned by file systems which don't
    521515            // support DASD DosOpen;
    522516            // use some other method then, this isn't likely
    523517            // to fail -- V0.9.1 (2000-02-09) [umoeller]
    524             FSALLOCATE  fsa;
    525             arc = DosQueryFSInfo(ulLogicalDrive,
    526                                  FSIL_ALLOC,
    527                                  &fsa,
    528                                  sizeof(fsa));
    529         break; }
     518
     519            // but don't do this for floppies
     520            // V0.9.11 (2001-04-23) [umoeller]
     521            if (ulLogicalDrive > 2)
     522            {
     523                FSALLOCATE  fsa;
     524                arc = DosQueryFSInfo(ulLogicalDrive,
     525                                     FSIL_ALLOC,
     526                                     &fsa,
     527                                     sizeof(fsa));
     528            }
     529        break;
    530530
    531531        case NO_ERROR:
     
    554554            paramsize = 0,
    555555            datasize = 0;
    556     APIRET    rc = NO_ERROR;
    557     USHORT    data,
    558               param;
     556    APIRET  rc = NO_ERROR;
     557    USHORT  data,
     558            param;
    559559
    560560    name[0] = doshQueryBootDrive();
     
    802802 *
    803803 *@@added V0.9.0 [umoeller]
     804 *@@changed V0.9.11 (2001-04-22) [umoeller]: this copied even with errors, fixed
    804805 */
    805806
     
    820821                         sizeof(FSInfoBuf)); // depends
    821822
    822     #ifdef __OS2V2X__
    823         strcpy(pszVolumeLabel, FSInfoBuf.szVolLabel);
    824     #else
    825         strcpy(pszVolumeLabel, FSInfoBuf.vol.szVolLabel);
    826     #endif
     823    if (!arc)       // V0.9.11 (2001-04-22) [umoeller]
     824    {
     825        #ifdef __OS2V2X__
     826            strcpy(pszVolumeLabel, FSInfoBuf.szVolLabel);
     827        #else
     828            strcpy(pszVolumeLabel, FSInfoBuf.vol.szVolLabel);
     829        #endif
     830    }
    827831
    828832    return (arc);
     
    10231027 *      --  FILE_HIDDEN
    10241028 *
    1025  *      This returns the APIRET of DosQueryPathAttr.
     1029 *      This returns the APIRET of DosQueryPathInfo.
    10261030 *      *pulAttr is only valid if NO_ERROR is
    10271031 *      returned.
  • trunk/src/helpers/encodings.c

    r36 r63  
    3737typedef struct _ENCODINGTABLE
    3838{
     39    XWPENCODINGID   EncodingID;
     40
    3941    unsigned short  cEntries;
    4042    unsigned short  ausEntries[1];        // variable size
     
    6971long encRegisterEncoding(PXWPENCODINGMAP pEncodingMap,
    7072                         unsigned long cArrayEntries,    // count of array items
    71                          XWPENCODINGID EncodingID)
     73                         XWPENCODINGID EncodingID)       // enum from encodings\base.h
    7274{
    7375    long lrc = 0;
  • trunk/src/helpers/gpih.c

    r56 r63  
    196196
    197197/*
     198 * HackColor:
     199 *
     200 */
     201
     202VOID HackColor(PBYTE pb, double dFactor)
     203{
     204    ULONG ul = (ULONG)((double)(*pb) * dFactor);
     205    if (ul > 255)
     206        *pb = 255;
     207    else
     208        *pb = (BYTE)ul;
     209}
     210
     211/*
    198212 *@@ gpihManipulateRGB:
    199213 *      this changes an RGB color value
    200214 *      by multiplying each color component
    201  *      (red, green, blue) with bMultiplier
    202  *      and dividing it by bDivisor afterwards.
     215 *      (red, green, blue) with dFactor.
    203216 *
    204217 *      Each color component is treated separately,
    205  *      so if overflows occur (because bMultiplier
     218 *      so if overflows occur (because dFactor
    206219 *      is > 1), this does not affect the other
    207220 *      components.
    208221 *
    209  *      Example: if you pass a brigt red
    210  *      (0xFF0000) to this func, this will
    211  *      be 0x7F0000 if bMultiplier and
    212  *      bDivisor are 1 and 2.
     222 *@@changed V0.9.11 (2001-04-25) [umoeller]: changed prototype to use a double now
    213223 */
    214224
    215225VOID gpihManipulateRGB(PLONG plColor,       // in/out: RGB color
    216                        BYTE bMultiplier,    // in: multiplier
    217                        BYTE bDivisor)       // in: divisor
     226                       double dFactor)      // in: factor (> 1 makes brigher, < 1 makes darker)
    218227{
    219228    PBYTE   pb = (PBYTE)plColor;
     229
    220230    // in memory, the bytes are blue, green, red, unused
    221     *pb++ = (BYTE)((LONG)(*pb) * bMultiplier / bDivisor); // blue
    222     *pb++ = (BYTE)((LONG)(*pb) * bMultiplier / bDivisor); // green
    223     *pb++ = (BYTE)((LONG)(*pb) * bMultiplier / bDivisor); // red
     231
     232    // blue
     233    ULONG   ul = (ULONG)(   (double)(*pb) * dFactor
     234                        );
     235    if (ul > 255)
     236        *pb = 255;
     237    else
     238        *pb = (BYTE)ul;
     239
     240    // green
     241    ul = (ULONG)(   (double)(*(++pb)) * dFactor
     242                );
     243    if (ul > 255)
     244        *pb = 255;
     245    else
     246        *pb = (BYTE)ul;
     247
     248    // red
     249    ul = (ULONG)(   (double)(*(++pb)) * dFactor
     250                );
     251    if (ul > 255)
     252        *pb = 255;
     253    else
     254        *pb = (BYTE)ul;
    224255}
    225256
  • trunk/src/helpers/xml.c

    r54 r63  
    142142/* ******************************************************************
    143143 *
    144  *   Generic methods
     144 *   Error handling
    145145 *
    146146 ********************************************************************/
    147 
    148 /*
    149  *@@ CompareNodeBaseNodes:
    150  *      tree comparison func for NodeBases.
    151  *      This works for all trees which contain structures
    152  *      whose first item is a _NODEBASE because NODEBASE's first
    153  *      member is a TREE.
    154  *
    155  *      Used in two places:
    156  *
    157  *      --  to insert _CMELEMENTDECLNODE nodes into
    158  *          _DOMDOCTYPENODE.ElementDeclsTree;
    159  *
    160  *      --  to insert _CMELEMENTPARTICLE nodes into
    161  *          _CMELEMENTDECLNODE.ElementNamesTree.
    162  *
    163  *@@added V0.9.9 (2001-02-16) [umoeller]
    164  */
    165 
    166 int TREEENTRY CompareNodeBaseNodes(TREE *t1,
    167                                   TREE *t2)
    168 {
    169     PNODEBASE   p1 = (PNODEBASE)t1,
    170                 p2 = (PNODEBASE)t2;
    171     return (strhcmp(p1->strNodeName.psz, p2->strNodeName.psz));
    172 }
    173 
    174 /*
    175  *@@ CompareNodeBaseNodes:
    176  *      tree comparison func for element declarations.
    177  *      Used to find nodes in _DOMDOCTYPENODE.ElementDeclsTree.
    178  *
    179  *@@added V0.9.9 (2001-02-16) [umoeller]
    180  */
    181 
    182 int TREEENTRY CompareNodeBaseData(TREE *t1,
    183                                  void *pData)
    184 {
    185     PNODEBASE     p1 = (PNODEBASE)t1;
    186     return (strhcmp(p1->strNodeName.psz, (const char*)pData));
    187 }
    188 
    189 /*
    190  *@@ xmlCreateNodeBase:
    191  *      creates a new NODEBASE node.
    192  *
    193  *      Gets called from xmlCreateDomNode also to create
    194  *      a DOMNODE, since that in turn has a NODEBASE.
    195  *
    196  *@@added V0.9.9 (2001-02-16) [umoeller]
    197  */
    198 
    199 APIRET xmlCreateNodeBase(NODEBASETYPE ulNodeType,     // in: node type
    200                          ULONG cb,                    // in: size of struct
    201                          const char *pcszNodeName,    // in: node name or NULL
    202                          ULONG ulNodeNameLength,      // in: node name length
    203                                                       // or 0 to run strlen(pcszNodeName)
    204                          PNODEBASE *ppNew)            // out: new node
    205 {
    206     APIRET      arc = NO_ERROR;
    207     PNODEBASE   pNewNode = (PNODEBASE)malloc(cb);
    208 
    209     if (!pNewNode)
    210         arc = ERROR_NOT_ENOUGH_MEMORY;
    211     else
    212     {
    213         memset(pNewNode, 0, cb);
    214         pNewNode->ulNodeType = ulNodeType;
    215 
    216         xstrInit(&pNewNode->strNodeName, 0);
    217         if (pcszNodeName)
    218             xstrcpy(&pNewNode->strNodeName,
    219                     pcszNodeName,
    220                     ulNodeNameLength);  // if 0, xstrcpy will do strlen()
    221 
    222 
    223         *ppNew = pNewNode;
    224     }
    225 
    226     return (arc);
    227 }
    228 
    229 /*
    230  *@@ xmlDeleteNode:
    231  *      deletes a NODEBASE and frees memory that was
    232  *      associated with its members.
    233  *
    234  *      NOTE: If you call this for derived types, call
    235  *      this LAST, after you have cleared additional
    236  *      members. After calling this, pNode is no longer
    237  *      valid.
    238  *
    239  *@@added V0.9.9 (2001-02-16) [umoeller]
    240  */
    241 
    242 VOID xmlDeleteNode(PNODEBASE pNode)
    243 {
    244     if (pNode)
    245     {
    246         PLISTNODE   pNodeThis;
    247         PDOMNODE    pDomNode = NULL;
    248 
    249         LINKLIST    llDeleteNodes;          // list that nodes to be deleted
    250                                             // can be appended to
    251         PLISTNODE   pDelNode;
    252         lstInit(&llDeleteNodes, FALSE);
    253 
    254         // now handle special types and their allocations
    255         switch (pNode->ulNodeType)
    256         {
    257             case DOMNODE_ELEMENT:
    258             {
    259                 PDOMNODE pAttrib;
    260 
    261                 pDomNode = (PDOMNODE)pNode;
    262 
    263                 // delete all attribute nodes
    264                 pAttrib = (PDOMNODE)treeFirst(pDomNode->AttributesMap);
    265                 while (pAttrib)
    266                 {
    267                     // call delete recursively
    268                     xmlDeleteNode((PNODEBASE)pAttrib);
    269                             // this will remove pAttrib from pNode's attrib
    270                             // tree and rebalance the tree; treeNext will
    271                             // still work #### noooooo
    272                     pAttrib = (PDOMNODE)treeNext((TREE*)pAttrib);
    273                 }
    274             break; }
    275 
    276             case DOMNODE_ATTRIBUTE:
    277             case DOMNODE_TEXT:
    278             case DOMNODE_PROCESSING_INSTRUCTION:
    279             case DOMNODE_COMMENT:
    280             case DOMNODE_DOCUMENT:
    281                 pDomNode = (PDOMNODE)pNode;
    282             break;
    283 
    284             case DOMNODE_DOCUMENT_TYPE:
    285             {
    286                 PDOMDOCTYPENODE pDocType = (PDOMDOCTYPENODE)pNode;
    287                 PCMELEMENTDECLNODE pElDecl;
    288                 PCMATTRIBUTEDECLBASE pAttrDeclBase;
    289 
    290                 pDomNode = (PDOMNODE)pNode;
    291 
    292                 pElDecl = (PCMELEMENTDECLNODE)treeFirst(pDocType->ElementDeclsTree);
    293                 while (pElDecl)
    294                 {
    295                     lstAppendItem(&llDeleteNodes, pElDecl);
    296                     pElDecl = (PCMELEMENTDECLNODE)treeNext((TREE*)pElDecl);
    297                 }
    298 
    299                 pAttrDeclBase = (PCMATTRIBUTEDECLBASE)treeFirst(pDocType->AttribDeclBasesTree);
    300                 while (pAttrDeclBase)
    301                 {
    302                     lstAppendItem(&llDeleteNodes, pAttrDeclBase);
    303                     pAttrDeclBase = (PCMATTRIBUTEDECLBASE)treeNext((TREE*)pAttrDeclBase);
    304                 }
    305 
    306                 xstrClear(&pDocType->strPublicID);
    307                 xstrClear(&pDocType->strSystemID);
    308             break; }
    309 
    310             case ELEMENTPARTICLE_EMPTY:
    311             case ELEMENTPARTICLE_ANY:
    312             case ELEMENTPARTICLE_MIXED:
    313             case ELEMENTPARTICLE_CHOICE:
    314             case ELEMENTPARTICLE_SEQ:
    315             case ELEMENTPARTICLE_NAME:
    316             {
    317                 PCMELEMENTPARTICLE pp = (PCMELEMENTPARTICLE)pNode;
    318                 if (pp->pllSubNodes)
    319                 {
    320                     pDelNode = lstQueryFirstNode(pp->pllSubNodes);
    321                     while (pDelNode)
    322                     {
    323                         PCMELEMENTPARTICLE
    324                                 pParticle = (PCMELEMENTPARTICLE)pDelNode->pItemData;
    325                         xmlDeleteNode((PNODEBASE)pParticle);
    326                         //  treeDelete(pp->         ###
    327                         pDelNode = pDelNode->pNext;
    328                     }
    329                 }
    330             break; }
    331 
    332             // case ATTRIBUTE_DECLARATION_ENUM:     // this is a plain NODEBASE
    333 
    334             case ATTRIBUTE_DECLARATION:
    335             {
    336                 PCMATTRIBUTEDECL pDecl = (PCMATTRIBUTEDECL)pNode;
    337             break; }
    338 
    339             case ATTRIBUTE_DECLARATION_BASE:
    340             break;
    341         }
    342 
    343         if (pDomNode)
    344         {
    345             // recurse into child nodes
    346             while (pNodeThis = lstQueryFirstNode(&pDomNode->llChildren))
    347                 // recurse!!
    348                 xmlDeleteNode((PNODEBASE)(pNodeThis->pItemData));
    349                             // this updates llChildren
    350 
    351             if (pDomNode->pParentNode)
    352             {
    353                 // node has a parent:
    354                 if (pNode->ulNodeType == DOMNODE_ATTRIBUTE)
    355                     // this is an attribute:
    356                     // remove from parent's attributes map
    357                     treeDelete(&pDomNode->pParentNode->AttributesMap,
    358                                (TREE*)pNode);
    359                 else
    360                     // remove this node from the parent's list
    361                     // of child nodes before deleting this node
    362                     lstRemoveItem(&pDomNode->pParentNode->llChildren,
    363                                   pNode);
    364 
    365                 pDomNode->pParentNode = NULL;
    366             }
    367 
    368             xstrFree(pDomNode->pstrNodeValue);
    369             lstClear(&pDomNode->llChildren);
    370         }
    371 
    372         pDelNode = lstQueryFirstNode(&llDeleteNodes);
    373         while (pDelNode)
    374         {
    375             PNODEBASE pNodeBase = (PNODEBASE)pDelNode->pItemData;
    376             xmlDeleteNode(pNodeBase);
    377             pDelNode = pDelNode->pNext;
    378         }
    379 
    380         lstClear(&llDeleteNodes);
    381 
    382         xstrClear(&pNode->strNodeName);
    383         free(pNode);
    384     }
    385 }
    386 
    387 /*
    388  *@@ xmlCreateDomNode:
    389  *      creates a new DOMNODE with the specified
    390  *      type and parent. Other than that, the
    391  *      node fields are zeroed.
    392  *
    393  *      If pParentNode is specified (which is required,
    394  *      unless you are creating a document node),
    395  *      its children list is automatically updated
    396  *      (unless this is an attribute node, which updates
    397  *      the attributes map).
    398  *
    399  *      This returns the following errors:
    400  *
    401  *      --  ERROR_NOT_ENOUGH_MEMORY
    402  *
    403  *      --  ERROR_DOM_NOT_SUPPORTED: invalid ulNodeType
    404  *          specified.
    405  *
    406  *      --  ERROR_DOM_WRONG_DOCUMENT: cannot find the
    407  *          document for this node. This happens if you do
    408  *          not have a document node at the root of your tree.
    409  */
    410 
    411 APIRET xmlCreateDomNode(PDOMNODE pParentNode,        // in: parent node or NULL if root
    412                         NODEBASETYPE ulNodeType,     // in: DOMNODE_* type
    413                         const char *pcszNodeName,    // in: node name or NULL
    414                         ULONG ulNodeNameLength,      // in: node name length
    415                                                      // or 0 to run strlen(pcszNodeName)
    416                         PDOMNODE *ppNew)             // out: new node
    417 {
    418     PDOMNODE pNewNode = NULL;
    419     APIRET  arc = NO_ERROR;
    420 
    421     ULONG   cb = 0;
    422 
    423     switch (ulNodeType)
    424     {
    425         case DOMNODE_DOCUMENT:
    426             cb = sizeof(DOMDOCUMENTNODE);
    427         break;
    428 
    429         case DOMNODE_DOCUMENT_TYPE:
    430             cb = sizeof(DOMDOCTYPENODE);
    431         break;
    432 
    433         default:
    434             cb = sizeof(DOMNODE);
    435         break;
    436     }
    437 
    438     arc = xmlCreateNodeBase(ulNodeType,
    439                             cb,
    440                             pcszNodeName,
    441                             ulNodeNameLength,
    442                             (PNODEBASE*)&pNewNode);
    443     if (arc == NO_ERROR)
    444     {
    445         pNewNode->pParentNode = pParentNode;
    446 
    447         if (pParentNode)
    448         {
    449             // parent specified:
    450             // check if this is an attribute
    451             if (ulNodeType == DOMNODE_ATTRIBUTE)
    452             {
    453                 // attribute:
    454                 // add to parent's attributes list
    455                 if (treeInsertNode(&pParentNode->AttributesMap,
    456                                    &pNewNode->NodeBase.Tree,
    457                                    CompareNodeBaseNodes,
    458                                    FALSE)      // no duplicates
    459                         == TREE_DUPLICATE)
    460                     arc = ERROR_DOM_DUPLICATE_ATTRIBUTE;
    461                                 // shouldn't happen, because expat takes care of this
    462             }
    463             else
    464                 // append this new node to the parent's
    465                 // list of child nodes
    466                 lstAppendItem(&pParentNode->llChildren,
    467                               pNewNode);
    468 
    469             if (!arc)
    470             {
    471                 // set document pointer...
    472                 // if the parent node has a document pointer,
    473                 // we can copy that
    474                 if (pParentNode->pDocumentNode)
    475                     pNewNode->pDocumentNode = pParentNode->pDocumentNode;
    476                 else
    477                     // parent has no document pointer: then it is probably
    478                     // the document itself... check
    479                     if (pParentNode->NodeBase.ulNodeType == DOMNODE_DOCUMENT)
    480                         pNewNode->pDocumentNode = pParentNode;
    481                     else
    482                         arc = ERROR_DOM_NO_DOCUMENT;
    483             }
    484         }
    485 
    486         lstInit(&pNewNode->llChildren, FALSE);
    487         treeInit(&pNewNode->AttributesMap);
    488     }
    489 
    490     if (!arc)
    491         *ppNew = pNewNode;
    492     else
    493         if (pNewNode)
    494             free(pNewNode);
    495 
    496     return (arc);
    497 }
    498 
    499 /*
    500  *@@ xmlGetFirstChild:
    501  *      returns the first child node of pDomNode.
    502  *      See _DOMNODE for what a "child" can be for the
    503  *      various node types.
    504  *
    505  *@@added V0.9.9 (2001-02-14) [umoeller]
    506  */
    507 
    508 PDOMNODE xmlGetFirstChild(PDOMNODE pDomNode)
    509 {
    510     PLISTNODE pListNode = lstQueryFirstNode(&pDomNode->llChildren);
    511     if (pListNode)
    512         return ((PDOMNODE)pListNode->pItemData);
    513 
    514     return (0);
    515 }
    516 
    517 /*
    518  *@@ xmlGetLastChild:
    519  *      returns the last child node of pDomNode.
    520  *      See _DOMNODE for what a "child" can be for the
    521  *      various node types.
    522  *
    523  *@@added V0.9.9 (2001-02-14) [umoeller]
    524  */
    525 
    526 PDOMNODE xmlGetLastChild(PDOMNODE pDomNode)
    527 {
    528     PLISTNODE pListNode = lstQueryLastNode(&pDomNode->llChildren);
    529     if (pListNode)
    530         return ((PDOMNODE)pListNode->pItemData);
    531 
    532     return (0);
    533 }
    534147
    535148/*
     
    584197        "Invalid attribute value",
    585198        "Required attribute is missing",
    586         "Subelement in empty element"
     199        "Subelement in empty element",
     200
     201        "Parsing error",
     202        "Validity error",
     203
     204        "DOM node type not supported",
     205        "No DOM document",
     206        "No DOM element",
     207        "Duplicate doctype",
     208        "Root element doesn't match doctype name",
     209        "DOM integrity error",
     210        "Duplicate attribute",
     211
     212        "Validation error: Undeclared element name",
     213        "Element declaration outside doctype",
     214        "Attlist declaration outside doctype"
    587215    };
    588216
     
    630258/* ******************************************************************
    631259 *
    632  *   Specific DOM node methods
     260 *   Most basic node management
     261 *
     262 ********************************************************************/
     263
     264/*
     265 *@@ CompareNodeBaseNodes:
     266 *      tree comparison func for NodeBases.
     267 *      This works for all trees which contain structures
     268 *      whose first item is a _NODEBASE because NODEBASE's first
     269 *      member is a TREE.
     270 *
     271 *      Used in two places:
     272 *
     273 *      --  to insert _CMELEMENTDECLNODE nodes into
     274 *          _DOMDOCTYPENODE.ElementDeclsTree;
     275 *
     276 *      --  to insert _CMELEMENTPARTICLE nodes into
     277 *          _CMELEMENTDECLNODE.ElementNamesTree.
     278 *
     279 *@@added V0.9.9 (2001-02-16) [umoeller]
     280 */
     281
     282int TREEENTRY CompareNodeBaseNodes(TREE *t1,
     283                                  TREE *t2)
     284{
     285    PNODEBASE   p1 = (PNODEBASE)t1,
     286                p2 = (PNODEBASE)t2;
     287    return (strhcmp(p1->strNodeName.psz, p2->strNodeName.psz));
     288}
     289
     290/*
     291 *@@ CompareNodeBaseNodes:
     292 *      tree comparison func for element declarations.
     293 *      Used to find nodes in _DOMDOCTYPENODE.ElementDeclsTree.
     294 *
     295 *@@added V0.9.9 (2001-02-16) [umoeller]
     296 */
     297
     298int TREEENTRY CompareNodeBaseData(TREE *t1,
     299                                 void *pData)
     300{
     301    PNODEBASE     p1 = (PNODEBASE)t1;
     302    return (strhcmp(p1->strNodeName.psz, (const char*)pData));
     303}
     304
     305/*
     306 *@@ xmlCreateNodeBase:
     307 *      creates a new NODEBASE node.
     308 *
     309 *      Gets called from xmlCreateDomNode also to create
     310 *      a DOMNODE, since that in turn has a NODEBASE.
     311 *
     312 *@@added V0.9.9 (2001-02-16) [umoeller]
     313 */
     314
     315APIRET xmlCreateNodeBase(NODEBASETYPE ulNodeType,     // in: node type
     316                         ULONG cb,                    // in: size of struct
     317                         const char *pcszNodeName,    // in: node name or NULL
     318                         ULONG ulNodeNameLength,      // in: node name length
     319                                                      // or 0 to run strlen(pcszNodeName)
     320                         PNODEBASE *ppNew)            // out: new node
     321{
     322    APIRET      arc = NO_ERROR;
     323    PNODEBASE   pNewNode = (PNODEBASE)malloc(cb);
     324
     325    if (!pNewNode)
     326        arc = ERROR_NOT_ENOUGH_MEMORY;
     327    else
     328    {
     329        memset(pNewNode, 0, cb);
     330        pNewNode->ulNodeType = ulNodeType;
     331
     332        xstrInit(&pNewNode->strNodeName, 0);
     333        if (pcszNodeName)
     334            xstrcpy(&pNewNode->strNodeName,
     335                    pcszNodeName,
     336                    ulNodeNameLength);  // if 0, xstrcpy will do strlen()
     337
     338
     339        *ppNew = pNewNode;
     340    }
     341
     342    return (arc);
     343}
     344
     345/*
     346 *@@ xmlDeleteNode:
     347 *      deletes a NODEBASE and frees memory that was
     348 *      associated with its members.
     349 *
     350 *      NOTE: If you call this for derived types, call
     351 *      this LAST, after you have cleared additional
     352 *      members. After calling this, pNode is no longer
     353 *      valid.
     354 *
     355 *@@added V0.9.9 (2001-02-16) [umoeller]
     356 */
     357
     358VOID xmlDeleteNode(PNODEBASE pNode)
     359{
     360    if (pNode)
     361    {
     362        PLISTNODE   pNodeThis;
     363        PDOMNODE    pDomNode = NULL;
     364
     365        LINKLIST    llDeleteNodes;          // list that nodes to be deleted
     366                                            // can be appended to
     367        PLISTNODE   pDelNode;
     368        lstInit(&llDeleteNodes, FALSE);
     369
     370        // now handle special types and their allocations
     371        switch (pNode->ulNodeType)
     372        {
     373            case DOMNODE_ELEMENT:
     374            {
     375                PDOMNODE pAttrib;
     376
     377                pDomNode = (PDOMNODE)pNode;
     378
     379                // delete all attribute nodes
     380                pAttrib = (PDOMNODE)treeFirst(pDomNode->AttributesMap);
     381                while (pAttrib)
     382                {
     383                    // call delete recursively
     384                    xmlDeleteNode((PNODEBASE)pAttrib);
     385                            // this will remove pAttrib from pNode's attrib
     386                            // tree and rebalance the tree; treeNext will
     387                            // still work #### noooooo
     388                    pAttrib = (PDOMNODE)treeNext((TREE*)pAttrib);
     389                }
     390            break; }
     391
     392            case DOMNODE_ATTRIBUTE:
     393            case DOMNODE_TEXT:
     394            case DOMNODE_PROCESSING_INSTRUCTION:
     395            case DOMNODE_COMMENT:
     396            case DOMNODE_DOCUMENT:
     397                pDomNode = (PDOMNODE)pNode;
     398            break;
     399
     400            case DOMNODE_DOCUMENT_TYPE:
     401            {
     402                PDOMDOCTYPENODE pDocType = (PDOMDOCTYPENODE)pNode;
     403                PCMELEMENTDECLNODE pElDecl;
     404                PCMATTRIBUTEDECLBASE pAttrDeclBase;
     405
     406                pDomNode = (PDOMNODE)pNode;
     407
     408                pElDecl = (PCMELEMENTDECLNODE)treeFirst(pDocType->ElementDeclsTree);
     409                while (pElDecl)
     410                {
     411                    lstAppendItem(&llDeleteNodes, pElDecl);
     412                    pElDecl = (PCMELEMENTDECLNODE)treeNext((TREE*)pElDecl);
     413                }
     414
     415                pAttrDeclBase = (PCMATTRIBUTEDECLBASE)treeFirst(pDocType->AttribDeclBasesTree);
     416                while (pAttrDeclBase)
     417                {
     418                    lstAppendItem(&llDeleteNodes, pAttrDeclBase);
     419                    pAttrDeclBase = (PCMATTRIBUTEDECLBASE)treeNext((TREE*)pAttrDeclBase);
     420                }
     421
     422                xstrClear(&pDocType->strPublicID);
     423                xstrClear(&pDocType->strSystemID);
     424            break; }
     425
     426            case ELEMENTPARTICLE_EMPTY:
     427            case ELEMENTPARTICLE_ANY:
     428            case ELEMENTPARTICLE_MIXED:
     429            case ELEMENTPARTICLE_CHOICE:
     430            case ELEMENTPARTICLE_SEQ:
     431            case ELEMENTPARTICLE_NAME:
     432            {
     433                PCMELEMENTPARTICLE pp = (PCMELEMENTPARTICLE)pNode;
     434                if (pp->pllSubNodes)
     435                {
     436                    pDelNode = lstQueryFirstNode(pp->pllSubNodes);
     437                    while (pDelNode)
     438                    {
     439                        PCMELEMENTPARTICLE
     440                                pParticle = (PCMELEMENTPARTICLE)pDelNode->pItemData;
     441                        xmlDeleteNode((PNODEBASE)pParticle);
     442                        //  treeDelete(pp->         ###
     443                        pDelNode = pDelNode->pNext;
     444                    }
     445                }
     446            break; }
     447
     448            // case ATTRIBUTE_DECLARATION_ENUM:     // this is a plain NODEBASE
     449
     450            case ATTRIBUTE_DECLARATION:
     451            {
     452                PCMATTRIBUTEDECL pDecl = (PCMATTRIBUTEDECL)pNode;
     453            break; }
     454
     455            case ATTRIBUTE_DECLARATION_BASE:
     456            break;
     457        }
     458
     459        if (pDomNode)
     460        {
     461            // recurse into child nodes
     462            while (pNodeThis = lstQueryFirstNode(&pDomNode->llChildren))
     463                // recurse!!
     464                xmlDeleteNode((PNODEBASE)(pNodeThis->pItemData));
     465                            // this updates llChildren
     466
     467            if (pDomNode->pParentNode)
     468            {
     469                // node has a parent:
     470                if (pNode->ulNodeType == DOMNODE_ATTRIBUTE)
     471                    // this is an attribute:
     472                    // remove from parent's attributes map
     473                    treeDelete(&pDomNode->pParentNode->AttributesMap,
     474                               (TREE*)pNode);
     475                else
     476                    // remove this node from the parent's list
     477                    // of child nodes before deleting this node
     478                    lstRemoveItem(&pDomNode->pParentNode->llChildren,
     479                                  pNode);
     480
     481                pDomNode->pParentNode = NULL;
     482            }
     483
     484            xstrFree(pDomNode->pstrNodeValue);
     485            lstClear(&pDomNode->llChildren);
     486        }
     487
     488        pDelNode = lstQueryFirstNode(&llDeleteNodes);
     489        while (pDelNode)
     490        {
     491            PNODEBASE pNodeBase = (PNODEBASE)pDelNode->pItemData;
     492            xmlDeleteNode(pNodeBase);
     493            pDelNode = pDelNode->pNext;
     494        }
     495
     496        lstClear(&llDeleteNodes);
     497
     498        xstrClear(&pNode->strNodeName);
     499        free(pNode);
     500    }
     501}
     502
     503/*
     504 *@@ xmlCreateDomNode:
     505 *      creates a new DOMNODE with the specified
     506 *      type and parent. Other than that, the
     507 *      node fields are zeroed.
     508 *
     509 *      If pParentNode is specified (which is required,
     510 *      unless you are creating a document node),
     511 *      its children list is automatically updated
     512 *      (unless this is an attribute node, which updates
     513 *      the attributes map).
     514 *
     515 *      This returns the following errors:
     516 *
     517 *      --  ERROR_NOT_ENOUGH_MEMORY
     518 *
     519 *      --  ERROR_DOM_NOT_SUPPORTED: invalid ulNodeType
     520 *          specified.
     521 *
     522 *      --  ERROR_DOM_WRONG_DOCUMENT: cannot find the
     523 *          document for this node. This happens if you do
     524 *          not have a document node at the root of your tree.
     525 */
     526
     527APIRET xmlCreateDomNode(PDOMNODE pParentNode,        // in: parent node or NULL if root
     528                        NODEBASETYPE ulNodeType,     // in: DOMNODE_* type
     529                        const char *pcszNodeName,    // in: node name or NULL
     530                        ULONG ulNodeNameLength,      // in: node name length
     531                                                     // or 0 to run strlen(pcszNodeName)
     532                        PDOMNODE *ppNew)             // out: new node
     533{
     534    PDOMNODE pNewNode = NULL;
     535    APIRET  arc = NO_ERROR;
     536
     537    ULONG   cb = 0;
     538
     539    switch (ulNodeType)
     540    {
     541        case DOMNODE_DOCUMENT:
     542            cb = sizeof(DOMDOCUMENTNODE);
     543        break;
     544
     545        case DOMNODE_DOCUMENT_TYPE:
     546            cb = sizeof(DOMDOCTYPENODE);
     547        break;
     548
     549        default:
     550            cb = sizeof(DOMNODE);
     551        break;
     552    }
     553
     554    arc = xmlCreateNodeBase(ulNodeType,
     555                            cb,
     556                            pcszNodeName,
     557                            ulNodeNameLength,
     558                            (PNODEBASE*)&pNewNode);
     559    if (arc == NO_ERROR)
     560    {
     561        pNewNode->pParentNode = pParentNode;
     562
     563        if (pParentNode)
     564        {
     565            // parent specified:
     566            // check if this is an attribute
     567            if (ulNodeType == DOMNODE_ATTRIBUTE)
     568            {
     569                // attribute:
     570                // add to parent's attributes list
     571                if (treeInsertNode(&pParentNode->AttributesMap,
     572                                   &pNewNode->NodeBase.Tree,
     573                                   CompareNodeBaseNodes,
     574                                   FALSE)      // no duplicates
     575                        == TREE_DUPLICATE)
     576                    arc = ERROR_DOM_DUPLICATE_ATTRIBUTE;
     577                                // shouldn't happen, because expat takes care of this
     578            }
     579            else
     580                // append this new node to the parent's
     581                // list of child nodes
     582                lstAppendItem(&pParentNode->llChildren,
     583                              pNewNode);
     584
     585            if (!arc)
     586            {
     587                // set document pointer...
     588                // if the parent node has a document pointer,
     589                // we can copy that
     590                if (pParentNode->pDocumentNode)
     591                    pNewNode->pDocumentNode = pParentNode->pDocumentNode;
     592                else
     593                    // parent has no document pointer: then it is probably
     594                    // the document itself... check
     595                    if (pParentNode->NodeBase.ulNodeType == DOMNODE_DOCUMENT)
     596                        pNewNode->pDocumentNode = pParentNode;
     597                    else
     598                        arc = ERROR_DOM_NO_DOCUMENT;
     599            }
     600        }
     601
     602        lstInit(&pNewNode->llChildren, FALSE);
     603        treeInit(&pNewNode->AttributesMap);
     604    }
     605
     606    if (!arc)
     607        *ppNew = pNewNode;
     608    else
     609        if (pNewNode)
     610            free(pNewNode);
     611
     612    return (arc);
     613}
     614
     615/* ******************************************************************
     616 *
     617 *   Specific DOM node constructors
    633618 *
    634619 ********************************************************************/
     
    871856}
    872857
    873 /*
    874  *@@ xmlGetElementsByTagName:
    875  *      returns a linked list of @DOM_ELEMENT nodes which
    876  *      match the specified element name. The special name
    877  *      "*" matches all elements.
    878  *
    879  *      The caller must free the list by calling lstFree.
    880  *      Returns NULL if no such elements could be found.
    881  *
    882  *@@added V0.9.9 (2001-02-14) [umoeller]
    883  */
    884 
    885 PLINKLIST xmlGetElementsByTagName(const char *pcszName)
    886 {
    887     APIRET arc = NO_ERROR;
    888 
    889     return (0);
    890 }
    891 
    892858/* ******************************************************************
    893859 *
    894  *   Content model methods
     860 *   DOM level 3 content models
    895861 *
    896862 ********************************************************************/
     
    1031997
    1032998/*
    1033  *@@ xmlFindElementDecl:
    1034  *      returns the _CMELEMENTDECLNODE for the element
    1035  *      with the specified name or NULL if there's none.
    1036  *
    1037  *@@added V0.9.9 (2001-02-16) [umoeller]
    1038  */
    1039 
    1040 PCMELEMENTDECLNODE xmlFindElementDecl(PXMLDOM pDom,
    1041                                       const XSTRING *pstrElementName)
    1042 {
    1043     PCMELEMENTDECLNODE pElementDecl = NULL;
    1044 
    1045     PDOMDOCTYPENODE pDocTypeNode = pDom->pDocTypeNode;
    1046     if (    (pDocTypeNode)
    1047          && (pstrElementName)
    1048          && (pstrElementName->ulLength)
    1049        )
    1050     {
    1051         pElementDecl = (PCMELEMENTDECLNODE)treeFindEQData(
    1052                                       &pDocTypeNode->ElementDeclsTree,
    1053                                       (void*)pstrElementName->psz,
    1054                                       CompareNodeBaseData);
    1055     }
    1056 
    1057     return (pElementDecl);
    1058 }
    1059 
    1060 /*
    1061  *@@ xmlFindAttribDeclBase:
    1062  *      returns the _CMATTRIBUTEDECLBASE for the specified
    1063  *      element name, or NULL if none exists.
    1064  *
    1065  *      To find a specific attribute declaration from both
    1066  *      an element and an attribute name, use xmlFindAttribDecl
    1067  *      instead.
    1068  *
    1069  *@@added V0.9.9 (2001-02-16) [umoeller]
    1070  */
    1071 
    1072 PCMATTRIBUTEDECLBASE xmlFindAttribDeclBase(PXMLDOM pDom,
    1073                                              const XSTRING *pstrElementName)
    1074 {
    1075     PCMATTRIBUTEDECLBASE pAttribDeclBase = NULL;
    1076 
    1077     PDOMDOCTYPENODE pDocTypeNode = pDom->pDocTypeNode;
    1078     if (    (pDocTypeNode)
    1079          && (pstrElementName)
    1080          && (pstrElementName->ulLength)
    1081        )
    1082     {
    1083         pAttribDeclBase = (PCMATTRIBUTEDECLBASE)treeFindEQData(
    1084                                         &pDocTypeNode->AttribDeclBasesTree,
    1085                                         (void*)pstrElementName->psz,
    1086                                         CompareNodeBaseData);
    1087     }
    1088 
    1089     return (pAttribDeclBase);
    1090 }
    1091 
    1092 /*
    1093  *@@ xmlFindAttribDecl:
    1094  *      returns the _CMATTRIBUTEDEDECL for the specified
    1095  *      element and attribute name, or NULL if none exists.
    1096  *
    1097  *@@added V0.9.9 (2001-02-16) [umoeller]
    1098  */
    1099 
    1100 PCMATTRIBUTEDECL xmlFindAttribDecl(PXMLDOM pDom,
    1101                                    const XSTRING *pstrElementName,
    1102                                    const XSTRING *pstrAttribName,
    1103                                    PCMATTRIBUTEDECLBASE *ppAttribDeclBase)
    1104                                             // in/out: attr decl base cache;
    1105                                             // the pointer pointed to by this
    1106                                             // must be NULL on the first call
    1107 {
    1108     PCMATTRIBUTEDECL pAttribDecl = NULL;
    1109     if (pstrElementName && pstrAttribName)
    1110     {
    1111         if (!*ppAttribDeclBase)
    1112             // first call for this:
    1113             *ppAttribDeclBase = xmlFindAttribDeclBase(pDom,
    1114                                                       pstrElementName);
    1115         if (*ppAttribDeclBase)
    1116         {
    1117             pAttribDecl = (PCMATTRIBUTEDECL)treeFindEQData(
    1118                                          &((**ppAttribDeclBase).AttribDeclsTree),
    1119                                          (void*)pstrAttribName->psz,
    1120                                          CompareNodeBaseData);
    1121         }
    1122     }
    1123 
    1124     return (pAttribDecl);
    1125 }
    1126 
    1127 /*
    1128999 *@@ ValidateElementChildren
    11291000 *      validates the specified element against the document's @DTD,
     
    11761047                return;     // that's OK
    11771048            else
    1178                 pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
     1049                xmlSetError(pDom,
     1050                            ERROR_DOM_VALIDATE_INVALID_ELEMENT,
     1051                            pNewElement->NodeBase.strNodeName.psz,
     1052                            TRUE);
    11791053        }
    11801054        else
     
    18261700
    18271701    // continue parsing only if we had no errors so far
    1828     /* if (!pDom->arcDOM)
    1829     {
    1830         PLISTNODE pStackLN = NULL;
    1831         PDOMSTACKITEM pSI = PopElementStack(pDom,
    1832                                             &pStackLN);
    1833 
    1834         if (pDom->arcDOM)
    1835             pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
    1836         else
    1837         {
    1838             if (pSI->pDomNode->NodeBase.ulNodeType != DOMNODE_DOCUMENT_TYPE)
    1839                 pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
    1840 
    1841             lstRemoveNode(&pDom->llElementStack, pStackLN); // auto-free
    1842         }
    1843     } */
     1702    if (!pDom->arcDOM)
     1703    {
     1704    }
    18441705}
    18451706
     
    18851746 *
    18861747 *      The pcszPublicId parameter is the public id given in the entity
    1887  *      declaration and may be null.
     1748 *      declaration and may be null (since XML doesn't require public
     1749 *      identifiers).
    18881750 *
    18891751 *      The pcszSystemId is the system identifier specified in the
     
    19261788                                        const XML_Char *pcszPublicId)
    19271789{
    1928     int i = 0;
    1929 
    1930     FILE *f = fopen("log", "w");
    1931     fprintf(f, "sysid: %s\n", pcszSystemId);
    1932     fclose(f);
     1790    int i = 1;
     1791
     1792    // @@todo: allow caller to load external references some way
    19331793
    19341794    /* PXMLDOM     pDom = (PXMLDOM)pUserData;
     
    19701830        PDOMDOCTYPENODE pDocType = pDom->pDocTypeNode;
    19711831        if (!pDocType)
    1972             pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
     1832            xmlSetError(pDom,
     1833                        ERROR_DOM_ELEMENT_DECL_OUTSIDE_DOCTYPE,
     1834                        pcszName,
     1835                        TRUE);
    19731836        else
    19741837        {
     
    20711934        PDOMDOCTYPENODE pDocType = pDom->pDocTypeNode;
    20721935        if (!pDocType)
    2073             pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
     1936            xmlSetError(pDom,
     1937                        ERROR_DOM_ATTLIST_DECL_OUTSIDE_DOCTYPE,
     1938                        pcszElementName,
     1939                        TRUE);
    20741940        else
    20751941        {
     
    22532119/* ******************************************************************
    22542120 *
    2255  *   DOM APIs
     2121 *   DOM root APIs
    22562122 *
    22572123 ********************************************************************/
     
    22712137 *
    22722138 *      --  DF_PARSEDTD: add the @DTD of the document into the DOM tree
    2273  *          as well and validate the document.
     2139 *          as well and validate the document, if a DTD was found.
     2140 *          Otherwise just parse and do not validate.
     2141 *
     2142 *      --  DF_FAIL_IF_NO_DTD: fail if no @DTD was found. Useful
     2143 *          if you want to enforce validation. @@todo
    22742144 *
    22752145 *      Usage:
     
    22782148 *
    22792149 +          PXMLDOM pDom = NULL;
    2280  +          APIRET arc = xmlCreateDom(flags, &pDom);
     2150 +          APIRET arc = xmlCreateDOM(flags, &pDom);
    22812151 +
    22822152 *      2) Give chunks of data (or an entire buffer)
     
    24122282 *         error information in the XMLDOM fields.
    24132283 *
    2414  *      -- ERROR_DOM_PARSING: the document is not @valid.
     2284 *      -- ERROR_DOM_VALIDITY: the document is not @valid.
    24152285 *         This can only happen if @DTD parsing was enabled
    24162286 *         with xmlCreateDOM.
     
    25102380    return (arc);
    25112381}
     2382
     2383/* ******************************************************************
     2384 *
     2385 *   DOM lookup
     2386 *
     2387 ********************************************************************/
     2388
     2389/*
     2390 *@@ xmlFindElementDecl:
     2391 *      returns the _CMELEMENTDECLNODE for the element
     2392 *      with the specified name or NULL if there's none.
     2393 *
     2394 *@@added V0.9.9 (2001-02-16) [umoeller]
     2395 */
     2396
     2397PCMELEMENTDECLNODE xmlFindElementDecl(PXMLDOM pDom,
     2398                                      const XSTRING *pstrElementName)
     2399{
     2400    PCMELEMENTDECLNODE pElementDecl = NULL;
     2401
     2402    PDOMDOCTYPENODE pDocTypeNode = pDom->pDocTypeNode;
     2403    if (    (pDocTypeNode)
     2404         && (pstrElementName)
     2405         && (pstrElementName->ulLength)
     2406       )
     2407    {
     2408        pElementDecl = (PCMELEMENTDECLNODE)treeFindEQData(
     2409                                      &pDocTypeNode->ElementDeclsTree,
     2410                                      (void*)pstrElementName->psz,
     2411                                      CompareNodeBaseData);
     2412    }
     2413
     2414    return (pElementDecl);
     2415}
     2416
     2417/*
     2418 *@@ xmlFindAttribDeclBase:
     2419 *      returns the _CMATTRIBUTEDECLBASE for the specified
     2420 *      element name, or NULL if none exists.
     2421 *
     2422 *      To find a specific attribute declaration from both
     2423 *      an element and an attribute name, use xmlFindAttribDecl
     2424 *      instead.
     2425 *
     2426 *@@added V0.9.9 (2001-02-16) [umoeller]
     2427 */
     2428
     2429PCMATTRIBUTEDECLBASE xmlFindAttribDeclBase(PXMLDOM pDom,
     2430                                           const XSTRING *pstrElementName)
     2431{
     2432    PCMATTRIBUTEDECLBASE pAttribDeclBase = NULL;
     2433
     2434    PDOMDOCTYPENODE pDocTypeNode = pDom->pDocTypeNode;
     2435    if (    (pDocTypeNode)
     2436         && (pstrElementName)
     2437         && (pstrElementName->ulLength)
     2438       )
     2439    {
     2440        pAttribDeclBase = (PCMATTRIBUTEDECLBASE)treeFindEQData(
     2441                                        &pDocTypeNode->AttribDeclBasesTree,
     2442                                        (void*)pstrElementName->psz,
     2443                                        CompareNodeBaseData);
     2444    }
     2445
     2446    return (pAttribDeclBase);
     2447}
     2448
     2449/*
     2450 *@@ xmlFindAttribDecl:
     2451 *      returns the _CMATTRIBUTEDEDECL for the specified
     2452 *      element and attribute name, or NULL if none exists.
     2453 *
     2454 *@@added V0.9.9 (2001-02-16) [umoeller]
     2455 */
     2456
     2457PCMATTRIBUTEDECL xmlFindAttribDecl(PXMLDOM pDom,
     2458                                   const XSTRING *pstrElementName,
     2459                                   const XSTRING *pstrAttribName,
     2460                                   PCMATTRIBUTEDECLBASE *ppAttribDeclBase)
     2461                                            // in/out: attr decl base cache;
     2462                                            // the pointer pointed to by this
     2463                                            // must be NULL on the first call
     2464{
     2465    PCMATTRIBUTEDECL pAttribDecl = NULL;
     2466    if (pstrElementName && pstrAttribName)
     2467    {
     2468        if (!*ppAttribDeclBase)
     2469            // first call for this:
     2470            *ppAttribDeclBase = xmlFindAttribDeclBase(pDom,
     2471                                                      pstrElementName);
     2472        if (*ppAttribDeclBase)
     2473        {
     2474            pAttribDecl = (PCMATTRIBUTEDECL)treeFindEQData(
     2475                                         &((**ppAttribDeclBase).AttribDeclsTree),
     2476                                         (void*)pstrAttribName->psz,
     2477                                         CompareNodeBaseData);
     2478        }
     2479    }
     2480
     2481    return (pAttribDecl);
     2482}
     2483
     2484/*
     2485 *@@ xmlGetRootElement:
     2486 *      returns the root element node from the specified
     2487 *      DOM. Useful helper to start enumerating elements.
     2488 *
     2489 *@@added V0.9.11 (2001-04-22) [umoeller]
     2490 */
     2491
     2492PDOMNODE xmlGetRootElement(PXMLDOM pDom)
     2493{
     2494    PDOMDOCUMENTNODE    pDocumentNode;
     2495    PLISTNODE           pListNode;
     2496    if (    (pDom)
     2497         && (pDocumentNode = pDom->pDocumentNode)
     2498         && (pListNode = lstQueryFirstNode(&pDocumentNode->DomNode.llChildren))
     2499       )
     2500    {
     2501        return ((PDOMNODE)pListNode->pItemData);
     2502    }
     2503
     2504    return (NULL);
     2505}
     2506
     2507/*
     2508 *@@ xmlGetFirstChild:
     2509 *      returns the first child node of pDomNode.
     2510 *      See _DOMNODE for what a "child" can be for the
     2511 *      various node types.
     2512 *
     2513 *@@added V0.9.9 (2001-02-14) [umoeller]
     2514 */
     2515
     2516PDOMNODE xmlGetFirstChild(PDOMNODE pDomNode)
     2517{
     2518    PLISTNODE pListNode = lstQueryFirstNode(&pDomNode->llChildren);
     2519    if (pListNode)
     2520        return ((PDOMNODE)pListNode->pItemData);
     2521
     2522    return (0);
     2523}
     2524
     2525/*
     2526 *@@ xmlGetLastChild:
     2527 *      returns the last child node of pDomNode.
     2528 *      See _DOMNODE for what a "child" can be for the
     2529 *      various node types.
     2530 *
     2531 *@@added V0.9.9 (2001-02-14) [umoeller]
     2532 */
     2533
     2534PDOMNODE xmlGetLastChild(PDOMNODE pDomNode)
     2535{
     2536    PLISTNODE pListNode = lstQueryLastNode(&pDomNode->llChildren);
     2537    if (pListNode)
     2538        return ((PDOMNODE)pListNode->pItemData);
     2539
     2540    return (0);
     2541}
     2542
     2543/*
     2544 *@@ xmlGetFirstText:
     2545 *      returns the first text (character data) node
     2546 *      of pElement or NULL if there's none.
     2547 *
     2548 *@@added V0.9.11 (2001-04-22) [umoeller]
     2549 */
     2550
     2551PDOMNODE xmlGetFirstText(PDOMNODE pElement)
     2552{
     2553    PLISTNODE   pNode;
     2554    PDOMNODE    pDomNodeThis;
     2555
     2556    for (pNode = lstQueryFirstNode(&pElement->llChildren);
     2557         pNode;
     2558         pNode = pNode->pNext)
     2559    {
     2560        if (    (pDomNodeThis = (PDOMNODE)pNode->pItemData)
     2561             && (pDomNodeThis->NodeBase.ulNodeType == DOMNODE_TEXT)
     2562           )
     2563            return (pDomNodeThis);
     2564    }
     2565
     2566    return (NULL);
     2567}
     2568
     2569/*
     2570 *@@ xmlGetElementsByTagName:
     2571 *      returns a linked list of _DOMNODE nodes which
     2572 *      match the specified element name. The special name
     2573 *      "*" matches all elements.
     2574 *
     2575 *      pParent must be the parent element DOMNODE...
     2576 *      the only allowed exception is
     2577 *
     2578 *      The caller must free the list by calling lstFree.
     2579 *      Returns NULL if no such elements could be found.
     2580 *
     2581 *@@added V0.9.9 (2001-02-14) [umoeller]
     2582 */
     2583
     2584PLINKLIST xmlGetElementsByTagName(PDOMNODE pParent,
     2585                                  const char *pcszName)
     2586{
     2587    APIRET arc = NO_ERROR;
     2588
     2589    PLINKLIST pll = lstCreate(FALSE);       // no free
     2590    if (pll)
     2591    {
     2592        ULONG   cItems = 0;
     2593        BOOL    fFindAll = !strcmp(pcszName, "*");
     2594
     2595        PLISTNODE   pNode;
     2596        PDOMNODE    pDomNodeThis;
     2597
     2598        for (pNode = lstQueryFirstNode(&pParent->llChildren);
     2599             pNode;
     2600             pNode = pNode->pNext)
     2601        {
     2602            if (    (pDomNodeThis = (PDOMNODE)pNode->pItemData)
     2603                 && (pDomNodeThis->NodeBase.ulNodeType == DOMNODE_ELEMENT)
     2604                 && (   fFindAll
     2605                     || (!strcmp(pcszName, pDomNodeThis->NodeBase.strNodeName.psz))
     2606                   )
     2607               )
     2608            {
     2609                // element matches:
     2610                lstAppendItem(pll, pDomNodeThis);
     2611                cItems++;
     2612            }
     2613        }
     2614
     2615        if (cItems)
     2616            return (pll);
     2617        else
     2618            lstFree(pll);
     2619    }
     2620
     2621    return (0);
     2622}
     2623
     2624/*
     2625 *@@ xmlGetAttribute:
     2626 *      returns the value of pElement's attribute
     2627 *      with the given name or NULL.
     2628 *
     2629 *      This is a const pointer into the element's
     2630 *      attribute list.
     2631 *
     2632 *@@added V0.9.11 (2001-04-22) [umoeller]
     2633 */
     2634
     2635const XSTRING* xmlGetAttribute(PDOMNODE pElement,
     2636                               const char *pcszAttribName)
     2637{
     2638    PDOMNODE pAttrNode = (PDOMNODE)treeFindEQData(&pElement->AttributesMap,
     2639                                                  (void*)pcszAttribName,
     2640                                                  CompareNodeBaseData);
     2641    if (pAttrNode)
     2642        return (pAttrNode->pstrNodeValue);
     2643
     2644    return (NULL);
     2645}
  • trunk/src/helpers/xmldefs.c

    r39 r63  
    876876 +              <!DOCTYPE name SYSTEM "whatever.dtd">
    877877 *
    878  *      or an internal subset in brackets, which contains the markup
    879  *      directly:
     878 *      The SYSTEM identifier is required with XML, while a public
     879 *      identifier is not. (In SGML, neither is required, but at
     880 *      least one must be present.)
     881 *
     882 *      Alternatively,specify an internal subset in brackets, which
     883 *      contains the markup directly:
    880884 *
    881885 +              <!DOCTYPE name [
  • trunk/src/helpers/xstring.c

    r45 r63  
    690690/*
    691691 *@@ xstrrpl:
    692  *      replaces cReplLen characters in pxstr, starting
    693  *      at the position ulFirstReplPos, with the string
    694  *      in pxstrReplaceWith.
     692 *      replaces "cReplLen" characters in pxstr, starting
     693 *      at the position "ulFirstReplPos", with the first
     694 *      "cReplaceWithLen" characters from pcszReplaceWith.
    695695 *
    696696 *      Returns the new length of the string, excluding
     
    727727 *@@changed V0.9.9 (2001-02-14) [umoeller]: fixed NULL target crash
    728728 *@@changed V0.9.9 (2001-03-09) [umoeller]: now using xstrReserve
     729 *@@changed V0.9.11 (2001-04-22) [umoeller]: replaced replacement XSTRING with PCSZ
    729730 */
    730731
     
    732733              ULONG ulFirstReplOfs,             // in: ofs of first char to replace
    733734              ULONG cReplLen,                   // in: no. of chars to replace
    734               const XSTRING *pstrReplaceWith)   // in: string to replace chars with
     735              const char *pcszReplaceWith,      // in: string to replace chars with
     736              ULONG cReplaceWithLen)            // in: length of replacement string
     737                                                // (this MUST be specified; if 0, chars are removed only)
    735738{
    736739    ULONG   ulrc = 0;
     
    739742    if (    (pxstr)         // V0.9.9 (2001-02-14) [umoeller]
    740743         && (ulFirstReplOfs + cReplLen <= pxstr->ulLength)
    741          && (pstrReplaceWith)
    742          // && (pstrReplaceWith->ulLength)      no, this can be empty
     744         && (pcszReplaceWith)
    743745       )
    744746    {
    745         ULONG   cReplaceLen = pstrReplaceWith->ulLength;
    746                     // can be 0!
    747 
    748747        // size of new buffer:
    749         ULONG   cbNeeded = pxstr->ulLength
    750                          + cReplaceLen
    751                          - cReplLen
    752                          + 1;                  // null terminator
     748        ULONG   cbNeeded = pxstr->ulLength      // existing
     749                         + cReplaceWithLen      // plus replacement string length
     750                         - cReplLen             // minus replaced characters
     751                         + 1;                   // plus null terminator
    753752        // offset where pszSearch was found
    754753        PSZ     pFound = pxstr->psz + ulFirstReplOfs;
     
    791790                       ulFirstReplOfs);     // up to "found"
    792791
    793             if (cReplaceLen)
     792            if (cReplaceWithLen)
    794793            {
    795794                // we have a replacement:
    796795                // insert it next
     796
     797                /* memcpy(pszNew + ulFirstReplOfs,
     798                       pstrReplaceWith->psz,
     799                       cReplaceWithLen + 1);        // include null terminator
     800                */
     801                // no, we no longer can be sure that pcszReplaceWith is
     802                // null terminated, so terminate explicitly
     803                // V0.9.11 (2001-04-22) [umoeller]
     804
    797805                memcpy(pszNew + ulFirstReplOfs,
    798                        pstrReplaceWith->psz,
    799                        cReplaceLen + 1);        // include null terminator
     806                       pcszReplaceWith,
     807                       cReplaceWithLen);
     808                *(pszNew + ulFirstReplOfs + cReplaceWithLen) = '\0';
    800809            }
    801810
     
    810819            //            ³            ³
    811820            //            pxstr->ulLength = 14
    812             memcpy(pszNew + ulFirstReplOfs + cReplaceLen,
     821            memcpy(pszNew + ulFirstReplOfs + cReplaceWithLen,
    813822                   pFound + cReplLen,
    814823                   // remaining bytes:
     
    833842            // first, we move the end to its new location
    834843            // (memmove handles overlap if needed)
    835             memmove(pFound + cReplaceLen,
     844            memmove(pFound + cReplaceWithLen,
    836845                    pFound + cReplLen,
    837846                    cTailLength + 1); // including null terminator
    838847
    839848            // now overwrite "found" in the middle
    840             if (cReplaceLen)
     849            if (cReplaceWithLen)
    841850            {
    842851                memcpy(pFound,
    843                        pstrReplaceWith->psz,
    844                        cReplaceLen);        // no null terminator
     852                       pcszReplaceWith,
     853                       cReplaceWithLen);        // no null terminator
    845854            }
    846855
     
    10321041                               ulFirstReplOfs,              // where to start
    10331042                               cSearchLen,                  // chars to replace
    1034                                pstrReplace);
     1043                               pstrReplace->psz,
     1044                               pstrReplace->ulLength);      // adjusted V0.9.11 (2001-04-22) [umoeller]
    10351045
    10361046                // return new length
Note: See TracChangeset for help on using the changeset viewer.