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.

2243 lines
65 KiB

  1. /******************************************************************************
  2. Source File: GPD Viewer.CPP
  3. This file implements the GPD viewing/editing class.
  4. Copyright (c) 1997 by Microsoft Corporation. All Rights Reserved.
  5. A Pretty Penny Enterprises Production.
  6. Change History:
  7. 03-24-1997 Bob_Kjelgaard@Prodigy.Net Created it
  8. ******************************************************************************/
  9. #include "StdAfx.H"
  10. #include "MiniDev.H"
  11. #include "MainFrm.H"
  12. #include <gpdparse.h>
  13. #include "ProjNode.H"
  14. #include "rcfile.h"
  15. #include "GPDFile.H"
  16. #include "GPDView.H"
  17. #include "Resource.H"
  18. #include "freeze.h"
  19. #include "projview.h"
  20. #include "comctrls.h"
  21. #include "INFWizrd.h" //raid 0001
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. /******************************************************************************
  28. CGPDViewer class
  29. This class implements the GPD viewer.
  30. ******************************************************************************/
  31. IMPLEMENT_DYNCREATE(CGPDViewer, CRichEditView)
  32. BEGIN_MESSAGE_MAP(CGPDViewer, CRichEditView)
  33. //{{AFX_MSG_MAP(CGPDViewer)
  34. ON_WM_DESTROY()
  35. ON_COMMAND(ID_FILE_PARSE, OnFileParse)
  36. ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
  37. ON_WM_TIMER()
  38. ON_CONTROL_REFLECT(EN_VSCROLL, OnVscroll)
  39. ON_WM_VSCROLL()
  40. ON_COMMAND(ID_FILE_SAVE, OnFileSave)
  41. ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
  42. ON_COMMAND(ID_FILE_ERROR_LEVEL, OnFileErrorLevel)
  43. ON_COMMAND(ID_EDIT_GOTO, OnGotoGPDLineNumber)
  44. ON_COMMAND(ID_SrchNextBtn, OnSrchNextBtn)
  45. ON_COMMAND(ID_SrchPrevBtn, OnSrchPrevBtn)
  46. ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
  47. ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
  48. ON_LBN_SELCHANGE(IDC_ErrorLst, OnSelchangeErrorLst)
  49. ON_WM_LBUTTONDBLCLK()
  50. ON_COMMAND(ID_EDIT_ENABLE_AIDS, OnEditEnableAids)
  51. ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
  52. ON_COMMAND(ID_EDIT_CUT, OnEditCut)
  53. ON_COMMAND(ID_FILE_INF, OnFileInf)
  54. //}}AFX_MSG_MAP
  55. ON_NOTIFY_REFLECT(EN_SELCHANGE, OnSelChange)
  56. END_MESSAGE_MAP()
  57. /******************************************************************************
  58. CGPDViewer::MarkError
  59. This private member highlights the given line in the error display. The
  60. offending line in the GPD is displayed and selected if the error message
  61. contains a line number.
  62. ******************************************************************************/
  63. void CGPDViewer::MarkError(unsigned u)
  64. {
  65. // Copy the error message to the status bar.
  66. CString cserror = GetDocument()->ModelData()->Error(u) ;
  67. m_csb.SetPaneText(0, cserror) ;
  68. SetFocus() ;
  69. // If the string starts with the GPD name, scroll to the line.
  70. CString csname = GetDocument()->ModelData()->FileTitleExt() ;
  71. if (!cserror.Find(csname) && cserror[csname.GetLength()] == _T('(')) {
  72. // Extract the line number
  73. cserror = cserror.Mid(1 + csname.GetLength()) ;
  74. int iLine = atoi(cserror) ;
  75. // Determine the line's first character number and its length
  76. int nstartchar = GetRichEditCtrl().LineIndex(-1 + iLine) ;
  77. int nlinelen = GetRichEditCtrl().GetLine(iLine - 1,
  78. cserror.GetBuffer(1024), 1024) ;
  79. cserror.ReleaseBuffer(nlinelen) ;
  80. nlinelen -= 2 ;
  81. // Select the line that caused the error and scroll it into view.
  82. GetRichEditCtrl().SetSel(nstartchar, nstartchar + nlinelen) ;
  83. GetRichEditCtrl().LineScroll(iLine - (5 +
  84. GetRichEditCtrl().GetFirstVisibleLine())) ;
  85. } ;
  86. CWnd *pcwnderrors = m_cdbActionBar.GetDlgItem(IDC_ErrorLst);
  87. pcwnderrors->SendMessage(WM_HSCROLL, SB_TOP, NULL) ;
  88. }
  89. /******************************************************************************
  90. CGPDViewer::CreateActionBar
  91. Create the action bar and attach it to the GPD Editor window iff the GPD has
  92. errors to display.
  93. ******************************************************************************/
  94. void CGPDViewer::CreateActionBar()
  95. {
  96. // Get reference to ModelData instance for the GPD in the editor
  97. CModelData& cmd = *GetDocument()->ModelData() ;
  98. // If the GPD has errors...
  99. if (cmd.HasErrors()) {
  100. // ...Iff the action bar has not been created yet...
  101. if (m_cdbActionBar.m_hWnd == NULL) {
  102. // ...Create the error bar, position it, and resize the REC to make
  103. // room for it.
  104. m_cdbActionBar.Create(GetParentFrame(), IDD_GPDActionBar,
  105. CBRS_BOTTOM, IDD_GPDActionBar) ;
  106. GetParentFrame()->RecalcLayout() ;
  107. // Now set the focus back to the REC.
  108. SetFocus() ;
  109. } ;
  110. } ;
  111. }
  112. /******************************************************************************
  113. CGPDViewer::LoadErrorListBox
  114. This fills the error dialog bar with the current set of errors, if there are
  115. any...
  116. ******************************************************************************/
  117. void CGPDViewer::LoadErrorListBox()
  118. {
  119. // Get reference to ModelData instance for the GPD in the editor
  120. CModelData& cmd = *GetDocument()->ModelData() ;
  121. // If the GPD has errors...
  122. if (cmd.HasErrors()) {
  123. // ...Get a pointer to the list box and attach it to CListBox. Then
  124. // clear the list box.
  125. CWnd *pcwndlst = m_cdbActionBar.GetDlgItem(IDC_ErrorLst) ;
  126. CListBox clberrors ;
  127. clberrors.Attach(pcwndlst->m_hWnd) ;
  128. clberrors.ResetContent() ;
  129. // Load the list box with the new errors. Detach the list box when
  130. // done.
  131. for (unsigned u = 0 ; u < cmd.Errors() ; u++)
  132. clberrors.AddString(cmd.Error(u)) ;
  133. clberrors.Detach() ;
  134. // Set the list box label. It contains the number of errors.
  135. CString cserror ;
  136. cserror.Format(IDS_ErrorLabel, u) ;
  137. m_cdbActionBar.SetDlgItemText(IDC_ErrorLabel, cserror) ;
  138. // Select the first error and set the focus to the REC.
  139. ChangeSelectedError(1) ;
  140. SetFocus() ;
  141. // Otherwise, just display a message saying there are no errors.
  142. } else {
  143. CString csWork;
  144. csWork.LoadString(IDS_NoSyntaxErrors);
  145. m_csb.SetPaneText(0, csWork);
  146. }
  147. }
  148. /******************************************************************************
  149. CGPDViewer::Color
  150. This private member syntax colors the rich edit controls contents using the
  151. information gleaned from the GPD file's analysis.
  152. ******************************************************************************/
  153. void CGPDViewer::Color()
  154. {
  155. CHARRANGE crCurrentSel;
  156. CHARFORMAT cf;
  157. CModelData& cmd = *(GetDocument() -> ModelData());
  158. CRichEditCtrl& crec = GetRichEditCtrl();
  159. m_bInColor = TRUE;
  160. // Turn off change and selection notification messages
  161. FreezeREC() ;
  162. // Get formatting info from the current selection to use as the default
  163. // characteristics for ever line on the screen.
  164. crec.GetSel(crCurrentSel);
  165. crec.GetDefaultCharFormat(cf);
  166. cf.dwEffects &= ~CFE_AUTOCOLOR;
  167. cf.dwMask |= CFM_COLOR;
  168. // Color each visible line as it was classsified visibility is
  169. // determined by checking the character bounds against the client
  170. // rectangle for the control.
  171. int iTop = m_iTopLineColored = crec.GetFirstVisibleLine();
  172. int i = iTop;
  173. int iLineHeight = crec.GetCharPos(crec.LineIndex(i+1)).y -
  174. crec.GetCharPos(crec.LineIndex(i)).y;
  175. // Tweak things to improve performance.
  176. CRect crEdit ;
  177. crec.GetClientRect(crEdit) ;
  178. crec.LockWindowUpdate() ; // Don't let this show until done!
  179. crec.HideSelection(TRUE, TRUE) ;
  180. // Use the formatting characteristics of the current selection as a
  181. // starting place for the characteristics of each line on the screen.
  182. // Then set the line's colors based on the data returned by TextColor().
  183. int nlinesinrec = crec.GetLineCount() ; // Number of lines in the REC
  184. int nstartchar, nendchar ; // Used to determine starting/ending chars to
  185. // color in current line and to say line done
  186. do {
  187. nstartchar = nendchar = 0 ;
  188. // Colorize each segment of the current line that needs colorizing
  189. while (1) {
  190. cf.crTextColor = TextColor(i, nstartchar, nendchar) ;
  191. if (nstartchar == -1)
  192. break ; // *** Loop exits here
  193. crec.SetSel(crec.LineIndex(i) + nstartchar,
  194. crec.LineIndex(i) + nendchar) ;
  195. crec.SetSelectionCharFormat(cf) ;
  196. } ;
  197. } while (++i < nlinesinrec &&
  198. crec.GetCharPos(crec.LineIndex(i)).y + iLineHeight <
  199. crEdit.bottom - 1) ;
  200. // Restore the original position of the cursor, and then the original
  201. // line (in case the cursor is no longer on this page).
  202. crec.SetSel(crCurrentSel);
  203. crec.LineScroll(iTop - crec.GetFirstVisibleLine());
  204. crec.HideSelection(FALSE, TRUE);
  205. crec.UnlockWindowUpdate(); // Let it shine!
  206. // Restore the notification mask
  207. UnfreezeREC() ;
  208. // Create the action bar and load the error list box.
  209. if (m_bStart) {
  210. CreateActionBar() ;
  211. LoadErrorListBox() ;
  212. } ;
  213. m_bInColor = FALSE;
  214. }
  215. /******************************************************************************
  216. CGPDViewer::TextColor
  217. This determines what colors to make a line. It is complicated a bit by the
  218. fact that the Rich Edit control gives false values for line length on long
  219. files. Probably some brain-dead 64K thing, but I sure can't fix it.
  220. This routine is/can be called multiple times on a line. Each time it is
  221. called, try to find the next piece of the line that needs to be colorized.
  222. If no colorizable part of the line can be found, set nstartchar to -1 and
  223. return.
  224. This routine will indicate the line range and color for these types of text:
  225. Normal to end of line comments (green)
  226. Comments containing error messages (red)
  227. Comments containing warning messages (amber/yellow)
  228. GPD keywords (blue)
  229. If a comment contains a keyword, the appropriate comment color is used. IE,
  230. comments take precedence over everything as far as colorizing is concerned.
  231. ******************************************************************************/
  232. unsigned CGPDViewer::TextColor(int i, int& nstartchar, int& nendchar)
  233. {
  234. // Get the specified line
  235. CByteArray cba ;
  236. CRichEditCtrl& crec = GetRichEditCtrl() ;
  237. cba.SetSize(max(crec.LineLength(i) + sizeof (unsigned), 100)) ;
  238. CString csline((LPCTSTR) cba.GetData(),
  239. crec.GetLine(i, (LPSTR) cba.GetData(),
  240. (int)(cba.GetSize() - sizeof (unsigned)))) ;
  241. // If the end of the line was dealt with the last time, indicate that this
  242. // line is done and return.
  243. if (nendchar + 1 >= csline.GetLength()) {
  244. nstartchar = -1 ;
  245. return RGB(0, 0, 0) ;
  246. } ;
  247. // Now get the segment of the line we need to check and see if there is a
  248. // comment or something that might be a keyword in it.
  249. CString csphrase = csline.Mid(nendchar) ;
  250. int ncomloc = csphrase.Find(_T("*%")) ;
  251. int nkeyloc = csphrase.Find(_T('*')) ;
  252. // Process any comment found in the string
  253. if (ncomloc >= 0)
  254. return (CommentColor(csphrase, ncomloc, csline, nstartchar, nendchar)) ;
  255. // If no comment was found, process anything that might be a GPD keyword.
  256. if (nkeyloc >= 0)
  257. return (KeywordColor(csphrase, nkeyloc, csline, nstartchar, nendchar)) ;
  258. // The rest of the line should be black
  259. nstartchar = nendchar + 1 ;
  260. nendchar = csline.GetLength() ;
  261. return RGB(0, 0, 0) ;
  262. }
  263. /******************************************************************************
  264. CGPDViewer::CommentColor
  265. Determine and save the character range for the comment. Then determine the
  266. type of comment and return the color required for that type. (See TextColor()
  267. for more details.)
  268. *******************************************************************************/
  269. unsigned CGPDViewer::CommentColor(CString csphrase, int ncomloc, CString csline,
  270. int& nstartchar, int& nendchar)
  271. {
  272. // Determine the range in the line that contains the comment. This starts
  273. // at the comment characters and goes to the end of the line.
  274. nstartchar = nendchar + ncomloc ;
  275. nendchar = csline.GetLength() - 1 ;
  276. // Errors
  277. if (csphrase.Find(_T("Error:")) > ncomloc)
  278. return RGB(0x80, 0, 0) ;
  279. // Warnings
  280. if (csphrase.Find(_T("Warning:")) > ncomloc)
  281. return RGB(0x80, 0x80, 0) ;
  282. // If this comment doesn't contain an error or warning, make it green.
  283. return RGB(0, 0x80, 0) ;
  284. }
  285. /******************************************************************************
  286. CGPDViewer::KeywordColor
  287. Determine and save the character range for the comment. Then determine the
  288. type of comment and return the color required for that type. (See TextColor()
  289. for more details.)
  290. *******************************************************************************/
  291. unsigned CGPDViewer::KeywordColor(CString csphrase, int nkeyloc, CString csline,
  292. int& nstartchar, int& nendchar)
  293. {
  294. // Determine the length of the token that might be a keyword. Keywords are
  295. // made up of letters, '?', '_', and '0'.
  296. TCHAR ch ;
  297. int nphlen = csphrase.GetLength() ;
  298. for (int nidx = nkeyloc + 1 ; nidx < nphlen ; nidx++) {
  299. ch = csphrase[nidx] ;
  300. if (ch != _T('?') && ch != _T('_') && (ch < _T('A') || ch > _T('Z'))
  301. && (ch < _T('a') || ch > _T('z')) && ch != _T('0'))
  302. break ;
  303. } ;
  304. // If there is a keyword to check, isolate it. Otherwise, update the range
  305. // for the * and return black as the color.
  306. CString cstoken ;
  307. if (nidx > nkeyloc + 1)
  308. cstoken = csphrase.Mid(nkeyloc + 1, nidx - nkeyloc - 1) ;
  309. else {
  310. nstartchar = nendchar + 1 ;
  311. nendchar = nstartchar + (nidx - nkeyloc - 1) ;
  312. return RGB(0, 0, 0) ;
  313. } ;
  314. // Update the range for the token no matter what it is. Include the * in
  315. // the range.
  316. nstartchar = nendchar + nkeyloc ;
  317. nendchar = nstartchar + (nidx - nkeyloc) ;
  318. // Try to find the token in the keyword array
  319. CStringArray& csakeys = ThisApp().GetGPDKeywordArray() ;
  320. int nelts = (int)csakeys.GetSize() ; // Number of elements in the keyword array
  321. int nleft, nright, ncomp ; // Variables needed for searching of array
  322. int ncheck ;
  323. for (nleft = 0, nright = nelts - 1 ; nleft <= nright ; ) {
  324. ncheck = (nleft + nright) >> 1 ;
  325. ncomp = csakeys[ncheck].Compare(cstoken) ;
  326. //TRACE("Key[%d] = '%s', Tok = '%s', Comp Res = %d\n", ncheck, csakeys[ncheck], cstoken, ncomp) ;
  327. if (ncomp > 0)
  328. nright = ncheck - 1 ;
  329. else if (ncomp < 0)
  330. nleft = ncheck + 1 ;
  331. else
  332. break ;
  333. } ;
  334. // If the token is a keyword, return blue as the color. Otherwise,
  335. // return black.
  336. if (ncomp == 0)
  337. return RGB(0, 0, 0x80) ;
  338. else
  339. return RGB(0, 0, 0) ;
  340. }
  341. /******************************************************************************
  342. CGPDViewer::UpdateNow
  343. This private member updates the underlying GPD and marks the document as
  344. changed, and the edit control as unmodified. It is called whenever this
  345. needs to be done.
  346. *******************************************************************************/
  347. void CGPDViewer::UpdateNow() {
  348. // Don't do this if nothing's chenged...
  349. if (!GetRichEditCtrl().GetModify())
  350. return;
  351. CWaitCursor cwc; // Just in case
  352. if (m_uTimer)
  353. ::KillTimer(m_hWnd, m_uTimer);
  354. m_uTimer = 0;
  355. GetDocument() -> ModelData() -> UpdateFrom(GetRichEditCtrl());
  356. GetDocument() -> SetModifiedFlag();
  357. GetRichEditCtrl().SetModify(FALSE);
  358. }
  359. CGPDViewer::CGPDViewer()
  360. {
  361. // Initialize member variables
  362. m_iLine = m_uTimer = 0 ;
  363. m_bInColor = FALSE ;
  364. m_bStart = TRUE ;
  365. m_iTopLineColored = -1 ;
  366. m_nErrorLevel = 0 ;
  367. m_bEditingAidsEnabled = true ;
  368. m_punk = NULL ;
  369. m_pdoc = NULL ;
  370. m_bVScroll = false ;
  371. // Initialize the GPD keyword array if this hasn't been done already.
  372. if (ThisApp().GetGPDKeywordArray().GetSize() == 0)
  373. InitGPDKeywordArray() ;
  374. }
  375. CGPDViewer::~CGPDViewer()
  376. {
  377. if (ThisApp().m_bOSIsW2KPlus)
  378. ReleaseFreeze(&m_punk, &m_pdoc) ;
  379. }
  380. /////////////////////////////////////////////////////////////////////////////
  381. // CGPDViewer diagnostics
  382. #ifdef _DEBUG
  383. void CGPDViewer::AssertValid() const {
  384. CRichEditView::AssertValid();
  385. }
  386. void CGPDViewer::Dump(CDumpContext& dc) const {
  387. CRichEditView::Dump(dc);
  388. }
  389. #endif //_DEBUG
  390. /******************************************************************************
  391. CGPDViewer::OnDestroy
  392. Handles the required project node notification when the view is destroyed.
  393. A GP Fault is a terrible thing to signal.
  394. ******************************************************************************/
  395. void CGPDViewer::OnDestroy() {
  396. CRichEditView::OnDestroy();
  397. if (GetDocument() -> ModelData())
  398. GetDocument() -> ModelData() -> OnEditorDestroyed();
  399. if (ThisApp().m_bOSIsW2KPlus)
  400. ReleaseFreeze(&m_punk, &m_pdoc) ;
  401. }
  402. /******************************************************************************
  403. CGPDViewer::OnInitialUpdate
  404. This is the wake-up call. We fill the view from the GPD's contents, and
  405. eventually color things to suit us.
  406. ******************************************************************************/
  407. void CGPDViewer::OnInitialUpdate()
  408. {
  409. // Set the frame's window style and initialize the rich edit control (REC).
  410. GetParentFrame() -> ModifyStyle(0, WS_OVERLAPPEDWINDOW);
  411. CRichEditView::OnInitialUpdate();
  412. // Create and configure the GPD Editor's status bar
  413. if (m_csb.Create(GetParentFrame())) {
  414. static UINT auid[] = {ID_SEPARATOR, ID_LineIndicator};
  415. m_csb.SetIndicators(auid, 2);
  416. m_csb.SetPaneInfo(1, ID_LineIndicator, SBPS_NORMAL, 200);
  417. GetParentFrame() -> RecalcLayout();
  418. }
  419. // We don't want EN_CHANGE messages while we load the control
  420. GetRichEditCtrl().SetEventMask(GetRichEditCtrl().GetEventMask() &
  421. ~ENM_CHANGE);
  422. // We also do not want the control to wrap lines for us, as it messes up
  423. // syntax coloring, etc.
  424. m_nWordWrap = WrapNone;
  425. WrapChanged();
  426. // Load the GPD's contents into the REC.
  427. GetDocument() -> ModelData() -> Fill(GetRichEditCtrl());
  428. SetFocus();
  429. // We want EN_CHANGE messages now that the initial load is complete so
  430. // that we can update the cache. To keep from overloading the machine,
  431. // some change notifications are just acted upon once every half second.
  432. // A timer is used to do this.
  433. GetRichEditCtrl().SetEventMask(GetRichEditCtrl().GetEventMask() |
  434. ENM_CHANGE);
  435. m_uTimer = (unsigned) SetTimer((UINT_PTR) this, 500, NULL);
  436. GetRichEditCtrl().SetSel(1, 1); // Have to change the selection!
  437. GetRichEditCtrl().SetSel(0, 0);
  438. // Initialize the pointers needed to freeze the REC.
  439. if (ThisApp().m_bOSIsW2KPlus)
  440. InitFreeze(GetRichEditCtrl().m_hWnd, &m_punk, &m_pdoc, &m_lcount) ;
  441. }
  442. /******************************************************************************
  443. CGPDViewer::OnFileParse
  444. Syntax check the GPD file, and show us the results
  445. ******************************************************************************/
  446. void CGPDViewer::OnFileParse() {
  447. CWaitCursor cwc;
  448. if (GetDocument() -> ModelData() -> HasErrors()) {
  449. m_cdbActionBar.DestroyWindow();
  450. GetParentFrame() -> RecalcLayout();
  451. }
  452. // Save any changes made to the file.
  453. bool brestore = false ; // True iff original file must be restored
  454. BOOL bdocmod = GetDocument()->IsModified() ;
  455. if (GetRichEditCtrl().GetModify() || bdocmod) {
  456. UpdateNow(); // Pick up any new changes
  457. GetDocument()->ModelData()->BkupStore() ;
  458. GetDocument()->SetModifiedFlag(bdocmod) ;
  459. brestore = true ;
  460. }
  461. // Reparse the GPD
  462. if (!GetDocument()->ModelData()->Parse(m_nErrorLevel))
  463. AfxMessageBox(IDS_UnusualError) ;
  464. // Restore the original GPD file (when needed) because the user wasn't
  465. // asked if it was ok to save the file.
  466. if (brestore)
  467. GetDocument()->ModelData()->Restore() ;
  468. // Display the action bar and load the error list.
  469. CreateActionBar() ;
  470. LoadErrorListBox() ;
  471. MessageBeep(MB_ICONASTERISK) ;
  472. // Mark the project containing this GPD as being dirty so that the new
  473. // errors (or lack there of) will be saved in the MDW file.
  474. //RAID 17181 Here are suggestions. current fix is (3)
  475. // (1). Ask when workspace close if Error box has the bug in any Gpd file, which was check
  476. // (2). Ask when Gpd viewer close if Error box has the bug in any Gpd file, which was check
  477. // (3). Do not ask at all, not saving error list
  478. // CModelData& cmd = *GetDocument()->ModelData(); //add 1/2
  479. // if(cmd.HasErrors()) // add 2/2
  480. // GetDocument()->ModelData()->WorkspaceChange() ; (1)
  481. // OnChange(); (2) // add This prompt save ask message when close gpd viewer instead of workspace
  482. // (3)
  483. }
  484. /******************************************************************************
  485. CGPDViewer::OnChange
  486. This gets called whenever a change is made to the contents of the file.
  487. The coloring (now done only on the visible page) is updated, and the
  488. appropriate flags are set. To keep performance smooth, the document is no
  489. longer updated as a result of this message.
  490. ******************************************************************************/
  491. void CGPDViewer::OnChange()
  492. {
  493. // Since this is a RICHEDIT control, I override the
  494. // CRichEditView::OnInitialUpdate() function to or the ENM_CHANGE flag
  495. // into the control's event mask. Otherwise this message wouldn't be
  496. // sent.
  497. //
  498. // To avoid thrashing the GPD contents unneedfully, we wait for 1 second
  499. // of inactivity before bashing the changes into the GPD.
  500. // Scrolling data in the control generates two messages; first a scroll
  501. // message and then a change message. This could cause scrolling to mark
  502. // the document as dirty if this flag wasn't used to keep this from
  503. // happening.
  504. if (m_bVScroll) {
  505. m_bVScroll = false ;
  506. return ;
  507. } ;
  508. // Do nothing if the change message was generated by Color().
  509. if (m_bInColor)
  510. return ;
  511. // Colorize whatever is on the screen and mark the document as having
  512. // changed.
  513. Color() ;
  514. GetDocument()->SetModifiedFlag() ;
  515. }
  516. /******************************************************************************
  517. CGPDViewer::OnTimer
  518. This handles the timeout of the timer used to batch changes into the
  519. underlying document. If this isn't for that timer, we pass it on to the base
  520. class.
  521. ******************************************************************************/
  522. void CGPDViewer::OnTimer(UINT uEvent) {
  523. // If this isn't our timer, let the base class do what it will with it.
  524. if (m_uTimer == uEvent)
  525. if (m_bStart) {
  526. if (GetRichEditCtrl().GetLineCount() <
  527. GetDocument() -> ModelData() -> LineCount())
  528. return; // The rich edit control isn't ready, yet...
  529. ::KillTimer(m_hWnd, m_uTimer);
  530. Color();
  531. m_uTimer = 0;
  532. m_bStart = FALSE;
  533. }
  534. else
  535. UpdateNow();
  536. else
  537. CRichEditView::OnTimer(uEvent);
  538. }
  539. /******************************************************************************
  540. CGPDViewer::OnSelChange
  541. This handles the message sent by the control when the selection changes. I'm
  542. hoping this means whenever the caret moves, since the selection, while empty,
  543. has changed.
  544. ******************************************************************************/
  545. void CGPDViewer::OnSelChange(LPNMHDR pnmh, LRESULT *plr) {
  546. SELCHANGE* psc = (SELCHANGE *) pnmh;
  547. long lLine = GetRichEditCtrl().LineFromChar(psc -> chrg.cpMin);
  548. CString csWork;
  549. csWork.Format(_T("Line %d, Column %d"), lLine + 1,
  550. 1 + psc -> chrg.cpMax - GetRichEditCtrl().LineIndex(lLine));
  551. m_csb.SetPaneText(1, csWork);
  552. }
  553. /******************************************************************************
  554. CGPDViewer::OnUpdate
  555. If the first update hasn't been made, do nothing.
  556. Next, check to see if this routine was called by CGPDContainer::OnSaveDocument().
  557. If it was, make sure that the document has an up to date copy of the GPD.
  558. This is a hack to work around problems with CGPDContainer routines in
  559. modldata.dll call CGPDViewer routines in minidev.exe. This problem should
  560. go away when the 3 MDT DLLs are folded back into the EXE.
  561. Otherwise, redo the error bar, because someone just syntax checked the
  562. workspace.
  563. ******************************************************************************/
  564. void CGPDViewer::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
  565. {
  566. if (m_bStart) // Have we already done the first update?
  567. return;
  568. // Update the document if this routine was called by the document class.
  569. if (lHint == 0x4545 && (INT_PTR) pHint == 0x4545) {
  570. UpdateNow() ;
  571. return ;
  572. } ;
  573. // If there's a dialog bar, can it.
  574. if (m_cdbActionBar.GetSafeHwnd()) {
  575. m_cdbActionBar.DestroyWindow();
  576. GetParentFrame() -> RecalcLayout();
  577. }
  578. // Recreate the action bar and load the error list.
  579. CreateActionBar() ;
  580. LoadErrorListBox();
  581. }
  582. /******************************************************************************
  583. CGPDViewer::QueryAcceptData
  584. Override the Rich Edit Control default behavior, because we (a) don't have
  585. an associated RichEditDoc, and (b) we don't want to paste anything but text.
  586. Not even rich text, because we control the formatting, and don't want to
  587. paste it.
  588. ******************************************************************************/
  589. HRESULT CGPDViewer::QueryAcceptData(LPDATAOBJECT lpdo, CLIPFORMAT* lpcf, DWORD,
  590. BOOL bReally, HGLOBAL hgMetaFile) {
  591. _ASSERTE(lpcf != NULL);
  592. COleDataObject codo;
  593. codo.Attach(lpdo, FALSE);
  594. // if format is 0, then force particular formats if available
  595. if (*lpcf == 0 && (m_nPasteType == 0)&& codo.IsDataAvailable(CF_TEXT)) {
  596. *lpcf = CF_TEXT;
  597. return S_OK;
  598. }
  599. return E_FAIL;
  600. }
  601. /******************************************************************************
  602. CGPDViewer::OnVScroll()
  603. This function is called when EN_VSCROLL messages are refelected from the
  604. edit control. As long as we are not coloring, we color the new page. The
  605. documentation says this message comes BEFORE the scolling occurs, but it
  606. obviously occurs afterwards.
  607. ******************************************************************************/
  608. void CGPDViewer::OnVscroll()
  609. {
  610. // Even though we turn scroll notifications off in the color routine,
  611. // we still get them, so use a flag to keep from recursive death.
  612. //
  613. // In addition, a flag is set to say that a scroll message was just
  614. // processed so that the OnChange routine will know when it doesn't need to
  615. // do anything. This is needed because scrolling generates both a scroll
  616. // and a change message.
  617. if (m_iTopLineColored != GetRichEditCtrl().GetFirstVisibleLine() &&
  618. !m_bInColor) {
  619. if(!(GetKeyState(VK_SHIFT) & 0x8000)) // raid 28160 : GetSel,SetSel has bug(seem sdk bug)
  620. Color() ;
  621. m_bVScroll = true ;
  622. } ;
  623. }
  624. /******************************************************************************
  625. CGPDViewer::OnVScroll(UINT uCode, UINT uPosition, CScrollBar *pcsb)
  626. This is called whwnever the scoll bar gets clicked. This may seem
  627. redundant, but EN_VSCROLL messages don't get sent when the thumb itself is
  628. moved with the mouse, and WM_VSCROLL doesn't get sent when the keyboard
  629. interface is used. So you get to lose either way.
  630. This control is buggy as can be, IMHO. Next time I want to do text editing,
  631. I'll use a third party tool. They starve if they don't get it right.
  632. ******************************************************************************/
  633. void CGPDViewer::OnVScroll(UINT uCode, UINT uPosition, CScrollBar* pcsb)
  634. {
  635. CRichEditView::OnVScroll(uCode, uPosition, pcsb);
  636. //(Raid 16569)
  637. if(uCode == SB_THUMBTRACK)
  638. OnVscroll();
  639. }
  640. /******************************************************************************
  641. CGPDViewer::OnFileSave
  642. CGPDViewer::OnFileSaveAs
  643. Since we don't update the document as changes are made in the editor, we have
  644. to intercept these, update the document, and then pass these on to the
  645. document.
  646. ******************************************************************************/
  647. void CGPDViewer::OnFileSave() {
  648. UpdateNow();
  649. GetDocument() -> OnFileSave();
  650. }
  651. void CGPDViewer::OnFileSaveAs() {
  652. UpdateNow();
  653. GetDocument() -> OnFileSaveAs();
  654. }
  655. /******************************************************************************
  656. CGPDViewer::OnUpdateEditPaste
  657. CGPDViewer::OnUpdateEditUndo
  658. These override the default processing for these menu items. Paste is only
  659. possible with a text format.
  660. DEAE_BUG Fix text coloring when an Undo operation is performed.
  661. *******************************************************************************/
  662. void CGPDViewer::OnUpdateEditPaste(CCmdUI* pccui) {
  663. pccui -> Enable(IsClipboardFormatAvailable(CF_TEXT));
  664. }
  665. void CGPDViewer::OnUpdateEditUndo(CCmdUI* pccui) {
  666. pccui -> Enable(0);
  667. }
  668. void CGPDViewer::OnEditPaste()
  669. { //raid 16573
  670. CMainFrame *pcmf = (CMainFrame*) GetTopLevelFrame() ;
  671. ASSERT(pcmf != NULL) ;
  672. CGPDToolBar *cgtb = pcmf->GetGpdToolBar() ;
  673. if(GetFocus() == FromHandle(cgtb->ceSearchBox.m_hWnd) )
  674. cgtb->ceSearchBox.Paste();
  675. else
  676. GetRichEditCtrl().Paste() ;
  677. OnChange() ;
  678. }
  679. void CGPDViewer::OnEditCut()
  680. {
  681. GetRichEditCtrl().Cut() ;
  682. OnChange() ;
  683. }
  684. /******************************************************************************
  685. CGPDViewer::OnSelchangeErrorLst
  686. Update the REC by selected the GPD line corresponding to the currently
  687. selected error list item.
  688. ******************************************************************************/
  689. void CGPDViewer::OnSelchangeErrorLst()
  690. {
  691. ChangeSelectedError(0) ;
  692. }
  693. /******************************************************************************
  694. CGPDViewer::ChangeSelectedError
  695. Whenever the error message selected in the list box and/or the GPD line that
  696. generated the error should change, this routine is called to manage the work.
  697. ******************************************************************************/
  698. void CGPDViewer::ChangeSelectedError(int nchange)
  699. {
  700. // Make sure that the action bar exists before doing anything.
  701. if (m_cdbActionBar.m_hWnd == NULL || !IsWindow(m_cdbActionBar.m_hWnd))
  702. return ;
  703. // Get a pointer to the list box and attach it to CListBox.
  704. CWnd *pcwndlst = m_cdbActionBar.GetDlgItem(IDC_ErrorLst) ;
  705. CListBox clberrors ;
  706. clberrors.Attach(pcwndlst->m_hWnd) ;
  707. // Get the selected item number and the number of items.
  708. int nselitem = clberrors.GetCurSel() ;
  709. int numitems = clberrors.GetCount() ;
  710. // If the selected item number should change, change it. Then "wrap" the
  711. // number if it goes out of bounds. Last, select the referenced item.
  712. if (nchange != 0) {
  713. nselitem += nchange ;
  714. if (nselitem < 0)
  715. nselitem = numitems - 1 ;
  716. else if (nselitem >= numitems)
  717. nselitem = 0 ;
  718. clberrors.SetCurSel(nselitem) ;
  719. } ;
  720. // We're done with the list box now so detach from it.
  721. clberrors.Detach() ;
  722. // Select the error line in the REC and set the focus to the REC.
  723. MarkError(nselitem) ;
  724. SetFocus() ;
  725. }
  726. /******************************************************************************
  727. CGPDViewer::PreTranslateMessage
  728. Take special action when certain characters are entered. Those characters
  729. are:
  730. F4 Select next error and corresponding GPD line when possible.
  731. Shift+F4 Select previous error and corresponding GPD line when possible.
  732. Ctrl+] Find a matching bracket "[]", paren "()", curly brace "{}", or
  733. angle brackets "<>".
  734. ******************************************************************************/
  735. BOOL CGPDViewer::PreTranslateMessage(MSG* pMsg)
  736. {
  737. // If F4 or Shift+F4 is pressed, change the selected error message and
  738. // update the current selected line in the GPD.
  739. if (pMsg->message == WM_KEYUP && pMsg->wParam == VK_F4) {
  740. if (!(GetKeyState(VK_SHIFT) & 0x8000))
  741. ChangeSelectedError(1) ;
  742. else
  743. ChangeSelectedError(-1) ;
  744. return CRichEditView::PreTranslateMessage(pMsg) ;
  745. } ;
  746. // Handle help command (F1)
  747. /*
  748. if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_F1) {
  749. //TRACE0("Calling Help on GPD\n") ;
  750. //ThisApp().WinHelp(0x20000 + IDR_GPD_VIEWER) ;
  751. //TRACE0("Calling Help on String\n") ;
  752. //ThisApp().WinHelp(0x20000 + IDR_STRINGEDITOR) ;
  753. //TRACE0("Calling Help on UFM\n") ;
  754. //ThisApp().WinHelp(0x20000 + IDR_FONT_VIEWER) ;
  755. TRACE0("Calling Help on GTT\n") ;
  756. ThisApp().WinHelp(0x20000 + IDR_GLYPHMAP) ;
  757. return 1 ;
  758. } ;
  759. */
  760. // From here on, only messages (usually keys) for the REC are interesting
  761. // so process the rest normally and just return.
  762. if (this != GetFocus() || pMsg->message != WM_KEYUP)
  763. return CRichEditView::PreTranslateMessage(pMsg) ;
  764. // Handle matching brace command
  765. if (GetKeyState(VK_CONTROL) & 0x8000) {
  766. //TRACE("KEY = %d, 0x%x\n", pMsg->wParam, pMsg->wParam) ;
  767. // Process goto matching brace commands.
  768. if (pMsg->wParam == 0xDD)
  769. GotoMatchingBrace() ;
  770. } ;
  771. // Process the message normally.
  772. return CRichEditView::PreTranslateMessage(pMsg) ;
  773. }
  774. /******************************************************************************
  775. CGPDViewer::OnSrchNextBtn
  776. Search forward for the next part of the GPD that matches the specified text.
  777. ******************************************************************************/
  778. void CGPDViewer::OnSrchNextBtn()
  779. {
  780. SearchTheREC(true) ;
  781. }
  782. /******************************************************************************
  783. CGPDViewer::OnSrchPrevBtn
  784. Search backward for the previous part of the GPD that matches the specified
  785. text.
  786. ******************************************************************************/
  787. void CGPDViewer::OnSrchPrevBtn()
  788. {
  789. SearchTheREC(false) ;
  790. }
  791. /******************************************************************************
  792. CGPDViewer::SearchTheREC
  793. Search either forward or backward for the next part of the GPD that matches
  794. the specified text. Select the matching text in the GPD.
  795. Return true if a match is found. Otherwise, return false.
  796. ******************************************************************************/
  797. bool CGPDViewer::SearchTheREC(bool bforward)
  798. {
  799. CMainFrame *pcmf = (CMainFrame*) GetTopLevelFrame() ;
  800. ASSERT(pcmf != NULL) ;
  801. CString cstext ;
  802. pcmf->GetGPDSearchString(cstext) ;
  803. int nstlen ;
  804. if ((nstlen = cstext.GetLength()) == 0) {
  805. AfxMessageBox(IDS_BadSearchString) ;
  806. return false ;
  807. } ;
  808. // Declare the find text structure and get a reference to the REC. Then
  809. // get the character range for the text currently selected in the REC.
  810. // This info will be used to compute the search range.
  811. FINDTEXTEX fte ;
  812. CRichEditCtrl& crec = GetRichEditCtrl() ;
  813. crec.GetSel(fte.chrg) ;
  814. // Set the search range. If searching forward, search from the current
  815. // selection to the end of the GPD. If searching backwards, search from
  816. // the current selection to the beginning of the GPD.
  817. //
  818. // DEAD_BUG Is the latter correct???
  819. int norgcpmin = fte.chrg.cpMin ;
  820. int norgcpmax = fte.chrg.cpMax ;
  821. if (bforward) {
  822. fte.chrg.cpMin = fte.chrg.cpMax ;
  823. fte.chrg.cpMax = -1 ;
  824. } else {
  825. fte.chrg.cpMin = 0 ;
  826. fte.chrg.cpMax = norgcpmin ;
  827. } ;
  828. // Load a pointer to the search string into the fte.
  829. fte.lpstrText = cstext.GetBuffer(nstlen + 1) ;
  830. // Perform the first attempt at finding a match.
  831. int nmatchpos ;
  832. if (bforward)
  833. nmatchpos = crec.FindText(0, &fte) ;
  834. else
  835. nmatchpos = ReverseSearchREC(crec, fte, norgcpmin, norgcpmax) ;
  836. // If the match failed, try to search the other part of the GPD. Return
  837. // failure if this doesn't work either.
  838. /* if (nmatchpos == -1) {
  839. if (bforward) {
  840. fte.chrg.cpMin = 0 ;
  841. fte.chrg.cpMax = norgcpmax ;
  842. } else {
  843. fte.chrg.cpMin = norgcpmin ;
  844. fte.chrg.cpMax = -1 ;
  845. } ;
  846. if (bforward)
  847. nmatchpos = crec.FindText(0, &fte) ;
  848. else
  849. nmatchpos = ReverseSearchREC(crec, fte, norgcpmin, norgcpmax) ;
  850. */ if (nmatchpos == -1) {
  851. cstext.ReleaseBuffer() ;
  852. CString csmsg ;
  853. csmsg.Format(IDS_GPDStringSearchFailed, cstext) ;
  854. AfxMessageBox(csmsg, MB_ICONEXCLAMATION) ;
  855. return false ;
  856. } ;
  857. // A match was found so select it.
  858. crec.SetSel(nmatchpos, nmatchpos + nstlen) ;
  859. // A match was found and selected so return true.
  860. cstext.ReleaseBuffer() ;
  861. return true ;
  862. }
  863. /******************************************************************************
  864. CGPDViewer::ReverseSearchREC
  865. The REC's built in searching support does not search backwards so this
  866. routine is used to do this. The text in the specified range is loaded
  867. into a string and searched.
  868. The index of the match is returned if one is found. Otherwise, return -1.
  869. ******************************************************************************/
  870. int CGPDViewer::ReverseSearchREC(CRichEditCtrl& crec, FINDTEXTEX& fte,
  871. int norgcpmin, int norgcpmax)
  872. {
  873. // Hide selections to prevent flashing
  874. crec.HideSelection(TRUE, TRUE) ;
  875. // Get the index of the last character in the GPD if it is needed.
  876. int nresult ;
  877. if (fte.chrg.cpMax == -1) {
  878. crec.SetSel(0, -1) ;
  879. nresult = fte.chrg.cpMin ;
  880. crec.GetSel(fte.chrg) ;
  881. fte.chrg.cpMin = nresult ;
  882. } ;
  883. // Get the text in the part of the GPD we need to check.
  884. crec.SetSel(fte.chrg) ;
  885. CString cstext = crec.GetSelText() ;
  886. // Search the string backwards
  887. cstext.MakeReverse() ;
  888. cstext.MakeUpper() ;
  889. CString csrevsrch = fte.lpstrText ;
  890. csrevsrch.MakeReverse() ;
  891. csrevsrch.MakeUpper() ;
  892. nresult = cstext.Find(csrevsrch) ;
  893. // If a match is found, "reverse" the number to reverse the affects of
  894. // reversing the strings.
  895. if (nresult >= 0) {
  896. nresult = fte.chrg.cpMax - fte.chrg.cpMin - nresult
  897. - csrevsrch.GetLength() ;
  898. // Adjust the offset of the matching string when necessary. We want a
  899. // REC index not a string index.
  900. if (fte.chrg.cpMin != 0)
  901. nresult += fte.chrg.cpMin - 2 ;
  902. } ;
  903. // Reset the original selection, show selections again, and return the
  904. // result.
  905. crec.SetSel(norgcpmin, norgcpmax) ;
  906. crec.HideSelection(FALSE, TRUE) ;
  907. return nresult ;
  908. }
  909. /******************************************************************************
  910. CGPDViewer::OnGotoGPDLineNumber
  911. Goto the requested GPD line number in the REC.
  912. ******************************************************************************/
  913. void CGPDViewer::OnGotoGPDLineNumber()
  914. {
  915. // Declare the Goto Line dialog box and set the maximum line number.
  916. CGotoLine cgl ;
  917. CRichEditCtrl& crec = GetRichEditCtrl() ;
  918. cgl.SetMaxLine(crec.GetLineCount()) ;
  919. // Display the dialog box and exit if the user cancels.
  920. if (cgl.DoModal() == IDCANCEL)
  921. return ;
  922. // Get the line number. Then, determine the line's first character number
  923. // and its length.
  924. int nlinenum = cgl.GetLineNum() ;
  925. CString csline ;
  926. int nstartchar = crec.LineIndex(-1 + nlinenum) ;
  927. int nlinelen = crec.GetLine(nlinenum - 1, csline.GetBuffer(1024), 1024) ;
  928. csline.ReleaseBuffer(nlinelen) ;
  929. nlinelen -= 2 ;
  930. // Select the requested line and scroll it into view.
  931. crec.SetSel(nstartchar, nstartchar + nlinelen) ;
  932. crec.LineScroll(nlinenum - (5 + crec.GetFirstVisibleLine())) ;
  933. // All went well so...
  934. return ;
  935. }
  936. /******************************************************************************
  937. CGPDViewer::OnFileErrorLevel
  938. Get and save the newly selected error level.
  939. ******************************************************************************/
  940. void CGPDViewer::OnFileErrorLevel()
  941. {
  942. // Initialize and display the error level dialog box. Just return if the
  943. // user cancels.
  944. CErrorLevel cel ;
  945. cel.SetErrorLevel(m_nErrorLevel) ;
  946. if (cel.DoModal() == IDCANCEL)
  947. return ;
  948. // Save the new error level
  949. m_nErrorLevel = cel.GetErrorLevel() ;
  950. }
  951. /******************************************************************************
  952. CGPDViewer::GotoMatchingBrace
  953. Find and goto the matching brace in the REC. The following types of braces
  954. are matched:
  955. (), {}, [], <>
  956. If there is a brace to match and a match is found, move the cursor to the
  957. left of the matching brace and make sure the line containing the brace is
  958. visible. Return true in this case.
  959. If there is no brace to match or a match cannot be found, just beep and
  960. return false.
  961. In the case where the cursor is in between two braces, the one to the right
  962. of the cursor is matched. If 1+ characters are actually selected, only
  963. check the last character to see if it is a brace to match.
  964. ******************************************************************************/
  965. bool CGPDViewer::GotoMatchingBrace()
  966. {
  967. // Get a reference to the REC and hide selections in it because this
  968. // routine might change the selection several times and I don't want the
  969. // screen to flash as the selection changes.
  970. CRichEditCtrl& crec = GetRichEditCtrl() ;
  971. crec.LockWindowUpdate() ;
  972. crec.HideSelection(TRUE, TRUE) ;
  973. // Get the selection range and make a copy of it. Increase the copy by one
  974. // on each side if the min and max are the same. This is done to find
  975. // match characters when there is no selection. Use the copy to set and get
  976. // the selection.
  977. CHARRANGE crorg, cr ;
  978. crec.GetSel(crorg) ;
  979. cr.cpMin = crorg.cpMin ;
  980. cr.cpMax = crorg.cpMax ;
  981. bool bchecksecondchar = false ;
  982. if (cr.cpMin == cr.cpMax) {
  983. cr.cpMax++ ;
  984. if (cr.cpMin > 0) // Do go passed beginning of file and maintain
  985. cr.cpMin-- ; // string length.
  986. else
  987. cr.cpMax++ ;
  988. crec.SetSel(cr) ;
  989. bchecksecondchar = true ;
  990. } ;
  991. CString cssel = crec.GetSelText() ;
  992. // HACK ALERT - There seems to be a bug in the REC that will return the
  993. // wrong characters if the cursor is flush left (at the beginning of
  994. // the line and cpMin is reduced so the characters requested span a
  995. // line. This is determined by the cssel beginning with CR+LF. When this
  996. // is detected, reset bchecksecondchar because in brace will be the last
  997. // character in the string so things will work fine if bchecksecondchar is
  998. // reset. CpMin needs to be adjusted too.
  999. bool bbegline = false ;
  1000. if (bchecksecondchar && cssel.GetLength() >= 2 && cssel[0] == 0xD
  1001. && cssel[1] == 0xA) {
  1002. bchecksecondchar = false ;
  1003. cr.cpMin = cr.cpMax - 1 ;
  1004. bbegline = true ;
  1005. } ;
  1006. // Try to find a brace to match in the selection (opening character) and
  1007. // use this info to set the matching brace (closing character). If this
  1008. // fails, reset everything, beep, and return.
  1009. TCHAR chopen, chclose ; // Opening/closing characters to match
  1010. int noffset ; // Offset in REC for brace to match
  1011. bool bsearchup ; // True iff must search up in REC for match
  1012. if (!IsBraceToMatch(cssel, chopen, chclose, bchecksecondchar, bsearchup,
  1013. cr, noffset)) {
  1014. crec.SetSel(crorg) ;
  1015. crec.HideSelection(FALSE, TRUE) ;
  1016. crec.UnlockWindowUpdate() ;
  1017. MessageBeep(0xFFFFFFFF) ;
  1018. return false ;
  1019. } ;
  1020. // Determine the starting and ending range to search.
  1021. if (bsearchup) {
  1022. cr.cpMin = 0 ;
  1023. cr.cpMax = noffset ;
  1024. if (bbegline) // One more tweak to get around the bug
  1025. cr.cpMax -= 2 ;
  1026. } else {
  1027. cr.cpMin = noffset + 1 ;
  1028. cr.cpMax = -1 ;
  1029. } ;
  1030. // Get the text we want to search.
  1031. crec.SetSel(cr) ;
  1032. cssel = crec.GetSelText() ;
  1033. // Set the loop counter, loop counter increment, and loop limit that will
  1034. // cause a search up (backwards) or down (forwards).
  1035. int nidx, nloopinc, nlimit ;
  1036. if (bsearchup) {
  1037. nidx = cssel.GetLength() - 1 ;
  1038. nloopinc = -1 ;
  1039. nlimit = -1 ;
  1040. } else {
  1041. nidx = 0 ;
  1042. nloopinc = 1 ;
  1043. nlimit = cssel.GetLength() ;
  1044. } ;
  1045. // Loop through the text checking characters for a matching brace. The
  1046. // brace count is incremented when an opening brace if found and decremented
  1047. // when a closing brace is found. The matching brace has been found when
  1048. // the brace count reaches 0.
  1049. int nbracecount = 1 ; // Count first opening brace
  1050. for ( ; nidx != nlimit && nbracecount != 0 ; nidx += nloopinc) {
  1051. if (cssel[nidx] == chclose)
  1052. nbracecount-- ;
  1053. else if (cssel[nidx] == chopen)
  1054. nbracecount++ ;
  1055. } ;
  1056. // Reset everything, beep, and return false if no matching brace was found.
  1057. if (nbracecount != 0) {
  1058. crec.SetSel(crorg) ;
  1059. crec.HideSelection(FALSE, TRUE) ;
  1060. crec.UnlockWindowUpdate() ;
  1061. MessageBeep(0xFFFFFFFF) ;
  1062. return false ;
  1063. } ;
  1064. // Determine the REC based range needed to put the cursor to the left of
  1065. // the matching brace. The method used to do this depends on the search
  1066. // direction. Then set the selection.
  1067. if (bsearchup)
  1068. cr.cpMin = cr.cpMax = nidx + 1 ;
  1069. else
  1070. cr.cpMin = cr.cpMax = cr.cpMin + nidx - 1 ;
  1071. crec.SetSel(cr) ;
  1072. // Scroll the line containing the matching brace into view iff it is not
  1073. // already visible.
  1074. int nline = crec.LineFromChar(cr.cpMin) ;
  1075. if (!IsRECLineVisible(nline)) {
  1076. if (bsearchup)
  1077. crec.LineScroll(nline - (2 + crec.GetFirstVisibleLine())) ;
  1078. else
  1079. crec.LineScroll(nline - (5 + crec.GetFirstVisibleLine())) ;
  1080. } ;
  1081. // Show the selection again and return true to indicate a match was found.
  1082. crec.HideSelection(FALSE, TRUE) ;
  1083. crec.UnlockWindowUpdate() ;
  1084. return true ;
  1085. }
  1086. /******************************************************************************
  1087. CGPDViewer::IsBraceToMatch
  1088. Find out if there is a brace to match. Return true if there is and save that
  1089. brace as the opening character and save its matching brace as the closing
  1090. character. In addition, determine and save the REC offset for the opening
  1091. character. Last, set a flag to tell if searching for the match should go
  1092. up into the REC or down into the REC based the opening character being the
  1093. right or left brace. If no opening brace is found, return false.
  1094. In the case where the cursor is in between two braces, the one to the right
  1095. of the cursor is matched. If 1+ characters are actually selected, only
  1096. check the last character to see if it is a brace to match.
  1097. ******************************************************************************/
  1098. bool CGPDViewer::IsBraceToMatch(CString& cssel, TCHAR& chopen, TCHAR& chclose,
  1099. bool bchecksecondchar, bool& bsearchup,
  1100. CHARRANGE cr, int& noffset)
  1101. {
  1102. int nsellen = cssel.GetLength() ; // Length of selection string
  1103. // Loop through the character(s) to be checked.
  1104. chclose = 0 ;
  1105. for (int n = 1 ; n >= 0 ; n--) {
  1106. // Use the type of selection and the iteration to determine which - if
  1107. // any - character to check and that character's offset.
  1108. if (bchecksecondchar) {
  1109. if (n >= nsellen)
  1110. continue ;
  1111. chopen = cssel[n] ;
  1112. noffset = cr.cpMin + n ;
  1113. } else if (n == 0) {
  1114. chopen = cssel[nsellen - 1] ;
  1115. noffset = cr.cpMin + nsellen - 1 ;
  1116. } else
  1117. continue ;
  1118. // Check all of the left braces. If an one is found, save its right
  1119. // brace. A left brace as an opening character means that the REC
  1120. // must be searched down.
  1121. bsearchup = false ;
  1122. if (chopen == _T('('))
  1123. chclose = _T(')') ;
  1124. if (chopen == _T('{'))
  1125. chclose = _T('}') ;
  1126. if (chopen == _T('['))
  1127. chclose = _T(']') ;
  1128. if (chopen == _T('<'))
  1129. chclose = _T('>') ;
  1130. // If we have a closing character, a match was found and all the needed
  1131. // info has been saved so return true.
  1132. if (chclose != 0)
  1133. return true ;
  1134. // Check all of the right braces. If an one is found, save its left
  1135. // brace. A right brace as an opening character means that the REC
  1136. // must be searched up.
  1137. bsearchup = true ;
  1138. if (chopen == _T(')'))
  1139. chclose = _T('(') ;
  1140. if (chopen == _T('}'))
  1141. chclose = _T('{') ;
  1142. if (chopen == _T(']'))
  1143. chclose = _T('[') ;
  1144. if (chopen == _T('>'))
  1145. chclose = _T('<') ;
  1146. // If we have a closing character, a match was found and all the needed
  1147. // info has been saved so return true.
  1148. if (chclose != 0)
  1149. return true ;
  1150. } ;
  1151. // If this point is reached, no brace was found so...
  1152. return false ;
  1153. }
  1154. /******************************************************************************
  1155. CGPDViewer::InitGPDKeywordArray
  1156. Build a sorted array of GPD keyword strings. This array is used to find and
  1157. colorize keywords, etc.
  1158. ******************************************************************************/
  1159. extern "C" PSTR GetGPDKeywordStr(int nkeyidx, PGLOBL pglobl) ;
  1160. extern "C" int InitGPDKeywordTable(PGLOBL pglobl) ;
  1161. void CGPDViewer::InitGPDKeywordArray()
  1162. {
  1163. // Begin by getting a reference to the array and setting its initial size.
  1164. GLOBL globl;
  1165. PGLOBL pglobl = &globl;
  1166. CStringArray& csakeys = ThisApp().GetGPDKeywordArray() ;
  1167. csakeys.SetSize(400) ;
  1168. // Initialize the GPD keyword table and save its size. Shrink the array
  1169. // and return if this fails.
  1170. int numtabents ;
  1171. if ((numtabents = InitGPDKeywordTable(pglobl)) == -1) {
  1172. csakeys.SetSize(0) ;
  1173. return ;
  1174. } ;
  1175. // Declare variables needed to insert elements into the array.
  1176. int nelts = 0 ; // Number of elements used in the array
  1177. int nleft, nright, ncomp ; // Variables needed for searching of array
  1178. int ncheck ;
  1179. LPSTR lpstrkey ; // Pointer to current keyword
  1180. // Get all of the GPD keywords and use them to make a sorted array of
  1181. // keyword strings.
  1182. for (int nkeyidx = 0 ; nkeyidx <= numtabents ; nkeyidx++) {
  1183. // Get the next string pointer. Skip it if the pointer is NULL.
  1184. if ((lpstrkey = GetGPDKeywordStr(nkeyidx, pglobl)) == NULL)
  1185. continue ;
  1186. // Skip the curly braces that are in the keyword list.
  1187. if (strcmp(lpstrkey, _T("{")) == 0 || strcmp(lpstrkey, _T("}")) == 0)
  1188. continue ;
  1189. // Now find the location to insert this string into the list
  1190. for (nleft = 0, nright = nelts - 1 ; nleft <= nright ; ) {
  1191. ncheck = (nleft + nright) >> 1 ;
  1192. ncomp = csakeys[ncheck].Compare(lpstrkey) ;
  1193. //TRACE("Key[%d] = '%s', Tok = '%s', Comp Res = %d\n", ncheck, csakeys[ncheck], lpstrkey, ncomp) ;
  1194. if (ncomp > 0)
  1195. nright = ncheck - 1 ;
  1196. else if (ncomp < 0)
  1197. nleft = ncheck + 1 ;
  1198. else
  1199. break ;
  1200. } ;
  1201. // Insert the new string at the correct spot in the array.
  1202. csakeys.InsertAt(nleft, lpstrkey) ;
  1203. // Count this element and assert if the array limit has been reached.
  1204. nelts++ ;
  1205. ASSERT(nelts < 400) ;
  1206. } ;
  1207. // Now that we know the actual number of keywords, shrink the array to its
  1208. // correct size.
  1209. csakeys.SetSize(nelts) ;
  1210. // Either something is wrong with my array building code above or something
  1211. // is wrong with the CStringArray class because the array isn't sorted
  1212. // perfectly. There are a few problems. The code below is meant to fix
  1213. // those problems. The sorting algorithm is slow but it only has to be
  1214. // run once and few strings need to be moved so it should be ok.
  1215. int nidx1, nidx2 ;
  1216. CString cstmp ;
  1217. for (nidx1 = 0 ; nidx1 < nelts - 1 ; nidx1++) {
  1218. for (nidx2 = nidx1 + 1 ; nidx2 < nelts ; nidx2++) {
  1219. if (csakeys[nidx1].Compare(csakeys[nidx2]) > 0) {
  1220. cstmp = csakeys[nidx1] ;
  1221. csakeys[nidx1] = csakeys[nidx2] ;
  1222. csakeys[nidx2] = cstmp ;
  1223. } ;
  1224. } ;
  1225. } ;
  1226. /*
  1227. // Testing code used to make sure the array is sorted in ascending order.
  1228. CString cs1, cs2 ;
  1229. int x, y, z ;
  1230. for (x = 0 ; x < (nelts - 1) ; x++) {
  1231. if (csakeys[x].Compare(csakeys[x+1]) > 0) {
  1232. cs1 = csakeys[x] ;
  1233. cs2 = csakeys[x+1] ;
  1234. } ;
  1235. } ;
  1236. */
  1237. // Dump the contents of the sorted keyword array.
  1238. //for (nleft = 0 ; nleft < nelts ; nleft++)
  1239. // TRACE("%4d %s\n", nleft, csakeys[nleft]) ;
  1240. }
  1241. /******************************************************************************
  1242. CGPDViewer::IsRECLineVisible
  1243. Return true if the specified line is visible in the REC's window. Otherwise,
  1244. return false. If the specified line is -1 (the default), check the current
  1245. line.
  1246. Visibility is determined by getting the rect for the REC's window and - based
  1247. on the line number and height - determine if the line is in that rect.
  1248. ******************************************************************************/
  1249. bool CGPDViewer::IsRECLineVisible(int nline /*= -1*/)
  1250. {
  1251. // Get a reference to the REC.
  1252. CRichEditCtrl& crec = GetRichEditCtrl() ;
  1253. // Determine the height of lines in the REC's window.
  1254. int ntopline = crec.GetFirstVisibleLine() ;
  1255. int nlineheight = crec.GetCharPos(crec.LineIndex(ntopline+1)).y -
  1256. crec.GetCharPos(crec.LineIndex(ntopline)).y ;
  1257. // Determine the current line number if needed
  1258. CHARRANGE cr ;
  1259. if (nline == -1) {
  1260. crec.GetSel(cr) ;
  1261. nline = crec.LineFromChar(cr.cpMin) ;
  1262. } ;
  1263. // Get the dimensions of the REC's window
  1264. CRect crwindim ;
  1265. crec.GetClientRect(crwindim) ;
  1266. // Return true if the bottom of the line is above the bottom of the
  1267. // REC's window.
  1268. return (crec.GetCharPos(crec.LineIndex(nline)).y + nlineheight <
  1269. crwindim.bottom - 1) ;
  1270. }
  1271. LPTSTR CGPDViewer::alptstrStringIDKeys[] = { // Keywords with string ID values
  1272. _T("*rcModelNameID"),
  1273. _T("*rcInstalledOptionNameID"),
  1274. _T("*rcNotInstalledOptionNameID"),
  1275. _T("*rcInstallableFeatureNameID"),
  1276. _T("*rcNameID"),
  1277. _T("*rcPromptMsgID"),
  1278. _T("*rcInstallableFeatureNameID"),
  1279. _T("*rcNameID"),
  1280. _T("*rcCartridgeNameID"),
  1281. _T("*rcTTFontNameID"),
  1282. _T("*rcDevFontNameID"),
  1283. _T("*rcPersonalityID"),
  1284. _T("*rcHelpTextID"),
  1285. NULL
  1286. } ;
  1287. LPTSTR CGPDViewer::alptstrUFMIDKeys[] = { // Keywords with UFM ID values
  1288. _T("*DeviceFonts"),
  1289. _T("*DefaultFont"),
  1290. _T("*MinFontID"),
  1291. _T("*MaxFontID"),
  1292. _T("*Fonts"),
  1293. _T("*PortraitFonts"),
  1294. _T("*LandscapeFonts"),
  1295. NULL
  1296. } ;
  1297. /******************************************************************************
  1298. CGPDViewer::OnLButtonDblClk
  1299. If the user clicked on the RC ID for a string or a UFM, start the String
  1300. Editor or the UFM Editor. In the latter case, load the specified UFM into
  1301. the editor.
  1302. Current restrictions:
  1303. o This instance of the GPD Editor must have been started from the Workspace
  1304. view.
  1305. o Only numeric RC IDs are supported. Macros representing an ID are not
  1306. supported.
  1307. ******************************************************************************/
  1308. void CGPDViewer::OnLButtonDblClk(UINT nFlags, CPoint point)
  1309. {
  1310. // Do default double click processing first so that whatever the user
  1311. // clicked on will be selected.
  1312. CRichEditView::OnLButtonDblClk(nFlags, point) ;
  1313. // Do no further processing if GPD editing aids have been disabled.
  1314. if (!m_bEditingAidsEnabled)
  1315. return ;
  1316. // Another editor can only be started when the GPD Editor was run from the
  1317. // workspace view.
  1318. // if (!GetDocument()->GetEmbedded())
  1319. // return ;
  1320. // Get reference for the REC and get the selected text.
  1321. CRichEditCtrl& crec = GetRichEditCtrl() ;
  1322. CString cssel = crec.GetSelText() ;
  1323. // Try to turn the selected text into a number. Return if this doesn't
  1324. // work or the number is negative because only positive, numeric RC IDs
  1325. // are supported at this time.
  1326. int nrcid ;
  1327. if ((nrcid = atoi(cssel)) <= 0)
  1328. return ;
  1329. // Get the line containing the current selection
  1330. CHARRANGE cr ;
  1331. crec.GetSel(cr) ;
  1332. int nline = crec.LineFromChar(cr.cpMin) ;
  1333. TCHAR achline[1024] ;
  1334. int numchars = crec.GetLine(nline, achline, 1024) ;
  1335. achline[numchars] = 0 ;
  1336. CString csline = achline ;
  1337. // Do nothing if the number selected was in a comment.
  1338. if (csline.Find(_T("*%")) >= 0
  1339. && csline.Find(_T("*%")) < cr.cpMin - crec.LineIndex(nline))
  1340. return ;
  1341. // Now try to find a keyword in the line that has a string or UFM ID
  1342. // associated with it. If no keyword is found in this line and it begins
  1343. // with a plus sign (continuation character), check the previous line.
  1344. bool bstring = false ; // True iff a string ID was found
  1345. bool bufm = false ; // True iff a UFM ID was found
  1346. int n ; // Loop index
  1347. for ( ; ; ) {
  1348. // Try to find a matching string keyword in the current line
  1349. for (n = 0 ; alptstrStringIDKeys[n] != NULL ; n++)
  1350. if (csline.Find(alptstrStringIDKeys[n]) >= 0) {
  1351. bstring = true ;
  1352. break ;
  1353. } ;
  1354. // Try to find a matching UFM keyword in the current line
  1355. for (n = 0 ; alptstrUFMIDKeys[n] != NULL ; n++)
  1356. if (csline.Find(alptstrUFMIDKeys[n]) >= 0) {
  1357. bufm = true ;
  1358. break ;
  1359. } ;
  1360. // Blow if both types of keywords were found because this case isn't
  1361. // handled correctly.
  1362. ASSERT(!(bstring && bufm)) ;
  1363. // Setup to process the previous line if no match was found and this
  1364. // line starts with a continuation character. Otherwise, exit the
  1365. // loop or the routine.
  1366. if (bstring || bufm)
  1367. break ; // *** Loop exits here
  1368. else if (csline[0] != _T('+') || --nline < 0)
  1369. return ; // *** Routine exits when there is nothing to do
  1370. else {
  1371. numchars = crec.GetLine(nline, achline, 1024) ;
  1372. achline[numchars] = 0 ;
  1373. csline = achline ;
  1374. } ;
  1375. } ;
  1376. // Start the appropriate editor with the appropriate data loaded.
  1377. // Raid 3176 all below if.
  1378. if (!GetDocument()->GetEmbedded()){
  1379. // find the font name in RC file
  1380. //1. get rc file name 2. load rc file 3. find font name 4.make array with it's number and file path
  1381. //get rc file , assuem rc file is same with DLL name.if not user have to select rc file.
  1382. CString csPath = GetDocument()->GetPathName();
  1383. CString csrfile = csPath.Left(csPath.ReverseFind(_T('\\')) + 1);
  1384. csrfile = csrfile + _T("*.rc");
  1385. CFileFind cff;
  1386. // raid 201554
  1387. if ( cff.FindFile(csrfile)) {
  1388. cff.FindNextFile() ;
  1389. csrfile = cff.GetFilePath();
  1390. }
  1391. else
  1392. {
  1393. CString cstmp;
  1394. cstmp.LoadString(IDS_NotFoundRC);
  1395. if ( AfxMessageBox(cstmp,MB_YESNO) == IDYES ) {
  1396. CFileDialog cfd(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  1397. _T("RC Files (*.rc)|*.rc||") );
  1398. if(IDCANCEL == cfd.DoModal())
  1399. return ;
  1400. csrfile = cfd.GetFileName();
  1401. }
  1402. else
  1403. return ;
  1404. }
  1405. CWinApp *cwa = AfxGetApp();
  1406. if (bstring){
  1407. // we save RC path, its rcid for the use on StringEditorDoc
  1408. cwa->WriteProfileString(_T("StrEditDoc"),_T("StrEditDocS"),csrfile);
  1409. cwa->WriteProfileInt(_T("StrEditDoc"),_T("StrEditDoc"),nrcid );
  1410. }
  1411. // load rc file : only interested in font name
  1412. CString csUFMName;
  1413. if (bufm){ // can use just "else "
  1414. CDriverResources* pcdr = new CDriverResources();
  1415. CStringArray csaTemp1, csaTemp2,csaTemp3,csaTemp4,csaTemp5;
  1416. CStringTable cstTemp1, cstFonts, cstTemp2;
  1417. pcdr->LoadRCFile(csrfile , csaTemp1, csaTemp2,csaTemp3,csaTemp4,csaTemp5,
  1418. cstTemp1, cstFonts, cstTemp2,Win2000);
  1419. // get font name
  1420. csUFMName = cstFonts[(WORD)nrcid];
  1421. csUFMName = csPath.Left(csPath.ReverseFind(_T('\\')) + 1) + csUFMName ;
  1422. }
  1423. // call the document
  1424. POSITION pos = cwa->GetFirstDocTemplatePosition();
  1425. CString csExtName;
  1426. CDocTemplate *pcdt ;
  1427. while (pos != NULL){
  1428. pcdt = cwa -> GetNextDocTemplate(pos);
  1429. ASSERT (pcdt != NULL);
  1430. ASSERT (pcdt ->IsKindOf(RUNTIME_CLASS(CDocTemplate)));
  1431. pcdt ->GetDocString(csExtName, CDocTemplate::filterExt);
  1432. if (csExtName == _T(".UFM") & bufm){
  1433. pcdt->OpenDocumentFile(csUFMName,TRUE);
  1434. return;
  1435. }
  1436. if (csExtName == _T(".STR") & bstring){
  1437. pcdt->OpenDocumentFile(NULL) ;
  1438. return;
  1439. }
  1440. }
  1441. }
  1442. else{
  1443. CDriverResources* pcdr = (CDriverResources*) GetDocument()->ModelData()->GetWorkspace() ;
  1444. pcdr->RunEditor(bstring, nrcid) ;
  1445. }
  1446. }
  1447. /******************************************************************************
  1448. CGPDViewer::OnEditEnableAids
  1449. Reverse the state of the "Editing Aids Enabled" flag and reverse the checked
  1450. status of the corresponding menu command.
  1451. ******************************************************************************/
  1452. void CGPDViewer::OnEditEnableAids()
  1453. {
  1454. // Reverse the state of the flag
  1455. m_bEditingAidsEnabled = !m_bEditingAidsEnabled ;
  1456. // Reverse the checked status of the menu command
  1457. CMenu* pcm = AfxGetMainWnd()->GetMenu() ;
  1458. UINT ustate = (m_bEditingAidsEnabled) ? MF_CHECKED : MF_UNCHECKED ;
  1459. pcm->CheckMenuItem(ID_EDIT_ENABLE_AIDS, ustate) ;
  1460. }
  1461. /******************************************************************************
  1462. CGPDViewer::FreezeREC
  1463. Use a COM interface to the REC to freeze its display if possible. This is
  1464. the most efficient but it is only possible under Win2K+. In additon, tell the
  1465. REC to ignore change messages. This is needed even on Win2K+ because the
  1466. messages are generated even when the REC's display is frozen.
  1467. ******************************************************************************/
  1468. void CGPDViewer::FreezeREC()
  1469. {
  1470. GetRichEditCtrl().SetEventMask(GetRichEditCtrl().GetEventMask() &
  1471. ~(ENM_CHANGE | ENM_SELCHANGE | ENM_SCROLLEVENTS)) ;
  1472. if(!m_pdoc)//raid 104081: click and start : not call OnInitUpdate()
  1473. InitFreeze(GetRichEditCtrl().m_hWnd, &m_punk, &m_pdoc, &m_lcount) ;
  1474. if (ThisApp().m_bOSIsW2KPlus)
  1475. Freeze(m_pdoc, &m_lcount) ;
  1476. }
  1477. /******************************************************************************
  1478. CGPDViewer::UnfreezeREC
  1479. Use a COM interface to the REC to unfreeze its display if possible. This is
  1480. only possible under Win2K+. In additon, tell the REC to process change
  1481. messages again. This is needed even on Win2K+ because the messages are
  1482. always disabled by FreezeREC().
  1483. ******************************************************************************/
  1484. void CGPDViewer::UnfreezeREC()
  1485. {
  1486. if (ThisApp().m_bOSIsW2KPlus)
  1487. Unfreeze(m_pdoc, &m_lcount) ;
  1488. GetRichEditCtrl().SetEventMask(GetRichEditCtrl().GetEventMask() |
  1489. ENM_CHANGE | ENM_SELCHANGE | ENM_SCROLLEVENTS) ;
  1490. }
  1491. // RAID 0001
  1492. void CGPDViewer::OnFileInf()
  1493. {
  1494. CINFWizard* pciw = new CINFWizard(this, 1) ;
  1495. if (pciw->DoModal() == IDCANCEL) {
  1496. delete pciw ;
  1497. return ;
  1498. } ;
  1499. // Generate the INF file based on the information collected.
  1500. if (!pciw->GenerateINFFile()) {
  1501. delete pciw ;
  1502. return ;
  1503. } ;
  1504. // Allocate and initialize the document.
  1505. CINFWizDoc* pciwd = new CINFWizDoc((CGPDContainer*) GetDocument(), pciw) ;
  1506. // Create the window.
  1507. CMDIChildWnd* pcmcwnew ;
  1508. CMultiDocTemplate* pcmdt = INFViewerTemplate() ;
  1509. pcmcwnew = (CMDIChildWnd *) pcmdt->CreateNewFrame(pciwd, NULL) ;
  1510. // If the window was created, finish the initialization. Otherwise, just
  1511. // return.
  1512. if (pcmcwnew) {
  1513. pcmdt->InitialUpdateFrame(pcmcwnew, pciwd, TRUE) ;
  1514. pcmdt->AddDocument(pciwd) ;
  1515. } ;
  1516. }
  1517. /*
  1518. LRESULT CGPDViewer::OnCommandHelp(WPARAM wParam, LPARAM lParam)
  1519. {
  1520. return 0 ;
  1521. }
  1522. */
  1523. /////////////////////////////////////////////////////////////////////////////
  1524. // CGotoLine dialog
  1525. CGotoLine::CGotoLine(CWnd* pParent /*=NULL*/)
  1526. : CDialog(CGotoLine::IDD, pParent)
  1527. {
  1528. //{{AFX_DATA_INIT(CGotoLine)
  1529. m_csLineNum = _T("");
  1530. //}}AFX_DATA_INIT
  1531. m_nMaxLine = m_nLineNum = -1 ;
  1532. }
  1533. void CGotoLine::DoDataExchange(CDataExchange* pDX)
  1534. {
  1535. CDialog::DoDataExchange(pDX);
  1536. //{{AFX_DATA_MAP(CGotoLine)
  1537. DDX_Control(pDX, IDC_GotoBox, m_ceGotoBox);
  1538. DDX_Text(pDX, IDC_GotoBox, m_csLineNum);
  1539. //}}AFX_DATA_MAP
  1540. }
  1541. BEGIN_MESSAGE_MAP(CGotoLine, CDialog)
  1542. //{{AFX_MSG_MAP(CGotoLine)
  1543. //}}AFX_MSG_MAP
  1544. END_MESSAGE_MAP()
  1545. /////////////////////////////////////////////////////////////////////////////
  1546. // CGotoLine message handlers
  1547. void CGotoLine::OnOK()
  1548. {
  1549. // Get the line number string. Complain and exit if there is no line number.
  1550. CString cserror ;
  1551. UpdateData(TRUE) ;
  1552. if (m_csLineNum == _T("")) {
  1553. cserror.Format(IDS_BadGotoLineNum, m_csLineNum) ;
  1554. AfxMessageBox(cserror) ;
  1555. m_ceGotoBox.SetFocus() ;
  1556. return ;
  1557. } ;
  1558. // Convert the line number string to a number. Complain if the number is
  1559. // invalid or too large.
  1560. m_nLineNum = atoi(m_csLineNum) ;
  1561. if (m_nLineNum < 1 || m_nLineNum > m_nMaxLine) {
  1562. cserror.Format(IDS_BadGotoLineNum, m_csLineNum) ;
  1563. AfxMessageBox(cserror) ;
  1564. m_ceGotoBox.SetFocus() ;
  1565. return ;
  1566. } ;
  1567. // The line number seems ok so...
  1568. CDialog::OnOK();
  1569. }
  1570. /////////////////////////////////////////////////////////////////////////////
  1571. // CErrorLevel dialog
  1572. CErrorLevel::CErrorLevel(CWnd* pParent /*=NULL*/)
  1573. : CDialog(CErrorLevel::IDD, pParent)
  1574. {
  1575. //{{AFX_DATA_INIT(CErrorLevel)
  1576. m_nErrorLevel = -1;
  1577. //}}AFX_DATA_INIT
  1578. }
  1579. void CErrorLevel::DoDataExchange(CDataExchange* pDX)
  1580. {
  1581. CDialog::DoDataExchange(pDX);
  1582. //{{AFX_DATA_MAP(CErrorLevel)
  1583. DDX_Control(pDX, IDC_ErrorLevelLst, m_ccbErrorLevel);
  1584. DDX_CBIndex(pDX, IDC_ErrorLevelLst, m_nErrorLevel);
  1585. //}}AFX_DATA_MAP
  1586. }
  1587. BEGIN_MESSAGE_MAP(CErrorLevel, CDialog)
  1588. //{{AFX_MSG_MAP(CErrorLevel)
  1589. //}}AFX_MSG_MAP
  1590. END_MESSAGE_MAP()
  1591. /////////////////////////////////////////////////////////////////////////////
  1592. // CErrorLevel message handlers
  1593. BOOL CErrorLevel::OnInitDialog()
  1594. {
  1595. CDialog::OnInitDialog() ;
  1596. // Blow if the current error level was not set
  1597. ASSERT(m_nErrorLevel != -1) ;
  1598. // Set the current error level in the error level list box.
  1599. UpdateData(FALSE) ;
  1600. return TRUE ; // return TRUE unless you set the focus to a control
  1601. // EXCEPTION: OCX Property Pages should return FALSE
  1602. }
  1603. void CErrorLevel::OnOK()
  1604. {
  1605. // Get the error level selected by the user
  1606. UpdateData() ;
  1607. CDialog::OnOK() ;
  1608. }
  1609.