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

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

Webmaster