Release 0.4.0
[wine] / loader / resource.c
1 static char RCSId[] = "$Id: resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
2 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include "prototypes.h"
7 #include "neexe.h"
8 #include "windows.h"
9 #include "gdi.h"
10
11 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
12 \f
13 /**********************************************************************
14  *                                      ConvertCoreBitmap
15  */
16 HBITMAP
17 ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image )
18 {
19     BITMAPINFO * bmpInfo;
20     HBITMAP hbitmap;
21     char * bits;
22     int i, size, n_colors;
23     
24     n_colors = 1 << image->bcBitCount;
25
26     if (image->bcBitCount < 24)
27     {
28         size = sizeof(BITMAPINFOHEADER) + n_colors * sizeof(RGBQUAD);   
29         bits = (char *) (image + 1) + (n_colors * sizeof(RGBTRIPLE));
30     }
31     else
32     {
33         size = sizeof(BITMAPINFOHEADER);
34         bits = (char *) (image + 1);
35     }
36     bmpInfo = (BITMAPINFO *) malloc( size );
37
38     bmpInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
39     bmpInfo->bmiHeader.biWidth         = image->bcWidth;
40     bmpInfo->bmiHeader.biHeight        = image->bcHeight;
41     bmpInfo->bmiHeader.biPlanes        = image->bcPlanes;
42     bmpInfo->bmiHeader.biBitCount      = image->bcBitCount;
43     bmpInfo->bmiHeader.biCompression   = 0;
44     bmpInfo->bmiHeader.biSizeImage     = 0;
45     bmpInfo->bmiHeader.biXPelsPerMeter = 0;
46     bmpInfo->bmiHeader.biYPelsPerMeter = 0;
47     bmpInfo->bmiHeader.biClrUsed       = 0;
48     bmpInfo->bmiHeader.biClrImportant  = 0;
49
50     if (image->bcBitCount < 24)
51     {
52         RGBTRIPLE * oldMap = (RGBTRIPLE *)(image + 1);
53         RGBQUAD * newMap = bmpInfo->bmiColors;
54         for (i = 0; i < n_colors; i++, oldMap++, newMap++)
55         {
56             newMap->rgbRed      = oldMap->rgbtRed;
57             newMap->rgbGreen    = oldMap->rgbtGreen;
58             newMap->rgbBlue     = oldMap->rgbtBlue;
59             newMap->rgbReserved = 0;
60         }
61     }
62
63     hbitmap = CreateDIBitmap( hdc, &bmpInfo->bmiHeader, CBM_INIT,
64                               bits, bmpInfo, DIB_RGB_COLORS );
65     free( bmpInfo );
66     return hbitmap;
67 }
68
69 /**********************************************************************
70  *                                      ConvertInfoBitmap
71  */
72 HBITMAP
73 ConvertInfoBitmap( HDC hdc, BITMAPINFO * image )
74 {
75     char * bits = ((char *)image) + DIB_BitmapInfoSize(image, DIB_RGB_COLORS);
76     return CreateDIBitmap( hdc, &image->bmiHeader, CBM_INIT,
77                            bits, image, DIB_RGB_COLORS );
78
79 \f
80 /**********************************************************************
81  *                                      FindResourceByNumber
82  */
83 int
84 FindResourceByNumber(struct resource_nameinfo_s *result_p,
85                      int type_id, int resource_id)
86 {
87     struct resource_typeinfo_s typeinfo;
88     struct resource_nameinfo_s nameinfo;
89     unsigned short size_shift;
90     int i;
91
92     /*
93      * Move to beginning of resource table.
94      */
95     lseek(CurrentNEFile, (CurrentMZHeader->ne_offset +
96                           CurrentNEHeader->resource_tab_offset), SEEK_SET);
97     
98     /*
99      * Read block size.
100      */
101     if (read(CurrentNEFile, &size_shift, sizeof(size_shift)) != 
102         sizeof(size_shift))
103     {
104         return -1;
105     }
106     
107     /*
108      * Find resource.
109      */
110     typeinfo.type_id = 0xffff;
111     while (typeinfo.type_id != 0)
112     {
113         if (read(CurrentNEFile, &typeinfo, sizeof(typeinfo)) !=
114             sizeof(typeinfo))
115         {
116             return -1;
117         }
118         if (typeinfo.type_id != 0)
119         {
120             for (i = 0; i < typeinfo.count; i++)
121             {
122                 if (read(CurrentNEFile, &nameinfo, sizeof(nameinfo)) != 
123                     sizeof(nameinfo))
124                 {
125                     return -1;
126                 }
127
128 #if defined(DEBUG_RESOURCE) && defined(VERBOSE_DEBUG)
129                 if (type_id == typeinfo.type_id)
130                 {
131                     printf("FindResource: type id = %d, resource id = %x\n",
132                            type_id, nameinfo.id);
133                 }
134 #endif
135                 if ((type_id == -1 || typeinfo.type_id == type_id) &&
136                     nameinfo.id == resource_id)
137                 {
138                     memcpy(result_p, &nameinfo, sizeof(nameinfo));
139                     return size_shift;
140                 }
141             }
142         }
143     }
144     
145     return -1;
146 }
147 \f
148 /**********************************************************************
149  *                                      FindResourceByName
150  */
151 int
152 FindResourceByName(struct resource_nameinfo_s *result_p,
153                      int type_id, char *resource_name)
154 {
155     struct resource_typeinfo_s typeinfo;
156     struct resource_nameinfo_s nameinfo;
157     unsigned short size_shift;
158     off_t old_pos, new_pos;
159     unsigned char nbytes;
160     char name[256];
161     int i;
162
163     /*
164      * Move to beginning of resource table.
165      */
166     lseek(CurrentNEFile, (CurrentMZHeader->ne_offset +
167                           CurrentNEHeader->resource_tab_offset), SEEK_SET);
168     
169     /*
170      * Read block size.
171      */
172     if (read(CurrentNEFile, &size_shift, sizeof(size_shift)) != 
173         sizeof(size_shift))
174     {
175         return -1;
176     }
177     
178     /*
179      * Find resource.
180      */
181     typeinfo.type_id = 0xffff;
182     while (typeinfo.type_id != 0)
183     {
184         if (read(CurrentNEFile, &typeinfo, sizeof(typeinfo)) !=
185             sizeof(typeinfo))
186         {
187             return -1;
188         }
189         if (typeinfo.type_id == type_id || type_id == -1)
190         {
191             for (i = 0; i < typeinfo.count; i++)
192             {
193                 if (read(CurrentNEFile, &nameinfo, sizeof(nameinfo)) != 
194                     sizeof(nameinfo))
195                 {
196                     return -1;
197                 }
198
199                 if (nameinfo.id & 0x8000)
200                     continue;
201                 
202                 old_pos = lseek(CurrentNEFile, 0, SEEK_CUR);
203                 new_pos = (CurrentMZHeader->ne_offset +
204                            CurrentNEHeader->resource_tab_offset +
205                            nameinfo.id);
206                 lseek(CurrentNEFile, new_pos, SEEK_SET);
207                 read(CurrentNEFile, &nbytes, 1);
208                 read(CurrentNEFile, name, nbytes);
209                 lseek(CurrentNEFile, old_pos, SEEK_SET);
210                 name[nbytes] = '\0';
211
212                 if (strcasecmp(name, resource_name) == 0)
213                 {
214                     memcpy(result_p, &nameinfo, sizeof(nameinfo));
215                     return size_shift;
216                 }
217             }
218         }
219     }
220     
221     return -1;
222 }
223 \f
224 /**********************************************************************
225  *                                      LoadString
226  */
227 int
228 LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
229 {
230     struct resource_nameinfo_s nameinfo;
231     unsigned short target_id;
232     unsigned char string_length;
233     int size_shift;
234     int string_num;
235     int i;
236
237 #ifdef DEBUG_RESOURCE
238     printf("LoadString: instance = %04x, id = %d, "
239            "buffer = %08x, length = %d\n",
240            instance, resource_id, buffer, buflen);
241 #endif
242     
243     /*
244      * Find string entry.
245      */
246     target_id = (resource_id >> 4) + 0x8001;
247     string_num = resource_id & 0x000f;
248
249     size_shift = FindResourceByNumber(&nameinfo, NE_RSCTYPE_STRING, target_id);
250     if (size_shift == -1)
251         return 0;
252     
253     lseek(CurrentNEFile, (int) nameinfo.offset << size_shift, SEEK_SET);
254
255     for (i = 0; i < string_num; i++)
256     {
257         read(CurrentNEFile, &string_length, 1);
258         lseek(CurrentNEFile, string_length, SEEK_CUR);
259     }
260                         
261     read(CurrentNEFile, &string_length, 1);
262     i = MIN(string_length, buflen - 1);
263     read(CurrentNEFile, buffer, i);
264     buffer[i] = '\0';
265 #ifdef DEBUG_RESOURCE
266     printf("            '%s'\n", buffer);
267 #endif
268     return i;
269 }
270 \f
271 /**********************************************************************
272  *                                      LoadIcon
273  */
274 HICON
275 LoadIcon(HANDLE instance, LPSTR icon_name)
276 {
277   fprintf(stderr,"LoadIcon: (%d),%d\n",instance,icon_name);
278     return 0;
279 }
280
281 /**********************************************************************
282  *                                      LoadCursor
283  */
284 HCURSOR
285 LoadCursor(HANDLE instance, LPSTR cursor_name)
286 {
287   fprintf(stderr,"LoadCursor: (%d),%d\n",instance,cursor_name);
288     return 0;
289 }
290
291 /**********************************************************************
292  *                                      LoadAccelerators
293  */
294 HANDLE
295 LoadAccelerators(HANDLE instance, LPSTR lpTableName)
296 {
297   fprintf(stderr,"LoadAccelerators: (%d),%d\n",instance,lpTableName);
298     return 0;
299 }
300 \f
301 /**********************************************************************
302  *                                      RSC_LoadResource
303  */
304 HANDLE
305 RSC_LoadResource(int instance, char *rsc_name, int type, int *image_size_ret)
306 {
307     struct resource_nameinfo_s nameinfo;
308     HANDLE hmem;
309     void *image;
310     int image_size;
311     int size_shift;
312     
313     /*
314      * Built-in resources
315      */
316     if (instance == 0)
317     {
318         return 0;
319     }
320     /*
321      * Get resource by ordinal
322      */
323     else if (((int) rsc_name & 0xffff0000) == 0)
324     {
325         size_shift = FindResourceByNumber(&nameinfo, type,
326                                           (int) rsc_name | 0x8000);
327     }
328     /*
329      * Get resource by name
330      */
331     else
332     {
333         size_shift = FindResourceByName(&nameinfo, type, rsc_name);
334     }
335     if (size_shift == -1)
336         return 0;
337
338     /*
339      * Read resource.
340      */
341     lseek(CurrentNEFile, ((int) nameinfo.offset << size_shift), SEEK_SET);
342
343     image_size = nameinfo.length << size_shift;
344     if (image_size_ret != NULL)
345         *image_size_ret = image_size;
346     
347     hmem = GlobalAlloc(GMEM_MOVEABLE, image_size);
348     image = GlobalLock(hmem);
349     if (image == NULL || read(CurrentNEFile, image, image_size) != image_size)
350     {
351         GlobalFree(hmem);
352         return 0;
353     }
354
355     GlobalUnlock(hmem);
356     return hmem;
357 }
358 \f
359 /**********************************************************************
360  *                                      RSC_LoadMenu
361  */
362 HANDLE
363 RSC_LoadMenu(HANDLE instance, LPSTR menu_name)
364 {
365     return RSC_LoadResource(instance, menu_name, NE_RSCTYPE_MENU, NULL);
366 }
367 \f
368 /**********************************************************************
369  *                                      LoadBitmap
370  */
371 HBITMAP
372 LoadBitmap(HANDLE instance, LPSTR bmp_name)
373 {
374     HBITMAP hbitmap;
375     HANDLE rsc_mem;
376     HDC hdc;
377     long *lp;
378     int image_size;
379
380 #ifdef DEBUG_RESOURCE
381     printf("LoadBitmap: instance = %04x, name = %08x\n",
382            instance, bmp_name);
383 #endif
384     
385     if (!(hdc = GetDC( 0 ))) return 0;
386
387     rsc_mem = RSC_LoadResource(instance, bmp_name, NE_RSCTYPE_BITMAP, 
388                                &image_size);
389     lp = (long *) GlobalLock(rsc_mem);
390     if (lp == NULL)
391     {
392         GlobalFree(rsc_mem);
393         return 0;
394     }
395
396     if (*lp == sizeof(BITMAPCOREHEADER))
397         hbitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lp );
398     else if (*lp == sizeof(BITMAPINFOHEADER))
399         hbitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lp );
400     else hbitmap = 0;
401
402     GlobalFree(rsc_mem);
403     ReleaseDC( 0, hdc );
404     return hbitmap;
405 }