📄 dialer.c
字号:
/*++
Copyright 1996 - 1999 Microsoft Corporation
Module Name:
dialer.c
--*/
#include "dialer.h"
#include "string.h"
#include "stdlib.h"
#include "shellapi.h"
#define ISDIGIT(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 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 = (HLINEAPP)((ULONG_PTR)NULL); // Dialer's usage handle (regist. w/TAPI)
HCALL ghCall = (HCALL)((ULONG_PTR)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.
BOOL gfMakeCallReplyPending = 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -