From aacf0365baa617a7c7b43c7d601c8d8925dafdba Mon Sep 17 00:00:00 2001 From: thrust26 Date: Thu, 27 Aug 2020 08:53:14 +0200 Subject: [PATCH 01/34] initial commit --- docs/debugger.html | 34 +++---- src/debugger/DebuggerParser.cxx | 11 +- src/debugger/gui/DebuggerDialog.cxx | 152 +++++++++++++++++++++++++++- src/debugger/gui/DebuggerDialog.hxx | 32 +++++- src/gui/BrowserDialog.cxx | 112 ++++++++++++++++---- src/gui/BrowserDialog.hxx | 2 +- src/gui/Dialog.cxx | 4 +- src/gui/Dialog.hxx | 12 +-- 8 files changed, 308 insertions(+), 51 deletions(-) diff --git a/docs/debugger.html b/docs/debugger.html index 781d05bf5..7e51a0333 100644 --- a/docs/debugger.html +++ b/docs/debugger.html @@ -74,7 +74,7 @@
  • Detailed Cartridge Extended RAM Information
  • -
  • Distella Configuration Files
  • +
  • DiStella Configuration Files
  • Tutorial: How to hack a ROM
  • @@ -119,14 +119,14 @@ feature that no other 2600 debugger has; it's completely cross-platform.<
  • Rewind previous advance operations and undo rewinds.
  • -
  • Supports Distella 'configuration directives', which may be used to +
  • Supports DiStella 'configuration directives', which may be used to override automatic code/data determination in the disassembly. For now, the following directives are supported: CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW. These directives can be entered at the debugger prompt, or be (automatically) loaded and saved in configuration files.
  • Extensive disassembly support, both from the emulation core and with help - from Distella. Where possible, the disassembly differentiates between code, + from DiStella. Where possible, the disassembly differentiates between code, player and playfield graphics, colors and audio (ie, addresses stored in GRPx, PFx, COLUxx, AUDxx) and data (addresses used as an operand of a command). Code sections are also @@ -294,7 +294,7 @@ more convenient.
  • "<rom_filename>.cfg"
    This file is described in - Distella Configuration Files. + DiStella Configuration Files.

  • @@ -917,7 +917,7 @@ Type "help 'cmd'" to see extended information about the given command.

    c - Carry Flag: set (0 or 1), or toggle (no arg) cheat - Use a cheat code (see manual for cheat types) clearbreaks - Clear all breakpoints - clearconfig - Clear Distella config directives [bank xx] + clearconfig - Clear DiStella config directives [bank xx] clearsavestateifs - Clear all savestate points cleartraps - Clear all traps clearwatches - Clear all watches @@ -954,11 +954,11 @@ clearsavestateifs - Clear all savestate points joy1fire - Set joystick 1 fire button to value <x> (0 or 1), or toggle (no arg) jump - Scroll disassembly to address xx listbreaks - List breakpoints - listconfig - List Distella config directives [bank xx] + listconfig - List DiStella config directives [bank xx] listfunctions - List user-defined functions listsavestateifs - List savestate points listtraps - List traps - loadconfig - Load Distella config file + loadconfig - Load DiStella config file loadallstates - Load all emulator states loadstate - Load emulator state xx (0-9) n - Negative Flag: set (0 or 1), or toggle (no arg) @@ -979,12 +979,12 @@ clearsavestateifs - Clear all savestate points s - Set Stack Pointer to value xx save - Save breaks, watches, traps and functions to file xx saveaccess - Save access counters to CSV file - saveconfig - Save Distella config file (with default name) - savedis - Save Distella disassembly (with default name) + saveconfig - Save DiStella config file (with default name) + savedis - Save DiStella disassembly (with default name) saverom - Save (possibly patched) ROM (with default name) saveses - Save console session (with default name) savesnap - Save current TIA image to PNG file - saveallstatea - Save all emulator states + saveallstates - Save all emulator states savestate - Save emulator state xx (valid args 0-9) savestateif - Create savestate on <condition> scanline - Advance emulation by <xx> scanlines (default=1) @@ -1333,11 +1333,11 @@ file is loaded, the disassembly will have labels. Even without a symbol file, th differentiate between code, graphics, data and unused bytes. There are actually two levels of disassembly in Stella. First, the emulation core tracks accesses as a game is running, making for very accurate results. This is known as a dynamic analysis. -Second, the built-in Distella code does a static analysis, which tentatively fills +Second, the built-in DiStella code does a static analysis, which tentatively fills in sections that the dynamic disassembler missed (usually because the addresses haven't been accessed at runtime yet).

    As such, code can be marked in two ways (absolute, when done by the emulation core), -and tentative (when done by Distella, and the emulation core hasn't accessed it yet). +and tentative (when done by DiStella, and the emulation core hasn't accessed it yet). Such 'tentative' code is marked with the '*' symbol, indicating that it has the potential to be accessed as code sometime during the program run. This gives very useful information, since it can indicate areas toggled by an option in the game (ie, when a player dies, @@ -1363,7 +1363,7 @@ by the break command, not the conditional "bre (which makes sense: conditional breaks can break on any condition, the Program Counter isn't necessarily involved).

  • Labels: Any labels assigned to the given address, either generated -automatically by Distella, read from a DASM symbol file or custom +automatically by DiStella, read from a DASM symbol file or custom labels created by the user. If 'Show PC addresses' (see ROM Disassembly Settings) is enabled, the address will be shown in grey.
  • @@ -1377,7 +1377,7 @@ Note that only code, graphics or data will show bytes and can be edited.

    At this point, we should explain the various 'types' that the disassembler can use. These are known as 'directives', and partly correspond to configuration -options from the standalone Distella program. They are listed in order of +options from the standalone DiStella program. They are listed in order of decreasing hierarchy:

    @@ -1504,7 +1504,7 @@ matches the address of the disassembly line where the mouse was clicked.
  • Disassemble @ current line: Disassemble from the disassembly line where the mouse was clicked. This allows to fill gaps in the disassembly and is most useful for bankswitched ROMs.
  • -
  • Show tentative code: Allow Distella to do a static analysis/disassembly.
  • +
  • Show tentative code: Allow DiStella to do a static analysis/disassembly.
  • Show PC addresses: Show Program Counter addresses as labels (where there isn't already a defined label).
  • @@ -1512,7 +1512,7 @@ isn't already a defined label).
  • Show GFX as binary: Switch between displaying/editing GFX and PGFX sections in either binary or hexidecimal.
  • -
  • Use address relocation: Corresponds to the Distella '-r' option +
  • Use address relocation: Corresponds to the DiStella '-r' option (Relocate calls out of address range).
    Note: The code will continue to run fine, but the ROM image will be altered.
  • @@ -1587,7 +1587,7 @@ the RAM in the DPC scheme is not viewable by the 6507, so its addresses start fr
    -

    Distella Configuration Files

    +

    DiStella Configuration Files

    As mentioned in ROM Disassembly, Stella supports the following directives: CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW. While the debugger will try to automatically mark address space with the appropriate directive, there are times when it will fail. There are diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 73f09268f..97c302392 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -35,6 +35,7 @@ #include "PromptWidget.hxx" #include "RomWidget.hxx" #include "ProgressDialog.hxx" +#include "BrowserDialog.hxx" #include "TimerManager.hxx" #include "Vec.hxx" @@ -1828,14 +1829,20 @@ void DebuggerParser::executeS() // "save" void DebuggerParser::executeSave() { - commandResult << saveScriptFile(argStrings[0]); + if(argCount && argStrings[0] == "?") + debugger.myDialog->showBrowser(DebuggerDialog::svScript); + else + commandResult << saveScriptFile(argStrings[0]); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "saveaccess" void DebuggerParser::executeSaveAccess() { - commandResult << debugger.cartDebug().saveAccessFile(); + if(argCount && argStrings[0] == "?") + debugger.myDialog->showBrowser(DebuggerDialog::svAccess); + else + commandResult << debugger.cartDebug().saveAccessFile(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index be9ad7515..9c51f567b 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -37,19 +37,20 @@ #include "DataGridOpsWidget.hxx" #include "EditTextWidget.hxx" #include "MessageBox.hxx" -#include "Debugger.hxx" -#include "DebuggerParser.hxx" +#include "debugger.hxx" +#include "debuggerParser.hxx" #include "ConsoleFont.hxx" #include "ConsoleBFont.hxx" #include "ConsoleMediumFont.hxx" #include "ConsoleMediumBFont.hxx" #include "StellaMediumFont.hxx" #include "OptionsDialog.hxx" +#include "BrowserDialog.hxx" #include "StateManager.hxx" #include "FrameManager.hxx" #include "OSystem.hxx" #include "Console.hxx" -#include "DebuggerDialog.hxx" +#include "debuggerDialog.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent, @@ -256,6 +257,43 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd, loadConfig(); break; + case kSvScriptCmd: + execSave("save"); + break; + + case kSvSessionCmd: + execSave("saveses"); + break; + + case kSvConfigCmd: + execSave("saveconfig"); + break; + + case kSvDisCmd: + execSave("savedis"); + break; + + case kSvAccessCmd: + execSave("saveaccess"); + break; + + case kSvRomCmd: + execSave("saverom"); + break; + + case kSvStateCmd: + execSave("savestate"); + break; + + + case kSvAllStatesCmd: + execSave("saveallstates"); + break; + + case kSvSnapCmd: + execSave("savesnap"); // TODO: param + break; + case RomWidget::kInvalidateListing: // Only do a full redraw if the disassembly tab is actually showing myRom->invalidate(myRomTab->getActiveTab() == 0); @@ -408,6 +446,114 @@ void DebuggerDialog::createFont() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DebuggerDialog::showBrowser(BrowserType type) +{ + int cmd; + string title; + string key; + string defaultPath; + + switch(type) + { + case BrowserType::svScript: + cmd = kSvScriptCmd; + title = "workbench"; + key = "dbg.savepath"; + defaultPath = instance().defaultSaveDir().getPath() + "commands.script"; + break; + + case BrowserType::svSession: + cmd = kSvSessionCmd; + title = "session"; + key = "dbg.savesessionpath"; + break; + + case BrowserType::svConfig: + cmd = kSvConfigCmd; + title = "DiStella config"; + key = "dbg.saveconfigpath"; + break; + + case BrowserType::svDis: + cmd = kSvDisCmd; + title = "disassembly"; + key = "dbg.savedispath"; + break; + + case BrowserType::svAccess: + cmd = kSvAccessCmd; + title = "access counters"; + key = "dbg.saveaccesspath"; + break; + + case BrowserType::svRom: + cmd = kSvRomCmd; + title = "ROM"; + key = "dbg.saverompath"; + break; + + case BrowserType::svState: + cmd = kSvStateCmd; + title = "state"; + key = "dbg.savestatepath"; + break; + + case BrowserType::svAllStates: + cmd = kSvAllStatesCmd; + title = "all states"; + key = "dbg.savestatepath"; + break; + + case BrowserType::svSnap: + cmd = kSvSnapCmd; + title = "snapshot"; + key = "snapsavedir"; + break; + + default: + cmd = 0; + break; + } + + if(cmd) + { + //TODO: default path (path and filename) + string path = instance().settings().getString(key); + + createBrowser("Save " + title + " as"); + + if(path.empty()) + path = defaultPath; + + //myBrowser->show(instance().defaultSaveDir().getPath(), + // BrowserDialog::FileSave, cmd); + myBrowser->show(path, BrowserDialog::FileSave, cmd); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DebuggerDialog::execSave(const string& command) +{ + FilesystemNode dir(myBrowser->getResult()); + + instance().debugger().parser().run(command + " " + dir.getShortPath()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DebuggerDialog::createBrowser(const string& title) +{ + uInt32 w = 0, h = 0; + getDynamicBounds(w, h); + + // Create file browser dialog + if(!myBrowser || uInt32(myBrowser->getWidth()) != w || + uInt32(myBrowser->getHeight()) != h) + myBrowser = make_unique(this, instance().frameBuffer().font(), w, h, title); + else + myBrowser->setTitle(title); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerDialog::showFatalMessage(const string& msg) { diff --git a/src/debugger/gui/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx index 0affa5160..76fb869bb 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -34,6 +34,7 @@ class TiaZoomWidget; class CartDebugWidget; class CartRamWidget; class OptionsDialog; +class BrowserDialog; namespace GUI { class MessageBox; @@ -54,6 +55,17 @@ class DebuggerDialog : public Dialog kMediumFontMinW = 1160, kMediumFontMinH = 770, kLargeFontMinW = 1160, kLargeFontMinH = 870 }; + enum BrowserType { + svScript, // save + svSession, // saveses + svConfig, // saveconfig + svDis, // savedis + svAccess, // saveaccess + svRom, // saverom + svState, // savestate + svAllStates, // saveallstates + svSnap // savesnap + }; DebuggerDialog(OSystem& osystem, DialogContainer& parent, int x, int y, int w, int h); @@ -74,6 +86,7 @@ class DebuggerDialog : public Dialog void showFatalMessage(const string& msg); void saveConfig() override; + void showBrowser(BrowserType type); private: void center() override { positionAt(0); } @@ -113,11 +126,23 @@ class DebuggerDialog : public Dialog kDDSAdvCmd = 'DDsv', kDDRewindCmd = 'DDrw', kDDUnwindCmd = 'DDuw', - kDDRunCmd = 'DDex', + kDDRunCmd = 'DDex', kDDExitFatalCmd = 'DDer', - kDDOptionsCmd = 'DDop' + kDDOptionsCmd = 'DDop', + kSvScriptCmd = 'SvSc', + kSvSessionCmd = 'SvSs', + kSvConfigCmd = 'SvCn', + kSvDisCmd = 'SvDs', + kSvAccessCmd = 'SvAc', + kSvRomCmd = 'SvRm', + kSvStateCmd = 'SvSt', + kSvAllStatesCmd = 'SvAs', + kSvSnapCmd = 'SvSn' }; + void execSave(const string& command); + void createBrowser(const string& title); + TabWidget *myTab{nullptr}, *myRomTab{nullptr}; PromptWidget* myPrompt{nullptr}; @@ -135,7 +160,8 @@ class DebuggerDialog : public Dialog ButtonWidget* myUnwindButton{nullptr}; unique_ptr myFatalError; - unique_ptr myOptions; + unique_ptr myOptions; + unique_ptr myBrowser; unique_ptr myLFont; // used for labels unique_ptr myNFont; // used for normal text diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 544ff4518..49a311763 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -74,7 +74,7 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, _type = new StaticTextWidget(this, font, xpos, ypos + 2, "Name "); _selected = new EditTextWidget(this, font, xpos + _type->getWidth(), ypos, _w - _type->getWidth() - 2 * xpos, lineHeight, ""); - _selected->setEditable(false); + addFocusWidget(_selected); // Buttons _goUpButton = new ButtonWidget(this, font, xpos, _h - buttonHeight - VBORDER, @@ -112,45 +112,71 @@ void BrowserDialog::show(const string& startpath, BrowserDialog::ListMode mode, int cmd, const string& ext) { +#ifdef BSPF_WINDOWS + #define PATH_SEPARATOR '\\' +#else + #define PATH_SEPARATOR '/' +#endif _cmd = cmd; _mode = mode; + string fileName; + + // Set start path + if(_mode != Directories) + { + // split startpath into path and filename + FilesystemNode fs = FilesystemNode(startpath); + fileName = fs.getName(); + string directory = fs.isDirectory() ? "" : fs.getParent().getPath(); + + _fileList->setDirectory(FilesystemNode(directory), fileName); + } + else + { + _fileList->setDirectory(FilesystemNode(startpath)); + } switch(_mode) { case FileLoad: _fileList->setListMode(FilesystemNode::ListMode::All); - _fileList->setNameFilter([&ext](const FilesystemNode& node) { + _fileList->setNameFilter([ext](const FilesystemNode& node) { return BSPF::endsWithIgnoreCase(node.getName(), ext); }); _selected->setEditable(false); + _selected->setEnabled(false); _selected->clearFlags(Widget::FLAG_INVISIBLE); _type->clearFlags(Widget::FLAG_INVISIBLE); + _okWidget->setLabel("Load"); + updateUI(true); break; case FileSave: _fileList->setListMode(FilesystemNode::ListMode::All); - _fileList->setNameFilter([&ext](const FilesystemNode& node) { + _fileList->setNameFilter([ext](const FilesystemNode& node) { return BSPF::endsWithIgnoreCase(node.getName(), ext); }); - _selected->setEditable(false); // FIXME - disable user input for now + _selected->setEditable(true); + _selected->setEnabled(true); _selected->clearFlags(Widget::FLAG_INVISIBLE); _type->clearFlags(Widget::FLAG_INVISIBLE); + _okWidget->setLabel("Save"); + _selected->setText(fileName); + updateUI(false); break; case Directories: _fileList->setListMode(FilesystemNode::ListMode::DirectoriesOnly); _fileList->setNameFilter([](const FilesystemNode&) { return true; }); _selected->setEditable(false); + _selected->setEnabled(false); _selected->setFlags(Widget::FLAG_INVISIBLE); _type->setFlags(Widget::FLAG_INVISIBLE); + _okWidget->setLabel("Choose"); + updateUI(true); break; } - // Set start path - _fileList->setDirectory(FilesystemNode(startpath)); - - updateUI(); - // Finally, open the dialog after it has been fully updated open(); } @@ -159,13 +185,17 @@ void BrowserDialog::show(const string& startpath, const FilesystemNode& BrowserDialog::getResult() const { if(_mode == FileLoad || _mode == FileSave) - return _fileList->selected(); + { + static FilesystemNode node(_fileList->currentDir().getShortPath() + _selected->getText()); + + return node; + } else return _fileList->currentDir(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void BrowserDialog::updateUI() +void BrowserDialog::updateUI(bool fileSelected) { // Only hilite the 'up' button if there's a parent directory _goUpButton->setEnabled(_fileList->currentDir().hasParent()); @@ -174,13 +204,56 @@ void BrowserDialog::updateUI() _currentPath->setText(_fileList->currentDir().getShortPath()); // Enable/disable OK button based on current mode - bool enable = _mode == Directories || !_fileList->selected().isDirectory(); + //bool enable = true; + //switch(_mode) + //{ + // case Directories: + // enable = true; + // break; + + // case FileLoad: + // if(_fileList->selected().isDirectory()) + // { + // enable = false; + // _selected->setText(""); + // } + // else + // { + // enable = fileSelected && !_selected->getText().empty(); + // _selected->setText(_fileList->getSelectedString()); + // } + // break; + + // case FileSave: + // if(_fileList->selected().isDirectory()) + // { + // enable = false; + // _selected->setText(""); + // } + // else + // { + // enable = fileSelected && !_selected->getText().empty(); // TODO + // _selected->setText(_fileList->getSelectedString()); + // } + // break; + + // default: + // break; + //} + //_okWidget->setEnabled(enable); + + bool enable = _mode == Directories + || (!_fileList->selected().isDirectory() && fileSelected) + || (!_selected->getText().empty() && !fileSelected); _okWidget->setEnabled(enable); - if(!_fileList->selected().isDirectory()) - _selected->setText(_fileList->getSelectedString()); - else - _selected->setText(""); + if(fileSelected) + { + if(!_fileList->selected().isDirectory()) + _selected->setText(_fileList->getSelectedString()); + else + _selected->setText(""); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -205,8 +278,13 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd, _fileList->setDirectory(FilesystemNode(instance().baseDir())); break; + case EditableWidget::kChangedCmd: + Dialog::handleCommand(sender, cmd, data, 0); + updateUI(false); + break; + case FileListWidget::ItemChanged: - updateUI(); + updateUI(true); break; default: diff --git a/src/gui/BrowserDialog.hxx b/src/gui/BrowserDialog.hxx index 253e183b7..75a84c7c3 100644 --- a/src/gui/BrowserDialog.hxx +++ b/src/gui/BrowserDialog.hxx @@ -52,7 +52,7 @@ class BrowserDialog : public Dialog, public CommandSender private: void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - void updateUI(); + void updateUI(bool fileSelected); private: enum { diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 85c95349f..7c1d7ecd5 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -684,7 +684,7 @@ bool Dialog::handleNavEvent(Event::Type e, bool repeated) if(_okWidget && _okWidget->isEnabled() && !repeated) { // Receiving 'OK' is the same as getting the 'Select' event - _okWidget->handleEvent(Event::UISelect); + //_okWidget->handleEvent(Event::UISelect); return true; } break; @@ -693,7 +693,7 @@ bool Dialog::handleNavEvent(Event::Type e, bool repeated) if(_cancelWidget && _cancelWidget->isEnabled() && !repeated) { // Receiving 'Cancel' is the same as getting the 'Select' event - _cancelWidget->handleEvent(Event::UISelect); + //_cancelWidget->handleEvent(Event::UISelect); return true; } else if(_processCancel) diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 1f6bbec60..001dafcc0 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -73,9 +73,9 @@ class Dialog : public GuiObject void addToFocusList(WidgetArray& list, TabWidget* w, int tabId); void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; } void addTabWidget(TabWidget* w); - void addDefaultWidget(Widget* w) { _defaultWidget = w; } - void addOKWidget(Widget* w) { _okWidget = w; } - void addCancelWidget(Widget* w) { _cancelWidget = w; } + void addDefaultWidget(ButtonWidget* w) { _defaultWidget = w; } + void addOKWidget(ButtonWidget* w) { _okWidget = w; } + void addCancelWidget(ButtonWidget* w) { _cancelWidget = w; } void setFocus(Widget* w); /** Returns the base surface associated with this dialog. */ @@ -192,9 +192,9 @@ class Dialog : public GuiObject Widget* _mouseWidget{nullptr}; Widget* _focusedWidget{nullptr}; Widget* _dragWidget{nullptr}; - Widget* _defaultWidget{nullptr}; - Widget* _okWidget{nullptr}; - Widget* _cancelWidget{nullptr}; + ButtonWidget* _defaultWidget{nullptr}; + ButtonWidget* _okWidget{nullptr}; + ButtonWidget* _cancelWidget{nullptr}; bool _visible{false}; bool _onTop{true}; From ad7e15139dd91916aa9dec91bcf255194cd485f8 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Wed, 2 Sep 2020 17:50:48 -0230 Subject: [PATCH 02/34] Fix compile errors. --- src/debugger/gui/DebuggerDialog.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 9c51f567b..17716b634 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -37,8 +37,8 @@ #include "DataGridOpsWidget.hxx" #include "EditTextWidget.hxx" #include "MessageBox.hxx" -#include "debugger.hxx" -#include "debuggerParser.hxx" +#include "Debugger.hxx" +#include "DebuggerParser.hxx" #include "ConsoleFont.hxx" #include "ConsoleBFont.hxx" #include "ConsoleMediumFont.hxx" @@ -50,7 +50,7 @@ #include "FrameManager.hxx" #include "OSystem.hxx" #include "Console.hxx" -#include "debuggerDialog.hxx" +#include "DebuggerDialog.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent, From 39aabf0f66e106701cddab0f0c3d28157ef05abd Mon Sep 17 00:00:00 2001 From: thrust26 Date: Tue, 22 Dec 2020 12:18:39 +0100 Subject: [PATCH 03/34] added tooltip to GameInfoDialog 'Save' button --- src/gui/Dialog.cxx | 8 ++++---- src/gui/Dialog.hxx | 2 ++ src/gui/GameInfoDialog.cxx | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 95107b7b3..4ae7e7921 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -971,10 +971,10 @@ void Dialog::addDefaultsExtraOKCancelBGroup( buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd)); wid.push_back(_defaultWidget); - wid.push_back(new ButtonWidget(this, font, HBORDER + buttonWidth + BUTTON_GAP, - _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, - extraText, extraCmd) - ); + addExtraWidget(new ButtonWidget(this, font, HBORDER + buttonWidth + BUTTON_GAP, + _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, + extraText, extraCmd)); + wid.push_back(_extraWidget); addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth); } diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 022334e47..e291cdacb 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -76,6 +76,7 @@ class Dialog : public GuiObject void addBGroupToFocusList(const WidgetArray& list) { _buttonGroup = list; } void addTabWidget(TabWidget* w); void addDefaultWidget(Widget* w) { _defaultWidget = w; } + void addExtraWidget(Widget* w) { _extraWidget = w; } void addOKWidget(Widget* w) { _okWidget = w; } void addCancelWidget(Widget* w) { _cancelWidget = w; } void setFocus(Widget* w); @@ -196,6 +197,7 @@ class Dialog : public GuiObject Widget* _focusedWidget{nullptr}; Widget* _dragWidget{nullptr}; Widget* _defaultWidget{nullptr}; + Widget* _extraWidget{nullptr}; Widget* _okWidget{nullptr}; Widget* _cancelWidget{nullptr}; diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 113569c0c..90628534c 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -93,6 +93,8 @@ GameInfoDialog::GameInfoDialog( // Add Defaults, OK and Cancel buttons addDefaultsExtraOKCancelBGroup(wid, font, "Save", kSavePressed); + _extraWidget->setToolTip("Save the current ROM's properties in a\n" + "separate file in the default directory."); addBGroupToFocusList(wid); } From 96e5e251484c2da209ff194d5134eb3f6c7fda3a Mon Sep 17 00:00:00 2001 From: thrust26 Date: Tue, 22 Dec 2020 14:56:48 +0100 Subject: [PATCH 04/34] renamed Game properties 'Save' button into 'Export' --- docs/graphics/options_gameinfo_cartridge.png | Bin 3168 -> 3454 bytes docs/graphics/options_gameinfo_console.png | Bin 2540 -> 2801 bytes docs/graphics/options_gameinfo_controller.png | Bin 4188 -> 4494 bytes docs/graphics/options_gameinfo_emulation.png | Bin 3279 -> 3630 bytes docs/graphics/options_gameinfo_highscores.png | Bin 3556 -> 3565 bytes docs/index.html | 8 ++++---- src/gui/GameInfoDialog.cxx | 16 ++++++++-------- src/gui/GameInfoDialog.hxx | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/graphics/options_gameinfo_cartridge.png b/docs/graphics/options_gameinfo_cartridge.png index b90761623b49600452ce6424dffe64eee68f17ec..da6f4fdc4409cf8582a8356dc9d02f4c6b16dc32 100644 GIT binary patch literal 3454 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 ZxyHC9yZeF7uJz9l!klJBEigG7@h^~}Pvrmr literal 3168 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 JEA=t={t2I!OeO#T literal 2540 zcmd5;`#%#38z0fd-LW_-oOH^iIxeG~8Fi54S}vP2mslYS?ZS=19eBNK)^AEhw=kt7?&-eTM^xU81tB%&PQb(i!0D!E` z<%`Y$fY`i9JtX#t7}XCct|B8A?rd!Vs2x7GC;}2Fa|d$(pgvt%h?Epz{j2t_Rw5f1 z7+7tj&<6mFAv9 z31h2VvXk{R7Tz0d=vZiBb}YQ5L&ZVz_eqJrf(Wy@)BY~JtGNh2u=ll6FAyz_Y22v2 zq02n8>jAV#x}>IE;hncZuB%wJA|J&5#4PvQ?qzHH-Dg0^JMMqZNRB}+Wk8+Z7kTIzGsa<&#Q6#$g3KGGy^u{SNZa9g0xJrn2~_#` zBG~mO7gVgKib5WFZK8~|oLapCwI)zGgF&4>)8jhiWf_4Q?Ep{}U8Izuejjq!nzH~T zVw1GiG>pNb5ZX;0zCEU?3k+2NN1 zOfv=$=8*2!>WK>7Z87OnSsXpA8Xz^jN53UGLBtQ>?b>80tLQ9P|I~2JU;*r5kh8!7 z#YKi8>pI1|h!D(hcvX(7&vWw*xz;5~_8SU+V$~}YB%fD$-Z}9nUtU8U- zv&t~Kxj-=<7-0a{7vv~;`0_B;7WD`%$K%-?b*K6^x$m~IGwlMD(;cmI5A62YkV)&8 zksl#6dQ>UCl_BD~`TAF~ALF;2tCL+Hs>RL!sAgCc0unxX{+PS!$w_5Fn$sY5cupZO z>OtH#mc;A;s&8ib?5A8;-t?|j_839)e7`6Vu?HEZ5*+_^lS&+{V|ehdh>fGmRf6~1 z0v3ygqco=!w6#gEU?p)UFtwlZ)MS@`n_t{rJy%y@8PE*38BJu~AT z&2<*oPTR&_%h(n?^NabWoI`;@2j{UT8(8{5IeFU5xo@^a_BFD*Fw~pshobW^n!M$U za8gA9|3iXFc_7KaHz9!pla3oIU$o^N`wSbvQT-OCAYtA1MuWp%oE+nL2rVb_1%-?K z8nWBuc)n_O@0Bss?OfAsk5q6f>v?~EHy;KM@Wr*Pg#;Hwr45<6jq8U;fYz4YoAqM& zH&H)a(VD)XccNN0z4*r>|Blnc;M?fy7R^TJoY#2p>Ce+c**&8xko(95}~r>$(2kulEb^3A?jl%q>B$& z`&%(u`RB_fw=sO#Sq-Q!K9T74uSQ)<^tJ5+K($W|n**5fa|hYR`ekbM+OK~5AiO`9 zzyKNw=xJ6RlqJL9q8hFDSlzX!U7m;w$)`P-!#AWkhIoyAEtut+6|o~+W?9AP4&~4W z#@6?A6xA`7np3liAYbx^hC(IGLR|u{3f^en8IX*G${H-Ot9+(6a%wtE-JBlNIfZ8T zf*EEg-AN~nCi?GKL9`AOHMwX*-2C}_=CB8skkU7_mXIl2s~B?7k8NIe&Mq*NcYN>T5#@$Bt4-2N(awg z30|-qi@qMQ%VR|7QTDo4caZLhlcD009^z0`>kfhpx7f$Ih2)##g!vcGW@*gEztAG$ zZ{k#A@OHb=E}h4W;-cz`u63oj zUyjIXDB9w;?>A#`6a63MP_fo4tWfFXASGZR;YNR9CA-&!yg!gBE!FyLXZN0cO#76bkQzpt`sU!Emd<)=&OV2S!bXw#*s2xQ*hdVQqPnTvW)?Te zgl{OfMGLxyPL;SO&BQeR-MQ6?XMgTS2Rosfm5}hHnbsHnYNS?J!J^cgO8m3;|FdoWKjgWdVaUcay>Sks8UbRMQNkZ!?Z01q z5GxG2rW4y^q&K*K0*5#xIx+t(dh46y$By262l91wypt5e4t)Q;Y^)qF)>`;H_%|Zb B^^O1l diff --git a/docs/graphics/options_gameinfo_controller.png b/docs/graphics/options_gameinfo_controller.png index 2714e5407ceab7d4ea2cbd4eb73ec453f1f8c28c..6b8740424429ef7e86ba52c72c8694754293d8cb 100644 GIT binary patch literal 4494 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 Ujmiakmm?fTdS<$XI*!l&4=k6kZ2$lO delta 4137 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 H%lG~dElH;} diff --git a/docs/graphics/options_gameinfo_emulation.png b/docs/graphics/options_gameinfo_emulation.png index 55c1e68938456a0408b0fab764001a8ef5b0a11f..8da3b8c42aeaea886f842f82b68aa9a2f21f044c 100644 GIT binary patch literal 3630 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 M8k?Uc8M@s2H|g{1i~s-t delta 3221 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 Hn@|1^AO70i diff --git a/docs/graphics/options_gameinfo_highscores.png b/docs/graphics/options_gameinfo_highscores.png index 6d18323e5ef682e78b22411ad804fc9b311ededf..9a6e7f1d261fc6aec26b5c369ba45e94d0a1f655 100644 GIT binary patch delta 3487 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 C89g`v delta 3478 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 diff --git a/docs/index.html b/docs/index.html index f679feab6..d6cfdb001 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5003,11 +5003,11 @@ Ms Pac-Man (Stella extended codes):

    The buttons at the bottom of the dialogs work as follows:

    The name of the properties file will depend on the version of Stella, as follows:

    diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 90628534c..40c1288d8 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -92,9 +92,9 @@ GameInfoDialog::GameInfoDialog( myTab->setActiveTab(0); // Add Defaults, OK and Cancel buttons - addDefaultsExtraOKCancelBGroup(wid, font, "Save", kSavePressed); - _extraWidget->setToolTip("Save the current ROM's properties in a\n" - "separate file in the default directory."); + addDefaultsExtraOKCancelBGroup(wid, font, "Export", kExportPressed); + _extraWidget->setToolTip("Export the current ROM's properties\n" + "into the default directory."); addBGroupToFocusList(wid); } @@ -1341,7 +1341,7 @@ void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget valWidget->setText(""); } -void GameInfoDialog::saveCurrentPropertiesToDisk() +void GameInfoDialog::exportCurrentPropertiesToDisk() { saveProperties(); stringstream out; @@ -1353,12 +1353,12 @@ void GameInfoDialog::saveCurrentPropertiesToDisk() propfile /= myGameFile.getNameWithExt(".pro"); propfile.write(out); - instance().frameBuffer().showTextMessage("Properties saved to " + + instance().frameBuffer().showTextMessage("Properties exported to " + propfile.getShortPath()); } catch(...) { - instance().frameBuffer().showTextMessage("Error saving properties"); + instance().frameBuffer().showTextMessage("Error exporting properties"); } } @@ -1377,8 +1377,8 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, setDefaults(); break; - case kSavePressed: - saveCurrentPropertiesToDisk(); + case kExportPressed: + exportCurrentPropertiesToDisk(); break; case TabWidget::kTabChangedCmd: diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index 2e9a92841..cb2d4c0c7 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -180,7 +180,7 @@ class GameInfoDialog : public Dialog, public CommandSender kHiScoresChanged = 'HSch', kPXCenterChanged = 'Pxch', kPYCenterChanged = 'Pych', - kSavePressed = 'GIsp' + kExportPressed = 'GIsp' }; // Game properties for currently loaded ROM From bd2029bbcc82d3e2eff4f4a5d758d51b93040256 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Tue, 22 Dec 2020 10:39:49 -0330 Subject: [PATCH 05/34] Fix compile error. --- src/gui/GameInfoDialog.cxx | 1 + src/gui/GameInfoDialog.hxx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 40c1288d8..3700caf5f 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -1341,6 +1341,7 @@ void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget valWidget->setText(""); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::exportCurrentPropertiesToDisk() { saveProperties(); diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index cb2d4c0c7..c217bd689 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -77,7 +77,7 @@ class GameInfoDialog : public Dialog, public CommandSender // set formatted memory value for given address field void setAddressVal(EditTextWidget* address, EditTextWidget* val, bool isBCD = true, bool zeroBased = false, uInt8 maxVal = 255); - void saveCurrentPropertiesToDisk(); + void exportCurrentPropertiesToDisk(); private: TabWidget* myTab{nullptr}; From a30d2cbead37553fd4f4bcc54f6ff87d2075d2f8 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Tue, 22 Dec 2020 19:59:15 +0100 Subject: [PATCH 06/34] intentionally broken code for testing libretro build notifications --- src/common/bspf.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index d43080b7e..dc269f5cb 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -117,7 +117,7 @@ static const string EmptyString(""); namespace BSPF { - static constexpr float PI_f = 3.141592653589793238462643383279502884F; + statix constexpr float PI_f = 3.141592653589793238462643383279502884F; static constexpr double PI_d = 3.141592653589793238462643383279502884; // CPU architecture type From 1799c87dca198441399762c1b557f6aa55853645 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Tue, 22 Dec 2020 20:43:45 +0100 Subject: [PATCH 07/34] Revert "intentionally broken code for testing libretro build notifications" This reverts commit a30d2cbead37553fd4f4bcc54f6ff87d2075d2f8. --- src/common/bspf.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index dc269f5cb..d43080b7e 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -117,7 +117,7 @@ static const string EmptyString(""); namespace BSPF { - statix constexpr float PI_f = 3.141592653589793238462643383279502884F; + static constexpr float PI_f = 3.141592653589793238462643383279502884F; static constexpr double PI_d = 3.141592653589793238462643383279502884; // CPU architecture type From 8f7af1c356e252c608e4c6f2eb6f604bc9f0f85c Mon Sep 17 00:00:00 2001 From: thrust26 Date: Tue, 22 Dec 2020 20:48:54 +0100 Subject: [PATCH 08/34] 2nd try to get notifications --- src/common/bspf.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index d43080b7e..382531416 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -118,7 +118,7 @@ static const string EmptyString(""); namespace BSPF { static constexpr float PI_f = 3.141592653589793238462643383279502884F; - static constexpr double PI_d = 3.141592653589793238462643383279502884; + stati2 constexpr double PI_d = 3.141592653589793238462643383279502884; // CPU architecture type // This isn't complete yet, but takes care of all the major platforms From c59bf70656b070fc039973a21fa92b367139f5c3 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Tue, 22 Dec 2020 21:07:19 +0100 Subject: [PATCH 09/34] Revert "2nd try to get notifications" This reverts commit 8f7af1c356e252c608e4c6f2eb6f604bc9f0f85c. --- src/common/bspf.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index 382531416..d43080b7e 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -118,7 +118,7 @@ static const string EmptyString(""); namespace BSPF { static constexpr float PI_f = 3.141592653589793238462643383279502884F; - stati2 constexpr double PI_d = 3.141592653589793238462643383279502884; + static constexpr double PI_d = 3.141592653589793238462643383279502884; // CPU architecture type // This isn't complete yet, but takes care of all the major platforms From 2a07daccb45bc9de607850be029ed61c9975a791 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Tue, 22 Dec 2020 18:33:30 -0330 Subject: [PATCH 10/34] Added a few more 'string_view' in bspf. --- src/common/bspf.hxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index d43080b7e..4a17719ad 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -242,7 +242,7 @@ namespace BSPF // Find location (if any) of the second string within the first, // starting from 'startpos' in the first string - static size_t findIgnoreCase(const string& s1, const string& s2, size_t startpos = 0) + static size_t findIgnoreCase(string_view s1, string_view s2, size_t startpos = 0) { auto pos = std::search(s1.cbegin()+startpos, s1.cend(), s2.cbegin(), s2.cend(), [](char ch1, char ch2) { @@ -252,7 +252,7 @@ namespace BSPF } // Test whether the first string contains the second one (case insensitive) - inline bool containsIgnoreCase(const string& s1, const string& s2) + inline bool containsIgnoreCase(string_view s1, string_view s2) { return findIgnoreCase(s1, s2) != string::npos; } @@ -260,7 +260,7 @@ namespace BSPF // Test whether the first string matches the second one (case insensitive) // - the first character must match // - the following characters must appear in the order of the first string - inline bool matches(const string& s1, const string& s2) + inline bool matches(string_view s1, string_view s2) { if(startsWithIgnoreCase(s1, s2.substr(0, 1))) { From f0cb9162823ff5a2d95e7408d6fd16d5aa985fe6 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Tue, 22 Dec 2020 19:29:49 -0330 Subject: [PATCH 11/34] Few more fixes for suggestions from cppcheck. --- src/common/PJoystickHandler.hxx | 2 +- src/debugger/gui/RiotWidget.cxx | 3 +-- src/emucore/CartCM.hxx | 2 +- src/gui/DeveloperDialog.cxx | 14 +++++++------- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/common/PJoystickHandler.hxx b/src/common/PJoystickHandler.hxx index 6a23f923b..1e48f80e5 100644 --- a/src/common/PJoystickHandler.hxx +++ b/src/common/PJoystickHandler.hxx @@ -49,7 +49,7 @@ class PhysicalJoystickHandler private: struct StickInfo { - StickInfo(nlohmann::json map, PhysicalJoystickPtr stick = nullptr) + explicit StickInfo(nlohmann::json map, PhysicalJoystickPtr stick = nullptr) : mapping(map), joy{std::move(stick)} {} nlohmann::json mapping; diff --git a/src/debugger/gui/RiotWidget.cxx b/src/debugger/gui/RiotWidget.cxx index 053ff1325..d6affaf3c 100644 --- a/src/debugger/gui/RiotWidget.cxx +++ b/src/debugger/gui/RiotWidget.cxx @@ -76,13 +76,12 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, bits->setTarget(this); \ bits->setID(bitsID); \ if(editable) addFocusWidget(bits); else bits->setEditable(false); \ - xpos += bits->getWidth() + 5; \ bits->setList(off, on); // SWCHA bits in 'poke' mode labels.clear(); CREATE_IO_REGS("SWCHA(W)", mySWCHAWriteBits, kSWCHABitsID, true) - col = xpos + 20; // remember this for adding widgets to the second column + col = xpos + mySWCHAWriteBits->getWidth() + 25; // remember this for adding widgets to the second column // SWACNT bits xpos = 10; ypos += lineHeight + 5; diff --git a/src/emucore/CartCM.hxx b/src/emucore/CartCM.hxx index 0c2ffd0ef..1c96561ed 100644 --- a/src/emucore/CartCM.hxx +++ b/src/emucore/CartCM.hxx @@ -232,7 +232,7 @@ class CartridgeCM : public Cartridge /** Inform the cartridge about the parent CompuMate controller */ - void setCompuMate(shared_ptr& cmate) { myCompuMate = cmate; } + void setCompuMate(const shared_ptr& cmate) { myCompuMate = cmate; } /** Get the current keyboard column diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index 31443e1bf..12e89b37a 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -725,21 +725,21 @@ void DeveloperDialog::saveSettings(SettingsSet set) instance().settings().setValue(prefix + "bankrandom", myRandomBank[set]); instance().settings().setValue(prefix + "ramrandom", myRandomizeRAM[set]); instance().settings().setValue(prefix + "cpurandom", myRandomizeCPU[set]); - // Undriven TIA pins + if(devSettings) - instance().settings().setValue("dev.tiadriven", myUndrivenPins[set]); -#ifdef DEBUGGER_SUPPORT - if (devSettings) { + // Undriven TIA pins + instance().settings().setValue("dev.tiadriven", myUndrivenPins[set]); + #ifdef DEBUGGER_SUPPORT // Read from write ports break instance().settings().setValue("dev.rwportbreak", myRWPortBreak[set]); // Write to read ports break instance().settings().setValue("dev.wrportbreak", myWRPortBreak[set]); - } -#endif - if(devSettings) + #endif // Thumb ARM emulation exception instance().settings().setValue("dev.thumb.trapfatal", myThumbException[set]); + } + // AtariVox/SaveKey EEPROM access instance().settings().setValue(prefix + "eepromaccess", myEEPROMAccess[set]); From a5b48b76b730c63b3c655e6244afb025e0cc0b7c Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Wed, 23 Dec 2020 17:20:31 -0330 Subject: [PATCH 12/34] Remove dead Blargg code. --- src/common/tv_filters/AtariNTSC.cxx | 56 +--------------------------- src/common/tv_filters/AtariNTSC.hxx | 22 ----------- src/common/tv_filters/NTSCFilter.cxx | 45 ---------------------- src/common/tv_filters/NTSCFilter.hxx | 11 +----- 4 files changed, 2 insertions(+), 132 deletions(-) diff --git a/src/common/tv_filters/AtariNTSC.cxx b/src/common/tv_filters/AtariNTSC.cxx index ad57a12f8..22976c115 100644 --- a/src/common/tv_filters/AtariNTSC.cxx +++ b/src/common/tv_filters/AtariNTSC.cxx @@ -57,15 +57,9 @@ void AtariNTSC::generateKernels() const uInt8* ptr = myRGBPalette.data(); for(size_t entry = 0; entry < myRGBPalette.size() / 3; ++entry) { - #ifdef BLARGG_PALETTE - float r = myImpl.to_float[*ptr++], - g = myImpl.to_float[*ptr++], - b = myImpl.to_float[*ptr++]; - #else float r = (*ptr++) / 255.F * rgb_unit + rgb_offset, g = (*ptr++) / 255.F * rgb_unit + rgb_offset, b = (*ptr++) / 255.F * rgb_unit + rgb_offset; - #endif float y, i, q; RGB_TO_YIQ( r, g, b, y, i, q ); // Generate kernel @@ -325,11 +319,6 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AtariNTSC::init(init_t& impl, const Setup& setup) { -#ifdef BLARGG_PALETTE - impl.brightness = setup.brightness * (0.5F * rgb_unit) + rgb_offset; - impl.contrast = setup.contrast * (0.5F * rgb_unit) + rgb_unit; -#endif - impl.artifacts = setup.artifacts; if ( impl.artifacts > 0 ) impl.artifacts *= artifacts_max - artifacts_mid; @@ -342,30 +331,8 @@ void AtariNTSC::init(init_t& impl, const Setup& setup) initFilters(impl, setup); -#ifdef BLARGG_PALETTE - /* generate gamma table */ - if (true) /* was (gamma_size > 1) */ - { - float const to_float = 1.F / (gamma_size - 1/*(gamma_size > 1)*/); - float const gamma = 1.1333F - setup.gamma * 0.5F; - /* match common PC's 2.2 gamma to TV's 2.65 gamma */ - int i; - for(i = 0; i < gamma_size; i++) - impl.to_float[i] = - powf(i * to_float, gamma) * impl.contrast + impl.brightness; - } -#endif - /* setup decoder matricies */ { - #ifdef BLARGG_PALETTE - float hue = setup.hue * BSPF::PI_f + BSPF::PI_f / 180 * ext_decoder_hue; - float sat = setup.saturation + 1; - hue += BSPF::PI_f / 180 * (std_decoder_hue - ext_decoder_hue); - - float s = sinf(hue)*sat; - float c = cosf(hue)*sat; - #endif float* out = impl.to_rgb.data(); int n; @@ -378,13 +345,8 @@ void AtariNTSC::init(init_t& impl, const Setup& setup) { float i = *in++; float q = *in++; - #ifdef BLARGG_PALETTE - *out++ = i * c - q * s; - *out++ = i * s + q * c; - #else - *out++ = i ; + *out++ = i; *out++ = q; - #endif } while ( --n2 ); #if 0 // burst_count is always 0 @@ -561,32 +523,16 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const AtariNTSC::Setup AtariNTSC::TV_Composite = { -#ifdef BLARGG_PALETTE - 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.15F, 0.0F, 0.0F, 0.0F -#else 0.0F, 0.15F, 0.0F, 0.0F, 0.0F -#endif }; const AtariNTSC::Setup AtariNTSC::TV_SVideo = { -#ifdef BLARGG_PALETTE - 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.45F, -1.0F, -1.0F, 0.0F -#else 0.0F, 0.45F, -1.0F, -1.0F, 0.0F -#endif }; const AtariNTSC::Setup AtariNTSC::TV_RGB = { -#ifdef BLARGG_PALETTE - 0.0F, 0.0F, 0.0F, 0.0F, 0.2F, 0.0F, 0.70F, -1.0F, -1.0F, -1.0F -#else 0.2F, 0.70F, -1.0F, -1.0F, -1.0F -#endif }; const AtariNTSC::Setup AtariNTSC::TV_Bad = { -#ifdef BLARGG_PALETTE - 0.1F, -0.3F, 0.3F, 0.25F, 0.2F, 0.0F, 0.1F, 0.5F, 0.5F, 0.5F -#else 0.2F, 0.1F, 0.5F, 0.5F, 0.5F -#endif }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/tv_filters/AtariNTSC.hxx b/src/common/tv_filters/AtariNTSC.hxx index 087e7c579..135ff41b8 100644 --- a/src/common/tv_filters/AtariNTSC.hxx +++ b/src/common/tv_filters/AtariNTSC.hxx @@ -46,8 +46,6 @@ #include "FrameBufferConstants.hxx" #include "bspf.hxx" -//#define BLARGG_PALETTE // also modify contrast, brightness, saturation, gamma and hue when defined - class AtariNTSC { public: @@ -59,18 +57,9 @@ class AtariNTSC struct Setup { // Basic parameters - #ifdef BLARGG_PALETTE - float hue{0.F}; // -1 = -180 degrees +1 = +180 degrees - float saturation{0.F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0) - float contrast{0.F}; // -1 = dark (0.5) +1 = light (1.5) - float brightness{0.F}; // -1 = dark (0.5) +1 = light (1.5) - #endif float sharpness{0.F}; // edge contrast enhancement/blurring // Advanced parameters - #ifdef BLARGG_PALETTE - float gamma{0.F}; // -1 = dark (1.5) +1 = light (0.5) - #endif float resolution{0.F}; // image resolution float artifacts{0.F}; // artifacts caused by color changes float fringing{0.F}; // color artifacts caused by brightness changes @@ -133,9 +122,6 @@ class AtariNTSC burst_size = entry_size / burst_count, kernel_half = 16, kernel_size = kernel_half * 2 + 1, - #ifdef BLARGG_PALETTE - gamma_size = 256, - #endif rgb_builder = ((1 << 21) | (1 << 11) | (1 << 1)), rgb_kernel_size = burst_size / alignment_count, @@ -170,20 +156,12 @@ class AtariNTSC struct init_t { std::array to_rgb{0.F}; - #ifdef BLARGG_PALETTE - std::array to_float{0.F}; - float contrast{0.F}; - float brightness{0.F}; - #endif float artifacts{0.F}; float fringing{0.F}; std::array kernel{0.F}; init_t() { to_rgb.fill(0.0); - #ifdef BLARGG_PALETTE - to_float.fill(0.0); - #endif kernel.fill(0.0); } }; diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx index 14c38697e..63698c64a 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -77,19 +77,11 @@ void NTSCFilter::selectAdjustable(int direction, { if(direction == +1) { - #ifdef BLARGG_PALETTE - myCurrentAdjustable = (myCurrentAdjustable + 1) % 10; - #else myCurrentAdjustable = (myCurrentAdjustable + 1) % 5; - #endif } else if(direction == -1) { - #ifdef BLARGG_PALETTE - if(myCurrentAdjustable == 0) myCurrentAdjustable = 9; - #else if(myCurrentAdjustable == 0) myCurrentAdjustable = 4; - #endif else --myCurrentAdjustable; } @@ -139,13 +131,6 @@ void NTSCFilter::loadConfig(const Settings& settings) { // Load adjustables for custom mode -#ifdef BLARGG_PALETTE - myCustomSetup.hue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F); - myCustomSetup.saturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F); - myCustomSetup.contrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F); - myCustomSetup.brightness = BSPF::clamp(settings.getFloat("tv.brightness"), -1.0F, 1.0F); - myCustomSetup.gamma = BSPF::clamp(settings.getFloat("tv.gamma"), -1.0F, 1.0F); -#endif myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F); myCustomSetup.resolution = BSPF::clamp(settings.getFloat("tv.resolution"), -1.0F, 1.0F); myCustomSetup.artifacts = BSPF::clamp(settings.getFloat("tv.artifacts"), -1.0F, 1.0F); @@ -157,13 +142,6 @@ void NTSCFilter::loadConfig(const Settings& settings) void NTSCFilter::saveConfig(Settings& settings) const { // Save adjustables for custom mode -#ifdef BLARGG_PALETTE - settings.setValue("tv.hue", myCustomSetup.hue); - settings.setValue("tv.saturation", myCustomSetup.saturation); - settings.setValue("tv.contrast", myCustomSetup.contrast); - settings.setValue("tv.brightness", myCustomSetup.brightness); - settings.setValue("tv.gamma", myCustomSetup.gamma); -#endif settings.setValue("tv.sharpness", myCustomSetup.sharpness); settings.setValue("tv.resolution", myCustomSetup.resolution); settings.setValue("tv.artifacts", myCustomSetup.artifacts); @@ -194,13 +172,6 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void NTSCFilter::setCustomAdjustables(const Adjustable& adjustable) { -#ifdef BLARGG_PALETTE - //myCustomSetup.hue = scaleFrom100(adjustable.hue); - //myCustomSetup.saturation = scaleFrom100(adjustable.saturation); - //myCustomSetup.contrast = scaleFrom100(adjustable.contrast); - //myCustomSetup.brightness = scaleFrom100(adjustable.brightness); - //myCustomSetup.gamma = scaleFrom100(adjustable.gamma); -#endif myCustomSetup.sharpness = scaleFrom100(adjustable.sharpness); myCustomSetup.resolution = scaleFrom100(adjustable.resolution); myCustomSetup.artifacts = scaleFrom100(adjustable.artifacts); @@ -212,13 +183,6 @@ void NTSCFilter::setCustomAdjustables(const Adjustable& adjustable) void NTSCFilter::convertToAdjustable(Adjustable& adjustable, const AtariNTSC::Setup& setup) const { -#ifdef BLARGG_PALETTE - //adjustable.hue = scaleTo100(setup.hue); - //adjustable.saturation = scaleTo100(setup.saturation); - //adjustable.contrast = scaleTo100(setup.contrast); - //adjustable.brightness = scaleTo100(setup.brightness); - //adjustable.gamma = scaleTo100(setup.gamma); -#endif adjustable.sharpness = scaleTo100(setup.sharpness); adjustable.resolution = scaleTo100(setup.resolution); adjustable.artifacts = scaleTo100(setup.artifacts); @@ -230,16 +194,7 @@ void NTSCFilter::convertToAdjustable(Adjustable& adjustable, AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#ifdef BLARGG_PALETTE -const std::array NTSCFilter::ourCustomAdjustables = { { - { "contrast", &myCustomSetup.contrast }, - { "brightness", &myCustomSetup.brightness }, - { "hue", &myCustomSetup.hue }, - { "saturation", &myCustomSetup.saturation }, - { "gamma", &myCustomSetup.gamma }, -#else const std::array NTSCFilter::ourCustomAdjustables = { { -#endif { "sharpness", &myCustomSetup.sharpness }, { "resolution", &myCustomSetup.resolution }, { "artifacts", &myCustomSetup.artifacts }, diff --git a/src/common/tv_filters/NTSCFilter.hxx b/src/common/tv_filters/NTSCFilter.hxx index fd5335806..cc5cbaaa5 100644 --- a/src/common/tv_filters/NTSCFilter.hxx +++ b/src/common/tv_filters/NTSCFilter.hxx @@ -59,12 +59,7 @@ class NTSCFilter /* Normally used in conjunction with custom mode, contains all aspects currently adjustable in NTSC TV emulation. */ struct Adjustable { - #ifdef BLARGG_PALETTE - uInt32 hue, saturation, contrast, brightness, gamma, - sharpness, resolution, artifacts, fringing, bleed; - #else - uInt32 sharpness, resolution, artifacts, fringing, bleed; - #endif + uInt32 sharpness{0}, resolution{0}, artifacts{0}, fringing{0}, bleed{0}; }; public: @@ -153,11 +148,7 @@ class NTSCFilter float* value{nullptr}; }; uInt32 myCurrentAdjustable{0}; - #ifdef BLARGG_PALETTE - static const std::array ourCustomAdjustables; - #else static const std::array ourCustomAdjustables; - #endif private: // Following constructors and assignment operators not supported From 31e50aa8d17e9f3f0f9e5ce9fbf4180f55158407 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Wed, 23 Dec 2020 23:07:00 +0100 Subject: [PATCH 13/34] added file browser to GameInfoDialog export code cleanup updated docs --- docs/graphics/options_gameinfo_cartridge.png | Bin 3454 -> 3456 bytes docs/graphics/options_gameinfo_console.png | Bin 2801 -> 2804 bytes docs/graphics/options_gameinfo_controller.png | Bin 4494 -> 4496 bytes docs/graphics/options_gameinfo_emulation.png | Bin 3630 -> 3632 bytes docs/graphics/options_gameinfo_highscores.png | Bin 3565 -> 3567 bytes docs/index.html | 2 +- src/debugger/gui/DataGridOpsWidget.cxx | 2 +- src/debugger/gui/DebuggerDialog.cxx | 2 + src/emucore/FSNode.cxx | 1 - src/gui/BrowserDialog.cxx | 133 +++++++----------- src/gui/BrowserDialog.hxx | 4 +- src/gui/GameInfoDialog.cxx | 37 ++++- src/gui/GameInfoDialog.hxx | 7 +- src/gui/RomAuditDialog.cxx | 2 + src/gui/SnapshotDialog.cxx | 2 + src/gui/UIDialog.cxx | 2 + 16 files changed, 99 insertions(+), 95 deletions(-) diff --git a/docs/graphics/options_gameinfo_cartridge.png b/docs/graphics/options_gameinfo_cartridge.png index da6f4fdc4409cf8582a8356dc9d02f4c6b16dc32..772f1334bec9d0d080a8d7f05832b8b5c70cf179 100644 GIT binary patch delta 389 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 delta 2451 zcmZ8iX;hO}8jgY!XwXlqNEyn=Y5vDqApZV4JR>S zux-putyhZ!V6d;S4#&{$c+LXdC+)uZt{&r^37cw#FX_F5;FDTJKy5; z8jZl^bYdQ@X!Ga31@Sw3lnUTK014pBC!IQZm)6MOfzKBQLJJ1ll((;0hX_u6B6F$71TL0dD71{$3{DC}`@%D>?OCVEwZ zc?!3A>OO#P%PUm1=g+KU9qb1e|1crs{5;R|-UYF%c8t`<1=L|p7BX%+wWA`GcFKF0 z&oWJWVEIdbuv?-d**%))$6?|Txo|Jj-{E&}P;*B3vwXzW#ion4l5m3RK9X+{>e=Hx zfb`wM{&{yWo7RPy+rttTtSNKRa}+TAgYS>i+!yfl;Jehbd3-{uOqg)8$wMvW1GQDS z-A;F(#-y|r4E-Zh*~K#Y30yc4{fJFA6k%$&^zUUCHD@FGea&vB7;e1qg-_d^9xSJH1ffOpE%5;vUPPD{9rDfEoN9i=Z1@kPr%`@!J zrNDnQSkkCb|5b-Q;0QVt?*Vs1^HQ7?h4?Hn(r1mq{_U4qfnZKAHu@0w(nu)atB)~~ zxRWB0hfd-Z?qp5lwV3Bmnio~TV?84Iog~Fyt9aM-T!(d&mlK%@qdR!$NN!3E-6O0@y& zYruG@o@MQcG8unOx9O^DC~vY4dtBSG#R!aNpKrdcM5~JdVMFD=dyrq zNlI8;DQ}3x`)tKCw&2IN&TjgTv%kETZlbD2f-N;P$wbVNr7YR3Mk-fII}{>VE;Fp~ z>=0y@M9hTDXVb3g^RbVP@W}*ZE11_ri1-@&JnVHv&r{^ve}`ooZI>#wFQ;znR`ED4z7lNxar=+ov9GY_jmKFR!H`H94IW({*`zd{E%(jhW6%mELAyJ!5z9ISYlFu{}rgm+1=!z?ExI%Mf@{SRk3xyQlxHqH7hs z{4lwffVRGD@o`meKGb5N=&u(fAHt4midY{KPBy4B^=;1@ghh5JFo#Au{h)VVXWoKd1C$$v$ya|P;QJ(Y#*To9~Y(F4O!|8U?un zV;Gd#6BQ)UoH^DKWEsz8^N?w}d+{&V4P*SRv3Y#n#sSx$bsNS+USQDmK243LW1p%h zCCxvu6-#M?w!@nKX~;xlU*fF`1BEm&*+OC0e81KKkXFfZLg)k)Qtr_eDXpmAk>{68 z4Vv|n@Q^KyuHz63bM2*2qcC2DX*%+#`=O59z$Q*0)KD2P)uastEKnX8kJ)Ca(dIh< z=-bP3N*U0bDp2Dg2ML!hH1E9AcxjO2SA>dt6-{3IUwW`@RX1R%*c>k3G9g85)KB20 zpI7->CF;mT-0q1ui*y}Tjr1Ospp9(@7DxoY$rauBFW>av9Px&k(wXkAdXV%Xi*h^P zddUETh0uP0*X^y*$x5m_dCOp8&5Zq@EiB&PCK5YK*TG`Gg`}XNDfB z=a^{dEz9$qW#$X7n&*mLP3;JURfv+U4tMik@)Y0h diff --git a/docs/graphics/options_gameinfo_controller.png b/docs/graphics/options_gameinfo_controller.png index 6b8740424429ef7e86ba52c72c8694754293d8cb..63b5548a3f776df9c2c73d0de8bc05c365f08d5d 100644 GIT binary patch delta 2814 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 s(*N8TbyND6+qO|y?WiNM)?_YI(~cpxmRyRt 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 diff --git a/docs/graphics/options_gameinfo_emulation.png b/docs/graphics/options_gameinfo_emulation.png index 8da3b8c42aeaea886f842f82b68aa9a2f21f044c..b67ca95f7561b2b22a036d3bff944dfa8f057578 100644 GIT binary patch delta 3256 zcmZWrc{J4PA0}yT=sVIvHP&lxrAW4BXk-_%XejWFL?S{)8`k!kL1{G91iT*TqCygfuI5gsp4(t&t?*BGt}4rbnnH?)3r5|SJ_rmosd z~?A(B~#Hw5Oq+-CiskX*Ill3)| z_X20j;2^J$gpG%hwYzo`#Gq=0{_AM1$GscgX#n5Cc{Fu>3K|M|+SP)rhGdwsr;| zJw~*{xh!b;y4+~sYq~Z=`@X+8n=nE#c*TNv?pq5LqJA+DR?no<4(;& zmitLlL#>lRr+lk(kBEYL3ApY_@rN;!0(1_fJpH|3-trJD`Zn-euOiT$lIurOY9ZnU zfqvDj9s$iUnXtWzxczJ6(@urG&4FPnBeDa83r6@f#<3hK82h9Zt2lGH6fCl zpq9iG64l*KxDly$v*!>DyhP|SF-=Lh(kSJ z569LYXRNlLK{eGQxpp{au*62a1D*$ckScaW=#43xAqKd7qb|&kd+*tD**PNyGTyuA-HlbeUoD+hg*2aWQEOF{++eT=7%uD&hC2hgCJ5Z6v6y-R*l0qE`OyqzN2C<`TAK`6S^uakIUw?KKX@-_Jx^TL|6WQ? z_>l9-V3NwSR-W?^o51k`Ev9R;h35|-ks{_xsfg<+f?Vm^wi@T7tcxeN>c5SZAA?i zHw~b;EY6H1xJ1@5)jv+(ShpC{e7p8vI{Z~+Lg8YuRuz~b3qROL$ErQ?LVvHIPL#*F z*a2bC;CS-c8~FV`aXOZ6Pqvn#s_63N3(-ni5l3da`qMEMknk5RSv_B>+w}*3oMXtB z^DEMb46SEb(ASra9l|6Zl!;!7>JCHQUhpbgO0Flj@@@jt#k$rRsuds|!BarQ8#DtgYt|AX{b0mW zlyFHQ$slSeBg%c| zSKDOne5>_nRa)m{)iC7*3QiSFySWc>Dj~jap&A)a?A zuq}~SaqZ&h_H@&wkMd$~2TGVlILYD+E;lnx-Zev*Ub1^rG^3R_Cpl<%0aVa3K;LP{ zE=~JVJ7~{G`FM-eZ2+*n+dZSoW%(lc`JgS8Wa_tm$?h|*Q<7^HIC<(HVEv|z`?rJ+ z_73aL`!+_yiQjm%Rv{Fkf?X@*FwxXx#BVqL>yi)KJ`z9#57v{Q3lcYy#Ci-PEy z{AHy-Jyp4Ra%tsw#v!=gO<-mk9XvPvf}%2a^>Ve9mxOdmB;KB`gi_6EINdVok#J7D zPdc(8f-pFZfja_PKU&D(PPD34sdFNe(9zIQ&zh&BSy`UWr+PvW6Q_0G(G*5u#1`qp z6B7ZbYEKPaDg3P`hUm=LzLaQg#Arlh{0@^#vTZD3v$&TH;+19-w5gFKWV^)589Bd! z$iJDE@JIxVzy8<|szt$WieBpQSbl8?JjkB1LQlOax_5bQ)pf9HGRVu)q6V@C(e022 z)DxG?qwi}DK4E5Y`EOHC)pBr62zs?-f$ntSN}9|p#|PZhNRf1C_2c~t^B+ctF^F4!9!8d-PnMO>1vZO5Id}f*5l~Dy(#|E<+1Afb|>bsnZHN7wPvIj-VRoMgJI^TeB#df%mvQJ6OLsJ;b*2R?N9hL z(O6eDw#SP=Ecqikj;7C_Fbfu92z<5foB*7h@!{imI!0;yM+!T$fpq&k+aL1aMfTC|T*+3}VL9 zf8=N+6Hen?xep*1mA_Kv&-H&4Xv{}8dVv2Q6cQ5!$6tDCsjmEPWdHs<5I3va=ZSwj z^-OO34Z3kQfgY3Heo_ohA{_W9seYce>36SExul_;qi$xKL9bc%?nTToAW@n&ei78MGB?&V_G?>zfAQ?HLvHHg$RNwBxEmkJDyn4n;3 z*$$uM31&w_sE1_R)Ae^9$Q#NFk|*wDRFRba(!gwZwce*`n?%@vVXs$A$qXvJnU1Bc#N>&L^}oGbU<613c!Jq>@Z|F z@8w4o^5I4bh4>WPwI#eWI#q*zmQ$ArtUd6{1?6{IV@Pb>Pkf;NMJhA09}?Uw WU&}ej#rcuI&M`B#GNKqbh5ZMxDPINv delta 3254 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 OE)!$Za}+~|C;tZ9-uZQQiXqJ zt1K%TF@*T0?EdPf?5}d)G^@q$Q1#cihO6)ey!eA0Yl_eCN)_>S;XB4hk2b;Y6W&;Z zFI-sxv#a_)Oo0>8gHCtwa=WOWU1 z()LBkf9eZR8$C0*w#V;k@jI2AIjU-W-ATmw9fmIt#irlhi}0_r@U>04dVI#1asCN@ z#`(MM`X2oHwl7+r!&i;B0^d|!XZ7(r-1+4Z-(>x&o?lluw0>8Cug|O)zG*->e%SUE zJ`-=)#`sm|{h-O$w|&`(xt?G3-@WV6ap$*QS!UAd@A|qe{>;lB>-@IoXTf#P<`=yz zm*xD|{Dhwt-SH7V;S>J;@E44c&&#swasF0C_|UKj9~u_nL&Itwzh!-V{2vvaXk~P{ Rvbg{N002ovPDHLkV1i0+$t(Z> delta 369 zcmV-%0gnFf8|@pAa1Ox$01m+cxRGn^000eJv3?p1e^*1s;v{GdSK;@Jb^Wztslq?A zRhHF^7(#qgc7OF#_E))Yn$^SaQ1#bo4Oig{c<~20(iETJRVw1^!gq|19&3W%Cw#F6 zUpTS?W>@uzc*lh2SRY65rCZ7by+}E}^g)x@2p?}{7`|#N0>)Oo0>8gHCtwa=WOWTM zYWt#WfAs~Zjh>l&TjO`N_?=45991>G?j&OT4#$@VW7F^NCHU7__}U^}Jw9X1IR6Ac z>-=4JeFuJh+ZS!m;j6}5fp03Vv-8Cug|O)zG*-y{IKmS ze6~G))p - +
    Allow all 4 directions ...Allow all 4 joystick directions to be pressed simultaneously-joyallow4
    Use modifier key combosEnable using modifier keys in keyboard actions-modcombo
    Swap Stelladaptor portsSwap the order of the detected Stelladaptors/2600-daptors (see Advanced Configuration - Stelladaptor/2600-daptor Support)-saport
    Joystick databaseShow all joysticks that Stella knows about, with the option to remove them 
    Joystick DatabaseShow all joysticks that Stella knows about, with the option to remove them 
    Erase EEPROMErase the whole AtariVox/SaveKey flash memory 
    AtariVox serial portDescribed in further detail in Advanced Configuration - AtariVox/SaveKey Support -avoxport
    diff --git a/src/debugger/gui/DataGridOpsWidget.cxx b/src/debugger/gui/DataGridOpsWidget.cxx index 2a62ec60c..e4bf5d247 100644 --- a/src/debugger/gui/DataGridOpsWidget.cxx +++ b/src/debugger/gui/DataGridOpsWidget.cxx @@ -34,7 +34,7 @@ DataGridOpsWidget::DataGridOpsWidget(GuiObject* boss, const GUI::Font& font, _zeroButton = new ButtonWidget(boss, font, xpos, ypos, bwidth, bheight, "0", kDGZeroCmd); _zeroButton->setToolTip("Zero currently selected value"); - + ypos += bheight + space; _invButton = new ButtonWidget(boss, font, xpos, ypos, bwidth, bheight, "Inv", kDGInvertCmd); diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 87481234c..8abf382d4 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -489,6 +489,8 @@ void DebuggerDialog::createBrowser(const string& title) { uInt32 w = 0, h = 0; getDynamicBounds(w, h); + if(w > uInt32(_font.getMaxCharWidth() * 80)) + w = _font.getMaxCharWidth() * 80; // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || diff --git a/src/emucore/FSNode.cxx b/src/emucore/FSNode.cxx index d9de7e0a5..212828379 100644 --- a/src/emucore/FSNode.cxx +++ b/src/emucore/FSNode.cxx @@ -59,7 +59,6 @@ FilesystemNode& FilesystemNode::operator/=(const string& path) } return *this; -#undef PATH_SEPARATOR } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 25b35aee1..3b1ee48a7 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -81,14 +81,19 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, buttonWidth, buttonHeight, "Go up", kGoUpCmd); addFocusWidget(_goUpButton); - _basedirButton = - new ButtonWidget(this, font, _goUpButton->getRight() + BUTTON_GAP, _h - buttonHeight - VBORDER, - buttonWidth, buttonHeight, "Base Dir", kBaseDirCmd); - addFocusWidget(_basedirButton); + b = new ButtonWidget(this, font, _goUpButton->getRight() + BUTTON_GAP, _h - buttonHeight - VBORDER, + buttonWidth, buttonHeight, "Base Dir", kBaseDirCmd); + b->setToolTip("Go to Stella's base directory."); + addFocusWidget(b); + + b = new ButtonWidget(this, font, b->getRight() + BUTTON_GAP, _h - buttonHeight - VBORDER, + buttonWidth, buttonHeight, "Home Dir", kHomeDirCmd); + b->setToolTip("Go to user's home directory."); + addFocusWidget(b); #ifndef BSPF_MACOS b = new ButtonWidget(this, font, _w - (2 * buttonWidth + BUTTON_GAP + HBORDER), _h - buttonHeight - VBORDER, - buttonWidth, buttonHeight, "Choose", kChooseCmd); + buttonWidth, buttonHeight, "OK", kChooseCmd); addFocusWidget(b); addOKWidget(b); b = new ButtonWidget(this, font, _w - (buttonWidth + HBORDER), _h - buttonHeight - VBORDER, @@ -101,7 +106,7 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, addFocusWidget(b); addCancelWidget(b); b = new ButtonWidget(this, font, _w - (buttonWidth + HBORDER), _h - buttonHeight - VBORDER, - buttonWidth, buttonHeight, "Choose", kChooseCmd); + buttonWidth, buttonHeight, "OK", kChooseCmd); addFocusWidget(b); addOKWidget(b); #endif @@ -115,7 +120,9 @@ void BrowserDialog::show(const string& startpath, _mode = mode; _cmd = cmd; _cancelCmd = cancelCmd; - string fileName; + string directory;// = EmptyString; + string fileName;// = EmptyString; + bool fileSelected = true; // Set start path if(_mode != Directories) @@ -123,13 +130,7 @@ void BrowserDialog::show(const string& startpath, // split startpath into path and filename FilesystemNode fs = FilesystemNode(startpath); fileName = fs.getName(); - string directory = fs.isDirectory() ? "" : fs.getParent().getPath(); - - _fileList->setDirectory(FilesystemNode(directory), fileName); - } - else - { - _fileList->setDirectory(FilesystemNode(startpath)); + directory = fs.isDirectory() ? "" : fs.getParent().getPath(); } switch(_mode) @@ -144,7 +145,6 @@ void BrowserDialog::show(const string& startpath, _selected->clearFlags(Widget::FLAG_INVISIBLE); _type->clearFlags(Widget::FLAG_INVISIBLE); _okWidget->setLabel("Load"); - updateUI(true); break; case FileSave: @@ -158,7 +158,7 @@ void BrowserDialog::show(const string& startpath, _type->clearFlags(Widget::FLAG_INVISIBLE); _okWidget->setLabel("Save"); _selected->setText(fileName); - updateUI(false); + fileSelected = false; break; case Directories: @@ -168,11 +168,17 @@ void BrowserDialog::show(const string& startpath, _selected->setEnabled(false); _selected->setFlags(Widget::FLAG_INVISIBLE); _type->setFlags(Widget::FLAG_INVISIBLE); - _okWidget->setLabel("Choose"); - updateUI(true); + _okWidget->setLabel("OK"); break; } + // Set start path + if(_mode != Directories) + _fileList->setDirectory(FilesystemNode(directory), fileName); + else + _fileList->setDirectory(FilesystemNode(startpath)); + updateUI(fileSelected); + // Finally, open the dialog after it has been fully updated open(); } @@ -182,76 +188,15 @@ const FilesystemNode& BrowserDialog::getResult() const { if(_mode == FileLoad || _mode == FileSave) { - static FilesystemNode node(_fileList->currentDir().getShortPath() + _selected->getText()); + static FilesystemNode node; - return node; + return node + = FilesystemNode(_fileList->currentDir().getShortPath() + _selected->getText()); } else return _fileList->currentDir(); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void BrowserDialog::updateUI(bool fileSelected) -{ - // Only hilite the 'up' button if there's a parent directory - _goUpButton->setEnabled(_fileList->currentDir().hasParent()); - - // Update the path display - _currentPath->setText(_fileList->currentDir().getShortPath()); - - // Enable/disable OK button based on current mode - //bool enable = true; - //switch(_mode) - //{ - // case Directories: - // enable = true; - // break; - - // case FileLoad: - // if(_fileList->selected().isDirectory()) - // { - // enable = false; - // _selected->setText(""); - // } - // else - // { - // enable = fileSelected && !_selected->getText().empty(); - // _selected->setText(_fileList->getSelectedString()); - // } - // break; - - // case FileSave: - // if(_fileList->selected().isDirectory()) - // { - // enable = false; - // _selected->setText(""); - // } - // else - // { - // enable = fileSelected && !_selected->getText().empty(); // TODO - // _selected->setText(_fileList->getSelectedString()); - // } - // break; - - // default: - // break; - //} - //_okWidget->setEnabled(enable); - - bool enable = _mode == Directories - || (!_fileList->selected().isDirectory() && fileSelected) - || (!_selected->getText().empty() && !fileSelected); - _okWidget->setEnabled(enable); - - if(fileSelected) - { - if(!_fileList->selected().isDirectory()) - _selected->setText(_fileList->getSelectedString()); - else - _selected->setText(""); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void BrowserDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) @@ -281,6 +226,10 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd, _fileList->setDirectory(FilesystemNode(instance().baseDir())); break; + case kHomeDirCmd: + _fileList->setDirectory(FilesystemNode(instance().defaultSaveDir())); + break; + case EditableWidget::kChangedCmd: Dialog::handleCommand(sender, cmd, data, 0); updateUI(false); @@ -295,3 +244,23 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd, break; } } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void BrowserDialog::updateUI(bool fileSelected) +{ + // Only hilite the 'up' button if there's a parent directory + _goUpButton->setEnabled(_fileList->currentDir().hasParent()); + + // Update the path display + _currentPath->setText(_fileList->currentDir().getShortPath()); + + // Enable/disable OK button based on current mode and status + bool enable = true; + + if(_mode != Directories) + enable = !_selected->getText().empty(); + _okWidget->setEnabled(enable); + + if(fileSelected && !_fileList->selected().isDirectory()) + _selected->setText(_fileList->getSelectedString()); +} diff --git a/src/gui/BrowserDialog.hxx b/src/gui/BrowserDialog.hxx index 9ee401ad6..1038398c0 100644 --- a/src/gui/BrowserDialog.hxx +++ b/src/gui/BrowserDialog.hxx @@ -58,7 +58,8 @@ class BrowserDialog : public Dialog, public CommandSender enum { kChooseCmd = 'CHOS', kGoUpCmd = 'GOUP', - kBaseDirCmd = 'BADR' + kBaseDirCmd = 'BADR', + kHomeDirCmd = 'HODR' }; int _cmd{0}; @@ -69,7 +70,6 @@ class BrowserDialog : public Dialog, public CommandSender StaticTextWidget* _type{nullptr}; EditTextWidget* _selected{nullptr}; ButtonWidget* _goUpButton{nullptr}; - ButtonWidget* _basedirButton{nullptr}; BrowserDialog::ListMode _mode{Directories}; diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 3700caf5f..fc2c08c47 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -29,6 +29,7 @@ #include "Paddles.hxx" #include "PopUpWidget.hxx" #include "PropsSet.hxx" +#include "BrowserDialog.hxx" #include "QuadTariDialog.hxx" #include "TabWidget.hxx" #include "TIAConstants.hxx" @@ -92,7 +93,7 @@ GameInfoDialog::GameInfoDialog( myTab->setActiveTab(0); // Add Defaults, OK and Cancel buttons - addDefaultsExtraOKCancelBGroup(wid, font, "Export", kExportPressed); + addDefaultsExtraOKCancelBGroup(wid, font, "Export" + ELLIPSIS, kExportPressed); _extraWidget->setToolTip("Export the current ROM's properties\n" "into the default directory."); addBGroupToFocusList(wid); @@ -660,12 +661,27 @@ void GameInfoDialog::addHighScoresTab() addToFocusList(wid, myTab, tabID); } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GameInfoDialog::~GameInfoDialog() { } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void GameInfoDialog::createBrowser(const string& title) +{ + uInt32 w = 0, h = 0; + getDynamicBounds(w, h); + if(w > uInt32(_font.getMaxCharWidth() * 80)) + w = _font.getMaxCharWidth() * 80; + + // Create file browser dialog + if(!myBrowser || uInt32(myBrowser->getWidth()) != w || + uInt32(myBrowser->getHeight()) != h) + myBrowser = make_unique(this, _font, w, h, title); + else + myBrowser->setTitle(title); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::loadConfig() { @@ -1350,16 +1366,14 @@ void GameInfoDialog::exportCurrentPropertiesToDisk() try { - FilesystemNode propfile = instance().defaultSaveDir(); - propfile /= myGameFile.getNameWithExt(".pro"); + FilesystemNode propfile(myBrowser->getResult().getShortPath()); propfile.write(out); - instance().frameBuffer().showTextMessage("Properties exported to " + - propfile.getShortPath()); + instance().frameBuffer().showTextMessage("ROM properties exported"); } catch(...) { - instance().frameBuffer().showTextMessage("Error exporting properties"); + instance().frameBuffer().showTextMessage("Error exporting ROM properties"); } } @@ -1379,6 +1393,15 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, break; case kExportPressed: + // This dialog is resizable under certain conditions, so we need + // to re-create it as necessary + createBrowser("Export properties as"); + + myBrowser->show(instance().defaultSaveDir().getPath() + myGameFile.getNameWithExt(".pro"), + BrowserDialog::FileSave, kExportChosen); + break; + + case kExportChosen: exportCurrentPropertiesToDisk(); break; diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index c217bd689..d3af6775e 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -27,6 +27,7 @@ class RadioButtonGroup; class TabWidget; class SliderWidget; class QuadTariDialog; +class BrowserDialog; #include "Dialog.hxx" #include "Command.hxx" @@ -78,6 +79,7 @@ class GameInfoDialog : public Dialog, public CommandSender void setAddressVal(EditTextWidget* address, EditTextWidget* val, bool isBCD = true, bool zeroBased = false, uInt8 maxVal = 255); void exportCurrentPropertiesToDisk(); + void createBrowser(const string& title); private: TabWidget* myTab{nullptr}; @@ -168,6 +170,8 @@ class GameInfoDialog : public Dialog, public CommandSender StaticTextWidget* myHighScoreNotesLabel{nullptr}; EditTextWidget* myHighScoreNotes{nullptr}; + unique_ptr myBrowser; + enum { kVCenterChanged = 'Vcch', kPhosphorChanged = 'PPch', @@ -180,7 +184,8 @@ class GameInfoDialog : public Dialog, public CommandSender kHiScoresChanged = 'HSch', kPXCenterChanged = 'Pxch', kPYCenterChanged = 'Pych', - kExportPressed = 'GIsp' + kExportPressed = 'Expr', + kExportChosen = 'Exch' }; // Game properties for currently loaded ROM diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index 65b4d0c33..60b627f8d 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -223,6 +223,8 @@ void RomAuditDialog::createBrowser(const string& title) { uInt32 w = 0, h = 0; getDynamicBounds(w, h); + if(w > uInt32(_font.getMaxCharWidth() * 80)) + w = _font.getMaxCharWidth() * 80; // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index 80af8ec1d..c983c1d5b 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -183,6 +183,8 @@ void SnapshotDialog::createBrowser(const string& title) { uInt32 w = 0, h = 0; getDynamicBounds(w, h); + if(w > uInt32(_font.getMaxCharWidth() * 80)) + w = _font.getMaxCharWidth() * 80; // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index beb6f576d..6ba10d9f8 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -706,6 +706,8 @@ void UIDialog::createBrowser(const string& title) { uInt32 w = 0, h = 0; getDynamicBounds(w, h); + if(w > uInt32(_font.getMaxCharWidth() * 80)) + w = _font.getMaxCharWidth() * 80; // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || From e664b29a91c413dcec936b822ae7f9769ee24c6d Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Wed, 23 Dec 2020 22:21:46 -0330 Subject: [PATCH 14/34] Eliminate duplicate copies of lastPathComponent function. --- src/common/FSNodeZIP.hxx | 15 --------------- src/emucore/FSNode.hxx | 20 ++++++++++++++++++++ src/unix/FSNodePOSIX.hxx | 24 ------------------------ src/windows/FSNodeWINDOWS.cxx | 25 ------------------------- 4 files changed, 20 insertions(+), 64 deletions(-) diff --git a/src/common/FSNodeZIP.hxx b/src/common/FSNodeZIP.hxx index 079d3c546..f71698871 100644 --- a/src/common/FSNodeZIP.hxx +++ b/src/common/FSNodeZIP.hxx @@ -106,21 +106,6 @@ class FilesystemNodeZIP : public AbstractFSNode // ZipHandler static reference variable responsible for accessing ZIP files static unique_ptr myZipHandler; - - // Get last component of path - static const char* lastPathComponent(const string& str) - { - if(str.empty()) - return ""; - - const char* start = str.c_str(); - const char* cur = start + str.size() - 2; - - while (cur >= start && !(*cur == '/' || *cur == '\\')) - --cur; - - return cur + 1; - } }; #endif diff --git a/src/emucore/FSNode.hxx b/src/emucore/FSNode.hxx index 05378d185..0737b8bdd 100644 --- a/src/emucore/FSNode.hxx +++ b/src/emucore/FSNode.hxx @@ -471,6 +471,26 @@ class AbstractFSNode * a try-catch block. */ virtual size_t write(const stringstream& buffer) const { return 0; } + + /** + * Returns the last component of a given path. + * + * @param str String containing the path. + * @return Pointer to the first char of the last component inside str. + */ + static const char* lastPathComponent(const string& str) + { + if(str.empty()) + return ""; + + const char* start = str.c_str(); + const char* cur = start + str.size() - 2; + + while (cur >= start && !(*cur == '/' || *cur == '\\')) + --cur; + + return cur + 1; + } }; #endif diff --git a/src/unix/FSNodePOSIX.hxx b/src/unix/FSNodePOSIX.hxx index 5aba86afa..3e09e3bb5 100644 --- a/src/unix/FSNodePOSIX.hxx +++ b/src/unix/FSNodePOSIX.hxx @@ -89,30 +89,6 @@ class FilesystemNodePOSIX : public AbstractFSNode * using the stat() function. */ void setFlags(); - - /** - * Returns the last component of a given path. - * - * Examples: - * /foo/bar.txt would return /bar.txt - * /foo/bar/ would return /bar/ - * - * @param str String containing the path. - * @return Pointer to the first char of the last component inside str. - */ - static const char* lastPathComponent(const string& str) - { - if(str.empty()) - return ""; - - const char* start = str.c_str(); - const char* cur = start + str.size() - 2; - - while (cur >= start && *cur != '/') - --cur; - - return cur + 1; - } }; #endif diff --git a/src/windows/FSNodeWINDOWS.cxx b/src/windows/FSNodeWINDOWS.cxx index 179476b27..bc4212ddd 100644 --- a/src/windows/FSNodeWINDOWS.cxx +++ b/src/windows/FSNodeWINDOWS.cxx @@ -39,31 +39,6 @@ #include "Windows.hxx" #include "FSNodeWINDOWS.hxx" -/** - * Returns the last component of a given path. - * - * Examples: - * c:\foo\bar.txt would return "\bar.txt" - * c:\foo\bar\ would return "\bar\" - * - * @param str Path to obtain the last component from. - * @return Pointer to the first char of the last component inside str. - */ -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const char* lastPathComponent(const string& str) -{ - if(str.empty()) - return ""; - - const char* start = str.c_str(); - const char* cur = start + str.size() - 2; - - while(cur >= start && *cur != '\\') - --cur; - - return cur + 1; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FilesystemNodeWINDOWS::exists() const { From b9cb829390719f38e6e177a2b68a87ce1fffeedc Mon Sep 17 00:00:00 2001 From: thrust26 Date: Thu, 24 Dec 2020 11:48:15 +0100 Subject: [PATCH 15/34] added "userdir" settings which can be used to overwrite default save (and load) directories --- src/debugger/CartDebug.cxx | 6 +-- src/debugger/DebuggerParser.cxx | 8 ++-- src/debugger/gui/DebuggerDialog.cxx | 2 +- src/emucore/OSystem.cxx | 16 +++++++ src/emucore/OSystem.hxx | 7 ++- src/emucore/Settings.cxx | 4 ++ src/gui/BrowserDialog.cxx | 66 ++++++++++++++++++++++++----- src/gui/BrowserDialog.hxx | 3 +- src/gui/GameInfoDialog.cxx | 2 +- src/gui/SnapshotDialog.cxx | 2 +- src/gui/Widget.cxx | 30 +++++++++++++ src/gui/Widget.hxx | 4 ++ 12 files changed, 127 insertions(+), 23 deletions(-) diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index 228c8456c..b91e5dc26 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -1352,7 +1352,7 @@ string CartDebug::saveDisassembly(string path) if(path.empty()) - path = myOSystem.defaultSaveDir().getPath() + path = myOSystem.userSaveDir().getPath() + myConsole.properties().get(PropType::Cart_Name) + ".asm"; else // Append default extension when missing @@ -1380,7 +1380,7 @@ string CartDebug::saveDisassembly(string path) string CartDebug::saveRom(string path) { if(path.empty()) - path = myOSystem.defaultSaveDir().getPath() + path = myOSystem.userSaveDir().getPath() + myConsole.properties().get(PropType::Cart_Name) + ".a26"; else // Append default extension when missing @@ -1406,7 +1406,7 @@ string CartDebug::saveAccessFile(string path) try { if(path.empty()) - path = myOSystem.defaultSaveDir().getPath() + path = myOSystem.userSaveDir().getPath() + myConsole.properties().get(PropType::Cart_Name) + ".csv"; else // Append default extension when missing diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 448eb73c9..2c02c53dd 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -683,7 +683,7 @@ string DebuggerParser::saveScriptFile(string file) // Use default path if no path is provided if(file.find_first_of(FilesystemNode::PATH_SEPARATOR) == string::npos) - file = debugger.myOSystem.defaultSaveDir().getPath() + file; + file = debugger.myOSystem.userSaveDir().getPath() + file; FilesystemNode node(file); @@ -1144,7 +1144,7 @@ void DebuggerParser::executeDump() else { ostringstream file; - file << debugger.myOSystem.defaultSaveDir() + file << debugger.myOSystem.userSaveDir() << debugger.myOSystem.console().properties().get(PropType::Cart_Name) << "_dbg_"; if(execDepth > 0) { @@ -1240,7 +1240,7 @@ void DebuggerParser::executeExec() file += ".script"; FilesystemNode node(file); if (!node.exists()) - node = FilesystemNode(debugger.myOSystem.defaultSaveDir().getPath() + file); + node = FilesystemNode(debugger.myOSystem.userSaveDir().getPath() + file); if (argCount == 2) { execPrefix = argStrings[1]; @@ -1910,7 +1910,7 @@ void DebuggerParser::executeSaveses() { ostringstream filename; auto timeinfo = BSPF::localTime(); - filename << debugger.myOSystem.defaultSaveDir() + filename << debugger.myOSystem.userSaveDir() << std::put_time(&timeinfo, "session_%F_%H-%M-%S.txt"); if(argCount && argStrings[0] == "?") diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 8abf382d4..e258aca08 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -466,7 +466,7 @@ void DebuggerDialog::showBrowser(BrowserType type, const string& defaultName) { createBrowser("Save " + title + " as"); - const string path = instance().defaultSaveDir().getPath() + defaultName; + const string path = instance().userSaveDir().getPath() + defaultName; myBrowser->show(path, BrowserDialog::FileSave, cmd, kBdCancelCmd); } } diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 6d9ab16f0..c9fb0070b 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -246,6 +246,14 @@ void OSystem::loadConfig(const Settings::Options& options) mySettings->load(options); + // TODO: check if affected by '-baseDir'and 'basedirinapp' params + string userDir = mySettings->getString("userdir"); + if(userDir.empty()) + userDir = defSaveDir; + myUserSaveDir = FilesystemNode(userDir); + if(!myUserSaveDir.isDirectory()) + myUserSaveDir.makeDir(); + Logger::instance().setLogParameters(mySettings->getInt("loglevel"), mySettings->getBool("logtoconsole")); Logger::debug("Loading config options ..."); @@ -333,6 +341,14 @@ void OSystem::setConfigPaths() #endif } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void OSystem::setUserDir(const string& path) +{ + mySettings->setValue("userdir", path); + + myUserSaveDir = FilesystemNode(path); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool OSystem::checkUserPalette(bool outputError) const { diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx index f335055f4..1ac973976 100644 --- a/src/emucore/OSystem.hxx +++ b/src/emucore/OSystem.hxx @@ -323,6 +323,7 @@ class OSystem */ const FilesystemNode& defaultSaveDir() const { return myDefaultSaveDir; } const FilesystemNode& defaultLoadDir() const { return myDefaultLoadDir; } + const FilesystemNode& userSaveDir() const { return myUserSaveDir; } /** Open the given ROM and return an array containing its contents. @@ -427,6 +428,9 @@ class OSystem static void overrideBaseDir(const string& path) { ourOverrideBaseDir = path; } static void overrideBaseDirWithApp() { ourOverrideBaseDirWithApp = true; } + // Update the path of the user directory + void setUserDir(const string& path); + public: ////////////////////////////////////////////////////////////////////// // The following methods are system-specific and can be overrided in @@ -552,7 +556,8 @@ class OSystem private: FilesystemNode myBaseDir, myStateDir, mySnapshotSaveDir, mySnapshotLoadDir, - myNVRamDir, myCfgDir, myDefaultSaveDir, myDefaultLoadDir; + myNVRamDir, myCfgDir, myDefaultSaveDir, myDefaultLoadDir, + myUserSaveDir; FilesystemNode myCheatFile, myConfigFile, myPaletteFile, myPropertiesFile; FilesystemNode myRomFile; string myRomMD5; diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 185b72c5c..8068b29a9 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -135,6 +135,8 @@ Settings::Settings() // Config files and paths setPermanent("romdir", ""); + setPermanent("userdir", ""); + setPermanent("saveuserdir", "false"); // ROM browser options setPermanent("exitlauncher", "false"); @@ -572,6 +574,8 @@ void Settings::usage() const << " -basic_settings <0|1> Display only a basic settings dialog\n" << " -romdir Set the directory where the ROM launcher will\n" << " start\n" + << " -userdir The directory to save user files to\n" + << " -saveuserdir <1|0> Update user directory when navigating in browser\n" << " -avoxport The name of the serial port where an AtariVox is\n" << " connected\n" << " -holdreset Start the emulator with the Game Reset switch\n" diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 3b1ee48a7..026c16b2f 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -61,8 +61,13 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, _currentPath = new EditTextWidget(this, font, xpos + t->getWidth(), ypos, _w - t->getWidth() - 2 * xpos, lineHeight); _currentPath->setEditable(false); + + xpos = _w - (HBORDER + _font.getStringWidth("Save") + CheckboxWidget::prefixSize(_font)); + _savePathBox = new CheckboxWidget(this, font, xpos, ypos + 2, "Save"); + _savePathBox->setToolTip("Check to save current path as default."); + // Add file list - ypos += lineHeight + VGAP * 2; + xpos = HBORDER; ypos += lineHeight + VGAP * 2; _fileList = new FileListWidget(this, font, xpos, ypos, _w - 2 * xpos, _h - selectHeight - buttonHeight - ypos - VBORDER * 2); _fileList->setEditable(false); @@ -71,9 +76,9 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, // Add currently selected item ypos += _fileList->getHeight() + VGAP * 2; - _type = new StaticTextWidget(this, font, xpos, ypos + 2, "Name "); - _selected = new EditTextWidget(this, font, xpos + _type->getWidth(), ypos, - _w - _type->getWidth() - 2 * xpos, lineHeight, ""); + _name = new StaticTextWidget(this, font, xpos, ypos + 2, "Name "); + _selected = new EditTextWidget(this, font, xpos + _name->getWidth(), ypos, + _w - _name->getWidth() - 2 * xpos, lineHeight, ""); addFocusWidget(_selected); // Buttons @@ -110,6 +115,9 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, addFocusWidget(b); addOKWidget(b); #endif + + // add last to avoid focus problems + addFocusWidget(_savePathBox); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -117,6 +125,11 @@ void BrowserDialog::show(const string& startpath, BrowserDialog::ListMode mode, int cmd, int cancelCmd, const string& ext) { + const int fontWidth = _font.getMaxCharWidth(), + //fontHeight = _font.getFontHeight(), + HBORDER = fontWidth * 1.25; + //VGAP = fontHeight / 4; + _mode = mode; _cmd = cmd; _cancelCmd = cancelCmd; @@ -140,10 +153,17 @@ void BrowserDialog::show(const string& startpath, _fileList->setNameFilter([ext](const FilesystemNode& node) { return BSPF::endsWithIgnoreCase(node.getName(), ext); }); + //_fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop()); + + _currentPath->setWidth(_savePathBox->getLeft() - _currentPath->getLeft() - fontWidth); + _savePathBox->setEnabled(true); + _savePathBox->clearFlags(Widget::FLAG_INVISIBLE); + _savePathBox->setState(instance().settings().getBool("saveuserdir")); + + _name->clearFlags(Widget::FLAG_INVISIBLE); + _selected->clearFlags(Widget::FLAG_INVISIBLE); _selected->setEditable(false); _selected->setEnabled(false); - _selected->clearFlags(Widget::FLAG_INVISIBLE); - _type->clearFlags(Widget::FLAG_INVISIBLE); _okWidget->setLabel("Load"); break; @@ -152,22 +172,36 @@ void BrowserDialog::show(const string& startpath, _fileList->setNameFilter([ext](const FilesystemNode& node) { return BSPF::endsWithIgnoreCase(node.getName(), ext); }); + //_fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop()); + + _currentPath->setWidth(_savePathBox->getLeft() - _currentPath->getLeft() - fontWidth); + _savePathBox->setEnabled(true); + _savePathBox->clearFlags(Widget::FLAG_INVISIBLE); + _savePathBox->setState(instance().settings().getBool("saveuserdir")); + + _name->clearFlags(Widget::FLAG_INVISIBLE); + _selected->clearFlags(Widget::FLAG_INVISIBLE); _selected->setEditable(true); _selected->setEnabled(true); - _selected->clearFlags(Widget::FLAG_INVISIBLE); - _type->clearFlags(Widget::FLAG_INVISIBLE); - _okWidget->setLabel("Save"); _selected->setText(fileName); + _okWidget->setLabel("Save"); fileSelected = false; break; case Directories: _fileList->setListMode(FilesystemNode::ListMode::DirectoriesOnly); _fileList->setNameFilter([](const FilesystemNode&) { return true; }); + // TODO: scrollbar affected too! + //_fileList->setHeight(_selected->getBottom() - _fileList->getTop()); + + _currentPath->setWidth(_savePathBox->getRight() - _currentPath->getLeft()); + _savePathBox->setEnabled(false); + _savePathBox->setFlags(Widget::FLAG_INVISIBLE); + + _name->setFlags(Widget::FLAG_INVISIBLE); + _selected->setFlags(Widget::FLAG_INVISIBLE); _selected->setEditable(false); _selected->setEnabled(false); - _selected->setFlags(Widget::FLAG_INVISIBLE); - _type->setFlags(Widget::FLAG_INVISIBLE); _okWidget->setLabel("OK"); break; } @@ -177,6 +211,7 @@ void BrowserDialog::show(const string& startpath, _fileList->setDirectory(FilesystemNode(directory), fileName); else _fileList->setDirectory(FilesystemNode(startpath)); + updateUI(fileSelected); // Finally, open the dialog after it has been fully updated @@ -207,6 +242,15 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd, case FileListWidget::ItemActivated: // Send a signal to the calling class that a selection has been made // Since we aren't derived from a widget, we don't have a 'data' or 'id' + if(_mode != Directories) + { + // TODO: check if affected by '-baseDir'and 'basedirinapp' params + bool savePath = _savePathBox->getState(); + + instance().settings().setValue("saveuserdir", savePath); + if(savePath) + instance().setUserDir(_fileList->currentDir().getShortPath()); + } if(_cmd) sendCommand(_cmd, -1, -1); close(); break; diff --git a/src/gui/BrowserDialog.hxx b/src/gui/BrowserDialog.hxx index 1038398c0..8d4b5c2a6 100644 --- a/src/gui/BrowserDialog.hxx +++ b/src/gui/BrowserDialog.hxx @@ -67,9 +67,10 @@ class BrowserDialog : public Dialog, public CommandSender FileListWidget* _fileList{nullptr}; EditTextWidget* _currentPath{nullptr}; - StaticTextWidget* _type{nullptr}; + StaticTextWidget* _name{nullptr}; EditTextWidget* _selected{nullptr}; ButtonWidget* _goUpButton{nullptr}; + CheckboxWidget* _savePathBox{nullptr}; BrowserDialog::ListMode _mode{Directories}; diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index fc2c08c47..4273ce6fc 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -1397,7 +1397,7 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, // to re-create it as necessary createBrowser("Export properties as"); - myBrowser->show(instance().defaultSaveDir().getPath() + myGameFile.getNameWithExt(".pro"), + myBrowser->show(instance().userSaveDir().getPath() + myGameFile.getNameWithExt(".pro"), BrowserDialog::FileSave, kExportChosen); break; diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index c983c1d5b..1f3edc36f 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -131,7 +131,7 @@ void SnapshotDialog::saveConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SnapshotDialog::setDefaults() { - mySnapSavePath->setText(instance().defaultSaveDir().getShortPath()); + mySnapSavePath->setText(instance().userSaveDir().getShortPath()); mySnapInterval->setValue(2); mySnapName->setState(false); mySnapSingle->setState(false); diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index 2d4a4c135..d568c14cb 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -203,6 +203,36 @@ void Widget::setPos(const Common::Point& pos) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Widget::setWidth(int w) +{ + setSize(w, _h); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Widget::setHeight(int h) +{ + setSize(_w, h); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Widget::setSize(int w, int h) +{ + setSize(Common::Point(w, h)); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Widget::setSize(const Common::Point& pos) +{ + if(pos != Common::Point(_w, _h)) + { + _w = pos.x; + _h = pos.y; + // we have to redraw the whole dialog! + dialog().setDirty(); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Widget::handleMouseEntered() { diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index d62f28e21..e9144f57d 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -57,6 +57,10 @@ class Widget : public GuiObject virtual void setPosY(int y); virtual void setPos(int x, int y); virtual void setPos(const Common::Point& pos); + void setWidth(int w) override; + void setHeight(int h) override; + virtual void setSize(int w, int h); + virtual void setSize(const Common::Point& pos); virtual bool handleText(char text) { return false; } virtual bool handleKeyDown(StellaKey key, StellaMod mod) { return false; } From 6356d56c58402de62281fce281ca66cf6bc027d1 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Thu, 24 Dec 2020 12:24:23 +0100 Subject: [PATCH 16/34] refactored directory names, removed default load dir updated docs --- Changes.txt | 2 ++ docs/index.html | 10 ++++++++++ src/debugger/CartDebug.cxx | 6 +++--- src/debugger/DebuggerParser.cxx | 8 ++++---- src/debugger/gui/DebuggerDialog.cxx | 2 +- src/emucore/OSystem.cxx | 28 ++++++++++++---------------- src/emucore/OSystem.hxx | 13 ++++++------- src/emucore/Settings.cxx | 17 ++++++++--------- src/gui/BrowserDialog.cxx | 2 +- src/gui/GameInfoDialog.cxx | 2 +- src/gui/LoggerDialog.cxx | 2 +- src/gui/SnapshotDialog.cxx | 2 +- src/gui/UIDialog.cxx | 2 +- 13 files changed, 51 insertions(+), 45 deletions(-) diff --git a/Changes.txt b/Changes.txt index 2f733a6e3..32a133633 100644 --- a/Changes.txt +++ b/Changes.txt @@ -32,6 +32,8 @@ * Added sound to Time Machine playback. + * Added browser dialogs for user saved files. + * Extended global hotkeys for input devices & ports settings. * Increased sample size for CDFJ+. diff --git a/docs/index.html b/docs/index.html index 359a8bfed..5657ce955 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3189,6 +3189,16 @@ Make the start path follow ROM launcher navigation. + +
    -userdir <dir>
    + Set the path to save user files to. + + + +
    -saveuserdir <0|1>
    + Update the user path when navigating in browser. + +
    -maxres <WxH>
    Useful for developers, this sets the maximum size of window that diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index b91e5dc26..47d3212ab 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -1352,7 +1352,7 @@ string CartDebug::saveDisassembly(string path) if(path.empty()) - path = myOSystem.userSaveDir().getPath() + path = myOSystem.userDir().getPath() + myConsole.properties().get(PropType::Cart_Name) + ".asm"; else // Append default extension when missing @@ -1380,7 +1380,7 @@ string CartDebug::saveDisassembly(string path) string CartDebug::saveRom(string path) { if(path.empty()) - path = myOSystem.userSaveDir().getPath() + path = myOSystem.userDir().getPath() + myConsole.properties().get(PropType::Cart_Name) + ".a26"; else // Append default extension when missing @@ -1406,7 +1406,7 @@ string CartDebug::saveAccessFile(string path) try { if(path.empty()) - path = myOSystem.userSaveDir().getPath() + path = myOSystem.userDir().getPath() + myConsole.properties().get(PropType::Cart_Name) + ".csv"; else // Append default extension when missing diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 2c02c53dd..488fb68f6 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -683,7 +683,7 @@ string DebuggerParser::saveScriptFile(string file) // Use default path if no path is provided if(file.find_first_of(FilesystemNode::PATH_SEPARATOR) == string::npos) - file = debugger.myOSystem.userSaveDir().getPath() + file; + file = debugger.myOSystem.userDir().getPath() + file; FilesystemNode node(file); @@ -1144,7 +1144,7 @@ void DebuggerParser::executeDump() else { ostringstream file; - file << debugger.myOSystem.userSaveDir() + file << debugger.myOSystem.userDir() << debugger.myOSystem.console().properties().get(PropType::Cart_Name) << "_dbg_"; if(execDepth > 0) { @@ -1240,7 +1240,7 @@ void DebuggerParser::executeExec() file += ".script"; FilesystemNode node(file); if (!node.exists()) - node = FilesystemNode(debugger.myOSystem.userSaveDir().getPath() + file); + node = FilesystemNode(debugger.myOSystem.userDir().getPath() + file); if (argCount == 2) { execPrefix = argStrings[1]; @@ -1910,7 +1910,7 @@ void DebuggerParser::executeSaveses() { ostringstream filename; auto timeinfo = BSPF::localTime(); - filename << debugger.myOSystem.userSaveDir() + filename << debugger.myOSystem.userDir() << std::put_time(&timeinfo, "session_%F_%H-%M-%S.txt"); if(argCount && argStrings[0] == "?") diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index e258aca08..24b2ed4bf 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -466,7 +466,7 @@ void DebuggerDialog::showBrowser(BrowserType type, const string& defaultName) { createBrowser("Save " + title + " as"); - const string path = instance().userSaveDir().getPath() + defaultName; + const string path = instance().userDir().getPath() + defaultName; myBrowser->show(path, BrowserDialog::FileSave, cmd, kBdCancelCmd); } } diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index c9fb0070b..72ec65814 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -217,8 +217,8 @@ void OSystem::loadConfig(const Settings::Options& options) { // Get base directory and config file from derived class // It will decide whether it can override its default location - string baseDir, cfgFile, defSaveDir, defLoadDir; - getBaseDirAndConfig(baseDir, cfgFile, defSaveDir, defLoadDir, + string baseDir, cfgFile, homeDir, unused; + getBaseDirAndConfig(baseDir, cfgFile, homeDir, unused, ourOverrideBaseDirWithApp, ourOverrideBaseDir); // Get fully-qualified pathnames, and make directories when needed @@ -228,13 +228,9 @@ void OSystem::loadConfig(const Settings::Options& options) if(!cfgFile.empty()) myConfigFile = FilesystemNode(cfgFile); - myDefaultSaveDir = FilesystemNode(defSaveDir); - if(!myDefaultSaveDir.isDirectory()) - myDefaultSaveDir.makeDir(); - - myDefaultLoadDir = FilesystemNode(defLoadDir); - if(!myDefaultLoadDir.isDirectory()) - myDefaultLoadDir.makeDir(); + myHomeDir = FilesystemNode(homeDir); + if(!myHomeDir.isDirectory()) + myHomeDir.makeDir(); #ifdef SQLITE_SUPPORT mySettingsDb = make_shared(myBaseDir.getPath(), "settings"); @@ -249,10 +245,10 @@ void OSystem::loadConfig(const Settings::Options& options) // TODO: check if affected by '-baseDir'and 'basedirinapp' params string userDir = mySettings->getString("userdir"); if(userDir.empty()) - userDir = defSaveDir; - myUserSaveDir = FilesystemNode(userDir); - if(!myUserSaveDir.isDirectory()) - myUserSaveDir.makeDir(); + userDir = homeDir; + myUserDir = FilesystemNode(userDir); + if(!myUserDir.isDirectory()) + myUserDir.makeDir(); Logger::instance().setLogParameters(mySettings->getInt("loglevel"), mySettings->getBool("logtoconsole")); @@ -303,7 +299,7 @@ void OSystem::setConfigPaths() #ifdef PNG_SUPPORT const string& ssSaveDir = mySettings->getString("snapsavedir"); if(ssSaveDir == EmptyString) - mySnapshotSaveDir = defaultSaveDir(); + mySnapshotSaveDir = userDir(); else mySnapshotSaveDir = FilesystemNode(ssSaveDir); if(!mySnapshotSaveDir.isDirectory()) @@ -311,7 +307,7 @@ void OSystem::setConfigPaths() const string& ssLoadDir = mySettings->getString("snaploaddir"); if(ssLoadDir == EmptyString) - mySnapshotLoadDir = defaultLoadDir(); + mySnapshotLoadDir = userDir(); else mySnapshotLoadDir = FilesystemNode(ssLoadDir); if(!mySnapshotLoadDir.isDirectory()) @@ -346,7 +342,7 @@ void OSystem::setUserDir(const string& path) { mySettings->setValue("userdir", path); - myUserSaveDir = FilesystemNode(path); + myUserDir = FilesystemNode(path); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx index 1ac973976..0ce5aef4b 100644 --- a/src/emucore/OSystem.hxx +++ b/src/emucore/OSystem.hxx @@ -318,12 +318,11 @@ class OSystem const FilesystemNode& romFile() const { return myRomFile; } /** - The default locations for saving and loading various files that - don't already have a specific location. + The default and user defined locations for saving and loading various + files that don't already have a specific location. */ - const FilesystemNode& defaultSaveDir() const { return myDefaultSaveDir; } - const FilesystemNode& defaultLoadDir() const { return myDefaultLoadDir; } - const FilesystemNode& userSaveDir() const { return myUserSaveDir; } + const FilesystemNode& homeDir() const { return myHomeDir; } + const FilesystemNode& userDir() const { return myUserDir; } /** Open the given ROM and return an array containing its contents. @@ -556,8 +555,8 @@ class OSystem private: FilesystemNode myBaseDir, myStateDir, mySnapshotSaveDir, mySnapshotLoadDir, - myNVRamDir, myCfgDir, myDefaultSaveDir, myDefaultLoadDir, - myUserSaveDir; + myNVRamDir, myCfgDir, myHomeDir, + myUserDir; FilesystemNode myCheatFile, myConfigFile, myPaletteFile, myPropertiesFile; FilesystemNode myRomFile; string myRomMD5; diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 8068b29a9..f9d8e459e 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -528,14 +528,14 @@ void Settings::usage() const << endl << " -saveonexit emulation\n" - << " -autoslot <1|0> Automatically change to next save slot when\n" + << " -autoslot <0|1> Automatically change to next save slot when\n" << " state saving\n" << endl << " -rominfo Display detailed information for the given ROM\n" << " -listrominfo Display contents of stella.pro, one line per ROM\n" << " entry\n" << endl - << " -exitlauncher <1|0> On exiting a ROM, go back to the ROM launcher\n" + << " -exitlauncher <0|1> On exiting a ROM, go back to the ROM launcher\n" << " -launcherpos Sets the window position in windowed EOM launcher mode\n" << " -launcherdisplay Sets the display for the ROM launcher\n" << " -launcherres The resolution to use in ROM launcher mode\n" @@ -544,11 +544,14 @@ void Settings::usage() const << " medium|large|\n" << " large12|large14|\n" << " large16>\n" - << " -launcherroms <1|0> Show only ROMs in the launcher (vs. all files)\n" - << " -launchersubdirs <1|0> Show files from subdirectories too\n" << " -romviewer Show ROM info viewer at given zoom level in ROM\n" << " launcher (use 0 for off)\n" - << " -followlauncher <0|1> Default ROM path follows launcher navigation\n" + << " -launcherroms <1|0> Show only ROMs in the launcher (vs. all files)\n" + << " -launchersubdirs <0|1> Show files from subdirectories too\n" + << " -romdir Set the path where the ROM launcher will start\n" + << " -followlauncher <0|1> Default ROM path follows launcher navigation\n" + << " -userdir Set the path to save user files to\n" + << " -saveuserdir <0|1> Update user path when navigating in browser\n" << " -lastrom Last played ROM, automatically selected in\n" << " launcher\n" << " -romloadcount Number of ROM to load next from multicard\n" @@ -572,10 +575,6 @@ void Settings::usage() const << " -ctrlrate Rate per second of repeated controller input in\n" << " UI\n" << " -basic_settings <0|1> Display only a basic settings dialog\n" - << " -romdir Set the directory where the ROM launcher will\n" - << " start\n" - << " -userdir The directory to save user files to\n" - << " -saveuserdir <1|0> Update user directory when navigating in browser\n" << " -avoxport The name of the serial port where an AtariVox is\n" << " connected\n" << " -holdreset Start the emulator with the Game Reset switch\n" diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 026c16b2f..d401ed8cb 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -271,7 +271,7 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd, break; case kHomeDirCmd: - _fileList->setDirectory(FilesystemNode(instance().defaultSaveDir())); + _fileList->setDirectory(FilesystemNode(instance().homeDir())); break; case EditableWidget::kChangedCmd: diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 4273ce6fc..7710e9fa1 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -1397,7 +1397,7 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, // to re-create it as necessary createBrowser("Export properties as"); - myBrowser->show(instance().userSaveDir().getPath() + myGameFile.getNameWithExt(".pro"), + myBrowser->show(instance().userDir().getPath() + myGameFile.getNameWithExt(".pro"), BrowserDialog::FileSave, kExportChosen); break; diff --git a/src/gui/LoggerDialog.cxx b/src/gui/LoggerDialog.cxx index 3f94e093e..83929464e 100644 --- a/src/gui/LoggerDialog.cxx +++ b/src/gui/LoggerDialog.cxx @@ -116,7 +116,7 @@ void LoggerDialog::saveConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LoggerDialog::saveLogFile() { - FilesystemNode node = instance().defaultSaveDir(); + FilesystemNode node = instance().userDir(); node /= "stella.log"; try diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index 1f3edc36f..69ad94936 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -131,7 +131,7 @@ void SnapshotDialog::saveConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SnapshotDialog::setDefaults() { - mySnapSavePath->setText(instance().userSaveDir().getShortPath()); + mySnapSavePath->setText(instance().userDir().getShortPath()); mySnapInterval->setValue(2); mySnapName->setState(false); mySnapSingle->setState(false); diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 6ba10d9f8..b5b8fb72c 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -515,7 +515,7 @@ void UIDialog::setDefaults() myLauncherHeightSlider->setValue(h); myLauncherFontPopup->setSelected("medium", ""); myRomViewerSize->setValue(35); - mySnapLoadPath->setText(instance().defaultLoadDir().getShortPath()); + mySnapLoadPath->setText(instance().userDir().getShortPath()); myLauncherExitWidget->setState(false); break; } From dfee0703246478c53affe6aadba4bafcff3da241 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Thu, 24 Dec 2020 14:50:26 +0100 Subject: [PATCH 17/34] fixed a saveses bug renamed browser titles --- src/debugger/DebuggerParser.cxx | 13 ++++++++----- src/debugger/gui/DebuggerDialog.cxx | 8 ++++---- src/gui/GameInfoDialog.cxx | 2 +- src/gui/RomAuditDialog.cxx | 2 +- src/gui/SnapshotDialog.cxx | 2 +- src/gui/UIDialog.cxx | 4 ++-- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 488fb68f6..3c8bdac5b 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1144,8 +1144,7 @@ void DebuggerParser::executeDump() else { ostringstream file; - file << debugger.myOSystem.userDir() - << debugger.myOSystem.console().properties().get(PropType::Cart_Name) << "_dbg_"; + file << debugger.myOSystem.userDir() << cartName() << "_dbg_"; if(execDepth > 0) { file << execPrefix; @@ -1910,8 +1909,7 @@ void DebuggerParser::executeSaveses() { ostringstream filename; auto timeinfo = BSPF::localTime(); - filename << debugger.myOSystem.userDir() - << std::put_time(&timeinfo, "session_%F_%H-%M-%S.txt"); + filename << std::put_time(&timeinfo, "session_%F_%H-%M-%S.txt"); if(argCount && argStrings[0] == "?") { @@ -1920,7 +1918,12 @@ void DebuggerParser::executeSaveses() } else { - FilesystemNode file(filename.str()); + ostringstream path; + if(argCount) + path << argStrings[0]; + else + path << debugger.myOSystem.userDir() << filename.str(); + FilesystemNode file(path.str()); if(debugger.prompt().saveBuffer(file)) commandResult << "saved " + file.getShortPath() + " OK"; diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 24b2ed4bf..4403009b8 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -434,12 +434,12 @@ void DebuggerDialog::showBrowser(BrowserType type, const string& defaultName) { case BrowserType::svAccess: cmd = kSvAccessCmd; - title = "access counters"; + title = "Access Counters"; break; case BrowserType::svDis: cmd = kSvDisCmd; - title = "disassembly"; + title = "Disassembly"; break; case BrowserType::svRom: @@ -449,12 +449,12 @@ void DebuggerDialog::showBrowser(BrowserType type, const string& defaultName) case BrowserType::svScript: cmd = kSvScriptCmd; - title = "workbench"; + title = "Workbench"; break; case BrowserType::svSession: cmd = kSvSessionCmd; - title = "session"; + title = "Session"; break; default: diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 7710e9fa1..9a0cb3fe7 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -1395,7 +1395,7 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, case kExportPressed: // This dialog is resizable under certain conditions, so we need // to re-create it as necessary - createBrowser("Export properties as"); + createBrowser("Export Properties as"); myBrowser->show(instance().userDir().getPath() + myGameFile.getNameWithExt(".pro"), BrowserDialog::FileSave, kExportChosen); diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index 60b627f8d..de7f3f5cd 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -198,7 +198,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd, break; case kChooseAuditDirCmd: - createBrowser("Select ROM directory to audit"); + createBrowser("Select ROM Directory to Audit"); myBrowser->show(myRomPath->getText(), BrowserDialog::Directories, kAuditDirChosenCmd); break; diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index 69ad94936..28067213c 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -156,7 +156,7 @@ void SnapshotDialog::handleCommand(CommandSender* sender, int cmd, case kChooseSnapSaveDirCmd: // This dialog is resizable under certain conditions, so we need // to re-create it as necessary - createBrowser("Select snapshot save directory"); + createBrowser("Select Snapshot Save Directory"); myBrowser->show(mySnapSavePath->getText(), BrowserDialog::Directories, kSnapSaveDirChosenCmd); break; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index b5b8fb72c..65c7d927b 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -586,7 +586,7 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) case kChooseRomDirCmd: // This dialog is resizable under certain conditions, so we need // to re-create it as necessary - createBrowser("Select ROM directory"); + createBrowser("Select ROM Directory"); myBrowser->show(myRomPath->getText(), BrowserDialog::Directories, LauncherDialog::kRomDirChosenCmd); break; @@ -602,7 +602,7 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) case kChooseSnapLoadDirCmd: // This dialog is resizable under certain conditions, so we need // to re-create it as necessary - createBrowser("Select snapshot load directory"); + createBrowser("Select ROM Info Viewer Image Directory"); myBrowser->show(mySnapLoadPath->getText(), BrowserDialog::Directories, kSnapLoadDirChosenCmd); break; From 38afecce4ab8a8ca85e0c96841c087665b21fe07 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Thu, 24 Dec 2020 11:51:53 -0330 Subject: [PATCH 18/34] Fix overzealous TV detection in ROM filenames. Fixes #747. --- Changes.txt | 3 +++ src/emucore/Console.cxx | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Changes.txt b/Changes.txt index 2f733a6e3..7386b39c6 100644 --- a/Changes.txt +++ b/Changes.txt @@ -38,6 +38,9 @@ * Fixed autofire bug for trackball controllers. + * Fixed bug in TV autodetection in filenames; a filename containing + 'PAL' would sometimes misdetect as a PAL ROM. + * Fixed Stelladaptor/2600'daptor devices sometimes not being assigned correct default mappings. diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 52620243e..db5850aa4 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -316,13 +316,13 @@ string Console::formatFromFilename() const { R"([ _\-(\[<]+NTSC[ _-]?50)", "NTSC50" }, { R"([ _\-(\[<]+PAL[ _-]?60)", "PAL60" }, { R"([ _\-(\[<]+SECAM[ _-]?60)", "SECAM60" }, - { R"([ _\-(\[<]+NTSC[ _\-)\]>]?)", "NTSC" }, - { R"([ _\-(\[<]+PAL[ _\-)\]>]?)", "PAL" }, - { R"([ _\-(\[<]+SECAM[ _\-)\]>]?)", "SECAM" } + { R"([ _\-(\[<]+NTSC[ _\-)\]>.])", "NTSC" }, + { R"([ _\-(\[<]+PAL[ _\-)\]>.])", "PAL" }, + { R"([ _\-(\[<]+SECAM[ _\-)\]>.])", "SECAM" } }}; - // Get filename *without* extension, and search using regex's above - const string& filename = myOSystem.romFile().getNameWithExt(""); + // Get filename, and search using regex's above + const string& filename = myOSystem.romFile().getName(); for(size_t i = 0; i < Pattern.size(); ++i) { try From b976bd95ca0eff50a7a0f067b1a8b16c9b55e278 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Fri, 25 Dec 2020 09:15:58 +0100 Subject: [PATCH 19/34] enhanced and cleaned up OS specific path code improved mouse double click marking added file list resizing in browser dialog --- src/common/bspf.hxx | 11 +++++++++++ src/emucore/OSystem.cxx | 7 +++---- src/emucore/OSystem.hxx | 7 +++---- src/gui/BrowserDialog.cxx | 12 ++++++------ src/gui/EditableWidget.cxx | 12 ++++++------ src/gui/ListWidget.cxx | 11 +++++++++++ src/gui/ListWidget.hxx | 1 + src/libretro/OSystemLIBRETRO.cxx | 6 +++--- src/libretro/OSystemLIBRETRO.hxx | 7 +++---- src/macos/OSystemMACOS.cxx | 9 +++------ src/macos/OSystemMACOS.hxx | 7 +++---- src/unix/OSystemUNIX.cxx | 10 ++++------ src/unix/OSystemUNIX.hxx | 7 +++---- src/unix/r77/OSystemR77.cxx | 4 ++-- src/unix/r77/OSystemR77.hxx | 7 +++---- src/windows/OSystemWINDOWS.cxx | 15 +++++++++------ src/windows/OSystemWINDOWS.hxx | 7 +++---- 17 files changed, 77 insertions(+), 63 deletions(-) diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index 4a17719ad..44d649869 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -336,6 +336,17 @@ namespace BSPF } #endif } + + inline bool isWhiteSpace(const char s) + { + const string WHITESPACES = " ,.;:+-*&/\\'"; + + for(size_t i = 0; i < WHITESPACES.length(); ++i) + if(s == WHITESPACES[i]) + return true; + + return false; + } } // namespace BSPF #endif diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 72ec65814..f920537b5 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -217,8 +217,8 @@ void OSystem::loadConfig(const Settings::Options& options) { // Get base directory and config file from derived class // It will decide whether it can override its default location - string baseDir, cfgFile, homeDir, unused; - getBaseDirAndConfig(baseDir, cfgFile, homeDir, unused, + string baseDir, cfgFile, homeDir; + getBaseDirAndConfig(baseDir, cfgFile, homeDir, ourOverrideBaseDirWithApp, ourOverrideBaseDir); // Get fully-qualified pathnames, and make directories when needed @@ -239,10 +239,9 @@ void OSystem::loadConfig(const Settings::Options& options) #endif mySettings->setRepository(createSettingsRepository()); - mySettings->load(options); - // TODO: check if affected by '-baseDir'and 'basedirinapp' params + // userDir is NOT affected by '-baseDir'and '-basedirinapp' params string userDir = mySettings->getString("userdir"); if(userDir.empty()) userDir = homeDir; diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx index 0ce5aef4b..484bf8861 100644 --- a/src/emucore/OSystem.hxx +++ b/src/emucore/OSystem.hxx @@ -463,8 +463,7 @@ class OSystem @param basedir The base directory for all configuration files @param cfgfile The fully qualified pathname of the config file (including the base directory) - @param savedir The default directory to save various other files - @param loaddir The default directory to load various other files + @param homedir The default directory to store various other files @param useappdir A hint that the base dir should be set to the app directory; not all ports can do this, so they are free to ignore it @@ -473,8 +472,8 @@ class OSystem they are free to ignore it */ virtual void getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) = 0; + string& homedir, + bool useappdir, const string& usedir) = 0; protected: // Pointer to the EventHandler object diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index d401ed8cb..d56b8558d 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -126,9 +126,9 @@ void BrowserDialog::show(const string& startpath, const string& ext) { const int fontWidth = _font.getMaxCharWidth(), - //fontHeight = _font.getFontHeight(), - HBORDER = fontWidth * 1.25; - //VGAP = fontHeight / 4; + fontHeight = _font.getFontHeight(), + HBORDER = fontWidth * 1.25, + VGAP = fontHeight / 4; _mode = mode; _cmd = cmd; @@ -153,7 +153,7 @@ void BrowserDialog::show(const string& startpath, _fileList->setNameFilter([ext](const FilesystemNode& node) { return BSPF::endsWithIgnoreCase(node.getName(), ext); }); - //_fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop()); + _fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop()); _currentPath->setWidth(_savePathBox->getLeft() - _currentPath->getLeft() - fontWidth); _savePathBox->setEnabled(true); @@ -172,7 +172,7 @@ void BrowserDialog::show(const string& startpath, _fileList->setNameFilter([ext](const FilesystemNode& node) { return BSPF::endsWithIgnoreCase(node.getName(), ext); }); - //_fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop()); + _fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop()); _currentPath->setWidth(_savePathBox->getLeft() - _currentPath->getLeft() - fontWidth); _savePathBox->setEnabled(true); @@ -192,7 +192,7 @@ void BrowserDialog::show(const string& startpath, _fileList->setListMode(FilesystemNode::ListMode::DirectoriesOnly); _fileList->setNameFilter([](const FilesystemNode&) { return true; }); // TODO: scrollbar affected too! - //_fileList->setHeight(_selected->getBottom() - _fileList->getTop()); + _fileList->setHeight(_selected->getBottom() - _fileList->getTop()); _currentPath->setWidth(_savePathBox->getRight() - _currentPath->getLeft()); _savePathBox->setEnabled(false); diff --git a/src/gui/EditableWidget.cxx b/src/gui/EditableWidget.cxx index 0a76bd7d1..2b37a0ba2 100644 --- a/src/gui/EditableWidget.cxx +++ b/src/gui/EditableWidget.cxx @@ -657,7 +657,7 @@ bool EditableWidget::killWord(int direction) { while(currentPos > 0) { - if(_editString[currentPos - 1] == ' ') + if(BSPF::isWhiteSpace(_editString[currentPos - 1])) { if(!space) break; @@ -673,7 +673,7 @@ bool EditableWidget::killWord(int direction) { while(currentPos < int(_editString.size())) { - if(currentPos && _editString[currentPos - 1] == ' ') + if(currentPos && BSPF::isWhiteSpace(_editString[currentPos - 1])) { if(!space) break; @@ -709,7 +709,7 @@ bool EditableWidget::moveWord(int direction, bool select) { while (currentPos > 0) { - if (_editString[currentPos - 1] == ' ') + if (BSPF::isWhiteSpace(_editString[currentPos - 1])) { if (!space) break; @@ -728,7 +728,7 @@ bool EditableWidget::moveWord(int direction, bool select) { while (currentPos < int(_editString.size())) { - if (currentPos && _editString[currentPos - 1] == ' ') + if (currentPos && BSPF::isWhiteSpace(_editString[currentPos - 1])) { if (!space) break; @@ -754,14 +754,14 @@ bool EditableWidget::markWord() while(_caretPos + _selectSize < int(_editString.size())) { - if(_editString[_caretPos + _selectSize] == ' ') + if(BSPF::isWhiteSpace(_editString[_caretPos + _selectSize])) break; _selectSize++; } while(_caretPos > 0) { - if(_editString[_caretPos - 1] == ' ') + if(BSPF::isWhiteSpace(_editString[_caretPos - 1])) break; _caretPos--; _selectSize++; diff --git a/src/gui/ListWidget.cxx b/src/gui/ListWidget.cxx index a8c0c37da..ae2551e8f 100644 --- a/src/gui/ListWidget.cxx +++ b/src/gui/ListWidget.cxx @@ -56,6 +56,17 @@ ListWidget::ListWidget(GuiObject* boss, const GUI::Font& font, _w = w - 1; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ListWidget::setHeight(int h) +{ + Widget::setHeight(h); + if(_useScrollbar) + _scrollBar->setHeight(h); + + _rows = (h - 2) / _lineHeight; + recalc(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ListWidget::setSelected(int item) { diff --git a/src/gui/ListWidget.hxx b/src/gui/ListWidget.hxx index 1fba03f01..25ea1906f 100644 --- a/src/gui/ListWidget.hxx +++ b/src/gui/ListWidget.hxx @@ -47,6 +47,7 @@ class ListWidget : public EditableWidget int rows() const { return _rows; } int currentPos() const { return _currentPos; } + void setHeight(int h) override; int getSelected() const { return _selectedItem; } void setSelected(int item); diff --git a/src/libretro/OSystemLIBRETRO.cxx b/src/libretro/OSystemLIBRETRO.cxx index 02844de63..4d1578f69 100644 --- a/src/libretro/OSystemLIBRETRO.cxx +++ b/src/libretro/OSystemLIBRETRO.cxx @@ -26,8 +26,8 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void OSystemLIBRETRO::getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) + string& homedir, + bool useappdir, const string& usedir) { - loaddir = savedir = cfgfile = basedir = "." + slash; + basedir = cfgfile = homedir = "." + slash; } diff --git a/src/libretro/OSystemLIBRETRO.hxx b/src/libretro/OSystemLIBRETRO.hxx index 60b1fc4e5..0fdadb8af 100644 --- a/src/libretro/OSystemLIBRETRO.hxx +++ b/src/libretro/OSystemLIBRETRO.hxx @@ -41,8 +41,7 @@ class OSystemLIBRETRO : public OSystem @param basedir The base directory for all configuration files @param cfgfile The fully qualified pathname of the config file (including the base directory) - @param savedir The default directory to save various other files - @param loaddir The default directory to load various other files + @param homedir The default directory to store various other files @param useappdir A hint that the base dir should be set to the app directory; not all ports can do this, so they are free to ignore it @@ -51,8 +50,8 @@ class OSystemLIBRETRO : public OSystem they are free to ignore it */ void getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) override; + string& homedir, + bool useappdir, const string& usedir) override; }; #endif diff --git a/src/macos/OSystemMACOS.cxx b/src/macos/OSystemMACOS.cxx index 9d933da8b..0ba22279e 100644 --- a/src/macos/OSystemMACOS.cxx +++ b/src/macos/OSystemMACOS.cxx @@ -21,8 +21,8 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void OSystemMACOS::getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) + string& homedir, + bool useappdir, const string& usedir) { basedir = "~/Library/Application Support/Stella/"; @@ -31,14 +31,11 @@ void OSystemMACOS::getBaseDirAndConfig(string& basedir, string& cfgfile, if(useappdir) cout << "ERROR: base dir in app folder not supported" << endl; else if(usedir != "") - { basedir = FilesystemNode(usedir).getPath(); - savedir = loaddir = basedir; - } #endif FilesystemNode desktop("~/Desktop/"); - savedir = loaddir = desktop.isDirectory() ? desktop.getShortPath() : "~/"; + homedir = desktop.isDirectory() ? desktop.getShortPath() : "~/"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/macos/OSystemMACOS.hxx b/src/macos/OSystemMACOS.hxx index 89d6638c1..1bfedb011 100644 --- a/src/macos/OSystemMACOS.hxx +++ b/src/macos/OSystemMACOS.hxx @@ -41,8 +41,7 @@ class OSystemMACOS : public OSystem @param basedir The base directory for all configuration files @param cfgfile The fully qualified pathname of the config file (including the base directory) - @param savedir The default directory to save various other files - @param loaddir The default directory to load various other files + @param homedir The default directory to store various other files @param useappdir A hint that the base dir should be set to the app directory; not all ports can do this, so they are free to ignore it @@ -51,8 +50,8 @@ class OSystemMACOS : public OSystem they are free to ignore it */ void getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) override; + string& homedir, + bool useappdir, const string& usedir) override; protected: virtual shared_ptr createSettingsRepository() override; diff --git a/src/unix/OSystemUNIX.cxx b/src/unix/OSystemUNIX.cxx index 6b6ec4df3..2156e0975 100644 --- a/src/unix/OSystemUNIX.cxx +++ b/src/unix/OSystemUNIX.cxx @@ -23,23 +23,21 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void OSystemUNIX::getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) + string& homedir, + bool useappdir, const string& usedir) { // Use XDG_CONFIG_HOME if defined, otherwise use the default string configDir = BSPF::getenv("XDG_CONFIG_HOME"); + if(configDir == EmptyString) configDir = "~/.config"; basedir = configDir + "/stella"; - savedir = loaddir = "~/"; + homedir = "~/"; // Check to see if basedir overrides are active if(useappdir) cout << "ERROR: base dir in app folder not supported" << endl; else if(usedir != "") - { basedir = FilesystemNode(usedir).getPath(); - savedir = loaddir = basedir; - } // (Currently) non-documented alternative for using version-specific // config file diff --git a/src/unix/OSystemUNIX.hxx b/src/unix/OSystemUNIX.hxx index b562a3c3d..e9309787e 100644 --- a/src/unix/OSystemUNIX.hxx +++ b/src/unix/OSystemUNIX.hxx @@ -41,8 +41,7 @@ class OSystemUNIX : public OSystem @param basedir The base directory for all configuration files @param cfgfile The fully qualified pathname of the config file (including the base directory) - @param savedir The default directory to save various other files - @param loaddir The default directory to load various other files + @param homedir The default directory to store various other files @param useappdir A hint that the base dir should be set to the app directory; not all ports can do this, so they are free to ignore it @@ -51,8 +50,8 @@ class OSystemUNIX : public OSystem they are free to ignore it */ void getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) override; + string& homedir, + bool useappdir, const string& usedir) override; private: // Following constructors and assignment operators not supported diff --git a/src/unix/r77/OSystemR77.cxx b/src/unix/r77/OSystemR77.cxx index dd692b24f..50da2b086 100644 --- a/src/unix/r77/OSystemR77.cxx +++ b/src/unix/r77/OSystemR77.cxx @@ -19,8 +19,8 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void OSystemR77::getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, bool, const string&) + string& homeDir, bool, const string&) { - basedir = savedir = loaddir = "/mnt/stella"; + basedir = homeDir = "/mnt/stella"; cfgfile = "/mnt/stella/stellarc"; } diff --git a/src/unix/r77/OSystemR77.hxx b/src/unix/r77/OSystemR77.hxx index 58d80d80e..fc7f4efa4 100644 --- a/src/unix/r77/OSystemR77.hxx +++ b/src/unix/r77/OSystemR77.hxx @@ -43,8 +43,7 @@ class OSystemR77 : public OSystem @param basedir The base directory for all configuration files @param cfgfile The fully qualified pathname of the config file (including the base directory) - @param savedir The default directory to save various other files - @param loaddir The default directory to load various other files + @param homedir The default directory to store various other files @param useappdir A hint that the base dir should be set to the app directory; not all ports can do this, so they are free to ignore it @@ -53,8 +52,8 @@ class OSystemR77 : public OSystem they are free to ignore it */ void getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) override; + string& homedir, + bool useappdir, const string& usedir) override; private: // Following constructors and assignment operators not supported diff --git a/src/windows/OSystemWINDOWS.cxx b/src/windows/OSystemWINDOWS.cxx index d1df4f55c..f7b6787fb 100644 --- a/src/windows/OSystemWINDOWS.cxx +++ b/src/windows/OSystemWINDOWS.cxx @@ -23,11 +23,12 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void OSystemWINDOWS::getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) + string& homedir, + bool useappdir, const string& usedir) { HomeFinder homefinder; FilesystemNode appdata(homefinder.getAppDataPath()); + if(appdata.isDirectory()) { basedir = appdata.getShortPath(); @@ -35,8 +36,9 @@ void OSystemWINDOWS::getBaseDirAndConfig(string& basedir, string& cfgfile, basedir += '\\'; basedir += "Stella\\"; } - FilesystemNode defaultLoadSaveDir(homefinder.getDesktopPath()); - savedir = loaddir = defaultLoadSaveDir.getShortPath(); + + FilesystemNode defaultHomeDir(homefinder.getDesktopPath()); + homedir = defaultHomeDir.getShortPath(); // Check to see if basedir overrides are active if(useappdir) @@ -44,12 +46,13 @@ void OSystemWINDOWS::getBaseDirAndConfig(string& basedir, string& cfgfile, char filename[MAX_PATH]; GetModuleFileNameA(NULL, filename, sizeof(filename)); FilesystemNode appdir(filename); + appdir = appdir.getParent(); if(appdir.isDirectory()) - savedir = loaddir = basedir = appdir.getPath(); + basedir = appdir.getPath(); } else if(usedir != "") - savedir = loaddir = basedir = FilesystemNode(usedir).getPath(); + basedir = FilesystemNode(usedir).getPath(); cfgfile = basedir + "stella.ini"; } diff --git a/src/windows/OSystemWINDOWS.hxx b/src/windows/OSystemWINDOWS.hxx index 4995f9f51..b938c3719 100644 --- a/src/windows/OSystemWINDOWS.hxx +++ b/src/windows/OSystemWINDOWS.hxx @@ -41,8 +41,7 @@ class OSystemWINDOWS : public OSystem @param basedir The base directory for all configuration files @param cfgfile The fully qualified pathname of the config file (including the base directory) - @param savedir The default directory to save various other files - @param loaddir The default directory to load various other files + @param homedir The default directory to store various other files @param useappdir A hint that the base dir should be set to the app directory; not all ports can do this, so they are free to ignore it @@ -51,8 +50,8 @@ class OSystemWINDOWS : public OSystem they are free to ignore it */ void getBaseDirAndConfig(string& basedir, string& cfgfile, - string& savedir, string& loaddir, - bool useappdir, const string& usedir) override; + string& homedir, + bool useappdir, const string& usedir) override; private: // Following constructors and assignment operators not supported From 717a678a035b399ad2ad22926a52b97e456ec4c6 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Fri, 25 Dec 2020 09:38:37 +0100 Subject: [PATCH 20/34] minor doc updates --- docs/index.html | 2 +- src/debugger/DebuggerParser.cxx | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/index.html b/docs/index.html index 5657ce955..aa200a645 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3191,7 +3191,7 @@
    -userdir <dir>
    - Set the path to save user files to. + Set the path to save user files (property exports, debugger saves) to. diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 3c8bdac5b..0d35b5e30 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -681,7 +681,7 @@ string DebuggerParser::saveScriptFile(string file) if(file.find_last_of('.') == string::npos) file += ".script"; - // Use default path if no path is provided + // Use user dir if no path is provided if(file.find_first_of(FilesystemNode::PATH_SEPARATOR) == string::npos) file = debugger.myOSystem.userDir().getPath() + file; @@ -2669,9 +2669,10 @@ std::array DebuggerParser::commands = { { "dump", "Dump data at address [to yy] [1: memory; 2: CPU state; 4: input regs]", "Example:\n" - " dump f000 - dumps 128 bytes @ f000\n" + " dump f000 - dumps 128 bytes from f000\n" " dump f000 f0ff - dumps all bytes from f000 to f0ff\n" - " dump f000 f0ff 7 - dumps all bytes from f000 to f0ff, CPU state and input registers into a file", + " dump f000 f0ff 7 - dumps all bytes from f000 to f0ff,\n" + " CPU state and input registers into a file in user dir", true, false, { Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE }, @@ -3095,7 +3096,8 @@ std::array DebuggerParser::commands = { { { "save", "Save breaks, watches, traps and functions to file xx", - "Example: save commands.script, save ?", + "Example: save commands.script, save ?\n" + "NOTE: saves to user dir by default", true, false, { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, @@ -3106,7 +3108,7 @@ std::array DebuggerParser::commands = { { "saveaccess", "Save the access counters to CSV file", "Example: saveaccess, saveaccess ?\n" - "NOTE: saves to default save location without ? parameter", + "NOTE: saves to user dir by default", false, false, { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, @@ -3127,7 +3129,7 @@ std::array DebuggerParser::commands = { { "savedis", "Save Distella disassembly", "Example: savedis, savedis ?\n" - "NOTE: saves to default save location without ? parameter", + "NOTE: saves to user dir by default", false, false, { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, @@ -3138,7 +3140,7 @@ std::array DebuggerParser::commands = { { "saverom", "Save (possibly patched) ROM", "Example: saverom, saverom ?\n" - "NOTE: saves to default save location without ? parameter", + "NOTE: saves to user dir by default", false, false, { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, @@ -3149,7 +3151,7 @@ std::array DebuggerParser::commands = { { "saveses", "Save console session", "Example: saveses, saveses ?\n" - "NOTE: saves to default save location without ? parameter", + "NOTE: saves to user dir by default", false, false, { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, From 5cac51c637f043308aefd6a52c4e1fe7c0e08cf9 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Fri, 25 Dec 2020 18:00:40 +0100 Subject: [PATCH 21/34] added BrowserDialog to LoggerDialog updated some docs --- docs/graphics/debugger_main.png | Bin 78817 -> 64326 bytes docs/graphics/resources/debugger_main.pdn | Bin 274816 -> 258756 bytes docs/index.html | 32 ++++++++++++---------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/graphics/debugger_main.png b/docs/graphics/debugger_main.png index 2064cd85a26a1ed33153a40cdcc8414b19038c2a..d6831b9ad70c276d6d1d641ae57d28c5801998ec 100644 GIT binary patch literal 64326 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 literal 78817 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� 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

    -TYQ0`<`#wchb@IM^W@!5hy$clS zgg3o5ae7A}zX}`npie>}8vPALU!r0Qg>}~NQAb7z09UvMP*|BGFx)2zu<^ahZy_to ziw_q*E=qR!njf?awI0>ed~-Oz>D@xKCc45abw-TFK9Vmi0AJIr{~Xb(^V^i%I?^A` z1tOtNT4#PYeYp~JTno!)jEt&(0GyQ8Jy)jx`$-@>eo2`vNEUR$fz7v|lnPMPA+)s( zFU5-Lbo+KMszzgjABY$Vz~-~q#as)Zc$uK>Eh@k9ihu}k4#AIvDGMIcvUgoyS&ab| z6yVHt>3t9?#myG6`aMB$0rO?Yz4OeL2WbgvFypBBq2@!6^dG59?wM}m5ynt@pds|{ z=ZO7!BG)3l&K9Zxxi!8+7~!TF#MS6JWjzT*=$Uj8Jt=9zxIot&JSy;#@C*QVG~n4l zWKxw@T|L!wR+i}7<4`}*{cM$^Yi%^$6)ni95@`RFd*cOl>CUq!f13uhi^>aMd!aoC z74I$>@a}Zhq8bcL*b5Ca@!st#Vz0!N;R9F7RYmVztMl5ndnFTyD0j+_Bt1P^5?@%6 z(e*8V*MQa^^wSuMGY0-A)v5Z3p<(AWmC{?0BD@V$TFyPxRN_uUL2flgFF-k2V_vz8(F-%n2i*!(0 zFv4@|P!w5~oR*HiKwMqcJM3J|#34&E=G|&G({e5t$|NC?Sdh(JA|9ye+~gYMJM@>$ zCw=|BI_}$l%8YXH4~wdIf0Dh#RPJ#ueNOcm4Ch|$L)n1wElg%7p96hq+Or~6dH^Sd zKP_K~g}1Ba(LpIC<|5Rw0|vq*P*#@yWD0E^vCdYG6+2dzz5!#am zW_5=ukWM{x8{K)czR+WHUo(1s+@6h|k_#_he{E16geTvGAkn2>`q3#D`H{V7ig5_a zumtAuq8)aiY`aosrkh+kBH?)I+@*$^8Qc|xwKd;a(N3cT~zL z`xE6fT^Kt15H;E%*oPk%VR(hf0Mix%M!GOe)D$*9h&q2rA+yD`;;7x$2s_(*cM%Vx zjRCtaUaLmr&jO#Zgaz#K76a4#+V|Li2=}{-X5>YXS~m4wN@pY*(!Qd!f=BVnHmi-iDb+ehpL)c5Elkrj1&v@)lSx>i#%aYZ|MG3(NQ^0u zH3P8O1*3Ws5CxwLnbWqeCttSeq&epu+Tz_Mz&O~Q>?TzpoiE%0RyW*Rnq7OSnvF#; ztFPy(R;~iw^Nfzf{*|Mpim{lyD6FX0=)_PX5M+f+B=0eByuD|OYyEx@n%(L2JQ)}P z(b{m+JQ3$9?H1OSX^Bhid-&4!Lz)Oub@GGmL+CNst-8Fi5(mJO`!Y(<1f7xP^w&ep z4w`OdZS+;AdN|7Xim*M{a&)V~JF?@h&zTVJ2@=+z6)NjsK!DG+;$yNA7QMZi-M9D{ zSbow&t@pmv0nE<=cckMv*48I(KkjPxXt$uKK?{As3JfH!qjCE-U0k5T^k%T8{jN?| zXC#va%rgL48MH4VmcXMDT-<}xNDMg zZgF$qV**x+u&u;ytW}G-#p_=sdaTBgvi z2TuEinG^$omCT0^?>7VKxnm9rcRK?6bsb)zT+=GV$R3eHC0_U>H1c9_f&>(x&CR&+ zNSS10K{R^(HV{-Mo$1i8)6uOH#S_OP2ZTC{IJ3~$P@2qj{g9q#isQT7DQzTSj-p^j zEtAZ!b<0^9o2-Q!vPG>p~B{Ah>`81%~m)5iCM+W{5za|2KD<%VRXvwmw2f?GLJrxA1KYS-&DKoBR^`L34#zQsJc0 zO#O<;9j5f9>CSEh7mCtE?mmp?&c_?^2Jny;BX^io(pKhDSX;Z){h?og_;GV@h^+ii zkAV2hAf-^({y->m-ZlA+iXxn|>pF89FWaM<42CTEZ~{u_QUzCvtSCws=6h7~a0 z=#P{&#g}Q@6+T|r1w+UoHRv$=ln*1Mlanav{7*pN38I|Y$0C!~z>m8t-kJHj{Kd{8 z#l3x7ymhV;pB8Wa{p|gUWcP@)n;s#t{G@zT2NIc?w_7^oaPZ^f zxdj_kphr-=Vb>rCd~W`+8A0|;E3HjtdBzuYRh}|>+&ahyO$G@TG~TBcp6mI76syVj1|}`u#~Vx{c{Dg zir1E|pFpZf=fA3U+psmnYe&>02@CSS)laN7Uq_LbmLX6Yp!J^-un{x)N0n&1n{LsV zuz4Y+)of{G*z8c={x{d95$MoVz|jG19jAQXq@5a_VJirNFY5Xftp8bfs8Q~e{oLnn z09>lwwn+5_yhHr6Oy77;dWw7 zgDDPdY9mM zPuGNbR!7^sJn(IKs@0)t697>E?g@OBEPfT`ZXUqSp!n+Vn^+VqTIxh8CHPOpz1Oab z#@NA5Wn3V>yMtA1R?bAWKSgC5ovTL!aB!^Z5@bRejf@BCalYMm=?)TBk5a8%<&MIv zq%*RU|EkPIBVWVqwc}{mgxJUj-KO9^>Gwl&na}gXYr9q9wy~u4 zu=`@($&`)U%7#QJdrT0N$@m2I-^2Nu$6gqxq{IJ=Ox^R*X&i)6%>}`rtG+l7uJd^} zb^V>I;uUSfgmWd6%Yn|@%>4Zz)BXGuU%T7nycndzRMr0ed_XeV$b{D8MwBgdkfWPU zaex4|B*s-t7M`TqBqOU(40|B<`LFpx`qS=L$brP_QW6*ycRS;W#?8?97t*hFtj_#i zYFLXehTL!bsuA-73_B+9@vd`lK9%g@YrWzL?<>)rXyeoQP%Pe$~rY5 z+{$1z!3xGU?kfVurFL0hL|1Bch~e;bc?UPQn|;quYE@a;mY$9lVdAz93Xown)JIMq z#f#>0!i%+OhR{V;uU#mdoA$r}M-4K5SmD!)hu-#&@DOHAL)mzn3i_L-jsr>gymW=W zQ{!QwgyrtIz@V=n=d9G5LbPzN$DfMisU{`;-Dr2NwXA2hiIYXUThCAtGsl`^wC*8Z zQ=Z!06eb^U4!LAXKdor@F7%fs2?oQEXU^hK46z^hnM}$)F ze$RfmB{^vnTqt-lOW)~5=$4;t1$O+f{Q@zHZk&a-0`ecX zfd7)^-^a94RC{WA*#DIIg#qAP=;2=!c>lzN&NswNgXk4|qYf-TcQ#nGNo7?+5ZP;WV{C@pyjZ@iEm+2H* zuVNwI4lfo=F0{_h-Pj%oR%lv~()JPCYIFZmw6*ab_@xD`@k$HFM)s?MF8j;;!PIWM zuwtCo`oyGLzhB{<9-QGE{(1!h%!?l0E=C)#GZmnQtN3PJY+3h8;TquXGM8JfHLh=P za552IEu*kTd)!%ZLiM%9r&Vk9jO*O$iwr`3GJBS(TVlNtf8F}4gfLPztFsO%2;u`h zln%3V<&WNz;u63Ag)V`w#{^NFYm{sudi?-C28O>rqodC`Ca;;zNP08KsopaT50P-o zY|JgmFamrvr$g$xzKX@vNY1!2c4zY;1OMRF?+fmXqV#Ix_3|w0J>9zxVv;KKK4fQ5 zD=c|WxqN{(q^sH|yZo%3{!#6=W8#@qEcHDTubp!))djcRYgMePj8icr3T+0;C;}qR zmpn`1Slw)MF4=r^lqOl`Fb;p(!sg1iO%bN`$UNMaKMf3t`b4(zYqq^9lCYP1-|U-M z@dZ$WcP1OWW~W{w`PM>Z)TDMA`4+?97H~NGBFJ>XU1J%B>O||)O?^-|cNFJ(SmP62 zU6|4R()!S4p?!8T$qb;S{IU;D!s1?MRX$8!2vKJU0Hf8k6KF?Wp#G8AnbqqYrmg$< zgs}W?^+a!7O7hwWZBZA$&ZHHNo^X1yf&=5(2uv^|>czLmgZpKF6CZhT$4k?Y2-5Ys#M)%y?LtBywvDM>)1A z=~pW+*-qA`5q&NdwzWwKpS@FJW9#dWyIMe>R>wEq6|u|g__mtLs8G1izKJ+hEpIYG ztc?(IKfc3JZ_0ewrB2hcNpF&A%GsnbrAHMm1&A5`#a?X7WiieybE$|a zAW*p2kS|$zIPo!UuK5$hsf%b+)%NpM$OJ2)7g(EJvBt?QQ>2?+wWx-OW_h-im-kPPBF(x`{`HZM+cFQVHfD4{LJeJlzt+W6kzhDD$4yTLZx$4KEHTD1 zt1*)v(=pYjg>3!qqIl$ypV&*T6{OoKH=2$2j9QgtJ-RT&Stx;+R|sop4ioSaKv4-{ z_9ab?Xtp-|DZ9M9NfD0vLoSGe*&!6z z$@vgODSQI*Jtx|HCk`})9y_S%cK8o*2^tLbJS;(&~rcPH_wcEX;^*He=KIZ~P znnww*>T>Z!f*St)vQc&B2sq>1%tfgj2NhF}q3qm6zw?y|b2K@X&p(szgWV99pAXKy zTeAc&q;^X}DJJ*!U~;$g5pEC|UgNT*w1GL=Bj{Tnx;kUNg;2t;RhAc_5* zI^&ni!&=FsFavRgao+F!ZBEhYd&BQdW_joVSZzyV{i9h#@_VMK=HIjGSW)4OMBA*I zX#>!jHafs|q^lwET_J&j00*-@EK(zeH?apmEX!zOJs?=&Msw}9uE(c7_{5y){d>5F zI(oIZ5Ln`+4vmIKQ%4h&1P9#{24+4r!bk{&!skH`owk*zJYj=uQX@vCoNP=0(V2iu zC1IkT?PEw-h%~->qCqtSHt>aFWrLW<^#7om-7hXdcGc`@`H0i1^NPLCeT{4a1rS-r z&=)E_-Ms-3f#7rWgj+-tct3OiGLzu$EA_hgRu9&yv!b6twUiW7BjLH60H2TvWMtT5 zmZQI%1k|vI=ZKl?mqK18k}O*SnZ-{ULh?cNfQM%;Y2Df4y}g^R>wNzbi_Ds@uqi%= z6YkrZWE@*tsu#v50EJY(!S4_-RB&N5C2WmPM3hcLT?_aTjnZmveY{mOwtkCr0ij%#y1QT8n~NYLpZl*^8vv? zY`Q@ux>e0#3xI#I?CZl502hrDhOcvT(!z$ij+^&RQKA1a0^^ zQ_~T$m1!e{&>@u3jw>Fm*U{;C{Axj^bm}v4RxlLO`Bz$IBJ9N+gGkT@iL|ReSq_6H zfES>XmPg2BSBUThVt8d9jK2bqPKD6l*WW+)Rm?S^erd8R&H#%G)IP`o=f7 z<0KtB$G~8}wv5>p^o_APOh5{4xb&uqbNudDSLy2;zH0eaTWZ%Oj)CFP^k9YoNxzf) zA7O*3s{OhB|nkgX*l!t5k$OW>pKJWY|HCzp!ukPIgMp;Za1 zvkQ*{z3Npn#6bITMdhfH7~Y`p$(GyY3$tY-`+DF@O>$gH((y5@?O~q?2b0AScM2iX zc;quLgk*z#P~8HbAaUN7g}wznl%uWAqTna8;0cVT8CvSrgvOtgl5On&NWOU5xqxI!we{d!OV$9+k`qY4P;BV=eDXGhcmZ zjR9V!Pe;_qV`lVkLzqZzW1+e4ydf88lo3cgY~>0s(wyTWl{SXKP+uRmy^Vv+2uIEK0 z@(wrdu=J9ulOh@HoSb?LdX%R9&nUom1PCGy zaCH}f5~z@VSMa*zdp*_Jq|gWUY5400r!F7P&Xx&FFApFYpY;*W5V>JTx#XVpU@64C zuAJESIBJd+;6_*d*ILr6wandblUu|)7AdTZ-UGQvu1`l_~V^PfkpGERud!S|hJ1;h{DQxA9UK%r}UHsCfbBZj%?jt!+*3O{Mg68v5Mr z^*EaQfo1YZ&>HHBOaDP}QVvqYIt*4N(#9a-8`iqGpSjz4&g2J_${UO&Iy5S)t8yxf z5mP{JAyzOC<1$KHkJJGw|7rKtQo*(-X(6!t6erWD8pu;UeZHksg-aX2%3S-t{8M$t zntNe!{8Mr1!<^jBlL{jN3%_x*;l!tKf~^UV3o${N7Msxa zdNOP>4A9DQ&fFeh?mL=~Y#?vD7J-@dEfVit=R52uP9(NPAyP4{cP_n&5Rjip2ZS?NLgGC)}p|GbgM_0 zm3|$kC-2wb&fcuY*<0~&f|xkstZ?~?4&L>J&+9st=*L}|(vb(AC*Wg{gzA}KA{@N6 z8ld}?92J@!-W^C*9y8RQxSNP`fNU(+jNYd=2EP|(!^$6Ng1!;{L?>*nfASN;3wQft z1dyPm^0W}kB2s4lk&b`w9)ql50*?DnP7;n~DL4f1!Y?PAn4bn2FG_y`&kYjmMn%1? z4t-4kU^@$|p^Zz!=Fd&7dVzZu?Ak_@p$2qCCr?Jfdx@RFQwKOo*b=1mrCPmLwV@J2 ziW*5*vdeZ31`7F5H4HCCvk7$m_3yPyeKYo^Q~y`cPlw^z7Ble%+cz^!$zISg>7@#> zO6%8F1)@T6HmJepC$gvAD__64gFb=7;}%i>m4qKWQS?%u`Rs+7Nx0(SL~{blZJE#5 zj^v!{sJya9oA`v&P^K*zbr8Q*mF{RRxir{_+{Rk&eAxNgP(=7Hk|q4 z|299CH@NV#!UawTBSYWQ`@bML?#8n!^{Huk!Q@v8xDR!fp`X9C%wcmHk@TN&1pA?D z-=x~cKSYiV`YJx=9k-|G@|LG8?_nkvaL|Ct(s5i=A#aCQL>8<&x?S=v?z&cOTsb{- z3E^(PSe{2teMfZ}=5YcVF<*SoZmtloGkN7CF)16Pvu+B#(D_3&TBUIIV!OLpO=`C- zlKq3d0S%Mc_bD1B?|Iu28hP~S%3A!`&upn;l>0BgR1a0t??yuhwEe=M4(gWfk9}-{ zr^j(C&Rg%qS`scIYgjiSO+EU9GcSKd-uc9-2uELO2h}X%Vvfe9a{`e2ebEF&&l`qw zj2WfU@Q%0$biahd-9OhGF(}reA14Lkj6#nY2Bjd;^+8J*J}ko&fb8O2@Ae`kx0WcVTNbY=6^Wd zck5Zy#s%#L7Nci(wo35L0tKr3Fei5!g0(%Mtu8W&gTUcX<5oq7G+zXbONzJn#Vt9W z2gcZAbQtSz9??x;4wz%2eqpI!kT85wG9IVo-i@d9-lZM28;{KkH6N~Q#C_8m>Rd!Q znR9a56#B%aSAqhEa>hV$=m%$Ws5319*q?ZVKp zogepdI4rctXgNlbi)@4z82NWU6C`LA;e?;<8-y$-^dnuJOFHrKR-EsGZ?l;Tj>hq6ADq3oQZq)%S#}UY`(651<>Y zOqs>9yvBJ`TsXoGPNPIVUG)ynCLe+w24{X&F&@2Q7mN1}L6FGbBasFQ zw0ey#!(SMx)vL9mi>jm)YC75P%IwVtIBl~m`m$A#9eap&UApAyBjk70D*dL34eD+@ z@mG(*9ss2|5}rY42wJ~Q?O8HUA9cI{|e)j#Bir@X)vJz>|eZz zBhRJDYq857M5K3OtG`=Q~HDxyb$t3mWqM${#rXtH-ZnG>6uIFjh44+;Hk8^F-L=GM>mS%;_ za4?)1fMC|8mUz$^r7>;H;FT~l7dw&gAt7<*(F;F`+HSK3c@enQY2o&(_m55ig;{?< z-tpDMG>1WfRVH?>DXd&{VQwBwNAzNE1chHCDQRzi$n@3fP^IqfA>S)%2_XIcuxumD zcH~+n?CB2Wmn$&|Nli(uoZDL?{7FbnqpSnN9VGmMU6P+bO-&)R?Q$J^8P6st?8PMS zEH{inSsez4wRL2#lWK9cO?-UOJzARRPsMGP;`A%q$S~v74du(*RQ*>5N&~vt_!By# zKGb7@;EOo#{9Lp}hE=v6>B+WbO{rpMU!tw9Q*%kQ`+MjaQ5SkQonUP%gDRw(%otPy z_tw-;%IL`?xKFTxt-{l39h+wlQ@WEIgb+x-`O{Q*sxz2+>W>+D}(Mow;y0xAs9czFIxlQ{$5owpmNKFBk-Cs>?IPr~~760eq_}>iP)3F9g zj)8==hH0>N)4ar54G`S+Lxn0kZ4z0mr8&{4Nm@4S8C<_^J2kl zHEbTECkm&L?X_ii0!<=a!LV02B4@`DvG|XGlhX?8=vUH|5m=-b<4+HWkcbE8xY79Df%kG!o6>@{-Pz4%LCiXN7Yfo4MnNlZ0D$x`AeYj9Q z1rNIMB5iFIjyi%)-Ov!q{6#G68fSQq^@K`yr)o_KL4%Fj6;*sig0iLa_W~eHL!r!5 zeTh#^?nvvyfNl zc?x#F+LJpaPJ(9Kj^g+zI?s~?mfC6xmeH{p&{T}8*pw+hGoKqt77cAR|4&7^I078? zlBIv$o>=*ubVa!hK*!@_8@NcG9SRfvOD8#?%arPlxL zb77Ash$Yo!1I@oHqINPUQGN^?OQ(#3kpt+H-=)KS_(lkAd35k0^794pa8rSl=wEp5 zdGR$D3{Na~7i*4#!yV3%YY;9%Yz7Vi^Rh!&ws`k`{atfW+NEaD_%VVSfL>v56;mf6 zc)saGEUiNYnf{BDUE>zf z2+C%C7xxuR$xL zRsw0>)bWZ2LVJe675piu~u^)l$6bqL?OBrjOEz%ePpKi!aDTVwLk6+`=;F?<_`E~!wR z&%rXUUb#ZQFH_?8`m+b-^A~|iz_So@GgNy1%z^s7+%9s`a*UYC`n!MLxn8S16vz88!9T{XdTNZ z?{YltO#s<|O)$Xnh%)r=-cX6+e9*<2J3R}RbcMlQd*V!%%O{n8(qrJ{PcMl64@Q>= zw_@uMsr(nu!i$RP30WupE-lo04!-5##GVcwi>n}?pSut~1oPx8M*6EQE_yEYA5B|1 z7BHo~8-RXv1>N;`<_-sP<3@@l6yJ>M7c|AZ!B_}lZXqih??#{GKk#vj$1fYmVnG%s zhU<{)xtAcl11}@bVDFms?K`lM)2=r=IY4Sp^v9Ml%~pB4Uu&&3c0jT3QSWMXCd`-W z02@U|znW#G{vtlLn#j$1>&Ul-`~ijF9wAsF``!cMo_ajNn|eXlHNSIe6F56K zShwc`*0`4sb?ppLuV5_HL-Y&|7YI>vG_6GKrmy!sh+UPP1MD-Qv2IQaSEAR*s4wVW``}EEe(MuG zA!~;o-k_JwFSO!AC~4d(^sCyiCiX2D7;mUeo7D2InipYZ>zPl^3cI8J2y~lfk1j!~ zIB#+eX|1NN1XiPu93-TF_+%8%Khx@Yf470?_45~8$0utyeY1JWQ8HWpK^WS-9**u* zMdBx8mZdSkt+FlIxLm4}@0N#+;EZ_l@rI9iX-`Js_0t>sIh%kNJ_XIU zdjHf|g6y#oCfO&IVoGz{;ZKtBRTGFpH+1%1q9C0}4R$`)jNJ}?HR&?*&0kONPhw1-;KxRQ?_1vtzDkDl)5 z{GSs7C%LjP&NV^0C2tgX=marHor&+5eS_wo0dy4oLcjBa*C#U&X{IS=@5{p1O>Z9# zF^o$}=mGHXUZR@-G)QWNs@e+8 zfVbUwNtq_)5At0yWC7j%{pzHiI|` z{kML^vRlD)T>f?HSDJFeq1_%+EoKpC56gdVeAVewA(82n$7Q?@+(Wmoht?L8v=IYY zUFhHa(1mX!PIfQ+<{vUTTaBz#kcA!NwbK|r8MrEkOLtXb9kV~O zUtFvVD{uXDdF5$~BdGV&v_Vg{)tF|GKR%>QvU6i(qGZOV<#*S7%jG#QnMyYvri8!* zekVK=)Jzib@l50zOw?Y! zI-`Xh`q)%xlLUDB9Tz*m{C+p4yrhzG42iqTd>uj@SE#X{Y5LDF(X=}DI04Wt0q1CV z?NMAV%j@%Q)lqjYk}`Ql0TBm4VHHu8PPCYeilU_EwGXn6#Y{q%jI7k7Cb=BxHH4nW zdkV&3W1KlMz91nRY5dypWlZVv23n+IT)+qUDZ$^@%KEu1F6&u`Cbq3oGVJ*75-7Db z#2=dv2Aabfd3zZZ|()RHy26_oDB6(X?QL z@_C)?-P%xx{uQYMgErlTb#v)s|pmlq+z}1SykTYq|s2;UKYH+2Em)te-0JT(HB_)DmA-$@n_!itn zXhDyTJN`6i@sRkcSQqol{!MsLbpFagpVG^#G0EgQfjB0T%vKs=M=r%j`8>-`cA{ET z^W;)rw>dB*EHYq9-RN@MC#33YWY>7+9MRCUcs45Bh|P_EkV-(yfvSedgupNRCew(T zL}I@~(@{xE%M?aNxis8HO;%Un9^J=*`z?A0q{v;lwwLleJQK;|1O+`;ybxEj*sCje zDBP!0*jp9^+j9Ql@?F5H3mvhy*KVjSKT5qJP(Cy;VR&mM%tmnp0SB>0 z+xZO#fe?8vx-bHA)9l#3$hdI3sQ}UIc$q6Mn07`54X+)b$d821WP?F{oR8K2e1CYr znNa6+xmGRiNv&*(kI^jyp>cjPLP9k&dLaK(+gP+a^*0%EZ$~@XWc4EHihG`SdLD;= z1+w*EcA#9UN04>PF_u)TLtmh?+zGS&SecrsAMHp+%cSou@Z3$<3%ter^q0!78Ygzw zB*VzWs%Ji;c6>3koqgB~qVo9U)OB=0J;VY-=(+hR_(AGdGQePZf!>kg9Gn_YSNi=a z`eWtKORPTl+`P{@nK*YGyHy#a+{I($8`)(X$nTVob1dlUbaaenvo>jp5QA`Jt?>ZS zKZyQO^2X+8JqHT3{b`-|n@JV>Pl49Zcl4Ez9=y^NR){K=p8!!Q)2oo~BjfYdr;=zK*|w*3Pb5SgYYHsyehB1C7FqIa8GyFi-yjhz$TS0)AEt47Q2j zL?~igs@)$sVPayAt{Ly%urL=TER5zbTYwYKIO&}*5t({G@w`&8U(Zaa-P4~yW!#fS z;G1^L)fuW2%lC2nAw@AAri;h8xBWX7f0Q%+L**a&m&)H4x^GIP3tq(h-|um7uSCWY zWZj8qkLoZY%5pCk_>82^MXW80Yirm(K{Bi1UNw+!$yB+%lf_c(!-60sBV0HTjBcon z-`|QgzH!k9JId{h6}PITY7e_9Cfc-RUapil7FTGpsgiyTm$8wn0PaT_q-mwap1ujJdfG$J#q(}!2IYQSozo6Yrdnrf-HDE+@pjY|J% z+^MtQ0w)N|%#DglyJqdOO%c4I(_Bzz#QPylEidG)Lkd~R0RkO4l2~bW$fFiT_H|^S zB&uJle+>9k4#*_TrXu%!CjgQ4qaU|%kpnmsL`S%%zJ5zJ&2s3HMO_Iei&LXIdk?7> z)fm zFS!(sw%EDvPo@8D+SJgO!5?#l9FNt?k}7{)1`pr-6!J2ct0pBeB9=QZsMQuDL)hQ56s{BPg~pd zmu(#XJd}`FzxO5~g6|L60pzNBJD66CD!SJ%E>-tAjPgtVxQpW&ZwHQKMk&4^UQxcYiNHxwx~vvPAi{b%$Lfdg!$%LDeiWR(X<3FY9v7SxDEhV8 zSVPZ{+vlN255{HQ9>~?zZWk^;GVrH@97Mj+n2a*r`xEUnP-N3DiCUD`x4R>N)0E$E zZ(4-RD!&#oAou)jzx>F(ZDILZ_!CmhT~aH=TY-0@3d3=&ZNF;l9!d*zFX1Si{A4a* z@XLr2%_4k!7i1{rH6r(^Y-}Pt{k(?H5!p@kH>Da zVh?EFo38*RFO=Q0eE-ecBC-=V6tkm{8Rd84!I~(moeEr+Ads5`XJ`7_8(R`%_kMrt zIp4FysrS~37`+>vax~S99#W-`PUCM!Q;&`4uk*O5jTeXNKE_b_a9iaMZDYnNCs#go z31B6N!d@UQ+hn(`@ja=jB`zVr(R%k=!fn>5o0o_!M#E49CxqY}T4j-uq%Y2jq{(MvFT(0=Z4yrYLnc6^Yn}?Ox=ln|^H7~WqIGFp#UI2c9 zYe4>4W9kW!()sel4PKu&RrbuU>uYa6-Vv&(jvv3>x5}oHnO!ppRqrXhEW^Dm`~crE z=?CiznUy-7^%0)-{_tm)E!lz!#e5V=TW2FLzwupri~IL$49Qm@$rl_v!ajFMPUO>b z{@%0j-QLMj;Zo=%>AZ~VO{KP>RWr^Wc|FBDm+dP>+Dn`X3A%r~sS30H@&Gk7s0u~X zDU9O2#|sBvMrxPdc}~E1)6UvHD<8gfL>*4=LTZnbta$^A)B%d+Em3VwzM$S{n_*Iv z_rb68G(_Ki0$ODIYkZYX;u7~GIifFrjxHt3VSoSrmyZ4SLV>9-@R6k)UmrJ5(j#u& z1;ZkcuUGF}*D;GFY@s#1{{E-c^%G)tCkA5)D!U^VA0zqRZxgph?(9|KDBHyP57YhW zzxBsr`k8IV(TVN$J%T>3uQ{8y6^q=$&ol7OeWg|_+pN@oxw9ii(-uUd79Og+|AE8oX zb%Hy!+HDcARP5!`FmG9{rVsLsBL&=Mr|f@cJ{O)+$0;rr^QdS9kt)VknHv87j|4^9 zuP3)6%6gAW;enrb3&`$-PcPfcT)Nk~w~TWZoHUl$x)cW+t8X$oaVD+r!dIJP{*BCM zM>?sM{&c9ALfEexhlLLFXa5NXHbD1{jnHC}+GgPGx4rYVC8{h|dT{@mEun`-(!BM6|6y2+;>+fjH&QCd&EN0!0UMPO%XnY+fSkT%!%)D zudd>lliM6B9P;rG0;!04Bu8>o(0YN2^~yUX!^Q4Ejd>YfB8DDOW-ep;Pu}sl$zR5` zGc^e;yBUqV>Yha3rjit?C4_xu##nS3LK-z9;}LA!cbQASS-tn5B8T31d)d>L7g31e z8^eWkB@}CAr14)Zk>h!y;4{;`XUMfk%${3C+QTTSb?I())@REtl0rU&WocINthCfG z80!5>IH6dKXm7GT{9_7dDt z5TSC!^a39*Xa7((d1%c1z4kE*8#QD#T$(4Ol;R^n#!u&pC_ueZU@{{N-NYrk3H3?c z_<;6OgdE_=1p`{t7DypqI_=;0k0+<`&wycECTj${HFt#Xy_oeP>M_zW(N=RL8x9Mk zC?Ozd{HkrypR!CQFd(;=!FsH$T+46U{?s-%`5T{h+B46ew}H*j)p)q{U?b5LUHi52 z*m^fU@~kI!LUqNz6*WO`eCpYMpIpsGbXTChZP$gEkB>>3{a43|-+&*N`fbPXEd!xN z%kMHapeskxSl ze?TB&QEUnZjo%_}Rs6y!+4k5s9~N`@EyEwlEBM&6Hz@yXy+bmqe||itRe>t~{G{lk zT(X_<0T6`A^fkT_F_A-kBz>9?(LbNWc}SxelEdLP5ajiMa&dHuqrNK5Me%NQX7mAd z*e^Zi*LZH-*{UMX3o&bRX6H+2cUJGjLe!z1+Kl<70`4tu--{?|##6vB{978!q`v>& zR$q(t61U_fh%(`-R`L7_U98xH%Tt#cv7(^^vK+hSYd(cGtOpQ?X-p(FShuUjjy@Bo z+Ne*s&4=PYEhpa<>=JVqaf=+1ZsG~D>5s1m?}?zK0-g2a)kpn;w#f9H43;Hoj$SUP#aDpRo$xS-PY1WvATum=&7FV@< zM7HjjIyUb_pD%R3qOU!d%V#6s3A=iBGkq+v-K&H2ZZ>mn_Q+^qYbWj&b;jP?>?~hn zU|Xenk9}+U_V2ePDkfmN)>0eU5t$Y9qZXS2Tgq|rMS8IFZ+dXK@miQ#?=kamGZ)8h zhFlzf{*)Jy>$G<2H|)3(_#@1qb?u88WSN5t z>9yZ_3kOFSR4+@$Dr9ugVnfA^)6X{_QQVDvrgaf!EIV*ne}9(!$J6#PRHIP)5s}i_mLXh!k_!CD z{PM?-EbCV_V&0K5vp7zt*}M-FcHaHcAGuuB^^>oZ(BZOw0*2#jW)w{KnG1z+#@#O= z!#UYQ!ckoL$z*3;LZ+!vD7HVNolid1fhLRI+KLT%=mKEaj|^K z64O7)xLvIYrvtNHT!$aojayPv*k`Q#mat_!-~Fkm9w#c|Sh$a!NUn%w_6~cW$`fm) zkC~dGxA6ZQse1);HIk1=7_CG%Oai-6Oisb{>2XP>WX2WjA!+YwUFPe# z;-+f7v*$k2spvbK)&!to$P^b_dP!^~m`>NBH^mv^!=Pe5CnrbWyN+c4U zU3?0Ze*0}Nw{g}oitgtYb ziaLjFiMF{iCFKm`NVv4uVRsUKlHylaw2xn#Da{CpBAxtZglJ<3FPUBZjKFeSr`BC9 z9>;7=eeCV(k&_Bx^ll7aj|wAJt<2P!6vz2QP}C&tpA}}sqNZ5Q&c*V?|JzFk?xUxU ztnY?|iE@pWe>@Ak!rPOTWLI<{=-aAsr9J-xewS~t!GrvzaDE%=My_>*p8QflwhfLN zaE`9@;``QTrcLK{({U4WICt+;!SRc#I`l%Jm7Z!;=GS32z^?nub470{Dg8|;3{X?5 zVN6cpSB6!a4YO$+X*;uG6|g0@PqDd*;UqmgUhKm>iv!yF7(w}jD*M`DX3##$;ZN)@ zXLLAY>e$`G=lk(sc`!}e4(+5&W_`XFg@hhUt2OD&t#pfoZnW<_-ZVU`=O0bz8df{& z%k~UU{#dDWrhONGbE$J&?WacD7~(`;N64w>9*Z42IRxUXGxFB%_ryKfE&5BzG}1?h zX$Tiu^nVjmceWF`A3qrCgdVgA8+}WO`qo%~As$H3gVGq-Pd z-Ri1(o~kC}q1F8N#8orJ`Xb8I5N$>3SOJz{R9r|vT5PH)A>@Gcdp;v@dq5L}h4?0F z`ZIl<2$tbCm8>wLTlnt-U=SZo*EM7ZV&xD1jm5viXQ^dOUrUe(>0d|ZwWYvb#D_$1 zP{RHb<<}#%UshW~q~fiSUf%%C;N!@C^Q%@6^z}d+2R3Z=9|@{jzWod3QHsK~|F=nu z|G#S3uV>)-zvAvtY`tyS2*==mmO)VSkG3Zv-%~d-LLLv-(_8wyOp_J*=TdXOSd=tJ@1Ij%`JB}8!lU$Qd8DGrJEY=Iq z$^n)4luHUco5OJGtKN87|LY@-w;?2JGDd6R6zG-m(j>YH64-T6y=a!zcrT^hCrlT6 zFRP4}I+Hi`(5OUIb8&alquNV(vr-s!k%K zu~B5XRuO^-<1OKxWWQX|@uIk+_vQRU$S=dIbm}?awiXa?)p*_EG&}PFK7Qu8!G*??lA8cE8_R)XS1eNwFNx%1OL1O2K8iP{{C=tvd0}VNy z7G>vlNW+I4R@BI^1wS3aFotkLHx602|zQlKP-kc% zFk{j$U|o`_9f>}aQt&gSsY5$N+Utkx=)e&M$Jq70m-fU|wPTP=p{3B@eWWs7-@>B# zP?SIwO;fDe5~@jYwN;|p^64A#kT7^kHYKNlfsS=O7=L&xUjC-={XV+d!8(Dh9K+S# z>qADWalW4_2myX3!7^u$(f8UqVR2VoYq!a@Si)A)avj0q){fEI#o?1!G0YefA zV=3br=dLUx2&O$4Yl|i$-?T)uIlw?@@N`ER242D;zW)O@-G^tYn|B@)B9hF(N#w~prY=xu) z=9RA!M;0+JW9E9@PU`lRcF0lFB`2gpR4GV%bLIHHp4fWLy|es_xEQBg%k0 zzjM*~V3*5KG6cV@BTPQL0ipx<{eJo*iWV9rwQtI$EPwx9piM5H|>;gjcDZ= zau)d`QSSmO7|1Bo-=oDE}isElIIZWn?kQ zkg9CA91pSZ!Z+Kt)}Y9DmDa-#LubIg8aJ^H|4gOce?}1S+fdb0g0Ec6*VZWw`>%Vi z|1-)mY2N0L-ar#+L(D*S{9)@%9Ms8PFV&Z%rS&W6D$@YX9>IR4V99EWiA| zn)dY`M*_WW_0W93hzfW)X^iA<{Ke#gUM5Sj}#yubhJ| zkDHqKAWeL^;O_^b@--|=YmNVuuA0HwuSWd25E9Kxnu_;`hnO;mnfDopzOA>U%9J&1 zrQlduwRK5Zhi}S9mSZ$YAwT8!nw1j#l){-sfle6w-jjYuw1Pc^X+ror@-8w*JwAlI zgv6#D>yG;e_JA<$<6{TeRu<0v@#{TELYFiNuHzRY4Fb{(9~DGB*Lka2bv`$S@WFYF zBSEq1oPf&#SA#AWgJlVy%JH!_GR2JIs0vai_iKhnhbh923-$;rgawKMo1P25@NffBU>mkmgVR9O;rM8c(mf$R?o$fr z9@ygklzJ~!b&W>3^Ke77PnBPQ@-;r3Gdp24{YwEska6+S`iOkmg%PQtnt#Mf^jEgVU!mgkX zQziU<@Zb_%c?4|rpP*_6Bxt7q6cRy%HgK+5QWr-y=0vsxL1mu+pPm0-q0;dD4D%pZ@PsvHJf%+>8Icq<`X@e=GTG zx73IRUT6QcX;{2|@n172`0r%E)bPq$rx|7$Dh6qOiq3yFz@1-xrVwb-F?ELdhN=$# zTU;f8)&MEmuJ`S0G|?Ova35-}{3CBM{Is{t!YdYAgKJ@+s_l2K{gLtPW<*VOYLoZ0 zGEztbRfF6y!2Md$h2yR1J^@hR+J#wN%?RhtuY3ugvhIBft7}=OdR+ zD8|oiW$%pPHS67w%;2F6)=i}G#8o^_-GA93CS`V3&)T7u7pTj>&qZc}PUUW&%$si1 zSyR{PeLGcQdq64|RqfV^;o)gwi1&`_X@l_(Zd|@HCi#7U{xyvzR!}G1(B6+-QXk#V z4IBdTOdrMK%?np4p$s&0I_6+sEHM&XO=jZjLfv2r;o-g0O%}v7sVrg3c0!5fvd#p5 zSf|^o#f09u*b1?xusGiW*7N6)X@kOBv+YKc;74DQq|?R_zgw@Y4bi(4O3v21@5R1_ z!$$Q1TIE_RFd+6%H68PPnYd8?I@zE3;fXb&YYD|B;syKyTU}Db2f_0>`Ql$~}#0mbei^#p2NJc022m ztQUFn(q9dTu~K?=7KQn9mwuFR$l;$ArL1`lrLjb0gU_nOGAsAZ-u-Ge!7vuknzrHb zeLAKGc~E%uo1&DKgcMG_gfoF!0Y0B9VSrfyqz)aaj`6dojlpcUqVl=Cyry%WoIyp+ ztyQAfC$^T!O-x-lC?-PbTCu24m9llTh_Wf9^x`T~X*PH<~%zz3*U%$Sa9B) zO=4U=o~5fy^Yxo6rki-coCDi!<7y6cag_1n`C^C8VUdcfFhqd_s(=hHB_9rAlSiMrMOyk*tOD4;88+?SZoY&Vtxq5OCkgF+$0P0T-P# zG}fciVzqLvXZPdH+uTZr|4fgzP)N@1Zw!}R8?98VsDsCC|4?G(frCtYrK^=vd?w(2LOoa@ zX%D^jYg#pEJl~x$mxo5_@}G~yDt7t~rtIq(;~$@09>0SyQ;W&hxOn=Z_Q}e_NE!KR ze8{Zv>?&Z^??C`Sp{O0VVz z6x0{w|55BvP~{x|;ySNK{~zW~koMT?G2@h7X0u`>v&+z-;`m~-6Ur4Zlq8w}nXUvM z-nhQlT8;-Hjf4dFo>84yG|RhX)}c(Wv9DeC>}85le%TQSEJF>@x43Weis11{Sy^9J zc6w(|u(ERN$kNm8hl9L1+GxPCDEr_B9%b3XTT3StKy z<%Jzl3^P4SPQpFr+A`hO-F*-PF=*T_B_jS?04SV-kCES43bP$ZY3Vkl7zJT{4e3!% z%y;3izEZ)m1~kEL6cM*Q(NM9v$Jg{GWG3uMgydrsEUsrwv61N*7Wg|CaM>D{J*1HL zKPztwHfGB>;Z#{#saXhn3>{a~Q3=oVa+k1y{y{ib%E$bLW9Aa3>{8}&FdhUNDwD%8 zbd6=$AV1Mu*142@0k{_7{U`&K%6$LU3$cPFo6j$!*6 z*SO(1FI)_S^$?M)HY_T#tWVz)QZ+DU~am=KMk88wm7mv-bCb>2B`A@pZbdpWxE~ z+3TagY9lFFn$MID9WMf%C9U!mTe?(Iv3`hXA&XK&mKPia;9SlW{0>>#lE{@ywc4ah z4)@2E)A%*E1_Ytyu9K>n) zC1)kSwZ}BC5Q&G>7Z{??E4@cSc@FE4a;lQEQ}x*TZa}#5 zcEjxv6Ayg{Dg(R^rwRmNQxVU8sebJjs-mJwE7FEX4DR6%5qMTce>PAwdk&z+!m52U zHu0ByGH7i6>ems%2!hK`7!2(A?I7HzM4rCcec6;w{@oWnu?|@7EyB-u*VaXo2ld>p zRlBIYblI48H7vAw8xzO!DbDN>Vr~eKOUj5I%L4P%yb84#Bx9dyZW;H|@^Wsig^-~9 zi4usMLf;E9k$?I|OiU_M6ar>f?&XL|=f7v)L_ZqNpmvsr*Mgt7iL-UjxwWATN$lH0 zTDYWG|C0w$UCX>zZHb@XYLaBHe%ht!mC6dZVQ5nr0k0NcoRusho#;^avw{7>5kG&6 zx8sy~T}$OCBfQ_1nO}T7Q%u)%dL$T0@+}1QlJmVaozJ}a6?!!Bg9O^!GNmj_?>z+H zR0vb>rbE<1q!h4)=W7%64anCwl~K~h|2CEv6qPq!*vdygnHR9FU^$tm9!*vYt=*KIDGCXt~Y5>E!+eoG#6qZz^T^aD8 z%l)lPGr!R|PB;#CX(WooCjQ3rL}KAoR-nhgae>iHcWidZ58GBstolz0udi4OrBiiA2zLkOq!l}X>xUC*Bf z99jSz{n|aX9aZIx4>C=KYm-+Uq2v8Dj(T+m(hamMSp4TYjv!1s%w|hq)~I2BRYMcY z7J|gw?TvR_PiDO^sVZh(uJ-$`JCS$XcqoM?NcU0U3S6UPz5MXXdWy@slXY~0&xs8o zf9V@n21_Gvola(X*~l(Ch@VmmT*Ta3s><4v#_0BBrW!BYO!kSL8KTZ8(L7B_qDp;h|?(8)Le({`Q+tx z@a4(xnZa`8I^{Nz;4fT_?zq!?>nw$;^QMx@1YH*bMflG1oCL#cI+OFt5_iS3kTOsC z8LP*Je?4UnFqC zG`Jv{Tr+*Z>J!@g(p+M`aaN!X#2! ziCCU*HF>x$>_;JxA)9hWaHivtBe%#Th-H_a&%negOX8P^_K8Biw4_;z@0ET3a6y9d zI&Ojz1HzENGzy#u9Q=h|)!Y*wqvE7xNmSqS2|VcgX&pT@BgcC8W|-(eTcmCvgt-A}2oE8<#m(Ec#8WRb zS7ib>ixPg%AHZ*Me@JP(tvo5*s4r8u)9GkwZFX~U_Z?hcv*;f>E88p zjmdJyY9f}r&Rh}Twb1+68rq~QSIstqyNDApe?MJDwG1`DUv6UWLk;D$288|XA*T2M zR8>wa5lKfu_ljTj`vsZbena-IIwku;?sEITfEA>!jLCpInwlotCjO@p)^6m7oHNP% zICtu+#&*3I{FhTZRdC|#W2M}z0gh9_wgiHDD;+OLl&is856cpMdO8;t1fdfVeN%QX z7y`B_zk!=uP=6V-d)oVRCtKt9{MTp1-i=z|#!W!nul?SsLkvxd<@dqtw^6joVuf2! z$1`^RM*%>tUV7g}L`e>wFIM^1%@rUmW zRxTBKvEnesC3Wj|oy}n@rE@5S8i0RZVOENm#*MuHLS$CBBmlJ#miP||Ni-YC1zCIx zIAFC9fhvSY=zolLmd{RaZSqK52d$LRRD2HL7Q<$?xs$WrTy<-|oze$(HS^6<(XUXW z9u;Sc0ZZZ`uY=%n6(W)>B3h%QfBRmV`B{x>P`iM<-jAr&dMub99a$@j)Lgc#)LuAE zInG+TSUJV>Y7~F7-E77)-B=NHtAg}`(Wo2VKRo62VN>i!o6Cni zAJ4`6JHRHG_=-pNeteI1?*jDrnF1kZayt0z(@d)UIt7DsX+A(-8k#EM)Ft-}FFwco zgY8e46E>EaOUB(F)7SNQM$+5&mM=A5zge_p)fTFZ+fExcB=#i=|32VILmWe z`=zJjoNx3?eEy%YF}V^NTjU|)P~=ru=bX@t$IuxU%OTvB`})e1qZkGNDWQc za3hb_=+s;{g!CpBF0&byW2l88$tNPZBshElp#Y(v_4FKN+KeV?qP(xTjsfV_D#eRG z+5%=oMSa17D*P=$tFbA5Gm`l!IsF5@=|9al+eBipm`Gf*uc#p*##;i0FlM-CiDgN@ zibG4(@j2rKH+du65qM*ZB=FMUhs$RzXSHS>NS00_zPAtjK}C){$)mmvz^(*uz32*Y zmNplsk(e4*bm&!e+-_v>G}A$40bjxIwZ;b`0&gPC>DxF_bu|gI&zSy;%hK5$U<;Z&$&}VDCc|~ zO3`%wq$CY=Kk;l)ybrIopPCXsmvKd=Lbe6-ilKV6yUTHn?{na7SIO~?3l{@mf^qgu z-k03_aq7Y*FY^+2Q?sxwwb}*1#w|x~3sflS!W74uH&DRC$SR&aIMmkuezM6N%tS*j zx6X?j#$ns>M}VKJKvSo~cXYPQNbe-109`hQY1T5aaNr?|yBsw}E*llF!MENNEO*oB zq?}GG@<(!3bk0Oz6S43HZcUo;q4C+u;kX9f^?-tQy%oe8-W^cfo6$N=Q}i7q{q6mz z3HRG_R=d%b_hF<$x_h_EUEY>45$DehMV8vG5 zT=ZrzKscW8jV9ua8b@WNafp};S&6BJghUtu0)pGgGF}I>Gknfc$lcy#UQ|>RzW&e8 zBDa0o6vE-iy1S>6w$z@uglQv_lka7}__VS3dd|C%EbTA2)-D`ec^YLo;MB~3LspK{ zn0CJ*`LVuv6>3~d7AGz^6a*)KxkU34yf=f@qG*~8-)wSQ#W>DX`i@9?B{0x%$@272 zFZB@(*^$0`i-zh^BOb;^iH`URx@rtiDhJ)O=XxUg48!~OiH$5Mi&I7Rt@@ ztcCINbue>0cf~x0yzEu^`Q=b#;@yt%VAui=WNmG0gE-`CbtW$tCoiw}pD4Gef*KsJ zfUg7H$c$VNlOUm&ipG=V;cc@lAMt}$g4nNhHeOy{-#ufIRqD2{gW8*L(U7|Nk-EQ> zi4jh-TK8MjFJ{Pr6bNl?5(;Wey0i0UyJv-9fp)NEdb+l!hngtm{N&BH zKV7E)H%)IX?n*y+G1|w|)6>JlBIOOPReh;aKDPjivToaxUl#Q_WXl$;e?DFFe6n4hUudqOV_C}|TDM()IKhje zRi|i~`eqqQ_zQ8BnS)%w*V$vC$?GQCg2=aR$F+wLe!smQ0fWqy8_+iTtg=q-D+id0 zcq_`oU&>tU?Ii<~OhBp2+LM>xN7Y(a@Y>9qAdWV6MQRLDX5bw}Yv_QKH5F)s!V#NB zO#fvpyz^feRYHYpuxZmhVgEtoo~|h0#(mGJX;7rP>(jnH7}hB0h;mb*@ZFkH?pNzo z-Tc-pc81Ta{4MNB1VUNCzteAABEB3HO`B*FC~^N4I&ICd)Ltf4A_;T; z%Qgf4z}(bTs2szHZM{Tz)RZO60C1`&N?-uwLc`Os0tv}`TaE@r;AYeBY@7UXAkDC) zHRSJVlLMa&9`cW5LAmfB@k!wQ#f({*!%4f!8dO?18{dsEge9qb&k zQ=$0yXfLGZ#TsBObvH|sYZcR^|I;f~aN-@~*I#qEb_$ileGPjIaNZ7Oh~m9@$z=VS zLyzLmK~%yv7QbiNnAYD9%KyFUbJNzi+T!QnOL)E1cQ#SXTmA8;f(u}|ZM?q^37kD# z0D(aH!h?e~$cI;2T{knxU{|lP1=Cgmjh>5F)%e={&m`+-j4TwuxSu|LlsO|o5h`0L znJul?`bLv$np*kw^K!E}=BngMXy_YSQ~Hw(>XS@mR@ok~##M`Zaj3*o9NSNG=Oxnb zEg`J0ahBIcwRMt*^kLax0wjC8>@!vmUbh>ErJ~`nEg* zJ&ya!jY)&du~@iWg9@#Z?bz$RBMq#mE2b11dpU45%K@-J&qL zk3m#X>HcV#P6@4H^XmWdN~tx$sqO#2+}|F&m=)z2#WC>UtFDIfZ>BI=PpHEheAfn2 z+`{37`7QzuLzKerkNZnuoc5+bJkP!a@sA!J_ZI-O8z` z7l8+m1q#IfD&y87jgJcS%zR#>ThQlx{q3ZfxE0|JaVq%jNtHYW+@j#GR&n_f`;6D1 zzQ3q_Rmco+6gUFhI78Jkgx8alro|_5uuv%^v=+SG;)66SYyma>nN}Txl01atJ;Sl~$`eOdqZZknE z;X!0d6NcUXt}ZMutK5XIr7DQ_*@6yMUdm=I+w}0k<0z`bG#}rfiSQ1u zYEU184ogB9(fatzbc8+&H%^*=Btm=11YJ#-FGWwgA;3e?h|l>-LxU6aka6Tnneo{_ zuT9}h1RLNjx84u}tjXN3o)DK!$pegy>i_>qFyLHpt+~2-xbrIj|vi(f7f8xaQ3hzLHk>O#ZC>Ez~vUB|^*SI?K)0Lx%@pZo_%0-~M*95OGFJn|PDWfv~KZ!TFsx9dF(R3)f1sn+y=kgBnc!p6G zY4e{lTOBW(tXhM+NC~ZIP`rL3xcmA(pROA(HAuk?9n^mquJK$UTadzrc(v*M0sPX< z>8oZ1Y_}eTWjus#On<}#>C{S{fZNH`$?vF17`ppnd0xVVfeg74ZIgSM%~23&_B)}k ze%)U~TGCD!5^P|pUT2t_!TayDa|3g9&(vdV~D=-*fuSJrXeai*{3Ko!LRsTw6u^f z+7WhsXf9u3zJ<98VOykvxS#6p?C_)@Eeu{8dDZ#cZf@uWnk%6#x&T`&)w8qlA-jms zr}zeG=&A&X^*N+D{!i|Wu^W_fgAsGlGXw>a5+{=KiYbLnLeUm!-@g-w8ZI_eeCCIQ z7bu-Am}PkY8g3xK&wG!5e&V4T`P{m}hPNA&sUtf!5g`BeNr?)nAUKz*ON%+=YSU$$ zCOZC5V;AZ&Q#@rHliG3y!OpQUmA7?B!A49;51!yhC1Of`lrJzDRRtB7p6u%nPOw zghPDd0W&~it|Ur$6Hum96SP1dcjaS?uynQ5%N`YjE@ z*Dd>bcRR?1M6J2Y_B(+8o%Xw*cGdN6dc}!V0#4>peui-_ESFqV4E^XY<1sH=t$+FN z+h44<@EtrcfV>v;{Bq|@GIK=7iLh+4fpxE!(d6eNf#+R7Y&hUXyQYKqd#|ruBTc~w z{SNM_&w#vCsJ%P#2^ZYwzRGO+g0!RxFivz5(oqupM6*vXvb_m(F~#d(ltB_dvZFyq z*Lk@ItYL_b__S3N-rm&Fic>+wo}V4M-A_@8{Ln8X{F3SPZZb@0OG0WEBQI+=gp^K(jJ`anKcBzcG`nFWyCxk28qsuOwET zD&v%Qk2G*maFm;K@!hcE)x{Pj{DOdt%{Azlq>$t4Jd#1RYP!o5c5c8Ffbf1SPS&CO z_KYK|x^W?=gHl=Zb~${RIbUH2Th>CXO?;d0WWCpwM51#ERR!6VPevk$Pu;wa?*<9l5S z5^g1Q25~l09|Giak2r0Q0HX{CY5Jd;efV=_GKiZ8@obm^C`VUE!^6LR?S!gUKSoAp zx!B<%UwMA(ZZ%TWffcW!LFc<4-@j?)^CUzSe@6pLp>J)YvY#k-?pPqa%jF|JUrBIS zy{;$2Kr*!b$ldEl4z~D%0JSs1cdW;DPnJ!-qWp*Qt1Ubp417ITq}A1eBV8eZ->GG~7)s1&Yg9qSlCHWgsTt4=OU!?h9-l!J}<tDvgeZ7`Cd-_x2#{#su0QbMNTo=rBy+oUb+E&$5r2wfD_Kp~drH z*5jblr-pe6ti96(Kd*uM-s7dl2bLp+syWlX*m5rK;p@DV;Tgj)zdMBfh@H-*P{IY? z-sB$M9J@{Dw8%?>UIHiziT`E%0u-3o?0*y(PbN)HxvfzdxVM!*;|bBG+2rNqZf-C# zeRkBOcw_A=3^b3nGQQ2j9Pva?n{$wcQSmzL@Aut>9CK#Q+gjx*RpAux9_garVRAj>IxUR3#{iACp-?xg!iKxUmfe-6rfq6+9SK=oC z;{*i|YpRg}e%;%D277dK42%?0)euntqZua2e%?KukfCPd5+5&bjm>VC7sem=P1&h1 zBfL;7R&9}G%#NjFQqqj{tSn_XU3!fWqe(B_l)dRTLqkD)C=(n=uw2I@grW7v+sm4TgNaWu^O3!70N>AlI}py$_XA~0tb!&% zZcKvgY#3)@5Kq+Pdw5gr@89RDbY1*DxtkjIJS9J4`Wege&MOoP-OE1`cTkck9Z$vv zefSR3_AIFLjfkHGY9U}uRr*-&?@`^Eb;ZjwV?lDI+JKx<;q*Rdv`EnhP2R!HQyX>0 z%!Cm`*4u`*NRS7~^Ne0!JcQf(5co62^;7>dS=h~Awbv8LkJR**8FU%0-;GHTT<Ts*$G zxUf~1Ozx?Ts=w|tNO?q;s0@;ZMlXs(_nGX;zTkl8E_cZ+eCi~lqFeY&9#d&#jS+zU zll@8#)EjS>IY)xfMtST^zDCt6&r#|<2 z@586&q^{1%eJc!R)Lson+$h?cB(_isjil|>7-tjfgXsn_fqdcx7{R0*_M~8`Rx7&% z6sr>_9_E`77wcAP79Sih9pb*YTHXnvejgT*grJTvmzbajJJ}pQRHIAGEzGvatI1ZB z2hxKUkz0}(dT72T^k3O_36Z)USo;I`|9A?5zGwQP(gEn8FN+Q_MGpirHgA3r?f1L3 zifB%AND99C)1s)OK%UlFEX1hqd_Cz06NM|2`dbwv?=S8Z1<8;V@tD{LbMzs@43fYdsQ*N%Ai$JT>=Vga@d$_H zeEi3T+jwD?eutyXm3?P<`EhjgOog~I<=Wa>m*d4*t%{EXs4{1#@3o!>n53|{VW+-w zxOXqW#zJ2YS()Cjle*qR2F`ST><2g}>;}q+ySUT#3Smw3?Dg*tHF430RjVR~#d6ul zXPj$IenKGiK@Z3SWFa2)`@fVTL9z%`Z>7#3Z`*z$riK2`>>c<%B)NA0l!ew+-DVYInPR{*>3S2E0|(5!YV4HXqH?fyD#m zVR!&K5hV@v)5w#W1lLKq>q|*UHR3_N?K1j1o%NhQ#Qy5O1$skT4IG5se*j?2csF&a zpzE61GJwT+7#|HLU7~*7vp>>U=p{L*8O-MA3}G+F_j1@640>v}SxUx7dmCWa?(uTm z_-EyhpQE?8qpR!W;gx0mt7`i%!l?^Rl+16&$RVgzH7Bs5A!UxZG`Um)NJ7d2cAx{yG)(`6?9URhnvSG`@>qQQ*P??!GHLCe zgbn2coKiZ-SiT|ON8FjywS0uF%a&413LHZHadmlX-nDh5y~#Q~D}$WZ!|~<0RsZGw z`(J+dzn7Okr}tw;X-3spk{cU7R_ZKJerRgfdxzH--#s9AKFZd|PP^xqv)#>d%JDVR zMmfyP%nTU&Se$HzkgOCcQz^8MK=`G0;c#IF!-c_2(Q2~aoFl&d0~BzLwIAw zyaR}n2y;$wyAghBSQnSrJ~agz_&iP`@)vtQYGi~pC86V_$NIk4V-4Pg`}$$s&55ykVD2$ z-iDlb7fb!nXmWbE1A?0LiP8Xu(lC$fOe(satw4WdZD(U=lQ?XIFx3`5bIK$psquqx z|2=HAmdquzhMp{9rxDVOi?s>iprfLjvMZ1-MH2nO38#W(DXLJcF4i0X zFI)2M*E`?;cwdY*u6pctZT2I`qsK^+0CAP223?5-{F0`M(Qk)yRVT-KKxl7c604Gk z22Jv9wB>%EPkt~Xl84iH9`bDOGU{Edf4K_dmFG%BpHuM)H}tIX=GC{W(F$2d>h)b@ zCCxGlDM_1bH8d>3lmW3LC zAiU6nzEOTQ0=5V0ivAvK@CLa8Yc*%M2xTH+7%@U**0ImUcf0uP#nnYBW;X`_l;l{- zkgJk7KeCWWV8n|$JUsOBYE7`LCyL;xnP#k~V%7jpzHDuj3PFNGZ{>AhOV=VC&MB_% z-uU$IJ98H(MJzJn$K>a4DBwg}3N~tIX~7w&p8Az;D6O#RyD!YQ(?&^2zBf0IKWzu< zFh5s7QQ%6Ci5<557*YsZR)Nq#QRN7#(ORTI@iC#JWCMnUL$2zC%o%E$ExI9yctJJH z!SnZnW*YVqNrV>!PH5|}WmsVU<%W#ER0T{-eAs5|=HyhXR~7a7y)Gz#k_=IZNtf9)09ppTxd_Ac?&@-l)jXk})ktZKAvgQrKv+b}h z<`+TCFuR3;_+~1jLJR&jU>JA^n^eMv5{IuzpXXF|#ODqQS>uxD+*CK3gv+#6QIXQ* zWJmJg{Q>M@kF#fAj!nJc;L{wSptEc=LGIkTBK%|i5UFd{!cB5N0@--9uH3P?POmD? zXnDSP&QkRUxkk0*3vLKHQ{uj#A(eL5(-TFRP}Xg{F?tw|`|wO?{-15rAa2Iwp~_#_ z#6g$4fY0u|Neswo1rStw@^{{R?uw6(SFS0O6{#SGQj5FI@_+97bZ_UEI+g8Ur013O z!!4Pp=mDz09CwlCXH|Y)zBUR}t;nAfWuurVGH3Z%2YP!MqPZP(^eB(iXF;x*oD0XE zT^e%y5Zm>UM-0MmdxSG~5no!^cYT}W{l=p_lj(XBL(ZruBJUH366nw%j`@czCk5XD z%#e2}1AT#Ud+L{`kC&H|l~t`;nW9Zs&4BWNP(YJTodSKzeP6CLMybP3V@HqP-q?}6 zRlvRYQZ(&x>7K<@%5#unDaEnaF#m1~q-USF7yj%8kfXS=wUg8U zV2%&aVC3P`8l|D{>VIqE*i3TNcCIVBkCV9+wLNh&=l)2HGKkogs(qkD9{0_5e=wB} zA^uyW{@xszRTkzF0VpRyUCx8KV9&&&-}>-{DDZyi^i{%wre|BYo`R|MorV%vnXwM3GdY|&?np!UB2pb^dl zPi>UX=`b}pIS9-XMTt5KunD75xXm;NfTe6|M?g-A^#~96ExK_79E+kG56w~4>^;BK zVFr}a*_A2G11p-dv-j@U#kNw(yLZ&M#1RcPZrm#$E!6JwmYnPYdY+;L7}TprDy|%x zb=Gu0Yu3M#7*A(0{tm)G<#Eb&EID0cjO(>%-Kpz)-n@Hiw$Y4Bf1g#UID)TtLhfx` z;X*eY^x@)q`02?GRm&{@hSQk;;_d9^p9kZ&);qI2V?6pfRI}(uwl7`kQfq`)qz})@ zgOZ*x?8r5owxEQ@Opig2zcCCVvLp9$G2az-LoEbu!Mop#`siME?D_L(w20pSeyRKE zYBfmV$(D5V|*j-oJ(fAuKNRe%EV z(X9`^4xt;Wd#kc|K}Z4^&RU@GLXRmh>F*y|l( zGoK_@BAH4_oVfV6w7}9$y-*)Cb2!g}Ce15(zgQ|}9OP}s60ohRR-U?gQY3mP8a(1f zr!?06eq_*t?0Q)K;@T~=spJaUee|L*2}zqs)f32WvWzWl-K_-3;kU=0wh_*_S@A{m z+QXEbDv-Sd5~@0-h3_d@2Q6b60X(ZKxSC1j2c{|Kps*4U8q4z7!7F)3S)t=HyYIYw zEOge1B+TopaD-n&;k;D*UiGX*3a5MGFoCg+sBppUo<^dt7L1H1rQG=I%3(jM|Lrwl zC6%biTpS%8kc5Cu$7KxSUec8MsZ*1@^68Jkq!6`1r|y;jy=ZfH6M)uA$-M=RPVaK~34`psvBeg|o8=W1gDw zxt6L*o$Y4W>MeJEp+SNZY$EMXzmHh-F9z+~J6_OspOd-J>Xzc~5de^@*U+cG)`mVZ zR7#calT;as9kG(W_$Z@vYX0Z%d#{<)Ko7Zu@z6JO_It$&EdUaYc2b`hB&0&^^U*{E zAGZzSkfW#81UtmQ3USL=^GoY29c4>vYi*;On4MVUOhZO!_QLU1aj~ycF?BFwNw)(L zuK!Q=Ne2Fz;GJ(b#EC90Qbk4vZr>QkhXTcWvu8wi_KXKwqxz8B?Blz?-L(244@@un zWHOcq=fOc{{t>T;xU}IxrYh!~GCFX!sk^(88r8K1{^9ORi ztAF;sXu#*{Q-D9h)>jA@zO0pns+y2bw-uRFgnAt+dVDKh*)}6X_q1_(D7-pCxV;JX z?pK`CrLz5KtkuW!PMOGAdy1Q8e+qIZfBWkn?r8GXK_4$QgDgbY(AYSLgWwRnw6*_eX9>%==#hChh7!4J!g@Sh3Ht#<%ySTN|+5UOcpL@Gj zmOB_!b&i{Vy;(I`_9(S(FzWlj*k%_!J~0vbc{CScuZ8@eI?vgDFkQk)_ZT(n=;`af z!$J0DrnBgF)wU*ph$fJUH1&CJR0Loa^R=fXe%auBTCdC|(0{ZG*9Spl9|2gWz&IB} z>kEhB`a<$8vXb;=NdtMfnFV~7DRJ7{M;0mk>`nnho~e*x|{rLqAg*pYgr*<5II8;k^RPJ^9g#R`4(E; zcPMp$sSWkbirzRK34lL4k>n_>SR(BU{!lfCsC=x}Mojt|!EdEG73>RGWh3Nim?Ihg zU#=l`SH)C)29+@glT+#+QLs-R_ZY)bC_Sk7zY;mQ;VB|5gwZyMx#RE9VVNani5Pi-&|FF=@n_Fwzad-Ypzjd zNk#~2-$V>J`2AiO0Xf7XT)h#l6Ox^^7ZE@QXAoUI|8Q9(P;!p?nm|fnx3!_UPSSVI zdljAp0x~yWF}_&p*F^jCmH3SV zyShXa!^DfkWdY14%bDZmpg`SdH@?$cURA@-=!bA7@iPc<-{D%sRQmb_7&~acmdH?G zU64C~gNqrE!+G}^sNpjNZvnw!Tw`msJ`Qu5KUP@5_<@#;GI3J#4n97jccKD+2M zM}2=eIe8Wj3R|&FCc5|2kc=h3X$`Ucl}7+QKrO{@%Afr@J^?M!-r4B_zsdvA15D z4t6$}%pHte5mqOLiM50H0V!BW&>C=LT)Uv?7G-{4z|sAB+FP^GkL~)Ph~*k7w*5&* zkM#CdoFp$FLGdbSBlv8MkmH#|P$m?x(GeUV#plZL=-U09XbgBLOWNOsaVsn0J|4QZ zdJ~%Qno7PWisG0{)t)H3^~rYf_5IP@Y^bRws;=^W4@2_I#?B6lgRtL0k`g(!lwG41 zSs1tF(+9L;G=Ck|NkUY>O$}5?W7hiVzkHV+qn+iUuT``E*|*vV>!CqEW2cHgiy#y8E{(S9WMXiDT(3`;V@+2Y~#q~C^R{m0+`x_rHf|+ zspBT$iLbdzBH6newH!0ET>zjxnWpQlf?i=15OXVS8=8-vKAem)m>^eJ?PxVmEi`SG zFNz()^w-(otHlN`EvVL9w89$7ZpahaQWOTr3w4qd`lOZ$PNuo;@Fg7+pLfD+fEwV% zdI~V40r+(0j_+sgChSbZM~_0QL%d7fv>=Pj3F^&k9fuXa8Lta(w;zFb(75jO} zeOW(T+G#`>$da}&Gtc0F#e?~ZGdsWdw-aoVx1X^EcR<~85xn?NsUu8byRrTw4>W%J z@X*%(niTg6e|v3kD~~q3;MhI=Q!BK#zmiij@4pryur3lsI$exBV^mp?@q zv*mlN@SXr=%~Fi(eZ637S!qn)nM*D%IVsmu2BT!)LoO{i5CzbiF{h4rt$hZV8_&nt z+B}}Hk-+x1Y933oO74bKue$Cw8;Dth^^|6+Zz>M@iLcbnk~nm^gE-GJ$0?lr@jWa; zMTCf=9u5nL!rq)U*Bt25UzI|yWPz<$$5%EgCandqaJ8($$Lx)uaG zC1LX=u+Q`XbFte`g%sZyYix+r7)DFHUH5Q|UWKY|7-J`+#@^O!hwJ*Vnp#HY}l6k~`2R z*`#@;v$4k8S{+Kw_WBBgzNZhiKK8iInzl7)tkFgzV5Gp2#XRbi*541Ykm!qv(AxsI zAA4u^iD!1z+rXPviRXAeVe?0R*H|o8b+Pbk_2V(Xs8MlWx{N_Ks)YH`Yb?@Pv+XUeZSWb;tu8gZ1$5O!!eVC081QUXJ`uJ3Y^tOe` zhIB4{f)&(q#J$16UygwjRzgbpy?p|x3In1R)c^Kuw6*;8id;eYuvkt%_W@Z}O>J$2 z+`&cb*Qt&z+7EPr!5a_}e~9_%}dQ2i7<3hiwiS8yVH6=*oR)3L%*0-F;@9?@eP9OOB`1Ly%gwe^HwNNnB+Np`tS*y6h%>B(2M8F(S4+^Kvl` zLYa#w$9D)L`;*tb6S7I_31i0Dp7$o?1_#S1s#0a7Wn>&^EpYb<4uDD1VW9XoTs)Ya zqnVu=FAX_=fik$kPOw!hPU*Xqxr?l~L7meVz1?%U;p(!bp@yhlO2x0cLlRgbZobZvuACm&G z^Q8V&!x(cD1uJNLz*iFRr94z+`}ag~@RAG3vpQ-oO4h%t=1;p;moEX4y8x?*C|KN@ z4*VT2QLag%6}i&z-Dm9qZOGb2ll<}>F|`wly6%N*`GLmp;*5s9%Y)Y4zVRvTLt3Ls+WN+ zHvChYYvUJkPrZ0V&WHPNxqLST2cA4|amlJd-#=e#O^)tN>Q zWsHJ-jfCBiUqs|DiXLn|;dIT~XL1BQ+J65G3`Vz&C%8C)U6?UPlplj31ohbe6A!u_ zY3zL-%nN@_;^eayldAdi@c*<@)WH|o~vYbYFTl0=opnItl8Fz13T}#^s$&mo3XNlPKJxB5toyJRRoyeQPS_B zq2xNE>P3g@*`|!#UL{g^8}hSsX|lJsC*}j*O5#CgETVy%84#S#RlAMWPZRfS-gdZ2&@mNThk zi=rIL+~iM4GhdF?qt0d}KdO%$QwwqE$OCnrt#qSix=HFU(T4Y0{?uv+9l9#00@+}| zIx>LIH_J`t47%QgBGKcUbdgxyf1HBA^Xn%oiJh1;FUdEm@sN^9B;fj+KpuNZ_PF(Z z{vCBs+qx4N91aZ)4Yr2%m%x#}$HbS*%i|A271C8EYXEBr+)AT%_oPGR{VmgSsyy5l6=BfrlK-LhH5{;tQnuYZgV68_am#3pEa6og}V5SS{5tq`UT<9 zGc|wt+ZM(wwI%ub_GFh&PHthd@8(+{Z}%(x8a%Rs=4WxwCS3lhP?$G~%=%kaRwADlZKBfW z^z<9k95lL{6D?oLM^z-VNe6A5x3BYxpGl68i%Sp`v8{~#iOEYDH~@7_!go zM4S)q+rfH+K{PZHaW9G*{aXAzJ%M?z`|vP-)&1uafp;~ma9(HxZ+z?Wr%o2O^r|;# zuO@qxeoG%@%uh9gWrvMLI2FniAMeVh@KQs4VD25q`@yK{AnPBFr`$S(`Dfnki6O^H zu8DtN{cg@>zO+|b>wYqbx*aR&ajo_MD3_8(g}GR*epD9|i98vn6 z^}{n}D~G+l)6*_s#4f(qe7v&%w-BI$<=@G>%C`>{k||icJ2Rxi^^E(g=)1E#Qa$t% zT7gjYUV>Q@B*V}_7fX}})C~T9qM*$9XMO|TKi**wOSwh;^f1A632%VSw=w3a3I1bK zGl3j3ydeCZuqk!w&Qncl&r60_g%g&axkZ)x%Stld^2d6RhgX8rp_i9vhAX!xNPG!4 zPA|n=5yuqgUPt|KxiOVF2Z-T_tnzuVU+pZ2+2OcvZB4%P?dvDM4yb=reu7oTz2Ny~ zT3%M!1UM)b2JcP6;vy8Z)V4;c3iW2^nZToU&CSi_|bt0Pd!)A0E zf}NBBX$geNj4ET0gG=;|-h1obp#Ij~ZcjnKhFbD~(+*Cx&Hv?J9CVgNFr{G-ui@cT zcvvxCR(=oA>*AERn>CAr@Rk$)TT|qU-CQ?(^`q#XsOLOui_1ho-_v6M33LUpBBo|3 zmKSS1&FjM#6MLY$0Z5JBT^y^V)YQz})WU)@_EIX8IU&M(|0f4e?|P>9+Tpg3|MgD{ z`qLJUxmRwp(~(`CvMTID&h$go=;#>Ly#?RE&QGzqNck1Zuyt;Y^7&mBR#x?$wYB^y z0r2H7Q83M?!J62tTc)aiBPVj|#y20y6f(=j- z(MdZ+ZRuNoq{t z<+a{jHFl{1bzGYPV!B)6mq2K9@8?f764_J>|5ou>`(N>uT*6dcmE2<3-t!7BYA{Jj zQjRq2`8DB_*i{O+;> zF%afCaFNm$sXyb14vLSXy);P$Bw`54&B+O_0qk_(y;MF}KoV1I1?~`P!RfVphADrK zGu1Dbw2GyY@Nfp~`*2nt@3FzbD6b~@e_UA#W-G1Pe~<3k<(eTL5h^BI({)K@*VPt% zxn*2Wa&0RYmoveV3jY02*-8szVFFuEeH$81{xmukuX@~oadKOmNy+@e z{5*e3KO&EeV_-@S`ngp|)>iB*0ALx&Q0{EsCT)dE0Z+#R$d^=Yg1jl%eE1{S>95hY z)~bOLZ|%a+o|t1jG?ns1%}&q>Dhr-kHovQHDEz&BR|*D-uu-QZlj=j~v14=*n_XJ) za@tNO;`Cf>_xOBk3uju+{dHj5Ehbtu66DbeC z%9wdvhgecKt}sV`Vf+H&Vo_NAj95q_>dsoFi_1n{HDq9 zDdj&GSnSG*t#6at&Wz?U@%!Jxf8FAI%x7v!$-tH2Y(Run_<%JD-+fnTV*{vK0MxHW zzH_mWnX~M!xp4|TgB4e66dg85rouypN;Gvr%-9+AZBWpvTnlJ3%a;Sa9ClEDNIPR* zrnSF_|Dy?HJ*F;k1tupK7qKv5IqKyS-&iPM&98Qx3wM3yc~eJsqg^E952wSTGB0Bs z{LhUp9qaW0ZZ;`EIByRmcQ8mzKQKE_b-#Q^1s`n$-^m>JcVBZ^MixjE=5_dhZ36BK zK2LGwj(ve1A3eO4^6WCQzx(u*P`Svkq+Y{G`k(r5Ryu@!{JMn$m9G*AOi=jGte|E1 zKw6VoU?$TD^3Z=vEL#PiB%=JUj{5y~xWF03 z6J+o3Pj0&Q@>9%7 zg#}rBo$T9vx^=2c2bF2?#Vbn#C!r2E;fhuXCS5BP0*+y_ji`v-We0+*GRIVMBR%nw zZ5A1Zue3(~|49B>)VLQX^16NPO)swR(-Fo=aPer;U}JOcmpdu!OTKu_&rgnO$6$z_ zAD#yCfW&!X{{wA`i2cOlHEz{pk;QMSn7exm!pgxBAzRX7%3^Hl)HO|&O`6;c zXDZj*+utUT3EZpaS@ADCBVtnsOlr5LqDPVxK@n2lux0wZ2u0I`5!#^S{6R`Q9m_Po z#hP=4hbfD0=mt!4B4$YeOw*fMw=kD?GDnP&w=e-j8kgTN1|eEX6T8JKH~U^FwEL=E z?css+aHfUYh)v;_BAULM~q?xZyGDV;At>82NK?e3&sZl1t@Qd=pt1e zutn_jJr$1b$7G~1hRE{O*MK)*=&%V$rJFO{g?na=Yb!4QL}umTycdKTH{)B zR!U5)#_la(%K*R=6_^l)E_7keL~yKnU5!DzisQB3m{c^X=whJvbGA-Q!`mzGIGwy7>t% Lry~0mY8>=G;t;L+n|NFoHha+0}|NH;_kN1+f)bDoVcuC1Tg(A;hFvuqoy@#>$>+>9f` z;|9iAc-c#`I3D{~meAL#w6vcj2)CD=`u%dH$CD&&eyEH;f4_}5%6q9KL{-)5`lR;L zTkoBIqA#)6jEV8zy6KTc-RX}Kk)em7d|V8CjRQ^Zf2lo0XlJio zEbg$rZM3B&S?LjdgM|wnTu&D6S<(!?pPi5kSyFQwdENQ`CwVMwdaRUK3w-z@TLSYW z!SllYiqCbQjCF}VD9n$j;@?NGs-xAww7up|F4KG$2UCIk{JO9QKlwQns>w4_p+ihZbY>TKRXAN+ zxzm9oLA>Qi`*%kU<>Q}bUi7&MlMFXvdC?zyl>(%=lLbTl@F%>i%sII2ZPW`b^`j|6 zOT-p;)SjVJn2O)Mo9xiG4;ekG$*8Y`Ml*9${59u(?GfW&tXJJ@?(xH0bOc>ZNW3mV z5R^Y6os>-@T}d{tojoQ0JaR}ZQKGP;fCf*U&AlOD^^16m7(K9kSmH`zLu4A^^l#A# zbg*<)rg8Ud-*0_Yv{ZQ04>KhdOFF76i2A{PKF^VKm?X(0Wyn|J$JD}_dQfhE+qMyr z+lotsldoW>>O^SrUH0W{#eWH>;Jt6E2>MX_OP=2S?LOtCU$@mlSP`=hL5#uXOqBvd zH}f%M9Yz^UA9sbWpY$CvG=#xa)4xKiXDJPuL#-b48g8KsrWE$T{}@W^-w3n~Jh__h z)Iqh+3oacg>qz2#4ZYLu zVf-c=7JnPgZ$TH1;RAjNBUy{Z>@P^s)ascWyn@fQWOyC?LU2%EZJy#_IS1;#N-<`U zvgNu@?Yv^S`Z3EJQpYE9lLk9e36 z_P35+nd8=9Mx)-(AtN>A^jAZC+B0R<4y7EyMf2kVcNs4*n&cbKa`93_3BKUX`lc8B zz;-UTEkDO_;&K{gYDD%?4Oa98{~ zNWRO~pZJZvPv~(W2Y+TR_hglGE)V%iIu{2`MZ*0bK3R^ddlp4aC~|{c9nb+eWE`xg z8h$VVFLR0<*i6X^(d$(SoRqu~^F1zml1%P$VlNE$sZfFM3&#%vUXIFW`(|ey?_w`B z!TTzcTO~N}O2@7F(n{UCEH&c-#aGhbUqkiD`fhuFV`cF&@zHh{8_r~8E(Gg5F-4*Z z4PN}H{P67HvNy38st}sQYs>cDEAbWOEA48DXUenH-M~SJ#mWB6&V-I0f_ar>Nu-NU z@WTUO@zIi?-hJI$l@CO3$ls}cRQpnv_|Z8d&F<9L@PbbzxS#Fa;4~T(0Mv&oi6(t$ zkd52Hp=2gV0){ObZTi6-TA$M@g4ESjaPar6x%`+IHROU)Qs(rKIyH7*#d=hS;+s09 zf(M)$q~n^0#{aNppsgWMgrAue3MT6gO!>aRI4!>QF|33aj11NAdN86W2!p{TvSk?J~)nDJ+a>g+B zycdUSPwj0QF{451ESd#*A~z*4-J;$Kf4#6c;{LE4!b~QxdJutrR;}ljpOa93i6g%e zpKfTaR7CIdYemWxH~4^7&UarAT8lCLy-8EHV2j|DG$X%fxtq6k%lBr z!^!>5w*j+T%bX@X>&)V5gxIE)rZMv`-r{DxTU2)`xC;Tv<93ZFK4C{ zJGOG_d3D(RIkt+l28}^>z0XCwUgaEioScMHwkH;%S|@803s)>Fx)7V?^{K})Lw|PN ziJ;`OeFBcG(~txPdh?=We6=qwf>Na}m7@0+rkj~;=l(NNRANr<$s{z#3Z2o(`Xyyu9if@`D#qj3$C8L7p2OdNV7TP-j zRH^iyFK4{$mvMVdr?LhouSjF1Z^X;{w+Dt+^yP<|uI{n%$mie&|J@di(eNjHrPUpt z3dGn=bCdP~BWS(AyL!AtvRS4-8tx$K--e(MyrZGSf?$BJVO$)-_0>F%4yE%@(+vab~8H05%24w5%Ry zWe|X~TR`9ClQ9x2PROVUt&%L@L01l6jM_xF^yTR>@WogYTSs?id!%E;{thx7YFww z*c(zLmt}s&{Mp@M-|Df&v+!=-PklQLdCbLAad{knY_HA7GUkqyG0L^Ro6nEO6cy)I z4*lfb2fVS!q`zOkk;_d=^in=1zU|r{>}br6zwm%gC;BnBk_IA{{$sHx)Wx6R)MMWK^Hi zX>k(Bh_!Bub25f8emy!30(->2WoyXuT8uN4Eb`A1)a;vb_+bZ4VPZ&v>YV<-0RZ)!54sGj;4o`H$krL$Ev<{nZ#E#t*HriyWepcRL9i+dbOjla zjs=su@d#140?%@fx~1e8D_4f%EQ|sreADCA>h{+sFr~%u8&Dq zFy2`~au2yP*?6TaZ)L0g=;*Wt&*g)syqmnulal5lK7D^0cx=EPl{=zF=CW z$tvnQs4&~9( zV7wwIkSBB4gP#soU{{~DM3gJ+#Hfe_;P?funsSCl2f@bxG~leL1`{bi5`T zpb_lvESuOb&v;%Z?Ymq~!!1lOR@TV9IDVJ1RG|X>n>Z-gJMQBm^^gMMdiH)4ThI$e zn=g}xI;Vd*Z7rHlei;=VLMmKa(St)e3*F#GTWd5Aff10<3;22lDkH;~1Y)#8rlHX8+_u&R(by6d`_bbhh z8k{QXpeOFVA37TQf5I~7$hE7n{K6vB5z){{5=!_UIM{FgAoT}@?*3I@V>ECl4;t^t znhx2TJit3_rl`8NEBh;_zf9@gL}on1GWrY@p6@I0Ap_O~GsLx%YYk2e-V54xB($$0 zHETdkvA89cS$BE}Q3=ImKxqF~y8&xkL?tT!{99k#N6858%QpUOC20XeCD@n2@VuP| z!>}>4@!Eu)=P{#^C{>MtFbrB=?G-dzxnWd1iBMx~J7#2l=RxM+Oq3N|H>bHGw2|Cu z^bC9TmrIo{;NXI=ii8jj2!ux1OaE(0rt2_AvCud@mdLnNw<&{DJeNjhdGNZIWPn;; z^kevZ@u>nDxDvM5?`zhE_ax4UEcktB^nLZ;u_ReP=~CXD_8odS0qoxy>~6hv?sLK{49pU|ovw%Njs1Tce>BsH1W5qaweT<_|!W{uDqu{ZZ%5l3C1<_hJ3nb-PoO zQfB?!z!=2Lp?pXMN9sNJ=G;}J;e0`k7oXOP@WL1DC^kTQBa_?O@l!Zf!>%F^?0Ns3 z+ja|9mvTbP8@8R}h1F~G`Qwi1xmdRuaLK}{N}jo&K*dh-QqWZRvz3#G+NK~%yZ(q2 z9?E<;mv>qRbD`b!G2qUGeB7g;%K8IHk<`Hu~AH-J;k|sLkBO#j}=!)cyD5#St zP^^i(?KE}BPw@CUZ~@3z`*$^+aEg+*i!Y%61QgXoQFi(*FX4}T#tvl^J)`Q`3!1({ z?g#pqO2ck)9`~}qwea-zUzttcx43Ub{NS9=nLGcfI`LTnENK#DDk3zES@u)*02jO$ z3a{okiaU(z3`3$D81$47hamTlMK2uoNDoEHnRqC+wnKSUGSGFMeuv=uD0q1BqUDG$ zuIZAhG%Ox84C8vIG9kV;_ms}{Gwl=Jk z(@c@xvD%{Te%^9-fHoH?gXUXn3%=kEN9_}Nn+ps;#k-*-NeI|@X51k4y6MIRU?g~u z@1bj{${A3;orS2}oEwH@O0r?A;8v<)b0&N?xB;g}l%J|~cWY|g>|_1`K(BKDSX{Mp znQlvVPA^PDGnqgk zd}(<{QuDRkr63Ex7KUU0o8uXKf`T?Giv>+(b0BjEQ(w6J%j>0?3yH%`Q-w^gs<1X= z*%O-o)&3yoQm*5~vbH| zP?e_L)W_g`eFfr%R-lqDz0Vnvx4*QjclBN)bpC4D?_y?31|!S6aqt9d)C%9Xj94Y! z5JoRflKK{yr(FktA6d9QepO5-`uu0y(+6maQ_@qakCme~S`6@ahj-QHr?}cUwoO~% zxLnU8!@*il#JU>Co55*PZ#bhUK(;M*czWPWR4_DBTZ`0Oxf20A?G0C#E9s2SUc+&P zPMzO=xYOI8G}PzNni=j-eR1a|r)+IiZccFV3DNG&6{iSrNchEy`Cg!|kq;k&ZpDr` zt{wfY_o8phnOr7&K8~v{AHL3X1mqHRo{iqws#uj|;g%3xUQDC?PJtAyEH;CSH2a>p zuLn@$v&gpTk19a7iA6@G_=SP*djI7jO?>bcyMR-AEq3@7f$C9yG~m+E?bmfOsVSCf zy@iBJ(2VPaY8Ac$*vIEaH^7LF?4QS>^NvRWx>sA+Y_D-^{G z$hKPi<&tG0D3f?2$XS!0bSo*Sk%6fQeCkr`r;wl^R*UN`H?D5Q>cRMq-YcE{gxI=N zEb#%i@_}V&1OD?f?F~F?1!LPG z=}w`B&9&M;0p12Mn;i61(T%nu1>&6%L5>uVk2z}RHjj%af;{1$_4jq9spE%)bIOlH zvqM|1fG}t@8}EA$oXp&$Y(9g5f*neaZggMr>XskFJLyZ{3Sxf0UMX9e><4i5FLlGt zJ0;$phCQ0VoajDomH377(+>p0ZcH&1MQQwETRYw`{2{i#`CLxF3MbN9`Ii?rXcvBR zceKER=Xwmm+HW|HTvHV+8XpJ*Aa-w%!?7its|}XUaq0$0Zq8Ls9W3rF`phYbcLa~Z zSxs-GYS+_k2qCBysoB=C^)upEmx{Hj!SaL5e;?SdQBizvfFx`Q=}7DahpWt4d|sHB zn{lf4+6pw}Y8)E`>HDf3!}h4eKVs&m9KVi60Ca~$v4H~{BOLqg&D>zW(d&ALIPj5O zlT)vy*q4e;h->xgAT0+X9D2@>E%py2S&%QsX?WoP=&b@fi+r{0Iumf&fSMHJQq+5c z!`qV9?GLsHV>2@uWZlY7_(4qJk;{6pP_=T$8-9-AVqjmk)}#b*A~u9{zWj5hn4N&{ zJj?@T9L63tuu$0m%%_*X8yac`x^B&3wOjl2-U97k;xFH=Iwx)_5mSpdjwZ2AH0+QNeFK!=QAt z1L2&;bf|u7@!}+gF)N^}p>#r)fFBPUP|BB5!4c?7%A^jTr^Z(FRRRFJBQ6YzGY+9C zH~w+Jp)>3)Lt!g04=cZ)U2V-a-%Pfg9tT6r?h=G9_PyzJ4zOmz}*)0>mN z`uZB40_d@Vz}HUn8n}|HMYL4|K>39$uXf_Q%!d8s%VLml^R9&b&yh>abX#94-F#Wc zR}~fJ&nuFuhFSuYX1~?HJH>dXIdMf-87IOg*7ci4t5!~&)q;?WQ^Q%jZj6umCj-ev zz*XsZ8J$`p0V6Ng8+{hrQ9>M`$F)38e>{PEru16z_Wybg=Jt?c7FB_!ZG>lk^EH&T zLEMZyK8<0f&TDS~E#sz^AV8!j{W5~eGmSjVBObO8vT_rC-ymOfB-kmJIa!lXCR0lY z2oPG3(>k<3G;3b%9wi{YaEdb(tv%otx5ul094U1KkdRHo0gsC*s794<7?k)G5mMGfp2?bEM@+X^_&SazS+1hzVnGttM&dz8{hdU~;e7FM3JFL++ z4?FB0I_Ucy9hFRcxoMi{WSTTe`kN0_*(AL4&L0SH4QT@{;DQ^FnoiH)!p7`OgFmX- zLqu1VhDt{J*u(O?OHHhHfum9peN&;=m7Tu~+ePmUBWtn$L1RP;x+D z8$DfmsW$pwLWaL4%ioiFA3Z44wZIhKllTzD_ua}|422v=KPZ#29KfA5UwtHjk>Wv` zzP!71?JJ~ZD8e7 z$NQZ~4E~Fhax=~qF%uO0vH=g5#^FkaBm7`V_SSh>6f+-5XXVWeJ-+?;-4DNiwRs8m z#du9Li<;p`&`$on7I~<@U5?}pQkyjIrf(tN#6?+0))O|+d`f}8j{A%FB8-R0z zCpBB@+oSU4OVn!BRa&jCzYj9WYESKgriEc%wj-i^P$>Di$i#!iA_X&z4+PKvBHnWm%Ek(ldCT7 zRqh6#ILG%3Vrq)Wl%akcXQSq&ll`Ij&$>6Gdt>>ley=~{r*z{9LM2(BgpT(Pe>(Ns zW4u4B5UP9)$m_^~!OsAL)POyO$P#H(u=n(bgmaIv7H2q@0(yIK%ib+-3GdLy=4eM* zuStGrbT!haPKo-6mwlj&zl;C6=#GOm3zo4IayjgOEGciUI)uebZ+mcdCB>TGKC*xfhnT?~aA+TwVCH=hBJgtacoXO%}$d07(;D zNxK*{NzfXhu>Ql{-BlF0hbYso!rr;21vaq?%dge4oi73cucAbVQohRNWTW{&2|dUI z$vKOn6qYR*#y~eIN|zD)pdiKHpC0?kLS;YP$Zj+>B{GqIWDNuy2yS8tILB~nzh&xE zj>~5L-Qkz<#-csOOi)1}}jq_&mczxa{9>WOBN*9Ji$f85v(nQhN+bXjTTpEnq_Fl9MeEwB?`$F79Dq#B3l(Bq zRU*ymwBCQ!n~zYu_`oKjsIn%5mIcmD97;q(k5!tM;%$-d6hFvFVMuuS2>_D38nGr`Fi z6=|R69CDd?4w8XJEJmtUg=62(kTWipG67$SbI#^gydJwiBuYQQE5}m0D>+++vG!9B zF^@Xq$V}}==Yk%PM;&A`{tEQ0kzvgjiLN+ADD1IXO z^mWJRg@Vrx^G~`ec^>^42F>TE$FM8{9A}UME!VsTkw0`|i+%Gq3e}*7s&L>%Kh|wok-rVQeF?qOcccIfKhVKfuktAMIN0$(9$%@9E7NZ-c+VdK&yK6 zx60A}@Mrk!-uG<=!g}a@-yo-*c>S#==D9wTg&P1rE7hH$ErmBZt#K0CXnE?{eD$D|n2?_m$ zSty`t9@3RhHW>ArRcB_W4Or$dQ5{D&w&6ROK|G6Fm)aU?A9y7Zm{(W?p9-ok=bejd z^VsH*$&=!BFUtww8tt3o6SELLHHt6@Z7(ix)^*X&L8uy32J-a!Hu^Bi@YjlRw_{6Q z>|bCZy&@eqT%N#}8TO_JMGg05PQe_WtC{>f*_u=_^h&oee|{nFj|*ambaFC$ss$oq z*B8j69I__N$Wk5k6Zy>W#QZ8w$gc_bFR$W1OUa)kO!JCk^|JhPyt8=2!2Fh8rIYL! zQbHY0-D?refOg!OiO!o0@_Yl5qU+QfK$5$kx&7PTd*bjBBp2UCTmr z-s8(Ber=?3c|j9B%U(}+gAne40g4Cz=4`ba0mA8X|I5KfYv8AUbMt54-DL+_4Fv6M~6*WYu2E;t37E& z)`;N<($oMn$gQwjub4v#ZJ#RmQGvA0d`#JgRU9U<9RoVJ<}-)++w04gU#(55m@5je ztB!y_q?}p{DkiXHJ?JmE^xP5Ps{nI5jT=NJE6z%eBsffLe%zgr+H#*2U@w@A-YrV| z?=M>SBE;$qj5M~Vl8h~-JUEp;C)Of>J9qV|G4BOeU|E0L-gOWwK=9*$3aPQo+E-{U zHx&%y4TCLzy!XIzHF5*!V9<@miv!|fKhk!k2jr&fK&ftL22OHdG?Hwytq0lUbiFNoO(PsgdN&Y?lZ`c}LdioB z`nTh{z=GUZ>$yVj0&&=IxhQ?%S;oiQ`SmRa96yN!BHj-omShr<@+r;)jMWs0SAxy> zz1Uy?N(g68q1S;|gJ)+4Olrvm9iu)?0Rjc=3>>7ZX#l8z@$HJ=0c7t|kL9U9V0VXC zLvzKKO*=#a!2?KnAZBxAH=iHqBfQc*(J8T~^O_V@d=RM1^hFwl!e59D=16Q)@g6Og!J*`c&J5o*!D|et*CxAwLn#G{}m- zf!5DwDJLzp**}^1+klvAG}I3^5CmbAF64kM`(u?6VXS{gMp{ws9N4Lpm0~3Th>nXF zx$>V!F{G9|Y&m{1AbjzgxZ(@y@i#&NJwXL*exNKHam)H|GP?A|zoEGDc3$9Ktz%m8 z31%B?vic>Bw|~?Zq=$9ha-zGiiZR?+@m*2{IB8GX-Muj)D*KbbvC&(>r1_$kvS|8& zfDRB%Rv`(ViT9=}p*aj`UGa>2o|7H++di1EAAdP*uI*)khv7Nn!ZI3ukPZc~n}ZjY zSC!yPvAx8GUk@AvknYq~JmB;45^EsFf`ID*ayp-z^SnywpXy%}Z+GzHgXk&;XfV)> zL56Xf>xC_uvYJREg%2>L(nNL#jG1HmBlnC&Vy&CVqRYTmdzhnQpEu@D^B6Z!A?GW~ zoGYs>JvroYu^}~s4TSn1eF zGosw`Iac<ANCya6){$lWjmb;Nlm#pTx&$*X#0Ww{3H7df8xcOBojJ;Q0w3hx0VSSqM|vPWiQCOGmtD?~HU0kS;Y3HaQ{Z=eh)DO9)6GnGR+)Ho4Y0}5@d6DokYE_~E-bo;ApKk0yK zGD!?(&`EN{6NA<7U#aA4lz)tfx1 zrzxnU1(LxV{KcW}je@9J3}~a)+WWa$ub-;BJ8%+qaXv9lB#J5f{(%H{{r#}A^Drsq zD(J%Ner36!%q`!90FwD2MYvF7H5+f zl-JXDcyi&OR;<_LXKwr5nsQ|s6e~kkYXv;J0%tV8*HZY4IaUNCJzyN^i>mKpTHcks z?Yo^yp|MqK?;WuY2B{nv7&78d0)P+ln2dTx_(vNhySZbR8eREJlG5-`K z#x}-sD~9n6(v_(Z;lSWiS}+MbW~F*i-}}Knw8B-$H(P)t3;vc8fN;2*%{bsQ~A!6;E;L zm8oJf;-2c^SZ3hBxg12IYvOj?4ziq^G6c-DB)T1Z7^K23R0o^+j(LY43FOSoAOrpz zG9RY1f)q~_oyy(-v%AJVE)MjUHu)z!D8dn*|dl(0}H9LZ4D=9i~4y$C7A!)z|2-1gt!HUV+%?s4wOy7G~Hbf zWgOBr{ToG?vQ;Y4h(KS9{uJ^m-4di>DG7#oE0BcWp&ZmsS(M;%4Jig9&e=dhTmDr; z>|;>oWM1bVt)zS-Wk+_nvA^;uZ?*v-gGsT1qwVC`IIyC=g`UpBUHvpFkjF9)w*Hl8y!-}^E5%9Dk z@*muAjL#RC?2pff%w1XdJbpl(Ab|!Z_jc>sm_m54}7v zW@XQ)uc?rW1K|)@@E~1DMqnP02WpIzw%m1i8zmu5F@#(@?0&xiuO!|13t$XRvKz0g zhV}IoRIuqVL)`7@vn4%Ku?h^o1)OXuOjR-+pvQ9}r&9I|g1{rEV!-}LWnRp*l!G|>3%Rb0c-64*b?bn%s2ugeDWqq? z5^0nmtplFYM=TCiL)YYgA93K41B{=CUP4T0E41e4{DLWZk5|-d=#*z0l-mHEN3Zy`)UU21y!!J`S}IuI*vG^ zI+wr;!hH+qzg)mHA(HBK)b~R?hK$cGIr#vhiGQ*^a#)q=U_6^yh7mb&{0H=)o{04p z^W7d5lGPUftrhJWA~YI%61thj<%`n4LEbiw$hF-8;3 zt9$7ytzdfuDecU_>8{$T4-=rt4H8v725Q> z8`Q>q1s}w;z3}+4;m4li6Ap1!s#Ok%Q69(Dy}mbJG~|KEapfPAmt@-b5bHNU2q^0- zq`p_4w4+xY0~ZmuKpw9!*Y)o)2f^f5CvV~?>3DYr5i!|VLEIUO>v;C*{@k0#_D^j) z(3=FqtL;K&uIfsyP98HD?HS;V5q~{8!e|^3>6>%DGLpt?+;V`@-rEqe&i`XvtiDCTxDVRWi z*iokupL+1wPGw(zu8$DJ^$-|r@f-I#tGjZiIg2^1ueiuQ@Oz$@fc7i=Pxp>B{D1aTXsJWZ){?@NxPW}QJ=*`4#z2}UAl65ZK3 zULs#|2O{nN#12)LG+=@Dcws4R}frRBanY&%K%Xk)-L00Khr z7bXt_A?h-XOO@;= zGz%v_bfsNA_XTJW82@Lt?EoV!Bmnve4M9%NA#JG)8PF84g8vSm3{>WG(LU#V%scR) zIe=HT*AFYad#_h81a+r7LW;gxTS8WeLSdB@+=)ha{$*x23$J$|O=Jm%P>m91uQYbNH`%R%npQ+ z5JCpe=Dzx5^=2X_dZIh3t8Yng&Tlfmyz~4mZSUgEXqMfPjj-)t(=uhQ&zK6fYHZwx zhJTiAd?{DK`ell(Szd*a5_^kYH2YiM+{d3`N?-&ui&8buS~m|E6l?F9lTiF}$01|P z{9^I=Zx$Tn2OHy+EO|Y6@j73jzx4^IlWaL%2~wJQ-}#&bm}dUf^_7UnTRZ=gMe)-+ z*f%f*WG~)vBQv(~uMob39btHbUQ{bFz862Z9} z_B5l_5r^2KvM9TIF9BE)a*OxpQ48uID$zopHD9wfXLZ_GfvgMs1^mKldk>X=G|%w9 z?IR!6KQX(^=u-2*mF3?Fs-@wiHP?zXe;obZ>dE`uyFCQP(0}8)1FaxrEhymao_o4Q zV1!?kZVyf7tlEYFz?-P^MqYxlWE=>=`Q6i&i^snQ_!PF(x<5K+IBlBv1cguDN4O>T zb#}5`RBN=L|1}PM9gcQE6J-2Dt?#y)`Q8N%N6&U5Fu(i+9eEWGr-_)H*Ui5cU)}Iq zCw>#>_a&$3lT)Y4rcjw#T+6b~txo;Qm;#V{AKs^&=X}aUjd+df$U@;`G1K|j26@2= z?EQWFi|#b97Ss@(g25Zr;7BavowK_bdl-KgJfDYnr*-!OiC$AYqMv_L0`G@MQ%J!q zxzht*M%raGm@}50{zi?$qPdCUf6FTTUC^JWkHhO?DJ+%Fc$!YzTfEl_m9mHGRtMV|K5-{Z@C3Oeab*+#5%)(QK;q0T1H5+-b2a!VuJ)ID}y&)ZP#0*OI0+;>~^Ll7Q>2zZv zA=82(>|c?4OVPIlcM_gY{Emx-yBzu;Jqt&Z-<;B#T#YGP>VjhU6L8*~}o{O!*=58uIovw2OAG6tg8`aX-L zah6U7D_%N`Iw=U2CFn5iD_`Zu{`j*`#?yGBQ$6VK-{S^hRQr<|IV#>(Obes~@e;vD zJS_)Dxq|1T!198G`RM!Z_na<8S0Ee2m-dbBn7>p)o5yH8h{LVHh#X{>jR=mfdAi;t zS|U#-b%A;A{z{CsvaMVAX}N2otim}xGTUHo;Y2-DiJHP)Fk&QPIOa9E(NFr#jU~<& z>pO=(%ga2&HNzd9Yxhg(Ves6_9rksl_LmRyb5)b$U4XUf37Y~+<*xMiciBB10?fn< zY5AfEWuVf@hnvCcZ*;mbC^hwz5T*bPv8DZ>C%K+fwVdmG=`y$%l|r+6Aa~^P9AfTS zz(p@oDl599{>I`EBWHe%a9aFjmqhY0JcV6``T7vSlcp4-cx!kGJvN3$giK73*{y_$ zp5TPW$rbAUd|8f(VxhMR80+`C96jUt#V!cT6(iQZJLh~C3qx(I14uHD$8Dvb-j?g}Zs@EXSCWnCEWM&*+rmDBrhlAZG2_{`q6 zf5T79dZA8!y7$*@!Z67}U68Nk#e7aW$Ye!CtNW;j>2Tqn-jCkPxgXH1rQm2!d!@!K z^SBvu_gZwE*0t66`Ryk5$IyP#^2@Fl^>K_}WW3)nVUBzpDKc}!K>sX$d&R?t&!4(h z*1V6({6*A!W7hs9YL!jjg#mlPfuBY}Vbjsri7pmhs?z zm!}2W2IX;1b0<%`9%cqr181x;&f;Ki@X?lmRonmQ_Vrx~r?pmYsgASD4clHTVobFER%P8v6Y}2t1=q%s zQv2c6MDO-ZPCNVA!X+oCd-n5XlAZfpub-5!`z{=k^hth%t8YT>Xa+)h#NS>ejG4FX ziFd_7!I1NQML3o}=yl>>o_xx5sTCfD2@~lcOJ|PLe?NVR*)+pW-*C`q$W` zsq3rFNrm;5YVRbb=opaR%yS+p+ciqzH6T9Wvi#XHF-A>V{*t^oOl2b$gzw@bE$`%Y zvOk||b106d**O4-b1I9AgSnt!u_JC#R{lXb{tFaBlic0K4Zn@Y8+oifW;BJ4w72Qb zd3e$n>X45Yk3-@rzizp$Vpy9#PA2_9{$0*h1|!)~?r!+Y^Y+hfe2Fai$T@x1OKV6R zNBnH}3NC7_22Lurhz`}H4yXt3_%f$`Fcx}PS;2_V>SMX!J~=4M8RIKPzLd5{dA#a{(^=8`pWb7NM5!sWj*S+ z216MO#u1im(}M9o1>k8pUF>nmcay81;lVlGGHvpqDMjCb|+WB*gJz`gU$mR1}u{i(jT$8z<-dq*m zZO|j6Up+6qcVSUE!IT`rGY?a7gj4FbnukWAQG%aOpNQ>v;0CwVxIjVxQ!jW!;gf-R zWxvl^dK7c{{ns$YLmnLC{TKZVs#V6$-ovswuXAI6KxPnoz1T4jr|FI_KleIl zOcv&EjFM|`c@9&@UX~f&&7R!Nbbsti5_YU-4ho<1=DTlvmM!N46_fJ;)MK}1H^4<; z*}lP;?U`@X@U>8?r0n&MidE((aw|0lLPs|-q*IT3z+MPc1Db0zo77aj7Qz8y|9uly zO-8DYN3#V_mk*kRnhblzyz`HJb-tW^Lz{WWQ3Z;Y5) z%qIyT4Yex4HLFbCpqjU+)T%rRP#c@g7wS&1YIqoqVJ&f(HdSsLi_-T|djb^j)2nFP z=cm0M>ZP|H)_4AI11MxVzRaC_aKHgu z>pU&)!dyKV=QTW!j3^ljBa(jtZm^t8wyZ4m-AxB8XaqJ z76yC$%sOmz>k_+l9>}ck zD=CCjWZz2QlycammNzdqoHbX7%byS@iyGNgjAp5CtO7ZI%B6PMSUa1C-R$pRLZz2+ zW{>XHJs;)wNBIAW*?Y*6StU*cdR`LsEZqhb!yf*rK z#kh$~*1!Arj2C}c9IK`dmZLxKZ|U4d`KPsZ-{nD3*)ZOmjBXzveHTE&ezc?C^xfLC z8E=gnSjPM){`^ns3)hf?)_MOtMDxXPcH4NJ+AsZE@JP_RuRd?_DI-@aY`*iO8Z97s zTnQel_6~mA~JQKi9ZFfFdt(7vYvI$Xx%OD(u@bZI&BE2o~-6hyluciz*;M}@N2 zFx~Y2;)h-n9%C25{)N{45(ZrsSzPKofYfsxk-gE@L{ys-wl5ZDZO0rwW%^`sDS8FJ ztx-?sg4Ob`;nDeF%RTZdXk(qJdDQp!86vS`uM(``)??E2Dhi57E3dcX!c9#Gwu#CF%Qh*cWeBQ*Wh=z_VqYWl1lf&hy5L)o-zmZDweC3 zY#)~?j&TvcyfkGD%Icm*o*qwEn0J$sMtf1z2|St;qY*&fWV^l#~)JEwJr&YjyB+D5q`Cjao_vec*efJn_gCMh}q5*>@6e_j9&g@b{B9^gffh9{!bG zk+Q1>@l@74b0GLQ;fjarZ+14B$N1T6_x{O-Z^m)N<>HL&FMZbEe0r6cWNOCzTUb9{ zi(p~X^Tlv$(dH!yo3)mH@15&oP7eL_(h9xf!YP#=3S7V3ANOhkSNu6_#s}vO7P;mV z^peL@ckZVMh7U57GJOtr@lB_5_0nQR1JGxSG6G z0lV3suh_UzDfZq=e*w9>KJUeDwWL>>ryDDL;Kd35hNU-Q`>i9*c+uz7h?RaMV}q%_ z)GH*tZ=|zPetYDxeSQAWkhR91~=JoH9y`Al9_H}mIezo`K^ce;|V1hgSyPv#faefOP{R?&JxgCUnnX?bk3KnDUGqC=6 z;Vs?8xE)|1UHs(qlv@tcE@`^ILVEjqe$w449Np=OGH@-B53-=~ZNq_A} z^SYa0%ovY!G->tyLJ(N%zQ#ZAqeab+5wQn5H^V^*f?xHl^mCYOimnsLlQ&(XiJHu-VTeRB?e8@2?KX5O>mBax)7yV_Vjdo6Cu!*{tUAuq{bn znbYSMiM#w47Mcp*M`{7d3o_}*qHyVIzVpv?87YkIY8&2boLF z^VEFr#qkyVaiR0d*^>0hZdYLrblyad)YiQ$t?tpBC$Na5V3|Myto5eA}k6{#toF8O#5cu(F!H;w%3X0X)+({lH?S;=GPCHj>Rgk zm1RzmwvPM3VTk2XcaE&6w%#bt>3(iMVrUN%Sy90qx^C@N_ESr+^JlN+#s)^ld;Qx( z+aCJo4z?J(E5#9~-Sb?5Kg%dLIz;*VeTh%l&erV8`#)@rG1mpnQL<5-JmAK7zXE9!3D7__HQ{We~@?zFo_8+n0TJyu8&Xp)gMKy#IAyqmnk_ zsY5+f$>h_wobp{%#e<-+8acl4l%4kF1boUClufH^PCOi%*@<)oEHyQI3Rk3 zxeMxX*|DFWnEflaN!t&4w);R!$v@9cr~2|C-+Yp@Xnf#l3GVft_zMhjli#mQI;mNd z0JHue-sA@9emk=NBTjVoq=Fh1`FbQp}`QBWDhpfzfZm26<(O8)=;AA@w6?gGf^_k-G zk#jA3RLd;LnASW~8#76-NJCN}C0GL=is}F&lRV4QZfh#<)wotwiBbTRFX{LgBDZYym99V4$lBRHua!^|MVjk~9ZgMa*G6LP*G<7FskxfX^ zwAO$c{81pb=9?^IG2b?A=8WFK{2kBs;j_+M$Lf!tYA-vjh!w`dc{$===k0XC{GbHRqRDVb1Ckjv)KRsGzn^r?(B zfZIBbn9q=*gwgrxyn{^Eo4%Bk96pNZoPV|bJDDH;XcS|UECWjVyN;)U7ssk>fq_Mn~n6I1)v^>m<)EjPzxkkK5c?Xh)^6HKMw4A1wl8!0TcSh|IRdQ@2HB4UB2%tRoDCFz z;JV*3Qy`V}8uAV%eK#mkBji|{t8Z!-GB0TtEAs+|ovH(I!Afd5q`ez4TcF%@tcF9wa-~MD*^L)OKOPv$#B;0Ij@^mp z;_6Cw%BbnSLde1@*}!)6PjSI~SAfm-Ppjt0+;^|JN`K^@Ot9x(o%<6&vU^H#W4QlN zJ%p{@;kaF=)3%8l+laW*OOQ-Rnq-ALiR;AuOi)v)^JS9v107X@Ew)Q9>kZi_Ku%}@ zNV;LD$0OB;uo!(G;mYDH{(?WkU5n#CISlM)9iwP9>#mVEx}x?0O)?!CQJ-}4D zIWW3XD^DJc0M`s3<`3dl@Rg06x_B{|DL_hV$$yoEJ|X9zd&E_Ba3^Ird0sqoXUveI zNC)m_#rB@X!?eTZC8;zcU3VWZM1Tq2wO>5ZL!pvMXz9HtbF`$q*z9M-_F)`A-w5AH zs093w5!2sZ+vS2S_1+Dh$dRLCL&L7d=m)xcDnTVRyS%j(lPjBGN-$$S-y0J;ewgA! za5`IG5{oNFrgZpyN_hJk|47SaxNrD_X55^kRn%PVg@eTemH1KAUUn8BakNDoGwd$y zKP&zMXCNu+p}GgqfcpvuRQetYAm2GSd{dTwg-&#i3c)9%lzfB&-f+VtS-N{+L5n@v zbG>ypA%2&eQB?jRdj=ACoKLc^GLVl1w$;a!yf+^heibMNFLGek3y|L0yifnK+vyCL zvq+Q9c4px!dTVG~DsrkofGWm)re?~aMlC*1zOVOof4js#7I5GQ0Q?4Ba|dK0YcR@Y ze5IhwD8|#_GkB!z%b?+rX7kJRY)OxwZ*LkXs{OY;rDGK(`szoi^Vi(;o32-5JiZ>O z@ct&h<`DoE$n#EG+2ZIE<1K%`IN6N*)As7-!zixn?tdk$m^Od!d*S<8mT zdoVc$0KYBu>ERk_g|I!m)A{tW?_Lmi%=M9M(4cFwM~K8<^1BttAVDm_cySHI$dP1l zb@G!9R2KUQ&se6ih?Bt-?HD<3qDKAcL*Fm(i$C<~XM7plx9$s^!boBxjhF5a2v2v` z2!6}^gc;tTBSPS=r!TVNBtKHCfPD936pmfpoSgR`e7ALgwUZ9sBiePTfYg&BFfj5e zQo0t*sNrR^EiD@P{wk$1>$Bs?&R0Uvp)0iFk5D$*>KuF4@prl7o5?2_Zdz$>V4abf zmfiQjrgq@T#q$n#fK;>`@V!p7P%Pt$f9jCrU68=9)PB3PTpo*_zEg!Zc;WV~mGOwT z;W20$^-df-;~fwUP%?@u4in%}hgZBj9XUg*J=w+=iqXrva=;AH&bgv1%FreK(7Is# zc=ZfYzuEqiKsTu5rtZ3fMdL50-25wX!V?}lJCR@=LI1U5?lY{u>U*2Pa^9!%wU%D@ zc#0-w;_V9u1IgrdJ$tGFXfeN-T2SFE6&3#()@`_AN0va*{MMs*Euj*}>gbZM%gv-8Us-vIxJGzjIs&C+jO&Y0S4=xw;jpi!sZ*__Q8B|N7H04bCUrVZ%qpDfTA|CsCd^(Z8OEwfIb|C^xM zzwwV{joO0P7Bu_Y=UTxeKE1fg@7hz<-S0d1sD4h%ahvisjOJ4F?OPOV+I8~;+w87G zsa91(h&-`*O2%eKiS`TG_*cAxh>Gyf^^v{pEMs3m!uS%`;VLH$YK{$2RRN#Av?F#lw`6~2$oG$c{=2`L{$MZauM)Bh z61OfU7ARyNQH%_ehjg^JVA^)e_|SML$tG3qFjkY8duFnz5!kx^4in&D5S2;Ut8q@6 zK!B3fIlC+GVbTL*3+`%(@3O&~fa_SvkCyI&_X1MxNBE0!rh)x$@5cVPV`|vxt%fLL zaFj;R4@9OnP>YeoIW!NKyOS{rf24pEk4d=UFyjT||`38P$Va;Y*6yuBupHu!h z!WQ-emg6)D(E`~m1$F5~IUUXo6lNB-3vIn%{@D5>E8-QGBiq!+7yXlLA7Yisi>Lh_ z#i2mb*MhoTKtfguMWOc7`X!>~OJ3^3n-$LIs?FRpKBx0@|KxgAY3Gu7f=H^Kw4xK1 zZ9{t^n}Q?-Sk-ARJYFNhi{>C<#pC%;MrRGj=tw9BE`sSDfacouY-MbguWE*knoO^8 zRG#fmxM6wu$-o#d6`DAozM%=hu#G$=OHryZb?!fvjg8;8_))Quw?;C1kN3v@{2jOV zpr{vk`=`LEmyiF%wZ9Ski{P&tJm1ejcszW`Gs4=w^-J-JdZxd-;&bw&Ub^o3n*XA} z_U{!nAe5nI#VWeD%-(t9g~n>}^$Q?&K3B!W;keY^+b&G!-u5+zz`L}nIEQNeaNkZZ z76x5*v4?+dda!0$|L>T2b$g!$JsWSQlh0;?*oWb^L@G9wI!|F{#P+}6@Av>((SMKY z`{EdDsVOoO&TpqjXY{Cpqrk+4>x&i_wje}BD)_2py9y(C3c>-BM2bBV2L|TS&u%`Q z6)W}ehf1#u_~QTsA~!ESxVevfER$}u0Ou!hF#~i}Q^r&xe7F>`0_)Btr&{h(LR5G# z$6La!?vm81w27MGr#wpaj!>YwHV-i+n1C8!+~l{c!yj%h!3;2_!1&Tf?~@DFbAMyF zQ~FnaR_U+TaRL%T(;*S>M2hSM zkIh&_M$~!n&+Iy}n1J2$H}N|+Qy4ScSywRokOE?UZokx1RBVGqlVH5p*$hk6pL#8F zbWUPnU1|@jxLy3rJv|fBY9xh3xtvqhF=`1DsT_1@y@8c;{IMWl0y)X)DTe;u*p8R6 zh(x0Co`6EUUwcTquH1Je9_$hP7%pioF#=EGDGA5+@KZu$tLh33&BqIa%I4}w6Q;NC)F&6_7BR9^R)`c_dVvom+8qR zx{{$e1rUFbOjaI;>)ap%@b!^j#KoVD`MioHzKqoJ>rgf`?abdqOz)Z3O(apXCN+;v zy7cjXjP-3rFHbk z0>>?u@kLc*yM?36s^cB09qvk72?e zH%X#+g2apMwOkm=+Yb?gWbu#F2ac|)RDaDlJ|uXsI`u{#c8E;mO2{!h_DmH&b|ZEB zV@@$^4MvM?U{q);0Y2IM4*?pqg zR5c47Ns3r<0TyqU<7X#ng#K>+NJVx6h9QfGUGMr+QAev>9}lYS!sVV|AnwX@hdhYV z-Gtgr?ua?Od*|wxAc=&v4-M4J6$^NS<%YML7c>LVHuZec4rLT56( zrwdzLGmX~NzsKkLvUjB6`iJA(iZC9CcO-A*O2ud0!3XTR-c24NXuu5-jB;ZOeUB!} zd`qnSCEzt9;b%e>>emmrf@Y*Bzb8xqeB-QIT;GYX7fySf7)Dr^KqD1smp!ExL zfeY%-?H`1tM!a(G^6FIlZV{W{3FNh0i#+Ip@@u_}CeAjRnoiyfkQ;f3FBN5}9aIRk zeX&F+%?<0Zk9PLKZo4_CJ8iu3t}`VDaxR39s0>^{_5fpaxODeufLQJMmw8A_YP?-z zfoRtUlC-_43ToTi%#P6w5S@EhxuWS61c~`k94qD0(d2%>j2yWR>q?rBH~m1!SV{&E zY@f6k1ltz~gEbp9x^@-FjMhpRn$Bm#ik6zhRi`;31|$Qb4ctE_HXa8^f8|9iRQq^98zIoUvu71;Lp2q)tIHK0`nkA8b^5zW9J&gMnXB$yDaa=+Qp>HFxv zB7|=~aguM+*PU;ATtihv3gWJXxNg$rb2bSdCpmPwaQX{3A@wfPdDqMzo<`y+&llmX>fmfWaUr>zPaIv%N#ZP+TFQ9(#IR{{;_QdW>>I@~5L zRC$X4qhw@~anS0A9y=cyhR&52FD~YJzl+Q5lLHZY zV0X1ploP~5<~}X`Os%_Yq|%};_@s@~TLXI2bAs!9gyk-I1yavKSTL);_^xK#3a|6~ zPL|`9Sp8RaOj}cq`{(g2xzYZDcl><*^X^bRV5)S*?3v3H0wHdC_hNmR?Y7~Ne6PYG ziw%qWTpZ~h?jV;RnI4_X@be$Z#|0LN;OFj|L;JsalT#aWy%;-xHSsL8IY4LDeIZ9D zM%vl4btZd$SuN(kK2}cd&sF{&#etA8m2nYLaSxMJl!TEDKL;gVgh)~*hds6h0xHKq zVTT!2Yu9bib|eUCZ5^0{L^H((818E@`(0ek@9}8|4gfjsDu>_c!AzhTl#D`@v_U;D zm~x^WA2Qzh^~~X@|H)pp2Nhfs5DL|?(eJt>H8}FTmK>C#4G-iZwgEGiMlu8?*15)j?$gCUeoyR%MP5qU-q%&GMv z<>I(KQ_*11UL+?Fe}YDRpg1iqmwxDpug#rT>$#*75dQR)u_Ww{LcPxorWv_4R2xzdLq#BFJ=` z3n5^;(G^s7VD3fu3~5kSFupz_h=E>sd3DDj01*S=^tp3CJrVZoWG!d<^>=HG=gknV zXBPo`+cTwG-}^08b08`h&2;Y-Q!n}V0|mQ<&A59LB92-iB11NZvbF8FOCmqKM;AV# zpF79#cOu~%s<{eAYM$f=Sju=?{wVud-NqBVr8wA_tx?7mN;Iw1upi{Vz9}oGG5{vKBe=w%>eLjqK7cZdNx2}4=#}W$ z`aJGGeSeXU#iew9{;&#mS8q4K#qUjw_~x^DMgCM)w7CS7HLT%T)cy9f;5s=Q+~{B2 zjs^9N4ljwv4vcN3?D;ZYxsfutn@t#2ZkGD8`3nf8AKkkifru|u}qR8KxqS6o=B^0!C!pt{?Qwh5=Vd60bPC30SB1)r`SPP>D%cuh-7LWv`1xG0CPEXSi zMIC&2|B|&t7^HG(Q2r5NAZ!0?N{GwmTQZ&=%fC?F#EhbO!s|{xBKJzUw)vd9FmBd4 zdwn08oJ$3FW!EcGX05-6n}Z2b?8YXrw3( zT@Oa~R$)&Pr9X+fL%g(cm!kn4kQXa^#qpgj*<9f!vVC(8WjOliu6m|FdA_KYwu9>U zLWjH)iNE)Q8D15d_GYj9=7Kflc00IdaU)Nz?fY3O)}*oHMk{`PinPDz=|`S-PV>M% z$h)rT?~jN}Os+Nxncfs*-HDlPkw(|3J?$GhZrC7(A#1wP0YAd!S?5{2y}0pYI+KxMvf~ z26~46M1uAm)Zk|aDrfh)jUf@5WyP~y=lf_+FF^myqP!34;|ZfY`JmpC_s*C@+xnd4 zh%*paDhK{8h`0li>s($IA>=2i;p|s57I)^9Ow)1iedpuD`fIsie-Mzz!^8OZ0ok7L zV;GjOqsb|W>D?FCY*B3;R*y}8_ws_`McZE#{vTfZ8%HIj%J0UY66W)0*Q0R~2M*k* zYWhvPIW^07Vum!*XS}DLv&RDJx^0NS%@myg>gF5w*BjX~^z>JPu}mX+G)~!%fzF>g zi=uq=9{Dz(sS~)4SI$G}SPN5PnwNiTaKNUENxdOO`P_)5v%YVzm{$tn)W9i>$)xZD zg#IDc2dwsQ#O&-zW#*ncSQzU07G9Bn(*5(Fpt0YisJv6m8%ecsLR zwc?SvCDQv$zIoRMGeZ%C8oOQMPu(!g$fsT$%`7D^^ZEW!W~l|A>i0B&e53YIlNgFr zU2)P_wVt+x3Z7UxW?L&wl(d(?d`$#u_goqtVjgd0<59Gyb-PK#I;7Y0b>0NyKi|uHQm# z=Mfh3ttYt{^}blIRvhxyzu+o$eha~JdmdL>(~X9iFsQkTsSx@-9dp!(LkG9?B9#WPygM_H|h#9}iKgWD;m)lD{mzS$)yBL8D)kdfnGr=o9477BGwTpzG*j~8p^Ciohihv$1QJxms zX9R}-E5EC_sGAre0GIoUg$qJ-z)gRY){|t`R(XVQI>fmgjiVzNU+r`u+~Zf@o+tUQSX{-% z$A8E}#K*atpL-rD4p;b4_p;ZBkVjEMELKF#ykT)m-Q6zD(&g7RxB0F|zoS&^5h~0JnS-c00fmEY{YZ z^ON3P#!+7ej7bl5OsSqATbNxcG3)*R57YlSFey8}K6Lu1k&(?wMOQEm*o-%@t-r)g zzZ-rq=t3vAvj5X?C00oPvTFDKeYxLCHtmqc*%5r-@~H8tw1?6YS7P_R(dxL&ov}Xm z+38yOh^1xs)*}1$_;%{tL}8;S_dmHjw#sLtzF+?S3+CXIVh0bS z=sq;qxfm!yQy2Mz`p4Qn$MzYB+r_DmkBc9j-tQ(l7`HYMkE?*F4Z+weh?~p$^TWob z?j6u?_KdarX?JOp&w*2=Z(Wa1V*h?o<7MV@mBjstxXZdbS;O}{z2FbvuyHa_rGK>f z&A`y~{qC5*K~&q5wqW8NM(1E}ltOAYY__`DfS(5&p@>GxdseTR94+zw$UNrDynjRR ze~98tdgtd6yViY;EM7g?0}8%Z(EXG@FMJB_5qU5RDB8I)14NNe%Pq!U1$i5>VGi&R z1^Yjt2Hy!$Ar0}1-~Q+Ko%jHAJ-~3%4}W?kr=EV$>lf-9uqThFRd{)gmA}t`qF!I$ zd&?S93K>?K6am&=ht{HG=QMV4pW)OwcduPK-S*O1*f;f|M&|KP55Z%{*piji@5Up4 z<^bv?a(6isF_Y>Xz(t;fI+b>%D5RPZUJmeKprd^SKwY@rL2)asl2nC(N zTjfi2Oe&E1v>w|Ygfg-vqJd9|+6IXADOdLed&yJy9fkT;93n60|JbJmX8mq2^oQf! zzccmri1475X$pnp%sx}ip^c#{q-bXt7XbE?|BPP`=7!l)@_0A(HbB^NT4xP5G1u;3 z_)H~*<%0X3MeZZFVLC`Jj3YYwCjs2`C%HQ7Ov2S`CZ z=kJN$8hvz27@GNA7uFl$nm_~PfRFy0;kpRZqPZWxYm9C;O;x!}t&~<{eI34@k){MC z>-?)kSWa&3k%PtK6BX$h4^Z?ty#m@2_PS+nTn)US?Z>j}nc!VCv?Z}#(Z z=fM)WxlgWQW;xJ@yKkNi`R=lq!XeHxFw=TutkP+@cYIfF7rWLd<%e<|3zJ2Grkn*# zV;#3}pj;PnF1Un{@5)+7#~M-xQjd@ECmIUZ8s(wosT_O=sMsdH1Mf!QH_0#Q=y4&d zG~Zp0Fr*7@`i3|^(MXF2uUVDJ7cuoRw-3V!RbH=M)1%x>-S()I^ZD=>DeooBG8Dmu%s zkBIaa#B?WY_K}uq=SdR48|VNFoVZAt!MjPuo6Pl=VVx2IOVsTj`;J}_9)(N@Co~4m4s;V9CP}#J8&dfVo7;nyU zv*yP8idz;#H-QUAEinDe}G(0eUp`s=|mf0y?98~tcaM{kDD9@BSJKtk} zOU|-O6tJ1}H{ie&Fr{VwA=cmmL6hicJxFW!4+@PWyFLBe>uG{eWMgZWtPs=u^I!ey z%$wGz3S6Wa$=~@mJjZIqRNSe3q?=c}a1T5K;`Uw`RMXV1C>(?;1F>YWr#MMVncc7d zGB%#(E6ZocGwzUklfdFBg*P#E*p`R4`u=*+Zod_W(-{<@c6}p~5wLzuME;{K+7(!- zwC&EwdDaegvWqFGtQON|GefH~scTq^-#%jm+|O>Wmnk^G7%+GKTg6X57rd&?mKz}i z^R|J@GY96ss4iFm?i_4A_M7G>|}?OoL6FV{1|N)Sqk(^X}Ns#zn!$h)uO}F|WXN zYZm5y=ZH(G-wMmEfXr8_q(nsLI4)8ET=f3q6E!k7d|%BY(ofJky!##=DESVcU5Z-7 zzWDlyzCID@Y2D~cn+4OZZ4Wf zc-tkebbv#4rTJ37v#J=<`(KUlYVzJLbn1LBchIH+ID5M;r{TkelI3y5Yr_haNuuJqKRwTce`sw- z*;1ko3ekR9h{1 z`9<-iJf2K8{s~=8xS*;`uCIe2f}` z@HyZAqU}pQd@m#VGc6K_CY0TT`I+*bo+jj6Mlkg02Y87;ht})xE{_0G0fn`VhzfJD zh+bmf>ojwxfEpcbUGrQO!ge@L2#JCOK}fU_5lDy; z0t6C*B9sy!%21I22?8NP3;{wCNl5rsXy5DfIq$hX|3Q>cRlD|np7pGC-@hA0wQ7-$ z#0_C&D+TTbKSv#flpYvIYN^Z^+iu3lGyw2|k&Z-zMrhpT*Q7(@q%FXQY~8pT_&qkZ z45FoEaX%$4p%VhuV9*&=uq0%_wvFKe86lTRR(3@m} ze-;gZvr)}4^F%s1LiyPBqnhf!{5MlsqzuPkgQ!>sjsi{) zAjy;Y5ok2!;mFK?t~vg?b&HZ(i0_m{2m2hr#LY?1McM{ z$Il3X{EP^b6*}8_=Y$lz=3lOb6Pk%xl(McSWAim6b&-QB#M|ggn0_Q&v&_~qZY9fKu)dL|! zNljR+HXsQ~k`MlCyAxI=#e);9O(&!Ma~A}t3&#m=+N1%-DPbhar0W11qa?fBK^nLS zpu$6`HoL%Ob|7+hoMZ+=IM?9yc&HS_mxi26kr2{vd3pr{I0p0(lLv{C1V=)m#FP|a zLJZRTke!>-16vgjMO1_+K%OLAX@ciXWk?B0TnE%O6sjx{mXfEnY#E1uc^MHeMI!`F z7jRE)f=CMDv+WR}5sE^tx!5aZ3r*~Vohyt(dOS?jz!FEKGZ`|I2*StR3YfK62uu%j zCNYf7ji@1tElpxlT^ug1pbEK34xPfY`dsiNj^#CBN-E$qT?`eS29Fd$#AjuK5`^SV zS)6Q{+Qm0}_!_ldtwtz%@VD?2VvrJWX{jKHpha++gLDO^Go&!vgno+^3#wg!8VS%e>WqZ{rGQ@IQq9VPT#dX1Sn??c{Sd=CV3PpUtaYO?#4M&4|1y}~?P8tr9j0n|y z8;|TD1j$Jy7~v_#1Y%)`Qd}Mf3u3qrky%sXun?ft+7OYJM*Tt~VeHvs1q~W^hG|t` zdV-dmVr78wmk@E`uM;K&LMWX8=n6g=zJ4O4RAJX+%J?quI3)L5N1vWuR{)vamt(;tb1Ry998lQphDxs2moD3%=Ww zQmnOjxzITWe0GEjgjoy3qlOU|&`jxo2klxc*cM1&@@*Xt5cVuqAdEexhW$Az0X5i?03O~&nZ zvr?*7Krpq{8Dkq|5GDy}_5p#=NH_Dr4w?e17isKNBSFC81L9j3fuB%hfbwS+g4_eR z+B#;;6%^^XLa)rva|Ho%?Gpq@QKDK4P+qyt4LP6!f?tfM-PKJ-5K^cbUf4|WQRN$jM5(Y8Otz!kDrO6XR@EHP(C{IeKc7pL#>=9BqzBI$mgc>NRHX~q^^Wc0w z*Wz#q%s#owBSNA^BGYR?0m`k2#F8mco%pDVh#6pAW>7g2t#Bw6V=|{A$bk6G2;Us= zbM%ZT5KN)Yg)%(Gx@4=us55m?cDCC1=$kI$P#4?$H!T?K# z+KPk80YXW~LWWdSkv_;~a5b2kNfTPrI+9Qk;G0vb1aQA~5nje>lNjU-2G0-{TM@b4 zOr!BMQV9ik*%lh$iq+8XjQiNY`iClC0^J5D)vVNkJU^o3`!iCHk?zZYyxXB=hJor# z5vn~#1cCg~m_`^*TDehY5SZ3t=+b2f!XTBJRKvdKhBgM9!$!0`uH5eznFUBR98dT` z$Y6j0Gsi4v1;AGw1gW$mz*CQn#M25J_;{>ZBkZ7naTam}DNc$gFmoV+=p{b5B zpuZudgVD_gHgb>-;Dm@vBQ z(Ib$A2(2liOiGfdrEw`&j>C8^ATjGK8F~OAa}q%tq7QgzMiyTp=evV&yh2P|C!L_q z$ZZ);n&XX_VaALAJB3KjSW#w519dczDs(8B0?=JH>I;$OK82d&pb8@(Kmu?C=5&+N zS})0|FpU+rVZK-_m&EiGz7`twkiSP#q(~Ni+M|+qqp<{oMusqFDm9f+OBJ3J4UADF zhcd-60aI5kP*Qmko0t*=DoxPNU}1<>KxF`x2!#c}=2SUNEG{&vU~(d6nvt~1%CshV z(A}0Ocy14iuQa&=0Hia>l;GBY$}PFTs2~0!y+8wL3h@Bs0COxclUXK!k)$bz`;%H9M<#IyXm*=d%}HwMEFh6sw5UjA zgVwT}Lt#Q(51H(taxtqdh51wf2qp6^3aLkyazR-VaOnd=ihazWWQ%gufcB*(BM=wL zb7LA3(cp5#g*1Wld~P5`32^vK zl@s))X-MQCgLNd%G=sbeL9|dY3GG=rn!t*c3<3Xwo2Eqn`F+nn^L46~Y zD`RP~pWuY_d5|1Xcz{FUSOI&Ta0vA_gDJ7Y%~+u55{jN;&po9*qHG` zj&C{@lX^LzqcE`6LJH^v3<32$r2Zs!I}Au`$GqUjS3iNLIdv8qU5(+C`PnT7>k(5Mzk>r4)A zRN|xP^icB~I10W?@ZjsBsJZGy&_!?&L7rkk(ooNt(>!W~!gf1paaKY?wenm9u1On_ zyKt^UipgNT_sWzpj5a1$VR93;Ah=bNT#48~0jM;WhY}Ds7(f)L(c%QA7@vf|QHDk{ zBN?k66)Pa36&4wWDk35R!NDw0XpK(rE(Wk5mmLYR_#8kRfuSv<^t0>?gDXshcr#dc z=uXJLi6kva8!;gwMiQJ*0v?(qnB;7bB%%;Q0+ybFhzXIHE5!pQkVen(l9`ZvO9Dp* z9jY83MvR4!7@f%jgPj779X!2D=ueP!a;Wlyh%e^!#+f>!GYPB%N0JOd9to66V~J%# z2T>!8(jkZgPYJ~?jPEpC`AVt}Fxgv25m34(yzlMX0It0w`(b46N{tDL}W=Cs$gnmhA@*7WCHEqm6S8XZi*Awi#i>} z2CX%X62>(#9)c05O1D*=;w3;&6$yJmVntF3=*);AVj=jr;%G?BR61#f{L@R8J~^Ygt5>UdaOQlhw@SI2@uV^wkq2L{IX^BU&e$9$^Rx7Kg~o zMIvCuVnswIwo)J`z*EQzB>-LoM3R7s;Zi~hDF>yenHpbeKllor;Gptz{Q&qDFkB)R$8Q4tD9C`*u9!@t zi2E~W#6+eeHn6~x;64tMsd^Lw?xjpzMRL-NFsO@?^afrar16L_Odik>(#Z^6OI4wg zu_=X}rIb(!TBaGgtqLO?9HC*U^0~!yZYC2UD^Lh5cM_CrSjE#e%$u|+QvpqksggU% z4i7C6^w~5Kwh{>F1S$hFP*qGPnJse*VRuR6L@6VJf@=|pLO6#{;1ogQ*ygvGj0B0? zU`J?aLB=1a2%JtQ6YO?DsfXqa0<#wSc#bsicKk}fBnovVGt&Y^poQbZ=wP~v2r`Zk zk!AKJO$?y93Sj}|2IXui#|#GyiAy9GQOZN5G0;?*olq)6G-b@j;;~#VG43)rS!x}Go)F!@ zoOgv4W>tXbR>$}hi1g$G{F+GBS=< zzXUn1K$2v0iIgG>P|j6EPJ+)Ab4(o2(TD7QHbI)^1m$p1bup8Nt0x;-8U>CB`KU7C zvOo(e=;xS7UZ069AVbH9?URF|g-DL-$u=uZg+X9|I3P=rd<>(2Esa<$g?y!yL*f8OoH-B&U3tu$0j#Kwg(^UTrvNoPk7TAhFfZ=3 zDuJXS*^m z%U9!Kxu1@(qcKvLqTm3=3-xm{G1&XT3=z>K0wkRt1TpE12MBLeBPf`(7LZN@Egv+^ z`hdiur=u8IC>DW!2b@O$qoNpub~PWG9RR1ISh*sFA`IcU3K(-}trjPROpGWJM5fNJ zGKO^-dI)E8g*rOR6_9|nmS6`}SUO6BRwiEuvNHBqTbsh8BxMp#*zHXcRUu=*!jgba zPK4SB4uq0%5Fk8KA!d5SYDlRP^<JPUkstxXxgGFo}atcyZyq~2s!BO*%J0jN_O(*kjw4jWS~2fZg*AR^e6 zOtv{a7GRfTSxMwD_$57RT#ErQ+wDP;tVoPw6sk#9aJuUZP6^#$fzvqP*%Y)j*7e%!Y8I^|AVF2LMxdy(QYGou9DHoq&Q@ec}3m=wGo{(*(Y5Za;q5$JU zRK`&mlVUNZHqn_HShQ@=g5%g}I2Wt~Y%^*hI^9OZ1^s_^fGpOi`AoflOGKG2DDd4j zGZFLpmt^<`V}Ibp&EXVXbi{ zyza0#LI5ZP#sMfH2la9FVE88jfbhXZCdn2W~~c%UOCB8Yg7c--w3L=bKiz}Ueg5&_pxG(E=WCo{b9 zFq@rVQaF(Im2~;#;FuoE{t;VT5)zGy)6iKrjkJ#)MjLCL}FB z2@KSTEHMK-rWWv!2LkFCB)kahdT8@&=`hVrr`gm12J`&u%EyY zP_N;5gP*a4|kdA_HOoL}w_>BABCSIS;njc*-lr(g>y|MwJ$x zK4B$sP$!U!048OD5GYq#sR=r1Q2p|~Y+b-bigKN1hbIa7a{-dbT#$c4bqZ{el#59+>1cAq!qYlfEK!6KXL{3$KpL`LJp>&$l@Kzd z8BQz%HvO;)0wFk{15hebay{6#?dd>(D1o(4ET-ARo`{Gc1Mvz%V2~xS4C6qj_WyHQ zsbx^b0Mkx~H5{D@AZ28$(?Qp`)mBsi4Mnmw0n1JxA~kZDHVRwAlZO$4gAq;~DrcG*`p`C?8s@=}L6n4hE9_(> zq2&tse;Na1GBX1{TSBV$hfyCJh>M=MBSJLl7*sZJ-#Hq;3Q~lLqy*ragKTDmL4zzw zgpY#$i4F-RX4s05kQAg>6s||lk%HeDWZvLElu$yDU}yG*<6wevg03+ha74HiIaMs- z3L&GGLJ0!`R|l;eyCcC%C-jj>nj;0TvWA*+#sk`PBp^WSeAMSL6R9bc#THaa^kEg( z3U>k}MnUittOzo5f*uodL@^H_ny7j%)#e7KpO_29qC+Y%b0cm|T!F|qmXtK@V>AVL&Btxjh^b6i!@dfq>V{u3K@KFG#O1pl7c_vhu8E(IXqKJ#D^XrNM^B& ziYaDbGzLQ^W2Inb7K8RnoF#~6C>k%S1_7~E4hRmfhzm0aB;jb$B1nS-L2@h}P*8($Ab%n}2XD+U4g^FO%VGh9 zP0Fp#z?PL^xO8kvgcwSpii8vrNjX-C_64C*+MAF_c?7W-1z1EP5~M*GF&Spb!1fDK z<17xOgNJO6s7oAGMQA#kN(ba6mJH8O)ta9jNR1dIEeOwDf^-7}rv_60`z#ipLdD#KAkHd2l zAfhBHjspgSnS}0|l8LHgdep$xDl-8F`rv!P9b@Ss35LSSgEZcl+fK-k-3&R)8gwT( z5IifE$|xw4NtQW*X*Jg741yX6xI)lv0hpgxNevr>YPe8hAfFkO@DO5Q8R}3mtZJJ* zZ2>Qa5s0mb*cVmv)oQanPL;8V5-_}ELM);#te4;xj3yK@L0oQA2u%V5+&>zS4sv-u zu-(}L`lw$?a!ccOuq3D0&^iYHbl9!c(}H5M6@f0Y*%VCKG3fC7-C_>_=Mjk95vRF| zjGo6ydXgGan2e&4pk17lLK{rJJtSKw#10)o}Mqx9yLb;oi8w3FVBA^5a z+fxSVW~YI{R;96!$RH%s2-+~@+k{na2+g9Rp0G>wpjF3&{1>B=tMl7@3Pn2VQ)Xb2 zOZG5nQkIr4BZ66i<8(RO(?{HBOK3+iz6}?%@Ox<>0rS0 z05^{Xt#?;a2Za_U6GjtqAj{i4>L36IA+p}aQCOHN03my5$|R!GBup`T1Yv*)nNEg8 z&oRCt;PDxBMCl+~1RSubt6dr}&%$-&K@%Y%vnBa58{(3&JxP%&?9YJy7tHPvx*-n^6i)60;`aVagZ)55dO_(tNIz zmrR3rjn9cA6e)yfN4O#2HOk^D5>4(;cnBm*0w%0xkJ6Z8a{b~o#tXt1N%SBnWF&Jv zF>)Npt0IzvtJWk#A-X7nG6V@P)d+*nvHlW_??BfH62(N+OLDX0`gqc2W!vNi1s>-_ zQ>?&)s}zK*q~giU?%%6lIV5BV&2BJfi=+^CLZR!)a;3-3PSfp5A7)Atxmr2HYiIaE zYG|98k)(?4=P?kIPL&|XEx=td^VN_)VU;^#Kt2iSS%EYooPa=*kbpo=@KaW@mWW#j z2Cvi0k~-u}a36vw9*%>+Bb7oN5l6tIS!{d>2x{CyWt6Ce7$fN4L?lXX)R3aPk~~=? zO81DMN&%q=A_c7=IjP_XS#B<@scJqJ^qUZ~0ZS@`F$g9CJx9!<#JoT#08E%Y9`m~8 z6de2tY!Sr{9XD^FcC7BkxOCSXa1W^s1Fg+Auul82n5g~x!O1nee6wwN?xapWY;7$st5J{ntK_)ujvFtX~ zoVJ7O-69V8aG_V|56Yq{6ozBzC>I>k8kxeUC2$m)XiyvHu-qV*Mr1-d1js5m6rVH% z?ns6q3ZCvU-^qT~P9ewHR9$@|r=tskYa~(&5G56jvlwQPm`b96o`?htGrmZvmstE{hzeJ`1zHq%(P9=v6sZVg zNDPLV4(RYwNwX&gNy$7sPJ-z`z?vX~Jc1AvX5>N;z7qqWR13rND5ZJja=J02Ri~7) zC`F%kGEy8Vj|oEqXbOuZI)jZMio*OXMAgu^T1m#P23RyZnQ#lhCJ;;jwqI{n8Feg3 z>Wm6W)QC9j7RKmKmIyk9M!8D&h+aa9u8x2E%Hy=TOa_TOm&&G4$vc1k_U(uNm>V~4 zTR*(b{g3{=vF(6J<@i5j{BmTKS^Lfz+O*qz)k?fUywKV`SWz-MYq)Vq<6tUXoF3>*P9MP)i;2Oa64oHf8a!A$ zy=htf-lYrw5Z~WWv+!R3;nu?A-pV#~o8V*og7?BhD)I97H$mIOzZx+dAPY-`W;$SP;&oQ{<4?q7}-Bg&FS*~GLRm)DJR|H!e@ztCGVjd1L6CiT=;AFZ9 zc>u>#g9EFhg9UF*+a8%h(d}9G*hj+$7KVTSJ1oa*U;ngW8}F^jzpg>!eakPg)g$!S zg$a;U3ty?`-k4^tvGtN zr^8>ov~OVRuiXB1tGnZl?yJjJ*0q?{U1AsA!Uu2N%4=_OeZPAd`_fQZ-NG-l4HeYD z;BUWOIKVv@IjSFC4`1D@$L5~M~Y`<*Y{NovIy5H?`~Z&<4VEb z&V9G8Y)z(M+6&8G%AJ1Z(AK*Ji$`;vs=qPQkN0gJU9y{1BR%8tl+tqxP=};0Ja}M7 zA?Necb@-XnyK5tl*9DtaTgp#O3B!cj|0?dx-!X05S4 zin0wGtZ&vVd+SUiW3YEhqR;VGWZmer4S~`#rqaoUh0A`Kdc#_ruiSor_4#U z71e7NR-Oi7Vh;VTw!NwR)B>$zdDEn9aq6k-cOwJ4@$-?-t~2yIMlDBoERe#-wZO-H zrLcZUUGvn{Xy>}4wL@ur{v<*>V`lb`-%MNo>G>D>XMdq9o!mRUtKe4g+N-9mt^l{sm9<-*RTl}C5x z6`jXd)#7(rC%)z18ux6SMkuO$s-{5Nn4H~_o`qdv-MV#&a^$QyP!egKJka{X$~xsX z*+>_5xO;YM6=B2mEuSWukJrAHn|#Edzh@D=M92Pg-xWVq>wxp+9Y8W3%->hlvox3)hJTz6Z^ca34pIiU^sq^1_yQu27lAq02M@F=L zTZj6mHrHN?JYKze8dmu!<buEqne z{`4ttDZSjd=DV*xk5v73*T`k(+WOy|vp(~urOiijo#vhJP>gf@=Zaavp2$GS{X=D& z*!rKQ4B%(4FV%Mc@p9ekx4OAC$4lCWf9&rPlzi0um#c$IN3ZW<8$Nm#B4T{rXW_?R z_Mk0k*H7!NqKCUF`#0?PI7r_;c5z<`MrOk=<1By8J`BHn^63BnZx@&L-@6+f`vF!J z&dToFzkmE*@z1V{l}&eN!hf7FBm3~)RVb_q(>|Uy@uH;kQMk6g$m~}M>?z~M9jyJn zcHE9DrcS(L1HWf?1HW$g{BNE;(@!j7Ui|Iecx+1Mj^t z`eXj(&)R?6y7;kvckjH4Q|;A*PlWQL_+umZZ6=O>I)j}na{RF8+@9_5f=3HvcUvNL zy`D}}&phe=Jw;`?9VmN>YW1}3fn05}xVd(qdm($u!8OGn-LCBPcAPp|+ZHcR1RL|J z7iS~0KY595xKM@m4wR!kt$W7a_8_UVu=&h^Eo;!a?%6%)`rgbkVynpZARqMXa>-vd+cbiVO&p4`@mu)LvG40a_Z$lcXYFsd(zr{Fo zZ$@bcr*v}1lUr_-?KxIE@JyjAv}?uRwoH0^z`PojZ!9jWd~$0ytE+9@$4K?@4e+7- zShVU>nN69mx()gh+Ff0?R6HeIr9D~ zd~3<>?`q#FI)};pYf%3>>-V*BOXsqnKVv_FIu3JFgEg*L_z&G=G zL8NK}_+E!UE1mB;kvqMivL1KL`rvQJJ-z>)mTrx%T=~I_k;+pu>vBZ6%qMdTrf)y( z`eei9Nj<0VIj+hL(GzUN{Xu!pqU&yU?(}chf|c{9L`IuFR}RMhbH(4fGL>yxPVf7s zaR~F5(g*8JBPCl7tVJIZe&s4%vl{c&?g;(I7K!7z=+V85r|Qp4!xRT-N&MXUTEo7@ zW8eOqmhAOj=A8<*Bkx?&b75g~ZRyRWRWtk>pP7JOMtf3c4}Cy+Yr}4FkM=sdx46Ic zhj_!4`W|WJr|`U3G%sYIX?`kq)wFQU7T##MnQaJ6zwzUq8Q;O@xMI3H{HMAlC%WEj zJA1nA@$Prn25)}Z%6CV@*&X-G3}wgRbmpJh1&Kag9 zi@noUtSl?Y_GyI8Pe-1YVu>dl%;jY)2((99&OvtYu8*~ByEda zTYspoWZ^&HV)(neg!P}dHzkUD`dV*1)ux-3UEWfAC#t$Xvi0)Hjo2^!?BTip{4Q2_ z{ck~-cdm`Rzi$21L#qZPbxXFwwVj$9IJ63Ld7NWcCvl|g(E-c-E_Lr@mm)p?89p2pLyb;zk9m2YF?5VlanawYB znzSX1GdMOJQ`S-6s&8H5ty~3HdhE4MKF)GIcX0##jmYeazrgnpHoR}anaPs&4VSM} zAq&@Uzmk)duBmi%u6S+3fpgxf?`uU{H$M3szPM-f(>boaZ(qBv**|S-$Io>;x6RpL z-LUJIe_bgSUNO~AJ(8FH=7S57(z>-4R9+fifc0(EJoo~de)zn+*UGuOAK!m}x*Qv9 zid3QO|G99f|IxViL!`8>WdG6H6V_STbw`uC+lq$qdv(LF?XFuk>C~A`3HFf%#MA%# zIwgE}ph)u=J2%h+tH|ESB<<+VMLoq9wqgH?lQ*hcH`R5UN*_JFOIXUE*ZtG}#+C~7 zxvl^En)aW!_gp;|A72_g(eg=K8b_M1?uu_6P^>{Z0v$Vkrn9HKI<0x6cc4;CUbbTT zxX9_z3$e$d=ZagVz2_fhG`y63_<4gbK# z@#lB{rKsN6T>V0J^2?K7f8pta?58CMKNfR;5FqZK>ptDc`2o*8y~SGd;Zgfv-^hG& zVeXl(T<@}NCoa9b^tf$snEk_s1+9P0 z-Fq$Gd#G@vbGr1?j(sD;eM|0-&acUKEbV*Z)v1*W@U6DzDwAJyOj}euZrt^T6RVq+ zjqH2wy}nvQpzUt)QNr`{uj0>luPpwgb=lYG;m67ztvGl{RVdv%@M}~1hS%eBHd!y! zxLT?%zq0_}wc#E9#{9b#YkvPZ+nv5~zh0~Buezv_%DyI{5<>B4Tt@v2`Y!R^?!Z%uXxXo@eTRLTc+?q_?Zvc zcP%}yX|ESc@|b6SeWYy7d{=*d6J_*d*GN~b>&UN>2`%$Bm$@R_7aKE2R$Q&@zS|cR z7u6M=&lfbKYpx1BH_CU5mrTf9tiAVocKP_ciQ_&w_I;~&(gsb3_V(Vb&L0bM!_)NV zazn+Advj*qTzY;!eq>YDd-%f9&DnK#u2wd0Vb)j{G0T3uV_G%nZ#%cBW(NB5Q~t94 z3(BT@Yd02MedOlY8@=0guCl4}n|aG#{cgp*;XSc)Pj+`Fl*oZ=Ew1X8vbuSqp*nO_H1tBj%<5k{<#~jsT>GlmyeBMMQ|ia-E6yEB4VpF=Nsqib zcYR*>wHiZx)qh}ner&&U`cizs)74MqO)QJgn=$>&ZCz^it7${=?C+m06WxA#G11hO zTV4G3-pT3I$ItFBYuq{5SkQd<`Ll0-CfI*f*;|_&&|j)G?A`EO^z+1MO=s>X8o$wa zchA+u>szVi8u*mAZq&BpWzoxHpK(svnmz+zk>Nk<&dGwG#Z#4&1l@H<(KRQuxr#rO zJ-W4Q)#%FXs$19k*3Qb^N_X8E@}y?>{<`Aqutjw8l>WgxxcuYZJ%YBKCwotx-Yveq zvv~B%3G+^J*#Ko*R?@vH=gy%8e{cMp;bh#`wA?MJs=xcok7z&M(A&5;7#LsH`IM)z zcFI-H%-Ot3x`xq?AiH--encH$_Mn%QdhMe?SH+0y<_)N+i$<0t3RW? zcHZ>omSeT~a8Z^SbMgK`&E}|M^8BVvQ@%#UmzIzpE9*ob&zqR&-$$ELw)x!0d2hd& z{RTzWa_KH`aIU_KYmZ zZL6={)=SOKJB+T$oO!Y%P*%6;gy-J=#;@llRrBw+MxK2a-<{WZcT4MMU5gH)KiASu zJn=(o_eoQJc_5gXX8224|I!^(_P^MqM{kVK}iX?mvXv0u95 zp4oZQJDU8R)O_;%O;c+2%INqzzhARw-)$9dRJ~Y6 z->Lk5!PtX4aBOKH^?Z7#gy8q>^U##`k-?`Gh?cH2&L+>Ryb0J z*Pce!O7=1o+*-7#UjRItprXJD{+p~SOfb64~ncFvMrb(QgC^x89lM(4HT zC9b?x%j%AZ_N@GN)eYBG)BfU)Q`BoE|EGG{iqoo1Q})9G9GzKld-=cRP281fY>Qv4 z&7B!8S+Ms4x^l(W=+{r|8pT&O;x*%c`TDkHr1a~d^#_U@UwLkP`n-8(MMt`@aSGv5 z+4Vm)T>0mFem(nebZy0ash zFAra`jLf?++|--h5;Kpvf$h&F!soN&1mq254Lw>&*n{R_+hB%Z}7-PZr8Pq-*S3z?A6cq{Z?Un z_q(j+){=9zU#$MG&B})VbJr2JhHo!Aj2?cd?9uk0lkH!xT3vG{kG1*0mMdZH@tY>> z^8dUN3p<#M;zBd+!Fv4r#_>>h{Aq08{^DM8`8!LiCZqet6YD))y??KH=hu(k`>|#G z%Qec2XP(VBJRXUc_zykUqQ>FlEEj7p)jz3B^B*aD^v;lMSHYC35$4Nq#~qwdMTbrH zzyEJq!IWRGO^2szT-l@JM$;R&&n}yO0c~sY)!YTd!(|v&i?o>C#iTL;| zB7DL2+pE4^dVN_#ag}Clw_96O<`^k%JK52?yA*q~@SCwJV)Mkjw}xI@@}P<^Wna#F zHQT0bYVSR5K0jVN|9)4byWW*OiWc-qrmxMsbbNbP#aF8bF2hxsKDMg7Iv19q+_34( z(E~5%m*=IPzCK~u*UI0_&FQOfYv41sWiypqPG*a`XWm-ScHbs&?Cejr^dEwySMgKJj{0}9 z`zGXzkSBm{Y1o*Jfw2*WcNBYum6d|BUj|qxpN^*cI?Ru_;q^zWDmxr_0{V z-VT-2uff+0qMo7c<%RDbc{|&dtoryt8Dzd&P})we5M5q88God#|5)9JgUjJm1Ot*A%DuQ z-v+vRw|rST{gt;C=MnyWejjZ65!lvxZkyU8h4`(HdPje*&9y2c#P#+SGt2b*vpWX! zJ~_X@cx*N8?Jl}MUUYJqpab6TtZHedWqien$?x~ZF<;NlrN{qJP)R5m3|(2aRb95` zi00X~^OyA||E|1cf~s_ALe+C8XE|?wjUw-@D)XjiPC)T z*;HSS@BBpHx+X2^{&j2b$sy6zomW0OIkMu|A$MN$la?l;Q$4f0Lve1+f34cPv)e9A z+}v4v5)AuK*Kg^DBC#)j%ibz8G5JPz=+0f~w;iuEQ%MF z$Ig8*ebwlKDS6v_O&@I3&l#9JxOQw0o^#U_qHal5t?SP%FR3y$oBvw9^~m5x=hd8O z(&n12$4|ARtw(OG@8})%EFG9rKfAYgJn_Lj+VJYwYF>G@HiDm%bUgJf`h7w9mHls5 zlUw|R1BZTEzG-G*{**lIKOdASAxe9Jp|ss(xU#9XeCNv+ZGL%0)_eT!pJ|1sx)zlW z4!*W_Xzbk-!5VI;q30W}uM&)WU6u7dXB^sZnuF7{z4`;2yG#Y6TRY$PqLJasTe26( z$8!C&vPYx%&H23{YI{L$xrsJVYn$Uj<_?}`ODH9&fD~=)Jc6%iE@B{_je9 z+Z38q(8sxy5ImC3arW?W#re&x58o|94vL+yVkLdydE#0t`m1hYIA3Ms}!R}R;*{= zzwFgtp>qX=lMYrC?YXBq`b9QV$hT&7%j_Y+BW>hyAI)6NM>g3bc7{?Dt(Td|GA1;PUdxzrwMtty#8waJo zAD(_c%Y1dH`Pb5&t>3S?wCjsK6Ux>+`@-2Wdq+Wb+SF6?C*6Vy2+f-~P}P|qmE>(| z=pg38$L{p*>S+6M#}Zxg;*5Xpk$=vg;_iQ@tpDrkyzY_{Tm7e|oqFR+9d$T6cFM6X zzUG?KwN88cmrlGtFMWS-g!O!?>h2IfKA|Xb>O_aO=+9q|eV4aP_b=yqCtp2*Y(J8p z?Syi%_3`Sy?q44)KNoBBs~^0F7aBSU@E!&xmC=n&|Krop^RULklRE~l_fF>2??}yl z|0Y!M_czrQ{PD-jZ`Xaf;|{*FyzkiG)8{3;vi=3ay4{{LHFwhY(+f6E-P!!yXTZ{B ztzX!)?_Lc~7RQZE4Tc@u}I(tU1?LW>0n#^CrG{vG(F)4K;*K zQAvsN`^$!#roMiR{aV-Mc5+^UfpEhxx8THQu;nahOrN>5Fa3BPHhRAppE#1&{DS)O zho_${n>;>$%8J*suRnY9z>XEA{X<70)sHOuvSR+GzOIrA$@GP%dtWMB^B(m=?&#r7 zSxI*Hq82|?#v@%%H}|b_H4F|p9~1+~dqqnoUkLKweKPh+^+V$-(iJsTw)az2ljpj! zclZ9wNvJUT-SIMPzAPLt^$s;+zb#$VEWch`@nMnnS?b65`mz^m^dmjBMu^1}+}KF0N#2ckaJy>i%}<{^SFxvHf{U|9jVKE%6Qg1%^CAWBFz{gq*l(s_&8( zR2D3`({SYW(!abmRyxe*o$Q$LRjKsfXKr{RulsS$^ixt#;r=~)E?qkw-MwIY=>&59 zt!Gl`iPOIZp3hVb;_Pj8^6ks^q^k_)ul3d6T18IH#^GDVvh7eempxj{x`2*Ma7{0p z^m{J`#sU9l<-hh~=9j)$|L2#7|83sa@78g@GZoiXOuO6t#}|H? zvTF18U!Smi;d$}>kDHZ`;D1IITz=@3S?1)uj~}x)ZQZu4xVRXf|0o>J4A=4&rpaPU0>d|%=}>6wch);FEbYmBnFzKujl2Lm-YRXF>~nM zC!?P`T~Gdqrl0Ss6`<-Z`ugeztA)9<)}T5!!Q8PV@km+cIkbBDA@un3uVvewA{K4y z|7~s;;`_(_W$a@7(bK*O@W{Y-2?vYa^Kd1e=G$kMJ=*;>diF5rZ1QvaZXHH@USkqF z4-6Q$OlHf-+_Hze6o@>+0r))C^b^-RZ}Qx(04UtA@@xh$VQ-{w?LJ zVDdiu`?&D<%Bg)@W)caR{MNF=zB(8z#Cm zZE4mO?zwAwX*UerA9fcbke!*@`zTaQ`qpT`FxBR@} z!N~wW1{>O+)~7$cdtr3_rbfTz-fMNO?|;kQ*Ip1#RheIm^!=Z*$H-rdG+)_B1? z@@DGIdB&43otgX8d!H@F@>^U7e;K*!)v(u=c6$G#`ocTw#XCCYwa=;FbD}brsvxf! z+E#b!c5Umr?pjIDrkZ-=J$1+U%QNov7T zC!bt;%QSrHxHNrB0{ar_5PD$=v97xR1%FMC>+QzatgbGy{NwpMy)V5RJUwl79=5Kq zI=ym*Sz4AoTGFN8F(fcvmv70gT2{D!V8lEh-$B~;KVG)I?989?nx}8RS21`tmwqR^ zyo^bFGyD2GsR2{{M|j=HonLDjp5GevoUgk~?~cCN=*Rj(NA7vpODryN!<=0W)3MK* zmmj!#({$_nyKs1i4MLBu%z}cxEFO$D5zjRI&?vt)`uR1XwC9bXN?p?`Ol4KQ`a^gfVFNtzzokj$s+zS#LWA zW?*dYRahOmPp4YEBS#cB z{OX_UDz+w@rb<<>FzfrwkkUp{mbP@X^>uR@`}V=2hA86EFQE zo4M7n#GE5;%g(xRKU$w2Gz~UX+%F=JeU59j-pgyfYv;e@*;N11isvx#LTvhr{S$Iw zF%)-$fjoSB*8g+uD>HAtd~w~ABj3IY``*rXuh$kW8l2TV#P2t?JhPyC>KXLR)d_jc z9gBQ-|3AXs1up69{~xE?*0#3X*0P&o%gU9Sm06)6ZS$5^u8WBG8l@$f6Y>V)yIotE zkeZsNu%%@tNT_JuYc25#c>xj?D=(<1q<|!d{14XJ_W6Auk3Ww`kCgZO++OGPdcI!g zb-dzn`yo64~Q{*f3}&fCg8GqJRR8ePnCzuB;*a1Y%2y*QhD#*9Cr z-5aYw-24u8?h`V zKy!F%IfeDlG-g&G(w}i2*pEBF9@vX(n|J=2DzEJKCQHW0IH7}v*5^_~^Nt>F+lMrt zo*RP=$XL5OP_ErV6|cS?}KdKZae{X&opyKpXnv4OCk9)85rR#OhoJ zIQiR(206#aV|PB|@Sn{(e>tJMNuLPUpJrQ9zz(-W%$<4&&$%zYm$=#WF{yX`Oio4d zSCRUg#&pnYcbT>i*1pjx-!yTiM$jN z1&5Fm&L`YkYUNB`n36VLu+?zCwF(BeraMh7WYU1I!v{a^lvOeZ);_2CBQb4nYw_rh z{TYa55q#O5?hl@Ev|u94kM%4GJ z1JDMZ?8C4AydLxCzq4SJm95__*()CS?w0ZI`+ab}?0nUuuScoyN0&))y zPK&^T4HmcYvc=`k!Xj(A%ZrA=xtq_|AVrmf&c5QY%23L=Z^@K1Xke4S$G>-*AK6`c zWh5_FaI!X1=@x->6ES1wSTb*~z|`wu!<_@1#5l;{Hp>0nDc(kIpuKCr3fkYt(ms6^ zxPo17TMrF*C3q#JZJ7n=vN38#L_StaYA|gEUiV$t6RWh3}?+Ij7Lk%F>Sbs`9!8j+ZV4t_e9s%qnhe*Mqcq!&DIjk{dlnX zhN{QWtud}BINmkk*50tLY6lRTysCP^fnYG_ktu8?4yEUoWmVQo%txJ#!S=0 zk7(&t)Ux^`7KP;FD2XvwTFJ9G2!r#o&nME=T4El)PO-9+8X?c3UAn&#+}=1X3!!%Jz8bsV>= z)0p-k5fv`CfV3L+le*=w?{~D|Ze3LsL|E2hY-bg;$03DP6dGF)kMHB z?R*ekY`CMnHEknoPSeH1p_V>(^1zpB`>kL?B-|&})FV@#v|H1u&KCZ3TR498yLA>x z3SM?J%PbBU2n%+6m$j63Yt*~b?K5x1{MhH=(F?64$GZdyroa-#rs3F;dUF(p_S4$u zoQ<;Q9IdEz94`{3#OOs54~7X#LtE+4`{{h}7ZCe<5f>tOAT!F_^v?BLO`4EbMmXE( zbz5ben{h0#7%=5fX>%vSKsc%lYvXiG1>O+JHRJ3<$4|AD;joukrWN@X`zQ0JJBIDI zmgDDu6PDpE(Y{~$^;_ceSs`Oi4~>)H<v}; z#H{DxF|`3NejDe6%UH*)fVWPxQ8>%b(}<+`<6cR;s?H7&YYtYW;?uPqlkAv+U3)@> z2b?aF8UnT2agZ7IqH&*SH6IeMNp5R<`f&T_%LhE6lS3SWGT|04wbkzu*tPhy9k+jy zk;fPiJ8pg4OEl>k#>Jx%Kdc1u|I-4?+jOb(rj(8pr5(G`v12qoL%AI|)z5?hC`8{t z4jujU#VNx?^upr7Ex|k9q}16r4xJe0sy{NnwTegj?)jf2RK~FW=e&l;E&3e}hE4K2 zw+>Fkoik78D}n|(!~{xP6_oQnyk*;=BocWVD}ZE@K`O{PeyfCh+7nD+OkT@;k9_{a zJKf7&X0WllWNpPEllH$z1S^B5Jm-=dz8cbI4gKz>+93hqOV7bJ9WQ4PA>r}X)aQwti`STAPx9tb%-zS;9&tM3A@BngQ2FjAy{x*`Id zv4Cq}2_GJ_7&z2p>zbf=%dv~R=~2$Ev&+p4Z&+FMiSe^+bt{Y-YLmtl6e)j4i2}I@$Ieb$@Y?zxq zl*DXFE8BY~1unm|d-*|h-iyZMmL`aOuiSLw#4fpK)r=<;ojPOJpC z(I^LOT!GzG!s#E^kEsBxE)yJ{bu6JSS}pGcuYxU`Z-+7Sa3kW793D;SSSHD;b)$o2#ljPi&LUMdVpmthg&ZPTi83}Y;>z_Pp}ukzI~4d z4OIZ>`;&OAj>^Qr8nowMZ|Gbrq!fQb#tE8;gR9+b@o^UXbkpVQubxu{>6xO?GE ztOEBCEh6q(EW*9R{NTb!jmQ*$oN=qh_<3f&u&Z+fWGM_J*eC1cwH9Fi2e$8Iux<-@ za)FQ2&sHm7Fqg94Fys5{KL&-Lfut0y_4gs?CC0DL7&kyIo^fEu-?P=MF@EFm6L0Zq zUV$Ja3CnYzKLws||0zTF(OkA+$&UA=;1Ku12@+8F{fU2NE&AG0%pRM*_iYxme%a?g zm@wOaOzu5yWqI$ygJtC(o>*!f_;AVbk=4iAkD|MU@%E9SxsNYBxiRV+66#Y}Fv)u| zH>b0J3?IQ>vIPvZLElHKpOXy<6w=xyhqNz8<;7BYsexjr_~Dk~20CHx{ci_bb>Q5s zT!sBsFoNO>HEiDE4LR|QMX=*gE_~TDH`=={dzD~>4;)dZ50c@_e*1oy@*eC$G|A?| zI+W=r&;Ks2+TJYN6lF`YS^sC2armN9&d66ZSGRw@=+j_p8S4ALis3~X$K(4!#ZN%S zvn!8xb16!6J(%5-A(fLeKnvd%@%-VkEJ$3|5pK(xSy#)b?Oz3-n&V2n&$|iqW%uXT zNbSSN^E8g*oU~&+9mHTAHU}|$=TT_JIqU-)1^HR46TD_U8!?NnL3PeVCPiWeLvfvFh$PH z#|gb;_*i?ct9b}5-L68czQhl2zfnF?K_0$BqHIvu6@&4Ap9f@p60Df(%N>p)oxZ7< zN71@TOi}5eO=;BmLr{^tf6V!QKW{|F7V4-uf#O_w2X0aC2 zW~PMcJIK65t#pYXrYWpMg+&xoe$~4SkCfbT{ks`CC%E1>l|0-{7>472<)39$JP8@B zT%A4?KRt`*%e}0EPF_(%VK*Pe$Z237D04 zP++G4^+sjC0yh6G?Tv1~QNhLc+i{CNRRIfDkG!79cTkYA3=l^<#CzqT2y?wqYMfsn z`AqeaeI|*UA2T`+*D(9Q*ujjfE>&ZpdA09-Mxy>8)eJ!xY@F@K(A4ufyPRFq_Dw<( z(}YnsIaceeyO_ApBaF1tW8uXsDS5mO+$g8GXCRPbxaYoL7(=;9&|qVVr8|E$f@Fir zfXl0l)@efizsd$x@)ke636yDsGtGAeO{Z9fT`>cNyZ{6mE$S+Z=U-e9N>h_sYY`{2 zC^6f%B7V)G1n}w?2ATN94kPo0lCH0P-ry|r? zTI*H~lz4KX_ypqniR&o{uw2@t(JWLj_)nWje&&?jHwA~Tq~GHC%USS=5)n|@dEj01 zCU2=6EQh+Xt!O3qaoK@$!}6m9h*oBSAh-$IfgEN?Or2)TT@58--r4I#d(2c}DYlF> z65775c;LWAE;uaI!7-yi!?Q&gTJ&&@E$y(R$?TMKDzR*sDJ~ey0mCl{I@AEi&(?<+ zYDC_)^}bq16exyKgrP13tFWz}G@+PqTkx{=exM*r*1(;8aeDsC+4=UsuIlNc>yQh|)BQvO%WLBigxBb9zxCOob0Ahjr)x?G|tCFMdC!BqtiiIM>tRMeM(& zlsm!6ko}&YHrj_{u`1nZ!m*k@XyQxuE|~`_ryY#{O;wmA@d!tS&C1%ex_d;!h9`l9 zgw}uN6Z=GGOw-)qX+4xzc_*5-(%7Ar^HTT($1|950*&|YUkYZ}D5(D}+<{A{fEzzP zB{3)w5o8AN_I*noihaxFK#M$HYtgc2wg9xh@S;Wc2cRS;)RUY^8Yj9YRctnNjalu+ z&(k4@QohPAZ02YlB#W{zYLaz9G6}IKj8I~`p zEU!xAv7n~+jE<%e%#p75{+_U|BU*(HY69v{&A|_%}?7j{UC{;Mu$}J#*=kBwz`@^O~Jjy{>o%L4^gTW%?k%=%db}L?W4R@xIUB znhmtaRTq4 z{$k6!~xM24sz0-jmTaQf)$Y;-0+*ODRqD-rSNsZG;R%zKcZ)PoFm!n>;#~; zQ;ltzA3KoA72<5euCn6u2OZpB_u(WTG4`EXkN52yuoJ1*gzPQU*za!x-nkS`?8K!& zSwLR*aw192!0?`r;At~hd?`;a_6#QOS`gu(;ha2pXqoi=Hhic|;ywHtB^>G?*y@4ZzrP8CKrHlu^S{HOuOMo#%ewcT znfAW zOGXae&7`+hYZQjWJ-@TjbLH0Bxwr@mbmE+j*KgRXdb&*;_(N1pymA;_IB>vP8E;ch zH^h#;(#S#}6c;HK8DdqEaY)C27Bui>P7ZF|99V~sxD(GWmB|LU>^gn=*X_hqd$?@A zEf%eBkz5ghAmjk;-LfY~X<%I+4y4X?ACu&t?AvP85Z~cJGo0e71A#P=slpD7oj3&W zdN08Gvh9Kv3(^gHzAXASZ*6?gf2k5Exihgy|=w3J86QQEiHrW(QgD){$L0kDKK zDkcgeK-iL)d1BHrC6at2EoYQ7Otxz7@kYb!wvy(6W3#<>#U2%d4M2%V6DcJPPX3DY zdH8}Fx(w!!!V()~JjHL%Y;?W|sU*80l8DuaCsZh?)-^ zfTQPmHe>~(_>iLBcFDeFsCgas77D}XXsDT0#@GNjKj;Duh=H8|_gZk%E`zF9nh(W2 zw-bV`3lyFRx&T1%1tf5i3$LlL3x3yX18}ndAmW1lp9gP5>;QTL>oK-I%2`0MLoQS> zw_w1pQsK)^|8X*BG<~5-h%o3fXmk;vCOgoSsjsq=mo#yDuDbKhn2iC`cR+u( zH;rEBWeJ)}~m)dBImeKk)2J<|MFhuxsWBbh*TZ}NWJeG@7t@6;j#-)isQ4^umF zt_4|SwVjSo#lISuv%s6e?stqB zT?T|(bO2ZrK2Pw7@>U10%+KX-13t@z_Bbfv)f}RwZ<@UO|LVt0-ivKF$@wF5^kiof zG48d?`z@#awa>Xe!ddNe&ih!k?`6J4)BoKiDCw}P#-n}Kat#Gu{2FQypZ-fjcHA9- zZ*hb+rYK*|n(_JTDnzT_s%B2L?5uf#8()icXD6%b`nFgNk;Pil5rO=!<{<5HM-^{z z+^NEWP?i7cjD=pNzJNaM;H{1S7k+u9*8ImUVlQ%aph+SOZR?Q&gAK~61& zT}96!tL|!Sr)T#=aLuC<-eqTt3sSJ)Jb0e=c`iB?sDd&|6YSMJd>Y^>zi9AUPRn6F zslFFSeOcG{MOb8gQL&YSZcKB~_aU&k^)z^r)Ma6)qkr)HTg(kN#qoqeC@@9Y>LWf% zXxkz#?G000#|Ow(&d%O)>WeH?JoXW%k?pz~_g9*nUuo2_>5;e1!;N4}ZK!u*TMadK zcTSTsJc|(;iWe$$R97C0LiD)wFZJz@BZ^6E~el*bUj<;g_4220XB0)KL zdEFEV#N^#_b+4`LuFiJoer;VOa38+?^PYdC=qymC``{?kTBor~{u;OTSyVNS#tkOh z)bsm>PwO|iA3Da*NGX<$NREWahe(qdX(bBl{-pq>!R-o=U+^g4-HdHV9XX#UAdPTD z1YUif`pKiLh$BX+m$i255b!BdITcDLw4p)-<^(Ez9T$jFcY|mbsID_2xLi>SrVZpL zzI4zAg7EI{7PaQY>yQw?0Ga=J!RxJ&0xV^!HNikyhiLC!TT3Z^<3fR6hmn|Jyrjvi zNBF)pF4_VBAe0Znr(13e{9BwpbcW`juxMW~%8~Hhfjy4`^DJza`O}mT(+~E{(}Bzc zTG%mc2~7Gt$>#U25uz>Qt>v)D%&@G=9-EM&sGK~dF=T=r0kD1~Pr&`hc?{Ll(zX7c z?&W+e6q%OlLvkkBz{&v<{`WPo&6GpyF5xwI7c@kvu~V{lo`A^f+i+E72E6DTAKjhv ztLjZ)1rl5znf^PlYEM>`ul)5y<}=fdpPW24RT4ifUhlE0(&4HjVF=Uv!%rVc<_9t%z0MF< zJ2T*2e>=XSa*mYD)wmX4s>&0)NHb4O(D{EBDWF+-zoDgd0Cu4$ZXz8$_i_m=KTFS4 zj~UX&Ho(D$jzIbjVo@cxFaf9_0%QZO;JT#X7TwvY^TUICtLqd}Zg< zTrIC!Es<#Qq7RpE?!mRJ7{$}30*4BFD{Ap|Cy+w!<42E_GEEtjXyvkZI-bd$AqADz zoRinC@g3v}*cJ1(Aiq%areD^npgR9}md`5n9p2Vx=`*f-dRn;)AD zI7OLy`SNVNRf)xTyR!0Ya7*%854cx$XQ!6Q6%~xn`?6x4>nmdWFhSSU2?SR?S2hN2 z?~Xu}em-1~C0|cGI6UhLq*HFyfeDQyf5A(|*~)^!P30(X>G!)!CcR2<0L9KA@`7O}$zguJYcX^2zAa#6P96`|*X#L+}jT~*4>ly)^z{K;2LdV8n z<;RtaO$6!m13m5X3NZg>xbs2LgUAiM#TWL1Ti!mC88}w0NMi7h27aC^t|)Hm3c*LX zgy4lCDRppj@5h}l)&X%NQOJ}S(ByYykH?lp53E4Z#xHn_zdfb$!?V1*^^t6NeCOSO znc_=bMo}g2kYAcnkHl?=aFL+pbrC^M+B%|7H>{h|yfkB3S<~$&0|c|(H-4fkS4`!g(0(Kel_ks^`=^zY z=g3TXvvcS444)$^$rEY(1=g6}fGq#~i9A11AAe&v>A+iScE(4j!QfoSvZ2^&l)UD2 zE!Uypa)D4$TTUa9glRtB3Z00UI5YgaY_3c)hC-(x!uv{tl`GctH`X9tfHb0F5K*=K zCb*Oo=`(t-f{FN9~2%BjeO)Sn7wpG);Q-fT*I3?DZix0)rygVf5)|>MIJwlZ4={FQ_}Tfl>eR0sviWwe@Pl#U-%s zO-l{)E+N25uYU6e&=`M1=s%F0hc+xbe$GvC!d+8uC3IcDLgH&+t`YsTKt^Qy79vYN zOaOojw*KCM{>DauKW2wkDfB+Bs(jHHZyW+3GkQBRmYJN#NOVofQd)r7g~2wA4`CUQ zV7}3TRrTA&iv^RHzE{Wj>nk5o$k}0$@R@mbDt(~oA1@4pJ^9X>r)8r29lY`r`|c(I zw=qV4-g$TMQSZ zn90v5?Fr^(!+&IFHgP5eZ&c#SJoyT2ICOBH%d`kNsi`jz$0L#6s)Rc52RFk{nYi=P z&KN+naE8u`z9)1$N!@^eFx&}mQ6f|qye{|Mw$>5*ruNr3HJ%Qlj$X8gP{bAc>mgDu z?~#&4ACjlf-F(qaZ2i8UK0L|+oz`_H{zVL>s@FbRn@8M?5X~>hF3MQEkwZT$n|g_C zFHK;j+k)RloA{k{D@Wd^f|Ur2oLhvbHi7KLyMU=Qo?yT8?a*?BXl>Sff8{)Ike7x& z#IJcIMC{)+aQ_iSw^^{(&pR|RPmzLa;$#p3gU5xvGoHXtT*aAB7;?e=133MDK}RNh zph-1K)l7`iM`Cx`cF=}v>#lrR%=AW=x9{=2nvfK<2#@^9f}aNYAmBZPZ|2E*lx z7sJMhzhv#E4r0A;Fq~LFiNxtsE_MA?iRY=&Lk`Zgl}tgfKU>3Ylge^u$1}|2&_7ZM?MJ`W_5OJchu>JX;MBjjnqRW?_c`>NRRbVKTKwT( znf-o?zk-HYUeiLd+95>a4cG~w#2+70^jfZN^#w$mGh{Phn9-A?q1m2(;bC|4=&r-E zJ!Cec1&5w{rHt@0NgBc7-E~#fZPM~hq@WwKsHUAW=($n0!JcRVV_moYA+S_n(eg?o zg_i6)=s;vvWY3~5nJrtNT=`j}gKqA5qRkdiC#aazWt`t~W8nKqSn)dq&~_td;Yru% zVRz~#o`jxh@L#-gskzZc$dj4H{)^W_#yIG&tk zFMeOi%d`tgOtYVFBn{vU?lc9(wrbnu$-F@=J|GhHE9-RbHOjTU=d}CfR;QS^bcKEe zK4=!bz*2p*ntw$c-IVASr#}h8zYDuSb-s#OTyDtFNysmjz*OUW@p)ji(d;}~Ok->J zcMscW_7~=odsS&*N1N%OEsXBDx2KV4=%Bi<8RxiP07hrF)OaU1nDJ1NntD7CCM~9N*Rq!t4h_KRs5sH z@-BS7Ms9`kgNiTG%!)Kvk|UXq^ivEhhm~=H41?nXhp6c#%jL5=9ASp6RyWF;HsEU{ zm9)f;F{Fc4VUU&DELrN!9@wpm&Lt%`aJHWI$s%ifYRmjkZ11>qnlHn|i=s)KJq1LR(us2W%E8FQw zjaI8u8P;bx{FYHGtDme7yQ7DSD@Jz5>b8I@7w8nqwKzJp%h+);y4~3sFy3L)aJA%v zcDyn4axoId>T2YObfPN%VT z?lrTb$J(m0Ml9Y;TrrGAh#MilUw!PwepRE z$O$BY6R7&CCD{8z^fYl^^o&zjZW%&r@Qiis9uP^|LKGoM0|@0g^mXjc>m7)LyILwc zA#Z;47T)4#5hMe}`a*l_c1GQ3^z(zY{E?CS<;|S(o*dTHQ37*>WH?>DR*c`6C#ljV z0{pU8OPuBAF#kKXZm{c3xrnG)X=H!BuXsbxnf8mpvOR$ONV+W+RiC+NsH^n09Rp{6 z>O8{l*jW4_u8JY?RdGtA+-ZmNHG#djPF>ZKXDA?h#vm4V$|-Uz+6`b*d)IwC87sVx z=J3-kgA_N??F1_Wglexg^441S#2;nbr{erNfk#zaxU;2;et#EGkXa!_*lzv}Qf`V_ zOLihK>&&?0i_M`0y$8DV- zZW3$YgPLzf&E#Ws`BpNl?-~&x2J60$k08b%-Fh}V@U}+Tw%yevh>j|7Ca}mfoin1O zPpTWqV=E^1lpJinU#|FyCe;*N8Mu?#8#sElHhp^agLJ^d`kHj0iq9%<#y7>}60CTRJ>FyY0f%O3)U{TQ zr;H2>lYWmD3Gw?U`jt{go@d)Q2-n4b3sqF8LMDewsRl3eL0v0;mTCz;{@4 zX%9V&PpDMvtwDee47f;FXUrsCg+UA?K%g@MX(D~$pkdUvyPyq81FX~0n#}HpJ21smke*A z94eSJ4CpMoW7_luGhl-)@>TcyAWMOKctC@zjYtNoY+1a_&wuCuR|Ca_934ZQtkl(y z=_aRkhyj=3E4NAuxk2Y_h$o*+PN}->6i}VRE*h?}u-5FA4P(Q2+ezD`^st>31%p@% zL%rr{cLE{S&<-ck1btHgB_lx3L>o%z9!;)Pc+y;rfnQZPSm`#Jg>#)e?19=GEBGaP zbLsx9fMR-Nn9e(Q6_E#(*8}PDcUVWwd6`+=w^mbDCX7%fCTHzlJ#GUb=E4C;0Qeu7 zXFfl<*bGX!_wLsv-HSfhvFN*1zn$G!zNr1T3s+owKfbbU+RVK06gMbDUwL=jDsES7 zRZ+{3KMLt-iu&aM+ zaMEU2It(q!4ABqnVhcuNkZ z4i3s-TJws2 zaa8hwPd$UuAzXS*h-J@}P|sQ|T0+C9+2-g6rwKOUXNjj(tFht{rG>zuM~!9mp7?k= z3pdmVtO|y`VV1PE$80U?J&}WUjz>%nrun?Mtlv_p$Uo~O4y5^fr^;Cj8%`mzo|`9{ zVEq|6YpHN0px6Aj1h!Vf@iF#LVguk7{en=RI9OTjuP3Yghp;;4IhA&ASZl2$Q#8q> zRthYVD}+;$;j6RuG4oxmoYI+g%AIa@y9`Y)8YD5>ar7S?VKD2LsI*!2nf95jwgjf$ zv0Ou{^)ZwVe$t+3+5OE%-0Aq5a>U8`E4k=fJ=Bwb6w1O&d7uV}UbKrh9Re0q+v`23 z>E!L7RIaZh zbo^&0sqg!+2N!b^Zn+;KUb9o5TQRHoNL?5WXkz^}b

    #omGsS9pWonb`EDd_9J*Z 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 SR{5R{TlHQ|*sAxPZ2tpg<2v{N delta 118584 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⪌nL&&((GG#YXW*N(f6Xm7ZPzx4KK77#`h`{-|- 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 LQ*}OD7NYcj5JaYy diff --git a/docs/index.html b/docs/index.html index aa200a645..ab72c53a3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1375,10 +1375,9 @@ Toggle adapting display refresh rate to game frame rate -
    - Note: Not available for macOS. +
    Note: Not available for macOS Alt + R - Cmd + R + - Decrease overscan in fullscreen mode @@ -2813,8 +2812,8 @@

    -tia.fs_refresh <1|0>
    While in fullscreen mode, adapt the display's refresh rate to the game's frame rate - to minimize judder.
    - Note: Not available for macOS. + to minimize judder. +
    Note: Not available for macOS @@ -2897,7 +2896,8 @@
    -tv.scanlines <0 - 100>
    - Set TV effects scanline intensity, where 0 means completely off. Note: No scanlines in 1x mode snapshots. + Set TV effects scanline intensity, where 0 means completely off. +
    Note: No scanlines in 1x mode snapshots @@ -3073,7 +3073,8 @@
    -ssinterval <number>
    - Set the interval in seconds between taking snapshots in continuous snapshot mode (currently 1 - 10). + Set the interval in seconds between taking snapshots in continuous + snapshot mode (currently 1 - 10). @@ -3123,8 +3124,8 @@
    -romviewer <float>
    Hide ROM Info Viewer in ROM launcher mode (0) or use the - given zoom level.
    - Note: The zoom level is converted into a percentage in the UI. + given zoom level. +
    Note: The zoom level is converted into a percentage in the UI. @@ -3207,17 +3208,20 @@
    -basedir <dir>
    - Override the base directory for all config files. + Override the base directory for all config files. +
    Note: Not available for macOS
    -baseinappdir
    - Override the base directory for all config files by attempting to use the application directory. For now this is only supported in Windows. + Override the base directory for all config files by attempting to use + the application directory. +
    Note: Only available for Windows
    -help
    - Prints a help message describing these options, and then + Print a help message describing these options, and then exit Stella. @@ -3612,7 +3616,7 @@ This depends on the OS and renderer used.-fullscreen StretchIn fullscreen mode, completely fill screen with the TIA image.-tia.fs_stretch Adapt display...In fullscreen mode, adapt the display's refresh rate to the game's frame rate to minimize judder. -
    Note: Not available for macOS.-tia.fs_refresh +
    Note: Not available for macOS-tia.fs_refresh OverscanIn fullscreen mode, add overscan to the TIA image.-tia.fs_overscan Correct aspect ratioEnable aspect ratio correct scaling.
    Note: Creates a cleaner looking TIA image when disabled (like z26 and old versions of Stella) vs. a correctly emulated aspect ratio when enabled.-tia.correct_aspect @@ -3662,7 +3666,7 @@ Blend (phosphor)Blend level to use in phosphor mode for all ROMs (needs to be manually adjusted for your particular hardware)-tv.phosblend Scanline intensitySets scanline black-level intensity.
    - Note: No scanlines in 1x mode snapshots.-tv.scanlines + Note: No scanlines in 1x mode snapshots-tv.scanlines Clone RGBCopy 'RGB' attributes to 'Custom' TV mode sliders  Clone S-VideoCopy 'S-Video' attributes to 'Custom' TV mode sliders  Clone CompositeCopy 'Composite' attributes to 'Custom' TV mode sliders  From e8cc3a14137b11a78f103271b073995fa2e81a3b Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Fri, 25 Dec 2020 17:44:23 -0330 Subject: [PATCH 22/34] Fix ZIP files in Windows not finding last path correctly. --- src/emucore/FSNode.hxx | 2 +- src/gui/BrowserDialog.cxx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/emucore/FSNode.hxx b/src/emucore/FSNode.hxx index d9c9dfab8..6b3f84c89 100644 --- a/src/emucore/FSNode.hxx +++ b/src/emucore/FSNode.hxx @@ -493,7 +493,7 @@ class AbstractFSNode const char* start = str.c_str(); const char* cur = start + str.size() - 2; - while (cur >= start && *cur != FilesystemNode::PATH_SEPARATOR) + while (cur >= start && !(*cur == '/' || *cur == '\\')) --cur; return cur + 1; diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index d56b8558d..7639dbfd3 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -127,7 +127,6 @@ void BrowserDialog::show(const string& startpath, { const int fontWidth = _font.getMaxCharWidth(), fontHeight = _font.getFontHeight(), - HBORDER = fontWidth * 1.25, VGAP = fontHeight / 4; _mode = mode; From 4e87dadf452d171c856c6b8f08255eee955c6811 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sat, 26 Dec 2020 00:13:14 -0330 Subject: [PATCH 23/34] Fix issues with About dialog in dark mode on macOS (fixes #748). Note that this only works with macOS 10.14 and above. Someone with more Mac experience will have to fix it for older versions. --- src/macos/AboutBox.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/macos/AboutBox.m b/src/macos/AboutBox.m index 188809386..e2ec7ae5a 100644 --- a/src/macos/AboutBox.m +++ b/src/macos/AboutBox.m @@ -95,6 +95,11 @@ static AboutBox *sharedInstance = nil; withRTF:[creditsString RTFFromRange: NSMakeRange( 0, [creditsString length] ) documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}]]; + if (@available(macOS 10.14, *)) { + creditsField.usesAdaptiveColorMappingForDarkAppearance = true; + } else { + // Fallback on earlier versions + } // Prepare some scroll info creditsBounds = [creditsField bounds]; From 969d772b72d04e24809a95a9fe7f26eb217aa7fd Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 26 Dec 2020 10:32:00 +0100 Subject: [PATCH 24/34] added missing changes in LoggerDialog --- src/gui/LoggerDialog.cxx | 37 +++++++++++++++++++++++++++++++------ src/gui/LoggerDialog.hxx | 10 ++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/gui/LoggerDialog.cxx b/src/gui/LoggerDialog.cxx index 83929464e..db235b67f 100644 --- a/src/gui/LoggerDialog.cxx +++ b/src/gui/LoggerDialog.cxx @@ -24,6 +24,7 @@ #include "Settings.hxx" #include "PopUpWidget.hxx" #include "StringListWidget.hxx" +#include "BrowserDialog.hxx" #include "StringParser.hxx" #include "Widget.hxx" #include "Font.hxx" @@ -39,7 +40,7 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Save log to disk") + fontWidth * 2.5, + buttonWidth = font.getStringWidth("Save log to disk" + ELLIPSIS) + fontWidth * 2.5, buttonHeight = font.getLineHeight() * 1.25; const int VBORDER = fontHeight / 2; const int HBORDER = fontWidth * 1.25; @@ -80,7 +81,7 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, // Add Save, OK and Cancel buttons ButtonWidget* b; b = new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER, - buttonWidth, buttonHeight, "Save log to disk", + buttonWidth, buttonHeight, "Save log to disk" + ELLIPSIS, GuiObject::kDefaultsCmd); wid.push_back(b); addOKCancelBGroup(wid, font); @@ -88,6 +89,22 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void LoggerDialog::createBrowser(const string& title) +{ + uInt32 w = 0, h = 0; + getDynamicBounds(w, h); + if(w > uInt32(_font.getMaxCharWidth() * 80)) + w = _font.getMaxCharWidth() * 80; + + // Create file browser dialog + if(!myBrowser || uInt32(myBrowser->getWidth()) != w || + uInt32(myBrowser->getHeight()) != h) + myBrowser = make_unique(this, _font, w, h, title); + else + myBrowser->setTitle(title); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LoggerDialog::loadConfig() { @@ -116,19 +133,18 @@ void LoggerDialog::saveConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LoggerDialog::saveLogFile() { - FilesystemNode node = instance().userDir(); - node /= "stella.log"; + FilesystemNode node(myBrowser->getResult().getShortPath()); try { stringstream out; out << Logger::instance().logMessages(); - instance().frameBuffer().showTextMessage("Saving log file to " + node.getShortPath()); node.write(out); + instance().frameBuffer().showTextMessage("System log saved"); } catch(...) { - instance().frameBuffer().showTextMessage("Error saving log file to " + node.getShortPath()); + instance().frameBuffer().showTextMessage("Error saving system log"); } } @@ -144,6 +160,15 @@ void LoggerDialog::handleCommand(CommandSender* sender, int cmd, break; case GuiObject::kDefaultsCmd: + // This dialog is resizable under certain conditions, so we need + // to re-create it as necessary + createBrowser("Save Log as"); + + myBrowser->show(instance().userDir().getPath() + "stella.log", + BrowserDialog::FileSave, kSaveCmd); + break; + + case kSaveCmd: saveLogFile(); break; diff --git a/src/gui/LoggerDialog.hxx b/src/gui/LoggerDialog.hxx index 2f5188343..eb49b29ff 100644 --- a/src/gui/LoggerDialog.hxx +++ b/src/gui/LoggerDialog.hxx @@ -22,6 +22,7 @@ class GuiObject; class CheckboxWidget; class PopUpWidget; class StringListWidget; +class BrowserDialog; #include "Dialog.hxx" #include "bspf.hxx" @@ -35,6 +36,8 @@ class LoggerDialog : public Dialog ~LoggerDialog() override = default; private: + void createBrowser(const string& title); + void loadConfig() override; void saveConfig() override; void saveLogFile(); @@ -46,6 +49,13 @@ class LoggerDialog : public Dialog PopUpWidget* myLogLevel{nullptr}; CheckboxWidget* myLogToConsole{nullptr}; + unique_ptr myBrowser; + + enum { + kSaveCmd = 'SvLg' + }; + + private: // Following constructors and assignment operators not supported LoggerDialog() = delete; From eb0350dbfb390ee50ac3f951567c5f572d51b622 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 26 Dec 2020 11:02:45 +0100 Subject: [PATCH 25/34] fixed selection issue when switching input event filters --- src/gui/ListWidget.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/ListWidget.cxx b/src/gui/ListWidget.cxx index ae2551e8f..ee79a36f3 100644 --- a/src/gui/ListWidget.cxx +++ b/src/gui/ListWidget.cxx @@ -172,7 +172,7 @@ void ListWidget::recalc() { int size = int(_list.size()); - if(_currentPos >= size) + if(_currentPos >= size - _rows) { if(size <= _rows) _currentPos = 0; @@ -182,7 +182,9 @@ void ListWidget::recalc() if (_currentPos < 0) _currentPos = 0; - if(_selectedItem < 0 || _selectedItem >= size) + if(_selectedItem >= size) + _selectedItem = size - 1; + if(_selectedItem < 0) _selectedItem = 0; _editMode = false; From b2f4a8d2ab3af2d6d6675b8746bbb0f060909fb7 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 26 Dec 2020 13:47:21 +0100 Subject: [PATCH 26/34] fixed scrollbar alignment issues --- src/gui/ScrollBarWidget.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gui/ScrollBarWidget.cxx b/src/gui/ScrollBarWidget.cxx index c9d68cb82..f6426a7e9 100644 --- a/src/gui/ScrollBarWidget.cxx +++ b/src/gui/ScrollBarWidget.cxx @@ -236,6 +236,7 @@ void ScrollBarWidget::checkBounds(int old_pos) if (old_pos != _currentPos) { recalc(); + setDirty(); sendCommand(GuiObject::kSetPositionCmd, _currentPos, _id); } } @@ -308,7 +309,13 @@ void ScrollBarWidget::drawWidget(bool hilite) // Slider if(!isSinglePage) { - s.fillRect(_x + 1, _y + _sliderPos - 1, _w - 2, _sliderHeight + 2, + // align slider to scroll intervals + int alignedPos = _upDownBoxHeight + (_h - 2 * _upDownBoxHeight - _sliderHeight) * + _currentPos / (_numEntries - _entriesPerPage); + if(alignedPos < 0) + alignedPos = 0; + + s.fillRect(_x + 1, _y + alignedPos - 1, _w - 2, _sliderHeight + 2, (hilite && _part == Part::Slider) ? kScrollColorHi : kScrollColor); } clearDirty(); @@ -316,4 +323,3 @@ void ScrollBarWidget::drawWidget(bool hilite) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int ScrollBarWidget::_WHEEL_LINES = 4; - From f94d8f925f39aefb62c77037ca6aa39d357f4325 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sat, 26 Dec 2020 11:19:51 -0330 Subject: [PATCH 27/34] Fix compile issue with LoggerDialog. --- src/gui/LoggerDialog.cxx | 5 +++++ src/gui/LoggerDialog.hxx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/LoggerDialog.cxx b/src/gui/LoggerDialog.cxx index db235b67f..41256ceb1 100644 --- a/src/gui/LoggerDialog.cxx +++ b/src/gui/LoggerDialog.cxx @@ -89,6 +89,11 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +LoggerDialog::~LoggerDialog() +{ +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LoggerDialog::createBrowser(const string& title) { diff --git a/src/gui/LoggerDialog.hxx b/src/gui/LoggerDialog.hxx index eb49b29ff..4addadb84 100644 --- a/src/gui/LoggerDialog.hxx +++ b/src/gui/LoggerDialog.hxx @@ -33,7 +33,7 @@ class LoggerDialog : public Dialog LoggerDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h, bool useLargeFont = true); - ~LoggerDialog() override = default; + ~LoggerDialog() override; private: void createBrowser(const string& title); From 1be26f29845ae4afb2c7d2151b6251819a99d212 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 27 Dec 2020 09:14:41 +0100 Subject: [PATCH 28/34] cleaned up code for use of fonts for BrowserDialog --- src/debugger/DebuggerParser.cxx | 1 - src/gui/LauncherDialog.cxx | 1 - src/gui/LauncherDialog.hxx | 2 -- src/gui/RomAuditDialog.cxx | 5 ++--- src/gui/RomAuditDialog.hxx | 1 - src/gui/SnapshotDialog.cxx | 5 ++--- src/gui/SnapshotDialog.hxx | 2 -- src/gui/UIDialog.cxx | 3 +-- src/gui/UIDialog.hxx | 1 - 9 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 0d35b5e30..2e4e757d9 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -35,7 +35,6 @@ #include "PromptWidget.hxx" #include "RomWidget.hxx" #include "ProgressDialog.hxx" -#include "BrowserDialog.hxx" #include "TimerManager.hxx" #include "Vec.hxx" diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index cec05172d..bf648e112 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -17,7 +17,6 @@ #include "bspf.hxx" #include "Bankswitch.hxx" -#include "BrowserDialog.hxx" #include "ContextMenu.hxx" #include "DialogContainer.hxx" #include "Dialog.hxx" diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index cd9d845a8..785394708 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -22,7 +22,6 @@ class ButtonWidget; class CommandSender; class ContextMenu; class DialogContainer; -class BrowserDialog; class OptionsDialog; class HighScoresDialog; class GlobalPropsDialog; @@ -168,7 +167,6 @@ class LauncherDialog : public Dialog unique_ptr myStellaSettingsDialog; unique_ptr myMenu; unique_ptr myGlobalProps; - unique_ptr myRomDir; unique_ptr myWhatsNewDialog; // automatically sized font for ROM info viewer diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index de7f3f5cd..121732998 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -37,7 +37,6 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Audit ROMs"), - myFont{font}, myMaxWidth{max_w}, myMaxHeight{max_h} { @@ -186,7 +185,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd, msg.push_back("If you're sure you want to proceed with the"); msg.push_back("audit, click 'OK', otherwise click 'Cancel'."); myConfirmMsg = make_unique - (this, myFont, msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd, + (this, _font, msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd, "OK", "Cancel", "ROM Audit", false); } myConfirmMsg->show(); @@ -229,7 +228,7 @@ void RomAuditDialog::createBrowser(const string& title) // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, myFont, w, h, title); + myBrowser = make_unique(this, _font, w, h, title); else myBrowser->setTitle(title); } diff --git a/src/gui/RomAuditDialog.hxx b/src/gui/RomAuditDialog.hxx index 3bc2a5969..c0e27d4bd 100644 --- a/src/gui/RomAuditDialog.hxx +++ b/src/gui/RomAuditDialog.hxx @@ -54,7 +54,6 @@ class RomAuditDialog : public Dialog // Select a new ROM audit path unique_ptr myBrowser; - const GUI::Font& myFont; // ROM audit path EditTextWidget* myRomPath{nullptr}; diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index 28067213c..6c2de15fa 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -28,8 +28,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "Snapshot settings"), - myFont{font} + : Dialog(osystem, parent, font, "Snapshot settings") { const int lineHeight = font.getLineHeight(), fontHeight = _font.getFontHeight(), @@ -189,7 +188,7 @@ void SnapshotDialog::createBrowser(const string& title) // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, myFont, w, h, title); + myBrowser = make_unique(this, _font, w, h, title); else myBrowser->setTitle(title); } diff --git a/src/gui/SnapshotDialog.hxx b/src/gui/SnapshotDialog.hxx index 6c9a30118..04b8b73a5 100644 --- a/src/gui/SnapshotDialog.hxx +++ b/src/gui/SnapshotDialog.hxx @@ -52,8 +52,6 @@ class SnapshotDialog : public Dialog kSnapshotInterval = 'SnIn' // snap chosen (load files) }; - const GUI::Font& myFont; - // Config paths EditTextWidget* mySnapSavePath{nullptr}; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 65c7d927b..722509899 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -42,7 +42,6 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, GuiObject* boss, int max_w, int max_h) : Dialog(osystem, parent, font, "User interface settings"), CommandSender(boss), - myFont{font}, myIsGlobal{boss != nullptr} { const GUI::Font& ifont = instance().frameBuffer().infoFont(); @@ -712,7 +711,7 @@ void UIDialog::createBrowser(const string& title) // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, myFont, w, h, title); + myBrowser = make_unique(this, _font, w, h, title); else myBrowser->setTitle(title); } diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 544f6c764..6c776c9c1 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -50,7 +50,6 @@ class UIDialog : public Dialog, public CommandSender kSnapLoadDirChosenCmd = 'UIsc' // snap chosen (load files) }; - const GUI::Font& myFont; TabWidget* myTab{nullptr}; // Launcher options From d1fe35cdfa8aa1ef28e0db5a39414432219dec0a Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 27 Dec 2020 11:32:23 -0330 Subject: [PATCH 29/34] Revert "cleaned up code for use of fonts for BrowserDialog" This reverts commit 1be26f29845ae4afb2c7d2151b6251819a99d212. --- src/debugger/DebuggerParser.cxx | 1 + src/gui/LauncherDialog.cxx | 1 + src/gui/LauncherDialog.hxx | 2 ++ src/gui/RomAuditDialog.cxx | 5 +++-- src/gui/RomAuditDialog.hxx | 1 + src/gui/SnapshotDialog.cxx | 5 +++-- src/gui/SnapshotDialog.hxx | 2 ++ src/gui/UIDialog.cxx | 3 ++- src/gui/UIDialog.hxx | 1 + 9 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 2e4e757d9..0d35b5e30 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -35,6 +35,7 @@ #include "PromptWidget.hxx" #include "RomWidget.hxx" #include "ProgressDialog.hxx" +#include "BrowserDialog.hxx" #include "TimerManager.hxx" #include "Vec.hxx" diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index bf648e112..cec05172d 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -17,6 +17,7 @@ #include "bspf.hxx" #include "Bankswitch.hxx" +#include "BrowserDialog.hxx" #include "ContextMenu.hxx" #include "DialogContainer.hxx" #include "Dialog.hxx" diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index 785394708..cd9d845a8 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -22,6 +22,7 @@ class ButtonWidget; class CommandSender; class ContextMenu; class DialogContainer; +class BrowserDialog; class OptionsDialog; class HighScoresDialog; class GlobalPropsDialog; @@ -167,6 +168,7 @@ class LauncherDialog : public Dialog unique_ptr myStellaSettingsDialog; unique_ptr myMenu; unique_ptr myGlobalProps; + unique_ptr myRomDir; unique_ptr myWhatsNewDialog; // automatically sized font for ROM info viewer diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index 121732998..de7f3f5cd 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -37,6 +37,7 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Audit ROMs"), + myFont{font}, myMaxWidth{max_w}, myMaxHeight{max_h} { @@ -185,7 +186,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd, msg.push_back("If you're sure you want to proceed with the"); msg.push_back("audit, click 'OK', otherwise click 'Cancel'."); myConfirmMsg = make_unique - (this, _font, msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd, + (this, myFont, msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd, "OK", "Cancel", "ROM Audit", false); } myConfirmMsg->show(); @@ -228,7 +229,7 @@ void RomAuditDialog::createBrowser(const string& title) // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, _font, w, h, title); + myBrowser = make_unique(this, myFont, w, h, title); else myBrowser->setTitle(title); } diff --git a/src/gui/RomAuditDialog.hxx b/src/gui/RomAuditDialog.hxx index c0e27d4bd..3bc2a5969 100644 --- a/src/gui/RomAuditDialog.hxx +++ b/src/gui/RomAuditDialog.hxx @@ -54,6 +54,7 @@ class RomAuditDialog : public Dialog // Select a new ROM audit path unique_ptr myBrowser; + const GUI::Font& myFont; // ROM audit path EditTextWidget* myRomPath{nullptr}; diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index 6c2de15fa..28067213c 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -28,7 +28,8 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "Snapshot settings") + : Dialog(osystem, parent, font, "Snapshot settings"), + myFont{font} { const int lineHeight = font.getLineHeight(), fontHeight = _font.getFontHeight(), @@ -188,7 +189,7 @@ void SnapshotDialog::createBrowser(const string& title) // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, _font, w, h, title); + myBrowser = make_unique(this, myFont, w, h, title); else myBrowser->setTitle(title); } diff --git a/src/gui/SnapshotDialog.hxx b/src/gui/SnapshotDialog.hxx index 04b8b73a5..6c9a30118 100644 --- a/src/gui/SnapshotDialog.hxx +++ b/src/gui/SnapshotDialog.hxx @@ -52,6 +52,8 @@ class SnapshotDialog : public Dialog kSnapshotInterval = 'SnIn' // snap chosen (load files) }; + const GUI::Font& myFont; + // Config paths EditTextWidget* mySnapSavePath{nullptr}; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 722509899..65c7d927b 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -42,6 +42,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, GuiObject* boss, int max_w, int max_h) : Dialog(osystem, parent, font, "User interface settings"), CommandSender(boss), + myFont{font}, myIsGlobal{boss != nullptr} { const GUI::Font& ifont = instance().frameBuffer().infoFont(); @@ -711,7 +712,7 @@ void UIDialog::createBrowser(const string& title) // Create file browser dialog if(!myBrowser || uInt32(myBrowser->getWidth()) != w || uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, _font, w, h, title); + myBrowser = make_unique(this, myFont, w, h, title); else myBrowser->setTitle(title); } diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 6c776c9c1..544f6c764 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -50,6 +50,7 @@ class UIDialog : public Dialog, public CommandSender kSnapLoadDirChosenCmd = 'UIsc' // snap chosen (load files) }; + const GUI::Font& myFont; TabWidget* myTab{nullptr}; // Launcher options From 9c39540a2113d0bba0eae29da1a492bd24ee4fba Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 27 Dec 2020 12:42:53 -0330 Subject: [PATCH 30/34] Improved BrowserDialog usage, eliminating redundant code in several places. This class now uses a lambda function to do the work when clicking OK or Cancel. This commit also adds the changes from the previously reverted commit. --- src/debugger/gui/DebuggerDialog.cxx | 74 +++++++---------------------- src/debugger/gui/DebuggerDialog.hxx | 15 ++---- src/gui/BrowserDialog.cxx | 70 ++++++++++++++------------- src/gui/BrowserDialog.hxx | 47 ++++++++++++++---- src/gui/GameInfoDialog.cxx | 39 ++++----------- src/gui/GameInfoDialog.hxx | 9 +--- src/gui/LauncherDialog.hxx | 2 - src/gui/LoggerDialog.cxx | 41 +++------------- src/gui/LoggerDialog.hxx | 14 +----- src/gui/RomAuditDialog.cxx | 41 +++++----------- src/gui/RomAuditDialog.hxx | 7 --- src/gui/SnapshotDialog.cxx | 39 +++------------ src/gui/SnapshotDialog.hxx | 9 +--- src/gui/UIDialog.cxx | 53 +++++---------------- src/gui/UIDialog.hxx | 12 ++--- 15 files changed, 152 insertions(+), 320 deletions(-) diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 4403009b8..f7a8987f0 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -259,30 +259,6 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd, loadConfig(); break; - case kSvAccessCmd: - runCommand("saveaccess"); - break; - - case kSvDisCmd: - runCommand("savedis"); - break; - - case kSvRomCmd: - runCommand("saverom"); - break; - - case kSvScriptCmd: - runCommand("save"); - break; - - case kSvSessionCmd: - runCommand("saveses"); - break; - - case kBdCancelCmd: - runCommand(); - break; - case RomWidget::kInvalidateListing: // Only do a full redraw if the disassembly tab is actually showing myRom->invalidate(myRomTab->getActiveTab() == 0); @@ -427,79 +403,63 @@ void DebuggerDialog::createFont() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerDialog::showBrowser(BrowserType type, const string& defaultName) { - int cmd; - string title; + string title, command; switch(type) { case BrowserType::svAccess: - cmd = kSvAccessCmd; title = "Access Counters"; + command = "saveaccess"; break; case BrowserType::svDis: - cmd = kSvDisCmd; title = "Disassembly"; + command = "savedis"; break; case BrowserType::svRom: - cmd = kSvRomCmd; title = "ROM"; + command = "saverom"; break; case BrowserType::svScript: - cmd = kSvScriptCmd; title = "Workbench"; + command = "save"; break; case BrowserType::svSession: - cmd = kSvSessionCmd; title = "Session"; + command = "saveses"; break; default: - cmd = 0; break; } - if(cmd) + if(command != EmptyString) { - createBrowser("Save " + title + " as"); - - const string path = instance().userDir().getPath() + defaultName; - myBrowser->show(path, BrowserDialog::FileSave, cmd, kBdCancelCmd); + BrowserDialog::show(this, instance().frameBuffer().font(), "Save " + title + " as", + instance().userDir().getPath() + defaultName, + BrowserDialog::Mode::FileSave, + [this, command](bool OK, const FilesystemNode& node) { + if(OK) runCommand(node, command); + else runCommand(node); + }); } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DebuggerDialog::runCommand(const string& command) +void DebuggerDialog::runCommand(const FilesystemNode& node, const string& command) { if(command != EmptyString) { - FilesystemNode dir(myBrowser->getResult()); - - string result = instance().debugger().parser().run(command + " {" + dir.getShortPath() + "}"); + string result = instance().debugger().parser().run(command + " {" + + node.getPath() + "}"); prompt().print(result + '\n'); } prompt().printPrompt(); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DebuggerDialog::createBrowser(const string& title) -{ - uInt32 w = 0, h = 0; - getDynamicBounds(w, h); - if(w > uInt32(_font.getMaxCharWidth() * 80)) - w = _font.getMaxCharWidth() * 80; - - // Create file browser dialog - if(!myBrowser || uInt32(myBrowser->getWidth()) != w || - uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, instance().frameBuffer().font(), w, h, title); - else - myBrowser->setTitle(title); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerDialog::showFatalMessage(const string& msg) { diff --git a/src/debugger/gui/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx index 1a4b4df67..2552f78c1 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -21,6 +21,7 @@ class Debugger; class OSystem; class DialogContainer; +class FilesystemNode; class ButtonWidget; class CpuWidget; class PromptWidget; @@ -34,7 +35,6 @@ class TiaZoomWidget; class CartDebugWidget; class CartRamWidget; class OptionsDialog; -class BrowserDialog; namespace GUI { class MessageBox; @@ -124,17 +124,11 @@ class DebuggerDialog : public Dialog kDDUnwindCmd = 'DDuw', kDDRunCmd = 'DDex', kDDExitFatalCmd = 'DDer', - kDDOptionsCmd = 'DDop', - kSvAccessCmd = 'SvAc', - kSvDisCmd = 'SvDs', - kSvRomCmd = 'SvRm', - kSvScriptCmd = 'SvSc', - kSvSessionCmd = 'SvSs', - kBdCancelCmd = 'SvCn' + kDDOptionsCmd = 'DDop' }; - void runCommand(const string& command = EmptyString); - void createBrowser(const string& title); + void runCommand(const FilesystemNode& node, + const string& command = EmptyString); TabWidget *myTab{nullptr}, *myRomTab{nullptr}; @@ -154,7 +148,6 @@ class DebuggerDialog : public Dialog unique_ptr myFatalError; unique_ptr myOptions; - unique_ptr myBrowser; unique_ptr myLFont; // used for labels unique_ptr myNFont; // used for normal text diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 7639dbfd3..02f550b70 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -26,16 +26,10 @@ #include "Font.hxx" #include "BrowserDialog.hxx" -/* We want to use this as a general directory selector at some point... possible uses - * - to select the data dir for a game - * - to select the place where save games are stored - * - others??? - */ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, int max_w, int max_h, const string& title) - : Dialog(boss->instance(), boss->parent(), font, title), - CommandSender(boss) + : Dialog(boss->instance(), boss->parent(), font, title) { // Set real dimensions _w = max_w; @@ -120,24 +114,42 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, addFocusWidget(_savePathBox); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void BrowserDialog::show(GuiObject* parent, const GUI::Font& font, + const string& title, const string& startpath, + BrowserDialog::Mode mode, + const Command& command, + const FilesystemNode::NameFilter& namefilter) +{ + uInt32 w = 0, h = 0; + static_cast(parent)->getDynamicBounds(w, h); + if(w > uInt32(font.getMaxCharWidth() * 80)) + w = font.getMaxCharWidth() * 80; + + static unique_ptr ourBrowser = + make_unique(parent, font, w, h, title); + + ourBrowser->show(startpath, mode, command, namefilter); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void BrowserDialog::show(const string& startpath, - BrowserDialog::ListMode mode, int cmd, int cancelCmd, - const string& ext) + BrowserDialog::Mode mode, + const Command& command, + const FilesystemNode::NameFilter& namefilter) { const int fontWidth = _font.getMaxCharWidth(), fontHeight = _font.getFontHeight(), VGAP = fontHeight / 4; _mode = mode; - _cmd = cmd; - _cancelCmd = cancelCmd; - string directory;// = EmptyString; - string fileName;// = EmptyString; + _command = command; + string directory; + string fileName; bool fileSelected = true; // Set start path - if(_mode != Directories) + if(_mode != Mode::Directories) { // split startpath into path and filename FilesystemNode fs = FilesystemNode(startpath); @@ -147,11 +159,9 @@ void BrowserDialog::show(const string& startpath, switch(_mode) { - case FileLoad: + case Mode::FileLoad: _fileList->setListMode(FilesystemNode::ListMode::All); - _fileList->setNameFilter([ext](const FilesystemNode& node) { - return BSPF::endsWithIgnoreCase(node.getName(), ext); - }); + _fileList->setNameFilter(namefilter); _fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop()); _currentPath->setWidth(_savePathBox->getLeft() - _currentPath->getLeft() - fontWidth); @@ -166,11 +176,9 @@ void BrowserDialog::show(const string& startpath, _okWidget->setLabel("Load"); break; - case FileSave: + case Mode::FileSave: _fileList->setListMode(FilesystemNode::ListMode::All); - _fileList->setNameFilter([ext](const FilesystemNode& node) { - return BSPF::endsWithIgnoreCase(node.getName(), ext); - }); + _fileList->setNameFilter(namefilter); _fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop()); _currentPath->setWidth(_savePathBox->getLeft() - _currentPath->getLeft() - fontWidth); @@ -187,7 +195,7 @@ void BrowserDialog::show(const string& startpath, fileSelected = false; break; - case Directories: + case Mode::Directories: _fileList->setListMode(FilesystemNode::ListMode::DirectoriesOnly); _fileList->setNameFilter([](const FilesystemNode&) { return true; }); // TODO: scrollbar affected too! @@ -206,7 +214,7 @@ void BrowserDialog::show(const string& startpath, } // Set start path - if(_mode != Directories) + if(_mode != Mode::Directories) _fileList->setDirectory(FilesystemNode(directory), fileName); else _fileList->setDirectory(FilesystemNode(startpath)); @@ -220,12 +228,12 @@ void BrowserDialog::show(const string& startpath, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const FilesystemNode& BrowserDialog::getResult() const { - if(_mode == FileLoad || _mode == FileSave) + if(_mode == Mode::FileLoad || _mode == Mode::FileSave) { static FilesystemNode node; return node - = FilesystemNode(_fileList->currentDir().getShortPath() + _selected->getText()); + = FilesystemNode(_fileList->currentDir().getPath() + _selected->getText()); } else return _fileList->currentDir(); @@ -240,8 +248,7 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd, case kChooseCmd: case FileListWidget::ItemActivated: // Send a signal to the calling class that a selection has been made - // Since we aren't derived from a widget, we don't have a 'data' or 'id' - if(_mode != Directories) + if(_mode != Mode::Directories) { // TODO: check if affected by '-baseDir'and 'basedirinapp' params bool savePath = _savePathBox->getState(); @@ -250,14 +257,13 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd, if(savePath) instance().setUserDir(_fileList->currentDir().getShortPath()); } - if(_cmd) sendCommand(_cmd, -1, -1); + _command(true, getResult()); close(); break; case kCloseCmd: // Send a signal to the calling class that the dialog was closed without selection - // Since we aren't derived from a widget, we don't have a 'data' or 'id' - if(_cancelCmd) sendCommand(_cancelCmd, -1, -1); + _command(false, getResult()); close(); break; @@ -300,7 +306,7 @@ void BrowserDialog::updateUI(bool fileSelected) // Enable/disable OK button based on current mode and status bool enable = true; - if(_mode != Directories) + if(_mode != Mode::Directories) enable = !_selected->getText().empty(); _okWidget->setEnabled(enable); diff --git a/src/gui/BrowserDialog.hxx b/src/gui/BrowserDialog.hxx index 8d4b5c2a6..c8c32759c 100644 --- a/src/gui/BrowserDialog.hxx +++ b/src/gui/BrowserDialog.hxx @@ -23,34 +23,62 @@ class ButtonWidget; class EditTextWidget; class FileListWidget; class StaticTextWidget; -class FilesystemNode; #include "Dialog.hxx" #include "Command.hxx" +#include "FSNode.hxx" #include "bspf.hxx" -class BrowserDialog : public Dialog, public CommandSender +class BrowserDialog : public Dialog { public: - enum ListMode { + enum class Mode { FileLoad, // File selector, no input from user FileSave, // File selector, filename changable by user Directories // Directories only, no input from user }; + /** Function which is run when the user clicks OK or Cancel. + Boolean parameter is passed as 'true' when OK is clicked, else 'false'. + FilesystemNode parameter is what is currently selected in the browser. + */ + using Command = std::function; + public: + // NOTE: Do not call this c'tor directly! Use the static show method below + // There is no point in doing so, since the result can't be returned BrowserDialog(GuiObject* boss, const GUI::Font& font, int max_w, int max_h, - const string& title = ""); + const string& title); ~BrowserDialog() override = default; + /** + Place the browser window onscreen, using the given attributes. + + @param parent The parent object of the browser (cannot be nullptr) + @param font The font to use in the browser + @param title The title of the browser window + @param startpath The initial path to select in the browser + @param mode The functionality to use (load/save/display) + @param command The command to run when 'OK' or 'Cancel' is clicked + @param namefilter Filter files/directories in browser display + */ + static void show(GuiObject* parent, const GUI::Font& font, + const string& title, const string& startpath, + BrowserDialog::Mode mode, + const Command& command, + const FilesystemNode::NameFilter& namefilter = { + [](const FilesystemNode&) { return true; }}); + + private: /** Place the browser window onscreen, using the given attributes */ void show(const string& startpath, - BrowserDialog::ListMode mode, int cmd, int cancelCmd = 0, const string& ext = ""); + BrowserDialog::Mode mode, + const Command& command, + const FilesystemNode::NameFilter& namefilter); /** Get resulting file node (called after receiving kChooseCmd) */ const FilesystemNode& getResult() const; - private: void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void updateUI(bool fileSelected); @@ -62,8 +90,9 @@ class BrowserDialog : public Dialog, public CommandSender kHomeDirCmd = 'HODR' }; - int _cmd{0}; - int _cancelCmd{0}; + // Called when the user selects OK (bool is true) or Cancel (bool is false) + // FSNode will be set to whatever is active (basically, getResult()) + Command _command{[](bool, const FilesystemNode&){}}; FileListWidget* _fileList{nullptr}; EditTextWidget* _currentPath{nullptr}; @@ -72,7 +101,7 @@ class BrowserDialog : public Dialog, public CommandSender ButtonWidget* _goUpButton{nullptr}; CheckboxWidget* _savePathBox{nullptr}; - BrowserDialog::ListMode _mode{Directories}; + BrowserDialog::Mode _mode{Mode::Directories}; private: // Following constructors and assignment operators not supported diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 9a0cb3fe7..24e787c32 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -666,22 +666,6 @@ GameInfoDialog::~GameInfoDialog() { } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void GameInfoDialog::createBrowser(const string& title) -{ - uInt32 w = 0, h = 0; - getDynamicBounds(w, h); - if(w > uInt32(_font.getMaxCharWidth() * 80)) - w = _font.getMaxCharWidth() * 80; - - // Create file browser dialog - if(!myBrowser || uInt32(myBrowser->getWidth()) != w || - uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, _font, w, h, title); - else - myBrowser->setTitle(title); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::loadConfig() { @@ -1358,7 +1342,7 @@ void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void GameInfoDialog::exportCurrentPropertiesToDisk() +void GameInfoDialog::exportCurrentPropertiesToDisk(const FilesystemNode& node) { saveProperties(); stringstream out; @@ -1366,9 +1350,7 @@ void GameInfoDialog::exportCurrentPropertiesToDisk() try { - FilesystemNode propfile(myBrowser->getResult().getShortPath()); - - propfile.write(out); + node.write(out); instance().frameBuffer().showTextMessage("ROM properties exported"); } catch(...) @@ -1393,16 +1375,13 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, break; case kExportPressed: - // This dialog is resizable under certain conditions, so we need - // to re-create it as necessary - createBrowser("Export Properties as"); - - myBrowser->show(instance().userDir().getPath() + myGameFile.getNameWithExt(".pro"), - BrowserDialog::FileSave, kExportChosen); - break; - - case kExportChosen: - exportCurrentPropertiesToDisk(); + BrowserDialog::show(this, _font, "Export Properties as", + instance().userDir().getPath() + + myGameFile.getNameWithExt(".pro"), + BrowserDialog::Mode::FileSave, + [this](bool OK, const FilesystemNode& node) { + if(OK) exportCurrentPropertiesToDisk(node); + }); break; case TabWidget::kTabChangedCmd: diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index d3af6775e..ffe41e223 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -27,7 +27,6 @@ class RadioButtonGroup; class TabWidget; class SliderWidget; class QuadTariDialog; -class BrowserDialog; #include "Dialog.hxx" #include "Command.hxx" @@ -78,8 +77,7 @@ class GameInfoDialog : public Dialog, public CommandSender // set formatted memory value for given address field void setAddressVal(EditTextWidget* address, EditTextWidget* val, bool isBCD = true, bool zeroBased = false, uInt8 maxVal = 255); - void exportCurrentPropertiesToDisk(); - void createBrowser(const string& title); + void exportCurrentPropertiesToDisk(const FilesystemNode& node); private: TabWidget* myTab{nullptr}; @@ -170,8 +168,6 @@ class GameInfoDialog : public Dialog, public CommandSender StaticTextWidget* myHighScoreNotesLabel{nullptr}; EditTextWidget* myHighScoreNotes{nullptr}; - unique_ptr myBrowser; - enum { kVCenterChanged = 'Vcch', kPhosphorChanged = 'PPch', @@ -184,8 +180,7 @@ class GameInfoDialog : public Dialog, public CommandSender kHiScoresChanged = 'HSch', kPXCenterChanged = 'Pxch', kPYCenterChanged = 'Pych', - kExportPressed = 'Expr', - kExportChosen = 'Exch' + kExportPressed = 'Expr' }; // Game properties for currently loaded ROM diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index cd9d845a8..785394708 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -22,7 +22,6 @@ class ButtonWidget; class CommandSender; class ContextMenu; class DialogContainer; -class BrowserDialog; class OptionsDialog; class HighScoresDialog; class GlobalPropsDialog; @@ -168,7 +167,6 @@ class LauncherDialog : public Dialog unique_ptr myStellaSettingsDialog; unique_ptr myMenu; unique_ptr myGlobalProps; - unique_ptr myRomDir; unique_ptr myWhatsNewDialog; // automatically sized font for ROM info viewer diff --git a/src/gui/LoggerDialog.cxx b/src/gui/LoggerDialog.cxx index 41256ceb1..b5d5ac9a8 100644 --- a/src/gui/LoggerDialog.cxx +++ b/src/gui/LoggerDialog.cxx @@ -89,27 +89,6 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LoggerDialog::~LoggerDialog() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void LoggerDialog::createBrowser(const string& title) -{ - uInt32 w = 0, h = 0; - getDynamicBounds(w, h); - if(w > uInt32(_font.getMaxCharWidth() * 80)) - w = _font.getMaxCharWidth() * 80; - - // Create file browser dialog - if(!myBrowser || uInt32(myBrowser->getWidth()) != w || - uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, _font, w, h, title); - else - myBrowser->setTitle(title); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LoggerDialog::loadConfig() { @@ -136,10 +115,8 @@ void LoggerDialog::saveConfig() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void LoggerDialog::saveLogFile() +void LoggerDialog::saveLogFile(const FilesystemNode& node) { - FilesystemNode node(myBrowser->getResult().getShortPath()); - try { stringstream out; @@ -165,16 +142,12 @@ void LoggerDialog::handleCommand(CommandSender* sender, int cmd, break; case GuiObject::kDefaultsCmd: - // This dialog is resizable under certain conditions, so we need - // to re-create it as necessary - createBrowser("Save Log as"); - - myBrowser->show(instance().userDir().getPath() + "stella.log", - BrowserDialog::FileSave, kSaveCmd); - break; - - case kSaveCmd: - saveLogFile(); + BrowserDialog::show(this, _font, "Save Log as", + instance().userDir().getPath() + "stella.log", + BrowserDialog::Mode::FileSave, + [this](bool OK, const FilesystemNode& node) { + if(OK) saveLogFile(node); + }); break; default: diff --git a/src/gui/LoggerDialog.hxx b/src/gui/LoggerDialog.hxx index 4addadb84..8eff3e8e4 100644 --- a/src/gui/LoggerDialog.hxx +++ b/src/gui/LoggerDialog.hxx @@ -22,7 +22,6 @@ class GuiObject; class CheckboxWidget; class PopUpWidget; class StringListWidget; -class BrowserDialog; #include "Dialog.hxx" #include "bspf.hxx" @@ -33,14 +32,12 @@ class LoggerDialog : public Dialog LoggerDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h, bool useLargeFont = true); - ~LoggerDialog() override; + ~LoggerDialog() override = default; private: - void createBrowser(const string& title); - void loadConfig() override; void saveConfig() override; - void saveLogFile(); + void saveLogFile(const FilesystemNode& node); void handleCommand(CommandSender* sender, int cmd, int data, int id) override; @@ -49,13 +46,6 @@ class LoggerDialog : public Dialog PopUpWidget* myLogLevel{nullptr}; CheckboxWidget* myLogToConsole{nullptr}; - unique_ptr myBrowser; - - enum { - kSaveCmd = 'SvLg' - }; - - private: // Following constructors and assignment operators not supported LoggerDialog() = delete; diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index de7f3f5cd..fb80f4f28 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -37,7 +37,6 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Audit ROMs"), - myFont{font}, myMaxWidth{max_w}, myMaxHeight{max_h} { @@ -186,7 +185,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd, msg.push_back("If you're sure you want to proceed with the"); msg.push_back("audit, click 'OK', otherwise click 'Cancel'."); myConfirmMsg = make_unique - (this, myFont, msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd, + (this, _font, msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd, "OK", "Cancel", "ROM Audit", false); } myConfirmMsg->show(); @@ -198,38 +197,20 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd, break; case kChooseAuditDirCmd: - createBrowser("Select ROM Directory to Audit"); - myBrowser->show(myRomPath->getText(), - BrowserDialog::Directories, kAuditDirChosenCmd); + BrowserDialog::show(this, _font, "Select ROM Directory to Audit", + myRomPath->getText(), + BrowserDialog::Mode::Directories, + [this](bool OK, const FilesystemNode& node) { + if(OK) { + myRomPath->setText(node.getShortPath()); + myResults1->setText(""); + myResults2->setText(""); + } + }); break; - case kAuditDirChosenCmd: - { - FilesystemNode dir(myBrowser->getResult()); - myRomPath->setText(dir.getShortPath()); - myResults1->setText(""); - myResults2->setText(""); - break; - } - default: Dialog::handleCommand(sender, cmd, data, 0); break; } } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void RomAuditDialog::createBrowser(const string& title) -{ - uInt32 w = 0, h = 0; - getDynamicBounds(w, h); - if(w > uInt32(_font.getMaxCharWidth() * 80)) - w = _font.getMaxCharWidth() * 80; - - // Create file browser dialog - if(!myBrowser || uInt32(myBrowser->getWidth()) != w || - uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, myFont, w, h, title); - else - myBrowser->setTitle(title); -} diff --git a/src/gui/RomAuditDialog.hxx b/src/gui/RomAuditDialog.hxx index 3bc2a5969..140256c41 100644 --- a/src/gui/RomAuditDialog.hxx +++ b/src/gui/RomAuditDialog.hxx @@ -23,7 +23,6 @@ class GuiObject; class DialogContainer; class EditTextWidget; class StaticTextWidget; -class BrowserDialog; namespace GUI { class MessageBox; } @@ -42,20 +41,14 @@ class RomAuditDialog : public Dialog private: void loadConfig() override; void auditRoms(); - void createBrowser(const string& title); void handleCommand(CommandSender* sender, int cmd, int data, int id) override; private: enum { kChooseAuditDirCmd = 'RAsl', // audit dir select - kAuditDirChosenCmd = 'RAch', // audit dir changed kConfirmAuditCmd = 'RAcf' // confirm rom audit }; - // Select a new ROM audit path - unique_ptr myBrowser; - const GUI::Font& myFont; - // ROM audit path EditTextWidget* myRomPath{nullptr}; diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index 28067213c..54dc6997e 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -28,8 +28,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "Snapshot settings"), - myFont{font} + : Dialog(osystem, parent, font, "Snapshot settings") { const int lineHeight = font.getLineHeight(), fontHeight = _font.getFontHeight(), @@ -98,11 +97,6 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -SnapshotDialog::~SnapshotDialog() -{ -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SnapshotDialog::loadConfig() { @@ -154,15 +148,12 @@ void SnapshotDialog::handleCommand(CommandSender* sender, int cmd, break; case kChooseSnapSaveDirCmd: - // This dialog is resizable under certain conditions, so we need - // to re-create it as necessary - createBrowser("Select Snapshot Save Directory"); - myBrowser->show(mySnapSavePath->getText(), - BrowserDialog::Directories, kSnapSaveDirChosenCmd); - break; - - case kSnapSaveDirChosenCmd: - mySnapSavePath->setText(myBrowser->getResult().getShortPath()); + BrowserDialog::show(this, _font, "Select Snapshot Save Directory", + mySnapSavePath->getText(), + BrowserDialog::Mode::Directories, + [this](bool OK, const FilesystemNode& node) { + if(OK) mySnapSavePath->setText(node.getShortPath()); + }); break; case kSnapshotInterval: @@ -177,19 +168,3 @@ void SnapshotDialog::handleCommand(CommandSender* sender, int cmd, break; } } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void SnapshotDialog::createBrowser(const string& title) -{ - uInt32 w = 0, h = 0; - getDynamicBounds(w, h); - if(w > uInt32(_font.getMaxCharWidth() * 80)) - w = _font.getMaxCharWidth() * 80; - - // Create file browser dialog - if(!myBrowser || uInt32(myBrowser->getWidth()) != w || - uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, myFont, w, h, title); - else - myBrowser->setTitle(title); -} diff --git a/src/gui/SnapshotDialog.hxx b/src/gui/SnapshotDialog.hxx index 6c9a30118..2ddcf6b37 100644 --- a/src/gui/SnapshotDialog.hxx +++ b/src/gui/SnapshotDialog.hxx @@ -25,7 +25,6 @@ class CheckboxWidget; class EditTextWidget; class SliderWidget; class StaticTextWidget; -class BrowserDialog; #include "Dialog.hxx" #include "Command.hxx" @@ -35,7 +34,7 @@ class SnapshotDialog : public Dialog public: SnapshotDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h); - ~SnapshotDialog() override; + ~SnapshotDialog() override = default; private: void loadConfig() override; @@ -43,17 +42,13 @@ class SnapshotDialog : public Dialog void setDefaults() override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - void createBrowser(const string& title); private: enum { kChooseSnapSaveDirCmd = 'LOss', // snapshot dir (save files) - kSnapSaveDirChosenCmd = 'snsc', // snap chosen (save files) kSnapshotInterval = 'SnIn' // snap chosen (load files) }; - const GUI::Font& myFont; - // Config paths EditTextWidget* mySnapSavePath{nullptr}; @@ -63,8 +58,6 @@ class SnapshotDialog : public Dialog CheckboxWidget* mySnapSingle{nullptr}; CheckboxWidget* mySnap1x{nullptr}; - unique_ptr myBrowser; - private: // Following constructors and assignment operators not supported SnapshotDialog() = delete; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 65c7d927b..4c1831a0b 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -42,7 +42,6 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, GuiObject* boss, int max_w, int max_h) : Dialog(osystem, parent, font, "User interface settings"), CommandSender(boss), - myFont{font}, myIsGlobal{boss != nullptr} { const GUI::Font& ifont = instance().frameBuffer().infoFont(); @@ -91,7 +90,6 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(myPalettePopup); ypos += lineHeight + VGAP; - // Dialog font items.clear(); VarList::push_back(items, "Small", "small"); // 8x13 @@ -318,11 +316,6 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, #endif } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UIDialog::~UIDialog() -{ -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void UIDialog::loadConfig() { @@ -584,15 +577,12 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) break; case kChooseRomDirCmd: - // This dialog is resizable under certain conditions, so we need - // to re-create it as necessary - createBrowser("Select ROM Directory"); - myBrowser->show(myRomPath->getText(), - BrowserDialog::Directories, LauncherDialog::kRomDirChosenCmd); - break; - - case LauncherDialog::kRomDirChosenCmd: - myRomPath->setText(myBrowser->getResult().getShortPath()); + BrowserDialog::show(this, _font, "Select ROM Directory", + myRomPath->getText(), + BrowserDialog::Mode::Directories, + [this](bool OK, const FilesystemNode& node) { + if(OK) myRomPath->setText(node.getShortPath()); + }); break; case kRomViewer: @@ -600,15 +590,12 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) break; case kChooseSnapLoadDirCmd: - // This dialog is resizable under certain conditions, so we need - // to re-create it as necessary - createBrowser("Select ROM Info Viewer Image Directory"); - myBrowser->show(mySnapLoadPath->getText(), - BrowserDialog::Directories, kSnapLoadDirChosenCmd); - break; - - case kSnapLoadDirChosenCmd: - mySnapLoadPath->setText(myBrowser->getResult().getShortPath()); + BrowserDialog::show(this, _font, "Select ROM Info Viewer Image Directory", + myRomPath->getText(), + BrowserDialog::Mode::Directories, + [this](bool OK, const FilesystemNode& node) { + if(OK) mySnapLoadPath->setText(node.getShortPath()); + }); break; default: @@ -700,19 +687,3 @@ void UIDialog::handleRomViewer() myOpenBrowserButton->setEnabled(enable); mySnapLoadPath->setEnabled(enable); } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void UIDialog::createBrowser(const string& title) -{ - uInt32 w = 0, h = 0; - getDynamicBounds(w, h); - if(w > uInt32(_font.getMaxCharWidth() * 80)) - w = _font.getMaxCharWidth() * 80; - - // Create file browser dialog - if(!myBrowser || uInt32(myBrowser->getWidth()) != w || - uInt32(myBrowser->getHeight()) != h) - myBrowser = make_unique(this, myFont, w, h, title); - else - myBrowser->setTitle(title); -} diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 544f6c764..9ecf9a3c4 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -18,14 +18,15 @@ #ifndef UI_DIALOG_HXX #define UI_DIALOG_HXX -class BrowserDialog; +#include "Dialog.hxx" +#include "bspf.hxx" class UIDialog : public Dialog, public CommandSender { public: UIDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, GuiObject* boss, int max_w, int max_h); - ~UIDialog() override; + ~UIDialog() override = default; private: void loadConfig() override; @@ -35,7 +36,6 @@ class UIDialog : public Dialog, public CommandSender void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleLauncherSize(); void handleRomViewer(); - void createBrowser(const string& title); private: enum @@ -46,11 +46,9 @@ class UIDialog : public Dialog, public CommandSender kControllerDelay = 'UIcd', kChooseRomDirCmd = 'LOrm', // rom select kRomViewer = 'UIRv', - kChooseSnapLoadDirCmd = 'UIsl', // snapshot dir (load files) - kSnapLoadDirChosenCmd = 'UIsc' // snap chosen (load files) + kChooseSnapLoadDirCmd = 'UIsl' // snapshot dir (load files) }; - const GUI::Font& myFont; TabWidget* myTab{nullptr}; // Launcher options @@ -76,8 +74,6 @@ class UIDialog : public Dialog, public CommandSender SliderWidget* myControllerDelaySlider{nullptr}; SliderWidget* myDoubleClickSlider{nullptr}; - unique_ptr myBrowser; - // Indicates if this dialog is used for global (vs. in-game) settings bool myIsGlobal{false}; From eeba0c9050b5ca6b9550b2bd983b522e2a3ae95f Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 27 Dec 2020 19:00:28 +0100 Subject: [PATCH 31/34] centralized some dialog constants --- src/cheat/CheatCodeDialog.cxx | 17 +++-- src/gui/AboutDialog.cxx | 19 +++--- src/gui/BrowserDialog.cxx | 25 ++++---- src/gui/ComboDialog.cxx | 14 ++--- src/gui/CommandDialog.cxx | 18 +++--- src/gui/DeveloperDialog.cxx | 88 ++++++++++++-------------- src/gui/Dialog.cxx | 66 +++++++++---------- src/gui/Dialog.hxx | 14 ++++- src/gui/EditableWidget.cxx | 6 +- src/gui/EmulationDialog.cxx | 16 +++-- src/gui/EventMappingWidget.cxx | 18 +++--- src/gui/GameInfoDialog.cxx | 84 +++++++++++-------------- src/gui/GlobalPropsDialog.cxx | 21 +++---- src/gui/HelpDialog.cxx | 21 +++---- src/gui/HighScoresDialog.cxx | 21 +++---- src/gui/InputDialog.cxx | 43 ++++++------- src/gui/InputTextDialog.cxx | 15 +++-- src/gui/JoystickDialog.cxx | 16 +++-- src/gui/LauncherDialog.cxx | 105 +++++++++++++++---------------- src/gui/LoggerDialog.cxx | 16 +++-- src/gui/MessageBox.cxx | 9 ++- src/gui/OptionsDialog.cxx | 22 +++---- src/gui/ProgressDialog.cxx | 28 ++++----- src/gui/QuadTariDialog.cxx | 11 ++-- src/gui/R77HelpDialog.cxx | 22 ++++--- src/gui/RomAuditDialog.cxx | 33 +++++----- src/gui/SnapshotDialog.cxx | 18 +++--- src/gui/StellaSettingsDialog.cxx | 33 +++++----- src/gui/UIDialog.cxx | 16 ++--- src/gui/VideoAudioDialog.cxx | 69 ++++++++++---------- src/gui/WhatsNewDialog.cxx | 28 +++++---- src/gui/WhatsNewDialog.hxx | 2 +- 32 files changed, 435 insertions(+), 499 deletions(-) diff --git a/src/cheat/CheatCodeDialog.cxx b/src/cheat/CheatCodeDialog.cxx index 481dcbcd5..7c7aa526f 100644 --- a/src/cheat/CheatCodeDialog.cxx +++ b/src/cheat/CheatCodeDialog.cxx @@ -35,15 +35,14 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font) : Dialog(osystem, parent, font, "Cheat codes") { - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(), - buttonWidth = font.getStringWidth("One shot ") + fontWidth * 2.5, - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("One shot "), + VGAP = Dialog::vGap(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(); int xpos, ypos; WidgetArray wid; ButtonWidget* b; diff --git a/src/gui/AboutDialog.cxx b/src/gui/AboutDialog.cxx index 426adbeeb..6ec7ab120 100644 --- a/src/gui/AboutDialog.cxx +++ b/src/gui/AboutDialog.cxx @@ -29,15 +29,14 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font) : Dialog(osystem, parent, font, "About Stella") { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Previous") + fontWidth * 2.5, - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Previous"), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos; WidgetArray wid; @@ -274,7 +273,7 @@ void AboutDialog::handleCommand(CommandSender* sender, int cmd, int data, int id case kWhatsNew: if(myWhatsNewDialog == nullptr) - myWhatsNewDialog = make_unique(instance(), parent(), _font, + myWhatsNewDialog = make_unique(instance(), parent(), 640 * 0.95, 480 * 0.95); myWhatsNewDialog->open(); break; diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 02f550b70..050e56831 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -34,16 +34,15 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, // Set real dimensions _w = max_w; _h = max_h; - - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() * 1.25, - buttonWidth = font.getStringWidth("Base Dir") + fontWidth * 2.5; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - const int BUTTON_GAP = fontWidth; + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Base Dir"), + BUTTON_GAP = Dialog::buttonGap(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); const int selectHeight = lineHeight + VGAP * 3; int xpos, ypos; ButtonWidget* b; @@ -138,10 +137,8 @@ void BrowserDialog::show(const string& startpath, const Command& command, const FilesystemNode::NameFilter& namefilter) { - const int fontWidth = _font.getMaxCharWidth(), - fontHeight = _font.getFontHeight(), - VGAP = fontHeight / 4; - + const int fontWidth = Dialog::fontWidth(), + VGAP = Dialog::vGap(); _mode = mode; _command = command; string directory; diff --git a/src/gui/ComboDialog.cxx b/src/gui/ComboDialog.cxx index e8b087c53..f93a43bf3 100644 --- a/src/gui/ComboDialog.cxx +++ b/src/gui/ComboDialog.cxx @@ -31,14 +31,12 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font, const VariantList& combolist) : Dialog(boss->instance(), boss->parent(), font, "Add...") { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos; WidgetArray wid; diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index e4c5f610a..1042dc3d8 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -34,16 +34,14 @@ CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent) : Dialog(osystem, parent, osystem.frameBuffer().font(), "Commands") { - const int fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - buttonHeight = _font.getLineHeight() * 1.25, - buttonWidth = _font.getStringWidth("Time Machine On") + fontWidth * 2; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - const int HGAP = fontWidth; - const int rowHeight = buttonHeight + VGAP; - + const int buttonHeight = Dialog::buttonHeight(), + buttonWidth = _font.getStringWidth("Time Machine On") + Dialog::fontWidth() * 2, + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); + const int HGAP = Dialog::buttonGap(), + rowHeight = buttonHeight + VGAP; // Set real dimensions _w = 3 * (buttonWidth + HGAP) - HGAP + HBORDER * 2; _h = 6 * rowHeight - VGAP + VBORDER * 2 + _th; diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index 12e89b37a..9d3e1c59f 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -48,14 +48,12 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Developer settings") { - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(), - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos; // Set real dimensions @@ -87,14 +85,12 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DeveloperDialog::addEmulationTab(const GUI::Font& font) { - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int ypos = VBORDER; WidgetArray wid; VariantList items; @@ -216,14 +212,11 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DeveloperDialog::addTiaTab(const GUI::Font& font) { - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int ypos = VBORDER; int pwidth = font.getStringWidth("Faulty Cosmic Ark stars"); WidgetArray wid; @@ -323,17 +316,16 @@ void DeveloperDialog::addTiaTab(const GUI::Font& font) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DeveloperDialog::addVideoTab(const GUI::Font& font) { - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int ypos = VBORDER; int lwidth = font.getStringWidth("Intensity "); - int pwidth = font.getMaxCharWidth() * 6; + int pwidth = fontWidth * 6; WidgetArray wid; VariantList items; int tabID = myTab->addTab(" Video ", TabWidget::AUTO_WIDTH); @@ -366,7 +358,7 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font) myTVJitterRecLabelWidget = new StaticTextWidget(myTab, font, myTVJitterRecWidget->getRight() + 4, myTVJitterRecWidget->getTop() + 2, - 5 * fontWidth, fontHeight, ""); + 5 * fontWidth, fontHeight); ypos += lineHeight + VGAP; myColorLossWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1, @@ -467,14 +459,13 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font) "30m", "60m" }; - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int xpos = HBORDER, ypos = VBORDER, lwidth = fontWidth * 11; @@ -568,13 +559,12 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font) WidgetArray wid; #ifdef DEBUGGER_SUPPORT - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); VariantList items; int xpos, ypos, pwidth; const Common::Size& ds = instance().frameBuffer().desktopSize(); diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 4ae7e7921..e510444cb 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -449,7 +449,7 @@ void Dialog::drawDialog() if(_th) { s.fillRect(_x, _y, _w, _th, kColorTitleBar); - s.drawString(_font, _title, _x + _font.getMaxCharWidth() * 1.25, _y + _font.getFontHeight() / 6, + s.drawString(_font, _title, _x + hBorder(), _y + _font.getFontHeight() / 6, _font.getStringWidth(_title), kColorTitleText); } } @@ -865,17 +865,14 @@ Widget* Dialog::findWidget(int x, int y) const void Dialog::addOKBGroup(WidgetArray& wid, const GUI::Font& font, const string& okText, int buttonWidth) { - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int BTN_BORDER = fontWidth * 2.5; - const int BUTTON_GAP = fontWidth; - - buttonWidth = fontWidth * 6 + BTN_BORDER; - buttonWidth = std::max(buttonWidth, font.getStringWidth(okText) + BTN_BORDER); + const int buttonHeight = Dialog::buttonHeight(), + BUTTON_GAP = Dialog::buttonGap(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(); + buttonWidth = std::max(buttonWidth, + std::max(Dialog::buttonWidth(okText), + Dialog::buttonWidth("Cancel"))); _w = std::max(HBORDER * 2 + buttonWidth * 2 + BUTTON_GAP, _w); addOKWidget(new ButtonWidget(this, font, (_w - buttonWidth) / 2, @@ -888,17 +885,15 @@ void Dialog::addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, const string& okText, const string& cancelText, bool focusOKButton, int buttonWidth) { - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int BTN_BORDER = fontWidth * 2.5; - const int BUTTON_GAP = fontWidth; + const int buttonHeight = Dialog::buttonHeight(), + BUTTON_GAP = Dialog::buttonGap(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(); + buttonWidth = std::max(buttonWidth, - std::max(font.getStringWidth("Defaults"), - std::max(font.getStringWidth(okText), - font.getStringWidth(cancelText))) + BTN_BORDER); + std::max(Dialog::buttonWidth("Defaults"), + std::max(Dialog::buttonWidth(okText), + Dialog::buttonWidth(cancelText)))); _w = std::max(HBORDER * 2 + buttonWidth * 2 + BUTTON_GAP, _w); @@ -936,13 +931,10 @@ void Dialog::addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, const string& defaultsText, bool focusOKButton) { - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int BTN_BORDER = fontWidth * 2.5; - const int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER; + const int buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth(defaultsText), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(); addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd)); @@ -958,22 +950,20 @@ void Dialog::addDefaultsExtraOKCancelBGroup( const string& okText, const string& cancelText, const string& defaultsText, bool focusOKButton) { - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int BTN_BORDER = fontWidth * 2.5; - const int BUTTON_GAP = fontWidth; - const int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER; + const int buttonHeight = Dialog::buttonHeight(), + buttonWidth = std::max(Dialog::buttonWidth(defaultsText), + Dialog::buttonWidth(extraText)), + BUTTON_GAP = Dialog::buttonGap(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(); addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd)); wid.push_back(_defaultWidget); addExtraWidget(new ButtonWidget(this, font, HBORDER + buttonWidth + BUTTON_GAP, - _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, - extraText, extraCmd)); + _h - buttonHeight - VBORDER, + buttonWidth, buttonHeight, extraText, extraCmd)); wid.push_back(_extraWidget); addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth); diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 5ba34b30c..478080760 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -127,6 +127,19 @@ class Dialog : public GuiObject ToolTip& tooltip() { return *_toolTip; } + int lineHeight() const { return _font.getLineHeight(); } + int fontHeight() const { return _font.getFontHeight(); } + int fontWidth() const { return _font.getMaxCharWidth(); } + int buttonHeight() const { return lineHeight() * 1.25; } + int buttonWidth(const string& label) const { + return _font.getStringWidth(label) + fontWidth() * 2.5; + } + int buttonGap() const { return fontWidth(); } + int hBorder() const { return fontWidth() * 1.25; }; + int vBorder() const { return fontHeight() / 2; }; + int vGap() const { return fontHeight() / 4; }; + int indent() const { return fontWidth() * 2; }; + protected: void draw() override { } void releaseFocus() override; @@ -164,7 +177,6 @@ class Dialog : public GuiObject const string& cancelText = "Cancel", const string& defaultsText = "Defaults", bool focusOKButton = true); - int buttonHeight(const GUI::Font& font) const; // NOTE: This method, and the three above it, are due to be refactored at some // point, since the parameter list is kind of getting ridiculous diff --git a/src/gui/EditableWidget.cxx b/src/gui/EditableWidget.cxx index 2b37a0ba2..be96728fa 100644 --- a/src/gui/EditableWidget.cxx +++ b/src/gui/EditableWidget.cxx @@ -477,13 +477,13 @@ void EditableWidget::drawCaretSelection() int y = editRect.y(); int w = editRect.w(); int h = editRect.h(); - int wt = int(text.length()) * _font.getMaxCharWidth() + 1; - int dx = selectStartPos() * _font.getMaxCharWidth() - _editScrollOffset; + int wt = int(text.length()) * _boss->dialog().fontWidth() + 1; + int dx = selectStartPos() * _boss->dialog().fontWidth() - _editScrollOffset; if(dx < 0) { // selected text starts left of displayed rect - text = text.substr(-(dx - 1) / _font.getMaxCharWidth()); + text = text.substr(-(dx - 1) / _boss->dialog().fontWidth()); wt += dx; dx = 0; } diff --git a/src/gui/EmulationDialog.cxx b/src/gui/EmulationDialog.cxx index a2c0bee9c..f2c6beff5 100644 --- a/src/gui/EmulationDialog.cxx +++ b/src/gui/EmulationDialog.cxx @@ -66,15 +66,13 @@ EmulationDialog::EmulationDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Emulation settings") { - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(), - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int xpos, ypos; int lwidth = font.getStringWidth("Emulation speed "); WidgetArray wid; diff --git a/src/gui/EventMappingWidget.cxx b/src/gui/EventMappingWidget.cxx index 4755c7789..f39d4d23a 100644 --- a/src/gui/EventMappingWidget.cxx +++ b/src/gui/EventMappingWidget.cxx @@ -42,14 +42,13 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, CommandSender(boss), myEventMode{mode} { - const int fontHeight = font.getFontHeight(), - lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - buttonWidth = font.getStringWidth("Defaults") + fontWidth * 1.25, - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; + const int lineHeight = boss->dialog().lineHeight(), + fontWidth = boss->dialog().fontWidth(), + buttonHeight = boss->dialog().buttonHeight(), + buttonWidth = boss->dialog().buttonWidth("Defaults"), + VBORDER = boss->dialog().vBorder(), + HBORDER = boss->dialog().hBorder(), + VGAP = boss->dialog().vGap(); const int ACTION_LINES = 2; int xpos = HBORDER, ypos = VBORDER; const int listWidth = _w - buttonWidth - HBORDER * 2 - fontWidth; @@ -136,8 +135,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, xpos = HBORDER; ypos = myActionsList->getBottom() + VGAP * 2; StaticTextWidget* t; - t = new StaticTextWidget(boss, font, xpos, ypos+2, font.getStringWidth("Action"), - fontHeight, "Action", TextAlign::Left); + t = new StaticTextWidget(boss, font, xpos, ypos+2, "Action"); myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + fontWidth, ypos, _w - xpos - t->getWidth() - fontWidth - HBORDER + 2, diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 24e787c32..a0cd40cff 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -56,16 +56,13 @@ GameInfoDialog::GameInfoDialog( CommandSender(boss) { const GUI::Font& ifont = instance().frameBuffer().infoFont(); - - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(), - buttonHeight = font.getLineHeight() * 1.25, - infoLineHeight = ifont.getLineHeight(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int infoLineHeight = ifont.getLineHeight(); + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); WidgetArray wid; // Set real dimensions @@ -103,13 +100,12 @@ GameInfoDialog::GameInfoDialog( void GameInfoDialog::addEmulationTab() { const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int ypos, pwidth, tabID; WidgetArray wid; VariantList items; @@ -200,13 +196,10 @@ void GameInfoDialog::addEmulationTab() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::addConsoleTab() { - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos, lwidth, tabID; WidgetArray wid; @@ -256,15 +249,13 @@ void GameInfoDialog::addConsoleTab() void GameInfoDialog::addControllersTab() { const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - buttonHeight = _font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int xpos, ypos, pwidth, tabID; VariantList items, ctrls; WidgetArray wid; @@ -408,13 +399,11 @@ void GameInfoDialog::addControllersTab() void GameInfoDialog::addCartridgeTab() { // 4) Cartridge properties - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos, lwidth, fwidth, tabID; WidgetArray wid; VariantList items; @@ -469,14 +458,13 @@ void GameInfoDialog::addCartridgeTab() void GameInfoDialog::addHighScoresTab() { // 4) High Scores properties - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int xpos, ypos, lwidth, pwidth, tabID; WidgetArray wid; VariantList items; diff --git a/src/gui/GlobalPropsDialog.cxx b/src/gui/GlobalPropsDialog.cxx index 232968f1c..bc58e5012 100644 --- a/src/gui/GlobalPropsDialog.cxx +++ b/src/gui/GlobalPropsDialog.cxx @@ -33,14 +33,12 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font) : Dialog(boss->instance(), boss->parent(), font, "Power-on options"), CommandSender(boss) { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonHeight = lineHeight * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos; int lwidth = font.getStringWidth("Right difficulty "), pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)"); @@ -138,10 +136,9 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font) int GlobalPropsDialog::addHoldWidgets(const GUI::Font& font, int x, int y, WidgetArray& wid) { - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(); - const int VGAP = fontHeight / 4; - + const int fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + VGAP = Dialog::vGap(); int xpos = x, ypos = y, xdiff = CheckboxWidget::boxSize(font) - 9; // Left joystick diff --git a/src/gui/HelpDialog.cxx b/src/gui/HelpDialog.cxx index 5d53488e1..7a7cdeee4 100644 --- a/src/gui/HelpDialog.cxx +++ b/src/gui/HelpDialog.cxx @@ -28,15 +28,14 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font) : Dialog(osystem, parent, font, "Help") { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Previous") + fontWidth * 2.5, - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Previous"), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos; WidgetArray wid; @@ -76,10 +75,10 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent, { myKey[i] = new StaticTextWidget(this, font, xpos, ypos, lwidth, - fontHeight, "", TextAlign::Left); + fontHeight); myDesc[i] = new StaticTextWidget(this, font, xpos+lwidth, ypos, _w - xpos - lwidth - HBORDER, - fontHeight, "", TextAlign::Left); + fontHeight); ypos += fontHeight; } diff --git a/src/gui/HighScoresDialog.cxx b/src/gui/HighScoresDialog.cxx index af39c125a..5fc7e54e4 100644 --- a/src/gui/HighScoresDialog.cxx +++ b/src/gui/HighScoresDialog.cxx @@ -107,23 +107,22 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, myScores.variation = HSM::DEFAULT_VARIATION; const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - infoLineHeight = ifont.getLineHeight(), - buttonHeight = _font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - const int BUTTON_GAP = fontWidth; - + const int infoLineHeight = ifont.getLineHeight(); + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + BUTTON_GAP = Dialog::buttonGap(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xposRank = HBORDER; int xposScore = xposRank + _font.getStringWidth("Rank"); int xposSpecial = xposScore + _font.getStringWidth(" Score "); int xposName = xposSpecial + _font.getStringWidth("Round "); int xposDate = xposName + _font.getStringWidth("Name "); int xposDelete = xposDate + _font.getStringWidth("YY-MM-DD HH:MM "); - int nWidth = _font.getStringWidth("ABC") + _font.getMaxCharWidth() * 0.75; + int nWidth = _font.getStringWidth("ABC") + fontWidth * 0.75; bool smallFont = _font.getFontHeight() < 24; int buttonSize = smallFont ? BUTTON_GFX_H : BUTTON_GFX_H_LARGE; int xpos, ypos; diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index 2345e3570..092af1242 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -44,13 +44,12 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, myMaxWidth{max_w}, myMaxHeight{max_h} { - const int lineHeight = _font.getLineHeight(), - fontWidth = _font.getMaxCharWidth(), - fontHeight = _font.getFontHeight(), - buttonHeight = _font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int VGAP = fontHeight / 4; - const int HBORDER = fontWidth * 1.25; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos, tabID; // Set real dimensions @@ -107,13 +106,12 @@ InputDialog::~InputDialog() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::addDevicePortTab() { - const int lineHeight = _font.getLineHeight(), - fontWidth = _font.getMaxCharWidth(), - fontHeight = _font.getFontHeight(), - buttonHeight = _font.getLineHeight() * 1.25; - const int VGAP = fontHeight / 4; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos, lwidth, tabID; WidgetArray wid; @@ -213,7 +211,7 @@ void InputDialog::addDevicePortTab() // Show joystick database ypos += lineHeight; - lwidth = _font.getStringWidth("Joystick Database" + ELLIPSIS) + fontWidth * 2.5; + lwidth = Dialog::buttonWidth("Joystick Database" + ELLIPSIS); myJoyDlgButton = new ButtonWidget(myTab, _font, HBORDER, ypos, lwidth, buttonHeight, "Joystick Database" + ELLIPSIS, kDBButtonPressed); wid.push_back(myJoyDlgButton); @@ -240,13 +238,12 @@ void InputDialog::addDevicePortTab() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::addMouseTab() { - const int lineHeight = _font.getLineHeight(), - fontWidth = _font.getMaxCharWidth(), - fontHeight = _font.getFontHeight(); - const int VGAP = fontHeight / 4; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int xpos = HBORDER, ypos, lwidth, pwidth, tabID; WidgetArray wid; VariantList items; @@ -713,7 +710,7 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd, { const GUI::Font& font = instance().frameBuffer().font(); myJoyDialog = make_unique - (this, font, font.getMaxCharWidth() * 56 + 20, font.getFontHeight() * 18 + 20); + (this, font, fontWidth() * 56 + 20, fontHeight() * 18 + 20); } myJoyDialog->show(); break; diff --git a/src/gui/InputTextDialog.cxx b/src/gui/InputTextDialog.cxx index 4c34de23e..0f13cf90d 100644 --- a/src/gui/InputTextDialog.cxx +++ b/src/gui/InputTextDialog.cxx @@ -50,14 +50,13 @@ InputTextDialog::InputTextDialog(GuiObject* boss, const GUI::Font& lfont, void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont, const StringList& labels) { - const int lineHeight = lfont.getLineHeight(), - fontWidth = lfont.getMaxCharWidth(), - fontHeight = lfont.getFontHeight(), - buttonHeight = lfont.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); uInt32 xpos, ypos, i, lwidth = 0, maxIdx = 0; WidgetArray wid; diff --git a/src/gui/JoystickDialog.cxx b/src/gui/JoystickDialog.cxx index 0073fb2ae..6935c56f2 100644 --- a/src/gui/JoystickDialog.cxx +++ b/src/gui/JoystickDialog.cxx @@ -31,15 +31,13 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font, { int xpos, ypos; WidgetArray wid; - - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Remove") + fontWidth * 2.5, - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Remove"), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(); // Joystick list xpos = HBORDER; ypos = VBORDER + _th; int w = _w - 2 * xpos; diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index cec05172d..e392f2150 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -61,20 +61,20 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, int x, int y, int w, int h) - : Dialog(osystem, parent, x, y, w, h) + : Dialog(osystem, parent, osystem.frameBuffer().launcherFont(), "", + x, y, w, h) { myUseMinimalUI = instance().settings().getBool("minimal_ui"); - - const GUI::Font& font = instance().frameBuffer().launcherFont(); - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - lineHeight = font.getLineHeight(), - HBORDER = fontWidth * 1.25, - VBORDER = fontHeight / 2, - BUTTON_GAP = fontWidth, - LBL_GAP = fontWidth, - VGAP = fontHeight / 4, - buttonHeight = myUseMinimalUI ? lineHeight - VGAP * 2: lineHeight * 1.25, + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + BUTTON_GAP = Dialog::buttonGap(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); + const int LBL_GAP = fontWidth, + buttonHeight = myUseMinimalUI ? lineHeight - VGAP * 2: Dialog::buttonHeight(), buttonWidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1)); int xpos = HBORDER, ypos = VBORDER; @@ -85,22 +85,22 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, string lblSubDirs = "Incl. subdirectories"; string lblFound = "12345 items found"; - tooltip().setFont(font); + tooltip().setFont(_font); - int lwSelect = font.getStringWidth(lblSelect); - int cwAllFiles = font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(font); - int cwSubDirs = font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(font); - int lwFilter = font.getStringWidth(lblFilter); - int lwFound = font.getStringWidth(lblFound); + int lwSelect = _font.getStringWidth(lblSelect); + int cwAllFiles = _font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(_font); + int cwSubDirs = _font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(_font); + int lwFilter = _font.getStringWidth(lblFilter); + int lwFound = _font.getStringWidth(lblFound); int wTotal = HBORDER * 2 + lwSelect + cwAllFiles + cwSubDirs + lwFilter + lwFound - + EditTextWidget::calcWidth(font, "123456") + LBL_GAP * 7; + + EditTextWidget::calcWidth(_font, "123456") + LBL_GAP * 7; bool noSelect = false; if(w < wTotal) { // make sure there is space for at least 6 characters in the filter field lblSelect = "Select a ROM" + ELLIPSIS; - int lwSelectShort = font.getStringWidth(lblSelect); + int lwSelectShort = _font.getStringWidth(lblSelect); wTotal -= lwSelect - lwSelectShort; lwSelect = lwSelectShort; @@ -109,7 +109,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, { // make sure there is space for at least 6 characters in the filter field lblSubDirs = "Subdir."; - int cwSubDirsShort = font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(font); + int cwSubDirsShort = _font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(_font); wTotal -= cwSubDirs - cwSubDirsShort; cwSubDirs = cwSubDirsShort; @@ -118,7 +118,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, { // make sure there is space for at least 6 characters in the filter field lblAllFiles = "All files"; - int cwAllFilesShort = font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(font); + int cwAllFilesShort = _font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(_font); wTotal -= cwAllFiles - cwAllFilesShort; cwAllFiles = cwAllFilesShort; @@ -127,7 +127,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, { // make sure there is space for at least 6 characters in the filter field lblFound = "12345 found"; - int lwFoundShort = font.getStringWidth(lblFound); + int lwFoundShort = _font.getStringWidth(lblFound); wTotal -= lwFound - lwFoundShort; lwFound = lwFoundShort; @@ -137,7 +137,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, { // make sure there is space for at least 6 characters in the filter field lblSelect = ""; - int lwSelectShort = font.getStringWidth(lblSelect); + int lwSelectShort = _font.getStringWidth(lblSelect); // wTotal -= lwSelect - lwSelectShort; // dead code lwSelect = lwSelectShort; @@ -152,16 +152,16 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, #if defined(RETRON77) ver << " for RetroN 77"; #endif - new StaticTextWidget(this, font, 0, ypos, _w, fontHeight, + new StaticTextWidget(this, _font, 0, ypos, _w, fontHeight, ver.str(), TextAlign::Center); ypos += lineHeight; } // Show the header - new StaticTextWidget(this, font, xpos, ypos, lblSelect); + new StaticTextWidget(this, _font, xpos, ypos, lblSelect); // Shop the files counter xpos = _w - HBORDER - lwFound; - myRomCount = new StaticTextWidget(this, font, xpos, ypos, + myRomCount = new StaticTextWidget(this, _font, xpos, ypos, lwFound, fontHeight, "", TextAlign::Right); @@ -169,23 +169,23 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, // It has to fit between both labels if(!myUseMinimalUI && w >= 640) { - int fwFilter = std::min(EditTextWidget::calcWidth(font, "123456789012345"), + int fwFilter = std::min(EditTextWidget::calcWidth(_font, "123456789012345"), xpos - cwSubDirs - lwFilter - cwAllFiles - lwSelect - HBORDER - LBL_GAP * (noSelect ? 5 : 7)); // Show the filter input field xpos -= fwFilter + LBL_GAP; - myPattern = new EditTextWidget(this, font, xpos, ypos - 2, fwFilter, lineHeight, ""); + myPattern = new EditTextWidget(this, _font, xpos, ypos - 2, fwFilter, lineHeight, ""); myPattern->setToolTip("Enter filter text to reduce file list.\n" "Use '*' and '?' as wildcards."); // Show the "Filter" label xpos -= lwFilter + LBL_GAP; - new StaticTextWidget(this, font, xpos, ypos, lblFilter); + new StaticTextWidget(this, _font, xpos, ypos, lblFilter); // Show the subdirectories checkbox xpos -= cwSubDirs + LBL_GAP * 2; - mySubDirs = new CheckboxWidget(this, font, xpos, ypos, lblSubDirs, kSubDirsCmd); + mySubDirs = new CheckboxWidget(this, _font, xpos, ypos, lblSubDirs, kSubDirsCmd); ostringstream tip; tip << "Search files in subdirectories too."; mySubDirs->setToolTip(tip.str()); @@ -195,7 +195,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, xpos = HBORDER; else xpos -= cwAllFiles + LBL_GAP; - myAllFiles = new CheckboxWidget(this, font, xpos, ypos, lblAllFiles, kAllfilesCmd); + myAllFiles = new CheckboxWidget(this, _font, xpos, ypos, lblAllFiles, kAllfilesCmd); myAllFiles->setToolTip("Uncheck to show ROM files only."); wid.push_back(myAllFiles); @@ -211,7 +211,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, if(romWidth > 0) romWidth += HBORDER; int listWidth = _w - (romWidth > 0 ? romWidth + fontWidth : 0) - HBORDER * 2; xpos = HBORDER; ypos += lineHeight + VGAP; - myList = new FileListWidget(this, font, xpos, ypos, listWidth, listHeight); + myList = new FileListWidget(this, _font, xpos, ypos, listWidth, listHeight); myList->setEditable(false); myList->setListMode(FilesystemNode::ListMode::All); wid.push_back(myList); @@ -236,11 +236,11 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, // Add textfield to show current directory xpos = HBORDER; ypos += myList->getHeight() + VGAP; - lwSelect = font.getStringWidth("Path") + LBL_GAP; - myDirLabel = new StaticTextWidget(this, font, xpos, ypos+2, lwSelect, fontHeight, + lwSelect = _font.getStringWidth("Path") + LBL_GAP; + myDirLabel = new StaticTextWidget(this, _font, xpos, ypos+2, lwSelect, fontHeight, "Path", TextAlign::Left); xpos += lwSelect; - myDir = new EditTextWidget(this, font, xpos, ypos, _w - xpos - HBORDER, lineHeight, ""); + myDir = new EditTextWidget(this, _font, xpos, ypos, _w - xpos - HBORDER, lineHeight, ""); myDir->setEditable(false, true); myDir->clearFlags(Widget::FLAG_RETAIN_FOCUS); @@ -249,41 +249,41 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, // Add four buttons at the bottom xpos = HBORDER; ypos = _h - VBORDER - buttonHeight; #ifndef BSPF_MACOS - myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight, + myStartButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight, "Select", kLoadROMCmd); wid.push_back(myStartButton); xpos += (buttonWidth + 0) / 4 + BUTTON_GAP; - myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight, + myPrevDirButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight, "Go Up", kPrevDirCmd); wid.push_back(myPrevDirButton); xpos += (buttonWidth + 1) / 4 + BUTTON_GAP; - myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight, + myOptionsButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight, "Options" + ELLIPSIS, kOptionsCmd); wid.push_back(myOptionsButton); xpos += (buttonWidth + 2) / 4 + BUTTON_GAP; - myQuitButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 4) / 4, buttonHeight, + myQuitButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 4) / 4, buttonHeight, "Quit", kQuitCmd); wid.push_back(myQuitButton); #else - myQuitButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight, + myQuitButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight, "Quit", kQuitCmd); wid.push_back(myQuitButton); xpos += (buttonWidth + 0) / 4 + BUTTON_GAP; - myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight, + myOptionsButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight, "Options" + ELLIPSIS, kOptionsCmd); wid.push_back(myOptionsButton); xpos += (buttonWidth + 1) / 4 + BUTTON_GAP; - myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 2) / 4, buttonHeight, + myPrevDirButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 2) / 4, buttonHeight, "Go Up", kPrevDirCmd); wid.push_back(myPrevDirButton); xpos += (buttonWidth + 2) / 4 + BUTTON_GAP; - myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight, + myStartButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight, "Select", kLoadROMCmd); wid.push_back(myStartButton); #endif @@ -297,12 +297,12 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); // Create (empty) context menu for ROM list options - myMenu = make_unique(this, osystem.frameBuffer().launcherFont(), EmptyVarList); + myMenu = make_unique(this, _font, EmptyVarList); // Create global props dialog, which is used to temporarily override // ROM properties myGlobalProps = make_unique(this, - myUseMinimalUI ? osystem.frameBuffer().launcherFont() : osystem.frameBuffer().font()); + myUseMinimalUI ? _font : osystem.frameBuffer().font()); // since we cannot know how many files there are, use are really high value here myList->progress().setRange(0, 50000, 5); @@ -536,16 +536,15 @@ float LauncherDialog::getRomInfoZoom(int listHeight) const if(zoom > 0.F) { - const GUI::Font& font = instance().frameBuffer().launcherFont(); const GUI::Font& smallFont = instance().frameBuffer().smallFont(); - const int fontWidth = font.getMaxCharWidth(), - HBORDER = fontWidth * 1.25; + const int fontWidth = Dialog::fontWidth(), + HBORDER = Dialog::hBorder(); // upper zoom limit - at least 24 launchers chars/line and 7 + 4 ROM info lines if((_w - (HBORDER * 2 + fontWidth + 30) - zoom * TIAConstants::viewableWidth) - / font.getMaxCharWidth() < MIN_LAUNCHER_CHARS) + / fontWidth < MIN_LAUNCHER_CHARS) { - zoom = float(_w - (HBORDER * 2 + fontWidth + 30) - MIN_LAUNCHER_CHARS * font.getMaxCharWidth()) + zoom = float(_w - (HBORDER * 2 + fontWidth + 30) - MIN_LAUNCHER_CHARS * fontWidth) / TIAConstants::viewableWidth; } if((listHeight - 12 - zoom * TIAConstants::viewableHeight) < @@ -584,7 +583,7 @@ void LauncherDialog::setRomInfoFont(const Common::Size& area) for(size_t i = 0; i < sizeof(FONTS) / sizeof(FontDesc); ++i) { // only use fonts <= launcher fonts - if(instance().frameBuffer().launcherFont().getFontHeight() >= FONTS[i].height) + if(Dialog::fontHeight() >= FONTS[i].height) { if(area.h >= uInt32(MIN_ROMINFO_ROWS * FONTS[i].height + 2 + MIN_ROMINFO_LINES * FONTS[i].height) @@ -916,7 +915,7 @@ void LauncherDialog::openHighScores() void LauncherDialog::openWhatsNew() { if(myWhatsNewDialog == nullptr) - myWhatsNewDialog = make_unique(instance(), parent(), _font, _w, _h); + myWhatsNewDialog = make_unique(instance(), parent(), _w, _h); myWhatsNewDialog->open(); } diff --git a/src/gui/LoggerDialog.cxx b/src/gui/LoggerDialog.cxx index b5d5ac9a8..79a6c82a1 100644 --- a/src/gui/LoggerDialog.cxx +++ b/src/gui/LoggerDialog.cxx @@ -37,15 +37,13 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, bool uselargefont) : Dialog(osystem, parent, font, "System logs") { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Save log to disk" + ELLIPSIS) + fontWidth * 2.5, - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Save log to disk" + ELLIPSIS), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos; WidgetArray wid; diff --git a/src/gui/MessageBox.cxx b/src/gui/MessageBox.cxx index ca3913543..ed751e5df 100644 --- a/src/gui/MessageBox.cxx +++ b/src/gui/MessageBox.cxx @@ -79,11 +79,10 @@ MessageBox::MessageBox(GuiObject* boss, const GUI::Font& font, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MessageBox::addText(const GUI::Font& font, const StringList& text) { - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - + const int fontWidth = Dialog::fontWidth(), + fontHeight = Dialog::fontHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(); int xpos, ypos; // Set real dimensions int str_w = 0; diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx index b2dc3b083..73e423807 100644 --- a/src/gui/OptionsDialog.cxx +++ b/src/gui/OptionsDialog.cxx @@ -54,17 +54,15 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, { // do not show basic settings options in debugger bool minSettings = osystem.settings().getBool("minimal_ui") && mode != Menu::AppMode::debugger; - const int - fontWidth = _font.getMaxCharWidth(), - fontHeight = _font.getFontHeight(), - buttonHeight = _font.getLineHeight() * 1.25, - VGAP = fontHeight / 4, - HGAP = fontWidth, - rowHeight = buttonHeight + VGAP; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - int buttonWidth = _font.getStringWidth("Game Properties" + ELLIPSIS) + fontWidth * 2.5; - + const int lineHeight = Dialog::lineHeight(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); + const int HGAP = Dialog::buttonGap(), + rowHeight = buttonHeight + VGAP; + int buttonWidth = Dialog::buttonWidth("Game Properties" + ELLIPSIS); _w = 2 * buttonWidth + HBORDER * 2 + HGAP; _h = 7 * rowHeight + VBORDER * 2 - VGAP + _th; @@ -133,7 +131,7 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, b = ADD_OD_BUTTON("About" + ELLIPSIS, kAboutCmd); wid.push_back(b); - buttonWidth = _font.getStringWidth(" Close ") + fontWidth * 2.5; + buttonWidth = Dialog::buttonWidth(" Close "); xoffset -= (buttonWidth + HGAP) / 2; b = ADD_OD_BUTTON("Close", kExitCmd); wid.push_back(b); diff --git a/src/gui/ProgressDialog.cxx b/src/gui/ProgressDialog.cxx index 235e24f6c..9c062b539 100644 --- a/src/gui/ProgressDialog.cxx +++ b/src/gui/ProgressDialog.cxx @@ -32,17 +32,14 @@ ProgressDialog::ProgressDialog(GuiObject* boss, const GUI::Font& font, : Dialog(boss->instance(), boss->parent()), myFont{font} { - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - lineHeight = font.getLineHeight(), - VBORDER = fontHeight / 2, - HBORDER = fontWidth * 1.25, - VGAP = fontHeight / 4, - buttonHeight = font.getLineHeight() * 1.25, - BTN_BORDER = fontWidth * 2.5, - buttonWidth = font.getStringWidth("Cancel") + BTN_BORDER, - lwidth = font.getStringWidth(message); - + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Cancel"), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); + const int lwidth = font.getStringWidth(message); int xpos, ypos; WidgetArray wid; @@ -73,12 +70,9 @@ ProgressDialog::ProgressDialog(GuiObject* boss, const GUI::Font& font, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ProgressDialog::setMessage(const string& message) { - const int fontWidth = myFont.getMaxCharWidth(), - HBORDER = fontWidth * 1.25, - lwidth = myFont.getStringWidth(message), - BTN_BORDER = fontWidth * 2.5, - buttonWidth = myFont.getStringWidth("Cancel") + BTN_BORDER; - + const int buttonWidth = Dialog::buttonWidth("Cancel"), + HBORDER = Dialog::hBorder(); + const int lwidth = myFont.getStringWidth(message); // Recalculate real dimensions _w = HBORDER * 2 + std::max(lwidth, buttonWidth); diff --git a/src/gui/QuadTariDialog.cxx b/src/gui/QuadTariDialog.cxx index 4b0ef8ead..95907597f 100644 --- a/src/gui/QuadTariDialog.cxx +++ b/src/gui/QuadTariDialog.cxx @@ -31,13 +31,10 @@ QuadTariDialog::QuadTariDialog(GuiObject* boss, const GUI::Font& font, int max_w : Dialog(boss->instance(), boss->parent(), font, "QuadTari controllers", 0, 0, max_w, max_h), myGameProperties{properties} { - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos; WidgetArray wid; VariantList ctrls; diff --git a/src/gui/R77HelpDialog.cxx b/src/gui/R77HelpDialog.cxx index 5d14d3719..67a57ee60 100644 --- a/src/gui/R77HelpDialog.cxx +++ b/src/gui/R77HelpDialog.cxx @@ -27,28 +27,30 @@ R77HelpDialog::R77HelpDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font) : Dialog(osystem, parent, font, "RetroN 77 help") { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Previous") + 20, - buttonHeight = font.getLineHeight() + 4; - const int HBORDER = 10; + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Previous"), + BUTTON_GAP = Dialog::buttonGap(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(); int xpos, ypos; WidgetArray wid; // Set real dimensions _w = 47 * fontWidth + HBORDER * 2; - _h = (LINES_PER_PAGE + 2) * lineHeight + 12 + _th; + _h = (LINES_PER_PAGE + 2) * lineHeight + VBORDER * 2 + _th; // Add Previous, Next and Close buttons - xpos = HBORDER; ypos = _h - buttonHeight - 10; + xpos = HBORDER; ypos = _h - buttonHeight - VBORDER; myPrevButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Previous", GuiObject::kPrevCmd); myPrevButton->clearFlags(Widget::FLAG_ENABLED); wid.push_back(myPrevButton); - xpos += buttonWidth + 8; + xpos += buttonWidth + BUTTON_GAP; myNextButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Next", GuiObject::kNextCmd); @@ -61,7 +63,7 @@ R77HelpDialog::R77HelpDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(b); addCancelWidget(b); - xpos = HBORDER; ypos = 5 + _th; + xpos = HBORDER; ypos = VBORDER + _th; myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - HBORDER * 2, fontHeight, "", TextAlign::Center); diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index fb80f4f28..fb3b2c5df 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -40,45 +40,44 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent, myMaxWidth{max_w}, myMaxHeight{max_h} { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Audit path" + ELLIPSIS) + fontWidth * 2.5, - buttonHeight = font.getLineHeight() * 1.25, - lwidth = font.getStringWidth("ROMs without properties (skipped) "); - const int VBORDER = _th + fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - - int xpos, ypos = VBORDER; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Audit path" + ELLIPSIS), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); + const int lwidth = font.getStringWidth("ROMs without properties (skipped) "); + int xpos, ypos = _th + VBORDER; WidgetArray wid; // Set real dimensions _w = 64 * fontWidth + HBORDER * 2; - _h = 7 * (lineHeight + 4) + VBORDER; + _h = _th + VBORDER * 2 + buttonHeight * 2 + lineHeight * 3 + VGAP * 10; // Audit path ButtonWidget* romButton = new ButtonWidget(this, font, HBORDER, ypos, buttonWidth, buttonHeight, "Audit path" + ELLIPSIS, kChooseAuditDirCmd); wid.push_back(romButton); - xpos = HBORDER + buttonWidth + 8; + xpos = HBORDER + buttonWidth + fontWidth; myRomPath = new EditTextWidget(this, font, xpos, ypos + (buttonHeight - lineHeight) / 2 - 1, - _w - xpos - HBORDER, lineHeight, ""); + _w - xpos - HBORDER, lineHeight); wid.push_back(myRomPath); // Show results of ROM audit - ypos += buttonHeight + 16; + ypos += buttonHeight + VGAP * 4; new StaticTextWidget(this, font, HBORDER, ypos, "ROMs with properties (renamed) "); myResults1 = new EditTextWidget(this, font, HBORDER + lwidth, ypos - 2, - fontWidth * 6, lineHeight, ""); + fontWidth * 6, lineHeight); myResults1->setEditable(false, true); ypos += buttonHeight; new StaticTextWidget(this, font, HBORDER, ypos, "ROMs without properties (skipped) "); myResults2 = new EditTextWidget(this, font, HBORDER + lwidth, ypos - 2, - fontWidth * 6, lineHeight, ""); + fontWidth * 6, lineHeight); myResults2->setEditable(false, true); - ypos += buttonHeight + 8; + ypos += buttonHeight + VGAP * 2; new StaticTextWidget(this, font, HBORDER, ypos, "(*) WARNING: Operation cannot be undone!"); // Add OK and Cancel buttons diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index 54dc6997e..fede37732 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -30,16 +30,14 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Snapshot settings") { - const int lineHeight = font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = font.getMaxCharWidth(), - buttonWidth = font.getStringWidth("Save path" + ELLIPSIS) + fontWidth * 2.5, - buttonHeight = font.getLineHeight() * 1.25; - const int HBORDER = fontWidth * 1.25; - const int VBORDER = fontHeight / 4; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Save path" + ELLIPSIS), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int xpos, ypos, fwidth; WidgetArray wid; ButtonWidget* b; diff --git a/src/gui/StellaSettingsDialog.cxx b/src/gui/StellaSettingsDialog.cxx index 5236735f0..e0e75fb1c 100644 --- a/src/gui/StellaSettingsDialog.cxx +++ b/src/gui/StellaSettingsDialog.cxx @@ -34,16 +34,15 @@ StellaSettingsDialog::StellaSettingsDialog(OSystem& osystem, DialogContainer& pa : Dialog(osystem, parent, osystem.frameBuffer().font(), "Basic settings"), myMode{mode} { - const int buttonHeight = _font.getLineHeight() + _font.getLineHeight() / 5, - lineHeight = _font.getLineHeight(), - fontWidth = _font.getMaxCharWidth(), - buttonWidth = _font.getStringWidth(" Help " + ELLIPSIS), - iLineHeight = instance().frameBuffer().infoFont().getLineHeight(); - - const int VBORDER = _font.getFontHeight() / 2; - const int HBORDER = fontWidth; - const int INDENT = fontWidth * 2; - const int VGAP = _font.getFontHeight() / 4; + const int iLineHeight = instance().frameBuffer().infoFont().getLineHeight(); + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth(" Help " + ELLIPSIS), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int xpos, ypos; ButtonWidget* bw = nullptr; @@ -97,8 +96,8 @@ StellaSettingsDialog::~StellaSettingsDialog() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos) { - const int VGAP = _font.getFontHeight() / 4; - const int lineHeight = _font.getLineHeight(); + const int lineHeight = Dialog::lineHeight(), + VGAP = Dialog::vGap(); VariantList items; int pwidth = _font.getStringWidth("Right bottom"); // align width with other popup @@ -126,10 +125,10 @@ void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StellaSettingsDialog::addVideoOptions(WidgetArray& wid, int& xpos, int& ypos) { - const int VGAP = _font.getFontHeight() / 4; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + VGAP = Dialog::vGap(); const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = _font.getLineHeight(), - fontWidth = _font.getMaxCharWidth(); VariantList items; // TV effects options @@ -180,8 +179,8 @@ void StellaSettingsDialog::addVideoOptions(WidgetArray& wid, int& xpos, int& ypo // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StellaSettingsDialog::addGameOptions(WidgetArray& wid, int& xpos, int& ypos) { - const int VGAP = _font.getFontHeight() / 4; - const int lineHeight = _font.getLineHeight(); + const int lineHeight = Dialog::lineHeight(), + VGAP = Dialog::vGap(); const GUI::Font& ifont = instance().frameBuffer().infoFont(); VariantList ctrls; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 4c1831a0b..457fa7af1 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -45,14 +45,14 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, myIsGlobal{boss != nullptr} { const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); int xpos, ypos, tabID; int lwidth, pwidth, bwidth; WidgetArray wid; diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx index ac2ad19bf..819fd5f35 100644 --- a/src/gui/VideoAudioDialog.cxx +++ b/src/gui/VideoAudioDialog.cxx @@ -57,13 +57,12 @@ VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Video & Audio settings") { - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - buttonHeight = _font.getLineHeight() * 1.25; - const int VGAP = fontHeight / 4; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int xpos, ypos; // Set real dimensions @@ -103,12 +102,12 @@ VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent, void VideoAudioDialog::addDisplayTab() { const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(); - const int VGAP = fontHeight / 4; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); const int INDENT = CheckboxWidget::prefixSize(_font); const int lwidth = _font.getStringWidth("V-Size adjust "), pwidth = _font.getStringWidth("OpenGLES2"); @@ -199,13 +198,12 @@ void VideoAudioDialog::addDisplayTab() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VideoAudioDialog::addPaletteTab() { - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(), + INDENT = Dialog::indent(); const int lwidth = _font.getStringWidth(" NTSC phase "); const int pwidth = _font.getStringWidth("Standard"); int xpos = HBORDER, @@ -331,14 +329,14 @@ void VideoAudioDialog::addPaletteTab() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VideoAudioDialog::addTVEffectsTab() { - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - buttonHeight = _font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + buttonWidth = Dialog::buttonWidth("Clone Bad Adjust"), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); const int INDENT = CheckboxWidget::prefixSize(_font);// fontWidth * 2; - const int VGAP = fontHeight / 4; int xpos = HBORDER, ypos = VBORDER; const int lwidth = _font.getStringWidth("Saturation "); @@ -392,14 +390,13 @@ void VideoAudioDialog::addTVEffectsTab() CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity", kScanlinesChanged) // Create buttons in 2nd column - int cloneWidth = _font.getStringWidth("Clone Bad Adjust") + fontWidth * 2.5; - xpos = _w - HBORDER - 2 * 2 - cloneWidth; + xpos = _w - HBORDER - 2 * 2 - buttonWidth; ypos = VBORDER - VGAP / 2; // Adjustable presets #define CREATE_CLONE_BUTTON(obj, desc) \ myClone ## obj = \ - new ButtonWidget(myTab, _font, xpos, ypos, cloneWidth, buttonHeight,\ + new ButtonWidget(myTab, _font, xpos, ypos, buttonWidth, buttonHeight,\ desc, kClone ## obj ##Cmd); \ wid.push_back(myClone ## obj); \ ypos += buttonHeight + VGAP; @@ -418,14 +415,12 @@ void VideoAudioDialog::addTVEffectsTab() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VideoAudioDialog::addAudioTab() { - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; + const int lineHeight = Dialog::lineHeight(), + fontWidth = Dialog::fontWidth(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); const int INDENT = CheckboxWidget::prefixSize(_font); - const int VGAP = fontHeight / 4; - int xpos, ypos; int lwidth = _font.getStringWidth("Volume "), pwidth; diff --git a/src/gui/WhatsNewDialog.cxx b/src/gui/WhatsNewDialog.cxx index 45c110bca..8dcb99903 100644 --- a/src/gui/WhatsNewDialog.cxx +++ b/src/gui/WhatsNewDialog.cxx @@ -15,6 +15,8 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" +#include "FrameBuffer.hxx" #include "Version.hxx" #include "WhatsNewDialog.hxx" @@ -22,20 +24,21 @@ constexpr int MAX_CHARS = 64; // maximum number of chars per line // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -WhatsNewDialog::WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, +WhatsNewDialog::WhatsNewDialog(OSystem& osystem, DialogContainer& parent, int max_w, int max_h) #if defined(RETRON77) - : Dialog(osystem, parent, font, "What's New in Stella " + string(STELLA_VERSION) + " for RetroN 77?") + : Dialog(osystem, parent, osystem.frameBuffer().font(), + "What's New in Stella " + string(STELLA_VERSION) + " for RetroN 77?") #else - : Dialog(osystem, parent, font, "What's New in Stella " + string(STELLA_VERSION) + "?") + : Dialog(osystem, parent, osystem.frameBuffer().font(), + "What's New in Stella " + string(STELLA_VERSION) + "?") #endif { - const int fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - buttonHeight = _font.getLineHeight() * 1.25; - const int VGAP = fontHeight / 4; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; + const int fontWidth = Dialog::fontWidth(), + buttonHeight = Dialog::buttonHeight(), + VBORDER = Dialog::vBorder(), + HBORDER = Dialog::hBorder(), + VGAP = Dialog::vGap(); int ypos = _th + VBORDER; // Set preliminary dimensions @@ -75,10 +78,9 @@ WhatsNewDialog::WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void WhatsNewDialog::add(int& ypos, const string& text) { - const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - HBORDER = fontWidth * 1.25; + const int lineHeight = Dialog::lineHeight(), + fontHeight = Dialog::fontHeight(), + HBORDER = Dialog::hBorder(); const string DOT = "\x1f"; string txt = DOT + " " + text; diff --git a/src/gui/WhatsNewDialog.hxx b/src/gui/WhatsNewDialog.hxx index 9c4154220..5f6c6d2e4 100644 --- a/src/gui/WhatsNewDialog.hxx +++ b/src/gui/WhatsNewDialog.hxx @@ -23,7 +23,7 @@ class WhatsNewDialog : public Dialog { public: - WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + WhatsNewDialog(OSystem& osystem, DialogContainer& parent, int max_w, int max_h); ~WhatsNewDialog() override = default; From 572e6ffe0c385aa22c1a5f91b0da02fa466c3d1e Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 27 Dec 2020 19:14:03 +0100 Subject: [PATCH 32/34] fixed copy & paste error --- src/gui/UIDialog.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 457fa7af1..e380fa6c8 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -591,7 +591,7 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) case kChooseSnapLoadDirCmd: BrowserDialog::show(this, _font, "Select ROM Info Viewer Image Directory", - myRomPath->getText(), + mySnapLoadPath->getText(), BrowserDialog::Mode::Directories, [this](bool OK, const FilesystemNode& node) { if(OK) mySnapLoadPath->setText(node.getShortPath()); From 5bab1a10c1028e7da8ade5d5073f57b50a6b3104 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 27 Dec 2020 15:03:04 -0330 Subject: [PATCH 33/34] Fix warning with unused variables. I left most of them there commented out, since they may be needed in the future. --- src/cheat/CheatCodeDialog.cxx | 2 +- src/gui/BrowserDialog.cxx | 4 ++-- src/gui/Dialog.hxx | 8 ++++---- src/gui/GlobalPropsDialog.cxx | 4 ++-- src/gui/LauncherDialog.cxx | 3 +-- src/gui/OptionsDialog.cxx | 6 ++---- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/cheat/CheatCodeDialog.cxx b/src/cheat/CheatCodeDialog.cxx index 7c7aa526f..45bccd57e 100644 --- a/src/cheat/CheatCodeDialog.cxx +++ b/src/cheat/CheatCodeDialog.cxx @@ -36,7 +36,7 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent, : Dialog(osystem, parent, font, "Cheat codes") { const int lineHeight = Dialog::lineHeight(), - fontHeight = Dialog::fontHeight(), + //fontHeight = Dialog::fontHeight(), fontWidth = Dialog::fontWidth(), buttonHeight = Dialog::buttonHeight(), buttonWidth = Dialog::buttonWidth("One shot "), diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 050e56831..5506c4bc3 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -35,8 +35,8 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, _w = max_w; _h = max_h; const int lineHeight = Dialog::lineHeight(), - fontHeight = Dialog::fontHeight(), - fontWidth = Dialog::fontWidth(), + //fontHeight = Dialog::fontHeight(), + //fontWidth = Dialog::fontWidth(), buttonHeight = Dialog::buttonHeight(), buttonWidth = Dialog::buttonWidth("Base Dir"), BUTTON_GAP = Dialog::buttonGap(), diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 478080760..43069d0bb 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -135,10 +135,10 @@ class Dialog : public GuiObject return _font.getStringWidth(label) + fontWidth() * 2.5; } int buttonGap() const { return fontWidth(); } - int hBorder() const { return fontWidth() * 1.25; }; - int vBorder() const { return fontHeight() / 2; }; - int vGap() const { return fontHeight() / 4; }; - int indent() const { return fontWidth() * 2; }; + int hBorder() const { return fontWidth() * 1.25; } + int vBorder() const { return fontHeight() / 2; } + int vGap() const { return fontHeight() / 4; } + int indent() const { return fontWidth() * 2; } protected: void draw() override { } diff --git a/src/gui/GlobalPropsDialog.cxx b/src/gui/GlobalPropsDialog.cxx index bc58e5012..1bf158ccb 100644 --- a/src/gui/GlobalPropsDialog.cxx +++ b/src/gui/GlobalPropsDialog.cxx @@ -136,8 +136,8 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font) int GlobalPropsDialog::addHoldWidgets(const GUI::Font& font, int x, int y, WidgetArray& wid) { - const int fontHeight = Dialog::fontHeight(), - fontWidth = Dialog::fontWidth(), + const int fontWidth = Dialog::fontWidth(), + //fontHeight = Dialog::fontHeight(), VGAP = Dialog::vGap(); int xpos = x, ypos = y, xdiff = CheckboxWidget::boxSize(font) - 9; diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index e392f2150..ffb191157 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -71,8 +71,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, BUTTON_GAP = Dialog::buttonGap(), VBORDER = Dialog::vBorder(), HBORDER = Dialog::hBorder(), - VGAP = Dialog::vGap(), - INDENT = Dialog::indent(); + VGAP = Dialog::vGap(); const int LBL_GAP = fontWidth, buttonHeight = myUseMinimalUI ? lineHeight - VGAP * 2: Dialog::buttonHeight(), buttonWidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1)); diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx index 73e423807..397306ce1 100644 --- a/src/gui/OptionsDialog.cxx +++ b/src/gui/OptionsDialog.cxx @@ -54,12 +54,10 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, { // do not show basic settings options in debugger bool minSettings = osystem.settings().getBool("minimal_ui") && mode != Menu::AppMode::debugger; - const int lineHeight = Dialog::lineHeight(), - buttonHeight = Dialog::buttonHeight(), + const int buttonHeight = Dialog::buttonHeight(), VBORDER = Dialog::vBorder(), HBORDER = Dialog::hBorder(), - VGAP = Dialog::vGap(), - INDENT = Dialog::indent(); + VGAP = Dialog::vGap(); const int HGAP = Dialog::buttonGap(), rowHeight = buttonHeight + VGAP; int buttonWidth = Dialog::buttonWidth("Game Properties" + ELLIPSIS); From 6ad467d657deace19a125d6d6e806a475ac62a7e Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 27 Dec 2020 18:54:51 -0330 Subject: [PATCH 34/34] Fixed a few more unused variables warnings. --- src/gui/CommandDialog.cxx | 4 ++-- src/gui/JoystickDialog.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index 1042dc3d8..54c6515ec 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -38,8 +38,8 @@ CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent) buttonWidth = _font.getStringWidth("Time Machine On") + Dialog::fontWidth() * 2, VBORDER = Dialog::vBorder(), HBORDER = Dialog::hBorder(), - VGAP = Dialog::vGap(), - INDENT = Dialog::indent(); + VGAP = Dialog::vGap(); + //INDENT = Dialog::indent(); const int HGAP = Dialog::buttonGap(), rowHeight = buttonHeight + VGAP; // Set real dimensions diff --git a/src/gui/JoystickDialog.cxx b/src/gui/JoystickDialog.cxx index 6935c56f2..4d00630ae 100644 --- a/src/gui/JoystickDialog.cxx +++ b/src/gui/JoystickDialog.cxx @@ -32,7 +32,7 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font, int xpos, ypos; WidgetArray wid; const int lineHeight = Dialog::lineHeight(), - fontHeight = Dialog::fontHeight(), + //fontHeight = Dialog::fontHeight(), fontWidth = Dialog::fontWidth(), buttonHeight = Dialog::buttonHeight(), buttonWidth = Dialog::buttonWidth("Remove"),