📄 spaceedit.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: SpaceEdit.c,v 1.14 2002/11/19 00:47:51 wjb Exp $
This is a Unicode version of Bill Blanke's original SpaceEdit subclass
code. This version stores the passphrase internally as a wide char
(UCS-2) string and converts it to/from UTF-8 and local code page format
as appropriate.
Also, this version handles all drawing of the text to the screen. This
allows better non-ASCII support on Win9x platforms and also avoids
giving the passphrase string to the RichEdit control where it may be
susceptible to being left in memory somewhere.
____________________________________________________________________________*/
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"
#include "richedit.h"
#include "pgpKeys.h"
#include "pgpConfig.h"
#include "pgpErrors.h"
#include "pgpEncode.h"
#include "pgpUtilities.h"
#include "pflPrefTypes.h"
#include "pgpPubTypes.h"
#include "pgpPassphraseUtils.h"
#include "pgpUnicode.h"
#include "pgpUnicodeWin32.h"
#include "SpaceEdit.h"
#define SE_BUFSIZE 255
typedef struct _SE
{
HWND hwndEdit;
BOOL bUnicodeOS;
BOOL bGotLanguageNotification;
BOOL bHideTyping;
BOOL bFocused;
BOOL bShowWarning;
WNDPROC wpOrigProc;
WCHAR wszRealText[SE_BUFSIZE +1];
PGPInt16 iNumSpaces[SE_BUFSIZE +1];
int iLen;
int iCaretHeight;
int iRowHeight;
POINT ptCaret;
RECT rcClient;
int iCharSet;
DWORD dwSpecialKey;
DWORD dwQuality;
HDC hdcMem;
HBITMAP hbmMem;
int iMaxLen;
USERCALLBACK UserCallback;
void * pUserValue;
} SE,*SEP;
//_________________________________________________
#if PGP_SDK_AVAILABLE
VOID*
SEsecAlloc (PGPContextRef context, UINT uBytes)
{
PGPMemoryMgrRef memmgr;
memmgr = PGPPeekContextMemoryMgr (context);
return (PGPNewSecureData (memmgr, uBytes, 0));
}
VOID
SEsecFree (VOID* p, UINT uBytes)
{
if (p)
{
FillMemory ((char *)p, uBytes, '\0');
PGPFreeData ((char *)p);
}
}
#endif
static void
sCalculateEstimatedQuality (SEP sep)
{
#if PGP_SDK_AVAILABLE
INT i;
char szRealText[SE_BUFSIZE +1];
PGPUInt32 ucopied;
///>>> fix this function!!!
// "de-obfuscate" the string for computing quality
for (i=0; i<sep->iLen ;i++)
sep->wszRealText[i]^=sep->iNumSpaces[i];
pgpUCS2StringToUTF8( sep->wszRealText, sep->iLen, szRealText, sizeof(szRealText)-1, &ucopied );
sep->dwQuality = ucopied ? pgpEstimatePassphraseQuality (szRealText) : 0;
memset(szRealText, 0, sizeof(szRealText));
// "re-obfuscate" the string
for (i=0; i<sep->iLen ;i++)
sep->wszRealText[i]^=sep->iNumSpaces[i];
#endif
}
// quick and dirty function to convert language ID to character set.
static INT
sGetCharset (VOID)
{
DWORD dwLang = (DWORD)GetKeyboardLayout (0);
dwLang = LOWORD (dwLang);
switch (dwLang) {
case 0x0408 :
return GREEK_CHARSET;
case 0x040D :
return HEBREW_CHARSET;
case 0x0419 :
return RUSSIAN_CHARSET;
case 0x041E :
return THAI_CHARSET;
case 0x041F :
return TURKISH_CHARSET;
case 0x042A :
return VIETNAMESE_CHARSET;
case 0x0812 :
return JOHAB_CHARSET;
default :
if ((dwLang & 0xFF) == 0x01)
return ARABIC_CHARSET;
else if ((dwLang & 0xFF) == 0x04)
return CHINESEBIG5_CHARSET;
else
return ANSI_CHARSET;
}
}
static void
sCheckCaps (SEP sep)
{
if (GetKeyState(VK_CAPITAL) & 1)
{
sep->bShowWarning=TRUE;
if(sep->UserCallback)
(sep->UserCallback)(sep->hwndEdit,sep->pUserValue);
}
else
{
sep->bShowWarning=FALSE;
if(sep->UserCallback)
(sep->UserCallback)(sep->hwndEdit,sep->pUserValue);
}
}
static void
sDrawText (
HDC hdc,
SEP sep)
{
HFONT hFont, hFontOld;
int i, ich, iYOffset;
WCHAR wch;
SIZE size;
if (sep->bUnicodeOS)
{
hFont = GetStockObject (DEFAULT_GUI_FONT);
}
else
{
LOGFONT lf;
ZeroMemory (&lf, sizeof(lf));
lf.lfHeight = -MulDiv(8, GetDeviceCaps (hdc, LOGPIXELSY), 72);
lf.lfCharSet = sep->iCharSet;
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
hFont = CreateFontIndirect (&lf);
}
hFontOld = SelectObject (sep->hdcMem, hFont);
iYOffset = 0;
start:
FillRect (sep->hdcMem, &sep->rcClient, (HBRUSH)(COLOR_WINDOW+1));
sep->ptCaret.x = 0;
sep->ptCaret.y = -iYOffset;
for (i=0; i<sep->iLen; i++)
{
if (sep->bHideTyping)
{
ich = (sep->iNumSpaces[i] & 0x03) +1;
wch = 0x20;
}
else
{
ich = 1;
wch = sep->wszRealText[i]^sep->iNumSpaces[i];
}
while (--ich >= 0)
{
GetTextExtentPoint32W (sep->hdcMem, &wch, 1, &size);
if (sep->ptCaret.x + size.cx >= sep->rcClient.right)
{
sep->ptCaret.x = 0;
sep->ptCaret.y += sep->iRowHeight;
if (sep->ptCaret.y + sep->iRowHeight > sep->rcClient.bottom)
{
sep->ptCaret.y -= sep->iRowHeight;
iYOffset += sep->iRowHeight;
goto start;
}
ExtTextOutW (sep->hdcMem, sep->ptCaret.x, sep->ptCaret.y,
ETO_CLIPPED, &sep->rcClient, &wch, 1, NULL);
}
else
{
ExtTextOutW (sep->hdcMem, sep->ptCaret.x, sep->ptCaret.y,
ETO_CLIPPED, &sep->rcClient, &wch, 1, NULL);
}
sep->ptCaret.x += size.cx;
}
}
SelectObject (sep->hdcMem, hFontOld);
BitBlt (hdc,
sep->rcClient.left, sep->rcClient.top,
sep->rcClient.right-sep->rcClient.left,
sep->rcClient.bottom-sep->rcClient.top,
sep->hdcMem, 0, 0, SRCCOPY);
}
// ______________________________________
//
// Tab focus to next or previous control on basis of shift key
static VOID
sTabToNextControl (
HWND hwndOrig)
{
UINT uDir = GW_HWNDNEXT;
UINT uReset = GW_HWNDFIRST;
HWND hwnd1, hwnd2;
if (GetKeyState (VK_SHIFT) & 0x8000)
{
uDir = GW_HWNDPREV;
uReset = GW_HWNDLAST;
}
hwnd1 = hwndOrig;
do
{
hwnd2 = GetNextWindow (hwnd1, uDir);
if (hwnd2 == NULL)
hwnd2 = GetNextWindow (hwnd1, uReset);
if (hwnd2 == NULL)
return;
if (GetWindowLong (hwnd2, GWL_STYLE) & WS_TABSTOP)
{
if (IsWindowEnabled (hwnd2))
{
SetFocus (hwnd2);
return;
}
}
hwnd1 = hwnd2;
} while (hwnd2 != hwndOrig);
}
// ______________________________________
//
// common message procedure for Unicode and ANSI versions
static BOOL
sCommonMsgProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam,
LRESULT* plResult)
{
*plResult = 0;
switch (uMsg)
{
case WM_INPUTLANGCHANGE :
{
SEP sep = (SEP)GetWindowLong (hWnd, GWL_USERDATA);
sep->iCharSet = LOWORD(wParam);
sep->bGotLanguageNotification = TRUE;
InvalidateRect (hWnd, NULL, FALSE);
return FALSE;
}
case WM_SETFOCUS :
{
SEP sep = (SEP)GetWindowLong (hWnd, GWL_USERDATA);
sep->bFocused = TRUE;
CreateCaret (hWnd, NULL, 0, sep->iCaretHeight);
ShowCaret (hWnd);
InvalidateRect (hWnd, NULL, FALSE);
return TRUE;
}
case WM_GETDLGCODE :
*plResult = DLGC_WANTTAB|DLGC_WANTCHARS;
return TRUE;
case WM_KILLFOCUS :
{
SEP sep = (SEP)GetWindowLong (hWnd, GWL_USERDATA);
sep->bFocused = FALSE;
DestroyCaret ();
return TRUE;
}
case WM_LBUTTONDOWN:
{
SetFocus (hWnd);
return TRUE;
}
case WM_KEYUP:
{
SEP sep = (SEP)GetWindowLong (hWnd, GWL_USERDATA);
sCheckCaps (sep);
switch (wParam)
{
case VK_HOME :
case VK_END :
case VK_UP :
case VK_DOWN :
case VK_LEFT :
case VK_RIGHT :
case VK_NEXT :
case VK_PRIOR :
return TRUE;
case VK_BACK :
{
SEP sep = (SEP)GetWindowLong (hWnd, GWL_USERDATA);
if (sep->iLen > 0)
return TRUE;
break;
}
}
break;
}
case WM_RBUTTONDOWN:
case WM_LBUTTONDBLCLK :
case WM_MOUSEMOVE :
case WM_COPY :
case WM_CUT :
case WM_PASTE :
case WM_CLEAR :
return TRUE;
case WM_KEYDOWN :
{
switch (wParam)
{
case VK_HOME :
case VK_END :
case VK_UP :
case VK_DOWN :
case VK_LEFT :
case VK_RIGHT :
case VK_NEXT :
case VK_PRIOR :
return TRUE;
case VK_TAB :
sTabToNextControl (hWnd);
return TRUE;
case VK_BACK :
{
SEP sep = (SEP)GetWindowLong (hWnd, GWL_USERDATA);
if (sep->iLen > 0)
return TRUE;
break;
}
}
break;
}
case WM_GETTEXT :
{
return TRUE;
}
case WM_PAINT :
{
SEP sep = (SEP)GetWindowLong (hWnd, GWL_USERDATA);
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint (hWnd, &ps);
if (hdc)
{
sDrawText (hdc, sep);
EndPaint (hWnd, &ps);
if (sep->bFocused)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -