// // Copyright 1997 Nicholas J. Irias. All rights reserved. // // // Cmd_Changes.cpp #include "stdafx.h" #include "p4win.h" #include "cmd_changes.h" #include "p4change.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNCREATE(CCmd_Changes, CP4Command) int compareChanges( const void *arg1, const void *arg2 ); CCmd_Changes::CCmd_Changes(CGuiClient *client) : CP4Command(client) { m_ReplyMsg= WM_P4CHANGES; m_TaskName= _T("Changes"); m_pBatch=NULL; } CCmd_Changes::~CCmd_Changes() { if(m_pBatch != NULL) delete m_pBatch; } // 'loquatious' values can be any of the following: // 0 -> no, do not add -l or -L // 1 -> yes, use -l to get full descriptions // 2 -> yes, use -L to get max 250 byte descriptions (valid only on 2005.1 and later servers) BOOL CCmd_Changes::Run(int filter, int loquatious, CStringList *viewSpec/*=NULL*/, long numToFetch/*=0*/, BOOL inclInteg/*=FALSE*/, CString *user/*=NULL*/, CString *client/*=NULL*/) { ClearArgs(); m_BaseArgs= AddArg(_T("changes")); // May only want numToFetch most recent changes if(numToFetch > 0) { AddArg(_T("-m")); m_BaseArgs= AddArg(numToFetch); } if (inclInteg) m_BaseArgs= AddArg(_T("-i")); if (user && (GET_SERVERLEVEL() >= 12)) { m_User = *user; m_BaseArgs= AddArg(_T("-u")); m_BaseArgs= AddArg(m_User); } if (client && (GET_SERVERLEVEL() >= 12)) { m_Client = *client; m_BaseArgs= AddArg(_T("-c")); m_BaseArgs= AddArg(m_Client); } if(loquatious) m_BaseArgs= AddArg(loquatious == 2 ? _T("-L") : _T("-l")); if(filter != ALL_CHANGES) { AddArg(_T("-s")); if(filter == PENDING_CHANGES) AddArg(_T("pending")); else if(filter == SUBMITTED_CHANGES) { AddArg(_T("submitted")); if (GET_SERVERLEVEL() >= 16) m_BaseArgs= AddArg(_T("-t")); } else ASSERT(0); } m_pBatch= new CObList; // We may or may not have a view spec to limit the fetching of // changes, so sometimes we have an input list and sometimes not ASSERT(viewSpec==NULL || viewSpec->IsKindOf(RUNTIME_CLASS(CStringList))); if(viewSpec != NULL && viewSpec->GetCount()) { m_pStrListIn= viewSpec; m_posStrListIn= m_pStrListIn->GetHeadPosition(); NextListArgs(); } return CP4Command::Run(); } void CCmd_Changes::OnOutputInfo(char level, LPCTSTR data, LPCTSTR msg) { // Parse into a CP4Change and send that back CP4Change *change= new CP4Change; if( change->Create(data, GET_P4REGPTR()->GetMyID()) ) m_Changes.Add(change); else { #ifdef _DEBUG CString errMsg; errMsg.Format(_T("Change parse failed:\n%s"), data); TheApp()->StatusAdd(errMsg, SV_DEBUG); #endif delete change; } } void CCmd_Changes::PostProcess() { // First, sort the changes in decending order unsigned int size= (unsigned int) m_Changes.GetSize(); CP4Change *array= (CP4Change *) m_Changes.GetData(); qsort( (void *) array, size, sizeof( CP4Change * ), compareChanges ); // Then, dole out unique results 50 at a time, so the UI wont freeze up int lastChange=0; for( int i=0; i < m_Changes.GetSize(); i++ ) { CP4Change *change= (CP4Change *) m_Changes.GetAt(i); if( change->GetChangeNumber() != lastChange || change->GetChangeNumber() == 0 ) { lastChange= change->GetChangeNumber(); m_pBatch->AddTail( change ); } else delete change; if(m_pBatch->GetCount() > 49) { // Send a full batch to gui ::PostMessage(m_ReplyWnd, m_ReplyMsg, (WPARAM) m_pBatch, 1); m_pBatch= new CObList; } } if(m_pBatch->GetCount() > 0) { // Send a partial batch to gui ::PostMessage(m_ReplyWnd, m_ReplyMsg, (WPARAM) m_pBatch, 1); m_pBatch= NULL; } } // return <0 if arg1 < arg2, 0 if arg1=arg2, >0 if arg1 > arg2 int compareChanges( const void *arg1, const void *arg2 ) { CP4Change *c1= *((CP4Change **) arg1); CP4Change *c2= *((CP4Change **) arg2); // Next compare change number return c2->GetChangeNumber() - c1->GetChangeNumber(); }