/*++
Copyright 1996 - 1997 Microsoft Corporation
Module Name:
dialer.c
--*/
#include "dialer.h"
#include "string.h"
#include "stdlib.h"
#include "shellapi.h"
#defineISDIGIT(x)(((x) - '0') >= 0) && (((x) - '0') <= 9)
enum NumberTypes
{
LOCAL_NUMBER = 7,
EXTENDED_LOCAL_NUMBER,
LONG_DISTANCE_NUMBER = 10,
EXTENDED_LONG_DISTANCE_NUMBER
};
// structs
typedef struct tagLINEINFO
{
DWORD nAddr; // Number of avail. addresses on the line
BOOL fVoiceLine; // Is this a voice line?
DWORD dwAPIVersion; // API version which the line supports
HLINE hLine; // line handle returned by lineOpen
DWORD dwPermanentLineID; // Permanent line ID retreived from devcaps
char szLineName[MAXBUFSIZE]; // the line's name
} LINEINFO, *LPLINEINFO;
// Global variables
// window/instance variables
HWND ghWndMain;
HWND ghWndDialing = NULL;
HINSTANCE ghInst = 0;
// file name vars.
static TCHAR gszAppName[64];
static TCHAR gszINIfilename [] = "DIALER.INI";
static TCHAR gszHELPfilename [] = "DIALER.HLP";
static TCHAR gszDialerClassName[] = "DialerClass";
TCHAR const gszNULL[] = "";
// window item variables
HFONT ghFontBtn; // handle to 1, 2, ..., 0's font
HFONT ghFontBtnText; // handle to number button's text font
HFONT ghFontBtnStar; // handle to * and # button's font
HLINEAPP ghLineApp = NULL; // Dialer's usage handle (regist. w/TAPI)
HCALL ghCall = NULL; // call handle for Dialer's call
LPSTR gszCurrentNumber = NULL; // number of destination of current call
LPSTR gszCurrentName = NULL; // name of destination of current call
BOOL gfRegistered; // was lineRegisterRequestRecipient()
// successful?
//BOOL gfDropping = FALSE; // is Dialer currently dropping a call?
BOOL gfNeedToReinit = FALSE; // does Dialer need to re-initialize?
BOOL gfCallRequest = FALSE; // Does a Simple TAPI app want a call?
BOOL gfCurrentLineAvail = TRUE; // Simple TAPI requests are only carried
// out if the current chosen line is avail.
BOOLgfMakeCallReplyPending = FALSE;
LONG gMakeCallRequestID = 0; // request ID returned by async TAPI fns.
LONG gDropCallRequestID = 0; // request ID returned by async TAPI fns.
DWORD gnAvailDevices = 0; // # of line devices avail. to Dialer
LINEINFO gCurrentLineInfo;
DWORD * gnAddr;
// global to remember where the cursor is in the edit control
DWORD gdwStartSel;
DWORD gdwEndSel;
DWORD * gdwPLID; // current line's permanent line ID
DWORD giCurrentLine = (DWORD)-1; // the line selected by the user
DWORD giCurrentAddress = 0; // the address selected by the user
// + 1 so we can work 1-based rather than 0-based (for convenience only)
// global varibles to hold the names and address of the
TCHAR gszSDNumber[ NSPEEDDIALS + 1 ][ TAPIMAXDESTADDRESSSIZE ];
// Function declarations
// button related functions
VOID ButtonFontSetup(VOID);
VOID DrawButton(HDC hdc, RECT rcBtn, BOOL fHighlighted);
VOID DrawButtonText(HDC hdc, RECT rcBtn, BOOL fHighlighted, UINT IDD_Btn);
VOID DisableDialButtons(BOOL fDisable);
VOID FitTextToButton( HWND, INT, LPSTR );
// Callback functions
BOOL CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK DialingProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK AboutProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK ConnectUsingProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK LineInUseProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK SpeedDial1Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK SpeedDial2Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
VOID CALLBACK tapiCallback (
DWORD hDevice, DWORD dwMsg,
DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2,
DWORD dwParam3
);
// tapi related functions
VOID ManageAssistedTelephony(VOID);
VOID InitiateCall(LPCSTR szNumber, LPCSTR szName);
VOID DialerLineClose(VOID);
VOID DialerCleanup(VOID);
VOID CloseTAPI(VOID);
DWORD GetLineInfo(DWORD iLine, LPLINEINFO lpLineInfo);
VOID GetLineInfoFailed (
DWORD iLine, LPLINEDEVCAPS lpDevCaps,
LPLINEINFO lpLineInfo
);
LPSTR GetAddressName(DWORD iLine, DWORD iAddress);
BOOL MakeCanonicalNumber( LPCSTR szName, LPSTR szCanNumber );
// misc. helper functions
VOID ReadINI(VOID);
int errString(HWND hWnd, UINT errCode, UINT uFlags);
VOID AddToRedialList(LPCSTR szNumber);
BOOL InitializeLineBox(HWND hwndLineBox);
BOOL InitializeAddressBox(HWND hwndLineBox, HWND hwndAddressBox);
BOOL Is911 ( LPLINETRANSLATEOUTPUT lpTransOut );
VOID AmpersandCompensate( LPCSTR lpszSrc, LPSTR lpszDst );
VOID AmpersandDeCompensate( LPCSTR lpszSrc, LPSTR lpszDst );
// Dialer memory management functions
LPVOID DialerAlloc(size_t cbToAlloc);
LPVOID DialerFree(LPVOID lpMem);
// Function definitions
//***************************************************************************
//***************************************************************************
//***************************************************************************
DWORD InitializeTAPI (VOID)
{
INT cvLine;
DWORD iLine;
DWORD dwPreferredPLID, dwID = (DWORD) -1;
MSG msg;
LPLINEINFO lpLineInfo = NULL;// LINEINFO for each available line
DWORD errCode;
DWORD tc = GetTickCount();
DWORD dwReturn = ERR_NONE;
char szBuffer[MAXBUFSIZE];// to read in dwPreferredPLID as a string first
errCode = lineInitialize (
&ghLineApp,
ghInst,
(LINECALLBACK) tapiCallback,
gszAppName,
&gnAvailDevices
);
if ( errCode == LINEERR_REINIT )
{
// take away dialer functionality
EnableWindow( ghWndMain, FALSE );
DisableDialButtons(TRUE);
// keep trying until the user cancels
// or we stop getting LINEERR_REINIT
while ( ( errCode = lineInitialize (
&ghLineApp,
ghInst,
(LINECALLBACK)tapiCallback,
gszAppName,
&gnAvailDevices
) )
== LINEERR_REINIT )
{
// flush queue & yield
while ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
// bring up the box if 5 seconds have passed since
if(GetTickCount() > 5000 + tc)
{
if ( errString( ghWndMain, ikszWarningTapiReInit, MB_RETRYCANCEL )
== IDCANCEL )
{
break;
}
// reset the relative counter
tc = GetTickCount();
}
}
// give back dialer functionality
DisableDialButtons( FALSE );
EnableWindow( ghWndMain, TRUE );
}
if ( errCode )
{
dwReturn = errCode;
goto tapiinit_exit;
}
// retrieve preferred line info from INI file
GetPrivateProfileString (
"Preference",
"Preferred Line",
gszNULL,
szBuffer,
MAXBUFSIZE,
gszINIfilename
);
// if szBuffer is not empty.
if ( lstrcmp ( gszNULL, szBuffer ) )
{
dwPreferredPLID = (DWORD) atoi( szBuffer );
}
else
{
dwPreferredPLID = (DWORD) -1;
}
// -1 default - tells us if it ever gets set
giCurrentLine = (DWORD) -1;
// allocate buffer for storing LINEINFO for all of the available lines
// always allocate space for at least one line
if ( gnAvailDevices == 0 )
{
gnAddr = (DWORD *) DialerAlloc( sizeof( DWORD ) );
gdwPLID = (DWORD *) DialerAlloc( sizeof( DWORD ) );
lpLineInfo = (LPLINEINFO) DialerAlloc( sizeof( LINEINFO ) );
}
else
{
gnAddr = (DWORD *) DialerAlloc( sizeof( DWORD ) * (int)gnAvailDevices);
gdwPLID = (DWORD *) DialerAlloc( sizeof( DWORD ) * (int)gnAvailDevices);
lpLineInfo = (LPLINEINFO) DialerAlloc( sizeof( LINEINFO ) * (int)gnAvailDevices );
}
// if no space was set aside...
if ( lpLineInfo == NULL || gnAddr == NULL )
{
dwReturn = LINEERR_NOMEM;
goto tapiinit_exit;
}
// fill lpLineInfo[] and open each line
for ( iLine = 0, cvLine = 0; iLine < gnAvailDevices; ++iLine )
{
// skip remaining processing for this if it didn't open
if ( GetLineInfo( iLine, &lpLineInfo[iLine] ) != ERR_NONE )
continue;
gnAddr [ iLine ] = lpLineInfo[iLine].nAddr;
gdwPLID[ iLine ] = lpLineInfo[iLine].dwPermanentLineID;
if ( lpLineInfo[iLine].dwPermanentLineID == dwPreferredPLID )
giCurrentLine = iLine;
// note number of lines with Interactive voice caps.
// used to select a preferred line by default
if ( lpLineInfo [ iLine ].fVoiceLine )
{
cvLine++;
dwID = iLine;
}
}
// if we couldn't find the preferred line,
// try and assign one by default
// else bring up connect using dialog
if ( giCurrentLine == (DWORD)-1 )
{
// check if there is only one line
// that has interactive voice caps,
// make it default line
if ( cvLine == 1 )
{
giCurrentLine = dwID;
// if the preferred address read from the INI file
// was different i.e we are changing setting, inform
// the user
if ( dwPreferredPLID != -1 )
{
errString( ghWndMain, ERR_NEWDEFAULT, MB_ICONEXCLAMATION | MB_OK );
}
}
else
{
gCurrentLineInfo = lpLineInfo[0];
if ( DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_CONNECTUSING),
ghWndMain,
(DLGPROC)ConnectUsingProc,
INVALID_LINE
)
== -1)
{
dwReturn = (DWORD) -1;
}
else
{
dwReturn = ERR_NONE;
}
goto tapiinit_exit;
}
}
gCurrentLineInfo = lpLineInfo[ giCurrentLine ];
// select default address
giCurrentAddress = 0;
// get the name of the preferred address from ini file
GetPrivateProfileString (
"Preference",
"Preferred Address",
gszNULL,
szBuffer,
MAXBUFSIZE,
gszINIfilename
);
// if preferred address read from INI file
if ( lstrcmp( gszNULL, szBuffer ) )
{
giCurrentAddress = (DWORD) atoi( szBuffer );
// if the address is invalid, set default
if ( giCurrentAddress >= gCurrentLineInfo.nAddr )
giCurrentAddress = 0;
}
tapiinit_exit:
if (lpLineInfo)
{
DialerFree(lpLineInfo);
}
return dwReturn;;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
int WINAPI WinMain (
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
HACCEL hAccel;
MSG msg;
DWORD errCode;
HANDLE hImHere;
ghInst = GetModuleHandle( NULL );
LoadString( ghInst, ikszAppFriendlyName, gszAppName, sizeof(gszAppName)/sizeof(TCHAR) );
//
// Now, let's see if we've already got an instance of ourself
hImHere = CreateMutex(NULL, TRUE, "DialersIveBeenStartedMutex");
//
// Is there another one of us already here?
if ( ERROR_ALREADY_EXISTS == GetLastError() )
{
HWND hDialerWnd;
hDialerWnd = FindWindow(gszDialerClassName,
NULL);
SetForegroundWindow(hDialerWnd);
CloseHandle( hImHere );
return 0;
}
{
WNDCLASS wc;
wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
wc.lpfnWndProc = DefDlgProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.hInstance = ghInst;
wc.hIcon = LoadIcon(ghInst, MAKEINTRESOURCE(IDI_DIALER) );
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = gszDialerClassName;
RegisterClass(&wc);
}
// create the dialog box and set it with info
// from the .INI file
ghWndMain = CreateDialog (
ghInst,
(LPCSTR)MAKEINTRESOURCE(IDD_DIALER),
(HWND)NULL,
MainWndProc
);
ReadINI();
ButtonFontSetup();
ShowWindow(ghWndMain, SW_SHOW);
UpdateWindow(ghWndMain);
// limit text in Number field to TAPIMAXDESTADDRESSSIZE
SendDlgItemMessage (
ghWndMain,
IDD_DCOMBO,
CB_LIMITTEXT,
(WPARAM)TAPIMAXDESTADDRESSSIZE,
0
);
// 0 (ERR_NONE) error code registers success - otherwise terminate
errCode = InitializeTAPI();
if(errCode)
{
errString(ghWndMain, errCode, MB_APPLMODAL | MB_ICONEXCLAMATION );
DialerCleanup();
return errCode;
}
errCode = lineRegisterRequestRecipient (
ghLineApp,
0, // registration instance
LINEREQUESTMODE_MAKECALL,
TRUE
);
if(errCode)
{
gfRegistered = FALSE;
errString(ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK );
}
else
{
gfRegistered = TRUE;
}
hAccel = LoadAccelerators(ghInst, gszAppName);
while ( GetMessage( &msg, NULL, 0, 0 ) )
{
if ( ghWndMain == NULL || !IsDialogMessage( ghWndMain, &msg ) )
{
if(!TranslateAccelerator(ghWndMain, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// If: 1) Dialer is a call manager (if not, ignore requests)
// 2) the currently chosen line is available
// 3) there is a Simple TAPI request
// Then: process the request
if ( gfCurrentLineAvail && gfCallRequest )
{
ManageAssistedTelephony();
}
}
DialerCleanup();
CloseHandle( hImHere );
return msg.wParam;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
LPVOID DialerAlloc(size_t cbToAlloc)
{
return LocalAlloc(LPTR, cbToAlloc);
}
LPVOID DialerFree(LPVOID lpMem)
{
return LocalFree( lpMem );
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID ReadINI( VOID )
{
WORD cSDEntry, cLastDialed;
DWORD cComma;
POINT ptLeftTop;
char szName[ TAPIMAXCALLEDPARTYSIZE ];
char szTemp[ TAPIMAXCALLEDPARTYSIZE ];
char szNum[MAXBUFSIZE];
char szFieldName[MAXBUFSIZE];
char szPt[MAXBUFSIZE];
// get speed dial settings from INI file
for(cSDEntry = 1; cSDEntry <= NSPEEDDIALS; ++cSDEntry)
{
wsprintf(szFieldName, "Name%d", cSDEntry);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
szName,
TAPIMAXCALLEDPARTYSIZE - 1,
gszINIfilename
);
wsprintf(szFieldName, "Number%d", cSDEntry);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
gszSDNumber[cSDEntry],
TAPIMAXDESTADDRESSSIZE - 1,
gszINIfilename
);
if ( !lstrcmp( gszNULL, szName ) )
{
lstrcpy( szName, gszSDNumber[ cSDEntry ] );
}
FitTextToButton( ghWndMain, IDD_DSPEEDDIAL1 + cSDEntry - 1, szName );
AmpersandCompensate( szName, szTemp );
SetDlgItemText (
ghWndMain,
IDD_DSPEEDDIAL1 + cSDEntry - 1,
(LPCSTR)szTemp
); // Label the speed dial button
}
// set up last dialed numbers in combo box (read from INI)
for(cLastDialed = 1; cLastDialed <= NLASTDIALED; ++cLastDialed)
{
wsprintf(szFieldName, "Last dialed %d", cLastDialed);
GetPrivateProfileString (
"Last dialed numbers",
szFieldName,
gszNULL,
szNum,
MAXBUFSIZE - 1,
gszINIfilename
);
if ( szNum[0] ) // i.e. if szNum isn't simply "" - if we read something
// from the INI - put it in the combo box
SendDlgItemMessage(
ghWndMain,
IDD_DCOMBO,
CB_ADDSTRING,
0,
(LPARAM)(LPCSTR)szNum
);
}
// set defaults
ptLeftTop.x = 100;
ptLeftTop.y = 100;
// set the window position based on the INI data
GetPrivateProfileString (
"Preference",
"Main Window Left/Top",
gszNULL,
szPt,
MAXBUFSIZE - 1,
gszINIfilename
);
if ( szPt[0] )
{
cComma = strcspn(szPt, ",");
szPt[cComma] = 0;
ptLeftTop.x = atoi(szPt);
// a possibly absurd check to see that the string
// wasn't akin to "320," with no second entry
if ( *(szPt + cComma + 1 ) )
ptLeftTop.y = atoi( szPt + cComma + 1 );
// check to see that the box is on the screen - the upper left
// must be on the screen, along with a 50x50 box below and to
// the right of it
if ( ptLeftTop.x < 0
|| ptLeftTop.x + 50 >= GetSystemMetrics(SM_CXSCREEN)
|| ptLeftTop.y < 0
|| ptLeftTop.y + 50 >= GetSystemMetrics(SM_CYSCREEN)
)
{
ptLeftTop.x = 100; // set defaults if the box is off of the screen
ptLeftTop.y = 100; // set defaults if the box is off of the screen
}
}
SetWindowPos (
ghWndMain,
NULL,
ptLeftTop.x,
ptLeftTop.y,
0,
0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOZORDER
);
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID ButtonFontSetup(VOID)
{
HDC hdc;
int IDD;
// define the fonts for the buttons
hdc = GetDC(GetDesktopWindow());
ghFontBtn = CreateFont(
(-10)*GetDeviceCaps(hdc, LOGPIXELSY)/72,
0,
0,
0,
FW_BOLD,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,
VARIABLE_PITCH | FF_SWISS,
(LPSTR)"Arial"
);
ghFontBtnText = CreateFont(
(-6)*GetDeviceCaps(hdc, LOGPIXELSY)/72,
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,
VARIABLE_PITCH | FF_SWISS,
NULL
);
ghFontBtnStar = CreateFont(
(-18)*GetDeviceCaps(hdc, LOGPIXELSY)/72,
0,
0,
0,
FW_BOLD,
FALSE,
FALSE,
FALSE,
SYMBOL_CHARSET,
OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,
VARIABLE_PITCH | FF_DONTCARE,
(LPSTR)"Symbol"
);
ReleaseDC(GetDesktopWindow(), hdc);
// set the fonts for the buttons
if(ghFontBtn)
{
// set fonts on number buttons
for(IDD = IDD_DBUTTON1; IDD <= IDD_DBUTTON0; ++IDD)
// the order is IDD_DBUTTON1, 2, 3, ..., 0 (thus from 1 to 0)
SendMessage(
GetDlgItem(ghWndMain, IDD),
WM_SETFONT,
(WPARAM)ghFontBtn,
0L
);
// set fonts on * and # buttons
SendMessage(
GetDlgItem(ghWndMain, IDD_DBUTTONSTAR),
WM_SETFONT,
(WPARAM)ghFontBtnStar,
0L
);
SendMessage(
GetDlgItem(ghWndMain, IDD_DBUTTONPOUND),
WM_SETFONT,
(WPARAM)ghFontBtnStar,
0L
);
}
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
// Draws a 3D button within rcBtn on hDC
VOID DrawButton(HDC hDC, RECT rcBtn, BOOL fHighlighted)
{
HPEN hPenPrev, hPenShadow, hPenHighlight, hPenBlack;
HBRUSH hBrushPrev, hBrushFace;
int RopPrev;
--rcBtn.right;
--rcBtn.bottom;
// set up pens/brush
hPenShadow = CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DSHADOW));
hPenHighlight = CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DHILIGHT));
hPenBlack = GetStockObject(BLACK_PEN);
hBrushFace = GetSysColorBrush(COLOR_3DFACE);
// get current state so we can put it back at the end of DrawButton
hPenPrev = SelectObject(hDC, hPenBlack);
RopPrev = SetROP2(hDC, R2_COPYPEN);
hBrushPrev = SelectObject(hDC, hBrushFace);
PatBlt(
hDC,
rcBtn.left + 1,
rcBtn.top + 1,
rcBtn.right - rcBtn.left - 1,
rcBtn.bottom - rcBtn.top - 1,
PATCOPY
);
if(fHighlighted)
{
SelectObject(hDC, hPenBlack);
MoveToEx(hDC, rcBtn.left, rcBtn.bottom - 1, NULL);
LineTo(hDC, rcBtn.left, rcBtn.top); // _
LineTo(hDC, rcBtn.right, rcBtn.top); // |
SelectObject(hDC, hPenHighlight);
MoveToEx(hDC, rcBtn.right, rcBtn.top, NULL);
LineTo(hDC, rcBtn.right, rcBtn.bottom);
LineTo(hDC, rcBtn.left - 1, rcBtn.bottom); // _|
SelectObject(hDC, hPenShadow);
MoveToEx(hDC, rcBtn.left + 1, rcBtn.bottom - 2, NULL);
LineTo(hDC, rcBtn.left + 1, rcBtn.top + 1);
LineTo(hDC, rcBtn.right - 1, rcBtn.top + 1);
}
else
{
SelectObject(hDC, hPenHighlight);
MoveToEx(hDC, rcBtn.left, rcBtn.bottom - 1, NULL);
LineTo(hDC, rcBtn.left, rcBtn.top); // _
LineTo(hDC, rcBtn.right, rcBtn.top); // |
SelectObject(hDC, hPenBlack);
MoveToEx(hDC, rcBtn.right, rcBtn.top, NULL);
LineTo(hDC, rcBtn.right, rcBtn.bottom);
LineTo(hDC, rcBtn.left - 1, rcBtn.bottom); // _|
SelectObject(hDC, hPenShadow);
MoveToEx(hDC, rcBtn.left + 1, rcBtn.bottom - 1, NULL);
LineTo(hDC, rcBtn.right - 1, rcBtn.bottom - 1);
LineTo(hDC, rcBtn.right - 1, rcBtn.top);
}
// put everything back how it was
SetROP2(hDC, RopPrev);
SelectObject(hDC, hBrushPrev);
SelectObject(hDC, hPenPrev);
DeleteObject(hPenBlack);
DeleteObject(hPenShadow);
DeleteObject(hPenHighlight);
DeleteObject(hBrushFace);
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID DrawButtonText(HDC hDC, RECT rcBtn, BOOL fHighlighted, UINT IDD_Btn)
{
char szLine1[MAXBUFSIZE]; // text in button up to '\n'
LPSTR pszLine2; // text in button after '\n'
int BkModePrev;
HFONT hFontPrev = NULL;
TEXTMETRIC tm;
RECT rcText = rcBtn;
BkModePrev = SetBkMode(hDC, TRANSPARENT);
GetDlgItemText(ghWndMain, IDD_Btn, szLine1, MAXBUFSIZE);
pszLine2 = strstr(szLine1, "\n");
if(pszLine2)
{
*pszLine2 = 0; // 1 -> "TEST1 \n TEST2" becomes "TEST 1 \0"
++pszLine2; // now 2 -> " TEST 2"
}
// now szLine1 points to the null terminated first string and
// pszLine2 points to either the null terminated second string or NULL
// if there was no second string
if(szLine1[0])
{
if(ghFontBtnText && pszLine2)
hFontPrev = SelectObject(hDC, ghFontBtnText);
GetTextMetrics(hDC, &tm);
rcText.bottom = (rcBtn.bottom + rcBtn.top)/2 - 2;
rcText.top = rcText.bottom - (tm.tmHeight - 1);
if(pszLine2 == NULL)
OffsetRect(&rcText, 0, (rcText.bottom - rcText.top)/2);
if(fHighlighted)
OffsetRect(&rcText, 1, 1);
DrawText(hDC, szLine1, -1, &rcText, DT_SINGLELINE | DT_CENTER);
if(hFontPrev)
SelectObject(hDC, hFontPrev);
}
if(pszLine2) // recall that pszLine2 == NULL to represent no second string
{
GetTextMetrics(hDC, &tm);
if(IDD_Btn == IDD_DBUTTONSTAR || IDD_Btn == IDD_DBUTTONPOUND)
rcText.top = (rcBtn.bottom + rcBtn.top)/2 - (tm.tmHeight)/2;
else
rcText.top = (rcBtn.bottom + rcBtn.top)/2 - 2;
rcText.bottom = rcText.top + tm.tmHeight;
if(fHighlighted)
OffsetRect(&rcText, 1, 1);
DrawText(hDC, pszLine2, -1, &rcText, DT_SINGLELINE | DT_CENTER);
}
SetBkMode(hDC, BkModePrev);
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID DisableDialButtons(BOOL fDisable)
{
int IDD;
// Disable/enable Dial button
EnableWindow( GetDlgItem( ghWndMain, IDD_DDIAL ),!fDisable) ;
// Disable/enable Speed dial buttons
for ( IDD = IDD_DSPEEDDIAL1; IDD <= IDD_DSPEEDDIAL8; ++IDD )
{
EnableWindow(GetDlgItem(ghWndMain, IDD),!fDisable);
}
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID DialerCleanup(VOID)
{
RECT rc;
WORD cItem; // count of numbers in combo box
DWORD cLastDialed;
char szPt[MAXBUFSIZE];
char szNumber[TAPIMAXDESTADDRESSSIZE];
char szFieldName[MAXBUFSIZE];
CloseTAPI(); // unregister and line close
if(!IsIconic(ghWndMain)) // if the window is not minimized, record position
{
GetWindowRect(ghWndMain, &rc);
wsprintf(szPt, "%ld, %ld", rc.left, rc.top);
WritePrivateProfileString(
"Preference",
"Main Window Left/Top",
szPt,
gszINIfilename
);
}
cItem = (WORD)SendDlgItemMessage(ghWndMain, IDD_DCOMBO, CB_GETCOUNT, 0, 0);
// write out last dialed numbers from combo box (write to INI)
for(cLastDialed = 1; cLastDialed <= NLASTDIALED; ++cLastDialed)
{
if(cLastDialed <= cItem)
SendDlgItemMessage(
ghWndMain,
IDD_DCOMBO,
CB_GETLBTEXT,
cLastDialed - 1, // it's a zero-based count
(LPARAM)(LPCSTR)szNumber);
else
szNumber[0] = 0;
wsprintf(szFieldName, "Last dialed %d", cLastDialed);
WritePrivateProfileString(
"Last dialed numbers",
szFieldName,
szNumber,
gszINIfilename
);
}
WinHelp(ghWndMain, gszHELPfilename, HELP_QUIT, 0); // unload help
DestroyWindow(ghWndMain);
ghWndMain = NULL;
DeleteObject(ghFontBtn);
DeleteObject(ghFontBtnText);
DeleteObject(ghFontBtnStar);
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
// unregister and line close
VOID CloseTAPI(VOID)
{
// unregister as call manager
lineRegisterRequestRecipient (
ghLineApp,
0, // registration instance
LINEREQUESTMODE_MAKECALL,
FALSE
);
if ( gCurrentLineInfo.hLine )
{
lineClose ( gCurrentLineInfo.hLine );
gfCurrentLineAvail = FALSE;
gCurrentLineInfo.hLine = NULL;
}
lineShutdown(ghLineApp);
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HICON hIcon;
static const DWORD aMenuHelpIDs[] =
{
IDD_DSPEEDDIALGRP, (DWORD)-1,
IDD_DNUMTODIAL, IDH_DIALER_DIAL_NUMBER,
IDD_DCOMBO, IDH_DIALER_DIAL_NUMBER,
IDD_DDIAL, IDH_DIALER_DIAL_BUTTON,
IDD_DSPEEDDIAL1, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIAL2, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIAL3, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIAL4, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIAL5, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIAL6, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIAL7, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIAL8, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIALTEXT1, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIALTEXT2, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIALTEXT3, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIALTEXT4, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIALTEXT5, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIALTEXT6, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIALTEXT7, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DSPEEDDIALTEXT8, IDH_DIALER_DIAL_SPEED_CHOOSE,
IDD_DBUTTON1, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON2, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON3, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON4, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON5, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON6, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON7, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON8, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON9, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTONSTAR, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTON0, IDH_DIALER_DIAL_KEYPAD,
IDD_DBUTTONPOUND, IDH_DIALER_DIAL_KEYPAD,
0, 0
};
switch (msg)
{
case WM_INITDIALOG:
hIcon = LoadIcon( ghInst, (LPCSTR) MAKEINTRESOURCE( IDI_DIALER ) );
return TRUE;
case WM_SYSCOMMAND:
switch( (DWORD) wParam )
{
case SC_CLOSE:
PostQuitMessage(0);
}
break;
// processes clicks on controls when
// context mode help is selected
case WM_HELP:
WinHelp (
( (LPHELPINFO) lParam)->hItemHandle,
gszHELPfilename,
HELP_WM_HELP,
(DWORD)(LPVOID) aMenuHelpIDs
);
return TRUE;
// processes right-clicks on controls
case WM_CONTEXTMENU:
WinHelp (
(HWND)wParam,
gszHELPfilename,
HELP_CONTEXTMENU,
(DWORD)(LPVOID)aMenuHelpIDs
);
return TRUE;
case WM_INITMENUPOPUP:
// if edit menu
if ( LOWORD(lParam) == 1 )
{
UINT wEnable;
if ( GetParent( GetFocus() ) != GetDlgItem( ghWndMain, IDD_DCOMBO ) )
{
wEnable = MF_GRAYED;
}
else
{
LONG lSelect = SendDlgItemMessage (
ghWndMain,
IDD_DCOMBO,
CB_GETEDITSEL,
0,
0
);
if ( HIWORD( lSelect ) != LOWORD( lSelect ) )
wEnable = MF_ENABLED;
else
wEnable = MF_GRAYED;
}
EnableMenuItem((HMENU)wParam, IDM_EDIT_CUT, wEnable);
EnableMenuItem((HMENU)wParam, IDM_EDIT_COPY, wEnable);
EnableMenuItem((HMENU)wParam, IDM_EDIT_DELETE, wEnable);
// enable paste option is there is data
// in the clipboard
if ( IsClipboardFormatAvailable( CF_TEXT ) )
{
if ( GetClipboardData ( CF_TEXT ) )
{
wEnable = MF_ENABLED;
}
else
{
wEnable = MF_GRAYED;
}
}
else
{
wEnable = MF_GRAYED;
}
}
break;
case WM_COMMAND:
{
char szName[TAPIMAXCALLEDPARTYSIZE] = {'\0'};
char szNumber[TAPIMAXDESTADDRESSSIZE] = {'\0'};
switch( LOWORD( (DWORD)wParam ) )
{
// FILE menu
case IDM_EXIT:
PostQuitMessage(0);
return TRUE;
// EDIT menu
case IDM_EDIT_CUT:
SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_CUT, 0, 0);
return TRUE;
case IDM_EDIT_COPY:
SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_COPY, 0, 0);
return TRUE;
case IDM_EDIT_PASTE:
SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_PASTE, 0, 0);
return TRUE;
case IDM_EDIT_DELETE:
SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_CLEAR, 0, 0);
return TRUE;
case IDM_EDIT_SPEEDDIAL:
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_SD1),
ghWndMain,
(DLGPROC)SpeedDial1Proc,
0
);
SetFocus(GetDlgItem(ghWndMain, IDD_DDIAL));
return TRUE;
// TOOLS menu
case IDM_CONNECTUSING:
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_CONNECTUSING),
ghWndMain,
(DLGPROC)ConnectUsingProc,
MENU_CHOICE
);
return TRUE;
case IDM_LOCATION:
{
char szCanNumber[ TAPIMAXDESTADDRESSSIZE ] = "";
// fetch the number to be dialed
if ( GetDlgItemText (
ghWndMain,
IDD_DCOMBO,
szNumber,
TAPIMAXDESTADDRESSSIZE
)
)
{
// if a number exists, convert it to
// its canonical form.
if ( !MakeCanonicalNumber ( szNumber, szCanNumber ) )
{
lstrcpy( szCanNumber, szNumber );
}
}
lineTranslateDialog (
ghLineApp,
0,
TAPI_CURRENT_VERSION,
ghWndMain,
szCanNumber
);
return TRUE;
}
// HELP menu
case IDM_HELP_CONTENTS:
WinHelp(ghWndMain, gszHELPfilename, HELP_CONTENTS, 0);
return TRUE;
case IDM_HELP_WHATSTHIS:
PostMessage(ghWndMain, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
return TRUE;
case IDM_ABOUT:
DialogBoxParam(
ghInst,
MAKEINTRESOURCE(IDD_ABOUT),
ghWndMain,
(DLGPROC)AboutProc,
0
);
return TRUE;
// Accelerator processing
case IDM_ACCEL_NUMTODIAL:
if(GetActiveWindow() == ghWndMain)
SetFocus(GetDlgItem(ghWndMain, IDD_DCOMBO));
return TRUE;
// Buttons
case IDD_DDIAL:
{
DWORD cSDEntry;
char szSDNumber[TAPIMAXDESTADDRESSSIZE];
char szFieldName[MAXBUFSIZE];
// check if number entered is dialable
if ( SendMessage (
GetDlgItem(ghWndMain, IDD_DCOMBO),
WM_GETTEXTLENGTH,
0,
0
) > 0
)
{
// get the number to be dialed
GetDlgItemText (
ghWndMain,
IDD_DCOMBO,
(LPSTR)szNumber,
TAPIMAXDESTADDRESSSIZE
);
// check if it is a speed dial number.
// If so choose the name to be displayed.
for( cSDEntry = 1; cSDEntry <= NSPEEDDIALS; ++cSDEntry)
{
wsprintf(szFieldName, "Number%d", cSDEntry);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
szSDNumber,
TAPIMAXCALLEDPARTYSIZE - 1,
gszINIfilename
);
// if the number matches, get the name
if ( lstrcmp(szSDNumber, szNumber) == 0 )
{
wsprintf( szFieldName, "Name%d", cSDEntry);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
szName,
TAPIMAXCALLEDPARTYSIZE - 1,
gszINIfilename
);
break;
}
}
SetFocus( GetDlgItem( ghWndMain, IDD_DDIAL ) );
// once the currentline has been set
// using the connect proc
// the user must hit dial again
if ( giCurrentLine == (DWORD)-1 )
{
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_CONNECTUSING),
ghWndMain,
(DLGPROC)ConnectUsingProc,
INVALID_LINE
);
}
else
{
AddToRedialList(szNumber);
InitiateCall(szNumber, szName);
}
}
return TRUE;
}
case IDD_DBUTTON1:
case IDD_DBUTTON2:
case IDD_DBUTTON3:
case IDD_DBUTTON4:
case IDD_DBUTTON5:
case IDD_DBUTTON6:
case IDD_DBUTTON7:
case IDD_DBUTTON8:
case IDD_DBUTTON9:
case IDD_DBUTTON0:
case IDD_DBUTTONSTAR:
case IDD_DBUTTONPOUND:
{
int i;
TCHAR szBuffer[TAPIMAXDESTADDRESSSIZE+1];
static const char digits[] = { '1', '2', '3', '4',
'5', '6', '7', '8',
'9', '0', '*', '#' };
i = SendDlgItemMessage(ghWndMain,
IDD_DCOMBO,
WM_GETTEXT,
(WPARAM)TAPIMAXDESTADDRESSSIZE+1,
(LPARAM)szBuffer);
if (i < TAPIMAXDESTADDRESSSIZE)
{
MoveMemory(szBuffer+gdwStartSel+1,
szBuffer+gdwEndSel,
i - ( gdwEndSel ) + 1 );
szBuffer[gdwStartSel] = digits[LOWORD(wParam) - IDD_DBUTTON1];
SendDlgItemMessage(ghWndMain,
IDD_DCOMBO,
WM_SETTEXT,
0,
(LPARAM)szBuffer);
gdwStartSel++;
gdwEndSel = gdwStartSel;
}
SetFocus(GetDlgItem(ghWndMain, IDD_DDIAL));
EnableWindow(GetDlgItem(ghWndMain, IDD_DDIAL), TRUE);
return TRUE;
}
case IDD_DCOMBO:
if (HIWORD(wParam) == CBN_SELENDOK)
{
EnableWindow( GetDlgItem(ghWndMain, IDD_DDIAL), TRUE );
}
if ((HIWORD(wParam) == CBN_SELENDOK) ||
(HIWORD(wParam) == CBN_SELENDCANCEL))
{
(DWORD)SendDlgItemMessage(ghWndMain,
IDD_DCOMBO,
CB_GETEDITSEL,
(WPARAM)&gdwStartSel,
(LPARAM)&gdwEndSel);
return FALSE;
}
if ( HIWORD( wParam ) == CBN_EDITCHANGE )
{
EnableWindow (
GetDlgItem( ghWndMain, IDD_DDIAL ),
(BOOL) GetWindowTextLength (
GetDlgItem (
ghWndMain,
IDD_DCOMBO
)
)
);
return TRUE;
}
break;
case IDD_DSPEEDDIAL1:
case IDD_DSPEEDDIAL2:
case IDD_DSPEEDDIAL3:
case IDD_DSPEEDDIAL4:
case IDD_DSPEEDDIAL5:
case IDD_DSPEEDDIAL6:
case IDD_DSPEEDDIAL7:
case IDD_DSPEEDDIAL8:
{
DWORD cSDEntry = LOWORD( (DWORD) wParam) - IDD_DSPEEDDIAL1 + 1;
char szFieldName [MAXBUFSIZE];
// get information for the speed dial button
// from the INI file
wsprintf(szFieldName, "Name%d", cSDEntry);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
szName,
TAPIMAXCALLEDPARTYSIZE - 1,
gszINIfilename
);
wsprintf(szFieldName, "%s%d", "Number", cSDEntry);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
gszSDNumber[cSDEntry],
TAPIMAXDESTADDRESSSIZE - 1,
gszINIfilename
);
// entry not set yet
if( gszSDNumber[cSDEntry][0] == 0 )
{
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_SD2),
ghWndMain,
(DLGPROC)SpeedDial2Proc,
MAKELPARAM(wParam,0)
);
}
// no line open
// once the currentline has been set
// using the connect proc
// the user must hit dial again
else if ( giCurrentLine == (DWORD)-1)
{
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_CONNECTUSING),
ghWndMain,
(DLGPROC)ConnectUsingProc,
INVALID_LINE
);
}
// entry is set and valid voice line is open
else
{
// add number to list box combo.
AddToRedialList( gszSDNumber[cSDEntry] );
InitiateCall( gszSDNumber[cSDEntry], szName );
}
break;
}
} // end switch (LOWORD((DWORD)wParam)) { ... }
break; // end case WM_COMMAND
}
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(ghWndMain, &ps);
if(IsIconic(ghWndMain))
DrawIcon(ps.hdc, 0, 0, hIcon);
else
{
HBRUSH hBrush;
hBrush = GetSysColorBrush( COLOR_3DFACE );
// FillRect(ps.hdc, &ps.rcPaint, GetStockObject(LTGRAY_BRUSH));
FillRect(ps.hdc, &ps.rcPaint, hBrush);
}
EndPaint(ghWndMain, &ps);
return TRUE;
}
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
BOOL fHighlighted = (SendDlgItemMessage(
ghWndMain,
lpdis->CtlID,
BM_GETSTATE,
0,
0
) & 0x0004);
DrawButton(lpdis->hDC, lpdis->rcItem, fHighlighted);
DrawButtonText(
lpdis->hDC,
lpdis->rcItem,
fHighlighted,
lpdis->CtlID
);
return TRUE;
}
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORBTN:
case WM_CTLCOLORSTATIC:
SetBkColor((HDC)wParam, GetSysColor(COLOR_BTNFACE));
return (BOOL)GetSysColorBrush( COLOR_3DFACE );
default:
;
// return DefDlgProc( hwnd, msg, wParam, lParam );
// return DefWindowProc( hwnd, msg, wParam, lParam );
} // switch (msg) { ... }
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID AddToRedialList( LPCSTR szNumber )
{
// NLASTDIALED == 10
WORD cNum;
HWND hWndCombo = GetDlgItem(ghWndMain, IDD_DCOMBO);
DWORD nMatch;
// if valid number
if ( szNumber[0] )
{
// if list box has entries, check if this number
// is already present. If so delete old entry
cNum = (WORD) SendMessage(hWndCombo, CB_GETCOUNT, 0, 0);
if ( cNum != 0 )
{
nMatch = SendMessage ( hWndCombo, CB_FINDSTRING, 0, (LPARAM)szNumber );
if ( nMatch != CB_ERR )
{
SendMessage(hWndCombo, CB_DELETESTRING, nMatch, 0);
}
else
{
// if the list is full, remove oldest
if ( cNum == NLASTDIALED )
{
SendMessage( hWndCombo, CB_DELETESTRING, NLASTDIALED - 1, 0 );
}
}
}
SendMessage(hWndCombo, CB_INSERTSTRING, 0, (LPARAM)szNumber);
SendMessage(hWndCombo, CB_SETCURSEL, 0, 0L);
EnableWindow ( GetDlgItem( ghWndMain, IDD_DDIAL ), TRUE );
}
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID InitiateCall ( LPCSTR szNumber, LPCSTR szName )
{
HLINE hLine = NULL;
DWORD errCode;
// struct size info
DWORD dwLTPSize= sizeof ( LINETRANSLATEOUTPUT );
DWORD dwNameLen= lstrlen( szName ) + 1;
DWORD dwLCPSize= sizeof( LINECALLPARAMS );
LPLINETRANSLATEOUTPUT lpTransOut = NULL;
LPLINECALLPARAMS lpLineCallParams = NULL;
char szCanNumber[ TAPIMAXDESTADDRESSSIZE ];
// Open a line
errCode = lineOpen (
ghLineApp,
giCurrentLine,
&hLine,
gCurrentLineInfo.dwAPIVersion,
0,
0,
LINECALLPRIVILEGE_NONE,
0,
NULL
);
if (errCode)
{
errString ( ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK );
goto error;
}
// call translate address before dialing
do
{
lpTransOut = (LPLINETRANSLATEOUTPUT) DialerAlloc( dwLTPSize );
if ( !lpTransOut )
{
errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK );
goto error;
}
lpTransOut-> dwTotalSize = dwLTPSize;
if ( !MakeCanonicalNumber( szNumber, szCanNumber ) )
{
lstrcpy( szCanNumber, szNumber );
}
errCode = lineTranslateAddress (
ghLineApp,
giCurrentLine,
gCurrentLineInfo.dwAPIVersion,
szCanNumber,
0,
0,
lpTransOut
);
if ( ((LONG)errCode) < 0 )
{
errString( ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK );
goto error;
}
if ( lpTransOut-> dwNeededSize <= lpTransOut->dwTotalSize )
{
// ok we are done
break;
}
else
{
dwLTPSize = lpTransOut-> dwNeededSize;
DialerFree ( lpTransOut );
lpTransOut = NULL;
}
} while ( TRUE );
// if number dialed is 911, bring up a warning
if ( Is911( lpTransOut) )
{
INT nRes = errString ( ghWndMain, ERR_911WARN, MB_ICONSTOP | MB_YESNO );
if ( nRes == IDNO )
{
goto error;
}
}
// set call parameters
dwLCPSize += dwNameLen + lpTransOut-> dwDisplayableStringSize;
lpLineCallParams = (LPLINECALLPARAMS) DialerAlloc( dwLCPSize );
if ( !lpLineCallParams )
{
errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK );
goto error;
}
lpLineCallParams->dwTotalSize = dwLCPSize;
lpLineCallParams->dwBearerMode = LINEBEARERMODE_VOICE;
lpLineCallParams->dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
lpLineCallParams->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
lpLineCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
lpLineCallParams->dwAddressID = giCurrentAddress;
if ( szName[ 0 ] )
{
lpLineCallParams->dwCalledPartySize = dwNameLen;
lpLineCallParams->dwCalledPartyOffset = sizeof( LINECALLPARAMS );
lstrcpy (
(LPSTR) lpLineCallParams + sizeof(LINECALLPARAMS),
szName
);
}
lpLineCallParams-> dwDisplayableAddressSize = lpTransOut-> dwDisplayableStringSize;
lpLineCallParams-> dwDisplayableAddressOffset = sizeof( LINECALLPARAMS ) + dwNameLen;
lstrcpy (
(LPSTR) lpLineCallParams + sizeof(LINECALLPARAMS) + dwNameLen,
(LPSTR) lpTransOut + lpTransOut-> dwDisplayableStringOffset
);
// save dialing information
// Free old allocs.
if ( gszCurrentName )
{
DialerFree ( gszCurrentName );
}
if ( gszCurrentNumber )
{
DialerFree ( gszCurrentNumber );
}
// save new stuff
gszCurrentName = (LPSTR) DialerAlloc( dwNameLen );
if ( !gszCurrentName )
{
errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK );
goto error;
}
lstrcpy ( gszCurrentName, szName );
gszCurrentNumber = (LPSTR) DialerAlloc( lpTransOut-> dwDisplayableStringSize );
if ( !gszCurrentNumber )
{
errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK );
goto error;
}
lstrcpy (
gszCurrentNumber,
(LPSTR) lpTransOut + lpTransOut-> dwDisplayableStringOffset
);
gCurrentLineInfo.hLine = hLine;
ghCall = NULL;
// finally make the call.
gMakeCallRequestID = 0;
gMakeCallRequestID = lineMakeCall (
hLine,
&ghCall,
(LPSTR) lpTransOut + lpTransOut-> dwDialableStringOffset,
0,
lpLineCallParams
);
// async request ID
// - the call is going out
if ( (LONG) gMakeCallRequestID > 0 )
{
gfCurrentLineAvail = FALSE;
gfMakeCallReplyPending = TRUE;
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_DIALING),
ghWndMain,
(DLGPROC)DialingProc,
0
);
}
else
{
if ( gMakeCallRequestID == LINEERR_CALLUNAVAIL )
{
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_CALLFAILED),
ghWndMain,
(DLGPROC)LineInUseProc,
0
);
}
else
{
errString( ghWndMain, gMakeCallRequestID, MB_ICONEXCLAMATION | MB_OK );
}
DialerLineClose();
gfCurrentLineAvail = TRUE;
}
error :
if ( lpLineCallParams )
{
DialerFree( lpLineCallParams );
}
if ( lpTransOut )
{
DialerFree( lpTransOut );
}
// if makecall did not succeed but line
// was opened, close it.
if ( ( gMakeCallRequestID <= 0 ) && ( gCurrentLineInfo.hLine ) )
{
DialerLineClose ();
gfCurrentLineAvail = TRUE;
}
SetFocus( GetDlgItem( ghWndMain, IDD_DCOMBO ) );
return;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
DWORD GetLineInfo ( DWORD iLine, LPLINEINFO lpLineInfo )
{
DWORD errCode = 0;
DWORD dwNeededSize = 0;
LINEEXTENSIONID ExtensionID;
LPSTR pszLineName = NULL;
LPLINEDEVCAPS lpDevCaps = NULL;
errCode = lineNegotiateAPIVersion (
ghLineApp,
iLine,
TAPI_VERSION_1_0,
TAPI_CURRENT_VERSION,
&( lpLineInfo->dwAPIVersion ),
&ExtensionID
);
if ( errCode )
{
GetLineInfoFailed( iLine, lpDevCaps, lpLineInfo );
goto error;
}
dwNeededSize = sizeof( LINEDEVCAPS );
do
{
lpDevCaps = ( LPLINEDEVCAPS ) DialerAlloc( dwNeededSize );
if ( !lpDevCaps )
{
GetLineInfoFailed( iLine, lpDevCaps, lpLineInfo );
errCode = LINEERR_NOMEM;
goto error;
}
lpDevCaps->dwTotalSize = dwNeededSize;
errCode = lineGetDevCaps (
ghLineApp,
iLine,
lpLineInfo->dwAPIVersion,
0,
lpDevCaps
);
if ( errCode )
{
GetLineInfoFailed( iLine, lpDevCaps, lpLineInfo );
goto error;
}
if ( lpDevCaps-> dwNeededSize <= lpDevCaps-> dwTotalSize )
{
break;
}
dwNeededSize = lpDevCaps->dwNeededSize;
DialerFree( lpDevCaps );
lpDevCaps = NULL;
} while ( TRUE );
lpLineInfo->nAddr = lpDevCaps->dwNumAddresses;
lpLineInfo->fVoiceLine =
( (lpDevCaps->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE) != 0 );
pszLineName = (LPSTR) DialerAlloc( MAXBUFSIZE );
if ( !pszLineName )
{
errCode = LINEERR_NOMEM;
goto error;
}
if ( lpDevCaps->dwLineNameSize > 0 )
{
if ( lpDevCaps-> dwLineNameSize > (MAXBUFSIZE - 1) )
{
strncpy (
pszLineName,
(LPSTR) lpDevCaps + lpDevCaps->dwLineNameOffset,
MAXBUFSIZE - 1
);
pszLineName[ MAXBUFSIZE - 1 ] = '\0';
}
else
{
lstrcpy( pszLineName, (LPSTR) lpDevCaps + lpDevCaps-> dwLineNameOffset );
}
}
else
{
wsprintf ( pszLineName, "Line %d", iLine );
}
lstrcpy( lpLineInfo->szLineName, pszLineName );
lpLineInfo->dwPermanentLineID = lpDevCaps->dwPermanentLineID;
error:
if ( lpDevCaps )
DialerFree( lpDevCaps );
if ( pszLineName )
DialerFree( pszLineName );
return errCode;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID GetLineInfoFailed ( DWORD iLine, LPLINEDEVCAPS lpDevCaps, LPLINEINFO lpLineInfo )
{
if ( lpDevCaps )
DialerFree(lpDevCaps);
lpLineInfo->nAddr = 0;
lpLineInfo->fVoiceLine = FALSE;
lpLineInfo->dwAPIVersion = 0;
lpLineInfo->hLine = (HLINE)0;
lpLineInfo->dwPermanentLineID = 0;
lpLineInfo->szLineName[0] = 0;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
LPSTR GetAddressName(DWORD iLine, DWORD iAddress)
{
DWORD errCode = 0;
DWORD dwNeededSize = 0;
LPSTR pszAddressName = NULL;
LPLINEADDRESSCAPS lpAddressCaps = NULL;
// allocate space for lineGetAddressCaps data
dwNeededSize = sizeof( LINEADDRESSCAPS );
do
{
lpAddressCaps = ( LPLINEADDRESSCAPS )DialerAlloc( dwNeededSize );
if ( !lpAddressCaps )
{
goto error;
}
lpAddressCaps->dwTotalSize = dwNeededSize;
errCode = lineGetAddressCaps (
ghLineApp,
iLine,
iAddress,
gCurrentLineInfo.dwAPIVersion,
0,
lpAddressCaps
);
if ( errCode )
{
errString( ghWndMain, errCode, MB_ICONSTOP | MB_OK );
goto error;
}
if ( lpAddressCaps-> dwNeededSize <= lpAddressCaps-> dwTotalSize )
{
break;
}
dwNeededSize = lpAddressCaps->dwNeededSize;
DialerFree( lpAddressCaps );
lpAddressCaps = NULL;
} while( TRUE );
// get the address name
pszAddressName = DialerAlloc( MAXBUFSIZE );
if ( !pszAddressName )
{
goto error;
}
if ( lpAddressCaps-> dwAddressSize > 0 )
{
// keep string length bounded
if ( lpAddressCaps-> dwAddressSize > (MAXBUFSIZE - 1 ) )
{
strncpy(
pszAddressName,
(LPSTR) lpAddressCaps + lpAddressCaps->dwAddressOffset,
MAXBUFSIZE - 1
);
pszAddressName[ MAXBUFSIZE - 1] = '\0';
}
else
{
lstrcpy (
pszAddressName,
(LPSTR) lpAddressCaps + lpAddressCaps->dwAddressOffset
);
}
}
else
// use default name
{
wsprintf(pszAddressName, "Address %d", iAddress);
}
error:
if ( lpAddressCaps )
{
DialerFree( lpAddressCaps );
}
return pszAddressName;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL CALLBACK DialingProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
char szTemp[ TAPIMAXCALLEDPARTYSIZE ];
case WM_INITDIALOG:
// set global handle to window
ghWndDialing = hwnd;
AmpersandCompensate( gszCurrentName, szTemp );
SetDlgItemText(hwnd, IDD_DGNUMBERTEXT, gszCurrentNumber);
SetDlgItemText(hwnd, IDD_DGNAMETEXT, szTemp );
break;
case WM_COMMAND:
switch ( LOWORD( (DWORD)wParam ) )
{
// hang up
case IDCANCEL:
//gfDropping = TRUE;
// if lineMakeCall has completed
// only then drop call.
if ( !gfMakeCallReplyPending && ghCall )
{
if ( ( gDropCallRequestID = lineDrop ( ghCall, NULL, 0 ) ) < 0 )
{
errString ( ghWndDialing, gDropCallRequestID, MB_ICONSTOP | MB_OK );
}
}
else
{
DialerLineClose();
gfCurrentLineAvail = TRUE;
gfMakeCallReplyPending = FALSE;
}
ghWndDialing = NULL;
EndDialog(hwnd, FALSE);
return TRUE;
// something else terminated the call
// all we have to do is terminate this dialog box
case IDOK:
ghWndDialing = NULL;
EndDialog(hwnd, TRUE);
return TRUE;
}
break;
default:
;
}
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL CALLBACK AboutProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
{
return TRUE;
}
case WM_CLOSE:
EndDialog(hwnd, TRUE);
return TRUE;
case WM_COMMAND:
if(LOWORD((DWORD)wParam) == IDOK)
{
EndDialog(hwnd, TRUE);
return TRUE;
}
break;
}
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL CALLBACK ConnectUsingProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
static const DWORD aMenuHelpIDs[] =
{
IDD_CUTEXTLINE, IDH_DIALER_OPTIONS_LINE,
IDD_CULISTLINE, IDH_DIALER_OPTIONS_LINE,
IDD_CUTEXTADDRESS, IDH_DIALER_OPTIONS_ADDRESS,
IDD_CULISTADDRESS, IDH_DIALER_OPTIONS_ADDRESS,
IDD_CUSIMPLETAPICHKBOX, IDH_DIALER_OPTIONS_VOICE,
IDD_CUPROPERTIES, IDH_DIALER_OPTIONS_PROPERTIES,
0, 0
};
switch(msg)
{
case WM_HELP:
// processes clicks on controls when
// context mode help is selected
WinHelp (
((LPHELPINFO)lParam)->hItemHandle,
gszHELPfilename,
HELP_WM_HELP,
(DWORD)(LPVOID)aMenuHelpIDs
);
return TRUE;
case WM_CONTEXTMENU:
// processes right-clicks on controls
WinHelp (
(HWND)wParam,
gszHELPfilename,
HELP_CONTEXTMENU,
(DWORD)(LPVOID)aMenuHelpIDs
);
return TRUE;
case WM_INITDIALOG:
{
BOOL fEnable;
DWORD dwPriority;
//
// Is there any point in even showing this dialog box?
if ( gnAvailDevices == 0 )
{
// Nope. Let's tell the user what we don't like.
errString ( ghWndMain, ERR_NOLINES, MB_ICONEXCLAMATION | MB_OK );
EndDialog(hwnd, FALSE);
return TRUE;
}
// if not brought up by InitializeTAPI()
if ( lParam != INVALID_LINE )
{
// hide error text
EnableWindow( GetDlgItem( hwnd, IDD_CUERRORTEXT ), FALSE );
}
// get list of lines into the line list box.
fEnable = InitializeLineBox( GetDlgItem(hwnd, IDD_CULISTLINE) );
EnableWindow( GetDlgItem( hwnd, IDD_CULISTLINE ), fEnable);
// get list of addresses into the address list box.
fEnable =fEnable &&
InitializeAddressBox (
GetDlgItem(hwnd, IDD_CULISTLINE),
GetDlgItem(hwnd, IDD_CULISTADDRESS)
);
EnableWindow( GetDlgItem( hwnd, IDD_CULISTADDRESS ), fEnable );
EnableWindow( GetDlgItem( hwnd, IDOK ), fEnable );
EnableWindow( GetDlgItem( hwnd, IDD_CUPROPERTIES ), fEnable );
lineGetAppPriority (
"DIALER.EXE",
0, // checking app priority for Assisted Telephony requests
NULL,
LINEREQUESTMODE_MAKECALL,
NULL,
&dwPriority
);
CheckDlgButton(hwnd, IDD_CUSIMPLETAPICHKBOX, (dwPriority == 1));
// if dwPriority == 1, we're supporting Assisted Telephony AND
// have the highest priority.
EnableWindow (
GetDlgItem(hwnd, IDD_CUSIMPLETAPICHKBOX),
gfRegistered
);
return FALSE;
}
case WM_COMMAND:
{
switch ( LOWORD( (DWORD)wParam ) )
{
case IDD_CULISTLINE:
if ( HIWORD( wParam ) == CBN_SELENDOK )
// update address box
InitializeAddressBox (
GetDlgItem(hwnd, IDD_CULISTLINE),
GetDlgItem(hwnd, IDD_CULISTADDRESS)
);
break;
case IDD_CUPROPERTIES:
{
HWND hW = GetDlgItem(hwnd, IDD_CULISTLINE);
lineConfigDialog (
// device ID
(DWORD) SendMessage (
hW,
CB_GETITEMDATA,
(WORD) SendMessage(hW, CB_GETCURSEL, 0, 0),
0
),
hwnd,
NULL
);
break;
}
case IDOK:
{
HWND hwndBox;
char szBuffer[MAXBUFSIZE];
DWORD dwPriority;
// Update line
hwndBox = GetDlgItem( hwnd, IDD_CULISTLINE );
giCurrentLine = SendMessage (
hwndBox,
CB_GETITEMDATA,
SendMessage( hwndBox, CB_GETCURSEL, 0, 0 ),
0
);
// base 10
itoa( gdwPLID[giCurrentLine], szBuffer, 10 );
WritePrivateProfileString (
"Preference",
"Preferred Line",
szBuffer,
gszINIfilename
);
// Update address
hwndBox = GetDlgItem( hwnd, IDD_CULISTADDRESS );
giCurrentAddress = SendMessage (
hwndBox,
CB_GETITEMDATA,
SendMessage(hwndBox, CB_GETCURSEL, 0, 0),
0
);
itoa( giCurrentAddress, szBuffer, 10 );
WritePrivateProfileString (
"Preference",
"Preferred Address",
szBuffer,
gszINIfilename
);
// Update application priority
if ( SendDlgItemMessage (
hwnd,
IDD_CUSIMPLETAPICHKBOX,
BM_GETCHECK,
0,
0L
)
== 0)
{
dwPriority = 0;
}
else
{
dwPriority = 1;
}
lineSetAppPriority (
"DIALER.EXE",
0,
NULL,
LINEREQUESTMODE_MAKECALL,
NULL,
dwPriority
);
EndDialog(hwnd, TRUE);
return TRUE;
}
case IDCANCEL:
EndDialog(hwnd, FALSE);
return TRUE;
}
}
default:
;
}
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL CALLBACK LineInUseProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LPARAM lNewParam = lParam;
PTSTR ptStr;
switch(msg)
{
case WM_INITDIALOG:
{
switch(lParam)
{
case LINEDISCONNECTMODE_REJECT:
lNewParam = ikszDisconnectedReject;
break;
case LINEDISCONNECTMODE_BUSY:
lNewParam = ikszDisconnectedBusy;
break;
case LINEDISCONNECTMODE_NOANSWER:
lNewParam = ikszDisconnectedNoAnswer;
break;
case LINEDISCONNECTMODE_CONGESTION:
lNewParam = ikszDisconnectedNetwork;
break;
case LINEDISCONNECTMODE_INCOMPATIBLE:
lNewParam = ikszDisconnectedIncompatible;
break;
case LINEDISCONNECTMODE_NODIALTONE:
lNewParam = ikszDisconnectedNoDialTone;
break;
default:
lNewParam = ikszDisconnectedCantDo;
break;
}
return TRUE;
}
case WM_COMMAND:
if(LOWORD((DWORD)wParam) == IDOK)
{
EndDialog(hwnd, TRUE);
return TRUE;
}
break;
default:
;
// return DefDlgProc( hwnd, msg, wParam, lParam );
}
ptStr = DialerAlloc( MAXBUFSIZE );
LoadString( ghInst, lNewParam, ptStr, MAXBUFSIZE );
SetDlgItemText(
hwnd,
IDD_CFTEXT,
ptStr
);
DialerFree( ptStr );
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL CALLBACK SpeedDial1Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static DWORD nCurrentSpeedDial;
static const DWORD aMenuHelpIDs[] =
{
IDOK, IDH_DIALER_SPEED_SAVE,
IDD_SD1SPEEDDIAL1, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIAL2, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIAL3, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIAL4, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIAL5, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIAL6, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIAL7, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIAL8, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIALTEXT1, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIALTEXT2, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIALTEXT3, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIALTEXT4, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIALTEXT5, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIALTEXT6, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIALTEXT7, IDH_DIALER_BUTTONS,
IDD_SD1SPEEDDIALTEXT8, IDH_DIALER_BUTTONS,
IDD_SD1TEXTNAME, IDH_DIALER_SPEED_NAME,
IDD_SD1EDITNAME, IDH_DIALER_SPEED_NAME,
IDD_SD1TEXTNUMBER, IDH_DIALER_SPEED_NUMBER,
IDD_SD1EDITNUMBER, IDH_DIALER_SPEED_NUMBER,
IDD_SD1TEXTCHOOSE, (DWORD)-1,
IDD_SD1TEXTENTER, (DWORD)-1,
0, 0
};
// buffer to store speed dial names till they are saved.
static TCHAR szSDName[NSPEEDDIALS + 1][TAPIMAXDESTADDRESSSIZE];
switch(msg)
{
case WM_HELP:
// processes clicks on controls when
// context mode help is selected
WinHelp(
((LPHELPINFO)lParam)->hItemHandle,
gszHELPfilename,
HELP_WM_HELP,
(DWORD)(LPVOID)aMenuHelpIDs
);
return TRUE;
case WM_CONTEXTMENU: // processes right-clicks on controls
WinHelp(
(HWND)wParam,
gszHELPfilename,
HELP_CONTEXTMENU,
(DWORD)(LPVOID)aMenuHelpIDs
);
return TRUE;
case WM_INITDIALOG:
{
DWORD cSDEntry;
DWORD idFirstEmpty = (DWORD) -1;
char szName[TAPIMAXCALLEDPARTYSIZE];
char szTemp[TAPIMAXCALLEDPARTYSIZE];
char szFieldName[MAXBUFSIZE];
// Retrieve speed dial info from INI file
for(cSDEntry = 1; cSDEntry <= NSPEEDDIALS; ++cSDEntry)
{
wsprintf(szFieldName, "Name%d", cSDEntry);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
szSDName[ cSDEntry ],
TAPIMAXCALLEDPARTYSIZE - 1,
gszINIfilename
);
// set the first empty speed dial button
if ( idFirstEmpty == -1 &&
szSDName[ cSDEntry ][0] == '\0' &&
gszSDNumber[ cSDEntry ][ 0 ] == '\0' )
idFirstEmpty = cSDEntry;
wsprintf(szFieldName, "Number%d", cSDEntry);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
gszSDNumber[cSDEntry],
MAXBUFSIZE - 1,
gszINIfilename
);
// get a copy of the name for editing
// if name is empty, use the number as the
// name.
if ( lstrcmp( gszNULL, szSDName[ cSDEntry ] ) )
{
lstrcpy( szName, szSDName[ cSDEntry] );
}
else
{
lstrcpy( szName, gszSDNumber[ cSDEntry ] );
}
FitTextToButton( hwnd, IDD_SD1SPEEDDIAL1 + cSDEntry - 1, szName );
AmpersandCompensate( szName, szTemp );
SetDlgItemText (
hwnd,
IDD_SD1SPEEDDIAL1 + cSDEntry - 1,
(LPCSTR) szTemp
);
}
// for the edit speed dial dialog
// limit the lengths of text
SendDlgItemMessage (
hwnd,
IDD_SD1EDITNAME,
EM_LIMITTEXT,
(WPARAM)(TAPIMAXCALLEDPARTYSIZE - 1),
0
);
SendDlgItemMessage (
hwnd,
IDD_SD1EDITNUMBER,
EM_LIMITTEXT,
(WPARAM)(TAPIMAXDESTADDRESSSIZE - 1),
0
);
// select the first empty button
// nothing empty, then edit #1
if ( -1 == idFirstEmpty )
{
nCurrentSpeedDial = 1;
SetDlgItemText(
hwnd,
IDD_SD1EDITNAME,
(LPCSTR) szSDName[ 1 ]
);
SetDlgItemText(
hwnd,
IDD_SD1EDITNUMBER,
(LPCSTR) gszSDNumber[ 1 ]
);
}
else
{
nCurrentSpeedDial = idFirstEmpty;
}
SetFocus( GetDlgItem( hwnd, IDD_SD1EDITNAME ) );
return FALSE;
}
case WM_COMMAND:
{
char szName[TAPIMAXCALLEDPARTYSIZE];
char szTemp[ TAPIMAXCALLEDPARTYSIZE ];
switch( LOWORD( (DWORD) wParam ) )
{
case IDOK:
{
DWORD cSDEntry;
char szFieldName[MAXBUFSIZE];
// save new speed dial settings
for ( cSDEntry = 1; cSDEntry <= NSPEEDDIALS; ++cSDEntry )
{
wsprintf(szFieldName, "Name%d", cSDEntry);
WritePrivateProfileString (
"Speed Dial Settings",
szFieldName,
szSDName [cSDEntry],
gszINIfilename
);
wsprintf(szFieldName, "Number%d", cSDEntry);
WritePrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszSDNumber[cSDEntry],
gszINIfilename
);
// set the text for the corresponding
// main window button
if ( szSDName[ cSDEntry ][ 0 ] == '\0' )
{
lstrcpy( szName, gszSDNumber[ cSDEntry ] );
}
else
{
lstrcpy( szName, szSDName[ cSDEntry ] );
}
FitTextToButton(
ghWndMain,
IDD_DSPEEDDIAL1 + cSDEntry - 1,
szName
);
AmpersandCompensate( szName, szTemp );
SetDlgItemText (
ghWndMain,
IDD_DSPEEDDIAL1 + cSDEntry - 1,
(LPCSTR) szTemp
);
}
EndDialog(hwnd, TRUE);
return TRUE;
}
case IDCANCEL:
EndDialog(hwnd, FALSE);
return TRUE;
case IDD_SD1SPEEDDIAL1:
case IDD_SD1SPEEDDIAL2:
case IDD_SD1SPEEDDIAL3:
case IDD_SD1SPEEDDIAL4:
case IDD_SD1SPEEDDIAL5:
case IDD_SD1SPEEDDIAL6:
case IDD_SD1SPEEDDIAL7:
case IDD_SD1SPEEDDIAL8:
nCurrentSpeedDial =LOWORD( (DWORD) wParam ) - IDD_SD1SPEEDDIAL1 + 1;
SetDlgItemText (
hwnd,
IDD_SD1EDITNAME,
szSDName [ nCurrentSpeedDial ]
);
SetDlgItemText (
hwnd,
IDD_SD1EDITNUMBER,
gszSDNumber[nCurrentSpeedDial]
);
SetFocus( GetDlgItem( hwnd, IDD_SD1EDITNAME ) );
SendDlgItemMessage(
hwnd,
IDD_SD1EDITNAME,
EM_SETSEL,
0,
MAKELPARAM(0, -1)
);
break;
case IDD_SD1EDITNAME:
if ( HIWORD( wParam ) == EN_CHANGE )
{
GetDlgItemText (
hwnd,
IDD_SD1EDITNAME,
szName,
TAPIMAXCALLEDPARTYSIZE
);
// if there is no name, label the button with
// the number
if ( szName[ 0 ] == '\0' )
{
szSDName[ nCurrentSpeedDial ][ 0 ] = '\0';
lstrcpy( szName, gszSDNumber[ nCurrentSpeedDial ] );
}
else
{
lstrcpy( szSDName[ nCurrentSpeedDial ], szName );
}
FitTextToButton (
hwnd,
IDD_SD1SPEEDDIAL1 + nCurrentSpeedDial - 1,
szName
);
AmpersandCompensate( szName, szTemp );
SetDlgItemText (
hwnd,
IDD_SD1SPEEDDIAL1 + nCurrentSpeedDial - 1,
szTemp
);
}
break;
case IDD_SD1EDITNUMBER:
if ( HIWORD( wParam ) == EN_CHANGE )
{
GetDlgItemText (
hwnd,
IDD_SD1EDITNUMBER,
gszSDNumber[nCurrentSpeedDial],
TAPIMAXDESTADDRESSSIZE
);
if ( gszSDNumber[ nCurrentSpeedDial ][ 0 ] == '\0' )
{
GetDlgItemText (
hwnd,
IDD_SD1EDITNAME,
szName,
TAPIMAXDESTADDRESSSIZE
);
if ( szName[ 0 ] == '\0' )
{
SetDlgItemText (
hwnd,
IDD_SD1SPEEDDIAL1 + nCurrentSpeedDial - 1,
szName
);
}
}
}
break;
} // switch(LOWORD((DWORD)wParam))
break;
} // case WM_COMMAND:
default:
;
} // switch(msg)
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL CALLBACK SpeedDial2Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static DWORD nCurrentSpeedDial;
static const DWORD aMenuHelpIDs[] =
{
IDOK, IDH_DIALER_SPEED_SAVE,
IDD_SD2SAVEANDDIAL, IDH_DIALER_SPEED_SAVE_DIAL,
IDD_SD2TEXTNAME, IDH_DIALER_SPEED_NAME,
IDD_SD2EDITNAME, IDH_DIALER_SPEED_NAME,
IDD_SD2TEXTNUMBER, IDH_DIALER_SPEED_NUMBER,
IDD_SD2EDITNUMBER, IDH_DIALER_SPEED_NUMBER,
0, 0
};
switch(msg)
{
case WM_HELP:
// processes clicks on controls when
// context mode help is selected
WinHelp (
((LPHELPINFO)lParam)->hItemHandle,
gszHELPfilename,
HELP_WM_HELP,
(DWORD)(LPVOID)aMenuHelpIDs
);
return TRUE;
case WM_CONTEXTMENU:
// processes right-clicks on controls
WinHelp (
(HWND)wParam,
gszHELPfilename,
HELP_CONTEXTMENU,
(DWORD)(LPVOID)aMenuHelpIDs
);
return TRUE;
case WM_INITDIALOG:
{
char szFieldName [MAXBUFSIZE];
char szName [TAPIMAXCALLEDPARTYSIZE];
nCurrentSpeedDial = LOWORD( lParam ) - IDD_DSPEEDDIAL1 + 1;
// retrieve speed dial button info
wsprintf(szFieldName, "Name%d", nCurrentSpeedDial);
GetPrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszNULL,
szName,
TAPIMAXCALLEDPARTYSIZE - 1,
gszINIfilename
);
SetDlgItemText (
hwnd,
IDD_SD2EDITNAME,
szName
);
SetDlgItemText (
hwnd,
IDD_SD2EDITNUMBER,
gszSDNumber[nCurrentSpeedDial]
);
// limit the lengths of the texts
SendDlgItemMessage (
hwnd,
IDD_SD2EDITNAME,
EM_LIMITTEXT,
(WPARAM)(TAPIMAXCALLEDPARTYSIZE - 1),
0
);
SendDlgItemMessage (
hwnd,
IDD_SD2EDITNUMBER,
EM_LIMITTEXT,
(WPARAM)(TAPIMAXDESTADDRESSSIZE - 1),
0
);
SetFocus( GetDlgItem( hwnd, IDD_SD2EDITNAME ) );
SendDlgItemMessage (
hwnd,
IDD_SD2EDITNAME,
EM_SETSEL,
0,
MAKELPARAM(0, -1)
);
return FALSE;
}
case WM_COMMAND:
{
char szName[ TAPIMAXCALLEDPARTYSIZE ];
char szTemp[ TAPIMAXCALLEDPARTYSIZE ];
char szFieldName[MAXBUFSIZE];
switch ( LOWORD( (DWORD) wParam ) )
{
case IDOK:
case IDD_SD2SAVEANDDIAL:
{
GetDlgItemText (
hwnd,
IDD_SD2EDITNAME,
(LPTSTR) szName,
TAPIMAXCALLEDPARTYSIZE
);
GetDlgItemText (
hwnd,
IDD_SD2EDITNUMBER,
(LPTSTR) gszSDNumber[nCurrentSpeedDial],
TAPIMAXCALLEDPARTYSIZE
);
wsprintf ( szFieldName, "Name%d", nCurrentSpeedDial );
WritePrivateProfileString (
"Speed Dial Settings",
szFieldName,
szName,
gszINIfilename
);
wsprintf ( szFieldName, "Number%d", nCurrentSpeedDial );
WritePrivateProfileString (
"Speed Dial Settings",
szFieldName,
gszSDNumber[nCurrentSpeedDial],
gszINIfilename
);
// update main window buttons
// is only number has been entered, label button with it.
if ( szName[ 0 ] == '\0' )
{
lstrcpy( szName, gszSDNumber[ nCurrentSpeedDial ] );
}
FitTextToButton (
ghWndMain,
IDD_DSPEEDDIAL1 + nCurrentSpeedDial - 1,
(LPSTR) szName
);
AmpersandCompensate( szName, szTemp );
SetDlgItemText (
ghWndMain,
IDD_DSPEEDDIAL1 + nCurrentSpeedDial - 1,
(LPCSTR)szTemp
);
// if save and dial, then post dial message to main window
if ( LOWORD( (DWORD) wParam ) == IDD_SD2SAVEANDDIAL )
{
PostMessage (
ghWndMain,
WM_COMMAND,
MAKEWPARAM (
nCurrentSpeedDial + IDD_DSPEEDDIAL1 - 1,
BN_CLICKED
),
(LPARAM) GetDlgItem (
ghWndMain,
nCurrentSpeedDial + IDD_DSPEEDDIAL1 - 1
)
);
}
EndDialog(hwnd, TRUE);
return TRUE;
}
case IDCANCEL:
EndDialog(hwnd, FALSE);
return TRUE;
case IDD_SD2EDITNAME:
case IDD_SD2EDITNUMBER:
if ( HIWORD( wParam ) == EN_CHANGE)
{
EnableWindow (
GetDlgItem( hwnd, IDD_SD2SAVEANDDIAL ),
GetWindowTextLength ( GetDlgItem( hwnd, IDD_SD2EDITNUMBER ) ) > 0
);
}
break;
} // switch(LOWORD((DWORD)wParam))
break;
}
default:
;
} // switch(msg)
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID CALLBACK
tapiCallback (
DWORD hDevice,
DWORD dwMsg,
DWORD dwCBInstance,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3
)
{
switch (dwMsg)
{
INT errCode;
case LINE_ADDRESSSTATE:
break;
case LINE_CALLINFO:
break;
case LINE_CALLSTATE:
if ( (HCALL)hDevice != ghCall )
return;
switch ( dwParam1 ) // new state
{
case LINECALLSTATE_IDLE:
// tell "Dialing" window to terminate
if ( ghWndDialing )
{
SendMessage (
ghWndDialing,
WM_COMMAND,
MAKEWPARAM( IDOK, 0 ),
0
);
}
// tapi call cleanup
if ( !gfMakeCallReplyPending && ghCall )
{
if ( ( errCode = lineDeallocateCall( ghCall ) ) < 0 )
{
errString ( ghWndMain, errCode, MB_ICONSTOP | MB_OK );
}
ghCall = NULL;
}
DialerLineClose();
gfCurrentLineAvail = TRUE;
// update main window
DisableDialButtons( FALSE );
break;
case LINECALLSTATE_BUSY:
tapiCallback (
hDevice,
dwMsg,
dwCBInstance,
LINECALLSTATE_DISCONNECTED,
LINEDISCONNECTMODE_BUSY,
dwParam3
);
break;
case LINECALLSTATE_SPECIALINFO:
tapiCallback (
hDevice,
dwMsg,
dwCBInstance,
LINECALLSTATE_DISCONNECTED,
LINEDISCONNECTMODE_UNREACHABLE,
dwParam3
);
break;
case LINECALLSTATE_DISCONNECTED:
{
BOOL fCallOK;
DWORD LineDisconnectMode;
if ( dwParam2 == 0 )
LineDisconnectMode = LINEDISCONNECTMODE_NORMAL;
else
LineDisconnectMode = dwParam2;
fCallOK = ( LineDisconnectMode == LINEDISCONNECTMODE_NORMAL||
LineDisconnectMode == LINEDISCONNECTMODE_UNKNOWN||
LineDisconnectMode == LINEDISCONNECTMODE_PICKUP||
LineDisconnectMode == LINEDISCONNECTMODE_FORWARDED||
LineDisconnectMode == LINEDISCONNECTMODE_UNAVAIL
);
if ( !gfMakeCallReplyPending && ghCall )
{
//gfDropping = TRUE;
if ( ( gDropCallRequestID = lineDrop ( ghCall, NULL, 0 ) ) < 0 )
{
errString ( ghWndMain, gDropCallRequestID, MB_ICONSTOP | MB_OK );
}
}
if ( !fCallOK )
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_CALLFAILED),
ghWndMain,
(DLGPROC)LineInUseProc,
LineDisconnectMode
);
break;
}
}
break;
case LINE_CLOSE:
if ( gCurrentLineInfo.hLine == (HLINE)hDevice )
{
errString(ghWndMain, ERR_LINECLOSE, MB_ICONEXCLAMATION | MB_OK );
gCurrentLineInfo.hLine = NULL;
gfCurrentLineAvail = FALSE;
DisableDialButtons(FALSE);
}
break;
case LINE_CREATE:
// dwParam1 is the new device's ID
if ( dwParam1 >= gnAvailDevices )
{
DWORD* gnAddrTemp;
DWORD iLine;
LINEINFO LineInfo;
// we record new device's address count.
// we are assuming here that we're just adding a new
// line and it's sequential and it's the last one
gnAvailDevices = dwParam1 + 1;
gnAddrTemp = (DWORD *) DialerAlloc ( sizeof(DWORD) * (int)(gnAvailDevices) );
for ( iLine = 0; iLine < (gnAvailDevices-1); ++iLine )
gnAddrTemp[iLine] = gnAddr[iLine];
DialerFree( gnAddr );
// we have effectively added one more
// space in the gnAddr array
gnAddr = gnAddrTemp;
if ( GetLineInfo( dwParam1, &LineInfo ) != ERR_NONE )
break;
gnAddr[dwParam1] = LineInfo.nAddr;
}
break;
case LINE_DEVSPECIFIC:
break;
case LINE_DEVSPECIFICFEATURE:
break;
case LINE_GATHERDIGITS:
break;
case LINE_GENERATE:
break;
case LINE_LINEDEVSTATE:
if ( dwParam1 & LINEDEVSTATE_REINIT )
{
if(dwParam2 != 0)
{
// this is another msg translated into REINIT
tapiCallback( hDevice, dwParam2, dwCBInstance, dwParam3, 0, 0 );
}
else
{
// Re-initialize TAPI
gfNeedToReinit = TRUE;
}
}
if ( dwParam1 & LINEDEVSTATE_REMOVED )
{
DialerLineClose();
tapiCallback(hDevice, LINE_CLOSE, dwCBInstance, 0, 0, 0); // is this needed?
}
break;
case LINE_MONITORDIGITS:
break;
case LINE_MONITORMEDIA:
break;
case LINE_MONITORTONE:
break;
// async reply from lineMakeCall() or lineDrop()
case LINE_REPLY:
// reply for lineMakeCall
if ( (LONG) dwParam1 == gMakeCallRequestID )
{
// error on make call
if ( dwParam2 != ERR_NONE )
{
// Get rid of the Dialing Dialog box if it's up
if ( ghWndDialing )
{
SendMessage(
ghWndDialing,
WM_COMMAND,
MAKEWPARAM(IDOK,0),
0
);
}
if ( dwParam2 == LINEERR_CALLUNAVAIL )
{
DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_CALLFAILED),
ghWndMain,
(DLGPROC)LineInUseProc,
0
);
}
else
{
errString ( ghWndMain, dwParam2, MB_ICONEXCLAMATION | MB_OK );
}
ghCall = NULL;
DialerLineClose();
gfCurrentLineAvail = TRUE;
}
gfMakeCallReplyPending = FALSE;
}
// reply from lineDrop()
if ( (LONG) dwParam1 == gDropCallRequestID )
{
//gfDropping = FALSE;
// tell "Dialing" window to terminate
if ( ghWndDialing )
{
SendMessage (
ghWndDialing,
WM_COMMAND,
MAKEWPARAM( IDOK,0 ),
0
);
}
// tapi call cleanup
if ( dwParam2 == ERR_NONE )
{
if ( !gfMakeCallReplyPending && ghCall )
{
if ( ( errCode = lineDeallocateCall( ghCall ) ) < 0 )
{
errString ( ghWndMain, errCode, MB_ICONSTOP | MB_OK );
}
ghCall = NULL;
}
}
DialerLineClose ();
gfCurrentLineAvail = TRUE;
}
break;
case LINE_REQUEST:
// Simple TAPI request
if ( dwParam1 == LINEREQUESTMODE_MAKECALL )
{
gfCallRequest = TRUE;
}
break;
}
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL InitializeLineBox(HWND hwndLineBox)
{
DWORD iLine, iItem, iItemCurrent = (DWORD)-1;
DWORD errCode;
LPLINEINFO lpLineInfo = NULL;
// allocate buffer for storing LINEINFO for all of
// the available lines. Always allocate space for
// at least one line
if ( gnAvailDevices == 0 )
{
lpLineInfo = (LPLINEINFO) DialerAlloc( sizeof(LINEINFO) );
}
else
{
lpLineInfo = (LPLINEINFO) DialerAlloc ( sizeof(LINEINFO) * (int)gnAvailDevices );
}
// if no space was set aside...
if ( lpLineInfo == NULL )
return LINEERR_NOMEM;
// fill lpLineInfo[] and open each line
for ( iLine = 0; iLine < gnAvailDevices; ++iLine )
{
// skip remaining processing for this line if it didn't open
if ( GetLineInfo( iLine, &lpLineInfo[iLine] ) != ERR_NONE )
{
continue;
}
iItem = SendMessage (
hwndLineBox,
CB_ADDSTRING,
0,
(LPARAM)(LPCSTR)(lpLineInfo[iLine].szLineName)
);
// error, bail out.
if ( iItem == CB_ERR || iItem == CB_ERRSPACE )
{
if (lpLineInfo)
{
DialerFree(lpLineInfo);
}
return FALSE;
}
errCode = SendMessage (
hwndLineBox,
CB_SETITEMDATA,
(WPARAM)iItem,
(LPARAM)iLine
);
if ( iLine == giCurrentLine )
{
iItemCurrent = iItem;
}
else if ( iItemCurrent != -1 && iItem <= iItemCurrent )
{
// if the item we are putting is before the
// "current" item, we must increment iItemCurrent
// to reflect that something is being placed before
// it, due to sorting
++iItemCurrent;
}
}
if ( iItemCurrent == (DWORD)-1 )
iItemCurrent = 0;
if ( SendMessage( hwndLineBox, CB_GETCOUNT, 0, 0) != 0 )
{
SendMessage( hwndLineBox, CB_SETCURSEL, (WPARAM)iItemCurrent, 0 );
return TRUE;
}
DialerFree(lpLineInfo);
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
BOOL InitializeAddressBox( HWND hwndLineBox, HWND hwndAddressBox )
{
DWORD errCode;
DWORD iAddress, iItem, iItemCurrent = (DWORD)-1;
DWORD iLineBoxCurrent;
LPSTR pszAddressName;
if ( SendMessage( hwndLineBox, CB_GETCOUNT, 0, 0 ) == 0 )
{
return FALSE;
}
// select current entry in line box
iLineBoxCurrent = SendMessage (
hwndLineBox,
CB_GETITEMDATA,
SendMessage( hwndLineBox, CB_GETCURSEL, 0, 0 ),
0
);
// empty address list box
SendMessage ( hwndAddressBox, CB_RESETCONTENT, 0, 0);
// get all the address for this line
for ( iAddress = 0; iAddress < gnAddr[iLineBoxCurrent]; ++iAddress )
{
pszAddressName = GetAddressName( iLineBoxCurrent, iAddress );
// if this address if fails, try the next one
if ( !pszAddressName )
continue;
iItem = SendMessage (
hwndAddressBox,
CB_ADDSTRING,
0,
(LPARAM) (LPCSTR) (pszAddressName)
);
// error, bail out
if ( iItem == CB_ERR || iItem == CB_ERRSPACE )
return FALSE;
errCode = SendMessage (
hwndAddressBox,
CB_SETITEMDATA,
(WPARAM) iItem,
(LPARAM) iAddress
);
if ( iLineBoxCurrent == giCurrentLine )
{
if(iAddress == giCurrentAddress)
{
iItemCurrent = iItem;
}
else
{
// if the item we are putting is before the
// "current" item, we must increment iItemCur
// to reflect that something is being placed
// before it, due to sorting
if ( iItemCurrent != -1 && iItem <= iItemCurrent )
{
++iItemCurrent;
}
}
}
DialerFree( pszAddressName );
}
if ( iLineBoxCurrent != giCurrentLine )
{
// if we're not looking at the current line
// then highlight address 0
iItemCurrent = 0;
}
SendMessage (
hwndAddressBox,
CB_SETCURSEL,
iItemCurrent,
0
);
return TRUE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID ManageAssistedTelephony(VOID)
{
DWORD errCode;
LPLINEREQMAKECALL lpRequestBuffer;
lpRequestBuffer = (LPLINEREQMAKECALL) DialerAlloc( sizeof( LINEREQMAKECALL ) );
if ( !lpRequestBuffer )
{
goto error;
}
// bring window to front
SetForegroundWindow(ghWndMain);
// get next queued request.
errCode = lineGetRequest (
ghLineApp,
LINEREQUESTMODE_MAKECALL,
lpRequestBuffer
);
if ( errCode )
{
// if no more call requests pending, reset flag.
if ( errCode == LINEERR_NOREQUEST )
{
gfCallRequest = FALSE;
}
else
{
errString ( ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK );
}
goto error;
}
// if a line has not been selected
if ( giCurrentLine == (DWORD)-1 )
{
if (!DialogBoxParam (
ghInst,
MAKEINTRESOURCE(IDD_CONNECTUSING),
ghWndMain,
(DLGPROC) ConnectUsingProc,
INVALID_LINE
))
{
// failed to get a line
goto error;
}
}
// make the reuested call.
InitiateCall (
lpRequestBuffer->szDestAddress,
lpRequestBuffer->szCalledParty
);
error :
if ( lpRequestBuffer )
{
DialerFree( lpRequestBuffer );
}
return;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
VOID DialerLineClose()
{
DWORD errCode;
if ( gCurrentLineInfo.hLine )
{
if ( errCode = lineClose ( gCurrentLineInfo.hLine ) )
{
errString ( ghWndMain, errCode, MB_ICONSTOP | MB_OK );
}
gCurrentLineInfo.hLine = NULL;
}
// re-initialize TAPI if it needs to be re-initialized
if ( gfNeedToReinit )
{
CloseTAPI();
errCode = InitializeTAPI();
if(errCode)
{
errString(ghWndMain, errCode, MB_APPLMODAL | MB_ICONEXCLAMATION );
DialerCleanup(); // terminate program if we can't init
return;
}
errCode = lineRegisterRequestRecipient (
ghLineApp,
0,
LINEREQUESTMODE_MAKECALL,
TRUE
);
if (errCode)
{
errString(ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK );
}
gfNeedToReinit = FALSE;
}
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
int errString( HWND hWndOwner, UINT errCode, UINT uFlags )
{
PTSTR ptStrTitle;
PTSTR ptStrError;
int nResult;
BOOL bDefault = FALSE;
ptStrTitle = DialerAlloc( MAXBUFSIZE );
if ( NULL == ptStrTitle )
{
// Now, _this_ is a problem.
return 0;
}
ptStrError = DialerAlloc( MAXBUFSIZE );
if ( NULL == ptStrError )
{
// Now, _this_ is a problem.
DialerFree( ptStrTitle);
return 0;
}
switch(errCode)
{
case ERR_NOLINES:
errCode = ikszErrNoVoiceLine;
break;
case ERR_NOVOICELINE:
errCode = ikszErrNoVoiceLine;
break;
case ERR_LINECLOSE:
errCode = ikszErrLineClose;
break;
case ERR_911WARN:
errCode = ikszWarningFor911;
break;
case ERR_NEWDEFAULT:
errCode = ikszWarningNewDefault;
break;
case LINEERR_NODRIVER:
errCode = ikszErrLineInitNoDriver;
break;
case LINEERR_NODEVICE:
errCode = ikszErrLineInitNoDevice;
break;
case LINEERR_INIFILECORRUPT:
errCode = ikszErrLineInitBadIniFile ;
break;
case LINEERR_NOMEM:
errCode = ikszErrOOM;
break;
case LINEERR_INCOMPATIBLEAPIVERSION:
errCode = ikszErrLineInitWrongDrivers ;
break;
case LINEERR_OPERATIONFAILED:
errCode = ikszErrTAPI;
break;
case LINEERR_INVALADDRESS:
errCode = ikszErrInvalAddress;
break;
case LINEERR_ADDRESSBLOCKED:
errCode = ikszErrAddrBlocked;
break;
case LINEERR_BILLINGREJECTED:
errCode = ikszErrBillingRejected;
break;
case LINEERR_RESOURCEUNAVAIL:
case LINEERR_ALLOCATED:
case LINEERR_INUSE:
errCode = ikszErrResUnavail;
break;
case LINEERR_NOMULTIPLEINSTANCE:
errCode = ikszErrNoMultipleInstance;
break;
case LINEERR_INVALCALLSTATE:
errCode = ikszErrInvalCallState;
break;
case LINEERR_INVALCOUNTRYCODE:
errCode = ikszErrInvalidCountryCode;
break;
default:
bDefault = TRUE;
break;
}
if (bDefault)
{
// if using default error, get TAPI's
// error message from FormatError()
if (!FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
(LPCVOID)GetModuleHandle(TEXT("TAPI32.DLL")),
(DWORD)TAPIERROR_FORMATMESSAGE(errCode),
0,
(LPTSTR)ptStrError,
MAXBUFSIZE,
NULL))
{
// if this fails, fall back on default
LoadString( ghInst, ikszErrDefault, ptStrError, MAXBUFSIZE);
}
}
else // not the default error message
{
if ( 0 == LoadString( ghInst, errCode, ptStrError, MAXBUFSIZE ) )
{
#if DBG
TCHAR buf[200];
wsprintf( buf, "Cannot load string: hinst:0x%08lx errcode: %ld", (DWORD)ghInst,(DWORD)errCode);
OutputDebugString( buf );
MessageBox( NULL, buf, "Dialer", MB_OK);
#endif
LoadString( ghInst, ikszErrDefault, ptStrError, MAXBUFSIZE );
}
}
LoadString( ghInst, ikszWarningTitle, ptStrTitle, MAXBUFSIZE );
nResult = MessageBox( hWndOwner, ptStrError, ptStrTitle, uFlags );
DialerFree( ptStrTitle );
DialerFree( ptStrError );
return nResult;
}
/*
*Name :
*FitTextToButton
*
*Arguements :
*hDlg handle for the dialog in which this button is embedded
*nButtonID button id of this button
*szNameName to fit on the button. Max size TAPIMAXCALLEDPARTYSIZE
*
*Return :
*None
*
*Comments :
*Function first checks to see if the button text specified fits in the
*button. If it does not it truncates it appropriately and adds trailing
*ellipses.
*/
VOID FitTextToButton ( HWND hDlg, INT nButtonID, LPSTR szName )
{
HDC hDC;
HFONT hFont, hOldFont;
HWND hWnd;
do
{
// calculate number of chars. that can fit on
// the button
intnLen;
RECT rect;
SIZE size;
POINT pt;
char buf [TAPIMAXCALLEDPARTYSIZE + 1];
// get button dimensions
hWnd = GetDlgItem( hDlg, nButtonID );
if ( hWnd == NULL )
break;
if ( !GetClientRect( hWnd, &rect ) )
break;
// get character dimensions
hDC = GetDC( hWnd );
if ( hDC == NULL )
break;
hFont = (HFONT) SendMessage( hWnd, WM_GETFONT, 0, 0 );
if ( hFont == NULL )
hOldFont = SelectObject( hDC, GetStockObject( SYSTEM_FONT ) );
else
hOldFont = SelectObject( hDC, hFont );
// add an extra char at the end to compensate for
// leading space,
lstrcpy ( buf, szName );
nLen = lstrlen( buf );
buf [ nLen ] = 'X';
buf [ nLen + 1 ] = '\0';
if ( !GetTextExtentPoint32( hDC, buf, nLen + 1, &size ) )
break;
pt.x = size.cx;
if ( !LPtoDP( hDC, &pt, 1 ) )
break;
// check if name fits on button
if ( pt.x > rect.right )
{
// find how much of the name fits
int i = 0;
nLen = lstrlen( szName );
for ( i = 0; i < nLen; i++ )
{
buf[ i ] = szName[ i ];
// an extra char is stuffed to compensate for the
// leading space left by the left alignment
buf [ i + 1 ] = 'X';
buf [ i + 2 ] = '\0';
// break out in cases of error condition
if ( !GetTextExtentPoint32( hDC, buf, i + 2, &size ) )
{
i = nLen;
break;
}
pt.x = size.cx;
if ( !LPtoDP( hDC, &pt, 1 ) )
{
i = nLen;
break;
}
if ( pt.x > rect.right )
break;
}
// error
if ( i >= nLen )
break;
// name is too long. truncate and add ellipses
szName [i - 3] = '\0';
lstrcat( szName, "..." );
}
} while( FALSE );
if ( hDC )
{
SelectObject( hDC, hOldFont );
ReleaseDC( hWnd, hDC );
}
return;
}
/*
*Name :
*Is911
*
*Arguements :
*lpTransOut -Translated address contained the dialable string
*
*Returns
*TRUE -If number to be dialed (in the US) is prefixed by 911
*FALSE -Otherwise
*
* Comments
*
*/
BOOL Is911 ( LPLINETRANSLATEOUTPUT lpTransOut )
{
DWORD i = 0, j = 0;
LPSTR lpDialDigits = (LPSTR)lpTransOut + lpTransOut-> dwDialableStringOffset;
char sz3Pref [ 4 ] = "";
// if this is not the US
if ( lpTransOut-> dwCurrentCountry != 1 )
return FALSE;
// skip non digit characters and extract
// the first 3 digits in the dialable number
for ( i = 0, j = 0; i < lpTransOut-> dwDialableStringSize ; i++ )
{
if ( ISDIGIT( lpDialDigits[i] ) )
{
sz3Pref[ j++ ] = lpDialDigits [ i ];
sz3Pref[ j ] = '\0';
if ( j == 3 )
break;
}
}
if ( !lstrcmp( sz3Pref, "911" ) )
{
return TRUE;
}
return FALSE;
}
/*
*Name :
*MakeCanonicalNumber
*
*Arguements :
*szNumber Number to convert into canonical form. Max size TAPIMAXDESTADDRESSSIZE
*szCanNumberCanonical representation of number specified in szNumber
*
*Return :
*TRUEIf the conversion was successful.
*FALSEotherwise
*
*Comments :
*Function first checks if given number is already in canonical form.
*If it is, it returns. If it is not, then it performs the conversion.
*/
BOOL MakeCanonicalNumber ( LPCSTR szNumber, LPSTR szCanNumber )
{
char szDigits [ TAPIMAXDESTADDRESSSIZE ];
char szPref [ TAPIMAXDESTADDRESSSIZE ];
BOOL bRes = FALSE;
INT errCode = -1;
INT nLenPref, nLenDigits, cPos, i;
DWORD dwSize = 0;
DWORD dwInd = 0;
LPLINETRANSLATEOUTPUT lpTransOut = NULL;
LPLINETRANSLATECAPS lpTransCaps = NULL;
dwSize = sizeof ( LINETRANSLATEOUTPUT );
do
{
lpTransOut = ( LPLINETRANSLATEOUTPUT ) DialerAlloc ( dwSize );
if ( !lpTransOut )
{
errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK );
goto error;
}
lpTransOut-> dwTotalSize = dwSize;
errCode = lineTranslateAddress (
ghLineApp,
giCurrentLine,
gCurrentLineInfo.dwAPIVersion,
szNumber,
0,
0,
lpTransOut
);
if ( errCode )
{
goto error;
}
if ( lpTransOut-> dwNeededSize <= lpTransOut-> dwTotalSize )
break;
dwSize = lpTransOut-> dwNeededSize;
DialerFree( lpTransOut );
} while( TRUE );
// check if input number is already in
// canonical form.
if ( lpTransOut-> dwTranslateResults & LINETRANSLATERESULT_CANONICAL )
goto error;
// ensure country is the USA.
if ( lpTransOut-> dwCurrentCountry != 1 )
goto error;
// Extract the digits from given string
// allowed formatting characters that are ignored are
// space, (, ), -, .
// presence of other characters will render the string invalid.
// find the prefix of the address upto the | mark.
// the rest of the string can be ignored
nLenPref = strcspn ( szNumber, "|" );
strncpy( szPref, szNumber, nLenPref );
szPref[ nLenPref ] = '\0';
// if string is not composed entirely of digits
// and allowable formating characters, quit conversion
if ( strspn( szPref, " 0123456789()-." ) != (size_t) nLenPref )
goto error;
// collect digits ignoring formating characters.
szDigits[ 0 ] = '\0';
for ( i = 0, nLenDigits = 0; i < nLenPref; i++ )
{
if ( ISDIGIT( szNumber[ i ] ) )
{
szDigits[ nLenDigits++ ] = szNumber[ i ];
}
}
szDigits[ nLenDigits ] = '\0';
// if "internal" number
if ( nLenDigits < LOCAL_NUMBER )
goto error;
switch ( nLenDigits )
{
// Local number ( 7 digits) preceeded by a 0/1
// Strip leading 0/1 and treat as a local number
case EXTENDED_LOCAL_NUMBER:
if ( szDigits[ 0 ] == '0' || szDigits[ 0 ] == '1' )
{
nLenDigits--;
memmove( szDigits, &(szDigits[1]), nLenDigits );
szDigits[ nLenDigits ] = '\0';
cPos = strcspn( szPref, "01" );
nLenPref--;
memmove( &(szPref[ cPos ]), &(szPref[ cPos + 1 ]), nLenPref - cPos );
szPref[ nLenPref ] = '\0';
}
else
{
goto error;
}
case LOCAL_NUMBER :
{
LPLINELOCATIONENTRY lpLocLst;
// if leading digit is 0 or 1, it is
// illegal in the US
if ( szDigits[ 0 ] == '0' || szDigits[ 0 ] == '1' )
{
goto error;
}
// get area code nformation for local number
dwSize = sizeof( LINETRANSLATECAPS );
do
{
lpTransCaps = (LPLINETRANSLATECAPS) DialerAlloc( dwSize );
if ( !lpTransCaps )
{
errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK );
goto error;
}
lpTransCaps-> dwTotalSize = dwSize;
errCode = lineGetTranslateCaps (
ghLineApp,
gCurrentLineInfo.dwAPIVersion,
lpTransCaps
);
if ( errCode )
{
errString( ghWndMain, errCode, MB_ICONSTOP | MB_OK );
goto error;
}
if ( lpTransCaps-> dwNeededSize <= lpTransCaps-> dwTotalSize )
{
break;
}
dwSize = lpTransCaps-> dwNeededSize;
DialerFree( lpTransCaps );
} while ( TRUE );
// skip entries till you locate information for current location
dwSize = sizeof( LINELOCATIONENTRY );
lpLocLst = (LPLINELOCATIONENTRY) ( (LPSTR) lpTransCaps +
lpTransCaps-> dwLocationListOffset );
for ( dwInd = 0; dwInd < lpTransCaps-> dwNumLocations ; dwInd++ )
{
if ( lpLocLst[ dwInd ].dwPermanentLocationID == lpTransCaps-> dwCurrentLocationID )
break;
}
// current location no found ?????
// login error
if ( dwInd == lpTransCaps-> dwNumLocations )
{
goto error;
}
// construct canonical form as
szCanNumber[ 0 ]= '\0';
lstrcat( szCanNumber, "+1 (" );
lstrcat( szCanNumber, (LPSTR) lpTransCaps + lpLocLst[ dwInd ].dwCityCodeOffset );
lstrcat( szCanNumber, ") " );
lstrcat( szCanNumber, szDigits );
cPos = strcspn( szNumber, "|" );
if ( cPos != lstrlen( szNumber ) )
{
lstrcat( szCanNumber, &(szNumber[ cPos ]) );
}
bRes = TRUE;
break;
}
case EXTENDED_LONG_DISTANCE_NUMBER:
{
// Long distance number ( 10 digits) preceeded by a 0/1
// Strip leading 0/1 and treat as a long distance number
if ( szDigits[ 0 ] == '0' || szDigits[ 0 ] == '1' )
{
nLenDigits--;
memmove( szDigits, &(szDigits[1]), nLenDigits );
szDigits[ nLenDigits ] = '\0';
cPos = strcspn( szPref, "01" );
nLenPref--;
memmove( &(szPref[ cPos ]), &(szPref[ cPos + 1 ]), nLenPref - cPos );
szPref[ nLenPref ] = '\0';
}
else
{
goto error;
}
}
case LONG_DISTANCE_NUMBER:
{
// if first or fourth digit is 0/1, illegal number
if ( szDigits[ 0 ] == '0' || szDigits[ 0 ] == '1' ||
szDigits[ 3 ] == '0' || szDigits[ 3 ] == '1' )
{
goto error;
}
szCanNumber[ 0 ] = '\0';
lstrcat( szCanNumber, "+1 (" );
strncat( szCanNumber, szDigits, 3 );
lstrcat( szCanNumber, ") " );
lstrcat( szCanNumber, &(szDigits[ 3 ]) );
bRes = TRUE;
}
break;
default :
goto error;
}
error:
if ( lpTransOut )
DialerFree( lpTransOut );
if ( lpTransCaps )
DialerFree( lpTransCaps );
return bRes;
}
/*
*Name :
*AmpersandCompensate
*
*Arguements :
*lpszSrc:Src string containing &s
*lpszDst:Dest string
*
*Return :
*
*Comments :
*Copies string pointed to by lpszSrc to lpszDst character by
*character. If an & is encountered in this process in lpszSrc
*it is copied as && into lpszDst.
*Assumes lpszDst and lpszSrc are of size TAPIMAXCALLEDPARTYSIZE
*/
VOID AmpersandCompensate ( LPCSTR lpszSrc, LPSTR lpszDst )
{
// check if the name has an & in it. If so replace
// it with &&.
INT cCnt, cInd;
for ( cCnt = 0, cInd = 0;
cInd < TAPIMAXCALLEDPARTYSIZE;
cInd++, cCnt++ )
{
if ( lpszSrc[ cCnt ] == '&' )
{
lpszDst[ cInd++ ] = '&';
}
lpszDst[ cInd ] = lpszSrc[ cCnt ];
if ( lpszSrc[ cCnt ] == '\0' )
break;
}
// make sure string is null terminated.
lpszDst[ TAPIMAXCALLEDPARTYSIZE - 1 ] = '\0';
return;
}
/*
*Name :
*AmpersandDeCompensate
*
*Arguements :
*lpszSrc:Src string containing &s
*lpszDst:Dest string
*
*Return :
*
*Comments :
*Copies string pointed to by lpszSrc to lpszDst character by
*character. If an && is encountered in this process in lpszSrc
*it is copied as & into lpszDst.
*Assumes lpszDst and lpszSrc are of size TAPIMAXCALLEDPARTYSIZE
*/
VOID AmpersandDeCompensate ( LPCSTR lpszSrc, LPSTR lpszDst )
{
// check if the name has an & in it. If so replace
// it with &&.
INT cCnt, cInd;
for ( cCnt = 0, cInd = 0;
cInd < TAPIMAXCALLEDPARTYSIZE;
cInd++, cCnt++ )
{
if ( ( lpszSrc[ cInd ] == '&' ) &&
( lpszSrc[ cInd + 1 ] == '&' ) )
{
cInd++;
}
lpszDst[ cCnt ] = lpszSrc[ cInd ] ;
if ( lpszSrc [ cInd ] == '\0' )
{
break;
}
}
lpszDst[ TAPIMAXCALLEDPARTYSIZE - 1 ] = '\0';
return;
}