1 // ResMake.c Resource making
4 * $Header: x:/prj/tech/libsrc/res/RCS/resmake.cpp 1.5 1996/09/14 16:10:34 TOML Exp $
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
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
)
45 // Extend res desc table if need to
49 // Check for resource at that id, if so delete it
51 Spew(DSRC_RES_Make
, ("ResMake: making resource $%x\n", id
));
57 // Add us to the soup, set lock so doesn't get swapped out
61 prd
->filenum
= filenum
;
63 prd
->offset
= RES_OFFSET_PENDING
;
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
)
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
);
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.
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
)
109 long sizeItemOffsets
,
114 DBG(DSRC_RES_ChkIdRef
,
116 if (!RefCheckRef(ref
))
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
;
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
);
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
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
));