// StatusView.cpp : implementation file // #include "stdafx.h" #include "p4win.h" #include "StatusView.h" #include "MainFrm.h" #include "MsgBox.h" #include "ImageList.h" #include "cmd_where.h" #pragma warning (push) #pragma warning (disable: 4201) #include <mmsystem.h> #pragma warning (pop) #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CStatusView IMPLEMENT_DYNCREATE(CStatusView, CListView) CStatusView::CStatusView() { m_HeadIndex=0; m_ErrFound = m_RowAdded = FALSE; m_ShowStatusMsgs = GET_P4REGPTR()->GetShowStatusMsgs(); OnMaxStatusLines(); CString tempPath= GET_P4REGPTR()->GetTempDir(); CreateDirectory(tempPath, NULL); // make sure the directory exists for (int i = -1; ++i < 256; ) { m_ErrFile.Format(_T("%s\\P4Werr%02x.txt"), tempPath, i); if ((m_hErrFile=CreateFile(m_ErrFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0)) != INVALID_HANDLE_VALUE) { #ifdef UNICODE TCHAR msg[] = {0xFEFF}; DWORD NumberOfBytesWritten; WriteFile(m_hErrFile, msg, 2, &NumberOfBytesWritten, NULL); #endif break; } } EnableToolTips(); } CStatusView::~CStatusView() { CloseHandle(m_hErrFile); } BEGIN_MESSAGE_MAP(CStatusView, CListView) //{{AFX_MSG_MAP(CStatusView) ON_WM_SIZE() ON_WM_SETCURSOR() ON_WM_KEYDOWN() ON_WM_CONTEXTMENU() ON_NOTIFY_EX( TTN_NEEDTEXTW, 0, OnToolTipText ) ON_NOTIFY_EX( TTN_NEEDTEXTA, 0, OnToolTipText ) ON_COMMAND(ID_WINDOW_CLEAR, OnWindowClear) ON_COMMAND(ID_SHOW_COMMAND_TRACE, OnShowCommandTrace ) ON_COMMAND(ID_SHOW_TIMESTAMP, OnShowTimestamp) ON_COMMAND(ID_SHOW_STATUSMSGS, OnShowStatusMsgs) ON_UPDATE_COMMAND_UI(ID_VIEW_WARNANDERR, OnUpdateViewWarnAndErrs) ON_COMMAND(ID_VIEW_WARNANDERR, OnViewWarnAndErrs) ON_UPDATE_COMMAND_UI(ID_WINDOW_COPYSELECTED, OnUpdateWindowCopyselected) ON_COMMAND(ID_EDIT_COPY, OnWindowCopyselected) ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll) ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll) ON_UPDATE_COMMAND_UI(ID_POSITIONDEPOT, OnUpdateFindInDepot) ON_COMMAND(ID_POSITIONDEPOT, OnFindInDepot) ON_UPDATE_COMMAND_UI(ID_POSITIONCHGS, OnUpdateFindInChgs) ON_COMMAND(ID_POSITIONCHGS, OnFindInChgs) ON_COMMAND(ID_PERFORCE_OPTIONS, OnPerforceOptions) //}}AFX_MSG_MAP ON_MESSAGE( WM_FINDPATTERN, OnFindPattern ) ON_WM_SYSCOLORCHANGE() END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CStatusView diagnostics #ifdef _DEBUG void CStatusView::AssertValid() const { CListView::AssertValid(); } void CStatusView::Dump(CDumpContext& dc) const { CListView::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CStatusView message handlers void CStatusView::Clear() { ListView_DeleteAllItems(m_hWnd); m_HeadIndex=0; } void CStatusView::OnInitialUpdate() { CListView::OnInitialUpdate(); // Set image shared list CListCtrl& list= (CListCtrl&) GetListCtrl(); list.SetImageList(TheApp()->GetImageList(), LVSIL_SMALL); LV_COLUMN lvCol; lvCol.mask= LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH; lvCol.fmt=LVCFMT_LEFT; lvCol.iSubItem=0; lvCol.cx=1800; list.InsertColumn(0, &lvCol); } void CStatusView::AddItem(LPCTSTR text, StatusView level, bool showDialog, BOOL ensureVisible /*=TRUE */) { ASSERT( text != NULL); ASSERT( level >= SV_MSG && level < SV_MAX); int len= lstrlen(text); BOOL didFirstRow= FALSE; BOOL write2file = (showDialog==true || level==SV_WARNING || level==SV_ERROR || level==SV_WARNSUMMARY) ? TRUE : FALSE; if (write2file && TheApp()->m_RunClientWizOnly) showDialog = TRUE; // Alloc a large enough buffer and initialize cleanText CString cleanText(_T(' '), len + 10); cleanText.Empty(); if (GET_P4REGPTR()->ShowStatusTime()) { SYSTEMTIME st; GetLocalTime(&st); if (GET_P4REGPTR()->Use24hourClock()) { cleanText.Format(_T("%02d:%02d:%02d "), st.wHour, st.wMinute, st.wSecond); } else { cleanText.Format(_T("%d:%02d:%02d "), (st.wHour > 12) ? st.wHour - 12 : st.wHour, st.wMinute, st.wSecond); } } for(int i=0; i < len; i++) { // Split out multiple rows as required if(text[i] == _T('\n') && cleanText.GetLength() > 0) { if(!didFirstRow) { AddOneRow(cleanText, level, ensureVisible, write2file); didFirstRow= TRUE; } else { // Dont show bitmap for continuation lines AddOneRow(cleanText, SV_BLANK, ensureVisible, write2file); } cleanText.Empty(); } // Get rid of misc control chars else if(text[i] != _T('\r') && text[i] != _T('\t') && text[i] != _T('\n')) cleanText+= text[i]; } if(cleanText.GetLength() > 0) { if(!didFirstRow) { AddOneRow(cleanText, level, ensureVisible, write2file); didFirstRow=TRUE; } else { // Dont show bitmap for continuation lines AddOneRow(cleanText, SV_BLANK, ensureVisible, write2file); } } if(didFirstRow) { // Play a sound. The nodefault flag is used so PlaySound is silent when the // sound is not defined. if(level== SV_WARNING) PlaySound(_T("PerforceWarning"), NULL, SND_ALIAS | SND_ASYNC | SND_NOWAIT | SND_NODEFAULT); else if(level== SV_COMPLETION) PlaySound(_T("PerforceCompleted"), NULL, SND_ALIAS | SND_ASYNC | SND_NOWAIT | SND_NODEFAULT); else if(level== SV_ERROR) { // Check to see if the main menu or Status pane context menu is open BOOL bMenuOpen = FALSE; MENUBARINFO mbi; mbi.cbSize = sizeof(MENUBARINFO); if (MainFrame()->m_InPopUpMenu || (MainFrame()->GetMenuBarInfo(OBJID_MENU, 0, &mbi) && mbi.fBarFocused)) bMenuOpen = TRUE; // If the mouse is captured - release it and pump the message loop. // This can happen if the user is dragging the toolbar to a new // location when we get here. We only do this however if all menus // are closed - if one is open and we mess with the Capture, it // makes another mess. Things are still a mess cuz MS still doesn't // clean up from the drag and leaves the main window on top with the // upcoming messagebox hidden. Yuck - and I still can't figure a way // out of that mess. while (!bMenuOpen && ::GetCapture()) { MSG msg; ::ReleaseCapture(); if (!MainFrame()->IsQuitting()) { while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) { if (!::GetMessage(&msg, NULL, NULL, NULL)) { ::PostQuitMessage(0); break; } if (!(TheApp( )->PreTranslateMessage(&msg))) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } } } } // Note: there is no real app modal message box, so set a flag to // kill the autopoll timer, thus preventing a billion error boxes // if the machine is unattended if (!showDialog) { SET_APP_HALTED(TRUE); PlaySound(_T("PerforceError"), NULL, SND_ALIAS | SND_SYNC | SND_NOWAIT | SND_NODEFAULT); AfxMessageBox(text, MB_ICONSTOP | MB_SYSTEMMODAL); SET_APP_HALTED(FALSE); } } } if(didFirstRow && showDialog) { CString str = CString(_T("OK\t")) + text; str.Replace('\t', ' '); str.SetAt(2, '\t'); int i, j; for (i = j = 0; (i = str.Find('\n', i)) != -1; i++) j++; BOOL b = (j > 5 || str.GetLength() > 200) ? TRUE : FALSE; switch(level) { case SV_WARNING: MsgBox( str, MB_ICONEXCLAMATION, IDC_BUTTON2, this, NULL, b ); break; default: MsgBox( str, MB_ICONSTOP, IDC_BUTTON2, this, NULL, b ); break; } MainFrame()->SetStatusBarLevel(level); } } void CStatusView::AddOneRow(LPCTSTR text, StatusView level, BOOL ensureVisible, BOOL write2file, BOOL bSave/*=TRUE*/) { DWORD NumberOfBytesWritten; ASSERT( text != NULL); ASSERT( level >= SV_MSG && level < SV_MAX); // Add the image and text LV_ITEM lvItem; lvItem.mask=LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; lvItem.iItem= m_HeadIndex; lvItem.iSubItem= 0; lvItem.iImage = CP4ViewImageList::VI_STATUS_MSG + level; lvItem.pszText= const_cast<LPTSTR>(text); lvItem.lParam= level; if (write2file || m_ShowStatusMsgs || level== SV_COMPLETION || level== SV_WARNING || level== SV_ERROR || level== SV_WARNSUMMARY) { // If the output window has too many rows, delete oldest row if(ListView_GetItemCount(m_hWnd) >= m_MaxStatusLines) ListView_DeleteItem(m_hWnd, 0); // Add the item to the status listview m_HeadIndex=ListView_InsertItem(m_hWnd, &lvItem); if( ensureVisible ) ListView_EnsureVisible(m_hWnd, m_HeadIndex, FALSE); m_HeadIndex++; m_RowAdded = TRUE; } CString msg; msg.Format(_T("%d %s\r\n"), level, text); if (bSave) { if (m_StatusRows.GetCount() > m_MaxSaveLines) m_StatusRows.RemoveHead(); m_StatusRows.AddTail(msg); } if (write2file) { m_ErrFound = TRUE; WriteFile(m_hErrFile, msg, msg.GetLength()*sizeof(TCHAR), &NumberOfBytesWritten, NULL); MainFrame()->SetStatusBarLevel(level); } if (GET_P4REGPTR()->GetStatusUpdateInterval() && m_ShowStatusMsgs) SendMessage(WM_SETREDRAW, FALSE, 0); } BOOL CStatusView::PreCreateWindow(CREATESTRUCT& cs) { cs.style|= LVS_NOCOLUMNHEADER | LVS_SHAREIMAGELISTS | LVS_ALIGNLEFT | LVS_REPORT; return CListView::PreCreateWindow(cs); } void CStatusView::OnSize(UINT nType, int cx, int cy) { CListView::OnSize(nType, cx, cy); } BOOL CStatusView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if(SERVER_BUSY()) return SET_BUSYCURSOR(); else return CListView::OnSetCursor(pWnd, nHitTest, message); } void CStatusView::OnWindowClear() { Clear(); } void CStatusView::OnContextMenu(CWnd* pWnd, CPoint point) { CMenu popMenu; MainFrame()->m_InPopUpMenu = TRUE; if (point.x <= 0 && point.y <= 0) // Position NOT actually in status window? { point.x = point.y = 0; ClientToScreen(&point); // re-position to upper left corner of status window } popMenu.LoadMenu(IDR_STATUS); popMenu.GetSubMenu(0)->CheckMenuItem(ID_SHOW_COMMAND_TRACE, MF_BYCOMMAND | (GET_P4REGPTR()->ShowCommandTrace( ) ? MF_CHECKED : MF_UNCHECKED)); popMenu.GetSubMenu(0)->CheckMenuItem(ID_SHOW_TIMESTAMP, MF_BYCOMMAND | (GET_P4REGPTR()->ShowStatusTime( ) ? MF_CHECKED : MF_UNCHECKED)); popMenu.GetSubMenu(0)->CheckMenuItem(ID_SHOW_STATUSMSGS, MF_BYCOMMAND | (GET_P4REGPTR()->GetShowStatusMsgs( ) ? MF_CHECKED : MF_UNCHECKED)); popMenu.GetSubMenu(0)->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd( )); MainFrame()->m_InPopUpMenu = FALSE; } /* _________________________________________________________________ toggle the show command trace flag in the registry. _________________________________________________________________ */ void CStatusView::OnShowCommandTrace() { GET_P4REGPTR()->SetShowCommandTrace( ! GET_P4REGPTR()->ShowCommandTrace() ); } void CStatusView::OnUpdateViewWarnAndErrs(CCmdUI* pCmdUI) { pCmdUI->Enable( m_ErrFound ); } void CStatusView::CallOnUpdateViewWarnAndErrs(CCmdUI* pCmdUI) { OnUpdateViewWarnAndErrs(pCmdUI); } void CStatusView::OnMaxStatusLines() { m_MaxStatusLines = GET_P4REGPTR()->GetMaxStatusLines(); m_MaxSaveLines = min(2000, max(m_MaxStatusLines >> 4, 250)); if (m_MaxSaveLines > m_MaxStatusLines) m_MaxSaveLines = m_MaxStatusLines; } void CStatusView::OnViewWarnAndErrs() { if (GET_P4REGPTR()->UseNotepad4WarnAndErr()) { #ifdef UNICODE DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT; #else DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS; #endif PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; GetStartupInfo(&startInfo); startInfo.lpReserved= startInfo.lpDesktop= NULL; startInfo.dwFlags |= STARTF_USESHOWWINDOW; startInfo.wShowWindow = SW_SHOWNORMAL; TCHAR commandLine[_MAX_PATH+1]; CString cmdline = _T("notepad.exe ") + m_ErrFile; lstrcpy(commandLine, cmdline); CreateProcess( NULL, // pointer to name of executable module commandLine, // pointer to command line string NULL, NULL, // default security rot FALSE, // handle inheritance flag dwCreationFlags, // creation flags NULL, // env NULL, //default dir &startInfo, &procInfo); } else ShellExecute( AfxGetApp( )->m_pMainWnd->m_hWnd, _T("open"), m_ErrFile, NULL, NULL, SW_SHOWNORMAL); MainFrame()->SetStatusBarLevel(SV_MSG); } void CStatusView::CallOnViewWarnAndErrs() { OnViewWarnAndErrs(); } void CStatusView::OnUpdateWindowCopyselected(CCmdUI* pCmdUI) { pCmdUI->Enable( GetSelectedCount() > 0 ); } void CStatusView::OnWindowCopyselected() { CString text; GetPaneText( text, TRUE ); CopyTextToClipboard( text ); } void CStatusView::GetPaneText( CString &txt, BOOL onlySelectedText) { TCHAR buf[1024]; txt.Empty(); for( int i = 0; i < ListView_GetItemCount( m_hWnd ); i++ ) { if( !onlySelectedText || ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) { ListView_GetItemText( m_hWnd, i, 0, buf, 1023 ); switch( GetListCtrl().GetItemData( i ) ) { case SV_TOOL: txt+= LoadStringResource(IDS_STATUS_TOOL); break; case SV_DEBUG: txt+= LoadStringResource(IDS_STATUS_DEBUG); break; case SV_WARNING: txt+= LoadStringResource(IDS_STATUS_WARNING); break; case SV_ERROR: txt+= LoadStringResource(IDS_STATUS_ERROR); break; case SV_MSG: txt+= LoadStringResource(IDS_STATUS_STATUS); break; case SV_COMPLETION: case SV_WARNSUMMARY: txt+= LoadStringResource(IDS_STATUS_COMPLETION); break; case SV_BLANK: // Indent rows following lead row txt+= _T(" "); break; default: break; } txt+= buf; txt+= _T("\r\n"); } } } int CStatusView::GetSelectedCount() { int selected= 0; for( int i = 0; i < ListView_GetItemCount( m_hWnd ); i++ ) if( ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) selected++; return selected; } void CStatusView::OnUpdateEditSelectAll(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); } void CStatusView::OnEditSelectAll() { for( int i = 0; i < ListView_GetItemCount( m_hWnd ); i++ ) ListView_SetItemState( m_hWnd, i, LVIS_SELECTED, LVIS_SELECTED ); } void CStatusView::OnShowTimestamp() { BOOL showStatusTime = !GET_P4REGPTR()->ShowStatusTime( ); GET_P4REGPTR()->SetShowStatusTime( showStatusTime ); } void CStatusView::OnShowStatusMsgs() { m_ShowStatusMsgs = !GET_P4REGPTR()->GetShowStatusMsgs( ); GET_P4REGPTR()->SetShowStatusMsgs( m_ShowStatusMsgs ); int i; LPTSTR p, q; OnWindowClear(); if (m_ShowStatusMsgs) { CString row; for (POSITION pos = m_StatusRows.GetHeadPosition(); pos != NULL; ) { row = m_StatusRows.GetNext(pos); p = row.GetBuffer(row.GetLength()+1); i = _tstoi(p); while (*++p != _T(' ')) ; q = p++; while(*++q != _T('\r')) ; *q = _T('\0'); AddOneRow(p, (StatusView)i, TRUE, FALSE, FALSE); } } else { DWORD dw = GetFileSize(m_hErrFile, 0); CString buf(_T('\0'), dw+1); if (dw) { SetFilePointer(m_hErrFile, 0, 0, FILE_BEGIN); if (ReadFile(m_hErrFile, p = buf.GetBuffer(dw+1), dw, &dw, 0)) { while(*p) { i = _tstoi(p); while (*++p != _T(' ')) ; q = p++; while(*++q != _T('\r')) ; *q = _T('\0'); AddOneRow(p, (StatusView)i, TRUE, FALSE, FALSE); for (p = q; *++p && *p < _T(' '); ) ; } } SetFilePointer(m_hErrFile, 0, 0, FILE_END); } } } CString CStatusView::Extract1stFilename(CString &str) { int i; CString itemStr = str; 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); } 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); } itemStr.TrimRight(); } // if we find a 2nd "//", throw it and the following chars away if ((i = itemStr.Find(_T("//"), 2)) > 0) itemStr = itemStr.Left(i); // 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); return itemStr; } void CStatusView::OnUpdateFindInDepot(CCmdUI* pCmdUI) { BOOL b = FALSE; CString text; GetPaneText( text, TRUE ); if ((GetSelectedCount() == 1) && ((text.Find(_T("//")) != -1) || (text.Find(_T(":\\")) != -1))) { b = TRUE; } pCmdUI->Enable(b); if (pCmdUI->m_pParentMenu == MainFrame()->GetMenu()) pCmdUI->SetText(LoadStringResource(IDS_FINDSELFILEINDEPOT)); } void CStatusView::OnFindInDepot() { CString itemStr; GetPaneText( itemStr, TRUE ); itemStr = Extract1stFilename(itemStr); itemStr.TrimRight(_T("*/\\")); ((CMainFrame *)AfxGetMainWnd())->ExpandDepotString( itemStr, TRUE ); } void CStatusView::OnUpdateFindInChgs(CCmdUI* pCmdUI) { CString text; GetPaneText( text, TRUE ); BOOL b = ((GetSelectedCount() == 1) && ((text.Find(_T("//")) != -1) || (text.Find(_T(":\\")) != -1))); if (b) { text = Extract1stFilename(text); b = ((text.Find(_T("...")) == -1) && (text.Find(_T("*")) == -1)); } pCmdUI->Enable(b); } void CStatusView::OnFindInChgs() { int i; CString itemStr; GetPaneText( itemStr, TRUE ); itemStr = Extract1stFilename(itemStr); if ((itemStr.Find(_T("...")) == -1) && (itemStr.Find(_T("*")) == -1)) { if ((i = itemStr.FindOneOf(_T("#@"))) != -1) itemStr = itemStr.Left(i); itemStr.TrimRight(_T("*/\\ ")); if (itemStr.GetAt(0) != _T('/')) { // have to convert to depot syntax CCmd_Where *pCmd1 = new CCmd_Where; pCmd1->Init(NULL, RUN_SYNC); if ( pCmd1->Run(itemStr) && !pCmd1->GetError() && pCmd1->GetDepotFiles()->GetCount() ) { itemStr = pCmd1->GetDepotSyntax(); itemStr.TrimRight(); } delete pCmd1; } if (((CMainFrame *)AfxGetMainWnd())->PositionChgs( itemStr, TRUE, TRUE ) != -1) return; // found it } MainFrame()->SetMessageText(LoadStringResource(SERVER_BUSY() ? IDS_FILE_NOT_FOUND_YOUR_CHGS : IDS_FILE_NOT_FOUND_IN_CHGS)); } void CStatusView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { int i; if (bActivate) { SendMessage(WM_SETREDRAW, TRUE, 0); ((CMainFrame *)AfxGetMainWnd())->SetStatusBarLevel(SV_MSG); if (m_RowAdded || (ListView_GetSelectedCount( m_hWnd ) == 0)) { m_RowAdded = FALSE; i = ListView_GetItemCount( m_hWnd ); if (i--) { ListView_SetItemState( m_hWnd, i, LVIS_SELECTED, LVIS_SELECTED ); ListView_EnsureVisible( m_hWnd, i, FALSE ); } } else { for( i = ListView_GetItemCount( m_hWnd ); i--; ) if( ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) break; ListView_EnsureVisible( m_hWnd, i, FALSE ); } } CListView::OnActivateView(bActivate, pActivateView, pDeactiveView); } void CStatusView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch ( nChar ) { case VK_TAB: if ( ::GetKeyState(VK_CONTROL) & 0x8000 ) // Ctrl+TAB switches to depot pane MainFrame()->SwitchPanes((CView *)this, FALSE); break; } CListView::OnKeyDown(nChar, nRepCnt, nFlags); } void CStatusView::OnSysColorChange() { CListView::OnSysColorChange(); CListCtrl& list= (CListCtrl&) GetListCtrl(); list.SetImageList(TheApp()->GetImageList(), LVSIL_SMALL); } void CStatusView::OnPerforceOptions() { MainFrame()->OnPerforceOptions(TRUE, FALSE, IDS_PAGE_STATUS); } LRESULT CStatusView::OnFindPattern(WPARAM wParam, LPARAM lParam) { TCHAR str[ 1024 ]; CString text; CString what = (TCHAR *)lParam; int flags = (int)wParam; int prev = -1; if (!(flags & FR_MATCHCASE)) what.MakeLower(); int i, j; CListCtrl& list= (CListCtrl&) GetListCtrl(); int columns = list.GetHeaderCtrl()->GetItemCount(); if (flags & FR_DOWN) { for( i = 0; i < ListView_GetItemCount(m_hWnd); i++ ) { if( ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) { ListView_SetItemState( m_hWnd, prev = i, 0, LVIS_SELECTED|LVIS_FOCUSED ); while (ListView_GetSelectedCount(m_hWnd)) // clear remaining selections { if( ListView_GetItemState( m_hWnd, ++i, LVIS_SELECTED ) == LVIS_SELECTED ) ListView_SetItemState( m_hWnd, i, 0, LVIS_SELECTED|LVIS_FOCUSED ); } i = prev; break; } } if (flags < 0) i++; while( i < ListView_GetItemCount(m_hWnd) ) { for (j =-1; ++j < columns; ) { ListView_GetItemText( m_hWnd, i, j, str, sizeof(str)/sizeof(TCHAR) ); text = _T(""); switch( GetListCtrl().GetItemData( i ) ) { case SV_ERROR: text = LoadStringResource(IDS_STATUS_ERROR); case SV_WARNING: case SV_WARNSUMMARY: text+= LoadStringResource(IDS_STATUS_WARNING) + str; break; case SV_COMPLETION: text = LoadStringResource(IDS_STATUS_COMPLETION) + str; break; case SV_TOOL: text = LoadStringResource(IDS_STATUS_TOOL) + str; break; default: text = str; break; } if (!(flags & FR_MATCHCASE)) text.MakeLower(); if (text.Find(what) != -1) { ListView_SetItemState( m_hWnd, i, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); list.EnsureVisible(i, FALSE); MainFrame()->SetMessageText(LoadStringResource(IDS_FOUND)); return 0; } } i++; } } else { for( i = ListView_GetItemCount(m_hWnd); --i >= 0; ) { if( ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) { ListView_SetItemState( m_hWnd, prev = i, 0, LVIS_SELECTED|LVIS_FOCUSED ); while (ListView_GetSelectedCount(m_hWnd)) // clear remaining selections { if( ListView_GetItemState( m_hWnd, --i, LVIS_SELECTED ) == LVIS_SELECTED ) ListView_SetItemState( m_hWnd, i, 0, LVIS_SELECTED|LVIS_FOCUSED ); } i = prev; break; } } if (flags < 0) i--; while( i >= 0 ) { for (j =-1; ++j < columns; ) { ListView_GetItemText( m_hWnd, i, j, str, sizeof(str)/sizeof(TCHAR) ); text = _T(""); switch( GetListCtrl().GetItemData( i ) ) { case SV_ERROR: text = LoadStringResource(IDS_STATUS_ERROR); case SV_WARNING: case SV_WARNSUMMARY: text+= LoadStringResource(IDS_STATUS_WARNING) + str; break; case SV_COMPLETION: text = LoadStringResource(IDS_STATUS_COMPLETION) + str; break; case SV_TOOL: text = LoadStringResource(IDS_STATUS_TOOL) + str; break; default: text = str; break; } if (!(flags & FR_MATCHCASE)) text.MakeLower(); if (text.Find(what) != -1) { ListView_SetItemState( m_hWnd, i, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); list.EnsureVisible(i, FALSE); MainFrame()->SetMessageText(LoadStringResource(IDS_FOUND)); return 0; } } i--; } } MessageBeep(0); MainFrame()->SetMessageText(LoadStringResource(IDS_NOT_FOUND)); if (prev != -1) ListView_SetItemState( m_hWnd, prev, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); return 0; } static int indexNbr = -1; int CStatusView::OnToolHitTest(CPoint point, TOOLINFO* pTI) const { // CWnd implementation won't do us any good, so we have to handle this. // watch out! sometimes get called with null pointer if (pTI == 0 || !GET_P4REGPTR()->GetShowTruncTooltip( )) return -1; // don't want to show tooltip if nothing is hidden // the tooltip is only there to show truncated text int index; LVHITTESTINFO info; info.pt = point; ListView_HitTest(m_hWnd, &info); if ((index = info.iItem) == -1) return -1; // retun because not on a line with text TCHAR buf[1024]; ListView_GetItemText( m_hWnd, index, 0, buf, 1023 ); int lgth = lstrlen(buf); if (lgth < 50) return -1; // return - line has less than 50 characters CRect rect; GetWindowRect(&rect); HDC hDC = ::GetDC(m_hWnd); SIZE size; GetTextExtentPoint32(hDC, buf, lgth, &size); ::ReleaseDC(m_hWnd, hDC); if ((size.cx < rect.Width()) && (size.cx < 1700)) return -1; // return - line is fully visible if (indexNbr != index) { // If this is the 1st time for this line, just return // in order to remove any current tooltip; we will be // called again and will put up the tooltip then. indexNbr = index; return -1; } // we want to show a tooltip, so set up for the normal callback pTI->hwnd = m_hWnd; // us pTI->uId = (UINT_PTR)m_hWnd; // us pTI->uFlags |= TTF_IDISHWND; // uId is HWND, not ID pTI->lpszText = LPSTR_TEXTCALLBACK; indexNbr = index; // save in a static since this function Must be const! return (int)pTI->uId; } BOOL CStatusView::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult ) { // first, check for my tooltip text request // and handle it here TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR; UINT nID =pNMHDR->idFrom; if (pTTT->uFlags & TTF_IDISHWND) { if(nID == (UINT)m_hWnd) { TCHAR buf[1024]; CRect rect; GetClientRect(&rect); ::SendMessage(pTTT->hdr.hwndFrom, TTM_SETMAXTIPWIDTH, 0, max(480, 2*rect.Width()/3)); ListView_GetItemText( m_hWnd, indexNbr, 0, buf, 1023 ); m_ToolTipText = buf; pTTT->lpszText = (LPTSTR)(LPCTSTR)m_ToolTipText; pTTT->hinst = NULL; return TRUE; } } // for other cases, just pass it along to mainframe return MainFrame()->OnToolTipText(id, pNMHDR, pResult); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 16169 | perforce_software | Move files to follow new path scheme for branches. | ||
//guest/perforce_software/p4win/gui/StatusView.cpp | |||||
#1 | 8562 | Matt Attaway |
These feet never stop running. Initial commit of the P4Win source code. To the best of our knowledge this compiles and runs using the 2013.3 P4 API and VS 2010. Expect a few changes as we refine the build process. Please post any build issues to the forums. |