// // Copyright 1997 Nicholas J. Irias. All rights reserved. // // // MainFrm.cpp : implementation of the CMainFrame class // #include "stdafx.h" #include "cderr.h" // #define TRACE_HERE #include "P4win.h" #include "MainFrm.h" #include "Document.h" #include "ClientView.h" #include "ClientWizSheet.h" #include "cmd_diff.h" #include "cmd_get.h" #include "cmd_fstat.h" #include "cmd_history.h" #include "cmd_info.h" #include "cmd_listopstat.h" #include "Cmd_Logout.h" #include "Cmd_Opened.h" #include "cmd_refresh.h" #include "cmd_where.h" #include "FileInfoDlg.h" #include "FirstTimeDlg.h" #include "P4Registry.h" #include "GuiClientUser.h" #include "ToolsDlg.h" #include "ToolsArgs.h" #include "Bookmarks.h" #include "Favorites.h" #include "FavEditDlg.h" #include "WindowsVersion.h" #include "MsgBox.h" #include "ImageList.h" #include "OptionsTreeDlg.h" #include "SpecDescDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Registered windows message used to reactivate p4win from a new instance // Need a module global, because ON_REGISTERED_MESSAGE can't eat this ptr UINT wmActivate; UINT wmSendcmd; UINT wmRplycmd; // Get the ctrl ID for a non-existant pane (x,2) (IDFromRowCol() would assert) //#define MAKEID(x) (m_wndHRSplitter.IdFromRowCol(0,0)+16*x +1) #define MAKEID(x) (m_wndVSplitter.IdFromRowCol(0,1)+16*x +1) ///////////////////////////////////////////////////////////////////////////// // CTBDropTarget CTBDropTarget::CTBDropTarget() {} CTBDropTarget::~CTBDropTarget() {} // // OnDragEnter is called by OLE dll's when drag cursor enters // a window that is REGISTERed with the OLE dll's // Pass the cal to MainFrame to deal with it DROPEFFECT CTBDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point ) { return MainFrame()->OnDragEnter(pWnd, pDataObject, dwKeyState, point); } // // OnDragLeave is called by OLE dll's when drag cursor leaves // a window that is REGISTERed with the OLE dll's // Pass the cal to MainFrame to deal with it void CTBDropTarget::OnDragLeave(CWnd* pWnd) { MainFrame()->OnDragLeave(pWnd); // Call base class implementation COleDropTarget:: OnDragLeave(pWnd); } // // OnDragOver is called by OLE dll's when cursor is dragged over // a window that is REGISTERed with the OLE dll's // Pass the cal to MainFrame to deal with it DROPEFFECT CTBDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point ) { return MainFrame()->OnDragOver(pWnd, pDataObject, dwKeyState, point); } // // OnDrop is called by OLE dll's when item is dropped in a window // that is REGISTERed with the OLE dll's // Pass the cal to MainFrame to deal with it BOOL CTBDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point ) { return MainFrame()->OnDrop(pWnd, pDataObject, dropEffect, point ); } ///////////////////////////////////////////////////////////////////////////// // CMainFrame IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_UPDATE_COMMAND_UI(ID_FILE_GET, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_OPENEDIT, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_OPENDELETE, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_REVERT, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_LOCK, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_UNLOCK, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_REVISIONHISTORY, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_DIFFHEAD, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_QUICKBROWSE, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILE_QUICKEDIT, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_VIEW_FILTEREDVIEW, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_VIEW_CLEARFILTER, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_CHANGE_SUBMIT, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILTER_SETVIEW, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILTER_CLEARVIEW, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_LABELFILTER_SETVIEW, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_LABELFILTER_SETVIEWREV, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_LABELFILTER_CLEARVIEW, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILTERBYOWNER, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_CLEAROWNERFILTER, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_JOB_CONFIGURE, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_JOB_SETFILTER, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_JOB_REMOVEFILTER, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_FILTERCLIENTS, OnUpdateMenuWithIcon) ON_UPDATE_COMMAND_UI(ID_CLEARCLIENTFILTER, OnUpdateMenuWithIcon) ON_COMMAND(ID_VIEW_UPDATE, OnViewUpdate) ON_UPDATE_COMMAND_UI(ID_VIEW_UPDATE, OnUpdateViewUpdate) ON_COMMAND(ID_FILE_CANCEL, OnCancelCommand) ON_UPDATE_COMMAND_UI(ID_FILE_CANCEL, OnUpdateCancelCommand) ON_COMMAND(ID_CANCEL_BUTTON, OnCancelButton) ON_UPDATE_COMMAND_UI(ID_CANCEL_BUTTON, OnUpdateCancelCommand) ON_UPDATE_COMMAND_UI(ID_CURRENTTASK, OnUpdateStatus) ON_WM_SIZE() ON_COMMAND(ID_PERFORCE_OPTIONS, OnPerforceOptions) ON_UPDATE_COMMAND_UI(ID_PERFORCE_OPTIONS, OnUpdateP4Options) ON_WM_CLOSE() ON_WM_DESTROY() ON_COMMAND(ID_PERFORCE_INFO, OnPerforceInfo) ON_UPDATE_COMMAND_UI(ID_PERFORCE_INFO, OnUpdatePerforceInfo) ON_UPDATE_COMMAND_UI(ID_BRANCH_ACTIVATE, OnUpdateViewSwitch) ON_COMMAND(ID_BRANCH_ACTIVATE, OnViewBranches) ON_COMMAND(ID_CHANGELIST_ACTIVATE, OnViewChanges) ON_COMMAND(ID_CLIENT_ACTIVATE, OnViewClients) ON_COMMAND(ID_JOB_ACTIVATE, OnViewJobs) ON_COMMAND(ID_LABEL_ACTIVATE, OnViewLabels) ON_COMMAND(ID_SUBMITTED_ACTIVATE, OnViewSubmitted) ON_COMMAND(ID_USER_ACTIVATE, OnViewUsers) ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_CLIENTVIEW, ID_VIEW_ENTIREVIEW, OnUpdateViewDepot) ON_COMMAND_RANGE(ID_VIEW_CLIENTVIEW, ID_VIEW_ENTIREVIEW, OnViewDepot) ON_WM_TIMER() ON_UPDATE_COMMAND_UI(ID_JOB_NEW, OnUpdateJobNew) ON_UPDATE_COMMAND_UI(ID_BRANCH_NEW, OnUpdateBranchNew) ON_UPDATE_COMMAND_UI(ID_LABEL_NEW, OnUpdateLabelNew) ON_COMMAND(ID_JOB_NEW, OnJobNew) ON_COMMAND(ID_BRANCH_NEW, OnBranchNew) ON_COMMAND(ID_LABEL_NEW, OnLabelNew) ON_UPDATE_COMMAND_UI(ID_CLIENT_EDITMY, OnUpdateClientEditmy) ON_COMMAND(ID_CLIENT_EDITMY, OnClientEditmy) ON_UPDATE_COMMAND_UI(ID_USER_EDITMY, OnUpdateUserEditmy) ON_COMMAND(ID_USER_EDITMY, OnUserEditmy) ON_WM_SYSCOLORCHANGE() ON_UPDATE_COMMAND_UI(ID_FILE_ADD, OnUpdateFileAdd) ON_COMMAND(ID_FILE_ADD, OnFileAdd) ON_UPDATE_COMMAND_UI(ID_CLIENTSPEC_NEW, OnUpdateClientspecNew) ON_COMMAND(ID_CLIENTSPEC_NEW, OnClientspecNew) ON_UPDATE_COMMAND_UI(ID_SUBMITTED_ACTIVATE, OnUpdateSubmittedActivate) ON_UPDATE_COMMAND_UI(ID_USER_CREATENEWUSER, OnUpdateUserNew) ON_COMMAND(ID_USER_CREATENEWUSER, OnUserNew) ON_UPDATE_COMMAND_UI(ID_USER_PASSWORD, OnUpdateUserPassword) ON_COMMAND(ID_USER_PASSWORD, OnUserPassword) ON_UPDATE_COMMAND_UI(ID_MRU_PCU0, OnUpdateMruPcu) ON_COMMAND(ID_MRU_PCU0, OnMruPcu0) ON_COMMAND(ID_MRU_PCU1, OnMruPcu1) ON_COMMAND(ID_MRU_PCU2, OnMruPcu2) ON_COMMAND(ID_MRU_PCU3, OnMruPcu3) ON_COMMAND(ID_MRU_PCU4, OnMruPcu4) ON_COMMAND(ID_MRU_PCU5, OnMruPcu5) ON_COMMAND(ID_MRU_PCU6, OnMruPcu6) ON_COMMAND(ID_MRU_PCU7, OnMruPcu7) ON_COMMAND(ID_MRU_PCU8, OnMruPcu8) ON_COMMAND(ID_MRU_PCU9, OnMruPcu9) ON_UPDATE_COMMAND_UI(ID_MRU_PCU_HDR, OnUpdateMruPcuHdr) ON_COMMAND(ID_SHOWDELETEDFILES, OnShowDeletedFiles) ON_UPDATE_COMMAND_UI(ID_SHOWDELETEDFILES, OnUpdateShowDeletedFiles) ON_COMMAND(ID_SORTBYEXTENSION, OnSortByExtension) ON_UPDATE_COMMAND_UI(ID_SORTBYEXTENSION, OnUpdateSortByExtension) ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) ON_UPDATE_COMMAND_UI(ID_VIEW_WARNANDERR, OnUpdateViewWarnAndErrs) ON_COMMAND(ID_VIEW_WARNANDERR, OnViewWarnAndErrs) ON_UPDATE_COMMAND_UI(ID_POSITIONTOPATTERN, OnUpdatePositionToPattern) ON_COMMAND(ID_POSITIONTOPATTERN, OnPositionToPattern) ON_UPDATE_COMMAND_UI(ID_FINDNEXT, OnUpdatePositionToNext) ON_COMMAND(ID_FINDNEXT, OnPositionToNext) ON_UPDATE_COMMAND_UI(ID_FINDPREV, OnUpdatePositionToPrev) ON_COMMAND(ID_FINDPREV, OnPositionToPrev) ON_UPDATE_COMMAND_UI(ID_WINEXPLORE, OnUpdateWinExplore) ON_COMMAND(ID_WINEXPLORE, OnWinExplore) ON_UPDATE_COMMAND_UI(ID_CMDPROMPT, OnUpdateCmdPrompt) ON_COMMAND(ID_CMDPROMPT, OnCmdPrompt) ON_COMMAND(ID_CUSTOMIZETOOLS, OnCustomizeTools) ON_UPDATE_COMMAND_UI(ID_IMPORT, OnUpdateToolsImport) ON_COMMAND(ID_IMPORT, OnToolsImport) ON_UPDATE_COMMAND_UI(ID_EXPORT, OnUpdateToolsExport) ON_COMMAND(ID_EXPORT, OnToolsExport) ON_COMMAND(ID_PAGE_SETUP, OnPageSetup) ON_UPDATE_COMMAND_UI(ID_MAKE_DEFAULT_PCU, OnUpdateMakeDefaultPcu) ON_COMMAND(ID_MAKE_DEFAULT_PCU, OnMakeDefaultPcu) ON_WM_MENUSELECT() ON_UPDATE_COMMAND_UI(ID_VIEW_CLOSEDIALOGS, OnUpdateCloseAllModelessDlgs) ON_COMMAND(ID_VIEW_CLOSEDIALOGS, CloseAllModelessDlgs) ON_UPDATE_COMMAND_UI(ID_CHGS_BY_USER, OnUpdateViewChgsByUser) ON_COMMAND(ID_CHGS_BY_USER, OnViewChgsByUser) ON_UPDATE_COMMAND_UI(ID_CHGS_BY_CLIENT, OnUpdateViewChgsByClient) ON_COMMAND(ID_CHGS_BY_CLIENT, OnViewChgsByClient) ON_UPDATE_COMMAND_UI(ID_CHANGE_DESCRIBE_2, OnUpdateDescribeChg) ON_COMMAND(ID_CHANGE_DESCRIBE_2, OnDescribeChg) ON_UPDATE_COMMAND_UI(ID_JOB_DESCRIBE_2, OnUpdateDescribeJob) ON_COMMAND(ID_JOB_DESCRIBE_2, OnDescribeJob) ON_UPDATE_COMMAND_UI(ID_BOOKMARKS, OnUpdateBookmarks) ON_COMMAND(ID_BOOKMARKS, OnBookmarks) ON_COMMAND(ID_ORGANIZE_BOOKMARKS, OnOrganizeBookmarks) ON_UPDATE_COMMAND_UI(ID_FAVORITES, OnUpdateFavorites) ON_UPDATE_COMMAND_UI(ID_ORGANIZE_FAVORITES, OnUpdateOrganizeFavorites) ON_COMMAND(ID_ORGANIZE_FAVORITES, OnOrganizeFavorites) ON_UPDATE_COMMAND_UI(ID_ADD_FAVORITE, OnUpdateAddFavorite) ON_COMMAND(ID_ADD_FAVORITE, OnAddFavorite) ON_UPDATE_COMMAND_UI(ID_LOGOUT, OnUpdateLogout) ON_COMMAND(ID_LOGOUT, OnLogout) ON_UPDATE_COMMAND_UI(ID_CHANGELIST_ACTIVATE, OnUpdateViewSwitch) ON_UPDATE_COMMAND_UI(ID_CLIENT_ACTIVATE, OnUpdateViewSwitch) ON_UPDATE_COMMAND_UI(ID_JOB_ACTIVATE, OnUpdateViewSwitch) ON_UPDATE_COMMAND_UI(ID_LABEL_ACTIVATE, OnUpdateViewSwitch) ON_UPDATE_COMMAND_UI(ID_USER_ACTIVATE, OnUpdateViewSwitch) ON_UPDATE_COMMAND_UI(ID_MRU_PCU1, OnUpdateMruPcu) ON_UPDATE_COMMAND_UI(ID_MRU_PCU2, OnUpdateMruPcu) ON_UPDATE_COMMAND_UI(ID_MRU_PCU3, OnUpdateMruPcu) ON_UPDATE_COMMAND_UI(ID_MRU_PCU4, OnUpdateMruPcu) ON_UPDATE_COMMAND_UI(ID_MRU_PCU5, OnUpdateMruPcu) ON_UPDATE_COMMAND_UI(ID_MRU_PCU6, OnUpdateMruPcu) ON_UPDATE_COMMAND_UI(ID_MRU_PCU7, OnUpdateMruPcu) ON_UPDATE_COMMAND_UI(ID_MRU_PCU8, OnUpdateMruPcu) ON_UPDATE_COMMAND_UI(ID_MRU_PCU9, OnUpdateMruPcu) ON_WM_ACTIVATE() ON_WM_ACTIVATEAPP() ON_WM_PARENTNOTIFY() ON_UPDATE_COMMAND_UI_RANGE(ID_TOOL_1, ID_TOOL_64, OnUpdateTool) ON_COMMAND_RANGE(ID_TOOL_1, ID_TOOL_64, OnTool) ON_UPDATE_COMMAND_UI_RANGE(ID_BKMK_1, ID_BKMK_128, OnUpdateBkMk) ON_COMMAND_RANGE(ID_BKMK_1, ID_BKMK_128, OnBkMk) ON_UPDATE_COMMAND_UI_RANGE(ID_FAV_1, ID_FAV_64, OnUpdateBkMk) ON_COMMAND_RANGE(ID_FAV_1, ID_FAV_64, OnFav) // Global help commands ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder) ON_COMMAND(ID_HELP, CFrameWnd::OnHelpFinder) // should be CFrameWnd::OnHelp ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnHelpFinder) // should be CFrameWnd::OnContextHelp ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder) ON_COMMAND(ID_HELP_GETTINGSTARTEDWITHP4WIN, OnGettingStartedWithP4win) ON_MESSAGE(WM_P4INFO, OnP4InitInfo ) ON_MESSAGE(WM_STATUSADD, OnStatusAdd ) ON_MESSAGE(WM_STATUSADDARRAY, OnStatusAddArray ) ON_MESSAGE(WM_STATUSCLEAR, OnStatusClear ) ON_MESSAGE(WM_CLIENTERROR, OnClientError ) ON_MESSAGE(WM_P4LISTOPSTAT, OnP4ListOp ) ON_MESSAGE(WM_P4FILEINFORMATION, OnP4FileInformation ) ON_MESSAGE(WM_P4DIFF, OnP4Diff ) ON_MESSAGE(WM_NEWCLIENT, OnNewClient ) ON_MESSAGE(WM_NEWUSER, OnNewUser ) ON_MESSAGE(WM_USERPSWDDLG, OnUserPasswordDlg ) ON_MESSAGE(WM_BROWSECALLBACK1, OnBrowseClientsCallBack) ON_MESSAGE(WM_P4DLGDESTROY, OnP4DialogDestroy) ON_MESSAGE(WM_HELPERAPP, OnP4HelperApp) ON_MESSAGE(WM_PERFORCE_OPTIONS, OnP4OptionsDlg) ON_MESSAGE(WM_ACTIVATEMODELESS, OnActivateModeless) ON_REGISTERED_MESSAGE(wmActivate, OnExternalActivation ) ON_REGISTERED_MESSAGE(wmSendcmd, OnExternalSendcmd ) ON_REGISTERED_MESSAGE(wmRplycmd, OnExternalRplycmd ) ON_REGISTERED_MESSAGE( WM_FINDREPLACE, OnFindReplace ) ON_COMMAND(ID_NEW, OnNew) ON_COMMAND(ID_FILE_REVISIONHISTORYCONT, OnFileRevisionhistory) ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnDropDown) END_MESSAGE_MAP() static UINT indicators[] = { ID_SEPARATOR, // status line indicator ID_CURRENTTASK, }; CWnd *MainFrameCWnd = 0; ///////////////////////////////////////////////////////////////////////////// // CMainFrame construction/destruction CMainFrame::CMainFrame() { m_FirstActivation=TRUE; m_FullRefreshRequired= TRUE; m_pStatusView= NULL; m_DoNotAutoPollCtr=0; m_Timer=0; m_LastUpdateTime=0; m_LastUpdateResult=UPDATE_SUCCESS; m_ClientError= FALSE; m_ModlessUp = FALSE; m_HasDisabled = FALSE; m_InPopUpMenu = FALSE; m_GetCliRootAndContinue = 0; m_Need2ExpandDepot = m_Need2Poll4Jobs = 0; m_P4QTree = m_P4TLV = 0; m_StatusBarWarnLevel = SV_MSG; m_CF_FILENAME = RegisterClipboardFormat(_T("FileName")); m_CF_FILENAMEW = RegisterClipboardFormat(_T("FileNameW")); m_hDevNames = NULL; m_hDevMode = NULL; m_rtMargin.top = m_rtMargin.bottom = m_rtMargin.right = m_rtMargin.left = 0; m_rtMinMargin.top = m_rtMinMargin.bottom = m_rtMinMargin.right = m_rtMinMargin.left = 0; m_bMetric = m_Quitting = FALSE; m_IsActive = m_GotInput = TRUE; m_MenuBmpCtr = 0; wmActivate= TheApp()->m_WM_ACTIVATE; wmSendcmd = TheApp()->m_WM_SENDCMD; wmRplycmd = TheApp()->m_WM_RPLYCMD; m_StatusUpdateInterval = (GET_P4REGPTR()->GetStatusUpdateInterval()+1)/2; m_pFRDlg = NULL; m_FindWhatFlags = FR_DOWN | FR_HIDEWHOLEWORD; m_FindStatusFlags = FR_HIDEWHOLEWORD; m_Need2RefreshOldChgs = TRUE; m_bNoRefresh = m_ShowOnlyNotInDepot = FALSE; m_DeltaUpdateTime = m_LabelUpdateTime = m_BranchUpdateTime = m_UserUpdateTime = m_ClientUpdateTime = m_JobUpdateTime = m_OldChgUpdateTime = 0; m_ReviewListClass = AfxRegisterWndClass(NULL); } CMainFrame::~CMainFrame() { delete m_pDropTgt; if (m_USER32dll) FreeLibrary(m_USER32dll); } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // Initialize the critical section one time only. if (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400) ) return -1; m_IconsInMenus = GET_P4REGPTR()->IconsInMenus(); m_osVer.dwOSVersionInfoSize= sizeof(OSVERSIONINFO); GetVersionEx(&m_osVer); // Determin number of display devices attached to the desktop // if there is only one monitor, we can check for resonable placements of dialogs, etc. // note that GetSystemMetrics(SM_CMONITORS) will return 0 for Win/95 & NT m_NbrDisplays = max(1, GetSystemMetrics(SM_CMONITORS)); // give all the views the needed pointers to each other SetWindowReferences(); // Set icon to use for small icons if ((m_osVer.dwMajorVersion < 5) || (m_osVer.dwMajorVersion == 5 && m_osVer.dwMinorVersion < 1)) SetIcon(AfxGetApp()->LoadIcon(IDI_ICONSM), FALSE); // Set the main menu style, etc. if (m_osVer.dwMajorVersion >= 5) { MENUINFO cmi; cmi.cbSize = sizeof(cmi); cmi.fMask = MIM_APPLYTOSUBMENUS | MIM_STYLE; cmi.dwStyle = MNS_CHECKORBMP; m_USER32dll = LoadLibrary(_T("USER32.dll")); if (m_USER32dll) { typedef int (PASCAL *SETMENUINFO)(HMENU hMenu, LPCMENUINFO lpcmi); SETMENUINFO setmenuinfo = (SETMENUINFO)GetProcAddress(m_USER32dll, "SetMenuInfo"); if (setmenuinfo) (setmenuinfo)(GetMenu()->m_hMenu, &cmi); } } // do the toolbar thing // Set the check button style for the different right-pane views // if (!m_wndToolBar.CreateEx(this))//|| { XTRACE(_T("Failed to create toolbar\n")); return -1; } m_wndToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS); m_wndToolBar.GetToolBarCtrl().SetImageList( TheApp()->GetToolBarImageList()); m_wndToolBar.GetToolBarCtrl().SetDisabledImageList( TheApp()->GetToolBarImageList()->GetDisabled()); m_wndToolBar.ModifyStyle(0, TBSTYLE_FLAT|TBSTYLE_TRANSPARENT); CSize sizeImage(18, 16); CSize sizeButton(18 + 7, 16 + 7); m_wndToolBar.SetSizes(sizeButton, sizeImage); const UINT ddStyle = TBSTYLE_DROPDOWN | BTNS_WHOLEDROPDOWN; // This struct contain one entry for each toolbar button // in the same order as the buttons are to appear // If you add items to this struct, you Must also // increase the dimensions of m_MenuIDbm & m_MenuBitmap // by the same amount static struct btn { UINT id; UINT style; int image; } btns[] = { {ID_FILE_GET, TBBS_BUTTON, CP4WinToolBarImageList::TBI_SYNC}, {ID_FILE_OPENEDIT, TBBS_BUTTON, CP4WinToolBarImageList::TBI_EDIT}, {ID_FILE_ADD, TBBS_BUTTON, CP4WinToolBarImageList::TBI_ADD}, {ID_SEPARATOR, TBSTYLE_SEP, 0}, {ID_FILE_OPENDELETE, TBBS_BUTTON, CP4WinToolBarImageList::TBI_DELETE}, {ID_SEPARATOR, TBSTYLE_SEP, 0}, {ID_FILE_REVERT, TBBS_BUTTON, CP4WinToolBarImageList::TBI_REVERT}, {ID_FILE_LOCK, TBBS_BUTTON, CP4WinToolBarImageList::TBI_LOCK}, {ID_FILE_UNLOCK, TBBS_BUTTON, CP4WinToolBarImageList::TBI_UNLOCK}, {ID_SEPARATOR, TBSTYLE_SEP, 0}, {ID_BOOKMARKS, ddStyle, CP4WinToolBarImageList::TBI_BOOKMARKS}, {ID_FAVORITES, ddStyle, CP4WinToolBarImageList::TBI_CONNECTIONS}, {ID_SEPARATOR, TBSTYLE_SEP, 0}, {ID_CHANGE_SUBMIT, TBBS_BUTTON, CP4WinToolBarImageList::TBI_SUBMIT}, {ID_SEPARATOR, TBSTYLE_SEP, 0}, {ID_FILE_REVISIONHISTORY,TBBS_BUTTON, CP4WinToolBarImageList::TBI_HISTORY}, {ID_FILE_DIFFHEAD, TBBS_BUTTON, CP4WinToolBarImageList::TBI_DIFF}, {ID_FILE_QUICKBROWSE, TBBS_BUTTON, CP4WinToolBarImageList::TBI_QUICKBROWSE}, {ID_FILE_QUICKEDIT, TBBS_BUTTON, CP4WinToolBarImageList::TBI_QUICKEDIT}, {ID_SEPARATOR, TBSTYLE_SEP, 0}, {ID_CHANGELIST_ACTIVATE,TBBS_CHECKBOX, CP4WinToolBarImageList::TBI_PENDING}, {ID_SUBMITTED_ACTIVATE, TBBS_CHECKBOX, CP4WinToolBarImageList::TBI_SUBMITTED}, {ID_BRANCH_ACTIVATE, TBBS_CHECKBOX, CP4WinToolBarImageList::TBI_BRANCH}, {ID_LABEL_ACTIVATE, TBBS_CHECKBOX, CP4WinToolBarImageList::TBI_LABEL}, {ID_CLIENT_ACTIVATE, TBBS_CHECKBOX, CP4WinToolBarImageList::TBI_CLIENT}, {ID_USER_ACTIVATE, TBBS_CHECKBOX, CP4WinToolBarImageList::TBI_USER}, {ID_JOB_ACTIVATE, TBBS_CHECKBOX, CP4WinToolBarImageList::TBI_JOB}, {ID_SEPARATOR, TBSTYLE_SEP, 0}, {ID_CANCEL_BUTTON, TBBS_BUTTON, CP4WinToolBarImageList::TBI_CANCELBUTTON}, {ID_PERFORCE_OPTIONS, TBBS_BUTTON, CP4WinToolBarImageList::TBI_SETTINGS}, {ID_PERFORCE_INFO, TBBS_BUTTON, CP4WinToolBarImageList::TBI_INFO}, }; const int buttonCount = sizeof(btns)/sizeof(btn); m_wndToolBar.SetButtons(NULL, buttonCount); MENUITEMINFO mii; CWindowDC dc(this); CDC memdc; memdc.CreateCompatibleDC(&dc); CBrush brush, brushDis; brush.CreateSysColorBrush(COLOR_MENU); brushDis.CreateStockObject(WHITE_BRUSH); RECT rect = {0, 0, 20, 16}; CImageList * disabledmenu = TheApp()->GetToolBarImageList()->GetDisabledMenu(); for(int b = 0; b < buttonCount; b++) { m_wndToolBar.SetButtonInfo(b, btns[b].id, btns[b].style, btns[b].image); if (btns[b].style != TBSTYLE_SEP && m_osVer.dwMajorVersion >= 5 && m_IconsInMenus) { HICON hIcon = TheApp()->GetToolBarImageList()->ExtractIcon(btns[b].image); HICON hIdis = disabledmenu ? disabledmenu->ExtractIcon(btns[b].image) : hIcon; if (hIcon) { // 'm_MenuBmpCtr' is the index of the next empty CBitmap // draw the icon on that CBitmap m_MenuBitmap[m_MenuBmpCtr].CreateCompatibleBitmap(&dc, 20, 16); CBitmap *poldbm = memdc.SelectObject(&m_MenuBitmap[m_MenuBmpCtr]); memdc.FillRect(&rect, &brush); ::DrawIconEx(memdc.m_hDC, 0, 0, hIcon, GetSystemMetrics(SM_CXMENUCHECK), // cx GetSystemMetrics(SM_CYMENUCHECK), // cy 0, brush, DI_NORMAL); // frame, brush, flags if (hIdis) { m_MenuBitDis[m_MenuBmpCtr].CreateBitmap(20, 16, 1, 1, NULL); memdc.SelectObject(&m_MenuBitDis[m_MenuBmpCtr]); memdc.FillRect(&rect, &brushDis); ::DrawIconEx(memdc.m_hDC, 0, 0, hIdis, GetSystemMetrics(SM_CXMENUCHECK), // cx GetSystemMetrics(SM_CYMENUCHECK), // cy 0, brush, DI_NORMAL); // frame, brush, flags m_HasDisabled = TRUE; } memdc.SelectObject(poldbm); // Attach the icon to the menu item // we do this here even tho some - but not all - // items will have the bitmap reattached by SetMenuIcon() memset(&mii, _T('\0'), sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_BITMAP; mii.hbmpItem = HBITMAP(m_MenuBitmap[m_MenuBmpCtr]); // Now save the associated menu ID in the corresponding 'm_MenuBmpCtr' UINT id; switch(btns[b].id) { case ID_BOOKMARKS: { m_MenuIDbm[m_MenuBmpCtr++] = 0xFFFFFFF1; CMenu* pSubMenu = GetMenu()->GetSubMenu(2); pSubMenu->SetMenuItemInfo(pSubMenu->GetMenuItemCount()-4, &mii, TRUE); continue; } case ID_FAVORITES: { m_MenuIDbm[m_MenuBmpCtr++] = 0xFFFFFFF2; CMenu* pSubMenu = GetMenu()->GetSubMenu(3); pSubMenu->SetMenuItemInfo(pSubMenu->GetMenuItemCount()-3, &mii, TRUE); continue; } case ID_CANCEL_BUTTON: id = ID_FILE_CANCEL; break; default: id = btns[b].id; } m_MenuIDbm[m_MenuBmpCtr++] = id; // Do the actual attach to the main menu GetMenu()->SetMenuItemInfo(id, &mii); // We have to also possibly attach it to // some submenu(s) if the ID occurs in // multiple dropdowns for (int n = 3; ++n < 10; ) GetMenu()->GetSubMenu(n)->SetMenuItemInfo(id, &mii); } } } // a 0 ID indicates the end of the in use 'm_MenuIDbm's m_MenuIDbm[m_MenuBmpCtr++] = 0; m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar, AFX_IDW_DOCKBAR_TOP); m_pDropTgt = new CTBDropTarget(); m_pDropTgt->Register(&m_wndToolBar); if (!(GET_P4REGPTR( )->ShowToolBar())) SendMessage(WM_COMMAND, ID_VIEW_TOOLBAR, 0); // Add remaining menu icons // if (m_osVer.dwMajorVersion >= 5 && m_IconsInMenus) { memset(&mii, _T('\0'), sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_BITMAP; mii.hbmpItem = HBMMENU_POPUP_CLOSE; GetMenu()->SetMenuItemInfo(ID_APP_EXIT, &mii); } // now the status bar stuff // if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { XTRACE(_T("Failed to create status bar\n")); return -1; } // Load the Tools Menu // LoadToolsMenu(); // Load the Bookmarks Menu // LoadBkMkMenu(); // Load the Favorites Menu // LoadFavMenu(); // Set the active views (depot on the left, pending changelists // on the right) and their captions. // OnViewChanges(); int iEntire = GET_P4REGPTR()->ShowEntireDepot(); SetDepotCaption( iEntire ); SetActiveView(m_pDepotView); MainFrameCWnd = this; // Vista sucks and won't let us write to HKEY_LOCAL_MACHINE // unless we have elevated privilages. But those writes // happen in the p4api and don't return status. So write // a dummy key for testing and report any failure. GET_P4REGPTR()->TestRegWrite2HKLM(); // This timer is here to support auto-update and miscellaneous // tasks. Will result in OnTimer() being called every .2 secs. // The interval is a compromise between // 1) wasting lots of CPU in OnTimer and // 2) having a fairly quick response when one of the right-side // panes needs to be loaded for the first time or a flyover // message needs to go away // m_Timer= SetTimer( UPDATE_TIMER, 200, NULL); TCHAR cmdLine[] = _T("P4V.exe"); m_P4Vver = GetExeVersion(cmdLine); m_P4QTree = m_P4TLV = m_P4Vver >= 20042 ? 1 : 0; if (!m_P4QTree) GetMenu()->DeleteMenu(ID_FILE_REVISIONTREE, MF_BYCOMMAND); if (!m_P4TLV) GetMenu()->DeleteMenu(ID_FILE_ANNOTATIONS, MF_BYCOMMAND); #if 0 else { int j = GetMenu()->GetSubMenu(0)->GetMenuItemCount(); for (int i=-1; ++i < j; ) { if (GetMenu()->GetSubMenu(0)->GetMenuItemID(i) == ID_FILE_AUTOEDIT) GetMenu()->GetSubMenu(0)->DeleteMenu(i+1, MF_BYPOSITION); } } #endif if (!GET_P4REGPTR()->GetEnableSubChgIntegFilter()) GetMenu()->DeleteMenu(ID_JOB_SETFILEFILTERINTEG, MF_BYCOMMAND); // are we running only to show a rev hist dialog box? if (!TheApp()->m_RevHistPath.IsEmpty()) { // Run p4 client to get the server version CCmd_Describe *pCmd = new CCmd_Describe; pCmd->Init( NULL, RUN_SYNC ); BOOL cmdStarted= pCmd->Run( P4CLIENT_SPEC, GET_P4REGPTR()->GetP4Client() ); if(cmdStarted && !pCmd->GetError()) { // since we have the client spec, set Client root in app TheApp()->Set_m_ClientRoot(TheApp()->GetClientSpecField( _T("Root"), pCmd->GetDescription())); if (GET_SERVERLEVEL() >= 22) TheApp()->Set_m_ClientSubOpts(TheApp()->GetClientSpecField( _T("SubmitOptions"), pCmd->GetDescription())); } // now run the rev hist command OnFileRevisionhistory(); delete pCmd; } else if (!TheApp()->m_FileInfoPath.IsEmpty()) { m_StringList.RemoveAll(); m_StringList.AddHead(TheApp()->m_FileInfoPath); CCmd_Opened *pCmd= new CCmd_Opened; pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK, 0); pCmd->SetAlternateReplyMsg( WM_P4FILEINFORMATION ); if( pCmd->Run( TRUE, FALSE, -1, &m_StringList ) ) UpdateStatus( LoadStringResource(IDS_REQUESTING_FILE_INFORMATION) ); else { delete pCmd; ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); } } else if (!TheApp()->m_DiffPath.IsEmpty()) { // Run p4 client to get the server version CCmd_Describe *pCmd1 = new CCmd_Describe; pCmd1->Init( NULL, RUN_SYNC ); BOOL cmdStarted= pCmd1->Run( P4CLIENT_SPEC, GET_P4REGPTR()->GetP4Client() ); if(cmdStarted && !pCmd1->GetError()) { // since we have the client spec, set Client root in app TheApp()->Set_m_ClientRoot(TheApp()->GetClientSpecField( _T("Root"), pCmd1->GetDescription())); if (GET_SERVERLEVEL() >= 22) TheApp()->Set_m_ClientSubOpts(TheApp()->GetClientSpecField( _T("SubmitOptions"), pCmd1->GetDescription())); } // now run the diff command m_StringList.RemoveAll(); m_StringList.AddHead(LPCTSTR(TheApp()->m_DiffPath)); CCmd_Diff *pCmd2= new CCmd_Diff; pCmd2->Init( m_hWnd, RUN_ASYNC); if( pCmd2->Run( &m_StringList, _T("-f"), '\0', TRUE ) ) MainFrame()->UpdateStatus( LoadStringResource(IDS_DIFFING_FILE) ); else { delete pCmd2; CString txt; txt.FormatMessage(IDS_CANTDIFF_s, TheApp()->m_DiffPath); AfxMessageBox( txt, MB_ICONSTOP ); ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); } } else if (!TheApp()->m_ToolsImportPath.IsEmpty()) { CString errorTxt; ImportTools(&(TheApp()->m_ToolsImportPath), &errorTxt); if(errorTxt.GetLength() > 0) AfxMessageBox(errorTxt, MB_ICONSTOP); ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); } #if 0 else if (GET_P4REGPTR()->Is1stRun()) { // this is the 1st time P4Win has been run on this machine // so don't fire an update; wait until after the dialog // asking 1st-timer info has been shown. } #endif else // normal operation { // Run the initial update of depot and changelist panes UpdateDepotandChangeViews(NO_REDRILL); m_Need2ExpandDepot = GET_P4REGPTR()->GetExpandFlag(); } return 0; } void CMainFrame::OnFileRevisionhistory() { // split off revision number, if any int i, rev = -1; CString itemStr= TheApp()->m_RevHistPath; if ((i = itemStr.Find(_T('#'))) != -1) { rev = _ttoi(itemStr.Right(itemStr.GetLength() - i - 1)); if (!rev) rev = -1; itemStr = itemStr.Left(i); } CString depotPath = itemStr; if (depotPath.GetAt(1) == _T(':')) // local syntax must be converted to depot syntax { CCmd_Where *pCmd1 = new CCmd_Where; pCmd1->Init(NULL, RUN_SYNC); if ( pCmd1->Run(itemStr) && !pCmd1->GetError() && pCmd1->GetDepotFiles()->GetCount() ) { depotPath = pCmd1->GetDepotSyntax(); } delete pCmd1; } // initialize the history command (which is p4 filelog) CCmd_History *pCmd= new CCmd_History; pCmd->Init(GetDepotWnd(), RUN_ASYNC); pCmd->SetCallingWnd(m_hWnd); pCmd->SetInitialRev(rev, depotPath); // handle any -m flag if (TheApp()->m_RevHistCount) { pCmd->OverrideFetchHistCount(TheApp()->m_RevHistCount); pCmd->OverrideFetchCompleteHist(0); pCmd->SetEnableShowIntegs(FALSE); TheApp()->m_RevHistEnableShowIntegs = FALSE; } // Run the filelog command to get the history info if( pCmd->Run( LPCTSTR(itemStr)) ) { UpdateStatus( LoadStringResource(IDS_REQUESTING_HISTORY) ); } else { delete pCmd; CString txt; txt.FormatMessage(IDS_CANTRUNREVHIST_s, TheApp()->m_RevHistPath); AfxMessageBox( txt, MB_ICONSTOP ); ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); } } LRESULT CMainFrame::OnP4FileInformation( WPARAM wParam, LPARAM lParam ) { CCmd_Opened *pCmd= (CCmd_Opened *) wParam; m_StringList.RemoveAll(); if (pCmd->GetError()) { CString txt; txt.FormatMessage(IDS_CANTRUNFILEINFO_s, TheApp()->m_FileInfoPath); AfxMessageBox( txt, MB_ICONSTOP ); } else { CString thisuser=GET_P4REGPTR()->GetMyID(); // Initialize the file info dialog CFileInfoDlg dlg; dlg.m_DepotPath = dlg.m_ClientPath = TheApp()->m_FileInfoPath; int key= pCmd->GetServerKey(); CCmd_Fstat *pCmd2= new CCmd_Fstat; pCmd2->Init(NULL, RUN_SYNC, HOLD_LOCK, key); if (!IsQuitting()) { MSG msg; while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { // get out if app is terminating // if ( msg.message == WM_QUIT ) goto CantGetFStat; TranslateMessage(&msg); DispatchMessage(&msg); } } pCmd2->SetIncludeAddedFiles( TRUE ); if( pCmd2->Run( FALSE, TheApp()->m_FileInfoPath, 0 ) && !pCmd2->GetError() ) { CObList *list = pCmd2->GetFileList ( ); ASSERT_KINDOF( CObList, list ); ASSERT( list->GetCount() <= 1 ); POSITION pos = list->GetHeadPosition( ); if( pos != NULL ) { CP4FileStats *stats = ( CP4FileStats * )list->GetNext( pos ); ASSERT_KINDOF( CP4FileStats, stats ); dlg.m_DepotPath = stats->GetFullDepotPath(); if(dlg.m_DepotPath.GetLength() == 0) dlg.m_DepotPath= LoadStringResource(IDS_NOT_IN_CLIENT_VIEW); dlg.m_ClientPath = stats->GetFullClientPath( ); if(dlg.m_ClientPath.GetLength() == 0) dlg.m_ClientPath= LoadStringResource(IDS_NOT_IN_CLIENT_VIEW); dlg.m_HeadRev.Format(_T("%ld"), stats->GetHeadRev()); dlg.m_HaveRev.Format(_T("%ld"), stats->GetHaveRev()); dlg.m_HeadAction= stats->GetActionStr(stats->GetHeadAction()); dlg.m_HeadChange.Format(_T("%ld"), stats->GetHeadChangeNum()); dlg.m_HeadType= stats->GetHeadType(); dlg.m_ModTime= stats->GetFormattedHeadTime(); dlg.m_FileSize= stats->GetFileSize(); // Check for open/lock by this user if(stats->IsMyLock()) dlg.m_LockedBy= thisuser; delete stats; } else dlg.m_ClientPath= LoadStringResource(IDS_NOT_IN_CLIENT_VIEW); } CantGetFStat: RELEASE_SERVER_LOCK(key); delete pCmd2; CObList *list= pCmd->GetList(); ASSERT_KINDOF(CObList, list); POSITION pos= list->GetHeadPosition(); while(pos != NULL) { CP4FileStats *fs= (CP4FileStats *) list->GetNext(pos); CString str; CString strUser; CString strChange; CString strAction; if( fs->GetOpenChangeNum() == 0 ) strChange= LoadStringResource(IDS_DEFAULT_CHANGE); else strChange.FormatMessage(IDS_CHANGE_n, fs->GetOpenChangeNum()); strUser= fs->GetOtherUsers(); if( fs->IsMyOpen() && strUser.IsEmpty() ) { strUser= thisuser; strAction= fs->GetActionStr(fs->GetMyOpenAction()); } else strAction= fs->GetActionStr(fs->GetOtherOpenAction()); str.Format(_T("%s - %s (%s)"), strUser, strChange, strAction); if( fs->IsOtherLock() ) str += " " + LoadStringResource(IDS_STAR_LOCKED); dlg.m_StrList.AddHead( str ); delete fs; } // Display the info SET_APP_HALTED(TRUE); dlg.DoModal(); SET_APP_HALTED(FALSE); } UpdateStatus(_T("")); delete pCmd; ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); return 0; } LRESULT CMainFrame::OnP4Diff(WPARAM wParam, LPARAM lParam) { CCmd_Diff *pCmd= (CCmd_Diff *) wParam; if( pCmd->GetDiffErrCount() ) { AfxMessageBox( pCmd->GetDiffErrBuf(), MB_ICONSTOP ); } else if( !pCmd->GetError() && pCmd->GetDiffRunCount() == 0) { if (pCmd->GetDiffNbrFiles() == 1) { CString msg; msg.FormatMessage(IDS_CLIENTFILE_s_DOESNOTDIFFER, pCmd->GetDiffFileName()); AfxMessageBox(msg, MB_OK); } else if (pCmd->GetDiffErrCount() == 0) AfxMessageBox(LoadStringResource(IDS_NONE_OF_THE_SELECTED_CLIENT_FILES_DIFFER), MB_OK); } else if (pCmd->GetError()) { CString txt; txt.FormatMessage(IDS_CANTDIFF_s, TheApp()->m_DiffPath); AfxMessageBox( txt, MB_ICONSTOP ); } ClearStatus(); delete pCmd; ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); return 0; } /* _________________________________________________________________ Create a static splitter with 2 horizontal rows, the bottom for the output (or 'status'), the top to be divided 2 ways, the left for the depot, the right for all the others (changelist, branch, etc.). okay, ideally, i should have a dockable window for the output (still not supported by mfc), and the rest... hmm. maybe MDI? all dockable? dynamically split? ah, the choices... and why does the left always have to be the depot? and why not have one for the client workspace? _________________________________________________________________ */ BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext) { if ( !m_wndHSplitter.CreateStatic( this, 2, 1, WS_CHILD | WS_VISIBLE, AFX_IDW_PANE_FIRST ) ) return FALSE; // Lowest splitter pane contains status view m_wndHSplitter.CreateView( 1,0, RUNTIME_CLASS(CStatusView), CSize(50,10), pContext ); // Create a static splitter, w/ 2 columns, in the top pane m_wndVSplitter.CreateStatic( &m_wndHSplitter, 1, 2, WS_CHILD | WS_VISIBLE | WS_BORDER, // intuitively, WS_BORDER is mandatory (yeah, right) m_wndHSplitter.IdFromRowCol(0,0) ); m_wndVSplitter.CreateView( 0,0, RUNTIME_CLASS(CDepotView), CSize(50,10), pContext ); m_wndVSplitter.CreateView( 0, 1, RUNTIME_CLASS(CDeltaView), CSize(50,10), pContext ); m_pStatusView= (CStatusView *) m_wndHSplitter.GetPane(1,0); m_pDepotView=(CDepotView *) m_wndVSplitter.GetPane(0,0); m_pDeltaView= (CDeltaView *) m_wndVSplitter.GetPane(0,1); m_currentTab=0; m_pRightView = m_pDeltaView; // Right pane also has a few views that are swapped in DWORD style=AFX_WS_DEFAULT_VIEW; style &= ~WS_VISIBLE; m_pLabelView= new CLabelView; m_pLabelView->Create(NULL, NULL, style, rectDefault, &m_wndVSplitter, MAKEID(1), pContext); m_pBranchView= new CBranchView; m_pBranchView->Create(NULL, NULL, style, rectDefault, &m_wndVSplitter, MAKEID(2), pContext); m_pUserView= new CUserView; m_pUserView->Create(NULL, NULL, style, rectDefault, &m_wndVSplitter, MAKEID(3), pContext); m_pClientView= new CClientView; m_pClientView->Create(NULL, NULL, style, rectDefault, &m_wndVSplitter, MAKEID(4), pContext); m_pJobView= new CJobView; m_pJobView->Create(NULL, NULL, style, rectDefault, &m_wndVSplitter, MAKEID(5), pContext); m_pOldChgView= new COldChgView; m_pOldChgView->Create(NULL, NULL, style, rectDefault, &m_wndVSplitter, MAKEID(6), pContext); return TRUE; } void CMainFrame::SetWindowReferences() { // Make sure the various views know where each other are, for msg routing m_pDepotView->SetBranchWnd(m_pBranchView); m_pDepotView->SetChangeWnd(m_pDeltaView); m_pDepotView->SetOldChgWnd(m_pOldChgView); m_pDepotView->SetLabelWnd(m_pLabelView); m_pDepotView->SetClientWnd(m_pClientView); m_pDepotView->SetUserWnd(m_pUserView); m_pDepotView->SetJobWnd(m_pJobView); m_pBranchView->SetDepotWnd(m_pDepotView); m_pBranchView->SetChangeWnd(m_pDeltaView); m_pClientView->SetDepotWnd(m_pDepotView); m_pDeltaView->SetDepotWnd(m_pDepotView); m_pDeltaView->SetJobWnd(m_pJobView); m_pDeltaView->SetOldChgWnd(m_pOldChgView); m_pJobView->SetDepotWnd(m_pDepotView); m_pJobView->SetChangeWnd(m_pDeltaView); m_pLabelView->SetDepotWnd(m_pDepotView); m_pOldChgView->SetDepotWnd(m_pDepotView); m_pOldChgView->SetJobWnd(m_pJobView); m_pUserView->SetDepotWnd(m_pDepotView); m_pUserView->SetClientWnd(m_pClientView); m_pUserView->SetBranchWnd(m_pBranchView); m_pUserView->SetLabelWnd(m_pLabelView); } void CMainFrame::SetRightSplitter(int tabNumber) { ASSERT(IsWindow(m_wndToolBar.m_hWnd)); // Is toolbar a window yet? CToolBarCtrl& toolbar= (CToolBarCtrl&) m_wndToolBar.GetToolBarCtrl( ); CMenu *pMenu= GetMenu(); ASSERT(pMenu != NULL); RECT rect; m_pRightView->GetClientRect(&rect); m_pRightView->SetDlgCtrlID( MAKEID(m_currentTab)); m_pRightView->ShowWindow(SW_HIDE); switch(m_currentTab) { case 0: m_pDeltaView->GetTreeCtrl().ShowWindow(SW_HIDE); toolbar.CheckButton(ID_CHANGELIST_ACTIVATE, FALSE); break; case 1: m_pLabelView->GetListCtrl().ShowWindow(SW_HIDE); toolbar.CheckButton(ID_LABEL_ACTIVATE, FALSE); break; case 2: m_pBranchView->GetListCtrl().ShowWindow(SW_HIDE); toolbar.CheckButton(ID_BRANCH_ACTIVATE, FALSE); break; case 3: m_pUserView->GetListCtrl().ShowWindow(SW_HIDE); toolbar.CheckButton(ID_USER_ACTIVATE, FALSE); break; case 4: m_pClientView->GetListCtrl().ShowWindow(SW_HIDE); toolbar.CheckButton(ID_CLIENT_ACTIVATE, FALSE); break; case 5: m_pJobView->GetListCtrl().ShowWindow(SW_HIDE); toolbar.CheckButton(ID_JOB_ACTIVATE, FALSE); break; case 6: m_pOldChgView->GetListCtrl().ShowWindow(SW_HIDE); toolbar.CheckButton(ID_SUBMITTED_ACTIVATE, FALSE); break; default: ASSERT(0); } m_currentTab=tabNumber; switch(tabNumber) { case 0: m_pRightView = m_pDeltaView; m_pDeltaView->GetTreeCtrl().ShowWindow(SW_SHOW); toolbar.CheckButton(ID_CHANGELIST_ACTIVATE, TRUE); break; case 1: m_pRightView = m_pLabelView; m_pLabelView->GetListCtrl().ShowWindow(SW_SHOW); toolbar.CheckButton(ID_LABEL_ACTIVATE, TRUE); break; case 2: m_pRightView = m_pBranchView; m_pBranchView->GetListCtrl().ShowWindow(SW_SHOW); toolbar.CheckButton(ID_BRANCH_ACTIVATE, TRUE); break; case 3: m_pRightView = m_pUserView; m_pUserView->GetListCtrl().ShowWindow(SW_SHOW); toolbar.CheckButton(ID_USER_ACTIVATE, TRUE); break; case 4: m_pRightView = m_pClientView; m_pClientView->GetListCtrl().ShowWindow(SW_SHOW); toolbar.CheckButton(ID_CLIENT_ACTIVATE, TRUE); break; case 5: m_pRightView = m_pJobView; m_pJobView->GetListCtrl().ShowWindow(SW_SHOW); toolbar.CheckButton(ID_JOB_ACTIVATE, TRUE); break; case 6: m_pRightView = m_pOldChgView; m_pOldChgView->GetListCtrl().ShowWindow(SW_SHOW); toolbar.CheckButton(ID_SUBMITTED_ACTIVATE, TRUE); break; default: ASSERT(0); break; } m_pRightView->SetDlgCtrlID(m_wndVSplitter.IdFromRowCol(0,1)); m_pRightView->ShowWindow(SW_SHOW); m_pRightView->SendMessage(WM_ACTIVATE, WA_ACTIVE, NULL); m_wndVSplitter.RecalcLayout(); m_wndVSplitter.SetActivePane(0,1,NULL); m_pRightView->PostMessage(WM_ACTIVATEMODELESS, WA_ACTIVE, NULL); } int CMainFrame::GetRightSplitter() { return m_currentTab; } BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { // Lose the document title, since we dont have a persistent doc cs.style &= ~FWS_ADDTOTITLE ; return CFrameWnd::PreCreateWindow(cs); } // Memory leak workaround: CStatusbar and CString join forces to leak memory // unless panetext is set back to " ". So do that in OnDestroy() to avoid // spurious mem leak messages. Problem is specific to VC 4.2 void CMainFrame::UpdateStatus(LPCTSTR txt, BOOL forceRedraw) { if (!this) // To avoid crashing if called while quitting return; CString msg; m_bStatusBarWarnMsg = FALSE; if (*txt) msg = txt; else if (m_StatusBarWarnLevel) { m_bStatusBarWarnMsg = TRUE; if(m_StatusBarWarnLevel == SV_ERROR) msg = LoadStringResource(IDS_ERROR); else msg = LoadStringResource(IDS_WARNING); } else msg.Empty(); m_wndStatusBar.SetPaneText(1, msg, TRUE); if(forceRedraw) m_wndStatusBar.RedrawWindow(); } void CMainFrame::SetStatusBarLevel(StatusView level) { if (TheApp()->m_RunClientWizOnly) return; m_StatusBarWarnLevel = level ? max(m_StatusBarWarnLevel, level) : SV_MSG; m_wndStatusBar.GetStatusBarCtrl( ).SetBkColor(level ? RGB(0xFF,0x90,0x90) : CLR_DEFAULT); if (!level && m_bStatusBarWarnMsg) UpdateStatus(_T(""), TRUE); } ///////////////////////////////////////////////////////////////////// // Status window updates: // Use AddToStatusLog to append a line to the status view // Use ClearStatusLog to clear the status view // Post WM_STATUSADD to run OnStatusAdd to append from outside main thread // WM_ADDTOSTATUS will delete wParam, a (char *) // Post WM_STATUSCLEAR to run OnStatusClear to run ClearStatusLog void CMainFrame::AddToStatusLog( LPCTSTR txt, StatusView level, bool showDialog) { ASSERT( level != SV_DEBUG || !showDialog ); #ifndef _DEBUG if ( level != SV_DEBUG ) #endif m_pStatusView->AddItem( txt, level, showDialog ); } void CMainFrame::AddToStatusLog( CStringArray *pArray, StatusView level, bool showDialog) { ASSERT( level != SV_DEBUG || !showDialog ); BOOL showIt= ( level != SV_DEBUG ); #ifdef _DEBUG showIt=TRUE; #endif if( showIt && pArray->GetSize() ) { // Prevent the status view from flickering by turning off // redraws during the data storm m_pStatusView->SetRedraw(FALSE); int i; for( i= 0; i < pArray->GetUpperBound(); i++ ) m_pStatusView->AddItem( pArray->GetAt(i), level, showDialog, FALSE ); // Add the last item forcing it to be visible m_pStatusView->AddItem( pArray->GetAt(i), level, showDialog, TRUE ); m_pStatusView->SetRedraw(TRUE); m_pStatusView->RedrawWindow(); } } void CMainFrame::ClearStatusLog() { m_pStatusView->Clear(); } LRESULT CMainFrame::OnStatusAdd(WPARAM wParam, LPARAM lParam) { LPTSTR txt= (LPTSTR) wParam; AddToStatusLog( txt, (StatusView)LOWORD(lParam), HIWORD(lParam) != 0); delete [] txt; return 0; } LRESULT CMainFrame::OnStatusAddArray(WPARAM wParam, LPARAM lParam) { CStringArray *pArray= (CStringArray *) wParam; ASSERT_KINDOF( CStringArray, pArray); AddToStatusLog( pArray, (StatusView)LOWORD(lParam), HIWORD(lParam) != 0); delete pArray; return 0; } LRESULT CMainFrame::OnStatusClear(WPARAM wParam, LPARAM lParam) { ClearStatusLog(); return 0; } void CMainFrame::OnDestroy() { // Release resources used by the critical section object. DeleteCriticalSection(&CriticalSection); UpdateStatus(_T(" ")); CFrameWnd::OnDestroy(); } ///////////////////////////////////////////////////////////////////////////// // CMainFrame diagnostics #ifdef _DEBUG void CMainFrame::AssertValid() const { CFrameWnd::AssertValid(); } void CMainFrame::Dump(CDumpContext& dc) const { CFrameWnd::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CMainFrame message handlers for menu items that are almost always // accessible void CMainFrame::EditConnectionParam( CCmdUI* pCmdUI, const CString &value ) { CString txt; txt.FormatMessage(IDS_AmpEDIT_s, value); txt += _T("..."); pCmdUI->SetText ( txt ); pCmdUI->Enable( !SERVER_BUSY() && !value.IsEmpty( ) /*and user is allow to edit the user or client! (get the owner) */ /*and no modless dialog box is up */ && !IsModlessUp() ); } void CMainFrame::OnUpdateJobNew(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY() && !m_pJobView->GetListCtrl().IsEditInProgress()); } void CMainFrame::OnJobNew() { m_pJobView->SendMessage( WM_COMMAND, MAKEWPARAM(ID_JOB_NEW, 0), 0 ); } void CMainFrame::OnUpdateUserNew(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY() && !IsModlessUp() && !m_pUserView->GetListCtrl().IsEditInProgress()); } void CMainFrame::OnUserNew() { m_pUserView->SendMessage( WM_COMMAND, MAKEWPARAM(ID_USER_CREATENEWUSER, 0), 0 ); } void CMainFrame::OnUpdateBranchNew(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY() && !IsModlessUp() && !m_pBranchView->GetListCtrl().IsEditInProgress()); } void CMainFrame::OnBranchNew() { m_pBranchView->SendMessage( WM_COMMAND, MAKEWPARAM(ID_BRANCH_NEW, 0), 0 ); } void CMainFrame::OnUpdateLabelNew(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY() && !m_pLabelView->GetListCtrl().IsEditInProgress()); } void CMainFrame::OnLabelNew() { m_pLabelView->SendMessage( WM_COMMAND, MAKEWPARAM(ID_LABEL_NEW, 0), 0 ); } void CMainFrame::OnUpdateClientEditmy(CCmdUI* pCmdUI) { EditConnectionParam( pCmdUI, TruncateString(GET_P4REGPTR()->GetP4Client(), 50) ); if (m_pClientView->GetListCtrl().IsEditInProgress()) pCmdUI->Enable(FALSE); } void CMainFrame::OnClientEditmy() { m_pClientView->GetListCtrl().OnClientEditmy(); } BOOL CMainFrame::ClientSpecSwitch(CString switchTo, BOOL bAlways /*=FALSE*/, BOOL portWasChangedAlso /*= FALSE*/) { return m_pClientView->GetListCtrl().ClientSpecSwitch(switchTo, bAlways, portWasChangedAlso); } void CMainFrame::OnUpdateUserEditmy(CCmdUI* pCmdUI) { EditConnectionParam( pCmdUI, TruncateString(GET_P4REGPTR()->GetP4User(), 50) ); if (m_pUserView->GetListCtrl().IsEditInProgress()) pCmdUI->Enable(FALSE); } void CMainFrame::OnUserEditmy() { m_pUserView->GetListCtrl().OnUserEditmy(); } void CMainFrame::OnUpdateUserPassword(CCmdUI* pCmdUI) { m_pUserView->GetListCtrl().OnUpdateUserPassword(pCmdUI, GET_P4REGPTR()->GetP4User() ); } void CMainFrame::OnUserPassword() { m_pUserView->GetListCtrl().OnUserPassword(); } void CMainFrame::OnUpdateDescribeChg(CCmdUI* pCmdUI) { pCmdUI->Enable( !SERVER_BUSY( ) ); } void CMainFrame::OnDescribeChg() { m_pOldChgView->GetListCtrl().OnDescribeChg(); } void CMainFrame::OnUpdateDescribeJob(CCmdUI* pCmdUI) { pCmdUI->Enable( !SERVER_BUSY( ) ); } void CMainFrame::OnDescribeJob() { m_pJobView->GetListCtrl().OnDescribeJob(); } void CMainFrame::EditJobSpec(CString *jobname) { m_pJobView->GetListCtrl().EditTheSpec(jobname); } void CMainFrame::OnNew() { switch(m_currentTab) { case 0: m_pDeltaView->GetTreeCtrl().CallOnChangeNew(); break; case 1: OnLabelNew(); break; case 2: OnBranchNew(); break; case 3: OnUserNew(); break; case 4: OnClientspecNew(); break; case 5: OnJobNew(); break; case 6: MessageBeep(0); break; default: ASSERT(0); } } //////////////////////////////////////////////////////////////////////////// void CMainFrame::OnUpdateStatus(CCmdUI* pCmdUI) { pCmdUI->Enable(); } LRESULT CMainFrame::OnExternalActivation(WPARAM wParam, LPARAM lParam) { // Another p4win instance just pulled our chain. Make sure we arent // iconic, then active forground popup, if any if(IsIconic()) ShowWindow(SW_RESTORE); CWnd *pWnd=GetLastActivePopup(); pWnd->SetForegroundWindow(); return 0; } LRESULT CMainFrame::OnExternalSendcmd(WPARAM wParam, LPARAM lParam) { // Another p4win instance wants us to do something // For now, we only position our depot to a string if (SERVER_BUSY()) // if we are busy, we can't position the depot return 0; HANDLE hMapFile = OpenFileMapping( FILE_MAP_ALL_ACCESS, // read/write access FALSE, // do not inherit the name P4WIN_SHARED_MEMORY_NAME); // name of mapping object if (hMapFile != NULL) { EXPANDPATH *ep = (EXPANDPATH *)MapViewOfFile(hMapFile, // handle to mapping object FILE_MAP_ALL_ACCESS,0, 0, P4WIN_SHARED_MEMORY_SIZE); if (ep != NULL) { if (!ep->flag) { TCHAR *port = ep->buf + ep->port; TCHAR *client=ep->buf + ep->client; TCHAR *user = ep->buf + ep->user; TCHAR *path = ep->buf + ep->path; if (!lstrcmp(*port ? port : GET_P4REGPTR()->GetP4Port(TRUE), GET_P4REGPTR()->GetP4Port()) && !lstrcmp(client, GET_P4REGPTR()->GetP4Client()) && !lstrcmp(user, GET_P4REGPTR()->GetP4User()) && !ep->flag) { ep->flag = 1; if(IsIconic()) ShowWindow(SW_RESTORE); CWnd *pWnd=GetLastActivePopup(); pWnd->SetForegroundWindow(); TheApp()->m_ExpandPath = path; TheApp()->m_bFindInChg = TRUE; m_Need2ExpandDepot = TRUE; UpdateDepotandChangeViews(NO_REDRILL); } } UnmapViewOfFile(ep); } CloseHandle(hMapFile); } return 0; } LRESULT CMainFrame::OnExternalRplycmd(WPARAM wParam, LPARAM lParam) { // Another p4win instance replied to our request // for now this is a no-op #if 0 if(IsIconic()) ShowWindow(SW_RESTORE); CWnd *pWnd=GetLastActivePopup(); pWnd->SetForegroundWindow(); #endif return 0; } void CMainFrame::OnSize(UINT nType, int cx, int cy) { if(m_pStatusView != NULL && IsWindow(m_pStatusView->m_hWnd)) { // Let the zimbabwe splitter know that this is a resize event, not // a splitter adjustment via the splitter bar m_wndHSplitter.SetSizing(TRUE); CFrameWnd::OnSize(nType, cx, cy); m_wndHSplitter.SetSizing(FALSE); // Make sure the splitter is displayed per new rowinfo m_wndHSplitter.Resized(); } else CFrameWnd::OnSize(nType, cx, cy); } void CMainFrame::UpdateCaption(BOOL updatePCU/* = TRUE*/) { CString txt; if (updatePCU) { // save port-client-user info for use in MRU menu CMenu *pMenu= GetMenu(); if (pMenu != NULL) { LPCTSTR p = GET_P4REGPTR()->GetP4Port(); LPCTSTR c = GET_P4REGPTR()->GetP4Client(); LPCTSTR u = GET_P4REGPTR()->GetP4User(); if (p && *p && c && *c && u && *u) { LPCTSTR q; for (q = p; *++q; ) { if (*q == _T(' ')) break; } txt.Format(*q ? _T("\"%s\" %s %s") : _T("%s %s %s"), p, c, u); GET_P4REGPTR()->AddMRUPcu( txt ); } loadMRUPcuMenuItems(pMenu); } } // inhouse, we want the caption bar to show the port, client and user, // since we usually have lots of different servers and clients for // testing, etc. customers don't really need it, although i suppose // they too could set the registry key. // if(GET_P4REGPTR()->ShowConnectSettings()) { CString port = GET_P4REGPTR()->GetP4Port(); if (GET_P4REGPTR()->ShowConnectPort1st()) { int i; if ((i = port.Find(_T(':'))) != -1) port = port.Mid(i+1) + _T(':') + port.Left(i); } txt.FormatMessage(IDS_PERFORCE_PORT_s_CLIENT_s_USER_s, port, GET_P4REGPTR()->GetP4Client(), GET_P4REGPTR()->GetP4User() ); } else { // Get active connection parameters. If any one of the 3 differs // from the permanent value, report in caption. // CString tempUser= GET_P4REGPTR()->GetP4User(FALSE); if( tempUser.GetLength() && tempUser.Compare(GET_P4REGPTR()->GetP4User(TRUE)) != 0) tempUser.FormatMessage(IDS_USER_s, tempUser); else tempUser.Empty(); CString tempClient= GET_P4REGPTR()->GetP4Client(FALSE); if( tempClient.GetLength() && tempClient.Compare(GET_P4REGPTR()->GetP4Client(TRUE)) != 0) tempClient.FormatMessage(IDS_CLIENT_s, tempClient); else tempClient.Empty(); CString tempPort= GET_P4REGPTR()->GetP4Port(FALSE); if( tempPort.GetLength() && tempPort.Compare(GET_P4REGPTR()->GetP4Port(TRUE)) != 0) tempPort.FormatMessage(IDS_PORT_s, tempPort); else tempPort.Empty(); txt.Empty(); txt.FormatMessage(IDS_PERFORCE_s_s_s, tempPort, tempClient, tempUser); txt.TrimRight(); } SetWindowText(txt); } void CMainFrame::OnPerforceOptions( BOOL m_ShowOptionsDlg, BOOL portWasChanged /* = FALSE */, int contextPage /*=0*/, int intialPage /*=0*/ ) { // Record whether entire depot was being displayed or file types shown BOOL wasShowDeleted=GET_P4REGPTR()->ShowDeleted(); BOOL wasShowFType=GET_P4REGPTR()->ShowFileType(); BOOL wasShowAction=GET_P4REGPTR()->ShowOpenAction(); BOOL wasShowChangeDesc=GET_P4REGPTR()->ShowChangeDesc(); BOOL allChanges= GET_P4REGPTR()->GetFetchAllChanges(); int numChanges=GET_P4REGPTR()->GetFetchChangeCount(); BOOL allJobs= GET_P4REGPTR()->GetFetchAllJobs(); int numJobs=GET_P4REGPTR()->GetFetchJobCount(); BOOL wasShowOtherPending= GET_P4REGPTR()->GetEnablePendingChgsOtherClients(); BOOL wasShowStatusMsgs = GET_P4REGPTR()->GetShowStatusMsgs( ); int maxStatusLines = GET_P4REGPTR()->GetMaxStatusLines(); BOOL wasShowHiddenFilesNotInDepot = GET_P4REGPTR()->ShowHiddenFilesNotInDepot(); CString wasPort= GET_P4REGPTR()->GetP4Port(); if ( m_ShowOptionsDlg ) { // Let the user fiddle with options COptionsTreeDlg dlg; if (intialPage) dlg.m_InitialPage = intialPage; else if (contextPage && GET_P4REGPTR()->GetOptionStartUpOption() == 0) dlg.m_InitialPage = contextPage; else if (GET_P4REGPTR()->GetOptionStartUpOption() == 1) dlg.m_InitialPage = GET_P4REGPTR()->GetOptionStartUpPage(); dlg.DoModal(); } else m_FullRefreshRequired=TRUE; UpdateCaption(); if (wasShowStatusMsgs != GET_P4REGPTR()->GetShowStatusMsgs()) m_pStatusView->SetShowStatusMsgs(GET_P4REGPTR()->GetShowStatusMsgs()); if (maxStatusLines != GET_P4REGPTR()->GetMaxStatusLines()) m_pStatusView->OnMaxStatusLines(); if( wasPort != GET_P4REGPTR()->GetP4Port() ) { m_FullRefreshRequired=TRUE; } // Look for change that would invalidate any depot or delta view else if( wasShowDeleted != GET_P4REGPTR()->ShowDeleted() || wasShowFType != GET_P4REGPTR()->ShowFileType()) { m_FullRefreshRequired=TRUE; SetDepotCaption( GET_P4REGPTR()->ShowEntireDepot() ); } else if( wasShowAction != GET_P4REGPTR()->ShowOpenAction() || wasShowChangeDesc != GET_P4REGPTR()->ShowChangeDesc() || wasShowOtherPending != GET_P4REGPTR()->GetEnablePendingChgsOtherClients() || wasShowHiddenFilesNotInDepot != GET_P4REGPTR()->ShowHiddenFilesNotInDepot() ) { m_FullRefreshRequired=TRUE; } // Are we going to fetch a different number of changes? if( allChanges != GET_P4REGPTR()->GetFetchAllChanges() || numChanges != GET_P4REGPTR()->GetFetchChangeCount() ) m_pOldChgView->GetListCtrl().Clear(); // Are we going to fetch a different number of jobs? if( allJobs != GET_P4REGPTR()->GetFetchAllJobs() || numJobs != GET_P4REGPTR()->GetFetchJobCount() ) m_pJobView->GetListCtrl().Clear(); // If an option change requires full refresh, start the refresh if(m_FullRefreshRequired) { if(wasPort != GET_P4REGPTR()->GetP4Port() || portWasChanged) { m_pOldChgView->GetListCtrl().Clear(); m_pOldChgView->GetListCtrl().ClearFilter(); m_pBranchView->GetListCtrl().Clear(); m_pClientView->GetListCtrl().Clear(); m_pUserView->GetListCtrl().Clear(); m_pLabelView->GetListCtrl().Clear(); m_pJobView->GetListCtrl().Clear(); UpdateDepotandChangeViews( NO_REDRILL ); } else UpdateDepotandChangeViews( REDRILL ); m_Need2ExpandDepot = GET_P4REGPTR()->GetExpandFlag(); } } LRESULT CMainFrame::OnP4OptionsDlg(WPARAM wParam, LPARAM lParam) { OnPerforceOptions( TRUE, FALSE, wParam, lParam ); return TRUE; } void CMainFrame::OnPerforceOptions() { m_DoNotAutoPollCtr = 0; OnPerforceOptions( TRUE ); } void CMainFrame::OnUpdateP4Options(CCmdUI* pCmdUI) { pCmdUI->Enable(SetMenuIcon(pCmdUI, !SERVER_BUSY() && !IsModlessUp())); } void CMainFrame::OnClose() { if(SERVER_BUSY()) { int rc = IDC_BUTTON3; if (!m_Quitting) { if (m_DlgWndList.GetCount() && APP_HALTED()) { CString txt; txt.FormatMessage(IDS_MODELESSDIALOGSUP_n, m_DlgWndList.GetCount()); if (IDYES != AfxMessageBox(txt, MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2)) return; } if (!SERVER_BUSY()) rc = IDC_BUTTON1; else if (TheApp()->m_RunClientWizOnly) { rc = IDC_BUTTON3; CString txt; txt.FormatMessage(IDS_CLIENT_s_ALREADY_EXISTS, GET_P4REGPTR()->GetP4Client()); AfxMessageBox( txt, MB_ICONEXCLAMATION ); } else if((rc = MsgBox(IDS_AN_OPERATION_IS_PENDING__EXIT, MB_ICONEXCLAMATION|MB_DEFBUTTON3)) == IDC_BUTTON2) return; } if (rc == IDC_BUTTON3) { MSG msg; m_Quitting = TRUE; UpdateStatus( LoadStringResource(IDS_WAITINGTOEXIT) ); while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { // get out if app is terminating if ( msg.message == WM_QUIT ) { m_Quitting = FALSE; break; } TranslateMessage(&msg); DispatchMessage(&msg); } if (m_Quitting) { Sleep(1000); ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); return; } } } if (GET_P4REGPTR()->GetLogoutOnExit()) OnLogout(); if (TheApp()->m_DiffPath.IsEmpty() && TheApp()->m_RevHistPath.IsEmpty() && TheApp()->m_FileInfoPath.IsEmpty() && !TheApp()->m_RunClientWizOnly) { GET_P4REGPTR( )->SetShowToolBar(m_wndToolBar.IsWindowVisible()); // If user wants to re-expand depot to last place they were on reconnect, then save current place if (GET_P4REGPTR()->GetExpandFlag() == 1) GET_P4REGPTR()->AddMRUPcuPath(GetCurrentItemPath()); // If user wants to re-expand pending changelist on reconnect, then save current expansion m_pDeltaView->GetTreeCtrl().SaveExpansion(); } // Kill update timer if reqd if(m_Timer != 0) KillTimer(UPDATE_TIMER); // Close all helper app programs for(POSITION pos = m_hWndHelperApp.GetHeadPosition(); pos != NULL; ) { HWND hWnd = (HWND)m_hWndHelperApp.GetNext(pos); ::PostMessage(hWnd, WM_CLOSE, 0, 0); } // Close All Modeless Dialogs SignalAllModelessDlgs(WM_QUITTING); // Hide the main window ShowWindow(SW_HIDE); // Save window position and state if (!TheApp()->m_RunClientWizOnly) { WINDOWPLACEMENT place; if(GetWindowPlacement(&place)) { GET_P4REGPTR()->SetWindowPosition(CRect(place.rcNormalPosition)); switch(place.showCmd) { case SW_SHOWMAXIMIZED: GET_P4REGPTR()->SetWindowIconic(FALSE); GET_P4REGPTR()->SetWindowMaximized(TRUE); break; case SW_SHOWMINIMIZED: GET_P4REGPTR()->SetWindowIconic(TRUE); GET_P4REGPTR()->SetWindowMaximized((place.flags != 0)); break; case SW_SHOWNORMAL: default: GET_P4REGPTR()->SetWindowIconic(FALSE); GET_P4REGPTR()->SetWindowMaximized(FALSE); } } // Save splitter positions int current, min; m_wndHSplitter.GetRowInfo(1, current, min); GET_P4REGPTR()->SetHSplitterPosition(current); m_wndVSplitter.GetColumnInfo(0, current, min); GET_P4REGPTR()->SetVSplitterPosition(current); } // Tell all worker threads it's time to exit. REQUEST_ABORT(); DWORD startAbortTime=GetTickCount(); // Attempt to delete temp files in the P4win temp directory CString tempPath= GET_P4REGPTR()->GetTempDir(); CString tempRoot=tempPath; if(tempPath.GetLength() > 0) { WIN32_FIND_DATA findData; CString fileName; tempPath+=_T("\\*.*"); HANDLE findHandle= FindFirstFile( tempPath, &findData ); while(findHandle != INVALID_HANDLE_VALUE) { fileName.Format(_T("%s\\%s"), tempRoot, findData.cFileName); if(fileName.Find(_T("-Rev-")) != -1) { SetFileAttributes(fileName, FILE_ATTRIBUTE_NORMAL); DeleteFile(fileName); } if(!FindNextFile( findHandle, &findData )) break; } FindClose(findHandle); } // Wait 10 seconds (20 secs if tick count wraps) for worker thread to quit //fanny: create an event handle for this. while(SERVER_BUSY()) { if(GetTickCount() < startAbortTime) startAbortTime=0; else if(GetTickCount() - startAbortTime > 10000) break; Sleep(1000); } CFrameWnd::OnClose(); } void CMainFrame::OnUpdatePerforceInfo(CCmdUI* pCmdUI) { pCmdUI->Enable(SetMenuIcon(pCmdUI, !SERVER_BUSY())); } void CMainFrame::UpdateDepotandChangeViews(BOOL redrill, int key /*=0*/) { if( GET_SERVERLEVEL() < 4 ) redrill= NO_REDRILL; m_pDepotView->GetTreeCtrl().OnViewUpdate( redrill, key ); } void CMainFrame::ExpandDepotString(const CString &path, BOOL newPath) { m_pDepotView->GetTreeCtrl().ExpandDepotString( path, newPath ); } long CMainFrame::PositionChgs(const CString &path, BOOL lookInMine, BOOL lookInOthers, BOOL addToSelectionSet) { if (0 != m_currentTab) { m_bNoRefresh = TRUE; OnViewChanges(); m_bNoRefresh = FALSE; } return m_pDeltaView->GetTreeCtrl().PositionChgs( path, lookInMine, lookInOthers, addToSelectionSet ); } /* _________________________________________________________________ sends command 'p4 info' to the server. put the result in the status pane, instead of a dialogue (and keep customers from cutting and pasting connect info to e-mail to tech support). OnPerforceInfo calls CCmd_Info's Run( ), which sends a WM_P4INFO message back to the mainframe, which calls OnP4InitInfo( ). why have this extra step? _________________________________________________________________ */ void CMainFrame::ShowPerforceInfo() { OnPerforceInfo(); } void CMainFrame::OnPerforceInfo() { CCmd_Info *pCmd= new CCmd_Info; pCmd->Init( m_hWnd, RUN_ASYNC); if( pCmd->Run( ) ) UpdateStatus( LoadStringResource(IDS_REQUESTING_SERVER_INFO) ); else delete pCmd; } LRESULT CMainFrame::OnP4InitInfo( WPARAM wParam, LPARAM lParam ) { CmdPtr pCmd(wParam); if(pCmd && !pCmd->GetError()) { CP4Info const &info = pCmd->GetInfo(); if (m_GetCliRootAndContinue) { TheApp()->Set_m_ClientRoot(info.m_ClientRoot); } else { BOOL showStatusMsgs = GET_P4REGPTR()->GetShowStatusMsgs( ); GET_P4REGPTR()->SetShowStatusMsgs( showStatusMsgs ); CString text = TheApp()->GetAppVersionString(); int i; if ((i = text.ReverseFind(_T(' '))) != -1) { if ((i = text.Find(_T('.'), i)) != -1) text.Delete(i); } if(info.m_ServerDate.IsEmpty()) { text.FormatMessage(IDS_USERCLIENTROOTADDRVERSERVERADDRVERLICENSEROOTOS , info.m_UserName , info.m_ClientName , info.m_ClientHost , info.m_ClientRoot.IsEmpty( ) ? LoadStringResource(IDS_UNKNOWN) : info.m_ClientRoot , info.m_ClientAddress , text , info.m_ServerAddress , info.m_ServerVersion , info.m_ServerLicense , info.m_ServerRoot , TheApp()->GetWindowsVersion()->GetVersionString() , info.m_ClientP4Charset , info.m_ClientAnsiCodePage , info.m_UnicodeMode ); } else if (info.m_CurrentDirectory.IsEmpty()) { text.FormatMessage(IDS_USERCLIENTROOTADDRVERSERVERADDRDATEVERLICENSEROOTOS , info.m_UserName , info.m_ClientName , info.m_ClientHost , info.m_ClientRoot.IsEmpty( ) ? LoadStringResource(IDS_UNKNOWN) : info.m_ClientRoot , info.m_ClientAddress , text , info.m_ServerAddress , info.m_ServerDate , info.m_ServerVersion , info.m_ServerLicense , info.m_ServerRoot , TheApp()->GetWindowsVersion()->GetVersionString() , info.m_ClientP4Charset , info.m_ClientAnsiCodePage , info.m_UnicodeMode ); } else { text.FormatMessage(IDS_USERCLIENTROOTCWDADDRVERSERVERADDRDATEVERLICENSEROOTOS , info.m_UserName , info.m_ClientName , info.m_ClientHost , info.m_ClientRoot.IsEmpty( ) ? LoadStringResource(IDS_UNKNOWN) : info.m_ClientRoot , info.m_CurrentDirectory , info.m_ClientAddress , text , info.m_ServerAddress , info.m_ServerDate , info.m_ServerVersion , info.m_ServerLicense , info.m_ServerRoot , TheApp()->GetWindowsVersion()->GetVersionString() , info.m_ClientP4Charset , info.m_ClientAnsiCodePage , info.m_UnicodeMode ); } if (!info.m_ProxyVersion.IsEmpty()) text.FormatMessage(IDS_PROXYVERSION_INFO, info.m_ProxyVersion, text); // write output to status pane without showing the time BOOL b1 = GET_P4REGPTR()->GetShowStatusMsgs( ); BOOL b2 = GET_P4REGPTR()->ShowStatusTime(); GET_P4REGPTR()->SetShowStatusMsgs( TRUE ); GET_P4REGPTR()->SetShowStatusTime( FALSE ); m_pStatusView->SetShowStatusMsgs(GET_P4REGPTR()->GetShowStatusMsgs()); AddToStatusLog( text ); GET_P4REGPTR()->SetShowStatusMsgs( b1 ); GET_P4REGPTR()->SetShowStatusTime( b2 ); m_pStatusView->SetShowStatusMsgs(GET_P4REGPTR()->GetShowStatusMsgs()); } } UpdateStatus(_T("")); switch (m_GetCliRootAndContinue) { case P4INFO_ADDFILE: OnFileAddSetDir(); break; case P4INFO_DOSBOX: OnCmdPromptContinue(); break; default: break; } return 0; } ////////////////////////////////////////////////////////////////// // OnupdateUI's and handlers for view activation ///////////////////////////////////////////////////////////////// void CMainFrame::OnUpdateViewSwitch(CCmdUI* pCmdUI) { CMenu *pMenu = GetMenu(); if ( pCmdUI->m_nID == ID_CHANGELIST_ACTIVATE ) { UINT start = ID_SUBMITTED_ACTIVATE; UINT end = ID_CHANGELIST_ACTIVATE; pMenu->CheckMenuRadioItem( start, end, ID_CHANGELIST_ACTIVATE, MF_BYCOMMAND ) ; } pCmdUI->Enable(TRUE); } void CMainFrame::OnUpdateViewDepot(CCmdUI* pCmdUI) { int map[] = { ID_VIEW_CLIENTVIEW, ID_VIEW_ENTIREVIEW, ID_VIEW_LOCAL_P4, ID_VIEW_LOCAL_TREE, ID_VIEW_FILESNOTINDEPOT }; pCmdUI->Enable(!SERVER_BUSY()); UINT iItem = m_ShowOnlyNotInDepot ? ID_VIEW_FILESNOTINDEPOT : map[ GET_P4REGPTR()->ShowEntireDepot() ]; if(pCmdUI->m_pMenu) pCmdUI->m_pMenu->CheckMenuRadioItem( ID_VIEW_CLIENTVIEW, ID_VIEW_ENTIREVIEW, iItem, MF_BYCOMMAND); } void CMainFrame::OnViewDepot(UINT nID) { ASSERT(nID >= ID_VIEW_CLIENTVIEW && nID <= ID_VIEW_ENTIREVIEW); m_ShowOnlyNotInDepot = nID == ID_VIEW_FILESNOTINDEPOT; if (m_ShowOnlyNotInDepot) m_pDepotView->GetTreeCtrl().ClearDepotFilter(FALSE); int prevView = GET_P4REGPTR( )->ShowEntireDepot( ); _sdf map[] = { SDF_CLIENT, SDF_LOCALP4, SDF_LOCALTREE, SDF_LOCALTREE, SDF_DEPOT }; _sdf view = map[nID - ID_VIEW_CLIENTVIEW]; SetDepotCaption( view ); GET_P4REGPTR( )->SetShowEntireDepot( view ); m_FullRefreshRequired = TRUE; BOOL redrill; switch(view) { case SDF_CLIENT: case SDF_DEPOT: redrill = (prevView == SDF_CLIENT) || (prevView == SDF_DEPOT); break; case SDF_LOCALTREE: case SDF_LOCALP4: redrill = (prevView == SDF_LOCALTREE) || (prevView == SDF_LOCALP4); break; default: ASSERT(0); redrill = FALSE; break; } UpdateDepotandChangeViews(redrill); if (redrill == NO_REDRILL) m_Need2ExpandDepot = GET_P4REGPTR()->GetExpandFlag(); } void CMainFrame::OnViewChanges() { int old_tab = m_currentTab; SetRightSplitter(0); if(GET_P4REGPTR()->GetReloadOnUncover() && !SERVER_BUSY() && !m_bNoRefresh && m_LastUpdateTime !=0 && (old_tab != m_currentTab) && ((m_DeltaUpdateTime + (GET_P4REGPTR()->GetReloadUncoverTime() * 60000)) < GetTickCount())) m_pDepotView->GetTreeCtrl().OnViewUpdate( TRUE ); } void CMainFrame::ViewLabels( ) { OnViewLabels( ) ; } void CMainFrame::OnViewLabels() { int old_tab = m_currentTab; SetRightSplitter(1); if((m_pLabelView->GetListCtrl().IsClear() || (GET_P4REGPTR()->GetReloadOnUncover() && !m_bNoRefresh)) && !SERVER_BUSY() && m_LastUpdateTime !=0 && (old_tab != m_currentTab) && ((m_LabelUpdateTime + (GET_P4REGPTR()->GetReloadUncoverTime() * 60000)) < GetTickCount())) m_pLabelView->GetListCtrl().OnViewUpdate(); } void CMainFrame::ViewBranches( ) { OnViewBranches( ) ; } void CMainFrame::OnViewBranches() { int old_tab = m_currentTab; SetRightSplitter(2); if((m_pBranchView->GetListCtrl().IsClear() || (GET_P4REGPTR()->GetReloadOnUncover() && !m_bNoRefresh)) && !SERVER_BUSY() && m_LastUpdateTime !=0 && (old_tab != m_currentTab) && ((m_BranchUpdateTime + (GET_P4REGPTR()->GetReloadUncoverTime() * 60000)) < GetTickCount())) m_pBranchView->GetListCtrl().OnViewUpdate(); } void CMainFrame::ViewUsers( ) { OnViewUsers( ) ; } void CMainFrame::OnViewUsers() { int old_tab = m_currentTab; SetRightSplitter(3); if((m_pUserView->GetListCtrl().IsClear() || (GET_P4REGPTR()->GetReloadOnUncover() && !m_bNoRefresh)) && !SERVER_BUSY() && m_LastUpdateTime !=0 && (old_tab != m_currentTab) && ((m_UserUpdateTime + (GET_P4REGPTR()->GetReloadUncoverTime() * 60000)) < GetTickCount())) m_pUserView->GetListCtrl().OnViewUpdate(); } void CMainFrame::ViewClients( ) { OnViewClients( ) ; } void CMainFrame::OnViewClients() { int old_tab = m_currentTab; SetRightSplitter(4); if((m_pClientView->GetListCtrl().IsClear() || (GET_P4REGPTR()->GetReloadOnUncover() && !m_bNoRefresh)) && !SERVER_BUSY() && m_LastUpdateTime !=0 && (old_tab != m_currentTab) && ((m_ClientUpdateTime + (GET_P4REGPTR()->GetReloadUncoverTime() * 60000)) < GetTickCount())) m_pClientView->GetListCtrl().OnViewUpdate(); } void CMainFrame::ViewJobs( ) { OnViewJobs( ) ; } void CMainFrame::OnViewJobs() { int old_tab = m_currentTab; SetRightSplitter(5); m_pJobView->GetListCtrl().SetCaption( ); if((m_pJobView->GetListCtrl().IsClear() || (GET_P4REGPTR()->GetReloadOnUncover() && !m_bNoRefresh)) && !SERVER_BUSY() && m_LastUpdateTime !=0 && (old_tab != m_currentTab) && ((m_JobUpdateTime + (GET_P4REGPTR()->GetReloadUncoverTime() * 60000)) < GetTickCount())) m_pJobView->GetListCtrl().OnViewUpdate(); } void CMainFrame::OnViewSubmitted() { int old_tab = m_currentTab; SetRightSplitter(6); if ((!m_OldChgUpdateTime || m_pOldChgView->GetListCtrl().IsClear() || (GET_P4REGPTR()->GetReloadOnUncover() && !m_bNoRefresh)) && !SERVER_BUSY() && m_LastUpdateTime !=0 && (old_tab != m_currentTab) && ((m_OldChgUpdateTime + (GET_P4REGPTR()->GetReloadUncoverTime() * 60000)) < GetTickCount())) { m_pOldChgView->GetListCtrl().OnViewUpdate(); } else if (m_Need2RefreshOldChgs) { ::SendMessage(m_pOldChgView->m_hWnd, WM_RUNUPDATE, 0, 0); } m_Need2RefreshOldChgs = FALSE; } LRESULT CMainFrame::OnClientError(WPARAM wParam, LPARAM lParam) { // activate the client pane so the user can switch-to/make-new client m_ClientError= TRUE; // wait until all in process commands finish so our 'p4 clients' will run ok int t = GET_P4REGPTR()->BusyWaitTime() * 10 + 5000; while (SERVER_BUSY() && t > 0) { if (!PumpMessages( )) break; Sleep(50); t -= 50; } OnViewClients(); // we want this to get started and hopefully finish while the dialogbox is up Sleep(100); // because our remove of MRU will get restored when the async part of OnViewClients() finishes // if there is a local default template in the registry // we'll go with that rather than run the wizard CString localdeftmplate = GET_P4REGPTR()->GetLocalCliTemplate(); if (GET_P4REGPTR()->LocalCliTemplateSw() && !localdeftmplate.IsEmpty() && localdeftmplate.Find(_T("\n\nClient:\t")) == 0) { m_pClientView->GetListCtrl().DoClientspecNew(TRUE, GET_P4REGPTR()->GetP4Client()); return 0; } // format a PCU string so we can remove this invalid one CString pcutxt; pcutxt.Format( _T("%s %s %s"), GET_P4REGPTR()->GetP4Port(), GET_P4REGPTR()->GetP4Client(), GET_P4REGPTR()->GetP4User()); CMenu *pMenu= GetMenu(); // Run the Client Wizard CString txt; CString port = GET_P4REGPTR()->GetP4Port(); CString clientname = GET_P4REGPTR()->GetP4Client(); if (GET_P4REGPTR()->Is1stRun()) txt.FormatMessage( IDS_YOUMUSTSPECIFYACLIENT_s_s, port, GET_P4REGPTR()->GetP4User() ); else txt.FormatMessage( IDS_NOCLIENT_s_s_s, clientname, port, GET_P4REGPTR()->GetP4User() ); CClientWizSheet dlg(_T("ClientWorkspace Wizard"), this, 0); dlg.SetMsg(txt); dlg.SetName(clientname); dlg.SetPort(port); if (TheApp()->m_RunClientWizOnly) dlg.AllowBrowse(FALSE); int i, rc; while(1) { rc = dlg.DoModal(); // display the Wizard and get the return code // remove the MRU for this PCU triplet since it is no good for now GET_P4REGPTR()->RmvMRUPcu(pcutxt); if (pMenu != NULL) loadMRUPcuMenuItems(pMenu); // handle the return code if( rc == IDCANCEL ) // user bailed { DoNotAutoPoll(); break; } if ( rc == IDIGNORE ) // user chose to browse existing clients { // Give the viewupdate for clients more time to finish for (i = 100; SERVER_BUSY() && i--; ) Sleep(100); // Because MFC tosses the return from this SendMessage // We have to pass the return code via a variable :-( m_ClientGet = 0; ::SendMessage(ClientWnd(), WM_WIZFETCHOBJECTLIST, (WPARAM)(this->m_hWnd), WM_BROWSECALLBACK1); if (m_ClientGet == 1) { UpdateDepotandChangeViews(TRUE); // update to reflect new client return 0; } else if (!m_ClientGet) break; // else m_Client == -1, so loop again and show 1st Wizard page // but first we have to destroy the Adobe bitmap dlg.DeleteAdobeBitmap(); } else // user clicked the Finish button on the create client page { CString newClient = dlg.GetName(); CString newRoot = dlg.GetRoot(); BOOL bEdit = dlg.IsEdit(); BOOL bTmpl = dlg.IsTmpl(); CString tmplate = dlg.GetTmpl(); if (m_pClientView->GetListCtrl().FindInList(newClient) != -1) { CString msg; msg.FormatMessage(IDS_CANT_RECREATE_EXISTING_CLIENT_s, newClient); AfxMessageBox( msg, MB_ICONSTOP ); dlg.DeleteAdobeBitmap(); } else if (!newClient.IsEmpty() && !newRoot.IsEmpty()) { if (m_pClientView->GetListCtrl().AutoCreateClientSpec(newClient, newRoot, bEdit, bTmpl, tmplate)) return 0; } } } // Inform the user we failed to establish a client txt.FormatMessage( IDS_NOCLIENT_s_s_s, GET_P4REGPTR()->GetP4Client(), GET_P4REGPTR()->GetP4Port(), GET_P4REGPTR()->GetP4User() ); if ((i = txt.Find(_T('\n'))) != -1) { txt = txt.Left(i); txt.TrimLeft(); } TheApp()->StatusAdd( txt, SV_WARNING ); UpdateCaption(FALSE); if (TheApp()->m_RunClientWizOnly) ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); return 0; } LRESULT CMainFrame::OnBrowseClientsCallBack(WPARAM wParam, LPARAM lParam) { if (wParam == IDC_BACK) { m_ClientGet = -1; return IDC_BACK; // The IDC_BACK gets tossed by MFC :-( } CString *str = (CString *)lParam; GET_P4REGPTR()->SetP4Client(*str, TRUE, FALSE, FALSE); UpdateCaption( ); m_ClientGet = 1; return IDOK; // The IDOK gets tossed by MFC :-( } void CMainFrame::SetLastUpdateTime(BOOL updateResult) { m_LastUpdateTime=GetTickCount(); m_LastUpdateResult=updateResult; if( updateResult == UPDATE_SUCCESS ) m_ClientError= FALSE; } void CMainFrame::ClearLastUpdateTime() { m_LastUpdateTime=0; m_LastUpdateResult= UPDATE_SUCCESS; m_ClientError= FALSE; } /* _________________________________________________________________ Timer fires every 5 secs. Only start an update if 1) server not busy 2) auto poll is on 3) time since last update finished exceeds poll interval 4) popup menu is not up 5) is active or user requests to poll when inactive _________________________________________________________________ */ void CMainFrame::OnTimer(UINT nIDEvent) { CFrameWnd::OnTimer(nIDEvent); static int statustimer = 0; if (m_StatusUpdateInterval && !SERVER_BUSY() || ++statustimer >= m_StatusUpdateInterval) { m_pStatusView->SetRedraw(TRUE); statustimer = 0; } long time=GetTickCount(); if( SERVER_BUSY() || m_DoNotAutoPollCtr > 0 ) return; if(GetLastActivePopup() != this) return; if(APP_HALTED()) { // User is staring at app-modal error message m_LastUpdateTime= time; return; } // Don't keep firing auto-updates when we know there // is a password error if(GET_PWD_ERROR()) return; // Don't keep firing auto-updates when we know the // last attempt ended in failure. The only exception // is the case of a client error, where we activate // and refresh the client pane if( m_LastUpdateResult == UPDATE_FAILED && m_ClientError) { OnViewClients(); if(UpdateRightView()) { m_LastUpdateResult= UPDATE_SUCCESS; return; } m_ClientError= FALSE; } else if( m_LastUpdateResult == UPDATE_FAILED) return; if(UpdateRightView()) { XTRACE(_T("OnTimer - updated right view\n")); m_LastUpdateTime= time; return; } // See if its time to update depot and changes windows if(!GET_P4REGPTR()->GetAutoPoll()) return; // Some users prefer no polling while inactive (default) if(!m_GotInput && !GET_P4REGPTR()->GetAutoPollIconic()) return; if((m_LastUpdateTime > time) || ((time-m_LastUpdateTime)/60000 >= GET_P4REGPTR()->GetAutoPollTime())) { XTRACE(_T("OnTimer - starting update\n")); // Clear our flag which indicates whether we got any mousedowns or keystrokes m_GotInput = FALSE; m_LastUpdateTime = time; if (GET_P4REGPTR()->GetAutoPollJobs()) { if (m_currentTab == 5) m_Need2Poll4Jobs = TRUE; else m_pJobView->GetListCtrl().Clear(); } // TODO: Rename all variables that sound like 'fullupdate' or 'fullrefresh' // so this code is a little easier to read. With the recent change in // how F5 works, m_FullRefreshRequired in this module means that the // depot + changelist panes have never been properly loaded since application // startup or since a change in connection parameters. But in CDepotView, // m_FullUpdate means that we don't want to run an incremental update of // the depot (fstat -c x combined with p4 opened -a), rather we want to // get a fresh copy of everything, by running fstat on every file. // // But I'm going to save this rename work till 99.1 so I dont have yet // another massive change to the code in several files. if((GET_SERVERLEVEL() > 3)) { // Against a 98.2 server, only try the redrill operation if the existing // window contents are known to be valid (!m_FullRefreshRequired). Never // ask for incremental update int lock = 0; GET_SERVER_LOCK( lock ); UpdateDepotandChangeViews(!m_FullRefreshRequired, lock); } else // Against a 97.3 server, if the timer is polling do what 97.3 gui did. UpdateDepotandChangeViews(FALSE, m_FullRefreshRequired); } } BOOL CMainFrame::UpdateRightView() { BOOL updating=FALSE; switch(m_currentTab) { case 0: break; case 1: if(m_pLabelView->GetListCtrl().IsClear()) { m_pLabelView->GetListCtrl().OnViewUpdate(); updating=TRUE; } break; case 2: if(m_pBranchView->GetListCtrl().IsClear()) { m_pBranchView->GetListCtrl().OnViewUpdate(); updating=TRUE; } break; case 3: if(m_pUserView->GetListCtrl().IsClear()) { m_pUserView->GetListCtrl().OnViewUpdate(); updating=TRUE; } break; case 4: if(m_pClientView->GetListCtrl().IsClear()) { m_pClientView->GetListCtrl().OnViewUpdate(); updating=TRUE; } break; case 5: if(m_pJobView->GetListCtrl().IsClear()) { m_pJobView->GetListCtrl().OnViewUpdate(); updating=TRUE; } break; case 6: if(m_pOldChgView->GetListCtrl().IsClear()) { m_pOldChgView->GetListCtrl().OnViewUpdate(); updating=TRUE; } break; default: ASSERT(0); } return updating; } void CMainFrame::OnSysColorChange() { // update image lists TheApp()->OnSysColorChange(); // pass it along to views CFrameWnd::OnSysColorChange(); m_wndToolBar.GetToolBarCtrl().SetImageList( TheApp()->GetToolBarImageList()); m_wndToolBar.GetToolBarCtrl().SetDisabledImageList( TheApp()->GetToolBarImageList()->GetDisabled()); } void CMainFrame::OnUpdateFileAdd(CCmdUI* pCmdUI) { pCmdUI->Enable(SetMenuIcon(pCmdUI, !SERVER_BUSY() && !m_pDeltaView->GetTreeCtrl().IsEditInProgress())); } void CMainFrame::OnFileAdd() { // In order to initalize the OpenFile dialogbox to the correct initial directory, // we need the root of the current client. So first go get that after setting a // flag to indicate to the p4 info completion routine that that is what we are up to. if (TheApp()->m_ClientRoot.IsEmpty()) { m_GetCliRootAndContinue = P4INFO_ADDFILE; OnPerforceInfo(); } else OnFileAddSetDir(); } void CMainFrame::OnFileAddSetDir(LPTSTR lpInitDir /*= NULL*/) { m_GetCliRootAndContinue = 0; TheApp()->m_ClientRoot.Replace('/', '\\'); // TODO: put filter categories in the registry and allow user prefs for file types // This loads the internal OPENFILENAME structure CFileDialog fDlg(TRUE, NULL, NULL, OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST | OFN_ENABLESIZING, LoadStringResource(IDS_MAIN_ADD_FILE_FILTER), this, m_osVer.dwMajorVersion < 5 ? OPENFILENAME_SIZE_VERSION_400 : sizeof(OPENFILENAME)); // Note that with NT4.0 < SP3, file dialog is limited to ~20 files // Set a reasonably large buffer for multi-file selects. This is big // enough for 1500 20 char filenames. I'm sure someone will complain // that's not enough... #define BUFLEN 32768 TCHAR buf[BUFLEN]; // Zero 1st char so commdlg knows we aren't providing a default filename buf[0]=_T('\0'); fDlg.m_ofn.lpstrFile= buf; fDlg.m_ofn.nMaxFile= BUFLEN; // Set the dlg caption CString title=LoadStringResource(IDS_ADD_FILES_TO_SOURCE_CONTROL); fDlg.m_ofn.lpstrTitle=title; // We dont need no stinking file title fDlg.m_ofn.lpstrFileTitle=NULL; // Set the initial directory TCHAR initdir[MAX_PATH+1]; if (lpInitDir && *lpInitDir) { lstrcpy(initdir, lpInitDir); } else { lstrcpy(initdir, GET_P4REGPTR()->GetAddFileCurDir()); LPTSTR p = TheApp()->m_ClientRoot.GetBuffer(TheApp()->m_ClientRoot.GetLength()+1); if (_tcsnicmp(initdir, p, TheApp()->m_ClientRoot.GetLength())) lstrcpy(initdir, p); TheApp()->m_ClientRoot.ReleaseBuffer(); } fDlg.m_ofn.lpstrInitialDir=initdir; // Set the user defined filter TCHAR customFilterBuf[512]; memset(customFilterBuf, 0, 512); CString customFilter=GET_P4REGPTR()->GetAddFileFilter(); CString filterTitle; filterTitle.FormatMessage(IDS_CUSTOM_FILTER_s, customFilter.GetLength() ? customFilter : _T("?")); lstrcpy(customFilterBuf, filterTitle); lstrcpy(customFilterBuf+(filterTitle.GetLength()+1), customFilter); fDlg.m_ofn.lpstrCustomFilter= customFilterBuf; fDlg.m_ofn.nMaxCustFilter=512; // Set custom filter index fDlg.m_ofn.nFilterIndex=GET_P4REGPTR()->GetAddFileFilterIndex(); CString errorTxt; int retcode=fDlg.DoModal(); if(retcode == IDOK) { // If the use made a selection w/ a modified custom filter, // update the registry with that custom filter if(fDlg.m_ofn.nFilterIndex==0) { // Save any change to the user filter TCHAR *ptr=customFilterBuf+(filterTitle.GetLength()+1); if(lstrlen(ptr) > 0) GET_P4REGPTR()->SetAddFileFilter(ptr); } // Always save index to search filter GET_P4REGPTR()->SetAddFileFilterIndex(fDlg.m_ofn.nFilterIndex); CStringList files; POSITION pos= fDlg.GetStartPosition(); int ctr=0; while(pos != NULL) { files.AddHead(fDlg.GetNextPathName(pos)); // Even tho we have a 32K buffer, windows can fail to give us // 32K worth of file names - warn if adding 500+ files if (++ctr == 500) AddToStatus( LoadStringResource(IDS_TOO_MANYFILES_TO_ADD), SV_WARNING ); } // Update registry for last add path if(files.GetCount()) { CString fname=files.GetHead(); int lastSlash= fname.ReverseFind(_T('\\')); fname= fname.Left(lastSlash); GET_P4REGPTR()->SetAddFileCurDir(fname); } m_pDeltaView->GetTreeCtrl().AddFileList(0, &files); } else if(retcode == IDCANCEL) // an error { DWORD exError=CommDlgExtendedError(); if(exError != 0) errorTxt.FormatMessage(IDS_EXTENDED_ERROR_n_IN_FILEDIALOG, exError); } else { DWORD error=GetLastError(); if(error) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); errorTxt = (TCHAR *)lpMsgBuf; } else errorTxt=LoadStringResource(IDS_UNKNOWN_FILEDIALOG_ERROR); } if(errorTxt.GetLength() > 0) AfxMessageBox(errorTxt, MB_ICONSTOP); } void CMainFrame::ActivateFrame(int nCmdShow) { if(m_FirstActivation) { m_FirstActivation=FALSE; ////////////////// // Calculate size of main window, making sure it still fits the // current screen size. CRect rect= GET_P4REGPTR()->GetWindowPosition(); if(rect.Width() < 50 || rect.Height() < 50) { // Might have a bad reg value, so set a reasonable default rect= CRect(GetSystemMetrics(SM_CXSCREEN) /10, GetSystemMetrics(SM_CYSCREEN) /10, GetSystemMetrics(SM_CXSCREEN) * 9/10, GetSystemMetrics(SM_CYSCREEN) * 9/10); } // if there is only one monitor, we can check for resonable placement else if (m_NbrDisplays < 2) { rect.NormalizeRect(); // If rectangle bigger than screen, shrink/shift as required // (some 8-ball may have changed video res since we last ran) int reduceX= max( rect.Width() - GetSystemMetrics(SM_CXSCREEN), 0 ); int reduceY= max( rect.Height() - GetSystemMetrics(SM_CYSCREEN), 0 ); rect.DeflateRect(reduceX/2, reduceY/2); // Move the window fully onto the screen int shiftX= max( rect.right - GetSystemMetrics(SM_CXSCREEN), 0); int shiftY= max( rect.bottom - GetSystemMetrics(SM_CYSCREEN), 0); rect.OffsetRect(-shiftX, -shiftY); } ///////////////// // Set the size of the main window WINDOWPLACEMENT place; if (nCmdShow == SW_SHOWNORMAL) { if(GET_P4REGPTR()->GetWindowMaximized()) { nCmdShow=SW_SHOWMAXIMIZED; place.flags=WPF_RESTORETOMAXIMIZED; } else { nCmdShow=SW_NORMAL; place.flags=WPF_SETMINPOSITION; } } else place.flags=WPF_SETMINPOSITION; place.length= sizeof(WINDOWPLACEMENT); place.showCmd= nCmdShow; place.ptMinPosition=CPoint(0,0); place.ptMaxPosition=CPoint(-::GetSystemMetrics(SM_CXBORDER), -::GetSystemMetrics(SM_CYBORDER)); place.rcNormalPosition= rect; SetWindowPlacement(&place); if (!TheApp()->m_DiffPath.IsEmpty()) nCmdShow=SW_SHOWMINIMIZED; if (!TheApp()->m_RevHistPath.IsEmpty() || !TheApp()->m_FileInfoPath.IsEmpty() || !TheApp()->m_SubmitPath.IsEmpty() || TheApp()->m_RunClientWizOnly) nCmdShow=SW_SHOWMINIMIZED; /////////////////////// // Set row height for main horizontal splitter m_wndHSplitter.GetClientRect(&rect); int h=GET_P4REGPTR()->GetHSplitterPosition(); int hb=rect.Height()-GetSystemMetrics(SM_CYBORDER)*4; if(h > hb) h=hb; // Shrink to fit else if(h<=0) h=100; // Default. About 5 rows of text, depending on font m_wndHSplitter.SetRowInfo( 0, rect.Height()-h-11, 0); m_wndHSplitter.SetRowInfo( 1, h, 0); m_wndHSplitter.RecalcLayout(); ////////////////////// // Set columns width for main vertical splitter m_wndVSplitter.GetClientRect(&rect); int w=GET_P4REGPTR()->GetVSplitterPosition(); int wb=rect.Width()-GetSystemMetrics(SM_CXBORDER)*4; if(w > wb) w=wb; // Shrink to fit else if(w<=0) w=wb/2; // Guess a reasonable default m_wndVSplitter.SetColumnInfo( 0, w, 0); m_wndVSplitter.SetColumnInfo( 1, w, 0); m_wndVSplitter.RecalcLayout(); #if 0 if (GET_P4REGPTR()->Is1stRun()) { CFirstTimeDlg dlg; if (dlg.DoModal() == IDOK) { OnGettingStartedWithP4win(); UpdateDepotandChangeViews(NO_REDRILL); } else { // Run the initial update of depot and changelist panes UpdateDepotandChangeViews(NO_REDRILL); m_Need2ExpandDepot = GET_P4REGPTR()->GetExpandFlag(); } } #endif } CFrameWnd::ActivateFrame(nCmdShow); } void CMainFrame::SetDepotCaption( int iShowEntireDepot ) { m_pDepotView->GetTreeCtrl().SetCaption(iShowEntireDepot); } void CMainFrame::OnUpdateClientspecNew(CCmdUI* pCmdUI) { pCmdUI->Enable( !SERVER_BUSY() && !IsModlessUp() && !m_pClientView->GetListCtrl().IsEditInProgress() ); } void CMainFrame::OnClientspecNew() { m_pClientView->GetListCtrl().ClientspecNew( ) ; } void CMainFrame::OnUpdateSubmittedActivate(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); } void CMainFrame::loadMRUPcuMenuItems(CMenu *pMenu) { CString str[MAX_MRU_PCUS+1]; CString temp; int i, j; CString SpeedNbr; CMenu *pEditMenu = pMenu->GetSubMenu(3); CMenu *pHistMenu = pEditMenu->GetSubMenu(4); // clear the old PCU menu items for (i = -1; ++i < MAX_MRU_PCUS; ) { if (!(pHistMenu->DeleteMenu( ID_MRU_PCU0 + i, MF_BYCOMMAND ))) break; } // Get the strings for(i = -1; ++i < MAX_MRU_PCUS; ) { int k = 0; str[i] = GET_P4REGPTR()->GetMRUPcu(i); if ((j = str[i].Find(_T('@'))) > 0) str[i] = str[i].Left(j); if (!str[i].IsEmpty() && (str[i].GetAt(0) == _T('\"')) && ((j = str[i].Find(_T('\"'), 1)) > 0)) k = j; if ((j = str[i].Find(_T(' '), k)) > 0) str[i].SetAt(j, _T('\t')); } // Sort the strings BOOL swapped; do { swapped = FALSE; for(i=0; ++i < MAX_MRU_PCUS; ) { if (str[i-1] > str[i]) { swapped = TRUE; temp = str[i-1]; str[i-1] = str[i]; str[i] = temp; } } } while (swapped); // Load all MRU PCUs into History menu for(i=-1, j=1; ++i < MAX_MRU_PCUS; ) { if (str[i].GetLength() > 0) { if (j != 10) SpeedNbr.Format(_T("&%d "), j); else SpeedNbr = _T("&0 "); pHistMenu->AppendMenu(MF_STRING, ID_MRU_PCU0+j-1, SpeedNbr+str[i]); j++; } } } void CMainFrame::OnUpdateMruPcu(CCmdUI* pCmdUI) { pCmdUI->Enable(IsModlessUp() ? FALSE : !SERVER_BUSY()); } void CMainFrame::OnUpdateMruPcuHdr(CCmdUI* pCmdUI) { pCmdUI->Enable(IsModlessUp() ? FALSE : !SERVER_BUSY()); } void CMainFrame::OnMruPcu(int nbr) { int j; int firstsep; int secondsep; CString menuStr; CString port; CString client; CString user; CString wasUser = GET_P4REGPTR()->GetP4User(); CString wasPort = GET_P4REGPTR()->GetP4Port(); if (IsModlessUp() || !GetMenu()->GetMenuString(ID_MRU_PCU0+nbr, menuStr, MF_BYCOMMAND)) { ASSERT(NULL); return; } menuStr = menuStr.Right(menuStr.GetLength()-3); if ((j = menuStr.Find(_T('@'))) > 0) menuStr = menuStr.Left(j); if (menuStr.GetAt(0) == _T('\"')) firstsep = menuStr.Find(_T('\"'),1) + 1; else firstsep = menuStr.Find(_T('\t')); secondsep= menuStr.Find(_T(' '), firstsep+1); port = menuStr.Left(firstsep); port.TrimLeft(_T('\"')); port.TrimRight(_T('\"')); client= menuStr.Mid(firstsep+1, secondsep - firstsep - 1); user = menuStr.Right(menuStr.GetLength() - secondsep - 1); if (GET_P4REGPTR()->GetExpandFlag() == 1) GET_P4REGPTR()->AddMRUPcuPath(GetCurrentItemPath()); GET_P4REGPTR()->SetP4Port(port, TRUE, FALSE, FALSE); GET_P4REGPTR()->SetP4User(user, TRUE, FALSE, FALSE); if (!ClientSpecSwitch(client, TRUE, wasPort != port))// calls OnPerforceOptions() { GET_P4REGPTR()->SetP4Port(wasPort, TRUE, FALSE, FALSE); // put old port back if client switched failed GET_P4REGPTR()->SetP4User(wasUser, TRUE, FALSE, FALSE); // put old user back if client switched failed } } void CMainFrame::OnMruPcu0() { OnMruPcu(0); } void CMainFrame::OnMruPcu1() { OnMruPcu(1); } void CMainFrame::OnMruPcu2() { OnMruPcu(2); } void CMainFrame::OnMruPcu3() { OnMruPcu(3); } void CMainFrame::OnMruPcu4() { OnMruPcu(4); } void CMainFrame::OnMruPcu5() { OnMruPcu(5); } void CMainFrame::OnMruPcu6() { OnMruPcu(6); } void CMainFrame::OnMruPcu7() { OnMruPcu(7); } void CMainFrame::OnMruPcu8() { OnMruPcu(8); } void CMainFrame::OnMruPcu9() { OnMruPcu(9); } void CMainFrame::OnUpdateViewWarnAndErrs(CCmdUI* pCmdUI) { m_pStatusView->CallOnUpdateViewWarnAndErrs(pCmdUI); } void CMainFrame::OnViewWarnAndErrs() { m_pStatusView->CallOnViewWarnAndErrs(); } /////////////////////////////////////////////////// // When doing Next/Prev in Describe, painting is turned off to stop flashing. // This CallBack function is called during an EnumChildWindows() to stop or resume // painting for all child windows in the process. BOOL CALLBACK ChildSetRedraw(HWND hwnd, LPARAM lParam) // LPARAM is TRUE for ON, FALSE for OFF { // Windows that are children of the righthand splitter // and are not childern of the current pane are NOT disable/enabled // because these are hidden and disabling/re-enabling them cause // them to become unhidden (for some unknown reason). BOOL b; if (::IsChild(MainFrame()->GetHSplitterWnd(), hwnd)) { if (MainFrame()->GetLeftHandWnd() == hwnd || ::IsChild(MainFrame()->GetLeftHandWnd(), hwnd)) b = TRUE; else if (MainFrame()->GetRightHandWnd() == hwnd || ::IsChild(MainFrame()->GetRightHandWnd(), hwnd)) b = TRUE; else if (MainFrame()->GetVSplitterWnd() == hwnd) b = TRUE; else b = FALSE; } else b = TRUE; if (b) { // Turn the painting on/off // for this visible child window // in accord with lParam value ::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)lParam, 0); // Force a repaint if enabling. if (lParam) ::InvalidateRect(hwnd, NULL, TRUE); } return(TRUE); } /////////////////////////////////////////////////// // Switch to the opposite pane void CMainFrame::SwitchPanes(CView *pView, BOOL bShift) { #ifdef _DEBUG ASSERT_KINDOF(CView, pView); #endif if(pView == m_pDepotView) SetActiveView(m_pRightView); else { if (bShift) SetActiveView(m_pStatusView, TRUE); else SetActiveView(m_pDepotView); } } void CMainFrame::OnUpdateShowDeletedFiles(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); pCmdUI->SetCheck(GET_P4REGPTR()->ShowDeleted()); } void CMainFrame::OnShowDeletedFiles() { BOOL showDeleted = !GET_P4REGPTR()->ShowDeleted(); GET_P4REGPTR()->SetShowDeleted( showDeleted ); SetDepotCaption( GET_P4REGPTR()->ShowEntireDepot() ); m_pDepotView->GetTreeCtrl().OnViewUpdate( TRUE ); } void CMainFrame::OnUpdateSortByExtension(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); pCmdUI->SetCheck(GET_P4REGPTR()->SortByExtension()); } void CMainFrame::OnSortByExtension() { BOOL sortByExtension = !GET_P4REGPTR()->SortByExtension(); GET_P4REGPTR()->SetSortByExtension( sortByExtension ); m_pDepotView->GetTreeCtrl().OnViewUpdate( TRUE ); } void CMainFrame::OnUpdatePositionToPattern(CCmdUI* pCmdUI) { CString txt = LoadStringResource(IDS_FINDPATTERN); pCmdUI->SetText( txt ); pCmdUI->Enable( NULL == m_pFRDlg ); } void CMainFrame::OnPositionToPattern() { CView * pView = GetActiveView(); int flags = (pView == m_pStatusView) ? m_FindStatusFlags : m_FindWhatFlags; if ( NULL == m_pFRDlg ) { m_pFRDlg = new CFindReplaceDialog(); // Must be created on the heap m_pFRDlg->m_fr.lStructSize = sizeof(FINDREPLACE); m_pFRDlg->m_fr.hwndOwner = this->m_hWnd; m_pFRDlg->Create( TRUE, m_FindWhatStr, _T(""), flags | FR_HIDEWHOLEWORD, this ); } SetMessageText(LoadStringResource(IDS_FOR_HELP_PRESS_F1)); } void CMainFrame::OnUpdatePositionToNext(CCmdUI* pCmdUI) { CView * pView = GetActiveView(); pCmdUI->Enable( pView != m_pDepotView && pView != m_pDeltaView && !m_FindWhatStr.IsEmpty()); } void CMainFrame::OnPositionToNext() { if (!m_FindWhatStr.IsEmpty()) { CView * pView = GetActiveView(); int flags = (pView == m_pStatusView) ? m_FindStatusFlags : m_FindWhatFlags; ::PostMessage(pView->m_hWnd, WM_FINDPATTERN, (WPARAM)flags | 0x80000000, (LPARAM)m_FindWhatStr.GetBuffer(0)); } } void CMainFrame::OnUpdatePositionToPrev(CCmdUI* pCmdUI) { CView * pView = GetActiveView(); pCmdUI->Enable( pView != m_pDepotView && pView != m_pDeltaView && !m_FindWhatStr.IsEmpty()); } void CMainFrame::OnPositionToPrev() { if (!m_FindWhatStr.IsEmpty()) { CView * pView = GetActiveView(); int flags = (pView == m_pStatusView) ? m_FindStatusFlags : m_FindWhatFlags; ::PostMessage(pView->m_hWnd, WM_FINDPATTERN, ((WPARAM)flags | 0x80000000) ^ FR_DOWN, (LPARAM)m_FindWhatStr.GetBuffer(0)); } } LONG CMainFrame::OnFindReplace(WPARAM wParam, LPARAM lParam) { LPFINDREPLACE lpfp = (LPFINDREPLACE)lParam; if (m_pFRDlg->FindNext() || m_pFRDlg->IsTerminating()) { CView * pView = GetActiveView(); m_FindWhatStr = lpfp->lpstrFindWhat; if (pView == m_pStatusView) m_FindStatusFlags = lpfp->Flags; else m_FindWhatFlags = lpfp->Flags; if (m_pFRDlg->FindNext()) { ::PostMessage(pView->m_hWnd, WM_FINDPATTERN, (WPARAM)(lpfp->Flags), (LPARAM)m_FindWhatStr.GetBuffer(0)); delete m_pFRDlg; } m_pFRDlg = NULL; } return 0; } void CMainFrame::OnUpdateEditPaste(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY() && ::CountClipboardFormats()); } // User can now copy a file path (in depot or local syntax) to the clipboard // and then when an Edit > Paste is done, the Depot Treeview will be // expanded to find the file // void CMainFrame::OnEditPaste() { if (::OpenClipboard(NULL)) { #ifdef UNICODE HGLOBAL hGlob = ::GetClipboardData(CF_UNICODETEXT); #else HGLOBAL hGlob = ::GetClipboardData(CF_TEXT); #endif LPCTSTR p; if ((hGlob != NULL) && ((p = (LPCTSTR)::GlobalLock(hGlob)) != NULL)) { CString itemStr = p; int i; ::GlobalUnlock(hGlob); if ((i = itemStr.Find(_T('#'))) != -1) itemStr = itemStr.Left(i); itemStr.TrimLeft(); itemStr.TrimRight(); if (itemStr.GetAt(0) != _T('/') && itemStr.GetAt(1) != _T(':')) { if ((i = itemStr.Find(_T("//"))) > 0) { // we have something like "STATUS: 3:33:26 Sync preview: //depot/main/www/perforce/customers/bycountry.html#16 - updating c:\workspac\main\www\perforce\customers\bycountry.html" // so throw away everything before the "//" itemStr = itemStr.Right(itemStr.GetLength() - i); // if we find a 2nd "//", throw it and the following chars away if ((i = itemStr.Find(_T("//"), 2)) > 0) itemStr = itemStr.Left(i); itemStr.TrimRight(); } else if ((i = itemStr.Find(_T(":\\"))) > 0) { // we have something like "STATUS: 11:48:04 Executing p4 where c:\workspac\P4CONFIG" // so throw away everything before the "c:\" itemStr = itemStr.Right(itemStr.GetLength() - i + 1); // if we find a 2nd "c:\", throw it and the following chars away if ((i = itemStr.Find(_T(":\\"), 3)) > 0) itemStr = itemStr.Left(i-1); itemStr.TrimRight(); } } if ((itemStr.FindOneOf(_T("?*")) != -1) || (itemStr.Find(_T("...")) != -1)) m_pDepotView->GetTreeCtrl().RunP4Files(itemStr); else if ((GetActiveView() == m_pDepotView) || (GetActiveView() == m_pDeltaView) || (itemStr.GetAt(0) == _T('/') && itemStr.GetAt(1) == _T('/')) || (_istalpha( itemStr.GetAt(0) ) && itemStr.GetAt(1) == _T(':'))) m_pDepotView->GetTreeCtrl().ExpandDepotString( itemStr, TRUE ); else { CP4PaneView * pView = DYNAMIC_DOWNCAST(CP4PaneView, GetActiveView()); if(pView) pView->OnEditPaste(itemStr); } ::CloseClipboard(); } #ifdef UNICODE else if (((hGlob = ::GetClipboardData(m_CF_FILENAMEW)) != NULL) #else else if (((hGlob = ::GetClipboardData(m_CF_FILENAME)) != NULL) #endif && ((p = (LPCTSTR)::GlobalLock(hGlob)) != NULL)) { // expand short filenames to long filenames CString itemStr = DemanglePath(p); ::GlobalUnlock(hGlob); if ((itemStr.FindOneOf(_T("?*")) == -1) && _istalpha( itemStr.GetAt(0) ) && itemStr.GetAt(1) == _T(':')) m_pDepotView->GetTreeCtrl().ExpandDepotString( itemStr, TRUE ); else m_pDepotView->GetTreeCtrl().RunP4Files(itemStr); ::CloseClipboard(); } else { ::CloseClipboard(); COleDataObject oleobj; oleobj.AttachClipboard(); FORMATETC fe; oleobj.BeginEnumFormats(); while (oleobj.GetNextFormat(&fe)) { if (HGLOBAL hGlobal = oleobj.GetGlobalData(fe.cfFormat)) { TCHAR fmtName[1024]; if(!GetClipboardFormatName(fe.cfFormat, fmtName, 1024) || lstrcmp(fmtName, _T("CF_VSREFPROJECTITEMS"))) continue; // when a single file is selected in the VS.NET solution explorer, // copying it to the clipboard yields a couple of formats. // The one registered as "CF_VSREFPROJECTITEMS" appears to // consist of the following: // DWORD offset; // size of header? // BYTE [offset-sizeof(DWORD)]; // unknown use // per file: // NULL terminated string string of WCHAR containing: // || // list terminating NULL WCHAR // // Note that only the 1st file in a list of multiple // files is found. This is because of potentially having // to go to the server when a node is expanded. Since this // server call is in the middle of a recursion and since // ExpandDepotString() will return while it awaits the // server results, looping when ExpandDepotString() // returns breaks its suspended recursion because it's // not written in a way that allows a second call before // the first one finishes. char *buf = (char*)GlobalLock(hGlobal); DWORD offset = *((DWORD*)buf); WCHAR * file = (WCHAR*)(buf + offset); m_pDepotView->GetTreeCtrl().SetAdd2ExpandItemList(TRUE); while (*file) { // let CString do conversion from unicode if needed CString itemStr(file); file += wcslen(file) + 1; int curPos = 0; // skip project GUID if(itemStr.Tokenize(_T("|"), curPos).IsEmpty()) break; // skip project file name if(itemStr.Tokenize(_T("|"), curPos).IsEmpty()) break; // get file name if((itemStr = itemStr.Tokenize(_T("|"), curPos)).IsEmpty()) break; // might be a solution explorer folder, not a file if(itemStr.Mid(1,2) != _T(":\\")) continue; // I don't think VS passes any wild cards - but it doesn't hurt... if ((itemStr.FindOneOf(_T("?*")) != -1) || (itemStr.Find(_T("...")) != -1)) { m_pDepotView->GetTreeCtrl().RunP4Files(itemStr); break; } else { m_pDepotView->GetTreeCtrl().ExpandDepotString( itemStr, TRUE ); while (m_pDepotView->GetTreeCtrl().IsExpandDepotContinuing() || SERVER_BUSY()) { if ( !m_pDeltaView->GetTreeCtrl().PumpMessages( ) ) break; Sleep(250); } } } GlobalUnlock(buf); m_pDepotView->GetTreeCtrl().SetAdd2ExpandItemList(FALSE); m_pDepotView->GetTreeCtrl().SelectExpandItemList(); } } } } } // These routines are called after the whole set of async commands that are run // at the time a connection is made to a port have finished. // If the user has opted to expand the depot treeview down a branch to a // particular node, start that expansion now. // void CMainFrame::FinishedGettingChgs(BOOL bNeed2RefreshOldChgs) { while (SERVER_BUSY()) Sleep(100); if (!TheApp()->m_SubmitPath.IsEmpty()) { int n; CString str; POSITION pos; if (TheApp()->m_SubmitPath.GetAt(0) != _T('/')) { // have to convert to depot syntax CCmd_Where *pCmd1 = new CCmd_Where; pCmd1->Init(NULL, RUN_SYNC); if ( pCmd1->Run(TheApp()->m_SubmitPath) && !pCmd1->GetError() && pCmd1->GetDepotFiles()->GetCount() ) { TheApp()->m_SubmitPath = pCmd1->GetDepotSyntax(); } delete pCmd1; if (TheApp()->m_SubmitPathList.GetCount()) { // copy the list CStringList list; for (pos = TheApp()->m_SubmitPathList.GetHeadPosition(); pos; ) list.AddHead(TheApp()->m_SubmitPathList.GetNext(pos)); TheApp()->m_SubmitPathList.RemoveAll(); for (POSITION pos = list.GetHeadPosition(); pos; ) { str = list.GetNext(pos); if (str.GetAt(0) != _T('/')) { CCmd_Where *pCmd1 = new CCmd_Where; pCmd1->Init(NULL, RUN_SYNC); if ( pCmd1->Run(str) && !pCmd1->GetError() && pCmd1->GetDepotFiles()->GetCount() ) { str = pCmd1->GetDepotSyntax(); } delete pCmd1; } TheApp()->m_SubmitPathList.AddHead(str); } } } long chgnbr = PositionChgs( TheApp()->m_SubmitPath, TRUE, FALSE ); if (chgnbr >= 0 && TheApp()->m_SubmitPathList.GetCount()) { for (pos = TheApp()->m_SubmitPathList.GetHeadPosition(); pos; ) { // wait a bit in 1/10 sec intervals to see if the server request finishes int t=5*GET_P4REGPTR()->BusyWaitTime(); do { Sleep(50); t -= 50; } while (SERVER_BUSY() && t > 0); str = TheApp()->m_SubmitPathList.GetNext(pos); if (chgnbr != (n = PositionChgs( str, TRUE, FALSE, TRUE ))) { CString txt; txt.FormatMessage(IDS_FILEINDIFFERENTCHGS_n_s_n_s, chgnbr, TheApp()->m_SubmitPath, n, str); AfxMessageBox( txt, MB_ICONSTOP ); ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); return; } } } if (chgnbr > 0) m_pDeltaView->SendMessage(WM_COMMAND, ID_EDIT_SELECT_ALL, 0); Sleep(0); SET_BUSYCURSOR(); // wait a bit in 1/10 sec intervals to see if the server request finishes int t=5*GET_P4REGPTR()->BusyWaitTime(); do { Sleep(50); t -= 50; } while (SERVER_BUSY() && t > 0); if (chgnbr >= 0) m_pDeltaView->GetTreeCtrl().OnChangeSubmit(); else { CString txt; txt.FormatMessage(IDS_CANTSUBMITFILE_s, TheApp()->m_SubmitPath); AfxMessageBox( txt, MB_ICONSTOP ); ::PostMessage(m_hWnd, WM_COMMAND, ID_APP_EXIT, 0); } return; } m_Need2RefreshOldChgs = bNeed2RefreshOldChgs; if (m_Need2Poll4Jobs) { m_Need2Poll4Jobs = 0; if (m_currentTab == 5) m_pJobView->GetListCtrl().OnViewUpdate( ); } else if (TheApp()->m_InitialView) { switch (TheApp()->m_InitialView) { case _T('L'): OnViewLabels(); break; case _T('B'): OnViewBranches(); break; case _T('U'): OnViewUsers(); break; case _T('C'): OnViewClients(); break; case _T('J'): OnViewJobs(); break; case _T('S'): OnViewSubmitted(); break; } TheApp()->m_InitialView = _T('\0'); } else ExpandDepotIfNeedBe(); } void CMainFrame::ExpandDepotIfNeedBe() { if (m_Need2ExpandDepot || !TheApp()->m_ExpandPath.IsEmpty()) { m_Need2ExpandDepot = 0; if (TheApp()->m_ExpandPath.IsEmpty()) { ExpandDepotString(GET_P4REGPTR()->GetExpandPath(), TRUE); } else { ExpandDepotString(TheApp()->m_ExpandPath, TRUE); TheApp()->m_ExpandPath.Empty(); } } } CString CMainFrame::GetCurrentItemPath() { return m_pDepotView->GetTreeCtrl().GetCurrentItemPath(); } void CMainFrame::OnUpdateWinExplore(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnWinExplore() { CString path = TheApp()->m_ClientRoot; if (path.IsEmpty() || path == _T("null")) path = _T("C:\\"); if (path.FindOneOf(_T(" &()[]{}^=;!'+,`~")) != -1) { path.TrimLeft(); path.TrimRight(); path = _T('\"') + path + _T('\"'); } STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; CreateProcess(NULL, const_cast((LPCTSTR)(TheApp()->GetExplorer() + path)), NULL, NULL, #ifdef UNICODE FALSE, DETACHED_PROCESS | NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, #else FALSE, DETACHED_PROCESS | NORMAL_PRIORITY_CLASS, #endif P4GetEnvironmentStrings(), NULL, &si, &pi); } void CMainFrame::OnUpdateCmdPrompt(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnCmdPromptPublic() { OnCmdPrompt(); } void CMainFrame::OnCmdPrompt() { // In order to create the DOS box in a reasonable directory, // we need the root of the current client. So first go get that after setting a // flag to indicate to the p4 info completion routine that that is what we are up to. if (TheApp()->m_ClientRoot.IsEmpty()) { m_GetCliRootAndContinue = P4INFO_DOSBOX; OnPerforceInfo(); } else OnCmdPromptContinue(); } void CMainFrame::OnCmdPromptContinue() { m_GetCliRootAndContinue = 0; TheApp()->m_ClientRoot.Replace('/', '\\'); TCHAR cmd[MAX_PATH+1]; GetEnvironmentVariable(_T("ComSpec"), cmd, MAX_PATH); // TheApp()->m_ClientRoot may be empty, if not connected to server // since CreateProcess expects a full path, including drive, this won't do // so, this gyration will ensure that we provide a legal path to CreateProcess TCHAR saveDir[MAX_PATH+1]; TCHAR useDir[MAX_PATH+1]; GetCurrentDirectory(MAX_PATH, saveDir); SetCurrentDirectory(TheApp()->m_ClientRoot); GetCurrentDirectory(MAX_PATH, useDir); SetCurrentDirectory(saveDir); STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; CreateProcess(NULL, cmd, NULL, NULL, #ifdef UNICODE FALSE, CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, #else FALSE, CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS, #endif P4GetEnvironmentStrings(), useDir, &si, &pi); } // Dropdown menus for Bookmark and Favorite toolbar buttons void CMainFrame::OnDropDown(NMHDR* pNotifyStruct, LRESULT* pResult) { // this function handles the dropdown menus from the toolbar NMTOOLBAR* pNMToolBar = (NMTOOLBAR*)pNotifyStruct; CRect rect; // translate the current toolbar item rectangle into screen coordinates // so that we'll know where to pop up the menu m_wndToolBar.GetToolBarCtrl().GetRect(pNMToolBar->iItem, &rect); rect.top = rect.bottom; ::ClientToScreen(pNMToolBar->hdr.hwndFrom, &rect.TopLeft()); CMenu *pMenu = 0; switch(pNMToolBar->iItem) { case ID_FAVORITES: pMenu = GetFavoriteMenu(); break; case ID_BOOKMARKS: pMenu = GetBookmarkMenu(); break; } pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, rect.left, rect.top + 1, AfxGetMainWnd()); *pResult = TBDDRET_DEFAULT; } // Bookmark Menu and Toolbar button CMenu * CMainFrame::GetBookmarkMenu() { CMenu *pMenu= GetMenu(); pMenu= pMenu->GetSubMenu(2); return pMenu->GetSubMenu(22); } void CMainFrame::OnUpdateBookmarks(CCmdUI* pCmdUI) { pCmdUI->Enable( !SERVER_BUSY() ); } void CMainFrame::OnBookmarks() { CMenu *pBkMkMenu = GetBookmarkMenu(); CRect rect; m_wndHSplitter.GetWindowRect(rect); pBkMkMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, rect.left, rect.top, AfxGetMainWnd()); } void CMainFrame::OnOrganizeBookmarks() { CBookmarks dlg; dlg.DoModal(); LoadBkMkMenu(); } void CMainFrame::LoadBkMkMenu() { BOOL bSM[MAX_BOOKMARKS+1]; CString str[MAX_BOOKMARKS+1]; CString temp; int i, j; int n, s; CMenu *pSubMenu; CMenu *pBkMkMenu = GetBookmarkMenu(); // clear the old BkMks submenus for (s = -1; ++s < MAX_BOOKMARK_SUBMENUS && ::IsMenu(m_BkMkSubMenu[s].m_hMenu); ) { while (m_BkMkSubMenu[s].DeleteMenu( 0, MF_BYPOSITION )) ; m_BkMkSubMenu[s].DestroyMenu(); } // clear the old BkMks menu for (i = -1; ++i < MAX_BOOKMARKS+1; ) { if (!(pBkMkMenu->DeleteMenu( 2, MF_BYPOSITION ))) break; } // Get the strings for(i = -1; ++i < MAX_BOOKMARKS; ) { str[i] = GET_P4REGPTR()->GetBkMkMenuName(i); bSM[i] = GET_P4REGPTR()->GetBkMkIsSubMenu(i); } if (str[0].GetLength()) { pBkMkMenu->AppendMenu(MF_SEPARATOR); // Load all BkMk menu items into BkMk menu for(s=i=-1, j=1; ++i < MAX_BOOKMARKS && !bSM[i]; ) { if (str[i].GetLength() > 0) { int id = ID_BKMK_1+j-1; if (id < ID_BKMK_11) { int nbr = id == ID_BKMK_10 ? 0 : id - ID_BKMK_1 + 1; CString speedkey; speedkey.FormatMessage(IDS_TAB_ALT_PLUS_n, nbr); if ((n = str[i].Find(_T('#'))) == -1) { str[i] += _T('\t'); speedkey.TrimLeft(); } else str[i].SetAt(n, _T('\t')); str[i] += speedkey; } else { if ((n = str[i].Find(_T('#'))) != -1) str[i].SetAt(n, _T('\t')); } pBkMkMenu->AppendMenu(MF_STRING, id, str[i]); j++; } } while ((i < MAX_BOOKMARKS) && (++s < MAX_BOOKMARK_SUBMENUS)) { CString name = str[i]; pSubMenu = &m_BkMkSubMenu[s]; pSubMenu->CreatePopupMenu(); while (++i < MAX_BOOKMARKS && !bSM[i]) { if (str[i].GetLength() > 0) { int id = ID_BKMK_1+j-1; if (id < ID_BKMK_11) { int nbr = id == ID_BKMK_10 ? 0 : id - ID_BKMK_1 + 1; CString speedkey; speedkey.FormatMessage(IDS_TAB_ALT_PLUS_n, nbr); if ((n = str[i].Find(_T('#'))) == -1) { str[i] += _T('\t'); speedkey.TrimLeft(); } else str[i].SetAt(n, _T('\t')); str[i] += speedkey; } pSubMenu->AppendMenu(MF_STRING, id, str[i]); j++; } } pBkMkMenu->AppendMenu(MF_POPUP, (UINT) pSubMenu->GetSafeHmenu(), name); } } } void CMainFrame::OnUpdateBkMk(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnBkMk(UINT nID) { int i; CString menuItem; if ((i = GetMenu()->GetMenuString(nID, menuItem, MF_BYCOMMAND)) == 0) { MessageBeep(0); return; } if ((i = menuItem.Find(_T('\t'))) != -1) menuItem = menuItem.Left(i); if ((menuItem.GetAt(0) == _T('/')) // no PCU info & depot syntax? || (menuItem.GetAt(1) == _T(':') && menuItem.GetAt(2) == _T('\\'))) // no PCU & local syntax? { ExpandDepotString( menuItem, TRUE ); return; } CString old_port = GET_P4REGPTR()->GetP4Port(); CString old_client = GET_P4REGPTR()->GetP4Client(); CString old_user = GET_P4REGPTR()->GetP4User(); CString port; CString client; CString user; if (menuItem.GetAt(0) == _T('*')) { port = old_port; menuItem = menuItem.Mid(1); menuItem.TrimLeft(_T(' ')); } else { if ((i = menuItem.Find(_T(' '))) != -1) { port = menuItem.Left(i); menuItem = menuItem.Mid(i); menuItem.TrimLeft(); } } if (menuItem.GetAt(0) == _T('*')) { client = old_client; menuItem = menuItem.Mid(1); menuItem.TrimLeft(_T(' ')); } else { if ((i = menuItem.Find(_T(' '))) != -1) { client = menuItem.Left(i); menuItem = menuItem.Mid(i); menuItem.TrimLeft(); } } if (menuItem.GetAt(0) == _T('*')) { user = old_user; menuItem.TrimLeft(_T("* ")); } else { if ((i = menuItem.Find(_T(' '))) != -1) { user = menuItem.Left(i); menuItem = menuItem.Mid(i); menuItem.TrimLeft(); } } if (port.IsEmpty() || client.IsEmpty() || user.IsEmpty()) { CString txt; GetMenu()->GetMenuString(nID, menuItem, MF_BYCOMMAND); txt.FormatMessage(IDS_BKMK_PCU_ERROR, menuItem); AfxMessageBox(txt, MB_OK); return; } // are all of port client user the same as the current ones? if (port == old_port && user == old_user && client == old_client) { ExpandDepotString( menuItem, TRUE ); return; } // one or more of port, client, user is different TheApp()->m_ExpandPath = menuItem; // change only the ones that are different if (port != old_port) if (!GET_P4REGPTR()->SetP4Port(port, TRUE, FALSE, FALSE)) AfxMessageBox( IDS_UNABLE_TO_WRITE_P4PORT_TO_THE_REGISTRY, MB_ICONEXCLAMATION); if (user != old_user) if (!GET_P4REGPTR()->SetP4User(user, TRUE, FALSE, FALSE)) AfxMessageBox( IDS_UNABLE_TO_WRITE_P4USER_TO_THE_REGISTRY, MB_ICONEXCLAMATION); if (client != old_client) { if(!ClientSpecSwitch(client, TRUE, old_port != port)) // calls OnPerforceOptions() { // put the old stuff back for port and user if client switch failed if (port != old_port) GET_P4REGPTR()->SetP4Port(old_port, TRUE, FALSE, FALSE); if (user != old_user) GET_P4REGPTR()->SetP4User(old_user, TRUE, FALSE, FALSE); return; } } else MainFrame()->OnPerforceOptions(FALSE, old_port != port);// if not changing client, need to call this for port/user chg } // Favorites Menu and Toolbar Button CMenu * CMainFrame::GetFavoriteMenu() { CMenu *pMenu= GetMenu(); pMenu= pMenu->GetSubMenu(3); return pMenu->GetSubMenu(5); } void CMainFrame::OnUpdateFavorites(CCmdUI* pCmdUI) { pCmdUI->Enable( !SERVER_BUSY() ); } void CMainFrame::OnUpdateOrganizeFavorites(CCmdUI* pCmdUI) { pCmdUI->Enable( !SERVER_BUSY() ); } void CMainFrame::OnOrganizeFavorites() { CFavorites dlg; dlg.DoModal(); LoadFavMenu(); } void CMainFrame::LoadFavMenu() { BOOL bSM[MAX_FAVORITES+1]; CString str[MAX_FAVORITES+1]; CString temp; int i, j; int n, s; CMenu *pSubMenu; CMenu *pFavMenu = GetFavoriteMenu(); // clear the old Favs submenus for (s = -1; ++s < MAX_FAVORITE_SUBMENUS && ::IsMenu(m_FavSubMenu[s].m_hMenu); ) { while (m_FavSubMenu[s].DeleteMenu( 2, MF_BYPOSITION )) ; m_FavSubMenu[s].DestroyMenu(); } // clear the old Favs menu for (i = -1; ++i < MAX_FAVORITES+1; ) { if (!(pFavMenu->DeleteMenu( 2, MF_BYPOSITION ))) break; } // Get the strings for(i = -1; ++i < MAX_FAVORITES; ) { bSM[i] = GET_P4REGPTR()->GetFavIsSubMenu(i); str[i] = GET_P4REGPTR()->GetFavMenuName(i); // remove the stuff from any @ thru any # if ((n = str[i].Find(_T('@'))) != -1) { j = str[i].Find(_T('#')); if (j == -1) j = str[i].GetLength(); if (j > n) { j -= n; str[i].Delete(n, j); } } } if (str[0].GetLength()) { pFavMenu->AppendMenu(MF_SEPARATOR); // Load all Fav menu items into Fav menu for(s=i=-1, j=1; ++i < MAX_FAVORITES && !bSM[i]; ) { if (str[i].GetLength() > 0) { int id = ID_FAV_1+j-1; if (id < ID_FAV_11) { int nbr = id == ID_FAV_10 ? 0 : id - ID_FAV_1 + 1; CString speedkey; speedkey.FormatMessage(IDS_SHIFT_ALT_PLUS_n, nbr); if ((n = str[i].Find(_T('#'))) == -1) { str[i] += _T('\t'); speedkey.TrimLeft(); } else str[i].SetAt(n, _T('\t')); str[i] += speedkey; } else if ((n = str[i].Find(_T('#'))) != -1) { str[i].SetAt(n, _T('\t')); } pFavMenu->AppendMenu(MF_STRING, id, str[i]); j++; } } while ((i < MAX_FAVORITES) && (++s < MAX_FAVORITE_SUBMENUS)) { CString name = str[i]; pSubMenu = &m_FavSubMenu[s]; pSubMenu->CreatePopupMenu(); while (++i < MAX_FAVORITES && !bSM[i]) { if (str[i].GetLength() > 0) { int id = ID_FAV_1+j-1; if (id < ID_FAV_11) { int nbr = id == ID_FAV_10 ? 0 : id - ID_FAV_1 + 1; CString speedkey; speedkey.FormatMessage(IDS_SHIFT_ALT_PLUS_n, nbr); if ((n = str[i].Find(_T('#'))) == -1) { str[i] += _T('\t'); speedkey.TrimLeft(); } else str[i].SetAt(n, _T('\t')); str[i] += speedkey; } else if ((n = str[i].Find(_T('#'))) != -1) { str[i].SetAt(n, _T('\t')); } pSubMenu->AppendMenu(MF_STRING, id, str[i]); j++; } } pFavMenu->AppendMenu(MF_POPUP, (UINT) pSubMenu->GetSafeHmenu(), name); } } } void CMainFrame::OnUpdateFav(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnFav(UINT nID) { int i; int firstsep; int secondsep; CString menuStr; CString port; CString client; CString user; CString wasUser = GET_P4REGPTR()->GetP4User(); CString wasPort = GET_P4REGPTR()->GetP4Port(); if (IsModlessUp() || !GetMenu()->GetMenuString(nID, menuStr, MF_BYCOMMAND)) { ASSERT(NULL); return; } if ((i = menuStr.Find(_T('\t'))) != -1) menuStr = menuStr.Left(i); if (menuStr.GetAt(0) == _T('\"')) firstsep = menuStr.Find(_T('\"'),1) + 1; else firstsep = menuStr.Find(_T(' ')); if (firstsep == -1) { port = menuStr; client= GET_P4REGPTR()->GetP4Client(); user = wasUser; } else { port = menuStr.Left(firstsep); port.TrimLeft(_T('\"')); port.TrimRight(_T('\"')); secondsep= menuStr.Find(_T(' '), firstsep+1); if (secondsep == -1) { client= menuStr.Mid(firstsep+1); user = wasUser; } else { client= menuStr.Mid(firstsep+1, secondsep - firstsep - 1); user = menuStr.Right(menuStr.GetLength() - secondsep - 1); } } if (GET_P4REGPTR()->GetExpandFlag() == 1) GET_P4REGPTR()->AddMRUPcuPath(GetCurrentItemPath()); GET_P4REGPTR()->SetP4Port(port, TRUE, FALSE, FALSE); GET_P4REGPTR()->SetP4User(user, TRUE, FALSE, FALSE); if (!ClientSpecSwitch(client, TRUE, wasPort != port))// calls OnPerforceOptions() { GET_P4REGPTR()->SetP4Port(wasPort, TRUE, FALSE, FALSE); // put old port back if client switched failed GET_P4REGPTR()->SetP4User(wasUser, TRUE, FALSE, FALSE); // put old user back if client switched failed } } void CMainFrame::OnUpdateAddFavorite(CCmdUI* pCmdUI) { pCmdUI->Enable( !SERVER_BUSY() ); } void CMainFrame::OnAddFavorite() { BOOL bSM[MAX_FAVORITES+1]; CString str[MAX_FAVORITES+1]; CString temp; int i, n; int j = 0; int k = MAX_FAVORITES+1; int s = MAX_FAVORITES+1; int found = -1; LPCTSTR p = GET_P4REGPTR()->GetP4Port(); LPCTSTR c = GET_P4REGPTR()->GetP4Client(); LPCTSTR u = GET_P4REGPTR()->GetP4User(); CString txt; CString pcu; CString oldpcu; CString newpcu; if (p && *p && c && *c && u && *u) { CString port = p; if (port.FindOneOf(_T("@#")) != -1) { txt.FormatMessage(IDS_FAV_CANT_HAVE_AT_OR_POUND_IN_PORT_s, port); AfxMessageBox( txt, MB_ICONEXCLAMATION ); return; } LPCTSTR q; for (q = p; *++q; ) { if (*q == _T(' ')) break; } pcu.Format(*q ? _T("\"%s\" %s %s") : _T("%s %s %s"), p, c, u); } else { MessageBeep(0); return; } // Get the strings for(i = -1; ++i < MAX_FAVORITES; ) { txt = str[i] = GET_P4REGPTR()->GetFavMenuName(i); if ((n = txt.Find(_T('#'))) > 0) txt = txt.Left(n); if ((n = txt.Find(_T('@'))) > 0) txt = txt.Left(n); if (txt == pcu) { AddToStatus(pcu + LoadStringResource(IDS_ALREADY_FAVORITE)); oldpcu = pcu; found = i; } bSM[i] = GET_P4REGPTR()->GetFavIsSubMenu(i); if (bSM[i]) { j = i; if (s == MAX_FAVORITES+1) s = i; } else if (!(str[i].IsEmpty())) j = i; else if (k == MAX_FAVORITES+1) k = i; } if (k == MAX_FAVORITES+1) { MessageBeep(0); return; } // Allow the user to enter a description or make changes CFavEditDlg dlg; if (found != -1) { if ((n = str[found].Find(_T('#'))) > 0) { pcu += _T('\t') + str[found].Mid(n+1); txt = str[found].Left(n); } else txt = str[found]; if ((n = txt.Find(_T('@'))) != -1) txt = txt.Mid(n+1); else txt.Empty(); dlg.SetTitle(LoadStringResource(IDS_CHANGE_FAVORITE)); } dlg.SetNewMenuName(pcu); dlg.SetIsSubMenu(FALSE); dlg.SetRadioShow(2); dlg.SetCanCr8SubMenu(FALSE); dlg.SetFocusDesc(TRUE); if ((dlg.DoModal() != IDOK) || !((dlg.GetNewMenuName()).GetLength())) return; pcu = dlg.GetNewMenuName(); if ((n = pcu.Find(_T('\t'))) != -1) { newpcu = pcu.Left(n); CString desc = pcu.Mid(n+1); if (!txt.IsEmpty()) pcu = newpcu + _T('@') + txt; else pcu = newpcu; pcu += _T('#') + desc; } else { newpcu = pcu; if (!txt.IsEmpty()) pcu += _T('@') + txt; } // Handle replacment if p/c/u are same as found BOOL bAdded = FALSE; if ((found != -1) && (oldpcu == newpcu)) { s = -1; str[found] = pcu; bAdded = TRUE; } // Reload the strings for(i = j = -1; ++j < MAX_FAVORITES; ) { if (j == s) { GET_P4REGPTR()->SetFavMenuName(j, pcu); GET_P4REGPTR()->SetFavIsSubMenu(j, FALSE); bAdded = TRUE; } else { GET_P4REGPTR()->SetFavMenuName(j, str[++i]); GET_P4REGPTR()->SetFavIsSubMenu(j, bSM[i]); } } if (!bAdded) { GET_P4REGPTR()->SetFavMenuName(k, pcu); GET_P4REGPTR()->SetFavIsSubMenu(k, FALSE); } LoadFavMenu(); pcu.Replace(_T('#'), _T(' ')); AddToStatus(pcu + LoadStringResource(IDS_ADDED_TO_FAVORITES)); } void CMainFrame::OnUpdateLogout(CCmdUI* pCmdUI) { pCmdUI->Enable( !SERVER_BUSY() && GET_SERVERLEVEL() >= 18); } void CMainFrame::OnLogout() { CCmd_Logout *pCmd = new CCmd_Logout; // run p4 logout pCmd->Init(NULL, RUN_SYNC); pCmd->Run(FALSE); // run the logout command delete pCmd; } void CMainFrame::OnCustomizeTools() { CToolsDlg dlg; dlg.DoModal(); LoadToolsMenu(); } void CMainFrame::LoadToolsMenu() { BOOL bSM[MAX_TOOLS+1]; CString str[MAX_TOOLS+1]; CString temp; int i, j; int s; CMenu *pMenu= GetMenu(); CMenu *pToolsMenu = pMenu->GetSubMenu(10); CMenu *pSubMenu; // clear the old tools submenus for (s = -1; ++s < MAX_TOOLS_SUBMENUS && ::IsMenu(m_ToolsSubMenu[s].m_hMenu); ) { while (m_ToolsSubMenu[s].DeleteMenu( 0, MF_BYPOSITION )) ; m_ToolsSubMenu[s].DestroyMenu(); } // clear the old tools menu for (i = -1; ++i < MAX_TOOLS+1; ) { if (!(pToolsMenu->DeleteMenu( 3, MF_BYPOSITION ))) break; } // Get the strings for(i = -1; ++i < MAX_TOOLS; ) { str[i] = GET_P4REGPTR()->GetToolMenuName(i); bSM[i] = GET_P4REGPTR()->GetToolIsSubMenu(i); } if (str[0].GetLength()) { pToolsMenu->AppendMenu(MF_SEPARATOR); // Load all Tool menu items into Tools menu for(s=i=-1, j=1; ++i < MAX_TOOLS && !bSM[i]; ) { if (str[i].GetLength() > 0) { pToolsMenu->AppendMenu(MF_STRING, ID_TOOL_1+j-1, str[i]); j++; } } while ((i < MAX_TOOLS) && (++s < MAX_TOOLS_SUBMENUS)) { CString name = str[i]; pSubMenu = &m_ToolsSubMenu[s]; pSubMenu->CreatePopupMenu(); j++; while (++i < MAX_TOOLS && !bSM[i]) { if (str[i].GetLength() > 0) { pSubMenu->AppendMenu(MF_STRING, ID_TOOL_1+j-1, str[i]); j++; } } pToolsMenu->AppendMenu(MF_POPUP, (UINT) pSubMenu->GetSafeHmenu(), name); } } } void CMainFrame::OnUpdateToolsImport(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnToolsImport() { CFileDialog fDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NONETWORKBUTTON, LoadStringResource(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_FILTER), this, m_osVer.dwMajorVersion < 5 ? OPENFILENAME_SIZE_VERSION_400 : sizeof(OPENFILENAME)); TCHAR buf[LONGPATH+1]; lstrcpy(buf, _T("tools.txt")); fDlg.m_ofn.lpstrFile= buf; fDlg.m_ofn.nMaxFile= LONGPATH; // Set the dlg caption CString title = LoadStringResource(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_TITLE); fDlg.m_ofn.lpstrTitle = title; // We dont need no stinking file title fDlg.m_ofn.lpstrFileTitle=NULL; // Set the initial directory fDlg.m_ofn.lpstrInitialDir=GET_P4REGPTR()->GetTempDir(); // Set the user defined filter TCHAR customFilterBuf[512] = _T(""); fDlg.m_ofn.lpstrCustomFilter= customFilterBuf; fDlg.m_ofn.nMaxCustFilter=512; CString errorTxt; int retcode=fDlg.DoModal(); if(retcode == IDOK) { CString filename = fDlg.GetPathName(); ImportTools(&filename, &errorTxt); } else if(retcode == IDCANCEL) // an error { DWORD exError=CommDlgExtendedError(); if(exError != 0) errorTxt.FormatMessage(IDS_EXTENDED_ERROR_n_IN_FILEDIALOG, exError); } else { DWORD error=GetLastError(); if(error) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); errorTxt = (TCHAR *)lpMsgBuf; } else errorTxt=LoadStringResource(IDS_UNKNOWN_FILEDIALOG_ERROR); } if(errorTxt.GetLength() > 0) AfxMessageBox(errorTxt, MB_ICONSTOP); } void CMainFrame::ImportTools(CString *filename, CString *errorTxt) { int toolnbr; int nbradded = 0; HANDLE hImportFile; if ((hImportFile=CreateFile(*filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) { DWORD exError=GetLastError(); errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_WRITE_ERROR_s_n, *filename, exError); } else { for (toolnbr=MAX_TOOLS; toolnbr--; ) { CString toolname = GET_P4REGPTR()->GetToolMenuName(toolnbr); if (!toolname.IsEmpty()) break; } DWORD NumberOfBytesRead; DWORD fsize = GetFileSize(hImportFile, NULL); HGLOBAL hText= ::GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT, fsize+4); LPTSTR pStr= (LPTSTR) ::GlobalLock( hText ); if (ReadFile(hImportFile, pStr, fsize, &NumberOfBytesRead, NULL)) { #ifdef UNICODE if (*pStr == 0xFEFF) pStr++; else { HGLOBAL h= ::GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT, fsize*2+4); LPWSTR pUTF= (LPWSTR) ::GlobalLock( h ); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pStr, -1, pUTF, fsize*2+4); pStr = pUTF; ::GlobalUnlock( hText ); ::GlobalFree( hText ); hText = h; } #else if ((unsigned char)*pStr == (unsigned char)0xFF && (unsigned char)*(pStr+1) == (unsigned char)0xFE) { AfxMessageBox(IDS_UNABLE_TO_IMPORT_UNICODE_FILE); return; } #endif while (*pStr) { if ((*pStr++ == _T('>')) && (*pStr++ == _T('>'))) { if (++toolnbr >= MAX_TOOLS) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_TOO_MANY_TOOLS_s, pStr); break; } else { LPTSTR p = pStr; CString ToolMenuName; CString ToolCommand; CString ToolArgs; CString ToolInitDir; CString ToolPromptText; BOOL ToolIsConsole; BOOL ToolIsPrompt; BOOL ToolIsOutput2Status = FALSE; BOOL ToolIsCloseOnExit; BOOL ToolIsShowBrowse; BOOL ToolIsSubMenu; BOOL ToolOnContext; BOOL ToolIsRefresh; CString buffer; pStr = GetNextToolToken(pStr, ToolMenuName); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, p); break; } pStr = GetNextToolToken(pStr, ToolCommand); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } pStr = GetNextToolToken(pStr, ToolArgs); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } pStr = GetNextToolToken(pStr, ToolInitDir); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } pStr = GetNextToolToken(pStr, buffer); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } ToolIsConsole = buffer.GetAt(0) == _T('0') ? FALSE : TRUE; pStr = GetNextToolToken(pStr, buffer); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } ToolIsPrompt = buffer.GetAt(0) == _T('0') ? FALSE : TRUE; pStr = GetNextToolToken(pStr, buffer); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } ToolIsCloseOnExit = buffer.GetAt(0) == _T('0') ? FALSE : TRUE; pStr = GetNextToolToken(pStr, buffer); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } ToolIsSubMenu = buffer.GetAt(0) == _T('0') ? FALSE : TRUE; if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } if (*pStr != '\n') { pStr = GetNextToolToken(pStr, buffer); ToolIsShowBrowse = buffer.GetAt(0) == _T('0') ? FALSE : TRUE; if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } if (*pStr != '\n') { pStr = GetNextToolToken(pStr, buffer); ToolOnContext = buffer.GetAt(0) == _T('0') ? FALSE : TRUE; if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } if (*pStr != '\n') { pStr = GetNextToolToken(pStr, buffer); ToolIsRefresh = buffer.GetAt(0) == _T('0') ? FALSE : TRUE; if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } if (*pStr != '\n') { pStr = GetNextToolToken(pStr, ToolPromptText); if (pStr == NULL) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } if (*pStr != '\n') { pStr = GetNextToolToken(pStr, buffer); ToolIsOutput2Status = buffer.GetAt(0) == _T('0') ? FALSE : TRUE; if ((pStr == NULL) || ((*pStr++ != '\n') && (*pStr != '\t'))) { errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_ERROR_PARSING_s, ToolMenuName); break; } } else { pStr++; ToolIsOutput2Status = FALSE; } } else { pStr++; ToolPromptText = _T(""); } } else { pStr++; ToolIsRefresh = FALSE; } } else { pStr++; ToolOnContext = ToolIsRefresh = FALSE; } } else { pStr++; ToolIsShowBrowse = ToolOnContext = ToolIsRefresh = FALSE; } GET_P4REGPTR()->SetToolMenuName(toolnbr, ToolMenuName); GET_P4REGPTR()->SetToolCommand(toolnbr, ToolCommand); GET_P4REGPTR()->SetToolArgs(toolnbr, ToolArgs); GET_P4REGPTR()->SetToolInitDir(toolnbr, ToolInitDir); GET_P4REGPTR()->SetToolPromptText(toolnbr, ToolPromptText); GET_P4REGPTR()->SetToolIsConsole(toolnbr, ToolIsConsole); GET_P4REGPTR()->SetToolIsPrompt(toolnbr, ToolIsPrompt); GET_P4REGPTR()->SetToolIsOutput2Status(toolnbr, ToolIsOutput2Status); GET_P4REGPTR()->SetToolIsCloseOnExit(toolnbr, ToolIsCloseOnExit); GET_P4REGPTR()->SetToolIsSubMenu(toolnbr, ToolIsSubMenu); GET_P4REGPTR()->SetToolIsShowBrowse(toolnbr, ToolIsShowBrowse); GET_P4REGPTR()->SetToolOnContext(toolnbr, ToolOnContext); GET_P4REGPTR()->SetToolIsRefresh(toolnbr, ToolIsRefresh); ++nbradded; } } else while (*pStr && (*pStr++ != _T('\n'))) ; } LoadToolsMenu(); if (nbradded) { CString txt; txt.FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_n_TOOLS_ADDED_FROM_s, nbradded, *filename); AddToStatusLog(txt, SV_COMPLETION); } } else errorTxt->FormatMessage(IDS_TOOLSDLG_READ_CUSTOM_TOOLS_READ_ERROR_s, *filename); ::GlobalUnlock( hText ); ::GlobalFree( hText ); CloseHandle(hImportFile); } } LPTSTR CMainFrame::GetNextToolToken(LPTSTR pStr, CString &token) { LPTSTR p; for (p = pStr-1; (TBYTE)(*++p) >= _T(' '); ) ; if ((*p != _T('\t')) && (*p != _T('\r'))) return NULL; *p = _T('\0'); token = pStr; return p+1; } void CMainFrame::OnUpdateToolsExport(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnToolsExport() { CFileDialog fDlg(FALSE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NONETWORKBUTTON, LoadStringResource(IDS_TOOLS_EXPORT_FILTER), this, m_osVer.dwMajorVersion < 5 ? OPENFILENAME_SIZE_VERSION_400 : sizeof(OPENFILENAME)); TCHAR buf[LONGPATH+1]; lstrcpy(buf, LoadStringResource(IDS_TOOLS_EXPORT_DEFAULT_FILE)); fDlg.m_ofn.lpstrFile= buf; fDlg.m_ofn.nMaxFile= LONGPATH; // Set the dlg caption CString title = LoadStringResource(IDS_TOOLS_EXPORT_TITLE); fDlg.m_ofn.lpstrTitle=title; // We dont need no stinking file title fDlg.m_ofn.lpstrFileTitle=NULL; // Set the initial directory fDlg.m_ofn.lpstrInitialDir=GET_P4REGPTR()->GetTempDir(); // Set the user defined filter TCHAR customFilterBuf[512] = _T(""); fDlg.m_ofn.lpstrCustomFilter= customFilterBuf; fDlg.m_ofn.nMaxCustFilter=512; CString errorTxt; int retcode=fDlg.DoModal(); if(retcode == IDOK) { CString filename = fDlg.GetPathName(); HANDLE hExportFile; if ((hExportFile=CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { DWORD exError=GetLastError(); errorTxt.FormatMessage(IDS_TOOLS_EXPORT_WRITE_ERROR_s_n, filename, exError); } else { DWORD NumberOfBytesWritten; #ifdef UNICODE TCHAR uhdr[] = {0xFEFF}; WriteFile(hExportFile, uhdr, 2, &NumberOfBytesWritten, NULL); #endif CString recd; recd.Format(_T("P4Win Tools File from %s\r\n"), GET_P4REGPTR()->GetP4User()); WriteFile(hExportFile, recd, recd.GetLength()*sizeof(TCHAR), &NumberOfBytesWritten, NULL); recd.FormatMessage(IDS_IMPORTED_FROM_USER, GET_P4REGPTR()->GetP4User()); WriteFile(hExportFile, recd, recd.GetLength()*sizeof(TCHAR), &NumberOfBytesWritten, NULL); for (int i = -1; ++i < MAX_TOOLS; ) { CString ToolMenuName = GET_P4REGPTR()->GetToolMenuName(i); if (ToolMenuName.IsEmpty()) break; CString ToolCommand = GET_P4REGPTR()->GetToolCommand(i); CString ToolArgs = GET_P4REGPTR()->GetToolArgs(i); CString ToolInitDir = GET_P4REGPTR()->GetToolInitDir(i); CString ToolPromptText = GET_P4REGPTR()->GetToolPromptText(i); if ((ToolMenuName.Find(_T("\t\r\n")) != -1) || (ToolCommand.Find(_T("\t\r\n")) != -1) || (ToolArgs.Find(_T("\t\r\n")) != -1) || (ToolInitDir.Find(_T("\t\r\n")) != -1) || (ToolPromptText.Find(_T("\t\r\n")) != -1)) { recd.FormatMessage(IDS_TOOL_EXPORT_DEF_ERROR_s_s, ToolMenuName, ToolMenuName); AddToStatusLog(recd, SV_WARNING); continue; } BOOL ToolIsConsole = GET_P4REGPTR()->GetToolIsConsole(i); BOOL ToolIsPrompt = GET_P4REGPTR()->GetToolIsPrompt(i); BOOL ToolIsOutput2Status = GET_P4REGPTR()->GetToolIsOutput2Status(i); BOOL ToolIsCloseOnExit = GET_P4REGPTR()->GetToolIsCloseOnExit(i); BOOL ToolIsSubMenu = GET_P4REGPTR()->GetToolIsSubMenu(i); BOOL ToolIsShowBrowse = GET_P4REGPTR()->GetToolIsShowBrowse(i); BOOL ToolOnContext = GET_P4REGPTR()->GetToolOnContext(i); BOOL ToolIsRefresh = GET_P4REGPTR()->GetToolIsRefresh(i); recd.Format(_T(">>%s\t%s\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\t%d\r\n"), ToolMenuName, ToolCommand, ToolArgs, ToolInitDir, ToolIsConsole, ToolIsPrompt, ToolIsCloseOnExit, ToolIsSubMenu, ToolIsShowBrowse, ToolOnContext, ToolIsRefresh, ToolPromptText, ToolIsOutput2Status); WriteFile(hExportFile, recd, recd.GetLength()*sizeof(TCHAR), &NumberOfBytesWritten, NULL); } CloseHandle(hExportFile); recd.FormatMessage(IDS_TOOL_EXPORT_TOOLS_EXPORTED_TO_s, filename); AddToStatusLog(recd, SV_COMPLETION); } } else if(retcode == IDCANCEL) // an error { DWORD exError=CommDlgExtendedError(); if(exError != 0) errorTxt.FormatMessage(IDS_EXTENDED_ERROR_n_IN_FILEDIALOG, exError); } else { DWORD error=GetLastError(); if(error) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); errorTxt = (TCHAR *)lpMsgBuf; } else errorTxt.LoadString(IDS_UNKNOWN_FILEDIALOG_ERROR); } if(errorTxt.GetLength() > 0) AfxMessageBox(errorTxt, MB_ICONSTOP); } #define BUFSIZE 4096 void CMainFrame::OnTool(UINT nID) { int index = nID - ID_TOOL_1; int i; int nbrSelected = 1; BOOL success; TCHAR sw; CString txt; CString command = GET_P4REGPTR()->GetToolCommand(index); CString args = GET_P4REGPTR()->GetToolArgs(index); CString initDir = GET_P4REGPTR()->GetToolInitDir(index); CString promptText = GET_P4REGPTR()->GetToolPromptText(index); BOOL isConsole = GET_P4REGPTR()->GetToolIsConsole(index); BOOL isPrompt = GET_P4REGPTR()->GetToolIsPrompt(index); BOOL isOutput2Status = GET_P4REGPTR()->GetToolIsOutput2Status(index); BOOL isCloseOnExit = GET_P4REGPTR()->GetToolIsCloseOnExit(index); BOOL isShowBrowse = GET_P4REGPTR()->GetToolIsShowBrowse(index); BOOL isRefresh = GET_P4REGPTR()->GetToolIsRefresh(index); #ifdef UNICODE DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT; #else DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS; #endif PROCESS_INFORMATION procInfo = {0}; STARTUPINFO startInfo = {0}; TCHAR cmdTitle[255]; GetStartupInfo(&startInfo); startInfo.lpReserved= startInfo.lpDesktop= NULL; startInfo.dwFlags = STARTF_USESHOWWINDOW; startInfo.wShowWindow = SW_SHOWNORMAL; if (!initDir.IsEmpty() && initDir.GetAt(0) == _T('$') && initDir.GetAt(1) == _T('r')) { if (TheApp()->m_ClientRoot.IsEmpty()) { CCmd_Info cmd; cmd.Init( NULL, RUN_SYNC ); if( cmd.Run( ) && !cmd.GetError() ) { CP4Info const &info = cmd.GetInfo(); if (!info.m_ClientRoot.IsEmpty( )) { TheApp()->Set_m_ClientRoot(info.m_ClientRoot); } } } initDir = ReplaceDollarArg(initDir, 0, TheApp()->m_ClientRoot); } HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup; hChildStdoutWr = hChildStdoutRdDup = 0; if(isConsole) { TCHAR cmd[MAX_PATH+1]; GetEnvironmentVariable(_T("ComSpec"), cmd, MAX_PATH); // Trunc cmd string if longer than will ft in title if (command.GetLength() >= sizeof(cmdTitle)/sizeof(TCHAR)) { CString temp = command.Left(sizeof(cmdTitle)/sizeof(TCHAR) - 10); lstrcpy(cmdTitle, temp); } else lstrcpy(cmdTitle, command); startInfo.lpTitle= cmdTitle; startInfo.dwXCountChars=80; startInfo.dwYCountChars=1000; startInfo.dwFlags=STARTF_USECOUNTCHARS; startInfo.cbReserved2=0; startInfo.lpReserved2=NULL; dwCreationFlags |= CREATE_NEW_CONSOLE; if (isCloseOnExit) command = cmd + CString(_T(" /c ")) + command; else command = cmd + CString(_T(" /k ")) + command; } else { if (command.IsEmpty() && args.IsEmpty()) { if (initDir == _T("%f")) { BOOL rc = FALSE; CStringList list; CView * pView = GetActiveView(); if (pView == (CView *) m_pDepotView) rc = m_pDepotView->GetTreeCtrl().GetSelectedFiles(&list); else if (pView == (CView *) m_pDeltaView) rc = m_pDeltaView->GetTreeCtrl().GetSelectedFiles(&list); if (rc && !list.IsEmpty()) { initDir = list.GetHead(); if ((i = initDir.ReverseFind(_T('\\'))) != -1) initDir = initDir.Left(i); } else initDir.Empty(); } if (initDir.Find(_T(" ")) != -1) { initDir.TrimLeft(); initDir.TrimRight(); initDir = _T('\"') + initDir + _T('\"'); } command = TheApp()->GetExplorer() + initDir; } } CString commandLine = command + _T(" "); CString promptStr; if (isPrompt) { CToolsArgs dlg; CString menuName = GET_P4REGPTR()->GetToolMenuName(index); CString promptText = GET_P4REGPTR()->GetToolPromptText(index); menuName.Remove(_T('&')); CString txt; if (promptText.IsEmpty()) txt.FormatMessage(IDS_TOOLS_ARGS_FOR_s, menuName); else txt.FormatMessage(IDS_TOOLS_s_COLON_s, menuName, promptText); dlg.SetTitle(txt); txt.FormatMessage(IDS_TOOLS_s_ARGUMENTS_s, command, args); dlg.SetStatusText(txt); dlg.SetShowBrowse(isShowBrowse); int rc = dlg.DoModal(); SetMessageText(_T("")); if (rc == IDCANCEL) return; promptStr = dlg.GetArgs(); } if (!promptStr.IsEmpty()) // look for $D in command line { bool b = false; CString txt = commandLine + _T(" ") + args; for (i=0; (i = FindDollarArg(txt, i+1)) != -1; ) { if (txt[i+1] == 'D') { b = true; break; } } if (!b) // if didn't find $D, stick prompt between cmd and args commandLine += promptStr + _T(" "); } commandLine += args; for (i=0; (i = FindDollarArg(commandLine, i+1)) != -1; ) { switch (sw = commandLine.GetAt(i+1)) { case _T('p'): commandLine = ReplaceDollarArg(commandLine, i, GET_P4REGPTR()->GetP4Port()); break; case _T('c'): commandLine = ReplaceDollarArg(commandLine, i, GET_P4REGPTR()->GetP4Client()); break; case _T('u'): commandLine = ReplaceDollarArg(commandLine, i, GET_P4REGPTR()->GetP4User()); break; case _T('P'): commandLine = ReplaceDollarArg(commandLine, i, GET_P4REGPTR()->GetP4UserPassword()); break; case _T('D'): commandLine = ReplaceDollarArg(commandLine, i, promptStr); break; case _T('r'): { if (TheApp()->m_ClientRoot.IsEmpty()) { CCmd_Info cmd; cmd.Init( NULL, RUN_SYNC ); if( cmd.Run( ) && !cmd.GetError() ) { CP4Info const &info = cmd.GetInfo(); if (!info.m_ClientRoot.IsEmpty( )) { TheApp()->Set_m_ClientRoot(info.m_ClientRoot); } } } commandLine = ReplaceDollarArg(commandLine, i, TheApp()->m_ClientRoot); break; } } } i = FindPercentArg(commandLine, 0); if (i != -1) { if (FindPercentArg(commandLine, i+1) != -1) { CString txt; txt.FormatMessage(IDS_TOOLS_MORE_THAN_ONE_REPLACEABLE_ARG_NOT_ALLOWED_s, commandLine); AfxMessageBox(txt, MB_ICONSTOP); return; } BOOL bUseOpened = FALSE; switch (sw = commandLine.GetAt(i+1)) { case _T('O'): bUseOpened = TRUE; goto doF; case _T('L'): if (GetActiveView() != (CView *) m_pDepotView) return; goto doF; case _T('R'): if (GetActiveView() != (CView *) m_pDeltaView) return; case _T('D'): case _T('F'): doF: if ((nbrSelected = InsertAllSelectedFilesIntoCmdline(commandLine, i, bUseOpened, sw == _T('D'))) == 0) txt.FormatMessage( tolower(commandLine.GetAt(i+1)) == _T('o') ? IDS_TOOLS_NO_OPENED_FILES_SELECTED_CANNOT_RUN_s : IDS_TOOLS_NO_FILES_SELECTED_CANNOT_RUN_s, commandLine); else if (nbrSelected < 1) txt.FormatMessage(IDS_TOOLS_UNABLE_TO_DETERMINE_PATH_CANNONT_RUN_s, commandLine); if (nbrSelected <= 0) { AfxMessageBox(txt, MB_ICONSTOP); return; } break; case _T('o'): bUseOpened = TRUE; goto dof; case _T('l'): if (GetActiveView() != (CView *) m_pDepotView) return; goto dof; case _T('P'): // Pending Chg sw = (TCHAR)tolower(sw); case _T('p'): case _T('r'): if (GetActiveView() != (CView *) m_pDeltaView) return; case _T('d'): case _T('f'): dof: ExecOnceForEachFile(i, commandLine, sw, initDir.IsEmpty() ? (LPCTSTR)NULL : LPCTSTR(initDir), dwCreationFlags, &startInfo, &procInfo, command.IsEmpty(), isRefresh, isOutput2Status); return; case _T('C'): case _T('J'): // job sw = (TCHAR)tolower(sw); case _T('c'): case _T('j'): // job if (GetActiveView() == (CView *) m_pDeltaView) goto dof; case _T('s'): // submitted change case _T('a'): // label case _T('b'): // branch case _T('i'): // client case _T('u'): // user case _T('S'): // submitted change case _T('A'): // label case _T('B'): // branch case _T('I'): // client case _T('U'): // user if ((nbrSelected = InsertSelectedObjectIntoCmdline(commandLine, i)) == 0) txt.FormatMessage(IDS_TOOLS_NO_OBJECT_SELECTED_CANNOT_RUN_s, commandLine); else if (nbrSelected < 1) txt.FormatMessage(IDS_TOOLS_UNABLE_TO_DETERMINE_OBJECT_CANNOT_RUN_s, commandLine); if (nbrSelected <= 0) { AfxMessageBox(txt, MB_ICONSTOP); return; } break; } } if (initDir == _T("%f")) { BOOL rc = FALSE; CStringList list; CView * pView = GetActiveView(); if (pView == (CView *) m_pDepotView) rc = m_pDepotView->GetTreeCtrl().GetSelectedFiles(&list); else if (pView == (CView *) m_pDeltaView) rc = m_pDeltaView->GetTreeCtrl().GetSelectedFiles(&list); if (rc && !list.IsEmpty()) { initDir = list.GetHead(); if ((i = initDir.ReverseFind(_T('\\'))) != -1) initDir = initDir.Left(i); } else initDir.Empty(); } if (command.IsEmpty()) { if (nbrSelected > 1) { txt = GET_P4REGPTR()->GetToolMenuName(index); txt.Remove('&'); txt.FormatMessage(IDS_TOOLS_TOOLS_s_REQUIRES_ONE_FILE_SELECTED, txt); AfxMessageBox(txt, MB_ICONSTOP); return; } commandLine.TrimLeft(_T(" \"")); commandLine.TrimRight(_T(" \"")); success=((int)(ShellExecute( m_hWnd, _T("Open.VisualStudio.7.1"), commandLine, NULL, initDir.IsEmpty() ? (LPCTSTR)NULL : initDir, SW_SHOWNORMAL)) > 32) ? TRUE : FALSE; if (!success && (ERROR_NO_ASSOCIATION == GetLastError())) { success=((int)(ShellExecute(m_hWnd, _T("&Open with MSDEV"), commandLine, NULL, initDir.IsEmpty() ? (LPCTSTR)NULL : initDir, SW_SHOWNORMAL)) > 32) ? TRUE : FALSE; } if (!success && (ERROR_NO_ASSOCIATION == GetLastError())) { success=((int)(ShellExecute(m_hWnd, _T("open"), commandLine, NULL, initDir.IsEmpty() ? (LPCTSTR)NULL : initDir, SW_SHOWNORMAL)) > 32) ? TRUE : FALSE; } isRefresh = FALSE; // can't wait on a ShellExecuted program } else { if (initDir.IsEmpty()) initDir = TheApp()->m_ClientRoot; if (isOutput2Status) { SECURITY_ATTRIBUTES saAttr = {0}; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDOUT. if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) isOutput2Status = FALSE; else { // Create noninheritable read handle and close the inheritable read handle. BOOL fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS); if( !fSuccess ) { CloseHandle(hChildStdoutWr); isOutput2Status = FALSE; } else { startInfo.wShowWindow = SW_SHOWMINIMIZED; startInfo.hStdError = hChildStdoutWr; startInfo.hStdOutput = hChildStdoutWr; startInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; } CloseHandle(hChildStdoutRd); } } success=CreateProcess( NULL, // pointer to name of executable module const_cast((LPCTSTR)commandLine), // pointer to command line string NULL, NULL, // default security rot isOutput2Status ? TRUE : FALSE, // handle inheritance flag dwCreationFlags, // creation flags P4GetEnvironmentStrings(), // env initDir.IsEmpty() ? (LPCTSTR)NULL : LPCTSTR(initDir), // initial dir &startInfo, &procInfo); } CString oldtext; CString newtext; if (!success) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); txt.FormatMessage(IDS_TOOLS_ERROR_n_CANNOT_RUN_s_s, GetLastError(), commandLine, lpMsgBuf); if ( GET_P4REGPTR()->ShowCommandTrace( ) ) TheApp()->StatusAdd(txt, SV_ERROR); else AfxMessageBox(txt, MB_ICONSTOP); } else { if ( GET_P4REGPTR()->ShowCommandTrace( ) ) TheApp()->StatusAdd(commandLine, SV_TOOL); if (isOutput2Status) { BOOL b = FALSE; DWORD dwRead; CHAR chBuf[BUFSIZE]; CHAR *p = chBuf; CHAR xxBuf[BUFSIZE]; CHAR lchBuf[BUFSIZE]; TCHAR tchBuf[BUFSIZE]; CHAR *q; CHAR *qbgn; // Close the write end of the pipe before reading from the // read end of the pipe. CloseHandle(hChildStdoutWr); // Let the user know why we aren't responding newtext.FormatMessage(IDS_WAITING_FOR_s_TO_FINISH, commandLine); AfxGetMainWnd()->GetWindowText(oldtext); AfxGetMainWnd()->SetWindowText(newtext); // Read output from the child process, and write to Status pane for (xxBuf[0] = '\0';;) { if (!PumpMessages( )) break; if (!ReadFile(hChildStdoutRdDup, p, BUFSIZE-4-(p-chBuf), &dwRead, NULL) || dwRead == 0) { if (*chBuf) // any last bits to be written? { #ifdef UNICODE memset(tchBuf, 0, BUFSIZE); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)chBuf, strlen(chBuf), tchBuf, BUFSIZE); AddToStatus(tchBuf, SV_MSG); #else AddToStatus(chBuf, SV_MSG); #endif } break; } p[dwRead] = 0; Sleep(10); if (xxBuf[0]) { #ifdef UNICODE memset(tchBuf, 0, BUFSIZE); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)xxBuf, strlen(xxBuf), tchBuf, BUFSIZE); AddToStatus(tchBuf, SV_MSG); #else AddToStatus(xxBuf, SV_MSG); #endif xxBuf[0] = '\0'; } if (p[0] == '\r' && p[1] == '\n' && !chBuf[2]) { p += 2; continue; } p = chBuf; if (chBuf[strlen(chBuf)-1] == '>') { for (b=FALSE, q = chBuf + strlen(chBuf); --q >= chBuf; ) { if (*q == '\r' && *(q+1) == '\n' && *(q+3) == ':') { strcpy(xxBuf, q); *q = '\0'; if (q == chBuf) b = TRUE; break; } } } if (b) { b = FALSE; continue; } for (qbgn = chBuf, q = qbgn-1; *++q; ) { if (*q == '\r' || *q == '\n') { strncpy(lchBuf, qbgn, q-qbgn); lchBuf[q-qbgn] = '\0'; #ifdef UNICODE memset(tchBuf, 0, BUFSIZE); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lchBuf, strlen(lchBuf), tchBuf, BUFSIZE); AddToStatus(tchBuf, SV_MSG); #else AddToStatus(lchBuf, SV_MSG); #endif q++; while (*q) { if ((*q >= ' ') || (*q == '\t')) break; q++; } qbgn = q; if (!*q) break; } } if (*qbgn) { if ((qbgn == chBuf) && (strlen(chBuf) > BUFSIZE/2)) { // Did we fail to write any output yet the buffer is over half full? // if so, we better output what we've got and clear the buffer #ifdef UNICODE memset(tchBuf, 0, BUFSIZE); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)chBuf, strlen(chBuf), tchBuf, BUFSIZE); AddToStatus(tchBuf, SV_MSG); #else AddToStatus(chBuf, SV_MSG); #endif *(p = chBuf) = '\0'; } else { strcpy(chBuf, qbgn); p = chBuf + strlen(chBuf); } } else { *(p = chBuf) = '\0'; } } AfxGetMainWnd()->SetWindowText(oldtext); if (isRefresh) { m_pBranchView->GetListCtrl().Clear(); m_pClientView->GetListCtrl().Clear(); m_pUserView->GetListCtrl().Clear(); m_pLabelView->GetListCtrl().Clear(); m_pJobView->GetListCtrl().Clear(); m_pDepotView->GetTreeCtrl().OnViewUpdate( TRUE ); } } else if (isRefresh) { newtext.FormatMessage(IDS_WAITING_FOR_s_TO_FINISH, commandLine); // Let the user know why we aren't responding // AfxGetMainWnd()->GetWindowText(oldtext); AfxGetMainWnd()->SetWindowText(newtext); // Disable the main window // BOOL bReEnableMain = FALSE; if (AfxGetMainWnd()->IsWindowEnabled()) { ::EnableWindow( AfxGetMainWnd()->GetSafeHwnd(), FALSE ); bReEnableMain = TRUE; } // Wait for the spawned app // WaitForSingleObject( procInfo.hProcess, INFINITE ); // Re-enable the main window // if (bReEnableMain) { ::EnableWindow( AfxGetMainWnd()->GetSafeHwnd(), TRUE ); ::SetForegroundWindow( AfxGetMainWnd()->GetSafeHwnd() ); ::SetFocus( AfxGetMainWnd()->GetSafeHwnd() ); } AfxGetMainWnd()->SetWindowText(oldtext); m_pBranchView->GetListCtrl().Clear(); m_pClientView->GetListCtrl().Clear(); m_pUserView->GetListCtrl().Clear(); m_pLabelView->GetListCtrl().Clear(); m_pJobView->GetListCtrl().Clear(); m_pDepotView->GetTreeCtrl().OnViewUpdate( TRUE ); } } } int CMainFrame::FindDollarArg(CString commandLine, int offset) { int n = commandLine.GetLength(); while ((offset = commandLine.Find(_T('$'), offset)) != -1) // look for "%$ " where x is alpha { if (offset+2 > n) { offset = -1; break; } if (((offset+2 == n) || ((TBYTE)commandLine.GetAt(offset+2) <= _T(' ')) || ((TBYTE)commandLine.GetAt(offset+2) == _T('/')) || ((TBYTE)commandLine.GetAt(offset+2) == _T('\\'))) && (_istalpha(commandLine.GetAt(offset+1)))) break; else offset+=2; } return offset; } CString CMainFrame::ReplaceDollarArg(CString commandLine, int i, LPCTSTR str) { CString result = i ? commandLine.Left(i) : ""; result += str; result += commandLine.Right(commandLine.GetLength() - i - 2); return result; } int CMainFrame::FindPercentArg(CString commandLine, int offset) { int n = commandLine.GetLength(); while ((offset = commandLine.Find(_T('%'), offset)) != -1) // look for "%x " where x is alpha { if (offset+2 > n) { offset = -1; break; } if (((offset+2 == n) || (!_istalpha(commandLine.GetAt(offset+2)) && !_istdigit(commandLine.GetAt(offset+2)))) && (_istalpha(commandLine.GetAt(offset+1)))) break; else offset+=2; } return offset; } int CMainFrame::GetOpenedFiles( CStringList *list ) { CCmd_Opened *pCmd= new CCmd_Opened; int rc = 0; int key=0; // Set up and run Opened synchronously pCmd->Init(NULL, RUN_SYNC); if( pCmd->Run(FALSE, FALSE, -1, list) && !pCmd->GetError() && !SERVER_BUSY() && GET_SERVER_LOCK(key)) { CObList *coblist= pCmd->GetList(); ASSERT_KINDOF(CObList, coblist); list->RemoveAll(); POSITION pos= coblist->GetHeadPosition(); while(pos != NULL) { if ( !m_pDeltaView->GetTreeCtrl().PumpMessages( ) ) { list->RemoveAll(); break; } CP4FileStats *fs= (CP4FileStats *) coblist->GetNext(pos); CCmd_Fstat *pCmd2= new CCmd_Fstat; pCmd2->Init(NULL, RUN_SYNC, HOLD_LOCK, key); pCmd2->SetIncludeAddedFiles( TRUE ); if( pCmd2->Run( FALSE, fs->GetFullDepotPath(), 0 ) && !pCmd2->GetError() ) { CObList *coblist2 = pCmd2->GetFileList( ); ASSERT_KINDOF( CObList, coblist2 ); ASSERT( coblist2->GetCount() <= 1 ); POSITION pos = coblist2->GetHeadPosition( ); if( pos != NULL ) { CP4FileStats *stats = ( CP4FileStats * )coblist2->GetNext( pos ); ASSERT_KINDOF( CP4FileStats, stats ); CString clientPath = stats->GetFullClientPath( ); if( !clientPath.IsEmpty() ) list->AddHead( clientPath); delete stats; } } delete pCmd2; delete fs; } RELEASE_SERVER_LOCK(key); rc = list->GetCount(); } delete pCmd; return rc; } int CMainFrame::InsertSelectedObjectIntoCmdline(CString &cmdLine, int offset) { CP4PaneView * pView = DYNAMIC_DOWNCAST(CP4PaneView, GetActiveView()); CString cmdli = cmdLine; CString cmdliBefore = cmdli.Left(offset); CString cmdliAfter = _T(""); int i = cmdli.Find(_T(' '), offset); if (i != -1) cmdliAfter = cmdli.Right(cmdli.GetLength() - i - 1); CString txt = pView->GetSelectedItemText(); if (txt.IsEmpty()) return 0; cmdLine = cmdliBefore + txt + _T(" ") + cmdliAfter; return 1; } int CMainFrame::InsertAllSelectedFilesIntoCmdline(CString &cmdLine, int offset, BOOL bUseOpened, BOOL bDepotSyntax) { CView * pView = GetActiveView(); if ((pView != (CView *) m_pDepotView) && (pView != (CView *) m_pDeltaView)) return(NULL); CString cmdli = cmdLine; CString cmdliBefore = cmdli.Left(offset); CString cmdliAfter; int i = cmdli.Find(_T(' '), offset); if (i != -1) cmdliAfter = cmdli.Right(cmdli.GetLength() - i - 1); CStringList list; POSITION pos; BOOL rc; if (bUseOpened) { if (pView == (CView *) m_pDepotView) { m_pDepotView->GetTreeCtrl().AssembleStringList(&list); rc = list.GetCount(); } else { list.RemoveAll(); rc = 1; } if (rc > 0) rc = GetOpenedFiles(&list); if (!rc) return(rc); } else if (pView == (CView *) m_pDepotView) { if (bDepotSyntax) { m_pDepotView->GetTreeCtrl().AssembleStringList(&list); rc = list.GetCount(); } else rc = m_pDepotView->GetTreeCtrl().GetSelectedFiles(&list); } else { if (bDepotSyntax) { m_pDeltaView->GetTreeCtrl().AssembleStringList(&list); if (list.IsEmpty()) return(-1); while (list.GetTail().IsEmpty()) // remove any jobs that snuck in list.RemoveTail(); rc = list.GetCount(); } else rc = m_pDeltaView->GetTreeCtrl().GetSelectedFiles(&list); } if (!rc) return(-1); if (list.IsEmpty()) return 0; cmdli.Empty(); for(pos=list.GetHeadPosition(); pos != NULL; ) { cmdli += _T("\"") + list.GetNext(pos) + _T("\" "); } cmdLine = cmdliBefore + cmdli + cmdliAfter; return list.GetCount(); } void CMainFrame::ExecOnceForEachFile(int offset, CString &cmdLine, TCHAR sw, LPCTSTR lpInitDirectory, DWORD dwCreationFlags, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation, BOOL bNoCommand, BOOL bRefresh, BOOL isOutput2Status) { CView * pView = GetActiveView(); if ((pView != (CView *) m_pDepotView) && (pView != (CView *) m_pDeltaView)) return; CString cmdli = cmdLine; CString cmdliBefore = cmdli.Left(offset); CString cmdliAfter; int i = cmdli.Find(_T(' '), offset); if (i != -1) cmdliAfter = cmdli.Right(cmdli.GetLength() - i - 1); CStringList list; CString txt; POSITION pos; BOOL rc; if (sw == _T('o')) { if (pView == (CView *) m_pDepotView) { m_pDepotView->GetTreeCtrl().AssembleStringList(&list); rc = list.GetCount(); } else { list.RemoveAll(); rc = 1; } if (rc > 0) rc = GetOpenedFiles(&list); } else if (pView == (CView *) m_pDepotView) { if (sw == _T('d')) // depot syntax { m_pDepotView->GetTreeCtrl().AssembleStringList(&list); rc = list.GetCount(); } else rc = m_pDepotView->GetTreeCtrl().GetSelectedFiles(&list); } else { if (sw == _T('d')) // depot syntax { m_pDeltaView->GetTreeCtrl().AssembleStringList(&list); while (list.GetTail().IsEmpty()) // remove any jobs that snuck in list.RemoveTail(); rc = list.GetCount(); } else if (sw == _T('j')) // jobs { list.RemoveAll(); for( int i = m_pDeltaView->GetTreeCtrl().GetSelectedCount()-1; i >= 0; i--) { txt = m_pDeltaView->GetTreeCtrl().GetItemText( m_pDeltaView->GetSelectedItem( i ) ); if( txt.ReverseFind( _T('#') ) == -1) // don't add any files that snuck in list.AddHead( txt ); } rc = list.GetCount(); } else if ((sw == 'p') || (sw == 'c')) // pending change { CString defaultStr; CString changeStr; defaultStr.LoadString(IDS_DEFAULTCHANGELISTNAME); changeStr.LoadString(IDS_CHANGE); list.RemoveAll(); txt = m_pDeltaView->GetItemText( m_pDeltaView->GetSelectedItem( 0 ) ); if (txt.Find(defaultStr) == 0) { txt =_T("default"); } else if (txt.Find(changeStr) == 0) { txt = txt.Right(txt.GetLength() - changeStr.GetLength()); txt.TrimLeft(); if ((i = txt.Find(_T(' '))) != -1) txt = txt.Left(i); } list.AddHead( txt ); rc = list.GetCount(); } else rc = m_pDeltaView->GetTreeCtrl().GetSelectedFiles(&list); } if (!rc) { txt.FormatMessage(IDS_TOOLS_NO_FILES_SELECTED_CANNOT_RUN_s, cmdLine); AfxMessageBox(txt, MB_ICONSTOP); return; } if (list.IsEmpty()) { txt.FormatMessage(IDS_TOOLS_UNABLE_TO_DETERMINE_PATH_CANNONT_RUN_s, cmdLine); AfxMessageBox(txt, MB_ICONSTOP); return; } HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup; hChildStdoutWr = hChildStdoutRdDup = 0; BOOL bNeed2Refresh = FALSE; for(pos=list.GetHeadPosition(); pos != NULL; ) { CString listItem = list.GetNext(pos); CString initDir; if (lpInitDirectory && *lpInitDirectory == _T('%')) { initDir = listItem; if ((i = initDir.ReverseFind(_T('\\'))) != -1) initDir = initDir.Left(i); } else initDir = lpInitDirectory; if (bNoCommand) { cmdli = listItem; cmdli.TrimLeft(_T(" \"")); cmdli.TrimRight(_T(" \"")); rc=((int)(ShellExecute(m_hWnd, _T("Open.VisualStudio.7.1"), cmdli, NULL, initDir, SW_SHOWNORMAL)) > 32) ? TRUE : FALSE; if (!rc && (ERROR_NO_ASSOCIATION == GetLastError())) { rc=((int)(ShellExecute(m_hWnd, _T("&Open with MSDEV"), cmdli, NULL, initDir, SW_SHOWNORMAL)) > 32) ? TRUE : FALSE; } if (!rc && (ERROR_NO_ASSOCIATION == GetLastError())) { rc=((int)(ShellExecute(m_hWnd, _T("open"), cmdli, NULL, initDir, SW_SHOWNORMAL)) > 32) ? TRUE : FALSE; } } else { if ((sw == _T('j')) || (sw == _T('p')) || (sw == _T('c'))) cmdli = cmdliBefore + listItem + _T(" ") + cmdliAfter; else cmdli = cmdliBefore + _T("\"") + listItem + _T("\" ") + cmdliAfter; if (initDir.IsEmpty()) initDir = TheApp()->m_ClientRoot; if (isOutput2Status) { SECURITY_ATTRIBUTES saAttr = {0}; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDOUT. if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) isOutput2Status = FALSE; else { // Create noninheritable read handle and close the inheritable read handle. BOOL fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS); if( !fSuccess ) { CloseHandle(hChildStdoutWr); isOutput2Status = FALSE; } else { lpStartupInfo->wShowWindow = SW_SHOWMINIMIZED; lpStartupInfo->hStdError = hChildStdoutWr; lpStartupInfo->hStdOutput = hChildStdoutWr; lpStartupInfo->dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; } CloseHandle(hChildStdoutRd); } } rc=CreateProcess( NULL, // pointer to name of executable module const_cast((LPCTSTR)cmdli), // pointer to command line string NULL, NULL, // default security rot isOutput2Status ? TRUE : FALSE, // handle inheritance flag dwCreationFlags, // creation flags P4GetEnvironmentStrings(), // env initDir.IsEmpty() ? (LPCTSTR)NULL : LPCTSTR(initDir), // initial dir lpStartupInfo, lpProcessInformation); } CString oldtext; CString newtext; if (!rc) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); txt.FormatMessage(IDS_TOOLS_ERROR_n_CANNOT_RUN_s_s, GetLastError(), cmdli, lpMsgBuf); if ( GET_P4REGPTR()->ShowCommandTrace( ) ) TheApp()->StatusAdd(txt, SV_ERROR); else AfxMessageBox(txt, MB_ICONSTOP); break; } else { if ( GET_P4REGPTR()->ShowCommandTrace( ) ) TheApp()->StatusAdd(cmdli, SV_TOOL); if (isOutput2Status) { BOOL b = FALSE; DWORD dwRead; CHAR chBuf[BUFSIZE]; CHAR *p = chBuf; CHAR xxBuf[BUFSIZE]; // holds "/r/nC:/dir>" strings until next read; last one will not be written CHAR lchBuf[BUFSIZE]; TCHAR tchBuf[BUFSIZE]; CHAR *q; CHAR *qbgn; // Close the write end of the pipe before reading from the // read end of the pipe. CloseHandle(hChildStdoutWr); // Let the user know why we aren't responding newtext.FormatMessage(IDS_WAITING_FOR_s_TO_FINISH, cmdli); AfxGetMainWnd()->GetWindowText(oldtext); AfxGetMainWnd()->SetWindowText(newtext); // Read output from the child process, and write to Status pane for (xxBuf[0] = '\0';;) { if (!PumpMessages( )) break; if (!ReadFile(hChildStdoutRdDup, p, BUFSIZE-4-(p-chBuf), &dwRead, NULL) || dwRead == 0) { if (*chBuf) // any last bits to be written? { #ifdef UNICODE memset(tchBuf, 0, BUFSIZE); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)chBuf, strlen(chBuf), tchBuf, BUFSIZE); AddToStatus(tchBuf, SV_MSG); #else AddToStatus(chBuf, SV_MSG); #endif } break; } p[dwRead] = 0; Sleep(10); if (xxBuf[0]) { #ifdef UNICODE memset(tchBuf, 0, BUFSIZE); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)xxBuf, strlen(xxBuf), tchBuf, BUFSIZE); AddToStatus(tchBuf, SV_MSG); #else AddToStatus(xxBuf, SV_MSG); #endif xxBuf[0] = '\0'; } if (p[0] == '\r' && p[1] == '\n' && !chBuf[2]) { p += 2; continue; } p = chBuf; if (chBuf[strlen(chBuf)-1] == '>') { for (b=FALSE, q = chBuf + strlen(chBuf); --q >= chBuf; ) { if (*q == '\r' && *(q+1) == '\n' && *(q+3) == ':') { strcpy(xxBuf, q); *q = '\0'; if (q == chBuf) b = TRUE; break; } } } if (b) { b = FALSE; continue; } for (qbgn = chBuf, q = qbgn-1; *++q; ) { if (*q == '\r' || *q == '\n') { strncpy(lchBuf, qbgn, q-qbgn); lchBuf[q-qbgn] = '\0'; #ifdef UNICODE memset(tchBuf, 0, BUFSIZE); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lchBuf, strlen(lchBuf), tchBuf, BUFSIZE); AddToStatus(tchBuf, SV_MSG); #else AddToStatus(lchBuf, SV_MSG); #endif q++; while (*q) { if ((*q >= ' ') || (*q == '\t')) break; q++; } qbgn = q; if (!*q) break; } } if (*qbgn) { if ((qbgn == chBuf) && (strlen(chBuf) > BUFSIZE/2)) { // Did we fail to write any output yet the buffer is over half full? // if so, we better output what we've got and clear the buffer #ifdef UNICODE memset(tchBuf, 0, BUFSIZE); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)chBuf, strlen(chBuf), tchBuf, BUFSIZE); AddToStatus(tchBuf, SV_MSG); #else AddToStatus(chBuf, SV_MSG); #endif *(p = chBuf) = '\0'; } else { strcpy(chBuf, qbgn); p = chBuf + strlen(chBuf); } } else { *(p = chBuf) = '\0'; } } AfxGetMainWnd()->SetWindowText(oldtext); if (bRefresh) bNeed2Refresh = TRUE; } else if (bRefresh) { newtext.FormatMessage(IDS_WAITING_FOR_s_TO_FINISH, cmdli); // Let the user know what we aren't responding // AfxGetMainWnd()->GetWindowText(oldtext); AfxGetMainWnd()->SetWindowText(newtext); // Disable the main window // BOOL bReEnableMain = FALSE; if (AfxGetMainWnd()->IsWindowEnabled()) { ::EnableWindow( AfxGetMainWnd()->GetSafeHwnd(), FALSE ); bReEnableMain = TRUE; } // Wait for the spawned app // WaitForSingleObject( lpProcessInformation->hProcess, INFINITE ); // Re-enable the main window // if (bReEnableMain) { ::EnableWindow( AfxGetMainWnd()->GetSafeHwnd(), TRUE ); ::SetForegroundWindow( AfxGetMainWnd()->GetSafeHwnd() ); ::SetFocus( AfxGetMainWnd()->GetSafeHwnd() ); } AfxGetMainWnd()->SetWindowText(oldtext); bNeed2Refresh = TRUE; } } } if (bNeed2Refresh) { m_pBranchView->GetListCtrl().Clear(); m_pClientView->GetListCtrl().Clear(); m_pUserView->GetListCtrl().Clear(); m_pLabelView->GetListCtrl().Clear(); m_pJobView->GetListCtrl().Clear(); m_pDepotView->GetTreeCtrl().OnViewUpdate( TRUE ); } } void CMainFrame::OnUpdateTool(CCmdUI* pCmdUI) { int index = pCmdUI->m_nID - ID_TOOL_1; if (GET_P4REGPTR()->GetToolIsRefresh(index) && SERVER_BUSY()) { pCmdUI->Enable(FALSE); return; } int i, n; int max = 0x7FFFFFFF; BOOL bNoCmd; BOOL root; CString command = GET_P4REGPTR()->GetToolCommand(index); CString args = command + _T(' ') + GET_P4REGPTR()->GetToolArgs(index); CString initDir = GET_P4REGPTR()->GetToolInitDir(index); if (initDir == _T("%f")) { BOOL canDo; CView * pView = GetActiveView(); if (pView == (CView *) m_pDepotView) { canDo = (m_pDepotView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDepotView->GetTreeCtrl().GetSelectedCount() <= max && !(m_pDepotView->GetTreeCtrl().AnyHaveChildren()) && m_pDepotView->GetTreeCtrl().AnyInView()); } else if (pView == (CView *) m_pDeltaView) { canDo = (m_pDeltaView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDeltaView->GetTreeCtrl().GetSelectedCount() <= max && m_pDeltaView->GetTreeCtrl().GetItemLevel(m_pDeltaView->GetSelectedItem(0), &root)== 2 && m_pDeltaView->GetTreeCtrl().IsAFile(m_pDeltaView->GetSelectedItem(0))); } else canDo = FALSE; if (!canDo) { pCmdUI->Enable(FALSE); return; } } bNoCmd = command.IsEmpty() ? TRUE : FALSE; i = 0; n = args.GetLength(); while ((i = args.Find(_T('%'), i)) != -1) // look for "%x " where x is alpha { if (i+2 > n) { i = -1; break; } if (((i+2 == n) || (!_istalpha(args.GetAt(i+2)) && !_istdigit(args.GetAt(i+2)))) && (_istalpha(args.GetAt(i+1)))) break; else i+=2; } if (i != -1) { switch (args.GetAt(i+1)) { case _T('L'): if (bNoCmd) max = 1; case _T('l'): pCmdUI->Enable((GetActiveView() == (CView *) m_pDepotView) && m_pDepotView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDepotView->GetTreeCtrl().GetSelectedCount() <= max && !(m_pDepotView->GetTreeCtrl().AnyHaveChildren()) && m_pDepotView->GetTreeCtrl().AnyInView()); break; case _T('R'): if (bNoCmd) max = 1; case _T('r'): pCmdUI->Enable((GetActiveView() == (CView *) m_pDeltaView) && m_pDeltaView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDeltaView->GetTreeCtrl().GetSelectedCount() <= max && m_pDeltaView->GetTreeCtrl().GetItemLevel(m_pDeltaView->GetSelectedItem(0), &root)== 2 && m_pDeltaView->GetTreeCtrl().IsAFile(m_pDeltaView->GetSelectedItem(0))); break; case _T('F'): if (bNoCmd) max = 1; case _T('f'): { CView * pView = GetActiveView(); if (pView == (CView *) m_pDepotView) { pCmdUI->Enable((GetActiveView() == (CView *) m_pDepotView) && m_pDepotView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDepotView->GetTreeCtrl().GetSelectedCount() <= max && !(m_pDepotView->GetTreeCtrl().AnyHaveChildren()) && m_pDepotView->GetTreeCtrl().AnyInView()); } else if (pView == (CView *) m_pDeltaView) { pCmdUI->Enable((GetActiveView() == (CView *) m_pDeltaView) && m_pDeltaView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDeltaView->GetTreeCtrl().GetSelectedCount() <= max && m_pDeltaView->GetTreeCtrl().GetItemLevel(m_pDeltaView->GetSelectedItem(0), &root)== 2 && m_pDeltaView->GetTreeCtrl().IsAFile(m_pDeltaView->GetSelectedItem(0))); } else pCmdUI->Enable(FALSE); break; } case _T('D'): case _T('d'): { if (bNoCmd) max = 0; CView * pView = GetActiveView(); if (pView == (CView *) m_pDepotView) { pCmdUI->Enable((GetActiveView() == (CView *) m_pDepotView) && m_pDepotView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDepotView->GetTreeCtrl().GetSelectedCount() <= max); } else if (pView == (CView *) m_pDeltaView) { pCmdUI->Enable((GetActiveView() == (CView *) m_pDeltaView) && m_pDeltaView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDeltaView->GetTreeCtrl().GetSelectedCount() <= max && m_pDeltaView->GetTreeCtrl().GetItemLevel(m_pDeltaView->GetSelectedItem(0), &root)== 2 && m_pDeltaView->GetTreeCtrl().IsAFile(m_pDeltaView->GetSelectedItem(0))); } else pCmdUI->Enable(FALSE); break; } case _T('O'): case _T('o'): { pCmdUI->Enable(!SERVER_BUSY() && (m_pDeltaView->GetTreeCtrl().AnyInDefault() || m_pDeltaView->GetTreeCtrl().AnyNbredChg())); break; } case _T('C'): // changelist (either pending or submitted) case _T('c'): if (GetActiveView() == (CView *) m_pOldChgView) goto subchg; case _T('P'): case _T('p'): // pending change pCmdUI->Enable((GetActiveView() == (CView *) m_pDeltaView) && m_pDeltaView->GetTreeCtrl().GetSelectedCount() == 1 && m_pDeltaView->GetTreeCtrl().GetItemLevel(m_pDeltaView->GetSelectedItem(0), &root)== 1); break; case _T('S'): case _T('s'): // submitted change subchg: pCmdUI->Enable(GetActiveView() == (CView *) m_pOldChgView && m_pOldChgView->GetListCtrl().GetSelectedItem() != -1); break; case _T('A'): case _T('a'): // label pCmdUI->Enable(GetActiveView() == (CView *) m_pLabelView && m_pLabelView->GetListCtrl().GetSelectedItem() != -1); break; case _T('B'): case _T('b'): // branch pCmdUI->Enable(GetActiveView() == (CView *) m_pBranchView && m_pBranchView->GetListCtrl().GetSelectedItem() != -1); break; case _T('I'): case _T('i'): // client pCmdUI->Enable(GetActiveView() == (CView *) m_pClientView && m_pClientView->GetListCtrl().GetSelectedItem() != -1); break; case _T('U'): case _T('u'): // user pCmdUI->Enable(GetActiveView() == (CView *) m_pUserView && m_pUserView->GetListCtrl().GetSelectedItem() != -1); break; case _T('J'): case _T('j'): // job if (GetActiveView() == (CView *) m_pJobView) pCmdUI->Enable(m_pJobView->GetSelectedItem() != -1); else if ((GetActiveView() == (CView *) m_pDeltaView)) { pCmdUI->Enable(m_pDeltaView->GetTreeCtrl().GetSelectedCount() > 0 && m_pDeltaView->GetTreeCtrl().GetItemLevel(m_pDeltaView->GetSelectedItem(0), &root)== 2 && !(m_pDeltaView->GetTreeCtrl().IsAFile(m_pDeltaView->GetSelectedItem(0)))); } else pCmdUI->Enable(FALSE); break; } } } void CMainFrame::AddToolsToContextMenu(CP4Menu *pPopMenu) { CMenu *pSubMenu; BOOL bSM[MAX_TOOLS+1]; CString str[MAX_TOOLS+1]; int i; int s; // Get the strings for(i = -1; ++i < MAX_TOOLS; ) { str[i] = GET_P4REGPTR()->GetToolMenuName(i); bSM[i] = GET_P4REGPTR()->GetToolIsSubMenu(i); } if (str[0].GetLength()) { BOOL bGotSep = FALSE; // Load all Tool menu items into Tools menu for(s=i=-1; ++i < MAX_TOOLS && str[i].GetLength() > 0; ) { if (GET_P4REGPTR()->GetToolOnContext(i)) { if (!bSM[i]) { // Add the menu item if (!bGotSep) pPopMenu->AppendMenu(MF_SEPARATOR); pPopMenu->AppendMenu(MF_STRING, ID_TOOL_1+i, str[i]); // now call the enable/disable routine CCmdUI cmdUI; cmdUI.m_pMenu = pPopMenu; cmdUI.m_nIndex = pPopMenu->GetMenuItemCount( )-1; cmdUI.m_nIndexMax = cmdUI.m_nIndex + 1; cmdUI.m_nID = ID_TOOL_1+i; OnUpdateTool(&cmdUI); // if the item got disabled, remove it. if (MF_DISABLED & pPopMenu->GetMenuState(ID_TOOL_1+i, MF_BYCOMMAND)) { pPopMenu->DeleteMenu(ID_TOOL_1+i, MF_BYCOMMAND); if (!bGotSep) pPopMenu->DeleteMenu(pPopMenu->GetMenuItemCount( )-1, MF_BYPOSITION); } else bGotSep = TRUE; } else // it is a submenu { CString name = str[i]; m_ContextToolsSubMenu[++s].m_hMenu = NULL; pSubMenu = &m_ContextToolsSubMenu[s]; pSubMenu->CreatePopupMenu(); BOOL b = FALSE; while (++i < MAX_TOOLS && !bSM[i]) { if (GET_P4REGPTR()->GetToolOnContext(i)) { pSubMenu->AppendMenu(MF_STRING, ID_TOOL_1+i, str[i]); // now call the enable/disable routine CCmdUI cmdUI; cmdUI.m_pMenu = pSubMenu; cmdUI.m_nIndex = pSubMenu->GetMenuItemCount( )-1; cmdUI.m_nIndexMax = cmdUI.m_nIndex + 1; cmdUI.m_nID = ID_TOOL_1+i; OnUpdateTool(&cmdUI); // if the item got disabled, remove it. if (MF_DISABLED & pSubMenu->GetMenuState(ID_TOOL_1+i, MF_BYCOMMAND)) pSubMenu->DeleteMenu(ID_TOOL_1+i, MF_BYCOMMAND); else b = TRUE; } } if (b) { if (!bGotSep) { pPopMenu->AppendMenu(MF_SEPARATOR); bGotSep = TRUE; } pPopMenu->AppendMenu(MF_POPUP, (UINT) pSubMenu->GetSafeHmenu(), name); } else pSubMenu->DestroyMenu( ); if (i < MAX_TOOLS && bSM[i]) i--; } } } } } LRESULT CMainFrame::OnP4ListOp(WPARAM wParam, LPARAM lParam) { int key; CCmd_ListOpStat *pCmd= (CCmd_ListOpStat *) wParam; if(!pCmd->GetError()) { switch(pCmd->GetCommand()) { case P4DELETE: if (m_StringList2.GetCount()) { key= pCmd->GetServerKey(); CCmd_ListOpStat *pCmd2= new CCmd_ListOpStat; pCmd2->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK, key ); if( pCmd2->Run( &m_StringList2, P4EDIT, m_SelectedChange ) ) UpdateStatus( LoadStringResource(IDS_REQUEST_OPEN_EDIT) ); else { if( key != 0 ) RELEASE_SERVER_LOCK(key); delete pCmd2; } break; } case P4EDIT: key= pCmd->GetServerKey(); UpdateDepotandChangeViews(REDRILL, key); break; default: ASSERT(0); } } pCmd->DeleteStatList(); delete pCmd; return 0; } BOOL CMainFrame::PrintString(CString &string, CString caption) { RECT rPrint; BOOL rc = FALSE; CPrintDialog dlg(FALSE); // get the info from Page Setup dlg.m_pd.hDevNames = m_hDevNames; dlg.m_pd.hDevMode = m_hDevMode; if (dlg.DoModal() == IDOK) { // Get a handle to the printer device context (DC). CDC dcPrinter; DOCINFO docinfo; HDC hdc = dlg.GetPrinterDC(); if (hdc) { ASSERT(hdc); // create a CDC and attach it to the default printer dcPrinter.Attach(hdc); // call StartDoc() to begin printing memset(&docinfo, 0, sizeof(docinfo)); docinfo.cbSize = sizeof(docinfo); docinfo.lpszDocName = caption; } // if it fails, complain and exit gracefully if (!hdc || (dcPrinter.StartDoc(&docinfo) < 0)) { AfxMessageBox(IDS_PRINTER_WOULDNT_INIT, MB_ICONSTOP); } else { // start a page if (dcPrinter.StartPage() < 0) { AfxMessageBox(IDS_PRINTER_COULDNT_START_PAGE, MB_ICONSTOP); dcPrinter.AbortDoc(); } else { // map mode of printer DC int mapMode = 0; // Create a printer font CFont cFont; CString face= GET_P4REGPTR()->GetFontFace(); int size= GET_P4REGPTR()->GetFontSize(); int weight= GET_P4REGPTR()->GetFontWeight(); BOOL isItalic= GET_P4REGPTR()->GetFontItalic(); LOGFONT logFont; memset( &logFont, 0, sizeof(LOGFONT) ); logFont.lfPitchAndFamily= FIXED_PITCH | FF_DONTCARE; lstrcpy(logFont.lfFaceName, face.GetBuffer(face.GetLength())); logFont.lfHeight= -abs(size); logFont.lfWeight = weight; //Regular logFont.lfItalic = (BYTE) isItalic; logFont.lfCharSet = DEFAULT_CHARSET; cFont.CreateFontIndirect( &logFont ); CGdiObject* pOldFont = dcPrinter.SelectObject(&cFont); // calculate the width and height of the printable area of the paper CSize wSize; // Printer 'window' sizes CSize vSize; // Printer viewport sizes dcPrinter.SetMapMode(MM_LOENGLISH); wSize = dcPrinter.GetWindowExt(); vSize = dcPrinter.GetViewportExt(); vSize.cy = 0 - vSize.cy; if (m_osVer.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { wSize.cx *= 8; wSize.cy *= 8; vSize.cx *= 8; vSize.cy *= 8; } dcPrinter.SetMapMode(mapMode = MM_ISOTROPIC); dcPrinter.SetWindowExt(wSize.cx, wSize.cy); dcPrinter.SetViewportExt(vSize.cx, vSize.cy); // subtract off margins from the paper size gotten from the WindowExt if (m_bMetric) // if Metric, gotta convert to inches 1/100 of inches { rPrint.top = (long)((m_rtMargin.top - m_rtMinMargin.top)/25.4); rPrint.left = (long)((m_rtMargin.left - m_rtMinMargin.bottom)/25.4); rPrint.right = (long)(wSize.cx - (m_rtMargin.right - m_rtMinMargin.right)/25.4); rPrint.bottom = (long)(wSize.cy - (m_rtMargin.bottom - m_rtMinMargin.right)/25.4); } else // gotta convert from 1/1000" to MM_LOENGLISH's 1/100" { rPrint.top = (m_rtMargin.top - m_rtMinMargin.top)/10; rPrint.left = (m_rtMargin.left - m_rtMinMargin.bottom)/10; rPrint.right = wSize.cx - (m_rtMargin.right - m_rtMinMargin.right)/10; rPrint.bottom = wSize.cy - (m_rtMargin.bottom - m_rtMinMargin.right)/10; } // loop to print individual pages, if necessary because of length of 'string' // first time, try to fit entire 'string' om a single page CString outBuf = string; // build current print page here CString overflow; // holds what is left to be printed do { RECT rect; // workarea printable RECT overflow.Empty(); outBuf.TrimRight(_T("\r\n")); rect.top = rPrint.top; rect.left = rPrint.left; rect.right = rPrint.right; rect.bottom = rPrint.bottom; dcPrinter.DrawText(outBuf, &rect, DT_CALCRECT | DT_EXPANDTABS | DT_NOPREFIX | DT_WORDBREAK); if (rect.bottom > rPrint.bottom) { // won't all fit on one page CString last; // last paragraph extracted from overflow CString test; // == outBuf + last rect.bottom = 0; overflow = outBuf; // move all that's left to overflow outBuf.Empty(); // and start building paragraph by paragraph // break into individual pages at CR-LF (paragraph) while (1) { int i; if ((i = overflow.Find(_T('\n'))) == -1) // if last paragraph { last = overflow; overflow.Empty(); } else // extract next paragraph { last = overflow.Left(i+1); overflow = overflow.Right(overflow.GetLength() - i - 1); last.TrimRight(_T("\r\n")); } test = outBuf + _T("\r\n") + last; rect.top = rPrint.top; rect.left = rPrint.left; rect.right = rPrint.right; rect.bottom = rPrint.bottom; dcPrinter.DrawText(test, &rect, DT_CALCRECT | DT_EXPANDTABS | DT_NOPREFIX | DT_WORDBREAK); if (rect.bottom > rPrint.bottom) { // last paragraph was too much if (outBuf.IsEmpty()) outBuf = last; // at least print first part of too big initial paragraph else // put last paragraph back for next loop overflow = last + _T("\r\n") + overflow; break; } outBuf += _T("\r\n") + last; // it'll fit; add last paragraph to output buffer } outBuf.TrimLeft(_T("\r\n")); } rect.top = rPrint.top; rect.left = rPrint.left; rect.right = rPrint.right; rect.bottom = rPrint.bottom; dcPrinter.DrawText(outBuf, &rect, DT_EXPANDTABS | DT_NOPREFIX | DT_WORDBREAK); outBuf = overflow; // move any leftovers to do in next loop if (!outBuf.IsEmpty()) // anything more to print? { dcPrinter.EndPage(); // end this page if (dcPrinter.StartPage() < 0) // and start a new one { AfxMessageBox(IDS_PRINTER_COULDNT_START_PAGE, MB_ICONSTOP); dcPrinter.AbortDoc(); break; } if (dcPrinter.GetMapMode() != mapMode) { dcPrinter.SetMapMode(MM_ISOTROPIC); dcPrinter.SetWindowExt(wSize.cx, wSize.cy); dcPrinter.SetViewportExt(vSize.cx, vSize.cy); } } } while (!outBuf.IsEmpty()); dcPrinter.EndPage(); dcPrinter.EndDoc(); dcPrinter.SelectObject(pOldFont); rc = TRUE; } } // Clean up. if (hdc) CDC::FromHandle(hdc)->DeleteDC(); } return rc; } void CMainFrame::OnPageSetup() { PageSetup(); } void CMainFrame::PageSetup() { int rc; CPageSetupDialog dlg; // use any previous page info if (m_hDevNames) dlg.m_psd.hDevNames = m_hDevNames; if (m_hDevMode) { dlg.m_psd.hDevMode = m_hDevMode; dlg.m_psd.rtMargin.top = m_rtMargin.top; dlg.m_psd.rtMargin.left = m_rtMargin.left; dlg.m_psd.rtMargin.right = m_rtMargin.right; dlg.m_psd.rtMargin.bottom = m_rtMargin.bottom; } if ((rc = dlg.DoModal()) == IDOK) // get the user's preferences { // save the good stuff AfxGetApp()->SelectPrinter(dlg.m_psd.hDevNames, dlg.m_psd.hDevMode, TRUE); m_hDevNames = dlg.m_psd.hDevNames; m_hDevMode = dlg.m_psd.hDevMode; m_rtMargin.top = dlg.m_psd.rtMargin.top; m_rtMargin.left = dlg.m_psd.rtMargin.left; m_rtMargin.right = dlg.m_psd.rtMargin.right; m_rtMargin.bottom = dlg.m_psd.rtMargin.bottom; m_rtMinMargin.top = dlg.m_psd.rtMinMargin.top; m_rtMinMargin.left = dlg.m_psd.rtMinMargin.left; m_rtMinMargin.right = dlg.m_psd.rtMinMargin.right; m_rtMinMargin.bottom = dlg.m_psd.rtMinMargin.bottom; m_bMetric = (dlg.m_psd.Flags & PSD_INTHOUSANDTHSOFINCHES) ? FALSE : TRUE; } else if (rc == IDCANCEL) { DWORD errcode = CommDlgExtendedError(); if (errcode) { CString txt; txt.FormatMessage(IDS_UNABLE_TO_SETUP_PRINTER_n, errcode); TheApp()->StatusAdd(txt, SV_ERROR); } } } void CMainFrame::OnUpdateMakeDefaultPcu(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnMakeDefaultPcu() { BOOL rc = !GET_P4REGPTR()->SetP4Port(GET_P4REGPTR()->GetP4Port(), TRUE, TRUE, TRUE); rc = rc || !GET_P4REGPTR()->SetP4Client(GET_P4REGPTR()->GetP4Client(), TRUE, TRUE, TRUE); rc = rc || !GET_P4REGPTR()->SetP4User(GET_P4REGPTR()->GetP4User(), TRUE, TRUE, TRUE); if (rc) AfxMessageBox(IDS_UNABLE_TO_WRITE_P4DEFAULT_TO_THE_REGISTRY, MB_ICONEXCLAMATION); } void CMainFrame::ResumeAutoPoll() { if (m_DoNotAutoPollCtr > 0) m_DoNotAutoPollCtr--; else if (m_DoNotAutoPollCtr < 0) m_DoNotAutoPollCtr = 0; if (!m_DoNotAutoPollCtr) WaitAWhileToPoll(); } void CMainFrame::WaitAWhileToPoll() { if(!GET_P4REGPTR()->GetAutoPoll()) return; long time=GetTickCount(); long period=GET_P4REGPTR()->GetAutoPollTime() * 60000; m_LastUpdateTime= max(m_LastUpdateTime, time + 20000 - period); } int CMainFrame::CreateNewChangeList(int key, CString *description/*=NULL*/, BOOL autoOK/*=FALSE*/) { return m_pDeltaView->GetTreeCtrl().CreateNewChangeList(key, description, autoOK); } void CMainFrame::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu) { static BOOL bNeed2Clear = FALSE; SetGotUserInput( ); if (bNeed2Clear && ((nItemID < ID_TOOL_1) || (nItemID > ID_TOOL_1 + MAX_TOOLS - 1))) { bNeed2Clear = FALSE; SetMessageText(_T("")); } CFrameWnd::OnMenuSelect(nItemID, nFlags, hSysMenu); if ((nItemID >= ID_TOOL_1) && (nItemID <= ID_TOOL_1 + MAX_TOOLS - 1)) { int index = nItemID - ID_TOOL_1; CString txt; CString command = GET_P4REGPTR()->GetToolCommand(index); CString args = GET_P4REGPTR()->GetToolArgs(index); BOOL isPrompt = GET_P4REGPTR()->GetToolIsPrompt(index); txt = command + (isPrompt ? LoadStringResource(IDS_TOOLS_PROMPT_FOR_ARGS) : _T(" ")) + args; SetMessageText(txt); bNeed2Clear = TRUE; } } void CMainFrame::OnUpdateViewChgsByUser(CCmdUI* pCmdUI) { CString txt = m_pUserView->GetListCtrl().GetSelectedItemText(); if (txt.IsEmpty()) txt = GET_P4REGPTR()->GetP4User(); pCmdUI->SetText(LoadStringResource(IDS_CHGS_BY_USER) + TruncateString(txt, 50)); pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnViewChgsByUser() { CString txt = m_pUserView->GetListCtrl().GetSelectedItemText(); if (txt.IsEmpty()) txt = GET_P4REGPTR()->GetP4User(); m_pOldChgView->GetListCtrl().FilterByUser(txt); if (m_currentTab != 6) OnViewSubmitted(); } void CMainFrame::OnUpdateViewChgsByClient(CCmdUI* pCmdUI) { CString txt = m_pClientView->GetListCtrl().GetSelectedItemText(); if (txt.IsEmpty()) txt = GET_P4REGPTR()->GetP4Client(); pCmdUI->SetText(LoadStringResource(IDS_CHGS_BY_CLIENT) + TruncateString(txt, 50)); pCmdUI->Enable(!SERVER_BUSY()); } void CMainFrame::OnViewChgsByClient() { CString txt = m_pClientView->GetListCtrl().GetSelectedItemText(); if (txt.IsEmpty()) txt = GET_P4REGPTR()->GetP4Client(); m_pOldChgView->GetListCtrl().FilterByClient(txt); if (m_currentTab != 6) OnViewSubmitted(); } BOOL CMainFrame::IsFileInList(CString *filename, CStringList *list) { int i; int lgth; CString listItem; CString s = ((i = filename->Find(_T('#'))) == -1) ? *filename : filename->Left(i); for(POSITION pos=list->GetHeadPosition(); pos != NULL; ) { listItem = list->GetNext(pos); if (listItem.Mid((lgth = listItem.GetLength()) - 4) == _T("/...")) { listItem = listItem.Left(lgth - 3); s = s.Left(lgth - 3); } if (s == listItem) return TRUE; } return FALSE; } void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) { CFrameWnd::OnActivate(nState, pWndOther, bMinimized); if (GET_P4REGPTR()->TryResetingFocus()) { if (m_DlgWndList.GetCount() && nState == WA_ACTIVE) PostMessage(WM_ACTIVATEMODELESS, WA_ACTIVE, (LPARAM)pWndOther); } } LRESULT CMainFrame::OnActivateModeless(WPARAM wParam, LPARAM lParam) { HWND hwnd = 0; CWnd* pWndOther = (CWnd*)lParam; CDialog *pDlg; POSITION pos1; for( pos1 = m_DlgWndList.GetTailPosition(); pos1 != NULL; ) { pDlg = (CDialog*) m_DlgWndList.GetPrev( pos1 ); if (!::IsWindow(pDlg->m_hWnd)) continue; if (::IsIconic(pDlg->m_hWnd)) continue; if (pDlg == pWndOther) continue; hwnd = pDlg->m_hWnd; } if (hwnd) ::SetFocus(hwnd); return 0; } void CMainFrame::OnActivateApp(BOOL bActive, DWORD dwThreadID) { CFrameWnd::OnActivateApp(bActive, dwThreadID); SetGotUserInput( ); WaitAWhileToPoll( ); m_IsActive = bActive; if (bActive) { if (m_hWndLastActive) ::SetFocus(m_hWndLastActive); } else { m_hWndLastActive = ::GetLastActivePopup(m_hWnd); if (m_hWndLastActive == m_hWnd) m_hWndLastActive = 0; } } void CMainFrame::OnParentNotify(UINT message, LPARAM lParam) { SetGotUserInput( ); CFrameWnd::OnParentNotify(message, lParam); } // This funtion gets the enviroment string from the OS // and then sets the 4 P4 environment variables to // match the current port/client/user/password LPVOID CMainFrame::P4GetEnvironmentStrings() { SetEnvironmentVariable(_T("P4PORT"), GET_P4REGPTR()->GetP4Port()); SetEnvironmentVariable(_T("P4CLIENT"), GET_P4REGPTR()->GetP4Client()); SetEnvironmentVariable(_T("P4USER"), GET_P4REGPTR()->GetP4User()); if (GET_SECURITYLEVEL() < 2) { CString p4passwd = GET_P4REGPTR()->GetP4UserPassword(); if (!p4passwd.IsEmpty()) SetEnvironmentVariable(_T("P4PASSWD"), p4passwd); } return GetEnvironmentStrings(); } // Called from Toolbar's OnDragEnter DROPEFFECT CMainFrame::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point ) { m_DragEnterTime = GetTickCount(); int m_DragEnterTabNbr = CvtPointToTabNbr(point.x, point.y); if (m_DragEnterTabNbr >= 0) { #ifdef _DEBUG CString txt; txt.Format(_T("CTBDropTarget::OnDragEnter - Button=%d\n"), m_DragEnterTabNbr); XTRACE(txt); #endif return m_CurDropEffect = SERVER_BUSY() ? DROPEFFECT_NONE : DROPEFFECT_COPY; } return m_CurDropEffect = DROPEFFECT_NONE; } // Called from Toolbar's OnDragLeave void CMainFrame::OnDragLeave(CWnd* pWnd) { m_DragEnterTime = 0; XTRACE(_T("CTBDropTarget::OnDragLeave\n")); } // Called from Toolbar's OnDragOver DROPEFFECT CMainFrame::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) { int i= CvtPointToTabNbr(point.x, point.y); if (i < 0) return m_CurDropEffect = DROPEFFECT_NONE; if (m_CurDropEffect == DROPEFFECT_COPY) { if ((m_DragEnterTabNbr == i) && (GetTickCount() > m_DragEnterTime + 750)) { if (i != m_currentTab) { m_bNoRefresh = TRUE; switch(i) { case 0: OnViewChanges(); break; case 1: OnViewLabels(); break; case 2: OnViewBranches(); break; case 3: OnViewUsers(); break; case 4: OnViewClients(); break; case 5: OnViewJobs(); break; case 6: OnViewSubmitted(); break; } m_bNoRefresh = FALSE; } else m_DragEnterTime = GetTickCount(); } else if (m_DragEnterTabNbr != i) { m_DragEnterTabNbr = i; m_DragEnterTime = GetTickCount(); } } else if ((m_CurDropEffect == DROPEFFECT_NONE) && !SERVER_BUSY()) { m_DragEnterTabNbr = i; m_DragEnterTime = GetTickCount(); m_CurDropEffect = DROPEFFECT_COPY; } return m_CurDropEffect; } // Called from Toolbar's OnDrop BOOL CMainFrame::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point ) { AddToStatus( LoadStringResource(IDS_DROPPING_ON_TOOLBAR_HAS_NO_EFFECT)); return FALSE; } // This routine coverts the HitTest return values // to corresponding values for m_currentTab int CMainFrame::CvtPointToTabNbr(int x, int y) { POINT pt; pt.x = x; pt.y = y; CToolBarCtrl& toolbarctrl= (CToolBarCtrl&) m_wndToolBar.GetToolBarCtrl( ); int i = toolbarctrl.HitTest(&pt); if (i >= 0) { switch(i - 20) { case 0: return 0; case 1: return 6; case 2: return 2; case 3: return 1; case 4: return 4; case 5: return 3; case 6: return 5; } } return -1; } CString CMainFrame::GetDragFromJob() { return m_pJobView->GetListCtrl().m_DragFromItemName; } CString CMainFrame::GetDragFromClient() { return m_pClientView->GetListCtrl().m_DragFromItemName; } CString CMainFrame::GetDragFromUser() { return m_pUserView->GetListCtrl().m_DragFromItemName; } LRESULT CMainFrame::OnNewClient( WPARAM wParam, LPARAM lParam ) { m_pClientView->GetListCtrl().OnNewClient(wParam, lParam); SignalAllModelessDlgs(WM_NEWCLIENT); return 0; } LRESULT CMainFrame::OnNewUser( WPARAM wParam, LPARAM lParam ) { m_pUserView->GetListCtrl().OnNewUser(wParam, lParam); SignalAllModelessDlgs(WM_NEWUSER); return 0; } LRESULT CMainFrame::OnUserPasswordDlg( WPARAM wParam, LPARAM lParam ) { return m_pUserView->GetListCtrl().OnUserPasswordDlg( wParam, lParam ); } void CMainFrame::GetClients(CStringArray *list) { return m_pClientView->GetListCtrl().GetListItems(list); } void CMainFrame::GetUsers(CStringArray *list) { return m_pUserView->GetListCtrl().GetListItems(list); } // This is only used with menu items that have icons // It is only called when no OnUpdate function // exists for the currently active pane // It disables the menu item and clears the icon void CMainFrame::OnUpdateMenuWithIcon(CCmdUI* pCmdUI) { pCmdUI->Enable(SetMenuIcon(pCmdUI, FALSE)); } void CMainFrame::OnUpdateViewUpdate(CCmdUI* pCmdUI) { pCmdUI->Enable(SetMenuIcon(pCmdUI, !SERVER_BUSY())); } void CMainFrame::OnViewUpdate() { // depot view handles refresh for itself // right hand views do their own refreshes on ID_VIEW_UPDATE_RIGHT CP4PaneView * active = DYNAMIC_DOWNCAST(CP4PaneView,GetActiveView()); if (active == m_pDepotView // Depot is active || (!active && !m_currentTab)) // Status is active, and right pane is pending changes m_pDepotView->GetTreeCtrl().OnViewUpdate(); else if (active) active->SendMessage(WM_COMMAND, ID_VIEW_UPDATE_RIGHT); } void CMainFrame::OnUpdateCancelCommand(CCmdUI* pCmdUI) { pCmdUI->Enable(SetMenuIcon(pCmdUI, SERVER_BUSY())); } void CMainFrame::OnCancelButton() { if (SERVER_BUSY() && IDYES == AfxMessageBox(IDS_CANCEL_AREYOUSURE, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2)) OnCancelCommand(); } void CMainFrame::OnCancelCommand() { if (SERVER_BUSY()) global_cancel = 1; } BOOL CMainFrame::SetMenuIcon(CCmdUI* pCmdUI, BOOL bEnable) { // Check that we are running win/2k or later // and we want to show icons in menus // and that we have a menu (rather than a toolbar button) // and that is has a valid handle // and that it is not a (top level) context menu if (m_osVer.dwMajorVersion >= 5 && m_IconsInMenus && pCmdUI->m_pMenu && IsMenu(pCmdUI->m_pMenu->m_hMenu) && pCmdUI->m_pParentMenu != pCmdUI->m_pMenu) { UINT id = pCmdUI->m_nID; if (bEnable || m_HasDisabled) { UINT look4id; switch(id) { case ID_FILTER_SETVIEW: case ID_LABELFILTER_SETVIEW: case ID_LABELFILTER_SETVIEWREV: case ID_FILTERBYOWNER: case ID_JOB_SETFILTER: case ID_FILTERCLIENTS: case ID_FILTERBRANCHBYOWNER: look4id = ID_VIEW_FILTEREDVIEW; break; case ID_FILTER_CLEARVIEW: case ID_LABELFILTER_CLEARVIEW: case ID_CLEAROWNERFILTER: case ID_JOB_REMOVEFILTER: case ID_CLEARCLIENTFILTER: case ID_CLEARBRANCHOWNERFILTER: look4id = ID_VIEW_CLEARFILTER; break; default: look4id = id; break; } for (int i=-1; ++i < m_MenuBmpCtr; ) { if (m_MenuIDbm[i] == look4id) { MENUITEMINFO mii; memset(&mii, _T('\0'), sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_BITMAP; mii.hbmpItem = bEnable ? HBITMAP(m_MenuBitmap[i]) : HBITMAP(m_MenuBitDis[i]); GetMenu()->SetMenuItemInfo(id, &mii); if (pCmdUI->m_pParentMenu == GetMenu()) for (int n = 3; ++n < 10; ) GetMenu()->GetSubMenu(n)->SetMenuItemInfo(id, &mii); break; } } } else { // Set the menu label to what it already is! // This has the side effect of erasing the bitmap CString str; if (pCmdUI->m_pMenu->GetMenuString(id, str, MF_BYCOMMAND)) pCmdUI->SetText(str); } } return bEnable; } void CMainFrame::SaveToolBarBitmap(int iconnbr, UINT id) { CImageList * disabledmenu = TheApp()->GetToolBarImageList()->GetDisabledMenu(); HICON hIcon = TheApp()->GetToolBarImageList()->ExtractIcon(iconnbr); HICON hIdis = disabledmenu ? disabledmenu->ExtractIcon(iconnbr) : hIcon; if (hIcon) { MENUITEMINFO mii; CWindowDC dc(this); CDC memdc; memdc.CreateCompatibleDC(&dc); CBrush brush, brushDis; brush.CreateSysColorBrush(COLOR_MENU); brushDis.CreateStockObject(WHITE_BRUSH); RECT rect = {0, 0, 20, 16}; // 'm_MenuBmpCtr' is the index of the next empty CBitmap // draw the icon on that CBitmap m_MenuBitmap[m_MenuBmpCtr].CreateCompatibleBitmap(&dc, 20, 16); CBitmap *poldbm = memdc.SelectObject(&m_MenuBitmap[m_MenuBmpCtr]); memdc.FillRect(&rect, &brush); ::DrawIconEx(memdc.m_hDC, 0, 0, hIcon, GetSystemMetrics(SM_CXMENUCHECK), // cx GetSystemMetrics(SM_CYMENUCHECK), // cy 0, brush, DI_NORMAL); // frame, brush, flags if (hIdis) { m_MenuBitDis[m_MenuBmpCtr].CreateBitmap(20, 16, 1, 1, NULL); memdc.SelectObject(&m_MenuBitDis[m_MenuBmpCtr]); memdc.FillRect(&rect, &brushDis); ::DrawIconEx(memdc.m_hDC, 0, 0, hIdis, GetSystemMetrics(SM_CXMENUCHECK), // cx GetSystemMetrics(SM_CYMENUCHECK), // cy 0, brush, DI_NORMAL); // frame, brush, flags m_HasDisabled = TRUE; } memdc.SelectObject(poldbm); // Attach the icon to the menu item // we do this here even tho some - but not all - // items will have the bitmap reattached by SetMenuIcon() memset(&mii, _T('\0'), sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_BITMAP; mii.hbmpItem = HBITMAP(m_MenuBitmap[m_MenuBmpCtr]); // Now save the associated menu ID in the corresponding 'm_MenuBmpCtr' m_MenuIDbm[m_MenuBmpCtr++] = id; // Do the actual attach to the main menu GetMenu()->SetMenuItemInfo(id, &mii); } } HWND CMainFrame::OldChgsWnd() { CP4PaneView * pv = DYNAMIC_DOWNCAST(CP4PaneView, m_pOldChgView); if(pv) { // target is a CP4PaneView, so we actually want to // send messages to its content window return pv->GetContent()->GetWnd()->m_hWnd; } else return m_pOldChgView->m_hWnd; } HWND CMainFrame::BranchWnd() { CP4PaneView * pv = DYNAMIC_DOWNCAST(CP4PaneView, m_pBranchView); if(pv) { // target is a CP4PaneView, so we actually want to // send messages to its content window return pv->GetContent()->GetWnd()->m_hWnd; } else return m_pBranchView->m_hWnd; } HWND CMainFrame::LabelWnd() { CP4PaneView * pv = DYNAMIC_DOWNCAST(CP4PaneView, m_pLabelView); if(pv) { // target is a CP4PaneView, so we actually want to // send messages to its content window return pv->GetContent()->GetWnd()->m_hWnd; } else return m_pLabelView->m_hWnd; } HWND CMainFrame::ClientWnd() { CP4PaneView * pv = DYNAMIC_DOWNCAST(CP4PaneView, m_pClientView); if(pv) { // target is a CP4PaneView, so we actually want to // send messages to its content window return pv->GetContent()->GetWnd()->m_hWnd; } else return m_pClientView->m_hWnd; } HWND CMainFrame::UserWnd() { CP4PaneView * pv = DYNAMIC_DOWNCAST(CP4PaneView, m_pUserView); if(pv) { // target is a CP4PaneView, so we actually want to // send messages to its content window return pv->GetContent()->GetWnd()->m_hWnd; } else return m_pUserView->m_hWnd; } HWND CMainFrame::JobWnd() { CP4PaneView * pv = DYNAMIC_DOWNCAST(CP4PaneView, m_pJobView); if(pv) { // target is a CP4PaneView, so we actually want to // send messages to its content window return pv->GetContent()->GetWnd()->m_hWnd; } else return m_pJobView->m_hWnd; } void CMainFrame::OnGettingStartedWithP4win() { int i; CString str = TheApp()->GetHelpFilePath(); HINSTANCE hinst=0; if ((i = str.ReverseFind(_T('.'))) != -1) { str = str.Left(i) + _T("-gs.pdf"); hinst = ShellExecute( m_hWnd, _T("open"), str, NULL, NULL, SW_SHOWNORMAL); if( (int) hinst > 32) return; // successfull launch switch( (int) hinst ) { case SE_ERR_NOASSOC: i = IDS_SE_ERR_NOASSOC; break; case SE_ERR_FNF: case SE_ERR_PNF: if (IDYES == AfxMessageBox(IDS_GET_P4WINGS_FROM_WEB, MB_ICONQUESTION|MB_YESNO)) { hinst = ShellExecute( m_hWnd, _T("open"), LoadStringResource(IDS_P4DOCS_URL), NULL, NULL, SW_SHOWNORMAL); if( (int) hinst > 32) return; // successfull launch } i = IDS_SE_ERR_FNF; break; default: i = IDS_SE_ERR_OTHER; break; } } CString txt; txt.FormatMessage(i, str, hinst); TheApp()->StatusAdd( txt, SV_ERROR ); } int CMainFrame::GetClientColNamesAndCount(CStringArray &cols) { return m_pClientView->GetListCtrl().GetColNamesAndCount(cols); } int CMainFrame::GetUserColNamesAndCount(CStringArray &cols) { return m_pUserView->GetListCtrl().GetColNamesAndCount(cols); } void CMainFrame::SetModelessWnd(CDialog *pDlg) { m_DlgWndList.AddHead((CObject *)pDlg); } LRESULT CMainFrame::OnP4DialogDestroy(WPARAM wParam, LPARAM lParam) { CDialog *pDlg = (CDialog *)lParam; POSITION pos1, pos2; for( pos1 = m_DlgWndList.GetHeadPosition(); ( pos2 = pos1 ) != NULL; ) { if( (CDialog*) m_DlgWndList.GetNext( pos1 ) == pDlg ) { m_DlgWndList.RemoveAt( pos2 ); break; } } GetDesktopWindow()->ArrangeIconicWindows(); delete pDlg; return TRUE; } void CMainFrame::OnUpdateCloseAllModelessDlgs(CCmdUI* pCmdUI) { pCmdUI->Enable(m_DlgWndList.GetCount() && !SERVER_BUSY()); } void CMainFrame::CloseAllModelessDlgs() { if (!SERVER_BUSY()) SignalAllModelessDlgs(WM_CLOSE); } void CMainFrame::SignalAllModelessDlgs(UINT msg) { CDialog *pDlg; POSITION pos1, pos2; for( pos1 = m_DlgWndList.GetHeadPosition(); ( pos2 = pos1 ) != NULL; ) { pDlg = (CDialog*) m_DlgWndList.GetNext( pos1 ); if (!::IsWindow(pDlg->m_hWnd)) continue; pDlg->SendMessage(msg, 0, 0); switch(msg) { case WM_CLOSE: m_DlgWndList.RemoveAt( pos2 ); break; case WM_QUITTING: delete pDlg; break; } } } DWORD CMainFrame::GetExeVersion( TCHAR *exeName ) { DWORD dummy; DWORD infoSize = GetFileVersionInfoSize( exeName, &dummy ); if( !infoSize ) return 0; BYTE* buf = new BYTE[infoSize]; if( !buf || !GetFileVersionInfo( exeName, 0, infoSize, buf ) ) { delete buf; return 0; } VS_FIXEDFILEINFO* info; UINT is; if( !VerQueryValue( buf, TEXT("\\"), (LPVOID*)&info, &is ) || !is ) { delete buf; return 0; } DWORD tmp = HIWORD( info->dwProductVersionMS ) * 10 + LOWORD( info->dwProductVersionMS ); delete buf; return tmp; } LRESULT CMainFrame::OnP4HelperApp(WPARAM wParam, LPARAM lParam) { switch (wParam) { case HAM_ADDHANDLE: m_hWndHelperApp.AddTail((CObject *)lParam); break; case HAM_RMVHANDLE: { POSITION pos1, pos2; /// CObject* pa; for( pos1 = m_hWndHelperApp.GetHeadPosition(); ( pos2 = pos1 ) != NULL; ) { if( (CObject*)m_hWndHelperApp.GetNext( pos1 ) == (CObject*)lParam ) { /// pa = list.GetAt( pos2 ); // Save the old pointer for /// //deletion. m_hWndHelperApp.RemoveAt( pos2 ); /// delete pa; // Deletion avoids memory leak. break; } } break; } } return 0; } #include void CMainFrame::SetMessageText(LPCTSTR lpszText) { if (m_DoNotAutoPollCtr) { CString msg = CString(lpszText) + LoadStringResource(IDS_POLLINGOFF); SendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)msg.GetBuffer()); } else SendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)lpszText); } BOOL CMainFrame::IsClientFilteredOut(CP4Client *client, CString *user, CString *curcli, CString *defcli) { // if no filter, nothing is filtered out int filterFlags = GET_P4REGPTR()->GetClientFilteredFlags(); if (!filterFlags) return FALSE; // default and current clients never get filtered out CString curclient = curcli ? *curcli : GET_P4REGPTR()->GetP4Client(); if (!curclient.Compare(client->GetClientName())) return FALSE; CString defclient = defcli ? *defcli : GET_P4REGPTR()->GetP4Client(TRUE); if (!defclient.Compare(client->GetClientName())) return FALSE; if (filterFlags & 0x10 && Compare(client->GetOwner(), user ? *user : GET_P4REGPTR()->GetP4User())) return TRUE; if (filterFlags & 0x01 && Compare(client->GetOwner(), GET_P4REGPTR()->GetClientFilterOwner())) return TRUE; if (filterFlags & 0x20) { CString host = client->GetHost(); if ((host.GetLength() != 0) && Compare(host, GET_P4REGPTR()->GetHostname())) return TRUE; } else if (filterFlags & 0x02) { CString host = client->GetHost(); if ((host.GetLength() != 0) && Compare(host, GET_P4REGPTR()->GetClientFilterHost())) return TRUE; } if (filterFlags & 0x04) { CString fnd = GET_P4REGPTR()->GetClientFilterDesc(); CString txt = client->GetDescription(); fnd.MakeLower(); txt.MakeLower(); if (txt.Find(fnd) == -1) return TRUE; } return FALSE; } BOOL CMainFrame::IsBranchFilteredOut(CP4Branch *branch, CString *user) { int filterFlags = GET_P4REGPTR()->GetBranchFilteredFlags(); if (!filterFlags) return FALSE; if (filterFlags & 0x10 && Compare(branch->GetOwner(), user ? *user : GET_P4REGPTR()->GetP4User())) return TRUE; if (filterFlags & 0x01 && Compare(branch->GetOwner(), GET_P4REGPTR()->GetBranchFilterOwner())) return TRUE; return FALSE; }