convert line ends
[canaan.git] / prj / tech / libsrc / res / resmake.cpp
blob3e0ed52562defce13fdc3d5e93f2328289cddd14
1 // ResMake.c Resource making
2 // Rex E. Bradford
3 /*
4 * $Header: x:/prj/tech/libsrc/res/RCS/resmake.cpp 1.5 1996/09/14 16:10:34 TOML Exp $
5 * $Log: resmake.cpp $
6 * Revision 1.5 1996/09/14 16:10:34 TOML
7 * Prepared for revision
9 * Revision 1.4 1996/09/14 14:12:43 TOML
10 * Made C++ parser friendly
12 * Revision 1.3 1994/09/22 10:48:17 rex
13 * Modified access to resdesc flags, which have moved
15 * Revision 1.2 1994/06/16 11:08:04 rex
16 * Modified LRU list handling, lock resource made with ResMake() instead of
17 * setting RDF_NODROP flag
19 * Revision 1.1 1994/02/17 11:23:57 rex
20 * Initial revision
24 #include <string.h>
26 #include <res.h>
27 #include <res_.h>
29 // --------------------------------------------------------
31 // ResMake() makes a resource from a data block.
33 // Id = id of resource
34 // ptr = ptr to memory block (resource is not copied; this should
35 // point to storage where the resource can live indefinitely)
36 // size = size of resource in bytes
37 // type = resource type (RTYPE_XXX)
38 // filenum = file number
39 // flags = flags (RDF_XXX)
41 void ResMake(Id id, void *ptr, long size, uchar type, int filenum, uchar flags)
43 ResDesc *prd;
44 ResDesc2 *prd2;
45 // Extend res desc table if need to
47 ResExtendDesc(id);
49 // Check for resource at that id, if so delete it
51 Spew(DSRC_RES_Make, ("ResMake: making resource $%x\n", id));
53 prd = RESDESC(id);
54 if (prd->offset)
55 ResDelete(id);
57 // Add us to the soup, set lock so doesn't get swapped out
59 prd->ptr = ptr;
60 prd->size = size;
61 prd->filenum = filenum;
62 prd->lock = 1;
63 prd->offset = RES_OFFSET_PENDING;
65 prd2 = RESDESC2(id);
66 prd2->flags = flags;
67 prd2->type = type;
69 // ---------------------------------------------------------------
71 // ResMakeCompound() makes an empty compound resource
73 // id = id of resource
74 // type = resource type (RTYPE_XXX)
75 // filenum = file number
76 // flags = flags (RDF_XXX, RDF_COMPOUND automatically added)
78 void ResMakeCompound(Id id, uchar type, int filenum, uchar flags)
80 RefTable *prt;
81 long sizeTable;
82 // Build empty compound resource in allocated memory
84 Spew(DSRC_RES_Make, ("ResMake: making compound resource $%x\n", id));
86 sizeTable = REFTABLESIZE(0);
87 prt = (RefTable *) Malloc(sizeTable);
88 prt->numRefs = 0;
89 prt->offset[0] = sizeTable;
91 // Make a resource out of it
93 ResMake(id, prt, sizeTable, type, filenum, flags | RDF_COMPOUND);
95 // ---------------------------------------------------------------
97 // ResAddRef() adds an item to a compound resource.
99 // ref = reference
100 // pitem = ptr to item's data (copied from here, unlike simple resource)
101 // itemSize = size of item
103 void ResAddRef(Ref ref, void *pitem, long itemSize)
105 ResDesc *prd;
106 RefTable *prt;
107 RefIndex index,
109 long sizeItemOffsets,
110 oldSize,
111 sizeDiff;
112 // Error check
114 DBG(DSRC_RES_ChkIdRef,
116 if (!RefCheckRef(ref))
117 return;
120 // Get vital info (and get into memory if not already)
122 Spew(DSRC_RES_Make, ("ResAddRef: adding ref $%x\n", ref));
124 prd = RESDESC(REFID(ref));
125 prt = (RefTable *) prd->ptr;
126 if (prt == NULL)
127 prt = (RefTable *) RefGet(ref);
129 // If index within current range of compound resource, replace or insert
131 index = REFINDEX(ref);
132 if (index < prt->numRefs)
134 oldSize = RefSize(prt, index);
136 // If same size, just copy in
138 if (itemSize == oldSize)
140 Spew(DSRC_RES_Make, ("ResAddRef: replacing same size ref\n"));
141 memcpy(REFPTR(prt, index), pitem, itemSize);
144 // Else if new item smaller, reduce offsets, shift data, insert new data
146 else if (itemSize < oldSize)
148 Spew(DSRC_RES_Make, ("ResAddRef: replacing larger ref\n"));
149 sizeDiff = oldSize - itemSize;
150 for (i = index + 1; i <= prt->numRefs; i++)
151 prt->offset[i] -= sizeDiff;
152 prd->size -= sizeDiff;
153 memmove(REFPTR(prt, index + 1), REFPTR(prt, index + 1) + sizeDiff,
154 prt->offset[prt->numRefs] - prt->offset[index + 1]);
155 memcpy(REFPTR(prt, index), pitem, itemSize);
156 prd->ptr = Realloc(prd->ptr, prd->size);
158 else
160 Spew(DSRC_RES_Make, ("ResAddRef: replacing smaller ref\n"));
161 sizeDiff = itemSize - oldSize;
162 prd->size += sizeDiff;
163 prd->ptr = prt = (RefTable *) Realloc(prd->ptr, prd->size);
164 memmove(REFPTR(prt, index + 1) + sizeDiff, REFPTR(prt, index + 1),
165 prt->offset[prt->numRefs] - prt->offset[index + 1]);
166 for (i = index + 1; i <= prt->numRefs; i++)
167 prt->offset[i] += sizeDiff;
168 memcpy(REFPTR(prt, index), pitem, itemSize);
172 // Else if index exceeds current range, expand
174 else
176 Spew(DSRC_RES_Make, ("ResAddRef: extending compound resource\n"));
178 // Extend resource for new offset(s) and data item
180 sizeItemOffsets = sizeof(long) * ((index + 1) - prt->numRefs);
181 prd->size += sizeItemOffsets + itemSize;
182 prd->ptr = Realloc(prd->ptr, prd->size);
183 prt = (RefTable *) prd->ptr;
185 // Shift data upwards to make room for new offset(s)
187 memmove(REFPTR(prt, 0) + sizeItemOffsets, REFPTR(prt, 0),
188 prd->size - REFTABLESIZE(index + 1));
190 // Advance old offsets, set new ones
192 for (i = 0; i <= prt->numRefs; i++)
193 prt->offset[i] += sizeItemOffsets;
194 for (i = prt->numRefs + 1; i <= index; i++)
195 prt->offset[i] = prt->offset[prt->numRefs];
196 prt->offset[index + 1] = prt->offset[index] + itemSize;
198 // Copy data into place, set new numRefs
200 memcpy(REFPTR(prt, index), pitem, itemSize);
201 prt->numRefs = index + 1;
204 // -------------------------------------------------------------
206 // ResUnmake() removes a resource from the LRU list and sets its
207 // ptr to NULL. In this way, a program may take over management
208 // of the resource data, and the RES system forgets about it.
209 // This is typically done when user-managed data needs to be
210 // written to a resource file, using ResMake(),ResWrite(),ResUnmake().
212 // id = id of resource to unmake
214 void ResUnmake(Id id)
216 memset(RESDESC(id), 0, sizeof(ResDesc));