home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d502 / cells.lha / CELLS / CELLSSource.lzh / cParts.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  8KB  |  354 lines

  1. /*
  2.  *  CELLS       An Implementation of the WireWorld cellular automata
  3.  *              as described in Scientific American, Jan 1990.
  4.  *
  5.  *              Copyright 1990 by Davide P. Cervone.
  6.  *  You may use this code, provided this copyright notice is kept intact.
  7.  *  See the CELLS.HELP file for complete information on distribution conditions.
  8.  */
  9.  
  10. /*
  11.  *  File:  cParts.c     Handles creation and maintenance of Parts and Libraries.
  12.  */
  13.  
  14.  
  15. #include "cGadget.h"
  16. #include "cRequest.h"
  17. #include "cParts.h"
  18.  
  19. LIBRARY PartsList = {NULL,NULL, "Parts List",0, PL_STATIC|PL_NODELETE, NULL};
  20. LIBRARY *FirstLibrary = &PartsList;
  21. LIBRARY *SelectedLibrary = &PartsList;
  22.  
  23.  
  24. /*
  25.  *  FreePart()
  26.  *
  27.  *  If a part was specified,
  28.  *    If the part has a data section, free it
  29.  *    If it has a name string, free it
  30.  *    If the part is not static, free the part
  31.  */
  32.  
  33. void FreePart(thePart)
  34. PART *thePart;
  35. {
  36.    if (thePart)
  37.    {
  38.       if (thePart->Data) FREEBLOCK(UBYTE,thePart->w*thePart->h,thePart->Data);
  39.       if (thePart->NameLen) FREECHAR(thePart->Name,thePart->NameLen);
  40.       if ((thePart->Flags & PT_STATIC) == 0) FREESTRUCT(Part,thePart);
  41.    }
  42. }
  43.  
  44.  
  45. /*
  46.  *  FreePartList()
  47.  *
  48.  *  Free every part in the specifie part list, and clear the list pointer
  49.  *  to NULL
  50.  */
  51.  
  52. void FreePartList(thePart)
  53. PART **thePart;
  54. {
  55.    PART *tmpPart;
  56.  
  57.    while (*thePart)
  58.    {
  59.       tmpPart = *thePart;
  60.       *thePart = (*thePart)->Next;
  61.       FreePart(tmpPart);
  62.    }
  63. }
  64.  
  65.  
  66. /*
  67.  *  FreeLibrary()
  68.  *
  69.  *  If a library is specified,
  70.  *    Free any parts in its list
  71.  *    If the library has a name, free it
  72.  *    If the library is no static, free it, otherwise, unlink it
  73.  */
  74.  
  75. void FreeLibrary(theLibrary)
  76. LIBRARY *theLibrary;
  77. {
  78.    if (theLibrary)
  79.    {
  80.       FreePartList(&(theLibrary->FirstPart));
  81.       if (theLibrary->NameLen) FREECHAR(theLibrary->Name,theLibrary->NameLen);
  82.       if ((theLibrary->Flags & PL_STATIC) == 0)
  83.          FREESTRUCT(Library,theLibrary);
  84.         else
  85.          theLibrary->Next = theLibrary->Prev = NULL;
  86.    }
  87. }
  88.  
  89.  
  90. /*
  91.  *  FreeLibList()
  92.  *
  93.  *  For each library in the list, free the library and go on to the next one
  94.  *  Set the library pointer to NULL.
  95.  */
  96.  
  97. void FreeLibList(theLibrary)
  98. LIBRARY **theLibrary;
  99. {
  100.    LIBRARY *tmpLibrary;
  101.    
  102.    while (*theLibrary)
  103.    {
  104.       tmpLibrary = *theLibrary;
  105.       *theLibrary = (*theLibrary)->Next;
  106.       FreeLibrary(tmpLibrary);
  107.    }
  108. }
  109.  
  110.  
  111. /*
  112.  *  ClearLibs()
  113.  *
  114.  *  Clear contents of all libraries, and reset the lists to the standard
  115.  *  Parts List.
  116.  */
  117.  
  118. void ClearLibs()
  119. {
  120.    FreeLibList(&FirstLibrary);
  121.    FirstLibrary = &PartsList;
  122.    SelectedLibrary = &PartsList;
  123. }
  124.  
  125.  
  126. /*
  127.  *  PartToGrid()
  128.  *
  129.  *  Get the size of the part's data area (clipped to the grid size)
  130.  *  Clear the grid to zeros and unpack the data area into the grid.
  131.  *  (a more sophisticated algorithm could be used here - only the first
  132.  *  two bits of each byte are used.  Packing the bits or byte-run compression
  133.  *  would help).
  134.  */
  135.  
  136. void PartToGrid(Grid,thePart)
  137. UBYTE Grid[];
  138. PART *thePart;
  139. {
  140.    register short X,Y;
  141.    register short i;
  142.    register UBYTE *theByte = thePart->Data;
  143.    short x,y,w,h;
  144.    
  145.    w = thePart->w;
  146.    h = thePart->h;
  147.    x = GridX + (GridW - w) / 2;
  148.    y = GridY + (GridH - h) / 2;
  149.    if (x+w > MAXGRIDW) x = MAXGRIDW-w;
  150.    if (y+w > MAXGRIDH) y = MAXGRIDH-h;
  151.    if (x < 0) x = 0; if (y < 0) y = 0;
  152.    w += x; h += y;
  153.  
  154.    ZeroGrid(Grid);
  155.    for (Y=y; Y<h; Y++)
  156.       for (X=x, i=X+MAXGRIDW*Y; X<w; X++,i++)
  157.          Grid[i] = *theByte++;
  158. }
  159.  
  160.  
  161. /*
  162.  *  GridToPart()
  163.  *
  164.  *  Copy the part data from the specified grid area.
  165.  */
  166.  
  167. void GridToPart(Grid,x,y,w,h,thePart)
  168. UBYTE Grid[];
  169. short x,y,w,h;
  170. PART *thePart;
  171. {
  172.    register short X,Y;
  173.    register short i;
  174.    register UBYTE *theByte = thePart->Data;
  175.  
  176.    w += x; h += y;
  177.    for (Y=y; Y<h; Y++)
  178.       for (X=x, i=X+MAXGRIDW*Y; X<w; X++,i++)
  179.          *theByte++ = Grid[i];
  180. }
  181.  
  182.  
  183. /*
  184.  *  NewPart()
  185.  *
  186.  *  If we can allocate a new part structure
  187.  *    Get the length of the part name
  188.  *    If we can get a new text string of that size
  189.  *      Copy the name
  190.  *      If we can get a block big enough for the data area
  191.  *        Set the part's width and height
  192.  *        Copy the grid to the part data area
  193.  *      Otherwise
  194.  *        Free the allocated memory and return NULL
  195.  *    Otherwise
  196.  *      Free the allocated memory and return NULL
  197.  *  Give a message if the part could not be made
  198.  */
  199.  
  200. PART *NewPart(Name,Grid,x,y,w,h)
  201. char *Name;
  202. UBYTE *Grid;
  203. short x,y,w,h;
  204. {
  205.    PART *thePart;
  206.  
  207.    if (NEWSTRUCT(Part,thePart))
  208.    {
  209.       thePart->NameLen = strlen(Name);
  210.       if (NEWCHAR(thePart->Name,thePart->NameLen))
  211.       {
  212.          strcpy(thePart->Name,Name);
  213.          if (NEWBLOCK(UBYTE,w*h,thePart->Data))
  214.          {
  215.             thePart->w = w;
  216.             thePart->h = h;
  217.             GridToPart(Grid,x,y,w,h,thePart);
  218.          } else {
  219.             FREECHAR(thePart->Name,thePart->NameLen);
  220.             FREESTRUCT(Part,thePart); thePart = NULL;
  221.          }
  222.       } else {
  223.          FREESTRUCT(Part,thePart); thePart = NULL;
  224.       }
  225.    }
  226.    if (thePart == NULL) DoError("Can't Get Memory for Part");
  227.    return(thePart);
  228. }
  229.  
  230.  
  231. /*
  232.  *  MakePart()
  233.  *
  234.  *  Get the size of the selected part
  235.  *  If there are no selected cells, give a message
  236.  *  Otherwise, if there is a name provided
  237.  *    Look for the parts (sorted) position in the Parts List
  238.  *    If its place was found (i.e., not already in the list)
  239.  *      Create a new part structure; if allocated OK
  240.  *        Link the part into the list and mark the change
  241.  *    Otherwise
  242.  *      Warn the user that a part with the given name already exists
  243.  *  Otherwise cancel creating the part
  244.  */
  245.  
  246. PART *MakePart(Name)
  247. char *Name;
  248. {
  249.    PART *thePart = NULL;
  250.    PART *PrevPart;
  251.    PART **PartPtr;
  252.    short x,y,w,h;
  253.  
  254.    GetBounds(NewGen,&x,&y,&w,&h,0);
  255.    if (x == MAXGRIDW || y == MAXGRIDH)
  256.    {
  257.       DoError("No Cells Selected for Part");
  258.    } else {
  259.       if (Name && Name[0])
  260.       {
  261.          FindListPos(Name,&(PartsList.FirstPart),&PrevPart,&PartPtr);
  262.          if (PartPtr)
  263.          {
  264.             thePart = NewPart(Name,NewGen,x,y,w,h);
  265.             if (thePart)
  266.             {
  267.                thePart->Prev = PrevPart;
  268.                thePart->Next = *PartPtr;
  269.                if (thePart->Next) thePart->Next->Prev = thePart;
  270.                *PartPtr = thePart;
  271.                Changed = TRUE;
  272.             }
  273.          } else {
  274.             DoError("Part '%s' Already Exists",Name);
  275.          }
  276.       } else thePart = CANCELPART;
  277.    }
  278.    return(thePart);
  279. }
  280.  
  281.  
  282. /*
  283.  *  FinishPart()
  284.  *
  285.  *  Get the bounds for the cells read in
  286.  *  If no cells were found give a warning
  287.  *  Otherwise
  288.  *    Find the (sorted) position of the part in the Parts List
  289.  *    If it does not already exist in the list
  290.  *      Create a new part structure; if OK
  291.  *        link the part into the list
  292.  *    Otherwise indicate that the part already exists
  293.  */
  294.  
  295. void FinishPart(Name,theLibrary)
  296. char *Name;
  297. LIBRARY *theLibrary;
  298. {
  299.    short x,y,w,h;
  300.    PART *thePart;
  301.    PART *PrevPart;
  302.    PART **PartPtr;
  303.  
  304.    GetBounds(NewGen,&x,&y,&w,&h,0);
  305.    if (x == MAXGRIDW || y == MAXGRIDH)
  306.    {
  307.       ReadError("No Cells for Part '%s' in Library '%s'",Name,theLibrary->Name);
  308.    } else {
  309.       FindListPos(Name,&(theLibrary->FirstPart),&PrevPart,&PartPtr);
  310.       if (PartPtr)
  311.       {
  312.          thePart = NewPart(Name,NewGen,x,y,w,h);
  313.          if (thePart)
  314.          {
  315.             thePart->Prev = PrevPart;
  316.             thePart->Next = *PartPtr;
  317.             if (thePart->Next) thePart->Next->Prev = thePart;
  318.             *PartPtr = thePart;
  319.          }
  320.       } else {
  321.          ReadError("Duplicate Part '%s' in Library '%s'",Name,theLibrary->Name);
  322.       }
  323.    }
  324. }
  325.  
  326.  
  327. /*
  328.  *  NewLibrary()
  329.  *
  330.  *  If we can allocate a new library structure
  331.  *    Make a copy of the name for the library, if possible
  332.  *  If any errors occur, warn the user.
  333.  */
  334.  
  335. LIBRARY *NewLibrary(Name)
  336. char *Name;
  337. {
  338.    LIBRARY *theLibrary;
  339.  
  340.    if (NEWSTRUCT(PartLibrary,theLibrary))
  341.    {
  342.       theLibrary->NameLen = strlen(Name);
  343.       if (NEWCHAR(theLibrary->Name,theLibrary->NameLen))
  344.       {
  345.          strcpy(theLibrary->Name,Name);
  346.       } else {
  347.          FREESTRUCT(PartLibrary,theLibrary);
  348.          theLibrary = NULL;
  349.       }
  350.    }
  351.    if (theLibrary == NULL) ReadError("Can't Get Memory for Library");
  352.    return(theLibrary);
  353. }
  354.