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