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

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
                     14: **
                     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: 
                     37: /*                             Creation Methods
                     38: **                             ================
                     39: **
                     40: **     Do not use "new" by itself outside this module. In order to enforce
                     41: **     consistency, we insist that you furnish more information about the
                     42: **     anchor you are creating : use newWithParent or newWithAddress.
                     43: */
1.16    ! frystyk    44: PRIVATE HTParentAnchor * HTParentAnchor_new NOARGS
1.1       timbl      45: {
1.16    ! frystyk    46:     HTParentAnchor *newAnchor =
        !            47:        (HTParentAnchor *) calloc(1, sizeof (HTParentAnchor));
        !            48:     newAnchor->parent = newAnchor;
        !            49:     return newAnchor;
1.1       timbl      50: }
                     51: 
1.16    ! frystyk    52: 
        !            53: PRIVATE HTChildAnchor * HTChildAnchor_new NOARGS
1.1       timbl      54: {
1.16    ! frystyk    55:     return (HTChildAnchor *) calloc (1, sizeof (HTChildAnchor));
1.1       timbl      56: }
                     57: 
                     58: 
                     59: /*     Case insensitive string comparison
                     60: **     ----------------------------------
                     61: ** On entry,
                     62: **     s       Points to one string, null terminated
                     63: **     t       points to the other.
                     64: ** On exit,
                     65: **     returns YES if the strings are equivalent ignoring case
                     66: **             NO if they differ in more than  their case.
                     67: */
                     68: 
                     69: PRIVATE BOOL equivalent
                     70:   ARGS2 (CONST char *,s, CONST char *,t)
                     71: {
                     72:   if (s && t) {  /* Make sure they point to something */
                     73:     for ( ; *s && *t ; s++, t++) {
                     74:         if (TOUPPER(*s) != TOUPPER(*t))
                     75:          return NO;
                     76:     }
                     77:     return TOUPPER(*s) == TOUPPER(*t);
                     78:   } else
                     79:     return s == t;  /* Two NULLs are equivalent, aren't they ? */
                     80: }
                     81: 
                     82: 
                     83: /*     Create new or find old sub-anchor
                     84: **     ---------------------------------
                     85: **
1.3       timbl      86: **     Me one is for a new anchor being edited into an existing
1.1       timbl      87: **     document. The parent anchor must already exist.
                     88: */
                     89: 
1.2       timbl      90: PUBLIC HTChildAnchor * HTAnchor_findChild
1.1       timbl      91:   ARGS2 (HTParentAnchor *,parent, CONST char *,tag)
                     92: {
                     93:   HTChildAnchor *child;
                     94:   HTList *kids;
                     95: 
                     96:   if (! parent) {
1.11      frystyk    97:     if (ANCH_TRACE)
1.16    ! frystyk    98:        fprintf(TDEST, "HTAnchor_findChild called with NULL parent.\n");
1.1       timbl      99:     return NULL;
                    100:   }
1.7       luotonen  101:   if ((kids = parent->children)) {  /* parent has children : search them */
1.1       timbl     102:     if (tag && *tag) {         /* TBL */
1.12      frystyk   103:        while ((child = (HTChildAnchor *) HTList_nextObject (kids))) {
1.1       timbl     104:            if (equivalent(child->tag, tag)) { /* Case sensitive 920226 */
1.16    ! frystyk   105:                if (ANCH_TRACE) fprintf (TDEST,
1.11      frystyk   106:               "AnchorChild. %p of parent %p with name `%s' already exists.\n",
1.4       timbl     107:                    (void*)child, (void*)parent, tag);
1.1       timbl     108:                return child;
                    109:            }
                    110:        }
                    111:      }  /*  end if tag is void */
                    112:   } else  /* parent doesn't have any children yet : create family */
                    113:     parent->children = HTList_new ();
                    114: 
                    115:   child = HTChildAnchor_new ();
1.13      frystyk   116:   /* int for apollo */
                    117:   if (ANCH_TRACE)
1.16    ! frystyk   118:       fprintf(TDEST, "AnchorChild. New Anchor %p named `%s' is child of %p\n",
1.13      frystyk   119:              (void *) child, tag ? tag : (CONST char *) "", (void *) parent);
1.1       timbl     120:   HTList_addObject (parent->children, child);
                    121:   child->parent = parent;
                    122:   StrAllocCopy(child->tag, tag);
                    123:   return child;
                    124: }
                    125: 
                    126: 
                    127: /*     Create or find a child anchor with a possible link
                    128: **     --------------------------------------------------
                    129: **
                    130: **     Create new anchor with a given parent and possibly
                    131: **     a name, and possibly a link to a _relatively_ named anchor.
                    132: **     (Code originally in ParseHTML.h)
                    133: */
                    134: PUBLIC HTChildAnchor * HTAnchor_findChildAndLink
                    135:   ARGS4(
                    136:        HTParentAnchor *,parent,        /* May not be 0 */
                    137:        CONST char *,tag,       /* May be "" or 0 */
                    138:        CONST char *,href,      /* May be "" or 0 */
                    139:        HTLinkType *,ltype      /* May be 0 */
                    140:        )
                    141: {
                    142:   HTChildAnchor * child = HTAnchor_findChild(parent, tag);
                    143:   if (href && *href) {
1.2       timbl     144:     char * relative_to = HTAnchor_address((HTAnchor *) parent);
                    145:     char * parsed_address = HTParse(href, relative_to, PARSE_ALL);
                    146:     HTAnchor * dest = HTAnchor_findAddress(parsed_address);
1.1       timbl     147:     HTAnchor_link((HTAnchor *) child, dest, ltype);
                    148:     free(parsed_address);
1.2       timbl     149:     free(relative_to);
1.1       timbl     150:   }
                    151:   return child;
                    152: }
                    153: 
                    154: 
                    155: /*     Create new or find old named anchor
                    156: **     -----------------------------------
                    157: **
1.3       timbl     158: **     Me one is for a reference which is found in a document, and might
1.1       timbl     159: **     not be already loaded.
                    160: **     Note: You are not guaranteed a new anchor -- you might get an old one,
                    161: **     like with fonts.
                    162: */
                    163: 
1.16    ! frystyk   164: PUBLIC HTAnchor * HTAnchor_findAddress ARGS1 (CONST char *, address)
1.1       timbl     165: {
1.16    ! frystyk   166:     char *tag = HTParse (address, "", PARSE_ANCHOR);           /* Any tags? */
        !           167:     char *newaddr=NULL;
1.1       timbl     168:     
1.16    ! frystyk   169:     StrAllocCopy(newaddr, address);                   /* Get a working copy */
        !           170:     if (!HTImProxy)
        !           171:        newaddr = HTSimplify(newaddr);       /* Proxy has already simplified */
        !           172: 
        !           173:     /* If the address represents a sub-anchor, we recursively load its parent,
        !           174:        then we create a child anchor within that document. */
        !           175:     if (*tag) {
        !           176:        char *docAddress = HTParse(newaddr, "", PARSE_ACCESS | PARSE_HOST |
        !           177:                                   PARSE_PATH | PARSE_PUNCTUATION);
        !           178:        HTParentAnchor * foundParent =
        !           179:            (HTParentAnchor *) HTAnchor_findAddress (docAddress);
        !           180:        HTChildAnchor * foundAnchor = HTAnchor_findChild (foundParent, tag);
        !           181:        free (docAddress);
        !           182:        free (tag);
        !           183:        return (HTAnchor *) foundAnchor;
        !           184:     } else {                        /* Else check whether we have this node */
        !           185:        int hash;
        !           186:        CONST char *p;
        !           187:        HTList * adults;
        !           188:        HTList *grownups;
        !           189:        HTParentAnchor * foundAnchor;
        !           190:        free (tag);
        !           191:        
        !           192:        /* Select list from hash table */
        !           193:        for(p=newaddr, hash=0; *p; p++)
        !           194:            hash = (int) ((hash * 3 + (*(unsigned char*)p)) % HASH_SIZE);
        !           195:        if (!adult_table)
        !           196:            adult_table = (HTList**) calloc(HASH_SIZE, sizeof(HTList*));
        !           197:        if (!adult_table[hash]) adult_table[hash] = HTList_new();
        !           198:        adults = adult_table[hash];
        !           199: 
        !           200:        /* Search list for anchor */
        !           201:        grownups = adults;
        !           202:        while ((foundAnchor = (HTParentAnchor *) HTList_nextObject(grownups))){
        !           203:            if (equivalent(foundAnchor->address, newaddr)) {
        !           204:                if (ANCH_TRACE)
        !           205:                    fprintf(TDEST, "FindAnchor.. %p with address `%s' already exists.\n",
        !           206:                            (void*) foundAnchor, newaddr);
        !           207:                return (HTAnchor *) foundAnchor;
        !           208:            }
        !           209:        }
        !           210:        
        !           211:        /* Node not found : create new anchor. */
        !           212:        foundAnchor = HTParentAnchor_new();
        !           213:        if (ANCH_TRACE) fprintf(TDEST, "FindAnchor.. %p with hash %d and address `%s' created\n", (void*)foundAnchor, hash, newaddr);
        !           214:        foundAnchor->address = newaddr;                 /* Remember our copy */
        !           215:        HTList_addObject (adults, foundAnchor);
1.1       timbl     216:        return (HTAnchor *) foundAnchor;
                    217:     }
                    218: }
                    219: 
                    220: 
                    221: /*     Delete an anchor and possibly related things (auto garbage collection)
                    222: **     --------------------------------------------
                    223: **
                    224: **     The anchor is only deleted if the corresponding document is not loaded.
1.10      frystyk   225: **     All outgoing links from parent and children are deleted, and this
                    226: **     anchor is removed from the sources list of all its targets.
1.1       timbl     227: **     We also try to delete the targets whose documents are not loaded.
                    228: **     If this anchor's source list is empty, we delete it and its children.
                    229: */
                    230: 
                    231: PRIVATE void deleteLinks
1.3       timbl     232:   ARGS1 (HTAnchor *,me)
1.1       timbl     233: {
1.3       timbl     234:   if (! me)
1.1       timbl     235:     return;
                    236: 
                    237:   /* Recursively try to delete target anchors */
1.3       timbl     238:   if (me->mainLink.dest) {
                    239:     HTParentAnchor *parent = me->mainLink.dest->parent;
                    240:     HTList_removeObject (parent->sources, me);
1.1       timbl     241:     if (! parent->document)  /* Test here to avoid calling overhead */
                    242:       HTAnchor_delete (parent);
                    243:   }
1.3       timbl     244:   if (me->links) {  /* Extra destinations */
1.1       timbl     245:     HTLink *target;
1.12      frystyk   246:     while ((target = (HTLink *) HTList_removeLastObject (me->links))) {
1.1       timbl     247:       HTParentAnchor *parent = target->dest->parent;
1.3       timbl     248:       HTList_removeObject (parent->sources, me);
1.1       timbl     249:       if (! parent->document)  /* Test here to avoid calling overhead */
                    250:        HTAnchor_delete (parent);
                    251:     }
                    252:   }
                    253: }
                    254: 
                    255: PUBLIC BOOL HTAnchor_delete
1.3       timbl     256:   ARGS1 (HTParentAnchor *,me)
1.1       timbl     257: {
                    258:   HTChildAnchor *child;
                    259: 
                    260:   /* Don't delete if document is loaded */
1.3       timbl     261:   if (me->document)
1.1       timbl     262:     return NO;
                    263: 
                    264:   /* Recursively try to delete target anchors */
1.3       timbl     265:   deleteLinks ((HTAnchor *) me);
1.1       timbl     266: 
1.3       timbl     267:   if (! HTList_isEmpty (me->sources)) {  /* There are still incoming links */
1.1       timbl     268:     /* Delete all outgoing links from children, if any */
1.3       timbl     269:     HTList *kids = me->children;
1.12      frystyk   270:     while ((child = (HTChildAnchor *) HTList_nextObject (kids)))
1.1       timbl     271:       deleteLinks ((HTAnchor *) child);
                    272:     return NO;  /* Parent not deleted */
                    273:   }
                    274: 
                    275:   /* No more incoming links : kill everything */
                    276:   /* First, recursively delete children */
1.12      frystyk   277:   while ((child = (HTChildAnchor *) HTList_removeLastObject (me->children))) {
1.1       timbl     278:     deleteLinks ((HTAnchor *) child);
                    279:     free (child->tag);
                    280:     free (child);
                    281:   }
                    282: 
                    283:   /* Now kill myself */
1.3       timbl     284:   HTList_delete (me->children);
                    285:   HTList_delete (me->sources);
                    286:   free (me->address);
1.1       timbl     287:   /* Devise a way to clean out the HTFormat if no longer needed (ref count?) */
1.3       timbl     288:   free (me);
1.6       timbl     289:   if (me->cacheItems) {
                    290:       HTCacheClear(me->cacheItems);
                    291:   }
1.1       timbl     292:   return YES;  /* Parent deleted */
                    293: }
                    294: 
                    295: 
                    296: /*             Move an anchor to the head of the list of its siblings
                    297: **             ------------------------------------------------------
                    298: **
                    299: **     This is to ensure that an anchor which might have already existed
                    300: **     is put in the correct order as we load the document.
                    301: */
                    302: 
1.10      frystyk   303: PUBLIC void HTAnchor_makeLastChild
1.3       timbl     304:   ARGS1(HTChildAnchor *,me)
1.1       timbl     305: {
1.3       timbl     306:   if (me->parent != (HTParentAnchor *) me) {  /* Make sure it's a child */
                    307:     HTList * siblings = me->parent->children;
                    308:     HTList_removeObject (siblings, me);
                    309:     HTList_addObject (siblings, me);
1.1       timbl     310:   }
                    311: }
                    312: 
                    313: /*     Data access functions
                    314: **     ---------------------
                    315: */
                    316: 
                    317: PUBLIC HTParentAnchor * HTAnchor_parent
1.3       timbl     318:   ARGS1 (HTAnchor *,me)
1.1       timbl     319: {
1.3       timbl     320:   return me ? me->parent : NULL;
1.1       timbl     321: }
                    322: 
1.10      frystyk   323: PUBLIC void HTAnchor_setDocument
1.3       timbl     324:   ARGS2 (HTParentAnchor *,me, HyperDoc *,doc)
1.1       timbl     325: {
1.3       timbl     326:   if (me)
                    327:     me->document = doc;
1.1       timbl     328: }
                    329: 
1.10      frystyk   330: PUBLIC HyperDoc * HTAnchor_document
1.3       timbl     331:   ARGS1 (HTParentAnchor *,me)
1.1       timbl     332: {
1.3       timbl     333:   return me ? me->document : NULL;
1.1       timbl     334: }
                    335: 
                    336: 
1.10      frystyk   337: #if 0
                    338: PUBLIC void HTAnchor_setAddress
1.3       timbl     339:   ARGS2 (HTAnchor *,me, char *,addr)
1.1       timbl     340: {
1.3       timbl     341:   if (me)
                    342:     StrAllocCopy (me->parent->address, addr);
1.1       timbl     343: }
1.10      frystyk   344: #endif
                    345: 
1.1       timbl     346: 
1.10      frystyk   347: PUBLIC char * HTAnchor_address
1.3       timbl     348:   ARGS1 (HTAnchor *,me)
1.1       timbl     349: {
                    350:   char *addr = NULL;
1.3       timbl     351:   if (me) {
                    352:     if (((HTParentAnchor *) me == me->parent) ||
                    353:        !((HTChildAnchor *) me)->tag) {  /* it's an adult or no tag */
                    354:       StrAllocCopy (addr, me->parent->address);
1.1       timbl     355:     }
                    356:     else {  /* it's a named child */
1.12      frystyk   357:       addr = (char *) malloc (2 + strlen (me->parent->address)
                    358:                              + strlen (((HTChildAnchor *) me)->tag));
1.1       timbl     359:       if (addr == NULL) outofmem(__FILE__, "HTAnchor_address");
1.3       timbl     360:       sprintf (addr, "%s#%s", me->parent->address,
                    361:               ((HTChildAnchor *) me)->tag);
1.1       timbl     362:     }
                    363:   }
                    364:   return addr;
                    365: }
                    366: 
                    367: 
                    368: 
1.10      frystyk   369: PUBLIC void HTAnchor_setFormat
1.3       timbl     370:   ARGS2 (HTParentAnchor *,me, HTFormat ,form)
1.1       timbl     371: {
1.3       timbl     372:   if (me)
                    373:     me->format = form;
1.1       timbl     374: }
                    375: 
1.10      frystyk   376: PUBLIC HTFormat HTAnchor_format
1.3       timbl     377:   ARGS1 (HTParentAnchor *,me)
1.1       timbl     378: {
1.3       timbl     379:   return me ? me->format : NULL;
1.1       timbl     380: }
                    381: 
1.10      frystyk   382: PUBLIC void HTAnchor_clearIndex
1.9       frystyk   383:   ARGS1 (HTParentAnchor *,me)
                    384: {
                    385:   if (me)
                    386:     me->isIndex = NO;
                    387: }
1.1       timbl     388: 
1.10      frystyk   389: PUBLIC void HTAnchor_setIndex
1.3       timbl     390:   ARGS1 (HTParentAnchor *,me)
1.1       timbl     391: {
1.3       timbl     392:   if (me)
                    393:     me->isIndex = YES;
1.1       timbl     394: }
                    395: 
1.10      frystyk   396: PUBLIC BOOL HTAnchor_isIndex
1.3       timbl     397:   ARGS1 (HTParentAnchor *,me)
1.1       timbl     398: {
1.3       timbl     399:   return me ? me->isIndex : NO;
1.1       timbl     400: }
                    401: 
                    402: 
1.10      frystyk   403: PUBLIC BOOL HTAnchor_hasChildren
1.3       timbl     404:   ARGS1 (HTParentAnchor *,me)
1.1       timbl     405: {
1.3       timbl     406:   return me ? ! HTList_isEmpty(me->children) : NO;
1.1       timbl     407: }
                    408: 
                    409: /*     Title handling
                    410: */
1.10      frystyk   411: PUBLIC CONST char * HTAnchor_title
1.3       timbl     412:   ARGS1 (HTParentAnchor *,me)
1.1       timbl     413: {
1.3       timbl     414:   return me ? me->title : 0;
1.1       timbl     415: }
                    416: 
1.10      frystyk   417: PUBLIC void HTAnchor_setTitle
1.3       timbl     418:   ARGS2(HTParentAnchor *,me, CONST char *,title)
1.1       timbl     419: {
1.3       timbl     420:   StrAllocCopy(me->title, title);
1.1       timbl     421: }
                    422: 
1.10      frystyk   423: PUBLIC void HTAnchor_appendTitle
1.3       timbl     424:   ARGS2(HTParentAnchor *,me, CONST char *,title)
1.1       timbl     425: {
1.3       timbl     426:   StrAllocCat(me->title, title);
1.1       timbl     427: }
                    428: 
1.3       timbl     429: /*     Link me Anchor to another given one
1.1       timbl     430: **     -------------------------------------
                    431: */
                    432: 
1.10      frystyk   433: PUBLIC BOOL HTAnchor_link
1.1       timbl     434:   ARGS3(HTAnchor *,source, HTAnchor *,destination, HTLinkType *,type)
                    435: {
                    436:   if (! (source && destination))
                    437:     return NO;  /* Can't link to/from non-existing anchor */
1.11      frystyk   438:   if (ANCH_TRACE)
1.16    ! frystyk   439:       fprintf(TDEST, "LinkAnchor.. Linking anchor %p to anchor %p\n",
1.8       frystyk   440:              (void *) source, (void *) destination);
1.1       timbl     441:   if (! source->mainLink.dest) {
                    442:     source->mainLink.dest = destination;
                    443:     source->mainLink.type = type;
                    444:   } else {
                    445:     HTLink * newLink = (HTLink *) malloc (sizeof (HTLink));
                    446:     if (newLink == NULL) outofmem(__FILE__, "HTAnchor_link");
                    447:     newLink->dest = destination;
                    448:     newLink->type = type;
                    449:     if (! source->links)
                    450:       source->links = HTList_new ();
                    451:     HTList_addObject (source->links, newLink);
                    452:   }
                    453:   if (!destination->parent->sources)
                    454:     destination->parent->sources = HTList_new ();
                    455:   HTList_addObject (destination->parent->sources, source);
                    456:   return YES;  /* Success */
                    457: }
                    458: 
                    459: 
                    460: /*     Manipulation of links
                    461: **     ---------------------
                    462: */
                    463: 
1.10      frystyk   464: PUBLIC HTAnchor * HTAnchor_followMainLink
1.3       timbl     465:   ARGS1 (HTAnchor *,me)
1.1       timbl     466: {
1.3       timbl     467:   return me->mainLink.dest;
1.1       timbl     468: }
                    469: 
1.10      frystyk   470: PUBLIC HTAnchor * HTAnchor_followTypedLink
1.3       timbl     471:   ARGS2 (HTAnchor *,me, HTLinkType *,type)
1.1       timbl     472: {
1.3       timbl     473:   if (me->mainLink.type == type)
                    474:     return me->mainLink.dest;
                    475:   if (me->links) {
                    476:     HTList *links = me->links;
1.1       timbl     477:     HTLink *link;
1.12      frystyk   478:     while ((link = (HTLink *) HTList_nextObject (links)))
1.1       timbl     479:       if (link->type == type)
                    480:        return link->dest;
                    481:   }
1.3       timbl     482:   return NULL;  /* No link of me type */
1.1       timbl     483: }
                    484: 
1.2       timbl     485: 
                    486: /*     Make main link
                    487: */
1.10      frystyk   488: PUBLIC BOOL HTAnchor_makeMainLink
1.3       timbl     489:   ARGS2 (HTAnchor *,me, HTLink *,movingLink)
1.1       timbl     490: {
                    491:   /* Check that everything's OK */
1.3       timbl     492:   if (! (me && HTList_removeObject (me->links, movingLink)))
1.1       timbl     493:     return NO;  /* link not found or NULL anchor */
                    494:   else {
                    495:     /* First push current main link onto top of links list */
                    496:     HTLink *newLink = (HTLink*) malloc (sizeof (HTLink));
                    497:     if (newLink == NULL) outofmem(__FILE__, "HTAnchor_makeMainLink");
1.3       timbl     498:     memcpy (newLink, & me->mainLink, sizeof (HTLink));
                    499:     HTList_addObject (me->links, newLink);
1.1       timbl     500: 
                    501:     /* Now make movingLink the new main link, and free it */
1.3       timbl     502:     memcpy (& me->mainLink, movingLink, sizeof (HTLink));
1.1       timbl     503:     free (movingLink);
                    504:     return YES;
                    505:   }
1.2       timbl     506: }
                    507: 
                    508: 
                    509: /*     Methods List
                    510: **     ------------
                    511: */
                    512: 
1.3       timbl     513: PUBLIC HTList * HTAnchor_methods ARGS1(HTParentAnchor *, me)
1.2       timbl     514: {
1.3       timbl     515:     if (!me->methods) {
                    516:         me->methods = HTList_new();
1.2       timbl     517:     }
1.3       timbl     518:     return me->methods;
1.2       timbl     519: }
                    520: 
                    521: /*     Protocol
                    522: **     --------
                    523: */
                    524: 
1.3       timbl     525: PUBLIC void * HTAnchor_protocol ARGS1(HTParentAnchor *, me)
1.2       timbl     526: {
1.3       timbl     527:     return me->protocol;
1.2       timbl     528: }
                    529: 
1.3       timbl     530: PUBLIC void HTAnchor_setProtocol ARGS2(HTParentAnchor *, me,
1.2       timbl     531:        void*,  protocol)
                    532: {
1.3       timbl     533:     me->protocol = protocol;
1.2       timbl     534: }
                    535: 
                    536: /*     Physical Address
                    537: **     ----------------
                    538: */
                    539: 
1.3       timbl     540: PUBLIC char * HTAnchor_physical ARGS1(HTParentAnchor *, me)
1.2       timbl     541: {
1.3       timbl     542:     return me->physical;
1.2       timbl     543: }
                    544: 
1.3       timbl     545: PUBLIC void HTAnchor_setPhysical ARGS2(HTParentAnchor *, me,
1.2       timbl     546:        char *, physical)
                    547: {
1.9       frystyk   548:     if (!me || !physical) {
1.11      frystyk   549:        if (ANCH_TRACE)
1.16    ! frystyk   550:            fprintf(TDEST, "HTAnchor.... setPhysical, called with null argument\n");
1.9       frystyk   551:        return;
                    552:     }
1.3       timbl     553:     StrAllocCopy(me->physical, physical);
1.1       timbl     554: }
1.10      frystyk   555: 

Webmaster