diff --git a/teraterm/common/bitmap.cpp b/teraterm/common/bitmap.cpp index 662d25db2..045328fab 100644 --- a/teraterm/common/bitmap.cpp +++ b/teraterm/common/bitmap.cpp @@ -292,9 +292,45 @@ static HBITMAP GetBitmapHandleW(const wchar_t *File) iPicture->get_Type(&type); if(type==PICTYPE_BITMAP){ iPicture->get_Handle(&hOle); + } else { + iPicture->Release(); + return NULL; } - hBitmap=(HBITMAP)(UINT_PTR)hOle; + HBITMAP hRaw = (HBITMAP)(UINT_PTR)hOle; + + BITMAP bm; + if (GetObject(hRaw, sizeof(bm), &bm)) { + HDC hScreenDC = GetDC(NULL); + if (hScreenDC) { + hBitmap = CreateCompatibleBitmap(hScreenDC, bm.bmWidth, bm.bmHeight); + if (hBitmap) { + HDC hSrcDC = CreateCompatibleDC(hScreenDC); + HDC hDstDC = CreateCompatibleDC(hScreenDC); + if (hSrcDC && hDstDC) { + HBITMAP hOldSrcBmp = (HBITMAP)SelectObject(hSrcDC, hRaw); + HBITMAP hOldDstBmp = (HBITMAP)SelectObject(hDstDC, hBitmap); + BOOL ok = BitBlt(hDstDC, 0, 0, bm.bmWidth, bm.bmHeight, hSrcDC, 0, 0, SRCCOPY); + SelectObject(hSrcDC, hOldSrcBmp); + SelectObject(hDstDC, hOldDstBmp); + if (!ok) { + DeleteObject(hBitmap); + hBitmap = NULL; + } + } else { + DeleteObject(hBitmap); + hBitmap = NULL; + } + if (hSrcDC) { + DeleteDC(hSrcDC); + } + if (hDstDC) { + DeleteDC(hDstDC); + } + } + ReleaseDC(NULL, hScreenDC); + } + } iPicture->Release(); diff --git a/teraterm/teraterm/CMakeLists.txt b/teraterm/teraterm/CMakeLists.txt index 9a642ffb4..3af9dc593 100644 --- a/teraterm/teraterm/CMakeLists.txt +++ b/teraterm/teraterm/CMakeLists.txt @@ -449,6 +449,7 @@ target_link_libraries( user32 uuid ws2_32 + Wtsapi32 ) install( diff --git a/teraterm/teraterm/ttermpro.v16.vcxproj b/teraterm/teraterm/ttermpro.v16.vcxproj index a98baa47a..d8458f894 100644 --- a/teraterm/teraterm/ttermpro.v16.vcxproj +++ b/teraterm/teraterm/ttermpro.v16.vcxproj @@ -154,7 +154,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -199,7 +199,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -243,7 +243,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -286,7 +286,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -330,7 +330,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -373,7 +373,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) diff --git a/teraterm/teraterm/ttermpro.v17.vcxproj b/teraterm/teraterm/ttermpro.v17.vcxproj index 123c1f983..8d4837fce 100644 --- a/teraterm/teraterm/ttermpro.v17.vcxproj +++ b/teraterm/teraterm/ttermpro.v17.vcxproj @@ -154,7 +154,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -199,7 +199,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -243,7 +243,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -286,7 +286,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -330,7 +330,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -373,7 +373,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) diff --git a/teraterm/teraterm/ttermpro.v18.vcxproj b/teraterm/teraterm/ttermpro.v18.vcxproj index 4462635b8..876bf7dfd 100644 --- a/teraterm/teraterm/ttermpro.v18.vcxproj +++ b/teraterm/teraterm/ttermpro.v18.vcxproj @@ -154,7 +154,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -199,7 +199,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -243,7 +243,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -286,7 +286,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -330,7 +330,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -373,7 +373,7 @@ $(SolutionDir)common;%(AdditionalIncludeDirectories) - onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies) + onig.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;Wtsapi32.lib;%(AdditionalDependencies) true $(SolutionDir)..\libs\oniguruma\build\$(Platform)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs) @@ -641,4 +641,4 @@ - \ No newline at end of file + diff --git a/teraterm/teraterm/vtdisp.c b/teraterm/teraterm/vtdisp.c index 9c40700fb..b36c37be4 100644 --- a/teraterm/teraterm/vtdisp.c +++ b/teraterm/teraterm/vtdisp.c @@ -259,9 +259,16 @@ static HDC CreateBitmapDC(HBITMAP hbm) _OutputDebugPrintf("CreateBitmapDC : hbm = %p\n",hbm); hdc = CreateCompatibleDC(NULL); + if (hdc == NULL) { + DeleteObject(hbm); + return NULL; + } - SaveDC(hdc); - SelectObject(hdc,hbm); + if (SelectObject(hdc, hbm) == NULL) { + DeleteDC(hdc); + DeleteObject(hbm); + return NULL; + } return hdc; } @@ -280,11 +287,12 @@ static void DeleteBitmapDC(HDC *hdc) hbm = GetCurrentObject(*hdc,OBJ_BITMAP); - RestoreDC(*hdc,-1); - DeleteObject(hbm); DeleteDC(*hdc); - *hdc = 0; + + if (hbm) { + DeleteObject(hbm); + } } static void FillBitmapDC(HDC hdc,COLORREF color) @@ -375,13 +383,19 @@ static void BGPreloadPicture(BGSrc *src, const TTTSet *pts) if(hbm) { BITMAP bm; - GetObject(hbm,sizeof(bm),&bm); - - src->hdc = CreateBitmapDC(hbm); - src->width = bm.bmWidth; - src->height = bm.bmHeight; + if (GetObject(hbm, sizeof(bm), &bm) == 0) { + DeleteObject(hbm); + } else { + HDC new_hdc = CreateBitmapDC(hbm); + if (new_hdc) { + DeleteBitmapDC(&(src->hdc)); + src->hdc = new_hdc; + src->width = bm.bmWidth; + src->height = bm.bmHeight; + } + } }else{ - src->type = BG_COLOR; + src->type = BG_COLOR; // 画像が読めない場合は、単色塗りにフォールバックする } free(susie_path); @@ -614,43 +628,75 @@ static void BGPreloadWallpaper(BGSrc *src) { BITMAP bm; - GetObject(hbm,sizeof(bm),&bm); - - src->hdc = CreateBitmapDC(hbm); - src->width = bm.bmWidth; - src->height = bm.bmHeight; - src->pattern = wi.pattern; - + if (GetObject(hbm, sizeof(bm), &bm) == 0) { + DeleteObject(hbm); + } else { + HDC new_hdc = CreateBitmapDC(hbm); + if (new_hdc) { + DeleteBitmapDC(&(src->hdc)); + src->hdc = new_hdc; + src->width = bm.bmWidth; + src->height = bm.bmHeight; + src->pattern = wi.pattern; + } + } }else{ - src->hdc = NULL; + src->hdc = NULL; // 壁紙を読めない場合は再読み込み出来るようにしておく } src->color = GetSysColor(COLOR_DESKTOP); } -static void BGPreloadSrc(BGSrc *src, const TTTSet *pts) +// 復帰値 +// TRUE 描画リソースの再構築を行った +// FALSE 既存の描画リソースをそのまま利用可能 +static BOOL BGPreloadSrc(BGSrc *src, const TTTSet *pts, BOOL forceReload) { if (!src->enable) { - return; + return FALSE; } - DeleteBitmapDC(&(src->hdc)); + if (forceReload == FALSE && src->hdc) { + HDC memdc = CreateCompatibleDC(src->hdc); + if (memdc) { + HBITMAP bmp = CreateCompatibleBitmap(src->hdc, 1, 1); + if (!bmp) { + DeleteDC(memdc); + } else { + HBITMAP oldBmp = SelectObject(memdc, bmp); + BOOL ok = BitBlt(memdc, 0, 0, 1, 1, src->hdc, 0, 0, SRCCOPY); + SelectObject(memdc, oldBmp); + DeleteObject(bmp); + DeleteDC(memdc); + if (ok) { + // 1x1ピクセルの画像の読み取りに成功した。 + // → HBITMAP(デバイス依存ビットマップ)は使用可能とみなす。 + return FALSE; + } + } + } + } + BOOL ret = FALSE; switch (src->type) { case BG_COLOR: break; case BG_WALLPAPER: BGPreloadWallpaper(src); + ret = TRUE; break; case BG_PICTURE: BGPreloadPicture(src, pts); + ret = TRUE; break; default: break; } + + return ret; } static void BGStretchPicture(HDC hdcDest, BGSrc *src, int x, int y, int width, int height) @@ -1063,6 +1109,7 @@ void BGSetupPrimary(vtdraw_t *vt, BOOL forceSetup) { POINT point; RECT rect; + BOOL preloaded = FALSE; if(!BGEnable) return; @@ -1075,16 +1122,27 @@ void BGSetupPrimary(vtdraw_t *vt, BOOL forceSetup) GetClientRect(vt->hVTWin,&rect); OffsetRect(&rect,point.x,point.y); - if(!forceSetup && EqualRect(&rect,&BGPrevRect)) - return; + if (!forceSetup && EqualRect(&rect,&BGPrevRect)) { + // クラウド環境(RDP等)でディスプレイデバイスが再構成されると、 + // DDB(デバイス依存ビットマップ)が作成時のデバイスと互換性を失い + // 描画不能になることがある。 + // HBITMAPが使用不可なら壁紙 or 背景を再ロードする。 + preloaded |= BGPreloadSrc(&BGDest, vt->pts, FALSE); + preloaded |= BGPreloadSrc(&BGSrc1, vt->pts, FALSE); + preloaded |= BGPreloadSrc(&BGSrc2, vt->pts, FALSE); + if (preloaded == FALSE) { + return; + } + } CopyRect(&BGPrevRect,&rect); //壁紙 or 背景をプリロード - BGPreloadSrc(&BGDest, vt->pts); - BGPreloadSrc(&BGSrc1, vt->pts); - BGPreloadSrc(&BGSrc2, vt->pts); - + if (preloaded == FALSE) { + BGPreloadSrc(&BGDest, vt->pts, TRUE); + BGPreloadSrc(&BGSrc1, vt->pts, TRUE); + BGPreloadSrc(&BGSrc2, vt->pts, TRUE); + } _OutputDebugPrintf("BGSetupPrimary : BGInSizeMove = %d\n",BGInSizeMove); //作業用 DC 作成 diff --git a/teraterm/teraterm/vtwin.cpp b/teraterm/teraterm/vtwin.cpp index 559b32767..04ac49d81 100644 --- a/teraterm/teraterm/vtwin.cpp +++ b/teraterm/teraterm/vtwin.cpp @@ -85,6 +85,7 @@ #include #include #include +#include #include "tt_res.h" #include "vtwin.h" @@ -760,6 +761,7 @@ CVTWindow::CVTWindow(HINSTANCE hInstance) cv.HWin = HVTWin; vt_src = InitDisp(HVTWin, &ts); BGLoadThemeFile(vt_src, &ts); + WTSRegisterSessionNotification(HVTWin, NOTIFY_FOR_THIS_SESSION); // Windows 11 でウィンドウの角が丸くならないようにする if (ts.WindowCornerDontround && pDwmSetWindowAttribute != NULL) { @@ -1828,6 +1830,7 @@ void CVTWindow::OnDestroy() } EndTerm(); + WTSUnRegisterSessionNotification(HVTWin); EndDisp(vt_src); vt_src = NULL; sendfiledlgUnInit(); @@ -5299,6 +5302,29 @@ LRESULT CVTWindow::OnDpiChanged(WPARAM wp, LPARAM lp, BOOL calcOnly) return 0; } +void CVTWindow::OnDisplayChange() +{ + if (vt_src == NULL || !ThemeIsEnabled()) { + return; + } + BGSetupPrimary(vt_src, TRUE); + ::InvalidateRect(m_hWnd, NULL, FALSE); +} + +void CVTWindow::OnWTSSessionChange(WPARAM wp) +{ + if (vt_src == NULL || !ThemeIsEnabled()) { + return; + } + if (wp == WTS_CONSOLE_CONNECT || + wp == WTS_REMOTE_CONNECT || + wp == WTS_SESSION_LOGON || + wp == WTS_SESSION_UNLOCK) { + BGSetupPrimary(vt_src, TRUE); + ::InvalidateRect(m_hWnd, NULL, FALSE); + } +} + LRESULT CVTWindow::Proc(UINT msg, WPARAM wp, LPARAM lp) { static const UINT WM_TASKBER_CREATED = RegisterWindowMessage("TaskbarCreated"); @@ -5555,6 +5581,12 @@ LRESULT CVTWindow::Proc(UINT msg, WPARAM wp, LPARAM lp) case WM_DPICHANGED: OnDpiChanged(wp, lp, FALSE); break; + case WM_DISPLAYCHANGE: + OnDisplayChange(); + break; + case WM_WTSSESSION_CHANGE: + OnWTSSessionChange(wp); + break; case WM_COMMAND: { if (isClosing) { diff --git a/teraterm/teraterm/vtwin.h b/teraterm/teraterm/vtwin.h index 05a5ee442..0578470bd 100644 --- a/teraterm/teraterm/vtwin.h +++ b/teraterm/teraterm/vtwin.h @@ -241,6 +241,8 @@ class CVTWindow : public TTCFrameWnd void OnHelpAbout(); LRESULT OnDropNotify(WPARAM ShowMenu, LPARAM lParam); LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam, BOOL calcOnly); + void OnDisplayChange(); + void OnWTSSessionChange(WPARAM wp); virtual LRESULT Proc(UINT msg, WPARAM wp, LPARAM lp); private: