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