|
|
/*++
Copyright (c) 1991-1997, Microsoft Corporation All rights reserved.
Module Name:
charmap.c
Abstract:
This module contains the main routines for the Charmap utility, an interface for selecting special characters.
Revision History:
--*/
//
// Include Files.
//
#define WIN31
#include "windows.h"
#include <port1632.h>
#include "charmap.h"
#include "stdlib.h"
#include "tchar.h"
#ifdef UNICODE
#include "wchar.h"
#else
#include "stdio.h"
#endif
#include "commctrl.h"
#include <htmlhelp.h>
//
// Macros.
//
#define FMagData(psycm) ((psycm)->xpMagCurr != 0)
#define abs(x) (((x) >= 0) ? (x) : (-(x)))
//
// Constant Declarations.
//
#define STATUSPOINTSIZE 8 // point size of status bar font
#define FE_STATUSPOINTSIZE 10 // FE point size of status bar font
#define DX_BITMAP 20 // width of TT bitmap
#define DY_BITMAP 12 // height of TT bitmap
#define BACKGROUND 0x000000FF // bright blue
#define BACKGROUNDSEL 0x00FF00FF // bright purple
#define BUTTONFACE 0x00C0C0C0 // bright grey
#define BUTTONSHADOW 0x00808080 // dark grey
#define TOOLBARPOINTSIZE 21 // height of toolbar in points
// Font types
#define PS_OPENTYPE_FONT 0x0001
#define TT_OPENTYPE_FONT 0x0002
#define TRUETYPE_FONT 0x0004
#define TYPE1_FONT 0x0008
//
// Debug Print Code.
//
#if 0
TCHAR szDOUT[3] = TEXT("A\n"); TCHAR szDbgBuf[256]; #define DOUTL(p) OutputDebugString(TEXT(p))
#define DOUTCHN(ch) if(0){}else {szDOUT[0] = ch; OutputDebugString(szDOUT);}
#define DPRINT(p) if(0){}else {wsprintf p; OutputDebugString(szDbgBuf);}
#else
#define DOUTL(p)
#define DOUTCHN(ch)
#define DPRINT(p)
#endif
//
// Global Variables.
//
HANDLE hInst;
INT cchSymRow = 32; // number of characters across the character grid
INT cchSymCol = 8; // number of rows in the character grid
UTCHAR chSymFirst = 32; UTCHAR chSymLast = 255; UTCHAR chRangeFirst = 32; UTCHAR chRangeLast = 255; SYCM sycm; // tons of data need to do char grid painting
WORD wCFRichText = 0; // private clipboard format, rich text format
HFONT hFontClipboard = NULL; // tells us which font is in the clipboard
HANDLE hstrClipboard = NULL; // contains the string which is in the clipboard
BOOL fDelClipboardFont = FALSE; // the clipboard font needs to be deleted
INT iControl = ID_CHARGRID; // index indicating which control has focus
HBITMAP hbmFont = NULL; // TT bitmap drawn before font facenames in combo
LONG lEditSel = 0; // contains the selection range of the EC
HBRUSH hStaticBrush; // used for static controls during WM_CTLCOLOR
//
// Currently there is no defined interface for querying what character
// ranges a Unicode font supports. For now, this table only has the subsets
// that contain characters supported by the Lucida Sans Unicode font
// uncommented. When we get an API that allows querying the font driver for
// ranges of Unicode characters supported (and whether or not a font is a
// Unicode font!) then all entries can be uncommented.
//
USUBSET aSubsetData[] = { { 0x0020, 0x00ff, IDS_WINDOWS }, { 0x0020, 0x00ff, IDS_LATIN1 }, { 0x0100, 0x017f, IDS_LATINEXA }, { 0x0180, 0x024f, IDS_LATINEXB }, { 0x0250, 0x02af, IDS_IPAEX }, { 0x02b0, 0x02ff, IDS_SPACINGMODIFIERS }, { 0x0300, 0x036f, IDS_COMBININGDIACRITICS }, { 0x0370, 0x03cf, IDS_BASICGREEK }, { 0x03d0, 0x03ff, IDS_GREEKSYMBOLS }, { 0x0400, 0x04ff, IDS_CYRILLIC }, { 0x0530, 0x058f, IDS_ARMENIAN }, { 0x0590, 0x05ff, IDS_HEBREW }, { 0x0600, 0x0652, IDS_BASICARABIC }, { 0x0653, 0x06ff, IDS_ARABICEX }, { 0x0900, 0x097f, IDS_DEVANAGARI }, { 0x0980, 0x09ff, IDS_BENGALI }, { 0x0a00, 0x0a7f, IDS_GURMUKHI }, { 0x0a80, 0x0aff, IDS_GUJARATI }, { 0x0b00, 0x0b7f, IDS_ORIYA }, { 0x0b80, 0x0bff, IDS_TAMIL }, { 0x0c00, 0x0c7f, IDS_TELUGU }, { 0x0c80, 0x0cff, IDS_KANNADA }, { 0x0d00, 0x0d7f, IDS_MALAYALAM }, { 0x0e00, 0x0e7f, IDS_THAI }, { 0x0e80, 0x0eff, IDS_LAO }, { 0x10d0, 0x10ff, IDS_BASICGEORGIAN }, { 0x10a0, 0x10cf, IDS_GEORGIANEX }, { 0x1100, 0x11ff, IDS_HANGULJAMO }, { 0x1e00, 0x1eff, IDS_LATINEXADDITIONAL }, { 0x1f00, 0x1fff, IDS_GREEKEX }, { 0x2000, 0x206f, IDS_GENERALPUNCTUATION }, { 0x2070, 0x209f, IDS_SUPERANDSUBSCRIPTS }, { 0x20a0, 0x20cf, IDS_CURRENCYSYMBOLS }, { 0x20d0, 0x20ff, IDS_COMBININGDIACRITICSFORSYMBOLS }, { 0x2100, 0x214f, IDS_LETTERLIKESYMBOLS }, { 0x2150, 0x218f, IDS_NUMBERFORMS }, { 0x2190, 0x21ff, IDS_ARROWS }, { 0x2200, 0x22ff, IDS_MATHEMATICALOPS }, { 0x2300, 0x23ff, IDS_MISCTECHNICAL }, { 0x2400, 0x243f, IDS_CONTROLPICTURES }, { 0x2440, 0x245f, IDS_OPTICALCHAR }, { 0x2460, 0x24ff, IDS_ENCLOSEDALPHANUM }, { 0x2500, 0x257f, IDS_BOXDRAWING }, { 0x2580, 0x259f, IDS_BLOCKELEMENTS }, { 0x25a0, 0x25ff, IDS_GEOMETRICSHAPES }, { 0x2600, 0x26ff, IDS_MISCDINGBATS }, { 0x2700, 0x27bf, IDS_DINGBATS }, { 0x3000, 0x303f, IDS_CJKSYMBOLSANDPUNC }, { 0x3040, 0x309f, IDS_HIRAGANA }, { 0x30a0, 0x30ff, IDS_KATAKANA }, { 0x3100, 0x312f, IDS_BOPOMOFO }, { 0x3130, 0x318f, IDS_HANGULCOMPATIBILITYJAMO }, { 0x3190, 0x319f, IDS_CJKMISC }, { 0x3200, 0x32ff, IDS_ENCLOSEDCJKLETTERSANDMONTHS }, { 0x3300, 0x33ff, IDS_CJKCOMPATIBILITY }, { 0x4e00, 0x9fff, IDS_CJKUNIFIEDIDEOGRAPHS }, { 0xac00, 0xd7a3, IDS_HANGUL }, { 0xe000, 0xf8ff, IDS_PRIVATEUSEAREA }, { 0xf900, 0xfaff, IDS_CJKCOMPATIBILITYIDEOGRAPHS }, { 0xfb00, 0xfb4f, IDS_ALPAHPRESENTATIONFORMS }, { 0xfb50, 0xfdff, IDS_ARABICPRESENTATIONFORMSA }, { 0xfe30, 0xfe4f, IDS_CJKCOMPFORMS }, { 0xfe50, 0xfe6f, IDS_SMALLFORMVARIANTS }, { 0xfe70, 0xfefe, IDS_ARABICPRESENTATIONFORMSB }, { 0xff00, 0xffef, IDS_HALFANDFULLWIDTHFORMS }, { 0xfff0, 0xfffd, IDS_SPECIALS } }; INT cSubsets = sizeof(aSubsetData) / sizeof(USUBSET); INT iCurSubset = 0; // index of current Unicode subset - default to Latin-1
//
// Useful window handles.
//
HWND hwndDialog; HWND hwndCharGrid;
//
// Data used to draw the status bar.
//
RECT rcStatusLine; // bounding rect for status bar
RECT rcToolbar[2]; // bounding rects for toolbars
INT dyStatus; // height of status bar
INT dyToolbar[2]; // height of tool bars
INT dxHelpField; // width of help window
INT dxKeystrokeField; // width of keystroke window
TCHAR szKeystrokeText[MAX_PATH]; // buffer for keystroke text
TCHAR szKeystrokeLabel[30]; // buffer for keystroke label
TCHAR szSpace[15]; // strings for keystroke description
TCHAR szCtrl[15]; TCHAR szCtrlAlt[25]; TCHAR szShiftCtrlAlt[25]; TCHAR szAlt[15]; TCHAR szUnicodeLabel[23]; // buffer for Unicode label
INT iKeystrokeTextStart; // place to start appending text to above
INT iUnicodeLabelStart; // place to start appending text to above
HFONT hfontStatus; // font used for text of status bar
////////////////////////////////////////////////////////////////////////////
//
// WinMain
//
// Calls initialization function, processes message loop, cleanup.
//
////////////////////////////////////////////////////////////////////////////
INT WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg;
if (!InitApplication(hInstance)) { return (FALSE); }
//
// Perform initialization for this instance.
//
if (!InitInstance(hInstance, nCmdShow)) { return (FALSE); }
while (GetMessage(&msg, NULL, 0, 0)) { //
// Filter for possible tabs now to implement context sensitive help.
//
if (msg.message == WM_KEYDOWN) { if (!UpdateHelpText(&msg, NULL)) { continue; } }
//
// Main message loop.
//
if (!IsDialogMessage(hwndDialog, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
//
// Free up some stuff.
//
if (hfontStatus) { DeleteObject(hfontStatus); } if (hbmFont) { DeleteObject(hbmFont); }
return (msg.wParam); }
////////////////////////////////////////////////////////////////////////////
//
// InitApplication
//
// Initializes window data and registers window class.
//
////////////////////////////////////////////////////////////////////////////
BOOL InitApplication( HANDLE hInstance) { WNDCLASS wc;
//
// Register a window class that we will use to draw the character
// grid into.
//
wc.style = CS_DBLCLKS; wc.lpfnWndProc = CharGridWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("CharGridWClass");
if (!RegisterClass(&wc)) { return (FALSE); }
wc.style = 0; wc.lpfnWndProc = DefDlgProc; wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDIC_CHARMAP)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("MyDlgClass");
if (!RegisterClass(&wc)) { return (FALSE); } }
////////////////////////////////////////////////////////////////////////////
//
// InitInstance
//
// Does some initialization and creates main window which is a dialog.
//
////////////////////////////////////////////////////////////////////////////
BOOL InitInstance( HANDLE hInstance, INT nCmdShow) { INT i; CHARSETINFO csi; DWORD dw = GetACP(); LANGID PrimaryLangId = (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()))); BOOL bFE = ((PrimaryLangId == LANG_JAPANESE) || (PrimaryLangId == LANG_KOREAN) || (PrimaryLangId == LANG_CHINESE));
//
// Save the instance handle in a global variable.
//
hInst = hInstance;
//
// This font will be used to paint the status line.
//
if (!TranslateCharsetInfo((DWORD*)dw, &csi, TCI_SRCCODEPAGE)) { csi.ciCharset = ANSI_CHARSET; } hfontStatus = CreateFont( -PointsToHeight(bFE ? FE_STATUSPOINTSIZE : STATUSPOINTSIZE), 0, 0, 0, 400, 0, 0, 0, csi.ciCharset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH, TEXT("MS Shell Dlg") );
dyStatus = 2 * PointsToHeight(STATUSPOINTSIZE); dyToolbar[0] = PointsToHeight(TOOLBARPOINTSIZE); dyToolbar[1] = PointsToHeight(TOOLBARPOINTSIZE);
//
// Load the Unicode subset names before initializing the main window.
//
for (i = 0; i < cSubsets; i++) { if (!LoadString( hInst, aSubsetData[i].StringResId, (LPTSTR)aSubsetData[i].Name, LF_SUBSETSIZE)) { return (FALSE); } }
//
// Create a main window for this application instance.
//
if (!(hwndDialog = CreateDialog( hInstance, TEXT("CharMap"), NULL, CharMapDlgProc ))) { return (FALSE); }
//
// Initialize some strings used for the Keystroke status bar field.
// For international purposes, this string could be length 0.
//
LoadString( hInst, IDS_KEYSTROKE, (LPTSTR)szKeystrokeLabel, BTOC(sizeof(szKeystrokeLabel)) ); if (!LoadString( hInst, IDS_UNICODELABEL, (LPTSTR)szUnicodeLabel, BTOC(sizeof(szUnicodeLabel)) )) { if (!LoadString( hInst, IDS_SPACE, (LPTSTR)szSpace, BTOC(sizeof(szSpace)) )) { return (FALSE); } } if (!LoadString( hInst, IDS_CTRL, (LPTSTR)szCtrl, BTOC(sizeof(szCtrl)) )) { return (FALSE); } if (!LoadString( hInst, IDS_CTRLALT, (LPTSTR)szCtrlAlt, BTOC(sizeof(szCtrlAlt)) )) { return (FALSE); } if (!LoadString( hInst, IDS_SHIFTCTRLALT, (LPTSTR)szShiftCtrlAlt, BTOC(sizeof(szShiftCtrlAlt)) )) { return (FALSE); } if (!LoadString( hInst, IDS_ALT, (LPTSTR)szAlt, BTOC(sizeof(szAlt)) )) { return (FALSE); }
//
// Store the index to where we start adding status line text changes.
//
iKeystrokeTextStart = lstrlen(szKeystrokeLabel); iUnicodeLabelStart = lstrlen(szUnicodeLabel);
//
// Initialize keystroke text, make the window visible,
// update its client area, and return "success".
//
UpdateKeystrokeText(NULL, sycm.fAnsiFont, sycm.chCurr, FALSE); ShowWindow(hwndDialog, nCmdShow); UpdateWindow(hwndDialog);
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// ConvertANSIFontToUnicode
//
////////////////////////////////////////////////////////////////////////////
WCHAR ConvertANSIFontToUnicode( HWND hwnd, HFONT hFont, CHAR ch) { WORD cp = CP_ACP; WCHAR wch; HDC hdc;
hdc = GetDC(hwnd); if (hdc != NULL) { HFONT hfOld; TEXTMETRIC tm; CHARSETINFO csi; DWORD cs;
hfOld = SelectObject(hdc, hFont);
if (GetTextMetrics(hdc, &tm)) { cs = MAKELONG(tm.tmCharSet, 0);
if (TranslateCharsetInfo((DWORD *)cs, &csi, TCI_SRCCHARSET)) { cp = csi.ciACP; } else { DPRINT(( szDbgBuf, TEXT("CvtAtoW: TranslateCharsetInfo(cset=%d) returned 0! (GetLastErr=%d), using CP_ACP\n"), cs, GetLastError() )); } } SelectObject(hdc, hfOld); ReleaseDC(hwnd, hdc); }
if (MultiByteToWideChar(cp, 0, &ch, 1, &wch, 1) != 1) { if (MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1) != 1) { wch = (WCHAR)(BYTE)ch; } }
DPRINT(( szDbgBuf, TEXT("CvtAtoW: 0x%02x '%c' (CP:%d) -> U'%04X'\n"), (DWORD)(BYTE)ch, ch, cp, (DWORD)wch ));
return (wch); }
////////////////////////////////////////////////////////////////////////////
//
// EnumChildProc
//
// Gets called during init for each child window.
//
////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumChildProc( HWND hwnd, LPARAM lParam) { LONG st; TCHAR szClass[MAX_PATH];
//
// Get control class.
//
GetClassName(hwnd, szClass, MAX_PATH); if (lstrcmpi(szClass, TEXT("button")) == 0 ) { //
// If it is a button, set the ex style to NOTIFYPARENT.
//
st = GetWindowLong(hwnd, GWL_EXSTYLE); st = st & ~WS_EX_NOPARENTNOTIFY; SetWindowLong(hwnd, GWL_EXSTYLE, st); }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// CharMapDlgProc
//
// Processes messages for the main window. This window is a dialog box.
//
////////////////////////////////////////////////////////////////////////////
INT_PTR APIENTRY CharMapDlgProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case ( WM_CTLCOLORSTATIC ) : { POINT point;
SetBkColor((HDC)wParam, GetSysColor(COLOR_BTNFACE)); UnrealizeObject(hStaticBrush); point.x = point.y = 0; ClientToScreen(hWnd, &point);
return ((INT_PTR)hStaticBrush); break; } case ( WM_INITDIALOG ) : { RECT rectParent, rectTopRightControl, rect; POINT pt; INT iSubset; HWND hwndCMSB;
//
// Set buttons to send WM_PARENTNOTIFY.
//
EnumChildWindows(hWnd, EnumChildProc, (LPARAM)NULL );
//
// Create the character grid with dimensions which just fit
// inside the space allowed in the dialog. When it processes
// the WM_CREATE message it will be sized and centered more
// accurately.
//
GetClientRect(hWnd, &rectParent); GetWindowRect(GetDlgItem(hWnd, ID_CLOSE), &rectTopRightControl); ScreenToClient(hWnd, (LPPOINT)&(rectTopRightControl.left)); ScreenToClient(hWnd, (LPPOINT)&(rectTopRightControl.right));
if (!(hwndCharGrid = CreateWindow( TEXT("CharGridWClass"), NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 1, rectParent.top + dyToolbar[0] + dyToolbar[1], rectParent.right - 1, rectParent.bottom - rectParent.top - dyStatus - dyToolbar[0] - dyToolbar[1] - 1, hWnd, (HMENU)ID_CHARGRID, hInst, NULL ))) { DestroyWindow(hWnd); break; }
GetWindowRect(hwndCharGrid, &rect); pt.x = rect.right; pt.y = rect.top;
ScreenToClient(hWnd, &pt);
hwndCMSB = CreateWindowEx( 0L, TEXT("SCROLLBAR"), NULL, WS_CHILD | SBS_VERT | WS_VISIBLE | WS_TABSTOP, pt.x + 1, pt.y + 1, sycm.dxpBox, sycm.dypCM, hWnd, (HMENU)ID_MAPSCROLL, hInst, NULL );
hStaticBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
//
// Initialize the status line data.
//
dxHelpField = 21 * rectParent.right / 32; dxKeystrokeField = 9 * rectParent.right / 32; rcStatusLine = rectParent; rcStatusLine.top = rcStatusLine.bottom - dyStatus;
//
// Initialize the toolbars.
//
rcToolbar[0] = rectParent; rcToolbar[0].bottom = rcToolbar[0].top + dyToolbar[0];
rcToolbar[1] = rcToolbar[0]; rcToolbar[1].top = rcToolbar[0].bottom + GetSystemMetrics(SM_CYBORDER); rcToolbar[1].bottom = rcToolbar[1].top + dyToolbar[1];
//
// Disable Copy button.
//
EnableWindow(GetDlgItem(hWnd, ID_COPY), FALSE);
//
// Fill "Subset" list box.
//
for (iSubset = 0; iSubset < cSubsets; iSubset++) { SendDlgItemMessage( hWnd, ID_UNICODESUBSET, CB_ADDSTRING, 0, (DWORD)aSubsetData[iSubset].Name ); } iCurSubset = SelectInitialSubset(hWnd);
//
// Fall through to WM_FONTCHANGE...
//
} case ( WM_FONTCHANGE ) : { HDC hdc = GetDC(hWnd);
//
// Get the fonts from the system and put them in the font
// selection combo box.
//
if (message == WM_FONTCHANGE) { SaveCurrentFont(hWnd); SendDlgItemMessage(hWnd, ID_FONT, CB_RESETCONTENT, 0, 0L); }
EnumFontFamilies(hdc, NULL, (FONTENUMPROC)FontLoadProc, (LPARAM)hWnd);
ReleaseDC(hWnd, hdc);
//
// Setup character dimensions and select this font.
//
RecalcCharMap( hWnd, &sycm, SelectInitialFont(hWnd), (message == WM_FONTCHANGE) ); SetEditCtlFont(hWnd, ID_STRING, sycm.hFont);
if (message == WM_INITDIALOG) { SetFocus(hwndCharGrid);
//
// Fall through to WM_SYSCOLORCHANGE...
//
} else { break; } } case ( WM_SYSCOLORCHANGE ) : { if (hbmFont) { DeleteObject(hbmFont); } hbmFont = LoadBitmaps(IDBM_TT); DeleteObject(hStaticBrush); hStaticBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); break; } case ( WM_PARENTNOTIFY ) : { POINTS points; DWORD dwMsgPos; POINT point;
DPRINT(( szDbgBuf, TEXT("WM_PARENTNOTIFY: lParam:0x%08lX, wParam:0x%08lX\n"), (DWORD)lParam, (DWORD)wParam ));
//
// We process this message to implement the context sensitive
// help. Downclicks to controls are found here, the help
// message is updated in the status bar.
//
// The parameters with this message are unreliable!
//
if (LOWORD(wParam) == WM_LBUTTONDOWN) { dwMsgPos = GetMessagePos(); points = MAKEPOINTS(dwMsgPos); point.x = points.x; point.y = points.y; UpdateHelpText(NULL, WindowFromPoint(point)); }
break; } case ( WM_VSCROLL ) : { ProcessScrollMsg(hWnd, LOWORD(wParam), HIWORD(wParam)); break; } case ( WM_PAINT ) : { HBRUSH hBrush; RECT rcTemp, rectNextButton; INT dyBorder, dxBorder; PAINTSTRUCT ps; HDC hdc;
//
// This code implements painting of the status bar.
//
hdc = BeginPaint(hWnd, &ps);
rcTemp = rcStatusLine;
dyBorder = GetSystemMetrics(SM_CYBORDER); dxBorder = GetSystemMetrics(SM_CXBORDER);
//
// Make the whole thing grey.
//
if (hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))) { FillRect(hdc, &rcTemp, hBrush); rcTemp.left = rcToolbar[0].left; rcTemp.top = rcToolbar[0].top; rcTemp.right = rcToolbar[1].right; rcTemp.bottom = rcToolbar[1].bottom; FillRect(hdc, &rcTemp, hBrush); DeleteObject(hBrush); }
GetWindowRect(GetDlgItem(hWnd, ID_TOPLEFT), &rectNextButton); ScreenToClient(hWnd, (LPPOINT)&(rectNextButton.left)); ScreenToClient(hWnd, (LPPOINT)&(rectNextButton.right)); //
// Solid black line across bottom of toolbar.
//
if (hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWFRAME))) { #ifdef USE_MIRRORING
DWORD dwLayout; GetProcessDefaultLayout(&dwLayout); if(dwLayout & LAYOUT_RTL) { //
// Interchange the right and left values.
//
int tmp = rectNextButton.left; rectNextButton.left = rectNextButton.right; rectNextButton.right = tmp; } #endif
rcTemp = rcToolbar[0]; rcTemp.top = rcTemp.bottom; rcTemp.bottom += dyBorder; rcTemp.left = rectNextButton.left - 2 - dxBorder; FillRect(hdc, &rcTemp, hBrush); rcTemp = rcToolbar[1]; rcTemp.top = rcTemp.bottom; rcTemp.bottom += dyBorder; FillRect(hdc, &rcTemp, hBrush);
//
// Vertical line.
//
rcTemp.top = rcToolbar[0].top; rcTemp.bottom = rcToolbar[1].bottom; rcTemp.left = rectNextButton.left - 2 - dxBorder; rcTemp.right = rectNextButton.left - 2; FillRect(hdc, &rcTemp, hBrush); DeleteObject(hBrush); }
if (hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW))) { //
// Status line top.
//
rcTemp.left = 8 * dyBorder; rcTemp.right = rcTemp.left + dxHelpField; rcTemp.top = rcStatusLine.top + dyBorder * 2; rcTemp.bottom = rcTemp.top + dyBorder; FillRect(hdc, &rcTemp, hBrush);
//
// Keystroke line top.
//
rcTemp.right = rcStatusLine.right - 8 * dyBorder; rcTemp.left = rcTemp.right - dxKeystrokeField; FillRect(hdc, &rcTemp, hBrush);
//
// Status line left side.
//
rcTemp = rcStatusLine; rcTemp.left = 8 * dyBorder; rcTemp.right = rcTemp.left + dyBorder; rcTemp.top += dyBorder * 2; rcTemp.bottom -= dyBorder * 2; FillRect(hdc, &rcTemp, hBrush);
//
// Keystroke line left side.
//
rcTemp.left = rcStatusLine.right - 9 * dyBorder - dxKeystrokeField; rcTemp.right = rcTemp.left + dyBorder; FillRect(hdc, &rcTemp, hBrush);
DeleteObject(hBrush); }
if (hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT))) { //
// Status line bottom.
//
rcTemp.left = 8 * dyBorder; rcTemp.right = rcTemp.left + dxHelpField; rcTemp.top = rcStatusLine.bottom - 3 * dyBorder; rcTemp.bottom = rcTemp.top + dyBorder; FillRect(hdc, &rcTemp, hBrush);
//
// Keystroke line bottom.
//
rcTemp.right = rcStatusLine.right - 8 * dyBorder; rcTemp.left = rcTemp.right - dxKeystrokeField; FillRect(hdc, &rcTemp, hBrush);
//
// Status line right side.
//
rcTemp = rcStatusLine; rcTemp.left = 8 * dyBorder + dxHelpField; rcTemp.right = rcTemp.left + dyBorder; rcTemp.top += dyBorder * 2; rcTemp.bottom -= dyBorder * 2; FillRect(hdc, &rcTemp, hBrush);
//
// Keystroke line right side.
//
rcTemp.left = rcStatusLine.right - 8 * dyBorder; rcTemp.right = rcTemp.left + dyBorder; FillRect(hdc, &rcTemp, hBrush);
DeleteObject(hBrush); }
//
// Solid black line across top.
//
if (hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWFRAME))) { rcTemp = rcStatusLine; rcTemp.bottom = rcTemp.top; rcTemp.top -= dyBorder; FillRect(hdc, &rcTemp, hBrush); DeleteObject(hBrush); }
PaintStatusLine(hdc, TRUE, TRUE);
EndPaint(hWnd, &ps);
return (TRUE); } case ( WM_MEASUREITEM ) : { HDC hDC; HFONT hFont; TEXTMETRIC tm;
hDC = GetDC(NULL); hFont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L); if (hFont) { hFont = SelectObject(hDC, hFont); } GetTextMetrics(hDC, &tm); if (hFont) { SelectObject(hDC, hFont); } ReleaseDC(NULL, hDC);
((LPMEASUREITEMSTRUCT)lParam)->itemHeight = max(tm.tmHeight, DY_BITMAP); break; } case ( WM_DRAWITEM ) : { if (((LPDRAWITEMSTRUCT)lParam)->itemID != -1) { DrawFamilyComboItem((LPDRAWITEMSTRUCT)lParam); } break; } case ( WM_ASKCBFORMATNAME ) : { LoadString(hInst, IDS_RTF, (LPTSTR)lParam, wParam); return (TRUE); } case ( WM_PAINTCLIPBOARD ) : { LPPAINTSTRUCT lpPS; HANDLE hFont; LPTSTR lpstrText;
if (hstrClipboard) { //
// Setup.
//
lpPS = (LPPAINTSTRUCT)GlobalLock((HANDLE)lParam); lpstrText = (LPTSTR)GlobalLock(hstrClipboard);
//
// Paint.
//
hFont = SelectObject(lpPS->hdc, hFontClipboard); TextOut(lpPS->hdc, 0, 0, lpstrText, lstrlen(lpstrText)); SelectObject(lpPS->hdc, hFont);
//
// Cleanup.
//
GlobalUnlock(hstrClipboard); GlobalUnlock((HANDLE)lParam); } return (TRUE); } case ( WM_CLOSE ) : { DestroyWindow(hWnd); return (TRUE); } case ( WM_COMMAND ) : { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case ( IDCANCEL ) : case ( ID_CLOSE ) : { DestroyWindow(hWnd); return (TRUE); break; } case ( ID_SELECT ) : { WCHAR wch = sycm.chCurr;
if (sycm.fAnsiFont) { wch = ConvertANSIFontToUnicode( hWnd, sycm.hFont, (char)wch ); }
SendDlgItemMessage(hWnd, ID_STRING, WM_CHAR, (WPARAM)wch, 0L); break; } case ( ID_COPY ) : { CopyString(hWnd); return (TRUE); break; } case ( ID_FONT ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { RecalcCharMap( hWnd, &sycm, (INT)SendDlgItemMessage( hWnd, ID_FONT, CB_GETCURSEL, 0, 0L ), TRUE ); SetEditCtlFont(hWnd, ID_STRING, sycm.hFont); } else if (HIWORD(wParam) == CBN_SETFOCUS) { //
// Necessary if hotkey is used to get to the CB.
//
UpdateHelpText(NULL, (HWND)lParam); }
return (TRUE); break; } case ( ID_UNICODESUBSET ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { INT iSubset; INT cEntries;
iSubset = (INT)SendDlgItemMessage( hWnd, ID_UNICODESUBSET, CB_GETCURSEL, 0, 0 ); SubSetChanged( hWnd, iSubset, aSubsetData[iSubset].BeginRange, aSubsetData[iSubset].EndRange );
cEntries = (INT)SendDlgItemMessage( hWnd, ID_UNICODESUBSET, CB_GETCOUNT, 0, 0 ) - 1;
EnableWindow( GetDlgItem(hWnd, ID_PREVSUBSET), iSubset > 0 );
EnableWindow( GetDlgItem(hWnd, ID_NEXTSUBSET), iSubset < cEntries ); } else if (HIWORD(wParam) == CBN_SETFOCUS) { //
// Necessary if hotkey is used to get to the CB.
//
UpdateHelpText(NULL, (HWND)lParam); } return (0L); break; } case ( ID_NEXTSUBSET ) : { INT iCurSelection, iNumEntries;
iCurSelection = (INT)SendDlgItemMessage( hWnd, ID_UNICODESUBSET, CB_GETCURSEL, 0, 0 ); if (iCurSelection == CB_ERR) { return (0L); } iNumEntries = (INT)SendDlgItemMessage( hWnd, ID_UNICODESUBSET, CB_GETCOUNT, 0, 0 ); if (iNumEntries == CB_ERR) { return (0L); } if (iCurSelection++ < (iNumEntries - 1)) { if (iCurSelection == 1) { //
// Enable Previous button.
//
EnableWindow(GetDlgItem(hWnd, ID_PREVSUBSET), TRUE); }
SendDlgItemMessage( hWnd, ID_UNICODESUBSET, CB_SETCURSEL, iCurSelection, 0 ); SubSetChanged( hWnd, iCurSelection, aSubsetData[iCurSelection].BeginRange, aSubsetData[iCurSelection].EndRange ); if (iCurSelection == (iNumEntries - 1)) { HWND hwndButton;
EnableWindow(GetDlgItem(hWnd, ID_NEXTSUBSET), FALSE); //
// Only reset the button style and focus if
// the "Next" button currently has it.
//
if (iControl == ID_NEXTSUBSET) { SendDlgItemMessage( hwndDialog, ID_PREVSUBSET, BM_SETSTYLE, BS_DEFPUSHBUTTON, 1 ); SendDlgItemMessage( hwndDialog, ID_NEXTSUBSET, BM_SETSTYLE, BS_PUSHBUTTON, 1 ); hwndButton = GetDlgItem(hWnd, ID_PREVSUBSET); SetFocus(hwndButton); UpdateHelpText(NULL, hwndButton); } } } return (0L); break; } case ( ID_PREVSUBSET ) : { INT iCurSelection;
iCurSelection = (INT)SendDlgItemMessage( hWnd, ID_UNICODESUBSET, CB_GETCURSEL, 0, 0 ); if (iCurSelection == CB_ERR) { return (0L); } if (iCurSelection > 0) { iCurSelection--;
if (iCurSelection == (cSubsets - 2)) { //
// Enable Next button.
//
EnableWindow(GetDlgItem(hWnd, ID_NEXTSUBSET), TRUE); }
SendDlgItemMessage( hWnd, ID_UNICODESUBSET, CB_SETCURSEL, iCurSelection, 0 ); SubSetChanged( hWnd, iCurSelection, aSubsetData[iCurSelection].BeginRange, aSubsetData[iCurSelection].EndRange ); if (iCurSelection == 0) { HWND hwndButton;
EnableWindow(GetDlgItem(hWnd, ID_PREVSUBSET), FALSE); //
// Only reset the button style and focus if
// the "Previous" button currently has it.
//
if (iControl == ID_PREVSUBSET) { SendDlgItemMessage( hwndDialog, ID_NEXTSUBSET, BM_SETSTYLE, BS_DEFPUSHBUTTON, 1 ); SendDlgItemMessage( hwndDialog, ID_PREVSUBSET, BM_SETSTYLE, BS_PUSHBUTTON, 1 ); hwndButton = GetDlgItem(hWnd, ID_NEXTSUBSET); SetFocus(hwndButton); UpdateHelpText(NULL, hwndButton); } } } return (0L); break; } case ( ID_STRING ) : { if (HIWORD(wParam) == EN_SETFOCUS) { //
// Necessary if hotkey is used to get to the EC.
//
UpdateHelpText(NULL, (HWND)lParam); } else if (HIWORD(wParam) == EN_CHANGE) { //
// Disable Copy button if there are no chars in EC.
//
INT iLength;
iLength = GetWindowTextLength((HWND)lParam); EnableWindow(GetDlgItem(hWnd, ID_COPY), (BOOL)iLength); }
break; } case ( ID_HELP ) : { DoHelp(hWnd, TRUE); break; } } break; } case ( WM_DESTROY ) : { SaveCurrentFont(hWnd); SaveCurrentSubset(hWnd); DoHelp(hWnd, FALSE); DeleteObject(hStaticBrush); PostQuitMessage(0); break; } case ( WM_ACTIVATEAPP ) : { if (wParam) { SendDlgItemMessage( hWnd, ID_STRING, EM_SETSEL, LOWORD(lEditSel), HIWORD(lEditSel) ); } else { lEditSel = SendDlgItemMessage(hWnd, ID_STRING, EM_GETSEL, 0, 0L); SendDlgItemMessage(hWnd, ID_STRING, EM_SETSEL, 0, 0L); } break; } }
return (0L); }
////////////////////////////////////////////////////////////////////////////
//
// CharGridWndProc
//
// Processes messages for the character grid window.
//
////////////////////////////////////////////////////////////////////////////
LRESULT APIENTRY CharGridWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case ( WM_CREATE ) : { RECT rect; HDC hdcScrn; POINT point1, point2;
//
// Setup global.
//
hwndCharGrid = hWnd;
GetClientRect(hWnd, &rect);
//
// Calculate metrics for the character grid and the
// magnify window.
//
sycm.dxpBox = (rect.right - 1) / (cchSymRow + 2); sycm.dypBox = (rect.bottom - 2) / (cchSymCol + 1); sycm.dxpCM = sycm.dxpBox * cchSymRow + 1; sycm.dypCM = sycm.dypBox * cchSymCol + 1; // space inside for border
if ((PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) == LANG_CHINESE)) { sycm.dxpMag = sycm.dxpBox * 3 + 5; } else { sycm.dxpMag = sycm.dxpBox * 2 + 4; // twice the size + 2 bit border
} sycm.dypMag = sycm.dypBox * 2 + 4;
sycm.chCurr = chSymFirst; sycm.hFontMag = NULL; sycm.hFont = NULL; sycm.hdcMag = NULL; sycm.hbmMag = NULL; sycm.ypDest = 0;
sycm.fFocusState = sycm.fMouseDn = sycm.fCursorOff = FALSE;
//
// Size the window precisely so the grid fits and is centered.
//
MoveWindow( hWnd, (rect.right - sycm.dxpCM + 1) / 2, (rect.bottom - sycm.dypCM + 1) / 2 + ((LPCREATESTRUCT)lParam)->y - 2, sycm.dxpCM + 2, sycm.dypCM + 2, FALSE );
//
// Figure out what the offsets are between the dialog
// and the character grid window.
//
point1.x = point1.y = point2.x = point2.y = 0; ClientToScreen(hWnd, &point1); ClientToScreen(((LPCREATESTRUCT)lParam)->hwndParent, &point2); #ifdef USE_MIRRORING
sycm.xpCM = (abs(point1.x - point2.x)) - (sycm.dxpMag - sycm.dxpBox) / 2; #else
sycm.xpCM = (point1.x - point2.x) - (sycm.dxpMag - sycm.dxpBox) / 2; #endif
sycm.ypCM = (point1.y - point2.y) - (sycm.dypMag - sycm.dypBox) / 2;
//
// Create dc and bitmap for the magnify window.
//
if ((hdcScrn = GetWindowDC(hWnd)) != NULL) { if ((sycm.hdcMag = CreateCompatibleDC(hdcScrn)) != NULL) { SetTextColor( sycm.hdcMag, GetSysColor(COLOR_WINDOWTEXT) ); SetBkColor( sycm.hdcMag, GetSysColor(COLOR_WINDOW) ); SetBkMode(sycm.hdcMag, OPAQUE); if ((sycm.hbmMag = CreateCompatibleBitmap( hdcScrn, sycm.dxpMag, sycm.dypMag * 2 )) == NULL) { DeleteObject(sycm.hdcMag); } else { SelectObject(sycm.hdcMag, sycm.hbmMag); } } ReleaseDC(hWnd, hdcScrn); } break; } case ( WM_DESTROY ) : { if (sycm.fMouseDn) { ExitMagnify(hWnd, &sycm); } if (fDelClipboardFont) { DeleteObject(hFontClipboard); } if (sycm.hFont != NULL) { DeleteObject(sycm.hFont); } if (sycm.hFontMag != NULL) { DeleteObject(sycm.hFontMag); } if (sycm.hdcMag != NULL) { DeleteDC(sycm.hdcMag); } if (sycm.hbmMag != NULL) { DeleteObject(sycm.hbmMag); } break; } case ( WM_SETFOCUS ) : case ( WM_KILLFOCUS ) : { RestoreSymMag(&sycm); DrawSymChOutlineHwnd( &sycm, hWnd, sycm.chCurr, TRUE, message == WM_SETFOCUS ); break; } case ( WM_LBUTTONDOWN ) : { RECT rect;
DOUTL("WM_LBUTTONDOWN: In\n");
//
// Don't draw anything if there's an update region pending.
//
if (GetUpdateRect(hWnd, (LPRECT)&rect, FALSE) != 0) { DOUTL("WM_LBUTTONDOWN: No upd rect\n"); break; }
SetFocus(hWnd); SetCapture(hWnd);
sycm.fMouseDn = TRUE;
if (!FMagData(&sycm)) { DOUTL("WM_LBUTTONDOWN: Drawing sym outline\n"); DrawSymChOutlineHwnd(&sycm, hWnd, sycm.chCurr, FALSE, FALSE); }
//
// Fall through to WM_MOUSEMOVE...
//
} case ( WM_MOUSEMOVE ) : { DOUTL("WM_MOUSEMOVE: In\n"); if (sycm.fMouseDn) { POINT pt; UINT chMouseSymbol;
DOUTL("WM_MOUSEMOVE: mouse is down\n");
pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); ClientToScreen(hWnd, (LPPOINT)&pt); if (WindowFromPoint(pt) == hWnd) { ScreenToClient(hWnd, (LPPOINT)&pt); //
// Convert back to a 'points'-like thing.
//
lParam = MAKELONG((WORD)pt.x, (WORD)pt.y); chMouseSymbol = (UINT)ChFromSymLParam(&sycm, lParam); if (chMouseSymbol > (UINT)chSymLast) { //
// We're outside of current character range (but
// still within the grid). Restore cursor and
// leave magnified character.
//
if (sycm.fCursorOff) { sycm.fCursorOff = FALSE; ShowCursor(TRUE); } } else { //
// We're in the grid and within the range of currently
// displayed characters, display magnified character.
//
DOUTL("WM_MOUSEMOVE: in grid and subrange\n");
if (!sycm.fCursorOff) { sycm.fCursorOff = TRUE; ShowCursor(FALSE); } DOUTL("WM_MOUSEMOVE: movsymsel "); DOUTCHN( (UTCHAR)chMouseSymbol ); MoveSymbolSel(&sycm, (UTCHAR)chMouseSymbol); } } else { //
// Left grid, leave magnified character and restore
// cursor.
//
if (sycm.fCursorOff) { sycm.fCursorOff = FALSE; ShowCursor(TRUE); } } } DOUTL("WM_MOUSEMOVE: Leaving\n"); break; } case ( WM_CANCELMODE ) : case ( WM_LBUTTONUP ) : { if (sycm.fMouseDn) { ExitMagnify(hWnd, &sycm); } break; } case ( WM_LBUTTONDBLCLK ) : { WCHAR wch = sycm.chCurr;
//
// Send this character to the entry field.
//
if (sycm.fAnsiFont) { wch = ConvertANSIFontToUnicode(hWnd, sycm.hFont, (char)wch); }
SendDlgItemMessage(hwndDialog, ID_STRING, WM_CHAR, (WPARAM)wch, 0L); break; } case ( WM_GETDLGCODE ) : { //
// Necessary to obtain arrow and tab messages.
//
return (DLGC_WANTARROWS | DLGC_WANTCHARS); break; } case ( WM_KEYDOWN ) : { UTCHAR chNew = sycm.chCurr; INT cchMoved;
if (sycm.fMouseDn) { break; }
switch (wParam) { case ( VK_LEFT ) : { if (--chNew < chSymFirst) { return (0L); } break; } case ( VK_UP ) : { if ((chNew -= cchSymRow) < chSymFirst) { if (!ScrollMap(GetParent(hWnd), -cchSymRow, TRUE)) { return (0L); } RestoreSymMag(&sycm); } break; } case ( VK_RIGHT ) : { if (++chNew > chSymLast) { return (0L); } break; } case ( VK_DOWN ) : { if ((chNew += cchSymRow) > chSymLast) { if (!ScrollMap(GetParent(hWnd), cchSymRow, TRUE)) { return (0L); } RestoreSymMag(&sycm); } break; } case ( VK_NEXT ) : { if ((cchMoved = ScrollMapPage(GetParent(hWnd), FALSE, TRUE)) == 0) { return (0L); } //
// We scrolled the map! Bump the char so it is
// still in the window.
//
RestoreSymMag(&sycm); chNew += cchMoved; break; } case ( VK_PRIOR ) : { if ((cchMoved = ScrollMapPage( GetParent(hWnd), TRUE, TRUE )) == 0) { return (0L); }
//
// We scrolled the map! Bump the char so it is
// still in the window.
//
RestoreSymMag(&sycm); chNew += cchMoved; break; } default : { return (0L); } }
if (!FMagData(&sycm)) { DrawSymChOutlineHwnd(&sycm, hWnd, sycm.chCurr, FALSE, FALSE); } MoveSymbolSel(&sycm, (UTCHAR)chNew); break; } case ( WM_CHAR ) : { WCHAR wch = (WCHAR)wParam; char ch;
if (sycm.fMouseDn) { break; } if (sycm.fAnsiFont) { if (WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL ) != 1) { break; } wch = (WCHAR)(BYTE)ch; }
if ((wch >= chSymFirst) && (wch <= chSymLast)) { if (!FMagData(&sycm)) { DrawSymChOutlineHwnd(&sycm, hWnd, sycm.chCurr, FALSE, FALSE); } MoveSymbolSel(&sycm, (UTCHAR)wch); SendDlgItemMessage(hwndDialog, ID_STRING, WM_CHAR, wParam, 0L); } break; } case ( WM_PAINT ) : { HDC hdc; PAINTSTRUCT ps;
DOUTL("WM_PAINT: In\n");
hdc = BeginPaint(hWnd, &ps); DOUTL("WM_PAINT: drawing map\n"); DrawSymbolMap(&sycm, hdc); EndPaint(hWnd, &ps);
DOUTL("WM_PAINT: Leaving\n"); return (TRUE); } default : { return (DefWindowProc(hWnd, message, wParam, lParam)); } }
return (0L); }
////////////////////////////////////////////////////////////////////////////
//
// ProcessScrollMsg
//
////////////////////////////////////////////////////////////////////////////
VOID ProcessScrollMsg( HWND hwndDlg, int nCode, int nPos) { UTCHAR chNew = sycm.chCurr; HWND hwndGrid = GetDlgItem(hwndDlg, ID_CHARGRID); int cchScroll;
switch( nCode ) { case ( SB_LINEUP ) : { cchScroll = -cchSymRow; break; } case ( SB_LINEDOWN ) : { cchScroll = cchSymRow; break; } case ( SB_PAGEUP ) : { cchScroll = (int)TRUE; break; } case ( SB_PAGEDOWN ) : { cchScroll = (int)FALSE; break; } case ( SB_THUMBTRACK ) : case ( SB_THUMBPOSITION ) : { cchScroll = (nPos * cchSymRow + chRangeFirst) - chSymFirst; break; } default : { return; } }
if (nCode == SB_PAGEUP || nCode == SB_PAGEDOWN) { if (!ScrollMapPage(hwndDlg, (BOOL)cchScroll, FALSE)) { return; }
//
// ScrollMapPage will do the right thing to sycm.chCurr.
//
chNew = sycm.chCurr; } else { if (cchScroll == 0 || !ScrollMap(hwndDlg, cchScroll, FALSE)) { return; }
//
// Keep the current symbol inside the window.
//
while (chNew > chSymLast) { chNew -= cchSymRow; }
while (chNew < chSymFirst) { chNew += cchSymRow; } }
#if 0
if (!FMagData(&sycm)) { DrawSymChOutlineHwnd(&sycm, hwndGrid, sycm.chCurr, FALSE, FALSE); } MoveSymbolSel(&sycm, (UTCHAR)chNew); #else
sycm.chCurr = chNew; InvalidateRect(hwndGrid, NULL, TRUE); #endif
}
////////////////////////////////////////////////////////////////////////////
//
// ScrollMapPage
//
// Scrolls the map up or down by a page. See ScrollMap().
//
////////////////////////////////////////////////////////////////////////////
INT ScrollMapPage( HWND hwndDlg, BOOL fUp, BOOL fRePaint) { INT cchScroll = cchFullMap;
if (fUp) { cchScroll = -cchScroll; }
if ((chSymFirst + cchScroll) < chRangeFirst) { cchScroll = (chRangeFirst - chSymFirst); } else if ((chSymLast + cchScroll) > chRangeLast) { cchScroll = (chRangeLast - chSymLast); }
return (ScrollMap(hwndDlg, cchScroll, fRePaint) ? cchScroll : 0); }
////////////////////////////////////////////////////////////////////////////
//
// ScrollMap
//
// Scrolls the map up or down if there are too many chars to fit in the
// chargrid.
//
////////////////////////////////////////////////////////////////////////////
BOOL ScrollMap( HWND hwndDlg, INT cchScroll, BOOL fRePaint) { HWND hwndSB, hwndCharGrid; INT chFirst = chSymFirst + cchScroll; INT chLast = chSymLast + cchScroll; HDC hdc;
if ((chFirst < chRangeFirst) || (chLast > chRangeLast)) { return (FALSE); }
hwndCharGrid = GetDlgItem(hwndDlg, ID_CHARGRID); hwndSB = GetDlgItem(hwndDlg, ID_MAPSCROLL); SetScrollPos(hwndSB, SB_CTL, (chFirst - chRangeFirst) / cchSymRow, TRUE);
UpdateSymbolRange(hwndDlg, chFirst, chLast);
if ((hwndDlg != NULL) && ((hdc = GetDC(hwndDlg)) != NULL)) { LPINT lpdxp; HFONT hFont; UINT ch;
hFont = SelectObject(hdc, sycm.hFont); lpdxp = (LPINT)sycm.rgdxp;
if (sycm.fAnsiFont) { GetCharWidth32A(hdc, chSymFirst, chSymLast, lpdxp); } else { GetCharWidth32(hdc, chSymFirst, chSymLast, lpdxp); }
SelectObject(hdc, hFont);
for (ch = (UINT) chSymFirst; ch <= (UINT) chSymLast; ch++, lpdxp++) { *lpdxp = (sycm.dxpBox - *lpdxp) / 2 - 1; } ReleaseDC(hwndDlg, hdc); }
if (fRePaint) { InvalidateRect(hwndCharGrid, NULL, TRUE); }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// ChFromSymLParam
//
// Determines the character to select from the mouse position (lParam).
//
////////////////////////////////////////////////////////////////////////////
INT ChFromSymLParam( PSYCM psycm, LPARAM lParam) { return (min( cchSymRow - 1, max(0, ((INT)LOWORD(lParam) - 1) / psycm->dxpBox) ) + min( cchSymCol - 1, max(0, ((INT)HIWORD(lParam) - 1) / psycm->dypBox) ) * cchSymRow + chSymFirst); }
////////////////////////////////////////////////////////////////////////////
//
// DrawSymChOutlineHwnd
//
// Gets a DC for hwnd, calls DrawSymChOutline.
//
////////////////////////////////////////////////////////////////////////////
VOID DrawSymChOutlineHwnd( PSYCM psycm, HWND hwnd, UTCHAR ch, BOOL fVisible, BOOL fFocus) { HDC hdc = GetDC(hwnd);
DrawSymChOutline(psycm, hdc, ch, fVisible, fFocus); ReleaseDC(hwnd, hdc); }
////////////////////////////////////////////////////////////////////////////
//
// RecalcCharMap
//
// Recalculates fixed character map data (font info, sizes, etc.).
//
////////////////////////////////////////////////////////////////////////////
VOID RecalcCharMap( HWND hwndDlg, PSYCM psycm, INT iCombo, BOOL fRedraw) { HDC hdc; TEXTMETRIC tm; UINT ch; LPINT lpdxp; HFONT hFont; LOGFONT LogFont; ITEMDATA ItemData; LONG iCurSel;
//
// Get rid of the old font handles.
//
if (hFontClipboard && (hFontClipboard == psycm->hFont)) { fDelClipboardFont = TRUE; } if (psycm->hFont && (hFontClipboard != psycm->hFont)) { DeleteObject(psycm->hFont); } if (psycm->hFontMag) { DeleteObject(psycm->hFontMag); }
hdc = GetDC(hwndCharGrid);
//
// Set up the LogFont structure.
// Make sure it fits in the grid.
//
if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) == LANG_CHINESE) { LogFont.lfHeight = 16; } else { LogFont.lfHeight = psycm->dypBox - 3; // Allow for whitespace.
} //
// Set these to zero.
//
LogFont.lfWidth = LogFont.lfEscapement = LogFont.lfOrientation = LogFont.lfWeight = 0; LogFont.lfItalic = LogFont.lfUnderline = LogFont.lfStrikeOut = LogFont.lfOutPrecision = LogFont.lfClipPrecision = LogFont.lfQuality = LogFont.lfPitchAndFamily = 0;
//
// Let the facename and size define the font.
//
// LogFont.lfCharSet = DEFAULT_CHARSET;
// Work around the GDI bug that assumes the font's default charset
// is always the system default locale.
//
*(DWORD *)&ItemData = SendDlgItemMessage( hwndDlg, ID_FONT, CB_GETITEMDATA, iCombo, 0L ); LogFont.lfCharSet = ItemData.CharSet;
//
// Get the facename from the combo box.
//
SendDlgItemMessage( hwndDlg, ID_FONT, CB_GETLBTEXT, iCombo, (LONG)(LPTSTR)LogFont.lfFaceName );
//
// Enable Block listbox and set defaults appropriately.
//
EnableWindow(GetDlgItem(hwndDlg, ID_UNICODESUBSET), TRUE); iCurSel = SendDlgItemMessage( hwndDlg, ID_UNICODESUBSET, CB_GETCURSEL, 0, 0L ); UpdateSymbolSelection( hwndDlg, aSubsetData[iCurSel].BeginRange, aSubsetData[iCurSel].EndRange ); //
// Enable Previous button if not on first subset.
//
if (iCurSel > 0) { EnableWindow(GetDlgItem(hwndDlg, ID_PREVSUBSET), TRUE); } else { EnableWindow(GetDlgItem(hwndDlg, ID_PREVSUBSET), FALSE); } //
// Enable Next button if not on last subset.
//
if (iCurSel < (cSubsets - 1)) { EnableWindow(GetDlgItem(hwndDlg, ID_NEXTSUBSET), TRUE); } else { EnableWindow(GetDlgItem(hwndDlg, ID_NEXTSUBSET), FALSE); }
//
// The first sub sel is the ANSI code page.
//
psycm->fAnsiFont = (iCurSel == 0);
//
// Create the font.
//
psycm->hFont = CreateFontIndirect(&LogFont); hFont = SelectObject(hdc, psycm->hFont);
//
// Create the magnify font.
//
LogFont.lfHeight = psycm->dypMag - 5; // Allow for whitespace.
psycm->hFontMag = CreateFontIndirect(&LogFont);
//
// Calculate new values and place in window data structure.
//
GetTextMetrics(hdc, &tm); psycm->xpCh = 2; psycm->ypCh = (4 + psycm->dypBox - tm.tmHeight) / 2;
lpdxp = (LPINT)psycm->rgdxp;
if (psycm->fAnsiFont) { GetCharWidth32A(hdc, chSymFirst, chSymLast, lpdxp); } else { GetCharWidth32(hdc, chSymFirst, chSymLast, lpdxp); }
SelectObject(hdc, hFont);
for (ch = (UINT) chSymFirst; ch <= (UINT) chSymLast; ch++, lpdxp++) { *lpdxp = (psycm->dxpBox - *lpdxp) / 2 - 1; } ReleaseDC(hwndCharGrid, hdc);
psycm->xpMagCurr = 0; // No magnification data
if (fRedraw) { InvalidateRect(hwndCharGrid, NULL, TRUE); } }
////////////////////////////////////////////////////////////////////////////
//
// DrawSymbolMap
//
// Draws all of the pieces of the symbol character map.
//
////////////////////////////////////////////////////////////////////////////
VOID DrawSymbolMap( PSYCM psycm, HDC hdc) { BOOL fFocus;
DrawSymbolGrid(psycm, hdc); DrawSymbolChars(psycm, hdc); //
// We need to force the focus rect to paint if we have the focus
// since the old focus rect has been drawn over already.
//
if (fFocus = psycm->fFocusState) { psycm->fFocusState = FALSE; } DrawSymChOutline(psycm, hdc, psycm->chCurr, TRUE, fFocus); }
////////////////////////////////////////////////////////////////////////////
//
// DrawSymbolGrid
//
// Draws the symbol character map grid.
//
////////////////////////////////////////////////////////////////////////////
VOID DrawSymbolGrid( PSYCM psycm, HDC hdc) { INT cli; // count of lines
INT xp, yp; INT dxpBox = psycm->dxpBox; INT dypBox = psycm->dypBox; HPEN hpenOld;
hpenOld = SelectObject(hdc, CreatePen( PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME) ));
//
// Draw horizontal lines.
//
xp = psycm->dxpCM + 1; yp = 1; cli = cchSymCol+1; while (cli--) { MoveToEx(hdc, 1, yp, NULL); LineTo(hdc, xp, yp); yp += dypBox; }
//
// Draw vertical lines.
//
yp = psycm->dypCM; xp = 1; cli = cchSymRow+1; while (cli--) { MoveToEx(hdc, xp, 1, NULL); LineTo(hdc, xp, yp); xp += dxpBox; }
DeleteObject(SelectObject(hdc, hpenOld)); }
////////////////////////////////////////////////////////////////////////////
//
// DrawSymbolChars
//
// Draws the symbol character map.
//
////////////////////////////////////////////////////////////////////////////
VOID DrawSymbolChars( PSYCM psycm, HDC hdc) { INT dxpBox = psycm->dxpBox; INT dypBox = psycm->dypBox; INT cch; INT x, y; INT yp; TCHAR ch; HFONT hFontOld; RECT rect; LPRECT lprect = (LPRECT)▭ LPINT lpdxp;
//
// Setup the font and colors.
//
hFontOld = (HFONT)SelectObject(hdc, psycm->hFont); SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); SetBkMode(hdc, OPAQUE);
//
// Draw characters.
//
cch = 1; ch = chSymFirst;
lpdxp = (LPINT)psycm->rgdxp;
rect.top = 2; yp = psycm->ypCh; rect.bottom = rect.top + dypBox - 1;
for (y = 0; y++ < cchSymCol;) { rect.left = psycm->xpCh; rect.right = rect.left + dxpBox - 1; for (x = 0; (x++ < cchSymRow) && (ch <= chSymLast);) { if (psycm->fAnsiFont) { ExtTextOutA( hdc, rect.left + (*lpdxp++), yp, ETO_OPAQUE | ETO_CLIPPED, lprect, &(CHAR)ch, 1, NULL ); } else { ExtTextOutW( hdc, rect.left + (*lpdxp++), yp, ETO_OPAQUE | ETO_CLIPPED, lprect, &ch, 1, NULL ); } ch++; rect.left += dxpBox; rect.right += dxpBox; } yp += dypBox; rect.top += dypBox; rect.bottom += dypBox; }
SelectObject(hdc, hFontOld); }
////////////////////////////////////////////////////////////////////////////
//
// DrawSymChOutline
//
// Draws an outline around the symbol in the character map. If fVisible,
// then it draws the outline, otherwise it erases it.
//
////////////////////////////////////////////////////////////////////////////
VOID DrawSymChOutline( PSYCM psycm, HDC hdc, UTCHAR ch, BOOL fVisible, BOOL fFocus) { HBRUSH hbrOld; RECT rc; INT dxpBox = psycm->dxpBox; INT dypBox = psycm->dypBox;
hbrOld = SelectObject( hdc, CreateSolidBrush(GetSysColor( fVisible ? COLOR_WINDOWFRAME : COLOR_WINDOW )) ); ch -= chSymFirst;
rc.left = (ch % cchSymRow) * dxpBox + 2; rc.right = rc.left + dxpBox - 1; rc.top = (ch / cchSymRow) * dypBox + 2; rc.bottom = rc.top + dypBox - 1;
//
// Draw selection rectangle.
//
PatBlt(hdc, rc.left, rc.top - 2, dxpBox - 1, 1, PATCOPY); PatBlt(hdc, rc.left, rc.bottom + 1, dxpBox - 1, 1, PATCOPY); PatBlt(hdc, rc.left - 2, rc.top, 1, dypBox - 1, PATCOPY); PatBlt(hdc, rc.right + 1, rc.top, 1, dypBox - 1, PATCOPY);
DeleteObject(SelectObject(hdc, GetStockObject(NULL_BRUSH)));
//
// Deal with the focus rectangle.
//
if (fFocus != psycm->fFocusState) { DrawFocusRect(hdc, &rc); psycm->fFocusState = fFocus; }
SelectObject(hdc, hbrOld); }
////////////////////////////////////////////////////////////////////////////
//
// MoveSymbolSel
//
// Changes the current symbol selection. Handles drawing of magnified
// characters.
//
////////////////////////////////////////////////////////////////////////////
VOID MoveSymbolSel( PSYCM psycm, UTCHAR chNew) { HDC hdc; HDC hdcMag = psycm->hdcMag; RECT rc; HFONT hFontOld; HFONT hFontMag; // old font in memory dc
HPEN hpenOld; UTCHAR chNorm = chNew - chSymFirst + 32; INT dxpMag = psycm->dxpMag; // for quick reference
INT dypMag = psycm->dypMag; INT ypMemSrc = psycm->ypDest; INT ypMemDest = ypMemSrc ^ dypMag; INT xpCurr = psycm->xpMagCurr; INT ypCurr = psycm->ypMagCurr; INT xpNew = psycm->xpCM + (psycm->dxpBox * (chNorm % cchSymRow)); INT ypNew = psycm->ypCM + (psycm->dypBox * ((chNorm / cchSymRow) - 1)); INT dxpCh; // width of extra character space (used to center char in box)
INT dypCh; SIZE sz;
DOUTL("MoveSymbolSel: In\n");
if (((chNew == (UTCHAR)psycm->chCurr) && FMagData(psycm))) { DOUTL("MoveSymbolSel: ch == cur && fMag... exiting\n"); return; }
//
// Don't draw a magnified character if the char grid has an update
// region or is not visible.
//
if (!IsWindowVisible(hwndCharGrid) || GetUpdateRect(hwndCharGrid, &rc, FALSE)) { DOUTL("MoveSymbolSel: not vis or upd rect... exiting\n"); return; }
hdc = GetDC(hwndDialog);
//
// Setup the magnified font character.
//
hFontMag = SelectObject(hdcMag, psycm->hFontMag);
if (psycm->fAnsiFont) { char chANSINew = (char)chNew; GetTextExtentPointA(hdcMag, &chANSINew, 1, &sz); } else { GetTextExtentPointW(hdcMag, &chNew, 1, &sz); }
if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) == LANG_CHINESE) { dxpCh = (dxpMag - (INT)sz.cx) / 2 - 2; dypCh = (dypMag - (INT)sz.cy) / 2 - 2; } else { dxpCh = (dxpMag - (INT)sz.cx) / 2 - 1; dypCh = (dypMag - (INT)sz.cy) / 2 - 1; } hpenOld = SelectObject(hdc, CreatePen( PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME) )); hFontOld = SelectObject(hdc, psycm->hFontMag);
//
// Copy screen data to offscreen bitmap.
//
BitBlt(hdcMag, 0, ypMemDest, dxpMag, dypMag, hdc, xpNew, ypNew, SRCCOPY);
//
// Setup DC.
//
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); SetBkMode(hdc, OPAQUE);
if (FMagData(psycm)) { INT xpT = xpNew - xpCurr; // point of overlap in offscreen data
INT ypT = ypNew - ypCurr; INT dxpT = dxpMag - abs(xpT); // size of overlap
INT dypT = dypMag - abs(ypT);
DOUTL("MoveSymbolSel: FMagData\n");
if ((dxpT > 0) && (dypT > 0)) { INT xpTmax, ypTmax; // max(0, xpT);
INT xpTmin, ypTmin; // min(0, xpT);
INT xpTnmin, ypTnmin; // min(0, -xpT);
DOUTL("MoveSymbolSel: dxpT > 0 && dypT > 0\n");
if (xpT < 0) { xpTnmin = - (xpTmin = xpT); xpTmax = 0; } else { xpTmax = xpT; xpTnmin = xpTmin = 0; } if (ypT < 0) { ypTnmin = - (ypTmin = ypT); ypTmax = 0; } else { ypTmax = ypT; ypTnmin = ypTmin = 0; }
rc.left = xpTmax; rc.right = xpTmin + dxpMag; rc.top = ypTmax + ypMemSrc; rc.bottom= ypTmin + dypMag + ypMemSrc;
//
// Copy overlapping offscreen data.
//
BitBlt( hdcMag, xpTnmin, ypTnmin + ypMemDest, dxpT, dypT, hdcMag, xpTmax, ypTmax + ypMemSrc, SRCCOPY );
//
// Print part of char over old screen data.
//
if (psycm->fAnsiFont) { ExtTextOutA( hdcMag, xpT + dxpCh, ypT + dypCh + ypMemSrc, ETO_OPAQUE | ETO_CLIPPED, (LPRECT)&rc, &(CHAR)chNew, 1, NULL ); } else { ExtTextOutW( hdcMag, xpT + dxpCh, ypT + dypCh + ypMemSrc, ETO_OPAQUE | ETO_CLIPPED, (LPRECT)&rc, &chNew, 1, NULL ); } }
//
// Restore old screen data.
//
BitBlt(hdc, xpCurr, ypCurr, dxpMag, dypMag, hdcMag, 0, ypMemSrc, SRCCOPY); }
rc.right = (psycm->xpMagCurr = rc.left = xpNew) + dxpMag - 2; rc.bottom = (psycm->ypMagCurr = rc.top = ypNew) + dypMag - 2;
//
// The rectangle.
//
MoveToEx(hdc, rc.left, rc.top, NULL); LineTo(hdc, rc.left, rc.bottom - 1); LineTo(hdc, rc.right - 1, rc.bottom - 1); LineTo(hdc, rc.right - 1, rc.top); LineTo(hdc, rc.left, rc.top);
//
// The shadow.
//
MoveToEx(hdc, rc.right, rc.top + 1, NULL); LineTo(hdc, rc.right, rc.bottom); LineTo(hdc, rc.left, rc.bottom); MoveToEx(hdc, rc.right + 1, rc.top + 2, NULL); LineTo(hdc, rc.right + 1, rc.bottom + 1); LineTo(hdc, rc.left + 1, rc.bottom + 1);
rc.left++; rc.top++; rc.right--; rc.bottom--;
//
// Draw magnified character on screen.
//
if (psycm->fAnsiFont) { ExtTextOutA( hdc, xpNew + dxpCh, ypNew + dypCh, ETO_OPAQUE | ETO_CLIPPED, (LPRECT)&rc, &(CHAR)chNew, 1, NULL ); } else { ExtTextOutW( hdc, xpNew + dxpCh, ypNew + dypCh, ETO_OPAQUE | ETO_CLIPPED, (LPRECT)&rc, &chNew, 1, NULL ); }
psycm->ypDest = ypMemDest;
DeleteObject(SelectObject(hdc, hpenOld)); SelectObject(hdc, hFontOld); SelectObject(hdcMag, hFontMag);
UpdateKeystrokeText(hdc, psycm->fAnsiFont, chNew, TRUE);
ReleaseDC(hwndDialog, hdc);
psycm->chCurr = chNew; DOUTL("MoveSymbolSel: Leaving\n"); }
////////////////////////////////////////////////////////////////////////////
//
// RestoreSymMag
//
// Restores the screen data under the magnifier.
//
////////////////////////////////////////////////////////////////////////////
VOID RestoreSymMag( PSYCM psycm) { if (FMagData(psycm)) { HDC hdc = GetDC(hwndDialog);
BitBlt( hdc, psycm->xpMagCurr, psycm->ypMagCurr, psycm->dxpMag, psycm->dypMag, psycm->hdcMag, 0, psycm->ypDest, SRCCOPY );
ReleaseDC(hwndDialog, hdc);
psycm->xpMagCurr = 0; // flag - no data offscreen (see FMagData)
} }
////////////////////////////////////////////////////////////////////////////
//
// FontLoadProc
//
// Used by EnumFonts to load our combo box with all the fonts installed
// in the system.
//
////////////////////////////////////////////////////////////////////////////
INT APIENTRY FontLoadProc( LPLOGFONT lpLogFont, NEWTEXTMETRICEX* lpTextMetric, DWORD nFontType, LPARAM lpData) { INT iPos; TCHAR szFace[LF_FACESIZE];
//
// Check for duplicates.
//
iPos = (INT)SendDlgItemMessage( (HWND)lpData, ID_FONT, CB_FINDSTRING, (WPARAM)-1, (DWORD)&lpLogFont->lfFaceName ); if (iPos == CB_ERR) { NotInListYet: //
// Doesn't exist, insert the facename into the combo box.
//
iPos = (INT)SendDlgItemMessage( (HWND)lpData, ID_FONT, CB_ADDSTRING, 0, (DWORD)&lpLogFont->lfFaceName ); } else { //
// Make sure it is not just a substring (want a full match).
//
SendDlgItemMessage( (HWND)lpData, ID_FONT, CB_GETLBTEXT, iPos, (LONG)(LPTSTR)szFace ); if (lstrcmpi(szFace, lpLogFont->lfFaceName)) { goto NotInListYet; }
//
// Already exists, blow out now if this is not a true type font.
//
if (!(nFontType & TRUETYPE_FONTTYPE)) { return (1); } }
//
// Store the pertinant font information in the combo item data.
//
if ((iPos != CB_ERR) && (iPos != CB_ERRSPACE)) { ITEMDATA ItemData; DWORD ntmFlags = lpTextMetric->ntmTm.ntmFlags; SHORT sFontType = 0;
if (ntmFlags & NTM_PS_OPENTYPE) { sFontType = PS_OPENTYPE_FONT; } else if (ntmFlags & NTM_TYPE1) { sFontType = TYPE1_FONT; } else if (nFontType & TRUETYPE_FONTTYPE) { if (ntmFlags & NTM_TT_OPENTYPE) sFontType = TT_OPENTYPE_FONT; else sFontType = TRUETYPE_FONT; }
ItemData.FontType = sFontType; ItemData.CharSet = lpLogFont->lfCharSet; ItemData.PitchAndFamily = lpLogFont->lfPitchAndFamily;
SendDlgItemMessage( (HWND)lpData, ID_FONT, CB_SETITEMDATA, iPos, *(DWORD *)&ItemData ); }
//
// Continue enumeration.
//
return (1); }
////////////////////////////////////////////////////////////////////////////
//
// GetEditText
//
// Returns HANDLE containing the text in the edit control.
//
// NOTE: Caller is responsible for freeing this handle!
//
////////////////////////////////////////////////////////////////////////////
HANDLE GetEditText( HWND hwndDlg) { INT cchText; HWND hwndEditCtl; HANDLE hmem; LPTSTR lpstrText; DWORD dwSel;
hwndEditCtl = GetDlgItem(hwndDlg, ID_STRING);
cchText = GetWindowTextLength(hwndEditCtl);
hmem = GlobalAlloc(0, CTOB((cchText + 1)));
lpstrText = (LPTSTR)GlobalLock(hmem);
cchText = GetWindowText(hwndEditCtl, lpstrText, cchText+1);
dwSel = SendMessage(hwndEditCtl, EM_GETSEL, 0, 0L);
if (LOWORD(dwSel) != HIWORD(dwSel)) { //
// If there is a selection, then only get the selected text.
//
*(lpstrText + HIWORD(dwSel)) = TEXT('\0'); lstrcpy(lpstrText, lpstrText + LOWORD(dwSel)); }
GlobalUnlock(hmem);
if (cchText == 0) { hmem = GlobalFree(hmem); }
return (hmem); }
////////////////////////////////////////////////////////////////////////////
//
// CopyString
//
// Implements the copy function.
//
////////////////////////////////////////////////////////////////////////////
VOID CopyString( HWND hwndDlg) { HANDLE hmem; LPTSTR lpstrText;
if (hmem = GetEditText(hwndDlg)) { lpstrText = (LPTSTR)GlobalLock(hmem);
//
// Copying string to clipboard.
//
if (OpenClipboard(hwndDlg)) { EmptyClipboard(); SendRTFToClip(hwndDlg, lpstrText); #ifdef UNICODE
SetClipboardData(CF_UNICODETEXT, hmem); #else
SetClipboardData(CF_TEXT, hmem); #endif
CloseClipboard(); } else { //
// If we couldn't open the clipboard, then we need to free memory.
//
GlobalUnlock(hmem); GlobalFree(hmem); } } }
////////////////////////////////////////////////////////////////////////////
//
// SendRTFToClip
//
// Puts the string in the clipboard using Rich Text Format. This assumes
// that the clipboard has already been opened.
//
////////////////////////////////////////////////////////////////////////////
VOID SendRTFToClip( HWND hwndDlg, LPTSTR lpstrText) { INT iCurrFont; ITEMDATA ItemData; TCHAR szFaceName[LF_FACESIZE]; HANDLE hmemRTF, hmemClip; LPTSTR lpstrClipString; TCHAR achHeaderTmpl[] = TEXT("{\\rtf1\\ansi\\ansicpg%d {\\fonttbl{\\f0\\"); TCHAR achHeader[sizeof(achHeaderTmpl) / sizeof(TCHAR) + 20]; TCHAR achMiddle[] = TEXT(";}}\\sectd\\pard\\plain\\f0 "); INT cchUC; #ifndef UNICODE_RTF
LPWSTR pszRTFW; #endif
#define MAXLENGTHFONTFAMILY 8
#define ALITTLEEXTRA 10 // covers extra characters + length of font size
iCurrFont = (INT)SendDlgItemMessage(hwndDlg, ID_FONT, CB_GETCURSEL, 0, 0L);
//
// Get the item data - contains fonttype, charset, and pitchandfamily.
//
*(DWORD *)&ItemData = SendDlgItemMessage( hwndDlg, ID_FONT, CB_GETITEMDATA, iCurrFont, 0L );
//
// Get the facename from the combo box.
//
SendDlgItemMessage( hwndDlg, ID_FONT, CB_GETLBTEXT, iCurrFont, (LPARAM)(LPTSTR)szFaceName );
wsprintf(achHeader, achHeaderTmpl, (INT)(SHORT)GetACP());
//
// 16 times in case they're all > 7 bits (each chr -> \uc1\uddddddd\'xx)
// and room for the second byte of DBCS.
//
hmemRTF = GlobalAlloc( 0, CTOB(lstrlen((LPTSTR)achHeader) + MAXLENGTHFONTFAMILY + lstrlen(szFaceName) + lstrlen((LPTSTR)achMiddle) + 2 * 16 * lstrlen(lpstrText) + ALITTLEEXTRA) ); if (hmemRTF == NULL) { return; }
//
// Allocate memory for local storage of clipboard string for owner draw.
//
if (hmemClip = GlobalAlloc(0, CTOB(lstrlen(lpstrText) + 1))) { //
// Get rid of old ones.
//
if (hstrClipboard) { GlobalFree(hstrClipboard); } if (fDelClipboardFont) { fDelClipboardFont = FALSE; DeleteObject(hFontClipboard); }
//
// Save this stuff away for owner drawing in a clipboard viewer.
//
hFontClipboard = sycm.hFont; hstrClipboard = hmemClip; lstrcpy(GlobalLock(hstrClipboard), lpstrText); GlobalUnlock(hstrClipboard); } else { GlobalFree(hmemRTF); return; }
lpstrClipString = GlobalLock(hmemRTF); #ifndef UNICODE_RTF
pszRTFW = lpstrClipString; #endif
lstrcpy(lpstrClipString, achHeader);
if (ItemData.CharSet == SYMBOL_CHARSET) { lstrcat(lpstrClipString, (LPTSTR)TEXT("ftech ")); } else { //
// Top four bits specify family.
//
switch (ItemData.PitchAndFamily & 0xf0) { case ( FF_DECORATIVE ) : { lstrcat(lpstrClipString, (LPTSTR)TEXT("fdecor ")); break; } case ( FF_MODERN ) : { lstrcat(lpstrClipString, (LPTSTR)TEXT("fmodern ")); break; } case ( FF_ROMAN ) : { lstrcat(lpstrClipString, (LPTSTR)TEXT("froman ")); break; } case ( FF_SCRIPT ) : { lstrcat(lpstrClipString, (LPTSTR)TEXT("fscript ")); break; } case ( FF_SWISS ) : { lstrcat(lpstrClipString, (LPTSTR)TEXT("fswiss ")); break; } default : { break; } } }
lstrcat(lpstrClipString, szFaceName);
lstrcat(lpstrClipString, (LPTSTR)achMiddle);
//
// We need to do the text character by character, making sure
// that we output a special sequence \'hh for characters bigger
// than 7 bits long!
//
lpstrClipString = (LPTSTR)(lpstrClipString + lstrlen(lpstrClipString));
cchUC = 0;
while (*lpstrText) { if ((UTCHAR)*lpstrText < 128) { if (*lpstrText == TEXT('\\') || *lpstrText == TEXT('{') || *lpstrText == TEXT('}')) { //
// Need to preface these symbols with a '\' since they are
// special control characters for RTF.
//
*lpstrClipString++ = TEXT('\\'); }
*lpstrClipString++ = *lpstrText++; } else { unsigned char achTmp[2]; unsigned char *pTmp = achTmp; int cch;
cch = WideCharToMultiByte( CP_ACP, 0, lpstrText, 1, pTmp, 2, NULL, NULL );
//
// Put in a \uc# to tell Unicode reader how many bytes to skip
// and the \uN code to indicate the real unicode value.
//
if (cch != cchUC ) { cchUC = cch; lpstrClipString += wsprintf( lpstrClipString, TEXT("\\uc%d"), (INT)(SHORT)cchUC ); }
lpstrClipString += wsprintf( lpstrClipString, TEXT("\\u%d"), (INT)(SHORT)*lpstrText );
//
// Now put the \'xx string in to indicate the actual character.
//
lpstrText++; while (cch--) { *lpstrClipString++ = TEXT('\\'); *lpstrClipString++ = TEXT('\''); wsprintf(achMiddle, TEXT("%x"), (INT)*pTmp++); *lpstrClipString++ = achMiddle[0]; *lpstrClipString++ = achMiddle[1]; } } } *lpstrClipString++ = TEXT('}'); *lpstrClipString++ = TEXT('\0');
if (!wCFRichText) { TCHAR szRTF[80];
LoadString(hInst, IDS_RTF, szRTF, BTOC(sizeof(szRTF)) - 1); wCFRichText = RegisterClipboardFormat(szRTF); }
#ifndef UNICODE_RTF
{ //
// RTF is only defined for ANSI, not for Unicode, therefore
// we need to convert the buffer before we put it on the
// clipboard. Eventually, we should add autoconversion code
// to USER to handle this for us.
//
int cch; HANDLE hmemRTFA; LPSTR pszRTFA;
cch = WideCharToMultiByte( CP_ACP, 0, pszRTFW, lpstrClipString - pszRTFW, NULL, 0, NULL, NULL );
if (cch != 0 && (hmemRTFA = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,cch)) != NULL) { pszRTFA = GlobalLock(hmemRTFA);
WideCharToMultiByte( CP_ACP, 0, pszRTFW, lpstrClipString - pszRTFW, pszRTFA, cch, NULL, NULL );
GlobalUnlock(hmemRTFA); GlobalUnlock(hmemRTF); GlobalFree(hmemRTF);
hmemRTF = hmemRTFA; } } #endif
//
// Put RTF and OwnerDisplay formats in the clipboard.
//
SetClipboardData(wCFRichText, hmemRTF); SetClipboardData(CF_OWNERDISPLAY, NULL); }
////////////////////////////////////////////////////////////////////////////
//
// PointsToHeight
//
// Calculates the height in pixels of the specified point size for the
// current display.
//
////////////////////////////////////////////////////////////////////////////
INT PointsToHeight( INT iPoints) { HDC hdc; INT iHeight;
hdc = GetDC(HWND_DESKTOP); iHeight = MulDiv(iPoints, GetDeviceCaps(hdc, LOGPIXELSY), 72); ReleaseDC(HWND_DESKTOP, hdc); return (iHeight); }
////////////////////////////////////////////////////////////////////////////
//
// UpdateKeystrokeText
//
// Calculates and updates the text string displayed in the Keystroke
// field of the status bar. It repaints the status field if fRedraw is
// TRUE.
//
////////////////////////////////////////////////////////////////////////////
VOID UpdateKeystrokeText( HDC hdc, BOOL fANSI, UTCHAR chNew, BOOL fRedraw) { TCHAR szUnshifted[CCH_KEYNAME]; INT vkRes; LONG lParam;
if (!fANSI) { lstrcpy(szKeystrokeText, szUnicodeLabel); wsprintf( (LPTSTR)(szKeystrokeText + iUnicodeLabelStart), TEXT("%04x"), chNew ); } else { lstrcpy(szKeystrokeText, szKeystrokeLabel); vkRes = VkKeyScan(chNew); //
// Map the virtual key code into an unshifted character value.
//
lParam = MapVirtualKey(LOBYTE(vkRes), 0) << 16; GetKeyNameText(lParam, szUnshifted, CCH_KEYNAME - 1);
switch (HIBYTE(vkRes)) { case ( 0 ) : // unshifted char
case ( 1 ) : // character is shifted, just display the shifted char
{ if (chNew != TEXT(' ')) { szKeystrokeText[iKeystrokeTextStart] = chNew; szKeystrokeText[iKeystrokeTextStart + 1] = TEXT('\0'); } else { lstrcat(szKeystrokeText, szUnshifted); } break; } case ( 2 ) : // character is control character
{ lstrcpy((LPTSTR)(szKeystrokeText + iKeystrokeTextStart), szCtrl); lstrcat(szKeystrokeText, (LPTSTR)szUnshifted); break; } case ( 6 ) : // character is CONTROL+ALT
{ lstrcpy((LPTSTR)(szKeystrokeText + iKeystrokeTextStart), szCtrlAlt); lstrcat(szKeystrokeText, (LPTSTR)szUnshifted); break; } case ( 7 ) : // character is SHIFT+CONTROL+ALT
{ lstrcpy((LPTSTR)(szKeystrokeText + iKeystrokeTextStart), szShiftCtrlAlt); lstrcat(szKeystrokeText, (LPTSTR)szUnshifted); break; } default : // Character created via Alt + Numpad
{ lstrcpy((LPTSTR)(szKeystrokeText + iKeystrokeTextStart), szAlt); wsprintf( (LPTSTR)(szKeystrokeText + lstrlen(szKeystrokeText)), TEXT("%d"), chNew ); break; } } }
if (fRedraw) { PaintStatusLine(hdc, FALSE, TRUE); } }
////////////////////////////////////////////////////////////////////////////
//
// UpdateHelpText
//
// Calculates if the Help string needs to be updated, and does so if
// necessary.
//
// If hwndCtrl is not NULL, then it specifies the window handle of the
// control gaining focus, and lpmsg is ignored.
//
// If hwndCtrl is NULL, then lpmsg must point to a valid message structure.
// If it is a tab character, then we calculate what the next control is
// that will receive the focus.
//
////////////////////////////////////////////////////////////////////////////
BOOL UpdateHelpText( LPMSG lpmsg, HWND hwndCtrl) { HDC hdc; BOOL fPaintStatus = FALSE; BOOL fRet = TRUE;
DPRINT((szDbgBuf, TEXT("UpdHlpTxt: lpmsg:0x%08lX, hwnd:0x%08lX\n"), (DWORD)lpmsg, (DWORD)hwndCtrl));
if (hwndCtrl != NULL) { fPaintStatus = TRUE; iControl = GetDlgCtrlID(hwndCtrl); } else if (lpmsg->message == WM_KEYDOWN) { if (lpmsg->wParam == VK_TAB) { fPaintStatus = TRUE; hwndCtrl = GetNextDlgTabItem( hwndDialog, GetDlgItem(hwndDialog, iControl), (BOOL)(GetKeyState(VK_SHIFT) & 0x8000) ); iControl = GetDlgCtrlID(hwndCtrl); if (iControl == ID_STRING) { //
// Do this ourselves, otherwise default action will select
// the whole edit control.
//
SetFocus(hwndCtrl); fRet = FALSE; } if (iControl == ID_CHARGRID) { //
// Set the default button back to "Select". The default
// might have changed to the "Next" or "Previous" button.
//
SendMessage(hwndDialog, DM_SETDEFID, ID_SELECT, 0); } } else if (lpmsg->wParam == VK_F1) { PostMessage(hwndDialog, WM_COMMAND, ID_HELP, 0L); } }
if (fPaintStatus) { hdc = GetDC(hwndDialog); PaintStatusLine(hdc, TRUE, FALSE); ReleaseDC(hwndDialog, hdc); }
return (fRet); }
////////////////////////////////////////////////////////////////////////////
//
// SubSetChanged
//
// Sets the ANSI bit if appropriate and then calls UpdateSymbolSelection
// and then repaints the window.
//
// Repaints Keystroke field if HWND != NULL.
// Sets sycm->fAnsiFont if 'Windows Chars' is the subset.
// Redraws the char grid.
//
////////////////////////////////////////////////////////////////////////////
VOID SubSetChanged( HWND hwnd, INT iSubSet, INT ichFirst, INT ichLast) { HDC hdc; BOOL fANSI = (iSubSet == 0);
if (fANSI != sycm.fAnsiFont) { sycm.fAnsiFont = fANSI; }
UpdateSymbolSelection(hwnd, ichFirst, ichLast);
if ((hwnd != NULL) && ((hdc = GetDC(hwnd)) != NULL)) { LPINT lpdxp; HFONT hFont; UINT ch;
hFont = SelectObject(hdc, sycm.hFont); lpdxp = (LPINT)sycm.rgdxp;
if (iSubSet == 0) { GetCharWidth32A(hdc, chSymFirst, chSymLast, lpdxp); } else { GetCharWidth32(hdc, chSymFirst, chSymLast, lpdxp); }
SelectObject(hdc, hFont);
for (ch = (UINT) chSymFirst; ch <= (UINT) chSymLast; ch++, lpdxp++) { *lpdxp = (sycm.dxpBox - *lpdxp) / 2 - 1; } ReleaseDC(hwnd, hdc); }
InvalidateRect(hwndCharGrid, NULL, TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// UpdateSymbolSelection
//
// Updates the values of the following global values:
// chRangeFirst
// chRangeLast
// Subsets in the Unicode character set have different numbers of
// characters. We have to do some bounds checking in order to set an
// appropriate sycm.chCurr value. The "Keystroke" status field is
// updated.
//
// Repaints Keystroke field if HWND != NULL.
//
////////////////////////////////////////////////////////////////////////////
VOID UpdateSymbolSelection( HWND hwnd, INT FirstChar, INT LastChar) { int iCmd = SW_HIDE; HWND hwndSB; UINT chFirst, chLast;
chRangeFirst = FirstChar; chRangeLast = LastChar;
chFirst = chRangeFirst;
chLast = chFirst + cchFullMap - 1; chLast = min(chLast, chRangeLast);
hwndSB = GetDlgItem(hwnd, ID_MAPSCROLL);
if (chLast != chRangeLast) { int i;
iCmd = SW_SHOW; SetScrollPos(hwndSB, SB_CTL, 0, FALSE); i = (chRangeLast - chRangeFirst + 1) - cchFullMap;
if (i < 0) { i = 1; } else { i = i / cchSymRow; }
SetScrollRange(hwndSB, SB_CTL, 0, i, FALSE); InvalidateRect(hwndSB, NULL, FALSE); }
ShowWindow(hwndSB, iCmd);
UpdateSymbolRange(hwnd, chFirst, chLast); }
////////////////////////////////////////////////////////////////////////////
//
// UpdateSymbolRange
//
// Updates the values of the following global values:
// chSymFirst
// chSymLast
// sycm.chCurr
// Subsets in the Unicode character set have different numbers of
// characters. We have to do some bounds checking in order to set an
// appropriate sycm.chCurr value. The "Keystroke" status field is
// updated.
//
// Repaints Keystroke field if HWND != NULL.
//
////////////////////////////////////////////////////////////////////////////
VOID UpdateSymbolRange( HWND hwnd, INT FirstChar, INT LastChar) { UTCHAR chSymOffset;
chSymOffset = sycm.chCurr - chSymFirst;
chSymFirst = FirstChar; chSymLast = LastChar;
sycm.chCurr = chSymOffset + chSymFirst; if (sycm.chCurr > chSymLast) { sycm.chCurr = chSymFirst; } if (hwnd != NULL) { HDC hdc;
hdc = GetDC(hwnd); UpdateKeystrokeText(hdc, sycm.fAnsiFont, sycm.chCurr, TRUE); ReleaseDC(hwnd, hdc); } else { UpdateKeystrokeText(NULL, sycm.fAnsiFont, sycm.chCurr, FALSE); } }
////////////////////////////////////////////////////////////////////////////
//
// PaintStatusLine
//
// Paints the Help and Keystroke fields in the status bar.
//
// Repaints Help field if fHelp == TRUE.
// Repaints Keystroke field if fKeystroke == TRUE.
//
////////////////////////////////////////////////////////////////////////////
VOID PaintStatusLine( HDC hdc, BOOL fHelp, BOOL fKeystroke) { HFONT hfontOld = NULL; RECT rect; INT dyBorder; TCHAR szHelpText[100];
dyBorder = GetSystemMetrics(SM_CYBORDER);
if (hfontStatus) { hfontOld = SelectObject(hdc, hfontStatus); }
//
// Set the text and background colors.
//
SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT)); SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
if (fHelp) { //
// Now the help text, with a gray background.
//
rect.top = rcStatusLine.top + 3 * dyBorder; rect.bottom = rcStatusLine.bottom - 3 * dyBorder; rect.left = 9 * dyBorder; rect.right = rect.left + dxHelpField - 2 * dyBorder;
LoadString(hInst, iControl, szHelpText, BTOC(sizeof(szHelpText)) - 1);
ExtTextOut( hdc, rect.left + dyBorder * 2, rect.top, ETO_OPAQUE | ETO_CLIPPED, &rect, szHelpText, lstrlen(szHelpText), NULL ); }
if (fKeystroke) { //
// Now the keystroke text, with a gray background.
//
rect.top = rcStatusLine.top + 3 * dyBorder; rect.bottom = rcStatusLine.bottom - 3 * dyBorder; rect.right = rcStatusLine.right - 9 * dyBorder; rect.left = rect.right - dxKeystrokeField + 2 * dyBorder;
ExtTextOut( hdc, rect.left + dyBorder * 2, rect.top, ETO_OPAQUE | ETO_CLIPPED, &rect, szKeystrokeText, lstrlen(szKeystrokeText), NULL ); }
if (hfontOld) { SelectObject(hdc, hfontOld); } }
////////////////////////////////////////////////////////////////////////////
//
// DrawFamilyComboItem
//
// Paints the font facenames and TT bitmap in the font combo box.
//
////////////////////////////////////////////////////////////////////////////
BOOL DrawFamilyComboItem( LPDRAWITEMSTRUCT lpdis) { HDC hDC, hdcMem; DWORD rgbBack, rgbText; TCHAR szFace[LF_FACESIZE]; HBITMAP hOld; INT dy; SHORT sFontType;
hDC = lpdis->hDC;
if (lpdis->itemState & ODS_SELECTED) { rgbBack = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT)); rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); } else { rgbBack = SetBkColor(hDC, GetSysColor(COLOR_WINDOW)); rgbText = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); }
SendMessage( lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LONG)(LPTSTR)szFace ); ExtTextOut( hDC, lpdis->rcItem.left + DX_BITMAP, lpdis->rcItem.top, ETO_OPAQUE | ETO_CLIPPED, &lpdis->rcItem, szFace, lstrlen(szFace), NULL );
hdcMem = CreateCompatibleDC(hDC); if (hdcMem) { if (hbmFont) { hOld = SelectObject(hdcMem, hbmFont); sFontType = ((ITEMDATA FAR *)&(lpdis->itemData))->FontType;
if (sFontType) {
int xSrc; dy = ((lpdis->rcItem.bottom - lpdis->rcItem.top) - DY_BITMAP) / 2;
if (sFontType & TRUETYPE_FONT) xSrc = 0; else if (sFontType & TT_OPENTYPE_FONT) xSrc = 2; else if(sFontType & PS_OPENTYPE_FONT) xSrc = 3; else if (sFontType & TYPE1_FONT) xSrc = 4;
BitBlt( hDC, lpdis->rcItem.left, lpdis->rcItem.top + dy, DX_BITMAP, DY_BITMAP, hdcMem, xSrc * DX_BITMAP, lpdis->itemState & ODS_SELECTED ? DY_BITMAP : 0, SRCCOPY ); } SelectObject(hdcMem, hOld); } DeleteDC(hdcMem); }
SetTextColor(hDC, rgbText); SetBkColor(hDC, rgbBack);
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// LoadBitmaps
//
// Loads DIB bitmaps and "fixes up" their color tables so that we get the
// desired result for the device we are on.
//
// This routine requires:
// - the DIB is a 16 color DIB authored with the standard windows colors
// - bright blue (00 00 FF) is converted to the background color
// - light grey (C0 C0 C0) is replaced with the button face color
// - dark grey (80 80 80) is replaced with the button shadow color
//
// This means you can't have any of these colors in your bitmap.
//
////////////////////////////////////////////////////////////////////////////
HBITMAP LoadBitmaps( INT id) { HDC hdc; HANDLE h, hRes; DWORD *p; LPBYTE lpBits; LPBITMAPINFOHEADER lpBitmapInfo; INT numcolors; DWORD rgbSelected, rgbUnselected; HBITMAP hbm;
rgbSelected = GetSysColor(COLOR_HIGHLIGHT); //
// Flip the colors.
//
rgbSelected = RGB( GetBValue(rgbSelected), GetGValue(rgbSelected), GetRValue(rgbSelected) ); rgbUnselected = GetSysColor(COLOR_WINDOW); //
// Flip the colors.
//
rgbUnselected = RGB( GetBValue(rgbUnselected), GetGValue(rgbUnselected), GetRValue(rgbUnselected) );
h = FindResource(hInst, MAKEINTRESOURCE(id), RT_BITMAP); hRes = LoadResource(hInst, h);
//
// Lock the bitmap and get a pointer to the color table.
//
lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
if (!lpBitmapInfo) { return (FALSE); }
p = (DWORD *)((LPSTR)(lpBitmapInfo) + lpBitmapInfo->biSize);
//
// Search for the Solid Blue entry and replace it with the current
// background RGB.
//
numcolors = 16;
while (numcolors-- > 0) { if (*p == BACKGROUND) { *p = rgbUnselected; } else if (*p == BACKGROUNDSEL) { *p = rgbSelected; } p++; } UnlockResource(hRes);
//
// Now create the DIB.
//
lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
//
// First skip over the header structure.
//
lpBits = (LPBYTE)(lpBitmapInfo + 1);
//
// Skip the color table entries, if any.
//
lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
//
// Create a color bitmap compatible with the display device.
//
hdc = GetDC(NULL); hbm = CreateDIBitmap( hdc, lpBitmapInfo, (DWORD)CBM_INIT, lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS ); ReleaseDC(NULL, hdc);
GlobalUnlock(hRes); FreeResource(hRes);
return (hbm); }
////////////////////////////////////////////////////////////////////////////
//
// DoHelp
//
// Invokes help if fInvokeHelp is true, or dismisses help if fInvokeHelp
// is FALSE.
//
////////////////////////////////////////////////////////////////////////////
VOID DoHelp( HWND hWnd, BOOL fInvokeHelp) { TCHAR szHelp[80];
if (LoadString(hInst, IDS_HELP, szHelp, BTOC(sizeof(szHelp)) - 1)) { if (fInvokeHelp) { // APPCOMPAT: an error in HtmlHelp prevents the unicode version from working
// This is a HACK to get around the problem. Remove this hack when the problem is fixed.
HtmlHelpA(GetDesktopWindow(), "charmap.chm", HH_DISPLAY_TOPIC, 0L); } } }
////////////////////////////////////////////////////////////////////////////
//
// SaveFont
//
// Saves the current font facename in win.ini, so that it can be selected
// the next time charmap comes up.
//
////////////////////////////////////////////////////////////////////////////
VOID SaveCurrentFont( HWND hWndDlg) { TCHAR szFaceName[LF_FACESIZE] = TEXT("");
SendDlgItemMessage( hWndDlg, ID_FONT, CB_GETLBTEXT, (WORD)SendDlgItemMessage( hWndDlg, ID_FONT, CB_GETCURSEL, 0, 0L ), (LONG)(LPTSTR)szFaceName );
WriteProfileString(TEXT("MSCharMap"), TEXT("Font"), (LPTSTR)szFaceName); }
////////////////////////////////////////////////////////////////////////////
//
// SelectInitialFont
//
// Selects the initial font by getting a saved facename from win.ini and
// selecting it in the combo box.
//
// Returns index to font selected.
//
////////////////////////////////////////////////////////////////////////////
INT SelectInitialFont( HWND hWndDlg) { TCHAR szFaceName[LF_FACESIZE] = TEXT(""); INT iIndex;
if ((GetProfileString( TEXT("MSCharMap"), TEXT("Font"), NULL, (LPTSTR)szFaceName, BTOC(sizeof(szFaceName)) ) == 0) || ((iIndex = (INT)SendDlgItemMessage( hWndDlg, ID_FONT, CB_SELECTSTRING, (WPARAM)-1, (LONG)(LPTSTR)szFaceName )) == CB_ERR)) { //
// If there was no profile or the selection failed then try selecting
// the symbol font, if that fails then select the first one.
//
if ((iIndex = (INT)SendDlgItemMessage( hWndDlg, ID_FONT, CB_SELECTSTRING, (WPARAM)-1, (LONG)(LPTSTR)TEXT("Symbol") )) == CB_ERR) { SendDlgItemMessage(hWndDlg, ID_FONT, CB_SETCURSEL, iIndex = 0, 0L); } }
return (iIndex); }
////////////////////////////////////////////////////////////////////////////
//
// SaveCurrentSubset
//
// Saves the current subset name in win.ini, so that it can be selected
// the next time charmap comes up.
//
////////////////////////////////////////////////////////////////////////////
VOID SaveCurrentSubset( HWND hWndDlg) { TCHAR szSubsetName[LF_SUBSETSIZE] = TEXT("");
SendDlgItemMessage( hWndDlg, ID_UNICODESUBSET, CB_GETLBTEXT, (WORD)SendDlgItemMessage( hWndDlg, ID_UNICODESUBSET, CB_GETCURSEL, 0, 0L ), (LONG)(LPTSTR)szSubsetName );
WriteProfileString(TEXT("MSCharMap"), TEXT("Block"), (LPTSTR)szSubsetName); }
////////////////////////////////////////////////////////////////////////////
//
// SelectInitialSubset
//
// Selects the initial Unicode subset by getting a saved block name from
// win.ini.
//
// Returns index to subset selected.
//
////////////////////////////////////////////////////////////////////////////
INT SelectInitialSubset( HWND hWndDlg) { TCHAR szSubsetName[LF_SUBSETSIZE] = TEXT(""); INT iIndex;
if ((GetProfileString( TEXT("MSCharMap"), TEXT("Block"), NULL, (LPTSTR)szSubsetName, BTOC(sizeof(szSubsetName)) ) == 0) || ((iIndex = (INT)SendDlgItemMessage( hWndDlg, ID_UNICODESUBSET, CB_SELECTSTRING, (WPARAM)-1, (LONG)(LPTSTR)szSubsetName )) == CB_ERR)) { //
// If there was no profile or the selection failed then try selecting
// the Basic Latin block, if that fails then select the first one.
//
if ((iIndex = (INT)SendDlgItemMessage( hWndDlg, ID_UNICODESUBSET, CB_SELECTSTRING, (WPARAM)-1, (LONG)(LPTSTR)TEXT("Basic Latin") )) == CB_ERR) { SendDlgItemMessage( hWndDlg, ID_UNICODESUBSET, CB_SETCURSEL, iIndex = 0, 0L ); } }
chSymFirst = aSubsetData[iIndex].BeginRange; chSymLast = aSubsetData[iIndex].EndRange; sycm.chCurr = chSymFirst;
return (iIndex); }
////////////////////////////////////////////////////////////////////////////
//
// ExitMagnify
//
// Releases mouse capture, exits magnify mode, and restores the cursor.
//
////////////////////////////////////////////////////////////////////////////
VOID ExitMagnify( HWND hWnd, PSYCM psycm) { //
// Release capture, remove magnified character, restore cursor.
//
ReleaseCapture(); RestoreSymMag(psycm); DrawSymChOutlineHwnd(psycm, hWnd, psycm->chCurr, TRUE, TRUE); if (psycm->fCursorOff) { ShowCursor(TRUE); } psycm->fMouseDn = psycm->fCursorOff = FALSE; }
////////////////////////////////////////////////////////////////////////////
//
// SetEditCtlFont
//
// Creates a font for the Edit control that visually matches the handle
// given, but is guaranteed not to be bigger than the size of the edit
// control.
//
////////////////////////////////////////////////////////////////////////////
void SetEditCtlFont( HWND hwndDlg, int idCtl, HFONT hfont) { static HFONT hfNew = NULL; LOGFONT lfNew; HWND hwndCtl = GetDlgItem(hwndDlg, idCtl); RECT rc;
if (hfNew != NULL) { DeleteObject(hfNew); }
GetWindowRect(hwndCtl, &rc);
if (GetObject(hfont, sizeof(lfNew), &lfNew) != 0) { lfNew.lfHeight = rc.bottom - rc.top - 8; lfNew.lfWidth = lfNew.lfEscapement = lfNew.lfOrientation = lfNew.lfWeight = 0;
hfNew = CreateFontIndirect(&lfNew); } else { hfNew = hfont; }
SendMessage(hwndCtl, WM_SETFONT, (WPARAM)hfNew, (LPARAM)TRUE);
if (hfNew == hfont) { hfNew = NULL; } }
|