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

  1. /******************************************************************************
  2. Source File: Glyph Map View.CPP
  3. This file implements the items that make up the glyph mapping editor
  4. Copyright (c) 1997 by Microsoft Corporation. All Rights Reserved.
  5. A Pretty Penny Enterprises Production
  6. Change History:
  7. 02-20-1997 Bob_Kjelgaard@Prodigy.Net Created it.
  8. ******************************************************************************/
  9. #include "StdAfx.H"
  10. #include <gpdparse.h>
  11. #include "MiniDev.H"
  12. #include "GTT.H"
  13. #include "ChildFrm.H"
  14. #include "GTTView.H"
  15. #include "Resource.H"
  16. #include "comctrls.h"
  17. #include "NewProj.H"
  18. #include <CodePage.H>
  19. #include "AddCdPt.H"
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. /******************************************************************************
  26. CGlyphMapView class implementation
  27. This is the view class for glyph translation tables. It presents a property
  28. sheet for display of all of the relevant items in the glyph map.
  29. ******************************************************************************/
  30. IMPLEMENT_DYNCREATE(CGlyphMapView, CView)
  31. CGlyphMapView::CGlyphMapView() {
  32. }
  33. CGlyphMapView::~CGlyphMapView() {
  34. }
  35. BEGIN_MESSAGE_MAP(CGlyphMapView, CView)
  36. //{{AFX_MSG_MAP(CGlyphMapView)
  37. ON_WM_DESTROY()
  38. //}}AFX_MSG_MAP
  39. END_MESSAGE_MAP()
  40. /******************************************************************************
  41. CGlyphMapView::OnInitialUpdate
  42. This member function is an override which handles the initial call to display
  43. the view. It creates the property sheet, positions it within the view, then
  44. sets the frame size to match.
  45. ******************************************************************************/
  46. void CGlyphMapView::OnInitialUpdate() {
  47. if (GetDocument() -> GlyphMap() -> Name().IsEmpty()) {
  48. GetDocument() -> GlyphMap() -> Rename(GetDocument() -> GetTitle());
  49. GetDocument() -> SetModifiedFlag(FALSE); // Rename sets it
  50. }
  51. m_cps.Construct(IDR_MAINFRAME, this);
  52. m_cgmp.Init(GetDocument() -> GlyphMap());
  53. m_ccpp.Init(GetDocument() -> GlyphMap());
  54. m_cpm.Init(GetDocument() -> GlyphMap());
  55. m_cps.AddPage(&m_cgmp);
  56. m_cps.AddPage(&m_ccpp);
  57. #if defined(NOPOLLO) // RAID 106376
  58. m_cps.AddPage(&m_cpm);
  59. #endif
  60. m_cps.Create(this, WS_CHILD, WS_EX_CLIENTEDGE);
  61. CRect crPropertySheet;
  62. m_cps.GetWindowRect(crPropertySheet);
  63. crPropertySheet -= crPropertySheet.TopLeft();
  64. m_cps.MoveWindow(crPropertySheet, FALSE);
  65. GetParentFrame() -> CalcWindowRect(crPropertySheet);
  66. GetParentFrame() -> SetWindowPos(NULL, 0, 0, crPropertySheet.Width(),
  67. crPropertySheet.Height(),
  68. SWP_NOZORDER | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
  69. CView::OnInitialUpdate();
  70. m_cps.ShowWindow(SW_SHOWNA);
  71. GetParentFrame() -> ShowWindow(SW_SHOW);
  72. }
  73. void CGlyphMapView::OnDraw(CDC* pDC) {
  74. CDocument* pDoc = GetDocument();
  75. // TODO: add draw code here
  76. }
  77. /******************************************************************************
  78. CGlyphMapView::SaveBothSelAndDeselStrings
  79. Save both the codepage, Select and the Deselect strings if they have changed.
  80. This routine is generally called by the document class to make sure this
  81. data is copied into the GTT before the GTT is saved.
  82. ******************************************************************************/
  83. void CGlyphMapView::SaveBothSelAndDeselStrings()
  84. {
  85. m_ccpp.SaveBothSelAndDeselStrings() ;
  86. }
  87. /////////////////////////////////////////////////////////////////////////////
  88. // CGlyphMapView diagnostics
  89. #ifdef _DEBUG
  90. void CGlyphMapView::AssertValid() const {
  91. CView::AssertValid();
  92. }
  93. void CGlyphMapView::Dump(CDumpContext& dc) const {
  94. CView::Dump(dc);
  95. }
  96. #endif //_DEBUG
  97. /////////////////////////////////////////////////////////////////////////////
  98. // CGlyphMapView message handlers
  99. void CGlyphMapView::OnDestroy() {
  100. CView::OnDestroy();
  101. if (GetDocument() -> GlyphMap())
  102. GetDocument() -> GlyphMap() -> OnEditorDestroyed();
  103. }
  104. /******************************************************************************
  105. CGlyphMapView::OnActivateView
  106. For some reason, the property sheet does not get the focus when the frame is
  107. activated (probably the view class takes it away from us). This member
  108. function guarantees keyboard afficionados aren't perturbed by this.
  109. ******************************************************************************/
  110. void CGlyphMapView::OnActivateView(BOOL bActivate, CView* pActivateView,
  111. CView* pDeactiveView) {
  112. CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
  113. if (bActivate)
  114. m_cps.SetFocus();
  115. }
  116. /******************************************************************************
  117. CGlyphMappingPage class
  118. This class implements the property page for viewing and editing the gory code
  119. point-by-code point details.
  120. ******************************************************************************/
  121. // Even before the constructor, we have the list sorting routine
  122. int CALLBACK CGlyphMappingPage::MapSorter(LPARAM lp1, LPARAM lp2,
  123. LPARAM lpThis) {
  124. // A negative return means the first is less...
  125. // First, let's uncast those LPARAMs
  126. CGlyphMappingPage *pcgmp = (CGlyphMappingPage *) lpThis;
  127. CGlyphHandle *pcgh1 = (CGlyphHandle*) lp1;
  128. CGlyphHandle *pcgh2 = (CGlyphHandle*) lp2;
  129. // We'll use 3 columns to store the sort possibilities.
  130. int aiResult[Columns];
  131. aiResult[Codes] = pcgh1 -> CodePoint() - pcgh2 -> CodePoint();
  132. aiResult[Pages] = pcgh1 -> CodePage() - pcgh2 -> CodePage();
  133. CString cs1, cs2;
  134. pcgh1 -> GetEncoding(cs1);
  135. pcgh2 -> GetEncoding(cs2);
  136. aiResult[Strings] = lstrcmp(cs1, cs2);
  137. if (aiResult[pcgmp -> m_bSortFirst])
  138. return pcgmp -> m_abDirection[pcgmp -> m_bSortFirst] ?
  139. aiResult[pcgmp -> m_bSortFirst] : -aiResult[pcgmp -> m_bSortFirst];
  140. if (aiResult[pcgmp -> m_bSortSecond])
  141. return pcgmp -> m_abDirection[pcgmp -> m_bSortSecond] ?
  142. aiResult[pcgmp -> m_bSortSecond] : -aiResult[pcgmp -> m_bSortSecond];
  143. return pcgmp -> m_abDirection[pcgmp -> m_bSortLast] ?
  144. aiResult[pcgmp -> m_bSortLast] : -aiResult[pcgmp -> m_bSortLast];
  145. }
  146. /******************************************************************************
  147. CGlyphMappingPage constructor
  148. As befits a class of this complexity, there's a bit of work to do here.
  149. ******************************************************************************/
  150. CGlyphMappingPage::CGlyphMappingPage() :
  151. CPropertyPage(CGlyphMappingPage::IDD) {
  152. m_pcgm = NULL;
  153. for (unsigned u = 0; u < Columns; u++)
  154. m_abDirection[u] = TRUE;
  155. m_bSortFirst = Codes;
  156. m_bSortSecond = Strings;
  157. m_bSortLast = Pages;
  158. m_bJustChangedSelectString = FALSE;
  159. m_uTimer = m_uidGlyph = 0;
  160. //{{AFX_DATA_INIT(CGlyphMappingPage)
  161. //}}AFX_DATA_INIT
  162. }
  163. CGlyphMappingPage::~CGlyphMappingPage() {
  164. }
  165. void CGlyphMappingPage::DoDataExchange(CDataExchange* pDX) {
  166. CPropertyPage::DoDataExchange(pDX);
  167. //{{AFX_DATA_MAP(CGlyphMappingPage)
  168. DDX_Control(pDX, IDC_Banner, m_cpcBanner);
  169. DDX_Control(pDX, IDC_GlyphMapping, m_clcMap);
  170. //}}AFX_DATA_MAP
  171. }
  172. BEGIN_MESSAGE_MAP(CGlyphMappingPage, CPropertyPage)
  173. //{{AFX_MSG_MAP(CGlyphMappingPage)
  174. ON_WM_CONTEXTMENU()
  175. ON_NOTIFY(LVN_ENDLABELEDIT, IDC_GlyphMapping, OnEndlabeleditGlyphMapping)
  176. ON_NOTIFY(LVN_ITEMCHANGED, IDC_GlyphMapping, OnItemchangedGlyphMapping)
  177. ON_NOTIFY(LVN_COLUMNCLICK, IDC_GlyphMapping, OnColumnclickGlyphMapping)
  178. ON_NOTIFY(LVN_GETDISPINFO, IDC_GlyphMapping, OnGetdispinfoGlyphMapping)
  179. ON_NOTIFY(LVN_KEYDOWN, IDC_GlyphMapping, OnKeydownGlyphMapping)
  180. ON_WM_TIMER()
  181. ON_WM_DESTROY()
  182. //}}AFX_MSG_MAP
  183. ON_COMMAND(ID_ChangeInvocation, OnChangeInvocation)
  184. ON_COMMAND(ID_ChangeCodePage, OnChangeCodePage)
  185. ON_COMMAND(ID_DeleteItem, OnDeleteItem)
  186. ON_COMMAND(ID_AddItem, OnAddItem)
  187. END_MESSAGE_MAP()
  188. /******************************************************************************
  189. CGlyphMappingPage::OnInitDialog
  190. This member intializes the controls on this page, which in this case means a
  191. list view with a sizeable numer of items.
  192. ******************************************************************************/
  193. BOOL CGlyphMappingPage::OnInitDialog() {
  194. CPropertyPage::OnInitDialog();
  195. // Initialize the list control
  196. CString csWork;
  197. csWork.LoadString(IDS_MapColumn0);
  198. m_clcMap.InsertColumn(0, csWork, LVCFMT_LEFT,
  199. m_clcMap.GetStringWidth(csWork) * 2, 2);
  200. csWork.LoadString(IDS_MapColumn1);
  201. m_clcMap.InsertColumn(1, csWork, LVCFMT_LEFT,
  202. m_clcMap.GetStringWidth(csWork) * 2, 1);
  203. csWork.LoadString(IDS_MapColumn2);
  204. m_clcMap.InsertColumn(2, csWork, LVCFMT_LEFT,
  205. m_clcMap.GetStringWidth(csWork) * 2, 0);
  206. m_lPredefinedID = m_pcgm -> PredefinedID();
  207. // Put up a message about the wait, then kick off a quick timer so the
  208. // message is seen...
  209. m_uTimer = (unsigned)SetTimer(IDD, 100, NULL);
  210. if (!m_uTimer) {
  211. CWaitCursor cwc;
  212. OnTimer(m_uTimer);
  213. }
  214. //LoadCharMapList() ;
  215. return TRUE;
  216. }
  217. /******************************************************************************
  218. CGlyphMappingPage::OnContextMenu
  219. This member function is called when a right-click with the mouse is detected.
  220. If it is within the area of the list view, we display an appropriate context
  221. menu. Otherwise, we default to the normal system handling of the message.
  222. ******************************************************************************/
  223. void CGlyphMappingPage::OnContextMenu(CWnd* pcw, CPoint cpt) {
  224. CPoint cptThis = cpt;
  225. m_clcMap.ScreenToClient(&cptThis);
  226. // Toss it out if it isn't within the view.
  227. CRect crMap;
  228. m_clcMap.GetClientRect(crMap);
  229. if (!crMap.PtInRect(cptThis))
  230. return;
  231. cptThis.x = 5; // Keep it well within the first column
  232. int idContext = m_clcMap.HitTest(cptThis);
  233. if (idContext == -1) { // Nothing selected, allow the "Add" item
  234. CMenu cmThis;
  235. CString csWork;
  236. cmThis.CreatePopupMenu();
  237. csWork.LoadString(ID_AddItem);
  238. cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_AddItem, csWork);
  239. cmThis.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, cpt.x, cpt.y,
  240. this);
  241. return;
  242. }
  243. m_clcMap.SetItemState(idContext, LVIS_SELECTED | LVIS_FOCUSED,
  244. LVIS_SELECTED | LVIS_FOCUSED);
  245. CMenu cmThis;
  246. CString csWork;
  247. cmThis.CreatePopupMenu();
  248. csWork.LoadString(ID_ChangeInvocation);
  249. cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_ChangeInvocation,
  250. csWork);
  251. if (m_pcgm -> CodePages() > 1) {
  252. csWork.LoadString(ID_ChangeCodePage);
  253. cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_ChangeCodePage,
  254. csWork);
  255. }
  256. cmThis.AppendMenu(MF_SEPARATOR);
  257. csWork.LoadString(ID_AddItem);
  258. cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_AddItem, csWork);
  259. csWork.LoadString(ID_DeleteItem);
  260. cmThis.AppendMenu(MF_STRING | MF_ENABLED, ID_DeleteItem,
  261. csWork);
  262. cmThis.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, cpt.x, cpt.y, this);
  263. }
  264. /******************************************************************************
  265. CGlyphMappingPage::OnChangeInvocation
  266. Called when the user decides to change the invocation for the code point.
  267. Simply initiate a label edit.
  268. ******************************************************************************/
  269. void CGlyphMappingPage::OnChangeInvocation() {
  270. int idContext = m_clcMap.GetNextItem(-1,
  271. LVNI_ALL | LVNI_FOCUSED | LVNI_SELECTED);
  272. if (idContext < 0 || idContext >= m_clcMap.GetItemCount())
  273. return;
  274. m_clcMap.EditLabel(idContext);
  275. }
  276. /******************************************************************************
  277. CGlyphMappingPage::OnChangeCodePage
  278. This handles a code page change request.
  279. ******************************************************************************/
  280. void CGlyphMappingPage::OnChangeCodePage() {
  281. int idContext = m_clcMap.GetNextItem(-1,
  282. LVNI_ALL | LVNI_FOCUSED | LVNI_SELECTED);
  283. if (idContext < 0 || idContext >= m_clcMap.GetItemCount())
  284. return;
  285. // Create a string naming the item, and invoke the CSelectCodePage
  286. // dialog...
  287. CGlyphHandle *pcgh = (CGlyphHandle*) m_clcMap.GetItemData(idContext);
  288. CSelectCodePage cscp(this, m_pcgm -> Name() + _TEXT(" ") +
  289. m_clcMap.GetItemText(idContext, 1),
  290. m_pcgm -> PageID(pcgh -> CodePage()));
  291. CDWordArray cdaPages;
  292. m_pcgm -> CodePages(cdaPages);
  293. cdaPages.RemoveAt(pcgh -> CodePage());
  294. cscp.LimitTo(cdaPages);
  295. if (cscp.DoModal() != IDOK)
  296. return;
  297. // Change the code page. For maximum flexibility, we'll use an array
  298. // for this. This is because if this is to correct a perceived mistake,
  299. // the codes should be translated to MBCS and then back.
  300. // NOTE: This was also to support multiple selection, which isn't allowed.
  301. CPtrArray cpaThis;
  302. cpaThis.Add((void *) m_clcMap.GetItemData(idContext));
  303. m_pcgm -> ChangeCodePage(cpaThis, cscp.SelectedCodePage());
  304. m_clcMap.SetItemText(idContext, 2, cscp.GetCodePageName());
  305. }
  306. /******************************************************************************
  307. CGlyphMappingPage::OnDeleteItem
  308. This handles the Delete Item message from the context menu, by verifying
  309. this is what is wanted, and then doing it.
  310. ******************************************************************************/
  311. void CGlyphMappingPage::OnDeleteItem() {
  312. int idContext = m_clcMap.GetNextItem(-1,
  313. LVNI_ALL | LVNI_FOCUSED | LVNI_SELECTED);
  314. if (idContext < 0 || idContext >= m_clcMap.GetItemCount())
  315. return;
  316. if (IDYES != AfxMessageBox(IDS_DeleteItemQuery,
  317. MB_YESNO | MB_ICONQUESTION))
  318. return;
  319. // Delete the entry from the glyph map
  320. CGlyphHandle* pcgh = (CGlyphHandle*) m_clcMap.GetItemData(idContext);
  321. m_pcgm -> DeleteGlyph(pcgh -> CodePoint());
  322. m_clcMap.DeleteItem(idContext);
  323. _ASSERTE((unsigned) m_clcMap.GetItemCount() == m_pcgm -> Glyphs());
  324. }
  325. /******************************************************************************
  326. CGlyphMappingPage::OnAddItem
  327. This is called whenever the user wishes to add new code points to the map. I
  328. ask the glyph map which points exist, and if there are any, invoke a modal
  329. dialog to allow the selection of new glyphs.
  330. ******************************************************************************/
  331. void CGlyphMappingPage::OnAddItem() {
  332. CMapWordToDWord cmw2dAvailable;
  333. m_pcgm -> UndefinedPoints(cmw2dAvailable);
  334. if (!cmw2dAvailable.Count()) {
  335. AfxMessageBox(IDS_NoUnmappedGlyphs);
  336. return;
  337. }
  338. CDWordArray cdaPages;
  339. m_pcgm -> CodePages(cdaPages);
  340. CAddCodePoints cacp(this, cmw2dAvailable, cdaPages, m_pcgm -> Name());
  341. if (cacp.DoModal() != IDOK) return;
  342. // The map will now contain only the new code points...
  343. m_pcgm -> AddPoints(cmw2dAvailable);
  344. m_uTimer = (unsigned) SetTimer(IDD, 10, NULL);
  345. if (!m_uTimer)
  346. OnTimer(m_uTimer);
  347. // Reset the sort criteria so we don't have to sort the data
  348. for (unsigned u = 0; u < Columns; u++)
  349. m_abDirection[u] = TRUE;
  350. m_bSortFirst = Codes;
  351. m_bSortSecond = Strings;
  352. m_bSortLast = Pages;
  353. }
  354. /******************************************************************************
  355. CGlyphMappingPage::OnEndlabeleditGlyphMapping
  356. This is called when a user clicks outside the edit control to end editing of
  357. a selection string. We pass the string down, and do some finagling to force
  358. the system to accept the value as we display it, which isn't as the user
  359. typed it, in some cases.
  360. ******************************************************************************/
  361. void CGlyphMappingPage::OnEndlabeleditGlyphMapping(NMHDR* pnmh, LRESULT* plr)
  362. {
  363. LV_DISPINFO* plvdi = (LV_DISPINFO*) pnmh;
  364. // Pass the new invocation string to the glyph map to handle
  365. CGlyphHandle* pcgh = (CGlyphHandle*) plvdi -> item.lParam;
  366. m_pcgm -> ChangeEncoding(pcgh -> CodePoint(), plvdi -> item.pszText);
  367. m_bJustChangedSelectString = TRUE;
  368. *plr = TRUE;
  369. }
  370. /******************************************************************************
  371. CGlyphMappingPage::OnItemchangedGlyphMapping
  372. This is called whenever anything changes in the list box- we are primarily
  373. interested in text changes (since we have to adjust encodings once entered)
  374. and selection changes (so we can move the "cursor" accordingly.
  375. ******************************************************************************/
  376. void CGlyphMappingPage::OnItemchangedGlyphMapping(NMHDR* pnmh, LRESULT* plr)
  377. {
  378. NM_LISTVIEW* pnmlv = (NM_LISTVIEW*) pnmh;
  379. int idContext = m_clcMap.GetNextItem(-1,
  380. LVNI_ALL | LVNI_FOCUSED | LVNI_SELECTED);
  381. // We only care if this notes a text change in the selected item and we
  382. // haven't fixed it, yet.
  383. if (pnmlv -> iItem != idContext || !(pnmlv -> uChanged & LVIF_TEXT) ||
  384. !m_bJustChangedSelectString)
  385. return;
  386. CGlyphHandle* pcgh = (CGlyphHandle*) m_clcMap.GetItemData(idContext);
  387. CString csWork;
  388. m_bJustChangedSelectString = FALSE;
  389. pcgh -> GetEncoding(csWork);
  390. m_clcMap.SetItemText(idContext, 0, csWork);
  391. *plr = 0;
  392. }
  393. /******************************************************************************
  394. CGlyphMappingPage::OnColumnclickGlyphMapping
  395. Called when the user wants to sort the list- so that's what we do!
  396. ******************************************************************************/
  397. void CGlyphMappingPage::OnColumnclickGlyphMapping(NMHDR* pnmh, LRESULT* plr) {
  398. NM_LISTVIEW* pnmlv = (NM_LISTVIEW*) pnmh;
  399. // Resort the list based upon the selected column, and the current sort
  400. // order
  401. if (pnmlv -> iSubItem == m_bSortFirst)
  402. m_abDirection[m_bSortFirst] = !m_abDirection[m_bSortFirst]; // Reverse
  403. else {
  404. if (pnmlv -> iSubItem == m_bSortSecond)
  405. m_bSortSecond = m_bSortFirst;
  406. else {
  407. m_bSortLast = m_bSortSecond;
  408. m_bSortSecond = m_bSortFirst;
  409. }
  410. m_bSortFirst = (BYTE)pnmlv -> iSubItem;
  411. }
  412. CWaitCursor cwc; // On FE tables, this can take a while...
  413. m_clcMap.SortItems(&MapSorter, (UINT_PTR) this);
  414. *plr = 0;
  415. }
  416. void CGlyphMappingPage::LoadCharMapList()
  417. {
  418. CWaitCursor cwc ;
  419. m_clcMap.EnableWindow(FALSE) ;
  420. CGlyphHandle* pcgh ;
  421. int idItem ;
  422. CString csWork ;
  423. for (unsigned u = 0 ; m_uidGlyph < m_pcgm -> Glyphs() ; u++, m_uidGlyph++) {
  424. pcgh = m_pcgm->Glyph(m_uidGlyph) ;
  425. if(pcgh != NULL)
  426. pcgh->GetEncoding(csWork) ;
  427. else
  428. {
  429. AfxMessageBox(IDS_LoadGTTError);//raid 116604 prefix : this fucntion(LoadCharMapList) are dead
  430. return ;
  431. } ;
  432. idItem = m_clcMap.InsertItem(m_uidGlyph, csWork) ;
  433. m_clcMap.SetItemData(idItem, (LPARAM) pcgh) ;
  434. csWork.Format(_TEXT("0x%4.4X"), pcgh->CodePoint()) ;
  435. m_clcMap.SetItem(idItem, 1, LVIF_TEXT, csWork, -1, 0, 0, u) ;
  436. csWork = m_pcgm->PageName(pcgh->CodePage()) ;
  437. m_clcMap.SetItem(idItem, 2, LVIF_TEXT, csWork, -1, 0, 0, u) ;
  438. }
  439. m_clcMap.EnableWindow(TRUE) ;
  440. m_cpcBanner.SetPos(0) ;
  441. m_cpcBanner.ShowWindow(SW_HIDE) ;
  442. }
  443. /******************************************************************************
  444. CGlyphMappingPage::OnGetdispinfoGlyphMapping
  445. This member function is an attempt to speed handling of large tables, and
  446. also to handle code page changes more gracefully. All items are initially
  447. declared as callbacks, so the control requests names for items as they are
  448. displayed, via this member.
  449. ******************************************************************************/
  450. void CGlyphMappingPage::OnGetdispinfoGlyphMapping(NMHDR* pnmh, LRESULT* plr) {
  451. LV_DISPINFO* plvdi = (LV_DISPINFO*) pnmh;
  452. *plr = 0;
  453. // If the window is obstructed when an item is deleted, there might not
  454. // be a glpyh at this point, so watch out!
  455. CGlyphHandle* pcgh = (CGlyphHandle*) plvdi -> item.lParam;
  456. if (!pcgh)
  457. return;
  458. CString csWork;
  459. switch (plvdi -> item.iSubItem) {
  460. case 0:
  461. pcgh -> GetEncoding(csWork);
  462. break;
  463. case 1:
  464. csWork.Format(_TEXT("0x%4.4X"), pcgh -> CodePoint());
  465. plvdi -> item.mask |= LVIF_DI_SETITEM; // This never changes
  466. break;
  467. case 2:
  468. csWork = m_pcgm -> PageName(pcgh -> CodePage());
  469. }
  470. lstrcpyn(plvdi -> item.pszText, csWork, plvdi -> item.cchTextMax);
  471. }
  472. /******************************************************************************
  473. CGlyphMappingPage::OnSetActive
  474. Called when the page is activated, but after OnInitDialog on the first
  475. activation. If the predefined code page ID has changed, we must rebuild the
  476. page.
  477. ******************************************************************************/
  478. // //raid 118880
  479. BOOL CGlyphMappingPage::OnSetActive() {
  480. m_lPredefinedID = m_pcgm -> PredefinedID();
  481. m_uTimer = (unsigned) SetTimer(IDD, 10, NULL);
  482. m_clcMap.DeleteAllItems();
  483. OnTimer(m_uTimer);
  484. return CPropertyPage::OnSetActive();
  485. }
  486. /******************************************************************************
  487. CGlyphMappingPage::OnKeydownGlyphMapping
  488. This is called whenever the user presses a key. We use it to provide an
  489. extended interface from the keyboard, to match the other editors.
  490. ******************************************************************************/
  491. void CGlyphMappingPage::OnKeydownGlyphMapping(NMHDR* pnmh, LRESULT* plr)
  492. {
  493. LV_KEYDOWN* plvkd = (LV_KEYDOWN*)pnmh;
  494. if (plvkd->wVKey == VK_F1) {
  495. AfxGetApp()->WinHelp(HID_BASE_RESOURCE + IDR_GLYPHMAP) ;
  496. return ;
  497. } ;
  498. *plr = 0;
  499. int idItem = m_clcMap.GetNextItem(-1, LVIS_FOCUSED | LVIS_SELECTED);
  500. if (idItem == -1) {
  501. if (plvkd -> wVKey == VK_F10)
  502. OnAddItem();
  503. return;
  504. }
  505. switch (plvkd -> wVKey) {
  506. case VK_F2:
  507. OnChangeInvocation();
  508. break;
  509. case VK_DELETE:
  510. OnDeleteItem();
  511. break;
  512. case VK_F10: {
  513. CRect crItem;
  514. m_clcMap.GetItemRect(idItem, crItem, LVIR_LABEL);
  515. m_clcMap.ClientToScreen(crItem);
  516. OnContextMenu(&m_clcMap, crItem.CenterPoint());
  517. }
  518. }
  519. }
  520. /******************************************************************************
  521. CGlhpyMappingPage::OnTimer
  522. The only event currently using a timer is the need to fill the list.
  523. ******************************************************************************/
  524. void CGlyphMappingPage::OnTimer(UINT uEvent) {
  525. if (uEvent != m_uTimer) {
  526. CPropertyPage::OnTimer(uEvent);
  527. return;
  528. }
  529. CString csWork;
  530. if (m_uTimer)
  531. ::KillTimer(m_hWnd, m_uTimer);
  532. if (!m_uidGlyph) {
  533. m_clcMap.DeleteAllItems();
  534. m_cpcBanner.SetRange(0, m_pcgm -> Glyphs() -1);
  535. m_cpcBanner.SetStep(1);
  536. m_cpcBanner.SetPos(0);
  537. m_cpcBanner.ShowWindow(SW_SHOW);
  538. csWork.LoadString(IDS_WaitToFill);
  539. CDC *pcdc = m_cpcBanner.GetDC();
  540. CRect crBanner;
  541. m_cpcBanner.GetClientRect(crBanner);
  542. pcdc -> SetBkMode(TRANSPARENT);
  543. pcdc -> DrawText(csWork, crBanner, DT_CENTER | DT_VCENTER);
  544. m_cpcBanner.ReleaseDC(pcdc);
  545. if (m_uTimer)
  546. m_clcMap.EnableWindow(FALSE);
  547. else
  548. m_clcMap.LockWindowUpdate();
  549. m_clcMap.SetItemCount(m_pcgm -> Glyphs());
  550. }
  551. for (unsigned u = 0;
  552. m_uidGlyph < m_pcgm -> Glyphs() && (!m_uTimer || u < 100);
  553. u++, m_uidGlyph++) {
  554. CGlyphHandle* pcgh = m_pcgm -> Glyph(m_uidGlyph);
  555. int idItem = m_clcMap.InsertItem(m_uidGlyph, LPSTR_TEXTCALLBACK);
  556. m_clcMap.SetItemData(idItem, (LPARAM) pcgh);
  557. m_clcMap.SetItem(idItem, 1, LVIF_TEXT, LPSTR_TEXTCALLBACK, -1, 0, 0,
  558. (LPARAM) pcgh);
  559. m_clcMap.SetItem(idItem, 2, LVIF_TEXT, LPSTR_TEXTCALLBACK, -1, 0, 0,
  560. (LPARAM) pcgh);
  561. }
  562. if (m_uidGlyph == m_pcgm -> Glyphs()) {
  563. if (m_uTimer)
  564. m_clcMap.EnableWindow(TRUE);
  565. else
  566. m_clcMap.UnlockWindowUpdate();
  567. m_uTimer = 0;
  568. m_cpcBanner.SetPos(0);
  569. m_cpcBanner.ShowWindow(SW_HIDE);
  570. SetFocus();
  571. m_uidGlyph = 0;
  572. }
  573. if (m_uTimer) {
  574. m_cpcBanner.SetPos(m_uidGlyph);
  575. csWork.LoadString(IDS_WaitToFill);
  576. CDC *pcdc = m_cpcBanner.GetDC();
  577. CRect crBanner;
  578. m_cpcBanner.GetClientRect(crBanner);
  579. pcdc -> SetBkMode(TRANSPARENT);
  580. pcdc -> DrawText(csWork, crBanner, DT_CENTER | DT_VCENTER);
  581. m_cpcBanner.ReleaseDC(pcdc);
  582. m_uTimer = (unsigned) SetTimer(IDD, 10, NULL);
  583. if (!m_uTimer) {
  584. CWaitCursor cwc; // Might be a while...
  585. m_clcMap.EnableWindow(TRUE);
  586. m_clcMap.LockWindowUpdate();
  587. OnTimer(m_uTimer);
  588. }
  589. }
  590. }
  591. /******************************************************************************
  592. CGlyphMappingPage::OnDestroy
  593. Since this also can be time-consuming, kill the list here, and throw up the
  594. wait cursor.
  595. ******************************************************************************/
  596. void CGlyphMappingPage::OnDestroy() {
  597. CWaitCursor cwc;
  598. if (m_uTimer)
  599. ::KillTimer(m_hWnd, m_uTimer);
  600. m_clcMap.DeleteAllItems();
  601. CPropertyPage::OnDestroy();
  602. }
  603. /******************************************************************************
  604. CCodePagePage class implementation
  605. This class implements the code page property page, providing an interface for
  606. viewing and implementing the code page assignments.
  607. ******************************************************************************/
  608. CCodePagePage::CCodePagePage() : CToolTipPage(CCodePagePage::IDD)
  609. {
  610. //{{AFX_DATA_INIT(CCodePagePage)
  611. // NOTE: the ClassWizard will add member initialization here
  612. //}}AFX_DATA_INIT
  613. m_uHelpID = HID_BASE_RESOURCE + IDR_GLYPHMAP ;
  614. m_bInitialized = false ;
  615. m_bSelDeselChgSignificant = true ;
  616. }
  617. CCodePagePage::~CCodePagePage() {
  618. }
  619. void CCodePagePage::DoDataExchange(CDataExchange* pDX) {
  620. CPropertyPage::DoDataExchange(pDX);
  621. //{{AFX_DATA_MAP(CCodePagePage)
  622. DDX_Control(pDX, IDC_DeletePage, m_cbDelete);
  623. DDX_Control(pDX, IDC_SelectString, m_ceSelect);
  624. DDX_Control(pDX, IDC_DeselectString, m_ceDeselect);
  625. DDX_Control(pDX, IDC_RemovePage, m_cbRemove);
  626. DDX_Control(pDX, IDC_CodePageList, m_clbPages);
  627. //}}AFX_DATA_MAP
  628. }
  629. BEGIN_MESSAGE_MAP(CCodePagePage, CToolTipPage)
  630. //{{AFX_MSG_MAP(CCodePagePage)
  631. ON_EN_KILLFOCUS(IDC_SelectString, OnKillfocusSelectString)
  632. ON_EN_KILLFOCUS(IDC_DeselectString, OnKillfocusDeselectString)
  633. ON_BN_CLICKED(IDC_AddPage, OnAddPage)
  634. ON_LBN_SELCHANGE(IDC_CodePageList, OnSelchangeCodePageList)
  635. ON_BN_CLICKED(IDC_RemovePage, OnReplacePage)
  636. ON_EN_CHANGE(IDC_SelectString, OnChangeSelectString)
  637. ON_EN_CHANGE(IDC_DeselectString, OnChangeDeselectString)
  638. ON_BN_CLICKED(IDC_DeletePage, OnDeletePage)
  639. //}}AFX_MSG_MAP
  640. END_MESSAGE_MAP()
  641. /******************************************************************************
  642. CCodePagePage::OnInitDialog
  643. This member function handles the WM_INITDIALOG message by initializing the
  644. various controls of the dialog.
  645. ******************************************************************************/
  646. BOOL CCodePagePage::OnInitDialog() {
  647. CToolTipPage::OnInitDialog();
  648. for (unsigned u = 0; u < m_pcgm -> CodePages(); u++) {
  649. int id =
  650. m_clbPages.AddString(m_pcgm -> PageName(u));
  651. m_clbPages.SetItemData(id, u);
  652. if (!u)
  653. m_clbPages.SetCurSel(id);
  654. }
  655. // Let the list box selection change handler do the rest
  656. OnSelchangeCodePageList();
  657. m_bInitialized = true ;
  658. return TRUE;
  659. }
  660. /******************************************************************************
  661. CCodePagePage::OnChangeSelectString
  662. Mark the GTT dirty to make sure the new string is saved.
  663. ******************************************************************************/
  664. void CCodePagePage::OnChangeSelectString()
  665. {
  666. // Only mark the GTT as having changed when this function is called after
  667. // the GTT Editor and only if this change in the selection string is
  668. // significant. Do nothing when the string change is just because a
  669. // previously entered string is being loaded into the control.
  670. if (m_bInitialized && m_bSelDeselChgSignificant)
  671. m_pcgm->Changed() ;
  672. }
  673. /******************************************************************************
  674. CCodePagePage::OnChangeDeselectString
  675. Mark the GTT dirty to make sure the new string is saved.
  676. ******************************************************************************/
  677. void CCodePagePage::OnChangeDeselectString()
  678. {
  679. // Only mark the GTT as having changed when this function is called after
  680. // the GTT Editor and only if this change in the deselection string is
  681. // significant. Do nothing when the string change is just because a
  682. // previously entered string is being loaded into the control.
  683. if (m_bInitialized && m_bSelDeselChgSignificant)
  684. m_pcgm->Changed() ;
  685. }
  686. /******************************************************************************
  687. CCodePagePage::OnKillfocusSelectString
  688. Save the Select String if it has changed.
  689. ******************************************************************************/
  690. void CCodePagePage::OnKillfocusSelectString()
  691. {
  692. SaveSelDeselString(m_ceSelect, TRUE) ;
  693. }
  694. /******************************************************************************
  695. CCodePagePage::OnKillfocusDeselectString
  696. Save the Deselect String if it has changed.
  697. ******************************************************************************/
  698. void CCodePagePage::OnKillfocusDeselectString()
  699. {
  700. SaveSelDeselString(m_ceDeselect, FALSE) ;
  701. }
  702. /******************************************************************************
  703. CCodePagePage::SaveBothSelAndDeselStrings
  704. Save both the Select and the Deselect strings if they have changed.
  705. ******************************************************************************/
  706. void CCodePagePage::SaveBothSelAndDeselStrings()
  707. {
  708. SaveSelDeselString(m_ceSelect, TRUE) ;
  709. SaveSelDeselString(m_ceDeselect, FALSE) ;
  710. }
  711. /******************************************************************************
  712. CCodePagePage::SaveSelDeselString
  713. This function is called to update the GTT when the Selection or Deselection
  714. string may have changed. Check to see if the control really was modified, and
  715. if it is, update the structure accordingly. Then flag the control as
  716. unmodified.
  717. ******************************************************************************/
  718. void CCodePagePage::SaveSelDeselString(CEdit &cesd, BOOL bselstr)
  719. {
  720. // Do nothing if the control has not been modified.
  721. if (!cesd || !cesd.GetModify())
  722. return ;
  723. // Get the new sel/desel string.
  724. CString csWork ;
  725. cesd.GetWindowText(csWork) ;
  726. // Save the sel/desel string as determined by bselstr. (Note:
  727. // SetInvocation() sets the GTT's changed flag, too.)
  728. m_pcgm -> SetInvocation(
  729. (unsigned)m_clbPages.GetItemData(m_clbPages.GetCurSel()), csWork,
  730. bselstr) ;
  731. // Clear the control's modified flag.
  732. cesd.SetModify(FALSE) ;
  733. // Now make sure that the string is displayed correctly.
  734. m_pcgm -> Invocation(
  735. (unsigned)m_clbPages.GetItemData(m_clbPages.GetCurSel()), csWork,
  736. bselstr) ;
  737. cesd.SetWindowText(csWork) ;
  738. }
  739. /******************************************************************************
  740. CCodePagePage::OnAddPage
  741. This is an event handler for the pressing of the "Add Page" button. We invoke
  742. the Select Code Page dialog, and if a new page is selected, we add it to the
  743. list of pages that are available.
  744. ******************************************************************************/
  745. void CCodePagePage::OnAddPage() {
  746. CDWordArray cdaPages;
  747. m_pcgm -> CodePages(cdaPages);
  748. CSelectCodePage cscp(this, m_pcgm -> Name(), 0);
  749. cscp.Exclude(cdaPages);
  750. if (cscp.DoModal() != IDOK)
  751. return;
  752. m_pcgm -> AddCodePage(cscp.SelectedCodePage());
  753. int id =
  754. m_clbPages.AddString(m_pcgm -> PageName(m_pcgm -> CodePages() - 1));
  755. m_clbPages.SetItemData(id, m_pcgm -> CodePages() -1);
  756. m_clbPages.SetCurSel(id);
  757. // Let OnSelchangeCodePageList do the rest (that's what happened, eh?)
  758. OnSelchangeCodePageList();
  759. m_ceSelect.SetFocus(); // A friendly place to leave it...
  760. }
  761. /******************************************************************************
  762. CCodePagePage::OnSelchangeCodePageList
  763. This member function handles changes in the selected code page. It fills
  764. the edit controls for the selected page's name, selection and deselection
  765. strings, and handles enabling of the "Remove Page" button (this message
  766. could mean nothing is now selected...)
  767. Make sure that the operations of this function do not mark the GTT dirty.
  768. ******************************************************************************/
  769. void CCodePagePage::OnSelchangeCodePageList()
  770. {
  771. m_bSelDeselChgSignificant = false ;
  772. int id = m_clbPages.GetCurSel();
  773. if (id < 0) {
  774. m_ceSelect.SetWindowText(_T(""));
  775. m_ceDeselect.SetWindowText(_T(""));
  776. m_cbRemove.EnableWindow(FALSE);
  777. m_cbDelete.EnableWindow(FALSE);
  778. m_ceSelect.EnableWindow(FALSE);
  779. m_ceDeselect.EnableWindow(FALSE);
  780. m_bSelDeselChgSignificant = true ;
  781. return;
  782. }
  783. unsigned u = (unsigned)m_clbPages.GetItemData(id);
  784. SetDlgItemText(IDC_CurrentPage, m_pcgm -> PageName(u));
  785. CString csWork;
  786. m_pcgm -> Invocation(u, csWork, TRUE);
  787. m_ceSelect.SetWindowText(csWork);
  788. m_pcgm -> Invocation(u, csWork, FALSE);
  789. m_ceDeselect.SetWindowText(csWork);
  790. m_cbRemove.EnableWindow(m_pcgm -> CodePages() > 1);
  791. m_cbDelete.EnableWindow(m_pcgm -> CodePages() > 1); // r118880
  792. m_ceSelect.EnableWindow();
  793. m_ceDeselect.EnableWindow();
  794. m_bSelDeselChgSignificant = true ;
  795. }
  796. /******************************************************************************
  797. CCodePagePage::OnReplacePage
  798. This handles the Remove Page button. Not much to it, here- we just tell the
  799. glyph map what we want done.
  800. ******************************************************************************/
  801. void CCodePagePage::OnReplacePage() {
  802. int id = m_clbPages.GetCurSel();
  803. if (id < 0 || m_clbPages.GetCount() < 2)
  804. return;
  805. unsigned u = (unsigned)m_clbPages.GetItemData(id);
  806. // Query for code page to map this one to
  807. CSelectCodePage cscp(this,
  808. CString(_TEXT("Replacing ")) + m_pcgm -> PageName(u), 0);
  809. CDWordArray cdaPages;
  810. m_pcgm -> CodePages(cdaPages);
  811. cdaPages.RemoveAt(u);
  812. cscp.LimitTo(cdaPages);
  813. if (cscp.DoModal() != IDOK)
  814. return;
  815. for (unsigned uTo = 0; uTo < m_pcgm -> CodePages(); uTo++)
  816. if (m_pcgm -> PageID(uTo) == cscp.SelectedCodePage())
  817. break;
  818. _ASSERTE(uTo < (unsigned) m_pcgm -> CodePages());
  819. if (!m_pcgm -> RemovePage(u, uTo))
  820. return;
  821. // Flush the list box and then refill it.
  822. m_clbPages.ResetContent();
  823. for (u = 0; u < m_pcgm -> CodePages(); u++) {
  824. int id = m_clbPages.AddString(m_pcgm -> PageName(u));
  825. m_clbPages.SetItemData(id, u);
  826. }
  827. // Select whoever moved into our position, then update the rest
  828. m_clbPages.SetCurSel(id < m_clbPages.GetCount() ? id : id - 1);
  829. OnSelchangeCodePageList();
  830. }
  831. /******************************************************************************
  832. //raid 118880
  833. CCodePagePage::OnDeletePage
  834. message handler :Delete code page when user push delete button
  835. logic : get page id of selected code -> get codepage id from Glyphmap ->
  836. call pcgm-> DeleteCodePage: actual part of deleting -> reset list box
  837. ********************************************************************************/
  838. void CCodePagePage::OnDeletePage()
  839. {
  840. int id = m_clbPages.GetCurSel();
  841. if (id < 0 || m_clbPages.GetCount() < 2)
  842. return;
  843. unsigned CodePageID = (unsigned)m_clbPages.GetItemData(id);
  844. // Actual delete call
  845. if (!m_pcgm -> RemovePage(CodePageID,CodePageID, TRUE))
  846. return;
  847. // Flush the list box and then refill it.
  848. m_clbPages.ResetContent();
  849. for (unsigned u = 0; u < m_pcgm -> CodePages(); u++) {
  850. int id = m_clbPages.AddString(m_pcgm -> PageName(u));
  851. m_clbPages.SetItemData(id, u);
  852. }
  853. // Select whoever moved into our position, then update the rest
  854. m_clbPages.SetCurSel(id < m_clbPages.GetCount() ? id : id - 1);
  855. OnSelchangeCodePageList();
  856. }
  857. /******************************************************************************
  858. CPredefinedMaps class
  859. This implements the class which handles the page for pre-defined mappings
  860. in a GTT file.
  861. ******************************************************************************/
  862. CPredefinedMaps::CPredefinedMaps() : CPropertyPage(CPredefinedMaps::IDD) {
  863. //{{AFX_DATA_INIT(CPredefinedMaps)
  864. // NOTE: the ClassWizard will add member initialization here
  865. //}}AFX_DATA_INIT
  866. }
  867. CPredefinedMaps::~CPredefinedMaps() {
  868. }
  869. void CPredefinedMaps::DoDataExchange(CDataExchange* pDX) {
  870. CPropertyPage::DoDataExchange(pDX);
  871. //{{AFX_DATA_MAP(CPredefinedMaps)
  872. DDX_Control(pDX, IDC_PredefinedList, m_clbIDs);
  873. //}}AFX_DATA_MAP
  874. }
  875. BEGIN_MESSAGE_MAP(CPredefinedMaps, CPropertyPage)
  876. //{{AFX_MSG_MAP(CPredefinedMaps)
  877. ON_BN_CLICKED(IDC_Overstrike, OnOverstrike)
  878. //}}AFX_MSG_MAP
  879. END_MESSAGE_MAP()
  880. /////////////////////////////////////////////////////////////////////////////
  881. // CPredefinedMaps message handlers
  882. /******************************************************************************
  883. CPredefinedMaps::OnInitDialog
  884. This override handles the WM_INITDIALOG message by initializing the various
  885. controls.
  886. ******************************************************************************/
  887. BOOL CPredefinedMaps::OnInitDialog() {
  888. CPropertyPage::OnInitDialog();
  889. // Fill the list box- first, with none, then with the defined IDs
  890. CString csWork;
  891. csWork.LoadString(IDS_NoPredefined);
  892. m_clbIDs.AddString(csWork);
  893. if (m_pcgm -> PredefinedID()== CGlyphMap::NoPredefined)
  894. m_clbIDs.SetCurSel(0);
  895. m_clbIDs.SetItemData(0, CGlyphMap::NoPredefined);
  896. for (int i = CGlyphMap::Wansung; i < 1; i++) {
  897. csWork.LoadString(IDS_DefaultPage + i);
  898. if (csWork.IsEmpty())
  899. continue;
  900. int id = m_clbIDs.AddString(csWork);
  901. m_clbIDs.SetItemData(id, i);
  902. if (i == m_pcgm -> PredefinedID())
  903. m_clbIDs.SetCurSel(i);
  904. }
  905. m_clbIDs.SetTopIndex(m_clbIDs.GetCurSel());
  906. CheckDlgButton(IDC_Overstrike, m_pcgm -> OverStrike());
  907. return TRUE; // return TRUE unless you set the focus to a control
  908. }
  909. /******************************************************************************
  910. CPredefinedMaps::OnKillActive
  911. This is called when we leave the page. Since changing pages can be very
  912. time-consuming, we only check when you leave, not every time the selection
  913. changes. Occasionally even my aged brain works.
  914. ******************************************************************************/
  915. BOOL CPredefinedMaps::OnKillActive() {
  916. if (m_clbIDs.GetCurSel() >= 0)
  917. m_pcgm -> UsePredefined((unsigned)m_clbIDs.GetItemData(m_clbIDs.GetCurSel()));
  918. return CPropertyPage::OnKillActive();
  919. }
  920. /******************************************************************************
  921. CPredefinedMaps::OnOverstrike
  922. Called when the user clicks the check box for enabling / disabling overstrike
  923. ******************************************************************************/
  924. void CPredefinedMaps::OnOverstrike() {
  925. m_pcgm -> OverStrike(IsDlgButtonChecked(IDC_Overstrike));
  926. }