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