⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 objects.c

📁 source code: Covert TXT to PDF
💻 C
📖 第 1 页 / 共 3 页
字号:
struct xobject *t1_Permanent(obj) /* non-ANSI to avoid overly strict type checking */       register struct xobject *obj;  /* object to be made permanent         */{       IfTrace1((MustTraceCalls),"Permanent(%p)\n", obj);        if ( (obj != NULL) && ( !(ISPERMANENT(obj->flag)) ) )       {       /* there is a non-NULL, temporary object to be made permanent.          If there are multiple references to this object, first get          a new COPY().          Note also that we have to decrement the reference count if          we do a Copy() here, because we are consuming the temporary          argument passed, and returning a unique, permanent one.       */           if ( obj->references > 1)           {               obj = Copy(obj);           }           /* now set the permanent flag, and increment the reference              count, since a temporary object has now become permanent. */           obj->references++;           obj->flag |= ISPERMANENT(ON);       }       return(obj);} /*:h3.Temporary() - Undoes the Effect of "Permanent()" This simply resets the "ISPERMANENT" flag. If a permanent object is made temporary, and there is more than one referenceto it, we must first Copy() it, then reset the ISPERMANENT flag. However,if the permanent object has obly one reference, we need only decrement thereference count ( and reset the flag). Note that this function, in the case of a PERMANENT argument, basicallyconverts the PERMANENT handle to a TEMPORARY one. Thus, in the case ofa nonunique, permanent argument passed, we not only make a Copy(),we also decrement the reference count, to reflect the fact that we havelost a permanent handle and gained a temporary one.PNM 3-2-6-91*/ struct xobject *xiTemporary(obj) /* non-ANSI to avoid overly strict type checking */       register struct xobject *obj;  /* object to be made permanent         */{       IfTrace1((MustTraceCalls),"Temporary(%p)\n", obj);        if (obj != NULL) {               /* if it's already temporary, there's nothing to do. */               if ISPERMANENT(obj->flag)               {               /* if there are multiple references to this object, get a                  Copy we can safely alter. Recall that the reference count                  is incremented for permanent objects.                  Recall further that Copy returns an object with the                  same flag state and a reference count of 2 (for PERMANENT                  objects).                  Thus, regardless of whether or not we need to copy a                  permanent object, we still decrement its reference                  count and reset the flag.               */                   if (obj->references != 2 || ISIMMORTAL(obj->flag))                   {               /* not unique; consume handle, get a temporary Copy! */                       obj = Copy(obj);                   }               /* else decrement the reference count (since it's going from                  permanent to temporary) and clear the flag. */                   else {                       obj->references--;                       obj->flag &= ~ISPERMANENT(ON);                   }               }       }       return(obj);} /*:h3.Dup() - Duplicate an Object Dup will increment the reference count of an object, only making aCopy() if needed.Note that Dup() retains the state of the permanent flag.3-26-91 PNM*/  struct xobject *t1_Dup(obj)   /* non-ANSI avoids overly strict type checking  */       register struct xobject *obj;  /* object to be duplicated             */{       register char oldflag;   /* copy of original object's flag byte */        IfTrace1((MustTraceCalls),"Dup(%p)\n", obj);        if (obj == NULL)               return(NULL);       /* An immortal object must be Copy'ed, so that we get a mortal          copy of it, since we try not to destroy immortal objects. */       if (ISIMMORTAL(obj->flag))           return(Copy(obj));        /* if incrementing the reference count doesn't cause the count          to wrap, simply return the object with the count bumped. Note          that the RefRoll macro increments the count to perform the          rollover check, so we must decrement the count. */       if (RefRoll(obj))           return(obj);        /* that didn't work out, so put the count back and call Copy(). */       --obj->references;       oldflag = obj->flag;       obj = Copy(obj);       if (ISPERMANENT(oldflag))               obj = Permanent(obj);       return(obj);} /*:h3.Copy() - Make a New Copy of an Object This is the generic Copy() where the object type is unknown.  Thereare specific Copyxxx functions for known object types. Copy will create a NEW temporary object, and WILL NOT simply bump thereference count. Sometimes duplicating an object is just as simple as Allocating with itas a template.  But other objects are complicated linked lists.  So, welet each module provide us a routine (or macro) that duplicates theobjects it knows about.*/ struct xobject *t1_Copy(obj)       register struct xobject *obj;  /* object to be  Copy'ed              */{       if (obj == NULL)               return(NULL);        if (ISPATHTYPE(obj->type))               obj = (struct xobject *) CopyPath(obj);       else               switch (obj->type) {                   case SPACETYPE:                       obj = (struct xobject *) CopySpace(obj); break;                   case FONTTYPE:                       obj = (struct xobject *) CopyFont(obj); break;                   case REGIONTYPE:                       obj = (struct xobject *) CopyRegion(obj); break;                   case PICTURETYPE:                       obj = (struct xobject *) CopyPicture(obj); break;                   case LINESTYLETYPE:                       obj = (struct xobject *) CopyLineStyle(obj); break;                   case STROKEPATHTYPE:                       obj = (struct xobject *) CopyStrokePath(obj); break;                   case CLUTTYPE:                       obj = (struct xobject *) CopyCLUT(obj); break;                   default:                       return(ArgErr("Copy: invalid object", obj, NULL));               }         return(obj);} /*:h3.Destroy() - Destroys an Object This can get complicated.  Just like with Copy(), we let the expertshandle it.*/struct xobject *Destroy(obj) /* non-ANSI avoids overly strict type checking  */       register struct xobject *obj;  /* object to be destroyed              */{       IfTrace1((MustTraceCalls),"Destroy(%p)\n", obj);        if (obj == NULL)               return(NULL);       if (ISIMMORTAL(obj->flag)) {               IfTrace1(TRUE,"Destroy of immortal object %p ignored\n", obj);               return(NULL);       }       if (ISPATHTYPE(obj->type))               KillPath(obj);       else {               switch (obj->type) {                   case REGIONTYPE:                       KillRegion(obj);                       break;                   case SPACETYPE:                       KillSpace(obj);                       break;                   case LINESTYLETYPE:                       KillLineStyle(obj);                       break;                   case FONTTYPE:                       KillFont(obj);                       break;                   case PICTURETYPE:		       /* KillPicture macro removed from sources (RMz, 2001-04-01)                       KillPicture(obj);		       */                       break;	           case STROKEPATHTYPE:                       KillStrokePath(obj);                       break;                   case CLUTTYPE:                       KillCLUT(obj);                       break;                   default:                       return(ArgErr("Destroy: invalid object", obj, NULL));               }       }       return(NULL);}/*:h2.Generally Useful Macros :h3.FOLLOWING() - Macro to Point to the Data Following a Structure There are several places in TYPE1IMAGER where we will allocate variabledata that belongs to a structure immediately after that structure.This is a performance technique, because it reduces the number oftrips we have to take through Xalloc() and Xfree().  It turns out C hasa very convenient way to point past a structure--if 'p' is a pointerto a structure, 'p+1' is a pointer to the data after it.  Thisbehavior of C is somewhat startling and somewhat hard to follow, ifyou are not used to it, so we define a macro to point to the datafollowing a structure:*//*SHARED LINE(S) ORIGINATED HERE*//*:h3.TYPECHECK() - Verify the Type of an Argument This macro tests the type of an argument.  If the test fails, it consumesany other arguments as necessary and causes the imbedding routine toreturn the value 'whenBAD'. Note that the consumeables list should be an argument list itself, forexample (0) or (2,A,B).  See :hdref refid=consume. below.*/ /*SHARED LINE(S) ORIGINATED HERE*//*:h3.ARGCHECK() - Perform an Arbitrary Check on an Argument This macro is a generalization of TYPECHECK to take an arbitrarypredicate.  If the error occurs (i.e., the predicate is true), thearbitrary message 'msg' is returned.*/ /*SHARED LINE(S) ORIGINATED HERE*//*:h3.TYPENULLCHECK() - Extension of TYPECHECK() for NULL arguments Many routines allow NULLs to be passed as arguments.  'whenBAD' willbe returned in this case, too.*/ /*SHARED LINE(S) ORIGINATED HERE*//*:h3.MAKECONSUME() - Create a "Consume"-type Macro Consuming an object means destroying it if it is not permanent.  Thislogic is so common to all the routines, that it is immortalized in thismacro.  For example, ConsumePath(p) can be simply defined asMAKECONSUME(p,KillPath(p)).  In effect, this macro operates on ameta-level.:i1/consuming objects/*/ /*SHARED LINE(S) ORIGINATED HERE*/ /*:h3.MAKEUNIQUE() - Create a "Unique"-type Macro Many routines are written to modify their arguments in place.  Thus,they want to insure that they duplicate an object if it is permanent.This is called making an object "unique".  For example, UniquePath(p)can be simply defined as MAKEUNIQUE(p,DupPath(p)).:i1/unique objects/*/ /*SHARED LINE(S) ORIGINATED HERE*/ /*An object is unique (and directly alterable) if there is only onereference to it, and it is not permanent (in which case we incrementthe reference count, so we don't have to check the permanent bit).3-26-91 PNM Note the rules for making a unique object:&drawing.   IF  (obj->references = 1)    return(obj);   ELSE (references > 1)       IF (ISPERMANENT(obj->flag))    return(Dupxxx(obj));       ELSE (nonunique, temporary object!)           obj->references--; return(Dupxxx(obj));&edrawing.If we must make a Copy of a nonunique, temporary object, we decrementreference count of the original object!*/ /*:h3.Unique() - Make a Unique Object Here is a generic 'Unique' function if the object type is not known.Why didn't we build it with the MAKEUNIQUE macro, you ask?  Well, weused to, but there is at least one damn compiler in the world thatraises errors if the types of an "(a) ? b : c" expression do not match.Also, when we changed Dup() to retain the permanent/temporary flag, wewanted to make sure "Unique" always returned a temporary object. Note that we cannot use Dup() to create a copy of the object in question,because Dup() may simply bump the reference count, and not return aunique copy to us. That is why we use t1_Copy(). The purpose of this function is to make sure we have a copy of an objectthat we can safely alter::ol.:li.If we have a unique, temporary object, we simply return the argument.:li.If we have a nonunique, temporary object, we have to make a new copyof it, and decrement the reference count of the original object, to reflectthe fact that we traded temporary handles.:li.If we have a permanent object, we make a temporary copy of it, butwe do not decrement the reference count of the original permanent object,because permanent objects, by definition, are persistent. 3-2-6-91 PNM:eol.*/ struct xobject *t1_Unique(obj)       struct xobject *obj;{    /* if the original object is not already unique, make a unique       copy...Note also that if the object was not permanent, we must       consume the old handle! 3-26-91 PNM       NOTE : consumption of the old handle moved to Allocate. 4-18-91 */    if (!obj || obj->references == 1)        return(obj);     obj = Copy(obj);    /* and make sure we return a temporary object ! */    if (ISPERMANENT(obj->flag))    {        obj->flag &= ~ISPERMANENT(ON);        obj->references--;    }    return(obj);}  /*:h2.Initialization, Error, and Debug Routines :h3 id=debugvar.Declarations for Debug Purposes We declare all the debug flags here.  Some link editors make the notunreasonable restriction that only one module may declare andinitialize global variables; all the rest must declare the variable'extern'.  This is logical, but is somewhat awkward to implement withC include files.  We solve the problem by temporarily making the name'extern' a null name if GLOBALS is defined.  (GLOBALS is only definedin this OBJECTS module.)  Since 'externs' can't be initialized, wehave to handle that with #defines too.:i1/GLOBALS (&#define.)/*/ /*SHARED LINE(S) ORIGINATED HERE*/static char *ErrorMessage = NULL; /*:h3.Pragmatics() - Set/Reset Debug Flags We provide a controlled way for the TYPE1IMAGER user to set and resetour debugging and tracing:*/void Pragmatics(username, value)       char *username;       /* name of the flag                             */       int value;            /* value to set it to                           */{       register char *p;     /* temporary loop variable                      */#define    NAMESIZE   40       char name[NAMESIZE];  /* buffer to store my copy of 'username'        */        if (strlen(username) >= NAMESIZE)               abort("Pragmatics name too large", 18);       strcpy(name, username);       for (p = name; *p != '\0'; p++)               *p = toupper(*p);        if (!strcmp(name, "ALL"))               MustTraceCalls = InternalTrace = /* MustCrash = */                    LineIOTrace = value;        else if (!strcmp(name, "LINEIOTRACE"))               LineIOTrace = value;        else if (!strcmp(name, "TRACECALLS"))               MustTraceCalls = value;        else if (!strcmp(name, "CHECKARGS"))               MustCheckArgs = value; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -