|
|
/****************************************************************************
Copyright (c) 1998-1999 Microsoft Corporation Module Name: cplcallingcardps.cpp Author: toddb - 10/06/98 ****************************************************************************/
// Property Sheet stuff for the main page
#include "cplPreComp.h"
#include "cplCallingCardPS.h"
#include "cplSimpleDialogs.h"
#include <strsafe.h>
#define MaxCallingCardRuleItems 16
CCallingCardPropSheet::CCallingCardPropSheet(BOOL bNew, BOOL bShowPIN, CCallingCard * pCard, CCallingCards * pCards) { m_bNew = bNew; m_bShowPIN = bShowPIN; m_pCard = pCard; m_pCards = pCards; m_bWasApplied = FALSE;
PWSTR pwsz; pwsz = pCard->GetLongDistanceRule(); m_bHasLongDistance = (pwsz && *pwsz);
pwsz = pCard->GetInternationalRule(); m_bHasInternational = (pwsz && *pwsz);
pwsz = pCard->GetLocalRule(); m_bHasLocal = (pwsz && *pwsz); }
CCallingCardPropSheet::~CCallingCardPropSheet() { }
LONG CCallingCardPropSheet::DoPropSheet(HWND hwndParent) { CCPAGEDATA aPageData[] = { { this, 0 }, { this, 1 }, { this, 2 }, };
struct { int iDlgID; DLGPROC pfnDlgProc; LPARAM lParam; } aData[] = { { IDD_CARD_GENERAL, CCallingCardPropSheet::General_DialogProc, (LPARAM)this }, { IDD_CARD_LONGDISTANCE, CCallingCardPropSheet::DialogProc, (LPARAM)&aPageData[0] }, { IDD_CARD_INTERNATIONAL, CCallingCardPropSheet::DialogProc, (LPARAM)&aPageData[1] }, { IDD_CARD_LOCALCALLS, CCallingCardPropSheet::DialogProc, (LPARAM)&aPageData[2] }, };
PROPSHEETHEADER psh; PROPSHEETPAGE psp; HPROPSHEETPAGE hpsp[ARRAYSIZE(aData)];
// Initialize the header:
psh.dwSize = sizeof(psh); psh.dwFlags = PSH_DEFAULT; psh.hwndParent = hwndParent; psh.hInstance = GetUIInstance(); psh.hIcon = NULL; psh.pszCaption = MAKEINTRESOURCE(m_bNew?IDS_NEWCALLINGCARD:IDS_EDITCALLINGCARD); psh.nPages = ARRAYSIZE(aData); psh.nStartPage = 0; psh.pfnCallback = NULL; psh.phpage = hpsp;
// Now setup the Property Sheet Page
psp.dwSize = sizeof(psp); psp.dwFlags = PSP_DEFAULT; psp.hInstance = GetUIInstance();
for (int i=0; i<ARRAYSIZE(aData); i++) { psp.pszTemplate = MAKEINTRESOURCE(aData[i].iDlgID); psp.pfnDlgProc = aData[i].pfnDlgProc; psp.lParam = aData[i].lParam; hpsp[i] = CreatePropertySheetPage( &psp ); }
PropertySheet( &psh );
return m_bWasApplied?PSN_APPLY:PSN_RESET; }
// ********************************************************************
//
// GENERAL page
//
// ********************************************************************
INT_PTR CALLBACK CCallingCardPropSheet::General_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { CCallingCardPropSheet* pthis = (CCallingCardPropSheet*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch(uMsg) { case WM_INITDIALOG: pthis = (CCallingCardPropSheet*)(((PROPSHEETPAGE*)lParam)->lParam); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pthis); return pthis->General_OnInitDialog(hwndDlg);
case WM_COMMAND: pthis->General_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), (HWND)lParam ); return 1;
case WM_NOTIFY: return pthis->General_OnNotify(hwndDlg, (LPNMHDR)lParam); case WM_HELP: // Process clicks on controls after Context Help mode selected
WinHelp ((HWND)((LPHELPINFO)lParam)->hItemHandle, gszHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) a105HelpIDs); break; case WM_CONTEXTMENU: // Process right-clicks on controls
WinHelp ((HWND) wParam, gszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) a105HelpIDs); break; }
return 0; }
BOOL CCallingCardPropSheet::General_OnInitDialog(HWND hwndDlg) { // Set all the edit controls to the inital values
HWND hwnd; TCHAR szText[MAX_INPUT];
hwnd = GetDlgItem(hwndDlg,IDC_CARDNAME); SHUnicodeToTChar(m_pCard->GetCardName(), szText, ARRAYSIZE(szText)); SetWindowText(hwnd, szText); SendMessage(hwnd, EM_SETLIMITTEXT, CPL_SETTEXTLIMIT, 0);
hwnd = GetDlgItem(hwndDlg,IDC_CARDNUMBER); SHUnicodeToTChar(m_pCard->GetAccountNumber(), szText, ARRAYSIZE(szText)); SetWindowText(hwnd, szText); SendMessage(hwnd, EM_SETLIMITTEXT, CPL_SETTEXTLIMIT, 0); LimitInput(hwnd, LIF_ALLOWNUMBER|LIF_ALLOWSPACE);
hwnd = GetDlgItem(hwndDlg,IDC_PIN); if(m_bShowPIN) { SHUnicodeToTChar(m_pCard->GetPIN(), szText, ARRAYSIZE(szText)); SetWindowText(hwnd, szText); } SendMessage(hwnd, EM_SETLIMITTEXT, CPL_SETTEXTLIMIT, 0); LimitInput(hwnd, LIF_ALLOWNUMBER|LIF_ALLOWSPACE);
SetTextForRules(hwndDlg);
return 1; }
void CCallingCardPropSheet::SetTextForRules(HWND hwndDlg) { TCHAR szText[512]; int iDlgID = IDC_CARDUSAGE1; if ( m_bHasLongDistance ) { // load the "dialing long distance calls." string
LoadString(GetUIInstance(), IDS_DIALING_LD_CALLS, szText, ARRAYSIZE(szText)); SetWindowText(GetDlgItem(hwndDlg,iDlgID), szText); iDlgID++; } if ( m_bHasInternational ) { // load the "dialing international calls." string
LoadString(GetUIInstance(), IDS_DIALING_INT_CALLS, szText, ARRAYSIZE(szText)); SetWindowText(GetDlgItem(hwndDlg,iDlgID), szText); iDlgID++; } if ( m_bHasLocal ) { // load the "dialing local calls." string
LoadString(GetUIInstance(), IDS_DIALING_LOC_CALLS, szText, ARRAYSIZE(szText)); SetWindowText(GetDlgItem(hwndDlg,iDlgID), szText); iDlgID++; } if ( IDC_CARDUSAGE1 == iDlgID ) { // load the "there are no rules defined for this card" string
LoadString(GetUIInstance(),IDS_NOCCRULES,szText,ARRAYSIZE(szText)); SetWindowText(GetDlgItem(hwndDlg,iDlgID), szText); iDlgID++; } while (iDlgID <= IDC_CARDUSAGE3) { SetWindowText(GetDlgItem(hwndDlg,iDlgID), TEXT("")); iDlgID++; } }
BOOL CCallingCardPropSheet::General_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl) { switch ( wID ) { case IDC_CARDNAME: case IDC_CARDNUMBER: case IDC_PIN: switch (wNotifyCode) { case EN_CHANGE: SendMessage(GetParent(hwndParent),PSM_CHANGED,(WPARAM)hwndParent,0); break;
default: break; } break;
default: break; }
return 0; }
BOOL CCallingCardPropSheet::General_OnNotify(HWND hwndDlg, LPNMHDR pnmhdr) { // The only notifies we should receive are from the property sheet
switch (pnmhdr->code) { case PSN_APPLY: // user pressed OK or Apply
// update all the strings
HideToolTip(); return Gerneral_OnApply(hwndDlg);
case PSN_RESET: // user pressed Cancel
HideToolTip(); break;
case PSN_SETACTIVE: // user is switching pages
// the user might have added some rules since switching pages so we
// need to update the text fields that show which rules are set.
SetTextForRules(hwndDlg); HideToolTip(); break; } return 0; }
BOOL CCallingCardPropSheet::Gerneral_OnApply(HWND hwndDlg) { HWND hwnd; DWORD dwStatus; PWSTR pwszOldCardNumber; PWSTR pwszOldPinNumber; WCHAR wsz[MAX_INPUT]; TCHAR szText[MAX_INPUT];
LOG((TL_TRACE, "Gerneral_OnApply: -- enter"));
// In order for this to work, I have to first store the new rules into the
// m_pCard object. Each page that has been created must be asked to generate
// it's rule. We do this in response to the PSM_QUERYSIBLINGS command.
// Unfortunately, we have to first store a copy of all the data we're about to
// change. That way, if the validation fails we can return the CallingCard
// object to it's original value (so if the user then presses cancel it will
// be in the correct state).
// cache the current values for the rules and access numbers
pwszOldCardNumber = ClientAllocString(m_pCard->GetAccountNumber()); pwszOldPinNumber = ClientAllocString(m_pCard->GetPIN());
// now update the object with the value we are about to test.
hwnd = GetDlgItem(hwndDlg,IDC_CARDNUMBER); GetWindowText(hwnd, szText, ARRAYSIZE(szText)); SHTCharToUnicode(szText, wsz, ARRAYSIZE(wsz)); m_pCard->SetAccountNumber(wsz);
hwnd = GetDlgItem(hwndDlg,IDC_PIN); GetWindowText(hwnd, szText, ARRAYSIZE(szText)); SHTCharToUnicode(szText, wsz, ARRAYSIZE(wsz)); m_pCard->SetPIN(wsz);
// let the other pages update thier values
PropSheet_QuerySiblings(GetParent(hwndDlg),0,0);
// Now we can validate the card.
dwStatus = m_pCard->Validate(); if ( dwStatus ) { int iStrID; int iDlgItem; int iDlgID = 0;
// Set the current values for the rules and access numbers to our cached values.
// This is required in case the user later decides to cancel instead of appling.
m_pCard->SetAccountNumber(pwszOldCardNumber); m_pCard->SetPIN(pwszOldPinNumber); ClientFree( pwszOldCardNumber ); ClientFree( pwszOldPinNumber ); // Something isn't right, figure out what. The order we check these
// in depends on which tab the error would need to be fixed from.
// First we check the items that get fixed on the general tab.
if ( dwStatus & (CCVF_NOCARDNAME|CCVF_NOCARDNUMBER|CCVF_NOPINNUMBER) ) { if ( dwStatus & CCVF_NOCARDNAME ) { iStrID = IDS_MUSTENTERCARDNAME; iDlgItem = IDC_CARDNAME; } else if ( dwStatus & CCVF_NOCARDNUMBER ) { iStrID = IDS_MUSTENTERCARDNUMBER; iDlgItem = IDC_CARDNUMBER; } else { iStrID = IDS_MUSTENTERPINNUMBER; iDlgItem = IDC_PIN; }
iDlgID = IDD_CARD_GENERAL; } else if ( dwStatus & CCVF_NOCARDRULES ) { // For this problem we stay on whatever page we are already on
// since this problem can be fixed on one of three different pages.
iStrID = IDS_NORULESFORTHISCARD; } else if ( dwStatus & CCVF_NOLONGDISTANCEACCESSNUMBER ) { iStrID = IDS_NOLONGDISTANCEACCESSNUMBER; iDlgID = IDD_CARD_LONGDISTANCE; iDlgItem = IDC_LONGDISTANCENUMBER; } else if ( dwStatus & CCVF_NOINTERNATIONALACCESSNUMBER ) { iStrID = IDS_NOINTERNATIONALACCESSNUMBER; iDlgID = IDD_CARD_INTERNATIONAL; iDlgItem = IDC_INTERNATIONALNUMBER; } else if ( dwStatus & CCVF_NOLOCALACCESSNUMBER ) { iStrID = IDS_NOLOCALACCESSNUMBER; iDlgID = IDD_CARD_LOCALCALLS; iDlgItem = IDC_LOCALNUMBER; }
hwnd = GetParent(hwndDlg); if ( iDlgID ) { PropSheet_SetCurSelByID(hwnd,iDlgID); hwnd = PropSheet_GetCurrentPageHwnd(hwnd); hwnd = GetDlgItem(hwnd,iDlgItem); } else { hwnd = hwndDlg; } ShowErrorMessage(hwnd, iStrID); SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,PSNRET_INVALID_NOCHANGEPAGE); return TRUE; }
// Check for the calling card name being unique
TCHAR szNone[MAX_INPUT]; LoadString(GetUIInstance(),IDS_NONE, szNone, ARRAYSIZE(szNone));
hwnd = GetDlgItem(hwndDlg,IDC_CARDNAME); GetWindowText(hwnd, szText, ARRAYSIZE(szText)); if ( 0 == StrCmpIW(szText, szNone) ) { goto buggeroff; } SHTCharToUnicode(szText, wsz, ARRAYSIZE(wsz));
CCallingCard * pCard; m_pCards->Reset(TRUE); // TRUE means show "hidden" cards, FALSE means hide them
while ( S_OK == m_pCards->Next(1,&pCard,NULL) ) { // hidden cards shall remain hidden for ever so we don't check names against those
if ( !pCard->IsMarkedHidden() ) { // Card0 is the "None (Direct Dial)" card which we don't want to consider
if ( 0 != pCard->GetCardID() ) { // we don't want to consider ourself either
if ( pCard->GetCardID() != m_pCard->GetCardID() ) { // see if the names are identical
if ( 0 == StrCmpIW(pCard->GetCardName(), wsz) ) { // yes, the name is in conflict
buggeroff: // return altered values to original state
m_pCard->SetAccountNumber(pwszOldCardNumber); m_pCard->SetPIN(pwszOldPinNumber); ClientFree( pwszOldCardNumber ); ClientFree( pwszOldPinNumber );
// display an error message
hwnd = GetParent(hwndDlg); PropSheet_SetCurSelByID(hwnd,IDD_CARD_GENERAL); hwnd = PropSheet_GetCurrentPageHwnd(hwnd); hwnd = GetDlgItem(hwnd,IDC_CARDNAME); ShowErrorMessage(hwnd, IDS_NEEDUNIQUECARDNAME); SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,PSNRET_INVALID_NOCHANGEPAGE); return TRUE; } } } } }
// card name doesn't conflict, update it.
m_pCard->SetCardName(wsz);
m_bWasApplied = TRUE;
ClientFree( pwszOldCardNumber ); ClientFree( pwszOldPinNumber ); return 0; }
// ********************************************************************
//
// LONG DISTANCE, INTERNATIONAL, and LOCAL pages
//
// ********************************************************************
INT_PTR CALLBACK CCallingCardPropSheet::DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { CCPAGEDATA * pPageData = (CCPAGEDATA *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch(uMsg) { case WM_INITDIALOG: pPageData = (CCPAGEDATA*)(((PROPSHEETPAGE*)lParam)->lParam); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)pPageData); return pPageData->pthis->OnInitDialog(hwndDlg,pPageData->iWhichPage);
case WM_COMMAND: pPageData->pthis->OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), (HWND)lParam, pPageData->iWhichPage); return 1;
case WM_NOTIFY: return pPageData->pthis->OnNotify(hwndDlg, (LPNMHDR)lParam,pPageData->iWhichPage);
case PSM_QUERYSIBLINGS: return pPageData->pthis->UpdateRule(hwndDlg,pPageData->iWhichPage);
case WM_DESTROY: return pPageData->pthis->OnDestroy(hwndDlg);
#define aIDs ((pPageData->iWhichPage==0)?a106HelpIDs:((pPageData->iWhichPage==1)?a107HelpIDs:a108HelpIDs))
case WM_HELP: // Process clicks on controls after Context Help mode selected
WinHelp ((HWND)((LPHELPINFO)lParam)->hItemHandle, gszHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) aIDs); break; case WM_CONTEXTMENU: // Process right-clicks on controls
WinHelp ((HWND) wParam, gszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) aIDs); break; #undef aIDs
}
return 0; }
void GetDescriptionForRule(PWSTR pwszRule, PTSTR szText, UINT cchText) { switch (*pwszRule) { case L',': { // Check if all characters are commas. If they are not, fall through to the
// "dial the specified digits" case
if(HasOnlyCommasW(pwszRule)) { // add a "wait for x seconds" rule. Each consecutive ',' adds two seconds to x.
int iSecondsToWait = lstrlenW(pwszRule)*2; TCHAR szFormat[256]; LPTSTR aArgs[] = {(LPTSTR)UIntToPtr(iSecondsToWait)};
LoadString(GetUIInstance(),IDS_WAITFORXSECONDS, szFormat, ARRAYSIZE(szFormat));
FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY, szFormat, 0,0, szText, cchText, (va_list *)aArgs );
break; } }
// ATTENTION !!
// Fall through
case L'0': case L'1': case L'2': case L'3': case L'4': case L'5': case L'6': case L'7': case L'8': case L'9': case L'A': case L'a': case L'B': case L'b': case L'C': case L'c': case L'D': case L'd': case L'#': case L'*': case L'+': case L'!': { // Add a "dial the specified digits" rule. The whole sequence of these digits should
// be considered to be one rule.
TCHAR szRule[MAX_INPUT]; TCHAR szFormat[MAX_INPUT]; TCHAR szTemp[MAX_INPUT*2]; // big enough for the rule and the format
LPTSTR aArgs[] = {szRule};
SHUnicodeToTChar(pwszRule, szRule, ARRAYSIZE(szRule)); LoadString(GetUIInstance(),IDS_DIALX, szFormat, ARRAYSIZE(szFormat));
// The formated message might be larger than cchText, in which case we just
// want to truncate the result. FormatMessage would simply fail in that case
// so we format to a larger buffer and then truncate down.
if (FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY, szFormat, 0,0, szTemp, ARRAYSIZE(szTemp), (va_list *)aArgs )) { StrCpyN(szText, szTemp, cchText); } else { szText[0] = 0; } } break;
default: { int iStrID;
switch (*pwszRule) { case L'J': // add a "dial the access number" rule.
iStrID = IDS_DIALACCESSNUMBER; break;
case L'K': // add a "dial the account number" rule.
iStrID = IDS_DIALACOUNTNUMBER; break;
case L'H': // add a "dial the pin number" rule.
iStrID = IDS_DIALPINNUMBER; break;
case L'W': // add a "Wait for dial tone" rule.
iStrID = IDS_WAITFORDIALTONE; break;
case L'@': // add a "Wait for quiet" rule.
iStrID = IDS_WAITFORQUIET; break;
case L'E': case L'F': case L'G': // add a "dial the destination number" rule. We look for these three letters together.
// Only certain combinations of these letters are valid, as indicated below:
if ( 0 == StrCmpW(pwszRule, L"EFG") ) { iStrID = IDS_DIAL_CCpACpNUM; } else if ( 0 == StrCmpW(pwszRule, L"EG") ) { iStrID = IDS_DIAL_CCpNUM; } else if ( 0 == StrCmpW(pwszRule, L"FG") ) { iStrID = IDS_DIAL_ACpNUM; } else if ( 0 == StrCmpW(pwszRule, L"E") ) { iStrID = IDS_DIAL_CC; } else if ( 0 == StrCmpW(pwszRule, L"F") ) { iStrID = IDS_DIAL_AC; } else if ( 0 == StrCmpW(pwszRule, L"G") ) { iStrID = IDS_DIAL_NUM; } break;
default: // We shouldn't be able to get here"
LOG((TL_ERROR, "Invalid calling card rule")); szText[0] = NULL; return; }
LoadString(GetUIInstance(), iStrID, szText, cchText); } break; } }
void PopulateStepList(HWND hwndList, PWSTR pwszRuleList) { TCHAR szText[MAX_INPUT]; WCHAR wch; PWSTR pwsz;
int i = 0;
// Parse the string into a series of rules. There are only types of rules that we should see
// in a calling card sting:
// J dial the access number
// K dial the account number
// H dial the pin number
// 0-9,#,*,+,!,ABCD Dial the digits directly
// W Wait for dial tone
// @ Wait for quiet
// , Wait for two seconds
// E Dial the counrty code
// F Dial the area code
// G Dial the local number (prefix and root)
// We copy the characters for the given rule into a buffer. Then we allocate a heap
// buffer into which these characters get copied. Each list view item tracks one of
// these character buffers in it's lParam data.
LOG((TL_INFO, "Rule to process (%ls)",pwszRuleList)); while ( *pwszRuleList ) { switch (*pwszRuleList) { case L'J': // add a "dial the access number" rule.
case L'K': // add a "dial the account number" rule.
case L'H': // add a "dial the pin number" rule.
case L'W': // add a "Wait for dial tone" rule.
case L'@': // add a "Wait for quiet" rule.
// These are all the one character rules.
pwsz = pwszRuleList+1; LOG((TL_INFO, "JKHW@ case (%ls) <%p>",pwsz,pwsz)); break;
case L'E': case L'F': case L'G': // add a "dial the destination number" rule. We look for these three letters together.
// If we find a consecutive group of these digits then we treat them as one rule. Only
// a few combinations of these letters are actually valid rules. If we find some other
// combination then we must treat it as a seperate rule instead of a single rule. We
// start by looking for the longest valid rules and then check for the shorter ones.
if ( 0 == StrCmpNW(pwszRuleList, L"EFG", 3) ) { pwsz = pwszRuleList+3; } else if ( 0 == StrCmpNW(pwszRuleList, L"EG", 2) ) { pwsz = pwszRuleList+2; } else if ( 0 == StrCmpNW(pwszRuleList, L"FG", 2) ) { pwsz = pwszRuleList+2; } else { pwsz = pwszRuleList+1; } LOG((TL_INFO, "EFG case (%ls)",pwsz)); break;
case L',': // add a "wait for x seconds" rule. Each consecutive , adds two seconds to x.
pwsz = pwszRuleList+1; while ( *(pwsz) == L',' ) { pwsz++; } break;
case L'0': case L'1': case L'2': case L'3': case L'4': case L'5': case L'6': case L'7': case L'8': case L'9': case L'A': case L'a': case L'B': case L'b': case L'C': case L'c': case L'D': case L'd': case L'#': case L'*': case L'+': case L'!': // Add a "dial the specified digits" rule. The whole sequence of these digits should
// be considered to be one rule.
pwsz = pwszRuleList+1; while ( ((*pwsz >= L'0') && (*pwsz <= L'9')) || ((*pwsz >= L'A') && (*pwsz <= L'D')) || ((*pwsz >= L'a') && (*pwsz <= L'd')) || (*pwsz == L'#') || (*pwsz == L'*') || (*pwsz == L'+') || (*pwsz == L'!') ) { pwsz++; } LOG((TL_INFO, "0-9,A-D,#,*,+,! case (%ls)", pwsz)); break;
default: // We shouldn't be able to get here
LOG((TL_ERROR, "Invalid calling card rule"));
// we just ignore this character and go back to the while loop. Yes, this is a continue
// inside a switch inside a while loop. A bit confusing, perhaps, but it's what we want.
pwszRuleList++; continue; }
// we temporarily stick a NULL into wpszRuleList to seperate out one rule
wch = *pwsz; *pwsz = NULL;
// for each rule, add a list box entry
LVITEM lvi; lvi.mask = LVIF_TEXT|LVIF_PARAM; lvi.iItem = i++; lvi.iSubItem = 0; lvi.pszText = szText; lvi.lParam = (LPARAM)ClientAllocString(pwszRuleList); GetDescriptionForRule(pwszRuleList, szText, ARRAYSIZE(szText)); LOG((TL_INFO, "Description for (%ls) is (%s)", pwszRuleList,szText));
ListView_InsertItem(hwndList, &lvi);
// restore pwszRuleList to it's former state before continuing or this is going to be a real short ride.
pwsz[0] = wch;
// after the above restoration, pwsz points to the head of the next rule (or to a NULL)
pwszRuleList = pwsz; } }
BOOL CCallingCardPropSheet::OnInitDialog(HWND hwndDlg, int iPage) { LOG((TL_TRACE, "OnInitDialog <%d>",iPage));
PWSTR pwsz; RECT rc; HWND hwnd = GetDlgItem(hwndDlg, IDC_LIST);
GetClientRect(hwnd, &rc);
LVCOLUMN lvc; lvc.mask = LVCF_SUBITEM | LVCF_WIDTH; lvc.iSubItem = 0; lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL); ListView_InsertColumn( hwnd, 0, &lvc ); ListView_SetExtendedListViewStyleEx(hwnd, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT);
switch ( iPage ) { case 0: pwsz = m_pCard->GetLongDistanceRule(); break;
case 1: pwsz = m_pCard->GetInternationalRule(); break;
case 2: pwsz = m_pCard->GetLocalRule(); break;
default: LOG((TL_ERROR, "OnInitDialog: Invalid page ID %d, failing.", iPage)); return -1; } PopulateStepList(hwnd, pwsz);
int iDlgItem; switch (iPage) { case 0: iDlgItem = IDC_LONGDISTANCENUMBER; pwsz = m_pCard->GetLongDistanceAccessNumber(); break;
case 1: iDlgItem = IDC_INTERNATIONALNUMBER; pwsz = m_pCard->GetInternationalAccessNumber(); break;
case 2: iDlgItem = IDC_LOCALNUMBER; pwsz = m_pCard->GetLocalAccessNumber(); break; }
TCHAR szText[MAX_INPUT]; hwnd = GetDlgItem(hwndDlg,iDlgItem); SHUnicodeToTChar(pwsz, szText, ARRAYSIZE(szText)); SetWindowText(hwnd, szText); SendMessage(hwnd, EM_SETLIMITTEXT, CPL_SETTEXTLIMIT, 0); LimitInput(hwnd, LIF_ALLOWNUMBER|LIF_ALLOWSPACE);
// disable the buttons since no item is selected by default
SetButtonStates(hwndDlg,-1);
return 0; }
BOOL CCallingCardPropSheet::OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl, int iPage) { HWND hwndList = GetDlgItem(hwndParent, IDC_LIST);
switch ( wID ) { case IDC_LONGDISTANCENUMBER: case IDC_INTERNATIONALNUMBER: case IDC_LOCALNUMBER: if (EN_CHANGE == wNotifyCode) { SendMessage(GetParent(hwndParent),PSM_CHANGED,(WPARAM)hwndParent,0); } break;
case IDC_MOVEUP: case IDC_MOVEDOWN: case IDC_REMOVE: { TCHAR szText[MAX_INPUT]; int iSelected = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
if (-1 != iSelected) { LVITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = iSelected; lvi.iSubItem = 0; lvi.pszText = szText; lvi.cchTextMax = ARRAYSIZE(szText); ListView_GetItem(hwndList, &lvi);
ListView_DeleteItem(hwndList, iSelected);
if ( IDC_MOVEDOWN == wID ) { iSelected++; } else { iSelected--; }
if ( IDC_REMOVE == wID ) { ClientFree( (PWSTR)lvi.lParam ); if ( ListView_GetItemCount(hwndList) > 0 ) { if (-1 == iSelected) iSelected = 0;
ListView_SetItemState(hwndList, iSelected, LVIS_SELECTED, LVIS_SELECTED); } else { // the last rule was deleted, update the "has rule" state
switch (iPage) { case 0: m_bHasLongDistance = FALSE; break;
case 1: m_bHasInternational = FALSE; break;
case 2: m_bHasLocal = FALSE; break; } if ( GetFocus() == hwndCrl ) { HWND hwndDef = GetDlgItem(hwndParent,IDC_ACCESSNUMBER); SendMessage(hwndCrl, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE,0)); SendMessage(hwndDef, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE,0)); SetFocus(hwndDef); } EnableWindow(hwndCrl,FALSE); } } else { lvi.mask |= LVIF_STATE; lvi.iItem = iSelected; lvi.state = lvi.stateMask = LVIS_SELECTED; iSelected = ListView_InsertItem(hwndList, &lvi); }
ListView_EnsureVisible(hwndList, iSelected, FALSE); }
SendMessage(GetParent(hwndParent), PSM_CHANGED, (WPARAM)hwndParent, 0); } break;
case IDC_ACCESSNUMBER: case IDC_PIN: case IDC_CARDNUMBER: case IDC_DESTNUMBER: case IDC_WAITFOR: case IDC_SPECIFYDIGITS: { TCHAR szText[MAX_INPUT]; WCHAR wszRule[MAX_INPUT]; int iItem = ListView_GetItemCount(hwndList); LVITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = iItem; lvi.iSubItem = 0; lvi.pszText = szText;
switch ( wID ) { case IDC_ACCESSNUMBER: lvi.lParam = (LPARAM)ClientAllocString(L"J"); break;
case IDC_PIN: lvi.lParam = (LPARAM)ClientAllocString(L"H"); break;
case IDC_CARDNUMBER: lvi.lParam = (LPARAM)ClientAllocString(L"K"); break;
case IDC_DESTNUMBER: { CDestNumDialog dnd(iPage==1, iPage!=2); INT_PTR iRes = dnd.DoModal(hwndParent); if (iRes == (INT_PTR)IDOK) { lvi.lParam = (LPARAM)ClientAllocString(dnd.GetResult()); } else { return 0; } } break;
case IDC_WAITFOR: { CWaitForDialog wd; INT_PTR ipRes = wd.DoModal(hwndParent); if (ipRes == (INT_PTR)IDOK) { int iRes; iRes = wd.GetWaitType(); LOG((TL_INFO, "WaitType is %d", iRes)); switch (iRes) { case 0: lvi.lParam = (LPARAM)ClientAllocString(L"W"); break;
case 1: lvi.lParam = (LPARAM)ClientAllocString(L"@"); break;
default: iRes = iRes/2; if ( ARRAYSIZE(wszRule) <= iRes ) { iRes = ARRAYSIZE(wszRule)-1; }
for (int i=0; i<iRes; i++) { wszRule[i] = L','; } wszRule[i] = NULL; lvi.lParam = (LPARAM)ClientAllocString(wszRule); break; } } else { return 0; } } break;
case IDC_SPECIFYDIGITS: { CEditDialog ed; WCHAR *pwcSrc, *pwcDest; INT_PTR iRes = ed.DoModal(hwndParent, IDS_SPECIFYDIGITS, IDS_TYPEDIGITS, IDS_DIGITS, LIF_ALLOWNUMBER|LIF_ALLOWPOUND|LIF_ALLOWSTAR|LIF_ALLOWSPACE|LIF_ALLOWCOMMA|LIF_ALLOWPLUS|LIF_ALLOWBANG|LIF_ALLOWATOD); if (iRes == (INT_PTR)IDOK) { SHTCharToUnicode(ed.GetString(), wszRule, ARRAYSIZE(wszRule)); // Strip the spaces
pwcSrc = wszRule; pwcDest = wszRule; do { if(*pwcSrc != TEXT(' ')) // including the NULL
*pwcDest++ = *pwcSrc; } while(*pwcSrc++); if (!wszRule[0]) return 0;
lvi.lParam = (LPARAM)ClientAllocString(wszRule); } else { return 0; } } break; }
if (NULL != lvi.lParam) { GetDescriptionForRule((PWSTR)lvi.lParam, szText, ARRAYSIZE(szText));
iItem = ListView_InsertItem(hwndList, &lvi); ListView_EnsureVisible(hwndList, iItem, FALSE); }
// a new rule was added, update the "has rule" state
switch (iPage) { case 0: m_bHasLongDistance = TRUE; break;
case 1: m_bHasInternational = TRUE; break;
case 2: m_bHasLocal = TRUE; break; }
// update the property sheet state
SendMessage(GetParent(hwndParent), PSM_CHANGED, (WPARAM)hwndParent, 0); } break;
default: break; } return 0; }
void CCallingCardPropSheet::SetButtonStates(HWND hwndDlg, int iItem) { EnableWindow(GetDlgItem(hwndDlg,IDC_MOVEUP), iItem>0); EnableWindow(GetDlgItem(hwndDlg,IDC_MOVEDOWN), (-1!=iItem) && (ListView_GetItemCount(GetDlgItem(hwndDlg,IDC_LIST))-1)!=iItem); EnableWindow(GetDlgItem(hwndDlg,IDC_REMOVE), -1!=iItem); }
BOOL CCallingCardPropSheet::OnNotify(HWND hwndDlg, LPNMHDR pnmhdr, int iPage) { switch ( pnmhdr->idFrom ) { case IDC_LIST: #define pnmlv ((LPNMLISTVIEW)pnmhdr)
switch (pnmhdr->code) { case LVN_ITEMCHANGED: if (pnmlv->uChanged & LVIF_STATE) { if (pnmlv->uNewState & LVIS_SELECTED) { SetButtonStates(hwndDlg,pnmlv->iItem); } else { SetButtonStates(hwndDlg,-1); } } break;
default: break; } break; #undef pnmlv
default: switch (pnmhdr->code) { case PSN_APPLY: // user pressed OK or Apply
LOG((TL_INFO, "OnApply <%d>", iPage)); case PSN_RESET: // user pressed Cancel
case PSN_KILLACTIVE: // user is switching pages
HideToolTip(); break; } break; }
return 0; }
BOOL CCallingCardPropSheet::UpdateRule(HWND hwndDlg, int iPage) { LOG((TL_TRACE, "UpdateRule <%d>",iPage));
WCHAR wszRule[1024]; PWSTR pwsz = wszRule; HWND hwnd = GetDlgItem(hwndDlg,IDC_LIST);
// in case there are no rules, we need to NULL the string
wszRule[0] = L'\0';
// add up all the items in the list and set the correct string
int iItems = ListView_GetItemCount(hwnd); if (iItems > MaxCallingCardRuleItems) iItems = MaxCallingCardRuleItems;
LVITEM lvi; HRESULT hr = S_OK; lvi.mask = LVIF_PARAM; lvi.iSubItem = 0; for (int i=0; i<iItems && SUCCEEDED(hr); i++) { lvi.iItem = i; ListView_GetItem(hwnd, &lvi);
hr = StringCchCatExW(pwsz, 1024, (PWSTR)lvi.lParam, NULL, NULL, STRSAFE_NO_TRUNCATION);
LOG((TL_INFO, "UpdateRule\tRule %d: %ls %s", i, lvi.lParam, FAILED(hr)?"FAILED":"SUCCEEDED")); }
int iDlgItem;
switch(iPage) { case 0: m_pCard->SetLongDistanceRule(wszRule); iDlgItem = IDC_LONGDISTANCENUMBER; break;
case 1: m_pCard->SetInternationalRule(wszRule); iDlgItem = IDC_INTERNATIONALNUMBER; break;
case 2: m_pCard->SetLocalRule(wszRule); iDlgItem = IDC_LOCALNUMBER; break; }
TCHAR szText[MAX_INPUT]; hwnd = GetDlgItem(hwndDlg,iDlgItem); GetWindowText(hwnd, szText, ARRAYSIZE(szText)); SHTCharToUnicode(szText, wszRule, ARRAYSIZE(wszRule));
switch(iPage) { case 0: m_pCard->SetLongDistanceAccessNumber(wszRule); break;
case 1: m_pCard->SetInternationalAccessNumber(wszRule); break;
case 2: m_pCard->SetLocalAccessNumber(wszRule); break; }
return 0; }
BOOL CCallingCardPropSheet::OnDestroy(HWND hwndDlg) { HWND hwnd = GetDlgItem(hwndDlg,IDC_LIST); // Free the memory we allocated and track in the list view
int iItems = ListView_GetItemCount(hwnd); LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iSubItem = 0; for (int i=0; i<iItems; i++) { lvi.iItem = i; ListView_GetItem(hwnd, &lvi);
ClientFree((PWSTR)lvi.lParam); }
return TRUE; }
BOOL HasOnlyCommasW(PWSTR pwszStr) { while(*pwszStr) if(*pwszStr++ != L',') return FALSE;
return TRUE; }
|