mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
508 lines
12 KiB
C++
508 lines
12 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
// NSAdrNam.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "nsadrlst.h"
|
|
#include "nsadrnam.h"
|
|
#include "addrbook.h"
|
|
#include "addrfrm.h" //only need for #ifdef MOZ_NEWADDR
|
|
#include "wfemsg.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CNSAddressNameEditField
|
|
|
|
|
|
CNSAddressNameEditField::CNSAddressNameEditField(CNSAddressList *pParentAddressList)
|
|
{
|
|
m_pIAddressParent = NULL;
|
|
m_bNameCompletion = FALSE;
|
|
m_bAttemptNameCompletion = TRUE;
|
|
#ifdef MOZ_NEWADDR
|
|
m_bSetTimerForCompletion = TRUE;
|
|
#else
|
|
m_bSetTimerForCompletion = FALSE;
|
|
#endif
|
|
m_uTypedownClock = 0;
|
|
|
|
m_pParentAddressList = pParentAddressList;
|
|
}
|
|
|
|
CNSAddressNameEditField::~CNSAddressNameEditField()
|
|
{
|
|
}
|
|
|
|
|
|
BOOL CNSAddressNameEditField::Create( CWnd *pParent, MWContext *pContext )
|
|
{
|
|
return CGenericEdit::Create(ES_MULTILINE|ES_WANTRETURN|ES_LEFT|ES_AUTOHSCROLL, CRect(0,0,0,0), pParent, (UINT)IDC_STATIC );
|
|
}
|
|
|
|
static BOOL replaceNewLineWithSpace(LPSTR szString, LPSTR szSource)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
int iLength = strlen(szSource);
|
|
|
|
for(int i = 0, j = 0; i < iLength; i++)
|
|
{
|
|
if((szSource[i] == '\n') || (szSource[i] == '\r') || (szSource[i] == '\t'))
|
|
{
|
|
bRet = TRUE;
|
|
szString[j] = ' ';
|
|
}
|
|
else
|
|
szString[j] = szSource[i];
|
|
|
|
if((j >= 0) && (szString[j - 1] == ' ') && (szString[j] == ' '))
|
|
continue;
|
|
|
|
j++;
|
|
}
|
|
|
|
szString[j] = '\0';
|
|
|
|
return bRet;
|
|
}
|
|
|
|
void CNSAddressNameEditField::Paste()
|
|
{
|
|
if(!IsClipboardFormatAvailable(CF_TEXT))
|
|
{
|
|
CGenericEdit::Paste();
|
|
return;
|
|
}
|
|
|
|
if(!OpenClipboard())
|
|
{
|
|
CGenericEdit::Paste();
|
|
return;
|
|
}
|
|
|
|
LPSTR psz = (LPSTR)GetClipboardData(CF_TEXT);
|
|
|
|
if(psz == NULL)
|
|
{
|
|
CloseClipboard();
|
|
CGenericEdit::Paste();
|
|
return;
|
|
}
|
|
|
|
// copy clipboard content for modification
|
|
HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, strlen(psz) + 1);
|
|
LPVOID pData = GlobalLock(hData);
|
|
strcpy((LPSTR)pData, psz);
|
|
|
|
if(!replaceNewLineWithSpace((LPSTR)pData, psz))
|
|
{
|
|
// no modification made
|
|
GlobalUnlock(hData);
|
|
GlobalFree(hData);
|
|
CloseClipboard();
|
|
CGenericEdit::Paste();
|
|
return;
|
|
}
|
|
|
|
// backup a copy of clipboard content
|
|
HGLOBAL hBackup = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, strlen(psz) + 1);
|
|
LPVOID pBackup = GlobalLock(hBackup);
|
|
strcpy((LPSTR)pBackup, psz);
|
|
|
|
GlobalUnlock(hData);
|
|
SetClipboardData(CF_TEXT, hData);
|
|
|
|
LPSTR pszNew = (LPSTR)GetClipboardData(CF_TEXT);
|
|
|
|
CGenericEdit::Paste();
|
|
|
|
// restore clipboard content
|
|
GlobalUnlock(hBackup);
|
|
SetClipboardData(CF_TEXT, hBackup);
|
|
|
|
GlobalFree(hData);
|
|
|
|
// we don't free hBackup -- see description of SetClipboardData(...)
|
|
|
|
CloseClipboard();
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CNSAddressNameEditField, CGenericEdit)
|
|
//{{AFX_MSG_MAP(CNSAddressNameEditField)
|
|
ON_WM_KILLFOCUS()
|
|
ON_WM_TIMER ()
|
|
ON_WM_CHAR()
|
|
ON_WM_CREATE()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CNSAddressNameEditField message handlers
|
|
|
|
|
|
BOOL CNSAddressNameEditField::PreTranslateMessage( MSG* pMsg )
|
|
{
|
|
if (pMsg->message == WM_KEYDOWN)
|
|
{
|
|
if (pMsg->wParam == 'v' || pMsg->wParam == 'V')
|
|
{
|
|
if (GetKeyState(VK_CONTROL)&0x8000)
|
|
{
|
|
Paste();
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (pMsg->wParam == VK_INSERT)
|
|
{
|
|
if (GetKeyState(VK_SHIFT)&0x8000)
|
|
{
|
|
Paste();
|
|
return TRUE;
|
|
}
|
|
else if (GetKeyState(VK_CONTROL)&0x8000)
|
|
{
|
|
Copy();
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (pMsg->wParam == 'x' || pMsg->wParam == 'X')
|
|
{
|
|
if (GetKeyState(VK_CONTROL)&0x8000)
|
|
{
|
|
Cut();
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (pMsg->wParam == 'c' || pMsg->wParam == 'C')
|
|
{
|
|
if (GetKeyState(VK_CONTROL)&0x8000)
|
|
{
|
|
Copy();
|
|
return TRUE;
|
|
}
|
|
}
|
|
#ifdef MOZ_NEWADDR
|
|
else if(pMsg->wParam == 'j' || pMsg->wParam == 'J')
|
|
{
|
|
//check this on 16 bit
|
|
if ( ((CNSAddressList *)GetParent())->OnKeyPress( this, pMsg->wParam, pMsg->lParam & 0x1000,
|
|
pMsg->lParam & 0x10000000))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
#endif
|
|
}
|
|
return CGenericEdit::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
void CNSAddressNameEditField::OnKillFocus(CWnd * pNewWnd)
|
|
{
|
|
if (GetParent()->SendMessage(WM_NOTIFYSELECTIONCHANGE))
|
|
CGenericEdit::OnKillFocus(pNewWnd);
|
|
else
|
|
SetSel(0, -1);
|
|
}
|
|
|
|
static int howManyAmpersands(char * szString)
|
|
{
|
|
if(szString == NULL)
|
|
return 0;
|
|
|
|
int iCount = 0;
|
|
int iLength = strlen(szString);
|
|
|
|
for(int i = 0; i < iLength; i++)
|
|
{
|
|
if(szString[i] == '&')
|
|
iCount++;
|
|
}
|
|
|
|
return iCount;
|
|
}
|
|
|
|
static char * makeRightAmpersandString(char * szString, int iNumAmp)
|
|
{
|
|
if(iNumAmp <= 0)
|
|
return NULL;
|
|
|
|
int iLength = strlen(szString);
|
|
int iRightLength = iLength + iNumAmp;
|
|
|
|
char * szRightString = new char[iRightLength + 1];
|
|
|
|
if(szRightString == NULL)
|
|
return NULL;
|
|
|
|
for(int i = 0, k = 0; i < iLength; i++, k++)
|
|
{
|
|
if(szString[i] == '&')
|
|
szRightString[k++] = '&';
|
|
szRightString[k] = szString[i];
|
|
}
|
|
|
|
szRightString[iRightLength] = '\0';
|
|
return szRightString;
|
|
}
|
|
|
|
static void freeRightAmpersandString(char * szString)
|
|
{
|
|
if(szString != NULL)
|
|
delete [] szString;
|
|
}
|
|
|
|
void CNSAddressNameEditField::DrawNameCompletion()
|
|
{
|
|
if (m_pIAddressParent)
|
|
{
|
|
CString cs;
|
|
GetWindowText(cs);
|
|
char *pName = NULL;
|
|
char *pMultiple = NULL;
|
|
|
|
#ifdef MOZ_NEWADDR
|
|
|
|
AB_NameCompletionCookie *pCookie;
|
|
int nNumResults;
|
|
|
|
m_pParentAddressList->GetNameCompletionCookieInfo(&pCookie, &nNumResults);
|
|
|
|
if(nNumResults > 1)
|
|
{
|
|
pMultiple = szLoadString(IDS_MULTIPLE_MATCHES);
|
|
}
|
|
else if(pCookie && nNumResults == 1)
|
|
{
|
|
pName = AB_GetNameCompletionDisplayString(pCookie);
|
|
}
|
|
|
|
#else
|
|
pName = m_pIAddressParent->NameCompletion((char*)((const char *)cs));
|
|
#endif
|
|
CDC * pDC = GetDC();
|
|
UINT iPre = cs.GetLength();
|
|
CFont * pOldFont = pDC->SelectObject(CFont::FromHandle(m_cfTextFont));
|
|
int iPixOffset = pDC->GetTextExtent(cs,iPre).cx;
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
rect.left = iPixOffset;
|
|
if (pName)
|
|
{
|
|
m_bNameCompletion = TRUE;
|
|
COLORREF crOld = pDC->SetTextColor(RGB(150,150,150));
|
|
COLORREF crOldBk = pDC->SetBkColor(GetSysColor(COLOR_WINDOW));
|
|
if (iPre < strlen(pName))
|
|
{
|
|
int iNumAmp = howManyAmpersands(&pName[iPre]);
|
|
if(iNumAmp == 0)
|
|
pDC->DrawText(&pName[iPre],strlen(&pName[iPre]),rect,DT_VCENTER|DT_LEFT);
|
|
else
|
|
{
|
|
char * pRightString = makeRightAmpersandString(&pName[iPre], iNumAmp);
|
|
if(pRightString != NULL)
|
|
{
|
|
pDC->DrawText(pRightString,strlen(pRightString),rect,DT_VCENTER|DT_LEFT);
|
|
freeRightAmpersandString(pRightString);
|
|
}
|
|
}
|
|
}
|
|
pDC->SetTextColor(crOld);
|
|
pDC->SetBkColor(crOldBk);
|
|
free(pName);
|
|
}
|
|
else if(pMultiple)
|
|
{
|
|
m_bNameCompletion = FALSE;
|
|
m_bNameCompletion = TRUE;
|
|
COLORREF crOld = pDC->SetTextColor(RGB(150,150,150));
|
|
COLORREF crOldBk = pDC->SetBkColor(GetSysColor(COLOR_WINDOW));
|
|
pDC->DrawText(pMultiple,strlen(pMultiple),rect,DT_VCENTER|DT_LEFT);
|
|
pDC->SetTextColor(crOld);
|
|
pDC->SetBkColor(crOldBk);
|
|
|
|
}
|
|
else
|
|
{
|
|
m_bNameCompletion = FALSE;
|
|
InvalidateRect(rect);
|
|
}
|
|
pDC->SelectObject(pOldFont);
|
|
ReleaseDC(pDC);
|
|
}
|
|
}
|
|
|
|
|
|
#define NAME_COMPLETION_TIMER 12
|
|
#define COMPLETION_SPEED 750
|
|
|
|
void CNSAddressNameEditField::OnTimer(UINT nID)
|
|
{
|
|
if (nID == NAME_COMPLETION_TIMER) {
|
|
KillTimer(m_uTypedownClock);
|
|
m_uTypedownClock = 0;
|
|
#ifdef MOZ_NEWADDR
|
|
m_pParentAddressList->StartNameCompletion();
|
|
#else
|
|
DrawNameCompletion();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void CNSAddressNameEditField::StopNameCompletion()
|
|
{
|
|
if (m_bSetTimerForCompletion)
|
|
{
|
|
if (m_uTypedownClock) {
|
|
KillTimer(m_uTypedownClock);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CNSAddressNameEditField::OnChar( UINT nChar, UINT nRepCnt, UINT nFlags )
|
|
{
|
|
switch (nChar)
|
|
{
|
|
case VK_ESCAPE:
|
|
return;
|
|
case VK_DELETE:
|
|
break;
|
|
default:
|
|
if ( ((CNSAddressList *)GetParent())->OnKeyPress( this, nChar, nRepCnt, nFlags ) )
|
|
return;
|
|
}
|
|
CGenericEdit::OnChar( nChar, nRepCnt, nFlags );
|
|
if (m_bAttemptNameCompletion)
|
|
{
|
|
if (m_bSetTimerForCompletion)
|
|
{
|
|
if (m_uTypedownClock) {
|
|
KillTimer(m_uTypedownClock);
|
|
|
|
}
|
|
#ifdef MOZ_NEWADDR
|
|
//Also need to kill current search because it's no longer valid
|
|
m_pParentAddressList->StopNameCompletion();
|
|
#endif
|
|
|
|
m_uTypedownClock = SetTimer(NAME_COMPLETION_TIMER, COMPLETION_SPEED, NULL);
|
|
}
|
|
else
|
|
DrawNameCompletion();
|
|
}
|
|
}
|
|
|
|
int CNSAddressNameEditField::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CGenericEdit::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
#ifndef MOZ_NEWADDR
|
|
uint32 count;
|
|
DIR_Server* pab = NULL;
|
|
|
|
|
|
DIR_GetPersonalAddressBook (theApp.m_directories, &pab);
|
|
if (pab) {
|
|
AB_GetEntryCount(pab, theApp.m_pABook, &count, ABTypeAll, NULL);
|
|
if (count > 1500)
|
|
m_bSetTimerForCompletion = TRUE;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
void CNSAddressNameEditField::SetCSID(int16 iCSID)
|
|
{
|
|
if(m_hWnd)
|
|
{
|
|
CDC * pdc = GetDC();
|
|
if (m_cfTextFont) {
|
|
theApp.ReleaseAppFont(m_cfTextFont);
|
|
}
|
|
LOGFONT lf;
|
|
memset(&lf,0,sizeof(LOGFONT));
|
|
|
|
lf.lfPitchAndFamily = FF_MODERN | FIXED_PITCH;
|
|
strcpy(lf.lfFaceName, IntlGetUIFixFaceName(iCSID));
|
|
lf.lfHeight = -MulDiv(NS_ADDRESSFONTSIZE,pdc->GetDeviceCaps(LOGPIXELSY),72);
|
|
lf.lfQuality = PROOF_QUALITY;
|
|
lf.lfCharSet = IntlGetLfCharset(iCSID);
|
|
m_cfTextFont = theApp.CreateAppFont( lf );
|
|
if (!(lf.lfPitchAndFamily & FIXED_PITCH))
|
|
m_bAttemptNameCompletion = FALSE;
|
|
::SendMessage(GetSafeHwnd(), WM_SETFONT, (WPARAM)m_cfTextFont, FALSE);
|
|
TEXTMETRIC tm;
|
|
pdc->GetTextMetrics(&tm);
|
|
m_iTextHeight = tm.tmHeight;
|
|
|
|
ReleaseDC(pdc);
|
|
}
|
|
}
|
|
void CNSAddressNameEditField::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
switch (nChar)
|
|
{
|
|
case VK_HOME:
|
|
{
|
|
int nStart, nEnd;
|
|
GetSel(nStart,nEnd);
|
|
if ((!nStart)&&(!nEnd))
|
|
((CNSAddressList *)GetParent())->OnKeyPress(this,nChar,nRepCnt,nFlags);
|
|
}
|
|
break;
|
|
case VK_END:
|
|
{
|
|
int nStart, nEnd;
|
|
GetSel(nStart,nEnd);
|
|
if (nStart == nEnd)
|
|
if (nStart == LineLength())
|
|
((CNSAddressList *)GetParent())->OnKeyPress(this,nChar,nRepCnt,nFlags);
|
|
}
|
|
break;
|
|
case VK_UP:
|
|
case VK_DOWN:
|
|
((CNSAddressList *)GetParent())->OnKeyPress(this,nChar,nRepCnt,nFlags);
|
|
break;
|
|
case VK_DELETE:
|
|
{
|
|
CString cs;
|
|
GetWindowText(cs);
|
|
if (!cs.GetLength())
|
|
{
|
|
((CNSAddressList *)GetParent())->OnKeyPress(this,nChar,nRepCnt,nFlags);
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
CGenericEdit::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CNSAddressNameEditField::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
SetSel(0,-1);
|
|
}
|
|
|
|
|