📄 answer.c
字号:
/*
Answering Machine
*/
#include "netfone.h"
// #define SCREENSHOT // Define SCREENSHOT for canned values in dialogue for screen shots
#define userIdMax 1024 // Maximum user identity field
#define answerBufferSize (2048 + userIdMax) // Buffer for reading message file
#ifdef answerBufferSize
static char answerBuffer[answerBufferSize];
#endif
char answerFileName[MAX_PATH] = ""; // Answering machine file name
char answerOutFileName[MAX_PATH] = ""; // Answering machine outgoing message file name
int answerRecord = TRUE; // Record incoming messages
static FILE *answerFile = NULL; // Answering machine file descriptor
static long answerLen; // Length of answering machine file
static long answerPlayPos; // Current replay address
static int replaying = FALSE; // Nonzero when replay is active
static int currentMessage; // Current message being replayed
static time_t lastPacket = 0; // Time of last packet recorded
static long *msgTable = NULL; // Pointers to messages in file
static int msgMax = 0; // Message table size
static int msgCount = 0; // Messages currently in table
#define newMessageCriterion 2 // Gap length, in seconds, defining a new message
/* SETMESSAGECOUNT -- If answering machine is displayed, update the
number of messages in the file. */
static void setMessageCount(void)
{
if (hDlgAnswer != NULL) {
char mno[24];
if (currentMessage >= 0) {
wsprintf(mno, Format(42), currentMessage + 1, msgCount);
} else {
if (msgCount > 1) {
wsprintf(mno, Format(43), msgCount);
} else {
strcpy(mno, msgCount == 1 ? rstring(IDS_T_ONE_MESSAGE) :
rstring(IDS_T_NO_MESSAGES));
}
}
SetDlgItemText(hDlgAnswer, IDC_RP_MSGBOX, mno);
}
}
// GROWMESSAGETABLE -- Expand in-memory message table if needed
static int growMessageTable(HWND hwnd, int currentMessage)
{
long *oldmsgTable; // In case the ReAlloc fails.
if (currentMessage >= msgMax) {
msgMax += 50;
oldmsgTable = msgTable;
msgTable = GlobalReAllocPtr(msgTable, msgMax * sizeof(long), 0);
if (msgTable == NULL) {
MessageBox(hwnd, rstring(IDS_T_EXPAND_MSG_TABLE_ERR),
NULL, MB_OK | MB_ICONEXCLAMATION);
/* At this point, the re-allocation failed (out of memory, etc.),
* but we still have the first few messages in memory. So, let's
* point back to the old location. -BCW 05/26/1999
*/
msgTable = oldmsgTable;
return FALSE;
}
}
return TRUE;
}
/* ANSWERRESETFOCUS -- If you should happen to disable a control
which had the current keyboard focus, what
do you think Windows does? Advance to the
next enabled control in the tab order? No.
The disabled control continues to suck and
discard all keyboard input *even keyboard
shortcuts to other controls*! In other words,
disabling the current focus control completely
breaks keyboard navigation. To make sure this
doesn't happen to us, after an operation which
might disable the currently active control, we
go through plausible new focus controls trying
to find one that's enabled. If none are, we
set focus to the Close box, which is always
enabled, a motion to adjourn always being in
order. */
static void answerResetFocus(HWND hwnd)
{
int buttonPushed;
HWND fw = GetFocus();
if ((fw == NULL) || (!IsWindowEnabled(fw))) {
if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_NEXT))) {
buttonPushed = IDC_RP_NEXT;
} else if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_PREV))) {
buttonPushed = IDC_RP_PREV;
} else if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_REPLAY))) {
buttonPushed = IDC_RP_REPLAY;
} else {
buttonPushed = IDOK;
}
SetFocus(GetDlgItem(hwnd, buttonPushed));
}
}
/* ANSWEROPEN -- Open the answering machine file. */
int answerOpen(void)
{
answerFile = fopen(answerFileName, "r+b");
if (answerFile == NULL) {
answerFile = fopen(answerFileName, "w+b");
}
if (answerFile != NULL) {
#ifdef answerBufferSize
setvbuf(answerFile, answerBuffer, _IOFBF, sizeof answerBuffer);
#endif
fseek(answerFile, 0L, 2);
answerLen = ftell(answerFile);
rewind(answerFile);
}
replaying = FALSE;
return answerFile != NULL;
}
// ANSWERENABLED -- Determine if recording messages is possible
int answerEnabled(void)
{
return answerFile != NULL;
}
/* ANSWERSAVE -- If the answering machine is on, save a sound
buffer in the answering machine file. */
void answerSave(struct in_addr IPaddr, LPSTR hostName, soundbuf *sb)
{
if (answerRecord && answerFile != NULL) {
struct respHeader r;
char lh[userIdMax];
long scomp, acomp;
fseek(answerFile, answerLen, 0);
r.hostIPnumber = IPaddr;
r.itemTime = time(NULL);
r.hostNameLength = lstrlen(hostName) + 1;
r.soundBufLength = (WORD) (sb->buffer.buffer_len + (sizeof(soundbuf) - BUFL));
fwrite(&r, sizeof r, 1, answerFile);
memcpy(lh, hostName, r.hostNameLength);
fwrite(lh, r.hostNameLength, 1, answerFile);
scomp = sb->compression;
acomp = sb->compression = fProtocol | fPlayback | (((r.itemTime - lastPacket) > newMessageCriterion) ?
fAnsNewMsg : 0) /* | (scomp & fComp2X) */ ;
lastPacket = r.itemTime;
fwrite(sb, r.soundBufLength, 1, answerFile);
if ((hDlgAnswer != NULL) && (sb->compression & fAnsNewMsg) &&
(msgTable != NULL)) {
if (growMessageTable(hDlgAnswer, msgCount + 1)) {
msgTable[msgCount++] = answerLen;
setMessageCount();
}
}
// When a new message is received, set the tray icon (if any) blinking
if (sb->compression & fAnsNewMsg) {
blinkTrayIcon(TRUE); // Blink tray icon to indicate new message
}
sb->compression = scomp;
answerLen = ftell(answerFile);
/* If the answering machine dialogue is displayed, enable
the "Next" and "Erase" buttons since a new message has
arrived. */
if (hDlgAnswer != NULL) {
EnableWindow(GetDlgItem(hDlgAnswer, IDC_RP_NEXT), answerLen > 0);
EnableWindow(GetDlgItem(hDlgAnswer, IDC_RP_ERASE), answerLen > 0);
answerResetFocus(hDlgAnswer);
}
/* If "Open on new answering machine message" is enabled, when
a new message arrives, first pop up the main window and
activate it, if necessary, then post a message to display
the answering machine if it isn't already open. */
if (openOnAnswerMessage && (acomp & fAnsNewMsg)) {
if (IsIconic(hwndMDIFrame)) {
ShowWindow(hwndMDIFrame, SW_SHOWNORMAL);
} else {
// SetWindowPos(hwndMDIFrame, HWND_TOP,
// 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
SetForegroundWindow(hwndMDIFrame);
}
if (hDlgAnswer == NULL) {
PostMessage(hwndMDIFrame, WM_COMMAND, IDM_CO_REPONDEUR, 0);
}
}
}
}
/* ANSWERSYNC -- Make sure output data are written to file. */
void answerSync(void)
{
if (answerFile != NULL) {
fflush(answerFile);
}
}
/* ANSWERCLOSE -- Close the answering machine. */
void answerClose(void)
{
if (answerFile != NULL) {
fclose(answerFile);
answerFile = NULL;
}
}
/* ANSWERREPLAY -- Begin replay of answering machine. */
static void answerReplay(void)
{
answerSync();
replaying = TRUE;
}
/* ANSWERREAD -- Read the next buffer from the answering machine. */
static int answerRead(struct in_addr *IPaddr, time_t *rtime,
char *hostName, soundbuf *sb)
{
struct respHeader r;
fseek(answerFile, answerPlayPos, 0);
if (fread(&r, sizeof r, 1, answerFile) != 1) {
return FALSE;
}
*IPaddr = r.hostIPnumber;
*rtime = r.itemTime;
if (fread(hostName, r.hostNameLength, 1, answerFile) != 1) {
return FALSE;
}
if (fread(sb, r.soundBufLength, 1, answerFile) != 1) {
return FALSE;
}
answerPlayPos = ftell(answerFile);
return TRUE;
}
/* ANSWERREPLAYDONE -- End replay of answer file. */
static void answerReplayDone(void)
{
replaying = FALSE;
answerPlayPos = 0;
}
// SCANMESSAGEFILE -- Built in-memory message table
static void scanMessageFile(HWND hwnd)
{
struct in_addr IPaddr;
char hostName[userIdMax];
time_t t;
long lp;
answerPlayPos = 0;
msgCount = 0;
if (answerFile != NULL) {
while (lp = answerPlayPos, answerRead(&IPaddr, &t, hostName, &ebuf)) {
if (ebuf.compression & fAnsNewMsg) {
if (!growMessageTable(hwnd, msgCount + 1)) {
return;
}
msgTable[msgCount++] = lp;
}
}
answerPlayPos = 0;
}
}
// ANSWERCLEARMESSAGEINFO -- Clear current message identity fields
static void answerClearMessageInfo(HWND hwnd)
{
#ifndef SCREENSHOT
SetDlgItemText(hwnd, IDC_RP_SITE, "");
SetDlgItemText(hwnd, IDC_RP_IP_ADDRESS, "");
SetDlgItemText(hwnd, IDC_RP_EMAIL, "");
SetDlgItemText(hwnd, IDC_RP_USER_NAME, "");
SetDlgItemText(hwnd, IDC_RP_TIME, "");
SetDlgItemText(hwnd, IDC_RP_CALL_IP, rstring(IDS_T_RP_CALL_IP));
SetDlgItemText(hwnd, IDC_RP_CALL_DOMAIN_NAME, rstring(IDS_T_RP_CALL_DOMAIN_NAME));
SetDlgItemText(hwnd, IDC_RP_LOOK_UP_USER, rstring(IDS_T_RP_LOOK_UP_USER));
EnableWindow(GetDlgItem(hwnd, IDC_RP_CALL_IP), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_RP_CALL_DOMAIN_NAME), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_RP_LOOK_UP_USER), FALSE);
#endif
}
// ANSWERUPDATEMESSAGEINFO -- Update identity information for current message
static void answerUpdateMessageInfo(HWND hwnd, time_t *t,
struct in_addr *IPaddr, char *hostName)
{
char ft[1024];
struct tm *lt;
char *email = NULL, *uname = NULL;
lt = localtime(t);
sprintf(ft, Format(49), rstring(IDS_WEEKDAYS + lt->tm_wday),
lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday,
lt->tm_hour, lt->tm_min, lt->tm_sec);
SetDlgItemText(hwnd, IDC_RP_TIME, ft);
#ifndef SCREENSHOT
if ((email = strchr(hostName, ';')) != NULL) {
*email = 0;
email++;
if ((uname = strchr(email, ';')) != NULL) {
*uname = 0;
uname++;
}
}
SetDlgItemText(hwnd, IDC_RP_SITE, hostName);
SetDlgItemText(hwnd, IDC_RP_EMAIL, (email == NULL) ? "" : email);
SetDlgItemText(hwnd, IDC_RP_USER_NAME, (uname == NULL) ? "" : uname);
SetDlgItemText(hwnd, IDC_RP_IP_ADDRESS, inet_ntoa(*IPaddr));
wsprintf(ft, Format(85), inet_ntoa(*IPaddr));
SetDlgItemText(hwnd, IDC_RP_CALL_IP, ft);
EnableWindow(GetDlgItem(hwnd, IDC_RP_CALL_IP), TRUE);
if (strlen(hostName) == 0) {
SetDlgItemText(hwnd, IDC_RP_CALL_DOMAIN_NAME, rstring(IDS_T_RP_CALL_DOMAIN_NAME));
EnableWindow(GetDlgItem(hwnd, IDC_RP_CALL_DOMAIN_NAME), FALSE);
} else {
wsprintf(ft, Format(87), hostName);
SetDlgItemText(hwnd, IDC_RP_CALL_DOMAIN_NAME, ft);
EnableWindow(GetDlgItem(hwnd, IDC_RP_CALL_DOMAIN_NAME), TRUE);
}
if (email == NULL) {
SetDlgItemText(hwnd, IDC_RP_LOOK_UP_USER, rstring(IDS_T_RP_LOOK_UP_USER));
EnableWindow(GetDlgItem(hwnd, IDC_RP_LOOK_UP_USER), FALSE);
} else {
wsprintf(ft, Format(86), email);
SetDlgItemText(hwnd, IDC_RP_LOOK_UP_USER, ft);
EnableWindow(GetDlgItem(hwnd, IDC_RP_LOOK_UP_USER), TRUE);
}
#endif
}
// ANSWERDLGPROC -- Answering machine dialogue procedure
BOOL CALLBACK answerDlgProc(HWND hwnd, UINT nMessage,
WPARAM wParam, LPARAM lParam)
{
static int replaying;
static int firstPacket, hostShown, hostPrelim;
static int buttonPushed;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -