Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

716 lines
20 KiB

#include "precomp.h"
/************************************************************************/
/* */
/* Windows Cardfile - Written by Mark Cliggett */
/* (c) Copyright Microsoft Corp. 1985, 1994 - All Rights Reserved */
/* */
/************************************************************************/
#if !defined(UNICODE) && defined(JAPAN)
/* Edit Control tune up routine */
WORD NEAR PASCAL EatOneCharacter(HWND);
/*
* routine to retrieve WM_CHAR from the message queue associated with hwnd.
* this is called by EatString.
*/
WORD NEAR PASCAL EatOneCharacter(hwnd)
register HWND hwnd;
{
MSG msg;
register int i = 10;
while (!PeekMessage (&msg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE))
{
if (--i == 0)
return -1;
Yield ();
}
return (msg.wParam & 0x00FF);
}
BOOL FAR PASCAL EatString(HWND,LPSTR,WORD);
/*
* This routine is called when the Edit Control receives WM_IME_REPORT
* with IR_STRINGSTART message. The purpose of this function is to eat
* all WM_CHARs between IR_STRINGSTART and IR_STRINGEND and to build a
* string block.
*/
BOOL FAR PASCAL EatString(hwnd, lpSp, cchLen)
register HWND hwnd;
LPSTR lpSp;
WORD cchLen;
{
MSG msg;
int i = 10; /* loop counter for avoid infinite loop */
int w;
*lpSp = '\0';
if (cchLen < 4)
return NULL; /* not enough */
cchLen -= 2;
while (i--)
{
while (PeekMessage (&msg, hwnd, NULL, NULL, PM_REMOVE))
{
i = 10;
switch (msg.message)
{
case WM_CHAR:
*lpSp++ = (BYTE)msg.wParam;
cchLen--;
if (IsDBCSLeadByte((BYTE)msg.wParam))
{
if ((w = EatOneCharacter(hwnd)) == -1)
{
/* Bad DBCS sequence - abort */
lpSp--;
goto WillBeDone;
}
*lpSp++ = (BYTE)w;
cchLen--;
}
if (cchLen <= 0)
goto WillBeDone; /* buffer exhausted */
break;
case WM_IME_REPORT:
if (msg.wParam == IR_STRINGEND)
{
if (cchLen <= 0)
goto WillBeDone; /* no more room to stuff */
if ((w = EatOneCharacter(hwnd)) == -1)
goto WillBeDone;
*lpSp++ = (BYTE)w;
if (IsDBCSLeadByte((BYTE)w))
{
if ((w = EatOneCharacter(hwnd)) == -1)
{
/* Bad DBCS sequence - abort */
lpSp--;
goto WillBeDone;
}
*lpSp++ = (BYTE)w;
}
goto WillBeDone;
}
/* Fall through */
default:
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
}
}
}
/* We don't get WM_IME_REPORT + IR_STRINGEND
* But received string will be OK
*/
WillBeDone:
*lpSp = '\0';
return TRUE;
}
#endif
#ifdef WIN32
/* These are C equivalents to functions that were in INDOS2.ASM */
VOID RepMov(
LPBYTE lpDest,
LPBYTE lpSrc,
UINT n)
{
while (n--)
{
*lpDest++ = *lpSrc++;
}
}
VOID RepMovDown(
LPBYTE lpDest,
LPBYTE lpSrc,
UINT n)
{
lpDest += n;
lpSrc += n;
lpDest--;
lpSrc--;
while (n--)
{
*lpDest-- = *lpSrc--;
}
}
#endif
NOEXPORT BOOL NEAR CardKey( INT wParam);
/*
* Hook Proc for the multi line Edit control.
* In picture mode,
* WM_SETCURSOR - sets the arrow cursor,
* mouse msgs - responds to left button down, up, dbl click and mouse move
* WM_KEYDOWN - responds to VK_UP/DOWN/LEFT/RIGHT/INSERT/DELETE
* In text mode,
* implements hot key to move to a card(e.g. using Ctrl+A, goto first/last/
* next/prev card), by responding to WM_CHAR and WM_KEYDOWN.
*/
LONG EditWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LONG lParam)
{
PAINTSTRUCT ps;
#if !defined(UNICODE) && defined(JAPAN)
LPSTR lpP;
HANDLE hMem;
HANDLE hClipSave;
#endif
switch (message) {
#if !defined(UNICODE) && defined(JAPAN)
/*
*
*
*
*/
case WM_IME_REPORT:
if (EditMode != I_TEXT)
break;
switch (wParam)
{
case IR_STRING:
/*OutputDebugString("IR_STRING\r\n");*/
if (lpP = (LPSTR) GlobalLock((HANDLE)lParam))
{
CallWindowProc(lpEditWndProc, hwnd, EM_REPLACESEL, 0, (DWORD)lpP);
GlobalUnlock((HANDLE)lParam);
return 1L; /* processed */
}
break;
case IR_STRINGSTART:
/* OutputDebugString("IR_STRINGSTART\r\n"); */
if ((hMem = GlobalAlloc(GMEM_MOVEABLE, 512)) == NULL)
{
/* OutputDebugString("Ga failed\r\n");*/
goto PassMessageOn;
}
if ((lpP = (LPSTR) GlobalLock(hMem)) == NULL)
{
/* OutputDebugString("Lock failed\r\n"); */
GlobalFree(hMem);
goto PassMessageOn;
}
if (EatString(hwnd, lpP, 512))
{
/* OutputDebugString("Eat ok\r\n"); */
CallWindowProc(lpEditWndProc, hwnd, EM_REPLACESEL, 0, (DWORD)lpP);
GlobalUnlock(hMem);
GlobalFree(hMem);
break;
}
GlobalUnlock(hMem);
GlobalFree(hMem);
}
break;
#endif
case WM_DROPFILES:
DoDragDrop(hwnd, (HANDLE)wParam, TRUE);
break;
case WM_SETCURSOR:
/* use arrow cursor when in picture mode */
if (EditMode == I_OBJECT)
SetCursor(hArrowCurs);
else
goto PassMessageOn;
break;
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_MOUSEMOVE:
case WM_LBUTTONUP:
if (EditMode == I_OBJECT)
BMMouse(hwnd, message, wParam, MYMAKEPOINT(lParam));
else /* In text mode, pass it to edit control */
goto PassMessageOn;
break;
case WM_CHAR:
/* In text mode, Ctrl+'char' acts as a hot key to move to a
* specific card. Respond to Ctrl+'A' etc */
if (!CardChar(wParam) && (EditMode == I_TEXT))
/* If it doesn't move our object, pass it to edit control */
goto PassMessageOn;
break;
case WM_KEYDOWN:
/* In text mode, respond to Ctrl+HOME, Ctrl+END(move to first/last card),
* VK_NEXT/VK_PRIOR(goto next and prev cards).
* In picture mode, respond to VK_UP/DOWN/LEFT/RIGHT/VK_INSERT/VK_DELETE
* keys */
if (!CardKey(wParam) && (EditMode == I_TEXT))
/* If it doesn't affect our object, ... */
goto PassMessageOn;
break;
case WM_PAINT:
BeginPaint(hwnd, &ps);
CallWindowProc((WNDPROC)lpEditWndProc, hEditWnd, message, (LONG)ps.hdc, 0L);
CardPaint(ps.hdc);
EndPaint(hwnd, &ps);
break;
default:
PassMessageOn:
return CallWindowProc((WNDPROC)lpEditWndProc, hEditWnd, message, wParam, lParam);
}
return(0L);
}
/*
* Responds to WM_KEYDOWN message.
* In text mode,
* Ctrl+HOME/END - goto first/last card
* VK_PRIOR/NEXT - goto previous/next card
*
* In picture mode,
* VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_INSERT, VK_DELETE handled
* in BMKey
*/
NOEXPORT BOOL NEAR CardKey( INT wParam)
{
switch(wParam)
{
case VK_HOME:
/* Home Beginning of line (don't process)
* Shft+Home Extend selection to beg. of line (don't process)
* Ctrl+Home Go to first card (process here)
*/
if (GetKeyState(VK_CONTROL) >= 0)
return(FALSE);
ScrollCards(hCardWnd, SB_THUMBPOSITION, 0);
break;
case VK_END:
/* End End of line (don't process)
* Shft+End Extend selection to end of line (don't process)
* Ctrl+End Go to last card (process here)
*/
if (GetKeyState(VK_CONTROL) >= 0)
return(FALSE);
ScrollCards(hCardWnd, SB_THUMBPOSITION, cCards-1);
break;
case VK_PRIOR:
ScrollCards(hCardWnd, SB_LINEUP, 0);
break;
case VK_NEXT:
ScrollCards(hCardWnd, SB_LINEDOWN, 0);
break;
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
case VK_INSERT:
case VK_DELETE:
if (EditMode == I_TEXT) /* should be handled by the edit control */
return(FALSE);
else
BMKey((WORD) wParam); /* we will handle this */
return(TRUE);
default:
return(FALSE);
}
ScrollCards(hCardWnd, SB_ENDSCROLL, 0);
return(TRUE);
}
/*
* Checks if the user is trying to move to a specific card using a hot key
* e.g. Ctrl+A will move it to a card starting with A
*/
BOOL CardChar(
int ch)
{
int fControl;
LPCARDHEADER Cards;
int i;
int iCard;
fControl = (GetKeyState(VK_CONTROL) < 0) && (GetKeyState(VK_SHIFT) < 0);
if (!fControl || ch >= TEXT(' '))
return(FALSE);
/* convert control char, i.e. from Ctrl+A get 'A' */
ch += TEXT('A') - 1;
Cards = (LPCARDHEADER) GlobalLock(hCards);
for (i = 0, iCard = iFirstCard+1; i < cCards; ++i, iCard++) {
if (iCard == cCards)
iCard = 0;
if ((TCHAR)(DWORD)CharUpper((LPTSTR)(DWORD)(BYTE)*(Cards[iCard].line)) == ch)
break;
}
GlobalUnlock(hCards);
if (i < cCards) /* make sure a card was found */
ScrollCards(hCardWnd, SB_THUMBPOSITION, iCard);
return(TRUE);
}
/*
* this paints the bitmap in the edit window.
*/
void CardPaint(
HDC hDC)
{
RECT rc;
if (CardPhone == PHONEBOOK || /* list mode */
!CurCard.lpObject || /* no object to draw */
fInsertComplete == FALSE) /* InsertObject in progress */
{
return;
}
Hourglass(TRUE);
/* If RECT is null, reget scaled object size */
/* This will never happen with a plain static BITMAP */
if (!CurCard.rcObject.right)
{
if (OleQueryBounds(CurCard.lpObject, &rc) != OLE_OK)
{
Hourglass(FALSE);
ErrorMessage(E_BOUNDS_QUERY_FAILED);
return;
}
FixBounds(&rc);
SetRect(&(CurCard.rcObject),
CurCard.rcObject.left, CurCard.rcObject.top,
CurCard.rcObject.left + (rc.right - rc.left),
CurCard.rcObject.top + (rc.bottom - rc.top));
}
/* Draw the object */
PicDraw(&CurCard, hDC, FALSE);
Hourglass(FALSE);
}
/*
* Delete the ith card by removing its header
*/
void DeleteCard(
int iCard)
{
LPCARDHEADER Cards;
cCards--;
Cards = (LPCARDHEADER) GlobalLock(hCards);
RepMov((LPBYTE)&Cards[iCard], (LPBYTE)&Cards[iCard+1], (cCards-iCard)*sizeof(CARDHEADER));
GlobalUnlock(hCards);
InitPhoneList(hListWnd, iFirstCard);
}
/*
* Add a card in order in the card array.
*/
int AddCurCard(
void)
{
LPCARDHEADER Cards;
int i;
Cards = (LPCARDHEADER) GlobalLock(hCards);
for (i = 0; i < cCards; i++)
{
if (lstrcmp(CurCardHead.line, Cards[i].line) <= 0)
break;
}
if (i != cCards)
RepMovDown((LPBYTE)&Cards[i+1], (LPBYTE)&Cards[i], (cCards - i) * sizeof(CARDHEADER));
Cards[i] = CurCardHead;
GlobalUnlock(hCards);
cCards++;
/* Set highlight to the new card */
InitPhoneList(hListWnd, i);
return(i);
}
/*
* save CurCardHead and assorted things??
*/
BOOL SaveCurrentCard(
int iCard)
{
LPCARDHEADER Cards;
/* save the card if it's dirty */
/* dirty if bitmap has changed or edittext has changed */
if (CurCardHead.flags & (FDIRTY+FNEW) || SendMessage(hEditWnd, EM_GETMODIFY, 0, 0L))
{
/* get modified text from edit window */
GetWindowText(hEditWnd, szText, CARDTEXTSIZE);
if (WriteCurCard(&CurCardHead, &CurCard, szText))
{
if (CurCardHead.flags & FDIRTY || SendMessage(hEditWnd, EM_GETMODIFY, 0, 0L))
fFileDirty = TRUE;
SendMessage(hEditWnd, EM_SETMODIFY, FALSE, 0L);
CurCardHead.flags &= (!FNEW);
CurCardHead.flags &= (!FDIRTY);
CurCardHead.flags |= FTMPFILE;
Cards = (LPCARDHEADER) GlobalLock(hCards);
Cards[iCard] = CurCardHead;
GlobalUnlock(hCards);
}
else
return(FALSE);
}
if (CurCard.lpObject)
PicDelete(&CurCard);
return(TRUE);
}
/*
* make card # iCard the current (editable and displayed) card
*
* copy the header into CurCardHead (from global memory)
* copy the bitmap into CurCard (from the file)
* copy the text into the Edit window (from the file)
*
*/
void SetCurCard(
int iCard)
{
LPCARDHEADER Cards;
/* Setting new card, remove undo possibility... */
DeleteUndoObject();
/* copy the header info */
Cards = (LPCARDHEADER) GlobalLock(hCards);
CurCardHead = Cards[iCard];
GlobalUnlock(hCards);
/* read in the bitmap and text stuff from the file */
if (ReadCurCardData(&CurCardHead, &CurCard, szText))
{
SetEditText(szText);
DoSetHostNames(CurCard.lpObject, CurCard.otObject);
}
}
/*
* Set edit windows text
*/
void SetEditText(
TCHAR *pText)
{
fNeedToUpdateObject = TRUE;
SendMessage(hEditWnd, WM_SETTEXT, 0, (LONG)pText);
}
int iCardStartScroll;
int fScrolling = FALSE;
/*
* scroll through the stack of cards
*
* this gets called when using the scroll bar control
* or when a card is selected by clicking on on or
* when someone presses movement keys
*
* the user can hold down a key or a mouse button and cause repetitive
* scroll messages to be sent. this action will update the headers but
* the edit window should only be updated when the key or mouse is
* released. saving of data also follows this.
* see the fScrolling stuff below.
*
* also note: some routines send SB_THUMBPOS messages here (we won't
* get a SB_ENDSCROLL). This case works because !fScrolling and
* iCardStartScroll gets set correctly.
*/
BOOL ScrollCards(
HWND hWindow,
int cmd,
int pos)
{
int OldFirst = iFirstCard; /* note where we started */
if (cCards < 2)
return TRUE; /* only one card, can't scroll */
/* two states:
fScrolling - we are receiving scroll messages (mouse is not released)
!fScrolling - enter scrolling state, save current position
*/
if (!fScrolling)
{
iCardStartScroll = iFirstCard;
fScrolling = TRUE;
}
switch (cmd)
{
/* these cases always change the card and leave us in
* Scrolling state */
case SB_LINEUP:
iFirstCard--; /* next card */
if (iFirstCard < 0)
iFirstCard = cCards-1;
break;
case SB_LINEDOWN:
iFirstCard++; /* prev card */
if (iFirstCard == cCards)
iFirstCard = 0;
break;
case SB_PAGEUP:
if (cFSHeads == cCards) /* already at top? */
break;
iFirstCard -= cFSHeads;
if (iFirstCard < 0)
iFirstCard += cCards; /* a negative number */
break;
case SB_PAGEDOWN:
if (cFSHeads == cCards) /* already at bottom? */
break;
iFirstCard += cFSHeads;
if (iFirstCard >= cCards)
iFirstCard -= cCards;
break;
/* these cases may change the current card and
* always leave Scrolling state */
case SB_THUMBPOSITION:
iFirstCard = pos; /* for single SB_THUMB calls */
/* fall through... */
case SB_ENDSCROLL:
fScrolling = FALSE; /* leave scrolling mode */
if (iFirstCard != iCardStartScroll)
{
if (SaveCurrentCard(iCardStartScroll))
{
SetCurCard(iFirstCard);
}
else
{
iFirstCard = iCardStartScroll;
return FALSE; /* save failed */
}
}
break;
}
if (iFirstCard != OldFirst) /* did the above change anything? */
{
HDC hDC;
hDC= GetDC( hWindow );
PaintNewHeaders( hDC ); /* yes, so redraw headers */
ReleaseDC( hWindow, hDC );
}
return TRUE; /* sucessful scroll */
}
void DoCutCopy(int event)
{
if (EditMode == I_TEXT)
SendMessage(hEditWnd, event == CUT ? WM_CUT : WM_COPY, 0, 0L);
else if (CurCard.lpObject)
PicCutCopy(&CurCard, (event == CUT));
}
void DoPaste(int event)
{
if (EditMode == I_TEXT) {
if (!SendMessage(hEditWnd, WM_PASTE, 0, 0L))
IndexOkError(ECLIPEMPTYTEXT);
} else
PicPaste(&CurCard, (event == PASTE), 0);
}
/*
* update the text in the card headers
*/
void PaintNewHeaders( HDC hDC )
{
int idCard;
LPCARDHEADER Cards;
LPCARDHEADER lpTCards;
int xCur;
int yCur;
int i;
RECT rect;
DWORD rgbOld;
DWORD rgbTextOld;
HFONT hOldFont;
yCur = yFirstCard - (cScreenHeads - 1) * ySpacing;
xCur = xFirstCard + (cScreenHeads - 1) * (2 * CharFixWidth);
idCard = (iFirstCard + cScreenHeads-1) % cCards;
Cards = (LPCARDHEADER) GlobalLock(hCards);
lpTCards = &Cards[idCard];
hOldFont= SelectObject(hDC, hFont); // use our selected font
/* for all cards with headers showing */
rgbOld = SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
rgbTextOld = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
for (i = 0; i < cScreenHeads; i++) /* cScreenHeads */
{
SetRect(&rect, xCur+1, yCur+1, xCur+CardWidth-1, yCur+ySpacing);
ExtTextOut(hDC,
xCur+1, yCur+1+(ExtLeading/2),
ETO_OPAQUE|ETO_CLIPPED, // use background color as fill
&rect, // clipping rect
lpTCards->line, // title
lstrlen(lpTCards->line), // length of title
NULL); // interchar spacing
xCur -= (2*CharFixWidth);
yCur += ySpacing;
lpTCards--;
idCard--;
if (idCard < 0)
{
idCard = cCards - 1;
lpTCards = &Cards[idCard];
}
}
SetBkColor(hDC, rgbOld);
SetTextColor(hDC, rgbTextOld);
SelectObject(hDC, hOldFont);
GlobalUnlock(hCards);
}