diff --git a/Aerofoil/Aerofoil.vcxproj b/Aerofoil/Aerofoil.vcxproj index 1aaa703..996d06e 100644 --- a/Aerofoil/Aerofoil.vcxproj +++ b/Aerofoil/Aerofoil.vcxproj @@ -73,6 +73,7 @@ + @@ -91,6 +92,7 @@ + diff --git a/Aerofoil/GpMain.cpp b/Aerofoil/GpMain.cpp index c15db20..60c1463 100644 --- a/Aerofoil/GpMain.cpp +++ b/Aerofoil/GpMain.cpp @@ -63,7 +63,11 @@ int GpMain::Run() // This appears to be the "standard" Mac sample rate, probably rounded from 244800/11. adProps.m_type = g_gpGlobalConfig.m_audioDriverType; adProps.m_sampleRate = (244800 * 2 + 11) / (11 * 2); +#ifdef NDEBUG adProps.m_debug = true; +#else + adProps.m_debug = false; +#endif IGpInputDriver **inputDrivers = static_cast(malloc(sizeof(IGpInputDriver*) * g_gpGlobalConfig.m_numInputDrivers)); diff --git a/GpApp/ColorUtils.cpp b/GpApp/ColorUtils.cpp index cb96f6d..75b46e1 100644 --- a/GpApp/ColorUtils.cpp +++ b/GpApp/ColorUtils.cpp @@ -59,18 +59,28 @@ void ColorOval (DrawSurface *surface, const Rect &theRect, long color) surface->SetForeColor(wasColor); } -//-------------------------------------------------------------- ColorRegion +void ColorOvalMaskPattern(DrawSurface *surface, const Rect &theRect, long color, bool isMask, const uint8_t *pattern) +{ + const PortabilityLayer::RGBAColor &rgbaColor = PortabilityLayer::StandardPalette::GetInstance()->GetColors()[color]; + + const PortabilityLayer::RGBAColor wasColor = surface->GetForeColor(); + surface->SetForeColor(rgbaColor); + surface->FillEllipseWithPattern(theRect, isMask, pattern); + surface->SetForeColor(wasColor); +} + +//-------------------------------------------------------------- ColorRegionMaskPattern // Given a region and color index, this function draws a solidÉ // region in that color. Current port, pen mode, etc. assumed. -void ColorRegion (DrawSurface *surface, PortabilityLayer::ScanlineMask *scanlineMask, long colorIndex) +void ColorRegionMaskPattern (DrawSurface *surface, PortabilityLayer::ScanlineMask *scanlineMask, long colorIndex, bool isMask, const uint8_t *pattern) { const PortabilityLayer::RGBAColor &rgbaColor = PortabilityLayer::StandardPalette::GetInstance()->GetColors()[colorIndex]; const PortabilityLayer::RGBAColor wasColor = surface->GetForeColor(); surface->SetForeColor(rgbaColor); - surface->FillScanlineMask(scanlineMask); + surface->FillScanlineMaskWithPattern(scanlineMask, isMask, pattern); surface->SetForeColor(wasColor); } diff --git a/GpApp/Coordinates.cpp b/GpApp/Coordinates.cpp index 5d05b97..112fec2 100644 --- a/GpApp/Coordinates.cpp +++ b/GpApp/Coordinates.cpp @@ -124,18 +124,19 @@ void OpenCoordWindow (void) Rect src, dest; Point globalMouse; short direction, dist; + + PortabilityLayer::WindowManager *wm = PortabilityLayer::WindowManager::GetInstance(); if (coordWindow == nil) { 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, 0L); - else - coordWindow = NewWindow(nil, &coordWindowRect, - PSTR("Tools"), false, windowStyle, kPutInFront, 0L); + + { + PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(coordWindowRect, windowStyle, true, 0, 0, PSTR("Tools")); + coordWindow = wm->CreateWindow(wdef); + } if (coordWindow == nil) RedAlert(kErrNoMemory); @@ -148,7 +149,7 @@ void OpenCoordWindow (void) MoveWindow(coordWindow, isCoordH, isCoordV, true); GetWindowRect(coordWindow, &dest); - BringToFront(coordWindow); + wm->PutWindowBehind(coordWindow, wm->GetPutInFrontSentinel()); PortabilityLayer::WindowManager::GetInstance()->ShowWindow(coordWindow); // FlagWindowFloating(coordWindow); TEMP - use flaoting windows HiliteAllWindows(); diff --git a/GpApp/DialogUtils.cpp b/GpApp/DialogUtils.cpp index 589cb5c..19ab1c6 100644 --- a/GpApp/DialogUtils.cpp +++ b/GpApp/DialogUtils.cpp @@ -374,8 +374,6 @@ void DrawDefaultButton (Dialog *theDialog) surface->FrameRoundRect(offsetRect, 8, 8); } } - - PenNormal(); } //-------------------------------------------------------------- GetDialogString @@ -602,7 +600,6 @@ void DrawDialogUserText (Dialog *dial, short item, StringPtr text, Boolean inver iRect.right -= inset; // Draw centered - PL_NotYetImplemented_TODO("Clip to iRect"); const int32_t ascender = surface->MeasureFontAscender(); @@ -709,7 +706,7 @@ void FrameOvalDialogItem (Dialog *theDialog, short item) // Given a dialog item, this function draws any combination of 4 sidesÉ // of a box around it. Which sides get drawn is encoded in "sides". -void BorderDialogItem (Dialog *theDialog, short item, short sides) +void BorderDialogItem(Dialog *theDialog, short item, short sides, short thickness, const uint8_t *pattern) { // 1 = left // 2 = top @@ -725,29 +722,65 @@ void BorderDialogItem (Dialog *theDialog, short item, short sides) if (sides >= 8) // 8 = right { const Point pointA = Point::Create(itemRect.right, itemRect.top); - const Point pointB = Point::Create(itemRect.right, itemRect.bottom); - surface->DrawLine(pointA, pointB); + const Point pointB = Point::Create(itemRect.right + thickness, itemRect.bottom + 1); + const Rect rect = Rect::Create(pointA.v, pointA.h, pointB.v, pointB.h); + if (pattern) + { + surface->SetForeColor(StdColors::White()); + surface->FillRect(rect); + surface->SetForeColor(StdColors::Black()); + surface->FillRectWithPattern8x8(rect, true, pattern); + } + else + surface->FillRect(rect); sides -= 8; } if (sides >= 4) // 4 = bottom { const Point pointA = Point::Create(itemRect.left, itemRect.bottom); - const Point pointB = Point::Create(itemRect.right, itemRect.bottom); - surface->DrawLine(pointA, pointB); + const Point pointB = Point::Create(itemRect.right + 1, itemRect.bottom + thickness); + const Rect rect = Rect::Create(pointA.v, pointA.h, pointB.v, pointB.h); + if (pattern) + { + surface->SetForeColor(StdColors::White()); + surface->FillRect(rect); + surface->SetForeColor(StdColors::Black()); + surface->FillRectWithPattern8x8(rect, true, pattern); + } + else + surface->FillRect(rect); sides -= 4; } if (sides >= 2) // 2 = top { const Point pointA = Point::Create(itemRect.left, itemRect.top - 1); - const Point pointB = Point::Create(itemRect.right, itemRect.top - 1); - surface->DrawLine(pointA, pointB); + const Point pointB = Point::Create(itemRect.right + 1, itemRect.top + thickness); + const Rect rect = Rect::Create(pointA.v, pointA.h, pointB.v, pointB.h); + if (pattern) + { + surface->SetForeColor(StdColors::White()); + surface->FillRect(rect); + surface->SetForeColor(StdColors::Black()); + surface->FillRectWithPattern8x8(rect, true, pattern); + } + else + surface->FillRect(rect); sides -= 2; } if (sides >= 1) // 1 = left { const Point pointA = Point::Create(itemRect.left - 1, itemRect.top); - const Point pointB = Point::Create(itemRect.left - 1, itemRect.bottom); - surface->DrawLine(pointA, pointB); + const Point pointB = Point::Create(itemRect.left - 1 + thickness, itemRect.bottom + 1); + const Rect rect = Rect::Create(pointA.v, pointA.h, pointB.v, pointB.h); + if (pattern) + { + surface->SetForeColor(StdColors::White()); + surface->FillRect(rect); + surface->SetForeColor(StdColors::Black()); + surface->FillRectWithPattern8x8(rect, true, pattern); + } + else + surface->FillRect(rect); } } diff --git a/GpApp/DialogUtils.h b/GpApp/DialogUtils.h index b5747cc..cde738a 100644 --- a/GpApp/DialogUtils.h +++ b/GpApp/DialogUtils.h @@ -43,6 +43,6 @@ void LoadDialogPICT (Dialog *, short, short); void FrameDialogItem (Dialog *, short); void FrameDialogItemC (Dialog *, short, long); void FrameOvalDialogItem (Dialog *, short); -void BorderDialogItem (Dialog *, short, short); +void BorderDialogItem (Dialog *theDialog, short item, short sides, short thickness, const uint8_t *pattern); void ShadowDialogItem (Dialog *, short, short); void EraseDialogItem (Dialog *, short); diff --git a/GpApp/Externs.h b/GpApp/Externs.h index 437b276..c61aca3 100644 --- a/GpApp/Externs.h +++ b/GpApp/Externs.h @@ -135,7 +135,8 @@ void BackSpinCursor (short); void ColorText (DrawSurface *surface, const Point &, StringPtr, long); // --- ColorUtils.c void ColorRect (DrawSurface *surface, const Rect &, long); void ColorOval (DrawSurface *surface, const Rect &, long); -void ColorRegion (DrawSurface *surface, PortabilityLayer::ScanlineMask *scanlineMask, long colorIndex); +void ColorOvalMaskPattern (DrawSurface *surface, const Rect &, long, bool, const uint8_t *); +void ColorRegionMaskPattern (DrawSurface *surface, PortabilityLayer::ScanlineMask *scanlineMask, long colorIndex, bool isMask, const uint8_t *pattern); void ColorLine (DrawSurface *surface, short, short, short, short, long); void HiliteRect (DrawSurface *surface, const Rect &rect, short, short); void ColorFrameRect (DrawSurface *surface, const Rect &theRect, long colorIndex); diff --git a/GpApp/House.cpp b/GpApp/House.cpp index 930dcb0..658a53b 100644 --- a/GpApp/House.cpp +++ b/GpApp/House.cpp @@ -17,6 +17,7 @@ #include "FileManager.h" #include "HostFileSystem.h" #include "House.h" +#include "PLTimeTaggedVOSEvent.h" #include "RectUtils.h" #include "ResourceManager.h" @@ -26,7 +27,7 @@ void UpdateGoToDialog (Dialog *); -Boolean GoToFilter (Dialog *, EventRecord *, short *); +int16_t GoToFilter (Dialog *dial, const TimeTaggedVOSEvent *evt); extern PortabilityLayer::ResourceArchive *houseResFork; @@ -594,7 +595,6 @@ void GenerateRetroLinks (void) void UpdateGoToDialog (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 10, kRedOrangeColor8); } @@ -602,37 +602,27 @@ void UpdateGoToDialog (Dialog *theDialog) //-------------------------------------------------------------- GoToFilter // Dialog filter for the "Go To Room..." dialog. -Boolean GoToFilter (Dialog *dial, EventRecord *event, short *item) +int16_t GoToFilter(Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + if (evt->IsKeyDownEvent()) { - case keyDown: - switch (event->message) + const GpKeyboardInputEvent &keyEvt = evt->m_vosEvent.m_event.m_keyboardInputEvent; + switch (PackVOSKeyCode(keyEvt)) { - 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; - - default: - return(false); - } - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateGoToDialog(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kOkayButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- DoGoToDialog @@ -664,10 +654,12 @@ Boolean GoToFilter (Dialog *dial, EventRecord *event, short *item) leaving = false; canceled = false; + + UpdateGoToDialog(theDialog); while (!leaving) { - ModalDialog(GoToFilter, &item); + item = theDialog->ExecuteModal(GoToFilter); if (item == kOkayButton) { diff --git a/GpApp/HouseInfo.cpp b/GpApp/HouseInfo.cpp index 7fdc53b..15b6ee5 100644 --- a/GpApp/HouseInfo.cpp +++ b/GpApp/HouseInfo.cpp @@ -14,6 +14,7 @@ #include "DialogUtils.h" #include "HostDisplayDriver.h" #include "IGpDisplayDriver.h" +#include "PLTimeTaggedVOSEvent.h" #define kHouseInfoDialogID 1001 @@ -31,7 +32,7 @@ long CountTotalHousePoints (void); void UpdateHouseInfoDialog (Dialog *); -Boolean HouseFilter (Dialog *, EventRecord *, short *); +int16_t HouseFilter(Dialog *dial, const TimeTaggedVOSEvent *evt); Boolean WarnLockingHouse (void); void HowToZeroScores (void); @@ -109,7 +110,6 @@ void UpdateHouseInfoDialog (Dialog *theDialog) { short nChars; - DrawDialog(theDialog); nChars = GetDialogStringLen(theDialog, kBannerTextItem); SetDialogNumToStr(theDialog, kBannerNCharsItem, (long)nChars); nChars = GetDialogStringLen(theDialog, kTrailerTextItem); @@ -121,7 +121,7 @@ void UpdateHouseInfoDialog (Dialog *theDialog) //-------------------------------------------------------------- HouseFilter -Boolean HouseFilter (Dialog *dial, EventRecord *event, short *item) +int16_t HouseFilter(Dialog *dial, const TimeTaggedVOSEvent *evt) { Point mouseIs; short nChars; @@ -134,70 +134,66 @@ Boolean HouseFilter (Dialog *dial, EventRecord *event, short *item) SetDialogNumToStr(dial, kTrailerNCharsItem, (long)nChars); keyHit = false; } - - switch (event->what) - { - case keyDown: - switch (event->message) - { - case PL_KEY_SPECIAL(kEnter): - case PL_KEY_NUMPAD_SPECIAL(kEnter): - FlashDialogButton(dial, kOkayButton); - *item = kOkayButton; - return(true); - break; - case PL_KEY_SPECIAL(kEscape): - FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - default: - keyHit = true; - return(false); - } - break; - - case mouseDown: - return(false); - break; - - case mouseUp: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateHouseInfoDialog(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - - default: - mouseIs = event->where; - mouseIs -= dial->GetWindow()->TopLeftCoord(); - if ((houseEditText1.Contains(mouseIs)) || - (houseEditText2.Contains(mouseIs))) + if (evt) + { + if (evt->m_vosEvent.m_eventType == GpVOSEventTypes::kKeyboardInput) { - if (houseCursorIs != kBeamCursor) + const GpKeyboardInputEvent &keyEvt = evt->m_vosEvent.m_event.m_keyboardInputEvent; + + if (keyEvt.m_eventType == GpKeyboardInputEventTypes::kDown) { - PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kIBeam); - houseCursorIs = kBeamCursor; + switch (PackVOSKeyCode(keyEvt)) + { + case PL_KEY_NUMPAD_SPECIAL(kEnter): + FlashDialogButton(dial, kOkayButton); + return kOkayButton; + + case PL_KEY_SPECIAL(kEscape): + FlashDialogButton(dial, kCancelButton); + return kCancelButton; + + default: + keyHit = true; + return -1; + } + } + else if (keyEvt.m_eventType == GpKeyboardInputEventTypes::kDownChar || keyEvt.m_eventType == GpKeyboardInputEventTypes::kAutoChar) + { + keyHit = true; + return -1; } } - else + else if (evt->m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) { - if (houseCursorIs != kArrowCursor) + const GpMouseInputEvent &mouseEvt = evt->m_vosEvent.m_event.m_mouseInputEvent; + + if (mouseEvt.m_eventType == GpMouseEventTypes::kMove) { - InitCursor(); - houseCursorIs = kArrowCursor; + mouseIs = Point::Create(mouseEvt.m_x, mouseEvt.m_y); + mouseIs -= dial->GetWindow()->TopLeftCoord(); + if ((houseEditText1.Contains(mouseIs)) || + (houseEditText2.Contains(mouseIs))) + { + if (houseCursorIs != kBeamCursor) + { + PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kIBeam); + houseCursorIs = kBeamCursor; + } + } + else + { + if (houseCursorIs != kArrowCursor) + { + InitCursor(); + houseCursorIs = kArrowCursor; + } + } } } - return(false); - break; } + + return -1; } //-------------------------------------------------------------- DoHouseInfo @@ -243,10 +239,12 @@ void DoHouseInfo (void) GetDialogItemRect(houseInfoDialog, kTrailerTextItem, &houseEditText2); houseCursorIs = kArrowCursor; leaving = false; + + UpdateHouseInfoDialog(houseInfoDialog); while (!leaving) { - ModalDialog(HouseFilter, &item); + item = houseInfoDialog->ExecuteModal(HouseFilter); if (item == kOkayButton) { diff --git a/GpApp/Link.cpp b/GpApp/Link.cpp index 1f81d6b..0df30f5 100644 --- a/GpApp/Link.cpp +++ b/GpApp/Link.cpp @@ -66,9 +66,9 @@ void UpdateLinkControl (void) switch (linkType) { - case kSwitchLinkOnly: + case kSwitchLinkOnly: if (objActive == kNoObjectSelected) - HiliteControl(linkControl, kControlInactive); + linkControl->SetEnabled(false);// HiliteControl(linkControl, kControlInactive); else switch (thisRoom->objects[objActive].what) { @@ -119,18 +119,18 @@ void UpdateLinkControl (void) case kBall: case kDrip: case kFish: - HiliteControl(linkControl, kControlActive); + linkControl->SetEnabled(true); break; default: - HiliteControl(linkControl, kControlInactive); + linkControl->SetEnabled(false); break; } break; case kTriggerLinkOnly: if (objActive == kNoObjectSelected) - HiliteControl(linkControl, kControlInactive); + linkControl->SetEnabled(false); else switch (thisRoom->objects[objActive].what) { @@ -147,7 +147,7 @@ void UpdateLinkControl (void) case kDartRt: case kDrip: case kFish: - HiliteControl(linkControl, kControlActive); + linkControl->SetEnabled(true); break; case kLightSwitch: @@ -157,18 +157,18 @@ void UpdateLinkControl (void) case kKnifeSwitch: case kInvisSwitch: if (linkRoom == thisRoomNumber) - HiliteControl(linkControl, kControlActive); + linkControl->SetEnabled(true); break; default: - HiliteControl(linkControl, kControlInactive); + linkControl->SetEnabled(false); break; } break; case kTransportLinkOnly: if (objActive == kNoObjectSelected) - HiliteControl(linkControl, kControlInactive); + linkControl->SetEnabled(false); else switch (thisRoom->objects[objActive].what) { @@ -185,11 +185,11 @@ void UpdateLinkControl (void) case kCalendar: case kBulletin: case kCloud: - HiliteControl(linkControl, kControlActive); + linkControl->SetEnabled(true); break; default: - HiliteControl(linkControl, kControlInactive); + linkControl->SetEnabled(false); break; } break; @@ -218,23 +218,25 @@ void OpenLinkWindow (void) #ifndef COMPILEDEMO Rect src, dest; Point globalMouse; + + PortabilityLayer::WindowManager *wm = PortabilityLayer::WindowManager::GetInstance(); if (linkWindow == nil) { 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, 0L); - else - linkWindow = NewWindow(nil, &linkWindowRect, - PSTR("Link"), false, windowStyle, kPutInFront, 0L); + + { + PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(linkWindowRect, windowStyle, true, 0, 0, PSTR("Link")); + linkWindow = wm->CreateWindow(wdef); + } + wm->PutWindowBehind(linkWindow, wm->GetPutInFrontSentinel()); + MoveWindow(linkWindow, isLinkH, isLinkV, true); GetWindowRect(linkWindow, &dest); - BringToFront(linkWindow); PortabilityLayer::WindowManager::GetInstance()->ShowWindow(linkWindow); // FlagWindowFloating(linkWindow); TEMP - use flaoting windows HiliteAllWindows(); @@ -250,6 +252,8 @@ void OpenLinkWindow (void) basicState.m_text.Set(6, "Unlink"); basicState.m_window = linkWindow; unlinkControl = PortabilityLayer::ButtonWidget::Create(basicState); + + linkWindow->DrawControls(); linkRoom = -1; linkObject = 255; @@ -265,7 +269,7 @@ void CloseLinkWindow (void) { #ifndef COMPILEDEMO if (linkWindow != nil) - DisposeWindow(linkWindow); + PortabilityLayer::WindowManager::GetInstance()->DestroyWindow(linkWindow); linkWindow = nil; isLinkOpen = false; @@ -380,7 +384,7 @@ void HandleLinkClick (Point wherePt) part = FindControl(wherePt, linkWindow, &theControl); if ((theControl != nil) && (part != 0)) { - part = TrackControl(theControl, wherePt, nil); + part = theControl->Capture(wherePt, nullptr); if (part != 0) { if (theControl == linkControl) diff --git a/GpApp/MainWindow.cpp b/GpApp/MainWindow.cpp index 6d139be..d2e2b30 100644 --- a/GpApp/MainWindow.cpp +++ b/GpApp/MainWindow.cpp @@ -368,7 +368,8 @@ void UpdateEditWindowTitle (void) } else PasStringConcat(newTitle, PSTR("House Locked")); - SetWTitle(mainWindow, newTitle); + + PortabilityLayer::WindowManager::GetInstance()->SetWindowTitle(mainWindow, newTitle); } #endif diff --git a/GpApp/Map.cpp b/GpApp/Map.cpp index fb002e7..4414331 100644 --- a/GpApp/Map.cpp +++ b/GpApp/Map.cpp @@ -254,7 +254,7 @@ void RedrawMapContents (void) surface->SetForeColor(StdColors::Blue()); Pattern dummyPat; - surface->FillRectWithPattern8x8(aRoom, *GetQDGlobalsGray(&dummyPat)); + surface->FillRectWithPattern8x8(aRoom, true, *GetQDGlobalsGray(&dummyPat)); } } } diff --git a/GpApp/Marquee.cpp b/GpApp/Marquee.cpp index 51fd7b5..9b16c16 100644 --- a/GpApp/Marquee.cpp +++ b/GpApp/Marquee.cpp @@ -339,7 +339,6 @@ void DragMarqueeHandle (Window *window, DrawSurface *surface, Point start, short } surface->InvertFrameRect(theMarquee.bounds, pattern); surface->InvertFillRect(theMarquee.handle, pattern); - PenNormal(); InitCursor(); } @@ -401,7 +400,6 @@ void DragMarqueeCorner (Window *window, DrawSurface *surface, Point start, short } surface->InvertFrameRect(theMarquee.bounds, pattern); surface->InvertFillRect(theMarquee.handle, pattern); - PenNormal(); InitCursor(); } diff --git a/GpApp/ObjectDraw.cpp b/GpApp/ObjectDraw.cpp index 5f43279..3946a6d 100644 --- a/GpApp/ObjectDraw.cpp +++ b/GpApp/ObjectDraw.cpp @@ -161,15 +161,12 @@ void DrawTable (Rect *tableTop, short down) -HalfRectTall(&tempRect) + kTableShadowTop + down); QOffsetRect(&tempRect, kTableShadowOffset, -kTableShadowOffset); - backSrcMap->SetPattern8x8(*GetQDGlobalsGray(&dummyPattern)); - backSrcMap->SetMaskMode(true); + GetQDGlobalsGray(&dummyPattern); if (thisMac.isDepth == 4) - ColorOval(backSrcMap, tempRect, 15); + ColorOvalMaskPattern(backSrcMap, tempRect, 15, true, dummyPattern); else - ColorOval(backSrcMap, tempRect, k8DkstGrayColor); - backSrcMap->ClearPattern(); - backSrcMap->SetMaskMode(false); + ColorOvalMaskPattern(backSrcMap, tempRect, k8DkstGrayColor, true, dummyPattern); InsetRect(tableTop, 0, 1); ColorRect(backSrcMap, *tableTop, brownC); @@ -280,14 +277,11 @@ void DrawShelf (Rect *shelfTop) if (mask) { - backSrcMap->SetPattern8x8(*GetQDGlobalsGray(&dummyPattern)); - backSrcMap->SetMaskMode(true); + GetQDGlobalsGray(&dummyPattern); if (thisMac.isDepth == 4) - ColorRegion(backSrcMap, mask, 15); + ColorRegionMaskPattern(backSrcMap, mask, 15, true, dummyPattern); else - ColorRegion(backSrcMap, mask, k8DkstGrayColor); - backSrcMap->ClearPattern(); - backSrcMap->SetMaskMode(false); + ColorRegionMaskPattern(backSrcMap, mask, k8DkstGrayColor, true, dummyPattern); mask->Destroy(); } @@ -371,14 +365,11 @@ void DrawCabinet (Rect *cabinet) if (mask) { - backSrcMap->SetPattern8x8(*GetQDGlobalsGray(&dummyPattern)); - backSrcMap->SetMaskMode(true); + GetQDGlobalsGray(&dummyPattern); if (thisMac.isDepth == 4) - ColorRegion(backSrcMap, mask, 15); + ColorRegionMaskPattern(backSrcMap, mask, 15, true, dummyPattern); else - ColorRegion(backSrcMap, mask, dkGrayC); - backSrcMap->ClearPattern(); - backSrcMap->SetMaskMode(false); + ColorRegionMaskPattern(backSrcMap, mask, dkGrayC, true, dummyPattern); mask->Destroy(); } @@ -511,14 +502,11 @@ void DrawCounter(Rect *counter) if (mask) { - backSrcMap->SetPattern8x8(*GetQDGlobalsGray(&dummyPattern)); - backSrcMap->SetMaskMode(true); + GetQDGlobalsGray(&dummyPattern); if (thisMac.isDepth == 4) - ColorRegion(backSrcMap, mask, 15); + ColorRegionMaskPattern(backSrcMap, mask, 15, true, dummyPattern); else - ColorRegion(backSrcMap, mask, dkGrayC); - backSrcMap->ClearPattern(); - backSrcMap->SetMaskMode(false); + ColorRegionMaskPattern(backSrcMap, mask, dkGrayC, true, dummyPattern); mask->Destroy(); } @@ -758,10 +746,8 @@ void DrawDeckTable (Rect *tableTop, short down) QOffsetRect(&tempRect, 0, -HalfRectTall(&tempRect) + kTableShadowTop + down); QOffsetRect(&tempRect, kTableShadowOffset, -kTableShadowOffset); - PenPat(GetQDGlobalsGray(&dummyPattern)); - PenMask(true); - ColorOval(backSrcMap, tempRect, dkGrayC); - PenNormal(); + GetQDGlobalsGray(&dummyPattern); + ColorOvalMaskPattern(backSrcMap, tempRect, dkGrayC, true, dummyPattern); InsetRect(tableTop, 0, 1); ColorRect(backSrcMap, *tableTop, kGoldColor); diff --git a/GpApp/ObjectEdit.cpp b/GpApp/ObjectEdit.cpp index 8db54ad..f320c4b 100644 --- a/GpApp/ObjectEdit.cpp +++ b/GpApp/ObjectEdit.cpp @@ -148,49 +148,51 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) { short hDelta, vDelta; Boolean whoCares; + + bool redrawMainWindow = false; switch (thisRoom->objects[objActive].what) { - case kFloorVent: - case kCeilingVent: - case kFloorBlower: - case kCeilingBlower: - case kSewerGrate: - case kTaper: - case kCandle: - case kStubby: - case kTiki: - case kBBQ: - case kGrecoVent: - case kSewerBlower: + case kFloorVent: + case kCeilingVent: + case kFloorBlower: + case kCeilingBlower: + case kSewerGrate: + case kTaper: + case kCandle: + case kStubby: + case kTiki: + case kBBQ: + case kGrecoVent: + case kSewerBlower: vDelta = thisRoom->objects[objActive].data.a.distance; DragMarqueeHandle(window, surface, where, &vDelta); thisRoom->objects[objActive].data.a.distance = vDelta; whoCares = KeepObjectLegal(); break; - case kLiftArea: + case kLiftArea: hDelta = thisRoom->objects[objActive].data.a.distance; vDelta = thisRoom->objects[objActive].data.a.tall * 2; DragMarqueeCorner(window, surface, where, &hDelta, &vDelta, false); thisRoom->objects[objActive].data.a.distance = hDelta; thisRoom->objects[objActive].data.a.tall = vDelta / 2; whoCares = KeepObjectLegal(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMainWindow = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); break; - case kLeftFan: - case kRightFan: + case kLeftFan: + case kRightFan: hDelta = thisRoom->objects[objActive].data.a.distance; DragMarqueeHandle(window, surface, where, &hDelta); thisRoom->objects[objActive].data.a.distance = hDelta; whoCares = KeepObjectLegal(); break; - case kInvisBlower: + case kInvisBlower: if (((thisRoom->objects[objActive].data.a.vector & 0x0F) == 1) || ((thisRoom->objects[objActive].data.a.vector & 0x0F) == 4)) { @@ -207,23 +209,23 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) whoCares = KeepObjectLegal(); break; - case kTable: - case kShelf: - case kDeckTable: + case kTable: + case kShelf: + case kDeckTable: hDelta = RectWide(&thisRoom->objects[objActive].data.b.bounds); DragMarqueeHandle(window, surface, where, &hDelta); thisRoom->objects[objActive].data.b.bounds.right = thisRoom->objects[objActive].data.b.bounds.left + hDelta; whoCares = KeepObjectLegal(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMainWindow = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); break; - case kCabinet: - case kInvisObstacle: - case kInvisBounce: + case kCabinet: + case kInvisObstacle: + case kInvisBounce: hDelta = RectWide(&thisRoom->objects[objActive].data.b.bounds); vDelta = RectTall(&thisRoom->objects[objActive].data.b.bounds); DragMarqueeCorner(window, surface, where, &hDelta, &vDelta, false); @@ -232,14 +234,14 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) thisRoom->objects[objActive].data.b.bounds.bottom = thisRoom->objects[objActive].data.b.bounds.top + vDelta; whoCares = KeepObjectLegal(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMainWindow = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); break; - case kCounter: - case kDresser: + case kCounter: + case kDresser: hDelta = RectWide(&thisRoom->objects[objActive].data.b.bounds); vDelta = RectTall(&thisRoom->objects[objActive].data.b.bounds); DragMarqueeCorner(window, surface, where, &hDelta, &vDelta, true); @@ -248,26 +250,26 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) thisRoom->objects[objActive].data.b.bounds.top = thisRoom->objects[objActive].data.b.bounds.bottom - vDelta; whoCares = KeepObjectLegal(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMainWindow = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); break; - case kGreaseRt: - case kGreaseLf: - case kSlider: + case kGreaseRt: + case kGreaseLf: + case kSlider: hDelta = thisRoom->objects[objActive].data.c.length; DragMarqueeHandle(window, surface, where, &hDelta); thisRoom->objects[objActive].data.c.length = hDelta; whoCares = KeepObjectLegal(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMainWindow = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); break; - case kInvisTrans: + case kInvisTrans: hDelta = thisRoom->objects[objActive].data.d.wide; vDelta = thisRoom->objects[objActive].data.d.tall; DragMarqueeCorner(window, surface, where, &hDelta, &vDelta, false); @@ -276,13 +278,13 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) thisRoom->objects[objActive].data.d.wide = (Byte)hDelta; thisRoom->objects[objActive].data.d.tall = vDelta; whoCares = KeepObjectLegal(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMainWindow = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); break; - case kDeluxeTrans: + case kDeluxeTrans: hDelta = ((thisRoom->objects[objActive].data.d.tall & 0xFF00) >> 8) * 4; vDelta = (thisRoom->objects[objActive].data.d.tall & 0x00FF) * 4; DragMarqueeCorner(window, surface, where, &hDelta, &vDelta, false); @@ -292,14 +294,14 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) vDelta = 32; thisRoom->objects[objActive].data.d.tall = ((hDelta / 4) << 8) + (vDelta / 4); whoCares = KeepObjectLegal(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMainWindow = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); break; - case kFlourescent: - case kTrackLight: + case kFlourescent: + case kTrackLight: hDelta = thisRoom->objects[objActive].data.f.length; DragMarqueeHandle(window, surface, where, &hDelta); thisRoom->objects[objActive].data.f.length = hDelta; @@ -310,16 +312,16 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) DrawThisRoomsObjects(); break; - case kToaster: + case kToaster: vDelta = thisRoom->objects[objActive].data.g.height; DragMarqueeHandle(window, surface, where, &vDelta); thisRoom->objects[objActive].data.g.height = vDelta; whoCares = KeepObjectLegal(); break; - case kBall: - case kDrip: - case kFish: + case kBall: + case kDrip: + case kFish: vDelta = thisRoom->objects[objActive].data.h.length; DragMarqueeHandle(window, surface, where, &vDelta); thisRoom->objects[objActive].data.h.length = vDelta; @@ -336,7 +338,7 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) thisRoom->objects[objActive].data.i.bounds.bottom = thisRoom->objects[objActive].data.i.bounds.top + vDelta; whoCares = KeepObjectLegal(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMainWindow = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -346,6 +348,9 @@ void DragHandle (Window *window, DrawSurface *surface, Point where) fileDirty = true; UpdateMenus(false); + + if (redrawMainWindow) + UpdateMainWindow(); } #endif @@ -2304,9 +2309,7 @@ void DrawThisRoomsObjects (void) { if (GetNumberOfLights(thisRoomNumber) <= 0) { - surface->SetMaskMode(true); - surface->FillRectWithPattern8x8(backSrcRect, *GetQDGlobalsGray(&dummyPattern)); - surface->SetMaskMode(false); + surface->FillRectWithPattern8x8(backSrcRect, true, *GetQDGlobalsGray(&dummyPattern)); } for (i = 0; i < kMaxRoomObs; i++) diff --git a/GpApp/ObjectInfo.cpp b/GpApp/ObjectInfo.cpp index 9d7f897..d27c572 100644 --- a/GpApp/ObjectInfo.cpp +++ b/GpApp/ObjectInfo.cpp @@ -81,18 +81,18 @@ void UpdateTransInfo (Dialog *); void UpdateEnemyInfo (Dialog *); void UpdateFlowerInfo (Dialog *); int16_t BlowerFilter (Dialog *, const TimeTaggedVOSEvent *evt); -Boolean FurnitureFilter (Dialog *, EventRecord *, short *); -Boolean CustPictFilter (Dialog *, EventRecord *, short *); -Boolean SwitchFilter (Dialog *, EventRecord *, short *); -Boolean TriggerFilter (Dialog *, EventRecord *, short *); -Boolean LightFilter (Dialog *, EventRecord *, short *); -Boolean ApplianceFilter (Dialog *, EventRecord *, short *); -Boolean MicrowaveFilter (Dialog *, EventRecord *, short *); -Boolean GreaseFilter (Dialog *, EventRecord *, short *); -Boolean InvisBonusFilter (Dialog *, EventRecord *, short *); -Boolean TransFilter (Dialog *, EventRecord *, short *); -Boolean EnemyFilter (Dialog *, EventRecord *, short *); -Boolean FlowerFilter (Dialog *, EventRecord *, short *); +int16_t FurnitureFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t CustPictFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t SwitchFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t TriggerFilter(Dialog *, const TimeTaggedVOSEvent *evt); +int16_t LightFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t ApplianceFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t MicrowaveFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t GreaseFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t InvisBonusFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t TransFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t EnemyFilter (Dialog *, const TimeTaggedVOSEvent *evt); +int16_t FlowerFilter (Dialog *, const TimeTaggedVOSEvent *evt); void DoBlowerObjectInfo (short); void DoFurnitureObjectInfo (void); void DoCustPictObjectInfo (void); @@ -242,7 +242,6 @@ void UpdateBlowerInfo (Dialog *theDialog) void UpdateFurnitureInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 4, kRedOrangeColor8); } @@ -251,7 +250,6 @@ void UpdateFurnitureInfo (Dialog *theDialog) void UpdateCustPictInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 5, kRedOrangeColor8); } @@ -260,7 +258,6 @@ void UpdateCustPictInfo (Dialog *theDialog) void UpdateSwitchInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); SelectFromRadioGroup(theDialog, newType + kToggleRadio, kToggleRadio, kForceOffRadio); @@ -272,7 +269,6 @@ void UpdateSwitchInfo (Dialog *theDialog) void UpdateTriggerInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 4, kRedOrangeColor8); FrameDialogItemC(theDialog, 13, kRedOrangeColor8); @@ -282,7 +278,6 @@ void UpdateTriggerInfo (Dialog *theDialog) void UpdateLightInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 5, kRedOrangeColor8); } @@ -291,7 +286,6 @@ void UpdateLightInfo (Dialog *theDialog) void UpdateApplianceInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 5, kRedOrangeColor8); } @@ -300,7 +294,6 @@ void UpdateApplianceInfo (Dialog *theDialog) void UpdateMicrowaveInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 5, kRedOrangeColor8); } @@ -309,7 +302,6 @@ void UpdateMicrowaveInfo (Dialog *theDialog) void UpdateGreaseInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 5, kRedOrangeColor8); } @@ -318,7 +310,6 @@ void UpdateGreaseInfo (Dialog *theDialog) void UpdateInvisBonusInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); SelectFromRadioGroup(theDialog, newPoint + k100PtRadio, k100PtRadio, k500PtRadio); @@ -329,7 +320,6 @@ void UpdateInvisBonusInfo (Dialog *theDialog) void UpdateTransInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 4, kRedOrangeColor8); FrameDialogItemC(theDialog, 10, kRedOrangeColor8); @@ -339,7 +329,6 @@ void UpdateTransInfo (Dialog *theDialog) void UpdateEnemyInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 4, kRedOrangeColor8); } @@ -348,7 +337,6 @@ void UpdateEnemyInfo (Dialog *theDialog) void UpdateFlowerInfo (Dialog *theDialog) { - DrawDialog(theDialog); DrawDefaultButton(theDialog); FrameDialogItemC(theDialog, 4, kRedOrangeColor8); } @@ -389,531 +377,340 @@ int16_t BlowerFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) //-------------------------------------------------------------- FurnitureFilter -Boolean FurnitureFilter (Dialog *dial, EventRecord *event, short *item) +int16_t FurnitureFilter(Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + if (evt->IsKeyDownEvent()) { - case keyDown: - switch (event->message) + const GpKeyboardInputEvent &keyEvt = evt->m_vosEvent.m_event.m_keyboardInputEvent; + + switch (PackVOSKeyCode(keyEvt)) { - 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; - - default: - return(false); - } - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateFurnitureInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kOkayButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- CustPictFilter -Boolean CustPictFilter (Dialog *dial, EventRecord *event, short *item) +int16_t CustPictFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + 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; - - default: - return(false); - } - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateCustPictInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kOkayButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- SwitchFilter -Boolean SwitchFilter (Dialog *dial, EventRecord *event, short *item) +int16_t SwitchFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + 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; - - case PL_KEY_SPECIAL(kEscape): + return kOkayButton; + + case PL_KEY_SPECIAL(kEscape): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - default: - return(false); - } - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateSwitchInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kCancelButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- TriggerFilter -Boolean TriggerFilter (Dialog *dial, EventRecord *event, short *item) +int16_t TriggerFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + 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; - - case PL_KEY_SPECIAL(kEscape): + return kOkayButton; + + case PL_KEY_SPECIAL(kEscape): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - case PL_KEY_SPECIAL(kTab): + return kCancelButton; + + case PL_KEY_SPECIAL(kTab): SelectDialogItemText(dial, kDelay3Item, 0, 1024); - return(true); - break; - - default: - return(false); - } - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateTriggerInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return 0; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- LightFilter -Boolean LightFilter (Dialog *dial, EventRecord *event, short *item) +int16_t LightFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) - { - case keyDown: - switch (event->message) - { - case PL_KEY_SPECIAL(kEnter): - case PL_KEY_NUMPAD_SPECIAL(kEnter): - FlashDialogButton(dial, kOkayButton); - *item = kOkayButton; - return(true); - break; + if (!evt) + return -1; - case PL_KEY_SPECIAL(kEscape): + if (evt->IsKeyDownEvent()) + { + switch (PackVOSKeyCode(evt->m_vosEvent.m_event.m_keyboardInputEvent)) + { + case PL_KEY_SPECIAL(kEnter): + case PL_KEY_NUMPAD_SPECIAL(kEnter): + FlashDialogButton(dial, kOkayButton); + return kOkayButton; + + case PL_KEY_SPECIAL(kEscape): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - default: - return(false); - } - break; - - case mouseDown: - return(false); - break; - - case mouseUp: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateLightInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kCancelButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- ApplianceFilter -Boolean ApplianceFilter (Dialog *dial, EventRecord *event, short *item) +int16_t ApplianceFilter(Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + 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, kDelayItem, 0, 1024); - return(true); - break; - - default: - return(false); - } - break; - - case mouseDown: - return(false); - break; - - case mouseUp: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateApplianceInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return 0; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- MicrowaveFilter -Boolean MicrowaveFilter (Dialog *dial, EventRecord *event, short *item) +int16_t MicrowaveFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) - { - case keyDown: - switch (event->message) - { - case PL_KEY_SPECIAL(kEnter): - case PL_KEY_NUMPAD_SPECIAL(kEnter): - FlashDialogButton(dial, kOkayButton); - *item = kOkayButton; - return(true); - break; + if (!evt) + return -1; - case PL_KEY_SPECIAL(kTab): + if (evt->IsKeyDownEvent()) + { + switch (PackVOSKeyCode(evt->m_vosEvent.m_event.m_keyboardInputEvent)) + { + case PL_KEY_SPECIAL(kEnter): + case PL_KEY_NUMPAD_SPECIAL(kEnter): + FlashDialogButton(dial, kOkayButton); + return kOkayButton; + + case PL_KEY_SPECIAL(kTab): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - default: - return(false); - } - break; - - case mouseDown: - return(false); - break; - - case mouseUp: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateMicrowaveInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kCancelButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- GreaseFilter -Boolean GreaseFilter (Dialog *dial, EventRecord *event, short *item) +int16_t GreaseFilter(Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) - { - case keyDown: - switch (event->message) - { - case PL_KEY_SPECIAL(kEnter): - case PL_KEY_NUMPAD_SPECIAL(kEnter): - FlashDialogButton(dial, kOkayButton); - *item = kOkayButton; - return(true); - break; + if (!evt) + return -1; - case PL_KEY_SPECIAL(kEscape): + if (evt->IsKeyDownEvent()) + { + switch (PackVOSKeyCode(evt->m_vosEvent.m_event.m_keyboardInputEvent)) + { + case PL_KEY_SPECIAL(kEnter): + case PL_KEY_NUMPAD_SPECIAL(kEnter): + FlashDialogButton(dial, kOkayButton); + return kOkayButton; + + case PL_KEY_SPECIAL(kEscape): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - default: - return(false); - } - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateGreaseInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kCancelButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- InvisBonusFilter -Boolean InvisBonusFilter (Dialog *dial, EventRecord *event, short *item) +int16_t InvisBonusFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + 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; - - default: - return(false); - } - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateInvisBonusInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kOkayButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- TransFilter -Boolean TransFilter (Dialog *dial, EventRecord *event, short *item) +int16_t TransFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) - { - case keyDown: - switch (event->message) - { - case PL_KEY_SPECIAL(kEnter): - case PL_KEY_NUMPAD_SPECIAL(kEnter): - FlashDialogButton(dial, kOkayButton); - *item = kOkayButton; - return(true); - break; + if (!evt) + return -1; - case PL_KEY_SPECIAL(kEscape): + if (evt->IsKeyDownEvent()) + { + switch (PackVOSKeyCode(evt->m_vosEvent.m_event.m_keyboardInputEvent)) + { + case PL_KEY_SPECIAL(kEnter): + case PL_KEY_NUMPAD_SPECIAL(kEnter): + FlashDialogButton(dial, kOkayButton); + return kOkayButton; + + case PL_KEY_SPECIAL(kEscape): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - default: - return(false); - } - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateTransInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kCancelButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- EnemyFilter -Boolean EnemyFilter (Dialog *dial, EventRecord *event, short *item) +int16_t EnemyFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + 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, kDelay2Item, 0, 1024); - return(true); - break; - - default: - return(false); - } - break; - - case mouseDown: - return(false); - break; - - case mouseUp: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateEnemyInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return 0; + default: - return(false); - break; + return -1; + } } + + return -1; } -//-------------------------------------------------------------- EnemyFilter +//-------------------------------------------------------------- FlowerFilter -Boolean FlowerFilter (Dialog *dial, EventRecord *event, short *item) +int16_t FlowerFilter (Dialog *dial, const TimeTaggedVOSEvent *evt) { - switch (event->what) + if (!evt) + return -1; + + 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; - - case PL_KEY_SPECIAL(kEscape): + return kOkayButton; + + case PL_KEY_SPECIAL(kEscape): FlashDialogButton(dial, kCancelButton); - *item = kCancelButton; - return(true); - break; - - default: - return(false); - } - break; - - case mouseDown: - return(false); - break; - - case mouseUp: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateFlowerInfo(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - + return kCancelButton; + default: - return(false); - break; + return -1; + } } + + return -1; } //-------------------------------------------------------------- DoBlowerObjectInfo @@ -983,6 +780,8 @@ void DoBlowerObjectInfo (short what) while (!leaving) { + bool redrawMain = false; + item = infoDial->ExecuteModal(BlowerFilter); if (item == kOkayButton) @@ -1032,7 +831,7 @@ void DoBlowerObjectInfo (short what) if (KeepObjectLegal()) { } - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -1077,6 +876,9 @@ void DoBlowerObjectInfo (short what) } UpdateBlowerInfo(infoDial); } + + if (redrawMain) + UpdateMainWindow(); } infoDial->Destroy(); @@ -1124,13 +926,15 @@ void DoFurnitureObjectInfo (void) if ((objActive < 0) || (retroLinkList[objActive].room == -1)) HideDialogItem(infoDial, 6); + + UpdateFurnitureInfo(infoDial); leaving = false; doReturn = false; while (!leaving) { - ModalDialog(FurnitureFilter, &item); + item = infoDial->ExecuteModal(FurnitureFilter); if (item == kOkayButton) leaving = true; @@ -1183,10 +987,14 @@ void DoCustPictObjectInfo (void) } SelectDialogItemText(infoDial, kCustPictIDItem, 0, 1024); leaving = false; - + + UpdateCustPictInfo(infoDial); + while (!leaving) { - ModalDialog(CustPictFilter, &item); + bool redrawMain = false; + + item = infoDial->ExecuteModal(CustPictFilter); if (item == kOkayButton) { @@ -1208,7 +1016,7 @@ void DoCustPictObjectInfo (void) } fileDirty = true; UpdateMenus(false); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -1229,7 +1037,7 @@ void DoCustPictObjectInfo (void) thisRoom->objects[objActive].data.e.where = (short)wasPict; fileDirty = true; UpdateMenus(false); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -1241,6 +1049,9 @@ void DoCustPictObjectInfo (void) { leaving = true; } + + if (redrawMain) + UpdateMainWindow(); } infoDial->Destroy(); @@ -1287,10 +1098,12 @@ void DoSwitchObjectInfo (void) if (retroLinkList[objActive].room == -1) HideDialogItem(infoDial, 15); + + UpdateSwitchInfo(infoDial); while (!leaving) { - ModalDialog(SwitchFilter, &item); + item = infoDial->ExecuteModal(SwitchFilter); if (item == kOkayButton) { @@ -1410,10 +1223,12 @@ void DoTriggerObjectInfo (void) SetDialogNumToStr(infoDial, kDelay3Item, (long)thisRoom->objects[objActive].data.e.delay); SelectDialogItemText(infoDial, kDelay3Item, 0, 1024); + + UpdateTriggerInfo(infoDial); while (!leaving) { - ModalDialog(TriggerFilter, &item); + item = infoDial->ExecuteModal(TriggerFilter); if (item == kOkayButton) { @@ -1548,10 +1363,13 @@ void DoLightObjectInfo (void) leaving = false; doReturn = false; + + UpdateLightInfo(infoDial); while (!leaving) { - ModalDialog(LightFilter, &item); + bool redrawMain = false; + item = infoDial->ExecuteModal(LightFilter); if (item == kOkayButton) { @@ -1563,7 +1381,7 @@ void DoLightObjectInfo (void) ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; fileDirty = true; UpdateMenus(false); leaving = true; @@ -1582,12 +1400,15 @@ void DoLightObjectInfo (void) ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; fileDirty = true; UpdateMenus(false); leaving = true; doReturn = true; } + + if (redrawMain) + UpdateMainWindow(); } infoDial->Destroy(); @@ -1636,10 +1457,13 @@ void DoApplianceObjectInfo (short what) leaving = false; doReturn = false; + + UpdateApplianceInfo(infoDial); while (!leaving) { - ModalDialog(ApplianceFilter, &item); + bool redrawMain = false; + item = infoDial->ExecuteModal(ApplianceFilter); if (item == kOkayButton) { @@ -1661,7 +1485,7 @@ void DoApplianceObjectInfo (short what) thisRoom->objects[objActive].data.g.initial = false; fileDirty = true; UpdateMenus(false); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -1692,7 +1516,7 @@ void DoApplianceObjectInfo (short what) thisRoom->objects[objActive].data.g.initial = false; fileDirty = true; UpdateMenus(false); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -1700,6 +1524,9 @@ void DoApplianceObjectInfo (short what) doReturn = true; } } + + if (redrawMain) + UpdateMainWindow(); } infoDial->Destroy(); @@ -1750,10 +1577,13 @@ void DoMicrowaveObjectInfo (void) leaving = false; doReturn = false; + + UpdateMicrowaveInfo(infoDial); while (!leaving) { - ModalDialog(MicrowaveFilter, &item); + bool redrawMain = false; + item = infoDial->ExecuteModal(MicrowaveFilter); if (item == kOkayButton) { @@ -1776,7 +1606,7 @@ void DoMicrowaveObjectInfo (void) fileDirty = true; UpdateMenus(false); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -1813,13 +1643,16 @@ void DoMicrowaveObjectInfo (void) fileDirty = true; UpdateMenus(false); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); leaving = true; doReturn = true; } + + if (redrawMain) + UpdateMainWindow(); } infoDial->Destroy(); @@ -1853,17 +1686,21 @@ void DoGreaseObjectInfo (void) SetDialogItemValue(infoDial, kGreaseItem, (short)wasSpilled); leaving = false; doReturn = false; + + UpdateGreaseInfo(infoDial); while (!leaving) { - ModalDialog(GreaseFilter, &item); + bool redrawMain = false; + + item = infoDial->ExecuteModal(GreaseFilter); if (item == kOkayButton) { thisRoom->objects[objActive].data.c.initial = !wasSpilled; fileDirty = true; UpdateMenus(false); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -1883,13 +1720,16 @@ void DoGreaseObjectInfo (void) thisRoom->objects[objActive].data.c.initial = !wasSpilled; fileDirty = true; UpdateMenus(false); - InvalWindowRect(mainWindow, &mainWindowRect); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); leaving = true; doReturn = true; } + + if (redrawMain) + UpdateMainWindow(); } infoDial->Destroy(); @@ -1936,10 +1776,12 @@ void DoInvisBonusObjectInfo (void) leaving = false; doReturn = false; + + UpdateInvisBonusInfo(infoDial); while (!leaving) { - ModalDialog(InvisBonusFilter, &item); + item = infoDial->ExecuteModal(InvisBonusFilter); if (item == kOkayButton) { @@ -2058,10 +1900,12 @@ void DoTransObjectInfo (short what) if (thisRoom->objects[objActive].data.d.who == 255) MyDisableControl(infoDial, kGotoButton1); + + UpdateTransInfo(infoDial); while (!leaving) { - ModalDialog(TransFilter, &item); + item = infoDial->ExecuteModal(TransFilter); if (item == kOkayButton) { @@ -2166,10 +2010,12 @@ void DoEnemyObjectInfo (short what) leaving = false; doReturn = false; + + UpdateEnemyInfo(infoDial); while (!leaving) { - ModalDialog(EnemyFilter, &item); + item = infoDial->ExecuteModal(EnemyFilter); if (item == kOkayButton) { @@ -2258,17 +2104,20 @@ void DoFlowerObjectInfo (void) leaving = false; doReturn = false; + + UpdateFlowerInfo(infoDial); while (!leaving) { - ModalDialog(FlowerFilter, &item); + bool redrawMain = false; + + item = infoDial->ExecuteModal(FlowerFilter); if (item == kOkayButton) { flower -= kRadioFlower1; if (flower != thisRoom->objects[objActive].data.i.pict) { - InvalWindowRect(mainWindow, &thisRoom->objects[objActive].data.i.bounds); thisRoom->objects[objActive].data.i.bounds.right = thisRoom->objects[objActive].data.i.bounds.left + RectWide(&flowerSrc[flower]); @@ -2276,7 +2125,7 @@ void DoFlowerObjectInfo (void) thisRoom->objects[objActive].data.i.bounds.bottom - RectTall(&flowerSrc[flower]); thisRoom->objects[objActive].data.i.pict = flower; - InvalWindowRect(mainWindow, &thisRoom->objects[objActive].data.i.bounds); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -2300,7 +2149,6 @@ void DoFlowerObjectInfo (void) flower -= kRadioFlower1; if (flower != thisRoom->objects[objActive].data.i.pict) { - InvalWindowRect(mainWindow, &thisRoom->objects[objActive].data.i.bounds); thisRoom->objects[objActive].data.i.bounds.right = thisRoom->objects[objActive].data.i.bounds.left + RectWide(&flowerSrc[flower]); @@ -2308,7 +2156,7 @@ void DoFlowerObjectInfo (void) thisRoom->objects[objActive].data.i.bounds.bottom - RectTall(&flowerSrc[flower]); thisRoom->objects[objActive].data.i.pict = flower; - InvalWindowRect(mainWindow, &thisRoom->objects[objActive].data.i.bounds); + redrawMain = true; GetThisRoomsObjRects(); ReadyBackground(thisRoom->background, thisRoom->tiles); DrawThisRoomsObjects(); @@ -2319,6 +2167,9 @@ void DoFlowerObjectInfo (void) leaving = true; doReturn = true; } + + if (redrawMain) + UpdateMainWindow(); } infoDial->Destroy(); diff --git a/GpApp/RoomInfo.cpp b/GpApp/RoomInfo.cpp index 3b00e3a..a7db647 100644 --- a/GpApp/RoomInfo.cpp +++ b/GpApp/RoomInfo.cpp @@ -17,6 +17,7 @@ #include "HostDisplayDriver.h" #include "IGpDisplayDriver.h" #include "RectUtils.h" +#include "PLPopupMenuWidget.h" #include "PLTimeTaggedVOSEvent.h" #include "QDPixMap.h" #include "ResourceCompiledRef.h" @@ -49,7 +50,7 @@ int16_t RoomFilter (Dialog *dialog, const TimeTaggedVOSEvent *evt); short ChooseOriginalArt (short); void UpdateOriginalArt (Dialog *); -Boolean OriginalArtFilter (Dialog *, EventRecord *, short *); +int16_t OriginalArtFilter (Dialog *dialog, const TimeTaggedVOSEvent *evt); Boolean PictIDExists (short); short GetFirstPICT (void); void BitchAboutPICTNotFound (void); @@ -66,6 +67,8 @@ Boolean originalFloor; extern IGpCursor *handCursor; extern short lastBackground; +extern PortabilityLayer::ResourceArchive *houseResFork; + //============================================================== Functions //-------------------------------------------------------------- UpdateRoomInfoDialog @@ -323,7 +326,6 @@ void HiliteTileOver (DrawSurface *surface, Point mouseIs) } surface->SetForeColor(StdColors::Black()); - PenNormal(); tileOver = -1; } @@ -417,56 +419,64 @@ int16_t RoomFilter(Dialog *dial, const TimeTaggedVOSEvent *evt) //-------------------------------------------------------------- DoRoomInfo -void DoRoomInfo (void) +void DoRoomInfo(void) { #ifndef COMPILEDEMO - #define kBackgroundsMenuID 140 +#define kBackgroundsMenuID 140 Dialog *roomInfoDialog; - MenuHandle backgroundsMenu; Str255 floorStr, suiteStr, objectsStr, tempStr; short item, i, newBack; char wasState; Boolean leaving, wasFirstRoom, forceDraw; PLError_t theErr; - + tileOver = -1; cursorIs = kArrowCursor; tempBack = thisRoom->background; - backgroundsMenu = GetMenu(kBackgroundsMenuID); -// SetMenuItemTextStyle(backgroundsMenu, kOriginalArtworkItem, italic); - if (HouseHasOriginalPicts()) - EnableMenuItem(backgroundsMenu, kOriginalArtworkItem); - + // SetMenuItemTextStyle(backgroundsMenu, kOriginalArtworkItem, italic); + NumToString(thisRoom->floor, floorStr); NumToString(thisRoom->suite, suiteStr); NumToString(thisRoom->numObjects, objectsStr); DialogTextSubstitutions substitutions(floorStr, suiteStr, objectsStr); - + theErr = CreateOffScreenGWorld(&tileSrcMap, &tileSrcRect, kPreferredPixelFormat); -// CreateOffScreenPixMap(&tileSrcRect, &tileSrcMap); -// SetPort((GrafPtr)tileSrcMap); + // CreateOffScreenPixMap(&tileSrcRect, &tileSrcMap); + // SetPort((GrafPtr)tileSrcMap); if ((tempBack > kStars) && (!PictIDExists(tempBack))) { BitchAboutPICTNotFound(); tempBack = kSimpleRoom; } - if ((tempBack == 2002) || (tempBack == 2011) || - (tempBack == 2016) || (tempBack == 2017)) + if ((tempBack == 2002) || (tempBack == 2011) || + (tempBack == 2016) || (tempBack == 2017)) LoadScaledGraphicCustom(tileSrcMap, tempBack - 800, &tileSrcRect); else LoadScaledGraphicCustom(tileSrcMap, tempBack, &tileSrcRect); - + for (i = 0; i < kNumTiles; i++) tempTiles[i] = thisRoom->tiles[i]; - -// CenterDialog(kRoomInfoDialogID); + + // CenterDialog(kRoomInfoDialogID); roomInfoDialog = PortabilityLayer::DialogManager::GetInstance()->LoadDialog(kRoomInfoDialogID, kPutInFront, &substitutions); if (roomInfoDialog == nil) RedAlert(kErrDialogDidntLoad); SetPort(&roomInfoDialog->GetWindow()->GetDrawSurface()->m_port); - - // Fix this later. TEMP -// AddMenuToPopUp(roomInfoDialog, kRoomPopupItem, backgroundsMenu); + + { + PortabilityLayer::WidgetBasicState state; + + GetDialogItemRect(roomInfoDialog, kRoomPopupItem, &state.m_rect); + state.m_resID = kBackgroundsMenuID; + state.m_enabled = true; + + PortabilityLayer::PopupMenuWidget *roomPopupWidget = PortabilityLayer::PopupMenuWidget::Create(state); + roomInfoDialog->ReplaceWidget(kRoomPopupItem - 1, roomPopupWidget); + + if (HouseHasOriginalPicts()) + EnableMenuItem(roomPopupWidget->GetMenu(), kOriginalArtworkItem); + } + if (tempBack >= kUserBackground) SetPopUpMenuValue(roomInfoDialog, kRoomPopupItem, kOriginalArtworkItem); else @@ -495,6 +505,8 @@ void DoRoomInfo (void) while (!leaving) { + bool needRedraw = false; + item = roomInfoDialog->ExecuteModal(RoomFilter); if (item == kOkayButton) @@ -543,8 +555,7 @@ void DoRoomInfo (void) { tempBack = newBack; LoadScaledGraphicCustom(tileSrcMap, tempBack, &tileSrcRect); - InvalWindowRect(roomInfoDialog->GetWindow(), &tileSrc); - InvalWindowRect(roomInfoDialog->GetWindow(), &tileDest); + needRedraw = true; } } else @@ -571,8 +582,7 @@ void DoRoomInfo (void) LoadScaledGraphicCustom(tileSrcMap, tempBack - 800, &tileSrcRect); else LoadScaledGraphicCustom(tileSrcMap, tempBack, &tileSrcRect); - InvalWindowRect(roomInfoDialog->GetWindow(), &tileSrc); - InvalWindowRect(roomInfoDialog->GetWindow(), &tileDest); + needRedraw = true; } } else if (item == kBoundsButton) @@ -582,10 +592,12 @@ void DoRoomInfo (void) { tempBack = newBack; LoadScaledGraphicCustom(tileSrcMap, tempBack, &tileSrcRect); - InvalWindowRect(roomInfoDialog->GetWindow(), &tileSrc); - InvalWindowRect(roomInfoDialog->GetWindow(), &tileDest); + needRedraw = true; } } + + if (needRedraw) + UpdateRoomInfoDialog(roomInfoDialog); } InitCursor(); @@ -602,133 +614,83 @@ void DoRoomInfo (void) #ifndef COMPILEDEMO void UpdateOriginalArt (Dialog *theDialog) { - Pattern dummyPattern; + Pattern grayPattern; + GetQDGlobalsGray(&grayPattern); - DrawDialog(theDialog); DrawDefaultButton(theDialog); - PenSize(2, 1); if (!originalLeftOpen) - BorderDialogItem(theDialog, 7, 8); + BorderDialogItem(theDialog, 7, 8, 2, nullptr); else - { - PenPat(GetQDGlobalsGray(&dummyPattern)); - BorderDialogItem(theDialog, 7, 8); - PenPat(GetQDGlobalsBlack(&dummyPattern)); - } + BorderDialogItem(theDialog, 7, 8, 2, grayPattern); - PenSize(1, 2); if (!originalTopOpen) - BorderDialogItem(theDialog, 8, 4); + BorderDialogItem(theDialog, 8, 4, 2, nullptr); else - { - PenPat(GetQDGlobalsGray(&dummyPattern)); - BorderDialogItem(theDialog, 8, 4); - PenPat(GetQDGlobalsBlack(&dummyPattern)); - } + BorderDialogItem(theDialog, 8, 4, 2, grayPattern); - PenSize(2, 1); if (!originalRightOpen) - BorderDialogItem(theDialog, 9, 1); + BorderDialogItem(theDialog, 9, 1, 2, nullptr); else - { - PenPat(GetQDGlobalsGray(&dummyPattern)); - BorderDialogItem(theDialog, 9, 1); - PenPat(GetQDGlobalsBlack(&dummyPattern)); - } + BorderDialogItem(theDialog, 9, 1, 2, grayPattern); - PenSize(1, 2); if (!originalBottomOpen) - BorderDialogItem(theDialog, 10, 2); + BorderDialogItem(theDialog, 10, 2, 2, nullptr); else - { - PenPat(GetQDGlobalsGray(&dummyPattern)); - BorderDialogItem(theDialog, 10, 2); - PenPat(GetQDGlobalsBlack(&dummyPattern)); - } - - PenSize(1, 1); + BorderDialogItem(theDialog, 10, 2, 2, grayPattern); } #endif //-------------------------------------------------------------- OriginalArtFilter #ifndef COMPILEDEMO -Boolean OriginalArtFilter (Dialog *dial, EventRecord *event, short *item) +int16_t OriginalArtFilter(Dialog *dial, const TimeTaggedVOSEvent *evt) { Point mouseIs; - - switch (event->what) + + if (!evt) + return -1; + + 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, kPICTIDItem, 0, 1024); - return(true); - break; - - default: - return(false); + return 0; + + default: + return -1; } - break; - - case mouseDown: - mouseIs = event->where; + } + else if (evt->IsLMouseDownEvent()) + { + const GpMouseInputEvent &mouseEvt = evt->m_vosEvent.m_event.m_mouseInputEvent; + + mouseIs = Point::Create(mouseEvt.m_x, mouseEvt.m_y); mouseIs -= dial->GetWindow()->TopLeftCoord(); if (leftBound.Contains(mouseIs)) - { - *item = 7; - return(true); - } + return 7; else if (topBound.Contains(mouseIs)) - { - *item = 8; - return(true); - } + return 8; else if (rightBound.Contains(mouseIs)) - { - *item = 9; - return(true); - } + return 9; else if (bottomBound.Contains(mouseIs)) - { - *item = 10; - return(true); - } + return 10; else - return(false); - break; - - case mouseUp: - return(false); - break; - - case updateEvt: - SetPortDialogPort(dial); - UpdateOriginalArt(dial); - EndUpdate(dial->GetWindow()); - event->what = nullEvent; - return(false); - break; - - default: - return(false); - break; + return -1; } + + return -1; } #endif @@ -775,10 +737,12 @@ short ChooseOriginalArt (short was) SetDialogItemValue(theDialog, kFloorSupportCheck, (short)originalFloor); leaving = false; + + UpdateOriginalArt(theDialog); while (!leaving) { - ModalDialog(OriginalArtFilter, &item); + item = theDialog->ExecuteModal(OriginalArtFilter); if (item == kOkayButton) { @@ -903,18 +867,11 @@ short GetFirstPICT (void) Handle resHandle; Str255 resName; - PL_NotYetImplemented(); + int16_t resID = 0; + if (!houseResFork->FindFirstResourceOfType('PICT', resID)) + return -1; - //resHandle = Get1IndResource('PICT', 1); - resHandle = Handle(); - if (resHandle != nil) - { - const PortabilityLayer::ResourceArchiveRef *resRef = PortabilityLayer::ResourceManager::GetInstance()->ResourceForHandle(resHandle.MMBlock()); - resHandle.Dispose(); - return resRef->m_resID; - } - else - return (-1); + return resID; } //-------------------------------------------------------------- BitchAboutPICTNotFound diff --git a/GpApp/Tools.cpp b/GpApp/Tools.cpp index 171bdb0..0329c25 100644 --- a/GpApp/Tools.cpp +++ b/GpApp/Tools.cpp @@ -134,7 +134,6 @@ void FrameSelectedTool (DrawSurface *surface) InsetRect(&theRect, 1, 1); surface->FrameRect(theRect); - PenNormal(); ForeColor(blackColor); } #endif @@ -484,6 +483,7 @@ void HandleToolsClick (Point wherePt) { EraseSelectedTool(); SwitchToolModes(newMode); + UpdateToolsWindow(); } } } diff --git a/PortabilityLayer/DialogManager.cpp b/PortabilityLayer/DialogManager.cpp index c0c6ca6..5470c68 100644 --- a/PortabilityLayer/DialogManager.cpp +++ b/PortabilityLayer/DialogManager.cpp @@ -91,6 +91,8 @@ namespace PortabilityLayer int16_t ExecuteModal(DialogFilterFunc_t filterFunc) override; + bool ReplaceWidget(unsigned int itemIndex, Widget *widget) override; + bool Populate(DialogTemplate *tmpl, const DialogTextSubstitutions *substitutions); void DrawControls(bool redraw); @@ -390,6 +392,19 @@ namespace PortabilityLayer } } + bool DialogImpl::ReplaceWidget(unsigned int itemIndex, Widget *widget) + { + DialogItem &item = m_items[itemIndex]; + Widget *oldWidget = item.GetWidget(); + + if (!m_window->ReplaceWidget(oldWidget, widget)) + return false; + + m_items[itemIndex].m_widget = widget; + + return true; + } + bool DialogImpl::Populate(DialogTemplate *tmpl, const DialogTextSubstitutions *substitutions) { Window *window = this->GetWindow(); diff --git a/PortabilityLayer/DialogManager.h b/PortabilityLayer/DialogManager.h index 667d32c..c6faab8 100644 --- a/PortabilityLayer/DialogManager.h +++ b/PortabilityLayer/DialogManager.h @@ -9,6 +9,7 @@ struct TimeTaggedVOSEvent; namespace PortabilityLayer { + class DialogImpl; class Widget; class DialogManager @@ -20,7 +21,7 @@ namespace PortabilityLayer static DialogManager *GetInstance(); }; - class DialogItem + class DialogItem final { public: explicit DialogItem(Widget *widget); @@ -29,6 +30,8 @@ namespace PortabilityLayer Widget *GetWidget() const; private: + friend class DialogImpl; + Widget *m_widget; }; } diff --git a/PortabilityLayer/MenuManager.cpp b/PortabilityLayer/MenuManager.cpp index 2af8d22..71e4c59 100644 --- a/PortabilityLayer/MenuManager.cpp +++ b/PortabilityLayer/MenuManager.cpp @@ -90,7 +90,11 @@ struct Menu bool haveMenuLayout; size_t layoutWidth; - size_t layoutHeight; + size_t layoutBaseHeight; + + size_t topItemsTruncated; + size_t bottomItemsTruncated; + size_t layoutFinalHeight; PortabilityLayer::MMHandleBlock *stringBlobHandle; @@ -143,6 +147,7 @@ namespace PortabilityLayer bool FindMenuShortcut(uint16_t &menuID, uint16_t &itemID, uint8_t shortcutChar) override; void MenuSelect(const Vec2i &initialPoint, int16_t *outMenu, uint16_t *outItem) override; + void PopupMenuSelect(const THandle &menu, const Vec2i &popupMenuPos, const Vec2i &initialPoint, size_t initialItem, uint16_t *outItem) override; void DrawMenuBar() override; void SetMenuVisible(bool isVisible) override; @@ -158,13 +163,17 @@ namespace PortabilityLayer MenuSelectionState(); ~MenuSelectionState(); - void HandleSelectionOfMenu(MenuManagerImpl *mm, Menu **menuHdl, bool &outNeedRedraw); + void HandleSelectionOfMenu(MenuManagerImpl *mm, Menu **menuHdl, bool isPopup, size_t initialItem, bool &outNeedRedraw); void Dismiss(); THandle GetSelectedMenu() const; DrawSurface *GetRenderedMenu() const; const unsigned int *GetSelectedItem() const; + bool IsPopup() const; + const Vec2i &GetPopupPosition() const; + void SetPopupPosition(const Vec2i &popupPosition); + void SelectItem(size_t item); void ClearSelection(); @@ -173,8 +182,10 @@ namespace PortabilityLayer THandle m_currentMenu; DrawSurface *m_menuGraf; + Vec2i m_popupPosition; unsigned int m_itemIndex; bool m_haveItem; + bool m_isPopup; }; void RefreshMenuBarLayout(); @@ -347,7 +358,10 @@ namespace PortabilityLayer menu->prevMenu = nullptr; menu->nextMenu = nullptr; menu->layoutWidth = 0; - menu->layoutHeight = 0; + menu->layoutBaseHeight = 0; + menu->layoutFinalHeight = 0; + menu->bottomItemsTruncated = 0; + menu->topItemsTruncated = 0; return THandle(menuData); } @@ -664,6 +678,56 @@ namespace PortabilityLayer this->DrawMenuBar(); } + void MenuManagerImpl::PopupMenuSelect(const THandle &menuHdl, const Vec2i &popupMenuPos, const Vec2i &initialPoint, size_t initialItem, uint16_t *outItem) + { + THandle menuHdlCopy = menuHdl; // Hack + + bool needRedraw = false; + m_menuSelectionState.SetPopupPosition(popupMenuPos); + m_menuSelectionState.HandleSelectionOfMenu(this, menuHdlCopy, true, initialItem, needRedraw); + + ProcessMouseMoveTo(initialPoint); + + TimeTaggedVOSEvent evt; + bool canDismiss = false; + while (!canDismiss) + { + if (WaitForEvent(&evt, 1)) + { + if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) + { + switch (evt.m_vosEvent.m_event.m_mouseInputEvent.m_eventType) + { + case GpMouseEventTypes::kMove: + ProcessMouseMoveTo(PortabilityLayer::Vec2i(evt.m_vosEvent.m_event.m_mouseInputEvent.m_x, evt.m_vosEvent.m_event.m_mouseInputEvent.m_y)); + break; + case GpMouseEventTypes::kDown: + if (evt.m_vosEvent.m_event.m_mouseInputEvent.m_button == GpMouseButtons::kLeft) + ProcessMouseMoveTo(PortabilityLayer::Vec2i(evt.m_vosEvent.m_event.m_mouseInputEvent.m_x, evt.m_vosEvent.m_event.m_mouseInputEvent.m_y)); + break; + case GpMouseEventTypes::kUp: + if (evt.m_vosEvent.m_event.m_mouseInputEvent.m_button == GpMouseButtons::kLeft) + canDismiss = true; + break; + } + } + } + } + + if (outItem) + *outItem = 0; + + Menu *menu = *menuHdl; + + if (const unsigned int *selectedItem = m_menuSelectionState.GetSelectedItem()) + { + if (outItem) + *outItem = (*selectedItem) + 1; + } + + m_menuSelectionState.Dismiss(); + } + void MenuManagerImpl::DrawMenuBar() { if (!m_haveIcon) @@ -893,9 +957,21 @@ namespace PortabilityLayer Menu *selectedMenu = *m_menuSelectionState.GetSelectedMenu(); const PixMap *pixMap = *renderedMenu->m_port.GetPixMap(); - const size_t xCoordinate = kMenuBarInitialPadding + selectedMenu->menuIndex * kMenuBarItemPadding * 2 + selectedMenu->cumulativeOffset - kMenuBarItemPadding; + int32_t xCoordinate = 0; + int32_t yCoordinate = 0; + if (!m_menuSelectionState.IsPopup()) + { + xCoordinate = kMenuBarInitialPadding + selectedMenu->menuIndex * kMenuBarItemPadding * 2 + selectedMenu->cumulativeOffset - kMenuBarItemPadding; + yCoordinate = kMenuBarHeight; + } + else + { + const Vec2i popupPosition = m_menuSelectionState.GetPopupPosition(); + xCoordinate = popupPosition.m_x; + yCoordinate = popupPosition.m_y; + } - displayDriver->DrawSurface(renderedMenu->m_ddSurface, xCoordinate, kMenuBarHeight, pixMap->m_rect.right, pixMap->m_rect.bottom); + displayDriver->DrawSurface(renderedMenu->m_ddSurface, xCoordinate, yCoordinate, pixMap->m_rect.right, pixMap->m_rect.bottom); } } @@ -987,7 +1063,8 @@ namespace PortabilityLayer menu->haveMenuLayout = true; menu->layoutWidth = width; - menu->layoutHeight = cumulativeHeight; + menu->layoutBaseHeight = cumulativeHeight; + menu->layoutFinalHeight = menu->layoutBaseHeight; } void MenuManagerImpl::ProcessMouseMoveTo(const Vec2i &point) @@ -995,7 +1072,7 @@ namespace PortabilityLayer if (point.m_y < 0) return; - if (point.m_y < static_cast(kMenuBarHeight)) + if (!m_menuSelectionState.IsPopup() && point.m_y < static_cast(kMenuBarHeight)) { m_menuSelectionState.ClearSelection(); ProcessMouseMoveToMenuBar(point); @@ -1034,7 +1111,7 @@ namespace PortabilityLayer if (selectedMenu) { bool needRedraw = false; - m_menuSelectionState.HandleSelectionOfMenu(this, menuHdl, needRedraw); + m_menuSelectionState.HandleSelectionOfMenu(this, menuHdl, false, 0, needRedraw); if (needRedraw) DrawMenuBar(); @@ -1048,11 +1125,24 @@ namespace PortabilityLayer if (selectedMenuHandle) { Menu *menu = *selectedMenuHandle; - const int32_t xCoordinate = static_cast(kMenuBarInitialPadding + menu->menuIndex * kMenuBarItemPadding * 2 + menu->cumulativeOffset - kMenuBarItemPadding); + int32_t xCoordinate = 0; + int32_t yCoordinate = 0; - const Vec2i localPoint = point - Vec2i(xCoordinate, kMenuBarHeight); + if (!m_menuSelectionState.IsPopup()) + { + xCoordinate = static_cast(kMenuBarInitialPadding + menu->menuIndex * kMenuBarItemPadding * 2 + menu->cumulativeOffset - kMenuBarItemPadding); + yCoordinate = kMenuBarHeight; + } + else + { + const Vec2i popupPos = m_menuSelectionState.GetPopupPosition(); + xCoordinate = popupPos.m_x; + yCoordinate = popupPos.m_y; + } - if (localPoint.m_x < 0 || localPoint.m_y < 0 || static_cast(localPoint.m_x) >= menu->layoutWidth || static_cast(localPoint.m_y) >= menu->layoutHeight) + const Vec2i localPoint = point - Vec2i(xCoordinate, yCoordinate); + + if (localPoint.m_x < 0 || localPoint.m_y < 0 || static_cast(localPoint.m_x) >= menu->layoutWidth || static_cast(localPoint.m_y) >= menu->layoutFinalHeight) { m_menuSelectionState.ClearSelection(); return; @@ -1098,6 +1188,7 @@ namespace PortabilityLayer MenuManagerImpl::MenuSelectionState::MenuSelectionState() : m_menuGraf(nullptr) , m_haveItem(false) + , m_isPopup(false) , m_itemIndex(0) { } @@ -1107,7 +1198,7 @@ namespace PortabilityLayer Dismiss(); } - void MenuManagerImpl::MenuSelectionState::HandleSelectionOfMenu(MenuManagerImpl *mm, Menu **menuHdl, bool &outNeedRedraw) + void MenuManagerImpl::MenuSelectionState::HandleSelectionOfMenu(MenuManagerImpl *mm, Menu **menuHdl, bool isPopup, size_t initialItem, bool &outNeedRedraw) { outNeedRedraw = false; @@ -1117,14 +1208,24 @@ namespace PortabilityLayer if (menuHdl != m_currentMenu) { Dismiss(); + m_currentMenu = menuHdl; + m_isPopup = isPopup; Menu *menu = *menuHdl; outNeedRedraw = true; + int32_t yCoordinate = isPopup ? m_popupPosition.m_y : kMenuBarHeight; + mm->RefreshMenuLayout(menu); + if (m_isPopup) + { + assert(initialItem < menu->numMenuItems); + m_popupPosition.m_y -= static_cast(menu->menuItems[initialItem].layoutYOffset); + } + RenderMenu(menu); } } @@ -1139,6 +1240,7 @@ namespace PortabilityLayer m_currentMenu = nullptr; m_haveItem = false; + m_isPopup = false; } THandle MenuManagerImpl::MenuSelectionState::GetSelectedMenu() const @@ -1159,6 +1261,21 @@ namespace PortabilityLayer return &m_itemIndex; } + bool MenuManagerImpl::MenuSelectionState::IsPopup() const + { + return m_isPopup; + } + + const Vec2i &MenuManagerImpl::MenuSelectionState::GetPopupPosition() const + { + return m_popupPosition; + } + + void MenuManagerImpl::MenuSelectionState::SetPopupPosition(const Vec2i &popupPosition) + { + m_popupPosition = popupPosition; + } + void MenuManagerImpl::MenuSelectionState::SelectItem(size_t item) { if (m_haveItem && m_itemIndex == item) @@ -1186,7 +1303,7 @@ namespace PortabilityLayer { PortabilityLayer::QDManager *qdManager = PortabilityLayer::QDManager::GetInstance(); - const Rect menuRect = Rect::Create(0, 0, static_cast(menu->layoutHeight), static_cast(menu->layoutWidth)); + const Rect menuRect = Rect::Create(0, 0, static_cast(menu->layoutFinalHeight), static_cast(menu->layoutWidth)); if (m_menuGraf == nullptr) { @@ -1208,16 +1325,16 @@ namespace PortabilityLayer qdState->SetForeColor(gs_barMidColor); { - const Rect rect = Rect::Create(0, 0, menu->layoutHeight, menu->layoutWidth); + const Rect rect = Rect::Create(0, 0, menu->layoutFinalHeight, menu->layoutWidth); surface->FillRect(rect); surface->SetForeColor(StdColors::White()); surface->FillRect(Rect::Create(0, 0, 1, menu->layoutWidth - 1)); - surface->FillRect(Rect::Create(1, 0, menu->layoutHeight - 1, 1)); + surface->FillRect(Rect::Create(1, 0, menu->layoutFinalHeight - 1, 1)); surface->SetForeColor(RGBAColor::Create(kDarkGray, kDarkGray, kDarkGray, 255)); - surface->FillRect(Rect::Create(1, menu->layoutWidth - 1, menu->layoutHeight, menu->layoutWidth)); - surface->FillRect(Rect::Create(menu->layoutHeight - 1, 1, menu->layoutHeight, menu->layoutWidth - 1)); + surface->FillRect(Rect::Create(1, menu->layoutWidth - 1, menu->layoutFinalHeight, menu->layoutWidth)); + surface->FillRect(Rect::Create(menu->layoutFinalHeight - 1, 1, menu->layoutFinalHeight, menu->layoutWidth - 1)); } m_menuGraf->SetSystemFont(kMenuFontSize, PortabilityLayer::FontFamilyFlag_Bold); diff --git a/PortabilityLayer/MenuManager.h b/PortabilityLayer/MenuManager.h index 16d6d54..365f3e0 100644 --- a/PortabilityLayer/MenuManager.h +++ b/PortabilityLayer/MenuManager.h @@ -43,6 +43,7 @@ namespace PortabilityLayer virtual bool FindMenuShortcut(uint16_t &menuID, uint16_t &itemID, uint8_t shortcutChar) = 0; virtual void MenuSelect(const Vec2i &initialPoint, int16_t *outMenu, uint16_t *outItem) = 0; + virtual void PopupMenuSelect(const THandle &menu, const Vec2i &popupMenuPos, const Vec2i &initialPoint, size_t initialItem, uint16_t *outItem) = 0; virtual void DrawMenuBar() = 0; virtual void SetMenuVisible(bool isVisible) = 0; diff --git a/PortabilityLayer/PLButtonWidget.cpp b/PortabilityLayer/PLButtonWidget.cpp index d10c18e..111ac5c 100644 --- a/PortabilityLayer/PLButtonWidget.cpp +++ b/PortabilityLayer/PLButtonWidget.cpp @@ -52,6 +52,31 @@ namespace PortabilityLayer return WidgetHandleStates::kIgnored; } + void ButtonWidget::OnEnabledChanged() + { + DrawControl(m_window->GetDrawSurface()); + } + + int16_t ButtonWidget::Capture(const Point &pos, WidgetUpdateCallback_t callback) + { + for (;;) + { + TimeTaggedVOSEvent evt; + if (WaitForEvent(&evt, 1)) + { + if (evt.IsLMouseUpEvent()) + { + const Point pt = m_window->MouseToLocal(evt.m_vosEvent.m_event.m_mouseInputEvent); + + if (m_rect.Contains(pt)) + return RegionIDs::kContent; + else + return RegionIDs::kNone; + } + } + } + } + bool ButtonWidget::Init(const WidgetBasicState &state) { (void)state; @@ -60,7 +85,14 @@ namespace PortabilityLayer void ButtonWidget::DrawControl(DrawSurface *surface) { - surface->SetForeColor(StdColors::Black()); + surface->SetForeColor(StdColors::White()); + surface->FillRect(this->m_rect.Inset(1, 1)); + + if (m_enabled) + surface->SetForeColor(StdColors::Black()); + else + surface->SetForeColor(RGBAColor::Create(136, 136, 136, 255)); + surface->FrameRect(this->m_rect); surface->SetSystemFont(12, PortabilityLayer::FontFamilyFlag_Bold); int32_t x = (m_rect.left + m_rect.right - static_cast(surface->MeasureString(m_text.ToShortStr()))) / 2; diff --git a/PortabilityLayer/PLButtonWidget.h b/PortabilityLayer/PLButtonWidget.h index cb7d65a..e585aca 100644 --- a/PortabilityLayer/PLButtonWidget.h +++ b/PortabilityLayer/PLButtonWidget.h @@ -16,6 +16,10 @@ namespace PortabilityLayer WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt) override; + void OnEnabledChanged() override; + + int16_t Capture(const Point &pos, WidgetUpdateCallback_t callback) override; + private: bool m_haveMouseDown; PascalStr<255> m_text; diff --git a/PortabilityLayer/PLCore.cpp b/PortabilityLayer/PLCore.cpp index 8ac508a..69ad2f6 100644 --- a/PortabilityLayer/PLCore.cpp +++ b/PortabilityLayer/PLCore.cpp @@ -136,11 +136,6 @@ void HiliteWindow(WindowPtr window, bool highlighted) PL_NotYetImplemented(); } -void DisposeWindow(WindowPtr window) -{ - PL_NotYetImplemented(); -} - void GetWindowBounds(WindowPtr window, WindowRegionType windowRegion, Rect *rect) { if (windowRegion == kWindowContentRgn) @@ -204,11 +199,6 @@ void ShowWindow(WindowPtr window) PortabilityLayer::WindowManager::GetInstance()->ShowWindow(window); } -void SetWTitle(WindowPtr window, const PLPasStr &title) -{ - PL_NotYetImplemented_TODO("Editor"); -} - long MenuSelect(Point point) { int16_t menuID = 0; @@ -760,6 +750,29 @@ PortabilityLayer::Widget* Window::GetWidgetById() const return nullptr; } +bool Window::ReplaceWidget(PortabilityLayer::Widget *oldWidget, PortabilityLayer::Widget *newWidget) +{ + for (size_t i = 0; i < m_numWidgets; i++) + { + if (m_widgets[i] == oldWidget) + { + assert(newWidget->GetWindow() == nullptr); + + oldWidget->Destroy(); + m_widgets[i] = newWidget; + newWidget->m_window = this; + + newWidget->DrawControl(&m_surface); + m_surface.m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); + + return true; + } + } + + return false; +} + + void Window::FocusWidget(PortabilityLayer::Widget *widget) { if (m_widgetWithFocus != widget) diff --git a/PortabilityLayer/PLCore.h b/PortabilityLayer/PLCore.h index c71cd1a..86cfecc 100644 --- a/PortabilityLayer/PLCore.h +++ b/PortabilityLayer/PLCore.h @@ -100,7 +100,8 @@ struct Window bool AddWidget(PortabilityLayer::Widget *widget); ArrayView GetWidgets() const; - PortabilityLayer::Widget* GetWidgetById() const; + PortabilityLayer::Widget *GetWidgetById() const; + bool ReplaceWidget(PortabilityLayer::Widget *oldWidget, PortabilityLayer::Widget *newWidget); void FocusWidget(PortabilityLayer::Widget *widget); PortabilityLayer::Widget *GetWidgetWithFocus() const; @@ -257,7 +258,6 @@ bool TrackGoAway(WindowPtr window, Point point); // Returns true if the close bo Int32 GrowWindow(WindowPtr window, Point start, Rect *size); bool TrackBox(WindowPtr window, Point point, int part); // Returns true if grow/shrink box was clicked (part corresponds to type) void HiliteWindow(WindowPtr window, bool highlighted); -void DisposeWindow(WindowPtr window); void GetWindowBounds(WindowPtr window, WindowRegionType windowRegion, Rect *rect); WindowPtr GetNewCWindow(int resID, void *storage, WindowPtr behind); @@ -266,7 +266,6 @@ WindowPtr NewWindow(void *storage, const Rect *bounds, const PLPasStr &title, Bo void SizeWindow(WindowPtr window, int width, int height, Boolean addToUpdateRegion); void MoveWindow(WindowPtr window, int x, int y, Boolean moveToFront); void ShowWindow(WindowPtr window); -void SetWTitle(WindowPtr window, const PLPasStr &title); long MenuSelect(Point point); // Breaks into menu select routine (in practice we'll just forward one from the queue?) diff --git a/PortabilityLayer/PLDialogs.cpp b/PortabilityLayer/PLDialogs.cpp index 70f1080..59664b9 100644 --- a/PortabilityLayer/PLDialogs.cpp +++ b/PortabilityLayer/PLDialogs.cpp @@ -4,6 +4,7 @@ #include "PLArrayView.h" #include "PLPasStr.h" #include "PLEditboxWidget.h" +#include "PLStandardColors.h" DialogTextSubstitutions::DialogTextSubstitutions() @@ -109,5 +110,14 @@ void ShowDialogItem(Dialog *dialog, int item) void HideDialogItem(Dialog *dialog, int item) { - dialog->GetItems()[item - 1].GetWidget()->SetVisible(false); + PortabilityLayer::Widget *widget = dialog->GetItems()[item - 1].GetWidget(); + + if (widget->IsVisible()) + { + widget->SetVisible(false); + + DrawSurface *surface = dialog->GetWindow()->GetDrawSurface(); + surface->SetForeColor(StdColors::White()); + surface->FillRect(widget->GetExpandedRect()); + } } diff --git a/PortabilityLayer/PLDialogs.h b/PortabilityLayer/PLDialogs.h index 53d1efe..bbebe91 100644 --- a/PortabilityLayer/PLDialogs.h +++ b/PortabilityLayer/PLDialogs.h @@ -40,6 +40,8 @@ struct Dialog virtual void SetItemVisibility(unsigned int itemIndex, bool isVisible) = 0; virtual int16_t ExecuteModal(DialogFilterFunc_t filterFunc) = 0; + + virtual bool ReplaceWidget(unsigned int itemIndex, PortabilityLayer::Widget *widget) = 0; }; typedef Boolean(*ModalFilterUPP)(Dialog *dial, EventRecord *event, short *item); diff --git a/PortabilityLayer/PLEditboxWidget.cpp b/PortabilityLayer/PLEditboxWidget.cpp index 90b5e88..844e574 100644 --- a/PortabilityLayer/PLEditboxWidget.cpp +++ b/PortabilityLayer/PLEditboxWidget.cpp @@ -46,6 +46,9 @@ namespace PortabilityLayer void EditboxWidget::EditboxWidget::DrawControl(DrawSurface *surface) { + if (!m_visible) + return; + const Rect textRect = m_rect; const Rect innerRect = textRect.Inset(-2, -2); const Rect outerRect = innerRect.Inset(-1, -1); @@ -224,6 +227,11 @@ namespace PortabilityLayer return WidgetHandleStates::kIgnored; } + Rect EditboxWidget::GetExpandedRect() const + { + return GetRect().Inset(-3, -3); + } + void EditboxWidget::Redraw() { if (m_window) diff --git a/PortabilityLayer/PLEditboxWidget.h b/PortabilityLayer/PLEditboxWidget.h index 3a2cb3c..4abd857 100644 --- a/PortabilityLayer/PLEditboxWidget.h +++ b/PortabilityLayer/PLEditboxWidget.h @@ -22,6 +22,8 @@ namespace PortabilityLayer WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt) override; + Rect GetExpandedRect() const override; + bool HandlesTickEvents() const; void SetSelection(size_t startChar, size_t endChar); diff --git a/PortabilityLayer/PLPopupMenuWidget.cpp b/PortabilityLayer/PLPopupMenuWidget.cpp index 581e47c..78032b9 100644 --- a/PortabilityLayer/PLPopupMenuWidget.cpp +++ b/PortabilityLayer/PLPopupMenuWidget.cpp @@ -4,7 +4,9 @@ #include "PLMenus.h" #include "PLPasStr.h" #include "PLStandardColors.h" +#include "PLTimeTaggedVOSEvent.h" #include "FontFamily.h" +#include "Vec2i.h" namespace PortabilityLayer { @@ -13,17 +15,59 @@ namespace PortabilityLayer { } + PopupMenuWidget::~PopupMenuWidget() + { + if (m_menu) + m_menu.Dispose(); + } + bool PopupMenuWidget::Init(const WidgetBasicState &state) { - m_menu = GetMenu(state.m_resID); + 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); + WidgetHandleState_t PopupMenuWidget::ProcessEvent(const TimeTaggedVOSEvent &evt) + { + if (evt.IsLMouseDownEvent()) + { + const GpMouseInputEvent &mouseEvent = evt.m_vosEvent.m_event.m_mouseInputEvent; + const Vec2i globalPoint = Vec2i(mouseEvent.m_x, mouseEvent.m_y); + const Vec2i localPoint = globalPoint - Vec2i(m_window->m_wmX, m_window->m_wmY); + + if (this->m_rect.Contains(Point::Create(localPoint.m_x, localPoint.m_y))) + { + int16_t part = Capture(Point::Create(localPoint.m_x, localPoint.m_y), nullptr); + if (part >= 1) + return WidgetHandleStates::kActivated; + else + return WidgetHandleStates::kIgnored; + } + } + + return WidgetHandleStates::kIgnored; + } + + int16_t PopupMenuWidget::Capture(const Point &pos, WidgetUpdateCallback_t callback) + { + MenuManager *mm = PortabilityLayer::MenuManager::GetInstance(); + + const Vec2i popupMenuPos = Vec2i(m_window->m_wmX, m_window->m_wmY) + Vec2i(m_rect.left, m_rect.top); + const Vec2i globalPos = Vec2i(pos.h, pos.v) + Vec2i(m_window->m_wmX, m_window->m_wmY); + + uint16_t item = 0; + mm->PopupMenuSelect(m_menu, popupMenuPos, globalPos, m_state - 1, &item); + + if (item < 1) + return -1; + + this->SetState(item); + return item; + } + void PopupMenuWidget::DrawControl(DrawSurface *surface) { const Rect rect = m_rect; @@ -59,9 +103,22 @@ namespace PortabilityLayer } } + void PopupMenuWidget::OnStateChanged() + { + DrawControl(m_window->GetDrawSurface()); + } + PLPasStr PopupMenuWidget::GetString() const { + if (m_state < 1) + return PSTR(""); + const Menu *menu = (*m_menu); return PortabilityLayer::MenuManager::GetInstance()->GetItemText(m_menu, m_state - 1); } + + const THandle &PopupMenuWidget::GetMenu() const + { + return m_menu; + } } diff --git a/PortabilityLayer/PLPopupMenuWidget.h b/PortabilityLayer/PLPopupMenuWidget.h index 1f22462..3ad2bcc 100644 --- a/PortabilityLayer/PLPopupMenuWidget.h +++ b/PortabilityLayer/PLPopupMenuWidget.h @@ -14,12 +14,19 @@ namespace PortabilityLayer bool Init(const WidgetBasicState &state) override; - //WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt); - //int16_t Capture(const Point &pos, WidgetUpdateCallback_t callback); + WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt); + int16_t Capture(const Point &pos, WidgetUpdateCallback_t callback); void DrawControl(DrawSurface *surface) override; + void OnStateChanged() override; + PLPasStr GetString() const override; + const THandle &GetMenu() const; + + protected: + ~PopupMenuWidget(); + private: THandle m_menu; }; diff --git a/PortabilityLayer/PLQDraw.cpp b/PortabilityLayer/PLQDraw.cpp index 2738bbc..3f54c90 100644 --- a/PortabilityLayer/PLQDraw.cpp +++ b/PortabilityLayer/PLQDraw.cpp @@ -3,6 +3,7 @@ #include "QDState.h" #include "BitmapImage.h" #include "DisplayDeviceManager.h" +#include "EllipsePlotter.h" #include "FontFamily.h" #include "FontManager.h" #include "LinePlotter.h" @@ -927,22 +928,6 @@ void DrawSurface::DrawPicture(THandle pictHdl, const Rect &bounds) m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } - -void DrawSurface::SetPattern8x8(const uint8_t *pattern) -{ - m_port.GetState()->SetPenPattern8x8(pattern); -} - -void DrawSurface::ClearPattern() -{ - m_port.GetState()->SetPenPattern8x8(nullptr); -} - -void DrawSurface::SetMaskMode(bool maskMode) -{ - m_port.GetState()->m_penMask = maskMode; -} - Rect DrawSurface::GetClipRect() const { return m_port.GetState()->m_clipRect; @@ -1001,7 +986,7 @@ void DrawSurface::FillRect(const Rect &rect) m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } -void DrawSurface::FillRectWithPattern8x8(const Rect &rect, const uint8_t *pattern) +void DrawSurface::FillRectWithPattern8x8(const Rect &rect, bool isMask, const uint8_t *pattern) { if (!rect.IsValid()) return; @@ -1037,6 +1022,10 @@ void DrawSurface::FillRectWithPattern8x8(const Rect &rect, const uint8_t *patter case GpPixelFormats::k8BitStandard: { const uint8_t color = qdState->ResolveForeColor8(nullptr, 0); + uint8_t backColor = 0; + + if (!isMask) + backColor = qdState->ResolveBackColor8(nullptr, 0); size_t scanlineIndex = 0; for (size_t ln = 0; ln < numLines; ln++) @@ -1049,6 +1038,8 @@ void DrawSurface::FillRectWithPattern8x8(const Rect &rect, const uint8_t *patter const int patternCol = static_cast((patternFirstCol + col) & 7); if ((pattern[patternRow] >> patternCol) & 1) pixData[firstLineIndex + col] = color; + else if (!isMask) + pixData[firstLineIndex + col] = backColor; } } } @@ -1106,9 +1097,90 @@ void DrawSurface::FillEllipse(const Rect &rect) } } +void DrawSurface::FillEllipseWithPattern(const Rect &rect, bool isMask, const uint8_t *pattern) +{ + if (!rect.IsValid() || rect.Width() < 1 || rect.Height() < 1) + return; + + if (rect.Width() <= 2 || rect.Height() <= 2) + { + FillRectWithPattern8x8(rect, isMask, pattern); + return; + } + + PortabilityLayer::ScanlineMask *mask = PortabilityLayer::ScanlineMaskConverter::CompileEllipse(PortabilityLayer::Rect2i(rect.top, rect.left, rect.bottom, rect.right)); + if (mask) + { + FillScanlineMaskWithPattern(mask, isMask, pattern); + mask->Destroy(); + } +} + void DrawSurface::FrameEllipse(const Rect &rect) { - PL_NotYetImplemented(); + if (!rect.IsValid()) + return; + + if (rect.Width() <= 2 || rect.Height() <= 2) + { + FillRect(rect); + return; + } + + Rect constrainedRect = rect; + + PortabilityLayer::QDPort *qdPort = &m_port; + + const Rect portRect = qdPort->GetRect(); + + PortabilityLayer::QDState *qdState = qdPort->GetState(); + constrainedRect = constrainedRect.Intersect(qdState->m_clipRect); + constrainedRect = constrainedRect.Intersect(portRect); + + if (!constrainedRect.IsValid()) + return; + + GpPixelFormat_t pixelFormat = qdPort->GetPixelFormat(); + + 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()); + + PortabilityLayer::EllipsePlotter plotter; + plotter.Reset(PortabilityLayer::Rect2i(rect.top, rect.left, rect.bottom, rect.right)); + + PortabilityLayer::Rect2i constraintRect32 = PortabilityLayer::Rect2i(constrainedRect.top, constrainedRect.left, constrainedRect.bottom, constrainedRect.right); + + switch (pixelFormat) + { + case GpPixelFormats::k8BitStandard: + { + const uint8_t color = qdState->ResolveForeColor8(nullptr, 0); + + for (;;) + { + const PortabilityLayer::Vec2i pt = plotter.GetPoint(); + + if (constraintRect32.Contains(pt)) + { + const size_t pixelIndex = static_cast(pt.m_y - portRect.top) * pitch + static_cast(pt.m_x - portRect.left); + pixData[pixelIndex] = color; + } + + if (plotter.PlotNext() == PortabilityLayer::PlotDirection_Exhausted) + break; + } + } + break; + default: + PL_NotYetImplemented(); + return; + } + + m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } static void FillScanlineSpan(uint8_t *rowStart, size_t startCol, size_t endCol, uint8_t patternByte, uint8_t foreColor, uint8_t bgColor, bool mask) @@ -1142,6 +1214,11 @@ static void FillScanlineSpan(uint8_t *rowStart, size_t startCol, size_t endCol, } void DrawSurface::FillScanlineMask(const PortabilityLayer::ScanlineMask *scanlineMask) +{ + FillScanlineMaskWithPattern(scanlineMask, false, nullptr); +} + +void DrawSurface::FillScanlineMaskWithPattern(const PortabilityLayer::ScanlineMask *scanlineMask, bool isMask, const uint8_t *pattern) { if (!scanlineMask) return; @@ -1175,7 +1252,6 @@ void DrawSurface::FillScanlineMask(const PortabilityLayer::ScanlineMask *scanlin uint8_t foreColor8 = 0; uint8_t backColor8 = 0; - const bool isMask = qdState->m_penMask; const GpPixelFormat_t pixelFormat = pixMap->m_pixelFormat; @@ -1193,9 +1269,9 @@ void DrawSurface::FillScanlineMask(const PortabilityLayer::ScanlineMask *scanlin uint8_t pattern8x8[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; bool havePattern = false; - if (const uint8_t *statePattern = qdState->GetPattern8x8()) + if (pattern) { - memcpy(pattern8x8, statePattern, 8); + memcpy(pattern8x8, pattern, 8); for (int i = 0; i < 8; i++) { if (pattern8x8[i] != 0xff) @@ -1452,36 +1528,11 @@ const PortabilityLayer::RGBAColor &DrawSurface::GetBackColor() const return m_port.GetState()->GetBackColor(); } -void PenInvertMode(bool invertMode) -{ - PortabilityLayer::QDState *qdState = PortabilityLayer::QDManager::GetInstance()->GetState(); - qdState->m_penInvert = invertMode; -} - -void PenMask(bool maskMode) -{ - PortabilityLayer::QDState *qdState = PortabilityLayer::QDManager::GetInstance()->GetState(); - qdState->m_penMask = maskMode; -} - -void PenPat(const Pattern *pattern) -{ - PortabilityLayer::QDState *qdState = PortabilityLayer::QDManager::GetInstance()->GetState(); - qdState->SetPenPattern8x8(*pattern); -} - void PenSize(int w, int h) { PL_NotYetImplemented(); } -void PenNormal() -{ - PortabilityLayer::QDState *qdState = PortabilityLayer::QDManager::GetInstance()->GetState(); - qdState->m_penInvert = false; - qdState->m_penMask = false; -} - void InsetRect(Rect *rect, int x, int y) { rect->left += x; diff --git a/PortabilityLayer/PLQDraw.h b/PortabilityLayer/PLQDraw.h index c681d85..3f7baa4 100644 --- a/PortabilityLayer/PLQDraw.h +++ b/PortabilityLayer/PLQDraw.h @@ -112,11 +112,7 @@ void GetForeColor(RGBColor *color); void ClipRect(const Rect *rect); void GetClip(Rect *rect); -void PenInvertMode(bool invertMode); -void PenMask(bool maskMode); -void PenPat(const Pattern *pattern); void PenSize(int w, int h); -void PenNormal(); void InsetRect(Rect *rect, int x, int y); Pattern *GetQDGlobalsGray(Pattern *pattern); Pattern *GetQDGlobalsBlack(Pattern *pattern); diff --git a/PortabilityLayer/PLResourceManager.cpp b/PortabilityLayer/PLResourceManager.cpp index 8eb5a98..f45507d 100644 --- a/PortabilityLayer/PLResourceManager.cpp +++ b/PortabilityLayer/PLResourceManager.cpp @@ -32,6 +32,8 @@ namespace ResourceValidationRules }; } +static const char *kPICTExtension = ".bmp"; + typedef ResourceValidationRules::ResourceValidationRule ResourceValidationRule_t; namespace @@ -302,6 +304,82 @@ namespace PortabilityLayer return m_zipFileProxy->HasPrefix(resPrefix); } + bool ResourceArchive::FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const + { + char resPrefix[6]; + resTypeID.ExportAsChars(resPrefix); + resPrefix[4] = '/'; + resPrefix[5] = '\0'; + + size_t fileIndex = 0; + if (!m_zipFileProxy->FindFirstWithPrefix(resPrefix, fileIndex)) + return false; + + const char *resName = nullptr; + size_t fnLength = 0; + m_zipFileProxy->GetFileName(fileIndex, resName, fnLength); + + assert(fnLength > 5); + + const char *idChars = resName + 5; + size_t idCharsRemaining = fnLength - 5; + + const size_t extLength = strlen(kPICTExtension); + + if (idCharsRemaining <= extLength) + return false; + + if (memcmp(idChars + idCharsRemaining - extLength, kPICTExtension, extLength)) + return false; + + idCharsRemaining -= extLength; + + bool isNegative = false; + + if (idChars[0] == '-') + { + isNegative = true; + idCharsRemaining--; + idChars++; + } + + if (idCharsRemaining == 0) + return false; + + if (idChars[0] == '0' && (idCharsRemaining > 1 || isNegative)) + return false; + + int32_t resID = 0; + while (idCharsRemaining) + { + const char idChar = *idChars; + + if (idChar < '0' || idChar > '9') + return false; + + resID = resID * 10; + if (isNegative) + { + resID -= (idChar - '0'); + if (resID < -32768) + return false; + } + else + { + resID += (idChar - '0'); + if (resID > 32767) + return false; + } + + idChars++; + idCharsRemaining--; + } + + outID = static_cast(resID); + + return true; + } + bool ResourceArchive::IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex, int &outValidationRule) const { const char *extension = ".bin"; @@ -314,7 +392,7 @@ namespace PortabilityLayer } else if (resTypeID == ResTypeID('Date') || resTypeID == ResTypeID('PICT')) { - extension = ".bmp"; + extension = kPICTExtension; outValidationRule = ResourceValidationRules::kBMP; } else if (resTypeID == ResTypeID('STR#')) diff --git a/PortabilityLayer/PLStandardColors.cpp b/PortabilityLayer/PLStandardColors.cpp index e72ce7c..30f638f 100644 --- a/PortabilityLayer/PLStandardColors.cpp +++ b/PortabilityLayer/PLStandardColors.cpp @@ -25,3 +25,8 @@ PortabilityLayer::RGBAColor StdColors::Blue() { return PortabilityLayer::RGBAColor::Create(0, 0, 255, 255); } + +PortabilityLayer::RGBAColor StdColors::Magenta() +{ + return PortabilityLayer::RGBAColor::Create(255, 0, 255, 255); +} diff --git a/PortabilityLayer/PLStandardColors.h b/PortabilityLayer/PLStandardColors.h index c5b9f19..c0be993 100644 --- a/PortabilityLayer/PLStandardColors.h +++ b/PortabilityLayer/PLStandardColors.h @@ -13,4 +13,5 @@ public: static PortabilityLayer::RGBAColor Red(); static PortabilityLayer::RGBAColor Green(); static PortabilityLayer::RGBAColor Blue(); + static PortabilityLayer::RGBAColor Magenta(); }; diff --git a/PortabilityLayer/PLWidgets.cpp b/PortabilityLayer/PLWidgets.cpp index 59c3a4e..96734b8 100644 --- a/PortabilityLayer/PLWidgets.cpp +++ b/PortabilityLayer/PLWidgets.cpp @@ -94,6 +94,11 @@ namespace PortabilityLayer return false; } + Rect Widget::GetExpandedRect() const + { + return GetRect(); + } + void Widget::GainFocus() { } diff --git a/PortabilityLayer/PLWidgets.h b/PortabilityLayer/PLWidgets.h index 92045ad..a6676b1 100644 --- a/PortabilityLayer/PLWidgets.h +++ b/PortabilityLayer/PLWidgets.h @@ -72,6 +72,7 @@ namespace PortabilityLayer virtual void SetHighlightStyle(int16_t style); virtual bool HandlesTickEvents() const; + virtual Rect GetExpandedRect() const; const Rect &GetRect() const; Window *GetWindow() const; @@ -118,7 +119,7 @@ namespace PortabilityLayer void Destroy() override { - static_cast(this)->~T(); + this->~WidgetSpec(); Widget::BaseRelease(static_cast(this)); } @@ -141,7 +142,7 @@ namespace PortabilityLayer return nullptr; } - if (!static_cast(state.m_window)->AddWidget(widget)) + if (state.m_window != nullptr && !static_cast(state.m_window)->AddWidget(widget)) { widget->Destroy(); return nullptr; diff --git a/PortabilityLayer/QDGraf.h b/PortabilityLayer/QDGraf.h index 053dab2..b61f069 100644 --- a/PortabilityLayer/QDGraf.h +++ b/PortabilityLayer/QDGraf.h @@ -59,16 +59,18 @@ struct DrawSurface final void PushToDDSurface(IGpDisplayDriver *displayDriver); void FillRect(const Rect &rect); - void FillRectWithPattern8x8(const Rect &rect, const uint8_t *pattern); + void FillRectWithPattern8x8(const Rect &rect, bool isMask, const uint8_t *pattern); void FrameRect(const Rect &rect); void FrameRoundRect(const Rect &rect, int quadrantWidth, int quadrantHeight); void InvertFrameRect(const Rect &rect, const uint8_t *pattern); void InvertFillRect(const Rect &rect, const uint8_t *pattern); void FillEllipse(const Rect &rect); + void FillEllipseWithPattern(const Rect &rect, bool isMask, const uint8_t *pattern); void FrameEllipse(const Rect &rect); void FillScanlineMask(const PortabilityLayer::ScanlineMask *scanlineMask); + void FillScanlineMaskWithPattern(const PortabilityLayer::ScanlineMask *scanlineMask, bool isMask, const uint8_t *pattern); void DrawLine(const Point &a, const Point &b); @@ -90,11 +92,6 @@ struct DrawSurface final void DrawPicture(THandle pictHandle, const Rect &rect); - void SetPattern8x8(const uint8_t *pattern); - void ClearPattern(); - - void SetMaskMode(bool maskMode); - Rect GetClipRect() const; void SetClipRect(const Rect &rect); diff --git a/PortabilityLayer/QDState.cpp b/PortabilityLayer/QDState.cpp index 70815f3..649ea59 100644 --- a/PortabilityLayer/QDState.cpp +++ b/PortabilityLayer/QDState.cpp @@ -18,16 +18,11 @@ namespace PortabilityLayer , m_isForeResolved8(false) , m_isBackResolved8(false) , m_clipRect(Rect::Create(INT16_MIN, INT16_MIN, INT16_MAX, INT16_MAX)) - , m_penInvert(false) - , m_penMask(false) - , m_havePattern8x8(false) { m_backUnresolvedColor.r = m_backUnresolvedColor.g = m_backUnresolvedColor.b = m_backUnresolvedColor.a = 255; m_foreUnresolvedColor.r = m_foreUnresolvedColor.g = m_foreUnresolvedColor.b = 0; m_foreUnresolvedColor.a = 255; m_penPos.h = m_penPos.v = 0; - - memset(m_pattern8x8, 0, sizeof(m_pattern8x8)); } void QDState::SetForeColor(const RGBAColor &color) @@ -84,39 +79,4 @@ namespace PortabilityLayer return resolvedColor; } } - - void QDState::SetPenPattern8x8(const uint8_t *pattern) - { - if (!pattern) - { - m_havePattern8x8 = false; - return; - } - - bool isSolid = true; - for (int i = 0; i < 8; i++) - { - if (pattern[i] != 0xff) - { - isSolid = false; - break; - } - } - - if (isSolid) - m_havePattern8x8 = false; - else - { - m_havePattern8x8 = true; - memcpy(m_pattern8x8, pattern, sizeof(m_pattern8x8)); - } - } - - const uint8_t *QDState::GetPattern8x8() const - { - if (m_havePattern8x8) - return m_pattern8x8; - - return nullptr; - } } diff --git a/PortabilityLayer/QDState.h b/PortabilityLayer/QDState.h index 81736e3..ac12593 100644 --- a/PortabilityLayer/QDState.h +++ b/PortabilityLayer/QDState.h @@ -16,8 +16,6 @@ namespace PortabilityLayer int m_fontSize; Rect m_clipRect; Point m_penPos; - bool m_penInvert; - bool m_penMask; void SetForeColor(const RGBAColor &color); void SetBackColor(const RGBAColor &color); @@ -28,9 +26,6 @@ namespace PortabilityLayer uint8_t ResolveForeColor8(const RGBAColor *palette, unsigned int numColors); uint8_t ResolveBackColor8(const RGBAColor *palette, unsigned int numColors); - void SetPenPattern8x8(const uint8_t *pattern); - const uint8_t *GetPattern8x8() const; - private: static uint8_t ResolveColor8(const RGBAColor &color, uint8_t &cached, bool &isCached, const RGBAColor *palette, unsigned int numColors); @@ -42,9 +37,6 @@ namespace PortabilityLayer uint8_t m_foreResolvedColor8; uint8_t m_backResolvedColor8; - uint8_t m_pattern8x8[8]; - bool m_havePattern8x8; - bool m_isForeResolved16; bool m_isForeResolved8; bool m_isBackResolved16; diff --git a/PortabilityLayer/Rect2i.h b/PortabilityLayer/Rect2i.h index cf46149..8b75f31 100644 --- a/PortabilityLayer/Rect2i.h +++ b/PortabilityLayer/Rect2i.h @@ -40,7 +40,8 @@ namespace PortabilityLayer void SetRight(int32_t i); bool IsValid() const; - Rect2i Intersect(const Rect2i &other) const; + Rect2i Intersect(const Rect2i &other) const; + bool Contains(const Vec2i &pt) const; Rect ToShortRect() const; }; @@ -156,6 +157,11 @@ namespace PortabilityLayer const int32_t right = std::min(m_bottomRight.m_x, other.m_bottomRight.m_x); return Rect2i(top, left, bottom, right); + } + + inline bool Rect2i::Contains(const Vec2i &pt) const + { + return pt.m_x >= m_topLeft.m_x && pt.m_x < m_bottomRight.m_x && pt.m_y >= m_topLeft.m_y && pt.m_y < m_bottomRight.m_y; } inline Rect Rect2i::ToShortRect() const diff --git a/PortabilityLayer/ResourceManager.h b/PortabilityLayer/ResourceManager.h index b9f01c8..d2d0f51 100644 --- a/PortabilityLayer/ResourceManager.h +++ b/PortabilityLayer/ResourceManager.h @@ -34,6 +34,7 @@ namespace PortabilityLayer bool GetResourceSize(const ResTypeID &resTypeID, int id, size_t &outSize) const; bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const; + bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const; private: ResourceArchive(ZipFileProxy *zipFileProxy, IOStream *stream, ResourceArchiveRef *resourceHandles); diff --git a/PortabilityLayer/WindowManager.cpp b/PortabilityLayer/WindowManager.cpp index 24e8cc3..0847df7 100644 --- a/PortabilityLayer/WindowManager.cpp +++ b/PortabilityLayer/WindowManager.cpp @@ -97,6 +97,8 @@ namespace PortabilityLayer bool IsBorderless() const; uint16_t GetStyleFlags() const; + + void SetTitle(const PLPasStr &str); const PascalStr<255> &GetTitle() const; private: @@ -124,6 +126,7 @@ namespace PortabilityLayer void FindWindow(const Point &point, Window **outWindow, short *outRegion) const override; void DestroyWindow(Window *window) override; void DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) override; + void SetWindowTitle(Window *window, const PLPasStr &title) override; void RenderFrame(IGpDisplayDriver *displayDriver) override; @@ -582,6 +585,12 @@ namespace PortabilityLayer return m_styleFlags; } + void WindowImpl::SetTitle(const PLPasStr &str) + { + m_title.Set(str.Length(), str.Chars()); + m_chromeTheme->RenderChrome(this, m_chromeSurfaces + WindowChromeSides::kTop, WindowChromeSides::kTop); + } + const PascalStr<255> &WindowImpl::GetTitle() const { return m_title; @@ -770,6 +779,11 @@ namespace PortabilityLayer } } + void WindowManagerImpl::SetWindowTitle(Window *window, const PLPasStr &title) + { + static_cast(window)->SetTitle(title); + } + void WindowManagerImpl::RenderFrame(IGpDisplayDriver *displayDriver) { PortabilityLayer::DisplayDeviceManager *dd = PortabilityLayer::DisplayDeviceManager::GetInstance(); diff --git a/PortabilityLayer/WindowManager.h b/PortabilityLayer/WindowManager.h index a55f3b5..c93dcb5 100644 --- a/PortabilityLayer/WindowManager.h +++ b/PortabilityLayer/WindowManager.h @@ -5,6 +5,7 @@ struct DrawSurface; struct GDevice; struct IGpDisplayDriver; struct Point; +class PLPasStr; struct Rect; struct Window; @@ -25,6 +26,7 @@ namespace PortabilityLayer virtual void FindWindow(const Point &point, Window **outWindow, short *outRegion) const = 0; virtual void DestroyWindow(Window *window) = 0; virtual void DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) = 0; + virtual void SetWindowTitle(Window *window, const PLPasStr &title) = 0; virtual void RenderFrame(IGpDisplayDriver *displayDriver) = 0; diff --git a/PortabilityLayer/ZipFileProxy.cpp b/PortabilityLayer/ZipFileProxy.cpp index 6f5c4d4..88097a8 100644 --- a/PortabilityLayer/ZipFileProxy.cpp +++ b/PortabilityLayer/ZipFileProxy.cpp @@ -137,21 +137,21 @@ namespace PortabilityLayer // -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; + lastFileExclusive = midFile; midFile = (firstFile + lastFileExclusive) / 2; } } + else if (delta > 0) + { + firstFile = midFile + 1; + midFile = (firstFile + lastFileExclusive) / 2; + } else //if(delta == 0) { // Found the directory @@ -163,6 +163,40 @@ namespace PortabilityLayer return false; } + bool ZipFileProxy::FindFirstWithPrefix(const char *prefix, size_t &outFileIndex) const + { + size_t prefixLen = strlen(prefix); + + // Could do binary search, but it's much more complicated in this case, just do linear scan... + for (size_t i = 0; i < m_numFiles; i++) + { + const UnalignedPtr itemPtr = m_sortedFiles[i]; + 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); + if (delta == 0) + continue; + + if (delta < 0) + { + const bool isPathPrefix = ((itemNameLength > prefixLen) && !memcmp(prefix, itemPath, prefixLen)); + + if (isPathPrefix) + { + outFileIndex = i; + return true; + } + else + return false; + } + } + + return false; + } + bool ZipFileProxy::LoadFile(size_t index, void *outBuffer) { ZipCentralDirectoryFileHeader centralDirHeader = m_sortedFiles[index].Get(); @@ -203,6 +237,15 @@ namespace PortabilityLayer return m_sortedFiles[index].Get().m_uncompressedSize; } + void ZipFileProxy::GetFileName(size_t index, const char *&outName, size_t &outLength) const + { + const UnalignedPtr itemPtr = m_sortedFiles[index]; + const PortabilityLayer::ZipCentralDirectoryFileHeader item = itemPtr.Get(); + + outLength = item.m_fileNameLength; + outName = GetZipItemName(itemPtr); + } + ZipFileProxy *ZipFileProxy::Create(IOStream *stream) { MemoryManager *mm = MemoryManager::GetInstance(); diff --git a/PortabilityLayer/ZipFileProxy.h b/PortabilityLayer/ZipFileProxy.h index 74e1535..38c7195 100644 --- a/PortabilityLayer/ZipFileProxy.h +++ b/PortabilityLayer/ZipFileProxy.h @@ -16,9 +16,12 @@ namespace PortabilityLayer bool LoadFile(size_t index, void *outBuffer); bool HasPrefix(const char *path) const; + bool FindFirstWithPrefix(const char *resPrefix, size_t &outFileIndex) const; size_t NumFiles() const; size_t GetFileSize(size_t index) const; + void GetFileName(size_t index, const char *&outName, size_t &outLength) const; + static ZipFileProxy *Create(IOStream *stream);