From aca18df74be9426df06d2a15dd208c25c1e85fc1 Mon Sep 17 00:00:00 2001 From: elasota Date: Sun, 5 Jan 2020 02:33:03 -0500 Subject: [PATCH] More stuff, fix saved games --- Aerofoil/GpFileSystem_Win32.cpp | 88 ++++++- Aerofoil/GpFileSystem_Win32.h | 2 + Aerofoil/GpPLGlueAudioDriver.cpp | 53 ++-- Aerofoil/GpPLGlueAudioDriver.h | 1 + GpApp/Coordinates.cpp | 7 +- GpApp/DialogUtils.cpp | 3 +- GpApp/Events.cpp | 3 + GpApp/Externs.h | 1 - GpApp/House.cpp | 6 + GpApp/HouseInfo.cpp | 2 +- GpApp/Link.cpp | 36 +-- GpApp/MainWindow.cpp | 2 +- GpApp/Map.cpp | 84 ++++--- GpApp/Menu.cpp | 60 ++--- GpApp/RectUtils.cpp | 29 --- GpApp/RectUtils.h | 2 - GpApp/RoomInfo.cpp | 4 +- GpApp/SavedGames.cpp | 227 +++++++++--------- GpApp/Settings.cpp | 138 +++++------ GpApp/Tools.cpp | 53 ++-- GpApp/Utilities.cpp | 18 +- GpApp/WindowUtils.cpp | 28 +-- .../GpAudioDriverXAudio2.cpp | 5 + GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h | 3 +- GpCommon/IGpAudioDriver.h | 4 + PortabilityLayer/DialogManager.cpp | 24 +- PortabilityLayer/FileManager.cpp | 6 + PortabilityLayer/FileManager.h | 1 + PortabilityLayer/HostAudioDriver.h | 7 +- PortabilityLayer/HostFileSystem.h | 1 + PortabilityLayer/InputManager.cpp | 7 + PortabilityLayer/InputManager.h | 1 + PortabilityLayer/MenuManager.cpp | 41 ++++ PortabilityLayer/MenuManager.h | 6 +- PortabilityLayer/PLCheckboxWidget.cpp | 20 ++ PortabilityLayer/PLCheckboxWidget.h | 15 ++ PortabilityLayer/PLControlDefinitions.cpp | 17 ++ PortabilityLayer/PLControlDefinitions.h | 15 +- PortabilityLayer/PLCore.cpp | 64 +++-- PortabilityLayer/PLCore.h | 15 +- PortabilityLayer/PLLabelWidget.cpp | 2 +- PortabilityLayer/PLPopupMenuWidget.cpp | 14 ++ PortabilityLayer/PLPopupMenuWidget.h | 15 ++ PortabilityLayer/PLQDraw.cpp | 137 ++++++++++- PortabilityLayer/PLQDraw.h | 1 - PortabilityLayer/PLRadioButtonWidget.cpp | 54 +++++ PortabilityLayer/PLRadioButtonWidget.h | 22 ++ PortabilityLayer/PLScrollBarWidget.cpp | 14 ++ PortabilityLayer/PLScrollBarWidget.h | 15 ++ PortabilityLayer/PLSound.cpp | 15 +- PortabilityLayer/PLWidgets.cpp | 38 ++- PortabilityLayer/PLWidgets.h | 30 ++- PortabilityLayer/PortabilityLayer.vcxproj | 8 + .../PortabilityLayer.vcxproj.filters | 24 ++ PortabilityLayer/QDGraf.h | 2 + PortabilityLayer/SharedTypes.h | 35 ++- PortabilityLayer/VirtualDirectory.h | 1 + PortabilityLayer/WindowManager.cpp | 3 + 58 files changed, 1075 insertions(+), 454 deletions(-) create mode 100644 PortabilityLayer/PLCheckboxWidget.cpp create mode 100644 PortabilityLayer/PLCheckboxWidget.h create mode 100644 PortabilityLayer/PLPopupMenuWidget.cpp create mode 100644 PortabilityLayer/PLPopupMenuWidget.h create mode 100644 PortabilityLayer/PLRadioButtonWidget.cpp create mode 100644 PortabilityLayer/PLRadioButtonWidget.h create mode 100644 PortabilityLayer/PLScrollBarWidget.cpp create mode 100644 PortabilityLayer/PLScrollBarWidget.h diff --git a/Aerofoil/GpFileSystem_Win32.cpp b/Aerofoil/GpFileSystem_Win32.cpp index a75c8f4..238dcc5 100644 --- a/Aerofoil/GpFileSystem_Win32.cpp +++ b/Aerofoil/GpFileSystem_Win32.cpp @@ -115,18 +115,21 @@ GpFileSystem_Win32::GpFileSystem_Win32() throw; } - m_prefsDir.append(L"\\GlidePort"); + m_prefsDir.append(L"\\" GP_APPLICATION_NAME_W); m_userHousesDir = m_prefsDir + L"\\Houses"; + m_userSavesDir = m_prefsDir + L"\\SavedGames"; m_scoresDir = m_prefsDir + L"\\Scores"; CreateDirectoryW(m_prefsDir.c_str(), nullptr); CreateDirectoryW(m_scoresDir.c_str(), nullptr); CreateDirectoryW(m_userHousesDir.c_str(), nullptr); + CreateDirectoryW(m_userSavesDir.c_str(), nullptr); m_prefsDir.append(L"\\"); m_scoresDir.append(L"\\"); m_userHousesDir.append(L"\\"); + m_userSavesDir.append(L"\\"); } DWORD modulePathSize = GetModuleFileNameW(nullptr, m_executablePath, MAX_PATH); @@ -363,6 +366,86 @@ bool GpFileSystem_Win32::PromptSaveFile(PortabilityLayer::VirtualDirectory_t vir return true; } +bool GpFileSystem_Win32::PromptOpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity) +{ + wchar_t baseFN[MAX_PATH + 5]; + wchar_t baseDir[MAX_PATH + 5]; + + baseFN[0] = 0; + + if (!ResolvePath(virtualDirectory, "", baseDir)) + return false; + + OPENFILENAMEW ofn; + memset(&ofn, 0, sizeof(ofn)); + + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFilter = GP_APPLICATION_NAME_W L" File (*.gpf)\0*.gpf\0"; + ofn.lpstrFile = baseFN; + ofn.lpstrDefExt = L"gpf"; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrInitialDir = baseDir; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; + + if (!GetOpenFileNameW(&ofn)) + return false; + + if (ofn.Flags & OFN_EXTENSIONDIFFERENT) + { + MessageBeep(MB_ICONERROR); + MessageBoxW(nullptr, L"Open file failed: Files must have the '.gpf' extension", L"Invalid file path", MB_OK); + return false; + } + + const wchar_t *fn = ofn.lpstrFile + ofn.nFileOffset; + size_t fnLengthWithoutExt = wcslen(fn); + if (ofn.nFileExtension - 1 > ofn.nFileOffset) // Off by 1 because extension doesn't include . + fnLengthWithoutExt = ofn.nFileExtension - ofn.nFileOffset - 1; + + if (fnLengthWithoutExt >= pathCapacity) + { + wchar_t msg[256]; + wsprintfW(msg, L"Open file failed: File name is too long. Limit is %i characters.", static_cast(pathCapacity)); + MessageBeep(MB_ICONERROR); + MessageBoxW(nullptr, msg, L"Invalid file path", MB_OK); + return false; + } + + if (ofn.nFileOffset != wcslen(baseDir) || memcmp(ofn.lpstrFile, baseDir, ofn.nFileOffset * sizeof(wchar_t))) + { + wchar_t msg[256 + MAX_PATH]; + wsprintfW(msg, L"Open file failed: File can't be opened from here, it must be in %s", baseDir); + MessageBeep(MB_ICONERROR); + MessageBoxW(nullptr, msg, L"Invalid file path", MB_OK); + return false; + } + + const wchar_t *unsupportedCharMsg = L"File name contains unsupported characters."; + + for (size_t i = 0; i < fnLengthWithoutExt; i++) + { + if (fn[i] < static_cast(0) || fn[i] >= static_cast(128)) + { + MessageBeep(MB_ICONERROR); + MessageBoxW(nullptr, unsupportedCharMsg, L"Invalid file path", MB_OK); + return false; + } + + path[i] = static_cast(fn[i]); + } + + if (!ValidateFilePath(path, fnLengthWithoutExt)) + { + MessageBeep(MB_ICONERROR); + MessageBoxW(nullptr, unsupportedCharMsg, L"Invalid file path", MB_OK); + return false; + } + + outPathLength = fnLengthWithoutExt; + + return true; +} + bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const { for (size_t i = 0; i < length; i++) @@ -414,6 +497,9 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua case PortabilityLayer::VirtualDirectories::kUserData: baseDir = m_userHousesDir.c_str(); break; + case PortabilityLayer::VirtualDirectories::kUserSaves: + baseDir = m_userSavesDir.c_str(); + break; case PortabilityLayer::VirtualDirectories::kPrefs: baseDir = m_prefsDir.c_str(); break; diff --git a/Aerofoil/GpFileSystem_Win32.h b/Aerofoil/GpFileSystem_Win32.h index 847544c..247c93a 100644 --- a/Aerofoil/GpFileSystem_Win32.h +++ b/Aerofoil/GpFileSystem_Win32.h @@ -19,6 +19,7 @@ public: PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) override; bool PromptSaveFile(PortabilityLayer::VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName) override; + bool PromptOpenFile(PortabilityLayer::VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity) override; bool ValidateFilePath(const char *path, size_t sz) const override; @@ -34,6 +35,7 @@ private: std::wstring m_packagedDir; std::wstring m_housesDir; std::wstring m_userHousesDir; + std::wstring m_userSavesDir; std::wstring m_resourcesDir; wchar_t m_executablePath[MAX_PATH]; diff --git a/Aerofoil/GpPLGlueAudioDriver.cpp b/Aerofoil/GpPLGlueAudioDriver.cpp index f85ccc2..703c5b2 100644 --- a/Aerofoil/GpPLGlueAudioDriver.cpp +++ b/Aerofoil/GpPLGlueAudioDriver.cpp @@ -1,12 +1,12 @@ -#include "GpPLGlueAudioDriver.h" +#include "GpPLGlueAudioDriver.h" -#include "GpPLGlueAudioChannel.h" -#include "IGpAudioChannel.h" -#include "IGpAudioDriver.h" - -GpPLGlueAudioDriver::GpPLGlueAudioDriver() - : m_audioDriver(nullptr) -{ +#include "GpPLGlueAudioChannel.h" +#include "IGpAudioChannel.h" +#include "IGpAudioDriver.h" + +GpPLGlueAudioDriver::GpPLGlueAudioDriver() + : m_audioDriver(nullptr) +{ } PortabilityLayer::HostAudioChannel *GpPLGlueAudioDriver::CreateChannel() @@ -17,22 +17,27 @@ PortabilityLayer::HostAudioChannel *GpPLGlueAudioDriver::CreateChannel() PortabilityLayer::HostAudioChannel *glueChannel = GpPLGlueAudioChannel::Create(channel); if (!glueChannel) - { + { channel->Destroy(); - return nullptr; + return nullptr; } - return glueChannel; -} - -GpPLGlueAudioDriver *GpPLGlueAudioDriver::GetInstance() -{ - return &ms_instance; -} - -void GpPLGlueAudioDriver::SetGpAudioDriver(IGpAudioDriver *audioDriver) -{ - m_audioDriver = audioDriver; -} - -GpPLGlueAudioDriver GpPLGlueAudioDriver::ms_instance; + return glueChannel; +} + +void GpPLGlueAudioDriver::SetMasterVolume(uint32_t vol, uint32_t maxVolume) +{ + m_audioDriver->SetMasterVolume(vol, maxVolume); +} + +GpPLGlueAudioDriver *GpPLGlueAudioDriver::GetInstance() +{ + return &ms_instance; +} + +void GpPLGlueAudioDriver::SetGpAudioDriver(IGpAudioDriver *audioDriver) +{ + m_audioDriver = audioDriver; +} + +GpPLGlueAudioDriver GpPLGlueAudioDriver::ms_instance; diff --git a/Aerofoil/GpPLGlueAudioDriver.h b/Aerofoil/GpPLGlueAudioDriver.h index 0796b3d..b108c7b 100644 --- a/Aerofoil/GpPLGlueAudioDriver.h +++ b/Aerofoil/GpPLGlueAudioDriver.h @@ -10,6 +10,7 @@ public: GpPLGlueAudioDriver(); PortabilityLayer::HostAudioChannel *CreateChannel() override; + void SetMasterVolume(uint32_t vol, uint32_t maxVolume) override; void SetGpAudioDriver(IGpAudioDriver *audioDriver); diff --git a/GpApp/Coordinates.cpp b/GpApp/Coordinates.cpp index a156d4c..63e50c2 100644 --- a/GpApp/Coordinates.cpp +++ b/GpApp/Coordinates.cpp @@ -13,6 +13,7 @@ #include "Marquee.h" #include "ObjectEdit.h" #include "RectUtils.h" +#include "WindowManager.h" Rect coordWindowRect; @@ -142,12 +143,10 @@ void OpenCoordWindow (void) // isCoordV = 204; // } MoveWindow(coordWindow, isCoordH, isCoordV, true); - globalMouse = MyGetGlobalMouse(); - QSetRect(&src, 0, 0, 1, 1); - QOffsetRect(&src, globalMouse.h, globalMouse.v); + GetWindowRect(coordWindow, &dest); BringToFront(coordWindow); - ShowHide(coordWindow, true); + PortabilityLayer::WindowManager::GetInstance()->ShowWindow(coordWindow); // FlagWindowFloating(coordWindow); TEMP - use flaoting windows HiliteAllWindows(); diff --git a/GpApp/DialogUtils.cpp b/GpApp/DialogUtils.cpp index e853510..e7cd69b 100644 --- a/GpApp/DialogUtils.cpp +++ b/GpApp/DialogUtils.cpp @@ -465,8 +465,7 @@ void SetDialogNumToStr (Dialog *theDialog, short item, long theNumber) short itemType; NumToString(theNumber, theString); - GetDialogItem(theDialog, item, &itemType, &itemHandle, &itemRect); - SetDialogItemText(itemHandle, theString); + theDialog->GetItems()[item - 1].GetWidget()->SetString(theString); } //-------------------------------------------------------------- GetDialogNumFromStr diff --git a/GpApp/Events.cpp b/GpApp/Events.cpp index 9f3f26e..7b4ebb9 100644 --- a/GpApp/Events.cpp +++ b/GpApp/Events.cpp @@ -521,6 +521,8 @@ void HandleEvent (void) void HiliteAllWindows (void) { + PL_NotYetImplemented_TODO("DeleteMe"); +#if 0 if (mainWindow != nil) HiliteWindow(mainWindow, true); if (mapWindow != nil) @@ -531,6 +533,7 @@ void HiliteAllWindows (void) HiliteWindow(coordWindow, true); if (linkWindow != nil) HiliteWindow(linkWindow, true); +#endif } //-------------------------------------------------------------- IgnoreThisClick diff --git a/GpApp/Externs.h b/GpApp/Externs.h index 238cd15..70bc6ff 100644 --- a/GpApp/Externs.h +++ b/GpApp/Externs.h @@ -188,7 +188,6 @@ void CollapseStringToWidth (DrawSurface *, StringPtr, short); void GetChooserName (StringPtr); StringPtr GetLocalizedString (short, StringPtr); -Point MyGetGlobalMouse (void); // --- Utilities.c void ToolBoxInit (void); void FindOurDevice (void); short RandomInt (short); diff --git a/GpApp/House.cpp b/GpApp/House.cpp index 3bd5a14..58c8b2a 100644 --- a/GpApp/House.cpp +++ b/GpApp/House.cpp @@ -20,6 +20,7 @@ #include "RectUtils.h" #include "ResourceManager.h" +#include #define kGoToDialogID 1043 @@ -69,6 +70,11 @@ Boolean CreateNewHouse (void) if (!fm->PromptSaveFile(theSpec.m_dir, savePath, savePathLength, sizeof(theSpec.m_name), PSTR("My House"))) return false; + assert(savePathLength < sizeof(theSpec.m_name) - 1); + + theSpec.m_name[0] = static_cast(savePathLength); + memcpy(theSpec.m_name + 1, savePath, savePathLength); + if (fm->FileExists(theSpec.m_dir, theSpec.m_name)) { if (!fm->DeleteFile(theSpec.m_dir, theSpec.m_name)) diff --git a/GpApp/HouseInfo.cpp b/GpApp/HouseInfo.cpp index 24153ca..18cee23 100644 --- a/GpApp/HouseInfo.cpp +++ b/GpApp/HouseInfo.cpp @@ -175,7 +175,7 @@ Boolean HouseFilter (Dialog *dial, EventRecord *event, short *item) default: mouseIs = event->where; - GlobalToLocal(&mouseIs); + mouseIs -= dial->GetWindow()->TopLeftCoord(); if ((PtInRect(mouseIs, &houseEditText1)) || (PtInRect(mouseIs, &houseEditText2))) { diff --git a/GpApp/Link.cpp b/GpApp/Link.cpp index 37f352e..23b4d89 100644 --- a/GpApp/Link.cpp +++ b/GpApp/Link.cpp @@ -11,7 +11,9 @@ #include "Environ.h" #include "ObjectEdit.h" #include "RectUtils.h" - +#include "PLButtonWidget.h" +#include "PLWidgets.h" +#include "WindowManager.h" #define kLinkControlID 130 #define kUnlinkControlID 131 @@ -22,7 +24,7 @@ void DoUnlink (void); Rect linkWindowRect; -ControlHandle linkControl, unlinkControl; +PortabilityLayer::Widget *linkControl, *unlinkControl; WindowPtr linkWindow; short isLinkH, isLinkV, linkRoom, linkType; Byte linkObject; @@ -227,22 +229,24 @@ void OpenLinkWindow (void) PSTR("Link"), false, kWindoidWDEF, kPutInFront, true, 0L); MoveWindow(linkWindow, isLinkH, isLinkV, true); - globalMouse = MyGetGlobalMouse(); - QSetRect(&src, 0, 0, 1, 1); - QOffsetRect(&src, globalMouse.h, globalMouse.v); + GetWindowRect(linkWindow, &dest); BringToFront(linkWindow); - ShowHide(linkWindow, true); + PortabilityLayer::WindowManager::GetInstance()->ShowWindow(linkWindow); // FlagWindowFloating(linkWindow); TEMP - use flaoting windows HiliteAllWindows(); - - linkControl = GetNewControl(kLinkControlID, linkWindow); - if (linkControl == nil) - RedAlert(kErrFailedResourceLoad); - - unlinkControl = GetNewControl(kUnlinkControlID, linkWindow); - if (unlinkControl == nil) - RedAlert(kErrFailedResourceLoad); + + PortabilityLayer::WidgetBasicState basicState; + basicState.m_rect = Rect::Create(5, 70, 25, 124); + basicState.m_text.Set(4, "Link"); + basicState.m_window = linkWindow; + + linkControl = PortabilityLayer::ButtonWidget::Create(basicState); + + basicState.m_rect = Rect::Create(5, 5, 25, 59); + basicState.m_text.Set(6, "Unlink"); + basicState.m_window = linkWindow; + unlinkControl = PortabilityLayer::ButtonWidget::Create(basicState); linkRoom = -1; linkObject = 255; @@ -361,14 +365,14 @@ void DoUnlink (void) void HandleLinkClick (Point wherePt) { #ifndef COMPILEDEMO - ControlHandle theControl; + PortabilityLayer::Widget *theControl; short part; if (linkWindow == nil) return; SetPortWindowPort(linkWindow); - GlobalToLocal(&wherePt); + wherePt -= linkWindow->TopLeftCoord(); part = FindControl(wherePt, linkWindow, &theControl); if ((theControl != nil) && (part != 0)) diff --git a/GpApp/MainWindow.cpp b/GpApp/MainWindow.cpp index 9db5326..5ac8a41 100644 --- a/GpApp/MainWindow.cpp +++ b/GpApp/MainWindow.cpp @@ -385,7 +385,7 @@ void HandleMainClick (Point wherePt, Boolean isDoubleClick) return; SetPortWindowPort(mainWindow); - GlobalToLocal(&wherePt); + wherePt -= mainWindow->TopLeftCoord(); DrawSurface *mainWindowSurface = mainWindow->GetDrawSurface(); diff --git a/GpApp/Map.cpp b/GpApp/Map.cpp index 1ebea12..7cfb8f3 100644 --- a/GpApp/Map.cpp +++ b/GpApp/Map.cpp @@ -12,6 +12,10 @@ #include "Externs.h" #include "Environ.h" #include "House.h" +#include "PLScrollBarWidget.h" +#include "PLWidgets.h" +#include "WindowDef.h" +#include "WindowManager.h" #include "RectUtils.h" #include "Utilities.h" @@ -40,7 +44,7 @@ Rect mapHScrollRect, mapVScrollRect, mapCenterRect; Rect mapWindowRect; DrawSurface *nailSrcMap; WindowPtr mapWindow; -ControlHandle mapHScroll, mapVScroll; +PortabilityLayer::Widget *mapHScroll, *mapVScroll; short isMapH, isMapV, mapRoomsHigh, mapRoomsWide; short mapLeftRoom, mapTopRoom; Boolean isMapOpen, doPrettyMap; @@ -91,8 +95,8 @@ void CenterMapOnRoom (short h, short v) if (mapWindow != nil) { - SetControlValue(mapHScroll, mapLeftRoom); - SetControlValue(mapVScroll, mapTopRoom); + mapHScroll->SetState(mapLeftRoom); + mapVScroll->SetState(mapTopRoom); } } #endif @@ -294,12 +298,13 @@ void UpdateMapWindow (void) if (mapWindow == nil) return; - SetControlValue(mapHScroll, mapLeftRoom); - SetControlValue(mapVScroll, mapTopRoom); + mapHScroll->SetState(mapLeftRoom); + mapVScroll->SetState(mapTopRoom); + + mapWindow->DrawControls(); SetPortWindowPort(mapWindow); - DrawControls(mapWindow); - DrawGrowIcon(mapWindow); + // PL_NotYetImplemented_TODO("Resize") RedrawMapContents(); #endif } @@ -328,17 +333,15 @@ void ResizeMapWindow (short newH, short newV) surface->FillRect(mapWindowRect); SizeWindow(mapWindow, mapWindowRect.right, mapWindowRect.bottom, true); - SetControlMaximum(mapHScroll, kMaxNumRoomsH - mapRoomsWide); - MoveControl(mapHScroll, 0, mapWindowRect.bottom - kMapScrollBarWidth + 2); - SizeControl(mapHScroll, mapWindowRect.right - kMapScrollBarWidth + 3, - kMapScrollBarWidth); - mapLeftRoom = GetControlValue(mapHScroll); + mapHScroll->SetMax(kMaxNumRoomsH - mapRoomsWide); + mapHScroll->SetPosition(Point::Create(0, mapWindowRect.bottom - kMapScrollBarWidth + 2)); + mapHScroll->Resize(mapWindowRect.right - kMapScrollBarWidth + 3, kMapScrollBarWidth); + mapLeftRoom = mapHScroll->GetState(); - SetControlMaximum(mapVScroll, kMaxNumRoomsV - mapRoomsHigh); - MoveControl(mapVScroll, mapWindowRect.right - kMapScrollBarWidth + 2, 0); - SizeControl(mapVScroll, kMapScrollBarWidth, - mapWindowRect.bottom - kMapScrollBarWidth + 3); - mapTopRoom = GetControlValue(mapVScroll); + mapVScroll->SetMax(kMaxNumRoomsV - mapRoomsHigh); + mapVScroll->SetPosition(Point::Create(mapWindowRect.right - kMapScrollBarWidth + 2, 0)); + mapVScroll->Resize(kMapScrollBarWidth, mapWindowRect.bottom - kMapScrollBarWidth + 3); + mapTopRoom = mapVScroll->GetState(); InvalWindowRect(mapWindow, &mapWindowRect); #endif @@ -350,7 +353,6 @@ void OpenMapWindow (void) { #ifndef COMPILEDEMO Rect src, dest; - Point globalMouse; if (mapWindow == nil) { @@ -358,9 +360,11 @@ void OpenMapWindow (void) QSetRect(&mapWindowRect, 0, 0, mapRoomsWide * kMapRoomWidth + kMapScrollBarWidth - 2, mapRoomsHigh * kMapRoomHeight + kMapScrollBarWidth - 2); - mapWindow = NewCWindow(nil, &mapWindowRect, - PSTR("Map"), false, kWindoidGrowWDEF, kPutInFront, true, 0L); + + PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(mapWindowRect, kWindoidGrowWDEF, false, true, 0, 0, PSTR("Map")); + mapWindow = PortabilityLayer::WindowManager::GetInstance()->CreateWindow(wdef); + if (mapWindow == nil) RedAlert(kErrNoMemory); @@ -370,32 +374,46 @@ void OpenMapWindow (void) // isMapV = qd.screenBits.bounds.bottom - 100; // } MoveWindow(mapWindow, isMapH, isMapV, true); - globalMouse = MyGetGlobalMouse(); + QSetRect(&wasActiveRoomRect, 0, 0, 1, 1); QSetRect(&activeRoomRect, 0, 0, 1, 1); - QSetRect(&src, 0, 0, 1, 1); - QOffsetRect(&src, globalMouse.h, globalMouse.v); + GetWindowRect(mapWindow, &dest); - BringToFront(mapWindow); - ShowHide(mapWindow, true); + PortabilityLayer::WindowManager::GetInstance()->PutWindowBehind(mapWindow, kPutInFront); + PortabilityLayer::WindowManager::GetInstance()->ShowWindow(mapWindow); // FlagWindowFloating(mapWindow); TEMP - use flaoting windows - HiliteAllWindows(); SetPort((GrafPtr)mapWindow); - SetOrigin(1, 1); QSetRect(&mapHScrollRect, -1, mapRoomsHigh * kMapRoomHeight, mapRoomsWide * kMapRoomWidth + 1, mapRoomsHigh * kMapRoomHeight + kMapScrollBarWidth); QSetRect(&mapVScrollRect, mapRoomsWide * kMapRoomWidth, -1, mapRoomsWide * kMapRoomWidth + kMapScrollBarWidth, mapRoomsHigh * kMapRoomHeight + 1); - mapHScroll = NewControl(mapWindow, &mapHScrollRect, PSTR(""), true, mapLeftRoom, - 0, kMaxNumRoomsH - mapRoomsWide, scrollBarProc, kHScrollRef); + + { + PortabilityLayer::WidgetBasicState state; + state.m_rect = mapHScrollRect; + state.m_refConstant = kHScrollRef; + state.m_window = mapWindow; + state.m_max = kMaxNumRoomsH - mapRoomsWide; + state.m_state = mapLeftRoom; + mapHScroll = PortabilityLayer::ScrollBarWidget::Create(state); + } + if (mapHScroll == nil) RedAlert(kErrNoMemory); - - mapVScroll = NewControl(mapWindow, &mapVScrollRect, PSTR(""), true, mapTopRoom, - 0, kMaxNumRoomsV - mapRoomsHigh, scrollBarProc, kVScrollRef); + + { + PortabilityLayer::WidgetBasicState state; + state.m_rect = mapVScrollRect; + state.m_refConstant = kVScrollRef; + state.m_window = mapWindow; + state.m_max = kMaxNumRoomsV - mapRoomsHigh; + state.m_state = mapTopRoom; + mapVScroll = PortabilityLayer::ScrollBarWidget::Create(state); + } + if (mapVScroll == nil) RedAlert(kErrNoMemory); @@ -575,7 +593,7 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) SetPortWindowPort(mapWindow); globalWhere = wherePt; - GlobalToLocal(&wherePt); + wherePt -= mapWindow->TopLeftCoord(); wherePt.h -= 1; wherePt.v -= 1; diff --git a/GpApp/Menu.cpp b/GpApp/Menu.cpp index 968a9d9..0de6bb7 100644 --- a/GpApp/Menu.cpp +++ b/GpApp/Menu.cpp @@ -9,6 +9,8 @@ //#include #include "PLNumberFormatting.h" #include "PLKeyEncoding.h" +#include "PLHacks.h" +#include "PLMenus.h" #include "PLPasStr.h" #include "PLToolUtils.h" #include "DialogManager.h" @@ -172,32 +174,34 @@ void UpdateClipboardMenus (void) if (!houseOpen) return; + + PortabilityLayer::MenuManager *mm = PortabilityLayer::MenuManager::GetInstance(); if (houseUnlocked) { if (objActive > kNoObjectSelected) { GetLocalizedString(36, title); - SetMenuItemText(houseMenu, iCut, title); + mm->SetItemText(houseMenu, iCut - 1, title); GetLocalizedString(37, title); - SetMenuItemText(houseMenu, iCopy, title); + mm->SetItemText(houseMenu, iCopy - 1, title); GetLocalizedString(38, title); - SetMenuItemText(houseMenu, iClear, title); - EnableMenuItem(houseMenu, iDuplicate); + mm->SetItemText(houseMenu, iClear - 1, title); + mm->SetItemEnabled(houseMenu, iDuplicate - 1, false); } else { GetLocalizedString(39, title); - SetMenuItemText(houseMenu, iCut, title); + mm->SetItemText(houseMenu, iCut - 1, title); GetLocalizedString(40, title); - SetMenuItemText(houseMenu, iCopy, title); + mm->SetItemText(houseMenu, iCopy - 1, title); GetLocalizedString(41, title); - SetMenuItemText(houseMenu, iClear, title); - DisableMenuItem(houseMenu, iDuplicate); + mm->SetItemText(houseMenu, iClear - 1, title); + mm->SetItemEnabled(houseMenu, iDuplicate - 1, false); } - EnableMenuItem(houseMenu, iCut); - EnableMenuItem(houseMenu, iCopy); + mm->SetItemEnabled(houseMenu, iCut - 1, true); + mm->SetItemEnabled(houseMenu, iCopy - 1, true); // if (hasScrap) // { // EnableMenuItem(houseMenu, iPaste); @@ -214,27 +218,27 @@ void UpdateClipboardMenus (void) // } // else { - DisableMenuItem(houseMenu, iPaste); + mm->SetItemEnabled(houseMenu, iPaste - 1, false); GetLocalizedString(44, title); - SetMenuItemText(houseMenu, iPaste, title); + mm->SetItemText(houseMenu, iPaste - 1, title); } - EnableMenuItem(houseMenu, iClear); - EnableMenuItem(houseMenu, iGoToRoom); - EnableMenuItem(houseMenu, iMapWindow); - EnableMenuItem(houseMenu, iObjectWindow); - EnableMenuItem(houseMenu, iCoordinateWindow); + mm->SetItemEnabled(houseMenu, iClear - 1, true); + mm->SetItemEnabled(houseMenu, iGoToRoom - 1, true); + mm->SetItemEnabled(houseMenu, iMapWindow - 1, true); + mm->SetItemEnabled(houseMenu, iObjectWindow - 1, true); + mm->SetItemEnabled(houseMenu, iCoordinateWindow - 1, true); } else { - DisableMenuItem(houseMenu, iCut); - DisableMenuItem(houseMenu, iCopy); - DisableMenuItem(houseMenu, iPaste); - DisableMenuItem(houseMenu, iClear); - DisableMenuItem(houseMenu, iDuplicate); - DisableMenuItem(houseMenu, iGoToRoom); - DisableMenuItem(houseMenu, iMapWindow); - DisableMenuItem(houseMenu, iObjectWindow); - DisableMenuItem(houseMenu, iCoordinateWindow); + mm->SetItemEnabled(houseMenu, iCut - 1, false); + mm->SetItemEnabled(houseMenu, iCopy - 1, false); + mm->SetItemEnabled(houseMenu, iPaste - 1, false); + mm->SetItemEnabled(houseMenu, iClear - 1, false); + mm->SetItemEnabled(houseMenu, iDuplicate - 1, false); + mm->SetItemEnabled(houseMenu, iGoToRoom - 1, false); + mm->SetItemEnabled(houseMenu, iMapWindow - 1, false); + mm->SetItemEnabled(houseMenu, iObjectWindow - 1, false); + mm->SetItemEnabled(houseMenu, iCoordinateWindow - 1, false); } } @@ -323,7 +327,8 @@ void DoGameMenu (short theItem) case iOpenSavedGame: resumedSavedGame = true; - HeyYourPissingAHighScore(); + if (!IsHighScoreDisabled()) + HeyYourPissingAHighScore(); if (OpenSavedGame()) { twoPlayerGame = false; @@ -780,6 +785,7 @@ void HeyYourPissingAHighScore (void) short whoCares; // CenterAlert(kNoHighScoreAlert); + whoCares = Alert(kNoHighScoreAlert, nil); } diff --git a/GpApp/RectUtils.cpp b/GpApp/RectUtils.cpp index 5d0d12a..7b7f8fc 100644 --- a/GpApp/RectUtils.cpp +++ b/GpApp/RectUtils.cpp @@ -105,35 +105,6 @@ short RectTall (Rect *theRect) return (theRect->bottom - theRect->top); } -//-------------------------------------------------------------- GlobalToLocalRect - -// This function offsets a rectangle from global to local coordinates. -// The "local" coordinate system is assumed to be the current port (window). - -void GlobalToLocalRect (Rect *theRect) -{ - Point upperLeftPt; - - upperLeftPt.h = 0; - upperLeftPt.v = 0; - GlobalToLocal(&upperLeftPt); - QOffsetRect(theRect, upperLeftPt.h, upperLeftPt.v); -} - -//-------------------------------------------------------------- LocalToGlobalRect - -// This function offsets a rectangle from local to global coordinates. -// The "local" coordinate system is assumed to be the current port (window). - -void LocalToGlobalRect (Rect *theRect) -{ - Point upperLeftPt; - - upperLeftPt.h = 0; - upperLeftPt.v = 0; - LocalToGlobal(&upperLeftPt); - QOffsetRect(theRect, upperLeftPt.h, upperLeftPt.v); -} //-------------------------------------------------------------- CenterRectInRect // Given two rectangles, this function centers the first rectangleÉ diff --git a/GpApp/RectUtils.h b/GpApp/RectUtils.h index 62ebef7..dd894b9 100644 --- a/GpApp/RectUtils.h +++ b/GpApp/RectUtils.h @@ -19,8 +19,6 @@ short HalfRectWide (Rect *); short HalfRectTall (Rect *); short RectWide (Rect *); short RectTall (Rect *); -void GlobalToLocalRect (Rect *); -void LocalToGlobalRect (Rect *); void CenterRectInRect (Rect *, Rect *); void HOffsetRect (Rect *, short); void VOffsetRect (Rect *, short); diff --git a/GpApp/RoomInfo.cpp b/GpApp/RoomInfo.cpp index d8e168d..ebba876 100644 --- a/GpApp/RoomInfo.cpp +++ b/GpApp/RoomInfo.cpp @@ -383,7 +383,7 @@ Boolean RoomFilter (Dialog *dial, EventRecord *event, short *item) case mouseDown: mouseIs = event->where; - GlobalToLocal(&mouseIs); + mouseIs -= dial->GetWindow()->TopLeftCoord(); if (PtInRect(mouseIs, &tileSrc)) { if (StillDown()) @@ -693,7 +693,7 @@ Boolean OriginalArtFilter (Dialog *dial, EventRecord *event, short *item) case mouseDown: mouseIs = event->where; - GlobalToLocal(&mouseIs); + mouseIs -= dial->GetWindow()->TopLeftCoord(); if (PtInRect(mouseIs, &leftBound)) { *item = 7; diff --git a/GpApp/SavedGames.cpp b/GpApp/SavedGames.cpp index 4b00b28..8f02634 100644 --- a/GpApp/SavedGames.cpp +++ b/GpApp/SavedGames.cpp @@ -8,7 +8,14 @@ #include "PLStringCompare.h" #include "Externs.h" +#include "FileManager.h" #include "House.h" +#include "IOStream.h" +#include "InputManager.h" +#include "MacFileInfo.h" +#include "MemoryManager.h" + +#include #define kSavedGameVersion 0x0200 @@ -29,62 +36,71 @@ extern Boolean twoPlayerGame; void SaveGame2 (void) { - PL_NotYetImplemented_TODO("SaveGame"); - // Add NavServices later. -/* - StandardFileReply theReply; - FSSpec tempSpec; + // Bringing up the save file UI can cause key/mouse events to be missed, resulting in state being stuck when this comes back. + // To avoid that, clear all state here. + PortabilityLayer::InputManager::GetInstance()->ClearState(); + Str255 gameNameStr; Size byteCount; - PLError_t theErr; houseType *thisHousePtr; roomType *srcRoom; savedRoom *destRoom; gamePtr savedGame; - short r, i, numRooms, gameRefNum; + short r, i, numRooms; char wasState; + PortabilityLayer::IOStream *gameStream = nullptr; + + PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); + PortabilityLayer::FileManager *fm = PortabilityLayer::FileManager::GetInstance(); FlushEvents(everyEvent, 0); - wasState = HGetState((Handle)thisHouse); - HLock((Handle)thisHouse); thisHousePtr = *thisHouse; numRooms = thisHousePtr->nRooms; - HSetState((Handle)thisHouse, wasState); - byteCount = sizeof(game2Type) + sizeof(savedRoom) * numRooms; - savedGame = (gamePtr)NewPtr(byteCount); + savedGame = (gamePtr)mm->Alloc(byteCount); if (savedGame == nil) { YellowAlert(kYellowFailedSaveGame, PLErrors::kOutOfMemory); return; } + + memset(savedGame, 0, byteCount); GetFirstWordOfString(thisHouseName, gameNameStr); if (gameNameStr[0] > 23) gameNameStr[0] = 23; - PasStringConcat(gameNameStr, "\p Game"); - - StandardPutFile("\pSave Game As:", gameNameStr, &theReply); - if (!theReply.sfGood) - return; - - if (theReply.sfReplacing) + PasStringConcat(gameNameStr, PSTR(" Game")); + + VFileSpec spec; + spec.m_dir = PortabilityLayer::VirtualDirectories::kUserSaves; + spec.m_name[0] = 0; + + char savePath[sizeof(spec.m_name) + 1]; + size_t savePathLength = 0; + + if (!fm->PromptSaveFile(spec.m_dir, savePath, savePathLength, sizeof(spec.m_name), PLPasStr(gameNameStr))) { - theErr = FSMakeFSSpec(theReply.sfFile.vRefNum, theReply.sfFile.parID, - theReply.sfFile.name, &tempSpec); - if (!CheckFileError(theErr, "\pSaved Game")) - return; - - theErr = FSpDelete(&tempSpec); - if (!CheckFileError(theErr, "\pSaved Game")) + mm->Release(savedGame); + return; + } + + assert(savePathLength < sizeof(spec.m_name) - 1); + + spec.m_name[0] = static_cast(savePathLength); + memcpy(spec.m_name + 1, savePath, savePathLength); + + if (fm->FileExists(spec.m_dir, PLPasStr(spec.m_name))) + { + if (!fm->DeleteFile(spec.m_dir, spec.m_name)) + { + CheckFileError(PLErrors::kAccessDenied, PSTR("Saved Game")); return; + } } - wasState = HGetState((Handle)thisHouse); - HLock((Handle)thisHouse); thisHousePtr = *thisHouse; savedGame->house = theHousesSpecs[thisHouseIndex]; @@ -117,35 +133,24 @@ void SaveGame2 (void) for (i = 0; i < kMaxRoomObs; i++) destRoom->objects[i] = srcRoom->objects[i]; } - - HSetState((Handle)thisHouse, wasState); - - theErr = FSpCreate(&theReply.sfFile, 'ozm5', 'gliG', theReply.sfScript); - if (CheckFileError(theErr, "\pSaved Game")) + + PLError_t theErr = fm->CreateFileAtCurrentTime(spec.m_dir, spec.m_name, 'ozm5', 'gliG'); + if (CheckFileError(theErr, PSTR("Saved Game"))) { - theErr = FSpOpenDF(&theReply.sfFile, fsCurPerm, &gameRefNum); - if (CheckFileError(theErr, "\pSaved Game")) + theErr = fm->OpenFileData(spec.m_dir, spec.m_name, PortabilityLayer::EFilePermission_Write, gameStream); + + if (CheckFileError(theErr, PSTR("Saved Game"))) { - theErr = SetFPos(gameRefNum, fsFromStart, 0L); - if (CheckFileError(theErr, "\pSaved Game")) - { - theErr = FSWrite(gameRefNum, &byteCount, (Ptr)savedGame); - if (CheckFileError(theErr, "\pSaved Game")) - { - theErr = SetEOF(gameRefNum, byteCount); - if (CheckFileError(theErr, "\pSaved Game")) - { - } - } - } - theErr = FSClose(gameRefNum); - if (CheckFileError(theErr, "\pSaved Game")) + if (gameStream->Write(savedGame, byteCount) != byteCount) { + CheckFileError(PLErrors::kIOError, PSTR("Saved Game")); } + + gameStream->Close(); } } - DisposePtr((Ptr)savedGame); - */ + + mm->Release(savedGame); } //-------------------------------------------------------------- SavedGameMismatchError @@ -167,95 +172,98 @@ void SavedGameMismatchError (StringPtr gameName) Boolean OpenSavedGame (void) { - PL_NotYetImplemented(); -return false; // TEMP fix this iwth NavServices -/* - StandardFileReply theReply; - SFTypeList theList; houseType *thisHousePtr; roomType *destRoom; savedRoom *srcRoom; gamePtr savedGame; - long byteCount; - PLError_t theErr; short r, i, gameRefNum; char wasState; - - theList[0] = 'gliG'; - - StandardGetFile(nil, 1, theList, &theReply); - if (!theReply.sfGood) + + PortabilityLayer::FileManager *fm = PortabilityLayer::FileManager::GetInstance(); + PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); + + + VFileSpec spec; + spec.m_dir = PortabilityLayer::VirtualDirectories::kUserSaves; + spec.m_name[0] = 0; + + char savePath[sizeof(spec.m_name) + 1]; + size_t savePathLength = 0; + + if (!fm->PromptOpenFile(spec.m_dir, savePath, savePathLength, sizeof(spec.m_name))) + return false; + + assert(savePathLength < sizeof(spec.m_name) - 1); + + spec.m_name[0] = static_cast(savePathLength); + memcpy(spec.m_name + 1, savePath, savePathLength); + + PortabilityLayer::MacFileProperties props; + if (!fm->ReadFileProperties(spec.m_dir, spec.m_name, props)) + return false; + + if (memcmp(props.m_fileType, "gliG", 4)) + return false; + + PortabilityLayer::IOStream *gameStream = nullptr; + PLError_t theErr = fm->OpenFileData(spec.m_dir, spec.m_name, PortabilityLayer::EFilePermission_Read, gameStream); + + if (!CheckFileError(theErr, PSTR("Saved Game"))) return(false); - - theErr = FSpOpenDF(&theReply.sfFile, fsCurPerm, &gameRefNum); - if (!CheckFileError(theErr, "\pSaved Game")) - return(false); - - theErr = GetEOF(gameRefNum, &byteCount); - if (!CheckFileError(theErr, "\pSaved Game")) + + const PortabilityLayer::UFilePos_t fileSizeFP = gameStream->Size(); + if (fileSizeFP > SIZE_MAX) { - theErr = FSClose(gameRefNum); - return(false); + gameStream->Close(); + return false; } - - savedGame = (gamePtr)NewPtr(byteCount); + + const size_t byteCount = static_cast(fileSizeFP); + + savedGame = (gamePtr)mm->Alloc(byteCount); if (savedGame == nil) { YellowAlert(kYellowFailedSaveGame, PLErrors::kOutOfMemory); - theErr = FSClose(gameRefNum); + gameStream->Close(); return(false); } - theErr = SetFPos(gameRefNum, fsFromStart, 0L); - if (!CheckFileError(theErr, "\pSaved Game")) + if (gameStream->Read(savedGame, byteCount) != byteCount) { - DisposePtr((Ptr)savedGame); - theErr = FSClose(gameRefNum); + CheckFileError(PLErrors::kIOError, PSTR("Saved Game")); + mm->Release(savedGame); + gameStream->Close(); return(false); } - theErr = FSRead(gameRefNum, &byteCount, savedGame); - if (!CheckFileError(theErr, "\pSaved Game")) - { - DisposePtr((Ptr)savedGame); - theErr = FSClose(gameRefNum); - return(false); - } - - wasState = HGetState((Handle)thisHouse); - HLock((Handle)thisHouse); thisHousePtr = *thisHouse; - if (!StrCmp::Equal(savedGame->house.name, thisHouseName)) + if (!StrCmp::Equal(savedGame->house.m_name, thisHouseName)) { - SavedGameMismatchError(savedGame->house.name); - HSetState((Handle)thisHouse, wasState); - DisposePtr((Ptr)savedGame); - theErr = FSClose(gameRefNum); + SavedGameMismatchError(savedGame->house.m_name); + mm->Release(savedGame); + gameStream->Close(); return(false); } else if (thisHousePtr->timeStamp != savedGame->timeStamp) { YellowAlert(kYellowSavedTimeWrong, 0); - HSetState((Handle)thisHouse, wasState); - DisposePtr((Ptr)savedGame); - theErr = FSClose(gameRefNum); + mm->Release(savedGame); + gameStream->Close(); return(false); } else if (savedGame->version != kSavedGameVersion) { YellowAlert(kYellowSavedVersWrong, kSavedGameVersion); - HSetState((Handle)thisHouse, wasState); - DisposePtr((Ptr)savedGame); - theErr = FSClose(gameRefNum); + mm->Release(savedGame); + gameStream->Close(); return(false); } else if (savedGame->nRooms != thisHousePtr->nRooms) { YellowAlert(kYellowSavedRoomsWrong, savedGame->nRooms - thisHousePtr->nRooms); - HSetState((Handle)thisHouse, wasState); - DisposePtr((Ptr)savedGame); - theErr = FSClose(gameRefNum); + mm->Release(savedGame); + gameStream->Close(); return(false); } else @@ -285,16 +293,11 @@ return false; // TEMP fix this iwth NavServices destRoom->objects[i] = srcRoom->objects[i]; } } - HSetState((Handle)thisHouse, wasState); - - DisposePtr((Ptr)savedGame); - - theErr = FSClose(gameRefNum); - if (!CheckFileError(theErr, "\pSaved Game")) - return (false); - + + mm->Release(savedGame); + gameStream->Close(); + return (true); - */ } //-------------------------------------------------------------- SaveGame diff --git a/GpApp/Settings.cpp b/GpApp/Settings.cpp index 9c0423b..4033c05 100644 --- a/GpApp/Settings.cpp +++ b/GpApp/Settings.cpp @@ -72,17 +72,17 @@ void DoControlPrefs (void); void SoundDefaults (Dialog *); void UpdateSettingsSound (Dialog *); void HandleSoundMusicChange (short, Boolean); -Boolean SoundFilter (Dialog *, EventRecord *, short *); +int16_t SoundFilter(Dialog *, const TimeTaggedVOSEvent &); void DoSoundPrefs (void); void DisplayDefaults (void); void FrameDisplayIcon (Dialog *, const PortabilityLayer::RGBAColor &color); void DisplayUpdate (Dialog *); -Boolean DisplayFilter (Dialog *, EventRecord *, short *); +int16_t DisplayFilter(Dialog *dialog, const TimeTaggedVOSEvent &); void DoDisplayPrefs (void); void SetAllDefaults (void); void FlashSettingsButton (DrawSurface *, short); void UpdateSettingsMain (Dialog *); -Boolean PrefsFilter (Dialog *, EventRecord *, short *); +int16_t PrefsFilter(Dialog *dialog, const TimeTaggedVOSEvent &evt); void BitchAboutChanges (void); @@ -623,8 +623,7 @@ void SoundDefaults (Dialog *theDialog) void UpdateSettingsSound (Dialog *theDialog) { short howLoudNow; - - DrawDialog(theDialog); + DrawDefaultButton(theDialog); UnivGetSoundVolume(&howLoudNow, thisMac.hasSM3); @@ -669,95 +668,66 @@ void HandleSoundMusicChange (short newVolume, Boolean sayIt) //-------------------------------------------------------------- SoundFilter -Boolean SoundFilter (Dialog *dial, EventRecord *event, short *item) +int16_t SoundFilter (Dialog *dial, const TimeTaggedVOSEvent &evt) { short newVolume; - - switch (event->what) + + if (evt.IsKeyDownEvent()) { - case keyDown: - switch (event->message) + intptr_t keyCode = PackVOSKeyCode(evt.m_vosEvent.m_event.m_keyboardInputEvent); + + switch (keyCode) { - case PL_KEY_SPECIAL(kEnter): - case PL_KEY_NUMPAD_SPECIAL(kEnter): + case PL_KEY_SPECIAL(kEnter): + case PL_KEY_NUMPAD_SPECIAL(kEnter): FlashDialogButton(dial, kOkayButton); - *item = kOkayButton; - return(true); - break; - - case PL_KEY_SPECIAL(kEscape): + return kOkayButton; + + case PL_KEY_SPECIAL(kEscape): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - case PL_KEY_SPECIAL(kUpArrow): - *item = kLouderItem; - return(true); - break; - - case PL_KEY_SPECIAL(kDownArrow): - *item = kSofterItem; - return(true); - break; - - case PL_KEY_ASCII('0'): - case PL_KEY_ASCII('1'): - case PL_KEY_ASCII('2'): - case PL_KEY_ASCII('3'): - case PL_KEY_ASCII('4'): - case PL_KEY_ASCII('5'): - case PL_KEY_ASCII('6'): - case PL_KEY_ASCII('7'): - newVolume = PL_KEY_GET_VALUE(event->message) - '0'; + return kCancelButton; + + case PL_KEY_SPECIAL(kUpArrow): + return kLouderItem; + + case PL_KEY_SPECIAL(kDownArrow): + return kSofterItem; + + case PL_KEY_ASCII('0'): + case PL_KEY_ASCII('1'): + case PL_KEY_ASCII('2'): + case PL_KEY_ASCII('3'): + case PL_KEY_ASCII('4'): + case PL_KEY_ASCII('5'): + case PL_KEY_ASCII('6'): + case PL_KEY_ASCII('7'): + newVolume = PL_KEY_GET_VALUE(keyCode) - '0'; if (newVolume == 7L) SetDialogNumToStr(dial, kVolNumberItem, 11L); else SetDialogNumToStr(dial, kVolNumberItem, (long)newVolume); - + UnivSetSoundVolume(newVolume, thisMac.hasSM3); - + HandleSoundMusicChange(newVolume, true); - return(false); - break; - - case PL_KEY_ASCII('D'): - *item = kSoundDefault; + return -1; + + case PL_KEY_ASCII('D'): FlashDialogButton(dial, kSoundDefault); - return(true); - break; - - case PL_KEY_ASCII('G'): - *item = kPlayMusicItem; - return(true); - break; - - case PL_KEY_ASCII('I'): - *item = kIdleMusicItem; - return(true); - break; - - default: - return(false); - } - break; - - case mouseDown: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateSettingsSound(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kSoundDefault; + + case PL_KEY_ASCII('G'): + return kPlayMusicItem; + + case PL_KEY_ASCII('I'): + return kIdleMusicItem; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- DoSettingsMain @@ -767,13 +737,15 @@ void DoSoundPrefs (void) Rect tempRect; Dialog *prefDlg; short wasLoudness, tempVolume; - PLError_t theErr; + PLError_t theErr; short itemHit; Boolean leaving; BringUpDialog(&prefDlg, kSoundPrefsDialID); DrawSurface *surface = prefDlg->GetWindow()->GetDrawSurface(); + + UpdateSettingsSound(prefDlg); UnivGetSoundVolume(&wasLoudness, thisMac.hasSM3); @@ -785,7 +757,7 @@ void DoSoundPrefs (void) while (!leaving) { - ModalDialog(SoundFilter, &itemHit); + itemHit = prefDlg->ExecuteModal(SoundFilter); switch (itemHit) { case kOkayButton: @@ -829,7 +801,7 @@ void DoSoundPrefs (void) SetDialogNumToStr(prefDlg, kVolNumberItem, (long)tempVolume); UnivSetSoundVolume(tempVolume, thisMac.hasSM3); HandleSoundMusicChange(tempVolume, true); - InvalWindowRect(prefDlg->GetWindow(), &tempRect); + //InvalWindowRect(prefDlg->GetWindow(), &tempRect); DelayTicks(8); } break; @@ -847,7 +819,7 @@ void DoSoundPrefs (void) SetDialogNumToStr(prefDlg, kVolNumberItem, tempVolume); UnivSetSoundVolume(tempVolume, thisMac.hasSM3); HandleSoundMusicChange(tempVolume, true); - InvalWindowRect(prefDlg->GetWindow(), &tempRect); + //InvalWindowRect(prefDlg->GetWindow(), &tempRect); DelayTicks(8); } break; diff --git a/GpApp/Tools.cpp b/GpApp/Tools.cpp index 3d71a8c..a1e622f 100644 --- a/GpApp/Tools.cpp +++ b/GpApp/Tools.cpp @@ -12,8 +12,12 @@ #include "Externs.h" #include "Environ.h" #include "FontFamily.h" +#include "PLWidgets.h" +#include "PLPopupMenuWidget.h" #include "RectUtils.h" #include "Utilities.h" +#include "WindowDef.h" +#include "WindowManager.h" #define kToolsHigh 4 @@ -60,7 +64,7 @@ void SwitchToolModes (short); Rect toolsWindowRect, toolSrcRect, toolTextRect; Rect toolRects[kTotalTools]; -ControlHandle classPopUp; +PortabilityLayer::Widget *classPopUp; DrawSurface *toolSrcMap; WindowPtr toolsWindow; short isToolsH, isToolsV; @@ -285,6 +289,8 @@ void OpenToolsWindow (void) Rect src, dest; Point globalMouse; short h, v; + + PortabilityLayer::WindowManager *wm = PortabilityLayer::WindowManager::GetInstance(); if (toolsWindow == nil) { @@ -292,12 +298,11 @@ void OpenToolsWindow (void) QSetRect(&toolTextRect, 0, 0, 116, 12); InsetRect(&toolTextRect, -1, -1); QOffsetRect(&toolTextRect, 0, 157 - 15); - if (thisMac.hasColor) - toolsWindow = NewCWindow(nil, &toolsWindowRect, - PSTR("Tools"), false, kWindoidWDEF, kPutInFront, true, 0L); - else - toolsWindow = NewWindow(nil, &toolsWindowRect, - PSTR("Tools"), false, kWindoidWDEF, kPutInFront, true, 0L); + + { + PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(toolsWindowRect, kWindoidWDEF, false, true, 0, 0, PSTR("Tools")); + toolsWindow = wm->CreateWindow(wdef); + } if (toolsWindow == nil) RedAlert(kErrNoMemory); @@ -308,20 +313,29 @@ void OpenToolsWindow (void) // isToolsV = 35; // } MoveWindow(toolsWindow, isToolsH, isToolsV, true); - globalMouse = MyGetGlobalMouse(); - QSetRect(&src, 0, 0, 1, 1); - QOffsetRect(&src, globalMouse.h, globalMouse.v); + GetWindowRect(toolsWindow, &dest); - BringToFront(toolsWindow); - ShowHide(toolsWindow, true); + wm->PutWindowBehind(toolsWindow, wm->GetPutInFrontSentinel()); + wm->ShowWindow(toolsWindow); // FlagWindowFloating(toolsWindow); TEMP - use flaoting windows HiliteAllWindows(); - - classPopUp = GetNewControl(kPopUpControl, toolsWindow); + + { + PortabilityLayer::WidgetBasicState state; + state.m_min = 1; + state.m_max = 3; + state.m_rect = Rect::Create(2, 4, 22, 112); + state.m_state = 1; + state.m_resID = 141; + state.m_window = toolsWindow; + + classPopUp = PortabilityLayer::PopupMenuWidget::Create(state); + } + if (classPopUp == nil) RedAlert(kErrFailedResourceLoad); - SetControlValue(classPopUp, toolMode); + classPopUp->SetState(toolMode); for (v = 0; v < kToolsHigh; v++) for (h = 0; h < kToolsWide; h++) @@ -436,7 +450,6 @@ void SwitchToolModes (short newMode) } toolMode = newMode; - InvalWindowRect(toolsWindow, &toolsWindowRect); } #endif @@ -452,7 +465,7 @@ void HandleToolsClick (Point wherePt) return; SetPortWindowPort(toolsWindow); - GlobalToLocal(&wherePt); + wherePt -= toolsWindow->TopLeftCoord(); part = FindControl(wherePt, toolsWindow, &theControl); if ((theControl != nil) && (part != 0)) @@ -505,7 +518,7 @@ void NextToolMode (void) { EraseSelectedTool(); toolMode++; - SetControlValue(classPopUp, toolMode); + classPopUp->SetState(toolMode); SwitchToolModes(toolMode); toolSelected = kSelectTool; } @@ -524,7 +537,7 @@ void PrevToolMode (void) { EraseSelectedTool(); toolMode--; - SetControlValue(classPopUp, toolMode); + classPopUp->SetState(toolMode); SwitchToolModes(toolMode); toolSelected = kSelectTool; } @@ -541,7 +554,7 @@ void SetSpecificToolMode (short modeToSet) EraseSelectedTool(); toolMode = modeToSet; - SetControlValue(classPopUp, toolMode); + classPopUp->SetState(toolMode); SwitchToolModes(toolMode); toolSelected = kSelectTool; #endif diff --git a/GpApp/Utilities.cpp b/GpApp/Utilities.cpp index 2aaed3d..8e17d3c 100644 --- a/GpApp/Utilities.cpp +++ b/GpApp/Utilities.cpp @@ -14,6 +14,7 @@ #include "QDPixMap.h" #include "Externs.h" #include "IconLoader.h" +#include "InputManager.h" #include "ResourceFile.h" #include "Utilities.h" @@ -24,19 +25,6 @@ UInt32 theSeed; extern Boolean switchedOut; -//============================================================== Functions -//-------------------------------------------------------------- MyGetGlobalMouse -// Returns the position of the mouse in global coordinates. - -Point MyGetGlobalMouse (void) -{ - Point localWhere; - - GetMouse(&localWhere); - LocalToGlobal(&localWhere); - return (localWhere); -} - //-------------------------------------------------------------- ToolBoxInit // The standard ToolBox intialization that must happen when any MacÉ @@ -574,8 +562,8 @@ void UnivSetSoundVolume (short volume, Boolean hasSM3) // if (hasSM3) // { longVol = (long)volume * 0x0025; - if (longVol > 0x00000100) - longVol = 0x00000100; + if (longVol > 0xff) + longVol = 0xff; PortabilityLayer::SoundSystem::GetInstance()->SetVolume(longVol); // } diff --git a/GpApp/WindowUtils.cpp b/GpApp/WindowUtils.cpp index d228d17..64df0ad 100644 --- a/GpApp/WindowUtils.cpp +++ b/GpApp/WindowUtils.cpp @@ -27,21 +27,15 @@ WindowPtr mssgWindow; void GetWindowLeftTop (WindowPtr theWindow, short *left, short *top) { - Point thePoint; - Rect bounds; - - *left = 0; - *top = 0; - - if (theWindow != nil) + if (theWindow == nullptr) { - SetPortWindowPort(theWindow); - GetWindowBounds(theWindow, kWindowContentRgn, &bounds); - thePoint.h = bounds.left; - thePoint.v = bounds.top; - LocalToGlobal(&thePoint); - *left = thePoint.h; - *top = thePoint.v; + *left = 0; + *top = 0; + } + else + { + *left = static_cast(theWindow->m_wmX); + *top = static_cast(theWindow->m_wmY); } } @@ -53,9 +47,9 @@ void GetWindowRect (WindowPtr theWindow, Rect *bounds) { if (theWindow != nil) { - SetPortWindowPort(theWindow); - GetWindowBounds(theWindow, kWindowContentRgn, bounds); - LocalToGlobalRect(bounds); + Point upperLeft; + GetWindowLeftTop(theWindow, &upperLeft.h, &upperLeft.v); + *bounds = theWindow->m_surface.m_port.GetRect() + upperLeft; } } diff --git a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp index cc15366..fb2a8ac 100644 --- a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp +++ b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.cpp @@ -67,6 +67,11 @@ IGpAudioChannel *GpAudioDriverXAudio2::CreateChannel() return GpAudioChannelXAudio2::Create(this); } +void GpAudioDriverXAudio2::SetMasterVolume(uint32_t vol, uint32_t maxVolume) +{ + m_mv->SetVolume(static_cast(vol) / static_cast(maxVolume)); +} + GpAudioDriverXAudio2::GpAudioDriverXAudio2(const GpAudioDriverProperties &properties, unsigned int realSampleRate, IXAudio2* xa2, IXAudio2MasteringVoice *mv) : m_properties(properties) , m_realSampleRate(realSampleRate) diff --git a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h index 227e41e..edc2595 100644 --- a/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h +++ b/GpAudioDriver_XAudio2/GpAudioDriverXAudio2.h @@ -10,7 +10,8 @@ struct IXAudio2MasteringVoice; class GpAudioDriverXAudio2 : public IGpAudioDriver { public: - IGpAudioChannel *CreateChannel() override; + IGpAudioChannel *CreateChannel() override; + void SetMasterVolume(uint32_t vol, uint32_t maxVolume) override; void Shutdown() override; const GpAudioDriverProperties &GetProperties() const; diff --git a/GpCommon/IGpAudioDriver.h b/GpCommon/IGpAudioDriver.h index ca65eb3..f3b16cb 100644 --- a/GpCommon/IGpAudioDriver.h +++ b/GpCommon/IGpAudioDriver.h @@ -1,5 +1,7 @@ #pragma once +#include + struct IGpAudioChannel; struct IGpAudioDriver @@ -7,5 +9,7 @@ struct IGpAudioDriver public: virtual IGpAudioChannel *CreateChannel() = 0; + virtual void SetMasterVolume(uint32_t vol, uint32_t maxVolume) = 0; + virtual void Shutdown() = 0; }; diff --git a/PortabilityLayer/DialogManager.cpp b/PortabilityLayer/DialogManager.cpp index a3c7459..b9485c0 100644 --- a/PortabilityLayer/DialogManager.cpp +++ b/PortabilityLayer/DialogManager.cpp @@ -5,11 +5,13 @@ #include "PLArrayView.h" #include "PLBigEndian.h" #include "PLButtonWidget.h" +#include "PLCheckboxWidget.h" #include "PLDialogs.h" #include "PLIconWidget.h" #include "PLImageWidget.h" #include "PLInvisibleWidget.h" #include "PLLabelWidget.h" +#include "PLRadioButtonWidget.h" #include "PLPasStr.h" #include "PLStandardColors.h" #include "PLSysCalls.h" @@ -108,8 +110,6 @@ namespace PortabilityLayer DialogItem::~DialogItem() { - if (m_widget) - m_widget->Destroy(); } Widget *DialogItem::GetWidget() const @@ -303,7 +303,11 @@ namespace PortabilityLayer widget = ImageWidget::Create(basicState); break; case SerializedDialogItemTypeCodes::kCheckBox: + //widget = CheckboxWidget::Create(basicState); + //break; case SerializedDialogItemTypeCodes::kRadioButton: + widget = RadioButtonWidget::Create(basicState); + break; case SerializedDialogItemTypeCodes::kEditBox: default: widget = InvisibleWidget::Create(basicState); @@ -321,21 +325,7 @@ namespace PortabilityLayer void DialogImpl::DrawControls(bool redraw) { - DrawSurface *surface = m_window->GetDrawSurface(); - - if (redraw) - { - surface->SetForeColor(StdColors::White()); - surface->FillRect(surface->m_port.GetRect()); - } - - for (ArrayViewIterator it = GetItems().begin(), itEnd = GetItems().end(); it != itEnd; ++it) - { - const DialogItem &item = *it; - Widget *widget = item.GetWidget(); - if (widget->IsVisible()) - widget->DrawControl(surface); - } + m_window->DrawControls(); } Point DialogImpl::MouseToDialog(const GpMouseInputEvent &evt) diff --git a/PortabilityLayer/FileManager.cpp b/PortabilityLayer/FileManager.cpp index e662a47..3680ceb 100644 --- a/PortabilityLayer/FileManager.cpp +++ b/PortabilityLayer/FileManager.cpp @@ -33,6 +33,7 @@ namespace PortabilityLayer PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t creationDisposition, IOStream *&outStream) override; bool PromptSaveFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName) override; + bool PromptOpenFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity) override; static FileManagerImpl *GetInstance(); @@ -181,6 +182,11 @@ namespace PortabilityLayer return PortabilityLayer::HostFileSystem::GetInstance()->PromptSaveFile(dirID, path, outPathLength, pathCapacity, extFN); } + bool FileManagerImpl::PromptOpenFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity) + { + return PortabilityLayer::HostFileSystem::GetInstance()->PromptOpenFile(dirID, path, outPathLength, pathCapacity); + } + FileManagerImpl *FileManagerImpl::GetInstance() { return &ms_instance; diff --git a/PortabilityLayer/FileManager.h b/PortabilityLayer/FileManager.h index be551e9..e10b121 100644 --- a/PortabilityLayer/FileManager.h +++ b/PortabilityLayer/FileManager.h @@ -36,6 +36,7 @@ namespace PortabilityLayer virtual PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream) = 0; virtual bool PromptSaveFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName) = 0; + virtual bool PromptOpenFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity) = 0; static FileManager *GetInstance(); }; diff --git a/PortabilityLayer/HostAudioDriver.h b/PortabilityLayer/HostAudioDriver.h index 936710a..b93a3b4 100644 --- a/PortabilityLayer/HostAudioDriver.h +++ b/PortabilityLayer/HostAudioDriver.h @@ -1,13 +1,16 @@ -#pragma once +#pragma once + +#include namespace PortabilityLayer { class HostAudioChannel; - + class HostAudioDriver { public: virtual HostAudioChannel *CreateChannel() = 0; + virtual void SetMasterVolume(uint32_t vol, uint32_t maxVolume) = 0; static HostAudioDriver *GetInstance(); static void SetInstance(HostAudioDriver *instance); diff --git a/PortabilityLayer/HostFileSystem.h b/PortabilityLayer/HostFileSystem.h index 56c070a..d6109f7 100644 --- a/PortabilityLayer/HostFileSystem.h +++ b/PortabilityLayer/HostFileSystem.h @@ -20,6 +20,7 @@ namespace PortabilityLayer virtual HostDirectoryCursor *ScanDirectory(VirtualDirectory_t virtualDirectory) = 0; virtual bool PromptSaveFile(VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName) = 0; + virtual bool PromptOpenFile(VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity) = 0; virtual bool ValidateFilePath(const char *path, size_t pathLen) const = 0; static HostFileSystem *GetInstance(); diff --git a/PortabilityLayer/InputManager.cpp b/PortabilityLayer/InputManager.cpp index 41a8651..c22e010 100644 --- a/PortabilityLayer/InputManager.cpp +++ b/PortabilityLayer/InputManager.cpp @@ -16,6 +16,7 @@ namespace PortabilityLayer void ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent) override; void ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent) override; int16_t GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) override; + void ClearState() override; static InputManagerImpl *GetInstance(); @@ -55,6 +56,12 @@ namespace PortabilityLayer return m_axisStates[playerNum][gamepadAxis]; } + void InputManagerImpl::ClearState() + { + memset(&m_axisStates, 0, sizeof(m_axisStates)); + memset(&m_keyMap, 0, sizeof(m_keyMap)); + } + void InputManagerImpl::ApplyEventAsKey(const GpKeyboardInputEvent &vosEvent, bool bit) { switch (vosEvent.m_keyIDSubset) diff --git a/PortabilityLayer/InputManager.h b/PortabilityLayer/InputManager.h index b931982..698db48 100644 --- a/PortabilityLayer/InputManager.h +++ b/PortabilityLayer/InputManager.h @@ -15,6 +15,7 @@ namespace PortabilityLayer virtual void ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent) = 0; virtual void ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent) = 0; virtual int16_t GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) = 0; + virtual void ClearState() = 0; static InputManager *GetInstance(); }; diff --git a/PortabilityLayer/MenuManager.cpp b/PortabilityLayer/MenuManager.cpp index ad6bc72..164d3e0 100644 --- a/PortabilityLayer/MenuManager.cpp +++ b/PortabilityLayer/MenuManager.cpp @@ -129,6 +129,7 @@ namespace PortabilityLayer void SetMenuEnabled(const THandle &menuHandle, bool enabled) override; void SetItemEnabled(const THandle &menu, unsigned int index, bool enabled) override; void SetItemChecked(const THandle &menu, unsigned int index, bool checked) override; + bool SetItemText(const THandle &menu, unsigned int index, const PLPasStr &str) override; bool IsPointInMenuBar(const Vec2i &point) const override; void MenuSelect(const Vec2i &initialPoint, int16_t *outMenu, uint16_t *outItem) override; @@ -442,6 +443,8 @@ namespace PortabilityLayer if (m_lastMenu == menu) m_lastMenu = menuPtr->prevMenu; + menu.Dispose(); + DrawMenuBar(); } @@ -476,6 +479,44 @@ namespace PortabilityLayer menu->menuItems[index].checked = checked; } + bool MenuManagerImpl::SetItemText(const THandle &menu, unsigned int index, const PLPasStr &str) + { + Menu *menuPtr = *menu; + + PortabilityLayer::MMHandleBlock *oldHandle = menuPtr->stringBlobHandle; + size_t oldSize = oldHandle->m_size; + + const uint8_t *oldStrBlob = static_cast(oldHandle->m_contents); + + const size_t newSize = oldSize - oldStrBlob[menuPtr->menuItems[index].nameOffsetInStringBlob] + str.Length() + 1; + + THandle newHandle = THandle(PortabilityLayer::MemoryManager::GetInstance()->AllocHandle(newSize)); + if (!newHandle) + return false; + + uint8_t *strWritePtr = *newHandle; + + uint32_t writeOffset = 0; + for (size_t i = 0; i < menuPtr->numMenuItems; i++) + { + MenuItem &menuItem = menuPtr->menuItems[i]; + + const PLPasStr copyStr = (i == index) ? str : PLPasStr(oldStrBlob + menuItem.nameOffsetInStringBlob); + + menuItem.nameOffsetInStringBlob = writeOffset; + + strWritePtr[writeOffset] = copyStr.Length(); + writeOffset++; + + memcpy(strWritePtr + writeOffset, copyStr.UChars(), copyStr.Length()); + writeOffset += copyStr.Length(); + } + + PortabilityLayer::MemoryManager::GetInstance()->ReleaseHandle(menuPtr->stringBlobHandle); + + menuPtr->stringBlobHandle = newHandle.MMBlock(); + } + bool MenuManagerImpl::IsPointInMenuBar(const Vec2i &point) const { return point.m_y >= 0 && static_cast(point.m_y) < kMenuBarHeight; diff --git a/PortabilityLayer/MenuManager.h b/PortabilityLayer/MenuManager.h index 13bf109..a65f642 100644 --- a/PortabilityLayer/MenuManager.h +++ b/PortabilityLayer/MenuManager.h @@ -1,10 +1,11 @@ #pragma once +#include + template class THandle; -#include - +class PLPasStr; struct IGpDisplayDriver; struct Menu; @@ -31,6 +32,7 @@ namespace PortabilityLayer virtual void SetMenuEnabled(const THandle &menuHandle, bool enabled) = 0; virtual void SetItemEnabled(const THandle &menu, unsigned int index, bool enabled) = 0; virtual void SetItemChecked(const THandle &menu, unsigned int index, bool checked) = 0; + virtual bool SetItemText(const THandle &menu, unsigned int index, const PLPasStr &str) = 0; virtual bool IsPointInMenuBar(const Vec2i &point) const = 0; diff --git a/PortabilityLayer/PLCheckboxWidget.cpp b/PortabilityLayer/PLCheckboxWidget.cpp new file mode 100644 index 0000000..40ca920 --- /dev/null +++ b/PortabilityLayer/PLCheckboxWidget.cpp @@ -0,0 +1,20 @@ +#include "PLCheckboxWidget.h" + +namespace PortabilityLayer +{ + CheckboxWidget::CheckboxWidget(const WidgetBasicState &state) + : WidgetSpec(state) + { + } + + CheckboxWidget::~CheckboxWidget() + { + } + + bool CheckboxWidget::Init(const WidgetBasicState &state) + { + (void)state; + + return true; + } +} diff --git a/PortabilityLayer/PLCheckboxWidget.h b/PortabilityLayer/PLCheckboxWidget.h new file mode 100644 index 0000000..78cd968 --- /dev/null +++ b/PortabilityLayer/PLCheckboxWidget.h @@ -0,0 +1,15 @@ +#pragma once + +#include "PLWidgets.h" + +namespace PortabilityLayer +{ + class CheckboxWidget final : public WidgetSpec + { + public: + CheckboxWidget(const WidgetBasicState &state); + ~CheckboxWidget(); + + bool Init(const WidgetBasicState &state) override; + }; +} diff --git a/PortabilityLayer/PLControlDefinitions.cpp b/PortabilityLayer/PLControlDefinitions.cpp index 89200cb..9b200d7 100644 --- a/PortabilityLayer/PLControlDefinitions.cpp +++ b/PortabilityLayer/PLControlDefinitions.cpp @@ -7,6 +7,12 @@ int FindControl(Point point, WindowPtr window, ControlHandle *outControl) return 0; } +int FindControl(Point point, WindowPtr window, PortabilityLayer::Widget **outControl) +{ + PL_NotYetImplemented(); + return 0; +} + void SetControlValue(ControlHandle control, int value) { PL_NotYetImplemented(); @@ -54,6 +60,12 @@ Boolean TrackControl(ControlHandle control, Point point, ControlActionUPP proc) return false; } +Boolean TrackControl(PortabilityLayer::Widget *widget, Point point, ControlActionUPP proc) +{ + PL_NotYetImplemented(); + return false; +} + long GetControlReference(ControlHandle control) { PL_NotYetImplemented(); @@ -70,3 +82,8 @@ void HiliteControl(ControlHandle control, int unknown) { PL_NotYetImplemented(); } + +void HiliteControl(PortabilityLayer::Widget *widget, int unknown) +{ + PL_NotYetImplemented(); +} diff --git a/PortabilityLayer/PLControlDefinitions.h b/PortabilityLayer/PLControlDefinitions.h index 0256a4a..5d2793d 100644 --- a/PortabilityLayer/PLControlDefinitions.h +++ b/PortabilityLayer/PLControlDefinitions.h @@ -4,6 +4,11 @@ #include "PLCore.h" +namespace PortabilityLayer +{ + class Widget; +} + struct Control { }; @@ -13,11 +18,6 @@ typedef THandle ControlHandle; typedef void(*ControlActionProc)(ControlHandle control, short part); typedef ControlActionProc ControlActionUPP; -enum BuiltinCDEFs -{ - scrollBarProc = 16, -}; - enum ControlParts { kControlUpButtonPart = 1, @@ -29,7 +29,8 @@ enum ControlParts }; -int FindControl(Point point, WindowPtr window, ControlHandle *outControl); // Returns part +int FindControl(Point point, WindowPtr window, PortabilityLayer::Widget **outControl); // Returns part +int FindControl(Point point, WindowPtr window, ControlHandle *outControl); void SetControlValue(ControlHandle control, int value); @@ -41,8 +42,10 @@ ControlHandle NewControl(WindowPtr window, const Rect *rect, const PLPasStr &lab ControlActionUPP NewControlActionUPP(ControlActionProc proc); void DisposeControlActionUPP(ControlActionUPP upp); Boolean TrackControl(ControlHandle control, Point point, ControlActionUPP proc); +Boolean TrackControl(PortabilityLayer::Widget *control, Point point, ControlActionUPP proc); long GetControlReference(ControlHandle control); // Returns userdata ControlHandle GetNewControl(int resID, WindowPtr window); void HiliteControl(ControlHandle control, int unknown); +void HiliteControl(PortabilityLayer::Widget *widget, int unknown); #endif diff --git a/PortabilityLayer/PLCore.cpp b/PortabilityLayer/PLCore.cpp index 233de15..e16636a 100644 --- a/PortabilityLayer/PLCore.cpp +++ b/PortabilityLayer/PLCore.cpp @@ -30,11 +30,13 @@ #include "RenderedFont.h" #include "ResTypeID.h" #include "RandomNumberGenerator.h" +#include "PLArrayViewIterator.h" #include "PLBigEndian.h" #include "PLEventQueue.h" #include "PLKeyEncoding.h" #include "PLSysCalls.h" #include "PLTimeTaggedVOSEvent.h" +#include "PLWidgets.h" #include "QDManager.h" #include "Vec2i.h" #include "WindowDef.h" @@ -184,11 +186,6 @@ void BringToFront(WindowPtr window) PL_NotYetImplemented(); } -void ShowHide(WindowPtr window, Boolean hide) -{ - PL_NotYetImplemented(); -} - bool TrackGoAway(WindowPtr window, Point point) { PL_NotYetImplemented(); @@ -627,16 +624,6 @@ Boolean WaitMouseUp() return false; } -void LocalToGlobal(Point *point) -{ - PL_NotYetImplemented(); -} - -void GlobalToLocal(Point *point) -{ - PL_NotYetImplemented(); -} - short Random() { // Should return with range -32767..32767 @@ -820,11 +807,20 @@ Window::Window() : m_surface(PortabilityLayer::QDPortType_Window) , m_wmX(0) , m_wmY(0) + , m_widgets(nullptr) + , m_numWidgets(0) { } Window::~Window() { + if (m_widgets) + { + for (size_t i = 0; i < m_numWidgets; i++) + m_widgets[i]->Destroy(); + + PortabilityLayer::MemoryManager::GetInstance()->Release(m_widgets); + } } DrawSurface *Window::GetDrawSurface() const @@ -836,3 +832,41 @@ Point Window::MouseToLocal(const GpMouseInputEvent &evt) const { return Point::Create(evt.m_x - m_wmX, evt.m_y - m_wmY); } + +Point Window::TopLeftCoord() const +{ + return Point::Create(m_wmX, m_wmY); +} + +bool Window::AddWidget(PortabilityLayer::Widget *widget) +{ + if (m_widgets == nullptr) + { + m_widgets = static_cast(PortabilityLayer::MemoryManager::GetInstance()->Alloc(sizeof(PortabilityLayer::Widget *))); + if (m_widgets == nullptr) + return false; + } + else + { + void *newBuffer = PortabilityLayer::MemoryManager::GetInstance()->Realloc(m_widgets, (m_numWidgets + 1) * sizeof(PortabilityLayer::Widget*)); + if (newBuffer == nullptr) + return false; + m_widgets = static_cast(newBuffer); + } + + m_widgets[m_numWidgets++] = widget; + + return true; +} + +void Window::DrawControls() +{ + DrawSurface *surface = GetDrawSurface(); + + for (size_t i = 0; i < m_numWidgets; i++) + { + PortabilityLayer::Widget *widget = m_widgets[i]; + if (widget->IsVisible()) + widget->DrawControl(surface); + } +} diff --git a/PortabilityLayer/PLCore.h b/PortabilityLayer/PLCore.h index 9a31c55..40586fd 100644 --- a/PortabilityLayer/PLCore.h +++ b/PortabilityLayer/PLCore.h @@ -22,6 +22,7 @@ namespace PortabilityLayer { struct MMHandleBlock; class IOStream; + class Widget; } typedef uint8_t Boolean; @@ -43,6 +44,7 @@ typedef unsigned char *StringPtr; class PLPasStr; struct DrawSurface; + struct Menu; typedef void *Ptr; @@ -108,6 +110,13 @@ struct Window // Convenience method to convert a mouse event to local point Point MouseToLocal(const GpMouseInputEvent &evt) const; + // Convenience method that returns a 16-bit precision X/Y + Point TopLeftCoord() const; + + bool AddWidget(PortabilityLayer::Widget *widget); + + void DrawControls(); + DrawSurface m_surface; // Must be the first item until the immediate mode draw API is completely removed // The port is always at 0,0 @@ -117,6 +126,9 @@ struct Window protected: ~Window(); + + PortabilityLayer::Widget **m_widgets; + size_t m_numWidgets; }; struct DateTimeRec @@ -269,7 +281,6 @@ short FindWindow(Point point, WindowPtr *window); // Translates global coordinat void DragWindow(WindowPtr window, Point start, Rect *bounds); // Drags the window (probably not implemented) void SendBehind(WindowPtr window, WindowPtr behind); void BringToFront(WindowPtr window); -void ShowHide(WindowPtr window, Boolean hide); bool TrackGoAway(WindowPtr window, Point point); // Returns true if the close box was actually clicked (?) Int32 GrowWindow(WindowPtr window, Point start, Rect *size); bool TrackBox(WindowPtr window, Point point, int part); // Returns true if grow/shrink box was clicked (part corresponds to type) @@ -320,8 +331,6 @@ Boolean Button(); // Returns true if there's a mouse down event in the queue Boolean StillDown(); Boolean WaitMouseUp(); -void LocalToGlobal(Point *point); -void GlobalToLocal(Point *point); short Random(); void GetDateTime(UInt32 *dateTime); void GetTime(DateTimeRec *dateTime); diff --git a/PortabilityLayer/PLLabelWidget.cpp b/PortabilityLayer/PLLabelWidget.cpp index 5286049..4f2529b 100644 --- a/PortabilityLayer/PLLabelWidget.cpp +++ b/PortabilityLayer/PLLabelWidget.cpp @@ -27,6 +27,6 @@ namespace PortabilityLayer const Point topLeftCorner = Point::Create(m_rect.left, m_rect.top); const Point textStartPoint = topLeftCorner + Point::Create(0, surface->MeasureFontAscender()); - surface->DrawString(textStartPoint, m_text.ToShortStr()); + surface->DrawStringWrap(textStartPoint, m_rect, m_text.ToShortStr()); } } diff --git a/PortabilityLayer/PLPopupMenuWidget.cpp b/PortabilityLayer/PLPopupMenuWidget.cpp new file mode 100644 index 0000000..44fce90 --- /dev/null +++ b/PortabilityLayer/PLPopupMenuWidget.cpp @@ -0,0 +1,14 @@ +#include "PLPopupMenuWidget.h" + +namespace PortabilityLayer +{ + PopupMenuWidget::PopupMenuWidget(const WidgetBasicState &state) + : WidgetSpec(state) + { + } + + bool PopupMenuWidget::Init(const WidgetBasicState &state) + { + return true; + } +} diff --git a/PortabilityLayer/PLPopupMenuWidget.h b/PortabilityLayer/PLPopupMenuWidget.h new file mode 100644 index 0000000..0cfb4a8 --- /dev/null +++ b/PortabilityLayer/PLPopupMenuWidget.h @@ -0,0 +1,15 @@ +#pragma once + +#include "PascalStr.h" +#include "PLWidgets.h" + +namespace PortabilityLayer +{ + class PopupMenuWidget final : public WidgetSpec + { + public: + explicit PopupMenuWidget(const WidgetBasicState &state); + + bool Init(const WidgetBasicState &state) override; + }; +} diff --git a/PortabilityLayer/PLQDraw.cpp b/PortabilityLayer/PLQDraw.cpp index d16033b..a93da99 100644 --- a/PortabilityLayer/PLQDraw.cpp +++ b/PortabilityLayer/PLQDraw.cpp @@ -427,11 +427,6 @@ static void PlotLine(PortabilityLayer::QDState *qdState, DrawSurface *surface, c surface->m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } -void SetOrigin(int x, int y) -{ - PL_NotYetImplemented(); -} - namespace { static bool SystemColorToRGBAColor(SystemColorID color, PortabilityLayer::RGBAColor &rgbaColor) @@ -610,6 +605,116 @@ void DrawSurface::DrawString(const Point &point, const PLPasStr &str) m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } +void DrawSurface::DrawStringWrap(const Point &point, const Rect &constrainRect, const PLPasStr &str) +{ + PortabilityLayer::QDPort *port = &m_port; + + PortabilityLayer::QDState *qdState = m_port.GetState(); + + PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance(); + + const int fontSize = qdState->m_fontSize; + const int fontVariationFlags = qdState->m_fontVariationFlags; + PortabilityLayer::FontFamily *fontFamily = qdState->m_fontFamily; + + PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, fontVariationFlags); + + Point penPos = point; + const size_t len = str.Length(); + const uint8_t *chars = str.UChars(); + + PixMap *pixMap = *port->GetPixMap(); + + const Rect limitRect = pixMap->m_rect.Intersect(constrainRect);; + const Rect areaRect = constrainRect; + + if (!limitRect.IsValid() || !areaRect.IsValid()) + return; // ??? + + Point paraStartPos = penPos; + + size_t currentStartChar = 0; + size_t currentSpanLength = 0; + + for (;;) + { + if (currentStartChar == len) + break; + + size_t lastWhitespace = currentStartChar; + bool shouldSkipSpaces = false; + + size_t committedLength = 0; + + size_t i = currentStartChar; + + // Find a span to print + int32_t spanWidth = 0; + for (;;) + { + if (i == len) + { + committedLength = i - currentStartChar; + break; + } + + uint8_t character = chars[i]; + + if (character <= ' ') + { + committedLength = i - currentStartChar + 1; + if (character == '\r') + break; + + i++; + } + else + { + const PortabilityLayer::RenderedGlyphMetrics *metrics = nullptr; + const void *glyphData = nullptr; + if (!rfont->GetGlyph(chars[i], metrics, glyphData)) + { + i++; + continue; + } + + spanWidth += metrics->m_advanceX; + + int32_t glyphEnd = penPos.h + spanWidth; + + if (glyphEnd >= constrainRect.right) + { + if (committedLength == 0) + { + // Word didn't fit + committedLength = i - currentStartChar; + if (committedLength == 0) + committedLength = 1; // Nothing fit, consume one char + } + + break; + } + + i++; + } + } + + for (size_t ci = 0; ci < committedLength; ci++) + { + const uint8_t character = chars[currentStartChar + ci]; + + DrawGlyph(qdState, pixMap, pixMap->m_rect, penPos, rfont, character); + } + + currentStartChar += committedLength; + + paraStartPos.v += rfont->GetMetrics().m_linegap; + penPos = paraStartPos; + } + + m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); +} + size_t DrawSurface::MeasureString(const PLPasStr &str) { const PortabilityLayer::QDState *qdState = m_port.GetState(); @@ -650,6 +755,26 @@ int32_t DrawSurface::MeasureFontAscender() return rfont->GetMetrics().m_ascent; } +int32_t DrawSurface::MeasureFontLineGap() +{ + const PortabilityLayer::QDState *qdState = m_port.GetState(); + PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance(); + + PortabilityLayer::FontFamily *fontFamily = qdState->m_fontFamily; + + if (!fontFamily) + return 0; + + const int variationFlags = qdState->m_fontVariationFlags; + const int fontSize = qdState->m_fontSize; + + PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, variationFlags); + if (!rfont) + return 0; + + return rfont->GetMetrics().m_linegap; +} + void DrawSurface::DrawPicture(THandle pictHdl, const Rect &bounds) { if (!pictHdl) @@ -799,7 +924,7 @@ void DrawSurface::FillRect(const Rect &rect) void DrawSurface::FillRectWithPattern8x8(const Rect &rect, const uint8_t *pattern) { - PL_NotYetImplemented(); + PL_NotYetImplemented_TODO("FillWithPattern"); m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } diff --git a/PortabilityLayer/PLQDraw.h b/PortabilityLayer/PLQDraw.h index f9175a6..0ed8af8 100644 --- a/PortabilityLayer/PLQDraw.h +++ b/PortabilityLayer/PLQDraw.h @@ -105,7 +105,6 @@ PLError_t PlotIconSuite(Rect *rect, Handle iconSuite); void SetRect(Rect *rect, short left, short top, short right, short bottom); int TextWidth(const PLPasStr &str, int firstChar1Based, int length); -void SetOrigin(int x, int y); void ForeColor(SystemColorID color); void BackColor(SystemColorID color); void GetForeColor(RGBColor *color); diff --git a/PortabilityLayer/PLRadioButtonWidget.cpp b/PortabilityLayer/PLRadioButtonWidget.cpp new file mode 100644 index 0000000..272fefe --- /dev/null +++ b/PortabilityLayer/PLRadioButtonWidget.cpp @@ -0,0 +1,54 @@ +#include "PLRadioButtonWidget.h" +#include "PLStandardColors.h" +#include "FontFamily.h" + +#include + +namespace PortabilityLayer +{ + RadioButtonWidget::RadioButtonWidget(const WidgetBasicState &state) + : WidgetSpec(state) + , m_text(state.m_text) + { + } + + RadioButtonWidget::~RadioButtonWidget() + { + } + + bool RadioButtonWidget::Init(const WidgetBasicState &state) + { + (void)state; + + return true; + } + + void RadioButtonWidget::DrawControl(DrawSurface *surface) + { + if (!m_rect.IsValid()) + return; + + uint16_t radioFrameSize = std::min(12, std::min(m_rect.Width(), m_rect.Height())); + int16_t top = (m_rect.top + m_rect.bottom - static_cast(radioFrameSize)) / 2; + + surface->SetForeColor(StdColors::Black()); + const Rect radioRect = Rect::Create(top, m_rect.left, top + static_cast(radioFrameSize), m_rect.left + static_cast(radioFrameSize)); + surface->FillEllipse(radioRect); + if (!m_state) + { + surface->SetForeColor(StdColors::White()); + surface->FillEllipse(radioRect.Inset(1, 1)); + } + + surface->SetForeColor(StdColors::Black()); + surface->SetSystemFont(12, FontFamilyFlag_Bold); + int32_t textV = (m_rect.top + m_rect.bottom + surface->MeasureFontAscender()) / 2; + surface->DrawString(Point::Create(m_rect.left + radioFrameSize + 2, textV), m_text.ToShortStr()); + } + + void RadioButtonWidget::SetString(const PLPasStr &str) + { + m_text = PascalStr<255>(str); + } + +} diff --git a/PortabilityLayer/PLRadioButtonWidget.h b/PortabilityLayer/PLRadioButtonWidget.h new file mode 100644 index 0000000..c310d6a --- /dev/null +++ b/PortabilityLayer/PLRadioButtonWidget.h @@ -0,0 +1,22 @@ +#pragma once + +#include "PascalStr.h" +#include "PLWidgets.h" + +namespace PortabilityLayer +{ + class RadioButtonWidget final : public WidgetSpec + { + public: + RadioButtonWidget(const WidgetBasicState &state); + ~RadioButtonWidget(); + + bool Init(const WidgetBasicState &state) override; + + void DrawControl(DrawSurface *surface) override; + void SetString(const PLPasStr &str) override; + + private: + PascalStr<255> m_text; + }; +} diff --git a/PortabilityLayer/PLScrollBarWidget.cpp b/PortabilityLayer/PLScrollBarWidget.cpp new file mode 100644 index 0000000..fa4e088 --- /dev/null +++ b/PortabilityLayer/PLScrollBarWidget.cpp @@ -0,0 +1,14 @@ +#include "PLScrollBarWidget.h" + +namespace PortabilityLayer +{ + ScrollBarWidget::ScrollBarWidget(const WidgetBasicState &state) + : WidgetSpec(state) + { + } + + bool ScrollBarWidget::Init(const WidgetBasicState &state) + { + return true; + } +} diff --git a/PortabilityLayer/PLScrollBarWidget.h b/PortabilityLayer/PLScrollBarWidget.h new file mode 100644 index 0000000..4ceb563 --- /dev/null +++ b/PortabilityLayer/PLScrollBarWidget.h @@ -0,0 +1,15 @@ +#pragma once + +#include "PascalStr.h" +#include "PLWidgets.h" + +namespace PortabilityLayer +{ + class ScrollBarWidget final : public WidgetSpec + { + public: + explicit ScrollBarWidget(const WidgetBasicState &state); + + bool Init(const WidgetBasicState &state) override; + }; +} diff --git a/PortabilityLayer/PLSound.cpp b/PortabilityLayer/PLSound.cpp index e6516ad..aa7df85 100644 --- a/PortabilityLayer/PLSound.cpp +++ b/PortabilityLayer/PLSound.cpp @@ -329,7 +329,11 @@ namespace PortabilityLayer static SoundSystemImpl *GetInstance(); private: + SoundSystemImpl(); + static SoundSystemImpl ms_instance; + + uint8_t m_volume; }; AudioChannel *SoundSystemImpl::CreateChannel() @@ -367,16 +371,16 @@ namespace PortabilityLayer return new (storage) PortabilityLayer::AudioChannelImpl(audioChannel, threadEvent, mutex); } - void SoundSystemImpl::SetVolume(uint8_t vol) { - PL_NotYetImplemented_TODO("Volume"); + PortabilityLayer::HostAudioDriver::GetInstance()->SetMasterVolume(vol, 255); + m_volume = vol; } uint8_t SoundSystemImpl::GetVolume() const { PL_NotYetImplemented_TODO("Volume"); - return 255; + return m_volume; } SoundSystemImpl *SoundSystemImpl::GetInstance() @@ -384,6 +388,11 @@ namespace PortabilityLayer return &ms_instance; } + SoundSystemImpl::SoundSystemImpl() + : m_volume(255) + { + } + SoundSystemImpl SoundSystemImpl::ms_instance; SoundSystem *SoundSystem::GetInstance() diff --git a/PortabilityLayer/PLWidgets.cpp b/PortabilityLayer/PLWidgets.cpp index ce24317..5bcb446 100644 --- a/PortabilityLayer/PLWidgets.cpp +++ b/PortabilityLayer/PLWidgets.cpp @@ -6,8 +6,12 @@ namespace PortabilityLayer WidgetBasicState::WidgetBasicState() : m_resID(0) , m_rect(Rect::Create(0, 0, 0, 0)) - , m_enabled(true) , m_window(nullptr) + , m_refConstant(0) + , m_min(0) + , m_max(0) + , m_state(0) + , m_enabled(true) { } @@ -23,6 +27,31 @@ namespace PortabilityLayer (void)surface; } + void Widget::SetMin(int32_t v) + { + } + + void Widget::SetMax(int32_t v) + { + } + + void Widget::SetPosition(const Point &pos) + { + uint16_t width = m_rect.Width(); + uint16_t height = m_rect.Height(); + + m_rect.left = pos.h; + m_rect.top = pos.v; + + Resize(width, height); + } + + void Widget::Resize(uint16_t width, uint16_t height) + { + m_rect.right = m_rect.left + width; + m_rect.bottom = m_rect.top + height; + } + void Widget::SetEnabled(bool enabled) { m_enabled = enabled; @@ -35,6 +64,11 @@ namespace PortabilityLayer OnStateChanged(); } + int16_t Widget::GetState() const + { + return m_state; + } + void Widget::SetVisible(bool visible) { m_visible = visible; @@ -64,8 +98,8 @@ namespace PortabilityLayer : m_rect(state.m_rect) , m_window(state.m_window) , m_enabled(state.m_enabled) + , m_state(state.m_state) , m_visible(true) - , m_state(0) { } diff --git a/PortabilityLayer/PLWidgets.h b/PortabilityLayer/PLWidgets.h index cb4355f..f5309ca 100644 --- a/PortabilityLayer/PLWidgets.h +++ b/PortabilityLayer/PLWidgets.h @@ -28,10 +28,14 @@ namespace PortabilityLayer WidgetBasicState(); Rect m_rect; - int16_t m_resID; PascalStr<255> m_text; - bool m_enabled; Window *m_window; + uint32_t m_refConstant; + int32_t m_min; + int32_t m_max; + int16_t m_state; + int16_t m_resID; + bool m_enabled; }; class Widget @@ -42,8 +46,15 @@ namespace PortabilityLayer virtual WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt); virtual void DrawControl(DrawSurface *surface); + virtual void SetMin(int32_t v); + virtual void SetMax(int32_t v); + + void SetPosition(const Point &pos); + void Resize(uint16_t width, uint16_t height); + void SetEnabled(bool enabled); void SetState(int16_t state); + int16_t GetState() const; void SetVisible(bool visible); bool IsVisible() const; @@ -71,6 +82,7 @@ namespace PortabilityLayer }; } +#include "PLCore.h" #include #include @@ -91,7 +103,7 @@ namespace PortabilityLayer Widget::BaseRelease(static_cast(this)); } - static WidgetSpec *Create(const WidgetBasicState &state) + static T *Create(const WidgetBasicState &state) { void *storage = Widget::BaseAlloc(sizeof(T)); if (!storage) @@ -99,13 +111,23 @@ namespace PortabilityLayer T *widgetT = new (storage) T(state); - Widget *widget = static_cast(widgetT); + // Conversion check + WidgetSpec *downcastWidget = widgetT; + (void)downcastWidget; + + Widget *widget = widgetT; if (!widget->Init(state)) { widget->Destroy(); return nullptr; } + if (!static_cast(state.m_window)->AddWidget(widget)) + { + widget->Destroy(); + return nullptr; + } + return widgetT; } }; diff --git a/PortabilityLayer/PortabilityLayer.vcxproj b/PortabilityLayer/PortabilityLayer.vcxproj index 5b7f44e..4c36adc 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj +++ b/PortabilityLayer/PortabilityLayer.vcxproj @@ -191,6 +191,7 @@ + @@ -203,6 +204,9 @@ + + + @@ -304,6 +308,7 @@ + @@ -318,10 +323,13 @@ + + + diff --git a/PortabilityLayer/PortabilityLayer.vcxproj.filters b/PortabilityLayer/PortabilityLayer.vcxproj.filters index c56141b..c1e6334 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj.filters +++ b/PortabilityLayer/PortabilityLayer.vcxproj.filters @@ -438,6 +438,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -677,5 +689,17 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + \ No newline at end of file diff --git a/PortabilityLayer/QDGraf.h b/PortabilityLayer/QDGraf.h index 6a00556..bb83276 100644 --- a/PortabilityLayer/QDGraf.h +++ b/PortabilityLayer/QDGraf.h @@ -77,9 +77,11 @@ struct DrawSurface final void SetApplicationFont(int size, int variationFlags); void SetSystemFont(int size, int variationFlags); void DrawString(const Point &point, const PLPasStr &str); + void DrawStringWrap(const Point &point, const Rect &constrainRect, const PLPasStr &str); size_t MeasureString(const PLPasStr &str); int32_t MeasureFontAscender(); + int32_t MeasureFontLineGap(); void DrawPicture(THandle pictHandle, const Rect &rect); diff --git a/PortabilityLayer/SharedTypes.h b/PortabilityLayer/SharedTypes.h index 71db377..838a57e 100644 --- a/PortabilityLayer/SharedTypes.h +++ b/PortabilityLayer/SharedTypes.h @@ -27,11 +27,17 @@ struct Rect int16_t right; bool IsValid() const; - Rect Intersect(const Rect &rect) const; Rect MakeValid() const; + + Rect Intersect(const Rect &rect) const; + Rect Inset(int16_t h, int16_t v) const; + Rect operator-(const Point &point) const; Rect operator+(const Point &point) const; + Rect &operator-=(const Point &point); + Rect &operator+=(const Point &point); + uint16_t Height() const; uint16_t Width() const; @@ -164,6 +170,11 @@ inline Rect Rect::Intersect(const Rect &other) const return result; } +inline Rect Rect::Inset(int16_t h, int16_t v) const +{ + return Rect::Create(top + v, left + h, bottom - v, right - h); +} + inline Rect Rect::MakeValid() const { Rect result = *this; @@ -186,6 +197,28 @@ inline Rect Rect::operator+(const Point &point) const return Rect::Create(this->top + point.v, this->left + point.h, this->bottom + point.v, this->right + point.h); } +inline Rect &Rect::operator-=(const Point &point) +{ + this->top -= point.v; + this->bottom -= point.v; + this->left -= point.h; + this->right -= point.h; + + return *this; +} + +inline Rect &Rect::operator+=(const Point &point) +{ + this->top += point.v; + this->bottom += point.v; + this->left += point.h; + this->right += point.h; + + return *this; +} + + + inline uint16_t Rect::Height() const { return static_cast(static_cast(this->bottom) - static_cast(this->top)); diff --git a/PortabilityLayer/VirtualDirectory.h b/PortabilityLayer/VirtualDirectory.h index c084aff..a29ece5 100644 --- a/PortabilityLayer/VirtualDirectory.h +++ b/PortabilityLayer/VirtualDirectory.h @@ -11,6 +11,7 @@ namespace PortabilityLayer kApplicationData = 1, kGameData, kUserData, + kUserSaves, kPrefs, kFonts, kCursors, diff --git a/PortabilityLayer/WindowManager.cpp b/PortabilityLayer/WindowManager.cpp index 895dc4a..549898c 100644 --- a/PortabilityLayer/WindowManager.cpp +++ b/PortabilityLayer/WindowManager.cpp @@ -344,6 +344,9 @@ namespace PortabilityLayer void WindowManagerImpl::RenderWindow(WindowImpl *window, IGpDisplayDriver *displayDriver) { + if (!window->IsVisible()) + return; + DrawSurface &graf = window->m_surface; graf.PushToDDSurface(displayDriver);