]> git.saurik.com Git - wxWidgets.git/blob - contrib/utils/convertrc/rc2xml.cpp
updated resources convertor
[wxWidgets.git] / contrib / utils / convertrc / rc2xml.cpp
1 // rc2xml.cpp: implementation of the rc2xml class.
2 //Author: Brian Gavin 9/24/00
3 //License: wxWindows License
4 /*
5 How to use:
6 #include "rc2xml.h"
7 ...
8 rc2xml trans;
9 trans->Convert("Myfile.rc","Myfile.xml");
10 */
11 /* TODO
12 1. Figure how to fix memory leaks in all wxLists in this class
13 2. Find a way to rename MS Windows fonts so that they work
14 cross platform (wxGTK,etc)
15 3. Be able to abort incorrectly formated files without crashing
16 */
17
18 #ifdef __GNUG__
19 #pragma implementation "rc2xml.cpp"
20 #pragma interface "rc2xml.cpp"
21 #endif
22
23 // For compilers that support precompilation, includes "wx/wx.h".
24 #include <wx/wxprec.h>
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 // for all others, include the necessary headers (this file is usually all you
31 // need because it includes almost all "standard" wxWindows headers
32 #ifndef WX_PRECOMP
33 #include <wx/wx.h>
34 #endif
35
36
37 #include "rc2xml.h"
38 #include "wx/image.h"
39 #include "wx/resource.h"
40 #include <wx/textfile.h>
41 #include <wx/tokenzr.h>
42
43
44
45 //////////////////////////////////////////////////////////////////////
46 // Construction/Destruction
47 //////////////////////////////////////////////////////////////////////
48
49 rc2xml::rc2xml()
50 {
51 m_done=FALSE;
52 m_bitmaplist=new wxList(wxKEY_STRING);
53 m_stringtable=new wxList(wxKEY_STRING);
54 m_iconlist = new wxList(wxKEY_STRING);
55 m_resourcelist =new wxList(wxKEY_INTEGER);
56 }
57
58 rc2xml::~rc2xml()
59 {
60 delete m_bitmaplist;
61 delete m_stringtable;
62 delete m_iconlist;
63 delete m_resourcelist;
64 }
65
66 bool rc2xml::Convert(wxString rcfile, wxString xmlfile)
67 {
68 m_rc.Open(rcfile.c_str());
69 m_filesize=m_rc.Length();
70
71 bool result;
72 result=m_xmlfile.Open(xmlfile.c_str(),"w+t");
73 wxASSERT_MSG(result,"Couldn't create XML file");
74 if (!result)
75 return FALSE;
76
77
78 /* Write Basic header for XML file */
79 m_xmlfile.Write("<?xml version=\"1.0\" ?>\n");
80 m_xmlfile.Write("<resource>\n");
81
82 //Read resource.h
83 ParseResourceHeader();
84 //Gather all the resource we need for toolbars,menus, and etc
85 FirstPass();
86 m_done=FALSE;
87 m_rc.Seek(0);
88 //Read in dialogs, toolbars,menus
89 SecondPass();
90
91 m_xmlfile.Write("</resource>\n");
92 m_xmlfile.Close();
93 m_rc.Close();
94
95 return TRUE;
96 }
97
98
99 void rc2xml::ParseDialog(wxString dlgname)
100 {
101 wxString token;
102 static int dlgid=999;
103 dlgid++;
104 /* Make sure that this really is a dialog
105 microsoft reuses the keyword DIALOG for other things
106 */
107 token=PeekToken();
108 //Microsoft notation?
109 if (token=="DISCARDABLE")
110 {
111 token=GetToken();
112 token=PeekToken();
113 }
114 //Error isn't a Dialog resource eject eject
115 if (!token.IsNumber())
116 return;
117
118 //Record x,y,width,height
119 int x,y,width,height;
120 ReadRect(x,y,width,height);
121 //Get Title
122 token=GetToken();
123 wxString title;
124 wxString ptsize,face;
125
126 m_xmlfile.Write("\t<dialog");
127 //Avoid duplicate names this way
128 dlgname.Replace("IDD_","DLG_");
129 WriteBasicInfo(x,y,width,height,dlgname);
130 WriteTitle(title);
131
132
133 while ((token!="BEGIN")&(token!="{"))
134 {
135 if (token=="CAPTION")
136 {
137 title=GetQuoteField();
138 }
139
140 //TODO fix face name so that it is cross platform name
141 // FONT 8, "MS Sans Serif"
142 if (token=="FONT")
143 {
144 ptsize=GetToken();
145 face=GetQuoteField();
146 m_xmlfile.Write("\t\t<font>\n");
147 m_xmlfile.Write("\t\t\t<size>"+ptsize+"</size>\n");
148 m_xmlfile.Write("\t\t\t<face>"+face+"</face>\n");
149 m_xmlfile.Write("\t\t</font>\n");
150 }
151
152 token=GetToken();
153 }
154
155 m_xmlfile.Write("\t<children>\n");
156 ParseControls();
157 m_xmlfile.Write("\t</children>\n");
158 m_xmlfile.Write("\t</dialog>\n");
159 }
160
161 /*
162 BEGIN
163 EDITTEXT IDC_BANDS,36,83,22,14,ES_AUTOHSCROLL | ES_NUMBER | NOT
164 WS_TABSTOP
165 LTEXT "Bands",IDC_STATIC,11,86,21,8
166 EDITTEXT IDC_NAME,10,3,75,14,ES_AUTOHSCROLL
167 END
168 */
169 void rc2xml::ParseControls()
170 {
171 wxString token;
172
173 token=GetToken();
174 while ((token!="END")&(token!="}"))
175 {
176 if (token=="LTEXT")
177 ParseStaticText();
178 else if (token=="EDITTEXT")
179 ParseTextCtrl();
180 else if (token=="PUSHBUTTON")
181 ParsePushButton();
182 else if (token=="DEFPUSHBUTTON")
183 ParsePushButton();
184 else if (token=="GROUPBOX")
185 ParseGroupBox();
186 else if (token=="COMBOBOX")
187 ParseComboBox();
188 else if (token=="CONTROL")
189 ParseControlMS();
190 else if (token=="LISTBOX")
191 ParseListBox();
192 else if (token=="ICON")
193 ParseIconStatic();
194 else if (token=="SCROLLBAR")
195 ParseScrollBar();
196 token=GetToken();
197 }
198
199 }
200 //LTEXT "Radius",IDC_STATIC,9,67,23,8
201 void rc2xml::ParseStaticText()
202 {
203 wxString token;
204 wxString phrase,varname;
205 phrase=GetQuoteField();
206 varname=GetToken();
207 int x,y,width,height;
208 ReadRect(x,y,width,height);
209
210 m_xmlfile.Write("\t\t<statictext");
211 WriteBasicInfo(x,y,width,height,varname);WriteLabel(phrase);
212 m_xmlfile.Write("\t\t</statictext>\n");
213
214 }
215 //EDITTEXT IDC_RADIUS,36,65,40,14,ES_AUTOHSCROLL
216 void rc2xml::ParseTextCtrl()
217 {
218 wxString token;
219 wxString varname,style;
220 varname=GetToken();
221 int x,y,width,height;
222 ReadRect(x,y,width,height);
223 //TODO
224 //style=GetToken();
225 m_xmlfile.Write("\t\t<textctrl");
226 WriteBasicInfo(x,y,width,height,varname);
227 m_xmlfile.Write("\t\t</textctrl>\n");
228
229 }
230 //PUSHBUTTON "Create/Update",IDC_CREATE,15,25,53,13,NOT WS_TABSTOP
231 void rc2xml::ParsePushButton()
232 {
233 wxString token;
234 wxString phrase,varname;
235 phrase=GetQuoteField();
236 varname=GetToken();
237
238 int x,y,width,height;
239 ReadRect(x,y,width,height);
240
241 m_xmlfile.Write("\t\t<button");
242 WriteBasicInfo(x,y,width,height,varname);
243 WriteLabel(phrase);
244 m_xmlfile.Write("\t\t</button>\n");
245
246 }
247
248
249 bool rc2xml::Seperator(int ch)
250 {
251 //if ((ch==' ')|(ch==',')|(ch==13)|(ch==10)|(ch=='|')|(ch=='\t'))
252 if ((ch==' ')|(ch==',')|(ch==13)|(ch==10)|(ch=='\t'))
253 return TRUE;
254
255 if (ch==EOF)
256 {
257 m_done=TRUE;
258 return TRUE;
259 }
260
261 return FALSE;
262 }
263
264 void rc2xml::ParseGroupBox()
265 {
266 // GROUPBOX "Rotate",IDC_STATIC,1,1,71,79
267 wxString token;
268 wxString phrase,varname;
269 phrase=GetQuoteField();
270 varname=GetToken();
271 int x,y,width,height;
272 ReadRect(x,y,width,height);
273
274 m_xmlfile.Write("\t\t<staticbox");
275 WriteBasicInfo(x,y,width,height,varname);
276 WriteLabel(phrase);
277 m_xmlfile.Write("\t\t</staticbox>\n");
278 }
279
280 void rc2xml::ReadRect(int & x, int & y, int & width, int & height)
281 {
282 x=atoi(GetToken());
283 y=atoi(GetToken());
284 width=atoi(GetToken());
285 height=atoi(GetToken());
286 }
287
288 wxString rc2xml::GetToken()
289 {
290 wxString token="";
291
292 if (m_rc.Eof())
293 {
294 m_done=TRUE;
295 return token;
296 }
297
298 int ch=0;
299 ReadChar(ch);
300 if (ch==EOF)
301 {
302 m_done=TRUE;
303 return token;
304 }
305
306 while (Seperator(ch))
307 {
308 ReadChar(ch);
309 if (m_done)
310 return token;
311 }
312
313 if (ch==EOF)
314 {
315 m_done=TRUE;
316 }
317
318
319 while (!Seperator(ch))
320 {
321 token+=(char)ch;
322 ReadChar(ch);
323 }
324
325 if (ch==EOF)
326 m_done=TRUE;
327
328 return token;
329 }
330
331 wxString rc2xml::GetQuoteField()
332 {
333 wxString phrase;
334 //ASCII code 34 "
335 int ch=0;
336 ReadChar(ch);
337
338 while (ch!=34)
339 ReadChar(ch);
340
341 ReadChar(ch);
342
343 while (ch!=34)
344 {
345 phrase+=(char)ch;
346 ReadChar(ch);
347 }
348 return phrase;
349 }
350
351 void rc2xml::ReadChar(int &ch)
352 {
353 int result;
354 result=m_rc.Tell();
355
356 if((result>=m_filesize))
357 m_done=TRUE;
358
359 result=m_rc.Read(&ch,1);
360
361 if((result==-1))
362 m_done=TRUE;
363
364 if(ch==EOF)
365 m_done=TRUE;
366 }
367
368 void rc2xml::ParseComboBox()
369 {
370 /* COMBOBOX IDC_SCALECOMBO,10,110,48,52,CBS_DROPDOWNLIST | CBS_SORT |
371 WS_VSCROLL | WS_TABSTOP */
372 wxString token;
373 wxString varname;
374 varname=GetToken();
375 int x,y,width,height;
376 ReadRect(x,y,width,height);
377
378 m_xmlfile.Write("\t\t<combobox");
379 WriteBasicInfo(x,y,width,height,varname);
380 m_xmlfile.Write("\n\t\t</combobox>\n");
381
382 }
383
384 void rc2xml::ParseMenu(wxString varname)
385 {
386 wxString token="";
387
388 //Write menubar to xml file
389 m_xmlfile.Write("\t<menubar");
390 //Avoid duplicate names this way
391 varname.Replace("IDR_","MB_");
392 WriteName(varname);
393 m_xmlfile.Write(">\n");
394 m_xmlfile.Write("\t\t<children>\n");
395
396 while ((token!="BEGIN")&(token!="{"))
397 token=GetToken();
398
399 while ((token!="END")&(token!="}"))
400 {
401 token=GetToken();
402 if (token=="POPUP")
403 {
404 ParsePopupMenu();
405 }
406 }
407 m_xmlfile.Write("\t\t</children>\n");
408 m_xmlfile.Write("\t</menubar>\n");
409 }
410
411 void rc2xml::ParsePopupMenu()
412 {
413 static int menucount=0;
414 menucount++;
415 wxString token,name,msg,longhelp,tip;
416 token=GetQuoteField();
417
418 //Remove \t because it causes problems
419
420 //spot=token.First("\\t");
421 //token=token.Left(spot);
422
423 //Write Menu item
424 //Generate a fake name since RC menus don't have one
425 name<<"Menu_"<<menucount;
426 m_xmlfile.Write("\t\t<menu");
427 WriteName(name);
428 m_xmlfile.Write(">\n");
429 WriteLabel(token);
430 m_xmlfile.Write("\t\t\t<children>\n");
431
432 while ((token!="BEGIN")&(token!="{"))
433 token=GetToken();
434
435 while ((token!="END")&(token!="}"))
436 {
437 token=GetToken();
438 if (token=="POPUP")
439 ParsePopupMenu();
440
441 if (token=="MENUITEM")
442 ParseMenuItem();
443 }
444 m_xmlfile.Write("\t\t\t</children>\n");
445 m_xmlfile.Write("\t\t\t</menu>\n");
446 }
447
448 wxString rc2xml::PeekToken()
449 {
450 wxString token;
451 int p;
452 p=m_rc.Tell();
453 token=GetToken();
454
455 m_rc.Seek(p);
456 return token;
457 }
458 //MS Windows pain in the butt CONTROL
459 void rc2xml::ParseControlMS()
460 {
461 wxString label,varname,kindctrl,token;
462 token=PeekToken();
463
464 if (token.Contains("\""))
465 ParseNormalMSControl();
466 else
467 ParseWeirdMSControl();
468
469 }
470
471 /* CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH |
472 TBS_NOTICKS | WS_TABSTOP,52,73,100,15
473 */
474
475 void rc2xml::ParseSlider(wxString label, wxString varname)
476 {
477 wxString token,style;
478 ReadOrs(token);
479 if (token.Find("TBS_VERT")!=-1)
480 style+="wxSL_VERTICAL";
481 //MFC RC Default is horizontal
482 else
483 style+="wxSL_HORIZONTAL";
484
485 int x,y,width,height;
486 ReadRect(x,y,width,height);
487 m_xmlfile.Write("\t\t<slider");
488 WriteBasicInfo(x,y,width,height,varname);
489 WriteStyle(style);
490 m_xmlfile.Write("\n\t\t</slider>\n");
491
492 }
493 /*
494 CONTROL "Progress1",CG_IDC_PROGDLG_PROGRESS,"msctls_progress32",
495 WS_BORDER,15,52,154,13
496 */
497 void rc2xml::ParseProgressBar(wxString label, wxString varname)
498 {
499 wxString token,style;
500 ReadOrs(token);
501
502 int x,y,width,height;
503 ReadRect(x,y,width,height);
504
505 //Always horizontal in MFC
506 m_xmlfile.Write("\t\t<gauge");
507 WriteBasicInfo(x,y,width,height,varname);
508 WriteStyle(style);
509 m_xmlfile.Write("\t\t</gauge>\n");
510 }
511
512 bool rc2xml::ReadOrs(wxString & orstring)
513 {
514 wxString token;
515
516 token=PeekToken();
517 if (token.IsNumber())
518 return FALSE;
519 orstring=GetToken();
520
521 while(PeekToken()==_T("|"))
522 {
523 //Grab |
524 orstring+=GetToken();
525 //Grab next token
526 orstring+=GetToken();
527 }
528 return TRUE;
529 }
530
531 //Is it a check button or a radio button
532 void rc2xml::ParseCtrlButton(wxString label, wxString varname)
533 {
534 wxString token;
535 ReadOrs(token);
536 int x,y,width,height;
537
538 if (token.Find("BS_AUTOCHECKBOX")!=-1)
539 {
540 ReadRect(x,y,width,height);
541 m_xmlfile.Write("\t\t<checkbox");
542 WriteBasicInfo(x,y,width,height,varname);
543 WriteLabel(label);
544 m_xmlfile.Write("\t\t</checkbox>\n");
545 }
546
547 if (token.Find("BS_AUTORADIOBUTTON")!=-1)
548 {
549 ReadRect(x,y,width,height);
550 m_xmlfile.Write("\t\t<radiobutton");
551 WriteBasicInfo(x,y,width,height,varname);
552 WriteLabel(label);
553 m_xmlfile.Write("\t\t</radiobutton>\n");
554 }
555
556 }
557
558
559 void rc2xml::WriteSize(int width, int height)
560 {
561 wxString msg;
562 msg<<" <size>"<<width<<","<<height<<"d</size>";
563 m_xmlfile.Write(msg);
564 }
565
566 void rc2xml::WritePosition(int x, int y)
567 {
568 wxString msg;
569 msg<<" <pos>"<<x<<","<<y<<"d</pos>";
570 m_xmlfile.Write(msg);
571 }
572
573 void rc2xml::WriteTitle(wxString title)
574 {
575 wxString msg;
576 msg=_T("\t\t<title>"+title+"</title>\n");
577 m_xmlfile.Write(msg);
578 }
579
580 void rc2xml::WriteName(wxString name)
581 {
582
583 //Try to convert any number ids into names
584 name=LookUpId(name);
585 //Replace common MS ids with wxWindows ids
586 //I didn't do everyone of them
587 if (name=="IDOK")
588 name="wxID_OK";
589 else if (name=="IDCANCEL")
590 name="wxID_CANCEL";
591 else if (name=="IDAPPLY")
592 name="wxID_APPLY";
593 else if (name=="ID_FILE_OPEN")
594 name="wxID_OPEN";
595 else if (name=="ID_FILE_CLOSE")
596 name="wxID_CLOSE";
597 else if (name=="ID_FILE_SAVE")
598 name="wxID_SAVE";
599 else if (name=="ID_FILE_SAVE_AS")
600 name="wxID_SAVEAS";
601 else if (name=="ID_APP_EXIT")
602 name="wxID_EXIT";
603 else if (name=="ID_FILE_PRINT")
604 name="wxID_PRINT";
605 else if (name=="ID_FILE_PRINT_PREVIEW")
606 name="wxID_PREVIEW";
607 else if (name=="ID_FILE_PRINT_SETUP")
608 name="wxID_PRINT_SETUP";
609 else if (name=="ID_APP_ABOUT")
610 name="wxID_ABOUT";
611 else if (name=="ID_EDIT_UNDO")
612 name="wxID_UNDO";
613 else if (name=="ID_EDIT_CUT")
614 name="wxID_CUT";
615 else if (name=="ID_EDIT_COPY")
616 name="wxID_COPY";
617 else if (name=="ID_EDIT_PASTE")
618 name="wxID_PASTE";
619
620 m_xmlfile.Write(" name= \""+name+"\"");
621 }
622
623 void rc2xml::WriteLabel(wxString label)
624 {
625 label.Replace("&","$");
626 m_xmlfile.Write("\t\t\t<label>"+label+"</label>\n");
627 }
628
629 void rc2xml::WriteBasicInfo(int x, int y, int width, int height, wxString name)
630 {
631 WriteName(name);
632 m_xmlfile.Write(">\n");
633 m_xmlfile.Write("\t\t\t");
634 WritePosition(x,y);
635 WriteSize(width,height);
636 m_xmlfile.Write("\n");
637 }
638
639 void rc2xml::WriteStyle(wxString style)
640 {
641 if (style.Length()==0)
642 return;
643 m_xmlfile.Write("\n\t\t<style>"+style+"</style>\n");
644 }
645 /*
646 LISTBOX IDC_LIST1,16,89,48,40,LBS_SORT | LBS_MULTIPLESEL |
647 LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
648 */
649 void rc2xml::ParseListBox()
650 {
651 wxString token;
652 wxString varname;
653 varname=GetToken();
654 int x,y,width,height;
655 ReadRect(x,y,width,height);
656
657 m_xmlfile.Write("\t\t<listbox");
658 WriteBasicInfo(x,y,width,height,varname);
659 m_xmlfile.Write("\n\t\t</listbox>\n");
660
661 }
662 /*
663 CONTROL "",IDC_RICHEDIT1,"RICHEDIT",ES_AUTOHSCROLL | WS_BORDER |
664 WS_TABSTOP,103,110,40,14
665 */
666 void rc2xml::ParseRichEdit(wxString label, wxString varname)
667 {
668 wxString token;
669 //while (ReadOrs(token));
670 ReadOrs(token);
671 int x,y,width,height;
672 ReadRect(x,y,width,height);
673 wxString style;
674 //Make it a rich text control
675 style+="wxTE_MULTILINE ";
676 m_xmlfile.Write("\t\t<textctrl");
677 WriteBasicInfo(x,y,width,height,varname);
678 WriteStyle(style);
679 m_xmlfile.Write("\t\t</textctrl>\n");
680
681 }
682 /*
683 CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_ARROWKEYS,209,72,
684 19,26
685 */
686 void rc2xml::ParseSpinCtrl(wxString label, wxString varname)
687 {
688 wxString token,style;
689
690 ReadOrs(token);
691 if (token.Find("UDS_HORZ")!=-1)
692 style="wxSP_HORIZONTAL";
693 //MFC default
694 else
695 style="wxSP_VERTICAL";
696
697 int x,y,width,height;
698 ReadRect(x,y,width,height);
699 m_xmlfile.Write("\t\t<spinbutton");
700 WriteBasicInfo(x,y,width,height,varname);
701 WriteStyle(style);
702 m_xmlfile.Write("\n\t\t</spinbutton>\n");
703
704 }
705
706 void rc2xml::FirstPass()
707 {
708 wxString token,prevtok;
709 while (!m_done)
710 {
711 token=GetToken();
712 if (token=="BITMAP")
713 ParseBitmap(prevtok);
714 else if (token=="STRINGTABLE")
715 ParseStringTable(prevtok);
716 else if (token=="ICON")
717 ParseIcon(prevtok);
718
719 prevtok=token;
720 }
721 }
722
723 void rc2xml::ParseBitmap(wxString varname)
724 {
725 wxString token,*bitmapfile;
726
727 token=PeekToken();
728 //Microsoft notation?
729 if (token=="DISCARDABLE")
730 {
731 token=GetToken();
732 token=PeekToken();
733 }
734 bitmapfile=new wxString;
735 *bitmapfile=GetQuoteField();
736 m_bitmaplist->Append(varname,bitmapfile);
737
738 }
739
740
741 void rc2xml::SecondPass()
742 {
743 wxString token,prevtok;
744 while (!m_done)
745 {
746 token=GetToken();
747 if (token=="DIALOG")
748 ParseDialog(prevtok);
749 else if (token=="MENU")
750 ParseMenu(prevtok);
751 else if (token=="TOOLBAR")
752 ParseToolBar(prevtok);
753
754 prevtok=token;
755 }
756
757 }
758
759 void rc2xml::ParseToolBar(wxString varname)
760 {
761 wxString token;
762 token=GetToken();
763 wxASSERT_MSG(token=="DISCARDABLE","Error in toolbar parsing");
764 //Look up bitmap for toolbar and load
765 wxNode *node=m_bitmaplist->Find(LookUpId(varname));
766 wxString *bitmappath;
767 bitmappath=(wxString *)node->Data();
768 wxBitmap bitmap;
769 if (!bitmap.LoadFile(*bitmappath,wxBITMAP_TYPE_BMP ))
770 wxLogError("Unable to load bitmap:"+*bitmappath);
771
772 //Write toolbar to xml file
773 m_xmlfile.Write(" <toolbar");
774 //Avoid duplicate names this way
775 varname.Replace("IDR_","TB_");
776 WriteName(varname);
777 m_xmlfile.Write(">\n");
778 wxString style;
779 style+="wxTB_FLAT";
780 WriteStyle(style);
781
782 m_xmlfile.Write("\t\t<children>\n");
783
784 //Grab width and height
785 int width,height;
786 width=atoi(GetToken());
787 height=atoi(GetToken());
788
789 int c=0;
790 wxString buttonname,msg,tip,longhelp;
791 token=GetToken();
792 while ((token!="BEGIN"))
793 token=GetToken();
794
795 while ((token!="END")&(token!="}"))
796 {
797 if (token=="BUTTON")
798 {
799 buttonname=GetToken();
800 m_xmlfile.Write("\t\t\t<tool");
801 WriteName(buttonname);
802 m_xmlfile.Write(">\n");
803 //Write tool tip if any
804 if (LookUpString(buttonname,msg))
805 {
806 SplitHelp(msg,tip,longhelp);
807 m_xmlfile.Write("\t\t\t\t<tooltip>"+tip+"</tooltip>\n");
808 m_xmlfile.Write(" <longhelp>"+longhelp+"</longhelp>\n");
809 }
810 //Make a bitmap file name
811 buttonname=CleanName(buttonname);
812 buttonname+=".bmp";
813 m_xmlfile.Write("\t\t\t\t<bitmap>"+buttonname+"</bitmap>\n");
814 WriteToolButton(buttonname,c,width,height,bitmap);
815 m_xmlfile.Write("\t\t\t</tool>\n");
816 c++;
817 }
818 else if (token=="SEPARATOR")
819 {
820 m_xmlfile.Write("\t\t\t<separator/>\n");
821 }
822 token=GetToken();
823 }
824 m_xmlfile.Write("\t</children>\n");
825 m_xmlfile.Write("\t</toolbar>\n");
826 }
827
828 //Extract bitmaps from larger toolbar bitmap
829 void rc2xml::WriteToolButton(wxString name,int index, int width, int height, wxBitmap bitmap)
830 {
831 int x;
832 x=index*width;
833 wxRect r(x,0,width,height);
834 wxBitmap little;
835 little=bitmap.GetSubBitmap(r);
836 little.SaveFile(name,wxBITMAP_TYPE_BMP);
837 }
838
839 void rc2xml::ParseStringTable(wxString varname)
840 {
841 wxString token;
842 token=GetToken();
843 while ((token!="BEGIN"))
844 token=GetToken();
845 token=GetToken();
846 wxString *msg;
847
848 while ((token!="END")&(token!="}"))
849 {
850 msg=new wxString;
851 *msg=GetQuoteField();
852 m_stringtable->Append(token,msg);
853 token=GetToken();
854 }
855
856 }
857
858 bool rc2xml::LookUpString(wxString strid,wxString & st)
859 {
860 wxNode *node=m_stringtable->Find(strid);
861 wxString *s;
862 if (node==NULL)
863 return FALSE;
864
865 s=(wxString *)node->Data();
866 st=*s;
867
868 return TRUE;
869 }
870
871 bool rc2xml::SplitHelp(wxString msg, wxString &shorthelp, wxString &longhelp)
872 {
873 int spot;
874 spot=msg.Find("\\n");
875 if (spot==-1)
876 {
877 shorthelp=msg;
878 longhelp=msg;
879 }
880
881 longhelp=msg.Left(spot);
882 spot=msg.Length()-spot-2;
883 shorthelp=msg.Right(spot);
884 return TRUE;
885 }
886
887 void rc2xml::ParseMenuItem()
888 {
889 wxString token,name,msg,tip,longhelp;
890 //int spot;
891 if (PeekToken()=="SEPARATOR")
892 {
893 m_xmlfile.Write("\t\t\t<separator/>\n");
894 return;
895 }
896
897 token=GetQuoteField();
898 name=GetToken();
899 //Remove \t because it causes problems
900 //spot=token.First("\\t");
901 //token=token.Left(spot);
902 m_xmlfile.Write("\t\t\t<menuitem");
903 WriteName(name);
904 m_xmlfile.Write(">\n");
905 WriteLabel(token);
906 //Look up help if any listed in stringtable
907 if (LookUpString(name,msg))
908 {
909 SplitHelp(msg,tip,longhelp);
910 m_xmlfile.Write("\t\t\t<help>"
911 +longhelp+"</help>\n");
912 }
913 //look for extra attributes like checked and break
914 wxString ptoken;
915 ptoken=PeekToken();
916 while ((ptoken!="MENUITEM")&(ptoken!="POPUP")&(ptoken!="END"))
917 {
918 token=GetToken();
919 if (token=="CHECKED")
920 m_xmlfile.Write("\t\t\t<checkable>1</checkable>\n");
921 else if (token=="MENUBREAK");
922 //m_xmlfile.Write("\t\t\t</break>\n");
923 else if (token=="GRAYED");
924 else
925 wxLogError("Unknown Menu Item token:"+token);
926
927 ptoken=PeekToken();
928 }
929 m_xmlfile.Write("\t\t\t</menuitem>\n");
930
931 }
932
933 //ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
934 void rc2xml::ParseIconStatic()
935 {
936 wxString token;
937 wxString varname,iconname;
938 iconname=GetToken();
939 //Look up icon
940 varname=GetToken();
941
942 int x,y,width,height;
943 ReadRect(x,y,width,height);
944
945 m_xmlfile.Write("\t\t<staticbitmap");
946 WriteBasicInfo(x,y,width,height,varname);
947 //Save icon as a bitmap
948 WriteIcon(iconname);
949 m_xmlfile.Write("\t\t</staticbitmap>\n");
950
951 }
952 //IDR_MAINFRAME ICON DISCARDABLE "res\\mfcexample.ico"
953 void rc2xml::ParseIcon(wxString varname)
954 {
955 wxString token,*iconfile;
956 iconfile=new wxString;
957 token=PeekToken();
958
959 *iconfile=GetQuoteField();
960 m_iconlist->Append(varname,iconfile);
961
962
963 }
964
965 wxString rc2xml::CleanName(wxString name)
966 {
967 name.MakeLower();
968 name.Replace("id_","");
969 name.Replace("idr_","");
970 name.Replace("idb_","");
971 name.Replace("idc_","");
972 return name;
973 }
974 // And the award for most messed up control goes to...
975 // CONTROL IDB_FACE,IDC_STATIC,"Static",SS_BITMAP,26,62,32,30
976 void rc2xml::ParseStaticBitmap(wxString bitmapname, wxString varname)
977 {
978 wxString token;
979 //Grab SS_BITMAP
980 token=GetToken();
981
982
983
984 int x,y,width,height;
985 ReadRect(x,y,width,height);
986
987 m_xmlfile.Write("\t\t<staticbitmap");
988 WriteBasicInfo(x,y,width,height,varname);
989 WriteBitmap(bitmapname);
990 m_xmlfile.Write("\t\t</staticbitmap>\n");
991
992 }
993
994 void rc2xml::ParseNormalMSControl()
995 {
996 wxString label,varname,kindctrl;
997
998 label=GetQuoteField();
999 varname=GetToken();
1000 kindctrl=GetQuoteField();
1001 kindctrl.MakeUpper();
1002
1003 if (kindctrl=="MSCTLS_UPDOWN32")
1004 ParseSpinCtrl(label,varname);
1005 if (kindctrl=="MSCTLS_TRACKBAR32")
1006 ParseSlider(label,varname);
1007 if (kindctrl=="MSCTLS_PROGRESS32")
1008 ParseProgressBar(label,varname);
1009 if (kindctrl=="SYSTREEVIEW32")
1010 ParseTreeCtrl(label,varname);
1011 if (kindctrl=="SYSMONTHCAL32")
1012 ParseCalendar(label,varname);
1013 if (kindctrl=="SYSLISTVIEW32")
1014 ParseListCtrl(label,varname);
1015 if (kindctrl=="BUTTON")
1016 ParseCtrlButton(label,varname);
1017 if (kindctrl=="RICHEDIT")
1018 ParseRichEdit(label,varname);
1019
1020 }
1021
1022 void rc2xml::ParseWeirdMSControl()
1023 {
1024 wxString kindctrl;
1025 wxString varname;
1026 wxString id;
1027 id=GetToken();
1028 varname=GetToken();
1029 kindctrl=GetQuoteField();
1030 kindctrl.MakeUpper();
1031 // CONTROL IDB_FACE,IDC_STATIC,"Static",SS_BITMAP,26,62,32,30
1032 if (kindctrl=="STATIC")
1033 {
1034 if (PeekToken()=="SS_BITMAP")
1035 ParseStaticBitmap(id,varname);
1036 else
1037 wxLogError("Unknown MS Control Static token");
1038 }
1039
1040 }
1041 //SCROLLBAR IDC_SCROLLBAR1,219,56,10,40,SBS_VERT
1042
1043 void rc2xml::ParseScrollBar()
1044 {
1045 wxString token;
1046 wxString varname;
1047
1048 varname=GetToken();
1049 int x,y,width,height;
1050 ReadRect(x,y,width,height);
1051 wxString style;
1052
1053 ReadOrs(token);
1054
1055 if (token.Find("SBS_VERT")!=-1)
1056 style=_T("wxSB_VERTICAL");
1057 //Default MFC style is horizontal
1058 else
1059 style=_T("wxSB_HORIZONTAL");
1060
1061 m_xmlfile.Write("\t\t<scrollbar");
1062 WriteBasicInfo(x,y,width,height,varname);
1063 WriteStyle(style);
1064 m_xmlfile.Write("\n\t\t</scrollbar>\n");
1065
1066 }
1067 // CONTROL "Tree1",IDC_TREE1,"SysTreeView32",WS_BORDER | WS_TABSTOP,
1068 // 7,7,66,61
1069
1070 void rc2xml::ParseTreeCtrl(wxString label, wxString varname)
1071 {
1072 wxString token;
1073 //while (ReadOrs(token));
1074 ReadOrs(token);
1075 int x,y,width,height;
1076 ReadRect(x,y,width,height);
1077 m_xmlfile.Write("\t\t<treectrl");
1078 WriteBasicInfo(x,y,width,height,varname);
1079 m_xmlfile.Write("\t\t</treectrl>\n");
1080
1081 }
1082 // CONTROL "MonthCalendar1",IDC_MONTHCALENDAR1,"SysMonthCal32",
1083 //MCS_NOTODAY | WS_TABSTOP,105,71,129,89
1084
1085 void rc2xml::ParseCalendar(wxString label, wxString varname)
1086 {
1087 wxString token;
1088 //while (ReadOrs(token));
1089 ReadOrs(token);
1090 int x,y,width,height;
1091 ReadRect(x,y,width,height);
1092 m_xmlfile.Write("\t\t<calendarctrl");
1093 WriteBasicInfo(x,y,width,height,varname);
1094 m_xmlfile.Write("\t\t</calendarctrl>\n");
1095 }
1096 // CONTROL "List1",IDC_LIST1,"SysListView32",WS_BORDER | WS_TABSTOP,
1097 // 7,89,68,71
1098
1099 void rc2xml::ParseListCtrl(wxString label, wxString varname)
1100 {
1101 wxString token;
1102 //while (ReadOrs(token));
1103 ReadOrs(token);
1104 int x,y,width,height;
1105 ReadRect(x,y,width,height);
1106 m_xmlfile.Write("\t\t<listctrl");
1107 WriteBasicInfo(x,y,width,height,varname);
1108 m_xmlfile.Write("\t\t</listctrl>\n");
1109
1110 }
1111
1112 void rc2xml::WriteBitmap(wxString bitmapname)
1113 {
1114 //Look up bitmap
1115 wxNode *node=m_bitmaplist->Find(LookUpId(bitmapname));
1116 if (node==NULL)
1117 {
1118 m_xmlfile.Write("\t\t\t<bitmap>missingfile</bitmap>\n");
1119 wxLogError("Unable to find bitmap:"+bitmapname);
1120 return;
1121 }
1122
1123 wxString *bitmappath;
1124 bitmappath=(wxString *)node->Data();
1125 wxBitmap bitmap;
1126 if (!bitmap.LoadFile(*bitmappath,wxBITMAP_TYPE_BMP ))
1127 wxLogError("Unable to load bitmap:"+*bitmappath);
1128
1129 //Make a bitmap file name
1130 bitmapname=CleanName(bitmapname);
1131 bitmapname+=".bmp";
1132 m_xmlfile.Write("\t\t\t<bitmap>"+bitmapname+"</bitmap>\n");
1133 bitmap.SaveFile(bitmapname,wxBITMAP_TYPE_BMP);
1134 }
1135
1136 void rc2xml::WriteIcon(wxString iconname)
1137 {
1138 wxNode *node=m_iconlist->Find(iconname);
1139 if (node==NULL)
1140 {
1141 m_xmlfile.Write("\t\t\t<bitmap>missing_file</bitmap>\n");
1142 wxLogError("Unable to find icon:"+iconname);
1143 }
1144 wxString *iconpath;
1145 iconpath=(wxString *)node->Data();
1146 wxIcon icon;
1147 wxBitmap bitmap;
1148 if (!icon.LoadFile(*iconpath,wxBITMAP_TYPE_ICO ))
1149 wxLogError("Unable to load icon:"+*iconpath);
1150 #ifdef __WXMSW__
1151 bitmap.CopyFromIcon(icon);
1152 #else
1153 bitmap = icon;
1154 #endif
1155
1156 //Make a bitmap file name
1157 iconname=CleanName(iconname);
1158 iconname+=".bmp";
1159 m_xmlfile.Write("\t\t\t<bitmap>"+iconname+"</bitmap>\n");
1160 bitmap.SaveFile(iconname,wxBITMAP_TYPE_BMP);
1161
1162
1163 }
1164 /*Unfortunately sometimes the great MSVC Resource editor decides
1165 to use numbers instead of the word id. I have no idea why they
1166 do this, but that is the way it is.
1167 */
1168 /* this is a quick and dirty way to parse the resource.h file
1169 it will not recognize #ifdef so it can be easily fooled
1170 */
1171 void rc2xml::ParseResourceHeader()
1172 {
1173 wxTextFile r;
1174 //Attempt to load resource.h in current path
1175 if (!r.Open("resource.h"))
1176 {
1177 wxLogError("Warining Unable to load resource.h file");
1178 return;
1179 }
1180
1181 wxString str;
1182 wxString id,v;
1183 wxStringTokenizer tok;
1184 wxString *varname;
1185
1186
1187 long n;
1188
1189 //Read through entire file
1190 for ( str = r.GetFirstLine(); !r.Eof(); str = r.GetNextLine() )
1191 {
1192 if (str.Find("#define")!=-1)
1193 {
1194 tok.SetString(str);
1195 //Just ignore #define token
1196 tok.GetNextToken();
1197 v=tok.GetNextToken();
1198 id=tok.GetNextToken();
1199 if (id.IsNumber())
1200 {
1201 varname=new wxString;
1202 id.ToLong(&n);
1203 *varname=v;
1204 m_resourcelist->Append(n,varname);
1205 }
1206 }
1207 }
1208
1209
1210
1211 }
1212
1213
1214 wxString rc2xml::LookUpId(wxString id)
1215 {
1216 wxString st;
1217
1218 if (!id.IsNumber())
1219 return id;
1220 long n;
1221 id.ToLong(&n);
1222 wxNode *node=m_resourcelist->Find(n);
1223 wxString *s;
1224 if (node==NULL)
1225 return id;
1226
1227 s=(wxString *)node->Data();
1228 st=*s;
1229 return st;
1230 }