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