wrc: Change the format of the output of "wrc --verify-translation".
[wine] / tools / wrc / dumpres.c
1 /*
2  * Copyright 1998 Bertho A. Stultiens (BS)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <ctype.h>
24
25 #include "wrc.h"
26 #include "dumpres.h"
27
28 /*
29  *****************************************************************************
30  * Function     : get_typename
31  * Syntax       : char *get_typename(resource_t* r)
32  * Input        :
33  *      r       - Resource description
34  * Output       : A pointer to a string representing the resource type
35  * Description  :
36  * Remarks      :
37  *****************************************************************************
38 */
39 const char *get_typename(const resource_t* r)
40 {
41         switch(r->type){
42         case res_acc:   return "ACCELERATOR";
43         case res_bmp:   return "BITMAP";
44         case res_cur:   return "CURSOR";
45         case res_curg:  return "GROUP_CURSOR";
46         case res_dlg:   return "DIALOG";
47         case res_dlgex: return "DIALOGEX";
48         case res_fnt:   return "FONT";
49         case res_ico:   return "ICON";
50         case res_icog:  return "GROUP_ICON";
51         case res_men:   return "MENU";
52         case res_menex: return "MENUEX";
53         case res_rdt:   return "RCDATA";
54         case res_stt:   return "STRINGTABLE";
55         case res_usr:   return "UserResource";
56         case res_msg:   return "MESSAGETABLE";
57         case res_ver:   return "VERSIONINFO";
58         case res_dlginit: return "DLGINIT";
59         case res_toolbar: return "TOOLBAR";
60         case res_anicur:  return "CURSOR (animated)";
61         case res_aniico:  return "ICON (animated)";
62         default:        return "Unknown";
63         }
64 }
65
66 /*
67  *****************************************************************************
68  * Function     : strncpyWtoA
69  * Syntax       : char *strncpyWtoA(char *cs, short *ws, int maxlen)
70  * Input        :
71  *      cs      - Pointer to buffer to receive result
72  *      ws      - Source wide-string
73  *      maxlen  - Max chars to copy
74  * Output       : 'cs'
75  * Description  : Copy a unicode string to ascii. Copying stops after the
76  *                first occurring '\0' or when maxlen-1 chars are copied. The
77  *                String is always nul terminated.
78  * Remarks      : No codepage translation is done.
79  *****************************************************************************
80 */
81 static char *strncpyWtoA(char *cs, const WCHAR *ws, int maxlen)
82 {
83         char *cptr = cs;
84         const WCHAR *wsMax = ws + maxlen - 1;
85         while(*ws && ws < wsMax)
86         {
87                 if(*ws > 255)
88                         fprintf(stderr, "***Warning: Unicode string contains non-printable chars***\n");
89                 *cptr++ = (char)*ws++;
90         }
91         *cptr = '\0';
92         return cs;
93 }
94
95 /*
96  *****************************************************************************
97  * Function     : print_string
98  * Syntax       : void print_string(string_t *str)
99  * Input        :
100  * Output       :
101  * Description  :
102  * Remarks      :
103  *****************************************************************************
104 */
105 static void print_string(const string_t *str)
106 {
107         char buffer[512];
108         if(!str)
109                 printf("<none>");
110         else if(str->type == str_char)
111                 printf("\"%s\"", str->str.cstr);
112         else
113         {
114                 strncpyWtoA(buffer, str->str.wstr, sizeof(buffer));
115                 printf("L\"%s\"", buffer);
116         }
117 }
118
119 /*
120  *****************************************************************************
121  * Function     : get_nameid_str
122  * Syntax       : const char *get_nameid_str(const name_id_t *n)
123  * Input        :
124  *      n       - nameid to convert to text
125  * Output       : A pointer to the name.
126  * Description  :
127  * Remarks      : Not reentrant because of static buffer
128  *****************************************************************************
129 */
130 const char *get_nameid_str(const name_id_t *n)
131 {
132         static char buffer[256];
133
134         if(!n)
135                 return "<none>";
136
137         if(n->type == name_ord)
138         {
139                 sprintf(buffer, "%d", n->name.i_name);
140                 return buffer;
141         }
142         else if(n->type == name_str)
143         {
144                 if(n->name.s_name->type == str_char)
145                         return n->name.s_name->str.cstr;
146                 else
147                 {
148                         strncpyWtoA(buffer, n->name.s_name->str.wstr, sizeof(buffer));
149                         return buffer;
150                 }
151         }
152         else
153                 return "Hoooo, report this: wrong type in nameid";
154 }
155
156 /*
157  *****************************************************************************
158  * Function     : dump_memopt
159  * Syntax       : void dump_memopt(DWORD memopt)
160  * Input        :
161  *      memopt  - flag bits of the options set
162  * Output       :
163  * Description  :
164  * Remarks      :
165  *****************************************************************************
166 */
167 static void dump_memopt(DWORD memopt)
168 {
169         printf("Memory/load options: ");
170         if(memopt & 0x0040)
171                 printf("PRELOAD ");
172         else
173                 printf("LOADONCALL ");
174         if(memopt & 0x0010)
175                 printf("MOVEABLE ");
176         else
177                 printf("FIXED ");
178         if(memopt & 0x0020)
179                 printf("PURE ");
180         else
181                 printf("IMPURE ");
182         if(memopt & 0x1000)
183                 printf("DISCARDABLE");
184         printf("\n");
185 }
186
187 /*
188  *****************************************************************************
189  * Function     : dump_lvc
190  * Syntax       : void dump_lvc(const lvc_t *l)
191  * Input        :
192  *      l       - pointer to lvc structure
193  * Output       :
194  * Description  : Dump language, version and characteristics
195  * Remarks      :
196  *****************************************************************************
197 */
198 static void dump_lvc(const lvc_t *l)
199 {
200         if(l->language)
201                 printf("LANGUAGE %04x, %04x\n", l->language->id, l->language->sub);
202         else
203                 printf("LANGUAGE <not set>\n");
204
205         if(l->version)
206                 printf("VERSION %08x\n", *(l->version));
207         else
208                 printf("VERSION <not set>\n");
209
210         if(l->characts)
211                 printf("CHARACTERISTICS %08x\n", *(l->characts));
212         else
213                 printf("CHARACTERISTICS <not set>\n");
214 }
215
216 /*
217  *****************************************************************************
218  * Function     : dump_raw_data
219  * Syntax       : void dump_raw_data(const raw_data_t *d)
220  * Input        :
221  *      d       - Raw data descriptor
222  * Output       :
223  * Description  :
224  * Remarks      :
225  *****************************************************************************
226 */
227 static void dump_raw_data(const raw_data_t *d)
228 {
229         unsigned int n;
230         int i;
231         int j;
232
233         if(!d)
234         {
235                 printf("<none>");
236                 return;
237         }
238         printf("Rawdata size: %d\n", d->size);
239         if(debuglevel < 2)
240                 return;
241
242         for(n = 0; n < d->size; n++)
243         {
244                 if((n % 16) == 0)
245                 {
246                         if(n)
247                         {
248                                 printf("- ");
249                                 for(i = 0; i < 16; i++)
250                                         printf("%c", isprint(d->data[n-16+i] & 0xff) ? d->data[n-16+i] : '.');
251                                 printf("\n%08x: ", n);
252                         }
253                         else
254                                 printf("%08x: ", n);
255                 }
256                 printf("%02x ", d->data[n] & 0xff);
257         }
258         printf("- ");
259         j = d->size % 16;
260         if(!j)
261                 j = 16;
262         for(i = 0; i < j; i++)
263                 printf("%c", isprint(d->data[n-j+i] & 0xff) ? d->data[n-j+i] : '.');
264         printf("\n");
265 }
266
267 /*
268  *****************************************************************************
269  * Function     : dump_accelerator
270  * Syntax       : void dump_accelerator(const accelerator_t *acc)
271  * Input        :
272  *      acc     - Accelerator resource descriptor
273  * Output       : nop
274  * Description  :
275  * Remarks      :
276  *****************************************************************************
277 */
278 static void dump_accelerator(const accelerator_t *acc)
279 {
280         event_t *ev = acc->events;
281
282         dump_memopt(acc->memopt);
283         dump_lvc(&(acc->lvc));
284
285         printf("Events: %s\n", ev ? "" : "<none>");
286         while(ev)
287         {
288                 printf("Key=");
289                 if(isprint(ev->key))
290                         printf("\"%c\"", ev->key);
291                 else if(iscntrl(ev->key))
292                         printf("\"^%c\"", ev->key +'@');
293                 else
294                         printf("\\x%02x", ev->key & 0xff);
295
296                 printf(" Id=%d flags=%04x\n", ev->id, ev->flags);
297                 ev = ev->next;
298         }
299 }
300
301 /*
302  *****************************************************************************
303  * Function     : dump_cursor
304  * Syntax       : void dump_cursor(const cursor_t *cur)
305  * Input        :
306  *      cur     - Cursor resource descriptor
307  * Output       : nop
308  * Description  :
309  * Remarks      :
310  *****************************************************************************
311 */
312 static void dump_cursor(const cursor_t *cur)
313 {
314         printf("Id: %d\n", cur->id);
315         printf("Width: %d\n", cur->width);
316         printf("Height: %d\n", cur->height);
317         printf("X Hotspot: %d\n", cur->xhot);
318         printf("Y Hotspot: %d\n", cur->yhot);
319         dump_raw_data(cur->data);
320 }
321
322 /*
323  *****************************************************************************
324  * Function     : dump_cursor_group
325  * Syntax       : void dump_cursor_group(const cursor_group_t *cur)
326  * Input        :
327  *      cur     - Cursor group resource descriptor
328  * Output       : nop
329  * Description  :
330  * Remarks      :
331  *****************************************************************************
332 */
333 static void dump_cursor_group(const cursor_group_t *curg)
334 {
335         dump_memopt(curg->memopt);
336         printf("There are %d cursors in this group\n", curg->ncursor);
337 }
338
339 /*
340  *****************************************************************************
341  * Function     : dump_icon
342  * Syntax       : void dump_icon(const icon_t *ico)
343  * Input        :
344  *      ico     - Icon resource descriptor
345  * Output       : nop
346  * Description  :
347  * Remarks      :
348  *****************************************************************************
349 */
350 static void dump_icon(const icon_t *ico)
351 {
352         printf("Id: %d\n", ico->id);
353         printf("Width: %d\n", ico->width);
354         printf("Height: %d\n", ico->height);
355         printf("NColor: %d\n", ico->nclr);
356         printf("NPlanes: %d\n", ico->planes);
357         printf("NBits: %d\n", ico->bits);
358         dump_raw_data(ico->data);
359 }
360
361 /*
362  *****************************************************************************
363  * Function     : dump_icon_group
364  * Syntax       : void dump_icon_group(const icon_group_t *ico)
365  * Input        :
366  *      ico     - Icon group resource descriptor
367  * Output       : nop
368  * Description  :
369  * Remarks      :
370  *****************************************************************************
371 */
372 static void dump_icon_group(const icon_group_t *icog)
373 {
374         dump_memopt(icog->memopt);
375         printf("There are %d icons in this group\n", icog->nicon);
376 }
377
378 /*
379  *****************************************************************************
380  * Function     : dump_ani_curico
381  * Syntax       : void dump_ani_curico(const ani_curico_t *ani)
382  * Input        :
383  *      ani     - Animated object resource descriptor
384  * Output       : nop
385  * Description  :
386  * Remarks      :
387  *****************************************************************************
388 */
389 static void dump_ani_curico(const ani_curico_t *ani)
390 {
391         dump_memopt(ani->memopt);
392         dump_lvc(&ani->data->lvc);
393         dump_raw_data(ani->data);
394 }
395
396 /*
397  *****************************************************************************
398  * Function     : dump_font
399  * Syntax       : void dump_font(const font_t *fnt)
400  * Input        :
401  *      fnt     - Font resource descriptor
402  * Output       : nop
403  * Description  :
404  * Remarks      :
405  *****************************************************************************
406 */
407 static void dump_font(const font_t *fnt)
408 {
409         dump_memopt(fnt->memopt);
410         dump_lvc(&(fnt->data->lvc));
411         dump_raw_data(fnt->data);
412 }
413
414 /*
415  *****************************************************************************
416  * Function     : dump_bitmap
417  * Syntax       : void dump_bitmap(const bitmap_t *bmp)
418  * Input        :
419  *      bmp     - Bitmap resource descriptor
420  * Output       : nop
421  * Description  :
422  * Remarks      :
423  *****************************************************************************
424 */
425 static void dump_bitmap(const bitmap_t *bmp)
426 {
427         dump_memopt(bmp->memopt);
428         dump_lvc(&(bmp->data->lvc));
429         dump_raw_data(bmp->data);
430 }
431
432 /*
433  *****************************************************************************
434  * Function     : dump_rcdata
435  * Syntax       : void dump_rcdata(const rcdata_t *rdt)
436  * Input        :
437  *      rdt     - RCData resource descriptor
438  * Output       : nop
439  * Description  :
440  * Remarks      :
441  *****************************************************************************
442 */
443 static void dump_rcdata(const rcdata_t *rdt)
444 {
445         dump_memopt(rdt->memopt);
446         dump_lvc(&(rdt->data->lvc));
447         dump_raw_data(rdt->data);
448 }
449
450 /*
451  *****************************************************************************
452  * Function     : dump_user
453  * Syntax       : void dump_user(const user_t *usr)
454  * Input        :
455  *      usr     - User resource descriptor
456  * Output       : nop
457  * Description  :
458  * Remarks      :
459  *****************************************************************************
460 */
461 static void dump_user(const user_t *usr)
462 {
463         dump_memopt(usr->memopt);
464         dump_lvc(&(usr->data->lvc));
465         printf("Class %s\n", get_nameid_str(usr->type));
466         dump_raw_data(usr->data);
467 }
468
469 /*
470  *****************************************************************************
471  * Function     : dump_messagetable
472  * Syntax       : void dump_messagetable(const messagetable_t *msg)
473  * Input        :
474  *      msg     - Messagetable resource descriptor
475  * Output       : nop
476  * Description  :
477  * Remarks      :
478  *****************************************************************************
479 */
480 static void dump_messagetable(const messagetable_t *msg)
481 {
482         dump_memopt(msg->memopt);
483         dump_lvc(&(msg->data->lvc));
484         dump_raw_data(msg->data);
485 }
486
487 /*
488  *****************************************************************************
489  * Function     : dump_stringtable
490  * Syntax       : void dump_stringtable(const stringtable_t *stt)
491  * Input        :
492  *      stt     - Stringtable resource descriptor
493  * Output       : nop
494  * Description  :
495  * Remarks      :
496  *****************************************************************************
497 */
498 static void dump_stringtable(const stringtable_t *stt)
499 {
500         int i;
501         for(; stt; stt = stt->next)
502         {
503                 printf("{\n");
504                 dump_memopt(stt->memopt);
505                 dump_lvc(&(stt->lvc));
506                 for(i = 0; i < stt->nentries; i++)
507                 {
508                         printf("Id=%-5d (%d) ", stt->idbase+i, stt->entries[i].id);
509                         if(stt->entries[i].str)
510                                 print_string(stt->entries[i].str);
511                         else
512                                 printf("<none>");
513                         printf("\n");
514                 }
515                 printf("}\n");
516         }
517 }
518
519 /*
520  *****************************************************************************
521  * Function     : dump_control
522  * Syntax       : void dump_control(const control_t *ctrl)
523  * Input        :
524  *      ctrl    - Control resource descriptor
525  * Output       :
526  * Description  :
527  * Remarks      :
528  *****************************************************************************
529 */
530 static void dump_control(const control_t *ctrl)
531 {
532         printf("Control {\n\tClass: %s\n", get_nameid_str(ctrl->ctlclass));
533         printf("\tText: "); get_nameid_str(ctrl->title); printf("\n");
534         printf("\tId: %d\n", ctrl->id);
535         printf("\tx, y, w, h: %d, %d, %d, %d\n", ctrl->x, ctrl->y, ctrl->width, ctrl->height);
536         if(ctrl->gotstyle)
537         {
538                 assert(ctrl->style != NULL);
539                 assert(ctrl->style->and_mask == 0);
540                 printf("\tStyle: %08x\n", ctrl->style->or_mask);
541         }
542         if(ctrl->gotexstyle)
543         {
544                 assert(ctrl->exstyle != NULL);
545                 assert(ctrl->exstyle->and_mask == 0);
546                 printf("\tExStyle: %08x\n", ctrl->exstyle->or_mask);
547         }
548         if(ctrl->gothelpid)
549                 printf("\tHelpid: %d\n", ctrl->helpid);
550         if(ctrl->extra)
551         {
552                 printf("\t");
553                 dump_raw_data(ctrl->extra);
554         }
555         printf("}\n");
556 }
557
558 /*
559  *****************************************************************************
560  * Function     : dump_dialog
561  * Syntax       : void dump_dialog(const dialog_t *dlg)
562  * Input        :
563  *      dlg     - Dialog resource descriptor
564  * Output       :
565  * Description  :
566  * Remarks      :
567  *****************************************************************************
568 */
569 static void dump_dialog(const dialog_t *dlg)
570 {
571         control_t *c = dlg->controls;
572
573         dump_memopt(dlg->memopt);
574         dump_lvc(&(dlg->lvc));
575         printf("x, y, w, h: %d, %d, %d, %d\n", dlg->x, dlg->y, dlg->width, dlg->height);
576         if(dlg->gotstyle)
577         {
578                 assert(dlg->style != NULL);
579                 assert(dlg->style->and_mask == 0);
580                 printf("Style: %08x\n", dlg->style->or_mask);
581
582         }
583         if(dlg->gotexstyle)
584         {
585                 assert(dlg->exstyle != NULL);
586                 assert(dlg->exstyle->and_mask == 0);
587                 printf("ExStyle: %08x\n", dlg->exstyle->or_mask);
588         }
589         printf("Menu: %s\n", get_nameid_str(dlg->menu));
590         printf("Class: %s\n", get_nameid_str(dlg->dlgclass));
591         printf("Title: "); print_string(dlg->title); printf("\n");
592         printf("Font: ");
593         if(!dlg->font)
594                 printf("<none>\n");
595         else
596         {
597                 printf("%d, ", dlg->font->size);
598                 print_string(dlg->font->name);
599                 printf("\n");
600         }
601         while(c)
602         {
603                 dump_control(c);
604                 c = c->next;
605         }
606 }
607
608 /*
609  *****************************************************************************
610  * Function     : dump_dialogex
611  * Syntax       : void dump_dialogex(const dialogex_t *dlgex)
612  * Input        :
613  *      dlgex   - DialogEx resource descriptor
614  * Output       :
615  * Description  :
616  * Remarks      :
617  *****************************************************************************
618 */
619 static void dump_dialogex(const dialogex_t *dlgex)
620 {
621         const control_t *c = dlgex->controls;
622
623         dump_memopt(dlgex->memopt);
624         dump_lvc(&(dlgex->lvc));
625         printf("x, y, w, h: %d, %d, %d, %d\n", dlgex->x, dlgex->y, dlgex->width, dlgex->height);
626         if(dlgex->gotstyle)
627         {
628                 assert(dlgex->style != NULL);
629                 assert(dlgex->style->and_mask == 0);
630                 printf("Style: %08x\n", dlgex->style->or_mask);
631         }
632         if(dlgex->gotexstyle)
633         {
634                 assert(dlgex->exstyle != NULL);
635                 assert(dlgex->exstyle->and_mask == 0);
636                 printf("ExStyle: %08x\n", dlgex->exstyle->or_mask);
637         }
638         if(dlgex->gothelpid)
639                 printf("Helpid: %d\n", dlgex->helpid);
640         printf("Menu: %s\n", get_nameid_str(dlgex->menu));
641         printf("Class: %s\n", get_nameid_str(dlgex->dlgclass));
642         printf("Title: "); print_string(dlgex->title); printf("\n");
643         printf("Font: ");
644         if(!dlgex->font)
645                 printf("<none>\n");
646         else
647         {
648                 printf("%d, ", dlgex->font->size);
649                 print_string(dlgex->font->name);
650                 printf(", %d, %d\n", dlgex->font->weight, dlgex->font->italic);
651         }
652         while(c)
653         {
654                 dump_control(c);
655                 c = c->next;
656         }
657 }
658
659 /*
660  *****************************************************************************
661  * Function     : dump_menu_item
662  * Syntax       : void dump_menu_item(const menu_item_t *item)
663  * Input        :
664  * Output       :
665  * Description  :
666  * Remarks      :
667  *****************************************************************************
668 */
669 static void dump_menu_item(const menu_item_t *item)
670 {
671         while(item)
672         {
673                 if(item->popup)
674                 {
675                         printf("POPUP ");
676                         print_string(item->name);
677                         printf("\n");
678                         dump_menu_item(item->popup);
679                 }
680                 else
681                 {
682                         printf("MENUITEM ");
683                         if(item->name)
684                         {
685                                 print_string(item->name);
686                                 printf(", %d, %08x", item->id, item->state);
687                         }
688                         else
689                                 printf("SEPARATOR");
690                         printf("\n");
691                 }
692                 item = item->next;
693         }
694 }
695
696 /*
697  *****************************************************************************
698  * Function     : dump_menu
699  * Syntax       : void dump_menu(const menu_t *men)
700  * Input        :
701  *      men     - Menu resource descriptor
702  * Output       :
703  * Description  :
704  * Remarks      :
705  *****************************************************************************
706 */
707 static void dump_menu(const menu_t *men)
708 {
709         dump_memopt(men->memopt);
710         dump_lvc(&(men->lvc));
711         dump_menu_item(men->items);
712 }
713
714 /*
715  *****************************************************************************
716  * Function     : dump_menuex_item
717  * Syntax       : void dump_menuex_item(const menuex_item_t *item)
718  * Input        :
719  * Output       :
720  * Description  :
721  * Remarks      :
722  *****************************************************************************
723 */
724 static void dump_menuex_item(const menuex_item_t *item)
725 {
726         while(item)
727         {
728                 if(item->popup)
729                 {
730                         printf("POPUP ");
731                         print_string(item->name);
732                         if(item->gotid)
733                                 printf(", Id=%d", item->id);
734                         if(item->gottype)
735                                 printf(", Type=%d", item->type);
736                         if(item->gotstate)
737                                 printf(", State=%08x", item->state);
738                         if(item->gothelpid)
739                                 printf(", HelpId=%d", item->helpid);
740                         printf("\n");
741                         dump_menuex_item(item->popup);
742                 }
743                 else
744                 {
745                         printf("MENUITEM ");
746                         if(item->name)
747                         {
748                                 print_string(item->name);
749                                 if(item->gotid)
750                                         printf(", Id=%d", item->id);
751                                 if(item->gottype)
752                                         printf(", Type=%d", item->type);
753                                 if(item->gotstate)
754                                         printf(", State=%08x", item->state);
755                                 if(item->gothelpid)
756                                         printf(", HelpId=%d", item->helpid);
757                         }
758                         else
759                                 printf("SEPARATOR");
760                         printf("\n");
761                 }
762                 item = item->next;
763         }
764 }
765
766 /*
767  *****************************************************************************
768  * Function     : dump_menuex
769  * Syntax       : void dump_menuex(const menuex_t *menex)
770  * Input        :
771  *      menex   - MenuEx resource descriptor
772  * Output       :
773  * Description  :
774  * Remarks      :
775  *****************************************************************************
776 */
777 static void dump_menuex(const menuex_t *menex)
778 {
779         dump_memopt(menex->memopt);
780         dump_lvc(&(menex->lvc));
781         dump_menuex_item(menex->items);
782 }
783
784 /*
785  *****************************************************************************
786  * Function     : dump_ver_value
787  * Syntax       : void dump_ver_value(const ver_value_t *val)
788  * Input        :
789  * Output       :
790  * Description  :
791  * Remarks      :
792  *****************************************************************************
793 */
794 static void dump_ver_block(const ver_block_t *);        /* Forward ref */
795
796 static void dump_ver_value(const ver_value_t *val)
797 {
798         if(val->type == val_str)
799         {
800                 printf("VALUE ");
801                 print_string(val->key);
802                 printf(" ");
803                 print_string(val->value.str);
804                 printf("\n");
805         }
806         else if(val->type == val_words)
807         {
808                 int i;
809                 printf("VALUE");
810                 print_string(val->key);
811                 for(i = 0; i < val->value.words->nwords; i++)
812                         printf(" %04x", val->value.words->words[i]);
813                 printf("\n");
814         }
815         else if(val->type == val_block)
816         {
817                 dump_ver_block(val->value.block);
818         }
819 }
820
821 /*
822  *****************************************************************************
823  * Function     : dump_ver_block
824  * Syntax       : void dump_ver_block(const ver_block_t *blk)
825  * Input        :
826  * Output       :
827  * Description  :
828  * Remarks      :
829  *****************************************************************************
830 */
831 static void dump_ver_block(const ver_block_t *blk)
832 {
833         const ver_value_t *val = blk->values;
834         printf("BLOCK ");
835         print_string(blk->name);
836         printf("\n{\n");
837         while(val)
838         {
839                 dump_ver_value(val);
840                 val = val->next;
841         }
842         printf("}\n");
843 }
844
845 /*
846  *****************************************************************************
847  * Function     : dump_versioninfo
848  * Syntax       : void dump_versioninfo(const versioninfo_t *ver)
849  * Input        :
850  *      ver     - Versioninfo resource descriptor
851  * Output       :
852  * Description  :
853  * Remarks      :
854  *****************************************************************************
855 */
856 static void dump_versioninfo(const versioninfo_t *ver)
857 {
858         const ver_block_t *blk = ver->blocks;
859
860         dump_lvc(&(ver->lvc));
861
862         if(ver->gotit.fv)
863                 printf("FILEVERSION %04x, %04x, %04x, %04x\n",
864                         ver->filever_maj1,
865                         ver->filever_maj2,
866                         ver->filever_min1,
867                         ver->filever_min2);
868         if(ver->gotit.pv)
869                 printf("PRODUCTVERSION %04x, %04x, %04x, %04x\n",
870                         ver->prodver_maj1,
871                         ver->prodver_maj2,
872                         ver->prodver_min1,
873                         ver->prodver_min2);
874         if(ver->gotit.fo)
875                 printf("FILEOS %08x\n", ver->fileos);
876         if(ver->gotit.ff)
877                 printf("FILEFLAGS %08x\n", ver->fileflags);
878         if(ver->gotit.ffm)
879                 printf("FILEFLAGSMASK %08x\n", ver->fileflagsmask);
880         if(ver->gotit.ft)
881                 printf("FILETYPE %08x\n", ver->filetype);
882         if(ver->gotit.fst)
883                 printf("FILESUBTYPE %08x\n", ver->filesubtype);
884         while(blk)
885         {
886                 dump_ver_block(blk);
887                 blk = blk->next;
888         }
889 }
890
891 /*
892  *****************************************************************************
893  * Function     : dump_toolbar_item
894  * Syntax       : void dump_toolbar_item(const toolbar_item_t *item)
895  * Input        :
896  * Output       :
897  * Description  :
898  * Remarks      :
899  *****************************************************************************
900 */
901 static void dump_toolbar_items(const toolbar_item_t *items)
902 {
903         while(items)
904         {
905                 if(items->id)
906                         printf("   BUTTON %d", items->id );
907                 else
908                         printf("   SEPARATOR");
909
910                 printf("\n");
911
912                 items = items->next;
913         }
914 }
915
916 /*
917  *****************************************************************************
918  * Function     : dump_toolbar
919  * Syntax       : void dump_toolbar(const toolbar_t *toolbar)
920  * Input        :
921  *      toolbar - Toolbar resource descriptor
922  * Output       :
923  * Description  :
924  * Remarks      :
925  *****************************************************************************
926 */
927 static void dump_toolbar(const toolbar_t *toolbar)
928 {
929         dump_memopt(toolbar->memopt);
930         dump_lvc(&(toolbar->lvc));
931         dump_toolbar_items(toolbar->items);
932 }
933
934 /*
935  *****************************************************************************
936  * Function     : dump_dlginit
937  * Syntax       : void dump_dlginit(const dlginit_t *dit)
938  * Input        :
939  *      dit     - DlgInit resource descriptor
940  * Output       :
941  * Description  :
942  * Remarks      :
943  *****************************************************************************
944 */
945 static void dump_dlginit(const dlginit_t *dit)
946 {
947         dump_memopt(dit->memopt);
948         dump_lvc(&(dit->data->lvc));
949         dump_raw_data(dit->data);
950 }
951
952 /*
953  *****************************************************************************
954  * Function     : dump_resources
955  * Syntax       : void dump_resources(const resource_t *top)
956  * Input        :
957  *      top     - Top of the resource tree
958  * Output       :
959  *      nop
960  * Description  : Dump the parsed resource-tree to stdout
961  * Remarks      :
962  *****************************************************************************
963 */
964 void dump_resources(const resource_t *top)
965 {
966         printf("Internal resource-tree dump:\n");
967         while(top)
968         {
969                 printf("Resource: %s\nId: %s\n",
970                        get_typename(top),
971                        get_nameid_str(top->name));
972                 switch(top->type)
973                 {
974                 case res_acc:
975                         dump_accelerator(top->res.acc);
976                         break;
977                 case res_bmp:
978                         dump_bitmap(top->res.bmp);
979                         break;
980                 case res_cur:
981                         dump_cursor(top->res.cur);
982                         break;
983                 case res_curg:
984                         dump_cursor_group(top->res.curg);
985                         break;
986                 case res_dlg:
987                         dump_dialog(top->res.dlg);
988                         break;
989                 case res_dlgex:
990                         dump_dialogex(top->res.dlgex);
991                         break;
992                 case res_fnt:
993                         dump_font(top->res.fnt);
994                         break;
995                 case res_icog:
996                         dump_icon_group(top->res.icog);
997                         break;
998                 case res_ico:
999                         dump_icon(top->res.ico);
1000                         break;
1001                 case res_men:
1002                         dump_menu(top->res.men);
1003                         break;
1004                 case res_menex:
1005                         dump_menuex(top->res.menex);
1006                         break;
1007                 case res_rdt:
1008                         dump_rcdata(top->res.rdt);
1009                         break;
1010                 case res_stt:
1011                         dump_stringtable(top->res.stt);
1012                         break;
1013                 case res_usr:
1014                         dump_user(top->res.usr);
1015                         break;
1016                 case res_msg:
1017                         dump_messagetable(top->res.msg);
1018                         break;
1019                 case res_ver:
1020                         dump_versioninfo(top->res.ver);
1021                         break;
1022                 case res_dlginit:
1023                         dump_dlginit(top->res.dlgi);
1024                         break;
1025                 case res_toolbar:
1026                         dump_toolbar(top->res.tbt);
1027                         break;
1028                 case res_anicur:
1029                 case res_aniico:
1030                         dump_ani_curico(top->res.ani);
1031                         break;
1032                 default:
1033                         printf("Report this: Unknown resource type parsed %08x\n", top->type);
1034                 }
1035                 printf("\n");
1036                 top = top->next;
1037         }
1038 }