📄 face.c
字号:
/*
Show Your Face
*/
#include "netfone.h"
char faceFileName[MAX_PATH] = ""; // Face image file name
int faceShow = TRUE; // Show faces ?
HFILE faceFile = HFILE_ERROR; // Face image file handle
// CLOSEFACEFILE -- Close face file (if open)
void closeFaceFile(void)
{
if (faceFile != HFILE_ERROR) {
_lclose(faceFile);
faceFile = HFILE_ERROR;
}
}
/* OPENFACEFILE -- Open face file and validate it's
in a compatible format. */
int openFaceFile(HWND hwnd)
{
closeFaceFile();
if (faceFileName[0] != 0) {
faceFile = _lopen(faceFileName, OF_READ);
if (faceFile == HFILE_ERROR) {
MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(65), (LPSTR) faceFileName);
} else {
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bmi;
_lread(faceFile, &bfh, sizeof bfh);
if (_fstrncmp((char *) &bfh, "GIF87a", 6) == 0 ||
_fstrncmp((char *) &bfh, "GIF89a", 6) == 0) {
return TRUE;
}
if (_fstrncmp((char *) &bfh, "BM", 2) == 0) {
_lread(faceFile, &bmi, sizeof(BITMAPINFOHEADER));
if (bmi.biBitCount == 8 && bmi.biCompression == BI_RGB &&
bmi.biClrUsed <= 256 && bmi.biPlanes == 1) {
return TRUE;
}
}
MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(66), (LPSTR) faceFileName);
closeFaceFile();
}
return FALSE;
}
return TRUE;
}
/* PROCESSFACEREQUEST -- Process a face request packet and place
the reply in the same packet. */
void processFaceRequest(soundbuf *d)
{
long l;
// Request for face data
if (faceFile != HFILE_ERROR) {
_llseek(faceFile, d->buffer.buffer_len, 0);
*((long *) d->buffer.buffer_val) = htonl(d->buffer.buffer_len);
l = _lread(faceFile, d->buffer.buffer_val + sizeof(long),
512 - (sizeof(long) + (sizeof(soundbuf) - BUFL)));
d->compression = fProtocol | fFaceData | faceReply;
l += sizeof(long);
} else {
// No face file. Shut down requestor.
d->compression = fProtocol | fFaceData | faceLess;
l = 0;
}
#ifdef TRACE_FACE
{
char s[132];
wsprintf(s, "Face data request for %ld, returned %ld\r\n",
ntohl(*((long *) d->buffer.buffer_val)), l);
OutputDebugString(s);
}
#endif
d->buffer.buffer_len = l;
}
// FACEDLGPROC -- Face dialogue procedure
BOOL CALLBACK faceDlgProc(HWND hwnd, UINT nMessage,
WPARAM wParam, LPARAM lParam)
{
switch (nMessage) {
case WM_INITDIALOG:
SetDlgItemText(hwnd, IDC_FA_FILENAME, faceFileName);
CheckDlgButton(hwnd, IDC_FA_SHOW, faceShow);
return TRUE;
case WM_CLOSE:
DestroyWindow(hwnd);
return TRUE;
case WM_COMMAND:
switch ((short) WM_COMMAND_ID(wParam)) {
case IDC_FA_CLEAR:
SetDlgItemText(hwnd, IDC_FA_FILENAME, "");
break;
case IDC_FA_BROWSE:
{
OPENFILENAME ofn;
char szString[MAX_PATH];
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = rfilter(IDS_T_FACE_FILE_FILTER);
ofn.lpstrCustomFilter = NULL;
strcpy(szString, faceFileName);
ofn.lpstrFile = (LPSTR) szString;
ofn.nMaxFile = sizeof(szString);
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = rstring(IDS_T_FACE_OPEN_TITLE);
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_SHOWHELP;
fileHelpKey = rstring(IDS_HELP_FACE);
if (GetOpenFileName((LPOPENFILENAME) &ofn)) {
SetDlgItemText(hwnd, IDC_FA_FILENAME, szString);
}
}
break;
case IDOK:
{
char sff[MAX_PATH];
_fstrcpy(sff, faceFileName);
GetDlgItemText(hwnd, IDC_FA_FILENAME,
faceFileName, sizeof faceFileName);
if (!openFaceFile(hwnd)) {
/* Don't let user exit until a valid (or no)
face file is specified. */
_fstrcpy(faceFileName, sff);
break;
}
faceShow = IsDlgButtonChecked(hwnd, IDC_FA_SHOW);
EndDialog(hwnd, TRUE);
}
break;
case IDCANCEL:
EndDialog(hwnd, FALSE);
break;
case ID_HELP:
WinHelp(hwndMDIFrame, rstring(IDS_HELPFILE), HELP_KEY,
((DWORD) (Lrstring(IDS_HELP_FACE))));
holped = TRUE;
break;
}
return FALSE;
default:
if (nMessage == fileOpenHelpButton && fileHelpKey != NULL) {
WinHelp(hwndMDIFrame, rstring(IDS_HELPFILE), HELP_KEY,
((DWORD) (LPSTR) fileHelpKey));
holped = TRUE;
}
break;
}
return FALSE;
}
// FACEDIALOGUE -- Face configuration dialogue
int faceDialogue(HWND hWndParent)
{
int result;
result = DialogBox(hInst, MAKEINTRESOURCE(IDD_FACE), hWndParent, faceDlgProc);
return result;
}
/* PROCESSFACEDATA -- Process a buffer-full of face image data
received for a connection. */
void processFaceData(HWND hwnd, LPCLIENT_DATA c, soundbuf *d)
{
if (d->compression & faceReply) {
// Face data packet received from remote server
if (d->buffer.buffer_len > sizeof(long)) {
long lp = ntohl(*((long *) d->buffer.buffer_val));
BITMAPFILEHEADER FAR *bfh;
if (lp == c->face_address) {
if (lp == 0) {
if (c->face_bmp != NULL) {
GlobalFreePtr(c->face_bmp);
}
c->face_bmp = NULL;
bfh = (BITMAPFILEHEADER *) (d->buffer.buffer_val + sizeof(long));
if (_fstrncmp((LPSTR) &bfh->bfType, "GIF87a", 6) == 0 ||
_fstrncmp((LPSTR) &bfh->bfType, "GIF89a", 6) == 0) {
/* GIF files don't tell us up-front how long they're
going to be. We initially allocate a 16K block (big
enough to hold the majority of face GIFs), then expand
it in increments of 16K if more data than that arrives. */
c->face_file_length = 16384L;
c->face_is_gif = TRUE;
} else {
if (_fstrncmp((LPSTR) &bfh->bfType, "BM", 2) != 0) {
#ifdef TRACE_FACE
char s[132];
wsprintf(s, "Face image is not a Windows bitmap or GIF file\r\n");
OutputDebugString(s);
#endif
}
if ((DWORD) (d->buffer.buffer_len - sizeof(long)) > bfh->bfSize) {
#ifdef TRACE_FACE
char s[132];
wsprintf(s, "Bogus size %ld in face bitmap\r\n", bfh->bfSize);
OutputDebugString(s);
#endif
c->face_stat = FSabandoned;
return;
}
c->face_file_length = bfh->bfSize;
c->face_is_gif = FALSE;
}
c->face_bmp = GlobalAllocPtr(GPTR, c->face_file_length);
if (c->face_bmp == NULL) {
#ifdef TRACE_FACE
char s[132];
wsprintf(s, "Cannot allocate %ld bytes for face bitmap\r\n", c->face_file_length);
OutputDebugString(s);
#endif
c->face_stat = FSabandoned;
return;
}
#ifdef TRACE_FACE
{
char s[132];
wsprintf(s, "Receiving %ld byte face bitmap\r\n", c->face_file_length);
OutputDebugString(s);
}
#endif
_fmemcpy(c->face_bmp, d->buffer.buffer_val + sizeof(long),
(int) d->buffer.buffer_len - sizeof(long));
c->face_address += d->buffer.buffer_len - sizeof(long);
c->face_stat = FSreply;
c->face_retry = 0;
return;
}
bfh = (BITMAPFILEHEADER FAR *) c->face_bmp;
if ((c->face_address + (d->buffer.buffer_len - sizeof(long))) >
(unsigned long) (c->face_file_length)) {
if (c->face_is_gif) {
#ifdef TRACE_FACE
char s[132];
wsprintf(s, "Expanding GIF buffer to %ld bytes.\r\n",
c->face_file_length + 16384L);
OutputDebugString(s);
#endif
c->face_bmp = GlobalReAllocPtr(c->face_bmp, c->face_file_length +
16384L, 0);
if (c->face_bmp == NULL) {
// Couldn't expand face bitmap buffer
c->face_stat = FSabandoned;
#ifdef TRACE_FACE
{
char s[132];
wsprintf(s, "Out of memory trying to expand GIF buffer to %ld bytes.\r\n",
c->face_file_length);
OutputDebugString(s);
}
#endif
return;
}
c->face_file_length += 16384L;
} else {
#ifdef TRACE_FACE
char s[132];
wsprintf(s, "Address %ld plus buffer length %ld overflows %ld byte bitmap\r\n",
c->face_address, d->buffer.buffer_len - sizeof(long), bfh->bfSize);
OutputDebugString(s);
#endif
GlobalFreePtr(c->face_bmp);
c->face_bmp = NULL;
c->face_stat = FSabandoned;
return;
}
}
#ifdef TRACE_FACE
{ char s[132];
wsprintf(s, "Storing %ld bytes at %ld in face bitmap\r\n",
d->buffer.buffer_len - sizeof(long), lp);
OutputDebugString(s);
}
#endif
_fmemcpy(c->face_bmp + c->face_address,
d->buffer.buffer_val + sizeof(long),
(int) (d->buffer.buffer_len - sizeof(long)));
c->face_address += d->buffer.buffer_len - sizeof(long);
/* Timeout will make next request after the
configured interval. */
c->face_stat = FSreply;
c->face_retry = 0;
} else {
#ifdef TRACE_FACE
{ char s[132];
wsprintf(s, "Discarded %ld bytes for %ld in face bitmap, expected data for %ld\r\n",
d->buffer.buffer_len - sizeof(long),
lp, c->face_address);
OutputDebugString(s);
}
#endif
}
} else {
BITMAPINFOHEADER FAR *bmi;
int bx, by;
RECT cr, wr;
#ifdef TRACE_FACE
{ char s[132];
wsprintf(s, "Face bitmap complete\r\n");
OutputDebugString(s);
}
#endif
/* If the file we received is in GIF format, convert it
to a BMP file. */
if (c->face_is_gif && (c->face_bmp != NULL)) {
LPBYTE cbmp = GIFtoBMP((LPBYTE) c->face_bmp, 1);
GlobalFreePtr(c->face_bmp);
if (cbmp != NULL) {
c->face_bmp = (LPSTR) cbmp;
} else {
c->face_bmp = NULL;
c->face_stat = FSabandoned;
return;
}
}
/* Oops, Mr. Walker forgot to check for NULL face pointer here. Thank God for
debuggers. :) -BCW 03/22/1998 */
if(c->face_bmp == NULL)
{
#ifdef TRACE_FACE
OutputDebugString("Face bitmap: NULL pointer, discarded.\r\n");
#endif
c->face_stat = FSabandoned;
return;
}
/* Now let's perform some rudimentary verification
of the format of this bitmap and ditch it if it's
bogus. */
bmi = (BITMAPINFOHEADER FAR *) (c->face_bmp + sizeof(BITMAPFILEHEADER));
if (bmi->biPlanes != 1 || bmi->biBitCount != 8 ||
bmi->biCompression != BI_RGB || bmi->biClrUsed > 256) {
#ifdef TRACE_FACE
OutputDebugString("Face bitmap: invalid format, discarded.\r\n");
#endif
GlobalFreePtr(c->face_bmp);
c->face_bmp = NULL;
c->face_stat = FSabandoned;
return;
}
c->face_stat = FScomplete;
// Resize window so that client area fits bitmap
GetWindowRect(hwnd, &wr);
GetClientRect(hwnd, &cr);
bx = (int) bmi->biWidth;
by = (int) bmi->biHeight;
if (bx != cr.right || by != cr.bottom) {
int bw = bx + ((wr.right - wr.left) - cr.right),
bh = by + ((wr.bottom - wr.top) - cr.bottom);
SetWindowPos(hwnd, HWND_TOP,
0, 0, bw, bh, SWP_NOMOVE | SWP_NOZORDER);
GetClientRect(hwnd, &cr);
#ifdef TRACE_FACE
{ char s[132];
wsprintf(s, "Resizing connection window to %dx%d (W=%dx%d)\r\n",
bx, by, bw, bh);
OutputDebugString("Resizing connection window.\r\n");
}
#endif
}
InvalidateRect(hwnd, NULL, FALSE);
}
} else if (d->compression & faceLess) {
if (c->face_bmp != NULL) {
GlobalFreePtr(c->face_bmp);
c->face_bmp = NULL;
}
c->face_stat = FSabandoned;
#ifdef TRACE_FACE
{ char s[MAX_HOST + 80];
wsprintf(s, "No face image available from %s\r\n", c->szHost);
OutputDebugString(s);
}
#endif
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -