Annotation of libwww/Library/src/HTAnchor.c, revision 1.17

1.14      frystyk     1: /*                                                                  HTAnchor.c
                      2: **     HYPERTEXT "ANCHOR" OBJECT
1.1       timbl       3: **
1.14      frystyk     4: **     (c) COPYRIGHT CERN 1994.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
                      6: **
                      7: **     An anchor represents a region of a hypertext document which is
                      8: **     linked to another anchor in the same or a different document.
1.1       timbl       9: **
                     10: ** History
                     11: **         Nov 1990  Written in Objective-C for the NeXT browser (TBL)
                     12: **     24-Oct-1991 (JFG), written in C, browser-independant 
                     13: **     21-Nov-1991 (JFG), first complete version
1.17    ! frystyk    14: **      3-May-1995 (HF), Added a lot of methods and other stuff
1.1       timbl      15: */
                     16: 
1.16      frystyk    17: /* Library include files */
                     18: #include "tcp.h"
                     19: #include "HTUtils.h"
                     20: #include "HTString.h"
1.7       luotonen   21: #include "HTFormat.h"
1.1       timbl      22: #include "HTParse.h"
1.16      frystyk    23: #include "HTFWrite.h"                                    /* for cache stuff */
1.11      frystyk    24: #include "HTAnchor.h"                                   /* Implemented here */
                     25: 
                     26: #define HASH_SIZE 101          /* Arbitrary prime. Memory/speed tradeoff */
1.1       timbl      27: 
                     28: typedef struct _HyperDoc Hyperdoc;
1.16      frystyk    29: #ifdef VMS
1.1       timbl      30: struct _HyperDoc {
1.16      frystyk    31:        int junk;       /* VMS cannot handle pointers to undefined structs */
1.1       timbl      32: };
                     33: #endif
                     34: 
                     35: PRIVATE HTList **adult_table=0;  /* Point to table of lists of all parents */
                     36: 
1.17    ! frystyk    37: /* ------------------------------------------------------------------------- */
        !            38: /*                             Creation Methods                             */
        !            39: /* ------------------------------------------------------------------------- */
        !            40: 
        !            41: /*
1.1       timbl      42: **     Do not use "new" by itself outside this module. In order to enforce
                     43: **     consistency, we insist that you furnish more information about the
                     44: **     anchor you are creating : use newWithParent or newWithAddress.
                     45: */
1.16      frystyk    46: PRIVATE HTParentAnchor * HTParentAnchor_new NOARGS
1.1       timbl      47: {
1.16      frystyk    48:     HTParentAnchor *newAnchor =
                     49:        (HTParentAnchor *) calloc(1, sizeof (HTParentAnchor));
                     50:     newAnchor->parent = newAnchor;
1.17    ! frystyk    51:     newAnchor->content_type = WWW_UNKNOWN;
        !            52:     newAnchor->level = HTML_INVALID;
1.16      frystyk    53:     return newAnchor;
1.1       timbl      54: }
                     55: 
1.16      frystyk    56: 
                     57: PRIVATE HTChildAnchor * HTChildAnchor_new NOARGS
1.1       timbl      58: {
1.16      frystyk    59:     return (HTChildAnchor *) calloc (1, sizeof (HTChildAnchor));
1.1       timbl      60: }
                     61: 
                     62: 
1.17    ! frystyk    63: /*     Create new or find old child anchor
        !            64: **     -----------------------------------
1.1       timbl      65: **
1.3       timbl      66: **     Me one is for a new anchor being edited into an existing
1.17    ! frystyk    67: **     document. The parent anchor must already exist. All
        !            68: **     children without tags (no NAME attribut) points to the same NULL
        !            69: **     child.
1.1       timbl      70: */
1.17    ! frystyk    71: PUBLIC HTChildAnchor * HTAnchor_findChild ARGS2 (HTParentAnchor *, parent,
        !            72:                                                 CONST char *,tag)
1.1       timbl      73: {
1.17    ! frystyk    74:     HTChildAnchor *child;
        !            75:     HTList *kids;
        !            76:     
        !            77:     if (!parent) {
        !            78:        if (ANCH_TRACE)
        !            79:            fprintf(TDEST, "Find Child.. called with NULL parent.\n");
        !            80:        return NULL;
        !            81:     }
1.1       timbl      82: 
1.17    ! frystyk    83:     /* First search list of children to see if tag is already there */
        !            84:     if ((kids = parent->children)) {
        !            85:        if (tag && *tag) {      /* TBL */
        !            86:            while ((child = (HTChildAnchor *) HTList_nextObject(kids))) {
        !            87:                if (!(child->tag && strcasecomp(child->tag, tag))) {
        !            88:                    if (ANCH_TRACE)
        !            89:                        fprintf (TDEST,
        !            90:                                 "Find Child.. %p of parent %p with name `%s' already exists.\n",
        !            91:                                 (void *) child, (void *) parent, tag);
        !            92:                    return child;
        !            93:                }
1.1       timbl      94:            }
                     95:        }
1.17    ! frystyk    96:     } else                                   /* Create new list of children */
        !            97:        parent->children = HTList_new ();
        !            98:     
        !            99:     /* Did't find it so we need to create a new one */
        !           100:     child = HTChildAnchor_new();
        !           101:     HTList_addObject(parent->children, child);
        !           102:     child->parent = parent;
        !           103:     StrAllocCopy(child->tag, tag);
        !           104:     if (ANCH_TRACE)
        !           105:        fprintf(TDEST,"Find Child.. New Anchor %p named `%s' is child of %p\n",
        !           106:                (void *) child, tag ? tag : (CONST char *) "", (void *)parent);
        !           107:     return child;
1.1       timbl     108: }
                    109: 
                    110: 
                    111: /*     Create new or find old named anchor
                    112: **     -----------------------------------
                    113: **
1.3       timbl     114: **     Me one is for a reference which is found in a document, and might
1.1       timbl     115: **     not be already loaded.
                    116: **     Note: You are not guaranteed a new anchor -- you might get an old one,
                    117: **     like with fonts.
                    118: */
1.16      frystyk   119: PUBLIC HTAnchor * HTAnchor_findAddress ARGS1 (CONST char *, address)
1.1       timbl     120: {
1.16      frystyk   121:     char *tag = HTParse (address, "", PARSE_ANCHOR);           /* Any tags? */
                    122:     char *newaddr=NULL;
1.1       timbl     123:     
1.17    ! frystyk   124:     StrAllocCopy(newaddr, address);                     /* Get our own copy */
1.16      frystyk   125:     if (!HTImProxy)
                    126:        newaddr = HTSimplify(newaddr);       /* Proxy has already simplified */
                    127: 
                    128:     /* If the address represents a sub-anchor, we recursively load its parent,
                    129:        then we create a child anchor within that document. */
                    130:     if (*tag) {
                    131:        char *docAddress = HTParse(newaddr, "", PARSE_ACCESS | PARSE_HOST |
                    132:                                   PARSE_PATH | PARSE_PUNCTUATION);
                    133:        HTParentAnchor * foundParent =
                    134:            (HTParentAnchor *) HTAnchor_findAddress (docAddress);
                    135:        HTChildAnchor * foundAnchor = HTAnchor_findChild (foundParent, tag);
                    136:        free (docAddress);
                    137:        free (tag);
                    138:        return (HTAnchor *) foundAnchor;
                    139:     } else {                        /* Else check whether we have this node */
                    140:        int hash;
                    141:        CONST char *p;
                    142:        HTList * adults;
                    143:        HTList *grownups;
                    144:        HTParentAnchor * foundAnchor;
                    145:        free (tag);
                    146:        
                    147:        /* Select list from hash table */
                    148:        for(p=newaddr, hash=0; *p; p++)
                    149:            hash = (int) ((hash * 3 + (*(unsigned char*)p)) % HASH_SIZE);
                    150:        if (!adult_table)
                    151:            adult_table = (HTList**) calloc(HASH_SIZE, sizeof(HTList*));
                    152:        if (!adult_table[hash]) adult_table[hash] = HTList_new();
                    153:        adults = adult_table[hash];
                    154: 
                    155:        /* Search list for anchor */
                    156:        grownups = adults;
                    157:        while ((foundAnchor = (HTParentAnchor *) HTList_nextObject(grownups))){
1.17    ! frystyk   158:            if (!strcasecomp(foundAnchor->address, newaddr)) {
1.16      frystyk   159:                if (ANCH_TRACE)
1.17    ! frystyk   160:                    fprintf(TDEST, "Find Parent. %p with address `%s' already exists.\n",
1.16      frystyk   161:                            (void*) foundAnchor, newaddr);
                    162:                return (HTAnchor *) foundAnchor;
                    163:            }
                    164:        }
                    165:        
                    166:        /* Node not found : create new anchor. */
                    167:        foundAnchor = HTParentAnchor_new();
                    168:        foundAnchor->address = newaddr;                 /* Remember our copy */
                    169:        HTList_addObject (adults, foundAnchor);
1.17    ! frystyk   170:        if (ANCH_TRACE) fprintf(TDEST, "Find Parent. %p with hash %d and address `%s' created\n", (void*)foundAnchor, hash, newaddr);
1.1       timbl     171:        return (HTAnchor *) foundAnchor;
                    172:     }
                    173: }
                    174: 
1.17    ! frystyk   175: /* ------------------------------------------------------------------------- */
        !           176: /*                                Link Methods                              */
        !           177: /* ------------------------------------------------------------------------- */
        !           178: 
        !           179: /*     Create or find a child anchor with a possible link
        !           180: **     --------------------------------------------------
        !           181: **
        !           182: **     Create new anchor with a given parent and possibly
        !           183: **     a name, and possibly a link to a _relatively_ named anchor.
        !           184: **     (Code originally in ParseHTML.h)
        !           185: */
        !           186: PUBLIC HTChildAnchor * HTAnchor_findChildAndLink
        !           187:   ARGS4(
        !           188:        HTParentAnchor *,parent,        /* May not be 0 */
        !           189:        CONST char *,tag,       /* May be "" or 0 */
        !           190:        CONST char *,href,      /* May be "" or 0 */
        !           191:        HTLinkType *,ltype      /* May be 0 */
        !           192:        )
        !           193: {
        !           194:   HTChildAnchor * child = HTAnchor_findChild(parent, tag);
        !           195:   if (href && *href) {
        !           196:     char * relative_to = HTAnchor_address((HTAnchor *) parent);
        !           197:     char * parsed_address = HTParse(href, relative_to, PARSE_ALL);
        !           198:     HTAnchor * dest = HTAnchor_findAddress(parsed_address);
        !           199:     HTAnchor_link((HTAnchor *) child, dest, ltype);
        !           200:     free(parsed_address);
        !           201:     free(relative_to);
        !           202:   }
        !           203:   return child;
        !           204: }
        !           205: 
        !           206: /*     Link me Anchor to another given one
        !           207: **     -------------------------------------
        !           208: */
        !           209: PUBLIC BOOL HTAnchor_link ARGS3(HTAnchor *,   source,
        !           210:                                HTAnchor *,   destination, 
        !           211:                                HTLinkType *, type)
        !           212: {
        !           213:     if (!(source && destination))
        !           214:        return NO;              /* Can't link to/from non-existing anchor */
        !           215:     if (ANCH_TRACE)
        !           216:        fprintf(TDEST, "Link Anchors anchor %p to anchor %p\n",
        !           217:                (void *) source, (void *) destination);
        !           218:     if (!source->mainLink.dest) {
        !           219:        source->mainLink.dest = destination;
        !           220:        source->mainLink.type = type;
        !           221:     } else {
        !           222:        HTLink * newLink = (HTLink *) calloc(1, sizeof (HTLink));
        !           223:        if (newLink == NULL) outofmem(__FILE__, "HTAnchor_link");
        !           224:        newLink->dest = destination;
        !           225:        newLink->type = type;
        !           226:        if (! source->links)
        !           227:            source->links = HTList_new ();
        !           228:        HTList_addObject (source->links, newLink);
        !           229:     }
        !           230:     if (!destination->parent->sources)
        !           231:        destination->parent->sources = HTList_new ();
        !           232:     HTList_addObject (destination->parent->sources, source);
        !           233:     return YES;
        !           234: }
        !           235: 
        !           236: 
        !           237: /*     Manipulation of links
        !           238: **     ---------------------
        !           239: */
        !           240: 
        !           241: PUBLIC HTAnchor * HTAnchor_followMainLink
        !           242:   ARGS1 (HTAnchor *,me)
        !           243: {
        !           244:   return me->mainLink.dest;
        !           245: }
        !           246: 
        !           247: PUBLIC HTAnchor * HTAnchor_followTypedLink
        !           248:   ARGS2 (HTAnchor *,me, HTLinkType *,type)
        !           249: {
        !           250:   if (me->mainLink.type == type)
        !           251:     return me->mainLink.dest;
        !           252:   if (me->links) {
        !           253:     HTList *links = me->links;
        !           254:     HTLink *link;
        !           255:     while ((link = (HTLink *) HTList_nextObject (links)))
        !           256:       if (link->type == type)
        !           257:        return link->dest;
        !           258:   }
        !           259:   return NULL;  /* No link of me type */
        !           260: }
        !           261: 
        !           262: 
        !           263: /*     Make main link
        !           264: */
        !           265: PUBLIC BOOL HTAnchor_makeMainLink
        !           266:   ARGS2 (HTAnchor *,me, HTLink *,movingLink)
        !           267: {
        !           268:   /* Check that everything's OK */
        !           269:   if (! (me && HTList_removeObject (me->links, movingLink)))
        !           270:     return NO;  /* link not found or NULL anchor */
        !           271:   else {
        !           272:     /* First push current main link onto top of links list */
        !           273:     HTLink *newLink = (HTLink*) malloc (sizeof (HTLink));
        !           274:     if (newLink == NULL) outofmem(__FILE__, "HTAnchor_makeMainLink");
        !           275:     memcpy (newLink, & me->mainLink, sizeof (HTLink));
        !           276:     HTList_addObject (me->links, newLink);
        !           277: 
        !           278:     /* Now make movingLink the new main link, and free it */
        !           279:     memcpy (& me->mainLink, movingLink, sizeof (HTLink));
        !           280:     free (movingLink);
        !           281:     return YES;
        !           282:   }
        !           283: }
        !           284: 
        !           285: /*             Move an anchor to the head of the list of its siblings
        !           286: **             ------------------------------------------------------
        !           287: **
        !           288: **     This is to ensure that an anchor which might have already existed
        !           289: **     is put in the correct order as we load the document.
        !           290: */
        !           291: 
        !           292: PUBLIC void HTAnchor_makeLastChild
        !           293:   ARGS1(HTChildAnchor *,me)
        !           294: {
        !           295:   if (me->parent != (HTParentAnchor *) me) {  /* Make sure it's a child */
        !           296:     HTList * siblings = me->parent->children;
        !           297:     HTList_removeObject (siblings, me);
        !           298:     HTList_addObject (siblings, me);
        !           299:   }
        !           300: }
        !           301: 
        !           302: /* ------------------------------------------------------------------------- */
        !           303: /*                             Deletion Methods                             */
        !           304: /* ------------------------------------------------------------------------- */
1.1       timbl     305: 
                    306: /*     Delete an anchor and possibly related things (auto garbage collection)
                    307: **     --------------------------------------------
                    308: **
                    309: **     The anchor is only deleted if the corresponding document is not loaded.
1.10      frystyk   310: **     All outgoing links from parent and children are deleted, and this
                    311: **     anchor is removed from the sources list of all its targets.
1.1       timbl     312: **     We also try to delete the targets whose documents are not loaded.
                    313: **     If this anchor's source list is empty, we delete it and its children.
                    314: */
                    315: 
                    316: PRIVATE void deleteLinks
1.3       timbl     317:   ARGS1 (HTAnchor *,me)
1.1       timbl     318: {
1.3       timbl     319:   if (! me)
1.1       timbl     320:     return;
                    321: 
                    322:   /* Recursively try to delete target anchors */
1.3       timbl     323:   if (me->mainLink.dest) {
                    324:     HTParentAnchor *parent = me->mainLink.dest->parent;
                    325:     HTList_removeObject (parent->sources, me);
1.1       timbl     326:     if (! parent->document)  /* Test here to avoid calling overhead */
                    327:       HTAnchor_delete (parent);
                    328:   }
1.3       timbl     329:   if (me->links) {  /* Extra destinations */
1.1       timbl     330:     HTLink *target;
1.12      frystyk   331:     while ((target = (HTLink *) HTList_removeLastObject (me->links))) {
1.1       timbl     332:       HTParentAnchor *parent = target->dest->parent;
1.3       timbl     333:       HTList_removeObject (parent->sources, me);
1.1       timbl     334:       if (! parent->document)  /* Test here to avoid calling overhead */
                    335:        HTAnchor_delete (parent);
                    336:     }
                    337:   }
                    338: }
                    339: 
                    340: PUBLIC BOOL HTAnchor_delete
1.3       timbl     341:   ARGS1 (HTParentAnchor *,me)
1.1       timbl     342: {
                    343:   HTChildAnchor *child;
                    344: 
                    345:   /* Don't delete if document is loaded */
1.3       timbl     346:   if (me->document)
1.1       timbl     347:     return NO;
                    348: 
                    349:   /* Recursively try to delete target anchors */
1.3       timbl     350:   deleteLinks ((HTAnchor *) me);
1.1       timbl     351: 
1.3       timbl     352:   if (! HTList_isEmpty (me->sources)) {  /* There are still incoming links */
1.1       timbl     353:     /* Delete all outgoing links from children, if any */
1.3       timbl     354:     HTList *kids = me->children;
1.12      frystyk   355:     while ((child = (HTChildAnchor *) HTList_nextObject (kids)))
1.1       timbl     356:       deleteLinks ((HTAnchor *) child);
                    357:     return NO;  /* Parent not deleted */
                    358:   }
                    359: 
                    360:   /* No more incoming links : kill everything */
                    361:   /* First, recursively delete children */
1.12      frystyk   362:   while ((child = (HTChildAnchor *) HTList_removeLastObject (me->children))) {
1.1       timbl     363:     deleteLinks ((HTAnchor *) child);
                    364:     free (child->tag);
                    365:     free (child);
                    366:   }
                    367: 
                    368:   /* Now kill myself */
1.3       timbl     369:   HTList_delete (me->children);
                    370:   HTList_delete (me->sources);
                    371:   free (me->address);
1.1       timbl     372:   /* Devise a way to clean out the HTFormat if no longer needed (ref count?) */
1.3       timbl     373:   free (me);
1.6       timbl     374:   if (me->cacheItems) {
                    375:       HTCacheClear(me->cacheItems);
                    376:   }
1.1       timbl     377:   return YES;  /* Parent deleted */
                    378: }
                    379: 
1.17    ! frystyk   380: /* ------------------------------------------------------------------------- */
        !           381: /*                             Data Access Methods                          */
        !           382: /* ------------------------------------------------------------------------- */
1.1       timbl     383: 
1.17    ! frystyk   384: PUBLIC HTParentAnchor * HTAnchor_parent ARGS1 (HTAnchor *,me)
1.1       timbl     385: {
1.17    ! frystyk   386:     return me ? me->parent : NULL;
1.1       timbl     387: }
                    388: 
1.17    ! frystyk   389: PUBLIC void HTAnchor_setDocument ARGS2 (HTParentAnchor *, me, HyperDoc *,doc)
1.1       timbl     390: {
1.17    ! frystyk   391:     if (me)
        !           392:        me->document = doc;
1.1       timbl     393: }
                    394: 
1.17    ! frystyk   395: PUBLIC HyperDoc * HTAnchor_document ARGS1 (HTParentAnchor *,me)
1.1       timbl     396: {
1.17    ! frystyk   397:     return me ? me->document : NULL;
1.1       timbl     398: }
                    399: 
                    400: 
1.10      frystyk   401: #if 0
1.17    ! frystyk   402: /* We might want to use this when we have a link editing application */
1.10      frystyk   403: PUBLIC void HTAnchor_setAddress
1.3       timbl     404:   ARGS2 (HTAnchor *,me, char *,addr)
1.1       timbl     405: {
1.3       timbl     406:   if (me)
                    407:     StrAllocCopy (me->parent->address, addr);
1.1       timbl     408: }
1.10      frystyk   409: #endif
                    410: 
1.17    ! frystyk   411: PUBLIC char * HTAnchor_address ARGS1 (HTAnchor *, me)
1.1       timbl     412: {
1.17    ! frystyk   413:     char *addr = NULL;
        !           414:     if (me) {
        !           415:        if (((HTParentAnchor *) me == me->parent) ||
        !           416:            !((HTChildAnchor *) me)->tag) { /* it's an adult or no tag */
        !           417:            StrAllocCopy (addr, me->parent->address);
        !           418:        }
        !           419:        else {                  /* it's a named child */
        !           420:            addr = (char *) malloc (2 + strlen (me->parent->address)
        !           421:                                    + strlen (((HTChildAnchor *) me)->tag));
        !           422:            if (addr == NULL) outofmem(__FILE__, "HTAnchor_address");
        !           423:            sprintf (addr, "%s#%s", me->parent->address,
        !           424:                     ((HTChildAnchor *) me)->tag);
        !           425:        }
1.1       timbl     426:     }
1.17    ! frystyk   427:     return addr;
1.1       timbl     428: }
                    429: 
1.17    ! frystyk   430: PUBLIC BOOL HTAnchor_hasChildren ARGS1 (HTParentAnchor *,me)
        !           431: {
        !           432:     return me ? ! HTList_isEmpty(me->children) : NO;
        !           433: }
1.1       timbl     434: 
1.17    ! frystyk   435: PUBLIC void HTAnchor_clearIndex ARGS1 (HTParentAnchor *,me)
        !           436: {
        !           437:     if (me)
        !           438:        me->isIndex = NO;
        !           439: }
1.1       timbl     440: 
1.17    ! frystyk   441: PUBLIC void HTAnchor_setIndex ARGS1 (HTParentAnchor *,me)
1.1       timbl     442: {
1.3       timbl     443:   if (me)
1.17    ! frystyk   444:     me->isIndex = YES;
        !           445: }
        !           446: 
        !           447: PUBLIC BOOL HTAnchor_isIndex ARGS1 (HTParentAnchor *,me)
        !           448: {
        !           449:     return me ? me->isIndex : NO;
1.1       timbl     450: }
                    451: 
1.17    ! frystyk   452: /*     Protocol
        !           453: **     --------
        !           454: */
        !           455: 
        !           456: PUBLIC void * HTAnchor_protocol ARGS1(HTParentAnchor *, me)
1.1       timbl     457: {
1.17    ! frystyk   458:     return me->protocol;
1.1       timbl     459: }
                    460: 
1.17    ! frystyk   461: PUBLIC void HTAnchor_setProtocol ARGS2(HTParentAnchor *, me,
        !           462:        void*,  protocol)
1.9       frystyk   463: {
1.17    ! frystyk   464:     me->protocol = protocol;
1.9       frystyk   465: }
1.1       timbl     466: 
1.17    ! frystyk   467: /*     Physical Address
        !           468: **     ----------------
        !           469: */
        !           470: 
        !           471: PUBLIC char * HTAnchor_physical ARGS1(HTParentAnchor *, me)
1.1       timbl     472: {
1.17    ! frystyk   473:     return me->physical;
1.1       timbl     474: }
                    475: 
1.17    ! frystyk   476: PUBLIC void HTAnchor_setPhysical ARGS2(HTParentAnchor *, me,
        !           477:        char *, physical)
1.1       timbl     478: {
1.17    ! frystyk   479:     if (!me || !physical) {
        !           480:        if (ANCH_TRACE)
        !           481:            fprintf(TDEST, "HTAnchor.... setPhysical, called with null argument\n");
        !           482:        return;
        !           483:     }
        !           484:     StrAllocCopy(me->physical, physical);
1.1       timbl     485: }
                    486: 
1.17    ! frystyk   487: /* ------------------------------------------------------------------------- */
        !           488: /*                           Entity Header Information                      */
        !           489: /* ------------------------------------------------------------------------- */
        !           490: 
        !           491: /*
        !           492: **     Media Types (Content-Type)
        !           493: */
        !           494: PUBLIC HTFormat HTAnchor_format ARGS1(HTParentAnchor *,me)
        !           495: {
        !           496:     return me ? me->content_type : NULL;
        !           497: }
1.1       timbl     498: 
1.17    ! frystyk   499: PUBLIC void HTAnchor_setFormat ARGS2(HTParentAnchor *,me, HTFormat, form)
1.1       timbl     500: {
1.17    ! frystyk   501:     if (me) me->content_type = form;
1.1       timbl     502: }
                    503: 
1.17    ! frystyk   504: /*
        !           505: **     Charset parameter to Content-Type
1.1       timbl     506: */
1.17    ! frystyk   507: PUBLIC HTCharset HTAnchor_charset ARGS1(HTParentAnchor *, me)
1.1       timbl     508: {
1.17    ! frystyk   509:     return me ? me->charset : NULL;
1.1       timbl     510: }
                    511: 
1.17    ! frystyk   512: PUBLIC void HTAnchor_setCharset ARGS2(HTParentAnchor *,me, HTCharset, charset)
1.1       timbl     513: {
1.17    ! frystyk   514:     if (me) me->charset = charset;
1.1       timbl     515: }
                    516: 
1.17    ! frystyk   517: /*
        !           518: **     Content Encoding
        !           519: */
        !           520: PUBLIC HTEncoding HTAnchor_encoding ARGS1(HTParentAnchor *,me)
1.1       timbl     521: {
1.17    ! frystyk   522:     return me ? me->content_encoding : NULL;
1.1       timbl     523: }
                    524: 
1.17    ! frystyk   525: PUBLIC void HTAnchor_setEncoding ARGS2(HTParentAnchor *,me,    
        !           526:                                       HTEncoding, encoding)
        !           527: {
        !           528:     if (me) me->content_encoding = encoding;
        !           529: }
        !           530: 
        !           531: /*
        !           532: **     Content Transfer Encoding
1.1       timbl     533: */
1.17    ! frystyk   534: PUBLIC HTCte HTAnchor_cte ARGS1(HTParentAnchor *,me)
        !           535: {
        !           536:     return me ? me->cte : NULL;
        !           537: }
1.1       timbl     538: 
1.17    ! frystyk   539: PUBLIC void HTAnchor_setCte ARGS2(HTParentAnchor *,me, HTCte, cte)
        !           540: {
        !           541:     if (me) me->cte = cte;
        !           542: }
        !           543: 
        !           544: /*
        !           545: **     Content Length
        !           546: */
        !           547: PUBLIC long int HTAnchor_length ARGS1(HTParentAnchor *,me)
1.1       timbl     548: {
1.17    ! frystyk   549:     return me ? me->content_length : -1;
1.1       timbl     550: }
                    551: 
1.17    ! frystyk   552: PUBLIC void HTAnchor_setLength ARGS2(HTParentAnchor *,me, long int, length)
        !           553: {
        !           554:     if (me) me->content_length = length;
        !           555: }
1.1       timbl     556: 
1.17    ! frystyk   557: /*
        !           558: **     Allowed methods (Allow)
1.1       timbl     559: */
1.17    ! frystyk   560: PUBLIC int HTAnchor_methods ARGS1(HTParentAnchor *, me)
        !           561: {
        !           562:     return me ? me->methods : 0;
        !           563: }
1.1       timbl     564: 
1.17    ! frystyk   565: PUBLIC void HTAnchor_setMethods ARGS2(HTParentAnchor *,me, int, methodset)
1.1       timbl     566: {
1.17    ! frystyk   567:     if (me) me->methods = methodset;
1.1       timbl     568: }
                    569: 
1.17    ! frystyk   570: PUBLIC void HTAnchor_appendMethods ARGS2(HTParentAnchor *,me, int, methodset)
1.1       timbl     571: {
1.17    ! frystyk   572:     if (me) me->methods += methodset;
1.1       timbl     573: }
                    574: 
1.17    ! frystyk   575: /*
        !           576: **     Title
1.2       timbl     577: */
1.17    ! frystyk   578: PUBLIC CONST char * HTAnchor_title ARGS1 (HTParentAnchor *,me)
1.1       timbl     579: {
1.17    ! frystyk   580:     return me ? me->title : NULL;
        !           581: }
1.1       timbl     582: 
1.17    ! frystyk   583: PUBLIC void HTAnchor_setTitle ARGS2(HTParentAnchor *,me, CONST char *, title)
        !           584: {
        !           585:     if (me && title) StrAllocCopy(me->title, title);
1.2       timbl     586: }
                    587: 
1.17    ! frystyk   588: PUBLIC void HTAnchor_appendTitle ARGS2(HTParentAnchor *,me, CONST char *,title)
        !           589: {
        !           590:     if (me && title) StrAllocCat(me->title, title);
        !           591: }
1.2       timbl     592: 
1.17    ! frystyk   593: /*
        !           594: **     Version
1.2       timbl     595: */
1.17    ! frystyk   596: PUBLIC CONST char * HTAnchor_version ARGS1 (HTParentAnchor *,me)
        !           597: {
        !           598:     return me ? me->version : NULL;
        !           599: }
1.2       timbl     600: 
1.17    ! frystyk   601: PUBLIC void HTAnchor_setVersion ARGS2(HTParentAnchor *, me,
        !           602:                                      CONST char *, version)
1.2       timbl     603: {
1.17    ! frystyk   604:     if (me && version) StrAllocCopy(me->version, version);
1.2       timbl     605: }
                    606: 
1.17    ! frystyk   607: /*
        !           608: **     Derived from
1.2       timbl     609: */
1.17    ! frystyk   610: PUBLIC CONST char * HTAnchor_derived ARGS1 (HTParentAnchor *,me)
        !           611: {
        !           612:     return me ? me->derived_from : NULL;
        !           613: }
        !           614: 
        !           615: PUBLIC void HTAnchor_setDerived ARGS2(HTParentAnchor *, me,
        !           616:                                      CONST char *, derived_from)
        !           617: {
        !           618:     if (me && derived_from) StrAllocCopy(me->derived_from, derived_from);
        !           619: }
1.2       timbl     620: 
1.17    ! frystyk   621: /*
        !           622: **     Extra Header List of unknown headers
        !           623: */
        !           624: PUBLIC HTList * HTAnchor_Extra ARGS1 (HTParentAnchor *, me)
1.2       timbl     625: {
1.17    ! frystyk   626:     return me ? me->extra_headers : NULL;
1.2       timbl     627: }
                    628: 
1.17    ! frystyk   629: PUBLIC void HTAnchor_addExtra ARGS2(HTParentAnchor *, me,
        !           630:                                    CONST char *    , header)
1.2       timbl     631: {
1.17    ! frystyk   632:     if (me) {
        !           633:        if (!me->extra_headers)
        !           634:            me->extra_headers = HTList_new();
        !           635:        HTList_addObject(me->extra_headers, (void *) header);
        !           636:     }
1.2       timbl     637: }
                    638: 
1.17    ! frystyk   639: /*     Has header been parsed?
        !           640: **     -----------------------
1.2       timbl     641: */
1.17    ! frystyk   642: PUBLIC BOOL HTAnchor_headerParsed ARGS1(HTParentAnchor *, me)
1.2       timbl     643: {
1.17    ! frystyk   644:     return (me ? me->header_parsed : NO);
1.2       timbl     645: }
                    646: 
1.17    ! frystyk   647: /*     Clear Header Information
        !           648: **     ------------------------
        !           649: */
        !           650: PUBLIC void HTAnchor_clearHeader ARGS1(HTParentAnchor *, me)
1.2       timbl     651: {
1.17    ! frystyk   652:     if (me->header) {
        !           653:        HTChunkFree(me->header);
        !           654:        me->derived_from = NULL;
        !           655:        me->version = NULL;
        !           656:        me->header = NULL;
        !           657:     } else {
        !           658:        FREE(me->version);
        !           659:        FREE(me->derived_from);
        !           660:     }
        !           661:     me->methods = METHOD_INVALID;
        !           662:     me->content_encoding = NULL;
        !           663:     if (me->content_language) {
        !           664:        HTList_delete(me->content_language);
        !           665:        me->content_language = HTList_new();
1.9       frystyk   666:     }
1.17    ! frystyk   667:     me->content_length = -1;                                     /* Invalid */
        !           668:     me->cte = NULL;
        !           669:     me->content_type = WWW_UNKNOWN;
        !           670:     me->charset = NULL;
        !           671:     me->level = HTML_INVALID;
        !           672:     
        !           673:     me->date = (time_t) 0;
        !           674:     me->expires = (time_t) 0;
        !           675:     me->last_modified = (time_t) 0;
        !           676:     
        !           677:     me->header_parsed = NO;                                  /* All cleared */
1.1       timbl     678: }

Webmaster