1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // Nestopia - NES/Famicom emulator written in C++
4 //
5 // Copyright (C) 2003-2008 Martin Freij
6 //
7 // This file is part of Nestopia.
8 //
9 // Nestopia is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Nestopia is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Nestopia; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #ifndef NST_DIALOG_LAUNCHER_H
26 #define NST_DIALOG_LAUNCHER_H
27 
28 #pragma once
29 
30 #include <vector>
31 #include <map>
32 #include "NstCollectionBitSet.hpp"
33 #include "NstWindowMenu.hpp"
34 #include "NstWindowStatusBar.hpp"
35 #include "NstWindowDialog.hpp"
36 #include "NstDialogFind.hpp"
37 #include "../core/api/NstApiCartridge.hpp"
38 #include <CommCtrl.h>
39 
40 namespace Nes
41 {
42 	using namespace Api;
43 }
44 
45 namespace Nestopia
46 {
47 	namespace Io
48 	{
49 		class File;
50 	}
51 
52 	namespace Managers
53 	{
54 		class Paths;
55 	}
56 
57 	namespace Window
58 	{
59 		class Launcher
60 		{
61 		public:
62 
63 			Launcher(const Nes::Cartridge::Database&,const Managers::Paths&,const Configuration&);
64 			~Launcher();
65 
66 			void Save(Configuration&,bool,bool);
67 			void Open(bool);
68 			void Synchronize(HWND) const;
69 			void Close();
70 
71 		private:
72 
73 			struct Handlers;
74 
75 			enum
76 			{
77 				STATUSBAR_SECOND_FIELD_WIDTH = 14,
78 				CMD_ENTER = 1
79 			};
80 
81 			void UpdateItemCount(uint) const;
82 			void OnNoSelection() const;
83 
84 			ibool OnInitDialog (Param&);
85 			ibool OnDropFiles  (Param&);
86 			ibool OnSize       (Param&);
87 			ibool OnCmdEnter   (Param&);
88 			ibool OnClose      (Param&);
89 			ibool OnDestroy    (Param&);
90 
91 			void OnCmdFileRun                   (uint=0);
92 			void OnCmdFileRefresh               (uint);
93 			void OnCmdEditHeader                (uint);
94 			void OnCmdViewShowGrids             (uint);
95 			void OnCmdViewShowDatabaseCorrected (uint);
96 			void OnCmdViewShowOnTop             (uint);
97 			void OnCmdOptionsPaths              (uint);
98 			void OnCmdOptionsColors             (uint);
99 
100 			void OnListGetDisplayInfo    (const NMHDR&);
101 			void OnListKeyDown           (const NMHDR&);
102 			void OnListColumnClick       (const NMHDR&);
103 			void OnListItemActivate      (const NMHDR&);
104 			void OnListItemChanged       (const NMHDR&);
105 			void OnListInsertItem        (const NMHDR&);
106 			void OnListDeleteItem        (const NMHDR&);
107 			void OnListDeleteAllItems    (const NMHDR&);
108 			void OnTreeSelectionChanging (const NMHDR&);
109 
110 			class List
111 			{
112 			public:
113 
114 				List
115 				(
116 					Dialog&,
117 					Menu::CmdHandler&,
118 					const Managers::Paths&,
119 					const Configuration&,
120 					const Nes::Cartridge::Database&
121 				);
122 
123 				~List();
124 
125 				void operator = (const Control::ListView&);
126 
127 				enum Updater
128 				{
129 					DONT_REPAINT,
130 					REPAINT
131 				};
132 
133 				void Add(wcstring);
134 				void Close();
135 				void Save(Configuration&,bool);
136 				void Sort(uint=0);
137 				bool CanRefresh() const;
138 				void Refresh();
139 				void Insert(const Param&);
140 				void SetColors(uint,uint,Updater=DONT_REPAINT) const;
141 				void OnGetDisplayInfo(LPARAM);
142 
143 				class Paths
144 				{
145 				public:
146 
147 					explicit Paths(const Configuration&);
148 
149 					void Save(Configuration&) const;
150 
151 					struct Settings
152 					{
153 						struct Folder
154 						{
155 							Path path;
156 							bool incSubDir;
157 						};
158 
159 						typedef std::vector<Folder> Folders;
160 
161 						struct Include : Collection::BitSet
162 						{
163 							enum
164 							{
165 								NES,UNF,XML,FDS,NSF,PATCH,ARCHIVE,ANY,UNIQUE
166 							};
167 
168 							enum
169 							{
170 								TYPES = NES|UNF|XML|FDS|NSF|PATCH,
171 								FILES = TYPES|ARCHIVE
172 							};
173 
IncludeNestopia::Window::Launcher::List::Paths::Settings::Include174 							explicit Include(bool a=false)
175 							: Collection::BitSet( (0xFF^0x40) | uint(a) << 6 ) {}
176 						};
177 
178 						Include include;
179 						Folders folders;
180 					};
181 
182 				private:
183 
184 					struct Handlers;
185 
186 					enum
187 					{
188 						LIMIT = 999
189 					};
190 
191 					ibool OnInitDialog (Param&);
192 					ibool OnCmdAdd     (Param&);
193 					ibool OnCmdRemove  (Param&);
194 					ibool OnCmdClear   (Param&);
195 					ibool OnCmdOk      (Param&);
196 
197 					void OnKeyDown     (const NMHDR&);
198 					void OnItemChanged (const NMHDR&);
199 					void OnInsertItem  (const NMHDR&);
200 					void OnDeleteItem  (const NMHDR&);
201 
202 					Settings settings;
203 					Dialog dialog;
204 					const Control::NotificationHandler notifications;
205 
206 				public:
207 
Open()208 					void Open()
209 					{
210 						dialog.Open();
211 					}
212 
GetSettings() const213 					const Settings& GetSettings() const
214 					{
215 						return settings;
216 					}
217 				};
218 
219 				class Files
220 				{
221 					class Inserter;
222 					class Searcher;
223 
224 				public:
225 
226 					class Strings
227 					{
228 						HeapString container;
229 
230 					public:
231 
232 						explicit Strings(uint=0);
233 
234 						typedef uint Index;
235 
236 						enum
237 						{
238 							NONE = -1
239 						};
240 
241 						int  Find(GenericString) const;
242 						void Clear();
243 
244 						template<typename T>
operator <<(const T & t)245 						Index operator << (const T& t)
246 						{
247 							uint pos = container.Length();
248 							container << t << '\0';
249 							return pos;
250 						}
251 
Import(cstring t)252 						Index Import(cstring t)
253 						{
254 							uint pos = container.Length();
255 							container.Import( t );
256 							container << '\0';
257 							return pos;
258 						}
259 
operator [](uint i) const260 						wcstring operator [] (uint i) const
261 						{
262 							return container.Ptr() + i;
263 						}
264 
Size() const265 						uint Size() const
266 						{
267 							return container.Length() * (container.Wide() ? 2 : 1);
268 						}
269 					};
270 
271 					Files();
272 
273 					void Load();
274 					void Save();
275 					void Refresh(const Paths::Settings&,const Nes::Cartridge::Database&);
276 					bool Insert(const Nes::Cartridge::Database&,GenericString);
277 					void Clear();
278 					bool ShouldDefrag() const;
279 					void Defrag();
280 
281 					class Entry
282 					{
283 						friend class Files;
284 						friend class Inserter;
285 						friend class Searcher;
286 
287 					public:
288 
289 						typedef Nes::Cartridge::Database Db;
290 
291 						enum Type
292 						{
293 							NES     = 0x01,
294 							UNF     = 0x02,
295 							XML     = 0x04,
296 							FDS     = 0x08,
297 							NSF     = 0x10,
298 							PATCH   = 0x20,
299 							ARCHIVE = 0x80,
300 							ALL     = NES|UNF|XML|FDS|NSF|PATCH
301 						};
302 
303 						enum
304 						{
305 							SYSTEM_UNKNOWN,
306 							SYSTEM_PC10,
307 							SYSTEM_VS,
308 							SYSTEM_PAL,
309 							SYSTEM_NTSC,
310 							SYSTEM_NTSC_PAL
311 						};
312 
313 						uint GetSystem(const Db*) const;
314 
315 					private:
316 
317 						explicit Entry(uint=0);
318 
319 						Db::Entry SearchDb(const Db*) const;
320 
321 						enum
322 						{
323 							ATR_BATTERY     = 0x08,
324 							ATR_PC10        = 0x10,
325 							ATR_VS          = 0x20,
326 							ATR_PAL         = 0x40,
327 							ATR_NTSC        = 0x80,
328 							ATR_NTSC_PAL    = ATR_PAL|ATR_NTSC,
329 							ATR_DEFAULT_FDS = ATR_NTSC
330 						};
331 
332 						Strings::Index file;
333 						Strings::Index path;
334 						Strings::Index name;
335 
336 						typedef Nes::Cartridge::Profile::Hash Hash;
337 
338 						Hash hash;
339 
340 						ushort pRom;
341 						ushort cRom;
342 						ushort wRam;
343 						ushort vRam;
344 						ushort mapper;
345 						uchar type;
346 						uchar attributes;
347 
348 					public:
349 
GetType() const350 						uint GetType() const
351 						{
352 							return type;
353 						}
354 
GetPath(const Strings & strings) const355 						wcstring GetPath(const Strings& strings) const
356 						{
357 							return strings[path];
358 						}
359 
GetFile(const Strings & strings) const360 						wcstring GetFile(const Strings& strings) const
361 						{
362 							return strings[file];
363 						}
364 
GetName(const Strings & strings,const Db * db) const365 						wcstring GetName(const Strings& strings,const Db* db) const
366 						{
367 							if (const Db::Entry entry = SearchDb( db ))
368 							{
369 								wcstring title = entry.GetTitle();
370 
371 								if (*title)
372 									return title;
373 							}
374 
375 							return name ? strings[name] : L"-";
376 						}
377 
GetPRom(const Db * db=NULL) const378 						uint GetPRom(const Db* db=NULL) const
379 						{
380 							if (const Db::Entry entry = SearchDb( db ))
381 								return entry.GetPrgRom() / Nes::Core::SIZE_1K;
382 							else
383 								return pRom;
384 						}
385 
GetCRom(const Db * db=NULL) const386 						uint GetCRom(const Db* db=NULL) const
387 						{
388 							if (const Db::Entry entry = SearchDb( db ))
389 								return entry.GetChrRom() / Nes::Core::SIZE_1K;
390 							else
391 								return cRom;
392 						}
393 
GetWRam(const Db * db=NULL) const394 						uint GetWRam(const Db* db=NULL) const
395 						{
396 							if (const Db::Entry entry = SearchDb( db ))
397 								return entry.GetWram() / Nes::Core::SIZE_1K;
398 							else
399 								return wRam;
400 						}
401 
GetVRam(const Db * db=NULL) const402 						uint GetVRam(const Db* db=NULL) const
403 						{
404 							if (const Db::Entry entry = SearchDb( db ))
405 								return entry.GetVram() / Nes::Core::SIZE_1K;
406 							else
407 								return vRam;
408 						}
409 
GetBattery(const Db * db=NULL) const410 						bool GetBattery(const Db* db=NULL) const
411 						{
412 							if (const Db::Entry entry = SearchDb( db ))
413 								return entry.HasBattery();
414 							else
415 								return (attributes & ATR_BATTERY);
416 						}
417 
GetMapper(const Db * db=NULL) const418 						uint GetMapper(const Db* db=NULL) const
419 						{
420 							if (const Db::Entry entry = SearchDb( db ))
421 								return entry.GetMapper();
422 							else
423 								return mapper;
424 						}
425 
GetDump(const Db * db=NULL) const426 						Nes::Cartridge::Profile::Dump::State GetDump(const Db* db=NULL) const
427 						{
428 							if (const Db::Entry entry = SearchDb( db ))
429 								return entry.GetDumpState();
430 							else
431 								return Nes::Cartridge::Profile::Dump::UNKNOWN;
432 						}
433 					};
434 
435 					typedef Collection::Vector<Entry> Entries;
436 
437 				private:
438 
439 					enum Exception
440 					{
441 						ERR_CORRUPT_DATA
442 					};
443 
444 					enum
445 					{
446 						MAX_ENTRIES = 0xFFFFF,
447 						GARBAGE_THRESHOLD = 127
448 					};
449 
450 					ushort dirty;
451 					ushort loaded;
452 					Strings strings;
453 					Entries entries;
454 
455 				public:
456 
Count() const457 					uint Count() const
458 					{
459 						return entries.Size();
460 					}
461 
operator [](uint i) const462 					const Entry& operator [] (uint i) const
463 					{
464 						return entries[i];
465 					}
466 
Disable(Entry * entry)467 					void Disable(Entry* entry)
468 					{
469 						if (entry->type)
470 						{
471 							entry->type = 0;
472 							dirty = true;
473 						}
474 					}
475 
GetStrings() const476 					const Strings& GetStrings() const
477 					{
478 						return strings;
479 					}
480 				};
481 
482 				class Columns
483 				{
484 				public:
485 
486 					explicit Columns(const Configuration&);
487 
488 					void Update(const uchar*);
489 					void Save(Configuration&) const;
490 
491 					enum Type
492 					{
493 						TYPE_FILE,
494 						TYPE_SYSTEM,
495 						TYPE_MAPPER,
496 						TYPE_PROM,
497 						TYPE_CROM,
498 						TYPE_WRAM,
499 						TYPE_VRAM,
500 						TYPE_BATTERY,
501 						TYPE_DUMP,
502 						TYPE_NAME,
503 						TYPE_FOLDER,
504 						NUM_TYPES,
505 						NUM_DEFAULT_SELECTED_TYPES = 9,
506 						NUM_DEFAULT_AVAILABLE_TYPES = NUM_TYPES - NUM_DEFAULT_SELECTED_TYPES
507 					};
508 
509 				private:
510 
511 					struct Handlers;
512 
513 					void Reset();
514 					void Add(uint,uint);
515 					void UpdateButtonRemove();
516 					void UpdateButtonAdd();
517 
518 					ibool OnInitDialog   (Param&);
519 					ibool OnCmdSelected  (Param&);
520 					ibool OnCmdAvailable (Param&);
521 					ibool OnCmdAdd       (Param&);
522 					ibool OnCmdRemove    (Param&);
523 					ibool OnCmdDefault   (Param&);
524 					ibool OnCmdOk        (Param&);
525 
526 					typedef Collection::Vector<uchar> Types;
527 
528 					Types available;
529 					Types selected;
530 					Dialog dialog;
531 
532 					static wcstring const cfgStrings[NUM_TYPES];
533 
534 				public:
535 
Count() const536 					uint Count() const
537 					{
538 						return selected.Size();
539 					}
540 
GetType(uint i) const541 					Type GetType(uint i) const
542 					{
543 						return Type(selected[i]);
544 					}
545 
GetStringId(uint i) const546 					uint GetStringId(uint i) const
547 					{
548 						return IDS_LAUNCHER_COLUMN_FILE + selected[i];
549 					}
550 
Open()551 					void Open()
552 					{
553 						dialog.Open();
554 					}
555 				};
556 
557 			private:
558 
559 				class Strings
560 				{
561 				public:
562 
563 					wcstring GetMapper(uint);
564 					wcstring GetSize(uint);
565 					void Flush();
566 
567 				private:
568 
569 					struct ValueString
570 					{
571 						wchar_t string[5];
572 					};
573 
574 					typedef String::Stack<10+1> SizeString;
575 					typedef std::map<uint,SizeString> Sizes;
576 					typedef Collection::Vector<ValueString> Mappers;
577 
578 					Sizes sizes;
579 					Mappers mappers;
580 				};
581 
582 				enum
583 				{
584 					STYLE =
585 					(
586 						LVS_EX_FULLROWSELECT |
587 						LVS_EX_TWOCLICKACTIVATE |
588 						LVS_EX_HEADERDRAGDROP
589 					)
590 				};
591 
592 				void ReloadListColumns() const;
593 				void UpdateColumnOrder();
594 				void UpdateSortColumnOrder(uint);
595 				void Redraw();
596 				int  Sorter(const void*,const void*);
597 				void OnFind(GenericString,uint);
598 				bool Optimize();
599 
600 				void OnCmdEditFind         (uint);
601 				void OnCmdEditInsert       (uint);
602 				void OnCmdEditDelete       (uint);
603 				void OnCmdEditClear        (uint);
604 				void OnCmdViewAlignColumns (uint);
605 				void OnCmdOptionsColumns   (uint);
606 
607 				Control::ListView ctrl;
608 
609 				const Nes::Cartridge::Database imageDatabase;
610 				const Nes::Cartridge::Database* useImageDatabase;
611 
612 				uchar order[Columns::NUM_TYPES];
613 
614 				uint typeFilter;
615 				uint style;
616 
617 				Finder finder;
618 				Paths paths;
619 				Files files;
620 				Columns columns;
621 				Strings strings;
622 				const Managers::Paths& pathManager;
623 
624 			public:
625 
GetWindow() const626 				Generic GetWindow() const
627 				{
628 					return ctrl.GetWindow();
629 				}
630 
OpenPathDialog()631 				void OpenPathDialog()
632 				{
633 					paths.Open();
634 				}
635 
Draw(uint type)636 				void Draw(uint type)
637 				{
638 					typeFilter = type;
639 					Redraw();
640 				}
641 
DatabaseCorrectionEnabled() const642 				bool DatabaseCorrectionEnabled() const
643 				{
644 					return useImageDatabase;
645 				}
646 
ToggleDatabase()647 				bool ToggleDatabase()
648 				{
649 					useImageDatabase = (useImageDatabase ? NULL : &imageDatabase);
650 					ctrl.Redraw();
651 					return useImageDatabase;
652 				}
653 
ToggleGrids()654 				bool ToggleGrids()
655 				{
656 					style ^= LVS_EX_GRIDLINES;
657 					ctrl.StyleEx() = style;
658 					return style & LVS_EX_GRIDLINES;
659 				}
660 
HitTest(const Point & point) const661 				bool HitTest(const Point& point) const
662 				{
663 					return ctrl.HitTest( point.x, point.y );
664 				}
665 
GetStyle() const666 				uint GetStyle() const
667 				{
668 					return ctrl.StyleEx();
669 				}
670 
GetHandle() const671 				HWND GetHandle() const
672 				{
673 					return ctrl.GetHandle();
674 				}
675 
NumPaths() const676 				uint NumPaths() const
677 				{
678 					return paths.GetSettings().folders.size();
679 				}
680 
Size() const681 				uint Size() const
682 				{
683 					return ctrl.Size();
684 				}
685 
operator [](uint i) const686 				const Files::Entry* operator [] (uint i) const
687 				{
688 					return static_cast<const Files::Entry*>(static_cast<const void*>( ctrl[i].Data() ));
689 				}
690 
GetSelection() const691 				const Files::Entry* GetSelection() const
692 				{
693 					int index = ctrl.Selection().GetIndex();
694 					return index >= 0 ? (*this)[index] : NULL;
695 				}
696 
GetStrings() const697 				const Files::Strings& GetStrings() const
698 				{
699 					return files.GetStrings();
700 				}
701 
GetPaths() const702 				const Managers::Paths& GetPaths() const
703 				{
704 					return pathManager;
705 				}
706 			};
707 
708 			class Tree
709 			{
710 			public:
711 
712 				Tree();
713 
714 				void operator = (const Control::TreeView&);
715 
716 				enum Updater {DONT_REPAINT,REPAINT};
717 
718 				void SetColors(uint,uint,Updater=DONT_REPAINT) const;
719 				uint GetType(HTREEITEM) const;
720 				void Close();
721 
722 			private:
723 
724 				Control::TreeView ctrl;
725 				uint selection;
726 				const Control::TreeView::ImageList imageList;
727 
728 			public:
729 
GetWindow() const730 				Generic GetWindow() const
731 				{
732 					return ctrl.GetWindow();
733 				}
734 			};
735 
736 			class Colors
737 			{
738 			public:
739 
740 				explicit Colors(const Configuration&);
741 
742 				void Save(Configuration&) const;
743 
744 			private:
745 
746 				struct Handlers;
747 
748 				enum
749 				{
750 					DEF_BACKGROUND_COLOR = RGB(0xFF,0xFF,0xFF),
751 					DEF_FOREGROUND_COLOR = RGB(0x00,0x00,0x00)
752 				};
753 
754 				struct Type
755 				{
756 					inline Type(int,int,int,int);
757 
758 					COLORREF color;
759 					const Rect rect;
760 				};
761 
762 				void UpdateColor(const Type&) const;
763 				void UpdateColors() const;
764 				void ChangeColor(COLORREF&);
765 
766 				ibool OnInitDialog          (Param&);
767 				ibool OnPaint               (Param&);
768 				ibool OnCmdChangeBackground (Param&);
769 				ibool OnCmdChangeForeground (Param&);
770 				ibool OnCmdDefault          (Param&);
771 
772 				Type background;
773 				Type foreground;
774 
775 				COLORREF customColors[16];
776 
777 				Dialog dialog;
778 
779 			public:
780 
GetBackgroundColor() const781 				COLORREF GetBackgroundColor() const
782 				{
783 					return background.color;
784 				}
785 
GetForegroundColor() const786 				COLORREF GetForegroundColor() const
787 				{
788 					return foreground.color;
789 				}
790 
Open()791 				void Open()
792 				{
793 					dialog.Open();
794 				}
795 			};
796 
797 			Dialog dialog;
798 			Menu menu;
799 			Control::NotificationHandler listNotifications;
800 			Control::NotificationHandler treeNotifications;
801 			StatusBar statusBar;
802 			Tree tree;
803 			List list;
804 			Point margin;
805 			Colors colors;
806 			Point initialSize;
807 		};
808 	}
809 }
810 
811 #endif
812