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