]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/common/win32/mltview.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / common / win32 / mltview.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it 
9 // under the terms of the GNU General Public License as published by the Free 
10 // Software Foundation; either version 2 of the License, or (at your option) 
11 // any later version.
12 // 
13 // This program is distributed in the hope that it will be useful, but WITHOUT 
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16 // more details.
17 // 
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc., 
20 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //                                                                          
24 //####COPYRIGHTEND####
25 // MLTView.cpp: implementation of the CMLTView class.
26 //
27 //////////////////////////////////////////////////////////////////////
28
29 #include "stdafx.h"
30 #ifndef PLUGIN
31 #include "BCMenu.h"
32 #endif
33 #include "ConfigtoolDoc.h"
34 #include "MLTView.h"
35 #include "ConfigTool.h"
36 #include "CTUtils.h"
37 #include "resource.h"
38
39 #ifdef _DEBUG
40 #define new DEBUG_NEW
41 #undef THIS_FILE
42 static char THIS_FILE[] = __FILE__;
43 #endif
44
45 using namespace std;
46
47 //////////////////////////////////////////////////////////////////////
48 // Construction/Destruction
49 //////////////////////////////////////////////////////////////////////
50
51 IMPLEMENT_DYNCREATE(CMLTView, CScrollView)
52
53 BEGIN_MESSAGE_MAP(CMLTView, CScrollView)
54   //{{AFX_MSG_MAP(CMLTView)
55     ON_WM_LBUTTONDOWN()
56     ON_WM_LBUTTONDBLCLK()
57     ON_WM_SIZE()
58     ON_WM_ERASEBKGND()
59     ON_WM_MOUSEMOVE()
60     ON_COMMAND(ID_EDIT_NEW_REGION, OnMLTNewRegion)
61     ON_COMMAND(ID_EDIT_NEW_SECTION, OnMLTNewSection)
62     ON_COMMAND(ID_EDIT_DELETE_SECTION, OnMLTDelete)
63     ON_COMMAND(ID_EDIT_PROPERTIES, OnMLTProperties)
64     ON_UPDATE_COMMAND_UI(ID_EDIT_NEW_SECTION, OnUpdateMLTNewSection)
65     ON_UPDATE_COMMAND_UI(ID_EDIT_DELETE_SECTION, OnUpdateMLTDelete)
66     ON_UPDATE_COMMAND_UI(ID_EDIT_PROPERTIES, OnUpdateMLTProperties)
67     ON_WM_CONTEXTMENU()
68     ON_COMMAND(ID_POPUP_PROPERTIES, OnPopupProperties)
69     ON_WM_RBUTTONDOWN()
70         ON_WM_KEYDOWN()
71         ON_WM_HELPINFO()
72         ON_WM_MENUCHAR()
73         //}}AFX_MSG_MAP
74   ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
75         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
76   // Standard printing commands
77   ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
78   ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
79   ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
80 END_MESSAGE_MAP()
81
82 CMLTView::CMLTView()
83 {
84   m_uViewWidth = 0;
85   m_uUnitCountMax = 0;
86   CConfigTool::SetMLTView(this);
87 }
88
89 CMLTView::~CMLTView()
90 {
91   CConfigTool::SetMLTView(0);
92   for(POSITION pos = m_arstrTooltipRects.GetStartPosition(); pos != NULL; ){
93     CRect *pRect;
94     CString strName;
95     m_arstrTooltipRects.GetNextAssoc( pos, strName, (void *&)pRect );
96     delete pRect;
97   }
98 }
99
100 /////////////////////////////////////////////////////////////////////////////
101 // CMLTView drawing
102
103 #define VERT_BORDER 30 /* the vertical border at the top/bottom of the client area */
104 #define HORIZ_BORDER 30 /* the horizontal border at the left/right of the client area */
105 #define BAR_HEIGHT 18 /* the height of the memory section caption bar */
106 #define MAP_HEIGHT 66 /* the height of each memory section rectangle (including caption bar) */
107 #define REGION_SPACING 115 /* the vertical offset between successive memory regions */
108 #define ADDRESS_TEXT_SPACE 0.9 /* use 90% of the section width to draw the address */
109 #define EXTERNAL_TEXT_BORDER 5 /* spacing between external text and border of region */
110 #define ADDRESS_FORMAT _T("%08X") /* draw memory addresses in hex format */
111 #define UNITS_PER_SECTION 3 /* memory section width in units, unused sections are 1 unit wide */
112 #define UNIT_WIDTH_MIN 27 /* minimum width of memory section unit before horizontal scrolling enabled */
113 #define TICK_HEIGHT 4 /* the height of the tick marks on the memory sections and regions */
114
115 #define DISPLAY_MODE 1 /* 1 == const unit width for all regions */
116 /* 2 == const region width for all regions */
117
118 void CMLTView::OnDraw(CDC* pDC)
119 {
120   CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
121   if (pDoc == NULL) // no document so nothing to draw
122     return;
123   
124   // clear the lists of region and section rectangles used for hit testing
125   
126   listRegionRect.RemoveAll ();
127   listSectionRect.RemoveAll ();
128   
129   // setup background mode
130   
131   int nOldBkMode = pDC->SetBkMode (TRANSPARENT);
132   
133   // setup font
134   
135   CFont fntName;
136   if (!fntName.CreatePointFont (80, _T("MS Sans Serif"), pDC))
137     return;
138   CFont * pOldFont = pDC->SelectObject (&fntName);
139   
140   // determine max unit count for any region
141   
142   mem_map * pMemoryMap = &CConfigTool::GetConfigToolDoc()->MemoryMap;
143   
144   // calculate the unit scaling for DISPLAY_MODE 1
145   
146   UINT uPixelsPerUnit = UNIT_WIDTH_MIN;
147   RECT rectClientRect;
148   if (m_uUnitCountMax != 0) // if there is something to draw
149   {
150     
151     GetClientRect (&rectClientRect);
152     uPixelsPerUnit = __max ((m_uClientWidth - HORIZ_BORDER * 2) / m_uUnitCountMax, UNIT_WIDTH_MIN);
153     m_uViewWidth = uPixelsPerUnit * m_uUnitCountMax + HORIZ_BORDER * 2;
154   }
155   
156   // draw the regions
157   
158   UINT uRegion = 0;
159   UINT uUnitCount;
160   list <mem_region>::iterator region;
161   for (region = pMemoryMap->region_list.begin (); region != pMemoryMap->region_list.end (); ++region)
162   {
163     uUnitCount = 0;
164     for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
165       uUnitCount += (section_view->section == NULL ? 1 : UNITS_PER_SECTION);
166     
167     if (DISPLAY_MODE == 1)
168       DrawRegion (pDC, uRegion++, uUnitCount, uPixelsPerUnit, region);
169     else // DISPLAY_MODE == 2
170       DrawRegion (pDC, uRegion++, uUnitCount, (rectClientRect.right - HORIZ_BORDER * 2) / uUnitCount, region);
171   }    
172   
173   pDC->SelectObject (pOldFont);
174   pDC->SetBkMode (nOldBkMode);
175 }
176
177
178 void CMLTView::DrawRegion (CDC* pDC, UINT uRegion, UINT uUnitCount, UINT uPixelsPerUnit, list <mem_region>::iterator region)
179 {
180   BOOL bDrawFocusRect = FALSE;
181   CRect rectAddress;
182   CString strAddress;
183   
184   // setup the drawing objects
185   
186   CBrush brshUnusedSection;
187   if (!brshUnusedSection.CreateHatchBrush (HS_BDIAGONAL, RGB (128, 128, 128)))
188     return;
189   
190   CBrush brshUsedSection;
191   if (!brshUsedSection.CreateSolidBrush (GetSysColor (COLOR_WINDOW)))
192     return;
193   
194   CBrush brshInitialSectionBar;
195   if (!brshInitialSectionBar.CreateSolidBrush (GetSysColor (COLOR_INACTIVECAPTION)))
196     return;
197   
198   CBrush brshFixedSectionBar;
199   if (!brshFixedSectionBar.CreateSolidBrush (GetSysColor (COLOR_ACTIVECAPTION)))
200     return;
201   
202   CBrush brshFinalSectionBar;
203   if (!brshFinalSectionBar.CreateSolidBrush (GetSysColor (COLOR_ACTIVECAPTION)))
204     return;
205   
206   CPen penBorder;
207   if (!penBorder.CreatePen (PS_SOLID, 1, GetSysColor (COLOR_WINDOWTEXT)))
208     return;
209   
210   CPen penSelected;
211   if (!penSelected.CreatePen (PS_SOLID, 2, GetSysColor (COLOR_WINDOWTEXT)))
212     return;
213   
214   // select the border pen object
215   
216   CPen * pOldPen = pDC->SelectObject (&penBorder);
217   
218   // calculate the region rectangle
219   
220   REGIONRECT srRegion;
221   srRegion.Rect.SetRect (HORIZ_BORDER, VERT_BORDER + REGION_SPACING * uRegion, HORIZ_BORDER + uUnitCount * uPixelsPerUnit + 1, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + 1);
222   srRegion.Region = region;
223   listRegionRect.AddTail (srRegion);
224   
225   // draw the region
226   
227   CPoint pointOrigin (srRegion.Rect.left, srRegion.Rect.top);
228   pDC->LPtoDP (&pointOrigin);
229   pointOrigin.x %= 8;
230   pointOrigin.y %= 8;
231   pDC->SetBrushOrg (pointOrigin);
232   CBrush * pOldBrush = pDC->SelectObject (&brshUnusedSection);
233   pDC->Rectangle (srRegion.Rect);
234   /*
235   pDC->MoveTo (srRegion.Rect.left, srRegion.Rect.bottom - 1); // draw tick
236   pDC->LineTo (srRegion.Rect.left, srRegion.Rect.bottom + TICK_HEIGHT); // draw tick
237   */
238   if (region == m_riSelectedRegion)
239   {
240     bDrawFocusRect = TRUE;
241     m_rectSelectedItem = srRegion.Rect;
242   }
243   
244   // draw the region label
245   
246   CRect rectRegionLabel (HORIZ_BORDER, VERT_BORDER + REGION_SPACING * uRegion - EXTERNAL_TEXT_BORDER - 20, m_uViewWidth - HORIZ_BORDER /*HORIZ_BORDER + uUnitCount * uPixelsPerUnit + 1*/, VERT_BORDER + REGION_SPACING * uRegion - EXTERNAL_TEXT_BORDER);
247   CString strRegionLabel;
248   strRegionLabel.Format (_T("%s (%08X-%08X)%s"), CString(region->name.c_str ()), region->address, region->address + region->size - 1, ((region->type == read_only) ? _T(" read only") : _T("")));
249   pDC->DrawText (strRegionLabel, -1, rectRegionLabel, DT_BOTTOM | DT_SINGLELINE);
250   
251   // draw the start address of the region
252   /*
253   rectAddress.SetRect (HORIZ_BORDER, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, HORIZ_BORDER + ADDRESS_TEXT_SPACE * UNITS_PER_SECTION * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
254   strAddress.Format (ADDRESS_FORMAT, region->address);
255   pDC->DrawText (strAddress, -1, rectAddress, DT_LEFT | DT_SINGLELINE);
256   */
257   // draw the end address of the region
258   /*
259   rectAddress.SetRect (HORIZ_BORDER + (uUnitCount - ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, HORIZ_BORDER + (uUnitCount + ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
260   strAddress.Format (ADDRESS_FORMAT, region->address + region->size);
261   pDC->DrawText (strAddress, -1, rectAddress, DT_CENTER | DT_SINGLELINE);
262   */
263   // draw the sections within the region
264   
265   UINT uSectionUnitCount = 0;
266   CRect rectBar;
267   SECTIONRECT srSection;
268   for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
269   {
270     if (section_view->section != NULL) // the section is used
271     {
272       // draw the section
273       
274       pDC->SelectObject (brshUsedSection);
275       srSection.Rect.SetRect (HORIZ_BORDER + uSectionUnitCount * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion, HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION) * uPixelsPerUnit + 1, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + 1);
276       srSection.SectionView = section_view;
277       listSectionRect.AddTail (srSection);
278       pDC->Rectangle (srSection.Rect);
279       if (section_view == m_sviSelectedSectionView)
280       {
281         bDrawFocusRect = TRUE;
282         m_rectSelectedItem = srSection.Rect;
283       }
284       
285       // draw text within the section
286       
287       CString strSection, strSectionLine;
288       
289       if ((section_view->section_location != initial_location) && (section_view->section->alignment > 1))
290       {
291         strSectionLine.Format (_T("align %lX\n"), section_view->section->alignment);
292         strSection += strSectionLine;
293       }
294       
295       if (section_view->section->size > 0)
296       {
297         strSectionLine.Format (_T("size %lX\n"), section_view->section->size);
298         strSection += strSectionLine;
299       }
300       
301       if (section_view->section_location == final_location)
302       {
303         strSectionLine.Format (_T("relocated\n"));
304         strSection += strSectionLine;
305       }
306       
307       pDC->DrawText (strSection, -1, srSection.Rect - (LPCRECT) CRect (EXTERNAL_TEXT_BORDER, EXTERNAL_TEXT_BORDER + BAR_HEIGHT, EXTERNAL_TEXT_BORDER, EXTERNAL_TEXT_BORDER), DT_LEFT);
308       
309       // select caption bar colour according to type of section
310       
311       if (section_view->section_location == initial_location)
312       {
313         pDC->SetTextColor (GetSysColor (COLOR_INACTIVECAPTIONTEXT));
314         pDC->SelectObject (&brshInitialSectionBar);
315       }
316       else
317       {
318         pDC->SetTextColor (GetSysColor (COLOR_CAPTIONTEXT));
319         pDC->SelectObject (&brshFinalSectionBar);
320       }
321       
322       // draw the caption bar
323       
324       rectBar.SetRect (HORIZ_BORDER + uSectionUnitCount * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion, HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION) * uPixelsPerUnit + 1, VERT_BORDER + REGION_SPACING * uRegion + BAR_HEIGHT + 1);
325       pDC->Rectangle (rectBar);
326       
327       // draw the section name within the caption bar
328       
329       CString strName(section_view->section->name.c_str ());
330       CRect *pRect=NULL;
331       m_arstrTooltipRects.Lookup(strName,(void *&)pRect);
332       UINT format;
333       if(pDC->GetTextExtent(strName).cx>rectBar.Width()-2*EXTERNAL_TEXT_BORDER){
334         format=DT_LEFT;
335         if(pRect){
336           pRect->CopyRect(rectBar);
337         } else {
338           pRect=new CRect;
339           m_arstrTooltipRects.SetAt(strName,pRect);
340         }
341         // Replace final three characters of name with an elipsis
342         int nLength=1+max(1,strName.GetLength()-3);
343         do {
344           --nLength;
345           strName=strName.Left(nLength)+_T("...");
346         } while(nLength>1 && pDC->GetTextExtent(strName).cx>rectBar.Width()-2*EXTERNAL_TEXT_BORDER);
347        
348         rectBar.left+=EXTERNAL_TEXT_BORDER;
349         rectBar.right-=EXTERNAL_TEXT_BORDER;
350       } else {
351         format=DT_CENTER;
352         if (pRect) {
353           m_arstrTooltipRects.RemoveKey(strName);
354         }
355       }
356
357       pDC->DrawText (strName, -1, rectBar, format | DT_VCENTER | DT_SINGLELINE);
358       pDC->SetTextColor (GetSysColor (COLOR_WINDOWTEXT));
359       
360       // find the mem_section item describing the current section_view item
361       
362       list <mem_section>::iterator MemorySection = section_view->section;
363       
364       // draw the section address if appropriate
365       
366       if ((section_view->section_location == initial_location))
367       {
368         if (MemorySection->initial_location->anchor == absolute)
369         {
370           pDC->MoveTo (srSection.Rect.left, srSection.Rect.bottom - 1); // draw tick
371           pDC->LineTo (srSection.Rect.left, srSection.Rect.bottom + TICK_HEIGHT); // draw tick
372           rectAddress.SetRect (HORIZ_BORDER + uSectionUnitCount * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, (int) (HORIZ_BORDER + (uSectionUnitCount + ADDRESS_TEXT_SPACE * UNITS_PER_SECTION) * uPixelsPerUnit), VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
373           strAddress.Format (ADDRESS_FORMAT, MemorySection->initial_location->address);
374           pDC->DrawText (strAddress, -1, rectAddress, DT_LEFT | DT_SINGLELINE);
375           
376           /*
377           if (MemorySection->size > 0) // the end address can be calculated
378           {
379           rectAddress.SetRect (HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION - ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION + ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
380           strAddress.Format (ADDRESS_FORMAT, MemorySection->initial_location->address + MemorySection->size);
381           pDC->DrawText (strAddress, -1, rectAddress, DT_CENTER | DT_SINGLELINE);
382           }
383           */
384         }
385       }
386       
387       else if ((section_view->section_location == final_location) || (section_view->section_location == fixed_location))
388       {
389         if (MemorySection->final_location->anchor == absolute)
390         {
391           pDC->MoveTo (srSection.Rect.left, srSection.Rect.bottom - 1); // draw tick
392           pDC->LineTo (srSection.Rect.left, srSection.Rect.bottom + TICK_HEIGHT); // draw tick
393           rectAddress.SetRect (HORIZ_BORDER + uSectionUnitCount * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, (int) (HORIZ_BORDER + (uSectionUnitCount + ADDRESS_TEXT_SPACE * UNITS_PER_SECTION) * uPixelsPerUnit), VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
394           strAddress.Format (ADDRESS_FORMAT, MemorySection->final_location->address);
395           pDC->DrawText (strAddress, -1, rectAddress, DT_LEFT | DT_SINGLELINE);
396           
397           /*
398           if (MemorySection->size > 0) // the end address can be calculated
399           {
400           rectAddress.SetRect (HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION - ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION + ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
401           strAddress.Format (ADDRESS_FORMAT, MemorySection->final_location->address + MemorySection->size);
402           pDC->DrawText (strAddress, -1, rectAddress, DT_CENTER | DT_SINGLELINE);
403           }
404           */
405         }
406       }
407       
408       uSectionUnitCount += UNITS_PER_SECTION;
409     }
410     else
411     {
412       uSectionUnitCount++; // unused sections occupy a single unit
413     }
414   }
415   
416   // draw the focus rectangle around the selected object (if any)
417   
418   if (bDrawFocusRect)
419     pDC->DrawFocusRect (m_rectSelectedItem + CRect (1, 1, 1, 1));
420   
421   // restore previous drawing objects
422   
423   pDC->SelectObject (pOldBrush);
424   pDC->SelectObject (pOldPen);
425 }
426
427
428 SECTIONRECT * CMLTView::SectionHitTest (CPoint pntTest)
429 {
430   for (POSITION posSection = listSectionRect.GetHeadPosition (); posSection != NULL; listSectionRect.GetNext (posSection))
431   {
432     if (listSectionRect.GetAt (posSection).Rect.PtInRect (pntTest))
433       return & listSectionRect.GetAt (posSection);
434   }
435   
436   return NULL;
437 }
438
439
440 REGIONRECT * CMLTView::RegionHitTest (CPoint pntTest)
441 {
442   for (POSITION posRegion = listRegionRect.GetHeadPosition (); posRegion != NULL; listRegionRect.GetNext (posRegion))
443   {
444     CRect rectRegion = listRegionRect.GetAt (posRegion).Rect +
445       CRect (EXTERNAL_TEXT_BORDER + 20, EXTERNAL_TEXT_BORDER + 20, EXTERNAL_TEXT_BORDER + 20, EXTERNAL_TEXT_BORDER + 20); // extended rectangle to allow clicking on region label
446     if (rectRegion.PtInRect (pntTest))
447       return & listRegionRect.GetAt (posRegion);
448   }
449   
450   return NULL;
451 }
452
453
454 /////////////////////////////////////////////////////////////////////////////
455 // CMLTView printing
456
457 BOOL CMLTView::OnPreparePrinting(CPrintInfo* pInfo)
458 {
459   // default preparation
460   return DoPreparePrinting(pInfo);
461 }
462
463 void CMLTView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
464 {
465   // TODO: add extra initialization before printing
466 }
467
468 void CMLTView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
469 {
470   // TODO: add cleanup after printing
471 }
472
473 /////////////////////////////////////////////////////////////////////////////
474 // CMLTView diagnostics
475
476 #ifdef _DEBUG
477 void CMLTView::AssertValid() const
478 {
479   CView::AssertValid();
480 }
481
482 void CMLTView::Dump(CDumpContext& dc) const
483 {
484   CView::Dump(dc);
485 }
486
487 #endif //_DEBUG
488
489 /////////////////////////////////////////////////////////////////////////////
490 // CMLTView message handlers
491
492
493 void CMLTView::OnLButtonDown(UINT nFlags, CPoint point) 
494 {
495   if (CConfigTool::GetConfigToolDoc() == NULL) // nothing to do
496     return;
497   
498   list <mem_section_view>::iterator sviOldSelectedSectionView = m_sviSelectedSectionView;
499   list <mem_region>::iterator riOldSelectedRegion = m_riSelectedRegion;
500   CRect rectOldSelectedItem = m_rectSelectedItem;
501   
502   CConfigTool::GetConfigToolDoc()->strSelectedRegion = _T("");
503   CConfigTool::GetConfigToolDoc()->strSelectedSection = _T("");
504   
505   SECTIONRECT * psrSection = SectionHitTest (point + GetScrollPosition ());
506   if (psrSection != NULL) // a section was clicked
507   {
508     m_sviSelectedSectionView = psrSection->SectionView;
509     m_rectSelectedItem = psrSection->Rect;
510     m_riSelectedRegion = NULL;
511     CConfigTool::GetConfigToolDoc()->strSelectedSection = m_sviSelectedSectionView->section->name.c_str ();
512   }
513   
514   else // no section was clicked, test for regions
515   {
516     REGIONRECT * prrRegion = RegionHitTest (point + GetScrollPosition ());
517     if (prrRegion != NULL) // a region was clicked, but not a section
518     {
519       m_riSelectedRegion = prrRegion->Region;
520       m_rectSelectedItem = prrRegion->Rect;
521       m_sviSelectedSectionView = NULL;
522       CConfigTool::GetConfigToolDoc()->strSelectedRegion = m_riSelectedRegion->name.c_str ();
523     }
524   }
525   
526   // redraw the focus rectangle if the selection has changed
527   
528   if ((m_sviSelectedSectionView != sviOldSelectedSectionView) || (m_riSelectedRegion != riOldSelectedRegion))
529   {
530     //          CDC * pDC = GetDC ();
531     if ((sviOldSelectedSectionView != NULL) || (riOldSelectedRegion != NULL))
532       //                        pDC->DrawFocusRect (rectOldSelectedItem + CRect (1, 1, 1, 1) - GetScrollPosition ());
533       InvalidateRect (rectOldSelectedItem + CRect (1, 1, 1, 1) - GetScrollPosition ()); // paint over the old focus rectangle
534     if ((m_sviSelectedSectionView != NULL) || (m_riSelectedRegion != NULL))
535       //                        pDC->DrawFocusRect (m_rectSelectedItem + CRect (1, 1, 1, 1) - GetScrollPosition ());
536       InvalidateRect (m_rectSelectedItem + CRect (1, 1, 1, 1) - GetScrollPosition ()); // paint the new focus rectangle
537   }
538   
539   // perform default processing
540   
541   CView::OnLButtonDown(nFlags, point);
542 }
543
544 void CMLTView::OnLButtonDblClk(UINT nFlags, CPoint point) 
545 {
546   if (CConfigTool::GetConfigToolDoc() != NULL)
547     CConfigTool::GetConfigToolDoc()->OnMLTProperties ();
548   
549   CView::OnLButtonDblClk(nFlags, point);
550 }
551
552 void CMLTView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
553 {       
554   if ((lHint != 0) && (pHint != NULL) && (lHint != CConfigToolDoc::MemLayoutChanged))
555     return; // no need to invalidate the view
556   m_arstrTooltipRects.RemoveAll();
557
558   CalcUnitCountMax (); // recalculate the total view width since the section count may have changed
559   if (m_uUnitCountMax == 0 || (m_uClientWidth < HORIZ_BORDER * 2)) // there is nothing to draw
560     m_uViewWidth = 0;
561   else // allow horizontal scrolling when the unit width reduces to UNIT_WIDTH_MIN
562     m_uViewWidth = __max ((m_uClientWidth - HORIZ_BORDER * 2) / m_uUnitCountMax, UNIT_WIDTH_MIN) * m_uUnitCountMax + HORIZ_BORDER * 2;
563   
564   SIZE sizeTotal;
565   sizeTotal.cx = __max (m_uViewWidth, m_uClientWidth);
566   sizeTotal.cy = CConfigTool::GetConfigToolDoc()->MemoryMap.region_list.size () * REGION_SPACING + EXTERNAL_TEXT_BORDER * 2;
567   SetScrollSizes (MM_TEXT, sizeTotal);
568   
569   CScrollView::OnUpdate (pSender, lHint, pHint);
570 }
571
572 void CMLTView::OnSize(UINT nType, int cx, int cy) 
573 {
574   CScrollView::OnSize(nType, cx, cy);
575   
576   m_uClientWidth = cx;
577   if (m_uUnitCountMax == 0) // there is nothing to draw
578     m_uViewWidth = 0;
579   else // allow horizontal scrolling when the unit width reduces to UNIT_WIDTH_MIN
580     m_uViewWidth = __max ((cx - HORIZ_BORDER * 2) / m_uUnitCountMax, UNIT_WIDTH_MIN) * m_uUnitCountMax + HORIZ_BORDER * 2;
581   
582   SIZE sizeTotal;
583   sizeTotal.cx = __max (m_uViewWidth, m_uClientWidth);
584   if (CConfigTool::GetConfigToolDoc() == NULL)
585     sizeTotal.cy = 0;
586   else
587     sizeTotal.cy = CConfigTool::GetConfigToolDoc()->MemoryMap.region_list.size () * REGION_SPACING + EXTERNAL_TEXT_BORDER * 2;
588   SetScrollSizes (MM_TEXT, sizeTotal);
589 }
590
591 void CMLTView::CalcUnitCountMax ()
592 {
593   UINT uUnitCountMax = 0;
594   UINT uUnitCount;
595   list <mem_region>::iterator region;
596   mem_map * pMemoryMap = & (CConfigTool::GetConfigToolDoc()->MemoryMap);
597   for (region = pMemoryMap->region_list.begin (); region != pMemoryMap->region_list.end (); ++region)
598   {
599     uUnitCount = 0;
600     for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
601       uUnitCount += (section_view->section == NULL ? 1 : UNITS_PER_SECTION);
602     
603     if (uUnitCount > uUnitCountMax)
604       uUnitCountMax = uUnitCount;
605   }
606   m_uUnitCountMax = uUnitCountMax;
607 }
608
609 BOOL CMLTView::OnEraseBkgnd(CDC* pDC) 
610 {
611   // Work around bug apparently caused by SlickEdit
612   CRect rcClient;
613   pDC->GetClipBox(rcClient);
614   pDC->FillSolidRect(rcClient,GetSysColor(COLOR_WINDOW));
615                 
616   return TRUE;//return CScrollView::OnEraseBkgnd(pDC);
617 }
618
619 BOOL CMLTView::OnToolTipText(UINT id, NMHDR* pNMHDR, LRESULT*pResult)
620 {
621         // need to handle both ANSI and UNICODE versions of the message
622         TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
623         TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
624         id=pNMHDR->idFrom;
625
626   if(id){
627     for(POSITION pos = m_arstrTooltipRects.GetStartPosition(); pos != NULL; ){
628       CRect *pRect;
629       CString strTipText;
630       m_arstrTooltipRects.GetNextAssoc( pos, strTipText, (void *&)pRect );
631       if((UINT)pRect==id){
632     #ifndef _UNICODE
633               if (pNMHDR->code == TTN_NEEDTEXTA)
634                       lstrcpyn(pTTTA->szText, strTipText, sizeof pTTTA->szText/sizeof TCHAR - 1);
635               else
636                       _mbstowcsz(pTTTW->szText, strTipText, sizeof pTTTW->szText/sizeof TCHAR - 1);
637     #else
638               if (pNMHDR->code == TTN_NEEDTEXTA)
639                       _wcstombsz(pTTTA->szText, strTipText, sizeof pTTTA->szText/sizeof TCHAR - 1);
640               else
641                       lstrcpyn(pTTTW->szText, strTipText, sizeof pTTTW->szText/sizeof TCHAR - 1);
642     #endif
643         *pResult = 0;
644         return TRUE;    // message was handled
645       }
646     }
647   }
648   return FALSE;
649 }
650
651 int CMLTView::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const
652 {
653   for(POSITION pos = m_arstrTooltipRects.GetStartPosition(); pos != NULL; ){
654     CRect *pRect;
655     CString strName;
656     m_arstrTooltipRects.GetNextAssoc( pos, strName, (void *&)pRect );
657     
658     if(pRect->PtInRect(point)){
659       pTI->hwnd = m_hWnd;
660       pTI->uId = (UINT)pRect; 
661       pTI->uFlags = 0 ;
662       GetClientRect(&pTI->rect);
663       pTI->lpszText=LPSTR_TEXTCALLBACK;
664             return pTI->uId;
665     }
666   }
667   return -1;
668 }
669
670 void CMLTView::OnInitialUpdate() 
671 {
672         CScrollView::OnInitialUpdate();
673         EnableToolTips(true);
674 }
675
676 void CMLTView::OnMouseMove(UINT nFlags, CPoint point) 
677 {
678 /*
679   CString strToolTipText;
680   for(POSITION pos = m_arstrTooltipRects.GetStartPosition(); pos != NULL; ){
681     CRect *pRect;
682     CString strName;
683     m_arstrTooltipRects.GetNextAssoc( pos, strName, (void *&)pRect );
684     
685     if(pRect->PtInRect(point)){
686       strToolTipText=strName;
687       break;
688     }
689   }
690   if(strToolTipText!=m_strTipText){
691           _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
692           CToolTipCtrl* pToolTip = pThreadState->m_pToolTip;
693     if(!m_strTipText.IsEmpty()){
694       pToolTip->Activate(false);
695     }
696     pToolTip->Activate(!strToolTipText.IsEmpty());
697     m_strTipText=strToolTipText;
698   }
699 */
700         CScrollView::OnMouseMove(nFlags, point);
701 }
702
703 void CMLTView::OnMLTNewRegion ()
704 {
705   CConfigTool::GetConfigToolDoc ()->OnMLTNewRegion ();
706 }
707
708 void CMLTView::OnMLTNewSection ()
709 {
710   CConfigTool::GetConfigToolDoc ()->OnMLTNewSection ();
711 }
712
713 void CMLTView::OnMLTDelete ()
714 {
715   CConfigTool::GetConfigToolDoc ()->OnMLTDelete ();
716 }
717
718 void CMLTView::OnMLTProperties ()
719 {
720   CConfigTool::GetConfigToolDoc ()->OnMLTProperties ();
721 }
722
723 void CMLTView::OnUpdateMLTNewRegion (CCmdUI* pCmdUI)
724 {
725   pCmdUI->Enable (true);
726 }
727
728 void CMLTView::OnUpdateMLTNewSection (CCmdUI* pCmdUI)
729 {
730   pCmdUI->Enable (CConfigTool::GetConfigToolDoc()->MemoryMap.region_list.size() > 0);
731 }
732
733 void CMLTView::OnUpdateMLTDelete (CCmdUI* pCmdUI)
734 {
735   pCmdUI->Enable(
736     (!CConfigTool::GetConfigToolDoc ()->strSelectedRegion.IsEmpty() || !CConfigTool::GetConfigToolDoc ()->strSelectedSection.IsEmpty()));
737 }
738
739 void CMLTView::OnUpdateMLTProperties (CCmdUI* pCmdUI)
740 {
741   pCmdUI->Enable(
742     (!CConfigTool::GetConfigToolDoc ()->strSelectedRegion.IsEmpty() || !CConfigTool::GetConfigToolDoc ()->strSelectedSection.IsEmpty()));
743 }
744
745
746 void CMLTView::OnContextMenu(CWnd*, CPoint point) 
747 {
748   CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
749   if (!pDoc->strSelectedRegion.IsEmpty() || !pDoc->strSelectedSection.IsEmpty()){
750     if(point.x<0){
751       // Keyboard
752       point=!pDoc->strSelectedRegion.IsEmpty()?m_rectSelectedItem.TopLeft():m_rectSelectedItem.CenterPoint();
753       ClientToScreen(&point);
754     }
755     Menu menu;
756     menu.LoadMenu(IDR_MLTVIEW_POPUP);
757
758     #ifndef PLUGIN
759     menu.LoadToolbar(IDR_MISCBAR);
760     #endif
761
762     Menu *pPopup=(Menu *)menu.GetSubMenu(0);
763     pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, point.x,point.y,this);  
764   }
765 }   
766
767 void CMLTView::OnPopupProperties() 
768 {
769   CConfigTool::GetConfigToolDoc()->OnMLTProperties ();
770 }
771
772 void CMLTView::OnRButtonDown(UINT nFlags, CPoint point) 
773 {
774   OnLButtonDown(nFlags, point);
775   ClientToScreen(&point);
776   OnContextMenu(this, point) ;
777 }
778
779 void CMLTView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
780 {
781   POSITION pos;
782   switch(nChar){
783     case VK_RIGHT:
784       pos = listSectionRect.GetHeadPosition ();
785       if(!CConfigTool::GetConfigToolDoc()->strSelectedSection.IsEmpty()){
786         while(NULL!=pos){
787           if (listSectionRect.GetNext (pos).SectionView==m_sviSelectedSectionView){
788             if(NULL==pos){
789               pos=listSectionRect.GetHeadPosition();
790             }
791             break;
792           }
793         }
794       }
795       OnLButtonDown(0, listSectionRect.GetNext(pos).Rect.CenterPoint()-GetScrollPosition());
796       break;
797     case VK_LEFT:
798       pos = listSectionRect.GetTailPosition ();
799       if(!CConfigTool::GetConfigToolDoc()->strSelectedSection.IsEmpty()){
800         while(NULL!=pos){
801           if (listSectionRect.GetPrev (pos).SectionView==m_sviSelectedSectionView){
802             if(NULL==pos){
803               pos=listSectionRect.GetTailPosition();
804             }
805             break;
806           }
807         }
808       }
809       OnLButtonDown(0, listSectionRect.GetPrev(pos).Rect.CenterPoint()-GetScrollPosition());
810       break;
811     case VK_DOWN:
812       pos = listRegionRect.GetHeadPosition ();
813       if(!CConfigTool::GetConfigToolDoc()->strSelectedRegion.IsEmpty()){
814         while(NULL!=pos){
815           if (listRegionRect.GetNext (pos).Region==m_riSelectedRegion){
816             if(NULL==pos){
817               pos=listRegionRect.GetHeadPosition();
818             }
819             break;
820           }
821         }
822       }
823       OnLButtonDown(0, listRegionRect.GetNext(pos).Rect.TopLeft()-CPoint(1,1)-GetScrollPosition());
824       break;
825     case VK_UP:
826       pos = listRegionRect.GetTailPosition ();
827       if(!CConfigTool::GetConfigToolDoc()->strSelectedRegion.IsEmpty()){
828         while(NULL!=pos){
829           if (listRegionRect.GetPrev (pos).Region==m_riSelectedRegion){
830             if(NULL==pos){
831               pos=listRegionRect.GetTailPosition();
832             }
833             break;
834           }
835         }
836       }
837       OnLButtonDown(0, listRegionRect.GetPrev(pos).Rect.TopLeft()-CPoint(1,1)-GetScrollPosition());
838       break;
839     default:
840       break;
841   }
842         
843         CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
844 }
845
846
847 BOOL CMLTView::OnHelpInfo(HELPINFO*) 
848 {
849   return CConfigTool::GetConfigToolDoc()->ShowURL(CUtils::LoadString(IDS_MLT_VIEW_HELP));       
850 }
851
852 LRESULT CMLTView::OnMenuChar(UINT, UINT, CMenu*) 
853 {
854   const MSG *pMsg=GetCurrentMessage();
855   // punt to the mainframe to deal with shortcuts in popups
856   return AfxGetMainWnd()->SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);
857 }