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