diff --git a/Aerofoil/Aerofoil.vcxproj b/Aerofoil/Aerofoil.vcxproj index f91463d..1aaa703 100644 --- a/Aerofoil/Aerofoil.vcxproj +++ b/Aerofoil/Aerofoil.vcxproj @@ -170,7 +170,7 @@ - + diff --git a/Aerofoil/GpColorCursor_Win32.cpp b/Aerofoil/GpColorCursor_Win32.cpp index cd23440..17a8c39 100644 --- a/Aerofoil/GpColorCursor_Win32.cpp +++ b/Aerofoil/GpColorCursor_Win32.cpp @@ -1,14 +1,14 @@ -#include "GpColorCursor_Win32.h" +#include "GpCursor_Win32.h" #include #include -void GpColorCursor_Win32::Destroy() +void GpCursor_Win32::Destroy() { this->DecRef(); } -IGpColorCursor_Win32 *GpColorCursor_Win32::Load(const wchar_t *path) +IGpCursor_Win32 *GpCursor_Win32::Load(const wchar_t *path) { HANDLE imageH = LoadImageW(nullptr, path, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE); @@ -16,43 +16,43 @@ IGpColorCursor_Win32 *GpColorCursor_Win32::Load(const wchar_t *path) return nullptr; HCURSOR cursor = reinterpret_cast(imageH); - void *storage = malloc(sizeof(GpColorCursor_Win32)); + void *storage = malloc(sizeof(GpCursor_Win32)); if (!storage) { DestroyCursor(cursor); return nullptr; } - return new (storage) GpColorCursor_Win32(reinterpret_cast(cursor)); + return new (storage) GpCursor_Win32(reinterpret_cast(cursor)); } -GpColorCursor_Win32::GpColorCursor_Win32(HCURSOR cursor) +GpCursor_Win32::GpCursor_Win32(HCURSOR cursor) : m_cursor(cursor) , m_refCount(1) { } -GpColorCursor_Win32::~GpColorCursor_Win32() +GpCursor_Win32::~GpCursor_Win32() { DestroyCursor(m_cursor); } -const HCURSOR &GpColorCursor_Win32::GetHCursor() const +const HCURSOR &GpCursor_Win32::GetHCursor() const { return m_cursor; } -void GpColorCursor_Win32::IncRef() +void GpCursor_Win32::IncRef() { m_refCount++; } -void GpColorCursor_Win32::DecRef() +void GpCursor_Win32::DecRef() { m_refCount--; if (m_refCount == 0) { - this->~GpColorCursor_Win32(); + this->~GpCursor_Win32(); free(this); } } diff --git a/Aerofoil/GpMain_Win32.cpp b/Aerofoil/GpMain_Win32.cpp index 7766c83..ec3990c 100644 --- a/Aerofoil/GpMain_Win32.cpp +++ b/Aerofoil/GpMain_Win32.cpp @@ -1,6 +1,6 @@ #include "GpMain.h" #include "GpAudioDriverFactory.h" -#include "GpColorCursor_Win32.h" +#include "GpCursor_Win32.h" #include "GpDisplayDriverFactory.h" #include "GpGlobalConfig.h" #include "GpFiber_Win32.h" @@ -390,7 +390,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine g_gpWindowsGlobals.m_baseDir = GpFileSystem_Win32::GetInstance()->GetBasePath(); g_gpWindowsGlobals.m_createFiberFunc = GpFiber_Win32::Create; - g_gpWindowsGlobals.m_loadColorCursorFunc = GpColorCursor_Win32::Load; + g_gpWindowsGlobals.m_loadCursorFunc = GpCursor_Win32::Load; g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage; g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11; diff --git a/ConvertColorCursors/ConvertColorCursors.cpp b/ConvertColorCursors/ConvertColorCursors.cpp index 75c379b..a0ded11 100644 --- a/ConvertColorCursors/ConvertColorCursors.cpp +++ b/ConvertColorCursors/ConvertColorCursors.cpp @@ -1,4 +1,5 @@ #include "CFileStream.h" +#include "BMPFormat.h" #include "MMHandleBlock.h" #include "ResourceCompiledTypeList.h" #include "ResourceFile.h" @@ -8,6 +9,7 @@ #include #include +#include #include "stb_image_write.h" @@ -53,6 +55,14 @@ struct CursorHeader BEUInt32_t m_cursorResourceID; }; +struct BWCursor +{ + uint8_t m_pixels[32]; + uint8_t m_mask[32]; + BEUInt16_t m_hotSpotX; + BEUInt16_t m_hotSpotY; +}; + struct IconDir { uint16_t m_reserved; @@ -84,6 +94,108 @@ void WriteToFileCallback(void *context, void *data, int size) fwrite(data, 1, size, static_cast(context)); } +void WriteToVectorCallback(void *context, void *data, int size) +{ + std::vector *vec = static_cast*>(context); + for (int i = 0; i < size; i++) + vec->push_back(static_cast(data)[i]); +} + +void ConvertBWCursors(PortabilityLayer::ResourceFile *resFile) +{ + const PortabilityLayer::ResourceCompiledTypeList *typeList = resFile->GetResourceTypeList('CURS'); + if (!typeList) + return; + + const size_t numRefs = typeList->m_numRefs; + for (size_t i = 0; i < numRefs; i++) + { + const int resID = typeList->m_firstRef[i].m_resID; + const THandle resHdl = resFile->LoadResource('CURS', resID); + const void *cursorDataBase = *resHdl; + const BWCursor *cursorData = static_cast(cursorDataBase); + + char outPathDebug[64]; + sprintf_s(outPathDebug, "Packaged\\WinCursors\\b%i.bmp", resID); + + char outPath[64]; + sprintf_s(outPath, "Packaged\\WinCursors\\b%i.cur", resID); + + FILE *outF = nullptr; + errno_t outErr = fopen_s(&outF, outPath, "wb"); + + if (!outErr) + { + IconDir iconDir; + iconDir.m_reserved = 0; + iconDir.m_type = 2; + iconDir.m_numImages = 1; + + IconDirEntry iconDirEntry; + iconDirEntry.m_width = 16; + iconDirEntry.m_height = 16; + iconDirEntry.m_numColors = 0; + iconDirEntry.m_reserved = 0; + iconDirEntry.m_numPlanes_HotSpotX = cursorData->m_hotSpotX; + iconDirEntry.m_bpp_HotSpotY = cursorData->m_hotSpotY; + iconDirEntry.m_imageDataSize = 0; + iconDirEntry.m_imageDataOffset = sizeof(IconDir) + sizeof(IconDirEntry); + + fwrite(&iconDir, 1, sizeof(IconDir), outF); + fwrite(&iconDirEntry, 1, sizeof(IconDirEntry), outF); + + long imageDataStart = ftell(outF); + + PortabilityLayer::BitmapInfoHeader bmpHeader; + bmpHeader.m_thisStructureSize = sizeof(bmpHeader); + bmpHeader.m_width = 16; + bmpHeader.m_height = 32; + bmpHeader.m_planes = 1; + bmpHeader.m_bitsPerPixel = 1; + bmpHeader.m_compression = 0; + bmpHeader.m_imageSize = (16 * 16 / 8); + bmpHeader.m_xPixelsPerMeter = 0; + bmpHeader.m_yPixelsPerMeter = 0; + bmpHeader.m_numColors = 2; + bmpHeader.m_importantColorCount = 2; + + fwrite(&bmpHeader, 1, sizeof(bmpHeader), outF); + + const uint8_t paletteData[] = { + 0, 0, 0, 0, + 255, 255, 255, 0 }; + + fwrite(paletteData, 1, sizeof(paletteData), outF); + uint8_t padding[2] = { 0, 0 }; + + for (int y = 0; y < 16; y++) + { + const uint8_t *maskRow = cursorData->m_mask + (15 - y) * 2; + const uint8_t *row = cursorData->m_pixels + (15 - y) * 2; + const uint8_t modifiedRow[] = { row[0] ^ maskRow[0], row[1] ^ maskRow[1] }; + fwrite(modifiedRow, 1, 2, outF); + fwrite(padding, 1, 2, outF); + } + + for (int y = 0; y < 16; y++) + { + const uint8_t *row = cursorData->m_mask + (15 - y) * 2; + const uint8_t modifiedRow[] = { row[0] ^ 255, row[1] ^ 255 }; + fwrite(modifiedRow, 1, 2, outF); + fwrite(padding, 1, 2, outF); + } + + long imageDataEnd = ftell(outF); + + fseek(outF, sizeof(IconDir), SEEK_SET); + + iconDirEntry.m_imageDataSize = static_cast(imageDataEnd - imageDataStart); + fwrite(&iconDirEntry, 1, sizeof(IconDirEntry), outF); + fclose(outF); + } + } +} + void ConvertCursors(PortabilityLayer::ResourceFile *resFile) { const PortabilityLayer::ResourceCompiledTypeList *typeList = resFile->GetResourceTypeList('crsr'); @@ -196,7 +308,7 @@ void ConvertCursors(PortabilityLayer::ResourceFile *resFile) } char outPath[64]; - sprintf_s(outPath, "Packaged\\WinCursors\\%i.cur", resID); + sprintf_s(outPath, "Packaged\\WinCursors\\c%i.cur", resID); FILE *outF = nullptr; errno_t outErr = fopen_s(&outF, outPath, "wb"); @@ -335,6 +447,7 @@ int main(int argc, const char **argv) stream.Close(); ConvertCursors(resFile); + ConvertBWCursors(resFile); ConvertIconFamily(resFile, 'ics#', 'ics8', "Small", 16); ConvertIconFamily(resFile, 'ICN#', 'icl8', "Large", 32); diff --git a/GpApp/AnimCursor.cpp b/GpApp/AnimCursor.cpp index e2cb6d4..f97cbdc 100644 --- a/GpApp/AnimCursor.cpp +++ b/GpApp/AnimCursor.cpp @@ -11,7 +11,7 @@ #include "Externs.h" #include "Environ.h" #include "HostDisplayDriver.h" -#include "IGpColorCursor.h" +#include "IGpCursor.h" #include "IGpDisplayDriver.h" #include "ResourceManager.h" @@ -37,7 +37,7 @@ typedef struct { struct { - IGpColorCursor *hwCursor; + IGpCursor *hwCursor; } frame[1]; } compiledAcurRec; @@ -61,7 +61,7 @@ compiledAcurHandle compiledAnimCursorH = nil; Boolean GetColorCursors (acurHandle ballCursH, compiledAcurHandle compiledBallCursH) { short i, j; - IGpColorCursor *hwCursor; + IGpCursor *hwCursor; Boolean result = true; if (ballCursH) @@ -70,7 +70,7 @@ Boolean GetColorCursors (acurHandle ballCursH, compiledAcurHandle compiledBallCu HideCursor(); // Hide the cursor for (i = 0; i < j; i++) // Walk through the acur resource { - hwCursor = PortabilityLayer::HostDisplayDriver::GetInstance()->LoadColorCursor((*ballCursH)->frame[i].resID); // Get the cursor + hwCursor = PortabilityLayer::HostDisplayDriver::GetInstance()->LoadCursor(true, (*ballCursH)->frame[i].resID); // Get the cursor if (hwCursor == nil) // Make sure a real cursor was returned { // If not, trash all cursors loaded for (j = 0; j < i; j++) @@ -81,7 +81,7 @@ Boolean GetColorCursors (acurHandle ballCursH, compiledAcurHandle compiledBallCu else // But, if the cursor loaded ok { // add it to our list or cursor handles (*compiledBallCursH)->frame[i].hwCursor = hwCursor; - PortabilityLayer::HostDisplayDriver::GetInstance()->SetColorCursor(hwCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetCursor(hwCursor); } } InitCursor(); // Show the cursor again (as arrow) @@ -168,10 +168,10 @@ void IncrementCursor (void) (*animCursorH)->index++; (*animCursorH)->index %= (*animCursorH)->n; - PortabilityLayer::HostDisplayDriver::GetInstance()->SetColorCursor((*compiledAnimCursorH)->frame[(*animCursorH)->index].hwCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetCursor((*compiledAnimCursorH)->frame[(*animCursorH)->index].hwCursor); } else - SetBuiltinCursor(watchCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kWait); } //-------------------------------------------------------------- DecrementCursor @@ -188,10 +188,10 @@ void DecrementCursor (void) if (((*animCursorH)->index) < 0) (*animCursorH)->index = ((*animCursorH)->n) - 1; - PortabilityLayer::HostDisplayDriver::GetInstance()->SetColorCursor((*compiledAnimCursorH)->frame[(*animCursorH)->index].hwCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetCursor((*compiledAnimCursorH)->frame[(*animCursorH)->index].hwCursor); } else - SetBuiltinCursor(watchCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kWait); } //-------------------------------------------------------------- SpinCursor diff --git a/GpApp/Coordinates.cpp b/GpApp/Coordinates.cpp index a812486..5d05b97 100644 --- a/GpApp/Coordinates.cpp +++ b/GpApp/Coordinates.cpp @@ -127,15 +127,15 @@ void OpenCoordWindow (void) if (coordWindow == nil) { - const uint16_t windowStyle = PortabilityLayer::WindowStyleFlags::kTitleBar | PortabilityLayer::WindowStyleFlags::kMiniBar; + const uint16_t windowStyle = PortabilityLayer::WindowStyleFlags::kTitleBar | PortabilityLayer::WindowStyleFlags::kMiniBar | PortabilityLayer::WindowStyleFlags::kCloseBox; QSetRect(&coordWindowRect, 0, 0, 50, 38); if (thisMac.hasColor) coordWindow = NewCWindow(nil, &coordWindowRect, - PSTR("Tools"), false, windowStyle, kPutInFront, true, 0L); + PSTR("Tools"), false, windowStyle, kPutInFront, 0L); else coordWindow = NewWindow(nil, &coordWindowRect, - PSTR("Tools"), false, windowStyle, kPutInFront, true, 0L); + PSTR("Tools"), false, windowStyle, kPutInFront, 0L); if (coordWindow == nil) RedAlert(kErrNoMemory); diff --git a/GpApp/DialogUtils.cpp b/GpApp/DialogUtils.cpp index 2557ee7..9588044 100644 --- a/GpApp/DialogUtils.cpp +++ b/GpApp/DialogUtils.cpp @@ -397,7 +397,9 @@ void GetDialogString (Dialog *theDialog, short item, StringPtr theString) void SetDialogString (Dialog *theDialog, short item, const PLPasStr &theString) { - theDialog->GetItems()[item - 1].GetWidget()->SetString(theString); + PortabilityLayer::Widget *widget = theDialog->GetItems()[item - 1].GetWidget(); + widget->SetString(theString); + widget->DrawControl(theDialog->GetWindow()->GetDrawSurface()); } //-------------------------------------------------------------- GetDialogStringLen diff --git a/GpApp/DynamicMaps.cpp b/GpApp/DynamicMaps.cpp index 14ee7f2..4814c4d 100644 --- a/GpApp/DynamicMaps.cpp +++ b/GpApp/DynamicMaps.cpp @@ -9,6 +9,7 @@ #include "Environ.h" #include "MainWindow.h" #include "Objects.h" +#include "QDPixMap.h" #include "RectUtils.h" #include "Room.h" #include "Utilities.h" diff --git a/GpApp/Events.cpp b/GpApp/Events.cpp index 760d7c2..b921baf 100644 --- a/GpApp/Events.cpp +++ b/GpApp/Events.cpp @@ -442,7 +442,7 @@ void HandleIdleTask (void) { if (theMode == kEditMode) { - SetPort((GrafPtr)mainWindow); + SetPort(&mainWindow->GetDrawSurface()->m_port); DoMarquee(); if ((autoRoomEdit) && (newRoomNow)) diff --git a/GpApp/HighScores.cpp b/GpApp/HighScores.cpp index c720e58..45bcb89 100644 --- a/GpApp/HighScores.cpp +++ b/GpApp/HighScores.cpp @@ -69,7 +69,7 @@ void DoHighScores (void) Rect tempRect; SpinCursor(3); - SetPort((GrafPtr)workSrcMap); + SetPort(&workSrcMap->m_port); workSrcMap->FillRect(workSrcRect); QSetRect(&tempRect, 0, 0, 640, 480); QOffsetRect(&tempRect, splashOriginH, splashOriginV); diff --git a/GpApp/House.cpp b/GpApp/House.cpp index 41cd203..930dcb0 100644 --- a/GpApp/House.cpp +++ b/GpApp/House.cpp @@ -28,6 +28,8 @@ void UpdateGoToDialog (Dialog *); Boolean GoToFilter (Dialog *, EventRecord *, short *); +extern PortabilityLayer::ResourceArchive *houseResFork; + houseHand thisHouse; linksPtr linksList; @@ -241,11 +243,7 @@ void WhereDoesGliderBegin (Rect *theRect, short mode) Boolean HouseHasOriginalPicts (void) { - short nPicts; - - PL_NotYetImplemented(); nPicts = 0; - //nPicts = Count1Resources('PICT'); - return (nPicts > 0); + return houseResFork->HasAnyResourcesOfType('PICT'); } //-------------------------------------------------------------- CountHouseLinks diff --git a/GpApp/HouseInfo.cpp b/GpApp/HouseInfo.cpp index aa42027..7fdc53b 100644 --- a/GpApp/HouseInfo.cpp +++ b/GpApp/HouseInfo.cpp @@ -12,6 +12,8 @@ #include "Externs.h" #include "DialogManager.h" #include "DialogUtils.h" +#include "HostDisplayDriver.h" +#include "IGpDisplayDriver.h" #define kHouseInfoDialogID 1001 @@ -181,7 +183,7 @@ Boolean HouseFilter (Dialog *dial, EventRecord *event, short *item) { if (houseCursorIs != kBeamCursor) { - SetBuiltinCursor(iBeamCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kIBeam); houseCursorIs = kBeamCursor; } } @@ -231,7 +233,7 @@ void DoHouseInfo (void) houseInfoDialog = PortabilityLayer::DialogManager::GetInstance()->LoadDialog(kHouseInfoDialogID, kPutInFront, &substitutions); if (houseInfoDialog == nil) RedAlert(kErrDialogDidntLoad); - SetPort((GrafPtr)houseInfoDialog); + SetPort(&houseInfoDialog->GetWindow()->GetDrawSurface()->m_port); ShowWindow(houseInfoDialog->GetWindow()); SetDialogString(houseInfoDialog, kBannerTextItem, banner); diff --git a/GpApp/Input.cpp b/GpApp/Input.cpp index 64d5ea7..06a8453 100644 --- a/GpApp/Input.cpp +++ b/GpApp/Input.cpp @@ -12,6 +12,7 @@ #include "Externs.h" #include "InputManager.h" #include "MainWindow.h" +#include "QDPixMap.h" #include "RectUtils.h" diff --git a/GpApp/InterfaceInit.cpp b/GpApp/InterfaceInit.cpp index 28c45dd..fc6e25c 100644 --- a/GpApp/InterfaceInit.cpp +++ b/GpApp/InterfaceInit.cpp @@ -8,6 +8,8 @@ #include "Externs.h" #include "Environ.h" +#include "HostDisplayDriver.h" +#include "IGpDisplayDriver.h" #include "Map.h" #include "MenuManager.h" #include "PLKeyEncoding.h" @@ -20,15 +22,14 @@ #define kHoriCursorID 130 #define kDiagCursorID 131 +struct IGpCursor; extern THandle mirrorRects; extern WindowPtr mapWindow, toolsWindow, linkWindow; extern WindowPtr menuWindow; extern Rect shieldRect, boardSrcRect, localRoomsDest[]; -extern CursHandle handCursorH, vertCursorH, horiCursorH; -extern CursHandle diagCursorH; -extern Cursor handCursor, vertCursor, horiCursor; -extern Cursor diagCursor; +extern IGpCursor *handCursor, *vertCursor, *horiCursor; +extern IGpCursor *diagCursor; extern MenuHandle appleMenu, gameMenu, optionsMenu, houseMenu; extern Point shieldPt; extern long incrementModeTime; @@ -81,25 +82,21 @@ void InitializeMenus (void) void GetExtraCursors (void) { - handCursorH = GetCursor(kHandCursorID); - if (handCursorH == nil) + handCursor = PortabilityLayer::HostDisplayDriver::GetInstance()->LoadCursor(false, kHandCursorID); + if (handCursor == nil) RedAlert(kErrFailedResourceLoad); - handCursor = **handCursorH; - vertCursorH = GetCursor(kVertCursorID); - if (vertCursorH == nil) + vertCursor = PortabilityLayer::HostDisplayDriver::GetInstance()->LoadCursor(false, kVertCursorID); + if (vertCursor == nil) RedAlert(kErrFailedResourceLoad); - vertCursor = **vertCursorH; - horiCursorH = GetCursor(kHoriCursorID); - if (horiCursorH == nil) + horiCursor = PortabilityLayer::HostDisplayDriver::GetInstance()->LoadCursor(false, kHoriCursorID); + if (horiCursor == nil) RedAlert(kErrFailedResourceLoad); - horiCursor = **horiCursorH; - diagCursorH = GetCursor(kDiagCursorID); - if (diagCursorH == nil) + diagCursor = PortabilityLayer::HostDisplayDriver::GetInstance()->LoadCursor(false, kDiagCursorID); + if (diagCursor == nil) RedAlert(kErrFailedResourceLoad); - diagCursor = **diagCursorH; } //-------------------------------------------------------------- VariableInit diff --git a/GpApp/Link.cpp b/GpApp/Link.cpp index 65edaa5..1f81d6b 100644 --- a/GpApp/Link.cpp +++ b/GpApp/Link.cpp @@ -221,15 +221,15 @@ void OpenLinkWindow (void) if (linkWindow == nil) { - const uint16_t windowStyle = PortabilityLayer::WindowStyleFlags::kTitleBar | PortabilityLayer::WindowStyleFlags::kMiniBar; + const uint16_t windowStyle = PortabilityLayer::WindowStyleFlags::kTitleBar | PortabilityLayer::WindowStyleFlags::kMiniBar | PortabilityLayer::WindowStyleFlags::kCloseBox; QSetRect(&linkWindowRect, 0, 0, 129, 30); if (thisMac.hasColor) linkWindow = NewCWindow(nil, &linkWindowRect, - PSTR("Link"), false, windowStyle, kPutInFront, true, 0L); + PSTR("Link"), false, windowStyle, kPutInFront, 0L); else linkWindow = NewWindow(nil, &linkWindowRect, - PSTR("Link"), false, windowStyle, kPutInFront, true, 0L); + PSTR("Link"), false, windowStyle, kPutInFront, 0L); MoveWindow(linkWindow, isLinkH, isLinkV, true); diff --git a/GpApp/MainWindow.cpp b/GpApp/MainWindow.cpp index 1a9a6d8..694d314 100644 --- a/GpApp/MainWindow.cpp +++ b/GpApp/MainWindow.cpp @@ -14,6 +14,7 @@ #include "House.h" #include "InputManager.h" #include "MenuManager.h" +#include "QDPixMap.h" #include "RectUtils.h" #include "PLKeyEncoding.h" #include "PLStandardColors.h" @@ -35,10 +36,8 @@ CTabHandle theCTab; PixMapHandle thePMap; ColorSpec * wasColors; ColorSpec * newColors; -CursHandle handCursorH, vertCursorH, horiCursorH; -CursHandle diagCursorH; -Cursor handCursor, vertCursor, horiCursor; -Cursor diagCursor; +IGpCursor *handCursor, *vertCursor, *horiCursor; +IGpCursor *diagCursor; Rect workSrcRect; DrawSurface *workSrcMap; Rect mainWindowRect; @@ -209,8 +208,8 @@ void OpenMainWindow (void) if (OptionKeyDown()) { - isEditH = 3; - isEditV = 41; + isEditH = 10; + isEditV = 46; } MoveWindow(mainWindow, isEditH, isEditV, true); ShowWindow(mainWindow); @@ -242,7 +241,7 @@ void OpenMainWindow (void) Rect scorebarRect = thisMac.screen; scorebarRect.bottom = scorebarRect.top + kScoreboardTall; - PortabilityLayer::WindowDef windowDef = PortabilityLayer::WindowDef::Create(scorebarRect, PortabilityLayer::WindowStyleFlags::kBorderless, true, false, 0, 0, PSTR("Scoreboard")); + PortabilityLayer::WindowDef windowDef = PortabilityLayer::WindowDef::Create(scorebarRect, PortabilityLayer::WindowStyleFlags::kBorderless, true, 0, 0, PSTR("Scoreboard")); boardWindow = windowManager->CreateWindow(windowDef); if (boardWindow != nil) windowManager->PutWindowBehind(boardWindow, PL_GetPutInFrontWindowPtr()); diff --git a/GpApp/Map.cpp b/GpApp/Map.cpp index 75b79b8..fb002e7 100644 --- a/GpApp/Map.cpp +++ b/GpApp/Map.cpp @@ -17,6 +17,7 @@ #include "PLWidgets.h" #include "WindowDef.h" #include "WindowManager.h" +#include "QDPixMap.h" #include "RectUtils.h" #include "Utilities.h" @@ -111,8 +112,7 @@ void FlagMapRoomsForUpdate (void) return; // SetPortWindowPort(mapWindow); - InvalWindowRect(mapWindow, &wasActiveRoomRect); - InvalWindowRect(mapWindow, &activeRoomRect); + UpdateMapWindow(); } #endif @@ -343,8 +343,8 @@ void ResizeMapWindow (short newH, short newV) mapVScroll->SetPosition(Point::Create(mapWindowRect.right - kMapScrollBarWidth + 2, 0)); mapVScroll->Resize(kMapScrollBarWidth, mapWindowRect.bottom - kMapScrollBarWidth + 3); mapTopRoom = mapVScroll->GetState(); - - InvalWindowRect(mapWindow, &mapWindowRect); + + UpdateMapWindow(); #endif } @@ -362,9 +362,9 @@ void OpenMapWindow (void) mapRoomsWide * kMapRoomWidth + kMapScrollBarWidth - 2, mapRoomsHigh * kMapRoomHeight + kMapScrollBarWidth - 2); - const uint16_t windowStyle = PortabilityLayer::WindowStyleFlags::kTitleBar | PortabilityLayer::WindowStyleFlags::kResizable | PortabilityLayer::WindowStyleFlags::kMiniBar; + const uint16_t windowStyle = PortabilityLayer::WindowStyleFlags::kTitleBar | PortabilityLayer::WindowStyleFlags::kResizable | PortabilityLayer::WindowStyleFlags::kMiniBar | PortabilityLayer::WindowStyleFlags::kCloseBox;; - PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(mapWindowRect, windowStyle, false, true, 0, 0, PSTR("Map")); + PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(mapWindowRect, windowStyle, false, 0, 0, PSTR("Map")); mapWindow = PortabilityLayer::WindowManager::GetInstance()->CreateWindow(wdef); @@ -386,7 +386,7 @@ void OpenMapWindow (void) PortabilityLayer::WindowManager::GetInstance()->ShowWindow(mapWindow); // FlagWindowFloating(mapWindow); TEMP - use flaoting windows - SetPort((GrafPtr)mapWindow); + SetPort(&mapWindow->GetDrawSurface()->m_port); QSetRect(&mapHScrollRect, -1, mapRoomsHigh * kMapRoomHeight, mapRoomsWide * kMapRoomWidth + 1, mapRoomsHigh * kMapRoomHeight + kMapScrollBarWidth); @@ -425,6 +425,8 @@ void OpenMapWindow (void) mapWindowRect.bottom + 2); CenterMapOnRoom(thisRoom->suite, thisRoom->floor); + + UpdateMapWindow(); } UpdateMapCheckmark(true); @@ -579,7 +581,7 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) { #ifndef COMPILEDEMO Rect aRoom; - ControlHandle whichControl; + PortabilityLayer::Widget *whichControl = nullptr; Point wherePt, globalWhere; long controlRef; short whichPart, localH, localV; @@ -665,7 +667,7 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) } else { - controlRef = GetControlReference(whichControl); + controlRef = whichControl->GetReferenceConstant(); if (controlRef == kHScrollRef) { switch (whichPart) @@ -683,7 +685,7 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) case kControlIndicatorPart: if (TrackControl(whichControl, wherePt, nil)) { - mapLeftRoom = GetControlValue(whichControl); + mapLeftRoom = whichControl->GetState(); RedrawMapContents(); } break; @@ -706,7 +708,7 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) case kControlIndicatorPart: if (TrackControl(whichControl, wherePt, nil)) { - mapTopRoom = GetControlValue(whichControl); + mapTopRoom = whichControl->GetState(); RedrawMapContents(); } break; diff --git a/GpApp/Marquee.cpp b/GpApp/Marquee.cpp index 8ce4c6f..b8fded1 100644 --- a/GpApp/Marquee.cpp +++ b/GpApp/Marquee.cpp @@ -6,11 +6,15 @@ #include "Externs.h" +#include "HostDisplayDriver.h" +#include "IGpDisplayDriver.h" #include "Marquee.h" #include "Objects.h" #include "ObjectEdit.h" #include "RectUtils.h" +#include + #define kMarqueePatListID 128 #define kHandleSideLong 9 @@ -25,7 +29,7 @@ Rect marqueeGliderRect; Boolean gliderMarqueeUp; -extern Cursor handCursor, vertCursor, horiCursor, diagCursor; +extern IGpCursor *handCursor, *vertCursor, *horiCursor, *diagCursor; extern Rect leftStartGliderSrc; @@ -216,7 +220,7 @@ void DragMarqueeRect (DrawSurface *surface, Point start, Rect *theRect, Boolean Point wasPt, newPt; short deltaH, deltaV; - SetCursor(&handCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetCursor(handCursor); StopMarquee(); const uint8_t *pattern = theMarquee.pats[theMarquee.index]; @@ -259,9 +263,9 @@ void DragMarqueeHandle (DrawSurface *surface, Point start, short *dragged) short deltaH, deltaV; if ((theMarquee.direction == kAbove) || (theMarquee.direction == kBelow)) - SetCursor(&vertCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetCursor(vertCursor); else - SetCursor(&horiCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetCursor(horiCursor); StopMarquee(); const uint8_t *pattern = theMarquee.pats[theMarquee.index]; @@ -344,7 +348,7 @@ void DragMarqueeCorner (DrawSurface *surface, Point start, short *hDragged, shor Point wasPt, newPt; short deltaH, deltaV; - SetCursor(&diagCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetCursor(diagCursor); StopMarquee(); const uint8_t *pattern = theMarquee.pats[theMarquee.index]; @@ -428,11 +432,9 @@ Boolean PtInMarqueeHandle (Point where) void DrawGliderMarquee (void) { - CopyBits((BitMap *)*GetGWorldPixMap(blowerMaskMap), - GetPortBitMapForCopyBits(GetWindowPort(mainWindow)), - &leftStartGliderSrc, - &marqueeGliderRect, - srcXor); + DrawSurface *surface = GetWindowPort(mainWindow); + ImageInvert(*GetGWorldPixMap(blowerMaskMap), GetPortBitMapForCopyBits(surface), leftStartGliderSrc, marqueeGliderRect); + surface->m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } //-------------------------------------------------------------- SetMarqueeGliderCenter @@ -488,7 +490,7 @@ void DrawMarquee (DrawSurface *surface, const uint8_t *pattern) break; } - surface->InvertDrawLine(points[0], points[1], pattern); + surface->InvertFillRect(Rect::Create(points[0].v, points[0].h, points[1].v, points[1].h), pattern); } if (gliderMarqueeUp) diff --git a/GpApp/Menu.cpp b/GpApp/Menu.cpp index 1e7e646..9c336d2 100644 --- a/GpApp/Menu.cpp +++ b/GpApp/Menu.cpp @@ -747,7 +747,7 @@ short QueryResumeGame (void) theDial = PortabilityLayer::DialogManager::GetInstance()->LoadDialog(kResumeGameDial, kPutInFront, &substitutions); if (theDial == nil) RedAlert(kErrDialogDidntLoad); - SetPort((GrafPtr)theDial); + SetPort(&theDial->GetWindow()->GetDrawSurface()->m_port); ShowWindow(theDial->GetWindow()); DrawDefaultButton(theDial); diff --git a/GpApp/ObjectAdd.cpp b/GpApp/ObjectAdd.cpp index a245382..8662ddd 100644 --- a/GpApp/ObjectAdd.cpp +++ b/GpApp/ObjectAdd.cpp @@ -789,7 +789,7 @@ Boolean AddNewObject (Point where, short what, Boolean showItNow) ReadyBackground(thisRoom->background, thisRoom->tiles); GetThisRoomsObjRects(); DrawThisRoomsObjects(); - InvalWindowRect(mainWindow, &mainWindowRect); + UpdateMainWindow(); if (handled) { diff --git a/GpApp/ObjectEdit.cpp b/GpApp/ObjectEdit.cpp index a587c76..284d8da 100644 --- a/GpApp/ObjectEdit.cpp +++ b/GpApp/ObjectEdit.cpp @@ -2316,8 +2316,7 @@ void DrawThisRoomsObjects (void) if (GetNumberOfLights(thisRoomNumber) <= 0) { surface->SetMaskMode(true); - surface->SetPattern8x8(*GetQDGlobalsGray(&dummyPattern)); - surface->FillRect(backSrcRect); + surface->FillRectWithPattern8x8(backSrcRect, *GetQDGlobalsGray(&dummyPattern)); surface->SetMaskMode(false); } diff --git a/GpApp/ObjectInfo.cpp b/GpApp/ObjectInfo.cpp index 1d904bb..aad1452 100644 --- a/GpApp/ObjectInfo.cpp +++ b/GpApp/ObjectInfo.cpp @@ -947,7 +947,7 @@ void DoBlowerObjectInfo (short what) infoDial = PortabilityLayer::DialogManager::GetInstance()->LoadDialog(kBlowerInfoDialogID, kPutInFront, &substitutions); if (infoDial == nil) RedAlert(kErrDialogDidntLoad); - SetPort((GrafPtr)infoDial); + SetPort(&infoDial->GetWindow()->GetDrawSurface()->m_port); newDirection = thisRoom->objects[objActive].data.a.vector & 0x0F; if (thisRoom->objects[objActive].data.a.initial) @@ -1544,7 +1544,7 @@ void DoLightObjectInfo (void) infoDial = PortabilityLayer::DialogManager::GetInstance()->LoadDialog(kLightInfoDialogID, kPutInFront, &substitutions); if (infoDial == nil) RedAlert(kErrDialogDidntLoad); - SetPort((GrafPtr)infoDial); + SetPort(&infoDial->GetWindow()->GetDrawSurface()->m_port); if (thisRoom->objects[objActive].data.f.initial) SetDialogItemValue(infoDial, kInitialStateCheckbox, 1); diff --git a/GpApp/Render.cpp b/GpApp/Render.cpp index fba6932..d1c9f62 100644 --- a/GpApp/Render.cpp +++ b/GpApp/Render.cpp @@ -12,6 +12,7 @@ #include "Objects.h" #include "Play.h" #include "Player.h" +#include "QDPixMap.h" #include "RectUtils.h" #include "Room.h" #include "RubberBands.h" @@ -148,7 +149,7 @@ void DrawReflection (gliderPtr thisGlider, Boolean oneOrTwo) dest = thisGlider->dest; QOffsetRect(&dest, playOriginH - 20, playOriginV - 16); - SetPort((GrafPtr)workSrcMap); + SetPort(&workSrcMap->m_port); long numMirrorRects = GetHandleSize(mirrorRects.StaticCast()) / sizeof(Rect); diff --git a/GpApp/Room.cpp b/GpApp/Room.cpp index e7fd4be..58d9c00 100644 --- a/GpApp/Room.cpp +++ b/GpApp/Room.cpp @@ -16,6 +16,7 @@ #include "House.h" #include "InputManager.h" #include "MainWindow.h" +#include "MemoryManager.h" #include "RectUtils.h" @@ -197,13 +198,13 @@ Boolean CreateNewRoom (short h, short v) if (availableRoom == -1) // found no available rooms { - howMuch = sizeof(roomType); // add new room to end of house - theErr = PtrAndHand((Ptr)thisRoom, thisHouse.StaticCast(), howMuch); - if (theErr != PLErrors::kNone) + // add new room to end of house + if (!PortabilityLayer::MemoryManager::GetInstance()->ResizeHandle(thisHouse.MMBlock(), thisHouse.MMBlock()->m_size + sizeof(roomType))) { - YellowAlert(kYellowUnaccounted, theErr); + YellowAlert(kYellowUnaccounted, PLErrors::kOutOfMemory); return (false); } + (*thisHouse)->rooms[(*thisHouse)->nRooms] = *thisRoom; (*thisHouse)->nRooms++; // increment nRooms numberRooms = (*thisHouse)->nRooms; previousRoom = thisRoomNumber; @@ -336,7 +337,7 @@ void ReflectCurrentRoom (Boolean forceMapRedraw) PL_NotYetImplemented_TODO("FixMe"); DebugPixMap(backSrcMap->m_port.GetPixMap(), "DebugData/EditorSplash6"); - //InvalWindowRect(mainWindow, &mainWindowRect); + UpdateMainWindow(); #endif } diff --git a/GpApp/RoomInfo.cpp b/GpApp/RoomInfo.cpp index 67b5228..6934ad9 100644 --- a/GpApp/RoomInfo.cpp +++ b/GpApp/RoomInfo.cpp @@ -14,7 +14,11 @@ #include "DialogManager.h" #include "DialogUtils.h" #include "Externs.h" +#include "HostDisplayDriver.h" +#include "IGpDisplayDriver.h" #include "RectUtils.h" +#include "PLTimeTaggedVOSEvent.h" +#include "QDPixMap.h" #include "ResourceCompiledRef.h" #include "ResourceManager.h" #include "Utilities.h" @@ -41,7 +45,8 @@ void UpdateRoomInfoDialog (Dialog *); void DragMiniTile (DrawSurface *, Point, short *); void HiliteTileOver (DrawSurface *, Point); -Boolean RoomFilter (Dialog *, EventRecord *, short *); +int16_t RoomFilter (Dialog *dialog, const TimeTaggedVOSEvent *evt); + short ChooseOriginalArt (short); void UpdateOriginalArt (Dialog *); Boolean OriginalArtFilter (Dialog *, EventRecord *, short *); @@ -58,7 +63,7 @@ short tileOver, tempBack, cursorIs; Boolean originalLeftOpen, originalTopOpen, originalRightOpen, originalBottomOpen; Boolean originalFloor; -extern Cursor handCursor; +extern IGpCursor *handCursor; extern short lastBackground; @@ -71,7 +76,6 @@ void UpdateRoomInfoDialog (Dialog *theDialog) Rect src, dest; short i; - DrawDialog(theDialog); if (tempBack >= kUserBackground) SetPopUpMenuValue(theDialog, kRoomPopupItem, kOriginalArtworkItem); else @@ -81,7 +85,7 @@ void UpdateRoomInfoDialog (Dialog *theDialog) CopyBits(GetPortBitMapForCopyBits(tileSrcMap), - GetPortBitMapForCopyBits(GetDialogPort(theDialog)), + GetPortBitMapForCopyBits(theDialog->GetWindow()->GetDrawSurface()), &tileSrcRect, &tileSrc, srcCopy); /* CopyBits(&((GrafPtr)tileSrcMap)->portBits, @@ -96,7 +100,7 @@ void UpdateRoomInfoDialog (Dialog *theDialog) QOffsetRect(&src, tempTiles[i] * kMiniTileWide, 0); CopyBits(GetPortBitMapForCopyBits(tileSrcMap), - GetPortBitMapForCopyBits(GetDialogPort(theDialog)), + GetPortBitMapForCopyBits(theDialog->GetWindow()->GetDrawSurface()), &src, &dest, srcCopy); /* CopyBits(&((GrafPtr)tileSrcMap)->portBits, @@ -263,7 +267,7 @@ void HiliteTileOver (DrawSurface *surface, Point mouseIs) { if (cursorIs != kHandCursor) { - SetCursor(&handCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetCursor(handCursor); cursorIs = kHandCursor; } @@ -327,7 +331,7 @@ void HiliteTileOver (DrawSurface *surface, Point mouseIs) { if (cursorIs != kBeamCursor) { - SetBuiltinCursor(iBeamCursor); + PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kIBeam); cursorIs = kBeamCursor; } } @@ -346,78 +350,66 @@ void HiliteTileOver (DrawSurface *surface, Point mouseIs) //-------------------------------------------------------------- RoomFilter #ifndef COMPILEDEMO -Boolean RoomFilter (Dialog *dial, EventRecord *event, short *item) +int16_t RoomFilter(Dialog *dial, const TimeTaggedVOSEvent *evt) { Point mouseIs; short newTileOver; + if (!evt) + return -1; + DrawSurface *surface = dial->GetWindow()->GetDrawSurface(); - - switch (event->what) + + if (evt->IsKeyDownEvent()) { - case keyDown: - switch (event->message) + switch (PackVOSKeyCode(evt->m_vosEvent.m_event.m_keyboardInputEvent)) { - 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; + return kOkayButton; - case PL_KEY_SPECIAL(kEscape): + case PL_KEY_SPECIAL(kEscape): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; + return kCancelButton; - case PL_KEY_SPECIAL(kTab): + case PL_KEY_SPECIAL(kTab): SelectDialogItemText(dial, kRoomNameItem, 0, 1024); - return(true); - break; - - default: - return(false); - } - break; - - case mouseDown: - mouseIs = event->where; - mouseIs -= dial->GetWindow()->TopLeftCoord(); - if (tileSrc.Contains(mouseIs)) - { - if (StillDown()) - { - DragMiniTile(surface, mouseIs, &newTileOver); - if ((newTileOver >= 0) && (newTileOver < kNumTiles)) - { - tempTiles[newTileOver] = tileOver; - UpdateRoomInfoDialog(dial); - } - } - return(true); - } - else - return(false); - break; - - case mouseUp: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateRoomInfoDialog(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return 0; + default: - GetMouse(&mouseIs); - HiliteTileOver(surface, mouseIs); - return(false); - break; + return -1; + } + } + else if (evt->m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) + { + const GpMouseInputEvent &mouseEvent = evt->m_vosEvent.m_event.m_mouseInputEvent; + + if (evt->IsLMouseDownEvent()) + { + mouseIs = Point::Create(mouseEvent.m_x, mouseEvent.m_y); + mouseIs -= dial->GetWindow()->TopLeftCoord(); + if (tileSrc.Contains(mouseIs)) + { + if (StillDown()) + { + DragMiniTile(surface, mouseIs, &newTileOver); + if ((newTileOver >= 0) && (newTileOver < kNumTiles)) + { + tempTiles[newTileOver] = tileOver; + UpdateRoomInfoDialog(dial); + } + } + return 0; + } + else + return -1; + } + else if (mouseEvent.m_eventType == GpMouseEventTypes::kMove) + { + mouseIs = dial->GetWindow()->MouseToLocal(mouseEvent); + HiliteTileOver(surface, mouseIs); + } } } #endif @@ -470,7 +462,7 @@ void DoRoomInfo (void) roomInfoDialog = PortabilityLayer::DialogManager::GetInstance()->LoadDialog(kRoomInfoDialogID, kPutInFront, &substitutions); if (roomInfoDialog == nil) RedAlert(kErrDialogDidntLoad); - SetPort((GrafPtr)roomInfoDialog); + SetPort(&roomInfoDialog->GetWindow()->GetDrawSurface()->m_port); // Fix this later. TEMP // AddMenuToPopUp(roomInfoDialog, kRoomPopupItem, backgroundsMenu); @@ -497,10 +489,12 @@ void DoRoomInfo (void) MyDisableControl(roomInfoDialog, kBoundsButton); leaving = false; + + UpdateRoomInfoDialog(roomInfoDialog); while (!leaving) { - ModalDialog(RoomFilter, &item); + item = roomInfoDialog->ExecuteModal(RoomFilter); if (item == kOkayButton) { diff --git a/GpApp/Scoreboard.cpp b/GpApp/Scoreboard.cpp index d104ac1..41c7076 100644 --- a/GpApp/Scoreboard.cpp +++ b/GpApp/Scoreboard.cpp @@ -11,6 +11,7 @@ #include "Externs.h" #include "Environ.h" #include "MenuManager.h" +#include "QDPixMap.h" #include "QDStandardPalette.h" #include "RectUtils.h" diff --git a/GpApp/Tools.cpp b/GpApp/Tools.cpp index 08d5f1b..171bdb0 100644 --- a/GpApp/Tools.cpp +++ b/GpApp/Tools.cpp @@ -14,6 +14,7 @@ #include "FontFamily.h" #include "PLWidgets.h" #include "PLPopupMenuWidget.h" +#include "QDPixMap.h" #include "RectUtils.h" #include "Utilities.h" #include "WindowDef.h" @@ -199,7 +200,7 @@ void EraseSelectedTool (void) if (toolsWindow == nil) return; - SetPort((GrafPtr)toolsWindow); + SetPort(&toolsWindow->GetDrawSurface()->m_port); toolIcon = toolSelected; if ((toolMode == kBlowerMode) && (toolIcon >= 7)) @@ -299,9 +300,9 @@ void OpenToolsWindow (void) QOffsetRect(&toolTextRect, 0, 157 - 15); { - const uint16_t windowStyle = PortabilityLayer::WindowStyleFlags::kTitleBar | PortabilityLayer::WindowStyleFlags::kMiniBar; + const uint16_t windowStyle = PortabilityLayer::WindowStyleFlags::kTitleBar | PortabilityLayer::WindowStyleFlags::kMiniBar | PortabilityLayer::WindowStyleFlags::kCloseBox; - PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(toolsWindowRect, windowStyle, false, true, 0, 0, PSTR("Tools")); + PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(toolsWindowRect, windowStyle, false, 0, 0, PSTR("Tools")); toolsWindow = wm->CreateWindow(wdef); } @@ -333,6 +334,8 @@ void OpenToolsWindow (void) classPopUp = PortabilityLayer::PopupMenuWidget::Create(state); } + toolsWindow->DrawControls(); + if (classPopUp == nil) RedAlert(kErrFailedResourceLoad); @@ -473,7 +476,7 @@ void HandleToolsClick (Point wherePt) part = FindControl(wherePt, toolsWindow, &theControl); if ((theControl != nil) && (part != 0)) { - part = TrackControl(theControl, wherePt, nullptr); + part = theControl->Capture(wherePt, nullptr); if (part != 0) { newMode = theControl->GetState(); diff --git a/GpApp/Transitions.cpp b/GpApp/Transitions.cpp index e177eac..b394071 100644 --- a/GpApp/Transitions.cpp +++ b/GpApp/Transitions.cpp @@ -9,6 +9,7 @@ #include "Externs.h" #include "Environ.h" #include "MainWindow.h" +#include "QDPixMap.h" #include "PLQDraw.h" #include "RectUtils.h" diff --git a/GpApp/WindowUtils.cpp b/GpApp/WindowUtils.cpp index 14b0af7..28e622e 100644 --- a/GpApp/WindowUtils.cpp +++ b/GpApp/WindowUtils.cpp @@ -108,7 +108,7 @@ void OpenMessageWindow (const PLPasStr &title) SetRect(&mssgWindowRect, 0, 0, 256, kMessageWindowTall); - const PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(mssgWindowRect, windowStyle, false, false, 0, 0, title); + const PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(mssgWindowRect, windowStyle, false, 0, 0, title); mssgWindow = PortabilityLayer::WindowManager::GetInstance()->CreateWindow(wdef); diff --git a/GpCommon/EGpStandardCursor.h b/GpCommon/EGpStandardCursor.h index cde59a7..499655a 100644 --- a/GpCommon/EGpStandardCursor.h +++ b/GpCommon/EGpStandardCursor.h @@ -5,6 +5,8 @@ namespace EGpStandardCursors enum EGpStandardCursor { kArrow, + kIBeam, + kWait, kHidden, }; } diff --git a/GpCommon/GpColorCursor_Win32.h b/GpCommon/GpCursor_Win32.h similarity index 50% rename from GpCommon/GpColorCursor_Win32.h rename to GpCommon/GpCursor_Win32.h index 0c24d51..da45656 100644 --- a/GpCommon/GpColorCursor_Win32.h +++ b/GpCommon/GpCursor_Win32.h @@ -1,10 +1,10 @@ #pragma once -#include "IGpColorCursor_Win32.h" +#include "IGpCursor_Win32.h" #include "GpWindows.h" -class GpColorCursor_Win32 final : public IGpColorCursor_Win32 +class GpCursor_Win32 final : public IGpCursor_Win32 { public: void Destroy() override; @@ -14,11 +14,11 @@ public: void IncRef() override; void DecRef() override; - static GpColorCursor_Win32 *Load(const wchar_t *path); + static IGpCursor_Win32 *Load(const wchar_t *path); private: - GpColorCursor_Win32(HCURSOR cursor); - ~GpColorCursor_Win32(); + GpCursor_Win32(HCURSOR cursor); + ~GpCursor_Win32(); HCURSOR m_cursor; int m_refCount; diff --git a/GpCommon/GpWindows.h b/GpCommon/GpWindows.h index 4ba6743..1bfb8a4 100644 --- a/GpCommon/GpWindows.h +++ b/GpCommon/GpWindows.h @@ -8,10 +8,11 @@ #undef CreateMutex #undef DeleteFile - +#undef LoadCursor struct IGpFiber; -struct IGpColorCursor_Win32; +struct IGpBWCursor_Win32; +struct IGpCursor_Win32; struct IGpVOSEventQueue; struct GpWindowsGlobals @@ -23,7 +24,6 @@ struct GpWindowsGlobals int m_nCmdShow; IGpFiber *(*m_createFiberFunc)(LPVOID fiber); - IGpColorCursor_Win32 *(*m_loadColorCursorFunc)(const wchar_t *path); + IGpCursor_Win32 *(*m_loadCursorFunc)(const wchar_t *path); void (*m_translateWindowsMessageFunc)(const MSG *msg, IGpVOSEventQueue *eventQueue); }; - diff --git a/GpCommon/IGpColorCursor.h b/GpCommon/IGpCursor.h similarity index 68% rename from GpCommon/IGpColorCursor.h rename to GpCommon/IGpCursor.h index f59fbc5..9e1b8d6 100644 --- a/GpCommon/IGpColorCursor.h +++ b/GpCommon/IGpCursor.h @@ -1,6 +1,6 @@ #pragma once -struct IGpColorCursor +struct IGpCursor { virtual void Destroy() = 0; }; diff --git a/GpCommon/IGpColorCursor_Win32.h b/GpCommon/IGpCursor_Win32.h similarity index 66% rename from GpCommon/IGpColorCursor_Win32.h rename to GpCommon/IGpCursor_Win32.h index 480be90..44d3802 100644 --- a/GpCommon/IGpColorCursor_Win32.h +++ b/GpCommon/IGpCursor_Win32.h @@ -1,9 +1,9 @@ #pragma once -#include "IGpColorCursor.h" +#include "IGpCursor.h" #include "GpWindows.h" -struct IGpColorCursor_Win32 : public IGpColorCursor +struct IGpCursor_Win32 : public IGpCursor { public: virtual const HCURSOR &GetHCursor() const = 0; diff --git a/GpCommon/IGpDisplayDriver.h b/GpCommon/IGpDisplayDriver.h index 46cc590..a975ce6 100644 --- a/GpCommon/IGpDisplayDriver.h +++ b/GpCommon/IGpDisplayDriver.h @@ -4,7 +4,7 @@ #include "EGpStandardCursor.h" struct IGpDisplayDriverSurface; -struct IGpColorCursor; +struct IGpCursor; // Display drivers are responsible for timing and calling the game tick function. struct IGpDisplayDriver @@ -16,10 +16,10 @@ public: virtual void GetDisplayResolution(unsigned int *width, unsigned int *height, GpPixelFormat_t *bpp) = 0; virtual IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, GpPixelFormat_t pixelFormat) = 0; - virtual void DrawSurface(IGpDisplayDriverSurface *surface, size_t x, size_t y, size_t width, size_t height) = 0; + virtual void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height) = 0; - virtual IGpColorCursor *LoadColorCursor(int cursorID) = 0; - virtual void SetColorCursor(IGpColorCursor *colorCursor) = 0; + virtual IGpCursor *LoadCursor(bool isColor, int cursorID) = 0; + virtual void SetCursor(IGpCursor *cursor) = 0; virtual void SetStandardCursor(EGpStandardCursor_t standardCursor) = 0; virtual void UpdatePalette(const void *paletteData) = 0; diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp index 0f87ece..134abbc 100644 --- a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp +++ b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.cpp @@ -3,7 +3,7 @@ #include "GpDisplayDriverD3D11.h" #include "GpDisplayDriverSurfaceD3D11.h" #include "GpWindows.h" -#include "IGpColorCursor_Win32.h" +#include "IGpCursor_Win32.h" #include "IGpFiber.h" #include @@ -502,7 +502,7 @@ void GpDisplayDriverD3D11::SynchronizeCursors() void GpDisplayDriverD3D11::ChangeToCursor(HCURSOR cursor) { if (m_mouseIsInClientArea) - SetCursor(cursor); + ::SetCursor(cursor); SetClassLongPtrW(m_hwnd, GCLP_HCURSOR, reinterpret_cast(cursor)); } @@ -511,6 +511,12 @@ void GpDisplayDriverD3D11::ChangeToStandardCursor(EGpStandardCursor_t cursor) { switch (cursor) { + case EGpStandardCursors::kIBeam: + ChangeToCursor(m_ibeamCursor); + break; + case EGpStandardCursors::kWait: + ChangeToCursor(m_waitCursor); + break; case EGpStandardCursors::kArrow: default: ChangeToCursor(m_arrowCursor); @@ -624,7 +630,7 @@ IGpDisplayDriverSurface *GpDisplayDriverD3D11::CreateSurface(size_t width, size_ return GpDisplayDriverSurfaceD3D11::Create(m_device, m_deviceContext, width, height, pixelFormat); } -void GpDisplayDriverD3D11::DrawSurface(IGpDisplayDriverSurface *surface, size_t x, size_t y, size_t width, size_t height) +void GpDisplayDriverD3D11::DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height) { ID3D11Buffer *vbPtr = m_quadVertexBuffer; UINT vbStride = sizeof(float) * 2; @@ -710,24 +716,30 @@ void GpDisplayDriverD3D11::DrawSurface(IGpDisplayDriverSurface *surface, size_t m_deviceContext->DrawIndexed(6, 0, 0); } -IGpColorCursor *GpDisplayDriverD3D11::LoadColorCursor(int cursorID) +IGpCursor *GpDisplayDriverD3D11::LoadCursor(bool isColor, int cursorID) { const size_t bufSize = MAX_PATH; wchar_t path[bufSize]; - int sz = _snwprintf(path, bufSize, L"%sPackaged\\WinCursors\\%i.cur", m_osGlobals->m_baseDir, cursorID); + int sz = 0; + if (isColor) + sz = _snwprintf(path, bufSize, L"%sPackaged\\WinCursors\\c%i.cur", m_osGlobals->m_baseDir, cursorID); + else + sz = _snwprintf(path, bufSize, L"%sPackaged\\WinCursors\\b%i.cur", m_osGlobals->m_baseDir, cursorID); + if (sz < 0 || static_cast(sz) >= bufSize) return nullptr; - return m_osGlobals->m_loadColorCursorFunc(path); + return m_osGlobals->m_loadCursorFunc(path); } + // We can't just set the cursor because we want to post WM_SETCURSOR to keep it limited // to the game window area, but depending on the fiber implementation, this may not be // the window thread. -void GpDisplayDriverD3D11::SetColorCursor(IGpColorCursor *colorCursor) +void GpDisplayDriverD3D11::SetCursor(IGpCursor *cursor) { - IGpColorCursor_Win32 *winCursor = static_cast(colorCursor); + IGpCursor_Win32 *winCursor = static_cast(cursor); winCursor->IncRef(); @@ -797,6 +809,8 @@ GpDisplayDriverD3D11::GpDisplayDriverD3D11(const GpDisplayDriverProperties &prop m_frameTimeSliceSize = m_QPFrequency.QuadPart * static_cast(properties.m_frameTimeLockNumerator) / static_cast(properties.m_frameTimeLockDenominator); m_arrowCursor = reinterpret_cast(LoadImageW(nullptr, MAKEINTRESOURCEW(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_SHARED)); + m_ibeamCursor = reinterpret_cast(LoadImageW(nullptr, MAKEINTRESOURCEW(OCR_IBEAM), IMAGE_CURSOR, 0, 0, LR_SHARED)); + m_waitCursor = reinterpret_cast(LoadImageW(nullptr, MAKEINTRESOURCEW(OCR_WAIT), IMAGE_CURSOR, 0, 0, LR_SHARED)); } GpDisplayDriverD3D11::~GpDisplayDriverD3D11() diff --git a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h index 4dcdca8..a9a61e2 100644 --- a/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h +++ b/GpDisplayDriver_D3D11/GpDisplayDriverD3D11.h @@ -11,7 +11,8 @@ #include "GpPixelFormat.h" struct GpWindowsGlobals; -struct IGpColorCursor_Win32; +struct IGpCursor_Win32; +struct IGpCursor; struct IGpFiber; struct IDXGISwapChain1; @@ -37,10 +38,10 @@ public: void GetDisplayResolution(unsigned int *width, unsigned int *height, GpPixelFormat_t *bpp) override; IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, GpPixelFormat_t pixelFormat) override; - void DrawSurface(IGpDisplayDriverSurface *surface, size_t x, size_t y, size_t width, size_t height) override; + void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height) override; - IGpColorCursor *LoadColorCursor(int cursorID) override; - void SetColorCursor(IGpColorCursor *colorCursor) override; + IGpCursor *LoadCursor(bool isColor, int cursorID) override; + void SetCursor(IGpCursor *cursor) override; void SetStandardCursor(EGpStandardCursor_t standardCursor) override; void UpdatePalette(const void *paletteData) override; @@ -109,8 +110,8 @@ private: DWORD m_windowWidth; DWORD m_windowHeight; - IGpColorCursor_Win32 *m_activeCursor; - IGpColorCursor_Win32 *m_pendingCursor; + IGpCursor_Win32 *m_activeCursor; + IGpCursor_Win32 *m_pendingCursor; EGpStandardCursor_t m_currentStandardCursor; EGpStandardCursor_t m_pendingStandardCursor; bool m_mouseIsInClientArea; @@ -119,5 +120,7 @@ private: GpWindowsGlobals *m_osGlobals; HCURSOR m_arrowCursor; + HCURSOR m_waitCursor; + HCURSOR m_ibeamCursor; HWND m_hwnd; }; diff --git a/PortabilityLayer/BitmapImage.h b/PortabilityLayer/BitmapImage.h index defa68b..15a3e99 100644 --- a/PortabilityLayer/BitmapImage.h +++ b/PortabilityLayer/BitmapImage.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "BMPFormat.h" #include "SharedTypes.h" diff --git a/PortabilityLayer/DialogManager.cpp b/PortabilityLayer/DialogManager.cpp index 8ff3ad2..c0c6ca6 100644 --- a/PortabilityLayer/DialogManager.cpp +++ b/PortabilityLayer/DialogManager.cpp @@ -328,11 +328,6 @@ namespace PortabilityLayer if (isVisible) widget->DrawControl(surface); - else - { - surface->SetForeColor(StdColors::Red()); - surface->FrameRect(surface->m_port.GetRect()); - } } } @@ -621,7 +616,11 @@ namespace PortabilityLayer WindowManager *wm = PortabilityLayer::WindowManager::GetInstance(); - WindowDef wdef = WindowDef::Create(rect, WindowStyleFlags::kAlert, visible, hasCloseBox, referenceConstant, positionSpec, title); + uint16_t styleFlags = WindowStyleFlags::kAlert; + if (hasCloseBox) + styleFlags |= PortabilityLayer::WindowStyleFlags::kCloseBox; + + WindowDef wdef = WindowDef::Create(rect, styleFlags, visible, referenceConstant, positionSpec, title); Window *window = wm->CreateWindow(wdef); if (!window) { diff --git a/PortabilityLayer/HostDisplayDriver.h b/PortabilityLayer/HostDisplayDriver.h index 518a7a1..00c6125 100644 --- a/PortabilityLayer/HostDisplayDriver.h +++ b/PortabilityLayer/HostDisplayDriver.h @@ -5,7 +5,7 @@ #include "GpPixelFormat.h" #include "EGpStandardCursor.h" -struct IGpColorCursor; +struct IGpCursor; struct IGpDisplayDriver; namespace PortabilityLayer diff --git a/PortabilityLayer/MenuManager.cpp b/PortabilityLayer/MenuManager.cpp index 04b2965..55fb306 100644 --- a/PortabilityLayer/MenuManager.cpp +++ b/PortabilityLayer/MenuManager.cpp @@ -131,6 +131,11 @@ namespace PortabilityLayer void SetItemChecked(const THandle &menu, unsigned int index, bool checked) override; bool SetItemText(const THandle &menu, unsigned int index, const PLPasStr &str) override; + bool GetMenuEnabled(const THandle &menuHandle) const override; + bool GetItemEnabled(const THandle &menu, unsigned int index) const override; + bool GetItemChecked(const THandle &menu, unsigned int index) const override; + PLPasStr GetItemText(const THandle &menu, unsigned int index) const override; + bool IsPointInMenuBar(const Vec2i &point) const override; bool FindMenuShortcut(uint16_t &menuID, uint16_t &itemID, uint8_t shortcutChar) override; @@ -517,6 +522,42 @@ namespace PortabilityLayer return true; } + bool MenuManagerImpl::GetMenuEnabled(const THandle &menuHandle) const + { + const Menu *menu = (*menuHandle); + return menu->enabled; + } + + bool MenuManagerImpl::GetItemEnabled(const THandle &menuHandle, unsigned int index) const + { + const Menu *menu = (*menuHandle); + if (index >= menu->numMenuItems) + return false; + + return menu->menuItems[index].enabled; + } + + bool MenuManagerImpl::GetItemChecked(const THandle &menuHandle, unsigned int index) const + { + const Menu *menu = (*menuHandle); + if (index >= menu->numMenuItems) + return false; + + return menu->menuItems[index].checked; + } + + PLPasStr MenuManagerImpl::GetItemText(const THandle &menuHandle, unsigned int index) const + { + const Menu *menu = (*menuHandle); + if (index >= menu->numMenuItems) + return PSTR(""); + + const uint32_t nameOffset = menu->menuItems[index].nameOffsetInStringBlob; + + const uint8_t *pstr = static_cast(menu->stringBlobHandle->m_contents) + nameOffset; + return PLPasStr(pstr); + } + 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 39b1b98..16d6d54 100644 --- a/PortabilityLayer/MenuManager.h +++ b/PortabilityLayer/MenuManager.h @@ -34,6 +34,11 @@ namespace PortabilityLayer 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 GetMenuEnabled(const THandle &menuHandle) const = 0; + virtual bool GetItemEnabled(const THandle &menu, unsigned int index) const = 0; + virtual bool GetItemChecked(const THandle &menu, unsigned int index) const = 0; + virtual PLPasStr GetItemText(const THandle &menu, unsigned int index) const = 0; + virtual bool IsPointInMenuBar(const Vec2i &point) const = 0; virtual bool FindMenuShortcut(uint16_t &menuID, uint16_t &itemID, uint8_t shortcutChar) = 0; diff --git a/PortabilityLayer/PLCore.cpp b/PortabilityLayer/PLCore.cpp index ab7d386..eaa9dcd 100644 --- a/PortabilityLayer/PLCore.cpp +++ b/PortabilityLayer/PLCore.cpp @@ -20,7 +20,7 @@ #include "HostDisplayDriver.h" #include "HostSystemServices.h" #include "HostVOSEventQueue.h" -#include "IGpColorCursor.h" +#include "IGpCursor.h" #include "IGpDisplayDriver.h" #include "InputManager.h" #include "ResourceManager.h" @@ -87,26 +87,11 @@ Rect BERect::ToRect() const return rect; } -CursHandle GetCursor(int cursorID) -{ - return PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('CURS', cursorID).ReinterpretCast(); -} - void HideCursor() { PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kHidden); } -void SetCursor(CursPtr cursor) -{ - PL_NotYetImplemented(); -} - -void SetBuiltinCursor(int builtinCursor) -{ - PL_NotYetImplemented(); -} - void Delay(int ticks, UInt32 *endTickCount) { PLSysCalls::Sleep(ticks); @@ -203,13 +188,13 @@ WindowPtr GetNewCWindow(int resID, void *storage, WindowPtr behind) return window; } -WindowPtr NewCWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, Boolean hasCloseBox, long userdata) +WindowPtr NewCWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, long userdata) { PL_NotYetImplemented(); return nullptr; } -WindowPtr NewWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, Boolean hasCloseBox, long userdata) +WindowPtr NewWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, long userdata) { PL_NotYetImplemented(); return nullptr; @@ -616,12 +601,6 @@ long GetHandleSize(Handle handle) return handle.MMBlock()->m_size; } -PLError_t PtrAndHand(const void *data, Handle handle, Size size) -{ - PL_NotYetImplemented(); - return PLErrors::kNone; -} - PLError_t SetHandleSize(Handle hdl, Size newSize) { PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); @@ -779,6 +758,19 @@ bool Window::AddWidget(PortabilityLayer::Widget *widget) return true; } +ArrayView Window::GetWidgets() const +{ + return ArrayView(m_widgets, m_numWidgets); +} + +PortabilityLayer::Widget* Window::GetWidgetById() const +{ + //for (size_t i = 0; i < m_numWidgets; i++) + // m_widgets[i]->get + //return ArrayView(m_widgets, m_numWidgets); + return nullptr; +} + void Window::FocusWidget(PortabilityLayer::Widget *widget) { if (m_widgetWithFocus != widget) @@ -825,7 +817,7 @@ void Window::OnTick() m_widgets[i]->OnTick(); } -ArrayView Window::GetWidgets() const +DrawSurface *Window::GetChromeSurface(WindowChromeSide_t aChromeSide) const { - return ArrayView< PortabilityLayer::Widget*>(m_widgets, m_numWidgets); + return const_cast(m_chromeSurfaces + aChromeSide); } diff --git a/PortabilityLayer/PLCore.h b/PortabilityLayer/PLCore.h index 479d120..a407d90 100644 --- a/PortabilityLayer/PLCore.h +++ b/PortabilityLayer/PLCore.h @@ -15,7 +15,7 @@ template class ArrayView; -struct IGpColorCursor; +struct IGpCursor; struct GpVOSEvent; struct GpMouseInputEvent; struct TimeTaggedVOSEvent; @@ -71,6 +71,21 @@ struct Cursor { }; +namespace WindowChromeSides +{ + enum WindowChromeSide + { + kTop, + kLeft, + kBottom, + kRight, + + kCount + }; +} + +typedef WindowChromeSides::WindowChromeSide WindowChromeSide_t; + struct Window { Window(); @@ -84,6 +99,8 @@ struct Window Point TopLeftCoord() const; bool AddWidget(PortabilityLayer::Widget *widget); + ArrayView GetWidgets() const; + PortabilityLayer::Widget* GetWidgetById() const; void FocusWidget(PortabilityLayer::Widget *widget); PortabilityLayer::Widget *GetWidgetWithFocus() const; @@ -93,7 +110,7 @@ struct Window void OnTick(); - ArrayView GetWidgets() const; + DrawSurface *GetChromeSurface(WindowChromeSide_t aChromeSide) const; DrawSurface m_surface; // Must be the first item until the immediate mode draw API is completely removed @@ -105,6 +122,8 @@ struct Window protected: ~Window(); + DrawSurface m_chromeSurfaces[WindowChromeSides::kCount]; + PortabilityLayer::Widget **m_widgets; size_t m_numWidgets; size_t m_numTickReceivingWidgets; @@ -225,9 +244,6 @@ void InitCursor(); CursHandle GetCursor(int cursorID); void HideCursor(); -void SetCursor(CursPtr cursor); -void SetBuiltinCursor(int builtinCursor); - void Delay(int ticks, UInt32 *endTickCount); short FindWindow(Point point, WindowPtr *window); // Translates global coordinates to window coordinates, returns a region ID @@ -243,8 +259,8 @@ void DisposeWindow(WindowPtr window); void GetWindowBounds(WindowPtr window, WindowRegionType windowRegion, Rect *rect); WindowPtr GetNewCWindow(int resID, void *storage, WindowPtr behind); -WindowPtr NewCWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, Boolean hasCloseBox, long userdata); -WindowPtr NewWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, Boolean hasCloseBox, long userdata); +WindowPtr NewCWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, long userdata); +WindowPtr NewWindow(void *storage, const Rect *bounds, const PLPasStr &title, Boolean visible, int wdef, WindowPtr behind, long userdata); void SizeWindow(WindowPtr window, int width, int height, Boolean addToUpdateRegion); void MoveWindow(WindowPtr window, int x, int y, Boolean moveToFront); void ShowWindow(WindowPtr window); @@ -288,7 +304,6 @@ void InvalWindowRect(WindowPtr window, const Rect *rect); Handle NewHandle(Size size); long GetHandleSize(Handle handle); -PLError_t PtrAndHand(const void *data, Handle handle, Size size); // Appends data to the end of a handle PLError_t SetHandleSize(Handle hdl, Size newSize); void *NewPtr(Size size); diff --git a/PortabilityLayer/PLPopupMenuWidget.cpp b/PortabilityLayer/PLPopupMenuWidget.cpp index 44fce90..581e47c 100644 --- a/PortabilityLayer/PLPopupMenuWidget.cpp +++ b/PortabilityLayer/PLPopupMenuWidget.cpp @@ -1,5 +1,11 @@ #include "PLPopupMenuWidget.h" +#include "MenuManager.h" +#include "PLMenus.h" +#include "PLPasStr.h" +#include "PLStandardColors.h" +#include "FontFamily.h" + namespace PortabilityLayer { PopupMenuWidget::PopupMenuWidget(const WidgetBasicState &state) @@ -9,6 +15,53 @@ namespace PortabilityLayer bool PopupMenuWidget::Init(const WidgetBasicState &state) { + m_menu = GetMenu(state.m_resID); + if (!m_menu) + return false; + return true; } + + //WidgetHandleState_t PopupMenuWidget::ProcessEvent(const TimeTaggedVOSEvent &evt); + //int16_t PopupMenuWidget::Capture(const Point &pos, WidgetUpdateCallback_t callback); + void PopupMenuWidget::DrawControl(DrawSurface *surface) + { + const Rect rect = m_rect; + const Rect innerRect = rect.Inset(2, 2); + + surface->SetForeColor(StdColors::White()); + surface->FillRect(m_rect.Inset(1, 1)); + + surface->SetForeColor(StdColors::Black()); + surface->FrameRect(m_rect); + + Rect textRect = innerRect; + textRect.right -= 9; + + surface->SetSystemFont(12, PortabilityLayer::FontFamilyFlag_Bold); + Point basePoint = Point::Create(textRect.left + 2, (textRect.top + textRect.bottom + surface->MeasureFontAscender() + 1) / 2); + + surface->DrawStringConstrained(basePoint, GetString(), true, textRect); + + Point arrowMidPoint = Point::Create(textRect.right + 5, (textRect.top + textRect.bottom + 1) / 2); + + const Rect arrowRects[3] = + { + Rect::Create(arrowMidPoint.v - 1, arrowMidPoint.h - 2, arrowMidPoint.v, arrowMidPoint.h + 3), + Rect::Create(arrowMidPoint.v, arrowMidPoint.h - 1, arrowMidPoint.v + 1, arrowMidPoint.h + 2), + Rect::Create(arrowMidPoint.v + 1, arrowMidPoint.h, arrowMidPoint.v + 2, arrowMidPoint.h + 1) + }; + + for (int i = 0; i < 3; i++) + { + const Rect constrainedRect = innerRect.Intersect(arrowRects[i]); + surface->FillRect(constrainedRect); + } + } + + PLPasStr PopupMenuWidget::GetString() const + { + const Menu *menu = (*m_menu); + return PortabilityLayer::MenuManager::GetInstance()->GetItemText(m_menu, m_state - 1); + } } diff --git a/PortabilityLayer/PLPopupMenuWidget.h b/PortabilityLayer/PLPopupMenuWidget.h index 0cfb4a8..1f22462 100644 --- a/PortabilityLayer/PLPopupMenuWidget.h +++ b/PortabilityLayer/PLPopupMenuWidget.h @@ -3,6 +3,8 @@ #include "PascalStr.h" #include "PLWidgets.h" +struct Menu; + namespace PortabilityLayer { class PopupMenuWidget final : public WidgetSpec @@ -11,5 +13,14 @@ namespace PortabilityLayer explicit PopupMenuWidget(const WidgetBasicState &state); bool Init(const WidgetBasicState &state) override; + + //WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt); + //int16_t Capture(const Point &pos, WidgetUpdateCallback_t callback); + void DrawControl(DrawSurface *surface) override; + + PLPasStr GetString() const override; + + private: + THandle m_menu; }; } diff --git a/PortabilityLayer/PLQDraw.cpp b/PortabilityLayer/PLQDraw.cpp index 885a75e..4513417 100644 --- a/PortabilityLayer/PLQDraw.cpp +++ b/PortabilityLayer/PLQDraw.cpp @@ -998,7 +998,61 @@ void DrawSurface::FillRect(const Rect &rect) void DrawSurface::FillRectWithPattern8x8(const Rect &rect, const uint8_t *pattern) { - PL_NotYetImplemented_TODO("FillWithPattern"); + if (!rect.IsValid()) + return; + + PortabilityLayer::QDPort *qdPort = &m_port; + + GpPixelFormat_t pixelFormat = qdPort->GetPixelFormat(); + + Rect constrainedRect = rect; + const Rect portRect = qdPort->GetRect(); + + PortabilityLayer::QDState *qdState = qdPort->GetState(); + constrainedRect = constrainedRect.Intersect(qdState->m_clipRect); + constrainedRect = constrainedRect.Intersect(qdPort->GetRect()); + + if (!constrainedRect.IsValid()) + return; + + assert(portRect.left == 0 && portRect.top == 0); + + PortabilityLayer::PixMapImpl *pixMap = static_cast(*qdPort->GetPixMap()); + const size_t pitch = pixMap->GetPitch(); + const size_t firstIndex = static_cast(constrainedRect.top) * pitch + static_cast(constrainedRect.left); + const size_t numLines = static_cast(constrainedRect.bottom - constrainedRect.top); + const size_t numCols = static_cast(constrainedRect.right - constrainedRect.left); + uint8_t *pixData = static_cast(pixMap->GetPixelData()); + + const int patternFirstRow = (constrainedRect.top & 7); + const int patternFirstCol = (constrainedRect.left & 7); + + switch (pixelFormat) + { + case GpPixelFormats::k8BitStandard: + { + const uint8_t color = qdState->ResolveForeColor8(nullptr, 0); + + size_t scanlineIndex = 0; + for (size_t ln = 0; ln < numLines; ln++) + { + const int patternRow = static_cast((patternFirstRow + ln) & 7); + const size_t firstLineIndex = firstIndex + ln * pitch; + + for (size_t col = 0; col < numCols; col++) + { + const int patternCol = static_cast((patternFirstCol + col) & 7); + if ((pattern[patternRow] >> patternCol) & 1) + pixData[firstLineIndex + col] = color; + } + } + } + break; + default: + PL_NotYetImplemented(); + return; + } + m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } @@ -1238,11 +1292,6 @@ void DrawSurface::DrawLine(const Point &a, const Point &b) PlotLine(m_port.GetState(), this, PortabilityLayer::Vec2i(a.h, a.v), PortabilityLayer::Vec2i(b.h, b.v)); } -void DrawSurface::InvertDrawLine(const Point &a, const Point &b, const uint8_t *pattern) -{ - PL_NotYetImplemented(); -} - void GetClip(Rect *rect) { PortabilityLayer::QDState *qdState = PortabilityLayer::QDManager::GetInstance()->GetState(); @@ -1301,12 +1350,81 @@ void DrawSurface::FrameRoundRect(const Rect &rect, int quadrantWidth, int quadra void DrawSurface::InvertFrameRect(const Rect &rect, const uint8_t *pattern) { - PL_NotYetImplemented(); + if (!rect.IsValid()) + return; + + if (rect.Width() <= 2 || rect.Height() <= 2) + { + InvertFillRect(rect, pattern); + return; + } + else + { + InvertFillRect(Rect::Create(rect.top, rect.left, rect.top + 1, rect.right), pattern); + InvertFillRect(Rect::Create(rect.top + 1, rect.left, rect.bottom - 1, rect.left + 1), pattern); + InvertFillRect(Rect::Create(rect.bottom - 1, rect.left, rect.bottom + 1, rect.right), pattern); + InvertFillRect(Rect::Create(rect.top + 1, rect.right - 1, rect.bottom - 1, rect.right), pattern); + } } void DrawSurface::InvertFillRect(const Rect &rect, const uint8_t *pattern) { - PL_NotYetImplemented_TODO("InvertFillRect"); + if (!rect.IsValid()) + return; + + PortabilityLayer::QDPort *qdPort = &m_port; + + GpPixelFormat_t pixelFormat = qdPort->GetPixelFormat(); + + Rect constrainedRect = rect; + const Rect portRect = qdPort->GetRect(); + + PortabilityLayer::QDState *qdState = qdPort->GetState(); + constrainedRect = constrainedRect.Intersect(qdState->m_clipRect); + constrainedRect = constrainedRect.Intersect(qdPort->GetRect()); + + if (!constrainedRect.IsValid()) + return; + + assert(portRect.left == 0 && portRect.top == 0); + + PortabilityLayer::PixMapImpl *pixMap = static_cast(*qdPort->GetPixMap()); + const size_t pitch = pixMap->GetPitch(); + const size_t firstIndex = static_cast(constrainedRect.top) * pitch + static_cast(constrainedRect.left); + const size_t numLines = static_cast(constrainedRect.bottom - constrainedRect.top); + const size_t numCols = static_cast(constrainedRect.right - constrainedRect.left); + uint8_t *pixData = static_cast(pixMap->GetPixelData()); + + const int patternFirstRow = (constrainedRect.top & 7); + const int patternFirstCol = (constrainedRect.left & 7); + + switch (pixelFormat) + { + case GpPixelFormats::k8BitStandard: + { + const uint8_t color = qdState->ResolveForeColor8(nullptr, 0); + + size_t scanlineIndex = 0; + for (size_t ln = 0; ln < numLines; ln++) + { + const int patternRow = static_cast((patternFirstRow + ln) & 7); + const size_t firstLineIndex = firstIndex + ln * pitch; + + for (size_t col = 0; col < numCols; col++) + { + const int patternCol = static_cast((patternFirstCol + col) & 7); + if ((pattern[patternRow] >> patternCol) & 1) + pixData[firstLineIndex + col] = 255 - pixData[firstLineIndex + col]; + } + } + } + break; + default: + PL_NotYetImplemented(); + return; + } + + m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } void DrawSurface::SetForeColor(const PortabilityLayer::RGBAColor &color) @@ -1617,6 +1735,63 @@ void CopyMaskConstrained(const BitMap *srcBitmap, const BitMap *maskBitmap, BitM CopyBitsComplete(srcBitmap, maskBitmap, destBitmap, srcRectBase, maskRectBase, destRectBase, constrainRect); } +// This doesn't bounds-check the source (because it's only used in one place) +void ImageInvert(const PixMap *invertMask, PixMap *targetBitmap, const Rect &srcRect, const Rect &destRect) +{ + assert(srcRect.Width() == destRect.Width()); + assert(srcRect.Height() == destRect.Height()); + + assert(invertMask->m_pixelFormat == GpPixelFormats::kBW1); + + const Rect invertBitmapRect = invertMask->m_rect; + const Rect targetBitmapRect = targetBitmap->m_rect; + + const Rect constrainedDestRect = targetBitmapRect.Intersect(destRect); + if (!constrainedDestRect.IsValid()) + return; + + const int32_t leftInset = constrainedDestRect.left - destRect.left; + const int32_t topInset = constrainedDestRect.top - destRect.top; + const int32_t rightInset = destRect.right - constrainedDestRect.right; + const int32_t bottomInset = destRect.bottom - constrainedDestRect.bottom; + + const int32_t firstSrcRow = srcRect.top - invertBitmapRect.top + topInset; + const int32_t firstSrcCol = srcRect.left - invertBitmapRect.left + leftInset; + const int32_t firstDestRow = destRect.top - targetBitmapRect.top + topInset; + const int32_t firstDestCol = destRect.left - targetBitmapRect.left + leftInset; + + const uint16_t numRows = destRect.Height(); + const uint16_t numCols = destRect.Width(); + + const size_t invertPitch = invertMask->m_pitch; + const uint8_t *invertPixelDataFirstRow = static_cast(invertMask->m_data) + firstSrcRow * invertPitch; + const size_t targetPitch = targetBitmap->m_pitch; + uint8_t *targetPixelDataFirstRow = static_cast(targetBitmap->m_data) + firstDestRow * targetPitch; + + const GpPixelFormat_t targetPixelFormat = targetBitmap->m_pixelFormat; + + for (uint16_t r = 0; r < numRows; r++) + { + const uint8_t *invertRowStart = invertPixelDataFirstRow + r * invertPitch; + uint8_t *targetRowStart = targetPixelDataFirstRow + r * targetPitch; + + switch (targetPixelFormat) + { + case GpPixelFormats::k8BitStandard: + for (uint16_t c = 0; c < numCols; c++) + { + const int32_t srcCol = c + firstSrcCol; + const int32_t destCol = c + firstDestCol; + if (invertRowStart[srcCol] != 0) + targetRowStart[destCol] = 255 - targetRowStart[destCol]; + } + break; + default: + PL_NotYetImplemented(); + break; + } + } +} bool PointInScanlineMask(Point point, PortabilityLayer::ScanlineMask *scanlineMask) { @@ -1629,7 +1804,7 @@ void CopyMask(const BitMap *srcBitmap, const BitMap *maskBitmap, BitMap *destBit CopyBitsComplete(srcBitmap, maskBitmap, destBitmap, srcRectBase, maskRectBase, destRectBase, nullptr); } -BitMap *GetPortBitMapForCopyBits(DrawSurface *grafPtr) +PixMap *GetPortBitMapForCopyBits(DrawSurface *grafPtr) { return *grafPtr->m_port.GetPixMap(); } diff --git a/PortabilityLayer/PLQDraw.h b/PortabilityLayer/PLQDraw.h index e947078..c7b3d7f 100644 --- a/PortabilityLayer/PLQDraw.h +++ b/PortabilityLayer/PLQDraw.h @@ -133,9 +133,11 @@ void CopyBitsConstrained(const BitMap *srcBitmap, BitMap *destBitmap, const Rect void CopyMask(const BitMap *srcBitmap, const BitMap *maskBitmap, BitMap *destBitmap, const Rect *srcRect, const Rect *maskRect, const Rect *destRect); void CopyMaskConstrained(const BitMap *srcBitmap, const BitMap *maskBitmap, BitMap *destBitmap, const Rect *srcRectBase, const Rect *maskRectBase, const Rect *destRectBase, const Rect *constraintRect); +void ImageInvert(const PixMap *invertMask, PixMap *targetBitmap, const Rect &srcRect, const Rect &destRect); + bool PointInScanlineMask(Point point, PortabilityLayer::ScanlineMask *scanlineMask); -BitMap *GetPortBitMapForCopyBits(DrawSurface *grafPtr); +PixMap *GetPortBitMapForCopyBits(DrawSurface *grafPtr); DrawSurface *GetWindowPort(WindowPtr window); // Computes A - B and returns it packed? diff --git a/PortabilityLayer/PLResourceManager.cpp b/PortabilityLayer/PLResourceManager.cpp index 2f17eb2..8eb5a98 100644 --- a/PortabilityLayer/PLResourceManager.cpp +++ b/PortabilityLayer/PLResourceManager.cpp @@ -281,32 +281,41 @@ namespace PortabilityLayer return GetResource(resTypeID, id, true); } - bool ResourceArchive::GetResourceSize(const ResTypeID &resTypeID, int id, size_t &outSize) + bool ResourceArchive::GetResourceSize(const ResTypeID &resTypeID, int id, size_t &outSize) const { - THandle hdl = GetResource(resTypeID, id, false); - if (const PortabilityLayer::MMHandleBlock *hdlBlock = hdl.MMBlock()) - { - outSize = hdlBlock->m_rmSelfRef->m_size; - return true; - } + size_t index = 0; + int validationRule = 0; + if (!IndexResource(resTypeID, id, index, validationRule)) + return false; - return false; + outSize = m_zipFileProxy->GetFileSize(index); + return true; } - THandle ResourceArchive::GetResource(const ResTypeID &resTypeID, int id, bool load) + bool ResourceArchive::HasAnyResourcesOfType(const ResTypeID &resTypeID) const + { + char resPrefix[6]; + resTypeID.ExportAsChars(resPrefix); + resPrefix[4] = '/'; + resPrefix[5] = '\0'; + + return m_zipFileProxy->HasPrefix(resPrefix); + } + + bool ResourceArchive::IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex, int &outValidationRule) const { const char *extension = ".bin"; - ResourceValidationRule_t validationRule = ResourceValidationRules::kNone; + outValidationRule = ResourceValidationRules::kNone; if (resTypeID == ResTypeID('snd ')) { extension = ".wav"; - validationRule = ResourceValidationRules::kWAV; + outValidationRule = ResourceValidationRules::kWAV; } else if (resTypeID == ResTypeID('Date') || resTypeID == ResTypeID('PICT')) { extension = ".bmp"; - validationRule = ResourceValidationRules::kBMP; + outValidationRule = ResourceValidationRules::kBMP; } else if (resTypeID == ResTypeID('STR#')) extension = ".txt"; @@ -320,7 +329,14 @@ namespace PortabilityLayer snprintf(resourceFile, sizeof(resourceFile) - 1, "%s/%i%s", resTag.m_id, id, extension); size_t index = 0; - if (!m_zipFileProxy->IndexFile(resourceFile, index)) + return m_zipFileProxy->IndexFile(resourceFile, outIndex); + } + + THandle ResourceArchive::GetResource(const ResTypeID &resTypeID, int id, bool load) + { + int validationRule = 0; + size_t index = 0; + if (!IndexResource(resTypeID, id, index, validationRule)) return THandle(); ResourceArchiveRef *ref = m_resourceHandles + index; @@ -348,7 +364,7 @@ namespace PortabilityLayer handle->m_contents = contents; handle->m_size = ref->m_size; - if (!m_zipFileProxy->LoadFile(index, contents) || (validationRule != ResourceValidationRules::kNone && !ValidateResource(contents, ref->m_size, validationRule))) + if (!m_zipFileProxy->LoadFile(index, contents) || (validationRule != ResourceValidationRules::kNone && !ValidateResource(contents, ref->m_size, static_cast(validationRule)))) { MemoryManager::GetInstance()->Release(contents); handle->m_contents = nullptr; diff --git a/PortabilityLayer/PLUnalignedPtr.h b/PortabilityLayer/PLUnalignedPtr.h new file mode 100644 index 0000000..5add020 --- /dev/null +++ b/PortabilityLayer/PLUnalignedPtr.h @@ -0,0 +1,49 @@ +#pragma once + +namespace PortabilityLayer +{ + template + class UnalignedPtr + { + public: + UnalignedPtr(); + explicit UnalignedPtr(const T *ref); + + const T *GetRawPtr() const; + T Get() const; + + private: + const T *m_ref; + }; + + template + UnalignedPtr::UnalignedPtr() + : m_ref(nullptr) + { + } + + template + UnalignedPtr::UnalignedPtr(const T *ref) + : m_ref(ref) + { + } +} + +#include + +namespace PortabilityLayer +{ + template + const T *UnalignedPtr::GetRawPtr() const + { + return m_ref; + } + + template + T UnalignedPtr::Get() const + { + T result; + memcpy(&result, m_ref, sizeof(T)); + return result; + } +} diff --git a/PortabilityLayer/PLWidgets.cpp b/PortabilityLayer/PLWidgets.cpp index 77574d4..59c3a4e 100644 --- a/PortabilityLayer/PLWidgets.cpp +++ b/PortabilityLayer/PLWidgets.cpp @@ -22,6 +22,11 @@ namespace PortabilityLayer return WidgetHandleStates::kIgnored; } + int16_t Widget::Capture(const Point &pos, WidgetUpdateCallback_t callback) + { + return 0; + } + void Widget::DrawControl(DrawSurface *surface) { (void)surface; @@ -107,6 +112,11 @@ namespace PortabilityLayer return PSTR(""); } + uint32_t Widget::GetReferenceConstant() const + { + return m_referenceConstant; + } + const Rect &Widget::GetRect() const { return m_rect; @@ -121,6 +131,7 @@ namespace PortabilityLayer : m_rect(state.m_rect) , m_window(state.m_window) , m_enabled(state.m_enabled) + , m_referenceConstant(state.m_refConstant) , m_state(state.m_state) , m_visible(true) { diff --git a/PortabilityLayer/PLWidgets.h b/PortabilityLayer/PLWidgets.h index 8bafc17..92045ad 100644 --- a/PortabilityLayer/PLWidgets.h +++ b/PortabilityLayer/PLWidgets.h @@ -10,6 +10,8 @@ struct Window; namespace PortabilityLayer { + class Widget; + namespace WidgetHandleStates { enum WidgetHandleState @@ -23,6 +25,8 @@ namespace PortabilityLayer typedef WidgetHandleStates::WidgetHandleState WidgetHandleState_t; + typedef void (*WidgetUpdateCallback_t)(Widget *control, int part); + struct WidgetBasicState { WidgetBasicState(); @@ -44,6 +48,7 @@ namespace PortabilityLayer virtual bool Init(const WidgetBasicState &state) = 0; virtual void Destroy() = 0; virtual WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt); + virtual int16_t Capture(const Point &pos, WidgetUpdateCallback_t callback); virtual void DrawControl(DrawSurface *surface); virtual void SetMin(int32_t v); @@ -62,6 +67,8 @@ namespace PortabilityLayer virtual void SetString(const PLPasStr &str); virtual PLPasStr GetString() const; + uint32_t GetReferenceConstant() const; + virtual void SetHighlightStyle(int16_t style); virtual bool HandlesTickEvents() const; @@ -87,6 +94,7 @@ namespace PortabilityLayer Window *m_window; Rect m_rect; + uint32_t m_referenceConstant; int16_t m_state; bool m_enabled; bool m_visible; diff --git a/PortabilityLayer/PortabilityLayer.vcxproj b/PortabilityLayer/PortabilityLayer.vcxproj index 475c36c..b8c7e99 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj +++ b/PortabilityLayer/PortabilityLayer.vcxproj @@ -226,6 +226,7 @@ + diff --git a/PortabilityLayer/PortabilityLayer.vcxproj.filters b/PortabilityLayer/PortabilityLayer.vcxproj.filters index 0fe804a..f426e2b 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj.filters +++ b/PortabilityLayer/PortabilityLayer.vcxproj.filters @@ -474,6 +474,9 @@ Header Files + + Header Files + diff --git a/PortabilityLayer/QDGraf.h b/PortabilityLayer/QDGraf.h index e4c74b2..053dab2 100644 --- a/PortabilityLayer/QDGraf.h +++ b/PortabilityLayer/QDGraf.h @@ -71,7 +71,6 @@ struct DrawSurface final void FillScanlineMask(const PortabilityLayer::ScanlineMask *scanlineMask); void DrawLine(const Point &a, const Point &b); - void InvertDrawLine(const Point &a, const Point &b, const uint8_t *pattern); void SetForeColor(const PortabilityLayer::RGBAColor &color); const PortabilityLayer::RGBAColor &GetForeColor() const; diff --git a/PortabilityLayer/ResourceManager.h b/PortabilityLayer/ResourceManager.h index f3378df..b9f01c8 100644 --- a/PortabilityLayer/ResourceManager.h +++ b/PortabilityLayer/ResourceManager.h @@ -31,12 +31,16 @@ namespace PortabilityLayer void Destroy(); THandle LoadResource(const ResTypeID &resTypeID, int id); - bool GetResourceSize(const ResTypeID &resTypeID, int id, size_t &outSize); + bool GetResourceSize(const ResTypeID &resTypeID, int id, size_t &outSize) const; + + bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const; private: ResourceArchive(ZipFileProxy *zipFileProxy, IOStream *stream, ResourceArchiveRef *resourceHandles); ~ResourceArchive(); + bool IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex, int &outValidationRule) const; + THandle GetResource(const ResTypeID &resTypeID, int id, bool load); ZipFileProxy *m_zipFileProxy; diff --git a/PortabilityLayer/WindowDef.cpp b/PortabilityLayer/WindowDef.cpp index 1f6a77a..43a38f9 100644 --- a/PortabilityLayer/WindowDef.cpp +++ b/PortabilityLayer/WindowDef.cpp @@ -69,10 +69,12 @@ namespace PortabilityLayer return false; // Unsupported window style } + if (wdefPart1.m_hasCloseBox != 0) + styleFlags |= WindowStyleFlags::kCloseBox; + m_initialRect = wdefPart1.m_initialRect.ToRect(); m_styleFlags = styleFlags; m_visibilityStatus = wdefPart1.m_visibilityStatus; - m_hasCloseBox = wdefPart1.m_hasCloseBox; m_referenceConstant = wdefPart1.m_referenceConstant; m_title[0] = wdefPart1.m_titleLength; @@ -87,17 +89,16 @@ namespace PortabilityLayer return true; } - WindowDef WindowDef::Create(const Rect &initialRect, uint16_t styleFlags, bool isVisible, bool hasCloseBox, uint32_t refConstant, uint16_t positionSpec, const PLPasStr &title) + WindowDef WindowDef::Create(const Rect &initialRect, uint16_t styleFlags, bool isVisible, uint32_t refConstant, uint16_t positionSpec, const PLPasStr &title) { WindowDef wdef; wdef.m_initialRect = initialRect; wdef.m_styleFlags = styleFlags; wdef.m_visibilityStatus = isVisible ? 1 : 0; - wdef.m_hasCloseBox = hasCloseBox ? 1 : 0; wdef.m_referenceConstant = refConstant; wdef.m_positionSpec = positionSpec; - const uint8_t titleLength = static_cast(std::max(255, title.Length())); + const uint8_t titleLength = static_cast(std::min(255, title.Length())); wdef.m_title[0] = titleLength; memcpy(wdef.m_title + 1, title.UChars(), titleLength); diff --git a/PortabilityLayer/WindowDef.h b/PortabilityLayer/WindowDef.h index c58864c..4a0a664 100644 --- a/PortabilityLayer/WindowDef.h +++ b/PortabilityLayer/WindowDef.h @@ -18,6 +18,7 @@ namespace PortabilityLayer kResizable = 4, kMiniBar = 8, kAlert = 16, + kCloseBox = 32, }; } @@ -26,13 +27,12 @@ namespace PortabilityLayer Rect m_initialRect; uint16_t m_styleFlags; uint16_t m_visibilityStatus; - uint16_t m_hasCloseBox; uint32_t m_referenceConstant; uint16_t m_positionSpec; uint8_t m_title[256]; bool Deserialize(IOStream *stream); - static WindowDef Create(const Rect &initialRect, uint16_t styleFlags, bool isVisible, bool hasCloseBox, uint32_t refConstant, uint16_t positionSpec, const PLPasStr &title); + static WindowDef Create(const Rect &initialRect, uint16_t styleFlags, bool isVisible, uint32_t refConstant, uint16_t positionSpec, const PLPasStr &title); }; } diff --git a/PortabilityLayer/WindowManager.cpp b/PortabilityLayer/WindowManager.cpp index 549898c..d304140 100644 --- a/PortabilityLayer/WindowManager.cpp +++ b/PortabilityLayer/WindowManager.cpp @@ -6,6 +6,8 @@ #include "IGpDisplayDriverSurface.h" #include "PLCore.h" #include "PLEventQueue.h" +#include "PLStandardColors.h" +#include "FontFamily.h" #include "MemoryManager.h" #include "MenuManager.h" #include "QDGraf.h" @@ -19,6 +21,53 @@ struct GDevice; namespace PortabilityLayer { class CGrafImpl; + class WindowImpl; + + struct WindowChromeTheme + { + virtual void GetChromePadding(const WindowImpl *window, uint16_t padding[WindowChromeSides::kCount]) const = 0; + virtual void RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const = 0; + }; + + template + struct WindowChromeThemeSingleton : public WindowChromeTheme + { + public: + static T *GetInstance(); + + private: + static T ms_instance; + }; + + class SimpleBoxChromeTheme final : public WindowChromeThemeSingleton + { + public: + void GetChromePadding(const WindowImpl *window, uint16_t padding[WindowChromeSides::kCount]) const override; + void RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const override; + }; + + class GenericWindowChromeTheme final : public WindowChromeThemeSingleton + { + public: + void GetChromePadding(const WindowImpl *window, uint16_t padding[WindowChromeSides::kCount]) const override; + void RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const override; + + private: + void RenderChromeTop(WindowImpl *window, DrawSurface *surface) const; + void RenderChromeLeft(WindowImpl *window, DrawSurface *surface) const; + void RenderChromeBottom(WindowImpl *window, DrawSurface *surface) const; + void RenderChromeRight(WindowImpl *window, DrawSurface *surface) const; + + void RenderChromeTopMini(WindowImpl *window, DrawSurface *surface) const; + void RenderChromeLeftMini(WindowImpl *window, DrawSurface *surface) const; + void RenderChromeBottomMini(WindowImpl *window, DrawSurface *surface) const; + void RenderChromeRightMini(WindowImpl *window, DrawSurface *surface) const; + + + static const int kDarkGray = 85; + static const int kMidGray = 187; + static const int kLightGray = 221; + }; class WindowImpl final : public Window { @@ -38,11 +87,22 @@ namespace PortabilityLayer bool IsVisible() const; void SetVisible(bool visible); + void GetChromePadding(uint16_t padding[WindowChromeSides::kCount]) const; + void GetChromeDimensions(int width, int height, Rect dimensions[WindowChromeSides::kCount]) const; + + bool IsBorderless() const; + uint16_t GetStyleFlags() const; + const PascalStr<255> &GetTitle() const; + private: WindowImpl *m_windowAbove; WindowImpl *m_windowBelow; + WindowChromeTheme *m_chromeTheme; + uint16_t m_styleFlags; bool m_visible; + + PascalStr<255> m_title; }; class WindowManagerImpl final : public WindowManager @@ -77,10 +137,272 @@ namespace PortabilityLayer static uint8_t ms_putInFrontSentinel; }; + + template + inline T *WindowChromeThemeSingleton::GetInstance() + { + + return &ms_instance; + } + + template + T WindowChromeThemeSingleton::ms_instance; + + //--------------------------------------------------------------------------- + void SimpleBoxChromeTheme::GetChromePadding(const WindowImpl *window, uint16_t padding[WindowChromeSides::kCount]) const + { + padding[WindowChromeSides::kTop] = 1; + padding[WindowChromeSides::kBottom] = 1; + padding[WindowChromeSides::kLeft] = 1; + padding[WindowChromeSides::kRight] = 1; + } + + void SimpleBoxChromeTheme::RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const + { + surface->SetForeColor(StdColors::Black()); + surface->FillRect((*surface->m_port.GetPixMap())->m_rect); + } + + //--------------------------------------------------------------------------- + void GenericWindowChromeTheme::GetChromePadding(const WindowImpl *window, uint16_t padding[WindowChromeSides::kCount]) const + { + if (window->GetStyleFlags() & WindowStyleFlags::kMiniBar) + { + padding[WindowChromeSides::kTop] = 13; + padding[WindowChromeSides::kBottom] = 1; + padding[WindowChromeSides::kLeft] = 1; + padding[WindowChromeSides::kRight] = 1; + + //if (window->GetStyleFlags() & WindowStyleFlags::kResizable) + //{ + // padding[WindowChromeSides::kBottom] = 16; + // padding[WindowChromeSides::kRight] = 16; + //} + } + else + { + padding[WindowChromeSides::kTop] = 22; + padding[WindowChromeSides::kBottom] = 6; + padding[WindowChromeSides::kLeft] = 6; + padding[WindowChromeSides::kRight] = 6; + + //if (window->GetStyleFlags() & WindowStyleFlags::kResizable) + //{ + // padding[WindowChromeSides::kBottom] = 21; + // padding[WindowChromeSides::kRight] = 21; + //} + } + } + + void GenericWindowChromeTheme::RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const + { + if (window->GetStyleFlags() & WindowStyleFlags::kMiniBar) + { + switch (chromeSide) + { + case WindowChromeSides::kTop: + RenderChromeTopMini(window, surface); + break; + case WindowChromeSides::kLeft: + RenderChromeLeftMini(window, surface); + break; + case WindowChromeSides::kBottom: + RenderChromeBottomMini(window, surface); + break; + case WindowChromeSides::kRight: + RenderChromeRightMini(window, surface); + break; + default: + break; + } + } + else + { + switch (chromeSide) + { + case WindowChromeSides::kTop: + RenderChromeTop(window, surface); + break; + case WindowChromeSides::kLeft: + RenderChromeLeft(window, surface); + break; + case WindowChromeSides::kBottom: + RenderChromeBottom(window, surface); + break; + case WindowChromeSides::kRight: + RenderChromeRight(window, surface); + break; + default: + break; + } + } + } + + void GenericWindowChromeTheme::RenderChromeTop(WindowImpl *window, DrawSurface *surface) const + { + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kMidGray, kMidGray, kMidGray, 255)); + surface->FillRect(rect); + + surface->SetForeColor(StdColors::Black()); + surface->FillRect(Rect::Create(rect.top, rect.left, rect.top + 1, rect.right)); + surface->FillRect(Rect::Create(rect.top, rect.left, rect.bottom, 1)); + surface->FillRect(Rect::Create(rect.top, rect.right - 1, rect.bottom, rect.right)); + surface->FillRect(Rect::Create(rect.bottom - 1, rect.left + 5, rect.bottom, rect.right - 5)); + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kDarkGray, kDarkGray, kDarkGray, 255)); + surface->FillRect(Rect::Create(rect.bottom - 2, rect.left + 4, rect.bottom - 1, rect.right - 5)); + surface->FillRect(Rect::Create(rect.bottom - 2, rect.left + 4, rect.bottom, rect.left + 5)); + surface->FillRect(Rect::Create(rect.top + 2, rect.right - 2, rect.bottom, rect.right - 1)); + + surface->SetForeColor(StdColors::White()); + surface->FillRect(Rect::Create(rect.top + 1, rect.left + 1, rect.bottom, rect.left + 2)); + surface->FillRect(Rect::Create(rect.top + 1, rect.left + 1, rect.top + 2, rect.right - 2)); + surface->FillRect(Rect::Create(rect.bottom - 1, rect.right - 5, rect.bottom, rect.right - 4)); + + surface->SetForeColor(StdColors::Black()); + surface->SetSystemFont(12, PortabilityLayer::FontFamilyFlags::FontFamilyFlag_Bold); + int32_t ascender = surface->MeasureFontAscender(); + + const PLPasStr titlePStr = window->GetTitle().ToShortStr(); + size_t titleWidth = surface->MeasureString(titlePStr); + + int32_t titleH = (rect.left + rect.right - static_cast(titleWidth) + 1) / 2; + int32_t titleV = (rect.top + rect.bottom + ascender + 1) / 2; + + surface->DrawString(Point::Create(titleH, titleV), titlePStr, true); + } + + void GenericWindowChromeTheme::RenderChromeLeft(WindowImpl *window, DrawSurface *surface) const + { + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + surface->SetForeColor(StdColors::Black()); + surface->FillRect(Rect::Create(rect.top, rect.right - 6, rect.bottom, rect.right - 5)); + surface->FillRect(Rect::Create(rect.top, rect.right - 1, rect.bottom, rect.right)); + + surface->SetForeColor(StdColors::White()); + surface->FillRect(Rect::Create(rect.top, rect.right - 5, rect.bottom, rect.right - 4)); + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kDarkGray, kDarkGray, kDarkGray, 255)); + surface->FillRect(Rect::Create(rect.top, rect.right - 2, rect.bottom, rect.right - 1)); + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kMidGray, kMidGray, kMidGray, 255)); + surface->FillRect(Rect::Create(rect.top, rect.right - 4, rect.bottom, rect.right - 2)); + } + + void GenericWindowChromeTheme::RenderChromeBottom(WindowImpl *window, DrawSurface *surface) const + { + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kMidGray, kMidGray, kMidGray, 255)); + surface->FillRect(Rect::Create(rect.top, rect.left + 1, rect.bottom - 1, rect.left + 5)); + surface->FillRect(Rect::Create(rect.bottom - 4, rect.left + 5, rect.bottom - 2, rect.right - 4)); + surface->FillRect(Rect::Create(rect.top, rect.right - 4, rect.bottom - 2, rect.right - 2)); + + surface->SetForeColor(StdColors::Black()); + surface->FillRect(Rect::Create(rect.top, rect.left, rect.bottom, rect.left + 1)); + surface->FillRect(Rect::Create(rect.bottom - 1, rect.left, rect.bottom, rect.right)); + surface->FillRect(Rect::Create(rect.top, rect.right - 1, rect.bottom, rect.right)); + surface->FillRect(Rect::Create(rect.top, rect.left + 5, rect.bottom - 5, rect.left + 6)); + surface->FillRect(Rect::Create(rect.top, rect.right - 6, rect.bottom - 5, rect.right - 5)); + surface->FillRect(Rect::Create(rect.bottom - 6, rect.left + 6, rect.bottom - 5, rect.right - 6)); + + surface->SetForeColor(StdColors::White()); + surface->FillRect(Rect::Create(rect.top, rect.right - 5, rect.bottom - 5, rect.right - 4)); + surface->FillRect(Rect::Create(rect.top, rect.left + 1, rect.bottom - 2, rect.left + 2)); + surface->FillRect(Rect::Create(rect.bottom - 5, rect.left + 5, rect.bottom - 4, rect.right - 4)); + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kDarkGray, kDarkGray, kDarkGray, 255)); + surface->FillRect(Rect::Create(rect.bottom - 2, rect.left + 2, rect.bottom - 1, rect.right - 2)); + surface->FillRect(Rect::Create(rect.top, rect.left + 4, rect.bottom - 5, rect.left + 5)); + surface->FillRect(Rect::Create(rect.top, rect.right - 2, rect.bottom - 1, rect.right - 1)); + } + + void GenericWindowChromeTheme::RenderChromeRight(WindowImpl *window, DrawSurface *surface) const + { + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + surface->SetForeColor(StdColors::Black()); + surface->FillRect(Rect::Create(rect.top, rect.right - 6, rect.bottom, rect.right - 5)); + surface->FillRect(Rect::Create(rect.top, rect.right - 1, rect.bottom, rect.right)); + + surface->SetForeColor(StdColors::White()); + surface->FillRect(Rect::Create(rect.top, rect.right - 5, rect.bottom, rect.right - 4)); + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kDarkGray, kDarkGray, kDarkGray, 255)); + surface->FillRect(Rect::Create(rect.top, rect.right - 2, rect.bottom, rect.right - 1)); + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kMidGray, kMidGray, kMidGray, 255)); + surface->FillRect(Rect::Create(rect.top, rect.right - 4, rect.bottom, rect.right - 2)); + } + + void GenericWindowChromeTheme::RenderChromeTopMini(WindowImpl *window, DrawSurface *surface) const + { + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kLightGray, kLightGray, kLightGray, 255)); + surface->FillRect(rect); + + surface->SetForeColor(StdColors::Black()); + surface->FillRect(Rect::Create(rect.top, rect.left, rect.top + 1, rect.right)); + surface->FillRect(Rect::Create(rect.top, rect.left, rect.bottom, 1)); + surface->FillRect(Rect::Create(rect.top, rect.right - 1, rect.bottom, rect.right)); + surface->FillRect(Rect::Create(rect.bottom - 1, rect.left + 1, rect.bottom, rect.right - 1)); + + surface->SetForeColor(PortabilityLayer::RGBAColor::Create(kDarkGray, kDarkGray, kDarkGray, 255)); + surface->FillRect(Rect::Create(rect.bottom - 2, rect.left + 2, rect.bottom - 1, rect.right - 2)); + surface->FillRect(Rect::Create(rect.top + 2, rect.right - 2, rect.bottom - 1, rect.right - 1)); + + surface->SetForeColor(StdColors::White()); + surface->FillRect(Rect::Create(rect.top + 1, rect.left + 1, rect.bottom - 2, rect.left + 2)); + surface->FillRect(Rect::Create(rect.top + 1, rect.left + 1, rect.top + 2, rect.right - 2)); + + surface->SetForeColor(StdColors::Black()); + surface->SetApplicationFont(10, PortabilityLayer::FontFamilyFlags::FontFamilyFlag_Bold); + int32_t ascender = surface->MeasureFontAscender(); + + const PLPasStr titlePStr = window->GetTitle().ToShortStr(); + size_t titleWidth = surface->MeasureString(titlePStr); + + int32_t titleH = (rect.left + rect.right - static_cast(titleWidth) + 1) / 2; + int32_t titleV = (rect.top + rect.bottom + ascender + 1) / 2; + + surface->DrawString(Point::Create(titleH, titleV), titlePStr, true); + } + + void GenericWindowChromeTheme::RenderChromeLeftMini(WindowImpl *window, DrawSurface *surface) const + { + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + surface->SetForeColor(StdColors::Black()); + surface->FillRect(rect); + } + + void GenericWindowChromeTheme::RenderChromeBottomMini(WindowImpl *window, DrawSurface *surface) const + { + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + surface->SetForeColor(StdColors::Black()); + surface->FillRect(rect); + } + + void GenericWindowChromeTheme::RenderChromeRightMini(WindowImpl *window, DrawSurface *surface) const + { + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + surface->SetForeColor(StdColors::Black()); + surface->FillRect(rect); + } + + //--------------------------------------------------------------------------- WindowImpl::WindowImpl() : m_windowAbove(nullptr) , m_windowBelow(nullptr) + , m_chromeTheme(nullptr) , m_visible(true) + , m_styleFlags(0) { } @@ -96,13 +418,37 @@ namespace PortabilityLayer if (!bounds.IsValid()) return false; - const Rect adjustedBounds = Rect::Create(0, 0, bounds.bottom - bounds.top, bounds.right - bounds.left); + m_styleFlags = windowDef.m_styleFlags; + + const Rect adjustedBounds = Rect::Create(0, 0, bounds.Height(), bounds.Width()); GpPixelFormat_t pixelFormat = PortabilityLayer::DisplayDeviceManager::GetInstance()->GetPixelFormat(); if (int errorCode = m_surface.Init(adjustedBounds, pixelFormat)) return false; + m_title.Set(windowDef.m_title[0], reinterpret_cast(windowDef.m_title + 1)); + + // Resolve chrome + if (!IsBorderless()) + { + m_chromeTheme = SimpleBoxChromeTheme::GetInstance(); + + if (m_styleFlags & WindowStyleFlags::kTitleBar) + m_chromeTheme = GenericWindowChromeTheme::GetInstance(); + + Rect chromeBounds[WindowChromeSides::kCount]; + GetChromeDimensions(bounds.Width(), bounds.Height(), chromeBounds); + + for (int chromeSide = 0; chromeSide < WindowChromeSides::kCount; chromeSide++) + { + if (int errorCode = m_chromeSurfaces[chromeSide].Init(chromeBounds[chromeSide], pixelFormat)) + return false; + + m_chromeTheme->RenderChrome(this, m_chromeSurfaces + chromeSide, static_cast(chromeSide)); + } + } + return true; } @@ -112,7 +458,26 @@ namespace PortabilityLayer rect.right = rect.left + width; rect.bottom = rect.top + height; - return m_surface.Resize(rect); + if (!m_surface.Resize(rect)) + return false; + + if (!IsBorderless()) + { + Rect chromeDimensions[WindowChromeSides::kCount]; + + GetChromeDimensions(width, height, chromeDimensions); + + bool resized = true; + for (int i = 0; i < WindowChromeSides::kCount; i++) + { + if (!m_chromeSurfaces[i].Resize(chromeDimensions[i])) + return false; + + m_chromeTheme->RenderChrome(this, m_chromeSurfaces + i, static_cast(i)); + } + } + + return true; } WindowImpl *WindowImpl::GetWindowAbove() const @@ -145,6 +510,40 @@ namespace PortabilityLayer m_visible = visible; } + void WindowImpl::GetChromePadding(uint16_t padding[WindowChromeSides::kCount]) const + { + return m_chromeTheme->GetChromePadding(this, padding); + } + + void WindowImpl::GetChromeDimensions(int width, int height, Rect dimensions[WindowChromeSides::kCount]) const + { + uint16_t padding[WindowChromeSides::kCount]; + GetChromePadding(padding); + + int32_t topAndBottomWidth = width + padding[WindowChromeSides::kLeft] + padding[WindowChromeSides::kRight]; + int32_t leftAndRightHeight = height; + + dimensions[WindowChromeSides::kTop] = Rect::Create(0, 0, padding[WindowChromeSides::kTop], topAndBottomWidth); + dimensions[WindowChromeSides::kBottom] = Rect::Create(0, 0, padding[WindowChromeSides::kBottom], topAndBottomWidth); + dimensions[WindowChromeSides::kLeft] = Rect::Create(0, 0, leftAndRightHeight, padding[WindowChromeSides::kLeft]); + dimensions[WindowChromeSides::kRight] = Rect::Create(0, 0, leftAndRightHeight, padding[WindowChromeSides::kRight]); + } + + bool WindowImpl::IsBorderless() const + { + return (m_styleFlags & WindowStyleFlags::kBorderless) != 0; + } + + uint16_t WindowImpl::GetStyleFlags() const + { + return m_styleFlags; + } + + const PascalStr<255> &WindowImpl::GetTitle() const + { + return m_title; + } + WindowManagerImpl::WindowManagerImpl() : m_windowStackTop(nullptr) , m_windowStackBottom(nullptr) @@ -352,9 +751,37 @@ namespace PortabilityLayer graf.PushToDDSurface(displayDriver); const PixMap *pixMap = *graf.m_port.GetPixMap(); - const size_t width = pixMap->m_rect.right - pixMap->m_rect.left; - const size_t height = pixMap->m_rect.bottom - pixMap->m_rect.top; + const uint16_t width = pixMap->m_rect.Width(); + const uint16_t height = pixMap->m_rect.Height(); displayDriver->DrawSurface(graf.m_ddSurface, window->m_wmX, window->m_wmY, width, height); + + + if (!window->IsBorderless()) + { + uint16_t chromePadding[WindowChromeSides::kCount]; + window->GetChromePadding(chromePadding); + + Vec2i chromeOrigins[WindowChromeSides::kCount]; + chromeOrigins[WindowChromeSides::kTop] = Vec2i(window->m_wmX - chromePadding[WindowChromeSides::kLeft], window->m_wmY - chromePadding[WindowChromeSides::kTop]); + chromeOrigins[WindowChromeSides::kLeft] = Vec2i(window->m_wmX - chromePadding[WindowChromeSides::kLeft], window->m_wmY); + chromeOrigins[WindowChromeSides::kRight] = Vec2i(window->m_wmX + width, window->m_wmY); + chromeOrigins[WindowChromeSides::kBottom] = Vec2i(window->m_wmX - chromePadding[WindowChromeSides::kLeft], window->m_wmY + height); + + Vec2i chromeDimensions[WindowChromeSides::kCount]; + chromeDimensions[WindowChromeSides::kTop] = Vec2i(chromePadding[WindowChromeSides::kLeft] + chromePadding[WindowChromeSides::kRight] + width, chromePadding[WindowChromeSides::kTop]); + chromeDimensions[WindowChromeSides::kLeft] = Vec2i(chromePadding[WindowChromeSides::kLeft], height); + chromeDimensions[WindowChromeSides::kRight] = Vec2i(chromePadding[WindowChromeSides::kRight], height); + chromeDimensions[WindowChromeSides::kBottom] = Vec2i(chromePadding[WindowChromeSides::kLeft] + chromePadding[WindowChromeSides::kRight] + width, chromePadding[WindowChromeSides::kBottom]); + + for (int i = 0; i < WindowChromeSides::kCount; i++) + { + DrawSurface *chromeSurface = window->GetChromeSurface(static_cast(i)); + + chromeSurface->PushToDDSurface(displayDriver); + + displayDriver->DrawSurface(chromeSurface->m_ddSurface, chromeOrigins[i].m_x, chromeOrigins[i].m_y, chromeDimensions[i].m_x, chromeDimensions[i].m_y); + } + } } WindowManagerImpl *WindowManagerImpl::GetInstance() diff --git a/PortabilityLayer/ZipFileProxy.cpp b/PortabilityLayer/ZipFileProxy.cpp index 4fefc21..6f5c4d4 100644 --- a/PortabilityLayer/ZipFileProxy.cpp +++ b/PortabilityLayer/ZipFileProxy.cpp @@ -7,14 +7,18 @@ #include "DeflateCodec.h" +#include + namespace { - static int ZipDirectorySearchPredicate(const char *path, PortabilityLayer::ZipCentralDirectoryFileHeader *item) + static const char *GetZipItemName(const PortabilityLayer::UnalignedPtr &itemPtr) { - const uint16_t fnameLength = item->m_fileNameLength; - const char *itemPath = reinterpret_cast(item) + sizeof(PortabilityLayer::ZipCentralDirectoryFileHeader); + return reinterpret_cast(itemPtr.GetRawPtr()) + sizeof(PortabilityLayer::ZipCentralDirectoryFileHeader); + } - for (size_t i = 0; i < fnameLength; i++) + static int ZipDirectorySearchPredicateResolved(const char *path, const char *itemPath, uint16_t itemPathLength) + { + for (size_t i = 0; i < itemPathLength; i++) { const uint8_t pathC = static_cast(path[i] & 0xff); @@ -29,12 +33,20 @@ namespace return 1; } - if (path[fnameLength] == 0) + if (path[itemPathLength] == 0) return 0; else return 1; } + static int ZipDirectorySearchPredicate(const char *path, const PortabilityLayer::UnalignedPtr &itemPtr) + { + const uint16_t fnameLength = itemPtr.Get().m_fileNameLength; + const char *itemPath = GetZipItemName(itemPtr); + + return ZipDirectorySearchPredicateResolved(path, itemPath, fnameLength); + } + static int ZipDirectorySortPredicate(const void *a, const void *b) { const PortabilityLayer::ZipCentralDirectoryFileHeader *typedA = *static_cast(a); @@ -93,7 +105,7 @@ namespace PortabilityLayer bool ZipFileProxy::IndexFile(const char *path, size_t &outIndex) const { - PortabilityLayer::ZipCentralDirectoryFileHeader **indexLoc = BinarySearch(m_sortedFiles, m_sortedFiles + m_numFiles, path, ZipDirectorySearchPredicate); + UnalignedPtr *indexLoc = BinarySearch(m_sortedFiles, m_sortedFiles + m_numFiles, path, ZipDirectorySearchPredicate); const size_t index = static_cast(indexLoc - m_sortedFiles); if (index == m_numFiles) @@ -105,11 +117,57 @@ namespace PortabilityLayer } } + + bool ZipFileProxy::HasPrefix(const char *prefix) const + { + size_t prefixLen = strlen(prefix); + + size_t firstFile = 0; + size_t lastFileExclusive = m_numFiles; + size_t midFile = (firstFile + lastFileExclusive) / 2; + + while (firstFile != lastFileExclusive) + { + const UnalignedPtr itemPtr = m_sortedFiles[midFile]; + const PortabilityLayer::ZipCentralDirectoryFileHeader item = itemPtr.Get(); + const uint16_t itemNameLength = item.m_fileNameLength; + const char *itemPath = GetZipItemName(itemPtr); + + const int delta = ZipDirectorySearchPredicateResolved(prefix, itemPath, itemNameLength); + + // -1 = path precedes item, 1 = path succeeds item + if (delta < 0) + { + lastFileExclusive = midFile; + midFile = (firstFile + lastFileExclusive) / 2; + } + else if (delta > 0) + { + const bool isPathPrefix = ((itemNameLength > prefixLen) && !memcmp(prefix, itemPath, prefixLen)); + if (isPathPrefix) + return true; + else + { + firstFile = midFile + 1; + midFile = (firstFile + lastFileExclusive) / 2; + } + } + else //if(delta == 0) + { + // Found the directory + firstFile = midFile + 1; + midFile = (firstFile + lastFileExclusive) / 2; + } + } + + return false; + } + bool ZipFileProxy::LoadFile(size_t index, void *outBuffer) { - ZipCentralDirectoryFileHeader *centralDirHeader = m_sortedFiles[index]; + ZipCentralDirectoryFileHeader centralDirHeader = m_sortedFiles[index].Get(); - if (!m_stream->SeekStart(centralDirHeader->m_localHeaderOffset)) + if (!m_stream->SeekStart(centralDirHeader.m_localHeaderOffset)) return false; ZipFileLocalHeader localHeader; @@ -119,15 +177,15 @@ namespace PortabilityLayer if (!m_stream->SeekCurrent(localHeader.m_fileNameLength + localHeader.m_extraFieldLength)) return false; - if (localHeader.m_compressedSize != centralDirHeader->m_compressedSize || localHeader.m_uncompressedSize != centralDirHeader->m_uncompressedSize || localHeader.m_method != centralDirHeader->m_method) + if (localHeader.m_compressedSize != centralDirHeader.m_compressedSize || localHeader.m_uncompressedSize != centralDirHeader.m_uncompressedSize || localHeader.m_method != centralDirHeader.m_method) return false; - const size_t uncompressedSize = centralDirHeader->m_uncompressedSize; + const size_t uncompressedSize = centralDirHeader.m_uncompressedSize; if (localHeader.m_method == PortabilityLayer::ZipConstants::kStoredMethod) return m_stream->Read(outBuffer, uncompressedSize) == uncompressedSize; else if (localHeader.m_method == PortabilityLayer::ZipConstants::kDeflatedMethod) { - const size_t compressedSize = centralDirHeader->m_compressedSize; + const size_t compressedSize = centralDirHeader.m_compressedSize; return DeflateCodec::DecompressStream(m_stream, compressedSize, outBuffer, uncompressedSize); } @@ -142,7 +200,7 @@ namespace PortabilityLayer size_t ZipFileProxy::GetFileSize(size_t index) const { - return m_sortedFiles[index]->m_uncompressedSize; + return m_sortedFiles[index].Get().m_uncompressedSize; } ZipFileProxy *ZipFileProxy::Create(IOStream *stream) @@ -164,7 +222,7 @@ namespace PortabilityLayer const size_t centralDirSize = eocd.m_centralDirectorySizeBytes; void *centralDirImage = nullptr; - ZipCentralDirectoryFileHeader **centralDirFiles = nullptr; + UnalignedPtr *centralDirFiles = nullptr; const size_t numFiles = eocd.m_numCentralDirRecords; @@ -174,7 +232,7 @@ namespace PortabilityLayer if (!centralDirImage) return nullptr; - centralDirFiles = static_cast(mm->Alloc(sizeof(ZipCentralDirectoryFileHeader*) * numFiles)); + centralDirFiles = static_cast*>(mm->Alloc(sizeof(UnalignedPtr) * numFiles)); if (!centralDirFiles) { mm->Release(centralDirImage); @@ -203,46 +261,48 @@ namespace PortabilityLayer break; } - ZipCentralDirectoryFileHeader *centralDirHeader = reinterpret_cast(centralDirCursor); + UnalignedPtr centralDirHeaderPtr = UnalignedPtr(reinterpret_cast(centralDirCursor)); + ZipCentralDirectoryFileHeader centralDirHeader = centralDirHeaderPtr.Get(); + centralDirCursor += sizeof(ZipCentralDirectoryFileHeader); - if (centralDirHeader->m_signature != ZipCentralDirectoryFileHeader::kSignature) + if (centralDirHeader.m_signature != ZipCentralDirectoryFileHeader::kSignature) { failed = true; break; } - if (centralDirEnd - centralDirCursor < centralDirHeader->m_fileNameLength) + if (centralDirEnd - centralDirCursor < centralDirHeader.m_fileNameLength) { failed = true; break; } - if (!CheckAndFixFileName(centralDirCursor, centralDirHeader->m_fileNameLength)) + if (!CheckAndFixFileName(centralDirCursor, centralDirHeader.m_fileNameLength)) { failed = true; break; } - centralDirCursor += centralDirHeader->m_fileNameLength; + centralDirCursor += centralDirHeader.m_fileNameLength; - if (centralDirEnd - centralDirCursor < centralDirHeader->m_extraFieldLength) + if (centralDirEnd - centralDirCursor < centralDirHeader.m_extraFieldLength) { failed = true; break; } - centralDirCursor += centralDirHeader->m_extraFieldLength; + centralDirCursor += centralDirHeader.m_extraFieldLength; - if (centralDirEnd - centralDirCursor < centralDirHeader->m_commentLength) + if (centralDirEnd - centralDirCursor < centralDirHeader.m_commentLength) { failed = true; break; } - centralDirCursor += centralDirHeader->m_commentLength; + centralDirCursor += centralDirHeader.m_commentLength; - centralDirFiles[i] = centralDirHeader; + centralDirFiles[i] = centralDirHeaderPtr; } if (failed) @@ -277,7 +337,7 @@ namespace PortabilityLayer return new (storage) ZipFileProxy(stream, centralDirImage, centralDirFiles, numFiles); } - ZipFileProxy::ZipFileProxy(IOStream *stream, void *centralDirImage, ZipCentralDirectoryFileHeader **sortedFiles, size_t numFiles) + ZipFileProxy::ZipFileProxy(IOStream *stream, void *centralDirImage, UnalignedPtr *sortedFiles, size_t numFiles) : m_stream(stream) , m_centralDirImage(centralDirImage) , m_sortedFiles(sortedFiles) diff --git a/PortabilityLayer/ZipFileProxy.h b/PortabilityLayer/ZipFileProxy.h index 704ccec..74e1535 100644 --- a/PortabilityLayer/ZipFileProxy.h +++ b/PortabilityLayer/ZipFileProxy.h @@ -1,5 +1,7 @@ #pragma once +#include "PLUnalignedPtr.h" + namespace PortabilityLayer { class IOStream; @@ -13,18 +15,20 @@ namespace PortabilityLayer bool IndexFile(const char *path, size_t &outIndex) const; bool LoadFile(size_t index, void *outBuffer); + bool HasPrefix(const char *path) const; + size_t NumFiles() const; size_t GetFileSize(size_t index) const; static ZipFileProxy *Create(IOStream *stream); private: - ZipFileProxy(IOStream *stream, void *centralDirImage, ZipCentralDirectoryFileHeader **sortedFiles, size_t numFiles); + ZipFileProxy(IOStream *stream, void *centralDirImage, UnalignedPtr *sortedFiles, size_t numFiles); ~ZipFileProxy(); IOStream *m_stream; void *m_centralDirImage; - ZipCentralDirectoryFileHeader **m_sortedFiles; + UnalignedPtr *m_sortedFiles; size_t m_numFiles; }; }