Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1346 lines
40 KiB

/******************************************************************************
Source File: Glyph Map View.CPP
This file implements the items that make up the glyph mapping editor
Copyright (c) 1997 by Microsoft Corporation. All Rights Reserved.
A Pretty Penny Enterprises Production
Change History:
02-20-1997 [email protected] Created it.
******************************************************************************/
#include "StdAfx.H"
#include <gpdparse.h>
#include "MiniDev.H"
#include "GTT.H"
#include "ChildFrm.H"
#include "GTTView.H"
#include "Resource.H"
#include "comctrls.h"
#include "NewProj.H"
#include <CodePage.H>
#include "AddCdPt.H"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/******************************************************************************
CGlyphMapView class implementation
This is the view class for glyph translation tables. It presents a property
sheet for display of all of the relevant items in the glyph map.
******************************************************************************/
IMPLEMENT_DYNCREATE(CGlyphMapView, CView)
CGlyphMapView::CGlyphMapView() {
}
CGlyphMapView::~CGlyphMapView() {
}
BEGIN_MESSAGE_MAP(CGlyphMapView, CView)
//{{AFX_MSG_MAP(CGlyphMapView)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/******************************************************************************
CGlyphMapView::OnInitialUpdate
This member function is an override which handles the initial call to display
the view. It creates the property sheet, positions it within the view, then
sets the frame size to match.
******************************************************************************/
void CGlyphMapView::OnInitialUpdate() {
if (GetDocument() -> GlyphMap() -> Name().IsEmpty()) {
GetDocument() -> GlyphMap() -> Rename(GetDocument() -> GetTitle());
GetDocument() -> SetModifiedFlag(FALSE); // Rename sets it
}
m_cps.Construct(IDR_MAINFRAME, this);
m_cgmp.Init(GetDocument() -> GlyphMap());
m_ccpp.Init(GetDocument() -> GlyphMap());
m_cpm.Init(GetDocument() -> GlyphMap());
m_cps.AddPage(&m_cgmp);
m_cps.AddPage(&m_ccpp);
#if defined(NOPOLLO) // RAID 106376
m_cps.AddPage(&m_cpm);
#endif
m_cps.Create(this, WS_CHILD, WS_EX_CLIENTEDGE);
CRect crPropertySheet;
m_cps.GetWindowRect(crPropertySheet);
crPropertySheet -= crPropertySheet.TopLeft();
m_cps.MoveWindow(crPropertySheet, FALSE);
GetParentFrame() -> CalcWindowRect(crPropertySheet);
GetParentFrame() -> SetWindowPos(NULL, 0, 0, crPropertySheet.Width(),
crPropertySheet.Height(),
SWP_NOZORDER | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
CView::OnInitialUpdate();
m_cps.ShowWindow(SW_SHOWNA);
GetParentFrame() -> ShowWindow(SW_SHOW);
}
void CGlyphMapView::OnDraw(CDC* pDC) {
CDocument* pDoc = GetDocument();
// TODO: add draw code here
}
/******************************************************************************
CGlyphMapView::SaveBothSelAndDeselStrings
Save both the codepage, Select and the Deselect strings if they have changed.
This routine is generally called by the document class to make sure this
data is copied into the GTT before the GTT is saved.
******************************************************************************/
void CGlyphMapView::SaveBothSelAndDeselStrings()
{
m_ccpp.SaveBothSelAndDeselStrings() ;
}
/////////////////////////////////////////////////////////////////////////////
// CGlyphMapView diagnostics
#ifdef _DEBUG
void CGlyphMapView::AssertValid() const {
CView::AssertValid();
}
void CGlyphMapView::Dump(CDumpContext& dc) const {
CView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CGlyphMapView message handlers
void CGlyphMapView::OnDestroy() {
CView::OnDestroy();
if (GetDocument() -> GlyphMap())
GetDocument() -> GlyphMap() -> OnEditorDestroyed();
}
/******************************************************************************
CGlyphMapView::OnActivateView
For some reason, the property sheet does not get the focus when the frame is
activated (probably the view class takes it away from us). This member
function guarantees keyboard afficionados aren't perturbed by this.
******************************************************************************/
void CGlyphMapView::OnActivateView(BOOL bActivate, CView* pActivateView,
CView* pDeactiveView) {
CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
if (bActivate)
m_cps.SetFocus();
}
/******************************************************************************
CGlyphMappingPage class
This class implements the property page for viewing and editing the gory code
point-by-code point details.
******************************************************************************/
// Even before the constructor, we have the list sorting routine
int CALLBACK CGlyphMappingPage::MapSorter(LPARAM lp1, LPARAM lp2,
LPARAM lpThis) {
// A negative return means the first is less...
// First, let's uncast those LPARAMs
CGlyphMappingPage *pcgmp = (CGlyphMappingPage *) lpThis;
CGlyphHandle *pcgh1 = (CGlyphHandle*) lp1;
CGlyphHandle *pcgh2 = (CGlyphHandle*) lp2;
// We'll use 3 columns to store the sort possibilities.
int aiResult[Columns];
aiResult[Codes] = pcgh1 -> CodePoint() - pcgh2 -> CodePoint();
aiResult[Pages] = pcgh1 -> CodePage() - pcgh2 -> CodePage();
CString cs1, cs2;
pcgh1 -> GetEncoding(cs1);
pcgh2 -> GetEncoding(cs2);
aiResult[Strings] = lstrcmp(cs1, cs2);
if (aiResult[pcgmp -> m_bSortFirst])
return pcgmp -> m_abDirection[pcgmp -> m_bSortFirst] ?
aiResult[pcgmp -> m_bSortFirst] : -aiResult[pcgmp -> m_bSortFirst];
if (aiResult[pcgmp -> m_bSortSecond])
return pcgmp -> m_abDirection[pcgmp -> m_bSortSecond] ?
aiResult[pcgmp -> m_bSortSecond] : -aiResult[pcgmp -> m_bSortSecond];
return pcgmp -> m_abDirection[pcgmp -> m_bSortLast] ?
aiResult[pcgmp -> m_bSortLast] : -aiResult[pcgmp -> m_bSortLast];
}
/******************************************************************************
CGlyphMappingPage constructor
As befits a class of this complexity, there's a bit of work to do here.
******************************************************************************/
CGlyphMappingPage::CGlyphMappingPage() :
CPropertyPage(CGlyphMappingPage::IDD) {
m_pcgm = NULL;
for (unsigned u = 0; u < Columns; u++)
m_abDirection[u] = TRUE;
m_bSortFirst = Codes;
m_bSortSecond = Strings;
m_bSortLast = Pages;
m_bJustChangedSelectString = FALSE;
m_uTimer = m_uidGlyph = 0;
//{{AFX_DATA_INIT(CGlyphMappingPage)
//}}AFX_DATA_INIT
}
CGlyphMappingPage::~CGlyphMappingPage() {
}
void CGlyphMappingPage::DoDataExchange(CDataExchange* pDX) {
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CGlyphMappingPage)
DDX_Control(pDX, IDC_Banner, m_cpcBanner);
DDX_Control(pDX, IDC_GlyphMapping, m_clcMap);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CGlyphMappingPage, CPropertyPage)
//{{AFX_MSG_MAP(CGlyphMappingPage)
ON_WM_CONTEXTMENU()
ON_NOTIFY(LVN_ENDLABELEDIT, IDC_GlyphMapping, OnEndlabeleditGlyphMapping)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_GlyphMapping, OnItemchangedGlyphMapping)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_GlyphMapping, OnColumnclickGlyphMapping)
ON_NOTIFY(LVN_GETDISPINFO, IDC_GlyphMapping, OnGetdispinfoGlyphMapping)
ON_NOTIFY(LVN_KEYDOWN, IDC_GlyphMapping, OnKeydownGlyphMapping)
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_COMMAND(ID_ChangeInvocation, OnChangeInvocation)
ON_COMMAND(ID_ChangeCodePage, OnChangeCodePage)
ON_COMMAND(ID_DeleteItem, OnDeleteItem)
ON_COMMAND(ID_AddItem, OnAddItem)
END_MESSAGE_MAP()
/******************************************************************************
CGlyphMappingPage::OnInitDialog
This member intializes the controls on this page, which in this case means a
list view with a sizeable numer of items.
******************************************************************************/
BOOL CGlyphMappingPage::OnInitDialog() {
CPropertyPage::OnInitDialog();
// Initialize the list control
CString csWork;
csWork.LoadString(IDS_MapColumn0);
m_clcMap.InsertColumn(0, csWork, LVCFMT_LEFT,
m_clcMap.GetStringWidth(csWork) * 2, 2);
csWork.LoadString(IDS_MapColumn1);
m_clcMap.InsertColumn(1, csWork, LVCFMT_LEFT,
m_clcMap.GetStringWidth(csWork) * 2, 1);
csWork.LoadString(IDS_MapColumn2);
m_clcMap.InsertColumn(2, csWork, LVCFMT_LEFT,
m_clcMap.GetStringWidth(csWork) * 2, 0);
m_lPredefinedID = m_pcgm -> PredefinedID();
// Put up a message about the wait, then kick off a quick timer so the
// message is seen...
m_uTimer = (unsigned)SetTimer(IDD, 100, NULL);
if (!m_uTimer) {
CWaitCursor cwc;
OnTimer(m_uTimer);
}
//LoadCharMapList() ;
return TRUE;
}
/******************************************************************************
CGlyphMappingPage::OnContextMenu
This member function is called when a right-click with the mouse is detected.
If it is within the area of the list view, we display an appropriate context
menu. Otherwise, we default to the normal system handling of the message.
******************************************************************************/
void CGlyphMappingPage::OnContextMenu(CWnd* pcw, CPoint cpt) {
CPoint cptThis = cpt;
m_clcMap.ScreenToClient(&cptThis);
// Toss it out if it isn't within the view.
CRect crMap;
m_clcMap.GetClientRect(crMap);
if (!crMap.PtInRect(cptThis))
return;
cptThis.x = 5; // Keep it well within the first column
int idContext = m_clcMap.HitTest(cptThis);
if (idContext == -1) { // Nothing selected, allow the "Add" item
CMenu cmThis;
CString csWork;
cmThis.CreatePopupMenu();
csWork.LoadString(ID_AddItem);
cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_AddItem, csWork);
cmThis.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, cpt.x, cpt.y,
this);
return;
}
m_clcMap.SetItemState(idContext, LVIS_SELECTED | LVIS_FOCUSED,
LVIS_SELECTED | LVIS_FOCUSED);
CMenu cmThis;
CString csWork;
cmThis.CreatePopupMenu();
csWork.LoadString(ID_ChangeInvocation);
cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_ChangeInvocation,
csWork);
if (m_pcgm -> CodePages() > 1) {
csWork.LoadString(ID_ChangeCodePage);
cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_ChangeCodePage,
csWork);
}
cmThis.AppendMenu(MF_SEPARATOR);
csWork.LoadString(ID_AddItem);
cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_AddItem, csWork);
csWork.LoadString(ID_DeleteItem);
cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_DeleteItem,
csWork);
cmThis.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, cpt.x, cpt.y, this);
}
/******************************************************************************
CGlyphMappingPage::OnChangeInvocation
Called when the user decides to change the invocation for the code point.
Simply initiate a label edit.
******************************************************************************/
void CGlyphMappingPage::OnChangeInvocation() {
int idContext = m_clcMap.GetNextItem(-1,
LVNI_ALL | LVNI_FOCUSED | LVNI_SELECTED);
if (idContext < 0 || idContext >= m_clcMap.GetItemCount())
return;
m_clcMap.EditLabel(idContext);
}
/******************************************************************************
CGlyphMappingPage::OnChangeCodePage
This handles a code page change request.
******************************************************************************/
void CGlyphMappingPage::OnChangeCodePage() {
int idContext = m_clcMap.GetNextItem(-1,
LVNI_ALL | LVNI_FOCUSED | LVNI_SELECTED);
if (idContext < 0 || idContext >= m_clcMap.GetItemCount())
return;
// Create a string naming the item, and invoke the CSelectCodePage
// dialog...
CGlyphHandle *pcgh = (CGlyphHandle*) m_clcMap.GetItemData(idContext);
CSelectCodePage cscp(this, m_pcgm -> Name() + _TEXT(" ") +
m_clcMap.GetItemText(idContext, 1),
m_pcgm -> PageID(pcgh -> CodePage()));
CDWordArray cdaPages;
m_pcgm -> CodePages(cdaPages);
cdaPages.RemoveAt(pcgh -> CodePage());
cscp.LimitTo(cdaPages);
if (cscp.DoModal() != IDOK)
return;
// Change the code page. For maximum flexibility, we'll use an array
// for this. This is because if this is to correct a perceived mistake,
// the codes should be translated to MBCS and then back.
// NOTE: This was also to support multiple selection, which isn't allowed.
CPtrArray cpaThis;
cpaThis.Add((void *) m_clcMap.GetItemData(idContext));
m_pcgm -> ChangeCodePage(cpaThis, cscp.SelectedCodePage());
m_clcMap.SetItemText(idContext, 2, cscp.GetCodePageName());
}
/******************************************************************************
CGlyphMappingPage::OnDeleteItem
This handles the Delete Item message from the context menu, by verifying
this is what is wanted, and then doing it.
******************************************************************************/
void CGlyphMappingPage::OnDeleteItem() {
int idContext = m_clcMap.GetNextItem(-1,
LVNI_ALL | LVNI_FOCUSED | LVNI_SELECTED);
if (idContext < 0 || idContext >= m_clcMap.GetItemCount())
return;
if (IDYES != AfxMessageBox(IDS_DeleteItemQuery,
MB_YESNO | MB_ICONQUESTION))
return;
// Delete the entry from the glyph map
CGlyphHandle* pcgh = (CGlyphHandle*) m_clcMap.GetItemData(idContext);
m_pcgm -> DeleteGlyph(pcgh -> CodePoint());
m_clcMap.DeleteItem(idContext);
_ASSERTE((unsigned) m_clcMap.GetItemCount() == m_pcgm -> Glyphs());
}
/******************************************************************************
CGlyphMappingPage::OnAddItem
This is called whenever the user wishes to add new code points to the map. I
ask the glyph map which points exist, and if there are any, invoke a modal
dialog to allow the selection of new glyphs.
******************************************************************************/
void CGlyphMappingPage::OnAddItem() {
CMapWordToDWord cmw2dAvailable;
m_pcgm -> UndefinedPoints(cmw2dAvailable);
if (!cmw2dAvailable.Count()) {
AfxMessageBox(IDS_NoUnmappedGlyphs);
return;
}
CDWordArray cdaPages;
m_pcgm -> CodePages(cdaPages);
CAddCodePoints cacp(this, cmw2dAvailable, cdaPages, m_pcgm -> Name());
if (cacp.DoModal() != IDOK) return;
// The map will now contain only the new code points...
m_pcgm -> AddPoints(cmw2dAvailable);
m_uTimer = (unsigned) SetTimer(IDD, 10, NULL);
if (!m_uTimer)
OnTimer(m_uTimer);
// Reset the sort criteria so we don't have to sort the data
for (unsigned u = 0; u < Columns; u++)
m_abDirection[u] = TRUE;
m_bSortFirst = Codes;
m_bSortSecond = Strings;
m_bSortLast = Pages;
}
/******************************************************************************
CGlyphMappingPage::OnEndlabeleditGlyphMapping
This is called when a user clicks outside the edit control to end editing of
a selection string. We pass the string down, and do some finagling to force
the system to accept the value as we display it, which isn't as the user
typed it, in some cases.
******************************************************************************/
void CGlyphMappingPage::OnEndlabeleditGlyphMapping(NMHDR* pnmh, LRESULT* plr)
{
LV_DISPINFO* plvdi = (LV_DISPINFO*) pnmh;
// Pass the new invocation string to the glyph map to handle
CGlyphHandle* pcgh = (CGlyphHandle*) plvdi -> item.lParam;
m_pcgm -> ChangeEncoding(pcgh -> CodePoint(), plvdi -> item.pszText);
m_bJustChangedSelectString = TRUE;
*plr = TRUE;
}
/******************************************************************************
CGlyphMappingPage::OnItemchangedGlyphMapping
This is called whenever anything changes in the list box- we are primarily
interested in text changes (since we have to adjust encodings once entered)
and selection changes (so we can move the "cursor" accordingly.
******************************************************************************/
void CGlyphMappingPage::OnItemchangedGlyphMapping(NMHDR* pnmh, LRESULT* plr)
{
NM_LISTVIEW* pnmlv = (NM_LISTVIEW*) pnmh;
int idContext = m_clcMap.GetNextItem(-1,
LVNI_ALL | LVNI_FOCUSED | LVNI_SELECTED);
// We only care if this notes a text change in the selected item and we
// haven't fixed it, yet.
if (pnmlv -> iItem != idContext || !(pnmlv -> uChanged & LVIF_TEXT) ||
!m_bJustChangedSelectString)
return;
CGlyphHandle* pcgh = (CGlyphHandle*) m_clcMap.GetItemData(idContext);
CString csWork;
m_bJustChangedSelectString = FALSE;
pcgh -> GetEncoding(csWork);
m_clcMap.SetItemText(idContext, 0, csWork);
*plr = 0;
}
/******************************************************************************
CGlyphMappingPage::OnColumnclickGlyphMapping
Called when the user wants to sort the list- so that's what we do!
******************************************************************************/
void CGlyphMappingPage::OnColumnclickGlyphMapping(NMHDR* pnmh, LRESULT* plr) {
NM_LISTVIEW* pnmlv = (NM_LISTVIEW*) pnmh;
// Resort the list based upon the selected column, and the current sort
// order
if (pnmlv -> iSubItem == m_bSortFirst)
m_abDirection[m_bSortFirst] = !m_abDirection[m_bSortFirst]; // Reverse
else {
if (pnmlv -> iSubItem == m_bSortSecond)
m_bSortSecond = m_bSortFirst;
else {
m_bSortLast = m_bSortSecond;
m_bSortSecond = m_bSortFirst;
}
m_bSortFirst = (BYTE)pnmlv -> iSubItem;
}
CWaitCursor cwc; // On FE tables, this can take a while...
m_clcMap.SortItems(&MapSorter, (UINT_PTR) this);
*plr = 0;
}
void CGlyphMappingPage::LoadCharMapList()
{
CWaitCursor cwc ;
m_clcMap.EnableWindow(FALSE) ;
CGlyphHandle* pcgh ;
int idItem ;
CString csWork ;
for (unsigned u = 0 ; m_uidGlyph < m_pcgm -> Glyphs() ; u++, m_uidGlyph++) {
pcgh = m_pcgm->Glyph(m_uidGlyph) ;
if(pcgh != NULL)
pcgh->GetEncoding(csWork) ;
else
{
AfxMessageBox(IDS_LoadGTTError);//raid 116604 prefix : this fucntion(LoadCharMapList) are dead
return ;
} ;
idItem = m_clcMap.InsertItem(m_uidGlyph, csWork) ;
m_clcMap.SetItemData(idItem, (LPARAM) pcgh) ;
csWork.Format(_TEXT("0x%4.4X"), pcgh->CodePoint()) ;
m_clcMap.SetItem(idItem, 1, LVIF_TEXT, csWork, -1, 0, 0, u) ;
csWork = m_pcgm->PageName(pcgh->CodePage()) ;
m_clcMap.SetItem(idItem, 2, LVIF_TEXT, csWork, -1, 0, 0, u) ;
}
m_clcMap.EnableWindow(TRUE) ;
m_cpcBanner.SetPos(0) ;
m_cpcBanner.ShowWindow(SW_HIDE) ;
}
/******************************************************************************
CGlyphMappingPage::OnGetdispinfoGlyphMapping
This member function is an attempt to speed handling of large tables, and
also to handle code page changes more gracefully. All items are initially
declared as callbacks, so the control requests names for items as they are
displayed, via this member.
******************************************************************************/
void CGlyphMappingPage::OnGetdispinfoGlyphMapping(NMHDR* pnmh, LRESULT* plr) {
LV_DISPINFO* plvdi = (LV_DISPINFO*) pnmh;
*plr = 0;
// If the window is obstructed when an item is deleted, there might not
// be a glpyh at this point, so watch out!
CGlyphHandle* pcgh = (CGlyphHandle*) plvdi -> item.lParam;
if (!pcgh)
return;
CString csWork;
switch (plvdi -> item.iSubItem) {
case 0:
pcgh -> GetEncoding(csWork);
break;
case 1:
csWork.Format(_TEXT("0x%4.4X"), pcgh -> CodePoint());
plvdi -> item.mask |= LVIF_DI_SETITEM; // This never changes
break;
case 2:
csWork = m_pcgm -> PageName(pcgh -> CodePage());
}
lstrcpyn(plvdi -> item.pszText, csWork, plvdi -> item.cchTextMax);
}
/******************************************************************************
CGlyphMappingPage::OnSetActive
Called when the page is activated, but after OnInitDialog on the first
activation. If the predefined code page ID has changed, we must rebuild the
page.
******************************************************************************/
// //raid 118880
BOOL CGlyphMappingPage::OnSetActive() {
m_lPredefinedID = m_pcgm -> PredefinedID();
m_uTimer = (unsigned) SetTimer(IDD, 10, NULL);
m_clcMap.DeleteAllItems();
OnTimer(m_uTimer);
return CPropertyPage::OnSetActive();
}
/******************************************************************************
CGlyphMappingPage::OnKeydownGlyphMapping
This is called whenever the user presses a key. We use it to provide an
extended interface from the keyboard, to match the other editors.
******************************************************************************/
void CGlyphMappingPage::OnKeydownGlyphMapping(NMHDR* pnmh, LRESULT* plr)
{
LV_KEYDOWN* plvkd = (LV_KEYDOWN*)pnmh;
if (plvkd->wVKey == VK_F1) {
AfxGetApp()->WinHelp(HID_BASE_RESOURCE + IDR_GLYPHMAP) ;
return ;
} ;
*plr = 0;
int idItem = m_clcMap.GetNextItem(-1, LVIS_FOCUSED | LVIS_SELECTED);
if (idItem == -1) {
if (plvkd -> wVKey == VK_F10)
OnAddItem();
return;
}
switch (plvkd -> wVKey) {
case VK_F2:
OnChangeInvocation();
break;
case VK_DELETE:
OnDeleteItem();
break;
case VK_F10: {
CRect crItem;
m_clcMap.GetItemRect(idItem, crItem, LVIR_LABEL);
m_clcMap.ClientToScreen(crItem);
OnContextMenu(&m_clcMap, crItem.CenterPoint());
}
}
}
/******************************************************************************
CGlhpyMappingPage::OnTimer
The only event currently using a timer is the need to fill the list.
******************************************************************************/
void CGlyphMappingPage::OnTimer(UINT uEvent) {
if (uEvent != m_uTimer) {
CPropertyPage::OnTimer(uEvent);
return;
}
CString csWork;
if (m_uTimer)
::KillTimer(m_hWnd, m_uTimer);
if (!m_uidGlyph) {
m_clcMap.DeleteAllItems();
m_cpcBanner.SetRange(0, m_pcgm -> Glyphs() -1);
m_cpcBanner.SetStep(1);
m_cpcBanner.SetPos(0);
m_cpcBanner.ShowWindow(SW_SHOW);
csWork.LoadString(IDS_WaitToFill);
CDC *pcdc = m_cpcBanner.GetDC();
CRect crBanner;
m_cpcBanner.GetClientRect(crBanner);
pcdc -> SetBkMode(TRANSPARENT);
pcdc -> DrawText(csWork, crBanner, DT_CENTER | DT_VCENTER);
m_cpcBanner.ReleaseDC(pcdc);
if (m_uTimer)
m_clcMap.EnableWindow(FALSE);
else
m_clcMap.LockWindowUpdate();
m_clcMap.SetItemCount(m_pcgm -> Glyphs());
}
for (unsigned u = 0;
m_uidGlyph < m_pcgm -> Glyphs() && (!m_uTimer || u < 100);
u++, m_uidGlyph++) {
CGlyphHandle* pcgh = m_pcgm -> Glyph(m_uidGlyph);
int idItem = m_clcMap.InsertItem(m_uidGlyph, LPSTR_TEXTCALLBACK);
m_clcMap.SetItemData(idItem, (LPARAM) pcgh);
m_clcMap.SetItem(idItem, 1, LVIF_TEXT, LPSTR_TEXTCALLBACK, -1, 0, 0,
(LPARAM) pcgh);
m_clcMap.SetItem(idItem, 2, LVIF_TEXT, LPSTR_TEXTCALLBACK, -1, 0, 0,
(LPARAM) pcgh);
}
if (m_uidGlyph == m_pcgm -> Glyphs()) {
if (m_uTimer)
m_clcMap.EnableWindow(TRUE);
else
m_clcMap.UnlockWindowUpdate();
m_uTimer = 0;
m_cpcBanner.SetPos(0);
m_cpcBanner.ShowWindow(SW_HIDE);
SetFocus();
m_uidGlyph = 0;
}
if (m_uTimer) {
m_cpcBanner.SetPos(m_uidGlyph);
csWork.LoadString(IDS_WaitToFill);
CDC *pcdc = m_cpcBanner.GetDC();
CRect crBanner;
m_cpcBanner.GetClientRect(crBanner);
pcdc -> SetBkMode(TRANSPARENT);
pcdc -> DrawText(csWork, crBanner, DT_CENTER | DT_VCENTER);
m_cpcBanner.ReleaseDC(pcdc);
m_uTimer = (unsigned) SetTimer(IDD, 10, NULL);
if (!m_uTimer) {
CWaitCursor cwc; // Might be a while...
m_clcMap.EnableWindow(TRUE);
m_clcMap.LockWindowUpdate();
OnTimer(m_uTimer);
}
}
}
/******************************************************************************
CGlyphMappingPage::OnDestroy
Since this also can be time-consuming, kill the list here, and throw up the
wait cursor.
******************************************************************************/
void CGlyphMappingPage::OnDestroy() {
CWaitCursor cwc;
if (m_uTimer)
::KillTimer(m_hWnd, m_uTimer);
m_clcMap.DeleteAllItems();
CPropertyPage::OnDestroy();
}
/******************************************************************************
CCodePagePage class implementation
This class implements the code page property page, providing an interface for
viewing and implementing the code page assignments.
******************************************************************************/
CCodePagePage::CCodePagePage() : CToolTipPage(CCodePagePage::IDD)
{
//{{AFX_DATA_INIT(CCodePagePage)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_uHelpID = HID_BASE_RESOURCE + IDR_GLYPHMAP ;
m_bInitialized = false ;
m_bSelDeselChgSignificant = true ;
}
CCodePagePage::~CCodePagePage() {
}
void CCodePagePage::DoDataExchange(CDataExchange* pDX) {
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCodePagePage)
DDX_Control(pDX, IDC_DeletePage, m_cbDelete);
DDX_Control(pDX, IDC_SelectString, m_ceSelect);
DDX_Control(pDX, IDC_DeselectString, m_ceDeselect);
DDX_Control(pDX, IDC_RemovePage, m_cbRemove);
DDX_Control(pDX, IDC_CodePageList, m_clbPages);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCodePagePage, CToolTipPage)
//{{AFX_MSG_MAP(CCodePagePage)
ON_EN_KILLFOCUS(IDC_SelectString, OnKillfocusSelectString)
ON_EN_KILLFOCUS(IDC_DeselectString, OnKillfocusDeselectString)
ON_BN_CLICKED(IDC_AddPage, OnAddPage)
ON_LBN_SELCHANGE(IDC_CodePageList, OnSelchangeCodePageList)
ON_BN_CLICKED(IDC_RemovePage, OnReplacePage)
ON_EN_CHANGE(IDC_SelectString, OnChangeSelectString)
ON_EN_CHANGE(IDC_DeselectString, OnChangeDeselectString)
ON_BN_CLICKED(IDC_DeletePage, OnDeletePage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/******************************************************************************
CCodePagePage::OnInitDialog
This member function handles the WM_INITDIALOG message by initializing the
various controls of the dialog.
******************************************************************************/
BOOL CCodePagePage::OnInitDialog() {
CToolTipPage::OnInitDialog();
for (unsigned u = 0; u < m_pcgm -> CodePages(); u++) {
int id =
m_clbPages.AddString(m_pcgm -> PageName(u));
m_clbPages.SetItemData(id, u);
if (!u)
m_clbPages.SetCurSel(id);
}
// Let the list box selection change handler do the rest
OnSelchangeCodePageList();
m_bInitialized = true ;
return TRUE;
}
/******************************************************************************
CCodePagePage::OnChangeSelectString
Mark the GTT dirty to make sure the new string is saved.
******************************************************************************/
void CCodePagePage::OnChangeSelectString()
{
// Only mark the GTT as having changed when this function is called after
// the GTT Editor and only if this change in the selection string is
// significant. Do nothing when the string change is just because a
// previously entered string is being loaded into the control.
if (m_bInitialized && m_bSelDeselChgSignificant)
m_pcgm->Changed() ;
}
/******************************************************************************
CCodePagePage::OnChangeDeselectString
Mark the GTT dirty to make sure the new string is saved.
******************************************************************************/
void CCodePagePage::OnChangeDeselectString()
{
// Only mark the GTT as having changed when this function is called after
// the GTT Editor and only if this change in the deselection string is
// significant. Do nothing when the string change is just because a
// previously entered string is being loaded into the control.
if (m_bInitialized && m_bSelDeselChgSignificant)
m_pcgm->Changed() ;
}
/******************************************************************************
CCodePagePage::OnKillfocusSelectString
Save the Select String if it has changed.
******************************************************************************/
void CCodePagePage::OnKillfocusSelectString()
{
SaveSelDeselString(m_ceSelect, TRUE) ;
}
/******************************************************************************
CCodePagePage::OnKillfocusDeselectString
Save the Deselect String if it has changed.
******************************************************************************/
void CCodePagePage::OnKillfocusDeselectString()
{
SaveSelDeselString(m_ceDeselect, FALSE) ;
}
/******************************************************************************
CCodePagePage::SaveBothSelAndDeselStrings
Save both the Select and the Deselect strings if they have changed.
******************************************************************************/
void CCodePagePage::SaveBothSelAndDeselStrings()
{
SaveSelDeselString(m_ceSelect, TRUE) ;
SaveSelDeselString(m_ceDeselect, FALSE) ;
}
/******************************************************************************
CCodePagePage::SaveSelDeselString
This function is called to update the GTT when the Selection or Deselection
string may have changed. Check to see if the control really was modified, and
if it is, update the structure accordingly. Then flag the control as
unmodified.
******************************************************************************/
void CCodePagePage::SaveSelDeselString(CEdit &cesd, BOOL bselstr)
{
// Do nothing if the control has not been modified.
if (!cesd || !cesd.GetModify())
return ;
// Get the new sel/desel string.
CString csWork ;
cesd.GetWindowText(csWork) ;
// Save the sel/desel string as determined by bselstr. (Note:
// SetInvocation() sets the GTT's changed flag, too.)
m_pcgm -> SetInvocation(
(unsigned)m_clbPages.GetItemData(m_clbPages.GetCurSel()), csWork,
bselstr) ;
// Clear the control's modified flag.
cesd.SetModify(FALSE) ;
// Now make sure that the string is displayed correctly.
m_pcgm -> Invocation(
(unsigned)m_clbPages.GetItemData(m_clbPages.GetCurSel()), csWork,
bselstr) ;
cesd.SetWindowText(csWork) ;
}
/******************************************************************************
CCodePagePage::OnAddPage
This is an event handler for the pressing of the "Add Page" button. We invoke
the Select Code Page dialog, and if a new page is selected, we add it to the
list of pages that are available.
******************************************************************************/
void CCodePagePage::OnAddPage() {
CDWordArray cdaPages;
m_pcgm -> CodePages(cdaPages);
CSelectCodePage cscp(this, m_pcgm -> Name(), 0);
cscp.Exclude(cdaPages);
if (cscp.DoModal() != IDOK)
return;
m_pcgm -> AddCodePage(cscp.SelectedCodePage());
int id =
m_clbPages.AddString(m_pcgm -> PageName(m_pcgm -> CodePages() - 1));
m_clbPages.SetItemData(id, m_pcgm -> CodePages() -1);
m_clbPages.SetCurSel(id);
// Let OnSelchangeCodePageList do the rest (that's what happened, eh?)
OnSelchangeCodePageList();
m_ceSelect.SetFocus(); // A friendly place to leave it...
}
/******************************************************************************
CCodePagePage::OnSelchangeCodePageList
This member function handles changes in the selected code page. It fills
the edit controls for the selected page's name, selection and deselection
strings, and handles enabling of the "Remove Page" button (this message
could mean nothing is now selected...)
Make sure that the operations of this function do not mark the GTT dirty.
******************************************************************************/
void CCodePagePage::OnSelchangeCodePageList()
{
m_bSelDeselChgSignificant = false ;
int id = m_clbPages.GetCurSel();
if (id < 0) {
m_ceSelect.SetWindowText(_T(""));
m_ceDeselect.SetWindowText(_T(""));
m_cbRemove.EnableWindow(FALSE);
m_cbDelete.EnableWindow(FALSE);
m_ceSelect.EnableWindow(FALSE);
m_ceDeselect.EnableWindow(FALSE);
m_bSelDeselChgSignificant = true ;
return;
}
unsigned u = (unsigned)m_clbPages.GetItemData(id);
SetDlgItemText(IDC_CurrentPage, m_pcgm -> PageName(u));
CString csWork;
m_pcgm -> Invocation(u, csWork, TRUE);
m_ceSelect.SetWindowText(csWork);
m_pcgm -> Invocation(u, csWork, FALSE);
m_ceDeselect.SetWindowText(csWork);
m_cbRemove.EnableWindow(m_pcgm -> CodePages() > 1);
m_cbDelete.EnableWindow(m_pcgm -> CodePages() > 1); // r118880
m_ceSelect.EnableWindow();
m_ceDeselect.EnableWindow();
m_bSelDeselChgSignificant = true ;
}
/******************************************************************************
CCodePagePage::OnReplacePage
This handles the Remove Page button. Not much to it, here- we just tell the
glyph map what we want done.
******************************************************************************/
void CCodePagePage::OnReplacePage() {
int id = m_clbPages.GetCurSel();
if (id < 0 || m_clbPages.GetCount() < 2)
return;
unsigned u = (unsigned)m_clbPages.GetItemData(id);
// Query for code page to map this one to
CSelectCodePage cscp(this,
CString(_TEXT("Replacing ")) + m_pcgm -> PageName(u), 0);
CDWordArray cdaPages;
m_pcgm -> CodePages(cdaPages);
cdaPages.RemoveAt(u);
cscp.LimitTo(cdaPages);
if (cscp.DoModal() != IDOK)
return;
for (unsigned uTo = 0; uTo < m_pcgm -> CodePages(); uTo++)
if (m_pcgm -> PageID(uTo) == cscp.SelectedCodePage())
break;
_ASSERTE(uTo < (unsigned) m_pcgm -> CodePages());
if (!m_pcgm -> RemovePage(u, uTo))
return;
// Flush the list box and then refill it.
m_clbPages.ResetContent();
for (u = 0; u < m_pcgm -> CodePages(); u++) {
int id = m_clbPages.AddString(m_pcgm -> PageName(u));
m_clbPages.SetItemData(id, u);
}
// Select whoever moved into our position, then update the rest
m_clbPages.SetCurSel(id < m_clbPages.GetCount() ? id : id - 1);
OnSelchangeCodePageList();
}
/******************************************************************************
//raid 118880
CCodePagePage::OnDeletePage
message handler :Delete code page when user push delete button
logic : get page id of selected code -> get codepage id from Glyphmap ->
call pcgm-> DeleteCodePage: actual part of deleting -> reset list box
********************************************************************************/
void CCodePagePage::OnDeletePage()
{
int id = m_clbPages.GetCurSel();
if (id < 0 || m_clbPages.GetCount() < 2)
return;
unsigned CodePageID = (unsigned)m_clbPages.GetItemData(id);
// Actual delete call
if (!m_pcgm -> RemovePage(CodePageID,CodePageID, TRUE))
return;
// Flush the list box and then refill it.
m_clbPages.ResetContent();
for (unsigned u = 0; u < m_pcgm -> CodePages(); u++) {
int id = m_clbPages.AddString(m_pcgm -> PageName(u));
m_clbPages.SetItemData(id, u);
}
// Select whoever moved into our position, then update the rest
m_clbPages.SetCurSel(id < m_clbPages.GetCount() ? id : id - 1);
OnSelchangeCodePageList();
}
/******************************************************************************
CPredefinedMaps class
This implements the class which handles the page for pre-defined mappings
in a GTT file.
******************************************************************************/
CPredefinedMaps::CPredefinedMaps() : CPropertyPage(CPredefinedMaps::IDD) {
//{{AFX_DATA_INIT(CPredefinedMaps)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
CPredefinedMaps::~CPredefinedMaps() {
}
void CPredefinedMaps::DoDataExchange(CDataExchange* pDX) {
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPredefinedMaps)
DDX_Control(pDX, IDC_PredefinedList, m_clbIDs);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPredefinedMaps, CPropertyPage)
//{{AFX_MSG_MAP(CPredefinedMaps)
ON_BN_CLICKED(IDC_Overstrike, OnOverstrike)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPredefinedMaps message handlers
/******************************************************************************
CPredefinedMaps::OnInitDialog
This override handles the WM_INITDIALOG message by initializing the various
controls.
******************************************************************************/
BOOL CPredefinedMaps::OnInitDialog() {
CPropertyPage::OnInitDialog();
// Fill the list box- first, with none, then with the defined IDs
CString csWork;
csWork.LoadString(IDS_NoPredefined);
m_clbIDs.AddString(csWork);
if (m_pcgm -> PredefinedID()== CGlyphMap::NoPredefined)
m_clbIDs.SetCurSel(0);
m_clbIDs.SetItemData(0, CGlyphMap::NoPredefined);
for (int i = CGlyphMap::Wansung; i < 1; i++) {
csWork.LoadString(IDS_DefaultPage + i);
if (csWork.IsEmpty())
continue;
int id = m_clbIDs.AddString(csWork);
m_clbIDs.SetItemData(id, i);
if (i == m_pcgm -> PredefinedID())
m_clbIDs.SetCurSel(i);
}
m_clbIDs.SetTopIndex(m_clbIDs.GetCurSel());
CheckDlgButton(IDC_Overstrike, m_pcgm -> OverStrike());
return TRUE; // return TRUE unless you set the focus to a control
}
/******************************************************************************
CPredefinedMaps::OnKillActive
This is called when we leave the page. Since changing pages can be very
time-consuming, we only check when you leave, not every time the selection
changes. Occasionally even my aged brain works.
******************************************************************************/
BOOL CPredefinedMaps::OnKillActive() {
if (m_clbIDs.GetCurSel() >= 0)
m_pcgm -> UsePredefined((unsigned)m_clbIDs.GetItemData(m_clbIDs.GetCurSel()));
return CPropertyPage::OnKillActive();
}
/******************************************************************************
CPredefinedMaps::OnOverstrike
Called when the user clicks the check box for enabling / disabling overstrike
******************************************************************************/
void CPredefinedMaps::OnOverstrike() {
m_pcgm -> OverStrike(IsDlgButtonChecked(IDC_Overstrike));
}